@oxgeneral/orch 0.2.2 → 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 (46) hide show
  1. package/dist/{App-NHSVGERJ.js → App-KHUT3IV7.js} +316 -105
  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 +17 -20
  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-UCVRVBVI.js → init-EQTGQ4G2.js} +60 -52
  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-AAEAU4HT.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/readme.md +6 -15
  35. package/scripts/release.sh +32 -0
  36. package/dist/chunk-E3TCKHU6.js +0 -13
  37. package/dist/chunk-E3TCKHU6.js.map +0 -1
  38. package/dist/chunk-XI4TU6VU.js +0 -50
  39. package/dist/chunk-ZU6AY2VU.js.map +0 -1
  40. package/dist/doctor-service-A34DHPKI.js +0 -2
  41. package/dist/doctor-service-NTWBWOM2.js +0 -2
  42. package/dist/doctor-service-NTWBWOM2.js.map +0 -1
  43. package/dist/orchestrator-TAFBYQQ5.js +0 -2
  44. package/dist/update-check-4RV7Z6WT.js +0 -2
  45. package/dist/workspace-manager-7M46ESUL.js +0 -2
  46. package/dist/workspace-manager-7M46ESUL.js.map +0 -1
@@ -46,13 +46,18 @@ 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";
53
57
  var LOZENGE = "\u25C8";
54
58
  var STAR = "\u2605";
55
59
  var LOOP = "\u27F3";
60
+ var DIAMOND = "\u25C6";
56
61
  var TICK_INTERVAL = 120;
57
62
  var globalTick = 0;
58
63
  var timer = null;
@@ -579,7 +584,6 @@ var TABS = [
579
584
  { key: "A", id: "agents", label: "AGENTS" },
580
585
  { key: "L", id: "logs", label: "ACTIONS" }
581
586
  ];
582
- var DIAMOND = "\u25C6";
583
587
  var FILLED_CIRCLE = "\u25CF";
584
588
  var EMPTY_CIRCLE3 = "\u25CB";
585
589
  var CHECK4 = "\u2713";
@@ -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
  }
@@ -1503,6 +1546,121 @@ function FormWizard({ title, steps, onComplete, onCancel, width, height }) {
1503
1546
  ] }) })
1504
1547
  ] });
1505
1548
  }
