@oxgeneral/orch 0.3.4 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/{App-RKAPZNZO.js → App-GJVTVGRU.js} +55 -20
  2. package/dist/{agent-KBTLGGCT.js → agent-7ZJ3ZDJ7.js} +1 -1
  3. package/dist/{chunk-D6RFF3KN.js → chunk-4IFIOMCW.js} +4 -3
  4. package/dist/{chunk-S3QYSBW4.js → chunk-C6XZ3FJT.js} +6 -3
  5. package/dist/chunk-C6XZ3FJT.js.map +1 -0
  6. package/dist/{chunk-VMDQVRBR.js → chunk-GBXUNDKN.js} +16 -7
  7. package/dist/chunk-GBXUNDKN.js.map +1 -0
  8. package/dist/{chunk-W6RSVMXR.js → chunk-MGGSRXWJ.js} +5 -2
  9. package/dist/{chunk-B4JQM4NU.js → chunk-VG4465AG.js} +119 -45
  10. package/dist/chunk-VG4465AG.js.map +1 -0
  11. package/dist/{chunk-A36WAF2S.js → chunk-VXS2CJFH.js} +117 -43
  12. package/dist/{chunk-52BFUGDD.js → chunk-XJTJ2TJV.js} +3 -2
  13. package/dist/{claude-INM52PTH.js → claude-WUJU5KIE.js} +6 -5
  14. package/dist/claude-WUJU5KIE.js.map +1 -0
  15. package/dist/claude-ZUEKJJ4X.js +5 -0
  16. package/dist/cli.js +10 -10
  17. package/dist/{codex-DIXT44JR.js → codex-7IXXXG5U.js} +3 -3
  18. package/dist/{codex-QGH2GRV6.js → codex-NYJWEPRQ.js} +4 -4
  19. package/dist/codex-NYJWEPRQ.js.map +1 -0
  20. package/dist/{container-LJU4QNDH.js → container-LUWGNBSS.js} +12 -10
  21. package/dist/{cursor-KQJTQ73D.js → cursor-3YHVD4NP.js} +4 -4
  22. package/dist/cursor-3YHVD4NP.js.map +1 -0
  23. package/dist/{cursor-C3TR2IJC.js → cursor-622RBRHH.js} +3 -3
  24. package/dist/{doctor-V2FPS236.js → doctor-XSGQSD57.js} +5 -5
  25. package/dist/index.d.ts +4 -1
  26. package/dist/index.js +15 -13
  27. package/dist/index.js.map +1 -1
  28. package/dist/{init-U7MCIOB2.js → init-JU343RXK.js} +3 -3
  29. package/dist/opencode-FAMPSA6X.js +100 -0
  30. package/dist/opencode-FAMPSA6X.js.map +1 -0
  31. package/dist/opencode-WOR53TSC.js +98 -0
  32. package/dist/orchestrator-IYWBVA7J.js +5 -0
  33. package/dist/{orchestrator-ADO66XZ3.js.map → orchestrator-IYWBVA7J.js.map} +1 -1
  34. package/dist/{orchestrator-E3FQ4SOE.js → orchestrator-QNAD7MFH.js} +14 -5
  35. package/dist/shell-DVFHHYAZ.js +5 -0
  36. package/dist/{shell-JXOPKDXH.js → shell-NJNW3O6K.js} +5 -3
  37. package/dist/shell-NJNW3O6K.js.map +1 -0
  38. package/dist/{task-2TJW6Z7O.js → task-3O2OFSP6.js} +1 -1
  39. package/dist/template-engine-5ZKVJMYA.js +3 -0
  40. package/dist/{template-engine-MFL5B677.js.map → template-engine-5ZKVJMYA.js.map} +1 -1
  41. package/dist/template-engine-AWIS56BL.js +3 -0
  42. package/dist/{tui-IM3YUUVD.js → tui-LN5XHSQY.js} +1 -1
  43. package/package.json +2 -1
  44. package/readme.md +3 -3
  45. package/scripts/load-test.ts +478 -0
  46. package/dist/chunk-B4JQM4NU.js.map +0 -1
  47. package/dist/chunk-S3QYSBW4.js.map +0 -1
  48. package/dist/chunk-VMDQVRBR.js.map +0 -1
  49. package/dist/claude-INM52PTH.js.map +0 -1
  50. package/dist/claude-NHUNA5RZ.js +0 -5
  51. package/dist/codex-QGH2GRV6.js.map +0 -1
  52. package/dist/cursor-KQJTQ73D.js.map +0 -1
  53. package/dist/orchestrator-ADO66XZ3.js +0 -5
  54. package/dist/shell-3S4VLYEG.js +0 -4
  55. package/dist/shell-JXOPKDXH.js.map +0 -1
  56. package/dist/template-engine-4IZKRRHG.js +0 -3
  57. package/dist/template-engine-MFL5B677.js +0 -3
