@oxgeneral/orch 0.2.4 → 0.3.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.
Files changed (143) hide show
  1. package/dist/App-TW35IULR.js +18 -0
  2. package/dist/agent-FRQKL7YI.js +9 -0
  3. package/dist/{orchestrator-OMU46RCE.js → chunk-2UC4SVJB.js} +190 -53
  4. package/dist/chunk-2UC4SVJB.js.map +1 -0
  5. package/dist/chunk-5AJ4LYO5.js +8 -0
  6. package/dist/{chunk-45K2XID7.js → chunk-6DWHQPTE.js} +2 -1
  7. package/dist/chunk-6DWHQPTE.js.map +1 -0
  8. package/dist/{chunk-POUC4CPC.js → chunk-6MJ7V6VY.js} +2 -2
  9. package/dist/{chunk-HNKJ4IF7.js → chunk-B4JQM4NU.js} +34 -10
  10. package/dist/chunk-B4JQM4NU.js.map +1 -0
  11. package/dist/{chunk-6HENRUYZ.js → chunk-CDFA4IIQ.js} +2 -2
  12. package/dist/chunk-CHRW4CLD.js +2 -0
  13. package/dist/{chunk-VAAOW526.js → chunk-GZ2Q56YZ.js} +2 -2
  14. package/dist/{doctor-service-QEJCE5FK.js → chunk-HMMPM7MF.js} +2 -2
  15. package/dist/{chunk-AELEEEV3.js → chunk-HSBYJ5C5.js} +27 -7
  16. package/dist/chunk-HXOMNULD.js +2 -0
  17. package/dist/{chunk-3TGCIXJA.js → chunk-IQXRQBUK.js} +2 -1
  18. package/dist/chunk-IQXRQBUK.js.map +1 -0
  19. package/dist/chunk-L26TK7Y5.js +2 -0
  20. package/dist/chunk-L3FYR45M.js +2 -0
  21. package/dist/chunk-LXNRCJ22.js +2 -0
  22. package/dist/{chunk-TX7WOFCW.js → chunk-MGFMVPRD.js} +4 -7
  23. package/dist/chunk-MGFMVPRD.js.map +1 -0
  24. package/dist/chunk-MNXU3KCD.js +2 -0
  25. package/dist/{chunk-CHIP7O6V.js → chunk-O2MSGW3V.js} +3 -1
  26. package/dist/chunk-O2MSGW3V.js.map +1 -0
  27. package/dist/chunk-PJ5DKXGR.js +2 -0
  28. package/dist/{chunk-2KSBOAW3.js → chunk-QEEM67OA.js} +11 -17
  29. package/dist/chunk-QEEM67OA.js.map +1 -0
  30. package/dist/chunk-UMZEA3JT.js +5 -0
  31. package/dist/{shell-OGTSH4RJ.js → chunk-UW6GUUE6.js} +3 -3
  32. package/dist/chunk-XDVMX2FO.js +8 -0
  33. package/dist/chunk-XDVMX2FO.js.map +1 -0
  34. package/dist/chunk-ZA5Z33GO.js +11 -0
  35. package/dist/claude-E36EGXUV.js +2 -0
  36. package/dist/{chunk-IRN2U2NE.js → claude-RIB3RQS5.js} +5 -2
  37. package/dist/claude-RIB3RQS5.js.map +1 -0
  38. package/dist/cli.js +1 -199
  39. package/dist/clipboard-service-PDTSZIR5.js +25 -0
  40. package/dist/codex-OTZKVESD.js +2 -0
  41. package/dist/{codex-U7LTJTX6.js → codex-VBUSA2GJ.js} +5 -3
  42. package/dist/codex-VBUSA2GJ.js.map +1 -0
  43. package/dist/config-CCSS2P7R.js +2 -0
  44. package/dist/container-OIXLFSX2.js +6 -0
  45. package/dist/context-GSMQHQES.js +7 -0
  46. package/dist/cursor-3DJA6LWS.js +2 -0
  47. package/dist/{cursor-3DI5GKRF.js → cursor-4QIOTDBW.js} +5 -3
  48. package/dist/cursor-4QIOTDBW.js.map +1 -0
  49. package/dist/doctor-KBK5JZBZ.js +2 -0
  50. package/dist/{chunk-K6DMQERQ.js → doctor-service-F2SXDWHS.js} +3 -1
  51. package/dist/doctor-service-F2SXDWHS.js.map +1 -0
  52. package/dist/doctor-service-PB7YBH3F.js +2 -0
  53. package/dist/goal-RFKFPR7M.js +8 -0
  54. package/dist/index.d.ts +105 -43
  55. package/dist/index.js +1817 -5
  56. package/dist/index.js.map +1 -1
  57. package/dist/init-WRDFAFS2.js +53 -0
  58. package/dist/logs-5QHJWMEG.js +12 -0
  59. package/dist/msg-4SCLBO4K.js +9 -0
  60. package/dist/orchestrator-FGGXK3N3.js +5 -0
  61. package/dist/{orchestrator-L6QX2LJ7.js.map → orchestrator-FGGXK3N3.js.map} +1 -1
  62. package/dist/orchestrator-R7IWZUT6.js +13 -0
  63. package/dist/process-manager-33H27MQF.js +2 -0
  64. package/dist/process-manager-A36Y7LHP.js +3 -0
  65. package/dist/{process-manager-TLZOTO4Y.js.map → process-manager-A36Y7LHP.js.map} +1 -1
  66. package/dist/registry-BO2PPRNG.js +2 -0
  67. package/dist/registry-JXXRLJ5J.js +3 -0
  68. package/dist/{registry-UQAHK77P.js.map → registry-JXXRLJ5J.js.map} +1 -1
  69. package/dist/run-HSHRELOP.js +3 -0
  70. package/dist/shell-EOJBDWTH.js +2 -0
  71. package/dist/{chunk-CIIE6LNG.js → shell-IH2MMTVP.js} +3 -2
  72. package/dist/shell-IH2MMTVP.js.map +1 -0
  73. package/dist/status-DLBNWSWM.js +2 -0
  74. package/dist/task-J6ZN7ALI.js +20 -0
  75. package/dist/team-MSIBKOQC.js +4 -0
  76. package/dist/template-engine-MFL5B677.js +3 -0
  77. package/dist/{template-engine-322SCRR6.js.map → template-engine-MFL5B677.js.map} +1 -1
  78. package/dist/template-engine-ONIDVD4F.js +2 -0
  79. package/dist/tui-G4XUFAIP.js +2 -0
  80. package/dist/update-PC2ENCKU.js +2 -0
  81. package/dist/update-check-HGMBDYHL.js +2 -0
  82. package/dist/workspace-manager-KOOYTO7E.js +3 -0
  83. package/dist/{workspace-manager-G5EQRS72.js → workspace-manager-T6AXG7XL.js} +4 -3
  84. package/dist/workspace-manager-T6AXG7XL.js.map +1 -0
  85. package/package.json +2 -1
  86. package/readme.md +5 -4
  87. package/scripts/benchmark.ts +304 -0
  88. package/dist/App-KHUT3IV7.js +0 -4962
  89. package/dist/agent-V5M2C3OC.js +0 -157
  90. package/dist/chunk-33QNTNR6.js +0 -46
  91. package/dist/chunk-6HENRUYZ.js.map +0 -1
  92. package/dist/chunk-AELEEEV3.js.map +0 -1
  93. package/dist/chunk-ED47GL3F.js +0 -29
  94. package/dist/chunk-FRTKB575.js +0 -87
  95. package/dist/chunk-HXYAZGLP.js +0 -15
  96. package/dist/chunk-I5WEMARW.js +0 -166
  97. package/dist/chunk-IZYSGYXG.js +0 -2
  98. package/dist/chunk-IZYSGYXG.js.map +0 -1
  99. package/dist/chunk-P6ATSXGL.js +0 -107
  100. package/dist/chunk-PBFE5V3G.js +0 -2
  101. package/dist/chunk-PBFE5V3G.js.map +0 -1
  102. package/dist/chunk-PNE6LQRF.js +0 -5
  103. package/dist/chunk-POUC4CPC.js.map +0 -1
  104. package/dist/chunk-QTDKQYZI.js +0 -11
  105. package/dist/chunk-QTDKQYZI.js.map +0 -1
  106. package/dist/chunk-VAAOW526.js.map +0 -1
  107. package/dist/chunk-ZTQ3KWXR.js +0 -13
  108. package/dist/chunk-ZTQ3KWXR.js.map +0 -1
  109. package/dist/claude-GH6P2DC5.js +0 -4
  110. package/dist/claude-S47YTIHU.js +0 -2
  111. package/dist/claude-S47YTIHU.js.map +0 -1
  112. package/dist/codex-2CH57B7G.js +0 -2
  113. package/dist/codex-2CH57B7G.js.map +0 -1
  114. package/dist/config-LJFM55LN.js +0 -75
  115. package/dist/container-KPH4HVAJ.js +0 -1532
  116. package/dist/context-EPSDCJTU.js +0 -83
  117. package/dist/cursor-QFUNKPCQ.js +0 -2
  118. package/dist/cursor-QFUNKPCQ.js.map +0 -1
  119. package/dist/doctor-GHRV5I2S.js +0 -67
  120. package/dist/doctor-service-QEJCE5FK.js.map +0 -1
  121. package/dist/doctor-service-TPOMFAIG.js +0 -2
  122. package/dist/goal-I56QP7HS.js +0 -110
  123. package/dist/init-EQTGQ4G2.js +0 -165
  124. package/dist/logs-AK255DEJ.js +0 -207
  125. package/dist/msg-SQWQLJP6.js +0 -95
  126. package/dist/orchestrator-L6QX2LJ7.js +0 -2
  127. package/dist/process-manager-HUVNAPQV.js +0 -2
  128. package/dist/process-manager-TLZOTO4Y.js +0 -2
  129. package/dist/registry-PQWRVNF2.js +0 -2
  130. package/dist/registry-UQAHK77P.js +0 -2
  131. package/dist/run-PSZURVVL.js +0 -95
  132. package/dist/shell-5ZNXFGXV.js +0 -3
  133. package/dist/shell-OGTSH4RJ.js.map +0 -1
  134. package/dist/status-DTF7D3DV.js +0 -56
  135. package/dist/task-35SDKXFC.js +0 -209
  136. package/dist/team-AISPLEJB.js +0 -97
  137. package/dist/template-engine-322SCRR6.js +0 -2
  138. package/dist/template-engine-3CDRZNMJ.js +0 -3
  139. package/dist/tui-AR6PVMBQ.js +0 -230
  140. package/dist/update-DCCWVISK.js +0 -64
  141. package/dist/update-check-4YKLGBFB.js +0 -2
  142. package/dist/workspace-manager-AS4TFA7R.js +0 -3
  143. package/dist/workspace-manager-AS4TFA7R.js.map +0 -1
