@oxgeneral/orch 1.0.2 → 1.0.4

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 (132) hide show
  1. package/dist/App-SSYYVFGW.js +22 -0
  2. package/dist/agent-Q34L27AY.js +9 -0
  3. package/dist/agent-shop-D2RS4BZK.js +2 -0
  4. package/dist/chunk-4MMHVHA6.js +112 -0
  5. package/dist/chunk-64WUDYEM.js +6 -0
  6. package/dist/chunk-6MJ7V6VY.js +2 -0
  7. package/dist/{chunk-DAVHOWGD.js → chunk-BCPUTULS.js} +16 -188
  8. package/dist/{chunk-INZ4O2RI.js → chunk-BSJVYRI3.js} +5 -2
  9. package/dist/chunk-BSJVYRI3.js.map +1 -0
  10. package/dist/chunk-CDFA4IIQ.js +2 -0
  11. package/dist/chunk-CHRW4CLD.js +2 -0
  12. package/dist/chunk-HMMPM7MF.js +3 -0
  13. package/dist/chunk-HXOMNULD.js +2 -0
  14. package/dist/chunk-IKNBPOQL.js +2 -0
  15. package/dist/chunk-KFQTWMZI.js +3 -0
  16. package/dist/chunk-LXNRCJ22.js +2 -0
  17. package/dist/{chunk-C6XZ3FJT.js → chunk-MOWC2CHX.js} +7 -4
  18. package/dist/chunk-MOWC2CHX.js.map +1 -0
  19. package/dist/chunk-P4JTJBWO.js +2 -0
  20. package/dist/chunk-PJ5DKXGR.js +2 -0
  21. package/dist/chunk-QNZ6D63E.js +4 -0
  22. package/dist/chunk-RHFRHCN5.js +16 -0
  23. package/dist/chunk-RHFRHCN5.js.map +1 -0
  24. package/dist/chunk-TPTHLFOB.js +2 -0
  25. package/dist/chunk-UMZEA3JT.js +5 -0
  26. package/dist/chunk-X54D5JZG.js +11 -0
  27. package/dist/{chunk-O2OQCSBL.js → chunk-YHIYJ5OL.js} +105 -29
  28. package/dist/chunk-YHIYJ5OL.js.map +1 -0
  29. package/dist/{claude-WUJU5KIE.js → claude-4R6L6BWY.js} +4 -4
  30. package/dist/{claude-WUJU5KIE.js.map → claude-4R6L6BWY.js.map} +1 -1
  31. package/dist/claude-ZLVOLRUG.js +2 -0
  32. package/dist/cli.js +1 -213
  33. package/dist/clipboard-service-WVON5ZN4.js +25 -0
  34. package/dist/{codex-NYJWEPRQ.js → codex-IMOW5ZUZ.js} +4 -4
  35. package/dist/{codex-NYJWEPRQ.js.map → codex-IMOW5ZUZ.js.map} +1 -1
  36. package/dist/codex-YRSODLH4.js +2 -0
  37. package/dist/config-OOB7QEKM.js +2 -0
  38. package/dist/container-FJI7RN2L.js +4 -0
  39. package/dist/context-FXRERFSP.js +7 -0
  40. package/dist/cursor-2HILMNM3.js +2 -0
  41. package/dist/{cursor-3YHVD4NP.js → cursor-NHV7X3WG.js} +4 -4
  42. package/dist/{cursor-3YHVD4NP.js.map → cursor-NHV7X3WG.js.map} +1 -1
  43. package/dist/doctor-GKTV4YYD.js +2 -0
  44. package/dist/doctor-service-PB7YBH3F.js +2 -0
  45. package/dist/editor-7IFRWVTL.js +8 -0
  46. package/dist/goal-RNNZYMNR.js +8 -0
  47. package/dist/index.d.ts +26 -8
  48. package/dist/index.js +247 -75
  49. package/dist/index.js.map +1 -1
  50. package/dist/init-56QC5QVX.js +53 -0
  51. package/dist/logs-4ISTWUWV.js +12 -0
  52. package/dist/msg-4ELI7Q52.js +9 -0
  53. package/dist/opencode-3S4VDXRG.js +2 -0
  54. package/dist/{opencode-FAMPSA6X.js → opencode-ULT6DYCT.js} +6 -5
  55. package/dist/opencode-ULT6DYCT.js.map +1 -0
  56. package/dist/orchestrator-PM4BW7W5.js +13 -0
  57. package/dist/orchestrator-QFNYZ6AH.js +6 -0
  58. package/dist/{orchestrator-X2CWGFCL.js.map → orchestrator-QFNYZ6AH.js.map} +1 -1
  59. package/dist/org-WAK3CDPG.js +3 -0
  60. package/dist/process-manager-33H27MQF.js +2 -0
  61. package/dist/registry-BO2PPRNG.js +2 -0
  62. package/dist/run-NE5E4JPW.js +3 -0
  63. package/dist/shell-OBHIVC2H.js +2 -0
  64. package/dist/{shell-NJNW3O6K.js → shell-UXEJRK3D.js} +4 -4
  65. package/dist/{shell-NJNW3O6K.js.map → shell-UXEJRK3D.js.map} +1 -1
  66. package/dist/shop-picker-LE3SKFOX.js +5 -0
  67. package/dist/status-NYHZ7Q5G.js +2 -0
  68. package/dist/task-SZBYNAZP.js +20 -0
  69. package/dist/team-VCJSUDWX.js +4 -0
  70. package/dist/template-engine-42PKL5KD.js +2 -0
  71. package/dist/tui-4VRDSRVB.js +2 -0
  72. package/dist/update-FFKCOV63.js +2 -0
  73. package/dist/update-check-HGMBDYHL.js +2 -0
  74. package/dist/{workspace-manager-2SFPKPLZ.js → workspace-manager-ABXFBL2A.js} +3 -3
  75. package/dist/{workspace-manager-2SFPKPLZ.js.map → workspace-manager-ABXFBL2A.js.map} +1 -1
  76. package/dist/workspace-manager-Q6WWXSTR.js +3 -0
  77. package/package.json +1 -1
  78. package/dist/App-YQOT4LBE.js +0 -6727
  79. package/dist/agent-7ZJ3ZDJ7.js +0 -183
  80. package/dist/agent-shop-YN2BSLHM.js +0 -2
  81. package/dist/chunk-2C2TFQ7K.js +0 -136
  82. package/dist/chunk-45K2XID7.js +0 -29
  83. package/dist/chunk-4IFIOMCW.js +0 -86
  84. package/dist/chunk-7X2GI5OV.js +0 -181
  85. package/dist/chunk-C6XZ3FJT.js.map +0 -1
  86. package/dist/chunk-CHIP7O6V.js +0 -83
  87. package/dist/chunk-FRTKB575.js +0 -87
  88. package/dist/chunk-HXYAZGLP.js +0 -15
  89. package/dist/chunk-I3SMISEF.js +0 -29
  90. package/dist/chunk-INZ4O2RI.js.map +0 -1
  91. package/dist/chunk-ITLJKMTP.js +0 -297
  92. package/dist/chunk-K6DMQERQ.js +0 -89
  93. package/dist/chunk-MGGSRXWJ.js +0 -69
  94. package/dist/chunk-O2OQCSBL.js.map +0 -1
  95. package/dist/chunk-P6ATSXGL.js +0 -107
  96. package/dist/chunk-PNE6LQRF.js +0 -5
  97. package/dist/chunk-U2VDNUZL.js +0 -52
  98. package/dist/chunk-VXS2CJFH.js +0 -273
  99. package/dist/chunk-XDVMX2FO.js +0 -8
  100. package/dist/chunk-XDVMX2FO.js.map +0 -1
  101. package/dist/chunk-XJTJ2TJV.js +0 -221
  102. package/dist/claude-ZUEKJJ4X.js +0 -5
  103. package/dist/clipboard-service-RTDUUQQU.js +0 -200
  104. package/dist/codex-7IXXXG5U.js +0 -123
  105. package/dist/config-OTAVSMOD.js +0 -75
  106. package/dist/container-IZZVO4AH.js +0 -1596
  107. package/dist/context-OL4BVUV5.js +0 -83
  108. package/dist/cursor-622RBRHH.js +0 -97
  109. package/dist/doctor-SETNAS4S.js +0 -67
  110. package/dist/doctor-service-TPOMFAIG.js +0 -2
  111. package/dist/goal-C6YGSX5D.js +0 -143
  112. package/dist/init-SWAAXP5H.js +0 -199
  113. package/dist/logs-PHPYWQ6I.js +0 -207
  114. package/dist/msg-FUWWLEKM.js +0 -95
  115. package/dist/opencode-FAMPSA6X.js.map +0 -1
  116. package/dist/opencode-WOR53TSC.js +0 -98
  117. package/dist/orchestrator-O6MFMATT.js +0 -1448
  118. package/dist/orchestrator-X2CWGFCL.js +0 -5
  119. package/dist/org-JSMMBZHI.js +0 -249
  120. package/dist/process-manager-HUVNAPQV.js +0 -2
  121. package/dist/registry-PQWRVNF2.js +0 -2
  122. package/dist/run-N72G5V2H.js +0 -95
  123. package/dist/shell-DVFHHYAZ.js +0 -5
  124. package/dist/shop-picker-2HY67UWP.js +0 -79
  125. package/dist/status-RZWN2C6C.js +0 -56
  126. package/dist/task-XNYZHPCS.js +0 -221
  127. package/dist/team-PFLP4PPL.js +0 -97
  128. package/dist/template-engine-AWIS56BL.js +0 -3
  129. package/dist/tui-JW3DOOKH.js +0 -245
  130. package/dist/update-YLP7FPNY.js +0 -64
  131. package/dist/update-check-4YKLGBFB.js +0 -2
  132. package/dist/workspace-manager-ESPU7WOH.js +0 -215