1549
+ var TL = "\u256D";
1550
+ var TR = "\u256E";
1551
+ var BL = "\u2570";
1552
+ var BR = "\u256F";
1553
+ var V = "\u2502";
1554
+ function Row({ children, cw }) {
1555
+ return /* @__PURE__ */ jsxs(Text, { children: [
1556
+ /* @__PURE__ */ jsx(Text, { color: tuiColors.ghost, children: V }),
1557
+ /* @__PURE__ */ jsxs(Text, { children: [
1558
+ " ",
1559
+ children.padEnd(cw),
1560
+ " "
1561
+ ] }),
1562
+ /* @__PURE__ */ jsx(Text, { color: tuiColors.ghost, children: V })
1563
+ ] });
1564
+ }
1565
+ function EmptyRow({ cw }) {
1566
+ return /* @__PURE__ */ jsx(Row, { cw, children: "" });
1567
+ }
1568
+ function OnboardingBox({ count, config, width }) {
1569
+ if (count >= 3) return null;
1570
+ const boxW = Math.min((width ?? 44) - 4, 50);
1571
+ const cw = boxW - 6;
1572
+ const hLine = LIGHT_RULE.repeat(boxW - 2);
1573
+ const topBorder = /* @__PURE__ */ jsxs(Text, { color: tuiColors.ghost, children: [
1574
+ TL,
1575
+ hLine,
1576
+ TR
1577
+ ] });
1578
+ const botBorder = /* @__PURE__ */ jsxs(Text, { color: tuiColors.ghost, children: [
1579
+ BL,
1580
+ hLine,
1581
+ BR
1582
+ ] });
1583
+ if (count > 0) {
1584
+ const hint = config.hints[0];
1585
+ const hintSuffix = hint ? ` ${hint.key} ${hint.label}` : "";
1586
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 2, marginTop: 1, children: [
1587
+ topBorder,
1588
+ /* @__PURE__ */ jsxs(Text, { children: [
1589
+ /* @__PURE__ */ jsxs(Text, { color: tuiColors.ghost, children: [
1590
+ V,
1591
+ " "
1592
+ ] }),
1593
+ /* @__PURE__ */ jsx(Text, { color: tuiColors.amber, children: DIAMOND }),
1594
+ /* @__PURE__ */ jsxs(Text, { color: tuiColors.silver, children: [
1595
+ " ",
1596
+ config.nudge.padEnd(cw - 2 - hintSuffix.length)
1597
+ ] }),
1598
+ hint && /* @__PURE__ */ jsxs(Fragment, { children: [
1599
+ /* @__PURE__ */ jsxs(Text, { color: tuiColors.amber, children: [
1600
+ " ",
1601
+ hint.key
1602
+ ] }),
1603
+ /* @__PURE__ */ jsxs(Text, { color: tuiColors.gray, children: [
1604
+ " ",
1605
+ hint.label
1606
+ ] })
1607
+ ] }),
1608
+ /* @__PURE__ */ jsx(Text, { children: " " }),
1609
+ /* @__PURE__ */ jsx(Text, { color: tuiColors.ghost, children: V })
1610
+ ] }),
1611
+ botBorder
1612
+ ] });
1613
+ }
1614
+ const hintsLen = config.hints.reduce((acc, h, i) => acc + h.key.length + 1 + h.label.length + (i > 0 ? 3 : 0), 0);
1615
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 2, marginTop: 1, children: [
1616
+ topBorder,
1617
+ /* @__PURE__ */ jsx(EmptyRow, { cw }),
1618
+ /* @__PURE__ */ jsxs(Text, { children: [
1619
+ /* @__PURE__ */ jsxs(Text, { color: tuiColors.ghost, children: [
1620
+ V,
1621
+ " "
1622
+ ] }),
1623
+ /* @__PURE__ */ jsx(Text, { color: tuiColors.amber, children: DIAMOND }),
1624
+ /* @__PURE__ */ jsxs(Text, { color: tuiColors.white, bold: true, children: [
1625
+ " ",
1626
+ config.title
1627
+ ] }),
1628
+ /* @__PURE__ */ jsx(Text, { children: " ".repeat(Math.max(0, cw - config.title.length - 2)) }),
1629
+ /* @__PURE__ */ jsx(Text, { children: " " }),
1630
+ /* @__PURE__ */ jsx(Text, { color: tuiColors.ghost, children: V })
1631
+ ] }),
1632
+ /* @__PURE__ */ jsx(EmptyRow, { cw }),
1633
+ config.description.map((line, i) => /* @__PURE__ */ jsxs(Text, { children: [
1634
+ /* @__PURE__ */ jsxs(Text, { color: tuiColors.ghost, children: [
1635
+ V,
1636
+ " "
1637
+ ] }),
1638
+ /* @__PURE__ */ jsx(Text, { color: tuiColors.silver, children: line.padEnd(cw) }),
1639
+ /* @__PURE__ */ jsx(Text, { children: " " }),
1640
+ /* @__PURE__ */ jsx(Text, { color: tuiColors.ghost, children: V })
1641
+ ] }, i)),
1642
+ /* @__PURE__ */ jsx(EmptyRow, { cw }),
1643
+ /* @__PURE__ */ jsxs(Text, { children: [
1644
+ /* @__PURE__ */ jsxs(Text, { color: tuiColors.ghost, children: [
1645
+ V,
1646
+ " "
1647
+ ] }),
1648
+ config.hints.map((h, i) => /* @__PURE__ */ jsxs(React5.Fragment, { children: [
1649
+ i > 0 && /* @__PURE__ */ jsx(Text, { color: tuiColors.ghost, children: " " }),
1650
+ /* @__PURE__ */ jsx(Text, { color: tuiColors.amber, children: h.key }),
1651
+ /* @__PURE__ */ jsxs(Text, { color: tuiColors.gray, children: [
1652
+ " ",
1653
+ h.label
1654
+ ] })
1655
+ ] }, i)),
1656
+ /* @__PURE__ */ jsx(Text, { children: " ".repeat(Math.max(0, cw - hintsLen)) }),
1657
+ /* @__PURE__ */ jsx(Text, { children: " " }),
1658
+ /* @__PURE__ */ jsx(Text, { color: tuiColors.ghost, children: V })
1659
+ ] }),
1660
+ /* @__PURE__ */ jsx(EmptyRow, { cw }),
1661
+ botBorder
1662
+ ] });
1663
+ }
1506
1664
 
1507
1665
  // src/tui/wizardConfigs.ts
