@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
@@ -1,12 +1,14 @@
1
1
  #!/usr/bin/env node
2
- import { DEFAULT_PROMPT_TEMPLATE } from './chunk-A36WAF2S.js';
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';
10
+ import { execFile } from 'child_process';
11
+ import { promisify } from 'util';
10
12
 
11
13
  // src/domain/default-agents.ts
12
14
  var AGENT_CREATOR_ROLE = `Agent architect \u2014 designs and creates AI agents for the orchestrator via \`orch agent add\`.
@@ -23,7 +25,7 @@ var AGENT_CREATOR_ROLE = `Agent architect \u2014 designs and creates AI agents f
23
25
  Do NOT include CLI documentation or goal-mode instructions \u2014 these are already injected by the system prompt template.
24
26
 
25
27
  3) CHOOSE CONFIGURATION:
26
- - adapter: \`claude\` (AI tasks), \`shell\` (bash scripts), \`codex\` (OpenAI Codex), \`cursor\` (Cursor IDE)
28
+ - adapter: \`claude\` (AI tasks), \`shell\` (bash scripts), \`codex\` (OpenAI Codex), \`cursor\` (Cursor IDE), \`opencode\` (OpenCode \u2014 multi-provider)
27
29
  - model: \`claude-opus-4-6\` (complex/architectural), \`claude-sonnet-4-6\` (fast/routine), \`claude-haiku-4-5-20251001\` (simple/templated)
28
30
  - approval_policy: \`auto\` (no confirmation) / \`suggest\` (proposes actions) / \`manual\` (human approval)
29
31
  - max_turns: 50 (default), up to 100 for complex tasks
@@ -76,6 +78,7 @@ function getDefaultAgents() {
76
78
  }
77
79
 
78
80
  // src/cli/commands/init.ts
81
+ var execFileAsync = promisify(execFile);
79
82
  async function runInit(opts = {}) {
80
83
  const projectRoot = process.cwd();
81
84
  const paths = new Paths(projectRoot);
@@ -91,8 +94,12 @@ async function runInit(opts = {}) {
91
94
  ensureDir(paths.templatesDir),
92
95
  ensureDir(paths.logsDir)
93
96
  ]);
94
- const config = { ...DEFAULT_CONFIG };
97
+ const gitAvailable = await ensureGitRepo(projectRoot);
98
+ const config = structuredClone(DEFAULT_CONFIG);
95
99
  config.project.name = opts.name ?? path.basename(projectRoot);
100
+ if (!gitAvailable) {
101
+ config.defaults.agent.workspace_mode = "shared";
102
+ }
96
103
  const gitignoreContent = [
97
104
  "# Runtime state",
98
105
  "state.json",
@@ -126,6 +133,9 @@ async function runInit(opts = {}) {
126
133
  ...defaultAgents.map((agent) => writeYaml(paths.agentPath(agent.id), agent))
127
134
  ]);
128
135
  await ensureRootGitignore(projectRoot);
136
+ if (gitAvailable) {
137
+ await ensureGitCommit(projectRoot);
138
+ }
129
139
  console.log();
130
140
  printSuccess("initialized");
131
141
  console.log();
@@ -140,6 +150,30 @@ async function runInit(opts = {}) {
140
150
  console.log(` ${dim("\u2514\u2500\u2500")} .gitignore`);
141
151
  console.log();
142
152
  }
153
+ async function ensureGitRepo(projectRoot) {
154
+ try {
155
+ await execFileAsync("git", ["rev-parse", "--is-inside-work-tree"], { cwd: projectRoot });
156
+ return true;
157
+ } catch {
158
+ try {
159
+ await execFileAsync("git", ["init"], { cwd: projectRoot });
160
+ return true;
161
+ } catch {
162
+ return false;
163
+ }
164
+ }
165
+ }
166
+ async function ensureGitCommit(projectRoot) {
167
+ try {
168
+ await execFileAsync("git", ["rev-parse", "HEAD"], { cwd: projectRoot });
169
+ } catch {
170
+ try {
171
+ await execFileAsync("git", ["add", "-A"], { cwd: projectRoot });
172
+ await execFileAsync("git", ["commit", "-m", "Initial commit", "--allow-empty"], { cwd: projectRoot });
173
+ } catch {
174
+ }
175
+ }
176
+ }
143
177
  async function ensureRootGitignore(projectRoot) {
144
178
  const gitignorePath = path.join(projectRoot, ".gitignore");
145
179
  try {
@@ -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,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { DEFAULT_PROMPT_TEMPLATE, buildPromptContext } from './chunk-A36WAF2S.js';
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 template = this.deps.config.prompt?.template ?? DEFAULT_PROMPT_TEMPLATE;
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.length > MAX_GOAL_TASK_NAMES ? [...taskNames.slice(0, MAX_GOAL_TASK_NAMES), `... and ${taskNames.length - MAX_GOAL_TASK_NAMES} more`] : 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
- const prompt = await this.deps.templateEngine.render(template, context);
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,
@@ -955,9 +963,12 @@ Agent role: ${role}` : `Autonomous work cycle. Agent role: ${role}`;
955
963
  await this.deps.taskService.assign(taskId, agent.id);
