@oxgeneral/orch 0.2.3 → 0.2.4

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 (44) hide show
  1. package/dist/{App-KDZSTAMR.js → App-KHUT3IV7.js} +169 -71
  2. package/dist/{chunk-VTA74YWX.js → chunk-2KSBOAW3.js} +1 -1
  3. package/dist/{chunk-O5AO5QIR.js → chunk-3TGCIXJA.js} +7 -1
  4. package/dist/{chunk-6GFVB6EK.js → chunk-FRTKB575.js} +24 -38
  5. package/dist/chunk-K6DMQERQ.js +89 -0
  6. package/dist/{chunk-2B32FPEB.js → chunk-QTDKQYZI.js} +3 -3
  7. package/dist/{chunk-2B32FPEB.js.map → chunk-QTDKQYZI.js.map} +1 -1
  8. package/dist/{chunk-ZU6AY2VU.js → chunk-VAAOW526.js} +2 -2
  9. package/dist/chunk-VAAOW526.js.map +1 -0
  10. package/dist/chunk-ZTQ3KWXR.js +13 -0
  11. package/dist/chunk-ZTQ3KWXR.js.map +1 -0
  12. package/dist/cli.js +16 -16
  13. package/dist/{container-JV7TAUP5.js → container-KPH4HVAJ.js} +6 -6
  14. package/dist/{doctor-IO4PV4D6.js → doctor-GHRV5I2S.js} +4 -4
  15. package/dist/doctor-service-QEJCE5FK.js +3 -0
  16. package/dist/doctor-service-QEJCE5FK.js.map +1 -0
  17. package/dist/doctor-service-TPOMFAIG.js +2 -0
  18. package/dist/index.d.ts +20 -4
  19. package/dist/index.js +3 -3
  20. package/dist/index.js.map +1 -1
  21. package/dist/{init-BE5VKWOM.js → init-EQTGQ4G2.js} +18 -2
  22. package/dist/{logs-IAUAS5TX.js → logs-AK255DEJ.js} +1 -1
  23. package/dist/orchestrator-L6QX2LJ7.js +2 -0
  24. package/dist/{orchestrator-TAFBYQQ5.js.map → orchestrator-L6QX2LJ7.js.map} +1 -1
  25. package/dist/{orchestrator-VGYKSOZJ.js → orchestrator-OMU46RCE.js} +47 -19
  26. package/dist/{task-5OJTXW27.js → task-35SDKXFC.js} +1 -1
  27. package/dist/{tui-XDJE3IUA.js → tui-AR6PVMBQ.js} +6 -1
  28. package/dist/{update-72GZMF65.js → update-DCCWVISK.js} +1 -1
  29. package/dist/update-check-4YKLGBFB.js +2 -0
  30. package/dist/workspace-manager-AS4TFA7R.js +3 -0
  31. package/dist/workspace-manager-AS4TFA7R.js.map +1 -0
  32. package/dist/{workspace-manager-47KI7B27.js → workspace-manager-G5EQRS72.js} +38 -2
  33. package/package.json +1 -1
  34. package/dist/chunk-E3TCKHU6.js +0 -13
  35. package/dist/chunk-E3TCKHU6.js.map +0 -1
  36. package/dist/chunk-XI4TU6VU.js +0 -50
  37. package/dist/chunk-ZU6AY2VU.js.map +0 -1
  38. package/dist/doctor-service-A34DHPKI.js +0 -2
  39. package/dist/doctor-service-NTWBWOM2.js +0 -2
  40. package/dist/doctor-service-NTWBWOM2.js.map +0 -1
  41. package/dist/orchestrator-TAFBYQQ5.js +0 -2
  42. package/dist/update-check-4RV7Z6WT.js +0 -2
  43. package/dist/workspace-manager-7M46ESUL.js +0 -2
  44. package/dist/workspace-manager-7M46ESUL.js.map +0 -1
@@ -46,7 +46,11 @@ var tuiColors = {
46
46
  // deep amber background for warnings
47
47
  successBg: "#0f2d1f",
48
48
  // deep green background for success
49
- infoBg: "#1a1a22"};
49
+ infoBg: "#1a1a22",
50
+ // subtle dark background for info chips
51
+ toolBg: "#0f1f2d"
52
+ // deep blue background for tool calls
53
+ };
50
54
  var HEAVY_RULE = "\u2501";
51
55
  var LIGHT_RULE = "\u2500";
52
56
  var DOT = "\xB7";
