@oxgeneral/orch 0.3.4 → 1.0.1

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 (57) hide show
  1. package/dist/{App-RKAPZNZO.js → App-GJVTVGRU.js} +55 -20
  2. package/dist/{agent-KBTLGGCT.js → agent-7ZJ3ZDJ7.js} +1 -1
  3. package/dist/{chunk-D6RFF3KN.js → chunk-4IFIOMCW.js} +4 -3
  4. package/dist/{chunk-S3QYSBW4.js → chunk-C6XZ3FJT.js} +6 -3
  5. package/dist/chunk-C6XZ3FJT.js.map +1 -0
  6. package/dist/{chunk-W6RSVMXR.js → chunk-MGGSRXWJ.js} +5 -2
  7. package/dist/{chunk-VMDQVRBR.js → chunk-O2OQCSBL.js} +40 -16
  8. package/dist/chunk-O2OQCSBL.js.map +1 -0
  9. package/dist/{chunk-B4JQM4NU.js → chunk-VG4465AG.js} +119 -45
  10. package/dist/chunk-VG4465AG.js.map +1 -0
  11. package/dist/{chunk-A36WAF2S.js → chunk-VXS2CJFH.js} +117 -43
  12. package/dist/{chunk-52BFUGDD.js → chunk-XJTJ2TJV.js} +3 -2
  13. package/dist/{claude-INM52PTH.js → claude-WUJU5KIE.js} +6 -5
  14. package/dist/claude-WUJU5KIE.js.map +1 -0
  15. package/dist/claude-ZUEKJJ4X.js +5 -0
  16. package/dist/cli.js +10 -10
  17. package/dist/{codex-DIXT44JR.js → codex-7IXXXG5U.js} +3 -3
  18. package/dist/{codex-QGH2GRV6.js → codex-NYJWEPRQ.js} +4 -4
  19. package/dist/codex-NYJWEPRQ.js.map +1 -0
  20. package/dist/{container-LJU4QNDH.js → container-RY54L3XC.js} +12 -10
  21. package/dist/{cursor-KQJTQ73D.js → cursor-3YHVD4NP.js} +4 -4
  22. package/dist/cursor-3YHVD4NP.js.map +1 -0
  23. package/dist/{cursor-C3TR2IJC.js → cursor-622RBRHH.js} +3 -3
  24. package/dist/{doctor-V2FPS236.js → doctor-XSGQSD57.js} +5 -5
  25. package/dist/index.d.ts +4 -1
  26. package/dist/index.js +15 -13
  27. package/dist/index.js.map +1 -1
  28. package/dist/{init-U7MCIOB2.js → init-45BEMVL6.js} +38 -4
  29. package/dist/opencode-FAMPSA6X.js +100 -0
  30. package/dist/opencode-FAMPSA6X.js.map +1 -0
  31. package/dist/opencode-WOR53TSC.js +98 -0
  32. package/dist/{orchestrator-E3FQ4SOE.js → orchestrator-O6MFMATT.js} +38 -14
  33. package/dist/orchestrator-X2CWGFCL.js +5 -0
  34. package/dist/{orchestrator-ADO66XZ3.js.map → orchestrator-X2CWGFCL.js.map} +1 -1
  35. package/dist/shell-DVFHHYAZ.js +5 -0
  36. package/dist/{shell-JXOPKDXH.js → shell-NJNW3O6K.js} +5 -3
  37. package/dist/shell-NJNW3O6K.js.map +1 -0
  38. package/dist/{task-2TJW6Z7O.js → task-5EL2RNGW.js} +1 -1
  39. package/dist/template-engine-5ZKVJMYA.js +3 -0
  40. package/dist/{template-engine-MFL5B677.js.map → template-engine-5ZKVJMYA.js.map} +1 -1
  41. package/dist/template-engine-AWIS56BL.js +3 -0
  42. package/dist/{tui-IM3YUUVD.js → tui-LN5XHSQY.js} +1 -1
  43. package/package.json +14 -10
  44. package/readme.md +208 -152
  45. package/scripts/load-test.ts +478 -0
  46. package/dist/chunk-B4JQM4NU.js.map +0 -1
  47. package/dist/chunk-S3QYSBW4.js.map +0 -1
  48. package/dist/chunk-VMDQVRBR.js.map +0 -1
  49. package/dist/claude-INM52PTH.js.map +0 -1
  50. package/dist/claude-NHUNA5RZ.js +0 -5
  51. package/dist/codex-QGH2GRV6.js.map +0 -1
  52. package/dist/cursor-KQJTQ73D.js.map +0 -1
  53. package/dist/orchestrator-ADO66XZ3.js +0 -5
  54. package/dist/shell-3S4VLYEG.js +0 -4
  55. package/dist/shell-JXOPKDXH.js.map +0 -1
  56. package/dist/template-engine-4IZKRRHG.js +0 -3
  57. package/dist/template-engine-MFL5B677.js +0 -3
@@ -38,6 +38,74 @@ var LiquidTemplateEngine = class {
38
38
  }
39
39
  }
40
40
  };
41
+ var MAX_CONTEXT_ENTRIES = 15;
42
+ function filterRelevantContext(allContext, filter) {
43
+ const entries = Object.entries(allContext);
44
+ if (entries.length === 0) return {};
45
+ const agentLower = filter.agentName.toLowerCase();
46
+ const roleKeywords = extractRoleKeywords(agentLower, filter.agentRole);
47
+ const scored = [];
48
+ for (const [key, value] of entries) {
49
+ let score = 0;
50
+ const keyLower = key.toLowerCase();
51
+ if (filter.goalId && keyLower.startsWith(filter.goalId.toLowerCase())) {
52
+ score += 10;
53
+ }
54
+ if (keyLower.includes(agentLower) || value.toLowerCase().includes(agentLower)) {
55
+ score += 8;
56
+ }
57
+ if (filter.taskScope?.length) {
58
+ for (const scopePattern of filter.taskScope) {
59
+ const scopeBase = scopePattern.replace(/\*+/g, "").replace(/\/+$/, "");
60
+ if (scopeBase && (keyLower.includes(scopeBase.toLowerCase()) || value.toLowerCase().includes(scopeBase.toLowerCase()))) {
61
+ score += 6;
62
+ break;
63
+ }
64
+ }
65
+ }
66
+ for (const kw of roleKeywords) {
67
+ if (keyLower.startsWith(kw + "-") || keyLower.startsWith(kw + "_")) {
68
+ score += 4;
69
+ break;
70
+ }
71
+ }
72
+ if (/^(bug|perf|stability|docs|arch|spec)-/i.test(key)) {
73
+ score += 1;
74
+ }
75
+ scored.push({ key, value, score });
76
+ }
77
+ scored.sort((a, b) => b.score - a.score);
78
+ const relevant = scored.filter((e) => e.score > 0).slice(0, MAX_CONTEXT_ENTRIES);
79
+ if (relevant.length < MAX_CONTEXT_ENTRIES) {
80
+ const remaining = scored.filter((e) => e.score === 0).slice(0, MAX_CONTEXT_ENTRIES - relevant.length);
81
+ relevant.push(...remaining);
82
+ }
83
+ const result = {};
84
+ for (const { key, value } of relevant) {
85
+ result[key] = value;
86
+ }
87
+ return result;
88
+ }
89
+ function extractRoleKeywords(agentNameLower, role) {
90
+ const keywords = [];
91
+ const firstWord = agentNameLower.split(/[\s_-]/)[0];
92
+ if (firstWord && firstWord.length > 1) {
93
+ keywords.push(firstWord);
94
+ }
95
+ if (agentNameLower.includes("front") || agentNameLower.includes("tui")) {
96
+ keywords.push("front-end", "frontend", "tui");
97
+ }
98
+ if (agentNameLower.includes("market") || agentNameLower.includes("cmo")) {
99
+ keywords.push("marketer", "marketing", "cmo");
100
+ }
101
+ if (role) {
102
+ const roleFirstWord = role.toLowerCase().split(/[\s_-]/)[0];
103
+ if (roleFirstWord && roleFirstWord.length > 2 && !keywords.includes(roleFirstWord)) {
104
+ keywords.push(roleFirstWord);
105
+ }
106
+ }
107
+ return keywords;
108
+ }
41
109
  function buildPromptContext(task, agent, attempt, workspacePath, config, options) {
42
110
  const { allAgents, retryContext, sharedContext, feedback, messages: rawMessages, goal } = options ?? {};
43
111
  const agentById = new Map((allAgents ?? []).map((a) => [a.id, a]));
@@ -72,21 +140,64 @@ function buildPromptContext(task, agent, attempt, workspacePath, config, options
72
140
  agents: (allAgents ?? []).map((a) => ({
73
141
  id: a.id,
74
142
  name: a.name,
75
- role: a.role,
143
+ role: a.id === agent.id ? void 0 : a.role,
76
144
  adapter: a.adapter
77
145
  })),
78
146
  attempt: attempt > 1 ? attempt : null,
79
147
  workspace_path: workspacePath,
80
148
  retry: attempt > 1 ? retryContext : void 0,
81
149
  feedback,
82
- shared_context: sharedContext && Object.keys(sharedContext).length > 0 ? sharedContext : void 0,
150
+ shared_context: sharedContext && Object.keys(sharedContext).length > 0 ? filterRelevantContext(sharedContext, {
151
+ agentName: agent.name,
152
+ agentRole: agent.role,
153
+ goalId: task.goalId,
154
+ taskScope: task.scope
155
+ }) : void 0,
83
156
  messages,
84
157
  goal
85
158
  };
86
159
  }