@@ -1,273 +0,0 @@
1
- #!/usr/bin/env node
2
- import { AUTONOMOUS_LABEL } from './chunk-PNE6LQRF.js';
3
-
4
- // src/infrastructure/template/template-engine.ts
5
- var LiquidTemplateEngine = class {
6
- engine;
7
- renderTimeoutMs;
8
- constructor(options) {
9
- this.renderTimeoutMs = options?.renderTimeoutMs ?? 5e3;
10
- }
11
- async getEngine() {
12
- if (!this.engine) {
13
- const { Liquid } = await import('liquidjs');
14
- this.engine = new Liquid({
15
- strictFilters: false,
16
- strictVariables: false
17
- });
18
- }
19
- return this.engine;
20
- }
21
- async render(template, context) {
22
- const engine = await this.getEngine();
23
- const renderPromise = engine.parseAndRender(template, context);
24
- if (this.renderTimeoutMs <= 0) {
25
- return renderPromise;
26
- }
27
- let timer;
28
- const timeoutPromise = new Promise((_, reject) => {
29
- timer = setTimeout(
30
- () => reject(new Error(`Template render timed out after ${this.renderTimeoutMs}ms`)),
31
- this.renderTimeoutMs
32
- );
33
- });
34
- try {
35
- return await Promise.race([renderPromise, timeoutPromise]);
36
- } finally {
37
- clearTimeout(timer);
38
- }
39
- }
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
- }
109
- function buildPromptContext(task, agent, attempt, workspacePath, config, options) {
110
- const { allAgents, retryContext, sharedContext, feedback, messages: rawMessages, goal } = options ?? {};
111
- const agentById = new Map((allAgents ?? []).map((a) => [a.id, a]));
112
- const messages = rawMessages?.length ? rawMessages.map((m) => ({
113
- id: m.id,
114
- from: agentById.get(m.from_agent_id)?.name ?? m.from_agent_id,
115
- subject: m.subject,
116
- body: m.body,
117
- sent_at: m.created_at,
118
- reply_to: m.reply_to
119
- })) : void 0;
120
- return {
121
- project: {
122
- name: config.project.name,
123
- description: config.project.description
124
- },
125
- task: {
126
- id: task.id,
127
- title: task.title,
128
- description: task.description,
129
- priority: task.priority,
130
- labels: task.labels,
131
- scope: task.scope,
132
- is_autonomous: task.labels?.includes(AUTONOMOUS_LABEL) ?? false,
133
- goal_id: task.goalId
134
- },
135
- agent: {
136
- id: agent.id,
137
- name: agent.name,
138
- role: agent.role
139
- },
140
- agents: (allAgents ?? []).map((a) => ({
141
- id: a.id,
142
- name: a.name,
143
- role: a.id === agent.id ? void 0 : a.role,
144
- adapter: a.adapter
145
- })),
146
- attempt: attempt > 1 ? attempt : null,
147
- workspace_path: workspacePath,
148
- retry: attempt > 1 ? retryContext : void 0,
149
- feedback,
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,
156
- messages,
157
- goal
158
- };
159
- }
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 %}
192
-
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 }}
201
- {{ task.description }}
202
-
203
- Priority: {{ task.priority }}
204
- {% if attempt %}Attempt: {{ attempt }}{% endif %}
205
- {% if retry %}
206
- ## Previous attempt failed
207
- **Error:** {{ retry.previous_error }}
208
- {% if retry.previous_output != "" %}
209
- **Last output:**
210
- \`\`\`
211
- {{ retry.previous_output }}
212
- \`\`\`
213
- {% endif %}
214
- **Important:** The previous approach failed. Analyze the error above and try a different strategy. Do NOT repeat the same steps that led to the failure.
215
- {% endif %}
216
-
217
- ## Context
218
- Project: {{ project.name }}
219
- Working directory: {{ workspace_path }}
220
-
221
- ## Team
222
- You are part of a multi-agent team. Available agents:
223
- {% for a in agents %}- **{{ a.name }}** ({{ a.adapter }}){% if a.role %} \u2014 {{ a.role }}{% endif %} \xB7 ID: \`{{ a.id }}\`
224
- {% endfor %}
225
- Use \`orch agent list\` to check current agent statuses. Find teammates by name/role \u2014 do NOT hardcode agent IDs.
226
-
227
- {% if feedback %}
228
- ## Review Feedback
229
- This task was previously completed but **rejected** during review with the following feedback:
230
- > {{ feedback }}
231
-
232
- **Important:** Address the feedback above. Focus on what the reviewer asked to change. Do NOT redo work that was already accepted.
233
- {% endif %}
234
-
235
- {% if shared_context %}
236
- ## Shared Context
237
- Other agents have shared the following information:
238
- {% for entry in shared_context %}- **{{ entry[0] }}**: {{ entry[1] }}
239
- {% endfor %}
240
- {% endif %}
241
-
242
- {% if messages %}
243
- ## Inbox ({{ messages.size }} message{% if messages.size != 1 %}s{% endif %})
244
- {% for msg in messages %}
245
- ---
246
- **From:** {{ msg.from }}{% if msg.subject != "" %} \xB7 **Subject:** {{ msg.subject }}{% endif %}
247
- {{ msg.body }}
248
- {% if msg.reply_to %}*(Reply to: {{ msg.reply_to }})*{% endif %}
249
- ---
250
- {% endfor %}
251
- {% endif %}
252
-
253
- {% if goal %}
254
- ## Goal: {{ goal.title }}
255
- **Status:** {{ goal.status }} \xB7 **ID:** \`{{ goal.id }}\`
256
- {% if goal.description != "" %}
257
- {{ goal.description }}
258
- {% endif %}
259
- {% if goal.task_names.size > 0 %}
260
- **Linked tasks ({{ goal.task_names.size }}):**
261
- {% for name in goal.task_names %}- {{ name }}
262
- {% endfor %}
263
- Use \`orch task list --goal-id {{ goal.id }}\` and \`orch task show <id>\` to inspect details.
264
- {% endif %}
265
- {% if goal.progress %}
266
- **Latest progress report:**
267
- {{ goal.progress }}
268
- {% endif %}
269
- {% endif %}
270
- `;
271
- var DEFAULT_PROMPT_TEMPLATE = DEFAULT_SYSTEM_TEMPLATE + "\n" + DEFAULT_USER_TEMPLATE;
272
-
273
- export { DEFAULT_PROMPT_TEMPLATE, DEFAULT_SYSTEM_TEMPLATE, DEFAULT_USER_TEMPLATE, LiquidTemplateEngine, buildPromptContext, filterRelevantContext };
@@ -1,8 +0,0 @@
1
- // src/domain/run.ts
2
- function createTokenUsage(input, output) {
3
- return { input, output, total: input + output };
4
- }
5
-
6
- export { createTokenUsage };
7
- //# sourceMappingURL=chunk-XDVMX2FO.js.map
8
- //# sourceMappingURL=chunk-XDVMX2FO.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/domain/run.ts"],"names":[],"mappings":";AAqCO,SAAS,gBAAA,CAAiB,OAAe,MAAA,EAA4B;AAC1E,EAAA,OAAO,EAAE,KAAA,EAAO,MAAA,EAAQ,KAAA,EAAO,QAAQ,MAAA,EAAO;AAChD","file":"chunk-XDVMX2FO.js","sourcesContent":["/**\n * Run domain model.\n *\n * A Run represents a single execution attempt of a Task by an Agent.\n * Events are stored in separate .jsonl files (append-only), not in memory.\n */\n\nexport type RunStatus =\n | 'preparing'\n | 'running'\n | 'succeeded'\n | 'failed'\n | 'timed_out'\n | 'cancelled';\n\nexport interface Run {\n id: string;\n task_id: string;\n agent_id: string;\n attempt: number;\n status: RunStatus;\n started_at: string;\n finished_at?: string;\n workspace_path: string;\n prompt: string;\n pid?: number;\n error?: string;\n tokens?: TokenUsage;\n}\n\nexport interface TokenUsage {\n input: number;\n output: number;\n total: number;\n}\n\n/** Create TokenUsage with total always computed as input + output. */\nexport function createTokenUsage(input: number, output: number): TokenUsage {\n return { input, output, total: input + output };\n}\n\nexport interface RunEvent {\n timestamp: string;\n type: RunEventType;\n data: unknown;\n}\n\nexport type RunEventType =\n | 'agent_output'\n | 'file_changed'\n | 'command_run'\n | 'tool_call'\n | 'error'\n | 'done';\n"]}
@@ -1,221 +0,0 @@
1
- #!/usr/bin/env node
2
- import { buildFullPrompt } from './chunk-MGGSRXWJ.js';
3
- import { classifyAdapterError } from './chunk-2C2TFQ7K.js';
4
- import { readLines } from './chunk-CHIP7O6V.js';
5
- import { execFile } from 'child_process';
6
- import { promisify } from 'util';
7
-
8
- // src/infrastructure/adapters/event-buffer.ts
9
- var DEFAULT_CAPACITY = 1024;
10
- function deferred() {
11
- let resolve;
12
- const promise = new Promise((r) => {
13
- resolve = r;
14
- });
15
- return { promise, resolve };
16
- }
17
- var EventBuffer = class {
18
- buf;
19
- head = 0;
20
- // read index
21
- tail = 0;
22
- // write index
23
- count = 0;
24
- capacity;
25
- // Consumer notification: resolved when new data is available
26
- dataReady = null;
27
- // Producer notification: resolved when space is available
28
- spaceReady = null;
29
- closed = false;
30
- constructor(capacity = DEFAULT_CAPACITY) {
31
- this.capacity = capacity;
32
- this.buf = new Array(capacity);
33
- }
34
- /** Number of buffered events. */
35
- get size() {
36
- return this.count;
37
- }
38
- get isFull() {
39
- return this.count >= this.capacity;
40
- }
41
- /**
42
- * Push an event into the buffer.
43
- * If the buffer is full, waits until space is available (backpressure).
44
- */
45
- async push(event) {
46
- while (this.isFull && !this.closed) {
47
- if (!this.spaceReady) {
48
- this.spaceReady = deferred();
49
- }
50
- await this.spaceReady.promise;
51
- }
52
- if (this.closed) return;
53
- this.buf[this.tail] = event;
54
- this.tail = (this.tail + 1) % this.capacity;
55
- this.count++;
56
- if (this.dataReady) {
57
- const dr = this.dataReady;
58
- this.dataReady = null;
59
- dr.resolve();
60
- }
61
- }
62
- /**
63
- * Dequeue the next event. O(1).
64
- * Returns undefined only when buffer is empty AND closed.
65
- */
66
- async take() {
67
- while (this.count === 0) {
68
- if (this.closed) return void 0;
69
- if (!this.dataReady) {
70
- this.dataReady = deferred();
71
- }
72
- await this.dataReady.promise;
73
- }
74
- const event = this.buf[this.head];
75
- this.buf[this.head] = void 0;
76
- this.head = (this.head + 1) % this.capacity;
77
- this.count--;
78
- if (this.spaceReady) {
79
- const sr = this.spaceReady;
80
- this.spaceReady = null;
81
- sr.resolve();
82
- }
83
- return event;
84
- }
85
- /**
86
- * Signal that no more events will be pushed.
87
- * Wakes up any waiting consumer/producer.
88
- */
89
- close() {
90
- this.closed = true;
91
- if (this.dataReady) {
92
- const dr = this.dataReady;
93
- this.dataReady = null;
94
- dr.resolve();
95
- }
96
- if (this.spaceReady) {
97
- const sr = this.spaceReady;
98
- this.spaceReady = null;
99
- sr.resolve();
100
- }
101
- }
102
- get isClosed() {
103
- return this.closed;
104
- }
105
- /**
106
- * Async iterator that drains the buffer until closed and empty.
107
- */
108
- async *[Symbol.asyncIterator]() {
109
- while (true) {
110
- const event = await this.take();
111
- if (event === void 0) return;
112
- yield event;
113
- }
114
- }
115
- };
116
- var execFileAsync = promisify(execFile);
117
- var ShellAdapter = class {
118
- constructor(processManager) {
119
- this.processManager = processManager;
120
- }
121
- kind = "shell";
122
- async test() {
123
- try {
124
- const { stdout } = await execFileAsync("bash", ["--version"]);
125
- const version = stdout.split("\n")[0]?.trim() ?? "unknown";
126
- return { ok: true, version };
127
- } catch {
128
- return { ok: false, error: "bash not found", errorKind: classifyAdapterError("bash not found") };
129
- }
130
- }
131
- execute(params) {
132
- const command = params.config.command;
133
- if (!command) {
134
- async function* errorGen() {
135
- yield {
136
- type: "error",
137
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
138
- data: "Shell adapter requires a command in agent config",
139
- errorKind: "spawn_failed" /* SPAWN_FAILED */
140
- };
141
- }
142
- return { pid: 0, events: errorGen() };
143
- }
144
- const { process: proc, pid } = this.processManager.spawn("bash", ["-lc", command], {
145
- cwd: params.workspace,
146
- env: {
147
- ...process.env,
148
- ...params.env,
149
- ORCHESTRY_TASK_PROMPT: buildFullPrompt(params.systemPrompt, params.prompt)
150
- },
151
- signal: params.signal
152
- });
153
- const signal = params.signal;
154
- const processManager = this.processManager;
155
- async function* generateEvents() {
156
- const buffer = new EventBuffer();
157
- const onAbort = () => {
158
- processManager.killWithGrace(pid, 5e3).catch(() => {
159
- });
160
- };
161
- if (signal) {
162
- if (signal.aborted) {
163
- onAbort();
164
- } else {
165
- signal.addEventListener("abort", onAbort, { once: true });
166
- }
167
- }
168
- const stdoutPromise = (async () => {
169
- if (!proc.stdout) return;
170
- for await (const line of readLines(proc.stdout)) {
171
- if (signal?.aborted) break;
172
- await buffer.push({
173
- type: "output",
174
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
175
- data: line
176
- });
177
- }
178
- })();
179
- const stderrPromise = (async () => {
180
- if (!proc.stderr) return;
181
- for await (const line of readLines(proc.stderr)) {
182
- if (signal?.aborted) break;
183
- await buffer.push({
184
- type: "error",
185
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
186
- data: line,
187
- errorKind: classifyAdapterError(line)
188
- });
189
- }
190
- })();
191
- void Promise.all([stdoutPromise, stderrPromise]).then(
192
- () => buffer.close(),
193
- () => buffer.close()
194
- );
195
- yield* buffer;
196
- if (signal && !signal.aborted) {
197
- signal.removeEventListener("abort", onAbort);
198
- }
199
- await new Promise((resolve, reject) => {
200
- if (proc.exitCode !== null || proc.killed) {
201
- resolve();
202
- return;
203
- }
204
- proc.on("close", (code) => {
205
- if (code === 0 || signal?.aborted) {
206
- resolve();
207
- } else {
208
- reject(new Error(`Shell command exited with code ${code}`));
209
- }
210
- });
211
- proc.on("error", reject);
212
- });
213
- }
214
- return { pid, events: generateEvents() };
215
- }
216
- async stop(pid) {
217
- await this.processManager.killWithGrace(pid);
218
- }
219
- };
220
-
221
- export { ShellAdapter };
@@ -1,5 +0,0 @@
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';