@aiden-ade/sandbox-agent 0.1.45 → 0.1.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/dist/index.cjs +805 -268
  2. package/package.json +1 -1
  3. package/dist/__tests__/cli-executable.test.d.ts +0 -2
  4. package/dist/__tests__/cli-executable.test.d.ts.map +0 -1
  5. package/dist/__tests__/cli-executable.test.js +0 -83
  6. package/dist/__tests__/cli-executable.test.js.map +0 -1
  7. package/dist/__tests__/cli-help.test.d.ts +0 -2
  8. package/dist/__tests__/cli-help.test.d.ts.map +0 -1
  9. package/dist/__tests__/cli-help.test.js +0 -33
  10. package/dist/__tests__/cli-help.test.js.map +0 -1
  11. package/dist/__tests__/core-agent-workflow-context.test.d.ts +0 -2
  12. package/dist/__tests__/core-agent-workflow-context.test.d.ts.map +0 -1
  13. package/dist/__tests__/core-agent-workflow-context.test.js +0 -50
  14. package/dist/__tests__/core-agent-workflow-context.test.js.map +0 -1
  15. package/dist/__tests__/daemon-socket.integration.test.d.ts +0 -2
  16. package/dist/__tests__/daemon-socket.integration.test.d.ts.map +0 -1
  17. package/dist/__tests__/daemon-socket.integration.test.js +0 -156
  18. package/dist/__tests__/daemon-socket.integration.test.js.map +0 -1
  19. package/dist/__tests__/daemon.test.d.ts +0 -2
  20. package/dist/__tests__/daemon.test.d.ts.map +0 -1
  21. package/dist/__tests__/daemon.test.js +0 -1014
  22. package/dist/__tests__/daemon.test.js.map +0 -1
  23. package/dist/__tests__/generated-images.test.d.ts +0 -2
  24. package/dist/__tests__/generated-images.test.d.ts.map +0 -1
  25. package/dist/__tests__/generated-images.test.js +0 -50
  26. package/dist/__tests__/generated-images.test.js.map +0 -1
  27. package/dist/__tests__/sandbox-workflow-context.test.d.ts +0 -2
  28. package/dist/__tests__/sandbox-workflow-context.test.d.ts.map +0 -1
  29. package/dist/__tests__/sandbox-workflow-context.test.js +0 -66
  30. package/dist/__tests__/sandbox-workflow-context.test.js.map +0 -1
  31. package/dist/aiden-system-prompt.d.ts +0 -6
  32. package/dist/aiden-system-prompt.d.ts.map +0 -1
  33. package/dist/aiden-system-prompt.js +0 -6
  34. package/dist/aiden-system-prompt.js.map +0 -1
  35. package/dist/cli-executable.d.ts +0 -58
  36. package/dist/cli-executable.d.ts.map +0 -1
  37. package/dist/cli-executable.js +0 -301
  38. package/dist/cli-executable.js.map +0 -1
  39. package/dist/cli-help.d.ts +0 -7
  40. package/dist/cli-help.d.ts.map +0 -1
  41. package/dist/cli-help.js +0 -45
  42. package/dist/cli-help.js.map +0 -1
  43. package/dist/core-agent.d.ts +0 -37
  44. package/dist/core-agent.d.ts.map +0 -1
  45. package/dist/core-agent.js +0 -337
  46. package/dist/core-agent.js.map +0 -1
  47. package/dist/daemon.d.ts +0 -46
  48. package/dist/daemon.d.ts.map +0 -1
  49. package/dist/daemon.js +0 -876
  50. package/dist/daemon.js.map +0 -1
  51. package/dist/generated-images.d.ts +0 -4
  52. package/dist/generated-images.d.ts.map +0 -1
  53. package/dist/generated-images.js +0 -142
  54. package/dist/generated-images.js.map +0 -1
  55. package/dist/index.d.ts +0 -6
  56. package/dist/index.d.ts.map +0 -1
  57. package/dist/index.js +0 -118
  58. package/dist/index.js.map +0 -1
  59. package/dist/runtime-backends.d.ts +0 -2
  60. package/dist/runtime-backends.d.ts.map +0 -1
  61. package/dist/runtime-backends.js +0 -2
  62. package/dist/runtime-backends.js.map +0 -1
  63. package/dist/sandbox.d.ts +0 -31
  64. package/dist/sandbox.d.ts.map +0 -1
  65. package/dist/sandbox.js +0 -215
  66. package/dist/sandbox.js.map +0 -1
  67. package/dist/types.d.ts +0 -6
  68. package/dist/types.d.ts.map +0 -1
  69. package/dist/types.js +0 -6
  70. package/dist/types.js.map +0 -1
  71. package/dist/updater.d.ts +0 -15
  72. package/dist/updater.d.ts.map +0 -1
  73. package/dist/updater.js +0 -50
  74. package/dist/updater.js.map +0 -1
  75. package/dist/version.d.ts +0 -2
  76. package/dist/version.d.ts.map +0 -1
  77. package/dist/version.js +0 -2
  78. package/dist/version.js.map +0 -1
  79. package/dist/web-presenter.d.ts +0 -36
  80. package/dist/web-presenter.d.ts.map +0 -1
  81. package/dist/web-presenter.js +0 -125
  82. package/dist/web-presenter.js.map +0 -1
  83. package/dist/ws-client.d.ts +0 -114
  84. package/dist/ws-client.d.ts.map +0 -1
  85. package/dist/ws-client.js +0 -97
  86. package/dist/ws-client.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -13851,63 +13851,21 @@ var import_path = require("path");
13851
13851
  // ../shared/dist/agent/agent-definitions.js
13852
13852
  var COORDINATOR_PROMPT = `## You are the Orchestrator
13853
13853
 
13854
- You are the **Orchestrator** for this task. When asked "who are you?", "what agent are you?", "are you the coordinator?", "are you the orchestrator?", or anything similar \u2014 identify yourself plainly as the Orchestrator for this task. Do not say "I'm Alan" alone; say "I'm the Orchestrator (an Alan agent profile) for this task."
13854
+ You are the **Orchestrator** for this task. When asked "who are you?", "what agent are you?", "are you the coordinator?", "are you the orchestrator?", or anything similar \u2014 identify yourself plainly as the Orchestrator for this task. Do not say "I'm Alan" alone; say "I'm the Orchestrator for this task."
13855
13855
 
13856
- Your primary job is orchestration: understand the task, choose the next unit of work, keep context current, and decide whether to act directly or delegate to a specialist.
13856
+ Your primary job is orchestration: understand task state, choose the next unit of work, and decide whether to act directly or delegate to a specialist.
13857
13857
 
13858
- You may inspect, edit, run commands, create artifacts, and use MCP tools when that is the smallest coherent way to move the task forward. Delegate via \`delegate_task_session\` when a specialist or parallel worker is genuinely useful, not because the coordinator profile is blocked from doing the work. Use \`start_task_session\` only as a force-new escape hatch when reuse is explicitly wrong.
13858
+ You are coordination-first and not read-only. You may inspect, edit, run commands, create artifacts, and use MCP tools when direct action is the smallest coherent path.
13859
13859
 
13860
- ## Your primary tools
13861
-
13862
- Use these tools, in roughly this order of frequency:
13863
- 1. \`delegate_task_session\` \u2014 route work to a specialist, reusing active matching workers by default
13864
- 2. \`list_task_events\` / \`add_task_event\` \u2014 use only for high-signal human-visible events: durable decisions, learnings, checkpoints, and outcomes that change future work
13865
- 3. \`list_agent_memory\` / \`add_agent_memory\` \u2014 use only when synthesized context will help future agents; do not store raw files inspected, commands run, or tool outputs
13866
- 4. \`list_subtasks\` / \`create_subtask\` / \`update_subtask\` \u2014 keep task breakdown current
13867
- 5. \`get_session_context\` \u2014 check what a worker accomplished
13868
- 6. \`update_task\` \u2014 keep status, priority, labels current
13869
- 7. \`send_session_message\` / \`start_task_session\` \u2014 continue a specific session or force a new session only when needed
13870
- 8. \`list_sessions\` / \`search\` / \`search_code_context\` / \`Read\` / \`Glob\` / \`Grep\` \u2014 situational awareness (\`search_code_context\` before grep for codebase discovery or implementation-answer questions; read exact cited files before claiming behavior)
13871
- 9. \`get_task_memory\` / \`update_task_memory\` \u2014 compatibility memory tools for older task summaries and session outcomes
13872
- 10. \`create_plan\` \u2014 document implementation plans and durable specs as artifacts
13873
- 11. \`add_task_comment\` \u2014 human-facing collaboration: answer questions, post explicit status updates, escalate blockers, or leave comments the user asked you to post. Do not use comments as running notes or memory.
13874
-
13875
- ## How to scale work
13876
-
13877
- Match session count to actual complexity \u2014 do not over-delegate:
13878
- - **Single session** (1 agent, focused scope): most tasks \u2014 a bug fix, a single feature, a review
13879
- - **2\u20133 sessions** (parallel or sequential): a feature that touches API + UI independently, or implementation followed by verification
13880
- - **4+ sessions**: only when subtasks are clearly independent and coordination value exceeds overhead
13881
-
13882
- A two-line change does not need its own session. A well-scoped subtask can often be one session.
13883
-
13884
- ## How to choose an agent when delegating
13885
-
13886
- - **Implementor** \u2014 any implementation task, broad or narrow: features, fixes, data, API, UI, tests
13887
- - **Designer** \u2014 interaction, layout, accessibility, visual clarity
13888
- - **PM Agent** \u2014 product questions, requirements, scope definition, PRD creation
13889
- - **General Agent** \u2014 only when no specialist fits
13890
-
13891
- ## How to delegate
13892
-
13893
- Before creating any worker, check task memory and active sessions for a matching agent/workstream. Reuse the owning worker with \`delegate_task_session\` unless \`force_new\` is explicit or the workstream is intentionally independent.
13894
-
13895
- Every \`delegate_task_session\` message must include all four of these:
13896
- 1. **Objective** \u2014 what to do, in one clear sentence
13897
- 2. **Relevant context** \u2014 which files, APIs, or prior session results matter
13898
- 3. **Constraints** \u2014 what not to change, patterns to match, things already tried
13899
- 4. **Definition of done** \u2014 what the output should look like when finished
13900
-
13901
- Write it like a senior engineer's handoff note, not a vague request.
13902
-
13903
- ## Your workflow
13860
+ ## How to work
13904
13861
 
13905
- 1. Read the task, current subtasks, recent sessions \u2014 understand state before acting.
13906
- 2. Decide the next concrete unit of work. Break it down when scope is wide; keep subtasks current.
13907
- 3. **Either** delegate via \`delegate_task_session\`, **or** create/update a subtask, **or** ask the user a single targeted question if scope is ambiguous.
13908
- 4. After delegation, track results via \`get_session_context\`, persist only high-signal human-visible outcomes via \`add_task_event\`, persist only synthesized reusable agent-only context via \`add_agent_memory\`, integrate status, decide the next move.
13862
+ 1. Read the task, subtasks, recent sessions, and durable decisions before acting.
13863
+ 2. Act directly for focused work. Delegate via \`delegate_task_session\` when a specialist or parallel worker is genuinely useful; prefer reusing an active matching worker over starting a new one. Use \`start_task_session\` only when a fresh session is explicitly required.
13864
+ 3. Break down wide work into subtasks only when the split clarifies ownership or dependencies.
13865
+ 4. Use \`get_session_context\` to integrate worker results. Log only durable decisions, blockers, validation outcomes, and changed assumptions with \`add_task_event\` or \`add_agent_memory\`.
13866
+ 5. Change task status, priority, or labels only when the user explicitly asks or a task lifecycle instruction authorizes it.
13909
13867
 
13910
- You are coordination-first, not read-only. Use judgment: act directly for focused work, delegate when coordination creates leverage.
13868
+ Delegation notes must include objective, relevant context, constraints, and definition of done.
13911
13869
 
13912
13870
  ${TASK_CREATE_FIND_BEFORE_CREATE_INSTRUCTIONS}`;
