@bojackduy/opencode-loopd 1.8.2 → 1.8.3

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.
package/dist/server.js CHANGED
@@ -1,34 +1,5 @@
1
1
  // @bun
2
- var __defProp = Object.defineProperty;
3
- var __returnValue = (v) => v;
4
- function __exportSetter(name, newValue) {
5
- this[name] = __returnValue.bind(null, newValue);
6
- }
7
- var __export = (target, all) => {
8
- for (var name in all)
9
- __defProp(target, name, {
10
- get: all[name],
11
- enumerable: true,
12
- configurable: true,
13
- set: __exportSetter.bind(all, name)
14
- });
15
- };
16
-
17
2
  // src/domain/runtime.ts
18
- var exports_runtime = {};
19
- __export(exports_runtime, {
20
- acquireLease: () => acquireLease,
21
- addToolCall: () => addToolCall,
22
- createRuntimeState: () => createRuntimeState,
23
- hasActiveToolCalls: () => hasActiveToolCalls,
24
- leaseIsValid: () => leaseIsValid,
25
- markParentNotified: () => markParentNotified,
26
- markProgress: () => markProgress,
27
- recordActivity: () => recordActivity,
28
- releaseLease: () => releaseLease,
29
- removeToolCall: () => removeToolCall,
30
- shouldNotifyParent: () => shouldNotifyParent
31
- });
32
3
  function createRuntimeState(goalID) {
33
4
  const now = new Date().toISOString();
34
5
  return {
@@ -135,9 +106,6 @@ function removeToolCall(rt, callID) {
135
106
  updatedAt: new Date().toISOString()
136
107
  };
137
108
  }
138
- function hasActiveToolCalls(rt) {
139
- return (rt.activeToolCallIDs?.length ?? 0) > 0;
140
- }
141
109
  var PARENT_NOTIFY_DEDUPE_MS = 60000;
142
110
 
143
111
  // src/application/control-worker.ts
@@ -176,8 +144,8 @@ async function acquireLock(directory, key, operation) {
176
144
  try {
177
145
  try {
178
146
  const raw = await fs.readFile(lockPath, "utf8");
179
- const meta2 = JSON.parse(raw);
180
- const age = Date.now() - Date.parse(meta2.acquiredAt);
147
+ const meta = JSON.parse(raw);
148
+ const age = Date.now() - Date.parse(meta.acquiredAt);
181
149
  if (age > LOCK_STALE_MS) {
182
150
  await fs.rm(lockPath, { force: true });
183
151
  }
@@ -712,54 +680,54 @@ function createControlWorker(options) {
712
680
  ownerSessionID: args.ownerSessionID,
713
681
  config: resolution.config
714
682
  });
715
- const state2 = await readState(directory);
683
+ const state = await readState(directory);
716
684
  response = {
717
685
  ...base,
718
686
  message: `goal "${args.name}" created (${goal.id.slice(0, 8)}...)`,
719
- stateRevision: state2.revision
687
+ stateRevision: state.revision
720
688
  };
721
689
  break;
722
690
  }
723
691
  case "pause": {
724
692
  await goalSvc.pause(directory, request.goalID);
725
- const state2 = await readState(directory);
726
- const goal = state2.goals.find((g) => g.id === request.goalID);
693
+ const state = await readState(directory);
694
+ const goal = state.goals.find((g) => g.id === request.goalID);
727
695
  response = {
728
696
  ...base,
729
697
  message: `goal "${goal?.name || request.goalID}" paused`,
730
- stateRevision: state2.revision
698
+ stateRevision: state.revision
731
699
  };
732
700
  break;
733
701
  }
734
702
  case "resume": {
735
703
  await goalSvc.resume(directory, request.goalID);
736
- const state2 = await readState(directory);
737
- const goal = state2.goals.find((g) => g.id === request.goalID);
704
+ const state = await readState(directory);
705
+ const goal = state.goals.find((g) => g.id === request.goalID);
738
706
  response = {
739
707
  ...base,
740
708
  message: `goal "${goal?.name || request.goalID}" resumed`,
741
- stateRevision: state2.revision
709
+ stateRevision: state.revision
742
710
  };
743
711
  break;
744
712
  }
745
713
  case "retry": {
746
714
  await goalSvc.retry(directory, request.goalID);
747
- const state2 = await readState(directory);
748
- const goal = state2.goals.find((g) => g.id === request.goalID);
715
+ const state = await readState(directory);
716
+ const goal = state.goals.find((g) => g.id === request.goalID);
749
717
  response = {
750
718
  ...base,
751
719
  message: `goal "${goal?.name || request.goalID}" retried`,
752
- stateRevision: state2.revision
720
+ stateRevision: state.revision
753
721
  };
754
722
  break;
755
723
  }
756
724
  case "clear": {
757
725
  await goalSvc.clear(directory, request.goalID);
758
- const state2 = await readState(directory);
726
+ const state = await readState(directory);
759
727
  response = {
760
728
  ...base,
761
729
  message: `goal cleared`,
762
- stateRevision: state2.revision
730
+ stateRevision: state.revision
763
731
  };
764
732
  break;
765
733
  }
@@ -775,25 +743,25 @@ function createControlWorker(options) {
775
743
  break;
776
744
  }
777
745
  await appendGoalInbox(directory, request.goalID, "user", text);
778
- const state2 = await readState(directory);
779
- const goal = state2.goals.find((g) => g.id === request.goalID);
746
+ const state = await readState(directory);
747
+ const goal = state.goals.find((g) => g.id === request.goalID);
780
748
  response = {
781
749
  ...base,
782
750
  message: `sent to "${goal?.name || request.goalID}"`,
783
- stateRevision: state2.revision
751
+ stateRevision: state.revision
784
752
  };
785
753
  break;
786
754
  }
787
755
  case "force_complete": {
788
756
  const args = request.args;
789
- const state2 = await readState(directory);
790
- const goal = state2.goals.find((g) => g.id === request.goalID);
757
+ const state = await readState(directory);
758
+ const goal = state.goals.find((g) => g.id === request.goalID);
791
759
  if (!goal) {
792
760
  response = { ...base, ok: false, message: "goal not found", errorCode: "not_found" };
793
761
  break;
794
762
  }
795
763
  if (goal.status === "complete") {
796
- response = { ...base, message: `goal "${goal.name}" already complete`, stateRevision: state2.revision };
764
+ response = { ...base, message: `goal "${goal.name}" already complete`, stateRevision: state.revision };
797
765
  break;
798
766
  }
799
767
  goal.status = "complete";
@@ -803,14 +771,14 @@ function createControlWorker(options) {
803
771
  evidence: String(args.evidence || "Manual override \u2014 no verification checks run."),
804
772
  at: new Date().toISOString()
805
773
  };
806
- const runtime = state2.runtimes.find((r) => r.goalID === goal.id);
774
+ const runtime = state.runtimes.find((r) => r.goalID === goal.id);
807
775
  if (runtime) {
808
776
  Object.assign(runtime, releaseLease(runtime));
809
777
  runtime.activeRunID = undefined;
810
778
  runtime.lastError = undefined;
811
779
  runtime.updatedAt = new Date().toISOString();
812
780
  }
813
- await writeState(directory, state2);
781
+ await writeState(directory, state);
814
782
  await appendEvent(directory, {
815
783
  version: 1,
816
784
  eventID: randomUUID(),
@@ -819,22 +787,22 @@ function createControlWorker(options) {
819
787
  summary: goal.completionEvidence.summary,
820
788
  evidence: goal.completionEvidence.evidence,
821
789
  timestamp: new Date().toISOString(),
822
- revision: state2.revision
790
+ revision: state.revision
823
791
  });
824
- response = { ...base, message: `goal "${goal.name}" force-completed`, stateRevision: state2.revision };
792
+ response = { ...base, message: `goal "${goal.name}" force-completed`, stateRevision: state.revision };
825
793
  break;
826
794
  }
827
795
  case "force_block":
828
796
  case "block": {
829
797
  const args = request.args;
830
- const state2 = await readState(directory);
831
- const goal = state2.goals.find((g) => g.id === request.goalID);
798
+ const state = await readState(directory);
799
+ const goal = state.goals.find((g) => g.id === request.goalID);
832
800
  if (!goal) {
833
801
  response = { ...base, ok: false, message: "goal not found", errorCode: "not_found" };
834
802
  break;
835
803
  }
836
804
  if (goal.status === "blocked") {
837
- response = { ...base, message: `goal "${goal.name}" already blocked`, stateRevision: state2.revision };
805
+ response = { ...base, message: `goal "${goal.name}" already blocked`, stateRevision: state.revision };
838
806
  break;
839
807
  }
840
808
  goal.status = "blocked";
@@ -844,14 +812,14 @@ function createControlWorker(options) {
844
812
  needed: String(args.needed || "User intervention required."),
845
813
  at: new Date().toISOString()
846
814
  };
847
- const runtime = state2.runtimes.find((r) => r.goalID === goal.id);
815
+ const runtime = state.runtimes.find((r) => r.goalID === goal.id);
848
816
  if (runtime) {
849
817
  Object.assign(runtime, releaseLease(runtime));
850
818
  runtime.activeRunID = undefined;
851
819
  runtime.lastError = undefined;
852
820
  runtime.updatedAt = new Date().toISOString();
853
821
  }
854
- await writeState(directory, state2);
822
+ await writeState(directory, state);
855
823
  await appendEvent(directory, {
856
824
  version: 1,
857
825
  eventID: randomUUID(),
@@ -860,9 +828,9 @@ function createControlWorker(options) {
860
828
  reason: goal.blocker.reason,
861
829
  needed: goal.blocker.needed,
862
830
  timestamp: new Date().toISOString(),
863
- revision: state2.revision
831
+ revision: state.revision
864
832
  });
865
- response = { ...base, message: `goal "${goal.name}" blocked`, stateRevision: state2.revision };
833
+ response = { ...base, message: `goal "${goal.name}" blocked`, stateRevision: state.revision };
866
834
  break;
867
835
  }
868
836
  default: {
@@ -878,8 +846,8 @@ function createControlWorker(options) {
878
846
  await recordInLedger(directory, request);
879
847
  return response;
880
848
  }
881
- async function recordInLedger(directory2, request) {
882
- const state = await readState(directory2);
849
+ async function recordInLedger(directory, request) {
850
+ const state = await readState(directory);
883
851
  if (!state.commandLedger)
884
852
  state.commandLedger = [];
885
853
  state.commandLedger.push({
@@ -892,7 +860,7 @@ function createControlWorker(options) {
892
860
  if (state.commandLedger.length > MAX_LEDGER_SIZE) {
893
861
  state.commandLedger = state.commandLedger.slice(-MAX_LEDGER_SIZE);
894
862
  }
895
- await writeState(directory2, state);
863
+ await writeState(directory, state);
896
864
  }
897
865
  return { start, stop: async () => {
898
866
  await stop();
@@ -1879,9 +1847,9 @@ function createGoalService(host) {
1879
1847
  rt.lastScheduleAt = undefined;
1880
1848
  }
1881
1849
  state.runtimes.push(rt);
1882
- const runtime2 = state.runtimes.find((r) => r.goalID === id);
1883
- if (runtime2)
1884
- runtime2.phase = "queued";
1850
+ const runtime = state.runtimes.find((r) => r.goalID === id);
1851
+ if (runtime)
1852
+ runtime.phase = "queued";
1885
1853
  return state;
1886
1854
  });
1887
1855
  let runtime = state1.runtimes.find((r) => r.goalID === id);
@@ -2122,17 +2090,17 @@ function createGoalService(host) {
2122
2090
  }
2123
2091
  async function resumeUnlocked(directory, goalID) {
2124
2092
  let resumed = false;
2125
- const state = await mutateState(directory, `goal.resume:${goalID}`, async (state2) => {
2126
- const goal2 = state2.goals.find((g) => g.id === goalID);
2127
- if (!goal2)
2128
- return state2;
2129
- if (!canTransition(goal2.status, "active", "user"))
2130
- return state2;
2131
- assertWorkspaceWriteAvailable(state2, goal2);
2132
- goal2.status = "active";
2133
- goal2.updatedAt = new Date().toISOString();
2093
+ const state = await mutateState(directory, `goal.resume:${goalID}`, async (state) => {
2094
+ const goal = state.goals.find((g) => g.id === goalID);
2095
+ if (!goal)
2096
+ return state;
2097
+ if (!canTransition(goal.status, "active", "user"))
2098
+ return state;
2099
+ assertWorkspaceWriteAvailable(state, goal);
2100
+ goal.status = "active";
2101
+ goal.updatedAt = new Date().toISOString();
2134
2102
  resumed = true;
2135
- return state2;
2103
+ return state;
2136
2104
  });
2137
2105
  const goal = state.goals.find((g) => g.id === goalID);
2138
2106
  if (!goal || !resumed)
@@ -2162,15 +2130,15 @@ function createGoalService(host) {
2162
2130
  }
2163
2131
  async function retryUnlocked(directory, goalID) {
2164
2132
  let retried = false;
2165
- const state = await mutateState(directory, `goal.retry:${goalID}`, async (state2) => {
2166
- const goal2 = state2.goals.find((g) => g.id === goalID);
2167
- if (!goal2 || goal2.status !== "blocked")
2168
- return state2;
2169
- assertWorkspaceWriteAvailable(state2, goal2);
2170
- goal2.status = "active";
2171
- goal2.updatedAt = new Date().toISOString();
2133
+ const state = await mutateState(directory, `goal.retry:${goalID}`, async (state) => {
2134
+ const goal = state.goals.find((g) => g.id === goalID);
2135
+ if (!goal || goal.status !== "blocked")
2136
+ return state;
2137
+ assertWorkspaceWriteAvailable(state, goal);
2138
+ goal.status = "active";
2139
+ goal.updatedAt = new Date().toISOString();
2172
2140
  retried = true;
2173
- const runtime = state2.runtimes.find((r) => r.goalID === goalID);
2141
+ const runtime = state.runtimes.find((r) => r.goalID === goalID);
2174
2142
  if (runtime) {
2175
2143
  runtime.consecutiveFailures = 0;
2176
2144
  runtime.lastError = undefined;
@@ -2180,7 +2148,7 @@ function createGoalService(host) {
2180
2148
  runtime.phase = "idle";
2181
2149
  runtime.updatedAt = new Date().toISOString();
2182
2150
  }
2183
- return state2;
2151
+ return state;
2184
2152
  });
2185
2153
  const goal = state.goals.find((g) => g.id === goalID);
2186
2154
  if (!goal || !retried)
@@ -2541,16 +2509,22 @@ function createRealHost(client, directory) {
2541
2509
  async sessionStatus(sessionID) {
2542
2510
  try {
2543
2511
  const result = await client.session.status({});
2512
+ if (result?.error)
2513
+ return "unknown";
2544
2514
  const data = result?.data;
2545
- if (!data || typeof data !== "object")
2515
+ if (!data || typeof data !== "object" || Array.isArray(data))
2546
2516
  return "unknown";
2547
2517
  const status = data[sessionID];
2548
- if (!status || typeof status !== "object")
2518
+ if (status === undefined || status === null)
2519
+ return "idle";
2520
+ if (typeof status !== "object" || Array.isArray(status))
2549
2521
  return "unknown";
2550
2522
  const type = status.type;
2551
2523
  if (type === "busy" || type === "retry")
2552
2524
  return type;
2553
- return "idle";
2525
+ if (type === "idle")
2526
+ return "idle";
2527
+ return "unknown";
2554
2528
  } catch {
2555
2529
  return "unknown";
2556
2530
  }
@@ -2861,9 +2835,9 @@ function goalTools(dir, goalService, hostSessionID, defaults = {}) {
2861
2835
  const cwd = goal.config.checkCwd || goal.config.artifactDir || dir;
2862
2836
  const checkResults = await runCompletionChecks(goal.config.checks, cwd);
2863
2837
  if (!checkResults.passed) {
2864
- const runtime2 = state.runtimes.find((r) => r.goalID === goal.id);
2865
- if (runtime2) {
2866
- runtime2.evaluatorRejectionCount = (runtime2.evaluatorRejectionCount || 0) + 1;
2838
+ const runtime = state.runtimes.find((r) => r.goalID === goal.id);
2839
+ if (runtime) {
2840
+ runtime.evaluatorRejectionCount = (runtime.evaluatorRejectionCount || 0) + 1;
2867
2841
  const failureDetails = checkResults.failures.map((f) => {
2868
2842
  const stdoutSnippet = f.stdout ? `
2869
2843
  Stdout: ${f.stdout.slice(0, 500)}` : "";
@@ -2874,7 +2848,7 @@ Exit code: ${f.exitCode}${stdoutSnippet}${stderrSnippet}`;
2874
2848
  }).join(`
2875
2849
 
2876
2850
  `);
2877
- runtime2.lastRejectionDetails = `Rejection #${runtime2.evaluatorRejectionCount} at ${new Date().toISOString()}
2851
+ runtime.lastRejectionDetails = `Rejection #${runtime.evaluatorRejectionCount} at ${new Date().toISOString()}
2878
2852
 
2879
2853
  Working directory: ${cwd}
2880
2854
 
@@ -2882,8 +2856,8 @@ ${failureDetails}`;
2882
2856
  const attemptID = randomUUID5();
2883
2857
  const verificationAttempt = {
2884
2858
  id: attemptID,
2885
- sequence: runtime2.evaluatorRejectionCount,
2886
- runGeneration: runtime2.runGeneration,
2859
+ sequence: runtime.evaluatorRejectionCount,
2860
+ runGeneration: runtime.runGeneration,
2887
2861
  claimedSummary: args.summary,
2888
2862
  claimedEvidence: args.evidence,
2889
2863
  startedAt: new Date().toISOString(),
@@ -2897,15 +2871,15 @@ ${failureDetails}`;
2897
2871
  stdout: f.stdout
2898
2872
  }))
2899
2873
  };
2900
- runtime2.lastVerificationAttempt = verificationAttempt;
2901
- runtime2.recentVerificationAttempts = appendVerificationAttempt(runtime2.recentVerificationAttempts || [], verificationAttempt);
2874
+ runtime.lastVerificationAttempt = verificationAttempt;
2875
+ runtime.recentVerificationAttempts = appendVerificationAttempt(runtime.recentVerificationAttempts || [], verificationAttempt);
2902
2876
  const rejectEvent = {
2903
2877
  version: 1,
2904
2878
  eventID: randomUUID5(),
2905
2879
  goalID: goal.id,
2906
2880
  type: "goal.completion_rejected",
2907
2881
  attemptID,
2908
- rejectionCount: runtime2.evaluatorRejectionCount,
2882
+ rejectionCount: runtime.evaluatorRejectionCount,
2909
2883
  failedCheckCount: checkResults.failures.length,
2910
2884
  failureSummary: failureDetails.slice(0, 500),
2911
2885
  timestamp: new Date().toISOString(),
@@ -2913,16 +2887,16 @@ ${failureDetails}`;
2913
2887
  };
2914
2888
  await appendEvent(dir, rejectEvent);
2915
2889
  const maxRejections = goal.config.maxEvaluatorRejections || 3;
2916
- if (runtime2.evaluatorRejectionCount >= maxRejections) {
2890
+ if (runtime.evaluatorRejectionCount >= maxRejections) {
2917
2891
  goal.status = "blocked";
2918
2892
  goal.updatedAt = new Date().toISOString();
2919
2893
  goal.blocker = {
2920
- reason: `Evaluator rejected ${runtime2.evaluatorRejectionCount} time(s). Last failure:
2894
+ reason: `Evaluator rejected ${runtime.evaluatorRejectionCount} time(s). Last failure:
2921
2895
  ${failureDetails.slice(0, 500)}`,
2922
2896
  needed: "Fix the failing checks and retry the goal.",
2923
2897
  at: new Date().toISOString()
2924
2898
  };
2925
- runtime2.forceFinishRequested = undefined;
2899
+ runtime.forceFinishRequested = undefined;
2926
2900
  await appendEvent(dir, {
2927
2901
  version: 1,
2928
2902
  eventID: randomUUID5(),
@@ -2934,10 +2908,10 @@ ${failureDetails.slice(0, 500)}`,
2934
2908
  revision: state.revision
2935
2909
  });
2936
2910
  } else {
2937
- runtime2.forceFinishRequested = false;
2938
- runtime2.freeRetryPending = true;
2911
+ runtime.forceFinishRequested = false;
2912
+ runtime.freeRetryPending = true;
2939
2913
  }
2940
- runtime2.updatedAt = new Date().toISOString();
2914
+ runtime.updatedAt = new Date().toISOString();
2941
2915
  await writeState(dir, state);
2942
2916
  }
2943
2917
  return {
@@ -2946,7 +2920,7 @@ ${failureDetails.slice(0, 500)}`,
2946
2920
  passed: false,
2947
2921
  failedChecks: checkResults.failures,
2948
2922
  message: "Evaluator rejected completion. Fix the issues above and try again.",
2949
- rejectionCount: runtime2?.evaluatorRejectionCount || 0,
2923
+ rejectionCount: runtime?.evaluatorRejectionCount || 0,
2950
2924
  status: goal.status
2951
2925
  })
2952
2926
  };
@@ -3637,8 +3611,8 @@ var server = async ({ client, directory }, pluginOptions) => {
3637
3611
  "tool.execute.before": async (input, _output) => {
3638
3612
  const activeWorkers = goalService.getActiveWorkers();
3639
3613
  let matchedGoalID;
3640
- for (const [goalID, worker2] of activeWorkers) {
3641
- if (worker2.workerSessionID === input.sessionID) {
3614
+ for (const [goalID, worker] of activeWorkers) {
3615
+ if (worker.workerSessionID === input.sessionID) {
3642
3616
  matchedGoalID = goalID;
3643
3617
  break;
3644
3618
  }
@@ -3661,8 +3635,8 @@ var server = async ({ client, directory }, pluginOptions) => {
3661
3635
  }
3662
3636
  const activeWorkers = goalService.getActiveWorkers();
3663
3637
  let matchedGoalID;
3664
- for (const [goalID, worker2] of activeWorkers) {
3665
- if (worker2.workerSessionID === input.sessionID) {
3638
+ for (const [goalID, worker] of activeWorkers) {
3639
+ if (worker.workerSessionID === input.sessionID) {
3666
3640
  matchedGoalID = goalID;
3667
3641
  break;
3668
3642
  }
@@ -3688,20 +3662,20 @@ var server = async ({ client, directory }, pluginOptions) => {
3688
3662
  const goalID = parsed.goalID;
3689
3663
  if (!goalID)
3690
3664
  return;
3691
- const { shouldNotifyParent: shouldNotifyParent2, markParentNotified: markParentNotified2 } = await Promise.resolve().then(() => exports_runtime);
3665
+ await Promise.resolve();
3692
3666
  const state = await readState(directory);
3693
3667
  const goal = state.goals.find((g) => g.id === goalID);
3694
3668
  if (!goal)
3695
3669
  return;
3696
3670
  const runtime = state.runtimes.find((r) => r.goalID === goalID);
3697
3671
  const notifyType = parsed.status === "complete" ? "complete" : "blocked";
3698
- if (runtime && !shouldNotifyParent2(runtime, notifyType))
3672
+ if (runtime && !shouldNotifyParent(runtime, notifyType))
3699
3673
  return;
3700
3674
  if (runtime) {
3701
3675
  await mutateState(directory, `notify-parent:${goalID}`, async (s) => {
3702
3676
  const rt = s.runtimes.find((r) => r.goalID === goalID);
3703
3677
  if (rt)
3704
- markParentNotified2(rt, notifyType);
3678
+ markParentNotified(rt, notifyType);
3705
3679
  return s;
3706
3680
  });
3707
3681
  }
package/dist/tui.js CHANGED
@@ -574,10 +574,10 @@ function LoopDashboard(props) {
574
574
  try {
575
575
  const s = await client.getState();
576
576
  setState(s);
577
- const goals2 = s.goals.filter((g) => showCompleted() || g.status !== "complete");
578
- if (goals2.length > 0 && selected() >= goals2.length)
579
- setSelected(goals2.length - 1);
580
- setSelectedGoal(goals2[selected()] || null);
577
+ const goals = s.goals.filter((g) => showCompleted() || g.status !== "complete");
578
+ if (goals.length > 0 && selected() >= goals.length)
579
+ setSelected(goals.length - 1);
580
+ setSelectedGoal(goals[selected()] || null);
581
581
  setEvents(await client.getEvents(20));
582
582
  } catch (e) {
583
583
  setStatusText(`Error: ${e instanceof Error ? e.message : String(e)}`);
@@ -1077,7 +1077,7 @@ function LoopDashboard(props) {
1077
1077
  children: (seg, idx) => {
1078
1078
  const hasArrow = seg.includes("\u2192");
1079
1079
  if (hasArrow) {
1080
- const [k2, d2] = seg.split("\u2192").map((s) => s.trim());
1080
+ const [k, d] = seg.split("\u2192").map((s) => s.trim());
1081
1081
  return [_$memo(() => _$memo(() => idx() > 0)() && (() => {
1082
1082
  var _el$54 = _$createElement("span");
1083
1083
  _$insertNode(_el$54, _$createTextNode(` | `));
@@ -1087,7 +1087,7 @@ function LoopDashboard(props) {
1087
1087
  return _el$54;
1088
1088
  })()), (() => {
1089
1089
  var _el$50 = _$createElement("span");
1090
- _$insert(_el$50, k2);
1090
+ _$insert(_el$50, k);
1091
1091
  _$effect((_$p) => _$setProp(_el$50, "style", {
1092
1092
  fg: theme().warning,
1093
1093
  bold: true
@@ -1102,7 +1102,7 @@ function LoopDashboard(props) {
1102
1102
  return _el$51;
1103
1103
  })(), (() => {
1104
1104
  var _el$53 = _$createElement("span");
1105
- _$insert(_el$53, d2);
1105
+ _$insert(_el$53, d);
1106
1106
  _$effect((_$p) => _$setProp(_el$53, "style", {
1107
1107
  fg: theme().text
1108
1108
  }, _$p));
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.8.2",
4
+ "version": "1.8.3",
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-or-later",