87
- var DEFAULT_PROMPT_TEMPLATE = `You are {{ agent.name }}{% if agent.role %} ({{ agent.role }}){% endif %}.
160
+ var DEFAULT_SYSTEM_TEMPLATE = `You are {{ agent.name }}{% if agent.role %} ({{ agent.role }}){% endif %}.
161
+
162
+ ## Orchestrator CLI
163
+ Manage tasks and coordinate with other agents using \`orch\`:
164
+
165
+ **Tasks:**
166
+ - \`orch task add "<title>" -d "<description>" -p <1-4> --assignee <agent-id>\` \u2014 create and assign a task
167
+ - \`orch task add "<title>" -d "<description>" --scope "src/path/**" --depends-on <task-id>\` \u2014 scoped task with dependency
168
+ - \`orch task list [--status todo|in_progress|done|failed]\` \u2014 list tasks
169
+
170
+ **Messaging:**
171
+ - \`orch msg send <agent-id> "<body>" -s "<subject>"\` \u2014 direct message
172
+ - \`orch msg broadcast "<body>" -s "<subject>"\` \u2014 broadcast to all
173
+ - \`orch msg inbox {{ agent.id }}\` \u2014 your pending messages
174
+
175
+ **Shared context:**
176
+ - \`orch context set <key> <value>\` / \`orch context get <key>\` / \`orch context list\`
177
+
178
+ {% if task.is_autonomous %}
179
+ ## Autonomous Goal Mode
180
+ This is an autonomous task driven by a goal. Work in a continuous loop until the goal is achieved:
181
+
182
+ 1. **Understand the goal** \u2014 read the Goal section above.
183
+ 2. **Decompose** \u2014 break the goal into concrete subtasks via \`orch task add\`. {% if task.goal_id %}Pass \`--goal-id {{ task.goal_id }}\` so subtasks are linked to this goal. {% endif %}Assign yourself for your specialty, delegate other work to appropriate teammates by role.
184
+ 3. **Execute** \u2014 follow your standard workflow for each subtask.
185
+ 4. **Track progress** \u2014 after each iteration: \`orch context set {{ task.goal_id | default: "<goal>" }}-progress "<summary of what's done and what remains>"\`.
186
+ 5. **Be proactive** \u2014 do NOT wait for tasks from others. Create your own subtasks and keep working.
187
+ 6. **Do NOT finish** the [auto] task until the goal is achieved \u2014 keep creating subtasks.
188
+ 7. **When done** \u2014 mark the goal as achieved: \`orch goal status {{ task.goal_id | default: "<goal-id>" }} achieved\`.
189
+
190
+ **Deep inspection:** Use \`orch goal show {{ task.goal_id | default: "<goal-id>" }}\` to see full goal details at any time.
191
+ {% endif %}
88
192
 
89
- ## Task: {{ task.title }}
193
+ ## Rules
194
+ - Do NOT ask clarifying questions. You are running autonomously without human input.
195
+ - Make reasonable assumptions and proceed with the best approach.
196
+ - If critical information is missing, document your assumptions and continue.
197
+ - When a task is too large or spans multiple domains, break it into subtasks using \`orch task add\`.
198
+ - When creating subtasks, use \`--scope\` to declare which files each task will touch, and \`--depends-on\` to order dependent work.
199
+ `;
200
+ var DEFAULT_USER_TEMPLATE = `## Task: {{ task.title }}
90
201
  {{ task.description }}
91
202
 
92
203
  Priority: {{ task.priority }}
@@ -139,22 +250,6 @@ Other agents have shared the following information:
139
250
  {% endfor %}
140
251
  {% endif %}
141
252
 
142
- ## Orchestrator CLI
143
- Manage tasks and coordinate with other agents using \`orch\`:
144
-
145
- **Tasks:**
146
- - \`orch task add "<title>" -d "<description>" -p <1-4> --assignee <agent-id>\` \u2014 create and assign a task
147
- - \`orch task add "<title>" -d "<description>" --scope "src/path/**" --depends-on <task-id>\` \u2014 scoped task with dependency
148
- - \`orch task list [--status todo|in_progress|done|failed]\` \u2014 list tasks
149
-
150
- **Messaging:**
151
- - \`orch msg send <agent-id> "<body>" -s "<subject>"\` \u2014 direct message
152
- - \`orch msg broadcast "<body>" -s "<subject>"\` \u2014 broadcast to all
153
- - \`orch msg inbox {{ agent.id }}\` \u2014 your pending messages
154
-
155
- **Shared context:**
156
- - \`orch context set <key> <value>\` / \`orch context get <key>\` / \`orch context list\`
157
-
158
253
  {% if goal %}
159
254
  ## Goal: {{ goal.title }}
160
255
  **Status:** {{ goal.status }} \xB7 **ID:** \`{{ goal.id }}\`
@@ -172,28 +267,7 @@ Use \`orch task list --goal-id {{ goal.id }}\` and \`orch task show <id>\` to in
172
267
  {{ goal.progress }}
173
268
  {% endif %}
174
269
  {% endif %}
175
-
176
- {% if task.is_autonomous %}
177
- ## Autonomous Goal Mode
178
- This is an autonomous task driven by a goal. Work in a continuous loop until the goal is achieved:
179
-
180
- 1. **Understand the goal** \u2014 read the Goal section above.
181
- 2. **Decompose** \u2014 break the goal into concrete subtasks via \`orch task add\`. {% if task.goal_id %}Pass \`--goal-id {{ task.goal_id }}\` so subtasks are linked to this goal. {% endif %}Assign yourself for your specialty, delegate other work to appropriate teammates by role.
182
- 3. **Execute** \u2014 follow your standard workflow for each subtask.
183
- 4. **Track progress** \u2014 after each iteration: \`orch context set {{ task.goal_id | default: "<goal>" }}-progress "<summary of what's done and what remains>"\`.
184
- 5. **Be proactive** \u2014 do NOT wait for tasks from others. Create your own subtasks and keep working.
185
- 6. **Do NOT finish** the [auto] task until the goal is achieved \u2014 keep creating subtasks.
186
- 7. **When done** \u2014 mark the goal as achieved: \`orch goal status {{ task.goal_id | default: "<goal-id>" }} achieved\`.
187
-
188
- **Deep inspection:** Use \`orch goal show {{ task.goal_id | default: "<goal-id>" }}\` to see full goal details at any time.
189
- {% endif %}
190
-
191
- ## Rules
192
- - Do NOT ask clarifying questions. You are running autonomously without human input.
193
- - Make reasonable assumptions and proceed with the best approach.
194
- - If critical information is missing, document your assumptions and continue.
195
- - When a task is too large or spans multiple domains, break it into subtasks using \`orch task add\`.
196
- - When creating subtasks, use \`--scope\` to declare which files each task will touch, and \`--depends-on\` to order dependent work.
197
270
  `;