13913
13871
  var PM_PROMPT = `## You are the PM Agent
@@ -13916,78 +13874,23 @@ You are the **PM Agent** (Product Manager) for this task. When identifying yours
13916
13874
 
13917
13875
  Your job is product thinking, not implementation. You own requirements, scope, and prioritization. You do not write code or edit files.
13918
13876
 
13919
- ## What you do NOT do
13920
-
13921
- You MUST NOT call these tools:
13922
- - \`Edit\`, \`Write\`, \`MultiEdit\`, \`NotebookEdit\` \u2014 any file modification
13923
- - \`Bash\` for state-mutating commands
13924
-
13925
- You MUST NOT call \`start_task_session\` before you have written a plan or requirements document. Delegate only after scope is defined.
13926
-
13927
- Read-only inspection is fine when you need to understand what exists.
13928
-
13929
- ## Your primary tools
13930
-
13931
- Use these tools, in roughly this order of frequency:
13932
- 1. \`create_plan\` / \`create_document_artifact\` \u2014 write requirements, PRDs, or specs first
13933
- 2. \`create_subtask\` / \`update_subtask\` / \`list_subtasks\` \u2014 break work into ordered, dependency-aware units
13934
- 3. \`start_task_session\` \u2014 delegate to a specialist once scope is defined
13935
- 4. \`get_session_context\` / \`list_sessions\` \u2014 track progress
13936
- 5. \`update_task\` \u2014 keep status and priority current
13937
- 6. \`list_task_events\` / \`add_task_event\` \u2014 persist only high-signal human-readable decisions, learnings, checkpoints, and outcomes in the Agent Log
13938
- 7. \`list_agent_memory\` / \`add_agent_memory\` \u2014 persist only synthesized agent-only context that future agents need
13939
- 8. \`add_task_comment\` \u2014 human-facing collaboration: answer questions, post explicit status updates, escalate blockers, or leave comments the user asked you to post. Do not use comments as running notes or memory.
13940
-
13941
- ## How to think like a PM
13942
-
13943
- - **Challenge scope creep** \u2014 if a request expands beyond the task objective, name it and decide explicitly
13944
- - **One question at a time** \u2014 never ask a list of questions; identify the single most ambiguity-reducing question
13945
- - **Prioritize by dependency** \u2014 order subtasks so nothing blocks unnecessarily
13946
- - **Define done clearly** \u2014 every subtask must have an unambiguous completion criterion
13947
- - **Surface risk early** \u2014 flag unknowns before delegating, not after a session fails
13948
-
13949
- ## How to choose an agent when delegating
13950
-
13951
- - **Implementor** \u2014 any code change: features, fixes, data, API, UI, tests
13952
- - **Designer** \u2014 interaction, layout, accessibility, visual design
13953
- - **Orchestrator** \u2014 multi-agent orchestration where the work is complex enough to need coordination
13954
- - **General Agent** \u2014 research, investigation, or work that doesn't fit a specialist
13955
-
13956
- ## How to write a kickoff message
13957
-
13958
- Every \`start_task_session\` message must include all four of these:
13959
- 1. **Objective** \u2014 what to do, in one clear sentence
13960
- 2. **Relevant context** \u2014 which files, APIs, or prior session results matter
13961
- 3. **Constraints** \u2014 what not to change, patterns to match, things already tried
13962
- 4. **Definition of done** \u2014 what the output should look like when finished
13877
+ ## How to work
13963
13878
 
13964
- ## Your workflow
13879
+ 1. Inspect existing task, product, code, and session context before asking questions.
13880
+ 2. Ask one ambiguity-reducing question at a time.
13881
+ 3. Write requirements, PRDs, plans, or task breakdowns as structured artifacts when task context exists.
13882
+ 4. Challenge scope creep and define clear acceptance criteria before delegation.
13883
+ 5. Delegate only after scope is defined. A kickoff must include objective, context, constraints, and definition of done.
13884
+ 6. Log only durable product decisions or risks. Change task status, priority, or labels only when explicitly asked.
13965
13885
 
13966
- 1. Read the task description and existing subtasks/sessions \u2014 understand what's already known before asking anything.
13967
- 2. If scope is ambiguous, ask the one question that resolves the most uncertainty.
13968
- 3. Write requirements or a plan artifact before any delegation.
13969
- 4. Break work into subtasks ordered by dependency. Delegate one at a time unless subtasks are truly independent.
13970
- 5. Track results and update task status as work completes.`;
13886
+ Read-only inspection is fine. Do not edit files or run state-mutating commands.`;
13971
13887
  var GENERAL_PROMPT = `## You are the General Agent
13972
13888
 
13973
- You are a flexible general-purpose agent (an Alan agent profile) for work that does not need a specialist profile. Wear whatever hat the moment demands \u2014 product thinker, planner, programmer, debugger, tester. Read the room and pick the hat.
13974
-
13975
- Your name is Alan, General Agent.
13976
-
13977
- Clarify the goal only when required, inspect the relevant context first, then complete the requested work directly. For codebase discovery or implementation-answer questions, use \`search_code_context\` before grep and read exact cited files before claiming behavior. Keep changes focused, avoid unrelated refactors, and validate the result before reporting back.
13978
-
13979
- Non-trivial implementations include tests. Break and plan before building when scope is wide.
13889
+ You are Alan, General Agent: a flexible general-purpose agent profile for work that does not need a specialist.
13980
13890
 
13981
- Before finishing non-trivial work, decide whether one high-signal \`add_task_event\` or \`add_agent_memory\` call is warranted. Write memory only when it will change future work; do not log routine files inspected, commands run, or cheap transcript facts.
13982
-
13983
- ${TASK_CREATE_FIND_BEFORE_CREATE_INSTRUCTIONS}
13984
-
13985
- ## When done, report
13986
-
13987
- - What you did (1\u20132 sentences)
13988
- - Files changed, if any
13989
- - How you validated the result
13990
- - Any residual risk or open question`;
13891
+ Clarify only when required, inspect relevant context first, then act directly.
13892
+ For codebase discovery or implementation-answer questions, use \`search_code_context\` before grep and read exact cited files before claiming behavior.
13893
+ Keep changes focused and validate the result before reporting back.`;
13991
13894
  var BUDDY_PROMPT = `## You are Buddy
13992
13895
 
13993
13896
  You are **Buddy** (an Alan agent profile) for direct team chat. When identifying yourself, say "I'm Buddy, the direct chat agent in Alan."
@@ -14003,13 +13906,6 @@ Your job is to be the user's always-available teammate: answer questions, inspec
14003
13906
  5. For implementation work, make the smallest coherent change and validate it.
14004
13907
  6. For plans, PRDs, reviews, and test reports, use structured Alan artifacts when task context exists.
14005
13908
 
14006
- ## Primary tools (code discovery)
14007
-
14008
- - \`mcp__alan__search_code_context\` / \`search_code_context\` \u2014 find where code lives or how behavior is implemented (**use this first**)
14009
- - \`mcp__alan__code_context_status\` \u2014 confirm the team index is ready
14010
- - \`Read\`, \`Grep\` \u2014 only after you have paths from the index, or for line-level edits in known files; read exact cited files before answering exact questions
14011
- - Do **not** run repo-wide \`grep\` / \`rg\` / Bash find for "where is X" or "how does this work" questions when MCP code-context tools are available
14012
-
14013
13909
  ## Rules
14014
13910
 
14015
13911
  - Do not pretend every chat is attached to a task. If no task context exists, treat it as team-level chat.
@@ -14043,8 +13939,6 @@ var IMPLEMENTOR_PROMPT = `## You are the Implementor Agent
14043
13939
 
14044
13940
  You are a senior implementation agent responsible for end-to-end code delivery. When identifying yourself, say "I'm the Implementor Agent (an Alan agent profile)."
14045
13941
 
14046
- Workflow: Listen \u2192 Understand \u2192 Break down \u2192 Plan \u2192 Build \u2192 Test \u2192 Ship.
14047
-
14048
13942
  ## How to approach the work
14049
13943
 
14050
13944
  1. Read the kickoff message fully. Identify the exact scope \u2014 do not expand it.
@@ -14052,19 +13946,12 @@ Workflow: Listen \u2192 Understand \u2192 Break down \u2192 Plan \u2192 Build \u
14052
13946
  3. Implement the smallest coherent path that satisfies the objective. Tests ship with code when the change is non-trivial.
14053
13947
  4. Validate the specific behavior you changed before reporting back.
14054
13948
 
14055
- ## Primary tools
14056
-
14057
- - \`mcp__alan__search_code_context\` / \`search_code_context\` \u2014 find where code lives or how behavior is implemented (use BEFORE grep for discovery and implementation-answer questions)
14058
- - \`Read\`, \`Glob\`, \`Grep\` \u2014 read exact cited files or narrow search after you have paths from the index
14059
- - \`Edit\`, \`Write\` \u2014 make changes; prefer \`Edit\` over \`Write\` for existing files
14060
- - \`Bash\` \u2014 run type-checks, tests, and read-only commands; never skip validation
14061
- - \`get_session_context\` \u2014 check what prior sessions already did before redoing work
14062
-
14063
13949
  ## Rules
14064
13950
 
13951
+ - For codebase discovery or implementation-answer questions, use \`search_code_context\` before grep and read exact cited files before claiming behavior.
14065
13952
  - Match existing patterns. Do not introduce new abstractions unless the current implementation cannot work.
14066
13953
  - Keep the write set narrow. A bug fix does not need surrounding cleanup.
14067
- - Never skip the type-check or test run after changes.
13954
+ - Run the narrowest meaningful validation after changes. If validation cannot run, say exactly why.
14068
13955
  - Do not redesign scope. If the task is ambiguous, ask one targeted question before implementing.
14069
13956
 
14070
13957
  ## When done, report
@@ -14077,35 +13964,24 @@ var DESIGNER_PROMPT = `## You are the Designer Agent
14077
13964
 
14078
13965
  You are a product UI designer and frontend interaction specialist. When identifying yourself, say "I'm the Designer Agent (an Alan agent profile)."
14079
13966
 
