@oxgeneral/orch 0.3.3 → 0.3.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.
- package/dist/App-RKAPZNZO.js +6682 -0
- package/dist/agent-KBTLGGCT.js +183 -0
- package/dist/agent-shop-YN2BSLHM.js +2 -0
- package/dist/chunk-2C2TFQ7K.js +136 -0
- package/dist/chunk-45K2XID7.js +29 -0
- package/dist/chunk-52BFUGDD.js +220 -0
- package/dist/chunk-7X2GI5OV.js +181 -0
- package/dist/{chunk-HSBYJ5C5.js → chunk-A36WAF2S.js} +89 -2
- package/dist/chunk-CHIP7O6V.js +83 -0
- package/dist/chunk-D6RFF3KN.js +85 -0
- package/dist/{chunk-BCPUTULS.js → chunk-DAVHOWGD.js} +188 -16
- package/dist/chunk-FRTKB575.js +87 -0
- package/dist/chunk-HXYAZGLP.js +15 -0
- package/dist/chunk-I3SMISEF.js +29 -0
- package/dist/chunk-K6DMQERQ.js +89 -0
- package/dist/chunk-LV6GDBBI.js +297 -0
- package/dist/chunk-P6ATSXGL.js +107 -0
- package/dist/chunk-PNE6LQRF.js +5 -0
- package/dist/chunk-U2VDNUZL.js +52 -0
- package/dist/{chunk-BGHCY7WY.js → chunk-VMDQVRBR.js} +18 -8
- package/dist/chunk-VMDQVRBR.js.map +1 -0
- package/dist/chunk-W6RSVMXR.js +66 -0
- package/dist/claude-NHUNA5RZ.js +5 -0
- package/dist/cli.js +199 -1
- package/dist/clipboard-service-RTDUUQQU.js +200 -0
- package/dist/codex-DIXT44JR.js +123 -0
- package/dist/config-OTAVSMOD.js +75 -0
- package/dist/container-LJU4QNDH.js +1594 -0
- package/dist/context-OL4BVUV5.js +83 -0
- package/dist/cursor-C3TR2IJC.js +97 -0
- package/dist/doctor-V2FPS236.js +67 -0
- package/dist/doctor-service-TPOMFAIG.js +2 -0
- package/dist/goal-FMYYN2FR.js +138 -0
- package/dist/index.d.ts +12 -1
- package/dist/index.js +14 -7
- package/dist/index.js.map +1 -1
- package/dist/init-U7MCIOB2.js +165 -0
- package/dist/logs-PHPYWQ6I.js +207 -0
- package/dist/msg-FUWWLEKM.js +95 -0
- package/dist/orchestrator-ADO66XZ3.js +5 -0
- package/dist/{orchestrator-KF4UY5GD.js.map → orchestrator-ADO66XZ3.js.map} +1 -1
- package/dist/orchestrator-E3FQ4SOE.js +1424 -0
- package/dist/process-manager-HUVNAPQV.js +2 -0
- package/dist/registry-PQWRVNF2.js +2 -0
- package/dist/run-N72G5V2H.js +95 -0
- package/dist/shell-3S4VLYEG.js +4 -0
- package/dist/{shell-UXJNTNBC.js → shell-JXOPKDXH.js} +3 -3
- package/dist/shell-JXOPKDXH.js.map +1 -0
- package/dist/shop-picker-2HY67UWP.js +79 -0
- package/dist/status-RZWN2C6C.js +56 -0
- package/dist/task-2TJW6Z7O.js +221 -0
- package/dist/team-PFLP4PPL.js +97 -0
- package/dist/template-engine-4IZKRRHG.js +3 -0
- package/dist/tui-IM3YUUVD.js +245 -0
- package/dist/update-YLP7FPNY.js +64 -0
- package/dist/update-check-4YKLGBFB.js +2 -0
- package/dist/workspace-manager-JM6U7JOH.js +215 -0
- package/package.json +1 -1
- package/readme.md +9 -2
- package/scripts/postinstall.js +44 -2
- package/dist/App-NN7HR7UE.js +0 -20
- package/dist/agent-S4DKSX63.js +0 -9
- package/dist/agent-shop-D2RS4BZK.js +0 -2
- package/dist/chunk-3MQNQ7QW.js +0 -2
- package/dist/chunk-5AJ4LYO5.js +0 -8
- package/dist/chunk-6MJ7V6VY.js +0 -2
- package/dist/chunk-BGHCY7WY.js.map +0 -1
- package/dist/chunk-CDFA4IIQ.js +0 -2
- package/dist/chunk-CHRW4CLD.js +0 -2
- package/dist/chunk-HMMPM7MF.js +0 -3
- package/dist/chunk-HXOMNULD.js +0 -2
- package/dist/chunk-IS3YBE2B.js +0 -3
- package/dist/chunk-KPCT44WU.js +0 -2
- package/dist/chunk-L26TK7Y5.js +0 -2
- package/dist/chunk-LXNRCJ22.js +0 -2
- package/dist/chunk-OQKREZUF.js +0 -11
- package/dist/chunk-PJ5DKXGR.js +0 -2
- package/dist/chunk-QFKVCNKL.js +0 -2
- package/dist/chunk-UMZEA3JT.js +0 -5
- package/dist/claude-GQZNDJ6L.js +0 -2
- package/dist/clipboard-service-MYLSWM5E.js +0 -25
- package/dist/codex-SJV7ZZBY.js +0 -2
- package/dist/config-CCSS2P7R.js +0 -2
- package/dist/container-NEKK5W2B.js +0 -6
- package/dist/context-GSMQHQES.js +0 -7
- package/dist/cursor-4JQOCP5X.js +0 -2
- package/dist/doctor-UAII4VWN.js +0 -2
- package/dist/doctor-service-PB7YBH3F.js +0 -2
- package/dist/goal-RFKFPR7M.js +0 -8
- package/dist/init-2D4RAN7B.js +0 -53
- package/dist/logs-UXFXVYCP.js +0 -12
- package/dist/msg-4SCLBO4K.js +0 -9
- package/dist/orchestrator-KF4UY5GD.js +0 -5
- package/dist/orchestrator-MFL3XK5L.js +0 -13
- package/dist/process-manager-33H27MQF.js +0 -2
- package/dist/registry-BO2PPRNG.js +0 -2
- package/dist/run-HSHRELOP.js +0 -3
- package/dist/shell-F42UUF3U.js +0 -2
- package/dist/shell-UXJNTNBC.js.map +0 -1
- package/dist/shop-picker-LE3SKFOX.js +0 -5
- package/dist/status-DLBNWSWM.js +0 -2
- package/dist/task-AP2TIOOF.js +0 -20
- package/dist/team-MSIBKOQC.js +0 -4
- package/dist/template-engine-ONIDVD4F.js +0 -2
- package/dist/tui-PIQT4ZZ2.js +0 -2
- package/dist/update-PC2ENCKU.js +0 -2
- package/dist/update-check-HGMBDYHL.js +0 -2
- package/dist/workspace-manager-DYN3XJ7X.js +0 -3
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
|
|
4
|
+
var icons = {
|
|
5
|
+
running: "\u25CF",
|
|
6
|
+
todo: "\u25CB",
|
|
7
|
+
review: "\u25C8",
|
|
8
|
+
done: "\u2713",
|
|
9
|
+
failed: "\u2715",
|
|
10
|
+
retrying: "\u21BB",
|
|
11
|
+
cancelled: "\u25CB",
|
|
12
|
+
idle: "\u25CB",
|
|
13
|
+
error: "\u2715",
|
|
14
|
+
disabled: "\u2500",
|
|
15
|
+
agentAction: "\u25B8",
|
|
16
|
+
orchestratorEvent: "\u2192",
|
|
17
|
+
warning: "\u26A0"
|
|
18
|
+
};
|
|
19
|
+
var asciiIcons = {
|
|
20
|
+
running: "*",
|
|
21
|
+
todo: "o",
|
|
22
|
+
review: "#",
|
|
23
|
+
done: "+",
|
|
24
|
+
failed: "x",
|
|
25
|
+
retrying: "~",
|
|
26
|
+
cancelled: "o",
|
|
27
|
+
idle: "o",
|
|
28
|
+
error: "x",
|
|
29
|
+
disabled: "-",
|
|
30
|
+
agentAction: ">",
|
|
31
|
+
orchestratorEvent: "->",
|
|
32
|
+
warning: "!!"
|
|
33
|
+
};
|
|
34
|
+
var COLOR_CODES = {
|
|
35
|
+
amber: 214,
|
|
36
|
+
green: 72,
|
|
37
|
+
red: 167,
|
|
38
|
+
blue: 74,
|
|
39
|
+
yellow: 178,
|
|
40
|
+
dim: 240,
|
|
41
|
+
ghost: 236,
|
|
42
|
+
white: 255,
|
|
43
|
+
purple: 141
|
|
44
|
+
};
|
|
45
|
+
var _colors;
|
|
46
|
+
function getColors() {
|
|
47
|
+
if (!_colors) {
|
|
48
|
+
_colors = {};
|
|
49
|
+
for (const [name, code] of Object.entries(COLOR_CODES)) {
|
|
50
|
+
_colors[name] = chalk.ansi256(code);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return _colors;
|
|
54
|
+
}
|
|
55
|
+
var colors = new Proxy({}, {
|
|
56
|
+
get(_target, prop) {
|
|
57
|
+
return getColors()[prop];
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
var useAscii = false;
|
|
61
|
+
function setAsciiMode(ascii) {
|
|
62
|
+
useAscii = ascii;
|
|
63
|
+
}
|
|
64
|
+
function setNoColor(noColor) {
|
|
65
|
+
if (noColor) {
|
|
66
|
+
chalk.level = 0;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function getIcon(name) {
|
|
70
|
+
return useAscii ? asciiIcons[name] : icons[name];
|
|
71
|
+
}
|
|
72
|
+
function statusIcon(status) {
|
|
73
|
+
const icon = getIcon(status);
|
|
74
|
+
switch (status) {
|
|
75
|
+
case "running":
|
|
76
|
+
case "in_progress":
|
|
77
|
+
return colors.green(getIcon("running"));
|
|
78
|
+
case "todo":
|
|
79
|
+
return colors.dim(getIcon("todo"));
|
|
80
|
+
case "review":
|
|
81
|
+
return colors.blue(getIcon("review"));
|
|
82
|
+
case "done":
|
|
83
|
+
return colors.green(getIcon("done"));
|
|
84
|
+
case "failed":
|
|
85
|
+
return colors.red(getIcon("failed"));
|
|
86
|
+
case "retrying":
|
|
87
|
+
return colors.yellow(getIcon("retrying"));
|
|
88
|
+
case "cancelled":
|
|
89
|
+
return colors.dim(getIcon("cancelled"));
|
|
90
|
+
case "idle":
|
|
91
|
+
return colors.dim(getIcon("idle"));
|
|
92
|
+
case "error":
|
|
93
|
+
return colors.red(getIcon("error"));
|
|
94
|
+
case "disabled":
|
|
95
|
+
return colors.ghost(getIcon("disabled"));
|
|
96
|
+
default:
|
|
97
|
+
return icon;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function priorityLabel(priority) {
|
|
101
|
+
switch (priority) {
|
|
102
|
+
case 1:
|
|
103
|
+
return colors.red("P1");
|
|
104
|
+
case 2:
|
|
105
|
+
return colors.yellow("P2");
|
|
106
|
+
case 3:
|
|
107
|
+
return "P3";
|
|
108
|
+
case 4:
|
|
109
|
+
return colors.dim("P4");
|
|
110
|
+
default:
|
|
111
|
+
return `P${priority}`;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function formatDuration(ms) {
|
|
115
|
+
const seconds = Math.floor(ms / 1e3);
|
|
116
|
+
if (seconds < 60) return `${seconds}s`;
|
|
117
|
+
const minutes = Math.floor(seconds / 60);
|
|
118
|
+
const secs = seconds % 60;
|
|
119
|
+
if (minutes < 60) return `${minutes}:${String(secs).padStart(2, "0")}`;
|
|
120
|
+
const hours = Math.floor(minutes / 60);
|
|
121
|
+
const mins = minutes % 60;
|
|
122
|
+
return `${hours}h${String(mins).padStart(2, "0")}m`;
|
|
123
|
+
}
|
|
124
|
+
function formatDurationSince(isoDate) {
|
|
125
|
+
const ms = Date.now() - new Date(isoDate).getTime();
|
|
126
|
+
return formatDuration(ms);
|
|
127
|
+
}
|
|
128
|
+
function formatTokens(n) {
|
|
129
|
+
if (n >= 1e3) return `${(n / 1e3).toFixed(1)}k`;
|
|
130
|
+
return String(n);
|
|
131
|
+
}
|
|
132
|
+
function printError(message, hint) {
|
|
133
|
+
console.error(` ${colors.red(getIcon("failed"))} ${message}`);
|
|
134
|
+
if (hint) {
|
|
135
|
+
console.error(` ${hint}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function printSuccess(message) {
|
|
139
|
+
console.log(` ${colors.green(getIcon("done"))} ${message}`);
|
|
140
|
+
}
|
|
141
|
+
function printWarning(message) {
|
|
142
|
+
console.log(` ${colors.yellow(getIcon("warning"))} ${message}`);
|
|
143
|
+
}
|
|
144
|
+
function printTable(headers, rows, padding = 2) {
|
|
145
|
+
const colWidths = headers.map(
|
|
146
|
+
(h, i) => Math.max(h.length, ...rows.map((r) => stripAnsi(r[i] ?? "").length))
|
|
147
|
+
);
|
|
148
|
+
const headerLine = headers.map((h, i) => h.padEnd(colWidths[i] + padding)).join("");
|
|
149
|
+
console.log(` ${colors.dim(headerLine)}`);
|
|
150
|
+
for (const row of rows) {
|
|
151
|
+
const line = row.map((cell, i) => {
|
|
152
|
+
const stripped = stripAnsi(cell);
|
|
153
|
+
const pad = (colWidths[i] ?? 0) + padding - stripped.length;
|
|
154
|
+
return cell + " ".repeat(Math.max(0, pad));
|
|
155
|
+
}).join("");
|
|
156
|
+
console.log(` ${line}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function printKeyValue(pairs) {
|
|
160
|
+
const maxKey = Math.max(...pairs.map(([k]) => k.length));
|
|
161
|
+
for (const [key, value] of pairs) {
|
|
162
|
+
console.log(` ${colors.dim(key.padEnd(maxKey + 2))}${value}`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function filePath(p) {
|
|
166
|
+
return colors.purple(p);
|
|
167
|
+
}
|
|
168
|
+
function agentName(name) {
|
|
169
|
+
return colors.green(name);
|
|
170
|
+
}
|
|
171
|
+
function amber(text) {
|
|
172
|
+
return colors.amber(text);
|
|
173
|
+
}
|
|
174
|
+
function dim(text) {
|
|
175
|
+
return colors.dim(text);
|
|
176
|
+
}
|
|
177
|
+
function stripAnsi(str) {
|
|
178
|
+
return str.replace(/\x1b\[[0-9;]*m/g, "");
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export { agentName, amber, dim, filePath, formatDuration, formatDurationSince, formatTokens, getIcon, printError, printKeyValue, printSuccess, printTable, printWarning, priorityLabel, setAsciiMode, setNoColor, statusIcon };
|
|
@@ -1,5 +1,90 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
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
|
+
function buildPromptContext(task, agent, attempt, workspacePath, config, options) {
|
|
42
|
+
const { allAgents, retryContext, sharedContext, feedback, messages: rawMessages, goal } = options ?? {};
|
|
43
|
+
const agentById = new Map((allAgents ?? []).map((a) => [a.id, a]));
|
|
44
|
+
const messages = rawMessages?.length ? rawMessages.map((m) => ({
|
|
45
|
+
id: m.id,
|
|
46
|
+
from: agentById.get(m.from_agent_id)?.name ?? m.from_agent_id,
|
|
47
|
+
subject: m.subject,
|
|
48
|
+
body: m.body,
|
|
49
|
+
sent_at: m.created_at,
|
|
50
|
+
reply_to: m.reply_to
|
|
51
|
+
})) : void 0;
|
|
52
|
+
return {
|
|
53
|
+
project: {
|
|
54
|
+
name: config.project.name,
|
|
55
|
+
description: config.project.description
|
|
56
|
+
},
|
|
57
|
+
task: {
|
|
58
|
+
id: task.id,
|
|
59
|
+
title: task.title,
|
|
60
|
+
description: task.description,
|
|
61
|
+
priority: task.priority,
|
|
62
|
+
labels: task.labels,
|
|
63
|
+
scope: task.scope,
|
|
64
|
+
is_autonomous: task.labels?.includes(AUTONOMOUS_LABEL) ?? false,
|
|
65
|
+
goal_id: task.goalId
|
|
66
|
+
},
|
|
67
|
+
agent: {
|
|
68
|
+
id: agent.id,
|
|
69
|
+
name: agent.name,
|
|
70
|
+
role: agent.role
|
|
71
|
+
},
|
|
72
|
+
agents: (allAgents ?? []).map((a) => ({
|
|
73
|
+
id: a.id,
|
|
74
|
+
name: a.name,
|
|
75
|
+
role: a.role,
|
|
76
|
+
adapter: a.adapter
|
|
77
|
+
})),
|
|
78
|
+
attempt: attempt > 1 ? attempt : null,
|
|
79
|
+
workspace_path: workspacePath,
|
|
80
|
+
retry: attempt > 1 ? retryContext : void 0,
|
|
81
|
+
feedback,
|
|
82
|
+
shared_context: sharedContext && Object.keys(sharedContext).length > 0 ? sharedContext : void 0,
|
|
83
|
+
messages,
|
|
84
|
+
goal
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
var DEFAULT_PROMPT_TEMPLATE = `You are {{ agent.name }}{% if agent.role %} ({{ agent.role }}){% endif %}.
|
|
3
88
|
|
|
4
89
|
## Task: {{ task.title }}
|
|
5
90
|
{{ task.description }}
|
|
@@ -109,4 +194,6 @@ This is an autonomous task driven by a goal. Work in a continuous loop until the
|
|
|
109
194
|
- If critical information is missing, document your assumptions and continue.
|
|
110
195
|
- When a task is too large or spans multiple domains, break it into subtasks using \`orch task add\`.
|
|
111
196
|
- When creating subtasks, use \`--scope\` to declare which files each task will touch, and \`--depends-on\` to order dependent work.
|
|
112
|
-
`;
|
|
197
|
+
`;
|
|
198
|
+
|
|
199
|
+
export { DEFAULT_PROMPT_TEMPLATE, LiquidTemplateEngine, buildPromptContext };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawn } from 'child_process';
|
|
3
|
+
|
|
4
|
+
var ProcessManager = class {
|
|
5
|
+
isAlive(pid) {
|
|
6
|
+
try {
|
|
7
|
+
process.kill(pid, 0);
|
|
8
|
+
return true;
|
|
9
|
+
} catch (err) {
|
|
10
|
+
if (err.code === "EPERM") return true;
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
kill(pid, signal = "SIGTERM") {
|
|
15
|
+
try {
|
|
16
|
+
process.kill(-pid, signal);
|
|
17
|
+
} catch {
|
|
18
|
+
try {
|
|
19
|
+
process.kill(pid, signal);
|
|
20
|
+
} catch {
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
async killWithGrace(pid, graceMs = 1e4) {
|
|
25
|
+
if (!this.isAlive(pid)) return;
|
|
26
|
+
this.kill(pid, "SIGTERM");
|
|
27
|
+
const deadline = Date.now() + graceMs;
|
|
28
|
+
while (Date.now() < deadline) {
|
|
29
|
+
if (!this.isAlive(pid)) return;
|
|
30
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
31
|
+
}
|
|
32
|
+
this.kill(pid, "SIGKILL");
|
|
33
|
+
}
|
|
34
|
+
spawn(command, args, options) {
|
|
35
|
+
const proc = spawn(command, args, {
|
|
36
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
37
|
+
detached: true,
|
|
38
|
+
// Create new process group so killWithGrace(-pid) kills all children
|
|
39
|
+
...options
|
|
40
|
+
});
|
|
41
|
+
if (!proc.pid) {
|
|
42
|
+
throw new Error(`Failed to spawn process: ${command}`);
|
|
43
|
+
}
|
|
44
|
+
proc.unref();
|
|
45
|
+
return { process: proc, pid: proc.pid };
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
var MAX_LINE_LEN = 16384;
|
|
49
|
+
function capLine(s) {
|
|
50
|
+
return s.length > MAX_LINE_LEN ? s.slice(0, MAX_LINE_LEN) : s;
|
|
51
|
+
}
|
|
52
|
+
async function* readLines(stream) {
|
|
53
|
+
const chunks = [];
|
|
54
|
+
let totalLen = 0;
|
|
55
|
+
for await (const chunk of stream) {
|
|
56
|
+
const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf-8");
|
|
57
|
+
if (buf.length === 0) continue;
|
|
58
|
+
chunks.push(buf);
|
|
59
|
+
totalLen += buf.length;
|
|
60
|
+
const buffer = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks, totalLen);
|
|
61
|
+
chunks.length = 0;
|
|
62
|
+
totalLen = 0;
|
|
63
|
+
let offset = 0;
|
|
64
|
+
let newlineIdx;
|
|
65
|
+
while ((newlineIdx = buffer.indexOf(10, offset)) !== -1) {
|
|
66
|
+
if (newlineIdx > offset) {
|
|
67
|
+
yield capLine(buffer.toString("utf-8", offset, newlineIdx));
|
|
68
|
+
}
|
|
69
|
+
offset = newlineIdx + 1;
|
|
70
|
+
}
|
|
71
|
+
if (offset < buffer.length) {
|
|
72
|
+
const remainder = buffer.subarray(offset);
|
|
73
|
+
chunks.push(remainder);
|
|
74
|
+
totalLen = remainder.length;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (totalLen > 0) {
|
|
78
|
+
const final = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks, totalLen);
|
|
79
|
+
yield capLine(final.toString("utf-8"));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export { ProcessManager, readLines };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createStreamingEvents, extractTokens } from './chunk-W6RSVMXR.js';
|
|
3
|
+
import { classifyAdapterError } from './chunk-2C2TFQ7K.js';
|
|
4
|
+
import { execFile } from 'child_process';
|
|
5
|
+
import { promisify } from 'util';
|
|
6
|
+
|
|
7
|
+
var execFileAsync = promisify(execFile);
|
|
8
|
+
var ClaudeAdapter = class {
|
|
9
|
+
constructor(processManager) {
|
|
10
|
+
this.processManager = processManager;
|
|
11
|
+
}
|
|
12
|
+
kind = "claude";
|
|
13
|
+
async test() {
|
|
14
|
+
try {
|
|
15
|
+
const { stdout } = await execFileAsync("claude", ["--version"]);
|
|
16
|
+
return { ok: true, version: stdout.trim() };
|
|
17
|
+
} catch (err) {
|
|
18
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
19
|
+
return {
|
|
20
|
+
ok: false,
|
|
21
|
+
error: "Claude Code CLI not found. Install: npm i -g @anthropic-ai/claude-code",
|
|
22
|
+
errorKind: classifyAdapterError(msg)
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
execute(params) {
|
|
27
|
+
const args = [
|
|
28
|
+
"--print",
|
|
29
|
+
"--output-format",
|
|
30
|
+
"stream-json",
|
|
31
|
+
"--max-turns",
|
|
32
|
+
String(params.config.max_turns ?? 50),
|
|
33
|
+
"--verbose",
|
|
34
|
+
"--dangerously-skip-permissions"
|
|
35
|
+
// Agents run autonomously; stdin is 'ignore' so prompts would hang
|
|
36
|
+
];
|
|
37
|
+
if (params.config.model) {
|
|
38
|
+
args.push("--model", params.config.model);
|
|
39
|
+
}
|
|
40
|
+
if (params.config.system_prompt) {
|
|
41
|
+
args.push("--system-prompt", params.config.system_prompt);
|
|
42
|
+
}
|
|
43
|
+
args.push(params.prompt);
|
|
44
|
+
const { process: proc, pid } = this.processManager.spawn("claude", args, {
|
|
45
|
+
cwd: params.workspace,
|
|
46
|
+
env: { ...process.env, ...params.env },
|
|
47
|
+
signal: params.signal
|
|
48
|
+
});
|
|
49
|
+
const events = createStreamingEvents(proc, parseClaudeEvent, "Claude", params.signal);
|
|
50
|
+
return { pid, events };
|
|
51
|
+
}
|
|
52
|
+
async stop(pid) {
|
|
53
|
+
await this.processManager.killWithGrace(pid);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
function parseClaudeEvent(line) {
|
|
57
|
+
if (!line.trim()) return null;
|
|
58
|
+
try {
|
|
59
|
+
const parsed = JSON.parse(line);
|
|
60
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
61
|
+
switch (parsed.type) {
|
|
62
|
+
case "assistant":
|
|
63
|
+
return { type: "output", timestamp, data: parsed.message ?? parsed };
|
|
64
|
+
case "tool_use":
|
|
65
|
+
return { type: "tool_call", timestamp, data: parsed };
|
|
66
|
+
case "tool_result":
|
|
67
|
+
return { type: "output", timestamp, data: parsed };
|
|
68
|
+
case "error": {
|
|
69
|
+
const errData = parsed.error ?? parsed;
|
|
70
|
+
const errMsg = typeof errData === "string" ? errData : JSON.stringify(errData);
|
|
71
|
+
return { type: "error", timestamp, data: errData, errorKind: classifyAdapterError(errMsg) };
|
|
72
|
+
}
|
|
73
|
+
case "result": {
|
|
74
|
+
const tokens = extractTokens(parsed, { statsFallback: true });
|
|
75
|
+
return { type: "done", timestamp, data: parsed, tokens };
|
|
76
|
+
}
|
|
77
|
+
default:
|
|
78
|
+
return { type: "output", timestamp, data: parsed };
|
|
79
|
+
}
|
|
80
|
+
} catch {
|
|
81
|
+
return { type: "output", timestamp: (/* @__PURE__ */ new Date()).toISOString(), data: line };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export { ClaudeAdapter };
|