@bojackduy/opencode-loopd 1.2.0 → 1.4.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 (3) hide show
  1. package/dist/server.js +47 -7
  2. package/dist/tui.js +454 -291
  3. package/package.json +1 -1
package/dist/server.js CHANGED
@@ -1118,6 +1118,7 @@ function createLoopEngine(options) {
1118
1118
  import { randomUUID as randomUUID4 } from "crypto";
1119
1119
  init_state_repository();
1120
1120
  import * as path2 from "path";
1121
+ import { promises as fs2 } from "fs";
1121
1122
 
1122
1123
  // src/server/worker-session.ts
1123
1124
  function createWorkerManager(host) {
@@ -1125,7 +1126,8 @@ function createWorkerManager(host) {
1125
1126
  async createWorker(goal) {
1126
1127
  const workerSessionID = await host.createWorker({
1127
1128
  parentID: goal.ownerSessionID,
1128
- title: `loopd: ${goal.name}`
1129
+ title: `loopd: ${goal.name}`,
1130
+ agent: goal.config.agent
1129
1131
  });
1130
1132
  return {
1131
1133
  goalID: goal.id,
@@ -1197,10 +1199,25 @@ function buildContinuationSteering(goal, runtime, context) {
1197
1199
  }
1198
1200
  }
1199
1201
  parts.push(...outputLocationBlock());
1202
+ if (context?.verification) {
1203
+ const v = context.verification;
1204
+ parts.push(``, `## VERIFICATION (deterministic pre-screen)`);
1205
+ if (v.checksPassed !== undefined) {
1206
+ if (v.checksPassed)
1207
+ parts.push(`- checks: all passed`);
1208
+ else if (v.failedChecks?.length)
1209
+ parts.push(`- checks FAILED: ${v.failedChecks.join(", ")} \u2014 fix before claiming completion`);
1210
+ else
1211
+ parts.push(`- checks: not yet run`);
1212
+ }
1213
+ if (v.artifactSummary)
1214
+ parts.push(`- artifacts: ${v.artifactSummary}`);
1215
+ }
1216
+ parts.push(``, `## COMPLETION AUDIT \u2014 you ARE the evaluator`, `Before deciding the goal is achieved, treat completion as unproven:`, `1. Derive concrete requirements from the objective and any referenced files/plans/specs/issues. Preserve original scope; do not redefine success.`, `2. For _every_ explicit requirement, numbered item, named artifact, command, test, gate, invariant, deliverable \u2192 identify authoritative evidence: files, command output, test results, PR state, rendered artifacts, runtime behavior.`, `3. Judge each per-requirement: proves | contradicts | incomplete | too weak/indirect | missing \u2014 matching scope narrowly (narrow check \u2260 broad claim).`, `4. Treat tests/manifests/verifiers as evidence only after confirming they cover the relevant requirement. Treat uncertain/indirect as NOT achieved.`, `5. Only call complete_goal when _every_ requirement's current-state evidence proves it and no required work remains. If any requirement is missing/incomplete/weak \u2192 keep working, do not call complete_goal.`);
1200
1217
  if (context?.forceFinish) {
1201
- parts.push(``, `## FINAL REPORT REQUIRED \u2014 STOPPING SOON`, `The system requires you to wrap up now. Do NOT start new work.`, `Call complete_goal NOW with:`, `- summary: a specific semantic summary of what was accomplished (files changed, results, key findings)`, `- evidence: concrete proof (commands run, files created, checks passed)`, `If you cannot complete, call block_goal with the reason.`);
1218
+ parts.push(``, `## FINAL REPORT REQUIRED \u2014 STOPPING SOON`, `The system requires you to wrap up now. Do NOT start new work.`, `Call complete_goal NOW with:`, `- summary: a specific semantic summary of what was accomplished (files changed, results, key findings)`, `- evidence: concrete proof (commands run, files created, checks passed)`, `If you cannot complete truthfully, call block_goal with the reason \u2014 do not fabricate evidence.`);
1202
1219
  } else {
1203
- parts.push(``, `## INSTRUCTIONS`, `1. Inspect current workspace state \u2014 read files, check what exists. Do NOT redo completed work.`, `2. Continue concrete progress toward the objective.`, `3. After completing a batch, call report_goal_progress with what you did and what's next.`, `4. Verify completion requirement-by-requirement before calling complete_goal.`, `5. Call block_goal only if the same blocker persists across 3+ consecutive turns.`, `6. Use the built-in question tool only for genuinely risky ambiguity.`);
1220
+ parts.push(``, `## INSTRUCTIONS`, `1. Inspect current workspace state \u2014 read files, check what exists. Do NOT redo completed work.`, `2. Continue concrete progress toward the objective.`, `3. After completing a batch, call report_goal_progress with what you did and what's next.`, `4. Use the built-in question tool only for genuinely risky ambiguity.`);
1204
1221
  }
1205
1222
  }
1206
1223
  if (context?.inboxMessages && context.inboxMessages.length > 0) {
@@ -1365,11 +1382,28 @@ function createGoalService(host) {
1365
1382
  } catch {
1366
1383
  transcriptTail = [];
1367
1384
  }
1385
+ let verification;
1386
+ try {
1387
+ const artifactDir = goal.config.artifactDir;
1388
+ if (artifactDir) {
1389
+ try {
1390
+ const files = await fs2.readdir(artifactDir);
1391
+ verification = { artifactSummary: files.length ? `${files.length} file(s): ${files.slice(0, 8).join(", ")}` : "no artifacts yet" };
1392
+ } catch {
1393
+ verification = { artifactSummary: "no artifacts yet" };
1394
+ }
1395
+ }
1396
+ if (goal.config.checks?.length) {
1397
+ const c = `checks configured: ${goal.config.checks.length} \u2014 run them before claiming completion`;
1398
+ verification = { ...verification || {}, failedChecks: [c], checksPassed: undefined };
1399
+ }
1400
+ } catch {}
1368
1401
  const context = {
1369
1402
  inboxMessages: inboxMessages.length > 0 ? inboxMessages : undefined,
1370
1403
  progressHistory: progressHistory.length > 0 ? progressHistory : undefined,
1371
1404
  transcriptTail: transcriptTail && transcriptTail.length > 0 ? transcriptTail : undefined,
1372
- forceFinish: opts?.forceFinish || undefined
1405
+ forceFinish: opts?.forceFinish || undefined,
1406
+ verification
1373
1407
  };
1374
1408
  await workers.continueWorker(session, goal, runtime, context);
1375
1409
  }
@@ -1551,9 +1585,12 @@ function createGoalService(host) {
1551
1585
  // src/server/host-adapter.ts
1552
1586
  function createRealHost(client, directory) {
1553
1587
  return {
1554
- async createWorker({ parentID, title }) {
1588
+ async createWorker({ parentID, title, agent }) {
1555
1589
  try {
1556
- const result = await withTimeout(client.session.create({ body: { parentID, title } }), 1e4, "OpenCode session.create");
1590
+ const body = { parentID, title };
1591
+ if (agent)
1592
+ body.agent = agent;
1593
+ const result = await withTimeout(client.session.create({ body }), 1e4, "OpenCode session.create");
1557
1594
  const data = result?.data;
1558
1595
  if (result?.error || !data?.id) {
1559
1596
  const detail = describeError(result?.error || "response contained no session ID");
@@ -1688,7 +1725,8 @@ function goalTools(dir, goalService, hostSessionID) {
1688
1725
  maxNoProgress: tool.schema.number().optional().describe("Block after N turns without progress."),
1689
1726
  maxFailures: tool.schema.number().optional().describe("Block after N consecutive failures."),
1690
1727
  compactEvery: tool.schema.number().optional().describe("Compact the worker session every N turns."),
1691
- timeoutMs: tool.schema.number().optional().describe("Per-turn timeout in ms.")
1728
+ timeoutMs: tool.schema.number().optional().describe("Per-turn timeout in ms."),
1729
+ agent: tool.schema.string().optional().describe('Agent to run the worker as (e.g. "dumb-agent", "build"). Defaults to primary agent.')
1692
1730
  },
1693
1731
  execute: async (args, context) => {
1694
1732
  const sessionID = context?.sessionID || hostSessionID;
@@ -1718,6 +1756,8 @@ function goalTools(dir, goalService, hostSessionID) {
1718
1756
  config.compactEvery = args.compactEvery;
1719
1757
  if (args.timeoutMs !== undefined)
1720
1758
  config.timeoutMs = args.timeoutMs;
1759
+ if (args.agent !== undefined)
1760
+ config.agent = args.agent;
1721
1761
  try {
1722
1762
  const { goal, worker } = await goalService.start(dir, {
1723
1763
  name: args.name,
package/dist/tui.js CHANGED
@@ -8,6 +8,8 @@ import { createComponent as _$createComponent2 } from "@opentui/solid";
8
8
  import { use as _$use } from "@opentui/solid";
9
9
  import { effect as _$effect } from "@opentui/solid";
10
10
  import { createComponent as _$createComponent } from "@opentui/solid";
11
+ import { spread as _$spread } from "@opentui/solid";
12
+ import { mergeProps as _$mergeProps } from "@opentui/solid";
11
13
  import { memo as _$memo } from "@opentui/solid";
12
14
  import { insert as _$insert } from "@opentui/solid";
13
15
  import { createTextNode as _$createTextNode } from "@opentui/solid";
@@ -246,8 +248,8 @@ function tokenize(input) {
246
248
  }
247
249
  function commandHelp() {
248
250
  return [
249
- "Modes: : insert \u2192 send/commands, Ctrl+N \u2192 normal, ? toggle help, Shift+B bug report",
250
- "Nav: j/k move \u2502 g/G top/bottom \u2502 o open child \u2502 p/r/R/x pause/resume/retry/clear \u2502 L logs \u2502 q close",
251
+ "Modes: : insert \u2192 send/commands | Ctrl+N \u2192 normal | ? toggle help | Shift+B bug report",
252
+ "Nav: j/k move | g/G top/bottom | o open child | p/r/R/x pause/resume/retry/clear | L logs | q close",
251
253
  "Commands (insert mode, : prefix):",
252
254
  " :send <message> Send instruction to selected goal",
253
255
  " :open Open child session (same as o)",
@@ -625,14 +627,7 @@ function LoopDashboard(props) {
625
627
  }
626
628
  if (key === "B") {
627
629
  prevent(evt);
628
- const goal = selectedGoal();
629
- const extra = goal ? `Goal: ${goal.name} (${goal.id.slice(0, 8)}) status=${goal.status} objective=${goal.objective.slice(0, 120)}` : "No goal selected";
630
- const url = bugReportUrl({
631
- runtimeLabel: `opencode-loopd dashboard`,
632
- extra
633
- });
634
- const res = openBrowserUrl(url);
635
- setStatusText(res.status === "opened" ? "Opening bug report in browser\u2026" : `Could not open browser: ${res.reason} \u2014 ${url}`);
630
+ handleBugReport();
636
631
  return;
637
632
  }
638
633
  if (key === "q") {
@@ -810,14 +805,7 @@ function LoopDashboard(props) {
810
805
  }
811
806
  case "bug":
812
807
  case "report": {
813
- const goal = selectedGoal();
814
- const extra = goal ? `Goal: ${goal.name} (${goal.id.slice(0, 8)}) status=${goal.status} objective=${goal.objective.slice(0, 120)}` : "No goal selected";
815
- const url = bugReportUrl({
816
- runtimeLabel: `opencode-loopd dashboard`,
817
- extra
818
- });
819
- const res = openBrowserUrl(url);
820
- setStatusText(res.status === "opened" ? "Opening bug report in browser\u2026" : `Could not open browser: ${res.reason} \u2014 ${url}`);
808
+ handleBugReport();
821
809
  break;
822
810
  }
823
811
  case "logs":
@@ -858,25 +846,39 @@ function LoopDashboard(props) {
858
846
  const activeGoals = () => state()?.goals.filter((g) => g.status !== "complete") || [];
859
847
  const runningCount = () => state()?.runtimes.filter((runtime) => runtime.phase === "running").length || 0;
860
848
  const runningFrame = () => ["|", "/", "-", "\\"][Math.floor(clock() / 500) % 4];
849
+ function handleBugReport() {
850
+ const goal = selectedGoal();
851
+ const extra = goal ? `Goal: ${goal.name} (${goal.id.slice(0, 8)}) status=${goal.status} objective=${goal.objective.slice(0, 120)}` : "No goal selected";
852
+ const url = bugReportUrl({
853
+ runtimeLabel: `opencode-loopd dashboard`,
854
+ extra
855
+ });
856
+ const res = openBrowserUrl(url);
857
+ setStatusText(res.status === "opened" ? "Opening bug report in browser\u2026" : `Could not open browser: ${res.reason} \u2014 ${url}`);
858
+ }
861
859
  createEffect(() => setSelectedGoal(activeGoals()[selected()] || null));
862
860
  return (() => {
863
- var _el$ = _$createElement("box"), _el$2 = _$createElement("box"), _el$3 = _$createElement("box"), _el$4 = _$createElement("text"), _el$5 = _$createElement("span"), _el$7 = _$createElement("span"), _el$9 = _$createElement("span"), _el$0 = _$createTextNode(` `), _el$1 = _$createTextNode(` `), _el$10 = _$createElement("span"), _el$12 = _$createElement("span"), _el$13 = _$createElement("span"), _el$15 = _$createElement("span"), _el$17 = _$createElement("span"), _el$18 = _$createTextNode(` `), _el$19 = _$createTextNode(` RUNNING`), _el$20 = _$createElement("span"), _el$22 = _$createElement("span"), _el$23 = _$createElement("span"), _el$25 = _$createElement("box"), _el$30 = _$createElement("box"), _el$37 = _$createElement("box"), _el$38 = _$createElement("text"), _el$39 = _$createElement("span"), _el$40 = _$createElement("input");
861
+ var _el$ = _$createElement("box"), _el$2 = _$createElement("box"), _el$3 = _$createElement("box"), _el$4 = _$createElement("text"), _el$5 = _$createElement("span"), _el$7 = _$createElement("span"), _el$9 = _$createElement("span"), _el$0 = _$createTextNode(` `), _el$1 = _$createTextNode(` `), _el$10 = _$createElement("span"), _el$12 = _$createElement("span"), _el$13 = _$createElement("span"), _el$15 = _$createElement("span"), _el$17 = _$createElement("span"), _el$18 = _$createTextNode(` `), _el$19 = _$createTextNode(` RUNNING`), _el$20 = _$createElement("span"), _el$22 = _$createElement("span"), _el$23 = _$createElement("span"), _el$25 = _$createElement("box"), _el$26 = _$createElement("text"), _el$27 = _$createElement("span"), _el$29 = _$createElement("box"), _el$34 = _$createElement("box"), _el$41 = _$createElement("box"), _el$42 = _$createElement("text"), _el$43 = _$createElement("span"), _el$44 = _$createElement("input");
864
862
  _$insertNode(_el$, _el$2);
865
863
  _$setProp(_el$, "flexDirection", "column");
866
864
  _$setProp(_el$, "width", "100%");
867
865
  _$setProp(_el$, "alignItems", "center");
868
866
  _$setProp(_el$, "padding", 1);
869
867
  _$insertNode(_el$2, _el$3);
870
- _$insertNode(_el$2, _el$25);
871
- _$insertNode(_el$2, _el$37);
868
+ _$insertNode(_el$2, _el$29);
869
+ _$insertNode(_el$2, _el$41);
872
870
  _$setProp(_el$2, "flexDirection", "column");
873
871
  _$setProp(_el$2, "width", "90%");
874
872
  _$setProp(_el$2, "border", true);
875
873
  _$setProp(_el$2, "padding", 1);
876
874
  _$insertNode(_el$3, _el$4);
875
+ _$insertNode(_el$3, _el$25);
877
876
  _$setProp(_el$3, "flexDirection", "row");
877
+ _$setProp(_el$3, "justifyContent", "space-between");
878
+ _$setProp(_el$3, "alignItems", "center");
878
879
  _$setProp(_el$3, "padding", 0);
879
880
  _$setProp(_el$3, "flexShrink", 0);
881
+ _$setProp(_el$3, "gap", 1);
880
882
  _$insertNode(_el$4, _el$5);
881
883
  _$insertNode(_el$4, _el$7);
882
884
  _$insertNode(_el$4, _el$9);
@@ -907,91 +909,233 @@ function LoopDashboard(props) {
907
909
  _$insertNode(_el$20, _$createTextNode(` \u2502 `));
908
910
  _$insert(_el$22, () => state()?.goals.filter((g) => g.status === "complete").length || 0);
909
911
  _$insertNode(_el$23, _$createTextNode(` done`));
910
- _$insertNode(_el$25, _el$30);
911
- _$setProp(_el$25, "flexDirection", "column");
912
- _$setProp(_el$25, "flexGrow", 1);
913
- _$setProp(_el$25, "minHeight", 0);
914
- _$setProp(_el$25, "overflow", "hidden");
915
- _$insert(_el$25, _$createComponent(Show, {
912
+ _$insertNode(_el$25, _el$26);
913
+ _$setProp(_el$25, "flexDirection", "row");
914
+ _$setProp(_el$25, "alignItems", "center");
915
+ _$setProp(_el$25, "paddingLeft", 1);
916
+ _$setProp(_el$25, "paddingRight", 1);
917
+ _$setProp(_el$25, "flexShrink", 0);
918
+ _$spread(_el$25, _$mergeProps({
919
+ get backgroundColor() {
920
+ return theme().error;
921
+ }
922
+ }, {
923
+ onMouseDown: handleBugReport
924
+ }), true);
925
+ _$insertNode(_el$26, _el$27);
926
+ _$insertNode(_el$27, _$createTextNode(`Bug Report`));
927
+ _$setProp(_el$27, "style", {
928
+ fg: "white",
929
+ bold: true
930
+ });
931
+ _$insertNode(_el$29, _el$34);
932
+ _$setProp(_el$29, "flexDirection", "column");
933
+ _$setProp(_el$29, "flexGrow", 1);
934
+ _$setProp(_el$29, "minHeight", 0);
935
+ _$setProp(_el$29, "overflow", "hidden");
936
+ _$insert(_el$29, _$createComponent(Show, {
916
937
  get when() {
917
938
  return showHelp();
918
939
  },
919
940
  get children() {
920
- var _el$26 = _$createElement("box"), _el$27 = _$createElement("text"), _el$28 = _$createElement("span");
921
- _$insertNode(_el$26, _el$27);
922
- _$setProp(_el$26, "flexDirection", "column");
923
- _$setProp(_el$26, "padding", 1);
924
- _$setProp(_el$26, "border", true);
925
- _$setProp(_el$26, "borderColor", "yellow");
926
- _$setProp(_el$26, "flexShrink", 0);
927
- _$setProp(_el$26, "maxHeight", 14);
928
- _$setProp(_el$26, "overflow", "hidden");
929
- _$insertNode(_el$27, _el$28);
930
- _$insertNode(_el$28, _$createTextNode(`\u2501\u2501\u2501 Keys: ? toggle : insert Ctrl+N normal o open B bug q close \u2501\u2501\u2501`));
931
- _$setProp(_el$28, "style", {
941
+ var _el$30 = _$createElement("box"), _el$31 = _$createElement("text"), _el$32 = _$createElement("span");
942
+ _$insertNode(_el$30, _el$31);
943
+ _$setProp(_el$30, "flexDirection", "column");
944
+ _$setProp(_el$30, "padding", 1);
945
+ _$setProp(_el$30, "border", true);
946
+ _$setProp(_el$30, "borderColor", "yellow");
947
+ _$setProp(_el$30, "flexShrink", 0);
948
+ _$setProp(_el$30, "maxHeight", 14);
949
+ _$setProp(_el$30, "overflow", "hidden");
950
+ _$insertNode(_el$31, _el$32);
951
+ _$insertNode(_el$32, _$createTextNode(`\u2501\u2501\u2501 Keys: ? toggle : insert Ctrl+N normal o open B bug q close \u2501\u2501\u2501`));
952
+ _$setProp(_el$32, "style", {
932
953
  fg: "yellow",
933
954
  bold: true
934
955
  });
935
- _$insert(_el$27, _$createComponent(For, {
956
+ _$insert(_el$31, _$createComponent(For, {
936
957
  get each() {
937
958
  return commandHelp().split(`
938
959
  `);
939
960
  },
940
961
  children: (line) => {
941
- const isHeader = line.startsWith("Modes:") || line.startsWith("Nav:") || line.startsWith("Commands");
942
- const isCmd = line.trim().startsWith(":");
962
+ if (line.startsWith("Modes:") || line.startsWith("Nav:")) {
963
+ const label = line.startsWith("Modes:") ? "Modes:" : "Nav:";
964
+ const rest = line.slice(label.length).trim();
965
+ const segments = rest.split(" | ");
966
+ return [`
967
+ `, (() => {
968
+ var _el$45 = _$createElement("span");
969
+ _$insert(_el$45, label);
970
+ _$effect((_$p) => _$setProp(_el$45, "style", {
971
+ fg: theme().primary,
972
+ bold: true
973
+ }, _$p));
974
+ return _el$45;
975
+ })(), (() => {
976
+ var _el$46 = _$createElement("span");
977
+ _$insertNode(_el$46, _$createTextNode(` `));
978
+ _$effect((_$p) => _$setProp(_el$46, "style", {
979
+ fg: theme().textMuted
980
+ }, _$p));
981
+ return _el$46;
982
+ })(), _$createComponent(For, {
983
+ each: segments,
984
+ children: (seg, idx) => {
985
+ const hasArrow = seg.includes("\u2192");
986
+ if (hasArrow) {
987
+ const [k2, d2] = seg.split("\u2192").map((s) => s.trim());
988
+ return [_$memo(() => _$memo(() => idx() > 0)() && (() => {
989
+ var _el$52 = _$createElement("span");
990
+ _$insertNode(_el$52, _$createTextNode(` | `));
991
+ _$effect((_$p) => _$setProp(_el$52, "style", {
992
+ fg: theme().textMuted
993
+ }, _$p));
994
+ return _el$52;
995
+ })()), (() => {
996
+ var _el$48 = _$createElement("span");
997
+ _$insert(_el$48, k2);
998
+ _$effect((_$p) => _$setProp(_el$48, "style", {
999
+ fg: theme().warning,
1000
+ bold: true
1001
+ }, _$p));
1002
+ return _el$48;
1003
+ })(), (() => {
1004
+ var _el$49 = _$createElement("span");
1005
+ _$insertNode(_el$49, _$createTextNode(` \u2192 `));
1006
+ _$effect((_$p) => _$setProp(_el$49, "style", {
1007
+ fg: theme().textMuted
1008
+ }, _$p));
1009
+ return _el$49;
1010
+ })(), (() => {
1011
+ var _el$51 = _$createElement("span");
1012
+ _$insert(_el$51, d2);
1013
+ _$effect((_$p) => _$setProp(_el$51, "style", {
1014
+ fg: theme().text
1015
+ }, _$p));
1016
+ return _el$51;
1017
+ })()];
1018
+ }
1019
+ const sp = seg.indexOf(" ");
1020
+ const k = sp > 0 ? seg.slice(0, sp) : seg;
1021
+ const d = sp > 0 ? seg.slice(sp + 1) : "";
1022
+ return [_$memo(() => _$memo(() => idx() > 0)() && (() => {
1023
+ var _el$55 = _$createElement("span");
1024
+ _$insertNode(_el$55, _$createTextNode(` | `));
1025
+ _$effect((_$p) => _$setProp(_el$55, "style", {
1026
+ fg: theme().textMuted
1027
+ }, _$p));
1028
+ return _el$55;
1029
+ })()), (() => {
1030
+ var _el$54 = _$createElement("span");
1031
+ _$insert(_el$54, k);
1032
+ _$effect((_$p) => _$setProp(_el$54, "style", {
1033
+ fg: theme().warning,
1034
+ bold: true
1035
+ }, _$p));
1036
+ return _el$54;
1037
+ })(), d && (() => {
1038
+ var _el$57 = _$createElement("span"), _el$58 = _$createTextNode(` `);
1039
+ _$insertNode(_el$57, _el$58);
1040
+ _$insert(_el$57, d, null);
1041
+ _$effect((_$p) => _$setProp(_el$57, "style", {
1042
+ fg: theme().text
1043
+ }, _$p));
1044
+ return _el$57;
1045
+ })()];
1046
+ }
1047
+ })];
1048
+ }
1049
+ if (line.trim().startsWith(":")) {
1050
+ const m = line.match(/^(\s*)(:\S+(?:\s+\S+)*?)\s{2,}(.*)$/);
1051
+ const indent = m?.[1] ?? line.match(/^\s*/)?.[0] ?? "";
1052
+ const key = m?.[2] ?? line.trim().split(/\s{2,}/)[0] ?? line.trim();
1053
+ const desc = m?.[3] ?? line.split(/\s{2,}/)[1] ?? "";
1054
+ return [`
1055
+ `, (() => {
1056
+ var _el$59 = _$createElement("span");
1057
+ _$insert(_el$59, indent);
1058
+ _$effect((_$p) => _$setProp(_el$59, "style", {
1059
+ fg: theme().textMuted
1060
+ }, _$p));
1061
+ return _el$59;
1062
+ })(), (() => {
1063
+ var _el$60 = _$createElement("span");
1064
+ _$insert(_el$60, key);
1065
+ _$effect((_$p) => _$setProp(_el$60, "style", {
1066
+ fg: theme().warning,
1067
+ bold: true
1068
+ }, _$p));
1069
+ return _el$60;
1070
+ })(), desc && [(() => {
1071
+ var _el$61 = _$createElement("span");
1072
+ _$insertNode(_el$61, _$createTextNode(` `));
1073
+ _$effect((_$p) => _$setProp(_el$61, "style", {
1074
+ fg: theme().textMuted
1075
+ }, _$p));
1076
+ return _el$61;
1077
+ })(), (() => {
1078
+ var _el$63 = _$createElement("span");
1079
+ _$insert(_el$63, desc);
1080
+ _$effect((_$p) => _$setProp(_el$63, "style", {
1081
+ fg: theme().textMuted
1082
+ }, _$p));
1083
+ return _el$63;
1084
+ })()]];
1085
+ }
1086
+ const isHeader = line.startsWith("Commands");
943
1087
  return [`
944
1088
  `, (() => {
945
- var _el$41 = _$createElement("span");
946
- _$insert(_el$41, line);
947
- _$effect((_$p) => _$setProp(_el$41, "style", {
948
- fg: isHeader ? theme().primary : isCmd ? theme().warning : theme().text,
1089
+ var _el$64 = _$createElement("span");
1090
+ _$insert(_el$64, line);
1091
+ _$effect((_$p) => _$setProp(_el$64, "style", {
1092
+ fg: isHeader ? theme().primary : theme().textMuted,
949
1093
  bold: isHeader
950
1094
  }, _$p));
951
- return _el$41;
1095
+ return _el$64;
952
1096
  })()];
953
1097
  }
954
1098
  }), null);
955
- _$effect((_$p) => _$setProp(_el$26, "backgroundColor", theme().background, _$p));
956
- return _el$26;
1099
+ _$effect((_$p) => _$setProp(_el$30, "backgroundColor", theme().background, _$p));
1100
+ return _el$30;
957
1101
  }
958
- }), _el$30);
959
- _$setProp(_el$30, "flexDirection", "column");
960
- _$setProp(_el$30, "flexGrow", 1);
961
- _$setProp(_el$30, "padding", 1);
962
- _$setProp(_el$30, "minHeight", 0);
963
- _$setProp(_el$30, "overflow", "hidden");
964
- _$insert(_el$30, _$createComponent(Show, {
1102
+ }), _el$34);
1103
+ _$setProp(_el$34, "flexDirection", "column");
1104
+ _$setProp(_el$34, "flexGrow", 1);
1105
+ _$setProp(_el$34, "padding", 1);
1106
+ _$setProp(_el$34, "minHeight", 0);
1107
+ _$setProp(_el$34, "overflow", "hidden");
1108
+ _$insert(_el$34, _$createComponent(Show, {
965
1109
  get when() {
966
1110
  return activeGoals().length > 0;
967
1111
  },
968
1112
  get fallback() {
969
1113
  return (() => {
970
- var _el$42 = _$createElement("box"), _el$43 = _$createElement("text"), _el$44 = _$createElement("span"), _el$46 = _$createElement("span"), _el$48 = _$createElement("span"), _el$50 = _$createElement("text"), _el$51 = _$createElement("span"), _el$53 = _$createElement("span"), _el$55 = _$createElement("span"), _el$57 = _$createElement("span"), _el$59 = _$createElement("span"), _el$61 = _$createElement("span"), _el$63 = _$createElement("span");
971
- _$insertNode(_el$42, _el$43);
972
- _$insertNode(_el$42, _el$50);
973
- _$setProp(_el$42, "flexDirection", "column");
974
- _$setProp(_el$42, "gap", 1);
975
- _$insertNode(_el$43, _el$44);
976
- _$insertNode(_el$43, _el$46);
977
- _$insertNode(_el$43, _el$48);
978
- _$insertNode(_el$44, _$createTextNode(`No active goals.`));
979
- _$insertNode(_el$46, _$createTextNode(` /goal`));
980
- _$insertNode(_el$48, _$createTextNode(` in parent chat to create one.`));
981
- _$insertNode(_el$50, _el$51);
982
- _$insertNode(_el$50, _el$53);
983
- _$insertNode(_el$50, _el$55);
984
- _$insertNode(_el$50, _el$57);
985
- _$insertNode(_el$50, _el$59);
986
- _$insertNode(_el$50, _el$61);
987
- _$insertNode(_el$50, _el$63);
988
- _$insertNode(_el$51, _$createTextNode(`Tip: `));
989
- _$insertNode(_el$53, _$createTextNode(`:send`));
990
- _$insertNode(_el$55, _$createTextNode(` to steer the worker \xB7 `));
991
- _$insertNode(_el$57, _$createTextNode(`o`));
992
- _$insertNode(_el$59, _$createTextNode(` to open child \xB7 `));
993
- _$insertNode(_el$61, _$createTextNode(`:force`));
994
- _$insertNode(_el$63, _$createTextNode(` to complete manually.`));
1114
+ var _el$65 = _$createElement("box"), _el$66 = _$createElement("text"), _el$67 = _$createElement("span"), _el$69 = _$createElement("span"), _el$71 = _$createElement("span"), _el$73 = _$createElement("text"), _el$74 = _$createElement("span"), _el$76 = _$createElement("span"), _el$78 = _$createElement("span"), _el$80 = _$createElement("span"), _el$82 = _$createElement("span"), _el$84 = _$createElement("span"), _el$86 = _$createElement("span");
1115
+ _$insertNode(_el$65, _el$66);
1116
+ _$insertNode(_el$65, _el$73);
1117
+ _$setProp(_el$65, "flexDirection", "column");
1118
+ _$setProp(_el$65, "gap", 1);
1119
+ _$insertNode(_el$66, _el$67);
1120
+ _$insertNode(_el$66, _el$69);
1121
+ _$insertNode(_el$66, _el$71);
1122
+ _$insertNode(_el$67, _$createTextNode(`No active goals.`));
1123
+ _$insertNode(_el$69, _$createTextNode(` /goal`));
1124
+ _$insertNode(_el$71, _$createTextNode(` in parent chat to create one.`));
1125
+ _$insertNode(_el$73, _el$74);
1126
+ _$insertNode(_el$73, _el$76);
1127
+ _$insertNode(_el$73, _el$78);
1128
+ _$insertNode(_el$73, _el$80);
1129
+ _$insertNode(_el$73, _el$82);
1130
+ _$insertNode(_el$73, _el$84);
1131
+ _$insertNode(_el$73, _el$86);
1132
+ _$insertNode(_el$74, _$createTextNode(`Tip: `));
1133
+ _$insertNode(_el$76, _$createTextNode(`:send`));
1134
+ _$insertNode(_el$78, _$createTextNode(` to steer the worker \xB7 `));
1135
+ _$insertNode(_el$80, _$createTextNode(`o`));
1136
+ _$insertNode(_el$82, _$createTextNode(` to open child \xB7 `));
1137
+ _$insertNode(_el$84, _$createTextNode(`:force`));
1138
+ _$insertNode(_el$86, _$createTextNode(` to complete manually.`));
995
1139
  _$effect((_p$) => {
996
1140
  var _v$21 = {
997
1141
  fg: theme().textMuted
@@ -1014,16 +1158,16 @@ function LoopDashboard(props) {
1014
1158
  }, _v$30 = {
1015
1159
  fg: theme().textMuted
1016
1160
  };
1017
- _v$21 !== _p$.e && (_p$.e = _$setProp(_el$44, "style", _v$21, _p$.e));
1018
- _v$22 !== _p$.t && (_p$.t = _$setProp(_el$46, "style", _v$22, _p$.t));
1019
- _v$23 !== _p$.a && (_p$.a = _$setProp(_el$48, "style", _v$23, _p$.a));
1020
- _v$24 !== _p$.o && (_p$.o = _$setProp(_el$51, "style", _v$24, _p$.o));
1021
- _v$25 !== _p$.i && (_p$.i = _$setProp(_el$53, "style", _v$25, _p$.i));
1022
- _v$26 !== _p$.n && (_p$.n = _$setProp(_el$55, "style", _v$26, _p$.n));
1023
- _v$27 !== _p$.s && (_p$.s = _$setProp(_el$57, "style", _v$27, _p$.s));
1024
- _v$28 !== _p$.h && (_p$.h = _$setProp(_el$59, "style", _v$28, _p$.h));
1025
- _v$29 !== _p$.r && (_p$.r = _$setProp(_el$61, "style", _v$29, _p$.r));
1026
- _v$30 !== _p$.d && (_p$.d = _$setProp(_el$63, "style", _v$30, _p$.d));
1161
+ _v$21 !== _p$.e && (_p$.e = _$setProp(_el$67, "style", _v$21, _p$.e));
1162
+ _v$22 !== _p$.t && (_p$.t = _$setProp(_el$69, "style", _v$22, _p$.t));
1163
+ _v$23 !== _p$.a && (_p$.a = _$setProp(_el$71, "style", _v$23, _p$.a));
1164
+ _v$24 !== _p$.o && (_p$.o = _$setProp(_el$74, "style", _v$24, _p$.o));
1165
+ _v$25 !== _p$.i && (_p$.i = _$setProp(_el$76, "style", _v$25, _p$.i));
1166
+ _v$26 !== _p$.n && (_p$.n = _$setProp(_el$78, "style", _v$26, _p$.n));
1167
+ _v$27 !== _p$.s && (_p$.s = _$setProp(_el$80, "style", _v$27, _p$.s));
1168
+ _v$28 !== _p$.h && (_p$.h = _$setProp(_el$82, "style", _v$28, _p$.h));
1169
+ _v$29 !== _p$.r && (_p$.r = _$setProp(_el$84, "style", _v$29, _p$.r));
1170
+ _v$30 !== _p$.d && (_p$.d = _$setProp(_el$86, "style", _v$30, _p$.d));
1027
1171
  return _p$;
1028
1172
  }, {
1029
1173
  e: undefined,
@@ -1037,7 +1181,7 @@ function LoopDashboard(props) {
1037
1181
  r: undefined,
1038
1182
  d: undefined
1039
1183
  });
1040
- return _el$42;
1184
+ return _el$65;
1041
1185
  })();
1042
1186
  },
1043
1187
  get children() {
@@ -1060,86 +1204,86 @@ function LoopDashboard(props) {
1060
1204
  return phaseColor(runtime().phase || "idle", theme());
1061
1205
  };
1062
1206
  return (() => {
1063
- var _el$65 = _$createElement("box"), _el$66 = _$createElement("text"), _el$67 = _$createElement("span"), _el$68 = _$createElement("span"), _el$70 = _$createElement("span");
1064
- _$insertNode(_el$65, _el$66);
1065
- _$setProp(_el$65, "flexDirection", "row");
1066
- _$setProp(_el$65, "paddingLeft", 1);
1067
- _$setProp(_el$65, "paddingRight", 1);
1068
- _$insertNode(_el$66, _el$67);
1069
- _$insertNode(_el$66, _el$68);
1070
- _$insertNode(_el$66, _el$70);
1071
- _$insert(_el$67, (() => {
1207
+ var _el$88 = _$createElement("box"), _el$89 = _$createElement("text"), _el$90 = _$createElement("span"), _el$91 = _$createElement("span"), _el$93 = _$createElement("span");
1208
+ _$insertNode(_el$88, _el$89);
1209
+ _$setProp(_el$88, "flexDirection", "row");
1210
+ _$setProp(_el$88, "paddingLeft", 1);
1211
+ _$setProp(_el$88, "paddingRight", 1);
1212
+ _$insertNode(_el$89, _el$90);
1213
+ _$insertNode(_el$89, _el$91);
1214
+ _$insertNode(_el$89, _el$93);
1215
+ _$insert(_el$90, (() => {
1072
1216
  var _c$2 = _$memo(() => !!isActive());
1073
1217
  return () => _c$2() ? `\u25B6 ${statusIcon(goal.status)} ${goal.name}` : ` ${statusIcon(goal.status)} ${goal.name}`;
1074
1218
  })());
1075
- _$insertNode(_el$68, _$createTextNode(` \u2502 `));
1076
- _$insert(_el$70, () => goal.status.toUpperCase());
1077
- _$insert(_el$66, (() => {
1219
+ _$insertNode(_el$91, _$createTextNode(` \u2502 `));
1220
+ _$insert(_el$93, () => goal.status.toUpperCase());
1221
+ _$insert(_el$89, (() => {
1078
1222
  var _c$3 = _$memo(() => !!runtime());
1079
1223
  return () => _c$3() && [(() => {
1080
- var _el$71 = _$createElement("span");
1081
- _$insertNode(_el$71, _$createTextNode(` \u2502 `));
1082
- _$effect((_$p) => _$setProp(_el$71, "style", {
1224
+ var _el$94 = _$createElement("span");
1225
+ _$insertNode(_el$94, _$createTextNode(` \u2502 `));
1226
+ _$effect((_$p) => _$setProp(_el$94, "style", {
1083
1227
  fg: theme().textMuted
1084
1228
  }, _$p));
1085
- return _el$71;
1229
+ return _el$94;
1086
1230
  })(), (() => {
1087
- var _el$73 = _$createElement("span"), _el$74 = _$createTextNode(` `);
1088
- _$insertNode(_el$73, _el$74);
1089
- _$insert(_el$73, (() => {
1231
+ var _el$96 = _$createElement("span"), _el$97 = _$createTextNode(` `);
1232
+ _$insertNode(_el$96, _el$97);
1233
+ _$insert(_el$96, (() => {
1090
1234
  var _c$6 = _$memo(() => runtime().phase === "running");
1091
1235
  return () => _c$6() ? runningFrame() : phaseIcon(runtime().phase);
1092
- })(), _el$74);
1093
- _$insert(_el$73, () => runtime().phase.toUpperCase(), null);
1094
- _$effect((_$p) => _$setProp(_el$73, "style", {
1236
+ })(), _el$97);
1237
+ _$insert(_el$96, () => runtime().phase.toUpperCase(), null);
1238
+ _$effect((_$p) => _$setProp(_el$96, "style", {
1095
1239
  fg: turnColor(),
1096
1240
  bold: runtime().phase === "running"
1097
1241
  }, _$p));
1098
- return _el$73;
1242
+ return _el$96;
1099
1243
  })(), (() => {
1100
- var _el$75 = _$createElement("span"), _el$76 = _$createTextNode(` `);
1101
- _$insertNode(_el$75, _el$76);
1102
- _$insert(_el$75, () => runtime().turnCount, null);
1103
- _$insert(_el$75, maxTurns ? `/${maxTurns}` : "", null);
1104
- _$effect((_$p) => _$setProp(_el$75, "style", {
1244
+ var _el$98 = _$createElement("span"), _el$99 = _$createTextNode(` `);
1245
+ _$insertNode(_el$98, _el$99);
1246
+ _$insert(_el$98, () => runtime().turnCount, null);
1247
+ _$insert(_el$98, maxTurns ? `/${maxTurns}` : "", null);
1248
+ _$effect((_$p) => _$setProp(_el$98, "style", {
1105
1249
  fg: turnColor()
1106
1250
  }, _$p));
1107
- return _el$75;
1251
+ return _el$98;
1108
1252
  })(), (() => {
1109
- var _el$77 = _$createElement("span"), _el$78 = _$createTextNode(` `);
1110
- _$insertNode(_el$77, _el$78);
1111
- _$insert(_el$77, () => ageLabel(runtime().lastProgressAt || runtime().lastRunAt, clock()), null);
1112
- _$effect((_$p) => _$setProp(_el$77, "style", {
1253
+ var _el$100 = _$createElement("span"), _el$101 = _$createTextNode(` `);
1254
+ _$insertNode(_el$100, _el$101);
1255
+ _$insert(_el$100, () => ageLabel(runtime().lastProgressAt || runtime().lastRunAt, clock()), null);
1256
+ _$effect((_$p) => _$setProp(_el$100, "style", {
1113
1257
  fg: theme().textMuted
1114
1258
  }, _$p));
1115
- return _el$77;
1259
+ return _el$100;
1116
1260
  })()];
1117
1261
  })(), null);
1118
- _$insert(_el$66, (() => {
1262
+ _$insert(_el$89, (() => {
1119
1263
  var _c$4 = _$memo(() => !!(runtime() && runtime().consecutiveFailures > 0));
1120
1264
  return () => _c$4() && (() => {
1121
- var _el$79 = _$createElement("span"), _el$80 = _$createTextNode(` \u2502 \u26A0 `), _el$81 = _$createTextNode(` fail`);
1122
- _$insertNode(_el$79, _el$80);
1123
- _$insertNode(_el$79, _el$81);
1124
- _$insert(_el$79, () => runtime().consecutiveFailures, _el$81);
1125
- _$effect((_$p) => _$setProp(_el$79, "style", {
1265
+ var _el$102 = _$createElement("span"), _el$103 = _$createTextNode(` \u2502 \u26A0 `), _el$104 = _$createTextNode(` fail`);
1266
+ _$insertNode(_el$102, _el$103);
1267
+ _$insertNode(_el$102, _el$104);
1268
+ _$insert(_el$102, () => runtime().consecutiveFailures, _el$104);
1269
+ _$effect((_$p) => _$setProp(_el$102, "style", {
1126
1270
  fg: theme().error,
1127
1271
  bold: true
1128
1272
  }, _$p));
1129
- return _el$79;
1273
+ return _el$102;
1130
1274
  })();
1131
1275
  })(), null);
1132
- _$insert(_el$66, (() => {
1276
+ _$insert(_el$89, (() => {
1133
1277
  var _c$5 = _$memo(() => !!(runtime() && (runtime().noProgressCount || 0) > 0));
1134
1278
  return () => _c$5() && (() => {
1135
- var _el$82 = _$createElement("span"), _el$83 = _$createTextNode(` \u2502 `), _el$84 = _$createTextNode(` no-progress`);
1136
- _$insertNode(_el$82, _el$83);
1137
- _$insertNode(_el$82, _el$84);
1138
- _$insert(_el$82, () => runtime().noProgressCount, _el$84);
1139
- _$effect((_$p) => _$setProp(_el$82, "style", {
1279
+ var _el$105 = _$createElement("span"), _el$106 = _$createTextNode(` \u2502 `), _el$107 = _$createTextNode(` no-progress`);
1280
+ _$insertNode(_el$105, _el$106);
1281
+ _$insertNode(_el$105, _el$107);
1282
+ _$insert(_el$105, () => runtime().noProgressCount, _el$107);
1283
+ _$effect((_$p) => _$setProp(_el$105, "style", {
1140
1284
  fg: theme().warning
1141
1285
  }, _$p));
1142
- return _el$82;
1286
+ return _el$105;
1143
1287
  })();
1144
1288
  })(), null);
1145
1289
  _$effect((_p$) => {
@@ -1152,10 +1296,10 @@ function LoopDashboard(props) {
1152
1296
  fg: statusColor(goal.status, theme()),
1153
1297
  bold: true
1154
1298
  };
1155
- _v$31 !== _p$.e && (_p$.e = _$setProp(_el$65, "backgroundColor", _v$31, _p$.e));
1156
- _v$32 !== _p$.t && (_p$.t = _$setProp(_el$67, "style", _v$32, _p$.t));
1157
- _v$33 !== _p$.a && (_p$.a = _$setProp(_el$68, "style", _v$33, _p$.a));
1158
- _v$34 !== _p$.o && (_p$.o = _$setProp(_el$70, "style", _v$34, _p$.o));
1299
+ _v$31 !== _p$.e && (_p$.e = _$setProp(_el$88, "backgroundColor", _v$31, _p$.e));
1300
+ _v$32 !== _p$.t && (_p$.t = _$setProp(_el$90, "style", _v$32, _p$.t));
1301
+ _v$33 !== _p$.a && (_p$.a = _$setProp(_el$91, "style", _v$33, _p$.a));
1302
+ _v$34 !== _p$.o && (_p$.o = _$setProp(_el$93, "style", _v$34, _p$.o));
1159
1303
  return _p$;
1160
1304
  }, {
1161
1305
  e: undefined,
@@ -1163,157 +1307,176 @@ function LoopDashboard(props) {
1163
1307
  a: undefined,
1164
1308
  o: undefined
1165
1309
  });
1166
- return _el$65;
1310
+ return _el$88;
1167
1311
  })();
1168
1312
  }
1169
1313
  });
1170
1314
  }
1171
1315
  }));
1172
- _$insert(_el$25, _$createComponent(Show, {
1316
+ _$insert(_el$29, _$createComponent(Show, {
1173
1317
  get when() {
1174
1318
  return selectedGoal();
1175
1319
  },
1176
1320
  children: (goal) => {
1177
1321
  const rt = () => state()?.runtimes.find((r) => r.goalID === goal().id);
1178
1322
  return (() => {
1179
- var _el$85 = _$createElement("box"), _el$86 = _$createElement("text"), _el$87 = _$createElement("span"), _el$88 = _$createTextNode(` `), _el$89 = _$createElement("span"), _el$90 = _$createTextNode(` `), _el$91 = _$createTextNode(`
1180
- `), _el$92 = _$createElement("span");
1181
- _$insertNode(_el$85, _el$86);
1182
- _$setProp(_el$85, "flexDirection", "column");
1183
- _$setProp(_el$85, "border", true);
1184
- _$setProp(_el$85, "padding", 1);
1185
- _$setProp(_el$85, "flexShrink", 0);
1186
- _$setProp(_el$85, "maxHeight", 10);
1187
- _$insertNode(_el$86, _el$87);
1188
- _$insertNode(_el$86, _el$89);
1189
- _$insertNode(_el$86, _el$91);
1190
- _$insertNode(_el$86, _el$92);
1191
- _$insertNode(_el$87, _el$88);
1192
- _$insert(_el$87, () => statusIcon(goal().status), _el$88);
1193
- _$insert(_el$87, () => goal().name, null);
1194
- _$insertNode(_el$89, _el$90);
1195
- _$insert(_el$89, () => goal().status.toUpperCase(), null);
1196
- _$insert(_el$86, (() => {
1323
+ var _el$108 = _$createElement("box"), _el$109 = _$createElement("text"), _el$110 = _$createElement("span"), _el$111 = _$createTextNode(` `), _el$112 = _$createElement("span"), _el$113 = _$createTextNode(` `), _el$114 = _$createTextNode(`
1324
+ `), _el$115 = _$createElement("span");
1325
+ _$insertNode(_el$108, _el$109);
1326
+ _$setProp(_el$108, "flexDirection", "column");
1327
+ _$setProp(_el$108, "border", true);
1328
+ _$setProp(_el$108, "padding", 1);
1329
+ _$setProp(_el$108, "flexShrink", 0);
1330
+ _$setProp(_el$108, "maxHeight", 10);
1331
+ _$insertNode(_el$109, _el$110);
1332
+ _$insertNode(_el$109, _el$112);
1333
+ _$insertNode(_el$109, _el$114);
1334
+ _$insertNode(_el$109, _el$115);
1335
+ _$insertNode(_el$110, _el$111);
1336
+ _$insert(_el$110, () => statusIcon(goal().status), _el$111);
1337
+ _$insert(_el$110, () => goal().name, null);
1338
+ _$insertNode(_el$112, _el$113);
1339
+ _$insert(_el$112, () => goal().status.toUpperCase(), null);
1340
+ _$insert(_el$109, (() => {
1197
1341
  var _c$7 = _$memo(() => !!rt());
1198
1342
  return () => _c$7() && [(() => {
1199
- var _el$93 = _$createElement("span");
1200
- _$insertNode(_el$93, _$createTextNode(` \u2502 `));
1201
- _$effect((_$p) => _$setProp(_el$93, "style", {
1343
+ var _el$116 = _$createElement("span");
1344
+ _$insertNode(_el$116, _$createTextNode(` \u2502 `));
1345
+ _$effect((_$p) => _$setProp(_el$116, "style", {
1202
1346
  fg: theme().textMuted
1203
1347
  }, _$p));
1204
- return _el$93;
1348
+ return _el$116;
1205
1349
  })(), (() => {
1206
- var _el$95 = _$createElement("span"), _el$96 = _$createTextNode(` `);
1207
- _$insertNode(_el$95, _el$96);
1208
- _$insert(_el$95, () => phaseIcon(rt().phase), _el$96);
1209
- _$insert(_el$95, () => rt().phase, null);
1210
- _$effect((_$p) => _$setProp(_el$95, "style", {
1350
+ var _el$118 = _$createElement("span"), _el$119 = _$createTextNode(` `);
1351
+ _$insertNode(_el$118, _el$119);
1352
+ _$insert(_el$118, () => phaseIcon(rt().phase), _el$119);
1353
+ _$insert(_el$118, () => rt().phase, null);
1354
+ _$effect((_$p) => _$setProp(_el$118, "style", {
1211
1355
  fg: phaseColor(rt().phase, theme()),
1212
1356
  bold: true
1213
1357
  }, _$p));
1214
- return _el$95;
1358
+ return _el$118;
1215
1359
  })(), (() => {
1216
- var _el$97 = _$createElement("span"), _el$98 = _$createTextNode(` turn `);
1217
- _$insertNode(_el$97, _el$98);
1218
- _$insert(_el$97, () => rt().turnCount, null);
1219
- _$effect((_$p) => _$setProp(_el$97, "style", {
1360
+ var _el$120 = _$createElement("span"), _el$121 = _$createTextNode(` turn `);
1361
+ _$insertNode(_el$120, _el$121);
1362
+ _$insert(_el$120, () => rt().turnCount, null);
1363
+ _$effect((_$p) => _$setProp(_el$120, "style", {
1220
1364
  fg: theme().textMuted
1221
1365
  }, _$p));
1222
- return _el$97;
1366
+ return _el$120;
1223
1367
  })()];
1224
- })(), _el$91);
1225
- _$insert(_el$92, () => goal().objective.slice(0, 160));
1226
- _$insert(_el$86, (() => {
1368
+ })(), _el$114);
1369
+ _$insert(_el$115, () => goal().objective.slice(0, 160));
1370
+ _$insert(_el$109, (() => {
1227
1371
  var _c$8 = _$memo(() => !!goal().lastProgress);
1228
1372
  return () => _c$8() && [(() => {
1229
- var _el$99 = _$createElement("span"), _el$100 = _$createTextNode(`
1373
+ var _el$122 = _$createElement("span"), _el$123 = _$createTextNode(`
1230
1374
  \u2714 `);
1231
- _$insertNode(_el$99, _el$100);
1232
- _$effect((_$p) => _$setProp(_el$99, "style", {
1375
+ _$insertNode(_el$122, _el$123);
1376
+ _$effect((_$p) => _$setProp(_el$122, "style", {
1233
1377
  fg: theme().success
1234
1378
  }, _$p));
1235
- return _el$99;
1379
+ return _el$122;
1236
1380
  })(), (() => {
1237
- var _el$102 = _$createElement("span");
1238
- _$insert(_el$102, () => goal().lastProgress.summary.slice(0, 100));
1239
- _$effect((_$p) => _$setProp(_el$102, "style", {
1381
+ var _el$125 = _$createElement("span");
1382
+ _$insert(_el$125, () => goal().lastProgress.summary.slice(0, 100));
1383
+ _$effect((_$p) => _$setProp(_el$125, "style", {
1240
1384
  fg: theme().text
1241
1385
  }, _$p));
1242
- return _el$102;
1386
+ return _el$125;
1243
1387
  })(), (() => {
1244
- var _el$103 = _$createElement("span"), _el$104 = _$createTextNode(` \u2192 `);
1245
- _$insertNode(_el$103, _el$104);
1246
- _$insert(_el$103, () => goal().lastProgress.next?.slice(0, 60) || "", null);
1247
- _$effect((_$p) => _$setProp(_el$103, "style", {
1388
+ var _el$126 = _$createElement("span"), _el$127 = _$createTextNode(` \u2192 `);
1389
+ _$insertNode(_el$126, _el$127);
1390
+ _$insert(_el$126, () => goal().lastProgress.next?.slice(0, 60) || "", null);
1391
+ _$effect((_$p) => _$setProp(_el$126, "style", {
1248
1392
  fg: theme().textMuted
1249
1393
  }, _$p));
1250
- return _el$103;
1394
+ return _el$126;
1251
1395
  })()];
1252
1396
  })(), null);
1253
- _$insert(_el$86, (() => {
1397
+ _$insert(_el$109, (() => {
1254
1398
  var _c$9 = _$memo(() => !!goal().blocker);
1255
1399
  return () => _c$9() && [(() => {
1256
- var _el$105 = _$createElement("span"), _el$106 = _$createTextNode(`
1400
+ var _el$128 = _$createElement("span"), _el$129 = _$createTextNode(`
1257
1401
  \u2716 blocked: `);
1258
- _$insertNode(_el$105, _el$106);
1259
- _$effect((_$p) => _$setProp(_el$105, "style", {
1402
+ _$insertNode(_el$128, _el$129);
1403
+ _$effect((_$p) => _$setProp(_el$128, "style", {
1260
1404
  fg: theme().error,
1261
1405
  bold: true
1262
1406
  }, _$p));
1263
- return _el$105;
1407
+ return _el$128;
1264
1408
  })(), (() => {
1265
- var _el$108 = _$createElement("span");
1266
- _$insert(_el$108, () => goal().blocker.reason.slice(0, 140));
1267
- _$effect((_$p) => _$setProp(_el$108, "style", {
1409
+ var _el$131 = _$createElement("span");
1410
+ _$insert(_el$131, () => goal().blocker.reason.slice(0, 140));
1411
+ _$effect((_$p) => _$setProp(_el$131, "style", {
1268
1412
  fg: theme().error
1269
1413
  }, _$p));
1270
- return _el$108;
1414
+ return _el$131;
1271
1415
  })(), (() => {
1272
- var _el$109 = _$createElement("span"), _el$110 = _$createTextNode(` \u2014 `);
1273
- _$insertNode(_el$109, _el$110);
1274
- _$insert(_el$109, () => goal().blocker.needed.slice(0, 60), null);
1275
- _$effect((_$p) => _$setProp(_el$109, "style", {
1416
+ var _el$132 = _$createElement("span"), _el$133 = _$createTextNode(` \u2014 `);
1417
+ _$insertNode(_el$132, _el$133);
1418
+ _$insert(_el$132, () => goal().blocker.needed.slice(0, 60), null);
1419
+ _$effect((_$p) => _$setProp(_el$132, "style", {
1276
1420
  fg: theme().textMuted
1277
1421
  }, _$p));
1278
- return _el$109;
1422
+ return _el$132;
1279
1423
  })()];
1280
1424
  })(), null);
1281
- _$insert(_el$86, (() => {
1425
+ _$insert(_el$109, (() => {
1282
1426
  var _c$0 = _$memo(() => !!goal().config.artifactDir);
1283
1427
  return () => _c$0() && [(() => {
1284
- var _el$111 = _$createElement("span"), _el$112 = _$createTextNode(`
1428
+ var _el$134 = _$createElement("span"), _el$135 = _$createTextNode(`
1285
1429
  \uD83D\uDCC1 `);
1286
- _$insertNode(_el$111, _el$112);
1287
- _$effect((_$p) => _$setProp(_el$111, "style", {
1430
+ _$insertNode(_el$134, _el$135);
1431
+ _$effect((_$p) => _$setProp(_el$134, "style", {
1288
1432
  fg: theme().accent
1289
1433
  }, _$p));
1290
- return _el$111;
1434
+ return _el$134;
1291
1435
  })(), (() => {
1292
- var _el$114 = _$createElement("span");
1293
- _$insert(_el$114, () => String(goal().config.artifactDir).replace(String(props.directory), "."));
1294
- _$effect((_$p) => _$setProp(_el$114, "style", {
1436
+ var _el$137 = _$createElement("span");
1437
+ _$insert(_el$137, () => String(goal().config.artifactDir).replace(String(props.directory), "."));
1438
+ _$effect((_$p) => _$setProp(_el$137, "style", {
1295
1439
  fg: theme().textMuted
1296
1440
  }, _$p));
1297
- return _el$114;
1441
+ return _el$137;
1298
1442
  })()];
1299
1443
  })(), null);
1300
- _$insert(_el$86, (() => {
1301
- var _c$1 = _$memo(() => !!rt()?.lastError);
1302
- return () => _c$1() && [(() => {
1303
- var _el$115 = _$createElement("span"), _el$116 = _$createTextNode(`
1444
+ _$insert(_el$109, (() => {
1445
+ var _c$1 = _$memo(() => (goal().config.checks?.length ?? 0) > 0);
1446
+ return () => _c$1() ? [(() => {
1447
+ var _el$138 = _$createElement("span"), _el$139 = _$createTextNode(`
1448
+ \u25A3 checks: `);
1449
+ _$insertNode(_el$138, _el$139);
1450
+ _$effect((_$p) => _$setProp(_el$138, "style", {
1451
+ fg: theme().warning
1452
+ }, _$p));
1453
+ return _el$138;
1454
+ })(), (() => {
1455
+ var _el$141 = _$createElement("span");
1456
+ _$insert(_el$141, () => goal().config.checks.join(", ").slice(0, 100));
1457
+ _$effect((_$p) => _$setProp(_el$141, "style", {
1458
+ fg: theme().textMuted
1459
+ }, _$p));
1460
+ return _el$141;
1461
+ })()] : null;
1462
+ })(), null);
1463
+ _$insert(_el$109, (() => {
1464
+ var _c$10 = _$memo(() => !!rt()?.lastError);
1465
+ return () => _c$10() && [(() => {
1466
+ var _el$142 = _$createElement("span"), _el$143 = _$createTextNode(`
1304
1467
  \u26A0 `);
1305
- _$insertNode(_el$115, _el$116);
1306
- _$effect((_$p) => _$setProp(_el$115, "style", {
1468
+ _$insertNode(_el$142, _el$143);
1469
+ _$effect((_$p) => _$setProp(_el$142, "style", {
1307
1470
  fg: theme().error
1308
1471
  }, _$p));
1309
- return _el$115;
1472
+ return _el$142;
1310
1473
  })(), (() => {
1311
- var _el$118 = _$createElement("span");
1312
- _$insert(_el$118, () => rt().lastError.slice(0, 120));
1313
- _$effect((_$p) => _$setProp(_el$118, "style", {
1474
+ var _el$145 = _$createElement("span");
1475
+ _$insert(_el$145, () => rt().lastError.slice(0, 120));
1476
+ _$effect((_$p) => _$setProp(_el$145, "style", {
1314
1477
  fg: theme().error
1315
1478
  }, _$p));
1316
- return _el$118;
1479
+ return _el$145;
1317
1480
  })()];
1318
1481
  })(), null);
1319
1482
  _$effect((_p$) => {
@@ -1325,10 +1488,10 @@ function LoopDashboard(props) {
1325
1488
  }, _v$38 = {
1326
1489
  fg: theme().text
1327
1490
  };
1328
- _v$35 !== _p$.e && (_p$.e = _$setProp(_el$85, "borderColor", _v$35, _p$.e));
1329
- _v$36 !== _p$.t && (_p$.t = _$setProp(_el$87, "style", _v$36, _p$.t));
1330
- _v$37 !== _p$.a && (_p$.a = _$setProp(_el$89, "style", _v$37, _p$.a));
1331
- _v$38 !== _p$.o && (_p$.o = _$setProp(_el$92, "style", _v$38, _p$.o));
1491
+ _v$35 !== _p$.e && (_p$.e = _$setProp(_el$108, "borderColor", _v$35, _p$.e));
1492
+ _v$36 !== _p$.t && (_p$.t = _$setProp(_el$110, "style", _v$36, _p$.t));
1493
+ _v$37 !== _p$.a && (_p$.a = _$setProp(_el$112, "style", _v$37, _p$.a));
1494
+ _v$38 !== _p$.o && (_p$.o = _$setProp(_el$115, "style", _v$38, _p$.o));
1332
1495
  return _p$;
1333
1496
  }, {
1334
1497
  e: undefined,
@@ -1336,48 +1499,48 @@ function LoopDashboard(props) {
1336
1499
  a: undefined,
1337
1500
  o: undefined
1338
1501
  });
1339
- return _el$85;
1502
+ return _el$108;
1340
1503
  })();
1341
1504
  }
1342
1505
  }), null);
1343
- _$insert(_el$25, _$createComponent(Show, {
1506
+ _$insert(_el$29, _$createComponent(Show, {
1344
1507
  get when() {
1345
1508
  return _$memo(() => !!showLogs())() && events().length > 0;
1346
1509
  },
1347
1510
  get children() {
1348
- var _el$31 = _$createElement("box"), _el$32 = _$createElement("text"), _el$33 = _$createElement("span"), _el$35 = _$createElement("span");
1349
- _$insertNode(_el$31, _el$32);
1350
- _$setProp(_el$31, "flexDirection", "column");
1351
- _$setProp(_el$31, "border", true);
1352
- _$setProp(_el$31, "padding", 1);
1353
- _$setProp(_el$31, "maxHeight", 7);
1354
- _$setProp(_el$31, "flexShrink", 0);
1355
- _$setProp(_el$31, "overflow", "hidden");
1356
- _$insertNode(_el$32, _el$33);
1357
- _$insertNode(_el$32, _el$35);
1358
- _$insertNode(_el$33, _$createTextNode(`\u25C8 Recent Events`));
1359
- _$insertNode(_el$35, _$createTextNode(` \u2014 :logs to hide`));
1360
- _$insert(_el$31, _$createComponent(For, {
1511
+ var _el$35 = _$createElement("box"), _el$36 = _$createElement("text"), _el$37 = _$createElement("span"), _el$39 = _$createElement("span");
1512
+ _$insertNode(_el$35, _el$36);
1513
+ _$setProp(_el$35, "flexDirection", "column");
1514
+ _$setProp(_el$35, "border", true);
1515
+ _$setProp(_el$35, "padding", 1);
1516
+ _$setProp(_el$35, "maxHeight", 7);
1517
+ _$setProp(_el$35, "flexShrink", 0);
1518
+ _$setProp(_el$35, "overflow", "hidden");
1519
+ _$insertNode(_el$36, _el$37);
1520
+ _$insertNode(_el$36, _el$39);
1521
+ _$insertNode(_el$37, _$createTextNode(`\u25C8 Recent Events`));
1522
+ _$insertNode(_el$39, _$createTextNode(` \u2014 :logs to hide`));
1523
+ _$insert(_el$35, _$createComponent(For, {
1361
1524
  get each() {
1362
1525
  return events().slice(-10);
1363
1526
  },
1364
1527
  children: (ev) => (() => {
1365
- var _el$119 = _$createElement("text"), _el$120 = _$createElement("span"), _el$121 = _$createElement("span"), _el$122 = _$createTextNode(` `);
1366
- _$insertNode(_el$119, _el$120);
1367
- _$insertNode(_el$119, _el$121);
1368
- _$insert(_el$120, () => String(ev.type));
1369
- _$insertNode(_el$121, _el$122);
1370
- _$insert(_el$121, () => ev.goalID?.slice(0, 8), null);
1371
- _$insert(_el$119, (() => {
1372
- var _c$10 = _$memo(() => !!ev.summary);
1373
- return () => _c$10() && (() => {
1374
- var _el$123 = _$createElement("span"), _el$124 = _$createTextNode(` \u2014 `);
1375
- _$insertNode(_el$123, _el$124);
1376
- _$insert(_el$123, () => String(ev.summary).slice(0, 60), null);
1377
- _$effect((_$p) => _$setProp(_el$123, "style", {
1528
+ var _el$146 = _$createElement("text"), _el$147 = _$createElement("span"), _el$148 = _$createElement("span"), _el$149 = _$createTextNode(` `);
1529
+ _$insertNode(_el$146, _el$147);
1530
+ _$insertNode(_el$146, _el$148);
1531
+ _$insert(_el$147, () => String(ev.type));
1532
+ _$insertNode(_el$148, _el$149);
1533
+ _$insert(_el$148, () => ev.goalID?.slice(0, 8), null);
1534
+ _$insert(_el$146, (() => {
1535
+ var _c$11 = _$memo(() => !!ev.summary);
1536
+ return () => _c$11() && (() => {
1537
+ var _el$150 = _$createElement("span"), _el$151 = _$createTextNode(` \u2014 `);
1538
+ _$insertNode(_el$150, _el$151);
1539
+ _$insert(_el$150, () => String(ev.summary).slice(0, 60), null);
1540
+ _$effect((_$p) => _$setProp(_el$150, "style", {
1378
1541
  fg: theme().text
1379
1542
  }, _$p));
1380
- return _el$123;
1543
+ return _el$150;
1381
1544
  })();
1382
1545
  })(), null);
1383
1546
  _$effect((_p$) => {
@@ -1387,14 +1550,14 @@ function LoopDashboard(props) {
1387
1550
  }, _v$40 = {
1388
1551
  fg: theme().textMuted
1389
1552
  };
1390
- _v$39 !== _p$.e && (_p$.e = _$setProp(_el$120, "style", _v$39, _p$.e));
1391
- _v$40 !== _p$.t && (_p$.t = _$setProp(_el$121, "style", _v$40, _p$.t));
1553
+ _v$39 !== _p$.e && (_p$.e = _$setProp(_el$147, "style", _v$39, _p$.e));
1554
+ _v$40 !== _p$.t && (_p$.t = _$setProp(_el$148, "style", _v$40, _p$.t));
1392
1555
  return _p$;
1393
1556
  }, {
1394
1557
  e: undefined,
1395
1558
  t: undefined
1396
1559
  });
1397
- return _el$119;
1560
+ return _el$146;
1398
1561
  })()
1399
1562
  }), null);
1400
1563
  _$effect((_p$) => {
@@ -1404,42 +1567,42 @@ function LoopDashboard(props) {
1404
1567
  }, _v$3 = {
1405
1568
  fg: theme().textMuted
1406
1569
  };
1407
- _v$ !== _p$.e && (_p$.e = _$setProp(_el$31, "borderColor", _v$, _p$.e));
1408
- _v$2 !== _p$.t && (_p$.t = _$setProp(_el$33, "style", _v$2, _p$.t));
1409
- _v$3 !== _p$.a && (_p$.a = _$setProp(_el$35, "style", _v$3, _p$.a));
1570
+ _v$ !== _p$.e && (_p$.e = _$setProp(_el$35, "borderColor", _v$, _p$.e));
1571
+ _v$2 !== _p$.t && (_p$.t = _$setProp(_el$37, "style", _v$2, _p$.t));
1572
+ _v$3 !== _p$.a && (_p$.a = _$setProp(_el$39, "style", _v$3, _p$.a));
1410
1573
  return _p$;
1411
1574
  }, {
1412
1575
  e: undefined,
1413
1576
  t: undefined,
1414
1577
  a: undefined
1415
1578
  });
1416
- return _el$31;
1579
+ return _el$35;
1417
1580
  }
1418
1581
  }), null);
1419
- _$insertNode(_el$37, _el$38);
1420
- _$insertNode(_el$37, _el$40);
1421
- _$setProp(_el$37, "flexDirection", "row");
1422
- _$setProp(_el$37, "border", true);
1423
- _$setProp(_el$37, "paddingLeft", 1);
1424
- _$setProp(_el$37, "paddingRight", 1);
1425
- _$setProp(_el$37, "flexShrink", 0);
1426
- _$setProp(_el$37, "height", 3);
1427
- _$setProp(_el$37, "gap", 1);
1428
- _$insertNode(_el$38, _el$39);
1429
- _$insert(_el$39, () => mode() === "insert" ? " INSERT \uE0B1" : " NORMAL ");
1582
+ _$insertNode(_el$41, _el$42);
1583
+ _$insertNode(_el$41, _el$44);
1584
+ _$setProp(_el$41, "flexDirection", "row");
1585
+ _$setProp(_el$41, "border", true);
1586
+ _$setProp(_el$41, "paddingLeft", 1);
1587
+ _$setProp(_el$41, "paddingRight", 1);
1588
+ _$setProp(_el$41, "flexShrink", 0);
1589
+ _$setProp(_el$41, "height", 3);
1590
+ _$setProp(_el$41, "gap", 1);
1591
+ _$insertNode(_el$42, _el$43);
1592
+ _$insert(_el$43, () => mode() === "insert" ? " INSERT \uE0B1" : " NORMAL ");
1430
1593
  _$use((el) => {
1431
1594
  inputEl = el;
1432
1595
  focusInput();
1433
- }, _el$40);
1434
- _$setProp(_el$40, "flexGrow", 1);
1435
- _$setProp(_el$40, "onInput", (v) => {
1596
+ }, _el$44);
1597
+ _$setProp(_el$44, "flexGrow", 1);
1598
+ _$setProp(_el$44, "onInput", (v) => {
1436
1599
  debugLog("onInput", JSON.stringify(v), "mode", mode());
1437
1600
  if (mode() === "insert")
1438
1601
  setCommandInput(v);
1439
1602
  else if (inputEl?.value)
1440
1603
  inputEl.value = "";
1441
1604
  });
1442
- _$setProp(_el$40, "onKeyDown", (evt) => {
1605
+ _$setProp(_el$44, "onKeyDown", (evt) => {
1443
1606
  const name = evt.name || "";
1444
1607
  const seq = evt.sequence || "";
1445
1608
  debugLog("input onKeyDown", `name=${name} seq=${JSON.stringify(seq)} mode=${mode()} value=${JSON.stringify(commandInput())}`);
@@ -1507,13 +1670,13 @@ function LoopDashboard(props) {
1507
1670
  _v$11 !== _p$.d && (_p$.d = _$setProp(_el$20, "style", _v$11, _p$.d));
1508
1671
  _v$12 !== _p$.l && (_p$.l = _$setProp(_el$22, "style", _v$12, _p$.l));
1509
1672
  _v$13 !== _p$.u && (_p$.u = _$setProp(_el$23, "style", _v$13, _p$.u));
1510
- _v$14 !== _p$.c && (_p$.c = _$setProp(_el$37, "borderColor", _v$14, _p$.c));
1511
- _v$15 !== _p$.w && (_p$.w = _$setProp(_el$39, "style", _v$15, _p$.w));
1512
- _v$16 !== _p$.m && (_p$.m = _$setProp(_el$40, "placeholder", _v$16, _p$.m));
1513
- _v$17 !== _p$.f && (_p$.f = _$setProp(_el$40, "placeholderColor", _v$17, _p$.f));
1514
- _v$18 !== _p$.y && (_p$.y = _$setProp(_el$40, "cursorColor", _v$18, _p$.y));
1515
- _v$19 !== _p$.g && (_p$.g = _$setProp(_el$40, "focusedTextColor", _v$19, _p$.g));
1516
- _v$20 !== _p$.p && (_p$.p = _$setProp(_el$40, "focusedBackgroundColor", _v$20, _p$.p));
1673
+ _v$14 !== _p$.c && (_p$.c = _$setProp(_el$41, "borderColor", _v$14, _p$.c));
1674
+ _v$15 !== _p$.w && (_p$.w = _$setProp(_el$43, "style", _v$15, _p$.w));
1675
+ _v$16 !== _p$.m && (_p$.m = _$setProp(_el$44, "placeholder", _v$16, _p$.m));
1676
+ _v$17 !== _p$.f && (_p$.f = _$setProp(_el$44, "placeholderColor", _v$17, _p$.f));
1677
+ _v$18 !== _p$.y && (_p$.y = _$setProp(_el$44, "cursorColor", _v$18, _p$.y));
1678
+ _v$19 !== _p$.g && (_p$.g = _$setProp(_el$44, "focusedTextColor", _v$19, _p$.g));
1679
+ _v$20 !== _p$.p && (_p$.p = _$setProp(_el$44, "focusedBackgroundColor", _v$20, _p$.p));
1517
1680
  return _p$;
1518
1681
  }, {
1519
1682
  e: undefined,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "@bojackduy/opencode-loopd",
4
- "version": "1.2.0",
4
+ "version": "1.4.0",
5
5
  "description": "Codex-inspired background goal engine for OpenCode — autonomous subagents, engine-driven loop, child worker sessions and modal TUI dashboard. Like Claude Code loop for OpenCode.",
6
6
  "type": "module",
7
7
  "license": "AGPL-3.0-only",