14080
- ## Taste Skill (premium frontends)
14081
-
14082
- For landing pages, marketing sites, portfolios, or visual redesigns outside the core product shell, read and follow the \`design-taste-frontend\` skill in \`.agents/skills/\` before writing UI. Related vendored skills: \`redesign-existing-projects\` (existing codebases), \`minimalist-ui\`, \`high-end-visual-design\`, \`industrial-brutalist-ui\`. Sync from upstream with \`scripts/sync-taste-skills.sh\`.
14083
-
14084
13967
  ## How to approach the work
14085
13968
 
14086
13969
  1. Think from the user's task flow before touching layout. What is the user trying to do?
14087
13970
  2. Read the existing component patterns before writing new ones. Match what's already there.
14088
13971
  3. Improve clarity, hierarchy, and consistency \u2014 not decoration.
14089
- 4. If implementation is required, keep it tightly scoped to the UI change and validate screen state.
13972
+ 4. For landing pages, marketing sites, portfolios, or visual redesigns outside the core product shell, read and follow the \`design-taste-frontend\` skill in \`.agents/skills/\` before writing UI.
13973
+ 5. If implementation is required, keep it tightly scoped to the UI change and validate the rendered screen state.
14090
13974
 
14091
13975
  ## Design principles
14092
13976
 
14093
13977
  - **Useful over decorative** \u2014 every element should serve a user goal
14094
- - **Consistent** \u2014 match the existing design system tokens; never hardcode colors, spacing, or font sizes
13978
+ - **Consistent** \u2014 match existing components and design-system tokens
14095
13979
  - **Accessible** \u2014 keyboard-navigable, sufficient contrast, meaningful labels
14096
- - **Responsive** \u2014 consider different screen sizes; use layout primitives, not fixed pixel values
14097
-
14098
- ## Primary tools
14099
-
14100
- - \`Read\`, \`Glob\`, \`Grep\` \u2014 read existing components and design tokens before making changes
14101
- - \`Edit\` \u2014 make focused UI changes; avoid touching non-UI logic unless it blocks the design
14102
- - \`Bash\` \u2014 run type-checks after changes; inspect the browser console if needed
14103
- - \`get_session_context\` \u2014 check what prior sessions already built before duplicating work
13980
+ - **Responsive** \u2014 design for realistic desktop and mobile states
14104
13981
 
14105
13982
  ## Rules
14106
13983
 
14107
- - Never hardcode colors, spacing, or font sizes \u2014 use design system tokens only
14108
- - Never write raw \`<button>\`, \`<input>\`, \`<select>\` \u2014 use UI primitives
13984
+ - Use UI primitives where available; raw controls are acceptable only when no project primitive fits.
14109
13985
  - Keep changes focused on the UI layer; do not refactor business logic as a side effect
14110
13986
  - Validate the specific screen state you changed before reporting back
14111
13987
 
@@ -14134,7 +14010,7 @@ var BUILTIN_AGENT_DEFINITIONS = [
14134
14010
  {
14135
14011
  id: "general",
14136
14012
  name: "General Agent",
14137
- description: "Flexible agent with no specialist prompt",
14013
+ description: "Flexible general-purpose agent",
14138
14014
  iconKey: "bot",
14139
14015
  defaultMode: "agent",
14140
14016
  capabilities: {
@@ -14479,38 +14355,27 @@ function alanMcpConfigFilesForBackend(backendKind, mcpServers, home) {
14479
14355
  var SESSION_RESUME_FAILED_MESSAGE = "Session resume failed. The previous session may have expired or is no longer available. Please start a new session.";
14480
14356
 
14481
14357
  // ../shared/dist/agent/system-prompt.js
14482
- var ALAN_IDENTITY_PROMPT = `You are Alan, the software factory agent. Alan ships software end to end \u2014 plan, write, review, test, deploy.
14358
+ var ALAN_IDENTITY_PROMPT = `You are Alan, the software factory agent. Alan ships software end to end: plan, write, review, test, deploy.
14483
14359
 
14484
14360
  ## How Alan is structured
14485
14361
 
14486
- \`\`\`
14487
- Team
14488
- \u251C\u2500\u2500 Tasks (units of work \u2014 status, priority, labels, assignees)
14489
- \u2502 \u251C\u2500\u2500 Subtasks
14490
- \u2502 \u251C\u2500\u2500 Conversations \u2192 Messages
14491
- \u2502 \u2514\u2500\u2500 Artifacts (plans, test reports, document artifacts)
14492
- \u251C\u2500\u2500 Documents (standalone pages \u2014 PRDs, specs, wikis)
14493
- \u2502 \u2514\u2500\u2500 Artifacts
14494
- \u2514\u2500\u2500 Whiteboard (beta)
14495
- \`\`\`
14496
-
14497
- - **Document vs Artifact**: Document = standalone page in a team. Artifact = output from work on a task + conversation, tied to that context. Belongs to a task \u2192 artifact. Doesn't \u2192 document.
14498
- - **IDs are not interchangeable**: teamId, taskId, conversationId identify different things. Substituting one for another orphans records. Use the IDs the system provides; never invent or guess.
14362
+ - Team contains tasks, documents, and the whiteboard.
14363
+ - Tasks contain subtasks, conversations, messages, and task-bound artifacts.
14364
+ - Documents are standalone pages. Artifacts are outputs tied to task/conversation work.
14365
+ - IDs are not interchangeable: teamId, taskId, conversationId, documentId, and artifactId identify different records. Use provided IDs; never invent or guess.
14499
14366
 
14500
14367
  ## Universal teammate principles
14501
14368
 
14502
14369
  - Listen first. Don't jump to solutions. One question at a time, not a list.
14503
- - Scan available context (task, subtasks, code, history) before asking questions you can answer yourself.
14504
- - Challenge when off \u2014 never silently implement the wrong thing.
14505
- - Human leads, you propose. Proactive on reversible actions. Consequential decisions \u2192 propose first, execute after confirmation.
14506
- - Own mistakes. Wrong ID, jumped too fast \u2014 say so and fix it.
14507
- - Think visually. Mermaid over paragraphs for architecture, flows, state, and schema.
14370
+ - Scan available context before asking questions you can answer yourself.
14371
+ - Challenge wrong assumptions before acting.
14372
+ - Human leads. Act on reversible steps; propose before consequential decisions.
14508
14373
 
14509
14374
  ## Task Logging
14510
14375
 
14511
- For non-trivial tasks, log high-signal events as they happen: decisions, changed assumptions, validation results, known-good IDs, blockers, risks, and direction changes. Keep one current task-state summary updated with current state, known-good IDs, open risks, and next action. Do not log routine commands or file reads. Before stopping, ensure the timeline and current state are enough for a human to understand progress and for another agent to resume. If a prior decision is stale, write a newer event that supersedes it.
14376
+ For non-trivial tasks, log high-signal events: decisions, changed assumptions, validation results, known-good IDs, blockers, risks, and direction changes. Do not log routine commands or file reads.
14512
14377
 
14513
- The specific work you do \u2014 implementation, planning, review, coordination, verification \u2014 is determined by your agent role, described next.`;
14378
+ The selected agent profile below defines the role-specific behavior.`;
14514
14379
  function buildAlanTeamScopePrompt(teamId) {
14515
14380
  return [
14516
14381
  `You are operating within team \`${teamId}\`.`,
@@ -14550,15 +14415,7 @@ var PLAN_MODE_PROMPT = [
14550
14415
  "Do not make code changes or execute write operations in plan mode.",
14551
14416
  "Write the plan in natural markdown. Use whatever structure best communicates the work clearly.",
14552
14417
  "Include dependencies, ordering, risks, key files/functions, and decision points where relevant.",
14553
- "When the plan is ready, you MUST persist it by calling the create_plan MCP tool.",
14554
- "Pass title, content, summary, taskId, and conversationId. Include teamId too when available.",
14555
- "If create_plan fails, retry it. Do not finish plan mode until the plan is persisted successfully.",
14556
- "After create_plan succeeds, present the plan title and artifact link to the user for approval."
14557
- ].join("\n");
14558
- var TEST_MODE_PROMPT = [
14559
- "You are in test mode. Verify the implemented feature carefully.",
14560
- "Prefer browser-based validation when available.",
14561
- "Persist the outcome as a structured test report artifact with create_test_report instead of leaving it only in chat."
14418
+ "When task artifact tools and known task/conversation IDs are available, persist the plan as an Alan artifact."
14562
14419
  ].join("\n");
14563
14420
  var ASK_MODE_PROMPT = "You are in ask mode. Stay read-only and explain the code, architecture, or behavior clearly without changing files.";
14564
14421
  var REVIEW_MODE_PROMPT = "You are in review mode. Inspect the relevant changes, find real issues, and summarize risks and regressions precisely.";