956
964
  await this.deps.taskService.incrementAttempts(taskId);
957
965
  if (worktreeBranch) {
958
- task.proof = { ...task.proof ?? { files_changed: [] }, branch: worktreeBranch };
959
- task.workspace = workspacePath;
960
- await this.deps.taskStore.save(task);
966
+ const freshTask = await this.deps.taskStore.get(taskId);
967
+ if (freshTask) {
968
+ freshTask.proof = { ...freshTask.proof ?? { files_changed: [] }, branch: worktreeBranch };
969
+ freshTask.workspace = workspacePath;
970
+ await this.deps.taskStore.save(freshTask);
971
+ }
961
972
  }
962
973
  await this.deps.agentService.setStatus(agent.id, "running");
963
974
  const agentData = await this.deps.agentService.get(agent.id);
@@ -969,6 +980,7 @@ Agent role: ${role}` : `Autonomous work cycle. Agent role: ${role}`;
969
980
  this.abortControllers.set(taskId, abortController);
970
981
  const handle = adapter.execute({
971
982
  prompt,
983
+ systemPrompt,
972
984
  workspace: workspacePath,
973
985
  env: {
974
986
  ...agent.config.env,
@@ -1044,11 +1056,15 @@ Agent role: ${role}` : `Autonomous work cycle. Agent role: ${role}`;
1044
1056
  if (typeof p === "string") filesChangedSet.add(p);
1045
1057
  }
1046
1058
  } else {
1047
- const filePath = data && typeof data.path === "string" ? data.path : typeof event.data === "string" ? event.data : String(event.data);
1048
- filesChangedSet.add(filePath);
1059
+ const filePath2 = data && typeof data.path === "string" ? data.path : typeof event.data === "string" ? event.data : String(event.data);
1060
+ filesChangedSet.add(filePath2);
1049
1061
  }
1050
1062
  }
1051
1063
  const eventTimestamp = isValidISOTimestamp(event.timestamp) ? event.timestamp : (/* @__PURE__ */ new Date()).toISOString();
1064
+ const filePath = event.type === "file_change" ? (() => {
1065
+ const d = event.data;
1066
+ return d && typeof d.path === "string" ? d.path : typeof event.data === "string" ? event.data : String(event.data);
1067
+ })() : null;
1052
1068
  const serialized = serializeEventData(event.data, MAX_EVENT_DATA_LEN);
1053
1069
  event.data = void 0;
1054
1070
  const runEvent = {
@@ -1074,7 +1090,7 @@ Agent role: ${role}` : `Autonomous work cycle. Agent role: ${role}`;
1074
1090
  type: "agent:file_changed",
1075
1091
  runId,
1076
1092
  agentId,
1077
- path: typeof event.data === "string" ? event.data : String(event.data)
1093
+ path: filePath
1078
1094
  });
1079
1095
  } else if (event.type === "error") {
1080
1096
  if (event.errorKind) lastErrorKind = event.errorKind;
@@ -1212,7 +1228,7 @@ Agent role: ${role}` : `Autonomous work cycle. Agent role: ${role}`;
1212
1228
  await this.deps.agentStore.save(agentAfter);
1213
1229
  }
1214
1230
  if (newStatus === "review" && task.review_criteria?.length) {
1215
- await this.runAutoReview(taskId, task.review_criteria, task.workspace ?? this.deps.projectRoot);
1231
+ await this.runAutoReview(taskId, task.review_criteria, task.workspace ?? this.deps.projectRoot, autoApprove);
1216
1232
  } else if (newStatus === "review" && autoApprove) {
1217
1233
  await this.deps.taskService.updateStatus(taskId, "done");
1218
1234
  }
