@wrongstack/webui 0.270.0 → 0.272.1
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/assets/index-CTDuGGlX.css +2 -0
- package/dist/assets/index-DSfCNNx4.js +122 -0
- package/dist/assets/{vendor-BL9KT5LK.js → vendor-cIhL9uWi.js} +254 -254
- package/dist/index.html +3 -3
- package/dist/index.js +1279 -188
- package/dist/index.js.map +1 -1
- package/dist/server/entry.js +2648 -1532
- package/dist/server/entry.js.map +1 -1
- package/dist/server/handlers.d.ts +7 -1
- package/dist/server/handlers.js +66 -1
- package/dist/server/handlers.js.map +1 -1
- package/dist/server/index.d.ts +74 -3
- package/dist/server/index.js +2652 -1533
- package/dist/server/index.js.map +1 -1
- package/dist/types.d.ts +315 -5
- package/package.json +15 -7
- package/dist/assets/index-BXhn7A6t.js +0 -121
- package/dist/assets/index-BwJjYOM3.css +0 -2
package/dist/index.js
CHANGED
|
@@ -607,6 +607,9 @@ var WrongStackWebSocketClient = class {
|
|
|
607
607
|
listFiles(query, limit, path) {
|
|
608
608
|
this.send({ type: "files.list", payload: { query, limit, path } });
|
|
609
609
|
}
|
|
610
|
+
requestCompletion(payload) {
|
|
611
|
+
this.send({ type: "completion.request", payload });
|
|
612
|
+
}
|
|
610
613
|
getTodos() {
|
|
611
614
|
this.send({ type: "todos.get" });
|
|
612
615
|
}
|
|
@@ -879,16 +882,7 @@ var useConfigStore = create2()(
|
|
|
879
882
|
(set) => ({
|
|
880
883
|
provider: "anthropic",
|
|
881
884
|
model: "claude-sonnet-4-20250514",
|
|
882
|
-
wsUrl: (
|
|
883
|
-
if (typeof window === "undefined" || !window.location?.hostname) {
|
|
884
|
-
return "ws://127.0.0.1:3457";
|
|
885
|
-
}
|
|
886
|
-
const h = window.location.hostname.toLowerCase();
|
|
887
|
-
if (h === "localhost" || h === "127.0.0.1" || h === "[::1]" || h === "::1") {
|
|
888
|
-
return "ws://127.0.0.1:3457";
|
|
889
|
-
}
|
|
890
|
-
return `ws://${window.location.hostname}:3457`;
|
|
891
|
-
})(),
|
|
885
|
+
wsUrl: defaultWsUrl(),
|
|
892
886
|
wsConnected: false,
|
|
893
887
|
wsStatus: { state: "connecting" },
|
|
894
888
|
theme: "system",
|
|
@@ -903,7 +897,23 @@ var useConfigStore = create2()(
|
|
|
903
897
|
setSoundOnComplete: (on) => set({ soundOnComplete: on })
|
|
904
898
|
}),
|
|
905
899
|
{
|
|
906
|
-
name: "wrongstack-config"
|
|
900
|
+
name: "wrongstack-config",
|
|
901
|
+
partialize: (state) => ({
|
|
902
|
+
provider: state.provider,
|
|
903
|
+
model: state.model,
|
|
904
|
+
baseUrl: state.baseUrl,
|
|
905
|
+
apiKey: state.apiKey,
|
|
906
|
+
theme: state.theme,
|
|
907
|
+
autoConnect: state.autoConnect,
|
|
908
|
+
soundOnComplete: state.soundOnComplete
|
|
909
|
+
}),
|
|
910
|
+
merge: (persisted, current) => ({
|
|
911
|
+
...current,
|
|
912
|
+
...persisted,
|
|
913
|
+
wsUrl: defaultWsUrl(),
|
|
914
|
+
wsConnected: false,
|
|
915
|
+
wsStatus: { state: "connecting" }
|
|
916
|
+
})
|
|
907
917
|
}
|
|
908
918
|
)
|
|
909
919
|
);
|
|
@@ -973,6 +983,10 @@ var useSessionStore = create3()(
|
|
|
973
983
|
cacheReadCost: env.cacheReadCost ?? state.cacheReadCost
|
|
974
984
|
})),
|
|
975
985
|
setIteration: (iteration) => set({ iteration }),
|
|
986
|
+
setContextUsage: (tokens, maxContext) => set((state) => ({
|
|
987
|
+
lastInputTokens: tokens,
|
|
988
|
+
maxContext: maxContext ?? state.maxContext
|
|
989
|
+
})),
|
|
976
990
|
setModes: (modes) => set({ modes }),
|
|
977
991
|
setContextModes: (contextModes) => set({ contextModes }),
|
|
978
992
|
setTodos: (todos) => set({ todos })
|
|
@@ -1023,7 +1037,9 @@ var useUIStore = create4()(
|
|
|
1023
1037
|
refineEnabled: true,
|
|
1024
1038
|
refinePanel: null,
|
|
1025
1039
|
dockSection: null,
|
|
1040
|
+
workDashboardTab: "todos",
|
|
1026
1041
|
hiddenChips: [],
|
|
1042
|
+
dockCustomizeOpen: false,
|
|
1027
1043
|
fleetMonitorOpen: false,
|
|
1028
1044
|
agentsMonitorOpen: false,
|
|
1029
1045
|
inspectorOpen: false,
|
|
@@ -1085,6 +1101,7 @@ var useUIStore = create4()(
|
|
|
1085
1101
|
toggleRefineEnabled: () => set((s) => ({ refineEnabled: !s.refineEnabled })),
|
|
1086
1102
|
setRefinePanel: (panel) => set({ refinePanel: panel }),
|
|
1087
1103
|
setDockSection: (section) => set({ dockSection: section }),
|
|
1104
|
+
setWorkDashboardTab: (tab) => set({ workDashboardTab: tab }),
|
|
1088
1105
|
toggleDockSection: (section) => set((s) => ({ dockSection: s.dockSection === section ? null : section })),
|
|
1089
1106
|
toggleChipHidden: (section) => set((s) => {
|
|
1090
1107
|
const hidden = s.hiddenChips.includes(section);
|
|
@@ -1094,6 +1111,7 @@ var useUIStore = create4()(
|
|
|
1094
1111
|
dockSection: !hidden && s.dockSection === section ? null : s.dockSection
|
|
1095
1112
|
};
|
|
1096
1113
|
}),
|
|
1114
|
+
setDockCustomizeOpen: (open) => set({ dockCustomizeOpen: open }),
|
|
1097
1115
|
setFleetMonitorOpen: (open) => set({ fleetMonitorOpen: open }),
|
|
1098
1116
|
setAgentsMonitorOpen: (open) => set({ agentsMonitorOpen: open }),
|
|
1099
1117
|
setInspectorOpen: (open) => set({ inspectorOpen: open }),
|
|
@@ -1141,6 +1159,7 @@ var useUIStore = create4()(
|
|
|
1141
1159
|
fileExplorerWidth: s.fileExplorerWidth,
|
|
1142
1160
|
refineEnabled: s.refineEnabled,
|
|
1143
1161
|
hiddenChips: s.hiddenChips,
|
|
1162
|
+
workDashboardTab: s.workDashboardTab,
|
|
1144
1163
|
inspectorOpen: s.inspectorOpen,
|
|
1145
1164
|
inspectorTab: s.inspectorTab,
|
|
1146
1165
|
skillsState: s.skillsState
|
|
@@ -1422,13 +1441,21 @@ var useFleetStore = create10()((set, get) => ({
|
|
|
1422
1441
|
fleetConcurrency: 0,
|
|
1423
1442
|
fleetConcurrencyMax: 4,
|
|
1424
1443
|
eventTimeline: [],
|
|
1444
|
+
agentTimeline: [],
|
|
1445
|
+
pushAgentTimelineEntry: (entry) => set((state) => ({
|
|
1446
|
+
agentTimeline: [
|
|
1447
|
+
{ id: `agent_tl_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`, ...entry },
|
|
1448
|
+
...state.agentTimeline
|
|
1449
|
+
].slice(0, 200)
|
|
1450
|
+
})),
|
|
1425
1451
|
clear: () => set({
|
|
1426
1452
|
agents: /* @__PURE__ */ new Map(),
|
|
1427
1453
|
leaderId: void 0,
|
|
1428
1454
|
fleetTokensIn: 0,
|
|
1429
1455
|
fleetTokensOut: 0,
|
|
1430
1456
|
fleetConcurrency: 0,
|
|
1431
|
-
eventTimeline: []
|
|
1457
|
+
eventTimeline: [],
|
|
1458
|
+
agentTimeline: []
|
|
1432
1459
|
}),
|
|
1433
1460
|
getAgentsBySession: (sessionId) => {
|
|
1434
1461
|
const result = [];
|
|
@@ -1544,6 +1571,22 @@ var useFleetStore = create10()((set, get) => ({
|
|
|
1544
1571
|
value: e.costUsd
|
|
1545
1572
|
});
|
|
1546
1573
|
break;
|
|
1574
|
+
case "budget_warning": {
|
|
1575
|
+
const kind = e.budgetKind ?? "budget";
|
|
1576
|
+
const used = typeof e.used === "number" ? e.used : 0;
|
|
1577
|
+
const limit = typeof e.limit === "number" ? e.limit : 0;
|
|
1578
|
+
next.budgetWarning = { kind, used, limit };
|
|
1579
|
+
timeline = pushTimeline(timeline, {
|
|
1580
|
+
id: makeTimelineId(),
|
|
1581
|
+
kind: "budget_warning",
|
|
1582
|
+
agentId: e.subagentId,
|
|
1583
|
+
agentName: next.name,
|
|
1584
|
+
timestamp: now,
|
|
1585
|
+
message: `${next.name} hit ${kind} budget ${used}/${limit}`,
|
|
1586
|
+
value: used
|
|
1587
|
+
});
|
|
1588
|
+
break;
|
|
1589
|
+
}
|
|
1547
1590
|
case "budget_extended":
|
|
1548
1591
|
next.extensions = e.totalExtensions ?? next.extensions + 1;
|
|
1549
1592
|
next.budgetWarning = void 0;
|
|
@@ -1644,6 +1687,18 @@ var useGoalStore = create11()((set) => ({
|
|
|
1644
1687
|
goal: null,
|
|
1645
1688
|
setGoal: (raw) => set({ goal: parseGoalState(raw) }),
|
|
1646
1689
|
clear: () => set({ goal: null }),
|
|
1690
|
+
appendJournalEntry: (entry) => set((state) => {
|
|
1691
|
+
if (!state.goal) return state;
|
|
1692
|
+
return {
|
|
1693
|
+
goal: {
|
|
1694
|
+
...state.goal,
|
|
1695
|
+
iterations: Math.max(state.goal.iterations, entry.iteration),
|
|
1696
|
+
lastTask: entry.task ?? state.goal.lastTask,
|
|
1697
|
+
lastStatus: entry.status ?? state.goal.lastStatus,
|
|
1698
|
+
journal: [entry, ...state.goal.journal ?? []].slice(0, 200)
|
|
1699
|
+
}
|
|
1700
|
+
};
|
|
1701
|
+
}),
|
|
1647
1702
|
refresh: () => {
|
|
1648
1703
|
try {
|
|
1649
1704
|
getWSClient()?.send?.({ type: "goal.get" });
|
|
@@ -1660,19 +1715,31 @@ var useAutoPhaseStore = create12()((set) => ({
|
|
|
1660
1715
|
overallPercent: 0,
|
|
1661
1716
|
autonomous: false,
|
|
1662
1717
|
title: null,
|
|
1718
|
+
status: "idle",
|
|
1719
|
+
lastEvent: null,
|
|
1720
|
+
lastError: null,
|
|
1721
|
+
progress: null,
|
|
1663
1722
|
setState: (patch) => set((prev) => ({
|
|
1664
1723
|
phases: patch.phases ?? prev.phases,
|
|
1665
1724
|
activePhaseId: patch.activePhaseId !== void 0 ? patch.activePhaseId : prev.activePhaseId,
|
|
1666
1725
|
overallPercent: patch.overallPercent ?? prev.overallPercent,
|
|
1667
1726
|
autonomous: patch.autonomous ?? prev.autonomous,
|
|
1668
|
-
title: patch.title !== void 0 ? patch.title : prev.title
|
|
1727
|
+
title: patch.title !== void 0 ? patch.title : prev.title,
|
|
1728
|
+
status: patch.status ?? prev.status,
|
|
1729
|
+
lastEvent: patch.lastEvent !== void 0 ? patch.lastEvent : prev.lastEvent,
|
|
1730
|
+
lastError: patch.lastError !== void 0 ? patch.lastError : prev.lastError,
|
|
1731
|
+
progress: patch.progress !== void 0 ? patch.progress : prev.progress
|
|
1669
1732
|
})),
|
|
1670
1733
|
clear: () => set({
|
|
1671
1734
|
phases: [],
|
|
1672
1735
|
activePhaseId: null,
|
|
1673
1736
|
overallPercent: 0,
|
|
1674
1737
|
autonomous: false,
|
|
1675
|
-
title: null
|
|
1738
|
+
title: null,
|
|
1739
|
+
status: "idle",
|
|
1740
|
+
lastEvent: null,
|
|
1741
|
+
lastError: null,
|
|
1742
|
+
progress: null
|
|
1676
1743
|
})
|
|
1677
1744
|
}));
|
|
1678
1745
|
|
|
@@ -1842,6 +1909,7 @@ function inferKind(event, isTarget = false) {
|
|
|
1842
1909
|
case "agent:status":
|
|
1843
1910
|
case "agent:text":
|
|
1844
1911
|
case "agent:ctx":
|
|
1912
|
+
case "budget:warning":
|
|
1845
1913
|
case "budget:extended":
|
|
1846
1914
|
return "agent";
|
|
1847
1915
|
case "tool:started":
|
|
@@ -1851,10 +1919,13 @@ function inferKind(event, isTarget = false) {
|
|
|
1851
1919
|
case "mailbox:send":
|
|
1852
1920
|
case "mailbox:deliver":
|
|
1853
1921
|
return "mailbox";
|
|
1922
|
+
case "collab:event":
|
|
1923
|
+
return "system";
|
|
1854
1924
|
case "session:start":
|
|
1855
1925
|
case "session:end":
|
|
1856
1926
|
case "iteration:start":
|
|
1857
1927
|
case "iteration:end":
|
|
1928
|
+
case "eternal:iteration":
|
|
1858
1929
|
case "fleet:snapshot":
|
|
1859
1930
|
return "session";
|
|
1860
1931
|
case "context:compacted":
|
|
@@ -2093,6 +2164,21 @@ function wsToVizEvent(wsType, payload) {
|
|
|
2093
2164
|
flowGroup: "provider"
|
|
2094
2165
|
};
|
|
2095
2166
|
}
|
|
2167
|
+
case "provider.stream_error": {
|
|
2168
|
+
const message = payload.message ?? "Provider stream error";
|
|
2169
|
+
return {
|
|
2170
|
+
id: nextId(),
|
|
2171
|
+
kind: "error",
|
|
2172
|
+
timestamp: Date.now(),
|
|
2173
|
+
source: "provider",
|
|
2174
|
+
target: "leader",
|
|
2175
|
+
label: message.slice(0, 80),
|
|
2176
|
+
magnitude: 1,
|
|
2177
|
+
data: payload,
|
|
2178
|
+
color: NODE_COLORS.error,
|
|
2179
|
+
flowGroup: "provider"
|
|
2180
|
+
};
|
|
2181
|
+
}
|
|
2096
2182
|
case "tool.started": {
|
|
2097
2183
|
const name = payload.name ?? "tool";
|
|
2098
2184
|
return {
|
|
@@ -2140,6 +2226,54 @@ function wsToVizEvent(wsType, payload) {
|
|
|
2140
2226
|
flowGroup: `tool:${name}`
|
|
2141
2227
|
};
|
|
2142
2228
|
}
|
|
2229
|
+
case "tool.loop_detected": {
|
|
2230
|
+
const tools = payload.tools ?? "";
|
|
2231
|
+
const kind = payload.kind ?? "loop";
|
|
2232
|
+
return {
|
|
2233
|
+
id: nextId(),
|
|
2234
|
+
kind: "error",
|
|
2235
|
+
timestamp: Date.now(),
|
|
2236
|
+
source: tools || kind,
|
|
2237
|
+
target: "leader",
|
|
2238
|
+
label: `${kind} loop x${payload.repeatCount ?? 0}`,
|
|
2239
|
+
magnitude: payload.repeatCount ?? 1,
|
|
2240
|
+
data: payload,
|
|
2241
|
+
color: NODE_COLORS.error,
|
|
2242
|
+
flowGroup: "tool"
|
|
2243
|
+
};
|
|
2244
|
+
}
|
|
2245
|
+
case "delegate.started": {
|
|
2246
|
+
const target = payload.target ?? "delegate";
|
|
2247
|
+
const task = payload.task ?? "";
|
|
2248
|
+
return {
|
|
2249
|
+
id: nextId(),
|
|
2250
|
+
kind: "agent:status",
|
|
2251
|
+
timestamp: Date.now(),
|
|
2252
|
+
source: "leader",
|
|
2253
|
+
target,
|
|
2254
|
+
label: task.slice(0, 80) || `Delegating to ${target}`,
|
|
2255
|
+
magnitude: 1,
|
|
2256
|
+
data: payload,
|
|
2257
|
+
color: NODE_COLORS.agent,
|
|
2258
|
+
flowGroup: `delegate:${target}`
|
|
2259
|
+
};
|
|
2260
|
+
}
|
|
2261
|
+
case "delegate.completed": {
|
|
2262
|
+
const target = payload.subagentId ?? payload.target ?? "delegate";
|
|
2263
|
+
const ok = payload.ok ?? false;
|
|
2264
|
+
return {
|
|
2265
|
+
id: nextId(),
|
|
2266
|
+
kind: ok ? "agent:status" : "error",
|
|
2267
|
+
timestamp: Date.now(),
|
|
2268
|
+
source: target,
|
|
2269
|
+
target: "leader",
|
|
2270
|
+
label: (payload.summary ?? payload.status ?? "delegate completed").slice(0, 80),
|
|
2271
|
+
magnitude: payload.durationMs ?? 1,
|
|
2272
|
+
data: payload,
|
|
2273
|
+
color: ok ? NODE_COLORS.agent : NODE_COLORS.error,
|
|
2274
|
+
flowGroup: `delegate:${target}`
|
|
2275
|
+
};
|
|
2276
|
+
}
|
|
2143
2277
|
case "subagent.event": {
|
|
2144
2278
|
const kind = payload.kind;
|
|
2145
2279
|
const agentId = payload.subagentId ?? "unknown";
|
|
@@ -2228,6 +2362,19 @@ function wsToVizEvent(wsType, payload) {
|
|
|
2228
2362
|
color: "hsl(40, 90%, 55%)",
|
|
2229
2363
|
flowGroup: `agent:${agentId}`
|
|
2230
2364
|
};
|
|
2365
|
+
case "budget_warning":
|
|
2366
|
+
return {
|
|
2367
|
+
id: nextId(),
|
|
2368
|
+
kind: "budget:warning",
|
|
2369
|
+
timestamp: Date.now(),
|
|
2370
|
+
source: agentId,
|
|
2371
|
+
target: "session",
|
|
2372
|
+
label: `${agentName} hit ${payload.budgetKind ?? "budget"} ${payload.used ?? 0}/${payload.limit ?? 0}`,
|
|
2373
|
+
magnitude: payload.used ?? 1,
|
|
2374
|
+
data: payload,
|
|
2375
|
+
color: NODE_COLORS.error,
|
|
2376
|
+
flowGroup: `agent:${agentId}`
|
|
2377
|
+
};
|
|
2231
2378
|
}
|
|
2232
2379
|
return null;
|
|
2233
2380
|
}
|
|
@@ -2265,6 +2412,37 @@ function wsToVizEvent(wsType, payload) {
|
|
|
2265
2412
|
flowGroup: "iteration"
|
|
2266
2413
|
};
|
|
2267
2414
|
}
|
|
2415
|
+
case "iteration.completed": {
|
|
2416
|
+
const idx = payload.index ?? 0;
|
|
2417
|
+
return {
|
|
2418
|
+
id: nextId(),
|
|
2419
|
+
kind: "iteration:end",
|
|
2420
|
+
timestamp: Date.now(),
|
|
2421
|
+
source: "leader",
|
|
2422
|
+
target: "session",
|
|
2423
|
+
label: `Iteration ${idx} done`,
|
|
2424
|
+
magnitude: idx,
|
|
2425
|
+
data: payload,
|
|
2426
|
+
color: NODE_COLORS.session,
|
|
2427
|
+
flowGroup: "iteration"
|
|
2428
|
+
};
|
|
2429
|
+
}
|
|
2430
|
+
case "ctx.pct": {
|
|
2431
|
+
const load = payload.load ?? 0;
|
|
2432
|
+
const tokens = payload.tokens ?? 0;
|
|
2433
|
+
return {
|
|
2434
|
+
id: nextId(),
|
|
2435
|
+
kind: "agent:ctx",
|
|
2436
|
+
timestamp: Date.now(),
|
|
2437
|
+
source: "leader",
|
|
2438
|
+
target: "session",
|
|
2439
|
+
label: `ctx ${Math.round(load * 100)}%`,
|
|
2440
|
+
magnitude: tokens,
|
|
2441
|
+
data: payload,
|
|
2442
|
+
color: NODE_COLORS.agent,
|
|
2443
|
+
flowGroup: "leader"
|
|
2444
|
+
};
|
|
2445
|
+
}
|
|
2268
2446
|
case "error": {
|
|
2269
2447
|
const msg = payload.message ?? "Error";
|
|
2270
2448
|
return {
|
|
@@ -2293,6 +2471,21 @@ function wsToVizEvent(wsType, payload) {
|
|
|
2293
2471
|
color: "hsl(220, 60%, 50%)",
|
|
2294
2472
|
flowGroup: "context"
|
|
2295
2473
|
};
|
|
2474
|
+
case "compaction.failed": {
|
|
2475
|
+
const message = payload.message ?? "Compaction failed";
|
|
2476
|
+
return {
|
|
2477
|
+
id: nextId(),
|
|
2478
|
+
kind: "error",
|
|
2479
|
+
timestamp: Date.now(),
|
|
2480
|
+
source: "compactor",
|
|
2481
|
+
target: "session",
|
|
2482
|
+
label: message.slice(0, 80),
|
|
2483
|
+
magnitude: payload.tokens ?? 1,
|
|
2484
|
+
data: payload,
|
|
2485
|
+
color: NODE_COLORS.error,
|
|
2486
|
+
flowGroup: "context"
|
|
2487
|
+
};
|
|
2488
|
+
}
|
|
2296
2489
|
case "context.repaired":
|
|
2297
2490
|
return {
|
|
2298
2491
|
id: nextId(),
|
|
@@ -3223,6 +3416,10 @@ function pipeViz2(msg) {
|
|
|
3223
3416
|
useVizStore.getState().setActive(true);
|
|
3224
3417
|
}
|
|
3225
3418
|
}
|
|
3419
|
+
var warnedCostModels = /* @__PURE__ */ new Set();
|
|
3420
|
+
function truncateLine(text, max = 140) {
|
|
3421
|
+
return text.length > max ? `${text.slice(0, max - 1)}\u2026` : text;
|
|
3422
|
+
}
|
|
3226
3423
|
function handleSessionStart(msg) {
|
|
3227
3424
|
const vizStart = wsToVizEvent("session.start", msg.payload);
|
|
3228
3425
|
if (vizStart) {
|
|
@@ -3346,6 +3543,17 @@ function handleContextCompacted(msg) {
|
|
|
3346
3543
|
useChatStore.getState().addMessage({ role: "assistant", content: `\u{1F5DC}\uFE0F Context compacted: ${payload.before} \u2192 ${payload.after} tokens (saved ~${payload.saved}). ${summary}` });
|
|
3347
3544
|
useSessionStore.setState({ lastInputTokens: payload.after });
|
|
3348
3545
|
}
|
|
3546
|
+
function handleCompactionFailed(msg) {
|
|
3547
|
+
pipeViz2(msg);
|
|
3548
|
+
const payload = msg.payload;
|
|
3549
|
+
const load = payload.maxContext > 0 ? Math.round(payload.tokens / payload.maxContext * 100) : 0;
|
|
3550
|
+
useChatStore.getState().addMessage({
|
|
3551
|
+
role: "assistant",
|
|
3552
|
+
content: `Compaction failed at ${payload.level} (${load}% context): ${payload.message}`,
|
|
3553
|
+
isError: payload.fatal
|
|
3554
|
+
});
|
|
3555
|
+
toast.error(`Compaction failed: ${payload.message}`);
|
|
3556
|
+
}
|
|
3349
3557
|
function handleProviderResponse(msg) {
|
|
3350
3558
|
pipeViz2(msg);
|
|
3351
3559
|
const payload = msg.payload;
|
|
@@ -3366,6 +3574,127 @@ function handleProviderResponse(msg) {
|
|
|
3366
3574
|
useChatStore.getState().setCurrentAssistantMessage(null);
|
|
3367
3575
|
useChatStore.getState().clearThinking();
|
|
3368
3576
|
}
|
|
3577
|
+
function handleIterationCompleted(msg) {
|
|
3578
|
+
pipeViz2(msg);
|
|
3579
|
+
const p = msg.payload;
|
|
3580
|
+
const current = useSessionStore.getState().iteration;
|
|
3581
|
+
if (current) {
|
|
3582
|
+
useSessionStore.getState().setIteration({
|
|
3583
|
+
index: p.index,
|
|
3584
|
+
max: current.max
|
|
3585
|
+
});
|
|
3586
|
+
}
|
|
3587
|
+
}
|
|
3588
|
+
function handleIterationLimitReached(msg) {
|
|
3589
|
+
const p = msg.payload;
|
|
3590
|
+
useChatStore.getState().addMessage({
|
|
3591
|
+
role: "assistant",
|
|
3592
|
+
content: `Iteration limit reached: ${p.currentIterations}/${p.currentLimit}.`,
|
|
3593
|
+
isError: true
|
|
3594
|
+
});
|
|
3595
|
+
toast.warn(`Iteration limit reached (${p.currentIterations}/${p.currentLimit})`);
|
|
3596
|
+
}
|
|
3597
|
+
function handleProviderRetry(msg) {
|
|
3598
|
+
const payload = msg.payload;
|
|
3599
|
+
const seconds = Math.max(0, Math.round(payload.delayMs / 100) / 10);
|
|
3600
|
+
toast.warn(
|
|
3601
|
+
`${payload.providerId} retry ${payload.attempt} after ${seconds}s (${payload.status})`
|
|
3602
|
+
);
|
|
3603
|
+
}
|
|
3604
|
+
function handleProviderError(msg) {
|
|
3605
|
+
const payload = msg.payload;
|
|
3606
|
+
useChatStore.getState().addMessage({
|
|
3607
|
+
role: "assistant",
|
|
3608
|
+
content: [
|
|
3609
|
+
`Provider error from \`${payload.providerId}\` (${payload.status}).`,
|
|
3610
|
+
payload.description,
|
|
3611
|
+
payload.retryable ? "_Retryable; WrongStack may recover automatically._" : ""
|
|
3612
|
+
].filter(Boolean).join("\n\n"),
|
|
3613
|
+
isError: true
|
|
3614
|
+
});
|
|
3615
|
+
toast.error(`${payload.providerId} provider error (${payload.status})`);
|
|
3616
|
+
}
|
|
3617
|
+
function handleProviderFallback(msg) {
|
|
3618
|
+
const payload = msg.payload;
|
|
3619
|
+
const from = `${payload.from.providerId}/${payload.from.model}`;
|
|
3620
|
+
const to = `${payload.to.providerId}/${payload.to.model}`;
|
|
3621
|
+
useChatStore.getState().addMessage({
|
|
3622
|
+
role: "assistant",
|
|
3623
|
+
content: `Provider fallback: \`${from}\` returned ${payload.status}; switching to \`${to}\`${payload.providerSwitched ? " with provider change" : ""}.`
|
|
3624
|
+
});
|
|
3625
|
+
toast.warn(`Fallback to ${to}`);
|
|
3626
|
+
}
|
|
3627
|
+
function handleProviderStreamError(msg) {
|
|
3628
|
+
pipeViz2(msg);
|
|
3629
|
+
const p = msg.payload;
|
|
3630
|
+
toast.warn(`Provider stream event skipped: ${p.eventType}`);
|
|
3631
|
+
useChatStore.getState().addMessage({
|
|
3632
|
+
role: "assistant",
|
|
3633
|
+
content: `Provider stream warning (${p.eventType}): ${p.message}`,
|
|
3634
|
+
isError: true
|
|
3635
|
+
});
|
|
3636
|
+
}
|
|
3637
|
+
function handleToolLoopDetected(msg) {
|
|
3638
|
+
pipeViz2(msg);
|
|
3639
|
+
const p = msg.payload;
|
|
3640
|
+
const subject = p.tools || p.kind || "assistant response";
|
|
3641
|
+
useChatStore.getState().addMessage({
|
|
3642
|
+
role: "assistant",
|
|
3643
|
+
content: `Loop guard triggered: ${subject} repeated ${p.repeatCount} time(s) at iteration ${p.iteration}.`,
|
|
3644
|
+
isError: true
|
|
3645
|
+
});
|
|
3646
|
+
toast.warn("Loop guard triggered");
|
|
3647
|
+
}
|
|
3648
|
+
function handleDelegateStarted(msg) {
|
|
3649
|
+
pipeViz2(msg);
|
|
3650
|
+
const p = msg.payload;
|
|
3651
|
+
const task = truncateLine(p.task, 180);
|
|
3652
|
+
useChatStore.getState().addMessage({
|
|
3653
|
+
role: "assistant",
|
|
3654
|
+
content: `Delegating to \`${p.target}\`: ${task}`
|
|
3655
|
+
});
|
|
3656
|
+
useFleetStore.getState().pushAgentTimelineEntry({
|
|
3657
|
+
subagentId: p.target,
|
|
3658
|
+
agentName: p.target,
|
|
3659
|
+
content: task,
|
|
3660
|
+
kind: "status",
|
|
3661
|
+
iteration: 0,
|
|
3662
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3663
|
+
status: "delegating"
|
|
3664
|
+
});
|
|
3665
|
+
}
|
|
3666
|
+
function handleDelegateCompleted(msg) {
|
|
3667
|
+
pipeViz2(msg);
|
|
3668
|
+
const p = msg.payload;
|
|
3669
|
+
const seconds = Math.max(0, Math.round(p.durationMs / 100) / 10);
|
|
3670
|
+
const cost = typeof p.costUsd === "number" && p.costUsd > 0 ? ` \xB7 $${p.costUsd.toFixed(4)}` : "";
|
|
3671
|
+
const stats = `${p.iterations} iteration(s), ${p.toolCalls} tool call(s), ${seconds}s${cost}`;
|
|
3672
|
+
useChatStore.getState().addMessage({
|
|
3673
|
+
role: "assistant",
|
|
3674
|
+
content: [
|
|
3675
|
+
`Delegate ${p.ok ? "completed" : "failed"} for \`${p.target}\`${p.status ? ` (${p.status})` : ""}.`,
|
|
3676
|
+
p.summary,
|
|
3677
|
+
stats
|
|
3678
|
+
].join("\n"),
|
|
3679
|
+
isError: !p.ok
|
|
3680
|
+
});
|
|
3681
|
+
useFleetStore.getState().pushAgentTimelineEntry({
|
|
3682
|
+
subagentId: p.subagentId ?? p.target,
|
|
3683
|
+
agentName: p.target,
|
|
3684
|
+
content: p.summary,
|
|
3685
|
+
kind: p.ok ? "status" : "error",
|
|
3686
|
+
iteration: p.iterations,
|
|
3687
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3688
|
+
status: p.status ?? (p.ok ? "completed" : "failed")
|
|
3689
|
+
});
|
|
3690
|
+
if (!p.ok) toast.warn(`Delegate failed: ${p.target}`);
|
|
3691
|
+
}
|
|
3692
|
+
function handleTrustPersisted(msg) {
|
|
3693
|
+
const p = msg.payload;
|
|
3694
|
+
const label = `${p.tool}: ${p.pattern}`;
|
|
3695
|
+
if (p.decision === "always") toast.success(`Always allowed ${label}`);
|
|
3696
|
+
else toast.warn(`Denied ${label}`);
|
|
3697
|
+
}
|
|
3369
3698
|
function handleContextRepaired(msg) {
|
|
3370
3699
|
pipeViz2(msg);
|
|
3371
3700
|
const payload = msg.payload;
|
|
@@ -3373,6 +3702,68 @@ function handleContextRepaired(msg) {
|
|
|
3373
3702
|
const msgCount = payload.beforeMessages !== void 0 && payload.afterMessages !== void 0 ? ` Messages: ${payload.beforeMessages} -> ${payload.afterMessages}.` : "";
|
|
3374
3703
|
useChatStore.getState().addMessage({ role: "assistant", content: `Context repaired: removed ${removed} orphan protocol item(s).${msgCount} tool_use ${payload.removedToolUses.length}, tool_result ${payload.removedToolResults.length}.` });
|
|
3375
3704
|
}
|
|
3705
|
+
function handleContextPct(msg) {
|
|
3706
|
+
pipeViz2(msg);
|
|
3707
|
+
const p = msg.payload;
|
|
3708
|
+
useSessionStore.getState().setContextUsage(p.tokens, p.maxContext);
|
|
3709
|
+
}
|
|
3710
|
+
function handleContextMaxContext(msg) {
|
|
3711
|
+
const p = msg.payload;
|
|
3712
|
+
useSessionStore.getState().setEnv({ maxContext: p.maxContext });
|
|
3713
|
+
}
|
|
3714
|
+
function handleTokenThreshold(msg) {
|
|
3715
|
+
const p = msg.payload;
|
|
3716
|
+
useSessionStore.getState().setContextUsage(p.used, p.limit);
|
|
3717
|
+
const pct = p.limit > 0 ? Math.round(p.used / p.limit * 100) : 0;
|
|
3718
|
+
toast.warn(`Token threshold reached (${pct}%)`);
|
|
3719
|
+
}
|
|
3720
|
+
function handleTokenCostEstimateUnavailable(msg) {
|
|
3721
|
+
const p = msg.payload;
|
|
3722
|
+
const model = p.model || "<unknown>";
|
|
3723
|
+
if (warnedCostModels.has(model)) return;
|
|
3724
|
+
warnedCostModels.add(model);
|
|
3725
|
+
toast.warn(`Cost estimate unavailable for ${model}`);
|
|
3726
|
+
}
|
|
3727
|
+
function handleSessionDamaged(msg) {
|
|
3728
|
+
const p = msg.payload;
|
|
3729
|
+
useChatStore.getState().addMessage({
|
|
3730
|
+
role: "assistant",
|
|
3731
|
+
content: `Session ${p.sessionId} is damaged: ${p.detail}`,
|
|
3732
|
+
isError: true
|
|
3733
|
+
});
|
|
3734
|
+
toast.error("Session damage detected");
|
|
3735
|
+
}
|
|
3736
|
+
function handleSessionRewound(msg) {
|
|
3737
|
+
const p = msg.payload;
|
|
3738
|
+
useChatStore.getState().addMessage({
|
|
3739
|
+
role: "assistant",
|
|
3740
|
+
content: `Session rewound to prompt #${p.toPromptIndex}. Removed ${p.removedEvents} event(s); reverted ${p.revertedFiles.length} file(s).`
|
|
3741
|
+
});
|
|
3742
|
+
toast.info("Session rewound");
|
|
3743
|
+
}
|
|
3744
|
+
function handleCheckpointWritten(msg) {
|
|
3745
|
+
const p = msg.payload;
|
|
3746
|
+
toast.success(`Checkpoint #${p.promptIndex} written (${p.fileCount} file(s))`);
|
|
3747
|
+
}
|
|
3748
|
+
function handleInFlightStarted(msg) {
|
|
3749
|
+
const p = msg.payload;
|
|
3750
|
+
useVizStore.getState().pushEvent({
|
|
3751
|
+
id: `inflight_${Date.now()}`,
|
|
3752
|
+
kind: "session:start",
|
|
3753
|
+
timestamp: Date.now(),
|
|
3754
|
+
source: "session",
|
|
3755
|
+
target: "leader",
|
|
3756
|
+
label: `In-flight: ${p.context}`,
|
|
3757
|
+
magnitude: 1,
|
|
3758
|
+
data: p,
|
|
3759
|
+
raw: msg.payload,
|
|
3760
|
+
flowGroup: "session"
|
|
3761
|
+
});
|
|
3762
|
+
}
|
|
3763
|
+
function handleInFlightEnded(msg) {
|
|
3764
|
+
const p = msg.payload;
|
|
3765
|
+
if (p.reason === "recovered") toast.info("Recovered previous in-flight operation");
|
|
3766
|
+
}
|
|
3376
3767
|
function handleSessionEnd() {
|
|
3377
3768
|
useConfigStore.getState().setWsConnected(false);
|
|
3378
3769
|
}
|
|
@@ -3398,9 +3789,29 @@ var sessionHandlerMap = {
|
|
|
3398
3789
|
"context.debug": handleContextDebug,
|
|
3399
3790
|
"key.operation_result": handleKeyOperationResult,
|
|
3400
3791
|
"context.compacted": handleContextCompacted,
|
|
3792
|
+
"compaction.failed": handleCompactionFailed,
|
|
3401
3793
|
"provider.response": handleProviderResponse,
|
|
3794
|
+
"iteration.completed": handleIterationCompleted,
|
|
3795
|
+
"iteration.limit_reached": handleIterationLimitReached,
|
|
3796
|
+
"provider.retry": handleProviderRetry,
|
|
3797
|
+
"provider.error": handleProviderError,
|
|
3798
|
+
"provider.fallback": handleProviderFallback,
|
|
3799
|
+
"provider.stream_error": handleProviderStreamError,
|
|
3800
|
+
"tool.loop_detected": handleToolLoopDetected,
|
|
3801
|
+
"delegate.started": handleDelegateStarted,
|
|
3802
|
+
"delegate.completed": handleDelegateCompleted,
|
|
3803
|
+
"trust.persisted": handleTrustPersisted,
|
|
3402
3804
|
"context.repaired": handleContextRepaired,
|
|
3805
|
+
"ctx.pct": handleContextPct,
|
|
3806
|
+
"ctx.max_context": handleContextMaxContext,
|
|
3807
|
+
"token.threshold": handleTokenThreshold,
|
|
3808
|
+
"token.cost_estimate_unavailable": handleTokenCostEstimateUnavailable,
|
|
3403
3809
|
"session.end": handleSessionEnd,
|
|
3810
|
+
"session.damaged": handleSessionDamaged,
|
|
3811
|
+
"session.rewound": handleSessionRewound,
|
|
3812
|
+
"checkpoint.written": handleCheckpointWritten,
|
|
3813
|
+
"in_flight.started": handleInFlightStarted,
|
|
3814
|
+
"in_flight.ended": handleInFlightEnded,
|
|
3404
3815
|
"context.modes.list": handleContextModesList,
|
|
3405
3816
|
"context.mode.changed": handleContextModeChanged,
|
|
3406
3817
|
"sessions.list": handleSessionsList,
|
|
@@ -3544,14 +3955,85 @@ var filesMailboxHandlerMap = {
|
|
|
3544
3955
|
|
|
3545
3956
|
// src/hooks/ws-handlers/misc-handlers.ts
|
|
3546
3957
|
import { normalizedEqual } from "@wrongstack/core";
|
|
3958
|
+
function deriveAutoPhaseStatus(phases) {
|
|
3959
|
+
if (!phases || phases.length === 0) return void 0;
|
|
3960
|
+
const statuses = phases.map((p) => p.status);
|
|
3961
|
+
if (statuses.some((s) => s === "failed")) return "failed";
|
|
3962
|
+
if (statuses.every((s) => s === "completed" || s === "skipped")) return "completed";
|
|
3963
|
+
if (statuses.some((s) => s === "paused")) return "paused";
|
|
3964
|
+
return "running";
|
|
3965
|
+
}
|
|
3547
3966
|
function handleAutoPhaseState(msg) {
|
|
3548
3967
|
const p = msg.payload;
|
|
3968
|
+
const phases = Array.isArray(p.phases) ? p.phases : void 0;
|
|
3969
|
+
const status = deriveAutoPhaseStatus(phases);
|
|
3549
3970
|
useAutoPhaseStore.getState().setState({
|
|
3550
|
-
phases
|
|
3971
|
+
phases,
|
|
3551
3972
|
activePhaseId: typeof p.activePhaseId === "string" ? p.activePhaseId : void 0,
|
|
3552
3973
|
overallPercent: typeof p.overallPercent === "number" ? p.overallPercent : void 0,
|
|
3553
3974
|
autonomous: typeof p.autonomous === "boolean" ? p.autonomous : void 0,
|
|
3554
|
-
title: typeof p.title === "string" ? p.title : void 0
|
|
3975
|
+
title: typeof p.title === "string" ? p.title : void 0,
|
|
3976
|
+
status,
|
|
3977
|
+
lastError: status === "failed" ? useAutoPhaseStore.getState().lastError : null
|
|
3978
|
+
});
|
|
3979
|
+
}
|
|
3980
|
+
function handleAutoPhaseProgress(msg) {
|
|
3981
|
+
const p = msg.payload;
|
|
3982
|
+
const progress = {
|
|
3983
|
+
totalPhases: typeof p.totalPhases === "number" ? p.totalPhases : 0,
|
|
3984
|
+
completed: typeof p.completed === "number" ? p.completed : 0,
|
|
3985
|
+
failed: typeof p.failed === "number" ? p.failed : 0,
|
|
3986
|
+
totalTasks: typeof p.totalTasks === "number" ? p.totalTasks : 0,
|
|
3987
|
+
completedTasks: typeof p.completedTasks === "number" ? p.completedTasks : 0,
|
|
3988
|
+
failedTasks: typeof p.failedTasks === "number" ? p.failedTasks : 0
|
|
3989
|
+
};
|
|
3990
|
+
useAutoPhaseStore.getState().setState({
|
|
3991
|
+
progress,
|
|
3992
|
+
overallPercent: typeof p.percentComplete === "number" ? Math.round(p.percentComplete) : void 0,
|
|
3993
|
+
status: progress.failed > 0 || progress.failedTasks > 0 ? "failed" : "running",
|
|
3994
|
+
lastEvent: "progress"
|
|
3995
|
+
});
|
|
3996
|
+
}
|
|
3997
|
+
function handleAutoPhaseLifecycle(msg) {
|
|
3998
|
+
const p = msg.payload;
|
|
3999
|
+
const title = typeof p.title === "string" && p.title ? p.title : "AutoPhase";
|
|
4000
|
+
const error = typeof p.error === "string" && p.error ? p.error : void 0;
|
|
4001
|
+
if (msg.type === "autophase.paused") {
|
|
4002
|
+
useAutoPhaseStore.getState().setState({ status: "paused", autonomous: false, lastEvent: "paused" });
|
|
4003
|
+
toast.info("AutoPhase paused");
|
|
4004
|
+
return;
|
|
4005
|
+
}
|
|
4006
|
+
if (msg.type === "autophase.resumed") {
|
|
4007
|
+
useAutoPhaseStore.getState().setState({ status: "running", autonomous: true, lastEvent: "resumed" });
|
|
4008
|
+
toast.info("AutoPhase resumed");
|
|
4009
|
+
return;
|
|
4010
|
+
}
|
|
4011
|
+
if (msg.type === "autophase.stopped") {
|
|
4012
|
+
useAutoPhaseStore.getState().setState({ status: "stopped", autonomous: false, lastEvent: "stopped" });
|
|
4013
|
+
toast.warn("AutoPhase stopped");
|
|
4014
|
+
return;
|
|
4015
|
+
}
|
|
4016
|
+
if (msg.type === "autophase.saved") {
|
|
4017
|
+
useAutoPhaseStore.getState().setState({ lastEvent: "saved" });
|
|
4018
|
+
toast.success("AutoPhase graph saved");
|
|
4019
|
+
return;
|
|
4020
|
+
}
|
|
4021
|
+
if (msg.type === "autophase.completed") {
|
|
4022
|
+
useAutoPhaseStore.getState().setState({ status: "completed", autonomous: false, overallPercent: 100, lastEvent: "completed", lastError: null });
|
|
4023
|
+
toast.success(`${title} completed`);
|
|
4024
|
+
return;
|
|
4025
|
+
}
|
|
4026
|
+
if (msg.type === "autophase.failed" || msg.type === "autophase.error") {
|
|
4027
|
+
const message = error ?? (typeof p.message === "string" ? p.message : `${title} failed`);
|
|
4028
|
+
useAutoPhaseStore.getState().setState({ status: "failed", autonomous: false, lastEvent: "failed", lastError: message });
|
|
4029
|
+
toast.error(message);
|
|
4030
|
+
}
|
|
4031
|
+
}
|
|
4032
|
+
function handleAutoPhaseList(msg) {
|
|
4033
|
+
const p = msg.payload;
|
|
4034
|
+
useAutoPhaseStore.getState().setState({
|
|
4035
|
+
lastEvent: "list",
|
|
4036
|
+
progress: p.graphs ? { totalPhases: p.graphs.length, completed: 0, failed: 0, totalTasks: 0, completedTasks: 0, failedTasks: 0 } : void 0
|
|
3555
4037
|
});
|
|
3556
4038
|
}
|
|
3557
4039
|
function handleGoalUpdated(msg) {
|
|
@@ -3611,6 +4093,62 @@ function handleBrainEvent(msg) {
|
|
|
3611
4093
|
toast.warn(`Brain denied: ${p.decision?.reason ?? p.request?.question ?? "request"}`);
|
|
3612
4094
|
}
|
|
3613
4095
|
}
|
|
4096
|
+
function handleCollabEvent(msg) {
|
|
4097
|
+
const p = msg.payload;
|
|
4098
|
+
const label = typeof p.kind === "string" ? p.kind : typeof p.event === "string" ? p.event : "collab.event";
|
|
4099
|
+
useVizStore.getState().pushEvent({
|
|
4100
|
+
id: `collab_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`,
|
|
4101
|
+
kind: "collab:event",
|
|
4102
|
+
timestamp: Date.now(),
|
|
4103
|
+
source: "collab",
|
|
4104
|
+
target: typeof p.sessionId === "string" ? p.sessionId : "session",
|
|
4105
|
+
label,
|
|
4106
|
+
magnitude: 1,
|
|
4107
|
+
data: p,
|
|
4108
|
+
raw: msg.payload,
|
|
4109
|
+
color: "hsl(200, 70%, 55%)",
|
|
4110
|
+
flowGroup: "collab"
|
|
4111
|
+
});
|
|
4112
|
+
useVizStore.getState().setActive(true);
|
|
4113
|
+
}
|
|
4114
|
+
function handleCollabInjectionGranted(msg) {
|
|
4115
|
+
handleCollabEvent(msg);
|
|
4116
|
+
const p = msg.payload;
|
|
4117
|
+
if (p?.phase === "consumed") {
|
|
4118
|
+
toast.success(`Tool injection applied${p.toolName ? ` to ${p.toolName}` : ""}`);
|
|
4119
|
+
} else {
|
|
4120
|
+
toast.info("Collab tool injection queued");
|
|
4121
|
+
}
|
|
4122
|
+
}
|
|
4123
|
+
function handleEternalIteration(msg) {
|
|
4124
|
+
const payload = msg.payload;
|
|
4125
|
+
const entry = payload?.entry;
|
|
4126
|
+
if (!entry) return;
|
|
4127
|
+
const iteration = typeof entry.iteration === "number" ? entry.iteration : 0;
|
|
4128
|
+
const task = typeof entry.task === "string" ? entry.task : void 0;
|
|
4129
|
+
const status = typeof entry.status === "string" ? entry.status : void 0;
|
|
4130
|
+
const timestamp = typeof entry.at === "string" ? entry.at : (/* @__PURE__ */ new Date()).toISOString();
|
|
4131
|
+
useGoalStore.getState().appendJournalEntry({
|
|
4132
|
+
iteration,
|
|
4133
|
+
task,
|
|
4134
|
+
status,
|
|
4135
|
+
timestamp
|
|
4136
|
+
});
|
|
4137
|
+
useVizStore.getState().pushEvent({
|
|
4138
|
+
id: `eternal_${Date.now()}_${iteration}`,
|
|
4139
|
+
kind: "eternal:iteration",
|
|
4140
|
+
timestamp: Date.now(),
|
|
4141
|
+
source: "eternal",
|
|
4142
|
+
target: "goal",
|
|
4143
|
+
label: task ? `L${iteration}: ${task}` : `Eternal iteration ${iteration}`,
|
|
4144
|
+
magnitude: typeof entry.costUsd === "number" ? entry.costUsd : 1,
|
|
4145
|
+
data: entry,
|
|
4146
|
+
raw: msg.payload,
|
|
4147
|
+
color: status === "failure" ? "hsl(0, 80%, 55%)" : "hsl(220, 80%, 60%)",
|
|
4148
|
+
flowGroup: "eternal"
|
|
4149
|
+
});
|
|
4150
|
+
useVizStore.getState().setActive(true);
|
|
4151
|
+
}
|
|
3614
4152
|
function handleWorkingDirChanged(msg) {
|
|
3615
4153
|
const p = msg.payload;
|
|
3616
4154
|
useSessionStore.getState().setEnv({
|
|
@@ -3672,9 +4210,21 @@ var miscHandlerMap = {
|
|
|
3672
4210
|
"goal.updated": handleGoalUpdated,
|
|
3673
4211
|
"prefs.updated": handlePrefsUpdated,
|
|
3674
4212
|
"autophase.state": handleAutoPhaseState,
|
|
4213
|
+
"autophase.progress": handleAutoPhaseProgress,
|
|
4214
|
+
"autophase.paused": handleAutoPhaseLifecycle,
|
|
4215
|
+
"autophase.resumed": handleAutoPhaseLifecycle,
|
|
4216
|
+
"autophase.stopped": handleAutoPhaseLifecycle,
|
|
4217
|
+
"autophase.saved": handleAutoPhaseLifecycle,
|
|
4218
|
+
"autophase.completed": handleAutoPhaseLifecycle,
|
|
4219
|
+
"autophase.failed": handleAutoPhaseLifecycle,
|
|
4220
|
+
"autophase.error": handleAutoPhaseLifecycle,
|
|
4221
|
+
"autophase.list": handleAutoPhaseList,
|
|
3675
4222
|
"brain.status": handleBrainStatus,
|
|
3676
4223
|
"brain.answer": handleBrainAnswer,
|
|
3677
4224
|
"brain.event": handleBrainEvent,
|
|
4225
|
+
"collab.event": handleCollabEvent,
|
|
4226
|
+
"collab.injection.granted": handleCollabInjectionGranted,
|
|
4227
|
+
"eternal.iteration": handleEternalIteration,
|
|
3678
4228
|
"working_dir.changed": handleWorkingDirChanged,
|
|
3679
4229
|
"model.refine_result": handleModelRefineResult,
|
|
3680
4230
|
"git.info": handleGitInfo,
|
|
@@ -3862,6 +4412,30 @@ var WS_HANDLERS = {
|
|
|
3862
4412
|
"todos.cleared": (_msg) => {
|
|
3863
4413
|
useSessionStore.getState().setTodos([]);
|
|
3864
4414
|
},
|
|
4415
|
+
"agent.timeline.message": (msg) => {
|
|
4416
|
+
const p = msg.payload;
|
|
4417
|
+
useFleetStore.getState().pushAgentTimelineEntry({
|
|
4418
|
+
subagentId: p.subagentId,
|
|
4419
|
+
agentName: p.agentName,
|
|
4420
|
+
content: p.content.slice(0, 200),
|
|
4421
|
+
kind: p.kind,
|
|
4422
|
+
iteration: p.iteration,
|
|
4423
|
+
ts: p.ts,
|
|
4424
|
+
toolName: p.toolName
|
|
4425
|
+
});
|
|
4426
|
+
},
|
|
4427
|
+
"agent.status_changed": (msg) => {
|
|
4428
|
+
const p = msg.payload;
|
|
4429
|
+
useFleetStore.getState().pushAgentTimelineEntry({
|
|
4430
|
+
subagentId: p.subagentId,
|
|
4431
|
+
agentName: p.agentName,
|
|
4432
|
+
content: p.summary ?? p.status,
|
|
4433
|
+
kind: "status",
|
|
4434
|
+
iteration: 0,
|
|
4435
|
+
ts: p.ts,
|
|
4436
|
+
status: p.status
|
|
4437
|
+
});
|
|
4438
|
+
},
|
|
3865
4439
|
"tasks.updated": (msg) => {
|
|
3866
4440
|
},
|
|
3867
4441
|
"plan.updated": (msg) => {
|
|
@@ -4912,6 +5486,8 @@ function AutoPhaseView({ onClose }) {
|
|
|
4912
5486
|
const overallPercent = useAutoPhaseStore((s) => s.overallPercent);
|
|
4913
5487
|
const autonomous = useAutoPhaseStore((s) => s.autonomous);
|
|
4914
5488
|
const title = useAutoPhaseStore((s) => s.title);
|
|
5489
|
+
const status = useAutoPhaseStore((s) => s.status);
|
|
5490
|
+
const lastError = useAutoPhaseStore((s) => s.lastError);
|
|
4915
5491
|
const worktrees = useWorktreeStore((s) => s.worktrees);
|
|
4916
5492
|
const baseBranch = useWorktreeStore((s) => s.baseBranch);
|
|
4917
5493
|
const [goal, setGoal] = useState3("");
|
|
@@ -4936,8 +5512,8 @@ function AutoPhaseView({ onClose }) {
|
|
|
4936
5512
|
client2?.send?.({ type: "autophase.toggleAutonomous", payload: {} });
|
|
4937
5513
|
}, [client2]);
|
|
4938
5514
|
const handleTaskStatusChange = useCallback2(
|
|
4939
|
-
(taskId,
|
|
4940
|
-
client2?.send?.({ type: "autophase.taskStatus", payload: { taskId, status } });
|
|
5515
|
+
(taskId, status2) => {
|
|
5516
|
+
client2?.send?.({ type: "autophase.taskStatus", payload: { taskId, status: status2 } });
|
|
4941
5517
|
},
|
|
4942
5518
|
[client2]
|
|
4943
5519
|
);
|
|
@@ -4957,7 +5533,18 @@ function AutoPhaseView({ onClose }) {
|
|
|
4957
5533
|
overallPercent,
|
|
4958
5534
|
"% complete"
|
|
4959
5535
|
] })
|
|
4960
|
-
] })
|
|
5536
|
+
] }),
|
|
5537
|
+
hasPhases && /* @__PURE__ */ jsx10(
|
|
5538
|
+
"span",
|
|
5539
|
+
{
|
|
5540
|
+
className: cn(
|
|
5541
|
+
"rounded border px-2 py-0.5 text-[11px] font-medium capitalize",
|
|
5542
|
+
status === "failed" ? "border-destructive/40 bg-destructive/10 text-destructive" : status === "paused" || status === "stopped" ? "border-amber-500/40 bg-amber-500/10 text-amber-700 dark:text-amber-300" : status === "completed" ? "border-green-500/40 bg-green-500/10 text-green-700 dark:text-green-300" : "border-primary/30 bg-primary/10 text-primary"
|
|
5543
|
+
),
|
|
5544
|
+
title: lastError ?? void 0,
|
|
5545
|
+
children: status
|
|
5546
|
+
}
|
|
5547
|
+
)
|
|
4961
5548
|
] }),
|
|
4962
5549
|
/* @__PURE__ */ jsx10(Button, { variant: "ghost", size: "icon", onClick: onClose, children: /* @__PURE__ */ jsx10(X2, { className: "h-4 w-4" }) })
|
|
4963
5550
|
] }),
|
|
@@ -5316,7 +5903,7 @@ var SLASH_COMMANDS = [
|
|
|
5316
5903
|
{ name: "/f2", category: "App", description: "Fleet orchestration monitor", hidden: true },
|
|
5317
5904
|
{ name: "/f3", category: "App", description: "Agents live monitor", hidden: true },
|
|
5318
5905
|
{ name: "/f4", category: "App", description: "Worktree monitor", hidden: true },
|
|
5319
|
-
{ name: "/f5", category: "App", description: "
|
|
5906
|
+
{ name: "/f5", category: "App", description: "Plan panel", hidden: true },
|
|
5320
5907
|
{ name: "/f6", category: "App", description: "Todos monitor overlay", hidden: true },
|
|
5321
5908
|
{ name: "/f7", category: "App", description: "Queue panel", hidden: true },
|
|
5322
5909
|
{ name: "/f8", category: "App", description: "Process list overlay", hidden: true },
|
|
@@ -6093,6 +6680,12 @@ function runChatSlashCommand(options) {
|
|
|
6093
6680
|
const head = (sp === -1 ? trimmed : trimmed.slice(0, sp)).toLowerCase();
|
|
6094
6681
|
const args = sp === -1 ? "" : trimmed.slice(sp + 1).trim();
|
|
6095
6682
|
const cmd = head;
|
|
6683
|
+
const openWorkTab = (tab) => {
|
|
6684
|
+
const ui = useUIStore.getState();
|
|
6685
|
+
ui.setCurrentView("chat");
|
|
6686
|
+
ui.setDockSection("work");
|
|
6687
|
+
ui.setWorkDashboardTab(tab);
|
|
6688
|
+
};
|
|
6096
6689
|
switch (cmd) {
|
|
6097
6690
|
case "/help": {
|
|
6098
6691
|
const lines = [
|
|
@@ -6270,7 +6863,7 @@ _Pass \`/working-dir <path>\` to change it._` : "Working directory unknown. Pass
|
|
|
6270
6863
|
case "/plan":
|
|
6271
6864
|
ws.getPlan();
|
|
6272
6865
|
setCurrentView("chat");
|
|
6273
|
-
|
|
6866
|
+
openWorkTab("plan");
|
|
6274
6867
|
return true;
|
|
6275
6868
|
case "/todos": {
|
|
6276
6869
|
const sub = args.toLowerCase();
|
|
@@ -6278,6 +6871,7 @@ _Pass \`/working-dir <path>\` to change it._` : "Working directory unknown. Pass
|
|
|
6278
6871
|
client2?.clearTodos?.();
|
|
6279
6872
|
return true;
|
|
6280
6873
|
}
|
|
6874
|
+
openWorkTab("todos");
|
|
6281
6875
|
const list = useSessionStore.getState().todos;
|
|
6282
6876
|
if (list.length === 0) {
|
|
6283
6877
|
addMessage({
|
|
@@ -6398,7 +6992,7 @@ ${err}` : "Investigate the most recent error or failing test, find the root caus
|
|
|
6398
6992
|
"/f2": "fleetMonitor",
|
|
6399
6993
|
"/f3": "agentsMonitor",
|
|
6400
6994
|
"/f4": "worktreeMonitor",
|
|
6401
|
-
"/f5": "
|
|
6995
|
+
"/f5": "planPanel",
|
|
6402
6996
|
"/f6": "todosMonitor",
|
|
6403
6997
|
"/f7": "queuePanel",
|
|
6404
6998
|
"/f8": "processList",
|
|
@@ -6407,7 +7001,7 @@ ${err}` : "Investigate the most recent error or failing test, find the root caus
|
|
|
6407
7001
|
"/f11": "coordinatorMonitor",
|
|
6408
7002
|
"/f12": "statuslinePicker"
|
|
6409
7003
|
};
|
|
6410
|
-
const panel = panelMap[cmd];
|
|
7004
|
+
const panel = cmd === "/f" && args ? panelMap[`/f${args.trim()}`] : panelMap[cmd];
|
|
6411
7005
|
if (!panel) {
|
|
6412
7006
|
const lines = [
|
|
6413
7007
|
"\u{1F39B}\uFE0F **F-key panels**",
|
|
@@ -6416,7 +7010,7 @@ ${err}` : "Investigate the most recent error or failing test, find the root caus
|
|
|
6416
7010
|
"/f 2 \u2014 Fleet orchestration monitor",
|
|
6417
7011
|
"/f 3 \u2014 Agents live monitor",
|
|
6418
7012
|
"/f 4 \u2014 Worktree monitor",
|
|
6419
|
-
"/f 5 \u2014
|
|
7013
|
+
"/f 5 \u2014 Plan panel",
|
|
6420
7014
|
"/f 6 \u2014 Todos monitor overlay",
|
|
6421
7015
|
"/f 7 \u2014 Queue panel",
|
|
6422
7016
|
"/f 8 \u2014 Process list overlay",
|
|
@@ -6431,6 +7025,13 @@ ${err}` : "Investigate the most recent error or failing test, find the root caus
|
|
|
6431
7025
|
return true;
|
|
6432
7026
|
}
|
|
6433
7027
|
const ui = useUIStore.getState();
|
|
7028
|
+
ui.setCurrentView("chat");
|
|
7029
|
+
ui.setDockCustomizeOpen(false);
|
|
7030
|
+
if (panel === "projectPicker") {
|
|
7031
|
+
ui.setSidebarOpen(true);
|
|
7032
|
+
ui.selectActivity("projects");
|
|
7033
|
+
return true;
|
|
7034
|
+
}
|
|
6434
7035
|
if (panel === "fleetMonitor") {
|
|
6435
7036
|
ui.setFleetMonitorOpen(true);
|
|
6436
7037
|
return true;
|
|
@@ -6439,6 +7040,21 @@ ${err}` : "Investigate the most recent error or failing test, find the root caus
|
|
|
6439
7040
|
ui.setAgentsMonitorOpen(true);
|
|
6440
7041
|
return true;
|
|
6441
7042
|
}
|
|
7043
|
+
if (panel === "worktreeMonitor") {
|
|
7044
|
+
ui.setDockSection("worktrees");
|
|
7045
|
+
return true;
|
|
7046
|
+
}
|
|
7047
|
+
if (panel === "planPanel") {
|
|
7048
|
+
ws.getPlan();
|
|
7049
|
+
ui.setDockSection("work");
|
|
7050
|
+
ui.setWorkDashboardTab("plan");
|
|
7051
|
+
return true;
|
|
7052
|
+
}
|
|
7053
|
+
if (panel === "todosMonitor") {
|
|
7054
|
+
ui.setDockSection("work");
|
|
7055
|
+
ui.setWorkDashboardTab("todos");
|
|
7056
|
+
return true;
|
|
7057
|
+
}
|
|
6442
7058
|
if (panel === "queuePanel") {
|
|
6443
7059
|
ui.setQueuePanelOpen(true);
|
|
6444
7060
|
return true;
|
|
@@ -6447,10 +7063,27 @@ ${err}` : "Investigate the most recent error or failing test, find the root caus
|
|
|
6447
7063
|
ui.setProcessMonitorOpen(true);
|
|
6448
7064
|
return true;
|
|
6449
7065
|
}
|
|
6450
|
-
|
|
6451
|
-
|
|
6452
|
-
|
|
6453
|
-
|
|
7066
|
+
if (panel === "goalPanel") {
|
|
7067
|
+
client2?.send?.({ type: "goal.get" });
|
|
7068
|
+
ui.setDockSection("goal");
|
|
7069
|
+
return true;
|
|
7070
|
+
}
|
|
7071
|
+
if (panel === "sessionsPanel") {
|
|
7072
|
+
ws.listSessions(50);
|
|
7073
|
+
setCurrentView("sessions");
|
|
7074
|
+
return true;
|
|
7075
|
+
}
|
|
7076
|
+
if (panel === "coordinatorMonitor") {
|
|
7077
|
+
ui.setSidebarOpen(true);
|
|
7078
|
+
ui.selectActivity("officemap");
|
|
7079
|
+
ui.setCurrentView("officemap");
|
|
7080
|
+
return true;
|
|
7081
|
+
}
|
|
7082
|
+
if (panel === "statuslinePicker") {
|
|
7083
|
+
ui.setDockSection("work");
|
|
7084
|
+
ui.setDockCustomizeOpen(true);
|
|
7085
|
+
return true;
|
|
7086
|
+
}
|
|
6454
7087
|
return true;
|
|
6455
7088
|
}
|
|
6456
7089
|
default:
|
|
@@ -11223,6 +11856,72 @@ function ChatView() {
|
|
|
11223
11856
|
] });
|
|
11224
11857
|
}
|
|
11225
11858
|
|
|
11859
|
+
// src/lib/completion.ts
|
|
11860
|
+
var LANG_MAP = {
|
|
11861
|
+
ts: "typescript",
|
|
11862
|
+
tsx: "typescript",
|
|
11863
|
+
js: "javascript",
|
|
11864
|
+
jsx: "javascript",
|
|
11865
|
+
json: "json",
|
|
11866
|
+
css: "css",
|
|
11867
|
+
html: "html",
|
|
11868
|
+
svg: "xml",
|
|
11869
|
+
md: "markdown",
|
|
11870
|
+
yml: "yaml",
|
|
11871
|
+
yaml: "yaml",
|
|
11872
|
+
toml: "toml",
|
|
11873
|
+
sh: "shell",
|
|
11874
|
+
bash: "shell",
|
|
11875
|
+
ps1: "powershell",
|
|
11876
|
+
py: "python",
|
|
11877
|
+
rs: "rust",
|
|
11878
|
+
go: "go",
|
|
11879
|
+
rb: "ruby",
|
|
11880
|
+
java: "java",
|
|
11881
|
+
c: "c",
|
|
11882
|
+
cpp: "cpp",
|
|
11883
|
+
h: "c",
|
|
11884
|
+
hpp: "cpp",
|
|
11885
|
+
sql: "sql",
|
|
11886
|
+
xml: "xml"
|
|
11887
|
+
};
|
|
11888
|
+
var COMPLETION_LANGUAGES = Array.from(new Set(Object.values(LANG_MAP))).filter((lang) => lang !== "plaintext");
|
|
11889
|
+
var COMPLETION_PREFIX_CHARS = 12e3;
|
|
11890
|
+
var COMPLETION_SUFFIX_CHARS = 4e3;
|
|
11891
|
+
var COMPLETION_TIMEOUT_MS = 5e3;
|
|
11892
|
+
var COMPLETION_CACHE_TTL_MS = 1e4;
|
|
11893
|
+
var COMPLETION_DOCUMENT_CHARS = 5e5;
|
|
11894
|
+
function getLanguage(filePath) {
|
|
11895
|
+
const ext = filePath.split(".").pop()?.toLowerCase() ?? "";
|
|
11896
|
+
return LANG_MAP[ext] ?? "plaintext";
|
|
11897
|
+
}
|
|
11898
|
+
function currentToken(linePrefix) {
|
|
11899
|
+
return linePrefix.match(/([A-Za-z_$][\w$]*)$/)?.[1] ?? "";
|
|
11900
|
+
}
|
|
11901
|
+
function shouldAskCompletionServer(trigger, tokenText) {
|
|
11902
|
+
if (trigger.triggerCharacter) return true;
|
|
11903
|
+
return tokenText.length >= 3;
|
|
11904
|
+
}
|
|
11905
|
+
function shouldAllowCompletionLlm(trigger, tokenText) {
|
|
11906
|
+
if (trigger.triggerCharacter === ".") return true;
|
|
11907
|
+
if (trigger.triggerCharacter) return false;
|
|
11908
|
+
return /^(findBy|findAllBy|create|update|delete|remove|get[A-Z_]|set[A-Z_]|use[A-Z_])/.test(
|
|
11909
|
+
tokenText
|
|
11910
|
+
);
|
|
11911
|
+
}
|
|
11912
|
+
function buildCompletionCacheKey(input) {
|
|
11913
|
+
return [
|
|
11914
|
+
input.filePath,
|
|
11915
|
+
input.language,
|
|
11916
|
+
input.lineNumber,
|
|
11917
|
+
input.column,
|
|
11918
|
+
input.versionId ?? "",
|
|
11919
|
+
input.triggerCharacter ?? "",
|
|
11920
|
+
input.linePrefix.slice(-160),
|
|
11921
|
+
input.suffix.slice(0, 160)
|
|
11922
|
+
].join("\0");
|
|
11923
|
+
}
|
|
11924
|
+
|
|
11226
11925
|
// src/components/CodeEditor.tsx
|
|
11227
11926
|
import { X as X8, Circle as Circle3 } from "lucide-react";
|
|
11228
11927
|
import { useCallback as useCallback11, useEffect as useEffect21, useMemo as useMemo8, useRef as useRef16 } from "react";
|
|
@@ -11587,37 +12286,43 @@ function getMonacoTheme() {
|
|
|
11587
12286
|
// src/components/CodeEditor.tsx
|
|
11588
12287
|
import { jsx as jsx37, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
11589
12288
|
loader.config({ monaco: monaco2 });
|
|
11590
|
-
|
|
11591
|
-
|
|
11592
|
-
|
|
11593
|
-
|
|
11594
|
-
|
|
11595
|
-
|
|
11596
|
-
|
|
11597
|
-
|
|
11598
|
-
|
|
11599
|
-
|
|
11600
|
-
|
|
11601
|
-
|
|
11602
|
-
|
|
11603
|
-
|
|
11604
|
-
|
|
11605
|
-
|
|
11606
|
-
|
|
11607
|
-
|
|
11608
|
-
|
|
11609
|
-
|
|
11610
|
-
|
|
11611
|
-
|
|
11612
|
-
|
|
11613
|
-
|
|
11614
|
-
|
|
11615
|
-
|
|
11616
|
-
|
|
11617
|
-
|
|
11618
|
-
|
|
11619
|
-
|
|
11620
|
-
|
|
12289
|
+
function completionKind(kind) {
|
|
12290
|
+
switch (kind) {
|
|
12291
|
+
case "method":
|
|
12292
|
+
return monaco2.languages.CompletionItemKind.Method;
|
|
12293
|
+
case "function":
|
|
12294
|
+
return monaco2.languages.CompletionItemKind.Function;
|
|
12295
|
+
case "constructor":
|
|
12296
|
+
return monaco2.languages.CompletionItemKind.Constructor;
|
|
12297
|
+
case "field":
|
|
12298
|
+
return monaco2.languages.CompletionItemKind.Field;
|
|
12299
|
+
case "variable":
|
|
12300
|
+
return monaco2.languages.CompletionItemKind.Variable;
|
|
12301
|
+
case "class":
|
|
12302
|
+
return monaco2.languages.CompletionItemKind.Class;
|
|
12303
|
+
case "interface":
|
|
12304
|
+
return monaco2.languages.CompletionItemKind.Interface;
|
|
12305
|
+
case "module":
|
|
12306
|
+
return monaco2.languages.CompletionItemKind.Module;
|
|
12307
|
+
case "property":
|
|
12308
|
+
return monaco2.languages.CompletionItemKind.Property;
|
|
12309
|
+
case "unit":
|
|
12310
|
+
return monaco2.languages.CompletionItemKind.Unit;
|
|
12311
|
+
case "value":
|
|
12312
|
+
return monaco2.languages.CompletionItemKind.Value;
|
|
12313
|
+
case "enum":
|
|
12314
|
+
return monaco2.languages.CompletionItemKind.Enum;
|
|
12315
|
+
case "keyword":
|
|
12316
|
+
return monaco2.languages.CompletionItemKind.Keyword;
|
|
12317
|
+
case "snippet":
|
|
12318
|
+
return monaco2.languages.CompletionItemKind.Snippet;
|
|
12319
|
+
case "file":
|
|
12320
|
+
return monaco2.languages.CompletionItemKind.File;
|
|
12321
|
+
case "reference":
|
|
12322
|
+
return monaco2.languages.CompletionItemKind.Reference;
|
|
12323
|
+
default:
|
|
12324
|
+
return monaco2.languages.CompletionItemKind.Text;
|
|
12325
|
+
}
|
|
11621
12326
|
}
|
|
11622
12327
|
function EditorTabs() {
|
|
11623
12328
|
const openFiles = useFileStore((s) => s.openFiles);
|
|
@@ -11672,16 +12377,120 @@ function CodeEditor() {
|
|
|
11672
12377
|
const updateContent = useFileStore((s) => s.updateContent);
|
|
11673
12378
|
const { theme: appTheme } = useTheme();
|
|
11674
12379
|
const editorRef = useRef16(null);
|
|
12380
|
+
const activeFilePathRef = useRef16(activeFilePath);
|
|
12381
|
+
const completionCacheRef = useRef16(/* @__PURE__ */ new Map());
|
|
11675
12382
|
const activeFile = useMemo8(
|
|
11676
12383
|
() => openFiles.find((f) => f.path === activeFilePath) ?? null,
|
|
11677
12384
|
[openFiles, activeFilePath]
|
|
11678
12385
|
);
|
|
11679
12386
|
const language = activeFilePath ? getLanguage(activeFilePath) : "plaintext";
|
|
11680
12387
|
const monacoTheme = getMonacoTheme();
|
|
12388
|
+
useEffect21(() => {
|
|
12389
|
+
activeFilePathRef.current = activeFilePath;
|
|
12390
|
+
}, [activeFilePath]);
|
|
11681
12391
|
useEffect21(() => {
|
|
11682
12392
|
const resolved = getMonacoTheme();
|
|
11683
12393
|
monaco2.editor.setTheme(resolved);
|
|
11684
12394
|
}, [appTheme]);
|
|
12395
|
+
useEffect21(() => {
|
|
12396
|
+
const disposables = COMPLETION_LANGUAGES.map(
|
|
12397
|
+
(registeredLanguage) => monaco2.languages.registerCompletionItemProvider(registeredLanguage, {
|
|
12398
|
+
triggerCharacters: [".", "_"],
|
|
12399
|
+
provideCompletionItems: async (model, position, context, token) => {
|
|
12400
|
+
const filePath = activeFilePathRef.current;
|
|
12401
|
+
if (!filePath) return { suggestions: [] };
|
|
12402
|
+
const offset = model.getOffsetAt(position);
|
|
12403
|
+
const value = model.getValue();
|
|
12404
|
+
const prefix = value.slice(Math.max(0, offset - COMPLETION_PREFIX_CHARS), offset);
|
|
12405
|
+
const suffix = value.slice(offset, offset + COMPLETION_SUFFIX_CHARS);
|
|
12406
|
+
const linePrefix = model.getLineContent(position.lineNumber).slice(0, Math.max(0, position.column - 1));
|
|
12407
|
+
const tokenText = currentToken(linePrefix);
|
|
12408
|
+
const trigger = {
|
|
12409
|
+
triggerCharacter: context.triggerCharacter,
|
|
12410
|
+
triggerKind: context.triggerKind
|
|
12411
|
+
};
|
|
12412
|
+
if (!shouldAskCompletionServer(trigger, tokenText)) return { suggestions: [] };
|
|
12413
|
+
const requestId = `cmp_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
12414
|
+
const word = model.getWordUntilPosition(position);
|
|
12415
|
+
const range = {
|
|
12416
|
+
startLineNumber: position.lineNumber,
|
|
12417
|
+
endLineNumber: position.lineNumber,
|
|
12418
|
+
startColumn: word.startColumn,
|
|
12419
|
+
endColumn: position.column
|
|
12420
|
+
};
|
|
12421
|
+
const client2 = getWSClient(useConfigStore.getState().wsUrl);
|
|
12422
|
+
const toSuggestions = (items) => items.map((item, index) => ({
|
|
12423
|
+
label: item.label,
|
|
12424
|
+
kind: completionKind(item.kind),
|
|
12425
|
+
insertText: item.insertText,
|
|
12426
|
+
detail: item.detail ?? (item.source ? `WrongStack ${item.source}` : void 0),
|
|
12427
|
+
documentation: item.documentation,
|
|
12428
|
+
sortText: item.sortText ?? `${String(index).padStart(3, "0")}-${item.label}`,
|
|
12429
|
+
range,
|
|
12430
|
+
insertTextRules: item.kind === "snippet" ? monaco2.languages.CompletionItemInsertTextRule.InsertAsSnippet : void 0
|
|
12431
|
+
}));
|
|
12432
|
+
const cacheKey = buildCompletionCacheKey({
|
|
12433
|
+
filePath,
|
|
12434
|
+
language: model.getLanguageId(),
|
|
12435
|
+
lineNumber: position.lineNumber,
|
|
12436
|
+
column: position.column,
|
|
12437
|
+
versionId: model.getVersionId(),
|
|
12438
|
+
triggerCharacter: context.triggerCharacter,
|
|
12439
|
+
linePrefix,
|
|
12440
|
+
suffix
|
|
12441
|
+
});
|
|
12442
|
+
const cached = completionCacheRef.current.get(cacheKey);
|
|
12443
|
+
if (cached && cached.expiresAt > Date.now()) {
|
|
12444
|
+
return { suggestions: toSuggestions(cached.items) };
|
|
12445
|
+
}
|
|
12446
|
+
return await new Promise(
|
|
12447
|
+
(resolve) => {
|
|
12448
|
+
let settled = false;
|
|
12449
|
+
let unsubscribe = () => {
|
|
12450
|
+
};
|
|
12451
|
+
let cancelDisposable = null;
|
|
12452
|
+
let timer;
|
|
12453
|
+
const finish = (suggestions) => {
|
|
12454
|
+
if (settled) return;
|
|
12455
|
+
settled = true;
|
|
12456
|
+
unsubscribe();
|
|
12457
|
+
if (timer !== void 0) window.clearTimeout(timer);
|
|
12458
|
+
cancelDisposable?.dispose();
|
|
12459
|
+
resolve({ suggestions });
|
|
12460
|
+
};
|
|
12461
|
+
unsubscribe = client2.on("completion.result", (message) => {
|
|
12462
|
+
const result = message;
|
|
12463
|
+
if (result.payload.requestId !== requestId) return;
|
|
12464
|
+
completionCacheRef.current.set(cacheKey, {
|
|
12465
|
+
expiresAt: Date.now() + COMPLETION_CACHE_TTL_MS,
|
|
12466
|
+
items: result.payload.items
|
|
12467
|
+
});
|
|
12468
|
+
finish(toSuggestions(result.payload.items));
|
|
12469
|
+
});
|
|
12470
|
+
timer = window.setTimeout(() => finish([]), COMPLETION_TIMEOUT_MS);
|
|
12471
|
+
cancelDisposable = token.onCancellationRequested(() => finish([]));
|
|
12472
|
+
client2.requestCompletion({
|
|
12473
|
+
requestId,
|
|
12474
|
+
filePath,
|
|
12475
|
+
language: model.getLanguageId(),
|
|
12476
|
+
lineNumber: position.lineNumber,
|
|
12477
|
+
column: position.column,
|
|
12478
|
+
content: value.length <= COMPLETION_DOCUMENT_CHARS ? value : void 0,
|
|
12479
|
+
prefix,
|
|
12480
|
+
suffix,
|
|
12481
|
+
triggerCharacter: context.triggerCharacter,
|
|
12482
|
+
triggerKind: context.triggerKind,
|
|
12483
|
+
allowLlm: shouldAllowCompletionLlm(trigger, tokenText)
|
|
12484
|
+
});
|
|
12485
|
+
}
|
|
12486
|
+
);
|
|
12487
|
+
}
|
|
12488
|
+
})
|
|
12489
|
+
);
|
|
12490
|
+
return () => {
|
|
12491
|
+
disposables.forEach((disposable) => disposable.dispose());
|
|
12492
|
+
};
|
|
12493
|
+
}, []);
|
|
11685
12494
|
const handleMount = useCallback11((editor4) => {
|
|
11686
12495
|
editorRef.current = editor4;
|
|
11687
12496
|
monaco2.editor.setTheme(getMonacoTheme());
|
|
@@ -13290,12 +14099,38 @@ function MCPSection() {
|
|
|
13290
14099
|
if (msg.type === "mcp.server.connected") {
|
|
13291
14100
|
const p = msg.payload;
|
|
13292
14101
|
setServers(
|
|
13293
|
-
(prev) => prev.map(
|
|
14102
|
+
(prev) => prev.map(
|
|
14103
|
+
(s) => s.name === p.name ? { ...s, status: "connected", pid: p.pid, error: void 0, lastError: void 0 } : s
|
|
14104
|
+
)
|
|
13294
14105
|
);
|
|
13295
14106
|
setPendingOp(null);
|
|
13296
14107
|
toast.success(`Server "${p.name}" connected`);
|
|
13297
14108
|
}
|
|
13298
14109
|
};
|
|
14110
|
+
const handleMcpServerReconnected = (msg) => {
|
|
14111
|
+
if (msg.type === "mcp.server.reconnected") {
|
|
14112
|
+
const p = msg.payload;
|
|
14113
|
+
setServers(
|
|
14114
|
+
(prev) => prev.map(
|
|
14115
|
+
(s) => s.name === p.name ? { ...s, status: "connected", error: void 0, lastError: void 0 } : s
|
|
14116
|
+
)
|
|
14117
|
+
);
|
|
14118
|
+
setPendingOp(null);
|
|
14119
|
+
toast.success(`Server "${p.name}" reconnected`);
|
|
14120
|
+
}
|
|
14121
|
+
};
|
|
14122
|
+
const handleMcpServerDisconnected = (msg) => {
|
|
14123
|
+
if (msg.type === "mcp.server.disconnected") {
|
|
14124
|
+
const p = msg.payload;
|
|
14125
|
+
setServers(
|
|
14126
|
+
(prev) => prev.map(
|
|
14127
|
+
(s) => s.name === p.name ? { ...s, status: "error", error: p.reason, lastError: p.reason, pid: void 0 } : s
|
|
14128
|
+
)
|
|
14129
|
+
);
|
|
14130
|
+
setPendingOp(null);
|
|
14131
|
+
toast.warn(`Server "${p.name}" disconnected: ${p.reason}`);
|
|
14132
|
+
}
|
|
14133
|
+
};
|
|
13299
14134
|
const handleMcpServerError = (msg) => {
|
|
13300
14135
|
if (msg.type === "mcp.server.error") {
|
|
13301
14136
|
const p = msg.payload;
|
|
@@ -13325,6 +14160,8 @@ function MCPSection() {
|
|
|
13325
14160
|
const off8 = ws.client.on("mcp.server.connected", handleMcpServerConnected);
|
|
13326
14161
|
const off9 = ws.client.on("mcp.server.error", handleMcpServerError);
|
|
13327
14162
|
const off10 = ws.client.on("mcp.operation_result", handleMcpOperationResult);
|
|
14163
|
+
const off11 = ws.client.on("mcp.server.reconnected", handleMcpServerReconnected);
|
|
14164
|
+
const off12 = ws.client.on("mcp.server.disconnected", handleMcpServerDisconnected);
|
|
13328
14165
|
setLoading(true);
|
|
13329
14166
|
ws.client?.listMcpServers();
|
|
13330
14167
|
return () => {
|
|
@@ -13338,6 +14175,8 @@ function MCPSection() {
|
|
|
13338
14175
|
off8?.();
|
|
13339
14176
|
off9?.();
|
|
13340
14177
|
off10?.();
|
|
14178
|
+
off11?.();
|
|
14179
|
+
off12?.();
|
|
13341
14180
|
};
|
|
13342
14181
|
}, [ws.client]);
|
|
13343
14182
|
const handleAddCustom = useCallback13(
|
|
@@ -15449,10 +16288,27 @@ var SHORTCUTS = [
|
|
|
15449
16288
|
{ keys: ["Ctrl", "K"], description: "Open command palette" },
|
|
15450
16289
|
{ keys: ["?"], description: "Show this shortcuts overlay" },
|
|
15451
16290
|
{ keys: ["Ctrl", "\\"], description: "Toggle sidebar" },
|
|
15452
|
-
{ keys: ["Ctrl", "1-
|
|
16291
|
+
{ keys: ["Ctrl", "1-9"], description: "Open side panel (Session, Agents, History, Files, Changes, Projects, Mailbox, Skills, Office Map)" },
|
|
15453
16292
|
{ keys: ["Ctrl", "/"], description: "Focus the message input" }
|
|
15454
16293
|
]
|
|
15455
16294
|
},
|
|
16295
|
+
{
|
|
16296
|
+
section: "TUI Panel Parity",
|
|
16297
|
+
items: [
|
|
16298
|
+
{ keys: ["F1"], description: "Project switcher" },
|
|
16299
|
+
{ keys: ["F2"], description: "Fleet monitor overlay" },
|
|
16300
|
+
{ keys: ["F3"], description: "Agents monitor overlay" },
|
|
16301
|
+
{ keys: ["F4"], description: "Worktree monitor" },
|
|
16302
|
+
{ keys: ["F5"], description: "Plan panel" },
|
|
16303
|
+
{ keys: ["F6"], description: "Todos panel" },
|
|
16304
|
+
{ keys: ["F7"], description: "Queue panel" },
|
|
16305
|
+
{ keys: ["F8"], description: "Process monitor" },
|
|
16306
|
+
{ keys: ["F9"], description: "Goal panel" },
|
|
16307
|
+
{ keys: ["F10"], description: "Sessions dashboard" },
|
|
16308
|
+
{ keys: ["F11"], description: "Coordinator office map" },
|
|
16309
|
+
{ keys: ["F12"], description: "Dock chip picker" }
|
|
16310
|
+
]
|
|
16311
|
+
},
|
|
15456
16312
|
{
|
|
15457
16313
|
section: "Fleet & Agents",
|
|
15458
16314
|
items: [
|
|
@@ -18998,7 +19854,7 @@ function SidePanel() {
|
|
|
18998
19854
|
|
|
18999
19855
|
// src/components/WorkspaceDock.tsx
|
|
19000
19856
|
import { Bot as Bot10, GitBranch as GitBranch3, ListTodo as ListTodo3, Maximize2 as Maximize22, Rocket as Rocket4, SlidersHorizontal as SlidersHorizontal2, Target as Target2, Users as Users4 } from "lucide-react";
|
|
19001
|
-
import { useCallback as useCallback30, useEffect as useEffect47, useMemo as useMemo16, useRef as useRef27, useState as
|
|
19857
|
+
import { useCallback as useCallback30, useEffect as useEffect47, useMemo as useMemo16, useRef as useRef27, useState as useState49 } from "react";
|
|
19002
19858
|
|
|
19003
19859
|
// src/hooks/useGitInfo.ts
|
|
19004
19860
|
import { useCallback as useCallback25, useEffect as useEffect41, useRef as useRef23 } from "react";
|
|
@@ -19020,18 +19876,38 @@ function useGitInfo() {
|
|
|
19020
19876
|
}
|
|
19021
19877
|
|
|
19022
19878
|
// src/components/CollabPanel.tsx
|
|
19023
|
-
import {
|
|
19879
|
+
import {
|
|
19880
|
+
Eye as Eye2,
|
|
19881
|
+
LogIn,
|
|
19882
|
+
LogOut,
|
|
19883
|
+
MessageSquareWarning,
|
|
19884
|
+
Pause as Pause5,
|
|
19885
|
+
Play as Play5,
|
|
19886
|
+
Syringe,
|
|
19887
|
+
UserPlus,
|
|
19888
|
+
Users as Users3
|
|
19889
|
+
} from "lucide-react";
|
|
19024
19890
|
import { useEffect as useEffect42, useState as useState44 } from "react";
|
|
19025
19891
|
import { jsx as jsx72, jsxs as jsxs65 } from "react/jsx-runtime";
|
|
19026
19892
|
function CollabPanel({ sessionId, className }) {
|
|
19027
19893
|
const [participants, setParticipants] = useState44([]);
|
|
19028
19894
|
const [joined, setJoined] = useState44(false);
|
|
19029
|
-
const [joinedRole, setJoinedRole] = useState44(
|
|
19895
|
+
const [joinedRole, setJoinedRole] = useState44(
|
|
19896
|
+
null
|
|
19897
|
+
);
|
|
19030
19898
|
const [error, setError] = useState44(null);
|
|
19031
19899
|
const [openAnnotationCount, setOpenAnnotationCount] = useState44(0);
|
|
19032
19900
|
const [paused, setPaused] = useState44(false);
|
|
19901
|
+
const [injectOpen, setInjectOpen] = useState44(false);
|
|
19902
|
+
const [injectToolUseId, setInjectToolUseId] = useState44("");
|
|
19903
|
+
const [injectContent, setInjectContent] = useState44("");
|
|
19904
|
+
const [injectIsError, setInjectIsError] = useState44(false);
|
|
19905
|
+
const [injectReason, setInjectReason] = useState44("");
|
|
19033
19906
|
const wsUrl = useConfigStore((s) => s.wsUrl);
|
|
19034
19907
|
const client2 = getWSClient(wsUrl);
|
|
19908
|
+
const pendingTools = useChatStore((s) => s.messages).filter(
|
|
19909
|
+
(m) => m.role === "tool" && m.toolResult === void 0 && !!m.toolUseId
|
|
19910
|
+
);
|
|
19035
19911
|
useEffect42(() => {
|
|
19036
19912
|
const offs = [];
|
|
19037
19913
|
offs.push(
|
|
@@ -19119,6 +19995,28 @@ function CollabPanel({ sessionId, className }) {
|
|
|
19119
19995
|
setJoined(false);
|
|
19120
19996
|
setParticipants([]);
|
|
19121
19997
|
};
|
|
19998
|
+
const handleGrantControl = (toParticipant) => {
|
|
19999
|
+
client2.send({ type: "collab.grant_control", payload: { sessionId, toParticipant } });
|
|
20000
|
+
};
|
|
20001
|
+
const handleInjectTool = () => {
|
|
20002
|
+
if (!injectToolUseId) return;
|
|
20003
|
+
client2.send({
|
|
20004
|
+
type: "collab.inject_tool",
|
|
20005
|
+
payload: {
|
|
20006
|
+
sessionId,
|
|
20007
|
+
toolUseId: injectToolUseId,
|
|
20008
|
+
content: injectContent,
|
|
20009
|
+
isError: injectIsError,
|
|
20010
|
+
reason: injectReason.trim() || "controller injection"
|
|
20011
|
+
}
|
|
20012
|
+
});
|
|
20013
|
+
setInjectOpen(false);
|
|
20014
|
+
setInjectToolUseId("");
|
|
20015
|
+
setInjectContent("");
|
|
20016
|
+
setInjectIsError(false);
|
|
20017
|
+
setInjectReason("");
|
|
20018
|
+
};
|
|
20019
|
+
const isController = joined && joinedRole === "controller";
|
|
19122
20020
|
if (participants.length === 0 && !error) {
|
|
19123
20021
|
return /* @__PURE__ */ jsxs65(
|
|
19124
20022
|
"div",
|
|
@@ -19209,7 +20107,7 @@ function CollabPanel({ sessionId, className }) {
|
|
|
19209
20107
|
"div",
|
|
19210
20108
|
{
|
|
19211
20109
|
className: cn(
|
|
19212
|
-
"flex items-center gap-2 px-3 py-2 rounded-md border border-emerald-500/40 bg-emerald-500/5",
|
|
20110
|
+
"relative flex items-center gap-2 px-3 py-2 rounded-md border border-emerald-500/40 bg-emerald-500/5",
|
|
19213
20111
|
className
|
|
19214
20112
|
),
|
|
19215
20113
|
children: [
|
|
@@ -19255,7 +20153,17 @@ function CollabPanel({ sessionId, className }) {
|
|
|
19255
20153
|
className: "inline-flex items-center gap-1 text-[10px] px-1.5 py-0.5 rounded bg-emerald-500/10 text-emerald-700 dark:text-emerald-300",
|
|
19256
20154
|
children: [
|
|
19257
20155
|
/* @__PURE__ */ jsx72(Eye2, { className: "w-3 h-3" }),
|
|
19258
|
-
p.role
|
|
20156
|
+
p.role,
|
|
20157
|
+
isController && p.role !== "controller" && /* @__PURE__ */ jsx72(
|
|
20158
|
+
"button",
|
|
20159
|
+
{
|
|
20160
|
+
type: "button",
|
|
20161
|
+
onClick: () => handleGrantControl(p.participantId),
|
|
20162
|
+
title: "Grant control \u2014 promote this participant to controller",
|
|
20163
|
+
className: "ml-0.5 inline-flex items-center rounded hover:bg-emerald-500/20 transition-colors",
|
|
20164
|
+
children: /* @__PURE__ */ jsx72(UserPlus, { className: "w-3 h-3" })
|
|
20165
|
+
}
|
|
20166
|
+
)
|
|
19259
20167
|
]
|
|
19260
20168
|
},
|
|
19261
20169
|
p.participantId
|
|
@@ -19265,31 +20173,46 @@ function CollabPanel({ sessionId, className }) {
|
|
|
19265
20173
|
participants.length - 3
|
|
19266
20174
|
] })
|
|
19267
20175
|
] }),
|
|
19268
|
-
|
|
19269
|
-
|
|
19270
|
-
|
|
19271
|
-
|
|
19272
|
-
|
|
19273
|
-
|
|
19274
|
-
|
|
19275
|
-
|
|
19276
|
-
|
|
19277
|
-
|
|
19278
|
-
|
|
19279
|
-
|
|
19280
|
-
|
|
19281
|
-
|
|
19282
|
-
|
|
19283
|
-
|
|
19284
|
-
|
|
19285
|
-
|
|
19286
|
-
|
|
19287
|
-
|
|
19288
|
-
|
|
19289
|
-
|
|
19290
|
-
|
|
19291
|
-
|
|
19292
|
-
|
|
20176
|
+
isController && /* @__PURE__ */ jsxs65("div", { className: "ml-auto flex items-center gap-1", children: [
|
|
20177
|
+
/* @__PURE__ */ jsxs65(
|
|
20178
|
+
"button",
|
|
20179
|
+
{
|
|
20180
|
+
type: "button",
|
|
20181
|
+
onClick: () => setInjectOpen((v) => !v),
|
|
20182
|
+
className: "inline-flex items-center gap-1 text-xs px-2 py-1 rounded border border-sky-500/40 bg-sky-500/10 text-sky-700 dark:text-sky-300 hover:bg-sky-500/20 transition-colors",
|
|
20183
|
+
title: "Inject a synthetic result for an in-flight tool call",
|
|
20184
|
+
children: [
|
|
20185
|
+
/* @__PURE__ */ jsx72(Syringe, { className: "w-3 h-3" }),
|
|
20186
|
+
"Inject"
|
|
20187
|
+
]
|
|
20188
|
+
}
|
|
20189
|
+
),
|
|
20190
|
+
paused ? /* @__PURE__ */ jsxs65(
|
|
20191
|
+
"button",
|
|
20192
|
+
{
|
|
20193
|
+
type: "button",
|
|
20194
|
+
onClick: handleResume,
|
|
20195
|
+
className: "inline-flex items-center gap-1 text-xs px-2 py-1 rounded border border-rose-500/40 bg-rose-500/10 text-rose-700 dark:text-rose-300 hover:bg-rose-500/20 transition-colors",
|
|
20196
|
+
title: "Resume the agent loop",
|
|
20197
|
+
children: [
|
|
20198
|
+
/* @__PURE__ */ jsx72(Play5, { className: "w-3 h-3" }),
|
|
20199
|
+
"Resume"
|
|
20200
|
+
]
|
|
20201
|
+
}
|
|
20202
|
+
) : /* @__PURE__ */ jsxs65(
|
|
20203
|
+
"button",
|
|
20204
|
+
{
|
|
20205
|
+
type: "button",
|
|
20206
|
+
onClick: handleRequestPause,
|
|
20207
|
+
className: "inline-flex items-center gap-1 text-xs px-2 py-1 rounded border border-amber-500/40 bg-amber-500/10 text-amber-700 dark:text-amber-300 hover:bg-amber-500/20 transition-colors",
|
|
20208
|
+
title: "Pause the agent before the next tool call",
|
|
20209
|
+
children: [
|
|
20210
|
+
/* @__PURE__ */ jsx72(Pause5, { className: "w-3 h-3" }),
|
|
20211
|
+
"Pause agent"
|
|
20212
|
+
]
|
|
20213
|
+
}
|
|
20214
|
+
)
|
|
20215
|
+
] }),
|
|
19293
20216
|
joined && joinedRole !== "controller" && /* @__PURE__ */ jsxs65(
|
|
19294
20217
|
"button",
|
|
19295
20218
|
{
|
|
@@ -19302,7 +20225,92 @@ function CollabPanel({ sessionId, className }) {
|
|
|
19302
20225
|
"Leave"
|
|
19303
20226
|
]
|
|
19304
20227
|
}
|
|
19305
|
-
)
|
|
20228
|
+
),
|
|
20229
|
+
isController && injectOpen && /* @__PURE__ */ jsxs65("div", { className: "absolute top-full left-0 right-0 mt-1 z-50 flex flex-col gap-2 p-3 rounded-md border border-sky-500/40 bg-card shadow-lg text-xs", children: [
|
|
20230
|
+
/* @__PURE__ */ jsxs65("div", { className: "flex items-center gap-2", children: [
|
|
20231
|
+
/* @__PURE__ */ jsx72(Syringe, { className: "w-3.5 h-3.5 text-sky-600 dark:text-sky-400" }),
|
|
20232
|
+
/* @__PURE__ */ jsx72("span", { className: "font-medium", children: "Inject tool result" }),
|
|
20233
|
+
/* @__PURE__ */ jsx72(
|
|
20234
|
+
"button",
|
|
20235
|
+
{
|
|
20236
|
+
type: "button",
|
|
20237
|
+
onClick: () => setInjectOpen(false),
|
|
20238
|
+
className: "ml-auto text-muted-foreground hover:text-foreground",
|
|
20239
|
+
children: "close"
|
|
20240
|
+
}
|
|
20241
|
+
)
|
|
20242
|
+
] }),
|
|
20243
|
+
/* @__PURE__ */ jsxs65("label", { className: "flex flex-col gap-1", children: [
|
|
20244
|
+
/* @__PURE__ */ jsx72("span", { className: "text-muted-foreground", children: "Target tool_use id" }),
|
|
20245
|
+
/* @__PURE__ */ jsx72(
|
|
20246
|
+
"input",
|
|
20247
|
+
{
|
|
20248
|
+
list: "collab-inject-tools",
|
|
20249
|
+
value: injectToolUseId,
|
|
20250
|
+
onChange: (e) => setInjectToolUseId(e.target.value),
|
|
20251
|
+
placeholder: "pick an in-flight call or type a tool_use id",
|
|
20252
|
+
className: "px-2 py-1 rounded border border-border bg-background font-mono"
|
|
20253
|
+
}
|
|
20254
|
+
),
|
|
20255
|
+
/* @__PURE__ */ jsx72("datalist", { id: "collab-inject-tools", children: pendingTools.map((m) => {
|
|
20256
|
+
const snip = m.toolInput === void 0 ? "" : ` \u2014 ${JSON.stringify(m.toolInput).slice(0, 40)}`;
|
|
20257
|
+
return /* @__PURE__ */ jsxs65("option", { value: m.toolUseId, children: [
|
|
20258
|
+
m.toolName ?? "tool",
|
|
20259
|
+
snip
|
|
20260
|
+
] }, m.toolUseId);
|
|
20261
|
+
}) }),
|
|
20262
|
+
pendingTools.length === 0 && /* @__PURE__ */ jsx72("span", { className: "text-[10px] text-muted-foreground", children: "No in-flight tool calls \u2014 type a tool_use id to pre-queue, or pause the agent first." })
|
|
20263
|
+
] }),
|
|
20264
|
+
/* @__PURE__ */ jsxs65("label", { className: "flex flex-col gap-1", children: [
|
|
20265
|
+
/* @__PURE__ */ jsx72("span", { className: "text-muted-foreground", children: "Result content" }),
|
|
20266
|
+
/* @__PURE__ */ jsx72(
|
|
20267
|
+
"textarea",
|
|
20268
|
+
{
|
|
20269
|
+
value: injectContent,
|
|
20270
|
+
onChange: (e) => setInjectContent(e.target.value),
|
|
20271
|
+
rows: 3,
|
|
20272
|
+
placeholder: "Synthetic tool result fed to the agent in place of running the tool",
|
|
20273
|
+
className: "px-2 py-1 rounded border border-border bg-background font-mono"
|
|
20274
|
+
}
|
|
20275
|
+
)
|
|
20276
|
+
] }),
|
|
20277
|
+
/* @__PURE__ */ jsxs65("div", { className: "flex items-center gap-3", children: [
|
|
20278
|
+
/* @__PURE__ */ jsxs65("label", { className: "flex items-center gap-1", children: [
|
|
20279
|
+
/* @__PURE__ */ jsx72(
|
|
20280
|
+
"input",
|
|
20281
|
+
{
|
|
20282
|
+
type: "checkbox",
|
|
20283
|
+
checked: injectIsError,
|
|
20284
|
+
onChange: (e) => setInjectIsError(e.target.checked)
|
|
20285
|
+
}
|
|
20286
|
+
),
|
|
20287
|
+
/* @__PURE__ */ jsx72("span", { children: "mark as error" })
|
|
20288
|
+
] }),
|
|
20289
|
+
/* @__PURE__ */ jsx72(
|
|
20290
|
+
"input",
|
|
20291
|
+
{
|
|
20292
|
+
type: "text",
|
|
20293
|
+
value: injectReason,
|
|
20294
|
+
onChange: (e) => setInjectReason(e.target.value),
|
|
20295
|
+
placeholder: "reason (audit log)",
|
|
20296
|
+
className: "flex-1 px-2 py-1 rounded border border-border bg-background"
|
|
20297
|
+
}
|
|
20298
|
+
)
|
|
20299
|
+
] }),
|
|
20300
|
+
/* @__PURE__ */ jsxs65(
|
|
20301
|
+
"button",
|
|
20302
|
+
{
|
|
20303
|
+
type: "button",
|
|
20304
|
+
onClick: handleInjectTool,
|
|
20305
|
+
disabled: !injectToolUseId,
|
|
20306
|
+
className: "self-end inline-flex items-center gap-1 text-xs px-3 py-1 rounded bg-sky-600 text-white hover:bg-sky-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
|
|
20307
|
+
children: [
|
|
20308
|
+
/* @__PURE__ */ jsx72(Syringe, { className: "w-3 h-3" }),
|
|
20309
|
+
"Queue injection"
|
|
20310
|
+
]
|
|
20311
|
+
}
|
|
20312
|
+
)
|
|
20313
|
+
] })
|
|
19306
20314
|
]
|
|
19307
20315
|
}
|
|
19308
20316
|
);
|
|
@@ -19601,9 +20609,6 @@ var DropdownMenuShortcut = ({ className, ...props }) => {
|
|
|
19601
20609
|
};
|
|
19602
20610
|
DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
|
|
19603
20611
|
|
|
19604
|
-
// src/components/WorkDashboard.tsx
|
|
19605
|
-
import { useState as useState49 } from "react";
|
|
19606
|
-
|
|
19607
20612
|
// src/components/TodosPanel.tsx
|
|
19608
20613
|
import { CheckCircle2 as CheckCircle212, Circle as Circle8, Clock as Clock11, Trash2 as Trash26 } from "lucide-react";
|
|
19609
20614
|
import { useCallback as useCallback27, useEffect as useEffect44, useRef as useRef24, useState as useState46 } from "react";
|
|
@@ -20066,7 +21071,8 @@ var TABS = [
|
|
|
20066
21071
|
{ id: "plan", label: "Plan", icon: "\u{1F5FA}\uFE0F" }
|
|
20067
21072
|
];
|
|
20068
21073
|
function WorkDashboard() {
|
|
20069
|
-
const
|
|
21074
|
+
const activeTab = useUIStore((s) => s.workDashboardTab);
|
|
21075
|
+
const setActiveTab = useUIStore((s) => s.setWorkDashboardTab);
|
|
20070
21076
|
return /* @__PURE__ */ jsxs71("div", { className: "rounded-lg border border-border bg-card/50 backdrop-blur-sm overflow-hidden", children: [
|
|
20071
21077
|
/* @__PURE__ */ jsx78("div", { className: "flex border-b border-border/50 bg-muted/30", children: TABS.map((tab) => /* @__PURE__ */ jsxs71(
|
|
20072
21078
|
"button",
|
|
@@ -20163,6 +21169,8 @@ function WorkspaceDock({ sessionId }) {
|
|
|
20163
21169
|
const setCurrentView = useUIStore((s) => s.setCurrentView);
|
|
20164
21170
|
const hiddenChips = useUIStore((s) => s.hiddenChips);
|
|
20165
21171
|
const toggleChipHidden = useUIStore((s) => s.toggleChipHidden);
|
|
21172
|
+
const dockCustomizeOpen = useUIStore((s) => s.dockCustomizeOpen);
|
|
21173
|
+
const setDockCustomizeOpen = useUIStore((s) => s.setDockCustomizeOpen);
|
|
20166
21174
|
const goal = useGoalStore((s) => s.goal);
|
|
20167
21175
|
const autoPhase = useAutoPhaseStore((s) => s);
|
|
20168
21176
|
const worktrees = useWorktreeStore((s) => s.worktrees);
|
|
@@ -20178,7 +21186,7 @@ function WorkspaceDock({ sessionId }) {
|
|
|
20178
21186
|
() => toggleAutoPhaseAutonomous(!autoPhase.autonomous),
|
|
20179
21187
|
[toggleAutoPhaseAutonomous, autoPhase.autonomous]
|
|
20180
21188
|
);
|
|
20181
|
-
const [worktreeView, setWorktreeView] =
|
|
21189
|
+
const [worktreeView, setWorktreeView] = useState49("graph");
|
|
20182
21190
|
const fleetTotal = fleetAgents.size;
|
|
20183
21191
|
const fleetRunning = useMemo16(
|
|
20184
21192
|
() => Array.from(fleetAgents.values()).filter((a) => a.status === "running").length,
|
|
@@ -20320,7 +21328,7 @@ function WorkspaceDock({ sessionId }) {
|
|
|
20320
21328
|
onClick: () => toggleDockSection("collab")
|
|
20321
21329
|
}
|
|
20322
21330
|
),
|
|
20323
|
-
/* @__PURE__ */ jsxs72(DropdownMenu, { children: [
|
|
21331
|
+
/* @__PURE__ */ jsxs72(DropdownMenu, { open: dockCustomizeOpen, onOpenChange: setDockCustomizeOpen, children: [
|
|
20324
21332
|
/* @__PURE__ */ jsx79(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx79(
|
|
20325
21333
|
"button",
|
|
20326
21334
|
{
|
|
@@ -20399,7 +21407,7 @@ function WorkspaceDock({ sessionId }) {
|
|
|
20399
21407
|
|
|
20400
21408
|
// src/components/AgentsMonitor.tsx
|
|
20401
21409
|
import { Bot as Bot11, ChevronLeft, ChevronRight as ChevronRight11, Cpu as Cpu13, Crown as Crown2, Loader2 as Loader215, Wrench as Wrench8, X as X15, Zap as Zap9 } from "lucide-react";
|
|
20402
|
-
import { useCallback as useCallback31, useEffect as useEffect48, useMemo as useMemo17, useState as
|
|
21410
|
+
import { useCallback as useCallback31, useEffect as useEffect48, useMemo as useMemo17, useState as useState50 } from "react";
|
|
20403
21411
|
import { Fragment as Fragment17, jsx as jsx80, jsxs as jsxs73 } from "react/jsx-runtime";
|
|
20404
21412
|
function fmtCost4(v) {
|
|
20405
21413
|
if (v <= 0) return "$0";
|
|
@@ -20524,7 +21532,7 @@ function AgentCard2({ agent, isLeader }) {
|
|
|
20524
21532
|
function AgentsMonitor({ onClose }) {
|
|
20525
21533
|
const fleetAgents = useFleetStore((s) => s.agents);
|
|
20526
21534
|
const leaderId = useFleetStore((s) => s.leaderId);
|
|
20527
|
-
const [selectedIdx, setSelectedIdx] =
|
|
21535
|
+
const [selectedIdx, setSelectedIdx] = useState50(0);
|
|
20528
21536
|
const fleetList = useMemo17(() => {
|
|
20529
21537
|
const arr = Array.from(fleetAgents.values());
|
|
20530
21538
|
arr.sort((x, y) => {
|
|
@@ -20678,7 +21686,7 @@ import {
|
|
|
20678
21686
|
XCircle as XCircle8,
|
|
20679
21687
|
Zap as Zap10
|
|
20680
21688
|
} from "lucide-react";
|
|
20681
|
-
import { useCallback as useCallback32, useEffect as useEffect49, useMemo as useMemo18, useState as
|
|
21689
|
+
import { useCallback as useCallback32, useEffect as useEffect49, useMemo as useMemo18, useState as useState51 } from "react";
|
|
20682
21690
|
|
|
20683
21691
|
// src/components/ui/concurrency-gauge.tsx
|
|
20684
21692
|
import { jsx as jsx81, jsxs as jsxs74 } from "react/jsx-runtime";
|
|
@@ -20721,6 +21729,7 @@ var KIND_ICONS = {
|
|
|
20721
21729
|
task_started: "\u25B6",
|
|
20722
21730
|
tool_executed: "\u26A1",
|
|
20723
21731
|
iteration_summary: "\u{1F504}",
|
|
21732
|
+
budget_warning: "!",
|
|
20724
21733
|
budget_extended: "\u26A1",
|
|
20725
21734
|
task_completed: "\u2705",
|
|
20726
21735
|
ctx_pct: "\u{1F4AC}",
|
|
@@ -20763,8 +21772,8 @@ function FleetAgentDetailPanel({
|
|
|
20763
21772
|
agent,
|
|
20764
21773
|
now
|
|
20765
21774
|
}) {
|
|
20766
|
-
const [copied, setCopied] =
|
|
20767
|
-
const [showFullToolLog, setShowFullToolLog] =
|
|
21775
|
+
const [copied, setCopied] = useState51(false);
|
|
21776
|
+
const [showFullToolLog, setShowFullToolLog] = useState51(false);
|
|
20768
21777
|
const meta2 = STATUS_META6[agent.status];
|
|
20769
21778
|
const active = agent.status === "running";
|
|
20770
21779
|
const handleCopy = useCallback32(async (text) => {
|
|
@@ -21085,8 +22094,9 @@ function FleetMonitor({
|
|
|
21085
22094
|
const fleetConcurrency = useFleetStore((s) => s.fleetConcurrency);
|
|
21086
22095
|
const fleetConcurrencyMax = useFleetStore((s) => s.fleetConcurrencyMax);
|
|
21087
22096
|
const eventTimeline = useFleetStore((s) => s.eventTimeline);
|
|
21088
|
-
const
|
|
21089
|
-
const [
|
|
22097
|
+
const fleetAgentTimeline = useFleetStore((s) => s.agentTimeline);
|
|
22098
|
+
const [selectedIdx, setSelectedIdx] = useState51(null);
|
|
22099
|
+
const [nowTick, setNowTick] = useState51(Date.now());
|
|
21090
22100
|
useEffect49(() => {
|
|
21091
22101
|
const t = setInterval(() => setNowTick(Date.now()), 1e3);
|
|
21092
22102
|
return () => clearInterval(t);
|
|
@@ -21243,9 +22253,26 @@ function FleetMonitor({
|
|
|
21243
22253
|
/* @__PURE__ */ jsxs76("div", { className: "border-t bg-card/80 shrink-0", children: [
|
|
21244
22254
|
/* @__PURE__ */ jsx83("div", { className: "px-4 py-2 border-b", children: /* @__PURE__ */ jsxs76("span", { className: "text-[10px] uppercase tracking-wider text-muted-foreground font-medium flex items-center gap-2", children: [
|
|
21245
22255
|
/* @__PURE__ */ jsx83(Clock15, { className: "h-3 w-3" }),
|
|
21246
|
-
"
|
|
22256
|
+
"Agent Timeline"
|
|
21247
22257
|
] }) }),
|
|
21248
22258
|
/* @__PURE__ */ jsx83("div", { className: "px-4 py-2 max-h-32 overflow-y-auto", children: /* @__PURE__ */ jsx83(EventTimeline, { events: eventTimeline, max: 10 }) }),
|
|
22259
|
+
/* @__PURE__ */ jsx83("div", { className: "border-t border-dashed" }),
|
|
22260
|
+
/* @__PURE__ */ jsx83("div", { className: "px-4 py-2 max-h-40 overflow-y-auto", children: fleetAgentTimeline.length === 0 ? /* @__PURE__ */ jsx83("p", { className: "text-[10px] text-muted-foreground italic", children: "No agent conversation events yet." }) : /* @__PURE__ */ jsx83("div", { className: "space-y-1", children: fleetAgentTimeline.slice(0, 15).map((entry) => {
|
|
22261
|
+
const iconMap = { text: "\u{1F4AC}", tool_use: "\u{1F527}", error: "\u274C", status: "\u{1F4AC}" };
|
|
22262
|
+
const icon = iconMap[entry.kind] ?? "\u25CF";
|
|
22263
|
+
const statusColor = entry.status === "running" || entry.status === "spawned" ? "text-emerald-500" : entry.status === "failed" || entry.status === "timeout" ? "text-destructive" : "text-muted-foreground";
|
|
22264
|
+
return /* @__PURE__ */ jsxs76("div", { className: "flex items-start gap-1.5 text-[10px] leading-tight", children: [
|
|
22265
|
+
/* @__PURE__ */ jsx83("span", { className: "shrink-0", children: icon }),
|
|
22266
|
+
/* @__PURE__ */ jsx83("span", { className: "font-medium text-primary shrink-0", children: entry.agentName }),
|
|
22267
|
+
entry.status && /* @__PURE__ */ jsx83("span", { className: `${statusColor} shrink-0`, children: entry.status }),
|
|
22268
|
+
entry.toolName && /* @__PURE__ */ jsxs76("span", { className: "text-muted-foreground shrink-0", children: [
|
|
22269
|
+
"[",
|
|
22270
|
+
entry.toolName,
|
|
22271
|
+
"]"
|
|
22272
|
+
] }),
|
|
22273
|
+
/* @__PURE__ */ jsx83("span", { className: "text-muted-foreground truncate", children: entry.content })
|
|
22274
|
+
] }, entry.id);
|
|
22275
|
+
}) }) }),
|
|
21249
22276
|
/* @__PURE__ */ jsxs76("div", { className: "px-4 py-1.5 border-t text-[10px] text-muted-foreground flex items-center gap-4", children: [
|
|
21250
22277
|
/* @__PURE__ */ jsx83("span", { children: "\u2191\u2193 navigate" }),
|
|
21251
22278
|
/* @__PURE__ */ jsx83("span", { children: "\u21B5 select detail" }),
|
|
@@ -21299,7 +22326,7 @@ function FleetMonitor({
|
|
|
21299
22326
|
|
|
21300
22327
|
// src/components/InspectorPanel.tsx
|
|
21301
22328
|
import { Bot as Bot13, ChevronDown as ChevronDown11, ChevronUp, Users as Users6 } from "lucide-react";
|
|
21302
|
-
import { useMemo as useMemo19, useState as
|
|
22329
|
+
import { useMemo as useMemo19, useState as useState52 } from "react";
|
|
21303
22330
|
import { Fragment as Fragment19, jsx as jsx84, jsxs as jsxs77 } from "react/jsx-runtime";
|
|
21304
22331
|
var PANEL_HEIGHT = 320;
|
|
21305
22332
|
function fmtCost5(v) {
|
|
@@ -21344,7 +22371,7 @@ function InspectorPanel() {
|
|
|
21344
22371
|
const runningCount = fleetList.filter((a) => a.status === "running").length;
|
|
21345
22372
|
const totalCost = fleetList.reduce((sum, a) => sum + a.costUsd, 0);
|
|
21346
22373
|
const fleetTotal = fleetList.length;
|
|
21347
|
-
const [selectedAgentId, setSelectedAgentId] =
|
|
22374
|
+
const [selectedAgentId, setSelectedAgentId] = useState52(null);
|
|
21348
22375
|
const selectedAgent = useMemo19(() => {
|
|
21349
22376
|
if (!selectedAgentId) return fleetList[0] ?? null;
|
|
21350
22377
|
return fleetAgents.get(selectedAgentId) ?? fleetList[0] ?? null;
|
|
@@ -22035,7 +23062,7 @@ import {
|
|
|
22035
23062
|
BookOpen
|
|
22036
23063
|
} from "lucide-react";
|
|
22037
23064
|
import TextareaCodeEditor from "@uiw/react-textarea-code-editor";
|
|
22038
|
-
import { useCallback as useCallback34, useEffect as useEffect52, useMemo as useMemo20, useRef as useRef30, useState as
|
|
23065
|
+
import { useCallback as useCallback34, useEffect as useEffect52, useMemo as useMemo20, useRef as useRef30, useState as useState53 } from "react";
|
|
22039
23066
|
import ReactMarkdown3 from "react-markdown";
|
|
22040
23067
|
import rehypeHighlight2 from "rehype-highlight";
|
|
22041
23068
|
import { Fragment as Fragment20, jsx as jsx88, jsxs as jsxs81 } from "react/jsx-runtime";
|
|
@@ -22067,23 +23094,23 @@ function SkillDetailView({ className }) {
|
|
|
22067
23094
|
const selectedSkill = skillsState.selectedSkill;
|
|
22068
23095
|
const navHistory = skillsState.navHistory;
|
|
22069
23096
|
const historyIndex = skillsState.historyIndex;
|
|
22070
|
-
const [skillContent, setSkillContent] =
|
|
22071
|
-
const [contentLoading, setContentLoading] =
|
|
22072
|
-
const [contentError, setContentError] =
|
|
22073
|
-
const [editMode, setEditMode] =
|
|
22074
|
-
const [editContent, setEditContent] =
|
|
22075
|
-
const [editSaving, setEditSaving] =
|
|
22076
|
-
const [editError, setEditError] =
|
|
22077
|
-
const [splitPreview, setSplitPreview] =
|
|
22078
|
-
const [draftSavedAt, setDraftSavedAt] =
|
|
22079
|
-
const [draftRestored, setDraftRestored] =
|
|
23097
|
+
const [skillContent, setSkillContent] = useState53(null);
|
|
23098
|
+
const [contentLoading, setContentLoading] = useState53(false);
|
|
23099
|
+
const [contentError, setContentError] = useState53(null);
|
|
23100
|
+
const [editMode, setEditMode] = useState53(false);
|
|
23101
|
+
const [editContent, setEditContent] = useState53("");
|
|
23102
|
+
const [editSaving, setEditSaving] = useState53(false);
|
|
23103
|
+
const [editError, setEditError] = useState53(null);
|
|
23104
|
+
const [splitPreview, setSplitPreview] = useState53(false);
|
|
23105
|
+
const [draftSavedAt, setDraftSavedAt] = useState53(null);
|
|
23106
|
+
const [draftRestored, setDraftRestored] = useState53(false);
|
|
22080
23107
|
const lastSavedDraftRef = useRef30("");
|
|
22081
|
-
const [checkingForUpdates, setCheckingForUpdates] =
|
|
22082
|
-
const [updateResult, setUpdateResult] =
|
|
22083
|
-
const [copiedSourceUrl, setCopiedSourceUrl] =
|
|
22084
|
-
const [uninstallConfirmSkill, setUninstallConfirmSkill] =
|
|
22085
|
-
const [uninstalling, setUninstalling] =
|
|
22086
|
-
const [skills, setSkills] =
|
|
23108
|
+
const [checkingForUpdates, setCheckingForUpdates] = useState53(false);
|
|
23109
|
+
const [updateResult, setUpdateResult] = useState53(null);
|
|
23110
|
+
const [copiedSourceUrl, setCopiedSourceUrl] = useState53(false);
|
|
23111
|
+
const [uninstallConfirmSkill, setUninstallConfirmSkill] = useState53(null);
|
|
23112
|
+
const [uninstalling, setUninstalling] = useState53(false);
|
|
23113
|
+
const [skills, setSkills] = useState53([]);
|
|
22087
23114
|
const skillsStateRef = useRef30(skillsState);
|
|
22088
23115
|
skillsStateRef.current = skillsState;
|
|
22089
23116
|
const isNavigatingBack = useRef30(false);
|
|
@@ -22783,7 +23810,7 @@ import {
|
|
|
22783
23810
|
EdgeLabelRenderer
|
|
22784
23811
|
} from "@xyflow/react";
|
|
22785
23812
|
import "@xyflow/react/dist/style.css";
|
|
22786
|
-
import { useCallback as useCallback36, useEffect as useEffect54, useMemo as useMemo22, useRef as useRef32, useState as
|
|
23813
|
+
import { useCallback as useCallback36, useEffect as useEffect54, useMemo as useMemo22, useRef as useRef32, useState as useState55 } from "react";
|
|
22787
23814
|
import {
|
|
22788
23815
|
Bot as Bot16,
|
|
22789
23816
|
Monitor as Monitor4,
|
|
@@ -22807,13 +23834,21 @@ import {
|
|
|
22807
23834
|
} from "lucide-react";
|
|
22808
23835
|
|
|
22809
23836
|
// src/components/SessionWatchPanel.tsx
|
|
22810
|
-
import { useCallback as useCallback35, useEffect as useEffect53, useMemo as useMemo21, useRef as useRef31, useState as
|
|
23837
|
+
import { useCallback as useCallback35, useEffect as useEffect53, useMemo as useMemo21, useRef as useRef31, useState as useState54 } from "react";
|
|
22811
23838
|
|
|
22812
23839
|
// src/components/WatchMessageBubble.tsx
|
|
22813
23840
|
import ReactMarkdown4 from "react-markdown";
|
|
22814
23841
|
import remarkGfm2 from "remark-gfm";
|
|
22815
|
-
import { AlertCircle as AlertCircle3, Bot as Bot14, Terminal as Terminal7, User as User3 } from "lucide-react";
|
|
23842
|
+
import { AlertCircle as AlertCircle3, Bot as Bot14, Clock as Clock17, Terminal as Terminal7, User as User3 } from "lucide-react";
|
|
22816
23843
|
import { jsx as jsx89, jsxs as jsxs82 } from "react/jsx-runtime";
|
|
23844
|
+
function fmtDuration3(durationMs) {
|
|
23845
|
+
if (durationMs < 1e3) return `${durationMs}ms`;
|
|
23846
|
+
const s = Math.round(durationMs / 100);
|
|
23847
|
+
if (s < 600) return `${(s / 10).toFixed(1)}s`;
|
|
23848
|
+
const m = Math.floor(s / 600);
|
|
23849
|
+
const sec = Math.round(s % 600 / 10);
|
|
23850
|
+
return `${m}m ${sec}s`;
|
|
23851
|
+
}
|
|
22817
23852
|
var ROLE_CONFIG = {
|
|
22818
23853
|
user: {
|
|
22819
23854
|
Icon: User3,
|
|
@@ -22867,29 +23902,41 @@ var ROLE_CONFIG = {
|
|
|
22867
23902
|
}
|
|
22868
23903
|
};
|
|
22869
23904
|
function WatchBubbleContent({ entry }) {
|
|
22870
|
-
if (!entry.text) return null;
|
|
22871
23905
|
if (entry.role === "error") {
|
|
22872
23906
|
return /* @__PURE__ */ jsx89(ErrorBodyWithStack, { text: entry.text });
|
|
22873
23907
|
}
|
|
22874
23908
|
if (entry.role === "tool") {
|
|
22875
|
-
const lines = entry.text.split("\n");
|
|
22876
|
-
let toolName = entry.tool || "tool";
|
|
22877
|
-
let inputText = null;
|
|
22878
|
-
if (lines.length > 1) {
|
|
22879
|
-
const maybeJson = lines.slice(1).join("\n");
|
|
22880
|
-
try {
|
|
22881
|
-
JSON.parse(maybeJson);
|
|
22882
|
-
toolName = lines[0] || entry.tool || "tool";
|
|
22883
|
-
inputText = maybeJson;
|
|
22884
|
-
} catch {
|
|
22885
|
-
}
|
|
22886
|
-
}
|
|
22887
23909
|
return /* @__PURE__ */ jsxs82("div", { className: "flex flex-col gap-1.5 tool-details", children: [
|
|
22888
23910
|
/* @__PURE__ */ jsxs82("div", { className: "flex items-center gap-1.5 text-sm font-medium text-foreground", children: [
|
|
22889
23911
|
/* @__PURE__ */ jsx89(Terminal7, { className: "h-3 w-3" }),
|
|
22890
|
-
/* @__PURE__ */ jsx89("span", { className: "font-mono", children:
|
|
23912
|
+
/* @__PURE__ */ jsx89("span", { className: "font-mono", children: entry.tool ?? "tool" }),
|
|
23913
|
+
entry.durationMs !== void 0 && /* @__PURE__ */ jsxs82("span", { className: "ml-auto text-[10px] text-muted-foreground font-normal tabular-nums", children: [
|
|
23914
|
+
/* @__PURE__ */ jsx89(Clock17, { className: "h-3 w-3 inline mr-0.5 align-text-bottom" }),
|
|
23915
|
+
fmtDuration3(entry.durationMs)
|
|
23916
|
+
] })
|
|
22891
23917
|
] }),
|
|
22892
|
-
|
|
23918
|
+
entry.input !== void 0 && entry.input !== null && /* @__PURE__ */ jsx89("div", { className: "p-3 bg-muted/50 rounded-lg overflow-x-auto", children: /* @__PURE__ */ jsx89(ToolInputView, { input: entry.input }) }),
|
|
23919
|
+
entry.output !== void 0 && entry.output !== null ? /* @__PURE__ */ jsx89("div", { className: "text-sm leading-relaxed markdown-content", children: typeof entry.output === "string" ? /* @__PURE__ */ jsx89(
|
|
23920
|
+
ReactMarkdown4,
|
|
23921
|
+
{
|
|
23922
|
+
remarkPlugins: [remarkGfm2],
|
|
23923
|
+
rehypePlugins,
|
|
23924
|
+
components: markdownComponents,
|
|
23925
|
+
children: entry.output
|
|
23926
|
+
}
|
|
23927
|
+
) : /* @__PURE__ */ jsx89("pre", { className: "whitespace-pre-wrap font-mono text-xs bg-card rounded-lg p-2 border border-border overflow-x-auto", children: JSON.stringify(entry.output, null, 2) }) }) : entry.text ? /* @__PURE__ */ jsx89("div", { className: "text-sm leading-relaxed markdown-content", children: /* @__PURE__ */ jsx89(
|
|
23928
|
+
ReactMarkdown4,
|
|
23929
|
+
{
|
|
23930
|
+
remarkPlugins: [remarkGfm2],
|
|
23931
|
+
rehypePlugins,
|
|
23932
|
+
components: markdownComponents,
|
|
23933
|
+
children: entry.text
|
|
23934
|
+
}
|
|
23935
|
+
) }) : null,
|
|
23936
|
+
entry.isError && /* @__PURE__ */ jsxs82("div", { className: "rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2", children: [
|
|
23937
|
+
/* @__PURE__ */ jsx89("span", { className: "text-xs font-medium text-destructive", children: "Tool failed" }),
|
|
23938
|
+
entry.text && /* @__PURE__ */ jsx89("pre", { className: "mt-1 text-xs whitespace-pre-wrap text-destructive/80", children: entry.text })
|
|
23939
|
+
] })
|
|
22893
23940
|
] });
|
|
22894
23941
|
}
|
|
22895
23942
|
return /* @__PURE__ */ jsx89("div", { className: "text-sm leading-relaxed markdown-content", children: /* @__PURE__ */ jsx89(
|
|
@@ -22923,20 +23970,15 @@ function WatchMessageBubble({
|
|
|
22923
23970
|
),
|
|
22924
23971
|
/* @__PURE__ */ jsxs82("div", { className: "flex flex-col gap-1.5 min-w-0 flex-1", children: [
|
|
22925
23972
|
!isContinuation && /* @__PURE__ */ jsxs82("div", { className: "flex items-center gap-2", children: [
|
|
22926
|
-
/* @__PURE__ */ jsx89(
|
|
22927
|
-
"span",
|
|
22928
|
-
{
|
|
22929
|
-
className: cn(
|
|
22930
|
-
"text-xs font-medium",
|
|
22931
|
-
cfg.textColor
|
|
22932
|
-
),
|
|
22933
|
-
children: entry.role === "tool" && entry.tool ? entry.tool : cfg.label
|
|
22934
|
-
}
|
|
22935
|
-
),
|
|
23973
|
+
/* @__PURE__ */ jsx89("span", { className: cn("text-xs font-medium", cfg.textColor), children: entry.role === "tool" && entry.tool ? entry.tool : cfg.label }),
|
|
22936
23974
|
/* @__PURE__ */ jsx89("span", { className: "text-xs text-muted-foreground", children: new Date(entry.ts).toLocaleTimeString([], {
|
|
22937
23975
|
hour: "2-digit",
|
|
22938
23976
|
minute: "2-digit"
|
|
22939
|
-
}) })
|
|
23977
|
+
}) }),
|
|
23978
|
+
entry.role === "tool" && entry.durationMs !== void 0 && /* @__PURE__ */ jsxs82("span", { className: "text-[10px] text-muted-foreground tabular-nums", children: [
|
|
23979
|
+
"\xB7 ",
|
|
23980
|
+
fmtDuration3(entry.durationMs)
|
|
23981
|
+
] })
|
|
22940
23982
|
] }),
|
|
22941
23983
|
/* @__PURE__ */ jsx89(
|
|
22942
23984
|
"div",
|
|
@@ -22951,16 +23993,7 @@ function WatchMessageBubble({
|
|
|
22951
23993
|
cfg.bubbleBg,
|
|
22952
23994
|
cfg.bubbleBorder
|
|
22953
23995
|
),
|
|
22954
|
-
children: /* @__PURE__ */ jsx89(
|
|
22955
|
-
"div",
|
|
22956
|
-
{
|
|
22957
|
-
className: cn(
|
|
22958
|
-
"text-sm leading-relaxed markdown-content",
|
|
22959
|
-
cfg.textColor
|
|
22960
|
-
),
|
|
22961
|
-
children: /* @__PURE__ */ jsx89(WatchBubbleContent, { entry })
|
|
22962
|
-
}
|
|
22963
|
-
)
|
|
23996
|
+
children: /* @__PURE__ */ jsx89("div", { className: cn("text-sm leading-relaxed markdown-content", cfg.textColor), children: /* @__PURE__ */ jsx89(WatchBubbleContent, { entry }) })
|
|
22964
23997
|
}
|
|
22965
23998
|
),
|
|
22966
23999
|
entry.text && entry.role !== "error" && /* @__PURE__ */ jsx89("div", { className: "opacity-0 group-hover:opacity-100 transition-opacity", children: /* @__PURE__ */ jsx89(CopyButton, { text: entry.text, label: "Copy" }) })
|
|
@@ -22982,15 +24015,15 @@ function SessionWatchPanel({
|
|
|
22982
24015
|
sessionId,
|
|
22983
24016
|
limit = 200
|
|
22984
24017
|
}) {
|
|
22985
|
-
const [data, setData] =
|
|
22986
|
-
const [error, setError] =
|
|
22987
|
-
const [draft, setDraft] =
|
|
22988
|
-
const [sending, setSending] =
|
|
22989
|
-
const [sent, setSent] =
|
|
22990
|
-
const [msgType, setMsgType] =
|
|
22991
|
-
const [priority, setPriority] =
|
|
22992
|
-
const [thread, setThread] =
|
|
22993
|
-
const [interrupting, setInterrupting] =
|
|
24018
|
+
const [data, setData] = useState54(null);
|
|
24019
|
+
const [error, setError] = useState54(null);
|
|
24020
|
+
const [draft, setDraft] = useState54("");
|
|
24021
|
+
const [sending, setSending] = useState54(false);
|
|
24022
|
+
const [sent, setSent] = useState54(null);
|
|
24023
|
+
const [msgType, setMsgType] = useState54("steer");
|
|
24024
|
+
const [priority, setPriority] = useState54("high");
|
|
24025
|
+
const [thread, setThread] = useState54([]);
|
|
24026
|
+
const [interrupting, setInterrupting] = useState54(false);
|
|
22994
24027
|
const scrollRef = useRef31(null);
|
|
22995
24028
|
const stickRef = useRef31(true);
|
|
22996
24029
|
const aliveRef = useRef31(true);
|
|
@@ -24018,12 +25051,12 @@ function OfficeMapCanvas() {
|
|
|
24018
25051
|
const background = useOfficeMapStore((s) => s.background);
|
|
24019
25052
|
const [nodes, setNodes, onNodesChange] = useNodesState([]);
|
|
24020
25053
|
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
|
|
24021
|
-
const [selectedNode, setSelectedNode] =
|
|
24022
|
-
const [watch, setWatch] =
|
|
24023
|
-
const [broadcastOpen, setBroadcastOpen] =
|
|
24024
|
-
const [broadcastDraft, setBroadcastDraft] =
|
|
24025
|
-
const [broadcasting, setBroadcasting] =
|
|
24026
|
-
const [broadcastResult, setBroadcastResult] =
|
|
25054
|
+
const [selectedNode, setSelectedNode] = useState55(null);
|
|
25055
|
+
const [watch, setWatch] = useState55(null);
|
|
25056
|
+
const [broadcastOpen, setBroadcastOpen] = useState55(false);
|
|
25057
|
+
const [broadcastDraft, setBroadcastDraft] = useState55("");
|
|
25058
|
+
const [broadcasting, setBroadcasting] = useState55(false);
|
|
25059
|
+
const [broadcastResult, setBroadcastResult] = useState55(null);
|
|
24027
25060
|
const sendBroadcast = useCallback36(async () => {
|
|
24028
25061
|
const text = broadcastDraft.trim();
|
|
24029
25062
|
if (!text || broadcasting) return;
|
|
@@ -24510,7 +25543,7 @@ function OfficeMapCanvas() {
|
|
|
24510
25543
|
);
|
|
24511
25544
|
setTimeout(() => fitView({ padding: 0.2, duration: 300 }), 50);
|
|
24512
25545
|
}, [setNodes, fitView]);
|
|
24513
|
-
const [, setTick] =
|
|
25546
|
+
const [, setTick] = useState55(0);
|
|
24514
25547
|
useEffect54(() => {
|
|
24515
25548
|
const interval = setInterval(() => setTick((t) => t + 1), 2e3);
|
|
24516
25549
|
return () => clearInterval(interval);
|
|
@@ -24889,8 +25922,8 @@ function OfficeMapPanel() {
|
|
|
24889
25922
|
}
|
|
24890
25923
|
|
|
24891
25924
|
// src/components/DebugDashboard.tsx
|
|
24892
|
-
import { useCallback as useCallback37, useEffect as useEffect55, useState as
|
|
24893
|
-
import { Activity as Activity7, AlertCircle as AlertCircle4, BarChart3 as BarChart32, Clock as
|
|
25925
|
+
import { useCallback as useCallback37, useEffect as useEffect55, useState as useState56 } from "react";
|
|
25926
|
+
import { Activity as Activity7, AlertCircle as AlertCircle4, BarChart3 as BarChart32, Clock as Clock18, Eye as Eye3, FileWarning, Gauge as Gauge2, RefreshCw as RefreshCw8, Server as Server3, TrendingUp as TrendingUp2 } from "lucide-react";
|
|
24894
25927
|
import { jsx as jsx93, jsxs as jsxs85 } from "react/jsx-runtime";
|
|
24895
25928
|
function MetricCard({
|
|
24896
25929
|
title,
|
|
@@ -24917,14 +25950,14 @@ function MetricCard({
|
|
|
24917
25950
|
] });
|
|
24918
25951
|
}
|
|
24919
25952
|
function DebugDashboard() {
|
|
24920
|
-
const [data, setData] =
|
|
25953
|
+
const [data, setData] = useState56({
|
|
24921
25954
|
fileWatcher: null,
|
|
24922
25955
|
system: null,
|
|
24923
25956
|
lastUpdated: null,
|
|
24924
25957
|
error: null
|
|
24925
25958
|
});
|
|
24926
|
-
const [isLoading, setIsLoading] =
|
|
24927
|
-
const [refreshInterval, setRefreshInterval] =
|
|
25959
|
+
const [isLoading, setIsLoading] = useState56(true);
|
|
25960
|
+
const [refreshInterval, setRefreshInterval] = useState56(2e3);
|
|
24928
25961
|
const fetchMetrics = useCallback37(async () => {
|
|
24929
25962
|
try {
|
|
24930
25963
|
const watcherRes = await fetch("/debug/watcher-metrics");
|
|
@@ -25010,7 +26043,7 @@ function DebugDashboard() {
|
|
|
25010
26043
|
] })
|
|
25011
26044
|
] }),
|
|
25012
26045
|
data.lastUpdated && /* @__PURE__ */ jsxs85("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
|
|
25013
|
-
/* @__PURE__ */ jsx93(
|
|
26046
|
+
/* @__PURE__ */ jsx93(Clock18, { className: "w-4 h-4" }),
|
|
25014
26047
|
"Last updated: ",
|
|
25015
26048
|
data.lastUpdated.toLocaleTimeString()
|
|
25016
26049
|
] }),
|
|
@@ -25095,7 +26128,7 @@ function DebugDashboard() {
|
|
|
25095
26128
|
title: "Avg Debounce Delay",
|
|
25096
26129
|
value: `${(data.fileWatcher?.averageDebounceDelayMs ?? 0).toFixed(1)}ms`,
|
|
25097
26130
|
subtitle: "Actual delay applied",
|
|
25098
|
-
icon:
|
|
26131
|
+
icon: Clock18,
|
|
25099
26132
|
color: "text-yellow-500"
|
|
25100
26133
|
}
|
|
25101
26134
|
),
|
|
@@ -25143,7 +26176,7 @@ function DebugDashboard() {
|
|
|
25143
26176
|
title: "Page Uptime",
|
|
25144
26177
|
value: formatUptime(data.system?.uptime ?? 0),
|
|
25145
26178
|
subtitle: "Since page load",
|
|
25146
|
-
icon:
|
|
26179
|
+
icon: Clock18,
|
|
25147
26180
|
color: "text-purple-500"
|
|
25148
26181
|
}
|
|
25149
26182
|
)
|
|
@@ -25295,6 +26328,64 @@ function AppInner() {
|
|
|
25295
26328
|
return;
|
|
25296
26329
|
}
|
|
25297
26330
|
}
|
|
26331
|
+
if (!inField && !mod && !e.altKey && /^F([1-9]|1[0-2])$/.test(e.key)) {
|
|
26332
|
+
e.preventDefault();
|
|
26333
|
+
const ui = useUIStore.getState();
|
|
26334
|
+
const ws = getWSClient(useConfigStore.getState().wsUrl);
|
|
26335
|
+
const n = Number(e.key.slice(1));
|
|
26336
|
+
ui.setDockCustomizeOpen(false);
|
|
26337
|
+
switch (n) {
|
|
26338
|
+
case 1:
|
|
26339
|
+
openPanel("projects");
|
|
26340
|
+
return;
|
|
26341
|
+
case 2:
|
|
26342
|
+
ui.setFleetMonitorOpen(true);
|
|
26343
|
+
return;
|
|
26344
|
+
case 3:
|
|
26345
|
+
ui.setAgentsMonitorOpen(true);
|
|
26346
|
+
return;
|
|
26347
|
+
case 4:
|
|
26348
|
+
ui.setCurrentView("chat");
|
|
26349
|
+
ui.setDockSection("worktrees");
|
|
26350
|
+
return;
|
|
26351
|
+
case 5:
|
|
26352
|
+
ws?.getPlan?.();
|
|
26353
|
+
ui.setCurrentView("chat");
|
|
26354
|
+
ui.setDockSection("work");
|
|
26355
|
+
ui.setWorkDashboardTab("plan");
|
|
26356
|
+
return;
|
|
26357
|
+
case 6:
|
|
26358
|
+
ui.setCurrentView("chat");
|
|
26359
|
+
ui.setDockSection("work");
|
|
26360
|
+
ui.setWorkDashboardTab("todos");
|
|
26361
|
+
return;
|
|
26362
|
+
case 7:
|
|
26363
|
+
ui.setQueuePanelOpen(true);
|
|
26364
|
+
return;
|
|
26365
|
+
case 8:
|
|
26366
|
+
ui.setProcessMonitorOpen(true);
|
|
26367
|
+
return;
|
|
26368
|
+
case 9:
|
|
26369
|
+
ws?.send?.({ type: "goal.get" });
|
|
26370
|
+
ui.setCurrentView("chat");
|
|
26371
|
+
ui.setDockSection("goal");
|
|
26372
|
+
return;
|
|
26373
|
+
case 10:
|
|
26374
|
+
ws?.listSessions?.(50);
|
|
26375
|
+
ui.setCurrentView("sessions");
|
|
26376
|
+
return;
|
|
26377
|
+
case 11:
|
|
26378
|
+
ui.setSidebarOpen(true);
|
|
26379
|
+
ui.selectActivity("officemap");
|
|
26380
|
+
ui.setCurrentView("officemap");
|
|
26381
|
+
return;
|
|
26382
|
+
case 12:
|
|
26383
|
+
ui.setCurrentView("chat");
|
|
26384
|
+
ui.setDockSection("work");
|
|
26385
|
+
ui.setDockCustomizeOpen(true);
|
|
26386
|
+
return;
|
|
26387
|
+
}
|
|
26388
|
+
}
|
|
25298
26389
|
if (mod && e.key.toLowerCase() === "f") {
|
|
25299
26390
|
e.preventDefault();
|
|
25300
26391
|
setSearchOpen(true);
|