271
+ var DEFAULT_PROMPT_TEMPLATE = DEFAULT_SYSTEM_TEMPLATE + "\n" + DEFAULT_USER_TEMPLATE;
198
272
 
199
- export { DEFAULT_PROMPT_TEMPLATE, LiquidTemplateEngine, buildPromptContext };
273
+ export { DEFAULT_PROMPT_TEMPLATE, DEFAULT_SYSTEM_TEMPLATE, DEFAULT_USER_TEMPLATE, LiquidTemplateEngine, buildPromptContext, filterRelevantContext };
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { readLines } from './chunk-CHIP7O6V.js';
2
+ import { buildFullPrompt } from './chunk-MGGSRXWJ.js';
3
3
  import { classifyAdapterError } from './chunk-2C2TFQ7K.js';
4
+ import { readLines } from './chunk-CHIP7O6V.js';
4
5
  import { execFile } from 'child_process';
5
6
  import { promisify } from 'util';
6
7
 
@@ -145,7 +146,7 @@ var ShellAdapter = class {
145
146
  env: {
146
147
  ...process.env,
147
148
  ...params.env,
148
- ORCHESTRY_TASK_PROMPT: params.prompt
149
+ ORCHESTRY_TASK_PROMPT: buildFullPrompt(params.systemPrompt, params.prompt)
149
150
  },
150
151
  signal: params.signal
151
152
  });
@@ -1,4 +1,4 @@
1
- import { createStreamingEvents, extractTokens } from './chunk-S3QYSBW4.js';
1
+ import { createStreamingEvents, extractTokens } from './chunk-C6XZ3FJT.js';
2
2
  import './chunk-XDVMX2FO.js';
3
3
  import { classifyAdapterError } from './chunk-NLQAJ7TW.js';
4
4
  import './chunk-O2MSGW3V.js';
