@voybio/ace-swarm 0.1.0 → 0.2.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/README.md +69 -29
- package/assets/agent-state/EVIDENCE_LOG.md +1 -1
- package/assets/agent-state/STATUS.md +2 -2
- package/assets/scripts/ace-hook-dispatch.mjs +1 -1
- package/dist/ace-autonomy.js +38 -1
- package/dist/ace-context.js +8 -0
- package/dist/ace-server-instructions.js +55 -19
- package/dist/ace-state-resolver.d.ts +18 -0
- package/dist/ace-state-resolver.js +106 -0
- package/dist/cli.js +74 -7
- package/dist/handoff-registry.js +11 -7
- package/dist/helpers.js +75 -9
- package/dist/job-scheduler.js +94 -44
- package/dist/run-ledger.js +3 -4
- package/dist/server.d.ts +1 -1
- package/dist/server.js +1 -1
- package/dist/shared.d.ts +1 -1
- package/dist/status-events.js +12 -14
- package/dist/store/ace-packed-store.d.ts +65 -26
- package/dist/store/ace-packed-store.js +448 -261
- package/dist/store/bootstrap-store.d.ts +1 -1
- package/dist/store/bootstrap-store.js +24 -13
- package/dist/store/catalog-builder.js +3 -3
- package/dist/store/importer.d.ts +2 -2
- package/dist/store/importer.js +2 -2
- package/dist/store/materializers/context-snapshot-materializer.d.ts +10 -0
- package/dist/store/materializers/context-snapshot-materializer.js +51 -0
- package/dist/store/materializers/hook-context-materializer.d.ts +1 -1
- package/dist/store/materializers/hook-context-materializer.js +1 -1
- package/dist/store/materializers/host-file-materializer.d.ts +6 -0
- package/dist/store/materializers/host-file-materializer.js +14 -1
- package/dist/store/materializers/projection-manager.d.ts +14 -0
- package/dist/store/materializers/projection-manager.js +73 -0
- package/dist/store/materializers/scheduler-projection-materializer.d.ts +16 -0
- package/dist/store/materializers/scheduler-projection-materializer.js +48 -0
- package/dist/store/repositories/context-snapshot-repository.d.ts +46 -0
- package/dist/store/repositories/context-snapshot-repository.js +105 -0
- package/dist/store/repositories/local-model-runtime-repository.d.ts +98 -0
- package/dist/store/repositories/local-model-runtime-repository.js +165 -0
- package/dist/store/repositories/scheduler-repository.d.ts +21 -39
- package/dist/store/repositories/scheduler-repository.js +123 -93
- package/dist/store/repositories/todo-repository.d.ts +4 -0
- package/dist/store/repositories/todo-repository.js +50 -0
- package/dist/store/skills-install.d.ts +1 -1
- package/dist/store/skills-install.js +3 -3
- package/dist/store/state-reader.d.ts +8 -1
- package/dist/store/state-reader.js +19 -13
- package/dist/store/store-artifacts.js +105 -41
- package/dist/store/store-authority-audit.d.ts +30 -0
- package/dist/store/store-authority-audit.js +448 -0
- package/dist/store/store-snapshot.js +3 -3
- package/dist/store/types.d.ts +6 -2
- package/dist/store/types.js +5 -2
- package/dist/todo-state.js +179 -11
- package/dist/tools-files.js +2 -1
- package/dist/tools-framework.js +62 -2
- package/dist/tools-memory.js +69 -34
- package/dist/tools-todo.js +1 -1
- package/dist/tui/agent-worker.d.ts +1 -1
- package/dist/tui/agent-worker.js +5 -3
- package/dist/tui/chat.d.ts +19 -0
- package/dist/tui/chat.js +275 -9
- package/dist/tui/commands.d.ts +2 -0
- package/dist/tui/commands.js +62 -0
- package/dist/tui/dashboard.d.ts +6 -1
- package/dist/tui/dashboard.js +44 -3
- package/dist/tui/index.d.ts +5 -0
- package/dist/tui/index.js +154 -0
- package/dist/tui/input.js +5 -0
- package/dist/tui/layout.d.ts +24 -0
- package/dist/tui/layout.js +76 -2
- package/dist/tui/local-model-contract.d.ts +50 -0
- package/dist/tui/local-model-contract.js +272 -0
- package/dist/vericify-bridge.js +3 -4
- package/dist/vericify-context.js +18 -6
- package/package.json +4 -6
package/dist/tui/index.js
CHANGED
|
@@ -18,6 +18,8 @@ import { detectColorLevel, write, cursor, screen, fg, style } from "./renderer.j
|
|
|
18
18
|
import { ALL_AGENTS, WORKSPACE_ROOT } from "../helpers.js";
|
|
19
19
|
import { backfillHandoffsIntoScheduler } from "../tools-handoff.js";
|
|
20
20
|
import { DEFAULT_OLLAMA_MODEL, inferProviderFromModel, normalizeLocalBaseUrl, } from "./provider-discovery.js";
|
|
21
|
+
import { resolveAceStateLayout } from "../ace-state-resolver.js";
|
|
22
|
+
import { withLocalModelRuntimeRepository, } from "../store/repositories/local-model-runtime-repository.js";
|
|
21
23
|
const DASHBOARD_CONTROLS = ["provider", "model", "chat", "logs", "refresh"];
|
|
22
24
|
// ── TUI Application ─────────────────────────────────────────────────
|
|
23
25
|
export class AceTui {
|
|
@@ -48,6 +50,8 @@ export class AceTui {
|
|
|
48
50
|
messageQueue = [];
|
|
49
51
|
workspaceRoot;
|
|
50
52
|
providerBaseUrls = new Map();
|
|
53
|
+
latestRuntimeStatus = null;
|
|
54
|
+
pendingCloseTabId = null;
|
|
51
55
|
constructor(options = {}) {
|
|
52
56
|
const workspaceRoot = options.workspaceRoot ?? WORKSPACE_ROOT;
|
|
53
57
|
this.workspaceRoot = workspaceRoot;
|
|
@@ -218,10 +222,22 @@ export class AceTui {
|
|
|
218
222
|
});
|
|
219
223
|
// Dashboard: state updated
|
|
220
224
|
this.dashboard.on("updated", () => {
|
|
225
|
+
this.latestRuntimeStatus = this.dashboard.getLatestRuntimeStatus() ?? null;
|
|
221
226
|
const active = this.tabs.getActiveTab();
|
|
222
227
|
if (active.type === "dashboard") {
|
|
223
228
|
this.renderActiveView();
|
|
224
229
|
}
|
|
230
|
+
this.renderStatusBar();
|
|
231
|
+
});
|
|
232
|
+
// Dashboard: discovered providers from the store → feed into TUI provider controls
|
|
233
|
+
this.dashboard.on("providers", (discovered) => {
|
|
234
|
+
for (const d of discovered) {
|
|
235
|
+
this.ensureProvider(d.provider);
|
|
236
|
+
if (d.endpoint)
|
|
237
|
+
this.setProviderBaseUrl(d.provider, d.endpoint);
|
|
238
|
+
if (d.models && d.models.length > 0)
|
|
239
|
+
this.setProviderModels(d.provider, d.models, false);
|
|
240
|
+
}
|
|
225
241
|
});
|
|
226
242
|
// Agent runner: agent output
|
|
227
243
|
this.agentRunner.on("agent_output", (role, text) => {
|
|
@@ -276,6 +292,9 @@ export class AceTui {
|
|
|
276
292
|
case "l":
|
|
277
293
|
this.clearView();
|
|
278
294
|
return;
|
|
295
|
+
case "w":
|
|
296
|
+
this.closeCurrentTab();
|
|
297
|
+
return;
|
|
279
298
|
}
|
|
280
299
|
}
|
|
281
300
|
// Alt+number → switch tab
|
|
@@ -469,6 +488,7 @@ export class AceTui {
|
|
|
469
488
|
renderStatusBar() {
|
|
470
489
|
const snap = this.telemetry.getSnapshot();
|
|
471
490
|
const agentTokens = this.agentRunner.getTotalTokens();
|
|
491
|
+
const runtimeStatus = this.getActiveRuntimeStatus();
|
|
472
492
|
const state = {
|
|
473
493
|
taskState: this.getTaskState(),
|
|
474
494
|
provider: this.provider,
|
|
@@ -476,6 +496,29 @@ export class AceTui {
|
|
|
476
496
|
tokensIn: snap.tokensIn + agentTokens.input,
|
|
477
497
|
tokensOut: snap.tokensOut + agentTokens.output,
|
|
478
498
|
startTime: this.startTime,
|
|
499
|
+
activeTabLabel: this.tabs.getActiveTab().label,
|
|
500
|
+
sessionId: runtimeStatus?.session_id,
|
|
501
|
+
turnCount: runtimeStatus?.turn_count,
|
|
502
|
+
preflightState: runtimeStatus?.preflight_state,
|
|
503
|
+
agentName: runtimeStatus?.role,
|
|
504
|
+
taskName: runtimeStatus?.current_task,
|
|
505
|
+
bridgeStatus: runtimeStatus?.bridge_status,
|
|
506
|
+
activeTool: runtimeStatus?.active_tool,
|
|
507
|
+
blockedReason: runtimeStatus?.blocked_reason,
|
|
508
|
+
nextAction: runtimeStatus?.recommended_next_action,
|
|
509
|
+
approvalState: runtimeStatus?.approval_state,
|
|
510
|
+
retryState: runtimeStatus?.retry_state
|
|
511
|
+
? `attempt ${runtimeStatus.retry_state.attempt}${typeof runtimeStatus.retry_state.max_attempts === "number"
|
|
512
|
+
? `/${runtimeStatus.retry_state.max_attempts}`
|
|
513
|
+
: ""}`
|
|
514
|
+
: undefined,
|
|
515
|
+
pollState: runtimeStatus?.poll_state
|
|
516
|
+
? runtimeStatus.poll_state.active
|
|
517
|
+
? `active${typeof runtimeStatus.poll_state.interval_ms === "number"
|
|
518
|
+
? `/${runtimeStatus.poll_state.interval_ms}ms`
|
|
519
|
+
: ""}`
|
|
520
|
+
: "paused"
|
|
521
|
+
: undefined,
|
|
479
522
|
};
|
|
480
523
|
this.layout.renderStatusBar(state);
|
|
481
524
|
}
|
|
@@ -485,6 +528,17 @@ export class AceTui {
|
|
|
485
528
|
this.layout.renderInputLine(this.input.getBuffer(), this.input.getCursorPos(), mode, prompt);
|
|
486
529
|
}
|
|
487
530
|
getTaskState() {
|
|
531
|
+
const runtimeStatus = this.getActiveRuntimeStatus();
|
|
532
|
+
if (runtimeStatus &&
|
|
533
|
+
["blocked", "failed", "needs_input", "approval_pending"].includes(runtimeStatus.bridge_status)) {
|
|
534
|
+
return "blocked";
|
|
535
|
+
}
|
|
536
|
+
if (runtimeStatus &&
|
|
537
|
+
(runtimeStatus.bridge_status === "retrying" ||
|
|
538
|
+
runtimeStatus.bridge_status === "running" ||
|
|
539
|
+
Boolean(runtimeStatus.active_tool))) {
|
|
540
|
+
return "running";
|
|
541
|
+
}
|
|
488
542
|
if (this.activeChatSession?.isStreaming())
|
|
489
543
|
return "running";
|
|
490
544
|
if (this.agentRunner.getActiveCount() > 0)
|
|
@@ -493,6 +547,7 @@ export class AceTui {
|
|
|
493
547
|
}
|
|
494
548
|
syncTabState() {
|
|
495
549
|
const tab = this.tabs.getActiveTab();
|
|
550
|
+
this.pendingCloseTabId = null;
|
|
496
551
|
// Update active chat session pointer
|
|
497
552
|
if (tab.type === "chat") {
|
|
498
553
|
this.activeChatSession = this.chatSessions.get(tab.id) ?? null;
|
|
@@ -517,6 +572,13 @@ export class AceTui {
|
|
|
517
572
|
const now = Date.now();
|
|
518
573
|
this.messageQueue = this.messageQueue.filter(m => m.expiry > now);
|
|
519
574
|
}
|
|
575
|
+
getActiveRuntimeStatus() {
|
|
576
|
+
const activeTab = this.tabs.getActiveTab();
|
|
577
|
+
if (activeTab.type === "chat") {
|
|
578
|
+
return this.chatSessions.get(activeTab.id)?.getCurrentRuntimeStatus() ?? this.latestRuntimeStatus;
|
|
579
|
+
}
|
|
580
|
+
return this.latestRuntimeStatus;
|
|
581
|
+
}
|
|
520
582
|
normalizeProvider(provider) {
|
|
521
583
|
if (!provider)
|
|
522
584
|
return undefined;
|
|
@@ -891,6 +953,25 @@ export class AceTui {
|
|
|
891
953
|
this.renderStatusBar();
|
|
892
954
|
this.renderInputArea();
|
|
893
955
|
});
|
|
956
|
+
session.on("runtime_status", (status) => {
|
|
957
|
+
this.latestRuntimeStatus = status;
|
|
958
|
+
if (this.tabs.getActiveTab().id === tab.id || this.tabs.getActiveTab().type === "dashboard") {
|
|
959
|
+
this.renderActiveView();
|
|
960
|
+
}
|
|
961
|
+
this.renderStatusBar();
|
|
962
|
+
});
|
|
963
|
+
session.on("tool_call", (tool) => {
|
|
964
|
+
this.dashboard.addEvent("bridge", `tool call → ${tool}`);
|
|
965
|
+
if (this.tabs.getActiveTab().type === "dashboard") {
|
|
966
|
+
this.renderActiveView();
|
|
967
|
+
}
|
|
968
|
+
});
|
|
969
|
+
session.on("tool_result", (tool, toolResult) => {
|
|
970
|
+
this.dashboard.addEvent("bridge", `${toolResult.ok ? "tool ok" : "tool error"} → ${tool}: ${toolResult.summary}`);
|
|
971
|
+
if (this.tabs.getActiveTab().type === "dashboard") {
|
|
972
|
+
this.renderActiveView();
|
|
973
|
+
}
|
|
974
|
+
});
|
|
894
975
|
session.on("error", (msg) => {
|
|
895
976
|
this.showMessage(msg, "error");
|
|
896
977
|
});
|
|
@@ -907,6 +988,19 @@ export class AceTui {
|
|
|
907
988
|
}
|
|
908
989
|
closeCurrentTab() {
|
|
909
990
|
const tab = this.tabs.getActiveTab();
|
|
991
|
+
if (!tab.closeable) {
|
|
992
|
+
this.showMessage(`Tab '${tab.label}' cannot be closed.`, "warn");
|
|
993
|
+
return;
|
|
994
|
+
}
|
|
995
|
+
if (tab.type === "chat") {
|
|
996
|
+
const session = this.chatSessions.get(tab.id);
|
|
997
|
+
if (session?.hasMeaningfulTranscript() && this.pendingCloseTabId !== tab.id) {
|
|
998
|
+
this.pendingCloseTabId = tab.id;
|
|
999
|
+
this.showMessage("Chat has transcript state. Use /archive to persist it, or close again to discard.", "warn");
|
|
1000
|
+
return;
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
this.pendingCloseTabId = null;
|
|
910
1004
|
// Clean up chat session if closing a chat tab
|
|
911
1005
|
if (tab.type === "chat") {
|
|
912
1006
|
const session = this.chatSessions.get(tab.id);
|
|
@@ -923,6 +1017,51 @@ export class AceTui {
|
|
|
923
1017
|
this.syncTabState();
|
|
924
1018
|
this.fullRender();
|
|
925
1019
|
}
|
|
1020
|
+
async archiveCurrentTab() {
|
|
1021
|
+
const tab = this.tabs.getActiveTab();
|
|
1022
|
+
if (tab.type !== "chat") {
|
|
1023
|
+
this.showMessage("Archive is available only for chat tabs.", "warn");
|
|
1024
|
+
return;
|
|
1025
|
+
}
|
|
1026
|
+
const session = this.chatSessions.get(tab.id);
|
|
1027
|
+
if (!session) {
|
|
1028
|
+
this.showMessage("Chat session not found for archive.", "error");
|
|
1029
|
+
return;
|
|
1030
|
+
}
|
|
1031
|
+
if (!session.hasMeaningfulTranscript()) {
|
|
1032
|
+
this.showMessage("Chat is empty. Closing without archive.", "info");
|
|
1033
|
+
this.pendingCloseTabId = tab.id;
|
|
1034
|
+
this.closeCurrentTab();
|
|
1035
|
+
return;
|
|
1036
|
+
}
|
|
1037
|
+
const runtimeStatus = session.getCurrentRuntimeStatus();
|
|
1038
|
+
await withLocalModelRuntimeRepository(this.workspaceRoot, async (repo) => {
|
|
1039
|
+
await repo.archiveChat({
|
|
1040
|
+
session_id: session.getSessionId(),
|
|
1041
|
+
tab_id: tab.id,
|
|
1042
|
+
label: tab.label,
|
|
1043
|
+
provider: session.getProvider(),
|
|
1044
|
+
model: session.getModel(),
|
|
1045
|
+
created_at: session.getCreatedAt(),
|
|
1046
|
+
last_active_at: session.getLastActiveAt(),
|
|
1047
|
+
transcript_excerpt: session.getTranscriptExcerpt(),
|
|
1048
|
+
transcript_summary: session.getTranscriptSummary(),
|
|
1049
|
+
ace_context: {
|
|
1050
|
+
resolved_layout_mode: resolveAceStateLayout(this.workspaceRoot).physicalMode,
|
|
1051
|
+
role: runtimeStatus?.role,
|
|
1052
|
+
bridge_status: runtimeStatus?.bridge_status ?? "done",
|
|
1053
|
+
active_tool: runtimeStatus?.active_tool,
|
|
1054
|
+
blocked_reason: runtimeStatus?.blocked_reason,
|
|
1055
|
+
approval_state: runtimeStatus?.approval_state,
|
|
1056
|
+
retry_state: runtimeStatus?.retry_state,
|
|
1057
|
+
recommended_next_action: runtimeStatus?.recommended_next_action,
|
|
1058
|
+
},
|
|
1059
|
+
});
|
|
1060
|
+
});
|
|
1061
|
+
this.showMessage(`Archived chat '${tab.label}'.`, "info");
|
|
1062
|
+
this.pendingCloseTabId = tab.id;
|
|
1063
|
+
this.closeCurrentTab();
|
|
1064
|
+
}
|
|
926
1065
|
showMessage(text, level = "info") {
|
|
927
1066
|
const colorFn = level === "error" ? fg.red : level === "warn" ? fg.yellow : fg.gray;
|
|
928
1067
|
const prefix = level === "error" ? "ERROR" : level === "warn" ? "WARN" : "INFO";
|
|
@@ -957,6 +1096,20 @@ export class AceTui {
|
|
|
957
1096
|
this.layout.fullRedraw();
|
|
958
1097
|
this.fullRender();
|
|
959
1098
|
}
|
|
1099
|
+
setApprovalState(state) {
|
|
1100
|
+
const session = this.activeChatSession;
|
|
1101
|
+
if (!session) {
|
|
1102
|
+
this.showMessage("No active chat runtime to update approval state.", "warn");
|
|
1103
|
+
return false;
|
|
1104
|
+
}
|
|
1105
|
+
const ok = session.setApprovalState(state);
|
|
1106
|
+
if (!ok) {
|
|
1107
|
+
this.showMessage("No active runtime packet to update approval state.", "warn");
|
|
1108
|
+
return false;
|
|
1109
|
+
}
|
|
1110
|
+
this.renderStatusBar();
|
|
1111
|
+
return true;
|
|
1112
|
+
}
|
|
960
1113
|
getStatus() {
|
|
961
1114
|
const snap = this.telemetry.getSnapshot();
|
|
962
1115
|
return {
|
|
@@ -969,6 +1122,7 @@ export class AceTui {
|
|
|
969
1122
|
requests: snap.requestCount,
|
|
970
1123
|
activeAgents: this.agentRunner.getActiveCount(),
|
|
971
1124
|
tabs: this.tabs.getTabs().length,
|
|
1125
|
+
bridgeStatus: this.latestRuntimeStatus?.bridge_status,
|
|
972
1126
|
};
|
|
973
1127
|
}
|
|
974
1128
|
quit() {
|
package/dist/tui/input.js
CHANGED
|
@@ -101,6 +101,11 @@ export class InputHandler extends EventEmitter {
|
|
|
101
101
|
this.emit("key", { name: "l", sequence: ch, ctrl: true, meta: false, shift: false });
|
|
102
102
|
continue;
|
|
103
103
|
}
|
|
104
|
+
// Ctrl+W — close/archive current tab
|
|
105
|
+
if (code === 23) {
|
|
106
|
+
this.emit("key", { name: "w", sequence: ch, ctrl: true, meta: false, shift: false });
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
104
109
|
// Tab
|
|
105
110
|
if (code === 9) {
|
|
106
111
|
if ((this.mode === "command" || this.mode === "chat") && this.buffer.length > 0) {
|
package/dist/tui/layout.d.ts
CHANGED
|
@@ -24,6 +24,17 @@ export interface StatusBarState {
|
|
|
24
24
|
tokensIn: number;
|
|
25
25
|
tokensOut: number;
|
|
26
26
|
startTime: number;
|
|
27
|
+
activeTabLabel?: string;
|
|
28
|
+
sessionId?: string;
|
|
29
|
+
turnCount?: number;
|
|
30
|
+
preflightState?: string;
|
|
31
|
+
bridgeStatus?: string;
|
|
32
|
+
activeTool?: string;
|
|
33
|
+
blockedReason?: string;
|
|
34
|
+
nextAction?: string;
|
|
35
|
+
approvalState?: string;
|
|
36
|
+
retryState?: string;
|
|
37
|
+
pollState?: string;
|
|
27
38
|
taskName?: string;
|
|
28
39
|
agentName?: string;
|
|
29
40
|
}
|
|
@@ -44,6 +55,17 @@ export interface DashboardControlState {
|
|
|
44
55
|
selectedIndex: number;
|
|
45
56
|
items: DashboardControlItem[];
|
|
46
57
|
}
|
|
58
|
+
export declare function formatRuntimeStatusSummary(state: Pick<StatusBarState, "sessionId" | "turnCount" | "preflightState" | "taskName" | "agentName" | "approvalState" | "retryState" | "pollState">): string | undefined;
|
|
59
|
+
interface RuntimeStatusSummary {
|
|
60
|
+
bridge_status: string;
|
|
61
|
+
preflight_state: string;
|
|
62
|
+
role?: string;
|
|
63
|
+
approval_state?: string;
|
|
64
|
+
active_tool?: string;
|
|
65
|
+
active_tool_role?: string;
|
|
66
|
+
recommended_next_action?: string;
|
|
67
|
+
blocked_reason?: string;
|
|
68
|
+
}
|
|
47
69
|
export declare class LayoutManager {
|
|
48
70
|
private zones;
|
|
49
71
|
private cols;
|
|
@@ -94,6 +116,7 @@ export interface DashboardData {
|
|
|
94
116
|
tokensIn: number;
|
|
95
117
|
tokensOut: number;
|
|
96
118
|
tokensPerSec: number;
|
|
119
|
+
runtimeStatus?: RuntimeStatusSummary;
|
|
97
120
|
tasks: TaskItem[];
|
|
98
121
|
events: ActivityEvent[];
|
|
99
122
|
}
|
|
@@ -113,4 +136,5 @@ export interface ChatMessage {
|
|
|
113
136
|
timestamp?: number;
|
|
114
137
|
tokens?: number;
|
|
115
138
|
}
|
|
139
|
+
export {};
|
|
116
140
|
//# sourceMappingURL=layout.d.ts.map
|
package/dist/tui/layout.js
CHANGED
|
@@ -5,6 +5,34 @@
|
|
|
5
5
|
* Arttime-inspired: defined zones for each UI element.
|
|
6
6
|
*/
|
|
7
7
|
import { getTermSize, write, writeAt, drawBox, clearRegion, cursor, screen, style, fg, bg, padRight, truncate, visibleWidth, box, symbols, formatTime, formatElapsed, formatNumber, hline, } from "./renderer.js";
|
|
8
|
+
export function formatRuntimeStatusSummary(state) {
|
|
9
|
+
const parts = [];
|
|
10
|
+
if (state.sessionId) {
|
|
11
|
+
parts.push(`sid:${truncate(state.sessionId, 10)}`);
|
|
12
|
+
}
|
|
13
|
+
if (typeof state.turnCount === "number") {
|
|
14
|
+
parts.push(`turn:${state.turnCount}`);
|
|
15
|
+
}
|
|
16
|
+
if (state.agentName) {
|
|
17
|
+
parts.push(`role:${truncate(state.agentName, 12)}`);
|
|
18
|
+
}
|
|
19
|
+
if (state.taskName) {
|
|
20
|
+
parts.push(`task:${truncate(state.taskName, 18)}`);
|
|
21
|
+
}
|
|
22
|
+
if (state.preflightState) {
|
|
23
|
+
parts.push(`pf:${state.preflightState}`);
|
|
24
|
+
}
|
|
25
|
+
if (state.approvalState) {
|
|
26
|
+
parts.push(`approval:${state.approvalState}`);
|
|
27
|
+
}
|
|
28
|
+
if (state.retryState) {
|
|
29
|
+
parts.push(`retry:${state.retryState}`);
|
|
30
|
+
}
|
|
31
|
+
if (state.pollState) {
|
|
32
|
+
parts.push(`poll:${state.pollState}`);
|
|
33
|
+
}
|
|
34
|
+
return parts.length > 0 ? parts.join(" ") : undefined;
|
|
35
|
+
}
|
|
8
36
|
// ── Layout manager ───────────────────────────────────────────────────
|
|
9
37
|
export class LayoutManager {
|
|
10
38
|
zones;
|
|
@@ -116,12 +144,39 @@ export class LayoutManager {
|
|
|
116
144
|
stateIndicator = `${fg.red}${style.bold}${symbols.bullet} OVERDUE${style.reset}`;
|
|
117
145
|
break;
|
|
118
146
|
}
|
|
147
|
+
if (state.bridgeStatus === "approval_pending") {
|
|
148
|
+
stateIndicator = `${fg.yellow}${symbols.bullet} approval${style.reset}`;
|
|
149
|
+
}
|
|
150
|
+
else if (state.bridgeStatus === "retrying") {
|
|
151
|
+
stateIndicator = `${fg.yellow}${symbols.bullet} retrying${style.reset}`;
|
|
152
|
+
}
|
|
153
|
+
else if (state.bridgeStatus === "needs_input") {
|
|
154
|
+
stateIndicator = `${fg.yellow}${symbols.bullet} needs_input${style.reset}`;
|
|
155
|
+
}
|
|
156
|
+
if (state.activeTool) {
|
|
157
|
+
stateIndicator = `${fg.green}${symbols.bullet} ${state.activeTool}${style.reset}`;
|
|
158
|
+
}
|
|
159
|
+
const tabSeg = state.activeTabLabel
|
|
160
|
+
? `${fg.gray}tab: ${fg.white}${state.activeTabLabel}${style.reset}`
|
|
161
|
+
: undefined;
|
|
119
162
|
const providerSeg = `${fg.cyan}provider: ${fg.brightCyan}${state.provider}${style.reset}`;
|
|
120
163
|
const modelSeg = `${fg.cyan}model: ${fg.brightCyan}${state.model}${style.reset}`;
|
|
164
|
+
const runtimeSummary = formatRuntimeStatusSummary(state);
|
|
165
|
+
const runtimeSeg = runtimeSummary
|
|
166
|
+
? `${fg.gray}${runtimeSummary}${style.reset}`
|
|
167
|
+
: undefined;
|
|
121
168
|
const tokenSeg = `${fg.gray}tokens: ${fg.white}${formatNumber(state.tokensIn)}/${formatNumber(state.tokensOut)}${style.reset}`;
|
|
122
169
|
const timeSeg = `${fg.gray}${elapsed}${style.reset}`;
|
|
123
170
|
const clockSeg = `${fg.gray}${style.underline}${time}${style.reset}`;
|
|
124
|
-
const
|
|
171
|
+
const contextSeg = state.blockedReason
|
|
172
|
+
? `${fg.red}${truncate(state.blockedReason, Math.max(18, Math.floor(this.cols * 0.22)))}${style.reset}`
|
|
173
|
+
: state.nextAction
|
|
174
|
+
? `${fg.gray}next: ${fg.white}${truncate(state.nextAction, Math.max(18, Math.floor(this.cols * 0.18)))}${style.reset}`
|
|
175
|
+
: state.bridgeStatus
|
|
176
|
+
? `${fg.gray}${state.bridgeStatus}${style.reset}`
|
|
177
|
+
: undefined;
|
|
178
|
+
const segments = [stateIndicator, tabSeg, providerSeg, modelSeg, runtimeSeg, contextSeg, tokenSeg, timeSeg, clockSeg]
|
|
179
|
+
.filter((segment) => Boolean(segment));
|
|
125
180
|
const sep = ` ${fg.gray}│${style.reset} `;
|
|
126
181
|
const line = ` ${segments.join(sep)} `;
|
|
127
182
|
// Clear and write
|
|
@@ -198,13 +253,32 @@ export class LayoutManager {
|
|
|
198
253
|
renderStatusPanel(x, y, w, h, data) {
|
|
199
254
|
const lines = [
|
|
200
255
|
`${fg.gray}Phase: ${fg.brightWhite}${data.phase}`,
|
|
256
|
+
data.runtimeStatus?.bridge_status
|
|
257
|
+
? `${fg.gray}Bridge: ${fg.brightYellow}${data.runtimeStatus.bridge_status}`
|
|
258
|
+
: undefined,
|
|
259
|
+
data.runtimeStatus?.preflight_state
|
|
260
|
+
? `${fg.gray}Preflt: ${data.runtimeStatus.preflight_state === "blocked"
|
|
261
|
+
? fg.brightRed
|
|
262
|
+
: data.runtimeStatus.preflight_state === "attention_required"
|
|
263
|
+
? fg.yellow
|
|
264
|
+
: fg.brightGreen}${data.runtimeStatus.preflight_state}`
|
|
265
|
+
: undefined,
|
|
266
|
+
data.runtimeStatus?.role
|
|
267
|
+
? `${fg.gray}Role: ${fg.brightCyan}${data.runtimeStatus.role}`
|
|
268
|
+
: undefined,
|
|
269
|
+
data.runtimeStatus?.blocked_reason
|
|
270
|
+
? `${fg.gray}Blocker: ${fg.brightRed}${data.runtimeStatus.blocked_reason}`
|
|
271
|
+
: undefined,
|
|
272
|
+
data.runtimeStatus?.recommended_next_action
|
|
273
|
+
? `${fg.gray}Next: ${fg.white}${data.runtimeStatus.recommended_next_action}`
|
|
274
|
+
: undefined,
|
|
201
275
|
`${fg.gray}Provider:${fg.brightCyan} ${padRight(data.provider, 8)}`,
|
|
202
276
|
`${fg.gray}Model: ${fg.brightCyan}${data.model}`,
|
|
203
277
|
`${fg.gray}Agents: ${fg.brightGreen}${data.activeAgents}${fg.gray}/${data.totalAgents} active`,
|
|
204
278
|
`${fg.gray}Uptime: ${fg.white}${formatElapsed(Date.now() - data.startTime)}`,
|
|
205
279
|
`${fg.gray}Tokens: ${fg.white}${formatNumber(data.tokensIn)} in / ${formatNumber(data.tokensOut)} out`,
|
|
206
280
|
`${fg.gray}Speed: ${fg.white}${data.tokensPerSec.toFixed(0)} tok/s`,
|
|
207
|
-
];
|
|
281
|
+
].filter((line) => Boolean(line));
|
|
208
282
|
for (let i = 0; i < Math.min(lines.length, h); i++) {
|
|
209
283
|
writeAt(x, y + i, truncate(lines[i] + style.reset, w));
|
|
210
284
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { type AceStateResolution } from "../ace-state-resolver.js";
|
|
2
|
+
import type { AceRuntimeStatusPacket, AceSessionActivationLedger, AceSessionContinuityRecord } from "../store/repositories/local-model-runtime-repository.js";
|
|
3
|
+
export interface AcePreflightPacket {
|
|
4
|
+
session_id: string;
|
|
5
|
+
workspace_root: string;
|
|
6
|
+
state_resolution: AceStateResolution;
|
|
7
|
+
preflight_state: "ready" | "attention_required" | "blocked";
|
|
8
|
+
bridge_status: "running" | "needs_input" | "approval_pending" | "retrying" | "blocked" | "failed" | "done";
|
|
9
|
+
quartet_health: "healthy" | "thin" | "incomplete" | "contradictory";
|
|
10
|
+
task_contract_health: "healthy" | "thin" | "blocked";
|
|
11
|
+
recommended_role?: string;
|
|
12
|
+
recommended_next_action?: string;
|
|
13
|
+
blockers: string[];
|
|
14
|
+
warnings: string[];
|
|
15
|
+
recall_summary?: string;
|
|
16
|
+
should_synthesize_plan: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface StartupNudge {
|
|
19
|
+
id: string;
|
|
20
|
+
text: string;
|
|
21
|
+
recommended_action: string;
|
|
22
|
+
}
|
|
23
|
+
export declare function shouldSynthesizeShortPlan(task: string): boolean;
|
|
24
|
+
export declare function buildAcePreflightPacket(input: {
|
|
25
|
+
sessionId: string;
|
|
26
|
+
workspaceRoot: string;
|
|
27
|
+
task: string;
|
|
28
|
+
preferredRole?: string;
|
|
29
|
+
}): AcePreflightPacket;
|
|
30
|
+
export declare function nextActivationLedger(sessionId: string, current: AceSessionActivationLedger | undefined, recommendedAction: string | undefined): AceSessionActivationLedger;
|
|
31
|
+
export declare function buildStartupNudge(preflight: AcePreflightPacket, ledger: AceSessionActivationLedger): StartupNudge | undefined;
|
|
32
|
+
export declare function buildBridgeTaskInput(conversation: string, preflight: AcePreflightPacket): string;
|
|
33
|
+
export declare function mapBridgeResultToRuntimeStatus(input: {
|
|
34
|
+
current: AceRuntimeStatusPacket;
|
|
35
|
+
summary: string;
|
|
36
|
+
toolNames: string[];
|
|
37
|
+
}): AceRuntimeStatusPacket;
|
|
38
|
+
export declare function buildContinuityRecord(input: {
|
|
39
|
+
preflight: AcePreflightPacket;
|
|
40
|
+
role: string;
|
|
41
|
+
activeTool?: string;
|
|
42
|
+
bridgeStatus: AceRuntimeStatusPacket["bridge_status"];
|
|
43
|
+
evidenceRefs?: string[];
|
|
44
|
+
}): AceSessionContinuityRecord;
|
|
45
|
+
export declare function containsVerificationLanguage(text: string): boolean;
|
|
46
|
+
export declare function hasEvidenceLikeTool(toolNames: readonly string[]): boolean;
|
|
47
|
+
export declare function applyEvidenceGuardrail(summary: string, toolNames: readonly string[]): string;
|
|
48
|
+
export declare function readRuntimeWorkflowHint(workspaceRoot: string): string | undefined;
|
|
49
|
+
export declare function readStatusHint(workspaceRoot: string): string | undefined;
|
|
50
|
+
//# sourceMappingURL=local-model-contract.d.ts.map
|