@@ -473,11 +473,16 @@ var GoalRow = React5.memo(function GoalRow2({ goal, selected, width, agentNameMa
473
473
  children: goal.title.length > titleWidth ? goal.title.slice(0, titleWidth - 1) + "\u2026" : goal.title
474
474
  }
475
475
  ) }),
476
- hasProgress && /* @__PURE__ */ jsxs(Box, { width: progressW, children: [
477
- /* @__PURE__ */ jsx(Text, { color: tuiColors.green, children: FILLED_BLOCK.repeat(Math.min(doneTasks, 6)) }),
478
- /* @__PURE__ */ jsx(Text, { color: tuiColors.ghost, children: EMPTY_BLOCK.repeat(Math.max(0, Math.min(totalTasks, 6) - doneTasks)) }),
479
- /* @__PURE__ */ jsx(Text, { color: tuiColors.dim, children: ` ${doneTasks}/${totalTasks}` })
480
- ] }),
476
+ hasProgress && (() => {
477
+ const barW = 6;
478
+ const filled = totalTasks > 0 ? Math.round(doneTasks / totalTasks * barW) : 0;
479
+ const empty = barW - filled;
480
+ return /* @__PURE__ */ jsxs(Box, { width: progressW, children: [
481
+ /* @__PURE__ */ jsx(Text, { color: tuiColors.green, children: FILLED_BLOCK.repeat(filled) }),
482
+ /* @__PURE__ */ jsx(Text, { color: tuiColors.ghost, children: EMPTY_BLOCK.repeat(empty) }),
483
+ /* @__PURE__ */ jsx(Text, { color: tuiColors.dim, children: ` ${doneTasks}/${totalTasks}` })
484
+ ] });
485
+ })(),
481
486
  /* @__PURE__ */ jsx(Box, { width: assigneeWidth, children: assigneeName ? /* @__PURE__ */ jsxs(Text, { backgroundColor: chipBg3.green, color: tuiColors.green, wrap: "truncate", children: [
482
487
  " ",
483
488
  assigneeName.length > assigneeWidth - 2 ? assigneeName.slice(0, assigneeWidth - 3) + "\u2026" : assigneeName,
@@ -1265,6 +1270,7 @@ function FormWizard({ title, steps, onComplete, onCancel, width, height, onPaste
1265
1270
  const [multiSelected, setMultiSelected] = useState(/* @__PURE__ */ new Set());
1266
1271
  const [browsingSuggestions, setBrowsingSuggestions] = useState(false);
1267
1272
  const [suggestionIndex, setSuggestionIndex] = useState(0);
1273
+ const [dirty, setDirty] = useState(false);
1268
1274
  const [validationError, setValidationError] = useState(null);
1269
1275
  const [enterBlockHint, setEnterBlockHint] = useState(false);
1270
1276
  const debounceTimerRef = useRef(null);
@@ -1324,6 +1330,7 @@ function FormWizard({ title, steps, onComplete, onCancel, width, height, onPaste
1324
1330
  setMultiSelected(/* @__PURE__ */ new Set());
1325
1331
  setBrowsingSuggestions(false);
1326
1332
  setSuggestionIndex(0);
1333
+ setDirty(false);
1327
1334
  setValidationError(null);
1328
1335
  setEnterBlockHint(false);
1329
1336
  if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);
@@ -1392,10 +1399,13 @@ function FormWizard({ title, steps, onComplete, onCancel, width, height, onPaste
1392
1399
  setCurrentStep(prevActiveIdx >= 0 ? prevActiveIdx : 0);
1393
1400
  setBrowsingSuggestions(false);
1394
1401
  setSuggestionIndex(0);
1402
+ setDirty(false);
1395
1403
  setValidationError(null);
1396
1404
  setEnterBlockHint(false);
1397
1405
  if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);
1398
1406
  const prevStep = steps[prevOrigIdx];
1407
+ const hasPrevValue = !!values[prevStep.id];
1408
+ if (hasPrevValue) setDirty(true);
1399
1409
  if (prevStep.type === "text") {
1400
1410
  const val = values[prevStep.id] ?? prevStep.defaultValue ?? "";
1401
1411
  setTextInput(val);
@@ -1456,8 +1466,12 @@ function FormWizard({ title, steps, onComplete, onCancel, width, height, onPaste
1456
1466
  }
1457
1467
  if (key.return) {
1458
1468
  const val = textInput.trim();
1459
- if (step.required && !val) return;
1469
+ if (step.required && !val) {
1470
+ setDirty(true);
1471
+ return;
1472
+ }
1460
1473
  if (validationError !== null) {
1474
+ setDirty(true);
1461
1475
  setEnterBlockHint(true);
1462
1476
  if (enterBlockTimerRef.current) clearTimeout(enterBlockTimerRef.current);
1463
1477
  enterBlockTimerRef.current = setTimeout(() => setEnterBlockHint(false), 2e3);
@@ -1491,6 +1505,7 @@ function FormWizard({ title, steps, onComplete, onCancel, width, height, onPaste
1491
1505
  return;
1492
1506
  }
1493
1507
  if (input && !key.ctrl && !key.meta && !key.escape) {
1508
+ setDirty(true);
1494
1509
  setBrowsingSuggestions(false);
1495
1510
  setSuggestionIndex(0);
1496
1511
  setTextInput((v) => v.slice(0, cursorPos) + input + v.slice(cursorPos));
@@ -1501,8 +1516,12 @@ function FormWizard({ title, steps, onComplete, onCancel, width, height, onPaste
1501
1516
  if (step.type === "textarea") {
1502
1517
  if (key.return && !key.shift) {
1503
1518
  const val = taLines.join("\n").trim();
1504
- if (step.required && !val) return;
1519
+ if (step.required && !val) {
1520
+ setDirty(true);
1521
+ return;
1522
+ }
1505
1523
  if (validationError !== null) {
1524
+ setDirty(true);
1506
1525
  setEnterBlockHint(true);
1507
1526
  if (enterBlockTimerRef.current) clearTimeout(enterBlockTimerRef.current);
1508
1527
  enterBlockTimerRef.current = setTimeout(() => setEnterBlockHint(false), 2e3);
@@ -1584,6 +1603,7 @@ function FormWizard({ title, steps, onComplete, onCancel, width, height, onPaste
1584
1603
  return;
1585
1604
  }
1586
1605
  if (input && !key.ctrl && !key.meta && !key.escape) {
1606
+ setDirty(true);
1587
1607
  const parts = input.split(/\r?\n/);
1588
1608
  if (parts.length === 1) {
1589
1609
  setTaLines((lines) => {
@@ -1637,6 +1657,7 @@ function FormWizard({ title, steps, onComplete, onCancel, width, height, onPaste
1637
1657
  if (step.validate) {
1638
1658
  const err = step.validate(selected.value);
1639
1659
  if (err !== null) {
1660
+ setDirty(true);
1640
1661
  setValidationError(err);
1641
1662
  setEnterBlockHint(true);
1642
1663
  if (enterBlockTimerRef.current) clearTimeout(enterBlockTimerRef.current);
@@ -1681,6 +1702,7 @@ function FormWizard({ title, steps, onComplete, onCancel, width, height, onPaste
1681
1702
  }
1682
1703
  });
1683
1704
  if (!step) return null;
1705
+ const visibleError = dirty ? validationError : null;
1684
1706
  const maxW = Math.max(20, width - 6);
1685
1707
  const progressText = `${currentStep + 1}/${totalSteps}`;
1686
1708
  const optionsH = Math.max(2, height - 4);
@@ -1719,7 +1741,7 @@ function FormWizard({ title, steps, onComplete, onCancel, width, height, onPaste
1719
1741
  !step.required && /* @__PURE__ */ jsx(Text, { color: tuiColors.dim, children: " (optional, Enter to skip)" })
1720
1742
  ] }),
1721
1743
  step.type === "text" && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
1722
- /* @__PURE__ */ jsxs(Box, { borderStyle: validationError ? "round" : void 0, borderColor: validationError ? tuiColors.red : void 0, children: [
1744
+ /* @__PURE__ */ jsxs(Box, { borderStyle: visibleError ? "round" : void 0, borderColor: visibleError ? tuiColors.red : void 0, children: [
1723
1745
  /* @__PURE__ */ jsxs(Text, { color: tuiColors.amber, children: [
1724
1746
  " ",
1725
1747
  ">",
@@ -1734,9 +1756,9 @@ function FormWizard({ title, steps, onComplete, onCancel, width, height, onPaste
1734
1756
  /* @__PURE__ */ jsx(Text, { color: tuiColors.amber, children: CURSOR })
1735
1757
  ] }) : /* @__PURE__ */ jsx(Text, { color: tuiColors.amber, children: CURSOR })
1736
1758
  ] }),
1737
- validationError && /* @__PURE__ */ jsxs(Text, { color: tuiColors.red, dimColor: true, children: [
1759
+ visibleError && /* @__PURE__ */ jsxs(Text, { color: tuiColors.red, dimColor: true, children: [
1738
1760
  " ",
1739
- validationError
1761
+ visibleError
1740
1762
  ] }),
1741
1763
  enterBlockHint && /* @__PURE__ */ jsx(Text, { color: tuiColors.red, children: " Fix the error above" })
1742
1764
  ] }),
@@ -1781,7 +1803,7 @@ function FormWizard({ title, steps, onComplete, onCancel, width, height, onPaste
1781
1803
  const visibleLines = taLines.slice(taScrollStart, taScrollStart + taVisibleH);
1782
1804
  const lineNumWidth = String(taLines.length).length;
1783
1805
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
1784
- /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: validationError ? "round" : void 0, borderColor: validationError ? tuiColors.red : void 0, children: [
1806
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: visibleError ? "round" : void 0, borderColor: visibleError ? tuiColors.red : void 0, children: [
1785
1807
  visibleLines.map((line, i) => {
1786
1808
  const realRow = i + taScrollStart;
1787
1809
  const lineNum = String(realRow + 1).padStart(lineNumWidth, " ");
@@ -1810,9 +1832,9 @@ function FormWizard({ title, steps, onComplete, onCancel, width, height, onPaste
1810
1832
  step.placeholder
1811
1833
  ] }) })
1812
1834
  ] }),
1813
- validationError && /* @__PURE__ */ jsxs(Text, { color: tuiColors.red, dimColor: true, children: [
1835
+ visibleError && /* @__PURE__ */ jsxs(Text, { color: tuiColors.red, dimColor: true, children: [
1814
1836
  " ",
1815
- validationError
1837
+ visibleError
1816
1838
  ] }),
1817
1839
  enterBlockHint && /* @__PURE__ */ jsx(Text, { color: tuiColors.red, children: " Fix the error above" })
1818
1840
  ] });
@@ -1833,9 +1855,9 @@ function FormWizard({ title, steps, onComplete, onCancel, width, height, onPaste
1833
1855
  ] })
1834
1856
  ] }, opt.value);
1835
1857
  }),
1836
- validationError && /* @__PURE__ */ jsxs(Text, { color: tuiColors.red, dimColor: true, children: [
1858
+ visibleError && /* @__PURE__ */ jsxs(Text, { color: tuiColors.red, dimColor: true, children: [
1837
1859
  " ",
1838
- validationError
1860
+ visibleError
1839
1861
  ] }),
1840
1862
  enterBlockHint && /* @__PURE__ */ jsx(Text, { color: tuiColors.red, children: " Fix the error above" })
1841
1863
  ] }),
@@ -2687,11 +2709,22 @@ var CURSOR_MODELS = [
2687
2709
  { value: "gpt-5.3-codex", label: "GPT-5.3 Codex", hint: "OpenAI" },
2688
2710
  { value: "claude-sonnet-4-6", label: "Claude Sonnet 4.6", hint: "Anthropic" }
2689
2711
  ];
2712
+ var OPENCODE_MODELS = [
2713
+ { value: "", label: "Default", hint: "use model configured in opencode" },
2714
+ { value: "openrouter/anthropic/claude-sonnet-4.6", label: "Claude Sonnet 4.6", hint: "fast, balanced" },
2715
+ { value: "openrouter/anthropic/claude-opus-4.6", label: "Claude Opus 4.6", hint: "most capable" },
2716
+ { value: "openrouter/google/gemini-2.5-pro", label: "Gemini 2.5 Pro", hint: "Google" },
2717
+ { value: "openrouter/google/gemini-2.5-flash", label: "Gemini 2.5 Flash", hint: "Google, fast" },
2718
+ { value: "openrouter/deepseek/deepseek-v3.2", label: "DeepSeek V3.2", hint: "open-source" },
2719
+ { value: "openrouter/deepseek/deepseek-r1:free", label: "DeepSeek R1", hint: "reasoning, free" },
2720
+ { value: "opencode/big-pickle", label: "Big Pickle", hint: "opencode native" }
2721
+ ];
2690
2722
  var SHELL_MODELS = [
2691
2723
  { value: "", label: "Default", hint: "use shell adapter default" }
2692
2724
  ];
2693
2725
  var ADAPTERS = [
2694
2726
  { value: "claude", label: "Claude", hint: "Claude Code CLI" },
2727
+ { value: "opencode", label: "OpenCode", hint: "OpenCode \u2014 multi-provider" },
2695
2728
  { value: "codex", label: "Codex", hint: "OpenAI Codex CLI" },
2696
2729
  { value: "cursor", label: "Cursor", hint: "Cursor Agent CLI" },
2697
2730
  { value: "shell", label: "Shell", hint: "custom shell command" }
@@ -2702,11 +2735,12 @@ var PRIORITY_OPTIONS = [
2702
2735
  { value: "3", label: "P3 Medium", hint: "default priority" },
2703
2736
  { value: "4", label: "P4 Low", hint: "nice to have" }
2704
2737
  ];
2705
- var AGENT_HINT_MAX_LEN = 80;
2738
+ var AGENT_ROLE_MAX_LEN = 60;
2706
2739
  function mapAgentOptions(agents) {
2707
2740
  return agents.filter((a) => a.status !== "disabled").map((a) => {
2708
- const raw = (a.role ?? a.adapter).split("\n")[0].trim();
2709
- const hint = raw.length > AGENT_HINT_MAX_LEN ? raw.slice(0, AGENT_HINT_MAX_LEN - 1) + "\u2026" : raw;
2741
+ const roleLine = (a.role ?? "").split("\n")[0].trim();
2742
+ const role = roleLine.length > AGENT_ROLE_MAX_LEN ? roleLine.slice(0, AGENT_ROLE_MAX_LEN - 1) + "\u2026" : roleLine;
2743
+ const hint = role ? `[${a.adapter}] ${role}` : a.adapter;
2710
2744
  return { value: a.id, label: a.name, hint };
2711
2745
  });
2712
2746
  }
@@ -2800,6 +2834,7 @@ function getAgentWizardSteps(agents, teams) {
2800
2834
  label: "Model",
2801
2835
  type: "select",
2802
2836
  getOptions: (vals) => {
2837
+ if (vals.adapter === "opencode") return OPENCODE_MODELS;
2803
2838
  if (vals.adapter === "codex") return CODEX_MODELS;
2804
2839
  if (vals.adapter === "cursor") return CURSOR_MODELS;
2805
2840
  if (vals.adapter === "shell") return SHELL_MODELS;
@@ -2997,7 +3032,7 @@ function editTaskWizardToFields(vals) {
2997
3032
  function getEditAgentWizardSteps(agent, agents, teams) {
2998
3033
  const currentRoleInPresets = ROLE_PRESETS.find((r) => r.value === agent.role);
2999
3034
  const roleDefault = currentRoleInPresets ? agent.role : agent.role ? "__custom__" : "";
3000
- const modelOptions = agent.adapter === "codex" ? CODEX_MODELS : agent.adapter === "cursor" ? CURSOR_MODELS : agent.adapter === "shell" ? SHELL_MODELS : CLAUDE_MODELS;
3035
+ const modelOptions = agent.adapter === "opencode" ? OPENCODE_MODELS : agent.adapter === "codex" ? CODEX_MODELS : agent.adapter === "cursor" ? CURSOR_MODELS : agent.adapter === "shell" ? SHELL_MODELS : CLAUDE_MODELS;
3001
3036
  const teamOptions = buildTeamOptions(teams);
3002
3037
  const currentTeamId = teams?.find((t) => t.members.some((m) => m.agent_id === agent.id))?.id;
3003
3038
  return [
@@ -6521,7 +6556,7 @@ function formatAgentOutput(raw) {
6521
6556
  const summary = summarizeToolResult(content);
6522
6557
  return { summary: `\u2190 ${summary.slice(0, 180)}`, detail: detail() };
6523
6558
  }
6524
- if (parsed.type === "tool_use") {
6559
+ if (parsed.type === "tool_use" || typeof parsed.name === "string" && "input" in parsed) {
6525
6560
  const name = parsed.name ?? "tool";
6526
6561
  const hint = formatToolInput(name, parsed.input);
6527
6562
  return { summary: `\u2699 ${name}(${hint})`, detail: detail() };
@@ -5,7 +5,7 @@ import { printSuccess, agentName, printTable, dim, statusIcon, formatTokens, pri
5
5
  // src/cli/commands/agent.ts
6
6
  function registerAgentCommand(program, container) {
7
7
  const agent = program.command("agent").description("Manage agents");
8
- agent.command("add <name>").description("Add a new agent").requiredOption("--adapter <adapter>", "Adapter type: claude, shell, codex, cursor").option("--role <role>", "Agent role description").option("--command <cmd>", "Shell command (for shell adapter)").option("--model <model>", "Model name (for AI adapters)").option("--max-turns <n>", "Max turns per run").option("--timeout <ms>", "Timeout in ms").option("--approval-policy <policy>", "suggest|auto|manual").option("--workspace-mode <mode>", "shared|worktree|isolated").option("--skills <skills>", "Comma-separated list of agent skills").option("-e, --edit", "Open $EDITOR to write the role description").action(async (name, opts) => {
8
+ agent.command("add <name>").description("Add a new agent").requiredOption("--adapter <adapter>", "Adapter type: claude, opencode, codex, cursor, shell").option("--role <role>", "Agent role description").option("--command <cmd>", "Shell command (for shell adapter)").option("--model <model>", "Model name (for AI adapters)").option("--max-turns <n>", "Max turns per run").option("--timeout <ms>", "Timeout in ms").option("--approval-policy <policy>", "suggest|auto|manual").option("--workspace-mode <mode>", "shared|worktree|isolated").option("--skills <skills>", "Comma-separated list of agent skills").option("-e, --edit", "Open $EDITOR to write the role description").action(async (name, opts) => {
9
9
  await container.paths.requireInit();
10
10
  let role = opts.role;
11
11
  if (opts.edit) {
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { createStreamingEvents, extractTokens } from './chunk-W6RSVMXR.js';
2
+ import { createStreamingEvents, extractTokens } from './chunk-MGGSRXWJ.js';
3
3
  import { classifyAdapterError } from './chunk-2C2TFQ7K.js';
4
4
  import { execFile } from 'child_process';
5
5
  import { promisify } from 'util';
@@ -37,8 +37,9 @@ var ClaudeAdapter = class {
37
37
  if (params.config.model) {
38
38
  args.push("--model", params.config.model);
39
39
  }
40
- if (params.config.system_prompt) {
41
- args.push("--system-prompt", params.config.system_prompt);
40
+ const effectiveSystemPrompt = params.systemPrompt ?? params.config.system_prompt;
41
+ if (effectiveSystemPrompt) {
42
+ args.push("--system-prompt", effectiveSystemPrompt);
42
43
  }
43
44
  args.push(params.prompt);
44
45
  const { process: proc, pid } = this.processManager.spawn("claude", args, {
@@ -3,6 +3,9 @@ import { classifyAdapterError } from './chunk-NLQAJ7TW.js';
3
3
  import { readLines } from './chunk-O2MSGW3V.js';
4
4
 
5
5
  // src/infrastructure/adapters/utils.ts
6
+ function buildFullPrompt(systemPrompt, userPrompt) {
7
+ return systemPrompt ? systemPrompt + "\n\n" + userPrompt : userPrompt;
8
+ }
6
9
  function extractTokens(parsed, opts) {
7
10
  let usage = parsed.usage;
8
11
  if (!usage && opts?.statsFallback) {
@@ -58,6 +61,6 @@ function createStreamingEvents(proc, parseEvent, adapterName, signal) {
58
61
  return generate();
59
62
  }
60
63
 
61
- export { createStreamingEvents, extractTokens };
62
- //# sourceMappingURL=chunk-S3QYSBW4.js.map
63
- //# sourceMappingURL=chunk-S3QYSBW4.js.map
64
+ export { buildFullPrompt, createStreamingEvents, extractTokens };
65
+ //# sourceMappingURL=chunk-C6XZ3FJT.js.map
66
+ //# sourceMappingURL=chunk-C6XZ3FJT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/infrastructure/adapters/utils.ts"],"names":[],"mappings":"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","file":"chunk-C6XZ3FJT.js","sourcesContent":["/**\n * Shared utilities for agent adapters.\n *\n * Deduplicates extractTokens and streaming event generation logic\n * common to claude, codex, and cursor adapters.\n */\n\nimport type { ChildProcess } from 'node:child_process';\nimport type { AgentEvent } from './interface.js';\nimport { readLines } from '../process/process-manager.js';\nimport { createTokenUsage } from '../../domain/run.js';\nimport { classifyAdapterError } from '../../domain/errors.js';\n\nexport type TokenInfo = { input: number; output: number; total: number };\n\n/** Combine system and user prompts. Adapters without native system prompt support use this. */\nexport function buildFullPrompt(systemPrompt: string | undefined, userPrompt: string): string {\n return systemPrompt ? systemPrompt + '\\n\\n' + userPrompt : userPrompt;\n}\n\n/**\n * Extract token usage from a parsed JSON event.\n *\n * @param parsed - The parsed JSON object from an adapter event line.\n * @param opts.statsFallback - If true, also checks `parsed.stats?.usage` (Claude-specific).\n */\nexport function extractTokens(\n parsed: Record<string, unknown>,\n opts?: { statsFallback?: boolean },\n): TokenInfo | undefined {\n let usage = parsed.usage as Record<string, unknown> | undefined;\n\n if (!usage && opts?.statsFallback) {\n const stats = parsed.stats as Record<string, unknown> | undefined;\n usage = stats?.usage as Record<string, unknown> | undefined;\n }\n\n if (usage && typeof usage.input_tokens === 'number') {\n const input = usage.input_tokens;\n const output = typeof usage.output_tokens === 'number' ? usage.output_tokens : 0;\n return createTokenUsage(input, output);\n }\n return undefined;\n}\n\n/**\n * Create an async generator that streams AgentEvents from a child process.\n *\n * Handles: exit promise setup, line-by-line reading, abort signal, exit code checking.\n *\n * @param proc - The spawned child process.\n * @param parseEvent - Adapter-specific function to parse a line into an AgentEvent.\n * @param adapterName - Name used in error messages (e.g. \"Claude\", \"Codex\").\n * @param signal - Optional abort signal.\n */\nexport function createStreamingEvents(\n proc: ChildProcess,\n parseEvent: (line: string) => AgentEvent | null,\n adapterName: string,\n signal?: AbortSignal,\n): AsyncGenerator<AgentEvent> {\n async function* generate(): AsyncGenerator<AgentEvent> {\n let gotDoneEvent = false;\n\n let exitCode: number | null = null;\n let exitError: Error | null = null;\n const exitPromise = new Promise<void>((resolve) => {\n proc.on('close', (code) => { exitCode = code; resolve(); });\n proc.on('error', (err) => { exitError = err; resolve(); });\n });\n\n if (proc.stdout) {\n for await (const line of readLines(proc.stdout)) {\n if (signal?.aborted) break;\n const event = parseEvent(line);\n if (event) {\n if (event.type === 'done') gotDoneEvent = true;\n yield event;\n }\n }\n }\n\n await exitPromise;\n\n if (exitError && !signal?.aborted && !gotDoneEvent) {\n const spawnErr = exitError as Error;\n const classified = classifyAdapterError(spawnErr.message, exitCode ?? undefined);\n const err = Object.assign(new Error(spawnErr.message), { errorKind: classified });\n throw err;\n }\n if (exitCode !== 0 && exitCode !== null && !signal?.aborted && !gotDoneEvent) {\n const msg = `${adapterName} process exited with code ${exitCode}`;\n const classified = classifyAdapterError(msg, exitCode);\n const err = Object.assign(new Error(msg), { errorKind: classified });\n throw err;\n }\n }\n\n return generate();\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { AUTONOMOUS_LABEL, DEFAULT_PROMPT_TEMPLATE, buildPromptContext } from './chunk-B4JQM4NU.js';
1
+ import { AUTONOMOUS_LABEL, DEFAULT_SYSTEM_TEMPLATE, DEFAULT_USER_TEMPLATE, buildPromptContext } from './chunk-VG4465AG.js';
2
2
  import { LockConflictError, WorkspaceError, TaskAlreadyRunningError, NoAgentsError, classifyAdapterError } from './chunk-NLQAJ7TW.js';
3
3
  import { dirname } from 'path';
4
4
  import fs from 'fs/promises';
@@ -941,7 +941,9 @@ Agent role: ${role}` : `Autonomous work cycle. Agent role: ${role}`;
941
941
  agent,
942
942
  this.deps.config
943
943
  );
944
- const template = this.deps.config.prompt?.template ?? DEFAULT_PROMPT_TEMPLATE;
944
+ const systemTemplate = this.deps.config.prompt?.system_template ?? DEFAULT_SYSTEM_TEMPLATE;
945
+ const userTemplate = this.deps.config.prompt?.user_template ?? DEFAULT_USER_TEMPLATE;
946
+ const legacyTemplate = this.deps.config.prompt?.template;
945
947
  const attempt = task.attempts + 1;
946
948
  let retryContext;
947
949
  if (attempt > 1) {
@@ -964,14 +966,13 @@ Agent role: ${role}` : `Autonomous work cycle. Agent role: ${role}`;
964
966
  const allTasks = await this.cachedTaskStore.list();
965
967
  const goalTasks = allTasks.filter((t) => t.goalId === goalId);
966
968
  const progressEntry = await this.deps.contextStore?.get(`${goalId}-progress`);
967
- const MAX_GOAL_TASK_NAMES = 30;
968
969
  const taskNames = goalTasks.map((t) => `[${t.status}] ${t.title}`);
969
970
  goalContext = {
970
971
  id: goalRaw.id,
971
972
  title: goalRaw.title,
972
973
  description: goalRaw.description,
973
974
  status: goalRaw.status,
974
- task_names: taskNames.length > MAX_GOAL_TASK_NAMES ? [...taskNames.slice(0, MAX_GOAL_TASK_NAMES), `... and ${taskNames.length - MAX_GOAL_TASK_NAMES} more`] : taskNames,
975
+ task_names: taskNames,
975
976
  progress: progressEntry?.value
976
977
  };
977
978
  }
@@ -983,7 +984,14 @@ Agent role: ${role}` : `Autonomous work cycle. Agent role: ${role}`;
983
984
  this.deps.config,
984
985
  { allAgents, retryContext, sharedContext, feedback: task.feedback, messages: pendingMessages.length ? pendingMessages : void 0, goal: goalContext }
985
986
  );
986
- const prompt = await this.deps.templateEngine.render(template, context);
987
+ let prompt;
988
+ let systemPrompt;
989
+ if (legacyTemplate) {
990
+ prompt = await this.deps.templateEngine.render(legacyTemplate, context);
991
+ } else {
992
+ systemPrompt = await this.deps.templateEngine.render(systemTemplate, context);
993
+ prompt = await this.deps.templateEngine.render(userTemplate, context);
994
+ }
987
995
  const run = await this.deps.runService.create({
988
996
  taskId: task.id,
989
997
  agentId: agent.id,
@@ -1014,6 +1022,7 @@ Agent role: ${role}` : `Autonomous work cycle. Agent role: ${role}`;
1014
1022
  this.abortControllers.set(taskId, abortController);
1015
1023
  const handle = adapter.execute({
1016
1024
  prompt,
1025
+ systemPrompt,
1017
1026
  workspace: workspacePath,
1018
1027
  env: {
1019
1028
  ...agent.config.env,
@@ -1467,5 +1476,5 @@ function serializeEventData(data, maxLen) {
1467
1476
  }
1468
1477
 
1469
1478
  export { Orchestrator, canTransition, isBlocked, isDispatchable, isTerminal, resolveFailureStatus };
1470
- //# sourceMappingURL=chunk-VMDQVRBR.js.map
1471
- //# sourceMappingURL=chunk-VMDQVRBR.js.map
1479
+ //# sourceMappingURL=chunk-GBXUNDKN.js.map
1480
+ //# sourceMappingURL=chunk-GBXUNDKN.js.map