@@ -38,8 +38,9 @@ var ClaudeAdapter = class {
38
38
  if (params.config.model) {
39
39
  args.push("--model", params.config.model);
40
40
  }
41
- if (params.config.system_prompt) {
42
- args.push("--system-prompt", params.config.system_prompt);
41
+ const effectiveSystemPrompt = params.systemPrompt ?? params.config.system_prompt;
42
+ if (effectiveSystemPrompt) {
43
+ args.push("--system-prompt", effectiveSystemPrompt);
43
44
  }
44
45
  args.push(params.prompt);
45
46
  const { process: proc, pid } = this.processManager.spawn("claude", args, {
@@ -84,5 +85,5 @@ function parseClaudeEvent(line) {
84
85
  }
85
86
 
86
87
  export { ClaudeAdapter };
87
- //# sourceMappingURL=claude-INM52PTH.js.map
88
- //# sourceMappingURL=claude-INM52PTH.js.map
88
+ //# sourceMappingURL=claude-WUJU5KIE.js.map
89
+ //# sourceMappingURL=claude-WUJU5KIE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/infrastructure/adapters/claude.ts"],"names":[],"mappings":";;;;;;;AAcA,IAAM,aAAA,GAAgB,UAAU,QAAQ,CAAA;AAEjC,IAAM,gBAAN,MAA6C;AAAA,EAGlD,YAA6B,cAAA,EAAiC;AAAjC,IAAA,IAAA,CAAA,cAAA,GAAA,cAAA;AAAA,EAAkC;AAAA,EAFtD,IAAA,GAAO,QAAA;AAAA,EAIhB,MAAM,IAAA,GAAmC;AACvC,IAAA,IAAI;AACF,MAAA,MAAM,EAAE,QAAO,GAAI,MAAM,cAAc,QAAA,EAAU,CAAC,WAAW,CAAC,CAAA;AAC9D,MAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,OAAA,EAAS,MAAA,CAAO,MAAK,EAAE;AAAA,IAC5C,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,MAAM,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC3D,MAAA,OAAO;AAAA,QACL,EAAA,EAAI,KAAA;AAAA,QACJ,KAAA,EAAO,wEAAA;AAAA,QACP,SAAA,EAAW,qBAAqB,GAAG;AAAA,OACrC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,QAAQ,MAAA,EAAsC;AAC5C,IAAA,MAAM,IAAA,GAAO;AAAA,MACX,SAAA;AAAA,MACA,iBAAA;AAAA,MAAmB,aAAA;AAAA,MACnB,aAAA;AAAA,MAAe,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,SAAA,IAAa,EAAE,CAAA;AAAA,MACnD,WAAA;AAAA,MACA;AAAA;AAAA,KACF;AAEA,IAAA,IAAI,MAAA,CAAO,OAAO,KAAA,EAAO;AACvB,MAAA,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,MAAA,CAAO,MAAA,CAAO,KAAK,CAAA;AAAA,IAC1C;AAGA,IAAA,MAAM,qBAAA,GAAwB,MAAA,CAAO,YAAA,IAAgB,MAAA,CAAO,MAAA,CAAO,aAAA;AACnE,IAAA,IAAI,qBAAA,EAAuB;AACzB,MAAA,IAAA,CAAK,IAAA,CAAK,mBAAmB,qBAAqB,CAAA;AAAA,IACpD;AAEA,IAAA,IAAA,CAAK,IAAA,CAAK,OAAO,MAAM,CAAA;AAEvB,IAAA,MAAM,EAAE,SAAS,IAAA,EAAM,GAAA,KAAQ,IAAA,CAAK,cAAA,CAAe,KAAA,CAAM,QAAA,EAAU,IAAA,EAAM;AAAA,MACvE,KAAK,MAAA,CAAO,SAAA;AAAA,MACZ,KAAK,EAAE,GAAG,QAAQ,GAAA,EAAK,GAAG,OAAO,GAAA,EAAI;AAAA,MACrC,QAAQ,MAAA,CAAO;AAAA,KAChB,CAAA;AAED,IAAA,MAAM,SAAS,qBAAA,CAAsB,IAAA,EAAM,gBAAA,EAAkB,QAAA,EAAU,OAAO,MAAM,CAAA;AAEpF,IAAA,OAAO,EAAE,KAAK,MAAA,EAAO;AAAA,EACvB;AAAA,EAEA,MAAM,KAAK,GAAA,EAA4B;AACrC,IAAA,MAAM,IAAA,CAAK,cAAA,CAAe,aAAA,CAAc,GAAG,CAAA;AAAA,EAC7C;AACF;AAEA,SAAS,iBAAiB,IAAA,EAAiC;AACzD,EAAA,IAAI,CAAC,IAAA,CAAK,IAAA,EAAK,EAAG,OAAO,IAAA;AAEzB,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAkC,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AACvD,IAAA,MAAM,SAAA,GAAA,iBAAY,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAEzC,IAAA,QAAQ,OAAO,IAAA;AAAM,MACnB,KAAK,WAAA;AACH,QAAA,OAAO,EAAE,IAAA,EAAM,QAAA,EAAU,WAAW,IAAA,EAAO,MAAA,CAAO,WAAuB,MAAA,EAAO;AAAA,MAClF,KAAK,UAAA;AACH,QAAA,OAAO,EAAE,IAAA,EAAM,WAAA,EAAa,SAAA,EAAW,MAAM,MAAA,EAAO;AAAA,MACtD,KAAK,aAAA;AACH,QAAA,OAAO,EAAE,IAAA,EAAM,QAAA,EAAU,SAAA,EAAW,MAAM,MAAA,EAAO;AAAA,MACnD,KAAK,OAAA,EAAS;AACZ,QAAA,MAAM,OAAA,GAAW,OAAO,KAAA,IAAqB,MAAA;AAC7C,QAAA,MAAM,SAAS,OAAO,OAAA,KAAY,WAAW,OAAA,GAAU,IAAA,CAAK,UAAU,OAAO,CAAA;AAC7E,QAAA,OAAO,EAAE,MAAM,OAAA,EAAS,SAAA,EAAW,MAAM,OAAA,EAAS,SAAA,EAAW,oBAAA,CAAqB,MAAM,CAAA,EAAE;AAAA,MAC5F;AAAA,MACA,KAAK,QAAA,EAAU;AACb,QAAA,MAAM,SAAS,aAAA,CAAc,MAAA,EAAQ,EAAE,aAAA,EAAe,MAAM,CAAA;AAC5D,QAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,SAAA,EAAW,IAAA,EAAM,QAAQ,MAAA,EAAO;AAAA,MACzD;AAAA,MACA;AACE,QAAA,OAAO,EAAE,IAAA,EAAM,QAAA,EAAU,SAAA,EAAW,MAAM,MAAA,EAAO;AAAA;AACrD,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,IAAA,EAAM,QAAA,EAAU,SAAA,EAAA,iBAAW,IAAI,MAAK,EAAE,WAAA,EAAY,EAAG,IAAA,EAAM,IAAA,EAAK;AAAA,EAC3E;AACF","file":"claude-WUJU5KIE.js","sourcesContent":["/**\n * Claude Code adapter.\n *\n * Spawns `claude --print --output-format stream-json` in headless mode.\n * Parses JSON-lines from stdout into AgentEvent stream.\n */\n\nimport type { IAgentAdapter, AdapterTestResult, ExecuteParams, AgentEvent, ExecuteHandle } from './interface.js';\nimport type { IProcessManager } from '../process/process-manager.js';\nimport { extractTokens, createStreamingEvents } from './utils.js';\nimport { classifyAdapterError, AdapterErrorKind } from '../../domain/errors.js';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nconst execFileAsync = promisify(execFile);\n\nexport class ClaudeAdapter implements IAgentAdapter {\n readonly kind = 'claude';\n\n constructor(private readonly processManager: IProcessManager) {}\n\n async test(): Promise<AdapterTestResult> {\n try {\n const { stdout } = await execFileAsync('claude', ['--version']);\n return { ok: true, version: stdout.trim() };\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n ok: false,\n error: 'Claude Code CLI not found. Install: npm i -g @anthropic-ai/claude-code',\n errorKind: classifyAdapterError(msg),\n };\n }\n }\n\n execute(params: ExecuteParams): ExecuteHandle {\n const args = [\n '--print',\n '--output-format', 'stream-json',\n '--max-turns', String(params.config.max_turns ?? 50),\n '--verbose',\n '--dangerously-skip-permissions', // Agents run autonomously; stdin is 'ignore' so prompts would hang\n ];\n\n if (params.config.model) {\n args.push('--model', params.config.model);\n }\n\n // System prompt: orchestrator-generated (cacheable) takes priority, then per-agent config\n const effectiveSystemPrompt = params.systemPrompt ?? params.config.system_prompt;\n if (effectiveSystemPrompt) {\n args.push('--system-prompt', effectiveSystemPrompt);\n }\n\n args.push(params.prompt);\n\n const { process: proc, pid } = this.processManager.spawn('claude', args, {\n cwd: params.workspace,\n env: { ...process.env, ...params.env },\n signal: params.signal,\n });\n\n const events = createStreamingEvents(proc, parseClaudeEvent, 'Claude', params.signal);\n\n return { pid, events };\n }\n\n async stop(pid: number): Promise<void> {\n await this.processManager.killWithGrace(pid);\n }\n}\n\nfunction parseClaudeEvent(line: string): AgentEvent | null {\n if (!line.trim()) return null;\n\n try {\n const parsed: Record<string, unknown> = JSON.parse(line);\n const timestamp = new Date().toISOString();\n\n switch (parsed.type) {\n case 'assistant':\n return { type: 'output', timestamp, data: (parsed.message as unknown) ?? parsed };\n case 'tool_use':\n return { type: 'tool_call', timestamp, data: parsed };\n case 'tool_result':\n return { type: 'output', timestamp, data: parsed };\n case 'error': {\n const errData = (parsed.error as unknown) ?? parsed;\n const errMsg = typeof errData === 'string' ? errData : JSON.stringify(errData);\n return { type: 'error', timestamp, data: errData, errorKind: classifyAdapterError(errMsg) };\n }\n case 'result': {\n const tokens = extractTokens(parsed, { statsFallback: true });\n return { type: 'done', timestamp, data: parsed, tokens };\n }\n default:\n return { type: 'output', timestamp, data: parsed };\n }\n } catch {\n return { type: 'output', timestamp: new Date().toISOString(), data: line };\n }\n}\n"]}
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ export { ClaudeAdapter } from './chunk-4IFIOMCW.js';
3
+ import './chunk-MGGSRXWJ.js';
4
+ import './chunk-2C2TFQ7K.js';
5
+ import './chunk-CHIP7O6V.js';
package/dist/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { setAsciiMode, setNoColor, printError } from './chunk-7X2GI5OV.js';
3
2
  import { findProjectRoot } from './chunk-LV6GDBBI.js';
3
+ import { setAsciiMode, setNoColor, printError } from './chunk-7X2GI5OV.js';
4
4
  import { OrchestryError, NotInitializedError } from './chunk-2C2TFQ7K.js';
5
5
  import { Command } from 'commander';
6
6
 
@@ -20,11 +20,11 @@ function createContext(opts) {
20
20
  // src/bin/cli.ts
21
21
  var LIGHT_COMMANDS = {
22
22
  task: async (p, c) => {
23
- const m = await import('./task-2TJW6Z7O.js');
23
+ const m = await import('./task-5EL2RNGW.js');
24
24
  m.registerTaskCommand(p, c);
25
25
  },
26
26
  agent: async (p, c) => {
27
- const m = await import('./agent-KBTLGGCT.js');
27
+ const m = await import('./agent-7ZJ3ZDJ7.js');
28
28
  m.registerAgentCommand(p, c);
29
29
  },
30
30
  status: async (p, c) => {
@@ -62,16 +62,16 @@ var FULL_COMMANDS = {
62
62
  m.registerRunCommand(p, c);
63
63
  },
64
64
  doctor: async (p, c) => {
65
- const m = await import('./doctor-V2FPS236.js');
65
+ const m = await import('./doctor-XSGQSD57.js');
66
66
  m.registerDoctorCommand(p, c);
67
67
  },
68
68
  tui: async (p, c) => {
69
- const m = await import('./tui-IM3YUUVD.js');
69
+ const m = await import('./tui-LN5XHSQY.js');
70
70
  m.registerTuiCommand(p, c);
71
71
  }
72
72
  };
73
73
  var program = new Command();
74
- program.name("orchestry").description("Agents Organizations \u2014 CLI orchestrator for AI agents").version("0.3.4").option("--json", "Output as JSON").option("--quiet", "Minimal output (IDs only)").option("--no-color", "Disable colors").option("--ascii", "ASCII-only output (no Unicode)").hook("preAction", async (thisCommand) => {
74
+ program.name("orchestry").description("Agents Organizations \u2014 CLI orchestrator for AI agents").version("1.0.1").option("--json", "Output as JSON").option("--quiet", "Minimal output (IDs only)").option("--no-color", "Disable colors").option("--ascii", "ASCII-only output (no Unicode)").hook("preAction", async (thisCommand) => {
75
75
  const opts = thisCommand.opts();
76
76
  if (opts.ascii) setAsciiMode(true);
77
77
  if (opts.color === false) setNoColor(true);
@@ -113,14 +113,14 @@ async function main() {
113
113
  return;
114
114
  }
115
115
  if (sub === "init") {
116
- const { registerInitCommand } = await import('./init-U7MCIOB2.js');
116
+ const { registerInitCommand } = await import('./init-45BEMVL6.js');
117
117
  registerInitCommand(program);
118
118
  } else if (sub === "update") {
119
119
  const { registerUpdateCommand } = await import('./update-YLP7FPNY.js');
120
120
  registerUpdateCommand(program);
121
121
  }
122
122
  const needsFull = !sub || sub in FULL_COMMANDS;
123
- const { buildFullContainer, buildLightContainer } = await import('./container-LJU4QNDH.js');
123
+ const { buildFullContainer, buildLightContainer } = await import('./container-RY54L3XC.js');
124
124
  try {
125
125
  if (needsFull) {
126
126
  const container = await buildFullContainer(context);
@@ -150,11 +150,11 @@ async function main() {
150
150
  } catch (err) {
151
151
  if (err instanceof NotInitializedError) {
152
152
  if (sub === "doctor") {
153
- const { registerDoctorCommand } = await import('./doctor-V2FPS236.js');
153
+ const { registerDoctorCommand } = await import('./doctor-XSGQSD57.js');
154
154
  registerDoctorCommand(program);
155
155
  }
156
156
  if (process.argv.length <= 2) {
157
- const { runInit } = await import('./init-U7MCIOB2.js');
157
+ const { runInit } = await import('./init-45BEMVL6.js');
158
158
  await runInit();
159
159
  const freshContainer = await buildFullContainer(context);
160
160
  await FULL_COMMANDS["tui"](program, freshContainer);
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { createStreamingEvents, extractTokens } from './chunk-W6RSVMXR.js';
3
- import './chunk-CHIP7O6V.js';
2
+ import { buildFullPrompt, createStreamingEvents, extractTokens } from './chunk-MGGSRXWJ.js';
4
3
  import { classifyAdapterError } from './chunk-2C2TFQ7K.js';
4
+ import './chunk-CHIP7O6V.js';
5
5
  import { execFile } from 'child_process';
6
6
  import { promisify } from 'util';
7
7
 
@@ -44,7 +44,7 @@ var CodexAdapter = class {
44
44
  // stdin must be 'pipe' to send prompt
45
45
  });
46
46
  if (proc.stdin) {
47
- proc.stdin.write(params.prompt);
47
+ proc.stdin.write(buildFullPrompt(params.systemPrompt, params.prompt));
48
48
  proc.stdin.end();
49
49
  }
50
50
  const events = createStreamingEvents(proc, parseCodexEvent, "Codex", params.signal);
@@ -1,4 +1,4 @@
1
- import { createStreamingEvents, extractTokens } from './chunk-S3QYSBW4.js';
1
+ import { buildFullPrompt, createStreamingEvents, extractTokens } from './chunk-C6XZ3FJT.js';
2
2
  import './chunk-XDVMX2FO.js';
3
3
  import { classifyAdapterError } from './chunk-NLQAJ7TW.js';
4
4
  import './chunk-O2MSGW3V.js';
@@ -44,7 +44,7 @@ var CodexAdapter = class {
44
44
  // stdin must be 'pipe' to send prompt
45
45
  });
46
46
  if (proc.stdin) {
47
- proc.stdin.write(params.prompt);
47
+ proc.stdin.write(buildFullPrompt(params.systemPrompt, params.prompt));
48
48
  proc.stdin.end();
49
49
  }
50
50
  const events = createStreamingEvents(proc, parseCodexEvent, "Codex", params.signal);
@@ -121,5 +121,5 @@ function parseCodexEvent(line) {
121
121
  }
122
122
 
123
123
  export { CodexAdapter };
124
- //# sourceMappingURL=codex-QGH2GRV6.js.map
125
- //# sourceMappingURL=codex-QGH2GRV6.js.map
124
+ //# sourceMappingURL=codex-NYJWEPRQ.js.map
125
+ //# sourceMappingURL=codex-NYJWEPRQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/infrastructure/adapters/codex.ts"],"names":[],"mappings":"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","file":"codex-NYJWEPRQ.js","sourcesContent":["/**\n * Codex CLI adapter.\n *\n * Spawns `codex exec --json -` in headless mode.\n * Prompt is piped via stdin (avoids CLI arg length limits).\n * Parses JSONL events from stdout into AgentEvent stream.\n */\n\nimport type { IAgentAdapter, AdapterTestResult, ExecuteParams, AgentEvent, ExecuteHandle } from './interface.js';\nimport type { IProcessManager } from '../process/process-manager.js';\nimport { extractTokens, createStreamingEvents, buildFullPrompt } from './utils.js';\nimport { classifyAdapterError, AdapterErrorKind } from '../../domain/errors.js';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nconst execFileAsync = promisify(execFile);\n\nexport class CodexAdapter implements IAgentAdapter {\n readonly kind = 'codex';\n\n constructor(private readonly processManager: IProcessManager) {}\n\n async test(): Promise<AdapterTestResult> {\n try {\n const { stdout } = await execFileAsync('codex', ['--version']);\n return { ok: true, version: stdout.trim() };\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n ok: false,\n error: 'Codex CLI not found. Install: npm i -g @openai/codex',\n errorKind: classifyAdapterError(msg),\n };\n }\n }\n\n execute(params: ExecuteParams): ExecuteHandle {\n const args = [\n 'exec',\n '--json',\n '--sandbox', 'danger-full-access', // autonomous agents can't respond to approval prompts\n ];\n\n if (params.config.model) {\n args.push('--model', params.config.model);\n }\n\n // Read prompt from stdin (avoids ARG_MAX limits on long prompts)\n args.push('-');\n\n const { process: proc, pid } = this.processManager.spawn('codex', args, {\n cwd: params.workspace,\n env: { ...process.env, ...params.env },\n signal: params.signal,\n stdio: ['pipe', 'pipe', 'pipe'], // stdin must be 'pipe' to send prompt\n });\n\n // Pipe prompt via stdin — prepend system prompt if present (Codex has no native --system-prompt)\n if (proc.stdin) {\n proc.stdin.write(buildFullPrompt(params.systemPrompt, params.prompt));\n proc.stdin.end();\n }\n\n const events = createStreamingEvents(proc, parseCodexEvent, 'Codex', params.signal);\n\n return { pid, events };\n }\n\n async stop(pid: number): Promise<void> {\n await this.processManager.killWithGrace(pid);\n }\n}\n\nfunction parseCodexEvent(line: string): AgentEvent | null {\n if (!line.trim()) return null;\n\n try {\n const parsed: Record<string, unknown> = JSON.parse(line);\n const timestamp = new Date().toISOString();\n\n const type = (parsed.type as string) ?? '';\n\n // Codex JSONL event types\n switch (type) {\n // Thread/session started\n case 'thread.started':\n return { type: 'output', timestamp, data: parsed };\n\n // Turn lifecycle\n case 'turn.started':\n return { type: 'output', timestamp, data: parsed };\n\n case 'turn.completed': {\n const tokens = extractTokens(parsed);\n return { type: 'done', timestamp, data: parsed, tokens };\n }\n\n case 'turn.failed': {\n const tokens = extractTokens(parsed);\n const failMsg = typeof parsed.error === 'string' ? parsed.error : JSON.stringify(parsed);\n return { type: 'error', timestamp, data: parsed, tokens, errorKind: classifyAdapterError(failMsg) };\n }\n\n // Item events\n case 'item.started':\n case 'item.completed': {\n const item = (parsed.item as Record<string, unknown>) ?? {};\n const itemType = (item.type as string) ?? '';\n\n if (itemType === 'agent_message') {\n return { type: 'output', timestamp, data: item };\n }\n if (itemType === 'reasoning') {\n return { type: 'output', timestamp, data: item };\n }\n if (itemType === 'command_execution') {\n return { type: 'command', timestamp, data: item };\n }\n if (itemType === 'file_change') {\n const changes = Array.isArray(item.changes) ? item.changes : [];\n const paths = (changes as Record<string, unknown>[])\n .map((c) => typeof c.path === 'string' ? c.path : '')\n .filter(Boolean);\n return { type: 'file_change', timestamp, data: { paths, raw: item } };\n }\n if (itemType === 'tool_use') {\n return { type: 'tool_call', timestamp, data: item };\n }\n if (itemType === 'tool_result') {\n return { type: 'output', timestamp, data: item };\n }\n if (itemType === 'error') {\n const itemErrMsg = typeof item.message === 'string' ? item.message : JSON.stringify(item);\n return { type: 'error', timestamp, data: item, errorKind: classifyAdapterError(itemErrMsg) };\n }\n return { type: 'output', timestamp, data: item };\n }\n\n case 'error': {\n const errData = (parsed.error as unknown) ?? parsed;\n const errMsg = typeof errData === 'string' ? errData : JSON.stringify(errData);\n return { type: 'error', timestamp, data: errData, errorKind: classifyAdapterError(errMsg) };\n }\n\n default:\n return { type: 'output', timestamp, data: parsed };\n }\n } catch {\n return { type: 'output', timestamp: new Date().toISOString(), data: line };\n }\n}\n"]}
@@ -1055,16 +1055,15 @@ var RunService = class {
1055
1055
  * Get error and last N lines of output from the most recent failed run for a task.
1056
1056
  * Used to provide retry context so agents can learn from previous failures.
1057
1057
  */
1058
- async getLastFailedRunContext(taskId, maxOutputLines = 50) {
1058
+ async getLastFailedRunContext(taskId) {
1059
1059
  const runs = await this.runStore.listForTask(taskId);
1060
1060
  const failedRun = runs.filter((r) => r.status === "failed").sort((a, b) => (b.finished_at ?? "").localeCompare(a.finished_at ?? ""))[0];
1061
1061
  if (!failedRun) return null;
1062
1062
  const error = failedRun.error ?? "Unknown error";
1063
1063
  let output = "";
1064
1064
  try {
1065
- const events = await this.runStore.readEventsTail(failedRun.id, maxOutputLines * 2);
1066
- const outputLines = events.filter((e) => e.type === "agent_output" || e.type === "error").map((e) => typeof e.data === "string" ? e.data : JSON.stringify(e.data)).join("\n").split("\n");
1067
- output = outputLines.slice(-maxOutputLines).join("\n");
1065
+ const events = await this.runStore.readEventsTail(failedRun.id, 50);
1066
+ output = events.filter((e) => e.type === "agent_output" || e.type === "error").map((e) => typeof e.data === "string" ? e.data : JSON.stringify(e.data)).join("\n");
1068
1067
  } catch {
1069
1068
  }
1070
1069
  return { error, output };
@@ -1528,6 +1527,7 @@ async function buildFullContainer(context) {
1528
1527
  { CodexAdapter },
1529
1528
  { CursorAdapter },
1530
1529
  { ShellAdapter },
1530
+ { OpenCodeAdapter },
1531
1531
  { WorkspaceManager },
1532
1532
  { LiquidTemplateEngine },
1533
1533
  { Orchestrator },
@@ -1535,13 +1535,14 @@ async function buildFullContainer(context) {
1535
1535
  ] = await Promise.all([
1536
1536
  import('./process-manager-HUVNAPQV.js'),
1537
1537
  import('./registry-PQWRVNF2.js'),
1538
- import('./claude-NHUNA5RZ.js'),
1539
- import('./codex-DIXT44JR.js'),
1540
- import('./cursor-C3TR2IJC.js'),
1541
- import('./shell-3S4VLYEG.js'),
1538
+ import('./claude-ZUEKJJ4X.js'),
1539
+ import('./codex-7IXXXG5U.js'),
1540
+ import('./cursor-622RBRHH.js'),
1541
+ import('./shell-DVFHHYAZ.js'),
1542
+ import('./opencode-WOR53TSC.js'),
1542
1543
  import('./workspace-manager-JM6U7JOH.js'),
1543
- import('./template-engine-4IZKRRHG.js'),
1544
- import('./orchestrator-E3FQ4SOE.js'),
1544
+ import('./template-engine-AWIS56BL.js'),
1545
+ import('./orchestrator-O6MFMATT.js'),
1545
1546
  import('./doctor-service-TPOMFAIG.js')
1546
1547
  ]);
1547
1548
  const processManager = new ProcessManager();
@@ -1556,6 +1557,7 @@ async function buildFullContainer(context) {
1556
1557
  adapterRegistry.register(new CodexAdapter(processManager));
1557
1558
  adapterRegistry.register(new CursorAdapter(processManager));
1558
1559
  adapterRegistry.register(new ShellAdapter(processManager));
1560
+ adapterRegistry.register(new OpenCodeAdapter(processManager));
1559
1561
  const doctorService = new DoctorService(adapterRegistry, processManager, context.projectRoot);
1560
1562
  const orchestrator = new Orchestrator({
1561
1563
  taskStore: light.taskStore,
@@ -1,4 +1,4 @@
1
- import { createStreamingEvents, extractTokens } from './chunk-S3QYSBW4.js';
1
+ import { buildFullPrompt, createStreamingEvents, extractTokens } from './chunk-C6XZ3FJT.js';
2
2
  import './chunk-XDVMX2FO.js';
3
3
  import { classifyAdapterError } from './chunk-NLQAJ7TW.js';
4
4
  import './chunk-O2MSGW3V.js';
@@ -55,7 +55,7 @@ var CursorAdapter = class {
55
55
  // stdin must be 'pipe' to send prompt
56
56
  });
57
57
  if (proc.stdin) {
58
- proc.stdin.write(params.prompt);
58
+ proc.stdin.write(buildFullPrompt(params.systemPrompt, params.prompt));
59
59
  proc.stdin.end();
60
60
  }
61
61
  const events = createStreamingEvents(proc, parseCursorEvent, "Cursor agent", params.signal);
@@ -95,5 +95,5 @@ function parseCursorEvent(line) {
95
95
  }
96
96
 
97
97
  export { CursorAdapter };
98
- //# sourceMappingURL=cursor-KQJTQ73D.js.map
99
- //# sourceMappingURL=cursor-KQJTQ73D.js.map
98
+ //# sourceMappingURL=cursor-3YHVD4NP.js.map
99
+ //# sourceMappingURL=cursor-3YHVD4NP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/infrastructure/adapters/cursor.ts"],"names":[],"mappings":"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","file":"cursor-3YHVD4NP.js","sourcesContent":["/**\n * Cursor Agent adapter.\n *\n * Spawns `cursor-agent` (Cursor's headless agent CLI) with `--output-format stream-json`.\n * Falls back to `agent` command if `cursor-agent` is not found.\n * Parses JSON-lines from stdout into AgentEvent stream.\n *\n * Note: This requires Cursor Agent CLI, not the regular `cursor` IDE command.\n * Install via: npm i -g @anthropic-ai/cursor-agent (when available)\n */\n\nimport type { IAgentAdapter, AdapterTestResult, ExecuteParams, AgentEvent, ExecuteHandle } from './interface.js';\nimport type { IProcessManager } from '../process/process-manager.js';\nimport { extractTokens, createStreamingEvents, buildFullPrompt } from './utils.js';\nimport { classifyAdapterError, AdapterErrorKind } from '../../domain/errors.js';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nconst execFileAsync = promisify(execFile);\n\n/** Try multiple command names and return the first that works */\nasync function findCommand(): Promise<{ command: string; version: string } | null> {\n for (const cmd of ['cursor-agent', 'agent']) {\n try {\n const { stdout } = await execFileAsync(cmd, ['--version']);\n return { command: cmd, version: stdout.trim() };\n } catch {\n // try next\n }\n }\n return null;\n}\n\nexport class CursorAdapter implements IAgentAdapter {\n readonly kind = 'cursor';\n\n private resolvedCommand: string = 'cursor-agent';\n\n constructor(private readonly processManager: IProcessManager) {}\n\n async test(): Promise<AdapterTestResult> {\n const found = await findCommand();\n if (found) {\n this.resolvedCommand = found.command;\n return { ok: true, version: found.version };\n }\n return {\n ok: false,\n error: 'Cursor Agent CLI not found. The headless agent CLI is required (cursor-agent or agent).',\n errorKind: AdapterErrorKind.ADAPTER_NOT_FOUND,\n };\n }\n\n execute(params: ExecuteParams): ExecuteHandle {\n const args = [\n '-p',\n '--output-format', 'stream-json',\n '--workspace', params.workspace,\n '--yolo', // bypass interactive prompts for autonomous agents\n ];\n\n if (params.config.model) {\n args.push('--model', params.config.model);\n }\n\n const { process: proc, pid } = this.processManager.spawn(this.resolvedCommand, args, {\n cwd: params.workspace,\n env: { ...process.env, ...params.env },\n signal: params.signal,\n stdio: ['pipe', 'pipe', 'pipe'], // stdin must be 'pipe' to send prompt\n });\n\n // Pipe prompt via stdin — prepend system prompt if present (Cursor has no native --system-prompt)\n if (proc.stdin) {\n proc.stdin.write(buildFullPrompt(params.systemPrompt, params.prompt));\n proc.stdin.end();\n }\n\n const events = createStreamingEvents(proc, parseCursorEvent, 'Cursor agent', params.signal);\n\n return { pid, events };\n }\n\n async stop(pid: number): Promise<void> {\n await this.processManager.killWithGrace(pid);\n }\n}\n\nfunction parseCursorEvent(line: string): AgentEvent | null {\n if (!line.trim()) return null;\n\n try {\n const parsed: Record<string, unknown> = JSON.parse(line);\n const timestamp = new Date().toISOString();\n\n // Cursor stream-json uses the same format as Claude stream-json\n switch (parsed.type) {\n case 'assistant':\n return { type: 'output', timestamp, data: (parsed.message as unknown) ?? parsed };\n case 'tool_use':\n return { type: 'tool_call', timestamp, data: parsed };\n case 'tool_result':\n return { type: 'output', timestamp, data: parsed };\n case 'error': {\n const errData = (parsed.error as unknown) ?? parsed;\n const errMsg = typeof errData === 'string' ? errData : JSON.stringify(errData);\n return { type: 'error', timestamp, data: errData, errorKind: classifyAdapterError(errMsg) };\n }\n case 'result': {\n const tokens = extractTokens(parsed);\n return { type: 'done', timestamp, data: parsed, tokens };\n }\n default:\n return { type: 'output', timestamp, data: parsed };\n }\n } catch {\n return { type: 'output', timestamp: new Date().toISOString(), data: line };\n }\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { createStreamingEvents, extractTokens } from './chunk-W6RSVMXR.js';
3
- import './chunk-CHIP7O6V.js';
2
+ import { buildFullPrompt, createStreamingEvents, extractTokens } from './chunk-MGGSRXWJ.js';
4
3
  import { classifyAdapterError } from './chunk-2C2TFQ7K.js';
4
+ import './chunk-CHIP7O6V.js';
5
5
  import { execFile } from 'child_process';
6
6
  import { promisify } from 'util';
7
7
 
@@ -55,7 +55,7 @@ var CursorAdapter = class {
55
55
  // stdin must be 'pipe' to send prompt
56
56
  });
57
57
  if (proc.stdin) {
58
- proc.stdin.write(params.prompt);
58
+ proc.stdin.write(buildFullPrompt(params.systemPrompt, params.prompt));
59
59
  proc.stdin.end();
60
60
  }
61
61
  const events = createStreamingEvents(proc, parseCursorEvent, "Cursor agent", params.signal);
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import { DoctorService } from './chunk-K6DMQERQ.js';
3
+ import { Paths } from './chunk-LV6GDBBI.js';
3
4
  import { amber, getIcon, dim } from './chunk-7X2GI5OV.js';
4
5
  import { AdapterRegistry } from './chunk-45K2XID7.js';
5
- import { ClaudeAdapter } from './chunk-D6RFF3KN.js';
6
- import './chunk-W6RSVMXR.js';
7
- import { ShellAdapter } from './chunk-52BFUGDD.js';
8
- import { ProcessManager } from './chunk-CHIP7O6V.js';
9
- import { Paths } from './chunk-LV6GDBBI.js';
6
+ import { ClaudeAdapter } from './chunk-4IFIOMCW.js';
7
+ import { ShellAdapter } from './chunk-XJTJ2TJV.js';
8
+ import './chunk-MGGSRXWJ.js';
10
9
  import './chunk-2C2TFQ7K.js';
10
+ import { ProcessManager } from './chunk-CHIP7O6V.js';
11
11
  import chalk from 'chalk';
12
12
 
13
13
  function registerDoctorCommand(program, container) {
package/dist/index.d.ts CHANGED
@@ -191,6 +191,8 @@ interface OrchestratorConfig {
191
191
  scheduling: SchedulingConfig;
192
192
  prompt?: {
193
193
  template?: string;
194
+ system_template?: string;
195
+ user_template?: string;
194
196
  };
195
197
  }
196
198
 
@@ -847,7 +849,7 @@ declare class RunService {
847
849
  * Get error and last N lines of output from the most recent failed run for a task.
848
850
  * Used to provide retry context so agents can learn from previous failures.
849
851
  */
850
- getLastFailedRunContext(taskId: string, maxOutputLines?: number): Promise<{
852
+ getLastFailedRunContext(taskId: string): Promise<{
851
853
  error: string;
852
854
  output: string;
853
855
  } | null>;
@@ -899,6 +901,7 @@ interface AdapterTestResult {
899
901
  }
900
902
  interface ExecuteParams {
901
903
  prompt: string;
904
+ systemPrompt?: string;
902
905
  workspace: string;
903
906
  env?: Record<string, string>;
904
907
  config: AgentConfig;
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ensureDir, Paths, readYaml, writeYaml, listFiles, writeJson, readJson, appendJsonl, readJsonl, readJsonlTail, pathExists } from './chunk-UIJYU3J7.js';
2
- import { canTransition, isTerminal } from './chunk-VMDQVRBR.js';
3
- export { Orchestrator, canTransition, isBlocked, isDispatchable, isTerminal, resolveFailureStatus } from './chunk-VMDQVRBR.js';
4
- import { AUTONOMOUS_LABEL } from './chunk-B4JQM4NU.js';
2
+ import { canTransition, isTerminal } from './chunk-O2OQCSBL.js';
3
+ export { Orchestrator, canTransition, isBlocked, isDispatchable, isTerminal, resolveFailureStatus } from './chunk-O2OQCSBL.js';
4
+ import { AUTONOMOUS_LABEL } from './chunk-VG4465AG.js';
5
5
  export { AdapterRegistry } from './chunk-6DWHQPTE.js';
6
6
  export { createTokenUsage } from './chunk-XDVMX2FO.js';
7
7
  import { InvalidArgumentsError, TaskNotFoundError, InvalidTransitionError, AgentNotFoundError, OrchestryError, TeamNotFoundError, GoalNotFoundError } from './chunk-NLQAJ7TW.js';
@@ -544,16 +544,15 @@ var RunService = class {
544
544
  * Get error and last N lines of output from the most recent failed run for a task.
545
545
  * Used to provide retry context so agents can learn from previous failures.
546
546
  */
547
- async getLastFailedRunContext(taskId, maxOutputLines = 50) {
547
+ async getLastFailedRunContext(taskId) {
548
548
  const runs = await this.runStore.listForTask(taskId);
549
549
  const failedRun = runs.filter((r) => r.status === "failed").sort((a, b) => (b.finished_at ?? "").localeCompare(a.finished_at ?? ""))[0];
550
550
  if (!failedRun) return null;
551
551
  const error = failedRun.error ?? "Unknown error";
552
552
  let output = "";
553
553
  try {
554
- const events = await this.runStore.readEventsTail(failedRun.id, maxOutputLines * 2);
555
- const outputLines = events.filter((e) => e.type === "agent_output" || e.type === "error").map((e) => typeof e.data === "string" ? e.data : JSON.stringify(e.data)).join("\n").split("\n");
556
- output = outputLines.slice(-maxOutputLines).join("\n");
554
+ const events = await this.runStore.readEventsTail(failedRun.id, 50);
555
+ output = events.filter((e) => e.type === "agent_output" || e.type === "error").map((e) => typeof e.data === "string" ? e.data : JSON.stringify(e.data)).join("\n");
557
556
  } catch {
558
557
  }
559
558
  return { error, output };
@@ -1759,6 +1758,7 @@ async function buildFullContainer(context) {
1759
1758
  { CodexAdapter },
1760
1759
  { CursorAdapter },
1761
1760
  { ShellAdapter },
1761
+ { OpenCodeAdapter },
1762
1762
  { WorkspaceManager },
1763
1763
  { LiquidTemplateEngine },
1764
1764
  { Orchestrator: Orchestrator2 },
@@ -1766,13 +1766,14 @@ async function buildFullContainer(context) {
1766
1766
  ] = await Promise.all([
1767
1767
  import('./process-manager-A36Y7LHP.js'),
1768
1768
  import('./registry-JXXRLJ5J.js'),
1769
- import('./claude-INM52PTH.js'),
1770
- import('./codex-QGH2GRV6.js'),
1771
- import('./cursor-KQJTQ73D.js'),
1772
- import('./shell-JXOPKDXH.js'),
1769
+ import('./claude-WUJU5KIE.js'),
1770
+ import('./codex-NYJWEPRQ.js'),
1771
+ import('./cursor-3YHVD4NP.js'),
1772
+ import('./shell-NJNW3O6K.js'),
1773
+ import('./opencode-FAMPSA6X.js'),
1773
1774
  import('./workspace-manager-EVD67GCG.js'),
1774
- import('./template-engine-MFL5B677.js'),
1775
- import('./orchestrator-ADO66XZ3.js'),
1775
+ import('./template-engine-5ZKVJMYA.js'),
1776
+ import('./orchestrator-X2CWGFCL.js'),
1776
1777
  import('./doctor-service-F2SXDWHS.js')
1777
1778
  ]);
1778
1779
  const processManager = new ProcessManager();
@@ -1787,6 +1788,7 @@ async function buildFullContainer(context) {
1787
1788
  adapterRegistry.register(new CodexAdapter(processManager));
1788
1789
  adapterRegistry.register(new CursorAdapter(processManager));
1789
1790
  adapterRegistry.register(new ShellAdapter(processManager));
1791
+ adapterRegistry.register(new OpenCodeAdapter(processManager));
1790
1792
  const doctorService = new DoctorService(adapterRegistry, processManager, context.projectRoot);
1791
1793
  const orchestrator = new Orchestrator2({
1792
1794
  taskStore: light.taskStore,