From c091d83d95c06efef8d52bc3c18123289049cceb Mon Sep 17 00:00:00 2001 From: "vlean.wei" Date: Mon, 7 Sep 2026 10:34:12 +0800 Subject: [PATCH 01/23] feat(kiro-cli): add the Kiro CLI goal-mode host surface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Kiro CLI (binary `kiro-cli`) ships both halves of a goal-mode host, so LoopX binds its native loop instead of treating it as one more self-driving agent: - native `/goal [--max N]`, whose host-side loop re-dispatches turns until the built-in `goal` tool proves completion, with a host-enforced iteration budget (default 5, ceiling 50) and `/goal clear` to cancel; - global skills at `~/.kiro/skills//SKILL.md`, each exposed as a `/` slash command, which is what the installed facade uses. The activation states the capability envelope honestly. LoopX installs no Kiro hook, so quota pacing is advisory: `quota_gate_enforcement=advisory_only`, and the gate text says the loop runs only while the session is alive, has no cross-session daemon, and caps at 50 iterations. The real `preToolUse` hook seam (which can block a tool call with exit 2) is recorded as host facts only, not claimed as enforcement. Host facts, the agent-type catalog entry, and the activation extras live in `loopx/kiro_cli_goal_mode/` so `host_loop_activation.py` does not carry them. Bounded companion refactor: `host_loop_activation.py` sat exactly on its 1500-line module budget, so the five skill-facade CLI activations (gemini, cursor, zcode, agy, kiro-cli) and their shared `skill_facade_cli_activation` seam move into `loopx/host_loop_activation_skill_facade.py`. Behavior is unchanged — the packets are byte-identical — and the owning module drops to 1384 lines, leaving the next host addition cheap instead of budget-blocked. Signed-off-by: vlean.wei --- loopx/agent_onboarding.py | 13 ++ loopx/agy_goal_mode/__init__.py | 2 +- loopx/bootstrap_command_pack.py | 2 + loopx/cli_commands/slash_commands.py | 8 +- loopx/control_plane/goals/start_contract.py | 1 + loopx/host_loop_activation.py | 158 +++--------------- loopx/host_loop_activation_skill_facade.py | 170 ++++++++++++++++++++ loopx/kiro_cli_goal_mode/__init__.py | 159 ++++++++++++++++++ loopx/slash_command_install.py | 32 +++- loopx/slash_commands.py | 1 + 10 files changed, 404 insertions(+), 142 deletions(-) create mode 100644 loopx/host_loop_activation_skill_facade.py create mode 100644 loopx/kiro_cli_goal_mode/__init__.py diff --git a/loopx/agent_onboarding.py b/loopx/agent_onboarding.py index 618875d2d3..229877c378 100644 --- a/loopx/agent_onboarding.py +++ b/loopx/agent_onboarding.py @@ -52,6 +52,8 @@ def _surface_install_command(agent_type: str, cli_bin: str, project: str) -> str return f"{shell_arg(cli_bin)} slash-commands --install --surface zcode" if agent_type == "agy": return f"{shell_arg(cli_bin)} slash-commands --install --surface agy" + if agent_type == "kiro-cli": + return f"{shell_arg(cli_bin)} slash-commands --install --surface kiro-cli" if agent_type == "pi": # The slash-commands installer resolves the Pi extension target through # --pi-project; pass the resolved project so the command stays correct @@ -282,6 +284,7 @@ def _bootstrap_pack_command( "cursor-agent": "cursor-agent", "zcode": "zcode", "agy": "agy", + "kiro-cli": "kiro-cli", "deepseek-harness": "deepseek-harness", "deepseek-harness-native": "deepseek-harness-native", "ark-managed-agent": "ark-managed-agent", @@ -355,6 +358,16 @@ def _start_instruction(agent_type: str) -> str: "wake Prompt; recurring via MaxIterations) when quota allows more " "work." ) + if agent_type == "kiro-cli": + return ( + "Run `/loopx ` (the LoopX skill installed in `~/.kiro/skills`); " + "after todo writeback, bind the objective with the native " + "`/goal --max ` command, taking N from the remaining " + "quota slots and never above the host ceiling of 50 (`/goal clear` " + "cancels). Start every turn and native goal iteration with `quota " + "should-run`, and settle through the built-in `goal` tool only after " + "LoopX writeback so its completion contract cites the same evidence." + ) if agent_type == "deepseek-harness": return ( "Install `loopx[deepseek-harness]`, prepare a dsh cordis.yml, and run " diff --git a/loopx/agy_goal_mode/__init__.py b/loopx/agy_goal_mode/__init__.py index fdfcff2f76..0d7301f3cb 100644 --- a/loopx/agy_goal_mode/__init__.py +++ b/loopx/agy_goal_mode/__init__.py @@ -49,7 +49,7 @@ def agy_activation_extras() -> dict[str, Any]: - """Keyword overrides for ``_agy_cli_activation``'s facade call. + """Keyword overrides for ``agy_cli_activation``'s facade call. Keeps the agy host facts (goal command, tokens, wake tools, gate text, activation steps) in the agy package instead of growing diff --git a/loopx/bootstrap_command_pack.py b/loopx/bootstrap_command_pack.py index 10b8112bfe..507c1db62b 100644 --- a/loopx/bootstrap_command_pack.py +++ b/loopx/bootstrap_command_pack.py @@ -73,6 +73,7 @@ "cursor-agent", "zcode", "agy", + "kiro-cli", "deepseek-harness", "deepseek-harness-native", "ark-managed-agent", @@ -360,6 +361,7 @@ def build_start_goal_host_surface_selection_packet( "cursor-agent": "cursor-agent driving its own loop through the LoopX skill facade and MCP server", "zcode": "ZCode loop via the LoopX skill facade", "agy": "agy session loop via the LoopX skill facade; native /goal + schedule wakes while the session lives", + "kiro-cli": "Kiro CLI loop via the LoopX skill facade; native /goal iteration budget", "deepseek-harness": "DeepSeek Harness automation loop through loopx.dsh_goal_mode (compat: scripts/dsh_turn_host_adapter.py)", "deepseek-harness-native": "DeepSeek Harness same-session LoopX skill and plugin driver", "ark-managed-agent": "Ark Managed Agent with one-shot Goal submission", diff --git a/loopx/cli_commands/slash_commands.py b/loopx/cli_commands/slash_commands.py index 909c231219..5a9604a9e9 100644 --- a/loopx/cli_commands/slash_commands.py +++ b/loopx/cli_commands/slash_commands.py @@ -68,13 +68,15 @@ def register_slash_commands_command( "z-code", "agy", "antigravity", + "kiro", + "kiro-cli", "pi", ], help=( "Host surface to install. Repeatable. Defaults to static command facades " - "for Codex, Claude Code, and OpenCode. `gemini`, `cursor`, `zcode` and " - "`agy`, `pi` are opt-in: they write into those hosts' own homes only when " - "requested." + "for Codex, Claude Code, and OpenCode. `gemini`, `cursor`, `zcode`, " + "`agy`, `kiro-cli`, `pi` are opt-in: they write into those hosts' own " + "homes only when requested." ), ) parser.add_argument( diff --git a/loopx/control_plane/goals/start_contract.py b/loopx/control_plane/goals/start_contract.py index 2142727704..3bcb47c54b 100644 --- a/loopx/control_plane/goals/start_contract.py +++ b/loopx/control_plane/goals/start_contract.py @@ -91,6 +91,7 @@ def build_goal_start_contract( "cursor-agent": "agent-driven cursor-agent loop; every turn enters through quota should-run", "zcode": "agent-driven ZCode loop; turns enter through quota should-run", "agy": "agy native /goal loop with schedule wakes; quota entry advisory", + "kiro-cli": "Kiro CLI native /goal loop; quota entry advisory", "deepseek-harness-native": "DeepSeek Harness same-session plugin driver; every turn enters through quota should-run", "ark-managed-agent": "one-shot Goal", "manual": "external scheduler or manual quota/status loop", diff --git a/loopx/host_loop_activation.py b/loopx/host_loop_activation.py index b0f6507283..28172ed474 100644 --- a/loopx/host_loop_activation.py +++ b/loopx/host_loop_activation.py @@ -3,8 +3,16 @@ from typing import Any from .agent_registry import normalize_registered_agents -from .agy_goal_mode import AGY_ACCEPTED_INPUTS, agy_activation_extras +from .agy_goal_mode import AGY_ACCEPTED_INPUTS from .control_plane.scheduler.execution_context import SchedulerRuntimeProfile +from .host_loop_activation_skill_facade import ( + agy_cli_activation, + cursor_agent_activation, + gemini_cli_activation, + kiro_cli_activation, + zcode_activation, +) +from .kiro_cli_goal_mode import KIRO_CLI_AGENT_TYPE_CATALOG_ENTRY from .control_plane.todos.contract import ( normalize_required_capabilities, normalize_todo_claimed_by, @@ -49,6 +57,7 @@ def scheduler_command_binding_for_agent_type( "cursor-agent": SchedulerRuntimeProfile.GENERIC_CLI_AGENT_LOOP, "zcode": SchedulerRuntimeProfile.GENERIC_CLI_AGENT_LOOP, "agy": SchedulerRuntimeProfile.GENERIC_CLI_AGENT_LOOP, + "kiro-cli": SchedulerRuntimeProfile.GENERIC_CLI_AGENT_LOOP, "deepseek-harness": SchedulerRuntimeProfile.GENERIC_CLI_AGENT_LOOP, "deepseek-harness-native": SchedulerRuntimeProfile.GENERIC_CLI_AGENT_LOOP, }.get(canonical) @@ -77,6 +86,7 @@ def agent_type_uses_host_managed_skills(agent_type: str) -> bool: "cursor-agent", "zcode", "agy", + "kiro-cli", "deepseek-harness", "deepseek-harness-native", "manual", @@ -259,6 +269,7 @@ def agent_type_uses_host_managed_skills(agent_type: str) -> bool: "entry": "the LoopX skill installed in ~/.gemini/antigravity-cli/skills", "accepted_inputs": list(AGY_ACCEPTED_INPUTS), }, + "kiro-cli": KIRO_CLI_AGENT_TYPE_CATALOG_ENTRY, "deepseek-harness": { "display_name": "DeepSeek Harness", "host_loop": "DeepSeek Harness headless/automation loop gated by LoopX quota", @@ -363,6 +374,8 @@ def to_payload(self) -> dict[str, Any]: "agy": "agy", "antigravity": "agy", "antigravity-cli": "agy", + "kiro-cli": "kiro-cli", + "kiro": "kiro-cli", "deepseek-harness": "deepseek-harness", "dsh": "deepseek-harness", "deepseek-harness-native": "deepseek-harness-native", @@ -500,6 +513,7 @@ def _heartbeat_commands( "cursor-agent": "Cursor Agent CLI loop gated by LoopX", "zcode": "ZCode agent loop gated by LoopX", "agy": "Antigravity CLI agent loop with advisory LoopX quota pacing", + "kiro-cli": "Kiro CLI native /goal loop with advisory LoopX quota pacing", "deepseek-harness": "DeepSeek Harness automation loop gated by LoopX", "deepseek-harness-native": "DeepSeek Harness same-session plugin loop gated by LoopX", "manual": "External scheduler or manual shell LoopX poll", @@ -1059,138 +1073,6 @@ def _traex_activation(commands: dict[str, str]) -> dict[str, Any]: } -def _skill_facade_cli_activation( - commands: dict[str, str], - cli_bin: str, - *, - host_label: str, - host_surface: str, - install_surface: str, - skills_root: str, - extra_host_mutation: dict[str, Any] | None = None, - extra_activation_steps: list[str] | None = None, - host_scheduler_note: str | None = None, - activation_method: str = "run_agent_cli_loop_gated_by_quota", -) -> dict[str, Any]: - """Activation for a CLI host that LoopX reaches through a skill facade. - - For skill-facade CLI hosts where no direct host-native loop binding is - integrated, the loop driver is the agent's own turn loop and LoopX gates it - by requiring every continuation to enter through quota should-run. A host - that does ship a native in-session scheduler passes ``host_scheduler_note`` - so the packet states that primitive instead of the default no-scheduler - sentence. A host that also owns a native goal primitive overrides - ``activation_method`` to name the goal binding. The weaker facade boundary - remains explicit rather than claiming autonomous heartbeat support the host - cannot deliver. - """ - return { - "host_surface": host_surface, - "entry_command_hint": f"the LoopX skill installed in {skills_root}", - "activation_method": activation_method, - "activation_input_command": commands["heartbeat_prompt_json"], - "setup_command": ( - f"{cli_bin} slash-commands --install --surface {install_surface}" - ), - "host_mutation": { - "owner": f"{host_label} session", - "host_loop_primitive": None, - "cli_can_mutate_directly": False, - "loop_driver": "agent_cli_turn_loop", - "missing_host_tool_gate": ( - f"{host_label} exposes no goal or automation primitive for LoopX to " - "bind. If the session cannot keep entering through quota should-run, " - "show the exact heartbeat-prompt command for the user to run and do " - "not claim autonomous heartbeat support." - ), - **(extra_host_mutation or {}), - }, - "activation_steps": [ - f"Install or refresh the LoopX {host_label} surface when needed.", - "Run the heartbeat-prompt JSON command after project state and todos are written.", - "Read task_body from the JSON payload and carry it as the session objective.", - *(extra_activation_steps or []), - "Start every following turn with quota should-run and stop when it says stop; " - + ( - host_scheduler_note - or "there is no host scheduler to fall back on." - ), - ], - "success_criteria": [ - f"The {host_label} session has the LoopX skill facade installed and the " - "generated task_body as its objective.", - "Each continuation enters through LoopX quota/status/state, and a stop " - "decision ends the session loop instead of free-running.", - ], - } - - -def _gemini_cli_activation(commands: dict[str, str], cli_bin: str) -> dict[str, Any]: - return _skill_facade_cli_activation( - commands, - cli_bin, - host_label="Gemini CLI", - host_surface="gemini_cli_agent_loop", - install_surface="gemini", - skills_root="GEMINI_HOME/skills", - ) - - -def _cursor_agent_activation(commands: dict[str, str], cli_bin: str) -> dict[str, Any]: - return _skill_facade_cli_activation( - commands, - cli_bin, - host_label="Cursor Agent CLI", - host_surface="cursor_agent_loop", - install_surface="cursor", - skills_root="CURSOR_HOME/skills", - extra_host_mutation={ - # The MCP server is how a cursor-agent session reads LoopX state - # without shelling out; the loop is still the agent's own turns. - "host_mcp_server": "loopx", - "host_mcp_config": "CURSOR_HOME/mcp.json", - }, - extra_activation_steps=[ - "Confirm the `loopx` MCP server is enabled in this session " - "(`cursor-agent mcp`); it is registered by the surface installer.", - ], - ) - - -def _zcode_activation(commands: dict[str, str], cli_bin: str) -> dict[str, Any]: - from .zcode_goal_mode import SKILLS_ROOT_LABEL, ZCODE_INSTALL_SURFACE - - return _skill_facade_cli_activation( - commands, - cli_bin, - host_label="ZCode", - host_surface="zcode_agent_loop", - install_surface=ZCODE_INSTALL_SURFACE, - skills_root=SKILLS_ROOT_LABEL, - extra_host_mutation={ - "missing_host_tool_gate": ( - "LoopX is currently integrated with ZCode via skill facade and " - "has no direct machine binding for ZCode native Goal Mode or " - "Automations. If the session cannot keep entering through quota " - "should-run, show the exact heartbeat-prompt command for the user " - "to run and do not claim autonomous heartbeat support." - ), - }, - ) - - -def _agy_cli_activation(commands: dict[str, str], cli_bin: str) -> dict[str, Any]: - return _skill_facade_cli_activation( - commands, - cli_bin, - host_label="Antigravity CLI", - host_surface="agy_agent_loop", - install_surface="agy", - skills_root="~/.gemini/antigravity-cli/skills", - **agy_activation_extras(), - ) - - def _deepseek_harness_activation(commands: dict[str, str]) -> dict[str, Any]: return { "host_surface": "deepseek_harness_automation_loop", @@ -1349,13 +1231,15 @@ def build_host_loop_activation_packet( elif canonical == "pi": surface = _pi_activation(commands, cli_bin) elif canonical == "gemini-cli": - surface = _gemini_cli_activation(commands, cli_bin) + surface = gemini_cli_activation(commands, cli_bin) elif canonical == "cursor-agent": - surface = _cursor_agent_activation(commands, cli_bin) + surface = cursor_agent_activation(commands, cli_bin) elif canonical == "zcode": - surface = _zcode_activation(commands, cli_bin) + surface = zcode_activation(commands, cli_bin) elif canonical == "agy": - surface = _agy_cli_activation(commands, cli_bin) + surface = agy_cli_activation(commands, cli_bin) + elif canonical == "kiro-cli": + surface = kiro_cli_activation(commands, cli_bin) elif canonical == "deepseek-harness": surface = _deepseek_harness_activation(commands) elif canonical == "deepseek-harness-native": diff --git a/loopx/host_loop_activation_skill_facade.py b/loopx/host_loop_activation_skill_facade.py new file mode 100644 index 0000000000..0335cd6304 --- /dev/null +++ b/loopx/host_loop_activation_skill_facade.py @@ -0,0 +1,170 @@ +"""Host-loop activation for CLI hosts LoopX reaches through a skill facade. + +These hosts share one seam: LoopX cannot mutate their loop surface from the +CLI, so the installed `/loopx` skill facade is the entry and the host's own +turn loop is the driver. The differences between them are small and factual — +which skills root the installer writes to, whether the host owns a native goal +or wake primitive, and how honest the quota claim can be — which is why they +live together here instead of each growing `host_loop_activation.py`, whose +module budget is already spent on the agent-type catalog and identity rules. + +Each host's facts stay in its own `*_goal_mode` package; this module only +binds them to the shared packet shape. +""" + +from __future__ import annotations + +from typing import Any + +from .agy_goal_mode import agy_activation_extras +from .kiro_cli_goal_mode import ( + KIRO_CLI_INSTALL_SURFACE, + SKILLS_ROOT_LABEL as KIRO_CLI_SKILLS_ROOT_LABEL, + kiro_cli_activation_extras, +) +from .zcode_goal_mode import ( + SKILLS_ROOT_LABEL as ZCODE_SKILLS_ROOT_LABEL, + ZCODE_INSTALL_SURFACE, +) + + +def skill_facade_cli_activation( + commands: dict[str, str], + cli_bin: str, + *, + host_label: str, + host_surface: str, + install_surface: str, + skills_root: str, + extra_host_mutation: dict[str, Any] | None = None, + extra_activation_steps: list[str] | None = None, + host_scheduler_note: str | None = None, + activation_method: str = "run_agent_cli_loop_gated_by_quota", +) -> dict[str, Any]: + """Activation for a CLI host that LoopX reaches through a skill facade. + + For skill-facade CLI hosts where no direct host-native loop binding is + integrated, the loop driver is the agent's own turn loop and LoopX gates it + by requiring every continuation to enter through quota should-run. A host + that does ship a native in-session scheduler passes ``host_scheduler_note`` + so the packet states that primitive instead of the default no-scheduler + sentence. A host that also owns a native goal primitive overrides + ``activation_method`` to name the goal binding. The weaker facade boundary + remains explicit rather than claiming autonomous heartbeat support the host + cannot deliver. + """ + return { + "host_surface": host_surface, + "entry_command_hint": f"the LoopX skill installed in {skills_root}", + "activation_method": activation_method, + "activation_input_command": commands["heartbeat_prompt_json"], + "setup_command": ( + f"{cli_bin} slash-commands --install --surface {install_surface}" + ), + "host_mutation": { + "owner": f"{host_label} session", + "host_loop_primitive": None, + "cli_can_mutate_directly": False, + "loop_driver": "agent_cli_turn_loop", + "missing_host_tool_gate": ( + f"{host_label} exposes no goal or automation primitive for LoopX to " + "bind. If the session cannot keep entering through quota should-run, " + "show the exact heartbeat-prompt command for the user to run and do " + "not claim autonomous heartbeat support." + ), + **(extra_host_mutation or {}), + }, + "activation_steps": [ + f"Install or refresh the LoopX {host_label} surface when needed.", + "Run the heartbeat-prompt JSON command after project state and todos are written.", + "Read task_body from the JSON payload and carry it as the session objective.", + *(extra_activation_steps or []), + "Start every following turn with quota should-run and stop when it says stop; " + + ( + host_scheduler_note + or "there is no host scheduler to fall back on." + ), + ], + "success_criteria": [ + f"The {host_label} session has the LoopX skill facade installed and the " + "generated task_body as its objective.", + "Each continuation enters through LoopX quota/status/state, and a stop " + "decision ends the session loop instead of free-running.", + ], + } + + +def gemini_cli_activation(commands: dict[str, str], cli_bin: str) -> dict[str, Any]: + return skill_facade_cli_activation( + commands, + cli_bin, + host_label="Gemini CLI", + host_surface="gemini_cli_agent_loop", + install_surface="gemini", + skills_root="GEMINI_HOME/skills", + ) + + +def cursor_agent_activation(commands: dict[str, str], cli_bin: str) -> dict[str, Any]: + return skill_facade_cli_activation( + commands, + cli_bin, + host_label="Cursor Agent CLI", + host_surface="cursor_agent_loop", + install_surface="cursor", + skills_root="CURSOR_HOME/skills", + extra_host_mutation={ + # The MCP server is how a cursor-agent session reads LoopX state + # without shelling out; the loop is still the agent's own turns. + "host_mcp_server": "loopx", + "host_mcp_config": "CURSOR_HOME/mcp.json", + }, + extra_activation_steps=[ + "Confirm the `loopx` MCP server is enabled in this session " + "(`cursor-agent mcp`); it is registered by the surface installer.", + ], + ) + + +def zcode_activation(commands: dict[str, str], cli_bin: str) -> dict[str, Any]: + return skill_facade_cli_activation( + commands, + cli_bin, + host_label="ZCode", + host_surface="zcode_agent_loop", + install_surface=ZCODE_INSTALL_SURFACE, + skills_root=ZCODE_SKILLS_ROOT_LABEL, + extra_host_mutation={ + "missing_host_tool_gate": ( + "LoopX is currently integrated with ZCode via skill facade and " + "has no direct machine binding for ZCode native Goal Mode or " + "Automations. If the session cannot keep entering through quota " + "should-run, show the exact heartbeat-prompt command for the user " + "to run and do not claim autonomous heartbeat support." + ), + }, + ) + + +def agy_cli_activation(commands: dict[str, str], cli_bin: str) -> dict[str, Any]: + return skill_facade_cli_activation( + commands, + cli_bin, + host_label="Antigravity CLI", + host_surface="agy_agent_loop", + install_surface="agy", + skills_root="~/.gemini/antigravity-cli/skills", + **agy_activation_extras(), + ) + + +def kiro_cli_activation(commands: dict[str, str], cli_bin: str) -> dict[str, Any]: + return skill_facade_cli_activation( + commands, + cli_bin, + host_label="Kiro CLI", + host_surface="kiro_cli_agent_loop", + install_surface=KIRO_CLI_INSTALL_SURFACE, + skills_root=KIRO_CLI_SKILLS_ROOT_LABEL, + **kiro_cli_activation_extras(), + ) diff --git a/loopx/kiro_cli_goal_mode/__init__.py b/loopx/kiro_cli_goal_mode/__init__.py new file mode 100644 index 0000000000..e2edbc7c83 --- /dev/null +++ b/loopx/kiro_cli_goal_mode/__init__.py @@ -0,0 +1,159 @@ +from __future__ import annotations + +from pathlib import Path +from typing import Any + +KIRO_CLI_INSTALL_SURFACE = "kiro-cli" +KIRO_CLI_AGENT_TYPE = "kiro-cli" +DEFAULT_KIRO_CLI_HOME = ".kiro" +SKILLS_SUBDIR = "skills" +SKILLS_ROOT_LABEL = "~/.kiro/skills" +KIRO_CLI_ACCEPTED_INPUTS = ( + "kiro-cli", + "kiro_cli", + "kiro cli", + "kirocli", + "kiro", + "kiro-cli-tui", + "kiro tui", +) + +# Native goal primitive built into the kiro-cli binary (probed live on +# kiro-cli 1.0.437 / TUI shell 2.21.1: `/goal` is present in the binary's +# slash-command registry and documented by the host's own `/goal` reference). +# The host owns the iteration loop: it re-dispatches the turn until the model +# proves completion through the `goal` tool or the iteration budget runs out. +KIRO_CLI_GOAL_COMMAND = "/goal" +KIRO_CLI_GOAL_CLEAR_COMMAND = "/goal clear" +KIRO_CLI_GOAL_MAX_FLAG = "--max" +KIRO_CLI_GOAL_DEFAULT_MAX_ITERATIONS = 5 +KIRO_CLI_GOAL_MAX_ITERATION_CEILING = 50 +KIRO_CLI_GOAL_COMPLETION_TOOL = "goal" +KIRO_CLI_GOAL_TERMINAL_STATES = ("completed", "exhausted") + +# Kiro CLI stamps every session with a stable id, which is what a LoopX +# thread binding can key on instead of prose. +KIRO_CLI_SESSION_ID_ENV = "KIRO_SESSION_ID" + +# The host ships a real hook seam, and `preToolUse` can block a tool call by +# exiting 2. LoopX installs no hook today, so quota pacing stays advisory; the +# seam is recorded here so the honest claim and the future binding point stay +# in one place instead of being rediscovered from host docs. +KIRO_CLI_HOOK_TRIGGERS = ( + "agentSpawn", + "userPromptSubmit", + "preToolUse", + "postToolUse", + "stop", +) +KIRO_CLI_HOOK_CONFIG_LABEL = "~/.kiro/agents/.json (or .kiro/agents/.json)" + +KIRO_CLI_NATIVE_GOAL_FACTS = ( + "native `/goal [--max N]` command: the host re-dispatches " + "turns toward one objective until completion is proven or the iteration " + "budget is spent (default 5, ceiling 50)", + "the built-in `goal` tool's `complete` command enforces a completion " + "contract: every success criterion needs cited tool output, not narrative " + "confidence", + "`/goal clear` cancels the active goal; the loop also stops on Exhausted " + "and pauses after 3 consecutive dispatch failures", + "`hooks` in the agent config expose agentSpawn/userPromptSubmit/" + "preToolUse/postToolUse/stop, and preToolUse can block a tool call with " + "exit code 2", +) + +KIRO_CLI_AGENT_TYPE_CATALOG_ENTRY: dict[str, Any] = { + "display_name": "Kiro CLI", + "host_loop": ( + "Kiro CLI native /goal iteration loop bounded by the host's own " + "iteration budget (LoopX quota pacing is advisory)" + ), + "entry": f"/loopx from the LoopX skill installed in {SKILLS_ROOT_LABEL}", + "accepted_inputs": list(KIRO_CLI_ACCEPTED_INPUTS), +} + + +def kiro_cli_activation_extras() -> dict[str, Any]: + """Keyword overrides for ``_kiro_cli_activation``'s facade call. + + Keeps the Kiro CLI host facts (goal command, iteration budget, completion + tool, gate text, activation steps) in this package instead of growing + ``host_loop_activation.py`` past its module metric budget. Kiro CLI ships + both halves of a goal-mode host: a native goal primitive — ``/goal + [--max N]`` whose host-side loop re-dispatches turns until the model + proves completion through the ``goal`` tool — and a bounded iteration + budget the host itself enforces (default 5, ceiling 50). What it does not + ship is a cross-session daemon, and LoopX installs no hook, so quota + pacing is instructed rather than enforced. + """ + return { + "activation_method": "bind_native_goal_with_advisory_quota_entry", + "extra_host_mutation": { + "host_loop_primitive": "kiro-cli-/goal-iteration-loop", + "loop_driver": "kiro_cli_native_goal_loop", + "quota_gate_enforcement": "advisory_only", + "native_goal_command": KIRO_CLI_GOAL_COMMAND, + "native_goal_cancel_command": KIRO_CLI_GOAL_CLEAR_COMMAND, + "native_goal_max_flag": KIRO_CLI_GOAL_MAX_FLAG, + "native_goal_default_max_iterations": ( + KIRO_CLI_GOAL_DEFAULT_MAX_ITERATIONS + ), + "native_goal_max_iteration_ceiling": ( + KIRO_CLI_GOAL_MAX_ITERATION_CEILING + ), + "native_goal_completion_tool": KIRO_CLI_GOAL_COMPLETION_TOOL, + "host_session_id_env": KIRO_CLI_SESSION_ID_ENV, + "host_hook_triggers": list(KIRO_CLI_HOOK_TRIGGERS), + "missing_host_tool_gate": ( + "Kiro CLI's /goal loop runs only while the CLI session is " + "alive; there is no cross-session daemon and the host caps it " + f"at {KIRO_CLI_GOAL_MAX_ITERATION_CEILING} iterations. LoopX " + "installs no Kiro hook, so no host hook intercepts a native " + "iteration and quota pacing is advisory: the facade instructs, " + "it cannot enforce. If the goal reaches Exhausted or the " + "session ends with work remaining, show the exact " + "heartbeat-prompt command for the user to run and do not " + "claim unattended heartbeat support." + ), + }, + "extra_activation_steps": [ + "Bind the objective with the native goal command: " + f"`{KIRO_CLI_GOAL_COMMAND} {KIRO_CLI_GOAL_MAX_FLAG} ` " + "— choose N from the remaining quota slots, not from ambition, and " + f"never above the host ceiling of " + f"{KIRO_CLI_GOAL_MAX_ITERATION_CEILING} " + f"(host default is {KIRO_CLI_GOAL_DEFAULT_MAX_ITERATIONS}); " + f"`{KIRO_CLI_GOAL_CLEAR_COMMAND}` cancels it.", + "Start every turn and native goal iteration with `quota " + "should-run` and honor a stop/throttle decision before any " + "delivery work — instructed pacing, not a host-enforced gate.", + f"Settle the goal through the built-in `{KIRO_CLI_GOAL_COMPLETION_TOOL}` " + "tool only after LoopX writeback: its completion contract wants " + "the same cited evidence LoopX records, so cite the validated " + "commands rather than a narrative summary.", + "When the goal reports Exhausted and quota still allows more " + "work, re-arm one further bounded goal instead of free-running, " + "and re-enter through `quota should-run` on the same advisory " + "basis.", + ], + "host_scheduler_note": ( + "the native `/goal` iteration loop drives this session within the " + "host's own iteration budget; quota should-run entry is advisory " + "guidance in the facade, not a host-enforced gate." + ), + } + + +def kiro_home(value: str | None = None) -> Path: + """The fixed Kiro CLI home: ``~/.kiro``. + + Kiro CLI discovers global skills from ``~/.kiro/skills//SKILL.md`` + and workspace skills from ``.kiro/skills//SKILL.md``; the default + agent carries both as ``skill://`` resources. The host documents no home + override for this root (``KIRO_AGENT_CONFIG_DIR`` relocates agent configs + only, not skills), so LoopX exposes none either: installs target exactly + this path, HOME-relative so tests stay hermetic. ``value`` is an internal + injection point for tests, not a public override. + """ + raw = value or str(Path.home() / DEFAULT_KIRO_CLI_HOME) + return Path(raw).expanduser() diff --git a/loopx/slash_command_install.py b/loopx/slash_command_install.py index 6e8fa581fb..72bb46c891 100644 --- a/loopx/slash_command_install.py +++ b/loopx/slash_command_install.py @@ -9,6 +9,7 @@ from typing import Any from .agy_goal_mode import agy_home as _agy_home +from .kiro_cli_goal_mode import kiro_home as _kiro_home from .opencode_goal_mode import plugin_source, runtime_source from .pi_goal_mode import extension_source as pi_extension_source from .pi_goal_mode import runtime_source as pi_runtime_source @@ -166,7 +167,7 @@ def _command_prompt_specs(*, cli_bin: str, include_legacy_aliases: bool) -> list "argument_hint": "[--fine-grained] [--capability-route issue-fix] [task text]", "instructions": [ "Visible command arguments: `$ARGUMENTS`.", - "Identify the exact current host surface (codex-app, codex-app-ssh, codex-ide-plugin, codex-cli-tui, opencode, opencode2, traex-cli, pi, gemini-cli, cursor-agent, zcode, agy, deepseek-harness, or ark-managed-agent).", + "Identify the exact current host surface (codex-app, codex-app-ssh, codex-ide-plugin, codex-cli-tui, opencode, opencode2, traex-cli, pi, gemini-cli, cursor-agent, zcode, agy, kiro-cli, deepseek-harness, or ark-managed-agent).", _loopx_start_goal_arguments_instruction( cli_bin=cli_bin, host_surface=None, @@ -574,6 +575,8 @@ def _normalize_surfaces(surfaces: list[str] | None) -> list[str]: candidates = ["zcode"] elif surface in {"agy", "antigravity", "antigravity-cli"}: candidates = ["agy"] + elif surface in {"kiro", "kiro-cli", "kirocli"}: + candidates = ["kiro-cli"] else: candidates = [surface] for candidate in candidates: @@ -761,6 +764,7 @@ def install_slash_commands( zcode_home: str | None = None, zcode_agents_home: str | None = None, agy_home: str | None = None, + kiro_home: str | None = None, pi_project: str | None = None, ) -> dict[str, Any]: specs = _command_prompt_specs(cli_bin=cli_bin, include_legacy_aliases=include_legacy_aliases) @@ -772,6 +776,7 @@ def install_slash_commands( cursor_root = _cursor_home(cursor_home) zcode_root = _zcode_home(zcode_home or zcode_agents_home) agy_root = _agy_home(agy_home) + kiro_root = _kiro_home(kiro_home) pi_project_root = Path(pi_project or ".").expanduser().resolve() installed: list[dict[str, Any]] = [] @@ -999,6 +1004,26 @@ def install_slash_commands( flat=True, ) + if "kiro-cli" in effective_surfaces: + # Kiro CLI discovers global skills from ~/.kiro/skills//SKILL.md + # (workspace skills live in .kiro/skills), and exposes every discovered + # skill as a `/` slash command. The host documents no home + # override for that root — KIRO_AGENT_CONFIG_DIR relocates agent + # configs only — so LoopX offers none either. A same-named user prompt + # in .kiro/prompts wins over a skill by Kiro's own resolution order; + # the installer never touches the prompt directories. + _install_skill_facade( + specs=specs, + installed=installed, + skills_dir=kiro_root / "skills", + surface="kiro-cli", + host_surfaces=["kiro-cli"], + mechanism="kiro_cli_skills", + execute=execute, + uninstall=uninstall, + invoke_prefix="/", + ) + if "cursor" in effective_surfaces: # Cursor reads SKILL.md from CURSOR_HOME/skills (its skill roots also # include .claude/skills and .codex/skills, but relying on another @@ -1338,6 +1363,7 @@ def install_slash_commands( "cursor_mcp_path": str(cursor_root / "mcp.json") if "cursor" in effective_surfaces else None, "zcode_skill_dir": str(zcode_root / "skills") if "zcode" in effective_surfaces else None, "agy_skill_dir": str(agy_root / "skills") if "agy" in effective_surfaces else None, + "kiro_cli_skill_dir": str(kiro_root / "skills") if "kiro-cli" in effective_surfaces else None, "opencode_skill_dir": str(opencode_root / "skills") if "opencode" in effective_surfaces else None, "opencode_command_dir": str(opencode_root / "commands") if "opencode" in effective_surfaces else None, "opencode_plugin_path": str(opencode_root / "plugins" / "loopx-goal.js") if "opencode" in effective_surfaces and with_goal_bridge else None, @@ -1360,6 +1386,7 @@ def install_slash_commands( "Cursor discovers skills from CURSOR_HOME/skills and has no user-defined slash commands, so the cursor surface installs the skill facade and registers the LoopX MCP server in CURSOR_HOME/mcp.json; run `cursor-agent mcp enable loopx` once to approve it.", "ZCode discovers user skills from ZCODE_HOME/skills (default ~/.zcode/skills) and exposes each skill for invocation via `$skill-name` or Settings -> Skills.", "Antigravity CLI discovers global skills from the fixed ~/.gemini/antigravity-cli/skills root using the documented flat layout (one .md per skill); the agy surface is opt-in and offers no home override because the host documents none.", + "Kiro CLI discovers global skills from ~/.kiro/skills//SKILL.md and exposes each as a `/` slash command; the kiro-cli surface is opt-in and offers no home override because the host documents none for that root. Kiro resolves .kiro/prompts and ~/.kiro/prompts before skills, so a same-named user prompt shadows the managed skill.", "OpenCode discovers global skills from OPENCODE_CONFIG_DIR/skills in addition to the static command facade; a command is typed by the user, a skill can be reached by the model itself.", "The default all surface installs only OpenCode's static command facade; the executable goal bridge requires --with-goal-bridge.", "The Pi surface is opt-in and installs the self-contained goal extension and its loop runtime into the project's .pi/extensions/; it is not part of the default all surface.", @@ -1386,6 +1413,7 @@ def render_slash_command_install_markdown(payload: dict[str, Any]) -> str: gemini_skill_dir = payload.get("summary", {}).get("gemini_skill_dir") cursor_skill_dir = payload.get("summary", {}).get("cursor_skill_dir") zcode_skill_dir = payload.get("summary", {}).get("zcode_skill_dir") + kiro_cli_skill_dir = payload.get("summary", {}).get("kiro_cli_skill_dir") opencode_command_dir = payload.get("summary", {}).get("opencode_command_dir") opencode_plugin_path = payload.get("summary", {}).get("opencode_plugin_path") if codex_prompt_dir: @@ -1400,6 +1428,8 @@ def render_slash_command_install_markdown(payload: dict[str, Any]) -> str: lines.append(f"- cursor skills: `{cursor_skill_dir}`") if zcode_skill_dir: lines.append(f"- zcode skills: `{zcode_skill_dir}`") + if kiro_cli_skill_dir: + lines.append(f"- kiro-cli skills: `{kiro_cli_skill_dir}`") if opencode_command_dir: lines.append(f"- opencode commands: `{opencode_command_dir}`") if opencode_plugin_path: diff --git a/loopx/slash_commands.py b/loopx/slash_commands.py index 1702237a6f..4b104a4e26 100644 --- a/loopx/slash_commands.py +++ b/loopx/slash_commands.py @@ -76,6 +76,7 @@ def build_slash_command_catalog( "cursor-agent": "drive the loop from the agent's own turns; enter every turn through quota should-run", "zcode": "drive the loop from the agent's turns; enter through quota should-run", "agy": "native /goal + schedule wakes; quota entry advisory", + "kiro-cli": "native /goal loop; quota entry advisory", "manual": "wire an external scheduler or run quota/status manually", "other-agent": "use the custom host loop driver declared by `loopx agent-onboard`", }, From 63a001372f3d358508ded079075db03411c699bd Mon Sep 17 00:00:00 2001 From: "vlean.wei" Date: Mon, 7 Sep 2026 10:34:26 +0800 Subject: [PATCH 02/23] test(kiro-cli): cover the Kiro CLI host contract end to end Installing discoverable files is not the same as being a usable host: the generated facade tells the agent to run `start-goal --host-surface kiro-cli`, so the shared host-surface probes execute that path for real (start-goal, selection gate with an executable rerun_command, and the onboarding setup command installing from an unrelated cwd). Beyond the shared probes, the surface-specific checks pin what could silently drift into a false capability claim: the activation names the native `/goal` primitive and the host iteration ceiling, keeps `advisory_only` quota semantics with no "gated" wording in the rendered heartbeat commands, reports `/loopx` (not a bare skill id) as the invocation because Kiro exposes skills as slash commands, resolves the bare `kiro` product name, and preserves a user-owned `~/.kiro/skills/loopx/SKILL.md` while refreshing a managed one. The host-surface selection gate assertion gains the new choice; the gate is the fallback path a facade uses when the host is unclear, so an absent entry would make the surface unreachable. Signed-off-by: vlean.wei --- .../test_start_goal_compact_projection.py | 1 + tests/test_kiro_cli_host_surface.py | 290 ++++++++++++++++++ 2 files changed, 291 insertions(+) create mode 100644 tests/test_kiro_cli_host_surface.py diff --git a/tests/control_plane/test_start_goal_compact_projection.py b/tests/control_plane/test_start_goal_compact_projection.py index 6b64e35332..18e7f6e230 100644 --- a/tests/control_plane/test_start_goal_compact_projection.py +++ b/tests/control_plane/test_start_goal_compact_projection.py @@ -1625,6 +1625,7 @@ def test_cli_without_host_returns_read_only_host_selection_gate( "cursor-agent", "zcode", "agy", + "kiro-cli", "deepseek-harness", "deepseek-harness-native", "ark-managed-agent", diff --git a/tests/test_kiro_cli_host_surface.py b/tests/test_kiro_cli_host_surface.py new file mode 100644 index 0000000000..91070a2422 --- /dev/null +++ b/tests/test_kiro_cli_host_surface.py @@ -0,0 +1,290 @@ +"""End-to-end host contract for the Kiro CLI surface. + +Installing discoverable files is not the same as being a usable LoopX host. The +generated `/loopx` facade tells the agent to run `start-goal ... --host-surface +`, so these tests execute that path for real: if kiro-cli +is missing from the CLI choices, the selection gate or the activation dispatch, +the facade dead-ends at argparse and the surface is decorative. +""" + +from __future__ import annotations + +import os +from pathlib import Path + +import pytest +from host_surface_cli_probes import ( + onboarding_setup_command_installs, + selection_gate_offers_surface, + start_goal_accepts_surface, +) + +from loopx.agent_onboarding import _start_instruction, _surface_install_command +from loopx.host_loop_activation import ( + _heartbeat_commands, + build_agent_type_catalog, + build_host_loop_activation_packet, + normalize_agent_type, + scheduler_command_binding_for_agent_type, +) +from loopx.kiro_cli_goal_mode import ( + KIRO_CLI_GOAL_CLEAR_COMMAND, + KIRO_CLI_GOAL_COMMAND, + KIRO_CLI_GOAL_COMPLETION_TOOL, + KIRO_CLI_GOAL_DEFAULT_MAX_ITERATIONS, + KIRO_CLI_GOAL_MAX_ITERATION_CEILING, + KIRO_CLI_HOOK_TRIGGERS, + KIRO_CLI_NATIVE_GOAL_FACTS, + KIRO_CLI_SESSION_ID_ENV, + kiro_home, +) +from loopx.slash_command_install import install_slash_commands + +HOST_SURFACE = "kiro-cli" + + +def test_start_goal_accepts_the_kiro_cli_host_surface(tmp_path: Path) -> None: + payload = start_goal_accepts_surface(HOST_SURFACE, tmp_path) + activation = payload["command_pack"]["host_loop_activation"] + assert activation["host_surface"] == "kiro_cli_agent_loop" + + +def test_host_selection_gate_offers_kiro_cli_and_its_rerun_command_works( + tmp_path: Path, +) -> None: + selection_gate_offers_surface(HOST_SURFACE, tmp_path) + + +def test_agent_onboarding_setup_command_installs_the_kiro_cli_surface( + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, +) -> None: + monkeypatch.delenv("LOOPX_SKILLS_DIR", raising=False) + outside = tmp_path / "outside" + outside.mkdir() + env = { + "PATH": "/usr/bin:/bin", + "HOME": str(tmp_path / "home"), + } + if "PYTHONPATH" in os.environ: # keep hermetic when run from a worktree + env["PYTHONPATH"] = os.environ["PYTHONPATH"] + + # Kiro CLI reads global skills from ~/.kiro/skills//SKILL.md, the + # per-skill directory layout, not one flat file per skill. + onboarding_setup_command_installs( + HOST_SURFACE, + outside, + env, + expected_skill=(tmp_path / "home" / ".kiro" / "skills" / "loopx" / "SKILL.md"), + ) + + +def test_kiro_home_is_the_documented_fixed_path( + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, +) -> None: + # The host documents no home override for the skills root + # (KIRO_AGENT_CONFIG_DIR relocates agent configs only), so LoopX exposes + # none: only HOME itself (tests stay hermetic) and the internal injection + # parameter move the root. + monkeypatch.setenv("HOME", str(tmp_path / "home")) + monkeypatch.setenv("KIRO_AGENT_CONFIG_DIR", str(tmp_path / "elsewhere")) + assert kiro_home() == tmp_path / "home" / ".kiro" + assert kiro_home(str(tmp_path / "explicit")) == tmp_path / "explicit" + + +def test_installed_skills_are_invocable_as_kiro_slash_commands( + tmp_path: Path, +) -> None: + """Kiro exposes every discovered skill as `/`, so the reported + invocation must be the slash form the user actually types — a bare skill id + would send them looking for a menu the host does not have.""" + payload = install_slash_commands( + execute=True, + surfaces=["kiro"], # the bare product name must resolve to the surface + kiro_home=str(tmp_path / "kiro-home"), + ) + assert payload["ok"] is True + assert payload["effective_surfaces"] == [HOST_SURFACE] + rows = { + item["command"]: item + for item in payload["installed"] + if item["surface"] == HOST_SURFACE + } + assert rows["/loopx"]["invoke_as"] == ["/loopx"] + assert rows["/loopx"]["mechanism"] == "kiro_cli_skills" + assert ( + payload["summary"]["kiro_cli_skill_dir"] + == str(tmp_path / "kiro-home" / "skills") + ) + assert (tmp_path / "kiro-home" / "skills" / "loopx" / "SKILL.md").is_file() + + +def test_installer_preserves_user_owned_kiro_skill(tmp_path: Path) -> None: + """The skills root is shared with the user's own skills; an unmarked file + must never be overwritten, and a rerun over a managed file is a no-op.""" + skills_dir = tmp_path / "kiro-home" / "skills" + skill_path = skills_dir / "loopx" / "SKILL.md" + skill_path.parent.mkdir(parents=True) + skill_path.write_text("user-owned skill body\n", encoding="utf-8") + + payload = install_slash_commands( + execute=True, + surfaces=[HOST_SURFACE], + kiro_home=str(tmp_path / "kiro-home"), + ) + statuses = { + (item["surface"], item["command"]): item["status"] + for item in payload["installed"] + } + assert statuses[(HOST_SURFACE, "/loopx")] == "skipped_user_file" + assert skill_path.read_text(encoding="utf-8") == "user-owned skill body\n" + + skill_path.write_text( + "\nold\n", + encoding="utf-8", + ) + payload = install_slash_commands( + execute=True, + surfaces=[HOST_SURFACE], + kiro_home=str(tmp_path / "kiro-home"), + ) + statuses = { + (item["surface"], item["command"]): item["status"] + for item in payload["installed"] + } + assert statuses[(HOST_SURFACE, "/loopx")] == "updated" + assert "user-owned skill body" not in skill_path.read_text(encoding="utf-8") + + retire = install_slash_commands( + execute=True, + uninstall=True, + surfaces=[HOST_SURFACE], + kiro_home=str(tmp_path / "kiro-home"), + ) + assert not skill_path.exists() + assert retire["ok"] is True + + +def test_agent_type_catalog_and_scheduler_binding() -> None: + """A host with no scheduler binding falls through to the generic default and + the loop it actually runs stops being visible to the control plane.""" + catalog = build_agent_type_catalog() + entry = next( + item + for item in catalog["canonical_agent_types"] + if item["agent_type"] == HOST_SURFACE + ) + assert entry["display_name"] == "Kiro CLI" + assert entry["host_loop"] + assert "gated" not in entry["host_loop"].lower() + assert "advisory" in entry["host_loop"].lower() + # The bare product name is what a user types. + assert "kiro" in entry["accepted_inputs"] + assert normalize_agent_type("kiro") == HOST_SURFACE + assert normalize_agent_type("kiro-cli") == HOST_SURFACE + assert normalize_agent_type("Kiro CLI") == HOST_SURFACE + assert scheduler_command_binding_for_agent_type(HOST_SURFACE) == { + "runtime_profile": "generic_cli" + } + + +def test_activation_binds_native_goal_with_advisory_quota_entry() -> None: + """Kiro CLI owns a native goal primitive (`/goal [--max N]`, whose + host-side loop re-dispatches turns until the `goal` tool proves completion) + and a host-enforced iteration budget. The packet has to state exactly that + capability envelope: bind the objective via `/goal`, bound it by quota and + the host ceiling, state advisory quota pacing without claiming a host hook + intercepts iterations, and admit the loop dies with the session — an + overstated capability here is what makes an agent claim autonomous setup it + cannot deliver.""" + packet = build_host_loop_activation_packet( + agent_type=HOST_SURFACE, + goal_id="surface-goal", + agent_id="probe-agent", + registered_agents=["probe-agent"], + ) + assert packet["activation_method"] == "bind_native_goal_with_advisory_quota_entry" + mutation = packet["host_mutation"] + assert mutation["cli_can_mutate_directly"] is False + # The native primitive is real and must be named, not denied. + assert mutation["host_loop_primitive"] == "kiro-cli-/goal-iteration-loop" + assert mutation["loop_driver"] == "kiro_cli_native_goal_loop" + # The quota claim must be honest: advisory guidance, no installed hook. + assert mutation["quota_gate_enforcement"] == "advisory_only" + assert mutation["native_goal_command"] == KIRO_CLI_GOAL_COMMAND + assert mutation["native_goal_cancel_command"] == KIRO_CLI_GOAL_CLEAR_COMMAND + assert ( + mutation["native_goal_max_iteration_ceiling"] + == KIRO_CLI_GOAL_MAX_ITERATION_CEILING + ) + assert ( + mutation["native_goal_default_max_iterations"] + == KIRO_CLI_GOAL_DEFAULT_MAX_ITERATIONS + ) + assert mutation["native_goal_completion_tool"] == KIRO_CLI_GOAL_COMPLETION_TOOL + assert mutation["host_session_id_env"] == KIRO_CLI_SESSION_ID_ENV + # The hook seam exists but LoopX installs none; recording the triggers must + # not be read as a claim of enforcement. + assert "preToolUse" in mutation["host_hook_triggers"] + # The loop dies with the CLI session; the gate text must say so instead of + # promising unattended heartbeat support. + gate = mutation["missing_host_tool_gate"] + assert "only" in gate + assert "alive" in gate + assert "daemon" in gate + assert "advisory" in gate + assert "installs no Kiro hook" in gate + + steps = " ".join(packet["activation_steps"]) + assert "`/goal --max `" in steps + assert str(KIRO_CLI_GOAL_MAX_ITERATION_CEILING) in steps + assert "quota should-run" in steps + assert KIRO_CLI_GOAL_COMPLETION_TOOL in steps + assert "no host scheduler to fall back on" not in steps + + assert packet["setup_command"] == _surface_install_command( + HOST_SURFACE, "loopx", "." + ) + assert "quota should-run" in _start_instruction(HOST_SURFACE) + assert "/goal" in _start_instruction(HOST_SURFACE) + assert ( + packet["entry_command_hint"] == "the LoopX skill installed in ~/.kiro/skills" + ) + # Rendered heartbeat commands and scope must carry no machine-gate semantics. + assert "gated" not in packet["activation_input_command"].lower() + assert "advisory" in packet["activation_input_command"].lower() + hb = _heartbeat_commands( + goal_id="surface-goal", + agent_type=HOST_SURFACE, + cli_bin="loopx", + agent_id="probe-agent", + ) + assert "gated" not in hb["heartbeat_prompt"].lower() + assert "gated" not in hb["heartbeat_prompt_json"].lower() + assert "advisory" in hb["heartbeat_prompt"].lower() + assert "advisory" in hb["heartbeat_prompt_json"].lower() + + +def test_native_goal_facts_match_the_probed_host() -> None: + """The host-facts constants are the single source the activation packet, + README and PR narrative cite; they must stay pinned to what the host + actually documents and what the probed binary exposes.""" + assert KIRO_CLI_GOAL_COMMAND == "/goal" + assert KIRO_CLI_GOAL_CLEAR_COMMAND == "/goal clear" + assert KIRO_CLI_GOAL_DEFAULT_MAX_ITERATIONS == 5 + assert KIRO_CLI_GOAL_MAX_ITERATION_CEILING == 50 + assert KIRO_CLI_GOAL_COMPLETION_TOOL == "goal" + assert KIRO_CLI_SESSION_ID_ENV == "KIRO_SESSION_ID" + assert set(KIRO_CLI_HOOK_TRIGGERS) == { + "agentSpawn", + "userPromptSubmit", + "preToolUse", + "postToolUse", + "stop", + } + facts = " ".join(KIRO_CLI_NATIVE_GOAL_FACTS) + assert "--max" in facts + assert "ceiling 50" in facts + assert "completion contract" in facts + assert "exit code 2" in facts From ec68639bc5847cc875cdb256413ed1fe1eb803b5 Mon Sep 17 00:00:00 2001 From: "vlean.wei" Date: Mon, 7 Sep 2026 10:34:26 +0800 Subject: [PATCH 03/23] docs(kiro-cli): document the Kiro CLI host surface Adds the bilingual host-table row and the adapter README. Both state the native `/goal --max ` loop, the host-enforced iteration budget, the `goal` completion contract, and the two boundaries a user needs before trusting it: quota pacing is advisory because LoopX installs no Kiro hook, and a same-named prompt in `.kiro/prompts` shadows the managed skill by Kiro's own resolution order. Signed-off-by: vlean.wei --- README.md | 4 +- README.zh-CN.md | 4 +- loopx/kiro_cli_goal_mode/README.md | 98 ++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 loopx/kiro_cli_goal_mode/README.md diff --git a/README.md b/README.md index a485d37c39..3d891f78fb 100644 --- a/README.md +++ b/README.md @@ -295,6 +295,7 @@ LoopX should reuse existing state rather than overwrite it. Keep `.loopx/`, | Pi | Install the opt-in goal extension with `loopx slash-commands --install --surface pi`, then use `/loopx ` from a trusted Pi session. | Visible Pi goal extension gated by LoopX quota (`loopx_goal_activate` + `agent_settled` continuation) | | ZCode | Install the skill facade with `loopx slash-commands --install --surface zcode`, then invoke the `$loopx` skill (or `/loopx `) from a ZCode session in the project. | The ZCode session's own turn loop; every continuation enters through `quota should-run` | | Antigravity CLI (agy) | Install the skill facade with `loopx slash-commands --install --surface agy`, then invoke the `loopx` skill (or `/loopx `) from an `agy` session in the project. | The session's native `/goal` loop (audited until ``) with `schedule` self-wakes while the session lives; the facade instructs every turn/wake to re-enter through `quota should-run` — advisory pacing, not a host-enforced gate | +| Kiro CLI | Install the skill facade with `loopx slash-commands --install --surface kiro-cli`, then run `/loopx ` from a `kiro-cli` session in the project. | The session's native `/goal --max ` loop, bounded by the host's own iteration budget (default 5, ceiling 50) and settled through the built-in `goal` completion contract; the facade instructs every turn and iteration to re-enter through `quota should-run` — advisory pacing, not a host-enforced gate | | DeepSeek Harness (dsh) | Install the [native DSH plugin](packages/dsh-loopx-plugin/README.md), select the `loopx` skill, and describe the task. The [dsh goal-mode adapter](loopx/dsh_goal_mode/README.md) remains available for headless turns. | Native same-session continuation and GoalBar, or headless dsh segments; both remain gated by LoopX authority | | Cursor, shell, or custom runner | Use the installer and `loopx doctor`; connect manually or call LoopX from your runner. | Your shell, scheduler, or runner | @@ -303,7 +304,8 @@ The exact, copy-ready setup messages and host recovery paths live in the [Codex App host command registry contract](docs/reference/protocols/codex-app-host-command-registry-v0.md), the [Codex CLI packaged install path](docs/product/runtimes/codex-cli/codex-cli-packaged-install.md), the [Claude Code adapter](loopx/claude_goal_mode/README.md), the -[KunlunCode native Goal adapter](loopx/kunluncode_goal_mode/README.md), or the +[KunlunCode native Goal adapter](loopx/kunluncode_goal_mode/README.md), the +[Kiro CLI goal-mode adapter](loopx/kiro_cli_goal_mode/README.md), or the [DeepSeek Harness turn adapter](loopx/dsh_goal_mode/README.md). See the [60-second DSH × LoopX Replan recording and reproducible diff --git a/README.zh-CN.md b/README.zh-CN.md index 47e2027e8b..b61127f9f5 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -265,6 +265,7 @@ loopx start-goal --guided --project . --goal-text "你的长程目标" | Pi | 用 `loopx slash-commands --install --surface pi` 安装 opt-in goal extension,然后在受信任的 Pi 会话里用 `/loopx <任务>`。 | 由 LoopX quota gate 的可见 Pi goal extension(`loopx_goal_activate` + `agent_settled` 续跑) | | ZCode | 用 `loopx slash-commands --install --surface zcode` 安装 skill facade,然后在项目里的 ZCode 会话中调用 `$loopx` skill(或 `/loopx <复杂任务>`)。 | ZCode 会话自身的 turn loop;每次续跑都从 `quota should-run` 进入 | | Antigravity CLI(agy) | 用 `loopx slash-commands --install --surface agy` 安装 skill facade,然后在项目里的 `agy` 会话中调用 `loopx` skill(或 `/loopx <复杂任务>`)。 | 会话原生 `/goal` 循环(审计至 ``)加 `schedule` 自唤醒,随会话存活;facade 指示每次 turn/唤醒都先过 `quota should-run`——advisory 节流,非宿主强制 gate | +| Kiro CLI | 用 `loopx slash-commands --install --surface kiro-cli` 安装 skill facade,然后在项目里的 `kiro-cli` 会话中执行 `/loopx <复杂任务>`。 | 会话原生 `/goal <任务> --max ` 循环,由宿主自己的迭代预算兜底(默认 5,上限 50),并通过内置 `goal` 完成契约收口;facade 指示每次 turn 与迭代都先过 `quota should-run`——advisory 节流,非宿主强制 gate | | DeepSeek Harness(dsh) | 安装 [DSH 原生 Plugin](packages/dsh-loopx-plugin/README.md),在技能选择器中点 `loopx`,然后直接描述任务;[dsh goal-mode adapter](loopx/dsh_goal_mode/README.md) 继续支持 headless turn。 | 原生同会话续跑与 GoalBar,或 headless dsh 工作段;两条路径都遵守 LoopX authority | | Cursor、shell、自有 runner | 使用同一 installer 和 `loopx doctor`,再手动连接或由 runner 调用。 | 你的 shell、scheduler 或 runner | @@ -273,7 +274,8 @@ loopx start-goal --guided --project . --goal-text "你的长程目标" [Codex App host command registry](docs/reference/protocols/codex-app-host-command-registry-v0.md)、 [Codex CLI packaged install](docs/product/runtimes/codex-cli/codex-cli-packaged-install.md)和 [Claude Code adapter](loopx/claude_goal_mode/README.md)、 -[KunlunCode 原生 Goal adapter](docs/guides/kunluncode-adapter.zh-CN.md),以及 +[KunlunCode 原生 Goal adapter](docs/guides/kunluncode-adapter.zh-CN.md)、 +[Kiro CLI goal-mode adapter](loopx/kiro_cli_goal_mode/README.md),以及 [DeepSeek Harness turn adapter](loopx/dsh_goal_mode/README.md)。 可查看 [60 秒 DSH × LoopX Replan 真实录屏和可复现 diff --git a/loopx/kiro_cli_goal_mode/README.md b/loopx/kiro_cli_goal_mode/README.md new file mode 100644 index 0000000000..739e05f770 --- /dev/null +++ b/loopx/kiro_cli_goal_mode/README.md @@ -0,0 +1,98 @@ +# Kiro CLI goal mode + +LoopX adapter for [Kiro CLI](https://kiro.dev/) (binary `kiro-cli`) — a +terminal coding agent with skills, steering files, agent configs, hooks, MCP, +and a native goal loop. Kiro CLI ships both halves of a goal-mode host: a goal +primitive *and* a host-enforced iteration budget, so LoopX binds the objective +to the host's own loop instead of pretending the agent merely drives itself. + +## Native goal primitive + +`/goal [--max N]` — built-in command. The host re-dispatches +turns toward the stated objective, and the model must prove completion through +the built-in `goal` tool before the loop ends. + +- Iteration budget is host-enforced: default `5`, ceiling `50`. This is the + one part of the loop LoopX does not have to trust the model for. +- `/goal clear` cancels the active goal. The loop also stops in `Exhausted` + (budget spent without completion) and pauses after 3 consecutive dispatch + failures. +- The `goal` tool's `complete` command enforces a completion contract: each + success criterion needs cited tool output, and belief or narrative + confidence is explicitly not evidence — the same standard LoopX writeback + wants. + +Verified against `kiro-cli 1.0.437` (TUI shell `2.21.1`): `/goal` is present +in the binary's slash-command registry, and the host's own `/goal` and `goal` +tool references document the iteration budget, terminal states, and completion +contract. + +## Native hook seam + +Agent configs (`~/.kiro/agents/.json` or `.kiro/agents/.json`) +carry `hooks` for `agentSpawn`, `userPromptSubmit`, `preToolUse`, +`postToolUse`, and `stop`; a `preToolUse` hook can block a tool call by exiting +`2`. That is a real machine-enforceable seam, but **LoopX installs no Kiro +hook today**, so this surface does not claim enforcement. The trigger list is +recorded in `__init__.py` so a future enforced-quota binding has one place to +start from rather than rediscovering it from host docs. + +## What this surface is + +Kiro CLI discovers global skills from `~/.kiro/skills//SKILL.md` and +workspace skills from `.kiro/skills//SKILL.md`; the default agent carries +both as `skill://` resources, and every discovered skill is invocable as a +`/` slash command with `$ARGUMENTS` expansion. LoopX reaches a +Kiro CLI session through the generated `/loopx` skill facade, and the +activation binds the objective with the native `/goal --max `. + +Three honest limits, stated in the activation packet: + +- **Quota pacing is advisory.** LoopX installs no Kiro hook that intercepts a + native goal iteration, so `quota should-run` entry is facade guidance the + agent is instructed to follow — not a host-enforced gate. +- **The loop lives and dies with the session.** The `/goal` loop runs only + while the CLI session is alive; there is no cross-session daemon, so it + bounds a live session's segments, not an unattended host loop. +- **A same-named file prompt wins.** Kiro resolves `.kiro/prompts/*.md` and + `~/.kiro/prompts/*.md` before skills, so a user prompt named `loopx` shadows + the managed skill. The installer never touches the prompt directories. + +## Install + +```bash +loopx slash-commands --install --surface kiro-cli +``` + +Writes the managed LoopX skill facades (`loopx/SKILL.md`, +`loopx-global-*/SKILL.md`, …) into `~/.kiro/skills/` using Kiro's per-skill +directory layout. The host documents no home override for this root +(`KIRO_AGENT_CONFIG_DIR` relocates agent configs only, not skills), so LoopX +offers none either: installs target exactly that path. Managed files carry the +`loopx-managed-slash-command` marker and are refreshed by rerunning the +installer; user-owned files are never overwritten. + +## Use + +From a Kiro CLI session in a connected project, run `/loopx `. +The facade instructs the agent to run: + +```bash +loopx start-goal --guided --project . --slash-command-arguments="" --host-surface kiro-cli +``` + +After todo writeback, bind the generated heartbeat task body with +`/goal --max ` — with `N` taken from the remaining quota slots +and never above the host ceiling of 50 — start every turn and native goal +iteration with `quota should-run` (advisory guidance; LoopX does not intercept +native host iterations), and settle through the built-in `goal` tool only after +LoopX writeback so the cited evidence matches what LoopX recorded. + +Kiro CLI exports `KIRO_SESSION_ID` for every session; it is the stable value a +LoopX thread binding should key on instead of prose. + +## Layout + +- `__init__.py` — host facts: install surface id, fixed skills root resolution, + the agent-type catalog entry, and the activation extras (native goal command, + host iteration budget, completion tool, advisory quota boundary). From 487793691845653ac7e32ee5020e8cbd43afc07d Mon Sep 17 00:00:00 2001 From: "vlean.wei" Date: Mon, 7 Sep 2026 11:28:35 +0800 Subject: [PATCH 04/23] fix(slash-commands): quote front-matter scalars only when YAML needs it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Kiro CLI derives a skill's slash command from its front-matter `name`, and its front-matter reader keeps quote characters verbatim. Because the writer always double-quoted every value, the installed entry skill declared `name: "loopx"` and Kiro exposed the command as `/"loopx"` — the surface installed cleanly and was still unusable as documented. Every skill Kiro ships itself uses a plain scalar. Quote only what YAML actually requires: a leading indicator character, an embedded `": "` or `" #"`, a trailing colon, surrounding whitespace, a bool/null-like token, or an embedded newline. Identifiers become plain, while `argument-hint: "[task text]"` (a bare `[` would parse as a flow sequence) and `description: "Run a bounded ... loop: packet-driven ..."` stay quoted so a strict reader still accepts the document. This is a shared writer, so the same correction applies to the Claude, Codex, Gemini, Cursor, ZCode, agy, OpenCode and DSH facades; managed files are refreshed in place on the next install. Three assertions and one smoke encoded the old always-quoted default and now pin the plain form plus the values that must remain quoted. Signed-off-by: vlean.wei --- examples/slash-command-install-smoke.py | 5 ++-- loopx/slash_command_files.py | 26 +++++++++++++++++-- tests/test_kiro_cli_host_surface.py | 34 +++++++++++++++++++++++++ tests/test_slash_command_install.py | 9 ++++--- 4 files changed, 67 insertions(+), 7 deletions(-) diff --git a/examples/slash-command-install-smoke.py b/examples/slash-command-install-smoke.py index 1b7d6768c7..44e3295fd4 100644 --- a/examples/slash-command-install-smoke.py +++ b/examples/slash-command-install-smoke.py @@ -112,7 +112,8 @@ def main() -> int: codex_skill = codex_home / "skills" / "loopx" / "SKILL.md" codex_skill_text = codex_skill.read_text(encoding="utf-8") - assert 'name: "loopx"' in codex_skill_text + assert "name: loopx\n" in codex_skill_text + assert 'name: "loopx"' not in codex_skill_text assert "surface=codex-skills" in codex_skill_text assert "LoopX `/loopx`" in codex_skill_text assert "start-goal --guided --project . --slash-command-arguments=" in codex_skill_text @@ -127,7 +128,7 @@ def main() -> int: claude_skill = claude_home / "skills" / "loopx-global-summary" / "SKILL.md" claude_skill_text = claude_skill.read_text(encoding="utf-8") - assert "name: \"loopx-global-summary\"" in claude_skill_text + assert "name: loopx-global-summary\n" in claude_skill_text assert "surface=claude-skills" in claude_skill_text assert "global-summary" in claude_skill_text diff --git a/loopx/slash_command_files.py b/loopx/slash_command_files.py index dde64d0bcf..a39cc1709e 100644 --- a/loopx/slash_command_files.py +++ b/loopx/slash_command_files.py @@ -19,11 +19,33 @@ def managed_marker(*, command: str, surface: str) -> str: return f"{MANAGED_MARKER_PREFIX} command={command} surface={surface} -->" +def _needs_yaml_quotes(value: str) -> bool: + """Whether a front-matter scalar must be double-quoted to stay valid YAML. + + Hosts do not agree on how forgiving their front-matter reader is. Kiro CLI + keeps the quote characters verbatim, so a quoted `name` turns the skill's + own slash command into `/"loopx"`; a strict YAML reader, on the other hand, + rejects an unquoted `[task text]` or a value containing `": "`. Quoting only + what YAML actually requires satisfies both: identifiers stay plain and + ambiguous prose stays quoted. + """ + if not value or value.strip() != value: + return True + if value[0] in "-?:,[]{}#&*!|>'\"%@`": + return True + if value.lower() in {"true", "false", "null", "yes", "no", "on", "off", "~"}: + return True + return ": " in value or " #" in value or value.endswith(":") or "\n" in value + + def front_matter(*, fields: dict[str, str]) -> str: lines = ["---"] for key, value in fields.items(): - escaped = value.replace('"', '\\"') - lines.append(f'{key}: "{escaped}"') + if _needs_yaml_quotes(value): + escaped = value.replace('"', '\\"') + lines.append(f'{key}: "{escaped}"') + else: + lines.append(f"{key}: {value}") lines.append("---") return "\n".join(lines) diff --git a/tests/test_kiro_cli_host_surface.py b/tests/test_kiro_cli_host_surface.py index 91070a2422..f732b4ee1b 100644 --- a/tests/test_kiro_cli_host_surface.py +++ b/tests/test_kiro_cli_host_surface.py @@ -13,6 +13,7 @@ from pathlib import Path import pytest +import yaml from host_surface_cli_probes import ( onboarding_setup_command_installs, selection_gate_offers_surface, @@ -120,6 +121,39 @@ def test_installed_skills_are_invocable_as_kiro_slash_commands( assert (tmp_path / "kiro-home" / "skills" / "loopx" / "SKILL.md").is_file() +def test_installed_skill_front_matter_keeps_names_unquoted(tmp_path: Path) -> None: + """Kiro derives the slash command from the front-matter `name`, and its + reader keeps quote characters verbatim: `name: "loopx"` becomes the command + `/"loopx"`. So the name must be a plain YAML scalar. Values YAML genuinely + needs quoted (a leading `[`, an embedded `": "`) must stay quoted, or a + strict reader rejects the whole front matter.""" + install_slash_commands( + execute=True, + surfaces=[HOST_SURFACE], + kiro_home=str(tmp_path / "kiro-home"), + ) + skills = sorted((tmp_path / "kiro-home" / "skills").glob("*/SKILL.md")) + assert skills, "installer wrote no skills" + for skill in skills: + text = skill.read_text(encoding="utf-8") + front_matter = text.split("---", 2)[1] + fields = yaml.safe_load(front_matter) + assert fields["name"] == skill.parent.name + assert '"' not in fields["name"] + assert f"name: {skill.parent.name}\n" in text + + # The values that must stay quoted, proven on the shipped specs rather than + # asserted in the abstract. + entry = (tmp_path / "kiro-home" / "skills" / "loopx" / "SKILL.md").read_text( + encoding="utf-8" + ) + assert 'argument-hint: "[' in entry # a bare [ would parse as a flow sequence + research = ( + tmp_path / "kiro-home" / "skills" / "loopx-deepresearch" / "SKILL.md" + ).read_text(encoding="utf-8") + assert 'description: "' in research # contains ": ", illegal unquoted + + def test_installer_preserves_user_owned_kiro_skill(tmp_path: Path) -> None: """The skills root is shared with the user's own skills; an unmarked file must never be overwritten, and a rerun over a managed file is a no-op.""" diff --git a/tests/test_slash_command_install.py b/tests/test_slash_command_install.py index f9ddf918d0..dc41179cfc 100644 --- a/tests/test_slash_command_install.py +++ b/tests/test_slash_command_install.py @@ -44,7 +44,10 @@ def test_host_materialization_installs_generated_loopx_entry_skill( "path": str(skill), "status": "created", } - assert 'name: "loopx"' in skill_text + # A plain scalar, not `name: "loopx"`: hosts such as Kiro CLI keep the quote + # characters verbatim and would expose the skill as `/"loopx"`. + assert "name: loopx\n" in skill_text + assert 'name: "loopx"' not in skill_text assert "ark-managed-agent" in skill_text assert "--slash-command-arguments" in skill_text assert "The CLI, not the model, owns parsing" in skill_text @@ -683,7 +686,7 @@ def test_gemini_surface_writes_skill_files_gemini_cli_can_discover(tmp_path: Pat assert skill.exists() body = skill.read_text(encoding="utf-8") assert body.startswith("---") - assert 'name: "loopx"' in body + assert "name: loopx\n" in body row = _row(payload, "gemini_cli_skills") assert row["surface"] == "gemini" @@ -716,7 +719,7 @@ def test_cursor_surface_installs_skills(tmp_path: Path) -> None: ) skill = cursor_home / "skills" / "loopx" / "SKILL.md" assert skill.exists() - assert 'name: "loopx"' in skill.read_text(encoding="utf-8") + assert "name: loopx\n" in skill.read_text(encoding="utf-8") assert _row(payload, "cursor_skills")["host_surfaces"] == ["cursor-agent"] From d0a8e5d2ae965c2687a8072d9bd5f2a09f21bdee Mon Sep 17 00:00:00 2001 From: "vlean.wei" Date: Mon, 7 Sep 2026 13:12:13 +0800 Subject: [PATCH 05/23] fix(kiro-cli): pin the /goal surface to the probed binary The adapter claimed it was verified against `kiro-cli 1.0.437 (TUI shell 2.21.1)`. That version string is absent from the shipped binaries and from the app bundle: `kiro-cli` and `kiro-cli-chat` both report `2.21.1`, and the bundle is `2.21.1` / `20260904.123104`. A version a reader cannot reproduce is worse than no version, because the surrounding host facts inherit its credibility. Re-probe and record what the binary actually carries. Its own hint is `/goal [description --validate criteria --agent name --max N] | clear`, so the documented primitive was also understated on three counts: - `--validate ` is what the host judges each iteration against, and its per-iteration result carries `passed` plus `feedback`. Binding a goal without it leaves the host checking nothing LoopX will accept as writeback, so the activation now passes the validation the todo already names. - `/goal status` reads the active loop back, which is what an agent needs instead of inferring loop state from prose. - `--agent ` selects the agent config that runs the goal. LoopX does not set it: the skill facade must stay reachable from whichever agent the user chose, and that is now stated rather than left implicit. The packet gains `native_goal_status_command` and `native_goal_validate_flag`; the fact constants stay the single source the packet, README and PR narrative cite. The README's version claim is replaced by the reproducible `strings` probe that produced it. Assertions pin the new flags in the facts, the packet mutation, and the rendered activation steps. Signed-off-by: vlean.wei --- loopx/kiro_cli_goal_mode/README.md | 46 +++++++++++++++++++--------- loopx/kiro_cli_goal_mode/__init__.py | 44 +++++++++++++++++--------- tests/test_kiro_cli_host_surface.py | 17 ++++++++++ 3 files changed, 79 insertions(+), 28 deletions(-) diff --git a/loopx/kiro_cli_goal_mode/README.md b/loopx/kiro_cli_goal_mode/README.md index 739e05f770..71d65b8d7b 100644 --- a/loopx/kiro_cli_goal_mode/README.md +++ b/loopx/kiro_cli_goal_mode/README.md @@ -8,24 +8,39 @@ to the host's own loop instead of pretending the agent merely drives itself. ## Native goal primitive -`/goal [--max N]` — built-in command. The host re-dispatches -turns toward the stated objective, and the model must prove completion through -the built-in `goal` tool before the loop ends. +`/goal [description --validate criteria --agent name --max N] | clear` — the +built-in command, exactly as the host's own hint states it. The host +re-dispatches turns toward the stated objective, judges each iteration against +the validation criteria, and the model must prove completion through the +built-in `goal` tool before the loop ends. - Iteration budget is host-enforced: default `5`, ceiling `50`. This is the one part of the loop LoopX does not have to trust the model for. -- `/goal clear` cancels the active goal. The loop also stops in `Exhausted` - (budget spent without completion) and pauses after 3 consecutive dispatch - failures. +- `--validate ` states what the host checks each iteration; its + per-iteration result carries `passed` plus `feedback`, so LoopX passes the + validation it already owns instead of leaving the criteria implicit. +- `--agent ` picks which agent config runs the goal. LoopX does not set + it: the LoopX skill facade must stay reachable from whichever agent the user + chose. +- `/goal clear` cancels the active goal and `/goal status` reads the current + one back. The loop also stops in `Exhausted` (budget spent without + completion) and pauses after 3 consecutive dispatch failures. - The `goal` tool's `complete` command enforces a completion contract: each success criterion needs cited tool output, and belief or narrative confidence is explicitly not evidence — the same standard LoopX writeback wants. -Verified against `kiro-cli 1.0.437` (TUI shell `2.21.1`): `/goal` is present -in the binary's slash-command registry, and the host's own `/goal` and `goal` -tool references document the iteration budget, terminal states, and completion -contract. +Probed on `kiro-cli-chat 2.21.1` (app bundle `20260904.123104`; `kiro-cli` and +`kiro-cli-chat` both report `2.21.1`). The command hint, `--validate`/`--agent`/ +`--max` flags, the iteration-ceiling rejection message, the `Completed` and +`Exhausted` terminal states, the 3-failure pause, and the per-iteration +`passed`/`feedback` result all come from the shipped binary rather than from +host marketing copy. Re-probe with: + +```bash +strings -a "$(readlink -f "$(command -v kiro-cli-chat)")" \ + | grep -ao "/goal \[[^]]*\]" +``` ## Native hook seam @@ -83,10 +98,13 @@ loopx start-goal --guided --project . --slash-command-arguments="" --host- After todo writeback, bind the generated heartbeat task body with `/goal --max ` — with `N` taken from the remaining quota slots -and never above the host ceiling of 50 — start every turn and native goal -iteration with `quota should-run` (advisory guidance; LoopX does not intercept -native host iterations), and settle through the built-in `goal` tool only after -LoopX writeback so the cited evidence matches what LoopX recorded. +and never above the host ceiling of 50 — pass the validation the todo already +names as `--validate ` so the host judges each iteration against the +check LoopX will accept, read the loop back with `/goal status`, start every +turn and native goal iteration with `quota should-run` (advisory guidance; +LoopX does not intercept native host iterations), and settle through the +built-in `goal` tool only after LoopX writeback so the cited evidence matches +what LoopX recorded. Kiro CLI exports `KIRO_SESSION_ID` for every session; it is the stable value a LoopX thread binding should key on instead of prose. diff --git a/loopx/kiro_cli_goal_mode/__init__.py b/loopx/kiro_cli_goal_mode/__init__.py index e2edbc7c83..1dd3874fd3 100644 --- a/loopx/kiro_cli_goal_mode/__init__.py +++ b/loopx/kiro_cli_goal_mode/__init__.py @@ -18,14 +18,20 @@ "kiro tui", ) -# Native goal primitive built into the kiro-cli binary (probed live on -# kiro-cli 1.0.437 / TUI shell 2.21.1: `/goal` is present in the binary's -# slash-command registry and documented by the host's own `/goal` reference). +# Native goal primitive built into the kiro-cli binary. Probed on +# `kiro-cli-chat 2.21.1` (app bundle 20260904.123104; both `kiro-cli` and +# `kiro-cli-chat` report 2.21.1): the binary carries the hint +# `/goal [description --validate criteria --agent name --max N] | clear`, the +# iteration-ceiling rejection message, the `Completed`/`Exhausted` terminal +# states and the per-iteration `passed`/`feedback` result. # The host owns the iteration loop: it re-dispatches the turn until the model # proves completion through the `goal` tool or the iteration budget runs out. KIRO_CLI_GOAL_COMMAND = "/goal" KIRO_CLI_GOAL_CLEAR_COMMAND = "/goal clear" +KIRO_CLI_GOAL_STATUS_COMMAND = "/goal status" KIRO_CLI_GOAL_MAX_FLAG = "--max" +KIRO_CLI_GOAL_VALIDATE_FLAG = "--validate" +KIRO_CLI_GOAL_AGENT_FLAG = "--agent" KIRO_CLI_GOAL_DEFAULT_MAX_ITERATIONS = 5 KIRO_CLI_GOAL_MAX_ITERATION_CEILING = 50 KIRO_CLI_GOAL_COMPLETION_TOOL = "goal" @@ -49,14 +55,16 @@ KIRO_CLI_HOOK_CONFIG_LABEL = "~/.kiro/agents/.json (or .kiro/agents/.json)" KIRO_CLI_NATIVE_GOAL_FACTS = ( - "native `/goal [--max N]` command: the host re-dispatches " - "turns toward one objective until completion is proven or the iteration " - "budget is spent (default 5, ceiling 50)", + "native `/goal [description --validate criteria --agent name --max N] | " + "clear` command: the host re-dispatches turns toward one objective, judges " + "each iteration against the validation criteria, and stops when completion " + "is proven or the iteration budget is spent (default 5, ceiling 50)", "the built-in `goal` tool's `complete` command enforces a completion " "contract: every success criterion needs cited tool output, not narrative " "confidence", - "`/goal clear` cancels the active goal; the loop also stops on Exhausted " - "and pauses after 3 consecutive dispatch failures", + "`/goal clear` cancels the active goal and `/goal status` reads it back; " + "the loop also stops on Exhausted and pauses after 3 consecutive dispatch " + "failures", "`hooks` in the agent config expose agentSpawn/userPromptSubmit/" "preToolUse/postToolUse/stop, and preToolUse can block a tool call with " "exit code 2", @@ -79,12 +87,13 @@ def kiro_cli_activation_extras() -> dict[str, Any]: Keeps the Kiro CLI host facts (goal command, iteration budget, completion tool, gate text, activation steps) in this package instead of growing ``host_loop_activation.py`` past its module metric budget. Kiro CLI ships - both halves of a goal-mode host: a native goal primitive — ``/goal - [--max N]`` whose host-side loop re-dispatches turns until the model - proves completion through the ``goal`` tool — and a bounded iteration - budget the host itself enforces (default 5, ceiling 50). What it does not - ship is a cross-session daemon, and LoopX installs no hook, so quota - pacing is instructed rather than enforced. + both halves of a goal-mode host: a native goal primitive — ``/goal + [description --validate criteria --agent name --max N] | clear`` whose + host-side loop re-dispatches turns until the ``goal`` tool proves + completion — and a bounded iteration budget the host itself enforces + (default 5, ceiling 50). What it does not ship is a cross-session daemon, + and LoopX installs no hook, so quota pacing is instructed rather than + enforced. """ return { "activation_method": "bind_native_goal_with_advisory_quota_entry", @@ -94,7 +103,9 @@ def kiro_cli_activation_extras() -> dict[str, Any]: "quota_gate_enforcement": "advisory_only", "native_goal_command": KIRO_CLI_GOAL_COMMAND, "native_goal_cancel_command": KIRO_CLI_GOAL_CLEAR_COMMAND, + "native_goal_status_command": KIRO_CLI_GOAL_STATUS_COMMAND, "native_goal_max_flag": KIRO_CLI_GOAL_MAX_FLAG, + "native_goal_validate_flag": KIRO_CLI_GOAL_VALIDATE_FLAG, "native_goal_default_max_iterations": ( KIRO_CLI_GOAL_DEFAULT_MAX_ITERATIONS ), @@ -124,6 +135,11 @@ def kiro_cli_activation_extras() -> dict[str, Any]: f"{KIRO_CLI_GOAL_MAX_ITERATION_CEILING} " f"(host default is {KIRO_CLI_GOAL_DEFAULT_MAX_ITERATIONS}); " f"`{KIRO_CLI_GOAL_CLEAR_COMMAND}` cancels it.", + "Pass the validation the LoopX todo already names as " + f"`{KIRO_CLI_GOAL_VALIDATE_FLAG} ` so the host judges " + "each iteration against the same check LoopX will accept as " + f"writeback, and read the loop back with " + f"`{KIRO_CLI_GOAL_STATUS_COMMAND}` instead of guessing its state.", "Start every turn and native goal iteration with `quota " "should-run` and honor a stop/throttle decision before any " "delivery work — instructed pacing, not a host-enforced gate.", diff --git a/tests/test_kiro_cli_host_surface.py b/tests/test_kiro_cli_host_surface.py index f732b4ee1b..3f8d8e983d 100644 --- a/tests/test_kiro_cli_host_surface.py +++ b/tests/test_kiro_cli_host_surface.py @@ -29,11 +29,14 @@ scheduler_command_binding_for_agent_type, ) from loopx.kiro_cli_goal_mode import ( + KIRO_CLI_GOAL_AGENT_FLAG, KIRO_CLI_GOAL_CLEAR_COMMAND, KIRO_CLI_GOAL_COMMAND, KIRO_CLI_GOAL_COMPLETION_TOOL, KIRO_CLI_GOAL_DEFAULT_MAX_ITERATIONS, KIRO_CLI_GOAL_MAX_ITERATION_CEILING, + KIRO_CLI_GOAL_STATUS_COMMAND, + KIRO_CLI_GOAL_VALIDATE_FLAG, KIRO_CLI_HOOK_TRIGGERS, KIRO_CLI_NATIVE_GOAL_FACTS, KIRO_CLI_SESSION_ID_ENV, @@ -248,6 +251,8 @@ def test_activation_binds_native_goal_with_advisory_quota_entry() -> None: assert mutation["quota_gate_enforcement"] == "advisory_only" assert mutation["native_goal_command"] == KIRO_CLI_GOAL_COMMAND assert mutation["native_goal_cancel_command"] == KIRO_CLI_GOAL_CLEAR_COMMAND + assert mutation["native_goal_status_command"] == KIRO_CLI_GOAL_STATUS_COMMAND + assert mutation["native_goal_validate_flag"] == KIRO_CLI_GOAL_VALIDATE_FLAG assert ( mutation["native_goal_max_iteration_ceiling"] == KIRO_CLI_GOAL_MAX_ITERATION_CEILING @@ -276,6 +281,10 @@ def test_activation_binds_native_goal_with_advisory_quota_entry() -> None: assert "quota should-run" in steps assert KIRO_CLI_GOAL_COMPLETION_TOOL in steps assert "no host scheduler to fall back on" not in steps + # The host judges each iteration against --validate criteria; binding the + # goal without them leaves the host checking nothing LoopX will accept. + assert KIRO_CLI_GOAL_VALIDATE_FLAG in steps + assert KIRO_CLI_GOAL_STATUS_COMMAND in steps assert packet["setup_command"] == _surface_install_command( HOST_SURFACE, "loopx", "." @@ -306,6 +315,9 @@ def test_native_goal_facts_match_the_probed_host() -> None: actually documents and what the probed binary exposes.""" assert KIRO_CLI_GOAL_COMMAND == "/goal" assert KIRO_CLI_GOAL_CLEAR_COMMAND == "/goal clear" + assert KIRO_CLI_GOAL_STATUS_COMMAND == "/goal status" + assert KIRO_CLI_GOAL_VALIDATE_FLAG == "--validate" + assert KIRO_CLI_GOAL_AGENT_FLAG == "--agent" assert KIRO_CLI_GOAL_DEFAULT_MAX_ITERATIONS == 5 assert KIRO_CLI_GOAL_MAX_ITERATION_CEILING == 50 assert KIRO_CLI_GOAL_COMPLETION_TOOL == "goal" @@ -322,3 +334,8 @@ def test_native_goal_facts_match_the_probed_host() -> None: assert "ceiling 50" in facts assert "completion contract" in facts assert "exit code 2" in facts + # The host's own hint names --validate and --agent; an adapter that only + # documents --max understates the primitive it binds. + assert KIRO_CLI_GOAL_VALIDATE_FLAG in facts + assert KIRO_CLI_GOAL_AGENT_FLAG in facts + assert KIRO_CLI_GOAL_STATUS_COMMAND in facts From 81fa8b5d3a6a1e1badebd0b88f9861c7aa26167c Mon Sep 17 00:00:00 2001 From: "vlean.wei" Date: Mon, 7 Sep 2026 13:12:42 +0800 Subject: [PATCH 06/23] feat(kiro-cli): serve Kiro CLI as a built-in Chat Agent `loopx dashboard` renders its Agent picker from `/api/chat/capabilities`, so a host is only reachable there if the running process advertises it as a capability row backed by an adapter the runtime can start. Kiro CLI had a goal surface and no row, so the dashboard could not reach it at all. Kiro CLI ships an ACP agent: `kiro-cli acp` answers `initialize` with protocolVersion 1 and `loadSession: true`, and `session/new` returns a session id. That is exactly what `chat_acp.ACPStdioAdapter` already speaks, so this adds a built-in row and one dispatch branch rather than a second transport or a new adapter class. Resume works through `session/load`, which the host reports. The row is built-in rather than something the owner hand-registers, because LoopX already owns this host's facts; `available` stays a live PATH probe so an uninstalled host renders as needing configuration instead of failing when a session opens. `--kiro-cli-bin` threads through `loopx chat` and `loopx dashboard` for a host that is not on PATH under the documented name. Two boundaries stay explicit: - The launch argv carries no `--trust-all-tools`. LoopX Chat answers every ACP `session/request_permission` with `cancelled` and exposes no client host tools, so a Kiro tool call that needs approval is refused rather than auto-approved. Adding the flag would move that decision out of the owner's hands, so the reason lives next to the argv. - A Chat session is one bounded conversation, not the governed `/goal` loop. The two surfaces share the host, not the loop, and both READMEs say so. `kiro-cli` joins `RESERVED_AGENT_IDS`, or an owner-local endpoint could claim the id and silently shadow the built-in adapter. The dashboard's agent label/capability helpers gain a Kiro branch, following the existing substring shape; `display_name` already arrives from the server, so the picker label needs no client-side mapping. Validation covers the built-in route end to end offline by pointing `kiro_cli_bin` at the existing fake ACP fixture: capability row shape, session open, one turn, the reserved-id rejection, and the unavailable-host row. Two focused tests pin the same contract in the host-surface suite. Signed-off-by: vlean.wei --- apps/presentation/dashboard/README.md | 25 ++++++ .../dashboard/src/views/dashboard-page.tsx | 6 ++ examples/loopx-chat-acp-adapter-smoke.py | 77 +++++++++++++++++++ loopx/chat_endpoints.py | 12 ++- loopx/chat_runtime.py | 37 +++++++++ loopx/chat_server.py | 3 + loopx/cli_commands/support_control.py | 19 +++++ loopx/dashboard_launcher.py | 3 + loopx/kiro_cli_goal_mode/README.md | 34 +++++++- loopx/kiro_cli_goal_mode/__init__.py | 28 +++++++ tests/test_kiro_cli_host_surface.py | 72 +++++++++++++++++ 11 files changed, 313 insertions(+), 3 deletions(-) diff --git a/apps/presentation/dashboard/README.md b/apps/presentation/dashboard/README.md index 0072f07e04..8679884df5 100644 --- a/apps/presentation/dashboard/README.md +++ b/apps/presentation/dashboard/README.md @@ -105,6 +105,31 @@ URL and opens the browser/PWA route, then exits without starting a second server. The desktop shell reuses the same services in the opposite order, so the browser/PWA and native entry points can be started in either order. +### Built-In Chat Agents + +The Agent picker is served by `/api/chat/capabilities`, so its rows come from +the running LoopX process rather than from browser state. The built-ins are +Codex (app-server), Claude Code, Kiro CLI, and the direct Claude/OpenAI API +lanes; owner-registered ACP endpoints are appended after them. A row's +`available` flag is a live probe, so an uninstalled host renders as needing +configuration instead of failing when a session opens. + +Kiro CLI is reached through its own ACP agent (`kiro-cli acp`) using the same +ACP stdio adapter as owner-registered endpoints. Override the executable when +it is not on `PATH` under the documented name: + +```bash +loopx dashboard --kiro-cli-bin /path/to/kiro-cli +``` + +The trust boundary is unchanged: LoopX Chat answers every ACP +`session/request_permission` with `cancelled` and exposes no client host tools, +so a Kiro tool call that needs approval is refused rather than auto-approved. +LoopX passes no `--trust-all-tools`. Reaching the host this way drives one +read-only Chat session; it is not the governed `/goal` loop, which is entered +from a Kiro CLI session through the +[Kiro CLI goal-mode adapter](../../../loopx/kiro_cli_goal_mode/README.md). + Source-checkout development is a separate mode: ```bash diff --git a/apps/presentation/dashboard/src/views/dashboard-page.tsx b/apps/presentation/dashboard/src/views/dashboard-page.tsx index 2fd8824028..9404ef25b0 100644 --- a/apps/presentation/dashboard/src/views/dashboard-page.tsx +++ b/apps/presentation/dashboard/src/views/dashboard-page.tsx @@ -626,6 +626,9 @@ function personalAgentLabel(agentId: string) { if (normalized.includes("claude")) { return "Claude Code"; } + if (normalized.includes("kiro")) { + return "Kiro CLI"; + } if (normalized.includes("trae")) { return "Trae CLI Agent"; } @@ -646,6 +649,9 @@ function personalAgentCapability(agentId: string) { if (normalized.includes("openai") || normalized.includes("anthropic")) { return "管家问答 · 无工具"; } + if (normalized.includes("kiro")) { + return "终端编码 · 原生 /goal 循环"; + } if (normalized.includes("trae")) { return "前端与交互实现"; } diff --git a/examples/loopx-chat-acp-adapter-smoke.py b/examples/loopx-chat-acp-adapter-smoke.py index 9a38f7d079..569b4a5335 100644 --- a/examples/loopx-chat-acp-adapter-smoke.py +++ b/examples/loopx-chat-acp-adapter-smoke.py @@ -18,6 +18,7 @@ from loopx.chat_endpoints import AgentEndpointRegistry # noqa: E402 from loopx.chat_runtime import ChatRuntimeController # noqa: E402 from loopx.chat_store import ChatSessionStore # noqa: E402 +from loopx.kiro_cli_goal_mode import KIRO_CLI_CHAT_AGENT_ID # noqa: E402 FAKE_ACP = r'''#!/usr/bin/env python3 @@ -239,6 +240,82 @@ def main() -> None: assert restored["session_id"] == session["session_id"] second.close() + # Kiro CLI is a built-in ACP agent, not an owner-registered endpoint: + # the capability row must advertise it and `open_session` must reach the + # same ACP adapter. Pointing kiro_cli_bin at the fixture keeps this + # offline while still proving the built-in route, because a row that + # renders in the dashboard but dead-ends at session open is decorative. + kiro_store = ChatSessionStore(root / "kiro-runtime") + kiro = ChatRuntimeController( + store=kiro_store, + codex_bin="missing-codex-for-fixture", + kiro_cli_bin=str(fake), + ) + row = next( + item + for item in kiro.capabilities() + if item["agent_id"] == KIRO_CLI_CHAT_AGENT_ID + ) + assert row["source"] == "builtin", row + assert row["adapter_kind"] == "acp", row + assert row["display_name"] == "Kiro CLI", row + assert row["available"] is True, row + assert row["trust_scope"] == "read_only", row + kiro_session, kiro_resumed = kiro.open_session( + goal_id="fixture-goal", + agent_id=KIRO_CLI_CHAT_AGENT_ID, + work_dir=root, + objective="Exercise the built-in Kiro CLI ACP route.", + mode="resume_latest", + ) + assert kiro_resumed is False + assert kiro_session["upstream_thread_id"] == "acp:fixture/session" + kiro_turn, kiro_created = kiro.submit_turn( + session_id=str(kiro_session["session_id"]), + client_turn_id="kiro-turn", + message="检查状态", + work_dir=root, + objective="Exercise the built-in Kiro CLI ACP route.", + ) + assert kiro_created is True + kiro_completed = kiro.wait_for_turn( + session_id=str(kiro_session["session_id"]), + turn_id=str(kiro_turn["turn_id"]), + timeout_sec=3, + ) + assert kiro_completed["status"] == "completed", kiro_completed + kiro.close() + + # A built-in id must not be claimable by an owner-local endpoint, or the + # registry row would silently shadow the built-in adapter. + try: + endpoint_registry.upsert( + { + "agent_id": KIRO_CLI_CHAT_AGENT_ID, + "display_name": "Shadow Kiro", + "command": [str(fake)], + } + ) + except ValueError as exc: + assert "reserved" in str(exc), exc + else: # pragma: no cover - guarded by the assertion above + raise AssertionError("a reserved built-in agent id was accepted") + + # An uninstalled host renders as needing configuration instead of + # failing at session open. + unavailable = ChatRuntimeController( + store=ChatSessionStore(root / "kiro-missing"), + codex_bin="missing-codex-for-fixture", + kiro_cli_bin="loopx-missing-kiro-cli-for-fixture", + ) + missing_row = next( + item + for item in unavailable.capabilities() + if item["agent_id"] == KIRO_CLI_CHAT_AGENT_ID + ) + assert missing_row["available"] is False, missing_row + unavailable.close() + print("loopx-chat-acp-adapter-smoke: ok") diff --git a/loopx/chat_endpoints.py b/loopx/chat_endpoints.py index c41ec26a56..cf313c5943 100644 --- a/loopx/chat_endpoints.py +++ b/loopx/chat_endpoints.py @@ -13,11 +13,21 @@ from .chat_store import utc_now from .file_lock import exclusive_file_lock +from .kiro_cli_goal_mode import KIRO_CLI_CHAT_AGENT_ID CHAT_ENDPOINT_REGISTRY_SCHEMA_VERSION = "loopx_chat_endpoint_registry_v1" CHAT_ENDPOINT_SCHEMA_VERSION = "loopx_chat_endpoint_v1" -RESERVED_AGENT_IDS = {"codex", "claude-code", "anthropic-api", "openai-api"} +# Built-in agent ids. An owner-local endpoint may not claim one, or the +# registry row would silently shadow the built-in adapter the capability list +# already advertises. +RESERVED_AGENT_IDS = { + "codex", + "claude-code", + "anthropic-api", + "openai-api", + KIRO_CLI_CHAT_AGENT_ID, +} SUPPORTED_TRANSPORTS = {"stdio"} SUPPORTED_LOCATIONS = {"local", "remote"} SUPPORTED_TRUST_SCOPES = {"read_only"} diff --git a/loopx/chat_runtime.py b/loopx/chat_runtime.py index 5084097367..6149c26241 100644 --- a/loopx/chat_runtime.py +++ b/loopx/chat_runtime.py @@ -13,6 +13,13 @@ from .chat_acp import ACPStdioAdapter from .chat_agent import CodexChatAgentError, CodexChatAgentSession, CodexChatTimeoutError from .chat_endpoints import AgentEndpointRegistry +from .kiro_cli_goal_mode import ( + KIRO_CLI_BIN, + KIRO_CLI_CHAT_ADAPTER_KIND, + KIRO_CLI_CHAT_AGENT_ID, + KIRO_CLI_CHAT_DISPLAY_NAME, + kiro_cli_chat_command, +) from .chat_store import ( CHAT_SESSION_MODE_ATTACHED, TERMINAL_TURN_STATES, @@ -207,6 +214,7 @@ def __init__( store: ChatSessionStore, codex_bin: str, claude_bin: str = "claude", + kiro_cli_bin: str = KIRO_CLI_BIN, startup_timeout_sec: float = 30.0, idle_timeout_sec: float = 180.0, hard_timeout_sec: float = 900.0, @@ -215,6 +223,7 @@ def __init__( self.store = store self.codex_bin = codex_bin self.claude_bin = claude_bin + self.kiro_cli_bin = kiro_cli_bin self.startup_timeout_sec = startup_timeout_sec self.idle_timeout_sec = idle_timeout_sec self.hard_timeout_sec = hard_timeout_sec @@ -256,6 +265,25 @@ def capabilities(self) -> list[dict[str, Any]]: "trust_scope": "read_only", "source": "builtin", }, + { + # Kiro CLI ships an ACP stdio agent (`kiro-cli acp`), so it is + # reachable through the existing ACP adapter without a new + # transport. It is a built-in row rather than something the + # owner must hand-register, because LoopX already owns the + # host's facts; `available` stays a live PATH probe so an + # uninstalled host renders as needing configuration instead of + # failing at session open. + "agent_id": KIRO_CLI_CHAT_AGENT_ID, + "display_name": KIRO_CLI_CHAT_DISPLAY_NAME, + "adapter_kind": KIRO_CLI_CHAT_ADAPTER_KIND, + "available": bool(shutil.which(self.kiro_cli_bin)), + "streaming": True, + "resume": True, + "interrupt": True, + "tool_calls": True, + "trust_scope": "read_only", + "source": "builtin", + }, { "agent_id": "anthropic-api", "display_name": "Claude API", @@ -338,6 +366,15 @@ def _start_adapter( session_id=resume_thread_id, history=history, ) + if agent_id == KIRO_CLI_CHAT_AGENT_ID: + return ACPStdioAdapter.start( + command=kiro_cli_chat_command(self.kiro_cli_bin), + work_dir=work_dir, + resume_thread_id=resume_thread_id, + startup_timeout_sec=self.startup_timeout_sec, + idle_timeout_sec=self.idle_timeout_sec, + hard_timeout_sec=self.hard_timeout_sec, + ) endpoint = self.endpoint_registry.get(agent_id) if endpoint is not None: return ACPStdioAdapter.start( diff --git a/loopx/chat_server.py b/loopx/chat_server.py index c30e485ebf..a2e2a53c8a 100644 --- a/loopx/chat_server.py +++ b/loopx/chat_server.py @@ -67,6 +67,7 @@ ) from .history import load_registry from .chat_completed_todos import CompletedTodoPages, CompletedTodoRequestMixin +from .kiro_cli_goal_mode import KIRO_CLI_BIN from .paths import resolve_runtime_root from .release_manifest import release_runtime_identity from .registry import registry_goals, resolve_state_file @@ -1412,6 +1413,7 @@ def serve_chat( goal_id: str | None = None, codex_bin: str = "codex", claude_bin: str = "claude", + kiro_cli_bin: str = KIRO_CLI_BIN, lark_cli_bin: str | None = None, startup_timeout_sec: float = 30.0, idle_timeout_sec: float = 180.0, @@ -1471,6 +1473,7 @@ def serve_chat( store=server.chat_store, codex_bin=codex_bin, claude_bin=claude_bin, + kiro_cli_bin=kiro_cli_bin, startup_timeout_sec=startup_timeout_sec, idle_timeout_sec=idle_timeout_sec, hard_timeout_sec=hard_timeout_sec, diff --git a/loopx/cli_commands/support_control.py b/loopx/cli_commands/support_control.py index 8be35a54e6..9eac156399 100644 --- a/loopx/cli_commands/support_control.py +++ b/loopx/cli_commands/support_control.py @@ -28,6 +28,7 @@ build_heartbeat_prompt_error_payload, render_heartbeat_prompt_markdown, ) +from ..kiro_cli_goal_mode import KIRO_CLI_BIN from ..paths import default_public_scan_root from ..presentation.renderers.status_markdown import render_status_markdown from ..promotion_gate import ( @@ -331,6 +332,14 @@ def register_support_control_commands( default="claude", help="Claude Code CLI executable used for read-only Agent sessions.", ) + chat_parser.add_argument( + "--kiro-cli-bin", + default=KIRO_CLI_BIN, + help=( + "Kiro CLI executable used for read-only ACP Agent sessions " + "(` acp`)." + ), + ) chat_parser.add_argument( "--lark-cli-bin", help=( @@ -422,6 +431,14 @@ def register_support_control_commands( default="claude", help="Claude Code CLI executable used for read-only Agent sessions.", ) + dashboard_parser.add_argument( + "--kiro-cli-bin", + default=KIRO_CLI_BIN, + help=( + "Kiro CLI executable used for read-only ACP Agent sessions " + "(` acp`)." + ), + ) dashboard_parser.add_argument( "--lark-cli-bin", help=( @@ -912,6 +929,7 @@ def handle_support_control_command( goal_id=getattr(args, "goal_id", None), codex_bin=getattr(args, "codex_bin", "codex"), claude_bin=getattr(args, "claude_bin", "claude"), + kiro_cli_bin=getattr(args, "kiro_cli_bin", KIRO_CLI_BIN), lark_cli_bin=getattr(args, "lark_cli_bin", None), assets_dir=Path(args.assets_dir).expanduser().resolve() if getattr(args, "assets_dir", None) @@ -954,6 +972,7 @@ def handle_support_control_command( goal_id=args.goal_id, codex_bin=args.codex_bin, claude_bin=args.claude_bin, + kiro_cli_bin=getattr(args, "kiro_cli_bin", KIRO_CLI_BIN), lark_cli_bin=args.lark_cli_bin, startup_timeout_sec=max(0.1, float(args.startup_timeout_seconds)), idle_timeout_sec=max(0.1, float(args.idle_timeout_seconds)), diff --git a/loopx/dashboard_launcher.py b/loopx/dashboard_launcher.py index 8def28979d..860f6a3cb7 100644 --- a/loopx/dashboard_launcher.py +++ b/loopx/dashboard_launcher.py @@ -12,6 +12,7 @@ from urllib.parse import quote import webbrowser +from .kiro_cli_goal_mode import KIRO_CLI_BIN from .release_manifest import release_runtime_identity @@ -209,6 +210,7 @@ def launch_dashboard( goal_id: str | None = None, codex_bin: str = "codex", claude_bin: str = "claude", + kiro_cli_bin: str = KIRO_CLI_BIN, lark_cli_bin: str | None = None, assets_dir: Path | None = None, verbose: bool = False, @@ -279,6 +281,7 @@ def launch_dashboard( goal_id=goal_id, codex_bin=codex_bin, claude_bin=claude_bin, + kiro_cli_bin=kiro_cli_bin, lark_cli_bin=lark_cli_bin, assets_dir=resolved_assets, verbose=verbose, diff --git a/loopx/kiro_cli_goal_mode/README.md b/loopx/kiro_cli_goal_mode/README.md index 71d65b8d7b..7d91c147bd 100644 --- a/loopx/kiro_cli_goal_mode/README.md +++ b/loopx/kiro_cli_goal_mode/README.md @@ -109,8 +109,38 @@ what LoopX recorded. Kiro CLI exports `KIRO_SESSION_ID` for every session; it is the stable value a LoopX thread binding should key on instead of prose. +## Dashboard and Chat agent + +Kiro CLI also ships an ACP agent (`kiro-cli acp`), so `loopx dashboard` and +`loopx chat` list **Kiro CLI** as a built-in Agent alongside Codex and Claude +Code. It reuses `loopx.chat_acp.ACPStdioAdapter` rather than a second +transport: probed on 2.21.1, the host answers `initialize` with +`protocolVersion: 1` and `loadSession: true`, and `session/new` returns a +session id, which is exactly what that adapter expects. + +```bash +loopx dashboard # Kiro CLI appears when it is on PATH +loopx dashboard --kiro-cli-bin /path/to/kiro-cli # explicit executable +``` + +Two boundaries this does **not** cross: + +- **Read-only by refusal.** LoopX Chat answers every ACP + `session/request_permission` with `cancelled` and exposes no client host + tools, so a Kiro tool call that needs approval is refused rather than + auto-approved. The launch argv carries no `--trust-all-tools`; adding it + would move that decision out of the owner's hands. +- **Not the governed loop.** A dashboard Chat session is one bounded + conversation. The `/goal` loop above is entered from a Kiro CLI session + through the installed skill facade; the two surfaces share the host, not the + loop. + +The built-in id `kiro-cli` is reserved in the owner-local endpoint registry so +a hand-registered endpoint cannot silently shadow it. + ## Layout - `__init__.py` — host facts: install surface id, fixed skills root resolution, - the agent-type catalog entry, and the activation extras (native goal command, - host iteration budget, completion tool, advisory quota boundary). + the agent-type catalog entry, the activation extras (native goal command, + host iteration budget, completion tool, advisory quota boundary), and the + Chat/ACP launch facts the dashboard's built-in Agent row is built from. diff --git a/loopx/kiro_cli_goal_mode/__init__.py b/loopx/kiro_cli_goal_mode/__init__.py index 1dd3874fd3..4761c9a29e 100644 --- a/loopx/kiro_cli_goal_mode/__init__.py +++ b/loopx/kiro_cli_goal_mode/__init__.py @@ -8,6 +8,7 @@ DEFAULT_KIRO_CLI_HOME = ".kiro" SKILLS_SUBDIR = "skills" SKILLS_ROOT_LABEL = "~/.kiro/skills" +KIRO_CLI_BIN = "kiro-cli" KIRO_CLI_ACCEPTED_INPUTS = ( "kiro-cli", "kiro_cli", @@ -18,6 +19,21 @@ "kiro tui", ) +# `kiro-cli acp` starts the host as an Agent Client Protocol agent over stdio. +# Probed on 2.21.1: it answers `initialize` with protocolVersion 1 and +# `loadSession: true`, and `session/new` returns a session id — exactly the +# shape `loopx.chat_acp.ACPStdioAdapter` already speaks, so LoopX Chat and the +# dashboard reach Kiro CLI through that adapter instead of a second transport. +# +# The argv carries no `--trust-all-tools`: LoopX Chat answers every ACP +# `session/request_permission` with `cancelled`, so a tool that needs approval +# is refused rather than auto-approved. Passing the trust flag here would move +# that decision out of the owner's hands. +KIRO_CLI_CHAT_AGENT_ID = "kiro-cli" +KIRO_CLI_CHAT_DISPLAY_NAME = "Kiro CLI" +KIRO_CLI_CHAT_ACP_SUBCOMMAND = "acp" +KIRO_CLI_CHAT_ADAPTER_KIND = "acp" + # Native goal primitive built into the kiro-cli binary. Probed on # `kiro-cli-chat 2.21.1` (app bundle 20260904.123104; both `kiro-cli` and # `kiro-cli-chat` report 2.21.1): the binary carries the hint @@ -160,6 +176,18 @@ def kiro_cli_activation_extras() -> dict[str, Any]: } +def kiro_cli_chat_command(bin_name: str | None = None) -> tuple[str, ...]: + """Argv that starts Kiro CLI as an ACP stdio agent for LoopX Chat. + + ``bin_name`` is an injection point for tests and for an owner whose host + binary is not on ``PATH`` under the documented name; the default is the + documented executable. No trust flag is added: LoopX Chat cancels every ACP + permission request, and auto-approving tools from a dashboard-launched + session is the owner's decision, not this adapter's. + """ + return (bin_name or KIRO_CLI_BIN, KIRO_CLI_CHAT_ACP_SUBCOMMAND) + + def kiro_home(value: str | None = None) -> Path: """The fixed Kiro CLI home: ``~/.kiro``. diff --git a/tests/test_kiro_cli_host_surface.py b/tests/test_kiro_cli_host_surface.py index 3f8d8e983d..1a55b75e26 100644 --- a/tests/test_kiro_cli_host_surface.py +++ b/tests/test_kiro_cli_host_surface.py @@ -21,6 +21,9 @@ ) from loopx.agent_onboarding import _start_instruction, _surface_install_command +from loopx.chat_endpoints import RESERVED_AGENT_IDS, AgentEndpointRegistry +from loopx.chat_runtime import ChatRuntimeController +from loopx.chat_store import ChatSessionStore from loopx.host_loop_activation import ( _heartbeat_commands, build_agent_type_catalog, @@ -29,6 +32,7 @@ scheduler_command_binding_for_agent_type, ) from loopx.kiro_cli_goal_mode import ( + KIRO_CLI_CHAT_AGENT_ID, KIRO_CLI_GOAL_AGENT_FLAG, KIRO_CLI_GOAL_CLEAR_COMMAND, KIRO_CLI_GOAL_COMMAND, @@ -40,6 +44,7 @@ KIRO_CLI_HOOK_TRIGGERS, KIRO_CLI_NATIVE_GOAL_FACTS, KIRO_CLI_SESSION_ID_ENV, + kiro_cli_chat_command, kiro_home, ) from loopx.slash_command_install import install_slash_commands @@ -47,6 +52,13 @@ HOST_SURFACE = "kiro-cli" +def _executable_stub(path: Path) -> Path: + """A file that only has to satisfy the runtime's PATH availability probe.""" + path.write_text("#!/bin/sh\nexit 0\n", encoding="utf-8") + path.chmod(0o755) + return path + + def test_start_goal_accepts_the_kiro_cli_host_surface(tmp_path: Path) -> None: payload = start_goal_accepts_surface(HOST_SURFACE, tmp_path) activation = payload["command_pack"]["host_loop_activation"] @@ -309,6 +321,66 @@ def test_activation_binds_native_goal_with_advisory_quota_entry() -> None: assert "advisory" in hb["heartbeat_prompt_json"].lower() +def test_dashboard_lists_kiro_cli_as_a_builtin_chat_agent(tmp_path: Path) -> None: + """`loopx dashboard` renders its Agent picker from the running process's + capability rows, so a host is only reachable there if it appears as a row + with an adapter the runtime can actually start. Kiro CLI ships an ACP agent, + so the row must be built-in, ACP-shaped, and read-only — and its id must be + reserved, or an owner-local endpoint could shadow the built-in adapter.""" + controller = ChatRuntimeController( + store=ChatSessionStore(tmp_path / "runtime"), + codex_bin="loopx-missing-codex-for-test", + kiro_cli_bin=str(_executable_stub(tmp_path / "kiro-cli")), + ) + try: + rows = controller.capabilities() + row = next( + item for item in rows if item["agent_id"] == KIRO_CLI_CHAT_AGENT_ID + ) + assert row["source"] == "builtin" + assert row["adapter_kind"] == "acp" + assert row["display_name"] == "Kiro CLI" + assert row["trust_scope"] == "read_only" + assert row["available"] is True + finally: + controller.close() + + # The launch argv must not auto-approve tools: LoopX Chat cancels every ACP + # permission request, and a trust flag here would bypass that decision. + command = kiro_cli_chat_command("kiro-cli") + assert command == ("kiro-cli", "acp") + assert not any("trust" in argument for argument in command) + + assert KIRO_CLI_CHAT_AGENT_ID in RESERVED_AGENT_IDS + with pytest.raises(ValueError, match="reserved"): + AgentEndpointRegistry(tmp_path / "endpoints").upsert( + { + "agent_id": KIRO_CLI_CHAT_AGENT_ID, + "display_name": "Shadow Kiro", + "command": ["kiro-cli", "acp"], + } + ) + + +def test_missing_kiro_cli_renders_as_needing_configuration(tmp_path: Path) -> None: + """An uninstalled host must render as unavailable rather than failing when a + session opens; `available` is a live probe, not a static claim.""" + controller = ChatRuntimeController( + store=ChatSessionStore(tmp_path / "runtime"), + codex_bin="loopx-missing-codex-for-test", + kiro_cli_bin="loopx-missing-kiro-cli-for-test", + ) + try: + row = next( + item + for item in controller.capabilities() + if item["agent_id"] == KIRO_CLI_CHAT_AGENT_ID + ) + assert row["available"] is False + finally: + controller.close() + + def test_native_goal_facts_match_the_probed_host() -> None: """The host-facts constants are the single source the activation packet, README and PR narrative cite; they must stay pinned to what the host From 09a188de4546621eda77920f7f1cf8dcae13ca5d Mon Sep 17 00:00:00 2001 From: "vlean.wei" Date: Mon, 7 Sep 2026 16:17:24 +0800 Subject: [PATCH 07/23] fix(kiro-cli): resolve the host by identity across the control plane MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Serving an Agent row made Kiro CLI selectable but not reachable. Four surfaces resolve a host by identity, and each degraded silently rather than failing at the row: - `chat_actions` collapses a runtime Endpoint and a durable Goal agent id onto a host family, so Endpoint `codex` resolves a registered `codex-main-control`. Kiro had no row, so selecting it and creating or reassigning a Todo raised `agent_binding_required` for an agent the user did register — the picker worked and the next action did not. - `KIRO_SESSION_ID` was recorded as the stable thread key and never read, so `start-goal` from a Kiro session left the thread unbound. A documented binding that no code performs is worse than an absent one. - `loopx project-skill` had no Kiro root, so project-level skills could not be delivered to the workspace skills directory the host discovers. - The workspace dispatch phrase matched codex/claude/kimi but not kiro, so "交给 kiro 做 X" did not route. Both lookups become one documented table instead of a chain of prefix branches. The prefix shape in `_AGENT_FAMILY_PREFIXES` is a compatibility seam for operator-chosen ids, not a classification rule, and says so; `HOST_THREAD_ID_ENV` keeps a host out unless its runtime really exports an id, so an unlisted host resolves to no thread rather than borrowing another host's variable. Existing families and the unknown-host fallback are pinned by assertions. `test_generic_delivery_supports_codex_claude_code_opencode_and_pi` encoded the old four-surface set in its name; it is renamed and now asserts the registry itself, so the next host cannot be missed by a hand-listed subset. Signed-off-by: vlean.wei --- .../personal-workspace-page.tsx | 2 +- .../project_skill_delivery/core.py | 1 + loopx/chat_actions.py | 22 ++++++-- loopx/cli_commands/_host_thread.py | 28 ++++++---- loopx/kiro_cli_goal_mode/README.md | 16 ++++++ .../test_material_project_skill_delivery.py | 9 +++- tests/test_kiro_cli_host_surface.py | 51 +++++++++++++++++++ 7 files changed, 113 insertions(+), 16 deletions(-) diff --git a/apps/presentation/dashboard/src/features/personal-workspace/personal-workspace-page.tsx b/apps/presentation/dashboard/src/features/personal-workspace/personal-workspace-page.tsx index 82a1bc88d3..1cd2ee3b96 100644 --- a/apps/presentation/dashboard/src/features/personal-workspace/personal-workspace-page.tsx +++ b/apps/presentation/dashboard/src/features/personal-workspace/personal-workspace-page.tsx @@ -1553,7 +1553,7 @@ export function PersonalWorkspacePage({ return; } const assignedAgentId = requestedAgent?.agentId - ?? (/(交给|分配给|让).{0,24}(agent|codex|claude|kimi)/iu.test(message) ? selectedAgentId : null); + ?? (/(交给|分配给|让).{0,24}(agent|codex|claude|kiro|kimi)/iu.test(message) ? selectedAgentId : null); await createPreview({ actionKind: "todo.create", context: { kind: "goal", goal_id: selectedGoalId, natural_language: message }, diff --git a/loopx/capabilities/project_skill_delivery/core.py b/loopx/capabilities/project_skill_delivery/core.py index 1ae59ae74d..2520bdf13d 100644 --- a/loopx/capabilities/project_skill_delivery/core.py +++ b/loopx/capabilities/project_skill_delivery/core.py @@ -18,6 +18,7 @@ PROJECT_SKILL_SURFACE_ROOTS = { "codex": Path(".agents") / "skills", "claude-code": Path(".claude") / "skills", + "kiro-cli": Path(".kiro") / "skills", "opencode": Path(".opencode") / "skills", "pi": Path(".pi") / "skills", } diff --git a/loopx/chat_actions.py b/loopx/chat_actions.py index bfc6265098..c2d2fc2569 100644 --- a/loopx/chat_actions.py +++ b/loopx/chat_actions.py @@ -22,6 +22,7 @@ from .control_plane.todos.contract import require_supported_todo_resume_when from .history import load_registry from .host_loop_activation import build_host_loop_activation_packet +from .kiro_cli_goal_mode import KIRO_CLI_CHAT_AGENT_ID from .quota import build_quota_should_run from .registry import registry_goals from .todos import add_goal_todo, update_goal_todo @@ -42,6 +43,20 @@ "gate.resolve", } _OPAQUE_ID = re.compile(r"^[A-Za-z0-9._:-]{1,200}$") +# Runtime Endpoint ids and durable Goal agent ids are chosen independently, so +# a family token collapses both onto the host that produced them: Endpoint +# `codex` has to resolve to a registered `codex-main-control`. Every host that +# owns a built-in Endpoint needs a row here, or selecting it in the workspace +# raises `agent_binding_required` for an agent the user did register. A host +# absent from the table resolves to its own id, which only matches an +# identically named agent — correct as a fallback, wrong as a built-in's only +# behavior. The prefix shape is a deliberate compatibility seam for existing +# operator-chosen ids, not a classification rule: keep it in this one table. +_AGENT_FAMILY_PREFIXES: tuple[tuple[str, str], ...] = ( + ("codex", "codex"), + ("claude", "claude-code"), + ("kiro", KIRO_CLI_CHAT_AGENT_ID), +) _MONITOR_CADENCE = re.compile( r"^(?P[1-9][0-9]{0,4})(?Ps|m|h|d)$", re.IGNORECASE, @@ -224,10 +239,9 @@ def _agent_eligibility( @staticmethod def _agent_family(value: str) -> str: token = value.strip().lower().replace("_", "-") - if token.startswith("codex"): - return "codex" - if token.startswith("claude"): - return "claude-code" + for prefix, family in _AGENT_FAMILY_PREFIXES: + if token.startswith(prefix): + return family return token def _resolve_goal_agent(self, goal_id: str, endpoint_id: str) -> str: diff --git a/loopx/cli_commands/_host_thread.py b/loopx/cli_commands/_host_thread.py index 4099dd43ed..68e40adf6f 100644 --- a/loopx/cli_commands/_host_thread.py +++ b/loopx/cli_commands/_host_thread.py @@ -3,17 +3,27 @@ import argparse import os +from ..kiro_cli_goal_mode import KIRO_CLI_AGENT_TYPE, KIRO_CLI_SESSION_ID_ENV + +# Host surface -> the environment variable that host exports for its own +# session/thread id. A binding is only durable if the host guarantees the id, so +# a surface stays out of this table unless its runtime actually exports one; it +# then resolves to no thread id instead of guessing from prose or reusing +# another host's variable. +HOST_THREAD_ID_ENV: dict[str, str] = { + "codex-app": "CODEX_THREAD_ID", + "codex-app-ssh": "CODEX_THREAD_ID", + "codex-ide-plugin": "CODEX_THREAD_ID", + "codex-cli-tui": "CODEX_THREAD_ID", + KIRO_CLI_AGENT_TYPE: KIRO_CLI_SESSION_ID_ENV, +} + def current_host_thread_id(args: argparse.Namespace) -> str | None: explicit = getattr(args, "thread_id", None) if explicit: return str(explicit) - host_surface = getattr(args, "host_surface", None) - if host_surface in { - "codex-app", - "codex-app-ssh", - "codex-ide-plugin", - "codex-cli-tui", - }: - return os.environ.get("CODEX_THREAD_ID") or None - return None + variable = HOST_THREAD_ID_ENV.get(str(getattr(args, "host_surface", None) or "")) + if not variable: + return None + return os.environ.get(variable) or None diff --git a/loopx/kiro_cli_goal_mode/README.md b/loopx/kiro_cli_goal_mode/README.md index 7d91c147bd..c4d5565196 100644 --- a/loopx/kiro_cli_goal_mode/README.md +++ b/loopx/kiro_cli_goal_mode/README.md @@ -138,6 +138,22 @@ Two boundaries this does **not** cross: The built-in id `kiro-cli` is reserved in the owner-local endpoint registry so a hand-registered endpoint cannot silently shadow it. +## Control-plane identity + +Serving an Agent row is not the same as being reachable. Three surfaces resolve +a host by identity, and each one needs Kiro CLI in its table: + +- **Endpoint to Goal agent.** A durable Goal agent id is operator-chosen, so + `chat_actions` collapses both onto a host family: Endpoint `kiro-cli` + resolves a registered `kiro-worker-1`, the same way `codex` resolves + `codex-main-control`. Without the row, selecting Kiro CLI in the workspace + raised `agent_binding_required` for an agent the user did register. +- **Host thread binding.** `KIRO_SESSION_ID` is read for the `kiro-cli` host + surface, so `start-goal` binds the live session instead of leaving the thread + unbound. +- **Project skills.** `loopx project-skill --surface kiro-cli` delivers into + `.kiro/skills`, the workspace skills root Kiro discovers per project. + ## Layout - `__init__.py` — host facts: install surface id, fixed skills root resolution, diff --git a/tests/capabilities/test_material_project_skill_delivery.py b/tests/capabilities/test_material_project_skill_delivery.py index c36ee335b9..c702328666 100644 --- a/tests/capabilities/test_material_project_skill_delivery.py +++ b/tests/capabilities/test_material_project_skill_delivery.py @@ -14,6 +14,7 @@ uninstall_project_material_skill, ) from loopx.capabilities.project_skill_delivery import ( + PROJECT_SKILL_SURFACES, install_project_skill, inspect_project_skill, project_skill_target, @@ -173,12 +174,16 @@ def test_project_skill_uninstall_is_preview_first_and_fails_closed( assert not target.exists() -def test_generic_delivery_supports_codex_claude_code_opencode_and_pi( +def test_generic_delivery_supports_every_registered_surface( tmp_path: Path, ) -> None: + """The old name pinned four surfaces as the supported set; Kiro CLI's + workspace skills root joined it, so the assertion is now the registry itself + rather than a hand-listed subset that silently misses a new host.""" source = _source(tmp_path) project = _project(tmp_path) - surfaces = ("codex", "claude-code", "opencode", "pi") + surfaces = PROJECT_SKILL_SURFACES + assert "kiro-cli" in surfaces preview = install_project_skill( project, diff --git a/tests/test_kiro_cli_host_surface.py b/tests/test_kiro_cli_host_surface.py index 1a55b75e26..11f37f876c 100644 --- a/tests/test_kiro_cli_host_surface.py +++ b/tests/test_kiro_cli_host_surface.py @@ -9,6 +9,7 @@ from __future__ import annotations +import argparse import os from pathlib import Path @@ -21,9 +22,18 @@ ) from loopx.agent_onboarding import _start_instruction, _surface_install_command +from loopx.capabilities.project_skill_delivery import ( + PROJECT_SKILL_SURFACE_ROOTS, + PROJECT_SKILL_SURFACES, +) +from loopx.chat_actions import ChatActionService from loopx.chat_endpoints import RESERVED_AGENT_IDS, AgentEndpointRegistry from loopx.chat_runtime import ChatRuntimeController from loopx.chat_store import ChatSessionStore +from loopx.cli_commands._host_thread import ( + HOST_THREAD_ID_ENV, + current_host_thread_id, +) from loopx.host_loop_activation import ( _heartbeat_commands, build_agent_type_catalog, @@ -381,6 +391,47 @@ def test_missing_kiro_cli_renders_as_needing_configuration(tmp_path: Path) -> No controller.close() +def test_kiro_cli_is_recognized_across_the_control_plane( + monkeypatch: pytest.MonkeyPatch, +) -> None: + """Serving an Agent row is not the same as being reachable. Three separate + surfaces resolve a host by identity, and each one silently degraded for Kiro + CLI: the Endpoint could not bind to a registered Goal agent, the session id + the adapter documents was never read, and project skills had no delivery + root. All three are table lookups; a host that owns a built-in Endpoint must + appear in every table.""" + # A durable Goal agent id is operator-chosen, so the Endpoint must resolve + # through its host family, exactly as `codex` resolves `codex-main-control`. + assert ChatActionService._agent_family("kiro-cli") == KIRO_CLI_CHAT_AGENT_ID + assert ChatActionService._agent_family("kiro-worker-1") == KIRO_CLI_CHAT_AGENT_ID + assert ChatActionService._agent_family("Kiro_CLI") == KIRO_CLI_CHAT_AGENT_ID + # Existing families keep their behavior, and an unknown host still resolves + # to its own id rather than being absorbed into a neighbour. + assert ChatActionService._agent_family("codex-main-control") == "codex" + assert ChatActionService._agent_family("claude-impl") == "claude-code" + assert ChatActionService._agent_family("trae-cli-1") == "trae-cli-1" + + # The adapter records KIRO_SESSION_ID as the stable thread key; reading it is + # what makes that a binding instead of a note. + assert HOST_THREAD_ID_ENV[HOST_SURFACE] == KIRO_CLI_SESSION_ID_ENV + monkeypatch.setenv(KIRO_CLI_SESSION_ID_ENV, "kiro-session-1") + args = argparse.Namespace(host_surface=HOST_SURFACE, thread_id=None) + assert current_host_thread_id(args) == "kiro-session-1" + # An explicit flag still wins, and a host that exports no id stays unbound + # instead of inheriting another host's variable. + assert current_host_thread_id( + argparse.Namespace(host_surface=HOST_SURFACE, thread_id="explicit") + ) == "explicit" + assert current_host_thread_id( + argparse.Namespace(host_surface="agy", thread_id=None) + ) is None + + # Kiro reads workspace skills from .kiro/skills, so project-level delivery + # has a real target root. + assert HOST_SURFACE in PROJECT_SKILL_SURFACES + assert PROJECT_SKILL_SURFACE_ROOTS[HOST_SURFACE] == Path(".kiro") / "skills" + + def test_native_goal_facts_match_the_probed_host() -> None: """The host-facts constants are the single source the activation packet, README and PR narrative cite; they must stay pinned to what the host From 68074fc226044bc64a48d3938dd7b6611440aacd Mon Sep 17 00:00:00 2001 From: "vlean.wei" Date: Tue, 8 Sep 2026 09:41:48 +0800 Subject: [PATCH 08/23] fix(ci): declare the yaml test dependency and refresh the packaged chat bundle Two CI failures on this branch, both from local-only assumptions. tests/test_kiro_cli_host_surface.py parses generated front matter with a strict YAML reader, which is the point of the quoting fix, but PyYAML was never declared so both shards failed collection with ModuleNotFoundError. It is added to the test extra only; runtime dependencies stay empty. The branch changed dashboard sources without rebuilding the tracked bundle, so the packaged-asset freshness gate saw index.html pointing at a stale chunk. The rebuilt bundle is committed alongside its index.html, following the existing convention in that directory of adding the new hashed asset. Signed-off-by: vlean.wei --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index b064f74ccf..767be0f5f7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,6 +27,7 @@ deepseek-harness = [ test = [ "jsonschema>=4.23,<5", "mcp==1.28.1", + "pyyaml>=6,<7", "types-jsonschema>=4.23,<5", "pytest>=9.0.3,<10", "pytest-cov>=5,<7", From 1e039ec6ccea670ca64cf551d711c46d4a5411f8 Mon Sep 17 00:00:00 2001 From: "vlean.wei" Date: Tue, 8 Sep 2026 10:45:39 +0800 Subject: [PATCH 09/23] fix(ci): pin pyyaml in the stage2c hash-locked test requirements The stage2c lanes install from a uv-compiled, hash-pinned lock with --no-deps --no-index, so adding pyyaml to the test extra was not enough: stage2c (e2e) still failed collection with ModuleNotFoundError. Regenerated with the exact command recorded in the file header, so the only content change is the pyyaml pin and its hashes. The header keeps the pinned uv version and explicit index that uv drops when it rewrites its own invocation. Signed-off-by: vlean.wei --- tests/requirements-stage2c-linux-py311.txt | 75 ++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/tests/requirements-stage2c-linux-py311.txt b/tests/requirements-stage2c-linux-py311.txt index 674ba52479..2bcf6196f0 100644 --- a/tests/requirements-stage2c-linux-py311.txt +++ b/tests/requirements-stage2c-linux-py311.txt @@ -732,6 +732,81 @@ python-multipart==0.0.32 \ --hash=sha256:be54b7f3fa167bb83e4fcd936b887b708f4e57fe75911c02aebf53efaf8d938e \ --hash=sha256:ff6d3f776f16878c894e52e107296ffc890e913c611b1a4ec6c44e2821fe2e23 # via mcp +pyyaml==6.0.3 \ + --hash=sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c \ + --hash=sha256:0150219816b6a1fa26fb4699fb7daa9caf09eb1999f3b70fb6e786805e80375a \ + --hash=sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3 \ + --hash=sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956 \ + --hash=sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6 \ + --hash=sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c \ + --hash=sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65 \ + --hash=sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a \ + --hash=sha256:1ebe39cb5fc479422b83de611d14e2c0d3bb2a18bbcb01f229ab3cfbd8fee7a0 \ + --hash=sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b \ + --hash=sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1 \ + --hash=sha256:22ba7cfcad58ef3ecddc7ed1db3409af68d023b7f940da23c6c2a1890976eda6 \ + --hash=sha256:27c0abcb4a5dac13684a37f76e701e054692a9b2d3064b70f5e4eb54810553d7 \ + --hash=sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e \ + --hash=sha256:2e71d11abed7344e42a8849600193d15b6def118602c4c176f748e4583246007 \ + --hash=sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310 \ + --hash=sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4 \ + --hash=sha256:3c5677e12444c15717b902a5798264fa7909e41153cdf9ef7ad571b704a63dd9 \ + --hash=sha256:3ff07ec89bae51176c0549bc4c63aa6202991da2d9a6129d7aef7f1407d3f295 \ + --hash=sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea \ + --hash=sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0 \ + --hash=sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e \ + --hash=sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac \ + --hash=sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9 \ + --hash=sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7 \ + --hash=sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35 \ + --hash=sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb \ + --hash=sha256:5cf4e27da7e3fbed4d6c3d8e797387aaad68102272f8f9752883bc32d61cb87b \ + --hash=sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69 \ + --hash=sha256:5ed875a24292240029e4483f9d4a4b8a1ae08843b9c54f43fcc11e404532a8a5 \ + --hash=sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b \ + --hash=sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c \ + --hash=sha256:6344df0d5755a2c9a276d4473ae6b90647e216ab4757f8426893b5dd2ac3f369 \ + --hash=sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd \ + --hash=sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824 \ + --hash=sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198 \ + --hash=sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065 \ + --hash=sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c \ + --hash=sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c \ + --hash=sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764 \ + --hash=sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196 \ + --hash=sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b \ + --hash=sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00 \ + --hash=sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac \ + --hash=sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8 \ + --hash=sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e \ + --hash=sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28 \ + --hash=sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3 \ + --hash=sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5 \ + --hash=sha256:9c57bb8c96f6d1808c030b1687b9b5fb476abaa47f0db9c0101f5e9f394e97f4 \ + --hash=sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b \ + --hash=sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf \ + --hash=sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5 \ + --hash=sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702 \ + --hash=sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8 \ + --hash=sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788 \ + --hash=sha256:b865addae83924361678b652338317d1bd7e79b1f4596f96b96c77a5a34b34da \ + --hash=sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d \ + --hash=sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc \ + --hash=sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c \ + --hash=sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba \ + --hash=sha256:c2514fceb77bc5e7a2f7adfaa1feb2fb311607c9cb518dbc378688ec73d8292f \ + --hash=sha256:c3355370a2c156cffb25e876646f149d5d68f5e0a3ce86a5084dd0b64a994917 \ + --hash=sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5 \ + --hash=sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26 \ + --hash=sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f \ + --hash=sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b \ + --hash=sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be \ + --hash=sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c \ + --hash=sha256:efd7b85f94a6f21e4932043973a7ba2613b059c4a000551892ac9f1d11f5baf3 \ + --hash=sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6 \ + --hash=sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926 \ + --hash=sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0 + # via loopx (pyproject.toml) referencing==0.37.0 \ --hash=sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231 \ --hash=sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8 From a39c31f29e5b6f71b81cb7eff36ff6ca85e97407 Mon Sep 17 00:00:00 2001 From: "vlean.wei" Date: Tue, 8 Sep 2026 15:15:59 +0800 Subject: [PATCH 10/23] fix(kiro-cli): resolve the host-authoritative KIRO_HOME The Kiro global root was hard-coded to ~/.kiro, and the docstring, README, and installer comment all claimed the host documents no override for it. Kiro CLI does support KIRO_HOME, and it relocates the global agents, prompts, skills, settings, and sessions. Verified against the live host binary: with KIRO_HOME set, kiro-cli reports its global root under that path and creates settings and agents there, while LoopX still resolved $HOME/.kiro. A supported relocated profile therefore received a successful install that the running host could never discover. kiro_home() now resolves injected value, then KIRO_HOME, then the default, matching every other host resolver in this repository. Install and uninstall share the one resolver, so they cannot target different roots. The skills root label follows the existing convention for a host with an override, so the activation hint names the resolved root instead of a path that may be wrong. Signed-off-by: vlean.wei --- loopx/kiro_cli_goal_mode/README.md | 13 ++++++----- loopx/kiro_cli_goal_mode/__init__.py | 33 ++++++++++++++++++---------- loopx/slash_command_install.py | 13 ++++++----- 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/loopx/kiro_cli_goal_mode/README.md b/loopx/kiro_cli_goal_mode/README.md index c4d5565196..e6b757711a 100644 --- a/loopx/kiro_cli_goal_mode/README.md +++ b/loopx/kiro_cli_goal_mode/README.md @@ -54,8 +54,9 @@ start from rather than rediscovering it from host docs. ## What this surface is -Kiro CLI discovers global skills from `~/.kiro/skills//SKILL.md` and -workspace skills from `.kiro/skills//SKILL.md`; the default agent carries +Kiro CLI discovers global skills from `/skills//SKILL.md` +(`~/.kiro` when `KIRO_HOME` is unset) and workspace skills from +`.kiro/skills//SKILL.md`; the default agent carries both as `skill://` resources, and every discovered skill is invocable as a `/` slash command with `$ARGUMENTS` expansion. LoopX reaches a Kiro CLI session through the generated `/loopx` skill facade, and the @@ -80,10 +81,10 @@ loopx slash-commands --install --surface kiro-cli ``` Writes the managed LoopX skill facades (`loopx/SKILL.md`, -`loopx-global-*/SKILL.md`, …) into `~/.kiro/skills/` using Kiro's per-skill -directory layout. The host documents no home override for this root -(`KIRO_AGENT_CONFIG_DIR` relocates agent configs only, not skills), so LoopX -offers none either: installs target exactly that path. Managed files carry the +`loopx-global-*/SKILL.md`, …) into `/skills/` using Kiro's per-skill +directory layout. `KIRO_HOME` is the host's own override for that global root, +so LoopX resolves it and falls back to `~/.kiro` when it is unset; install and +uninstall always target the same resolved root. Managed files carry the `loopx-managed-slash-command` marker and are refreshed by rerunning the installer; user-owned files are never overwritten. diff --git a/loopx/kiro_cli_goal_mode/__init__.py b/loopx/kiro_cli_goal_mode/__init__.py index 4761c9a29e..8cced0ff5b 100644 --- a/loopx/kiro_cli_goal_mode/__init__.py +++ b/loopx/kiro_cli_goal_mode/__init__.py @@ -1,13 +1,18 @@ from __future__ import annotations +import os from pathlib import Path from typing import Any KIRO_CLI_INSTALL_SURFACE = "kiro-cli" KIRO_CLI_AGENT_TYPE = "kiro-cli" DEFAULT_KIRO_CLI_HOME = ".kiro" +# The host's own override for its global root. Kiro CLI relocates global +# agents, prompts, skills, settings, and sessions when this is set, so it is +# authoritative over the default for anything LoopX installs or removes. +KIRO_CLI_HOME_ENV = "KIRO_HOME" SKILLS_SUBDIR = "skills" -SKILLS_ROOT_LABEL = "~/.kiro/skills" +SKILLS_ROOT_LABEL = "KIRO_HOME/skills" KIRO_CLI_BIN = "kiro-cli" KIRO_CLI_ACCEPTED_INPUTS = ( "kiro-cli", @@ -189,15 +194,21 @@ def kiro_cli_chat_command(bin_name: str | None = None) -> tuple[str, ...]: def kiro_home(value: str | None = None) -> Path: - """The fixed Kiro CLI home: ``~/.kiro``. - - Kiro CLI discovers global skills from ``~/.kiro/skills//SKILL.md`` - and workspace skills from ``.kiro/skills//SKILL.md``; the default - agent carries both as ``skill://`` resources. The host documents no home - override for this root (``KIRO_AGENT_CONFIG_DIR`` relocates agent configs - only, not skills), so LoopX exposes none either: installs target exactly - this path, HOME-relative so tests stay hermetic. ``value`` is an internal - injection point for tests, not a public override. + """The Kiro CLI home: ``KIRO_HOME`` when set, else ``~/.kiro``. + + Kiro CLI discovers global skills from ``/skills//SKILL.md`` and + workspace skills from ``.kiro/skills//SKILL.md``; the default agent + carries both as ``skill://`` resources. ``KIRO_HOME`` is the host's own + override for that global root, so LoopX must resolve it: writing to + ``~/.kiro`` while the active profile lives elsewhere would report a + successful install that the running host never discovers. Resolution order + matches every other host in this repository: explicit injected ``value``, + then the host environment override, then the default. Install and uninstall + share this one resolver, so they cannot target different roots. """ - raw = value or str(Path.home() / DEFAULT_KIRO_CLI_HOME) + raw = ( + value + or os.environ.get(KIRO_CLI_HOME_ENV) + or str(Path.home() / DEFAULT_KIRO_CLI_HOME) + ) return Path(raw).expanduser() diff --git a/loopx/slash_command_install.py b/loopx/slash_command_install.py index 72bb46c891..15aa62ebf2 100644 --- a/loopx/slash_command_install.py +++ b/loopx/slash_command_install.py @@ -1005,13 +1005,14 @@ def install_slash_commands( ) if "kiro-cli" in effective_surfaces: - # Kiro CLI discovers global skills from ~/.kiro/skills//SKILL.md + # Kiro CLI discovers global skills from /skills//SKILL.md # (workspace skills live in .kiro/skills), and exposes every discovered - # skill as a `/` slash command. The host documents no home - # override for that root — KIRO_AGENT_CONFIG_DIR relocates agent - # configs only — so LoopX offers none either. A same-named user prompt - # in .kiro/prompts wins over a skill by Kiro's own resolution order; - # the installer never touches the prompt directories. + # skill as a `/` slash command. KIRO_HOME is the host's own + # override for that global root, so the resolver honours it: installing + # into ~/.kiro while the active profile lives elsewhere would report a + # success the running host never discovers. A same-named user prompt in + # .kiro/prompts wins over a skill by Kiro's own resolution order; the + # installer never touches the prompt directories. _install_skill_facade( specs=specs, installed=installed, From 435818e0a75b22ca282e500f7c2af2839ba81ef2 Mon Sep 17 00:00:00 2001 From: "vlean.wei" Date: Tue, 8 Sep 2026 15:15:59 +0800 Subject: [PATCH 11/23] fix(chat): bound agent-family matching at the delimiter The endpoint-to-durable-agent family helper used a bare prefix match, so an unrelated operator-chosen id that merely began with a family root was absorbed into that family. Reproduced: kiroscope-worker and kirograph classified as the Kiro family, and the two pre-existing roots had the same defect with codexplorer and claudeflow. When such an id is the only family match, _resolve_goal_agent binds a built-in Endpoint to the wrong durable identity instead of raising agent_binding_required. Matching now requires the whole id or a `-` delimiter, so the table lists family roots rather than free prefixes. Every documented shape still resolves (kiro, kiro-cli, kiro_cli, kiro-worker-1, codex-main-control), and the regression pins both directions for all three roots. Signed-off-by: vlean.wei --- loopx/chat_actions.py | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/loopx/chat_actions.py b/loopx/chat_actions.py index c2d2fc2569..457100e119 100644 --- a/loopx/chat_actions.py +++ b/loopx/chat_actions.py @@ -50,9 +50,10 @@ # raises `agent_binding_required` for an agent the user did register. A host # absent from the table resolves to its own id, which only matches an # identically named agent — correct as a fallback, wrong as a built-in's only -# behavior. The prefix shape is a deliberate compatibility seam for existing -# operator-chosen ids, not a classification rule: keep it in this one table. -_AGENT_FAMILY_PREFIXES: tuple[tuple[str, str], ...] = ( +# behavior. Matching is bounded at a `-` delimiter, so this table lists family +# roots rather than free prefixes: `kiro-worker-1` joins the Kiro family while +# `kiroscope-worker` keeps its own identity. Keep the rule in this one table. +_AGENT_FAMILY_ROOTS: tuple[tuple[str, str], ...] = ( ("codex", "codex"), ("claude", "claude-code"), ("kiro", KIRO_CLI_CHAT_AGENT_ID), @@ -238,9 +239,20 @@ def _agent_eligibility( @staticmethod def _agent_family(value: str) -> str: + """Classify an id into a host family, bounded at a delimiter. + + A bare prefix match silently swallowed unrelated operator ids: + ``kiroscope-worker`` and ``codexplorer`` are not the Kiro or Codex + family, but they matched, and a single false match is enough for + ``_resolve_goal_agent`` to bind a built-in endpoint to the wrong + durable identity instead of raising ``agent_binding_required``. The + family token must therefore be the whole id or end at a ``-`` + delimiter, which still accepts every documented shape (``kiro``, + ``kiro-cli``, ``kiro-worker-1``) because ids are normalized first. + """ token = value.strip().lower().replace("_", "-") - for prefix, family in _AGENT_FAMILY_PREFIXES: - if token.startswith(prefix): + for prefix, family in _AGENT_FAMILY_ROOTS: + if token == prefix or token.startswith(f"{prefix}-"): return family return token From 2d29023695a1cb0a501183949fe1a18cc8ea0792 Mon Sep 17 00:00:00 2001 From: "vlean.wei" Date: Tue, 8 Sep 2026 15:15:59 +0800 Subject: [PATCH 12/23] test(kiro-cli): cover the real host override and the identity bound The previous home test asserted the adjacent but wrong variable, so it stayed green while a relocated profile got a false install success. It now pins the resolution order and adds an install, readback, and uninstall regression with HOME and the host override pointing at different roots; both fail on the pre-fix resolver. The identity test gains the negative cases the family bound exists for, plus the exact family roots so built-in Endpoint ids keep resolving. Signed-off-by: vlean.wei --- tests/test_kiro_cli_host_surface.py | 71 ++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 7 deletions(-) diff --git a/tests/test_kiro_cli_host_surface.py b/tests/test_kiro_cli_host_surface.py index 11f37f876c..8db01258eb 100644 --- a/tests/test_kiro_cli_host_surface.py +++ b/tests/test_kiro_cli_host_surface.py @@ -51,12 +51,14 @@ KIRO_CLI_GOAL_MAX_ITERATION_CEILING, KIRO_CLI_GOAL_STATUS_COMMAND, KIRO_CLI_GOAL_VALIDATE_FLAG, + KIRO_CLI_HOME_ENV, KIRO_CLI_HOOK_TRIGGERS, KIRO_CLI_NATIVE_GOAL_FACTS, KIRO_CLI_SESSION_ID_ENV, kiro_cli_chat_command, kiro_home, ) +from loopx.slash_command_files import MANAGED_MARKER_PREFIX from loopx.slash_command_install import install_slash_commands HOST_SURFACE = "kiro-cli" @@ -105,20 +107,62 @@ def test_agent_onboarding_setup_command_installs_the_kiro_cli_surface( ) -def test_kiro_home_is_the_documented_fixed_path( +def test_kiro_home_resolves_the_host_override_then_the_default( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: - # The host documents no home override for the skills root - # (KIRO_AGENT_CONFIG_DIR relocates agent configs only), so LoopX exposes - # none: only HOME itself (tests stay hermetic) and the internal injection - # parameter move the root. + """KIRO_HOME is the host's own override for the global root. + + The earlier version of this test asserted the adjacent but wrong variable + (KIRO_AGENT_CONFIG_DIR), so it passed while a relocated profile received a + successful install it could never discover. Resolution order must be the + same as every other host: injected value, host override, default. + """ monkeypatch.setenv("HOME", str(tmp_path / "home")) - monkeypatch.setenv("KIRO_AGENT_CONFIG_DIR", str(tmp_path / "elsewhere")) + monkeypatch.delenv(KIRO_CLI_HOME_ENV, raising=False) assert kiro_home() == tmp_path / "home" / ".kiro" + + monkeypatch.setenv(KIRO_CLI_HOME_ENV, str(tmp_path / "profile")) + assert kiro_home() == tmp_path / "profile" assert kiro_home(str(tmp_path / "explicit")) == tmp_path / "explicit" +def test_install_and_uninstall_follow_the_host_override_not_home( + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, +) -> None: + """The real failure this guards: install reporting success outside the + active profile. HOME and KIRO_HOME differ, so a resolver that ignores the + override writes where the running host never looks.""" + home = tmp_path / "home" + profile = tmp_path / "profile" + monkeypatch.setenv("HOME", str(home)) + monkeypatch.setenv(KIRO_CLI_HOME_ENV, str(profile)) + + payload = install_slash_commands(execute=True, surfaces=[HOST_SURFACE]) + assert payload["ok"] is True + + installed_skill = profile / "skills" / "loopx" / "SKILL.md" + assert installed_skill.is_file(), "install must target the resolved host root" + assert not (home / ".kiro").exists(), "install must not touch the default root" + assert MANAGED_MARKER_PREFIX in installed_skill.read_text(encoding="utf-8") + + reported = { + item["path"] + for item in payload["installed"] + if item["surface"] == HOST_SURFACE and item["path"] + } + assert str(installed_skill) in reported, "readback must name the resolved path" + + removed = install_slash_commands( + execute=True, + surfaces=[HOST_SURFACE], + uninstall=True, + ) + assert removed["ok"] is True + assert not installed_skill.exists(), "uninstall must use the same resolved root" + + def test_installed_skills_are_invocable_as_kiro_slash_commands( tmp_path: Path, ) -> None: @@ -314,7 +358,8 @@ def test_activation_binds_native_goal_with_advisory_quota_entry() -> None: assert "quota should-run" in _start_instruction(HOST_SURFACE) assert "/goal" in _start_instruction(HOST_SURFACE) assert ( - packet["entry_command_hint"] == "the LoopX skill installed in ~/.kiro/skills" + packet["entry_command_hint"] + == "the LoopX skill installed in KIRO_HOME/skills" ) # Rendered heartbeat commands and scope must carry no machine-gate semantics. assert "gated" not in packet["activation_input_command"].lower() @@ -410,6 +455,18 @@ def test_kiro_cli_is_recognized_across_the_control_plane( assert ChatActionService._agent_family("codex-main-control") == "codex" assert ChatActionService._agent_family("claude-impl") == "claude-code" assert ChatActionService._agent_family("trae-cli-1") == "trae-cli-1" + # Matching is bounded at the delimiter: an unrelated operator id that merely + # begins with a family root keeps its own identity. Without this bound a + # single false match lets `_resolve_goal_agent` bind a built-in Endpoint to + # the wrong durable agent instead of raising `agent_binding_required`. + assert ChatActionService._agent_family("kiroscope-worker") == "kiroscope-worker" + assert ChatActionService._agent_family("kirograph") == "kirograph" + assert ChatActionService._agent_family("codexplorer") == "codexplorer" + assert ChatActionService._agent_family("claudeflow") == "claudeflow" + # The exact family root itself still classifies, so built-in Endpoint ids + # such as `kiro` keep resolving to their registered peer. + assert ChatActionService._agent_family("kiro") == KIRO_CLI_CHAT_AGENT_ID + assert ChatActionService._agent_family("codex") == "codex" # The adapter records KIRO_SESSION_ID as the stable thread key; reading it is # what makes that a binding instead of a note. From 8fba5e4ad1a09dab840740940813d16b732ea6e6 Mon Sep 17 00:00:00 2001 From: "vlean.wei" Date: Tue, 8 Sep 2026 17:49:02 +0800 Subject: [PATCH 13/23] fix(kiro-cli): derive the public activation output from the host facts The resolver honoured KIRO_HOME but the outputs a user actually reads did not. The onboarding recommended_start hardcoded ~/.kiro/skills and rendered the native goal command without --validate, and the installer note still claimed the host documents no home override. A relocated profile therefore got a working install with instructions pointing at the wrong root, and a goal bound without --validate lets the host judge completion by its own reading instead of the LoopX Todo's acceptance criteria. kiro_cli_goal_invocation() is now the single owner of the command string, in the host's documented argument order, and both consumers render from it and from SKILLS_ROOT_LABEL. The unused hook config label is removed rather than left as a public structure for an unexercised path. Signed-off-by: vlean.wei --- loopx/agent_onboarding.py | 26 +++++++++++++++++++------- loopx/kiro_cli_goal_mode/__init__.py | 23 ++++++++++++++++++++++- loopx/slash_command_install.py | 7 +++++-- 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/loopx/agent_onboarding.py b/loopx/agent_onboarding.py index 229877c378..0608f81827 100644 --- a/loopx/agent_onboarding.py +++ b/loopx/agent_onboarding.py @@ -15,6 +15,14 @@ scheduler_command_binding_for_agent_type, ) from .install_contract import NO_CLONE_INSTALL_URL +from .kiro_cli_goal_mode import ( + KIRO_CLI_GOAL_CLEAR_COMMAND, + KIRO_CLI_GOAL_COMPLETION_TOOL, + KIRO_CLI_GOAL_MAX_ITERATION_CEILING, + KIRO_CLI_GOAL_STATUS_COMMAND, + SKILLS_ROOT_LABEL as KIRO_CLI_SKILLS_ROOT_LABEL, + kiro_cli_goal_invocation, +) from .project_prompt import ( render_available_capability_args, render_codex_cli_install_preflight, @@ -360,13 +368,17 @@ def _start_instruction(agent_type: str) -> str: ) if agent_type == "kiro-cli": return ( - "Run `/loopx ` (the LoopX skill installed in `~/.kiro/skills`); " - "after todo writeback, bind the objective with the native " - "`/goal --max ` command, taking N from the remaining " - "quota slots and never above the host ceiling of 50 (`/goal clear` " - "cancels). Start every turn and native goal iteration with `quota " - "should-run`, and settle through the built-in `goal` tool only after " - "LoopX writeback so its completion contract cites the same evidence." + f"Run `/loopx ` (the LoopX skill installed in " + f"`{KIRO_CLI_SKILLS_ROOT_LABEL}`); after todo writeback, bind the " + f"objective with the native `{kiro_cli_goal_invocation()}` command, " + f"taking N from the remaining quota slots and never above the host " + f"ceiling of {KIRO_CLI_GOAL_MAX_ITERATION_CEILING} " + f"(`{KIRO_CLI_GOAL_CLEAR_COMMAND}` cancels, " + f"`{KIRO_CLI_GOAL_STATUS_COMMAND}` reads the bound goal back). " + f"Start every turn and native goal iteration with `quota " + f"should-run`, and settle through the built-in " + f"`{KIRO_CLI_GOAL_COMPLETION_TOOL}` tool only after LoopX writeback " + f"so its completion contract cites the same evidence." ) if agent_type == "deepseek-harness": return ( diff --git a/loopx/kiro_cli_goal_mode/__init__.py b/loopx/kiro_cli_goal_mode/__init__.py index 8cced0ff5b..0c91ce5789 100644 --- a/loopx/kiro_cli_goal_mode/__init__.py +++ b/loopx/kiro_cli_goal_mode/__init__.py @@ -73,7 +73,6 @@ "postToolUse", "stop", ) -KIRO_CLI_HOOK_CONFIG_LABEL = "~/.kiro/agents/.json (or .kiro/agents/.json)" KIRO_CLI_NATIVE_GOAL_FACTS = ( "native `/goal [description --validate criteria --agent name --max N] | " @@ -102,6 +101,28 @@ } +def kiro_cli_goal_invocation( + *, + task: str = "", + criteria: str = "", + max_iterations: str = "", +) -> str: + """The canonical native goal invocation, in the host's own argument order. + + Every public projection — onboarding instructions, activation packets, + installer notes — must render the command from here. Dropping + ``--validate`` makes the host judge completion by its own reading instead + of the LoopX Todo's acceptance criteria, and a hand-copied string in a + second consumer is exactly how that flag went missing before. + """ + + return ( + f"{KIRO_CLI_GOAL_COMMAND} {task} " + f"{KIRO_CLI_GOAL_VALIDATE_FLAG} {criteria} " + f"--max {max_iterations}" + ) + + def kiro_cli_activation_extras() -> dict[str, Any]: """Keyword overrides for ``_kiro_cli_activation``'s facade call. diff --git a/loopx/slash_command_install.py b/loopx/slash_command_install.py index 15aa62ebf2..fe1a53d741 100644 --- a/loopx/slash_command_install.py +++ b/loopx/slash_command_install.py @@ -9,7 +9,10 @@ from typing import Any from .agy_goal_mode import agy_home as _agy_home -from .kiro_cli_goal_mode import kiro_home as _kiro_home +from .kiro_cli_goal_mode import ( + SKILLS_ROOT_LABEL as _KIRO_SKILLS_ROOT_LABEL, + kiro_home as _kiro_home, +) from .opencode_goal_mode import plugin_source, runtime_source from .pi_goal_mode import extension_source as pi_extension_source from .pi_goal_mode import runtime_source as pi_runtime_source @@ -1387,7 +1390,7 @@ def install_slash_commands( "Cursor discovers skills from CURSOR_HOME/skills and has no user-defined slash commands, so the cursor surface installs the skill facade and registers the LoopX MCP server in CURSOR_HOME/mcp.json; run `cursor-agent mcp enable loopx` once to approve it.", "ZCode discovers user skills from ZCODE_HOME/skills (default ~/.zcode/skills) and exposes each skill for invocation via `$skill-name` or Settings -> Skills.", "Antigravity CLI discovers global skills from the fixed ~/.gemini/antigravity-cli/skills root using the documented flat layout (one .md per skill); the agy surface is opt-in and offers no home override because the host documents none.", - "Kiro CLI discovers global skills from ~/.kiro/skills//SKILL.md and exposes each as a `/` slash command; the kiro-cli surface is opt-in and offers no home override because the host documents none for that root. Kiro resolves .kiro/prompts and ~/.kiro/prompts before skills, so a same-named user prompt shadows the managed skill.", + f"Kiro CLI discovers global skills from {_KIRO_SKILLS_ROOT_LABEL}//SKILL.md (default ~/.kiro/skills) and exposes each as a `/` slash command; the kiro-cli surface is opt-in and resolves KIRO_HOME so install and uninstall target the profile the running host reads. Kiro resolves .kiro/prompts and KIRO_HOME/prompts before skills, so a same-named user prompt shadows the managed skill.", "OpenCode discovers global skills from OPENCODE_CONFIG_DIR/skills in addition to the static command facade; a command is typed by the user, a skill can be reached by the model itself.", "The default all surface installs only OpenCode's static command facade; the executable goal bridge requires --with-goal-bridge.", "The Pi surface is opt-in and installs the self-contained goal extension and its loop runtime into the project's .pi/extensions/; it is not part of the default all surface.", From d05a504665e74f27e4d46ba2d4a116a6e9caa0ae Mon Sep 17 00:00:00 2001 From: "vlean.wei" Date: Tue, 8 Sep 2026 17:49:02 +0800 Subject: [PATCH 14/23] fix(chat): release the ACP session before signalling the agent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Found by running the real host instead of the fixture. An ACP agent that persists sessions holds a per-session lock while it runs, and LoopX only sent a close request when the agent advertised sessionCapabilities.close. A host that advertises none — the real Kiro CLI reports an empty object — was signalled straight away, so the session stayed locked and the next session/load from a new process failed with "Session is active in another process". Shutdown now closes stdin and lets the agent exit on its own before falling back to terminate. Verified end to end against the real binary: with the fix close_session leaves returncode 0 and the same session id resumes in a new process; reverted, returncode is -15 and the resume is refused. The contract smoke reproduces a host with no close capability and asserts the graceful exit, and it fails on the pre-fix code. Signed-off-by: vlean.wei --- examples/loopx-chat-acp-adapter-smoke.py | 28 ++++++++++++++++++++++++ loopx/chat_acp.py | 20 +++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/examples/loopx-chat-acp-adapter-smoke.py b/examples/loopx-chat-acp-adapter-smoke.py index 569b4a5335..9674d70f8f 100644 --- a/examples/loopx-chat-acp-adapter-smoke.py +++ b/examples/loopx-chat-acp-adapter-smoke.py @@ -316,6 +316,34 @@ def main() -> None: assert missing_row["available"] is False, missing_row unavailable.close() + # Closing a session must release the agent, not just signal it. An ACP + # agent that persists sessions holds a per-session lock while it runs, + # so a signalled exit leaves the session looking active and the next + # `session/load` from a new process is refused. Hosts that advertise no + # `sessionCapabilities.close` are exactly the ones this affects, since + # LoopX has no close request to send them. + no_close = root / "acp-no-close.py" + no_close.write_text( + FAKE_ACP.replace('"sessionCapabilities": {"close": {}},', ""), + encoding="utf-8", + ) + no_close.chmod(no_close.stat().st_mode | stat.S_IXUSR) + adapter = ACPStdioAdapter.start( + command=(sys.executable, str(no_close)), + work_dir=root, + startup_timeout_sec=10.0, + idle_timeout_sec=10.0, + hard_timeout_sec=20.0, + ) + assert not adapter.agent_capabilities.get("sessionCapabilities"), ( + "fixture must reproduce a host with no session close capability" + ) + adapter.close_session() + assert adapter.process.returncode == 0, ( + "close_session must let the agent exit on its own so it can release " + f"the session; got returncode {adapter.process.returncode}" + ) + print("loopx-chat-acp-adapter-smoke: ok") diff --git a/loopx/chat_acp.py b/loopx/chat_acp.py index 2c65c56405..6e63cdab64 100644 --- a/loopx/chat_acp.py +++ b/loopx/chat_acp.py @@ -62,6 +62,9 @@ class ACPStdioAdapter: startup_timeout_sec: float = 30.0 idle_timeout_sec: float = 180.0 hard_timeout_sec: float = 900.0 + # Grace window for the agent to exit on stdin EOF and release any + # per-session lock before LoopX signals the process. + _graceful_exit_timeout_sec: float = 5.0 next_request_id: int = 3 current_request_id: int | None = None _write_lock: threading.Lock = field(default_factory=threading.Lock, repr=False) @@ -440,6 +443,23 @@ def close_session(self) -> None: def _terminate(self) -> None: if self.process.poll() is not None: return + # Close stdin first so the agent sees EOF and shuts down on its own. + # An ACP agent that persists sessions holds a per-session lock while it + # runs; signalling it instead leaves that lock behind, and the next + # `session/load` from a new process is rejected because the session + # still looks active. Verified against a real host: after stdin EOF the + # agent exits 0 and the same session id resumes, while a straight + # terminate produced "Session is active in another process". + try: + if self.process.stdin is not None and not self.process.stdin.closed: + self.process.stdin.close() + except Exception: + pass + try: + self.process.wait(timeout=self._graceful_exit_timeout_sec) + return + except subprocess.TimeoutExpired: + pass self.process.terminate() try: self.process.wait(timeout=2) From 01142c66da098e072ce22c0203773843a738008f Mon Sep 17 00:00:00 2001 From: "vlean.wei" Date: Tue, 8 Sep 2026 17:49:18 +0800 Subject: [PATCH 15/23] fix(dashboard): bound presented agent identity at the delimiter The backend family rule was tightened to exact or delimiter-bounded matching, but the dashboard still classified labels and capabilities with a substring test. An unrelated kiroscope-worker therefore stayed independent in the control plane while being displayed as "Kiro CLI" in diagnostics, run timelines, evidence and report cards, attributing one agent's work to another. The rule moves into agent-family.ts as a testable owner that mirrors the backend, the page renders through it, and the capability row's typed adapter_kind is preferred over the operator-chosen id. The new smoke pins both directions for every family root. Signed-off-by: vlean.wei --- apps/presentation/dashboard/package.json | 19 ++--- .../personal-workspace/agent-family.test.mjs | 35 +++++++++ .../personal-workspace/agent-family.ts | 50 +++++++++++++ .../dashboard/src/views/dashboard-page.tsx | 74 +++++++++---------- 4 files changed, 132 insertions(+), 46 deletions(-) create mode 100644 apps/presentation/dashboard/src/features/personal-workspace/agent-family.test.mjs create mode 100644 apps/presentation/dashboard/src/features/personal-workspace/agent-family.ts diff --git a/apps/presentation/dashboard/package.json b/apps/presentation/dashboard/package.json index 37f582cd3e..c254175a3f 100644 --- a/apps/presentation/dashboard/package.json +++ b/apps/presentation/dashboard/package.json @@ -6,37 +6,38 @@ "type": "module", "scripts": { "build": "tsc --noEmit && vite build && vite build --config vite.chat.config.ts", - "build:desktop": "tsc --noEmit && vite build", "build:chat": "tsc --noEmit && vite build --config vite.chat.config.ts", + "build:desktop": "tsc --noEmit && vite build", "dev": "bash ../../../scripts/dashboard-dev.sh", "dev:web": "vite --host 127.0.0.1", "export:frontstage-share": "node ../../../examples/export-frontstage-share-bundle.mjs", "preview": "vite preview --host 127.0.0.1", "smoke:action-packet": "rm -rf /tmp/loopx-action-packet-smoke && tsc --ignoreConfig --target ES2022 --module NodeNext --moduleResolution NodeNext --skipLibCheck --strict --outDir /tmp/loopx-action-packet-smoke smoke/action-packet-smoke.ts src/data/action-packet.ts && node /tmp/loopx-action-packet-smoke/smoke/action-packet-smoke.js", - "smoke:pwa-bundle": "python3 ../../../examples/dashboard-pwa-bundle-smoke.py", + "smoke:agent-family": "tsc --ignoreConfig --target ES2022 --module ES2022 --moduleResolution Bundler --skipLibCheck --strict --outDir node_modules/.cache/loopx-agent-family src/features/personal-workspace/agent-family.ts && node src/features/personal-workspace/agent-family.test.mjs", + "smoke:benchmark-study": "rm -rf node_modules/.cache/loopx-benchmark-study-smoke && tsc --ignoreConfig --target ES2022 --module NodeNext --moduleResolution NodeNext --skipLibCheck --strict --resolveJsonModule --outDir node_modules/.cache/loopx-benchmark-study-smoke smoke/benchmark-study-contract-smoke.ts src/data/benchmark-study.ts && node node_modules/.cache/loopx-benchmark-study-smoke/smoke/benchmark-study-contract-smoke.js", + "smoke:benchmark-study-browser": "node ../../../examples/dashboard-benchmark-study-browser-smoke.mjs", + "smoke:capability-configuration": "rm -rf node_modules/.cache/loopx-capability-configuration-smoke && tsc --ignoreConfig --target ES2022 --module NodeNext --moduleResolution NodeNext --types node --skipLibCheck --strict --outDir node_modules/.cache/loopx-capability-configuration-smoke smoke/capability-configuration-smoke.ts src/data/capability-configuration.ts && node node_modules/.cache/loopx-capability-configuration-smoke/smoke/capability-configuration-smoke.js", "smoke:chat-route": "tsc --ignoreConfig --target ES2022 --module ES2022 --moduleResolution Bundler --ignoreDeprecations 6.0 --skipLibCheck --strict --outDir node_modules/.cache/loopx-chat-route-smoke smoke/chat-route-smoke.ts src/data/chat-model.ts src/vite-env.d.ts && node node_modules/.cache/loopx-chat-route-smoke/smoke/chat-route-smoke.js", "smoke:demo-readiness": "bash ../../../scripts/loopx-python.sh --exec ../../../examples/dashboard-demo-readiness-smoke.py", "smoke:frontstage-browser": "node ../../../examples/dashboard-frontstage-browser-smoke.mjs", "smoke:frontstage-design-baseline": "node ../../../examples/dashboard-frontstage-design-baseline-smoke.mjs", - "smoke:frontstage-route": "rm -rf /tmp/loopx-frontstage-route-smoke && tsc --ignoreConfig --target ES2022 --module NodeNext --moduleResolution NodeNext --skipLibCheck --strict --outDir /tmp/loopx-frontstage-route-smoke smoke/frontstage-route-smoke.ts && node /tmp/loopx-frontstage-route-smoke/frontstage-route-smoke.js", "smoke:frontstage-operator-state": "rm -rf /tmp/loopx-frontstage-operator-state-smoke && tsc --ignoreConfig --target ES2022 --module commonjs --moduleResolution node --ignoreDeprecations 6.0 --skipLibCheck --strict --outDir /tmp/loopx-frontstage-operator-state-smoke smoke/frontstage-operator-state-smoke.ts src/data/goal-channel-frontstage.ts && NODE_PATH=\"$PWD/node_modules\" node $(find /tmp/loopx-frontstage-operator-state-smoke -name 'frontstage-operator-state-smoke.js')", + "smoke:frontstage-route": "rm -rf /tmp/loopx-frontstage-route-smoke && tsc --ignoreConfig --target ES2022 --module NodeNext --moduleResolution NodeNext --skipLibCheck --strict --outDir /tmp/loopx-frontstage-route-smoke smoke/frontstage-route-smoke.ts && node /tmp/loopx-frontstage-route-smoke/frontstage-route-smoke.js", "smoke:frontstage-share-bundle": "node ../../../examples/frontstage-share-bundle-smoke.mjs", - "smoke:home-browser": "node ../../../examples/dashboard-home-browser-smoke.mjs", "smoke:goal-order": "tsc --ignoreConfig --target ES2022 --module ES2022 --moduleResolution Bundler --skipLibCheck --strict --outDir node_modules/.cache/loopx-goal-order src/features/personal-workspace/goal-order.ts && node src/features/personal-workspace/goal-order.test.mjs", + "smoke:home-browser": "node ../../../examples/dashboard-home-browser-smoke.mjs", + "smoke:home-route": "rm -rf /tmp/loopx-home-route-smoke && tsc --ignoreConfig --target ES2022 --module CommonJS --moduleResolution Node --ignoreDeprecations 6.0 --skipLibCheck --strict --outDir /tmp/loopx-home-route-smoke smoke/home-route-smoke.ts && node /tmp/loopx-home-route-smoke/home-route-smoke.js", "smoke:personal-workspace": "npm run smoke:goal-order && node src/features/personal-workspace/workspace-theme.test.mjs && node ../../../examples/personal-workspace-browser-smoke.mjs", "smoke:personal-workspace-packaged": "npm run smoke:goal-order && node src/features/personal-workspace/workspace-theme.test.mjs && LOOPX_PERSONAL_WORKSPACE_PACKAGED=1 LOOPX_PLAYWRIGHT_PACKAGE=\"$PWD/node_modules/playwright\" node ../../../examples/personal-workspace-browser-smoke.mjs", "smoke:personal-workspace-router": "rm -rf /tmp/loopx-personal-workspace-router-smoke && tsc --ignoreConfig --target ES2022 --module commonjs --moduleResolution node --ignoreDeprecations 6.0 --skipLibCheck --strict --outDir /tmp/loopx-personal-workspace-router-smoke smoke/personal-workspace-router-smoke.ts src/features/personal-workspace/personal-workspace-router.ts && node /tmp/loopx-personal-workspace-router-smoke/smoke/personal-workspace-router-smoke.js", - "smoke:home-route": "rm -rf /tmp/loopx-home-route-smoke && tsc --ignoreConfig --target ES2022 --module CommonJS --moduleResolution Node --ignoreDeprecations 6.0 --skipLibCheck --strict --outDir /tmp/loopx-home-route-smoke smoke/home-route-smoke.ts && node /tmp/loopx-home-route-smoke/home-route-smoke.js", "smoke:presentation-surface-schema": "rm -rf /tmp/loopx-presentation-surface-schema-smoke && tsc --ignoreConfig --target ES2022 --module CommonJS --moduleResolution Node --ignoreDeprecations 6.0 --skipLibCheck --strict --resolveJsonModule --esModuleInterop --outDir /tmp/loopx-presentation-surface-schema-smoke smoke/presentation-surface-schema-smoke.ts src/data/status.ts src/data/decision-research.ts src/data/goal-channel-frontstage.ts && NODE_PATH=\"$PWD/node_modules\" node /tmp/loopx-presentation-surface-schema-smoke/apps/presentation/dashboard/smoke/presentation-surface-schema-smoke.js", "smoke:projection-localization": "rm -rf /tmp/loopx-projection-localization-smoke && tsc --ignoreConfig --target ES2022 --module NodeNext --moduleResolution NodeNext --skipLibCheck --strict --outDir /tmp/loopx-projection-localization-smoke smoke/projection-localization-smoke.ts src/features/personal-workspace/projection-localization.ts && node /tmp/loopx-projection-localization-smoke/smoke/projection-localization-smoke.js", + "smoke:pwa-bundle": "python3 ../../../examples/dashboard-pwa-bundle-smoke.py", + "smoke:status-projection-contract": "rm -rf /tmp/loopx-status-projection-contract-smoke && tsc --ignoreConfig --target ES2022 --module CommonJS --moduleResolution Node --ignoreDeprecations 6.0 --skipLibCheck --strict --resolveJsonModule --esModuleInterop --outDir /tmp/loopx-status-projection-contract-smoke smoke/status-projection-contract-smoke.ts src/data/status.ts src/data/status-merge.ts src/data/status-request-fence.ts && NODE_PATH=\"$PWD/node_modules\" node /tmp/loopx-status-projection-contract-smoke/apps/presentation/dashboard/smoke/status-projection-contract-smoke.js", "smoke:status-source-switch-browser": "node ../../../examples/status-source-switch-browser-smoke.mjs", "smoke:status-source-switch-packaged": "LOOPX_STATUS_SOURCE_SWITCH_PACKAGED=1 LOOPX_STATUS_SOURCE_SWITCH_PORT=5198 node ../../../examples/status-source-switch-browser-smoke.mjs", "smoke:status-sources": "rm -rf /tmp/loopx-status-source-smoke && tsc --ignoreConfig --target ES2022 --module CommonJS --moduleResolution Node --ignoreDeprecations 6.0 --skipLibCheck --strict --resolveJsonModule --esModuleInterop --outDir /tmp/loopx-status-source-smoke smoke/status-source-catalog-smoke.ts src/data/ssh-host-catalog.ts src/data/status-source-catalog.ts src/data/local-status-query.ts src/data/status.ts && NODE_PATH=\"$PWD/node_modules\" node /tmp/loopx-status-source-smoke/apps/presentation/dashboard/smoke/status-source-catalog-smoke.js", - "smoke:status-projection-contract": "rm -rf /tmp/loopx-status-projection-contract-smoke && tsc --ignoreConfig --target ES2022 --module CommonJS --moduleResolution Node --ignoreDeprecations 6.0 --skipLibCheck --strict --resolveJsonModule --esModuleInterop --outDir /tmp/loopx-status-projection-contract-smoke smoke/status-projection-contract-smoke.ts src/data/status.ts src/data/status-merge.ts src/data/status-request-fence.ts && NODE_PATH=\"$PWD/node_modules\" node /tmp/loopx-status-projection-contract-smoke/apps/presentation/dashboard/smoke/status-projection-contract-smoke.js", "smoke:task-board-scroll": "node smoke/task-board-scroll-smoke.mjs", - "smoke:benchmark-study": "rm -rf node_modules/.cache/loopx-benchmark-study-smoke && tsc --ignoreConfig --target ES2022 --module NodeNext --moduleResolution NodeNext --skipLibCheck --strict --resolveJsonModule --outDir node_modules/.cache/loopx-benchmark-study-smoke smoke/benchmark-study-contract-smoke.ts src/data/benchmark-study.ts && node node_modules/.cache/loopx-benchmark-study-smoke/smoke/benchmark-study-contract-smoke.js", - "smoke:benchmark-study-browser": "node ../../../examples/dashboard-benchmark-study-browser-smoke.mjs", - "smoke:capability-configuration": "rm -rf node_modules/.cache/loopx-capability-configuration-smoke && tsc --ignoreConfig --target ES2022 --module NodeNext --moduleResolution NodeNext --types node --skipLibCheck --strict --outDir node_modules/.cache/loopx-capability-configuration-smoke smoke/capability-configuration-smoke.ts src/data/capability-configuration.ts && node node_modules/.cache/loopx-capability-configuration-smoke/smoke/capability-configuration-smoke.js", "smoke:usage-progress": "rm -rf /tmp/loopx-usage-progress-smoke && tsc --ignoreConfig --target ES2022 --module CommonJS --moduleResolution Node --ignoreDeprecations 6.0 --resolveJsonModule --esModuleInterop --skipLibCheck --strict --outDir /tmp/loopx-usage-progress-smoke smoke/usage-progress-smoke.ts src/features/personal-workspace/personal-workspace-model.ts && node /tmp/loopx-usage-progress-smoke/apps/presentation/dashboard/smoke/usage-progress-smoke.js" }, "dependencies": { diff --git a/apps/presentation/dashboard/src/features/personal-workspace/agent-family.test.mjs b/apps/presentation/dashboard/src/features/personal-workspace/agent-family.test.mjs new file mode 100644 index 0000000000..9b373e5e55 --- /dev/null +++ b/apps/presentation/dashboard/src/features/personal-workspace/agent-family.test.mjs @@ -0,0 +1,35 @@ +import assert from "node:assert/strict"; +import { + agentFamily, + presentedAgentFamily, +} from "../../../node_modules/.cache/loopx-agent-family/agent-family.js"; + +// Positive: every documented shape still resolves to its host family, so a +// built-in Endpoint keeps its label. +assert.equal(agentFamily("kiro"), "kiro"); +assert.equal(agentFamily("kiro-cli"), "kiro"); +assert.equal(agentFamily("kiro_cli"), "kiro"); +assert.equal(agentFamily("Kiro-Worker-1"), "kiro"); +assert.equal(agentFamily("codex"), "codex"); +assert.equal(agentFamily("codex-main-control"), "codex"); +assert.equal(agentFamily("claude-code"), "claude"); + +// Negative: an unrelated operator id that merely begins with a family root +// keeps its own identity, matching the backend. Displaying it as the host would +// attribute another agent's work to Kiro/Codex/Claude. +assert.equal(agentFamily("kiroscope-worker"), "kiroscope-worker"); +assert.equal(agentFamily("kirograph"), "kirograph"); +assert.equal(agentFamily("codexplorer"), "codexplorer"); +assert.equal(agentFamily("claudeflow"), "claudeflow"); + +// The typed adapter kind wins over the operator-chosen id when present, and the +// status projection placeholder is not treated as a family signal. +assert.equal(presentedAgentFamily("kiroscope-worker", "kiro-cli"), "kiro"); +assert.equal(presentedAgentFamily("kiroscope-worker", null), "kiroscope-worker"); +assert.equal(presentedAgentFamily("kiroscope-worker", ""), "kiroscope-worker"); +assert.equal( + presentedAgentFamily("kiroscope-worker", "status_projection"), + "kiroscope-worker", +); + +console.log("Agent family presentation invariants passed"); diff --git a/apps/presentation/dashboard/src/features/personal-workspace/agent-family.ts b/apps/presentation/dashboard/src/features/personal-workspace/agent-family.ts new file mode 100644 index 0000000000..df5929282a --- /dev/null +++ b/apps/presentation/dashboard/src/features/personal-workspace/agent-family.ts @@ -0,0 +1,50 @@ +/** + * Presentation-side host family resolution. + * + * Mirrors the backend rule in `loopx/chat_actions.py`: the family token must be + * the whole id or end at a `-` delimiter. A substring match displayed an + * unrelated `kiroscope-worker` as "Kiro CLI" even after the backend correctly + * kept it independent, which is wrong owner attribution wherever the label is + * rendered — diagnostics, run timelines, evidence and report cards. + * + * A capability row's typed `display_name` / `adapter_kind` stays authoritative; + * this module is the fallback used when no row is in scope. + */ + +export const AGENT_FAMILY_ROOTS = [ + "codex", + "claude", + "kiro", + "trae", + "coco", + "openai", + "anthropic", +] as const; + +export type AgentFamilyRoot = (typeof AGENT_FAMILY_ROOTS)[number]; + +/** Return the bounded family root for an id, or the normalized id itself. */ +export function agentFamily(agentId: string): string { + const token = agentId.trim().toLowerCase().replace(/_/gu, "-"); + for (const root of AGENT_FAMILY_ROOTS) { + if (token === root || token.startsWith(`${root}-`)) { + return root; + } + } + return token; +} + +/** + * Resolve the family a capability row should be presented as, preferring the + * typed adapter kind over the operator-chosen id when the row carries one. + */ +export function presentedAgentFamily( + agentId: string, + adapterKind?: string | null, +): string { + const typed = adapterKind?.trim().toLowerCase() ?? ""; + if (typed.length > 0 && typed !== "status_projection") { + return agentFamily(typed); + } + return agentFamily(agentId); +} diff --git a/apps/presentation/dashboard/src/views/dashboard-page.tsx b/apps/presentation/dashboard/src/views/dashboard-page.tsx index 9404ef25b0..20486fd1cd 100644 --- a/apps/presentation/dashboard/src/views/dashboard-page.tsx +++ b/apps/presentation/dashboard/src/views/dashboard-page.tsx @@ -69,6 +69,10 @@ import { mergeScopedStatusProjections } from "../data/status-merge"; import { Button } from "../components/ui/button"; import { Card, CardContent } from "../components/ui/card"; import { Badge } from "../components/ui/badge"; +import { + agentFamily, + presentedAgentFamily, +} from "../features/personal-workspace/agent-family"; import { PersonalWorkspacePage } from "../features/personal-workspace/personal-workspace-page"; import { useWorkspaceI18n, type WorkspaceTranslate } from "../features/personal-workspace/i18n"; import { @@ -618,47 +622,43 @@ function isAgentResultMessage(role: string, text: string) { return ["agent", "assistant"].includes(role.trim().toLowerCase()) && text.trim().length > 0; } +const PERSONAL_AGENT_FALLBACK_CAPABILITY = "已发现的项目 Agent"; + function personalAgentLabel(agentId: string) { - const normalized = agentId.toLowerCase(); - if (normalized.includes("codex")) { - return "Codex"; - } - if (normalized.includes("claude")) { - return "Claude Code"; - } - if (normalized.includes("kiro")) { - return "Kiro CLI"; - } - if (normalized.includes("trae")) { - return "Trae CLI Agent"; - } - if (normalized.includes("coco")) { - return "Coco Agent"; + switch (agentFamily(agentId)) { + case "codex": + return "Codex"; + case "claude": + return "Claude Code"; + case "kiro": + return "Kiro CLI"; + case "trae": + return "Trae CLI Agent"; + case "coco": + return "Coco Agent"; + default: + return personalGoalTitle(agentId); } - return personalGoalTitle(agentId); } -function personalAgentCapability(agentId: string) { - const normalized = agentId.toLowerCase(); - if (normalized.includes("codex")) { - return "代码与项目执行"; - } - if (normalized.includes("claude")) { - return "复杂分析与长任务"; - } - if (normalized.includes("openai") || normalized.includes("anthropic")) { - return "管家问答 · 无工具"; - } - if (normalized.includes("kiro")) { - return "终端编码 · 原生 /goal 循环"; - } - if (normalized.includes("trae")) { - return "前端与交互实现"; - } - if (normalized.includes("coco")) { - return "通用任务"; +function personalAgentCapability(agentId: string, adapterKind?: string | null) { + switch (presentedAgentFamily(agentId, adapterKind)) { + case "codex": + return "代码与项目执行"; + case "claude": + return "复杂分析与长任务"; + case "openai": + case "anthropic": + return "管家问答 · 无工具"; + case "kiro": + return "终端编码 · 原生 /goal 循环"; + case "trae": + return "前端与交互实现"; + case "coco": + return "通用任务"; + default: + return PERSONAL_AGENT_FALLBACK_CAPABILITY; } - return "已发现的项目 Agent"; } function personalVisibleAgentMessage(value: string) { @@ -1428,7 +1428,7 @@ function PersonalGoalHome({ agentId: agent.agent_id, adapterKind: agent.adapter_kind, available: agent.available, - capability: personalAgentCapability(agent.agent_id), + capability: personalAgentCapability(agent.agent_id, agent.adapter_kind), interrupt: agent.interrupt, label: agent.display_name, location: agent.location, From 61b8a07defd9bfa8eac956d07e3a98fb8385a0dd Mon Sep 17 00:00:00 2001 From: "vlean.wei" Date: Tue, 8 Sep 2026 17:49:18 +0800 Subject: [PATCH 16/23] test(kiro-cli): assert the public output contract, not just the resolver A green resolver test is what let the contradiction ship: the observable onboarding instruction and installer note were never asserted. The new test reads both public outputs with HOME and the host override pointing at different roots and requires them to agree with the fact module, carry the validation flag, and name the status readback. An independent oracle pins the command's argument order from the host's documented syntax, and removing --validate from the composer fails both. Signed-off-by: vlean.wei --- tests/test_kiro_cli_host_surface.py | 50 +++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/tests/test_kiro_cli_host_surface.py b/tests/test_kiro_cli_host_surface.py index 8db01258eb..933b3d6cc5 100644 --- a/tests/test_kiro_cli_host_surface.py +++ b/tests/test_kiro_cli_host_surface.py @@ -53,9 +53,11 @@ KIRO_CLI_GOAL_VALIDATE_FLAG, KIRO_CLI_HOME_ENV, KIRO_CLI_HOOK_TRIGGERS, + SKILLS_ROOT_LABEL as KIRO_CLI_SKILLS_ROOT_LABEL, KIRO_CLI_NATIVE_GOAL_FACTS, KIRO_CLI_SESSION_ID_ENV, kiro_cli_chat_command, + kiro_cli_goal_invocation, kiro_home, ) from loopx.slash_command_files import MANAGED_MARKER_PREFIX @@ -107,6 +109,54 @@ def test_agent_onboarding_setup_command_installs_the_kiro_cli_surface( ) +def test_public_outputs_agree_with_the_canonical_host_facts( + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, +) -> None: + """The consumers a user actually reads must not contradict the fact module. + + Resolver tests passing is not the contract: the onboarding instruction and + the installer note are the observable output, and both previously named a + fixed ~/.kiro root and claimed the host has no override while the fact + module already resolved KIRO_HOME. A relocated profile then got a working + install with instructions pointing at the wrong root. + """ + monkeypatch.setenv("HOME", str(tmp_path / "home")) + monkeypatch.setenv(KIRO_CLI_HOME_ENV, str(tmp_path / "profile")) + + instruction = _start_instruction(HOST_SURFACE) + note = next( + item + for item in install_slash_commands(execute=False, surfaces=[HOST_SURFACE])[ + "notes" + ] + if item.startswith("Kiro CLI") + ) + + # Neither output may hardcode the default root or deny the override. + assert "~/.kiro/skills" not in instruction + assert KIRO_CLI_SKILLS_ROOT_LABEL in instruction + assert "offers no home override" not in note + assert KIRO_CLI_HOME_ENV in note + + # The activation command must be complete: without the validation flag the + # host judges completion by its own reading instead of the Todo's criteria. + assert KIRO_CLI_GOAL_VALIDATE_FLAG in instruction + assert kiro_cli_goal_invocation() in instruction + assert KIRO_CLI_GOAL_STATUS_COMMAND in instruction + + +def test_canonical_goal_invocation_uses_the_host_argument_order() -> None: + """An independent oracle for the command, built from the host's documented + syntax rather than from the composer's own output.""" + command = kiro_cli_goal_invocation( + task="", criteria="", max_iterations="7" + ) + assert command == "/goal --validate --max 7" + # The flag order follows the host's own `--validate` before `--max`. + assert command.index(KIRO_CLI_GOAL_VALIDATE_FLAG) < command.index("--max") + + def test_kiro_home_resolves_the_host_override_then_the_default( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, From 48d7438b9c80774fc25052b1b467464d015a7637 Mon Sep 17 00:00:00 2001 From: "vlean.wei" Date: Tue, 8 Sep 2026 18:07:16 +0800 Subject: [PATCH 17/23] build(chat): regenerate the packaged bundle for the changed source The Frontstage Pages workflow rebuilds the chat bundle and requires the tracked output to match a clean source build. This branch changed dashboard-page.tsx, so the committed bundle was stale and that check failed. Regenerated with `npm run build:chat` rather than editing a hash by hand. Only the JS bundle changed, so the stylesheet hash is untouched, and the chunk this rebuild supersedes is removed instead of being left behind as another unreferenced asset. Signed-off-by: vlean.wei --- .../{index-BtQNwJj6.js => index-RG-_aLC3.js} | 20 +++++++++---------- loopx/web/chat/index.html | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) rename loopx/web/chat/assets/{index-BtQNwJj6.js => index-RG-_aLC3.js} (91%) diff --git a/loopx/web/chat/assets/index-BtQNwJj6.js b/loopx/web/chat/assets/index-RG-_aLC3.js similarity index 91% rename from loopx/web/chat/assets/index-BtQNwJj6.js rename to loopx/web/chat/assets/index-RG-_aLC3.js index 01ebbf8f87..15d958473f 100644 --- a/loopx/web/chat/assets/index-BtQNwJj6.js +++ b/loopx/web/chat/assets/index-RG-_aLC3.js @@ -115,15 +115,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs. `);for(;i>=0;){let e=l.slice(0,i);l=l.slice(i+2);let n=Ih(e);n&&(n.event_id&&(r=n.event_id),t(n),a=[`turn.completed`,`turn.interrupted`,`turn.failed`].includes(n.kind)),i=l.indexOf(` -`)}if(e||a)break}i=a?i:i+1}catch(e){if(n?.aborted||(i+=1,i>=4))throw e;await new Promise(e=>globalThis.setTimeout(e,250*2**(i-1)))}}if(!a)throw new _h(`Agent 事件流连接已断开。`,{reconnect_attempts:i})}async function Rh(e,t){return Dh(`/api/chat/sessions/${e}/turns/${t}/interrupt`,{method:`POST`,body:`{}`})}async function zh(e,t,n={}){let r=await Fh(e,t,n.clientTurnId??crypto.randomUUID(),n.attachments);return n.onPhase?.(`turn.accepted`,r.turn_id),Bh(e,r.turn_id,r.events_url,n)}async function Bh(e,t,n,r={}){let i=null,a={failure:null,interrupted:null};try{await Lh(n,e=>{r.onPhase?.(e.kind,t),(e.kind===`answer.delta`||e.kind===`assistant.delta`)&&r.onDelta?.(String(e.payload.text??``)),e.kind===`agent.phase`&&r.onActivity?.(String(e.payload.label??`Agent 正在处理`)),e.kind===`turn.completed`&&(i=e.payload.response),e.kind===`turn.failed`&&(a.failure=e.payload),e.kind===`turn.interrupted`&&(a.interrupted=e.payload)},r.signal)}catch(i){throw i instanceof _h&&!r.signal?.aborted?new _h(i.message,{...i.payload,events_url:n,reconnectable:!0,session_id:e,turn_id:t}):i}if(a.failure)throw new _h(String(a.failure.message||`Agent 回合失败。`),a.failure);if(a.interrupted)throw new _h(`Agent 回合已中断。`,{...a.interrupted,error_code:`turn_interrupted`,session_id:e,turn_id:t});return{response:dh.parse(i),sessionId:e,turnId:t}}async function Vh(e,t,n={}){return Bh(e,t,`/api/chat/sessions/${e}/turns/${t}/events`,n)}async function Hh(e){let t=fh.parse(await Dh(`/api/chat/sessions/${e}`,{keepalive:!0,method:`DELETE`}));if(t.session_id!==e)throw new _h(`Agent 会话关闭回执与本次请求不一致。`,{session_id:t.session_id});return t}async function Uh(e){return Dh(`/api/chat/sessions/${e}/resume`,{method:`POST`,body:`{}`})}function Wh(e){return{goal_id:e.goalId,enabled:e.enabled,...e.enabled?{max_children:e.maxChildren,allowed_domains:e.allowedDomains}:{}}}function Gh(e,t){let n=e.after.orchestration,r=[...new Set(t.allowedDomains)],i=e.feature_summary.multi_subagent===`enabled`;if(!(e.goal_id===t.goalId&&i===t.enabled&&(t.enabled?n.max_children===t.maxChildren&&JSON.stringify(n.allowed_domains)===JSON.stringify(r):n.spawn_allowed===!1&&n.max_children===0)))throw new _h(`Goal 子代理配置回执与本次请求不一致,界面已停止更新。`,{after:e.after,goal_id:e.goal_id});return e}async function Kh(e){let t=hh.parse(await Dh(`/api/chat/goal-subagents/dry-run`,{method:`POST`,body:JSON.stringify(Wh(e))}));if(!t.dry_run||t.execute||t.written)throw new _h(`Goal 子代理预览返回了非预览回执,已停止进入确认状态。`,{result:t});return Gh(t,e)}async function qh(e,t){let n=hh.parse(await Dh(`/api/chat/goal-subagents/apply`,{method:`POST`,body:JSON.stringify({...Wh(e),preview_id:t})}));if(n.preview_id!==t||n.dry_run||!n.execute)throw new _h(`Goal 子代理写入回执与本次确认不一致,界面已停止更新。`,{result:n});if(n.changed&&(!n.written||!n.global_sync.executed||!n.global_sync.readback.verified))throw new _h(`Goal 子代理设置未通过共享状态读回验证。`,{result:n});return Gh(n,e)}var Jh=J({ok:X(!0),targets:q(J({enabled:K(),provider:W(),target_name:W()}))});async function Yh(){return Jh.parse(await Dh(`/api/chat/goal-channel/targets`)).targets}var Xh=J({ok:K(),blocker:W().optional(),public_summary:W().optional(),status:W().optional()});async function Zh(e){return Xh.parse(await Dh(`/api/chat/goal-channel/setup`,{method:`POST`,body:JSON.stringify({execute:e.execute,goal_id:e.goalId,target:e.target})}))}async function Qh(e){return Xh.parse(await Dh(`/api/chat/goal-channel/configure`,{method:`POST`,body:JSON.stringify({auto_notify_human_gates:e.autoNotify,goal_id:e.goalId})}))}J({schema_version:X(`periodic_report_machine_defaults_v0`),enabled:K(),inheritance:X(`live_machine_default`),profile_preset:W().optional(),route_ref:W().optional(),timezone:W()});var $h=J({schema_version:X(`loopx_machine_configuration_v0`),namespaces:gd(W(),gd(W(),id()))}),eg=J({namespace:W(),title:W(),description:W(),schema_versions:q(W()).min(1),configuration_template:gd(W(),id()),template_status:Y([`ready`,`schema_only`])}),tg=J({schema_version:X(`machine_configuration_catalog_v0`),namespaces:q(eg)}),ng=J({key:W(),label:W(),description:W(),input_kind:Y([`boolean`,`number`,`select`,`string_list`,`text`]),required:K(),minimum:G().int().optional(),maximum:G().int().optional(),options:q(W()).optional()}),rg=J({schema_version:X(`capability_configuration_editor_v0`),editable:K(),supported_scopes:q(Y([`goal`,`machine`])),writable_scopes:q(Y([`goal`,`machine`])),fields:q(ng),read_only_reason:W().optional()}),ig=J({schema_version:X(`capability_configuration_catalog_v0`),capabilities:q(J({capability_id:W(),display_name:W(),description:W(),available_scopes:q(Y([`goal`,`machine`])),machine_namespace:W().optional(),goal_feature_id:W().optional(),effective_value_policy:X(`goal_override_over_live_machine_default`).optional(),availability:W().optional(),default:gd(W(),id()).optional(),current:gd(W(),id()).optional(),machine_current:gd(W(),id()).optional(),effective_configuration:J({schema_version:X(`capability_configuration_resolution_v0`),capability_id:W(),source:Y([`goal_override`,`machine_default`,`capability_default`,`not_configured`]),configuration:gd(W(),id()).nullable(),inherited:K(),goal_override_present:K(),machine_default_present:K(),effective_revision:W()}).optional(),documentation:gd(W(),id()).optional(),configuration_editor:rg}))}),ag=J({ok:X(!0),schema_version:X(`goal_configuration_inspection_v0`),status:X(`configured`),goal_id:W(),revision:W(),available_capabilities:q(W()),capability_catalog:ig}),og=J({ok:X(!0),goal_id:W(),capability_id:W(),changed_fields:q(W()),goal_configuration:gd(W(),id()).nullable(),capability_catalog:ig}),sg=og.extend({schema_version:X(`goal_configuration_update_plan_v0`),status:X(`preview`),action:Y([`create`,`update`,`delete`,`unchanged`]),current_revision:W(),desired_revision:W(),base_revision:W(),plan_revision:W(),writes_required:G().int().nonnegative()}),cg=ud([og.extend({schema_version:X(`goal_configuration_transaction_v0`),status:Y([`applied`,`unchanged`]),plan_revision:W(),applied_revision:W(),readback_verified:X(!0)}),J({ok:X(!1),schema_version:X(`goal_configuration_transaction_v0`),status:X(`partial_write`),goal_id:W(),capability_id:W(),plan_revision:W(),applied_revision:W().nullable(),source_written:X(!0),shared_sync_pending:X(!0),readback_verified:K(),changed_fields:q(W()),goal_configuration:gd(W(),id()).nullable(),capability_catalog:ig,error:W(),recommended_action:W()})]),lg=J({ok:X(!0),available_namespaces:q(W()),namespace_catalog:tg.optional().default({schema_version:`machine_configuration_catalog_v0`,namespaces:[]}),capability_catalog:ig,changed_namespaces:q(W()).optional().default([]),machine_configuration:$h.nullable().optional()}),ug=lg.extend({schema_version:X(`machine_configuration_inspection_v0`),status:Y([`configured`,`absent`]),revision:W()}),dg=lg.extend({schema_version:X(`machine_configuration_update_plan_v0`),status:X(`preview`),action:Y([`create`,`update`,`delete`,`unchanged`]),current_revision:W(),desired_revision:W(),plan_revision:W(),writes_required:G().int().nonnegative(),machine_configuration:$h.nullable()}),fg=lg.extend({schema_version:X(`machine_configuration_transaction_v0`),status:Y([`applied`,`unchanged`]),plan_revision:W(),transaction_id:W().nullable(),readback_verified:X(!0),rollback_available:K(),applied_revision:W().optional(),prior_revision:W().optional()}),pg=lg.extend({schema_version:X(`machine_configuration_rollback_plan_v0`),status:X(`preview`),action:Y([`delete`,`restore`,`unchanged`,`blocked`]),reason:W(),transaction_id:W(),plan_revision:W(),rollback_allowed:K(),writes_required:G().int().nonnegative()}),mg=lg.extend({schema_version:X(`machine_configuration_rollback_receipt_v0`),status:Y([`rolled_back`,`unchanged`]),transaction_id:W(),plan_revision:W(),rollback_id:W().nullable(),readback_verified:X(!0)});async function hg(){return ug.parse(await Dh(`/api/chat/machine-configuration`))}async function gg(e){let t=new URLSearchParams({goal_id:e});return ag.parse(await Dh(`/api/chat/goal-configuration?${t.toString()}`))}async function _g(e,t,n){return sg.parse(await Dh(`/api/chat/goal-configuration/preview`,{method:`POST`,body:JSON.stringify({goal_id:e,capability_id:t,configuration:n})}))}async function vg(e,t,n,r){return cg.parse(await Dh(`/api/chat/goal-configuration/apply`,{method:`POST`,body:JSON.stringify({goal_id:e,capability_id:t,configuration:n,expected_plan_revision:r})}))}async function yg(e,t){return dg.parse(await Dh(`/api/chat/machine-configuration/preview`,{method:`POST`,body:JSON.stringify({namespace:e,namespace_configuration:t})}))}async function bg(e,t,n){return fg.parse(await Dh(`/api/chat/machine-configuration/apply`,{method:`POST`,body:JSON.stringify({expected_plan_revision:n,namespace:e,namespace_configuration:t})}))}async function xg(e){return dg.parse(await Dh(`/api/chat/machine-configuration/preview`,{method:`POST`,body:JSON.stringify({namespace:e,operation:`remove`})}))}async function Sg(e,t){return fg.parse(await Dh(`/api/chat/machine-configuration/apply`,{method:`POST`,body:JSON.stringify({expected_plan_revision:t,namespace:e,operation:`remove`})}))}async function Cg(e){return pg.parse(await Dh(`/api/chat/machine-configuration/rollback`,{method:`POST`,body:JSON.stringify({execute:!1,transaction_id:e})}))}async function wg(e,t){return mg.parse(await Dh(`/api/chat/machine-configuration/rollback`,{method:`POST`,body:JSON.stringify({execute:!0,expected_plan_revision:t,transaction_id:e})}))}var Tg=J({ok:X(!0),goals:q(J({goal_id:W(),repository:J({branch:W(),identity:W(),label:W(),read_only:X(!0)})}))});async function Eg(){return Tg.parse(await Dh(`/api/chat/goals/contexts`)).goals}var Dg=J({ok:X(!0),apps:q(J({active:K(),app_ref:W(),brand:W(),health_error_code:W().nullable().default(null),label:W(),ready:K(),reply_ready:K().default(!1)}))});async function Og(){return Dg.parse(await Dh(`/api/chat/lark/apps`)).apps}var kg=J({ok:X(!0),app_ref:W(),error:W().nullable(),setup_id:W(),status:Y([`starting`,`waiting_for_feishu`,`ready`,`failed`,`cancelled`]),verification_url:W().url().nullable()});async function Ag(e){return kg.parse(await Dh(`/api/chat/lark/app-setups`,{method:`POST`,body:JSON.stringify({app_ref:e.appRef,brand:e.brand})}))}async function jg(e){return kg.parse(await Dh(`/api/chat/lark/app-setups/${encodeURIComponent(e)}`))}async function Mg(e){return kg.parse(await Dh(`/api/chat/lark/app-setups/${encodeURIComponent(e)}`,{method:`DELETE`}))}var Ng=[`invalid_event`,`binding_unavailable`,`chat_mismatch`,`topic_mismatch`,`route_ambiguous`,`self_message`,`invalid_routing_state`,`not_addressed`],Pg=J({ok:X(!0),chats:q(J({chat_id:W(),chat_name:W()}))});async function Fg(e,t){let n=new URLSearchParams({app_ref:e});return t&&n.set(`query`,t),Pg.parse(await Dh(`/api/chat/lark/chats?${n.toString()}`)).chats}var Ig=J({ok:X(!0),connections:q(J({agent_id:W().nullable().default(null),connection_id:W(),app_label:W(),app_ref:W(),capture_scope:Y([`addressed_only`,`configured_chat_all`]).default(`addressed_only`),chat_name:W(),enabled:K(),goal_id:W(),goal_title:W(),health_error_code:W().nullable().default(null),history_permission_guidance:J({action:X(`enable_application_scopes_and_publish`),api_document_url:W().url(),capability:X(`group_history_pagination`),identity:X(`bot`),required_scopes:md([X(`im:message.group_msg`),X(`im:message.group_msg.include_bot:read`)]),schema_version:X(`lark_bot_group_history_permission_guidance_v0`)}).nullable().default(null),incoming_mode:Y([`mentions`,`all`]),ingress_mode:Y([`live_steering`,`session_queue`,`async_inbox`,`direct_session`]).default(`async_inbox`),event_count:G().int().nonnegative().default(0),last_event_reason:Y(Ng).nullable().default(null).catch(null),last_event_status:W().nullable().default(null),listener_error_code:W().nullable().default(null),listener_status:Y([`starting`,`listening`,`retrying`,`stopped`]).nullable().default(null),replied_count:G().int().nonnegative().default(0),reply_ready:K().default(!1),reply_mode:X(`topic_reply`),session_bound:K().default(!1),target_ref:W(),topic_name:W(),topic_setup_required:K()}))});async function Lg(){return Ig.parse(await Dh(`/api/chat/lark/connections`)).connections}async function Rg(e){return Xh.parse(await Dh(`/api/chat/lark/connections`,{method:`POST`,body:JSON.stringify({...e.agentBindings?{agent_bindings:e.agentBindings.map(e=>({agent_id:e.agentId,app_ref:e.appRef}))}:{},...e.agentId?{agent_id:e.agentId}:{},...e.appRef?{app_ref:e.appRef}:{},capture_scope:e.captureScope,chat_id:e.chatId,chat_name:e.chatName,execute:e.execute,goal_id:e.goalId,incoming_mode:e.incomingMode,ingress_mode:e.ingressMode,reply_mode:e.replyMode})}))}async function zg(e,t){let n=new URLSearchParams({goal_id:e,connection_id:t});return Xh.parse(await Dh(`/api/chat/lark/connections?${n.toString()}`,{method:`DELETE`}))}function Bg(e){return{loadedUrl:null,projectionRevision:0,requestedUrl:e,selectionRevision:0,requestGeneration:0}}function Vg(e,t){return e.selectionRevision+=1,e.requestedUrl=t,e.selectionRevision}function Hg(e,t,n){if(n.background)return e.requestedUrl!==null||e.loadedUrl!==t?null:(e.requestGeneration+=1,{background:!0,projectionRevision:e.projectionRevision,selectionRevision:e.selectionRevision,url:t,generation:e.requestGeneration});let r=n.selectionRevision??e.selectionRevision+1;return n.selectionRevision!==void 0&&e.selectionRevision!==r?null:(e.selectionRevision=r,e.projectionRevision+=1,e.requestedUrl=t,e.requestGeneration+=1,{background:!1,projectionRevision:e.projectionRevision,selectionRevision:r,url:t,generation:e.requestGeneration})}function Ug(e,t){return t.generation===e.requestGeneration&&e.projectionRevision===t.projectionRevision&&e.selectionRevision===t.selectionRevision}function Wg(e,t){return Ug(e,t)&&(!t.background||e.requestedUrl===null&&e.loadedUrl===t.url)}function Gg(e,t,n){return t.get(e)===n}function Kg(e,t,n,r){return e.filter(e=>Gg(r(e),n,t))}function qg(e,t,n){let r=new Set,i=[];for(let a of[...e,...t]){let e=n(a);e==null||r.has(e)||(r.add(e),i.push(a))}return i}var Jg=[`runs_24h`,`runs_7d`,`quota_spend_slots_24h`,`quota_spend_slots_7d`,`automation_run_count_24h`,`automation_run_count_7d`,`progress_signal_run_count_24h`,`progress_signal_run_count_7d`],Yg=[`input_tokens_24h`,`input_tokens_7d`,`output_tokens_24h`,`output_tokens_7d`,`cache_tokens_24h`,`cache_tokens_7d`,`cost_usd_24h`,`cost_usd_7d`,`duration_ms_24h`,`duration_ms_7d`],Xg=[`accounting`,`decision`,`evidence`,`state`,`work`],Zg={accounting:0,decision:0,evidence:0,state:0,work:0},Qg={runs_24h:0,runs_7d:0,quota_spend_slots_24h:0,quota_spend_slots_7d:0,automation_run_count_24h:0,automation_run_count_7d:0,progress_signal_run_count_24h:0,progress_signal_run_count_7d:0};function $g(e,t){let n={...e};for(let r of Jg)n[r]=(Number(e[r])||0)+(Number(t[r])||0);for(let r of Yg)(e[r]!==void 0||t[r]!==void 0)&&(n[r]=(e[r]??0)+(t[r]??0));return n}function e_(e,t){return!e.length||t<=0?e:e.map(e=>({...e,project_share_24h:Math.round((Number(e.runs_24h)||0)/t*1e3)/1e3}))}function t_(e,t){let n={...e};for(let r of Xg)n[r]=(e[r]??0)+(t[r]??0);return n}function n_(e){let t={events_24h:0,events_7d:0,by_class_24h:{...Zg},by_class_7d:{...Zg}};for(let n of e)t.events_24h+=n.events_24h,t.events_7d+=n.events_7d,t.by_class_24h=t_(t.by_class_24h,n.by_class_24h),t.by_class_7d=t_(t.by_class_7d,n.by_class_7d);return t}function r_(e,t,n){if(!e&&!t)return null;let r=Kg(e?.goals??[],`active`,n,e=>e.goal_id),i=Kg(t?.goals??[],`stopped`,n,e=>e.goal_id),a=qg(r,i,e=>e.goal_id),o=n_(r),s=n_(i),c={events_24h:o.events_24h+s.events_24h,events_7d:o.events_7d+s.events_7d,by_class_24h:t_(o.by_class_24h,s.by_class_24h),by_class_7d:t_(o.by_class_7d,s.by_class_7d)};return{...e??t,goals:a,sample_run_count:(e?.sample_run_count??0)+(t?.sample_run_count??0),totals:c}}function i_(e,t,n){if(!e&&!t)return null;let r=qg([...Kg(e?.items??[],`active`,n,e=>e.goal_id),...Kg(t?.items??[],`stopped`,n,e=>e.goal_id)],[],e=>`${e.goal_id}:${e.decision_kind??``}:${e.decision_at??``}`),i={decision_count:(e?.summary.decision_count??0)+(t?.summary.decision_count??0),stale_count:r.filter(e=>e.stale_by_age).length,rebase_required_count:(e?.summary.rebase_required_count??0)+(t?.summary.rebase_required_count??0),fresh_count:(e?.summary.fresh_count??0)+(t?.summary.fresh_count??0)};return{...e??t,items:r,sample_run_count:(e?.sample_run_count??0)+(t?.sample_run_count??0),summary:i}}function a_(e,t){return qg([...e,...t].sort((e,t)=>t.generated_at.localeCompare(e.generated_at)),[],e=>`${e.goal_id}:${e.generated_at}:${e.classification??``}`)}function o_(e,t,n){let r=qg(Kg(e.items,`active`,n,e=>e.goal_id),Kg(t.items,`stopped`,n,e=>e.goal_id),e=>e.goal_id);return{...e,item_count:r.length,items:r,needs_controller:r.filter(e=>e.waiting_on===`controller`).length,needs_codex:r.filter(e=>e.waiting_on===`codex`).length,needs_user_or_controller:r.filter(e=>[`user_or_controller`,`controller`].includes(e.waiting_on)).length,watching_external_evidence:r.filter(e=>e.waiting_on===`external_evidence`).length}}function s_(e){let t=e.todo_id?.trim()||``;return t?`${e.goal_id}:${t}`:`${e.goal_id}:synthetic:${e.role??``}:${e.index??``}:${e.text??``}`}function c_(e){let t={...Qg};for(let n of e){for(let e of Jg)t[e]+=Number(n[e])||0;for(let e of Yg)n[e]!==void 0&&(t[e]=(t[e]??0)+n[e])}return t}function l_(e,t,n){if(!e&&!t)return null;let r=Kg(e?.items??[],`active`,n,e=>e.goal_id),i=Kg(t?.items??[],`stopped`,n,e=>e.goal_id),a=qg(r,i,s_);return{...e??t,current_projected_count:r.length+i.length,items:a,rollout_event_count:a.reduce((e,t)=>e+(t.event_count??0),0),total_count:a.length}}function u_(e,t,n){if(!e&&!t)return null;let r=Kg(e?.goals??[],`active`,n,e=>e.goal_id),i=Kg(t?.goals??[],`stopped`,n,e=>e.goal_id),a=qg(r,i,e=>e.goal_id),o=$g(c_(r),c_(i));return{...e??t,goals:e_(a,Number(o.runs_24h)||0),sample_run_count:(e?.sample_run_count??0)+(t?.sample_run_count??0),totals:o}}function d_(e,t,n){if(!e&&!t)return null;let r=(e?.agents??[]).filter(e=>e.goal_ids.some(e=>Gg(e,n,`active`))||(e.current_todo?.goal_id?Gg(e.current_todo.goal_id,n,`active`):!1)),i=(t?.agents??[]).filter(e=>e.goal_ids.some(e=>Gg(e,n,`stopped`))||(e.current_todo?.goal_id?Gg(e.current_todo.goal_id,n,`stopped`):!1)),a=qg(r,i,e=>e.agent_id).map(e=>{let t=i.find(t=>t.agent_id===e.agent_id);return t?{...e,goal_ids:Array.from(new Set([...e.goal_ids??[],...t.goal_ids]))}:e});return{...e??t,agents:a,source_summary:(e??t)?.source_summary?{...(e??t).source_summary,projected_agent_count:a.length,registered_agent_count:new Set(a.map(e=>e.agent_id)).size}:(e??t)?.source_summary}}function f_(e,t,n){if(!e&&!t)return null;let r=qg(Kg(e?.goals??[],`active`,n,e=>e.goal_id),Kg(t?.goals??[],`stopped`,n,e=>e.goal_id),e=>e.goal_id);return{...e??t,goals:r}}function p_(e,t){let n=t.goal_projection?.scope;if(n!==`active`&&n!==`stopped`)return t;let r=n,i=t.run_history.goals,a=e.run_history.goals,o=qg(r===`active`?i:a.filter(e=>e.activation_state!==`stopped`),r===`stopped`?i:a.filter(e=>e.activation_state===`stopped`),e=>e.id),s=new Map(o.map(e=>[e.id,e.activation_state])),c=r===`active`?t:e,l=r===`stopped`?t:e,u=e.goal_projection?.registry_revision??null,d=t.goal_projection?.registry_revision??null,f=u===null||d===null||u===d;return{...e,agent_management_projection:d_(c.agent_management_projection,l.agent_management_projection,s),attention_queue:o_(c.attention_queue,l.attention_queue,s),decision_freshness_summary:i_(c.decision_freshness_summary,l.decision_freshness_summary,s),event_ledger_summary:r_(c.event_ledger_summary,l.event_ledger_summary,s),goal_channel_notification_projection:f_(c.goal_channel_notification_projection,l.goal_channel_notification_projection,s),goal_projection:{schema_version:`loopx_goal_projection_scope_v0`,...t.goal_projection,complete:f,projected_goal_count:o.length,registry_goal_count:t.goal_projection?.registry_goal_count??0,scope:`all`},run_history:{...e.run_history,goal_count:o.length,goals:o,recent_runs:a_(c.run_history.recent_runs,l.run_history.recent_runs),run_count:c.run_history.run_count+l.run_history.run_count},todo_index:l_(c.todo_index,l.todo_index,s),usage_summary:u_(c.usage_summary,l.usage_summary,s)}}function m_(e){var t,n,r=``;if(typeof e==`string`||typeof e==`number`)r+=e;else if(typeof e==`object`){if(Array.isArray(e)){var i=e.length;for(t=0;ttypeof e==`boolean`?`${e}`:e===0?`0`:e,__=h_,v_=(e,t)=>n=>{if(t?.variants==null)return __(e,n?.class,n?.className);let{variants:r,defaultVariants:i}=t,a=Object.keys(r).map(e=>{let t=n?.[e],a=i?.[e];if(t===null)return null;let o=g_(t)||g_(a);return r[e][o]}),o=n&&Object.entries(n).reduce((e,t)=>{let[n,r]=t;return r===void 0||(e[n]=r),e},{});return __(e,a,t?.compoundVariants?.reduce((e,t)=>{let{class:n,className:r,...a}=t;return Object.entries(a).every(e=>{let[t,n]=e;return Array.isArray(n)?n.includes({...i,...o}[t]):{...i,...o}[t]===n})?[...e,n,r]:e},[]),n?.class,n?.className)},y_=(e,t)=>{let n=Array(e.length+t.length);for(let t=0;t({classGroupId:e,validator:t}),x_=(e=new Map,t=null,n)=>({nextPart:e,validators:t,classGroupId:n}),S_=`-`,C_=[],w_=`arbitrary..`,T_=e=>{let t=O_(e),{conflictingClassGroups:n,conflictingClassGroupModifiers:r}=e;return{getClassGroupId:e=>{if(e.startsWith(`[`)&&e.endsWith(`]`))return D_(e);let n=e.split(S_);return E_(n,+(n[0]===``&&n.length>1),t)},getConflictingClassGroupIds:(e,t)=>{if(t){let t=r[e],i=n[e];return t?i?y_(i,t):t:i||C_}return n[e]||C_}}},E_=(e,t,n)=>{if(e.length-t===0)return n.classGroupId;let r=e[t],i=n.nextPart.get(r);if(i){let n=E_(e,t+1,i);if(n)return n}let a=n.validators;if(a===null)return;let o=t===0?e.join(S_):e.slice(t).join(S_),s=a.length;for(let e=0;ee.slice(1,-1).indexOf(`:`)===-1?void 0:(()=>{let t=e.slice(1,-1),n=t.indexOf(`:`),r=t.slice(0,n);return r?w_+r:void 0})(),O_=e=>{let{theme:t,classGroups:n}=e;return k_(n,t)},k_=(e,t)=>{let n=x_();for(let r in e){let i=e[r];A_(i,n,r,t)}return n},A_=(e,t,n,r)=>{let i=e.length;for(let a=0;a{if(typeof e==`string`){M_(e,t,n);return}if(typeof e==`function`){N_(e,t,n,r);return}P_(e,t,n,r)},M_=(e,t,n)=>{let r=e===``?t:F_(t,e);r.classGroupId=n},N_=(e,t,n,r)=>{if(I_(e)){A_(e(r),t,n,r);return}t.validators===null&&(t.validators=[]),t.validators.push(b_(n,e))},P_=(e,t,n,r)=>{let i=Object.entries(e),a=i.length;for(let e=0;e{let n=e,r=t.split(S_),i=r.length;for(let e=0;e`isThemeGetter`in e&&e.isThemeGetter===!0,L_=e=>{if(e<1)return{get:()=>void 0,set:()=>{}};let t=0,n=Object.create(null),r=Object.create(null),i=(i,a)=>{n[i]=a,t++,t>e&&(t=0,r=n,n=Object.create(null))};return{get(e){let t=n[e];if(t!==void 0)return t;if((t=r[e])!==void 0)return i(e,t),t},set(e,t){e in n?n[e]=t:i(e,t)}}},R_=`!`,z_=`:`,B_=[],V_=(e,t,n,r,i)=>({modifiers:e,hasImportantModifier:t,baseClassName:n,maybePostfixModifierPosition:r,isExternal:i}),H_=e=>{let{prefix:t,experimentalParseClassName:n}=e,r=e=>{let t=[],n=0,r=0,i=0,a,o=e.length;for(let s=0;si?a-i:void 0;return V_(t,l,c,u)};if(t){let e=t+z_,n=r;r=t=>t.startsWith(e)?n(t.slice(e.length)):V_(B_,!1,t,void 0,!0)}if(n){let e=r;r=t=>n({className:t,parseClassName:e})}return r},U_=e=>{let t=new Map;return e.orderSensitiveModifiers.forEach((e,n)=>{t.set(e,1e6+n)}),e=>{let n=[],r=[];for(let i=0;i0&&(r.sort(),n.push(...r),r=[]),n.push(a)):r.push(a)}return r.length>0&&(r.sort(),n.push(...r)),n}},W_=e=>({cache:L_(e.cacheSize),parseClassName:H_(e),sortModifiers:U_(e),postfixLookupClassGroupIds:G_(e),...T_(e)}),G_=e=>{let t=Object.create(null),n=e.postfixLookupClassGroups;if(n)for(let e=0;e{let{parseClassName:n,getClassGroupId:r,getConflictingClassGroupIds:i,sortModifiers:a,postfixLookupClassGroupIds:o}=t,s=[],c=e.trim().split(K_),l=``;for(let e=c.length-1;e>=0;--e){let t=c[e],{isExternal:u,modifiers:d,hasImportantModifier:f,baseClassName:p,maybePostfixModifierPosition:m}=n(t);if(u){l=t+(l.length>0?` `+l:l);continue}let h=!!m,g;if(h){g=r(p.substring(0,m));let e=g&&o[g]?r(p):void 0;e&&e!==g&&(g=e,h=!1)}else g=r(p);if(!g){if(!h){l=t+(l.length>0?` `+l:l);continue}if(g=r(p),!g){l=t+(l.length>0?` `+l:l);continue}h=!1}let _=d.length===0?``:d.length===1?d[0]:a(d).join(`:`),v=f?_+R_:_,y=v+g;if(s.indexOf(y)>-1)continue;s.push(y);let b=i(g,h);for(let e=0;e0?` `+l:l)}return l},J_=(...e)=>{let t=0,n,r,i=``;for(;t{if(typeof e==`string`)return e;let t,n=``;for(let r=0;r{let n,r,i,a,o=o=>(n=W_(t.reduce((e,t)=>t(e),e())),r=n.cache.get,i=n.cache.set,a=s,s(o)),s=e=>{let t=r(e);if(t)return t;let a=q_(e,n);return i(e,a),a};return a=o,(...e)=>a(J_(...e))},Z_=[],Q_=e=>{let t=t=>t[e]||Z_;return t.isThemeGetter=!0,t},$_=/^\[(?:(\w[\w-]*):)?(.+)\]$/i,ev=/^\((?:(\w[\w-]*):)?(.+)\)$/i,tv=/^\d+(?:\.\d+)?\/\d+(?:\.\d+)?$/,nv=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,rv=/\d+(%|px|r?em|[sdl]?v([hwib]|min|max)|pt|pc|in|cm|mm|cap|ch|ex|r?lh|cq(w|h|i|b|min|max))|\b(calc|min|max|clamp)\(.+\)|^0$/,iv=/^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/,av=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,ov=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,sv=e=>tv.test(e),cv=e=>!!e&&!Number.isNaN(Number(e)),lv=e=>!!e&&Number.isInteger(Number(e)),uv=e=>e.endsWith(`%`)&&cv(e.slice(0,-1)),dv=e=>nv.test(e),fv=()=>!0,pv=e=>rv.test(e)&&!iv.test(e),mv=()=>!1,hv=e=>av.test(e),gv=e=>ov.test(e),_v=e=>!Q(e)&&!$(e),vv=e=>e.startsWith(`@container`)&&(e[10]===`/`&&e[11]!==void 0||e[11]===`s`&&e[16]!==void 0&&e.startsWith(`-size/`,10)||e[11]===`n`&&e[18]!==void 0&&e.startsWith(`-normal/`,10)),yv=e=>Pv(e,Rv,mv),Q=e=>$_.test(e),bv=e=>Pv(e,zv,pv),xv=e=>Pv(e,Bv,cv),Sv=e=>Pv(e,Hv,fv),Cv=e=>Pv(e,Vv,mv),wv=e=>Pv(e,Iv,mv),Tv=e=>Pv(e,Lv,gv),Ev=e=>Pv(e,Uv,hv),$=e=>ev.test(e),Dv=e=>Fv(e,zv),Ov=e=>Fv(e,Vv),kv=e=>Fv(e,Iv),Av=e=>Fv(e,Rv),jv=e=>Fv(e,Lv),Mv=e=>Fv(e,Uv,!0),Nv=e=>Fv(e,Hv,!0),Pv=(e,t,n)=>{let r=$_.exec(e);return r?r[1]?t(r[1]):n(r[2]):!1},Fv=(e,t,n=!1)=>{let r=ev.exec(e);return r?r[1]?t(r[1]):n:!1},Iv=e=>e===`position`||e===`percentage`,Lv=e=>e===`image`||e===`url`,Rv=e=>e===`length`||e===`size`||e===`bg-size`,zv=e=>e===`length`,Bv=e=>e===`number`,Vv=e=>e===`family-name`,Hv=e=>e===`number`||e===`weight`,Uv=e=>e===`shadow`,Wv=X_(()=>{let e=Q_(`color`),t=Q_(`font`),n=Q_(`text`),r=Q_(`font-weight`),i=Q_(`tracking`),a=Q_(`leading`),o=Q_(`breakpoint`),s=Q_(`container`),c=Q_(`spacing`),l=Q_(`radius`),u=Q_(`shadow`),d=Q_(`inset-shadow`),f=Q_(`text-shadow`),p=Q_(`drop-shadow`),m=Q_(`blur`),h=Q_(`perspective`),g=Q_(`aspect`),_=Q_(`ease`),v=Q_(`animate`),y=()=>[`auto`,`avoid`,`all`,`avoid-page`,`page`,`left`,`right`,`column`],b=()=>[`center`,`top`,`bottom`,`left`,`right`,`top-left`,`left-top`,`top-right`,`right-top`,`bottom-right`,`right-bottom`,`bottom-left`,`left-bottom`],x=()=>[...b(),$,Q],S=()=>[`auto`,`hidden`,`clip`,`visible`,`scroll`],C=()=>[`auto`,`contain`,`none`],w=()=>[$,Q,c],T=()=>[sv,`full`,`auto`,...w()],E=()=>[lv,`none`,`subgrid`,$,Q],D=()=>[`auto`,{span:[`full`,lv,$,Q]},lv,$,Q],O=()=>[lv,`auto`,$,Q],k=()=>[`auto`,`min`,`max`,`fr`,$,Q],ee=()=>[`start`,`end`,`center`,`between`,`around`,`evenly`,`stretch`,`baseline`,`center-safe`,`end-safe`],A=()=>[`start`,`end`,`center`,`stretch`,`center-safe`,`end-safe`],j=()=>[`auto`,...w()],te=()=>[sv,`auto`,`full`,`dvw`,`dvh`,`lvw`,`lvh`,`svw`,`svh`,`min`,`max`,`fit`,...w()],ne=()=>[sv,`screen`,`full`,`dvw`,`lvw`,`svw`,`min`,`max`,`fit`,...w()],re=()=>[sv,`screen`,`full`,`lh`,`dvh`,`lvh`,`svh`,`min`,`max`,`fit`,...w()],M=()=>[e,$,Q],N=()=>[...b(),kv,wv,{position:[$,Q]}],ie=()=>[`no-repeat`,{repeat:[``,`x`,`y`,`space`,`round`]}],ae=()=>[`auto`,`cover`,`contain`,Av,yv,{size:[$,Q]}],oe=()=>[uv,Dv,bv],P=()=>[``,`none`,`full`,l,$,Q],F=()=>[``,cv,Dv,bv],I=()=>[`solid`,`dashed`,`dotted`,`double`],se=()=>[`normal`,`multiply`,`screen`,`overlay`,`darken`,`lighten`,`color-dodge`,`color-burn`,`hard-light`,`soft-light`,`difference`,`exclusion`,`hue`,`saturation`,`color`,`luminosity`],ce=()=>[cv,uv,kv,wv],le=()=>[``,`none`,m,$,Q],ue=()=>[`none`,cv,$,Q],de=()=>[`none`,cv,$,Q],fe=()=>[cv,$,Q],pe=()=>[sv,`full`,...w()];return{cacheSize:500,theme:{animate:[`spin`,`ping`,`pulse`,`bounce`],aspect:[`video`],blur:[dv],breakpoint:[dv],color:[fv],container:[dv],"drop-shadow":[dv],ease:[`in`,`out`,`in-out`],font:[_v],"font-weight":[`thin`,`extralight`,`light`,`normal`,`medium`,`semibold`,`bold`,`extrabold`,`black`],"inset-shadow":[dv],leading:[`none`,`tight`,`snug`,`normal`,`relaxed`,`loose`],perspective:[`dramatic`,`near`,`normal`,`midrange`,`distant`,`none`],radius:[dv],shadow:[dv],spacing:[`px`,cv],text:[dv],"text-shadow":[dv],tracking:[`tighter`,`tight`,`normal`,`wide`,`wider`,`widest`]},classGroups:{aspect:[{aspect:[`auto`,`square`,sv,Q,$,g]}],container:[`container`],"container-type":[{"@container":[``,`normal`,`size`,$,Q]}],"container-named":[vv],columns:[{columns:[cv,Q,$,s]}],"break-after":[{"break-after":y()}],"break-before":[{"break-before":y()}],"break-inside":[{"break-inside":[`auto`,`avoid`,`avoid-page`,`avoid-column`]}],"box-decoration":[{"box-decoration":[`slice`,`clone`]}],box:[{box:[`border`,`content`]}],display:[`block`,`inline-block`,`inline`,`flex`,`inline-flex`,`table`,`inline-table`,`table-caption`,`table-cell`,`table-column`,`table-column-group`,`table-footer-group`,`table-header-group`,`table-row-group`,`table-row`,`flow-root`,`grid`,`inline-grid`,`contents`,`list-item`,`hidden`],sr:[`sr-only`,`not-sr-only`],float:[{float:[`right`,`left`,`none`,`start`,`end`]}],clear:[{clear:[`left`,`right`,`both`,`none`,`start`,`end`]}],isolation:[`isolate`,`isolation-auto`],"object-fit":[{object:[`contain`,`cover`,`fill`,`none`,`scale-down`]}],"object-position":[{object:x()}],overflow:[{overflow:S()}],"overflow-x":[{"overflow-x":S()}],"overflow-y":[{"overflow-y":S()}],overscroll:[{overscroll:C()}],"overscroll-x":[{"overscroll-x":C()}],"overscroll-y":[{"overscroll-y":C()}],position:[`static`,`fixed`,`absolute`,`relative`,`sticky`],inset:[{inset:T()}],"inset-x":[{"inset-x":T()}],"inset-y":[{"inset-y":T()}],start:[{"inset-s":T(),start:T()}],end:[{"inset-e":T(),end:T()}],"inset-bs":[{"inset-bs":T()}],"inset-be":[{"inset-be":T()}],top:[{top:T()}],right:[{right:T()}],bottom:[{bottom:T()}],left:[{left:T()}],visibility:[`visible`,`invisible`,`collapse`],z:[{z:[lv,`auto`,$,Q]}],basis:[{basis:[sv,`full`,`auto`,s,...w()]}],"flex-direction":[{flex:[`row`,`row-reverse`,`col`,`col-reverse`]}],"flex-wrap":[{flex:[`nowrap`,`wrap`,`wrap-reverse`]}],flex:[{flex:[cv,sv,`auto`,`initial`,`none`,Q]}],grow:[{grow:[``,cv,$,Q]}],shrink:[{shrink:[``,cv,$,Q]}],order:[{order:[lv,`first`,`last`,`none`,$,Q]}],"grid-cols":[{"grid-cols":E()}],"col-start-end":[{col:D()}],"col-start":[{"col-start":O()}],"col-end":[{"col-end":O()}],"grid-rows":[{"grid-rows":E()}],"row-start-end":[{row:D()}],"row-start":[{"row-start":O()}],"row-end":[{"row-end":O()}],"grid-flow":[{"grid-flow":[`row`,`col`,`dense`,`row-dense`,`col-dense`]}],"auto-cols":[{"auto-cols":k()}],"auto-rows":[{"auto-rows":k()}],gap:[{gap:w()}],"gap-x":[{"gap-x":w()}],"gap-y":[{"gap-y":w()}],"justify-content":[{justify:[...ee(),`normal`]}],"justify-items":[{"justify-items":[...A(),`normal`]}],"justify-self":[{"justify-self":[`auto`,...A()]}],"align-content":[{content:[`normal`,...ee()]}],"align-items":[{items:[...A(),{baseline:[``,`last`]}]}],"align-self":[{self:[`auto`,...A(),{baseline:[``,`last`]}]}],"place-content":[{"place-content":ee()}],"place-items":[{"place-items":[...A(),`baseline`]}],"place-self":[{"place-self":[`auto`,...A()]}],p:[{p:w()}],px:[{px:w()}],py:[{py:w()}],ps:[{ps:w()}],pe:[{pe:w()}],pbs:[{pbs:w()}],pbe:[{pbe:w()}],pt:[{pt:w()}],pr:[{pr:w()}],pb:[{pb:w()}],pl:[{pl:w()}],m:[{m:j()}],mx:[{mx:j()}],my:[{my:j()}],ms:[{ms:j()}],me:[{me:j()}],mbs:[{mbs:j()}],mbe:[{mbe:j()}],mt:[{mt:j()}],mr:[{mr:j()}],mb:[{mb:j()}],ml:[{ml:j()}],"space-x":[{"space-x":w()}],"space-x-reverse":[`space-x-reverse`],"space-y":[{"space-y":w()}],"space-y-reverse":[`space-y-reverse`],size:[{size:te()}],"inline-size":[{inline:[`auto`,...ne()]}],"min-inline-size":[{"min-inline":[`auto`,...ne()]}],"max-inline-size":[{"max-inline":[`none`,...ne()]}],"block-size":[{block:[`auto`,...re()]}],"min-block-size":[{"min-block":[`auto`,...re()]}],"max-block-size":[{"max-block":[`none`,...re()]}],w:[{w:[s,`screen`,...te()]}],"min-w":[{"min-w":[s,`screen`,`none`,...te()]}],"max-w":[{"max-w":[s,`screen`,`none`,`prose`,{screen:[o]},...te()]}],h:[{h:[`screen`,`lh`,...te()]}],"min-h":[{"min-h":[`screen`,`lh`,`none`,...te()]}],"max-h":[{"max-h":[`screen`,`lh`,...te()]}],"font-size":[{text:[`base`,n,Dv,bv]}],"font-smoothing":[`antialiased`,`subpixel-antialiased`],"font-style":[`italic`,`not-italic`],"font-weight":[{font:[r,Nv,Sv]}],"font-stretch":[{"font-stretch":[`ultra-condensed`,`extra-condensed`,`condensed`,`semi-condensed`,`normal`,`semi-expanded`,`expanded`,`extra-expanded`,`ultra-expanded`,uv,Q]}],"font-family":[{font:[Ov,Cv,t]}],"font-features":[{"font-features":[Q]}],"fvn-normal":[`normal-nums`],"fvn-ordinal":[`ordinal`],"fvn-slashed-zero":[`slashed-zero`],"fvn-figure":[`lining-nums`,`oldstyle-nums`],"fvn-spacing":[`proportional-nums`,`tabular-nums`],"fvn-fraction":[`diagonal-fractions`,`stacked-fractions`],tracking:[{tracking:[i,$,Q]}],"line-clamp":[{"line-clamp":[cv,`none`,$,xv]}],leading:[{leading:[a,...w()]}],"list-image":[{"list-image":[`none`,$,Q]}],"list-style-position":[{list:[`inside`,`outside`]}],"list-style-type":[{list:[`disc`,`decimal`,`none`,$,Q]}],"text-alignment":[{text:[`left`,`center`,`right`,`justify`,`start`,`end`]}],"placeholder-color":[{placeholder:M()}],"text-color":[{text:M()}],"text-decoration":[`underline`,`overline`,`line-through`,`no-underline`],"text-decoration-style":[{decoration:[...I(),`wavy`]}],"text-decoration-thickness":[{decoration:[cv,`from-font`,`auto`,$,bv]}],"text-decoration-color":[{decoration:M()}],"underline-offset":[{"underline-offset":[cv,`auto`,$,Q]}],"text-transform":[`uppercase`,`lowercase`,`capitalize`,`normal-case`],"text-overflow":[`truncate`,`text-ellipsis`,`text-clip`],"text-wrap":[{text:[`wrap`,`nowrap`,`balance`,`pretty`]}],indent:[{indent:w()}],"tab-size":[{tab:[lv,$,Q]}],"vertical-align":[{align:[`baseline`,`top`,`middle`,`bottom`,`text-top`,`text-bottom`,`sub`,`super`,$,Q]}],whitespace:[{whitespace:[`normal`,`nowrap`,`pre`,`pre-line`,`pre-wrap`,`break-spaces`]}],break:[{break:[`normal`,`words`,`all`,`keep`]}],wrap:[{wrap:[`break-word`,`anywhere`,`normal`]}],hyphens:[{hyphens:[`none`,`manual`,`auto`]}],content:[{content:[`none`,$,Q]}],"bg-attachment":[{bg:[`fixed`,`local`,`scroll`]}],"bg-clip":[{"bg-clip":[`border`,`padding`,`content`,`text`]}],"bg-origin":[{"bg-origin":[`border`,`padding`,`content`]}],"bg-position":[{bg:N()}],"bg-repeat":[{bg:ie()}],"bg-size":[{bg:ae()}],"bg-image":[{bg:[`none`,{linear:[{to:[`t`,`tr`,`r`,`br`,`b`,`bl`,`l`,`tl`]},lv,$,Q],radial:[``,$,Q],conic:[lv,$,Q]},jv,Tv]}],"bg-color":[{bg:M()}],"gradient-from-pos":[{from:oe()}],"gradient-via-pos":[{via:oe()}],"gradient-to-pos":[{to:oe()}],"gradient-from":[{from:M()}],"gradient-via":[{via:M()}],"gradient-to":[{to:M()}],rounded:[{rounded:P()}],"rounded-s":[{"rounded-s":P()}],"rounded-e":[{"rounded-e":P()}],"rounded-t":[{"rounded-t":P()}],"rounded-r":[{"rounded-r":P()}],"rounded-b":[{"rounded-b":P()}],"rounded-l":[{"rounded-l":P()}],"rounded-ss":[{"rounded-ss":P()}],"rounded-se":[{"rounded-se":P()}],"rounded-ee":[{"rounded-ee":P()}],"rounded-es":[{"rounded-es":P()}],"rounded-tl":[{"rounded-tl":P()}],"rounded-tr":[{"rounded-tr":P()}],"rounded-br":[{"rounded-br":P()}],"rounded-bl":[{"rounded-bl":P()}],"border-w":[{border:F()}],"border-w-x":[{"border-x":F()}],"border-w-y":[{"border-y":F()}],"border-w-s":[{"border-s":F()}],"border-w-e":[{"border-e":F()}],"border-w-bs":[{"border-bs":F()}],"border-w-be":[{"border-be":F()}],"border-w-t":[{"border-t":F()}],"border-w-r":[{"border-r":F()}],"border-w-b":[{"border-b":F()}],"border-w-l":[{"border-l":F()}],"divide-x":[{"divide-x":F()}],"divide-x-reverse":[`divide-x-reverse`],"divide-y":[{"divide-y":F()}],"divide-y-reverse":[`divide-y-reverse`],"border-style":[{border:[...I(),`hidden`,`none`]}],"divide-style":[{divide:[...I(),`hidden`,`none`]}],"border-color":[{border:M()}],"border-color-x":[{"border-x":M()}],"border-color-y":[{"border-y":M()}],"border-color-s":[{"border-s":M()}],"border-color-e":[{"border-e":M()}],"border-color-bs":[{"border-bs":M()}],"border-color-be":[{"border-be":M()}],"border-color-t":[{"border-t":M()}],"border-color-r":[{"border-r":M()}],"border-color-b":[{"border-b":M()}],"border-color-l":[{"border-l":M()}],"divide-color":[{divide:M()}],"outline-style":[{outline:[...I(),`none`,`hidden`]}],"outline-offset":[{"outline-offset":[cv,$,Q]}],"outline-w":[{outline:[``,cv,Dv,bv]}],"outline-color":[{outline:M()}],shadow:[{shadow:[``,`none`,u,Mv,Ev]}],"shadow-color":[{shadow:M()}],"inset-shadow":[{"inset-shadow":[`none`,d,Mv,Ev]}],"inset-shadow-color":[{"inset-shadow":M()}],"ring-w":[{ring:F()}],"ring-w-inset":[`ring-inset`],"ring-color":[{ring:M()}],"ring-offset-w":[{"ring-offset":[cv,bv]}],"ring-offset-color":[{"ring-offset":M()}],"inset-ring-w":[{"inset-ring":F()}],"inset-ring-color":[{"inset-ring":M()}],"text-shadow":[{"text-shadow":[`none`,f,Mv,Ev]}],"text-shadow-color":[{"text-shadow":M()}],opacity:[{opacity:[cv,$,Q]}],"mix-blend":[{"mix-blend":[...se(),`plus-darker`,`plus-lighter`]}],"bg-blend":[{"bg-blend":se()}],"mask-clip":[{"mask-clip":[`border`,`padding`,`content`,`fill`,`stroke`,`view`]},`mask-no-clip`],"mask-composite":[{mask:[`add`,`subtract`,`intersect`,`exclude`]}],"mask-image-linear-pos":[{"mask-linear":[cv]}],"mask-image-linear-from-pos":[{"mask-linear-from":ce()}],"mask-image-linear-to-pos":[{"mask-linear-to":ce()}],"mask-image-linear-from-color":[{"mask-linear-from":M()}],"mask-image-linear-to-color":[{"mask-linear-to":M()}],"mask-image-t-from-pos":[{"mask-t-from":ce()}],"mask-image-t-to-pos":[{"mask-t-to":ce()}],"mask-image-t-from-color":[{"mask-t-from":M()}],"mask-image-t-to-color":[{"mask-t-to":M()}],"mask-image-r-from-pos":[{"mask-r-from":ce()}],"mask-image-r-to-pos":[{"mask-r-to":ce()}],"mask-image-r-from-color":[{"mask-r-from":M()}],"mask-image-r-to-color":[{"mask-r-to":M()}],"mask-image-b-from-pos":[{"mask-b-from":ce()}],"mask-image-b-to-pos":[{"mask-b-to":ce()}],"mask-image-b-from-color":[{"mask-b-from":M()}],"mask-image-b-to-color":[{"mask-b-to":M()}],"mask-image-l-from-pos":[{"mask-l-from":ce()}],"mask-image-l-to-pos":[{"mask-l-to":ce()}],"mask-image-l-from-color":[{"mask-l-from":M()}],"mask-image-l-to-color":[{"mask-l-to":M()}],"mask-image-x-from-pos":[{"mask-x-from":ce()}],"mask-image-x-to-pos":[{"mask-x-to":ce()}],"mask-image-x-from-color":[{"mask-x-from":M()}],"mask-image-x-to-color":[{"mask-x-to":M()}],"mask-image-y-from-pos":[{"mask-y-from":ce()}],"mask-image-y-to-pos":[{"mask-y-to":ce()}],"mask-image-y-from-color":[{"mask-y-from":M()}],"mask-image-y-to-color":[{"mask-y-to":M()}],"mask-image-radial":[{"mask-radial":[$,Q]}],"mask-image-radial-from-pos":[{"mask-radial-from":ce()}],"mask-image-radial-to-pos":[{"mask-radial-to":ce()}],"mask-image-radial-from-color":[{"mask-radial-from":M()}],"mask-image-radial-to-color":[{"mask-radial-to":M()}],"mask-image-radial-shape":[{"mask-radial":[`circle`,`ellipse`]}],"mask-image-radial-size":[{"mask-radial":[{closest:[`side`,`corner`],farthest:[`side`,`corner`]}]}],"mask-image-radial-pos":[{"mask-radial-at":b()}],"mask-image-conic-pos":[{"mask-conic":[cv]}],"mask-image-conic-from-pos":[{"mask-conic-from":ce()}],"mask-image-conic-to-pos":[{"mask-conic-to":ce()}],"mask-image-conic-from-color":[{"mask-conic-from":M()}],"mask-image-conic-to-color":[{"mask-conic-to":M()}],"mask-mode":[{mask:[`alpha`,`luminance`,`match`]}],"mask-origin":[{"mask-origin":[`border`,`padding`,`content`,`fill`,`stroke`,`view`]}],"mask-position":[{mask:N()}],"mask-repeat":[{mask:ie()}],"mask-size":[{mask:ae()}],"mask-type":[{"mask-type":[`alpha`,`luminance`]}],"mask-image":[{mask:[`none`,$,Q]}],filter:[{filter:[``,`none`,$,Q]}],blur:[{blur:le()}],brightness:[{brightness:[cv,$,Q]}],contrast:[{contrast:[cv,$,Q]}],"drop-shadow":[{"drop-shadow":[``,`none`,p,Mv,Ev]}],"drop-shadow-color":[{"drop-shadow":M()}],grayscale:[{grayscale:[``,cv,$,Q]}],"hue-rotate":[{"hue-rotate":[cv,$,Q]}],invert:[{invert:[``,cv,$,Q]}],saturate:[{saturate:[cv,$,Q]}],sepia:[{sepia:[``,cv,$,Q]}],"backdrop-filter":[{"backdrop-filter":[``,`none`,$,Q]}],"backdrop-blur":[{"backdrop-blur":le()}],"backdrop-brightness":[{"backdrop-brightness":[cv,$,Q]}],"backdrop-contrast":[{"backdrop-contrast":[cv,$,Q]}],"backdrop-grayscale":[{"backdrop-grayscale":[``,cv,$,Q]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[cv,$,Q]}],"backdrop-invert":[{"backdrop-invert":[``,cv,$,Q]}],"backdrop-opacity":[{"backdrop-opacity":[cv,$,Q]}],"backdrop-saturate":[{"backdrop-saturate":[cv,$,Q]}],"backdrop-sepia":[{"backdrop-sepia":[``,cv,$,Q]}],"border-collapse":[{border:[`collapse`,`separate`]}],"border-spacing":[{"border-spacing":w()}],"border-spacing-x":[{"border-spacing-x":w()}],"border-spacing-y":[{"border-spacing-y":w()}],"table-layout":[{table:[`auto`,`fixed`]}],caption:[{caption:[`top`,`bottom`]}],transition:[{transition:[``,`all`,`colors`,`opacity`,`shadow`,`transform`,`none`,$,Q]}],"transition-behavior":[{transition:[`normal`,`discrete`]}],duration:[{duration:[cv,`initial`,$,Q]}],ease:[{ease:[`linear`,`initial`,_,$,Q]}],delay:[{delay:[cv,$,Q]}],animate:[{animate:[`none`,v,$,Q]}],backface:[{backface:[`hidden`,`visible`]}],perspective:[{perspective:[h,$,Q]}],"perspective-origin":[{"perspective-origin":x()}],rotate:[{rotate:ue()}],"rotate-x":[{"rotate-x":ue()}],"rotate-y":[{"rotate-y":ue()}],"rotate-z":[{"rotate-z":ue()}],scale:[{scale:de()}],"scale-x":[{"scale-x":de()}],"scale-y":[{"scale-y":de()}],"scale-z":[{"scale-z":de()}],"scale-3d":[`scale-3d`],skew:[{skew:fe()}],"skew-x":[{"skew-x":fe()}],"skew-y":[{"skew-y":fe()}],transform:[{transform:[$,Q,``,`none`,`gpu`,`cpu`]}],"transform-origin":[{origin:x()}],"transform-style":[{transform:[`3d`,`flat`]}],translate:[{translate:pe()}],"translate-x":[{"translate-x":pe()}],"translate-y":[{"translate-y":pe()}],"translate-z":[{"translate-z":pe()}],"translate-none":[`translate-none`],zoom:[{zoom:[lv,$,Q]}],accent:[{accent:M()}],appearance:[{appearance:[`none`,`auto`]}],"caret-color":[{caret:M()}],"color-scheme":[{scheme:[`normal`,`dark`,`light`,`light-dark`,`only-dark`,`only-light`]}],cursor:[{cursor:[`auto`,`default`,`pointer`,`wait`,`text`,`move`,`help`,`not-allowed`,`none`,`context-menu`,`progress`,`cell`,`crosshair`,`vertical-text`,`alias`,`copy`,`no-drop`,`grab`,`grabbing`,`all-scroll`,`col-resize`,`row-resize`,`n-resize`,`e-resize`,`s-resize`,`w-resize`,`ne-resize`,`nw-resize`,`se-resize`,`sw-resize`,`ew-resize`,`ns-resize`,`nesw-resize`,`nwse-resize`,`zoom-in`,`zoom-out`,$,Q]}],"field-sizing":[{"field-sizing":[`fixed`,`content`]}],"pointer-events":[{"pointer-events":[`auto`,`none`]}],resize:[{resize:[`none`,``,`y`,`x`]}],"scroll-behavior":[{scroll:[`auto`,`smooth`]}],"scrollbar-thumb-color":[{"scrollbar-thumb":M()}],"scrollbar-track-color":[{"scrollbar-track":M()}],"scrollbar-gutter":[{"scrollbar-gutter":[`auto`,`stable`,`both`]}],"scrollbar-w":[{scrollbar:[`auto`,`thin`,`none`]}],"scroll-m":[{"scroll-m":w()}],"scroll-mx":[{"scroll-mx":w()}],"scroll-my":[{"scroll-my":w()}],"scroll-ms":[{"scroll-ms":w()}],"scroll-me":[{"scroll-me":w()}],"scroll-mbs":[{"scroll-mbs":w()}],"scroll-mbe":[{"scroll-mbe":w()}],"scroll-mt":[{"scroll-mt":w()}],"scroll-mr":[{"scroll-mr":w()}],"scroll-mb":[{"scroll-mb":w()}],"scroll-ml":[{"scroll-ml":w()}],"scroll-p":[{"scroll-p":w()}],"scroll-px":[{"scroll-px":w()}],"scroll-py":[{"scroll-py":w()}],"scroll-ps":[{"scroll-ps":w()}],"scroll-pe":[{"scroll-pe":w()}],"scroll-pbs":[{"scroll-pbs":w()}],"scroll-pbe":[{"scroll-pbe":w()}],"scroll-pt":[{"scroll-pt":w()}],"scroll-pr":[{"scroll-pr":w()}],"scroll-pb":[{"scroll-pb":w()}],"scroll-pl":[{"scroll-pl":w()}],"snap-align":[{snap:[`start`,`end`,`center`,`align-none`]}],"snap-stop":[{snap:[`normal`,`always`]}],"snap-type":[{snap:[`none`,`x`,`y`,`both`]}],"snap-strictness":[{snap:[`mandatory`,`proximity`]}],touch:[{touch:[`auto`,`none`,`manipulation`]}],"touch-x":[{"touch-pan":[`x`,`left`,`right`]}],"touch-y":[{"touch-pan":[`y`,`up`,`down`]}],"touch-pz":[`touch-pinch-zoom`],select:[{select:[`none`,`text`,`all`,`auto`]}],"will-change":[{"will-change":[`auto`,`scroll`,`contents`,`transform`,$,Q]}],fill:[{fill:[`none`,...M()]}],"stroke-w":[{stroke:[cv,Dv,bv,xv]}],stroke:[{stroke:[`none`,...M()]}],"forced-color-adjust":[{"forced-color-adjust":[`auto`,`none`]}]},conflictingClassGroups:{"container-named":[`container-type`],overflow:[`overflow-x`,`overflow-y`],overscroll:[`overscroll-x`,`overscroll-y`],inset:[`inset-x`,`inset-y`,`inset-bs`,`inset-be`,`start`,`end`,`top`,`right`,`bottom`,`left`],"inset-x":[`right`,`left`],"inset-y":[`top`,`bottom`],flex:[`basis`,`grow`,`shrink`],gap:[`gap-x`,`gap-y`],p:[`px`,`py`,`ps`,`pe`,`pbs`,`pbe`,`pt`,`pr`,`pb`,`pl`],px:[`pr`,`pl`],py:[`pt`,`pb`],m:[`mx`,`my`,`ms`,`me`,`mbs`,`mbe`,`mt`,`mr`,`mb`,`ml`],mx:[`mr`,`ml`],my:[`mt`,`mb`],size:[`w`,`h`],"font-size":[`leading`],"fvn-normal":[`fvn-ordinal`,`fvn-slashed-zero`,`fvn-figure`,`fvn-spacing`,`fvn-fraction`],"fvn-ordinal":[`fvn-normal`],"fvn-slashed-zero":[`fvn-normal`],"fvn-figure":[`fvn-normal`],"fvn-spacing":[`fvn-normal`],"fvn-fraction":[`fvn-normal`],"line-clamp":[`display`,`overflow`],rounded:[`rounded-s`,`rounded-e`,`rounded-t`,`rounded-r`,`rounded-b`,`rounded-l`,`rounded-ss`,`rounded-se`,`rounded-ee`,`rounded-es`,`rounded-tl`,`rounded-tr`,`rounded-br`,`rounded-bl`],"rounded-s":[`rounded-ss`,`rounded-es`],"rounded-e":[`rounded-se`,`rounded-ee`],"rounded-t":[`rounded-tl`,`rounded-tr`],"rounded-r":[`rounded-tr`,`rounded-br`],"rounded-b":[`rounded-br`,`rounded-bl`],"rounded-l":[`rounded-tl`,`rounded-bl`],"border-spacing":[`border-spacing-x`,`border-spacing-y`],"border-w":[`border-w-x`,`border-w-y`,`border-w-s`,`border-w-e`,`border-w-bs`,`border-w-be`,`border-w-t`,`border-w-r`,`border-w-b`,`border-w-l`],"border-w-x":[`border-w-r`,`border-w-l`],"border-w-y":[`border-w-t`,`border-w-b`],"border-color":[`border-color-x`,`border-color-y`,`border-color-s`,`border-color-e`,`border-color-bs`,`border-color-be`,`border-color-t`,`border-color-r`,`border-color-b`,`border-color-l`],"border-color-x":[`border-color-r`,`border-color-l`],"border-color-y":[`border-color-t`,`border-color-b`],translate:[`translate-x`,`translate-y`,`translate-none`],"translate-none":[`translate`,`translate-x`,`translate-y`,`translate-z`],"scroll-m":[`scroll-mx`,`scroll-my`,`scroll-ms`,`scroll-me`,`scroll-mbs`,`scroll-mbe`,`scroll-mt`,`scroll-mr`,`scroll-mb`,`scroll-ml`],"scroll-mx":[`scroll-mr`,`scroll-ml`],"scroll-my":[`scroll-mt`,`scroll-mb`],"scroll-p":[`scroll-px`,`scroll-py`,`scroll-ps`,`scroll-pe`,`scroll-pbs`,`scroll-pbe`,`scroll-pt`,`scroll-pr`,`scroll-pb`,`scroll-pl`],"scroll-px":[`scroll-pr`,`scroll-pl`],"scroll-py":[`scroll-pt`,`scroll-pb`],touch:[`touch-x`,`touch-y`,`touch-pz`],"touch-x":[`touch`],"touch-y":[`touch`],"touch-pz":[`touch`]},conflictingClassGroupModifiers:{"font-size":[`leading`]},postfixLookupClassGroups:[`container-type`],orderSensitiveModifiers:[`*`,`**`,`after`,`backdrop`,`before`,`details-content`,`file`,`first-letter`,`first-line`,`marker`,`placeholder`,`selection`]}});function Gv(...e){return Wv(h_(e))}var Kv=v_(`inline-flex h-9 shrink-0 items-center justify-center gap-2 whitespace-nowrap rounded-md border px-3 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-400 disabled:pointer-events-none disabled:opacity-50 dark:focus-visible:ring-zinc-500`,{variants:{variant:{primary:`border-slate-900 bg-slate-950 text-white hover:bg-slate-800 dark:border-zinc-100 dark:bg-zinc-50 dark:text-zinc-950 dark:hover:bg-zinc-200`,secondary:`border-slate-200 bg-white text-slate-900 hover:bg-slate-50 dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-100 dark:hover:bg-zinc-900`,ghost:`border-transparent bg-transparent text-slate-700 hover:bg-slate-100 dark:text-zinc-300 dark:hover:bg-zinc-900`},size:{sm:`h-8 px-2 text-xs`,md:`h-9 px-3 text-sm`,icon:`h-9 w-9 px-0`}},defaultVariants:{variant:`secondary`,size:`md`}});function qv({className:e,variant:t,size:n,...r}){return(0,z.jsx)(`button`,{className:Gv(Kv({variant:t,size:n}),e),type:`button`,...r})}function Jv({className:e,...t}){return(0,z.jsx)(`section`,{className:Gv(`rounded-lg border border-slate-200/80 bg-white/95 text-slate-950 shadow-[0_1px_2px_rgba(15,23,42,0.04)] dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-50`,e),...t})}function Yv({className:e,...t}){return(0,z.jsx)(`div`,{className:Gv(`p-4 pt-0`,e),...t})}function Xv(e){return{blockingTodoCount:e.blockingTodoCount,goalNotifications:e.goalNotifications,goals:e.goals,openUserTodoCount:e.openUserTodoCount,systemHealth:e.systemHealth,userTodos:e.userTodos,workers:e.workers}}function Zv(e,t){return e.goals.find(e=>e.goalId===t)?.title??t}function Qv(e){return e.activationState===`stopped`||e.state===`已停止`?`stopped`:e.state===`已完成`?`history`:e.needsYou||e.state===`等你`?`needs_you`:e.state===`推进中`||e.state===`需修复`?`running`:e.state===`安静运行`?`observing`:`scheduled`}function $v(e){let t=e;return t>=1e6?`${(t/1e6).toFixed(1)}M`:t>=1e3?`${(t/1e3).toFixed(1)}k`:String(t)}function ey(e){return`$${e.toFixed(2)}`}function ty(e){let t=e;return t>=36e5?`${(t/36e5).toFixed(1)}h`:t>=6e4?`${(t/6e4).toFixed(1)}m`:t>=1e3?`${Math.round(t/1e3)}s`:`${t}ms`}function ny(e,t,n){return e==null?t:n(e)}function ry(e){return!!(e&&[e.tokens24h,e.tokens7d,e.costUsd24h,e.costUsd7d,e.durationMs24h,e.durationMs7d].some(e=>e!=null))}function iy(e,t){if(!ry(e))return null;let n=(e,n,r,i)=>{let a=[n==null?null:`${$v(n)} ${t.tokens}`,r==null?null:`${t.cost}: ${ey(r)}`,i==null?null:`${t.duration}: ${ty(i)}`].filter(e=>e!==null);return a.length?`${e} ${a.join(` · `)}`:null};return n(t.period7d,e.tokens7d,e.costUsd7d,e.durationMs7d)??n(t.period24h,e.tokens24h,e.costUsd24h,e.durationMs24h)}function ay({ariaLabel:e,className:t,icon:n,onChange:r,options:i,prefixLabel:a,value:o}){let s=(0,R.useId)(),c=(0,R.useRef)(null),l=(0,R.useRef)(null),u=(0,R.useRef)(new Map),[d,f]=(0,R.useState)(!1),[p,m]=(0,R.useState)(o),h=i.find(e=>e.value===o)??i[0],g=i.filter(e=>!e.disabled);(0,R.useEffect)(()=>{if(!d)return;let e=e=>{c.current?.contains(e.target)||f(!1)};return document.addEventListener(`pointerdown`,e),()=>document.removeEventListener(`pointerdown`,e)},[d]),(0,R.useEffect)(()=>{d&&u.current.get(p)?.focus()},[p,d]);function _(e){m(e)}function v(e=`selected`){let t=e===`last`?g.at(-1):g[0],n=e===`selected`&&h&&!h.disabled?h:t;n&&(f(!0),_(n.value))}function y({restoreFocus:e=!1}={}){f(!1),e&&l.current?.focus()}function b(e){e.disabled||(r(e.value),y({restoreFocus:!0}))}function x(e){if(!g.length)return;let t=g.findIndex(e=>e.value===p),n=t<0?0:(t+e+g.length)%g.length;_(g[n].value)}function S(e){e.key===`ArrowDown`||e.key===`Enter`||e.key===` `?(e.preventDefault(),v(`selected`)):e.key===`ArrowUp`&&(e.preventDefault(),v(`last`))}function C(e,t){if(e.key===`ArrowDown`)e.preventDefault(),x(1);else if(e.key===`ArrowUp`)e.preventDefault(),x(-1);else if(e.key===`Home`)e.preventDefault(),g[0]&&_(g[0].value);else if(e.key===`End`){e.preventDefault();let t=g.at(-1);t&&_(t.value)}else e.key===`Enter`||e.key===` `?(e.preventDefault(),b(t)):e.key===`Escape`?(e.preventDefault(),y({restoreFocus:!0})):e.key===`Tab`&&y()}let w;return(0,z.jsxs)(`div`,{className:`personal-select${t?` ${t}`:``}`,ref:c,children:[(0,z.jsxs)(`button`,{"aria-controls":s,"aria-expanded":d,"aria-haspopup":`listbox`,"aria-label":e,className:`personal-select-trigger`,"data-value":o,onClick:()=>d?y():v(),onKeyDown:S,ref:l,role:`combobox`,type:`button`,children:[n?(0,z.jsx)(`span`,{className:`personal-select-icon`,children:n}):null,(0,z.jsxs)(`span`,{className:`personal-select-value`,children:[a?(0,z.jsx)(`small`,{children:a}):null,(0,z.jsx)(`span`,{children:h?.label??o})]}),(0,z.jsx)(qp,{"aria-hidden":!0,className:d?`is-open`:void 0,size:14})]}),d?(0,z.jsx)(`div`,{"aria-label":e,className:`personal-select-listbox`,id:s,role:`listbox`,children:i.map(e=>{let t=e.group&&e.group!==w;return w=e.group,(0,z.jsxs)(`div`,{className:`personal-select-option-wrap`,children:[t?(0,z.jsx)(`div`,{className:`personal-select-group-label`,children:e.group}):null,(0,z.jsxs)(`button`,{"aria-disabled":e.disabled||void 0,"aria-selected":e.value===o,className:`personal-select-option`,disabled:e.disabled,id:`${s}-${e.value.replace(/[^a-z0-9_-]/gi,`-`)}`,onClick:()=>b(e),onFocus:()=>m(e.value),onKeyDown:t=>C(t,e),ref:t=>{t?u.current.set(e.value,t):u.current.delete(e.value)},role:`option`,tabIndex:e.value===p?0:-1,type:`button`,children:[(0,z.jsx)(`span`,{children:e.label}),e.value===o?(0,z.jsx)(Kp,{"aria-hidden":!0,size:15}):null]})]},e.value)})}):null]})}function oy({agents:e,managerChatOpen:t,mobileNavigationOpen:n,onOpenGoalCapabilities:r,onOpenGoalDetail:i,onOpenManagerChat:a,onRefresh:o,onOpenNavigation:s,onSelectGoalTab:c,onSelectAgent:l,onReturnManagerHome:u,refreshState:d,readOnlySourceLabel:f,selectedAgentId:p,selectedGoal:m,selectedGoalTab:h}){let{locale:g,t:_}=Ji(),[v,y]=(0,R.useState)(!1),b=(0,R.useRef)(null),x=(0,R.useRef)(null);(0,R.useEffect)(()=>{if(!v)return;function e(e){x.current?.contains(e.target)||y(!1)}function t(e){e.key===`Escape`&&(y(!1),b.current?.focus())}return document.addEventListener(`pointerdown`,e),document.addEventListener(`keydown`,t),()=>{document.removeEventListener(`pointerdown`,e),document.removeEventListener(`keydown`,t)}},[v]),(0,R.useEffect)(()=>y(!1),[m?.goalId]);function S(e){y(!1),e?.()}let C=m?iy(m.usage,{cost:_(`drawer.costShort`),duration:_(`drawer.durationShort`),period24h:_(`drawer.period24h`),period7d:_(`drawer.period7d`),tokens:_(`drawer.tokensShort`)}):null;return(0,z.jsxs)(`header`,{className:`personal-channel-header`,children:[(0,z.jsx)(`button`,{"aria-expanded":n??!1,"aria-label":_(`header.openGoalNavigation`),className:`personal-icon-button personal-mobile-menu`,onClick:s,type:`button`,children:(0,z.jsx)(_m,{size:18})}),(0,z.jsxs)(`div`,{className:`personal-channel-title`,children:[(0,z.jsx)(`h1`,{children:m?.title??_(`header.manager`)}),(0,z.jsx)(`p`,{children:m?m.loadState?_(m.loadState===`error`?`startup.goalError`:`startup.goalLoading`):`${m.agentLaneCount&&m.agentLaneCount>1?_(`header.workAgentCount`,{count:m.agentLaneCount}):m.agentLabel??m.agentId} · ${m.loadState?_(m.loadState===`error`?`startup.goalError`:`startup.goalLoading`):Yi(m.state,g)}${C?` · ${C}`:``} · ${m.nextSentence}`:_(`header.managerDescription`)})]}),m?(0,z.jsxs)(`nav`,{"aria-label":_(`header.goalView`),className:`personal-goal-tabs`,children:[(0,z.jsx)(`button`,{"aria-current":h===`chat`?`page`:void 0,onClick:()=>c(`chat`),type:`button`,children:_(`header.chat`)}),(0,z.jsx)(`button`,{"aria-current":h===`tasks`?`page`:void 0,onClick:()=>c(`tasks`),type:`button`,children:_(`header.tasks`)}),(0,z.jsx)(`button`,{"aria-current":h===`files`?`page`:void 0,onClick:()=>c(`files`),type:`button`,children:_(`header.files`)})]}):(0,z.jsxs)(`nav`,{"aria-label":_(`header.managerView`),className:`personal-goal-tabs`,children:[(0,z.jsx)(`button`,{"aria-current":t?void 0:`page`,onClick:u,type:`button`,children:_(`header.managerOverview`)}),(0,z.jsx)(`button`,{"aria-current":t?`page`:void 0,onClick:a,type:`button`,children:_(`header.chat`)})]}),(0,z.jsxs)(`div`,{className:`personal-channel-actions`,children:[m&&i&&r?(0,z.jsxs)(`div`,{className:`personal-goal-tools`,ref:x,children:[(0,z.jsxs)(`button`,{"aria-expanded":v,"aria-haspopup":`menu`,"aria-label":_(`header.goalSettingsDescription`),className:`personal-goal-tools-trigger`,onClick:()=>y(e=>!e),ref:b,title:_(`header.goalSettingsDescription`),type:`button`,children:[(0,z.jsx)(Lm,{"aria-hidden":!0,size:16}),(0,z.jsx)(`span`,{children:_(`header.goalSettings`)}),(0,z.jsx)(qp,{"aria-hidden":!0,size:13})]}),v?(0,z.jsxs)(`fieldset`,{"aria-label":_(`header.goalSettings`),className:`personal-goal-tools-menu`,children:[(0,z.jsxs)(`button`,{onClick:()=>S(i),type:`button`,children:[(0,z.jsx)(dm,{"aria-hidden":!0,size:17}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:_(`header.goalDetails`)}),(0,z.jsx)(`small`,{children:_(`header.goalDetailsDescription`)})]})]}),(0,z.jsxs)(`button`,{onClick:()=>S(r),type:`button`,children:[(0,z.jsx)(Lm,{"aria-hidden":!0,size:17}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:_(`header.goalCapabilities`)}),(0,z.jsx)(`small`,{children:_(`header.goalCapabilitiesDescription`)})]})]})]}):null]}):null,f?(0,z.jsxs)(`span`,{className:`personal-read-only-source`,title:_(`header.readOnlySourceDescription`,{source:f}),children:[(0,z.jsx)(am,{size:15}),f,(0,z.jsx)(`small`,{children:_(`common.readOnly`)})]}):(0,z.jsx)(ay,{ariaLabel:_(`header.selectChatRuntime`),className:`personal-agent-select`,icon:(0,z.jsx)(Up,{size:16}),onChange:l,options:e.map(e=>({disabled:!e.available,label:`${e.label}${e.available?``:` · ${_(`header.agentUnavailable`)}`}`,value:e.agentId})),prefixLabel:_(`header.chatRuntime`),value:p}),(0,z.jsxs)(`span`,{className:`personal-live-indicator`,children:[(0,z.jsx)(`i`,{}),_(`header.live`)]}),o?(0,z.jsxs)(`span`,{className:`personal-refresh-control is-${d??`idle`}`,children:[d===`loading`?(0,z.jsx)(`small`,{children:_(`header.refreshing`)}):d===`done`?(0,z.jsx)(`small`,{children:_(`header.refreshDone`)}):d===`error`?(0,z.jsx)(`small`,{children:_(`header.refreshFailed`)}):null,(0,z.jsx)(`button`,{"aria-label":_(d===`loading`?`header.refreshing`:`header.refresh`),className:`personal-icon-button`,disabled:d===`loading`,onClick:o,type:`button`,children:(0,z.jsx)(Om,{className:d===`loading`?`is-spinning`:void 0,size:17})})]}):null]})]})}function sy({attention:e,onSelect:t}){let{t:n}=Ji(),r=Zi(e.updatedAt,n);return(0,z.jsxs)(`button`,{className:`personal-timeline-row personal-attention-row`,"data-testid":`personal-browse-row`,onClick:t,type:`button`,children:[(0,z.jsx)(`span`,{className:`personal-row-icon is-attention`,children:(0,z.jsx)(Xp,{size:18})}),(0,z.jsxs)(`span`,{className:`personal-row-copy`,children:[(0,z.jsxs)(`small`,{children:[e.goalTitle??e.goalId,` · `,n(`home.lane.needsYou`),r?` · ${n(`tasks.waitingAge`,{age:r})}`:``]}),(0,z.jsx)(`strong`,{children:e.text})]}),(0,z.jsx)(`span`,{className:`personal-priority-dot is-${e.priority??(e.blocking?`high`:`medium`)}`}),(0,z.jsx)(`span`,{className:`personal-row-status ${e.blocking?`is-blocking`:`is-pending`}`,children:e.blocking?n(`tasks.blocked`):n(`tasks.pending`)}),(0,z.jsx)(Jp,{size:17})]})}var cy=/(`[^`\n]+`)|(\*\*[^*\n]+(\*[^*\n]*)?\*\*)|(\[[^\]\n]{1,120}\]\(https?:\/\/[^)\s]+\))/g;function ly(e,t){let n=[],r=0,i=0;for(let a of e.matchAll(cy)){let o=a.index??0;o>r&&n.push(e.slice(r,o));let s=a[0],c=`${t}-i${i++}`;if(s.startsWith("`"))n.push((0,z.jsx)(`code`,{className:`personal-md-code`,children:s.slice(1,-1)},c));else if(s.startsWith(`**`))n.push((0,z.jsx)(`strong`,{children:s.slice(2,-2)},c));else{let e=s.indexOf(`](`),t=s.slice(1,e),r=s.slice(e+2,-1);n.push((0,z.jsx)(`a`,{className:`personal-md-link`,href:r,rel:`noreferrer`,target:`_blank`,children:t},c))}r=o+s.length}return r=4))throw e;await new Promise(e=>globalThis.setTimeout(e,250*2**(i-1)))}}if(!a)throw new _h(`Agent 事件流连接已断开。`,{reconnect_attempts:i})}async function Rh(e,t){return Dh(`/api/chat/sessions/${e}/turns/${t}/interrupt`,{method:`POST`,body:`{}`})}async function zh(e,t,n={}){let r=await Fh(e,t,n.clientTurnId??crypto.randomUUID(),n.attachments);return n.onPhase?.(`turn.accepted`,r.turn_id),Bh(e,r.turn_id,r.events_url,n)}async function Bh(e,t,n,r={}){let i=null,a={failure:null,interrupted:null};try{await Lh(n,e=>{r.onPhase?.(e.kind,t),(e.kind===`answer.delta`||e.kind===`assistant.delta`)&&r.onDelta?.(String(e.payload.text??``)),e.kind===`agent.phase`&&r.onActivity?.(String(e.payload.label??`Agent 正在处理`)),e.kind===`turn.completed`&&(i=e.payload.response),e.kind===`turn.failed`&&(a.failure=e.payload),e.kind===`turn.interrupted`&&(a.interrupted=e.payload)},r.signal)}catch(i){throw i instanceof _h&&!r.signal?.aborted?new _h(i.message,{...i.payload,events_url:n,reconnectable:!0,session_id:e,turn_id:t}):i}if(a.failure)throw new _h(String(a.failure.message||`Agent 回合失败。`),a.failure);if(a.interrupted)throw new _h(`Agent 回合已中断。`,{...a.interrupted,error_code:`turn_interrupted`,session_id:e,turn_id:t});return{response:dh.parse(i),sessionId:e,turnId:t}}async function Vh(e,t,n={}){return Bh(e,t,`/api/chat/sessions/${e}/turns/${t}/events`,n)}async function Hh(e){let t=fh.parse(await Dh(`/api/chat/sessions/${e}`,{keepalive:!0,method:`DELETE`}));if(t.session_id!==e)throw new _h(`Agent 会话关闭回执与本次请求不一致。`,{session_id:t.session_id});return t}async function Uh(e){return Dh(`/api/chat/sessions/${e}/resume`,{method:`POST`,body:`{}`})}function Wh(e){return{goal_id:e.goalId,enabled:e.enabled,...e.enabled?{max_children:e.maxChildren,allowed_domains:e.allowedDomains}:{}}}function Gh(e,t){let n=e.after.orchestration,r=[...new Set(t.allowedDomains)],i=e.feature_summary.multi_subagent===`enabled`;if(!(e.goal_id===t.goalId&&i===t.enabled&&(t.enabled?n.max_children===t.maxChildren&&JSON.stringify(n.allowed_domains)===JSON.stringify(r):n.spawn_allowed===!1&&n.max_children===0)))throw new _h(`Goal 子代理配置回执与本次请求不一致,界面已停止更新。`,{after:e.after,goal_id:e.goal_id});return e}async function Kh(e){let t=hh.parse(await Dh(`/api/chat/goal-subagents/dry-run`,{method:`POST`,body:JSON.stringify(Wh(e))}));if(!t.dry_run||t.execute||t.written)throw new _h(`Goal 子代理预览返回了非预览回执,已停止进入确认状态。`,{result:t});return Gh(t,e)}async function qh(e,t){let n=hh.parse(await Dh(`/api/chat/goal-subagents/apply`,{method:`POST`,body:JSON.stringify({...Wh(e),preview_id:t})}));if(n.preview_id!==t||n.dry_run||!n.execute)throw new _h(`Goal 子代理写入回执与本次确认不一致,界面已停止更新。`,{result:n});if(n.changed&&(!n.written||!n.global_sync.executed||!n.global_sync.readback.verified))throw new _h(`Goal 子代理设置未通过共享状态读回验证。`,{result:n});return Gh(n,e)}var Jh=J({ok:X(!0),targets:q(J({enabled:K(),provider:W(),target_name:W()}))});async function Yh(){return Jh.parse(await Dh(`/api/chat/goal-channel/targets`)).targets}var Xh=J({ok:K(),blocker:W().optional(),public_summary:W().optional(),status:W().optional()});async function Zh(e){return Xh.parse(await Dh(`/api/chat/goal-channel/setup`,{method:`POST`,body:JSON.stringify({execute:e.execute,goal_id:e.goalId,target:e.target})}))}async function Qh(e){return Xh.parse(await Dh(`/api/chat/goal-channel/configure`,{method:`POST`,body:JSON.stringify({auto_notify_human_gates:e.autoNotify,goal_id:e.goalId})}))}J({schema_version:X(`periodic_report_machine_defaults_v0`),enabled:K(),inheritance:X(`live_machine_default`),profile_preset:W().optional(),route_ref:W().optional(),timezone:W()});var $h=J({schema_version:X(`loopx_machine_configuration_v0`),namespaces:gd(W(),gd(W(),id()))}),eg=J({namespace:W(),title:W(),description:W(),schema_versions:q(W()).min(1),configuration_template:gd(W(),id()),template_status:Y([`ready`,`schema_only`])}),tg=J({schema_version:X(`machine_configuration_catalog_v0`),namespaces:q(eg)}),ng=J({key:W(),label:W(),description:W(),input_kind:Y([`boolean`,`number`,`select`,`string_list`,`text`]),required:K(),minimum:G().int().optional(),maximum:G().int().optional(),options:q(W()).optional()}),rg=J({schema_version:X(`capability_configuration_editor_v0`),editable:K(),supported_scopes:q(Y([`goal`,`machine`])),writable_scopes:q(Y([`goal`,`machine`])),fields:q(ng),read_only_reason:W().optional()}),ig=J({schema_version:X(`capability_configuration_catalog_v0`),capabilities:q(J({capability_id:W(),display_name:W(),description:W(),available_scopes:q(Y([`goal`,`machine`])),machine_namespace:W().optional(),goal_feature_id:W().optional(),effective_value_policy:X(`goal_override_over_live_machine_default`).optional(),availability:W().optional(),default:gd(W(),id()).optional(),current:gd(W(),id()).optional(),machine_current:gd(W(),id()).optional(),effective_configuration:J({schema_version:X(`capability_configuration_resolution_v0`),capability_id:W(),source:Y([`goal_override`,`machine_default`,`capability_default`,`not_configured`]),configuration:gd(W(),id()).nullable(),inherited:K(),goal_override_present:K(),machine_default_present:K(),effective_revision:W()}).optional(),documentation:gd(W(),id()).optional(),configuration_editor:rg}))}),ag=J({ok:X(!0),schema_version:X(`goal_configuration_inspection_v0`),status:X(`configured`),goal_id:W(),revision:W(),available_capabilities:q(W()),capability_catalog:ig}),og=J({ok:X(!0),goal_id:W(),capability_id:W(),changed_fields:q(W()),goal_configuration:gd(W(),id()).nullable(),capability_catalog:ig}),sg=og.extend({schema_version:X(`goal_configuration_update_plan_v0`),status:X(`preview`),action:Y([`create`,`update`,`delete`,`unchanged`]),current_revision:W(),desired_revision:W(),base_revision:W(),plan_revision:W(),writes_required:G().int().nonnegative()}),cg=ud([og.extend({schema_version:X(`goal_configuration_transaction_v0`),status:Y([`applied`,`unchanged`]),plan_revision:W(),applied_revision:W(),readback_verified:X(!0)}),J({ok:X(!1),schema_version:X(`goal_configuration_transaction_v0`),status:X(`partial_write`),goal_id:W(),capability_id:W(),plan_revision:W(),applied_revision:W().nullable(),source_written:X(!0),shared_sync_pending:X(!0),readback_verified:K(),changed_fields:q(W()),goal_configuration:gd(W(),id()).nullable(),capability_catalog:ig,error:W(),recommended_action:W()})]),lg=J({ok:X(!0),available_namespaces:q(W()),namespace_catalog:tg.optional().default({schema_version:`machine_configuration_catalog_v0`,namespaces:[]}),capability_catalog:ig,changed_namespaces:q(W()).optional().default([]),machine_configuration:$h.nullable().optional()}),ug=lg.extend({schema_version:X(`machine_configuration_inspection_v0`),status:Y([`configured`,`absent`]),revision:W()}),dg=lg.extend({schema_version:X(`machine_configuration_update_plan_v0`),status:X(`preview`),action:Y([`create`,`update`,`delete`,`unchanged`]),current_revision:W(),desired_revision:W(),plan_revision:W(),writes_required:G().int().nonnegative(),machine_configuration:$h.nullable()}),fg=lg.extend({schema_version:X(`machine_configuration_transaction_v0`),status:Y([`applied`,`unchanged`]),plan_revision:W(),transaction_id:W().nullable(),readback_verified:X(!0),rollback_available:K(),applied_revision:W().optional(),prior_revision:W().optional()}),pg=lg.extend({schema_version:X(`machine_configuration_rollback_plan_v0`),status:X(`preview`),action:Y([`delete`,`restore`,`unchanged`,`blocked`]),reason:W(),transaction_id:W(),plan_revision:W(),rollback_allowed:K(),writes_required:G().int().nonnegative()}),mg=lg.extend({schema_version:X(`machine_configuration_rollback_receipt_v0`),status:Y([`rolled_back`,`unchanged`]),transaction_id:W(),plan_revision:W(),rollback_id:W().nullable(),readback_verified:X(!0)});async function hg(){return ug.parse(await Dh(`/api/chat/machine-configuration`))}async function gg(e){let t=new URLSearchParams({goal_id:e});return ag.parse(await Dh(`/api/chat/goal-configuration?${t.toString()}`))}async function _g(e,t,n){return sg.parse(await Dh(`/api/chat/goal-configuration/preview`,{method:`POST`,body:JSON.stringify({goal_id:e,capability_id:t,configuration:n})}))}async function vg(e,t,n,r){return cg.parse(await Dh(`/api/chat/goal-configuration/apply`,{method:`POST`,body:JSON.stringify({goal_id:e,capability_id:t,configuration:n,expected_plan_revision:r})}))}async function yg(e,t){return dg.parse(await Dh(`/api/chat/machine-configuration/preview`,{method:`POST`,body:JSON.stringify({namespace:e,namespace_configuration:t})}))}async function bg(e,t,n){return fg.parse(await Dh(`/api/chat/machine-configuration/apply`,{method:`POST`,body:JSON.stringify({expected_plan_revision:n,namespace:e,namespace_configuration:t})}))}async function xg(e){return dg.parse(await Dh(`/api/chat/machine-configuration/preview`,{method:`POST`,body:JSON.stringify({namespace:e,operation:`remove`})}))}async function Sg(e,t){return fg.parse(await Dh(`/api/chat/machine-configuration/apply`,{method:`POST`,body:JSON.stringify({expected_plan_revision:t,namespace:e,operation:`remove`})}))}async function Cg(e){return pg.parse(await Dh(`/api/chat/machine-configuration/rollback`,{method:`POST`,body:JSON.stringify({execute:!1,transaction_id:e})}))}async function wg(e,t){return mg.parse(await Dh(`/api/chat/machine-configuration/rollback`,{method:`POST`,body:JSON.stringify({execute:!0,expected_plan_revision:t,transaction_id:e})}))}var Tg=J({ok:X(!0),goals:q(J({goal_id:W(),repository:J({branch:W(),identity:W(),label:W(),read_only:X(!0)})}))});async function Eg(){return Tg.parse(await Dh(`/api/chat/goals/contexts`)).goals}var Dg=J({ok:X(!0),apps:q(J({active:K(),app_ref:W(),brand:W(),health_error_code:W().nullable().default(null),label:W(),ready:K(),reply_ready:K().default(!1)}))});async function Og(){return Dg.parse(await Dh(`/api/chat/lark/apps`)).apps}var kg=J({ok:X(!0),app_ref:W(),error:W().nullable(),setup_id:W(),status:Y([`starting`,`waiting_for_feishu`,`ready`,`failed`,`cancelled`]),verification_url:W().url().nullable()});async function Ag(e){return kg.parse(await Dh(`/api/chat/lark/app-setups`,{method:`POST`,body:JSON.stringify({app_ref:e.appRef,brand:e.brand})}))}async function jg(e){return kg.parse(await Dh(`/api/chat/lark/app-setups/${encodeURIComponent(e)}`))}async function Mg(e){return kg.parse(await Dh(`/api/chat/lark/app-setups/${encodeURIComponent(e)}`,{method:`DELETE`}))}var Ng=[`invalid_event`,`binding_unavailable`,`chat_mismatch`,`topic_mismatch`,`route_ambiguous`,`self_message`,`invalid_routing_state`,`not_addressed`],Pg=J({ok:X(!0),chats:q(J({chat_id:W(),chat_name:W()}))});async function Fg(e,t){let n=new URLSearchParams({app_ref:e});return t&&n.set(`query`,t),Pg.parse(await Dh(`/api/chat/lark/chats?${n.toString()}`)).chats}var Ig=J({ok:X(!0),connections:q(J({agent_id:W().nullable().default(null),connection_id:W(),app_label:W(),app_ref:W(),capture_scope:Y([`addressed_only`,`configured_chat_all`]).default(`addressed_only`),chat_name:W(),enabled:K(),goal_id:W(),goal_title:W(),health_error_code:W().nullable().default(null),history_permission_guidance:J({action:X(`enable_application_scopes_and_publish`),api_document_url:W().url(),capability:X(`group_history_pagination`),identity:X(`bot`),required_scopes:md([X(`im:message.group_msg`),X(`im:message.group_msg.include_bot:read`)]),schema_version:X(`lark_bot_group_history_permission_guidance_v0`)}).nullable().default(null),incoming_mode:Y([`mentions`,`all`]),ingress_mode:Y([`live_steering`,`session_queue`,`async_inbox`,`direct_session`]).default(`async_inbox`),event_count:G().int().nonnegative().default(0),last_event_reason:Y(Ng).nullable().default(null).catch(null),last_event_status:W().nullable().default(null),listener_error_code:W().nullable().default(null),listener_status:Y([`starting`,`listening`,`retrying`,`stopped`]).nullable().default(null),replied_count:G().int().nonnegative().default(0),reply_ready:K().default(!1),reply_mode:X(`topic_reply`),session_bound:K().default(!1),target_ref:W(),topic_name:W(),topic_setup_required:K()}))});async function Lg(){return Ig.parse(await Dh(`/api/chat/lark/connections`)).connections}async function Rg(e){return Xh.parse(await Dh(`/api/chat/lark/connections`,{method:`POST`,body:JSON.stringify({...e.agentBindings?{agent_bindings:e.agentBindings.map(e=>({agent_id:e.agentId,app_ref:e.appRef}))}:{},...e.agentId?{agent_id:e.agentId}:{},...e.appRef?{app_ref:e.appRef}:{},capture_scope:e.captureScope,chat_id:e.chatId,chat_name:e.chatName,execute:e.execute,goal_id:e.goalId,incoming_mode:e.incomingMode,ingress_mode:e.ingressMode,reply_mode:e.replyMode})}))}async function zg(e,t){let n=new URLSearchParams({goal_id:e,connection_id:t});return Xh.parse(await Dh(`/api/chat/lark/connections?${n.toString()}`,{method:`DELETE`}))}function Bg(e){return{loadedUrl:null,projectionRevision:0,requestedUrl:e,selectionRevision:0,requestGeneration:0}}function Vg(e,t){return e.selectionRevision+=1,e.requestedUrl=t,e.selectionRevision}function Hg(e,t,n){if(n.background)return e.requestedUrl!==null||e.loadedUrl!==t?null:(e.requestGeneration+=1,{background:!0,projectionRevision:e.projectionRevision,selectionRevision:e.selectionRevision,url:t,generation:e.requestGeneration});let r=n.selectionRevision??e.selectionRevision+1;return n.selectionRevision!==void 0&&e.selectionRevision!==r?null:(e.selectionRevision=r,e.projectionRevision+=1,e.requestedUrl=t,e.requestGeneration+=1,{background:!1,projectionRevision:e.projectionRevision,selectionRevision:r,url:t,generation:e.requestGeneration})}function Ug(e,t){return t.generation===e.requestGeneration&&e.projectionRevision===t.projectionRevision&&e.selectionRevision===t.selectionRevision}function Wg(e,t){return Ug(e,t)&&(!t.background||e.requestedUrl===null&&e.loadedUrl===t.url)}function Gg(e,t,n){return t.get(e)===n}function Kg(e,t,n,r){return e.filter(e=>Gg(r(e),n,t))}function qg(e,t,n){let r=new Set,i=[];for(let a of[...e,...t]){let e=n(a);e==null||r.has(e)||(r.add(e),i.push(a))}return i}var Jg=[`runs_24h`,`runs_7d`,`quota_spend_slots_24h`,`quota_spend_slots_7d`,`automation_run_count_24h`,`automation_run_count_7d`,`progress_signal_run_count_24h`,`progress_signal_run_count_7d`],Yg=[`input_tokens_24h`,`input_tokens_7d`,`output_tokens_24h`,`output_tokens_7d`,`cache_tokens_24h`,`cache_tokens_7d`,`cost_usd_24h`,`cost_usd_7d`,`duration_ms_24h`,`duration_ms_7d`],Xg=[`accounting`,`decision`,`evidence`,`state`,`work`],Zg={accounting:0,decision:0,evidence:0,state:0,work:0},Qg={runs_24h:0,runs_7d:0,quota_spend_slots_24h:0,quota_spend_slots_7d:0,automation_run_count_24h:0,automation_run_count_7d:0,progress_signal_run_count_24h:0,progress_signal_run_count_7d:0};function $g(e,t){let n={...e};for(let r of Jg)n[r]=(Number(e[r])||0)+(Number(t[r])||0);for(let r of Yg)(e[r]!==void 0||t[r]!==void 0)&&(n[r]=(e[r]??0)+(t[r]??0));return n}function e_(e,t){return!e.length||t<=0?e:e.map(e=>({...e,project_share_24h:Math.round((Number(e.runs_24h)||0)/t*1e3)/1e3}))}function t_(e,t){let n={...e};for(let r of Xg)n[r]=(e[r]??0)+(t[r]??0);return n}function n_(e){let t={events_24h:0,events_7d:0,by_class_24h:{...Zg},by_class_7d:{...Zg}};for(let n of e)t.events_24h+=n.events_24h,t.events_7d+=n.events_7d,t.by_class_24h=t_(t.by_class_24h,n.by_class_24h),t.by_class_7d=t_(t.by_class_7d,n.by_class_7d);return t}function r_(e,t,n){if(!e&&!t)return null;let r=Kg(e?.goals??[],`active`,n,e=>e.goal_id),i=Kg(t?.goals??[],`stopped`,n,e=>e.goal_id),a=qg(r,i,e=>e.goal_id),o=n_(r),s=n_(i),c={events_24h:o.events_24h+s.events_24h,events_7d:o.events_7d+s.events_7d,by_class_24h:t_(o.by_class_24h,s.by_class_24h),by_class_7d:t_(o.by_class_7d,s.by_class_7d)};return{...e??t,goals:a,sample_run_count:(e?.sample_run_count??0)+(t?.sample_run_count??0),totals:c}}function i_(e,t,n){if(!e&&!t)return null;let r=qg([...Kg(e?.items??[],`active`,n,e=>e.goal_id),...Kg(t?.items??[],`stopped`,n,e=>e.goal_id)],[],e=>`${e.goal_id}:${e.decision_kind??``}:${e.decision_at??``}`),i={decision_count:(e?.summary.decision_count??0)+(t?.summary.decision_count??0),stale_count:r.filter(e=>e.stale_by_age).length,rebase_required_count:(e?.summary.rebase_required_count??0)+(t?.summary.rebase_required_count??0),fresh_count:(e?.summary.fresh_count??0)+(t?.summary.fresh_count??0)};return{...e??t,items:r,sample_run_count:(e?.sample_run_count??0)+(t?.sample_run_count??0),summary:i}}function a_(e,t){return qg([...e,...t].sort((e,t)=>t.generated_at.localeCompare(e.generated_at)),[],e=>`${e.goal_id}:${e.generated_at}:${e.classification??``}`)}function o_(e,t,n){let r=qg(Kg(e.items,`active`,n,e=>e.goal_id),Kg(t.items,`stopped`,n,e=>e.goal_id),e=>e.goal_id);return{...e,item_count:r.length,items:r,needs_controller:r.filter(e=>e.waiting_on===`controller`).length,needs_codex:r.filter(e=>e.waiting_on===`codex`).length,needs_user_or_controller:r.filter(e=>[`user_or_controller`,`controller`].includes(e.waiting_on)).length,watching_external_evidence:r.filter(e=>e.waiting_on===`external_evidence`).length}}function s_(e){let t=e.todo_id?.trim()||``;return t?`${e.goal_id}:${t}`:`${e.goal_id}:synthetic:${e.role??``}:${e.index??``}:${e.text??``}`}function c_(e){let t={...Qg};for(let n of e){for(let e of Jg)t[e]+=Number(n[e])||0;for(let e of Yg)n[e]!==void 0&&(t[e]=(t[e]??0)+n[e])}return t}function l_(e,t,n){if(!e&&!t)return null;let r=Kg(e?.items??[],`active`,n,e=>e.goal_id),i=Kg(t?.items??[],`stopped`,n,e=>e.goal_id),a=qg(r,i,s_);return{...e??t,current_projected_count:r.length+i.length,items:a,rollout_event_count:a.reduce((e,t)=>e+(t.event_count??0),0),total_count:a.length}}function u_(e,t,n){if(!e&&!t)return null;let r=Kg(e?.goals??[],`active`,n,e=>e.goal_id),i=Kg(t?.goals??[],`stopped`,n,e=>e.goal_id),a=qg(r,i,e=>e.goal_id),o=$g(c_(r),c_(i));return{...e??t,goals:e_(a,Number(o.runs_24h)||0),sample_run_count:(e?.sample_run_count??0)+(t?.sample_run_count??0),totals:o}}function d_(e,t,n){if(!e&&!t)return null;let r=(e?.agents??[]).filter(e=>e.goal_ids.some(e=>Gg(e,n,`active`))||(e.current_todo?.goal_id?Gg(e.current_todo.goal_id,n,`active`):!1)),i=(t?.agents??[]).filter(e=>e.goal_ids.some(e=>Gg(e,n,`stopped`))||(e.current_todo?.goal_id?Gg(e.current_todo.goal_id,n,`stopped`):!1)),a=qg(r,i,e=>e.agent_id).map(e=>{let t=i.find(t=>t.agent_id===e.agent_id);return t?{...e,goal_ids:Array.from(new Set([...e.goal_ids??[],...t.goal_ids]))}:e});return{...e??t,agents:a,source_summary:(e??t)?.source_summary?{...(e??t).source_summary,projected_agent_count:a.length,registered_agent_count:new Set(a.map(e=>e.agent_id)).size}:(e??t)?.source_summary}}function f_(e,t,n){if(!e&&!t)return null;let r=qg(Kg(e?.goals??[],`active`,n,e=>e.goal_id),Kg(t?.goals??[],`stopped`,n,e=>e.goal_id),e=>e.goal_id);return{...e??t,goals:r}}function p_(e,t){let n=t.goal_projection?.scope;if(n!==`active`&&n!==`stopped`)return t;let r=n,i=t.run_history.goals,a=e.run_history.goals,o=qg(r===`active`?i:a.filter(e=>e.activation_state!==`stopped`),r===`stopped`?i:a.filter(e=>e.activation_state===`stopped`),e=>e.id),s=new Map(o.map(e=>[e.id,e.activation_state])),c=r===`active`?t:e,l=r===`stopped`?t:e,u=e.goal_projection?.registry_revision??null,d=t.goal_projection?.registry_revision??null,f=u===null||d===null||u===d;return{...e,agent_management_projection:d_(c.agent_management_projection,l.agent_management_projection,s),attention_queue:o_(c.attention_queue,l.attention_queue,s),decision_freshness_summary:i_(c.decision_freshness_summary,l.decision_freshness_summary,s),event_ledger_summary:r_(c.event_ledger_summary,l.event_ledger_summary,s),goal_channel_notification_projection:f_(c.goal_channel_notification_projection,l.goal_channel_notification_projection,s),goal_projection:{schema_version:`loopx_goal_projection_scope_v0`,...t.goal_projection,complete:f,projected_goal_count:o.length,registry_goal_count:t.goal_projection?.registry_goal_count??0,scope:`all`},run_history:{...e.run_history,goal_count:o.length,goals:o,recent_runs:a_(c.run_history.recent_runs,l.run_history.recent_runs),run_count:c.run_history.run_count+l.run_history.run_count},todo_index:l_(c.todo_index,l.todo_index,s),usage_summary:u_(c.usage_summary,l.usage_summary,s)}}function m_(e){var t,n,r=``;if(typeof e==`string`||typeof e==`number`)r+=e;else if(typeof e==`object`){if(Array.isArray(e)){var i=e.length;for(t=0;ttypeof e==`boolean`?`${e}`:e===0?`0`:e,__=h_,v_=(e,t)=>n=>{if(t?.variants==null)return __(e,n?.class,n?.className);let{variants:r,defaultVariants:i}=t,a=Object.keys(r).map(e=>{let t=n?.[e],a=i?.[e];if(t===null)return null;let o=g_(t)||g_(a);return r[e][o]}),o=n&&Object.entries(n).reduce((e,t)=>{let[n,r]=t;return r===void 0||(e[n]=r),e},{});return __(e,a,t?.compoundVariants?.reduce((e,t)=>{let{class:n,className:r,...a}=t;return Object.entries(a).every(e=>{let[t,n]=e;return Array.isArray(n)?n.includes({...i,...o}[t]):{...i,...o}[t]===n})?[...e,n,r]:e},[]),n?.class,n?.className)},y_=(e,t)=>{let n=Array(e.length+t.length);for(let t=0;t({classGroupId:e,validator:t}),x_=(e=new Map,t=null,n)=>({nextPart:e,validators:t,classGroupId:n}),S_=`-`,C_=[],w_=`arbitrary..`,T_=e=>{let t=O_(e),{conflictingClassGroups:n,conflictingClassGroupModifiers:r}=e;return{getClassGroupId:e=>{if(e.startsWith(`[`)&&e.endsWith(`]`))return D_(e);let n=e.split(S_);return E_(n,+(n[0]===``&&n.length>1),t)},getConflictingClassGroupIds:(e,t)=>{if(t){let t=r[e],i=n[e];return t?i?y_(i,t):t:i||C_}return n[e]||C_}}},E_=(e,t,n)=>{if(e.length-t===0)return n.classGroupId;let r=e[t],i=n.nextPart.get(r);if(i){let n=E_(e,t+1,i);if(n)return n}let a=n.validators;if(a===null)return;let o=t===0?e.join(S_):e.slice(t).join(S_),s=a.length;for(let e=0;ee.slice(1,-1).indexOf(`:`)===-1?void 0:(()=>{let t=e.slice(1,-1),n=t.indexOf(`:`),r=t.slice(0,n);return r?w_+r:void 0})(),O_=e=>{let{theme:t,classGroups:n}=e;return k_(n,t)},k_=(e,t)=>{let n=x_();for(let r in e){let i=e[r];A_(i,n,r,t)}return n},A_=(e,t,n,r)=>{let i=e.length;for(let a=0;a{if(typeof e==`string`){M_(e,t,n);return}if(typeof e==`function`){N_(e,t,n,r);return}P_(e,t,n,r)},M_=(e,t,n)=>{let r=e===``?t:F_(t,e);r.classGroupId=n},N_=(e,t,n,r)=>{if(I_(e)){A_(e(r),t,n,r);return}t.validators===null&&(t.validators=[]),t.validators.push(b_(n,e))},P_=(e,t,n,r)=>{let i=Object.entries(e),a=i.length;for(let e=0;e{let n=e,r=t.split(S_),i=r.length;for(let e=0;e`isThemeGetter`in e&&e.isThemeGetter===!0,L_=e=>{if(e<1)return{get:()=>void 0,set:()=>{}};let t=0,n=Object.create(null),r=Object.create(null),i=(i,a)=>{n[i]=a,t++,t>e&&(t=0,r=n,n=Object.create(null))};return{get(e){let t=n[e];if(t!==void 0)return t;if((t=r[e])!==void 0)return i(e,t),t},set(e,t){e in n?n[e]=t:i(e,t)}}},R_=`!`,z_=`:`,B_=[],V_=(e,t,n,r,i)=>({modifiers:e,hasImportantModifier:t,baseClassName:n,maybePostfixModifierPosition:r,isExternal:i}),H_=e=>{let{prefix:t,experimentalParseClassName:n}=e,r=e=>{let t=[],n=0,r=0,i=0,a,o=e.length;for(let s=0;si?a-i:void 0;return V_(t,l,c,u)};if(t){let e=t+z_,n=r;r=t=>t.startsWith(e)?n(t.slice(e.length)):V_(B_,!1,t,void 0,!0)}if(n){let e=r;r=t=>n({className:t,parseClassName:e})}return r},U_=e=>{let t=new Map;return e.orderSensitiveModifiers.forEach((e,n)=>{t.set(e,1e6+n)}),e=>{let n=[],r=[];for(let i=0;i0&&(r.sort(),n.push(...r),r=[]),n.push(a)):r.push(a)}return r.length>0&&(r.sort(),n.push(...r)),n}},W_=e=>({cache:L_(e.cacheSize),parseClassName:H_(e),sortModifiers:U_(e),postfixLookupClassGroupIds:G_(e),...T_(e)}),G_=e=>{let t=Object.create(null),n=e.postfixLookupClassGroups;if(n)for(let e=0;e{let{parseClassName:n,getClassGroupId:r,getConflictingClassGroupIds:i,sortModifiers:a,postfixLookupClassGroupIds:o}=t,s=[],c=e.trim().split(K_),l=``;for(let e=c.length-1;e>=0;--e){let t=c[e],{isExternal:u,modifiers:d,hasImportantModifier:f,baseClassName:p,maybePostfixModifierPosition:m}=n(t);if(u){l=t+(l.length>0?` `+l:l);continue}let h=!!m,g;if(h){g=r(p.substring(0,m));let e=g&&o[g]?r(p):void 0;e&&e!==g&&(g=e,h=!1)}else g=r(p);if(!g){if(!h){l=t+(l.length>0?` `+l:l);continue}if(g=r(p),!g){l=t+(l.length>0?` `+l:l);continue}h=!1}let _=d.length===0?``:d.length===1?d[0]:a(d).join(`:`),v=f?_+R_:_,y=v+g;if(s.indexOf(y)>-1)continue;s.push(y);let b=i(g,h);for(let e=0;e0?` `+l:l)}return l},J_=(...e)=>{let t=0,n,r,i=``;for(;t{if(typeof e==`string`)return e;let t,n=``;for(let r=0;r{let n,r,i,a,o=o=>(n=W_(t.reduce((e,t)=>t(e),e())),r=n.cache.get,i=n.cache.set,a=s,s(o)),s=e=>{let t=r(e);if(t)return t;let a=q_(e,n);return i(e,a),a};return a=o,(...e)=>a(J_(...e))},Z_=[],Q_=e=>{let t=t=>t[e]||Z_;return t.isThemeGetter=!0,t},$_=/^\[(?:(\w[\w-]*):)?(.+)\]$/i,ev=/^\((?:(\w[\w-]*):)?(.+)\)$/i,tv=/^\d+(?:\.\d+)?\/\d+(?:\.\d+)?$/,nv=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,rv=/\d+(%|px|r?em|[sdl]?v([hwib]|min|max)|pt|pc|in|cm|mm|cap|ch|ex|r?lh|cq(w|h|i|b|min|max))|\b(calc|min|max|clamp)\(.+\)|^0$/,iv=/^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/,av=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,ov=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,sv=e=>tv.test(e),cv=e=>!!e&&!Number.isNaN(Number(e)),lv=e=>!!e&&Number.isInteger(Number(e)),uv=e=>e.endsWith(`%`)&&cv(e.slice(0,-1)),dv=e=>nv.test(e),fv=()=>!0,pv=e=>rv.test(e)&&!iv.test(e),mv=()=>!1,hv=e=>av.test(e),gv=e=>ov.test(e),_v=e=>!Q(e)&&!$(e),vv=e=>e.startsWith(`@container`)&&(e[10]===`/`&&e[11]!==void 0||e[11]===`s`&&e[16]!==void 0&&e.startsWith(`-size/`,10)||e[11]===`n`&&e[18]!==void 0&&e.startsWith(`-normal/`,10)),yv=e=>Pv(e,Rv,mv),Q=e=>$_.test(e),bv=e=>Pv(e,zv,pv),xv=e=>Pv(e,Bv,cv),Sv=e=>Pv(e,Hv,fv),Cv=e=>Pv(e,Vv,mv),wv=e=>Pv(e,Iv,mv),Tv=e=>Pv(e,Lv,gv),Ev=e=>Pv(e,Uv,hv),$=e=>ev.test(e),Dv=e=>Fv(e,zv),Ov=e=>Fv(e,Vv),kv=e=>Fv(e,Iv),Av=e=>Fv(e,Rv),jv=e=>Fv(e,Lv),Mv=e=>Fv(e,Uv,!0),Nv=e=>Fv(e,Hv,!0),Pv=(e,t,n)=>{let r=$_.exec(e);return r?r[1]?t(r[1]):n(r[2]):!1},Fv=(e,t,n=!1)=>{let r=ev.exec(e);return r?r[1]?t(r[1]):n:!1},Iv=e=>e===`position`||e===`percentage`,Lv=e=>e===`image`||e===`url`,Rv=e=>e===`length`||e===`size`||e===`bg-size`,zv=e=>e===`length`,Bv=e=>e===`number`,Vv=e=>e===`family-name`,Hv=e=>e===`number`||e===`weight`,Uv=e=>e===`shadow`,Wv=X_(()=>{let e=Q_(`color`),t=Q_(`font`),n=Q_(`text`),r=Q_(`font-weight`),i=Q_(`tracking`),a=Q_(`leading`),o=Q_(`breakpoint`),s=Q_(`container`),c=Q_(`spacing`),l=Q_(`radius`),u=Q_(`shadow`),d=Q_(`inset-shadow`),f=Q_(`text-shadow`),p=Q_(`drop-shadow`),m=Q_(`blur`),h=Q_(`perspective`),g=Q_(`aspect`),_=Q_(`ease`),v=Q_(`animate`),y=()=>[`auto`,`avoid`,`all`,`avoid-page`,`page`,`left`,`right`,`column`],b=()=>[`center`,`top`,`bottom`,`left`,`right`,`top-left`,`left-top`,`top-right`,`right-top`,`bottom-right`,`right-bottom`,`bottom-left`,`left-bottom`],x=()=>[...b(),$,Q],S=()=>[`auto`,`hidden`,`clip`,`visible`,`scroll`],C=()=>[`auto`,`contain`,`none`],w=()=>[$,Q,c],T=()=>[sv,`full`,`auto`,...w()],E=()=>[lv,`none`,`subgrid`,$,Q],D=()=>[`auto`,{span:[`full`,lv,$,Q]},lv,$,Q],O=()=>[lv,`auto`,$,Q],k=()=>[`auto`,`min`,`max`,`fr`,$,Q],ee=()=>[`start`,`end`,`center`,`between`,`around`,`evenly`,`stretch`,`baseline`,`center-safe`,`end-safe`],A=()=>[`start`,`end`,`center`,`stretch`,`center-safe`,`end-safe`],j=()=>[`auto`,...w()],te=()=>[sv,`auto`,`full`,`dvw`,`dvh`,`lvw`,`lvh`,`svw`,`svh`,`min`,`max`,`fit`,...w()],ne=()=>[sv,`screen`,`full`,`dvw`,`lvw`,`svw`,`min`,`max`,`fit`,...w()],re=()=>[sv,`screen`,`full`,`lh`,`dvh`,`lvh`,`svh`,`min`,`max`,`fit`,...w()],M=()=>[e,$,Q],N=()=>[...b(),kv,wv,{position:[$,Q]}],ie=()=>[`no-repeat`,{repeat:[``,`x`,`y`,`space`,`round`]}],ae=()=>[`auto`,`cover`,`contain`,Av,yv,{size:[$,Q]}],oe=()=>[uv,Dv,bv],P=()=>[``,`none`,`full`,l,$,Q],F=()=>[``,cv,Dv,bv],I=()=>[`solid`,`dashed`,`dotted`,`double`],se=()=>[`normal`,`multiply`,`screen`,`overlay`,`darken`,`lighten`,`color-dodge`,`color-burn`,`hard-light`,`soft-light`,`difference`,`exclusion`,`hue`,`saturation`,`color`,`luminosity`],ce=()=>[cv,uv,kv,wv],le=()=>[``,`none`,m,$,Q],ue=()=>[`none`,cv,$,Q],de=()=>[`none`,cv,$,Q],fe=()=>[cv,$,Q],pe=()=>[sv,`full`,...w()];return{cacheSize:500,theme:{animate:[`spin`,`ping`,`pulse`,`bounce`],aspect:[`video`],blur:[dv],breakpoint:[dv],color:[fv],container:[dv],"drop-shadow":[dv],ease:[`in`,`out`,`in-out`],font:[_v],"font-weight":[`thin`,`extralight`,`light`,`normal`,`medium`,`semibold`,`bold`,`extrabold`,`black`],"inset-shadow":[dv],leading:[`none`,`tight`,`snug`,`normal`,`relaxed`,`loose`],perspective:[`dramatic`,`near`,`normal`,`midrange`,`distant`,`none`],radius:[dv],shadow:[dv],spacing:[`px`,cv],text:[dv],"text-shadow":[dv],tracking:[`tighter`,`tight`,`normal`,`wide`,`wider`,`widest`]},classGroups:{aspect:[{aspect:[`auto`,`square`,sv,Q,$,g]}],container:[`container`],"container-type":[{"@container":[``,`normal`,`size`,$,Q]}],"container-named":[vv],columns:[{columns:[cv,Q,$,s]}],"break-after":[{"break-after":y()}],"break-before":[{"break-before":y()}],"break-inside":[{"break-inside":[`auto`,`avoid`,`avoid-page`,`avoid-column`]}],"box-decoration":[{"box-decoration":[`slice`,`clone`]}],box:[{box:[`border`,`content`]}],display:[`block`,`inline-block`,`inline`,`flex`,`inline-flex`,`table`,`inline-table`,`table-caption`,`table-cell`,`table-column`,`table-column-group`,`table-footer-group`,`table-header-group`,`table-row-group`,`table-row`,`flow-root`,`grid`,`inline-grid`,`contents`,`list-item`,`hidden`],sr:[`sr-only`,`not-sr-only`],float:[{float:[`right`,`left`,`none`,`start`,`end`]}],clear:[{clear:[`left`,`right`,`both`,`none`,`start`,`end`]}],isolation:[`isolate`,`isolation-auto`],"object-fit":[{object:[`contain`,`cover`,`fill`,`none`,`scale-down`]}],"object-position":[{object:x()}],overflow:[{overflow:S()}],"overflow-x":[{"overflow-x":S()}],"overflow-y":[{"overflow-y":S()}],overscroll:[{overscroll:C()}],"overscroll-x":[{"overscroll-x":C()}],"overscroll-y":[{"overscroll-y":C()}],position:[`static`,`fixed`,`absolute`,`relative`,`sticky`],inset:[{inset:T()}],"inset-x":[{"inset-x":T()}],"inset-y":[{"inset-y":T()}],start:[{"inset-s":T(),start:T()}],end:[{"inset-e":T(),end:T()}],"inset-bs":[{"inset-bs":T()}],"inset-be":[{"inset-be":T()}],top:[{top:T()}],right:[{right:T()}],bottom:[{bottom:T()}],left:[{left:T()}],visibility:[`visible`,`invisible`,`collapse`],z:[{z:[lv,`auto`,$,Q]}],basis:[{basis:[sv,`full`,`auto`,s,...w()]}],"flex-direction":[{flex:[`row`,`row-reverse`,`col`,`col-reverse`]}],"flex-wrap":[{flex:[`nowrap`,`wrap`,`wrap-reverse`]}],flex:[{flex:[cv,sv,`auto`,`initial`,`none`,Q]}],grow:[{grow:[``,cv,$,Q]}],shrink:[{shrink:[``,cv,$,Q]}],order:[{order:[lv,`first`,`last`,`none`,$,Q]}],"grid-cols":[{"grid-cols":E()}],"col-start-end":[{col:D()}],"col-start":[{"col-start":O()}],"col-end":[{"col-end":O()}],"grid-rows":[{"grid-rows":E()}],"row-start-end":[{row:D()}],"row-start":[{"row-start":O()}],"row-end":[{"row-end":O()}],"grid-flow":[{"grid-flow":[`row`,`col`,`dense`,`row-dense`,`col-dense`]}],"auto-cols":[{"auto-cols":k()}],"auto-rows":[{"auto-rows":k()}],gap:[{gap:w()}],"gap-x":[{"gap-x":w()}],"gap-y":[{"gap-y":w()}],"justify-content":[{justify:[...ee(),`normal`]}],"justify-items":[{"justify-items":[...A(),`normal`]}],"justify-self":[{"justify-self":[`auto`,...A()]}],"align-content":[{content:[`normal`,...ee()]}],"align-items":[{items:[...A(),{baseline:[``,`last`]}]}],"align-self":[{self:[`auto`,...A(),{baseline:[``,`last`]}]}],"place-content":[{"place-content":ee()}],"place-items":[{"place-items":[...A(),`baseline`]}],"place-self":[{"place-self":[`auto`,...A()]}],p:[{p:w()}],px:[{px:w()}],py:[{py:w()}],ps:[{ps:w()}],pe:[{pe:w()}],pbs:[{pbs:w()}],pbe:[{pbe:w()}],pt:[{pt:w()}],pr:[{pr:w()}],pb:[{pb:w()}],pl:[{pl:w()}],m:[{m:j()}],mx:[{mx:j()}],my:[{my:j()}],ms:[{ms:j()}],me:[{me:j()}],mbs:[{mbs:j()}],mbe:[{mbe:j()}],mt:[{mt:j()}],mr:[{mr:j()}],mb:[{mb:j()}],ml:[{ml:j()}],"space-x":[{"space-x":w()}],"space-x-reverse":[`space-x-reverse`],"space-y":[{"space-y":w()}],"space-y-reverse":[`space-y-reverse`],size:[{size:te()}],"inline-size":[{inline:[`auto`,...ne()]}],"min-inline-size":[{"min-inline":[`auto`,...ne()]}],"max-inline-size":[{"max-inline":[`none`,...ne()]}],"block-size":[{block:[`auto`,...re()]}],"min-block-size":[{"min-block":[`auto`,...re()]}],"max-block-size":[{"max-block":[`none`,...re()]}],w:[{w:[s,`screen`,...te()]}],"min-w":[{"min-w":[s,`screen`,`none`,...te()]}],"max-w":[{"max-w":[s,`screen`,`none`,`prose`,{screen:[o]},...te()]}],h:[{h:[`screen`,`lh`,...te()]}],"min-h":[{"min-h":[`screen`,`lh`,`none`,...te()]}],"max-h":[{"max-h":[`screen`,`lh`,...te()]}],"font-size":[{text:[`base`,n,Dv,bv]}],"font-smoothing":[`antialiased`,`subpixel-antialiased`],"font-style":[`italic`,`not-italic`],"font-weight":[{font:[r,Nv,Sv]}],"font-stretch":[{"font-stretch":[`ultra-condensed`,`extra-condensed`,`condensed`,`semi-condensed`,`normal`,`semi-expanded`,`expanded`,`extra-expanded`,`ultra-expanded`,uv,Q]}],"font-family":[{font:[Ov,Cv,t]}],"font-features":[{"font-features":[Q]}],"fvn-normal":[`normal-nums`],"fvn-ordinal":[`ordinal`],"fvn-slashed-zero":[`slashed-zero`],"fvn-figure":[`lining-nums`,`oldstyle-nums`],"fvn-spacing":[`proportional-nums`,`tabular-nums`],"fvn-fraction":[`diagonal-fractions`,`stacked-fractions`],tracking:[{tracking:[i,$,Q]}],"line-clamp":[{"line-clamp":[cv,`none`,$,xv]}],leading:[{leading:[a,...w()]}],"list-image":[{"list-image":[`none`,$,Q]}],"list-style-position":[{list:[`inside`,`outside`]}],"list-style-type":[{list:[`disc`,`decimal`,`none`,$,Q]}],"text-alignment":[{text:[`left`,`center`,`right`,`justify`,`start`,`end`]}],"placeholder-color":[{placeholder:M()}],"text-color":[{text:M()}],"text-decoration":[`underline`,`overline`,`line-through`,`no-underline`],"text-decoration-style":[{decoration:[...I(),`wavy`]}],"text-decoration-thickness":[{decoration:[cv,`from-font`,`auto`,$,bv]}],"text-decoration-color":[{decoration:M()}],"underline-offset":[{"underline-offset":[cv,`auto`,$,Q]}],"text-transform":[`uppercase`,`lowercase`,`capitalize`,`normal-case`],"text-overflow":[`truncate`,`text-ellipsis`,`text-clip`],"text-wrap":[{text:[`wrap`,`nowrap`,`balance`,`pretty`]}],indent:[{indent:w()}],"tab-size":[{tab:[lv,$,Q]}],"vertical-align":[{align:[`baseline`,`top`,`middle`,`bottom`,`text-top`,`text-bottom`,`sub`,`super`,$,Q]}],whitespace:[{whitespace:[`normal`,`nowrap`,`pre`,`pre-line`,`pre-wrap`,`break-spaces`]}],break:[{break:[`normal`,`words`,`all`,`keep`]}],wrap:[{wrap:[`break-word`,`anywhere`,`normal`]}],hyphens:[{hyphens:[`none`,`manual`,`auto`]}],content:[{content:[`none`,$,Q]}],"bg-attachment":[{bg:[`fixed`,`local`,`scroll`]}],"bg-clip":[{"bg-clip":[`border`,`padding`,`content`,`text`]}],"bg-origin":[{"bg-origin":[`border`,`padding`,`content`]}],"bg-position":[{bg:N()}],"bg-repeat":[{bg:ie()}],"bg-size":[{bg:ae()}],"bg-image":[{bg:[`none`,{linear:[{to:[`t`,`tr`,`r`,`br`,`b`,`bl`,`l`,`tl`]},lv,$,Q],radial:[``,$,Q],conic:[lv,$,Q]},jv,Tv]}],"bg-color":[{bg:M()}],"gradient-from-pos":[{from:oe()}],"gradient-via-pos":[{via:oe()}],"gradient-to-pos":[{to:oe()}],"gradient-from":[{from:M()}],"gradient-via":[{via:M()}],"gradient-to":[{to:M()}],rounded:[{rounded:P()}],"rounded-s":[{"rounded-s":P()}],"rounded-e":[{"rounded-e":P()}],"rounded-t":[{"rounded-t":P()}],"rounded-r":[{"rounded-r":P()}],"rounded-b":[{"rounded-b":P()}],"rounded-l":[{"rounded-l":P()}],"rounded-ss":[{"rounded-ss":P()}],"rounded-se":[{"rounded-se":P()}],"rounded-ee":[{"rounded-ee":P()}],"rounded-es":[{"rounded-es":P()}],"rounded-tl":[{"rounded-tl":P()}],"rounded-tr":[{"rounded-tr":P()}],"rounded-br":[{"rounded-br":P()}],"rounded-bl":[{"rounded-bl":P()}],"border-w":[{border:F()}],"border-w-x":[{"border-x":F()}],"border-w-y":[{"border-y":F()}],"border-w-s":[{"border-s":F()}],"border-w-e":[{"border-e":F()}],"border-w-bs":[{"border-bs":F()}],"border-w-be":[{"border-be":F()}],"border-w-t":[{"border-t":F()}],"border-w-r":[{"border-r":F()}],"border-w-b":[{"border-b":F()}],"border-w-l":[{"border-l":F()}],"divide-x":[{"divide-x":F()}],"divide-x-reverse":[`divide-x-reverse`],"divide-y":[{"divide-y":F()}],"divide-y-reverse":[`divide-y-reverse`],"border-style":[{border:[...I(),`hidden`,`none`]}],"divide-style":[{divide:[...I(),`hidden`,`none`]}],"border-color":[{border:M()}],"border-color-x":[{"border-x":M()}],"border-color-y":[{"border-y":M()}],"border-color-s":[{"border-s":M()}],"border-color-e":[{"border-e":M()}],"border-color-bs":[{"border-bs":M()}],"border-color-be":[{"border-be":M()}],"border-color-t":[{"border-t":M()}],"border-color-r":[{"border-r":M()}],"border-color-b":[{"border-b":M()}],"border-color-l":[{"border-l":M()}],"divide-color":[{divide:M()}],"outline-style":[{outline:[...I(),`none`,`hidden`]}],"outline-offset":[{"outline-offset":[cv,$,Q]}],"outline-w":[{outline:[``,cv,Dv,bv]}],"outline-color":[{outline:M()}],shadow:[{shadow:[``,`none`,u,Mv,Ev]}],"shadow-color":[{shadow:M()}],"inset-shadow":[{"inset-shadow":[`none`,d,Mv,Ev]}],"inset-shadow-color":[{"inset-shadow":M()}],"ring-w":[{ring:F()}],"ring-w-inset":[`ring-inset`],"ring-color":[{ring:M()}],"ring-offset-w":[{"ring-offset":[cv,bv]}],"ring-offset-color":[{"ring-offset":M()}],"inset-ring-w":[{"inset-ring":F()}],"inset-ring-color":[{"inset-ring":M()}],"text-shadow":[{"text-shadow":[`none`,f,Mv,Ev]}],"text-shadow-color":[{"text-shadow":M()}],opacity:[{opacity:[cv,$,Q]}],"mix-blend":[{"mix-blend":[...se(),`plus-darker`,`plus-lighter`]}],"bg-blend":[{"bg-blend":se()}],"mask-clip":[{"mask-clip":[`border`,`padding`,`content`,`fill`,`stroke`,`view`]},`mask-no-clip`],"mask-composite":[{mask:[`add`,`subtract`,`intersect`,`exclude`]}],"mask-image-linear-pos":[{"mask-linear":[cv]}],"mask-image-linear-from-pos":[{"mask-linear-from":ce()}],"mask-image-linear-to-pos":[{"mask-linear-to":ce()}],"mask-image-linear-from-color":[{"mask-linear-from":M()}],"mask-image-linear-to-color":[{"mask-linear-to":M()}],"mask-image-t-from-pos":[{"mask-t-from":ce()}],"mask-image-t-to-pos":[{"mask-t-to":ce()}],"mask-image-t-from-color":[{"mask-t-from":M()}],"mask-image-t-to-color":[{"mask-t-to":M()}],"mask-image-r-from-pos":[{"mask-r-from":ce()}],"mask-image-r-to-pos":[{"mask-r-to":ce()}],"mask-image-r-from-color":[{"mask-r-from":M()}],"mask-image-r-to-color":[{"mask-r-to":M()}],"mask-image-b-from-pos":[{"mask-b-from":ce()}],"mask-image-b-to-pos":[{"mask-b-to":ce()}],"mask-image-b-from-color":[{"mask-b-from":M()}],"mask-image-b-to-color":[{"mask-b-to":M()}],"mask-image-l-from-pos":[{"mask-l-from":ce()}],"mask-image-l-to-pos":[{"mask-l-to":ce()}],"mask-image-l-from-color":[{"mask-l-from":M()}],"mask-image-l-to-color":[{"mask-l-to":M()}],"mask-image-x-from-pos":[{"mask-x-from":ce()}],"mask-image-x-to-pos":[{"mask-x-to":ce()}],"mask-image-x-from-color":[{"mask-x-from":M()}],"mask-image-x-to-color":[{"mask-x-to":M()}],"mask-image-y-from-pos":[{"mask-y-from":ce()}],"mask-image-y-to-pos":[{"mask-y-to":ce()}],"mask-image-y-from-color":[{"mask-y-from":M()}],"mask-image-y-to-color":[{"mask-y-to":M()}],"mask-image-radial":[{"mask-radial":[$,Q]}],"mask-image-radial-from-pos":[{"mask-radial-from":ce()}],"mask-image-radial-to-pos":[{"mask-radial-to":ce()}],"mask-image-radial-from-color":[{"mask-radial-from":M()}],"mask-image-radial-to-color":[{"mask-radial-to":M()}],"mask-image-radial-shape":[{"mask-radial":[`circle`,`ellipse`]}],"mask-image-radial-size":[{"mask-radial":[{closest:[`side`,`corner`],farthest:[`side`,`corner`]}]}],"mask-image-radial-pos":[{"mask-radial-at":b()}],"mask-image-conic-pos":[{"mask-conic":[cv]}],"mask-image-conic-from-pos":[{"mask-conic-from":ce()}],"mask-image-conic-to-pos":[{"mask-conic-to":ce()}],"mask-image-conic-from-color":[{"mask-conic-from":M()}],"mask-image-conic-to-color":[{"mask-conic-to":M()}],"mask-mode":[{mask:[`alpha`,`luminance`,`match`]}],"mask-origin":[{"mask-origin":[`border`,`padding`,`content`,`fill`,`stroke`,`view`]}],"mask-position":[{mask:N()}],"mask-repeat":[{mask:ie()}],"mask-size":[{mask:ae()}],"mask-type":[{"mask-type":[`alpha`,`luminance`]}],"mask-image":[{mask:[`none`,$,Q]}],filter:[{filter:[``,`none`,$,Q]}],blur:[{blur:le()}],brightness:[{brightness:[cv,$,Q]}],contrast:[{contrast:[cv,$,Q]}],"drop-shadow":[{"drop-shadow":[``,`none`,p,Mv,Ev]}],"drop-shadow-color":[{"drop-shadow":M()}],grayscale:[{grayscale:[``,cv,$,Q]}],"hue-rotate":[{"hue-rotate":[cv,$,Q]}],invert:[{invert:[``,cv,$,Q]}],saturate:[{saturate:[cv,$,Q]}],sepia:[{sepia:[``,cv,$,Q]}],"backdrop-filter":[{"backdrop-filter":[``,`none`,$,Q]}],"backdrop-blur":[{"backdrop-blur":le()}],"backdrop-brightness":[{"backdrop-brightness":[cv,$,Q]}],"backdrop-contrast":[{"backdrop-contrast":[cv,$,Q]}],"backdrop-grayscale":[{"backdrop-grayscale":[``,cv,$,Q]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[cv,$,Q]}],"backdrop-invert":[{"backdrop-invert":[``,cv,$,Q]}],"backdrop-opacity":[{"backdrop-opacity":[cv,$,Q]}],"backdrop-saturate":[{"backdrop-saturate":[cv,$,Q]}],"backdrop-sepia":[{"backdrop-sepia":[``,cv,$,Q]}],"border-collapse":[{border:[`collapse`,`separate`]}],"border-spacing":[{"border-spacing":w()}],"border-spacing-x":[{"border-spacing-x":w()}],"border-spacing-y":[{"border-spacing-y":w()}],"table-layout":[{table:[`auto`,`fixed`]}],caption:[{caption:[`top`,`bottom`]}],transition:[{transition:[``,`all`,`colors`,`opacity`,`shadow`,`transform`,`none`,$,Q]}],"transition-behavior":[{transition:[`normal`,`discrete`]}],duration:[{duration:[cv,`initial`,$,Q]}],ease:[{ease:[`linear`,`initial`,_,$,Q]}],delay:[{delay:[cv,$,Q]}],animate:[{animate:[`none`,v,$,Q]}],backface:[{backface:[`hidden`,`visible`]}],perspective:[{perspective:[h,$,Q]}],"perspective-origin":[{"perspective-origin":x()}],rotate:[{rotate:ue()}],"rotate-x":[{"rotate-x":ue()}],"rotate-y":[{"rotate-y":ue()}],"rotate-z":[{"rotate-z":ue()}],scale:[{scale:de()}],"scale-x":[{"scale-x":de()}],"scale-y":[{"scale-y":de()}],"scale-z":[{"scale-z":de()}],"scale-3d":[`scale-3d`],skew:[{skew:fe()}],"skew-x":[{"skew-x":fe()}],"skew-y":[{"skew-y":fe()}],transform:[{transform:[$,Q,``,`none`,`gpu`,`cpu`]}],"transform-origin":[{origin:x()}],"transform-style":[{transform:[`3d`,`flat`]}],translate:[{translate:pe()}],"translate-x":[{"translate-x":pe()}],"translate-y":[{"translate-y":pe()}],"translate-z":[{"translate-z":pe()}],"translate-none":[`translate-none`],zoom:[{zoom:[lv,$,Q]}],accent:[{accent:M()}],appearance:[{appearance:[`none`,`auto`]}],"caret-color":[{caret:M()}],"color-scheme":[{scheme:[`normal`,`dark`,`light`,`light-dark`,`only-dark`,`only-light`]}],cursor:[{cursor:[`auto`,`default`,`pointer`,`wait`,`text`,`move`,`help`,`not-allowed`,`none`,`context-menu`,`progress`,`cell`,`crosshair`,`vertical-text`,`alias`,`copy`,`no-drop`,`grab`,`grabbing`,`all-scroll`,`col-resize`,`row-resize`,`n-resize`,`e-resize`,`s-resize`,`w-resize`,`ne-resize`,`nw-resize`,`se-resize`,`sw-resize`,`ew-resize`,`ns-resize`,`nesw-resize`,`nwse-resize`,`zoom-in`,`zoom-out`,$,Q]}],"field-sizing":[{"field-sizing":[`fixed`,`content`]}],"pointer-events":[{"pointer-events":[`auto`,`none`]}],resize:[{resize:[`none`,``,`y`,`x`]}],"scroll-behavior":[{scroll:[`auto`,`smooth`]}],"scrollbar-thumb-color":[{"scrollbar-thumb":M()}],"scrollbar-track-color":[{"scrollbar-track":M()}],"scrollbar-gutter":[{"scrollbar-gutter":[`auto`,`stable`,`both`]}],"scrollbar-w":[{scrollbar:[`auto`,`thin`,`none`]}],"scroll-m":[{"scroll-m":w()}],"scroll-mx":[{"scroll-mx":w()}],"scroll-my":[{"scroll-my":w()}],"scroll-ms":[{"scroll-ms":w()}],"scroll-me":[{"scroll-me":w()}],"scroll-mbs":[{"scroll-mbs":w()}],"scroll-mbe":[{"scroll-mbe":w()}],"scroll-mt":[{"scroll-mt":w()}],"scroll-mr":[{"scroll-mr":w()}],"scroll-mb":[{"scroll-mb":w()}],"scroll-ml":[{"scroll-ml":w()}],"scroll-p":[{"scroll-p":w()}],"scroll-px":[{"scroll-px":w()}],"scroll-py":[{"scroll-py":w()}],"scroll-ps":[{"scroll-ps":w()}],"scroll-pe":[{"scroll-pe":w()}],"scroll-pbs":[{"scroll-pbs":w()}],"scroll-pbe":[{"scroll-pbe":w()}],"scroll-pt":[{"scroll-pt":w()}],"scroll-pr":[{"scroll-pr":w()}],"scroll-pb":[{"scroll-pb":w()}],"scroll-pl":[{"scroll-pl":w()}],"snap-align":[{snap:[`start`,`end`,`center`,`align-none`]}],"snap-stop":[{snap:[`normal`,`always`]}],"snap-type":[{snap:[`none`,`x`,`y`,`both`]}],"snap-strictness":[{snap:[`mandatory`,`proximity`]}],touch:[{touch:[`auto`,`none`,`manipulation`]}],"touch-x":[{"touch-pan":[`x`,`left`,`right`]}],"touch-y":[{"touch-pan":[`y`,`up`,`down`]}],"touch-pz":[`touch-pinch-zoom`],select:[{select:[`none`,`text`,`all`,`auto`]}],"will-change":[{"will-change":[`auto`,`scroll`,`contents`,`transform`,$,Q]}],fill:[{fill:[`none`,...M()]}],"stroke-w":[{stroke:[cv,Dv,bv,xv]}],stroke:[{stroke:[`none`,...M()]}],"forced-color-adjust":[{"forced-color-adjust":[`auto`,`none`]}]},conflictingClassGroups:{"container-named":[`container-type`],overflow:[`overflow-x`,`overflow-y`],overscroll:[`overscroll-x`,`overscroll-y`],inset:[`inset-x`,`inset-y`,`inset-bs`,`inset-be`,`start`,`end`,`top`,`right`,`bottom`,`left`],"inset-x":[`right`,`left`],"inset-y":[`top`,`bottom`],flex:[`basis`,`grow`,`shrink`],gap:[`gap-x`,`gap-y`],p:[`px`,`py`,`ps`,`pe`,`pbs`,`pbe`,`pt`,`pr`,`pb`,`pl`],px:[`pr`,`pl`],py:[`pt`,`pb`],m:[`mx`,`my`,`ms`,`me`,`mbs`,`mbe`,`mt`,`mr`,`mb`,`ml`],mx:[`mr`,`ml`],my:[`mt`,`mb`],size:[`w`,`h`],"font-size":[`leading`],"fvn-normal":[`fvn-ordinal`,`fvn-slashed-zero`,`fvn-figure`,`fvn-spacing`,`fvn-fraction`],"fvn-ordinal":[`fvn-normal`],"fvn-slashed-zero":[`fvn-normal`],"fvn-figure":[`fvn-normal`],"fvn-spacing":[`fvn-normal`],"fvn-fraction":[`fvn-normal`],"line-clamp":[`display`,`overflow`],rounded:[`rounded-s`,`rounded-e`,`rounded-t`,`rounded-r`,`rounded-b`,`rounded-l`,`rounded-ss`,`rounded-se`,`rounded-ee`,`rounded-es`,`rounded-tl`,`rounded-tr`,`rounded-br`,`rounded-bl`],"rounded-s":[`rounded-ss`,`rounded-es`],"rounded-e":[`rounded-se`,`rounded-ee`],"rounded-t":[`rounded-tl`,`rounded-tr`],"rounded-r":[`rounded-tr`,`rounded-br`],"rounded-b":[`rounded-br`,`rounded-bl`],"rounded-l":[`rounded-tl`,`rounded-bl`],"border-spacing":[`border-spacing-x`,`border-spacing-y`],"border-w":[`border-w-x`,`border-w-y`,`border-w-s`,`border-w-e`,`border-w-bs`,`border-w-be`,`border-w-t`,`border-w-r`,`border-w-b`,`border-w-l`],"border-w-x":[`border-w-r`,`border-w-l`],"border-w-y":[`border-w-t`,`border-w-b`],"border-color":[`border-color-x`,`border-color-y`,`border-color-s`,`border-color-e`,`border-color-bs`,`border-color-be`,`border-color-t`,`border-color-r`,`border-color-b`,`border-color-l`],"border-color-x":[`border-color-r`,`border-color-l`],"border-color-y":[`border-color-t`,`border-color-b`],translate:[`translate-x`,`translate-y`,`translate-none`],"translate-none":[`translate`,`translate-x`,`translate-y`,`translate-z`],"scroll-m":[`scroll-mx`,`scroll-my`,`scroll-ms`,`scroll-me`,`scroll-mbs`,`scroll-mbe`,`scroll-mt`,`scroll-mr`,`scroll-mb`,`scroll-ml`],"scroll-mx":[`scroll-mr`,`scroll-ml`],"scroll-my":[`scroll-mt`,`scroll-mb`],"scroll-p":[`scroll-px`,`scroll-py`,`scroll-ps`,`scroll-pe`,`scroll-pbs`,`scroll-pbe`,`scroll-pt`,`scroll-pr`,`scroll-pb`,`scroll-pl`],"scroll-px":[`scroll-pr`,`scroll-pl`],"scroll-py":[`scroll-pt`,`scroll-pb`],touch:[`touch-x`,`touch-y`,`touch-pz`],"touch-x":[`touch`],"touch-y":[`touch`],"touch-pz":[`touch`]},conflictingClassGroupModifiers:{"font-size":[`leading`]},postfixLookupClassGroups:[`container-type`],orderSensitiveModifiers:[`*`,`**`,`after`,`backdrop`,`before`,`details-content`,`file`,`first-letter`,`first-line`,`marker`,`placeholder`,`selection`]}});function Gv(...e){return Wv(h_(e))}var Kv=v_(`inline-flex h-9 shrink-0 items-center justify-center gap-2 whitespace-nowrap rounded-md border px-3 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-400 disabled:pointer-events-none disabled:opacity-50 dark:focus-visible:ring-zinc-500`,{variants:{variant:{primary:`border-slate-900 bg-slate-950 text-white hover:bg-slate-800 dark:border-zinc-100 dark:bg-zinc-50 dark:text-zinc-950 dark:hover:bg-zinc-200`,secondary:`border-slate-200 bg-white text-slate-900 hover:bg-slate-50 dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-100 dark:hover:bg-zinc-900`,ghost:`border-transparent bg-transparent text-slate-700 hover:bg-slate-100 dark:text-zinc-300 dark:hover:bg-zinc-900`},size:{sm:`h-8 px-2 text-xs`,md:`h-9 px-3 text-sm`,icon:`h-9 w-9 px-0`}},defaultVariants:{variant:`secondary`,size:`md`}});function qv({className:e,variant:t,size:n,...r}){return(0,z.jsx)(`button`,{className:Gv(Kv({variant:t,size:n}),e),type:`button`,...r})}function Jv({className:e,...t}){return(0,z.jsx)(`section`,{className:Gv(`rounded-lg border border-slate-200/80 bg-white/95 text-slate-950 shadow-[0_1px_2px_rgba(15,23,42,0.04)] dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-50`,e),...t})}function Yv({className:e,...t}){return(0,z.jsx)(`div`,{className:Gv(`p-4 pt-0`,e),...t})}var Xv=[`codex`,`claude`,`kiro`,`trae`,`coco`,`openai`,`anthropic`];function Zv(e){let t=e.trim().toLowerCase().replace(/_/gu,`-`);for(let e of Xv)if(t===e||t.startsWith(`${e}-`))return e;return t}function Qv(e,t){let n=t?.trim().toLowerCase()??``;return n.length>0&&n!==`status_projection`?Zv(n):Zv(e)}function $v(e){return{blockingTodoCount:e.blockingTodoCount,goalNotifications:e.goalNotifications,goals:e.goals,openUserTodoCount:e.openUserTodoCount,systemHealth:e.systemHealth,userTodos:e.userTodos,workers:e.workers}}function ey(e,t){return e.goals.find(e=>e.goalId===t)?.title??t}function ty(e){return e.activationState===`stopped`||e.state===`已停止`?`stopped`:e.state===`已完成`?`history`:e.needsYou||e.state===`等你`?`needs_you`:e.state===`推进中`||e.state===`需修复`?`running`:e.state===`安静运行`?`observing`:`scheduled`}function ny(e){let t=e;return t>=1e6?`${(t/1e6).toFixed(1)}M`:t>=1e3?`${(t/1e3).toFixed(1)}k`:String(t)}function ry(e){return`$${e.toFixed(2)}`}function iy(e){let t=e;return t>=36e5?`${(t/36e5).toFixed(1)}h`:t>=6e4?`${(t/6e4).toFixed(1)}m`:t>=1e3?`${Math.round(t/1e3)}s`:`${t}ms`}function ay(e,t,n){return e==null?t:n(e)}function oy(e){return!!(e&&[e.tokens24h,e.tokens7d,e.costUsd24h,e.costUsd7d,e.durationMs24h,e.durationMs7d].some(e=>e!=null))}function sy(e,t){if(!oy(e))return null;let n=(e,n,r,i)=>{let a=[n==null?null:`${ny(n)} ${t.tokens}`,r==null?null:`${t.cost}: ${ry(r)}`,i==null?null:`${t.duration}: ${iy(i)}`].filter(e=>e!==null);return a.length?`${e} ${a.join(` · `)}`:null};return n(t.period7d,e.tokens7d,e.costUsd7d,e.durationMs7d)??n(t.period24h,e.tokens24h,e.costUsd24h,e.durationMs24h)}function cy({ariaLabel:e,className:t,icon:n,onChange:r,options:i,prefixLabel:a,value:o}){let s=(0,R.useId)(),c=(0,R.useRef)(null),l=(0,R.useRef)(null),u=(0,R.useRef)(new Map),[d,f]=(0,R.useState)(!1),[p,m]=(0,R.useState)(o),h=i.find(e=>e.value===o)??i[0],g=i.filter(e=>!e.disabled);(0,R.useEffect)(()=>{if(!d)return;let e=e=>{c.current?.contains(e.target)||f(!1)};return document.addEventListener(`pointerdown`,e),()=>document.removeEventListener(`pointerdown`,e)},[d]),(0,R.useEffect)(()=>{d&&u.current.get(p)?.focus()},[p,d]);function _(e){m(e)}function v(e=`selected`){let t=e===`last`?g.at(-1):g[0],n=e===`selected`&&h&&!h.disabled?h:t;n&&(f(!0),_(n.value))}function y({restoreFocus:e=!1}={}){f(!1),e&&l.current?.focus()}function b(e){e.disabled||(r(e.value),y({restoreFocus:!0}))}function x(e){if(!g.length)return;let t=g.findIndex(e=>e.value===p),n=t<0?0:(t+e+g.length)%g.length;_(g[n].value)}function S(e){e.key===`ArrowDown`||e.key===`Enter`||e.key===` `?(e.preventDefault(),v(`selected`)):e.key===`ArrowUp`&&(e.preventDefault(),v(`last`))}function C(e,t){if(e.key===`ArrowDown`)e.preventDefault(),x(1);else if(e.key===`ArrowUp`)e.preventDefault(),x(-1);else if(e.key===`Home`)e.preventDefault(),g[0]&&_(g[0].value);else if(e.key===`End`){e.preventDefault();let t=g.at(-1);t&&_(t.value)}else e.key===`Enter`||e.key===` `?(e.preventDefault(),b(t)):e.key===`Escape`?(e.preventDefault(),y({restoreFocus:!0})):e.key===`Tab`&&y()}let w;return(0,z.jsxs)(`div`,{className:`personal-select${t?` ${t}`:``}`,ref:c,children:[(0,z.jsxs)(`button`,{"aria-controls":s,"aria-expanded":d,"aria-haspopup":`listbox`,"aria-label":e,className:`personal-select-trigger`,"data-value":o,onClick:()=>d?y():v(),onKeyDown:S,ref:l,role:`combobox`,type:`button`,children:[n?(0,z.jsx)(`span`,{className:`personal-select-icon`,children:n}):null,(0,z.jsxs)(`span`,{className:`personal-select-value`,children:[a?(0,z.jsx)(`small`,{children:a}):null,(0,z.jsx)(`span`,{children:h?.label??o})]}),(0,z.jsx)(qp,{"aria-hidden":!0,className:d?`is-open`:void 0,size:14})]}),d?(0,z.jsx)(`div`,{"aria-label":e,className:`personal-select-listbox`,id:s,role:`listbox`,children:i.map(e=>{let t=e.group&&e.group!==w;return w=e.group,(0,z.jsxs)(`div`,{className:`personal-select-option-wrap`,children:[t?(0,z.jsx)(`div`,{className:`personal-select-group-label`,children:e.group}):null,(0,z.jsxs)(`button`,{"aria-disabled":e.disabled||void 0,"aria-selected":e.value===o,className:`personal-select-option`,disabled:e.disabled,id:`${s}-${e.value.replace(/[^a-z0-9_-]/gi,`-`)}`,onClick:()=>b(e),onFocus:()=>m(e.value),onKeyDown:t=>C(t,e),ref:t=>{t?u.current.set(e.value,t):u.current.delete(e.value)},role:`option`,tabIndex:e.value===p?0:-1,type:`button`,children:[(0,z.jsx)(`span`,{children:e.label}),e.value===o?(0,z.jsx)(Kp,{"aria-hidden":!0,size:15}):null]})]},e.value)})}):null]})}function ly({agents:e,managerChatOpen:t,mobileNavigationOpen:n,onOpenGoalCapabilities:r,onOpenGoalDetail:i,onOpenManagerChat:a,onRefresh:o,onOpenNavigation:s,onSelectGoalTab:c,onSelectAgent:l,onReturnManagerHome:u,refreshState:d,readOnlySourceLabel:f,selectedAgentId:p,selectedGoal:m,selectedGoalTab:h}){let{locale:g,t:_}=Ji(),[v,y]=(0,R.useState)(!1),b=(0,R.useRef)(null),x=(0,R.useRef)(null);(0,R.useEffect)(()=>{if(!v)return;function e(e){x.current?.contains(e.target)||y(!1)}function t(e){e.key===`Escape`&&(y(!1),b.current?.focus())}return document.addEventListener(`pointerdown`,e),document.addEventListener(`keydown`,t),()=>{document.removeEventListener(`pointerdown`,e),document.removeEventListener(`keydown`,t)}},[v]),(0,R.useEffect)(()=>y(!1),[m?.goalId]);function S(e){y(!1),e?.()}let C=m?sy(m.usage,{cost:_(`drawer.costShort`),duration:_(`drawer.durationShort`),period24h:_(`drawer.period24h`),period7d:_(`drawer.period7d`),tokens:_(`drawer.tokensShort`)}):null;return(0,z.jsxs)(`header`,{className:`personal-channel-header`,children:[(0,z.jsx)(`button`,{"aria-expanded":n??!1,"aria-label":_(`header.openGoalNavigation`),className:`personal-icon-button personal-mobile-menu`,onClick:s,type:`button`,children:(0,z.jsx)(_m,{size:18})}),(0,z.jsxs)(`div`,{className:`personal-channel-title`,children:[(0,z.jsx)(`h1`,{children:m?.title??_(`header.manager`)}),(0,z.jsx)(`p`,{children:m?m.loadState?_(m.loadState===`error`?`startup.goalError`:`startup.goalLoading`):`${m.agentLaneCount&&m.agentLaneCount>1?_(`header.workAgentCount`,{count:m.agentLaneCount}):m.agentLabel??m.agentId} · ${m.loadState?_(m.loadState===`error`?`startup.goalError`:`startup.goalLoading`):Yi(m.state,g)}${C?` · ${C}`:``} · ${m.nextSentence}`:_(`header.managerDescription`)})]}),m?(0,z.jsxs)(`nav`,{"aria-label":_(`header.goalView`),className:`personal-goal-tabs`,children:[(0,z.jsx)(`button`,{"aria-current":h===`chat`?`page`:void 0,onClick:()=>c(`chat`),type:`button`,children:_(`header.chat`)}),(0,z.jsx)(`button`,{"aria-current":h===`tasks`?`page`:void 0,onClick:()=>c(`tasks`),type:`button`,children:_(`header.tasks`)}),(0,z.jsx)(`button`,{"aria-current":h===`files`?`page`:void 0,onClick:()=>c(`files`),type:`button`,children:_(`header.files`)})]}):(0,z.jsxs)(`nav`,{"aria-label":_(`header.managerView`),className:`personal-goal-tabs`,children:[(0,z.jsx)(`button`,{"aria-current":t?void 0:`page`,onClick:u,type:`button`,children:_(`header.managerOverview`)}),(0,z.jsx)(`button`,{"aria-current":t?`page`:void 0,onClick:a,type:`button`,children:_(`header.chat`)})]}),(0,z.jsxs)(`div`,{className:`personal-channel-actions`,children:[m&&i&&r?(0,z.jsxs)(`div`,{className:`personal-goal-tools`,ref:x,children:[(0,z.jsxs)(`button`,{"aria-expanded":v,"aria-haspopup":`menu`,"aria-label":_(`header.goalSettingsDescription`),className:`personal-goal-tools-trigger`,onClick:()=>y(e=>!e),ref:b,title:_(`header.goalSettingsDescription`),type:`button`,children:[(0,z.jsx)(Lm,{"aria-hidden":!0,size:16}),(0,z.jsx)(`span`,{children:_(`header.goalSettings`)}),(0,z.jsx)(qp,{"aria-hidden":!0,size:13})]}),v?(0,z.jsxs)(`fieldset`,{"aria-label":_(`header.goalSettings`),className:`personal-goal-tools-menu`,children:[(0,z.jsxs)(`button`,{onClick:()=>S(i),type:`button`,children:[(0,z.jsx)(dm,{"aria-hidden":!0,size:17}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:_(`header.goalDetails`)}),(0,z.jsx)(`small`,{children:_(`header.goalDetailsDescription`)})]})]}),(0,z.jsxs)(`button`,{onClick:()=>S(r),type:`button`,children:[(0,z.jsx)(Lm,{"aria-hidden":!0,size:17}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:_(`header.goalCapabilities`)}),(0,z.jsx)(`small`,{children:_(`header.goalCapabilitiesDescription`)})]})]})]}):null]}):null,f?(0,z.jsxs)(`span`,{className:`personal-read-only-source`,title:_(`header.readOnlySourceDescription`,{source:f}),children:[(0,z.jsx)(am,{size:15}),f,(0,z.jsx)(`small`,{children:_(`common.readOnly`)})]}):(0,z.jsx)(cy,{ariaLabel:_(`header.selectChatRuntime`),className:`personal-agent-select`,icon:(0,z.jsx)(Up,{size:16}),onChange:l,options:e.map(e=>({disabled:!e.available,label:`${e.label}${e.available?``:` · ${_(`header.agentUnavailable`)}`}`,value:e.agentId})),prefixLabel:_(`header.chatRuntime`),value:p}),(0,z.jsxs)(`span`,{className:`personal-live-indicator`,children:[(0,z.jsx)(`i`,{}),_(`header.live`)]}),o?(0,z.jsxs)(`span`,{className:`personal-refresh-control is-${d??`idle`}`,children:[d===`loading`?(0,z.jsx)(`small`,{children:_(`header.refreshing`)}):d===`done`?(0,z.jsx)(`small`,{children:_(`header.refreshDone`)}):d===`error`?(0,z.jsx)(`small`,{children:_(`header.refreshFailed`)}):null,(0,z.jsx)(`button`,{"aria-label":_(d===`loading`?`header.refreshing`:`header.refresh`),className:`personal-icon-button`,disabled:d===`loading`,onClick:o,type:`button`,children:(0,z.jsx)(Om,{className:d===`loading`?`is-spinning`:void 0,size:17})})]}):null]})]})}function uy({attention:e,onSelect:t}){let{t:n}=Ji(),r=Zi(e.updatedAt,n);return(0,z.jsxs)(`button`,{className:`personal-timeline-row personal-attention-row`,"data-testid":`personal-browse-row`,onClick:t,type:`button`,children:[(0,z.jsx)(`span`,{className:`personal-row-icon is-attention`,children:(0,z.jsx)(Xp,{size:18})}),(0,z.jsxs)(`span`,{className:`personal-row-copy`,children:[(0,z.jsxs)(`small`,{children:[e.goalTitle??e.goalId,` · `,n(`home.lane.needsYou`),r?` · ${n(`tasks.waitingAge`,{age:r})}`:``]}),(0,z.jsx)(`strong`,{children:e.text})]}),(0,z.jsx)(`span`,{className:`personal-priority-dot is-${e.priority??(e.blocking?`high`:`medium`)}`}),(0,z.jsx)(`span`,{className:`personal-row-status ${e.blocking?`is-blocking`:`is-pending`}`,children:e.blocking?n(`tasks.blocked`):n(`tasks.pending`)}),(0,z.jsx)(Jp,{size:17})]})}var dy=/(`[^`\n]+`)|(\*\*[^*\n]+(\*[^*\n]*)?\*\*)|(\[[^\]\n]{1,120}\]\(https?:\/\/[^)\s]+\))/g;function fy(e,t){let n=[],r=0,i=0;for(let a of e.matchAll(dy)){let o=a.index??0;o>r&&n.push(e.slice(r,o));let s=a[0],c=`${t}-i${i++}`;if(s.startsWith("`"))n.push((0,z.jsx)(`code`,{className:`personal-md-code`,children:s.slice(1,-1)},c));else if(s.startsWith(`**`))n.push((0,z.jsx)(`strong`,{children:s.slice(2,-2)},c));else{let e=s.indexOf(`](`),t=s.slice(1,e),r=s.slice(e+2,-1);n.push((0,z.jsx)(`a`,{className:`personal-md-link`,href:r,rel:`noreferrer`,target:`_blank`,children:t},c))}r=o+s.length}return r{r.length>0&&(n.push({type:`paragraph`,lines:r}),r=[])},a=0;for(;a{let n=`b${t}`;if(e.type===`code`)return(0,z.jsx)(`pre`,{className:`personal-md-pre`,children:(0,z.jsx)(`code`,{children:e.text})},n);if(e.type===`heading`)return(0,z.jsx)(`p`,{className:`personal-md-heading is-h${e.level}`,children:ly(e.text,n)},n);if(e.type===`list`){let t=e.items.map((e,t)=>(0,z.jsx)(`li`,{children:ly(e,`${n}-${t}`)},`${n}-${t}`));return e.ordered?(0,z.jsx)(`ol`,{className:`personal-md-list`,children:t},n):(0,z.jsx)(`ul`,{className:`personal-md-list`,children:t},n)}return(0,z.jsx)(`p`,{children:e.lines.map((e,t)=>(0,z.jsxs)(R.Fragment,{children:[t>0?(0,z.jsx)(`br`,{}):null,ly(e,`${n}-${t}`)]},`${n}-${t}`))},n)})})}function my({onSelect:e,output:t}){let{t:n}=Ji(),r=t.kind===`report`?cm:sm;return(0,z.jsxs)(`button`,{className:`personal-timeline-row personal-output-row`,"data-output-kind":t.kind,"data-testid":`personal-browse-row`,onClick:e,type:`button`,children:[(0,z.jsx)(`span`,{className:`personal-row-icon is-output`,children:(0,z.jsx)(r,{size:18})}),(0,z.jsxs)(`span`,{className:`personal-row-copy`,children:[(0,z.jsxs)(`small`,{children:[t.goalTitle??t.goalId,` · `,t.agentLabel??`LoopX`]}),(0,z.jsx)(`strong`,{children:t.title}),t.summary?(0,z.jsx)(`span`,{children:t.summary}):null,t.report?(0,z.jsxs)(`small`,{children:[n(`files.reportDelta`,{added:t.report.addedCount,changed:t.report.changedCount}),` · `,n(`files.verifiedReport`)]}):null]}),t.createdAt?(0,z.jsx)(`time`,{children:t.createdAt}):null,(0,z.jsx)(Jp,{size:17})]})}var hy={completed:`runs.completed`,failed:`runs.failed`,interrupted:`runs.interrupted`,queued:`runs.queued`,running:`runs.running`,waiting:`runs.waiting`};function gy({onSelect:e,run:t}){let{t:n}=Ji(),r=t.totalSteps>0?Math.min(100,t.completedSteps/t.totalSteps*100):0;return(0,z.jsxs)(`button`,{"aria-label":`${n(`tasks.viewExecution`)}:${t.title}`,className:`personal-timeline-row personal-run-row`,"data-testid":`personal-browse-row`,onClick:e,type:`button`,children:[(0,z.jsx)(`span`,{className:`personal-row-icon is-run`,children:(0,z.jsx)(Up,{size:18})}),(0,z.jsxs)(`span`,{className:`personal-run-identity`,children:[(0,z.jsx)(`small`,{children:t.goalTitle}),(0,z.jsx)(`strong`,{children:t.agentLabel})]}),(0,z.jsxs)(`span`,{className:`personal-row-copy`,children:[(0,z.jsx)(`strong`,{children:t.title}),(0,z.jsx)(`small`,{children:t.latestActivity})]}),(0,z.jsxs)(`span`,{className:`personal-run-progress`,"aria-label":`${t.completedSteps}/${t.totalSteps}`,children:[(0,z.jsxs)(`small`,{children:[t.completedSteps,`/`,t.totalSteps]}),(0,z.jsx)(`i`,{children:(0,z.jsx)(`b`,{style:{width:`${r}%`}})})]}),(0,z.jsxs)(`span`,{className:`personal-row-status is-${t.status}`,children:[t.status===`running`?(0,z.jsx)(hm,{className:`personal-spin`,size:14}):null,n(hy[t.status])]}),t.sessionId?(0,z.jsx)(`span`,{className:`personal-run-open-label`,children:n(`tasks.viewExecution`)}):null,(0,z.jsx)(Jp,{size:17})]})}function _y({onSelect:e,schedule:t}){let{t:n}=Ji(),r=t.scheduleKind===`heartbeat`;return(0,z.jsxs)(`button`,{"aria-label":`${r?`Heartbeat`:n(`tasks.scheduled`)}:${t.label};${t.status??`active`}`,className:`personal-schedule-row`,onClick:e,type:`button`,children:[(0,z.jsx)(`span`,{className:`personal-schedule-icon`,children:r?(0,z.jsx)(Dm,{size:17}):(0,z.jsx)(Gp,{size:17})}),(0,z.jsxs)(`span`,{className:`personal-schedule-copy`,children:[(0,z.jsx)(`small`,{children:n(r?`schedule.heartbeat`:`schedule.monitor`)}),(0,z.jsx)(`strong`,{children:t.label}),(0,z.jsx)(`p`,{children:t.schedule??n(`schedule.summary`)})]}),(0,z.jsx)(`span`,{className:`personal-schedule-status is-${t.status??`active`}`,children:t.status===`paused`?n(`schedule.paused`):n(`schedule.active`)}),(0,z.jsx)(Jp,{size:16})]})}function vy({items:e,onSelect:t,selectedGoal:n}){let{t:r}=Ji();if(e.length===0)return(0,z.jsxs)(`div`,{className:`personal-timeline-empty`,children:[(0,z.jsx)(`span`,{children:(0,z.jsx)(Rm,{size:20})}),(0,z.jsx)(`strong`,{children:r(n?`timeline.emptyGoal`:`timeline.emptyWorkspace`)}),(0,z.jsx)(`p`,{children:r(n?`timeline.emptyGoalDescription`:`timeline.emptyWorkspaceDescription`)})]});let i=[...e].reverse().find(e=>e.kind===`message`&&e.message.role!==`user`||e.kind===`proposal`&&[`applied`,`stale`,`error`,`gated`].includes(e.proposal.status)||e.kind===`run`&&e.run.status===`completed`),a=i?.kind===`message`?`${i.message.agentLabel??r(`header.manager`)}:${i.message.pending?r(`timeline.pending`):i.message.text}`:i?.kind===`proposal`?`${i.proposal.title}:${i.proposal.status}`:i?.kind===`run`?r(`timeline.runCompleted`,{run:i.run.title}):``,o=e.filter(e=>e.kind===`proposal`&&e.proposal.status===`gated`),s=e.filter(e=>e.kind!==`proposal`),c=e.filter(e=>e.kind===`proposal`&&e.proposal.status!==`gated`);function l(e){return e.kind===`attention`?(0,z.jsx)(sy,{attention:e.attention,onSelect:()=>t({item:e.attention,kind:`attention`})},e.id):e.kind===`run`?(0,z.jsx)(gy,{onSelect:()=>t({item:e.run,kind:`run`}),run:e.run},e.id):e.kind===`output`?(0,z.jsx)(my,{onSelect:()=>t({item:e.output,kind:`output`}),output:e.output},e.id):e.kind===`schedule`?(0,z.jsx)(_y,{onSelect:()=>t({item:e.schedule,kind:`schedule`}),schedule:e.schedule},e.id):e.kind===`proposal`?(0,z.jsxs)(`button`,{className:`personal-proposal-row is-${e.proposal.status}`,onClick:()=>t({item:e.proposal,kind:`proposal`}),type:`button`,children:[(0,z.jsx)(`span`,{children:(0,z.jsx)(Rm,{size:17})}),(0,z.jsxs)(`span`,{children:[(0,z.jsxs)(`small`,{children:[e.proposal.actionKind,` · `,e.proposal.status]}),(0,z.jsx)(`strong`,{children:e.proposal.title}),(0,z.jsx)(`p`,{children:e.proposal.impact})]}),(0,z.jsx)(`b`,{children:e.proposal.status===`gated`?r(`timeline.review`):e.proposal.primaryLabel??r(`timeline.reviewAndConfirm`)})]},e.id):(0,z.jsxs)(`article`,{className:`personal-message is-${e.message.role}`,children:[e.message.role===`user`?null:(0,z.jsx)(`span`,{className:`personal-message-avatar`,children:(0,z.jsx)(Up,{size:17})}),(0,z.jsxs)(`div`,{children:[(0,z.jsxs)(`header`,{children:[(0,z.jsx)(`strong`,{children:e.message.role===`user`?r(`common.you`):e.message.agentLabel??r(`header.manager`)}),e.message.time?(0,z.jsx)(`time`,{children:e.message.time}):null]}),e.message.attachments?.length?(0,z.jsx)(`div`,{className:`personal-message-images`,children:e.message.attachments.map(e=>(0,z.jsx)(`img`,{alt:e.name,src:e.dataUrl},e.id))}):null,e.message.role===`user`?(0,z.jsx)(`p`,{children:e.message.text}):(0,z.jsx)(py,{text:e.message.text}),e.message.pending?(0,z.jsx)(`span`,{className:`personal-message-pending`,children:r(`timeline.pending`)}):null]})]},e.id)}return(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`p`,{"aria-atomic":`true`,"aria-live":`polite`,className:`personal-live-region`,role:`status`,children:a}),(0,z.jsxs)(`div`,{className:`personal-channel-timeline`,children:[s.map(l),o.length?(0,z.jsxs)(`details`,{className:`personal-gated-summary`,children:[(0,z.jsxs)(`summary`,{children:[(0,z.jsx)(`span`,{children:(0,z.jsx)(Rm,{size:16})}),(0,z.jsx)(`strong`,{children:r(`timeline.waitingConfirmation`)}),(0,z.jsx)(`small`,{children:r(`timeline.gateHistory`,{count:o.length})})]}),(0,z.jsx)(`div`,{children:o.map(l)})]}):null,c.map(l)]})]})}function yy(e){return e.replace(/\s+/gu,` `).trim()}function by(e,t){let n=RegExp(`(?:不要|不需要|无需|禁止|别|暂不|do not\\b|don't\\b|without\\b).{0,10}(?:${t.source})`,`iu`),r=RegExp(`(?:${t.source}).{0,10}(?:不要|不需要|无需|禁止|关闭)`,`iu`),i=RegExp(`disable\\b.{0,10}(?:${t.source})|(?:turn|switch|set)\\b.{0,10}(?:${t.source}).{0,10}\\boff\\b|(?:${t.source})\\s+(?:is\\s+)?disabled\\b`,`iu`);return n.test(e)||r.test(e)||i.test(e)}function xy(e){return/(我现在该做什么|下一步|哪些\s*Goal\s*在等我|需要我|谁在等我|Agent\s*在做什么|当前进度|总结(?:今天)?进展)/iu.test(e)}function Sy(e){let t=/(怎么|如何|为什么|给.*建议|分析一下|解释|只读)/u.test(e),n=/(解决一下|修复一下|处理一下|执行一下|改一下|跑(?:一下)?测试|rebase|push|提交|推送)/iu.test(e);return!t&&n&&/(帮我|请|给我|直接|现在|开始|bytedcli|codebase|git|rebase|push|提交|推送)/iu.test(e)}function Cy(e){return yy(e).toLowerCase().match(/(?:^|[\s,,;;:((:]|到|至)(?todo_done:todo_[a-z0-9_-]{3,64}|pr_merged:(?:(?:[a-z0-9_.-]{1,80})\/(?:[a-z0-9_.-]{1,100}))?#[1-9][0-9]{0,8}|capacity_available:[a-z][a-z0-9_:-]{0,63})(?=$|[\s,,。;;))])/iu)?.groups?.condition??null}function wy(e,t){let n=yy(e),r=[],i=t.agents.find(e=>{let t=n.toLowerCase();return t.includes(e.agentId.toLowerCase())||t.includes(e.label.toLowerCase())}),a=t.todos.find(e=>n.includes(e.todoId)||n.includes(e.text)),o=/(刚刚|已经|已)(?:经)?\s*(新增|创建|添加)(?:的)?\s*(todo|待办|任务)/iu.test(n),s=!!t.goalId&&!by(n,/heartbeat|心跳/iu)&&/(heartbeat|心跳|每天推进|持续推进|daily progress)/iu.test(n);if(!t.goalId&&!by(n,/goal|目标/iu)&&/(创建|新建|设置|create|start|set up).{0,24}(goal|目标)/iu.test(n)&&r.push({actionKind:`goal.create`,confidence:.97,normalizedParameters:{heartbeat_enabled:!by(n,/heartbeat|心跳/iu)&&/(heartbeat|心跳|每天推进|持续推进|daily progress)/iu.test(n)}}),t.goalId&&s&&r.push({actionKind:`heartbeat.bind`,confidence:.96,normalizedParameters:{goal_id:t.goalId}}),t.goalId&&!s&&!by(n,/定时|监控|监测|持续观察|scheduled check|monitor/iu)&&/(定时|监控|监测|每.{0,8}(分钟|小时|天)|持续观察|scheduled check|monitor|every.{0,12}(minute|hour|day)|daily)/iu.test(n)&&r.push({actionKind:`monitor.create`,confidence:.94,normalizedParameters:{goal_id:t.goalId}}),t.goalId&&i&&!by(n,/绑定|负责|接管|管理/iu)&&/((让|交给).{0,20}(管理|负责|接管).{0,8}(goal|目标)|(绑定).{0,12}(goal|目标)|(goal|目标).{0,12}(交给|绑定|负责|接管))/iu.test(n)&&r.push({actionKind:`agent.bind`,confidence:.96,normalizedParameters:{agent_id:i.agentId,goal_id:t.goalId}}),t.goalId&&!o&&!by(n,RegExp(`todo|待办|任务`,`iu`))&&/(创建|新建|新增|添加|加一个|记一个).{0,16}(todo|待办|任务)|(todo|待办|任务).{0,12}(创建|新建|新增|添加)|(?:create|add)(?:\s+(?:a|an|new))?\s+(?:todo|task)|(?:todo|task).{0,12}(?:create|add)/iu.test(n)&&r.push({actionKind:`todo.create`,confidence:.94,normalizedParameters:{goal_id:t.goalId}}),t.goalId&&Sy(n)&&r.push({actionKind:`todo.create`,confidence:.9,normalizedParameters:{goal_id:t.goalId,start_execution:!0}}),t.goalId&&a){let e=!by(n,/完成|做完|关闭/u)&&/完成|做完|关闭/u.test(n)?`complete`:!by(n,/阻塞|卡住/u)&&/阻塞|卡住/u.test(n)?`block`:!by(n,/暂缓|稍后|推迟/u)&&/暂缓|稍后|推迟/u.test(n)?`defer`:i&&!by(n,/交给|分配给|改派/u)&&/交给|分配给|改派/u.test(n)?`reassign`:null;if(e){let i=e===`defer`?Cy(n):null;if(e===`defer`&&!i)return{actionKind:`todo.update`,confidence:.97,missingFields:[`resume_when`],normalizedParameters:{goal_id:t.goalId,operation:e,todo_id:a.todoId},route:`clarify`};r.push({actionKind:`todo.update`,confidence:.97,normalizedParameters:{goal_id:t.goalId,operation:e,...i?{resume_when:i}:{},todo_id:a.todoId}})}}let c=[...new Map(r.map(e=>[e.actionKind,e])).values()];return c.length>1?{actionKind:null,confidence:.4,missingFields:[`single_intent`],normalizedParameters:{},route:`clarify`}:c.length===1?{...c[0],missingFields:[],route:`typed_action`}:!t.goalId&&xy(n)?{actionKind:null,confidence:.98,missingFields:[],normalizedParameters:{},route:`projection`}:{actionKind:null,confidence:.75,missingFields:[],normalizedParameters:{},route:`agent_chat`}}var Ty=[`a[href]`,`button:not([disabled])`,`textarea:not([disabled])`,`select:not([disabled])`,`input:not([disabled])`,`[tabindex]:not([tabindex='-1'])`].join(`,`),Ey=[{key:`drawer.taskBlock`,operation:`block`},{key:`drawer.taskSuccessor`,operation:`successor_create`}],Dy=[{key:`drawer.decisionReject`,resolution:`reject`},{key:`drawer.decisionDefer`,resolution:`defer`}],Oy=Array.from({length:32},(e,t)=>t+1),ky=/^[a-z][a-z0-9_.-]{0,63}$/u;function Ay(e){let t=String(e??``).trim().toLowerCase();return ky.test(t)?t:null}function jy(e,t){return e.enabled===t.enabled&&e.maxChildren===t.maxChildren&&[...e.allowedDomains].sort((e,t)=>e.localeCompare(t)).join(`\0`)===[...t.allowedDomains].sort((e,t)=>e.localeCompare(t)).join(`\0`)}function My({agents:e,callbacks:t,goalNotifications:n=[],goals:r=[],inspectorExpanded:i=!1,larkConnections:a=[],onClose:o,onToggleInspectorSize:s,readOnly:c=!1,runs:l=[],selection:u}){let{locale:d,t:f}=Ji(),[p,m]=(0,R.useState)(``),[h,g]=(0,R.useState)(!1),[_,v]=(0,R.useState)(`idle`),[y,b]=(0,R.useState)(`record`),[x,S]=(0,R.useState)([]),[C,w]=(0,R.useState)(null),[T,E]=(0,R.useState)(2),[D,O]=(0,R.useState)(`idle`),[k,ee]=(0,R.useState)(null),[A,j]=(0,R.useState)(null),te=(0,R.useRef)(null),ne=(0,R.useRef)(null),[re,M]=(0,R.useState)(e.find(e=>e.available)?.agentId??`codex`),[N,ie]=(0,R.useState)(``),ae=(0,R.useRef)(null),oe=(0,R.useRef)(null),P=(0,R.useRef)(null),F=(0,R.useRef)(null),I=u.kind===`run`?`run:${u.item.runId}`:u.kind===`proposal`?`proposal:${u.item.previewId}`:u.kind===`todo`?`todo:${u.item.todoId}`:u.kind===`attention`?`attention:${u.item.todoId}`:u.kind===`output`?`output:${u.item.outputId}`:u.kind===`schedule`?`schedule:${u.item.scheduleId}`:`goal:${u.item.goalId}`;(0,R.useEffect)(()=>{v(`idle`),g(!1),b(`record`),ie(``);let e=u.kind===`goal`?u.item.subagentExecution:void 0;S(e?.allowedDomains??[]),E(e?.maxChildren?Math.min(e.maxChildren,32):2),w(null),O(`idle`),ee(null),j(null),te.current=e??null,ne.current=null},[I]);let se=u.kind===`goal`?u.item.subagentExecution:void 0;(0,R.useEffect)(()=>{let e=te.current,t=se?!e||!jy(e,se):e!==null;if(te.current=se??null,!A){t&&se&&(S(se.allowedDomains),E(se.maxChildren||2),w(null),O(`idle`),ee(null));return}let n=ne.current;(!se||jy(A,se)||n&&!jy(n,se))&&(se&&(S(se.allowedDomains),E(se.maxChildren||2)),ne.current=null,j(null))},[se,A]),(0,R.useEffect)(()=>{let e=document.activeElement;e instanceof HTMLElement&&!oe.current?.contains(e)&&(P.current=e);let t=window.requestAnimationFrame(()=>F.current?.focus());return()=>window.cancelAnimationFrame(t)},[I]);let ce=(0,R.useCallback)(()=>{let e=P.current;o(),window.requestAnimationFrame(()=>e?.focus())},[o]);(0,R.useEffect)(()=>{function e(e){if(e.key===`Escape`){e.preventDefault(),ce();return}if(e.key===`Tab`&&u.kind!==`todo`){let t=Array.from(oe.current?.querySelectorAll(Ty)??[]).filter(e=>!e.hasAttribute(`disabled`)&&e.getAttribute(`aria-hidden`)!==`true`);if(t.length===0)return;let n=t[0],r=t[t.length-1];e.shiftKey&&document.activeElement===n?(e.preventDefault(),r.focus()):!e.shiftKey&&document.activeElement===r&&(e.preventDefault(),n.focus())}}return document.addEventListener(`keydown`,e),()=>{document.removeEventListener(`keydown`,e)}},[ce,u.kind]);let le=u.kind===`attention`?f(`drawer.titleAttention`):u.kind===`todo`?f(`drawer.taskDetails`):u.kind===`run`?f(`drawer.runDetails`):u.kind===`output`?f(`drawer.titleOutput`):u.kind===`proposal`?f(u.item.status===`applied`?`drawer.titleProposalApplied`:`drawer.titleProposalConfirm`):u.kind===`schedule`?u.item.scheduleKind===`heartbeat`?`Heartbeat`:f(`drawer.titleSchedule`):f(`drawer.goalDetails`),ue=u.kind===`proposal`?u.item.goalId??`manager`:u.item.goalId,de=u.kind===`attention`?u.item.goalTitle??f(`drawer.currentGoal`):u.kind===`todo`||u.kind===`run`?u.item.goalTitle:u.kind===`output`?u.item.goalTitle??f(`drawer.currentGoal`):u.kind===`goal`?u.item.title:u.kind===`schedule`?f(`drawer.goalAutoRun`):u.item.goalId?f(`drawer.goalChanges`):f(`drawer.managerChanges`),fe=u.kind===`goal`?l.find(e=>e.goalId===u.item.goalId&&!!e.sessionId)??l.find(e=>e.goalId===u.item.goalId):null,pe=u.kind===`run`&&(u.item.completedSteps>0||!!u.item.latestActivity||!!u.item.outputs?.length),me=u.kind===`attention`?Zi(u.item.updatedAt,f):null,he=Cy(N);async function ge(){u.kind!==`run`||!p.trim()||(await t.onCorrectRun?.(u.item,p.trim()),m(``))}async function _e(e,n,r,i){if(n===`successor_create`){await t.onPreviewAction?.({actionKind:`todo.create`,context:{goal_id:e.goalId,kind:`todo`,todo_id:e.todoId},idempotencyKey:`workspace-todo-successor-${e.todoId}-${Date.now().toString(36)}`,normalizedParameters:{goal_id:e.goalId,text:f(`drawer.taskSuccessorText`,{task:e.text})},summary:f(`drawer.taskSuccessorSummary`,{task:e.text})});return}await t.onPreviewAction?.({actionKind:`todo.update`,context:{goal_id:e.goalId,kind:`todo`,todo_id:e.todoId},idempotencyKey:`workspace-todo-${e.todoId}-${n}-${Date.now().toString(36)}`,normalizedParameters:{agent_id:e.claimedBy??re,goal_id:e.goalId,operation:n,...n===`block`?{note:f(`drawer.taskSuccessorNote`)}:{},...n===`defer`&&i?{resume_when:i}:{},todo_id:e.todoId},summary:`${r}:${e.text}`})}async function ve(e,n,r){await t.onPreviewAction?.({actionKind:`gate.resolve`,context:{goal_id:e.goalId,kind:`todo`,todo_id:e.todoId},idempotencyKey:`workspace-decision-${e.todoId}-${n}-${Date.now().toString(36)}`,normalizedParameters:{goal_id:e.goalId,decision:n,todo_id:e.todoId},summary:`${r}:${e.text}`})}let ye=u.kind===`goal`?A??u.item.subagentExecution??{allowedDomains:[],domainCandidates:[],enabled:!1,maxChildren:0}:{allowedDomains:[],domainCandidates:[],enabled:!1,maxChildren:0},be=D===`previewing`||D===`applying`,xe=(()=>{if(u.kind!==`goal`)return[];let e=new Map;for(let t of ye.allowedDomains){let n=Ay(t);n&&e.set(n,{matchingTodoCount:0,value:n})}if(ye.domainCandidates)for(let t of ye.domainCandidates){let n=Ay(t.domain);if(!n)continue;let r=e.get(n);e.set(n,{matchingTodoCount:(r?.matchingTodoCount??0)+t.matchingTodoCount,value:n})}else for(let t of u.item.agentTodos){if(t.done||t.taskClass!==`advancement_task`)continue;let n=Ay(t.taskDomain);if(!n)continue;let r=e.get(n);e.set(n,{matchingTodoCount:(r?.matchingTodoCount??0)+1,value:n})}return[...e.values()]})();function Se(){S(ye.allowedDomains),E(ye.maxChildren||2),w(null),O(`idle`),ee(null)}function Ce(){let e=[...new Set(x.map(e=>Ay(e)))];return e.every(e=>!!e)?e:null}function we(e,t){S(n=>t?[...n,e].filter((e,t,n)=>n.indexOf(e)===t):n.filter(t=>t!==e)),ee(null),O(`idle`),w(null)}async function Te(e){if(u.kind!==`goal`||!t.onPreviewGoalSubagentConfiguration)return;let n=e?Ce():[];if(e&&!n){O(`error`),w(f(`drawer.subagentDomainInvalid`)),ee(null);return}let r={allowedDomains:n??[],enabled:e,goalId:u.item.goalId,maxChildren:e?T:0};O(`previewing`),w(f(`drawer.subagentPreviewing`)),ee(null);try{let e=await t.onPreviewGoalSubagentConfiguration(r);if(!e.changed){ne.current=se??null,j({...e.configuration,domainCandidates:ye.domainCandidates}),S(e.configuration.allowedDomains),E(e.configuration.maxChildren||2),O(`success`),w(f(`drawer.subagentNoChange`));return}ee({...r,changed:e.changed,previewId:e.previewId}),O(`ready`),w(f(`drawer.subagentPreviewReady`))}catch(e){O(`error`),w(e instanceof Error?e.message:f(`drawer.subagentPreviewFailed`))}}async function Ee(){if(!(!k||!t.onApplyGoalSubagentConfiguration)){O(`applying`),w(f(`drawer.subagentApplying`));try{let e=await t.onApplyGoalSubagentConfiguration({allowedDomains:k.allowedDomains,enabled:k.enabled,goalId:k.goalId,maxChildren:k.maxChildren,previewId:k.previewId});ne.current=se??null,j({...e,domainCandidates:ye.domainCandidates}),S(e.allowedDomains),E(e.maxChildren||2),O(`success`),w(f(`drawer.subagentApplied`)),ee(null);try{await t.onRefresh?.()}catch{O(`warning`),w(f(`drawer.subagentAppliedRefreshFailed`))}}catch(e){O(`error`),w(e instanceof Error?e.message:f(`drawer.subagentApplyFailed`))}}}return(0,z.jsxs)(`div`,{"aria-labelledby":`personal-drawer-title`,"aria-modal":u.kind===`todo`?void 0:`true`,className:`personal-context-drawer`,"data-context-kind":u.kind,ref:oe,role:`dialog`,children:[(0,z.jsxs)(`header`,{className:`personal-drawer-header${u.kind===`todo`?` is-task-inspector`:``}`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`h2`,{id:`personal-drawer-title`,ref:F,tabIndex:-1,children:le}),(0,z.jsx)(`p`,{children:de})]}),(0,z.jsxs)(`div`,{className:`personal-drawer-header-actions`,children:[u.kind===`todo`&&s?(0,z.jsx)(`button`,{"aria-label":f(i?`drawer.inspectorHalf`:`drawer.inspectorFull`),className:`personal-icon-button personal-inspector-size`,onClick:s,title:f(i?`drawer.inspectorHalfView`:`drawer.inspectorFullView`),type:`button`,children:i?(0,z.jsx)(bm,{size:17}):(0,z.jsx)(gm,{size:17})}):null,(0,z.jsxs)(`button`,{"aria-label":f(`drawer.closeDetail`,{context:de}),className:`personal-icon-button personal-drawer-close`,onClick:ce,ref:ae,type:`button`,children:[(0,z.jsx)(Lp,{className:`personal-mobile-back`,size:18}),(0,z.jsx)(Gm,{className:`personal-desktop-close`,size:18})]})]})]}),(0,z.jsxs)(`div`,{className:`personal-drawer-body`,children:[u.kind===`attention`?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`section`,{className:`personal-detail-card is-attention`,children:[(0,z.jsx)(`small`,{children:u.item.blocking?f(`drawer.attentionBlocking`):f(`drawer.attentionWaiting`)}),(0,z.jsx)(`h3`,{children:u.item.text}),(0,z.jsxs)(`dl`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Goal`}),(0,z.jsx)(`dd`,{children:u.item.goalTitle??u.item.goalId})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.priority`)}),(0,z.jsx)(`dd`,{children:u.item.priority??`medium`})]}),me?(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`common.waiting`)}),(0,z.jsx)(`dd`,{children:f(`tasks.waitingAge`,{age:me})})]}):null,(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.reason`)}),(0,z.jsx)(`dd`,{children:u.item.explanation??f(`drawer.decisionDefaultReason`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.evidence`)}),(0,z.jsx)(`dd`,{children:u.item.evidence??f(`drawer.decisionDefaultEvidence`)})]})]})]}),c?null:(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`button`,{className:`personal-primary-action`,onClick:()=>void ve(u.item,`approve`,f(`common.confirm`)),type:`button`,children:[(0,z.jsx)(Kp,{size:17}),f(`drawer.decisionReview`)]}),(0,z.jsxs)(`details`,{className:`personal-compact-menu`,children:[(0,z.jsxs)(`summary`,{children:[(0,z.jsx)(rm,{size:17}),f(`drawer.decisionMore`)]}),(0,z.jsxs)(`div`,{children:[(0,z.jsxs)(`button`,{onClick:()=>void t.onExplainDecision?.(u.item),type:`button`,children:[(0,z.jsx)(vm,{size:16}),f(`drawer.explainDecision`)]}),Dy.map(e=>(0,z.jsx)(`button`,{onClick:()=>void ve(u.item,e.resolution,f(e.key)),type:`button`,children:f(e.key)},e.resolution))]})]})]})]}):null,u.kind===`todo`?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`section`,{className:`personal-task-inspector-summary`,children:[(0,z.jsxs)(`div`,{className:`personal-task-inspector-status`,children:[(0,z.jsxs)(`span`,{className:u.item.done?`is-done`:u.item.status===`blocked`?`is-blocked`:`is-open`,children:[(0,z.jsx)(`i`,{}),u.item.done?f(`drawer.taskStatusCompleted`):u.item.status===`deferred`?f(`drawer.taskStatusDeferred`):u.item.status===`blocked`?f(`drawer.taskStatusBlocked`):f(`drawer.taskStatusOpen`)]}),u.item.priority?(0,z.jsx)(`span`,{children:u.item.priority}):null,(0,z.jsx)(`span`,{children:u.item.taskClass===`advancement_task`?f(`drawer.taskAdvancement`):u.item.taskClass??f(`drawer.taskOrdinary`)})]}),(0,z.jsx)(`h3`,{children:u.item.text})]}),(0,z.jsxs)(`section`,{"aria-label":f(`drawer.taskInfo`),className:`personal-task-inspector-fields`,children:[(0,z.jsx)(`h4`,{children:f(`drawer.taskInfo`)}),(0,z.jsxs)(`dl`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Goal`}),(0,z.jsx)(`dd`,{children:u.item.goalTitle})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`common.owner`)}),(0,z.jsx)(`dd`,{children:u.item.ownerLabel??u.item.claimedBy??f(`drawer.notAssigned`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`common.status`)}),(0,z.jsx)(`dd`,{children:u.item.done?f(`drawer.taskStatusCompleted`):u.item.status===`deferred`?f(`drawer.taskStatusDeferred`):u.item.status===`blocked`?f(`drawer.taskStatusBlocked`):f(`drawer.taskStatusOpen`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.priority`)}),(0,z.jsx)(`dd`,{children:u.item.priority??f(`drawer.notSet`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.dependencies`)}),(0,z.jsx)(`dd`,{children:u.item.dependencies?.join(` · `)||f(`common.none`)})]}),u.item.status===`deferred`?(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.resumeWhen`)}),(0,z.jsx)(`dd`,{children:u.item.resumeWhen||f(`drawer.notSet`)})]}):null,(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.nextTransition`)}),(0,z.jsx)(`dd`,{children:u.item.nextTransition??(u.item.done?f(`drawer.taskNextCompleted`):u.item.status===`deferred`?f(`drawer.taskNextDeferred`):f(`drawer.taskNextOpen`))})]})]})]}),!c&&!u.item.done?(0,z.jsxs)(`div`,{className:`personal-task-inspector-actions`,"aria-label":f(`drawer.taskActions`),children:[(0,z.jsxs)(`details`,{className:`personal-task-management`,children:[(0,z.jsxs)(`summary`,{children:[(0,z.jsx)(rm,{size:16}),f(`drawer.taskManage`)]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:f(`drawer.reassign`)}),(0,z.jsxs)(`label`,{className:`personal-inline-agent-select`,children:[f(`drawer.reassign`),(0,z.jsx)(`select`,{"aria-label":f(`drawer.reassign`),onChange:e=>M(e.target.value),value:re,children:e.filter(e=>e.available).map(e=>(0,z.jsx)(`option`,{value:e.agentId,children:e.label},e.agentId))}),(0,z.jsx)(`button`,{className:`personal-secondary-action`,onClick:()=>void t.onPreviewAction?.({actionKind:`todo.update`,context:{goal_id:u.item.goalId,kind:`todo`,todo_id:u.item.todoId},idempotencyKey:`workspace-todo-${u.item.todoId}-reassign-${re}-${Date.now().toString(36)}`,normalizedParameters:{agent_id:re,goal_id:u.item.goalId,operation:`reassign`,todo_id:u.item.todoId},summary:f(`drawer.reassignSummary`,{task:u.item.text})}),type:`button`,children:f(`timeline.review`)})]}),(0,z.jsx)(`strong`,{children:f(`drawer.taskDeferUntil`)}),(0,z.jsxs)(`label`,{className:`personal-inline-agent-select personal-inline-resume-when`,children:[f(`drawer.taskDeferUntil`),(0,z.jsx)(`input`,{"aria-label":f(`drawer.taskDeferCondition`),"aria-invalid":!!N.trim()&&!he,onChange:e=>ie(e.target.value),placeholder:f(`drawer.taskDeferPlaceholder`),value:N}),(0,z.jsx)(`button`,{className:`personal-secondary-action`,disabled:!he,onClick:()=>void _e(u.item,`defer`,f(`drawer.taskDefer`),he??void 0),type:`button`,children:f(`drawer.taskDeferReview`)}),(0,z.jsx)(`small`,{children:N.trim()&&!he?f(`drawer.taskDeferInvalid`):f(`drawer.taskDeferSupported`)})]}),(0,z.jsx)(`div`,{className:`personal-task-management-secondary`,children:Ey.map(e=>(0,z.jsx)(`button`,{onClick:()=>void _e(u.item,e.operation,f(e.key)),type:`button`,children:f(e.key)},e.operation))})]})]}),(0,z.jsxs)(`button`,{className:`personal-primary-action`,onClick:()=>void _e(u.item,`complete`,f(`drawer.taskComplete`)),type:`button`,children:[(0,z.jsx)(Kp,{size:17}),f(`drawer.taskComplete`)]})]}):null,u.item.done?(0,z.jsxs)(`div`,{className:`personal-task-completed-note`,children:[(0,z.jsx)(Kp,{size:16}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:f(`drawer.taskCompletedTitle`)}),(0,z.jsx)(`small`,{children:f(`drawer.taskCompletedNote`)})]})]}):null]}):null,u.kind===`goal`?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`section`,{className:`personal-detail-card`,children:[(0,z.jsx)(`small`,{children:Yi(u.item.state,d)}),(0,z.jsx)(`h3`,{children:u.item.title}),(0,z.jsx)(`p`,{children:u.item.agentSentence}),(0,z.jsxs)(`dl`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.tokens`)}),(0,z.jsxs)(`dd`,{children:[ny(u.item.usage?.tokens24h,f(`drawer.usageNotMeasured`),$v),` / `,ny(u.item.usage?.tokens7d,f(`drawer.usageNotMeasured`),$v)]})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.cost`)}),(0,z.jsxs)(`dd`,{children:[ny(u.item.usage?.costUsd24h,f(`drawer.usageNotMeasured`),ey),` / `,ny(u.item.usage?.costUsd7d,f(`drawer.usageNotMeasured`),ey)]})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.duration`)}),(0,z.jsxs)(`dd`,{children:[ny(u.item.usage?.durationMs24h,f(`drawer.usageNotMeasured`),ty),` / `,ny(u.item.usage?.durationMs7d,f(`drawer.usageNotMeasured`),ty)]})]})]})]}),(()=>{let e=n.find(e=>e.goalId===u.item.goalId),r=a.find(e=>e.goal_id===u.item.goalId);return(0,z.jsxs)(z.Fragment,{children:[u.item.repository?(0,z.jsxs)(`section`,{className:`personal-detail-card personal-goal-repository`,children:[(0,z.jsxs)(`div`,{className:`personal-detail-card-title`,children:[(0,z.jsx)(`small`,{children:f(`drawer.repository`)}),(0,z.jsx)(`em`,{children:f(`common.readOnly`)})]}),(0,z.jsxs)(`h3`,{children:[(0,z.jsx)(lm,{size:16}),u.item.repository.label]}),(0,z.jsxs)(`dl`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.branch`)}),(0,z.jsx)(`dd`,{children:u.item.repository.branch||`detached`})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Role`}),(0,z.jsx)(`dd`,{children:f(`drawer.repositoryRole`)})]})]}),(0,z.jsxs)(`button`,{className:`personal-secondary-action`,onClick:()=>{let e=navigator.clipboard?.writeText(u.item.repository?.identity??``);if(!e){v(`error`);return}e.then(()=>v(`copied`)).catch(()=>v(`error`))},type:`button`,children:[(0,z.jsx)(em,{size:15}),f(_===`copied`?`drawer.copyRepositoryDone`:`drawer.copyRepository`)]}),_===`error`?(0,z.jsx)(`p`,{className:`personal-copy-feedback is-error`,role:`status`,children:f(`drawer.copyRepositoryError`)}):_===`copied`?(0,z.jsx)(`p`,{className:`personal-copy-feedback`,role:`status`,children:f(`drawer.copyRepositorySuccess`)}):null]}):null,c?(0,z.jsxs)(`section`,{className:`personal-detail-card personal-goal-notification`,children:[(0,z.jsx)(`small`,{children:f(`drawer.larkConnection`)}),(0,z.jsx)(`h3`,{children:f(`drawer.remoteDetailsUnavailable`)}),(0,z.jsx)(`p`,{children:f(`drawer.remoteDetailsDescription`)})]}):(0,z.jsxs)(`section`,{className:`personal-detail-card personal-goal-notification`,children:[(0,z.jsx)(`small`,{children:f(`drawer.larkConnection`)}),r?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`h3`,{children:[r.app_label,(0,z.jsx)(`span`,{className:`personal-connection-status`,children:f(`drawer.connected`)})]}),(0,z.jsxs)(`dl`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.group`)}),(0,z.jsx)(`dd`,{children:r.chat_name})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.topic`)}),(0,z.jsxs)(`dd`,{children:[`# `,r.topic_name]})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.trigger`)}),(0,z.jsx)(`dd`,{children:r.incoming_mode===`mentions`?f(`lark.someoneMentions`):f(`lark.allMessages`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.replyMode`)}),(0,z.jsx)(`dd`,{children:f(`lark.topicReply`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.autoNotify`)}),(0,z.jsx)(`dd`,{children:e?.humanGateAutoNotifyEnabled?f(`common.on`):f(`common.off`)})]}),e?.lastNotifiedAt?(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.lastNotification`)}),(0,z.jsx)(`dd`,{children:e.lastNotifiedAt})]}):null]})]}):(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`h3`,{children:f(`drawer.larkNotConfigured`)}),(0,z.jsx)(`p`,{children:f(`drawer.larkNotConfiguredDescription`)})]}),(0,z.jsxs)(`button`,{className:`personal-secondary-action`,onClick:()=>t.onOpenNotificationSettings?.(u.item.goalId),type:`button`,children:[(0,z.jsx)(Hp,{size:16}),f(r?`drawer.larkConfigure`:`drawer.larkConnect`)]})]})]})})(),(0,z.jsxs)(`section`,{className:`personal-detail-card personal-goal-session`,children:[(0,z.jsx)(`small`,{children:f(`drawer.runDetails`)}),fe?.sessionId?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`h3`,{children:Xi(fe.sessionStatus??fe.status,f)}),(0,z.jsx)(`p`,{children:fe.title}),t.onOpenRunSession?(0,z.jsxs)(`button`,{className:`personal-primary-action`,onClick:()=>void t.onOpenRunSession?.(fe),type:`button`,children:[(0,z.jsx)(Tm,{size:16}),f(`drawer.runLatest`)]}):null]}):(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`h3`,{children:f(`drawer.noRun`)}),(0,z.jsx)(`p`,{children:f(`drawer.noRunDescription`)})]})]}),c?null:(0,z.jsxs)(`div`,{className:`personal-drawer-action-grid`,children:[(0,z.jsxs)(`button`,{className:`personal-secondary-action`,onClick:()=>t.onRequestScheduleConfig?.(`heartbeat`,u.item.goalId),type:`button`,children:[(0,z.jsx)(Dm,{size:16}),f(`drawer.setupHeartbeat`)]}),(0,z.jsxs)(`button`,{className:`personal-secondary-action`,onClick:()=>t.onRequestScheduleConfig?.(`monitor`,u.item.goalId),type:`button`,children:[(0,z.jsx)(Gp,{size:16}),f(`drawer.scheduleAdd`)]})]}),u.item.subagentExecution?(0,z.jsxs)(`section`,{className:`personal-detail-card personal-goal-subagents`,children:[(0,z.jsxs)(`div`,{className:`personal-subagent-heading`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`small`,{children:f(`drawer.subagentLabel`)}),(0,z.jsxs)(`h3`,{children:[(0,z.jsx)(Up,{size:16}),f(`drawer.subagentTitle`)]})]}),(0,z.jsxs)(`button`,{"aria-checked":ye.enabled,"aria-label":f(k&&D===`ready`?`drawer.subagentPending`:ye.enabled?`drawer.subagentDisable`:`drawer.subagentEnable`),className:`personal-subagent-switch`,"data-pending":k&&D===`ready`?`true`:void 0,disabled:c||be||!!k||!t.onPreviewGoalSubagentConfiguration,onClick:()=>void Te(!ye.enabled),role:`switch`,type:`button`,children:[(0,z.jsx)(`span`,{}),f(k&&D===`ready`?`drawer.subagentPending`:ye.enabled?`common.on`:`common.off`)]})]}),(0,z.jsx)(`p`,{children:f(`drawer.subagentDescription`)}),k&&D===`ready`?(0,z.jsxs)(`div`,{className:`personal-subagent-preview`,children:[(0,z.jsx)(`strong`,{children:f(k.enabled?`drawer.subagentConfirmEnable`:`drawer.subagentConfirmDisable`)}),(0,z.jsx)(`p`,{children:k.enabled?f(`drawer.subagentPreviewSummary`,{count:k.maxChildren,domains:k.allowedDomains.join(` · `)||f(`drawer.subagentDomainsUnrestricted`)}):f(`drawer.subagentDisableSummary`)}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`button`,{className:`personal-primary-action`,onClick:()=>void Ee(),type:`button`,children:f(`common.confirm`)}),(0,z.jsx)(`button`,{className:`personal-secondary-action`,onClick:Se,type:`button`,children:f(`common.cancel`)})]})]}):null,C?(0,z.jsxs)(`p`,{className:`personal-subagent-feedback is-${D}`,role:`status`,children:[D===`previewing`||D===`applying`?(0,z.jsx)(km,{className:`personal-spin`,size:13}):null,C]}):null,(0,z.jsxs)(`dl`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.subagentCurrentBoundary`)}),(0,z.jsx)(`dd`,{children:ye.allowedDomains.join(` · `)||f(`drawer.subagentDomainsUnrestricted`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.subagentChildLimit`)}),(0,z.jsx)(`dd`,{children:ye.maxChildren||0})]})]}),c?(0,z.jsx)(`p`,{className:`personal-subagent-read-only`,children:f(`drawer.subagentRemoteReadOnly`)}):(0,z.jsxs)(`div`,{className:`personal-subagent-fields`,children:[(0,z.jsxs)(`fieldset`,{className:`personal-subagent-domain-picker`,disabled:be,children:[(0,z.jsx)(`legend`,{children:f(`drawer.subagentDomains`)}),xe.length>0?(0,z.jsx)(`div`,{className:`personal-subagent-domain-options`,children:xe.map(e=>{let t=x.includes(e.value);return(0,z.jsxs)(`label`,{className:`personal-subagent-domain-option${t?` is-selected`:``}`,children:[(0,z.jsx)(`input`,{"aria-label":e.value,checked:t,onChange:t=>we(e.value,t.target.checked),type:`checkbox`}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:e.value}),(0,z.jsx)(`small`,{children:f(`drawer.subagentDomainTodoCount`,{count:e.matchingTodoCount})})]})]},e.value)})}):(0,z.jsx)(`p`,{className:`personal-subagent-domain-empty`,children:f(`drawer.subagentDomainsEmpty`)}),(0,z.jsx)(`small`,{children:f(`drawer.subagentDomainsHint`)})]}),(0,z.jsxs)(`label`,{className:`personal-subagent-limit-field`,children:[(0,z.jsx)(`span`,{children:f(`drawer.subagentMaxChildren`)}),(0,z.jsx)(`select`,{"aria-label":f(`drawer.subagentMaxChildren`),disabled:be,onChange:e=>{E(Number(e.target.value)),ee(null),O(`idle`),w(null)},value:T,children:Oy.map(e=>(0,z.jsx)(`option`,{value:e,children:e},e))})]}),ye.enabled?(0,z.jsx)(`button`,{className:`personal-secondary-action`,disabled:be,onClick:()=>void Te(!0),type:`button`,children:f(`drawer.subagentPreviewBoundary`)}):null]})]}):null]}):null,u.kind===`run`?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`div`,{"aria-label":f(`drawer.runView`),className:`personal-run-drawer-tabs`,role:`tablist`,children:[(0,z.jsx)(`button`,{"aria-selected":y===`record`,onClick:()=>b(`record`),role:`tab`,type:`button`,children:f(`drawer.executionRecordAndResult`)}),(0,z.jsx)(`button`,{"aria-selected":y===`details`,onClick:()=>b(`details`),role:`tab`,type:`button`,children:f(`drawer.detailsAndActions`)})]}),y===`record`?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`section`,{className:`personal-detail-card personal-session-summary`,children:[(0,z.jsxs)(`small`,{children:[u.item.agentLabel,` · `,Xi(u.item.sessionStatus??u.item.status,f)]}),(0,z.jsx)(`h3`,{children:u.item.title}),(0,z.jsx)(`p`,{children:u.item.latestActivity}),(0,z.jsxs)(`dl`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Goal`}),(0,z.jsx)(`dd`,{children:u.item.goalTitle})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.progress`)}),(0,z.jsxs)(`dd`,{children:[u.item.completedSteps,`/`,u.item.totalSteps]})]})]})]}),(0,z.jsxs)(`section`,{"aria-label":f(`drawer.executionRecord`),className:`personal-session-message-record`,children:[(0,z.jsx)(`h3`,{children:f(`drawer.executionRecord`)}),u.item.sessionMessages?.length?(0,z.jsx)(`ol`,{children:u.item.sessionMessages.map(e=>(0,z.jsxs)(`li`,{className:`is-${e.role}`,children:[(0,z.jsx)(`i`,{}),(0,z.jsxs)(`div`,{children:[(0,z.jsxs)(`header`,{children:[(0,z.jsx)(`strong`,{children:e.role===`user`?f(`drawer.runRoleUser`):e.role===`assistant`?f(`drawer.runRoleAssistant`):f(`drawer.runRoleSystem`)}),e.createdAt?(0,z.jsx)(`time`,{children:new Date(e.createdAt).toLocaleTimeString(d,{hour:`2-digit`,minute:`2-digit`,hour12:!1})}):null]}),(0,z.jsx)(`p`,{children:e.text})]})]},e.messageId))}):(0,z.jsx)(`p`,{className:`personal-session-empty`,children:pe?f(`drawer.runRecordProjected`,{completed:u.item.completedSteps,outputs:u.item.outputs?.length?f(`drawer.runRecordProjectedOutputs`,{count:u.item.outputs.length}):``,total:u.item.totalSteps}):f(`drawer.runRecordEmpty`)}),u.item.status===`running`?(0,z.jsxs)(`div`,{className:`personal-session-active-step`,children:[(0,z.jsx)(`i`,{}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:f(`drawer.analysis`)}),(0,z.jsx)(`small`,{children:f(`drawer.agentWorking`)})]})]}):null]}),u.item.outputs?.length?(0,z.jsxs)(`section`,{className:`personal-execution-history`,"aria-labelledby":`personal-run-outputs-title`,children:[(0,z.jsx)(`h3`,{id:`personal-run-outputs-title`,children:f(`drawer.outputs`)}),(0,z.jsx)(`ol`,{children:u.item.outputs.map(e=>(0,z.jsx)(`li`,{children:(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:e.title}),(0,z.jsx)(`small`,{children:e.createdAt??e.kind??f(`files.emptySummary`)})]})},e.outputId))})]}):null]}):(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`section`,{className:`personal-detail-card`,children:[(0,z.jsxs)(`small`,{children:[u.item.agentLabel,` · `,Xi(u.item.status,f)]}),(0,z.jsx)(`h3`,{children:u.item.title}),(0,z.jsx)(`p`,{children:u.item.latestActivity}),(0,z.jsxs)(`dl`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Goal`}),(0,z.jsx)(`dd`,{children:u.item.goalTitle})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.progress`)}),(0,z.jsxs)(`dd`,{children:[u.item.completedSteps,`/`,u.item.totalSteps]})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.sessionStatus`)}),(0,z.jsx)(`dd`,{children:Xi(u.item.sessionStatus??u.item.status,f)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.sessionRecoverable`)}),(0,z.jsx)(`dd`,{children:u.item.resumable===!1?f(`drawer.resumeNo`):f(`drawer.resumeYes`)})]})]})]}),u.item.sessionStatus===`resume_failed`&&!c?(0,z.jsxs)(`section`,{className:`personal-recovery-panel`,"aria-label":f(`drawer.recoveryFailed`),children:[(0,z.jsx)(`strong`,{children:f(`drawer.recoveryFailed`)}),(0,z.jsx)(`p`,{children:f(`drawer.recoveryDescription`)}),(0,z.jsxs)(`button`,{className:`personal-primary-action`,onClick:()=>void t.onRetryResumeRun?.(u.item),type:`button`,children:[(0,z.jsx)(km,{size:16}),f(`drawer.recoveryRetry`)]}),(0,z.jsxs)(`button`,{className:`personal-secondary-action`,onClick:()=>void t.onStartNewRunSession?.(u.item),type:`button`,children:[(0,z.jsx)(Tm,{size:16}),f(`drawer.recoveryNewSession`)]})]}):null,c?null:(0,z.jsxs)(`section`,{className:`personal-correction-panel`,children:[(0,z.jsx)(`header`,{children:(0,z.jsxs)(`span`,{children:[(0,z.jsx)(Up,{size:16}),f(`drawer.correctionLabel`,{agent:u.item.agentLabel})]})}),(0,z.jsx)(`p`,{children:f(`drawer.correctionDescription`)}),(0,z.jsxs)(`div`,{className:`personal-correction-composer`,children:[(0,z.jsx)(`textarea`,{"aria-label":f(`drawer.correctionTextarea`,{agent:u.item.agentLabel,goal:u.item.goalTitle,run:u.item.title}),onChange:e=>m(e.target.value),placeholder:f(`drawer.correctionPlaceholder`),rows:3,value:p}),(0,z.jsx)(`button`,{"aria-label":f(`drawer.correctionSend`),disabled:!p.trim(),onClick:()=>void ge(),type:`button`,children:(0,z.jsx)(Mm,{size:16})})]})]}),c?null:(0,z.jsxs)(`details`,{className:`personal-compact-menu personal-run-more`,children:[(0,z.jsxs)(`summary`,{children:[(0,z.jsx)(rm,{size:17}),f(`drawer.moreRunActions`)]}),(0,z.jsxs)(`div`,{children:[(0,z.jsxs)(`button`,{disabled:!u.item.canInterrupt,onClick:()=>void t.onInterruptRun?.(u.item),type:`button`,children:[(0,z.jsx)(wm,{size:16}),f(`drawer.runInterrupt`)]}),(0,z.jsxs)(`button`,{disabled:u.item.resumable===!1,onClick:()=>void t.onRetryResumeRun?.(u.item),type:`button`,children:[(0,z.jsx)(km,{size:16}),f(`drawer.recoveryRetry`)]}),(0,z.jsxs)(`button`,{onClick:()=>void t.onStartNewRunSession?.(u.item),type:`button`,children:[(0,z.jsx)(Tm,{size:16}),f(`drawer.runNewSession`)]}),(0,z.jsxs)(`button`,{onClick:()=>void t.onCloseRunSession?.(u.item),type:`button`,children:[(0,z.jsx)(zm,{size:16}),f(`drawer.runCloseSession`)]})]})]})]})]}):null,u.kind===`output`?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`section`,{className:`personal-detail-card`,children:[(0,z.jsx)(`small`,{children:u.item.kind??`output`}),(0,z.jsx)(`h3`,{children:u.item.title}),(0,z.jsx)(`p`,{children:u.item.summary??f(`drawer.outputRecorded`)}),(0,z.jsxs)(`dl`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Goal`}),(0,z.jsx)(`dd`,{children:u.item.goalTitle??u.item.goalId})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.outputTodo`)}),(0,z.jsx)(`dd`,{children:u.item.todoId??f(`drawer.notLinked`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.outputRun`)}),(0,z.jsx)(`dd`,{children:u.item.runId??f(`drawer.notLinked`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Agent`}),(0,z.jsx)(`dd`,{children:u.item.agentLabel??u.item.agentId??`LoopX`})]})]})]}),u.item.report?(0,z.jsxs)(`section`,{className:`personal-report-detail`,"data-testid":`personal-periodic-report-detail`,children:[(0,z.jsxs)(`header`,{children:[(0,z.jsxs)(`span`,{children:[(0,z.jsxs)(`strong`,{children:[`+`,u.item.report.addedCount]}),f(`files.reportAdded`)]}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:u.item.report.changedCount}),f(`files.reportChanged`)]})]}),(0,z.jsxs)(`p`,{children:[u.item.report.periodStartAt,` → `,u.item.report.periodEndAt]}),(0,z.jsx)(`ol`,{children:u.item.report.items.map(e=>(0,z.jsxs)(`li`,{"data-change-kind":e.changeKind,children:[(0,z.jsxs)(`small`,{children:[e.changeKind,` · `,e.status]}),(0,z.jsx)(`strong`,{children:e.title}),(0,z.jsx)(`p`,{children:e.summary})]},e.sourceRef))}),(0,z.jsxs)(`footer`,{children:[(0,z.jsxs)(`span`,{children:[f(`files.reportPublication`),`: `,u.item.report.publicationId]}),(0,z.jsxs)(`span`,{children:[f(`files.reportGeneration`),`: `,u.item.report.generationId]})]})]}):null,u.item.safePreview?(0,z.jsx)(`pre`,{"aria-label":f(`drawer.outputSafePreview`),className:`personal-safe-preview`,children:u.item.safePreview}):(0,z.jsx)(`p`,{className:`personal-preview-unavailable`,children:f(`drawer.previewUnavailable`)}),(0,z.jsxs)(`div`,{className:`personal-drawer-action-grid`,children:[(0,z.jsxs)(`button`,{className:`personal-primary-action`,disabled:!t.onOpenOutput,onClick:()=>{t.onOpenOutput?.(u.item),o()},type:`button`,children:[(0,z.jsx)(im,{size:16}),f(`files.openConversation`)]}),(0,z.jsxs)(`button`,{className:`personal-secondary-action`,disabled:!t.onExportOutput,onClick:()=>void t.onExportOutput?.(u.item),type:`button`,children:[(0,z.jsx)(nm,{size:16}),f(`files.exportSummary`)]})]})]}):null,u.kind===`proposal`?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`section`,{className:`personal-proposal-card`,children:[(0,z.jsxs)(`small`,{children:[u.item.actionKind,` · `,u.item.status]}),(0,z.jsx)(`h3`,{children:u.item.title}),(0,z.jsx)(`p`,{children:u.item.impact}),u.item.status===`ready`?(0,z.jsx)(`p`,{className:`personal-proposal-explainer`,children:f(`drawer.proposalExplainer`)}):null,(0,z.jsx)(`dl`,{children:u.item.fields.map(e=>(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:e.label}),(0,z.jsx)(`dd`,{children:e.value})]},e.key))})]}),u.item.status===`applied`?(0,z.jsxs)(`p`,{className:`personal-proposal-state is-applied`,children:[(0,z.jsx)(Kp,{size:16}),f(`drawer.proposalApplied`)]}):null,u.item.status===`applied`&&u.item.goalId?(0,z.jsxs)(`button`,{className:`personal-primary-action`,onClick:()=>{let e=u.item.goalId;o(),t.onOpenGoal?.(e)},type:`button`,children:[(0,z.jsx)(im,{size:16}),u.item.actionKind===`goal.create`?f(`drawer.proposalEnterGoal`):f(`drawer.proposalViewGoal`)]}):null,u.item.status===`stale`?(0,z.jsx)(`p`,{className:`personal-proposal-state is-stale`,children:f(`drawer.proposalStale`)}):null,u.item.status===`error`?(0,z.jsxs)(`div`,{className:`personal-proposal-state is-error`,children:[(0,z.jsx)(`span`,{children:f(`drawer.proposalApplyFailed`)}),u.item.errorMessage?(0,z.jsx)(`small`,{children:u.item.errorMessage}):null,(0,z.jsx)(`small`,{children:f(`drawer.proposalApplyFailedHint`)})]}):null,u.item.status===`rejected`?(0,z.jsx)(`p`,{className:`personal-proposal-state is-error`,children:f(`drawer.proposalRejected`)}):null,u.item.status===`deferred`?(0,z.jsx)(`p`,{className:`personal-proposal-state is-gated`,children:f(`drawer.proposalDeferred`)}):null,u.item.status===`gated`?(0,z.jsxs)(`div`,{className:`personal-proposal-state is-gated`,children:[(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:f(`drawer.gateRequiresHost`)}),f(`drawer.gateRequiresHostDescription`)]}),u.item.gate?.nextAction?(0,z.jsx)(`small`,{children:u.item.gate.nextAction}):null]}):null,u.item.status===`gated`&&u.item.actionKind===`gate.resolve`?(()=>{let e=e=>u.item.fields.find(t=>t.key===e)?.value,t=e(`goal_id`),n=e(`todo_id`);return!t||!n?null:(0,z.jsxs)(`section`,{className:`personal-detail-card personal-gate-cli-hint`,children:[(0,z.jsx)(`small`,{children:f(`drawer.gateApproveHint`)}),(0,z.jsxs)(`code`,{children:[`loopx todo complete --goal-id `,t,` --todo-id `,n,` --decision-outcome approve`]}),(0,z.jsx)(`small`,{children:f(`drawer.gateRejectHint`)})]})})():null,!c&&u.item.workspaceCandidates?.length?(0,z.jsx)(`div`,{className:`personal-workspace-candidates`,"aria-label":f(`drawer.workspaceCandidates`),children:u.item.workspaceCandidates.map(e=>(0,z.jsxs)(`button`,{onClick:()=>void t.onSelectWorkspaceCandidate?.(u.item,e.workspaceRef),type:`button`,children:[(0,z.jsx)(`strong`,{children:e.label}),(0,z.jsx)(`small`,{children:e.workspaceRef})]},e.workspaceRef))}):null,!c&&u.item.status===`error`?(0,z.jsxs)(`button`,{className:`personal-primary-action`,onClick:()=>void t.onTransitionProposal?.(u.item,`regenerate`),type:`button`,children:[(0,z.jsx)(km,{size:17}),f(`drawer.proposalRegenerate`)]}):!c&&u.item.status!==`gated`?(0,z.jsxs)(`button`,{className:`personal-primary-action`,disabled:![`ready`,`deferred`].includes(u.item.status),onClick:()=>void t.onApplyProposal?.(u.item),type:`button`,children:[(0,z.jsx)(Kp,{size:17}),u.item.status===`applying`?f(`drawer.applying`):u.item.primaryLabel??f(`drawer.apply`)]}):null,!c&&[`stale`,`gated`,`rejected`].includes(u.item.status)?(0,z.jsxs)(`button`,{className:`personal-secondary-action`,onClick:()=>void t.onTransitionProposal?.(u.item,`regenerate`),type:`button`,children:[(0,z.jsx)(km,{size:16}),f(`drawer.proposalRecheck`)]}):null,!c&&[`ready`,`gated`].includes(u.item.status)?(0,z.jsxs)(`div`,{className:`personal-drawer-action-grid`,children:[(0,z.jsx)(`button`,{className:`personal-secondary-action`,onClick:()=>void t.onTransitionProposal?.(u.item,`defer`),type:`button`,children:f(`drawer.proposalDefer`)}),(0,z.jsx)(`button`,{className:`personal-secondary-action`,onClick:()=>void t.onTransitionProposal?.(u.item,`reject`),type:`button`,children:f(`drawer.decisionReject`)})]}):null,[`applied`,`applying`].includes(u.item.status)?null:(0,z.jsx)(`button`,{className:`personal-secondary-action`,onClick:o,type:`button`,children:f(`drawer.proposalClose`)})]}):null,u.kind===`schedule`?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`section`,{className:`personal-detail-card`,children:[(0,z.jsxs)(`small`,{children:[u.item.scheduleKind===`heartbeat`?`Goal Heartbeat`:`continuous_monitor`,` · `,u.item.status??`active`]}),(0,z.jsx)(`h3`,{children:u.item.label}),(0,z.jsx)(`p`,{children:u.item.target??u.item.schedule??f(`drawer.scheduleDefaultTarget`)}),(0,z.jsxs)(`dl`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.scheduleTimezone`)}),(0,z.jsx)(`dd`,{children:u.item.timezone??f(`drawer.scheduleLocalTimezone`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.scheduleNext`)}),(0,z.jsx)(`dd`,{children:u.item.nextRunAt??f(`drawer.schedulePending`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.scheduleLast`)}),(0,z.jsx)(`dd`,{children:u.item.previousRunAt??f(`drawer.scheduleNeverRun`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.scheduleNotification`)}),(0,z.jsx)(`dd`,{children:u.item.notificationRule??f(`drawer.scheduleDefaultNotification`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.scheduleStopCondition`)}),(0,z.jsx)(`dd`,{children:u.item.stopCondition??f(`drawer.scheduleDefaultStop`)})]})]})]}),!c&&u.item.scheduleKind===`monitor`?(0,z.jsxs)(`button`,{className:`personal-primary-action`,onClick:()=>void t.onUpdateSchedule?.(u.item,`run_now`),type:`button`,children:[(0,z.jsx)(Tm,{size:16}),f(`drawer.scheduleRunNow`)]}):null,c?null:(0,z.jsxs)(`div`,{className:`personal-drawer-action-grid`,children:[(0,z.jsxs)(`button`,{className:`personal-secondary-action`,onClick:()=>void t.onUpdateSchedule?.(u.item,u.item.status===`paused`?`resume`:`pause`),type:`button`,children:[u.item.status===`paused`?(0,z.jsx)(Tm,{size:16}):(0,z.jsx)(wm,{size:16}),u.item.status===`paused`?f(`drawer.scheduleResume`):f(`drawer.schedulePause`)]}),(0,z.jsxs)(`button`,{className:`personal-secondary-action`,onClick:()=>void t.onUpdateSchedule?.(u.item,`edit`),type:`button`,children:[(0,z.jsx)(Gp,{size:16}),f(`drawer.scheduleEdit`)]})]}),c?null:(0,z.jsxs)(`button`,{className:`personal-danger-action`,onClick:()=>void t.onUpdateSchedule?.(u.item,`stop`),type:`button`,children:[(0,z.jsx)(zm,{size:16}),f(`drawer.scheduleStop`,{kind:u.item.scheduleKind===`heartbeat`?` Heartbeat`:f(`drawer.titleSchedule`)})]}),(0,z.jsxs)(`section`,{className:`personal-execution-history`,"aria-labelledby":`personal-execution-history-title`,children:[(0,z.jsx)(`h3`,{id:`personal-execution-history-title`,children:f(`drawer.executionHistory`)}),u.item.executionHistory?.length?(0,z.jsx)(`ol`,{children:u.item.executionHistory.map((e,t)=>(0,z.jsxs)(`li`,{children:[(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:e.label}),(0,z.jsx)(`small`,{children:e.timestamp})]}),(0,z.jsx)(`em`,{className:`is-${e.status}`,children:e.status})]},`${e.timestamp}:${e.runId??t}`))}):(0,z.jsx)(`p`,{children:f(`drawer.noExecutionHistory`)})]})]}):null,u.kind===`run`||u.kind===`proposal`||u.kind===`schedule`?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`button`,{"aria-expanded":h,className:`personal-diagnostics-trigger`,onClick:()=>g(e=>!e),type:`button`,children:[(0,z.jsx)(`span`,{children:f(`drawer.advancedDiagnostics`)}),(0,z.jsx)(qp,{className:h?`is-open`:``,size:16})]}),h?(0,z.jsxs)(`div`,{className:`personal-diagnostics`,children:[(0,z.jsxs)(`code`,{children:[`goal_id: `,ue]}),(0,z.jsxs)(`code`,{children:[`kind: `,u.kind]}),u.kind===`run`?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`code`,{children:[`session_id: `,u.item.sessionId??f(`drawer.notLinked`)]}),(0,z.jsxs)(`code`,{children:[`turn_id: `,u.item.turnId??f(`common.none`)]}),(0,z.jsxs)(`code`,{children:[`adapter: `,u.item.agentId]}),(0,z.jsxs)(`code`,{children:[`status: `,u.item.sessionStatus??u.item.status]})]}):u.kind===`proposal`?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`code`,{children:[`action: `,u.item.actionKind]}),(0,z.jsxs)(`code`,{children:[`status: `,u.item.status]})]}):(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`code`,{children:[`schedule_id: `,u.item.scheduleId]}),(0,z.jsxs)(`code`,{children:[`status: `,u.item.status??`active`]})]})]}):null]}):null]})]})}var Ny=[`checking`,`connecting`,`downloading`,`installing_app`,`installing_runtime`],Py={desktop_status_unavailable:[`无法读取 App 更新状态。请重启 App 后再试;若仍失败,请重新安装最新 App。`,`Cannot read the App update status. Restart the App; if this persists, reinstall the latest App.`],update_feed_unavailable:[`此通道的更新源尚未就绪或暂时不可用。可稍后重新检查,当前版本仍可继续使用。`,`This channel's update feed is not ready or temporarily unavailable. Check again later; you can keep using this version.`],update_feed_invalid:[`更新源格式异常。请稍后重新检查。`,`The update feed is invalid. Check again later.`],update_platform_unavailable:[`此通道尚无适用于本机的更新包。`,`This channel has no update package for this platform.`],update_check_timeout:[`检查更新超时。请稍后重试。`,`The update check timed out. Try again later.`],update_network_failed:[`无法连接更新服务器。请检查网络后重试。`,`Cannot reach the update server. Check your connection and retry.`],update_download_or_signature_failed:[`更新包下载或签名校验失败,尚未安装。请重新检查更新。`,`Download or signature verification failed; the update was not installed. Check for updates again.`]};function Fy(e,t=`update_failed`){return{phase:`error`,details:{code:typeof e==`string`&&Object.hasOwn(Py,e)?e:t}}}function Iy(){let{locale:e}=Ji(),t=e===`zh-CN`,[n,r]=(0,R.useState)(!1),i=(0,R.useRef)(null),[a,o]=(0,R.useState)(`stable`),[s,c]=(0,R.useState)({phase:`idle`}),[l,u]=(0,R.useState)(``),[d,f]=(0,R.useState)(!1),p=(0,R.useRef)(!1),m=window.__TAURI__?.core.invoke,h=Ny.includes(s.phase);(0,R.useEffect)(()=>{let e=i.current;if(!e)return;let t=()=>r(e.matches(`:popover-open`));return e.addEventListener(`toggle`,t),()=>e.removeEventListener(`toggle`,t)},[]),(0,R.useEffect)(()=>{if(!m)return;let e=!0;return m(`desktop_update_status`).then(t=>{if(!e)return;u(t.app_version),f(t.rollback_available===!0),t.state?.phase&&c(t.state);let n=t.state?.details?.channel??(t.app_version.includes(`-main.`)?`main`:`stable`);o(n),t.state?.phase||m(`desktop_update`,{action:`check`,channel:n}).then(t=>{e&&c(t)}).catch(t=>{e&&c(Fy(t))})}).catch(()=>{e&&c(Fy(null,`desktop_status_unavailable`))}),()=>{e=!1}},[m]),(0,R.useEffect)(()=>{if(!m||!h)return;let e=window.setInterval(()=>{m(`desktop_update_status`).then(e=>{e.state?.phase&&c(e.state)}).catch(()=>{})},1e3);return()=>window.clearInterval(e)},[m,h]);async function g(e){if(!(!m||p.current)){p.current=!0,c({phase:e===`check`?`checking`:e===`repair`?`installing_runtime`:`downloading`});try{if(!l){let e=await m(`desktop_update_status`);u(e.app_version),f(e.rollback_available===!0)}c(await m(`desktop_update`,{action:e,channel:a}))}catch(e){c(Fy(e,l?`update_failed`:`desktop_status_unavailable`))}finally{p.current=!1}}}let _={service_error:t?`运行时已安装,但服务尚未连接。可重试更新、修复或恢复上版。`:`Runtime installed, but services are unavailable. Retry updates, repair, or restore the previous version.`,idle:t?`App 会检查可用更新,不会自动安装。`:`Updates are checked automatically, never installed without confirmation.`,runtime_required:t?`请完成匹配组件安装,或检查 App 更新。`:`Install matching components or check for an App update.`,connecting:t?`正在连接更新后的服务…`:`Connecting to updated services…`,checking:t?`正在检查更新…`:`Checking for updates…`,available:t?`新版本已就绪,一次更新 App 与匹配的运行时。`:`Update the App and its matching runtime together.`,up_to_date:t?`当前通道暂无更新。`:`No newer update on this channel.`,downloading:t?`正在下载并校验签名…`:`Downloading and verifying signature…`,installing_app:t?`正在安装 App,请保持窗口打开。`:`Installing the App. Keep this window open.`,installing_runtime:t?`正在安装匹配的运行时,请稍候…`:`Installing the matching runtime…`,restart_required:t?`重启后将自动完成运行时安装与服务连接。`:`Restart to finish runtime installation and reconnect services.`,ready:t?`更新完成,服务已就绪。`:`Update completed; services are ready.`,error:Py[s.details?.code??``]?.[+!t]??(t?`更新未完成。请重试;启动失败可尝试修复当前版本。`:`Update incomplete. Retry; repair this version if startup fails.`)},v=h?t?`正在更新…`:`Updating…`:s.phase===`available`?t?`有可用更新`:`Update available`:s.phase===`restart_required`?t?`重启完成更新`:`Restart to finish`:s.phase===`error`?t?`更新需重试`:`Retry update`:t?`更新 LoopX`:`Update LoopX`;return(0,z.jsxs)(`div`,{className:`personal-desktop-update`,children:[(0,z.jsxs)(`button`,{className:`personal-update-trigger`,type:`button`,"aria-expanded":n,"aria-controls":`desktop-update-panel`,onClick:e=>{i.current?.style.setProperty(`bottom`,`${window.innerHeight-e.currentTarget.getBoundingClientRect().top+8}px`),i.current?.togglePopover()},children:[(0,z.jsx)(nm,{size:16,"aria-hidden":`true`}),(0,z.jsx)(`span`,{children:v}),(0,z.jsx)(Yp,{size:14,"aria-hidden":`true`})]}),(0,z.jsxs)(`section`,{ref:i,popover:`auto`,id:`desktop-update-panel`,className:`personal-update-panel`,"aria-label":t?`LoopX 更新`:`LoopX updates`,children:[(0,z.jsxs)(`header`,{children:[(0,z.jsx)(`strong`,{children:t?`LoopX 更新`:`LoopX updates`}),(0,z.jsx)(`button`,{type:`button`,"aria-label":t?`关闭更新面板`:`Close updates`,onClick:()=>i.current?.hidePopover(),children:(0,z.jsx)(Gm,{size:16,"aria-hidden":`true`})})]}),(0,z.jsxs)(`small`,{children:[l,` · `,a===`main`?t?`main 预览版`:`main preview`:t?`稳定版`:`Stable`]}),s.details?.version?(0,z.jsxs)(`p`,{children:[t?`目标版本:`:`Target: `,s.details.version]}):null,(0,z.jsxs)(`p`,{role:`status`,"aria-live":`polite`,children:[h?(0,z.jsx)(Om,{className:`is-spinning`,size:14,"aria-hidden":`true`}):null,_[s.phase]]}),s.phase===`downloading`&&s.details?.total?(0,z.jsx)(`progress`,{"aria-label":t?`下载进度`:`Download progress`,max:s.details.total,value:s.details.received??0}):null,m?(0,z.jsx)(`div`,{className:`personal-update-actions`,children:s.phase===`restart_required`?(0,z.jsx)(`button`,{type:`button`,onClick:()=>void g(`restart`),children:t?`重启完成更新`:`Restart to finish`}):(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`button`,{type:`button`,disabled:h,onClick:()=>void g(`check`),children:t?`检查更新`:`Check for updates`}),s.phase===`available`?(0,z.jsx)(`button`,{type:`button`,onClick:()=>void g(`apply`),children:t?`更新并准备重启`:`Install update`}):null]})}):(0,z.jsx)(`p`,{children:t?`请在 LoopX App 中更新;浏览器自身无需安装包。`:`Update from the LoopX App; the browser needs no installer.`}),(0,z.jsxs)(`details`,{children:[(0,z.jsx)(`summary`,{children:t?`高级选项`:`Advanced options`}),(0,z.jsxs)(`label`,{children:[t?`更新通道`:`Update channel`,(0,z.jsxs)(`select`,{disabled:h||s.phase===`restart_required`,value:a,onChange:e=>{o(e.target.value),c({phase:`idle`})},children:[(0,z.jsx)(`option`,{value:`stable`,children:t?`稳定版(推荐)`:`Stable (recommended)`}),(0,z.jsx)(`option`,{value:`main`,children:t?`main 预览版`:`main preview`})]})]}),(0,z.jsx)(`p`,{children:t?`App 与匹配的 CLI 一起更新,服务可能短暂断开。不删除 Goal 数据。`:`Updates the App and matching CLI. Services may briefly disconnect. Goal data is not deleted.`}),m?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`p`,{children:t?`启动失败时,可重装当前 App 随附的运行时。`:`If startup fails, reinstall this App's bundled runtime.`}),(0,z.jsx)(`button`,{disabled:h||s.phase===`restart_required`,type:`button`,onClick:()=>void g(`repair`),children:t?`修复当前版本`:`Repair this version`})]}):null,m&&d?(0,z.jsxs)(`details`,{children:[(0,z.jsx)(`summary`,{children:t?`恢复上个版本`:`Restore previous version`}),(0,z.jsx)(`p`,{children:t?`将恢复已保留的 App 和它的运行时,需要重启。`:`Restore the retained App and its runtime, then restart.`}),(0,z.jsx)(`button`,{disabled:h,type:`button`,onClick:()=>void g(`rollback`),children:t?`确认恢复上版`:`Restore previous version`})]}):null]})]})]})}var Ly=e=>`loopx-sidebar-goal-order-v1:${encodeURIComponent(e)}`;function Ry(e){try{let t=JSON.parse(e??`null`);return Array.isArray(t)&&t.every(e=>typeof e==`string`)?[...new Set(t)]:[]}catch{return[]}}function zy(e,t){let n=new Map(t.map((e,t)=>[e,t]));return[...e].sort((e,t)=>(n.get(e.goalId)??1/0)-(n.get(t.goalId)??1/0))}function By(e,t,n,r,i){if(n===r||!t.includes(n)||!t.includes(r))return e;let a=[...new Set([...e,...t])].filter(e=>e!==n);return a.splice(a.indexOf(r)+Number(i),0,n),a}function Vy(e,t){let n=Ly(t),[r,i]=(0,R.useState)(()=>{try{return Ry(localStorage.getItem(n))}catch{return[]}}),[a,o]=(0,R.useState)(!1),[s,c]=(0,R.useState)(null),[l,u]=(0,R.useState)(null),d=(0,R.useRef)(null),f=(0,R.useRef)(!1),p=zy(e,r),m=p.map(e=>e.goalId);function h(t,a,s){let l=By(r,m,t,a,s);if(l===r)return;i(l);let u=zy(e,l),d=u.findIndex(e=>e.goalId===t),f=u[d];f&&c({title:f.title,position:d+1});try{localStorage.setItem(n,JSON.stringify(l)),o(!1)}catch{o(!0)}}function g(){d.current=null,u(null)}return{sorted:p,target:l,saveFailed:a,lastMoved:s,move:h,moveBy(e,t){let n=p[m.indexOf(e)+t];n&&h(e,n.goalId,t===1)},pointerProps:e=>({onPointerDown(t){f.current=!1,t.pointerType===`mouse`&&t.button===0&&(d.current={id:e,x:t.clientX,y:t.clientY,dragging:!1},t.currentTarget.setPointerCapture(t.pointerId))},onPointerMove(e){let t=d.current;if(!t||!t.dragging&&Math.hypot(e.clientX-t.x,e.clientY-t.y)<6)return;t.dragging=!0,f.current=!0;let n=document.elementFromPoint(e.clientX,e.clientY)?.closest(`[data-reorder-goal]`),r=e.currentTarget.closest(`.personal-goal-list`),i=n?.dataset.reorderGoal;if(!n||!i||!r?.contains(n)||i===t.id){u(null);return}let a=n.getBoundingClientRect();u({id:i,after:e.clientY>a.top+a.height/2})},onPointerUp(){d.current?.dragging&&l&&h(d.current.id,l.id,l.after),g()},onPointerCancel:g,onLostPointerCapture:g,onKeyDown(e){e.key===`Escape`&&g()},onClickCapture(e){f.current&&=(e.preventDefault(),e.stopPropagation(),!1)}})}}var Hy=`/ssh-hosts`,Uy=/^[A-Za-z0-9][A-Za-z0-9._-]{0,254}$/;function Wy(e){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`SSH Host 列表响应无效。`);let t=e;if(t.ok!==!0||t.schema_version!==`ssh_host_catalog_v0`||!Array.isArray(t.hosts))throw Error(`SSH Host 列表协议不兼容,请更新本机 LoopX 服务。`);let n=new Set;return{hosts:t.hosts.flatMap(e=>{if(!e||typeof e!=`object`||Array.isArray(e))return[];let t=String(e.alias??``).trim();return!Uy.test(t)||n.has(t)?[]:(n.add(t),[{alias:t}])}),schemaVersion:`ssh_host_catalog_v0`}}async function Gy(e=fetch,t=Hy){let n=await e(t,{cache:`no-store`});if(!n.ok)throw Error(`无法读取本机 SSH Host(HTTP ${n.status})。`);return Wy(await n.json())}function Ky(e,t){let n=e.trim();if(!Uy.test(n))return{error:`请选择有效的 SSH Host。`};let r=Number(t);return!Number.isInteger(r)||r<1024||r>65535?{error:`本地端口必须是 1024–65535 之间的整数。`}:{command:`ssh -N -L ${r}:127.0.0.1:8766 ${n}`,label:n,statusUrl:`http://127.0.0.1:${r}/status.json`}}var qy=`/api/ssh-source/ensure`;async function Jy(e,t){let n=await fetch(qy,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({host_alias:e,local_port:Number(t)})}),r=await n.json().catch(()=>null);if(!n.ok)throw Error(r?.error??`无法建立 SSH 隧道来源。`);if(!r?.ok)throw Error(`无法建立 SSH 隧道来源。`);return r}function Yy({activeSource:e,connectionState:t,errorMessage:n,onAdd:r,onRemove:i,onSelect:a,sources:o}){let{t:s}=Ji(),[c,l]=(0,R.useState)(!1),[u,d]=(0,R.useState)(null),[f,p]=(0,R.useState)(`configured`),[m,h]=(0,R.useState)([]),[g,_]=(0,R.useState)(null),[v,y]=(0,R.useState)(!1),[b,x]=(0,R.useState)(!1),[S,C]=(0,R.useState)(``),[w,T]=(0,R.useState)(``),[E,D]=(0,R.useState)(`8876`),[O,k]=(0,R.useState)(``),ee=`configured:`,A=[...o.map(e=>({label:e.label,value:e.id})),...m.filter(e=>!o.some(t=>t.label===e.alias)).map(e=>({group:s(`source.configuredGroup`,{count:m.length}),label:e.alias,value:`${ee}${e.alias}`}))],j=(0,R.useMemo)(()=>m.some(e=>e.alias===S)?Ky(S,E):{error:s(`source.selectHost`)},[m,S,E,s]);(0,R.useEffect)(()=>{te()},[]);async function te(){y(!0),_(null);try{let e=await Gy();h(e.hosts),C(t=>t||e.hosts[0]?.alias||``),e.hosts.length||_(s(`source.hostEmpty`))}catch(e){_(e instanceof Error?e.message:s(`source.hostLoadError`))}finally{y(!1)}}function ne(){l(!0),p(`configured`),d(null),te()}function re(){l(!1),p(`configured`),_(null),x(!1),C(``),d(null),T(``),D(`8876`),k(``)}function M(){let e=r({label:w,statusUrl:O});if(e.error){d(e.error);return}re()}function N(){if(`error`in j){d(j.error??s(`source.invalid`));return}let e=r({ensureTunnel:!0,label:j.label,statusUrl:j.statusUrl});if(e.error){d(e.error);return}re()}function ie(e){let t=new Set;for(let e of o)try{t.add(new URL(e.statusUrl).port)}catch{}let n=`8877`;for(let e=8877;e<9077;e+=1)if(!t.has(String(e))){n=String(e);break}let i=Ky(e,n);if(`error`in i){d(i.error??s(`source.invalid`));return}let a=r({ensureTunnel:!0,label:i.label,statusUrl:i.statusUrl});a.error?d(a.error):d(null),D(n)}async function ae(){if(`error`in j){d(j.error??s(`source.invalid`));return}try{await navigator.clipboard.writeText(j.command),x(!0),d(null)}catch{d(s(`source.copyError`))}}return(0,z.jsxs)(`section`,{"aria-label":s(`source.controlPlane`),className:`personal-status-source`,children:[(0,z.jsxs)(`header`,{children:[(0,z.jsx)(`span`,{children:`Control plane`}),(0,z.jsx)(`button`,{"aria-label":s(`source.addSsh`),onClick:ne,title:s(`source.add`),type:`button`,children:(0,z.jsx)(Em,{size:14})})]}),(0,z.jsx)(ay,{ariaLabel:s(`source.select`),className:`personal-status-source-select`,icon:(0,z.jsx)(Pm,{size:15}),onChange:e=>{if(e.startsWith(ee)){ie(e.slice(11));return}a(e)},options:A,value:e.id}),(0,z.jsxs)(`div`,{className:`personal-status-source-meta`,children:[(0,z.jsxs)(`span`,{className:`is-${t}`,children:[(0,z.jsx)(`i`,{}),s(t===`loading`?`source.connecting`:t===`error`?`source.notAvailable`:`source.connected`)]}),(0,z.jsx)(`small`,{children:e.readOnly?s(`source.readOnly`):s(`source.localInteractive`)}),e.kind===`ssh_tunnel`?(0,z.jsx)(`button`,{"aria-label":s(`source.remove`,{source:e.label}),onClick:()=>i(e.id),title:s(`source.removeCurrent`),type:`button`,children:(0,z.jsx)(Hm,{size:12})}):null]}),n?(0,z.jsx)(`p`,{className:`personal-status-source-error`,role:`alert`,children:n}):null,c?(0,z.jsxs)(`div`,{className:`personal-status-source-form`,children:[(0,z.jsxs)(`header`,{children:[(0,z.jsx)(`strong`,{children:s(`source.addSsh`)}),(0,z.jsx)(`button`,{"aria-label":s(`source.closeForm`),onClick:re,type:`button`,children:(0,z.jsx)(Gm,{size:13})})]}),(0,z.jsxs)(`div`,{"aria-label":s(`source.addMethod`),className:`personal-status-source-modes`,role:`tablist`,children:[(0,z.jsx)(`button`,{"aria-selected":f===`configured`,onClick:()=>{p(`configured`),d(null)},role:`tab`,type:`button`,children:s(`source.configured`)}),(0,z.jsx)(`button`,{"aria-selected":f===`manual`,onClick:()=>{p(`manual`),d(null)},role:`tab`,type:`button`,children:s(`source.manual`)})]}),f===`configured`?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:s(`source.configuredCount`,{count:m.length})}),(0,z.jsxs)(`span`,{className:`personal-status-source-field-row`,children:[(0,z.jsx)(`input`,{"aria-label":s(`source.host`),disabled:v||!m.length,list:`loopx-configured-ssh-hosts`,onChange:e=>{C(e.target.value),x(!1)},placeholder:s(v?`source.loadingHosts`:`source.hostPlaceholder`),value:S}),(0,z.jsx)(`datalist`,{id:`loopx-configured-ssh-hosts`,children:m.map(e=>(0,z.jsx)(`option`,{value:e.alias},e.alias))}),(0,z.jsx)(`button`,{"aria-label":s(`source.refreshHosts`),disabled:v,onClick:()=>void te(),title:s(`source.refreshHosts`),type:`button`,children:(0,z.jsx)(Am,{size:13})})]})]}),(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:s(`source.localPort`)}),(0,z.jsx)(`input`,{"aria-label":s(`source.localPort`),inputMode:`numeric`,onChange:e=>{D(e.target.value),x(!1)},value:E})]}),(0,z.jsxs)(`div`,{className:`personal-status-source-command`,children:[(0,z.jsx)(`code`,{children:`error`in j?s(`source.tunnelCommandPending`):j.command}),(0,z.jsxs)(`button`,{"aria-label":s(`source.copyCommand`),disabled:`error`in j,onClick:()=>void ae(),type:`button`,children:[(0,z.jsx)(em,{size:12}),s(b?`source.copied`:`source.copy`)]})]}),g?(0,z.jsx)(`p`,{className:`is-error`,children:g}):null,(0,z.jsx)(`p`,{children:s(`source.description`)}),(0,z.jsx)(`button`,{className:`personal-status-source-add`,disabled:`error`in j,onClick:N,type:`button`,children:s(`source.addConfigured`)})]}):(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:s(`source.name`)}),(0,z.jsx)(`input`,{autoFocus:!0,maxLength:48,onChange:e=>T(e.target.value),placeholder:s(`source.namePlaceholder`),value:w})]}),(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:s(`source.statusUrl`)}),(0,z.jsx)(`input`,{onChange:e=>k(e.target.value),placeholder:`http://127.0.0.1:8876/status.json`,value:O})]}),(0,z.jsx)(`p`,{children:(0,z.jsx)(`code`,{children:`ssh -N -L 8876:127.0.0.1:8766 `})}),(0,z.jsx)(`p`,{children:s(`source.manualDescription`)}),(0,z.jsx)(`button`,{className:`personal-status-source-add`,onClick:M,type:`button`,children:s(`source.addConfigured`)})]}),u?(0,z.jsx)(`p`,{className:`is-error`,role:`alert`,children:u}):null]}):null]})}var Xy={需修复:`is-danger`,等你:`is-warning`,等待条件:`is-info`,推进中:`is-success`,安静运行:`is-quiet`,已完成:`is-quiet`,已停止:`is-stopped`};function Zy({attentionCount:e,goals:t,goalArchiveLoadState:n={error:null,phase:`ready`},lifecycleBusyGoalIds:r,onRequestGoalCreate:i,onOpenSettings:a,onRetryGoalArchive:o,onRequestGoalLifecycle:s,onSelectGoal:c,selectedGoalId:l,statusSourceControl:u}){let{locale:d,t:f}=Ji(),[p,m]=(0,R.useState)(!1),h=Vy(t.filter(e=>e.activationState!==`stopped`),u?.activeSource.statusUrl??`/status.json`),g=h.sorted,_=t.filter(e=>e.activationState===`stopped`),v=(e,t)=>(0,z.jsxs)(`div`,{className:`personal-goal-row${h.target?.id===e.goalId?h.target.after?` is-drop-after`:` is-drop-before`:``}`,"data-reorder-goal":t?void 0:e.goalId,"data-load-error":e.loadError,children:[(0,z.jsxs)(`button`,{...t?{}:h.pointerProps(e.goalId),title:t?void 0:f(`sidebar.dragGoal`),"aria-current":l===e.goalId?`page`:void 0,className:`personal-goal-link`,onClick:()=>c(e.goalId),type:`button`,children:[(0,z.jsx)(`span`,{className:`personal-goal-state-dot ${e.loadState?``:Xy[e.state]}`}),(0,z.jsxs)(`span`,{className:`personal-goal-link-copy`,children:[(0,z.jsx)(`strong`,{children:e.title}),(0,z.jsxs)(`small`,{children:[e.loadState&&(!t||l===e.goalId)?f(e.loadState===`error`?`startup.goalError`:`startup.goalLoading`):Yi(e.state,d),e.needsYou&&!t?` · ${f(`home.lane.needsYou`)}`:``]})]}),(0,z.jsx)(Jp,{size:15})]}),!t&&p?(0,z.jsxs)(`div`,{className:`personal-goal-move-actions`,children:[(0,z.jsx)(`button`,{type:`button`,"aria-label":f(`sidebar.moveUp`,{goal:e.title}),disabled:g[0]?.goalId===e.goalId,onClick:()=>h.moveBy(e.goalId,-1),children:(0,z.jsx)(Bp,{"aria-hidden":`true`,size:13})}),(0,z.jsx)(`button`,{type:`button`,"aria-label":f(`sidebar.moveDown`,{goal:e.title}),disabled:g.at(-1)?.goalId===e.goalId,onClick:()=>h.moveBy(e.goalId,1),children:(0,z.jsx)(Ip,{"aria-hidden":`true`,size:13})})]}):null,s?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`button`,{"aria-label":`${f(t?`sidebar.resume`:`sidebar.stop`)} ${e.title}`,"aria-busy":r?.has(e.goalId)||void 0,className:`personal-goal-lifecycle${r?.has(e.goalId)?` is-pending`:``}`,disabled:r?.has(e.goalId),onClick:()=>s(e,t?`resume`:`stop`),title:f(t?`sidebar.resumeGoal`:`sidebar.stopGoal`),type:`button`,children:r?.has(e.goalId)?(0,z.jsx)(hm,{size:13}):t?(0,z.jsx)(km,{size:13}):(0,z.jsx)(wm,{size:13})}),t?(0,z.jsx)(`button`,{"aria-label":`${f(`sidebar.delete`)} ${e.title}`,className:`personal-goal-lifecycle personal-goal-delete`,onClick:()=>s(e,`delete`),title:f(`sidebar.deleteGoal`),type:`button`,children:(0,z.jsx)(Hm,{size:13})}):null]}):null]},e.goalId);return(0,z.jsxs)(`div`,{className:`personal-goal-directory`,children:[(0,z.jsxs)(`div`,{className:`personal-sidebar-brand`,children:[(0,z.jsx)(`span`,{className:`personal-brand-mark`,children:(0,z.jsx)(Up,{size:18})}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:`LoopX`}),(0,z.jsx)(`small`,{children:f(`sidebar.product`)})]})]}),u?(0,z.jsx)(Yy,{...u}):null,(0,z.jsxs)(`nav`,{"aria-label":f(`home.workspace`),className:`personal-sidebar-nav`,children:[(0,z.jsxs)(`button`,{"aria-current":l===null?`page`:void 0,className:`personal-manager-link`,onClick:()=>c(null),type:`button`,children:[(0,z.jsx)(`span`,{className:`personal-manager-icon`,children:(0,z.jsx)(Up,{size:17})}),(0,z.jsx)(`span`,{children:f(`sidebar.manager`)}),e>0?(0,z.jsx)(`span`,{className:`personal-sidebar-count`,children:e}):null,(0,z.jsx)(Jp,{size:15})]}),(0,z.jsxs)(`div`,{className:`personal-sidebar-section-title`,children:[(0,z.jsx)(`span`,{children:`Goals`}),(0,z.jsxs)(`span`,{className:`personal-sidebar-title-actions`,children:[(0,z.jsx)(`small`,{children:g.length}),(0,z.jsx)(`button`,{"aria-label":f(`sidebar.sortGoals`),title:f(`sidebar.sortGoals`),"aria-pressed":p,onClick:()=>m(!p),type:`button`,children:(0,z.jsx)(zp,{"aria-hidden":`true`,size:15})}),i?(0,z.jsx)(`button`,{"aria-label":f(`sidebar.createGoal`),onClick:i,type:`button`,children:(0,z.jsx)(Em,{size:15})}):null]})]}),h.saveFailed?(0,z.jsx)(`p`,{role:`status`,children:f(`sidebar.orderNotSaved`)}):null,(0,z.jsx)(`span`,{className:`personal-sr-only`,role:`status`,children:h.lastMoved?f(`sidebar.goalMoved`,{goal:h.lastMoved.title,position:h.lastMoved.position}):``}),(0,z.jsx)(`div`,{className:`personal-goal-list`,children:g.map(e=>v(e,!1))}),_.length||n.phase===`loading`||n.phase===`error`?(0,z.jsxs)(`details`,{className:`personal-stopped-goals`,open:n.phase===`error`||void 0,children:[(0,z.jsxs)(`summary`,{children:[(0,z.jsx)(qp,{size:13}),(0,z.jsx)(`span`,{children:f(`sidebar.stopped`)}),n.phase===`loading`?(0,z.jsx)(hm,{"aria-label":f(`sidebar.stoppedLoading`),className:`is-spinning`,size:13}):(0,z.jsx)(`small`,{children:_.length})]}),(0,z.jsxs)(`div`,{className:`personal-goal-list is-stopped`,children:[n.phase===`error`?(0,z.jsxs)(`div`,{className:`personal-stopped-goal-error`,role:`alert`,children:[(0,z.jsx)(`span`,{children:f(`sidebar.stoppedLoadFailed`)}),o?(0,z.jsx)(`button`,{onClick:o,type:`button`,children:f(`sidebar.retryStopped`)}):null]}):null,_.map(e=>v(e,!0))]})]}):null]}),(0,z.jsxs)(`div`,{className:`personal-sidebar-footer`,children:[(0,z.jsx)(Iy,{}),a?(0,z.jsxs)(`button`,{"aria-label":f(`settings.open`),className:`personal-sidebar-utility`,onClick:a,type:`button`,children:[(0,z.jsx)(`span`,{className:`personal-sidebar-utility-icon`,children:(0,z.jsx)(Fm,{size:17})}),(0,z.jsxs)(`span`,{className:`personal-sidebar-utility-copy`,children:[(0,z.jsx)(`strong`,{children:f(`settings.open`)}),(0,z.jsx)(`small`,{children:f(`settings.eyebrow`)})]}),(0,z.jsx)(Jp,{"aria-hidden":`true`,size:15})]}):null]})]})}var Qy=J({ok:X(!0),total:G().int().nonnegative(),next_cursor:W().nullable(),items:q(J({todo_id:W(),text:W(),claimed_by:W().nullable(),evidence:W().nullable(),priority:W().nullable(),task_class:W().nullable()})).max(40)});function $y({goal:e,agentId:t,seed:n,enabled:r,listView:i=!1,onSelect:a}){let{t:o}=Ji(),s=(0,R.useId)(),[c,l]=(0,R.useState)(!1),u=!i||c,d=i?96:148,[f,p]=(0,R.useState)(n),[m,h]=(0,R.useState)(t===`all`?e.doneTodoCount??n.length:n.length),[g,_]=(0,R.useState)(void 0),[v,y]=(0,R.useState)(!1),[b,x]=(0,R.useState)(!1),[S,C]=(0,R.useState)(!1),[w,T]=(0,R.useState)({top:0,height:600}),[E,D]=(0,R.useState)(null),O=(0,R.useRef)(null),k=(0,R.useRef)(null),[ee,A]=(0,R.useState)(0);(0,R.useEffect)(()=>{let e=O.current;if(!e)return;let t=new ResizeObserver(()=>T({top:e.scrollTop,height:e.clientHeight}));return t.observe(e),()=>{t.disconnect(),k.current?.abort()}},[]);let j=g===void 0||w.top+w.height>=f.length*d-d*2;(0,R.useEffect)(()=>{if(!r||!u||!j||g===null||b||k.current)return;let n=new AbortController;k.current=n,y(!0);let i=new URLSearchParams({goal_id:e.goalId});t!==`all`&&i.set(`agent_id`,t),g&&i.set(`cursor`,g),fetch(`/api/chat/completed-todos?${i}`,{signal:n.signal}).then(async e=>{if(e.status===409&&C(!0),!e.ok)throw Error(`history unavailable`);let t=Qy.parse(await e.json());if(n.signal.aborted)return;let r=t.items.map(e=>({todoId:e.todo_id,text:e.text,claimedBy:e.claimed_by,evidence:e.evidence,priority:e.priority,taskClass:e.task_class,done:!0,status:`done`}));p(e=>g===void 0?r:[...e,...r.filter(t=>!e.some(e=>e.todoId===t.todoId))]),h(t.total),_(t.next_cursor)}).catch(()=>{n.signal.aborted||x(!0)}).finally(()=>{n.signal.aborted||(k.current=null,y(!1))})},[r,u,j,g,b,ee,e.goalId,t,v]),(0,R.useEffect)(()=>{O.current&&(O.current.scrollTop=0),T({top:0,height:O.current?.clientHeight??600}),D(null)},[i]);let te=Math.max(0,Math.floor(w.top/d)-3),ne=Math.min(f.length,Math.ceil((w.top+w.height)/d)+3),re=Array.from({length:Math.max(0,ne-te)},(e,t)=>te+t);return E!==null&&El(e=>!e),children:[(0,z.jsx)(`span`,{"aria-hidden":`true`,children:c?`▾`:`▸`}),` `,o(`tasks.completed`)]}):(0,z.jsxs)(`strong`,{children:[(0,z.jsx)(`i`,{"aria-hidden":`true`,className:`personal-kanban-dot tone-done`}),o(`tasks.completed`)]}),(0,z.jsx)(`span`,{children:m})]}),(0,z.jsxs)(`div`,{id:s,hidden:!u,"aria-label":o(`tasks.completed`),className:`personal-task-lane-scroll`,ref:O,role:`region`,tabIndex:0,onScroll:e=>T({top:e.currentTarget.scrollTop,height:e.currentTarget.clientHeight}),children:[(0,z.jsx)(`div`,{className:`personal-completed-window`,style:{height:f.length*d},children:re.map(t=>{let n=f[t];return(0,z.jsx)(`div`,{className:`personal-task-card personal-completed-row`,style:{top:t*d,height:d},children:(0,z.jsxs)(`button`,{type:`button`,onFocus:()=>D(t),onBlur:()=>D(null),onClick:()=>a({kind:`todo`,item:{...n,goalId:e.goalId,goalTitle:e.title,ownerLabel:n.claimedBy??e.agentLabel??e.agentId}}),children:[(0,z.jsx)(`span`,{className:`is-done`,children:`✓`}),(0,z.jsx)(`strong`,{children:n.text}),(0,z.jsx)(`small`,{children:n.claimedBy??e.agentLabel??e.agentId})]})},n.todoId)})}),(0,z.jsx)(`div`,{className:`personal-completed-footer`,role:`status`,children:v?o(`tasks.historyLoading`):b?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`span`,{children:o(S?`tasks.historyExpired`:`tasks.historyError`)}),(0,z.jsx)(`button`,{type:`button`,onClick:()=>{S&&(_(void 0),O.current&&(O.current.scrollTop=0)),C(!1),x(!1),A(e=>e+1)},children:o(`tasks.historyRetry`)})]}):r?g===null?o(`tasks.historyEnd`):(0,z.jsx)(`button`,{type:`button`,onClick:()=>{O.current&&(O.current.scrollTop=f.length*d)},children:o(`tasks.historyMore`)}):o(`tasks.historyLocalOnly`)})]})]})}function eb({children:e,count:t,label:n,tone:r,listView:i=!1}){let a=(0,R.useId)(),o=(0,R.useRef)(null),s=(0,R.useRef)([]),c=(0,R.useRef)(null),[l,u]=(0,R.useState)({after:!1,before:!1}),d=(0,R.useCallback)(()=>{let e=o.current;if(!e)return;let t={after:Math.max(0,e.scrollHeight-e.clientHeight)-e.scrollTop>1,before:e.scrollTop>1};u(e=>e.after===t.after&&e.before===t.before?e:t)},[]);return(0,R.useEffect)(()=>{let e=o.current;if(!e)return;let t=new ResizeObserver(d);return c.current=t,t.observe(e),e.addEventListener(`scroll`,d,{passive:!0}),d(),()=>{t.disconnect(),c.current=null,s.current=[],e.removeEventListener(`scroll`,d)}},[i,d]),(0,R.useEffect)(()=>{let e=o.current,t=c.current;if(!e||!t)return;for(let e of s.current)t.unobserve(e);let n=Array.from(e.children).filter(e=>e instanceof HTMLElement);for(let e of n)t.observe(e);s.current=n,d()},[e,t,i,d]),i?!t&&r!==`done`?null:(0,z.jsxs)(`details`,{className:`personal-task-group tone-${r}`,open:!0,children:[(0,z.jsxs)(`summary`,{children:[(0,z.jsx)(qp,{size:16}),(0,z.jsx)(`strong`,{children:n}),(0,z.jsx)(`span`,{children:t})]}),(0,z.jsx)(`div`,{className:`personal-task-list-rows`,children:e})]}):(0,z.jsxs)(`section`,{className:`personal-object-list personal-task-lane`,children:[(0,z.jsxs)(`header`,{id:a,children:[(0,z.jsxs)(`strong`,{children:[(0,z.jsx)(`i`,{"aria-hidden":`true`,className:`personal-kanban-dot tone-${r}`}),n]}),(0,z.jsx)(`span`,{children:t})]}),(0,z.jsx)(`div`,{"aria-labelledby":a,className:`personal-task-lane-scroll${l.before?` has-overflow-before`:``}${l.after?` has-overflow-after`:``}`,ref:o,role:`region`,tabIndex:t>0?0:-1,children:e})]})}function tb({historyEnabled:e=!1,goal:t,items:n,onDraftTaskFromMessage:r,onOpenChat:i,onQuickComplete:a,quickCompletingTodoIds:o,onSelect:s,selectedTodoId:c=null,userTodos:l}){let{t:u}=Ji(),[d,f]=(0,R.useState)(!1),[p,m]=(0,R.useState)({goalId:``,laneId:`all`}),h=(0,R.useRef)(null);(0,R.useEffect)(()=>{if(!c)return;let e=window.requestAnimationFrame(()=>h.current?.scrollIntoView({block:`nearest`,inline:`nearest`}));return()=>window.cancelAnimationFrame(e)},[c]);let g=l.filter(e=>e.goalId===t.goalId).map(e=>({...e,goalTitle:t.title})),_=e=>e.priority===`P0`?0:e.priority===`P1`?1:e.priority===`P2`?2:3,v=(0,R.useMemo)(()=>{let e=new Map((t.agentLanes??[]).map(e=>[e.agentId,e]));for(let n of t.agentTodos)n.claimedBy&&!e.has(n.claimedBy)&&e.set(n.claimedBy,{agentId:n.claimedBy,label:n.claimedBy});return[...e.values()]},[t.agentLanes,t.agentTodos]),y=p.goalId===t.goalId&&v.some(e=>e.agentId===p.laneId)?p.laneId:`all`,b=e=>y===`all`||e===y,x=t.agentTodos.filter(e=>e.taskClass!==`continuous_monitor`&&!e.done).filter(e=>b(e.claimedBy)).sort((e,t)=>_(e)-_(t)),S=t.agentTodos.filter(e=>e.taskClass!==`continuous_monitor`&&e.done).filter(e=>b(e.claimedBy)),C=n.filter(e=>e.kind===`schedule`&&b(e.schedule.agentId)),w=n.filter(e=>e.kind===`run`&&!!e.run.todoId&&b(e.run.agentId)),T=!g.length&&!x.length&&!S.length&&!C.length,E=n.filter(e=>e.kind===`message`&&(e.message.role===`user`||e.message.role===`assistant`)),D=E.reduce((e,t,n)=>t.message.role===`user`?n:e,-1),O=D>=0?E[D]?.message:null,k=D>=0?E.slice(D+1).reverse().find(e=>e.message.role===`assistant`)?.message:null,ee=D>=0&&E.slice(D+1).some(e=>e.message.role===`assistant`&&e.message.pending);return(0,z.jsxs)(`section`,{"aria-label":u(`header.tasks`),className:`personal-task-board${d?` is-list-view`:``}`,children:[(0,z.jsxs)(`header`,{className:`personal-task-view-toolbar`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:u(`header.tasks`)}),(0,z.jsx)(`span`,{children:u(`tasks.viewDescription`)})]}),(0,z.jsxs)(`div`,{className:`personal-task-view-switch`,role:`group`,"aria-label":u(`tasks.viewLabel`),children:[(0,z.jsx)(`button`,{type:`button`,"aria-pressed":d,onClick:()=>f(!0),children:u(`tasks.listView`)}),(0,z.jsx)(`button`,{type:`button`,"aria-pressed":!d,onClick:()=>f(!1),children:u(`tasks.boardView`)})]})]}),v.length>1?(0,z.jsxs)(`section`,{"aria-label":u(`tasks.agentLaneFilter`),className:`personal-task-lane-filter`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(Up,{size:15}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:u(`tasks.agentLane`)}),(0,z.jsx)(`small`,{children:u(`tasks.agentLaneDescription`)})]})]}),(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{className:`sr-only`,children:u(`tasks.agentLaneFilter`)}),(0,z.jsxs)(`select`,{"aria-label":u(`tasks.agentLaneFilter`),onChange:e=>m({goalId:t.goalId,laneId:e.target.value}),value:y,children:[(0,z.jsx)(`option`,{value:`all`,children:u(`tasks.allAgentLanes`,{count:v.length})}),v.map(e=>(0,z.jsx)(`option`,{value:e.agentId,children:e.label},e.agentId))]}),(0,z.jsx)(qp,{"aria-hidden":!0,size:14})]})]}):null,O?(0,z.jsxs)(`section`,{"aria-label":u(`tasks.chatRecent`),className:`personal-task-chat-receipt`,children:[(0,z.jsx)(`span`,{className:`personal-task-chat-icon`,children:(0,z.jsx)(ym,{size:18})}),(0,z.jsxs)(`div`,{children:[(0,z.jsxs)(`header`,{children:[(0,z.jsx)(`strong`,{children:u(ee?`tasks.chatPending`:k?`tasks.chatAgentReplied`:`tasks.chatRecent`)}),(0,z.jsx)(`small`,{children:t.agentLabel??t.agentId})]}),(0,z.jsxs)(`p`,{className:`is-user`,children:[(0,z.jsx)(`b`,{children:u(`common.you`)}),O.text]}),k&&!k.pending?(0,z.jsxs)(`p`,{className:`is-assistant`,children:[(0,z.jsx)(`b`,{children:u(`common.agent`)}),k.text]}):null,(0,z.jsx)(`small`,{children:u(ee?`tasks.chatPendingDescription`:`tasks.chatUnchangedDescription`)})]}),(0,z.jsxs)(`footer`,{children:[(0,z.jsxs)(`button`,{onClick:i,type:`button`,children:[(0,z.jsx)(ym,{size:14}),u(`tasks.chatViewReply`)]}),k&&!ee&&r?(0,z.jsxs)(`button`,{onClick:()=>r(k.text),type:`button`,children:[(0,z.jsx)(mm,{size:14}),u(`tasks.convertToTask`)]}):null]})]}):null,(0,z.jsxs)(`div`,{className:d?`personal-task-grouped-list`:`personal-task-kanban`,children:[(0,z.jsxs)(eb,{listView:d,count:g.length,label:u(`timeline.waitingConfirmation`),tone:`attention`,children:[g.map(e=>{let t=Zi(e.updatedAt,u);return(0,z.jsxs)(`button`,{onClick:()=>s({item:e,kind:`attention`}),type:`button`,children:[(0,z.jsx)(`span`,{"aria-hidden":`true`,className:`is-attention`,children:`!`}),(0,z.jsx)(`strong`,{children:e.text}),(0,z.jsxs)(`small`,{children:[(0,z.jsx)(`span`,{className:`personal-row-status ${e.blocking?`is-blocking`:`is-pending`}`,children:e.blocking?u(`tasks.blocked`):u(`tasks.pending`)}),t?(0,z.jsx)(`span`,{className:`personal-task-age`,children:u(`tasks.waitingAge`,{age:t})}):null]})]},e.todoId)}),g.length?null:(0,z.jsx)(`p`,{className:`personal-task-empty`,children:u(`tasks.emptyConfirm`)})]}),(0,z.jsxs)(eb,{listView:d,count:x.length,label:u(`tasks.pendingAndRunning`),tone:`progress`,children:[x.map(e=>{let n={...e,goalId:t.goalId,goalTitle:t.title,ownerLabel:e.claimedBy??t.agentLabel??t.agentId},r=w.find(t=>t.run.todoId===e.todoId)?.run;return(0,z.jsxs)(`div`,{className:`personal-task-card${r?` has-session`:``}${c===e.todoId?` is-selected`:``}`,ref:c===e.todoId?e=>{h.current=e}:void 0,children:[(0,z.jsxs)(`button`,{"aria-pressed":c===e.todoId,onClick:()=>s({item:n,kind:`todo`}),type:`button`,children:[(0,z.jsx)(`span`,{children:`○`}),(0,z.jsx)(`strong`,{children:e.text}),(0,z.jsxs)(`small`,{children:[e.priority?(0,z.jsx)(`span`,{className:`personal-priority-badge is-${e.priority.toLowerCase()}`,children:e.priority}):null,e.status===`blocked`?(0,z.jsx)(`span`,{className:`personal-priority-badge is-blocked`,children:u(`tasks.blocked`)}):null,r?(0,z.jsx)(`span`,{className:`personal-task-session-status`,children:r.status===`running`||r.status===`queued`?u(`runs.running`):r.status===`failed`?u(`tasks.sessionError`):u(`common.waiting`)}):null,e.status===`deferred`?(0,z.jsx)(`span`,{className:`personal-task-session-status`,children:u(`drawer.taskStatusDeferred`)}):r?null:(0,z.jsx)(`span`,{className:`personal-task-session-status`,children:u(`tasks.waiting`)}),e.claimedBy??t.agentLabel??t.agentId]})]}),(0,z.jsxs)(`div`,{className:`personal-task-card-actions`,children:[r?(0,z.jsxs)(`button`,{className:`personal-task-session-link`,"aria-label":u(`tasks.openExecution`,{name:e.text}),onClick:()=>s({item:r,kind:`run`}),title:r.status===`completed`?u(`tasks.viewResult`):u(`tasks.viewExecution`),type:`button`,children:[(0,z.jsx)(im,{size:14}),(0,z.jsx)(`span`,{children:r.status===`completed`?u(`tasks.viewResult`):u(`tasks.viewExecution`)})]}):null,a?(0,z.jsx)(`button`,{"aria-busy":o?.has(e.todoId)||void 0,"aria-label":u(`tasks.markComplete`,{name:e.text}),disabled:o?.has(e.todoId),onClick:()=>void a(n),title:u(`tasks.completed`),type:`button`,children:o?.has(e.todoId)?(0,z.jsx)(hm,{className:`personal-spin`,size:14}):(0,z.jsx)(Kp,{size:14})}):null,(0,z.jsx)(`button`,{"aria-label":u(`tasks.moreActions`,{name:e.text}),onClick:()=>s({item:n,kind:`todo`}),title:u(`common.actions`),type:`button`,children:(0,z.jsx)(rm,{size:14})})]})]},e.todoId)}),x.length?null:(0,z.jsx)(`p`,{className:`personal-task-empty`,children:u(`tasks.emptyRunning`)})]}),(0,z.jsxs)(eb,{listView:d,count:C.length,label:u(`tasks.scheduled`),tone:`schedule`,children:[C.map(e=>(0,z.jsxs)(`button`,{onClick:()=>s({item:e.schedule,kind:`schedule`}),type:`button`,children:[(0,z.jsx)(`span`,{children:`◷`}),(0,z.jsx)(`strong`,{children:e.schedule.label}),(0,z.jsx)(`small`,{children:e.schedule.status===`paused`?u(`schedule.paused`):u(`schedule.active`)})]},e.id)),C.length?null:(0,z.jsx)(`p`,{className:`personal-task-empty`,children:u(`tasks.emptySchedules`)})]}),(0,z.jsx)($y,{goal:t,agentId:y,seed:S,enabled:e,listView:d,onSelect:s},`${t.goalId}:${y}:${e}`)]}),T?(0,z.jsx)(`p`,{className:`personal-task-empty`,children:u(`tasks.emptyGoal`)}):null]})}function nb(e,t){return{live_steering:{label:t(`lark.ingressSteering`),detail:t(`lark.ingressSteeringDescription`)},session_queue:{label:t(`lark.ingressQueue`),detail:t(`lark.ingressQueueDescription`)},async_inbox:{label:t(`lark.ingressAsync`),detail:t(`lark.ingressAsyncDescription`)},direct_session:{label:t(`lark.ingressLegacy`),detail:t(`lark.ingressLegacyDescription`)}}[e]}function rb(e,t){return e.listener_status===`starting`?{label:t(`lark.health.starting`),detail:t(`lark.health.startingDetail`),ready:!1}:e.listener_status===`retrying`?{label:t(`lark.health.retrying`),detail:t(`lark.health.retryingDetail`),ready:!1}:e.listener_status===`stopped`||e.listener_status===null?{label:t(`lark.health.notStarted`),detail:t(`lark.health.notStartedDetail`),ready:!1}:e.last_event_status===`message_context_permission_required`?{label:t(`lark.health.messageContextPermission`),detail:t(`lark.health.messageContextPermissionDetail`),ready:!1}:e.last_event_status===`processing_failed`?{label:t(`lark.health.processingFailed`),detail:t(`lark.health.processingFailedDetail`),ready:!1}:e.health_error_code===`invalid_routing_state`?{label:t(`lark.health.invalidRouting`),detail:t(`lark.health.invalidRoutingDetail`),ready:!1}:e.last_event_status===`queued_for_agent`?{label:t(`lark.health.queued`),detail:t(`lark.health.queuedDetail`,{agent:e.agent_id??t(`lark.targetAgent`)}),ready:!0}:e.last_event_status===`ignored`&&e.last_event_reason===`not_addressed`?{label:t(`lark.health.notAddressed`),detail:t(`lark.health.notAddressedDetail`),ready:!0}:e.last_event_status===`ignored`&&e.last_event_reason===`self_message`?{label:t(`lark.health.listening`),detail:t(`lark.health.ignoredSelf`),ready:!0}:e.health_error_code===`lark_event_route_mismatch`||[`chat_mismatch`,`topic_mismatch`,`route_ambiguous`].includes(e.last_event_reason??``)?{label:e.last_event_reason===`route_ambiguous`?t(`lark.health.routeAmbiguous`):t(`lark.health.routeMismatch`),detail:e.last_event_reason===`route_ambiguous`?t(`lark.health.routeAmbiguousDetail`):t(`lark.health.routeMismatchDetail`),ready:!1}:[`invalid_event`,`binding_unavailable`].includes(e.last_event_reason??``)?{label:t(`lark.health.routeUnavailable`),detail:t(`lark.health.routeUnavailableDetail`),ready:!1}:e.last_event_status===`replied_and_acknowledged`?{label:t(`lark.health.listening`),detail:t(`lark.health.eventProcessed`,{events:e.event_count,replies:e.replied_count}),ready:!0}:e.health_error_code===`lark_event_delivery_unverified`||e.event_count===0?{label:t(`lark.health.eventUnverified`),detail:t(`lark.health.eventUnverifiedDetail`),ready:!1}:{label:e.reply_ready?t(`lark.health.listening`):t(`lark.health.unavailable`),detail:t(`lark.health.lastStatus`,{status:e.last_event_status??t(`lark.health.waiting`)}),ready:e.reply_ready}}function ib(e){return e.history_permission_guidance?.api_document_url??null}function ab(e,t,n){if(e instanceof _h){let t=String(e.payload.error_code??``);return{lark_cli_not_installed:n(`lark.error.cliMissing`),lark_cli_not_executable:n(`lark.error.cliExecutable`),lark_cli_start_failed:n(`lark.error.cliStart`),lark_message_permissions_required:n(`lark.error.messagePermissions`),lark_app_required:n(`lark.error.appRequired`),invalid_lark_app:n(`lark.error.invalidApp`),lark_group_lookup_failed:n(`lark.error.groupLookup`),provider_api_failed:n(`lark.error.provider`)}[t]??e.message}return e instanceof Error?e.message:t}function ob({embedded:e=!1,focusGoalConnection:t=!1,goals:n,initialGoalId:r,onChanged:i,onClose:a}){let{t:o}=Ji(),[s,c]=(0,R.useState)(`connections`),[l,u]=(0,R.useState)([]),[d,f]=(0,R.useState)([]),[p,m]=(0,R.useState)(!0),[h,g]=(0,R.useState)(null),[_,v]=(0,R.useState)(``),[y,b]=(0,R.useState)(t),[x,S]=(0,R.useState)(``),[C,w]=(0,R.useState)(r??n[0]?.goalId??``),[T,E]=(0,R.useState)(``),[D,O]=(0,R.useState)([]),[k,ee]=(0,R.useState)(``),[A,j]=(0,R.useState)(!1),[te,ne]=(0,R.useState)(null),[re,M]=(0,R.useState)(`addressed_only`),[N,ie]=(0,R.useState)(`async_inbox`),[ae,oe]=(0,R.useState)(`topic_reply`),[P,F]=(0,R.useState)(``),[I,se]=(0,R.useState)(!1),[ce,le]=(0,R.useState)({}),[ue,de]=(0,R.useState)(!1),[fe,pe]=(0,R.useState)(null),[me,he]=(0,R.useState)(null),[ge,_e]=(0,R.useState)(null),[ve,ye]=(0,R.useState)(!1),[be,xe]=(0,R.useState)(`loopx-workspace-bot`),[Se,Ce]=(0,R.useState)(`feishu`),[we,Te]=(0,R.useState)(null),[Ee,De]=(0,R.useState)(!1),[L,Oe]=(0,R.useState)(null),ke=(0,R.useRef)(null),Ae=(0,R.useRef)(null),je=(0,R.useRef)(!1);async function Me(){m(!0),g(null);try{let[e,t]=await Promise.all([Og(),Lg()]);u(e),f(t),S(t=>t||e.find(e=>e.reply_ready)?.app_ref||e.find(e=>e.ready)?.app_ref||e[0]?.app_ref||``)}catch(e){g(ab(e,o(`lark.error.configuration`),o))}finally{m(!1)}}(0,R.useEffect)(()=>{Me()},[]),(0,R.useEffect)(()=>{if(!t||p||je.current||!r)return;je.current=!0;let e=d.find(e=>e.goal_id===r);e?Ue(e):He(n.find(e=>e.goalId===r))},[d,t,n,r,p]),(0,R.useEffect)(()=>{if(!y||!x){O([]),ee(``),j(!1),ne(null);return}let e=!1;j(!0),ne(null);let t=window.setTimeout(()=>{Fg(x,T).then(t=>{e||(O(t),ee(e=>t.some(t=>t.chat_id===e)?e:t[0]?.chat_id??``))}).catch(t=>{e||(O([]),ee(``),ne(ab(t,o(`lark.error.groupLoad`),o)))}).finally(()=>{e||j(!1)})},180);return()=>{e=!0,window.clearTimeout(t)}},[x,T,y]),(0,R.useEffect)(()=>{if(!ve||!we||[`ready`,`failed`,`cancelled`].includes(we.status))return;let e=!1,t=window.setTimeout(()=>{jg(we.setup_id).then(async t=>{e||(Te(t),t.verification_url&&Ae.current!==t.verification_url&&(Ae.current=t.verification_url,ke.current&&!ke.current.closed&&(ke.current.location.href=t.verification_url)),t.status===`ready`&&(await Me(),S(t.app_ref),le({}),ye(!1)),t.status===`failed`&&Oe(t.error??o(`lark.error.appCreate`)))}).catch(t=>{e||Oe(ab(t,o(`lark.error.setupPoll`),o))})},650);return()=>{e=!0,window.clearTimeout(t)}},[ve,we]);let Ne=n.find(e=>e.goalId===C),Pe=Ne?.agentId?[{agentId:Ne.agentId,label:Ne.agentLabel??Ne.agentId}]:[],Fe=Ne?.agentLanes?.length?Ne.agentLanes:Pe,Ie=Fe.some(e=>e.agentId===P),B=[];I?B=Fe.map(e=>({agentId:e.agentId,appRef:ce[e.agentId]??x})):Ie&&(B=[{agentId:P,appRef:x}]);let Le=B.map(e=>e.agentId),Re=B.length>0&&B.every(e=>l.some(t=>t.app_ref===e.appRef&&t.reply_ready)),V=o(`lark.connect`);me?V=o(`lark.saveConnection`):I&&(V=o(`lark.connectAllAgentsAction`,{count:Le.length}));let ze=l.find(e=>e.app_ref===x),Be=D.find(e=>e.chat_id===k),Ve=(0,R.useMemo)(()=>{let e=_.trim().toLocaleLowerCase();return e?d.filter(t=>[t.app_label,t.chat_name,t.goal_title,t.topic_name].some(t=>t.toLocaleLowerCase().includes(e))):d},[d,_]);function He(e){let t=e??n.find(e=>e.goalId===r)??n[0];he(null),w(t?.goalId??``),F(t?.agentId??``),se(!1),le({}),M(`addressed_only`),ie(`async_inbox`),oe(`topic_reply`),E(``),pe(null),b(!0)}function Ue(e){he(e.goal_id),S(e.app_ref),w(e.goal_id),F(e.agent_id??n.find(t=>t.goalId===e.goal_id)?.agentId??``),se(!1),le({}),M(e.capture_scope),ie(e.ingress_mode===`direct_session`?`session_queue`:e.ingress_mode),oe(e.reply_mode),E(e.chat_name),pe(null),b(!0)}function We(){Te(null),Oe(null),Ae.current=null,ye(!0)}async function Ge(){if(!(Ee||!/^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$/.test(be))){De(!0),Oe(null),Ae.current=null,ke.current=window.open(window.location.href,`_blank`);try{let e=await Ag({appRef:be,brand:Se});Te(e)}catch(e){ke.current?.close(),Oe(ab(e,o(`lark.error.setupStart`),o))}finally{De(!1)}}}async function Ke(){let e=we;if(ye(!1),ke.current?.close(),e&&![`ready`,`failed`,`cancelled`].includes(e.status))try{await Mg(e.setup_id)}catch{}}async function qe(){if(!(!x||!C||!Be||Le.length===0||ue)){de(!0),pe(null);try{let e={agentBindings:B,captureScope:re,chatId:Be.chat_id,chatName:Be.chat_name,goalId:C,incomingMode:re===`configured_chat_all`?`all`:`mentions`,ingressMode:N,replyMode:ae},t=await Rg({...e,execute:!1});if(!t.ok)throw new _h(t.public_summary??t.blocker??o(`lark.error.bindPreview`),{error_code:t.blocker??`provider_api_failed`});let n=await Rg({...e,execute:!0});if(!n.ok)throw new _h(n.public_summary??n.blocker??o(`lark.error.bind`),{error_code:n.blocker??`provider_api_failed`});b(!1),await Me(),i?.()}catch(e){pe(ab(e,o(`lark.error.bind`),o))}finally{de(!1)}}}async function Je(e,t){if(ge!==t){_e(t);return}try{await zg(e,t),_e(null),await Me(),i?.()}catch(e){g(ab(e,o(`lark.error.disconnect`),o))}}return(0,z.jsxs)(`section`,{className:`personal-lark-settings${e?` is-embedded`:``}`,"aria-label":o(`lark.configuration`),children:[e?null:(0,z.jsxs)(`header`,{className:`personal-lark-header`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`small`,{children:o(`settings.goalConnections`)}),(0,z.jsx)(`h1`,{children:`Lark`}),(0,z.jsx)(`p`,{children:o(`lark.description`)})]}),(0,z.jsx)(`button`,{"aria-label":o(`lark.closeSettings`),className:`personal-icon-button`,onClick:a,type:`button`,children:(0,z.jsx)(Gm,{size:18})})]}),(0,z.jsxs)(`nav`,{className:`personal-lark-tabs`,"aria-label":o(`lark.management`),children:[(0,z.jsxs)(`button`,{"aria-current":s===`apps`?`page`:void 0,onClick:()=>c(`apps`),type:`button`,children:[o(`lark.apps`),` `,(0,z.jsx)(`span`,{children:p?`…`:l.length})]}),(0,z.jsxs)(`button`,{"aria-current":s===`connections`?`page`:void 0,onClick:()=>c(`connections`),type:`button`,children:[o(`lark.connections`),` `,(0,z.jsx)(`span`,{children:p?`…`:d.length})]})]}),h?(0,z.jsx)(`p`,{className:`personal-notification-error`,children:h}):null,p?(0,z.jsxs)(`div`,{className:`personal-lark-loading`,children:[(0,z.jsx)(hm,{className:`is-spinning`,size:18}),o(`lark.loading`)]}):null,!p&&s===`apps`?(0,z.jsxs)(`div`,{className:`personal-lark-apps`,children:[(0,z.jsxs)(`div`,{className:`personal-lark-app-toolbar`,children:[(0,z.jsx)(`span`,{children:o(`lark.reusableApps`,{count:l.length})}),(0,z.jsxs)(`button`,{className:`personal-primary-action`,onClick:We,type:`button`,children:[(0,z.jsx)(Em,{size:16}),o(`lark.newApp`)]})]}),(0,z.jsxs)(`div`,{className:`personal-lark-app-grid`,children:[l.map(e=>(0,z.jsxs)(`article`,{className:`personal-lark-app-card`,children:[(0,z.jsx)(`span`,{className:`personal-lark-app-avatar`,children:(0,z.jsx)(Up,{size:19})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:e.label}),(0,z.jsxs)(`small`,{children:[e.brand,` · lark-cli profile`]})]}),(0,z.jsx)(`em`,{className:e.reply_ready?`is-ready`:`is-off`,children:e.reply_ready?o(`lark.autoReplyReady`):e.ready?o(`lark.needsMessagePermissions`):o(`lark.needsSetup`)}),(0,z.jsxs)(`p`,{children:[o(`lark.goalConnections`,{count:d.filter(t=>t.app_ref===e.app_ref).length}),e.ready&&!e.reply_ready?` · ${o(`lark.autoReplyUnavailable`)}`:``]})]},e.app_ref)),l.length===0?(0,z.jsx)(`p`,{className:`personal-lark-empty`,children:o(`lark.noProfiles`)}):null]})]}):null,!p&&s===`connections`?(0,z.jsxs)(`div`,{className:`personal-lark-connections`,children:[(0,z.jsxs)(`div`,{className:`personal-lark-toolbar`,children:[(0,z.jsxs)(`label`,{children:[(0,z.jsx)(jm,{size:16}),(0,z.jsx)(`input`,{"aria-label":o(`lark.searchConnections`),onChange:e=>v(e.target.value),placeholder:o(`lark.searchPlaceholder`),type:`search`,value:_})]}),(0,z.jsxs)(`button`,{className:`personal-primary-action`,disabled:l.length===0||n.length===0,onClick:()=>He(),type:`button`,children:[(0,z.jsx)(Em,{size:16}),o(`lark.connectApp`)]})]}),(0,z.jsxs)(`div`,{className:`personal-lark-table`,role:`table`,"aria-label":o(`lark.goalTopicConnections`),children:[(0,z.jsxs)(`div`,{className:`personal-lark-table-head`,role:`row`,children:[(0,z.jsx)(`span`,{children:o(`lark.connection`)}),(0,z.jsx)(`span`,{children:o(`common.goal`)}),(0,z.jsx)(`span`,{children:o(`lark.capture`)}),(0,z.jsx)(`span`,{children:o(`lark.processing`)}),(0,z.jsx)(`span`,{children:o(`common.actions`)})]}),Ve.map(e=>(0,z.jsxs)(`div`,{className:`personal-lark-table-row`,role:`row`,children:[(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:e.chat_name}),(0,z.jsxs)(`small`,{children:[e.app_label,` · `,rb(e,o).label]}),(0,z.jsx)(`small`,{children:rb(e,o).detail}),e.health_error_code===`lark_event_delivery_unverified`?(0,z.jsxs)(`a`,{href:`https://open.feishu.cn/document/server-docs/im-v1/message/events/receive?lang=zh-CN`,rel:`noreferrer`,target:`_blank`,children:[(0,z.jsx)(im,{size:12}),o(`lark.openEventSettings`)]}):null,ib(e)?(0,z.jsxs)(`a`,{href:ib(e)??void 0,rel:`noreferrer`,target:`_blank`,children:[(0,z.jsx)(im,{size:12}),o(`lark.historyPermission`)]}):null]}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:e.goal_title}),(0,z.jsxs)(`small`,{children:[`# `,e.topic_name]})]}),(0,z.jsx)(`span`,{children:e.capture_scope===`addressed_only`?o(`lark.mentionsOnly`):o(`lark.allTopicMessages`)}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:nb(e.ingress_mode,o).label}),(0,z.jsx)(`small`,{children:e.agent_id??nb(e.ingress_mode,o).detail})]}),(0,z.jsxs)(`span`,{className:`personal-lark-row-actions`,children:[(0,z.jsx)(`button`,{"aria-label":o(`lark.settingsConfigure`,{goal:e.goal_title}),onClick:()=>Ue(e),type:`button`,children:(0,z.jsx)(Fm,{size:15})}),(0,z.jsxs)(`button`,{"aria-label":o(`lark.settingsDisconnect`,{goal:e.goal_title}),className:ge===e.connection_id?`is-confirm`:``,onClick:()=>void Je(e.goal_id,e.connection_id),type:`button`,children:[(0,z.jsx)(Wm,{size:15}),ge===e.connection_id?o(`common.confirm`):null]})]})]},e.connection_id)),Ve.length===0?(0,z.jsx)(`p`,{className:`personal-lark-empty`,children:o(`lark.noConnections`)}):null]})]}):null,y?(0,z.jsx)(`div`,{className:`personal-lark-modal-backdrop`,role:`presentation`,children:(0,z.jsxs)(`section`,{"aria-labelledby":`connect-lark-title`,"aria-modal":`true`,className:`personal-lark-modal`,role:`dialog`,children:[(0,z.jsxs)(`header`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`small`,{children:`Goal Topic connection`}),(0,z.jsx)(`h2`,{id:`connect-lark-title`,children:o(me?`lark.editConnection`:`lark.connectApp`)})]}),(0,z.jsx)(`button`,{"aria-label":o(`lark.closeConnection`),onClick:()=>b(!1),type:`button`,children:(0,z.jsx)(Gm,{size:18})})]}),(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:o(`lark.appProfile`)}),(0,z.jsx)(`select`,{"aria-label":o(`lark.appProfile`),disabled:p,onChange:e=>{e.target.value===`__register__`?We():(S(e.target.value),le({}))},value:x,children:p?(0,z.jsx)(`option`,{value:``,children:o(`lark.appLoading`)}):(0,z.jsxs)(z.Fragment,{children:[l.map(e=>(0,z.jsxs)(`option`,{disabled:!e.ready,value:e.app_ref,children:[e.label,e.reply_ready?``:e.ready?` · ${o(`lark.needsMessagePermissions`)}`:` · ${o(`lark.needsSetup`)}`]},e.app_ref)),(0,z.jsx)(`option`,{value:`__register__`,children:o(`lark.registerAnother`)})]})}),(0,z.jsx)(`small`,{children:o(`lark.defaultAgentAppDescription`)})]}),ze?.ready&&!ze.reply_ready?(0,z.jsx)(`div`,{className:`personal-lark-group-state is-error`,role:`alert`,children:o(`lark.appPermissions`)}):null,(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:o(`lark.groupChat`)}),(0,z.jsx)(`input`,{"aria-label":o(`lark.groupSearch`),onChange:e=>E(e.target.value),placeholder:o(`lark.groupSearch`),type:`search`,value:T}),A?(0,z.jsxs)(`div`,{className:`personal-lark-group-state`,role:`status`,children:[(0,z.jsx)(hm,{className:`is-spinning`,size:15}),o(`lark.groupLoading`)]}):null,!A&&te?(0,z.jsx)(`div`,{className:`personal-lark-group-state is-error`,role:`alert`,children:te}):null,!A&&!te&&D.length===0?(0,z.jsx)(`div`,{className:`personal-lark-group-state`,role:`status`,children:o(`lark.groupEmpty`)}):null,!A&&!te&&D.length>0?(0,z.jsx)(`select`,{"aria-label":o(`lark.groupChat`),onChange:e=>ee(e.target.value),value:k,children:D.map(e=>(0,z.jsx)(`option`,{value:e.chat_id,children:e.chat_name},e.chat_id))}):null]}),(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:o(`lark.bindGoal`)}),(0,z.jsx)(`select`,{"aria-label":o(`lark.bindGoal`),onChange:e=>{let t=e.target.value;w(t),F(n.find(e=>e.goalId===t)?.agentId??``),le({})},value:C,children:n.map(e=>(0,z.jsx)(`option`,{value:e.goalId,children:e.title},e.goalId))})]}),(0,z.jsxs)(`label`,{className:`personal-lark-check`,children:[(0,z.jsx)(`input`,{checked:!0,readOnly:!0,type:`checkbox`}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:o(`lark.createAutomatically`)}),(0,z.jsx)(`small`,{children:o(`lark.createAutomaticallyDescription`)})]})]}),(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:o(`lark.topicPreview`)}),(0,z.jsxs)(`div`,{className:`personal-lark-topic-preview`,children:[(0,z.jsx)(ym,{size:15}),`# `,Ne?.title??Ne?.goalId??`Goal`]})]}),(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:o(`lark.captureScope`)}),(0,z.jsxs)(`select`,{"aria-label":o(`lark.captureScope`),onChange:e=>M(e.target.value),value:re,children:[(0,z.jsx)(`option`,{value:`addressed_only`,children:o(`lark.captureAddressed`)}),(0,z.jsx)(`option`,{value:`configured_chat_all`,children:o(`lark.captureAll`)})]}),(0,z.jsx)(`small`,{children:o(`lark.captureScopeDescription`)})]}),(0,z.jsxs)(`fieldset`,{"aria-label":o(`lark.agentIngress`),className:`personal-lark-ingress`,children:[(0,z.jsx)(`legend`,{children:o(`lark.agentIngress`)}),(0,z.jsx)(`div`,{children:[`live_steering`,`session_queue`,`async_inbox`].map(e=>{let t=nb(e,o);return(0,z.jsxs)(`label`,{className:N===e?`is-active`:``,children:[(0,z.jsx)(`input`,{"aria-label":t.label,checked:N===e,name:`lark-agent-ingress`,onChange:()=>ie(e),type:`radio`,value:e}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:t.label}),(0,z.jsx)(`small`,{children:t.detail})]})]},e)})})]}),(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:o(`lark.targetAgent`)}),(0,z.jsxs)(`select`,{"aria-label":o(`lark.targetAgent`),onChange:e=>F(e.target.value),value:P,children:[Ie?null:(0,z.jsx)(`option`,{disabled:!0,value:P,children:P?o(`lark.agentUnavailable`,{agent:P}):o(`lark.noAgentConfigured`)}),Fe.map(e=>(0,z.jsx)(`option`,{value:e.agentId,children:e.label===e.agentId?e.agentId:`${e.label} · ${e.agentId}`},e.agentId))]}),(0,z.jsx)(`small`,{children:o(`lark.targetAgentDescription`)})]}),!me&&Fe.length>1?(0,z.jsxs)(`label`,{"aria-label":o(`lark.connectAllAgents`),className:`personal-lark-check`,children:[(0,z.jsx)(`input`,{checked:I,onChange:e=>se(e.target.checked),type:`checkbox`}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:o(`lark.connectAllAgents`)}),(0,z.jsx)(`small`,{children:o(`lark.connectAllAgentsDescription`,{count:Fe.length})})]})]}):null,!me&&I&&Fe.length>1?(0,z.jsxs)(`fieldset`,{"aria-label":o(`lark.agentApps`),className:`personal-lark-agent-apps`,children:[(0,z.jsx)(`legend`,{children:o(`lark.agentApps`)}),(0,z.jsx)(`small`,{children:o(`lark.agentAppsDescription`)}),(0,z.jsx)(`div`,{children:Fe.map(e=>(0,z.jsxs)(`label`,{children:[(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:e.label}),(0,z.jsx)(`small`,{children:e.agentId})]}),(0,z.jsx)(`select`,{"aria-label":o(`lark.agentAppSelection`,{agent:e.label}),onChange:t=>le(n=>({...n,[e.agentId]:t.target.value})),value:ce[e.agentId]??x,children:l.map(e=>(0,z.jsxs)(`option`,{disabled:!e.ready,value:e.app_ref,children:[e.label,e.reply_ready?``:e.ready?` · ${o(`lark.needsMessagePermissions`)}`:` · ${o(`lark.needsSetup`)}`]},e.app_ref))})]},e.agentId))})]}):null,I&&B.length>0&&!Re?(0,z.jsx)(`div`,{className:`personal-lark-group-state is-error`,role:`alert`,children:o(`lark.agentAppPermissions`)}):null,Le.length===0?(0,z.jsx)(`p`,{className:`personal-notification-error`,role:`alert`,children:o(`lark.selectRegisteredAgent`)}):null,(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:o(`lark.replyMode`)}),(0,z.jsx)(`select`,{"aria-label":o(`lark.replyMode`),onChange:e=>oe(e.target.value),value:ae,children:(0,z.jsx)(`option`,{value:`topic_reply`,children:o(`lark.topicReply`)})}),(0,z.jsx)(`small`,{children:o(`lark.replyModeDescription`)})]}),(0,z.jsxs)(`p`,{className:`personal-lark-cardinality`,children:[(0,z.jsx)(Kp,{size:15}),o(`lark.cardinality`)]}),fe?(0,z.jsx)(`p`,{className:`personal-notification-error`,role:`alert`,children:fe}):null,(0,z.jsxs)(`footer`,{children:[(0,z.jsx)(`button`,{className:`personal-secondary-action`,onClick:()=>b(!1),type:`button`,children:o(`lark.cancel`)}),(0,z.jsxs)(`button`,{className:`personal-primary-action`,disabled:p||!x||!ze?.reply_ready||!Re||!C||!k||Le.length===0||ue,onClick:()=>void qe(),type:`button`,children:[ue?(0,z.jsx)(hm,{className:`is-spinning`,size:15}):null,V]})]})]})}):null,ve?(0,z.jsx)(`div`,{className:`personal-lark-modal-backdrop is-setup`,role:`presentation`,children:(0,z.jsxs)(`section`,{"aria-labelledby":`new-lark-app-title`,"aria-modal":`true`,className:`personal-lark-modal personal-lark-setup-modal`,role:`dialog`,children:[(0,z.jsxs)(`header`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`small`,{children:o(`lark.reusableWorkspaceApp`)}),(0,z.jsx)(`h2`,{id:`new-lark-app-title`,children:o(`lark.newApp`)})]}),(0,z.jsx)(`button`,{"aria-label":o(`lark.closeCreate`),onClick:()=>void Ke(),type:`button`,children:(0,z.jsx)(Gm,{size:18})})]}),we?(0,z.jsxs)(`div`,{className:`personal-lark-setup-progress`,children:[(0,z.jsx)(`span`,{className:`personal-lark-setup-icon is-${we.status}`,children:we.status===`ready`?(0,z.jsx)(Kp,{size:22}):(0,z.jsx)(hm,{className:we.status===`failed`?``:`is-spinning`,size:22})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:we.status===`ready`?o(`lark.appCreated`):we.status===`failed`?o(`lark.appCreateFailed`):o(`lark.waitingFeishu`)}),(0,z.jsx)(`p`,{children:we.status===`waiting_for_feishu`?o(`lark.waitingFeishuDescription`):we.status===`starting`?o(`lark.waitingLink`):we.error})]}),we.verification_url?(0,z.jsxs)(`a`,{href:we.verification_url,rel:`noreferrer`,target:`_blank`,children:[(0,z.jsx)(im,{size:15}),o(`lark.reopenFeishu`)]}):null]}):(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`p`,{className:`personal-lark-setup-copy`,children:o(`lark.setupCopy`)}),(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:o(`lark.profileName`)}),(0,z.jsx)(`input`,{"aria-label":o(`lark.profileName`),autoComplete:`off`,onChange:e=>xe(e.target.value),placeholder:`loopx-workspace-bot`,value:be})]}),(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:o(`lark.region`)}),(0,z.jsxs)(`select`,{"aria-label":o(`lark.region`),onChange:e=>Ce(e.target.value),value:Se,children:[(0,z.jsx)(`option`,{value:`feishu`,children:`Feishu`}),(0,z.jsx)(`option`,{value:`lark`,children:`Lark`})]})]}),be&&!/^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$/.test(be)?(0,z.jsx)(`p`,{className:`personal-notification-error`,children:o(`lark.profileValidation`)}):null]}),L?(0,z.jsx)(`p`,{className:`personal-notification-error`,children:L}):null,(0,z.jsxs)(`footer`,{children:[(0,z.jsx)(`button`,{className:`personal-secondary-action`,onClick:()=>void Ke(),type:`button`,children:o(`lark.cancel`)}),we?null:(0,z.jsxs)(`button`,{className:`personal-primary-action`,disabled:Ee||!/^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$/.test(be),onClick:()=>void Ge(),type:`button`,children:[Ee?(0,z.jsx)(hm,{className:`is-spinning`,size:15}):(0,z.jsx)(im,{size:15}),o(`lark.continueFeishu`)]})]})]})}):null]})}function sb(e){return e&&typeof e==`object`&&!Array.isArray(e)?e:{}}function cb(e,t,n){let r=sb(t),i=sb(n);return Object.fromEntries(e.fields.flatMap(({key:e})=>{let t=r[e],n=i[e];return Object.hasOwn(r,e)&&t!=null?[[e,t]]:Object.hasOwn(i,e)&&n!=null?[[e,n]]:[]}))}function lb({children:e}){return e?(0,z.jsx)(`small`,{children:e}):null}function ub({copy:e,field:t,id:n,onChange:r,value:i}){let a=e[t.key]?.label??t.label,o=e[t.key]?.description??t.description,s=!r;if(t.input_kind===`boolean`)return(0,z.jsxs)(`label`,{className:`is-boolean`,htmlFor:n,children:[(0,z.jsx)(`span`,{children:a}),(0,z.jsx)(`input`,{checked:i===!0,id:n,onChange:r?e=>r(t.key,e.target.checked):void 0,readOnly:s,type:`checkbox`}),(0,z.jsx)(lb,{children:o})]});if(t.input_kind===`select`)return(0,z.jsxs)(`label`,{htmlFor:n,children:[(0,z.jsx)(`span`,{children:a}),(0,z.jsxs)(`select`,{id:n,onChange:r?e=>r(t.key,e.target.value):void 0,value:typeof i==`string`?i:``,children:[(0,z.jsx)(`option`,{value:``}),(t.options??[]).map(e=>(0,z.jsx)(`option`,{value:e,children:e},e))]}),(0,z.jsx)(lb,{children:o})]});if(t.input_kind===`string_list`)return(0,z.jsxs)(`label`,{htmlFor:n,children:[(0,z.jsx)(`span`,{children:a}),(0,z.jsx)(`textarea`,{id:n,onChange:r?e=>r(t.key,e.target.value.split(/\r?\n/u).filter(Boolean)):void 0,readOnly:s,rows:4,value:Array.isArray(i)?i.join(` -`):``}),(0,z.jsx)(lb,{children:o})]});let c=t.input_kind===`number`;return(0,z.jsxs)(`label`,{htmlFor:n,children:[(0,z.jsx)(`span`,{children:a}),(0,z.jsx)(`input`,{id:n,max:t.maximum,min:t.minimum,onChange:r?e=>r(t.key,c?Number(e.target.value):e.target.value):void 0,readOnly:s,required:t.required,type:c?`number`:`text`,value:typeof i==`number`||typeof i==`string`?i:``}),(0,z.jsx)(lb,{children:o})]})}function db({copy:e={},disabled:t=!1,editor:n,omitKeys:r=[],onChange:i,value:a}){let o=(0,R.useId)(),s=new Set(r);return(0,z.jsx)(`fieldset`,{className:`personal-capability-fields`,disabled:t,children:n.fields.filter(e=>!s.has(e.key)).map(t=>(0,z.jsx)(ub,{copy:e,field:t,id:`${o}-${t.key.replace(/[^a-z0-9_-]/gi,`-`)}`,onChange:i,value:a[t.key]},t.key))})}var fb={en:{change_quality_qualification:{displayName:`Change quality qualification`,description:`Prepares a provider-neutral review packet, allows at most one policy-authorized safe-fix pass, and can require an exact-diff receipt.`},explore_graph:{displayName:`Explore Graph`,description:`Organizes bounded exploration as a typed evidence graph so branches, findings, and synthesis remain inspectable.`},explore_harness:{displayName:`Explore Harness`,description:`Selects a capability-owned planning and research harness profile for bounded multi-step exploration.`},lark_event_inbox:{displayName:`Lark event inbox`,description:`Receives provider events through a local-private inbox binding before LoopX projects them into governed work.`,readOnlyReason:`This capability requires a local-private inbox binding. Manage it in Lark settings or through the capability CLI.`},lark_kanban_heartbeat_sync:{displayName:`Lark Kanban heartbeat sync`,description:`Synchronizes accepted LoopX work state to the configured Lark Kanban heartbeat surface.`},local_authority_shadow:{displayName:`Local authority shadow`,description:`Observes post-commit Todo and task-lease state through the shared authority contract without taking write authority.`},multi_subagent:{displayName:`Adaptive child capacity`,description:`Sets bounded child-agent capacity and the public-safe responsibility domains in which parallel work may be delegated.`},peer_task_coordination:{displayName:`Registered-peer task coordination`,description:`Routes explicitly scoped peer-owned work to one registered coordinator without granting cross-owner mutation authority.`},periodic_report:{displayName:`Periodic reports`,description:`Turns validated Goal stage progress into a frozen report and automatically delivers it through the configured Goal Channel with exact readback.`},reward_memory:{displayName:`Reward Memory experiment`,description:`Runs an opt-in, provider-bound retrieval experiment over an explicitly allowlisted memory corpus.`,readOnlyReason:`This capability requires a reviewed local-private provider binding and an explicit Agent allowlist. Configure it through the capability CLI.`}},"zh-CN":{change_quality_qualification:{displayName:`变更质量验证`,description:`生成与 Provider 无关的审阅包,最多允许一次策略授权的安全修复,并可要求精确 diff 回执。`},explore_graph:{displayName:`探索图谱`,description:`把有界探索组织为 typed 证据图,让探索分支、发现与综合结论都可检查、可追溯。`},explore_harness:{displayName:`探索 Harness`,description:`为有界的多步探索选择由能力负责的规划与研究 Harness profile。`},lark_event_inbox:{displayName:`飞书事件收件箱`,description:`通过本机私有收件箱接收 Provider 事件,再由 LoopX 将其投影为受治理的工作。`,readOnlyReason:`此能力依赖本机私有的收件箱绑定,请在飞书设置或 capability CLI 中管理。`},lark_kanban_heartbeat_sync:{displayName:`飞书看板心跳同步`,description:`把 LoopX 已接受的工作状态同步到配置好的飞书看板心跳界面。`},local_authority_shadow:{displayName:`本地 Authority 影子观测`,description:`通过共享 Authority contract 观测提交后的 Todo 与 task lease 状态,但不取得写入权。`},multi_subagent:{displayName:`自适应子 Agent 容量`,description:`限定子 Agent 容量与可公开的职责域,只有落在这些边界内的工作才能并行委派。`},peer_task_coordination:{displayName:`已注册 Peer 任务协调`,description:`把明确限定的 Peer 工作路由给一个已注册协调者,不授予跨 Owner 修改权限。`},periodic_report:{displayName:`周期报告`,description:`把经过验证的 Goal 阶段进展整理为冻结报告,并通过配置的 Goal Channel 自动发送和精确回读。`},reward_memory:{displayName:`Reward Memory 实验`,description:`在明确 allowlist 的记忆语料上运行可选、Provider 绑定的检索实验。`,readOnlyReason:`此能力依赖经过审阅的本机私有 Provider 绑定和明确的 Agent allowlist,请通过 capability CLI 配置。`}}},pb={en:{allowed_domains:{label:`Allowed responsibility domains`,description:`Enter one bounded, public-safe domain per line.`},coordinator_agent_id:{label:`Coordinator Agent`,description:`Use an already registered Agent id; leave blank to disable coordination.`},enabled:{label:`Enabled`},max_children:{label:`Maximum children`,description:`Hard upper bound for concurrently delegated child work.`},profile:{label:`Planner profile`,description:`Select one registered Explore Harness profile.`},profile_preset:{label:`Report profile`,description:`Capability-owned report profile, such as weekly-progress.`},route_ref:{label:`Goal Channel route`,description:`Public route alias only; credentials and provider identifiers stay outside this form.`},safe_fix:{label:`Allow one bounded safe-fix pass`},strict_receipt:{label:`Require an exact-diff receipt`},timezone:{label:`Timezone`,description:`Use an IANA timezone, for example Asia/Shanghai.`}},"zh-CN":{allowed_domains:{label:`允许的职责域`,description:`每行填写一个有边界、可公开的职责域。`},coordinator_agent_id:{label:`协调 Agent`,description:`填写一个已经注册的 Agent ID;留空表示关闭协调。`},enabled:{label:`启用`},max_children:{label:`最大子 Agent 数`,description:`可同时委派的子任务硬上限。`},profile:{label:`规划 Profile`,description:`选择一个已注册的 Explore Harness profile。`},profile_preset:{label:`报告 Profile`,description:`由该能力管理的报告 profile,例如 weekly-progress。`},route_ref:{label:`Goal Channel 路由`,description:`只填写公开 route alias;凭据与 Provider 标识不会进入此表单。`},safe_fix:{label:`允许一次有界安全修复`},strict_receipt:{label:`要求精确 diff 回执`},timezone:{label:`时区`,description:`使用 IANA 时区,例如 Asia/Shanghai。`}}};function mb(e,t){let n=fb[t][e.capability_id];return n?{...e,display_name:n.displayName,description:n.description,configuration_editor:{...e.configuration_editor,...n.readOnlyReason?{read_only_reason:n.readOnlyReason}:{}}}:e}function hb(e){return pb[e]}Object.freeze(Object.keys(fb.en).sort());function gb(e,t){return e.available_scopes.includes(t)&&(t!==`machine`||!!e.machine_namespace)&&e.configuration_editor.editable&&e.configuration_editor.writable_scopes.includes(t)}function _b({values:e,t}){return(0,z.jsxs)(`details`,{className:`personal-capability-raw-values`,children:[(0,z.jsx)(`summary`,{children:t(`capabilities.rawJson`)}),(0,z.jsx)(`div`,{className:`personal-capability-value-grid`,children:e.map(({label:e,value:t})=>(0,z.jsxs)(`section`,{children:[(0,z.jsx)(`strong`,{children:e}),(0,z.jsx)(`pre`,{children:t?JSON.stringify(t,null,2):`—`})]},e))})]})}function vb({source:e,t}){return e?(0,z.jsxs)(`p`,{className:`personal-capability-effective-source`,children:[(0,z.jsx)(Im,{"aria-hidden":!0,size:15}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:t(`capabilities.effectiveSource`)}),t(`capabilities.source.${e}`)]})]}):null}function yb({available:e,description:t,t:n}){return e?null:(0,z.jsxs)(`section`,{className:`personal-capability-editor-status is-read-only`,children:[(0,z.jsx)(Um,{"aria-hidden":!0,size:18}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:n(`capabilities.readOnly`)}),(0,z.jsx)(`p`,{children:t})]})]})}function bb(e){return e.availability?.includes(`experimental`)?4:e.capability_id===`multi_subagent`?3:e.configuration_editor.writable_scopes.length===0||e.availability===`supported_explicit_opt_in`?2:e.availability===`supported_explicit_override`?0:1}function xb(e,t){return[...e].sort((e,n)=>{let r=bb(e)-bb(n);if(r!==0)return r;let i=mb(e,t),a=mb(n,t);return i.display_name.localeCompare(a.display_name,t)||e.capability_id.localeCompare(n.capability_id)})}function Sb({capabilities:e,locale:t,onSelect:n,scope:r,selectedCapabilityId:i,t:a}){return(0,z.jsx)(`nav`,{"aria-label":a(r===`goal`?`capabilities.catalog`:`machine.capabilityCatalog`),className:`personal-capability-list`,children:xb(e,t).map(e=>{let o=mb(e,t);return(0,z.jsxs)(`button`,{"aria-current":i===o.capability_id?`page`:void 0,onClick:()=>n(o.capability_id),type:`button`,children:[(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:o.display_name}),(0,z.jsx)(`small`,{children:o.capability_id})]}),(0,z.jsx)(`em`,{children:a(o.available_scopes.includes(r)?r===`goal`?`capabilities.goalScope`:`capabilities.machineScope`:r===`machine`?`capabilities.goalScope`:`capabilities.machineScope`)})]},o.capability_id)})})}function Cb({capability:e,locale:t}){let n=mb(e,t);return(0,z.jsxs)(`header`,{children:[(0,z.jsx)(`span`,{className:`personal-settings-icon`,children:(0,z.jsx)(Lm,{"aria-hidden":!0,size:18})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`small`,{children:n.capability_id}),(0,z.jsx)(`h2`,{children:n.display_name}),(0,z.jsx)(`p`,{children:n.description})]})]})}function wb({goalId:e,onApplied:t,selected:n,t:r}){let[i,a]=(0,R.useState)({busy:null,draft:{},partialWrite:null,preview:null}),[o,s]=(0,R.useState)(null);(0,R.useEffect)(()=>{a({busy:null,draft:cb(n?.configuration_editor??{fields:[]},n?.current??n?.effective_configuration?.configuration??n?.default,n?.default),partialWrite:null,preview:null}),s(null)},[n]);async function c(t){if(!(!n||i.busy)){a(e=>({...e,busy:`preview`,partialWrite:null})),s(null);try{let r=await _g(e,n.capability_id,t);a(e=>({...e,preview:r}))}catch(e){s(e instanceof Error?e.message:r(`capabilities.previewFailed`))}finally{a(e=>({...e,busy:null}))}}}async function l(){if(!(!n||!i.preview||i.busy)){a(e=>({...e,busy:`apply`})),s(null);try{let r=cb(n.configuration_editor,i.draft,n.default),o=await vg(e,n.capability_id,i.preview.action===`delete`?null:r,i.preview.plan_revision);a(e=>({...e,partialWrite:o.status===`partial_write`?o:null,preview:null})),o.status!==`partial_write`&&t()}catch(e){a(e=>({...e,preview:null})),s(e instanceof Error?e.message:r(`capabilities.applyFailed`))}finally{a(e=>({...e,busy:null}))}}}function u(e,t){a(n=>({...n,draft:{...n.draft,[e]:t},preview:null})),s(null)}return{apply:l,changeDraft:u,error:o,mutation:i,preview:c}}function Tb({mutationError:e,onApplied:t,partialWrite:n,preview:r}){let{t:i}=Ji();return(0,z.jsxs)(z.Fragment,{children:[e?(0,z.jsx)(`p`,{className:`personal-machine-error`,role:`alert`,children:e}):null,n?(0,z.jsxs)(`section`,{"aria-live":`polite`,className:`personal-capability-recovery`,children:[(0,z.jsx)(Um,{"aria-hidden":!0,size:18}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:i(`capabilities.partialWrite`)}),(0,z.jsx)(`p`,{children:i(`capabilities.partialWriteDescription`)}),(0,z.jsx)(`small`,{children:n.recommended_action})]}),(0,z.jsxs)(`button`,{onClick:t,type:`button`,children:[(0,z.jsx)(Om,{"aria-hidden":!0,size:15}),i(`capabilities.refreshSource`)]})]}):null,r?(0,z.jsxs)(`section`,{className:`personal-capability-preview`,"aria-label":i(`capabilities.preview`),children:[(0,z.jsx)(`strong`,{children:i(`capabilities.preview`)}),(0,z.jsx)(`span`,{children:i(`machine.action.${r.action}`)}),(0,z.jsx)(`small`,{children:i(`capabilities.previewLocked`)})]}):null]})}function Eb({catalog:e,goalId:t,onApplied:n}){let{locale:r,t:i}=Ji(),[a,o]=(0,R.useState)(e.capabilities[0]?.capability_id??``),s=(0,R.useMemo)(()=>e.capabilities.find(e=>e.capability_id===a)??e.capabilities[0],[e.capabilities,a]),c=(0,R.useMemo)(()=>s?mb(s,r):void 0,[r,s]),{apply:l,changeDraft:u,error:d,mutation:f,preview:p}=wb({goalId:t,onApplied:n,selected:c,t:i}),{busy:m,draft:h,partialWrite:g,preview:_}=f;if(!s||!c)return(0,z.jsx)(`p`,{className:`personal-capability-empty`,children:i(`capabilities.empty`)});let v=c.available_scopes.includes(`goal`),y=gb(c,`goal`),b=c.configuration_editor.read_only_reason??i(v?`capabilities.previewOnly`:`capabilities.machineOnly`);async function x(){if(!c||!y||m)return;let e=cb(c.configuration_editor,h,c.default);await p(e)}async function S(){!y||m||await p(null)}return(0,z.jsxs)(`div`,{className:`personal-capability-layout`,children:[(0,z.jsx)(Sb,{capabilities:e.capabilities,locale:r,onSelect:o,scope:`goal`,selectedCapabilityId:c.capability_id,t:i}),(0,z.jsxs)(`article`,{className:`personal-capability-detail`,children:[(0,z.jsx)(Cb,{capability:s,locale:r}),(0,z.jsx)(vb,{source:c.effective_configuration?.source,t:i}),(0,z.jsx)(yb,{available:y,t:i,description:b}),y?(0,z.jsxs)(`section`,{className:`personal-capability-field-summary`,children:[(0,z.jsx)(`strong`,{children:i(`capabilities.fields`)}),(0,z.jsx)(db,{disabled:!!m,copy:hb(r),editor:c.configuration_editor,onChange:u,value:h})]}):null,(0,z.jsx)(Tb,{mutationError:d,onApplied:n,partialWrite:g,preview:_}),y?(0,z.jsxs)(`footer`,{className:`personal-capability-actions`,children:[c.current&&c.available_scopes.includes(`machine`)?(0,z.jsx)(`button`,{disabled:!!m,onClick:()=>void S(),type:`button`,children:i(`capabilities.restoreInheritance`)}):null,(0,z.jsx)(`button`,{disabled:!!m,onClick:()=>void x(),type:`button`,children:i(m===`preview`?`common.loading`:`capabilities.previewChanges`)}),(0,z.jsx)(`button`,{className:`is-primary`,disabled:!!m||!_,onClick:()=>void l(),type:`button`,children:i(m===`apply`?`common.loading`:`capabilities.applyPreview`)})]}):null,(0,z.jsx)(_b,{values:[{label:i(`capabilities.goalValue`),value:c.current},{label:i(c.machine_current?`capabilities.machineValue`:`capabilities.defaultValue`),value:c.machine_current??c.default}],t:i},s.capability_id)]})]})}function Db({goalId:e}){let{t}=Ji(),[n,r]=(0,R.useState)(null),[i,a]=(0,R.useState)(null),[o,s]=(0,R.useState)(!1);function c(){e&&(s(!0),a(null),gg(e).then(r).catch(e=>a(e instanceof Error?e.message:t(`capabilities.loadFailed`))).finally(()=>s(!1)))}return(0,R.useEffect)(c,[e]),e?o&&!n?(0,z.jsxs)(`p`,{"aria-live":`polite`,className:`personal-capability-empty`,children:[(0,z.jsx)(hm,{className:`personal-spin`,size:18}),t(`capabilities.loading`)]}):i?(0,z.jsxs)(`section`,{className:`personal-capability-error`,role:`alert`,children:[(0,z.jsx)(Um,{"aria-hidden":!0,size:18}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:t(`capabilities.loadFailed`)}),(0,z.jsx)(`small`,{children:i})]}),(0,z.jsxs)(`button`,{onClick:c,type:`button`,children:[(0,z.jsx)(Om,{"aria-hidden":!0,size:15}),t(`capabilities.retry`)]})]}):n?(0,z.jsxs)(`section`,{className:`personal-capability-settings`,"data-revision":n.revision,children:[(0,z.jsxs)(`div`,{className:`personal-capability-scope-note`,children:[(0,z.jsx)(Im,{"aria-hidden":!0,size:17}),(0,z.jsxs)(`p`,{children:[(0,z.jsx)(`strong`,{children:t(`capabilities.atomicOverride`)}),t(`capabilities.atomicOverrideDescription`)]})]}),(0,z.jsx)(Eb,{catalog:n.capability_catalog,goalId:e,onApplied:c})]}):null:(0,z.jsx)(`p`,{className:`personal-capability-empty`,children:t(`capabilities.chooseGoal`)})}function Ob(e){return e&&typeof e==`object`&&!Array.isArray(e)?e:{}}function kb(e,t){let n=t?.machine_namespace;return n?e?.machine_configuration?.namespaces[n]:void 0}function Ab(e,t,n){return{...Ob(e.default),...Ob(t),...n}}function jb(e,t){for(let n of e.configuration_editor.fields){let e=t[n.key];if(n.required&&(e==null||e===``))return!1}return e.capability_id===`periodic_report`&&t.enabled===!0?!!(String(t.profile_preset??``).trim()&&String(t.route_ref??``).trim()&&String(t.timezone??``).trim()):!0}function Mb(e){try{let t=JSON.parse(e);return t&&typeof t==`object`&&!Array.isArray(t)?t:null}catch{return null}}function Nb(e){return e?e===`absent`?e:e.replace(/^sha256:/,``).slice(0,12):`—`}function Pb(){let{locale:e,t}=Ji(),[n,r]=(0,R.useState)(null),[i,a]=(0,R.useState)(``),[o,s]=(0,R.useState)({}),[c,l]=(0,R.useState)(`{}`),[u,d]=(0,R.useState)(`guided`),[f,p]=(0,R.useState)(null),[m,h]=(0,R.useState)(`upsert`),[g,_]=(0,R.useState)(null),[v,y]=(0,R.useState)(null),[b,x]=(0,R.useState)(`load`),[S,C]=(0,R.useState)(null),[w,T]=(0,R.useState)(null),E=n?.capability_catalog.capabilities??[],D=E.find(e=>e.capability_id===i)??E[0],O=D?mb(D,e):void 0,k=kb(n,O),ee=!!(O?.machine_namespace&&k),A=!!(O&&gb(O,`machine`)),j=(0,R.useMemo)(()=>Mb(c),[c]),te=O?u===`json`?j:Ab(O,k,o):null,ne=!!(O&&(u===`json`?j:jb(O,te??{})));async function re(){r(await hg())}(0,R.useEffect)(()=>{let e=!0;return hg().then(t=>{e&&(r(t),a(t.capability_catalog.capabilities.find(e=>e.available_scopes.includes(`machine`))?.capability_id??``))}).catch(n=>{e&&C(n instanceof Error?n.message:t(`machine.loadError`))}).finally(()=>{e&&x(null)}),()=>{e=!1}},[t]),(0,R.useEffect)(()=>{if(!O)return;let e=kb(n,O),t=cb(O.configuration_editor,e??O.default,O.default),r=Ab(O,e,t);s(t),l(JSON.stringify(r,null,2)),d(A?`guided`:`json`),p(null),h(`upsert`),y(null)},[n,i,e]);function M(e,t){s(n=>({...n,[e]:t})),p(null),h(`upsert`),C(null),T(null)}function N(e){if(O){if(e===`json`)l(JSON.stringify(Ab(O,k,o),null,2));else if(j)s(cb(O.configuration_editor,j,O.default));else{C(t(`machine.jsonInvalid`));return}d(e),p(null),h(`upsert`),C(null)}}async function ie(){if(!(!A||!O?.machine_namespace||!te||!ne||b)){x(`preview`),C(null),T(null);try{h(`upsert`),p(await yg(O.machine_namespace,te))}catch(e){C(e instanceof Error?e.message:t(`machine.previewError`))}finally{x(null)}}}async function ae(){if(!(!A||!O?.machine_namespace||!ee||b)){x(`preview`),C(null),T(null);try{h(`remove`),p(await xg(O.machine_namespace))}catch(e){C(e instanceof Error?e.message:t(`machine.previewError`))}finally{x(null)}}}async function oe(){if(!A||!O?.machine_namespace||!f||b||m===`upsert`&&!te)return;x(`apply`),C(null);let e=m;try{let n=e===`remove`?await Sg(O.machine_namespace,f.plan_revision):await bg(O.machine_namespace,te,f.plan_revision);_(n),p(null),h(`upsert`),y(null),await re(),T(n.status===`applied`?t(e===`remove`?`machine.removed`:`machine.applied`):t(`machine.unchanged`))}catch(e){p(null),h(`upsert`),C(e instanceof Error?e.message:t(`machine.applyError`))}finally{x(null)}}async function P(){if(!(!g?.transaction_id||b)){x(`rollback-preview`),C(null);try{y(await Cg(g.transaction_id))}catch(e){C(e instanceof Error?e.message:t(`machine.rollbackError`))}finally{x(null)}}}async function F(){if(!(!g?.transaction_id||!v||b)){x(`rollback`),C(null);try{await wg(g.transaction_id,v.plan_revision),_(null),y(null),p(null),await re(),T(t(`machine.rolledBack`))}catch(e){y(null),C(e instanceof Error?e.message:t(`machine.rollbackError`))}finally{x(null)}}}return b===`load`?(0,z.jsx)(`div`,{className:`personal-machine-loading`,role:`status`,children:t(`common.loading`)}):O?(0,z.jsxs)(`section`,{className:`personal-capability-settings`,"data-revision":n?.revision,children:[(0,z.jsxs)(`div`,{className:`personal-capability-scope-note`,children:[(0,z.jsx)(Im,{"aria-hidden":!0,size:17}),(0,z.jsxs)(`p`,{children:[(0,z.jsx)(`strong`,{children:t(`machine.liveDefault`)}),t(`machine.liveDefaultDescription`)]})]}),(0,z.jsxs)(`div`,{className:`personal-capability-layout`,children:[(0,z.jsx)(Sb,{capabilities:E,locale:e,onSelect:a,scope:`machine`,selectedCapabilityId:O.capability_id,t}),(0,z.jsxs)(`article`,{className:`personal-capability-detail`,children:[(0,z.jsx)(Cb,{capability:D,locale:e}),O.available_scopes.includes(`machine`)?(0,z.jsx)(vb,{source:ee?`machine_default`:`capability_default`,t}):null,(0,z.jsx)(yb,{available:A,t,description:O.available_scopes.includes(`machine`)?t(`machine.editorUnavailableDescription`):t(`machine.goalOnly`)}),O.capability_id===`periodic_report`?(0,z.jsxs)(`section`,{className:`personal-capability-behavior-note`,children:[(0,z.jsx)(Im,{"aria-hidden":!0,size:18}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:t(`machine.periodicReportActivation`)}),(0,z.jsx)(`p`,{children:t(`machine.periodicReportActivationDescription`)})]})]}):null,A?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`div`,{className:`personal-capability-editor-mode`,children:[(0,z.jsx)(`span`,{children:t(`machine.editorMode`)}),(0,z.jsxs)(`div`,{role:`group`,"aria-label":t(`machine.editorMode`),children:[(0,z.jsx)(`button`,{"aria-pressed":u===`guided`,disabled:!A,onClick:()=>N(`guided`),type:`button`,children:t(`machine.visualEditor`)}),(0,z.jsxs)(`button`,{"aria-pressed":u===`json`,onClick:()=>N(`json`),type:`button`,children:[(0,z.jsx)($p,{"aria-hidden":!0,size:14}),t(`machine.jsonEditor`)]})]})]}),u===`guided`?(0,z.jsxs)(`section`,{className:`personal-capability-field-summary`,children:[(0,z.jsx)(`strong`,{children:t(`capabilities.fields`)}),(0,z.jsx)(db,{copy:hb(e),disabled:!!b,editor:O.configuration_editor,onChange:M,value:o}),ne?null:(0,z.jsx)(`p`,{className:`personal-machine-validation`,role:`alert`,children:t(`machine.requiredFields`)})]}):(0,z.jsxs)(`label`,{className:`personal-capability-json-editor`,htmlFor:`machine-configuration-json`,children:[(0,z.jsx)(`span`,{children:t(`machine.jsonConfiguration`)}),(0,z.jsx)(`textarea`,{"aria-describedby":`machine-configuration-json-help`,disabled:!!b,id:`machine-configuration-json`,onChange:e=>{l(e.target.value),p(null),C(null)},rows:12,spellCheck:!1,value:c}),(0,z.jsx)(`small`,{id:`machine-configuration-json-help`,children:t(`machine.jsonConfigurationHelp`)}),j?null:(0,z.jsx)(`span`,{className:`personal-machine-validation`,role:`alert`,children:t(`machine.jsonInvalid`)})]})]}):null,S?(0,z.jsx)(`p`,{className:`personal-machine-error`,role:`alert`,children:S}):null,w?(0,z.jsxs)(`p`,{className:`personal-machine-notice`,role:`status`,"aria-live":`polite`,children:[(0,z.jsx)(Kp,{"aria-hidden":!0,size:16}),w]}):null,f?(0,z.jsxs)(`section`,{"aria-label":t(`machine.preview`),className:`personal-machine-preview`,children:[(0,z.jsxs)(`header`,{children:[(0,z.jsx)(`strong`,{children:t(`machine.preview`)}),(0,z.jsx)(`span`,{children:t(`machine.action.${f.action}`)})]}),(0,z.jsxs)(`dl`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:t(`machine.currentRevision`)}),(0,z.jsx)(`dd`,{title:f.current_revision,children:Nb(f.current_revision)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:t(`machine.desiredRevision`)}),(0,z.jsx)(`dd`,{title:f.desired_revision,children:Nb(f.desired_revision)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:t(`machine.changedNamespaces`)}),(0,z.jsx)(`dd`,{children:f.changed_namespaces.join(`, `)||t(`common.none`)})]})]}),(0,z.jsx)(`p`,{children:t(`machine.previewLocked`)})]}):null,g?.rollback_available&&g.transaction_id?(0,z.jsxs)(`section`,{className:`personal-machine-rollback`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:t(`machine.rollbackAvailable`)}),(0,z.jsx)(`p`,{children:t(v?`machine.rollbackPreviewDescription`:`machine.rollbackDescription`)})]}),(0,z.jsxs)(`button`,{className:`personal-secondary-action`,disabled:!!b||!!(v&&!v.rollback_allowed),onClick:()=>void(v?F():P()),type:`button`,children:[(0,z.jsx)(km,{"aria-hidden":!0,size:15}),t(b===`rollback`||b===`rollback-preview`?`common.loading`:v?`machine.confirmRollback`:`machine.previewRollback`)]})]}):null,A?(0,z.jsxs)(`footer`,{className:`personal-capability-actions`,children:[ee?(0,z.jsxs)(`button`,{className:`is-danger`,disabled:!!b,onClick:()=>void ae(),type:`button`,children:[(0,z.jsx)(Hm,{"aria-hidden":!0,size:15}),t(`machine.previewRemoval`)]}):null,(0,z.jsx)(`button`,{disabled:!!b||!ne,onClick:()=>void ie(),type:`button`,children:t(b===`preview`?`common.loading`:`machine.previewChanges`)}),(0,z.jsx)(`button`,{className:`is-primary`,disabled:!!b||!f,onClick:()=>void oe(),type:`button`,children:t(b===`apply`?`common.loading`:`machine.applyPreview`)})]}):null,O.available_scopes.includes(`machine`)?(0,z.jsx)(_b,{values:[{label:t(`machine.currentValue`),value:k},{label:t(`capabilities.defaultValue`),value:O.default}],t},O.capability_id):null]})]})]}):(0,z.jsx)(`p`,{className:`personal-capability-empty`,children:t(`machine.capabilityEmpty`)})}var Fb={appearance:Sm,capabilities:Lm,language:fm,lark:Fm,machine:Nm};function Ib({focusGoalConnection:e=!1,goals:t,initialGoalId:n,initialTab:r=`lark`,onChanged:i,onClose:a,onThemeChange:o,theme:s}){let{locale:c,setLocale:l,t:u}=Ji(),[d,f]=(0,R.useState)(r),p=[...n?[{description:u(`settings.capabilitiesTabDescription`),key:`capabilities`,label:u(`capabilities.title`)}]:[],{description:u(`settings.machineTabDescription`),key:`machine`,label:u(`machine.title`)},{description:u(`settings.larkTabDescription`),key:`lark`,label:`Lark`},{description:u(`settings.appearanceTabDescription`),key:`appearance`,label:u(`settings.appearance`)},{description:u(`settings.languageTabDescription`),key:`language`,label:u(`settings.language`)}],m=[{description:u(`settings.languageEnglishDescription`),label:u(`settings.languageEnglish`),value:`en`},{description:u(`settings.languageSimplifiedChineseDescription`),label:u(`settings.languageSimplifiedChinese`),value:`zh-CN`}],h={appearance:{description:u(`settings.appearanceDescription`),eyebrow:u(`settings.workspaceDisplay`),title:u(`settings.appearance`)},capabilities:{description:u(`capabilities.description`),eyebrow:u(`capabilities.goalPolicy`),title:u(`capabilities.title`)},language:{description:u(`settings.languageDescription`),eyebrow:u(`settings.workspaceDisplay`),title:u(`settings.language`)},lark:{description:u(`lark.description`),eyebrow:u(`settings.goalConnections`),title:`Lark`},machine:{description:u(`machine.description`),eyebrow:u(`machine.machinePolicy`),title:u(`machine.title`)}}[d];return(0,z.jsxs)(`section`,{"aria-label":u(`settings.title`),className:`personal-settings-page`,"data-pw-theme":s,children:[(0,z.jsxs)(`aside`,{className:`personal-settings-sidebar`,children:[(0,z.jsxs)(`button`,{className:`personal-settings-back`,onClick:a,type:`button`,children:[(0,z.jsx)(Lp,{size:17}),(0,z.jsx)(`span`,{children:u(`settings.back`)})]}),(0,z.jsxs)(`div`,{className:`personal-settings-title`,children:[(0,z.jsx)(`small`,{children:u(`settings.eyebrow`)}),(0,z.jsx)(`strong`,{children:u(`settings.title`)})]}),(0,z.jsx)(`nav`,{"aria-label":u(`settings.categories`),className:`personal-settings-tabs`,children:p.map(e=>{let t=Fb[e.key];return(0,z.jsxs)(`button`,{"aria-current":d===e.key?`page`:void 0,onClick:()=>f(e.key),type:`button`,children:[(0,z.jsx)(t,{size:17}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:e.label}),(0,z.jsx)(`small`,{children:e.description})]})]},e.key)})})]}),(0,z.jsxs)(`main`,{className:`personal-settings-body`,children:[(0,z.jsx)(`header`,{className:`personal-settings-header`,children:(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`small`,{children:h.eyebrow}),(0,z.jsx)(`h1`,{children:h.title}),(0,z.jsx)(`p`,{children:h.description})]})}),d===`lark`?(0,z.jsx)(ob,{embedded:!0,focusGoalConnection:e,goals:t,initialGoalId:n,onChanged:i,onClose:a}):null,d===`machine`?(0,z.jsx)(Pb,{}):null,d===`capabilities`?(0,z.jsx)(Db,{goalId:n}):null,d===`appearance`?(0,z.jsxs)(`section`,{className:`personal-detail-card personal-appearance-settings`,children:[(0,z.jsx)(`small`,{children:u(`settings.workspaceDisplay`)}),(0,z.jsx)(`h3`,{children:u(`settings.appearance`)}),(0,z.jsx)(`p`,{children:u(`settings.themeDescription`)}),(0,z.jsxs)(`div`,{className:`personal-settings-choice-group`,role:`radiogroup`,"aria-label":u(`settings.workspaceTheme`),children:[(0,z.jsxs)(`button`,{"aria-checked":s===`loopx`,onClick:()=>o(`loopx`),role:`radio`,type:`button`,children:[(0,z.jsx)(`span`,{className:`personal-settings-theme-swatch is-loopx`}),(0,z.jsx)(`strong`,{children:u(`settings.themeLoopx`)}),(0,z.jsx)(`small`,{children:u(`settings.themeLoopxDescription`)})]}),(0,z.jsxs)(`button`,{"aria-checked":s===`paper`,onClick:()=>o(`paper`),role:`radio`,type:`button`,children:[(0,z.jsx)(`span`,{className:`personal-settings-theme-swatch is-paper`}),(0,z.jsx)(`strong`,{children:u(`settings.themeDefault`)}),(0,z.jsx)(`small`,{children:u(`settings.themeDefaultDescription`)})]}),(0,z.jsxs)(`button`,{"aria-checked":s===`brutal`,onClick:()=>o(`brutal`),role:`radio`,type:`button`,children:[(0,z.jsx)(`span`,{className:`personal-settings-theme-swatch is-brutal`}),(0,z.jsx)(`strong`,{children:u(`settings.themeHighContrast`)}),(0,z.jsx)(`small`,{children:u(`settings.themeHighContrastDescription`)})]})]})]}):null,d===`language`?(0,z.jsxs)(`section`,{className:`personal-settings-card`,children:[(0,z.jsxs)(`header`,{children:[(0,z.jsx)(`span`,{className:`personal-settings-icon`,children:(0,z.jsx)(fm,{size:18})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`h2`,{children:u(`settings.language`)}),(0,z.jsx)(`p`,{children:u(`settings.languageDescription`)})]})]}),(0,z.jsx)(`div`,{"aria-label":u(`settings.language`),className:`personal-language-options`,role:`radiogroup`,children:m.map(e=>(0,z.jsxs)(`button`,{"aria-checked":c===e.value,className:c===e.value?`is-selected`:``,onClick:()=>l(e.value),role:`radio`,type:`button`,children:[(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:e.label}),(0,z.jsx)(`small`,{children:e.description})]}),c===e.value?(0,z.jsx)(Kp,{"aria-hidden":!0,size:17}):null]},e.value))}),(0,z.jsx)(`footer`,{children:u(`settings.languageStoredLocally`)})]}):null]})]})}var Lb=`loopx-pw-theme`,Rb=`loopx`;function zb(){try{let e=window.localStorage.getItem(Lb);return e===`loopx`||e===`paper`||e===`brutal`?e:Rb}catch{return Rb}}function Bb(e){try{window.localStorage.setItem(Lb,e)}catch{}}function Vb({drawer:e,drawerMode:t=`panel`,drawerOpen:n,main:r,mobileSidebarOpen:i=!1,onCloseMobileSidebar:a,sidebar:o,theme:s=`loopx`}){let{t:c}=Ji(),l=(0,R.useRef)(null),u=(0,R.useRef)(null);return(0,R.useEffect)(()=>{if(!i)return;u.current=document.activeElement instanceof HTMLElement?document.activeElement:null;let e=l.current?.querySelectorAll(`button:not([disabled]), a[href], select:not([disabled]), textarea:not([disabled]), input:not([disabled]), [tabindex]:not([tabindex="-1"])`);e?.[0]?.focus();function t(t){if(t.key!==`Tab`||!e?.length)return;let n=e[0],r=e[e.length-1];t.shiftKey&&document.activeElement===n?(t.preventDefault(),r.focus()):!t.shiftKey&&document.activeElement===r&&(t.preventDefault(),n.focus())}return document.addEventListener(`keydown`,t),()=>{document.removeEventListener(`keydown`,t),u.current?.focus(),u.current=null}},[i]),(0,z.jsxs)(`section`,{className:`personal-workspace-shell${n?` has-drawer`:``}${n&&t.startsWith(`inspector`)?` has-task-inspector`:``}${t===`inspector-full`?` is-task-inspector-full`:``}${i?` mobile-sidebar-open`:``}`,"data-pw-theme":s,children:[i?(0,z.jsx)(`button`,{"aria-hidden":!0,className:`personal-sidebar-backdrop`,onClick:a,tabIndex:-1,type:`button`}):null,(0,z.jsx)(`aside`,{"aria-label":i?c(`header.goalNavigation`):void 0,"aria-modal":i?!0:void 0,className:`personal-workspace-sidebar`,"data-workspace-sidebar":!0,ref:l,role:i?`dialog`:void 0,children:(0,z.jsxs)(`div`,{className:`personal-workspace-sidebar-inner`,children:[i?(0,z.jsxs)(`button`,{className:`personal-sr-only`,onClick:a,type:`button`,children:[c(`common.close`),` `,c(`header.goalNavigation`)]}):null,o]})}),(0,z.jsx)(`main`,{"aria-hidden":i||void 0,className:`personal-workspace-main`,inert:i||void 0,children:r}),n?(0,z.jsx)(`aside`,{className:`personal-workspace-drawer`,"data-context-drawer":!0,"data-drawer-mode":t,children:e}):null]})}function Hb(e){let t=e.match(/(?:下一步|建议|行动项|待办)[::\s]*([^\n]+)/u),n=t?t[1]:e;n=n.replace(/```[\s\S]*?```/g,``).replace(/`([^`]+)`/g,`$1`).replace(/\[([^\]]+)\]\([^)]+\)/g,`$1`).replace(/[#*~_>]/g,``).replace(/^[-*•\d+.\s]+/u,``).replace(/^(好的|没问题|收到|建议如下|任务如下|分析如下|结论[::])[\s,,::]*/u,``);let r=(n.split(/\r?\n/).map(e=>e.trim()).filter(Boolean)[0]||n).replace(/\s+/gu,` `).trim();return Array.from(r).slice(0,120).join(``)}function Ub(e){let t=new Map;return e.forEach(e=>{let n=e.fields.find(e=>e.key===`todo_id`)?.value??``,r=[e.actionKind,e.goalId??``,n,e.title].join(`:`);t.set(r,e)}),[...t.values()]}function Wb(e,t,n){if(!e)return n(`home.noFirstActivity`);let r=new Date(e);if(Number.isNaN(r.getTime()))return e;let i=new Date,a=new Intl.DateTimeFormat(t,{hour:`2-digit`,minute:`2-digit`,hour12:!1}).format(r);return r.toDateString()===i.toDateString()?n(`home.todayAt`,{time:a}):new Intl.DateTimeFormat(t,{month:`numeric`,day:`numeric`,hour:`2-digit`,minute:`2-digit`,hour12:!1}).format(r)}function Gb({goals:e,onSelectGoal:t,onRetry:n,systemHealth:r}){let{locale:i,t:a}=Ji(),o=e.filter(e=>e.activationState===`active`),s=o.filter(e=>e.loadState===`error`).length,c=[{description:a(`home.lane.needsYouDescription`),key:`needs_you`,label:a(`home.lane.needsYou`)},{description:a(`home.lane.runningDescription`),key:`running`,label:a(`home.lane.running`)},{description:a(`home.lane.observingDescription`),key:`observing`,label:a(`home.lane.observing`)},{description:a(`home.lane.scheduledDescription`),key:`scheduled`,label:a(`home.lane.scheduled`)}],l=Object.fromEntries(c.map(e=>[e.key,[]])),u=[],d=[];e.filter(e=>!e.loadState).forEach(e=>{let t=Qv(e);t===`history`?u.push(e):t===`stopped`?d.push(e):l[t].push(e)});let f=e=>(0,z.jsxs)(`button`,{className:`personal-home-goal-card`,"data-goal-state":e.loadState??e.state,"data-load-error":e.loadError,onClick:()=>t(e.goalId),type:`button`,children:[(0,z.jsxs)(`span`,{className:`personal-home-goal-meta`,children:[(0,z.jsx)(`i`,{}),e.agentLaneCount&&e.agentLaneCount>1?a(`header.workAgentCount`,{count:e.agentLaneCount}):e.agentLabel??e.agentId]}),(0,z.jsx)(`strong`,{children:e.title}),(0,z.jsx)(`p`,{children:e.loadError?a(`startup.error.${e.loadError}`):e.needsYou??e.nextSentence}),(0,z.jsxs)(`footer`,{children:[(0,z.jsx)(`span`,{children:e.loadState?a(e.loadState===`error`?`startup.goalError`:`startup.goalLoading`):Yi(e.state,i)}),(0,z.jsx)(`small`,{title:e.latestActivity,children:e.loadState?``:e.latestActivity?Wb(e.latestActivity,i,a):e.agentTodos.length?a(`home.taskCount`,{count:e.agentTodos.length}):a(`home.noActivity`)})]})]},e.goalId);return(0,z.jsxs)(`section`,{"aria-label":a(`home.workspace`),className:`personal-home-board`,children:[r&&(!r.ok||r.issues.length>0||r.freshnessWarning)?(0,z.jsxs)(`div`,{className:`personal-system-health-banner`,role:`alert`,children:[(0,z.jsxs)(`div`,{className:`personal-system-health-header`,children:[(0,z.jsx)(Xp,{size:15}),(0,z.jsx)(`strong`,{children:a(`home.systemHealth`,{summary:r.summary})}),r.freshnessWarning?(0,z.jsxs)(`small`,{children:[`(`,r.freshnessWarning,`)`]}):null]}),r.issues.length>0?(0,z.jsx)(`ul`,{className:`personal-system-health-issues`,children:r.issues.map((e,t)=>(0,z.jsx)(`li`,{children:e},t))}):null]}):null,o.some(e=>e.loadState)?(0,z.jsxs)(`section`,{className:`personal-home-lane`,"aria-live":`polite`,children:[(0,z.jsx)(`header`,{children:a(`startup.progress`,{loaded:o.filter(e=>!e.loadState).length,total:o.length})}),s?(0,z.jsxs)(`div`,{className:`personal-stopped-goal-error`,role:`status`,children:[(0,z.jsx)(`span`,{children:a(`startup.failedCount`,{count:s})}),(0,z.jsx)(`button`,{className:`min-h-11 rounded-md border px-3 py-2 text-sm`,onClick:n,type:`button`,children:a(`startup.retryFailed`)})]}):null,o.filter(e=>e.loadState).map(f)]}):null,(0,z.jsx)(`div`,{className:`personal-home-lanes`,children:c.map(e=>(0,z.jsxs)(`section`,{className:`personal-home-lane is-${e.key}`,"data-testid":`personal-home-lane-${e.key}`,children:[(0,z.jsxs)(`header`,{children:[(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`i`,{}),e.label]}),(0,z.jsx)(`b`,{children:l[e.key].length})]}),(0,z.jsx)(`p`,{children:e.description}),(0,z.jsx)(`div`,{className:`personal-home-lane-list`,children:l[e.key].length?l[e.key].map(f):(0,z.jsx)(`span`,{className:`personal-home-empty`,children:a(`home.empty`)})})]},e.key))}),(0,z.jsxs)(`details`,{className:`personal-home-history`,children:[(0,z.jsxs)(`summary`,{children:[(0,z.jsx)(`span`,{children:a(`home.history`)}),(0,z.jsx)(`b`,{children:u.length}),(0,z.jsx)(`small`,{children:a(`home.completedGoals`)})]}),(0,z.jsx)(`div`,{children:u.length?u.map(f):(0,z.jsx)(`span`,{className:`personal-home-empty`,children:a(`home.noCompletedGoals`)})})]}),d.length?(0,z.jsxs)(`details`,{className:`personal-home-history is-stopped`,children:[(0,z.jsxs)(`summary`,{children:[(0,z.jsx)(`span`,{children:a(`home.stopped`)}),(0,z.jsx)(`b`,{children:d.length}),(0,z.jsx)(`small`,{children:a(`home.preservedState`)})]}),(0,z.jsx)(`div`,{children:d.map(f)})]}):null]})}function Kb({items:e,onSelect:t,reportState:n}){let{locale:r,t:i}=Ji();return(0,z.jsxs)(`section`,{className:`personal-object-list personal-files-list`,"data-testid":`personal-goal-outputs`,children:[(0,z.jsxs)(`header`,{children:[(0,z.jsx)(`strong`,{children:i(`files.title`)}),(0,z.jsx)(`span`,{children:e.length})]}),n?.loading?(0,z.jsxs)(`p`,{className:`personal-object-list-state`,role:`status`,children:[(0,z.jsx)(Om,{className:`is-spinning`,size:14}),i(`files.loadingReports`)]}):null,n?.error?(0,z.jsxs)(`p`,{className:`personal-object-list-state is-error`,role:`alert`,children:[(0,z.jsx)(Xp,{size:14}),i(`files.reportLoadFailed`),`: `,n.error]}):null,!n?.loading&&!n?.error&&e.length===0?(0,z.jsxs)(`p`,{className:`personal-object-list-state`,children:[(0,z.jsx)(cm,{size:14}),i(`files.empty`)]}):null,e.map(e=>(0,z.jsxs)(`button`,{"data-output-kind":e.output.kind,onClick:()=>t({item:e.output,kind:`output`}),type:`button`,children:[(0,z.jsx)(`span`,{className:`personal-file-icon`,children:(0,z.jsx)(cm,{size:16})}),(0,z.jsx)(`strong`,{children:e.output.title}),e.output.report?(0,z.jsx)(`em`,{children:i(`files.reportDelta`,{added:e.output.report.addedCount,changed:e.output.report.changedCount})}):null,(0,z.jsx)(`p`,{children:e.output.summary??e.output.safePreview??e.output.kind??i(`files.emptySummary`)}),(0,z.jsx)(`small`,{title:e.output.createdAt,children:[e.output.goalTitle,e.output.kind===`report`?i(`files.verifiedReport`):null,e.output.todoId?`${i(`common.task`)} ${e.output.todoId}`:null,Wb(e.output.createdAt,r,i)].filter(Boolean).join(` · `)})]},e.id))]})}function qb({agentLabel:e,messages:t,onClose:n,onDraftTask:r,onOpenConversation:i,title:a}){let{t:o}=Ji(),s=t.reduce((e,t,n)=>t.role===`user`?n:e,0),c=t.slice(Math.max(0,s)).slice(-3),l=c.filter(e=>e.role===`assistant`&&!e.pending).at(-1);return(0,R.useEffect)(()=>{if(!n)return;let e=e=>{e.key===`Escape`&&n()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[n]),(0,z.jsxs)(`aside`,{"aria-label":o(`conversation.receipt`),className:`personal-manager-conversation-tray`,children:[(0,z.jsxs)(`header`,{children:[(0,z.jsxs)(`span`,{children:[(0,z.jsx)(Up,{size:16}),(0,z.jsx)(`strong`,{children:a??o(`conversation.title`)}),(0,z.jsx)(`small`,{children:t.at(-1)?.pending?o(`conversation.replying`):o(`common.recently`)})]}),(0,z.jsxs)(`div`,{className:`personal-manager-conversation-actions`,children:[r&&l?(0,z.jsxs)(`button`,{className:`personal-manager-conversation-btn`,onClick:()=>r(l.text),title:o(`conversation.convertHint`),type:`button`,children:[(0,z.jsx)(mm,{size:13}),(0,z.jsx)(`span`,{children:o(`conversation.toTask`)})]}):null,(0,z.jsx)(`button`,{className:`personal-manager-conversation-link`,onClick:i,type:`button`,children:o(`conversation.full`)}),n?(0,z.jsx)(`button`,{"aria-label":o(`conversation.close`),className:`personal-manager-conversation-close`,onClick:n,title:o(`conversation.close`),type:`button`,children:(0,z.jsx)(Gm,{size:14})}):null]})]}),(0,z.jsx)(`div`,{"aria-live":`polite`,className:`personal-manager-conversation-messages`,children:c.map(t=>(0,z.jsxs)(`article`,{className:`is-${t.role}`,children:[(0,z.jsx)(`strong`,{children:t.role===`user`?o(`common.you`):t.agentLabel??e??o(`header.manager`)}),(0,z.jsxs)(`div`,{className:`personal-manager-conversation-bubble`,children:[t.role===`user`?(0,z.jsx)(`p`,{children:t.text}):(0,z.jsx)(py,{text:t.text}),t.pending?(0,z.jsx)(`small`,{children:o(`conversation.agentPending`)}):null]})]},t.id))})]})}function Jb({onClose:e,onOpenDetails:t,run:n}){let{t:r}=Ji();return(0,z.jsxs)(`section`,{"aria-label":r(`session.record`),className:`personal-session-record`,children:[(0,z.jsxs)(`header`,{children:[(0,z.jsxs)(`span`,{children:[(0,z.jsx)(Up,{size:17}),r(`session.record`)]}),(0,z.jsx)(`button`,{"aria-label":r(`session.closeRecord`),onClick:e,type:`button`,children:(0,z.jsx)(Gm,{size:15})})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:n.title}),(0,z.jsx)(`p`,{children:r(`session.recordDescription`)})]}),(0,z.jsxs)(`dl`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Agent`}),(0,z.jsx)(`dd`,{children:n.agentLabel})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:r(`common.status`)}),(0,z.jsx)(`dd`,{children:Xi(n.sessionStatus??n.status,r)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Session`}),(0,z.jsx)(`dd`,{title:n.sessionId,children:n.sessionId})]})]}),(0,z.jsx)(`button`,{className:`personal-secondary-action`,onClick:t,type:`button`,children:r(`session.details`)})]})}function Yb(e,t,n){let r=[];if(t===null)return e.userTodos.slice(0,4).forEach(t=>r.push({attention:{...t,goalTitle:t.goalTitle??Zv(e,t.goalId)},id:`attention:${t.todoId}`,kind:`attention`})),e.goals.filter(e=>Qv(e)===`running`).slice(0,4).forEach(e=>r.push({id:`run:${e.goalId}`,kind:`run`,run:{agentId:e.agentId,agentLabel:e.agentLabel??e.agentId,completedSteps:e.doneTodoCount??e.agentTodos.filter(e=>e.done).length,goalId:e.goalId,goalTitle:e.title,latestActivity:e.agentSentence,runId:`goal:${e.goalId}`,status:`running`,title:e.nextSentence,totalSteps:Math.max((e.doneTodoCount??0)+e.agentTodos.filter(e=>!e.done).length,1)}})),r;let i=e.goals.find(e=>e.goalId===t);if(!i)return r;i.needsYou&&r.push({attention:{blocking:i.needsYouBlocking??!1,goalId:i.goalId,goalTitle:i.title,text:i.needsYou,todoId:`${i.goalId}:attention`},id:`attention:${i.goalId}`,kind:`attention`}),r.push({id:`run:${i.goalId}`,kind:`run`,run:{agentId:i.agentId,agentLabel:i.agentLabel??i.agentId,completedSteps:i.doneTodoCount??i.agentTodos.filter(e=>e.done).length,goalId:i.goalId,goalTitle:i.title,latestActivity:i.agentSentence,runId:`goal:${i.goalId}`,status:i.state===`推进中`?`running`:i.state===`需修复`?`failed`:`waiting`,title:i.nextSentence,totalSteps:Math.max((i.doneTodoCount??0)+i.agentTodos.filter(e=>!e.done).length,1)}}),i.agentTodos.filter(e=>e.taskClass===`continuous_monitor`).forEach(t=>{let a=e.timeline?.find(e=>e.kind===`run`&&e.run.goalId===i.goalId&&e.run.todoId===t.todoId&&!!e.run.sessionId);r.push({id:`schedule:${i.goalId}:${t.todoId}`,kind:`schedule`,schedule:{agentId:i.agentId,executionHistory:a?[{label:a.run.latestActivity||a.run.title,runId:a.run.runId,status:a.run.status===`waiting`||a.run.status===`queued`?`running`:a.run.status,timestamp:i.latestActivity||n(`common.recently`)}]:[],goalId:i.goalId,label:t.text,schedule:t.evidence??n(`schedule.summary`),scheduleId:t.todoId,scheduleKind:`monitor`,sessionId:a?.run.sessionId,status:t.done||t.status===`paused`?`paused`:`active`,stopCondition:n(`drawer.scheduleDefaultStop`),target:t.text,timezone:`Asia/Shanghai`}})});let a=e.timeline?.find(e=>e.kind===`proposal`&&e.proposal.actionKind===`heartbeat.bind`&&e.proposal.goalId===i.goalId);if(a){let e=e=>a.proposal.fields.find(t=>t.key===e)?.value;r.push({id:`schedule:${i.goalId}:heartbeat`,kind:`schedule`,schedule:{agentId:i.agentId,executionHistory:[],goalId:i.goalId,label:`${n(`schedule.heartbeat`)} · ${i.title}`,nextRunAt:n(`drawer.schedulePending`),notificationRule:n(`drawer.scheduleDefaultNotification`),schedule:e(`cadence`)??n(`schedule.summary`),scheduleId:`${i.goalId}:heartbeat`,scheduleKind:`heartbeat`,status:a.proposal.status===`applied`?`active`:`draft`,stopCondition:e(`stop_condition`)??n(`drawer.scheduleDefaultStop`),timezone:e(`timezone`)??`Asia/Shanghai`}})}return r}function Xb(e){return e===`preview_ready`?`ready`:e===`cancelled`?`draft`:e===`failed`?`error`:e}function Zb(e,t){let n={agent_id:t(`proposal.field.agentId`),cadence:t(`proposal.field.cadence`),completion_criteria:t(`proposal.field.completionCriteria`),execution_boundary:t(`proposal.field.executionBoundary`),goal_id:t(`proposal.field.goalId`),heartbeat:t(`proposal.field.heartbeat`),initial_todos:t(`proposal.field.initialTodos`),objective:t(`proposal.field.objective`),operation:t(`proposal.field.operation`),permission:t(`proposal.field.permission`),reason:t(`proposal.field.reason`),stop_condition:t(`proposal.field.stopCondition`),target:t(`proposal.field.target`),timezone:t(`proposal.field.timezone`),title:t(`proposal.field.title`),workspace_ref:t(`proposal.field.workspace`)},r=[`title`,`objective`,`completion_criteria`,`execution_boundary`,`permission`,`agent_id`,`workspace_ref`,`initial_todos`,`heartbeat`,`stop_condition`,`goal_id`];return Object.entries(e).sort(([e],[t])=>{let n=r.indexOf(e),i=r.indexOf(t);return(n<0?r.length:n)-(i<0?r.length:i)}).slice(0,10).map(([e,r])=>({key:e,label:n[e]??e.replaceAll(`_`,` `),value:e===`workspace_ref`?r===`current`?t(`proposal.workspace.current`):t(`proposal.workspace.named`,{workspace:String(r??`current`)}):Array.isArray(r)?r.join(` · `):typeof r==`object`&&r?JSON.stringify(r):String(r??`—`)}))}function Qb(e){if(e.action_kind!==`goal.lifecycle`)return;let t=e.normalized_parameters.operation;return t===`stop`||t===`resume`||t===`delete`?t:void 0}function $b(e,t){let n=Qb(e),r=typeof e.normalized_parameters.title==`string`?e.normalized_parameters.title:typeof e.normalized_parameters.goal_id==`string`?e.normalized_parameters.goal_id:``,i=typeof e.normalized_parameters.target==`string`?e.normalized_parameters.target:``,a=e.action_kind===`goal.create`?t(`proposal.summary.goalCreate`,{title:r}):e.action_kind===`heartbeat.bind`?t(`proposal.summary.heartbeat`):e.action_kind===`monitor.create`?t(`proposal.summary.monitor`,{target:i}):e.action_kind===`goal.lifecycle`&&n===`stop`?t(`proposal.summary.lifecycleStop`,{title:r}):e.action_kind===`goal.lifecycle`&&n===`delete`?t(`proposal.summary.lifecycleDelete`,{title:r}):e.action_kind===`goal.lifecycle`?t(`proposal.summary.lifecycleResume`,{title:r}):e.summary;return{actionKind:e.action_kind,fields:Zb(e.normalized_parameters,t),goalId:typeof e.normalized_parameters.goal_id==`string`?e.normalized_parameters.goal_id:void 0,impact:e.action_kind===`goal.create`?t(`proposal.impact.goalCreate`):e.action_kind===`goal.lifecycle`&&n===`stop`?t(`proposal.impact.lifecycleStop`):e.action_kind===`goal.lifecycle`&&n===`delete`?t(`proposal.impact.lifecycleDelete`):e.action_kind===`goal.lifecycle`?t(`proposal.impact.lifecycleResume`):e.permission_classification===`protected`?t(`proposal.impact.protected`):t(`proposal.impact.default`),previewId:e.proposal_id,lifecycleOperation:n,gate:e.gate?{kind:String(e.gate.kind??`protected_action`),nextAction:typeof e.gate.next_action==`string`?e.gate.next_action:void 0,summary:String(e.gate.summary??t(`proposal.gate.default`))}:void 0,primaryLabel:e.action_kind===`goal.create`?t(`proposal.primary.goalCreate`):e.action_kind===`goal.lifecycle`&&n===`stop`?t(`proposal.primary.lifecycleStop`):e.action_kind===`goal.lifecycle`&&n===`delete`?t(`proposal.primary.lifecycleDelete`):e.action_kind===`goal.lifecycle`?t(`proposal.primary.lifecycleResume`):e.action_kind===`todo.create`&&e.normalized_parameters.start_execution===!0?t(`proposal.primary.todoStart`):t(`proposal.primary.apply`),status:Xb(e.status),title:a}}function ex(e){let t=e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``).slice(0,42);if(t)return t;let n=2166136261;for(let t of e)n^=t.codePointAt(0)??0,n=Math.imul(n,16777619);return`goal-${(n>>>0).toString(36)}`}function tx(e,t){let n=e.match(/[「“"]([^」”"]{2,80})[」”"]/u)?.[1];return n?n.trim():e.replace(/^(请|帮我|我想|给我|创建|新建|设置|please|i want to|create|set up)+/iu,``).replace(/(一个|新的)?\s*(goal|目标)/giu,``).replace(/[,。!?].*$/u,``).trim().slice(0,80)||t(`goal.defaultTitle`)}function nx(e,t){for(let n of e.split(/\r?\n/u)){let e=n.trim();for(let n of t){let t=e.match(RegExp(`^${n.replace(/[.*+?^${}()|[\]\\]/gu,`\\$&`)}\\s*[::]\\s*(.*)$`,`iu`));if(t?.[1]?.trim())return t[1].trim()}}return``}function rx(e,t){let n=nx(e,[`目标`,`Objective`]),r=nx(e,[`完成标准`,`Completion criteria`]),i=nx(e,[`执行边界(可选)`,`执行边界`,`边界`,`Execution boundary (optional)`,`Execution boundary`,`Boundary`]),a=(n||tx(e,t)).split(/[。;;\n]/u)[0].trim().slice(0,80)||t(`goal.defaultTitle`),o=[n||a,r?t(`goal.objectiveCompletion`,{criteria:r}):``,i?t(`goal.objectiveBoundary`,{boundary:i}):``].filter(Boolean).join(` -`),s=/(只读|不调用外部工具|不修改(?:仓库|代码|状态)|read.?only|do not (?:call|use) external tools|do not modify (?:repositories|repository|code|state))/iu.test(i||e);return{completionCriteria:r,executionBoundary:i,initialTodos:r?[t(`goal.initialTodo`,{criteria:r})]:[],objective:o,permission:s?`read_only`:`workspace_write_on_confirmation`,title:a}}function ix(e){let t=e.match(/(?:每|every)\s*(\d{1,3})\s*(?:分钟|minutes?)/iu)?.[1];if(t)return`${t}m`;let n=e.match(/(?:每|every)\s*(\d{1,2})\s*(?:小时|hours?)/iu)?.[1];return n?`${n}h`:/每小时|every hour|hourly/iu.test(e)?`1h`:(/每天|每日|早上|上午|daily|every day/iu.test(e),`1d`)}function ax(e,t){return/(每周|星期|周[一二三四五六日天]|weekly|every\s+(?:mon|tues|wednes|thurs|fri|satur|sun)day|\d{1,2}\s*[::]\s*\d{2})/iu.test(e)?t(`schedule.unsupportedCalendar`):null}function ox(e,t){return nx(e,[`检查内容`,`监控内容`,`目标`,`Check target`,`Monitor target`,`Target`])||e.replace(/^(?:为当前 Goal |for the current Goal )?(?:添加|配置|创建|add|configure|create)?\s*(?:定时检查|监控|scheduled check|monitor)[::]?/iu,``).split(/\r?\n/u)[0].trim()||t(`schedule.defaultTarget`)}function sx(e){return/(mr|pr).{0,8}(合并|merge)/iu.test(e)?`pr_merged`:/发布完成|上线完成|release (?:is )?complete|deployment (?:is )?complete/iu.test(e)?`release_complete`:`goal_complete`}function cx(e,t){let n=e.toLowerCase();return t.find(e=>n.includes(e.agentId.toLowerCase())||n.includes(e.label.toLowerCase()))}function lx(e){let t=nx(e,[`标题`,`任务标题`,`Todo 标题`]),n=nx(e,[`内容`,`任务内容`,`Todo 内容`]);if(t)return[t,n].filter(Boolean).join(`:`).slice(0,400);let r=e.match(/[「“"]([^」”"]{2,200})[」”"]/u)?.[1];return r?r.trim():e.replace(/^(请|帮我|给我|为当前 Goal |新增|新建|创建|添加|加上|加一个|记一个)+/u,``).replace(/^(一个\s*)?(普通\s*)?(todo|待办|任务)(?:\s*到\s*Tasks?)?[::\s]*/iu,``).replace(/[。;;,,]\s*(?:不要|不需要|无需|禁止|别|暂不).{0,80}(?:heartbeat|心跳|定时|监控|执行).*$/iu,``).replace(/[,,]\s*(并且|然后|再)?\s*(交给|分配给|让).+$/u,``).replace(/\s*(交给|分配给|让)\s+.+$/u,``).trim().slice(0,400)||`推进当前 Goal 的下一项工作`}var ux=new Set([`image/png`,`image/jpeg`,`image/webp`,`image/gif`]),dx=5242880,fx=4;function px(e,t){return new Promise((n,r)=>{let i=new FileReader;i.onerror=()=>r(Error(t(`composer.imageReadError`,{name:e.name}))),i.onload=()=>n({dataUrl:String(i.result??``),id:crypto.randomUUID(),mimeType:e.type,name:e.name,size:e.size}),i.readAsDataURL(e)})}function mx({agents:e=[{agentId:`codex`,available:!0,capability:`代码与项目执行`,label:`Codex`}],callbacks:t={},goalArchiveLoadState:n={error:null,phase:`ready`},model:r,readOnly:i=!1,selectedAgentId:a,selectedGoalId:o,statusSourceControl:s}){let{locale:c,t:l}=Ji(),[u,d]=(0,R.useState)(o??null),[f,p]=(0,R.useState)(a??e.find(e=>e.available)?.agentId??`codex`),[m,h]=(0,R.useState)(null),[g,_]=(0,R.useState)(!1),[v,y]=(0,R.useState)(null),[b,x]=(0,R.useState)({}),[S,C]=(0,R.useState)(`chat`),[w,T]=(0,R.useState)(!1),[E,D]=(0,R.useState)(!1),[O,k]=(0,R.useState)(!1),[ee,A]=(0,R.useState)(()=>{try{let e=window.sessionStorage.getItem(`loopx-pw-composer-drafts`),t=e?JSON.parse(e):{};return t&&typeof t==`object`&&!Array.isArray(t)?t:{}}catch{return{}}}),[j,te]=(0,R.useState)(!1),[ne,re]=(0,R.useState)([]),[M,N]=(0,R.useState)(null),[ie,ae]=(0,R.useState)(null),[oe,P]=(0,R.useState)(()=>new Set),[F,I]=(0,R.useState)(()=>new Set),[se,ce]=(0,R.useState)(`idle`),[le,ue]=(0,R.useState)([]),[de,fe]=(0,R.useState)(!1),[pe,me]=(0,R.useState)(zb),[he,ge]=(0,R.useState)({}),[_e,ve]=(0,R.useState)([]),ye=(0,R.useRef)(!1),be=(0,R.useRef)(NaN),xe=(0,R.useRef)(null),Se=(0,R.useRef)(null),Ce=(0,R.useRef)(null),we=(0,R.useRef)(new Set),Te=(0,R.useRef)(new Set),[Ee,De]=(0,R.useState)(null),L=o===void 0?u:o,Oe=a??f,ke=`${L??`manager`}:${Oe}`,Ae=ee[ke]??``;(0,R.useEffect)(()=>{re([]),N(null)},[ke]);function je(e,t){A(n=>{let r={...n};t?r[e]=t:delete r[e];try{window.sessionStorage.setItem(`loopx-pw-composer-drafts`,JSON.stringify(r))}catch{}return r})}function Me(e){je(ke,e)}function Ne(e){let t=ee[ke]?.trimEnd();Me(t?`${t}\n${e}`:e),window.requestAnimationFrame(()=>xe.current?.focus())}(0,R.useEffect)(()=>{let e=xe.current;e&&(e.style.height=`auto`,e.style.height=`${Math.min(e.scrollHeight,120)}px`)},[Ae]);let Pe=(0,R.useMemo)(()=>r.goals.map(e=>{let t=he[e.goalId];return t?{...e,repository:{branch:t.branch,identity:t.identity,label:t.label,readOnly:!0}}:e}),[he,r.goals]),Fe=(0,R.useMemo)(()=>Pe.filter(e=>Qv(e)===`needs_you`).length,[Pe]),Ie=(0,R.useMemo)(()=>Pe.filter(e=>Qv(e)===`needs_you`&&(e.needsYouBlocking||e.state===`等你`)).length,[Pe]),B=Pe.find(e=>e.goalId===L)??null,Le=m?.kind===`settings`,Re=L,V=(0,R.useMemo)(()=>{let e=Object.values(b).filter(e=>e.actionKind===`heartbeat.bind`&&e.goalId&&e.status===`applied`).map(e=>({id:`schedule:${e.goalId}:heartbeat`,kind:`schedule`,schedule:{agentId:Oe,executionHistory:[],goalId:e.goalId,label:e.title,nextRunAt:l(`drawer.schedulePending`),notificationRule:l(`drawer.scheduleDefaultNotification`),schedule:e.fields.find(e=>e.key===`cadence`)?.value??l(`schedule.summary`),scheduleId:`${e.goalId}:heartbeat`,scheduleKind:`heartbeat`,status:e.status===`applied`?`active`:`draft`,stopCondition:e.fields.find(e=>e.key===`stop_condition`)?.value??l(`drawer.scheduleDefaultStop`),timezone:e.fields.find(e=>e.key===`timezone`)?.value??`Asia/Shanghai`}})),t=[...Yb(r,Re,l),...r.timeline??[],...e,...Ub(Object.values(b)).filter(e=>e.actionKind!==`heartbeat.bind`||e.status!==`applied`).map(e=>({id:`proposal:${e.previewId}`,kind:`proposal`,proposal:e}))];return[...new Map(t.map(e=>[e.id,e])).values()].filter(e=>e.kind!==`proposal`||![`stale`,`error`].includes(e.proposal.status)||le.includes(e.proposal.previewId)).filter(e=>!L||e.kind===`message`?!0:e.kind===`proposal`?!e.proposal.goalId||e.proposal.goalId===L:e.kind===`attention`?e.attention.goalId===L:e.kind===`run`?e.run.goalId===L:e.kind===`schedule`?e.schedule.goalId===L:e.output.goalId===L)},[Re,r,b,Oe,L,le,l]),ze=(0,R.useMemo)(()=>v?V.filter(e=>e.kind===`message`?!0:e.kind===`run`?e.run.runId===v.runId:e.kind===`output`&&e.output.runId===v.runId):V,[v,V]);(0,R.useEffect)(()=>{if(!v)return;let e=V.find(e=>e.kind===`run`&&e.run.runId===v.runId);!e||e.kind!==`run`||JSON.stringify({completedSteps:v.completedSteps,latestActivity:v.latestActivity,messages:v.sessionMessages,sessionStatus:v.sessionStatus,status:v.status,totalSteps:v.totalSteps})!==JSON.stringify({completedSteps:e.run.completedSteps,latestActivity:e.run.latestActivity,messages:e.run.sessionMessages,sessionStatus:e.run.sessionStatus,status:e.run.status,totalSteps:e.run.totalSteps})&&y(e.run)},[v,V]);let Be=(0,R.useMemo)(()=>V.flatMap(e=>e.kind===`message`?[e.message]:[]),[V]),Ve=(0,R.useMemo)(()=>B?V.flatMap(e=>e.kind===`message`?[e.message]:[]):[],[V,B]);(0,R.useEffect)(()=>{B||w||Be.some(e=>e.pending)&&D(!0)},[w,Be,B]),(0,R.useEffect)(()=>{!B||S===`chat`||Ve.some(e=>e.pending)&&k(!0)},[Ve,B,S]);let He=(0,R.useMemo)(()=>V.filter(e=>e.kind===`message`||e.kind===`proposal`&&le.includes(e.proposal.previewId)),[V,le]),Ue=He[He.length-1],We=Ue?.kind===`message`?Ue.message.text.length:0;(0,R.useEffect)(()=>{if(!w||!Se.current)return;let e=window.requestAnimationFrame(()=>{Se.current&&(Se.current.scrollTop=Se.current.scrollHeight)});return()=>window.cancelAnimationFrame(e)},[He.length,w,We]);let Ge=(0,R.useMemo)(()=>{if(m?.kind===`settings`)return null;if(m?.kind===`goal`){let e=Pe.find(e=>e.goalId===m.item.goalId);return e?{item:e,kind:`goal`}:m}if(m?.kind!==`run`)return m;let e=V.find(e=>e.kind===`run`&&e.run.runId===m.item.runId);return e?{item:e.run,kind:`run`}:m},[V,m,Pe]);(0,R.useEffect)(()=>{if(i){ge({}),ve([]);return}let e=!1;return Promise.all([Eg(),Lg()]).then(([t,n])=>{e||(ge(Object.fromEntries(t.map(e=>[e.goal_id,e.repository]))),ve(n))}).catch(()=>{}),()=>{e=!0}},[i]),(0,R.useEffect)(()=>{if(!de)return;function e(e){e.key===`Escape`&&fe(!1)}return document.addEventListener(`keydown`,e),()=>document.removeEventListener(`keydown`,e)},[de]),(0,R.useEffect)(()=>{if(L||!V.length)return;if(!ye.current){ye.current=!0;try{be.current=Date.parse(window.localStorage.getItem(`loopx-pw-last-visit`)??``),window.localStorage.setItem(`loopx-pw-last-visit`,new Date().toISOString())}catch{be.current=NaN}}let e=be.current,t=V.filter(e=>e.kind===`run`).map(e=>e.run),n=t=>{let n=Date.parse(t??``);return!Number.isNaN(e)&&!Number.isNaN(n)&&n>e},r={attention:Fe,done:t.filter(e=>e.status===`completed`&&n(e.latestActivity)).length,failed:t.filter(e=>(e.status===`failed`||e.status===`interrupted`)&&n(e.latestActivity)).length};De(e=>e?.attention===r.attention&&e.done===r.done&&e.failed===r.failed?e:r)},[V,Fe,L]),(0,R.useEffect)(()=>{if(i){x({});return}let e=!1;return Ch(L?{goalId:L}:{contextKind:`manager`}).then(t=>{if(e)return;let n=Object.fromEntries(t.filter(e=>[`ready`,`gated`,`deferred`,`applying`].includes(e.status)).map(e=>{let t=$b(e,l);return[t.previewId,t]}));x(e=>({...e,...n}))}).catch(()=>{}),()=>{e=!0}},[i,L,l]);async function Ke(e,n={}){if(i)throw Error(l(`source.readOnlyWriteError`));let r;try{r=t.onPreviewAction?await t.onPreviewAction(e):$b(await xh(e),l)}catch(t){if(!(t instanceof _h)||t.payload.error_code!==`action_preview_gate`)throw t;let n=t.payload.gate&&typeof t.payload.gate==`object`?t.payload.gate:{},i=(Array.isArray(n.candidates)?n.candidates:[]).flatMap(e=>{if(!e||typeof e!=`object`)return[];let t=e;return typeof t.workspace_ref==`string`&&typeof t.label==`string`?[{label:t.label,workspaceRef:t.workspace_ref}]:[]}),a=String(n.kind??`workspace_selection_required`),o=a===`agent_binding_required`||a===`agent_identity_selection_required`;r={actionKind:e.actionKind,fields:i.map(e=>({key:`workspace_ref:${e.workspaceRef}`,label:e.label,value:e.workspaceRef})),gate:{kind:a,nextAction:typeof n.next_action==`string`?n.next_action:void 0,summary:String(n.summary??l(`proposal.workspaceGate.defaultSummary`))},impact:l(o?`proposal.workspaceGate.agentImpact`:`proposal.workspaceGate.selectionImpact`),previewId:`workspace-choice-${Date.now().toString(36)}`,sourceRequest:e,status:`gated`,title:l(o?`proposal.workspaceGate.agentTitle`:`proposal.workspaceGate.selectionTitle`),workspaceCandidates:i}}return ue(e=>e.includes(r.previewId)?e:[...e,r.previewId]),x(e=>({...e,[r.previewId]:r})),n.select!==!1&&h({item:r,kind:`proposal`}),r}function qe(){tt(null),je(`manager:${Oe}`,l(`composer.createGoalTemplate`)),window.requestAnimationFrame(()=>xe.current?.focus())}async function Je(e,n){let r={delete:`Deleted from the owner workspace`,resume:`Resumed from the owner workspace`,stop:`Stopped from the owner workspace`},i={delete:l(`proposal.summary.lifecycleDelete`,{title:e.title}),resume:l(`proposal.summary.lifecycleResume`,{title:e.title}),stop:l(`proposal.summary.lifecycleStop`,{title:e.title})},a=null,o=!1;try{if(n===`stop`){if(we.current.has(e.goalId))return;we.current.add(e.goalId),P(new Set(we.current)),h(null),a={goalId:e.goalId,next:`stopped`,optimisticApplied:!0,previous:e.activationState},ae(l(`feedback.applying`,{title:i.stop})),t.onGoalActivationStateChange?.(e.goalId,`stopped`)}let s=await Ke({actionKind:`goal.lifecycle`,context:{kind:`goal_directory`,goal_id:e.goalId},idempotencyKey:`workspace-goal-${n}-${e.goalId}-${Date.now().toString(36)}`,normalizedParameters:{goal_id:e.goalId,operation:n,reason:r[n]},summary:i[n]},{select:n!==`stop`});n===`stop`&&(s.status===`ready`?(o=!0,await Qe(s,{lifecycleProjection:a??void 0,presentation:`feedback`})):(a&&t.onGoalActivationStateChange?.(a.goalId,a.previous),ae(s.gate?l(`feedback.gateRequired`,{summary:s.gate.summary}):l(`feedback.notCompleted`,{status:s.status})),h({item:s,kind:`proposal`})))}catch(e){a&&!o&&t.onGoalActivationStateChange?.(a.goalId,a.previous),ae(l(`feedback.executionFailed`,{error:e instanceof Error?e.message:String(e)}))}finally{n===`stop`&&(we.current.delete(e.goalId),P(new Set(we.current)))}}function Ye(e,t){Me(l(t?e===`heartbeat`?`composer.heartbeatTemplate`:`composer.monitorTemplate`:e===`heartbeat`?`composer.heartbeatTemplateWithoutGoal`:`composer.monitorTemplateWithoutGoal`)),h(null),window.requestAnimationFrame(()=>xe.current?.focus())}async function Xe(e,n,r=``){let i=await t.onRequestScheduleConfig?.(e,n);if(i){ue(e=>e.includes(i.previewId)?e:[...e,i.previewId]),x(e=>({...e,[i.previewId]:i})),h({item:i,kind:`proposal`});return}if(!n){Me(l(e===`heartbeat`?`composer.heartbeatGoalQuestion`:`composer.monitorGoalQuestion`));return}let a=Date.now().toString(36);await Ke({actionKind:e===`heartbeat`?`heartbeat.bind`:`monitor.create`,context:{kind:`schedule`,goal_id:n},idempotencyKey:`workspace-${e}-${n}-${a}`,normalizedParameters:e===`heartbeat`?{agent_id:Oe,cadence:ix(r),goal_id:n,stop_condition:sx(r),timezone:`Asia/Shanghai`}:{agent_id:Oe,cadence:ix(r),goal_id:n,stop_condition:sx(r),target:ox(r,l),target_key:`goal-${n}`,timezone:`Asia/Shanghai`},summary:e===`heartbeat`?l(`proposal.summary.heartbeat`):l(`proposal.summary.monitor`,{target:ox(r,l)})})}async function Ze(e){if(!Te.current.has(e.todoId)){Te.current.add(e.todoId),I(new Set(Te.current)),ae(l(`feedback.preparingPreview`,{title:e.text}));try{await Ke({actionKind:`todo.update`,context:{goal_id:e.goalId,kind:`todo`,todo_id:e.todoId},idempotencyKey:`workspace-todo-${e.todoId}-complete-${Date.now().toString(36)}`,normalizedParameters:{goal_id:e.goalId,operation:`complete`,todo_id:e.todoId},summary:l(`tasks.markComplete`,{name:e.text})}),ae(null)}catch(e){ae(l(`feedback.previewFailed`,{error:e instanceof Error?e.message:String(e)}))}finally{Te.current.delete(e.todoId),I(new Set(Te.current))}}}async function Qe(e,n={}){let i=n.presentation!==`feedback`,a=e.actionKind===`goal.lifecycle`&&e.goalId&&(e.lifecycleOperation===`stop`||e.lifecycleOperation===`resume`)?{goalId:e.goalId,next:e.lifecycleOperation===`stop`?`stopped`:`active`,optimisticApplied:!1,previous:r.goals.find(t=>t.goalId===e.goalId)?.activationState??(e.lifecycleOperation===`stop`?`active`:`stopped`)}:null,o=n.lifecycleProjection??a;ae(l(`feedback.applying`,{title:e.title}));let s={...e,status:`applying`};x(t=>({...t,[e.previewId]:s})),i&&h({item:s,kind:`proposal`}),o&&!o.optimisticApplied&&t.onGoalActivationStateChange?.(o.goalId,o.next);try{if(t.onApplyProposal){await t.onApplyProposal(e);let n={...e,status:`applied`};if(x(t=>({...t,[e.previewId]:n})),i&&h({item:n,kind:`proposal`}),ae(l(`feedback.completed`,{title:e.title})),e.actionKind===`goal.lifecycle`){(e.lifecycleOperation===`stop`||e.lifecycleOperation===`delete`)&&tt(null),e.lifecycleOperation===`delete`&&e.goalId&&t.onGoalDeleted?.(e.goalId);let n=t.onReconcileStatus??t.onRefresh;Promise.resolve().then(()=>n?.()).catch(()=>void 0)}return}let n=await wh(e.previewId),r=$b(n.proposal,l);if(x(t=>({...t,[e.previewId]:r})),i&&h({item:r,kind:`proposal`}),n.proposal.status!==`applied`||n.proposal.receipt?.projection_verified!==!0){o&&t.onGoalActivationStateChange?.(o.goalId,o.previous),ae(n.proposal.status===`stale`?l(`feedback.stale`):l(`feedback.notCompleted`,{status:n.proposal.status}));return}if(ae(l(`feedback.completed`,{title:r.title})),r.actionKind===`todo.create`&&await t.onRefresh?.(),r.actionKind===`goal.lifecycle`&&(r.lifecycleOperation===`stop`||r.lifecycleOperation===`delete`)&&tt(null),r.actionKind===`goal.lifecycle`&&r.lifecycleOperation===`delete`&&r.goalId&&t.onGoalDeleted?.(r.goalId),r.actionKind===`goal.lifecycle`){let e=t.onReconcileStatus??t.onRefresh;Promise.resolve().then(()=>e?.()).catch(()=>void 0)}}catch(n){if(o&&t.onGoalActivationStateChange?.(o.goalId,o.previous),n instanceof _h&&n.payload.error_code===`protected_action`){let r=n.payload.gate,i=r&&typeof r==`object`?r:{},a={...e,gate:{kind:String(i.kind??`protected_action`),nextAction:typeof i.next_action==`string`?i.next_action:void 0,summary:String(i.summary??n.message)},status:`gated`};x(t=>({...t,[e.previewId]:a})),h({item:a,kind:`proposal`}),ae(l(`feedback.gateRequired`,{summary:a.gate.summary})),e.actionKind===`goal.create`&&e.goalId&&(t.onRefresh?.(),tt(e.goalId));return}let r=n instanceof Error&&/stale|状态.*变化|conflict/i.test(n.message),a={...e,errorMessage:n instanceof Error?n.message:String(n),status:r?`stale`:`error`};x(t=>({...t,[e.previewId]:a})),i&&h({item:a,kind:`proposal`}),ae(l(`feedback.executionFailed`,{error:a.errorMessage}))}}let $e={...t,onOpenRunSession:async e=>{e.goalId!==L&&tt(e.goalId),C(`chat`),await t.onOpenRunSession?.(e),y(e),h(null)},onOpenGoal:e=>{tt(e);let n=t.onReconcileStatus??t.onRefresh;Promise.resolve().then(()=>n?.()).catch(()=>{ae(l(`feedback.goalRefreshFailed`))})},onOpenGoalView:e=>{C(e),e===`chat`&&y(null),h(null)},onOpenOutput:e=>{e.goalId!==L&&tt(e.goalId),C(`files`),t.onOpenOutput?.(e)},onApplyProposal:Qe,onCancelProposal:async e=>{h(null),x(t=>{let n={...t};return delete n[e.previewId],n});try{t.onCancelProposal?.(e),t.onCancelProposal||await Th(e.previewId)}catch(t){x(t=>({...t,[e.previewId]:e})),ae(l(`feedback.cancelFailed`,{error:t instanceof Error?t.message:String(t)}))}},onTransitionProposal:async(e,t)=>{let n=$b(await Eh(e.previewId,t),l);ue(e=>e.includes(n.previewId)?e:[...e,n.previewId]),x(r=>{let i={...r};return t===`regenerate`&&delete i[e.previewId],i[n.previewId]=n,i}),h({item:n,kind:`proposal`})},onSelectWorkspaceCandidate:async(e,t)=>{e.sourceRequest&&(x(t=>{let n={...t};return delete n[e.previewId],n}),await Ke({...e.sourceRequest,idempotencyKey:`${e.sourceRequest.idempotencyKey}-${t}`,normalizedParameters:{...e.sourceRequest.normalizedParameters,workspace_ref:t}}))},onPreviewAction:Ke,onRequestScheduleConfig:(e,t)=>Ye(e,t),onOpenNotificationSettings:e=>h({goalId:e,kind:`settings`,tab:`lark`}),onFetchNotificationTargets:()=>Yh(),onSetupGoalChannel:e=>Zh(e),onToggleGoalAutoNotify:e=>Qh(e),onUpdateSchedule:async(e,t)=>{let n=Date.now().toString(36),r=e.scheduleKind===`heartbeat`;await Ke({actionKind:r?`heartbeat.bind`:`monitor.update`,context:{kind:`schedule`,goal_id:e.goalId},idempotencyKey:`workspace-monitor-${e.scheduleId}-${t}-${n}`,normalizedParameters:{agent_id:e.agentId??Oe,...!r&&t===`run_now`?{endpoint_id:Oe}:{},...t===`edit`?{cadence:`2h`,...r?{timezone:e.timezone??`Asia/Shanghai`}:{}}:{},goal_id:e.goalId,operation:t,...!r&&t===`run_now`&&e.sessionId?{session_id:e.sessionId}:{},...r?{}:{todo_id:e.scheduleId}},summary:t===`pause`?`暂停自动运行:${e.label}`:t===`resume`?`恢复自动运行:${e.label}`:t===`run_now`?`立即运行:${e.label}`:t===`stop`?`停止自动运行:${e.label}`:`编辑自动运行生命周期:${e.label}`})}},et=i?{onOpenGoal:$e.onOpenGoal,onOpenGoalView:$e.onOpenGoalView,onOpenOutput:$e.onOpenOutput}:$e;function tt(e){d(e),T(!1),D(!1),k(!1),y(null),h(null),C(`tasks`),fe(!1),t.onSelectGoal?.(e)}function nt(e){p(e),t.onSelectAgent?.(e)}function rt(e){me(e),Bb(e)}async function it(n){let r=n?[]:ne,i=(n??Ae).trim()||(r.length?l(`composer.imageAnalysisPrompt`):``);if(!(!i||j)){n||(Me(``),re([])),N(null),te(!0);try{if(r.length){L?S!==`chat`&&k(!0):D(!0);let e=await t.onSendMessage?.(i,Oe,L,r);e&&await Ke(e);return}let n=wy(i,{agents:e.map(e=>({agentId:e.agentId,label:e.label})),goalId:L,todos:(B?.agentTodos??[]).map(e=>({text:e.text,todoId:e.todoId}))});if(n.route===`clarify`){Me(i);let e=l(`composer.clarifySingleAction`);n.missingFields.includes(`resume_when`)&&(e=l(`composer.clarifyDefer`)),ae(e);return}if(n.actionKind===`goal.create`){let e=rx(i,l),t=ex(e.title);await Ke({actionKind:`goal.create`,context:{kind:`manager`,goal_id:null,natural_language:i},idempotencyKey:`workspace-goal-intent-${t}-${Date.now().toString(36)}`,normalizedParameters:{agent_id:Oe,completion_criteria:e.completionCriteria,execution_boundary:e.executionBoundary,goal_id:t,heartbeat:{cadence:ix(i),enabled:n.normalizedParameters.heartbeat_enabled===!0,timezone:`Asia/Shanghai`},initial_todos:e.initialTodos,objective:e.objective,permission:e.permission,stop_condition:sx(i),title:e.title,workspace_ref:`current`},summary:l(`proposal.summary.goalCreate`,{title:e.title})});return}if(L&&n.actionKind===`heartbeat.bind`){await Xe(`heartbeat`,L,i);return}if(L&&n.actionKind===`monitor.create`){let e=ax(i,l);if(e){Me(i),ae(e);return}await Xe(`monitor`,L,i);return}let a=cx(i,e);if(L&&a&&n.actionKind===`agent.bind`){await Ke({actionKind:`agent.bind`,context:{kind:`goal`,goal_id:L,natural_language:i},idempotencyKey:`workspace-agent-bind-${L}-${a.agentId}-${Date.now().toString(36)}`,normalizedParameters:{agent_id:a.agentId,goal_id:L},summary:`将 ${a.label} 绑定到 ${B?.title??L}`});return}if(L&&n.actionKind===`todo.create`){if(n.normalizedParameters.start_execution===!0){await Ke({actionKind:`todo.create`,context:{kind:`goal`,goal_id:L,natural_language:i},idempotencyKey:`workspace-task-start-${L}-${Date.now().toString(36)}`,normalizedParameters:{endpoint_id:a?.agentId??Oe,goal_id:L,start_execution:!0,text:i},summary:`交给 Agent 执行:${i.slice(0,120)}`});return}let e=a?.agentId??(/(交给|分配给|让).{0,24}(agent|codex|claude|kimi)/iu.test(i)?Oe:null);await Ke({actionKind:`todo.create`,context:{kind:`goal`,goal_id:L,natural_language:i},idempotencyKey:`workspace-todo-create-${L}-${Date.now().toString(36)}`,normalizedParameters:{...e?{endpoint_id:e}:{},goal_id:L,text:lx(i)},summary:`创建 Todo:${lx(i)}`});return}let o=B?.agentTodos.find(e=>i.includes(e.todoId)||i.includes(e.text)),s=typeof n.normalizedParameters.operation==`string`?n.normalizedParameters.operation:null;if(L&&o&&n.actionKind===`todo.update`&&s){await Ke({actionKind:`todo.update`,context:{kind:`todo`,goal_id:L,todo_id:o.todoId,natural_language:i},idempotencyKey:`workspace-todo-update-${o.todoId}-${s}-${Date.now().toString(36)}`,normalizedParameters:{agent_id:Oe,...s===`reassign`&&a?{endpoint_id:a.agentId}:{},...s===`block`?{note:i}:{},...s===`defer`&&typeof n.normalizedParameters.resume_when==`string`?{resume_when:n.normalizedParameters.resume_when}:{},goal_id:L,operation:s,todo_id:o.todoId},summary:`更新 Todo:${o.text}`});return}L?S!==`chat`&&k(!0):D(!0);let c=await t.onSendMessage?.(i,Oe,L);c&&await Ke(c)}catch(e){n||(Me(i),re(r));let t=e instanceof Error?e.message:l(`feedback.sendGenericError`);ae(l(`feedback.sendFailed`,{error:t}))}finally{te(!1)}}}let at=e.find(e=>e.agentId===Oe)?.label??Oe,ot=!B&&Ae.startsWith(l(`composer.createGoalDraftLead`)),st=V.filter(e=>e.kind===`run`&&!!e.run.sessionId&&!!e.run.canInterrupt&&(e.run.status===`running`||e.run.status===`queued`)).length;async function ct(e){if(!e?.length)return;let t=fx-ne.length,n=Array.from(e).slice(0,Math.max(0,t)),r=n.find(e=>!ux.has(e.type)),i=n.find(e=>e.size>dx);if(t<=0){N(l(`composer.imageCountError`,{count:fx}));return}if(r){N(l(`composer.imageTypeError`));return}if(i){N(l(`composer.imageSizeError`,{size:dx/1024/1024}));return}try{let t=await Promise.all(n.map(e=>px(e,l)));re(e=>[...e,...t].slice(0,fx)),N(e.length>n.length?l(`composer.imageCountError`,{count:fx}):null)}catch(e){N(e instanceof Error?e.message:l(`composer.imageReadGenericError`))}finally{Ce.current&&(Ce.current.value=``)}}function lt(e){let t=Array.from(e.clipboardData.items).filter(e=>e.kind===`file`&&e.type.startsWith(`image/`)).flatMap(e=>{let t=e.getAsFile();return t?[t]:[]});t.length&&(e.preventDefault(),ct(t))}async function ut(){let e=await Lg();ve(e)}async function dt(){await Promise.all([ut(),t.onRefresh?.()])}async function ft(){if(!(!t.onRefresh||se===`loading`)){ce(`loading`);try{await t.onRefresh(),ce(`done`)}catch{ce(`error`)}window.setTimeout(()=>ce(`idle`),1800)}}return Le?(0,z.jsx)(Ib,{focusGoalConnection:!!(m?.kind===`settings`&&m.goalId),goals:Pe,initialGoalId:m?.kind===`settings`?m.goalId??L:L,initialTab:m?.kind===`settings`?m.tab??`lark`:`lark`,onChanged:()=>void dt(),onClose:()=>h(null),onThemeChange:rt,theme:pe}):(0,z.jsx)(Vb,{drawer:Ge?(0,z.jsx)(My,{agents:e,callbacks:et,goalNotifications:r.goalNotifications??[],goals:Pe,inspectorExpanded:g,larkConnections:i?[]:_e,onClose:()=>{Ge.kind===`proposal`&&[`applied`,`rejected`].includes(Ge.item.status)&&(Ge.item.actionKind!==`heartbeat.bind`||Ge.item.status!==`applied`)&&x(e=>{let t={...e};return delete t[Ge.item.previewId],t}),_(!1),h(null)},onToggleInspectorSize:()=>_(e=>!e),readOnly:i,runs:V.flatMap(e=>e.kind===`run`?[e.run]:[]),selection:Ge}):null,drawerMode:Ge?.kind===`todo`?g?`inspector-full`:`inspector`:`panel`,drawerOpen:Ge!==null,mobileSidebarOpen:de,onCloseMobileSidebar:()=>fe(!1),theme:pe,main:(0,z.jsxs)(`div`,{className:`personal-channel`,children:[(0,z.jsx)(oy,{agents:e,managerChatOpen:w,mobileNavigationOpen:de,onOpenGoalCapabilities:B?()=>h({goalId:B.goalId,kind:`settings`,tab:`capabilities`}):void 0,onOpenGoalDetail:B&&!B.loadState?()=>h({item:B,kind:`goal`}):void 0,onRefresh:t.onRefresh?()=>void ft():void 0,onOpenNavigation:()=>fe(!0),onOpenManagerChat:()=>{D(!1),T(!0)},onSelectGoalTab:e=>{C(e),e===`chat`&&(y(null),k(!1))},onSelectAgent:nt,onReturnManagerHome:()=>{T(!1),D(!1),window.requestAnimationFrame(()=>Se.current?.scrollTo({behavior:`smooth`,top:0}))},selectedAgentId:Oe,refreshState:se,readOnlySourceLabel:i?s?.activeSource.label:void 0,selectedGoal:B,selectedGoalTab:S}),(0,z.jsxs)(`div`,{className:`personal-channel-scroll`,ref:Se,children:[!B&&!w&&Ee&&Ee.done+Ee.failed+Ee.attention>0?(0,z.jsxs)(`section`,{className:`personal-digest-card`,"aria-label":l(`digest.away`),children:[(0,z.jsx)(`strong`,{children:l(`digest.away`)}),(0,z.jsxs)(`div`,{className:`personal-digest-stats`,children:[(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`b`,{children:Ee.done}),l(`digest.completed`)]}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`b`,{children:Ee.failed}),l(`digest.failed`)]}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`b`,{children:Ee.attention}),l(`digest.needsYou`)]})]})]}):null,!B&&!w?(0,z.jsxs)(`section`,{className:`personal-manager-greeting`,children:[(0,z.jsx)(`span`,{children:(0,z.jsx)(Up,{size:20})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:l(`home.greeting`)}),(0,z.jsx)(`p`,{children:r.goals.some(e=>e.activationState===`active`&&e.loadState)?l(`startup.partial`):(0,z.jsxs)(z.Fragment,{children:[l(`home.waitingCount`,{count:Fe}),` `,l(`home.blockingSummary`,{count:Ie})]})})]})]}):null,B?.loadState?(0,z.jsx)(`section`,{className:`personal-manager-greeting`,role:`status`,"data-testid":`goal-status-loading`,children:(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:l(B.loadState===`error`?`startup.goalError`:`startup.goalLoading`)}),(0,z.jsx)(`p`,{children:l(B.loadError?`startup.error.${B.loadError}`:`startup.independent`)}),B.loadState===`error`?(0,z.jsx)(`button`,{className:`min-h-11 rounded-md border px-3 py-2 text-sm`,type:`button`,onClick:()=>void t.onRefresh?.(),children:l(`startup.retry`)}):null]})}):B&&S===`tasks`?(0,z.jsx)(tb,{historyEnabled:!i,goal:B,items:V,onDraftTaskFromMessage:i?void 0:e=>{Me(`创建一个 Task:${Hb(e)}`),ae(l(`feedback.taskDraftCreated`)),window.requestAnimationFrame(()=>xe.current?.focus())},onOpenChat:()=>C(`chat`),onQuickComplete:i?void 0:Ze,onSelect:h,quickCompletingTodoIds:F,selectedTodoId:Ge?.kind===`todo`?Ge.item.todoId:null,userTodos:r.userTodos}):B&&S===`files`?(0,z.jsx)(Kb,{items:V.filter(e=>e.kind===`output`),onSelect:h,reportState:r.periodicReports}):!B&&!w?(0,z.jsx)(Gb,{goals:Pe,onRetry:()=>void t.onRefresh?.(),onSelectGoal:tt,systemHealth:r.systemHealth}):B?(0,z.jsxs)(z.Fragment,{children:[B&&v?.goalId===B.goalId?(0,z.jsx)(Jb,{onClose:()=>y(null),onOpenDetails:()=>h({item:v,kind:`run`}),run:v}):null,(0,z.jsx)(vy,{items:ze,onSelect:h,selectedGoal:B})]}):(0,z.jsx)(vy,{items:He,onSelect:h,selectedGoal:null})]}),(0,z.jsx)(`div`,{className:`personal-composer-wrap`,children:i?(0,z.jsxs)(`div`,{className:`personal-read-only-notice`,children:[(0,z.jsx)(`strong`,{children:l(`source.readOnlyNoticeTitle`)}),(0,z.jsx)(`span`,{children:l(`source.readOnlyNoticeDescription`)})]}):(0,z.jsxs)(z.Fragment,{children:[!B&&!w&&E&&Be.length?(0,z.jsx)(qb,{messages:Be,onClose:()=>D(!1),onOpenConversation:()=>{D(!1),T(!0)}}):null,B&&S!==`chat`&&O&&Ve.length?(0,z.jsx)(qb,{agentLabel:at,messages:Ve,onClose:()=>k(!1),onDraftTask:S===`tasks`?e=>{Me(`创建一个 Task:${Hb(e)}`),ae(l(`feedback.taskDraftCreated`)),window.requestAnimationFrame(()=>xe.current?.focus())}:void 0,onOpenConversation:()=>{k(!1),C(`chat`)},title:`${B.title} · ${at}`}):null,ie?(0,z.jsxs)(`div`,{className:`personal-action-feedback`,role:`status`,children:[(0,z.jsx)(`span`,{children:ie}),(0,z.jsx)(`button`,{"aria-label":l(`common.closeActionReceipt`),onClick:()=>ae(null),type:`button`,children:(0,z.jsx)(Gm,{size:14})})]}):null,(0,z.jsx)(`p`,{className:`personal-composer-hint`,children:B?st>0?l(`composer.goalRunningHint`,{agent:at,count:st}):l(`composer.goalMessageHint`,{agent:at}):l(`composer.managerMessageHint`)}),B?(0,z.jsxs)(`div`,{className:`personal-quick-prompts`,children:[(0,z.jsxs)(`button`,{"aria-label":l(`composer.nextAction`),className:`is-draft`,onClick:()=>Ne(l(`composer.nextActionPrompt`)),title:l(`composer.prepareDraft`),type:`button`,children:[(0,z.jsx)(vm,{size:13}),(0,z.jsx)(`span`,{children:l(`composer.nextAction`)}),(0,z.jsx)(`small`,{className:`personal-prompt-subtle`,children:l(`composer.draft`)})]}),(0,z.jsxs)(`button`,{className:`is-immediate`,disabled:j,onClick:()=>void it(l(`composer.agentProgressPrompt`)),title:l(`composer.immediate`),type:`button`,children:[(0,z.jsx)(Mm,{size:13}),(0,z.jsx)(`span`,{children:l(`composer.agentProgress`)}),(0,z.jsx)(`em`,{className:`personal-prompt-badge`,children:l(`composer.immediate`)})]}),(0,z.jsxs)(`button`,{"aria-label":l(`composer.monitor`),className:`is-draft`,onClick:()=>Ye(`monitor`,L),title:l(`composer.monitorHint`),type:`button`,children:[(0,z.jsx)(Gp,{size:13}),(0,z.jsx)(`span`,{children:l(`composer.monitor`)}),(0,z.jsx)(`small`,{className:`personal-prompt-subtle`,children:l(`composer.draft`)})]})]}):(0,z.jsxs)(`div`,{className:`personal-quick-prompts`,children:[(0,z.jsxs)(`button`,{"aria-label":l(`composer.globalTasks`),className:`is-draft`,onClick:()=>Ne(l(`composer.globalTasksPrompt`)),title:l(`composer.prepareDraft`),type:`button`,children:[(0,z.jsx)(vm,{size:13}),(0,z.jsx)(`span`,{children:l(`composer.globalTasks`)}),(0,z.jsx)(`small`,{className:`personal-prompt-subtle`,children:l(`composer.draft`)})]}),(0,z.jsxs)(`button`,{className:`is-immediate`,disabled:j,onClick:()=>void it(l(`composer.globalProgressPrompt`)),title:l(`composer.immediate`),type:`button`,children:[(0,z.jsx)(Mm,{size:13}),(0,z.jsx)(`span`,{children:l(`composer.globalProgress`)}),(0,z.jsx)(`em`,{className:`personal-prompt-badge`,children:l(`composer.immediate`)})]}),(0,z.jsxs)(`button`,{"aria-label":l(`composer.createGoal`),className:`is-draft`,onClick:qe,title:l(`composer.createGoalHint`),type:`button`,children:[(0,z.jsx)(Em,{size:13}),(0,z.jsx)(`span`,{children:l(`composer.createGoal`)}),(0,z.jsx)(`small`,{className:`personal-prompt-subtle`,children:l(`composer.draft`)})]})]}),ot?(0,z.jsxs)(`div`,{className:`personal-goal-draft-status`,role:`status`,children:[(0,z.jsx)(`strong`,{children:l(`composer.createGoalDraft`)}),(0,z.jsx)(`span`,{children:l(`composer.createGoalDraftDescription`)})]}):null,ne.length?(0,z.jsx)(`div`,{className:`personal-composer-images`,"aria-label":l(`composer.imagesPending`),children:ne.map(e=>(0,z.jsxs)(`figure`,{children:[(0,z.jsx)(`img`,{alt:e.name,src:e.dataUrl}),(0,z.jsx)(`button`,{"aria-label":l(`composer.sentImageAlt`,{name:e.name}),onClick:()=>re(t=>t.filter(t=>t.id!==e.id)),type:`button`,children:(0,z.jsx)(Gm,{size:13})})]},e.id))}):null,M?(0,z.jsx)(`p`,{className:`personal-composer-error`,role:`alert`,children:M}):null,(0,z.jsxs)(`div`,{className:`personal-channel-composer`,onDragOver:e=>{[...e.dataTransfer.items].some(e=>e.kind===`file`&&e.type.startsWith(`image/`))&&e.preventDefault()},onDrop:e=>{let t=[...e.dataTransfer.files].filter(e=>e.type.startsWith(`image/`));t.length&&(e.preventDefault(),ct(t))},children:[(0,z.jsxs)(`span`,{children:[(0,z.jsx)(Up,{size:17}),e.find(e=>e.agentId===Oe)?.label??Oe]}),(0,z.jsx)(`button`,{"aria-label":l(`composer.addImage`),className:`personal-composer-attach`,disabled:j||ne.length>=fx,onClick:()=>Ce.current?.click(),title:l(`composer.attachImageHint`),type:`button`,children:(0,z.jsx)(Cm,{size:17})}),(0,z.jsx)(`input`,{accept:`image/png,image/jpeg,image/webp,image/gif`,"aria-label":l(`composer.imagePicker`),className:`personal-composer-file-input`,disabled:j||ne.length>=fx,multiple:!0,onChange:e=>void ct(e.target.files),ref:Ce,type:`file`}),(0,z.jsx)(`textarea`,{"aria-label":l(`composer.sendMessage`),onChange:e=>Me(e.target.value),onKeyDown:e=>{e.key===`Enter`&&!e.shiftKey&&!e.nativeEvent.isComposing&&(e.preventDefault(),it())},onPaste:lt,placeholder:B?l(`composer.goalPlaceholder`,{goal:B.title}):l(`composer.managerPlaceholder`),ref:xe,rows:1,value:Ae}),(0,z.jsx)(`button`,{"aria-label":l(ot?`composer.createGoal`:`composer.send`),disabled:!Ae.trim()&&ne.length===0||j,onClick:()=>void it(),title:l(ot?`composer.createGoalHint`:`composer.sendMessageHint`),type:`button`,children:(0,z.jsx)(Mm,{size:18})})]})]})})]}),sidebar:(0,z.jsx)(Zy,{attentionCount:Fe,goals:Pe,goalArchiveLoadState:n,lifecycleBusyGoalIds:oe,onRequestGoalCreate:i?void 0:qe,onRequestGoalLifecycle:i?void 0:(e,t)=>void Je(e,t),onRetryGoalArchive:t.onRetryGoalArchive||t.onRefresh?()=>void(t.onRetryGoalArchive??t.onRefresh)?.():void 0,onOpenSettings:i?void 0:()=>h({kind:`settings`}),onSelectGoal:tt,selectedGoalId:L,statusSourceControl:s},s?.activeSource.statusUrl??`/status.json`)})}function hx(e){return(e??``).replace(/\s+/gu,` `).trim()}function gx(e,t=120){let n=Array.from(e);return n.length<=t?e:`${n.slice(0,t-1).join(``)}…`}function _x(e,t,n){let r=hx(e);return!r||r===`暂无`?n?t(n):``:/refresh-state|latest_run|latest run-derived/iu.test(r)?t(`projection.refreshState`):/first read-only adapter tick|read-only adapter/iu.test(r)?t(`projection.firstReadOnlyAdapterCheck`):/todo update recorded for/iu.test(r)?t(`projection.todoStatusUpdated`):/^(loopx|python3|npm|git|run)\s|\s--[a-z0-9-]+|\b[a-z]+_[a-z_]+\b/iu.test(r)?t(n??`projection.agentPreparingNextStep`):gx(r)}function vx(e,t){return t({advancing:`projection.agentAdvancingGoal`,idle:`projection.agentIdle`,needs_you:`projection.agentNeedsDecision`,stopped:`projection.agentStopped`,waiting_external:`projection.agentWaitingExternal`}[e])}function yx({eventCount:e,hasArtifact:t,hasLatestValidation:n},r){return{label:r(n?`projection.latestValidation`:`projection.latestRun`),metadata:e>0?r(`projection.events24h`,{count:e}):r(t?`projection.runEvidenceAvailable`:`projection.publicSafeProjection`)}}var bx=`/status.json`,xx=`loopx-status-source-catalog-v1`,Sx={id:`local`,kind:`local`,label:`本机`,readOnly:!1,statusUrl:bx};function Cx(e,t){let n=Xm(e,t).source;if(!n||!n.isLoopback||n.isRelative)return{error:`SSH 隧道来源必须使用显式的 localhost、127.0.0.1 或 ::1 URL。`};let r=new URL(n.url,t);return[`http:`,`https:`].includes(r.protocol)?{url:r.toString()}:{error:`状态来源只支持 HTTP 或 HTTPS。`}}function wx(e){let t=2166136261;for(let n of e)t^=n.codePointAt(0)??0,t=Math.imul(t,16777619);return`ssh-${(t>>>0).toString(36)}`}function Tx(e,t){if(!e||typeof e!=`object`||Array.isArray(e))return null;let n=e;if(n.kind!==`ssh_tunnel`||typeof n.label!=`string`||typeof n.statusUrl!=`string`)return null;let r=n.label.trim(),i=Cx(n.statusUrl,t);return!r||r.length>48||!(`url`in i)?null:{id:wx(i.url),kind:`ssh_tunnel`,label:r,readOnly:!0,statusUrl:i.url}}function Ex(){return{schemaVersion:1,sources:[Sx]}}function Dx(e,t){try{let n=e.getItem(xx);if(!n)return Ex();let r=JSON.parse(n);if(r.schemaVersion!==1||!Array.isArray(r.sources))return Ex();let i=new Set([Sx.statusUrl]);return{schemaVersion:1,sources:[Sx,...r.sources.flatMap(e=>{let n=Tx(e,t);return!n||i.has(n.statusUrl)?[]:(i.add(n.statusUrl),[n])})]}}catch{return Ex()}}function Ox(e,t){e.setItem(xx,JSON.stringify({schemaVersion:1,sources:t.sources.filter(e=>e.kind===`ssh_tunnel`)}))}function kx(e,t,n){let r=t.label.trim();if(!r)return{error:`请填写来源名称。`};if(r.length>48)return{error:`来源名称不能超过 48 个字符。`};let i=Cx(t.statusUrl,n);if(!(`url`in i))return i;if(e.sources.some(e=>e.statusUrl===i.url))return{error:`这个状态 URL 已经在来源目录中。`};let a={id:wx(i.url),kind:`ssh_tunnel`,label:r,readOnly:!0,statusUrl:i.url};return{catalog:{...e,sources:[...e.sources,a]},source:a}}function Ax(e,t){return{...e,sources:e.sources.filter(e=>e.kind===`local`||e.id!==t)}}function jx(e,t,n){if(!t.trim()||Xm(t,n).source?.isRelative)return Sx;let r=t.trim();try{r=new URL(r,n).toString()}catch{return null}return e.sources.find(e=>e.statusUrl===r)??null}function Mx(e,t,n){return jx(e,t,n)||(Xm(t,n).source?.isRelative?Sx:{id:`temporary`,kind:`ssh_tunnel`,label:`临时来源`,readOnly:!0,statusUrl:t.trim()})}function Nx(e,t,n,r){return Mx(e,t??n,r)}var Px={delete:`删除`,deploy:`部署`,merge:`合并`,payment:`付款`,release:`发布`};function Fx(e,t,n){let r=t.replace(/\s+/gu,` `).trim().toLowerCase(),i=n.target.replace(/\s+/gu,` `).trim().toLowerCase();return!i||!r.includes(i)?null:{actionKind:`goal.update`,context:{goal_id:e,kind:`goal`,natural_language:t,semantic_proposal:{operation:n.operation,target:n.target}},idempotencyKey:`workspace-semantic-protected-${e}-${Date.now().toString(36)}`,normalizedParameters:{goal_id:e,status:`operator_gate_requested`},summary:`请求受保护操作:${Px[n.operation]} · ${n.target}`}}var Ix=bx;async function Lx(e){let t=await fetch(e,{cache:`no-store`,signal:AbortSignal.timeout(3e4)});if(!t.ok)throw Error(`HTTP ${t.status} while loading ${e}`);return vp(await t.json())}function Rx(e,t){if(t?.controller_readiness?.decision_advisor_ready||t?.controller_readiness?.write_controller_ready)return`controller_ready`;if(t?.controller_readiness)return`controller_gated`;if(t?.human_reward)return`reward_judged`;if(t?.operator_gate?.decision===`approve`)return`operator_approved`;if(t?.operator_gate)return`operator_gated`;let n=e||t?.classification||``;return n===`connected_without_run`?`connected`:n===`read_only_project_map`||t?.project_map?`mapped`:n===`state_refreshed`?`refreshed`:n&&n!==`no_status`?`adapter_inspected`:`registered`}function zx(e,t){let n=new Map(t.map(e=>[e.goal_id,e])),r=new Set,i=e.map(e=>{r.add(e.id);let t=n.get(e.id),i=e.latest_runs[0],a=t?.lifecycle_phase??e.lifecycle_phase??i?.lifecycle_phase??Rx(t?.status??i?.classification??e.status,i),o=t?.lifecycle_flags?.length?t.lifecycle_flags:e.lifecycle_flags?.length?e.lifecycle_flags:i?.lifecycle_flags?.length?i.lifecycle_flags:[a];return{goal:e,queueItem:t,latestRun:i,status:t?.status??i?.classification??e.status??`no_status`,waitingOn:t?.waiting_on??`clear`,severity:t?.severity??`clear`,lifecyclePhase:a,lifecycleFlags:o}});for(let e of t)r.has(e.goal_id)||i.push({goal:{activation_state:e.activation_state,id:e.goal_id,status:e.status,display_name:e.goal_id,latest_runs:[],lifecycle_flags:[e.lifecycle_phase??`registered`],registry_member:!0,legacy_runtime_goal:!1,index_exists:!1,raw_index_records:0,unique_runs:0},queueItem:e,status:e.status,waitingOn:e.waiting_on,severity:e.severity,lifecyclePhase:e.lifecycle_phase??`registered`,lifecycleFlags:e.lifecycle_flags??[`registered`]});return i}function Bx(e){return(e??``).replace(/\s+/g,` `).trim()}function Vx(e,t=132){let n=Bx(e);return n.length<=t?n:`${n.slice(0,Math.max(0,t-1))}…`}function Hx(e){let t=new Map;for(let n of e?.goals??[])t.set(n.goal_id,n);return t}function Ux(e,t){return e===void 0||t===void 0?void 0:e+t}function Wx(e,t){if(!e)return null;let n=t===`user`?e.queueItem?.project_asset?.user_todos:e.queueItem?.project_asset?.agent_todos;if(n?.items?.length)return{done_count:n.done??n.items.filter(e=>e.done).length,items:n.items,open_count:n.open??n.items.filter(e=>!e.done).length,total_count:n.total??n.items.length};let r=t===`user`?e.queueItem?.user_todos:e.queueItem?.agent_todos;return r?.items?.length?r:null}function Gx(e){return e?.items.find(e=>!e.done)}function Kx(e,t,n=`todos`){return e?.items?.length?{advancement_done_count:e.advancement_done_count??t?.advancement_done_count,done_count:e.done??e.items.filter(e=>e.done).length,items:e.items,open_count:e.open??e.items.filter(e=>!e.done).length,total_count:e.total??e.items.length}:t??null}function qx(e){return e?.queueItem?.project_asset?.quota?.state??e?.queueItem?.quota?.state??e?.goal.quota?.state??`waiting`}function Jx(e,t,n){let r=[];for(let t of e){let e=Wx(t,`agent`);for(let n of e?.items??[])r.push({goalId:t.goal.id,role:`agent`,todo:n})}let i=new Map;for(let e of r){let t=e.todo.claimed_by||`codex`,n=i.get(t)??[];n.push(e),i.set(t,n)}let a=new Map((n?.agents??[]).map(e=>[e.agent_id,e]));return Array.from(new Set([...i.keys(),...a.keys()])).map(e=>{let t=i.get(e)??[],n=a.get(e),r=Array.from(new Set([...t.map(e=>e.goalId),n?.current_todo?.goal_id,...n?.goal_ids??[]].filter(Boolean))),o=(t.filter(e=>!e.todo.done)[0]??t[0])?.goalId??n?.current_todo?.goal_id??r[0]??``,s=n?.last_activity_at??null;return{agentId:e,claimedTodos:t,currentTodo:n?.current_todo??null,evidenceRefs:[],goalIds:r,handoffNote:null,lastActivity:s,nextSafeAction:n?.next_action?.trim()||`Inspect status projection before taking work`,primaryGoalId:o,quotaHints:[],staleClaimHint:null,status:{label:`可用`,summary:`正常运行`,variant:`success`},workspaceRef:null}})}function Yx(e){return e?.map(e=>({dataUrl:e.data_url,id:e.id,mimeType:e.mime_type,name:e.name,size:e.size}))}var Xx=`loopx.personal-agent-selection.v1`;function Zx(){if(typeof window>`u`)return{};try{let e=JSON.parse(window.localStorage.getItem(Xx)??`{}`);return!e||typeof e!=`object`||Array.isArray(e)?{}:Object.fromEntries(Object.entries(e).filter(e=>typeof e[0]==`string`&&typeof e[1]==`string`))}catch{return{}}}var Qx={需修复:`danger`,等你:`warning`,等待条件:`info`,推进中:`success`,安静运行:`neutral`,已停止:`neutral`,已完成:`neutral`};function $x(e,t){return Bx(t)||e.replace(/^loopx[-_]/i,`LoopX `).split(/[-_]+/).filter(Boolean).map((e,t)=>t===0?`${e.slice(0,1).toUpperCase()}${e.slice(1)}`:e).join(` `)}function eS(e){return e.split(/\r?\n/u).filter(e=>!/^\s*GOAL_(STATUS|PROGRESS)\s*:/u.test(e)).map(e=>/^\s*GOAL_EVIDENCE\s*:/u.test(e)?e.replace(/^\s*GOAL_EVIDENCE\s*:/u,`验证依据:`):/^\s*NEXT_ACTION\s*:/u.test(e)?e.replace(/^\s*NEXT_ACTION\s*:/u,`下一步:`):e).join(` -`).trim()}function tS(e,t){return[`agent`,`assistant`].includes(e.trim().toLowerCase())&&t.trim().length>0}function nS(e){let t=e.toLowerCase();return t.includes(`codex`)?`Codex`:t.includes(`claude`)?`Claude Code`:t.includes(`trae`)?`Trae CLI Agent`:t.includes(`coco`)?`Coco Agent`:$x(e)}function rS(e){let t=e.toLowerCase();return t.includes(`codex`)?`代码与项目执行`:t.includes(`claude`)?`复杂分析与长任务`:t.includes(`openai`)||t.includes(`anthropic`)?`管家问答 · 无工具`:t.includes(`trae`)?`前端与交互实现`:t.includes(`coco`)?`通用任务`:`已发现的项目 Agent`}function iS(e,t){let n=e.project_asset;return t===`user`?Kx(n?.user_todos,e.user_todos,`project_asset.user_todos`):Kx(n?.agent_todos,e.agent_todos,`project_asset.agent_todos`)}function aS(e){return Vx(e.title??e.text,112)}function oS(e,t){return{resumeWhen:e.resume_when??null,claimedBy:e.claimed_by??null,done:e.status!==`deferred`&&e.done,evidence:e.evidence?Vx(e.evidence,96):null,index:e.index,priority:e.priority??null,status:e.status??null,taskClass:e.task_class??null,taskDomain:e.task_domain??null,text:aS(e),todoId:e.todo_id?.trim()||`${t.goal.id}:agent:${e.index}`}}function sS(e){let t=e.queueItem?.agent_todos,n=t?.items??e.queueItem?.project_asset?.agent_todos?.items??[],r=new Map(n.map(t=>[t.todo_id?.trim()||`${e.goal.id}:agent:${t.index}`,t]));for(let n of t?.deferred_items??[]){let t=n.todo_id?.trim()||`${e.goal.id}:agent:${n.index}`;r.has(t)||r.set(t,n)}return[...r.values()]}function cS(e){return sS(e).map(t=>oS(t,e))}function lS(e,t,n){let r=new Map;for(let n of e.todo_index?.items??[]){if(n.goal_id!==t.goal.id||n.role!==`agent`)continue;let e=oS(n,t);r.set(e.todoId,e)}for(let e of n)r.has(e.todoId)||r.set(e.todoId,e);let i=new Map;for(let e of r.values()){if(e.done||e.taskClass!==`advancement_task`)continue;let t=e.taskDomain?.trim();t&&i.set(t,(i.get(t)??0)+1)}return[...i].map(([e,t])=>({domain:e,matchingTodoCount:t}))}function uS(e,t){return{claimedBy:e.claimed_by??null,done:e.status===`done`||e.status===`completed`,index:-1,priority:e.priority??null,status:e.status??null,taskClass:e.task_class??null,text:Vx(e.title,112),todoId:e.todo_id?.trim()||`${t.goal.id}:agent:${e.claimed_by??`unknown`}:current`}}function dS(e,t,n){let r=new Map(e.map(e=>[e.todoId,e]));for(let e of t){let t=e.currentTodo;if(!t||t.goal_id!==n.goal.id)continue;let i=uS(t,n);r.has(i.todoId)||r.set(i.todoId,i)}return[...r.values()]}function fS(e){let t=e.queueItem?.project_asset?.agent_todos,n=e.queueItem?.agent_todos,r=sS(e),i=t?.advancement_done_count??n?.advancement_done_count??t?.done??n?.done_count??null,a=r.filter(e=>e.done&&e.status!==`deferred`).length,o=Math.max(i??0,a),s=new Set(r.map(e=>e.todo_id?.trim()).filter(e=>!!e)),c=(t?.recent_completed_advancement_items??[]).filter(e=>!e.todo_id?.trim()||!s.has(e.todo_id.trim())).map(t=>oS(t,e)),l=r.find(e=>!e.done);return{doneTodoCount:o,nextTodoText:Bx(t?.next??``)||(l?Bx(l.title??``)||Bx(l.text??``):``)||null,recentCompleted:c}}function pS(e,t){let n=Bx(e);return n?/\b(state_file|registry_goal|authority_sources|source_registry)\b|\b[a-z_]+\s+\d+\/\d+/i.test(n)?t(`projection.goalVerified`):_x(n,t,`projection.validationRecorded`):``}function mS(e,t=4){if(e.length<=t)return e;let n=e.findIndex(e=>!e.done);if(n<0)return e.slice(-t);let r=Math.max(0,Math.min(n-2,e.length-t));return e.slice(r,r+t)}function hS(e,t,n){let r=t.queueItem?.project_asset?.latest_validation,i=t.latestRun,a=e.event_ledger_summary?.goals.find(e=>e.goal_id===t.goal.id);if(!r&&!i&&!a)return null;let o=[pS(r?.summary,n),_x(i?.health_check,n),_x(i?.recommended_action,n)].find(e=>e!==``&&e!==`暂无`)??n(`projection.runRecorded`),s=yx({eventCount:a?.events_24h??0,hasArtifact:!!(i?.json_exists||i?.markdown_exists),hasLatestValidation:!!r},n);return{generatedAt:r?.generated_at??i?.generated_at??a?.latest_event_at??``,label:s.label,metadata:s.metadata,runId:i?`${t.goal.id}:${i.generated_at}`:null,safePreview:[o,s.metadata].filter(Boolean).join(` -`),summary:o,todoId:t.queueItem?.project_asset?.agent_todos?.items.find(e=>!e.done)?.todo_id??null}}function gS(e){return[e.status,e.goal.status,e.latestRun?.classification,e.lifecyclePhase].filter(Boolean).some(e=>/(^|[_\s-])(done|complete|completed|finished|terminal|closed|success)([_\s-]|$)/i.test(e??``))}function _S(e,t){return e.global_registry?.findings?.find(e=>e.severity===`high`&&(e.goal_id===t.goal.id||e.goal_ids.includes(t.goal.id)))}function vS(e){return[e.status,e.goal.status,e.latestRun?.classification,e.lifecyclePhase].filter(Boolean).some(e=>/(^|[_\s-])(failure|failed|error|broken|unhealthy|blocked[_\s-]?health|health[_\s-]?blocked)([_\s-]|$)/i.test(e??``))}function yS(e,t){let n=t.queueItem?.stale_latest_run_warning;return t.severity===`high`||!!_S(e,t)||!!(n?.requires_refresh_state||n?.severity===`high`)||vS(t)}function bS(e,t){let n=_S(e,t);return t.queueItem?.stale_latest_run_warning?.recommended_action??t.queueItem?.stale_latest_run_warning?.reason??n?.recommended_action??n?.message??t.queueItem?.recommended_action??t.latestRun?.recommended_action??null}function xS(e){let t=e.latestRun?.operator_gate,n=t?.decision?.trim().toLowerCase()??``,r=new Set([`approve`,`approved`,`reject`,`rejected`,`defer`,`deferred`,`cancel`,`cancelled`]),i=[e.queueItem?.recommended_action,e.latestRun?.recommended_action].filter(Boolean).join(` `),a=/(?:等待|需要)(?:用户|你|owner).{0,24}(?:批准|确认|授权|补充|选择|决定)|(?:批准|确认|授权).{0,16}(?:后|才能|方可)/i.test(i);return!!(t&&!r.has(n))||e.lifecyclePhase===`operator_gated`&&!r.has(n)||a}function SS(e,t){let n=e.latestRun?.operator_gate;return _x(n?.operator_question??n?.reason_summary??n?.follow_up??e.queueItem?.recommended_action??e.latestRun?.recommended_action,t,`projection.confirmAgentDecision`)}function CS(e,t){if(t.goal.activation_state===`stopped`)return`已停止`;let n=Wx(t,`user`),r=Wx(t,`agent`),i=!!Gx(n),a=!!Gx(r);return[`user_or_controller`,`controller`].includes(t.waitingOn)||i||xS(t)?`等你`:yS(e,t)?`需修复`:t.waitingOn===`external_evidence`?`等待条件`:qx(t)===`eligible`||a?`推进中`:gS(t)?`已完成`:`安静运行`}function wS(e,t,n,r){if(n===`已停止`)return vx(`stopped`,r);if(n===`需修复`)return _x(bS(e,t),r,`projection.statusRefreshNeeded`);if(n===`等你`)return vx(`needs_you`,r);if(n===`推进中`){let e=[(Wx(t,`agent`)?.items??[]).filter(e=>!e.done).flatMap(e=>[e.title,e.text]).map(e=>Bx(e)).find(e=>e!==``&&e!==`暂无`),t.queueItem?.recommended_action,t.latestRun?.recommended_action].map(e=>Bx(e)).find(e=>e!==``&&e!==`暂无`);return e?_x(e,r,`projection.agentAdvancingGoal`):vx(`advancing`,r)}return vx(n===`等待条件`?`waiting_external`:`idle`,r)}function TS(e,t){return t.some(t=>e.includes(t))}function ES(e){return TS(e,[`我现在该做什么`,`该做什么`,`下一步`,`哪些 Goal 在等我`,`哪些 Goal 正在等我`,`等我`,`优先处理`,`全局待办`,`Agent 在做什么`,`哪些 Goal 需要我`])}function DS(e,t,n){if(t.goals.some(e=>e.activationState===`active`&&e.loadState))return{text:`Goal 状态尚未全部加载,暂不能给出完整统计。可先打开已加载的 Goal,失败项可重试。`,lines:[]};if(TS(n,[`Agent`,`agent`,`推进`,`在做`])){let e=t.goals.filter(e=>![`安静运行`,`已完成`,`已停止`].includes(e.state)),n=(e.length>0?e:t.goals).slice(0,3);return n.length===0?{text:`当前状态里还没有 Goal 可供汇总。`,lines:[]}:{text:e.length>0?`Agent 当前关注这些 Goal:`:`当前 Goal 都比较安静:`,lines:n.map(e=>`${e.title} · ${e.state} · ${e.agentSentence}`)}}if(TS(n,[`现在`,`下一步`,`我该`,`该做什么`,`优先处理`])){let e=t.userTodos[0];if(e)return{text:e.blocking?`先处理「${$x(e.goalId)}」:${e.text}`:`当前最先处理「${$x(e.goalId)}」:${e.text}`,lines:[]};let n=t.goals.find(e=>e.state===`需修复`);if(n)return{text:`没有待办,但这个 Goal 需要先修复。`,lines:[`${n.title} · ${n.agentSentence}`]};let r=t.goals.find(e=>e.state===`推进中`);return r?{text:`目前不需要你介入,Agent 正在推进。`,lines:[`${r.title} · ${r.agentSentence}`]}:{text:`当前系统很安静,没有需要你立即处理的事项。`,lines:[]}}if(TS(n,[`等我`,`阻塞`,`需要我`,`全局待办`]))return t.userTodos.length===0?{text:`目前没有 Goal 在等你,开放用户待办为 0。`,lines:[]}:{text:`有 ${t.userTodos.length} 项开放用户待办,阻塞项优先:`,lines:t.userTodos.slice(0,3).map(e=>`${$x(e.goalId)} · ${e.blocking?`阻塞`:`待处理`} · ${e.text}`)};if(TS(n,[`状态`,`异常`,`修复`,`健康`])){let n=t.systemHealth?!t.systemHealth.ok:!e.ok||!e.contract?.ok||!e.global_registry?.ok||(e.global_registry?.summary?.high??0)>0,r=t.goals.filter(e=>e.state===`需修复`),i=r.slice(0,n?2:3).map(e=>`${e.title} · ${e.agentSentence}`);return n&&i.push(`全局状态、契约或注册表健康检查未通过,请进入管理页检查。`),i.length===0?{text:`当前没有发现 Goal 级或全局健康异常。`,lines:[]}:{text:r.length>0?`当前需要关注这些健康问题:`:`Goal 状态正常,但全局健康需要检查:`,lines:i}}return{text:`当前管家支持三类问题:下一步、等待你的事项、Agent 与健康状态。`,lines:[`问“我现在该做什么?”`,`问“哪些 Goal 在等我?”`,`问“Agent 在做什么?”或当前健康状态`]}}function OS(e,t,n,r=!1){let i=new Map(t.map(e=>[e.goal.id,e])),a=new Set(e.run_history.goals.filter(e=>e.activation_state===`stopped`).map(e=>e.id)),o=Hx(e.usage_summary),s=Jx(t,e.todo_index,e.agent_management_projection),c=e.attention_queue.items.flatMap((e,t)=>{if(a.has(e.goal_id))return[];let n=[`user_or_controller`,`controller`].includes(e.waiting_on);return(iS(e,`user`)?.items??[]).filter(e=>!e.done).map((r,i)=>({actionKind:r.action_kind??null,blocking:n,goalId:e.goal_id,sourceOrder:t,taskClass:r.task_class??null,text:aS(r),todoId:r.todo_id?.trim()||`${e.goal_id}:user:${r.index}`,todoOrder:i,updatedAt:r.updated_at??null}))}),l=new Set(c.map(e=>e.goalId)),u=t.flatMap((t,r)=>a.has(t.goal.id)||l.has(t.goal.id)||!xS(t)?[]:[{actionKind:`gate.resolve`,blocking:!0,goalId:t.goal.id,sourceOrder:e.attention_queue.items.length+r,taskClass:`user_gate`,text:SS(t,n),todoId:`${t.goal.id}:operator-gate`,todoOrder:0,updatedAt:t.latestRun?.operator_gate?.recorded_at??t.latestRun?.generated_at??null}]),d=[...c,...u].sort((e,t)=>Number(t.blocking)-Number(e.blocking)||e.sourceOrder-t.sourceOrder||e.todoOrder-t.todoOrder),f=e.run_history.goals.flatMap(t=>{if(t.registry_member===!1)return[];let a=i.get(t.id);if(!a)return[];let c=CS(e,a),l=d.find(e=>e.goalId===t.id),u=l?.text??null,f=fS(a),p=t.coordination?.registered_agents??[],m=new Set(p),h=[...s.filter(e=>e.goalIds.includes(t.id)&&!/unassigned|unknown/i.test(e.agentId)&&(m.size===0||m.has(e.agentId))&&(e.currentTodo?.goal_id===t.id||e.claimedTodos.some(e=>e.goalId===t.id)))].sort((e,t)=>(t.lastActivity??``).localeCompare(e.lastActivity??``)),g=new Set(h.map(e=>e.agentId)),_=[...h.map(e=>({agentId:e.agentId,label:e.agentId,lastActivityAt:e.lastActivity,state:e.status.label})),...p.filter(e=>!g.has(e)).map(e=>({agentId:e,label:e,lastActivityAt:null,state:`registered`}))],v=h[0],y=dS(cS(a),h,a),b=[f.nextTodoText,a.queueItem?.recommended_action,a.latestRun?.recommended_action,wS(e,a,c,n)].map(e=>_x(e,n)).find(e=>e!==``&&e!==`暂无`)??n(`projection.nextUpdatePending`);return[{activationState:t.activation_state,agentId:v?.agentId??p[0]??`codex`,agentLaneCount:_.length,agentLanes:_,agentLabel:v?.agentId,agentSentence:wS(e,a,c,n),agentTodos:[...y,...f.recentCompleted],doneTodoCount:f.doneTodoCount,goalId:t.id,latestActivity:a.latestRun?.generated_at??``,needsYou:u,needsYouActionKind:l?.actionKind??null,needsYouBlocking:l?.blocking??!1,needsYouTaskClass:l?.taskClass??null,needsYouTodoId:l?.todoId??null,nextSentence:b,runEvidence:hS(e,a,n),state:c,...r?{subagentExecution:{allowedDomains:t.spawn_policy?.allowed_domains??[],domainCandidates:lS(e,a,y),enabled:t.spawn_policy?.mode===`multi_subagent`&&t.spawn_policy.spawn_allowed===!0&&t.spawn_policy.max_children>0,maxChildren:t.spawn_policy?.max_children??0}}:{},title:$x(t.id,t.display_name),usage:(()=>{let e=o.get(t.id);return e?{costUsd24h:e.cost_usd_24h,costUsd7d:e.cost_usd_7d,durationMs24h:e.duration_ms_24h,durationMs7d:e.duration_ms_7d,tokens24h:Ux(e.input_tokens_24h,e.output_tokens_24h),tokens7d:Ux(e.input_tokens_7d,e.output_tokens_7d)}:null})()}]}),p=[];if(e.ok||p.push(`状态载荷未标记为正常 (payload.ok === false)`),e.contract&&!e.contract.ok){let t=e.contract.summary,n=t?`${t.errors} 项错误 / ${t.warnings} 项警告`:e.contract.errors?.[0]||`请检查控制面契约`;p.push(`契约检查未通过: ${n}`)}if(e.global_registry){e.global_registry.ok||p.push(`注册表状态异常: ${e.global_registry.summary.high} 项高危`);for(let t of e.global_registry.findings||[])t.severity===`high`&&p.push(`[${t.kind}] ${t.message}`)}let m=e.decision_freshness_summary?.summary?.stale_count?`${e.decision_freshness_summary.summary.stale_count} 项决策状态已过期`:null,h=p.length===0&&!m,g={ok:h,summary:h?`所有控制面契约与注册表检查均正常`:`发现 ${p.length+ +!!m} 项系统健康关注点`,issues:p,freshnessWarning:m};return{blockingTodoCount:d.filter(e=>e.blocking).length,goalNotifications:(e.goal_channel_notification_projection?.goals??[]).map(e=>({goalId:e.goal_id,configured:e.configured,enabled:e.enabled,humanGateAutoNotifyEnabled:e.human_gate_auto_notify_enabled,lastNotifiedAt:e.last_notified_at??null,receiptCount:e.receipt_count,targetRef:e.target_ref??null})),goals:f,openUserTodoCount:d.length,systemHealth:g,userTodos:d,visibleUserTodos:d.slice(0,5),workers:(e.agent_management_projection?.agents??[]).map(e=>({agentId:e.agent_id,currentTodoGoalId:e.current_todo?.goal_id??null,currentTodoText:e.current_todo?.title?Vx(e.current_todo.title,96):null,lastActivityAt:e.last_activity_at??null,state:e.state??null}))}}function kS({goalArchiveLoadState:e,isLoading:t,onGoalActivationStateChange:n,onGoalDeleted:r,onSelectGoal:i,onReconcileStatus:a,onRefresh:o,onRetryGoalArchive:s,payload:c,progress:l,rows:u,selectedGoalId:d,statusSourceControl:f,theme:p,toggleTheme:m}){let h=f.activeSource.readOnly,{t:g}=Ji(),[_,v]=(0,R.useState)([]),[y,b]=(0,R.useState)(!1),x=(0,R.useMemo)(()=>{let e=OS(c,u,g,y);if(!l)return e;let t=Object.values(l.snapshots).map(e=>OS(e,zx(e.run_history.goals,e.attention_queue.items),g,y)),n=new Map(t.flatMap(e=>e.goals).map(e=>[e.goalId,e])),r=e.goals.map(e=>n.get(e.goalId)??{...e,loadError:l.errors[e.goalId],loadState:l.errors[e.goalId]?`error`:`loading`,agentId:``,agentSentence:``,nextSentence:``,subagentExecution:void 0}),i=t.flatMap(e=>e.userTodos),a=r.some(e=>e.activationState===`active`&&e.loadState),o=[...new Set(t.flatMap(e=>e.systemHealth?.issues??[]))];return{...e,goals:r,userTodos:i,visibleUserTodos:i.slice(0,5),openUserTodoCount:i.length,blockingTodoCount:i.filter(e=>e.blocking).length,workers:[...new Map(t.flatMap(e=>e.workers??[]).map(e=>[e.agentId,e])).values()],goalNotifications:t.flatMap(e=>e.goalNotifications??[]),systemHealth:a||t.length===0?void 0:{ok:t.every(e=>e.systemHealth?.ok),issues:o,summary:o.length?`发现 ${o.length} 项系统健康关注点`:`状态检查已完成`,freshnessWarning:t.map(e=>e.systemHealth?.freshnessWarning).filter(Boolean).join(`;`)||null}}},[c,u,l,y,g]),S=x.goals.find(e=>e.goalId===d)??null,C=l?.snapshots[d]??c,[w,T]=(0,R.useState)(null),[E,D]=(0,R.useState)(null),[O,k]=(0,R.useState)(!1),ee=x.goals.some(e=>e.activationState===`active`&&e.loadState===`loading`)?`loading`:x.goals.map(e=>`${e.goalId}:${e.agentId}`).join(`|`),A=S?.goalId??`manager`;x.goals.some(e=>e.activationState===`active`&&e.loadState)||(x.systemHealth?!x.systemHealth.ok:!c.ok)||x.openUserTodoCount>0&&`${x.openUserTodoCount}${x.blockingTodoCount}`;let j=_.length>0?_.map(e=>({agentId:e.agent_id,adapterKind:e.adapter_kind,available:e.available,capability:rS(e.agent_id),interrupt:e.interrupt,label:e.display_name,location:e.location,resume:e.resume,source:e.source,statusLabel:e.available?`可用`:`需要配置`,streaming:e.streaming,toolCalls:e.tool_calls,trustScope:e.trust_scope})):[{agentId:`codex`,available:!0,capability:rS(`codex`),label:`Codex`,statusLabel:`正在检测`}],te=[...j,{agentId:`status-only`,available:!0,capability:`不调用模型`,adapterKind:`status_projection`,interrupt:!1,label:`仅查状态`,resume:!0,statusLabel:`只读`,streaming:!1,toolCalls:!1,trustScope:`read_only`}],ne=j.find(e=>e.label===`Codex`&&e.available)?.agentId??j.find(e=>e.available)?.agentId??`status-only`,[re,M]=(0,R.useState)(Zx),N=nh(te,re[A]??ne,ne),[ie,ae]=(0,R.useState)(!1),[oe,P]=(0,R.useState)(!1),[F,I]=(0,R.useState)(`chat`),[se,ce]=(0,R.useState)(``),[le,ue]=(0,R.useState)({}),[de,fe]=(0,R.useState)({}),[pe,me]=(0,R.useState)(null),[he,ge]=(0,R.useState)({}),[_e,ve]=(0,R.useState)([]),[ye,be]=(0,R.useState)(null),[xe,Se]=(0,R.useState)({}),Ce=(0,R.useRef)(1),we=(0,R.useRef)(1),Te=(0,R.useRef)(new Map),Ee=(0,R.useRef)(new Set),De=(0,R.useRef)(new Map),L=(0,R.useRef)(new Map),Oe=(0,R.useRef)(new Set),ke=(0,R.useRef)(new Set),Ae=(0,R.useRef)(null),je=(0,R.useRef)(null),Me=(0,R.useRef)(null),Ne=(0,R.useRef)(null);(0,R.useRef)(null);let Pe=le[A]??[];de[A];let Fe=S?x.userTodos.filter(e=>e.goalId===S.goalId):x.userTodos,Ie=S?.agentTodos??[];mS(Ie,S?.needsYou?3:4);let B=Ie.filter(e=>e.done).length,Le=Ie.length>0?`${B}/${Ie.length}`:`暂无计划`,Re=S?{...x,blockingTodoCount:Fe.filter(e=>e.blocking).length,goals:[S],openUserTodoCount:Fe.length,userTodos:Fe,visibleUserTodos:Fe}:x;(0,R.useEffect)(()=>{let e=Ym(f.activeSource.statusUrl,window.location.href),t=e.source?$m(C,e.source):null;if(!S||!t?.indexUrl||!t.detailUrl){T(null),D(null),k(!1);return}let{detailUrl:n,indexUrl:r}=t,i=!1;return T(null),D(null),k(!0),eh(r,S.goalId).then(async e=>{let t=e.items[0]?.detail_ref;return t?th(n,t):null}).then(e=>{i||T(e)}).catch(e=>{i||D(yp(e))}).finally(()=>{i||k(!1)}),()=>{i=!0}},[C,S?.goalId,f.activeSource.statusUrl]);function V(e,t){ge(n=>{if(t===null){let t={...n};return delete t[e],t}return{...n,[e]:t}})}(0,R.useEffect)(()=>{if(h){v([]),b(!1);return}let e=!1;return Oh().then(t=>{e||(v(t.adapters??[]),b(t.goal_subagent_configuration===`preview_locked`))}).catch(()=>{e||b(!1)}),()=>{e=!0}},[h]),(0,R.useEffect)(()=>{try{window.localStorage.setItem(Xx,JSON.stringify(re))}catch{}},[re]),(0,R.useEffect)(()=>{if(h||!N.available)return;let e=A,t=`${e}:${N.agentId}`,n=S?`goal`:`manager`,r=S?`goal.${S.goalId}`:`manager`,i=S?.goalId??x.goals[0]?.goalId??``,a=!1,o=null,s=null;return(async()=>{try{let c=await Ph({agentId:N.agentId,channelId:r,goalId:S?.goalId});if(a||(ue(t=>(t[e]?.length??0)>0?t:{...t,[e]:c.messages.map(e=>({agentLabel:e.role===`user`?void 0:N.label,attachments:Yx(e.attachments),id:Ce.current++,lines:[],role:e.role===`user`?`user`:`assistant`,sourceLabel:e.role===`user`?void 0:e.role===`error`?`本地会话记录`:`恢复的 ${N.label} 会话`,text:e.role===`user`?e.text:eS(e.text)}))}),N.agentId===`status-only`))return;let l=c.sessions[0];if(s=l?.session_id??null,l&&!l.resumable){Ee.current.add(t),V(e,{agentId:N.agentId,resumable:!1,sessionId:l.session_id,status:`resume_failed`});return}let u=l?.goal_id??i;if(!u)return;let d=await Ah(u,N.agentId,`resume_latest`,n);if(a)return;Te.current.set(t,d.session_id);let f=c.snapshots.find(e=>e.session.session_id===d.session_id),p=f?.session.active_turn_id??``;if(V(e,{agentId:N.agentId,resumable:!0,sessionId:d.session_id,status:p?`running`:`ready`,turnId:p||void 0}),Ee.current.delete(t),!p)return;let m=`${d.session_id}:${p}`;if(ke.current.has(m))return;ke.current.add(m),De.current.set(e,p),V(e,{agentId:N.agentId,resumable:!0,sessionId:d.session_id,status:`running`,turnId:p}),me(e),o=new AbortController,L.current.set(e,o);let h=``,g=ze(e,{activity:[`正在恢复进行中的 Agent 回合`],agentLabel:N.label,lines:[],pending:!0,sourceLabel:`恢复的 ${N.label} 会话`,text:``});try{let t=await Vh(d.session_id,p,{signal:o.signal,onDelta:t=>{h+=t,Be(e,g,{text:h})},onActivity:t=>{ue(n=>({...n,[e]:(n[e]??[]).map(e=>e.id===g?{...e,activity:[...new Set([...e.activity??[],t])].slice(-6)}:e)}))}});if(a)return;Be(e,g,{lines:t.response.gate?[t.response.gate.summary,t.response.gate.next_action].filter(Boolean).slice(0,2):[],pending:!1,text:t.response.message||h.trim()||`${N.label} 已完成分析。`});let n=x.goals.find(e=>e.goalId===f?.session.goal_id)??S??x.goals[0]??null;if(n&&t.response.proposals.length>0){let r=t.response.proposals.map(e=>({goalId:n.goalId,id:we.current++,previewId:null,proposal:e,receiptLabel:null,state:`candidate`,statusMessage:null}));fe(t=>({...t,[e]:[...t[e]??[],...r]}))}}catch(t){if(a)return;Be(e,g,{activity:[],lines:[],pending:!1,reconnect:t instanceof _h&&t.payload.reconnectable===!0,sourceLabel:`LoopX Chat 本地后端`,text:t instanceof Error?t.message:`无法恢复进行中的 Agent 回合。`})}finally{ke.current.delete(m),De.current.get(e)===p&&De.current.delete(e),V(e,{agentId:N.agentId,resumable:!0,sessionId:d.session_id,status:`ready`}),L.current.get(e)===o&&L.current.delete(e),a||me(t=>t===e?null:t)}}catch(n){if(a)return;n instanceof _h&&n.payload.error_code===`resume_failed`&&(Ee.current.add(t),s&&V(e,{agentId:N.agentId,resumable:!1,sessionId:s,status:`resume_failed`}))}})(),()=>{a=!0,o?.abort()}},[A,x.goals[0]?.goalId,h,S?.goalId,N.agentId,N.available,N.label]),(0,R.useEffect)(()=>{if(h||S||x.goals.length===0||ee===`loading`)return;let e=!1;return Promise.all(x.goals.filter(e=>!e.loadState).map(async e=>{let t=await Mh({agentId:e.agentId,channelId:`goal.${e.goalId}`,goalId:e.goalId});return{goalId:e.goalId,session:t.sessions[0]??null}})).then(t=>{e||ge(e=>{let n={...e};for(let e of t)e.session&&(n[e.goalId]={agentId:e.session.agent_id,resumable:e.session.resumable,sessionId:e.session.session_id,status:e.session.active_turn_id?`running`:e.session.status,turnId:e.session.active_turn_id??void 0});return n})}).catch(()=>{}),()=>{e=!0}},[h,ee,S?.goalId]),(0,R.useEffect)(()=>{if(be(null),h){ve([]),Se({});return}if(!S){ve([]),Se({});return}let e=!1,t=0,n=0;ve([]),Se({});let r=async()=>{if(!e){if(document.hidden){t=window.setTimeout(()=>void r(),1e4);return}try{let t=await Mh({goalId:S.goalId});if(!e){let r=t.sessions.filter(e=>e.channel_id?.startsWith(`task.`));ve(r);let i=await Promise.allSettled(r.map(e=>jh(e.session_id)));if(!e){let e=i.some(e=>e.status===`rejected`);n=e?n+1:0,be(e?`partial`:null),Se(Object.fromEntries(i.flatMap((e,t)=>e.status===`fulfilled`?[[r[t].session_id,e.value]]:[])))}}}catch{n+=1,e||be(`offline`)}e||(t=window.setTimeout(()=>void r(),Math.min(3e4,2e3*2**Math.min(n,4))))}};return r(),()=>{e=!0,window.clearTimeout(t)}},[h,S?.goalId]),(0,R.useEffect)(()=>{if(!ie)return;let e=window.requestAnimationFrame(()=>{Ae.current?.querySelector(`[role="menuitem"]:not(:disabled)`)?.focus()});return()=>{window.cancelAnimationFrame(e),je.current?.focus()}},[ie]),(0,R.useEffect)(()=>{if(!oe)return;let e=window.requestAnimationFrame(()=>Me.current?.focus());return()=>{window.cancelAnimationFrame(e),Ne.current?.focus()}},[oe]),(0,R.useEffect)(()=>{if(!ie&&!oe)return;let e=e=>{e.key===`Escape`&&(ae(!1),P(!1))};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[ie,oe]);function ze(e,t){let n=Ce.current++;return ue(r=>({...r,[e]:[...r[e]??[],{...t,id:n,role:`assistant`}]})),n}function Be(e,t,n){ue(r=>({...r,[e]:(r[e]??[]).map(e=>e.id===t?{...e,...n}:e)}))}async function Ve(e,t){let n=e.trim();if(!n)return;let r=t&&`goalId`in t?t.goalId??`manager`:A,i=r===`manager`?Re.goals[0]??x.goals[0]??null:x.goals.find(e=>e.goalId===r)??null,a=t?.agentId?nh(te,t.agentId,ne):N,o=r===`manager`?x:i?{...x,blockingTodoCount:x.userTodos.filter(e=>e.goalId===i.goalId&&e.blocking).length,goals:[i],openUserTodoCount:x.userTodos.filter(e=>e.goalId===i.goalId).length,userTodos:x.userTodos.filter(e=>e.goalId===i.goalId),visibleUserTodos:x.userTodos.filter(e=>e.goalId===i.goalId)}:x,s=Ce.current++;if(ue(e=>({...e,[r]:[...e[r]??[],{attachments:t?.attachments,id:s,lines:[],role:`user`,text:n}]})),ce(``),me(r),r===`manager`&&ES(n)||a.agentId===`status-only`||!i){let e=DS(C,o,n),t=a.agentId===`status-only`;ze(r,{agentLabel:t?`仅查状态`:`LoopX 管家`,lines:e.lines.slice(0,3),sourceLabel:t?`LoopX 状态投影 · 仅查状态`:`LoopX 状态投影`,text:e.text}),kh({answer:[e.text,...e.lines.slice(0,3)].filter(Boolean).join(` -`),contextKind:r===`manager`?`manager`:`goal`,goalId:r===`manager`?void 0:r,question:n}).catch(()=>{}),me(null);return}let c=`${r}:${a.agentId}`,l=null;try{let e=Te.current.get(c);if(!e){let t=Ee.current.has(c)?`new`:`resume_latest`;e=(await Ah(i.goalId,a.agentId,t,r===`manager`?`manager`:`goal`)).session_id,Te.current.set(c,e),V(r,{agentId:a.agentId,resumable:!0,sessionId:e,status:`ready`}),Ee.current.delete(c)}let o=``;l=ze(r,{activity:[`正在连接 Agent`],agentLabel:a.label,lines:[],pending:!0,sourceLabel:r===`manager`?`${a.label} 管家 · 跨 Goal`:`${a.label} Agent · ${$x(i.goalId)}`,text:``});let s=(await zh(e,n,{attachments:t?.attachments,signal:(()=>{let e=new AbortController;return L.current.set(r,e),e.signal})(),onDelta:e=>{o+=e,l!==null&&Be(r,l,{text:o})},onActivity:e=>{l!==null&&ue(t=>({...t,[r]:(t[r]??[]).map(t=>t.id===l?{...t,activity:[...new Set([...t.activity??[],e])].slice(-6)}:t)}))},onPhase:(t,n)=>{De.current.set(r,n),V(r,{agentId:a.agentId,resumable:!0,sessionId:e,status:`running`,turnId:n})}})).response;if(Be(r,l,{lines:s.gate?[s.gate.summary,s.gate.next_action].filter(Boolean).slice(0,2):[],pending:!1,text:eS(s.message||o.trim())||`${a.label} 已完成分析。`}),s.proposals.length>0){let e=s.proposals.map(e=>({goalId:i.goalId,id:we.current++,previewId:null,proposal:e,receiptLabel:null,state:`candidate`,statusMessage:null}));fe(t=>({...t,[r]:[...t[r]??[],...e]}))}if(r!==`manager`&&s.protected_action){let e=Fx(r,n,s.protected_action);if(e)return e}}catch(e){if(Oe.current.delete(r)){let e={agentLabel:a.label,lines:[],pending:!1,sourceLabel:`${a.label} 会话`,text:`已中断。你可以在当前会话继续发送消息。`};l===null?ze(r,e):Be(r,l,e);return}let t=e instanceof _h?e.payload:null;t&&rh(t)&&Te.current.delete(c),t?.error_code===`resume_failed`&&(Te.current.delete(c),Ee.current.add(c),V(r,{agentId:a.agentId,resumable:!1,sessionId:he[r]?.sessionId??`resume-failed`,status:`resume_failed`}));let n=t?.gate,i=n&&typeof n==`object`?String(n.summary??``):``,o={agentLabel:a.label,lines:i?[i]:[],pending:!1,reconnect:t?.reconnectable===!0,sourceLabel:`LoopX Chat 本地后端`,text:t?.error_code===`resume_failed`?`原 ${a.label} 会话无法恢复。本地历史已经保留,请在运行详情里选择“重试恢复”或“开始新 Session”。`:e instanceof Error?e.message:`${a.label} 会话暂时不可用。`};l===null?ze(r,o):Be(r,l,o)}finally{De.current.delete(r),L.current.delete(r);let e=Te.current.get(c);e&&V(r,{agentId:a.agentId,resumable:!0,sessionId:e,status:`ready`}),me(e=>e===r?null:e)}}async function He(e){let t=e?.goalId??A,n=he[t],r=e?.agentId??n?.agentId??N.agentId,i=`${t}:${r}`,a=e?.sessionId??n?.sessionId??Te.current.get(i),o=e?.turnId??n?.turnId??De.current.get(t);if(!(!a||!o))try{Oe.current.add(t),await Rh(a,o),L.current.get(t)?.abort()}catch(e){throw Oe.current.delete(t),e}finally{De.current.delete(t),V(t,{agentId:r,resumable:!0,sessionId:a,status:`ready`}),L.current.delete(t),me(e=>e===t?null:e)}}async function Ue(e){let t=e.goalId,n=`${t}:${e.agentId}`,r=e.sessionId??he[t]?.sessionId??Te.current.get(n);if(r)try{let i=await Uh(r);Te.current.set(n,r),Ee.current.delete(n),V(t,{agentId:e.agentId,resumable:i.session.resumable,sessionId:r,status:i.session.status})}catch{V(t,{agentId:e.agentId,resumable:!1,sessionId:r,status:`resume_failed`})}}function We(e){let t=`${e.goalId}:${e.agentId}`;Te.current.delete(t),Ee.current.add(t),V(e.goalId,{agentId:e.agentId,resumable:!0,sessionId:`new-session-pending`,status:`ready`})}async function Ge(e){let t=`${e.goalId}:${e.agentId}`,n=e.sessionId??he[e.goalId]?.sessionId??Te.current.get(t);n&&n!==`new-session-pending`&&await Hh(n),Te.current.delete(t),Ee.current.add(t),V(e.goalId,null)}function Ke(e){te.some(t=>t.agentId===e&&t.available)&&(M(t=>({...t,[A]:e})),ae(!1))}function qe(){i(``),I(`chat`)}function Je(e){i(e),I(`chat`)}S&&Qx[S.state],S&&(`${N.label}${S.state}`,Ie.length>0&&`${Le}`,Fe.length>0&&`${Fe.length}`),S?.state===`需修复`||!S&&!c.ok?(S&&nS(S.agentId),S?.nextSentence,S?.agentSentence):S?.state===`等你`?(S.needsYouBlocking,S.needsYouBlocking,S.needsYou??S.nextSentence,S.needsYou):(S&&nS(S.agentId),S?.nextSentence);let Ye=[...!S&&he.manager?.status===`resume_failed`?[{id:`run:manager:resume-failed`,kind:`run`,run:{agentId:he.manager.agentId,agentLabel:nS(he.manager.agentId),canInterrupt:!1,completedSteps:0,goalId:`manager`,goalTitle:`LoopX 管家`,latestActivity:`本地聊天记录已保留,点我查看恢复方式。`,resumable:!1,runId:`manager:resume-failed`,sessionId:he.manager.sessionId,sessionStatus:`resume_failed`,status:`failed`,title:`上次会话需要恢复`,totalSteps:1,outputs:[]}}]:[],...S?_e.map(e=>{let t=e.channel_id?.startsWith(`task.`)?e.channel_id.slice(5):void 0,n=S.agentTodos.find(e=>e.todoId===t),r=!!e.active_turn_id,i=xe[e.session_id],a=i?.messages.some(e=>tS(e.role,e.text))===!0;return{id:`run:task:${e.session_id}`,kind:`run`,run:{agentId:e.agent_id,agentLabel:nS(e.agent_id),canInterrupt:r,completedSteps:n?.done||a?1:0,goalId:S.goalId,goalTitle:S.title,latestActivity:r?`Agent 正在执行,可进入 Session 查看过程或发送纠偏。`:a?`Agent 已返回结果,点击查看结果与完整运行记录。`:`执行 Session 已保留,可继续纠偏或恢复。`,resumable:e.resumable,runId:e.session_id,sessionId:e.session_id,sessionMessages:i?.messages.map(e=>({createdAt:e.created_at,messageId:e.message_id,role:e.role===`user`?`user`:tS(e.role,e.text)?`assistant`:`error`,text:e.role===`user`?e.text:eS(e.text)})),sessionStatus:a?`completed`:e.status,status:n?.done||a?`completed`:r?`running`:e.status===`resume_failed`?`failed`:`waiting`,title:n?.text??`Agent 执行任务`,todoId:t,totalSteps:1,turnId:e.active_turn_id??void 0}}}):[],...S?[{id:`run:${S.goalId}`,kind:`run`,run:{agentId:he[S.goalId]?.agentId??S.agentId,agentLabel:nS(he[S.goalId]?.agentId??S.agentId),canInterrupt:!!he[S.goalId]?.turnId,completedSteps:S.agentTodos.filter(e=>e.done).length,goalId:S.goalId,goalTitle:S.title,latestActivity:S.agentSentence,resumable:he[S.goalId]?.resumable??!0,runId:`goal:${S.goalId}`,sessionId:he[S.goalId]?.sessionId,sessionStatus:he[S.goalId]?.status,status:he[S.goalId]?.turnId?`running`:S.state===`需修复`?`failed`:`waiting`,title:S.nextSentence,totalSteps:S.agentTodos.length||1,turnId:he[S.goalId]?.turnId,outputs:S.runEvidence?[{createdAt:S.runEvidence.generatedAt,kind:`evidence`,outputId:`${S.goalId}:latest-evidence`,title:S.runEvidence.label}]:[]}}]:[],...Pe.map(e=>({id:`message:${e.id}`,kind:`message`,message:{agentLabel:e.agentLabel,attachments:e.attachments,id:String(e.id),pending:e.pending,role:e.role,text:e.text||(e.pending?`Agent 正在处理…`:e.lines.join(` -`))}})),...(S?[S]:x.goals).flatMap(e=>e.runEvidence?[{id:`output:${e.goalId}:${e.runEvidence.generatedAt||`latest`}`,kind:`output`,output:{agentLabel:nS(e.agentId),createdAt:e.runEvidence.generatedAt,goalId:e.goalId,goalTitle:e.title,kind:`evidence`,outputId:`${e.goalId}:latest-evidence`,runId:e.runEvidence.runId??void 0,safePreview:e.runEvidence.safePreview,summary:e.runEvidence.summary,title:e.runEvidence.label,todoId:e.runEvidence.todoId??void 0}}]:[]),...S&&w?[{id:`output:${S.goalId}:report:${w.publication.publication_id}`,kind:`output`,output:{agentId:w.agent_id,agentLabel:nS(w.agent_id),createdAt:w.publication.delivered_at,goalId:S.goalId,goalTitle:S.title,kind:`report`,outputId:w.publication.publication_id,report:{addedCount:w.delta.added_count,changedCount:w.delta.changed_count,deliveredAt:w.publication.delivered_at,generationId:w.generation_id,items:w.delta.items.map(e=>({changeKind:e.change_kind,previousStatus:e.previous_status,sourceRef:e.source_ref,status:e.status,summary:e.summary,title:e.title})),periodEndAt:w.period_window.end_at,periodStartAt:w.period_window.start_at,predecessorPublicationId:w.publication.predecessor_publication_id,publicationId:w.publication.publication_id},safePreview:w.delta.items.map(e=>`${e.change_kind===`added`?`+`:`~`} ${e.title}\n${e.summary}`).join(` +`)});continue}let o=e.match(/^\s{0,3}#{1,4}\s+(.*)$/);if(o){i();let t=e.trimStart().match(/^#+/)?.[0].length??1;n.push({type:`heading`,level:t,text:o[1].trim()}),a+=1;continue}if(py.test(e)||my.test(e)){i();let r=my.test(e),o=r?my:py,s=[];for(;a{let n=`b${t}`;if(e.type===`code`)return(0,z.jsx)(`pre`,{className:`personal-md-pre`,children:(0,z.jsx)(`code`,{children:e.text})},n);if(e.type===`heading`)return(0,z.jsx)(`p`,{className:`personal-md-heading is-h${e.level}`,children:fy(e.text,n)},n);if(e.type===`list`){let t=e.items.map((e,t)=>(0,z.jsx)(`li`,{children:fy(e,`${n}-${t}`)},`${n}-${t}`));return e.ordered?(0,z.jsx)(`ol`,{className:`personal-md-list`,children:t},n):(0,z.jsx)(`ul`,{className:`personal-md-list`,children:t},n)}return(0,z.jsx)(`p`,{children:e.lines.map((e,t)=>(0,z.jsxs)(R.Fragment,{children:[t>0?(0,z.jsx)(`br`,{}):null,fy(e,`${n}-${t}`)]},`${n}-${t}`))},n)})})}function _y({onSelect:e,output:t}){let{t:n}=Ji(),r=t.kind===`report`?cm:sm;return(0,z.jsxs)(`button`,{className:`personal-timeline-row personal-output-row`,"data-output-kind":t.kind,"data-testid":`personal-browse-row`,onClick:e,type:`button`,children:[(0,z.jsx)(`span`,{className:`personal-row-icon is-output`,children:(0,z.jsx)(r,{size:18})}),(0,z.jsxs)(`span`,{className:`personal-row-copy`,children:[(0,z.jsxs)(`small`,{children:[t.goalTitle??t.goalId,` · `,t.agentLabel??`LoopX`]}),(0,z.jsx)(`strong`,{children:t.title}),t.summary?(0,z.jsx)(`span`,{children:t.summary}):null,t.report?(0,z.jsxs)(`small`,{children:[n(`files.reportDelta`,{added:t.report.addedCount,changed:t.report.changedCount}),` · `,n(`files.verifiedReport`)]}):null]}),t.createdAt?(0,z.jsx)(`time`,{children:t.createdAt}):null,(0,z.jsx)(Jp,{size:17})]})}var vy={completed:`runs.completed`,failed:`runs.failed`,interrupted:`runs.interrupted`,queued:`runs.queued`,running:`runs.running`,waiting:`runs.waiting`};function yy({onSelect:e,run:t}){let{t:n}=Ji(),r=t.totalSteps>0?Math.min(100,t.completedSteps/t.totalSteps*100):0;return(0,z.jsxs)(`button`,{"aria-label":`${n(`tasks.viewExecution`)}:${t.title}`,className:`personal-timeline-row personal-run-row`,"data-testid":`personal-browse-row`,onClick:e,type:`button`,children:[(0,z.jsx)(`span`,{className:`personal-row-icon is-run`,children:(0,z.jsx)(Up,{size:18})}),(0,z.jsxs)(`span`,{className:`personal-run-identity`,children:[(0,z.jsx)(`small`,{children:t.goalTitle}),(0,z.jsx)(`strong`,{children:t.agentLabel})]}),(0,z.jsxs)(`span`,{className:`personal-row-copy`,children:[(0,z.jsx)(`strong`,{children:t.title}),(0,z.jsx)(`small`,{children:t.latestActivity})]}),(0,z.jsxs)(`span`,{className:`personal-run-progress`,"aria-label":`${t.completedSteps}/${t.totalSteps}`,children:[(0,z.jsxs)(`small`,{children:[t.completedSteps,`/`,t.totalSteps]}),(0,z.jsx)(`i`,{children:(0,z.jsx)(`b`,{style:{width:`${r}%`}})})]}),(0,z.jsxs)(`span`,{className:`personal-row-status is-${t.status}`,children:[t.status===`running`?(0,z.jsx)(hm,{className:`personal-spin`,size:14}):null,n(vy[t.status])]}),t.sessionId?(0,z.jsx)(`span`,{className:`personal-run-open-label`,children:n(`tasks.viewExecution`)}):null,(0,z.jsx)(Jp,{size:17})]})}function by({onSelect:e,schedule:t}){let{t:n}=Ji(),r=t.scheduleKind===`heartbeat`;return(0,z.jsxs)(`button`,{"aria-label":`${r?`Heartbeat`:n(`tasks.scheduled`)}:${t.label};${t.status??`active`}`,className:`personal-schedule-row`,onClick:e,type:`button`,children:[(0,z.jsx)(`span`,{className:`personal-schedule-icon`,children:r?(0,z.jsx)(Dm,{size:17}):(0,z.jsx)(Gp,{size:17})}),(0,z.jsxs)(`span`,{className:`personal-schedule-copy`,children:[(0,z.jsx)(`small`,{children:n(r?`schedule.heartbeat`:`schedule.monitor`)}),(0,z.jsx)(`strong`,{children:t.label}),(0,z.jsx)(`p`,{children:t.schedule??n(`schedule.summary`)})]}),(0,z.jsx)(`span`,{className:`personal-schedule-status is-${t.status??`active`}`,children:t.status===`paused`?n(`schedule.paused`):n(`schedule.active`)}),(0,z.jsx)(Jp,{size:16})]})}function xy({items:e,onSelect:t,selectedGoal:n}){let{t:r}=Ji();if(e.length===0)return(0,z.jsxs)(`div`,{className:`personal-timeline-empty`,children:[(0,z.jsx)(`span`,{children:(0,z.jsx)(Rm,{size:20})}),(0,z.jsx)(`strong`,{children:r(n?`timeline.emptyGoal`:`timeline.emptyWorkspace`)}),(0,z.jsx)(`p`,{children:r(n?`timeline.emptyGoalDescription`:`timeline.emptyWorkspaceDescription`)})]});let i=[...e].reverse().find(e=>e.kind===`message`&&e.message.role!==`user`||e.kind===`proposal`&&[`applied`,`stale`,`error`,`gated`].includes(e.proposal.status)||e.kind===`run`&&e.run.status===`completed`),a=i?.kind===`message`?`${i.message.agentLabel??r(`header.manager`)}:${i.message.pending?r(`timeline.pending`):i.message.text}`:i?.kind===`proposal`?`${i.proposal.title}:${i.proposal.status}`:i?.kind===`run`?r(`timeline.runCompleted`,{run:i.run.title}):``,o=e.filter(e=>e.kind===`proposal`&&e.proposal.status===`gated`),s=e.filter(e=>e.kind!==`proposal`),c=e.filter(e=>e.kind===`proposal`&&e.proposal.status!==`gated`);function l(e){return e.kind===`attention`?(0,z.jsx)(uy,{attention:e.attention,onSelect:()=>t({item:e.attention,kind:`attention`})},e.id):e.kind===`run`?(0,z.jsx)(yy,{onSelect:()=>t({item:e.run,kind:`run`}),run:e.run},e.id):e.kind===`output`?(0,z.jsx)(_y,{onSelect:()=>t({item:e.output,kind:`output`}),output:e.output},e.id):e.kind===`schedule`?(0,z.jsx)(by,{onSelect:()=>t({item:e.schedule,kind:`schedule`}),schedule:e.schedule},e.id):e.kind===`proposal`?(0,z.jsxs)(`button`,{className:`personal-proposal-row is-${e.proposal.status}`,onClick:()=>t({item:e.proposal,kind:`proposal`}),type:`button`,children:[(0,z.jsx)(`span`,{children:(0,z.jsx)(Rm,{size:17})}),(0,z.jsxs)(`span`,{children:[(0,z.jsxs)(`small`,{children:[e.proposal.actionKind,` · `,e.proposal.status]}),(0,z.jsx)(`strong`,{children:e.proposal.title}),(0,z.jsx)(`p`,{children:e.proposal.impact})]}),(0,z.jsx)(`b`,{children:e.proposal.status===`gated`?r(`timeline.review`):e.proposal.primaryLabel??r(`timeline.reviewAndConfirm`)})]},e.id):(0,z.jsxs)(`article`,{className:`personal-message is-${e.message.role}`,children:[e.message.role===`user`?null:(0,z.jsx)(`span`,{className:`personal-message-avatar`,children:(0,z.jsx)(Up,{size:17})}),(0,z.jsxs)(`div`,{children:[(0,z.jsxs)(`header`,{children:[(0,z.jsx)(`strong`,{children:e.message.role===`user`?r(`common.you`):e.message.agentLabel??r(`header.manager`)}),e.message.time?(0,z.jsx)(`time`,{children:e.message.time}):null]}),e.message.attachments?.length?(0,z.jsx)(`div`,{className:`personal-message-images`,children:e.message.attachments.map(e=>(0,z.jsx)(`img`,{alt:e.name,src:e.dataUrl},e.id))}):null,e.message.role===`user`?(0,z.jsx)(`p`,{children:e.message.text}):(0,z.jsx)(gy,{text:e.message.text}),e.message.pending?(0,z.jsx)(`span`,{className:`personal-message-pending`,children:r(`timeline.pending`)}):null]})]},e.id)}return(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`p`,{"aria-atomic":`true`,"aria-live":`polite`,className:`personal-live-region`,role:`status`,children:a}),(0,z.jsxs)(`div`,{className:`personal-channel-timeline`,children:[s.map(l),o.length?(0,z.jsxs)(`details`,{className:`personal-gated-summary`,children:[(0,z.jsxs)(`summary`,{children:[(0,z.jsx)(`span`,{children:(0,z.jsx)(Rm,{size:16})}),(0,z.jsx)(`strong`,{children:r(`timeline.waitingConfirmation`)}),(0,z.jsx)(`small`,{children:r(`timeline.gateHistory`,{count:o.length})})]}),(0,z.jsx)(`div`,{children:o.map(l)})]}):null,c.map(l)]})]})}function Sy(e){return e.replace(/\s+/gu,` `).trim()}function Cy(e,t){let n=RegExp(`(?:不要|不需要|无需|禁止|别|暂不|do not\\b|don't\\b|without\\b).{0,10}(?:${t.source})`,`iu`),r=RegExp(`(?:${t.source}).{0,10}(?:不要|不需要|无需|禁止|关闭)`,`iu`),i=RegExp(`disable\\b.{0,10}(?:${t.source})|(?:turn|switch|set)\\b.{0,10}(?:${t.source}).{0,10}\\boff\\b|(?:${t.source})\\s+(?:is\\s+)?disabled\\b`,`iu`);return n.test(e)||r.test(e)||i.test(e)}function wy(e){return/(我现在该做什么|下一步|哪些\s*Goal\s*在等我|需要我|谁在等我|Agent\s*在做什么|当前进度|总结(?:今天)?进展)/iu.test(e)}function Ty(e){let t=/(怎么|如何|为什么|给.*建议|分析一下|解释|只读)/u.test(e),n=/(解决一下|修复一下|处理一下|执行一下|改一下|跑(?:一下)?测试|rebase|push|提交|推送)/iu.test(e);return!t&&n&&/(帮我|请|给我|直接|现在|开始|bytedcli|codebase|git|rebase|push|提交|推送)/iu.test(e)}function Ey(e){return Sy(e).toLowerCase().match(/(?:^|[\s,,;;:((:]|到|至)(?todo_done:todo_[a-z0-9_-]{3,64}|pr_merged:(?:(?:[a-z0-9_.-]{1,80})\/(?:[a-z0-9_.-]{1,100}))?#[1-9][0-9]{0,8}|capacity_available:[a-z][a-z0-9_:-]{0,63})(?=$|[\s,,。;;))])/iu)?.groups?.condition??null}function Dy(e,t){let n=Sy(e),r=[],i=t.agents.find(e=>{let t=n.toLowerCase();return t.includes(e.agentId.toLowerCase())||t.includes(e.label.toLowerCase())}),a=t.todos.find(e=>n.includes(e.todoId)||n.includes(e.text)),o=/(刚刚|已经|已)(?:经)?\s*(新增|创建|添加)(?:的)?\s*(todo|待办|任务)/iu.test(n),s=!!t.goalId&&!Cy(n,/heartbeat|心跳/iu)&&/(heartbeat|心跳|每天推进|持续推进|daily progress)/iu.test(n);if(!t.goalId&&!Cy(n,/goal|目标/iu)&&/(创建|新建|设置|create|start|set up).{0,24}(goal|目标)/iu.test(n)&&r.push({actionKind:`goal.create`,confidence:.97,normalizedParameters:{heartbeat_enabled:!Cy(n,/heartbeat|心跳/iu)&&/(heartbeat|心跳|每天推进|持续推进|daily progress)/iu.test(n)}}),t.goalId&&s&&r.push({actionKind:`heartbeat.bind`,confidence:.96,normalizedParameters:{goal_id:t.goalId}}),t.goalId&&!s&&!Cy(n,/定时|监控|监测|持续观察|scheduled check|monitor/iu)&&/(定时|监控|监测|每.{0,8}(分钟|小时|天)|持续观察|scheduled check|monitor|every.{0,12}(minute|hour|day)|daily)/iu.test(n)&&r.push({actionKind:`monitor.create`,confidence:.94,normalizedParameters:{goal_id:t.goalId}}),t.goalId&&i&&!Cy(n,/绑定|负责|接管|管理/iu)&&/((让|交给).{0,20}(管理|负责|接管).{0,8}(goal|目标)|(绑定).{0,12}(goal|目标)|(goal|目标).{0,12}(交给|绑定|负责|接管))/iu.test(n)&&r.push({actionKind:`agent.bind`,confidence:.96,normalizedParameters:{agent_id:i.agentId,goal_id:t.goalId}}),t.goalId&&!o&&!Cy(n,RegExp(`todo|待办|任务`,`iu`))&&/(创建|新建|新增|添加|加一个|记一个).{0,16}(todo|待办|任务)|(todo|待办|任务).{0,12}(创建|新建|新增|添加)|(?:create|add)(?:\s+(?:a|an|new))?\s+(?:todo|task)|(?:todo|task).{0,12}(?:create|add)/iu.test(n)&&r.push({actionKind:`todo.create`,confidence:.94,normalizedParameters:{goal_id:t.goalId}}),t.goalId&&Ty(n)&&r.push({actionKind:`todo.create`,confidence:.9,normalizedParameters:{goal_id:t.goalId,start_execution:!0}}),t.goalId&&a){let e=!Cy(n,/完成|做完|关闭/u)&&/完成|做完|关闭/u.test(n)?`complete`:!Cy(n,/阻塞|卡住/u)&&/阻塞|卡住/u.test(n)?`block`:!Cy(n,/暂缓|稍后|推迟/u)&&/暂缓|稍后|推迟/u.test(n)?`defer`:i&&!Cy(n,/交给|分配给|改派/u)&&/交给|分配给|改派/u.test(n)?`reassign`:null;if(e){let i=e===`defer`?Ey(n):null;if(e===`defer`&&!i)return{actionKind:`todo.update`,confidence:.97,missingFields:[`resume_when`],normalizedParameters:{goal_id:t.goalId,operation:e,todo_id:a.todoId},route:`clarify`};r.push({actionKind:`todo.update`,confidence:.97,normalizedParameters:{goal_id:t.goalId,operation:e,...i?{resume_when:i}:{},todo_id:a.todoId}})}}let c=[...new Map(r.map(e=>[e.actionKind,e])).values()];return c.length>1?{actionKind:null,confidence:.4,missingFields:[`single_intent`],normalizedParameters:{},route:`clarify`}:c.length===1?{...c[0],missingFields:[],route:`typed_action`}:!t.goalId&&wy(n)?{actionKind:null,confidence:.98,missingFields:[],normalizedParameters:{},route:`projection`}:{actionKind:null,confidence:.75,missingFields:[],normalizedParameters:{},route:`agent_chat`}}var Oy=[`a[href]`,`button:not([disabled])`,`textarea:not([disabled])`,`select:not([disabled])`,`input:not([disabled])`,`[tabindex]:not([tabindex='-1'])`].join(`,`),ky=[{key:`drawer.taskBlock`,operation:`block`},{key:`drawer.taskSuccessor`,operation:`successor_create`}],Ay=[{key:`drawer.decisionReject`,resolution:`reject`},{key:`drawer.decisionDefer`,resolution:`defer`}],jy=Array.from({length:32},(e,t)=>t+1),My=/^[a-z][a-z0-9_.-]{0,63}$/u;function Ny(e){let t=String(e??``).trim().toLowerCase();return My.test(t)?t:null}function Py(e,t){return e.enabled===t.enabled&&e.maxChildren===t.maxChildren&&[...e.allowedDomains].sort((e,t)=>e.localeCompare(t)).join(`\0`)===[...t.allowedDomains].sort((e,t)=>e.localeCompare(t)).join(`\0`)}function Fy({agents:e,callbacks:t,goalNotifications:n=[],goals:r=[],inspectorExpanded:i=!1,larkConnections:a=[],onClose:o,onToggleInspectorSize:s,readOnly:c=!1,runs:l=[],selection:u}){let{locale:d,t:f}=Ji(),[p,m]=(0,R.useState)(``),[h,g]=(0,R.useState)(!1),[_,v]=(0,R.useState)(`idle`),[y,b]=(0,R.useState)(`record`),[x,S]=(0,R.useState)([]),[C,w]=(0,R.useState)(null),[T,E]=(0,R.useState)(2),[D,O]=(0,R.useState)(`idle`),[k,ee]=(0,R.useState)(null),[A,j]=(0,R.useState)(null),te=(0,R.useRef)(null),ne=(0,R.useRef)(null),[re,M]=(0,R.useState)(e.find(e=>e.available)?.agentId??`codex`),[N,ie]=(0,R.useState)(``),ae=(0,R.useRef)(null),oe=(0,R.useRef)(null),P=(0,R.useRef)(null),F=(0,R.useRef)(null),I=u.kind===`run`?`run:${u.item.runId}`:u.kind===`proposal`?`proposal:${u.item.previewId}`:u.kind===`todo`?`todo:${u.item.todoId}`:u.kind===`attention`?`attention:${u.item.todoId}`:u.kind===`output`?`output:${u.item.outputId}`:u.kind===`schedule`?`schedule:${u.item.scheduleId}`:`goal:${u.item.goalId}`;(0,R.useEffect)(()=>{v(`idle`),g(!1),b(`record`),ie(``);let e=u.kind===`goal`?u.item.subagentExecution:void 0;S(e?.allowedDomains??[]),E(e?.maxChildren?Math.min(e.maxChildren,32):2),w(null),O(`idle`),ee(null),j(null),te.current=e??null,ne.current=null},[I]);let se=u.kind===`goal`?u.item.subagentExecution:void 0;(0,R.useEffect)(()=>{let e=te.current,t=se?!e||!Py(e,se):e!==null;if(te.current=se??null,!A){t&&se&&(S(se.allowedDomains),E(se.maxChildren||2),w(null),O(`idle`),ee(null));return}let n=ne.current;(!se||Py(A,se)||n&&!Py(n,se))&&(se&&(S(se.allowedDomains),E(se.maxChildren||2)),ne.current=null,j(null))},[se,A]),(0,R.useEffect)(()=>{let e=document.activeElement;e instanceof HTMLElement&&!oe.current?.contains(e)&&(P.current=e);let t=window.requestAnimationFrame(()=>F.current?.focus());return()=>window.cancelAnimationFrame(t)},[I]);let ce=(0,R.useCallback)(()=>{let e=P.current;o(),window.requestAnimationFrame(()=>e?.focus())},[o]);(0,R.useEffect)(()=>{function e(e){if(e.key===`Escape`){e.preventDefault(),ce();return}if(e.key===`Tab`&&u.kind!==`todo`){let t=Array.from(oe.current?.querySelectorAll(Oy)??[]).filter(e=>!e.hasAttribute(`disabled`)&&e.getAttribute(`aria-hidden`)!==`true`);if(t.length===0)return;let n=t[0],r=t[t.length-1];e.shiftKey&&document.activeElement===n?(e.preventDefault(),r.focus()):!e.shiftKey&&document.activeElement===r&&(e.preventDefault(),n.focus())}}return document.addEventListener(`keydown`,e),()=>{document.removeEventListener(`keydown`,e)}},[ce,u.kind]);let le=u.kind===`attention`?f(`drawer.titleAttention`):u.kind===`todo`?f(`drawer.taskDetails`):u.kind===`run`?f(`drawer.runDetails`):u.kind===`output`?f(`drawer.titleOutput`):u.kind===`proposal`?f(u.item.status===`applied`?`drawer.titleProposalApplied`:`drawer.titleProposalConfirm`):u.kind===`schedule`?u.item.scheduleKind===`heartbeat`?`Heartbeat`:f(`drawer.titleSchedule`):f(`drawer.goalDetails`),ue=u.kind===`proposal`?u.item.goalId??`manager`:u.item.goalId,de=u.kind===`attention`?u.item.goalTitle??f(`drawer.currentGoal`):u.kind===`todo`||u.kind===`run`?u.item.goalTitle:u.kind===`output`?u.item.goalTitle??f(`drawer.currentGoal`):u.kind===`goal`?u.item.title:u.kind===`schedule`?f(`drawer.goalAutoRun`):u.item.goalId?f(`drawer.goalChanges`):f(`drawer.managerChanges`),fe=u.kind===`goal`?l.find(e=>e.goalId===u.item.goalId&&!!e.sessionId)??l.find(e=>e.goalId===u.item.goalId):null,pe=u.kind===`run`&&(u.item.completedSteps>0||!!u.item.latestActivity||!!u.item.outputs?.length),me=u.kind===`attention`?Zi(u.item.updatedAt,f):null,he=Ey(N);async function ge(){u.kind!==`run`||!p.trim()||(await t.onCorrectRun?.(u.item,p.trim()),m(``))}async function _e(e,n,r,i){if(n===`successor_create`){await t.onPreviewAction?.({actionKind:`todo.create`,context:{goal_id:e.goalId,kind:`todo`,todo_id:e.todoId},idempotencyKey:`workspace-todo-successor-${e.todoId}-${Date.now().toString(36)}`,normalizedParameters:{goal_id:e.goalId,text:f(`drawer.taskSuccessorText`,{task:e.text})},summary:f(`drawer.taskSuccessorSummary`,{task:e.text})});return}await t.onPreviewAction?.({actionKind:`todo.update`,context:{goal_id:e.goalId,kind:`todo`,todo_id:e.todoId},idempotencyKey:`workspace-todo-${e.todoId}-${n}-${Date.now().toString(36)}`,normalizedParameters:{agent_id:e.claimedBy??re,goal_id:e.goalId,operation:n,...n===`block`?{note:f(`drawer.taskSuccessorNote`)}:{},...n===`defer`&&i?{resume_when:i}:{},todo_id:e.todoId},summary:`${r}:${e.text}`})}async function ve(e,n,r){await t.onPreviewAction?.({actionKind:`gate.resolve`,context:{goal_id:e.goalId,kind:`todo`,todo_id:e.todoId},idempotencyKey:`workspace-decision-${e.todoId}-${n}-${Date.now().toString(36)}`,normalizedParameters:{goal_id:e.goalId,decision:n,todo_id:e.todoId},summary:`${r}:${e.text}`})}let ye=u.kind===`goal`?A??u.item.subagentExecution??{allowedDomains:[],domainCandidates:[],enabled:!1,maxChildren:0}:{allowedDomains:[],domainCandidates:[],enabled:!1,maxChildren:0},be=D===`previewing`||D===`applying`,xe=(()=>{if(u.kind!==`goal`)return[];let e=new Map;for(let t of ye.allowedDomains){let n=Ny(t);n&&e.set(n,{matchingTodoCount:0,value:n})}if(ye.domainCandidates)for(let t of ye.domainCandidates){let n=Ny(t.domain);if(!n)continue;let r=e.get(n);e.set(n,{matchingTodoCount:(r?.matchingTodoCount??0)+t.matchingTodoCount,value:n})}else for(let t of u.item.agentTodos){if(t.done||t.taskClass!==`advancement_task`)continue;let n=Ny(t.taskDomain);if(!n)continue;let r=e.get(n);e.set(n,{matchingTodoCount:(r?.matchingTodoCount??0)+1,value:n})}return[...e.values()]})();function Se(){S(ye.allowedDomains),E(ye.maxChildren||2),w(null),O(`idle`),ee(null)}function Ce(){let e=[...new Set(x.map(e=>Ny(e)))];return e.every(e=>!!e)?e:null}function we(e,t){S(n=>t?[...n,e].filter((e,t,n)=>n.indexOf(e)===t):n.filter(t=>t!==e)),ee(null),O(`idle`),w(null)}async function Te(e){if(u.kind!==`goal`||!t.onPreviewGoalSubagentConfiguration)return;let n=e?Ce():[];if(e&&!n){O(`error`),w(f(`drawer.subagentDomainInvalid`)),ee(null);return}let r={allowedDomains:n??[],enabled:e,goalId:u.item.goalId,maxChildren:e?T:0};O(`previewing`),w(f(`drawer.subagentPreviewing`)),ee(null);try{let e=await t.onPreviewGoalSubagentConfiguration(r);if(!e.changed){ne.current=se??null,j({...e.configuration,domainCandidates:ye.domainCandidates}),S(e.configuration.allowedDomains),E(e.configuration.maxChildren||2),O(`success`),w(f(`drawer.subagentNoChange`));return}ee({...r,changed:e.changed,previewId:e.previewId}),O(`ready`),w(f(`drawer.subagentPreviewReady`))}catch(e){O(`error`),w(e instanceof Error?e.message:f(`drawer.subagentPreviewFailed`))}}async function Ee(){if(!(!k||!t.onApplyGoalSubagentConfiguration)){O(`applying`),w(f(`drawer.subagentApplying`));try{let e=await t.onApplyGoalSubagentConfiguration({allowedDomains:k.allowedDomains,enabled:k.enabled,goalId:k.goalId,maxChildren:k.maxChildren,previewId:k.previewId});ne.current=se??null,j({...e,domainCandidates:ye.domainCandidates}),S(e.allowedDomains),E(e.maxChildren||2),O(`success`),w(f(`drawer.subagentApplied`)),ee(null);try{await t.onRefresh?.()}catch{O(`warning`),w(f(`drawer.subagentAppliedRefreshFailed`))}}catch(e){O(`error`),w(e instanceof Error?e.message:f(`drawer.subagentApplyFailed`))}}}return(0,z.jsxs)(`div`,{"aria-labelledby":`personal-drawer-title`,"aria-modal":u.kind===`todo`?void 0:`true`,className:`personal-context-drawer`,"data-context-kind":u.kind,ref:oe,role:`dialog`,children:[(0,z.jsxs)(`header`,{className:`personal-drawer-header${u.kind===`todo`?` is-task-inspector`:``}`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`h2`,{id:`personal-drawer-title`,ref:F,tabIndex:-1,children:le}),(0,z.jsx)(`p`,{children:de})]}),(0,z.jsxs)(`div`,{className:`personal-drawer-header-actions`,children:[u.kind===`todo`&&s?(0,z.jsx)(`button`,{"aria-label":f(i?`drawer.inspectorHalf`:`drawer.inspectorFull`),className:`personal-icon-button personal-inspector-size`,onClick:s,title:f(i?`drawer.inspectorHalfView`:`drawer.inspectorFullView`),type:`button`,children:i?(0,z.jsx)(bm,{size:17}):(0,z.jsx)(gm,{size:17})}):null,(0,z.jsxs)(`button`,{"aria-label":f(`drawer.closeDetail`,{context:de}),className:`personal-icon-button personal-drawer-close`,onClick:ce,ref:ae,type:`button`,children:[(0,z.jsx)(Lp,{className:`personal-mobile-back`,size:18}),(0,z.jsx)(Gm,{className:`personal-desktop-close`,size:18})]})]})]}),(0,z.jsxs)(`div`,{className:`personal-drawer-body`,children:[u.kind===`attention`?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`section`,{className:`personal-detail-card is-attention`,children:[(0,z.jsx)(`small`,{children:u.item.blocking?f(`drawer.attentionBlocking`):f(`drawer.attentionWaiting`)}),(0,z.jsx)(`h3`,{children:u.item.text}),(0,z.jsxs)(`dl`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Goal`}),(0,z.jsx)(`dd`,{children:u.item.goalTitle??u.item.goalId})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.priority`)}),(0,z.jsx)(`dd`,{children:u.item.priority??`medium`})]}),me?(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`common.waiting`)}),(0,z.jsx)(`dd`,{children:f(`tasks.waitingAge`,{age:me})})]}):null,(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.reason`)}),(0,z.jsx)(`dd`,{children:u.item.explanation??f(`drawer.decisionDefaultReason`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.evidence`)}),(0,z.jsx)(`dd`,{children:u.item.evidence??f(`drawer.decisionDefaultEvidence`)})]})]})]}),c?null:(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`button`,{className:`personal-primary-action`,onClick:()=>void ve(u.item,`approve`,f(`common.confirm`)),type:`button`,children:[(0,z.jsx)(Kp,{size:17}),f(`drawer.decisionReview`)]}),(0,z.jsxs)(`details`,{className:`personal-compact-menu`,children:[(0,z.jsxs)(`summary`,{children:[(0,z.jsx)(rm,{size:17}),f(`drawer.decisionMore`)]}),(0,z.jsxs)(`div`,{children:[(0,z.jsxs)(`button`,{onClick:()=>void t.onExplainDecision?.(u.item),type:`button`,children:[(0,z.jsx)(vm,{size:16}),f(`drawer.explainDecision`)]}),Ay.map(e=>(0,z.jsx)(`button`,{onClick:()=>void ve(u.item,e.resolution,f(e.key)),type:`button`,children:f(e.key)},e.resolution))]})]})]})]}):null,u.kind===`todo`?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`section`,{className:`personal-task-inspector-summary`,children:[(0,z.jsxs)(`div`,{className:`personal-task-inspector-status`,children:[(0,z.jsxs)(`span`,{className:u.item.done?`is-done`:u.item.status===`blocked`?`is-blocked`:`is-open`,children:[(0,z.jsx)(`i`,{}),u.item.done?f(`drawer.taskStatusCompleted`):u.item.status===`deferred`?f(`drawer.taskStatusDeferred`):u.item.status===`blocked`?f(`drawer.taskStatusBlocked`):f(`drawer.taskStatusOpen`)]}),u.item.priority?(0,z.jsx)(`span`,{children:u.item.priority}):null,(0,z.jsx)(`span`,{children:u.item.taskClass===`advancement_task`?f(`drawer.taskAdvancement`):u.item.taskClass??f(`drawer.taskOrdinary`)})]}),(0,z.jsx)(`h3`,{children:u.item.text})]}),(0,z.jsxs)(`section`,{"aria-label":f(`drawer.taskInfo`),className:`personal-task-inspector-fields`,children:[(0,z.jsx)(`h4`,{children:f(`drawer.taskInfo`)}),(0,z.jsxs)(`dl`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Goal`}),(0,z.jsx)(`dd`,{children:u.item.goalTitle})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`common.owner`)}),(0,z.jsx)(`dd`,{children:u.item.ownerLabel??u.item.claimedBy??f(`drawer.notAssigned`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`common.status`)}),(0,z.jsx)(`dd`,{children:u.item.done?f(`drawer.taskStatusCompleted`):u.item.status===`deferred`?f(`drawer.taskStatusDeferred`):u.item.status===`blocked`?f(`drawer.taskStatusBlocked`):f(`drawer.taskStatusOpen`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.priority`)}),(0,z.jsx)(`dd`,{children:u.item.priority??f(`drawer.notSet`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.dependencies`)}),(0,z.jsx)(`dd`,{children:u.item.dependencies?.join(` · `)||f(`common.none`)})]}),u.item.status===`deferred`?(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.resumeWhen`)}),(0,z.jsx)(`dd`,{children:u.item.resumeWhen||f(`drawer.notSet`)})]}):null,(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.nextTransition`)}),(0,z.jsx)(`dd`,{children:u.item.nextTransition??(u.item.done?f(`drawer.taskNextCompleted`):u.item.status===`deferred`?f(`drawer.taskNextDeferred`):f(`drawer.taskNextOpen`))})]})]})]}),!c&&!u.item.done?(0,z.jsxs)(`div`,{className:`personal-task-inspector-actions`,"aria-label":f(`drawer.taskActions`),children:[(0,z.jsxs)(`details`,{className:`personal-task-management`,children:[(0,z.jsxs)(`summary`,{children:[(0,z.jsx)(rm,{size:16}),f(`drawer.taskManage`)]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:f(`drawer.reassign`)}),(0,z.jsxs)(`label`,{className:`personal-inline-agent-select`,children:[f(`drawer.reassign`),(0,z.jsx)(`select`,{"aria-label":f(`drawer.reassign`),onChange:e=>M(e.target.value),value:re,children:e.filter(e=>e.available).map(e=>(0,z.jsx)(`option`,{value:e.agentId,children:e.label},e.agentId))}),(0,z.jsx)(`button`,{className:`personal-secondary-action`,onClick:()=>void t.onPreviewAction?.({actionKind:`todo.update`,context:{goal_id:u.item.goalId,kind:`todo`,todo_id:u.item.todoId},idempotencyKey:`workspace-todo-${u.item.todoId}-reassign-${re}-${Date.now().toString(36)}`,normalizedParameters:{agent_id:re,goal_id:u.item.goalId,operation:`reassign`,todo_id:u.item.todoId},summary:f(`drawer.reassignSummary`,{task:u.item.text})}),type:`button`,children:f(`timeline.review`)})]}),(0,z.jsx)(`strong`,{children:f(`drawer.taskDeferUntil`)}),(0,z.jsxs)(`label`,{className:`personal-inline-agent-select personal-inline-resume-when`,children:[f(`drawer.taskDeferUntil`),(0,z.jsx)(`input`,{"aria-label":f(`drawer.taskDeferCondition`),"aria-invalid":!!N.trim()&&!he,onChange:e=>ie(e.target.value),placeholder:f(`drawer.taskDeferPlaceholder`),value:N}),(0,z.jsx)(`button`,{className:`personal-secondary-action`,disabled:!he,onClick:()=>void _e(u.item,`defer`,f(`drawer.taskDefer`),he??void 0),type:`button`,children:f(`drawer.taskDeferReview`)}),(0,z.jsx)(`small`,{children:N.trim()&&!he?f(`drawer.taskDeferInvalid`):f(`drawer.taskDeferSupported`)})]}),(0,z.jsx)(`div`,{className:`personal-task-management-secondary`,children:ky.map(e=>(0,z.jsx)(`button`,{onClick:()=>void _e(u.item,e.operation,f(e.key)),type:`button`,children:f(e.key)},e.operation))})]})]}),(0,z.jsxs)(`button`,{className:`personal-primary-action`,onClick:()=>void _e(u.item,`complete`,f(`drawer.taskComplete`)),type:`button`,children:[(0,z.jsx)(Kp,{size:17}),f(`drawer.taskComplete`)]})]}):null,u.item.done?(0,z.jsxs)(`div`,{className:`personal-task-completed-note`,children:[(0,z.jsx)(Kp,{size:16}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:f(`drawer.taskCompletedTitle`)}),(0,z.jsx)(`small`,{children:f(`drawer.taskCompletedNote`)})]})]}):null]}):null,u.kind===`goal`?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`section`,{className:`personal-detail-card`,children:[(0,z.jsx)(`small`,{children:Yi(u.item.state,d)}),(0,z.jsx)(`h3`,{children:u.item.title}),(0,z.jsx)(`p`,{children:u.item.agentSentence}),(0,z.jsxs)(`dl`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.tokens`)}),(0,z.jsxs)(`dd`,{children:[ay(u.item.usage?.tokens24h,f(`drawer.usageNotMeasured`),ny),` / `,ay(u.item.usage?.tokens7d,f(`drawer.usageNotMeasured`),ny)]})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.cost`)}),(0,z.jsxs)(`dd`,{children:[ay(u.item.usage?.costUsd24h,f(`drawer.usageNotMeasured`),ry),` / `,ay(u.item.usage?.costUsd7d,f(`drawer.usageNotMeasured`),ry)]})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.duration`)}),(0,z.jsxs)(`dd`,{children:[ay(u.item.usage?.durationMs24h,f(`drawer.usageNotMeasured`),iy),` / `,ay(u.item.usage?.durationMs7d,f(`drawer.usageNotMeasured`),iy)]})]})]})]}),(()=>{let e=n.find(e=>e.goalId===u.item.goalId),r=a.find(e=>e.goal_id===u.item.goalId);return(0,z.jsxs)(z.Fragment,{children:[u.item.repository?(0,z.jsxs)(`section`,{className:`personal-detail-card personal-goal-repository`,children:[(0,z.jsxs)(`div`,{className:`personal-detail-card-title`,children:[(0,z.jsx)(`small`,{children:f(`drawer.repository`)}),(0,z.jsx)(`em`,{children:f(`common.readOnly`)})]}),(0,z.jsxs)(`h3`,{children:[(0,z.jsx)(lm,{size:16}),u.item.repository.label]}),(0,z.jsxs)(`dl`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.branch`)}),(0,z.jsx)(`dd`,{children:u.item.repository.branch||`detached`})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Role`}),(0,z.jsx)(`dd`,{children:f(`drawer.repositoryRole`)})]})]}),(0,z.jsxs)(`button`,{className:`personal-secondary-action`,onClick:()=>{let e=navigator.clipboard?.writeText(u.item.repository?.identity??``);if(!e){v(`error`);return}e.then(()=>v(`copied`)).catch(()=>v(`error`))},type:`button`,children:[(0,z.jsx)(em,{size:15}),f(_===`copied`?`drawer.copyRepositoryDone`:`drawer.copyRepository`)]}),_===`error`?(0,z.jsx)(`p`,{className:`personal-copy-feedback is-error`,role:`status`,children:f(`drawer.copyRepositoryError`)}):_===`copied`?(0,z.jsx)(`p`,{className:`personal-copy-feedback`,role:`status`,children:f(`drawer.copyRepositorySuccess`)}):null]}):null,c?(0,z.jsxs)(`section`,{className:`personal-detail-card personal-goal-notification`,children:[(0,z.jsx)(`small`,{children:f(`drawer.larkConnection`)}),(0,z.jsx)(`h3`,{children:f(`drawer.remoteDetailsUnavailable`)}),(0,z.jsx)(`p`,{children:f(`drawer.remoteDetailsDescription`)})]}):(0,z.jsxs)(`section`,{className:`personal-detail-card personal-goal-notification`,children:[(0,z.jsx)(`small`,{children:f(`drawer.larkConnection`)}),r?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`h3`,{children:[r.app_label,(0,z.jsx)(`span`,{className:`personal-connection-status`,children:f(`drawer.connected`)})]}),(0,z.jsxs)(`dl`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.group`)}),(0,z.jsx)(`dd`,{children:r.chat_name})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.topic`)}),(0,z.jsxs)(`dd`,{children:[`# `,r.topic_name]})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.trigger`)}),(0,z.jsx)(`dd`,{children:r.incoming_mode===`mentions`?f(`lark.someoneMentions`):f(`lark.allMessages`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.replyMode`)}),(0,z.jsx)(`dd`,{children:f(`lark.topicReply`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.autoNotify`)}),(0,z.jsx)(`dd`,{children:e?.humanGateAutoNotifyEnabled?f(`common.on`):f(`common.off`)})]}),e?.lastNotifiedAt?(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.lastNotification`)}),(0,z.jsx)(`dd`,{children:e.lastNotifiedAt})]}):null]})]}):(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`h3`,{children:f(`drawer.larkNotConfigured`)}),(0,z.jsx)(`p`,{children:f(`drawer.larkNotConfiguredDescription`)})]}),(0,z.jsxs)(`button`,{className:`personal-secondary-action`,onClick:()=>t.onOpenNotificationSettings?.(u.item.goalId),type:`button`,children:[(0,z.jsx)(Hp,{size:16}),f(r?`drawer.larkConfigure`:`drawer.larkConnect`)]})]})]})})(),(0,z.jsxs)(`section`,{className:`personal-detail-card personal-goal-session`,children:[(0,z.jsx)(`small`,{children:f(`drawer.runDetails`)}),fe?.sessionId?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`h3`,{children:Xi(fe.sessionStatus??fe.status,f)}),(0,z.jsx)(`p`,{children:fe.title}),t.onOpenRunSession?(0,z.jsxs)(`button`,{className:`personal-primary-action`,onClick:()=>void t.onOpenRunSession?.(fe),type:`button`,children:[(0,z.jsx)(Tm,{size:16}),f(`drawer.runLatest`)]}):null]}):(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`h3`,{children:f(`drawer.noRun`)}),(0,z.jsx)(`p`,{children:f(`drawer.noRunDescription`)})]})]}),c?null:(0,z.jsxs)(`div`,{className:`personal-drawer-action-grid`,children:[(0,z.jsxs)(`button`,{className:`personal-secondary-action`,onClick:()=>t.onRequestScheduleConfig?.(`heartbeat`,u.item.goalId),type:`button`,children:[(0,z.jsx)(Dm,{size:16}),f(`drawer.setupHeartbeat`)]}),(0,z.jsxs)(`button`,{className:`personal-secondary-action`,onClick:()=>t.onRequestScheduleConfig?.(`monitor`,u.item.goalId),type:`button`,children:[(0,z.jsx)(Gp,{size:16}),f(`drawer.scheduleAdd`)]})]}),u.item.subagentExecution?(0,z.jsxs)(`section`,{className:`personal-detail-card personal-goal-subagents`,children:[(0,z.jsxs)(`div`,{className:`personal-subagent-heading`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`small`,{children:f(`drawer.subagentLabel`)}),(0,z.jsxs)(`h3`,{children:[(0,z.jsx)(Up,{size:16}),f(`drawer.subagentTitle`)]})]}),(0,z.jsxs)(`button`,{"aria-checked":ye.enabled,"aria-label":f(k&&D===`ready`?`drawer.subagentPending`:ye.enabled?`drawer.subagentDisable`:`drawer.subagentEnable`),className:`personal-subagent-switch`,"data-pending":k&&D===`ready`?`true`:void 0,disabled:c||be||!!k||!t.onPreviewGoalSubagentConfiguration,onClick:()=>void Te(!ye.enabled),role:`switch`,type:`button`,children:[(0,z.jsx)(`span`,{}),f(k&&D===`ready`?`drawer.subagentPending`:ye.enabled?`common.on`:`common.off`)]})]}),(0,z.jsx)(`p`,{children:f(`drawer.subagentDescription`)}),k&&D===`ready`?(0,z.jsxs)(`div`,{className:`personal-subagent-preview`,children:[(0,z.jsx)(`strong`,{children:f(k.enabled?`drawer.subagentConfirmEnable`:`drawer.subagentConfirmDisable`)}),(0,z.jsx)(`p`,{children:k.enabled?f(`drawer.subagentPreviewSummary`,{count:k.maxChildren,domains:k.allowedDomains.join(` · `)||f(`drawer.subagentDomainsUnrestricted`)}):f(`drawer.subagentDisableSummary`)}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`button`,{className:`personal-primary-action`,onClick:()=>void Ee(),type:`button`,children:f(`common.confirm`)}),(0,z.jsx)(`button`,{className:`personal-secondary-action`,onClick:Se,type:`button`,children:f(`common.cancel`)})]})]}):null,C?(0,z.jsxs)(`p`,{className:`personal-subagent-feedback is-${D}`,role:`status`,children:[D===`previewing`||D===`applying`?(0,z.jsx)(km,{className:`personal-spin`,size:13}):null,C]}):null,(0,z.jsxs)(`dl`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.subagentCurrentBoundary`)}),(0,z.jsx)(`dd`,{children:ye.allowedDomains.join(` · `)||f(`drawer.subagentDomainsUnrestricted`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.subagentChildLimit`)}),(0,z.jsx)(`dd`,{children:ye.maxChildren||0})]})]}),c?(0,z.jsx)(`p`,{className:`personal-subagent-read-only`,children:f(`drawer.subagentRemoteReadOnly`)}):(0,z.jsxs)(`div`,{className:`personal-subagent-fields`,children:[(0,z.jsxs)(`fieldset`,{className:`personal-subagent-domain-picker`,disabled:be,children:[(0,z.jsx)(`legend`,{children:f(`drawer.subagentDomains`)}),xe.length>0?(0,z.jsx)(`div`,{className:`personal-subagent-domain-options`,children:xe.map(e=>{let t=x.includes(e.value);return(0,z.jsxs)(`label`,{className:`personal-subagent-domain-option${t?` is-selected`:``}`,children:[(0,z.jsx)(`input`,{"aria-label":e.value,checked:t,onChange:t=>we(e.value,t.target.checked),type:`checkbox`}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:e.value}),(0,z.jsx)(`small`,{children:f(`drawer.subagentDomainTodoCount`,{count:e.matchingTodoCount})})]})]},e.value)})}):(0,z.jsx)(`p`,{className:`personal-subagent-domain-empty`,children:f(`drawer.subagentDomainsEmpty`)}),(0,z.jsx)(`small`,{children:f(`drawer.subagentDomainsHint`)})]}),(0,z.jsxs)(`label`,{className:`personal-subagent-limit-field`,children:[(0,z.jsx)(`span`,{children:f(`drawer.subagentMaxChildren`)}),(0,z.jsx)(`select`,{"aria-label":f(`drawer.subagentMaxChildren`),disabled:be,onChange:e=>{E(Number(e.target.value)),ee(null),O(`idle`),w(null)},value:T,children:jy.map(e=>(0,z.jsx)(`option`,{value:e,children:e},e))})]}),ye.enabled?(0,z.jsx)(`button`,{className:`personal-secondary-action`,disabled:be,onClick:()=>void Te(!0),type:`button`,children:f(`drawer.subagentPreviewBoundary`)}):null]})]}):null]}):null,u.kind===`run`?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`div`,{"aria-label":f(`drawer.runView`),className:`personal-run-drawer-tabs`,role:`tablist`,children:[(0,z.jsx)(`button`,{"aria-selected":y===`record`,onClick:()=>b(`record`),role:`tab`,type:`button`,children:f(`drawer.executionRecordAndResult`)}),(0,z.jsx)(`button`,{"aria-selected":y===`details`,onClick:()=>b(`details`),role:`tab`,type:`button`,children:f(`drawer.detailsAndActions`)})]}),y===`record`?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`section`,{className:`personal-detail-card personal-session-summary`,children:[(0,z.jsxs)(`small`,{children:[u.item.agentLabel,` · `,Xi(u.item.sessionStatus??u.item.status,f)]}),(0,z.jsx)(`h3`,{children:u.item.title}),(0,z.jsx)(`p`,{children:u.item.latestActivity}),(0,z.jsxs)(`dl`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Goal`}),(0,z.jsx)(`dd`,{children:u.item.goalTitle})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.progress`)}),(0,z.jsxs)(`dd`,{children:[u.item.completedSteps,`/`,u.item.totalSteps]})]})]})]}),(0,z.jsxs)(`section`,{"aria-label":f(`drawer.executionRecord`),className:`personal-session-message-record`,children:[(0,z.jsx)(`h3`,{children:f(`drawer.executionRecord`)}),u.item.sessionMessages?.length?(0,z.jsx)(`ol`,{children:u.item.sessionMessages.map(e=>(0,z.jsxs)(`li`,{className:`is-${e.role}`,children:[(0,z.jsx)(`i`,{}),(0,z.jsxs)(`div`,{children:[(0,z.jsxs)(`header`,{children:[(0,z.jsx)(`strong`,{children:e.role===`user`?f(`drawer.runRoleUser`):e.role===`assistant`?f(`drawer.runRoleAssistant`):f(`drawer.runRoleSystem`)}),e.createdAt?(0,z.jsx)(`time`,{children:new Date(e.createdAt).toLocaleTimeString(d,{hour:`2-digit`,minute:`2-digit`,hour12:!1})}):null]}),(0,z.jsx)(`p`,{children:e.text})]})]},e.messageId))}):(0,z.jsx)(`p`,{className:`personal-session-empty`,children:pe?f(`drawer.runRecordProjected`,{completed:u.item.completedSteps,outputs:u.item.outputs?.length?f(`drawer.runRecordProjectedOutputs`,{count:u.item.outputs.length}):``,total:u.item.totalSteps}):f(`drawer.runRecordEmpty`)}),u.item.status===`running`?(0,z.jsxs)(`div`,{className:`personal-session-active-step`,children:[(0,z.jsx)(`i`,{}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:f(`drawer.analysis`)}),(0,z.jsx)(`small`,{children:f(`drawer.agentWorking`)})]})]}):null]}),u.item.outputs?.length?(0,z.jsxs)(`section`,{className:`personal-execution-history`,"aria-labelledby":`personal-run-outputs-title`,children:[(0,z.jsx)(`h3`,{id:`personal-run-outputs-title`,children:f(`drawer.outputs`)}),(0,z.jsx)(`ol`,{children:u.item.outputs.map(e=>(0,z.jsx)(`li`,{children:(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:e.title}),(0,z.jsx)(`small`,{children:e.createdAt??e.kind??f(`files.emptySummary`)})]})},e.outputId))})]}):null]}):(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`section`,{className:`personal-detail-card`,children:[(0,z.jsxs)(`small`,{children:[u.item.agentLabel,` · `,Xi(u.item.status,f)]}),(0,z.jsx)(`h3`,{children:u.item.title}),(0,z.jsx)(`p`,{children:u.item.latestActivity}),(0,z.jsxs)(`dl`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Goal`}),(0,z.jsx)(`dd`,{children:u.item.goalTitle})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.progress`)}),(0,z.jsxs)(`dd`,{children:[u.item.completedSteps,`/`,u.item.totalSteps]})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.sessionStatus`)}),(0,z.jsx)(`dd`,{children:Xi(u.item.sessionStatus??u.item.status,f)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.sessionRecoverable`)}),(0,z.jsx)(`dd`,{children:u.item.resumable===!1?f(`drawer.resumeNo`):f(`drawer.resumeYes`)})]})]})]}),u.item.sessionStatus===`resume_failed`&&!c?(0,z.jsxs)(`section`,{className:`personal-recovery-panel`,"aria-label":f(`drawer.recoveryFailed`),children:[(0,z.jsx)(`strong`,{children:f(`drawer.recoveryFailed`)}),(0,z.jsx)(`p`,{children:f(`drawer.recoveryDescription`)}),(0,z.jsxs)(`button`,{className:`personal-primary-action`,onClick:()=>void t.onRetryResumeRun?.(u.item),type:`button`,children:[(0,z.jsx)(km,{size:16}),f(`drawer.recoveryRetry`)]}),(0,z.jsxs)(`button`,{className:`personal-secondary-action`,onClick:()=>void t.onStartNewRunSession?.(u.item),type:`button`,children:[(0,z.jsx)(Tm,{size:16}),f(`drawer.recoveryNewSession`)]})]}):null,c?null:(0,z.jsxs)(`section`,{className:`personal-correction-panel`,children:[(0,z.jsx)(`header`,{children:(0,z.jsxs)(`span`,{children:[(0,z.jsx)(Up,{size:16}),f(`drawer.correctionLabel`,{agent:u.item.agentLabel})]})}),(0,z.jsx)(`p`,{children:f(`drawer.correctionDescription`)}),(0,z.jsxs)(`div`,{className:`personal-correction-composer`,children:[(0,z.jsx)(`textarea`,{"aria-label":f(`drawer.correctionTextarea`,{agent:u.item.agentLabel,goal:u.item.goalTitle,run:u.item.title}),onChange:e=>m(e.target.value),placeholder:f(`drawer.correctionPlaceholder`),rows:3,value:p}),(0,z.jsx)(`button`,{"aria-label":f(`drawer.correctionSend`),disabled:!p.trim(),onClick:()=>void ge(),type:`button`,children:(0,z.jsx)(Mm,{size:16})})]})]}),c?null:(0,z.jsxs)(`details`,{className:`personal-compact-menu personal-run-more`,children:[(0,z.jsxs)(`summary`,{children:[(0,z.jsx)(rm,{size:17}),f(`drawer.moreRunActions`)]}),(0,z.jsxs)(`div`,{children:[(0,z.jsxs)(`button`,{disabled:!u.item.canInterrupt,onClick:()=>void t.onInterruptRun?.(u.item),type:`button`,children:[(0,z.jsx)(wm,{size:16}),f(`drawer.runInterrupt`)]}),(0,z.jsxs)(`button`,{disabled:u.item.resumable===!1,onClick:()=>void t.onRetryResumeRun?.(u.item),type:`button`,children:[(0,z.jsx)(km,{size:16}),f(`drawer.recoveryRetry`)]}),(0,z.jsxs)(`button`,{onClick:()=>void t.onStartNewRunSession?.(u.item),type:`button`,children:[(0,z.jsx)(Tm,{size:16}),f(`drawer.runNewSession`)]}),(0,z.jsxs)(`button`,{onClick:()=>void t.onCloseRunSession?.(u.item),type:`button`,children:[(0,z.jsx)(zm,{size:16}),f(`drawer.runCloseSession`)]})]})]})]})]}):null,u.kind===`output`?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`section`,{className:`personal-detail-card`,children:[(0,z.jsx)(`small`,{children:u.item.kind??`output`}),(0,z.jsx)(`h3`,{children:u.item.title}),(0,z.jsx)(`p`,{children:u.item.summary??f(`drawer.outputRecorded`)}),(0,z.jsxs)(`dl`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Goal`}),(0,z.jsx)(`dd`,{children:u.item.goalTitle??u.item.goalId})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.outputTodo`)}),(0,z.jsx)(`dd`,{children:u.item.todoId??f(`drawer.notLinked`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.outputRun`)}),(0,z.jsx)(`dd`,{children:u.item.runId??f(`drawer.notLinked`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Agent`}),(0,z.jsx)(`dd`,{children:u.item.agentLabel??u.item.agentId??`LoopX`})]})]})]}),u.item.report?(0,z.jsxs)(`section`,{className:`personal-report-detail`,"data-testid":`personal-periodic-report-detail`,children:[(0,z.jsxs)(`header`,{children:[(0,z.jsxs)(`span`,{children:[(0,z.jsxs)(`strong`,{children:[`+`,u.item.report.addedCount]}),f(`files.reportAdded`)]}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:u.item.report.changedCount}),f(`files.reportChanged`)]})]}),(0,z.jsxs)(`p`,{children:[u.item.report.periodStartAt,` → `,u.item.report.periodEndAt]}),(0,z.jsx)(`ol`,{children:u.item.report.items.map(e=>(0,z.jsxs)(`li`,{"data-change-kind":e.changeKind,children:[(0,z.jsxs)(`small`,{children:[e.changeKind,` · `,e.status]}),(0,z.jsx)(`strong`,{children:e.title}),(0,z.jsx)(`p`,{children:e.summary})]},e.sourceRef))}),(0,z.jsxs)(`footer`,{children:[(0,z.jsxs)(`span`,{children:[f(`files.reportPublication`),`: `,u.item.report.publicationId]}),(0,z.jsxs)(`span`,{children:[f(`files.reportGeneration`),`: `,u.item.report.generationId]})]})]}):null,u.item.safePreview?(0,z.jsx)(`pre`,{"aria-label":f(`drawer.outputSafePreview`),className:`personal-safe-preview`,children:u.item.safePreview}):(0,z.jsx)(`p`,{className:`personal-preview-unavailable`,children:f(`drawer.previewUnavailable`)}),(0,z.jsxs)(`div`,{className:`personal-drawer-action-grid`,children:[(0,z.jsxs)(`button`,{className:`personal-primary-action`,disabled:!t.onOpenOutput,onClick:()=>{t.onOpenOutput?.(u.item),o()},type:`button`,children:[(0,z.jsx)(im,{size:16}),f(`files.openConversation`)]}),(0,z.jsxs)(`button`,{className:`personal-secondary-action`,disabled:!t.onExportOutput,onClick:()=>void t.onExportOutput?.(u.item),type:`button`,children:[(0,z.jsx)(nm,{size:16}),f(`files.exportSummary`)]})]})]}):null,u.kind===`proposal`?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`section`,{className:`personal-proposal-card`,children:[(0,z.jsxs)(`small`,{children:[u.item.actionKind,` · `,u.item.status]}),(0,z.jsx)(`h3`,{children:u.item.title}),(0,z.jsx)(`p`,{children:u.item.impact}),u.item.status===`ready`?(0,z.jsx)(`p`,{className:`personal-proposal-explainer`,children:f(`drawer.proposalExplainer`)}):null,(0,z.jsx)(`dl`,{children:u.item.fields.map(e=>(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:e.label}),(0,z.jsx)(`dd`,{children:e.value})]},e.key))})]}),u.item.status===`applied`?(0,z.jsxs)(`p`,{className:`personal-proposal-state is-applied`,children:[(0,z.jsx)(Kp,{size:16}),f(`drawer.proposalApplied`)]}):null,u.item.status===`applied`&&u.item.goalId?(0,z.jsxs)(`button`,{className:`personal-primary-action`,onClick:()=>{let e=u.item.goalId;o(),t.onOpenGoal?.(e)},type:`button`,children:[(0,z.jsx)(im,{size:16}),u.item.actionKind===`goal.create`?f(`drawer.proposalEnterGoal`):f(`drawer.proposalViewGoal`)]}):null,u.item.status===`stale`?(0,z.jsx)(`p`,{className:`personal-proposal-state is-stale`,children:f(`drawer.proposalStale`)}):null,u.item.status===`error`?(0,z.jsxs)(`div`,{className:`personal-proposal-state is-error`,children:[(0,z.jsx)(`span`,{children:f(`drawer.proposalApplyFailed`)}),u.item.errorMessage?(0,z.jsx)(`small`,{children:u.item.errorMessage}):null,(0,z.jsx)(`small`,{children:f(`drawer.proposalApplyFailedHint`)})]}):null,u.item.status===`rejected`?(0,z.jsx)(`p`,{className:`personal-proposal-state is-error`,children:f(`drawer.proposalRejected`)}):null,u.item.status===`deferred`?(0,z.jsx)(`p`,{className:`personal-proposal-state is-gated`,children:f(`drawer.proposalDeferred`)}):null,u.item.status===`gated`?(0,z.jsxs)(`div`,{className:`personal-proposal-state is-gated`,children:[(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:f(`drawer.gateRequiresHost`)}),f(`drawer.gateRequiresHostDescription`)]}),u.item.gate?.nextAction?(0,z.jsx)(`small`,{children:u.item.gate.nextAction}):null]}):null,u.item.status===`gated`&&u.item.actionKind===`gate.resolve`?(()=>{let e=e=>u.item.fields.find(t=>t.key===e)?.value,t=e(`goal_id`),n=e(`todo_id`);return!t||!n?null:(0,z.jsxs)(`section`,{className:`personal-detail-card personal-gate-cli-hint`,children:[(0,z.jsx)(`small`,{children:f(`drawer.gateApproveHint`)}),(0,z.jsxs)(`code`,{children:[`loopx todo complete --goal-id `,t,` --todo-id `,n,` --decision-outcome approve`]}),(0,z.jsx)(`small`,{children:f(`drawer.gateRejectHint`)})]})})():null,!c&&u.item.workspaceCandidates?.length?(0,z.jsx)(`div`,{className:`personal-workspace-candidates`,"aria-label":f(`drawer.workspaceCandidates`),children:u.item.workspaceCandidates.map(e=>(0,z.jsxs)(`button`,{onClick:()=>void t.onSelectWorkspaceCandidate?.(u.item,e.workspaceRef),type:`button`,children:[(0,z.jsx)(`strong`,{children:e.label}),(0,z.jsx)(`small`,{children:e.workspaceRef})]},e.workspaceRef))}):null,!c&&u.item.status===`error`?(0,z.jsxs)(`button`,{className:`personal-primary-action`,onClick:()=>void t.onTransitionProposal?.(u.item,`regenerate`),type:`button`,children:[(0,z.jsx)(km,{size:17}),f(`drawer.proposalRegenerate`)]}):!c&&u.item.status!==`gated`?(0,z.jsxs)(`button`,{className:`personal-primary-action`,disabled:![`ready`,`deferred`].includes(u.item.status),onClick:()=>void t.onApplyProposal?.(u.item),type:`button`,children:[(0,z.jsx)(Kp,{size:17}),u.item.status===`applying`?f(`drawer.applying`):u.item.primaryLabel??f(`drawer.apply`)]}):null,!c&&[`stale`,`gated`,`rejected`].includes(u.item.status)?(0,z.jsxs)(`button`,{className:`personal-secondary-action`,onClick:()=>void t.onTransitionProposal?.(u.item,`regenerate`),type:`button`,children:[(0,z.jsx)(km,{size:16}),f(`drawer.proposalRecheck`)]}):null,!c&&[`ready`,`gated`].includes(u.item.status)?(0,z.jsxs)(`div`,{className:`personal-drawer-action-grid`,children:[(0,z.jsx)(`button`,{className:`personal-secondary-action`,onClick:()=>void t.onTransitionProposal?.(u.item,`defer`),type:`button`,children:f(`drawer.proposalDefer`)}),(0,z.jsx)(`button`,{className:`personal-secondary-action`,onClick:()=>void t.onTransitionProposal?.(u.item,`reject`),type:`button`,children:f(`drawer.decisionReject`)})]}):null,[`applied`,`applying`].includes(u.item.status)?null:(0,z.jsx)(`button`,{className:`personal-secondary-action`,onClick:o,type:`button`,children:f(`drawer.proposalClose`)})]}):null,u.kind===`schedule`?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`section`,{className:`personal-detail-card`,children:[(0,z.jsxs)(`small`,{children:[u.item.scheduleKind===`heartbeat`?`Goal Heartbeat`:`continuous_monitor`,` · `,u.item.status??`active`]}),(0,z.jsx)(`h3`,{children:u.item.label}),(0,z.jsx)(`p`,{children:u.item.target??u.item.schedule??f(`drawer.scheduleDefaultTarget`)}),(0,z.jsxs)(`dl`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.scheduleTimezone`)}),(0,z.jsx)(`dd`,{children:u.item.timezone??f(`drawer.scheduleLocalTimezone`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.scheduleNext`)}),(0,z.jsx)(`dd`,{children:u.item.nextRunAt??f(`drawer.schedulePending`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.scheduleLast`)}),(0,z.jsx)(`dd`,{children:u.item.previousRunAt??f(`drawer.scheduleNeverRun`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.scheduleNotification`)}),(0,z.jsx)(`dd`,{children:u.item.notificationRule??f(`drawer.scheduleDefaultNotification`)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:f(`drawer.scheduleStopCondition`)}),(0,z.jsx)(`dd`,{children:u.item.stopCondition??f(`drawer.scheduleDefaultStop`)})]})]})]}),!c&&u.item.scheduleKind===`monitor`?(0,z.jsxs)(`button`,{className:`personal-primary-action`,onClick:()=>void t.onUpdateSchedule?.(u.item,`run_now`),type:`button`,children:[(0,z.jsx)(Tm,{size:16}),f(`drawer.scheduleRunNow`)]}):null,c?null:(0,z.jsxs)(`div`,{className:`personal-drawer-action-grid`,children:[(0,z.jsxs)(`button`,{className:`personal-secondary-action`,onClick:()=>void t.onUpdateSchedule?.(u.item,u.item.status===`paused`?`resume`:`pause`),type:`button`,children:[u.item.status===`paused`?(0,z.jsx)(Tm,{size:16}):(0,z.jsx)(wm,{size:16}),u.item.status===`paused`?f(`drawer.scheduleResume`):f(`drawer.schedulePause`)]}),(0,z.jsxs)(`button`,{className:`personal-secondary-action`,onClick:()=>void t.onUpdateSchedule?.(u.item,`edit`),type:`button`,children:[(0,z.jsx)(Gp,{size:16}),f(`drawer.scheduleEdit`)]})]}),c?null:(0,z.jsxs)(`button`,{className:`personal-danger-action`,onClick:()=>void t.onUpdateSchedule?.(u.item,`stop`),type:`button`,children:[(0,z.jsx)(zm,{size:16}),f(`drawer.scheduleStop`,{kind:u.item.scheduleKind===`heartbeat`?` Heartbeat`:f(`drawer.titleSchedule`)})]}),(0,z.jsxs)(`section`,{className:`personal-execution-history`,"aria-labelledby":`personal-execution-history-title`,children:[(0,z.jsx)(`h3`,{id:`personal-execution-history-title`,children:f(`drawer.executionHistory`)}),u.item.executionHistory?.length?(0,z.jsx)(`ol`,{children:u.item.executionHistory.map((e,t)=>(0,z.jsxs)(`li`,{children:[(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:e.label}),(0,z.jsx)(`small`,{children:e.timestamp})]}),(0,z.jsx)(`em`,{className:`is-${e.status}`,children:e.status})]},`${e.timestamp}:${e.runId??t}`))}):(0,z.jsx)(`p`,{children:f(`drawer.noExecutionHistory`)})]})]}):null,u.kind===`run`||u.kind===`proposal`||u.kind===`schedule`?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`button`,{"aria-expanded":h,className:`personal-diagnostics-trigger`,onClick:()=>g(e=>!e),type:`button`,children:[(0,z.jsx)(`span`,{children:f(`drawer.advancedDiagnostics`)}),(0,z.jsx)(qp,{className:h?`is-open`:``,size:16})]}),h?(0,z.jsxs)(`div`,{className:`personal-diagnostics`,children:[(0,z.jsxs)(`code`,{children:[`goal_id: `,ue]}),(0,z.jsxs)(`code`,{children:[`kind: `,u.kind]}),u.kind===`run`?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`code`,{children:[`session_id: `,u.item.sessionId??f(`drawer.notLinked`)]}),(0,z.jsxs)(`code`,{children:[`turn_id: `,u.item.turnId??f(`common.none`)]}),(0,z.jsxs)(`code`,{children:[`adapter: `,u.item.agentId]}),(0,z.jsxs)(`code`,{children:[`status: `,u.item.sessionStatus??u.item.status]})]}):u.kind===`proposal`?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`code`,{children:[`action: `,u.item.actionKind]}),(0,z.jsxs)(`code`,{children:[`status: `,u.item.status]})]}):(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`code`,{children:[`schedule_id: `,u.item.scheduleId]}),(0,z.jsxs)(`code`,{children:[`status: `,u.item.status??`active`]})]})]}):null]}):null]})]})}var Iy=[`checking`,`connecting`,`downloading`,`installing_app`,`installing_runtime`],Ly={desktop_status_unavailable:[`无法读取 App 更新状态。请重启 App 后再试;若仍失败,请重新安装最新 App。`,`Cannot read the App update status. Restart the App; if this persists, reinstall the latest App.`],update_feed_unavailable:[`此通道的更新源尚未就绪或暂时不可用。可稍后重新检查,当前版本仍可继续使用。`,`This channel's update feed is not ready or temporarily unavailable. Check again later; you can keep using this version.`],update_feed_invalid:[`更新源格式异常。请稍后重新检查。`,`The update feed is invalid. Check again later.`],update_platform_unavailable:[`此通道尚无适用于本机的更新包。`,`This channel has no update package for this platform.`],update_check_timeout:[`检查更新超时。请稍后重试。`,`The update check timed out. Try again later.`],update_network_failed:[`无法连接更新服务器。请检查网络后重试。`,`Cannot reach the update server. Check your connection and retry.`],update_download_or_signature_failed:[`更新包下载或签名校验失败,尚未安装。请重新检查更新。`,`Download or signature verification failed; the update was not installed. Check for updates again.`]};function Ry(e,t=`update_failed`){return{phase:`error`,details:{code:typeof e==`string`&&Object.hasOwn(Ly,e)?e:t}}}function zy(){let{locale:e}=Ji(),t=e===`zh-CN`,[n,r]=(0,R.useState)(!1),i=(0,R.useRef)(null),[a,o]=(0,R.useState)(`stable`),[s,c]=(0,R.useState)({phase:`idle`}),[l,u]=(0,R.useState)(``),[d,f]=(0,R.useState)(!1),p=(0,R.useRef)(!1),m=window.__TAURI__?.core.invoke,h=Iy.includes(s.phase);(0,R.useEffect)(()=>{let e=i.current;if(!e)return;let t=()=>r(e.matches(`:popover-open`));return e.addEventListener(`toggle`,t),()=>e.removeEventListener(`toggle`,t)},[]),(0,R.useEffect)(()=>{if(!m)return;let e=!0;return m(`desktop_update_status`).then(t=>{if(!e)return;u(t.app_version),f(t.rollback_available===!0),t.state?.phase&&c(t.state);let n=t.state?.details?.channel??(t.app_version.includes(`-main.`)?`main`:`stable`);o(n),t.state?.phase||m(`desktop_update`,{action:`check`,channel:n}).then(t=>{e&&c(t)}).catch(t=>{e&&c(Ry(t))})}).catch(()=>{e&&c(Ry(null,`desktop_status_unavailable`))}),()=>{e=!1}},[m]),(0,R.useEffect)(()=>{if(!m||!h)return;let e=window.setInterval(()=>{m(`desktop_update_status`).then(e=>{e.state?.phase&&c(e.state)}).catch(()=>{})},1e3);return()=>window.clearInterval(e)},[m,h]);async function g(e){if(!(!m||p.current)){p.current=!0,c({phase:e===`check`?`checking`:e===`repair`?`installing_runtime`:`downloading`});try{if(!l){let e=await m(`desktop_update_status`);u(e.app_version),f(e.rollback_available===!0)}c(await m(`desktop_update`,{action:e,channel:a}))}catch(e){c(Ry(e,l?`update_failed`:`desktop_status_unavailable`))}finally{p.current=!1}}}let _={service_error:t?`运行时已安装,但服务尚未连接。可重试更新、修复或恢复上版。`:`Runtime installed, but services are unavailable. Retry updates, repair, or restore the previous version.`,idle:t?`App 会检查可用更新,不会自动安装。`:`Updates are checked automatically, never installed without confirmation.`,runtime_required:t?`请完成匹配组件安装,或检查 App 更新。`:`Install matching components or check for an App update.`,connecting:t?`正在连接更新后的服务…`:`Connecting to updated services…`,checking:t?`正在检查更新…`:`Checking for updates…`,available:t?`新版本已就绪,一次更新 App 与匹配的运行时。`:`Update the App and its matching runtime together.`,up_to_date:t?`当前通道暂无更新。`:`No newer update on this channel.`,downloading:t?`正在下载并校验签名…`:`Downloading and verifying signature…`,installing_app:t?`正在安装 App,请保持窗口打开。`:`Installing the App. Keep this window open.`,installing_runtime:t?`正在安装匹配的运行时,请稍候…`:`Installing the matching runtime…`,restart_required:t?`重启后将自动完成运行时安装与服务连接。`:`Restart to finish runtime installation and reconnect services.`,ready:t?`更新完成,服务已就绪。`:`Update completed; services are ready.`,error:Ly[s.details?.code??``]?.[+!t]??(t?`更新未完成。请重试;启动失败可尝试修复当前版本。`:`Update incomplete. Retry; repair this version if startup fails.`)},v=h?t?`正在更新…`:`Updating…`:s.phase===`available`?t?`有可用更新`:`Update available`:s.phase===`restart_required`?t?`重启完成更新`:`Restart to finish`:s.phase===`error`?t?`更新需重试`:`Retry update`:t?`更新 LoopX`:`Update LoopX`;return(0,z.jsxs)(`div`,{className:`personal-desktop-update`,children:[(0,z.jsxs)(`button`,{className:`personal-update-trigger`,type:`button`,"aria-expanded":n,"aria-controls":`desktop-update-panel`,onClick:e=>{i.current?.style.setProperty(`bottom`,`${window.innerHeight-e.currentTarget.getBoundingClientRect().top+8}px`),i.current?.togglePopover()},children:[(0,z.jsx)(nm,{size:16,"aria-hidden":`true`}),(0,z.jsx)(`span`,{children:v}),(0,z.jsx)(Yp,{size:14,"aria-hidden":`true`})]}),(0,z.jsxs)(`section`,{ref:i,popover:`auto`,id:`desktop-update-panel`,className:`personal-update-panel`,"aria-label":t?`LoopX 更新`:`LoopX updates`,children:[(0,z.jsxs)(`header`,{children:[(0,z.jsx)(`strong`,{children:t?`LoopX 更新`:`LoopX updates`}),(0,z.jsx)(`button`,{type:`button`,"aria-label":t?`关闭更新面板`:`Close updates`,onClick:()=>i.current?.hidePopover(),children:(0,z.jsx)(Gm,{size:16,"aria-hidden":`true`})})]}),(0,z.jsxs)(`small`,{children:[l,` · `,a===`main`?t?`main 预览版`:`main preview`:t?`稳定版`:`Stable`]}),s.details?.version?(0,z.jsxs)(`p`,{children:[t?`目标版本:`:`Target: `,s.details.version]}):null,(0,z.jsxs)(`p`,{role:`status`,"aria-live":`polite`,children:[h?(0,z.jsx)(Om,{className:`is-spinning`,size:14,"aria-hidden":`true`}):null,_[s.phase]]}),s.phase===`downloading`&&s.details?.total?(0,z.jsx)(`progress`,{"aria-label":t?`下载进度`:`Download progress`,max:s.details.total,value:s.details.received??0}):null,m?(0,z.jsx)(`div`,{className:`personal-update-actions`,children:s.phase===`restart_required`?(0,z.jsx)(`button`,{type:`button`,onClick:()=>void g(`restart`),children:t?`重启完成更新`:`Restart to finish`}):(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`button`,{type:`button`,disabled:h,onClick:()=>void g(`check`),children:t?`检查更新`:`Check for updates`}),s.phase===`available`?(0,z.jsx)(`button`,{type:`button`,onClick:()=>void g(`apply`),children:t?`更新并准备重启`:`Install update`}):null]})}):(0,z.jsx)(`p`,{children:t?`请在 LoopX App 中更新;浏览器自身无需安装包。`:`Update from the LoopX App; the browser needs no installer.`}),(0,z.jsxs)(`details`,{children:[(0,z.jsx)(`summary`,{children:t?`高级选项`:`Advanced options`}),(0,z.jsxs)(`label`,{children:[t?`更新通道`:`Update channel`,(0,z.jsxs)(`select`,{disabled:h||s.phase===`restart_required`,value:a,onChange:e=>{o(e.target.value),c({phase:`idle`})},children:[(0,z.jsx)(`option`,{value:`stable`,children:t?`稳定版(推荐)`:`Stable (recommended)`}),(0,z.jsx)(`option`,{value:`main`,children:t?`main 预览版`:`main preview`})]})]}),(0,z.jsx)(`p`,{children:t?`App 与匹配的 CLI 一起更新,服务可能短暂断开。不删除 Goal 数据。`:`Updates the App and matching CLI. Services may briefly disconnect. Goal data is not deleted.`}),m?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`p`,{children:t?`启动失败时,可重装当前 App 随附的运行时。`:`If startup fails, reinstall this App's bundled runtime.`}),(0,z.jsx)(`button`,{disabled:h||s.phase===`restart_required`,type:`button`,onClick:()=>void g(`repair`),children:t?`修复当前版本`:`Repair this version`})]}):null,m&&d?(0,z.jsxs)(`details`,{children:[(0,z.jsx)(`summary`,{children:t?`恢复上个版本`:`Restore previous version`}),(0,z.jsx)(`p`,{children:t?`将恢复已保留的 App 和它的运行时,需要重启。`:`Restore the retained App and its runtime, then restart.`}),(0,z.jsx)(`button`,{disabled:h,type:`button`,onClick:()=>void g(`rollback`),children:t?`确认恢复上版`:`Restore previous version`})]}):null]})]})]})}var By=e=>`loopx-sidebar-goal-order-v1:${encodeURIComponent(e)}`;function Vy(e){try{let t=JSON.parse(e??`null`);return Array.isArray(t)&&t.every(e=>typeof e==`string`)?[...new Set(t)]:[]}catch{return[]}}function Hy(e,t){let n=new Map(t.map((e,t)=>[e,t]));return[...e].sort((e,t)=>(n.get(e.goalId)??1/0)-(n.get(t.goalId)??1/0))}function Uy(e,t,n,r,i){if(n===r||!t.includes(n)||!t.includes(r))return e;let a=[...new Set([...e,...t])].filter(e=>e!==n);return a.splice(a.indexOf(r)+Number(i),0,n),a}function Wy(e,t){let n=By(t),[r,i]=(0,R.useState)(()=>{try{return Vy(localStorage.getItem(n))}catch{return[]}}),[a,o]=(0,R.useState)(!1),[s,c]=(0,R.useState)(null),[l,u]=(0,R.useState)(null),d=(0,R.useRef)(null),f=(0,R.useRef)(!1),p=Hy(e,r),m=p.map(e=>e.goalId);function h(t,a,s){let l=Uy(r,m,t,a,s);if(l===r)return;i(l);let u=Hy(e,l),d=u.findIndex(e=>e.goalId===t),f=u[d];f&&c({title:f.title,position:d+1});try{localStorage.setItem(n,JSON.stringify(l)),o(!1)}catch{o(!0)}}function g(){d.current=null,u(null)}return{sorted:p,target:l,saveFailed:a,lastMoved:s,move:h,moveBy(e,t){let n=p[m.indexOf(e)+t];n&&h(e,n.goalId,t===1)},pointerProps:e=>({onPointerDown(t){f.current=!1,t.pointerType===`mouse`&&t.button===0&&(d.current={id:e,x:t.clientX,y:t.clientY,dragging:!1},t.currentTarget.setPointerCapture(t.pointerId))},onPointerMove(e){let t=d.current;if(!t||!t.dragging&&Math.hypot(e.clientX-t.x,e.clientY-t.y)<6)return;t.dragging=!0,f.current=!0;let n=document.elementFromPoint(e.clientX,e.clientY)?.closest(`[data-reorder-goal]`),r=e.currentTarget.closest(`.personal-goal-list`),i=n?.dataset.reorderGoal;if(!n||!i||!r?.contains(n)||i===t.id){u(null);return}let a=n.getBoundingClientRect();u({id:i,after:e.clientY>a.top+a.height/2})},onPointerUp(){d.current?.dragging&&l&&h(d.current.id,l.id,l.after),g()},onPointerCancel:g,onLostPointerCapture:g,onKeyDown(e){e.key===`Escape`&&g()},onClickCapture(e){f.current&&=(e.preventDefault(),e.stopPropagation(),!1)}})}}var Gy=`/ssh-hosts`,Ky=/^[A-Za-z0-9][A-Za-z0-9._-]{0,254}$/;function qy(e){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`SSH Host 列表响应无效。`);let t=e;if(t.ok!==!0||t.schema_version!==`ssh_host_catalog_v0`||!Array.isArray(t.hosts))throw Error(`SSH Host 列表协议不兼容,请更新本机 LoopX 服务。`);let n=new Set;return{hosts:t.hosts.flatMap(e=>{if(!e||typeof e!=`object`||Array.isArray(e))return[];let t=String(e.alias??``).trim();return!Ky.test(t)||n.has(t)?[]:(n.add(t),[{alias:t}])}),schemaVersion:`ssh_host_catalog_v0`}}async function Jy(e=fetch,t=Gy){let n=await e(t,{cache:`no-store`});if(!n.ok)throw Error(`无法读取本机 SSH Host(HTTP ${n.status})。`);return qy(await n.json())}function Yy(e,t){let n=e.trim();if(!Ky.test(n))return{error:`请选择有效的 SSH Host。`};let r=Number(t);return!Number.isInteger(r)||r<1024||r>65535?{error:`本地端口必须是 1024–65535 之间的整数。`}:{command:`ssh -N -L ${r}:127.0.0.1:8766 ${n}`,label:n,statusUrl:`http://127.0.0.1:${r}/status.json`}}var Xy=`/api/ssh-source/ensure`;async function Zy(e,t){let n=await fetch(Xy,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({host_alias:e,local_port:Number(t)})}),r=await n.json().catch(()=>null);if(!n.ok)throw Error(r?.error??`无法建立 SSH 隧道来源。`);if(!r?.ok)throw Error(`无法建立 SSH 隧道来源。`);return r}function Qy({activeSource:e,connectionState:t,errorMessage:n,onAdd:r,onRemove:i,onSelect:a,sources:o}){let{t:s}=Ji(),[c,l]=(0,R.useState)(!1),[u,d]=(0,R.useState)(null),[f,p]=(0,R.useState)(`configured`),[m,h]=(0,R.useState)([]),[g,_]=(0,R.useState)(null),[v,y]=(0,R.useState)(!1),[b,x]=(0,R.useState)(!1),[S,C]=(0,R.useState)(``),[w,T]=(0,R.useState)(``),[E,D]=(0,R.useState)(`8876`),[O,k]=(0,R.useState)(``),ee=`configured:`,A=[...o.map(e=>({label:e.label,value:e.id})),...m.filter(e=>!o.some(t=>t.label===e.alias)).map(e=>({group:s(`source.configuredGroup`,{count:m.length}),label:e.alias,value:`${ee}${e.alias}`}))],j=(0,R.useMemo)(()=>m.some(e=>e.alias===S)?Yy(S,E):{error:s(`source.selectHost`)},[m,S,E,s]);(0,R.useEffect)(()=>{te()},[]);async function te(){y(!0),_(null);try{let e=await Jy();h(e.hosts),C(t=>t||e.hosts[0]?.alias||``),e.hosts.length||_(s(`source.hostEmpty`))}catch(e){_(e instanceof Error?e.message:s(`source.hostLoadError`))}finally{y(!1)}}function ne(){l(!0),p(`configured`),d(null),te()}function re(){l(!1),p(`configured`),_(null),x(!1),C(``),d(null),T(``),D(`8876`),k(``)}function M(){let e=r({label:w,statusUrl:O});if(e.error){d(e.error);return}re()}function N(){if(`error`in j){d(j.error??s(`source.invalid`));return}let e=r({ensureTunnel:!0,label:j.label,statusUrl:j.statusUrl});if(e.error){d(e.error);return}re()}function ie(e){let t=new Set;for(let e of o)try{t.add(new URL(e.statusUrl).port)}catch{}let n=`8877`;for(let e=8877;e<9077;e+=1)if(!t.has(String(e))){n=String(e);break}let i=Yy(e,n);if(`error`in i){d(i.error??s(`source.invalid`));return}let a=r({ensureTunnel:!0,label:i.label,statusUrl:i.statusUrl});a.error?d(a.error):d(null),D(n)}async function ae(){if(`error`in j){d(j.error??s(`source.invalid`));return}try{await navigator.clipboard.writeText(j.command),x(!0),d(null)}catch{d(s(`source.copyError`))}}return(0,z.jsxs)(`section`,{"aria-label":s(`source.controlPlane`),className:`personal-status-source`,children:[(0,z.jsxs)(`header`,{children:[(0,z.jsx)(`span`,{children:`Control plane`}),(0,z.jsx)(`button`,{"aria-label":s(`source.addSsh`),onClick:ne,title:s(`source.add`),type:`button`,children:(0,z.jsx)(Em,{size:14})})]}),(0,z.jsx)(cy,{ariaLabel:s(`source.select`),className:`personal-status-source-select`,icon:(0,z.jsx)(Pm,{size:15}),onChange:e=>{if(e.startsWith(ee)){ie(e.slice(11));return}a(e)},options:A,value:e.id}),(0,z.jsxs)(`div`,{className:`personal-status-source-meta`,children:[(0,z.jsxs)(`span`,{className:`is-${t}`,children:[(0,z.jsx)(`i`,{}),s(t===`loading`?`source.connecting`:t===`error`?`source.notAvailable`:`source.connected`)]}),(0,z.jsx)(`small`,{children:e.readOnly?s(`source.readOnly`):s(`source.localInteractive`)}),e.kind===`ssh_tunnel`?(0,z.jsx)(`button`,{"aria-label":s(`source.remove`,{source:e.label}),onClick:()=>i(e.id),title:s(`source.removeCurrent`),type:`button`,children:(0,z.jsx)(Hm,{size:12})}):null]}),n?(0,z.jsx)(`p`,{className:`personal-status-source-error`,role:`alert`,children:n}):null,c?(0,z.jsxs)(`div`,{className:`personal-status-source-form`,children:[(0,z.jsxs)(`header`,{children:[(0,z.jsx)(`strong`,{children:s(`source.addSsh`)}),(0,z.jsx)(`button`,{"aria-label":s(`source.closeForm`),onClick:re,type:`button`,children:(0,z.jsx)(Gm,{size:13})})]}),(0,z.jsxs)(`div`,{"aria-label":s(`source.addMethod`),className:`personal-status-source-modes`,role:`tablist`,children:[(0,z.jsx)(`button`,{"aria-selected":f===`configured`,onClick:()=>{p(`configured`),d(null)},role:`tab`,type:`button`,children:s(`source.configured`)}),(0,z.jsx)(`button`,{"aria-selected":f===`manual`,onClick:()=>{p(`manual`),d(null)},role:`tab`,type:`button`,children:s(`source.manual`)})]}),f===`configured`?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:s(`source.configuredCount`,{count:m.length})}),(0,z.jsxs)(`span`,{className:`personal-status-source-field-row`,children:[(0,z.jsx)(`input`,{"aria-label":s(`source.host`),disabled:v||!m.length,list:`loopx-configured-ssh-hosts`,onChange:e=>{C(e.target.value),x(!1)},placeholder:s(v?`source.loadingHosts`:`source.hostPlaceholder`),value:S}),(0,z.jsx)(`datalist`,{id:`loopx-configured-ssh-hosts`,children:m.map(e=>(0,z.jsx)(`option`,{value:e.alias},e.alias))}),(0,z.jsx)(`button`,{"aria-label":s(`source.refreshHosts`),disabled:v,onClick:()=>void te(),title:s(`source.refreshHosts`),type:`button`,children:(0,z.jsx)(Am,{size:13})})]})]}),(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:s(`source.localPort`)}),(0,z.jsx)(`input`,{"aria-label":s(`source.localPort`),inputMode:`numeric`,onChange:e=>{D(e.target.value),x(!1)},value:E})]}),(0,z.jsxs)(`div`,{className:`personal-status-source-command`,children:[(0,z.jsx)(`code`,{children:`error`in j?s(`source.tunnelCommandPending`):j.command}),(0,z.jsxs)(`button`,{"aria-label":s(`source.copyCommand`),disabled:`error`in j,onClick:()=>void ae(),type:`button`,children:[(0,z.jsx)(em,{size:12}),s(b?`source.copied`:`source.copy`)]})]}),g?(0,z.jsx)(`p`,{className:`is-error`,children:g}):null,(0,z.jsx)(`p`,{children:s(`source.description`)}),(0,z.jsx)(`button`,{className:`personal-status-source-add`,disabled:`error`in j,onClick:N,type:`button`,children:s(`source.addConfigured`)})]}):(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:s(`source.name`)}),(0,z.jsx)(`input`,{autoFocus:!0,maxLength:48,onChange:e=>T(e.target.value),placeholder:s(`source.namePlaceholder`),value:w})]}),(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:s(`source.statusUrl`)}),(0,z.jsx)(`input`,{onChange:e=>k(e.target.value),placeholder:`http://127.0.0.1:8876/status.json`,value:O})]}),(0,z.jsx)(`p`,{children:(0,z.jsx)(`code`,{children:`ssh -N -L 8876:127.0.0.1:8766 `})}),(0,z.jsx)(`p`,{children:s(`source.manualDescription`)}),(0,z.jsx)(`button`,{className:`personal-status-source-add`,onClick:M,type:`button`,children:s(`source.addConfigured`)})]}),u?(0,z.jsx)(`p`,{className:`is-error`,role:`alert`,children:u}):null]}):null]})}var $y={需修复:`is-danger`,等你:`is-warning`,等待条件:`is-info`,推进中:`is-success`,安静运行:`is-quiet`,已完成:`is-quiet`,已停止:`is-stopped`};function eb({attentionCount:e,goals:t,goalArchiveLoadState:n={error:null,phase:`ready`},lifecycleBusyGoalIds:r,onRequestGoalCreate:i,onOpenSettings:a,onRetryGoalArchive:o,onRequestGoalLifecycle:s,onSelectGoal:c,selectedGoalId:l,statusSourceControl:u}){let{locale:d,t:f}=Ji(),[p,m]=(0,R.useState)(!1),h=Wy(t.filter(e=>e.activationState!==`stopped`),u?.activeSource.statusUrl??`/status.json`),g=h.sorted,_=t.filter(e=>e.activationState===`stopped`),v=(e,t)=>(0,z.jsxs)(`div`,{className:`personal-goal-row${h.target?.id===e.goalId?h.target.after?` is-drop-after`:` is-drop-before`:``}`,"data-reorder-goal":t?void 0:e.goalId,"data-load-error":e.loadError,children:[(0,z.jsxs)(`button`,{...t?{}:h.pointerProps(e.goalId),title:t?void 0:f(`sidebar.dragGoal`),"aria-current":l===e.goalId?`page`:void 0,className:`personal-goal-link`,onClick:()=>c(e.goalId),type:`button`,children:[(0,z.jsx)(`span`,{className:`personal-goal-state-dot ${e.loadState?``:$y[e.state]}`}),(0,z.jsxs)(`span`,{className:`personal-goal-link-copy`,children:[(0,z.jsx)(`strong`,{children:e.title}),(0,z.jsxs)(`small`,{children:[e.loadState&&(!t||l===e.goalId)?f(e.loadState===`error`?`startup.goalError`:`startup.goalLoading`):Yi(e.state,d),e.needsYou&&!t?` · ${f(`home.lane.needsYou`)}`:``]})]}),(0,z.jsx)(Jp,{size:15})]}),!t&&p?(0,z.jsxs)(`div`,{className:`personal-goal-move-actions`,children:[(0,z.jsx)(`button`,{type:`button`,"aria-label":f(`sidebar.moveUp`,{goal:e.title}),disabled:g[0]?.goalId===e.goalId,onClick:()=>h.moveBy(e.goalId,-1),children:(0,z.jsx)(Bp,{"aria-hidden":`true`,size:13})}),(0,z.jsx)(`button`,{type:`button`,"aria-label":f(`sidebar.moveDown`,{goal:e.title}),disabled:g.at(-1)?.goalId===e.goalId,onClick:()=>h.moveBy(e.goalId,1),children:(0,z.jsx)(Ip,{"aria-hidden":`true`,size:13})})]}):null,s?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`button`,{"aria-label":`${f(t?`sidebar.resume`:`sidebar.stop`)} ${e.title}`,"aria-busy":r?.has(e.goalId)||void 0,className:`personal-goal-lifecycle${r?.has(e.goalId)?` is-pending`:``}`,disabled:r?.has(e.goalId),onClick:()=>s(e,t?`resume`:`stop`),title:f(t?`sidebar.resumeGoal`:`sidebar.stopGoal`),type:`button`,children:r?.has(e.goalId)?(0,z.jsx)(hm,{size:13}):t?(0,z.jsx)(km,{size:13}):(0,z.jsx)(wm,{size:13})}),t?(0,z.jsx)(`button`,{"aria-label":`${f(`sidebar.delete`)} ${e.title}`,className:`personal-goal-lifecycle personal-goal-delete`,onClick:()=>s(e,`delete`),title:f(`sidebar.deleteGoal`),type:`button`,children:(0,z.jsx)(Hm,{size:13})}):null]}):null]},e.goalId);return(0,z.jsxs)(`div`,{className:`personal-goal-directory`,children:[(0,z.jsxs)(`div`,{className:`personal-sidebar-brand`,children:[(0,z.jsx)(`span`,{className:`personal-brand-mark`,children:(0,z.jsx)(Up,{size:18})}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:`LoopX`}),(0,z.jsx)(`small`,{children:f(`sidebar.product`)})]})]}),u?(0,z.jsx)(Qy,{...u}):null,(0,z.jsxs)(`nav`,{"aria-label":f(`home.workspace`),className:`personal-sidebar-nav`,children:[(0,z.jsxs)(`button`,{"aria-current":l===null?`page`:void 0,className:`personal-manager-link`,onClick:()=>c(null),type:`button`,children:[(0,z.jsx)(`span`,{className:`personal-manager-icon`,children:(0,z.jsx)(Up,{size:17})}),(0,z.jsx)(`span`,{children:f(`sidebar.manager`)}),e>0?(0,z.jsx)(`span`,{className:`personal-sidebar-count`,children:e}):null,(0,z.jsx)(Jp,{size:15})]}),(0,z.jsxs)(`div`,{className:`personal-sidebar-section-title`,children:[(0,z.jsx)(`span`,{children:`Goals`}),(0,z.jsxs)(`span`,{className:`personal-sidebar-title-actions`,children:[(0,z.jsx)(`small`,{children:g.length}),(0,z.jsx)(`button`,{"aria-label":f(`sidebar.sortGoals`),title:f(`sidebar.sortGoals`),"aria-pressed":p,onClick:()=>m(!p),type:`button`,children:(0,z.jsx)(zp,{"aria-hidden":`true`,size:15})}),i?(0,z.jsx)(`button`,{"aria-label":f(`sidebar.createGoal`),onClick:i,type:`button`,children:(0,z.jsx)(Em,{size:15})}):null]})]}),h.saveFailed?(0,z.jsx)(`p`,{role:`status`,children:f(`sidebar.orderNotSaved`)}):null,(0,z.jsx)(`span`,{className:`personal-sr-only`,role:`status`,children:h.lastMoved?f(`sidebar.goalMoved`,{goal:h.lastMoved.title,position:h.lastMoved.position}):``}),(0,z.jsx)(`div`,{className:`personal-goal-list`,children:g.map(e=>v(e,!1))}),_.length||n.phase===`loading`||n.phase===`error`?(0,z.jsxs)(`details`,{className:`personal-stopped-goals`,open:n.phase===`error`||void 0,children:[(0,z.jsxs)(`summary`,{children:[(0,z.jsx)(qp,{size:13}),(0,z.jsx)(`span`,{children:f(`sidebar.stopped`)}),n.phase===`loading`?(0,z.jsx)(hm,{"aria-label":f(`sidebar.stoppedLoading`),className:`is-spinning`,size:13}):(0,z.jsx)(`small`,{children:_.length})]}),(0,z.jsxs)(`div`,{className:`personal-goal-list is-stopped`,children:[n.phase===`error`?(0,z.jsxs)(`div`,{className:`personal-stopped-goal-error`,role:`alert`,children:[(0,z.jsx)(`span`,{children:f(`sidebar.stoppedLoadFailed`)}),o?(0,z.jsx)(`button`,{onClick:o,type:`button`,children:f(`sidebar.retryStopped`)}):null]}):null,_.map(e=>v(e,!0))]})]}):null]}),(0,z.jsxs)(`div`,{className:`personal-sidebar-footer`,children:[(0,z.jsx)(zy,{}),a?(0,z.jsxs)(`button`,{"aria-label":f(`settings.open`),className:`personal-sidebar-utility`,onClick:a,type:`button`,children:[(0,z.jsx)(`span`,{className:`personal-sidebar-utility-icon`,children:(0,z.jsx)(Fm,{size:17})}),(0,z.jsxs)(`span`,{className:`personal-sidebar-utility-copy`,children:[(0,z.jsx)(`strong`,{children:f(`settings.open`)}),(0,z.jsx)(`small`,{children:f(`settings.eyebrow`)})]}),(0,z.jsx)(Jp,{"aria-hidden":`true`,size:15})]}):null]})]})}var tb=J({ok:X(!0),total:G().int().nonnegative(),next_cursor:W().nullable(),items:q(J({todo_id:W(),text:W(),claimed_by:W().nullable(),evidence:W().nullable(),priority:W().nullable(),task_class:W().nullable()})).max(40)});function nb({goal:e,agentId:t,seed:n,enabled:r,listView:i=!1,onSelect:a}){let{t:o}=Ji(),s=(0,R.useId)(),[c,l]=(0,R.useState)(!1),u=!i||c,d=i?96:148,[f,p]=(0,R.useState)(n),[m,h]=(0,R.useState)(t===`all`?e.doneTodoCount??n.length:n.length),[g,_]=(0,R.useState)(void 0),[v,y]=(0,R.useState)(!1),[b,x]=(0,R.useState)(!1),[S,C]=(0,R.useState)(!1),[w,T]=(0,R.useState)({top:0,height:600}),[E,D]=(0,R.useState)(null),O=(0,R.useRef)(null),k=(0,R.useRef)(null),[ee,A]=(0,R.useState)(0);(0,R.useEffect)(()=>{let e=O.current;if(!e)return;let t=new ResizeObserver(()=>T({top:e.scrollTop,height:e.clientHeight}));return t.observe(e),()=>{t.disconnect(),k.current?.abort()}},[]);let j=g===void 0||w.top+w.height>=f.length*d-d*2;(0,R.useEffect)(()=>{if(!r||!u||!j||g===null||b||k.current)return;let n=new AbortController;k.current=n,y(!0);let i=new URLSearchParams({goal_id:e.goalId});t!==`all`&&i.set(`agent_id`,t),g&&i.set(`cursor`,g),fetch(`/api/chat/completed-todos?${i}`,{signal:n.signal}).then(async e=>{if(e.status===409&&C(!0),!e.ok)throw Error(`history unavailable`);let t=tb.parse(await e.json());if(n.signal.aborted)return;let r=t.items.map(e=>({todoId:e.todo_id,text:e.text,claimedBy:e.claimed_by,evidence:e.evidence,priority:e.priority,taskClass:e.task_class,done:!0,status:`done`}));p(e=>g===void 0?r:[...e,...r.filter(t=>!e.some(e=>e.todoId===t.todoId))]),h(t.total),_(t.next_cursor)}).catch(()=>{n.signal.aborted||x(!0)}).finally(()=>{n.signal.aborted||(k.current=null,y(!1))})},[r,u,j,g,b,ee,e.goalId,t,v]),(0,R.useEffect)(()=>{O.current&&(O.current.scrollTop=0),T({top:0,height:O.current?.clientHeight??600}),D(null)},[i]);let te=Math.max(0,Math.floor(w.top/d)-3),ne=Math.min(f.length,Math.ceil((w.top+w.height)/d)+3),re=Array.from({length:Math.max(0,ne-te)},(e,t)=>te+t);return E!==null&&El(e=>!e),children:[(0,z.jsx)(`span`,{"aria-hidden":`true`,children:c?`▾`:`▸`}),` `,o(`tasks.completed`)]}):(0,z.jsxs)(`strong`,{children:[(0,z.jsx)(`i`,{"aria-hidden":`true`,className:`personal-kanban-dot tone-done`}),o(`tasks.completed`)]}),(0,z.jsx)(`span`,{children:m})]}),(0,z.jsxs)(`div`,{id:s,hidden:!u,"aria-label":o(`tasks.completed`),className:`personal-task-lane-scroll`,ref:O,role:`region`,tabIndex:0,onScroll:e=>T({top:e.currentTarget.scrollTop,height:e.currentTarget.clientHeight}),children:[(0,z.jsx)(`div`,{className:`personal-completed-window`,style:{height:f.length*d},children:re.map(t=>{let n=f[t];return(0,z.jsx)(`div`,{className:`personal-task-card personal-completed-row`,style:{top:t*d,height:d},children:(0,z.jsxs)(`button`,{type:`button`,onFocus:()=>D(t),onBlur:()=>D(null),onClick:()=>a({kind:`todo`,item:{...n,goalId:e.goalId,goalTitle:e.title,ownerLabel:n.claimedBy??e.agentLabel??e.agentId}}),children:[(0,z.jsx)(`span`,{className:`is-done`,children:`✓`}),(0,z.jsx)(`strong`,{children:n.text}),(0,z.jsx)(`small`,{children:n.claimedBy??e.agentLabel??e.agentId})]})},n.todoId)})}),(0,z.jsx)(`div`,{className:`personal-completed-footer`,role:`status`,children:v?o(`tasks.historyLoading`):b?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`span`,{children:o(S?`tasks.historyExpired`:`tasks.historyError`)}),(0,z.jsx)(`button`,{type:`button`,onClick:()=>{S&&(_(void 0),O.current&&(O.current.scrollTop=0)),C(!1),x(!1),A(e=>e+1)},children:o(`tasks.historyRetry`)})]}):r?g===null?o(`tasks.historyEnd`):(0,z.jsx)(`button`,{type:`button`,onClick:()=>{O.current&&(O.current.scrollTop=f.length*d)},children:o(`tasks.historyMore`)}):o(`tasks.historyLocalOnly`)})]})]})}function rb({children:e,count:t,label:n,tone:r,listView:i=!1}){let a=(0,R.useId)(),o=(0,R.useRef)(null),s=(0,R.useRef)([]),c=(0,R.useRef)(null),[l,u]=(0,R.useState)({after:!1,before:!1}),d=(0,R.useCallback)(()=>{let e=o.current;if(!e)return;let t={after:Math.max(0,e.scrollHeight-e.clientHeight)-e.scrollTop>1,before:e.scrollTop>1};u(e=>e.after===t.after&&e.before===t.before?e:t)},[]);return(0,R.useEffect)(()=>{let e=o.current;if(!e)return;let t=new ResizeObserver(d);return c.current=t,t.observe(e),e.addEventListener(`scroll`,d,{passive:!0}),d(),()=>{t.disconnect(),c.current=null,s.current=[],e.removeEventListener(`scroll`,d)}},[i,d]),(0,R.useEffect)(()=>{let e=o.current,t=c.current;if(!e||!t)return;for(let e of s.current)t.unobserve(e);let n=Array.from(e.children).filter(e=>e instanceof HTMLElement);for(let e of n)t.observe(e);s.current=n,d()},[e,t,i,d]),i?!t&&r!==`done`?null:(0,z.jsxs)(`details`,{className:`personal-task-group tone-${r}`,open:!0,children:[(0,z.jsxs)(`summary`,{children:[(0,z.jsx)(qp,{size:16}),(0,z.jsx)(`strong`,{children:n}),(0,z.jsx)(`span`,{children:t})]}),(0,z.jsx)(`div`,{className:`personal-task-list-rows`,children:e})]}):(0,z.jsxs)(`section`,{className:`personal-object-list personal-task-lane`,children:[(0,z.jsxs)(`header`,{id:a,children:[(0,z.jsxs)(`strong`,{children:[(0,z.jsx)(`i`,{"aria-hidden":`true`,className:`personal-kanban-dot tone-${r}`}),n]}),(0,z.jsx)(`span`,{children:t})]}),(0,z.jsx)(`div`,{"aria-labelledby":a,className:`personal-task-lane-scroll${l.before?` has-overflow-before`:``}${l.after?` has-overflow-after`:``}`,ref:o,role:`region`,tabIndex:t>0?0:-1,children:e})]})}function ib({historyEnabled:e=!1,goal:t,items:n,onDraftTaskFromMessage:r,onOpenChat:i,onQuickComplete:a,quickCompletingTodoIds:o,onSelect:s,selectedTodoId:c=null,userTodos:l}){let{t:u}=Ji(),[d,f]=(0,R.useState)(!1),[p,m]=(0,R.useState)({goalId:``,laneId:`all`}),h=(0,R.useRef)(null);(0,R.useEffect)(()=>{if(!c)return;let e=window.requestAnimationFrame(()=>h.current?.scrollIntoView({block:`nearest`,inline:`nearest`}));return()=>window.cancelAnimationFrame(e)},[c]);let g=l.filter(e=>e.goalId===t.goalId).map(e=>({...e,goalTitle:t.title})),_=e=>e.priority===`P0`?0:e.priority===`P1`?1:e.priority===`P2`?2:3,v=(0,R.useMemo)(()=>{let e=new Map((t.agentLanes??[]).map(e=>[e.agentId,e]));for(let n of t.agentTodos)n.claimedBy&&!e.has(n.claimedBy)&&e.set(n.claimedBy,{agentId:n.claimedBy,label:n.claimedBy});return[...e.values()]},[t.agentLanes,t.agentTodos]),y=p.goalId===t.goalId&&v.some(e=>e.agentId===p.laneId)?p.laneId:`all`,b=e=>y===`all`||e===y,x=t.agentTodos.filter(e=>e.taskClass!==`continuous_monitor`&&!e.done).filter(e=>b(e.claimedBy)).sort((e,t)=>_(e)-_(t)),S=t.agentTodos.filter(e=>e.taskClass!==`continuous_monitor`&&e.done).filter(e=>b(e.claimedBy)),C=n.filter(e=>e.kind===`schedule`&&b(e.schedule.agentId)),w=n.filter(e=>e.kind===`run`&&!!e.run.todoId&&b(e.run.agentId)),T=!g.length&&!x.length&&!S.length&&!C.length,E=n.filter(e=>e.kind===`message`&&(e.message.role===`user`||e.message.role===`assistant`)),D=E.reduce((e,t,n)=>t.message.role===`user`?n:e,-1),O=D>=0?E[D]?.message:null,k=D>=0?E.slice(D+1).reverse().find(e=>e.message.role===`assistant`)?.message:null,ee=D>=0&&E.slice(D+1).some(e=>e.message.role===`assistant`&&e.message.pending);return(0,z.jsxs)(`section`,{"aria-label":u(`header.tasks`),className:`personal-task-board${d?` is-list-view`:``}`,children:[(0,z.jsxs)(`header`,{className:`personal-task-view-toolbar`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:u(`header.tasks`)}),(0,z.jsx)(`span`,{children:u(`tasks.viewDescription`)})]}),(0,z.jsxs)(`div`,{className:`personal-task-view-switch`,role:`group`,"aria-label":u(`tasks.viewLabel`),children:[(0,z.jsx)(`button`,{type:`button`,"aria-pressed":d,onClick:()=>f(!0),children:u(`tasks.listView`)}),(0,z.jsx)(`button`,{type:`button`,"aria-pressed":!d,onClick:()=>f(!1),children:u(`tasks.boardView`)})]})]}),v.length>1?(0,z.jsxs)(`section`,{"aria-label":u(`tasks.agentLaneFilter`),className:`personal-task-lane-filter`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(Up,{size:15}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:u(`tasks.agentLane`)}),(0,z.jsx)(`small`,{children:u(`tasks.agentLaneDescription`)})]})]}),(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{className:`sr-only`,children:u(`tasks.agentLaneFilter`)}),(0,z.jsxs)(`select`,{"aria-label":u(`tasks.agentLaneFilter`),onChange:e=>m({goalId:t.goalId,laneId:e.target.value}),value:y,children:[(0,z.jsx)(`option`,{value:`all`,children:u(`tasks.allAgentLanes`,{count:v.length})}),v.map(e=>(0,z.jsx)(`option`,{value:e.agentId,children:e.label},e.agentId))]}),(0,z.jsx)(qp,{"aria-hidden":!0,size:14})]})]}):null,O?(0,z.jsxs)(`section`,{"aria-label":u(`tasks.chatRecent`),className:`personal-task-chat-receipt`,children:[(0,z.jsx)(`span`,{className:`personal-task-chat-icon`,children:(0,z.jsx)(ym,{size:18})}),(0,z.jsxs)(`div`,{children:[(0,z.jsxs)(`header`,{children:[(0,z.jsx)(`strong`,{children:u(ee?`tasks.chatPending`:k?`tasks.chatAgentReplied`:`tasks.chatRecent`)}),(0,z.jsx)(`small`,{children:t.agentLabel??t.agentId})]}),(0,z.jsxs)(`p`,{className:`is-user`,children:[(0,z.jsx)(`b`,{children:u(`common.you`)}),O.text]}),k&&!k.pending?(0,z.jsxs)(`p`,{className:`is-assistant`,children:[(0,z.jsx)(`b`,{children:u(`common.agent`)}),k.text]}):null,(0,z.jsx)(`small`,{children:u(ee?`tasks.chatPendingDescription`:`tasks.chatUnchangedDescription`)})]}),(0,z.jsxs)(`footer`,{children:[(0,z.jsxs)(`button`,{onClick:i,type:`button`,children:[(0,z.jsx)(ym,{size:14}),u(`tasks.chatViewReply`)]}),k&&!ee&&r?(0,z.jsxs)(`button`,{onClick:()=>r(k.text),type:`button`,children:[(0,z.jsx)(mm,{size:14}),u(`tasks.convertToTask`)]}):null]})]}):null,(0,z.jsxs)(`div`,{className:d?`personal-task-grouped-list`:`personal-task-kanban`,children:[(0,z.jsxs)(rb,{listView:d,count:g.length,label:u(`timeline.waitingConfirmation`),tone:`attention`,children:[g.map(e=>{let t=Zi(e.updatedAt,u);return(0,z.jsxs)(`button`,{onClick:()=>s({item:e,kind:`attention`}),type:`button`,children:[(0,z.jsx)(`span`,{"aria-hidden":`true`,className:`is-attention`,children:`!`}),(0,z.jsx)(`strong`,{children:e.text}),(0,z.jsxs)(`small`,{children:[(0,z.jsx)(`span`,{className:`personal-row-status ${e.blocking?`is-blocking`:`is-pending`}`,children:e.blocking?u(`tasks.blocked`):u(`tasks.pending`)}),t?(0,z.jsx)(`span`,{className:`personal-task-age`,children:u(`tasks.waitingAge`,{age:t})}):null]})]},e.todoId)}),g.length?null:(0,z.jsx)(`p`,{className:`personal-task-empty`,children:u(`tasks.emptyConfirm`)})]}),(0,z.jsxs)(rb,{listView:d,count:x.length,label:u(`tasks.pendingAndRunning`),tone:`progress`,children:[x.map(e=>{let n={...e,goalId:t.goalId,goalTitle:t.title,ownerLabel:e.claimedBy??t.agentLabel??t.agentId},r=w.find(t=>t.run.todoId===e.todoId)?.run;return(0,z.jsxs)(`div`,{className:`personal-task-card${r?` has-session`:``}${c===e.todoId?` is-selected`:``}`,ref:c===e.todoId?e=>{h.current=e}:void 0,children:[(0,z.jsxs)(`button`,{"aria-pressed":c===e.todoId,onClick:()=>s({item:n,kind:`todo`}),type:`button`,children:[(0,z.jsx)(`span`,{children:`○`}),(0,z.jsx)(`strong`,{children:e.text}),(0,z.jsxs)(`small`,{children:[e.priority?(0,z.jsx)(`span`,{className:`personal-priority-badge is-${e.priority.toLowerCase()}`,children:e.priority}):null,e.status===`blocked`?(0,z.jsx)(`span`,{className:`personal-priority-badge is-blocked`,children:u(`tasks.blocked`)}):null,r?(0,z.jsx)(`span`,{className:`personal-task-session-status`,children:r.status===`running`||r.status===`queued`?u(`runs.running`):r.status===`failed`?u(`tasks.sessionError`):u(`common.waiting`)}):null,e.status===`deferred`?(0,z.jsx)(`span`,{className:`personal-task-session-status`,children:u(`drawer.taskStatusDeferred`)}):r?null:(0,z.jsx)(`span`,{className:`personal-task-session-status`,children:u(`tasks.waiting`)}),e.claimedBy??t.agentLabel??t.agentId]})]}),(0,z.jsxs)(`div`,{className:`personal-task-card-actions`,children:[r?(0,z.jsxs)(`button`,{className:`personal-task-session-link`,"aria-label":u(`tasks.openExecution`,{name:e.text}),onClick:()=>s({item:r,kind:`run`}),title:r.status===`completed`?u(`tasks.viewResult`):u(`tasks.viewExecution`),type:`button`,children:[(0,z.jsx)(im,{size:14}),(0,z.jsx)(`span`,{children:r.status===`completed`?u(`tasks.viewResult`):u(`tasks.viewExecution`)})]}):null,a?(0,z.jsx)(`button`,{"aria-busy":o?.has(e.todoId)||void 0,"aria-label":u(`tasks.markComplete`,{name:e.text}),disabled:o?.has(e.todoId),onClick:()=>void a(n),title:u(`tasks.completed`),type:`button`,children:o?.has(e.todoId)?(0,z.jsx)(hm,{className:`personal-spin`,size:14}):(0,z.jsx)(Kp,{size:14})}):null,(0,z.jsx)(`button`,{"aria-label":u(`tasks.moreActions`,{name:e.text}),onClick:()=>s({item:n,kind:`todo`}),title:u(`common.actions`),type:`button`,children:(0,z.jsx)(rm,{size:14})})]})]},e.todoId)}),x.length?null:(0,z.jsx)(`p`,{className:`personal-task-empty`,children:u(`tasks.emptyRunning`)})]}),(0,z.jsxs)(rb,{listView:d,count:C.length,label:u(`tasks.scheduled`),tone:`schedule`,children:[C.map(e=>(0,z.jsxs)(`button`,{onClick:()=>s({item:e.schedule,kind:`schedule`}),type:`button`,children:[(0,z.jsx)(`span`,{children:`◷`}),(0,z.jsx)(`strong`,{children:e.schedule.label}),(0,z.jsx)(`small`,{children:e.schedule.status===`paused`?u(`schedule.paused`):u(`schedule.active`)})]},e.id)),C.length?null:(0,z.jsx)(`p`,{className:`personal-task-empty`,children:u(`tasks.emptySchedules`)})]}),(0,z.jsx)(nb,{goal:t,agentId:y,seed:S,enabled:e,listView:d,onSelect:s},`${t.goalId}:${y}:${e}`)]}),T?(0,z.jsx)(`p`,{className:`personal-task-empty`,children:u(`tasks.emptyGoal`)}):null]})}function ab(e,t){return{live_steering:{label:t(`lark.ingressSteering`),detail:t(`lark.ingressSteeringDescription`)},session_queue:{label:t(`lark.ingressQueue`),detail:t(`lark.ingressQueueDescription`)},async_inbox:{label:t(`lark.ingressAsync`),detail:t(`lark.ingressAsyncDescription`)},direct_session:{label:t(`lark.ingressLegacy`),detail:t(`lark.ingressLegacyDescription`)}}[e]}function ob(e,t){return e.listener_status===`starting`?{label:t(`lark.health.starting`),detail:t(`lark.health.startingDetail`),ready:!1}:e.listener_status===`retrying`?{label:t(`lark.health.retrying`),detail:t(`lark.health.retryingDetail`),ready:!1}:e.listener_status===`stopped`||e.listener_status===null?{label:t(`lark.health.notStarted`),detail:t(`lark.health.notStartedDetail`),ready:!1}:e.last_event_status===`message_context_permission_required`?{label:t(`lark.health.messageContextPermission`),detail:t(`lark.health.messageContextPermissionDetail`),ready:!1}:e.last_event_status===`processing_failed`?{label:t(`lark.health.processingFailed`),detail:t(`lark.health.processingFailedDetail`),ready:!1}:e.health_error_code===`invalid_routing_state`?{label:t(`lark.health.invalidRouting`),detail:t(`lark.health.invalidRoutingDetail`),ready:!1}:e.last_event_status===`queued_for_agent`?{label:t(`lark.health.queued`),detail:t(`lark.health.queuedDetail`,{agent:e.agent_id??t(`lark.targetAgent`)}),ready:!0}:e.last_event_status===`ignored`&&e.last_event_reason===`not_addressed`?{label:t(`lark.health.notAddressed`),detail:t(`lark.health.notAddressedDetail`),ready:!0}:e.last_event_status===`ignored`&&e.last_event_reason===`self_message`?{label:t(`lark.health.listening`),detail:t(`lark.health.ignoredSelf`),ready:!0}:e.health_error_code===`lark_event_route_mismatch`||[`chat_mismatch`,`topic_mismatch`,`route_ambiguous`].includes(e.last_event_reason??``)?{label:e.last_event_reason===`route_ambiguous`?t(`lark.health.routeAmbiguous`):t(`lark.health.routeMismatch`),detail:e.last_event_reason===`route_ambiguous`?t(`lark.health.routeAmbiguousDetail`):t(`lark.health.routeMismatchDetail`),ready:!1}:[`invalid_event`,`binding_unavailable`].includes(e.last_event_reason??``)?{label:t(`lark.health.routeUnavailable`),detail:t(`lark.health.routeUnavailableDetail`),ready:!1}:e.last_event_status===`replied_and_acknowledged`?{label:t(`lark.health.listening`),detail:t(`lark.health.eventProcessed`,{events:e.event_count,replies:e.replied_count}),ready:!0}:e.health_error_code===`lark_event_delivery_unverified`||e.event_count===0?{label:t(`lark.health.eventUnverified`),detail:t(`lark.health.eventUnverifiedDetail`),ready:!1}:{label:e.reply_ready?t(`lark.health.listening`):t(`lark.health.unavailable`),detail:t(`lark.health.lastStatus`,{status:e.last_event_status??t(`lark.health.waiting`)}),ready:e.reply_ready}}function sb(e){return e.history_permission_guidance?.api_document_url??null}function cb(e,t,n){if(e instanceof _h){let t=String(e.payload.error_code??``);return{lark_cli_not_installed:n(`lark.error.cliMissing`),lark_cli_not_executable:n(`lark.error.cliExecutable`),lark_cli_start_failed:n(`lark.error.cliStart`),lark_message_permissions_required:n(`lark.error.messagePermissions`),lark_app_required:n(`lark.error.appRequired`),invalid_lark_app:n(`lark.error.invalidApp`),lark_group_lookup_failed:n(`lark.error.groupLookup`),provider_api_failed:n(`lark.error.provider`)}[t]??e.message}return e instanceof Error?e.message:t}function lb({embedded:e=!1,focusGoalConnection:t=!1,goals:n,initialGoalId:r,onChanged:i,onClose:a}){let{t:o}=Ji(),[s,c]=(0,R.useState)(`connections`),[l,u]=(0,R.useState)([]),[d,f]=(0,R.useState)([]),[p,m]=(0,R.useState)(!0),[h,g]=(0,R.useState)(null),[_,v]=(0,R.useState)(``),[y,b]=(0,R.useState)(t),[x,S]=(0,R.useState)(``),[C,w]=(0,R.useState)(r??n[0]?.goalId??``),[T,E]=(0,R.useState)(``),[D,O]=(0,R.useState)([]),[k,ee]=(0,R.useState)(``),[A,j]=(0,R.useState)(!1),[te,ne]=(0,R.useState)(null),[re,M]=(0,R.useState)(`addressed_only`),[N,ie]=(0,R.useState)(`async_inbox`),[ae,oe]=(0,R.useState)(`topic_reply`),[P,F]=(0,R.useState)(``),[I,se]=(0,R.useState)(!1),[ce,le]=(0,R.useState)({}),[ue,de]=(0,R.useState)(!1),[fe,pe]=(0,R.useState)(null),[me,he]=(0,R.useState)(null),[ge,_e]=(0,R.useState)(null),[ve,ye]=(0,R.useState)(!1),[be,xe]=(0,R.useState)(`loopx-workspace-bot`),[Se,Ce]=(0,R.useState)(`feishu`),[we,Te]=(0,R.useState)(null),[Ee,De]=(0,R.useState)(!1),[L,Oe]=(0,R.useState)(null),ke=(0,R.useRef)(null),Ae=(0,R.useRef)(null),je=(0,R.useRef)(!1);async function Me(){m(!0),g(null);try{let[e,t]=await Promise.all([Og(),Lg()]);u(e),f(t),S(t=>t||e.find(e=>e.reply_ready)?.app_ref||e.find(e=>e.ready)?.app_ref||e[0]?.app_ref||``)}catch(e){g(cb(e,o(`lark.error.configuration`),o))}finally{m(!1)}}(0,R.useEffect)(()=>{Me()},[]),(0,R.useEffect)(()=>{if(!t||p||je.current||!r)return;je.current=!0;let e=d.find(e=>e.goal_id===r);e?Ue(e):He(n.find(e=>e.goalId===r))},[d,t,n,r,p]),(0,R.useEffect)(()=>{if(!y||!x){O([]),ee(``),j(!1),ne(null);return}let e=!1;j(!0),ne(null);let t=window.setTimeout(()=>{Fg(x,T).then(t=>{e||(O(t),ee(e=>t.some(t=>t.chat_id===e)?e:t[0]?.chat_id??``))}).catch(t=>{e||(O([]),ee(``),ne(cb(t,o(`lark.error.groupLoad`),o)))}).finally(()=>{e||j(!1)})},180);return()=>{e=!0,window.clearTimeout(t)}},[x,T,y]),(0,R.useEffect)(()=>{if(!ve||!we||[`ready`,`failed`,`cancelled`].includes(we.status))return;let e=!1,t=window.setTimeout(()=>{jg(we.setup_id).then(async t=>{e||(Te(t),t.verification_url&&Ae.current!==t.verification_url&&(Ae.current=t.verification_url,ke.current&&!ke.current.closed&&(ke.current.location.href=t.verification_url)),t.status===`ready`&&(await Me(),S(t.app_ref),le({}),ye(!1)),t.status===`failed`&&Oe(t.error??o(`lark.error.appCreate`)))}).catch(t=>{e||Oe(cb(t,o(`lark.error.setupPoll`),o))})},650);return()=>{e=!0,window.clearTimeout(t)}},[ve,we]);let Ne=n.find(e=>e.goalId===C),Pe=Ne?.agentId?[{agentId:Ne.agentId,label:Ne.agentLabel??Ne.agentId}]:[],Fe=Ne?.agentLanes?.length?Ne.agentLanes:Pe,Ie=Fe.some(e=>e.agentId===P),B=[];I?B=Fe.map(e=>({agentId:e.agentId,appRef:ce[e.agentId]??x})):Ie&&(B=[{agentId:P,appRef:x}]);let Le=B.map(e=>e.agentId),Re=B.length>0&&B.every(e=>l.some(t=>t.app_ref===e.appRef&&t.reply_ready)),V=o(`lark.connect`);me?V=o(`lark.saveConnection`):I&&(V=o(`lark.connectAllAgentsAction`,{count:Le.length}));let ze=l.find(e=>e.app_ref===x),Be=D.find(e=>e.chat_id===k),Ve=(0,R.useMemo)(()=>{let e=_.trim().toLocaleLowerCase();return e?d.filter(t=>[t.app_label,t.chat_name,t.goal_title,t.topic_name].some(t=>t.toLocaleLowerCase().includes(e))):d},[d,_]);function He(e){let t=e??n.find(e=>e.goalId===r)??n[0];he(null),w(t?.goalId??``),F(t?.agentId??``),se(!1),le({}),M(`addressed_only`),ie(`async_inbox`),oe(`topic_reply`),E(``),pe(null),b(!0)}function Ue(e){he(e.goal_id),S(e.app_ref),w(e.goal_id),F(e.agent_id??n.find(t=>t.goalId===e.goal_id)?.agentId??``),se(!1),le({}),M(e.capture_scope),ie(e.ingress_mode===`direct_session`?`session_queue`:e.ingress_mode),oe(e.reply_mode),E(e.chat_name),pe(null),b(!0)}function We(){Te(null),Oe(null),Ae.current=null,ye(!0)}async function Ge(){if(!(Ee||!/^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$/.test(be))){De(!0),Oe(null),Ae.current=null,ke.current=window.open(window.location.href,`_blank`);try{let e=await Ag({appRef:be,brand:Se});Te(e)}catch(e){ke.current?.close(),Oe(cb(e,o(`lark.error.setupStart`),o))}finally{De(!1)}}}async function Ke(){let e=we;if(ye(!1),ke.current?.close(),e&&![`ready`,`failed`,`cancelled`].includes(e.status))try{await Mg(e.setup_id)}catch{}}async function qe(){if(!(!x||!C||!Be||Le.length===0||ue)){de(!0),pe(null);try{let e={agentBindings:B,captureScope:re,chatId:Be.chat_id,chatName:Be.chat_name,goalId:C,incomingMode:re===`configured_chat_all`?`all`:`mentions`,ingressMode:N,replyMode:ae},t=await Rg({...e,execute:!1});if(!t.ok)throw new _h(t.public_summary??t.blocker??o(`lark.error.bindPreview`),{error_code:t.blocker??`provider_api_failed`});let n=await Rg({...e,execute:!0});if(!n.ok)throw new _h(n.public_summary??n.blocker??o(`lark.error.bind`),{error_code:n.blocker??`provider_api_failed`});b(!1),await Me(),i?.()}catch(e){pe(cb(e,o(`lark.error.bind`),o))}finally{de(!1)}}}async function Je(e,t){if(ge!==t){_e(t);return}try{await zg(e,t),_e(null),await Me(),i?.()}catch(e){g(cb(e,o(`lark.error.disconnect`),o))}}return(0,z.jsxs)(`section`,{className:`personal-lark-settings${e?` is-embedded`:``}`,"aria-label":o(`lark.configuration`),children:[e?null:(0,z.jsxs)(`header`,{className:`personal-lark-header`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`small`,{children:o(`settings.goalConnections`)}),(0,z.jsx)(`h1`,{children:`Lark`}),(0,z.jsx)(`p`,{children:o(`lark.description`)})]}),(0,z.jsx)(`button`,{"aria-label":o(`lark.closeSettings`),className:`personal-icon-button`,onClick:a,type:`button`,children:(0,z.jsx)(Gm,{size:18})})]}),(0,z.jsxs)(`nav`,{className:`personal-lark-tabs`,"aria-label":o(`lark.management`),children:[(0,z.jsxs)(`button`,{"aria-current":s===`apps`?`page`:void 0,onClick:()=>c(`apps`),type:`button`,children:[o(`lark.apps`),` `,(0,z.jsx)(`span`,{children:p?`…`:l.length})]}),(0,z.jsxs)(`button`,{"aria-current":s===`connections`?`page`:void 0,onClick:()=>c(`connections`),type:`button`,children:[o(`lark.connections`),` `,(0,z.jsx)(`span`,{children:p?`…`:d.length})]})]}),h?(0,z.jsx)(`p`,{className:`personal-notification-error`,children:h}):null,p?(0,z.jsxs)(`div`,{className:`personal-lark-loading`,children:[(0,z.jsx)(hm,{className:`is-spinning`,size:18}),o(`lark.loading`)]}):null,!p&&s===`apps`?(0,z.jsxs)(`div`,{className:`personal-lark-apps`,children:[(0,z.jsxs)(`div`,{className:`personal-lark-app-toolbar`,children:[(0,z.jsx)(`span`,{children:o(`lark.reusableApps`,{count:l.length})}),(0,z.jsxs)(`button`,{className:`personal-primary-action`,onClick:We,type:`button`,children:[(0,z.jsx)(Em,{size:16}),o(`lark.newApp`)]})]}),(0,z.jsxs)(`div`,{className:`personal-lark-app-grid`,children:[l.map(e=>(0,z.jsxs)(`article`,{className:`personal-lark-app-card`,children:[(0,z.jsx)(`span`,{className:`personal-lark-app-avatar`,children:(0,z.jsx)(Up,{size:19})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:e.label}),(0,z.jsxs)(`small`,{children:[e.brand,` · lark-cli profile`]})]}),(0,z.jsx)(`em`,{className:e.reply_ready?`is-ready`:`is-off`,children:e.reply_ready?o(`lark.autoReplyReady`):e.ready?o(`lark.needsMessagePermissions`):o(`lark.needsSetup`)}),(0,z.jsxs)(`p`,{children:[o(`lark.goalConnections`,{count:d.filter(t=>t.app_ref===e.app_ref).length}),e.ready&&!e.reply_ready?` · ${o(`lark.autoReplyUnavailable`)}`:``]})]},e.app_ref)),l.length===0?(0,z.jsx)(`p`,{className:`personal-lark-empty`,children:o(`lark.noProfiles`)}):null]})]}):null,!p&&s===`connections`?(0,z.jsxs)(`div`,{className:`personal-lark-connections`,children:[(0,z.jsxs)(`div`,{className:`personal-lark-toolbar`,children:[(0,z.jsxs)(`label`,{children:[(0,z.jsx)(jm,{size:16}),(0,z.jsx)(`input`,{"aria-label":o(`lark.searchConnections`),onChange:e=>v(e.target.value),placeholder:o(`lark.searchPlaceholder`),type:`search`,value:_})]}),(0,z.jsxs)(`button`,{className:`personal-primary-action`,disabled:l.length===0||n.length===0,onClick:()=>He(),type:`button`,children:[(0,z.jsx)(Em,{size:16}),o(`lark.connectApp`)]})]}),(0,z.jsxs)(`div`,{className:`personal-lark-table`,role:`table`,"aria-label":o(`lark.goalTopicConnections`),children:[(0,z.jsxs)(`div`,{className:`personal-lark-table-head`,role:`row`,children:[(0,z.jsx)(`span`,{children:o(`lark.connection`)}),(0,z.jsx)(`span`,{children:o(`common.goal`)}),(0,z.jsx)(`span`,{children:o(`lark.capture`)}),(0,z.jsx)(`span`,{children:o(`lark.processing`)}),(0,z.jsx)(`span`,{children:o(`common.actions`)})]}),Ve.map(e=>(0,z.jsxs)(`div`,{className:`personal-lark-table-row`,role:`row`,children:[(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:e.chat_name}),(0,z.jsxs)(`small`,{children:[e.app_label,` · `,ob(e,o).label]}),(0,z.jsx)(`small`,{children:ob(e,o).detail}),e.health_error_code===`lark_event_delivery_unverified`?(0,z.jsxs)(`a`,{href:`https://open.feishu.cn/document/server-docs/im-v1/message/events/receive?lang=zh-CN`,rel:`noreferrer`,target:`_blank`,children:[(0,z.jsx)(im,{size:12}),o(`lark.openEventSettings`)]}):null,sb(e)?(0,z.jsxs)(`a`,{href:sb(e)??void 0,rel:`noreferrer`,target:`_blank`,children:[(0,z.jsx)(im,{size:12}),o(`lark.historyPermission`)]}):null]}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:e.goal_title}),(0,z.jsxs)(`small`,{children:[`# `,e.topic_name]})]}),(0,z.jsx)(`span`,{children:e.capture_scope===`addressed_only`?o(`lark.mentionsOnly`):o(`lark.allTopicMessages`)}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:ab(e.ingress_mode,o).label}),(0,z.jsx)(`small`,{children:e.agent_id??ab(e.ingress_mode,o).detail})]}),(0,z.jsxs)(`span`,{className:`personal-lark-row-actions`,children:[(0,z.jsx)(`button`,{"aria-label":o(`lark.settingsConfigure`,{goal:e.goal_title}),onClick:()=>Ue(e),type:`button`,children:(0,z.jsx)(Fm,{size:15})}),(0,z.jsxs)(`button`,{"aria-label":o(`lark.settingsDisconnect`,{goal:e.goal_title}),className:ge===e.connection_id?`is-confirm`:``,onClick:()=>void Je(e.goal_id,e.connection_id),type:`button`,children:[(0,z.jsx)(Wm,{size:15}),ge===e.connection_id?o(`common.confirm`):null]})]})]},e.connection_id)),Ve.length===0?(0,z.jsx)(`p`,{className:`personal-lark-empty`,children:o(`lark.noConnections`)}):null]})]}):null,y?(0,z.jsx)(`div`,{className:`personal-lark-modal-backdrop`,role:`presentation`,children:(0,z.jsxs)(`section`,{"aria-labelledby":`connect-lark-title`,"aria-modal":`true`,className:`personal-lark-modal`,role:`dialog`,children:[(0,z.jsxs)(`header`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`small`,{children:`Goal Topic connection`}),(0,z.jsx)(`h2`,{id:`connect-lark-title`,children:o(me?`lark.editConnection`:`lark.connectApp`)})]}),(0,z.jsx)(`button`,{"aria-label":o(`lark.closeConnection`),onClick:()=>b(!1),type:`button`,children:(0,z.jsx)(Gm,{size:18})})]}),(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:o(`lark.appProfile`)}),(0,z.jsx)(`select`,{"aria-label":o(`lark.appProfile`),disabled:p,onChange:e=>{e.target.value===`__register__`?We():(S(e.target.value),le({}))},value:x,children:p?(0,z.jsx)(`option`,{value:``,children:o(`lark.appLoading`)}):(0,z.jsxs)(z.Fragment,{children:[l.map(e=>(0,z.jsxs)(`option`,{disabled:!e.ready,value:e.app_ref,children:[e.label,e.reply_ready?``:e.ready?` · ${o(`lark.needsMessagePermissions`)}`:` · ${o(`lark.needsSetup`)}`]},e.app_ref)),(0,z.jsx)(`option`,{value:`__register__`,children:o(`lark.registerAnother`)})]})}),(0,z.jsx)(`small`,{children:o(`lark.defaultAgentAppDescription`)})]}),ze?.ready&&!ze.reply_ready?(0,z.jsx)(`div`,{className:`personal-lark-group-state is-error`,role:`alert`,children:o(`lark.appPermissions`)}):null,(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:o(`lark.groupChat`)}),(0,z.jsx)(`input`,{"aria-label":o(`lark.groupSearch`),onChange:e=>E(e.target.value),placeholder:o(`lark.groupSearch`),type:`search`,value:T}),A?(0,z.jsxs)(`div`,{className:`personal-lark-group-state`,role:`status`,children:[(0,z.jsx)(hm,{className:`is-spinning`,size:15}),o(`lark.groupLoading`)]}):null,!A&&te?(0,z.jsx)(`div`,{className:`personal-lark-group-state is-error`,role:`alert`,children:te}):null,!A&&!te&&D.length===0?(0,z.jsx)(`div`,{className:`personal-lark-group-state`,role:`status`,children:o(`lark.groupEmpty`)}):null,!A&&!te&&D.length>0?(0,z.jsx)(`select`,{"aria-label":o(`lark.groupChat`),onChange:e=>ee(e.target.value),value:k,children:D.map(e=>(0,z.jsx)(`option`,{value:e.chat_id,children:e.chat_name},e.chat_id))}):null]}),(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:o(`lark.bindGoal`)}),(0,z.jsx)(`select`,{"aria-label":o(`lark.bindGoal`),onChange:e=>{let t=e.target.value;w(t),F(n.find(e=>e.goalId===t)?.agentId??``),le({})},value:C,children:n.map(e=>(0,z.jsx)(`option`,{value:e.goalId,children:e.title},e.goalId))})]}),(0,z.jsxs)(`label`,{className:`personal-lark-check`,children:[(0,z.jsx)(`input`,{checked:!0,readOnly:!0,type:`checkbox`}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:o(`lark.createAutomatically`)}),(0,z.jsx)(`small`,{children:o(`lark.createAutomaticallyDescription`)})]})]}),(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:o(`lark.topicPreview`)}),(0,z.jsxs)(`div`,{className:`personal-lark-topic-preview`,children:[(0,z.jsx)(ym,{size:15}),`# `,Ne?.title??Ne?.goalId??`Goal`]})]}),(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:o(`lark.captureScope`)}),(0,z.jsxs)(`select`,{"aria-label":o(`lark.captureScope`),onChange:e=>M(e.target.value),value:re,children:[(0,z.jsx)(`option`,{value:`addressed_only`,children:o(`lark.captureAddressed`)}),(0,z.jsx)(`option`,{value:`configured_chat_all`,children:o(`lark.captureAll`)})]}),(0,z.jsx)(`small`,{children:o(`lark.captureScopeDescription`)})]}),(0,z.jsxs)(`fieldset`,{"aria-label":o(`lark.agentIngress`),className:`personal-lark-ingress`,children:[(0,z.jsx)(`legend`,{children:o(`lark.agentIngress`)}),(0,z.jsx)(`div`,{children:[`live_steering`,`session_queue`,`async_inbox`].map(e=>{let t=ab(e,o);return(0,z.jsxs)(`label`,{className:N===e?`is-active`:``,children:[(0,z.jsx)(`input`,{"aria-label":t.label,checked:N===e,name:`lark-agent-ingress`,onChange:()=>ie(e),type:`radio`,value:e}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:t.label}),(0,z.jsx)(`small`,{children:t.detail})]})]},e)})})]}),(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:o(`lark.targetAgent`)}),(0,z.jsxs)(`select`,{"aria-label":o(`lark.targetAgent`),onChange:e=>F(e.target.value),value:P,children:[Ie?null:(0,z.jsx)(`option`,{disabled:!0,value:P,children:P?o(`lark.agentUnavailable`,{agent:P}):o(`lark.noAgentConfigured`)}),Fe.map(e=>(0,z.jsx)(`option`,{value:e.agentId,children:e.label===e.agentId?e.agentId:`${e.label} · ${e.agentId}`},e.agentId))]}),(0,z.jsx)(`small`,{children:o(`lark.targetAgentDescription`)})]}),!me&&Fe.length>1?(0,z.jsxs)(`label`,{"aria-label":o(`lark.connectAllAgents`),className:`personal-lark-check`,children:[(0,z.jsx)(`input`,{checked:I,onChange:e=>se(e.target.checked),type:`checkbox`}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:o(`lark.connectAllAgents`)}),(0,z.jsx)(`small`,{children:o(`lark.connectAllAgentsDescription`,{count:Fe.length})})]})]}):null,!me&&I&&Fe.length>1?(0,z.jsxs)(`fieldset`,{"aria-label":o(`lark.agentApps`),className:`personal-lark-agent-apps`,children:[(0,z.jsx)(`legend`,{children:o(`lark.agentApps`)}),(0,z.jsx)(`small`,{children:o(`lark.agentAppsDescription`)}),(0,z.jsx)(`div`,{children:Fe.map(e=>(0,z.jsxs)(`label`,{children:[(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:e.label}),(0,z.jsx)(`small`,{children:e.agentId})]}),(0,z.jsx)(`select`,{"aria-label":o(`lark.agentAppSelection`,{agent:e.label}),onChange:t=>le(n=>({...n,[e.agentId]:t.target.value})),value:ce[e.agentId]??x,children:l.map(e=>(0,z.jsxs)(`option`,{disabled:!e.ready,value:e.app_ref,children:[e.label,e.reply_ready?``:e.ready?` · ${o(`lark.needsMessagePermissions`)}`:` · ${o(`lark.needsSetup`)}`]},e.app_ref))})]},e.agentId))})]}):null,I&&B.length>0&&!Re?(0,z.jsx)(`div`,{className:`personal-lark-group-state is-error`,role:`alert`,children:o(`lark.agentAppPermissions`)}):null,Le.length===0?(0,z.jsx)(`p`,{className:`personal-notification-error`,role:`alert`,children:o(`lark.selectRegisteredAgent`)}):null,(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:o(`lark.replyMode`)}),(0,z.jsx)(`select`,{"aria-label":o(`lark.replyMode`),onChange:e=>oe(e.target.value),value:ae,children:(0,z.jsx)(`option`,{value:`topic_reply`,children:o(`lark.topicReply`)})}),(0,z.jsx)(`small`,{children:o(`lark.replyModeDescription`)})]}),(0,z.jsxs)(`p`,{className:`personal-lark-cardinality`,children:[(0,z.jsx)(Kp,{size:15}),o(`lark.cardinality`)]}),fe?(0,z.jsx)(`p`,{className:`personal-notification-error`,role:`alert`,children:fe}):null,(0,z.jsxs)(`footer`,{children:[(0,z.jsx)(`button`,{className:`personal-secondary-action`,onClick:()=>b(!1),type:`button`,children:o(`lark.cancel`)}),(0,z.jsxs)(`button`,{className:`personal-primary-action`,disabled:p||!x||!ze?.reply_ready||!Re||!C||!k||Le.length===0||ue,onClick:()=>void qe(),type:`button`,children:[ue?(0,z.jsx)(hm,{className:`is-spinning`,size:15}):null,V]})]})]})}):null,ve?(0,z.jsx)(`div`,{className:`personal-lark-modal-backdrop is-setup`,role:`presentation`,children:(0,z.jsxs)(`section`,{"aria-labelledby":`new-lark-app-title`,"aria-modal":`true`,className:`personal-lark-modal personal-lark-setup-modal`,role:`dialog`,children:[(0,z.jsxs)(`header`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`small`,{children:o(`lark.reusableWorkspaceApp`)}),(0,z.jsx)(`h2`,{id:`new-lark-app-title`,children:o(`lark.newApp`)})]}),(0,z.jsx)(`button`,{"aria-label":o(`lark.closeCreate`),onClick:()=>void Ke(),type:`button`,children:(0,z.jsx)(Gm,{size:18})})]}),we?(0,z.jsxs)(`div`,{className:`personal-lark-setup-progress`,children:[(0,z.jsx)(`span`,{className:`personal-lark-setup-icon is-${we.status}`,children:we.status===`ready`?(0,z.jsx)(Kp,{size:22}):(0,z.jsx)(hm,{className:we.status===`failed`?``:`is-spinning`,size:22})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:we.status===`ready`?o(`lark.appCreated`):we.status===`failed`?o(`lark.appCreateFailed`):o(`lark.waitingFeishu`)}),(0,z.jsx)(`p`,{children:we.status===`waiting_for_feishu`?o(`lark.waitingFeishuDescription`):we.status===`starting`?o(`lark.waitingLink`):we.error})]}),we.verification_url?(0,z.jsxs)(`a`,{href:we.verification_url,rel:`noreferrer`,target:`_blank`,children:[(0,z.jsx)(im,{size:15}),o(`lark.reopenFeishu`)]}):null]}):(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`p`,{className:`personal-lark-setup-copy`,children:o(`lark.setupCopy`)}),(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:o(`lark.profileName`)}),(0,z.jsx)(`input`,{"aria-label":o(`lark.profileName`),autoComplete:`off`,onChange:e=>xe(e.target.value),placeholder:`loopx-workspace-bot`,value:be})]}),(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`span`,{children:o(`lark.region`)}),(0,z.jsxs)(`select`,{"aria-label":o(`lark.region`),onChange:e=>Ce(e.target.value),value:Se,children:[(0,z.jsx)(`option`,{value:`feishu`,children:`Feishu`}),(0,z.jsx)(`option`,{value:`lark`,children:`Lark`})]})]}),be&&!/^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$/.test(be)?(0,z.jsx)(`p`,{className:`personal-notification-error`,children:o(`lark.profileValidation`)}):null]}),L?(0,z.jsx)(`p`,{className:`personal-notification-error`,children:L}):null,(0,z.jsxs)(`footer`,{children:[(0,z.jsx)(`button`,{className:`personal-secondary-action`,onClick:()=>void Ke(),type:`button`,children:o(`lark.cancel`)}),we?null:(0,z.jsxs)(`button`,{className:`personal-primary-action`,disabled:Ee||!/^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$/.test(be),onClick:()=>void Ge(),type:`button`,children:[Ee?(0,z.jsx)(hm,{className:`is-spinning`,size:15}):(0,z.jsx)(im,{size:15}),o(`lark.continueFeishu`)]})]})]})}):null]})}function ub(e){return e&&typeof e==`object`&&!Array.isArray(e)?e:{}}function db(e,t,n){let r=ub(t),i=ub(n);return Object.fromEntries(e.fields.flatMap(({key:e})=>{let t=r[e],n=i[e];return Object.hasOwn(r,e)&&t!=null?[[e,t]]:Object.hasOwn(i,e)&&n!=null?[[e,n]]:[]}))}function fb({children:e}){return e?(0,z.jsx)(`small`,{children:e}):null}function pb({copy:e,field:t,id:n,onChange:r,value:i}){let a=e[t.key]?.label??t.label,o=e[t.key]?.description??t.description,s=!r;if(t.input_kind===`boolean`)return(0,z.jsxs)(`label`,{className:`is-boolean`,htmlFor:n,children:[(0,z.jsx)(`span`,{children:a}),(0,z.jsx)(`input`,{checked:i===!0,id:n,onChange:r?e=>r(t.key,e.target.checked):void 0,readOnly:s,type:`checkbox`}),(0,z.jsx)(fb,{children:o})]});if(t.input_kind===`select`)return(0,z.jsxs)(`label`,{htmlFor:n,children:[(0,z.jsx)(`span`,{children:a}),(0,z.jsxs)(`select`,{id:n,onChange:r?e=>r(t.key,e.target.value):void 0,value:typeof i==`string`?i:``,children:[(0,z.jsx)(`option`,{value:``}),(t.options??[]).map(e=>(0,z.jsx)(`option`,{value:e,children:e},e))]}),(0,z.jsx)(fb,{children:o})]});if(t.input_kind===`string_list`)return(0,z.jsxs)(`label`,{htmlFor:n,children:[(0,z.jsx)(`span`,{children:a}),(0,z.jsx)(`textarea`,{id:n,onChange:r?e=>r(t.key,e.target.value.split(/\r?\n/u).filter(Boolean)):void 0,readOnly:s,rows:4,value:Array.isArray(i)?i.join(` +`):``}),(0,z.jsx)(fb,{children:o})]});let c=t.input_kind===`number`;return(0,z.jsxs)(`label`,{htmlFor:n,children:[(0,z.jsx)(`span`,{children:a}),(0,z.jsx)(`input`,{id:n,max:t.maximum,min:t.minimum,onChange:r?e=>r(t.key,c?Number(e.target.value):e.target.value):void 0,readOnly:s,required:t.required,type:c?`number`:`text`,value:typeof i==`number`||typeof i==`string`?i:``}),(0,z.jsx)(fb,{children:o})]})}function mb({copy:e={},disabled:t=!1,editor:n,omitKeys:r=[],onChange:i,value:a}){let o=(0,R.useId)(),s=new Set(r);return(0,z.jsx)(`fieldset`,{className:`personal-capability-fields`,disabled:t,children:n.fields.filter(e=>!s.has(e.key)).map(t=>(0,z.jsx)(pb,{copy:e,field:t,id:`${o}-${t.key.replace(/[^a-z0-9_-]/gi,`-`)}`,onChange:i,value:a[t.key]},t.key))})}var hb={en:{change_quality_qualification:{displayName:`Change quality qualification`,description:`Prepares a provider-neutral review packet, allows at most one policy-authorized safe-fix pass, and can require an exact-diff receipt.`},explore_graph:{displayName:`Explore Graph`,description:`Organizes bounded exploration as a typed evidence graph so branches, findings, and synthesis remain inspectable.`},explore_harness:{displayName:`Explore Harness`,description:`Selects a capability-owned planning and research harness profile for bounded multi-step exploration.`},lark_event_inbox:{displayName:`Lark event inbox`,description:`Receives provider events through a local-private inbox binding before LoopX projects them into governed work.`,readOnlyReason:`This capability requires a local-private inbox binding. Manage it in Lark settings or through the capability CLI.`},lark_kanban_heartbeat_sync:{displayName:`Lark Kanban heartbeat sync`,description:`Synchronizes accepted LoopX work state to the configured Lark Kanban heartbeat surface.`},local_authority_shadow:{displayName:`Local authority shadow`,description:`Observes post-commit Todo and task-lease state through the shared authority contract without taking write authority.`},multi_subagent:{displayName:`Adaptive child capacity`,description:`Sets bounded child-agent capacity and the public-safe responsibility domains in which parallel work may be delegated.`},peer_task_coordination:{displayName:`Registered-peer task coordination`,description:`Routes explicitly scoped peer-owned work to one registered coordinator without granting cross-owner mutation authority.`},periodic_report:{displayName:`Periodic reports`,description:`Turns validated Goal stage progress into a frozen report and automatically delivers it through the configured Goal Channel with exact readback.`},reward_memory:{displayName:`Reward Memory experiment`,description:`Runs an opt-in, provider-bound retrieval experiment over an explicitly allowlisted memory corpus.`,readOnlyReason:`This capability requires a reviewed local-private provider binding and an explicit Agent allowlist. Configure it through the capability CLI.`}},"zh-CN":{change_quality_qualification:{displayName:`变更质量验证`,description:`生成与 Provider 无关的审阅包,最多允许一次策略授权的安全修复,并可要求精确 diff 回执。`},explore_graph:{displayName:`探索图谱`,description:`把有界探索组织为 typed 证据图,让探索分支、发现与综合结论都可检查、可追溯。`},explore_harness:{displayName:`探索 Harness`,description:`为有界的多步探索选择由能力负责的规划与研究 Harness profile。`},lark_event_inbox:{displayName:`飞书事件收件箱`,description:`通过本机私有收件箱接收 Provider 事件,再由 LoopX 将其投影为受治理的工作。`,readOnlyReason:`此能力依赖本机私有的收件箱绑定,请在飞书设置或 capability CLI 中管理。`},lark_kanban_heartbeat_sync:{displayName:`飞书看板心跳同步`,description:`把 LoopX 已接受的工作状态同步到配置好的飞书看板心跳界面。`},local_authority_shadow:{displayName:`本地 Authority 影子观测`,description:`通过共享 Authority contract 观测提交后的 Todo 与 task lease 状态,但不取得写入权。`},multi_subagent:{displayName:`自适应子 Agent 容量`,description:`限定子 Agent 容量与可公开的职责域,只有落在这些边界内的工作才能并行委派。`},peer_task_coordination:{displayName:`已注册 Peer 任务协调`,description:`把明确限定的 Peer 工作路由给一个已注册协调者,不授予跨 Owner 修改权限。`},periodic_report:{displayName:`周期报告`,description:`把经过验证的 Goal 阶段进展整理为冻结报告,并通过配置的 Goal Channel 自动发送和精确回读。`},reward_memory:{displayName:`Reward Memory 实验`,description:`在明确 allowlist 的记忆语料上运行可选、Provider 绑定的检索实验。`,readOnlyReason:`此能力依赖经过审阅的本机私有 Provider 绑定和明确的 Agent allowlist,请通过 capability CLI 配置。`}}},gb={en:{allowed_domains:{label:`Allowed responsibility domains`,description:`Enter one bounded, public-safe domain per line.`},coordinator_agent_id:{label:`Coordinator Agent`,description:`Use an already registered Agent id; leave blank to disable coordination.`},enabled:{label:`Enabled`},max_children:{label:`Maximum children`,description:`Hard upper bound for concurrently delegated child work.`},profile:{label:`Planner profile`,description:`Select one registered Explore Harness profile.`},profile_preset:{label:`Report profile`,description:`Capability-owned report profile, such as weekly-progress.`},route_ref:{label:`Goal Channel route`,description:`Public route alias only; credentials and provider identifiers stay outside this form.`},safe_fix:{label:`Allow one bounded safe-fix pass`},strict_receipt:{label:`Require an exact-diff receipt`},timezone:{label:`Timezone`,description:`Use an IANA timezone, for example Asia/Shanghai.`}},"zh-CN":{allowed_domains:{label:`允许的职责域`,description:`每行填写一个有边界、可公开的职责域。`},coordinator_agent_id:{label:`协调 Agent`,description:`填写一个已经注册的 Agent ID;留空表示关闭协调。`},enabled:{label:`启用`},max_children:{label:`最大子 Agent 数`,description:`可同时委派的子任务硬上限。`},profile:{label:`规划 Profile`,description:`选择一个已注册的 Explore Harness profile。`},profile_preset:{label:`报告 Profile`,description:`由该能力管理的报告 profile,例如 weekly-progress。`},route_ref:{label:`Goal Channel 路由`,description:`只填写公开 route alias;凭据与 Provider 标识不会进入此表单。`},safe_fix:{label:`允许一次有界安全修复`},strict_receipt:{label:`要求精确 diff 回执`},timezone:{label:`时区`,description:`使用 IANA 时区,例如 Asia/Shanghai。`}}};function _b(e,t){let n=hb[t][e.capability_id];return n?{...e,display_name:n.displayName,description:n.description,configuration_editor:{...e.configuration_editor,...n.readOnlyReason?{read_only_reason:n.readOnlyReason}:{}}}:e}function vb(e){return gb[e]}Object.freeze(Object.keys(hb.en).sort());function yb(e,t){return e.available_scopes.includes(t)&&(t!==`machine`||!!e.machine_namespace)&&e.configuration_editor.editable&&e.configuration_editor.writable_scopes.includes(t)}function bb({values:e,t}){return(0,z.jsxs)(`details`,{className:`personal-capability-raw-values`,children:[(0,z.jsx)(`summary`,{children:t(`capabilities.rawJson`)}),(0,z.jsx)(`div`,{className:`personal-capability-value-grid`,children:e.map(({label:e,value:t})=>(0,z.jsxs)(`section`,{children:[(0,z.jsx)(`strong`,{children:e}),(0,z.jsx)(`pre`,{children:t?JSON.stringify(t,null,2):`—`})]},e))})]})}function xb({source:e,t}){return e?(0,z.jsxs)(`p`,{className:`personal-capability-effective-source`,children:[(0,z.jsx)(Im,{"aria-hidden":!0,size:15}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:t(`capabilities.effectiveSource`)}),t(`capabilities.source.${e}`)]})]}):null}function Sb({available:e,description:t,t:n}){return e?null:(0,z.jsxs)(`section`,{className:`personal-capability-editor-status is-read-only`,children:[(0,z.jsx)(Um,{"aria-hidden":!0,size:18}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:n(`capabilities.readOnly`)}),(0,z.jsx)(`p`,{children:t})]})]})}function Cb(e){return e.availability?.includes(`experimental`)?4:e.capability_id===`multi_subagent`?3:e.configuration_editor.writable_scopes.length===0||e.availability===`supported_explicit_opt_in`?2:e.availability===`supported_explicit_override`?0:1}function wb(e,t){return[...e].sort((e,n)=>{let r=Cb(e)-Cb(n);if(r!==0)return r;let i=_b(e,t),a=_b(n,t);return i.display_name.localeCompare(a.display_name,t)||e.capability_id.localeCompare(n.capability_id)})}function Tb({capabilities:e,locale:t,onSelect:n,scope:r,selectedCapabilityId:i,t:a}){return(0,z.jsx)(`nav`,{"aria-label":a(r===`goal`?`capabilities.catalog`:`machine.capabilityCatalog`),className:`personal-capability-list`,children:wb(e,t).map(e=>{let o=_b(e,t);return(0,z.jsxs)(`button`,{"aria-current":i===o.capability_id?`page`:void 0,onClick:()=>n(o.capability_id),type:`button`,children:[(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:o.display_name}),(0,z.jsx)(`small`,{children:o.capability_id})]}),(0,z.jsx)(`em`,{children:a(o.available_scopes.includes(r)?r===`goal`?`capabilities.goalScope`:`capabilities.machineScope`:r===`machine`?`capabilities.goalScope`:`capabilities.machineScope`)})]},o.capability_id)})})}function Eb({capability:e,locale:t}){let n=_b(e,t);return(0,z.jsxs)(`header`,{children:[(0,z.jsx)(`span`,{className:`personal-settings-icon`,children:(0,z.jsx)(Lm,{"aria-hidden":!0,size:18})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`small`,{children:n.capability_id}),(0,z.jsx)(`h2`,{children:n.display_name}),(0,z.jsx)(`p`,{children:n.description})]})]})}function Db({goalId:e,onApplied:t,selected:n,t:r}){let[i,a]=(0,R.useState)({busy:null,draft:{},partialWrite:null,preview:null}),[o,s]=(0,R.useState)(null);(0,R.useEffect)(()=>{a({busy:null,draft:db(n?.configuration_editor??{fields:[]},n?.current??n?.effective_configuration?.configuration??n?.default,n?.default),partialWrite:null,preview:null}),s(null)},[n]);async function c(t){if(!(!n||i.busy)){a(e=>({...e,busy:`preview`,partialWrite:null})),s(null);try{let r=await _g(e,n.capability_id,t);a(e=>({...e,preview:r}))}catch(e){s(e instanceof Error?e.message:r(`capabilities.previewFailed`))}finally{a(e=>({...e,busy:null}))}}}async function l(){if(!(!n||!i.preview||i.busy)){a(e=>({...e,busy:`apply`})),s(null);try{let r=db(n.configuration_editor,i.draft,n.default),o=await vg(e,n.capability_id,i.preview.action===`delete`?null:r,i.preview.plan_revision);a(e=>({...e,partialWrite:o.status===`partial_write`?o:null,preview:null})),o.status!==`partial_write`&&t()}catch(e){a(e=>({...e,preview:null})),s(e instanceof Error?e.message:r(`capabilities.applyFailed`))}finally{a(e=>({...e,busy:null}))}}}function u(e,t){a(n=>({...n,draft:{...n.draft,[e]:t},preview:null})),s(null)}return{apply:l,changeDraft:u,error:o,mutation:i,preview:c}}function Ob({mutationError:e,onApplied:t,partialWrite:n,preview:r}){let{t:i}=Ji();return(0,z.jsxs)(z.Fragment,{children:[e?(0,z.jsx)(`p`,{className:`personal-machine-error`,role:`alert`,children:e}):null,n?(0,z.jsxs)(`section`,{"aria-live":`polite`,className:`personal-capability-recovery`,children:[(0,z.jsx)(Um,{"aria-hidden":!0,size:18}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:i(`capabilities.partialWrite`)}),(0,z.jsx)(`p`,{children:i(`capabilities.partialWriteDescription`)}),(0,z.jsx)(`small`,{children:n.recommended_action})]}),(0,z.jsxs)(`button`,{onClick:t,type:`button`,children:[(0,z.jsx)(Om,{"aria-hidden":!0,size:15}),i(`capabilities.refreshSource`)]})]}):null,r?(0,z.jsxs)(`section`,{className:`personal-capability-preview`,"aria-label":i(`capabilities.preview`),children:[(0,z.jsx)(`strong`,{children:i(`capabilities.preview`)}),(0,z.jsx)(`span`,{children:i(`machine.action.${r.action}`)}),(0,z.jsx)(`small`,{children:i(`capabilities.previewLocked`)})]}):null]})}function kb({catalog:e,goalId:t,onApplied:n}){let{locale:r,t:i}=Ji(),[a,o]=(0,R.useState)(e.capabilities[0]?.capability_id??``),s=(0,R.useMemo)(()=>e.capabilities.find(e=>e.capability_id===a)??e.capabilities[0],[e.capabilities,a]),c=(0,R.useMemo)(()=>s?_b(s,r):void 0,[r,s]),{apply:l,changeDraft:u,error:d,mutation:f,preview:p}=Db({goalId:t,onApplied:n,selected:c,t:i}),{busy:m,draft:h,partialWrite:g,preview:_}=f;if(!s||!c)return(0,z.jsx)(`p`,{className:`personal-capability-empty`,children:i(`capabilities.empty`)});let v=c.available_scopes.includes(`goal`),y=yb(c,`goal`),b=c.configuration_editor.read_only_reason??i(v?`capabilities.previewOnly`:`capabilities.machineOnly`);async function x(){if(!c||!y||m)return;let e=db(c.configuration_editor,h,c.default);await p(e)}async function S(){!y||m||await p(null)}return(0,z.jsxs)(`div`,{className:`personal-capability-layout`,children:[(0,z.jsx)(Tb,{capabilities:e.capabilities,locale:r,onSelect:o,scope:`goal`,selectedCapabilityId:c.capability_id,t:i}),(0,z.jsxs)(`article`,{className:`personal-capability-detail`,children:[(0,z.jsx)(Eb,{capability:s,locale:r}),(0,z.jsx)(xb,{source:c.effective_configuration?.source,t:i}),(0,z.jsx)(Sb,{available:y,t:i,description:b}),y?(0,z.jsxs)(`section`,{className:`personal-capability-field-summary`,children:[(0,z.jsx)(`strong`,{children:i(`capabilities.fields`)}),(0,z.jsx)(mb,{disabled:!!m,copy:vb(r),editor:c.configuration_editor,onChange:u,value:h})]}):null,(0,z.jsx)(Ob,{mutationError:d,onApplied:n,partialWrite:g,preview:_}),y?(0,z.jsxs)(`footer`,{className:`personal-capability-actions`,children:[c.current&&c.available_scopes.includes(`machine`)?(0,z.jsx)(`button`,{disabled:!!m,onClick:()=>void S(),type:`button`,children:i(`capabilities.restoreInheritance`)}):null,(0,z.jsx)(`button`,{disabled:!!m,onClick:()=>void x(),type:`button`,children:i(m===`preview`?`common.loading`:`capabilities.previewChanges`)}),(0,z.jsx)(`button`,{className:`is-primary`,disabled:!!m||!_,onClick:()=>void l(),type:`button`,children:i(m===`apply`?`common.loading`:`capabilities.applyPreview`)})]}):null,(0,z.jsx)(bb,{values:[{label:i(`capabilities.goalValue`),value:c.current},{label:i(c.machine_current?`capabilities.machineValue`:`capabilities.defaultValue`),value:c.machine_current??c.default}],t:i},s.capability_id)]})]})}function Ab({goalId:e}){let{t}=Ji(),[n,r]=(0,R.useState)(null),[i,a]=(0,R.useState)(null),[o,s]=(0,R.useState)(!1);function c(){e&&(s(!0),a(null),gg(e).then(r).catch(e=>a(e instanceof Error?e.message:t(`capabilities.loadFailed`))).finally(()=>s(!1)))}return(0,R.useEffect)(c,[e]),e?o&&!n?(0,z.jsxs)(`p`,{"aria-live":`polite`,className:`personal-capability-empty`,children:[(0,z.jsx)(hm,{className:`personal-spin`,size:18}),t(`capabilities.loading`)]}):i?(0,z.jsxs)(`section`,{className:`personal-capability-error`,role:`alert`,children:[(0,z.jsx)(Um,{"aria-hidden":!0,size:18}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:t(`capabilities.loadFailed`)}),(0,z.jsx)(`small`,{children:i})]}),(0,z.jsxs)(`button`,{onClick:c,type:`button`,children:[(0,z.jsx)(Om,{"aria-hidden":!0,size:15}),t(`capabilities.retry`)]})]}):n?(0,z.jsxs)(`section`,{className:`personal-capability-settings`,"data-revision":n.revision,children:[(0,z.jsxs)(`div`,{className:`personal-capability-scope-note`,children:[(0,z.jsx)(Im,{"aria-hidden":!0,size:17}),(0,z.jsxs)(`p`,{children:[(0,z.jsx)(`strong`,{children:t(`capabilities.atomicOverride`)}),t(`capabilities.atomicOverrideDescription`)]})]}),(0,z.jsx)(kb,{catalog:n.capability_catalog,goalId:e,onApplied:c})]}):null:(0,z.jsx)(`p`,{className:`personal-capability-empty`,children:t(`capabilities.chooseGoal`)})}function jb(e){return e&&typeof e==`object`&&!Array.isArray(e)?e:{}}function Mb(e,t){let n=t?.machine_namespace;return n?e?.machine_configuration?.namespaces[n]:void 0}function Nb(e,t,n){return{...jb(e.default),...jb(t),...n}}function Pb(e,t){for(let n of e.configuration_editor.fields){let e=t[n.key];if(n.required&&(e==null||e===``))return!1}return e.capability_id===`periodic_report`&&t.enabled===!0?!!(String(t.profile_preset??``).trim()&&String(t.route_ref??``).trim()&&String(t.timezone??``).trim()):!0}function Fb(e){try{let t=JSON.parse(e);return t&&typeof t==`object`&&!Array.isArray(t)?t:null}catch{return null}}function Ib(e){return e?e===`absent`?e:e.replace(/^sha256:/,``).slice(0,12):`—`}function Lb(){let{locale:e,t}=Ji(),[n,r]=(0,R.useState)(null),[i,a]=(0,R.useState)(``),[o,s]=(0,R.useState)({}),[c,l]=(0,R.useState)(`{}`),[u,d]=(0,R.useState)(`guided`),[f,p]=(0,R.useState)(null),[m,h]=(0,R.useState)(`upsert`),[g,_]=(0,R.useState)(null),[v,y]=(0,R.useState)(null),[b,x]=(0,R.useState)(`load`),[S,C]=(0,R.useState)(null),[w,T]=(0,R.useState)(null),E=n?.capability_catalog.capabilities??[],D=E.find(e=>e.capability_id===i)??E[0],O=D?_b(D,e):void 0,k=Mb(n,O),ee=!!(O?.machine_namespace&&k),A=!!(O&&yb(O,`machine`)),j=(0,R.useMemo)(()=>Fb(c),[c]),te=O?u===`json`?j:Nb(O,k,o):null,ne=!!(O&&(u===`json`?j:Pb(O,te??{})));async function re(){r(await hg())}(0,R.useEffect)(()=>{let e=!0;return hg().then(t=>{e&&(r(t),a(t.capability_catalog.capabilities.find(e=>e.available_scopes.includes(`machine`))?.capability_id??``))}).catch(n=>{e&&C(n instanceof Error?n.message:t(`machine.loadError`))}).finally(()=>{e&&x(null)}),()=>{e=!1}},[t]),(0,R.useEffect)(()=>{if(!O)return;let e=Mb(n,O),t=db(O.configuration_editor,e??O.default,O.default),r=Nb(O,e,t);s(t),l(JSON.stringify(r,null,2)),d(A?`guided`:`json`),p(null),h(`upsert`),y(null)},[n,i,e]);function M(e,t){s(n=>({...n,[e]:t})),p(null),h(`upsert`),C(null),T(null)}function N(e){if(O){if(e===`json`)l(JSON.stringify(Nb(O,k,o),null,2));else if(j)s(db(O.configuration_editor,j,O.default));else{C(t(`machine.jsonInvalid`));return}d(e),p(null),h(`upsert`),C(null)}}async function ie(){if(!(!A||!O?.machine_namespace||!te||!ne||b)){x(`preview`),C(null),T(null);try{h(`upsert`),p(await yg(O.machine_namespace,te))}catch(e){C(e instanceof Error?e.message:t(`machine.previewError`))}finally{x(null)}}}async function ae(){if(!(!A||!O?.machine_namespace||!ee||b)){x(`preview`),C(null),T(null);try{h(`remove`),p(await xg(O.machine_namespace))}catch(e){C(e instanceof Error?e.message:t(`machine.previewError`))}finally{x(null)}}}async function oe(){if(!A||!O?.machine_namespace||!f||b||m===`upsert`&&!te)return;x(`apply`),C(null);let e=m;try{let n=e===`remove`?await Sg(O.machine_namespace,f.plan_revision):await bg(O.machine_namespace,te,f.plan_revision);_(n),p(null),h(`upsert`),y(null),await re(),T(n.status===`applied`?t(e===`remove`?`machine.removed`:`machine.applied`):t(`machine.unchanged`))}catch(e){p(null),h(`upsert`),C(e instanceof Error?e.message:t(`machine.applyError`))}finally{x(null)}}async function P(){if(!(!g?.transaction_id||b)){x(`rollback-preview`),C(null);try{y(await Cg(g.transaction_id))}catch(e){C(e instanceof Error?e.message:t(`machine.rollbackError`))}finally{x(null)}}}async function F(){if(!(!g?.transaction_id||!v||b)){x(`rollback`),C(null);try{await wg(g.transaction_id,v.plan_revision),_(null),y(null),p(null),await re(),T(t(`machine.rolledBack`))}catch(e){y(null),C(e instanceof Error?e.message:t(`machine.rollbackError`))}finally{x(null)}}}return b===`load`?(0,z.jsx)(`div`,{className:`personal-machine-loading`,role:`status`,children:t(`common.loading`)}):O?(0,z.jsxs)(`section`,{className:`personal-capability-settings`,"data-revision":n?.revision,children:[(0,z.jsxs)(`div`,{className:`personal-capability-scope-note`,children:[(0,z.jsx)(Im,{"aria-hidden":!0,size:17}),(0,z.jsxs)(`p`,{children:[(0,z.jsx)(`strong`,{children:t(`machine.liveDefault`)}),t(`machine.liveDefaultDescription`)]})]}),(0,z.jsxs)(`div`,{className:`personal-capability-layout`,children:[(0,z.jsx)(Tb,{capabilities:E,locale:e,onSelect:a,scope:`machine`,selectedCapabilityId:O.capability_id,t}),(0,z.jsxs)(`article`,{className:`personal-capability-detail`,children:[(0,z.jsx)(Eb,{capability:D,locale:e}),O.available_scopes.includes(`machine`)?(0,z.jsx)(xb,{source:ee?`machine_default`:`capability_default`,t}):null,(0,z.jsx)(Sb,{available:A,t,description:O.available_scopes.includes(`machine`)?t(`machine.editorUnavailableDescription`):t(`machine.goalOnly`)}),O.capability_id===`periodic_report`?(0,z.jsxs)(`section`,{className:`personal-capability-behavior-note`,children:[(0,z.jsx)(Im,{"aria-hidden":!0,size:18}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:t(`machine.periodicReportActivation`)}),(0,z.jsx)(`p`,{children:t(`machine.periodicReportActivationDescription`)})]})]}):null,A?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`div`,{className:`personal-capability-editor-mode`,children:[(0,z.jsx)(`span`,{children:t(`machine.editorMode`)}),(0,z.jsxs)(`div`,{role:`group`,"aria-label":t(`machine.editorMode`),children:[(0,z.jsx)(`button`,{"aria-pressed":u===`guided`,disabled:!A,onClick:()=>N(`guided`),type:`button`,children:t(`machine.visualEditor`)}),(0,z.jsxs)(`button`,{"aria-pressed":u===`json`,onClick:()=>N(`json`),type:`button`,children:[(0,z.jsx)($p,{"aria-hidden":!0,size:14}),t(`machine.jsonEditor`)]})]})]}),u===`guided`?(0,z.jsxs)(`section`,{className:`personal-capability-field-summary`,children:[(0,z.jsx)(`strong`,{children:t(`capabilities.fields`)}),(0,z.jsx)(mb,{copy:vb(e),disabled:!!b,editor:O.configuration_editor,onChange:M,value:o}),ne?null:(0,z.jsx)(`p`,{className:`personal-machine-validation`,role:`alert`,children:t(`machine.requiredFields`)})]}):(0,z.jsxs)(`label`,{className:`personal-capability-json-editor`,htmlFor:`machine-configuration-json`,children:[(0,z.jsx)(`span`,{children:t(`machine.jsonConfiguration`)}),(0,z.jsx)(`textarea`,{"aria-describedby":`machine-configuration-json-help`,disabled:!!b,id:`machine-configuration-json`,onChange:e=>{l(e.target.value),p(null),C(null)},rows:12,spellCheck:!1,value:c}),(0,z.jsx)(`small`,{id:`machine-configuration-json-help`,children:t(`machine.jsonConfigurationHelp`)}),j?null:(0,z.jsx)(`span`,{className:`personal-machine-validation`,role:`alert`,children:t(`machine.jsonInvalid`)})]})]}):null,S?(0,z.jsx)(`p`,{className:`personal-machine-error`,role:`alert`,children:S}):null,w?(0,z.jsxs)(`p`,{className:`personal-machine-notice`,role:`status`,"aria-live":`polite`,children:[(0,z.jsx)(Kp,{"aria-hidden":!0,size:16}),w]}):null,f?(0,z.jsxs)(`section`,{"aria-label":t(`machine.preview`),className:`personal-machine-preview`,children:[(0,z.jsxs)(`header`,{children:[(0,z.jsx)(`strong`,{children:t(`machine.preview`)}),(0,z.jsx)(`span`,{children:t(`machine.action.${f.action}`)})]}),(0,z.jsxs)(`dl`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:t(`machine.currentRevision`)}),(0,z.jsx)(`dd`,{title:f.current_revision,children:Ib(f.current_revision)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:t(`machine.desiredRevision`)}),(0,z.jsx)(`dd`,{title:f.desired_revision,children:Ib(f.desired_revision)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:t(`machine.changedNamespaces`)}),(0,z.jsx)(`dd`,{children:f.changed_namespaces.join(`, `)||t(`common.none`)})]})]}),(0,z.jsx)(`p`,{children:t(`machine.previewLocked`)})]}):null,g?.rollback_available&&g.transaction_id?(0,z.jsxs)(`section`,{className:`personal-machine-rollback`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:t(`machine.rollbackAvailable`)}),(0,z.jsx)(`p`,{children:t(v?`machine.rollbackPreviewDescription`:`machine.rollbackDescription`)})]}),(0,z.jsxs)(`button`,{className:`personal-secondary-action`,disabled:!!b||!!(v&&!v.rollback_allowed),onClick:()=>void(v?F():P()),type:`button`,children:[(0,z.jsx)(km,{"aria-hidden":!0,size:15}),t(b===`rollback`||b===`rollback-preview`?`common.loading`:v?`machine.confirmRollback`:`machine.previewRollback`)]})]}):null,A?(0,z.jsxs)(`footer`,{className:`personal-capability-actions`,children:[ee?(0,z.jsxs)(`button`,{className:`is-danger`,disabled:!!b,onClick:()=>void ae(),type:`button`,children:[(0,z.jsx)(Hm,{"aria-hidden":!0,size:15}),t(`machine.previewRemoval`)]}):null,(0,z.jsx)(`button`,{disabled:!!b||!ne,onClick:()=>void ie(),type:`button`,children:t(b===`preview`?`common.loading`:`machine.previewChanges`)}),(0,z.jsx)(`button`,{className:`is-primary`,disabled:!!b||!f,onClick:()=>void oe(),type:`button`,children:t(b===`apply`?`common.loading`:`machine.applyPreview`)})]}):null,O.available_scopes.includes(`machine`)?(0,z.jsx)(bb,{values:[{label:t(`machine.currentValue`),value:k},{label:t(`capabilities.defaultValue`),value:O.default}],t},O.capability_id):null]})]})]}):(0,z.jsx)(`p`,{className:`personal-capability-empty`,children:t(`machine.capabilityEmpty`)})}var Rb={appearance:Sm,capabilities:Lm,language:fm,lark:Fm,machine:Nm};function zb({focusGoalConnection:e=!1,goals:t,initialGoalId:n,initialTab:r=`lark`,onChanged:i,onClose:a,onThemeChange:o,theme:s}){let{locale:c,setLocale:l,t:u}=Ji(),[d,f]=(0,R.useState)(r),p=[...n?[{description:u(`settings.capabilitiesTabDescription`),key:`capabilities`,label:u(`capabilities.title`)}]:[],{description:u(`settings.machineTabDescription`),key:`machine`,label:u(`machine.title`)},{description:u(`settings.larkTabDescription`),key:`lark`,label:`Lark`},{description:u(`settings.appearanceTabDescription`),key:`appearance`,label:u(`settings.appearance`)},{description:u(`settings.languageTabDescription`),key:`language`,label:u(`settings.language`)}],m=[{description:u(`settings.languageEnglishDescription`),label:u(`settings.languageEnglish`),value:`en`},{description:u(`settings.languageSimplifiedChineseDescription`),label:u(`settings.languageSimplifiedChinese`),value:`zh-CN`}],h={appearance:{description:u(`settings.appearanceDescription`),eyebrow:u(`settings.workspaceDisplay`),title:u(`settings.appearance`)},capabilities:{description:u(`capabilities.description`),eyebrow:u(`capabilities.goalPolicy`),title:u(`capabilities.title`)},language:{description:u(`settings.languageDescription`),eyebrow:u(`settings.workspaceDisplay`),title:u(`settings.language`)},lark:{description:u(`lark.description`),eyebrow:u(`settings.goalConnections`),title:`Lark`},machine:{description:u(`machine.description`),eyebrow:u(`machine.machinePolicy`),title:u(`machine.title`)}}[d];return(0,z.jsxs)(`section`,{"aria-label":u(`settings.title`),className:`personal-settings-page`,"data-pw-theme":s,children:[(0,z.jsxs)(`aside`,{className:`personal-settings-sidebar`,children:[(0,z.jsxs)(`button`,{className:`personal-settings-back`,onClick:a,type:`button`,children:[(0,z.jsx)(Lp,{size:17}),(0,z.jsx)(`span`,{children:u(`settings.back`)})]}),(0,z.jsxs)(`div`,{className:`personal-settings-title`,children:[(0,z.jsx)(`small`,{children:u(`settings.eyebrow`)}),(0,z.jsx)(`strong`,{children:u(`settings.title`)})]}),(0,z.jsx)(`nav`,{"aria-label":u(`settings.categories`),className:`personal-settings-tabs`,children:p.map(e=>{let t=Rb[e.key];return(0,z.jsxs)(`button`,{"aria-current":d===e.key?`page`:void 0,onClick:()=>f(e.key),type:`button`,children:[(0,z.jsx)(t,{size:17}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:e.label}),(0,z.jsx)(`small`,{children:e.description})]})]},e.key)})})]}),(0,z.jsxs)(`main`,{className:`personal-settings-body`,children:[(0,z.jsx)(`header`,{className:`personal-settings-header`,children:(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`small`,{children:h.eyebrow}),(0,z.jsx)(`h1`,{children:h.title}),(0,z.jsx)(`p`,{children:h.description})]})}),d===`lark`?(0,z.jsx)(lb,{embedded:!0,focusGoalConnection:e,goals:t,initialGoalId:n,onChanged:i,onClose:a}):null,d===`machine`?(0,z.jsx)(Lb,{}):null,d===`capabilities`?(0,z.jsx)(Ab,{goalId:n}):null,d===`appearance`?(0,z.jsxs)(`section`,{className:`personal-detail-card personal-appearance-settings`,children:[(0,z.jsx)(`small`,{children:u(`settings.workspaceDisplay`)}),(0,z.jsx)(`h3`,{children:u(`settings.appearance`)}),(0,z.jsx)(`p`,{children:u(`settings.themeDescription`)}),(0,z.jsxs)(`div`,{className:`personal-settings-choice-group`,role:`radiogroup`,"aria-label":u(`settings.workspaceTheme`),children:[(0,z.jsxs)(`button`,{"aria-checked":s===`loopx`,onClick:()=>o(`loopx`),role:`radio`,type:`button`,children:[(0,z.jsx)(`span`,{className:`personal-settings-theme-swatch is-loopx`}),(0,z.jsx)(`strong`,{children:u(`settings.themeLoopx`)}),(0,z.jsx)(`small`,{children:u(`settings.themeLoopxDescription`)})]}),(0,z.jsxs)(`button`,{"aria-checked":s===`paper`,onClick:()=>o(`paper`),role:`radio`,type:`button`,children:[(0,z.jsx)(`span`,{className:`personal-settings-theme-swatch is-paper`}),(0,z.jsx)(`strong`,{children:u(`settings.themeDefault`)}),(0,z.jsx)(`small`,{children:u(`settings.themeDefaultDescription`)})]}),(0,z.jsxs)(`button`,{"aria-checked":s===`brutal`,onClick:()=>o(`brutal`),role:`radio`,type:`button`,children:[(0,z.jsx)(`span`,{className:`personal-settings-theme-swatch is-brutal`}),(0,z.jsx)(`strong`,{children:u(`settings.themeHighContrast`)}),(0,z.jsx)(`small`,{children:u(`settings.themeHighContrastDescription`)})]})]})]}):null,d===`language`?(0,z.jsxs)(`section`,{className:`personal-settings-card`,children:[(0,z.jsxs)(`header`,{children:[(0,z.jsx)(`span`,{className:`personal-settings-icon`,children:(0,z.jsx)(fm,{size:18})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`h2`,{children:u(`settings.language`)}),(0,z.jsx)(`p`,{children:u(`settings.languageDescription`)})]})]}),(0,z.jsx)(`div`,{"aria-label":u(`settings.language`),className:`personal-language-options`,role:`radiogroup`,children:m.map(e=>(0,z.jsxs)(`button`,{"aria-checked":c===e.value,className:c===e.value?`is-selected`:``,onClick:()=>l(e.value),role:`radio`,type:`button`,children:[(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`strong`,{children:e.label}),(0,z.jsx)(`small`,{children:e.description})]}),c===e.value?(0,z.jsx)(Kp,{"aria-hidden":!0,size:17}):null]},e.value))}),(0,z.jsx)(`footer`,{children:u(`settings.languageStoredLocally`)})]}):null]})]})}var Bb=`loopx-pw-theme`,Vb=`loopx`;function Hb(){try{let e=window.localStorage.getItem(Bb);return e===`loopx`||e===`paper`||e===`brutal`?e:Vb}catch{return Vb}}function Ub(e){try{window.localStorage.setItem(Bb,e)}catch{}}function Wb({drawer:e,drawerMode:t=`panel`,drawerOpen:n,main:r,mobileSidebarOpen:i=!1,onCloseMobileSidebar:a,sidebar:o,theme:s=`loopx`}){let{t:c}=Ji(),l=(0,R.useRef)(null),u=(0,R.useRef)(null);return(0,R.useEffect)(()=>{if(!i)return;u.current=document.activeElement instanceof HTMLElement?document.activeElement:null;let e=l.current?.querySelectorAll(`button:not([disabled]), a[href], select:not([disabled]), textarea:not([disabled]), input:not([disabled]), [tabindex]:not([tabindex="-1"])`);e?.[0]?.focus();function t(t){if(t.key!==`Tab`||!e?.length)return;let n=e[0],r=e[e.length-1];t.shiftKey&&document.activeElement===n?(t.preventDefault(),r.focus()):!t.shiftKey&&document.activeElement===r&&(t.preventDefault(),n.focus())}return document.addEventListener(`keydown`,t),()=>{document.removeEventListener(`keydown`,t),u.current?.focus(),u.current=null}},[i]),(0,z.jsxs)(`section`,{className:`personal-workspace-shell${n?` has-drawer`:``}${n&&t.startsWith(`inspector`)?` has-task-inspector`:``}${t===`inspector-full`?` is-task-inspector-full`:``}${i?` mobile-sidebar-open`:``}`,"data-pw-theme":s,children:[i?(0,z.jsx)(`button`,{"aria-hidden":!0,className:`personal-sidebar-backdrop`,onClick:a,tabIndex:-1,type:`button`}):null,(0,z.jsx)(`aside`,{"aria-label":i?c(`header.goalNavigation`):void 0,"aria-modal":i?!0:void 0,className:`personal-workspace-sidebar`,"data-workspace-sidebar":!0,ref:l,role:i?`dialog`:void 0,children:(0,z.jsxs)(`div`,{className:`personal-workspace-sidebar-inner`,children:[i?(0,z.jsxs)(`button`,{className:`personal-sr-only`,onClick:a,type:`button`,children:[c(`common.close`),` `,c(`header.goalNavigation`)]}):null,o]})}),(0,z.jsx)(`main`,{"aria-hidden":i||void 0,className:`personal-workspace-main`,inert:i||void 0,children:r}),n?(0,z.jsx)(`aside`,{className:`personal-workspace-drawer`,"data-context-drawer":!0,"data-drawer-mode":t,children:e}):null]})}function Gb(e){let t=e.match(/(?:下一步|建议|行动项|待办)[::\s]*([^\n]+)/u),n=t?t[1]:e;n=n.replace(/```[\s\S]*?```/g,``).replace(/`([^`]+)`/g,`$1`).replace(/\[([^\]]+)\]\([^)]+\)/g,`$1`).replace(/[#*~_>]/g,``).replace(/^[-*•\d+.\s]+/u,``).replace(/^(好的|没问题|收到|建议如下|任务如下|分析如下|结论[::])[\s,,::]*/u,``);let r=(n.split(/\r?\n/).map(e=>e.trim()).filter(Boolean)[0]||n).replace(/\s+/gu,` `).trim();return Array.from(r).slice(0,120).join(``)}function Kb(e){let t=new Map;return e.forEach(e=>{let n=e.fields.find(e=>e.key===`todo_id`)?.value??``,r=[e.actionKind,e.goalId??``,n,e.title].join(`:`);t.set(r,e)}),[...t.values()]}function qb(e,t,n){if(!e)return n(`home.noFirstActivity`);let r=new Date(e);if(Number.isNaN(r.getTime()))return e;let i=new Date,a=new Intl.DateTimeFormat(t,{hour:`2-digit`,minute:`2-digit`,hour12:!1}).format(r);return r.toDateString()===i.toDateString()?n(`home.todayAt`,{time:a}):new Intl.DateTimeFormat(t,{month:`numeric`,day:`numeric`,hour:`2-digit`,minute:`2-digit`,hour12:!1}).format(r)}function Jb({goals:e,onSelectGoal:t,onRetry:n,systemHealth:r}){let{locale:i,t:a}=Ji(),o=e.filter(e=>e.activationState===`active`),s=o.filter(e=>e.loadState===`error`).length,c=[{description:a(`home.lane.needsYouDescription`),key:`needs_you`,label:a(`home.lane.needsYou`)},{description:a(`home.lane.runningDescription`),key:`running`,label:a(`home.lane.running`)},{description:a(`home.lane.observingDescription`),key:`observing`,label:a(`home.lane.observing`)},{description:a(`home.lane.scheduledDescription`),key:`scheduled`,label:a(`home.lane.scheduled`)}],l=Object.fromEntries(c.map(e=>[e.key,[]])),u=[],d=[];e.filter(e=>!e.loadState).forEach(e=>{let t=ty(e);t===`history`?u.push(e):t===`stopped`?d.push(e):l[t].push(e)});let f=e=>(0,z.jsxs)(`button`,{className:`personal-home-goal-card`,"data-goal-state":e.loadState??e.state,"data-load-error":e.loadError,onClick:()=>t(e.goalId),type:`button`,children:[(0,z.jsxs)(`span`,{className:`personal-home-goal-meta`,children:[(0,z.jsx)(`i`,{}),e.agentLaneCount&&e.agentLaneCount>1?a(`header.workAgentCount`,{count:e.agentLaneCount}):e.agentLabel??e.agentId]}),(0,z.jsx)(`strong`,{children:e.title}),(0,z.jsx)(`p`,{children:e.loadError?a(`startup.error.${e.loadError}`):e.needsYou??e.nextSentence}),(0,z.jsxs)(`footer`,{children:[(0,z.jsx)(`span`,{children:e.loadState?a(e.loadState===`error`?`startup.goalError`:`startup.goalLoading`):Yi(e.state,i)}),(0,z.jsx)(`small`,{title:e.latestActivity,children:e.loadState?``:e.latestActivity?qb(e.latestActivity,i,a):e.agentTodos.length?a(`home.taskCount`,{count:e.agentTodos.length}):a(`home.noActivity`)})]})]},e.goalId);return(0,z.jsxs)(`section`,{"aria-label":a(`home.workspace`),className:`personal-home-board`,children:[r&&(!r.ok||r.issues.length>0||r.freshnessWarning)?(0,z.jsxs)(`div`,{className:`personal-system-health-banner`,role:`alert`,children:[(0,z.jsxs)(`div`,{className:`personal-system-health-header`,children:[(0,z.jsx)(Xp,{size:15}),(0,z.jsx)(`strong`,{children:a(`home.systemHealth`,{summary:r.summary})}),r.freshnessWarning?(0,z.jsxs)(`small`,{children:[`(`,r.freshnessWarning,`)`]}):null]}),r.issues.length>0?(0,z.jsx)(`ul`,{className:`personal-system-health-issues`,children:r.issues.map((e,t)=>(0,z.jsx)(`li`,{children:e},t))}):null]}):null,o.some(e=>e.loadState)?(0,z.jsxs)(`section`,{className:`personal-home-lane`,"aria-live":`polite`,children:[(0,z.jsx)(`header`,{children:a(`startup.progress`,{loaded:o.filter(e=>!e.loadState).length,total:o.length})}),s?(0,z.jsxs)(`div`,{className:`personal-stopped-goal-error`,role:`status`,children:[(0,z.jsx)(`span`,{children:a(`startup.failedCount`,{count:s})}),(0,z.jsx)(`button`,{className:`min-h-11 rounded-md border px-3 py-2 text-sm`,onClick:n,type:`button`,children:a(`startup.retryFailed`)})]}):null,o.filter(e=>e.loadState).map(f)]}):null,(0,z.jsx)(`div`,{className:`personal-home-lanes`,children:c.map(e=>(0,z.jsxs)(`section`,{className:`personal-home-lane is-${e.key}`,"data-testid":`personal-home-lane-${e.key}`,children:[(0,z.jsxs)(`header`,{children:[(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`i`,{}),e.label]}),(0,z.jsx)(`b`,{children:l[e.key].length})]}),(0,z.jsx)(`p`,{children:e.description}),(0,z.jsx)(`div`,{className:`personal-home-lane-list`,children:l[e.key].length?l[e.key].map(f):(0,z.jsx)(`span`,{className:`personal-home-empty`,children:a(`home.empty`)})})]},e.key))}),(0,z.jsxs)(`details`,{className:`personal-home-history`,children:[(0,z.jsxs)(`summary`,{children:[(0,z.jsx)(`span`,{children:a(`home.history`)}),(0,z.jsx)(`b`,{children:u.length}),(0,z.jsx)(`small`,{children:a(`home.completedGoals`)})]}),(0,z.jsx)(`div`,{children:u.length?u.map(f):(0,z.jsx)(`span`,{className:`personal-home-empty`,children:a(`home.noCompletedGoals`)})})]}),d.length?(0,z.jsxs)(`details`,{className:`personal-home-history is-stopped`,children:[(0,z.jsxs)(`summary`,{children:[(0,z.jsx)(`span`,{children:a(`home.stopped`)}),(0,z.jsx)(`b`,{children:d.length}),(0,z.jsx)(`small`,{children:a(`home.preservedState`)})]}),(0,z.jsx)(`div`,{children:d.map(f)})]}):null]})}function Yb({items:e,onSelect:t,reportState:n}){let{locale:r,t:i}=Ji();return(0,z.jsxs)(`section`,{className:`personal-object-list personal-files-list`,"data-testid":`personal-goal-outputs`,children:[(0,z.jsxs)(`header`,{children:[(0,z.jsx)(`strong`,{children:i(`files.title`)}),(0,z.jsx)(`span`,{children:e.length})]}),n?.loading?(0,z.jsxs)(`p`,{className:`personal-object-list-state`,role:`status`,children:[(0,z.jsx)(Om,{className:`is-spinning`,size:14}),i(`files.loadingReports`)]}):null,n?.error?(0,z.jsxs)(`p`,{className:`personal-object-list-state is-error`,role:`alert`,children:[(0,z.jsx)(Xp,{size:14}),i(`files.reportLoadFailed`),`: `,n.error]}):null,!n?.loading&&!n?.error&&e.length===0?(0,z.jsxs)(`p`,{className:`personal-object-list-state`,children:[(0,z.jsx)(cm,{size:14}),i(`files.empty`)]}):null,e.map(e=>(0,z.jsxs)(`button`,{"data-output-kind":e.output.kind,onClick:()=>t({item:e.output,kind:`output`}),type:`button`,children:[(0,z.jsx)(`span`,{className:`personal-file-icon`,children:(0,z.jsx)(cm,{size:16})}),(0,z.jsx)(`strong`,{children:e.output.title}),e.output.report?(0,z.jsx)(`em`,{children:i(`files.reportDelta`,{added:e.output.report.addedCount,changed:e.output.report.changedCount})}):null,(0,z.jsx)(`p`,{children:e.output.summary??e.output.safePreview??e.output.kind??i(`files.emptySummary`)}),(0,z.jsx)(`small`,{title:e.output.createdAt,children:[e.output.goalTitle,e.output.kind===`report`?i(`files.verifiedReport`):null,e.output.todoId?`${i(`common.task`)} ${e.output.todoId}`:null,qb(e.output.createdAt,r,i)].filter(Boolean).join(` · `)})]},e.id))]})}function Xb({agentLabel:e,messages:t,onClose:n,onDraftTask:r,onOpenConversation:i,title:a}){let{t:o}=Ji(),s=t.reduce((e,t,n)=>t.role===`user`?n:e,0),c=t.slice(Math.max(0,s)).slice(-3),l=c.filter(e=>e.role===`assistant`&&!e.pending).at(-1);return(0,R.useEffect)(()=>{if(!n)return;let e=e=>{e.key===`Escape`&&n()};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[n]),(0,z.jsxs)(`aside`,{"aria-label":o(`conversation.receipt`),className:`personal-manager-conversation-tray`,children:[(0,z.jsxs)(`header`,{children:[(0,z.jsxs)(`span`,{children:[(0,z.jsx)(Up,{size:16}),(0,z.jsx)(`strong`,{children:a??o(`conversation.title`)}),(0,z.jsx)(`small`,{children:t.at(-1)?.pending?o(`conversation.replying`):o(`common.recently`)})]}),(0,z.jsxs)(`div`,{className:`personal-manager-conversation-actions`,children:[r&&l?(0,z.jsxs)(`button`,{className:`personal-manager-conversation-btn`,onClick:()=>r(l.text),title:o(`conversation.convertHint`),type:`button`,children:[(0,z.jsx)(mm,{size:13}),(0,z.jsx)(`span`,{children:o(`conversation.toTask`)})]}):null,(0,z.jsx)(`button`,{className:`personal-manager-conversation-link`,onClick:i,type:`button`,children:o(`conversation.full`)}),n?(0,z.jsx)(`button`,{"aria-label":o(`conversation.close`),className:`personal-manager-conversation-close`,onClick:n,title:o(`conversation.close`),type:`button`,children:(0,z.jsx)(Gm,{size:14})}):null]})]}),(0,z.jsx)(`div`,{"aria-live":`polite`,className:`personal-manager-conversation-messages`,children:c.map(t=>(0,z.jsxs)(`article`,{className:`is-${t.role}`,children:[(0,z.jsx)(`strong`,{children:t.role===`user`?o(`common.you`):t.agentLabel??e??o(`header.manager`)}),(0,z.jsxs)(`div`,{className:`personal-manager-conversation-bubble`,children:[t.role===`user`?(0,z.jsx)(`p`,{children:t.text}):(0,z.jsx)(gy,{text:t.text}),t.pending?(0,z.jsx)(`small`,{children:o(`conversation.agentPending`)}):null]})]},t.id))})]})}function Zb({onClose:e,onOpenDetails:t,run:n}){let{t:r}=Ji();return(0,z.jsxs)(`section`,{"aria-label":r(`session.record`),className:`personal-session-record`,children:[(0,z.jsxs)(`header`,{children:[(0,z.jsxs)(`span`,{children:[(0,z.jsx)(Up,{size:17}),r(`session.record`)]}),(0,z.jsx)(`button`,{"aria-label":r(`session.closeRecord`),onClick:e,type:`button`,children:(0,z.jsx)(Gm,{size:15})})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:n.title}),(0,z.jsx)(`p`,{children:r(`session.recordDescription`)})]}),(0,z.jsxs)(`dl`,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Agent`}),(0,z.jsx)(`dd`,{children:n.agentLabel})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:r(`common.status`)}),(0,z.jsx)(`dd`,{children:Xi(n.sessionStatus??n.status,r)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Session`}),(0,z.jsx)(`dd`,{title:n.sessionId,children:n.sessionId})]})]}),(0,z.jsx)(`button`,{className:`personal-secondary-action`,onClick:t,type:`button`,children:r(`session.details`)})]})}function Qb(e,t,n){let r=[];if(t===null)return e.userTodos.slice(0,4).forEach(t=>r.push({attention:{...t,goalTitle:t.goalTitle??ey(e,t.goalId)},id:`attention:${t.todoId}`,kind:`attention`})),e.goals.filter(e=>ty(e)===`running`).slice(0,4).forEach(e=>r.push({id:`run:${e.goalId}`,kind:`run`,run:{agentId:e.agentId,agentLabel:e.agentLabel??e.agentId,completedSteps:e.doneTodoCount??e.agentTodos.filter(e=>e.done).length,goalId:e.goalId,goalTitle:e.title,latestActivity:e.agentSentence,runId:`goal:${e.goalId}`,status:`running`,title:e.nextSentence,totalSteps:Math.max((e.doneTodoCount??0)+e.agentTodos.filter(e=>!e.done).length,1)}})),r;let i=e.goals.find(e=>e.goalId===t);if(!i)return r;i.needsYou&&r.push({attention:{blocking:i.needsYouBlocking??!1,goalId:i.goalId,goalTitle:i.title,text:i.needsYou,todoId:`${i.goalId}:attention`},id:`attention:${i.goalId}`,kind:`attention`}),r.push({id:`run:${i.goalId}`,kind:`run`,run:{agentId:i.agentId,agentLabel:i.agentLabel??i.agentId,completedSteps:i.doneTodoCount??i.agentTodos.filter(e=>e.done).length,goalId:i.goalId,goalTitle:i.title,latestActivity:i.agentSentence,runId:`goal:${i.goalId}`,status:i.state===`推进中`?`running`:i.state===`需修复`?`failed`:`waiting`,title:i.nextSentence,totalSteps:Math.max((i.doneTodoCount??0)+i.agentTodos.filter(e=>!e.done).length,1)}}),i.agentTodos.filter(e=>e.taskClass===`continuous_monitor`).forEach(t=>{let a=e.timeline?.find(e=>e.kind===`run`&&e.run.goalId===i.goalId&&e.run.todoId===t.todoId&&!!e.run.sessionId);r.push({id:`schedule:${i.goalId}:${t.todoId}`,kind:`schedule`,schedule:{agentId:i.agentId,executionHistory:a?[{label:a.run.latestActivity||a.run.title,runId:a.run.runId,status:a.run.status===`waiting`||a.run.status===`queued`?`running`:a.run.status,timestamp:i.latestActivity||n(`common.recently`)}]:[],goalId:i.goalId,label:t.text,schedule:t.evidence??n(`schedule.summary`),scheduleId:t.todoId,scheduleKind:`monitor`,sessionId:a?.run.sessionId,status:t.done||t.status===`paused`?`paused`:`active`,stopCondition:n(`drawer.scheduleDefaultStop`),target:t.text,timezone:`Asia/Shanghai`}})});let a=e.timeline?.find(e=>e.kind===`proposal`&&e.proposal.actionKind===`heartbeat.bind`&&e.proposal.goalId===i.goalId);if(a){let e=e=>a.proposal.fields.find(t=>t.key===e)?.value;r.push({id:`schedule:${i.goalId}:heartbeat`,kind:`schedule`,schedule:{agentId:i.agentId,executionHistory:[],goalId:i.goalId,label:`${n(`schedule.heartbeat`)} · ${i.title}`,nextRunAt:n(`drawer.schedulePending`),notificationRule:n(`drawer.scheduleDefaultNotification`),schedule:e(`cadence`)??n(`schedule.summary`),scheduleId:`${i.goalId}:heartbeat`,scheduleKind:`heartbeat`,status:a.proposal.status===`applied`?`active`:`draft`,stopCondition:e(`stop_condition`)??n(`drawer.scheduleDefaultStop`),timezone:e(`timezone`)??`Asia/Shanghai`}})}return r}function $b(e){return e===`preview_ready`?`ready`:e===`cancelled`?`draft`:e===`failed`?`error`:e}function ex(e,t){let n={agent_id:t(`proposal.field.agentId`),cadence:t(`proposal.field.cadence`),completion_criteria:t(`proposal.field.completionCriteria`),execution_boundary:t(`proposal.field.executionBoundary`),goal_id:t(`proposal.field.goalId`),heartbeat:t(`proposal.field.heartbeat`),initial_todos:t(`proposal.field.initialTodos`),objective:t(`proposal.field.objective`),operation:t(`proposal.field.operation`),permission:t(`proposal.field.permission`),reason:t(`proposal.field.reason`),stop_condition:t(`proposal.field.stopCondition`),target:t(`proposal.field.target`),timezone:t(`proposal.field.timezone`),title:t(`proposal.field.title`),workspace_ref:t(`proposal.field.workspace`)},r=[`title`,`objective`,`completion_criteria`,`execution_boundary`,`permission`,`agent_id`,`workspace_ref`,`initial_todos`,`heartbeat`,`stop_condition`,`goal_id`];return Object.entries(e).sort(([e],[t])=>{let n=r.indexOf(e),i=r.indexOf(t);return(n<0?r.length:n)-(i<0?r.length:i)}).slice(0,10).map(([e,r])=>({key:e,label:n[e]??e.replaceAll(`_`,` `),value:e===`workspace_ref`?r===`current`?t(`proposal.workspace.current`):t(`proposal.workspace.named`,{workspace:String(r??`current`)}):Array.isArray(r)?r.join(` · `):typeof r==`object`&&r?JSON.stringify(r):String(r??`—`)}))}function tx(e){if(e.action_kind!==`goal.lifecycle`)return;let t=e.normalized_parameters.operation;return t===`stop`||t===`resume`||t===`delete`?t:void 0}function nx(e,t){let n=tx(e),r=typeof e.normalized_parameters.title==`string`?e.normalized_parameters.title:typeof e.normalized_parameters.goal_id==`string`?e.normalized_parameters.goal_id:``,i=typeof e.normalized_parameters.target==`string`?e.normalized_parameters.target:``,a=e.action_kind===`goal.create`?t(`proposal.summary.goalCreate`,{title:r}):e.action_kind===`heartbeat.bind`?t(`proposal.summary.heartbeat`):e.action_kind===`monitor.create`?t(`proposal.summary.monitor`,{target:i}):e.action_kind===`goal.lifecycle`&&n===`stop`?t(`proposal.summary.lifecycleStop`,{title:r}):e.action_kind===`goal.lifecycle`&&n===`delete`?t(`proposal.summary.lifecycleDelete`,{title:r}):e.action_kind===`goal.lifecycle`?t(`proposal.summary.lifecycleResume`,{title:r}):e.summary;return{actionKind:e.action_kind,fields:ex(e.normalized_parameters,t),goalId:typeof e.normalized_parameters.goal_id==`string`?e.normalized_parameters.goal_id:void 0,impact:e.action_kind===`goal.create`?t(`proposal.impact.goalCreate`):e.action_kind===`goal.lifecycle`&&n===`stop`?t(`proposal.impact.lifecycleStop`):e.action_kind===`goal.lifecycle`&&n===`delete`?t(`proposal.impact.lifecycleDelete`):e.action_kind===`goal.lifecycle`?t(`proposal.impact.lifecycleResume`):e.permission_classification===`protected`?t(`proposal.impact.protected`):t(`proposal.impact.default`),previewId:e.proposal_id,lifecycleOperation:n,gate:e.gate?{kind:String(e.gate.kind??`protected_action`),nextAction:typeof e.gate.next_action==`string`?e.gate.next_action:void 0,summary:String(e.gate.summary??t(`proposal.gate.default`))}:void 0,primaryLabel:e.action_kind===`goal.create`?t(`proposal.primary.goalCreate`):e.action_kind===`goal.lifecycle`&&n===`stop`?t(`proposal.primary.lifecycleStop`):e.action_kind===`goal.lifecycle`&&n===`delete`?t(`proposal.primary.lifecycleDelete`):e.action_kind===`goal.lifecycle`?t(`proposal.primary.lifecycleResume`):e.action_kind===`todo.create`&&e.normalized_parameters.start_execution===!0?t(`proposal.primary.todoStart`):t(`proposal.primary.apply`),status:$b(e.status),title:a}}function rx(e){let t=e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``).slice(0,42);if(t)return t;let n=2166136261;for(let t of e)n^=t.codePointAt(0)??0,n=Math.imul(n,16777619);return`goal-${(n>>>0).toString(36)}`}function ix(e,t){let n=e.match(/[「“"]([^」”"]{2,80})[」”"]/u)?.[1];return n?n.trim():e.replace(/^(请|帮我|我想|给我|创建|新建|设置|please|i want to|create|set up)+/iu,``).replace(/(一个|新的)?\s*(goal|目标)/giu,``).replace(/[,。!?].*$/u,``).trim().slice(0,80)||t(`goal.defaultTitle`)}function ax(e,t){for(let n of e.split(/\r?\n/u)){let e=n.trim();for(let n of t){let t=e.match(RegExp(`^${n.replace(/[.*+?^${}()|[\]\\]/gu,`\\$&`)}\\s*[::]\\s*(.*)$`,`iu`));if(t?.[1]?.trim())return t[1].trim()}}return``}function ox(e,t){let n=ax(e,[`目标`,`Objective`]),r=ax(e,[`完成标准`,`Completion criteria`]),i=ax(e,[`执行边界(可选)`,`执行边界`,`边界`,`Execution boundary (optional)`,`Execution boundary`,`Boundary`]),a=(n||ix(e,t)).split(/[。;;\n]/u)[0].trim().slice(0,80)||t(`goal.defaultTitle`),o=[n||a,r?t(`goal.objectiveCompletion`,{criteria:r}):``,i?t(`goal.objectiveBoundary`,{boundary:i}):``].filter(Boolean).join(` +`),s=/(只读|不调用外部工具|不修改(?:仓库|代码|状态)|read.?only|do not (?:call|use) external tools|do not modify (?:repositories|repository|code|state))/iu.test(i||e);return{completionCriteria:r,executionBoundary:i,initialTodos:r?[t(`goal.initialTodo`,{criteria:r})]:[],objective:o,permission:s?`read_only`:`workspace_write_on_confirmation`,title:a}}function sx(e){let t=e.match(/(?:每|every)\s*(\d{1,3})\s*(?:分钟|minutes?)/iu)?.[1];if(t)return`${t}m`;let n=e.match(/(?:每|every)\s*(\d{1,2})\s*(?:小时|hours?)/iu)?.[1];return n?`${n}h`:/每小时|every hour|hourly/iu.test(e)?`1h`:(/每天|每日|早上|上午|daily|every day/iu.test(e),`1d`)}function cx(e,t){return/(每周|星期|周[一二三四五六日天]|weekly|every\s+(?:mon|tues|wednes|thurs|fri|satur|sun)day|\d{1,2}\s*[::]\s*\d{2})/iu.test(e)?t(`schedule.unsupportedCalendar`):null}function lx(e,t){return ax(e,[`检查内容`,`监控内容`,`目标`,`Check target`,`Monitor target`,`Target`])||e.replace(/^(?:为当前 Goal |for the current Goal )?(?:添加|配置|创建|add|configure|create)?\s*(?:定时检查|监控|scheduled check|monitor)[::]?/iu,``).split(/\r?\n/u)[0].trim()||t(`schedule.defaultTarget`)}function ux(e){return/(mr|pr).{0,8}(合并|merge)/iu.test(e)?`pr_merged`:/发布完成|上线完成|release (?:is )?complete|deployment (?:is )?complete/iu.test(e)?`release_complete`:`goal_complete`}function dx(e,t){let n=e.toLowerCase();return t.find(e=>n.includes(e.agentId.toLowerCase())||n.includes(e.label.toLowerCase()))}function fx(e){let t=ax(e,[`标题`,`任务标题`,`Todo 标题`]),n=ax(e,[`内容`,`任务内容`,`Todo 内容`]);if(t)return[t,n].filter(Boolean).join(`:`).slice(0,400);let r=e.match(/[「“"]([^」”"]{2,200})[」”"]/u)?.[1];return r?r.trim():e.replace(/^(请|帮我|给我|为当前 Goal |新增|新建|创建|添加|加上|加一个|记一个)+/u,``).replace(/^(一个\s*)?(普通\s*)?(todo|待办|任务)(?:\s*到\s*Tasks?)?[::\s]*/iu,``).replace(/[。;;,,]\s*(?:不要|不需要|无需|禁止|别|暂不).{0,80}(?:heartbeat|心跳|定时|监控|执行).*$/iu,``).replace(/[,,]\s*(并且|然后|再)?\s*(交给|分配给|让).+$/u,``).replace(/\s*(交给|分配给|让)\s+.+$/u,``).trim().slice(0,400)||`推进当前 Goal 的下一项工作`}var px=new Set([`image/png`,`image/jpeg`,`image/webp`,`image/gif`]),mx=5242880,hx=4;function gx(e,t){return new Promise((n,r)=>{let i=new FileReader;i.onerror=()=>r(Error(t(`composer.imageReadError`,{name:e.name}))),i.onload=()=>n({dataUrl:String(i.result??``),id:crypto.randomUUID(),mimeType:e.type,name:e.name,size:e.size}),i.readAsDataURL(e)})}function _x({agents:e=[{agentId:`codex`,available:!0,capability:`代码与项目执行`,label:`Codex`}],callbacks:t={},goalArchiveLoadState:n={error:null,phase:`ready`},model:r,readOnly:i=!1,selectedAgentId:a,selectedGoalId:o,statusSourceControl:s}){let{locale:c,t:l}=Ji(),[u,d]=(0,R.useState)(o??null),[f,p]=(0,R.useState)(a??e.find(e=>e.available)?.agentId??`codex`),[m,h]=(0,R.useState)(null),[g,_]=(0,R.useState)(!1),[v,y]=(0,R.useState)(null),[b,x]=(0,R.useState)({}),[S,C]=(0,R.useState)(`chat`),[w,T]=(0,R.useState)(!1),[E,D]=(0,R.useState)(!1),[O,k]=(0,R.useState)(!1),[ee,A]=(0,R.useState)(()=>{try{let e=window.sessionStorage.getItem(`loopx-pw-composer-drafts`),t=e?JSON.parse(e):{};return t&&typeof t==`object`&&!Array.isArray(t)?t:{}}catch{return{}}}),[j,te]=(0,R.useState)(!1),[ne,re]=(0,R.useState)([]),[M,N]=(0,R.useState)(null),[ie,ae]=(0,R.useState)(null),[oe,P]=(0,R.useState)(()=>new Set),[F,I]=(0,R.useState)(()=>new Set),[se,ce]=(0,R.useState)(`idle`),[le,ue]=(0,R.useState)([]),[de,fe]=(0,R.useState)(!1),[pe,me]=(0,R.useState)(Hb),[he,ge]=(0,R.useState)({}),[_e,ve]=(0,R.useState)([]),ye=(0,R.useRef)(!1),be=(0,R.useRef)(NaN),xe=(0,R.useRef)(null),Se=(0,R.useRef)(null),Ce=(0,R.useRef)(null),we=(0,R.useRef)(new Set),Te=(0,R.useRef)(new Set),[Ee,De]=(0,R.useState)(null),L=o===void 0?u:o,Oe=a??f,ke=`${L??`manager`}:${Oe}`,Ae=ee[ke]??``;(0,R.useEffect)(()=>{re([]),N(null)},[ke]);function je(e,t){A(n=>{let r={...n};t?r[e]=t:delete r[e];try{window.sessionStorage.setItem(`loopx-pw-composer-drafts`,JSON.stringify(r))}catch{}return r})}function Me(e){je(ke,e)}function Ne(e){let t=ee[ke]?.trimEnd();Me(t?`${t}\n${e}`:e),window.requestAnimationFrame(()=>xe.current?.focus())}(0,R.useEffect)(()=>{let e=xe.current;e&&(e.style.height=`auto`,e.style.height=`${Math.min(e.scrollHeight,120)}px`)},[Ae]);let Pe=(0,R.useMemo)(()=>r.goals.map(e=>{let t=he[e.goalId];return t?{...e,repository:{branch:t.branch,identity:t.identity,label:t.label,readOnly:!0}}:e}),[he,r.goals]),Fe=(0,R.useMemo)(()=>Pe.filter(e=>ty(e)===`needs_you`).length,[Pe]),Ie=(0,R.useMemo)(()=>Pe.filter(e=>ty(e)===`needs_you`&&(e.needsYouBlocking||e.state===`等你`)).length,[Pe]),B=Pe.find(e=>e.goalId===L)??null,Le=m?.kind===`settings`,Re=L,V=(0,R.useMemo)(()=>{let e=Object.values(b).filter(e=>e.actionKind===`heartbeat.bind`&&e.goalId&&e.status===`applied`).map(e=>({id:`schedule:${e.goalId}:heartbeat`,kind:`schedule`,schedule:{agentId:Oe,executionHistory:[],goalId:e.goalId,label:e.title,nextRunAt:l(`drawer.schedulePending`),notificationRule:l(`drawer.scheduleDefaultNotification`),schedule:e.fields.find(e=>e.key===`cadence`)?.value??l(`schedule.summary`),scheduleId:`${e.goalId}:heartbeat`,scheduleKind:`heartbeat`,status:e.status===`applied`?`active`:`draft`,stopCondition:e.fields.find(e=>e.key===`stop_condition`)?.value??l(`drawer.scheduleDefaultStop`),timezone:e.fields.find(e=>e.key===`timezone`)?.value??`Asia/Shanghai`}})),t=[...Qb(r,Re,l),...r.timeline??[],...e,...Kb(Object.values(b)).filter(e=>e.actionKind!==`heartbeat.bind`||e.status!==`applied`).map(e=>({id:`proposal:${e.previewId}`,kind:`proposal`,proposal:e}))];return[...new Map(t.map(e=>[e.id,e])).values()].filter(e=>e.kind!==`proposal`||![`stale`,`error`].includes(e.proposal.status)||le.includes(e.proposal.previewId)).filter(e=>!L||e.kind===`message`?!0:e.kind===`proposal`?!e.proposal.goalId||e.proposal.goalId===L:e.kind===`attention`?e.attention.goalId===L:e.kind===`run`?e.run.goalId===L:e.kind===`schedule`?e.schedule.goalId===L:e.output.goalId===L)},[Re,r,b,Oe,L,le,l]),ze=(0,R.useMemo)(()=>v?V.filter(e=>e.kind===`message`?!0:e.kind===`run`?e.run.runId===v.runId:e.kind===`output`&&e.output.runId===v.runId):V,[v,V]);(0,R.useEffect)(()=>{if(!v)return;let e=V.find(e=>e.kind===`run`&&e.run.runId===v.runId);!e||e.kind!==`run`||JSON.stringify({completedSteps:v.completedSteps,latestActivity:v.latestActivity,messages:v.sessionMessages,sessionStatus:v.sessionStatus,status:v.status,totalSteps:v.totalSteps})!==JSON.stringify({completedSteps:e.run.completedSteps,latestActivity:e.run.latestActivity,messages:e.run.sessionMessages,sessionStatus:e.run.sessionStatus,status:e.run.status,totalSteps:e.run.totalSteps})&&y(e.run)},[v,V]);let Be=(0,R.useMemo)(()=>V.flatMap(e=>e.kind===`message`?[e.message]:[]),[V]),Ve=(0,R.useMemo)(()=>B?V.flatMap(e=>e.kind===`message`?[e.message]:[]):[],[V,B]);(0,R.useEffect)(()=>{B||w||Be.some(e=>e.pending)&&D(!0)},[w,Be,B]),(0,R.useEffect)(()=>{!B||S===`chat`||Ve.some(e=>e.pending)&&k(!0)},[Ve,B,S]);let He=(0,R.useMemo)(()=>V.filter(e=>e.kind===`message`||e.kind===`proposal`&&le.includes(e.proposal.previewId)),[V,le]),Ue=He[He.length-1],We=Ue?.kind===`message`?Ue.message.text.length:0;(0,R.useEffect)(()=>{if(!w||!Se.current)return;let e=window.requestAnimationFrame(()=>{Se.current&&(Se.current.scrollTop=Se.current.scrollHeight)});return()=>window.cancelAnimationFrame(e)},[He.length,w,We]);let Ge=(0,R.useMemo)(()=>{if(m?.kind===`settings`)return null;if(m?.kind===`goal`){let e=Pe.find(e=>e.goalId===m.item.goalId);return e?{item:e,kind:`goal`}:m}if(m?.kind!==`run`)return m;let e=V.find(e=>e.kind===`run`&&e.run.runId===m.item.runId);return e?{item:e.run,kind:`run`}:m},[V,m,Pe]);(0,R.useEffect)(()=>{if(i){ge({}),ve([]);return}let e=!1;return Promise.all([Eg(),Lg()]).then(([t,n])=>{e||(ge(Object.fromEntries(t.map(e=>[e.goal_id,e.repository]))),ve(n))}).catch(()=>{}),()=>{e=!0}},[i]),(0,R.useEffect)(()=>{if(!de)return;function e(e){e.key===`Escape`&&fe(!1)}return document.addEventListener(`keydown`,e),()=>document.removeEventListener(`keydown`,e)},[de]),(0,R.useEffect)(()=>{if(L||!V.length)return;if(!ye.current){ye.current=!0;try{be.current=Date.parse(window.localStorage.getItem(`loopx-pw-last-visit`)??``),window.localStorage.setItem(`loopx-pw-last-visit`,new Date().toISOString())}catch{be.current=NaN}}let e=be.current,t=V.filter(e=>e.kind===`run`).map(e=>e.run),n=t=>{let n=Date.parse(t??``);return!Number.isNaN(e)&&!Number.isNaN(n)&&n>e},r={attention:Fe,done:t.filter(e=>e.status===`completed`&&n(e.latestActivity)).length,failed:t.filter(e=>(e.status===`failed`||e.status===`interrupted`)&&n(e.latestActivity)).length};De(e=>e?.attention===r.attention&&e.done===r.done&&e.failed===r.failed?e:r)},[V,Fe,L]),(0,R.useEffect)(()=>{if(i){x({});return}let e=!1;return Ch(L?{goalId:L}:{contextKind:`manager`}).then(t=>{if(e)return;let n=Object.fromEntries(t.filter(e=>[`ready`,`gated`,`deferred`,`applying`].includes(e.status)).map(e=>{let t=nx(e,l);return[t.previewId,t]}));x(e=>({...e,...n}))}).catch(()=>{}),()=>{e=!0}},[i,L,l]);async function Ke(e,n={}){if(i)throw Error(l(`source.readOnlyWriteError`));let r;try{r=t.onPreviewAction?await t.onPreviewAction(e):nx(await xh(e),l)}catch(t){if(!(t instanceof _h)||t.payload.error_code!==`action_preview_gate`)throw t;let n=t.payload.gate&&typeof t.payload.gate==`object`?t.payload.gate:{},i=(Array.isArray(n.candidates)?n.candidates:[]).flatMap(e=>{if(!e||typeof e!=`object`)return[];let t=e;return typeof t.workspace_ref==`string`&&typeof t.label==`string`?[{label:t.label,workspaceRef:t.workspace_ref}]:[]}),a=String(n.kind??`workspace_selection_required`),o=a===`agent_binding_required`||a===`agent_identity_selection_required`;r={actionKind:e.actionKind,fields:i.map(e=>({key:`workspace_ref:${e.workspaceRef}`,label:e.label,value:e.workspaceRef})),gate:{kind:a,nextAction:typeof n.next_action==`string`?n.next_action:void 0,summary:String(n.summary??l(`proposal.workspaceGate.defaultSummary`))},impact:l(o?`proposal.workspaceGate.agentImpact`:`proposal.workspaceGate.selectionImpact`),previewId:`workspace-choice-${Date.now().toString(36)}`,sourceRequest:e,status:`gated`,title:l(o?`proposal.workspaceGate.agentTitle`:`proposal.workspaceGate.selectionTitle`),workspaceCandidates:i}}return ue(e=>e.includes(r.previewId)?e:[...e,r.previewId]),x(e=>({...e,[r.previewId]:r})),n.select!==!1&&h({item:r,kind:`proposal`}),r}function qe(){tt(null),je(`manager:${Oe}`,l(`composer.createGoalTemplate`)),window.requestAnimationFrame(()=>xe.current?.focus())}async function Je(e,n){let r={delete:`Deleted from the owner workspace`,resume:`Resumed from the owner workspace`,stop:`Stopped from the owner workspace`},i={delete:l(`proposal.summary.lifecycleDelete`,{title:e.title}),resume:l(`proposal.summary.lifecycleResume`,{title:e.title}),stop:l(`proposal.summary.lifecycleStop`,{title:e.title})},a=null,o=!1;try{if(n===`stop`){if(we.current.has(e.goalId))return;we.current.add(e.goalId),P(new Set(we.current)),h(null),a={goalId:e.goalId,next:`stopped`,optimisticApplied:!0,previous:e.activationState},ae(l(`feedback.applying`,{title:i.stop})),t.onGoalActivationStateChange?.(e.goalId,`stopped`)}let s=await Ke({actionKind:`goal.lifecycle`,context:{kind:`goal_directory`,goal_id:e.goalId},idempotencyKey:`workspace-goal-${n}-${e.goalId}-${Date.now().toString(36)}`,normalizedParameters:{goal_id:e.goalId,operation:n,reason:r[n]},summary:i[n]},{select:n!==`stop`});n===`stop`&&(s.status===`ready`?(o=!0,await Qe(s,{lifecycleProjection:a??void 0,presentation:`feedback`})):(a&&t.onGoalActivationStateChange?.(a.goalId,a.previous),ae(s.gate?l(`feedback.gateRequired`,{summary:s.gate.summary}):l(`feedback.notCompleted`,{status:s.status})),h({item:s,kind:`proposal`})))}catch(e){a&&!o&&t.onGoalActivationStateChange?.(a.goalId,a.previous),ae(l(`feedback.executionFailed`,{error:e instanceof Error?e.message:String(e)}))}finally{n===`stop`&&(we.current.delete(e.goalId),P(new Set(we.current)))}}function Ye(e,t){Me(l(t?e===`heartbeat`?`composer.heartbeatTemplate`:`composer.monitorTemplate`:e===`heartbeat`?`composer.heartbeatTemplateWithoutGoal`:`composer.monitorTemplateWithoutGoal`)),h(null),window.requestAnimationFrame(()=>xe.current?.focus())}async function Xe(e,n,r=``){let i=await t.onRequestScheduleConfig?.(e,n);if(i){ue(e=>e.includes(i.previewId)?e:[...e,i.previewId]),x(e=>({...e,[i.previewId]:i})),h({item:i,kind:`proposal`});return}if(!n){Me(l(e===`heartbeat`?`composer.heartbeatGoalQuestion`:`composer.monitorGoalQuestion`));return}let a=Date.now().toString(36);await Ke({actionKind:e===`heartbeat`?`heartbeat.bind`:`monitor.create`,context:{kind:`schedule`,goal_id:n},idempotencyKey:`workspace-${e}-${n}-${a}`,normalizedParameters:e===`heartbeat`?{agent_id:Oe,cadence:sx(r),goal_id:n,stop_condition:ux(r),timezone:`Asia/Shanghai`}:{agent_id:Oe,cadence:sx(r),goal_id:n,stop_condition:ux(r),target:lx(r,l),target_key:`goal-${n}`,timezone:`Asia/Shanghai`},summary:e===`heartbeat`?l(`proposal.summary.heartbeat`):l(`proposal.summary.monitor`,{target:lx(r,l)})})}async function Ze(e){if(!Te.current.has(e.todoId)){Te.current.add(e.todoId),I(new Set(Te.current)),ae(l(`feedback.preparingPreview`,{title:e.text}));try{await Ke({actionKind:`todo.update`,context:{goal_id:e.goalId,kind:`todo`,todo_id:e.todoId},idempotencyKey:`workspace-todo-${e.todoId}-complete-${Date.now().toString(36)}`,normalizedParameters:{goal_id:e.goalId,operation:`complete`,todo_id:e.todoId},summary:l(`tasks.markComplete`,{name:e.text})}),ae(null)}catch(e){ae(l(`feedback.previewFailed`,{error:e instanceof Error?e.message:String(e)}))}finally{Te.current.delete(e.todoId),I(new Set(Te.current))}}}async function Qe(e,n={}){let i=n.presentation!==`feedback`,a=e.actionKind===`goal.lifecycle`&&e.goalId&&(e.lifecycleOperation===`stop`||e.lifecycleOperation===`resume`)?{goalId:e.goalId,next:e.lifecycleOperation===`stop`?`stopped`:`active`,optimisticApplied:!1,previous:r.goals.find(t=>t.goalId===e.goalId)?.activationState??(e.lifecycleOperation===`stop`?`active`:`stopped`)}:null,o=n.lifecycleProjection??a;ae(l(`feedback.applying`,{title:e.title}));let s={...e,status:`applying`};x(t=>({...t,[e.previewId]:s})),i&&h({item:s,kind:`proposal`}),o&&!o.optimisticApplied&&t.onGoalActivationStateChange?.(o.goalId,o.next);try{if(t.onApplyProposal){await t.onApplyProposal(e);let n={...e,status:`applied`};if(x(t=>({...t,[e.previewId]:n})),i&&h({item:n,kind:`proposal`}),ae(l(`feedback.completed`,{title:e.title})),e.actionKind===`goal.lifecycle`){(e.lifecycleOperation===`stop`||e.lifecycleOperation===`delete`)&&tt(null),e.lifecycleOperation===`delete`&&e.goalId&&t.onGoalDeleted?.(e.goalId);let n=t.onReconcileStatus??t.onRefresh;Promise.resolve().then(()=>n?.()).catch(()=>void 0)}return}let n=await wh(e.previewId),r=nx(n.proposal,l);if(x(t=>({...t,[e.previewId]:r})),i&&h({item:r,kind:`proposal`}),n.proposal.status!==`applied`||n.proposal.receipt?.projection_verified!==!0){o&&t.onGoalActivationStateChange?.(o.goalId,o.previous),ae(n.proposal.status===`stale`?l(`feedback.stale`):l(`feedback.notCompleted`,{status:n.proposal.status}));return}if(ae(l(`feedback.completed`,{title:r.title})),r.actionKind===`todo.create`&&await t.onRefresh?.(),r.actionKind===`goal.lifecycle`&&(r.lifecycleOperation===`stop`||r.lifecycleOperation===`delete`)&&tt(null),r.actionKind===`goal.lifecycle`&&r.lifecycleOperation===`delete`&&r.goalId&&t.onGoalDeleted?.(r.goalId),r.actionKind===`goal.lifecycle`){let e=t.onReconcileStatus??t.onRefresh;Promise.resolve().then(()=>e?.()).catch(()=>void 0)}}catch(n){if(o&&t.onGoalActivationStateChange?.(o.goalId,o.previous),n instanceof _h&&n.payload.error_code===`protected_action`){let r=n.payload.gate,i=r&&typeof r==`object`?r:{},a={...e,gate:{kind:String(i.kind??`protected_action`),nextAction:typeof i.next_action==`string`?i.next_action:void 0,summary:String(i.summary??n.message)},status:`gated`};x(t=>({...t,[e.previewId]:a})),h({item:a,kind:`proposal`}),ae(l(`feedback.gateRequired`,{summary:a.gate.summary})),e.actionKind===`goal.create`&&e.goalId&&(t.onRefresh?.(),tt(e.goalId));return}let r=n instanceof Error&&/stale|状态.*变化|conflict/i.test(n.message),a={...e,errorMessage:n instanceof Error?n.message:String(n),status:r?`stale`:`error`};x(t=>({...t,[e.previewId]:a})),i&&h({item:a,kind:`proposal`}),ae(l(`feedback.executionFailed`,{error:a.errorMessage}))}}let $e={...t,onOpenRunSession:async e=>{e.goalId!==L&&tt(e.goalId),C(`chat`),await t.onOpenRunSession?.(e),y(e),h(null)},onOpenGoal:e=>{tt(e);let n=t.onReconcileStatus??t.onRefresh;Promise.resolve().then(()=>n?.()).catch(()=>{ae(l(`feedback.goalRefreshFailed`))})},onOpenGoalView:e=>{C(e),e===`chat`&&y(null),h(null)},onOpenOutput:e=>{e.goalId!==L&&tt(e.goalId),C(`files`),t.onOpenOutput?.(e)},onApplyProposal:Qe,onCancelProposal:async e=>{h(null),x(t=>{let n={...t};return delete n[e.previewId],n});try{t.onCancelProposal?.(e),t.onCancelProposal||await Th(e.previewId)}catch(t){x(t=>({...t,[e.previewId]:e})),ae(l(`feedback.cancelFailed`,{error:t instanceof Error?t.message:String(t)}))}},onTransitionProposal:async(e,t)=>{let n=nx(await Eh(e.previewId,t),l);ue(e=>e.includes(n.previewId)?e:[...e,n.previewId]),x(r=>{let i={...r};return t===`regenerate`&&delete i[e.previewId],i[n.previewId]=n,i}),h({item:n,kind:`proposal`})},onSelectWorkspaceCandidate:async(e,t)=>{e.sourceRequest&&(x(t=>{let n={...t};return delete n[e.previewId],n}),await Ke({...e.sourceRequest,idempotencyKey:`${e.sourceRequest.idempotencyKey}-${t}`,normalizedParameters:{...e.sourceRequest.normalizedParameters,workspace_ref:t}}))},onPreviewAction:Ke,onRequestScheduleConfig:(e,t)=>Ye(e,t),onOpenNotificationSettings:e=>h({goalId:e,kind:`settings`,tab:`lark`}),onFetchNotificationTargets:()=>Yh(),onSetupGoalChannel:e=>Zh(e),onToggleGoalAutoNotify:e=>Qh(e),onUpdateSchedule:async(e,t)=>{let n=Date.now().toString(36),r=e.scheduleKind===`heartbeat`;await Ke({actionKind:r?`heartbeat.bind`:`monitor.update`,context:{kind:`schedule`,goal_id:e.goalId},idempotencyKey:`workspace-monitor-${e.scheduleId}-${t}-${n}`,normalizedParameters:{agent_id:e.agentId??Oe,...!r&&t===`run_now`?{endpoint_id:Oe}:{},...t===`edit`?{cadence:`2h`,...r?{timezone:e.timezone??`Asia/Shanghai`}:{}}:{},goal_id:e.goalId,operation:t,...!r&&t===`run_now`&&e.sessionId?{session_id:e.sessionId}:{},...r?{}:{todo_id:e.scheduleId}},summary:t===`pause`?`暂停自动运行:${e.label}`:t===`resume`?`恢复自动运行:${e.label}`:t===`run_now`?`立即运行:${e.label}`:t===`stop`?`停止自动运行:${e.label}`:`编辑自动运行生命周期:${e.label}`})}},et=i?{onOpenGoal:$e.onOpenGoal,onOpenGoalView:$e.onOpenGoalView,onOpenOutput:$e.onOpenOutput}:$e;function tt(e){d(e),T(!1),D(!1),k(!1),y(null),h(null),C(`tasks`),fe(!1),t.onSelectGoal?.(e)}function nt(e){p(e),t.onSelectAgent?.(e)}function rt(e){me(e),Ub(e)}async function it(n){let r=n?[]:ne,i=(n??Ae).trim()||(r.length?l(`composer.imageAnalysisPrompt`):``);if(!(!i||j)){n||(Me(``),re([])),N(null),te(!0);try{if(r.length){L?S!==`chat`&&k(!0):D(!0);let e=await t.onSendMessage?.(i,Oe,L,r);e&&await Ke(e);return}let n=Dy(i,{agents:e.map(e=>({agentId:e.agentId,label:e.label})),goalId:L,todos:(B?.agentTodos??[]).map(e=>({text:e.text,todoId:e.todoId}))});if(n.route===`clarify`){Me(i);let e=l(`composer.clarifySingleAction`);n.missingFields.includes(`resume_when`)&&(e=l(`composer.clarifyDefer`)),ae(e);return}if(n.actionKind===`goal.create`){let e=ox(i,l),t=rx(e.title);await Ke({actionKind:`goal.create`,context:{kind:`manager`,goal_id:null,natural_language:i},idempotencyKey:`workspace-goal-intent-${t}-${Date.now().toString(36)}`,normalizedParameters:{agent_id:Oe,completion_criteria:e.completionCriteria,execution_boundary:e.executionBoundary,goal_id:t,heartbeat:{cadence:sx(i),enabled:n.normalizedParameters.heartbeat_enabled===!0,timezone:`Asia/Shanghai`},initial_todos:e.initialTodos,objective:e.objective,permission:e.permission,stop_condition:ux(i),title:e.title,workspace_ref:`current`},summary:l(`proposal.summary.goalCreate`,{title:e.title})});return}if(L&&n.actionKind===`heartbeat.bind`){await Xe(`heartbeat`,L,i);return}if(L&&n.actionKind===`monitor.create`){let e=cx(i,l);if(e){Me(i),ae(e);return}await Xe(`monitor`,L,i);return}let a=dx(i,e);if(L&&a&&n.actionKind===`agent.bind`){await Ke({actionKind:`agent.bind`,context:{kind:`goal`,goal_id:L,natural_language:i},idempotencyKey:`workspace-agent-bind-${L}-${a.agentId}-${Date.now().toString(36)}`,normalizedParameters:{agent_id:a.agentId,goal_id:L},summary:`将 ${a.label} 绑定到 ${B?.title??L}`});return}if(L&&n.actionKind===`todo.create`){if(n.normalizedParameters.start_execution===!0){await Ke({actionKind:`todo.create`,context:{kind:`goal`,goal_id:L,natural_language:i},idempotencyKey:`workspace-task-start-${L}-${Date.now().toString(36)}`,normalizedParameters:{endpoint_id:a?.agentId??Oe,goal_id:L,start_execution:!0,text:i},summary:`交给 Agent 执行:${i.slice(0,120)}`});return}let e=a?.agentId??(/(交给|分配给|让).{0,24}(agent|codex|claude|kiro|kimi)/iu.test(i)?Oe:null);await Ke({actionKind:`todo.create`,context:{kind:`goal`,goal_id:L,natural_language:i},idempotencyKey:`workspace-todo-create-${L}-${Date.now().toString(36)}`,normalizedParameters:{...e?{endpoint_id:e}:{},goal_id:L,text:fx(i)},summary:`创建 Todo:${fx(i)}`});return}let o=B?.agentTodos.find(e=>i.includes(e.todoId)||i.includes(e.text)),s=typeof n.normalizedParameters.operation==`string`?n.normalizedParameters.operation:null;if(L&&o&&n.actionKind===`todo.update`&&s){await Ke({actionKind:`todo.update`,context:{kind:`todo`,goal_id:L,todo_id:o.todoId,natural_language:i},idempotencyKey:`workspace-todo-update-${o.todoId}-${s}-${Date.now().toString(36)}`,normalizedParameters:{agent_id:Oe,...s===`reassign`&&a?{endpoint_id:a.agentId}:{},...s===`block`?{note:i}:{},...s===`defer`&&typeof n.normalizedParameters.resume_when==`string`?{resume_when:n.normalizedParameters.resume_when}:{},goal_id:L,operation:s,todo_id:o.todoId},summary:`更新 Todo:${o.text}`});return}L?S!==`chat`&&k(!0):D(!0);let c=await t.onSendMessage?.(i,Oe,L);c&&await Ke(c)}catch(e){n||(Me(i),re(r));let t=e instanceof Error?e.message:l(`feedback.sendGenericError`);ae(l(`feedback.sendFailed`,{error:t}))}finally{te(!1)}}}let at=e.find(e=>e.agentId===Oe)?.label??Oe,ot=!B&&Ae.startsWith(l(`composer.createGoalDraftLead`)),st=V.filter(e=>e.kind===`run`&&!!e.run.sessionId&&!!e.run.canInterrupt&&(e.run.status===`running`||e.run.status===`queued`)).length;async function ct(e){if(!e?.length)return;let t=hx-ne.length,n=Array.from(e).slice(0,Math.max(0,t)),r=n.find(e=>!px.has(e.type)),i=n.find(e=>e.size>mx);if(t<=0){N(l(`composer.imageCountError`,{count:hx}));return}if(r){N(l(`composer.imageTypeError`));return}if(i){N(l(`composer.imageSizeError`,{size:mx/1024/1024}));return}try{let t=await Promise.all(n.map(e=>gx(e,l)));re(e=>[...e,...t].slice(0,hx)),N(e.length>n.length?l(`composer.imageCountError`,{count:hx}):null)}catch(e){N(e instanceof Error?e.message:l(`composer.imageReadGenericError`))}finally{Ce.current&&(Ce.current.value=``)}}function lt(e){let t=Array.from(e.clipboardData.items).filter(e=>e.kind===`file`&&e.type.startsWith(`image/`)).flatMap(e=>{let t=e.getAsFile();return t?[t]:[]});t.length&&(e.preventDefault(),ct(t))}async function ut(){let e=await Lg();ve(e)}async function dt(){await Promise.all([ut(),t.onRefresh?.()])}async function ft(){if(!(!t.onRefresh||se===`loading`)){ce(`loading`);try{await t.onRefresh(),ce(`done`)}catch{ce(`error`)}window.setTimeout(()=>ce(`idle`),1800)}}return Le?(0,z.jsx)(zb,{focusGoalConnection:!!(m?.kind===`settings`&&m.goalId),goals:Pe,initialGoalId:m?.kind===`settings`?m.goalId??L:L,initialTab:m?.kind===`settings`?m.tab??`lark`:`lark`,onChanged:()=>void dt(),onClose:()=>h(null),onThemeChange:rt,theme:pe}):(0,z.jsx)(Wb,{drawer:Ge?(0,z.jsx)(Fy,{agents:e,callbacks:et,goalNotifications:r.goalNotifications??[],goals:Pe,inspectorExpanded:g,larkConnections:i?[]:_e,onClose:()=>{Ge.kind===`proposal`&&[`applied`,`rejected`].includes(Ge.item.status)&&(Ge.item.actionKind!==`heartbeat.bind`||Ge.item.status!==`applied`)&&x(e=>{let t={...e};return delete t[Ge.item.previewId],t}),_(!1),h(null)},onToggleInspectorSize:()=>_(e=>!e),readOnly:i,runs:V.flatMap(e=>e.kind===`run`?[e.run]:[]),selection:Ge}):null,drawerMode:Ge?.kind===`todo`?g?`inspector-full`:`inspector`:`panel`,drawerOpen:Ge!==null,mobileSidebarOpen:de,onCloseMobileSidebar:()=>fe(!1),theme:pe,main:(0,z.jsxs)(`div`,{className:`personal-channel`,children:[(0,z.jsx)(ly,{agents:e,managerChatOpen:w,mobileNavigationOpen:de,onOpenGoalCapabilities:B?()=>h({goalId:B.goalId,kind:`settings`,tab:`capabilities`}):void 0,onOpenGoalDetail:B&&!B.loadState?()=>h({item:B,kind:`goal`}):void 0,onRefresh:t.onRefresh?()=>void ft():void 0,onOpenNavigation:()=>fe(!0),onOpenManagerChat:()=>{D(!1),T(!0)},onSelectGoalTab:e=>{C(e),e===`chat`&&(y(null),k(!1))},onSelectAgent:nt,onReturnManagerHome:()=>{T(!1),D(!1),window.requestAnimationFrame(()=>Se.current?.scrollTo({behavior:`smooth`,top:0}))},selectedAgentId:Oe,refreshState:se,readOnlySourceLabel:i?s?.activeSource.label:void 0,selectedGoal:B,selectedGoalTab:S}),(0,z.jsxs)(`div`,{className:`personal-channel-scroll`,ref:Se,children:[!B&&!w&&Ee&&Ee.done+Ee.failed+Ee.attention>0?(0,z.jsxs)(`section`,{className:`personal-digest-card`,"aria-label":l(`digest.away`),children:[(0,z.jsx)(`strong`,{children:l(`digest.away`)}),(0,z.jsxs)(`div`,{className:`personal-digest-stats`,children:[(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`b`,{children:Ee.done}),l(`digest.completed`)]}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`b`,{children:Ee.failed}),l(`digest.failed`)]}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`b`,{children:Ee.attention}),l(`digest.needsYou`)]})]})]}):null,!B&&!w?(0,z.jsxs)(`section`,{className:`personal-manager-greeting`,children:[(0,z.jsx)(`span`,{children:(0,z.jsx)(Up,{size:20})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:l(`home.greeting`)}),(0,z.jsx)(`p`,{children:r.goals.some(e=>e.activationState===`active`&&e.loadState)?l(`startup.partial`):(0,z.jsxs)(z.Fragment,{children:[l(`home.waitingCount`,{count:Fe}),` `,l(`home.blockingSummary`,{count:Ie})]})})]})]}):null,B?.loadState?(0,z.jsx)(`section`,{className:`personal-manager-greeting`,role:`status`,"data-testid":`goal-status-loading`,children:(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:l(B.loadState===`error`?`startup.goalError`:`startup.goalLoading`)}),(0,z.jsx)(`p`,{children:l(B.loadError?`startup.error.${B.loadError}`:`startup.independent`)}),B.loadState===`error`?(0,z.jsx)(`button`,{className:`min-h-11 rounded-md border px-3 py-2 text-sm`,type:`button`,onClick:()=>void t.onRefresh?.(),children:l(`startup.retry`)}):null]})}):B&&S===`tasks`?(0,z.jsx)(ib,{historyEnabled:!i,goal:B,items:V,onDraftTaskFromMessage:i?void 0:e=>{Me(`创建一个 Task:${Gb(e)}`),ae(l(`feedback.taskDraftCreated`)),window.requestAnimationFrame(()=>xe.current?.focus())},onOpenChat:()=>C(`chat`),onQuickComplete:i?void 0:Ze,onSelect:h,quickCompletingTodoIds:F,selectedTodoId:Ge?.kind===`todo`?Ge.item.todoId:null,userTodos:r.userTodos}):B&&S===`files`?(0,z.jsx)(Yb,{items:V.filter(e=>e.kind===`output`),onSelect:h,reportState:r.periodicReports}):!B&&!w?(0,z.jsx)(Jb,{goals:Pe,onRetry:()=>void t.onRefresh?.(),onSelectGoal:tt,systemHealth:r.systemHealth}):B?(0,z.jsxs)(z.Fragment,{children:[B&&v?.goalId===B.goalId?(0,z.jsx)(Zb,{onClose:()=>y(null),onOpenDetails:()=>h({item:v,kind:`run`}),run:v}):null,(0,z.jsx)(xy,{items:ze,onSelect:h,selectedGoal:B})]}):(0,z.jsx)(xy,{items:He,onSelect:h,selectedGoal:null})]}),(0,z.jsx)(`div`,{className:`personal-composer-wrap`,children:i?(0,z.jsxs)(`div`,{className:`personal-read-only-notice`,children:[(0,z.jsx)(`strong`,{children:l(`source.readOnlyNoticeTitle`)}),(0,z.jsx)(`span`,{children:l(`source.readOnlyNoticeDescription`)})]}):(0,z.jsxs)(z.Fragment,{children:[!B&&!w&&E&&Be.length?(0,z.jsx)(Xb,{messages:Be,onClose:()=>D(!1),onOpenConversation:()=>{D(!1),T(!0)}}):null,B&&S!==`chat`&&O&&Ve.length?(0,z.jsx)(Xb,{agentLabel:at,messages:Ve,onClose:()=>k(!1),onDraftTask:S===`tasks`?e=>{Me(`创建一个 Task:${Gb(e)}`),ae(l(`feedback.taskDraftCreated`)),window.requestAnimationFrame(()=>xe.current?.focus())}:void 0,onOpenConversation:()=>{k(!1),C(`chat`)},title:`${B.title} · ${at}`}):null,ie?(0,z.jsxs)(`div`,{className:`personal-action-feedback`,role:`status`,children:[(0,z.jsx)(`span`,{children:ie}),(0,z.jsx)(`button`,{"aria-label":l(`common.closeActionReceipt`),onClick:()=>ae(null),type:`button`,children:(0,z.jsx)(Gm,{size:14})})]}):null,(0,z.jsx)(`p`,{className:`personal-composer-hint`,children:B?st>0?l(`composer.goalRunningHint`,{agent:at,count:st}):l(`composer.goalMessageHint`,{agent:at}):l(`composer.managerMessageHint`)}),B?(0,z.jsxs)(`div`,{className:`personal-quick-prompts`,children:[(0,z.jsxs)(`button`,{"aria-label":l(`composer.nextAction`),className:`is-draft`,onClick:()=>Ne(l(`composer.nextActionPrompt`)),title:l(`composer.prepareDraft`),type:`button`,children:[(0,z.jsx)(vm,{size:13}),(0,z.jsx)(`span`,{children:l(`composer.nextAction`)}),(0,z.jsx)(`small`,{className:`personal-prompt-subtle`,children:l(`composer.draft`)})]}),(0,z.jsxs)(`button`,{className:`is-immediate`,disabled:j,onClick:()=>void it(l(`composer.agentProgressPrompt`)),title:l(`composer.immediate`),type:`button`,children:[(0,z.jsx)(Mm,{size:13}),(0,z.jsx)(`span`,{children:l(`composer.agentProgress`)}),(0,z.jsx)(`em`,{className:`personal-prompt-badge`,children:l(`composer.immediate`)})]}),(0,z.jsxs)(`button`,{"aria-label":l(`composer.monitor`),className:`is-draft`,onClick:()=>Ye(`monitor`,L),title:l(`composer.monitorHint`),type:`button`,children:[(0,z.jsx)(Gp,{size:13}),(0,z.jsx)(`span`,{children:l(`composer.monitor`)}),(0,z.jsx)(`small`,{className:`personal-prompt-subtle`,children:l(`composer.draft`)})]})]}):(0,z.jsxs)(`div`,{className:`personal-quick-prompts`,children:[(0,z.jsxs)(`button`,{"aria-label":l(`composer.globalTasks`),className:`is-draft`,onClick:()=>Ne(l(`composer.globalTasksPrompt`)),title:l(`composer.prepareDraft`),type:`button`,children:[(0,z.jsx)(vm,{size:13}),(0,z.jsx)(`span`,{children:l(`composer.globalTasks`)}),(0,z.jsx)(`small`,{className:`personal-prompt-subtle`,children:l(`composer.draft`)})]}),(0,z.jsxs)(`button`,{className:`is-immediate`,disabled:j,onClick:()=>void it(l(`composer.globalProgressPrompt`)),title:l(`composer.immediate`),type:`button`,children:[(0,z.jsx)(Mm,{size:13}),(0,z.jsx)(`span`,{children:l(`composer.globalProgress`)}),(0,z.jsx)(`em`,{className:`personal-prompt-badge`,children:l(`composer.immediate`)})]}),(0,z.jsxs)(`button`,{"aria-label":l(`composer.createGoal`),className:`is-draft`,onClick:qe,title:l(`composer.createGoalHint`),type:`button`,children:[(0,z.jsx)(Em,{size:13}),(0,z.jsx)(`span`,{children:l(`composer.createGoal`)}),(0,z.jsx)(`small`,{className:`personal-prompt-subtle`,children:l(`composer.draft`)})]})]}),ot?(0,z.jsxs)(`div`,{className:`personal-goal-draft-status`,role:`status`,children:[(0,z.jsx)(`strong`,{children:l(`composer.createGoalDraft`)}),(0,z.jsx)(`span`,{children:l(`composer.createGoalDraftDescription`)})]}):null,ne.length?(0,z.jsx)(`div`,{className:`personal-composer-images`,"aria-label":l(`composer.imagesPending`),children:ne.map(e=>(0,z.jsxs)(`figure`,{children:[(0,z.jsx)(`img`,{alt:e.name,src:e.dataUrl}),(0,z.jsx)(`button`,{"aria-label":l(`composer.sentImageAlt`,{name:e.name}),onClick:()=>re(t=>t.filter(t=>t.id!==e.id)),type:`button`,children:(0,z.jsx)(Gm,{size:13})})]},e.id))}):null,M?(0,z.jsx)(`p`,{className:`personal-composer-error`,role:`alert`,children:M}):null,(0,z.jsxs)(`div`,{className:`personal-channel-composer`,onDragOver:e=>{[...e.dataTransfer.items].some(e=>e.kind===`file`&&e.type.startsWith(`image/`))&&e.preventDefault()},onDrop:e=>{let t=[...e.dataTransfer.files].filter(e=>e.type.startsWith(`image/`));t.length&&(e.preventDefault(),ct(t))},children:[(0,z.jsxs)(`span`,{children:[(0,z.jsx)(Up,{size:17}),e.find(e=>e.agentId===Oe)?.label??Oe]}),(0,z.jsx)(`button`,{"aria-label":l(`composer.addImage`),className:`personal-composer-attach`,disabled:j||ne.length>=hx,onClick:()=>Ce.current?.click(),title:l(`composer.attachImageHint`),type:`button`,children:(0,z.jsx)(Cm,{size:17})}),(0,z.jsx)(`input`,{accept:`image/png,image/jpeg,image/webp,image/gif`,"aria-label":l(`composer.imagePicker`),className:`personal-composer-file-input`,disabled:j||ne.length>=hx,multiple:!0,onChange:e=>void ct(e.target.files),ref:Ce,type:`file`}),(0,z.jsx)(`textarea`,{"aria-label":l(`composer.sendMessage`),onChange:e=>Me(e.target.value),onKeyDown:e=>{e.key===`Enter`&&!e.shiftKey&&!e.nativeEvent.isComposing&&(e.preventDefault(),it())},onPaste:lt,placeholder:B?l(`composer.goalPlaceholder`,{goal:B.title}):l(`composer.managerPlaceholder`),ref:xe,rows:1,value:Ae}),(0,z.jsx)(`button`,{"aria-label":l(ot?`composer.createGoal`:`composer.send`),disabled:!Ae.trim()&&ne.length===0||j,onClick:()=>void it(),title:l(ot?`composer.createGoalHint`:`composer.sendMessageHint`),type:`button`,children:(0,z.jsx)(Mm,{size:18})})]})]})})]}),sidebar:(0,z.jsx)(eb,{attentionCount:Fe,goals:Pe,goalArchiveLoadState:n,lifecycleBusyGoalIds:oe,onRequestGoalCreate:i?void 0:qe,onRequestGoalLifecycle:i?void 0:(e,t)=>void Je(e,t),onRetryGoalArchive:t.onRetryGoalArchive||t.onRefresh?()=>void(t.onRetryGoalArchive??t.onRefresh)?.():void 0,onOpenSettings:i?void 0:()=>h({kind:`settings`}),onSelectGoal:tt,selectedGoalId:L,statusSourceControl:s},s?.activeSource.statusUrl??`/status.json`)})}function vx(e){return(e??``).replace(/\s+/gu,` `).trim()}function yx(e,t=120){let n=Array.from(e);return n.length<=t?e:`${n.slice(0,t-1).join(``)}…`}function bx(e,t,n){let r=vx(e);return!r||r===`暂无`?n?t(n):``:/refresh-state|latest_run|latest run-derived/iu.test(r)?t(`projection.refreshState`):/first read-only adapter tick|read-only adapter/iu.test(r)?t(`projection.firstReadOnlyAdapterCheck`):/todo update recorded for/iu.test(r)?t(`projection.todoStatusUpdated`):/^(loopx|python3|npm|git|run)\s|\s--[a-z0-9-]+|\b[a-z]+_[a-z_]+\b/iu.test(r)?t(n??`projection.agentPreparingNextStep`):yx(r)}function xx(e,t){return t({advancing:`projection.agentAdvancingGoal`,idle:`projection.agentIdle`,needs_you:`projection.agentNeedsDecision`,stopped:`projection.agentStopped`,waiting_external:`projection.agentWaitingExternal`}[e])}function Sx({eventCount:e,hasArtifact:t,hasLatestValidation:n},r){return{label:r(n?`projection.latestValidation`:`projection.latestRun`),metadata:e>0?r(`projection.events24h`,{count:e}):r(t?`projection.runEvidenceAvailable`:`projection.publicSafeProjection`)}}var Cx=`/status.json`,wx=`loopx-status-source-catalog-v1`,Tx={id:`local`,kind:`local`,label:`本机`,readOnly:!1,statusUrl:Cx};function Ex(e,t){let n=Xm(e,t).source;if(!n||!n.isLoopback||n.isRelative)return{error:`SSH 隧道来源必须使用显式的 localhost、127.0.0.1 或 ::1 URL。`};let r=new URL(n.url,t);return[`http:`,`https:`].includes(r.protocol)?{url:r.toString()}:{error:`状态来源只支持 HTTP 或 HTTPS。`}}function Dx(e){let t=2166136261;for(let n of e)t^=n.codePointAt(0)??0,t=Math.imul(t,16777619);return`ssh-${(t>>>0).toString(36)}`}function Ox(e,t){if(!e||typeof e!=`object`||Array.isArray(e))return null;let n=e;if(n.kind!==`ssh_tunnel`||typeof n.label!=`string`||typeof n.statusUrl!=`string`)return null;let r=n.label.trim(),i=Ex(n.statusUrl,t);return!r||r.length>48||!(`url`in i)?null:{id:Dx(i.url),kind:`ssh_tunnel`,label:r,readOnly:!0,statusUrl:i.url}}function kx(){return{schemaVersion:1,sources:[Tx]}}function Ax(e,t){try{let n=e.getItem(wx);if(!n)return kx();let r=JSON.parse(n);if(r.schemaVersion!==1||!Array.isArray(r.sources))return kx();let i=new Set([Tx.statusUrl]);return{schemaVersion:1,sources:[Tx,...r.sources.flatMap(e=>{let n=Ox(e,t);return!n||i.has(n.statusUrl)?[]:(i.add(n.statusUrl),[n])})]}}catch{return kx()}}function jx(e,t){e.setItem(wx,JSON.stringify({schemaVersion:1,sources:t.sources.filter(e=>e.kind===`ssh_tunnel`)}))}function Mx(e,t,n){let r=t.label.trim();if(!r)return{error:`请填写来源名称。`};if(r.length>48)return{error:`来源名称不能超过 48 个字符。`};let i=Ex(t.statusUrl,n);if(!(`url`in i))return i;if(e.sources.some(e=>e.statusUrl===i.url))return{error:`这个状态 URL 已经在来源目录中。`};let a={id:Dx(i.url),kind:`ssh_tunnel`,label:r,readOnly:!0,statusUrl:i.url};return{catalog:{...e,sources:[...e.sources,a]},source:a}}function Nx(e,t){return{...e,sources:e.sources.filter(e=>e.kind===`local`||e.id!==t)}}function Px(e,t,n){if(!t.trim()||Xm(t,n).source?.isRelative)return Tx;let r=t.trim();try{r=new URL(r,n).toString()}catch{return null}return e.sources.find(e=>e.statusUrl===r)??null}function Fx(e,t,n){return Px(e,t,n)||(Xm(t,n).source?.isRelative?Tx:{id:`temporary`,kind:`ssh_tunnel`,label:`临时来源`,readOnly:!0,statusUrl:t.trim()})}function Ix(e,t,n,r){return Fx(e,t??n,r)}var Lx={delete:`删除`,deploy:`部署`,merge:`合并`,payment:`付款`,release:`发布`};function Rx(e,t,n){let r=t.replace(/\s+/gu,` `).trim().toLowerCase(),i=n.target.replace(/\s+/gu,` `).trim().toLowerCase();return!i||!r.includes(i)?null:{actionKind:`goal.update`,context:{goal_id:e,kind:`goal`,natural_language:t,semantic_proposal:{operation:n.operation,target:n.target}},idempotencyKey:`workspace-semantic-protected-${e}-${Date.now().toString(36)}`,normalizedParameters:{goal_id:e,status:`operator_gate_requested`},summary:`请求受保护操作:${Lx[n.operation]} · ${n.target}`}}var zx=Cx;async function Bx(e){let t=await fetch(e,{cache:`no-store`,signal:AbortSignal.timeout(3e4)});if(!t.ok)throw Error(`HTTP ${t.status} while loading ${e}`);return vp(await t.json())}function Vx(e,t){if(t?.controller_readiness?.decision_advisor_ready||t?.controller_readiness?.write_controller_ready)return`controller_ready`;if(t?.controller_readiness)return`controller_gated`;if(t?.human_reward)return`reward_judged`;if(t?.operator_gate?.decision===`approve`)return`operator_approved`;if(t?.operator_gate)return`operator_gated`;let n=e||t?.classification||``;return n===`connected_without_run`?`connected`:n===`read_only_project_map`||t?.project_map?`mapped`:n===`state_refreshed`?`refreshed`:n&&n!==`no_status`?`adapter_inspected`:`registered`}function Hx(e,t){let n=new Map(t.map(e=>[e.goal_id,e])),r=new Set,i=e.map(e=>{r.add(e.id);let t=n.get(e.id),i=e.latest_runs[0],a=t?.lifecycle_phase??e.lifecycle_phase??i?.lifecycle_phase??Vx(t?.status??i?.classification??e.status,i),o=t?.lifecycle_flags?.length?t.lifecycle_flags:e.lifecycle_flags?.length?e.lifecycle_flags:i?.lifecycle_flags?.length?i.lifecycle_flags:[a];return{goal:e,queueItem:t,latestRun:i,status:t?.status??i?.classification??e.status??`no_status`,waitingOn:t?.waiting_on??`clear`,severity:t?.severity??`clear`,lifecyclePhase:a,lifecycleFlags:o}});for(let e of t)r.has(e.goal_id)||i.push({goal:{activation_state:e.activation_state,id:e.goal_id,status:e.status,display_name:e.goal_id,latest_runs:[],lifecycle_flags:[e.lifecycle_phase??`registered`],registry_member:!0,legacy_runtime_goal:!1,index_exists:!1,raw_index_records:0,unique_runs:0},queueItem:e,status:e.status,waitingOn:e.waiting_on,severity:e.severity,lifecyclePhase:e.lifecycle_phase??`registered`,lifecycleFlags:e.lifecycle_flags??[`registered`]});return i}function Ux(e){return(e??``).replace(/\s+/g,` `).trim()}function Wx(e,t=132){let n=Ux(e);return n.length<=t?n:`${n.slice(0,Math.max(0,t-1))}…`}function Gx(e){let t=new Map;for(let n of e?.goals??[])t.set(n.goal_id,n);return t}function Kx(e,t){return e===void 0||t===void 0?void 0:e+t}function qx(e,t){if(!e)return null;let n=t===`user`?e.queueItem?.project_asset?.user_todos:e.queueItem?.project_asset?.agent_todos;if(n?.items?.length)return{done_count:n.done??n.items.filter(e=>e.done).length,items:n.items,open_count:n.open??n.items.filter(e=>!e.done).length,total_count:n.total??n.items.length};let r=t===`user`?e.queueItem?.user_todos:e.queueItem?.agent_todos;return r?.items?.length?r:null}function Jx(e){return e?.items.find(e=>!e.done)}function Yx(e,t,n=`todos`){return e?.items?.length?{advancement_done_count:e.advancement_done_count??t?.advancement_done_count,done_count:e.done??e.items.filter(e=>e.done).length,items:e.items,open_count:e.open??e.items.filter(e=>!e.done).length,total_count:e.total??e.items.length}:t??null}function Xx(e){return e?.queueItem?.project_asset?.quota?.state??e?.queueItem?.quota?.state??e?.goal.quota?.state??`waiting`}function Zx(e,t,n){let r=[];for(let t of e){let e=qx(t,`agent`);for(let n of e?.items??[])r.push({goalId:t.goal.id,role:`agent`,todo:n})}let i=new Map;for(let e of r){let t=e.todo.claimed_by||`codex`,n=i.get(t)??[];n.push(e),i.set(t,n)}let a=new Map((n?.agents??[]).map(e=>[e.agent_id,e]));return Array.from(new Set([...i.keys(),...a.keys()])).map(e=>{let t=i.get(e)??[],n=a.get(e),r=Array.from(new Set([...t.map(e=>e.goalId),n?.current_todo?.goal_id,...n?.goal_ids??[]].filter(Boolean))),o=(t.filter(e=>!e.todo.done)[0]??t[0])?.goalId??n?.current_todo?.goal_id??r[0]??``,s=n?.last_activity_at??null;return{agentId:e,claimedTodos:t,currentTodo:n?.current_todo??null,evidenceRefs:[],goalIds:r,handoffNote:null,lastActivity:s,nextSafeAction:n?.next_action?.trim()||`Inspect status projection before taking work`,primaryGoalId:o,quotaHints:[],staleClaimHint:null,status:{label:`可用`,summary:`正常运行`,variant:`success`},workspaceRef:null}})}function Qx(e){return e?.map(e=>({dataUrl:e.data_url,id:e.id,mimeType:e.mime_type,name:e.name,size:e.size}))}var $x=`loopx.personal-agent-selection.v1`;function eS(){if(typeof window>`u`)return{};try{let e=JSON.parse(window.localStorage.getItem($x)??`{}`);return!e||typeof e!=`object`||Array.isArray(e)?{}:Object.fromEntries(Object.entries(e).filter(e=>typeof e[0]==`string`&&typeof e[1]==`string`))}catch{return{}}}var tS={需修复:`danger`,等你:`warning`,等待条件:`info`,推进中:`success`,安静运行:`neutral`,已停止:`neutral`,已完成:`neutral`};function nS(e,t){return Ux(t)||e.replace(/^loopx[-_]/i,`LoopX `).split(/[-_]+/).filter(Boolean).map((e,t)=>t===0?`${e.slice(0,1).toUpperCase()}${e.slice(1)}`:e).join(` `)}function rS(e){return e.split(/\r?\n/u).filter(e=>!/^\s*GOAL_(STATUS|PROGRESS)\s*:/u.test(e)).map(e=>/^\s*GOAL_EVIDENCE\s*:/u.test(e)?e.replace(/^\s*GOAL_EVIDENCE\s*:/u,`验证依据:`):/^\s*NEXT_ACTION\s*:/u.test(e)?e.replace(/^\s*NEXT_ACTION\s*:/u,`下一步:`):e).join(` +`).trim()}function iS(e,t){return[`agent`,`assistant`].includes(e.trim().toLowerCase())&&t.trim().length>0}var aS=`已发现的项目 Agent`;function oS(e){switch(Zv(e)){case`codex`:return`Codex`;case`claude`:return`Claude Code`;case`kiro`:return`Kiro CLI`;case`trae`:return`Trae CLI Agent`;case`coco`:return`Coco Agent`;default:return nS(e)}}function sS(e,t){switch(Qv(e,t)){case`codex`:return`代码与项目执行`;case`claude`:return`复杂分析与长任务`;case`openai`:case`anthropic`:return`管家问答 · 无工具`;case`kiro`:return`终端编码 · 原生 /goal 循环`;case`trae`:return`前端与交互实现`;case`coco`:return`通用任务`;default:return aS}}function cS(e,t){let n=e.project_asset;return t===`user`?Yx(n?.user_todos,e.user_todos,`project_asset.user_todos`):Yx(n?.agent_todos,e.agent_todos,`project_asset.agent_todos`)}function lS(e){return Wx(e.title??e.text,112)}function uS(e,t){return{resumeWhen:e.resume_when??null,claimedBy:e.claimed_by??null,done:e.status!==`deferred`&&e.done,evidence:e.evidence?Wx(e.evidence,96):null,index:e.index,priority:e.priority??null,status:e.status??null,taskClass:e.task_class??null,taskDomain:e.task_domain??null,text:lS(e),todoId:e.todo_id?.trim()||`${t.goal.id}:agent:${e.index}`}}function dS(e){let t=e.queueItem?.agent_todos,n=t?.items??e.queueItem?.project_asset?.agent_todos?.items??[],r=new Map(n.map(t=>[t.todo_id?.trim()||`${e.goal.id}:agent:${t.index}`,t]));for(let n of t?.deferred_items??[]){let t=n.todo_id?.trim()||`${e.goal.id}:agent:${n.index}`;r.has(t)||r.set(t,n)}return[...r.values()]}function fS(e){return dS(e).map(t=>uS(t,e))}function pS(e,t,n){let r=new Map;for(let n of e.todo_index?.items??[]){if(n.goal_id!==t.goal.id||n.role!==`agent`)continue;let e=uS(n,t);r.set(e.todoId,e)}for(let e of n)r.has(e.todoId)||r.set(e.todoId,e);let i=new Map;for(let e of r.values()){if(e.done||e.taskClass!==`advancement_task`)continue;let t=e.taskDomain?.trim();t&&i.set(t,(i.get(t)??0)+1)}return[...i].map(([e,t])=>({domain:e,matchingTodoCount:t}))}function mS(e,t){return{claimedBy:e.claimed_by??null,done:e.status===`done`||e.status===`completed`,index:-1,priority:e.priority??null,status:e.status??null,taskClass:e.task_class??null,text:Wx(e.title,112),todoId:e.todo_id?.trim()||`${t.goal.id}:agent:${e.claimed_by??`unknown`}:current`}}function hS(e,t,n){let r=new Map(e.map(e=>[e.todoId,e]));for(let e of t){let t=e.currentTodo;if(!t||t.goal_id!==n.goal.id)continue;let i=mS(t,n);r.has(i.todoId)||r.set(i.todoId,i)}return[...r.values()]}function gS(e){let t=e.queueItem?.project_asset?.agent_todos,n=e.queueItem?.agent_todos,r=dS(e),i=t?.advancement_done_count??n?.advancement_done_count??t?.done??n?.done_count??null,a=r.filter(e=>e.done&&e.status!==`deferred`).length,o=Math.max(i??0,a),s=new Set(r.map(e=>e.todo_id?.trim()).filter(e=>!!e)),c=(t?.recent_completed_advancement_items??[]).filter(e=>!e.todo_id?.trim()||!s.has(e.todo_id.trim())).map(t=>uS(t,e)),l=r.find(e=>!e.done);return{doneTodoCount:o,nextTodoText:Ux(t?.next??``)||(l?Ux(l.title??``)||Ux(l.text??``):``)||null,recentCompleted:c}}function _S(e,t){let n=Ux(e);return n?/\b(state_file|registry_goal|authority_sources|source_registry)\b|\b[a-z_]+\s+\d+\/\d+/i.test(n)?t(`projection.goalVerified`):bx(n,t,`projection.validationRecorded`):``}function vS(e,t=4){if(e.length<=t)return e;let n=e.findIndex(e=>!e.done);if(n<0)return e.slice(-t);let r=Math.max(0,Math.min(n-2,e.length-t));return e.slice(r,r+t)}function yS(e,t,n){let r=t.queueItem?.project_asset?.latest_validation,i=t.latestRun,a=e.event_ledger_summary?.goals.find(e=>e.goal_id===t.goal.id);if(!r&&!i&&!a)return null;let o=[_S(r?.summary,n),bx(i?.health_check,n),bx(i?.recommended_action,n)].find(e=>e!==``&&e!==`暂无`)??n(`projection.runRecorded`),s=Sx({eventCount:a?.events_24h??0,hasArtifact:!!(i?.json_exists||i?.markdown_exists),hasLatestValidation:!!r},n);return{generatedAt:r?.generated_at??i?.generated_at??a?.latest_event_at??``,label:s.label,metadata:s.metadata,runId:i?`${t.goal.id}:${i.generated_at}`:null,safePreview:[o,s.metadata].filter(Boolean).join(` +`),summary:o,todoId:t.queueItem?.project_asset?.agent_todos?.items.find(e=>!e.done)?.todo_id??null}}function bS(e){return[e.status,e.goal.status,e.latestRun?.classification,e.lifecyclePhase].filter(Boolean).some(e=>/(^|[_\s-])(done|complete|completed|finished|terminal|closed|success)([_\s-]|$)/i.test(e??``))}function xS(e,t){return e.global_registry?.findings?.find(e=>e.severity===`high`&&(e.goal_id===t.goal.id||e.goal_ids.includes(t.goal.id)))}function SS(e){return[e.status,e.goal.status,e.latestRun?.classification,e.lifecyclePhase].filter(Boolean).some(e=>/(^|[_\s-])(failure|failed|error|broken|unhealthy|blocked[_\s-]?health|health[_\s-]?blocked)([_\s-]|$)/i.test(e??``))}function CS(e,t){let n=t.queueItem?.stale_latest_run_warning;return t.severity===`high`||!!xS(e,t)||!!(n?.requires_refresh_state||n?.severity===`high`)||SS(t)}function wS(e,t){let n=xS(e,t);return t.queueItem?.stale_latest_run_warning?.recommended_action??t.queueItem?.stale_latest_run_warning?.reason??n?.recommended_action??n?.message??t.queueItem?.recommended_action??t.latestRun?.recommended_action??null}function TS(e){let t=e.latestRun?.operator_gate,n=t?.decision?.trim().toLowerCase()??``,r=new Set([`approve`,`approved`,`reject`,`rejected`,`defer`,`deferred`,`cancel`,`cancelled`]),i=[e.queueItem?.recommended_action,e.latestRun?.recommended_action].filter(Boolean).join(` `),a=/(?:等待|需要)(?:用户|你|owner).{0,24}(?:批准|确认|授权|补充|选择|决定)|(?:批准|确认|授权).{0,16}(?:后|才能|方可)/i.test(i);return!!(t&&!r.has(n))||e.lifecyclePhase===`operator_gated`&&!r.has(n)||a}function ES(e,t){let n=e.latestRun?.operator_gate;return bx(n?.operator_question??n?.reason_summary??n?.follow_up??e.queueItem?.recommended_action??e.latestRun?.recommended_action,t,`projection.confirmAgentDecision`)}function DS(e,t){if(t.goal.activation_state===`stopped`)return`已停止`;let n=qx(t,`user`),r=qx(t,`agent`),i=!!Jx(n),a=!!Jx(r);return[`user_or_controller`,`controller`].includes(t.waitingOn)||i||TS(t)?`等你`:CS(e,t)?`需修复`:t.waitingOn===`external_evidence`?`等待条件`:Xx(t)===`eligible`||a?`推进中`:bS(t)?`已完成`:`安静运行`}function OS(e,t,n,r){if(n===`已停止`)return xx(`stopped`,r);if(n===`需修复`)return bx(wS(e,t),r,`projection.statusRefreshNeeded`);if(n===`等你`)return xx(`needs_you`,r);if(n===`推进中`){let e=[(qx(t,`agent`)?.items??[]).filter(e=>!e.done).flatMap(e=>[e.title,e.text]).map(e=>Ux(e)).find(e=>e!==``&&e!==`暂无`),t.queueItem?.recommended_action,t.latestRun?.recommended_action].map(e=>Ux(e)).find(e=>e!==``&&e!==`暂无`);return e?bx(e,r,`projection.agentAdvancingGoal`):xx(`advancing`,r)}return xx(n===`等待条件`?`waiting_external`:`idle`,r)}function kS(e,t){return t.some(t=>e.includes(t))}function AS(e){return kS(e,[`我现在该做什么`,`该做什么`,`下一步`,`哪些 Goal 在等我`,`哪些 Goal 正在等我`,`等我`,`优先处理`,`全局待办`,`Agent 在做什么`,`哪些 Goal 需要我`])}function jS(e,t,n){if(t.goals.some(e=>e.activationState===`active`&&e.loadState))return{text:`Goal 状态尚未全部加载,暂不能给出完整统计。可先打开已加载的 Goal,失败项可重试。`,lines:[]};if(kS(n,[`Agent`,`agent`,`推进`,`在做`])){let e=t.goals.filter(e=>![`安静运行`,`已完成`,`已停止`].includes(e.state)),n=(e.length>0?e:t.goals).slice(0,3);return n.length===0?{text:`当前状态里还没有 Goal 可供汇总。`,lines:[]}:{text:e.length>0?`Agent 当前关注这些 Goal:`:`当前 Goal 都比较安静:`,lines:n.map(e=>`${e.title} · ${e.state} · ${e.agentSentence}`)}}if(kS(n,[`现在`,`下一步`,`我该`,`该做什么`,`优先处理`])){let e=t.userTodos[0];if(e)return{text:e.blocking?`先处理「${nS(e.goalId)}」:${e.text}`:`当前最先处理「${nS(e.goalId)}」:${e.text}`,lines:[]};let n=t.goals.find(e=>e.state===`需修复`);if(n)return{text:`没有待办,但这个 Goal 需要先修复。`,lines:[`${n.title} · ${n.agentSentence}`]};let r=t.goals.find(e=>e.state===`推进中`);return r?{text:`目前不需要你介入,Agent 正在推进。`,lines:[`${r.title} · ${r.agentSentence}`]}:{text:`当前系统很安静,没有需要你立即处理的事项。`,lines:[]}}if(kS(n,[`等我`,`阻塞`,`需要我`,`全局待办`]))return t.userTodos.length===0?{text:`目前没有 Goal 在等你,开放用户待办为 0。`,lines:[]}:{text:`有 ${t.userTodos.length} 项开放用户待办,阻塞项优先:`,lines:t.userTodos.slice(0,3).map(e=>`${nS(e.goalId)} · ${e.blocking?`阻塞`:`待处理`} · ${e.text}`)};if(kS(n,[`状态`,`异常`,`修复`,`健康`])){let n=t.systemHealth?!t.systemHealth.ok:!e.ok||!e.contract?.ok||!e.global_registry?.ok||(e.global_registry?.summary?.high??0)>0,r=t.goals.filter(e=>e.state===`需修复`),i=r.slice(0,n?2:3).map(e=>`${e.title} · ${e.agentSentence}`);return n&&i.push(`全局状态、契约或注册表健康检查未通过,请进入管理页检查。`),i.length===0?{text:`当前没有发现 Goal 级或全局健康异常。`,lines:[]}:{text:r.length>0?`当前需要关注这些健康问题:`:`Goal 状态正常,但全局健康需要检查:`,lines:i}}return{text:`当前管家支持三类问题:下一步、等待你的事项、Agent 与健康状态。`,lines:[`问“我现在该做什么?”`,`问“哪些 Goal 在等我?”`,`问“Agent 在做什么?”或当前健康状态`]}}function MS(e,t,n,r=!1){let i=new Map(t.map(e=>[e.goal.id,e])),a=new Set(e.run_history.goals.filter(e=>e.activation_state===`stopped`).map(e=>e.id)),o=Gx(e.usage_summary),s=Zx(t,e.todo_index,e.agent_management_projection),c=e.attention_queue.items.flatMap((e,t)=>{if(a.has(e.goal_id))return[];let n=[`user_or_controller`,`controller`].includes(e.waiting_on);return(cS(e,`user`)?.items??[]).filter(e=>!e.done).map((r,i)=>({actionKind:r.action_kind??null,blocking:n,goalId:e.goal_id,sourceOrder:t,taskClass:r.task_class??null,text:lS(r),todoId:r.todo_id?.trim()||`${e.goal_id}:user:${r.index}`,todoOrder:i,updatedAt:r.updated_at??null}))}),l=new Set(c.map(e=>e.goalId)),u=t.flatMap((t,r)=>a.has(t.goal.id)||l.has(t.goal.id)||!TS(t)?[]:[{actionKind:`gate.resolve`,blocking:!0,goalId:t.goal.id,sourceOrder:e.attention_queue.items.length+r,taskClass:`user_gate`,text:ES(t,n),todoId:`${t.goal.id}:operator-gate`,todoOrder:0,updatedAt:t.latestRun?.operator_gate?.recorded_at??t.latestRun?.generated_at??null}]),d=[...c,...u].sort((e,t)=>Number(t.blocking)-Number(e.blocking)||e.sourceOrder-t.sourceOrder||e.todoOrder-t.todoOrder),f=e.run_history.goals.flatMap(t=>{if(t.registry_member===!1)return[];let a=i.get(t.id);if(!a)return[];let c=DS(e,a),l=d.find(e=>e.goalId===t.id),u=l?.text??null,f=gS(a),p=t.coordination?.registered_agents??[],m=new Set(p),h=[...s.filter(e=>e.goalIds.includes(t.id)&&!/unassigned|unknown/i.test(e.agentId)&&(m.size===0||m.has(e.agentId))&&(e.currentTodo?.goal_id===t.id||e.claimedTodos.some(e=>e.goalId===t.id)))].sort((e,t)=>(t.lastActivity??``).localeCompare(e.lastActivity??``)),g=new Set(h.map(e=>e.agentId)),_=[...h.map(e=>({agentId:e.agentId,label:e.agentId,lastActivityAt:e.lastActivity,state:e.status.label})),...p.filter(e=>!g.has(e)).map(e=>({agentId:e,label:e,lastActivityAt:null,state:`registered`}))],v=h[0],y=hS(fS(a),h,a),b=[f.nextTodoText,a.queueItem?.recommended_action,a.latestRun?.recommended_action,OS(e,a,c,n)].map(e=>bx(e,n)).find(e=>e!==``&&e!==`暂无`)??n(`projection.nextUpdatePending`);return[{activationState:t.activation_state,agentId:v?.agentId??p[0]??`codex`,agentLaneCount:_.length,agentLanes:_,agentLabel:v?.agentId,agentSentence:OS(e,a,c,n),agentTodos:[...y,...f.recentCompleted],doneTodoCount:f.doneTodoCount,goalId:t.id,latestActivity:a.latestRun?.generated_at??``,needsYou:u,needsYouActionKind:l?.actionKind??null,needsYouBlocking:l?.blocking??!1,needsYouTaskClass:l?.taskClass??null,needsYouTodoId:l?.todoId??null,nextSentence:b,runEvidence:yS(e,a,n),state:c,...r?{subagentExecution:{allowedDomains:t.spawn_policy?.allowed_domains??[],domainCandidates:pS(e,a,y),enabled:t.spawn_policy?.mode===`multi_subagent`&&t.spawn_policy.spawn_allowed===!0&&t.spawn_policy.max_children>0,maxChildren:t.spawn_policy?.max_children??0}}:{},title:nS(t.id,t.display_name),usage:(()=>{let e=o.get(t.id);return e?{costUsd24h:e.cost_usd_24h,costUsd7d:e.cost_usd_7d,durationMs24h:e.duration_ms_24h,durationMs7d:e.duration_ms_7d,tokens24h:Kx(e.input_tokens_24h,e.output_tokens_24h),tokens7d:Kx(e.input_tokens_7d,e.output_tokens_7d)}:null})()}]}),p=[];if(e.ok||p.push(`状态载荷未标记为正常 (payload.ok === false)`),e.contract&&!e.contract.ok){let t=e.contract.summary,n=t?`${t.errors} 项错误 / ${t.warnings} 项警告`:e.contract.errors?.[0]||`请检查控制面契约`;p.push(`契约检查未通过: ${n}`)}if(e.global_registry){e.global_registry.ok||p.push(`注册表状态异常: ${e.global_registry.summary.high} 项高危`);for(let t of e.global_registry.findings||[])t.severity===`high`&&p.push(`[${t.kind}] ${t.message}`)}let m=e.decision_freshness_summary?.summary?.stale_count?`${e.decision_freshness_summary.summary.stale_count} 项决策状态已过期`:null,h=p.length===0&&!m,g={ok:h,summary:h?`所有控制面契约与注册表检查均正常`:`发现 ${p.length+ +!!m} 项系统健康关注点`,issues:p,freshnessWarning:m};return{blockingTodoCount:d.filter(e=>e.blocking).length,goalNotifications:(e.goal_channel_notification_projection?.goals??[]).map(e=>({goalId:e.goal_id,configured:e.configured,enabled:e.enabled,humanGateAutoNotifyEnabled:e.human_gate_auto_notify_enabled,lastNotifiedAt:e.last_notified_at??null,receiptCount:e.receipt_count,targetRef:e.target_ref??null})),goals:f,openUserTodoCount:d.length,systemHealth:g,userTodos:d,visibleUserTodos:d.slice(0,5),workers:(e.agent_management_projection?.agents??[]).map(e=>({agentId:e.agent_id,currentTodoGoalId:e.current_todo?.goal_id??null,currentTodoText:e.current_todo?.title?Wx(e.current_todo.title,96):null,lastActivityAt:e.last_activity_at??null,state:e.state??null}))}}function NS({goalArchiveLoadState:e,isLoading:t,onGoalActivationStateChange:n,onGoalDeleted:r,onSelectGoal:i,onReconcileStatus:a,onRefresh:o,onRetryGoalArchive:s,payload:c,progress:l,rows:u,selectedGoalId:d,statusSourceControl:f,theme:p,toggleTheme:m}){let h=f.activeSource.readOnly,{t:g}=Ji(),[_,v]=(0,R.useState)([]),[y,b]=(0,R.useState)(!1),x=(0,R.useMemo)(()=>{let e=MS(c,u,g,y);if(!l)return e;let t=Object.values(l.snapshots).map(e=>MS(e,Hx(e.run_history.goals,e.attention_queue.items),g,y)),n=new Map(t.flatMap(e=>e.goals).map(e=>[e.goalId,e])),r=e.goals.map(e=>n.get(e.goalId)??{...e,loadError:l.errors[e.goalId],loadState:l.errors[e.goalId]?`error`:`loading`,agentId:``,agentSentence:``,nextSentence:``,subagentExecution:void 0}),i=t.flatMap(e=>e.userTodos),a=r.some(e=>e.activationState===`active`&&e.loadState),o=[...new Set(t.flatMap(e=>e.systemHealth?.issues??[]))];return{...e,goals:r,userTodos:i,visibleUserTodos:i.slice(0,5),openUserTodoCount:i.length,blockingTodoCount:i.filter(e=>e.blocking).length,workers:[...new Map(t.flatMap(e=>e.workers??[]).map(e=>[e.agentId,e])).values()],goalNotifications:t.flatMap(e=>e.goalNotifications??[]),systemHealth:a||t.length===0?void 0:{ok:t.every(e=>e.systemHealth?.ok),issues:o,summary:o.length?`发现 ${o.length} 项系统健康关注点`:`状态检查已完成`,freshnessWarning:t.map(e=>e.systemHealth?.freshnessWarning).filter(Boolean).join(`;`)||null}}},[c,u,l,y,g]),S=x.goals.find(e=>e.goalId===d)??null,C=l?.snapshots[d]??c,[w,T]=(0,R.useState)(null),[E,D]=(0,R.useState)(null),[O,k]=(0,R.useState)(!1),ee=x.goals.some(e=>e.activationState===`active`&&e.loadState===`loading`)?`loading`:x.goals.map(e=>`${e.goalId}:${e.agentId}`).join(`|`),A=S?.goalId??`manager`;x.goals.some(e=>e.activationState===`active`&&e.loadState)||(x.systemHealth?!x.systemHealth.ok:!c.ok)||x.openUserTodoCount>0&&`${x.openUserTodoCount}${x.blockingTodoCount}`;let j=_.length>0?_.map(e=>({agentId:e.agent_id,adapterKind:e.adapter_kind,available:e.available,capability:sS(e.agent_id,e.adapter_kind),interrupt:e.interrupt,label:e.display_name,location:e.location,resume:e.resume,source:e.source,statusLabel:e.available?`可用`:`需要配置`,streaming:e.streaming,toolCalls:e.tool_calls,trustScope:e.trust_scope})):[{agentId:`codex`,available:!0,capability:sS(`codex`),label:`Codex`,statusLabel:`正在检测`}],te=[...j,{agentId:`status-only`,available:!0,capability:`不调用模型`,adapterKind:`status_projection`,interrupt:!1,label:`仅查状态`,resume:!0,statusLabel:`只读`,streaming:!1,toolCalls:!1,trustScope:`read_only`}],ne=j.find(e=>e.label===`Codex`&&e.available)?.agentId??j.find(e=>e.available)?.agentId??`status-only`,[re,M]=(0,R.useState)(eS),N=nh(te,re[A]??ne,ne),[ie,ae]=(0,R.useState)(!1),[oe,P]=(0,R.useState)(!1),[F,I]=(0,R.useState)(`chat`),[se,ce]=(0,R.useState)(``),[le,ue]=(0,R.useState)({}),[de,fe]=(0,R.useState)({}),[pe,me]=(0,R.useState)(null),[he,ge]=(0,R.useState)({}),[_e,ve]=(0,R.useState)([]),[ye,be]=(0,R.useState)(null),[xe,Se]=(0,R.useState)({}),Ce=(0,R.useRef)(1),we=(0,R.useRef)(1),Te=(0,R.useRef)(new Map),Ee=(0,R.useRef)(new Set),De=(0,R.useRef)(new Map),L=(0,R.useRef)(new Map),Oe=(0,R.useRef)(new Set),ke=(0,R.useRef)(new Set),Ae=(0,R.useRef)(null),je=(0,R.useRef)(null),Me=(0,R.useRef)(null),Ne=(0,R.useRef)(null);(0,R.useRef)(null);let Pe=le[A]??[];de[A];let Fe=S?x.userTodos.filter(e=>e.goalId===S.goalId):x.userTodos,Ie=S?.agentTodos??[];vS(Ie,S?.needsYou?3:4);let B=Ie.filter(e=>e.done).length,Le=Ie.length>0?`${B}/${Ie.length}`:`暂无计划`,Re=S?{...x,blockingTodoCount:Fe.filter(e=>e.blocking).length,goals:[S],openUserTodoCount:Fe.length,userTodos:Fe,visibleUserTodos:Fe}:x;(0,R.useEffect)(()=>{let e=Ym(f.activeSource.statusUrl,window.location.href),t=e.source?$m(C,e.source):null;if(!S||!t?.indexUrl||!t.detailUrl){T(null),D(null),k(!1);return}let{detailUrl:n,indexUrl:r}=t,i=!1;return T(null),D(null),k(!0),eh(r,S.goalId).then(async e=>{let t=e.items[0]?.detail_ref;return t?th(n,t):null}).then(e=>{i||T(e)}).catch(e=>{i||D(yp(e))}).finally(()=>{i||k(!1)}),()=>{i=!0}},[C,S?.goalId,f.activeSource.statusUrl]);function V(e,t){ge(n=>{if(t===null){let t={...n};return delete t[e],t}return{...n,[e]:t}})}(0,R.useEffect)(()=>{if(h){v([]),b(!1);return}let e=!1;return Oh().then(t=>{e||(v(t.adapters??[]),b(t.goal_subagent_configuration===`preview_locked`))}).catch(()=>{e||b(!1)}),()=>{e=!0}},[h]),(0,R.useEffect)(()=>{try{window.localStorage.setItem($x,JSON.stringify(re))}catch{}},[re]),(0,R.useEffect)(()=>{if(h||!N.available)return;let e=A,t=`${e}:${N.agentId}`,n=S?`goal`:`manager`,r=S?`goal.${S.goalId}`:`manager`,i=S?.goalId??x.goals[0]?.goalId??``,a=!1,o=null,s=null;return(async()=>{try{let c=await Ph({agentId:N.agentId,channelId:r,goalId:S?.goalId});if(a||(ue(t=>(t[e]?.length??0)>0?t:{...t,[e]:c.messages.map(e=>({agentLabel:e.role===`user`?void 0:N.label,attachments:Qx(e.attachments),id:Ce.current++,lines:[],role:e.role===`user`?`user`:`assistant`,sourceLabel:e.role===`user`?void 0:e.role===`error`?`本地会话记录`:`恢复的 ${N.label} 会话`,text:e.role===`user`?e.text:rS(e.text)}))}),N.agentId===`status-only`))return;let l=c.sessions[0];if(s=l?.session_id??null,l&&!l.resumable){Ee.current.add(t),V(e,{agentId:N.agentId,resumable:!1,sessionId:l.session_id,status:`resume_failed`});return}let u=l?.goal_id??i;if(!u)return;let d=await Ah(u,N.agentId,`resume_latest`,n);if(a)return;Te.current.set(t,d.session_id);let f=c.snapshots.find(e=>e.session.session_id===d.session_id),p=f?.session.active_turn_id??``;if(V(e,{agentId:N.agentId,resumable:!0,sessionId:d.session_id,status:p?`running`:`ready`,turnId:p||void 0}),Ee.current.delete(t),!p)return;let m=`${d.session_id}:${p}`;if(ke.current.has(m))return;ke.current.add(m),De.current.set(e,p),V(e,{agentId:N.agentId,resumable:!0,sessionId:d.session_id,status:`running`,turnId:p}),me(e),o=new AbortController,L.current.set(e,o);let h=``,g=ze(e,{activity:[`正在恢复进行中的 Agent 回合`],agentLabel:N.label,lines:[],pending:!0,sourceLabel:`恢复的 ${N.label} 会话`,text:``});try{let t=await Vh(d.session_id,p,{signal:o.signal,onDelta:t=>{h+=t,Be(e,g,{text:h})},onActivity:t=>{ue(n=>({...n,[e]:(n[e]??[]).map(e=>e.id===g?{...e,activity:[...new Set([...e.activity??[],t])].slice(-6)}:e)}))}});if(a)return;Be(e,g,{lines:t.response.gate?[t.response.gate.summary,t.response.gate.next_action].filter(Boolean).slice(0,2):[],pending:!1,text:t.response.message||h.trim()||`${N.label} 已完成分析。`});let n=x.goals.find(e=>e.goalId===f?.session.goal_id)??S??x.goals[0]??null;if(n&&t.response.proposals.length>0){let r=t.response.proposals.map(e=>({goalId:n.goalId,id:we.current++,previewId:null,proposal:e,receiptLabel:null,state:`candidate`,statusMessage:null}));fe(t=>({...t,[e]:[...t[e]??[],...r]}))}}catch(t){if(a)return;Be(e,g,{activity:[],lines:[],pending:!1,reconnect:t instanceof _h&&t.payload.reconnectable===!0,sourceLabel:`LoopX Chat 本地后端`,text:t instanceof Error?t.message:`无法恢复进行中的 Agent 回合。`})}finally{ke.current.delete(m),De.current.get(e)===p&&De.current.delete(e),V(e,{agentId:N.agentId,resumable:!0,sessionId:d.session_id,status:`ready`}),L.current.get(e)===o&&L.current.delete(e),a||me(t=>t===e?null:t)}}catch(n){if(a)return;n instanceof _h&&n.payload.error_code===`resume_failed`&&(Ee.current.add(t),s&&V(e,{agentId:N.agentId,resumable:!1,sessionId:s,status:`resume_failed`}))}})(),()=>{a=!0,o?.abort()}},[A,x.goals[0]?.goalId,h,S?.goalId,N.agentId,N.available,N.label]),(0,R.useEffect)(()=>{if(h||S||x.goals.length===0||ee===`loading`)return;let e=!1;return Promise.all(x.goals.filter(e=>!e.loadState).map(async e=>{let t=await Mh({agentId:e.agentId,channelId:`goal.${e.goalId}`,goalId:e.goalId});return{goalId:e.goalId,session:t.sessions[0]??null}})).then(t=>{e||ge(e=>{let n={...e};for(let e of t)e.session&&(n[e.goalId]={agentId:e.session.agent_id,resumable:e.session.resumable,sessionId:e.session.session_id,status:e.session.active_turn_id?`running`:e.session.status,turnId:e.session.active_turn_id??void 0});return n})}).catch(()=>{}),()=>{e=!0}},[h,ee,S?.goalId]),(0,R.useEffect)(()=>{if(be(null),h){ve([]),Se({});return}if(!S){ve([]),Se({});return}let e=!1,t=0,n=0;ve([]),Se({});let r=async()=>{if(!e){if(document.hidden){t=window.setTimeout(()=>void r(),1e4);return}try{let t=await Mh({goalId:S.goalId});if(!e){let r=t.sessions.filter(e=>e.channel_id?.startsWith(`task.`));ve(r);let i=await Promise.allSettled(r.map(e=>jh(e.session_id)));if(!e){let e=i.some(e=>e.status===`rejected`);n=e?n+1:0,be(e?`partial`:null),Se(Object.fromEntries(i.flatMap((e,t)=>e.status===`fulfilled`?[[r[t].session_id,e.value]]:[])))}}}catch{n+=1,e||be(`offline`)}e||(t=window.setTimeout(()=>void r(),Math.min(3e4,2e3*2**Math.min(n,4))))}};return r(),()=>{e=!0,window.clearTimeout(t)}},[h,S?.goalId]),(0,R.useEffect)(()=>{if(!ie)return;let e=window.requestAnimationFrame(()=>{Ae.current?.querySelector(`[role="menuitem"]:not(:disabled)`)?.focus()});return()=>{window.cancelAnimationFrame(e),je.current?.focus()}},[ie]),(0,R.useEffect)(()=>{if(!oe)return;let e=window.requestAnimationFrame(()=>Me.current?.focus());return()=>{window.cancelAnimationFrame(e),Ne.current?.focus()}},[oe]),(0,R.useEffect)(()=>{if(!ie&&!oe)return;let e=e=>{e.key===`Escape`&&(ae(!1),P(!1))};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[ie,oe]);function ze(e,t){let n=Ce.current++;return ue(r=>({...r,[e]:[...r[e]??[],{...t,id:n,role:`assistant`}]})),n}function Be(e,t,n){ue(r=>({...r,[e]:(r[e]??[]).map(e=>e.id===t?{...e,...n}:e)}))}async function Ve(e,t){let n=e.trim();if(!n)return;let r=t&&`goalId`in t?t.goalId??`manager`:A,i=r===`manager`?Re.goals[0]??x.goals[0]??null:x.goals.find(e=>e.goalId===r)??null,a=t?.agentId?nh(te,t.agentId,ne):N,o=r===`manager`?x:i?{...x,blockingTodoCount:x.userTodos.filter(e=>e.goalId===i.goalId&&e.blocking).length,goals:[i],openUserTodoCount:x.userTodos.filter(e=>e.goalId===i.goalId).length,userTodos:x.userTodos.filter(e=>e.goalId===i.goalId),visibleUserTodos:x.userTodos.filter(e=>e.goalId===i.goalId)}:x,s=Ce.current++;if(ue(e=>({...e,[r]:[...e[r]??[],{attachments:t?.attachments,id:s,lines:[],role:`user`,text:n}]})),ce(``),me(r),r===`manager`&&AS(n)||a.agentId===`status-only`||!i){let e=jS(C,o,n),t=a.agentId===`status-only`;ze(r,{agentLabel:t?`仅查状态`:`LoopX 管家`,lines:e.lines.slice(0,3),sourceLabel:t?`LoopX 状态投影 · 仅查状态`:`LoopX 状态投影`,text:e.text}),kh({answer:[e.text,...e.lines.slice(0,3)].filter(Boolean).join(` +`),contextKind:r===`manager`?`manager`:`goal`,goalId:r===`manager`?void 0:r,question:n}).catch(()=>{}),me(null);return}let c=`${r}:${a.agentId}`,l=null;try{let e=Te.current.get(c);if(!e){let t=Ee.current.has(c)?`new`:`resume_latest`;e=(await Ah(i.goalId,a.agentId,t,r===`manager`?`manager`:`goal`)).session_id,Te.current.set(c,e),V(r,{agentId:a.agentId,resumable:!0,sessionId:e,status:`ready`}),Ee.current.delete(c)}let o=``;l=ze(r,{activity:[`正在连接 Agent`],agentLabel:a.label,lines:[],pending:!0,sourceLabel:r===`manager`?`${a.label} 管家 · 跨 Goal`:`${a.label} Agent · ${nS(i.goalId)}`,text:``});let s=(await zh(e,n,{attachments:t?.attachments,signal:(()=>{let e=new AbortController;return L.current.set(r,e),e.signal})(),onDelta:e=>{o+=e,l!==null&&Be(r,l,{text:o})},onActivity:e=>{l!==null&&ue(t=>({...t,[r]:(t[r]??[]).map(t=>t.id===l?{...t,activity:[...new Set([...t.activity??[],e])].slice(-6)}:t)}))},onPhase:(t,n)=>{De.current.set(r,n),V(r,{agentId:a.agentId,resumable:!0,sessionId:e,status:`running`,turnId:n})}})).response;if(Be(r,l,{lines:s.gate?[s.gate.summary,s.gate.next_action].filter(Boolean).slice(0,2):[],pending:!1,text:rS(s.message||o.trim())||`${a.label} 已完成分析。`}),s.proposals.length>0){let e=s.proposals.map(e=>({goalId:i.goalId,id:we.current++,previewId:null,proposal:e,receiptLabel:null,state:`candidate`,statusMessage:null}));fe(t=>({...t,[r]:[...t[r]??[],...e]}))}if(r!==`manager`&&s.protected_action){let e=Rx(r,n,s.protected_action);if(e)return e}}catch(e){if(Oe.current.delete(r)){let e={agentLabel:a.label,lines:[],pending:!1,sourceLabel:`${a.label} 会话`,text:`已中断。你可以在当前会话继续发送消息。`};l===null?ze(r,e):Be(r,l,e);return}let t=e instanceof _h?e.payload:null;t&&rh(t)&&Te.current.delete(c),t?.error_code===`resume_failed`&&(Te.current.delete(c),Ee.current.add(c),V(r,{agentId:a.agentId,resumable:!1,sessionId:he[r]?.sessionId??`resume-failed`,status:`resume_failed`}));let n=t?.gate,i=n&&typeof n==`object`?String(n.summary??``):``,o={agentLabel:a.label,lines:i?[i]:[],pending:!1,reconnect:t?.reconnectable===!0,sourceLabel:`LoopX Chat 本地后端`,text:t?.error_code===`resume_failed`?`原 ${a.label} 会话无法恢复。本地历史已经保留,请在运行详情里选择“重试恢复”或“开始新 Session”。`:e instanceof Error?e.message:`${a.label} 会话暂时不可用。`};l===null?ze(r,o):Be(r,l,o)}finally{De.current.delete(r),L.current.delete(r);let e=Te.current.get(c);e&&V(r,{agentId:a.agentId,resumable:!0,sessionId:e,status:`ready`}),me(e=>e===r?null:e)}}async function He(e){let t=e?.goalId??A,n=he[t],r=e?.agentId??n?.agentId??N.agentId,i=`${t}:${r}`,a=e?.sessionId??n?.sessionId??Te.current.get(i),o=e?.turnId??n?.turnId??De.current.get(t);if(!(!a||!o))try{Oe.current.add(t),await Rh(a,o),L.current.get(t)?.abort()}catch(e){throw Oe.current.delete(t),e}finally{De.current.delete(t),V(t,{agentId:r,resumable:!0,sessionId:a,status:`ready`}),L.current.delete(t),me(e=>e===t?null:e)}}async function Ue(e){let t=e.goalId,n=`${t}:${e.agentId}`,r=e.sessionId??he[t]?.sessionId??Te.current.get(n);if(r)try{let i=await Uh(r);Te.current.set(n,r),Ee.current.delete(n),V(t,{agentId:e.agentId,resumable:i.session.resumable,sessionId:r,status:i.session.status})}catch{V(t,{agentId:e.agentId,resumable:!1,sessionId:r,status:`resume_failed`})}}function We(e){let t=`${e.goalId}:${e.agentId}`;Te.current.delete(t),Ee.current.add(t),V(e.goalId,{agentId:e.agentId,resumable:!0,sessionId:`new-session-pending`,status:`ready`})}async function Ge(e){let t=`${e.goalId}:${e.agentId}`,n=e.sessionId??he[e.goalId]?.sessionId??Te.current.get(t);n&&n!==`new-session-pending`&&await Hh(n),Te.current.delete(t),Ee.current.add(t),V(e.goalId,null)}function Ke(e){te.some(t=>t.agentId===e&&t.available)&&(M(t=>({...t,[A]:e})),ae(!1))}function qe(){i(``),I(`chat`)}function Je(e){i(e),I(`chat`)}S&&tS[S.state],S&&(`${N.label}${S.state}`,Ie.length>0&&`${Le}`,Fe.length>0&&`${Fe.length}`),S?.state===`需修复`||!S&&!c.ok?(S&&oS(S.agentId),S?.nextSentence,S?.agentSentence):S?.state===`等你`?(S.needsYouBlocking,S.needsYouBlocking,S.needsYou??S.nextSentence,S.needsYou):(S&&oS(S.agentId),S?.nextSentence);let Ye=[...!S&&he.manager?.status===`resume_failed`?[{id:`run:manager:resume-failed`,kind:`run`,run:{agentId:he.manager.agentId,agentLabel:oS(he.manager.agentId),canInterrupt:!1,completedSteps:0,goalId:`manager`,goalTitle:`LoopX 管家`,latestActivity:`本地聊天记录已保留,点我查看恢复方式。`,resumable:!1,runId:`manager:resume-failed`,sessionId:he.manager.sessionId,sessionStatus:`resume_failed`,status:`failed`,title:`上次会话需要恢复`,totalSteps:1,outputs:[]}}]:[],...S?_e.map(e=>{let t=e.channel_id?.startsWith(`task.`)?e.channel_id.slice(5):void 0,n=S.agentTodos.find(e=>e.todoId===t),r=!!e.active_turn_id,i=xe[e.session_id],a=i?.messages.some(e=>iS(e.role,e.text))===!0;return{id:`run:task:${e.session_id}`,kind:`run`,run:{agentId:e.agent_id,agentLabel:oS(e.agent_id),canInterrupt:r,completedSteps:n?.done||a?1:0,goalId:S.goalId,goalTitle:S.title,latestActivity:r?`Agent 正在执行,可进入 Session 查看过程或发送纠偏。`:a?`Agent 已返回结果,点击查看结果与完整运行记录。`:`执行 Session 已保留,可继续纠偏或恢复。`,resumable:e.resumable,runId:e.session_id,sessionId:e.session_id,sessionMessages:i?.messages.map(e=>({createdAt:e.created_at,messageId:e.message_id,role:e.role===`user`?`user`:iS(e.role,e.text)?`assistant`:`error`,text:e.role===`user`?e.text:rS(e.text)})),sessionStatus:a?`completed`:e.status,status:n?.done||a?`completed`:r?`running`:e.status===`resume_failed`?`failed`:`waiting`,title:n?.text??`Agent 执行任务`,todoId:t,totalSteps:1,turnId:e.active_turn_id??void 0}}}):[],...S?[{id:`run:${S.goalId}`,kind:`run`,run:{agentId:he[S.goalId]?.agentId??S.agentId,agentLabel:oS(he[S.goalId]?.agentId??S.agentId),canInterrupt:!!he[S.goalId]?.turnId,completedSteps:S.agentTodos.filter(e=>e.done).length,goalId:S.goalId,goalTitle:S.title,latestActivity:S.agentSentence,resumable:he[S.goalId]?.resumable??!0,runId:`goal:${S.goalId}`,sessionId:he[S.goalId]?.sessionId,sessionStatus:he[S.goalId]?.status,status:he[S.goalId]?.turnId?`running`:S.state===`需修复`?`failed`:`waiting`,title:S.nextSentence,totalSteps:S.agentTodos.length||1,turnId:he[S.goalId]?.turnId,outputs:S.runEvidence?[{createdAt:S.runEvidence.generatedAt,kind:`evidence`,outputId:`${S.goalId}:latest-evidence`,title:S.runEvidence.label}]:[]}}]:[],...Pe.map(e=>({id:`message:${e.id}`,kind:`message`,message:{agentLabel:e.agentLabel,attachments:e.attachments,id:String(e.id),pending:e.pending,role:e.role,text:e.text||(e.pending?`Agent 正在处理…`:e.lines.join(` +`))}})),...(S?[S]:x.goals).flatMap(e=>e.runEvidence?[{id:`output:${e.goalId}:${e.runEvidence.generatedAt||`latest`}`,kind:`output`,output:{agentLabel:oS(e.agentId),createdAt:e.runEvidence.generatedAt,goalId:e.goalId,goalTitle:e.title,kind:`evidence`,outputId:`${e.goalId}:latest-evidence`,runId:e.runEvidence.runId??void 0,safePreview:e.runEvidence.safePreview,summary:e.runEvidence.summary,title:e.runEvidence.label,todoId:e.runEvidence.todoId??void 0}}]:[]),...S&&w?[{id:`output:${S.goalId}:report:${w.publication.publication_id}`,kind:`output`,output:{agentId:w.agent_id,agentLabel:oS(w.agent_id),createdAt:w.publication.delivered_at,goalId:S.goalId,goalTitle:S.title,kind:`report`,outputId:w.publication.publication_id,report:{addedCount:w.delta.added_count,changedCount:w.delta.changed_count,deliveredAt:w.publication.delivered_at,generationId:w.generation_id,items:w.delta.items.map(e=>({changeKind:e.change_kind,previousStatus:e.previous_status,sourceRef:e.source_ref,status:e.status,summary:e.summary,title:e.title})),periodEndAt:w.period_window.end_at,periodStartAt:w.period_window.start_at,predecessorPublicationId:w.publication.predecessor_publication_id,publicationId:w.publication.publication_id},safePreview:w.delta.items.map(e=>`${e.change_kind===`added`?`+`:`~`} ${e.title}\n${e.summary}`).join(` -`),summary:w.summary,title:w.title}}]:[]],Xe={...Xv(x),periodicReports:{error:E,loading:O},timeline:Ye};return(0,z.jsxs)(`div`,{className:p===`dark`?`dark`:``,"data-testid":`personal-goal-home`,children:[ye?(0,z.jsx)(`p`,{role:`status`,className:`m-0 bg-amber-50 px-4 py-2 text-sm text-amber-900`,children:g(ye===`partial`?`runs.discoveryPartial`:`runs.discoveryOffline`)}):null,(0,z.jsx)(mx,{agents:te.map(e=>({adapterKind:e.adapterKind,agentId:e.agentId,available:e.available,capability:e.capability,interrupt:e.interrupt,label:e.label,location:e.location,resume:e.resume,source:e.source,streaming:e.streaming,toolCalls:e.toolCalls,trustScope:e.trustScope,workspaceCompatibility:e.available?`当前 Goal 写入前验证`:`不可用,需先修复 Endpoint`})),callbacks:{onApplyAttention:e=>Je(e.goalId),onCorrectRun:async(e,t)=>{if(!e.sessionId)throw Error(`这个 Run 还没有可纠偏的执行 Session。`);let n=await wh((await xh({actionKind:`run.correct`,context:{kind:`run`,goal_id:e.goalId,todo_id:e.todoId},idempotencyKey:`workspace-run-correct-${e.sessionId}-${Date.now().toString(36)}`,normalizedParameters:{goal_id:e.goalId,message:t,session_id:e.sessionId},summary:`纠偏执行任务:${e.title}`})).proposal_id),r=typeof n.turn?.turn_id==`string`?n.turn.turn_id:void 0;if(V(e.goalId,{agentId:e.agentId,resumable:!0,sessionId:e.sessionId,status:r?`running`:`ready`,turnId:r}),r){De.current.set(e.goalId,r);let t=new AbortController;L.current.set(e.goalId,t);let n=``,i=ze(e.goalId,{activity:[`正在把纠偏送入原执行 Session`],agentLabel:e.agentLabel,lines:[],pending:!0,sourceLabel:`${e.agentLabel} · 执行 Session`,text:``});try{let a=await Vh(e.sessionId,r,{signal:t.signal,onDelta:t=>{n+=t,Be(e.goalId,i,{text:n})}});Be(e.goalId,i,{activity:[],pending:!1,text:eS(a.response.message||n.trim())||`${e.agentLabel} 已完成纠偏。`})}catch(t){let n=Oe.current.delete(e.goalId);Be(e.goalId,i,{activity:[],pending:!1,text:n?`已中断。你可以在当前会话继续发送消息。`:t instanceof Error?t.message:`纠偏回合失败。`})}finally{De.current.delete(e.goalId),L.current.delete(e.goalId),V(e.goalId,{agentId:e.agentId,resumable:!0,sessionId:e.sessionId,status:`ready`})}}},onCloseRunSession:Ge,onInterruptRun:async e=>He(e),onOpenGoal:Je,onOpenRunSession:async e=>{if(!e.sessionId)return;let t=e.sessionId,n=await jh(t);Se(e=>({...e,[t]:n})),Je(e.goalId),ue(t=>({...t,[e.goalId]:n.messages.map(t=>({agentLabel:t.role===`user`?void 0:e.agentLabel,attachments:Yx(t.attachments),id:Ce.current++,lines:[],role:t.role===`user`?`user`:`assistant`,sourceLabel:t.role===`user`?void 0:`${e.agentLabel} · 执行 Session`,text:t.role===`user`?t.text:eS(t.text)}))})),V(e.goalId,{agentId:e.agentId,resumable:n.session.resumable,sessionId:t,status:n.session.active_turn_id?`running`:n.session.status,turnId:n.session.active_turn_id??void 0})},onOpenOutput:e=>Je(e.goalId),...y?{onPreviewGoalSubagentConfiguration:async e=>{let t=await Kh(e);return{changed:t.changed,configuration:{allowedDomains:t.after.orchestration.allowed_domains,enabled:t.feature_summary.multi_subagent===`enabled`,maxChildren:t.after.orchestration.max_children},previewId:t.preview_id}},onApplyGoalSubagentConfiguration:async({previewId:e,...t})=>{let n=await qh(t,e);return{allowedDomains:n.after.orchestration.allowed_domains,enabled:n.feature_summary.multi_subagent===`enabled`,maxChildren:n.after.orchestration.max_children}}}:{},onGoalActivationStateChange:n,onGoalDeleted:r,onReconcileStatus:a,onRetryGoalArchive:s,onExportOutput:async e=>{let t=[`# ${e.title}`,``,e.summary??``,``,e.safePreview??`此产出没有可用的公开安全预览。`,``,`Goal: ${e.goalId}`,`Todo: ${e.todoId??`unlinked`}`,`Run: ${e.runId??`unlinked`}`].join(` -`),n=URL.createObjectURL(new Blob([t],{type:`text/markdown;charset=utf-8`})),r=document.createElement(`a`);r.href=n,r.download=`${e.outputId.replace(/[^a-z0-9._-]+/gi,`-`)}.md`,r.click(),URL.revokeObjectURL(n)},onRefresh:o,onRetryResumeRun:Ue,onSelectAgent:Ke,onSelectGoal:e=>e?Je(e):qe(),onSendMessage:async(e,t,n,r)=>Ve(e,{agentId:t,goalId:n,attachments:r}),onStartNewRunSession:We},goalArchiveLoadState:e,model:Xe,readOnly:h,selectedAgentId:N.agentId,selectedGoalId:S?.goalId??null,statusSourceControl:f})]})}function AS({error:e,isLoading:t,onRetry:n,requestedUrl:r,theme:i,toggleTheme:a}){let o=!!(e&&/failed to fetch|networkerror|load failed/i.test(e)&&r.includes(`status.json`));return(0,z.jsx)(`div`,{className:i===`dark`?`dark`:``,children:(0,z.jsxs)(`main`,{className:`min-h-screen bg-[#f6f7f9] text-slate-950 dark:bg-[#09090b] dark:text-zinc-50`,children:[(0,z.jsxs)(`header`,{className:`flex min-h-16 flex-wrap items-center justify-between gap-3 border-b border-slate-200 bg-white px-4 py-3 dark:border-zinc-800 dark:bg-zinc-950 sm:px-6`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`h1`,{className:`text-xl font-semibold`,children:`LoopX Workspace`}),(0,z.jsx)(`p`,{className:`mt-1 break-all text-sm text-slate-500 dark:text-zinc-400`,children:`Personal Workspace`})]}),(0,z.jsx)(qv,{"aria-label":`切换主题`,onClick:a,size:`icon`,variant:`secondary`,children:i===`dark`?(0,z.jsx)(Bm,{className:`h-4 w-4`}):(0,z.jsx)(xm,{className:`h-4 w-4`})})]}),(0,z.jsxs)(`div`,{className:`grid min-h-[calc(100vh-80px)] sm:grid-cols-[240px_1fr]`,children:[(0,z.jsxs)(`aside`,{className:`hidden border-r border-slate-200 p-6 dark:border-zinc-800 sm:block`,"aria-label":`Workspace`,children:[(0,z.jsx)(`strong`,{children:`LoopX`}),(0,z.jsx)(`p`,{className:`mt-6 text-sm`,children:`Workspace`}),(0,z.jsx)(`p`,{className:`mt-8 text-xs text-slate-500`,children:`Goals`}),[1,2,3].map(e=>(0,z.jsx)(`div`,{className:`mt-4 h-8 rounded bg-slate-100 dark:bg-zinc-900`},e))]}),(0,z.jsx)(`div`,{className:`p-4 sm:p-8`,children:(0,z.jsx)(Jv,{"data-testid":`initial-status-state`,children:(0,z.jsx)(Yv,{className:`flex min-h-64 items-center justify-center p-6`,children:(0,z.jsxs)(`div`,{className:`max-w-xl text-center`,children:[e?(0,z.jsx)(Xp,{className:`mx-auto h-6 w-6 text-rose-600 dark:text-rose-300`}):(0,z.jsx)(Om,{className:`mx-auto h-6 w-6 animate-spin text-slate-500 dark:text-zinc-400`}),(0,z.jsx)(`p`,{className:`mt-3 text-sm font-medium`,children:e?`无法加载实时状态`:`正在加载实时状态`}),e?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`p`,{className:`mt-2 break-words text-sm leading-6 text-slate-500 dark:text-zinc-400`,children:o?`本地状态服务暂时未连接。升级或启动期间可能短暂断开,请重试;仍失败时重新打开 LoopX App,或运行 loopx doctor。`:e}),o?(0,z.jsx)(`p`,{className:`mt-2 text-xs leading-5 text-slate-400 dark:text-zinc-500`,children:`重新加载不会执行任务,也不会改变 Goal 配置。`}):null,(0,z.jsx)(`div`,{className:`mt-4 flex flex-wrap justify-center gap-2`,children:(0,z.jsxs)(qv,{disabled:t,onClick:n,children:[(0,z.jsx)(Om,{className:`h-4 w-4`}),`重试`]})})]}):(0,z.jsx)(`p`,{className:`mt-2 text-sm leading-6 text-slate-500 dark:text-zinc-400`,role:`status`,children:`正在连接 Workspace,Goal 列表将先出现,详细状态会逐个补齐。 / Connecting to your Workspace. Goals load independently.`})]})})})})]})]})})}function jS(){let e=OC.useSearch(),t=OC.useNavigate(),[n,r]=(0,R.useState)(`light`),[i,a]=(0,R.useState)(null),o=(0,R.useRef)(null),s=(0,R.useRef)(e.goalId);s.current=e.goalId;let[c,l]=(0,R.useState)(bp),[u,d]=(0,R.useState)({kind:`example`,label:`bundled example`}),[f,p]=(0,R.useState)(()=>Dx(window.localStorage,window.location.href)),[m,h]=(0,R.useState)(e.statusUrl),[g,_]=(0,R.useState)(null),[v,y]=(0,R.useState)(!1),[b,x]=(0,R.useState)({error:null,phase:`idle`}),[S,C]=(0,R.useState)(e.statusUrl.trim()||null),[w,T]=(0,R.useState)(!1),E=(0,R.useRef)(null),D=(0,R.useRef)(Bg(e.statusUrl.trim()||null)),O=!w&&u.kind===`example`?e.statusUrl.trim():``,k=S??O,ee=u.kind===`url`?u.label:Ix,A=!!(g&&S),j=Nx(f,S,ee,window.location.href),te=u.kind===`example`&&!w,ne=c.attention_queue,re=c.run_history,M=(0,R.useMemo)(()=>zx(re.goals,ne.items),[re.goals,ne.items]);function N(e,t,n=0){x({error:null,phase:`loading`}),Lx(Zm(e,`stopped`,window.location.href)).then(r=>{if(!Wg(D.current,t))return;let i=r.goal_projection?.registry_revision??null,a=t.registryRevision!==null&&t.registryRevision!==void 0&&i!==null&&t.registryRevision!==i;if(l(e=>p_(e,r)),a&&n<1){oe(e,{background:!0,resyncAttempt:n+1});return}x(a?{error:`Goal 状态在加载历史时发生变化,请重试。`,phase:`error`}:{error:null,phase:`ready`})}).catch(e=>{Wg(D.current,t)&&x({error:yp(e),phase:`error`})})}function ie(){let e=u.kind===`url`?u.label:m||Ix,t=Hg(D.current,e,{background:!0});if(i){oe(e);return}t&&N(e,t)}async function ae(e,n,r){if(r.background)return l(e=>p_(e,n)),!0;let i={kind:`url`,label:e};return D.current.loadedUrl=e,l(n),d(i),h(e),await t({search:t=>({...t,statusUrl:e})}),Ug(D.current,r)?(D.current.requestedUrl=null,C(null),!0):!1}async function oe(e,t={}){let n=e.trim(),r=t.background===!0;if(!n){r||_(`状态地址不能为空`);return}let c=Hg(D.current,n,{background:r,selectionRevision:t.selectionRevision});if(!c)return;o.current?.abort();let d=new AbortController;o.current=d,r||(E.current=null,T(!1),C(n),y(!0),_(null),x({error:null,phase:`idle`}));try{let e=await Cp(n,window.location.href).catch(()=>null);if(!Wg(D.current,c))return;if(e){let o=t.retryOnly&&u.kind===`url`&&u.label===n&&i?.directory.registry_revision===e.registry_revision?i.snapshots:{};a({directory:e,snapshots:o,errors:{}});let f={...e,goals:e.goals.filter(e=>!o[e.id])},p=!1,m=wp(e);if(r)l(m);else if(!await ae(n,m,c))return;if(x({error:null,phase:`loading`}),await Tp(n,window.location.href,f,(e,t,n)=>{n===`revision`&&(p=!0),a(r=>r&&{...r,snapshots:t?{...r.snapshots,[e]:t}:r.snapshots,errors:n?{...r.errors,[e]:n}:r.errors})},()=>Wg(D.current,c),()=>s.current,d.signal),p&&(t.resyncAttempt??0)<1&&Wg(D.current,c)){await oe(n,{resyncAttempt:1});return}Wg(D.current,c)&&x({error:null,phase:`ready`});return}let o=await Lx(Zm(n,`active`,window.location.href));if(!Wg(D.current,c)||(a(null),c.registryRevision=o.goal_projection?.registry_revision??null,!await ae(n,o,c)))return;if(o.goal_projection?.scope!==`active`||o.goal_projection.complete){x({error:null,phase:`ready`});return}N(n,c,t.resyncAttempt??0)}catch(e){if(!Ug(D.current,c))return;r||_(yp(e))}finally{!r&&Ug(D.current,c)&&y(!1)}}function P(e,t={}){o.current?.abort();let n=Vg(D.current,e.statusUrl);E.current=null,T(!1),C(e.statusUrl),y(!0),_(null),(async()=>{if(t.ensureTunnel&&e.kind===`ssh_tunnel`){let t=new URL(e.statusUrl,window.location.href).port;if(t)try{await Jy(e.label,t)}catch{}}D.current.selectionRevision===n&&await oe(e.statusUrl,{selectionRevision:n})})()}function F(e){p(e);try{Ox(window.localStorage,e)}catch{}}let I={activeSource:j,connectionState:v?`loading`:A?`error`:`connected`,errorMessage:A?`未切换到 ${S??`所选来源`}:${g}`:null,onAdd:e=>{let t=kx(f,e,window.location.href);return`error`in t?{error:t.error}:(F(t.catalog),P(t.source,{ensureTunnel:e.ensureTunnel}),{})},onRemove:e=>{F(Ax(f,e)),j.id===e&&P(Sx)},onSelect:e=>{let t=f.sources.find(t=>t.id===e);t&&P(t,{ensureTunnel:t.kind===`ssh_tunnel`})},sources:j.id===`temporary`?[...f.sources,j]:f.sources};(0,R.useEffect)(()=>{let t=e.statusUrl.trim();if(t){if(E.current===t||S&&S!==t)return;(u.kind!==`url`||u.label!==t)&&oe(t);return}E.current=null,!w&&(S||u.kind===`example`&&oe(Ix))},[w,S,e.statusUrl,u.kind,u.label]),(0,R.useEffect)(()=>{if(e.statusUrl&&u.kind===`example`)return;let n=new Set(M.map(e=>e.goal.id));if(M.length===0){e.goalId&&t({search:e=>({...e,goalId:``})});return}e.goalId&&!n.has(e.goalId)&&b.phase!==`loading`&&t({search:e=>({...e,goalId:``})})},[b.phase,M,t,e.goalId,e.statusUrl,u.kind]),(0,R.useEffect)(()=>{if(!i||v||!e.goalId||u.kind!==`url`)return;let t=i.directory.goals.find(t=>t.id===e.goalId);t?.activation_state===`stopped`&&!i.snapshots[t.id]&&!i.errors[t.id]&&oe(u.label,{retryOnly:!0})},[e.goalId,v,i,u]);function se(e){t({search:t=>({...t,goalId:e})})}return te?(0,z.jsx)(AS,{error:g,isLoading:v,onRetry:()=>void oe(k||Ix),requestedUrl:k||Ix,theme:n,toggleTheme:()=>r(n===`dark`?`light`:`dark`)}):(0,z.jsx)(kS,{goalArchiveLoadState:b,isLoading:v,onGoalActivationStateChange:(e,t)=>{D.current.projectionRevision+=1,l(n=>gp(n,e,t)),a(n=>n&&{...n,snapshots:Object.fromEntries(Object.entries(n.snapshots).map(([n,r])=>[n,gp(r,e,t)]))})},onGoalDeleted:e=>{D.current.projectionRevision+=1,l(t=>_p(t,e)),a(t=>t&&{...t,snapshots:Object.fromEntries(Object.entries(t.snapshots).filter(([t])=>t!==e))})},onSelectGoal:se,onReconcileStatus:()=>oe(u.kind===`url`?u.label:m||Ix,{background:!0}),onRetryGoalArchive:ie,onRefresh:()=>oe(u.kind===`url`?u.label:m||Ix,{retryOnly:!!(i&&Object.keys(i.errors).length)}),payload:c,progress:i,rows:M,selectedGoalId:e.goalId,statusSourceControl:I,theme:n,toggleTheme:()=>r(n===`dark`?`light`:`dark`)})}var MS=v_(`inline-flex items-center gap-1 rounded-md border px-2 py-0.5 text-xs font-medium`,{variants:{variant:{neutral:`border-slate-200 bg-white text-slate-700 dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-300`,success:`border-emerald-200 bg-emerald-50 text-emerald-800 dark:border-emerald-900 dark:bg-emerald-950 dark:text-emerald-200`,warning:`border-amber-200 bg-amber-50 text-amber-800 dark:border-amber-900 dark:bg-amber-950 dark:text-amber-200`,info:`border-sky-200 bg-sky-50 text-sky-800 dark:border-sky-900 dark:bg-sky-950 dark:text-sky-200`,danger:`border-rose-200 bg-rose-50 text-rose-800 dark:border-rose-900 dark:bg-rose-950 dark:text-rose-200`}},defaultVariants:{variant:`neutral`}});function NS({className:e,variant:t,...n}){return(0,z.jsx)(`span`,{className:Gv(MS({variant:t}),e),...n})}var PS=[{label:`status payload`,source:`apps/presentation/dashboard/src/data/status.ts`,detail:`status_contract, attention_queue, local_dashboard_api, run_history`},{label:`channel projection`,source:`apps/presentation/dashboard/src/data/goal-channel-frontstage.ts`,detail:`decision_frame, todos, gates, leases, artifacts, truth_contract`},{label:`public showcase catalog`,source:`docs/showcases/showcase-catalog.json`,detail:`case metadata, visual hints, evidence boundaries, story beats`},{label:`route smoke`,source:`apps/presentation/dashboard/smoke/frontstage-route-smoke.ts`,detail:`static route contract, source guards, component expectations`}],FS=[{axis:`schema`,current:`goal_channel_projection_v0`,proposed:`new optional projection field`,gate:`parser default plus route smoke assertion`},{axis:`truth`,current:`event ledger and active state remain source of truth`,proposed:`derived UI state only`,gate:`truth_contract must stay read-only`},{axis:`privacy`,current:`compact source refs and warnings`,proposed:`public-safe fixture field`,gate:`loopx check and browser fake-private fixture`},{axis:`interaction`,current:`render, filter, select, inspect`,proposed:`no browser write by default`,gate:`write affordance requires explicit loopback capability`}],IS=[{title:`Fixture sources`,body:`Use examples/status.example.json, browser-smoke fixtures, and docs/showcases/showcase-catalog.json.`},{title:`Required proof`,body:`Every projection addition needs parser coverage, route smoke assertions, and one browser or bundle check when UI output changes.`},{title:`Never include`,body:`Raw task text, trajectories, transcripts, local paths, private registry state, credentials, or internal document links.`}],LS=[`npm --prefix apps/presentation/dashboard run smoke:frontstage-route`,`npm --prefix apps/presentation/dashboard run smoke:frontstage-browser`,`npm --prefix apps/presentation/dashboard run smoke:frontstage-share-bundle`,`npm --prefix apps/presentation/dashboard run build`,`loopx check --scan-path apps/presentation/dashboard --scan-path docs/status-data-contract.md`],RS=[{name:`Projection lane`,badges:[`read-only`,`schema v0`],body:`Summarizes one compact projection lane without mutating the underlying LoopX state.`},{name:`Capability badge`,badges:[`loopback`,`dry-run`],body:`Shows an advertised local capability only after the status feed declares it.`},{name:`Boundary warning`,badges:[`public-safe`,`omitted`],body:`Names omitted private material and points contributors back to compact source references.`}];function zS({children:e,icon:t,title:n}){return(0,z.jsxs)(`section`,{className:`rounded-lg border border-slate-200 bg-white shadow-sm`,children:[(0,z.jsx)(`div`,{className:`flex items-center justify-between gap-3 border-b border-slate-200 px-4 py-3`,children:(0,z.jsxs)(`h2`,{className:`flex items-center gap-2 text-sm font-semibold text-slate-950`,children:[(0,z.jsx)(t,{className:`h-4 w-4 text-slate-500`}),n]})}),e]})}function BS(){return(0,z.jsx)(zS,{icon:Wp,title:`Status Contract Explorer`,children:(0,z.jsx)(`div`,{className:`grid gap-3 p-4 lg:grid-cols-2`,"data-testid":`developer-contract-explorer`,children:PS.map(e=>(0,z.jsxs)(`div`,{className:`rounded-md border border-slate-200 bg-slate-50 px-3 py-3`,children:[(0,z.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,z.jsx)(NS,{variant:`info`,children:e.label}),(0,z.jsx)(NS,{variant:`neutral`,children:`public contract`})]}),(0,z.jsx)(`div`,{className:`mt-2 break-words font-mono text-xs text-slate-700`,children:e.source}),(0,z.jsx)(`p`,{className:`mt-2 text-sm leading-6 text-slate-600`,children:e.detail})]},e.label))})})}function VS(){return(0,z.jsx)(zS,{icon:um,title:`Projection Diffing`,children:(0,z.jsx)(`div`,{className:`overflow-x-auto`,"data-testid":`developer-projection-diffing`,children:(0,z.jsxs)(`table`,{className:`min-w-full border-separate border-spacing-0 text-left text-sm`,children:[(0,z.jsx)(`thead`,{children:(0,z.jsxs)(`tr`,{className:`bg-slate-50 text-xs uppercase tracking-normal text-slate-500`,children:[(0,z.jsx)(`th`,{className:`border-b border-slate-200 px-4 py-3 font-semibold`,children:`Axis`}),(0,z.jsx)(`th`,{className:`border-b border-slate-200 px-4 py-3 font-semibold`,children:`Current`}),(0,z.jsx)(`th`,{className:`border-b border-slate-200 px-4 py-3 font-semibold`,children:`Proposed`}),(0,z.jsx)(`th`,{className:`border-b border-slate-200 px-4 py-3 font-semibold`,children:`Gate`})]})}),(0,z.jsx)(`tbody`,{children:FS.map(e=>(0,z.jsxs)(`tr`,{className:`align-top`,children:[(0,z.jsx)(`td`,{className:`border-b border-slate-100 px-4 py-3 font-semibold text-slate-950`,children:e.axis}),(0,z.jsx)(`td`,{className:`border-b border-slate-100 px-4 py-3 text-slate-600`,children:e.current}),(0,z.jsx)(`td`,{className:`border-b border-slate-100 px-4 py-3 text-slate-600`,children:e.proposed}),(0,z.jsx)(`td`,{className:`border-b border-slate-100 px-4 py-3 text-slate-600`,children:e.gate})]},e.axis))})]})})})}function HS(){return(0,z.jsx)(zS,{icon:om,title:`Fixture Generation`,children:(0,z.jsx)(`div`,{className:`grid gap-3 p-4 md:grid-cols-3`,"data-testid":`developer-fixture-generation`,children:IS.map(e=>(0,z.jsxs)(`div`,{className:`rounded-md border border-slate-200 bg-slate-50 px-3 py-3`,children:[(0,z.jsx)(`div`,{className:`text-sm font-semibold text-slate-950`,children:e.title}),(0,z.jsx)(`p`,{className:`mt-2 text-sm leading-6 text-slate-600`,children:e.body})]},e.title))})})}function US(){return(0,z.jsx)(zS,{icon:Qp,title:`Smoke Checklist`,children:(0,z.jsx)(`div`,{className:`space-y-2 p-4`,"data-testid":`developer-smoke-checklist`,children:LS.map(e=>(0,z.jsxs)(`div`,{className:`flex items-start gap-3 rounded-md border border-slate-200 bg-slate-50 px-3 py-2`,children:[(0,z.jsx)(Vp,{className:`mt-0.5 h-4 w-4 shrink-0 text-emerald-600`}),(0,z.jsx)(`code`,{className:`break-all text-xs font-semibold leading-5 text-slate-700`,children:e})]},e))})})}function WS(){return(0,z.jsx)(zS,{icon:$p,title:`Component Examples`,children:(0,z.jsx)(`div`,{className:`grid gap-3 p-4 lg:grid-cols-3`,"data-testid":`developer-component-examples`,children:RS.map(e=>(0,z.jsxs)(`article`,{className:`rounded-md border border-slate-200 bg-slate-50 p-3`,children:[(0,z.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:e.badges.map(e=>(0,z.jsx)(NS,{variant:e===`read-only`||e===`public-safe`?`success`:`neutral`,children:e},e))}),(0,z.jsx)(`h3`,{className:`mt-3 text-sm font-semibold leading-6 text-slate-950`,children:e.name}),(0,z.jsx)(`p`,{className:`mt-2 text-sm leading-6 text-slate-600`,children:e.body})]},e.name))})})}function GS(){return(0,z.jsx)(`main`,{className:`min-h-screen bg-[#f7f7f4] px-4 py-4 text-slate-950 sm:px-5`,"data-testid":`frontstage-developer-cockpit`,children:(0,z.jsxs)(`div`,{className:`mx-auto grid max-w-[1500px] gap-4 xl:grid-cols-[260px_minmax(0,1fr)]`,children:[(0,z.jsxs)(`aside`,{className:`rounded-lg border border-slate-200 bg-white p-4 shadow-sm xl:sticky xl:top-4 xl:self-start`,children:[(0,z.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,z.jsx)(`div`,{className:`flex h-9 w-9 items-center justify-center rounded-md border border-slate-200 bg-slate-950 text-white`,children:(0,z.jsx)(Vm,{className:`h-4 w-4`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`text-sm font-semibold`,children:`Developer Cockpit`}),(0,z.jsx)(`div`,{className:`text-xs text-slate-500`,children:`Projection extension`})]})]}),(0,z.jsxs)(`div`,{className:`mt-4 grid gap-2`,children:[(0,z.jsxs)(`a`,{className:`flex items-center gap-2 rounded-md border border-slate-200 px-3 py-2 text-sm font-medium`,href:`https://huangruiteng.github.io/loopx/`,children:[(0,z.jsx)(pm,{className:`h-4 w-4`}),`LoopX home`]}),(0,z.jsxs)(`a`,{className:`flex items-center gap-2 rounded-md border border-slate-200 px-3 py-2 text-sm font-medium`,href:`https://huangruiteng.github.io/loopx/docs/showcases/index.en.html`,children:[(0,z.jsx)(im,{className:`h-4 w-4`}),`Public cases`]}),(0,z.jsxs)(`a`,{className:`flex items-center gap-2 rounded-md bg-slate-950 px-3 py-2 text-sm font-medium text-white`,href:`/chat/developers/projections/`,children:[(0,z.jsx)($p,{className:`h-4 w-4`}),`Developer cockpit`]})]}),(0,z.jsxs)(`div`,{className:`mt-5 space-y-2 rounded-md border border-emerald-200 bg-emerald-50 p-3 text-xs leading-5 text-emerald-950`,children:[(0,z.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,z.jsx)(NS,{variant:`success`,children:`read-only`}),(0,z.jsx)(NS,{variant:`neutral`,children:`public fixtures`})]}),(0,z.jsx)(`p`,{children:`This route uses static public contracts only; live status feeds, registry files, and browser write APIs stay outside the cockpit.`})]})]}),(0,z.jsxs)(`section`,{className:`space-y-4`,children:[(0,z.jsx)(`div`,{className:`rounded-lg border border-slate-200 bg-white px-5 py-5 shadow-sm`,children:(0,z.jsxs)(`div`,{className:`flex flex-wrap items-start justify-between gap-4`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,z.jsx)(NS,{variant:`info`,children:`developers/projections`}),(0,z.jsx)(NS,{variant:`success`,children:`public-safe`}),(0,z.jsx)(NS,{variant:`neutral`,children:`no browser writes`})]}),(0,z.jsx)(`h1`,{className:`mt-3 text-3xl font-semibold tracking-normal text-slate-950`,children:`LoopX Projection Developer Cockpit`}),(0,z.jsx)(`p`,{className:`mt-2 max-w-3xl text-sm leading-6 text-slate-600`,children:`A read-only contributor workbench for adding dashboard/frontstage projections without reverse-engineering the large operator page.`})]}),(0,z.jsxs)(`div`,{className:`grid min-w-[260px] gap-2 text-sm`,children:[(0,z.jsxs)(`div`,{className:`rounded-md border border-slate-200 bg-slate-50 px-3 py-2`,children:[(0,z.jsx)(`div`,{className:`text-[11px] font-semibold uppercase tracking-normal text-slate-500`,children:`Source of truth`}),(0,z.jsx)(`div`,{className:`mt-1 font-semibold text-slate-950`,children:`status contract + compact fixtures`})]}),(0,z.jsxs)(`div`,{className:`rounded-md border border-slate-200 bg-slate-50 px-3 py-2`,children:[(0,z.jsx)(`div`,{className:`text-[11px] font-semibold uppercase tracking-normal text-slate-500`,children:`Boundary`}),(0,z.jsx)(`div`,{className:`mt-1 font-semibold text-slate-950`,children:`read-only extension surface`})]})]})]})}),(0,z.jsxs)(`div`,{className:`grid gap-4 xl:grid-cols-2`,children:[(0,z.jsx)(BS,{}),(0,z.jsx)(VS,{})]}),(0,z.jsxs)(`div`,{className:`grid gap-4 xl:grid-cols-[minmax(0,1fr)_420px]`,children:[(0,z.jsx)(HS,{}),(0,z.jsx)(US,{})]}),(0,z.jsx)(WS,{}),(0,z.jsx)(zS,{icon:Im,title:`Extension Boundary`,children:(0,z.jsxs)(`div`,{className:`grid gap-3 p-4 md:grid-cols-3`,"data-testid":`developer-extension-boundary`,children:[(0,z.jsxs)(`div`,{className:`rounded-md border border-emerald-200 bg-emerald-50 px-3 py-3`,children:[(0,z.jsx)(`div`,{className:`text-sm font-semibold text-slate-950`,children:`Allowed`}),(0,z.jsx)(`p`,{className:`mt-2 text-sm leading-6 text-slate-600`,children:`Versioned parser defaults, public fixtures, read-only route panels, and focused smoke assertions.`})]}),(0,z.jsxs)(`div`,{className:`rounded-md border border-amber-200 bg-amber-50 px-3 py-3`,children:[(0,z.jsx)(`div`,{className:`text-sm font-semibold text-slate-950`,children:`Review`}),(0,z.jsx)(`p`,{className:`mt-2 text-sm leading-6 text-slate-600`,children:`New dashboard dependencies, status contract fields, loopback capability display, and browser-visible workflows.`})]}),(0,z.jsxs)(`div`,{className:`rounded-md border border-rose-200 bg-rose-50 px-3 py-3`,children:[(0,z.jsx)(`div`,{className:`text-sm font-semibold text-slate-950`,children:`Stop`}),(0,z.jsx)(`p`,{className:`mt-2 text-sm leading-6 text-slate-600`,children:`Credentials, private registry material, raw logs, transcripts, production actions, or default browser write authority.`})]})]})})]})]})})}var KS=J({value:G().finite(),total:G().finite().positive().optional(),unit:W().optional(),higher_is_better:K()}).passthrough(),qS=gd(W(),G().finite()).default({}),JS=J({outcome_status:W().optional(),failure_class:W(),causal_summary:W(),expectedness:W(),implication:W(),next_probe:W(),confidence:W(),evidence_refs:q(W()).optional()}).passthrough(),YS=J({arm_id:W(),selected_run_id:W().nullable(),score_countable:K(),metrics:gd(W(),KS),effort:qS,insight:JS.nullable().optional()}),XS=J({run_id:W(),case_id:W(),arm_id:W(),arm_role:W(),status:W(),protocol_id:W(),runner_revision:W().optional(),observed_at:W(),metrics:gd(W(),KS),countability:J({integrity_qualified:K(),official_result_present:K(),score_countable:K()}).passthrough(),treatment_fidelity:W(),effort:qS,redacted_insight:JS.nullable().optional(),upload_provenance:J({producer_id:W(),producer_version:W(),observed_at:W(),source_revision:W()}).passthrough()}).passthrough(),ZS=J({case_denominator:G().int().nonnegative(),value_sum:G().finite(),value_mean:G().finite().nullable(),value_median:G().finite().nullable(),value_min:G().finite().nullable(),value_max:G().finite().nullable(),case_macro_rate:G().finite().optional(),suite_micro_rate:G().finite().optional(),suite_micro_numerator:G().finite().optional(),suite_micro_denominator:G().finite().positive().optional()}).passthrough(),QS=J({arm_id:W(),arm_role:W(),factor_assignments:gd(W(),W()),protocol_counts:gd(W(),G().int().nonnegative()).default({}),runner_revision_counts:gd(W(),G().int().nonnegative()).default({}),orchestrator_runtime_counts:gd(W(),G().int().nonnegative()).default({}),intended_case_count:G().int().positive(),run_count:G().int().nonnegative(),terminal_run_count:G().int().nonnegative(),selected_score_countable_case_count:G().int().nonnegative(),coverage_rate:G().finite().min(0).max(1),metrics:gd(W(),ZS),binary_outcomes:gd(W(),J({success_count:G().int().nonnegative(),case_denominator:G().int().nonnegative(),success_rate:G().finite().min(0).max(1).nullable()})),effort:gd(W(),J({denominator:G().int().nonnegative(),mean:G().finite().nullable(),median:G().finite().nullable()})),failure_class_counts:gd(W(),G().int().nonnegative())}).passthrough(),$S=J({baseline_value:G().finite(),candidate_value:G().finite(),delta:G().finite(),direction:Y([`improved`,`flat`,`regressed`]).optional()}).passthrough(),eC=J({comparison_id:W(),comparison_anchor_run_id:W(),candidate_run_id:W(),candidate_arm_id:W(),primary_metric:W(),matched_pair_countable:X(!0),metric_deltas:gd(W(),$S)}).passthrough(),tC=J({ok:X(!0),schema_version:X(`benchmark_study_dashboard_v0`),benchmark_id:W(),study_id:W(),status:Y([`complete`,`provisional`]),design:J({protocol_id:W(),comparison_protocol_id:W(),baseline_arm_id:W(),case_set:J({case_set_id:W(),case_ids:q(W())}),metric_catalog:q(J({metric_name:W(),role:Y([`primary`,`guardrail`,`supporting`]),unit:W().optional(),higher_is_better:K(),binary:K()})),labels:gd(W(),W())}).passthrough(),campaign:J({intended_case_count:G().int().positive(),intended_arm_count:G().int().positive(),intended_cell_denominator:G().int().positive(),selected_score_countable_cell_count:G().int().nonnegative(),selected_score_countable_coverage_rate:G().finite().min(0).max(1),complete_declared_design_case_count:G().int().nonnegative(),ambiguous_score_countable_cell_count:G().int().nonnegative(),in_flight_run_count:G().int().nonnegative(),matched_pair_countable_count:G().int().nonnegative(),factorial_contrast_count:G().int().nonnegative(),factorial_contrast_countable_count:G().int().nonnegative(),runtime_observation_count:G().int().nonnegative(),runtime_classification_counts:gd(W(),G().int().nonnegative())}),arms:q(QS),contrasts:gd(W(),J({matched_pair_denominator:G().int().nonnegative(),primary_metric_directions:J({improved:G().int().nonnegative(),flat:G().int().nonnegative(),regressed:G().int().nonnegative()}),binary_metric_transitions:gd(W(),J({"0_to_1":G().int().nonnegative(),"1_to_0":G().int().nonnegative(),same:G().int().nonnegative()}))})),cases:q(J({case_id:W(),complete_declared_design:K(),arms:q(YS),eligible_comparisons:q(eC),largest_eligible_primary_contrast:eC.nullable()})),runs:q(XS),authority:J({score_source:W(),matched_comparison_source:W(),factorial_comparison_source:W().nullable(),manifest_changes_scores:X(!1),dashboard_is_execution_authority:X(!1)}),public_boundary:J({raw_task_recorded:X(!1),raw_trajectory_recorded:X(!1),hidden_evaluation_recorded:X(!1),raw_verifier_output_recorded:X(!1),credentials_recorded:X(!1),local_paths_recorded:X(!1)}),write_performed:X(!1),network_access_performed:X(!1)});function nC(e){return tC.parse(e)}function rC(e,t){let n=new URL(t),r=new URL(e||`/benchmark-study.example.json`,n);if(!new Set([`http:`,`https:`]).has(r.protocol))throw Error(`Benchmark dashboard source must use HTTP or HTTPS`);if(r.origin!==n.origin)throw Error(`Benchmark dashboard source must use same-origin local readback`);return r.toString()}var iC=[{id:`campaign`,label:`Campaign`},{id:`arms`,label:`Arms`},{id:`cases`,label:`Cases`},{id:`runs`,label:`Runs`}];function aC(e){return e==null?`—`:`${(e*100).toFixed(e>=.995?0:1)}%`}function oC(e){return e==null?`—`:new Intl.NumberFormat(`en`,{maximumFractionDigits:2,notation:`compact`}).format(e)}function sC(e){if(e==null)return`—`;let t=e/6e4;return t>=120?`${(t/60).toFixed(1)} h`:`${oC(t)} min`}function cC(e){let t=Object.entries(e);return t.length?t.map(([e,t])=>`${e} (${t})`).join(`, `):`—`}function lC(e){if(!e)return`—`;let t=e.total==null?oC(e.value):`${oC(e.value)}/${oC(e.total)}`;return e.unit?`${t} ${e.unit}`:t}function uC(e,t){let n=e.metrics[t];return!n||n.case_denominator===0?`—`:n.suite_micro_rate==null?`${oC(n.value_mean)} mean`:`${aC(n.suite_micro_rate)} · ${oC(n.suite_micro_numerator)}/${oC(n.suite_micro_denominator)}`}function dC(e,t){let n=e.largest_eligible_primary_contrast,r=n?.metric_deltas[t];if(!n||!r)return null;let i=r.delta>0?`+`:``;return{direction:r.direction,text:`${n.candidate_arm_id}: ${i}${oC(r.delta)}`}}function fC({children:e,tone:t=`neutral`}){return(0,z.jsx)(`span`,{className:`benchmark-state benchmark-state-${t}`,children:e})}function pC({packet:e,primaryMetric:t}){return(0,z.jsxs)(`div`,{className:`benchmark-view-stack`,children:[(0,z.jsxs)(`section`,{"aria-labelledby":`arm-summary-title`,children:[(0,z.jsxs)(`div`,{className:`benchmark-section-heading`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`p`,{className:`benchmark-kicker`,children:`ARM SUMMARY`}),(0,z.jsx)(`h2`,{id:`arm-summary-title`,children:`Comparable outcomes, denominator first`})]}),(0,z.jsx)(`p`,{children:`Only one score-countable run per declared case × arm cell is selected.`})]}),(0,z.jsx)(`div`,{className:`benchmark-arm-grid`,children:e.arms.map(e=>{let n=Object.values(e.binary_outcomes)[0];return(0,z.jsxs)(`article`,{className:`benchmark-arm-card`,children:[(0,z.jsxs)(`div`,{className:`benchmark-card-heading`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`span`,{className:`benchmark-mono`,children:e.arm_role}),(0,z.jsx)(`h3`,{children:e.arm_id})]}),(0,z.jsx)(fC,{tone:e.coverage_rate===1?`success`:`warning`,children:e.coverage_rate===1?`Complete`:`Provisional`})]}),(0,z.jsxs)(`dl`,{className:`benchmark-stat-list`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsxs)(`dt`,{children:[`Primary · `,t]}),(0,z.jsx)(`dd`,{children:uC(e,t)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Score-countable coverage`}),(0,z.jsxs)(`dd`,{children:[e.selected_score_countable_case_count,`/`,e.intended_case_count]})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Binary success`}),(0,z.jsx)(`dd`,{children:n?`${n.success_count}/${n.case_denominator}`:`Not declared`})]})]})]},e.arm_id)})})]}),(0,z.jsxs)(`section`,{"aria-labelledby":`contrast-title`,children:[(0,z.jsxs)(`div`,{className:`benchmark-section-heading`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`p`,{className:`benchmark-kicker`,children:`MATCHED CONTRASTS`}),(0,z.jsx)(`h2`,{id:`contrast-title`,children:`Direction counts on eligible pairs`})]}),(0,z.jsx)(`p`,{children:`Raw run volume is never used as a comparison denominator.`})]}),(0,z.jsx)(`div`,{className:`benchmark-table-shell`,children:(0,z.jsxs)(`table`,{children:[(0,z.jsx)(`thead`,{children:(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`th`,{children:`Candidate arm`}),(0,z.jsx)(`th`,{children:`Matched denominator`}),(0,z.jsx)(`th`,{children:`Improved`}),(0,z.jsx)(`th`,{children:`Flat`}),(0,z.jsx)(`th`,{children:`Regressed`}),(0,z.jsx)(`th`,{children:`Binary transitions`})]})}),(0,z.jsxs)(`tbody`,{children:[Object.entries(e.contrasts).map(([e,t])=>(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`td`,{children:(0,z.jsx)(`strong`,{children:e})}),(0,z.jsx)(`td`,{children:t.matched_pair_denominator}),(0,z.jsx)(`td`,{className:`benchmark-positive`,children:t.primary_metric_directions.improved}),(0,z.jsx)(`td`,{children:t.primary_metric_directions.flat}),(0,z.jsx)(`td`,{className:`benchmark-negative`,children:t.primary_metric_directions.regressed}),(0,z.jsx)(`td`,{children:Object.entries(t.binary_metric_transitions).map(([e,t])=>`${e}: 0→1 ${t[`0_to_1`]}, 1→0 ${t[`1_to_0`]}, same ${t.same}`).join(` · `)||`—`})]},e)),Object.keys(e.contrasts).length===0&&(0,z.jsx)(`tr`,{children:(0,z.jsx)(`td`,{colSpan:6,children:`No matched comparisons are countable yet.`})})]})]})})]}),(0,z.jsxs)(`section`,{"aria-labelledby":`runtime-health-title`,children:[(0,z.jsxs)(`div`,{className:`benchmark-section-heading`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`p`,{className:`benchmark-kicker`,children:`RUNTIME HEALTH`}),(0,z.jsx)(`h2`,{id:`runtime-health-title`,children:`Qualified observations, without execution authority`})]}),(0,z.jsxs)(`p`,{children:[e.campaign.runtime_observation_count,` public-safe runtime observations.`]})]}),(0,z.jsxs)(`div`,{className:`benchmark-runtime-list`,children:[Object.entries(e.campaign.runtime_classification_counts).map(([e,t])=>(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`span`,{children:e}),(0,z.jsx)(`strong`,{children:t})]},e)),e.campaign.runtime_observation_count===0&&(0,z.jsx)(`p`,{className:`benchmark-muted`,children:`No runtime observations uploaded.`})]})]})]})}function mC({packet:e}){return(0,z.jsx)(`div`,{className:`benchmark-detail-grid`,children:e.arms.map(t=>(0,z.jsxs)(`article`,{className:`benchmark-detail-card`,children:[(0,z.jsxs)(`div`,{className:`benchmark-card-heading`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`span`,{className:`benchmark-mono`,children:t.arm_role}),(0,z.jsx)(`h2`,{children:t.arm_id})]}),(0,z.jsxs)(fC,{tone:t.coverage_rate===1?`success`:`warning`,children:[t.selected_score_countable_case_count,`/`,t.intended_case_count,` countable`]})]}),(0,z.jsx)(`div`,{className:`benchmark-factor-row`,children:Object.entries(t.factor_assignments).map(([e,t])=>(0,z.jsxs)(`span`,{children:[e,`: `,(0,z.jsx)(`strong`,{children:t})]},e))}),(0,z.jsxs)(`dl`,{className:`benchmark-stat-list`,children:[e.design.metric_catalog.map(e=>(0,z.jsxs)(`div`,{children:[(0,z.jsxs)(`dt`,{children:[e.role,` · `,e.metric_name]}),(0,z.jsx)(`dd`,{children:uC(t,e.metric_name)})]},e.metric_name)),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Runs terminal / observed`}),(0,z.jsxs)(`dd`,{children:[t.terminal_run_count,`/`,t.run_count]})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Median duration`}),(0,z.jsx)(`dd`,{children:sC(t.effort.duration_ms?.median)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Protocols`}),(0,z.jsx)(`dd`,{children:cC(t.protocol_counts)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Runner revisions`}),(0,z.jsx)(`dd`,{children:cC(t.runner_revision_counts)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Orchestrator runtimes`}),(0,z.jsxs)(`dd`,{children:[Object.keys(t.orchestrator_runtime_counts).length||0,` distinct`]})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Failure classes`}),(0,z.jsx)(`dd`,{children:cC(t.failure_class_counts)})]})]})]},t.arm_id))})}function hC({packet:e,primaryMetric:t,onOpenRun:n}){return(0,z.jsx)(`div`,{className:`benchmark-table-shell benchmark-wide-table`,children:(0,z.jsxs)(`table`,{children:[(0,z.jsx)(`thead`,{children:(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`th`,{children:`Case`}),(0,z.jsx)(`th`,{children:`Design status`}),(0,z.jsx)(`th`,{children:`Largest eligible delta`}),e.arms.map(e=>(0,z.jsx)(`th`,{children:e.arm_id},e.arm_id))]})}),(0,z.jsx)(`tbody`,{children:e.cases.map(r=>{let i=dC(r,t);return(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`td`,{children:(0,z.jsx)(`strong`,{children:r.case_id})}),(0,z.jsx)(`td`,{children:(0,z.jsx)(fC,{tone:r.complete_declared_design?`success`:`warning`,children:r.complete_declared_design?`Complete`:`Provisional`})}),(0,z.jsx)(`td`,{className:i?.direction===`improved`?`benchmark-positive`:i?.direction===`regressed`?`benchmark-negative`:void 0,children:i?.text??`—`}),r.arms.map(r=>(0,z.jsx)(`td`,{children:r.selected_run_id&&r.score_countable?(0,z.jsxs)(`button`,{className:`benchmark-cell-link`,onClick:()=>n(r.selected_run_id),type:`button`,children:[(0,z.jsxs)(`span`,{children:[t,`: `,lC(r.metrics[t])]}),e.design.metric_catalog.filter(e=>e.metric_name!==t).map(e=>(0,z.jsxs)(`small`,{className:`benchmark-cell-metric`,children:[e.metric_name,`: `,lC(r.metrics[e.metric_name])]},e.metric_name)),(0,z.jsxs)(`small`,{children:[`Countable · `,sC(r.effort.duration_ms),` `,(0,z.jsx)(Rp,{"aria-hidden":`true`,size:12})]}),r.insight&&(0,z.jsxs)(`small`,{children:[r.insight.failure_class,` · `,r.insight.confidence]})]}):(0,z.jsx)(`span`,{className:`benchmark-muted`,children:`Not countable`})},r.arm_id))]},r.case_id)})})]})})}function gC({run:e,packet:t}){return(0,z.jsxs)(`aside`,{"aria-label":`Run detail for ${e.run_id}`,className:`benchmark-run-detail`,children:[(0,z.jsxs)(`div`,{className:`benchmark-card-heading`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`span`,{className:`benchmark-mono`,children:`RUN DETAIL`}),(0,z.jsx)(`h2`,{children:e.run_id})]}),(0,z.jsx)(fC,{tone:e.countability.score_countable?`success`:`warning`,children:e.countability.score_countable?`Score-countable`:`Diagnostic only`})]}),(0,z.jsxs)(`dl`,{className:`benchmark-stat-list benchmark-run-facts`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Case / arm`}),(0,z.jsxs)(`dd`,{children:[e.case_id,` · `,e.arm_id]})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Lifecycle`}),(0,z.jsxs)(`dd`,{children:[e.status,` · `,e.observed_at]})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Protocol`}),(0,z.jsx)(`dd`,{children:e.protocol_id})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Qualification`}),(0,z.jsxs)(`dd`,{children:[`Integrity `,e.countability.integrity_qualified?`qualified`:`not qualified`,` · result `,e.countability.official_result_present?`present`:`missing`]})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Treatment fidelity`}),(0,z.jsx)(`dd`,{children:e.treatment_fidelity})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Effort`}),(0,z.jsxs)(`dd`,{children:[sC(e.effort.duration_ms),` · `,oC(e.effort.agent_steps),` steps · `,oC(e.effort.token_count),` tokens`]})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Runner revision`}),(0,z.jsx)(`dd`,{children:e.runner_revision??`—`})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Upload provenance`}),(0,z.jsxs)(`dd`,{children:[e.upload_provenance.producer_id,` · `,e.upload_provenance.source_revision]})]})]}),(0,z.jsx)(`div`,{className:`benchmark-run-metrics`,children:t.design.metric_catalog.map(t=>(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`span`,{children:t.metric_name}),(0,z.jsx)(`strong`,{children:lC(e.metrics[t.metric_name])})]},t.metric_name))}),e.redacted_insight&&(0,z.jsxs)(`div`,{className:`benchmark-insight`,children:[(0,z.jsxs)(`span`,{className:`benchmark-mono`,children:[`REDACTED CASE INSIGHT · `,e.redacted_insight.confidence]}),(0,z.jsx)(`p`,{children:e.redacted_insight.causal_summary}),(0,z.jsxs)(`small`,{children:[`Implication: `,e.redacted_insight.implication]}),(0,z.jsx)(`br`,{}),(0,z.jsxs)(`small`,{children:[`Next probe: `,e.redacted_insight.next_probe]}),!!e.redacted_insight.evidence_refs?.length&&(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`br`,{}),(0,z.jsxs)(`small`,{children:[`Evidence: `,e.redacted_insight.evidence_refs.join(`, `)]})]})]})]})}function _C({packet:e,selectedRunId:t,onSelectRun:n}){let r=e.runs.find(e=>e.run_id===t)??e.runs[0];return(0,z.jsxs)(`div`,{className:`benchmark-runs-layout`,children:[(0,z.jsx)(`div`,{className:`benchmark-table-shell`,children:(0,z.jsxs)(`table`,{children:[(0,z.jsx)(`thead`,{children:(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`th`,{children:`Run`}),(0,z.jsx)(`th`,{children:`Case`}),(0,z.jsx)(`th`,{children:`Arm`}),(0,z.jsx)(`th`,{children:`Status`}),(0,z.jsx)(`th`,{children:`Countability`})]})}),(0,z.jsx)(`tbody`,{children:e.runs.map(e=>(0,z.jsxs)(`tr`,{"aria-selected":e.run_id===r?.run_id,children:[(0,z.jsx)(`td`,{children:(0,z.jsx)(`button`,{className:`benchmark-run-link`,onClick:()=>n(e.run_id),type:`button`,children:e.run_id})}),(0,z.jsx)(`td`,{children:e.case_id}),(0,z.jsx)(`td`,{children:e.arm_id}),(0,z.jsx)(`td`,{children:e.status}),(0,z.jsx)(`td`,{children:e.countability.score_countable?`Score-countable`:`Diagnostic only`})]},e.run_id))})]})}),r&&(0,z.jsx)(gC,{packet:e,run:r})]})}function vC(){let e=NC.useSearch(),t=NC.useNavigate(),[n,r]=(0,R.useState)(null),[i,a]=(0,R.useState)(null),[o,s]=(0,R.useState)(0),c=(0,R.useMemo)(()=>{let t=e.dashboardUrl||`/chat/benchmark-study.example.json`;try{return{url:rC(t,window.location.href),error:null}}catch(e){return{url:``,error:e instanceof Error?e.message:`Invalid dashboard source`}}},[e.dashboardUrl]);if((0,R.useEffect)(()=>{let e=!0;return r(null),a(null),c.error?(a(c.error),()=>{e=!1}):(fetch(c.url,{cache:`no-store`}).then(async e=>{if(!e.ok)throw Error(`HTTP ${e.status} while loading the dashboard packet`);return nC(await e.json())}).then(t=>{e&&r(t)}).catch(t=>{e&&a(t instanceof Error?t.message:`Unable to load dashboard packet`)}),()=>{e=!1})},[o,c]),(0,R.useEffect)(()=>{n&&(document.title=`${n.design.labels.title??n.study_id} · LoopX Benchmark`)},[n]),i)return(0,z.jsxs)(`main`,{className:`benchmark-page benchmark-loading`,children:[(0,z.jsx)(Xp,{"aria-hidden":`true`}),(0,z.jsx)(`h1`,{children:`Dashboard packet unavailable`}),(0,z.jsx)(`p`,{children:i}),(0,z.jsxs)(`button`,{onClick:()=>s(e=>e+1),type:`button`,children:[(0,z.jsx)(Om,{"aria-hidden":`true`,size:16}),` Retry readback`]})]});if(!n)return(0,z.jsxs)(`main`,{"aria-busy":`true`,className:`benchmark-page benchmark-loading`,children:[(0,z.jsx)(Fp,{"aria-hidden":`true`}),(0,z.jsx)(`h1`,{children:`Reading benchmark study`}),(0,z.jsx)(`p`,{children:`Validating the public-safe dashboard packet…`})]});let l=n.design.metric_catalog.find(e=>e.role===`primary`)?.metric_name??`primary`,u=(n,r=e.runId)=>t({search:e=>({...e,view:n,runId:r})}),d=new URL(c.url).pathname;return(0,z.jsxs)(`main`,{className:`benchmark-page`,children:[(0,z.jsxs)(`header`,{className:`benchmark-hero`,children:[(0,z.jsxs)(`div`,{className:`benchmark-hero-topline`,children:[(0,z.jsx)(`a`,{className:`benchmark-wordmark`,href:`/chat/`,children:`LoopX`}),(0,z.jsxs)(`div`,{className:`benchmark-readonly`,children:[(0,z.jsx)(Im,{"aria-hidden":`true`,size:15}),` Derived read-only projection`]})]}),(0,z.jsxs)(`div`,{className:`benchmark-hero-grid`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsxs)(`p`,{className:`benchmark-kicker`,children:[`BENCHMARK STUDY / `,n.benchmark_id]}),(0,z.jsxs)(`div`,{className:`benchmark-title-row`,children:[(0,z.jsx)(`h1`,{children:n.design.labels.title??n.study_id}),(0,z.jsx)(fC,{tone:n.status===`complete`?`success`:`warning`,children:n.status})]}),(0,z.jsx)(`p`,{className:`benchmark-lead`,children:`One declared study, explicit denominators, and the same countability rules from campaign summary to exact run.`})]}),(0,z.jsxs)(`dl`,{className:`benchmark-identity`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Study`}),(0,z.jsx)(`dd`,{children:n.study_id})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Protocol`}),(0,z.jsx)(`dd`,{children:n.design.protocol_id})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Case set`}),(0,z.jsx)(`dd`,{children:n.design.case_set.case_set_id})]})]})]}),(0,z.jsxs)(`div`,{className:`benchmark-kpi-grid`,children:[(0,z.jsxs)(`article`,{children:[(0,z.jsx)(tm,{"aria-hidden":`true`}),(0,z.jsx)(`span`,{children:`Score-countable cells`}),(0,z.jsxs)(`strong`,{children:[n.campaign.selected_score_countable_cell_count,(0,z.jsxs)(`small`,{children:[` / `,n.campaign.intended_cell_denominator]})]}),(0,z.jsxs)(`p`,{children:[aC(n.campaign.selected_score_countable_coverage_rate),` declared coverage`]})]}),(0,z.jsxs)(`article`,{children:[(0,z.jsx)(Zp,{"aria-hidden":`true`}),(0,z.jsx)(`span`,{children:`Complete designs`}),(0,z.jsxs)(`strong`,{children:[n.campaign.complete_declared_design_case_count,(0,z.jsxs)(`small`,{children:[` / `,n.campaign.intended_case_count]})]}),(0,z.jsx)(`p`,{children:`Cases with every declared arm`})]}),(0,z.jsxs)(`article`,{children:[(0,z.jsx)(Rp,{"aria-hidden":`true`}),(0,z.jsx)(`span`,{children:`Matched comparisons`}),(0,z.jsx)(`strong`,{children:n.campaign.matched_pair_countable_count}),(0,z.jsx)(`p`,{children:`Eligible pairs only`})]}),(0,z.jsxs)(`article`,{children:[(0,z.jsx)(Fp,{"aria-hidden":`true`}),(0,z.jsx)(`span`,{children:`In flight`}),(0,z.jsx)(`strong`,{children:n.campaign.in_flight_run_count}),(0,z.jsx)(`p`,{children:n.status===`provisional`?`Coverage remains provisional`:`Declared coverage complete`})]})]})]}),(0,z.jsxs)(`nav`,{"aria-label":`Benchmark dashboard views`,className:`benchmark-tabs`,children:[iC.map(t=>(0,z.jsx)(`button`,{"aria-current":e.view===t.id?`page`:void 0,onClick:()=>u(t.id),type:`button`,children:t.label},t.id)),(0,z.jsxs)(`button`,{className:`benchmark-refresh`,onClick:()=>s(e=>e+1),type:`button`,children:[(0,z.jsx)(Om,{"aria-hidden":`true`,size:14}),` Refresh local readback`]})]}),(0,z.jsxs)(`div`,{className:`benchmark-content`,children:[e.view===`campaign`&&(0,z.jsx)(pC,{packet:n,primaryMetric:l}),e.view===`arms`&&(0,z.jsx)(mC,{packet:n}),e.view===`cases`&&(0,z.jsx)(hC,{onOpenRun:e=>u(`runs`,e),packet:n,primaryMetric:l}),e.view===`runs`&&(0,z.jsx)(_C,{onSelectRun:e=>u(`runs`,e),packet:n,selectedRunId:e.runId})]}),(0,z.jsxs)(`footer`,{className:`benchmark-footer`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(Im,{"aria-hidden":`true`,size:16}),(0,z.jsxs)(`span`,{children:[`Scores: `,n.authority.score_source]}),(0,z.jsx)(`span`,{children:`Dashboard cannot launch, grade, or mutate runs.`})]}),(0,z.jsxs)(`code`,{title:d,children:[`local`,d]})]})]})}var yC=J({goalId:W().optional().default(``),statusUrl:W().optional().default(``)}),bC=J({goalId:W().optional().default(``),mode:Y([`showcase`,`developer`,`ops`]).optional().default(`showcase`),statusUrl:W().optional().default(``),todoLane:Y([`all`,`user`,`agent`]).optional().default(`all`),todoQuery:W().optional().default(``)}),xC=bC.omit({mode:!0}),SC=J({dashboardUrl:W().optional().default(``),view:Y([`campaign`,`arms`,`cases`,`runs`]).optional().default(`campaign`),runId:W().optional().default(``)});function CC(){let e=`https://huangruiteng.github.io/loopx/docs/showcases/index.en.html`;return(0,R.useEffect)(()=>{window.location.replace(e)},[]),(0,z.jsx)(`a`,{href:e,children:`Open LoopX cases / 浏览案例`})}function wC({goalId:e,statusUrl:t}){let n=t?Ym(t,window.location.href):null;return n?.error?(0,z.jsx)(`main`,{role:`alert`,children:n.error}):(0,z.jsx)(ii,{replace:!0,to:`/`,search:{goalId:e,statusUrl:t}})}function TC(){let e=kC.useSearch();return e.mode===`ops`?(0,z.jsx)(wC,{...e}):e.mode===`developer`?(0,z.jsx)(ii,{replace:!0,to:`/developers/projections`}):(0,z.jsx)(CC,{})}function EC(){return(0,z.jsx)(wC,{...AC.useSearch()})}var DC=Ci({component:()=>(0,z.jsx)(Mi,{}),errorComponent:()=>(0,z.jsxs)(`main`,{role:`alert`,className:`p-8`,children:[(0,z.jsx)(`h1`,{children:`页面暂时无法显示 / Page unavailable`}),(0,z.jsx)(`p`,{children:`请重新加载页面;这不会执行任务。 / Reloading does not execute tasks.`}),(0,z.jsx)(`button`,{type:`button`,onClick:()=>window.location.reload(),children:`重新加载 / Reload`})]})}),OC=xi({getParentRoute:()=>DC,path:`/`,validateSearch:e=>yC.parse(e),component:jS}),kC=xi({getParentRoute:()=>DC,path:`/frontstage`,validateSearch:e=>bC.parse(e),component:TC}),AC=xi({getParentRoute:()=>DC,path:`/deprecated/frontstage/ops`,validateSearch:e=>xC.parse(e),component:EC}),jC=xi({getParentRoute:()=>DC,path:`/frontstage/developer`,component:()=>(0,z.jsx)(ii,{replace:!0,to:`/developers/projections`})}),MC=xi({getParentRoute:()=>DC,path:`/developers/projections`,component:GS}),NC=xi({getParentRoute:()=>DC,path:`/benchmarks/study`,validateSearch:e=>SC.parse(e),component:vC}),PC=DC.addChildren([OC,kC,AC,jC,MC,NC]);function FC(e){return!e||e===`/`||e===`./`?`/`:(e.startsWith(`/`)?e:`/${e}`).replace(/\/+$/,``)||`/`}var IC=Li({routeTree:PC,basepath:FC(`/chat/`),trailingSlash:`preserve`}),LC=document.getElementById(`root`);if(!LC)throw Error(`Root element not found`);var RC=new je({defaultOptions:{queries:{refetchOnWindowFocus:!1,retry:1,staleTime:1e4}}});(0,Vi.createRoot)(LC).render((0,z.jsx)(Fe,{client:RC,children:(0,z.jsx)(qi,{children:(0,z.jsx)(Bi,{router:IC})})})); \ No newline at end of file +`),summary:w.summary,title:w.title}}]:[]],Xe={...$v(x),periodicReports:{error:E,loading:O},timeline:Ye};return(0,z.jsxs)(`div`,{className:p===`dark`?`dark`:``,"data-testid":`personal-goal-home`,children:[ye?(0,z.jsx)(`p`,{role:`status`,className:`m-0 bg-amber-50 px-4 py-2 text-sm text-amber-900`,children:g(ye===`partial`?`runs.discoveryPartial`:`runs.discoveryOffline`)}):null,(0,z.jsx)(_x,{agents:te.map(e=>({adapterKind:e.adapterKind,agentId:e.agentId,available:e.available,capability:e.capability,interrupt:e.interrupt,label:e.label,location:e.location,resume:e.resume,source:e.source,streaming:e.streaming,toolCalls:e.toolCalls,trustScope:e.trustScope,workspaceCompatibility:e.available?`当前 Goal 写入前验证`:`不可用,需先修复 Endpoint`})),callbacks:{onApplyAttention:e=>Je(e.goalId),onCorrectRun:async(e,t)=>{if(!e.sessionId)throw Error(`这个 Run 还没有可纠偏的执行 Session。`);let n=await wh((await xh({actionKind:`run.correct`,context:{kind:`run`,goal_id:e.goalId,todo_id:e.todoId},idempotencyKey:`workspace-run-correct-${e.sessionId}-${Date.now().toString(36)}`,normalizedParameters:{goal_id:e.goalId,message:t,session_id:e.sessionId},summary:`纠偏执行任务:${e.title}`})).proposal_id),r=typeof n.turn?.turn_id==`string`?n.turn.turn_id:void 0;if(V(e.goalId,{agentId:e.agentId,resumable:!0,sessionId:e.sessionId,status:r?`running`:`ready`,turnId:r}),r){De.current.set(e.goalId,r);let t=new AbortController;L.current.set(e.goalId,t);let n=``,i=ze(e.goalId,{activity:[`正在把纠偏送入原执行 Session`],agentLabel:e.agentLabel,lines:[],pending:!0,sourceLabel:`${e.agentLabel} · 执行 Session`,text:``});try{let a=await Vh(e.sessionId,r,{signal:t.signal,onDelta:t=>{n+=t,Be(e.goalId,i,{text:n})}});Be(e.goalId,i,{activity:[],pending:!1,text:rS(a.response.message||n.trim())||`${e.agentLabel} 已完成纠偏。`})}catch(t){let n=Oe.current.delete(e.goalId);Be(e.goalId,i,{activity:[],pending:!1,text:n?`已中断。你可以在当前会话继续发送消息。`:t instanceof Error?t.message:`纠偏回合失败。`})}finally{De.current.delete(e.goalId),L.current.delete(e.goalId),V(e.goalId,{agentId:e.agentId,resumable:!0,sessionId:e.sessionId,status:`ready`})}}},onCloseRunSession:Ge,onInterruptRun:async e=>He(e),onOpenGoal:Je,onOpenRunSession:async e=>{if(!e.sessionId)return;let t=e.sessionId,n=await jh(t);Se(e=>({...e,[t]:n})),Je(e.goalId),ue(t=>({...t,[e.goalId]:n.messages.map(t=>({agentLabel:t.role===`user`?void 0:e.agentLabel,attachments:Qx(t.attachments),id:Ce.current++,lines:[],role:t.role===`user`?`user`:`assistant`,sourceLabel:t.role===`user`?void 0:`${e.agentLabel} · 执行 Session`,text:t.role===`user`?t.text:rS(t.text)}))})),V(e.goalId,{agentId:e.agentId,resumable:n.session.resumable,sessionId:t,status:n.session.active_turn_id?`running`:n.session.status,turnId:n.session.active_turn_id??void 0})},onOpenOutput:e=>Je(e.goalId),...y?{onPreviewGoalSubagentConfiguration:async e=>{let t=await Kh(e);return{changed:t.changed,configuration:{allowedDomains:t.after.orchestration.allowed_domains,enabled:t.feature_summary.multi_subagent===`enabled`,maxChildren:t.after.orchestration.max_children},previewId:t.preview_id}},onApplyGoalSubagentConfiguration:async({previewId:e,...t})=>{let n=await qh(t,e);return{allowedDomains:n.after.orchestration.allowed_domains,enabled:n.feature_summary.multi_subagent===`enabled`,maxChildren:n.after.orchestration.max_children}}}:{},onGoalActivationStateChange:n,onGoalDeleted:r,onReconcileStatus:a,onRetryGoalArchive:s,onExportOutput:async e=>{let t=[`# ${e.title}`,``,e.summary??``,``,e.safePreview??`此产出没有可用的公开安全预览。`,``,`Goal: ${e.goalId}`,`Todo: ${e.todoId??`unlinked`}`,`Run: ${e.runId??`unlinked`}`].join(` +`),n=URL.createObjectURL(new Blob([t],{type:`text/markdown;charset=utf-8`})),r=document.createElement(`a`);r.href=n,r.download=`${e.outputId.replace(/[^a-z0-9._-]+/gi,`-`)}.md`,r.click(),URL.revokeObjectURL(n)},onRefresh:o,onRetryResumeRun:Ue,onSelectAgent:Ke,onSelectGoal:e=>e?Je(e):qe(),onSendMessage:async(e,t,n,r)=>Ve(e,{agentId:t,goalId:n,attachments:r}),onStartNewRunSession:We},goalArchiveLoadState:e,model:Xe,readOnly:h,selectedAgentId:N.agentId,selectedGoalId:S?.goalId??null,statusSourceControl:f})]})}function PS({error:e,isLoading:t,onRetry:n,requestedUrl:r,theme:i,toggleTheme:a}){let o=!!(e&&/failed to fetch|networkerror|load failed/i.test(e)&&r.includes(`status.json`));return(0,z.jsx)(`div`,{className:i===`dark`?`dark`:``,children:(0,z.jsxs)(`main`,{className:`min-h-screen bg-[#f6f7f9] text-slate-950 dark:bg-[#09090b] dark:text-zinc-50`,children:[(0,z.jsxs)(`header`,{className:`flex min-h-16 flex-wrap items-center justify-between gap-3 border-b border-slate-200 bg-white px-4 py-3 dark:border-zinc-800 dark:bg-zinc-950 sm:px-6`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`h1`,{className:`text-xl font-semibold`,children:`LoopX Workspace`}),(0,z.jsx)(`p`,{className:`mt-1 break-all text-sm text-slate-500 dark:text-zinc-400`,children:`Personal Workspace`})]}),(0,z.jsx)(qv,{"aria-label":`切换主题`,onClick:a,size:`icon`,variant:`secondary`,children:i===`dark`?(0,z.jsx)(Bm,{className:`h-4 w-4`}):(0,z.jsx)(xm,{className:`h-4 w-4`})})]}),(0,z.jsxs)(`div`,{className:`grid min-h-[calc(100vh-80px)] sm:grid-cols-[240px_1fr]`,children:[(0,z.jsxs)(`aside`,{className:`hidden border-r border-slate-200 p-6 dark:border-zinc-800 sm:block`,"aria-label":`Workspace`,children:[(0,z.jsx)(`strong`,{children:`LoopX`}),(0,z.jsx)(`p`,{className:`mt-6 text-sm`,children:`Workspace`}),(0,z.jsx)(`p`,{className:`mt-8 text-xs text-slate-500`,children:`Goals`}),[1,2,3].map(e=>(0,z.jsx)(`div`,{className:`mt-4 h-8 rounded bg-slate-100 dark:bg-zinc-900`},e))]}),(0,z.jsx)(`div`,{className:`p-4 sm:p-8`,children:(0,z.jsx)(Jv,{"data-testid":`initial-status-state`,children:(0,z.jsx)(Yv,{className:`flex min-h-64 items-center justify-center p-6`,children:(0,z.jsxs)(`div`,{className:`max-w-xl text-center`,children:[e?(0,z.jsx)(Xp,{className:`mx-auto h-6 w-6 text-rose-600 dark:text-rose-300`}):(0,z.jsx)(Om,{className:`mx-auto h-6 w-6 animate-spin text-slate-500 dark:text-zinc-400`}),(0,z.jsx)(`p`,{className:`mt-3 text-sm font-medium`,children:e?`无法加载实时状态`:`正在加载实时状态`}),e?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`p`,{className:`mt-2 break-words text-sm leading-6 text-slate-500 dark:text-zinc-400`,children:o?`本地状态服务暂时未连接。升级或启动期间可能短暂断开,请重试;仍失败时重新打开 LoopX App,或运行 loopx doctor。`:e}),o?(0,z.jsx)(`p`,{className:`mt-2 text-xs leading-5 text-slate-400 dark:text-zinc-500`,children:`重新加载不会执行任务,也不会改变 Goal 配置。`}):null,(0,z.jsx)(`div`,{className:`mt-4 flex flex-wrap justify-center gap-2`,children:(0,z.jsxs)(qv,{disabled:t,onClick:n,children:[(0,z.jsx)(Om,{className:`h-4 w-4`}),`重试`]})})]}):(0,z.jsx)(`p`,{className:`mt-2 text-sm leading-6 text-slate-500 dark:text-zinc-400`,role:`status`,children:`正在连接 Workspace,Goal 列表将先出现,详细状态会逐个补齐。 / Connecting to your Workspace. Goals load independently.`})]})})})})]})]})})}function FS(){let e=MC.useSearch(),t=MC.useNavigate(),[n,r]=(0,R.useState)(`light`),[i,a]=(0,R.useState)(null),o=(0,R.useRef)(null),s=(0,R.useRef)(e.goalId);s.current=e.goalId;let[c,l]=(0,R.useState)(bp),[u,d]=(0,R.useState)({kind:`example`,label:`bundled example`}),[f,p]=(0,R.useState)(()=>Ax(window.localStorage,window.location.href)),[m,h]=(0,R.useState)(e.statusUrl),[g,_]=(0,R.useState)(null),[v,y]=(0,R.useState)(!1),[b,x]=(0,R.useState)({error:null,phase:`idle`}),[S,C]=(0,R.useState)(e.statusUrl.trim()||null),[w,T]=(0,R.useState)(!1),E=(0,R.useRef)(null),D=(0,R.useRef)(Bg(e.statusUrl.trim()||null)),O=!w&&u.kind===`example`?e.statusUrl.trim():``,k=S??O,ee=u.kind===`url`?u.label:zx,A=!!(g&&S),j=Ix(f,S,ee,window.location.href),te=u.kind===`example`&&!w,ne=c.attention_queue,re=c.run_history,M=(0,R.useMemo)(()=>Hx(re.goals,ne.items),[re.goals,ne.items]);function N(e,t,n=0){x({error:null,phase:`loading`}),Bx(Zm(e,`stopped`,window.location.href)).then(r=>{if(!Wg(D.current,t))return;let i=r.goal_projection?.registry_revision??null,a=t.registryRevision!==null&&t.registryRevision!==void 0&&i!==null&&t.registryRevision!==i;if(l(e=>p_(e,r)),a&&n<1){oe(e,{background:!0,resyncAttempt:n+1});return}x(a?{error:`Goal 状态在加载历史时发生变化,请重试。`,phase:`error`}:{error:null,phase:`ready`})}).catch(e=>{Wg(D.current,t)&&x({error:yp(e),phase:`error`})})}function ie(){let e=u.kind===`url`?u.label:m||zx,t=Hg(D.current,e,{background:!0});if(i){oe(e);return}t&&N(e,t)}async function ae(e,n,r){if(r.background)return l(e=>p_(e,n)),!0;let i={kind:`url`,label:e};return D.current.loadedUrl=e,l(n),d(i),h(e),await t({search:t=>({...t,statusUrl:e})}),Ug(D.current,r)?(D.current.requestedUrl=null,C(null),!0):!1}async function oe(e,t={}){let n=e.trim(),r=t.background===!0;if(!n){r||_(`状态地址不能为空`);return}let c=Hg(D.current,n,{background:r,selectionRevision:t.selectionRevision});if(!c)return;o.current?.abort();let d=new AbortController;o.current=d,r||(E.current=null,T(!1),C(n),y(!0),_(null),x({error:null,phase:`idle`}));try{let e=await Cp(n,window.location.href).catch(()=>null);if(!Wg(D.current,c))return;if(e){let o=t.retryOnly&&u.kind===`url`&&u.label===n&&i?.directory.registry_revision===e.registry_revision?i.snapshots:{};a({directory:e,snapshots:o,errors:{}});let f={...e,goals:e.goals.filter(e=>!o[e.id])},p=!1,m=wp(e);if(r)l(m);else if(!await ae(n,m,c))return;if(x({error:null,phase:`loading`}),await Tp(n,window.location.href,f,(e,t,n)=>{n===`revision`&&(p=!0),a(r=>r&&{...r,snapshots:t?{...r.snapshots,[e]:t}:r.snapshots,errors:n?{...r.errors,[e]:n}:r.errors})},()=>Wg(D.current,c),()=>s.current,d.signal),p&&(t.resyncAttempt??0)<1&&Wg(D.current,c)){await oe(n,{resyncAttempt:1});return}Wg(D.current,c)&&x({error:null,phase:`ready`});return}let o=await Bx(Zm(n,`active`,window.location.href));if(!Wg(D.current,c)||(a(null),c.registryRevision=o.goal_projection?.registry_revision??null,!await ae(n,o,c)))return;if(o.goal_projection?.scope!==`active`||o.goal_projection.complete){x({error:null,phase:`ready`});return}N(n,c,t.resyncAttempt??0)}catch(e){if(!Ug(D.current,c))return;r||_(yp(e))}finally{!r&&Ug(D.current,c)&&y(!1)}}function P(e,t={}){o.current?.abort();let n=Vg(D.current,e.statusUrl);E.current=null,T(!1),C(e.statusUrl),y(!0),_(null),(async()=>{if(t.ensureTunnel&&e.kind===`ssh_tunnel`){let t=new URL(e.statusUrl,window.location.href).port;if(t)try{await Zy(e.label,t)}catch{}}D.current.selectionRevision===n&&await oe(e.statusUrl,{selectionRevision:n})})()}function F(e){p(e);try{jx(window.localStorage,e)}catch{}}let I={activeSource:j,connectionState:v?`loading`:A?`error`:`connected`,errorMessage:A?`未切换到 ${S??`所选来源`}:${g}`:null,onAdd:e=>{let t=Mx(f,e,window.location.href);return`error`in t?{error:t.error}:(F(t.catalog),P(t.source,{ensureTunnel:e.ensureTunnel}),{})},onRemove:e=>{F(Nx(f,e)),j.id===e&&P(Tx)},onSelect:e=>{let t=f.sources.find(t=>t.id===e);t&&P(t,{ensureTunnel:t.kind===`ssh_tunnel`})},sources:j.id===`temporary`?[...f.sources,j]:f.sources};(0,R.useEffect)(()=>{let t=e.statusUrl.trim();if(t){if(E.current===t||S&&S!==t)return;(u.kind!==`url`||u.label!==t)&&oe(t);return}E.current=null,!w&&(S||u.kind===`example`&&oe(zx))},[w,S,e.statusUrl,u.kind,u.label]),(0,R.useEffect)(()=>{if(e.statusUrl&&u.kind===`example`)return;let n=new Set(M.map(e=>e.goal.id));if(M.length===0){e.goalId&&t({search:e=>({...e,goalId:``})});return}e.goalId&&!n.has(e.goalId)&&b.phase!==`loading`&&t({search:e=>({...e,goalId:``})})},[b.phase,M,t,e.goalId,e.statusUrl,u.kind]),(0,R.useEffect)(()=>{if(!i||v||!e.goalId||u.kind!==`url`)return;let t=i.directory.goals.find(t=>t.id===e.goalId);t?.activation_state===`stopped`&&!i.snapshots[t.id]&&!i.errors[t.id]&&oe(u.label,{retryOnly:!0})},[e.goalId,v,i,u]);function se(e){t({search:t=>({...t,goalId:e})})}return te?(0,z.jsx)(PS,{error:g,isLoading:v,onRetry:()=>void oe(k||zx),requestedUrl:k||zx,theme:n,toggleTheme:()=>r(n===`dark`?`light`:`dark`)}):(0,z.jsx)(NS,{goalArchiveLoadState:b,isLoading:v,onGoalActivationStateChange:(e,t)=>{D.current.projectionRevision+=1,l(n=>gp(n,e,t)),a(n=>n&&{...n,snapshots:Object.fromEntries(Object.entries(n.snapshots).map(([n,r])=>[n,gp(r,e,t)]))})},onGoalDeleted:e=>{D.current.projectionRevision+=1,l(t=>_p(t,e)),a(t=>t&&{...t,snapshots:Object.fromEntries(Object.entries(t.snapshots).filter(([t])=>t!==e))})},onSelectGoal:se,onReconcileStatus:()=>oe(u.kind===`url`?u.label:m||zx,{background:!0}),onRetryGoalArchive:ie,onRefresh:()=>oe(u.kind===`url`?u.label:m||zx,{retryOnly:!!(i&&Object.keys(i.errors).length)}),payload:c,progress:i,rows:M,selectedGoalId:e.goalId,statusSourceControl:I,theme:n,toggleTheme:()=>r(n===`dark`?`light`:`dark`)})}var IS=v_(`inline-flex items-center gap-1 rounded-md border px-2 py-0.5 text-xs font-medium`,{variants:{variant:{neutral:`border-slate-200 bg-white text-slate-700 dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-300`,success:`border-emerald-200 bg-emerald-50 text-emerald-800 dark:border-emerald-900 dark:bg-emerald-950 dark:text-emerald-200`,warning:`border-amber-200 bg-amber-50 text-amber-800 dark:border-amber-900 dark:bg-amber-950 dark:text-amber-200`,info:`border-sky-200 bg-sky-50 text-sky-800 dark:border-sky-900 dark:bg-sky-950 dark:text-sky-200`,danger:`border-rose-200 bg-rose-50 text-rose-800 dark:border-rose-900 dark:bg-rose-950 dark:text-rose-200`}},defaultVariants:{variant:`neutral`}});function LS({className:e,variant:t,...n}){return(0,z.jsx)(`span`,{className:Gv(IS({variant:t}),e),...n})}var RS=[{label:`status payload`,source:`apps/presentation/dashboard/src/data/status.ts`,detail:`status_contract, attention_queue, local_dashboard_api, run_history`},{label:`channel projection`,source:`apps/presentation/dashboard/src/data/goal-channel-frontstage.ts`,detail:`decision_frame, todos, gates, leases, artifacts, truth_contract`},{label:`public showcase catalog`,source:`docs/showcases/showcase-catalog.json`,detail:`case metadata, visual hints, evidence boundaries, story beats`},{label:`route smoke`,source:`apps/presentation/dashboard/smoke/frontstage-route-smoke.ts`,detail:`static route contract, source guards, component expectations`}],zS=[{axis:`schema`,current:`goal_channel_projection_v0`,proposed:`new optional projection field`,gate:`parser default plus route smoke assertion`},{axis:`truth`,current:`event ledger and active state remain source of truth`,proposed:`derived UI state only`,gate:`truth_contract must stay read-only`},{axis:`privacy`,current:`compact source refs and warnings`,proposed:`public-safe fixture field`,gate:`loopx check and browser fake-private fixture`},{axis:`interaction`,current:`render, filter, select, inspect`,proposed:`no browser write by default`,gate:`write affordance requires explicit loopback capability`}],BS=[{title:`Fixture sources`,body:`Use examples/status.example.json, browser-smoke fixtures, and docs/showcases/showcase-catalog.json.`},{title:`Required proof`,body:`Every projection addition needs parser coverage, route smoke assertions, and one browser or bundle check when UI output changes.`},{title:`Never include`,body:`Raw task text, trajectories, transcripts, local paths, private registry state, credentials, or internal document links.`}],VS=[`npm --prefix apps/presentation/dashboard run smoke:frontstage-route`,`npm --prefix apps/presentation/dashboard run smoke:frontstage-browser`,`npm --prefix apps/presentation/dashboard run smoke:frontstage-share-bundle`,`npm --prefix apps/presentation/dashboard run build`,`loopx check --scan-path apps/presentation/dashboard --scan-path docs/status-data-contract.md`],HS=[{name:`Projection lane`,badges:[`read-only`,`schema v0`],body:`Summarizes one compact projection lane without mutating the underlying LoopX state.`},{name:`Capability badge`,badges:[`loopback`,`dry-run`],body:`Shows an advertised local capability only after the status feed declares it.`},{name:`Boundary warning`,badges:[`public-safe`,`omitted`],body:`Names omitted private material and points contributors back to compact source references.`}];function US({children:e,icon:t,title:n}){return(0,z.jsxs)(`section`,{className:`rounded-lg border border-slate-200 bg-white shadow-sm`,children:[(0,z.jsx)(`div`,{className:`flex items-center justify-between gap-3 border-b border-slate-200 px-4 py-3`,children:(0,z.jsxs)(`h2`,{className:`flex items-center gap-2 text-sm font-semibold text-slate-950`,children:[(0,z.jsx)(t,{className:`h-4 w-4 text-slate-500`}),n]})}),e]})}function WS(){return(0,z.jsx)(US,{icon:Wp,title:`Status Contract Explorer`,children:(0,z.jsx)(`div`,{className:`grid gap-3 p-4 lg:grid-cols-2`,"data-testid":`developer-contract-explorer`,children:RS.map(e=>(0,z.jsxs)(`div`,{className:`rounded-md border border-slate-200 bg-slate-50 px-3 py-3`,children:[(0,z.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,z.jsx)(LS,{variant:`info`,children:e.label}),(0,z.jsx)(LS,{variant:`neutral`,children:`public contract`})]}),(0,z.jsx)(`div`,{className:`mt-2 break-words font-mono text-xs text-slate-700`,children:e.source}),(0,z.jsx)(`p`,{className:`mt-2 text-sm leading-6 text-slate-600`,children:e.detail})]},e.label))})})}function GS(){return(0,z.jsx)(US,{icon:um,title:`Projection Diffing`,children:(0,z.jsx)(`div`,{className:`overflow-x-auto`,"data-testid":`developer-projection-diffing`,children:(0,z.jsxs)(`table`,{className:`min-w-full border-separate border-spacing-0 text-left text-sm`,children:[(0,z.jsx)(`thead`,{children:(0,z.jsxs)(`tr`,{className:`bg-slate-50 text-xs uppercase tracking-normal text-slate-500`,children:[(0,z.jsx)(`th`,{className:`border-b border-slate-200 px-4 py-3 font-semibold`,children:`Axis`}),(0,z.jsx)(`th`,{className:`border-b border-slate-200 px-4 py-3 font-semibold`,children:`Current`}),(0,z.jsx)(`th`,{className:`border-b border-slate-200 px-4 py-3 font-semibold`,children:`Proposed`}),(0,z.jsx)(`th`,{className:`border-b border-slate-200 px-4 py-3 font-semibold`,children:`Gate`})]})}),(0,z.jsx)(`tbody`,{children:zS.map(e=>(0,z.jsxs)(`tr`,{className:`align-top`,children:[(0,z.jsx)(`td`,{className:`border-b border-slate-100 px-4 py-3 font-semibold text-slate-950`,children:e.axis}),(0,z.jsx)(`td`,{className:`border-b border-slate-100 px-4 py-3 text-slate-600`,children:e.current}),(0,z.jsx)(`td`,{className:`border-b border-slate-100 px-4 py-3 text-slate-600`,children:e.proposed}),(0,z.jsx)(`td`,{className:`border-b border-slate-100 px-4 py-3 text-slate-600`,children:e.gate})]},e.axis))})]})})})}function KS(){return(0,z.jsx)(US,{icon:om,title:`Fixture Generation`,children:(0,z.jsx)(`div`,{className:`grid gap-3 p-4 md:grid-cols-3`,"data-testid":`developer-fixture-generation`,children:BS.map(e=>(0,z.jsxs)(`div`,{className:`rounded-md border border-slate-200 bg-slate-50 px-3 py-3`,children:[(0,z.jsx)(`div`,{className:`text-sm font-semibold text-slate-950`,children:e.title}),(0,z.jsx)(`p`,{className:`mt-2 text-sm leading-6 text-slate-600`,children:e.body})]},e.title))})})}function qS(){return(0,z.jsx)(US,{icon:Qp,title:`Smoke Checklist`,children:(0,z.jsx)(`div`,{className:`space-y-2 p-4`,"data-testid":`developer-smoke-checklist`,children:VS.map(e=>(0,z.jsxs)(`div`,{className:`flex items-start gap-3 rounded-md border border-slate-200 bg-slate-50 px-3 py-2`,children:[(0,z.jsx)(Vp,{className:`mt-0.5 h-4 w-4 shrink-0 text-emerald-600`}),(0,z.jsx)(`code`,{className:`break-all text-xs font-semibold leading-5 text-slate-700`,children:e})]},e))})})}function JS(){return(0,z.jsx)(US,{icon:$p,title:`Component Examples`,children:(0,z.jsx)(`div`,{className:`grid gap-3 p-4 lg:grid-cols-3`,"data-testid":`developer-component-examples`,children:HS.map(e=>(0,z.jsxs)(`article`,{className:`rounded-md border border-slate-200 bg-slate-50 p-3`,children:[(0,z.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:e.badges.map(e=>(0,z.jsx)(LS,{variant:e===`read-only`||e===`public-safe`?`success`:`neutral`,children:e},e))}),(0,z.jsx)(`h3`,{className:`mt-3 text-sm font-semibold leading-6 text-slate-950`,children:e.name}),(0,z.jsx)(`p`,{className:`mt-2 text-sm leading-6 text-slate-600`,children:e.body})]},e.name))})})}function YS(){return(0,z.jsx)(`main`,{className:`min-h-screen bg-[#f7f7f4] px-4 py-4 text-slate-950 sm:px-5`,"data-testid":`frontstage-developer-cockpit`,children:(0,z.jsxs)(`div`,{className:`mx-auto grid max-w-[1500px] gap-4 xl:grid-cols-[260px_minmax(0,1fr)]`,children:[(0,z.jsxs)(`aside`,{className:`rounded-lg border border-slate-200 bg-white p-4 shadow-sm xl:sticky xl:top-4 xl:self-start`,children:[(0,z.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,z.jsx)(`div`,{className:`flex h-9 w-9 items-center justify-center rounded-md border border-slate-200 bg-slate-950 text-white`,children:(0,z.jsx)(Vm,{className:`h-4 w-4`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`text-sm font-semibold`,children:`Developer Cockpit`}),(0,z.jsx)(`div`,{className:`text-xs text-slate-500`,children:`Projection extension`})]})]}),(0,z.jsxs)(`div`,{className:`mt-4 grid gap-2`,children:[(0,z.jsxs)(`a`,{className:`flex items-center gap-2 rounded-md border border-slate-200 px-3 py-2 text-sm font-medium`,href:`https://huangruiteng.github.io/loopx/`,children:[(0,z.jsx)(pm,{className:`h-4 w-4`}),`LoopX home`]}),(0,z.jsxs)(`a`,{className:`flex items-center gap-2 rounded-md border border-slate-200 px-3 py-2 text-sm font-medium`,href:`https://huangruiteng.github.io/loopx/docs/showcases/index.en.html`,children:[(0,z.jsx)(im,{className:`h-4 w-4`}),`Public cases`]}),(0,z.jsxs)(`a`,{className:`flex items-center gap-2 rounded-md bg-slate-950 px-3 py-2 text-sm font-medium text-white`,href:`/chat/developers/projections/`,children:[(0,z.jsx)($p,{className:`h-4 w-4`}),`Developer cockpit`]})]}),(0,z.jsxs)(`div`,{className:`mt-5 space-y-2 rounded-md border border-emerald-200 bg-emerald-50 p-3 text-xs leading-5 text-emerald-950`,children:[(0,z.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,z.jsx)(LS,{variant:`success`,children:`read-only`}),(0,z.jsx)(LS,{variant:`neutral`,children:`public fixtures`})]}),(0,z.jsx)(`p`,{children:`This route uses static public contracts only; live status feeds, registry files, and browser write APIs stay outside the cockpit.`})]})]}),(0,z.jsxs)(`section`,{className:`space-y-4`,children:[(0,z.jsx)(`div`,{className:`rounded-lg border border-slate-200 bg-white px-5 py-5 shadow-sm`,children:(0,z.jsxs)(`div`,{className:`flex flex-wrap items-start justify-between gap-4`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,z.jsx)(LS,{variant:`info`,children:`developers/projections`}),(0,z.jsx)(LS,{variant:`success`,children:`public-safe`}),(0,z.jsx)(LS,{variant:`neutral`,children:`no browser writes`})]}),(0,z.jsx)(`h1`,{className:`mt-3 text-3xl font-semibold tracking-normal text-slate-950`,children:`LoopX Projection Developer Cockpit`}),(0,z.jsx)(`p`,{className:`mt-2 max-w-3xl text-sm leading-6 text-slate-600`,children:`A read-only contributor workbench for adding dashboard/frontstage projections without reverse-engineering the large operator page.`})]}),(0,z.jsxs)(`div`,{className:`grid min-w-[260px] gap-2 text-sm`,children:[(0,z.jsxs)(`div`,{className:`rounded-md border border-slate-200 bg-slate-50 px-3 py-2`,children:[(0,z.jsx)(`div`,{className:`text-[11px] font-semibold uppercase tracking-normal text-slate-500`,children:`Source of truth`}),(0,z.jsx)(`div`,{className:`mt-1 font-semibold text-slate-950`,children:`status contract + compact fixtures`})]}),(0,z.jsxs)(`div`,{className:`rounded-md border border-slate-200 bg-slate-50 px-3 py-2`,children:[(0,z.jsx)(`div`,{className:`text-[11px] font-semibold uppercase tracking-normal text-slate-500`,children:`Boundary`}),(0,z.jsx)(`div`,{className:`mt-1 font-semibold text-slate-950`,children:`read-only extension surface`})]})]})]})}),(0,z.jsxs)(`div`,{className:`grid gap-4 xl:grid-cols-2`,children:[(0,z.jsx)(WS,{}),(0,z.jsx)(GS,{})]}),(0,z.jsxs)(`div`,{className:`grid gap-4 xl:grid-cols-[minmax(0,1fr)_420px]`,children:[(0,z.jsx)(KS,{}),(0,z.jsx)(qS,{})]}),(0,z.jsx)(JS,{}),(0,z.jsx)(US,{icon:Im,title:`Extension Boundary`,children:(0,z.jsxs)(`div`,{className:`grid gap-3 p-4 md:grid-cols-3`,"data-testid":`developer-extension-boundary`,children:[(0,z.jsxs)(`div`,{className:`rounded-md border border-emerald-200 bg-emerald-50 px-3 py-3`,children:[(0,z.jsx)(`div`,{className:`text-sm font-semibold text-slate-950`,children:`Allowed`}),(0,z.jsx)(`p`,{className:`mt-2 text-sm leading-6 text-slate-600`,children:`Versioned parser defaults, public fixtures, read-only route panels, and focused smoke assertions.`})]}),(0,z.jsxs)(`div`,{className:`rounded-md border border-amber-200 bg-amber-50 px-3 py-3`,children:[(0,z.jsx)(`div`,{className:`text-sm font-semibold text-slate-950`,children:`Review`}),(0,z.jsx)(`p`,{className:`mt-2 text-sm leading-6 text-slate-600`,children:`New dashboard dependencies, status contract fields, loopback capability display, and browser-visible workflows.`})]}),(0,z.jsxs)(`div`,{className:`rounded-md border border-rose-200 bg-rose-50 px-3 py-3`,children:[(0,z.jsx)(`div`,{className:`text-sm font-semibold text-slate-950`,children:`Stop`}),(0,z.jsx)(`p`,{className:`mt-2 text-sm leading-6 text-slate-600`,children:`Credentials, private registry material, raw logs, transcripts, production actions, or default browser write authority.`})]})]})})]})]})})}var XS=J({value:G().finite(),total:G().finite().positive().optional(),unit:W().optional(),higher_is_better:K()}).passthrough(),ZS=gd(W(),G().finite()).default({}),QS=J({outcome_status:W().optional(),failure_class:W(),causal_summary:W(),expectedness:W(),implication:W(),next_probe:W(),confidence:W(),evidence_refs:q(W()).optional()}).passthrough(),$S=J({arm_id:W(),selected_run_id:W().nullable(),score_countable:K(),metrics:gd(W(),XS),effort:ZS,insight:QS.nullable().optional()}),eC=J({run_id:W(),case_id:W(),arm_id:W(),arm_role:W(),status:W(),protocol_id:W(),runner_revision:W().optional(),observed_at:W(),metrics:gd(W(),XS),countability:J({integrity_qualified:K(),official_result_present:K(),score_countable:K()}).passthrough(),treatment_fidelity:W(),effort:ZS,redacted_insight:QS.nullable().optional(),upload_provenance:J({producer_id:W(),producer_version:W(),observed_at:W(),source_revision:W()}).passthrough()}).passthrough(),tC=J({case_denominator:G().int().nonnegative(),value_sum:G().finite(),value_mean:G().finite().nullable(),value_median:G().finite().nullable(),value_min:G().finite().nullable(),value_max:G().finite().nullable(),case_macro_rate:G().finite().optional(),suite_micro_rate:G().finite().optional(),suite_micro_numerator:G().finite().optional(),suite_micro_denominator:G().finite().positive().optional()}).passthrough(),nC=J({arm_id:W(),arm_role:W(),factor_assignments:gd(W(),W()),protocol_counts:gd(W(),G().int().nonnegative()).default({}),runner_revision_counts:gd(W(),G().int().nonnegative()).default({}),orchestrator_runtime_counts:gd(W(),G().int().nonnegative()).default({}),intended_case_count:G().int().positive(),run_count:G().int().nonnegative(),terminal_run_count:G().int().nonnegative(),selected_score_countable_case_count:G().int().nonnegative(),coverage_rate:G().finite().min(0).max(1),metrics:gd(W(),tC),binary_outcomes:gd(W(),J({success_count:G().int().nonnegative(),case_denominator:G().int().nonnegative(),success_rate:G().finite().min(0).max(1).nullable()})),effort:gd(W(),J({denominator:G().int().nonnegative(),mean:G().finite().nullable(),median:G().finite().nullable()})),failure_class_counts:gd(W(),G().int().nonnegative())}).passthrough(),rC=J({baseline_value:G().finite(),candidate_value:G().finite(),delta:G().finite(),direction:Y([`improved`,`flat`,`regressed`]).optional()}).passthrough(),iC=J({comparison_id:W(),comparison_anchor_run_id:W(),candidate_run_id:W(),candidate_arm_id:W(),primary_metric:W(),matched_pair_countable:X(!0),metric_deltas:gd(W(),rC)}).passthrough(),aC=J({ok:X(!0),schema_version:X(`benchmark_study_dashboard_v0`),benchmark_id:W(),study_id:W(),status:Y([`complete`,`provisional`]),design:J({protocol_id:W(),comparison_protocol_id:W(),baseline_arm_id:W(),case_set:J({case_set_id:W(),case_ids:q(W())}),metric_catalog:q(J({metric_name:W(),role:Y([`primary`,`guardrail`,`supporting`]),unit:W().optional(),higher_is_better:K(),binary:K()})),labels:gd(W(),W())}).passthrough(),campaign:J({intended_case_count:G().int().positive(),intended_arm_count:G().int().positive(),intended_cell_denominator:G().int().positive(),selected_score_countable_cell_count:G().int().nonnegative(),selected_score_countable_coverage_rate:G().finite().min(0).max(1),complete_declared_design_case_count:G().int().nonnegative(),ambiguous_score_countable_cell_count:G().int().nonnegative(),in_flight_run_count:G().int().nonnegative(),matched_pair_countable_count:G().int().nonnegative(),factorial_contrast_count:G().int().nonnegative(),factorial_contrast_countable_count:G().int().nonnegative(),runtime_observation_count:G().int().nonnegative(),runtime_classification_counts:gd(W(),G().int().nonnegative())}),arms:q(nC),contrasts:gd(W(),J({matched_pair_denominator:G().int().nonnegative(),primary_metric_directions:J({improved:G().int().nonnegative(),flat:G().int().nonnegative(),regressed:G().int().nonnegative()}),binary_metric_transitions:gd(W(),J({"0_to_1":G().int().nonnegative(),"1_to_0":G().int().nonnegative(),same:G().int().nonnegative()}))})),cases:q(J({case_id:W(),complete_declared_design:K(),arms:q($S),eligible_comparisons:q(iC),largest_eligible_primary_contrast:iC.nullable()})),runs:q(eC),authority:J({score_source:W(),matched_comparison_source:W(),factorial_comparison_source:W().nullable(),manifest_changes_scores:X(!1),dashboard_is_execution_authority:X(!1)}),public_boundary:J({raw_task_recorded:X(!1),raw_trajectory_recorded:X(!1),hidden_evaluation_recorded:X(!1),raw_verifier_output_recorded:X(!1),credentials_recorded:X(!1),local_paths_recorded:X(!1)}),write_performed:X(!1),network_access_performed:X(!1)});function oC(e){return aC.parse(e)}function sC(e,t){let n=new URL(t),r=new URL(e||`/benchmark-study.example.json`,n);if(!new Set([`http:`,`https:`]).has(r.protocol))throw Error(`Benchmark dashboard source must use HTTP or HTTPS`);if(r.origin!==n.origin)throw Error(`Benchmark dashboard source must use same-origin local readback`);return r.toString()}var cC=[{id:`campaign`,label:`Campaign`},{id:`arms`,label:`Arms`},{id:`cases`,label:`Cases`},{id:`runs`,label:`Runs`}];function lC(e){return e==null?`—`:`${(e*100).toFixed(e>=.995?0:1)}%`}function uC(e){return e==null?`—`:new Intl.NumberFormat(`en`,{maximumFractionDigits:2,notation:`compact`}).format(e)}function dC(e){if(e==null)return`—`;let t=e/6e4;return t>=120?`${(t/60).toFixed(1)} h`:`${uC(t)} min`}function fC(e){let t=Object.entries(e);return t.length?t.map(([e,t])=>`${e} (${t})`).join(`, `):`—`}function pC(e){if(!e)return`—`;let t=e.total==null?uC(e.value):`${uC(e.value)}/${uC(e.total)}`;return e.unit?`${t} ${e.unit}`:t}function mC(e,t){let n=e.metrics[t];return!n||n.case_denominator===0?`—`:n.suite_micro_rate==null?`${uC(n.value_mean)} mean`:`${lC(n.suite_micro_rate)} · ${uC(n.suite_micro_numerator)}/${uC(n.suite_micro_denominator)}`}function hC(e,t){let n=e.largest_eligible_primary_contrast,r=n?.metric_deltas[t];if(!n||!r)return null;let i=r.delta>0?`+`:``;return{direction:r.direction,text:`${n.candidate_arm_id}: ${i}${uC(r.delta)}`}}function gC({children:e,tone:t=`neutral`}){return(0,z.jsx)(`span`,{className:`benchmark-state benchmark-state-${t}`,children:e})}function _C({packet:e,primaryMetric:t}){return(0,z.jsxs)(`div`,{className:`benchmark-view-stack`,children:[(0,z.jsxs)(`section`,{"aria-labelledby":`arm-summary-title`,children:[(0,z.jsxs)(`div`,{className:`benchmark-section-heading`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`p`,{className:`benchmark-kicker`,children:`ARM SUMMARY`}),(0,z.jsx)(`h2`,{id:`arm-summary-title`,children:`Comparable outcomes, denominator first`})]}),(0,z.jsx)(`p`,{children:`Only one score-countable run per declared case × arm cell is selected.`})]}),(0,z.jsx)(`div`,{className:`benchmark-arm-grid`,children:e.arms.map(e=>{let n=Object.values(e.binary_outcomes)[0];return(0,z.jsxs)(`article`,{className:`benchmark-arm-card`,children:[(0,z.jsxs)(`div`,{className:`benchmark-card-heading`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`span`,{className:`benchmark-mono`,children:e.arm_role}),(0,z.jsx)(`h3`,{children:e.arm_id})]}),(0,z.jsx)(gC,{tone:e.coverage_rate===1?`success`:`warning`,children:e.coverage_rate===1?`Complete`:`Provisional`})]}),(0,z.jsxs)(`dl`,{className:`benchmark-stat-list`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsxs)(`dt`,{children:[`Primary · `,t]}),(0,z.jsx)(`dd`,{children:mC(e,t)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Score-countable coverage`}),(0,z.jsxs)(`dd`,{children:[e.selected_score_countable_case_count,`/`,e.intended_case_count]})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Binary success`}),(0,z.jsx)(`dd`,{children:n?`${n.success_count}/${n.case_denominator}`:`Not declared`})]})]})]},e.arm_id)})})]}),(0,z.jsxs)(`section`,{"aria-labelledby":`contrast-title`,children:[(0,z.jsxs)(`div`,{className:`benchmark-section-heading`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`p`,{className:`benchmark-kicker`,children:`MATCHED CONTRASTS`}),(0,z.jsx)(`h2`,{id:`contrast-title`,children:`Direction counts on eligible pairs`})]}),(0,z.jsx)(`p`,{children:`Raw run volume is never used as a comparison denominator.`})]}),(0,z.jsx)(`div`,{className:`benchmark-table-shell`,children:(0,z.jsxs)(`table`,{children:[(0,z.jsx)(`thead`,{children:(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`th`,{children:`Candidate arm`}),(0,z.jsx)(`th`,{children:`Matched denominator`}),(0,z.jsx)(`th`,{children:`Improved`}),(0,z.jsx)(`th`,{children:`Flat`}),(0,z.jsx)(`th`,{children:`Regressed`}),(0,z.jsx)(`th`,{children:`Binary transitions`})]})}),(0,z.jsxs)(`tbody`,{children:[Object.entries(e.contrasts).map(([e,t])=>(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`td`,{children:(0,z.jsx)(`strong`,{children:e})}),(0,z.jsx)(`td`,{children:t.matched_pair_denominator}),(0,z.jsx)(`td`,{className:`benchmark-positive`,children:t.primary_metric_directions.improved}),(0,z.jsx)(`td`,{children:t.primary_metric_directions.flat}),(0,z.jsx)(`td`,{className:`benchmark-negative`,children:t.primary_metric_directions.regressed}),(0,z.jsx)(`td`,{children:Object.entries(t.binary_metric_transitions).map(([e,t])=>`${e}: 0→1 ${t[`0_to_1`]}, 1→0 ${t[`1_to_0`]}, same ${t.same}`).join(` · `)||`—`})]},e)),Object.keys(e.contrasts).length===0&&(0,z.jsx)(`tr`,{children:(0,z.jsx)(`td`,{colSpan:6,children:`No matched comparisons are countable yet.`})})]})]})})]}),(0,z.jsxs)(`section`,{"aria-labelledby":`runtime-health-title`,children:[(0,z.jsxs)(`div`,{className:`benchmark-section-heading`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`p`,{className:`benchmark-kicker`,children:`RUNTIME HEALTH`}),(0,z.jsx)(`h2`,{id:`runtime-health-title`,children:`Qualified observations, without execution authority`})]}),(0,z.jsxs)(`p`,{children:[e.campaign.runtime_observation_count,` public-safe runtime observations.`]})]}),(0,z.jsxs)(`div`,{className:`benchmark-runtime-list`,children:[Object.entries(e.campaign.runtime_classification_counts).map(([e,t])=>(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`span`,{children:e}),(0,z.jsx)(`strong`,{children:t})]},e)),e.campaign.runtime_observation_count===0&&(0,z.jsx)(`p`,{className:`benchmark-muted`,children:`No runtime observations uploaded.`})]})]})]})}function vC({packet:e}){return(0,z.jsx)(`div`,{className:`benchmark-detail-grid`,children:e.arms.map(t=>(0,z.jsxs)(`article`,{className:`benchmark-detail-card`,children:[(0,z.jsxs)(`div`,{className:`benchmark-card-heading`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`span`,{className:`benchmark-mono`,children:t.arm_role}),(0,z.jsx)(`h2`,{children:t.arm_id})]}),(0,z.jsxs)(gC,{tone:t.coverage_rate===1?`success`:`warning`,children:[t.selected_score_countable_case_count,`/`,t.intended_case_count,` countable`]})]}),(0,z.jsx)(`div`,{className:`benchmark-factor-row`,children:Object.entries(t.factor_assignments).map(([e,t])=>(0,z.jsxs)(`span`,{children:[e,`: `,(0,z.jsx)(`strong`,{children:t})]},e))}),(0,z.jsxs)(`dl`,{className:`benchmark-stat-list`,children:[e.design.metric_catalog.map(e=>(0,z.jsxs)(`div`,{children:[(0,z.jsxs)(`dt`,{children:[e.role,` · `,e.metric_name]}),(0,z.jsx)(`dd`,{children:mC(t,e.metric_name)})]},e.metric_name)),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Runs terminal / observed`}),(0,z.jsxs)(`dd`,{children:[t.terminal_run_count,`/`,t.run_count]})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Median duration`}),(0,z.jsx)(`dd`,{children:dC(t.effort.duration_ms?.median)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Protocols`}),(0,z.jsx)(`dd`,{children:fC(t.protocol_counts)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Runner revisions`}),(0,z.jsx)(`dd`,{children:fC(t.runner_revision_counts)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Orchestrator runtimes`}),(0,z.jsxs)(`dd`,{children:[Object.keys(t.orchestrator_runtime_counts).length||0,` distinct`]})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Failure classes`}),(0,z.jsx)(`dd`,{children:fC(t.failure_class_counts)})]})]})]},t.arm_id))})}function yC({packet:e,primaryMetric:t,onOpenRun:n}){return(0,z.jsx)(`div`,{className:`benchmark-table-shell benchmark-wide-table`,children:(0,z.jsxs)(`table`,{children:[(0,z.jsx)(`thead`,{children:(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`th`,{children:`Case`}),(0,z.jsx)(`th`,{children:`Design status`}),(0,z.jsx)(`th`,{children:`Largest eligible delta`}),e.arms.map(e=>(0,z.jsx)(`th`,{children:e.arm_id},e.arm_id))]})}),(0,z.jsx)(`tbody`,{children:e.cases.map(r=>{let i=hC(r,t);return(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`td`,{children:(0,z.jsx)(`strong`,{children:r.case_id})}),(0,z.jsx)(`td`,{children:(0,z.jsx)(gC,{tone:r.complete_declared_design?`success`:`warning`,children:r.complete_declared_design?`Complete`:`Provisional`})}),(0,z.jsx)(`td`,{className:i?.direction===`improved`?`benchmark-positive`:i?.direction===`regressed`?`benchmark-negative`:void 0,children:i?.text??`—`}),r.arms.map(r=>(0,z.jsx)(`td`,{children:r.selected_run_id&&r.score_countable?(0,z.jsxs)(`button`,{className:`benchmark-cell-link`,onClick:()=>n(r.selected_run_id),type:`button`,children:[(0,z.jsxs)(`span`,{children:[t,`: `,pC(r.metrics[t])]}),e.design.metric_catalog.filter(e=>e.metric_name!==t).map(e=>(0,z.jsxs)(`small`,{className:`benchmark-cell-metric`,children:[e.metric_name,`: `,pC(r.metrics[e.metric_name])]},e.metric_name)),(0,z.jsxs)(`small`,{children:[`Countable · `,dC(r.effort.duration_ms),` `,(0,z.jsx)(Rp,{"aria-hidden":`true`,size:12})]}),r.insight&&(0,z.jsxs)(`small`,{children:[r.insight.failure_class,` · `,r.insight.confidence]})]}):(0,z.jsx)(`span`,{className:`benchmark-muted`,children:`Not countable`})},r.arm_id))]},r.case_id)})})]})})}function bC({run:e,packet:t}){return(0,z.jsxs)(`aside`,{"aria-label":`Run detail for ${e.run_id}`,className:`benchmark-run-detail`,children:[(0,z.jsxs)(`div`,{className:`benchmark-card-heading`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`span`,{className:`benchmark-mono`,children:`RUN DETAIL`}),(0,z.jsx)(`h2`,{children:e.run_id})]}),(0,z.jsx)(gC,{tone:e.countability.score_countable?`success`:`warning`,children:e.countability.score_countable?`Score-countable`:`Diagnostic only`})]}),(0,z.jsxs)(`dl`,{className:`benchmark-stat-list benchmark-run-facts`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Case / arm`}),(0,z.jsxs)(`dd`,{children:[e.case_id,` · `,e.arm_id]})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Lifecycle`}),(0,z.jsxs)(`dd`,{children:[e.status,` · `,e.observed_at]})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Protocol`}),(0,z.jsx)(`dd`,{children:e.protocol_id})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Qualification`}),(0,z.jsxs)(`dd`,{children:[`Integrity `,e.countability.integrity_qualified?`qualified`:`not qualified`,` · result `,e.countability.official_result_present?`present`:`missing`]})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Treatment fidelity`}),(0,z.jsx)(`dd`,{children:e.treatment_fidelity})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Effort`}),(0,z.jsxs)(`dd`,{children:[dC(e.effort.duration_ms),` · `,uC(e.effort.agent_steps),` steps · `,uC(e.effort.token_count),` tokens`]})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Runner revision`}),(0,z.jsx)(`dd`,{children:e.runner_revision??`—`})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Upload provenance`}),(0,z.jsxs)(`dd`,{children:[e.upload_provenance.producer_id,` · `,e.upload_provenance.source_revision]})]})]}),(0,z.jsx)(`div`,{className:`benchmark-run-metrics`,children:t.design.metric_catalog.map(t=>(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`span`,{children:t.metric_name}),(0,z.jsx)(`strong`,{children:pC(e.metrics[t.metric_name])})]},t.metric_name))}),e.redacted_insight&&(0,z.jsxs)(`div`,{className:`benchmark-insight`,children:[(0,z.jsxs)(`span`,{className:`benchmark-mono`,children:[`REDACTED CASE INSIGHT · `,e.redacted_insight.confidence]}),(0,z.jsx)(`p`,{children:e.redacted_insight.causal_summary}),(0,z.jsxs)(`small`,{children:[`Implication: `,e.redacted_insight.implication]}),(0,z.jsx)(`br`,{}),(0,z.jsxs)(`small`,{children:[`Next probe: `,e.redacted_insight.next_probe]}),!!e.redacted_insight.evidence_refs?.length&&(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`br`,{}),(0,z.jsxs)(`small`,{children:[`Evidence: `,e.redacted_insight.evidence_refs.join(`, `)]})]})]})]})}function xC({packet:e,selectedRunId:t,onSelectRun:n}){let r=e.runs.find(e=>e.run_id===t)??e.runs[0];return(0,z.jsxs)(`div`,{className:`benchmark-runs-layout`,children:[(0,z.jsx)(`div`,{className:`benchmark-table-shell`,children:(0,z.jsxs)(`table`,{children:[(0,z.jsx)(`thead`,{children:(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`th`,{children:`Run`}),(0,z.jsx)(`th`,{children:`Case`}),(0,z.jsx)(`th`,{children:`Arm`}),(0,z.jsx)(`th`,{children:`Status`}),(0,z.jsx)(`th`,{children:`Countability`})]})}),(0,z.jsx)(`tbody`,{children:e.runs.map(e=>(0,z.jsxs)(`tr`,{"aria-selected":e.run_id===r?.run_id,children:[(0,z.jsx)(`td`,{children:(0,z.jsx)(`button`,{className:`benchmark-run-link`,onClick:()=>n(e.run_id),type:`button`,children:e.run_id})}),(0,z.jsx)(`td`,{children:e.case_id}),(0,z.jsx)(`td`,{children:e.arm_id}),(0,z.jsx)(`td`,{children:e.status}),(0,z.jsx)(`td`,{children:e.countability.score_countable?`Score-countable`:`Diagnostic only`})]},e.run_id))})]})}),r&&(0,z.jsx)(bC,{packet:e,run:r})]})}function SC(){let e=LC.useSearch(),t=LC.useNavigate(),[n,r]=(0,R.useState)(null),[i,a]=(0,R.useState)(null),[o,s]=(0,R.useState)(0),c=(0,R.useMemo)(()=>{let t=e.dashboardUrl||`/chat/benchmark-study.example.json`;try{return{url:sC(t,window.location.href),error:null}}catch(e){return{url:``,error:e instanceof Error?e.message:`Invalid dashboard source`}}},[e.dashboardUrl]);if((0,R.useEffect)(()=>{let e=!0;return r(null),a(null),c.error?(a(c.error),()=>{e=!1}):(fetch(c.url,{cache:`no-store`}).then(async e=>{if(!e.ok)throw Error(`HTTP ${e.status} while loading the dashboard packet`);return oC(await e.json())}).then(t=>{e&&r(t)}).catch(t=>{e&&a(t instanceof Error?t.message:`Unable to load dashboard packet`)}),()=>{e=!1})},[o,c]),(0,R.useEffect)(()=>{n&&(document.title=`${n.design.labels.title??n.study_id} · LoopX Benchmark`)},[n]),i)return(0,z.jsxs)(`main`,{className:`benchmark-page benchmark-loading`,children:[(0,z.jsx)(Xp,{"aria-hidden":`true`}),(0,z.jsx)(`h1`,{children:`Dashboard packet unavailable`}),(0,z.jsx)(`p`,{children:i}),(0,z.jsxs)(`button`,{onClick:()=>s(e=>e+1),type:`button`,children:[(0,z.jsx)(Om,{"aria-hidden":`true`,size:16}),` Retry readback`]})]});if(!n)return(0,z.jsxs)(`main`,{"aria-busy":`true`,className:`benchmark-page benchmark-loading`,children:[(0,z.jsx)(Fp,{"aria-hidden":`true`}),(0,z.jsx)(`h1`,{children:`Reading benchmark study`}),(0,z.jsx)(`p`,{children:`Validating the public-safe dashboard packet…`})]});let l=n.design.metric_catalog.find(e=>e.role===`primary`)?.metric_name??`primary`,u=(n,r=e.runId)=>t({search:e=>({...e,view:n,runId:r})}),d=new URL(c.url).pathname;return(0,z.jsxs)(`main`,{className:`benchmark-page`,children:[(0,z.jsxs)(`header`,{className:`benchmark-hero`,children:[(0,z.jsxs)(`div`,{className:`benchmark-hero-topline`,children:[(0,z.jsx)(`a`,{className:`benchmark-wordmark`,href:`/chat/`,children:`LoopX`}),(0,z.jsxs)(`div`,{className:`benchmark-readonly`,children:[(0,z.jsx)(Im,{"aria-hidden":`true`,size:15}),` Derived read-only projection`]})]}),(0,z.jsxs)(`div`,{className:`benchmark-hero-grid`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsxs)(`p`,{className:`benchmark-kicker`,children:[`BENCHMARK STUDY / `,n.benchmark_id]}),(0,z.jsxs)(`div`,{className:`benchmark-title-row`,children:[(0,z.jsx)(`h1`,{children:n.design.labels.title??n.study_id}),(0,z.jsx)(gC,{tone:n.status===`complete`?`success`:`warning`,children:n.status})]}),(0,z.jsx)(`p`,{className:`benchmark-lead`,children:`One declared study, explicit denominators, and the same countability rules from campaign summary to exact run.`})]}),(0,z.jsxs)(`dl`,{className:`benchmark-identity`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Study`}),(0,z.jsx)(`dd`,{children:n.study_id})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Protocol`}),(0,z.jsx)(`dd`,{children:n.design.protocol_id})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`dt`,{children:`Case set`}),(0,z.jsx)(`dd`,{children:n.design.case_set.case_set_id})]})]})]}),(0,z.jsxs)(`div`,{className:`benchmark-kpi-grid`,children:[(0,z.jsxs)(`article`,{children:[(0,z.jsx)(tm,{"aria-hidden":`true`}),(0,z.jsx)(`span`,{children:`Score-countable cells`}),(0,z.jsxs)(`strong`,{children:[n.campaign.selected_score_countable_cell_count,(0,z.jsxs)(`small`,{children:[` / `,n.campaign.intended_cell_denominator]})]}),(0,z.jsxs)(`p`,{children:[lC(n.campaign.selected_score_countable_coverage_rate),` declared coverage`]})]}),(0,z.jsxs)(`article`,{children:[(0,z.jsx)(Zp,{"aria-hidden":`true`}),(0,z.jsx)(`span`,{children:`Complete designs`}),(0,z.jsxs)(`strong`,{children:[n.campaign.complete_declared_design_case_count,(0,z.jsxs)(`small`,{children:[` / `,n.campaign.intended_case_count]})]}),(0,z.jsx)(`p`,{children:`Cases with every declared arm`})]}),(0,z.jsxs)(`article`,{children:[(0,z.jsx)(Rp,{"aria-hidden":`true`}),(0,z.jsx)(`span`,{children:`Matched comparisons`}),(0,z.jsx)(`strong`,{children:n.campaign.matched_pair_countable_count}),(0,z.jsx)(`p`,{children:`Eligible pairs only`})]}),(0,z.jsxs)(`article`,{children:[(0,z.jsx)(Fp,{"aria-hidden":`true`}),(0,z.jsx)(`span`,{children:`In flight`}),(0,z.jsx)(`strong`,{children:n.campaign.in_flight_run_count}),(0,z.jsx)(`p`,{children:n.status===`provisional`?`Coverage remains provisional`:`Declared coverage complete`})]})]})]}),(0,z.jsxs)(`nav`,{"aria-label":`Benchmark dashboard views`,className:`benchmark-tabs`,children:[cC.map(t=>(0,z.jsx)(`button`,{"aria-current":e.view===t.id?`page`:void 0,onClick:()=>u(t.id),type:`button`,children:t.label},t.id)),(0,z.jsxs)(`button`,{className:`benchmark-refresh`,onClick:()=>s(e=>e+1),type:`button`,children:[(0,z.jsx)(Om,{"aria-hidden":`true`,size:14}),` Refresh local readback`]})]}),(0,z.jsxs)(`div`,{className:`benchmark-content`,children:[e.view===`campaign`&&(0,z.jsx)(_C,{packet:n,primaryMetric:l}),e.view===`arms`&&(0,z.jsx)(vC,{packet:n}),e.view===`cases`&&(0,z.jsx)(yC,{onOpenRun:e=>u(`runs`,e),packet:n,primaryMetric:l}),e.view===`runs`&&(0,z.jsx)(xC,{onSelectRun:e=>u(`runs`,e),packet:n,selectedRunId:e.runId})]}),(0,z.jsxs)(`footer`,{className:`benchmark-footer`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(Im,{"aria-hidden":`true`,size:16}),(0,z.jsxs)(`span`,{children:[`Scores: `,n.authority.score_source]}),(0,z.jsx)(`span`,{children:`Dashboard cannot launch, grade, or mutate runs.`})]}),(0,z.jsxs)(`code`,{title:d,children:[`local`,d]})]})]})}var CC=J({goalId:W().optional().default(``),statusUrl:W().optional().default(``)}),wC=J({goalId:W().optional().default(``),mode:Y([`showcase`,`developer`,`ops`]).optional().default(`showcase`),statusUrl:W().optional().default(``),todoLane:Y([`all`,`user`,`agent`]).optional().default(`all`),todoQuery:W().optional().default(``)}),TC=wC.omit({mode:!0}),EC=J({dashboardUrl:W().optional().default(``),view:Y([`campaign`,`arms`,`cases`,`runs`]).optional().default(`campaign`),runId:W().optional().default(``)});function DC(){let e=`https://huangruiteng.github.io/loopx/docs/showcases/index.en.html`;return(0,R.useEffect)(()=>{window.location.replace(e)},[]),(0,z.jsx)(`a`,{href:e,children:`Open LoopX cases / 浏览案例`})}function OC({goalId:e,statusUrl:t}){let n=t?Ym(t,window.location.href):null;return n?.error?(0,z.jsx)(`main`,{role:`alert`,children:n.error}):(0,z.jsx)(ii,{replace:!0,to:`/`,search:{goalId:e,statusUrl:t}})}function kC(){let e=NC.useSearch();return e.mode===`ops`?(0,z.jsx)(OC,{...e}):e.mode===`developer`?(0,z.jsx)(ii,{replace:!0,to:`/developers/projections`}):(0,z.jsx)(DC,{})}function AC(){return(0,z.jsx)(OC,{...PC.useSearch()})}var jC=Ci({component:()=>(0,z.jsx)(Mi,{}),errorComponent:()=>(0,z.jsxs)(`main`,{role:`alert`,className:`p-8`,children:[(0,z.jsx)(`h1`,{children:`页面暂时无法显示 / Page unavailable`}),(0,z.jsx)(`p`,{children:`请重新加载页面;这不会执行任务。 / Reloading does not execute tasks.`}),(0,z.jsx)(`button`,{type:`button`,onClick:()=>window.location.reload(),children:`重新加载 / Reload`})]})}),MC=xi({getParentRoute:()=>jC,path:`/`,validateSearch:e=>CC.parse(e),component:FS}),NC=xi({getParentRoute:()=>jC,path:`/frontstage`,validateSearch:e=>wC.parse(e),component:kC}),PC=xi({getParentRoute:()=>jC,path:`/deprecated/frontstage/ops`,validateSearch:e=>TC.parse(e),component:AC}),FC=xi({getParentRoute:()=>jC,path:`/frontstage/developer`,component:()=>(0,z.jsx)(ii,{replace:!0,to:`/developers/projections`})}),IC=xi({getParentRoute:()=>jC,path:`/developers/projections`,component:YS}),LC=xi({getParentRoute:()=>jC,path:`/benchmarks/study`,validateSearch:e=>EC.parse(e),component:SC}),RC=jC.addChildren([MC,NC,PC,FC,IC,LC]);function zC(e){return!e||e===`/`||e===`./`?`/`:(e.startsWith(`/`)?e:`/${e}`).replace(/\/+$/,``)||`/`}var BC=Li({routeTree:RC,basepath:zC(`/chat/`),trailingSlash:`preserve`}),VC=document.getElementById(`root`);if(!VC)throw Error(`Root element not found`);var HC=new je({defaultOptions:{queries:{refetchOnWindowFocus:!1,retry:1,staleTime:1e4}}});(0,Vi.createRoot)(VC).render((0,z.jsx)(Fe,{client:HC,children:(0,z.jsx)(qi,{children:(0,z.jsx)(Bi,{router:BC})})})); \ No newline at end of file diff --git a/loopx/web/chat/index.html b/loopx/web/chat/index.html index 98783eb2be..a9a238c053 100644 --- a/loopx/web/chat/index.html +++ b/loopx/web/chat/index.html @@ -18,7 +18,7 @@ content="LoopX 个人 Agent 工作区:在同一个频道里查看、纠偏并推进 Goal。" /> LoopX 个人 Agent 工作区 - + From 7183a882dd87fd033bb27bce44df886a8f80e7e5 Mon Sep 17 00:00:00 2001 From: "vlean.wei" Date: Tue, 8 Sep 2026 23:41:28 +0800 Subject: [PATCH 18/23] fix(kiro-cli): render every actionable goal command from the composer The canonical composer already existed, but the surfaces a reader actually copies did not use it. The first activation step still hand-wrote `/goal --max `, and the adapter README plus both root README host tables carried the same incomplete command. --validate appeared only in a neighbouring sentence, which cannot repair a command that has already been copied and run: the host then judges each iteration by its own default completion standard instead of the Todo's acceptance criteria. The activation step now renders kiro_cli_goal_invocation() and folds the criteria substitution into the same step, so there is no separate literal to drift. The three documentation surfaces carry the complete command, keeping the English and Chinese rows in parity. Signed-off-by: vlean.wei --- README.md | 2 +- README.zh-CN.md | 2 +- loopx/kiro_cli_goal_mode/README.md | 12 +++++++----- loopx/kiro_cli_goal_mode/__init__.py | 11 +++++------ 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 3d891f78fb..528ff48aa5 100644 --- a/README.md +++ b/README.md @@ -295,7 +295,7 @@ LoopX should reuse existing state rather than overwrite it. Keep `.loopx/`, | Pi | Install the opt-in goal extension with `loopx slash-commands --install --surface pi`, then use `/loopx ` from a trusted Pi session. | Visible Pi goal extension gated by LoopX quota (`loopx_goal_activate` + `agent_settled` continuation) | | ZCode | Install the skill facade with `loopx slash-commands --install --surface zcode`, then invoke the `$loopx` skill (or `/loopx `) from a ZCode session in the project. | The ZCode session's own turn loop; every continuation enters through `quota should-run` | | Antigravity CLI (agy) | Install the skill facade with `loopx slash-commands --install --surface agy`, then invoke the `loopx` skill (or `/loopx `) from an `agy` session in the project. | The session's native `/goal` loop (audited until ``) with `schedule` self-wakes while the session lives; the facade instructs every turn/wake to re-enter through `quota should-run` — advisory pacing, not a host-enforced gate | -| Kiro CLI | Install the skill facade with `loopx slash-commands --install --surface kiro-cli`, then run `/loopx ` from a `kiro-cli` session in the project. | The session's native `/goal --max ` loop, bounded by the host's own iteration budget (default 5, ceiling 50) and settled through the built-in `goal` completion contract; the facade instructs every turn and iteration to re-enter through `quota should-run` — advisory pacing, not a host-enforced gate | +| Kiro CLI | Install the skill facade with `loopx slash-commands --install --surface kiro-cli`, then run `/loopx ` from a `kiro-cli` session in the project. | The session's native `/goal --validate --max ` loop, bounded by the host's own iteration budget (default 5, ceiling 50) and settled through the built-in `goal` completion contract; the facade instructs every turn and iteration to re-enter through `quota should-run` — advisory pacing, not a host-enforced gate | | DeepSeek Harness (dsh) | Install the [native DSH plugin](packages/dsh-loopx-plugin/README.md), select the `loopx` skill, and describe the task. The [dsh goal-mode adapter](loopx/dsh_goal_mode/README.md) remains available for headless turns. | Native same-session continuation and GoalBar, or headless dsh segments; both remain gated by LoopX authority | | Cursor, shell, or custom runner | Use the installer and `loopx doctor`; connect manually or call LoopX from your runner. | Your shell, scheduler, or runner | diff --git a/README.zh-CN.md b/README.zh-CN.md index b61127f9f5..21cb199ca5 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -265,7 +265,7 @@ loopx start-goal --guided --project . --goal-text "你的长程目标" | Pi | 用 `loopx slash-commands --install --surface pi` 安装 opt-in goal extension,然后在受信任的 Pi 会话里用 `/loopx <任务>`。 | 由 LoopX quota gate 的可见 Pi goal extension(`loopx_goal_activate` + `agent_settled` 续跑) | | ZCode | 用 `loopx slash-commands --install --surface zcode` 安装 skill facade,然后在项目里的 ZCode 会话中调用 `$loopx` skill(或 `/loopx <复杂任务>`)。 | ZCode 会话自身的 turn loop;每次续跑都从 `quota should-run` 进入 | | Antigravity CLI(agy) | 用 `loopx slash-commands --install --surface agy` 安装 skill facade,然后在项目里的 `agy` 会话中调用 `loopx` skill(或 `/loopx <复杂任务>`)。 | 会话原生 `/goal` 循环(审计至 ``)加 `schedule` 自唤醒,随会话存活;facade 指示每次 turn/唤醒都先过 `quota should-run`——advisory 节流,非宿主强制 gate | -| Kiro CLI | 用 `loopx slash-commands --install --surface kiro-cli` 安装 skill facade,然后在项目里的 `kiro-cli` 会话中执行 `/loopx <复杂任务>`。 | 会话原生 `/goal <任务> --max ` 循环,由宿主自己的迭代预算兜底(默认 5,上限 50),并通过内置 `goal` 完成契约收口;facade 指示每次 turn 与迭代都先过 `quota should-run`——advisory 节流,非宿主强制 gate | +| Kiro CLI | 用 `loopx slash-commands --install --surface kiro-cli` 安装 skill facade,然后在项目里的 `kiro-cli` 会话中执行 `/loopx <复杂任务>`。 | 会话原生 `/goal <任务> --validate <验收条件> --max ` 循环,由宿主自己的迭代预算兜底(默认 5,上限 50),并通过内置 `goal` 完成契约收口;facade 指示每次 turn 与迭代都先过 `quota should-run`——advisory 节流,非宿主强制 gate | | DeepSeek Harness(dsh) | 安装 [DSH 原生 Plugin](packages/dsh-loopx-plugin/README.md),在技能选择器中点 `loopx`,然后直接描述任务;[dsh goal-mode adapter](loopx/dsh_goal_mode/README.md) 继续支持 headless turn。 | 原生同会话续跑与 GoalBar,或 headless dsh 工作段;两条路径都遵守 LoopX authority | | Cursor、shell、自有 runner | 使用同一 installer 和 `loopx doctor`,再手动连接或由 runner 调用。 | 你的 shell、scheduler 或 runner | diff --git a/loopx/kiro_cli_goal_mode/README.md b/loopx/kiro_cli_goal_mode/README.md index e6b757711a..3d0f4f0b6f 100644 --- a/loopx/kiro_cli_goal_mode/README.md +++ b/loopx/kiro_cli_goal_mode/README.md @@ -60,7 +60,8 @@ Kiro CLI discovers global skills from `/skills//SKILL.md` both as `skill://` resources, and every discovered skill is invocable as a `/` slash command with `$ARGUMENTS` expansion. LoopX reaches a Kiro CLI session through the generated `/loopx` skill facade, and the -activation binds the objective with the native `/goal --max `. +activation binds the objective with the native +`/goal --validate --max `. Three honest limits, stated in the activation packet: @@ -98,10 +99,11 @@ loopx start-goal --guided --project . --slash-command-arguments="" --host- ``` After todo writeback, bind the generated heartbeat task body with -`/goal --max ` — with `N` taken from the remaining quota slots -and never above the host ceiling of 50 — pass the validation the todo already -names as `--validate ` so the host judges each iteration against the -check LoopX will accept, read the loop back with `/goal status`, start every +`/goal --validate --max ` — substituting the +validation the todo already names for `` so the host judges each +iteration against the check LoopX will accept, and `N` taken from the remaining +quota slots and never above the host ceiling of 50 — read the loop back with +`/goal status`, start every turn and native goal iteration with `quota should-run` (advisory guidance; LoopX does not intercept native host iterations), and settle through the built-in `goal` tool only after LoopX writeback so the cited evidence matches diff --git a/loopx/kiro_cli_goal_mode/__init__.py b/loopx/kiro_cli_goal_mode/__init__.py index 0c91ce5789..0c29af03df 100644 --- a/loopx/kiro_cli_goal_mode/__init__.py +++ b/loopx/kiro_cli_goal_mode/__init__.py @@ -171,16 +171,15 @@ def kiro_cli_activation_extras() -> dict[str, Any]: }, "extra_activation_steps": [ "Bind the objective with the native goal command: " - f"`{KIRO_CLI_GOAL_COMMAND} {KIRO_CLI_GOAL_MAX_FLAG} ` " - "— choose N from the remaining quota slots, not from ambition, and " + f"`{kiro_cli_goal_invocation()}` — substitute the validation the " + "LoopX todo already names for `` so the host judges each " + "iteration against the same check LoopX will accept as writeback, " + "and choose N from the remaining quota slots, not from ambition, " f"never above the host ceiling of " f"{KIRO_CLI_GOAL_MAX_ITERATION_CEILING} " f"(host default is {KIRO_CLI_GOAL_DEFAULT_MAX_ITERATIONS}); " f"`{KIRO_CLI_GOAL_CLEAR_COMMAND}` cancels it.", - "Pass the validation the LoopX todo already names as " - f"`{KIRO_CLI_GOAL_VALIDATE_FLAG} ` so the host judges " - "each iteration against the same check LoopX will accept as " - f"writeback, and read the loop back with " + "Read the loop back with " f"`{KIRO_CLI_GOAL_STATUS_COMMAND}` instead of guessing its state.", "Start every turn and native goal iteration with `quota " "should-run` and honor a stop/throttle decision before any " From 2a367c03e51acb18fc3c0239e6d363bd460fd4ae Mon Sep 17 00:00:00 2001 From: "vlean.wei" Date: Tue, 8 Sep 2026 23:41:28 +0800 Subject: [PATCH 19/23] test(kiro-cli): make each command consumer sensitive to a dropped argument The previous assertions pinned the incomplete literal and then searched for --validate anywhere in the joined activation prose, so a complete-looking test suite passed while the copyable command was incomplete. Coverage is now per consumer. A scanner collects every backticked goal command that names a task placeholder and requires each one to be complete on its own; the activation packet, activation extras and onboarding instruction must expose such a command, while the catalog entry and fact tuple only have to keep any command they do render complete. Both READMEs are checked as consumers too, because a reader copies the row rather than the module. Verified in both directions: dropping --validate from the composer fails four tests, and reverting a README row to the old literal fails the consumer test. Signed-off-by: vlean.wei --- tests/test_kiro_cli_host_surface.py | 113 +++++++++++++++++++++++++++- 1 file changed, 109 insertions(+), 4 deletions(-) diff --git a/tests/test_kiro_cli_host_surface.py b/tests/test_kiro_cli_host_surface.py index 933b3d6cc5..f086b8f8af 100644 --- a/tests/test_kiro_cli_host_surface.py +++ b/tests/test_kiro_cli_host_surface.py @@ -11,6 +11,7 @@ import argparse import os +import re from pathlib import Path import pytest @@ -52,10 +53,12 @@ KIRO_CLI_GOAL_STATUS_COMMAND, KIRO_CLI_GOAL_VALIDATE_FLAG, KIRO_CLI_HOME_ENV, + KIRO_CLI_AGENT_TYPE_CATALOG_ENTRY, KIRO_CLI_HOOK_TRIGGERS, SKILLS_ROOT_LABEL as KIRO_CLI_SKILLS_ROOT_LABEL, KIRO_CLI_NATIVE_GOAL_FACTS, KIRO_CLI_SESSION_ID_ENV, + kiro_cli_activation_extras, kiro_cli_chat_command, kiro_cli_goal_invocation, kiro_home, @@ -109,6 +112,103 @@ def test_agent_onboarding_setup_command_installs_the_kiro_cli_surface( ) +def _copyable_goal_commands(value: object) -> list[str]: + """Every backticked native goal command carrying a task placeholder. + + These are the strings a reader or agent copies and runs. A command is only + counted when it names a task placeholder, so prose that merely mentions + `/goal status` or `/goal clear` is not treated as an activation command. + """ + found: list[str] = [] + + def walk(node: object) -> None: + if isinstance(node, str): + for candidate in re.findall(r"`([^`]*?/goal[^`]*?)`", node): + if "" in candidate: + found.append(candidate) + elif isinstance(node, dict): + for item in node.values(): + walk(item) + elif isinstance(node, (list, tuple)): + for item in node: + walk(item) + + walk(value) + return found + + +def assert_no_incomplete_goal_command( + label: str, + value: object, + *, + require_command: bool = False, +) -> None: + """Assert every copyable goal command is complete on its own. + + Presence is a separate question: some surfaces legitimately expose only the + `/loopx` skill entry. Only the surfaces whose job is to hand over the + activation command are required to contain one. + """ + commands = _copyable_goal_commands(value) + if require_command: + assert commands, f"{label} exposes no copyable native goal command" + incomplete = [ + command + for command in commands + if KIRO_CLI_GOAL_VALIDATE_FLAG not in command + ] + assert not incomplete, ( + f"{label} exposes a copyable goal command without " + f"{KIRO_CLI_GOAL_VALIDATE_FLAG}: {incomplete}" + ) + + +def test_every_actionable_consumer_renders_the_complete_goal_command() -> None: + """One assertion per final consumer, sensitive to a dropped argument. + + The canonical composer existed already, but the activation step and the + public README rows still carried hand-written commands. Searching for + `--validate` anywhere in concatenated prose hid that, because the flag was + present in a neighbouring sentence while the copyable command was not. Each + consumer is therefore checked on its own, and every copyable command it + exposes must be complete. + """ + repo_root = Path(__file__).resolve().parents[1] + + # These hand over the activation command, so they must expose one. + for label, value in { + "activation packet": build_host_loop_activation_packet( + agent_type=HOST_SURFACE, goal_id="consumer-probe" + ), + "activation extras": kiro_cli_activation_extras(), + "onboarding recommended start": _start_instruction(HOST_SURFACE), + }.items(): + assert_no_incomplete_goal_command(label, value, require_command=True) + + # These may describe the host without handing over a command, but anything + # they do render must still be complete. + for label, value in { + "agent type catalog entry": KIRO_CLI_AGENT_TYPE_CATALOG_ENTRY, + "native goal facts": KIRO_CLI_NATIVE_GOAL_FACTS, + }.items(): + assert_no_incomplete_goal_command(label, value) + + # Public docs are consumers too: a reader copies the row, not the module. + for doc in ( + "loopx/kiro_cli_goal_mode/README.md", + "README.md", + "README.zh-CN.md", + ): + text = (repo_root / doc).read_text(encoding="utf-8") + kiro_lines = [ + line + for line in text.splitlines() + if "/goal" in line and "kiro" in line.lower() + ] + assert kiro_lines, f"{doc} no longer documents the Kiro goal command" + assert_no_incomplete_goal_command(doc, kiro_lines) + + def test_public_outputs_agree_with_the_canonical_host_facts( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, @@ -392,15 +492,20 @@ def test_activation_binds_native_goal_with_advisory_quota_entry() -> None: assert "installs no Kiro hook" in gate steps = " ".join(packet["activation_steps"]) - assert "`/goal --max `" in steps + # The command must be rendered from the canonical composer, not a hand-kept + # literal. Asserting a literal is what let the activation step drift: it + # pinned an incomplete command while --validate was only mentioned in a + # separate prose step, so an agent copying the command bound a goal the host + # judged by its own default instead of the Todo's criteria. + assert kiro_cli_goal_invocation() in steps assert str(KIRO_CLI_GOAL_MAX_ITERATION_CEILING) in steps assert "quota should-run" in steps assert KIRO_CLI_GOAL_COMPLETION_TOOL in steps assert "no host scheduler to fall back on" not in steps - # The host judges each iteration against --validate criteria; binding the - # goal without them leaves the host checking nothing LoopX will accept. - assert KIRO_CLI_GOAL_VALIDATE_FLAG in steps assert KIRO_CLI_GOAL_STATUS_COMMAND in steps + # Every copyable command in the packet must be complete on its own. Prose + # elsewhere cannot repair a command a reader has already executed. + assert_no_incomplete_goal_command("activation packet", packet) assert packet["setup_command"] == _surface_install_command( HOST_SURFACE, "loopx", "." From 9aa33395f3183ec81d85da5e3a27b114e19a51ed Mon Sep 17 00:00:00 2001 From: "vlean.wei" Date: Wed, 9 Sep 2026 11:42:03 +0800 Subject: [PATCH 20/23] fix(kiro-cli): project only the contracted native goal arguments LoopX claimed a native goal syntax the host does not contract. The projection carried `--validate `, `--agent `, a `status` subcommand and an iteration ceiling of 50, and placed `--max` after the description. Two authoritative sources were checked rather than trusted from the earlier draft. The published command reference documents `/goal `, `/goal --max ` and `/goal clear`, and states that the agent derives its acceptance criteria from the goal statement. The installed host advertises its own command registry over ACP, where `/goal` carries exactly one subcommand, `clear`. Neither contracts the extra arguments, and the ceiling appears in neither. This mattered because the failure was silent rather than loud: an unrecognised flag after the description is read as more goal text, so the objective would be polluted with literal flag names and `--max` would never apply. The previous round made this worse by propagating the flag to every consumer. The composer now renders `/goal --max ` in the documented order and carries the todo's acceptance criteria inside the statement, which is the host's own mechanism for binding them. Removed constants have no remaining consumers. Signed-off-by: vlean.wei --- loopx/agent_onboarding.py | 12 +-- loopx/kiro_cli_goal_mode/__init__.py | 113 ++++++++++++++++----------- 2 files changed, 72 insertions(+), 53 deletions(-) diff --git a/loopx/agent_onboarding.py b/loopx/agent_onboarding.py index 0608f81827..ef10a8ddea 100644 --- a/loopx/agent_onboarding.py +++ b/loopx/agent_onboarding.py @@ -18,8 +18,7 @@ from .kiro_cli_goal_mode import ( KIRO_CLI_GOAL_CLEAR_COMMAND, KIRO_CLI_GOAL_COMPLETION_TOOL, - KIRO_CLI_GOAL_MAX_ITERATION_CEILING, - KIRO_CLI_GOAL_STATUS_COMMAND, + KIRO_CLI_GOAL_DEFAULT_MAX_ITERATIONS, SKILLS_ROOT_LABEL as KIRO_CLI_SKILLS_ROOT_LABEL, kiro_cli_goal_invocation, ) @@ -371,10 +370,11 @@ def _start_instruction(agent_type: str) -> str: f"Run `/loopx ` (the LoopX skill installed in " f"`{KIRO_CLI_SKILLS_ROOT_LABEL}`); after todo writeback, bind the " f"objective with the native `{kiro_cli_goal_invocation()}` command, " - f"taking N from the remaining quota slots and never above the host " - f"ceiling of {KIRO_CLI_GOAL_MAX_ITERATION_CEILING} " - f"(`{KIRO_CLI_GOAL_CLEAR_COMMAND}` cancels, " - f"`{KIRO_CLI_GOAL_STATUS_COMMAND}` reads the bound goal back). " + f"stating the todo's acceptance criteria inside the goal statement " + f"because the host derives them from it, and taking N from the " + f"remaining quota slots (host default is " + f"{KIRO_CLI_GOAL_DEFAULT_MAX_ITERATIONS}; " + f"`{KIRO_CLI_GOAL_CLEAR_COMMAND}` cancels). " f"Start every turn and native goal iteration with `quota " f"should-run`, and settle through the built-in " f"`{KIRO_CLI_GOAL_COMPLETION_TOOL}` tool only after LoopX writeback " diff --git a/loopx/kiro_cli_goal_mode/__init__.py b/loopx/kiro_cli_goal_mode/__init__.py index 0c29af03df..7484e7edbf 100644 --- a/loopx/kiro_cli_goal_mode/__init__.py +++ b/loopx/kiro_cli_goal_mode/__init__.py @@ -39,24 +39,34 @@ KIRO_CLI_CHAT_ACP_SUBCOMMAND = "acp" KIRO_CLI_CHAT_ADAPTER_KIND = "acp" -# Native goal primitive built into the kiro-cli binary. Probed on -# `kiro-cli-chat 2.21.1` (app bundle 20260904.123104; both `kiro-cli` and -# `kiro-cli-chat` report 2.21.1): the binary carries the hint -# `/goal [description --validate criteria --agent name --max N] | clear`, the -# iteration-ceiling rejection message, the `Completed`/`Exhausted` terminal -# states and the per-iteration `passed`/`feedback` result. +# Native goal primitive built into the kiro-cli binary. Only what the host +# itself contracts is recorded here. +# +# Two authoritative sources agree, and both were checked rather than copied +# from an earlier draft: +# * the published command reference documents `/goal `, +# `/goal --max ` and `/goal clear`, and states that the +# agent derives its acceptance criteria from the goal statement; +# * the installed host advertises its own command registry over ACP +# (`_kiro.dev/commands/available`), where `/goal` carries exactly one +# subcommand, `clear`. +# +# An earlier revision of this module also projected `--validate`, `--agent` and +# a `status` subcommand. Neither source contracts them, so LoopX no longer +# emits them: a flag the parser does not recognise would be absorbed into the +# description, silently polluting the objective and dropping the iteration +# budget instead of failing loudly. Acceptance criteria therefore travel inside +# the goal statement, which is the host's documented mechanism. # The host owns the iteration loop: it re-dispatches the turn until the model -# proves completion through the `goal` tool or the iteration budget runs out. +# proves completion or the iteration budget runs out. KIRO_CLI_GOAL_COMMAND = "/goal" KIRO_CLI_GOAL_CLEAR_COMMAND = "/goal clear" -KIRO_CLI_GOAL_STATUS_COMMAND = "/goal status" KIRO_CLI_GOAL_MAX_FLAG = "--max" -KIRO_CLI_GOAL_VALIDATE_FLAG = "--validate" -KIRO_CLI_GOAL_AGENT_FLAG = "--agent" +# The documented mechanism for binding acceptance criteria: state them in the +# goal text so the host's own verification step has a concrete target. +KIRO_CLI_GOAL_CRITERIA_LEAD = "Done when:" KIRO_CLI_GOAL_DEFAULT_MAX_ITERATIONS = 5 -KIRO_CLI_GOAL_MAX_ITERATION_CEILING = 50 KIRO_CLI_GOAL_COMPLETION_TOOL = "goal" -KIRO_CLI_GOAL_TERMINAL_STATES = ("completed", "exhausted") # Kiro CLI stamps every session with a stable id, which is what a LoopX # thread binding can key on instead of prose. @@ -75,16 +85,19 @@ ) KIRO_CLI_NATIVE_GOAL_FACTS = ( - "native `/goal [description --validate criteria --agent name --max N] | " - "clear` command: the host re-dispatches turns toward one objective, judges " - "each iteration against the validation criteria, and stops when completion " - "is proven or the iteration budget is spent (default 5, ceiling 50)", + "native `/goal [--max N] | clear` command: the host " + "re-dispatches turns toward one objective, verifies each iteration against " + "the acceptance criteria it derives from the goal statement, and stops when " + f"the work is confirmed or the iteration budget is spent (default " + f"{KIRO_CLI_GOAL_DEFAULT_MAX_ITERATIONS})", "the built-in `goal` tool's `complete` command enforces a completion " "contract: every success criterion needs cited tool output, not narrative " "confidence", - "`/goal clear` cancels the active goal and `/goal status` reads it back; " - "the loop also stops on Exhausted and pauses after 3 consecutive dispatch " - "failures", + "the host derives acceptance criteria from the goal statement, so LoopX " + "states the todo's criteria inside the description instead of passing a " + "separate flag", + "`/goal clear` cancels the active goal; a running goal is steered in place " + "rather than read back through a status subcommand", "`hooks` in the agent config expose agentSpawn/userPromptSubmit/" "preToolUse/postToolUse/stop, and preToolUse can block a tool call with " "exit code 2", @@ -104,22 +117,31 @@ def kiro_cli_goal_invocation( *, task: str = "", - criteria: str = "", + criteria: str | None = "", max_iterations: str = "", ) -> str: - """The canonical native goal invocation, in the host's own argument order. + """The canonical native goal invocation, in the host's documented order. Every public projection — onboarding instructions, activation packets, - installer notes — must render the command from here. Dropping - ``--validate`` makes the host judge completion by its own reading instead - of the LoopX Todo's acceptance criteria, and a hand-copied string in a - second consumer is exactly how that flag went missing before. + docs — must render the command from here. + + The host documents ``/goal --max ``: the iteration flag + precedes the description, and everything after it is the goal statement. + Acceptance criteria therefore belong *inside* that statement, because the + host derives them from it; there is no criteria flag to pass. Appending an + unrecognised flag after the description would not fail loudly — it would be + read as more goal text, polluting the objective and silently dropping the + iteration budget. """ + description = ( + task + if not criteria + else f"{task} {KIRO_CLI_GOAL_CRITERIA_LEAD} {criteria}" + ) return ( - f"{KIRO_CLI_GOAL_COMMAND} {task} " - f"{KIRO_CLI_GOAL_VALIDATE_FLAG} {criteria} " - f"--max {max_iterations}" + f"{KIRO_CLI_GOAL_COMMAND} {KIRO_CLI_GOAL_MAX_FLAG} {max_iterations} " + f"{description}" ) @@ -145,42 +167,39 @@ def kiro_cli_activation_extras() -> dict[str, Any]: "quota_gate_enforcement": "advisory_only", "native_goal_command": KIRO_CLI_GOAL_COMMAND, "native_goal_cancel_command": KIRO_CLI_GOAL_CLEAR_COMMAND, - "native_goal_status_command": KIRO_CLI_GOAL_STATUS_COMMAND, "native_goal_max_flag": KIRO_CLI_GOAL_MAX_FLAG, - "native_goal_validate_flag": KIRO_CLI_GOAL_VALIDATE_FLAG, + "native_goal_criteria_placement": "inside_goal_statement", "native_goal_default_max_iterations": ( KIRO_CLI_GOAL_DEFAULT_MAX_ITERATIONS ), - "native_goal_max_iteration_ceiling": ( - KIRO_CLI_GOAL_MAX_ITERATION_CEILING - ), "native_goal_completion_tool": KIRO_CLI_GOAL_COMPLETION_TOOL, "host_session_id_env": KIRO_CLI_SESSION_ID_ENV, "host_hook_triggers": list(KIRO_CLI_HOOK_TRIGGERS), "missing_host_tool_gate": ( "Kiro CLI's /goal loop runs only while the CLI session is " - "alive; there is no cross-session daemon and the host caps it " - f"at {KIRO_CLI_GOAL_MAX_ITERATION_CEILING} iterations. LoopX " + "alive; there is no cross-session daemon, and the host stops " + "the loop on its own turn and context limits rather than a " + "LoopX-declared iteration ceiling. LoopX " "installs no Kiro hook, so no host hook intercepts a native " "iteration and quota pacing is advisory: the facade instructs, " - "it cannot enforce. If the goal reaches Exhausted or the " - "session ends with work remaining, show the exact " + "it cannot enforce. If the loop stops with work remaining, " + "show the exact " "heartbeat-prompt command for the user to run and do not " "claim unattended heartbeat support." ), }, "extra_activation_steps": [ "Bind the objective with the native goal command: " - f"`{kiro_cli_goal_invocation()}` — substitute the validation the " - "LoopX todo already names for `` so the host judges each " - "iteration against the same check LoopX will accept as writeback, " - "and choose N from the remaining quota slots, not from ambition, " - f"never above the host ceiling of " - f"{KIRO_CLI_GOAL_MAX_ITERATION_CEILING} " + f"`{kiro_cli_goal_invocation()}` — the host derives its acceptance " + "criteria from the goal statement, so state the criteria the LoopX " + f"todo already names after `{KIRO_CLI_GOAL_CRITERIA_LEAD}` rather " + "than passing a separate flag, and choose N from the remaining " + "quota slots, not from ambition " f"(host default is {KIRO_CLI_GOAL_DEFAULT_MAX_ITERATIONS}); " f"`{KIRO_CLI_GOAL_CLEAR_COMMAND}` cancels it.", - "Read the loop back with " - f"`{KIRO_CLI_GOAL_STATUS_COMMAND}` instead of guessing its state.", + "Steer a running goal in place instead of expecting a status " + "readback: the host exposes cancellation and mid-loop steering, " + "not a goal status subcommand.", "Start every turn and native goal iteration with `quota " "should-run` and honor a stop/throttle decision before any " "delivery work — instructed pacing, not a host-enforced gate.", @@ -188,8 +207,8 @@ def kiro_cli_activation_extras() -> dict[str, Any]: "tool only after LoopX writeback: its completion contract wants " "the same cited evidence LoopX records, so cite the validated " "commands rather than a narrative summary.", - "When the goal reports Exhausted and quota still allows more " - "work, re-arm one further bounded goal instead of free-running, " + "When the loop stops with work remaining and quota still allows " + "more, re-arm one further bounded goal instead of free-running, " "and re-enter through `quota should-run` on the same advisory " "basis.", ], From 24200aba6e3a11ce7af56a2ca8faf30213e74dc5 Mon Sep 17 00:00:00 2001 From: "vlean.wei" Date: Wed, 9 Sep 2026 11:42:20 +0800 Subject: [PATCH 21/23] docs(kiro-cli): correct the documented goal syntax The adapter README and both root README host rows taught the unsupported syntax, and the adapter README cited a `strings` probe of the binary as the source. That probe returns nothing on the shipped app bundle, so it could not have established the facts it was credited with. All three surfaces now show `/goal --max ` with the acceptance criteria inside the statement, and the adapter README points at a probe that actually works and states plainly which arguments were withdrawn. The English and Chinese rows stay in parity. Signed-off-by: vlean.wei --- README.md | 2 +- README.zh-CN.md | 2 +- loopx/kiro_cli_goal_mode/README.md | 63 +++++++++++++++--------------- 3 files changed, 34 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 528ff48aa5..d5c46152d1 100644 --- a/README.md +++ b/README.md @@ -295,7 +295,7 @@ LoopX should reuse existing state rather than overwrite it. Keep `.loopx/`, | Pi | Install the opt-in goal extension with `loopx slash-commands --install --surface pi`, then use `/loopx ` from a trusted Pi session. | Visible Pi goal extension gated by LoopX quota (`loopx_goal_activate` + `agent_settled` continuation) | | ZCode | Install the skill facade with `loopx slash-commands --install --surface zcode`, then invoke the `$loopx` skill (or `/loopx `) from a ZCode session in the project. | The ZCode session's own turn loop; every continuation enters through `quota should-run` | | Antigravity CLI (agy) | Install the skill facade with `loopx slash-commands --install --surface agy`, then invoke the `loopx` skill (or `/loopx `) from an `agy` session in the project. | The session's native `/goal` loop (audited until ``) with `schedule` self-wakes while the session lives; the facade instructs every turn/wake to re-enter through `quota should-run` — advisory pacing, not a host-enforced gate | -| Kiro CLI | Install the skill facade with `loopx slash-commands --install --surface kiro-cli`, then run `/loopx ` from a `kiro-cli` session in the project. | The session's native `/goal --validate --max ` loop, bounded by the host's own iteration budget (default 5, ceiling 50) and settled through the built-in `goal` completion contract; the facade instructs every turn and iteration to re-enter through `quota should-run` — advisory pacing, not a host-enforced gate | +| Kiro CLI | Install the skill facade with `loopx slash-commands --install --surface kiro-cli`, then run `/loopx ` from a `kiro-cli` session in the project. | The session's native `/goal --max Done when: ` loop, with the acceptance criteria stated inside the goal statement because the host derives them from it, bounded by the host's own iteration budget (default 5) and settled through the built-in `goal` completion contract; the facade instructs every turn and iteration to re-enter through `quota should-run` — advisory pacing, not a host-enforced gate | | DeepSeek Harness (dsh) | Install the [native DSH plugin](packages/dsh-loopx-plugin/README.md), select the `loopx` skill, and describe the task. The [dsh goal-mode adapter](loopx/dsh_goal_mode/README.md) remains available for headless turns. | Native same-session continuation and GoalBar, or headless dsh segments; both remain gated by LoopX authority | | Cursor, shell, or custom runner | Use the installer and `loopx doctor`; connect manually or call LoopX from your runner. | Your shell, scheduler, or runner | diff --git a/README.zh-CN.md b/README.zh-CN.md index 21cb199ca5..62e7830743 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -265,7 +265,7 @@ loopx start-goal --guided --project . --goal-text "你的长程目标" | Pi | 用 `loopx slash-commands --install --surface pi` 安装 opt-in goal extension,然后在受信任的 Pi 会话里用 `/loopx <任务>`。 | 由 LoopX quota gate 的可见 Pi goal extension(`loopx_goal_activate` + `agent_settled` 续跑) | | ZCode | 用 `loopx slash-commands --install --surface zcode` 安装 skill facade,然后在项目里的 ZCode 会话中调用 `$loopx` skill(或 `/loopx <复杂任务>`)。 | ZCode 会话自身的 turn loop;每次续跑都从 `quota should-run` 进入 | | Antigravity CLI(agy) | 用 `loopx slash-commands --install --surface agy` 安装 skill facade,然后在项目里的 `agy` 会话中调用 `loopx` skill(或 `/loopx <复杂任务>`)。 | 会话原生 `/goal` 循环(审计至 ``)加 `schedule` 自唤醒,随会话存活;facade 指示每次 turn/唤醒都先过 `quota should-run`——advisory 节流,非宿主强制 gate | -| Kiro CLI | 用 `loopx slash-commands --install --surface kiro-cli` 安装 skill facade,然后在项目里的 `kiro-cli` 会话中执行 `/loopx <复杂任务>`。 | 会话原生 `/goal <任务> --validate <验收条件> --max ` 循环,由宿主自己的迭代预算兜底(默认 5,上限 50),并通过内置 `goal` 完成契约收口;facade 指示每次 turn 与迭代都先过 `quota should-run`——advisory 节流,非宿主强制 gate | +| Kiro CLI | 用 `loopx slash-commands --install --surface kiro-cli` 安装 skill facade,然后在项目里的 `kiro-cli` 会话中执行 `/loopx <复杂任务>`。 | 会话原生 `/goal --max <任务> Done when: <验收条件>` 循环,验收条件写入目标语句本身(宿主由该语句推导验收标准),由宿主自己的迭代预算兜底(默认 5),并通过内置 `goal` 完成契约收口;facade 指示每次 turn 与迭代都先过 `quota should-run`——advisory 节流,非宿主强制 gate | | DeepSeek Harness(dsh) | 安装 [DSH 原生 Plugin](packages/dsh-loopx-plugin/README.md),在技能选择器中点 `loopx`,然后直接描述任务;[dsh goal-mode adapter](loopx/dsh_goal_mode/README.md) 继续支持 headless turn。 | 原生同会话续跑与 GoalBar,或 headless dsh 工作段;两条路径都遵守 LoopX authority | | Cursor、shell、自有 runner | 使用同一 installer 和 `loopx doctor`,再手动连接或由 runner 调用。 | 你的 shell、scheduler 或 runner | diff --git a/loopx/kiro_cli_goal_mode/README.md b/loopx/kiro_cli_goal_mode/README.md index 3d0f4f0b6f..4d52a8c932 100644 --- a/loopx/kiro_cli_goal_mode/README.md +++ b/loopx/kiro_cli_goal_mode/README.md @@ -8,40 +8,41 @@ to the host's own loop instead of pretending the agent merely drives itself. ## Native goal primitive -`/goal [description --validate criteria --agent name --max N] | clear` — the -built-in command, exactly as the host's own hint states it. The host -re-dispatches turns toward the stated objective, judges each iteration against -the validation criteria, and the model must prove completion through the -built-in `goal` tool before the loop ends. - -- Iteration budget is host-enforced: default `5`, ceiling `50`. This is the - one part of the loop LoopX does not have to trust the model for. -- `--validate ` states what the host checks each iteration; its - per-iteration result carries `passed` plus `feedback`, so LoopX passes the - validation it already owns instead of leaving the criteria implicit. -- `--agent ` picks which agent config runs the goal. LoopX does not set - it: the LoopX skill facade must stay reachable from whichever agent the user - chose. -- `/goal clear` cancels the active goal and `/goal status` reads the current - one back. The loop also stops in `Exhausted` (budget spent without - completion) and pauses after 3 consecutive dispatch failures. +`/goal [--max N] | clear` — the built-in command as the host +contracts it. The host re-dispatches turns toward the stated objective, verifies +each iteration against the acceptance criteria it derives from the goal +statement, and the model must prove completion through the built-in `goal` tool +before the loop ends. + +- Iteration budget: the host default is `5`, raised with `--max`. The flag + precedes the description, and everything after it is the goal statement. +- **Acceptance criteria travel inside the description.** The host derives them + from the goal statement, so LoopX appends the criteria its todo already owns + (after `Done when:`) instead of passing a separate flag. There is no criteria + flag to pass: an unrecognised flag after the description would be read as more + goal text, polluting the objective and silently dropping `--max`. +- `/goal clear` cancels the active goal. A running goal is steered in place + rather than read back — the host advertises no goal status subcommand. - The `goal` tool's `complete` command enforces a completion contract: each success criterion needs cited tool output, and belief or narrative confidence is explicitly not evidence — the same standard LoopX writeback wants. -Probed on `kiro-cli-chat 2.21.1` (app bundle `20260904.123104`; `kiro-cli` and -`kiro-cli-chat` both report `2.21.1`). The command hint, `--validate`/`--agent`/ -`--max` flags, the iteration-ceiling rejection message, the `Completed` and -`Exhausted` terminal states, the 3-failure pause, and the per-iteration -`passed`/`feedback` result all come from the shipped binary rather than from -host marketing copy. Re-probe with: +The contracted surface is checked against the host itself, not transcribed. The +installed binary advertises its own command registry over ACP, so the shape can +be replayed on any machine that has the CLI: ```bash -strings -a "$(readlink -f "$(command -v kiro-cli-chat)")" \ - | grep -ao "/goal \[[^]]*\]" +python3 examples/kiro-cli-goal-command-contract-probe.py ``` +It asserts that `/goal` exists and that its advertised subcommands are exactly +the ones LoopX projects. An earlier revision of this document claimed +`--validate`, `--agent` and `/goal status` and cited a `strings` probe of the +binary; that probe returns nothing on the shipped app bundle, and neither the +published command reference nor the host's own registry contracts those +arguments, so they are no longer projected. + ## Native hook seam Agent configs (`~/.kiro/agents/.json` or `.kiro/agents/.json`) @@ -61,7 +62,7 @@ both as `skill://` resources, and every discovered skill is invocable as a `/` slash command with `$ARGUMENTS` expansion. LoopX reaches a Kiro CLI session through the generated `/loopx` skill facade, and the activation binds the objective with the native -`/goal --validate --max `. +`/goal --max Done when: `. Three honest limits, stated in the activation packet: @@ -99,11 +100,11 @@ loopx start-goal --guided --project . --slash-command-arguments="" --host- ``` After todo writeback, bind the generated heartbeat task body with -`/goal --validate --max ` — substituting the -validation the todo already names for `` so the host judges each -iteration against the check LoopX will accept, and `N` taken from the remaining -quota slots and never above the host ceiling of 50 — read the loop back with -`/goal status`, start every +`/goal --max Done when: ` — stating the criteria the +todo already names inside the goal statement, because the host derives its +acceptance criteria from that statement rather than from a flag, and `N` taken +from the remaining quota slots (host default is 5) — steer a running goal in +place rather than expecting a status readback, start every turn and native goal iteration with `quota should-run` (advisory guidance; LoopX does not intercept native host iterations), and settle through the built-in `goal` tool only after LoopX writeback so the cited evidence matches From 3c288ff216b12241d40b0bea329fbc3c575c99c1 Mon Sep 17 00:00:00 2001 From: "vlean.wei" Date: Wed, 9 Sep 2026 11:42:20 +0800 Subject: [PATCH 22/23] test(kiro-cli): add a replayable goal command contract probe Documentation transcription is what produced the wrong syntax, so the shape is now checked against the host itself. The installed CLI advertises its command registry over ACP, which makes the contract verifiable on any machine that has the binary. The probe asserts the projection keeps the iteration flag before the description and claims no withdrawn argument, then compares the advertised `/goal` subcommands with what LoopX projects. It skips with exit 0 when the binary is absent, so it is safe where the host is not installed, and it fails on a reintroduced flag. Signed-off-by: vlean.wei --- .../kiro-cli-goal-command-contract-probe.py | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 examples/kiro-cli-goal-command-contract-probe.py diff --git a/examples/kiro-cli-goal-command-contract-probe.py b/examples/kiro-cli-goal-command-contract-probe.py new file mode 100644 index 0000000000..495e7dbee1 --- /dev/null +++ b/examples/kiro-cli-goal-command-contract-probe.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python3 +"""Check the projected Kiro goal command against the host's own registry. + +LoopX must not claim native command arguments the host does not contract. The +installed CLI advertises its command registry over ACP +(`_kiro.dev/commands/available`), which makes the shape verifiable on any +machine that has the binary instead of transcribed from documentation. + +This probe is replayable and public-safe: it starts the host as an ACP stdio +agent, reads the advertised `/goal` entry, and compares it with what +`loopx.kiro_cli_goal_mode` projects. It exits 0 and reports `skipped` when the +binary is absent, so it is safe in environments without the host. + + python3 examples/kiro-cli-goal-command-contract-probe.py +""" + +from __future__ import annotations + +import json +import os +import selectors +import shutil +import subprocess +import sys +import time +from pathlib import Path + +REPO_ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(REPO_ROOT)) + +from loopx.kiro_cli_goal_mode import ( # noqa: E402 + KIRO_CLI_GOAL_CLEAR_COMMAND, + KIRO_CLI_GOAL_COMMAND, + KIRO_CLI_GOAL_MAX_FLAG, + kiro_cli_chat_command, + kiro_cli_goal_invocation, +) + +HANDSHAKE_TIMEOUT_SEC = 15.0 +REGISTRY_NOTIFICATION = "_kiro.dev/commands/available" + + +def _read_frames(stdout, sel, deadline: float) -> list[dict]: + frames: list[dict] = [] + buffer = "" + while time.monotonic() < deadline: + for key, _ in sel.select(timeout=0.4): + chunk = os.read(key.fileobj.fileno(), 65536).decode("utf-8", "replace") + if not chunk: + return frames + buffer += chunk + while "\n" in buffer: + line, buffer = buffer.split("\n", 1) + if not line.strip(): + continue + try: + frames.append(json.loads(line)) + except json.JSONDecodeError: + continue + return frames + + +def advertised_goal_command() -> dict | None: + """Return the host's own `/goal` registry entry, or None when unavailable.""" + command = kiro_cli_chat_command() + if shutil.which(command[0]) is None: + return None + process = subprocess.Popen( + command, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + selector = selectors.DefaultSelector() + selector.register(process.stdout, selectors.EVENT_READ) + try: + for request_id, method, params in ( + ( + 1, + "initialize", + { + "protocolVersion": 1, + "clientCapabilities": { + "fs": {"readTextFile": False, "writeTextFile": False} + }, + }, + ), + (2, "session/new", {"cwd": str(REPO_ROOT), "mcpServers": []}), + ): + payload = { + "jsonrpc": "2.0", + "id": request_id, + "method": method, + "params": params, + } + process.stdin.write((json.dumps(payload) + "\n").encode()) + process.stdin.flush() + frames = _read_frames( + process.stdout, + selector, + time.monotonic() + HANDSHAKE_TIMEOUT_SEC, + ) + for frame in frames: + if frame.get("method") != REGISTRY_NOTIFICATION: + continue + for entry in frame.get("params", {}).get("commands", []): + if entry.get("name") == KIRO_CLI_GOAL_COMMAND: + return entry + return {} + finally: + # Close stdin first so the host releases its session before exiting. + try: + if process.stdin is not None and not process.stdin.closed: + process.stdin.close() + except OSError: + pass + try: + process.wait(timeout=5) + except subprocess.TimeoutExpired: + process.terminate() + try: + process.wait(timeout=3) + except subprocess.TimeoutExpired: + process.kill() + + +def main() -> int: + projected = kiro_cli_goal_invocation() + # The projection itself must stay inside the contracted shape regardless of + # whether the host is installed, so assert that part unconditionally. + assert projected.startswith( + f"{KIRO_CLI_GOAL_COMMAND} {KIRO_CLI_GOAL_MAX_FLAG} " + ), f"the iteration flag must precede the description: {projected}" + for unsupported in ("--validate", "--agent"): + assert unsupported not in projected, ( + f"{unsupported} is not a contracted argument of " + f"{KIRO_CLI_GOAL_COMMAND}: {projected}" + ) + + entry = advertised_goal_command() + if entry is None: + print( + "kiro-cli-goal-command-contract-probe: skipped " + "(host binary not on PATH); projection shape checked" + ) + return 0 + assert entry, ( + f"the host advertised no {KIRO_CLI_GOAL_COMMAND} entry; " + "LoopX must not project a command the host does not expose" + ) + + subcommands = sorted(entry.get("meta", {}).get("subcommands", [])) + expected = sorted({KIRO_CLI_GOAL_CLEAR_COMMAND.split()[-1]}) + assert subcommands == expected, ( + f"advertised {KIRO_CLI_GOAL_COMMAND} subcommands {subcommands} do not " + f"match the projected {expected}; update the projection rather than the " + "expectation" + ) + + print( + "kiro-cli-goal-command-contract-probe: ok " + f"(advertised subcommands={subcommands}, projection={projected!r})" + ) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From 68d3a510117e59b9e94ffa4c15743e6ea4cd6ff1 Mon Sep 17 00:00:00 2001 From: "vlean.wei" Date: Wed, 9 Sep 2026 11:42:20 +0800 Subject: [PATCH 23/23] test(kiro-cli): pin consumers to the contracted goal arguments The consumer scanner previously required `--validate` in every copyable command, so it actively enforced the wrong contract. It now rejects any withdrawn argument and requires the iteration flag to precede the description, across the activation packet, activation extras, onboarding instruction, the fact tuple and all three documentation surfaces. The host-facts test drops the ceiling and withdrawn arguments and instead requires the facts to state where acceptance criteria live. Verified in both directions: reintroducing the flag in the composer fails four tests and the contract probe, and reverting a README row fails the consumer test with the offending command named. Signed-off-by: vlean.wei --- tests/test_kiro_cli_host_surface.py | 132 ++++++++++++++++++---------- 1 file changed, 87 insertions(+), 45 deletions(-) diff --git a/tests/test_kiro_cli_host_surface.py b/tests/test_kiro_cli_host_surface.py index f086b8f8af..14a861d846 100644 --- a/tests/test_kiro_cli_host_surface.py +++ b/tests/test_kiro_cli_host_surface.py @@ -44,14 +44,12 @@ ) from loopx.kiro_cli_goal_mode import ( KIRO_CLI_CHAT_AGENT_ID, - KIRO_CLI_GOAL_AGENT_FLAG, KIRO_CLI_GOAL_CLEAR_COMMAND, KIRO_CLI_GOAL_COMMAND, KIRO_CLI_GOAL_COMPLETION_TOOL, KIRO_CLI_GOAL_DEFAULT_MAX_ITERATIONS, - KIRO_CLI_GOAL_MAX_ITERATION_CEILING, - KIRO_CLI_GOAL_STATUS_COMMAND, - KIRO_CLI_GOAL_VALIDATE_FLAG, + KIRO_CLI_GOAL_CRITERIA_LEAD, + KIRO_CLI_GOAL_MAX_FLAG, KIRO_CLI_HOME_ENV, KIRO_CLI_AGENT_TYPE_CATALOG_ENTRY, KIRO_CLI_HOOK_TRIGGERS, @@ -112,6 +110,12 @@ def test_agent_onboarding_setup_command_installs_the_kiro_cli_surface( ) +# Arguments an earlier revision projected that neither the published command +# reference nor the host's own advertised registry contracts. Kept as data so a +# reintroduction fails on every consumer at once. +UNSUPPORTED_GOAL_ARGUMENTS = ("--validate", "--agent", "/goal status") + + def _copyable_goal_commands(value: object) -> list[str]: """Every backticked native goal command carrying a task placeholder. @@ -143,7 +147,13 @@ def assert_no_incomplete_goal_command( *, require_command: bool = False, ) -> None: - """Assert every copyable goal command is complete on its own. + """Assert every copyable goal command matches the contracted shape. + + Two failure modes are guarded. A command must not claim an argument the host + does not contract — an unrecognised flag after the description is read as + more goal text, so the objective is polluted and the iteration budget is + silently dropped. And it must keep the iteration flag before the + description, which is the documented order. Presence is a separate question: some surfaces legitimately expose only the `/loopx` skill entry. Only the surfaces whose job is to hand over the @@ -152,15 +162,29 @@ def assert_no_incomplete_goal_command( commands = _copyable_goal_commands(value) if require_command: assert commands, f"{label} exposes no copyable native goal command" - incomplete = [ - command - for command in commands - if KIRO_CLI_GOAL_VALIDATE_FLAG not in command - ] - assert not incomplete, ( - f"{label} exposes a copyable goal command without " - f"{KIRO_CLI_GOAL_VALIDATE_FLAG}: {incomplete}" - ) + for command in commands: + for unsupported in UNSUPPORTED_GOAL_ARGUMENTS: + assert unsupported not in command, ( + f"{label} projects {unsupported}, which the host does not " + f"contract for {KIRO_CLI_GOAL_COMMAND}: {command}" + ) + if KIRO_CLI_GOAL_MAX_FLAG in command: + description_starts = min( + ( + command.index(token) + for token in ("") + if token in command + ), + default=None, + ) + assert description_starts is not None, ( + f"{label} exposes a goal command with no description " + f"placeholder: {command}" + ) + assert command.index(KIRO_CLI_GOAL_MAX_FLAG) < description_starts, ( + f"{label} places {KIRO_CLI_GOAL_MAX_FLAG} after the " + f"description; the host documents it first: {command}" + ) def test_every_actionable_consumer_renders_the_complete_goal_command() -> None: @@ -239,22 +263,31 @@ def test_public_outputs_agree_with_the_canonical_host_facts( assert "offers no home override" not in note assert KIRO_CLI_HOME_ENV in note - # The activation command must be complete: without the validation flag the - # host judges completion by its own reading instead of the Todo's criteria. - assert KIRO_CLI_GOAL_VALIDATE_FLAG in instruction + # The activation command must carry the acceptance criteria inside the goal + # statement, because that is where the host derives them from, and must not + # claim an argument the host does not contract. assert kiro_cli_goal_invocation() in instruction - assert KIRO_CLI_GOAL_STATUS_COMMAND in instruction + assert KIRO_CLI_GOAL_CRITERIA_LEAD in instruction + for unsupported in UNSUPPORTED_GOAL_ARGUMENTS: + assert unsupported not in instruction def test_canonical_goal_invocation_uses_the_host_argument_order() -> None: - """An independent oracle for the command, built from the host's documented - syntax rather than from the composer's own output.""" + """An independent oracle, written from the host's documented syntax rather + than from the composer's own output. + + The reference documents `/goal --max `: the flag first, then + the goal statement. Acceptance criteria are part of that statement because + the host derives them from it.""" command = kiro_cli_goal_invocation( task="", criteria="", max_iterations="7" ) - assert command == "/goal --validate --max 7" - # The flag order follows the host's own `--validate` before `--max`. - assert command.index(KIRO_CLI_GOAL_VALIDATE_FLAG) < command.index("--max") + assert command == "/goal --max 7 Done when: " + # Omitting criteria still yields a valid command, just without them stated. + assert ( + kiro_cli_goal_invocation(task="", criteria=None, max_iterations="7") + == "/goal --max 7 " + ) def test_kiro_home_resolves_the_host_override_then_the_default( @@ -467,12 +500,15 @@ def test_activation_binds_native_goal_with_advisory_quota_entry() -> None: assert mutation["quota_gate_enforcement"] == "advisory_only" assert mutation["native_goal_command"] == KIRO_CLI_GOAL_COMMAND assert mutation["native_goal_cancel_command"] == KIRO_CLI_GOAL_CLEAR_COMMAND - assert mutation["native_goal_status_command"] == KIRO_CLI_GOAL_STATUS_COMMAND - assert mutation["native_goal_validate_flag"] == KIRO_CLI_GOAL_VALIDATE_FLAG - assert ( - mutation["native_goal_max_iteration_ceiling"] - == KIRO_CLI_GOAL_MAX_ITERATION_CEILING - ) + assert mutation["native_goal_criteria_placement"] == "inside_goal_statement" + for unsupported_key in ( + "native_goal_status_command", + "native_goal_validate_flag", + "native_goal_max_iteration_ceiling", + ): + assert unsupported_key not in mutation, ( + f"{unsupported_key} projects an argument the host does not contract" + ) assert ( mutation["native_goal_default_max_iterations"] == KIRO_CLI_GOAL_DEFAULT_MAX_ITERATIONS @@ -498,13 +534,16 @@ def test_activation_binds_native_goal_with_advisory_quota_entry() -> None: # separate prose step, so an agent copying the command bound a goal the host # judged by its own default instead of the Todo's criteria. assert kiro_cli_goal_invocation() in steps - assert str(KIRO_CLI_GOAL_MAX_ITERATION_CEILING) in steps + assert str(KIRO_CLI_GOAL_DEFAULT_MAX_ITERATIONS) in steps assert "quota should-run" in steps assert KIRO_CLI_GOAL_COMPLETION_TOOL in steps assert "no host scheduler to fall back on" not in steps - assert KIRO_CLI_GOAL_STATUS_COMMAND in steps - # Every copyable command in the packet must be complete on its own. Prose - # elsewhere cannot repair a command a reader has already executed. + # The steps must say criteria live in the goal statement, and must not tell + # the agent to read a status subcommand the host does not expose. + assert KIRO_CLI_GOAL_CRITERIA_LEAD in steps + assert "steer" in steps.lower() + # Every copyable command in the packet must match the contracted shape. + # Prose elsewhere cannot repair a command a reader has already executed. assert_no_incomplete_goal_command("activation packet", packet) assert packet["setup_command"] == _surface_install_command( @@ -646,15 +685,18 @@ def test_kiro_cli_is_recognized_across_the_control_plane( def test_native_goal_facts_match_the_probed_host() -> None: """The host-facts constants are the single source the activation packet, - README and PR narrative cite; they must stay pinned to what the host - actually documents and what the probed binary exposes.""" + README and PR narrative cite, so they must stay pinned to what the host + itself contracts. + + An earlier revision pinned `--validate`, `--agent`, a `status` subcommand + and an iteration ceiling of 50. None of those appear in the published + command reference or in the registry the installed host advertises over ACP, + and `examples/kiro-cli-goal-command-contract-probe.py` replays that check + against a real binary.""" assert KIRO_CLI_GOAL_COMMAND == "/goal" assert KIRO_CLI_GOAL_CLEAR_COMMAND == "/goal clear" - assert KIRO_CLI_GOAL_STATUS_COMMAND == "/goal status" - assert KIRO_CLI_GOAL_VALIDATE_FLAG == "--validate" - assert KIRO_CLI_GOAL_AGENT_FLAG == "--agent" + assert KIRO_CLI_GOAL_MAX_FLAG == "--max" assert KIRO_CLI_GOAL_DEFAULT_MAX_ITERATIONS == 5 - assert KIRO_CLI_GOAL_MAX_ITERATION_CEILING == 50 assert KIRO_CLI_GOAL_COMPLETION_TOOL == "goal" assert KIRO_CLI_SESSION_ID_ENV == "KIRO_SESSION_ID" assert set(KIRO_CLI_HOOK_TRIGGERS) == { @@ -666,11 +708,11 @@ def test_native_goal_facts_match_the_probed_host() -> None: } facts = " ".join(KIRO_CLI_NATIVE_GOAL_FACTS) assert "--max" in facts - assert "ceiling 50" in facts assert "completion contract" in facts assert "exit code 2" in facts - # The host's own hint names --validate and --agent; an adapter that only - # documents --max understates the primitive it binds. - assert KIRO_CLI_GOAL_VALIDATE_FLAG in facts - assert KIRO_CLI_GOAL_AGENT_FLAG in facts - assert KIRO_CLI_GOAL_STATUS_COMMAND in facts + # The facts must state where acceptance criteria live, because that is the + # host's mechanism and the reason no criteria flag is projected. + assert "goal statement" in facts + # They must not reintroduce an argument the host does not contract. + for unsupported in UNSUPPORTED_GOAL_ARGUMENTS: + assert unsupported not in facts