@@ -651,13 +655,24 @@ function BrandBar({
651
655
  mode,
652
656
  stats,
653
657
  uptime,
654
- width
658
+ width,
659
+ version,
660
+ latestVersion
655
661
  }) {
656
662
  const isWatching = mode === "watching";
657
663
  return /* @__PURE__ */ jsxs(Box, { paddingX: 1, justifyContent: "space-between", width, children: [
658
664
  /* @__PURE__ */ jsxs(Box, { gap: 0, children: [
659
665
  /* @__PURE__ */ jsx(PulsingDiamond, {}),
660
666
  /* @__PURE__ */ jsx(Text, { color: tuiColors.amber, bold: true, children: " ORCH" }),
667
+ version && /* @__PURE__ */ jsxs(Text, { color: tuiColors.ghost, children: [
668
+ " ",
669
+ version
670
+ ] }),
671
+ latestVersion && latestVersion !== version && /* @__PURE__ */ jsxs(Text, { backgroundColor: chipBg4.green, color: tuiColors.green, bold: true, children: [
672
+ " UPDATE ",
673
+ latestVersion,
674
+ " "
675
+ ] }),
661
676
  /* @__PURE__ */ jsxs(Text, { color: tuiColors.ghost, children: [
662
677
  " ",
663
678
  DOT,
@@ -799,7 +814,9 @@ var Header = React5.memo(function Header2(props) {
799
814
  mode: props.mode,
800
815
  stats: props.stats,
801
816
  uptime: props.uptime,
802
- width: props.width
817
+ width: props.width,
818
+ version: props.version,
819
+ latestVersion: props.latestVersion
803
820
  }
804
821
  ),
805
822
  /* @__PURE__ */ jsx(Box, { height: 1 }),
@@ -929,6 +946,7 @@ var CommandBar = React5.memo(function CommandBar2({
929
946
  canReject,
930
947
  canCancel,
931
948
  canDelete,
949
+ canUndo,
932
950
  canEdit,
933
951
  canForceStop,
934
952
  canToggleAuto,
@@ -1020,6 +1038,11 @@ var CommandBar = React5.memo(function CommandBar2({
1020
1038
  /* @__PURE__ */ jsx(Text, { bold: true, color: tuiColors.gray, children: "D" }),
1021
1039
  " delete"
1022
1040
  ] }),
1041
+ canUndo && /* @__PURE__ */ jsxs(Fragment, { children: [
1042
+ " ",
1043
+ /* @__PURE__ */ jsx(Text, { bold: true, color: tuiColors.yellow, children: "Z" }),
1044
+ " undo"
1045
+ ] }),
1023
1046
  hasDetail && /* @__PURE__ */ jsxs(Fragment, { children: [
1024
1047
  " ",
1025
1048
  /* @__PURE__ */ jsx(Text, { bold: true, color: tuiColors.gray, children: "Esc" }),
@@ -1274,9 +1297,6 @@ function FormWizard({ title, steps, onComplete, onCancel, width, height }) {
1274
1297
  }
1275
1298
  if (key.backspace || key.delete) {
1276
1299
  if (taCursorCol === 0 && taCursorRow === 0) {
1277
- if (taLines.length === 1 && taLines[0] === "" && currentStep > 0) {
1278
- goToPrevStep();
1279
- }
1280
1300
  return;
1281
1301
  }
1282
1302
  if (taCursorCol > 0) {
@@ -1302,13 +1322,36 @@ function FormWizard({ title, steps, onComplete, onCancel, width, height }) {
1302
1322
  return;
1303
1323
  }
1304
1324
  if (input && !key.ctrl && !key.meta && !key.escape) {
1305
- setTaLines((lines) => {
1306
- const newLines = [...lines];
1307
- const line = newLines[taCursorRow] ?? "";
1308
- newLines[taCursorRow] = line.slice(0, taCursorCol) + input + line.slice(taCursorCol);
1309
- return newLines;
1310
- });
1311
- setTaCursorCol((c) => c + input.length);
1325
+ const parts = input.split(/\r?\n/);
1326
+ if (parts.length === 1) {
1327
+ setTaLines((lines) => {
1328
+ const newLines = [...lines];
1329
+ const line = newLines[taCursorRow] ?? "";
1330
+ newLines[taCursorRow] = line.slice(0, taCursorCol) + input + line.slice(taCursorCol);
1331
+ return newLines;
1332
+ });
1333
+ setTaCursorCol((c) => c + input.length);
1334
+ } else {
1335
+ const row = taCursorRow;
1336
+ const col = taCursorCol;
1337
+ setTaLines((lines) => {
1338
+ const newLines = [...lines];
1339
+ const line = newLines[row] ?? "";
1340
+ const before = line.slice(0, col);
1341
+ const after = line.slice(col);
1342
+ const firstPart = parts[0] ?? "";
1343
+ const lastPart = parts[parts.length - 1] ?? "";
1344
+ const insertLines = [
1345
+ before + firstPart,
1346
+ ...parts.slice(1, -1),
1347
+ lastPart + after
1348
+ ];
1349
+ newLines.splice(row, 1, ...insertLines);
1350
+ return newLines;
1351
+ });
1352
+ setTaCursorRow(row + parts.length - 1);
1353
+ setTaCursorCol((parts[parts.length - 1] ?? "").length);
1354
+ }
1312
1355
  }
1313
1356
  return;
1314
1357
  }
@@ -2076,6 +2119,11 @@ var ONBOARDING_AGENTS = {
2076
2119
  hints: [{ key: "N", label: "new agent" }, { key: "W", label: "start orchestrator" }],
2077
2120
  nudge: "Add more agents to increase parallelism."
2078
2121
  };
2122
+ var UNDO_TIMEOUT_MS = 5e3;
2123
+ var pendingDeletionSeq = 0;
2124
+ function _resetPendingDeletionSeq() {
2125
+ pendingDeletionSeq = 0;
2126
+ }
2079
2127
  var LIFECYCLE_TAG_RE = /^\[[\w_]+\]$/;
2080
2128
  function classifyAgentSummary(summary) {
2081
2129
  if (LIFECYCLE_TAG_RE.test(summary)) return { msgType: "lifecycle", color: tuiColors.dim };
@@ -2185,7 +2233,9 @@ function App({
2185
2233
  initialActivityFilter = "all",
2186
2234
  onSaveActivityFilter,
2187
2235
  initialMaxConcurrent = DEFAULT_CONFIG.scheduling.max_concurrent_agents,
2188
- onSaveMaxConcurrent
2236
+ onSaveMaxConcurrent,
2237
+ version,
2238
+ latestVersion
2189
2239
  }) {
2190
2240
  const { exit } = useApp();
2191
2241
  const { stdout } = useStdout();
@@ -2238,6 +2288,7 @@ function App({
2238
2288
  const [goalScrollOffset, setGoalScrollOffset] = useState(0);
2239
2289
  const [suggestionIndex, setSuggestionIndex] = useState(0);
2240
2290
  const [liveTeams, setLiveTeams] = useState([]);
2291
+ const [pendingDeletions, setPendingDeletions] = useState([]);
2241
2292
  const liveTeamsRef = useRef(liveTeams);
2242
2293
  liveTeamsRef.current = liveTeams;
2243
2294
  const refreshAll = useCallback(async (opts) => {
@@ -2366,6 +2417,65 @@ function App({
2366
2417
  addMessage(`Watch mode failed: ${watchError}. Tasks will not auto-dispatch.`, tuiColors.red);
2367
2418
  }
2368
2419
  }, []);
2420
+ const scheduleDeletion = useCallback((entityType, entityId, entityName, opts) => {
2421
+ const entry = {
2422
+ key: ++pendingDeletionSeq,
2423
+ entityType,
2424
+ entityId,
2425
+ entityName,
2426
+ expiresAt: Date.now() + UNDO_TIMEOUT_MS,
2427
+ needsForceStop: opts?.needsForceStop
2428
+ };
2429
+ setPendingDeletions((prev) => [...prev, entry]);
2430
+ addMessage(`\u2717 "${entityName}" will be deleted in ${Math.round(UNDO_TIMEOUT_MS / 1e3)}s \u2014 press Z to undo`, tuiColors.yellow);
2431
+ }, [addMessage]);
2432
+ const undoLastDeletion = useCallback(() => {
2433
+ setPendingDeletions((prev) => {
2434
+ if (prev.length === 0) return prev;
2435
+ const last = prev[prev.length - 1];
2436
+ addMessage(`\u21B6 Undo: "${last.entityName}" restored`, tuiColors.green);
2437
+ return prev.slice(0, -1);
2438
+ });
2439
+ }, [addMessage]);
2440
+ const executeDeletion = useCallback(async (entry) => {
2441
+ try {
2442
+ if (entry.entityType === "task" && onDeleteTask) {
2443
+ await onDeleteTask(entry.entityId);
2444
+ } else if (entry.entityType === "agent") {
2445
+ if (entry.needsForceStop && onForceStopAgent) {
2446
+ await onForceStopAgent(entry.entityId);
2447
+ }
2448
+ if (onDeleteAgent) await onDeleteAgent(entry.entityId);
2449
+ } else if (entry.entityType === "goal" && onDeleteGoal) {
2450
+ await onDeleteGoal(entry.entityId);
2451
+ }
2452
+ addMessage(`\u2713 Deleted "${entry.entityName}"`, tuiColors.green);
2453
+ refreshAll();
2454
+ } catch (err) {
2455
+ addMessage(`Failed to delete "${entry.entityName}": ${err instanceof Error ? err.message : String(err)}`, tuiColors.red);
2456
+ }
2457
+ }, [onDeleteTask, onDeleteAgent, onDeleteGoal, onForceStopAgent, addMessage, refreshAll]);
2458
+ const executeDeletionRef = useRef(executeDeletion);
2459
+ executeDeletionRef.current = executeDeletion;
2460
+ useEffect(() => {
2461
+ if (pendingDeletions.length === 0) return;
2462
+ const timer2 = setInterval(() => {
2463
+ const now = Date.now();
2464
+ const expired = [];
2465
+ setPendingDeletions((prev) => {
2466
+ const remaining = prev.filter((d) => {
2467
+ if (d.expiresAt <= now) {
2468
+ expired.push(d);
2469
+ return false;
2470
+ }
2471
+ return true;
2472
+ });
2473
+ return expired.length > 0 ? remaining : prev;
2474
+ });
2475
+ for (const entry of expired) executeDeletionRef.current(entry);
2476
+ }, 1e3);
2477
+ return () => clearInterval(timer2);
2478
+ }, [pendingDeletions.length > 0]);
2369
2479
  useEffect(() => {
2370
2480
  if (!onLoadHistory) return;
2371
2481
  const historyEntryToMsg = (entry) => {
@@ -2881,14 +2991,7 @@ function App({
2881
2991
  return;
2882
2992
  }
2883
2993
  if (!onDeleteTask) return;
2884
- addMessage(`Deleting "${t.title}"...`, tuiColors.amber);
2885
- onDeleteTask(t.id).then(
2886
- () => {
2887
- addMessage(`\u2713 Deleted "${t.title}"`, tuiColors.green);
2888
- refreshAll();
2889
- },
2890
- (err) => addMessage(`Failed: ${errMsg(err)}`, tuiColors.red)
2891
- );
2994
+ scheduleDeletion("task", t.id, t.title);
2892
2995
  } else {
2893
2996
  addMessage("Usage: /task add|list|show|cancel|retry|assign|approve|reject|delete", tuiColors.yellow);
2894
2997
  }
@@ -2964,14 +3067,7 @@ function App({
2964
3067
  addMessage("Agent deletion not available", tuiColors.yellow);
2965
3068
  return;
2966
3069
  }
2967
- addMessage(`Deleting agent "${a.name}"...`, tuiColors.amber);
2968
- onDeleteAgent(a.id).then(
2969
- () => {
2970
- addMessage(`\u2713 Deleted agent "${a.name}"`, tuiColors.green);
2971
- refreshAll();
2972
- },
2973
- (err) => addMessage(`Failed: ${errMsg(err)}`, tuiColors.red)
2974
- );
3070
+ scheduleDeletion("agent", a.id, a.name);
2975
3071
  } else if (sub === "autonomous" || sub === "auto") {
2976
3072
  const a = parts[2] ? sortedAgents.find((x) => x.id === parts[2] || x.name === parts[2]) : selectedAgent;
2977
3073
  if (!a) {
@@ -3400,6 +3496,10 @@ function App({
3400
3496
  setLogTypeFilter((prev) => new Set(cyclePreset(prev).types));
3401
3497
  return;
3402
3498
  }
3499
+ if ((input === "z" || input === "Z") && pendingDeletions.length > 0) {
3500
+ undoLastDeletion();
3501
+ return;
3502
+ }
3403
3503
  if ((input === "f" || input === "F") && (activeView === "tasks" || activeView === "agents" || activeView === "goals") && !detailOpen) {
3404
3504
  setActivityFilter((prev) => {
3405
3505
  const next = cyclePreset(prev);
@@ -3429,14 +3529,7 @@ function App({
3429
3529
  return;
3430
3530
  }
3431
3531
  if ((input === "d" || input === "D") && activeView === "goals" && selectedGoal && onDeleteGoal) {
3432
- addMessage(`Deleting goal "${selectedGoal.title}"...`, tuiColors.amber);
3433
- onDeleteGoal(selectedGoal.id).then(
3434
- () => {
3435
- addMessage(`\u2713 Deleted goal "${selectedGoal.title}"`, tuiColors.green);
3436
- refreshAll();
3437
- },
3438
- (err) => addMessage(`Failed: ${err instanceof Error ? err.message : String(err)}`, tuiColors.red)
3439
- );
3532
+ scheduleDeletion("goal", selectedGoal.id, selectedGoal.title);
3440
3533
  return;
3441
3534
  }
3442
3535
  if ((input === "c" || input === "C") && activeView === "goals" && selectedGoal && onUpdateGoalStatus) {
@@ -3546,43 +3639,16 @@ function App({
3546
3639
  return;
3547
3640
  }
3548
3641
  if ((input === "d" || input === "D") && activeView === "tasks" && selectedTask && selectedTask.status !== "in_progress" && onDeleteTask) {
3549
- addMessage(`Deleting "${selectedTask.title}"...`, tuiColors.amber);
3550
- onDeleteTask(selectedTask.id).then(
3551
- () => {
3552
- addMessage(`\u2713 Deleted "${selectedTask.title}"`, tuiColors.green);
3553
- refreshAll();
3554
- },
3555
- (err) => addMessage(`Failed: ${err instanceof Error ? err.message : String(err)}`, tuiColors.red)
3556
- );
3642
+ scheduleDeletion("task", selectedTask.id, selectedTask.title);
3557
3643
  return;
3558
3644
  }
3559
3645
  if ((input === "d" || input === "D") && activeView === "agents" && selectedAgent && onDeleteAgent) {
3560
3646
  const isActuallyRunning = Object.values(liveState.running).some((e) => e.agent_id === selectedAgent.id);
3561
- if (isActuallyRunning) {
3562
- if (onForceStopAgent) {
3563
- addMessage(`Stopping & deleting agent "${selectedAgent.name}"...`, tuiColors.amber);
3564
- onForceStopAgent(selectedAgent.id).then(
3565
- () => onDeleteAgent(selectedAgent.id)
3566
- ).then(
3567
- () => {
3568
- addMessage(`\u2713 Deleted agent "${selectedAgent.name}"`, tuiColors.green);
3569
- refreshAll();
3570
- },
3571
- (err) => addMessage(`Failed: ${err instanceof Error ? err.message : String(err)}`, tuiColors.red)
3572
- );
3573
- } else {
3574
- addMessage(`Cannot delete \u2014 agent "${selectedAgent.name}" is running. Press S to stop first.`, tuiColors.yellow);
3575
- }
3647
+ if (isActuallyRunning && !onForceStopAgent) {
3648
+ addMessage(`Cannot delete \u2014 agent "${selectedAgent.name}" is running. Press S to stop first.`, tuiColors.yellow);
3576
3649
  return;
3577
3650
  }
3578
- addMessage(`Deleting agent "${selectedAgent.name}"...`, tuiColors.amber);
3579
- onDeleteAgent(selectedAgent.id).then(
3580
- () => {
3581
- addMessage(`\u2713 Deleted agent "${selectedAgent.name}"`, tuiColors.green);
3582
- refreshAll();
3583
- },
3584
- (err) => addMessage(`Failed: ${err instanceof Error ? err.message : String(err)}`, tuiColors.red)
3585
- );
3651
+ scheduleDeletion("agent", selectedAgent.id, selectedAgent.name, { needsForceStop: isActuallyRunning });
3586
3652
  return;
3587
3653
  }
3588
3654
  if ((input === "u" || input === "U") && activeView === "agents" && selectedAgent && onToggleAutonomous) {
@@ -3767,6 +3833,7 @@ function App({
3767
3833
  const canForceStop = !inInput && activeView === "agents" && selectedAgent && (agentActuallyRunning || selectedAgent.status === "running") && !!onForceStopAgent;
3768
3834
  const canToggleAuto = !inInput && activeView === "agents" && !!selectedAgent && !!onToggleAutonomous;
3769
3835
  const canPause = !inInput && activeView === "goals" && !!selectedGoal && (selectedGoal.status === "active" || selectedGoal.status === "paused") && !!onUpdateGoalStatus;
3836
+ const canUndo = !inInput && pendingDeletions.length > 0;
3770
3837
  const showSuggestions = inputMode === "command" && suggestions.length > 0;
3771
3838
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", width: W, height: H, children: [
3772
3839
  /* @__PURE__ */ jsx(
@@ -3778,7 +3845,9 @@ function App({
3778
3845
  stats: headerStats,
3779
3846
  tokens: headerTokens,
3780
3847
  uptime,
3781
- width: W
3848
+ width: W,
3849
+ version,
3850
+ latestVersion
3782
3851
  }
3783
3852
  ),
3784
3853
  /* @__PURE__ */ jsx(Box, { height: 1 }),
@@ -3912,6 +3981,7 @@ function App({
3912
3981
  )
3913
3982
  ] }) : activeView === "goals" ? /* @__PURE__ */ jsx(OnboardingBox, { count: sortedGoals.length, config: ONBOARDING_GOALS, width: ruleW }) : activeView === "tasks" ? /* @__PURE__ */ jsx(OnboardingBox, { count: sortedTasks.length, config: ONBOARDING_TASKS, width: ruleW }) : activeView === "agents" ? /* @__PURE__ */ jsx(OnboardingBox, { count: sortedAgents.length, config: ONBOARDING_AGENTS, width: ruleW }) : null,
3914
3983
  /* @__PURE__ */ jsx(Box, { flexGrow: 1 }),
3984
+ pendingDeletions.length > 0 && /* @__PURE__ */ jsx(UndoBanner, { deletions: pendingDeletions, width: W }),
3915
3985
  /* @__PURE__ */ jsx(
3916
3986
  CommandBar,
3917
3987
  {
@@ -3925,6 +3995,7 @@ function App({
3925
3995
  canReject: !!canReject,
3926
3996
  canCancel: activeView === "tasks" && !!selectedTask && selectedTask.status === "in_progress" && !!onCancelTask,
3927
3997
  canDelete: !!canDelete,
3998
+ canUndo: !!canUndo,
3928
3999
  canEdit: !!canEdit,
3929
4000
  canForceStop: !!canForceStop,
3930
4001
  canToggleAuto: !!canToggleAuto,
@@ -3942,6 +4013,33 @@ function App({
3942
4013
  )
3943
4014
  ] });
3944
4015
  }
4016
+ var UndoBanner = React5.memo(function UndoBanner2({ deletions, width }) {
4017
+ const [, setTick] = useState(0);
4018
+ useEffect(() => {
4019
+ const t = setInterval(() => setTick((n) => n + 1), 1e3);
4020
+ return () => clearInterval(t);
4021
+ }, []);
4022
+ const now = Date.now();
4023
+ return /* @__PURE__ */ jsx(Box, { flexDirection: "column", width, children: deletions.map((d) => {
4024
+ const remaining = Math.max(0, Math.ceil((d.expiresAt - now) / 1e3));
4025
+ const barWidth = Math.max(0, width - 4);
4026
+ const label = d.entityType === "task" ? "Task" : d.entityType === "agent" ? "Agent" : "Goal";
4027
+ const nameMax = Math.max(10, barWidth - label.length - 30);
4028
+ const name = d.entityName.length > nameMax ? d.entityName.slice(0, nameMax - 1) + "\u2026" : d.entityName;
4029
+ return /* @__PURE__ */ jsx(Box, { paddingX: 2, children: /* @__PURE__ */ jsxs(Text, { color: tuiColors.yellow, children: [
4030
+ "\u2717 ",
4031
+ /* @__PURE__ */ jsx(Text, { bold: true, children: label }),
4032
+ ` "${name}" \u2014 `,
4033
+ /* @__PURE__ */ jsxs(Text, { color: tuiColors.amber, bold: true, children: [
4034
+ remaining,
4035
+ "s"
4036
+ ] }),
4037
+ /* @__PURE__ */ jsx(Text, { color: tuiColors.dim, children: " \u2502 " }),
4038
+ /* @__PURE__ */ jsx(Text, { color: tuiColors.gray, bold: true, children: "Z" }),
4039
+ /* @__PURE__ */ jsx(Text, { color: tuiColors.dim, children: " undo" })
4040
+ ] }) }, d.key);
4041
+ }) });
4042
+ });
3945
4043
  function SuggestionsPanel({ suggestions, selectedIndex, height, width }) {
3946
4044
  const maxVisible = height;
3947
4045
  let scrollStart = 0;
@@ -4861,4 +4959,4 @@ function formatEvent(event, addMsg, runIdToAgentId, runIdToTaskId) {
4861
4959
  }
4862
4960
  }
4863
4961
 
4864
- export { App };
4962
+ export { App, _resetPendingDeletionSeq };
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { NotInitializedError } from './chunk-O5AO5QIR.js';
2
+ import { NotInitializedError } from './chunk-3TGCIXJA.js';
3
3
  import { randomBytes } from 'crypto';
4
4
  import fs from 'fs/promises';
5
5
  import path2 from 'path';
@@ -72,5 +72,11 @@ var TeamNotFoundError = class extends OrchestryError {
72
72
  this.name = "TeamNotFoundError";
73
73
  }
74
74
  };
75
+ var WorkspaceError = class extends OrchestryError {
76
+ constructor(message, hint) {
77
+ super(message, 6, hint);
78
+ this.name = "WorkspaceError";
79
+ }
80
+ };
75
81
 
76
- export { AgentNotFoundError, GoalNotFoundError, InvalidArgumentsError, InvalidTransitionError, LockConflictError, NoAgentsError, NotInitializedError, OrchestryError, TaskAlreadyRunningError, TaskNotFoundError, TeamNotFoundError };
82
+ export { AgentNotFoundError, GoalNotFoundError, InvalidArgumentsError, InvalidTransitionError, LockConflictError, NoAgentsError, NotInitializedError, OrchestryError, TaskAlreadyRunningError, TaskNotFoundError, TeamNotFoundError, WorkspaceError };
@@ -8,6 +8,7 @@ var PACKAGE_NAME = "@oxgeneral/orch";
8
8
  var CACHE_DIR = path.join(os.homedir(), ".orchestry");
9
9
  var CACHE_FILE = path.join(CACHE_DIR, "update-check.json");
10
10
  var CHECK_INTERVAL_MS = 4 * 60 * 60 * 1e3;
11
+ var REVALIDATE_AFTER_MS = CHECK_INTERVAL_MS * 0.75;
11
12
  function compareSemver(a, b) {
12
13
  const pa = a.split(".").map(Number);
13
14
  const pb = b.split(".").map(Number);
@@ -35,7 +36,7 @@ async function writeCache(latest) {
35
36
  }
36
37
  function fetchLatestVersion() {
37
38
  return new Promise((resolve) => {
38
- execFile("npm", ["view", PACKAGE_NAME, "version", "--json"], { timeout: 5e3 }, (err, stdout) => {
39
+ const child = execFile("npm", ["view", PACKAGE_NAME, "version", "--json"], { timeout: 5e3 }, (err, stdout) => {
39
40
  if (err) return resolve(null);
40
41
  try {
41
42
  resolve(JSON.parse(stdout.trim()));
@@ -43,52 +44,37 @@ function fetchLatestVersion() {
43
44
  resolve(null);
44
45
  }
45
46
  });
47
+ child.unref();
46
48
  });
47
49
  }
48
- async function checkForUpdate(currentVersion) {
50
+ function buildUpdateInfo(current, latest) {
51
+ return { current, latest, updateAvailable: compareSemver(latest, current) > 0 };
52
+ }
53
+ async function checkForUpdateNow(currentVersion) {
54
+ const latest = await fetchLatestVersion();
55
+ if (!latest) return null;
56
+ await writeCache(latest).catch(() => {
57
+ });
58
+ return buildUpdateInfo(currentVersion, latest);
59
+ }
60
+ async function checkForUpdateSWR(currentVersion) {
49
61
  try {
50
62
  const cached = await readCache();
51
- if (cached) {
52
- return {
53
- current: currentVersion,
54
- latest: cached.latest,
55
- updateAvailable: compareSemver(cached.latest, currentVersion) > 0
56
- };
63
+ if (!cached) {
64
+ checkForUpdateNow(currentVersion).catch(() => {
65
+ });
66
+ return null;
57
67
  }
58
- fetchLatestVersion().then(async (latest) => {
59
- if (latest) await writeCache(latest).catch(() => {
68
+ const age = Date.now() - cached.checked_at;
69
+ if (age >= REVALIDATE_AFTER_MS) {
70
+ checkForUpdateNow(currentVersion).catch(() => {
60
71
  });
61
- }).catch(() => {
62
- });
63
- return null;
64
- } catch {
65
- return null;
66
- }
67
- }
68
- async function checkForUpdateCached(currentVersion) {
69
- try {
70
- const cached = await readCache();
71
- if (!cached) return null;
72
- return {
73
- current: currentVersion,
74
- latest: cached.latest,
75
- updateAvailable: compareSemver(cached.latest, currentVersion) > 0
76
- };
72
+ }
73
+ return buildUpdateInfo(currentVersion, cached.latest);
77
74
  } catch {
78
75
  return null;
79
76
  }
80
77
  }
81
- async function checkForUpdateNow(currentVersion) {
82
- const latest = await fetchLatestVersion();
83
- if (!latest) return null;
84
- await writeCache(latest).catch(() => {
85
- });
86
- return {
87
- current: currentVersion,
88
- latest,
89
- updateAvailable: compareSemver(latest, currentVersion) > 0
90
- };
91
- }
92
78
  function printUpdateNotification(info) {
93
79
  if (!info.updateAvailable) return;
94
80
  const msg = `
@@ -98,4 +84,4 @@ function printUpdateNotification(info) {
98
84
  process.stderr.write(msg);
99
85
  }
100
86
 
101
- export { checkForUpdate, checkForUpdateCached, checkForUpdateNow, printUpdateNotification };
87
+ export { checkForUpdateNow, checkForUpdateSWR, printUpdateNotification };
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env node
2
+ import { execFile } from 'child_process';
3
+ import { promisify } from 'util';
4
+ import fs from 'fs/promises';
5
+ import path from 'path';
6
+
7
+ var execFileAsync = promisify(execFile);
8
+ var DoctorService = class {
9
+ constructor(adapterRegistry, processManager, projectRoot) {
10
+ this.adapterRegistry = adapterRegistry;
11
+ this.processManager = processManager;
12
+ this.cwd = projectRoot ?? process.cwd();
13
+ }
14
+ cwd;
15
+ async runAll() {
16
+ const checks = [];
17
+ const adapters = this.adapterRegistry.list();
18
+ let adaptersReady = 0;
19
+ for (const adapter of adapters) {
20
+ const result = await adapter.test();
21
+ if (result.ok) {
22
+ adaptersReady++;
23
+ checks.push({
24
+ name: adapter.kind,
25
+ status: "ok",
26
+ detail: result.version
27
+ });
28
+ } else {
29
+ checks.push({
30
+ name: adapter.kind,
31
+ status: "fail",
32
+ detail: result.error
33
+ });
34
+ }
35
+ }
36
+ checks.push(await this.checkCommand("git", ["--version"], "git"));
37
+ checks.push(await this.checkGitRepo());
38
+ checks.push(await this.checkGitignore());
39
+ checks.push(await this.checkCommand("node", ["--version"], "node"));
40
+ return {
41
+ checks,
42
+ adaptersReady,
43
+ adaptersTotal: adapters.length
44
+ };
45
+ }
46
+ async checkCommand(command, args, name) {
47
+ try {
48
+ const { stdout } = await execFileAsync(command, args);
49
+ return { name, status: "ok", detail: stdout.trim() };
50
+ } catch {
51
+ return { name, status: "fail", detail: `${command}: command not found` };
52
+ }
53
+ }
54
+ async checkGitignore() {
55
+ const gitignorePath = path.join(this.cwd, ".gitignore");
56
+ try {
57
+ const content = await fs.readFile(gitignorePath, "utf-8");
58
+ const hasEntry = content.split("\n").some((line) => line.trim() === ".orchestry");
59
+ if (hasEntry) {
60
+ return { name: ".gitignore", status: "ok", detail: ".orchestry is excluded" };
61
+ }
62
+ return {
63
+ name: ".gitignore",
64
+ status: "fail",
65
+ detail: ".orchestry not in .gitignore \u2014 worktrees will copy state recursively. Run: orch init"
66
+ };
67
+ } catch {
68
+ return {
69
+ name: ".gitignore",
70
+ status: "fail",
71
+ detail: "no .gitignore found \u2014 .orchestry may be committed to git. Run: orch init"
72
+ };
73
+ }
74
+ }
75
+ async checkGitRepo() {
76
+ try {
77
+ await execFileAsync("git", ["rev-parse", "--is-inside-work-tree"], { cwd: this.cwd });
78
+ return { name: "git repo", status: "ok", detail: "git repository detected" };
79
+ } catch {
80
+ return {
81
+ name: "git repo",
82
+ status: "fail",
83
+ detail: "not a git repository \u2014 worktree/isolated modes will fail. Run: git init"
84
+ };
85
+ }
86
+ }
87
+ };
88
+
89
+ export { DoctorService };
@@ -1,4 +1,4 @@
1
- import {b as b$1}from'./chunk-ZU6AY2VU.js';import {randomBytes}from'crypto';import s from'fs/promises';import i from'path';import P from'js-yaml';import'fs';async function D(r,t){let n=i.dirname(r);await k(n);let e=i.join(n,`.${i.basename(r)}.${randomBytes(4).toString("hex")}.tmp`);try{await s.writeFile(e,t,"utf-8"),await s.rename(e,r);}catch(l){throw await s.unlink(e).catch(()=>{}),l}}async function L(r){try{let t=await s.readFile(r,"utf-8");return P.load(t)}catch(t){if(f(t))return null;throw t}}async function B(r,t){let n=P.dump(t,{indent:2,lineWidth:120,noRefs:true,sortKeys:false});await D(r,n);}async function M(r){try{let t=await s.readFile(r,"utf-8");return JSON.parse(t)}catch(t){if(f(t))return null;throw t}}async function W(r,t){let n=JSON.stringify(t,null,2)+`
1
+ import {b as b$1}from'./chunk-VAAOW526.js';import {randomBytes}from'crypto';import s from'fs/promises';import i from'path';import P from'js-yaml';import'fs';async function D(r,t){let n=i.dirname(r);await k(n);let e=i.join(n,`.${i.basename(r)}.${randomBytes(4).toString("hex")}.tmp`);try{await s.writeFile(e,t,"utf-8"),await s.rename(e,r);}catch(l){throw await s.unlink(e).catch(()=>{}),l}}async function L(r){try{let t=await s.readFile(r,"utf-8");return P.load(t)}catch(t){if(f(t))return null;throw t}}async function B(r,t){let n=P.dump(t,{indent:2,lineWidth:120,noRefs:true,sortKeys:false});await D(r,n);}async function M(r){try{let t=await s.readFile(r,"utf-8");return JSON.parse(t)}catch(t){if(f(t))return null;throw t}}async function W(r,t){let n=JSON.stringify(t,null,2)+`
2
2
  `;await D(r,n);}var x=4096;async function A(r,t){let n=i.dirname(r);await k(n);let e=JSON.stringify(t)+`
3
3
  `;if(Buffer.byteLength(e,"utf-8")>x&&t!==null&&typeof t=="object"){let a=t;if(typeof a.data=="string"&&a.data.length>0){let u=JSON.stringify({...a,data:""})+`
4
4
  `,h=Buffer.byteLength(u,"utf-8"),m=x-h-3;if(m>0){let g=a.data.slice(0,m);e=JSON.stringify({...a,data:g+"\u2026"})+`
@@ -7,5 +7,5 @@ import {b as b$1}from'./chunk-ZU6AY2VU.js';import {randomBytes}from'crypto';impo
7
7
  `).filter($=>$.trim().length>0);if(j.length>=t+1)return p(j.slice(-t));if(o===0)break;o=Math.max(0,o-l);}let h=u.split(`
8
8
  `).filter(g=>g.trim().length>0),m=a>0?h.slice(1):h;return p(m.slice(-t))}finally{await e.close();}}catch(n){if(f(n))return [];throw n}}async function E(r){let n=(await s.readFile(r,"utf-8")).split(`
9
9
  `).filter(e=>e.trim().length>0);return p(n)}function p(r){let t=[];for(let n of r){let e=n.trim();if(e)try{t.push(JSON.parse(e));}catch{process.stderr.write(`[readJsonl] skipping corrupt line: ${e.slice(0,200)}
10
- `);}}return t}async function k(r){await s.mkdir(r,{recursive:true});}async function v(r){try{return await s.access(r),!0}catch{return false}}async function Z(r,t){try{let n=await s.readdir(r);return t?n.filter(e=>e.endsWith(t)):n}catch(n){if(f(n))return [];throw n}}function f(r){return r instanceof Error&&"code"in r&&r.code==="ENOENT"}var N=".orchestry",R=/^[A-Za-z0-9._-]+$/,J=class{constructor(t){this.projectRoot=t;}get root(){return i.join(this.projectRoot,N)}get configPath(){return i.join(this.root,"config.yml")}get statePath(){return i.join(this.root,"state.json")}get lockPath(){return i.join(this.root,"orchestry.lock")}get tasksDir(){return i.join(this.root,"tasks")}get agentsDir(){return i.join(this.root,"agents")}get runsDir(){return i.join(this.root,"runs")}get templatesDir(){return i.join(this.root,"templates")}get logsDir(){return i.join(this.root,"logs")}get contextDir(){return i.join(this.root,"context")}contextPath(t){return i.join(this.contextDir,`${c(t)}.json`)}get messagesDir(){return i.join(this.root,"messages")}messagePath(t){return i.join(this.messagesDir,`${c(t)}.json`)}get goalsDir(){return i.join(this.root,"goals")}goalPath(t){return i.join(this.goalsDir,`${c(t)}.yml`)}get teamsDir(){return i.join(this.root,"teams")}teamPath(t){return i.join(this.teamsDir,`${c(t)}.yml`)}get gitignorePath(){return i.join(this.root,".gitignore")}get workspaceExcludePath(){return i.join(this.root,"workspace-exclude")}taskPath(t){return i.join(this.tasksDir,`${c(t)}.yml`)}agentPath(t){return i.join(this.agentsDir,`${c(t)}.yml`)}runPath(t){return i.join(this.runsDir,`${c(t)}.json`)}runEventsPath(t){return i.join(this.runsDir,`${c(t)}.jsonl`)}defaultTemplatePath(){return i.join(this.templatesDir,"default.md")}async isInitialized(){return v(this.root)}async requireInit(){if(!await this.isInitialized())throw new b$1}};function c(r){if(!R.test(r))throw new Error(`Invalid identifier: "${r}"`);return r}function G(r,t){let n=i.resolve(r),e=i.resolve(t);if(!n.startsWith(e+i.sep)&&n!==e)throw new Error(`Workspace path "${r}" is outside project root`)}export{L as a,B as b,M as c,W as d,A as e,Y as f,z as g,k as h,v as i,Z as j,J as k,c as l,G as m};//# sourceMappingURL=chunk-2B32FPEB.js.map
11
- //# sourceMappingURL=chunk-2B32FPEB.js.map
10
+ `);}}return t}async function k(r){await s.mkdir(r,{recursive:true});}async function v(r){try{return await s.access(r),!0}catch{return false}}async function Z(r,t){try{let n=await s.readdir(r);return t?n.filter(e=>e.endsWith(t)):n}catch(n){if(f(n))return [];throw n}}function f(r){return r instanceof Error&&"code"in r&&r.code==="ENOENT"}var N=".orchestry",R=/^[A-Za-z0-9._-]+$/,J=class{constructor(t){this.projectRoot=t;}get root(){return i.join(this.projectRoot,N)}get configPath(){return i.join(this.root,"config.yml")}get statePath(){return i.join(this.root,"state.json")}get lockPath(){return i.join(this.root,"orchestry.lock")}get tasksDir(){return i.join(this.root,"tasks")}get agentsDir(){return i.join(this.root,"agents")}get runsDir(){return i.join(this.root,"runs")}get templatesDir(){return i.join(this.root,"templates")}get logsDir(){return i.join(this.root,"logs")}get contextDir(){return i.join(this.root,"context")}contextPath(t){return i.join(this.contextDir,`${c(t)}.json`)}get messagesDir(){return i.join(this.root,"messages")}messagePath(t){return i.join(this.messagesDir,`${c(t)}.json`)}get goalsDir(){return i.join(this.root,"goals")}goalPath(t){return i.join(this.goalsDir,`${c(t)}.yml`)}get teamsDir(){return i.join(this.root,"teams")}teamPath(t){return i.join(this.teamsDir,`${c(t)}.yml`)}get gitignorePath(){return i.join(this.root,".gitignore")}get workspaceExcludePath(){return i.join(this.root,"workspace-exclude")}taskPath(t){return i.join(this.tasksDir,`${c(t)}.yml`)}agentPath(t){return i.join(this.agentsDir,`${c(t)}.yml`)}runPath(t){return i.join(this.runsDir,`${c(t)}.json`)}runEventsPath(t){return i.join(this.runsDir,`${c(t)}.jsonl`)}defaultTemplatePath(){return i.join(this.templatesDir,"default.md")}async isInitialized(){return v(this.root)}async requireInit(){if(!await this.isInitialized())throw new b$1}};function c(r){if(!R.test(r))throw new Error(`Invalid identifier: "${r}"`);return r}function G(r,t){let n=i.resolve(r),e=i.resolve(t);if(!n.startsWith(e+i.sep)&&n!==e)throw new Error(`Workspace path "${r}" is outside project root`)}export{L as a,B as b,M as c,W as d,A as e,Y as f,z as g,k as h,v as i,Z as j,J as k,c as l,G as m};//# sourceMappingURL=chunk-QTDKQYZI.js.map
11
+ //# sourceMappingURL=chunk-QTDKQYZI.js.map