@oxgeneral/orch 0.2.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 (87) hide show
  1. package/LICENSE +21 -0
  2. package/dist/App-CPQPQTZU.js +4751 -0
  3. package/dist/agent-J62U7ABO.js +157 -0
  4. package/dist/chunk-2B32FPEB.js +11 -0
  5. package/dist/chunk-2B32FPEB.js.map +1 -0
  6. package/dist/chunk-2VSAM7RH.js +166 -0
  7. package/dist/chunk-33QNTNR6.js +46 -0
  8. package/dist/chunk-45K2XID7.js +29 -0
  9. package/dist/chunk-6GFVB6EK.js +101 -0
  10. package/dist/chunk-6HENRUYZ.js +2 -0
  11. package/dist/chunk-6HENRUYZ.js.map +1 -0
  12. package/dist/chunk-AELEEEV3.js +92 -0
  13. package/dist/chunk-AELEEEV3.js.map +1 -0
  14. package/dist/chunk-CHIP7O6V.js +83 -0
  15. package/dist/chunk-CIIE6LNG.js +217 -0
  16. package/dist/chunk-E3TCKHU6.js +13 -0
  17. package/dist/chunk-E3TCKHU6.js.map +1 -0
  18. package/dist/chunk-ED47GL3F.js +29 -0
  19. package/dist/chunk-HNKJ4IF7.js +177 -0
  20. package/dist/chunk-HXYAZGLP.js +15 -0
  21. package/dist/chunk-IRN2U2NE.js +79 -0
  22. package/dist/chunk-IZYSGYXG.js +2 -0
  23. package/dist/chunk-IZYSGYXG.js.map +1 -0
  24. package/dist/chunk-O5AO5QIR.js +76 -0
  25. package/dist/chunk-P6ATSXGL.js +107 -0
  26. package/dist/chunk-PBFE5V3G.js +2 -0
  27. package/dist/chunk-PBFE5V3G.js.map +1 -0
  28. package/dist/chunk-PNE6LQRF.js +5 -0
  29. package/dist/chunk-POUC4CPC.js +2 -0
  30. package/dist/chunk-POUC4CPC.js.map +1 -0
  31. package/dist/chunk-TX7WOFCW.js +59 -0
  32. package/dist/chunk-VTA74YWX.js +291 -0
  33. package/dist/chunk-XI4TU6VU.js +50 -0
  34. package/dist/chunk-ZU6AY2VU.js +2 -0
  35. package/dist/chunk-ZU6AY2VU.js.map +1 -0
  36. package/dist/claude-GH6P2DC5.js +4 -0
  37. package/dist/claude-S47YTIHU.js +2 -0
  38. package/dist/claude-S47YTIHU.js.map +1 -0
  39. package/dist/cli.js +205 -0
  40. package/dist/codex-2CH57B7G.js +2 -0
  41. package/dist/codex-2CH57B7G.js.map +1 -0
  42. package/dist/codex-U7LTJTX6.js +115 -0
  43. package/dist/config-VN4MYHSY.js +75 -0
  44. package/dist/container-74P43KDY.js +1532 -0
  45. package/dist/context-EPHCF34F.js +83 -0
  46. package/dist/cursor-3DI5GKRF.js +92 -0
  47. package/dist/cursor-QFUNKPCQ.js +2 -0
  48. package/dist/cursor-QFUNKPCQ.js.map +1 -0
  49. package/dist/doctor-BK46WCQ5.js +67 -0
  50. package/dist/doctor-service-A34DHPKI.js +2 -0
  51. package/dist/doctor-service-NTWBWOM2.js +2 -0
  52. package/dist/doctor-service-NTWBWOM2.js.map +1 -0
  53. package/dist/goal-KGAIM3ZK.js +110 -0
  54. package/dist/index.d.ts +1356 -0
  55. package/dist/index.js +6 -0
  56. package/dist/index.js.map +1 -0
  57. package/dist/init-QBWCEDCI.js +152 -0
  58. package/dist/logs-PYEKMQE2.js +207 -0
  59. package/dist/msg-BBIPCGDO.js +95 -0
  60. package/dist/orchestrator-TAFBYQQ5.js +2 -0
  61. package/dist/orchestrator-TAFBYQQ5.js.map +1 -0
  62. package/dist/orchestrator-VGYKSOZJ.js +1292 -0
  63. package/dist/output-5VQVCJ2K.js +2 -0
  64. package/dist/process-manager-HUVNAPQV.js +2 -0
  65. package/dist/process-manager-TLZOTO4Y.js +2 -0
  66. package/dist/process-manager-TLZOTO4Y.js.map +1 -0
  67. package/dist/registry-PQWRVNF2.js +2 -0
  68. package/dist/registry-UQAHK77P.js +2 -0
  69. package/dist/registry-UQAHK77P.js.map +1 -0
  70. package/dist/run-4GSZFGQZ.js +95 -0
  71. package/dist/shell-5ZNXFGXV.js +3 -0
  72. package/dist/shell-OGTSH4RJ.js +3 -0
  73. package/dist/shell-OGTSH4RJ.js.map +1 -0
  74. package/dist/status-KIISF542.js +56 -0
  75. package/dist/task-NUCRHYW7.js +209 -0
  76. package/dist/team-IBUP5XV4.js +97 -0
  77. package/dist/template-engine-322SCRR6.js +2 -0
  78. package/dist/template-engine-322SCRR6.js.map +1 -0
  79. package/dist/template-engine-3CDRZNMJ.js +3 -0
  80. package/dist/tui-WWZA73IO.js +225 -0
  81. package/dist/update-RJ4IYACQ.js +64 -0
  82. package/dist/update-check-4RV7Z6WT.js +2 -0
  83. package/dist/workspace-manager-47KI7B27.js +179 -0
  84. package/dist/workspace-manager-7M46ESUL.js +2 -0
  85. package/dist/workspace-manager-7M46ESUL.js.map +1 -0
  86. package/package.json +79 -0
  87. package/readme.md +270 -0