1508
1666
  var CLAUDE_MODELS = [
@@ -1931,6 +2089,41 @@ var MAX_RUN_MAP_SIZE = 500;
1931
2089
  var MAX_DETAIL_LEN = 2048;
1932
2090
  var MAX_MESSAGES = 200;
1933
2091
  var RUNNABLE = /* @__PURE__ */ new Set(["todo", "failed", "cancelled"]);
2092
+ var ONBOARDING_GOALS = {
2093
+ title: "Goals",
2094
+ description: [
2095
+ "Define what your team should achieve.",
2096
+ "The orchestrator breaks goals into tasks",
2097
+ "and assigns them to agents automatically."
2098
+ ],
2099
+ hints: [{ key: "N", label: "new goal" }, { key: "/", label: "commands" }],
2100
+ nudge: "Add more goals to keep your team focused."
2101
+ };
2102
+ var ONBOARDING_TASKS = {
2103
+ title: "Tasks",
2104
+ description: [
2105
+ "Units of work dispatched to agents.",
2106
+ "Create them manually or let goals",
2107
+ "generate them automatically."
2108
+ ],
2109
+ hints: [{ key: "N", label: "new task" }, { key: "W", label: "start orchestrator" }],
2110
+ nudge: "Add more tasks to keep agents busy."
2111
+ };
2112
+ var ONBOARDING_AGENTS = {
2113
+ title: "Agents",
2114
+ description: [
2115
+ "AI workers that execute your tasks.",
2116
+ "Each agent uses an adapter (claude, codex,",
2117
+ "cursor, shell) and has its own role."
2118
+ ],
2119
+ hints: [{ key: "N", label: "new agent" }, { key: "W", label: "start orchestrator" }],
2120
+ nudge: "Add more agents to increase parallelism."
2121
+ };
2122
+ var UNDO_TIMEOUT_MS = 5e3;
2123
+ var pendingDeletionSeq = 0;
2124
+ function _resetPendingDeletionSeq() {
2125
+ pendingDeletionSeq = 0;
2126
+ }
1934
2127
  var LIFECYCLE_TAG_RE = /^\[[\w_]+\]$/;
1935
2128
  function classifyAgentSummary(summary) {
1936
2129
  if (LIFECYCLE_TAG_RE.test(summary)) return { msgType: "lifecycle", color: tuiColors.dim };
@@ -2040,7 +2233,9 @@ function App({
2040
2233
  initialActivityFilter = "all",
2041
2234
  onSaveActivityFilter,
2042
2235
  initialMaxConcurrent = DEFAULT_CONFIG.scheduling.max_concurrent_agents,
2043
- onSaveMaxConcurrent
2236
+ onSaveMaxConcurrent,
2237
+ version,
2238
+ latestVersion
2044
2239
  }) {
2045
2240
  const { exit } = useApp();
2046
2241
  const { stdout } = useStdout();
@@ -2093,6 +2288,7 @@ function App({
2093
2288
  const [goalScrollOffset, setGoalScrollOffset] = useState(0);
2094
2289
  const [suggestionIndex, setSuggestionIndex] = useState(0);
2095
2290
  const [liveTeams, setLiveTeams] = useState([]);
2291
+ const [pendingDeletions, setPendingDeletions] = useState([]);
2096
2292
  const liveTeamsRef = useRef(liveTeams);
2097
2293
  liveTeamsRef.current = liveTeams;
2098
2294
  const refreshAll = useCallback(async (opts) => {
@@ -2221,6 +2417,65 @@ function App({
2221
2417
  addMessage(`Watch mode failed: ${watchError}. Tasks will not auto-dispatch.`, tuiColors.red);
2222
2418
  }
2223
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]);
2224
2479
  useEffect(() => {
2225
2480
  if (!onLoadHistory) return;
2226
2481
  const historyEntryToMsg = (entry) => {
@@ -2736,14 +2991,7 @@ function App({
2736
2991
  return;
2737
2992
  }
2738
2993
  if (!onDeleteTask) return;
2739
- addMessage(`Deleting "${t.title}"...`, tuiColors.amber);
2740
- onDeleteTask(t.id).then(
2741
- () => {
2742
- addMessage(`\u2713 Deleted "${t.title}"`, tuiColors.green);
2743
- refreshAll();
2744
- },
2745
- (err) => addMessage(`Failed: ${errMsg(err)}`, tuiColors.red)
2746
- );
2994
+ scheduleDeletion("task", t.id, t.title);
2747
2995
  } else {
2748
2996
  addMessage("Usage: /task add|list|show|cancel|retry|assign|approve|reject|delete", tuiColors.yellow);
2749
2997
  }
@@ -2819,14 +3067,7 @@ function App({
2819
3067
  addMessage("Agent deletion not available", tuiColors.yellow);
2820
3068
  return;
2821
3069
  }
2822
- addMessage(`Deleting agent "${a.name}"...`, tuiColors.amber);
2823
- onDeleteAgent(a.id).then(
2824
- () => {
2825
- addMessage(`\u2713 Deleted agent "${a.name}"`, tuiColors.green);
2826
- refreshAll();
2827
- },
2828
- (err) => addMessage(`Failed: ${errMsg(err)}`, tuiColors.red)
2829
- );
3070
+ scheduleDeletion("agent", a.id, a.name);
2830
3071
  } else if (sub === "autonomous" || sub === "auto") {
2831
3072
  const a = parts[2] ? sortedAgents.find((x) => x.id === parts[2] || x.name === parts[2]) : selectedAgent;
2832
3073
  if (!a) {
@@ -3255,6 +3496,10 @@ function App({
3255
3496
  setLogTypeFilter((prev) => new Set(cyclePreset(prev).types));
3256
3497
  return;
3257
3498
  }
3499
+ if ((input === "z" || input === "Z") && pendingDeletions.length > 0) {
3500
+ undoLastDeletion();
3501
+ return;
3502
+ }
3258
3503
  if ((input === "f" || input === "F") && (activeView === "tasks" || activeView === "agents" || activeView === "goals") && !detailOpen) {
3259
3504
  setActivityFilter((prev) => {
3260
3505
  const next = cyclePreset(prev);
@@ -3284,14 +3529,7 @@ function App({
3284
3529
  return;
3285
3530
  }
3286
3531
  if ((input === "d" || input === "D") && activeView === "goals" && selectedGoal && onDeleteGoal) {
3287
- addMessage(`Deleting goal "${selectedGoal.title}"...`, tuiColors.amber);
3288
- onDeleteGoal(selectedGoal.id).then(
3289
- () => {
3290
- addMessage(`\u2713 Deleted goal "${selectedGoal.title}"`, tuiColors.green);
3291
- refreshAll();
3292
- },
3293
- (err) => addMessage(`Failed: ${err instanceof Error ? err.message : String(err)}`, tuiColors.red)
3294
- );
3532
+ scheduleDeletion("goal", selectedGoal.id, selectedGoal.title);
3295
3533
  return;
3296
3534
  }
3297
3535
  if ((input === "c" || input === "C") && activeView === "goals" && selectedGoal && onUpdateGoalStatus) {
@@ -3401,43 +3639,16 @@ function App({
3401
3639
  return;
3402
3640
  }
3403
3641
  if ((input === "d" || input === "D") && activeView === "tasks" && selectedTask && selectedTask.status !== "in_progress" && onDeleteTask) {
3404
- addMessage(`Deleting "${selectedTask.title}"...`, tuiColors.amber);
3405
- onDeleteTask(selectedTask.id).then(
3406
- () => {
3407
- addMessage(`\u2713 Deleted "${selectedTask.title}"`, tuiColors.green);
3408
- refreshAll();
3409
- },
3410
- (err) => addMessage(`Failed: ${err instanceof Error ? err.message : String(err)}`, tuiColors.red)
3411
- );
3642
+ scheduleDeletion("task", selectedTask.id, selectedTask.title);
3412
3643
  return;
3413
3644
  }
3414
3645
  if ((input === "d" || input === "D") && activeView === "agents" && selectedAgent && onDeleteAgent) {
3415
3646
  const isActuallyRunning = Object.values(liveState.running).some((e) => e.agent_id === selectedAgent.id);
3416
- if (isActuallyRunning) {
3417
- if (onForceStopAgent) {
3418
- addMessage(`Stopping & deleting agent "${selectedAgent.name}"...`, tuiColors.amber);
3419
- onForceStopAgent(selectedAgent.id).then(
3420
- () => onDeleteAgent(selectedAgent.id)
3421
- ).then(
3422
- () => {
3423
- addMessage(`\u2713 Deleted agent "${selectedAgent.name}"`, tuiColors.green);
3424
- refreshAll();
3425
- },
3426
- (err) => addMessage(`Failed: ${err instanceof Error ? err.message : String(err)}`, tuiColors.red)
3427
- );
3428
- } else {
3429
- addMessage(`Cannot delete \u2014 agent "${selectedAgent.name}" is running. Press S to stop first.`, tuiColors.yellow);
3430
- }
3647
+ if (isActuallyRunning && !onForceStopAgent) {
3648
+ addMessage(`Cannot delete \u2014 agent "${selectedAgent.name}" is running. Press S to stop first.`, tuiColors.yellow);
3431
3649
  return;
3432
3650
  }
3433
- addMessage(`Deleting agent "${selectedAgent.name}"...`, tuiColors.amber);
3434
- onDeleteAgent(selectedAgent.id).then(
3435
- () => {
3436
- addMessage(`\u2713 Deleted agent "${selectedAgent.name}"`, tuiColors.green);
3437
- refreshAll();
3438
- },
3439
- (err) => addMessage(`Failed: ${err instanceof Error ? err.message : String(err)}`, tuiColors.red)
3440
- );
3651
+ scheduleDeletion("agent", selectedAgent.id, selectedAgent.name, { needsForceStop: isActuallyRunning });
3441
3652
  return;
3442
3653
  }
3443
3654
  if ((input === "u" || input === "U") && activeView === "agents" && selectedAgent && onToggleAutonomous) {
@@ -3622,6 +3833,7 @@ function App({
3622
3833
  const canForceStop = !inInput && activeView === "agents" && selectedAgent && (agentActuallyRunning || selectedAgent.status === "running") && !!onForceStopAgent;
3623
3834
  const canToggleAuto = !inInput && activeView === "agents" && !!selectedAgent && !!onToggleAutonomous;
3624
3835
  const canPause = !inInput && activeView === "goals" && !!selectedGoal && (selectedGoal.status === "active" || selectedGoal.status === "paused") && !!onUpdateGoalStatus;
3836
+ const canUndo = !inInput && pendingDeletions.length > 0;
3625
3837
  const showSuggestions = inputMode === "command" && suggestions.length > 0;
3626
3838
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", width: W, height: H, children: [
3627
3839
  /* @__PURE__ */ jsx(
@@ -3633,7 +3845,9 @@ function App({
3633
3845
  stats: headerStats,
3634
3846
  tokens: headerTokens,
3635
3847
  uptime,
3636
- width: W
3848
+ width: W,
3849
+ version,
3850
+ latestVersion
3637
3851
  }
3638
3852
  ),
3639
3853
  /* @__PURE__ */ jsx(Box, { height: 1 }),
@@ -3765,8 +3979,9 @@ function App({
3765
3979
  agentNameMap
3766
3980
  }
3767
3981
  )
3768
- ] }) : null,
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,
3769
3983
  /* @__PURE__ */ jsx(Box, { flexGrow: 1 }),
3984
+ pendingDeletions.length > 0 && /* @__PURE__ */ jsx(UndoBanner, { deletions: pendingDeletions, width: W }),
3770
3985
  /* @__PURE__ */ jsx(
3771
3986
  CommandBar,
3772
3987
  {
@@ -3780,6 +3995,7 @@ function App({
3780
3995
  canReject: !!canReject,
3781
3996
  canCancel: activeView === "tasks" && !!selectedTask && selectedTask.status === "in_progress" && !!onCancelTask,
3782
3997
  canDelete: !!canDelete,
3998
+ canUndo: !!canUndo,
3783
3999
  canEdit: !!canEdit,
3784
4000
  canForceStop: !!canForceStop,
3785
4001
  canToggleAuto: !!canToggleAuto,
@@ -3797,6 +4013,33 @@ function App({
3797
4013
  )
3798
4014
  ] });
3799
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
+ });
3800
4043
  function SuggestionsPanel({ suggestions, selectedIndex, height, width }) {
3801
4044
  const maxVisible = height;
3802
4045
  let scrollStart = 0;
@@ -3823,19 +4066,8 @@ function SuggestionsPanel({ suggestions, selectedIndex, height, width }) {
3823
4066
  }
3824
4067
  function GoalsContent({ goals, selectedIndex, scrollOffset = 0, height, width, showAddRow, agentNameMap }) {
3825
4068
  const addRowIndex = goals.length;
3826
- const totalItems = goals.length + (showAddRow ? 1 : 0);
3827
4069
  const visible = goals.slice(scrollOffset, scrollOffset + height);
3828
4070
  const addRowVisible = showAddRow && addRowIndex >= scrollOffset && addRowIndex < scrollOffset + height;
3829
- if (totalItems === 0 || goals.length === 0 && !showAddRow) {
3830
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 2, children: [
3831
- /* @__PURE__ */ jsx(Text, { children: " " }),
3832
- /* @__PURE__ */ jsxs(Text, { color: tuiColors.dim, children: [
3833
- " No goals yet. Press ",
3834
- /* @__PURE__ */ jsx(Text, { color: tuiColors.gray, bold: true, children: "N" }),
3835
- " to create one."
3836
- ] })
3837
- ] });
3838
- }
3839
4071
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", height, children: [
3840
4072
  visible.map((goal, i) => /* @__PURE__ */ jsx(Box, { paddingX: 2, children: /* @__PURE__ */ jsx(GoalRow, { goal, selected: i + scrollOffset === selectedIndex, width: width - 2, agentNameMap }) }, goal.id)),
3841
4073
  addRowVisible && /* @__PURE__ */ jsx(Box, { paddingX: 2, children: /* @__PURE__ */ jsxs(Text, { color: selectedIndex === addRowIndex ? tuiColors.amber : tuiColors.ghost, children: [
@@ -3872,20 +4104,9 @@ function TasksContent({ tasks, selectedIndex, scrollOffset = 0, height, width, s
3872
4104
  const hasShowAll = hiddenCount > 0;
3873
4105
  const showAllIndex = hasShowAll ? tasks.length : -1;
3874
4106
  const addRowIndex = tasks.length + (hasShowAll ? 1 : 0);
3875
- const totalItems = tasks.length + (hasShowAll ? 1 : 0) + (showAddRow ? 1 : 0);
3876
4107
  const visible = tasks.slice(scrollOffset, scrollOffset + height);
3877
4108
  const showAllVisible = hasShowAll && showAllIndex >= scrollOffset && showAllIndex < scrollOffset + height;
3878
4109
  const addRowVisible = showAddRow && addRowIndex >= scrollOffset && addRowIndex < scrollOffset + height;
3879
- if (totalItems === 0 || tasks.length === 0 && !showAddRow) {
3880
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 2, children: [
3881
- /* @__PURE__ */ jsx(Text, { children: " " }),
3882
- /* @__PURE__ */ jsxs(Text, { color: tuiColors.dim, children: [
3883
- " No tasks yet. Press ",
3884
- /* @__PURE__ */ jsx(Text, { color: tuiColors.gray, bold: true, children: "Enter" }),
3885
- " to create one."
3886
- ] })
3887
- ] });
3888
- }
3889
4110
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", height, children: [
3890
4111
  visible.map((task, i) => /* @__PURE__ */ jsx(Box, { paddingX: 2, children: /* @__PURE__ */ jsx(TaskRow, { task, selected: i + scrollOffset === selectedIndex, width: width - 2, agentNameMap }) }, task.id)),
3891
4112
  showAllVisible && /* @__PURE__ */ jsx(Box, { paddingX: 2, children: /* @__PURE__ */ jsxs(Text, { color: selectedIndex === showAllIndex ? tuiColors.amber : tuiColors.ghost, children: [
@@ -3919,16 +4140,6 @@ function AgentsContent({ agents, selectedIndex, scrollOffset = 0, height, width,
3919
4140
  const addRowIndex = agents.length;
3920
4141
  const visible = agents.slice(scrollOffset, scrollOffset + height);
3921
4142
  const addRowVisible = showAddRow && addRowIndex >= scrollOffset && addRowIndex < scrollOffset + height;
3922
- if (agents.length === 0 && !showAddRow) {
3923
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 2, children: [
3924
- /* @__PURE__ */ jsx(Text, { children: " " }),
3925
- /* @__PURE__ */ jsxs(Text, { color: tuiColors.dim, children: [
3926
- " No agents yet. Press ",
3927
- /* @__PURE__ */ jsx(Text, { color: tuiColors.gray, bold: true, children: "Enter" }),
3928
- " to create one."
3929
- ] })
3930
- ] });
3931
- }
3932
4143
  const hasTeams = activeTeamCount != null && activeTeamCount > 0;
3933
4144
  const teamLeadNameMap = /* @__PURE__ */ new Map();
3934
4145
  if (hasTeams && teamLeadSet && agentTeamMap) {
@@ -4748,4 +4959,4 @@ function formatEvent(event, addMsg, runIdToAgentId, runIdToTaskId) {
4748
4959
  }
4749
4960
  }
4750
4961
 
4751
- 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 };