@@ -1287,7 +1303,7 @@ Agent role: ${role}` : `Autonomous work cycle. Agent role: ${role}`;
1287
1303
  * If all criteria pass, transition review → done.
1288
1304
  * If any fail, stay in review with results attached.
1289
1305
  */
1290
- async runAutoReview(taskId, criteria, cwd) {
1306
+ async runAutoReview(taskId, criteria, cwd, autoApprove = false) {
1291
1307
  const runner = new ReviewRunner({ cwd });
1292
1308
  const results = await runner.runAll(criteria);
1293
1309
  const allPassed = ReviewRunner.allPassed(results);
@@ -1306,7 +1322,15 @@ Agent role: ${role}` : `Autonomous work cycle. Agent role: ${role}`;
1306
1322
  passed: allPassed,
1307
1323
  results
1308
1324
  });
1309
- if (allPassed) {
1325
+ if (allPassed || autoApprove) {
1326
+ if (!allPassed) {
1327
+ this.deps.eventBus.emit({
1328
+ type: "orchestrator:error",
1329
+ error: `Review criteria failed for task ${taskId} but autoApprove is set \u2014 force-approving`,
1330
+ context: "auto-review-with-auto-approve",
1331
+ fatal: false
1332
+ });
1333
+ }
1310
1334
  try {
1311
1335
  await this.deps.taskService.updateStatus(taskId, "done");
1312
1336
  } catch (validationErr) {
@@ -0,0 +1,5 @@
1
+ export { Orchestrator } from './chunk-O2OQCSBL.js';
2
+ import './chunk-VG4465AG.js';
3
+ import './chunk-NLQAJ7TW.js';
4
+ //# sourceMappingURL=orchestrator-X2CWGFCL.js.map
5
+ //# sourceMappingURL=orchestrator-X2CWGFCL.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"orchestrator-ADO66XZ3.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"orchestrator-X2CWGFCL.js"}
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ export { ShellAdapter } from './chunk-XJTJ2TJV.js';
3
+ import './chunk-MGGSRXWJ.js';
4
+ import './chunk-2C2TFQ7K.js';
5
+ import './chunk-CHIP7O6V.js';
@@ -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-JXOPKDXH.js.map
221
- //# sourceMappingURL=shell-JXOPKDXH.js.map
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-LJU4QNDH.js');
196
+ const { buildFullContainer } = await import('./container-RY54L3XC.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-MFL5B677.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"template-engine-5ZKVJMYA.js"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export { DEFAULT_PROMPT_TEMPLATE, DEFAULT_SYSTEM_TEMPLATE, DEFAULT_USER_TEMPLATE, LiquidTemplateEngine, buildPromptContext, filterRelevantContext } from './chunk-VXS2CJFH.js';
3
+ import './chunk-PNE6LQRF.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-RKAPZNZO.js');
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,7 +1,7 @@
1
1
  {
2
2
  "name": "@oxgeneral/orch",
3
- "version": "0.3.4",
4
- "description": "Agents Organizations CLI orchestrator for AI agents",
3
+ "version": "1.0.1",
4
+ "description": "Open-source orchestration for zero-human companies, processes and departments — deploy AI engineering, editorial, sales, analytics teams from your terminal",
5
5
  "type": "module",
6
6
  "engines": {
7
7
  "node": ">=20.0.0"
@@ -34,22 +34,26 @@
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": [
40
- "cli",
41
+ "ai-agent-runtime",
42
+ "agent-orchestration",
43
+ "ai-agents",
44
+ "multi-agent",
45
+ "ai-team",
41
46
  "orchestrator",
42
- "ai",
43
- "agents",
44
47
  "claude",
45
48
  "codex",
46
- "terminal",
47
- "llm",
48
- "multi-agent",
49
- "ai-team",
50
- "agent-orchestration",
49
+ "cursor",
50
+ "opencode",
51
51
  "claude-code",
52
52
  "openai",
53
+ "llm",
54
+ "cli",
55
+ "typescript",
56
+ "git-worktree",
53
57
  "workflow",
54
58
  "devops"
55
59
  ],