@@ -1,83 +0,0 @@
1
- #!/usr/bin/env node
2
- import { printSuccess, printError, dim, formatDurationSince, printTable } from './chunk-I5WEMARW.js';
3
-
4
- // src/cli/commands/context.ts
5
- function registerContextCommand(program, container) {
6
- const ctx = program.command("context").description("Shared context store for inter-agent data exchange");
7
- ctx.command("set <key> <value>").description("Set a shared context entry").option("--ttl <ms>", "Time-to-live in milliseconds").action(async (key, value, opts) => {
8
- await container.paths.requireInit();
9
- const ttlMs = opts.ttl ? parseInt(opts.ttl, 10) : void 0;
10
- await container.contextStore.set(key, value, ttlMs);
11
- if (container.context.json) {
12
- const entry = await container.contextStore.get(key);
13
- console.log(JSON.stringify(entry, null, 2));
14
- } else if (container.context.quiet) {
15
- console.log(key);
16
- } else {
17
- printSuccess(`Set context "${key}"`);
18
- }
19
- });
20
- ctx.command("get <key>").description("Get a shared context entry").action(async (key) => {
21
- await container.paths.requireInit();
22
- const entry = await container.contextStore.get(key);
23
- if (!entry) {
24
- if (container.context.json) {
25
- console.log("null");
26
- } else {
27
- printError(`Context key "${key}" not found`);
28
- }
29
- return;
30
- }
31
- if (container.context.json) {
32
- console.log(JSON.stringify(entry, null, 2));
33
- } else if (container.context.quiet) {
34
- console.log(entry.value);
35
- } else {
36
- console.log(`
37
- ${key} = ${entry.value}`);
38
- if (entry.expires_at) {
39
- console.log(` ${dim(`expires: ${entry.expires_at}`)}`);
40
- }
41
- console.log();
42
- }
43
- });
44
- ctx.command("list").description("List all shared context entries").action(async () => {
45
- await container.paths.requireInit();
46
- const entries = await container.contextStore.list();
47
- if (container.context.json) {
48
- console.log(JSON.stringify(entries, null, 2));
49
- return;
50
- }
51
- if (container.context.quiet) {
52
- entries.forEach((e) => console.log(`${e.key}=${e.value}`));
53
- return;
54
- }
55
- if (entries.length === 0) {
56
- console.log(`
57
- No shared context entries. Set one: ${dim("orch context set key value")}
58
- `);
59
- return;
60
- }
61
- const headers = ["KEY", "VALUE", "UPDATED", "TTL"];
62
- const rows = entries.map((e) => [
63
- e.key,
64
- e.value.length > 50 ? e.value.slice(0, 47) + "..." : e.value,
65
- formatDurationSince(e.updated_at),
66
- e.expires_at ? formatDurationSince(e.expires_at) : dim("\u2014")
67
- ]);
68
- console.log();
69
- printTable(headers, rows);
70
- console.log(`
71
- ${entries.length} entries
72
- `);
73
- });
74
- ctx.command("delete <key>").description("Delete a shared context entry").action(async (key) => {
75
- await container.paths.requireInit();
76
- await container.contextStore.delete(key);
77
- if (!container.context.quiet && !container.context.json) {
78
- printSuccess(`Deleted context "${key}"`);
79
- }
80
- });
81
- }
82
-
83
- export { registerContextCommand };
@@ -1,2 +0,0 @@
1
- import {b,a as a$1}from'./chunk-IZYSGYXG.js';import'./chunk-PBFE5V3G.js';import'./chunk-POUC4CPC.js';import {execFile}from'child_process';import {promisify}from'util';var d=promisify(execFile);async function m(){for(let r of ["cursor-agent","agent"])try{let{stdout:e}=await d(r,["--version"]);return {command:r,version:e.trim()}}catch{}return null}var a=class{constructor(e){this.processManager=e;}kind="cursor";resolvedCommand="cursor-agent";async test(){let e=await m();return e?(this.resolvedCommand=e.command,{ok:true,version:e.version}):{ok:false,error:"Cursor Agent CLI not found. The headless agent CLI is required (cursor-agent or agent)."}}execute(e){let t=["-p","--output-format","stream-json","--workspace",e.workspace,"--yolo"];e.config.model&&t.push("--model",e.config.model);let{process:n,pid:i}=this.processManager.spawn(this.resolvedCommand,t,{cwd:e.workspace,env:{...process.env,...e.env},signal:e.signal,stdio:["pipe","pipe","pipe"]});n.stdin&&(n.stdin.write(e.prompt),n.stdin.end());let c=b(n,l,"Cursor agent",e.signal);return {pid:i,events:c}}async stop(e){await this.processManager.killWithGrace(e);}};function l(r){if(!r.trim())return null;try{let e=JSON.parse(r),t=new Date().toISOString();switch(e.type){case "assistant":return {type:"output",timestamp:t,data:e.message??e};case "tool_use":return {type:"tool_call",timestamp:t,data:e};case "tool_result":return {type:"output",timestamp:t,data:e};case "error":return {type:"error",timestamp:t,data:e.error??e};case "result":{let n=a$1(e);return {type:"done",timestamp:t,data:e,tokens:n}}default:return {type:"output",timestamp:t,data:e}}}catch{return {type:"output",timestamp:new Date().toISOString(),data:r}}}export{a as CursorAdapter};//# sourceMappingURL=cursor-QFUNKPCQ.js.map
2
- //# sourceMappingURL=cursor-QFUNKPCQ.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/infrastructure/adapters/cursor.ts"],"names":["execFileAsync","promisify","execFile","findCommand","cmd","stdout","CursorAdapter","processManager","found","params","args","proc","pid","events","createStreamingEvents","parseCursorEvent","line","parsed","timestamp","tokens","extractTokens"],"mappings":"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","file":"cursor-QFUNKPCQ.js","sourcesContent":["/**\n * Cursor Agent adapter.\n *\n * Spawns `cursor-agent` (Cursor's headless agent CLI) with `--output-format stream-json`.\n * Falls back to `agent` command if `cursor-agent` is not found.\n * Parses JSON-lines from stdout into AgentEvent stream.\n *\n * Note: This requires Cursor Agent CLI, not the regular `cursor` IDE command.\n * Install via: npm i -g @anthropic-ai/cursor-agent (when available)\n */\n\nimport type { IAgentAdapter, AdapterTestResult, ExecuteParams, AgentEvent, ExecuteHandle } from './interface.js';\nimport type { IProcessManager } from '../process/process-manager.js';\nimport { extractTokens, createStreamingEvents } from './utils.js';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nconst execFileAsync = promisify(execFile);\n\n/** Try multiple command names and return the first that works */\nasync function findCommand(): Promise<{ command: string; version: string } | null> {\n for (const cmd of ['cursor-agent', 'agent']) {\n try {\n const { stdout } = await execFileAsync(cmd, ['--version']);\n return { command: cmd, version: stdout.trim() };\n } catch {\n // try next\n }\n }\n return null;\n}\n\nexport class CursorAdapter implements IAgentAdapter {\n readonly kind = 'cursor';\n\n private resolvedCommand: string = 'cursor-agent';\n\n constructor(private readonly processManager: IProcessManager) {}\n\n async test(): Promise<AdapterTestResult> {\n const found = await findCommand();\n if (found) {\n this.resolvedCommand = found.command;\n return { ok: true, version: found.version };\n }\n return {\n ok: false,\n error: 'Cursor Agent CLI not found. The headless agent CLI is required (cursor-agent or agent).',\n };\n }\n\n execute(params: ExecuteParams): ExecuteHandle {\n const args = [\n '-p',\n '--output-format', 'stream-json',\n '--workspace', params.workspace,\n '--yolo', // bypass interactive prompts for autonomous agents\n ];\n\n if (params.config.model) {\n args.push('--model', params.config.model);\n }\n\n const { process: proc, pid } = this.processManager.spawn(this.resolvedCommand, args, {\n cwd: params.workspace,\n env: { ...process.env, ...params.env },\n signal: params.signal,\n stdio: ['pipe', 'pipe', 'pipe'], // stdin must be 'pipe' to send prompt\n });\n\n // Pipe prompt via stdin\n if (proc.stdin) {\n proc.stdin.write(params.prompt);\n proc.stdin.end();\n }\n\n const events = createStreamingEvents(proc, parseCursorEvent, 'Cursor agent', params.signal);\n\n return { pid, events };\n }\n\n async stop(pid: number): Promise<void> {\n await this.processManager.killWithGrace(pid);\n }\n}\n\nfunction parseCursorEvent(line: string): AgentEvent | null {\n if (!line.trim()) return null;\n\n try {\n const parsed: Record<string, unknown> = JSON.parse(line);\n const timestamp = new Date().toISOString();\n\n // Cursor stream-json uses the same format as Claude stream-json\n switch (parsed.type) {\n case 'assistant':\n return { type: 'output', timestamp, data: (parsed.message as unknown) ?? parsed };\n case 'tool_use':\n return { type: 'tool_call', timestamp, data: parsed };\n case 'tool_result':\n return { type: 'output', timestamp, data: parsed };\n case 'error':\n return { type: 'error', timestamp, data: (parsed.error as unknown) ?? parsed };\n case 'result': {\n const tokens = extractTokens(parsed);\n return { type: 'done', timestamp, data: parsed, tokens };\n }\n default:\n return { type: 'output', timestamp, data: parsed };\n }\n } catch {\n return { type: 'output', timestamp: new Date().toISOString(), data: line };\n }\n}\n"]}
@@ -1,67 +0,0 @@
1
- #!/usr/bin/env node
2
- import { DoctorService } from './chunk-K6DMQERQ.js';
3
- import { amber, getIcon, dim } from './chunk-I5WEMARW.js';
4
- import { AdapterRegistry } from './chunk-45K2XID7.js';
5
- import { ClaudeAdapter } from './chunk-IRN2U2NE.js';
6
- import './chunk-TX7WOFCW.js';
7
- import { ShellAdapter } from './chunk-CIIE6LNG.js';
8
- import { ProcessManager } from './chunk-CHIP7O6V.js';
9
- import { Paths } from './chunk-2KSBOAW3.js';
10
- import './chunk-3TGCIXJA.js';
11
- import chalk from 'chalk';
12
-
13
- function registerDoctorCommand(program, container) {
14
- program.command("doctor").description("Check adapters and dependencies").action(async () => {
15
- let doctorService;
16
- let paths;
17
- let hasContainer = false;
18
- if (container) {
19
- doctorService = container.doctorService;
20
- paths = container.paths;
21
- hasContainer = true;
22
- } else {
23
- const pm = new ProcessManager();
24
- const registry = new AdapterRegistry();
25
- registry.register(new ClaudeAdapter(pm));
26
- registry.register(new ShellAdapter(pm));
27
- doctorService = new DoctorService(registry, pm, process.cwd());
28
- paths = new Paths(process.cwd());
29
- }
30
- console.log();
31
- console.log(` ${amber("orch doctor")} \xB7 checking adapters and dependencies`);
32
- console.log();
33
- const report = await doctorService.runAll();
34
- if (container?.context.json) {
35
- console.log(JSON.stringify(report, null, 2));
36
- return;
37
- }
38
- for (const check of report.checks) {
39
- const icon = check.status === "ok" ? chalk.ansi256(72)(getIcon("done")) : check.status === "fail" ? chalk.ansi256(167)(getIcon("failed")) : dim("\u2014");
40
- const detail = check.detail ? dim(` ${check.detail}`) : "";
41
- console.log(` ${icon} ${check.name.padEnd(12)}${detail}`);
42
- }
43
- if (paths) {
44
- const initialized = await paths.isInitialized();
45
- if (initialized && hasContainer) {
46
- const agents = await container.agentService.list();
47
- const tasks = await container.taskService.list();
48
- console.log();
49
- console.log(
50
- ` ${chalk.ansi256(72)(getIcon("done"))} .orchestry/ ${dim(`exists \xB7 ${agents.length} agents \xB7 ${tasks.length} tasks`)}`
51
- );
52
- } else if (!initialized) {
53
- console.log();
54
- console.log(
55
- ` ${chalk.ansi256(167)(getIcon("failed"))} .orchestry/ ${dim("not found \u2014 run: orch init")}`
56
- );
57
- }
58
- }
59
- console.log();
60
- console.log(
61
- ` ${report.adaptersReady} of ${report.adaptersTotal} adapters ready`
62
- );
63
- console.log();
64
- });
65
- }
66
-
67
- export { registerDoctorCommand };
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/application/doctor-service.ts"],"names":["execFileAsync","promisify","execFile","DoctorService","adapterRegistry","processManager","projectRoot","checks","adapters","adaptersReady","adapter","result","command","args","name","stdout","gitignorePath","path","fs","line"],"mappings":"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","file":"doctor-service-QEJCE5FK.js","sourcesContent":["/**\n * Doctor service — diagnostics and health checks.\n *\n * Checks adapter availability, system dependencies, project state.\n */\n\nimport type { AdapterRegistry } from '../infrastructure/adapters/registry.js';\nimport type { IProcessManager } from '../infrastructure/process/process-manager.js';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\n\nconst execFileAsync = promisify(execFile);\n\nexport interface DoctorCheck {\n name: string;\n status: 'ok' | 'fail' | 'skip';\n detail?: string;\n}\n\nexport interface DoctorReport {\n checks: DoctorCheck[];\n adaptersReady: number;\n adaptersTotal: number;\n}\n\nexport class DoctorService {\n private readonly cwd: string;\n\n constructor(\n private readonly adapterRegistry: AdapterRegistry,\n private readonly processManager: IProcessManager,\n projectRoot?: string,\n ) {\n this.cwd = projectRoot ?? process.cwd();\n }\n\n async runAll(): Promise<DoctorReport> {\n const checks: DoctorCheck[] = [];\n\n // Check adapters\n const adapters = this.adapterRegistry.list();\n let adaptersReady = 0;\n\n for (const adapter of adapters) {\n const result = await adapter.test();\n if (result.ok) {\n adaptersReady++;\n checks.push({\n name: adapter.kind,\n status: 'ok',\n detail: result.version,\n });\n } else {\n checks.push({\n name: adapter.kind,\n status: 'fail',\n detail: result.error,\n });\n }\n }\n\n // Check git\n checks.push(await this.checkCommand('git', ['--version'], 'git'));\n\n // Check git repository (required for worktree/isolated workspace modes)\n checks.push(await this.checkGitRepo());\n\n // Check .orchestry in root .gitignore (prevents recursive worktrees)\n checks.push(await this.checkGitignore());\n\n // Check node\n checks.push(await this.checkCommand('node', ['--version'], 'node'));\n\n return {\n checks,\n adaptersReady,\n adaptersTotal: adapters.length,\n };\n }\n\n private async checkCommand(\n command: string,\n args: string[],\n name: string,\n ): Promise<DoctorCheck> {\n try {\n const { stdout } = await execFileAsync(command, args);\n return { name, status: 'ok', detail: stdout.trim() };\n } catch {\n return { name, status: 'fail', detail: `${command}: command not found` };\n }\n }\n\n private async checkGitignore(): Promise<DoctorCheck> {\n const gitignorePath = path.join(this.cwd, '.gitignore');\n try {\n const content = await fs.readFile(gitignorePath, 'utf-8');\n const hasEntry = content.split('\\n').some((line) => line.trim() === '.orchestry');\n if (hasEntry) {\n return { name: '.gitignore', status: 'ok', detail: '.orchestry is excluded' };\n }\n return {\n name: '.gitignore',\n status: 'fail',\n detail: '.orchestry not in .gitignore — worktrees will copy state recursively. Run: orch init',\n };\n } catch {\n return {\n name: '.gitignore',\n status: 'fail',\n detail: 'no .gitignore found — .orchestry may be committed to git. Run: orch init',\n };\n }\n }\n\n private async checkGitRepo(): Promise<DoctorCheck> {\n try {\n await execFileAsync('git', ['rev-parse', '--is-inside-work-tree'], { cwd: this.cwd });\n return { name: 'git repo', status: 'ok', detail: 'git repository detected' };\n } catch {\n return {\n name: 'git repo',\n status: 'fail',\n detail: 'not a git repository — worktree/isolated modes will fail. Run: git init',\n };\n }\n }\n}\n"]}
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- export { DoctorService } from './chunk-K6DMQERQ.js';
@@ -1,110 +0,0 @@
1
- #!/usr/bin/env node
2
- import { GOAL_STATUSES } from './chunk-HXYAZGLP.js';
3
- import { printSuccess, dim, printTable, printKeyValue, printError } from './chunk-I5WEMARW.js';
4
-
5
- // src/cli/commands/goal.ts
6
- var STATUS_ICON = {
7
- active: "\u25CF",
8
- // ●
9
- paused: "\u2016",
10
- // ‖
11
- achieved: "\u2713",
12
- // ✓
13
- abandoned: "\u2715"
14
- // ✕
15
- };
16
- function registerGoalCommand(program, container) {
17
- const goal = program.command("goal").description("Manage goals");
18
- goal.command("add <title>").description("Create a new goal").option("--description <desc>", "Goal description").option("--assignee <agentId>", "Assign to a specific agent").action(async (title, opts) => {
19
- await container.paths.requireInit();
20
- const g = await container.goalService.create({
21
- title,
22
- description: opts.description,
23
- assignee: opts.assignee
24
- });
25
- if (container.context.json) {
26
- console.log(JSON.stringify(g, null, 2));
27
- } else if (container.context.quiet) {
28
- console.log(g.id);
29
- } else {
30
- printSuccess(`Created goal "${g.title}" (${g.id})`);
31
- }
32
- });
33
- goal.command("list").alias("ls").description("List all goals").option("--status <status>", "Filter by status").action(async (opts) => {
34
- await container.paths.requireInit();
35
- const goals = await container.goalService.list(
36
- opts.status ? { status: opts.status } : void 0
37
- );
38
- if (container.context.json) {
39
- console.log(JSON.stringify(goals, null, 2));
40
- return;
41
- }
42
- if (goals.length === 0) {
43
- console.log(dim("No goals found."));
44
- return;
45
- }
46
- const rows = goals.map((g) => [
47
- STATUS_ICON[g.status] ?? "?",
48
- g.id,
49
- g.title,
50
- g.status,
51
- g.assignee ?? dim("any")
52
- ]);
53
- printTable(["", "ID", "Title", "Status", "Assignee"], rows);
54
- });
55
- goal.command("show <id>").description("Show goal details").action(async (id) => {
56
- await container.paths.requireInit();
57
- const g = await container.goalService.get(id);
58
- if (container.context.json) {
59
- console.log(JSON.stringify(g, null, 2));
60
- return;
61
- }
62
- printKeyValue([
63
- ["ID", g.id],
64
- ["Title", g.title],
65
- ["Status", g.status],
66
- ["Assignee", g.assignee ?? dim("any")],
67
- ["Description", g.description || dim("none")],
68
- ["Created", g.created_at],
69
- ["Updated", g.updated_at ?? dim("never")]
70
- ]);
71
- });
72
- goal.command("status <id> <status>").description("Change goal status (active, paused, achieved, abandoned)").action(async (id, status) => {
73
- await container.paths.requireInit();
74
- if (!GOAL_STATUSES.includes(status)) {
75
- printError(`Invalid status "${status}". Valid: ${GOAL_STATUSES.join(", ")}`);
76
- process.exitCode = 1;
77
- return;
78
- }
79
- const g = await container.goalService.updateStatus(id, status);
80
- if (container.context.json) {
81
- console.log(JSON.stringify(g, null, 2));
82
- } else if (container.context.quiet) {
83
- console.log(g.id);
84
- } else {
85
- printSuccess(`Goal "${g.title}" \u2192 ${g.status}`);
86
- }
87
- });
88
- goal.command("update <id>").description("Update goal fields").option("--title <title>", "New title").option("--description <desc>", "New description").option("--assignee <agentId>", "New assignee (empty string to unassign)").action(async (id, opts) => {
89
- await container.paths.requireInit();
90
- const g = await container.goalService.update(id, opts);
91
- if (container.context.json) {
92
- console.log(JSON.stringify(g, null, 2));
93
- } else if (container.context.quiet) {
94
- console.log(g.id);
95
- } else {
96
- printSuccess(`Updated goal "${g.title}"`);
97
- }
98
- });
99
- goal.command("delete <id>").alias("rm").description("Delete a goal").action(async (id) => {
100
- await container.paths.requireInit();
101
- await container.goalService.delete(id);
102
- if (container.context.json) {
103
- console.log(JSON.stringify({ deleted: id }));
104
- } else if (!container.context.quiet) {
105
- printSuccess(`Deleted goal ${id}`);
106
- }
107
- });
108
- }
109
-
110
- export { registerGoalCommand };
@@ -1,165 +0,0 @@
1
- #!/usr/bin/env node
2
- import { DEFAULT_PROMPT_TEMPLATE } from './chunk-HNKJ4IF7.js';
3
- import { DEFAULT_CONFIG } from './chunk-ED47GL3F.js';
4
- import './chunk-PNE6LQRF.js';
5
- import { printWarning, printSuccess, dim } from './chunk-I5WEMARW.js';
6
- import { Paths, pathExists, ensureDir, writeYaml, atomicWrite } from './chunk-2KSBOAW3.js';
7
- import './chunk-3TGCIXJA.js';
8
- import path from 'path';
9
- import fs from 'fs/promises';
10
-
11
- // src/domain/default-agents.ts
12
- var AGENT_CREATOR_ROLE = `Agent architect \u2014 designs and creates AI agents for the orchestrator via \`orch agent add\`.
13
-
14
- ## CREATION PROCESS
15
-
16
- 1) ANALYZE \u2014 determine: agent function, required skills, adapter, team interactions.
17
-
18
- 2) WRITE THE ROLE \u2014 this is the most important part. A good role includes:
19
- - Identity and specialization (who you are)
20
- - Concrete workflow (numbered steps)
21
- - Which skills to invoke (\`/skill-name\`)
22
- - Rules and constraints
23
- Do NOT include CLI documentation or goal-mode instructions \u2014 these are already injected by the system prompt template.
24
-
25
- 3) CHOOSE CONFIGURATION:
26
- - adapter: \`claude\` (AI tasks), \`shell\` (bash scripts), \`codex\` (OpenAI Codex), \`cursor\` (Cursor IDE)
27
- - model: \`claude-opus-4-6\` (complex/architectural), \`claude-sonnet-4-6\` (fast/routine), \`claude-haiku-4-5-20251001\` (simple/templated)
28
- - approval_policy: \`auto\` (no confirmation) / \`suggest\` (proposes actions) / \`manual\` (human approval)
29
- - max_turns: 50 (default), up to 100 for complex tasks
30
-
31
- 4) CREATE:
32
- \`orch agent add "<name>" --adapter claude --model <model> --skills "<skills>" --role "<role>" --approval-policy auto\`
33
-
34
- ## AVAILABLE SKILLS
35
-
36
- Development: feature-dev:feature-dev, feature-dev:code-explorer, feature-dev:code-architect, feature-dev:code-reviewer, simplify, claude-api
37
- Testing: testing-suite:generate-tests, testing-suite:test-coverage, testing-suite:e2e-setup, testing-suite:test-quality-analyzer
38
- Frontend: frontend-design, document-skills:frontend-design
39
- Documents: pdf, xlsx, docx, pptx
40
- Marketing: marketing-psychology, product-manager-toolkit
41
-
42
- ## ANTI-PATTERNS
43
-
44
- - Never create agents without skills \u2014 they cannot be auto-matched to tasks.
45
- - Never write generic roles like "helper" \u2014 be specific about actions and tools.
46
- - Never use opus for simple tasks \u2014 it is expensive; use sonnet or haiku.
47
- - Never assign more than 3-4 skills per agent \u2014 create specialized agents instead.
48
- - Never use the -e/--edit flag in automated mode \u2014 it opens an interactive editor.
49
- - Always specify --role when calling \`orch agent add\`.
50
-
51
- After creation \u2014 \`orch context set agent-<name> "<capabilities>"\`.`;
52
- function getDefaultAgents() {
53
- return [
54
- {
55
- id: "agt_creator",
56
- name: "Agent Creator",
57
- adapter: "claude",
58
- role: AGENT_CREATOR_ROLE,
59
- config: {
60
- model: "claude-sonnet-4-6",
61
- approval_policy: "suggest",
62
- max_turns: 50,
63
- timeout_ms: 36e5,
64
- stall_timeout_ms: 3e5,
65
- skills: ["document-skills:skill-creator"]
66
- },
67
- status: "idle",
68
- stats: {
69
- tasks_completed: 0,
70
- tasks_failed: 0,
71
- total_runs: 0,
72
- total_runtime_ms: 0
73
- }
74
- }
75
- ];
76
- }
77
-
78
- // src/cli/commands/init.ts
79
- async function runInit(opts = {}) {
80
- const projectRoot = process.cwd();
81
- const paths = new Paths(projectRoot);
82
- if (await pathExists(paths.root)) {
83
- printWarning("Already initialized");
84
- return;
85
- }
86
- await Promise.all([
87
- ensureDir(paths.tasksDir),
88
- ensureDir(paths.agentsDir),
89
- ensureDir(paths.goalsDir),
90
- ensureDir(paths.runsDir),
91
- ensureDir(paths.templatesDir),
92
- ensureDir(paths.logsDir)
93
- ]);
94
- const config = { ...DEFAULT_CONFIG };
95
- config.project.name = opts.name ?? path.basename(projectRoot);
96
- const gitignoreContent = [
97
- "# Runtime state",
98
- "state.json",
99
- "*.lock",
100
- "",
101
- "# Logs and runs",
102
- "runs/",
103
- "logs/",
104
- "",
105
- "# Agent workspaces",
106
- "workspaces/"
107
- ].join("\n") + "\n";
108
- const excludeContent = [
109
- ".orchestry",
110
- "node_modules",
111
- ".env",
112
- ".env.*",
113
- "dist",
114
- "build",
115
- ".next",
116
- "__pycache__",
117
- "*.pyc",
118
- ".venv"
119
- ].join("\n") + "\n";
120
- const defaultAgents = getDefaultAgents();
121
- await Promise.all([
122
- writeYaml(paths.configPath, config),
123
- atomicWrite(paths.gitignorePath, gitignoreContent),
124
- atomicWrite(paths.workspaceExcludePath, excludeContent),
125
- atomicWrite(paths.defaultTemplatePath(), DEFAULT_PROMPT_TEMPLATE),
126
- ...defaultAgents.map((agent) => writeYaml(paths.agentPath(agent.id), agent))
127
- ]);
128
- await ensureRootGitignore(projectRoot);
129
- console.log();
130
- printSuccess("initialized");
131
- console.log();
132
- console.log(` Created ${dim(".orchestry/")}`);
133
- console.log(` ${dim("\u251C\u2500\u2500")} config.yml`);
134
- console.log(` ${dim("\u251C\u2500\u2500")} tasks/`);
135
- console.log(` ${dim("\u251C\u2500\u2500")} agents/`);
136
- for (const agent of defaultAgents) {
137
- console.log(` ${dim("\u2502 \u2514\u2500\u2500")} ${agent.id}.yml ${dim(`(${agent.name})`)}`);
138
- }
139
- console.log(` ${dim("\u251C\u2500\u2500")} templates/default.md`);
140
- console.log(` ${dim("\u2514\u2500\u2500")} .gitignore`);
141
- console.log();
142
- }
143
- async function ensureRootGitignore(projectRoot) {
144
- const gitignorePath = path.join(projectRoot, ".gitignore");
145
- try {
146
- const content = await fs.readFile(gitignorePath, "utf-8");
147
- if (content.split("\n").some((line) => line.trim() === ".orchestry")) return;
148
- const separator = content.endsWith("\n") ? "" : "\n";
149
- await fs.appendFile(gitignorePath, `${separator}
150
- # Orchestry state
151
- .orchestry
152
- `);
153
- } catch {
154
- await atomicWrite(gitignorePath, "# Orchestry state\n.orchestry\n");
155
- }
156
- }
157
- function registerInitCommand(program) {
158
- program.command("init").description("Initialize .orchestry/ in the current directory").option("--name <name>", "Project name").action(async (opts) => {
159
- await runInit(opts);
160
- console.log(` Next: ${dim('orch task add "Create backend agent" --assignee agt_creator')}`);
161
- console.log();
162
- });
163
- }
164
-
165
- export { registerInitCommand, runInit };
@@ -1,207 +0,0 @@
1
- #!/usr/bin/env node
2
- import { printError, dim, getIcon } from './chunk-I5WEMARW.js';
3
- import { InvalidArgumentsError } from './chunk-3TGCIXJA.js';
4
-
5
- // src/cli/commands/logs.ts
6
- function registerLogsCommand(program, container) {
7
- program.command("logs [run-id]").description("View run logs").option("--agent <agent-id>", "Filter by agent").option("--task <task-id>", "Filter by task").option("--follow", "Live stream").option("--since <duration>", "Filter by time (e.g. 5m, 1h)").action(async (runId, opts) => {
8
- await container.paths.requireInit();
9
- const sinceMs = opts.since ? parseDuration(opts.since) : void 0;
10
- if (opts.follow) {
11
- await followLive(container, { runId, taskId: opts.task, agentId: opts.agent });
12
- } else if (runId) {
13
- await showRunLogs(container, runId, sinceMs);
14
- } else if (opts.task) {
15
- await showTaskLogs(container, opts.task, sinceMs);
16
- } else if (opts.agent) {
17
- await showAgentLogs(container, opts.agent, sinceMs);
18
- } else {
19
- printError("Specify a run ID, --task, or --agent");
20
- process.exit(2);
21
- }
22
- });
23
- }
24
- function formatEvent(event) {
25
- const time = new Date(event.timestamp).toLocaleTimeString("en-US", {
26
- hour12: false,
27
- hour: "2-digit",
28
- minute: "2-digit",
29
- second: "2-digit"
30
- });
31
- const icon = event.type === "error" ? getIcon("failed") : getIcon("agentAction");
32
- const data = typeof event.data === "string" ? event.data : JSON.stringify(event.data);
33
- return ` ${dim(time)} ${icon} ${data.slice(0, 80)}`;
34
- }
35
- function filterBySince(events, sinceMs) {
36
- if (!sinceMs) return events;
37
- const cutoff = Date.now() - sinceMs;
38
- return events.filter((e) => new Date(e.timestamp).getTime() >= cutoff);
39
- }
40
- async function showRunLogs(container, runId, sinceMs) {
41
- let events = sinceMs ? filterBySince(await container.runService.readEventsTail(runId, 500), sinceMs) : await container.runService.readEventsTail(runId, 50);
42
- if (container.context.json) {
43
- console.log(JSON.stringify(events, null, 2));
44
- return;
45
- }
46
- if (events.length === 0) {
47
- console.log(`
48
- No events for run ${runId}
49
- `);
50
- return;
51
- }
52
- console.log();
53
- for (const event of events) {
54
- console.log(formatEvent(event));
55
- }
56
- console.log();
57
- }
58
- async function showTaskLogs(container, taskId, sinceMs) {
59
- const runs = await container.runService.listForTask(taskId);
60
- if (container.context.json) {
61
- console.log(JSON.stringify(runs, null, 2));
62
- return;
63
- }
64
- if (runs.length === 0) {
65
- console.log(`
66
- No runs for task ${taskId}
67
- `);
68
- return;
69
- }
70
- const recentRuns = sinceMs ? runs.slice(-20) : runs;
71
- const eventsPerRun = await Promise.all(
72
- recentRuns.map(
73
- (run) => sinceMs ? container.runService.readEventsTail(run.id, 500).then((e) => filterBySince(e, sinceMs)) : container.runService.readEventsTail(run.id, 10)
74
- )
75
- );
76
- for (let i = 0; i < recentRuns.length; i++) {
77
- const run = recentRuns[i];
78
- const events = eventsPerRun[i];
79
- console.log(`
80
- Run ${run.id} \xB7 attempt ${run.attempt} \xB7 ${run.status}`);
81
- for (const event of events.slice(-10)) {
82
- console.log(formatEvent(event));
83
- }
84
- }
85
- console.log();
86
- }
87
- async function showAgentLogs(container, agentId, sinceMs) {
88
- const runs = await container.runService.listForAgent(agentId);
89
- if (container.context.json) {
90
- console.log(JSON.stringify(runs, null, 2));
91
- return;
92
- }
93
- if (runs.length === 0) {
94
- console.log(`
95
- No runs for agent ${agentId}
96
- `);
97
- return;
98
- }
99
- const recentRuns = runs.slice(-5);
100
- const eventsPerRun = await Promise.all(
101
- recentRuns.map(
102
- (run) => sinceMs ? container.runService.readEventsTail(run.id, 500).then((e) => filterBySince(e, sinceMs)) : container.runService.readEventsTail(run.id, 5)
103
- )
104
- );
105
- for (let i = 0; i < recentRuns.length; i++) {
106
- const run = recentRuns[i];
107
- const events = eventsPerRun[i];
108
- console.log(`
109
- Run ${run.id} \xB7 task ${run.task_id} \xB7 ${run.status}`);
110
- for (const event of events.slice(-5)) {
111
- console.log(formatEvent(event));
112
- }
113
- }
114
- console.log();
115
- }
116
- async function followLive(container, filter) {
117
- const runIds = /* @__PURE__ */ new Set();
118
- const agentIds = /* @__PURE__ */ new Set();
119
- if (filter.runId) {
120
- runIds.add(filter.runId);
121
- }
122
- if (filter.taskId) {
123
- const runs = await container.runService.listForTask(filter.taskId);
124
- for (const r of runs) runIds.add(r.id);
125
- }
126
- if (filter.agentId) {
127
- agentIds.add(filter.agentId);
128
- }
129
- const hasFilter = runIds.size > 0 || agentIds.size > 0;
130
- console.log(`
131
- ${dim("Following live events...")} ${dim("(Ctrl+C to stop)")}
132
- `);
133
- const unsub = container.eventBus.onAny((event) => {
134
- const time = (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", {
135
- hour12: false,
136
- hour: "2-digit",
137
- minute: "2-digit",
138
- second: "2-digit"
139
- });
140
- if (hasFilter) {
141
- if ("runId" in event && runIds.size > 0 && !runIds.has(event.runId)) return;
142
- if ("agentId" in event && agentIds.size > 0) {
143
- const evt = event;
144
- if (!agentIds.has(evt.agentId)) return;
145
- }
146
- }
147
- switch (event.type) {
148
- case "agent:output": {
149
- const data = typeof event.data === "string" ? event.data.slice(0, 80) : "";
150
- console.log(` ${dim(time)} ${getIcon("agentAction")} ${data}`);
151
- break;
152
- }
153
- case "agent:file_changed":
154
- console.log(` ${dim(time)} ${getIcon("agentAction")} Modified ${event.path}`);
155
- break;
156
- case "agent:error":
157
- console.log(` ${dim(time)} ${getIcon("failed")} ${event.error}`);
158
- break;
159
- case "agent:started":
160
- console.log(` ${dim(time)} ${getIcon("orchestratorEvent")} Started ${event.runId} (agent: ${event.agentId})`);
161
- break;
162
- case "agent:completed":
163
- if (event.success) {
164
- console.log(` ${dim(time)} ${getIcon("done")} DONE ${event.runId}`);
165
- } else {
166
- console.log(` ${dim(time)} ${getIcon("failed")} FAIL ${event.runId}`);
167
- }
168
- break;
169
- case "run:retry":
170
- console.log(` ${dim(time)} ${getIcon("retrying")} RETRY attempt ${event.attempt} \xB7 next in ${Math.round(event.delay_ms / 1e3)}s`);
171
- break;
172
- case "orchestrator:stall_detected":
173
- console.log(` ${dim(time)} ${getIcon("warning")} STALL ${event.runId}`);
174
- break;
175
- }
176
- });
177
- await new Promise((resolve) => {
178
- const cleanup = () => {
179
- unsub();
180
- resolve();
181
- };
182
- process.once("SIGINT", cleanup);
183
- process.once("SIGTERM", cleanup);
184
- });
185
- }
186
- function parseDuration(input) {
187
- const match = input.match(/^(\d+)(s|m|h|d)$/);
188
- if (!match) {
189
- throw new InvalidArgumentsError(`Invalid duration: "${input}". Use format: 5m, 1h, 30s, 1d`);
190
- }
191
- const value = parseInt(match[1], 10);
192
- const unit = match[2];
193
- switch (unit) {
194
- case "s":
195
- return value * 1e3;
196
- case "m":
197
- return value * 6e4;
198
- case "h":
199
- return value * 36e5;
200
- case "d":
201
- return value * 864e5;
202
- default:
203
- return value * 6e4;
204
- }
205
- }
206
-
207
- export { registerLogsCommand };