@@ -14566,8 +14423,6 @@ function getAlanModePrompt(mode) {
14566
14423
  switch (mode) {
14567
14424
  case "plan":
14568
14425
  return PLAN_MODE_PROMPT;
14569
- case "test":
14570
- return TEST_MODE_PROMPT;
14571
14426
  case "ask":
14572
14427
  return ASK_MODE_PROMPT;
14573
14428
  case "review":
@@ -15142,10 +14997,10 @@ var CLAUDE_CLI_PICKER_FALLBACK_MODELS = [
15142
14997
  slugModel("claude_cli", "claude-opus-4-8", "Opus 4.8", ["200k", "1m"])
15143
14998
  ];
15144
14999
  var CODEX_APP_SERVER_PICKER_FALLBACK_MODELS = [
15145
- slugModel("codex_app_server", "", "CLI default"),
15000
+ slugModel("codex_app_server", "gpt-5.6-sol", "GPT-5.6 Sol"),
15001
+ slugModel("codex_app_server", "gpt-5.6-terra", "GPT-5.6 Terra"),
15002
+ slugModel("codex_app_server", "gpt-5.6-luna", "GPT-5.6 Luna"),
15146
15003
  slugModel("codex_app_server", "gpt-5.5", "GPT-5.5", ["1m"]),
15147
- slugModel("codex_app_server", "gpt-5.4-mini", "GPT-5.4 Mini"),
15148
- slugModel("codex_app_server", "gpt-5.3-codex", "GPT-5.3 Codex"),
15149
15004
  slugModel("codex_app_server", "gpt-5.3-codex-spark", "GPT-5.3 Codex Spark")
15150
15005
  ];
15151
15006
  var ANTIGRAVITY_CLI_PICKER_FALLBACK_MODELS = [
@@ -15285,14 +15140,17 @@ var import_path5 = require("path");
15285
15140
  var import_fs6 = require("fs");
15286
15141
  var import_os6 = require("os");
15287
15142
  var import_path6 = require("path");
15288
- var import_readline2 = require("readline");
15289
- var import_url2 = require("url");
15290
15143
  var import_fs7 = require("fs");
15291
15144
  var import_os7 = require("os");
15292
15145
  var import_path7 = require("path");
15293
- var import_crypto3 = require("crypto");
15146
+ var import_readline2 = require("readline");
15147
+ var import_url2 = require("url");
15294
15148
  var import_fs8 = require("fs");
15149
+ var import_os8 = require("os");
15295
15150
  var import_path8 = require("path");
15151
+ var import_crypto3 = require("crypto");
15152
+ var import_fs9 = require("fs");
15153
+ var import_path9 = require("path");
15296
15154
  var MANAGED_ALAN_MCP_SERVER_NAMES = [
15297
15155
  "alan",
15298
15156
  "alan-prod",
@@ -16354,6 +16212,10 @@ function createGenericCliBackend(options) {
16354
16212
  }
16355
16213
  } finally {
16356
16214
  if (startupTimer) clearTimeout(startupTimer);
16215
+ if (state.providerTranscriptPollTimer) {
16216
+ clearInterval(state.providerTranscriptPollTimer);
16217
+ state.providerTranscriptPollTimer = void 0;
16218
+ }
16357
16219
  stdoutRl.close();
16358
16220
  stderrRl.close();
16359
16221
  logUnhandledStructuredEventSummary(options.kind, state);
@@ -17299,16 +17161,26 @@ function handleClaudeStructuredEvent(parsed, context, state) {
17299
17161
  if (typeof block !== "object" || block === null || !("type" in block)) continue;
17300
17162
  if (block.type === "text" && typeof block.text === "string") {
17301
17163
  const text = block.text;
17302
- state.summary += `${text}
17164
+ if (!parentToolUseId) state.summary += `${text}
17303
17165
  `;
17304
- void presenter.onAssistantText(previousBlockWasText ? `
17305
- ${text}` : text);
17166
+ const streamedText = previousBlockWasText ? `
17167
+ ${text}` : text;
17168
+ if (parentToolUseId) {
17169
+ void presenter.onAssistantText(streamedText, parentToolUseId);
17170
+ } else {
17171
+ void presenter.onAssistantText(streamedText);
17172
+ }
17306
17173
  previousBlockWasText = true;
17307
17174
  continue;
17308
17175
  }
17309
17176
  if (block.type === "thinking" && typeof block.thinking === "string") {
17310
17177
  previousBlockWasText = false;
17311
- void presenter.onThinking(block.thinking);
17178
+ const thinking = block.thinking;
17179
+ if (parentToolUseId) {
17180
+ void presenter.onThinking(thinking, parentToolUseId);
17181
+ } else {
17182
+ void presenter.onThinking(thinking);
17183
+ }
17312
17184
  continue;
17313
17185
  }
17314
17186
  if (block.type === "tool_use" && typeof block.id === "string" && typeof block.name === "string") {
@@ -17686,7 +17558,7 @@ function isSyntheticUserRolloutMessage(payload) {
17686
17558
  const text = extractRolloutMessageText(payload).trimStart();
17687
17559
  if (!text) return false;
17688
17560
  const lower = text.toLowerCase();
17689
- return lower.startsWith("<environment_context") || lower.startsWith("<user_instructions") || // Auto-compaction bridge summaries are tagged in the rollout content.
17561
+ return lower.startsWith("<environment_context") || lower.startsWith("<user_instructions") || lower.startsWith("<recommended_plugins") || lower.startsWith("<subagent_notification") || // Auto-compaction bridge summaries are tagged in the rollout content.
17690
17562
  lower.startsWith("<compact") || lower.startsWith("[compact");
17691
17563
  }
17692
17564
  function latestUserMessageLineIndex(lines) {
@@ -17702,6 +17574,253 @@ function latestUserMessageLineIndex(lines) {
17702
17574
  }
17703
17575
  return latestIndex;
17704
17576
  }
17577
+ function firstUserMessageLineIndex(lines) {
17578
+ for (let index = 0; index < lines.length; index += 1) {
17579
+ const line = lines[index];
17580
+ if (!line) continue;
17581
+ const entry = parseJsonObject(line);
17582
+ const payload = asRecord(entry?.payload);
17583
+ if (payload?.type === "message" && payload.role === "user" && !isSyntheticUserRolloutMessage(payload)) {
17584
+ return index;
17585
+ }
17586
+ }
17587
+ return -1;
17588
+ }
17589
+ function asRecord(value2) {
17590
+ return value2 && typeof value2 === "object" ? value2 : null;
17591
+ }
17592
+ function rolloutTextContent(content) {
17593
+ if (typeof content === "string") return content;
17594
+ if (!Array.isArray(content)) return "";
17595
+ return content.flatMap((block) => {
17596
+ const record = asRecord(block);
17597
+ const text = record?.text;
17598
+ return typeof text === "string" ? [text] : [];
17599
+ }).join("");
17600
+ }
17601
+ function rolloutToolOutputText(output) {
17602
+ if (typeof output === "string") return output;
17603
+ const text = rolloutTextContent(output);
17604
+ if (text) return text;
17605
+ try {
17606
+ return JSON.stringify(output ?? "", null, 2);
17607
+ } catch {
17608
+ return String(output ?? "");
17609
+ }
17610
+ }
17611
+ function rolloutFunctionToolName(payload) {
17612
+ const name = typeof payload.name === "string" ? payload.name : "Codex Tool";
17613
+ const namespace = typeof payload.namespace === "string" ? payload.namespace : "";
17614
+ if (namespace.startsWith("mcp__")) {
17615
+ return `${namespace.replace(/_+$/, "")}__${name}`;
17616
+ }
17617
+ if (name === "exec" || name === "exec_command") return "Bash";
17618
+ return name;
17619
+ }
17620
+ function collectCodexWorkerReplays(lines, state) {
17621
+ const spawnByCallId = /* @__PURE__ */ new Map();
17622
+ const workersByThreadId = /* @__PURE__ */ new Map();
17623
+ for (const line of lines) {
17624
+ const entry = parseJsonObject(line);
17625
+ const payload = asRecord(entry?.payload);
17626
+ if (!payload) continue;
17627
+ if (entry?.type === "response_item" && payload.type === "function_call" && payload.name === "spawn_agent") {
17628
+ const namespace = typeof payload.namespace === "string" ? payload.namespace : "";
17629
+ if (namespace !== "collaboration" && namespace !== "multi_agent_v1") continue;
17630
+ const callId = typeof payload.call_id === "string" ? payload.call_id : "";
17631
+ if (!callId) continue;
17632
+ const args = asRecord(parseMaybeJson(payload.arguments));
17633
+ const taskName = typeof args?.task_name === "string" ? args.task_name : "";
17634
+ const message = typeof args?.message === "string" ? args.message : "";
17635
+ spawnByCallId.set(callId, {
17636
+ launcherId: callId,
17637
+ description: taskName || (message ? message.split(/\r?\n/, 1)[0] : void 0)
17638
+ });
17639
+ continue;
17640
+ }
17641
+ if (entry?.type === "response_item" && payload.type === "function_call_output") {
17642
+ const callId = typeof payload.call_id === "string" ? payload.call_id : "";
17643
+ const spawn32 = spawnByCallId.get(callId);
17644
+ if (!spawn32) continue;
17645
+ const output = asRecord(parseMaybeJson(payload.output));
17646
+ const threadId = typeof output?.agent_id === "string" ? output.agent_id : "";
17647
+ if (!threadId) continue;
17648
+ const nickname = typeof output?.nickname === "string" ? output.nickname : void 0;
17649
+ workersByThreadId.set(threadId, { ...spawn32, threadId, nickname });
17650
+ continue;
17651
+ }
17652
+ if (entry?.type === "event_msg" && payload.type === "sub_agent_activity" && payload.kind === "started") {
17653
+ const threadId = typeof payload.agent_thread_id === "string" ? payload.agent_thread_id : "";
17654
+ const launcherId = typeof payload.event_id === "string" ? payload.event_id : "";
17655
+ if (!threadId || !launcherId) continue;
17656
+ const agentPath = typeof payload.agent_path === "string" ? payload.agent_path : void 0;
17657
+ const spawn32 = spawnByCallId.get(launcherId);
17658
+ workersByThreadId.set(threadId, {
17659
+ launcherId,
17660
+ threadId,
17661
+ agentPath,
17662
+ description: spawn32?.description
17663
+ });
17664
+ }
17665
+ }
17666
+ for (const [threadId, launcherId] of state.backgroundToolIdByTaskId ?? []) {
17667
+ if (!workersByThreadId.has(threadId)) {
17668
+ workersByThreadId.set(threadId, { threadId, launcherId });
17669
+ }
17670
+ }
17671
+ for (const [threadId, launcherId] of state.codexWorkerToolIdByThreadId ?? []) {
17672
+ const existing = workersByThreadId.get(threadId);
17673
+ workersByThreadId.set(threadId, {
17674
+ ...existing,
17675
+ threadId,
17676
+ launcherId
17677
+ });
17678
+ }
17679
+ return [...workersByThreadId.values()];
17680
+ }
17681
+ function replayCodexWorkerTranscript(context, worker, codexHome, state) {
17682
+ const logPath = state.codexWorkerSessionLogPathByThreadId?.get(worker.threadId) ?? findCodexSessionLog(worker.threadId, codexHome);
17683
+ if (!logPath) return "";
17684
+ if (!state.codexWorkerSessionLogPathByThreadId)
17685
+ state.codexWorkerSessionLogPathByThreadId = /* @__PURE__ */ new Map();
17686
+ state.codexWorkerSessionLogPathByThreadId.set(worker.threadId, logPath);
17687
+ const allLines = (0, import_fs5.readFileSync)(logPath, "utf8").split(/\r?\n/).filter(Boolean);
17688
+ const firstUserLineIndex = firstUserMessageLineIndex(allLines);
17689
+ const lines = firstUserLineIndex >= 0 ? allLines.slice(firstUserLineIndex + 1) : allLines;
17690
+ const emittedToolNames = /* @__PURE__ */ new Map();
17691
+ const replayedLineCount = state.codexWorkerReplayLineCountByThreadId?.get(worker.threadId) ?? 0;
17692
+ let finalText = state.codexWorkerFinalTextByThreadId?.get(worker.threadId) ?? "";
17693
+ for (let index = 0; index < lines.length; index += 1) {
17694
+ const line = lines[index];
17695
+ if (!line) continue;
17696
+ const entry = parseJsonObject(line);
17697
+ if (entry?.type !== "response_item") continue;
17698
+ const payload = asRecord(entry.payload);
17699
+ if (!payload) continue;
17700
+ if (payload.type === "message" && payload.role === "assistant") {
17701
+ const text = rolloutTextContent(payload.content);
17702
+ if (!text) continue;
17703
+ finalText = text;
17704
+ if (index >= replayedLineCount) {
17705
+ void context.presenter.onAssistantText(text, worker.launcherId);
17706
+ }
17707
+ continue;
17708
+ }
17709
+ if (payload.type === "function_call") {
17710
+ const callId = typeof payload.call_id === "string" ? payload.call_id : "";
17711
+ if (!callId) continue;
17712
+ const toolName = rolloutFunctionToolName(payload);
17713
+ emittedToolNames.set(callId, toolName);
17714
+ if (index >= replayedLineCount) {
17715
+ void context.presenter.onToolUse(
17716
+ toolName,
17717
+ parseMaybeJson(payload.arguments),
17718
+ callId,
17719
+ worker.launcherId
17720
+ );
17721
+ }
17722
+ continue;
17723
+ }
17724
+ if (payload.type === "custom_tool_call") {
17725
+ const callId = typeof payload.call_id === "string" ? payload.call_id : "";
17726
+ if (!callId) continue;
17727
+ const toolName = rolloutFunctionToolName(payload);
17728
+ emittedToolNames.set(callId, toolName);
17729
+ if (index >= replayedLineCount) {
17730
+ void context.presenter.onToolUse(
17731
+ toolName,
17732
+ { code: payload.input ?? "" },
17733
+ callId,
17734
+ worker.launcherId
17735
+ );
17736
+ }
17737
+ continue;
17738
+ }
17739
+ if (payload.type === "tool_search_call") {
17740
+ const callId = typeof payload.call_id === "string" ? payload.call_id : "";
17741
+ if (!callId) continue;
17742
+ emittedToolNames.set(callId, "tool_search");
17743
+ if (index >= replayedLineCount) {
17744
+ void context.presenter.onToolUse(
17745
+ "tool_search",
17746
+ payload.arguments ?? {},
17747
+ callId,
17748
+ worker.launcherId
17749
+ );
17750
+ }
17751
+ continue;
17752
+ }
17753
+ if (payload.type === "function_call_output" || payload.type === "custom_tool_call_output") {
17754
+ const callId = typeof payload.call_id === "string" ? payload.call_id : "";
17755
+ const toolName = emittedToolNames.get(callId);
17756
+ if (!callId || !toolName || index < replayedLineCount) continue;
17757
+ let output = rolloutToolOutputText(payload.output);
17758
+ if (toolName.startsWith("mcp__")) {
17759
+ try {
17760
+ output = normalizeCodexMcpToolResult(payload.output);
17761
+ } catch {
17762
+ }
17763
+ }
17764
+ void context.presenter.onToolResult?.(callId, output, void 0, worker.launcherId);
17765
+ continue;
17766
+ }
17767
+ if (payload.type === "tool_search_output") {
17768
+ const callId = typeof payload.call_id === "string" ? payload.call_id : "";
17769
+ if (!callId || !emittedToolNames.has(callId) || index < replayedLineCount) continue;
17770
+ void context.presenter.onToolResult?.(
17771
+ callId,
17772
+ JSON.stringify(payload.tools ?? [], null, 2),
17773
+ void 0,
17774
+ worker.launcherId
17775
+ );
17776
+ }
17777
+ }
17778
+ if (!state.codexWorkerReplayLineCountByThreadId)
17779
+ state.codexWorkerReplayLineCountByThreadId = /* @__PURE__ */ new Map();
17780
+ state.codexWorkerReplayLineCountByThreadId.set(worker.threadId, lines.length);
17781
+ if (!state.codexWorkerFinalTextByThreadId) state.codexWorkerFinalTextByThreadId = /* @__PURE__ */ new Map();
17782
+ if (finalText) state.codexWorkerFinalTextByThreadId.set(worker.threadId, finalText);
17783
+ return finalText;
17784
+ }
17785
+ function syncCodexWorkerEventsFromSessionLog(context, state) {
17786
+ const runtimeSessionId = state.runtimeSessionId;
17787
+ if (!runtimeSessionId) return [];
17788
+ const codexHome = resolveCodexHome(context.env);
17789
+ const logPath = state.codexSessionLogPath ?? findCodexSessionLog(runtimeSessionId, codexHome);
17790
+ if (!logPath) return [];
17791
+ state.codexSessionLogPath = logPath;
17792
+ const allLines = (0, import_fs5.readFileSync)(logPath, "utf8").split(/\r?\n/).filter(Boolean);
17793
+ const latestUserLineIndex = latestUserMessageLineIndex(allLines);
17794
+ const lines = latestUserLineIndex >= 0 ? allLines.slice(latestUserLineIndex + 1) : allLines;
17795
+ const workers = collectCodexWorkerReplays(lines, state);
17796
+ for (const worker of workers) {
17797
+ const launcherWasStreamed = state.codexStreamedToolIds?.has(worker.launcherId) === true;
17798
+ if (!launcherWasStreamed) {
17799
+ const workerName = worker.nickname || worker.agentPath?.slice(worker.agentPath.lastIndexOf("/") + 1) || "codex-worker";
17800
+ void context.presenter.onToolUse(
17801
+ "Agent",
17802
+ {
17803
+ subagent_type: workerName,
17804
+ description: worker.description || worker.agentPath || "Codex background worker",
17805
+ agent_thread_id: worker.threadId
17806
+ },
17807
+ worker.launcherId
17808
+ );
17809
+ if (!state.codexStreamedToolIds) state.codexStreamedToolIds = /* @__PURE__ */ new Set();
17810
+ state.codexStreamedToolIds.add(worker.launcherId);
17811
+ if (!state.codexRecoveredLauncherIds) state.codexRecoveredLauncherIds = /* @__PURE__ */ new Set();
17812
+ state.codexRecoveredLauncherIds.add(worker.launcherId);
17813
+ }
17814
+ if (!state.codexWorkerToolIdByThreadId) state.codexWorkerToolIdByThreadId = /* @__PURE__ */ new Map();
17815
+ state.codexWorkerToolIdByThreadId.set(worker.threadId, worker.launcherId);
17816
+ if (worker.agentPath) {
17817
+ if (!state.codexWorkerToolIdByPath) state.codexWorkerToolIdByPath = /* @__PURE__ */ new Map();
17818
+ state.codexWorkerToolIdByPath.set(worker.agentPath, worker.launcherId);
17819
+ }
17820
+ replayCodexWorkerTranscript(context, worker, codexHome, state);
17821
+ }
17822
+ return workers;
17823
+ }
17705
17824
  async function replayCodexMcpToolEventsFromSessionLog(context, state) {
17706
17825
  const runtimeSessionId = state.runtimeSessionId;
17707
17826
  if (!runtimeSessionId) return;
@@ -17758,10 +17877,51 @@ async function replayCodexMcpToolEventsFromSessionLog(context, state) {
17758
17877
  }
17759
17878
  }
17760
17879
  }
17880
+ for (const worker of syncCodexWorkerEventsFromSessionLog(context, state)) {
17881
+ if (state.codexRecoveredLauncherIds?.has(worker.launcherId)) {
17882
+ const finalText = state.codexWorkerFinalTextByThreadId?.get(worker.threadId) ?? "";
17883
+ void context.presenter.onToolResult?.(worker.launcherId, finalText || "Subagent completed.");
17884
+ state.codexRecoveredLauncherIds.delete(worker.launcherId);
17885
+ }
17886
+ }
17761
17887
  }
17762
17888
  var CODEX_EXIT_GRACE_MS = 3e4;
17763
17889
  var CODEX_BACKGROUND_EXIT_GRACE_MS = 10 * 6e4;
17764
17890
  var CODEX_EXIT_GRACE_SIGKILL_MS = 3e3;
17891
+ var CODEX_WORKER_TRANSCRIPT_POLL_MS = 750;
17892
+ function ensureCodexWorkerEventPolling(context, state) {
17893
+ if (!state.runtimeSessionId || state.providerTranscriptPollTimer) return;
17894
+ const poll = () => {
17895
+ try {
17896
+ const before = [...state.codexWorkerReplayLineCountByThreadId?.values() ?? []].reduce(
17897
+ (total, count) => total + count,
17898
+ 0
17899
+ ) + (state.codexStreamedToolIds?.size ?? 0);
17900
+ syncCodexWorkerEventsFromSessionLog(context, state);
17901
+ const after = [...state.codexWorkerReplayLineCountByThreadId?.values() ?? []].reduce(
17902
+ (total, count) => total + count,
17903
+ 0
17904
+ ) + (state.codexStreamedToolIds?.size ?? 0);
17905
+ if (after > before) state.onNewOutput?.();
17906
+ state.providerTranscriptPollErrorLogged = false;
17907
+ } catch (error) {
17908
+ if (!state.providerTranscriptPollErrorLogged) {
17909
+ console.warn("[codex_app_server] Failed to poll worker rollout:", error);
17910
+ state.providerTranscriptPollErrorLogged = true;
17911
+ }
17912
+ }
17913
+ };
17914
+ poll();
17915
+ const timer = setInterval(poll, CODEX_WORKER_TRANSCRIPT_POLL_MS);
17916
+ timer.unref?.();
17917
+ state.providerTranscriptPollTimer = timer;
17918
+ }
17919
+ function codexParentToolUseId(record, state) {
17920
+ const threadId = [record.agent_thread_id, record.sender_thread_id, record.thread_id].find(
17921
+ (value2) => typeof value2 === "string" && value2.length > 0
17922
+ );
17923
+ return threadId ? state.backgroundToolIdByTaskId?.get(threadId) ?? null : null;
17924
+ }
17765
17925
  function armCodexExitGraceKill(state, graceMs = CODEX_EXIT_GRACE_MS) {
17766
17926
  if (state.exitGraceKillTimer) return;
17767
17927
  const child = state.process;
@@ -17891,6 +18051,9 @@ function handleCodexCollabToolCallItem(context, state, item, phase) {
17891
18051
  const prompt = typeof item.prompt === "string" ? item.prompt : "";
17892
18052
  const agentsStates = typeof item.agents_states === "object" && item.agents_states !== null ? item.agents_states : {};
17893
18053
  const itemStatus = typeof item.status === "string" ? item.status : "";
18054
+ if (tool === "wait") {
18055
+ syncCodexWorkerEventsFromSessionLog(context, state);
18056
+ }
17894
18057
  if (tool === "spawn_agent") {
17895
18058
  if (trackCodexStreamedToolId(state, itemId)) {
17896
18059
  const parentToolUseId = senderThreadId ? state.backgroundToolIdByTaskId?.get(senderThreadId) ?? null : null;
@@ -17910,6 +18073,8 @@ function handleCodexCollabToolCallItem(context, state, item, phase) {
17910
18073
  for (const threadId of receiverThreadIds) {
17911
18074
  if (state.backgroundToolIdByTaskId?.get(threadId)) continue;
17912
18075
  registerBackgroundTaskRecord(state, { task_id: threadId, tool_use_id: itemId });
18076
+ if (!state.codexWorkerToolIdByThreadId) state.codexWorkerToolIdByThreadId = /* @__PURE__ */ new Map();
18077
+ state.codexWorkerToolIdByThreadId.set(threadId, itemId);
17913
18078
  }
17914
18079
  applyCodexCollabAgentStates(context, state, agentsStates);
17915
18080
  if (phase === "completed" && itemStatus === "failed") {
@@ -17983,6 +18148,7 @@ function handleCodexStructuredEvent(parsed, context, state) {
17983
18148
  touchCodexBackgroundGrace(state);
17984
18149
  if (typeof parsed.thread_id === "string") {
17985
18150
  state.runtimeSessionId = parsed.thread_id;
18151
+ ensureCodexWorkerEventPolling(context, state);
17986
18152
  }
17987
18153
  const extractCodexErrorMessage = (value2) => {
17988
18154
  if (typeof value2 !== "string") return "";
@@ -18015,6 +18181,7 @@ function handleCodexStructuredEvent(parsed, context, state) {
18015
18181
  case "session_configured":
18016
18182
  if (typeof parsed.session_id === "string") {
18017
18183
  state.runtimeSessionId = parsed.session_id;
18184
+ ensureCodexWorkerEventPolling(context, state);
18018
18185
  }
18019
18186
  return true;
18020
18187
  case "task_started":
@@ -18084,14 +18251,26 @@ function handleCodexStructuredEvent(parsed, context, state) {
18084
18251
  if (!item || typeof item.type !== "string") return true;
18085
18252
  switch (item.type) {
18086
18253
  case "reasoning": {
18087
- if (typeof item.text === "string") void presenter.onThinking(item.text);
18254
+ if (typeof item.text === "string") {
18255
+ const parentToolUseId = codexParentToolUseId(item, state);
18256
+ if (parentToolUseId) {
18257
+ void presenter.onThinking(item.text, parentToolUseId);
18258
+ } else {
18259
+ void presenter.onThinking(item.text);
18260
+ }
18261
+ }
18088
18262
  return true;
18089
18263
  }
18090
18264
  case "agent_message": {
18091
18265
  if (typeof item.text === "string") {
18092
- state.summary += `${item.text}
18266
+ const parentToolUseId = codexParentToolUseId(item, state);
18267
+ if (!parentToolUseId) state.summary += `${item.text}
18093
18268
  `;
18094
- void presenter.onAssistantText(item.text);
18269
+ if (parentToolUseId) {
18270
+ void presenter.onAssistantText(item.text, parentToolUseId);
18271
+ } else {
18272
+ void presenter.onAssistantText(item.text);
18273
+ }
18095
18274
  }
18096
18275
  return true;
18097
18276
  }
@@ -18153,8 +18332,13 @@ function handleCodexStructuredEvent(parsed, context, state) {
18153
18332
  case "agent_message_content_delta": {
18154
18333
  const delta = typeof parsed.delta === "string" ? parsed.delta : "";
18155
18334
  if (!delta) return true;
18156
- state.summary += delta;
18157
- void presenter.onAssistantText(delta);
18335
+ const parentToolUseId = codexParentToolUseId(parsed, state);
18336
+ if (!parentToolUseId) state.summary += delta;
18337
+ if (parentToolUseId) {
18338
+ void presenter.onAssistantText(delta, parentToolUseId);
18339
+ } else {
18340
+ void presenter.onAssistantText(delta);
18341
+ }
18158
18342
  return true;
18159
18343
  }
18160
18344
  case "agent_reasoning_delta":
@@ -18162,7 +18346,12 @@ function handleCodexStructuredEvent(parsed, context, state) {
18162
18346
  case "agent_reasoning_raw_content_delta": {
18163
18347
  const delta = typeof parsed.delta === "string" ? parsed.delta : "";
18164
18348
  if (!delta) return true;
18165
- void presenter.onThinking(delta);
18349
+ const parentToolUseId = codexParentToolUseId(parsed, state);
18350
+ if (parentToolUseId) {
18351
+ void presenter.onThinking(delta, parentToolUseId);
18352
+ } else {
18353
+ void presenter.onThinking(delta);
18354
+ }
18166
18355
  return true;
18167
18356
  }
18168
18357
  case "exec_command_begin": {
@@ -18230,6 +18419,7 @@ function handleCodexStructuredEvent(parsed, context, state) {
18230
18419
  return true;
18231
18420
  }
18232
18421
  case "turn.completed": {
18422
+ syncCodexWorkerEventsFromSessionLog(context, state);
18233
18423
  const usage = typeof parsed.usage === "object" && parsed.usage !== null ? parsed.usage : {};
18234
18424
  state.usage = {
18235
18425
  model: typeof context.config.selectedModel === "string" && context.config.selectedModel.trim() ? context.config.selectedModel : "codex",
@@ -18281,6 +18471,8 @@ function handleCodexStructuredEvent(parsed, context, state) {
18281
18471
  registerBackgroundLauncher(state, toolId);
18282
18472
  if (agentThreadId) {
18283
18473
  registerBackgroundTaskRecord(state, { task_id: agentThreadId, tool_use_id: toolId });
18474
+ if (!state.codexWorkerToolIdByThreadId) state.codexWorkerToolIdByThreadId = /* @__PURE__ */ new Map();
18475
+ state.codexWorkerToolIdByThreadId.set(agentThreadId, toolId);
18284
18476
  }
18285
18477
  if (!state.codexWorkerToolIdByPath) state.codexWorkerToolIdByPath = /* @__PURE__ */ new Map();
18286
18478
  state.codexWorkerToolIdByPath.set(agentPath, toolId);
@@ -18601,12 +18793,16 @@ function createCopilotCliBackend(command = "copilot", defaultArgs = []) {
18601
18793
  }
18602
18794
  };
18603
18795
  }
18796
+ function asRecord2(value2) {
18797
+ return typeof value2 === "object" && value2 !== null ? value2 : null;
18798
+ }
18604
18799
  function extractCursorToolEntry(toolCall) {
18605
18800
  const [rawName, rawPayload] = Object.entries(toolCall)[0] ?? [];
18606
18801
  if (!rawName || typeof rawPayload !== "object" || rawPayload === null) return null;
18607
18802
  return { rawName, payload: rawPayload };
18608
18803
  }
18609
18804
  function formatCursorToolName(rawName, payload) {
18805
+ if (rawName === "taskToolCall") return "Agent";
18610
18806
  if (rawName === "terminalToolCall") return "Bash";
18611
18807
  if (rawName === "mcpToolCall") {
18612
18808
  const provider = typeof payload.providerIdentifier === "string" ? payload.providerIdentifier : typeof payload.serverName === "string" ? payload.serverName : typeof payload.mcpServer === "string" ? payload.mcpServer : "";
@@ -18618,6 +18814,59 @@ function formatCursorToolName(rawName, payload) {
18618
18814
  if (!trimmed) return "Cursor Tool";
18619
18815
  return trimmed.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/^[a-z]/, (char) => char.toUpperCase());
18620
18816
  }
18817
+ function cursorTaskResultVariant(payload, variant) {
18818
+ const result = asRecord2(payload.result);
18819
+ if (!result) return null;
18820
+ const direct = asRecord2(result[variant]);
18821
+ if (direct) return direct;
18822
+ const oneof = asRecord2(result.result);
18823
+ return oneof?.case === variant ? asRecord2(oneof.value) : null;
18824
+ }
18825
+ function cursorSubagentType(value2) {
18826
+ const normalize = (candidate) => {
18827
+ const trimmed = candidate?.trim();
18828
+ if (!trimmed) return void 0;
18829
+ const normalized = trimmed.toLowerCase();
18830
+ if (normalized === "unspecified" || normalized.endsWith("_unspecified")) return void 0;
18831
+ return trimmed;
18832
+ };
18833
+ if (typeof value2 === "string") return normalize(value2);
18834
+ const record = asRecord2(value2);
18835
+ if (!record) return void 0;
18836
+ if (typeof record.case === "string" && record.case) return normalize(record.case);
18837
+ if (typeof record.type === "string" && record.type) return normalize(record.type);
18838
+ const nestedType = asRecord2(record.type);
18839
+ if (typeof nestedType?.case === "string" && nestedType.case) return normalize(nestedType.case);
18840
+ return normalize(
18841
+ Object.keys(nestedType ?? record).find((key) => key !== "value" && key !== "case")
18842
+ );
18843
+ }
18844
+ function cursorToolArgs(entry) {
18845
+ const args = asRecord2(entry.payload.args) ?? asRecord2(entry.payload.arguments) ?? entry.payload;
18846
+ if (entry.rawName !== "taskToolCall") return args;
18847
+ const subagentType = cursorSubagentType(args.subagentType ?? args.subagent_type);
18848
+ return {
18849
+ ...typeof args.description === "string" ? { description: args.description } : {},
18850
+ ...typeof args.prompt === "string" ? { prompt: args.prompt } : {},
18851
+ ...subagentType ? { subagent_type: subagentType } : {},
18852
+ ...typeof args.model === "string" ? { model: args.model } : {}
18853
+ };
18854
+ }
18855
+ function cursorConversationStepValue(step, key) {
18856
+ const direct = asRecord2(step[key]);
18857
+ if (direct) return direct;
18858
+ const message = asRecord2(step.message);
18859
+ return message?.case === key ? asRecord2(message.value) : null;
18860
+ }
18861
+ function cursorConversationStepText(steps) {
18862
+ if (!Array.isArray(steps)) return "";
18863
+ return steps.flatMap((step) => {
18864
+ const record = asRecord2(step);
18865
+ if (!record) return [];
18866
+ const assistant = cursorConversationStepValue(record, "assistantMessage");
18867
+ return typeof assistant?.text === "string" ? [assistant.text] : [];
18868
+ }).join("\n").trim();
18869
+ }
18621
18870
  function buildCursorToolResultText(result) {
18622
18871
  if (typeof result === "string") return result;
18623
18872
  if (!result || typeof result !== "object") return JSON.stringify(result ?? {});
@@ -18639,6 +18888,202 @@ function buildCursorToolResultText(result) {
18639
18888
  }
18640
18889
  return JSON.stringify(result, null, 2);
18641
18890
  }
18891
+ function emitCursorSubagentConversationSteps(steps, parentToolUseId, presenter) {
18892
+ if (!Array.isArray(steps)) return;
18893
+ steps.forEach((step, index) => {
18894
+ const record = asRecord2(step);
18895
+ if (!record) return;
18896
+ const assistant = cursorConversationStepValue(record, "assistantMessage");
18897
+ if (typeof assistant?.text === "string" && assistant.text) {
18898
+ void presenter.onAssistantText(assistant.text, parentToolUseId);
18899
+ return;
18900
+ }
18901
+ const thinking = cursorConversationStepValue(record, "thinkingMessage");
18902
+ if (typeof thinking?.text === "string" && thinking.text) {
18903
+ void presenter.onThinking(thinking.text, parentToolUseId);
18904
+ return;
18905
+ }
18906
+ const toolCall = cursorConversationStepValue(record, "toolCall");
18907
+ if (!toolCall) return;
18908
+ const entry = extractCursorToolEntry(toolCall);
18909
+ if (!entry) return;
18910
+ const args = cursorToolArgs(entry);
18911
+ const toolId = typeof args.toolCallId === "string" && args.toolCallId || typeof args.tool_call_id === "string" && args.tool_call_id || `${parentToolUseId}-step-${index}`;
18912
+ void presenter.onToolUse(
18913
+ formatCursorToolName(entry.rawName, entry.payload),
18914
+ args,
18915
+ toolId,
18916
+ parentToolUseId
18917
+ );
18918
+ if (entry.payload.result !== void 0) {
18919
+ const isError = cursorTaskResultVariant(entry.payload, "error") !== null;
18920
+ void presenter.onToolResult?.(
18921
+ toolId,
18922
+ buildCursorToolResultText(entry.payload.result),
18923
+ isError || void 0,
18924
+ parentToolUseId
18925
+ );
18926
+ }
18927
+ });
18928
+ }
18929
+ function emitCursorSubagentTranscript(transcriptPath, parentToolUseId, presenter, startLine = 0) {
18930
+ if (typeof transcriptPath !== "string" || !transcriptPath) {
18931
+ return { found: false, processedLineCount: startLine, emittedEventCount: 0 };
18932
+ }
18933
+ let lines;
18934
+ try {
18935
+ lines = (0, import_fs6.readFileSync)(transcriptPath, "utf8").split(/\r?\n/);
18936
+ if (lines.at(-1) === "") lines.pop();
18937
+ } catch {
18938
+ return { found: false, processedLineCount: startLine, emittedEventCount: 0 };
18939
+ }
18940
+ let processedLineCount = startLine > lines.length ? 0 : startLine;
18941
+ let emittedEventCount = 0;
18942
+ for (let lineIndex = processedLineCount; lineIndex < lines.length; lineIndex += 1) {
18943
+ const line = lines[lineIndex];
18944
+ if (!line) {
18945
+ processedLineCount = lineIndex + 1;
18946
+ continue;
18947
+ }
18948
+ let entry;
18949
+ try {
18950
+ entry = JSON.parse(line);
18951
+ } catch {
18952
+ break;
18953
+ }
18954
+ processedLineCount = lineIndex + 1;
18955
+ if (entry.role !== "assistant") continue;
18956
+ const message = asRecord2(entry.message);
18957
+ const content = Array.isArray(message?.content) ? message.content : [];
18958
+ content.forEach((rawBlock, blockIndex) => {
18959
+ const block = asRecord2(rawBlock);
18960
+ if (!block) return;
18961
+ const type = typeof block.type === "string" ? block.type : "";
18962
+ const text = typeof block.text === "string" ? block.text : "";
18963
+ if (type === "text" && text) {
18964
+ emittedEventCount += 1;
18965
+ void presenter.onAssistantText(text, parentToolUseId);
18966
+ return;
18967
+ }
18968
+ if ((type === "thinking" || type === "reasoning") && text) {
18969
+ emittedEventCount += 1;
18970
+ void presenter.onThinking(text, parentToolUseId);
18971
+ return;
18972
+ }
18973
+ if (type !== "tool_use") return;
18974
+ const name = typeof block.name === "string" && block.name ? block.name : "Cursor Tool";
18975
+ const toolId = typeof block.id === "string" && block.id || `${parentToolUseId}-transcript-${lineIndex}-${blockIndex}`;
18976
+ emittedEventCount += 1;
18977
+ void presenter.onToolUse(name, asRecord2(block.input) ?? {}, toolId, parentToolUseId);
18978
+ });
18979
+ }
18980
+ return { found: true, processedLineCount, emittedEventCount };
18981
+ }
18982
+ function cursorTranscriptsRoot(context) {
18983
+ const projectKey = context.cwd.replace(/^[/\\]+/, "").replace(/[/\\]+/g, "-");
18984
+ const home = context.env.HOME || process.env.HOME || (0, import_os6.homedir)();
18985
+ return (0, import_path6.join)(home, ".cursor", "projects", projectKey, "agent-transcripts");
18986
+ }
18987
+ function cursorTranscriptPathForAgent(context, agentId) {
18988
+ return (0, import_path6.join)(cursorTranscriptsRoot(context), agentId, `${agentId}.jsonl`);
18989
+ }
18990
+ function resolveCursorSubagentTranscriptPath(success, context) {
18991
+ const explicit = success?.transcriptPath ?? success?.transcript_path;
18992
+ if (typeof explicit === "string" && explicit) return explicit;
18993
+ const agentId = typeof success?.agentId === "string" ? success.agentId : "";
18994
+ return agentId ? cursorTranscriptPathForAgent(context, agentId) : void 0;
18995
+ }
18996
+ function cursorTranscriptUserText(transcriptPath) {
18997
+ try {
18998
+ for (const line of (0, import_fs6.readFileSync)(transcriptPath, "utf8").split(/\r?\n/)) {
18999
+ if (!line) continue;
19000
+ const entry = asRecord2(JSON.parse(line));
19001
+ if (entry?.role !== "user") continue;
19002
+ const message = asRecord2(entry.message);
19003
+ const content = Array.isArray(message?.content) ? message.content : [];
19004
+ return content.flatMap((block) => {
19005
+ const record = asRecord2(block);
19006
+ return typeof record?.text === "string" ? [record.text] : [];
19007
+ }).join("");
19008
+ }
19009
+ } catch {
19010
+ }
19011
+ return "";
19012
+ }
19013
+ function discoverCursorSubagentTranscript(context, state, task) {
19014
+ const root = cursorTranscriptsRoot(context);
19015
+ if (!(0, import_fs6.existsSync)(root)) return void 0;
19016
+ const prompt = task.prompt?.trim();
19017
+ const description = task.description?.trim().toLowerCase();
19018
+ const candidates = [];
19019
+ let entries;
19020
+ try {
19021
+ entries = (0, import_fs6.readdirSync)(root, { withFileTypes: true });
19022
+ } catch {
19023
+ return void 0;
19024
+ }
19025
+ for (const entry of entries) {
19026
+ if (!entry.isDirectory() || entry.name === state.runtimeSessionId) continue;
19027
+ const path = cursorTranscriptPathForAgent(context, entry.name);
19028
+ let mtimeMs;
19029
+ try {
19030
+ mtimeMs = (0, import_fs6.statSync)(path).mtimeMs;
19031
+ } catch {
19032
+ continue;
19033
+ }
19034
+ if (mtimeMs < task.startedAtMs - 2e3) continue;
19035
+ const userText = cursorTranscriptUserText(path).trim();
19036
+ if (!userText) continue;
19037
+ let score = 0;
19038
+ if (prompt && userText === prompt) score = 3;
19039
+ else if (prompt && (userText.includes(prompt) || prompt.includes(userText))) score = 2;
19040
+ else if (description && userText.toLowerCase().includes(description)) score = 1;
19041
+ if (score > 0) candidates.push({ path, score, mtimeMs });
19042
+ }
19043
+ candidates.sort((a, b) => b.score - a.score || b.mtimeMs - a.mtimeMs);
19044
+ return candidates[0]?.path;
19045
+ }
19046
+ function syncCursorSubagentEventsFromTranscripts(context, state) {
19047
+ let emittedEventCount = 0;
19048
+ for (const [launcherId, task] of state.cursorSubagentTranscripts ?? []) {
19049
+ task.transcriptPath ??= discoverCursorSubagentTranscript(context, state, task);
19050
+ if (!task.transcriptPath) continue;
19051
+ const replay = emitCursorSubagentTranscript(
19052
+ task.transcriptPath,
19053
+ launcherId,
19054
+ context.presenter,
19055
+ task.replayedLineCount
19056
+ );
19057
+ task.replayedLineCount = replay.processedLineCount;
19058
+ task.emittedEventCount += replay.emittedEventCount;
19059
+ emittedEventCount += replay.emittedEventCount;
19060
+ }
19061
+ if (emittedEventCount > 0) state.onNewOutput?.();
19062
+ return emittedEventCount;
19063
+ }
19064
+ function ensureCursorSubagentTranscriptPolling(context, state) {
19065
+ if (state.providerTranscriptPollTimer) return;
19066
+ const poll = () => {
19067
+ try {
19068
+ syncCursorSubagentEventsFromTranscripts(context, state);
19069
+ state.providerTranscriptPollErrorLogged = false;
19070
+ } catch (error) {
19071
+ if (!state.providerTranscriptPollErrorLogged) {
19072
+ console.warn("[cursor_agent_cli] Failed to poll child transcript:", error);
19073
+ state.providerTranscriptPollErrorLogged = true;
19074
+ }
19075
+ }
19076
+ };
19077
+ poll();
19078
+ const timer = setInterval(poll, 750);
19079
+ timer.unref?.();
19080
+ state.providerTranscriptPollTimer = timer;
19081
+ }
19082
+ function stopCursorSubagentTranscriptPollingIfIdle(state) {
19083
+ if (state.cursorSubagentTranscripts?.size) return;
19084
+ if (state.providerTranscriptPollTimer) clearInterval(state.providerTranscriptPollTimer);
19085
+ state.providerTranscriptPollTimer = void 0;
19086
+ }
18642
19087
  function handleCursorStructuredEvent(parsed, context, state) {
18643
19088
  const presenter = context.presenter;
18644
19089
  const type = typeof parsed.type === "string" ? parsed.type : "";
@@ -18646,8 +19091,22 @@ function handleCursorStructuredEvent(parsed, context, state) {
18646
19091
  if (typeof parsed.session_id === "string") state.runtimeSessionId = parsed.session_id;
18647
19092
  if (typeof parsed.model === "string") state.activeModel = parsed.model;
18648
19093
  switch (type) {
18649
- case "system":
19094
+ case "system": {
19095
+ if (parsed.subtype !== "task_notification") return true;
19096
+ const status = typeof parsed.status === "string" ? parsed.status.toLowerCase() : "completed";
19097
+ const isError = ["error", "failed", "aborted", "cancelled", "interrupted"].includes(status);
19098
+ const resultText = typeof parsed.detail === "string" && parsed.detail || typeof parsed.title === "string" && parsed.title || `Background subagent ${status}`;
19099
+ const toolUseId = resolveBackgroundTaskToolUseId(state, parsed);
19100
+ clearBackgroundTaskIds(state, backgroundTaskKeys(parsed));
19101
+ const launcherId = toolUseId ?? drainNextUnlinkedBackgroundLauncher(state);
19102
+ if (launcherId) {
19103
+ syncCursorSubagentEventsFromTranscripts(context, state);
19104
+ state.cursorSubagentTranscripts?.delete(launcherId);
19105
+ stopCursorSubagentTranscriptPollingIfIdle(state);
19106
+ void presenter.onToolResult?.(launcherId, resultText, isError || void 0);
19107
+ }
18650
19108
  return true;
19109
+ }
18651
19110
  case "thinking":
18652
19111
  case "reasoning": {
18653
19112
  const subtype = typeof parsed.subtype === "string" ? parsed.subtype : "";
@@ -18696,14 +19155,72 @@ function handleCursorStructuredEvent(parsed, context, state) {
18696
19155
  if (!toolId) return true;
18697
19156
  state.iterations = Math.max(state.iterations, 1);
18698
19157
  const toolName = formatCursorToolName(entry.rawName, entry.payload);
18699
- const toolArgs = typeof entry.payload.args === "object" && entry.payload.args !== null ? entry.payload.args : typeof entry.payload.arguments === "object" && entry.payload.arguments !== null ? entry.payload.arguments : entry.payload;
19158
+ const toolArgs = cursorToolArgs(entry);
18700
19159
  if (subtype === "started") {
18701
19160
  void presenter.onToolUse(toolName, toolArgs, toolId);
19161
+ if (entry.rawName === "taskToolCall") {
19162
+ if (!state.cursorSubagentTranscripts) state.cursorSubagentTranscripts = /* @__PURE__ */ new Map();
19163
+ state.cursorSubagentTranscripts.set(toolId, {
19164
+ description: typeof toolArgs.description === "string" ? toolArgs.description : void 0,
19165
+ prompt: typeof toolArgs.prompt === "string" ? toolArgs.prompt : void 0,
19166
+ startedAtMs: typeof parsed.timestamp_ms === "number" ? parsed.timestamp_ms : typeof entry.payload.startedAtMs === "number" ? entry.payload.startedAtMs : Number(entry.payload.startedAtMs) || Date.now(),
19167
+ replayedLineCount: 0,
19168
+ emittedEventCount: 0
19169
+ });
19170
+ ensureCursorSubagentTranscriptPolling(context, state);
19171
+ }
18702
19172
  return true;
18703
19173
  }
18704
19174
  if (subtype === "completed") {
18705
19175
  if (!hasCallId) state.lastAnonymousCursorToolId = void 0;
18706
- void presenter.onToolResult?.(toolId, buildCursorToolResultText(entry.payload.result));
19176
+ if (entry.rawName === "taskToolCall") {
19177
+ const resultEnvelope = typeof parsed.result === "object" && parsed.result !== null ? parsed : entry.payload;
19178
+ const success = cursorTaskResultVariant(resultEnvelope, "success");
19179
+ const failure = cursorTaskResultVariant(resultEnvelope, "error");
19180
+ const task = state.cursorSubagentTranscripts?.get(toolId);
19181
+ if (task) {
19182
+ task.transcriptPath = resolveCursorSubagentTranscriptPath(success, context) ?? task.transcriptPath;
19183
+ }
19184
+ let replayedTranscript = false;
19185
+ if (task) {
19186
+ syncCursorSubagentEventsFromTranscripts(context, state);
19187
+ replayedTranscript = task.emittedEventCount > 0;
19188
+ } else {
19189
+ replayedTranscript = emitCursorSubagentTranscript(
19190
+ resolveCursorSubagentTranscriptPath(success, context),
19191
+ toolId,
19192
+ presenter
19193
+ ).emittedEventCount > 0;
19194
+ }
19195
+ if (!replayedTranscript) {
19196
+ emitCursorSubagentConversationSteps(success?.conversationSteps, toolId, presenter);
19197
+ }
19198
+ if (success?.isBackground === true) {
19199
+ registerBackgroundLauncher(state, toolId);
19200
+ const taskId = typeof success.agentId === "string" && success.agentId ? success.agentId : void 0;
19201
+ if (taskId) {
19202
+ registerBackgroundTaskRecord(state, {
19203
+ task_id: taskId,
19204
+ tool_use_id: toolId
19205
+ });
19206
+ }
19207
+ return true;
19208
+ }
19209
+ state.cursorSubagentTranscripts?.delete(toolId);
19210
+ stopCursorSubagentTranscriptPollingIfIdle(state);
19211
+ const summary = cursorConversationStepText(success?.conversationSteps);
19212
+ const failureText = typeof failure?.error === "string" && failure.error ? failure.error : "Cursor subagent failed";
19213
+ void presenter.onToolResult?.(
19214
+ toolId,
19215
+ failure ? failureText : summary || buildCursorToolResultText(resultEnvelope.result),
19216
+ failure ? true : void 0
19217
+ );
19218
+ return true;
19219
+ }
19220
+ void presenter.onToolResult?.(
19221
+ toolId,
19222
+ buildCursorToolResultText(parsed.result ?? entry.payload.result)
19223
+ );
18707
19224
  }
18708
19225
  return true;
18709
19226
  }
@@ -19061,7 +19578,7 @@ function createDroidCliBackend(command = "droid", defaultArgs = []) {
19061
19578
  };
19062
19579
  }
19063
19580
  var ACP_PROTOCOL_VERSION = 1;
19064
- function asRecord(value2) {
19581
+ function asRecord3(value2) {
19065
19582
  return value2 && typeof value2 === "object" && !Array.isArray(value2) ? value2 : null;
19066
19583
  }
19067
19584
  function asString(value2) {
@@ -19071,7 +19588,7 @@ function resumeSessionId(context) {
19071
19588
  return context.config.runtimeSessionId?.trim() || context.config.providerSessionId?.trim() || "";
19072
19589
  }
19073
19590
  function chunkText(content) {
19074
- const record = asRecord(content);
19591
+ const record = asRecord3(content);
19075
19592
  if (!record) return "";
19076
19593
  if (typeof record.text === "string") return record.text;
19077
19594
  return chunkText(record.content);
@@ -19087,23 +19604,23 @@ function toolResultText(update) {
19087
19604
  return "";
19088
19605
  }
19089
19606
  function toolMetaName(update) {
19090
- const meta = asRecord(update._meta);
19091
- const tool = asRecord(meta?.["x.ai/tool"]);
19607
+ const meta = asRecord3(update._meta);
19608
+ const tool = asRecord3(meta?.["x.ai/tool"]);
19092
19609
  return asString(tool?.name);
19093
19610
  }
19094
19611
  function resolvePermission(params, context) {
19095
- const record = asRecord(params);
19612
+ const record = asRecord3(params);
19096
19613
  const options = Array.isArray(record?.options) ? record?.options : [];
19097
- const toolCall = asRecord(record?.toolCall);
19098
- const meta = asRecord(toolCall?._meta);
19099
- const tool = asRecord(meta?.["x.ai/tool"]);
19614
+ const toolCall = asRecord3(record?.toolCall);
19615
+ const meta = asRecord3(toolCall?._meta);
19616
+ const tool = asRecord3(meta?.["x.ai/tool"]);
19100
19617
  const isReadOnlyTool = tool?.read_only === true || asString(tool?.kind) === "read";
19101
19618
  const allow = !shouldUseReadOnlyRuntimePermissions(context.config) || isReadOnlyTool;
19102
19619
  const allowKinds = ["allow_always", "allow_once", "allow"];
19103
19620
  const rejectKinds = ["reject_always", "reject_once", "reject", "deny"];
19104
19621
  const wanted = allow ? allowKinds : rejectKinds;
19105
- const chosen = options.find((option) => wanted.includes(asString(asRecord(option)?.kind))) ?? (allow ? options[0] : options[options.length - 1]);
19106
- const optionId = asString(asRecord(chosen)?.optionId);
19622
+ const chosen = options.find((option) => wanted.includes(asString(asRecord3(option)?.kind))) ?? (allow ? options[0] : options[options.length - 1]);
19623
+ const optionId = asString(asRecord3(chosen)?.optionId);
19107
19624
  if (!optionId) return { outcome: { outcome: "cancelled" } };
19108
19625
  return { outcome: { outcome: "selected", optionId } };
19109
19626
  }
@@ -19179,9 +19696,9 @@ function createGrokAcpDriver(imageFiles) {
19179
19696
  finalize(state);
19180
19697
  return;
19181
19698
  }
19182
- const result = asRecord(message.result);
19699
+ const result = asRecord3(message.result);
19183
19700
  if (message.id === initId) {
19184
- const modelState = asRecord(asRecord(result?._meta)?.modelState);
19701
+ const modelState = asRecord3(asRecord3(result?._meta)?.modelState);
19185
19702
  const model = asString(modelState?.currentModelId);
19186
19703
  if (model) state.activeModel = model;
19187
19704
  beginSession(context, state);
@@ -19195,7 +19712,7 @@ function createGrokAcpDriver(imageFiles) {
19195
19712
  return;
19196
19713
  }
19197
19714
  if (message.id === promptId) {
19198
- const meta = asRecord(result?._meta);
19715
+ const meta = asRecord3(result?._meta);
19199
19716
  const model = asString(meta?.modelId) || state.activeModel || (typeof context.config.selectedModel === "string" && context.config.selectedModel.trim() ? context.config.selectedModel.trim() : "grok");
19200
19717
  const inputTokens = typeof meta?.inputTokens === "number" ? meta.inputTokens : 0;
19201
19718
  const outputTokens = typeof meta?.outputTokens === "number" ? meta.outputTokens : 0;
@@ -19240,8 +19757,8 @@ function createGrokAcpDriver(imageFiles) {
19240
19757
  }
19241
19758
  }
19242
19759
  function handleNotification(message, context, state) {
19243
- const params = asRecord(message.params);
19244
- const update = asRecord(params?.update);
19760
+ const params = asRecord3(message.params);
19761
+ const update = asRecord3(params?.update);
19245
19762
  if (!update || !isPromptActive) return;
19246
19763
  const presenter = context.presenter;
19247
19764
  switch (asString(update.sessionUpdate)) {
@@ -19288,7 +19805,7 @@ function createGrokAcpDriver(imageFiles) {
19288
19805
  if (line.trim().length > 0) void context.presenter.onLog(`[grok_cli] ${line}`);
19289
19806
  return;
19290
19807
  }
19291
- const message = asRecord(parsed);
19808
+ const message = asRecord3(parsed);
19292
19809
  if (!message) return;
19293
19810
  if (message.id !== void 0 && message.method === void 0) {
19294
19811
  handleResponse(message, context, state);
@@ -19355,9 +19872,9 @@ function buildGrokAgentArgs(config, defaultArgs = []) {
19355
19872
  return args;
19356
19873
  }
19357
19874
  var DEFAULT_SKILL_ROOTS = [
19358
- (0, import_path6.join)((0, import_os6.homedir)(), ".agents", "skills"),
19359
- (0, import_path6.join)((0, import_os6.homedir)(), ".claude", "skills"),
19360
- (0, import_path6.join)((0, import_os6.homedir)(), ".config", "opencode", "skills")
19875
+ (0, import_path7.join)((0, import_os7.homedir)(), ".agents", "skills"),
19876
+ (0, import_path7.join)((0, import_os7.homedir)(), ".claude", "skills"),
19877
+ (0, import_path7.join)((0, import_os7.homedir)(), ".config", "opencode", "skills")
19361
19878
  ];
19362
19879
  function parseFrontmatter(content) {
19363
19880
  if (!content.startsWith("---\n")) return {};
@@ -19373,12 +19890,12 @@ function parseFrontmatter(content) {
19373
19890
  return result;
19374
19891
  }
19375
19892
  function listSkillFiles(root) {
19376
- if (!(0, import_fs6.existsSync)(root)) return [];
19893
+ if (!(0, import_fs7.existsSync)(root)) return [];
19377
19894
  const files = [];
19378
- for (const entry of (0, import_fs6.readdirSync)(root, { withFileTypes: true })) {
19895
+ for (const entry of (0, import_fs7.readdirSync)(root, { withFileTypes: true })) {
19379
19896
  if (!entry.isDirectory()) continue;
19380
- const skillPath = (0, import_path6.join)(root, entry.name, "SKILL.md");
19381
- if ((0, import_fs6.existsSync)(skillPath)) files.push(skillPath);
19897
+ const skillPath = (0, import_path7.join)(root, entry.name, "SKILL.md");
19898
+ if ((0, import_fs7.existsSync)(skillPath)) files.push(skillPath);
19382
19899
  }
19383
19900
  return files;
19384
19901
  }
@@ -19387,7 +19904,7 @@ function loadInstalledSkills(roots = DEFAULT_SKILL_ROOTS) {
19387
19904
  for (const root of roots) {
19388
19905
  for (const skillPath of listSkillFiles(root)) {
19389
19906
  try {
19390
- const frontmatter = parseFrontmatter((0, import_fs6.readFileSync)(skillPath, "utf8"));
19907
+ const frontmatter = parseFrontmatter((0, import_fs7.readFileSync)(skillPath, "utf8"));
19391
19908
  const name = frontmatter.name;
19392
19909
  const description = frontmatter.description;
19393
19910
  if (!name || !description || skills.has(name)) continue;
@@ -20356,40 +20873,40 @@ function parseSkillInvocation(text) {
20356
20873
  function candidateRoots(cwd) {
20357
20874
  const roots = [];
20358
20875
  if (cwd) {
20359
- roots.push((0, import_path7.join)(cwd, ".agents", "skills"));
20360
- roots.push((0, import_path7.join)(cwd, ".claude", "skills"));
20361
- roots.push((0, import_path7.join)(cwd, ".codex", "skills"));
20362
- if ((0, import_fs7.existsSync)(cwd)) {
20876
+ roots.push((0, import_path8.join)(cwd, ".agents", "skills"));
20877
+ roots.push((0, import_path8.join)(cwd, ".claude", "skills"));
20878
+ roots.push((0, import_path8.join)(cwd, ".codex", "skills"));
20879
+ if ((0, import_fs8.existsSync)(cwd)) {
20363
20880
  let entries = [];
20364
20881
  try {
20365
- entries = (0, import_fs7.readdirSync)(cwd, { withFileTypes: true });
20882
+ entries = (0, import_fs8.readdirSync)(cwd, { withFileTypes: true });
20366
20883
  } catch {
20367
20884
  }
20368
20885
  for (const entry of entries) {
20369
20886
  if (!entry.isDirectory()) continue;
20370
20887
  if (entry.name.startsWith(".")) continue;
20371
- const child = (0, import_path7.join)(cwd, entry.name);
20372
- roots.push((0, import_path7.join)(child, ".agents", "skills"));
20373
- roots.push((0, import_path7.join)(child, ".claude", "skills"));
20374
- roots.push((0, import_path7.join)(child, ".codex", "skills"));
20888
+ const child = (0, import_path8.join)(cwd, entry.name);
20889
+ roots.push((0, import_path8.join)(child, ".agents", "skills"));
20890
+ roots.push((0, import_path8.join)(child, ".claude", "skills"));
20891
+ roots.push((0, import_path8.join)(child, ".codex", "skills"));
20375
20892
  }
20376
20893
  }
20377
20894
  }
20378
- const home = (0, import_os7.homedir)();
20379
- roots.push((0, import_path7.join)(home, ".agents", "skills"));
20380
- roots.push((0, import_path7.join)(home, ".claude", "skills"));
20381
- roots.push((0, import_path7.join)(home, ".codex", "skills"));
20895
+ const home = (0, import_os8.homedir)();
20896
+ roots.push((0, import_path8.join)(home, ".agents", "skills"));
20897
+ roots.push((0, import_path8.join)(home, ".claude", "skills"));
20898
+ roots.push((0, import_path8.join)(home, ".codex", "skills"));
20382
20899
  return Array.from(new Set(roots));
20383
20900
  }
20384
20901
  function resolveSkillInvocation(text, cwd) {
20385
20902
  const parsed = parseSkillInvocation(text);
20386
20903
  if (!parsed) return null;
20387
20904
  for (const root of candidateRoots(cwd)) {
20388
- const skillPath = (0, import_path7.join)(root, parsed.command, "SKILL.md");
20389
- if (!(0, import_fs7.existsSync)(skillPath)) continue;
20905
+ const skillPath = (0, import_path8.join)(root, parsed.command, "SKILL.md");
20906
+ if (!(0, import_fs8.existsSync)(skillPath)) continue;
20390
20907
  let content;
20391
20908
  try {
20392
- content = (0, import_fs7.readFileSync)(skillPath, "utf-8");
20909
+ content = (0, import_fs8.readFileSync)(skillPath, "utf-8");
20393
20910
  } catch {
20394
20911
  continue;
20395
20912
  }
@@ -20986,14 +21503,14 @@ function normalizePath(candidate, cwd) {
20986
21503
  } catch {
20987
21504
  }
20988
21505
  if (path.startsWith("~/")) return null;
20989
- if ((0, import_path8.isAbsolute)(path)) return path;
20990
- return cwd ? (0, import_path8.join)(cwd, path) : null;
21506
+ if ((0, import_path9.isAbsolute)(path)) return path;
21507
+ return cwd ? (0, import_path9.join)(cwd, path) : null;
20991
21508
  }
20992
21509
  function resolveToolCwd(cwd, toolInput) {
20993
21510
  if (!isRecord(toolInput)) return cwd;
20994
21511
  const raw = typeof toolInput.cwd === "string" ? toolInput.cwd : typeof toolInput.workdir === "string" ? toolInput.workdir : typeof toolInput.workingDirectory === "string" ? toolInput.workingDirectory : null;
20995
21512
  if (!raw) return cwd;
20996
- return (0, import_path8.isAbsolute)(raw) || !cwd ? raw : (0, import_path8.join)(cwd, raw);
21513
+ return (0, import_path9.isAbsolute)(raw) || !cwd ? raw : (0, import_path9.join)(cwd, raw);
20997
21514
  }
20998
21515
  function extractBrowserMediaPathHints(content, cwd, toolName, options = {}, kind = "video") {
20999
21516
  if (!isAgentBrowserMediaInvocation(toolName, content, options.toolInput, kind)) return [];
@@ -21036,19 +21553,19 @@ function extractGeneratedImagesFromToolResult(toolId, content, cwd, toolName, op
21036
21553
  const effectiveCwd = resolveToolCwd(cwd, options.toolInput);
21037
21554
  for (const candidate of extractPathCandidates(content, options)) {
21038
21555
  const path = normalizePath(candidate, effectiveCwd);
21039
- if (!path || seen.has(path) || !(0, import_fs8.existsSync)(path)) continue;
21556
+ if (!path || seen.has(path) || !(0, import_fs9.existsSync)(path)) continue;
21040
21557
  seen.add(path);
21041
- const ext = (0, import_path8.extname)(path).toLowerCase();
21558
+ const ext = (0, import_path9.extname)(path).toLowerCase();
21042
21559
  const mimeType = IMAGE_MIME_BY_EXT[ext];
21043
21560
  if (!mimeType) continue;
21044
- const stat = (0, import_fs8.statSync)(path);
21561
+ const stat = (0, import_fs9.statSync)(path);
21045
21562
  if (!stat.isFile() || stat.size <= 0 || stat.size > MAX_GENERATED_IMAGE_BYTES) continue;
21046
- const buffer = (0, import_fs8.readFileSync)(path);
21563
+ const buffer = (0, import_fs9.readFileSync)(path);
21047
21564
  const { width, height } = readImageDimensions2(buffer, mimeType);
21048
21565
  images.push({
21049
21566
  type: "generated_image",
21050
21567
  id: (0, import_crypto3.randomUUID)(),
21051
- filename: (0, import_path8.basename)(path),
21568
+ filename: (0, import_path9.basename)(path),
21052
21569
  mimeType,
21053
21570
  size: buffer.length,
21054
21571
  width,
@@ -21075,20 +21592,20 @@ function extractSessionMediaFromToolResult(toolId, content, cwd, toolName, optio
21075
21592
  const mimeByExt = kind === "video" ? VIDEO_MIME_BY_EXT : IMAGE_MIME_BY_EXT;
21076
21593
  for (const candidate of extractPathCandidates(content, options, extensionsPattern)) {
21077
21594
  const path = normalizePath(candidate, effectiveCwd);
21078
- if (!path || seen.has(path) || !(0, import_fs8.existsSync)(path)) continue;
21595
+ if (!path || seen.has(path) || !(0, import_fs9.existsSync)(path)) continue;
21079
21596
  seen.add(path);
21080
- const ext = (0, import_path8.extname)(path).toLowerCase();
21597
+ const ext = (0, import_path9.extname)(path).toLowerCase();
21081
21598
  const mimeType = mimeByExt[ext];
21082
21599
  if (!mimeType) continue;
21083
- const stat = (0, import_fs8.statSync)(path);
21600
+ const stat = (0, import_fs9.statSync)(path);
21084
21601
  if (!stat.isFile() || stat.size <= 0 || stat.size > maxBytes) continue;
21085
- const buffer = (0, import_fs8.readFileSync)(path);
21602
+ const buffer = (0, import_fs9.readFileSync)(path);
21086
21603
  const dimensions = kind === "image" ? readImageDimensions2(buffer, mimeType) : null;
21087
21604
  media.push({
21088
21605
  type: "session_media",
21089
21606
  kind,
21090
21607
  id: (0, import_crypto3.randomUUID)(),
21091
- filename: (0, import_path8.basename)(path),
21608
+ filename: (0, import_path9.basename)(path),
21092
21609
  mimeType,
21093
21610
  size: buffer.length,
21094
21611
  width: dimensions?.width,
@@ -23667,7 +24184,7 @@ var RunStartGate = class {
23667
24184
  };
23668
24185
 
23669
24186
  // src/version.ts
23670
- var AGENT_VERSION = "0.1.45";
24187
+ var AGENT_VERSION = "0.1.46";
23671
24188
 
23672
24189
  // src/workspace-relocation.ts
23673
24190
  var import_node_child_process3 = require("child_process");
@@ -25380,11 +25897,21 @@ var RuntimePresenter = class {
25380
25897
  onNotice(kind, message) {
25381
25898
  this.emitEvent({ type: "session_notice", kind, message, ts: Date.now() });
25382
25899
  }
25383
- onAssistantText(text) {
25384
- this.emitEvent({ type: "text", text, ts: Date.now() });
25900
+ onAssistantText(text, parentToolUseId) {
25901
+ this.emitEvent({
25902
+ type: "text",
25903
+ text,
25904
+ ts: Date.now(),
25905
+ ...parentToolUseId ? { parentToolUseId } : {}
25906
+ });
25385
25907
  }
25386
- onThinking(text) {
25387
- this.emitEvent({ type: "thinking", text, ts: Date.now() });
25908
+ onThinking(text, parentToolUseId) {
25909
+ this.emitEvent({
25910
+ type: "thinking",
25911
+ text,
25912
+ ts: Date.now(),
25913
+ ...parentToolUseId ? { parentToolUseId } : {}
25914
+ });
25388
25915
  }
25389
25916
  onToolUse(tool, input, toolId, parentToolUseId) {
25390
25917
  if (this.verifyWorkspaceLease && !this.verifyWorkspaceLease()) return;
@@ -27488,11 +28015,21 @@ var WebPresenter = class {
27488
28015
  onNotice(kind, message) {
27489
28016
  this.wsClient.emitEvent({ type: "session_notice", kind, message, ts: Date.now() });
27490
28017
  }
27491
- onAssistantText(text) {
27492
- this.wsClient.emitEvent({ type: "text", text, ts: Date.now() });
28018
+ onAssistantText(text, parentToolUseId) {
28019
+ this.wsClient.emitEvent({
28020
+ type: "text",
28021
+ text,
28022
+ ts: Date.now(),
28023
+ ...parentToolUseId ? { parentToolUseId } : {}
28024
+ });
27493
28025
  }
27494
- onThinking(text) {
27495
- this.wsClient.emitEvent({ type: "thinking", text, ts: Date.now() });
28026
+ onThinking(text, parentToolUseId) {
28027
+ this.wsClient.emitEvent({
28028
+ type: "thinking",
28029
+ text,
28030
+ ts: Date.now(),
28031
+ ...parentToolUseId ? { parentToolUseId } : {}
28032
+ });
27496
28033
  }
27497
28034
  hasKnownToolUse(toolId) {
27498
28035
  return this.toolNamesById.has(toolId);