@@ -0,0 +1,92 @@
1
+ var g="autonomous";var u=class{engine;renderTimeoutMs;constructor(t){this.renderTimeoutMs=t?.renderTimeoutMs??5e3;}async getEngine(){if(!this.engine){let{Liquid:t}=await import('liquidjs');this.engine=new t({strictFilters:false,strictVariables:false});}return this.engine}async render(t,s){let o=(await this.getEngine()).parseAndRender(t,s);if(this.renderTimeoutMs<=0)return o;let i,a=new Promise((c,n)=>{i=setTimeout(()=>n(new Error(`Template render timed out after ${this.renderTimeoutMs}ms`)),this.renderTimeoutMs);});try{return await Promise.race([o,a])}finally{clearTimeout(i);}}};function k(r,t,s,d,o,i){let{allAgents:a,retryContext:c,sharedContext:n,feedback:m,messages:p}=i??{},l=new Map((a??[]).map(e=>[e.id,e])),f=p?.length?p.map(e=>({id:e.id,from:l.get(e.from_agent_id)?.name??e.from_agent_id,subject:e.subject,body:e.body,sent_at:e.created_at,reply_to:e.reply_to})):void 0;return {project:{name:o.project.name,description:o.project.description},task:{id:r.id,title:r.title,description:r.description,priority:r.priority,labels:r.labels,scope:r.scope,is_autonomous:r.labels?.includes(g)??false},agent:{id:t.id,name:t.name,role:t.role},agents:(a??[]).map(e=>({id:e.id,name:e.name,role:e.role,adapter:e.adapter})),attempt:s>1?s:null,workspace_path:d,retry:s>1?c:void 0,feedback:m,shared_context:n&&Object.keys(n).length>0?n:void 0,messages:f}}var b=`You are {{ agent.name }}{% if agent.role %} ({{ agent.role }}){% endif %}.
2
+
3
+ ## Task: {{ task.title }}
4
+ {{ task.description }}
5
+
6
+ Priority: {{ task.priority }}
7
+ {% if attempt %}Attempt: {{ attempt }}{% endif %}
8
+ {% if retry %}
9
+ ## Previous attempt failed
10
+ **Error:** {{ retry.previous_error }}
11
+ {% if retry.previous_output != "" %}
12
+ **Last output:**
13
+ \`\`\`
14
+ {{ retry.previous_output }}
15
+ \`\`\`
16
+ {% endif %}
17
+ **Important:** The previous approach failed. Analyze the error above and try a different strategy. Do NOT repeat the same steps that led to the failure.
18
+ {% endif %}
19
+
20
+ ## Context
21
+ Project: {{ project.name }}
22
+ Working directory: {{ workspace_path }}
23
+
24
+ ## Team
25
+ You are part of a multi-agent team. Available agents:
26
+ {% for a in agents %}- **{{ a.name }}** ({{ a.adapter }}){% if a.role %} \u2014 {{ a.role }}{% endif %} \xB7 ID: \`{{ a.id }}\`
27
+ {% endfor %}
28
+ Use \`orch agent list\` to check current agent statuses. Find teammates by name/role \u2014 do NOT hardcode agent IDs.
29
+
30
+ {% if feedback %}
31
+ ## Review Feedback
32
+ This task was previously completed but **rejected** during review with the following feedback:
33
+ > {{ feedback }}
34
+
35
+ **Important:** Address the feedback above. Focus on what the reviewer asked to change. Do NOT redo work that was already accepted.
36
+ {% endif %}
37
+
38
+ {% if shared_context %}
39
+ ## Shared Context
40
+ Other agents have shared the following information:
41
+ {% for entry in shared_context %}- **{{ entry[0] }}**: {{ entry[1] }}
42
+ {% endfor %}
43
+ {% endif %}
44
+
45
+ {% if messages %}
46
+ ## Inbox ({{ messages.size }} message{% if messages.size != 1 %}s{% endif %})
47
+ {% for msg in messages %}
48
+ ---
49
+ **From:** {{ msg.from }}{% if msg.subject != "" %} \xB7 **Subject:** {{ msg.subject }}{% endif %}
50
+ {{ msg.body }}
51
+ {% if msg.reply_to %}*(Reply to: {{ msg.reply_to }})*{% endif %}
52
+ ---
53
+ {% endfor %}
54
+ {% endif %}
55
+
56
+ ## Orchestrator CLI
57
+ Manage tasks and coordinate with other agents using \`orch\`:
58
+
59
+ **Tasks:**
60
+ - \`orch task add "<title>" -d "<description>" -p <1-4> --assignee <agent-id>\` \u2014 create and assign a task
61
+ - \`orch task add "<title>" -d "<description>" --scope "src/path/**" --depends-on <task-id>\` \u2014 scoped task with dependency
62
+ - \`orch task list [--status todo|in_progress|done|failed]\` \u2014 list tasks
63
+
64
+ **Messaging:**
65
+ - \`orch msg send <agent-id> "<body>" -s "<subject>"\` \u2014 direct message
66
+ - \`orch msg broadcast "<body>" -s "<subject>"\` \u2014 broadcast to all
67
+ - \`orch msg inbox {{ agent.id }}\` \u2014 your pending messages
68
+
69
+ **Shared context:**
70
+ - \`orch context set <key> <value>\` / \`orch context get <key>\` / \`orch context list\`
71
+
72
+ {% if task.is_autonomous %}
73
+ ## Autonomous Goal Mode
74
+ This is an autonomous task driven by a goal. Work in a continuous loop until the goal is achieved:
75
+
76
+ 1. **Read the GOAL section** above \u2014 understand the desired outcome.
77
+ 2. **Decompose** \u2014 break the goal into concrete subtasks via \`orch task add\`. Assign yourself for your specialty, delegate other work to appropriate teammates by role.
78
+ 3. **Execute** \u2014 follow your standard workflow for each subtask.
79
+ 4. **Track progress** \u2014 after each iteration: \`orch context set <goal>-progress "<done, remaining>"\`.
80
+ 5. **Be proactive** \u2014 do NOT wait for tasks from others. Create your own subtasks and keep working.
81
+ 6. **Do NOT finish** the [auto] task until the goal is achieved \u2014 keep creating subtasks.
82
+ 7. **When done** \u2014 \`orch context set <goal>-status "ACHIEVED: <summary>"\`.
83
+ {% endif %}
84
+
85
+ ## Rules
86
+ - Do NOT ask clarifying questions. You are running autonomously without human input.
87
+ - Make reasonable assumptions and proceed with the best approach.
88
+ - If critical information is missing, document your assumptions and continue.
89
+ - When a task is too large or spans multiple domains, break it into subtasks using \`orch task add\`.
90
+ - When creating subtasks, use \`--scope\` to declare which files each task will touch, and \`--depends-on\` to order dependent work.
91
+ `;export{g as a,u as b,k as c,b as d};//# sourceMappingURL=chunk-AELEEEV3.js.map
92
+ //# sourceMappingURL=chunk-AELEEEV3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/domain/task.ts","../src/infrastructure/template/template-engine.ts"],"names":["AUTONOMOUS_LABEL","LiquidTemplateEngine","options","Liquid","template","context","renderPromise","timer","timeoutPromise","_","reject","buildPromptContext","task","agent","attempt","workspacePath","config","allAgents","retryContext","sharedContext","feedback","rawMessages","agentById","a","messages","m","DEFAULT_PROMPT_TEMPLATE"],"mappings":"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","file":"chunk-AELEEEV3.js","sourcesContent":["/**\n * Task domain model.\n *\n * A Task is the unit of work in the orchestrator.\n * It moves through a state machine: todo → in_progress → review → done.\n */\n\nexport type TaskStatus =\n | 'todo'\n | 'in_progress'\n | 'retrying'\n | 'review'\n | 'done'\n | 'failed'\n | 'cancelled';\n\n/** Label applied to tasks auto-generated by the orchestrator for autonomous agents. */\nexport const AUTONOMOUS_LABEL = 'autonomous' as const;\n\nexport type WorkspaceMode = 'shared' | 'worktree' | 'isolated';\n\nexport type ReviewCriterion = 'test_pass' | 'typecheck' | 'lint';\n\nexport interface ReviewResult {\n criterion: ReviewCriterion;\n passed: boolean;\n output: string;\n}\n\nexport interface TaskProof {\n branch?: string;\n pr_url?: string;\n files_changed: string[];\n test_results?: string;\n agent_summary?: string;\n}\n\nexport interface Task {\n id: string;\n title: string;\n description: string;\n status: TaskStatus;\n priority: number;\n assignee?: string;\n labels: string[];\n depends_on: string[];\n created_at: string;\n updated_at: string;\n attempts: number;\n max_attempts: number;\n workspace_mode?: WorkspaceMode;\n workspace?: string;\n proof?: TaskProof;\n review_criteria?: ReviewCriterion[];\n review_results?: ReviewResult[];\n scope?: string[];\n feedback?: string;\n}\n\nexport interface CreateTaskInput {\n title: string;\n description?: string;\n priority?: number;\n assignee?: string;\n labels?: string[];\n depends_on?: string[];\n max_attempts?: number;\n workspace_mode?: WorkspaceMode;\n review_criteria?: ReviewCriterion[];\n scope?: string[];\n}\n","/**\n * Template engine for prompt construction.\n *\n * Uses LiquidJS for Liquid-compatible templating with\n * task, agent, project, and run context variables.\n */\n\nimport type { Liquid } from 'liquidjs';\nimport type { Agent } from '../../domain/agent.js';\nimport type { OrchestratorConfig } from '../../domain/config.js';\nimport { AUTONOMOUS_LABEL, type Task } from '../../domain/task.js';\n\nexport interface ITemplateEngine {\n render(template: string, context: PromptContext): Promise<string>;\n}\n\nexport interface AgentInfo {\n id: string;\n name: string;\n role?: string;\n adapter: string;\n}\n\nexport interface RetryContext {\n previous_error: string;\n previous_output: string;\n}\n\nexport interface PromptContext {\n project: {\n name: string;\n description?: string;\n };\n task: {\n id: string;\n title: string;\n description: string;\n priority: number;\n labels: string[];\n scope?: string[];\n is_autonomous: boolean;\n };\n agent: {\n id: string;\n name: string;\n role?: string;\n };\n agents: AgentInfo[];\n attempt: number | null;\n workspace_path: string;\n retry?: RetryContext;\n feedback?: string;\n shared_context?: Record<string, string>;\n messages?: Array<{\n id: string;\n from: string;\n subject: string;\n body: string;\n sent_at: string;\n reply_to?: string;\n }>;\n}\n\nexport class LiquidTemplateEngine implements ITemplateEngine {\n private engine: Liquid | undefined;\n private readonly renderTimeoutMs: number;\n\n constructor(options?: { renderTimeoutMs?: number }) {\n this.renderTimeoutMs = options?.renderTimeoutMs ?? 5_000;\n }\n\n private async getEngine(): Promise<Liquid> {\n if (!this.engine) {\n const { Liquid } = await import('liquidjs');\n this.engine = new Liquid({\n strictFilters: false,\n strictVariables: false,\n });\n }\n return this.engine;\n }\n\n async render(template: string, context: PromptContext): Promise<string> {\n const engine = await this.getEngine();\n const renderPromise = engine.parseAndRender(template, context);\n\n if (this.renderTimeoutMs <= 0) {\n return renderPromise;\n }\n\n let timer: ReturnType<typeof setTimeout>;\n const timeoutPromise = new Promise<never>((_, reject) => {\n timer = setTimeout(\n () => reject(new Error(`Template render timed out after ${this.renderTimeoutMs}ms`)),\n this.renderTimeoutMs,\n );\n });\n\n try {\n return await Promise.race([renderPromise, timeoutPromise]);\n } finally {\n clearTimeout(timer!);\n }\n }\n}\n\n/**\n * Build prompt context from domain objects.\n */\nexport interface BuildPromptOptions {\n allAgents?: Agent[];\n retryContext?: RetryContext;\n sharedContext?: Record<string, string>;\n feedback?: string;\n messages?: import('../../domain/message.js').Message[];\n}\n\nexport function buildPromptContext(\n task: Task,\n agent: Agent,\n attempt: number,\n workspacePath: string,\n config: OrchestratorConfig,\n options?: BuildPromptOptions,\n): PromptContext {\n const { allAgents, retryContext, sharedContext, feedback, messages: rawMessages } = options ?? {};\n\n // Map messages to prompt-friendly shape\n const agentById = new Map((allAgents ?? []).map((a) => [a.id, a]));\n const messages = rawMessages?.length\n ? rawMessages.map((m) => ({\n id: m.id,\n from: agentById.get(m.from_agent_id)?.name ?? m.from_agent_id,\n subject: m.subject,\n body: m.body,\n sent_at: m.created_at,\n reply_to: m.reply_to,\n }))\n : undefined;\n\n return {\n project: {\n name: config.project.name,\n description: config.project.description,\n },\n task: {\n id: task.id,\n title: task.title,\n description: task.description,\n priority: task.priority,\n labels: task.labels,\n scope: task.scope,\n is_autonomous: task.labels?.includes(AUTONOMOUS_LABEL) ?? false,\n },\n agent: {\n id: agent.id,\n name: agent.name,\n role: agent.role,\n },\n agents: (allAgents ?? []).map((a) => ({\n id: a.id,\n name: a.name,\n role: a.role,\n adapter: a.adapter,\n })),\n attempt: attempt > 1 ? attempt : null,\n workspace_path: workspacePath,\n retry: attempt > 1 ? retryContext : undefined,\n feedback,\n shared_context: sharedContext && Object.keys(sharedContext).length > 0 ? sharedContext : undefined,\n messages,\n };\n}\n\n/** Default prompt template */\nexport const DEFAULT_PROMPT_TEMPLATE = `You are {{ agent.name }}{% if agent.role %} ({{ agent.role }}){% endif %}.\n\n## Task: {{ task.title }}\n{{ task.description }}\n\nPriority: {{ task.priority }}\n{% if attempt %}Attempt: {{ attempt }}{% endif %}\n{% if retry %}\n## Previous attempt failed\n**Error:** {{ retry.previous_error }}\n{% if retry.previous_output != \"\" %}\n**Last output:**\n\\`\\`\\`\n{{ retry.previous_output }}\n\\`\\`\\`\n{% endif %}\n**Important:** The previous approach failed. Analyze the error above and try a different strategy. Do NOT repeat the same steps that led to the failure.\n{% endif %}\n\n## Context\nProject: {{ project.name }}\nWorking directory: {{ workspace_path }}\n\n## Team\nYou are part of a multi-agent team. Available agents:\n{% for a in agents %}- **{{ a.name }}** ({{ a.adapter }}){% if a.role %} — {{ a.role }}{% endif %} · ID: \\`{{ a.id }}\\`\n{% endfor %}\nUse \\`orch agent list\\` to check current agent statuses. Find teammates by name/role — do NOT hardcode agent IDs.\n\n{% if feedback %}\n## Review Feedback\nThis task was previously completed but **rejected** during review with the following feedback:\n> {{ feedback }}\n\n**Important:** Address the feedback above. Focus on what the reviewer asked to change. Do NOT redo work that was already accepted.\n{% endif %}\n\n{% if shared_context %}\n## Shared Context\nOther agents have shared the following information:\n{% for entry in shared_context %}- **{{ entry[0] }}**: {{ entry[1] }}\n{% endfor %}\n{% endif %}\n\n{% if messages %}\n## Inbox ({{ messages.size }} message{% if messages.size != 1 %}s{% endif %})\n{% for msg in messages %}\n---\n**From:** {{ msg.from }}{% if msg.subject != \"\" %} · **Subject:** {{ msg.subject }}{% endif %}\n{{ msg.body }}\n{% if msg.reply_to %}*(Reply to: {{ msg.reply_to }})*{% endif %}\n---\n{% endfor %}\n{% endif %}\n\n## Orchestrator CLI\nManage tasks and coordinate with other agents using \\`orch\\`:\n\n**Tasks:**\n- \\`orch task add \"<title>\" -d \"<description>\" -p <1-4> --assignee <agent-id>\\` — create and assign a task\n- \\`orch task add \"<title>\" -d \"<description>\" --scope \"src/path/**\" --depends-on <task-id>\\` — scoped task with dependency\n- \\`orch task list [--status todo|in_progress|done|failed]\\` — list tasks\n\n**Messaging:**\n- \\`orch msg send <agent-id> \"<body>\" -s \"<subject>\"\\` — direct message\n- \\`orch msg broadcast \"<body>\" -s \"<subject>\"\\` — broadcast to all\n- \\`orch msg inbox {{ agent.id }}\\` — your pending messages\n\n**Shared context:**\n- \\`orch context set <key> <value>\\` / \\`orch context get <key>\\` / \\`orch context list\\`\n\n{% if task.is_autonomous %}\n## Autonomous Goal Mode\nThis is an autonomous task driven by a goal. Work in a continuous loop until the goal is achieved:\n\n1. **Read the GOAL section** above — understand the desired outcome.\n2. **Decompose** — break the goal into concrete subtasks via \\`orch task add\\`. Assign yourself for your specialty, delegate other work to appropriate teammates by role.\n3. **Execute** — follow your standard workflow for each subtask.\n4. **Track progress** — after each iteration: \\`orch context set <goal>-progress \"<done, remaining>\"\\`.\n5. **Be proactive** — do NOT wait for tasks from others. Create your own subtasks and keep working.\n6. **Do NOT finish** the [auto] task until the goal is achieved — keep creating subtasks.\n7. **When done** — \\`orch context set <goal>-status \"ACHIEVED: <summary>\"\\`.\n{% endif %}\n\n## Rules\n- Do NOT ask clarifying questions. You are running autonomously without human input.\n- Make reasonable assumptions and proceed with the best approach.\n- If critical information is missing, document your assumptions and continue.\n- When a task is too large or spans multiple domains, break it into subtasks using \\`orch task add\\`.\n- When creating subtasks, use \\`--scope\\` to declare which files each task will touch, and \\`--depends-on\\` to order dependent work.\n`;\n"]}
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env node
2
+ import { spawn } from 'child_process';
3
+
4
+ var ProcessManager = class {
5
+ isAlive(pid) {
6
+ try {
7
+ process.kill(pid, 0);
8
+ return true;
9
+ } catch (err) {
10
+ if (err.code === "EPERM") return true;
11
+ return false;
12
+ }
13
+ }
14
+ kill(pid, signal = "SIGTERM") {
15
+ try {
16
+ process.kill(-pid, signal);
17
+ } catch {
18
+ try {
19
+ process.kill(pid, signal);
20
+ } catch {
21
+ }
22
+ }
23
+ }
24
+ async killWithGrace(pid, graceMs = 1e4) {
25
+ if (!this.isAlive(pid)) return;
26
+ this.kill(pid, "SIGTERM");
27
+ const deadline = Date.now() + graceMs;
28
+ while (Date.now() < deadline) {
29
+ if (!this.isAlive(pid)) return;
30
+ await new Promise((r) => setTimeout(r, 200));
31
+ }
32
+ this.kill(pid, "SIGKILL");
33
+ }
34
+ spawn(command, args, options) {
35
+ const proc = spawn(command, args, {
36
+ stdio: ["ignore", "pipe", "pipe"],
37
+ detached: true,
38
+ // Create new process group so killWithGrace(-pid) kills all children
39
+ ...options
40
+ });
41
+ if (!proc.pid) {
42
+ throw new Error(`Failed to spawn process: ${command}`);
43
+ }
44
+ proc.unref();
45
+ return { process: proc, pid: proc.pid };
46
+ }
47
+ };
48
+ var MAX_LINE_LEN = 16384;
49
+ function capLine(s) {
50
+ return s.length > MAX_LINE_LEN ? s.slice(0, MAX_LINE_LEN) : s;
51
+ }
52
+ async function* readLines(stream) {
53
+ const chunks = [];
54
+ let totalLen = 0;
55
+ for await (const chunk of stream) {
56
+ const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf-8");
57
+ if (buf.length === 0) continue;
58
+ chunks.push(buf);
59
+ totalLen += buf.length;
60
+ const buffer = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks, totalLen);
61
+ chunks.length = 0;
62
+ totalLen = 0;
63
+ let offset = 0;
64
+ let newlineIdx;
65
+ while ((newlineIdx = buffer.indexOf(10, offset)) !== -1) {
66
+ if (newlineIdx > offset) {
67
+ yield capLine(buffer.toString("utf-8", offset, newlineIdx));
68
+ }
69
+ offset = newlineIdx + 1;
70
+ }
71
+ if (offset < buffer.length) {
72
+ const remainder = buffer.subarray(offset);
73
+ chunks.push(remainder);
74
+ totalLen = remainder.length;
75
+ }
76
+ }
77
+ if (totalLen > 0) {
78
+ const final = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks, totalLen);
79
+ yield capLine(final.toString("utf-8"));
80
+ }
81
+ }
82
+
83
+ export { ProcessManager, readLines };
@@ -0,0 +1,217 @@
1
+ #!/usr/bin/env node
2
+ import { readLines } from './chunk-CHIP7O6V.js';
3
+ import { execFile } from 'child_process';
4
+ import { promisify } from 'util';
5
+
6
+ // src/infrastructure/adapters/event-buffer.ts
7
+ var DEFAULT_CAPACITY = 1024;
8
+ function deferred() {
9
+ let resolve;
10
+ const promise = new Promise((r) => {
11
+ resolve = r;
12
+ });
13
+ return { promise, resolve };
14
+ }
15
+ var EventBuffer = class {
16
+ buf;
17
+ head = 0;
18
+ // read index
19
+ tail = 0;
20
+ // write index
21
+ count = 0;
22
+ capacity;
23
+ // Consumer notification: resolved when new data is available
24
+ dataReady = null;
25
+ // Producer notification: resolved when space is available
26
+ spaceReady = null;
27
+ closed = false;
28
+ constructor(capacity = DEFAULT_CAPACITY) {
29
+ this.capacity = capacity;
30
+ this.buf = new Array(capacity);
31
+ }
32
+ /** Number of buffered events. */
33
+ get size() {
34
+ return this.count;
35
+ }
36
+ get isFull() {
37
+ return this.count >= this.capacity;
38
+ }
39
+ /**
40
+ * Push an event into the buffer.
41
+ * If the buffer is full, waits until space is available (backpressure).
42
+ */
43
+ async push(event) {
44
+ while (this.isFull && !this.closed) {
45
+ if (!this.spaceReady) {
46
+ this.spaceReady = deferred();
47
+ }
48
+ await this.spaceReady.promise;
49
+ }
50
+ if (this.closed) return;
51
+ this.buf[this.tail] = event;
52
+ this.tail = (this.tail + 1) % this.capacity;
53
+ this.count++;
54
+ if (this.dataReady) {
55
+ const dr = this.dataReady;
56
+ this.dataReady = null;
57
+ dr.resolve();
58
+ }
59
+ }
60
+ /**
61
+ * Dequeue the next event. O(1).
62
+ * Returns undefined only when buffer is empty AND closed.
63
+ */
64
+ async take() {
65
+ while (this.count === 0) {
66
+ if (this.closed) return void 0;
67
+ if (!this.dataReady) {
68
+ this.dataReady = deferred();
69
+ }
70
+ await this.dataReady.promise;
71
+ }
72
+ const event = this.buf[this.head];
73
+ this.buf[this.head] = void 0;
74
+ this.head = (this.head + 1) % this.capacity;
75
+ this.count--;
76
+ if (this.spaceReady) {
77
+ const sr = this.spaceReady;
78
+ this.spaceReady = null;
79
+ sr.resolve();
80
+ }
81
+ return event;
82
+ }
83
+ /**
84
+ * Signal that no more events will be pushed.
85
+ * Wakes up any waiting consumer/producer.
86
+ */
87
+ close() {
88
+ this.closed = true;
89
+ if (this.dataReady) {
90
+ const dr = this.dataReady;
91
+ this.dataReady = null;
92
+ dr.resolve();
93
+ }
94
+ if (this.spaceReady) {
95
+ const sr = this.spaceReady;
96
+ this.spaceReady = null;
97
+ sr.resolve();
98
+ }
99
+ }
100
+ get isClosed() {
101
+ return this.closed;
102
+ }
103
+ /**
104
+ * Async iterator that drains the buffer until closed and empty.
105
+ */
106
+ async *[Symbol.asyncIterator]() {
107
+ while (true) {
108
+ const event = await this.take();
109
+ if (event === void 0) return;
110
+ yield event;
111
+ }
112
+ }
113
+ };
114
+ var execFileAsync = promisify(execFile);
115
+ var ShellAdapter = class {
116
+ constructor(processManager) {
117
+ this.processManager = processManager;
118
+ }
119
+ kind = "shell";
120
+ async test() {
121
+ try {
122
+ const { stdout } = await execFileAsync("bash", ["--version"]);
123
+ const version = stdout.split("\n")[0]?.trim() ?? "unknown";
124
+ return { ok: true, version };
125
+ } catch {
126
+ return { ok: false, error: "bash not found" };
127
+ }
128
+ }
129
+ execute(params) {
130
+ const command = params.config.command;
131
+ if (!command) {
132
+ async function* errorGen() {
133
+ yield {
134
+ type: "error",
135
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
136
+ data: "Shell adapter requires a command in agent config"
137
+ };
138
+ }
139
+ return { pid: 0, events: errorGen() };
140
+ }
141
+ const { process: proc, pid } = this.processManager.spawn("bash", ["-lc", command], {
142
+ cwd: params.workspace,
143
+ env: {
144
+ ...process.env,
145
+ ...params.env,
146
+ ORCHESTRY_TASK_PROMPT: params.prompt
147
+ },
148
+ signal: params.signal
149
+ });
150
+ const signal = params.signal;
151
+ const processManager = this.processManager;
152
+ async function* generateEvents() {
153
+ const buffer = new EventBuffer();
154
+ const onAbort = () => {
155
+ processManager.killWithGrace(pid, 5e3).catch(() => {
156
+ });
157
+ };
158
+ if (signal) {
159
+ if (signal.aborted) {
160
+ onAbort();
161
+ } else {
162
+ signal.addEventListener("abort", onAbort, { once: true });
163
+ }
164
+ }
165
+ const stdoutPromise = (async () => {
166
+ if (!proc.stdout) return;
167
+ for await (const line of readLines(proc.stdout)) {
168
+ if (signal?.aborted) break;
169
+ await buffer.push({
170
+ type: "output",
171
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
172
+ data: line
173
+ });
174
+ }
175
+ })();
176
+ const stderrPromise = (async () => {
177
+ if (!proc.stderr) return;
178
+ for await (const line of readLines(proc.stderr)) {
179
+ if (signal?.aborted) break;
180
+ await buffer.push({
181
+ type: "error",
182
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
183
+ data: line
184
+ });
185
+ }
186
+ })();
187
+ void Promise.all([stdoutPromise, stderrPromise]).then(
188
+ () => buffer.close(),
189
+ () => buffer.close()
190
+ );
191
+ yield* buffer;
192
+ if (signal && !signal.aborted) {
193
+ signal.removeEventListener("abort", onAbort);
194
+ }
195
+ await new Promise((resolve, reject) => {
196
+ if (proc.exitCode !== null || proc.killed) {
197
+ resolve();
198
+ return;
199
+ }
200
+ proc.on("close", (code) => {
201
+ if (code === 0 || signal?.aborted) {
202
+ resolve();
203
+ } else {
204
+ reject(new Error(`Shell command exited with code ${code}`));
205
+ }
206
+ });
207
+ proc.on("error", reject);
208
+ });
209
+ }
210
+ return { pid, events: generateEvents() };
211
+ }
212
+ async stop(pid) {
213
+ await this.processManager.killWithGrace(pid);
214
+ }
215
+ };
216
+
217
+ export { ShellAdapter };
@@ -0,0 +1,13 @@
1
+ import {d,h,e}from'./chunk-ZU6AY2VU.js';import {a,d as d$1,c}from'./chunk-AELEEEV3.js';import {dirname}from'path';import k from'fs/promises';import {execFile}from'child_process';var J={todo:["in_progress","cancelled"],in_progress:["review","retrying","failed","cancelled"],retrying:["in_progress","failed","cancelled"],review:["done","todo","cancelled"],done:[],failed:["todo","retrying"],cancelled:["todo"]},Q=new Set(["done","failed","cancelled"]);function st(c,t){return J[c].includes(t)}function P(c){return Q.has(c)}function D(c){return c==="todo"||c==="retrying"}function G(c,t){return c.depends_on.length===0?false:c.depends_on.some(e=>{let s=t.find(a=>a.id===e);return !s||s.status!=="done"})}function A(c){return c.attempts<c.max_attempts?"retrying":"failed"}function N(c,t,e){return "review"}function F(c,t,e){let s=t*Math.pow(2,c);return Math.min(s,e)}function U(c,t){if(!c?.length||!t?.length)return false;for(let e of c)for(let s of t)if(V(e,s))return true;return false}function V(c,t){if(c===t)return true;let e=c.split("*")[0],s=t.split("*")[0];if(e.startsWith(s)||s.startsWith(e))return true;if(!e.endsWith("/")&&!s.endsWith("/")){let a=dirname(e),l=dirname(s);return a===l&&a!=="."}return false}async function C(c){let t=c+".bak",e=await H(c);if(e!==null){if(X(e))return {acquired:false,pid:e};try{await k.rename(c,t);}catch{}}try{let s=await k.open(c,"wx");return await s.writeFile(String(process.pid),"utf-8"),await s.close(),await k.unlink(t).catch(()=>{}),{acquired:!0,pid:process.pid}}catch(s){if(s.code==="EEXIST")return await k.rename(t,c).catch(()=>{}),{acquired:false,pid:await H(c)??void 0};throw s}}async function B(c){await k.unlink(c).catch(()=>{});}async function H(c){try{let t=await k.readFile(c,"utf-8"),e=parseInt(t.trim(),10);return isNaN(e)?null:e}catch{return null}}function X(c){try{return process.kill(c,0),!0}catch(t){return t.code==="EPERM"}}var R=class{constructor(t){this.inner=t;}cache=new Map;async list(t){let e=t?.status??"__all__";if(this.cache.has(e))return this.cache.get(e);let s=await this.inner.list(t);return this.cache.set(e,s),s}async get(t){return this.inner.get(t)}async save(t){await this.inner.save(t),this.cache.clear();}async delete(t){await this.inner.delete(t),this.cache.clear();}invalidate(){this.cache.clear();}},b=class{constructor(t){this.inner=t;}listCache=null;async list(){if(this.listCache)return this.listCache;let t=await this.inner.list();return this.listCache=t,t}async get(t){return this.inner.get(t)}async getByName(t){return this.inner.getByName(t)}async save(t){await this.inner.save(t),this.listCache=null;}async delete(t){await this.inner.delete(t),this.listCache=null;}invalidate(){this.listCache=null;}},x=class{constructor(t){this.inner=t;}cache=new Map;async list(t){let e=t?.status??"__all__";if(this.cache.has(e))return this.cache.get(e);let s=await this.inner.list(t);return this.cache.set(e,s),s}async get(t){return this.inner.get(t)}async save(t){await this.inner.save(t),this.cache.clear();}async delete(t){await this.inner.delete(t),this.cache.clear();}invalidate(){this.cache.clear();}};var Y={test_pass:{cmd:"npm",args:["test"]},typecheck:{cmd:"npx",args:["tsc","--noEmit"]},lint:{cmd:"npm",args:["run","lint"]}},_=class{cwd;timeoutMs;constructor(t){this.cwd=t.cwd,this.timeoutMs=t.timeout_ms??12e4;}async runAll(t){let e=[];for(let s of t){let a=await this.runCriterion(s);e.push(a);}return e}static allPassed(t){return t.length>0&&t.every(e=>e.passed)}static formatReport(t){return t.map(s=>{let a=s.passed?"\u2713":"\u2717",l=s.output.slice(0,500);return `${a} ${s.criterion}: ${s.passed?"PASSED":"FAILED"}
2
+ ${l}`}).join(`
3
+
4
+ `)}runCriterion(t){let{cmd:e,args:s}=Y[t];return new Promise(a=>{execFile(e,s,{cwd:this.cwd,timeout:this.timeoutMs,maxBuffer:1024*1024},(l,r,i)=>{let u=(r+`
5
+ `+i).trim();a({criterion:t,passed:!l,output:u.slice(0,2e3)});});})}};var Z=8192,tt=4096,W=class{constructor(t){this.deps=t;this.cachedTaskStore=new R(t.taskStore),this.cachedAgentStore=new b(t.agentStore),this.cachedGoalStore=t.goalStore?new x(t.goalStore):null;}intervalId=null;shuttingDown=false;state=null;abortControllers=new Map;cachedTaskStore;cachedAgentStore;cachedGoalStore;saveStateTimer=null;saveStateDirty=false;lockAcquired=false;consecutiveTickFailures=0;maxConsecutiveTickFailures=5;maxRetryQueueSize=100;signalHandlers=[];immediateDispatchTimer=null;taskCreatedUnsub=null;tickInProgress=false;stateMutex=Promise.resolve();get isOwner(){return this.lockAcquired}withStateLock(t){let e,s=new Promise(l=>{e=l;}),a=this.stateMutex;return this.stateMutex=s,a.then(async()=>{try{return await t()}finally{e();}})}async runTask(t){await this.withTemporaryLock(async()=>{await this.loadState(),await this.dispatchTask(t);});}async runAll(){await this.withTemporaryLock(async()=>{await this.loadState(),await this.dispatchAll();});}async withTemporaryLock(t){let e=await C(this.deps.lockPath);if(!e.acquired)throw new d(e.pid);this.lockAcquired=true;try{await t();}finally{this.lockAcquired=false,await B(this.deps.lockPath);}}async startWatch(){let t=await C(this.deps.lockPath);if(!t.acquired)throw new d(t.pid);this.lockAcquired=true,await this.loadState(),this.state.pid=process.pid,this.state.started_at=new Date().toISOString(),await this.saveState(),this.registerSignalHandlers(),this.taskCreatedUnsub=this.deps.eventBus.on("task:created",()=>{this.scheduleImmediateDispatch();}),await this.tick(),this.intervalId=setInterval(()=>this.tick().then(()=>{this.consecutiveTickFailures=0;},e=>{this.consecutiveTickFailures++;let s=e instanceof Error?e.message:String(e);this.deps.eventBus.emit({type:"orchestrator:error",error:s,context:"tick",fatal:this.consecutiveTickFailures>=this.maxConsecutiveTickFailures}),this.consecutiveTickFailures>=this.maxConsecutiveTickFailures&&(this.deps.eventBus.emit({type:"orchestrator:shutdown",reason:`${this.consecutiveTickFailures} consecutive tick failures`}),this.stop().catch(a=>{this.deps.eventBus.emit({type:"orchestrator:error",error:a instanceof Error?a.message:String(a),context:"stop after consecutive tick failures",fatal:false});}));}),this.deps.config.scheduling.poll_interval_ms);}registerSignalHandlers(){let t=e=>{this.deps.eventBus.emit({type:"orchestrator:shutdown",reason:`Received ${e}`}),this.stop().catch(s=>{this.deps.eventBus.emit({type:"orchestrator:error",error:s instanceof Error?s.message:String(s),context:`stop after ${e} signal`,fatal:false});});};for(let e of ["SIGINT","SIGTERM"]){let s=()=>t(e);this.signalHandlers.push([e,s]),process.on(e,s);}}removeSignalHandlers(){for(let[t,e]of this.signalHandlers)process.removeListener(t,e);this.signalHandlers=[];}async stop(){this.shuttingDown||(this.shuttingDown=true,this.intervalId&&(clearInterval(this.intervalId),this.intervalId=null),this.taskCreatedUnsub&&(this.taskCreatedUnsub(),this.taskCreatedUnsub=null),this.immediateDispatchTimer&&(clearTimeout(this.immediateDispatchTimer),this.immediateDispatchTimer=null),await this.flushStateLazy(),await this.withStateLock(async()=>{if(this.state){for(let[t,e]of Object.entries(this.state.running)){this.abortControllers.get(t)?.abort(),this.abortControllers.delete(t),await this.deps.processManager.killWithGrace(e.pid),await this.deps.runService.finish(e.run_id,"cancelled");let s=await this.deps.taskStore.get(t);s&&await this.deps.taskService.updateStatus(t,A(s)),await this.deps.agentService.setStatus(e.agent_id,"idle");}this.state.running={},this.state.claimed=[],this.state.pid=void 0,this.state.started_at=void 0,await this.saveState();}}),this.lockAcquired&&(await B(this.deps.lockPath),this.lockAcquired=false),this.removeSignalHandlers());}async cancelTask(t){if(!this.lockAcquired)return this.withTemporaryLock(()=>this.cancelTask(t));await this.withStateLock(async()=>{await this.loadState();let e=this.state,s=e.running[t];s&&(this.abortControllers.get(t)?.abort(),this.abortControllers.delete(t),await this.deps.processManager.killWithGrace(s.pid,3e3).catch(a=>{this.deps.eventBus.emit({type:"orchestrator:error",error:a instanceof Error?a.message:String(a),context:`cancelTask kill process ${s.pid} for task ${t}`,fatal:false});}),await this.deps.runService.finish(s.run_id,"cancelled").catch(a=>{this.deps.eventBus.emit({type:"orchestrator:error",error:a instanceof Error?a.message:String(a),context:`cancelTask finish run ${s.run_id}`,fatal:false});}),await this.deps.agentService.setStatus(s.agent_id,"idle").catch(a=>{this.deps.eventBus.emit({type:"orchestrator:error",error:a instanceof Error?a.message:String(a),context:`cancelTask setStatus idle for agent ${s.agent_id}`,fatal:false});}),delete e.running[t],await this.saveState()),e.retry_queue=e.retry_queue.filter(a=>a.task_id!==t);try{await this.deps.taskService.cancel(t);}catch{try{await this.deps.taskService.updateStatus(t,"cancelled");}catch{}}await this.saveState();});}async forceStopAgent(t){if(!this.lockAcquired)return this.withTemporaryLock(()=>this.forceStopAgent(t));await this.withStateLock(async()=>{await this.loadState();let e=this.state;for(let[s,a]of Object.entries(e.running))if(a.agent_id===t){this.abortControllers.get(s)?.abort(),this.abortControllers.delete(s),await this.deps.processManager.killWithGrace(a.pid,3e3),await this.deps.runService.finish(a.run_id,"cancelled");try{await this.deps.taskService.updateStatus(s,"failed");}catch{}delete e.running[s];}await this.deps.agentService.setStatus(t,"idle"),await this.saveState();});}async tick(){if(!this.shuttingDown){this.tickInProgress=true;try{await this.withStateLock(async()=>{if(this.shuttingDown)return;this.cachedTaskStore.invalidate(),this.cachedAgentStore.invalidate(),this.cachedGoalStore?.invalidate(),await this.loadState(),await this.reconcile(),await this.seedAutonomousTasks(),await this.dispatchAll();let t=await this.cachedTaskStore.list(),e=Object.keys(this.state.running).length,s=t.filter(a=>D(a.status)).length;this.deps.eventBus.emit({type:"orchestrator:tick",running:e,queued:s});});}finally{this.tickInProgress=false;}}}scheduleImmediateDispatch(){this.shuttingDown||this.immediateDispatchTimer||(this.immediateDispatchTimer=setTimeout(()=>{this.immediateDispatchTimer=null,!(this.shuttingDown||this.tickInProgress)&&this.immediateDispatch().catch(t=>{this.deps.eventBus.emit({type:"orchestrator:error",error:t instanceof Error?t.message:String(t),context:"immediate dispatch on task:created",fatal:false});});},500));}async immediateDispatch(){this.shuttingDown||await this.withStateLock(async()=>{this.shuttingDown||(this.cachedTaskStore.invalidate(),this.cachedAgentStore.invalidate(),await this.loadState(),await this.dispatchAll(),await this.saveState());});}async reconcile(){let t=this.state,e=Date.now();for(let[r,i]of Object.entries(t.running)){let u=await this.deps.taskStore.get(r);if(!u||P(u.status)){this.abortControllers.delete(r),delete t.running[r],await this.deps.agentService.setStatus(i.agent_id,"idle").catch(d=>{this.deps.eventBus.emit({type:"orchestrator:error",error:d instanceof Error?d.message:String(d),context:`reconcile setStatus idle for stale agent ${i.agent_id} (task ${r})`,fatal:false});});continue}if(!this.deps.processManager.isAlive(i.pid)){try{await this._handleRunFailure(r,i,"Process crashed unexpectedly");}catch{delete t.running[r],await this.deps.agentService.setStatus(i.agent_id,"idle").catch(d=>{this.deps.eventBus.emit({type:"orchestrator:error",error:d instanceof Error?d.message:String(d),context:`reconcile crash fallback setStatus idle for agent ${i.agent_id} (task ${r})`,fatal:false});});}continue}let o=new Date(i.last_event_at).getTime(),n=this.deps.config.defaults.agent.stall_timeout_ms;if(e-o>n){this.deps.eventBus.emit({type:"orchestrator:stall_detected",runId:i.run_id}),this.abortControllers.get(r)?.abort(),await this.deps.processManager.killWithGrace(i.pid,5e3);try{await this._handleRunFailure(r,i,"Agent stalled (no events)");}catch{delete t.running[r],await this.deps.agentService.setStatus(i.agent_id,"idle").catch(d=>{this.deps.eventBus.emit({type:"orchestrator:error",error:d instanceof Error?d.message:String(d),context:`reconcile stall fallback setStatus idle for agent ${i.agent_id} (task ${r})`,fatal:false});});}}}let s=new Set(Object.values(t.running).map(r=>r.agent_id)),a=await this.cachedAgentStore.list();for(let r of a)r.status==="running"&&!s.has(r.id)&&await this.deps.agentService.setStatus(r.id,"idle");let l=await this.cachedTaskStore.list();for(let r of l)if(r.status==="in_progress"&&!t.running[r.id]){try{await this.deps.taskService.updateStatus(r.id,"failed");}catch{r.status="failed",r.updated_at=new Date().toISOString(),await this.deps.taskStore.save(r).catch(i=>{this.deps.eventBus.emit({type:"orchestrator:error",error:i instanceof Error?i.message:String(i),context:`force-write orphaned task ${r.id}`,fatal:false});});}this.deps.eventBus.emit({type:"task:orphaned",taskId:r.id});}for(let r=t.retry_queue.length-1;r>=0;r--){let i=t.retry_queue[r];e>=new Date(i.due_at).getTime()&&(t.retry_queue.splice(r,1),await this.dispatchTask(i.task_id));}await this.saveState();}async seedAutonomousTasks(){let e=(await this.cachedAgentStore.list()).filter(i=>i.autonomous&&i.status==="idle");if(e.length===0)return;let s=await this.cachedTaskStore.list(),a$1=this.cachedGoalStore?await this.cachedGoalStore.list({status:"active"}):[],l=false,r=new Set;for(let i of e){if(s.some(h=>h.assignee===i.id&&!P(h.status)))continue;let o=a$1.find(h=>h.assignee===i.id&&!r.has(h.id))??a$1.find(h=>!h.assignee&&!r.has(h.id));o&&r.add(o.id);let n=i.role??"general assistant",d=o?`[auto] ${i.name}: ${o.title.slice(0,60)}`:`[auto] ${i.name}: ${n.slice(0,60)}`,g=o?`## GOAL (highest priority)
6
+
7
+ ${o.description||o.title}
8
+
9
+ ---
10
+ Agent role: ${n}`:`Autonomous work cycle. Agent role: ${n}`;try{await this.deps.taskService.create({title:d,description:g,assignee:i.id,labels:[a],priority:3}),l=!0;}catch(h){this.deps.eventBus.emit({type:"orchestrator:error",error:h instanceof Error?h.message:String(h),context:`autonomous task for agent ${i.id}`,fatal:false});}}l&&this.cachedTaskStore.invalidate();}async dispatchAll(){let t=this.state,e=this.deps.config.scheduling.max_concurrent_agents,s=Object.keys(t.running).length,a=e-s;if(a<=0)return;let l=await this.cachedTaskStore.list(),r=l.filter(o=>D(o.status)&&!G(o,l)&&!t.running[o.id]&&!t.claimed.includes(o.id)).sort((o,n)=>{let d=n.updated_at??"",g=o.updated_at??"";return d<g?-1:d>g?1:0}).slice(0,a),i=new Set,u=l.filter(o=>o.status==="in_progress"&&o.scope?.length);for(let o=0;o<r.length;o++){let n=r[o];if(!n.scope?.length)continue;let d=r.slice(0,o).filter(v=>!i.has(v.id)),g=[...u,...d],h=false;for(let v of g)if(U(n.scope,v.scope)){this.deps.eventBus.emit({type:"task:scope_overlap",taskId:n.id,overlappingTaskId:v.id,patterns:n.scope}),h=true;break}h&&i.add(n.id);}for(let o of r)if(!i.has(o.id))try{await this.dispatchTask(o.id);}catch(n){this.deps.eventBus.emit({type:"orchestrator:error",error:n instanceof Error?n.message:String(n),context:`dispatch task ${o.id}`,fatal:false});}}async dispatchTask(t){let e$1=this.state;if(e$1.running[t]){let a=e$1.running[t];throw new h(t,a.run_id,a.agent_id)}let s=await this.deps.taskService.get(t);e$1.claimed.push(t),await this.saveState();try{let a=await this.deps.agentService.findBestAgent(s);if(!a){if((await this.cachedAgentStore.list()).length===0)throw new e;this.unclaim(t),await this.saveState();return}let{path:l,branch:r}=await this.deps.workspaceManager.prepare(s,a,this.deps.config),i=this.deps.config.prompt?.template??d$1,u=await this.cachedAgentStore.list(),o=s.attempts+1,n;if(o>1){let w=await this.deps.runService.getLastFailedRunContext(s.id);w&&(n={previous_error:w.error,previous_output:w.output});}let d=this.deps.contextStore?await this.deps.contextStore.getAll():void 0,g=this.deps.messageService?await this.deps.messageService.drainMailbox(a.id,s.id):[],h=c(s,a,o,l,this.deps.config,{allAgents:u,retryContext:n,sharedContext:d,feedback:s.feedback,messages:g.length?g:void 0}),v=await this.deps.templateEngine.render(i,h),p=await this.deps.runService.create({taskId:s.id,agentId:a.id,attempt:o,prompt:v,workspacePath:l});(s.status==="failed"||s.status==="cancelled")&&(await this.deps.taskService.retry(t),s.status="todo",s.attempts=0),await this.deps.taskService.updateStatus(t,"in_progress"),await this.deps.taskService.assign(t,a.id),await this.deps.taskService.incrementAttempts(t),r&&(s.proof={...s.proof??{files_changed:[]},branch:r},s.workspace=l,await this.deps.taskStore.save(s)),await this.deps.agentService.setStatus(a.id,"running");let m=await this.deps.agentService.get(a.id);m.current_task=t,await this.deps.agentStore.save(m);let f=this.deps.adapterRegistry.require(a.adapter),S=new AbortController;this.abortControllers.set(t,S);let y=f.execute({prompt:v,workspace:l,env:{...a.config.env,ORCH_AGENT_ID:a.id,ORCH_AGENT_NAME:a.name,ORCH_TASK_ID:s.id},config:m.config,signal:S.signal}),M=y.pid,O=new Date().toISOString();await this.deps.runService.start(p.id,M),this.unclaim(t),e$1.running[t]={run_id:p.id,agent_id:a.id,task_id:t,pid:M,started_at:O,last_event_at:O},await this.saveState(),this.collectEvents(y.events,p.id,t,a.id).catch(w=>{this.deps.eventBus.emit({type:"orchestrator:error",error:w instanceof Error?w.message:String(w),context:`adapter execution for ${t}`,fatal:!1});});}catch(a){throw this.unclaim(t),await this.saveState(),a}}async collectEvents(t,e,s,a){let l,r,i,u=new Set;try{for await(let n of t){if(this.shuttingDown)break;if(n.type==="done"){n.tokens&&(l=n.tokens);let p=n.data;p&&typeof p.result=="string"&&(r=p.result);}if(n.type==="output"){let p=n.data;if(p){let m=typeof p.text=="string"?p.text:typeof p.message=="string"?p.message:void 0;m?.trim()&&(i=m);}}if(n.type==="file_change"){let p=n.data;if(p&&Array.isArray(p.paths))for(let m of p.paths)typeof m=="string"&&u.add(m);else {let m=p&&typeof p.path=="string"?p.path:typeof n.data=="string"?n.data:String(n.data);u.add(m);}}let d=et(n.timestamp)?n.timestamp:new Date().toISOString(),g=z(n.data,Z);n.data=void 0;let h={timestamp:d,type:n.type==="output"?"agent_output":n.type==="file_change"?"file_changed":n.type==="command"?"command_run":n.type==="tool_call"?"tool_call":n.type==="error"?"error":"done",data:g};await this.deps.runService.appendEvent(e,h),this.state?.running[s]&&(this.state.running[s].last_event_at=d,this.saveStateLazy());let v=z(g,tt);n.type==="output"||n.type==="tool_call"?this.deps.eventBus.emit({type:"agent:output",runId:e,agentId:a,data:v}):n.type==="file_change"?this.deps.eventBus.emit({type:"agent:file_changed",runId:e,agentId:a,path:typeof n.data=="string"?n.data:String(n.data)}):n.type==="error"&&this.deps.eventBus.emit({type:"agent:error",runId:e,agentId:a,error:v});}let o=r??i;await this.handleRunSuccess(s,e,a,l,o,[...u]);}catch(o){let n=o instanceof Error?o.message:String(o),d=this.state?.running[s];d&&await this.handleRunFailure(s,d,n);}}async handleRunSuccess(t,e,s,a,l,r){return this.withStateLock(()=>this._handleRunSuccess(t,e,s,a,l,r))}async _handleRunSuccess(t,e,s,a$1,l,r){await this.flushStateLazy(),this.abortControllers.delete(t);let i=this.state;if(!i.running[t])return;let u=await this.deps.taskStore.get(t);if(!u)return;u.proof={...u.proof,agent_summary:l?.slice(0,2e3)??u.proof?.agent_summary,files_changed:r?.length?r:u.proof?.files_changed??[]},delete u.feedback,await this.deps.taskStore.save(u);let o=await this.deps.agentStore.get(s),d=u.labels?.includes(a)||o?.config.approval_policy==="auto",g=N();await this.deps.runService.finish(e,"succeeded",a$1);let h=i.running[t],v=h?Date.now()-new Date(h.started_at).getTime():0;h&&(i.stats.total_runtime_ms+=v),delete i.running[t];let p={tasks_completed:(o?.stats.tasks_completed??0)+1,total_runs:(o?.stats.total_runs??0)+1,total_runtime_ms:(o?.stats.total_runtime_ms??0)+v};if(a$1&&(p.tokens_used=(o?.stats.tokens_used??0)+a$1.total),await this.deps.agentService.updateStats(s,p).catch(f=>{this.deps.eventBus.emit({type:"orchestrator:error",error:f instanceof Error?f.message:String(f),context:`agent stats update for ${s}`,fatal:false});}),i.stats.total_tasks_completed++,i.stats.total_runs++,a$1&&(i.stats.total_tokens.input+=a$1.input,i.stats.total_tokens.output+=a$1.output,i.stats.total_tokens.total=i.stats.total_tokens.input+i.stats.total_tokens.output),u.proof?.branch)try{let f=await this.deps.workspaceManager.mergeBack(u.proof.branch);if(f.success)this.deps.eventBus.emit({type:"workspace:merge_succeeded",taskId:t,branch:u.proof.branch}),await this.deps.workspaceManager.cleanup(t).catch(S=>{this.deps.eventBus.emit({type:"orchestrator:error",error:S instanceof Error?S.message:String(S),context:`workspace cleanup for ${t}`,fatal:!1});});else {this.deps.eventBus.emit({type:"workspace:merge_conflict",taskId:t,branch:u.proof.branch,conflictInfo:f.conflictInfo}),await this.forceTaskToReview(u,s,`MERGE CONFLICT: ${f.conflictInfo}`);return}}catch(f){let S=f instanceof Error?f.message:String(f);await this.forceTaskToReview(u,s,`MERGE ERROR: ${S}`);return}try{await this.deps.taskService.updateStatus(t,g);}catch(f){let S=f instanceof Error?f.message:String(f);this.deps.eventBus.emit({type:"orchestrator:error",error:S,context:`state machine validation failed for task ${t} -> ${g}, force-writing`,fatal:false}),u.status=g,u.updated_at=new Date().toISOString(),await this.deps.taskStore.save(u).catch(y=>{this.deps.eventBus.emit({type:"orchestrator:error",error:y instanceof Error?y.message:String(y),context:`force-write task ${t} to store failed`,fatal:false});});}await this.deps.agentService.setStatus(s,"idle").catch(f=>{this.deps.eventBus.emit({type:"orchestrator:error",error:f instanceof Error?f.message:String(f),context:`_handleRunSuccess setStatus idle for agent ${s}`,fatal:false});});let m=await this.deps.agentStore.get(s);m&&(m.current_task=void 0,await this.deps.agentStore.save(m)),u.review_criteria?.length?await this.runAutoReview(t,u.review_criteria,u.workspace??this.deps.projectRoot):d&&await this.deps.taskService.updateStatus(t,"done"),await this.saveState(),this.scheduleImmediateDispatch();}async handleRunFailure(t,e,s){return this.withStateLock(()=>this._handleRunFailure(t,e,s))}async _handleRunFailure(t,e,s){await this.flushStateLazy(),this.abortControllers.delete(t);let a=this.state,l=await this.deps.taskStore.get(t);if(!l)return;await this.deps.runService.finish(e.run_id,"failed",void 0,s),await this.deps.agentService.setStatus(e.agent_id,"idle");let r=await this.deps.agentStore.get(e.agent_id);r&&(r.current_task=void 0,await this.deps.agentStore.save(r));let i=await this.deps.agentStore.get(e.agent_id),u=Date.now()-new Date(e.started_at).getTime();await this.deps.agentService.updateStats(e.agent_id,{tasks_failed:(i?.stats.tasks_failed??0)+1,total_runs:(i?.stats.total_runs??0)+1,total_runtime_ms:(i?.stats.total_runtime_ms??0)+u});let o=A(l);if(await this.deps.taskService.updateStatus(t,o),o==="retrying"){let n=F(l.attempts-1,this.deps.config.scheduling.retry_base_delay_ms,this.deps.config.scheduling.retry_max_delay_ms);a.retry_queue.some(g=>g.task_id===t)||(a.retry_queue.length>=this.maxRetryQueueSize&&a.retry_queue.shift(),a.retry_queue.push({task_id:t,attempt:l.attempts+1,due_at:new Date(Date.now()+n).toISOString(),error:s})),this.deps.eventBus.emit({type:"run:retry",runId:e.run_id,attempt:l.attempts+1,delay_ms:n});}else a.stats.total_tasks_failed++;a.stats.total_runtime_ms+=u,delete a.running[t],a.stats.total_runs++,await this.saveState(),this.scheduleImmediateDispatch();}async runAutoReview(t,e,s){let l=await new _({cwd:s}).runAll(e),r=_.allPassed(l),i=await this.deps.taskStore.get(t);if(i&&(i.review_results=l,i.proof={...i.proof,test_results:_.formatReport(l),files_changed:i.proof?.files_changed??[]},await this.deps.taskStore.save(i),this.deps.eventBus.emit({type:"task:auto_reviewed",taskId:t,passed:r,results:l}),r))try{await this.deps.taskService.updateStatus(t,"done");}catch(u){let o=u instanceof Error?u.message:String(u);this.deps.eventBus.emit({type:"orchestrator:error",error:o,context:`auto-review transition failed for task ${t} -> done, force-writing`,fatal:false}),i.status="done",i.updated_at=new Date().toISOString(),await this.deps.taskStore.save(i).catch(n=>{this.deps.eventBus.emit({type:"orchestrator:error",error:n instanceof Error?n.message:String(n),context:`force-write task ${t} to store failed (auto-review)`,fatal:false});});}}async forceTaskToReview(t,e,s){t.proof={...t.proof,agent_summary:`${s}
11
+
12
+ ${t.proof?.agent_summary??""}`.slice(0,2e3),files_changed:t.proof?.files_changed??[]},t.status="review",t.updated_at=new Date().toISOString(),await this.deps.taskStore.save(t),await this.deps.agentService.setStatus(e,"idle").catch(l=>{this.deps.eventBus.emit({type:"orchestrator:error",error:l instanceof Error?l.message:String(l),context:`forceTaskToReview setStatus idle for agent ${e}`,fatal:false});});let a=await this.deps.agentStore.get(e);a&&(a.current_task=void 0,await this.deps.agentStore.save(a)),await this.saveState();}unclaim(t){let e=this.state.claimed.indexOf(t);e!==-1&&this.state.claimed.splice(e,1);}requireOwnership(){if(!this.lockAcquired)throw new d(0)}async loadState(){this.state=await this.deps.stateStore.read();}async saveState(){this.state&&await this.deps.stateStore.write(this.state);}saveStateLazy(){this.saveStateDirty=true,!this.saveStateTimer&&(this.saveStateTimer=setTimeout(()=>{this.saveStateTimer=null,this.saveStateDirty&&(this.saveStateDirty=false,this.saveState().catch(t=>{this.deps.eventBus.emit({type:"orchestrator:error",error:t instanceof Error?t.message:String(t),context:"debounced state save",fatal:false});}));},500));}async flushStateLazy(){this.saveStateTimer&&(clearTimeout(this.saveStateTimer),this.saveStateTimer=null),this.saveStateDirty&&(this.saveStateDirty=false,await this.saveState());}};function et(c){if(typeof c!="string")return false;let t=new Date(c);return !isNaN(t.getTime())&&t.toISOString()===c}function z(c,t){let e=typeof c=="string"?c:JSON.stringify(c);return e.length>t?e.slice(0,t)+"\u2026":e}export{st as a,P as b,D as c,G as d,A as e,W as f};//# sourceMappingURL=chunk-E3TCKHU6.js.map
13
+ //# sourceMappingURL=chunk-E3TCKHU6.js.map