@oxgeneral/orch 0.3.4 → 1.0.0
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 → App-GJVTVGRU.js} +55 -20
- package/dist/{agent-KBTLGGCT.js → agent-7ZJ3ZDJ7.js} +1 -1
- package/dist/{chunk-D6RFF3KN.js → chunk-4IFIOMCW.js} +4 -3
- package/dist/{chunk-S3QYSBW4.js → chunk-C6XZ3FJT.js} +6 -3
- package/dist/chunk-C6XZ3FJT.js.map +1 -0
- package/dist/{chunk-VMDQVRBR.js → chunk-GBXUNDKN.js} +16 -7
- package/dist/chunk-GBXUNDKN.js.map +1 -0
- package/dist/{chunk-W6RSVMXR.js → chunk-MGGSRXWJ.js} +5 -2
- package/dist/{chunk-B4JQM4NU.js → chunk-VG4465AG.js} +119 -45
- package/dist/chunk-VG4465AG.js.map +1 -0
- package/dist/{chunk-A36WAF2S.js → chunk-VXS2CJFH.js} +117 -43
- package/dist/{chunk-52BFUGDD.js → chunk-XJTJ2TJV.js} +3 -2
- package/dist/{claude-INM52PTH.js → claude-WUJU5KIE.js} +6 -5
- package/dist/claude-WUJU5KIE.js.map +1 -0
- package/dist/claude-ZUEKJJ4X.js +5 -0
- package/dist/cli.js +10 -10
- package/dist/{codex-DIXT44JR.js → codex-7IXXXG5U.js} +3 -3
- package/dist/{codex-QGH2GRV6.js → codex-NYJWEPRQ.js} +4 -4
- package/dist/codex-NYJWEPRQ.js.map +1 -0
- package/dist/{container-LJU4QNDH.js → container-LUWGNBSS.js} +12 -10
- package/dist/{cursor-KQJTQ73D.js → cursor-3YHVD4NP.js} +4 -4
- package/dist/cursor-3YHVD4NP.js.map +1 -0
- package/dist/{cursor-C3TR2IJC.js → cursor-622RBRHH.js} +3 -3
- package/dist/{doctor-V2FPS236.js → doctor-XSGQSD57.js} +5 -5
- package/dist/index.d.ts +4 -1
- package/dist/index.js +15 -13
- package/dist/index.js.map +1 -1
- package/dist/{init-U7MCIOB2.js → init-JU343RXK.js} +3 -3
- package/dist/opencode-FAMPSA6X.js +100 -0
- package/dist/opencode-FAMPSA6X.js.map +1 -0
- package/dist/opencode-WOR53TSC.js +98 -0
- package/dist/orchestrator-IYWBVA7J.js +5 -0
- package/dist/{orchestrator-ADO66XZ3.js.map → orchestrator-IYWBVA7J.js.map} +1 -1
- package/dist/{orchestrator-E3FQ4SOE.js → orchestrator-QNAD7MFH.js} +14 -5
- package/dist/shell-DVFHHYAZ.js +5 -0
- package/dist/{shell-JXOPKDXH.js → shell-NJNW3O6K.js} +5 -3
- package/dist/shell-NJNW3O6K.js.map +1 -0
- package/dist/{task-2TJW6Z7O.js → task-3O2OFSP6.js} +1 -1
- package/dist/template-engine-5ZKVJMYA.js +3 -0
- package/dist/{template-engine-MFL5B677.js.map → template-engine-5ZKVJMYA.js.map} +1 -1
- package/dist/template-engine-AWIS56BL.js +3 -0
- package/dist/{tui-IM3YUUVD.js → tui-LN5XHSQY.js} +1 -1
- package/package.json +2 -1
- package/readme.md +3 -3
- package/scripts/load-test.ts +478 -0
- package/dist/chunk-B4JQM4NU.js.map +0 -1
- package/dist/chunk-S3QYSBW4.js.map +0 -1
- package/dist/chunk-VMDQVRBR.js.map +0 -1
- package/dist/claude-INM52PTH.js.map +0 -1
- package/dist/claude-NHUNA5RZ.js +0 -5
- package/dist/codex-QGH2GRV6.js.map +0 -1
- package/dist/cursor-KQJTQ73D.js.map +0 -1
- package/dist/orchestrator-ADO66XZ3.js +0 -5
- package/dist/shell-3S4VLYEG.js +0 -4
- package/dist/shell-JXOPKDXH.js.map +0 -1
- package/dist/template-engine-4IZKRRHG.js +0 -3
- package/dist/template-engine-MFL5B677.js +0 -3
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { DEFAULT_PROMPT_TEMPLATE } from './chunk-
|
|
2
|
+
import { DEFAULT_PROMPT_TEMPLATE } from './chunk-VXS2CJFH.js';
|
|
3
3
|
import { DEFAULT_CONFIG } from './chunk-I3SMISEF.js';
|
|
4
4
|
import './chunk-PNE6LQRF.js';
|
|
5
|
-
import { printWarning, printSuccess, dim } from './chunk-7X2GI5OV.js';
|
|
6
5
|
import { Paths, pathExists, ensureDir, writeYaml, atomicWrite } from './chunk-LV6GDBBI.js';
|
|
6
|
+
import { printWarning, printSuccess, dim } from './chunk-7X2GI5OV.js';
|
|
7
7
|
import './chunk-2C2TFQ7K.js';
|
|
8
8
|
import path from 'path';
|
|
9
9
|
import fs from 'fs/promises';
|
|
@@ -23,7 +23,7 @@ var AGENT_CREATOR_ROLE = `Agent architect \u2014 designs and creates AI agents f
|
|
|
23
23
|
Do NOT include CLI documentation or goal-mode instructions \u2014 these are already injected by the system prompt template.
|
|
24
24
|
|
|
25
25
|
3) CHOOSE CONFIGURATION:
|
|
26
|
-
- adapter: \`claude\` (AI tasks), \`shell\` (bash scripts), \`codex\` (OpenAI Codex), \`cursor\` (Cursor IDE)
|
|
26
|
+
- adapter: \`claude\` (AI tasks), \`shell\` (bash scripts), \`codex\` (OpenAI Codex), \`cursor\` (Cursor IDE), \`opencode\` (OpenCode \u2014 multi-provider)
|
|
27
27
|
- model: \`claude-opus-4-6\` (complex/architectural), \`claude-sonnet-4-6\` (fast/routine), \`claude-haiku-4-5-20251001\` (simple/templated)
|
|
28
28
|
- approval_policy: \`auto\` (no confirmation) / \`suggest\` (proposes actions) / \`manual\` (human approval)
|
|
29
29
|
- max_turns: 50 (default), up to 100 for complex tasks
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { buildFullPrompt, createStreamingEvents } from './chunk-C6XZ3FJT.js';
|
|
2
|
+
import { createTokenUsage } from './chunk-XDVMX2FO.js';
|
|
3
|
+
import { classifyAdapterError } from './chunk-NLQAJ7TW.js';
|
|
4
|
+
import './chunk-O2MSGW3V.js';
|
|
5
|
+
import { execFile } from 'child_process';
|
|
6
|
+
import { promisify } from 'util';
|
|
7
|
+
|
|
8
|
+
var execFileAsync = promisify(execFile);
|
|
9
|
+
var OpenCodeAdapter = class {
|
|
10
|
+
constructor(processManager) {
|
|
11
|
+
this.processManager = processManager;
|
|
12
|
+
}
|
|
13
|
+
kind = "opencode";
|
|
14
|
+
async test() {
|
|
15
|
+
try {
|
|
16
|
+
const { stdout } = await execFileAsync("opencode", ["--version"]);
|
|
17
|
+
return { ok: true, version: stdout.trim() };
|
|
18
|
+
} catch (err) {
|
|
19
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
20
|
+
return {
|
|
21
|
+
ok: false,
|
|
22
|
+
error: "OpenCode CLI not found. Install: npm i -g opencode",
|
|
23
|
+
errorKind: classifyAdapterError(msg)
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
execute(params) {
|
|
28
|
+
const args = [
|
|
29
|
+
"run",
|
|
30
|
+
"--format",
|
|
31
|
+
"json"
|
|
32
|
+
];
|
|
33
|
+
if (params.config.model) {
|
|
34
|
+
args.push("--model", params.config.model);
|
|
35
|
+
}
|
|
36
|
+
const fullPrompt = buildFullPrompt(params.systemPrompt, params.prompt);
|
|
37
|
+
args.push(fullPrompt);
|
|
38
|
+
const { process: proc, pid } = this.processManager.spawn("opencode", args, {
|
|
39
|
+
cwd: params.workspace,
|
|
40
|
+
env: { ...process.env, ...params.env },
|
|
41
|
+
signal: params.signal
|
|
42
|
+
});
|
|
43
|
+
const events = createStreamingEvents(proc, parseOpenCodeEvent, "OpenCode", params.signal);
|
|
44
|
+
return { pid, events };
|
|
45
|
+
}
|
|
46
|
+
async stop(pid) {
|
|
47
|
+
await this.processManager.killWithGrace(pid);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
function parseOpenCodeEvent(line) {
|
|
51
|
+
if (!line.trim()) return null;
|
|
52
|
+
try {
|
|
53
|
+
const parsed = JSON.parse(line);
|
|
54
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
55
|
+
const type = parsed.type ?? "";
|
|
56
|
+
const part = parsed.part ?? {};
|
|
57
|
+
switch (type) {
|
|
58
|
+
case "step_start":
|
|
59
|
+
return null;
|
|
60
|
+
// lifecycle event — no user-visible content
|
|
61
|
+
case "text":
|
|
62
|
+
return { type: "output", timestamp, data: part.text ?? part };
|
|
63
|
+
case "tool_use": {
|
|
64
|
+
const state = part.state ?? {};
|
|
65
|
+
if (state.status === "error") {
|
|
66
|
+
const errMsg = typeof state.error === "string" ? state.error : JSON.stringify(state);
|
|
67
|
+
return { type: "error", timestamp, data: state, errorKind: classifyAdapterError(errMsg) };
|
|
68
|
+
}
|
|
69
|
+
return { type: "tool_call", timestamp, data: { name: part.tool, input: state.input } };
|
|
70
|
+
}
|
|
71
|
+
case "step_finish": {
|
|
72
|
+
const reason = part.reason;
|
|
73
|
+
const tokens = extractOpenCodeTokens(part);
|
|
74
|
+
if (reason === "error") {
|
|
75
|
+
const errMsg = typeof part.error === "string" ? part.error : JSON.stringify(part);
|
|
76
|
+
return { type: "error", timestamp, data: part, tokens, errorKind: classifyAdapterError(errMsg) };
|
|
77
|
+
}
|
|
78
|
+
if (reason === "tool-calls") {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
return { type: "done", timestamp, data: part, tokens };
|
|
82
|
+
}
|
|
83
|
+
default:
|
|
84
|
+
return { type: "output", timestamp, data: parsed };
|
|
85
|
+
}
|
|
86
|
+
} catch {
|
|
87
|
+
return { type: "output", timestamp: (/* @__PURE__ */ new Date()).toISOString(), data: line };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function extractOpenCodeTokens(part) {
|
|
91
|
+
const tokens = part.tokens;
|
|
92
|
+
if (!tokens || typeof tokens.input !== "number") return void 0;
|
|
93
|
+
const input = tokens.input;
|
|
94
|
+
const output = typeof tokens.output === "number" ? tokens.output : 0;
|
|
95
|
+
return createTokenUsage(input, output);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export { OpenCodeAdapter };
|
|
99
|
+
//# sourceMappingURL=opencode-FAMPSA6X.js.map
|
|
100
|
+
//# sourceMappingURL=opencode-FAMPSA6X.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/infrastructure/adapters/opencode.ts"],"names":[],"mappings":"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","file":"opencode-FAMPSA6X.js","sourcesContent":["/**\n * OpenCode adapter.\n *\n * Spawns `opencode run --format json` in headless mode.\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 { createStreamingEvents, buildFullPrompt } from './utils.js';\nimport { classifyAdapterError } from '../../domain/errors.js';\nimport { createTokenUsage } from '../../domain/run.js';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nconst execFileAsync = promisify(execFile);\n\nexport class OpenCodeAdapter implements IAgentAdapter {\n readonly kind = 'opencode';\n\n constructor(private readonly processManager: IProcessManager) {}\n\n async test(): Promise<AdapterTestResult> {\n try {\n const { stdout } = await execFileAsync('opencode', ['--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: 'OpenCode CLI not found. Install: npm i -g opencode',\n errorKind: classifyAdapterError(msg),\n };\n }\n }\n\n execute(params: ExecuteParams): ExecuteHandle {\n const args = [\n 'run',\n '--format', 'json',\n ];\n\n if (params.config.model) {\n args.push('--model', params.config.model);\n }\n\n // OpenCode has no native --system-prompt; prepend to user prompt\n const fullPrompt = buildFullPrompt(params.systemPrompt, params.prompt);\n args.push(fullPrompt);\n\n const { process: proc, pid } = this.processManager.spawn('opencode', args, {\n cwd: params.workspace,\n env: { ...process.env, ...params.env },\n signal: params.signal,\n });\n\n const events = createStreamingEvents(proc, parseOpenCodeEvent, 'OpenCode', 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 parseOpenCodeEvent(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 const type = (parsed.type as string) ?? '';\n const part = (parsed.part as Record<string, unknown>) ?? {};\n\n switch (type) {\n case 'step_start':\n return null; // lifecycle event — no user-visible content\n\n case 'text':\n return { type: 'output', timestamp, data: part.text ?? part };\n\n case 'tool_use': {\n const state = (part.state as Record<string, unknown>) ?? {};\n if (state.status === 'error') {\n const errMsg = typeof state.error === 'string' ? state.error : JSON.stringify(state);\n return { type: 'error', timestamp, data: state, errorKind: classifyAdapterError(errMsg) };\n }\n // Map to { name, input } shape expected by TUI formatToolInput\n return { type: 'tool_call', timestamp, data: { name: part.tool, input: state.input } };\n }\n\n case 'step_finish': {\n const reason = part.reason as string | undefined;\n const tokens = extractOpenCodeTokens(part);\n\n if (reason === 'error') {\n const errMsg = typeof part.error === 'string' ? part.error : JSON.stringify(part);\n return { type: 'error', timestamp, data: part, tokens, errorKind: classifyAdapterError(errMsg) };\n }\n if (reason === 'tool-calls') {\n return null; // intermediate lifecycle — tool_use events carry the actual content\n }\n // reason === 'stop', 'max_tokens', or any other terminal reason → done\n return { type: 'done', timestamp, data: part, tokens };\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\n/** Extract token usage from opencode step_finish part. */\nfunction extractOpenCodeTokens(part: Record<string, unknown>): { input: number; output: number; total: number } | undefined {\n const tokens = part.tokens as Record<string, unknown> | undefined;\n if (!tokens || typeof tokens.input !== 'number') return undefined;\n\n const input = tokens.input;\n const output = typeof tokens.output === 'number' ? tokens.output : 0;\n return createTokenUsage(input, output);\n}\n"]}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { buildFullPrompt, createStreamingEvents, createTokenUsage } from './chunk-MGGSRXWJ.js';
|
|
3
|
+
import { classifyAdapterError } from './chunk-2C2TFQ7K.js';
|
|
4
|
+
import './chunk-CHIP7O6V.js';
|
|
5
|
+
import { execFile } from 'child_process';
|
|
6
|
+
import { promisify } from 'util';
|
|
7
|
+
|
|
8
|
+
var execFileAsync = promisify(execFile);
|
|
9
|
+
var OpenCodeAdapter = class {
|
|
10
|
+
constructor(processManager) {
|
|
11
|
+
this.processManager = processManager;
|
|
12
|
+
}
|
|
13
|
+
kind = "opencode";
|
|
14
|
+
async test() {
|
|
15
|
+
try {
|
|
16
|
+
const { stdout } = await execFileAsync("opencode", ["--version"]);
|
|
17
|
+
return { ok: true, version: stdout.trim() };
|
|
18
|
+
} catch (err) {
|
|
19
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
20
|
+
return {
|
|
21
|
+
ok: false,
|
|
22
|
+
error: "OpenCode CLI not found. Install: npm i -g opencode",
|
|
23
|
+
errorKind: classifyAdapterError(msg)
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
execute(params) {
|
|
28
|
+
const args = [
|
|
29
|
+
"run",
|
|
30
|
+
"--format",
|
|
31
|
+
"json"
|
|
32
|
+
];
|
|
33
|
+
if (params.config.model) {
|
|
34
|
+
args.push("--model", params.config.model);
|
|
35
|
+
}
|
|
36
|
+
const fullPrompt = buildFullPrompt(params.systemPrompt, params.prompt);
|
|
37
|
+
args.push(fullPrompt);
|
|
38
|
+
const { process: proc, pid } = this.processManager.spawn("opencode", args, {
|
|
39
|
+
cwd: params.workspace,
|
|
40
|
+
env: { ...process.env, ...params.env },
|
|
41
|
+
signal: params.signal
|
|
42
|
+
});
|
|
43
|
+
const events = createStreamingEvents(proc, parseOpenCodeEvent, "OpenCode", params.signal);
|
|
44
|
+
return { pid, events };
|
|
45
|
+
}
|
|
46
|
+
async stop(pid) {
|
|
47
|
+
await this.processManager.killWithGrace(pid);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
function parseOpenCodeEvent(line) {
|
|
51
|
+
if (!line.trim()) return null;
|
|
52
|
+
try {
|
|
53
|
+
const parsed = JSON.parse(line);
|
|
54
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
55
|
+
const type = parsed.type ?? "";
|
|
56
|
+
const part = parsed.part ?? {};
|
|
57
|
+
switch (type) {
|
|
58
|
+
case "step_start":
|
|
59
|
+
return null;
|
|
60
|
+
// lifecycle event — no user-visible content
|
|
61
|
+
case "text":
|
|
62
|
+
return { type: "output", timestamp, data: part.text ?? part };
|
|
63
|
+
case "tool_use": {
|
|
64
|
+
const state = part.state ?? {};
|
|
65
|
+
if (state.status === "error") {
|
|
66
|
+
const errMsg = typeof state.error === "string" ? state.error : JSON.stringify(state);
|
|
67
|
+
return { type: "error", timestamp, data: state, errorKind: classifyAdapterError(errMsg) };
|
|
68
|
+
}
|
|
69
|
+
return { type: "tool_call", timestamp, data: { name: part.tool, input: state.input } };
|
|
70
|
+
}
|
|
71
|
+
case "step_finish": {
|
|
72
|
+
const reason = part.reason;
|
|
73
|
+
const tokens = extractOpenCodeTokens(part);
|
|
74
|
+
if (reason === "error") {
|
|
75
|
+
const errMsg = typeof part.error === "string" ? part.error : JSON.stringify(part);
|
|
76
|
+
return { type: "error", timestamp, data: part, tokens, errorKind: classifyAdapterError(errMsg) };
|
|
77
|
+
}
|
|
78
|
+
if (reason === "tool-calls") {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
return { type: "done", timestamp, data: part, tokens };
|
|
82
|
+
}
|
|
83
|
+
default:
|
|
84
|
+
return { type: "output", timestamp, data: parsed };
|
|
85
|
+
}
|
|
86
|
+
} catch {
|
|
87
|
+
return { type: "output", timestamp: (/* @__PURE__ */ new Date()).toISOString(), data: line };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function extractOpenCodeTokens(part) {
|
|
91
|
+
const tokens = part.tokens;
|
|
92
|
+
if (!tokens || typeof tokens.input !== "number") return void 0;
|
|
93
|
+
const input = tokens.input;
|
|
94
|
+
const output = typeof tokens.output === "number" ? tokens.output : 0;
|
|
95
|
+
return createTokenUsage(input, output);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export { OpenCodeAdapter };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"orchestrator-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"orchestrator-IYWBVA7J.js"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { DEFAULT_SYSTEM_TEMPLATE, DEFAULT_USER_TEMPLATE, buildPromptContext } from './chunk-VXS2CJFH.js';
|
|
3
3
|
import { resolveFailureStatus, isDispatchable, isTerminal, isBlocked, resolveCompletionStatus, calculateRetryDelay } from './chunk-U2VDNUZL.js';
|
|
4
4
|
import { AUTONOMOUS_LABEL } from './chunk-PNE6LQRF.js';
|
|
5
5
|
import { LockConflictError, WorkspaceError, TaskAlreadyRunningError, NoAgentsError, classifyAdapterError } from './chunk-2C2TFQ7K.js';
|
|
@@ -896,7 +896,9 @@ Agent role: ${role}` : `Autonomous work cycle. Agent role: ${role}`;
|
|
|
896
896
|
agent,
|
|
897
897
|
this.deps.config
|
|
898
898
|
);
|
|
899
|
-
const
|
|
899
|
+
const systemTemplate = this.deps.config.prompt?.system_template ?? DEFAULT_SYSTEM_TEMPLATE;
|
|
900
|
+
const userTemplate = this.deps.config.prompt?.user_template ?? DEFAULT_USER_TEMPLATE;
|
|
901
|
+
const legacyTemplate = this.deps.config.prompt?.template;
|
|
900
902
|
const attempt = task.attempts + 1;
|
|
901
903
|
let retryContext;
|
|
902
904
|
if (attempt > 1) {
|
|
@@ -919,14 +921,13 @@ Agent role: ${role}` : `Autonomous work cycle. Agent role: ${role}`;
|
|
|
919
921
|
const allTasks = await this.cachedTaskStore.list();
|
|
920
922
|
const goalTasks = allTasks.filter((t) => t.goalId === goalId);
|
|
921
923
|
const progressEntry = await this.deps.contextStore?.get(`${goalId}-progress`);
|
|
922
|
-
const MAX_GOAL_TASK_NAMES = 30;
|
|
923
924
|
const taskNames = goalTasks.map((t) => `[${t.status}] ${t.title}`);
|
|
924
925
|
goalContext = {
|
|
925
926
|
id: goalRaw.id,
|
|
926
927
|
title: goalRaw.title,
|
|
927
928
|
description: goalRaw.description,
|
|
928
929
|
status: goalRaw.status,
|
|
929
|
-
task_names: taskNames
|
|
930
|
+
task_names: taskNames,
|
|
930
931
|
progress: progressEntry?.value
|
|
931
932
|
};
|
|
932
933
|
}
|
|
@@ -938,7 +939,14 @@ Agent role: ${role}` : `Autonomous work cycle. Agent role: ${role}`;
|
|
|
938
939
|
this.deps.config,
|
|
939
940
|
{ allAgents, retryContext, sharedContext, feedback: task.feedback, messages: pendingMessages.length ? pendingMessages : void 0, goal: goalContext }
|
|
940
941
|
);
|
|
941
|
-
|
|
942
|
+
let prompt;
|
|
943
|
+
let systemPrompt;
|
|
944
|
+
if (legacyTemplate) {
|
|
945
|
+
prompt = await this.deps.templateEngine.render(legacyTemplate, context);
|
|
946
|
+
} else {
|
|
947
|
+
systemPrompt = await this.deps.templateEngine.render(systemTemplate, context);
|
|
948
|
+
prompt = await this.deps.templateEngine.render(userTemplate, context);
|
|
949
|
+
}
|
|
942
950
|
const run = await this.deps.runService.create({
|
|
943
951
|
taskId: task.id,
|
|
944
952
|
agentId: agent.id,
|
|
@@ -969,6 +977,7 @@ Agent role: ${role}` : `Autonomous work cycle. Agent role: ${role}`;
|
|
|
969
977
|
this.abortControllers.set(taskId, abortController);
|
|
970
978
|
const handle = adapter.execute({
|
|
971
979
|
prompt,
|
|
980
|
+
systemPrompt,
|
|
972
981
|
workspace: workspacePath,
|
|
973
982
|
env: {
|
|
974
983
|
...agent.config.env,
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { buildFullPrompt } from './chunk-C6XZ3FJT.js';
|
|
2
|
+
import './chunk-XDVMX2FO.js';
|
|
1
3
|
import { classifyAdapterError } from './chunk-NLQAJ7TW.js';
|
|
2
4
|
import { readLines } from './chunk-O2MSGW3V.js';
|
|
3
5
|
import { execFile } from 'child_process';
|
|
@@ -144,7 +146,7 @@ var ShellAdapter = class {
|
|
|
144
146
|
env: {
|
|
145
147
|
...process.env,
|
|
146
148
|
...params.env,
|
|
147
|
-
ORCHESTRY_TASK_PROMPT: params.prompt
|
|
149
|
+
ORCHESTRY_TASK_PROMPT: buildFullPrompt(params.systemPrompt, params.prompt)
|
|
148
150
|
},
|
|
149
151
|
signal: params.signal
|
|
150
152
|
});
|
|
@@ -217,5 +219,5 @@ var ShellAdapter = class {
|
|
|
217
219
|
};
|
|
218
220
|
|
|
219
221
|
export { ShellAdapter };
|
|
220
|
-
//# sourceMappingURL=shell-
|
|
221
|
-
//# sourceMappingURL=shell-
|
|
222
|
+
//# sourceMappingURL=shell-NJNW3O6K.js.map
|
|
223
|
+
//# sourceMappingURL=shell-NJNW3O6K.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/infrastructure/adapters/event-buffer.ts","../src/infrastructure/adapters/shell.ts"],"names":[],"mappings":"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","file":"shell-NJNW3O6K.js","sourcesContent":["/**\n * Lock-free ring buffer for AgentEvent streaming.\n *\n * Replaces Array.shift() O(n) polling with O(1) dequeue\n * and event-driven notification instead of 50ms busy-wait.\n * Includes backpressure: when buffer is full, push() returns\n * a promise that resolves when space is available.\n */\n\nimport type { AgentEvent } from './interface.js';\n\nconst DEFAULT_CAPACITY = 1024;\n\ninterface Deferred<T> {\n promise: Promise<T>;\n resolve: (value: T) => void;\n}\n\nfunction deferred<T>(): Deferred<T> {\n let resolve!: (value: T) => void;\n const promise = new Promise<T>((r) => { resolve = r; });\n return { promise, resolve };\n}\n\nexport class EventBuffer {\n private buf: (AgentEvent | undefined)[];\n private head = 0; // read index\n private tail = 0; // write index\n private count = 0;\n private readonly capacity: number;\n\n // Consumer notification: resolved when new data is available\n private dataReady: Deferred<void> | null = null;\n // Producer notification: resolved when space is available\n private spaceReady: Deferred<void> | null = null;\n\n private closed = false;\n\n constructor(capacity = DEFAULT_CAPACITY) {\n this.capacity = capacity;\n this.buf = new Array(capacity);\n }\n\n /** Number of buffered events. */\n get size(): number {\n return this.count;\n }\n\n get isFull(): boolean {\n return this.count >= this.capacity;\n }\n\n /**\n * Push an event into the buffer.\n * If the buffer is full, waits until space is available (backpressure).\n */\n async push(event: AgentEvent): Promise<void> {\n while (this.isFull && !this.closed) {\n if (!this.spaceReady) {\n this.spaceReady = deferred<void>();\n }\n await this.spaceReady.promise;\n }\n if (this.closed) return;\n\n this.buf[this.tail] = event;\n this.tail = (this.tail + 1) % this.capacity;\n this.count++;\n\n // Wake up consumer if waiting\n if (this.dataReady) {\n const dr = this.dataReady;\n this.dataReady = null;\n dr.resolve();\n }\n }\n\n /**\n * Dequeue the next event. O(1).\n * Returns undefined only when buffer is empty AND closed.\n */\n async take(): Promise<AgentEvent | undefined> {\n while (this.count === 0) {\n if (this.closed) return undefined;\n if (!this.dataReady) {\n this.dataReady = deferred<void>();\n }\n await this.dataReady.promise;\n }\n\n const event = this.buf[this.head];\n this.buf[this.head] = undefined; // allow GC\n this.head = (this.head + 1) % this.capacity;\n this.count--;\n\n // Wake up producer if waiting for space\n if (this.spaceReady) {\n const sr = this.spaceReady;\n this.spaceReady = null;\n sr.resolve();\n }\n\n return event;\n }\n\n /**\n * Signal that no more events will be pushed.\n * Wakes up any waiting consumer/producer.\n */\n close(): void {\n this.closed = true;\n if (this.dataReady) {\n const dr = this.dataReady;\n this.dataReady = null;\n dr.resolve();\n }\n if (this.spaceReady) {\n const sr = this.spaceReady;\n this.spaceReady = null;\n sr.resolve();\n }\n }\n\n get isClosed(): boolean {\n return this.closed;\n }\n\n /**\n * Async iterator that drains the buffer until closed and empty.\n */\n async *[Symbol.asyncIterator](): AsyncGenerator<AgentEvent> {\n while (true) {\n const event = await this.take();\n if (event === undefined) return;\n yield event;\n }\n }\n}\n","/**\n * Shell adapter.\n *\n * Spawns an arbitrary command via `bash -lc`.\n * Task prompt is passed via ORCHESTRY_TASK_PROMPT env variable.\n * Consumes stdout and stderr concurrently to avoid deadlocks.\n */\n\nimport type { IAgentAdapter, AdapterTestResult, ExecuteParams, AgentEvent, ExecuteHandle } from './interface.js';\nimport type { IProcessManager } from '../process/process-manager.js';\nimport { buildFullPrompt } from './utils.js';\nimport { readLines } from '../process/process-manager.js';\nimport { EventBuffer } from './event-buffer.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 ShellAdapter implements IAgentAdapter {\n readonly kind = 'shell';\n\n constructor(private readonly processManager: IProcessManager) {}\n\n async test(): Promise<AdapterTestResult> {\n try {\n const { stdout } = await execFileAsync('bash', ['--version']);\n const version = stdout.split('\\n')[0]?.trim() ?? 'unknown';\n return { ok: true, version };\n } catch {\n return { ok: false, error: 'bash not found', errorKind: classifyAdapterError('bash not found') };\n }\n }\n\n execute(params: ExecuteParams): ExecuteHandle {\n const command = params.config.command;\n if (!command) {\n // Return a handle that immediately yields an error\n async function* errorGen(): AsyncGenerator<AgentEvent> {\n yield {\n type: 'error',\n timestamp: new Date().toISOString(),\n data: 'Shell adapter requires a command in agent config',\n errorKind: AdapterErrorKind.SPAWN_FAILED,\n };\n }\n return { pid: 0, events: errorGen() };\n }\n\n const { process: proc, pid } = this.processManager.spawn('bash', ['-lc', command], {\n cwd: params.workspace,\n env: {\n ...process.env,\n ...params.env,\n ORCHESTRY_TASK_PROMPT: buildFullPrompt(params.systemPrompt, params.prompt),\n },\n signal: params.signal,\n });\n\n const signal = params.signal;\n const processManager = this.processManager;\n\n async function* generateEvents(): AsyncGenerator<AgentEvent> {\n // Ring buffer with backpressure replaces Array.shift() polling\n const buffer = new EventBuffer();\n\n // Ensure process is reaped on abort — SIGTERM + grace period + SIGKILL\n const onAbort = () => {\n processManager.killWithGrace(pid, 5_000).catch(() => {});\n };\n if (signal) {\n if (signal.aborted) {\n onAbort();\n } else {\n signal.addEventListener('abort', onAbort, { once: true });\n }\n }\n\n const stdoutPromise = (async () => {\n if (!proc.stdout) return;\n for await (const line of readLines(proc.stdout)) {\n if (signal?.aborted) break;\n await buffer.push({\n type: 'output',\n timestamp: new Date().toISOString(),\n data: line,\n });\n }\n })();\n\n const stderrPromise = (async () => {\n if (!proc.stderr) return;\n for await (const line of readLines(proc.stderr)) {\n if (signal?.aborted) break;\n await buffer.push({\n type: 'error',\n timestamp: new Date().toISOString(),\n data: line,\n errorKind: classifyAdapterError(line),\n });\n }\n })();\n\n // Close the buffer once both streams are drained (or on error)\n void Promise.all([stdoutPromise, stderrPromise]).then(\n () => buffer.close(),\n () => buffer.close(),\n );\n\n // Yield events as they arrive — no polling, no busy-wait\n yield* buffer;\n\n // Clean up abort listener\n if (signal && !signal.aborted) {\n signal.removeEventListener('abort', onAbort);\n }\n\n // Wait for process to exit\n await new Promise<void>((resolve, reject) => {\n // If process already exited, resolve immediately\n if (proc.exitCode !== null || proc.killed) {\n resolve();\n return;\n }\n proc.on('close', (code) => {\n if (code === 0 || signal?.aborted) {\n resolve();\n } else {\n reject(new Error(`Shell command exited with code ${code}`));\n }\n });\n proc.on('error', reject);\n });\n }\n\n return { pid, events: generateEvents() };\n }\n\n async stop(pid: number): Promise<void> {\n await this.processManager.killWithGrace(pid);\n }\n}\n"]}
|
|
@@ -193,7 +193,7 @@ function registerTaskCommand(program, container) {
|
|
|
193
193
|
await container.paths.requireInit();
|
|
194
194
|
const task2 = await container.taskService.get(id);
|
|
195
195
|
if (task2.status === "in_progress") {
|
|
196
|
-
const { buildFullContainer } = await import('./container-
|
|
196
|
+
const { buildFullContainer } = await import('./container-LUWGNBSS.js');
|
|
197
197
|
const full = await buildFullContainer(container.context);
|
|
198
198
|
await full.orchestrator.cancelTask(id);
|
|
199
199
|
} else {
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { DEFAULT_PROMPT_TEMPLATE, DEFAULT_SYSTEM_TEMPLATE, DEFAULT_USER_TEMPLATE, LiquidTemplateEngine, buildPromptContext, filterRelevantContext } from './chunk-VG4465AG.js';
|
|
2
|
+
//# sourceMappingURL=template-engine-5ZKVJMYA.js.map
|
|
3
|
+
//# sourceMappingURL=template-engine-5ZKVJMYA.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"template-engine-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"template-engine-5ZKVJMYA.js"}
|
|
@@ -8,7 +8,7 @@ function registerTuiCommand(program, container) {
|
|
|
8
8
|
const state = await container.stateStore.read();
|
|
9
9
|
const { render } = await import('ink');
|
|
10
10
|
const { createElement } = await import('react');
|
|
11
|
-
const { App } = await import('./App-
|
|
11
|
+
const { App } = await import('./App-GJVTVGRU.js');
|
|
12
12
|
const onRunTask = async (taskId) => {
|
|
13
13
|
await container.orchestrator.runTask(taskId);
|
|
14
14
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oxgeneral/orch",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Agents Organizations — CLI orchestrator for AI agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"clean": "rm -rf dist",
|
|
35
35
|
"postinstall": "node scripts/postinstall.js || true",
|
|
36
36
|
"benchmark": "tsx scripts/benchmark.ts",
|
|
37
|
+
"load-test": "tsx scripts/load-test.ts",
|
|
37
38
|
"prepublishOnly": "npm run build"
|
|
38
39
|
},
|
|
39
40
|
"keywords": [
|
package/readme.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<img src="assets/logo.svg" alt="ORCH" height="60" />
|
|
3
3
|
<p align="center">
|
|
4
4
|
<strong>Stop babysitting AI agents. Start orchestrating them.</strong><br/>
|
|
5
|
-
One CLI to run Claude, Codex, Cursor, and shell scripts as a team — in parallel, with retries, from your terminal.
|
|
5
|
+
One CLI to run Claude, OpenCode, Codex, Cursor, and shell scripts as a team — in parallel, with retries, from your terminal.
|
|
6
6
|
</p>
|
|
7
7
|
<p align="center">
|
|
8
8
|
<a href="https://github.com/oxgeneral/ORCH/stargazers"><img src="https://img.shields.io/github/stars/oxgeneral/ORCH?style=social" alt="GitHub Stars" /></a>
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<a href="https://www.npmjs.com/package/@oxgeneral/orch"><img src="https://img.shields.io/npm/v/@oxgeneral/orch?color=cb0000" alt="npm" /></a>
|
|
11
11
|
<a href="#get-started-in-30-seconds"><img src="https://img.shields.io/badge/setup-one%20command-brightgreen" alt="One command setup" /></a>
|
|
12
12
|
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue" alt="MIT License" /></a>
|
|
13
|
-
<a href="#development"><img src="https://img.shields.io/badge/tests-
|
|
13
|
+
<a href="#development"><img src="https://img.shields.io/badge/tests-1493%20passing-brightgreen" alt="Tests" /></a>
|
|
14
14
|
<a href="#architecture"><img src="https://img.shields.io/badge/TypeScript-strict-blue" alt="TypeScript strict" /></a>
|
|
15
15
|
</p>
|
|
16
16
|
</p>
|
|
@@ -224,7 +224,7 @@ src/
|
|
|
224
224
|
│ └── errors.ts # Domain error types
|
|
225
225
|
├── application/ # Orchestrator engine, services, event bus
|
|
226
226
|
├── infrastructure/
|
|
227
|
-
│ ├── adapters/ # Claude, Codex, Cursor, Shell (pluggable)
|
|
227
|
+
│ ├── adapters/ # Claude, OpenCode, Codex, Cursor, Shell (pluggable)
|
|
228
228
|
│ ├── storage/ # File-based (YAML/JSON/JSONL)
|
|
229
229
|
│ ├── process/ # PID management, graceful kill
|
|
230
230
|
│ ├── template/ # LiquidJS template engine
|