@snoglobe/helios 0.3.6 → 0.4.0
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/__tests__/db-helper.d.ts +8 -0
- package/dist/__tests__/db-helper.d.ts.map +1 -0
- package/dist/__tests__/db-helper.js +15 -0
- package/dist/__tests__/db-helper.js.map +1 -0
- package/dist/config/project.test.d.ts +2 -0
- package/dist/config/project.test.d.ts.map +1 -0
- package/dist/config/project.test.js +219 -0
- package/dist/config/project.test.js.map +1 -0
- package/dist/core/orchestrator-integration.test.d.ts +2 -0
- package/dist/core/orchestrator-integration.test.d.ts.map +1 -0
- package/dist/core/orchestrator-integration.test.js +674 -0
- package/dist/core/orchestrator-integration.test.js.map +1 -0
- package/dist/core/orchestrator.d.ts +1 -0
- package/dist/core/orchestrator.d.ts.map +1 -1
- package/dist/core/orchestrator.js +81 -37
- package/dist/core/orchestrator.js.map +1 -1
- package/dist/core/orchestrator.test.d.ts +2 -0
- package/dist/core/orchestrator.test.d.ts.map +1 -0
- package/dist/core/orchestrator.test.js +982 -0
- package/dist/core/orchestrator.test.js.map +1 -0
- package/dist/core/state-machine.d.ts.map +1 -1
- package/dist/core/state-machine.js +3 -0
- package/dist/core/state-machine.js.map +1 -1
- package/dist/core/state-machine.test.d.ts +2 -0
- package/dist/core/state-machine.test.d.ts.map +1 -0
- package/dist/core/state-machine.test.js +95 -0
- package/dist/core/state-machine.test.js.map +1 -0
- package/dist/core/stickies.d.ts.map +1 -1
- package/dist/core/stickies.js +3 -0
- package/dist/core/stickies.js.map +1 -1
- package/dist/core/stickies.test.d.ts +2 -0
- package/dist/core/stickies.test.d.ts.map +1 -0
- package/dist/core/stickies.test.js +63 -0
- package/dist/core/stickies.test.js.map +1 -0
- package/dist/core/task-poller.d.ts.map +1 -1
- package/dist/core/task-poller.js +2 -1
- package/dist/core/task-poller.js.map +1 -1
- package/dist/init.d.ts +2 -0
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +19 -0
- package/dist/init.js.map +1 -1
- package/dist/memory/context-gate.test.d.ts +2 -0
- package/dist/memory/context-gate.test.d.ts.map +1 -0
- package/dist/memory/context-gate.test.js +318 -0
- package/dist/memory/context-gate.test.js.map +1 -0
- package/dist/memory/experiment-tracker.test.d.ts +2 -0
- package/dist/memory/experiment-tracker.test.d.ts.map +1 -0
- package/dist/memory/experiment-tracker.test.js +325 -0
- package/dist/memory/experiment-tracker.test.js.map +1 -0
- package/dist/memory/memory-store.d.ts +2 -0
- package/dist/memory/memory-store.d.ts.map +1 -1
- package/dist/memory/memory-store.js +35 -28
- package/dist/memory/memory-store.js.map +1 -1
- package/dist/memory/memory-store.test.d.ts +2 -0
- package/dist/memory/memory-store.test.d.ts.map +1 -0
- package/dist/memory/memory-store.test.js +144 -0
- package/dist/memory/memory-store.test.js.map +1 -0
- package/dist/memory/token-estimator.test.d.ts +2 -0
- package/dist/memory/token-estimator.test.d.ts.map +1 -0
- package/dist/memory/token-estimator.test.js +42 -0
- package/dist/memory/token-estimator.test.js.map +1 -0
- package/dist/metrics/analyzer.test.d.ts +2 -0
- package/dist/metrics/analyzer.test.d.ts.map +1 -0
- package/dist/metrics/analyzer.test.js +65 -0
- package/dist/metrics/analyzer.test.js.map +1 -0
- package/dist/metrics/parser.test.d.ts +2 -0
- package/dist/metrics/parser.test.d.ts.map +1 -0
- package/dist/metrics/parser.test.js +106 -0
- package/dist/metrics/parser.test.js.map +1 -0
- package/dist/metrics/store.d.ts +2 -0
- package/dist/metrics/store.d.ts.map +1 -1
- package/dist/metrics/store.js +26 -50
- package/dist/metrics/store.js.map +1 -1
- package/dist/metrics/store.test.d.ts +2 -0
- package/dist/metrics/store.test.d.ts.map +1 -0
- package/dist/metrics/store.test.js +148 -0
- package/dist/metrics/store.test.js.map +1 -0
- package/dist/paths.js +5 -5
- package/dist/paths.js.map +1 -1
- package/dist/providers/auth/auth-manager.d.ts +1 -0
- package/dist/providers/auth/auth-manager.d.ts.map +1 -1
- package/dist/providers/auth/auth-manager.js +8 -1
- package/dist/providers/auth/auth-manager.js.map +1 -1
- package/dist/providers/auth/auth-manager.test.d.ts +2 -0
- package/dist/providers/auth/auth-manager.test.d.ts.map +1 -0
- package/dist/providers/auth/auth-manager.test.js +364 -0
- package/dist/providers/auth/auth-manager.test.js.map +1 -0
- package/dist/providers/auth/token-store.js +2 -2
- package/dist/providers/auth/token-store.js.map +1 -1
- package/dist/providers/claude/history.test.d.ts +2 -0
- package/dist/providers/claude/history.test.d.ts.map +1 -0
- package/dist/providers/claude/history.test.js +755 -0
- package/dist/providers/claude/history.test.js.map +1 -0
- package/dist/providers/claude/provider.d.ts +3 -1
- package/dist/providers/claude/provider.d.ts.map +1 -1
- package/dist/providers/claude/provider.js +33 -19
- package/dist/providers/claude/provider.js.map +1 -1
- package/dist/providers/claude/provider.test.d.ts +2 -0
- package/dist/providers/claude/provider.test.d.ts.map +1 -0
- package/dist/providers/claude/provider.test.js +1167 -0
- package/dist/providers/claude/provider.test.js.map +1 -0
- package/dist/providers/openai/history.test.d.ts +2 -0
- package/dist/providers/openai/history.test.d.ts.map +1 -0
- package/dist/providers/openai/history.test.js +655 -0
- package/dist/providers/openai/history.test.js.map +1 -0
- package/dist/providers/openai/provider.d.ts +2 -1
- package/dist/providers/openai/provider.d.ts.map +1 -1
- package/dist/providers/openai/provider.js +14 -8
- package/dist/providers/openai/provider.js.map +1 -1
- package/dist/providers/openai/provider.test.d.ts +2 -0
- package/dist/providers/openai/provider.test.d.ts.map +1 -0
- package/dist/providers/openai/provider.test.js +1089 -0
- package/dist/providers/openai/provider.test.js.map +1 -0
- package/dist/providers/retry.test.d.ts +2 -0
- package/dist/providers/retry.test.d.ts.map +1 -0
- package/dist/providers/retry.test.js +194 -0
- package/dist/providers/retry.test.js.map +1 -0
- package/dist/providers/sse.d.ts +1 -0
- package/dist/providers/sse.d.ts.map +1 -1
- package/dist/providers/sse.js +29 -20
- package/dist/providers/sse.js.map +1 -1
- package/dist/providers/sse.test.d.ts +2 -0
- package/dist/providers/sse.test.d.ts.map +1 -0
- package/dist/providers/sse.test.js +79 -0
- package/dist/providers/sse.test.js.map +1 -0
- package/dist/providers/types.test.d.ts +2 -0
- package/dist/providers/types.test.d.ts.map +1 -0
- package/dist/providers/types.test.js +112 -0
- package/dist/providers/types.test.js.map +1 -0
- package/dist/remote/connection-pool.d.ts.map +1 -1
- package/dist/remote/connection-pool.js +24 -3
- package/dist/remote/connection-pool.js.map +1 -1
- package/dist/remote/file-sync.d.ts.map +1 -1
- package/dist/remote/file-sync.js +4 -3
- package/dist/remote/file-sync.js.map +1 -1
- package/dist/scheduler/sleep-manager.d.ts.map +1 -1
- package/dist/scheduler/sleep-manager.js +8 -1
- package/dist/scheduler/sleep-manager.js.map +1 -1
- package/dist/scheduler/sleep-manager.test.d.ts +2 -0
- package/dist/scheduler/sleep-manager.test.d.ts.map +1 -0
- package/dist/scheduler/sleep-manager.test.js +491 -0
- package/dist/scheduler/sleep-manager.test.js.map +1 -0
- package/dist/scheduler/ssh-batcher.d.ts.map +1 -1
- package/dist/scheduler/ssh-batcher.js +6 -4
- package/dist/scheduler/ssh-batcher.js.map +1 -1
- package/dist/scheduler/ssh-batcher.test.d.ts +2 -0
- package/dist/scheduler/ssh-batcher.test.d.ts.map +1 -0
- package/dist/scheduler/ssh-batcher.test.js +76 -0
- package/dist/scheduler/ssh-batcher.test.js.map +1 -0
- package/dist/scheduler/state-store.d.ts.map +1 -1
- package/dist/scheduler/state-store.js +1 -2
- package/dist/scheduler/state-store.js.map +1 -1
- package/dist/scheduler/trigger-scheduler.d.ts.map +1 -1
- package/dist/scheduler/trigger-scheduler.js +59 -36
- package/dist/scheduler/trigger-scheduler.js.map +1 -1
- package/dist/scheduler/trigger-scheduler.test.d.ts +2 -0
- package/dist/scheduler/trigger-scheduler.test.d.ts.map +1 -0
- package/dist/scheduler/trigger-scheduler.test.js +483 -0
- package/dist/scheduler/trigger-scheduler.test.js.map +1 -0
- package/dist/scheduler/triggers/file.d.ts.map +1 -1
- package/dist/scheduler/triggers/file.js +12 -3
- package/dist/scheduler/triggers/file.js.map +1 -1
- package/dist/scheduler/triggers/file.test.d.ts +2 -0
- package/dist/scheduler/triggers/file.test.d.ts.map +1 -0
- package/dist/scheduler/triggers/file.test.js +294 -0
- package/dist/scheduler/triggers/file.test.js.map +1 -0
- package/dist/scheduler/triggers/metric.d.ts +3 -1
- package/dist/scheduler/triggers/metric.d.ts.map +1 -1
- package/dist/scheduler/triggers/metric.js +12 -8
- package/dist/scheduler/triggers/metric.js.map +1 -1
- package/dist/scheduler/triggers/metric.test.d.ts +2 -0
- package/dist/scheduler/triggers/metric.test.d.ts.map +1 -0
- package/dist/scheduler/triggers/metric.test.js +533 -0
- package/dist/scheduler/triggers/metric.test.js.map +1 -0
- package/dist/scheduler/triggers/process-exit.d.ts.map +1 -1
- package/dist/scheduler/triggers/process-exit.js +2 -1
- package/dist/scheduler/triggers/process-exit.js.map +1 -1
- package/dist/scheduler/triggers/process-exit.test.d.ts +2 -0
- package/dist/scheduler/triggers/process-exit.test.d.ts.map +1 -0
- package/dist/scheduler/triggers/process-exit.test.js +118 -0
- package/dist/scheduler/triggers/process-exit.test.js.map +1 -0
- package/dist/scheduler/triggers/resource.d.ts.map +1 -1
- package/dist/scheduler/triggers/resource.js +2 -10
- package/dist/scheduler/triggers/resource.js.map +1 -1
- package/dist/scheduler/triggers/resource.test.d.ts +2 -0
- package/dist/scheduler/triggers/resource.test.d.ts.map +1 -0
- package/dist/scheduler/triggers/resource.test.js +225 -0
- package/dist/scheduler/triggers/resource.test.js.map +1 -0
- package/dist/scheduler/triggers/timer.test.d.ts +2 -0
- package/dist/scheduler/triggers/timer.test.d.ts.map +1 -0
- package/dist/scheduler/triggers/timer.test.js +56 -0
- package/dist/scheduler/triggers/timer.test.js.map +1 -0
- package/dist/scheduler/triggers/types.d.ts +4 -2
- package/dist/scheduler/triggers/types.d.ts.map +1 -1
- package/dist/scheduler/triggers/types.js +0 -1
- package/dist/scheduler/triggers/types.js.map +1 -1
- package/dist/skills/executor.d.ts.map +1 -1
- package/dist/skills/executor.js +13 -15
- package/dist/skills/executor.js.map +1 -1
- package/dist/store/database.d.ts +5 -0
- package/dist/store/database.d.ts.map +1 -1
- package/dist/store/database.js +17 -1
- package/dist/store/database.js.map +1 -1
- package/dist/store/migrations.test.d.ts +2 -0
- package/dist/store/migrations.test.d.ts.map +1 -0
- package/dist/store/migrations.test.js +278 -0
- package/dist/store/migrations.test.js.map +1 -0
- package/dist/store/session-store-edge.test.d.ts +2 -0
- package/dist/store/session-store-edge.test.d.ts.map +1 -0
- package/dist/store/session-store-edge.test.js +522 -0
- package/dist/store/session-store-edge.test.js.map +1 -0
- package/dist/store/session-store.d.ts +6 -0
- package/dist/store/session-store.d.ts.map +1 -1
- package/dist/store/session-store.js +25 -24
- package/dist/store/session-store.js.map +1 -1
- package/dist/store/session-store.test.d.ts +2 -0
- package/dist/store/session-store.test.d.ts.map +1 -0
- package/dist/store/session-store.test.js +125 -0
- package/dist/store/session-store.test.js.map +1 -0
- package/dist/subagent/executor.d.ts +21 -0
- package/dist/subagent/executor.d.ts.map +1 -0
- package/dist/subagent/executor.js +136 -0
- package/dist/subagent/executor.js.map +1 -0
- package/dist/subagent/manager.d.ts +20 -0
- package/dist/subagent/manager.d.ts.map +1 -0
- package/dist/subagent/manager.js +98 -0
- package/dist/subagent/manager.js.map +1 -0
- package/dist/subagent/scoped-memory.d.ts +28 -0
- package/dist/subagent/scoped-memory.d.ts.map +1 -0
- package/dist/subagent/scoped-memory.js +122 -0
- package/dist/subagent/scoped-memory.js.map +1 -0
- package/dist/subagent/types.d.ts +27 -0
- package/dist/subagent/types.d.ts.map +1 -0
- package/dist/subagent/types.js +2 -0
- package/dist/subagent/types.js.map +1 -0
- package/dist/tools/file-ops.d.ts.map +1 -1
- package/dist/tools/file-ops.js +23 -13
- package/dist/tools/file-ops.js.map +1 -1
- package/dist/tools/file-ops.test.d.ts +2 -0
- package/dist/tools/file-ops.test.d.ts.map +1 -0
- package/dist/tools/file-ops.test.js +656 -0
- package/dist/tools/file-ops.test.js.map +1 -0
- package/dist/tools/memory-tools.test.d.ts +2 -0
- package/dist/tools/memory-tools.test.d.ts.map +1 -0
- package/dist/tools/memory-tools.test.js +273 -0
- package/dist/tools/memory-tools.test.js.map +1 -0
- package/dist/tools/subagent.d.ts +10 -0
- package/dist/tools/subagent.d.ts.map +1 -0
- package/dist/tools/subagent.js +164 -0
- package/dist/tools/subagent.js.map +1 -0
- package/dist/tools/task-output.d.ts.map +1 -1
- package/dist/tools/task-output.js +13 -2
- package/dist/tools/task-output.js.map +1 -1
- package/dist/ui/components/input-bar.d.ts +1 -1
- package/dist/ui/components/input-bar.d.ts.map +1 -1
- package/dist/ui/components/input-bar.js +3 -3
- package/dist/ui/components/input-bar.js.map +1 -1
- package/dist/ui/components/input-bar.test.d.ts +2 -0
- package/dist/ui/components/input-bar.test.d.ts.map +1 -0
- package/dist/ui/components/input-bar.test.js +380 -0
- package/dist/ui/components/input-bar.test.js.map +1 -0
- package/dist/ui/components/key-hint-rule.d.ts +2 -1
- package/dist/ui/components/key-hint-rule.d.ts.map +1 -1
- package/dist/ui/components/key-hint-rule.js +3 -3
- package/dist/ui/components/key-hint-rule.js.map +1 -1
- package/dist/ui/components/status-bar.d.ts +1 -1
- package/dist/ui/components/status-bar.d.ts.map +1 -1
- package/dist/ui/components/status-bar.js +11 -10
- package/dist/ui/components/status-bar.js.map +1 -1
- package/dist/ui/components/status-bar.test.d.ts +2 -0
- package/dist/ui/components/status-bar.test.d.ts.map +1 -0
- package/dist/ui/components/status-bar.test.js +206 -0
- package/dist/ui/components/status-bar.test.js.map +1 -0
- package/dist/ui/format.d.ts +9 -0
- package/dist/ui/format.d.ts.map +1 -1
- package/dist/ui/format.js +21 -0
- package/dist/ui/format.js.map +1 -1
- package/dist/ui/format.test.d.ts +2 -0
- package/dist/ui/format.test.d.ts.map +1 -0
- package/dist/ui/format.test.js +122 -0
- package/dist/ui/format.test.js.map +1 -0
- package/dist/ui/layout.d.ts.map +1 -1
- package/dist/ui/layout.js +63 -11
- package/dist/ui/layout.js.map +1 -1
- package/dist/ui/markdown.test.d.ts +2 -0
- package/dist/ui/markdown.test.d.ts.map +1 -0
- package/dist/ui/markdown.test.js +133 -0
- package/dist/ui/markdown.test.js.map +1 -0
- package/dist/ui/mouse-filter.test.d.ts +2 -0
- package/dist/ui/mouse-filter.test.d.ts.map +1 -0
- package/dist/ui/mouse-filter.test.js +231 -0
- package/dist/ui/mouse-filter.test.js.map +1 -0
- package/dist/ui/overlays/metrics-overlay.test.d.ts +2 -0
- package/dist/ui/overlays/metrics-overlay.test.d.ts.map +1 -0
- package/dist/ui/overlays/metrics-overlay.test.js +248 -0
- package/dist/ui/overlays/metrics-overlay.test.js.map +1 -0
- package/dist/ui/overlays/task-overlay.test.d.ts +2 -0
- package/dist/ui/overlays/task-overlay.test.d.ts.map +1 -0
- package/dist/ui/overlays/task-overlay.test.js +238 -0
- package/dist/ui/overlays/task-overlay.test.js.map +1 -0
- package/dist/ui/panels/conversation.d.ts.map +1 -1
- package/dist/ui/panels/conversation.js +60 -5
- package/dist/ui/panels/conversation.js.map +1 -1
- package/dist/ui/panels/conversation.test.d.ts +2 -0
- package/dist/ui/panels/conversation.test.d.ts.map +1 -0
- package/dist/ui/panels/conversation.test.js +381 -0
- package/dist/ui/panels/conversation.test.js.map +1 -0
- package/dist/ui/panels/metrics-dashboard.test.d.ts +2 -0
- package/dist/ui/panels/metrics-dashboard.test.d.ts.map +1 -0
- package/dist/ui/panels/metrics-dashboard.test.js +191 -0
- package/dist/ui/panels/metrics-dashboard.test.js.map +1 -0
- package/dist/ui/panels/sleep-panel.test.d.ts +2 -0
- package/dist/ui/panels/sleep-panel.test.d.ts.map +1 -0
- package/dist/ui/panels/sleep-panel.test.js +376 -0
- package/dist/ui/panels/sleep-panel.test.js.map +1 -0
- package/dist/ui/panels/task-list.d.ts.map +1 -1
- package/dist/ui/panels/task-list.js +3 -2
- package/dist/ui/panels/task-list.js.map +1 -1
- package/dist/ui/panels/task-list.test.d.ts +2 -0
- package/dist/ui/panels/task-list.test.d.ts.map +1 -0
- package/dist/ui/panels/task-list.test.js +210 -0
- package/dist/ui/panels/task-list.test.js.map +1 -0
- package/dist/ui/theme.test.d.ts +2 -0
- package/dist/ui/theme.test.d.ts.map +1 -0
- package/dist/ui/theme.test.js +159 -0
- package/dist/ui/theme.test.js.map +1 -0
- package/dist/ui/types.d.ts +3 -0
- package/dist/ui/types.d.ts.map +1 -1
- package/package.json +6 -2
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { C } from "../theme.js";
|
|
3
|
+
import { formatDuration } from "../format.js";
|
|
4
|
+
// ─── Copies of module-level constants from status-bar.tsx ────────
|
|
5
|
+
const SLEEP_FRAMES = ["\u25c7", "\u25c6", "\u25c7", "\u25c7"];
|
|
6
|
+
const STATE_COLOR = {
|
|
7
|
+
idle: C.dim,
|
|
8
|
+
active: C.primary,
|
|
9
|
+
sleeping: C.primary,
|
|
10
|
+
waiting: C.dim,
|
|
11
|
+
error: C.error,
|
|
12
|
+
};
|
|
13
|
+
// ─── Cost formatting logic (inline in the component) ─────────────
|
|
14
|
+
function formatCost(cost) {
|
|
15
|
+
return `$${cost.toFixed(4)}`;
|
|
16
|
+
}
|
|
17
|
+
// ─── Tests ───────────────────────────────────────────────────────
|
|
18
|
+
describe("STATE_COLOR mapping", () => {
|
|
19
|
+
it("has all expected states", () => {
|
|
20
|
+
const expectedStates = ["idle", "active", "sleeping", "waiting", "error"];
|
|
21
|
+
for (const state of expectedStates) {
|
|
22
|
+
expect(STATE_COLOR[state]).toBeDefined();
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
it("maps idle to dim", () => {
|
|
26
|
+
expect(STATE_COLOR["idle"]).toBe(C.dim);
|
|
27
|
+
expect(STATE_COLOR["idle"]).toBe("gray");
|
|
28
|
+
});
|
|
29
|
+
it("maps active to primary", () => {
|
|
30
|
+
expect(STATE_COLOR["active"]).toBe(C.primary);
|
|
31
|
+
expect(STATE_COLOR["active"]).toBe("yellow");
|
|
32
|
+
});
|
|
33
|
+
it("maps sleeping to primary", () => {
|
|
34
|
+
expect(STATE_COLOR["sleeping"]).toBe(C.primary);
|
|
35
|
+
expect(STATE_COLOR["sleeping"]).toBe("yellow");
|
|
36
|
+
});
|
|
37
|
+
it("maps waiting to dim", () => {
|
|
38
|
+
expect(STATE_COLOR["waiting"]).toBe(C.dim);
|
|
39
|
+
expect(STATE_COLOR["waiting"]).toBe("gray");
|
|
40
|
+
});
|
|
41
|
+
it("maps error to error", () => {
|
|
42
|
+
expect(STATE_COLOR["error"]).toBe(C.error);
|
|
43
|
+
expect(STATE_COLOR["error"]).toBe("red");
|
|
44
|
+
});
|
|
45
|
+
it("returns undefined for unknown state (fallback in component uses C.dim)", () => {
|
|
46
|
+
expect(STATE_COLOR["unknown"]).toBeUndefined();
|
|
47
|
+
// The component does: STATE_COLOR[state] ?? C.dim
|
|
48
|
+
expect(STATE_COLOR["bogus"] ?? C.dim).toBe(C.dim);
|
|
49
|
+
});
|
|
50
|
+
it("active and sleeping share the same color", () => {
|
|
51
|
+
expect(STATE_COLOR["active"]).toBe(STATE_COLOR["sleeping"]);
|
|
52
|
+
});
|
|
53
|
+
it("idle and waiting share the same color", () => {
|
|
54
|
+
expect(STATE_COLOR["idle"]).toBe(STATE_COLOR["waiting"]);
|
|
55
|
+
});
|
|
56
|
+
it("error has a unique color", () => {
|
|
57
|
+
const otherColors = ["idle", "active", "sleeping", "waiting"].map((s) => STATE_COLOR[s]);
|
|
58
|
+
expect(otherColors).not.toContain(STATE_COLOR["error"]);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
describe("cost formatting", () => {
|
|
62
|
+
it("formats zero cost", () => {
|
|
63
|
+
expect(formatCost(0)).toBe("$0.0000");
|
|
64
|
+
});
|
|
65
|
+
it("formats small cost with 4 decimal places", () => {
|
|
66
|
+
expect(formatCost(0.0012)).toBe("$0.0012");
|
|
67
|
+
});
|
|
68
|
+
it("formats typical API cost", () => {
|
|
69
|
+
expect(formatCost(0.0345)).toBe("$0.0345");
|
|
70
|
+
});
|
|
71
|
+
it("formats cost over one dollar", () => {
|
|
72
|
+
expect(formatCost(1.2345)).toBe("$1.2345");
|
|
73
|
+
});
|
|
74
|
+
it("formats cost with rounding", () => {
|
|
75
|
+
expect(formatCost(0.00005)).toBe("$0.0001");
|
|
76
|
+
expect(formatCost(0.00004)).toBe("$0.0000");
|
|
77
|
+
});
|
|
78
|
+
it("formats larger costs", () => {
|
|
79
|
+
expect(formatCost(10.5)).toBe("$10.5000");
|
|
80
|
+
expect(formatCost(100)).toBe("$100.0000");
|
|
81
|
+
});
|
|
82
|
+
it("cost is only shown when > 0 (component logic)", () => {
|
|
83
|
+
// The component renders cost only when cost > 0
|
|
84
|
+
const cost = 0;
|
|
85
|
+
const shouldShow = cost > 0;
|
|
86
|
+
expect(shouldShow).toBe(false);
|
|
87
|
+
const cost2 = 0.0001;
|
|
88
|
+
expect(cost2 > 0).toBe(true);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
describe("SLEEP_FRAMES", () => {
|
|
92
|
+
it("has exactly 4 frames", () => {
|
|
93
|
+
expect(SLEEP_FRAMES).toHaveLength(4);
|
|
94
|
+
});
|
|
95
|
+
it("contains diamond glyphs", () => {
|
|
96
|
+
// ◇ = \u25c7 (open diamond), ◆ = \u25c6 (filled diamond)
|
|
97
|
+
expect(SLEEP_FRAMES[0]).toBe("\u25c7"); // ◇
|
|
98
|
+
expect(SLEEP_FRAMES[1]).toBe("\u25c6"); // ◆
|
|
99
|
+
expect(SLEEP_FRAMES[2]).toBe("\u25c7"); // ◇
|
|
100
|
+
expect(SLEEP_FRAMES[3]).toBe("\u25c7"); // ◇
|
|
101
|
+
});
|
|
102
|
+
it("frame sequence has one filled diamond and three open", () => {
|
|
103
|
+
const filled = SLEEP_FRAMES.filter((f) => f === "\u25c6");
|
|
104
|
+
const open = SLEEP_FRAMES.filter((f) => f === "\u25c7");
|
|
105
|
+
expect(filled).toHaveLength(1);
|
|
106
|
+
expect(open).toHaveLength(3);
|
|
107
|
+
});
|
|
108
|
+
it("animation cycles correctly (frame index mod length)", () => {
|
|
109
|
+
// The component does: setFrame((f) => (f + 1) % SLEEP_FRAMES.length)
|
|
110
|
+
const length = SLEEP_FRAMES.length;
|
|
111
|
+
expect(0 % length).toBe(0);
|
|
112
|
+
expect(1 % length).toBe(1);
|
|
113
|
+
expect(2 % length).toBe(2);
|
|
114
|
+
expect(3 % length).toBe(3);
|
|
115
|
+
expect(4 % length).toBe(0); // wraps around
|
|
116
|
+
expect(5 % length).toBe(1);
|
|
117
|
+
});
|
|
118
|
+
it("each frame is a single character", () => {
|
|
119
|
+
for (const frame of SLEEP_FRAMES) {
|
|
120
|
+
expect(frame).toHaveLength(1);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
describe("work elapsed time formatting", () => {
|
|
125
|
+
it("formats zero elapsed", () => {
|
|
126
|
+
expect(formatDuration(0)).toBe("0s");
|
|
127
|
+
});
|
|
128
|
+
it("formats seconds", () => {
|
|
129
|
+
expect(formatDuration(5000)).toBe("5s");
|
|
130
|
+
expect(formatDuration(30000)).toBe("30s");
|
|
131
|
+
});
|
|
132
|
+
it("formats minutes and seconds", () => {
|
|
133
|
+
expect(formatDuration(65000)).toBe("1m 5s");
|
|
134
|
+
expect(formatDuration(120000)).toBe("2m 0s");
|
|
135
|
+
});
|
|
136
|
+
it("formats hours and minutes", () => {
|
|
137
|
+
expect(formatDuration(3660000)).toBe("1h 1m");
|
|
138
|
+
expect(formatDuration(7200000)).toBe("2h 0m");
|
|
139
|
+
});
|
|
140
|
+
it("elapsed updates correctly (component logic)", () => {
|
|
141
|
+
// The component does: setWorkElapsed(Date.now() - streamingStartedAt)
|
|
142
|
+
const streamingStartedAt = 1000;
|
|
143
|
+
const now = 6000;
|
|
144
|
+
expect(now - streamingStartedAt).toBe(5000);
|
|
145
|
+
expect(formatDuration(now - streamingStartedAt)).toBe("5s");
|
|
146
|
+
});
|
|
147
|
+
it("elapsed resets when streaming stops", () => {
|
|
148
|
+
// Component sets workElapsed to 0 when !isStreaming
|
|
149
|
+
const isStreaming = false;
|
|
150
|
+
const workElapsed = isStreaming ? 5000 : 0;
|
|
151
|
+
expect(workElapsed).toBe(0);
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
describe("provider/model display logic", () => {
|
|
155
|
+
it("displays dash for missing provider", () => {
|
|
156
|
+
const provider = undefined;
|
|
157
|
+
const displayName = provider?.displayName ?? "\u2014";
|
|
158
|
+
expect(displayName).toBe("\u2014");
|
|
159
|
+
});
|
|
160
|
+
it("displays provider name when available", () => {
|
|
161
|
+
const provider = { displayName: "Claude" };
|
|
162
|
+
const displayName = provider?.displayName ?? "\u2014";
|
|
163
|
+
expect(displayName).toBe("Claude");
|
|
164
|
+
});
|
|
165
|
+
it("displays dash for missing model", () => {
|
|
166
|
+
const model = undefined;
|
|
167
|
+
const display = model ?? "\u2014";
|
|
168
|
+
expect(display).toBe("\u2014");
|
|
169
|
+
});
|
|
170
|
+
it("displays model when available", () => {
|
|
171
|
+
const model = "claude-sonnet-4-20250514";
|
|
172
|
+
const display = model ?? "\u2014";
|
|
173
|
+
expect(display).toBe("claude-sonnet-4-20250514");
|
|
174
|
+
});
|
|
175
|
+
it("displays reasoning effort with medium as default", () => {
|
|
176
|
+
const reasoning1 = undefined;
|
|
177
|
+
expect(reasoning1 ?? "medium").toBe("medium");
|
|
178
|
+
const reasoning2 = "high";
|
|
179
|
+
expect(reasoning2 ?? "medium").toBe("high");
|
|
180
|
+
const reasoning3 = "low";
|
|
181
|
+
expect(reasoning3 ?? "medium").toBe("low");
|
|
182
|
+
});
|
|
183
|
+
it("state color falls back to dim for unknown state", () => {
|
|
184
|
+
const state = "something_else";
|
|
185
|
+
const stateColor = STATE_COLOR[state] ?? C.dim;
|
|
186
|
+
expect(stateColor).toBe(C.dim);
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
describe("sleep elapsed time formatting", () => {
|
|
190
|
+
it("formats sleep duration from session createdAt", () => {
|
|
191
|
+
const createdAt = Date.now() - 120_000; // 2 minutes ago
|
|
192
|
+
const elapsed = Date.now() - createdAt;
|
|
193
|
+
// Should be approximately "2m 0s" (within a second of tolerance)
|
|
194
|
+
const formatted = formatDuration(elapsed);
|
|
195
|
+
expect(formatted).toMatch(/^2m \d+s$/);
|
|
196
|
+
});
|
|
197
|
+
it("formats short sleep durations", () => {
|
|
198
|
+
expect(formatDuration(500)).toBe("0s");
|
|
199
|
+
expect(formatDuration(1500)).toBe("1s");
|
|
200
|
+
});
|
|
201
|
+
it("formats long sleep durations", () => {
|
|
202
|
+
expect(formatDuration(7_200_000)).toBe("2h 0m");
|
|
203
|
+
expect(formatDuration(86_400_000)).toBe("24h 0m");
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
//# sourceMappingURL=status-bar.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status-bar.test.js","sourceRoot":"","sources":["../../../src/ui/components/status-bar.test.ts"],"names":[],"mappings":"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"}
|
package/dist/ui/format.d.ts
CHANGED
|
@@ -13,6 +13,15 @@ export declare function formatError(err: unknown): string;
|
|
|
13
13
|
export declare function formatBytes(bytes: number): string;
|
|
14
14
|
/** Shell-escape a string using single quotes. */
|
|
15
15
|
export declare function shellQuote(s: string): string;
|
|
16
|
+
/** Coerce an unknown thrown value to an Error instance. */
|
|
17
|
+
export declare function toError(err: unknown): Error;
|
|
18
|
+
/** Run a promise with a timeout. Cleans up the timer on completion. */
|
|
19
|
+
export declare function withTimeout<T>(promise: Promise<T>, ms: number, label: string): Promise<T>;
|
|
20
|
+
/** Split stdout at a sentinel string, returning before/after parts. */
|
|
21
|
+
export declare function splitAtSentinel(output: string, sentinel: string): {
|
|
22
|
+
before: string;
|
|
23
|
+
after: string;
|
|
24
|
+
} | null;
|
|
16
25
|
/** Standard JSON error response for tool execute() returns. */
|
|
17
26
|
export declare function toolError(err: unknown): string;
|
|
18
27
|
/** Standard JSON success response for tool execute() returns. */
|
package/dist/ui/format.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/ui/format.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,0EAA0E;AAC1E,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED,0FAA0F;AAC1F,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAOjD;AAED,oFAAoF;AACpF,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,UAAQ,GAAG,MAAM,CAIxE;AAED,iDAAiD;AACjD,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAEhD;AAED,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMjD;AAED,iDAAiD;AACjD,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED,+DAA+D;AAC/D,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAE9C;AAED,iEAAiE;AACjE,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAEhD"}
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/ui/format.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,0EAA0E;AAC1E,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED,0FAA0F;AAC1F,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAOjD;AAED,oFAAoF;AACpF,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,UAAQ,GAAG,MAAM,CAIxE;AAED,iDAAiD;AACjD,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAEhD;AAED,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMjD;AAED,iDAAiD;AACjD,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED,2DAA2D;AAC3D,wBAAgB,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,KAAK,CAE3C;AAED,uEAAuE;AACvE,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAQzF;AAED,uEAAuE;AACvE,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAI1G;AAED,+DAA+D;AAC/D,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAE9C;AAED,iEAAiE;AACjE,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAEhD"}
|
package/dist/ui/format.js
CHANGED
|
@@ -49,6 +49,27 @@ export function formatBytes(bytes) {
|
|
|
49
49
|
export function shellQuote(s) {
|
|
50
50
|
return "'" + s.replace(/'/g, "'\\''") + "'";
|
|
51
51
|
}
|
|
52
|
+
/** Coerce an unknown thrown value to an Error instance. */
|
|
53
|
+
export function toError(err) {
|
|
54
|
+
return err instanceof Error ? err : new Error(String(err));
|
|
55
|
+
}
|
|
56
|
+
/** Run a promise with a timeout. Cleans up the timer on completion. */
|
|
57
|
+
export function withTimeout(promise, ms, label) {
|
|
58
|
+
let timer;
|
|
59
|
+
return Promise.race([
|
|
60
|
+
promise,
|
|
61
|
+
new Promise((_, reject) => {
|
|
62
|
+
timer = setTimeout(() => reject(new Error(`"${label}" timed out after ${ms / 1000}s`)), ms);
|
|
63
|
+
}),
|
|
64
|
+
]).finally(() => clearTimeout(timer));
|
|
65
|
+
}
|
|
66
|
+
/** Split stdout at a sentinel string, returning before/after parts. */
|
|
67
|
+
export function splitAtSentinel(output, sentinel) {
|
|
68
|
+
const idx = output.lastIndexOf(sentinel);
|
|
69
|
+
if (idx < 0)
|
|
70
|
+
return null;
|
|
71
|
+
return { before: output.slice(0, idx), after: output.slice(idx + sentinel.length).trim() };
|
|
72
|
+
}
|
|
52
73
|
/** Standard JSON error response for tool execute() returns. */
|
|
53
74
|
export function toolError(err) {
|
|
54
75
|
return JSON.stringify({ error: formatError(err) });
|
package/dist/ui/format.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/ui/format.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/ui/format.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.test.d.ts","sourceRoot":"","sources":["../../src/ui/format.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { formatMetricValue, formatDuration, truncate, formatError, formatBytes, shellQuote, toolError, toolResult, } from "./format.js";
|
|
3
|
+
describe("formatMetricValue", () => {
|
|
4
|
+
it("formats large numbers with 1 decimal", () => {
|
|
5
|
+
expect(formatMetricValue(1234.5)).toBe("1234.5");
|
|
6
|
+
expect(formatMetricValue(-5000)).toBe("-5000.0");
|
|
7
|
+
});
|
|
8
|
+
it("formats values >= 1 with 4 significant digits", () => {
|
|
9
|
+
expect(formatMetricValue(3.14159)).toBe("3.142");
|
|
10
|
+
expect(formatMetricValue(99.99)).toBe("99.99"); // 4 significant digits
|
|
11
|
+
});
|
|
12
|
+
it("formats small values with 3 significant digits", () => {
|
|
13
|
+
expect(formatMetricValue(0.00567)).toBe("0.00567");
|
|
14
|
+
});
|
|
15
|
+
it("formats very small values in scientific notation", () => {
|
|
16
|
+
expect(formatMetricValue(0.000001)).toBe("1.00e-6");
|
|
17
|
+
});
|
|
18
|
+
it("handles zero", () => {
|
|
19
|
+
expect(formatMetricValue(0)).toBe("0.00e+0");
|
|
20
|
+
});
|
|
21
|
+
it("handles negative values", () => {
|
|
22
|
+
expect(formatMetricValue(-0.5)).toBe("-0.500");
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
describe("formatDuration", () => {
|
|
26
|
+
it("formats seconds", () => {
|
|
27
|
+
expect(formatDuration(0)).toBe("0s");
|
|
28
|
+
expect(formatDuration(5000)).toBe("5s");
|
|
29
|
+
expect(formatDuration(59000)).toBe("59s");
|
|
30
|
+
});
|
|
31
|
+
it("formats minutes and seconds", () => {
|
|
32
|
+
expect(formatDuration(60000)).toBe("1m 0s");
|
|
33
|
+
expect(formatDuration(90000)).toBe("1m 30s");
|
|
34
|
+
expect(formatDuration(3599000)).toBe("59m 59s");
|
|
35
|
+
});
|
|
36
|
+
it("formats hours and minutes", () => {
|
|
37
|
+
expect(formatDuration(3600000)).toBe("1h 0m");
|
|
38
|
+
expect(formatDuration(7500000)).toBe("2h 5m");
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
describe("truncate", () => {
|
|
42
|
+
it("returns short strings unchanged", () => {
|
|
43
|
+
expect(truncate("hello", 10)).toBe("hello");
|
|
44
|
+
});
|
|
45
|
+
it("truncates with ellipsis", () => {
|
|
46
|
+
expect(truncate("hello world", 6)).toBe("hello\u2026");
|
|
47
|
+
});
|
|
48
|
+
it("flattens whitespace when flatten=true", () => {
|
|
49
|
+
expect(truncate("hello\n world", 20, true)).toBe("hello world");
|
|
50
|
+
});
|
|
51
|
+
it("handles exact-length strings", () => {
|
|
52
|
+
expect(truncate("abc", 3)).toBe("abc");
|
|
53
|
+
});
|
|
54
|
+
it("handles single char max", () => {
|
|
55
|
+
expect(truncate("abc", 1)).toBe("\u2026");
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
describe("formatError", () => {
|
|
59
|
+
it("extracts message from Error", () => {
|
|
60
|
+
expect(formatError(new Error("boom"))).toBe("boom");
|
|
61
|
+
});
|
|
62
|
+
it("converts non-Error values to string", () => {
|
|
63
|
+
expect(formatError("oops")).toBe("oops");
|
|
64
|
+
expect(formatError(42)).toBe("42");
|
|
65
|
+
expect(formatError(null)).toBe("null");
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
describe("formatBytes", () => {
|
|
69
|
+
it("formats bytes", () => {
|
|
70
|
+
expect(formatBytes(500)).toBe("500B");
|
|
71
|
+
});
|
|
72
|
+
it("formats kilobytes", () => {
|
|
73
|
+
expect(formatBytes(1500)).toBe("2K");
|
|
74
|
+
});
|
|
75
|
+
it("formats megabytes", () => {
|
|
76
|
+
expect(formatBytes(5_000_000)).toBe("5M");
|
|
77
|
+
});
|
|
78
|
+
it("formats gigabytes", () => {
|
|
79
|
+
expect(formatBytes(1_500_000_000)).toBe("1.5G");
|
|
80
|
+
});
|
|
81
|
+
it("formats terabytes", () => {
|
|
82
|
+
expect(formatBytes(2_000_000_000_000)).toBe("2.0T");
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
describe("shellQuote", () => {
|
|
86
|
+
it("wraps in single quotes", () => {
|
|
87
|
+
expect(shellQuote("hello")).toBe("'hello'");
|
|
88
|
+
});
|
|
89
|
+
it("escapes single quotes", () => {
|
|
90
|
+
expect(shellQuote("it's")).toBe("'it'\\''s'");
|
|
91
|
+
});
|
|
92
|
+
it("handles empty string", () => {
|
|
93
|
+
expect(shellQuote("")).toBe("''");
|
|
94
|
+
});
|
|
95
|
+
it("handles special shell characters", () => {
|
|
96
|
+
const special = 'rm -rf "$(whoami)"';
|
|
97
|
+
const quoted = shellQuote(special);
|
|
98
|
+
expect(quoted).toBe(`'rm -rf "$(whoami)"'`);
|
|
99
|
+
});
|
|
100
|
+
it("handles paths with spaces", () => {
|
|
101
|
+
expect(shellQuote("/path/to/my file.txt")).toBe("'/path/to/my file.txt'");
|
|
102
|
+
});
|
|
103
|
+
it("handles multiple single quotes", () => {
|
|
104
|
+
expect(shellQuote("a'b'c")).toBe("'a'\\''b'\\''c'");
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
describe("toolError", () => {
|
|
108
|
+
it("returns JSON with error field", () => {
|
|
109
|
+
const result = JSON.parse(toolError("something failed"));
|
|
110
|
+
expect(result).toEqual({ error: "something failed" });
|
|
111
|
+
});
|
|
112
|
+
it("extracts Error message", () => {
|
|
113
|
+
const result = JSON.parse(toolError(new Error("boom")));
|
|
114
|
+
expect(result).toEqual({ error: "boom" });
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
describe("toolResult", () => {
|
|
118
|
+
it("serializes data as JSON", () => {
|
|
119
|
+
expect(toolResult({ ok: true })).toBe('{"ok":true}');
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
//# sourceMappingURL=format.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.test.js","sourceRoot":"","sources":["../../src/ui/format.test.ts"],"names":[],"mappings":"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"}
|
package/dist/ui/layout.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../src/ui/layout.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAchD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AASxD,UAAU,WAAW;IACnB,OAAO,EAAE,aAAa,CAAC;IACvB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kBAAkB,CAAC,EAAE,UAAU,EAAE,CAAC;CACnC;
|
|
1
|
+
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../src/ui/layout.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAchD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AASxD,UAAU,WAAW;IACnB,OAAO,EAAE,aAAa,CAAC;IACvB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kBAAkB,CAAC,EAAE,UAAU,EAAE,CAAC;CACnC;AAqBD,wBAAgB,MAAM,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,kBAAkB,EAAE,EAAE,WAAW,2CAwiBzG"}
|
package/dist/ui/layout.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState, useCallback, useRef, useEffect, useMemo } from "react";
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useCallback, useRef, useEffect, useMemo, memo } from "react";
|
|
3
3
|
import { Box, Text, useInput, useApp, measureElement } from "ink";
|
|
4
4
|
import { useScreenSize } from "fullscreen-ink";
|
|
5
5
|
import { MessageLine, PulsingIndicator } from "./panels/conversation.js";
|
|
@@ -17,8 +17,11 @@ import { COMMANDS, handleSlashCommand } from "./commands.js";
|
|
|
17
17
|
import { pollTaskStatuses, handleFinishedTasks, buildMonitorMessage } from "../core/task-poller.js";
|
|
18
18
|
import { formatDuration, formatError, truncate } from "./format.js";
|
|
19
19
|
let messageIdCounter = 0;
|
|
20
|
+
function MessageList({ messages, isStreaming }) {
|
|
21
|
+
return (_jsxs(_Fragment, { children: [messages.map((msg) => (_jsx(Box, { paddingX: 1, children: _jsx(MessageLine, { message: msg }) }, msg.id))), isStreaming && (_jsx(Box, { paddingX: 1, paddingLeft: 3, children: _jsx(PulsingIndicator, {}) }))] }));
|
|
22
|
+
}
|
|
20
23
|
export function Layout({ runtime, mouseEmitter, headless, initialPrompt, initialAttachments }) {
|
|
21
|
-
const { orchestrator, sleepManager, connectionPool, executor, metricStore, metricCollector, monitorManager, experimentTracker, memoryStore, stickyManager, agentName, } = runtime;
|
|
24
|
+
const { orchestrator, sleepManager, connectionPool, executor, metricStore, metricCollector, monitorManager, experimentTracker, memoryStore, stickyManager, agentName, subagentManager, } = runtime;
|
|
22
25
|
const { exit } = useApp();
|
|
23
26
|
const [messages, setMessages] = useState(() => {
|
|
24
27
|
// If a session was already resumed (via -r / -c flags) before Layout mounted,
|
|
@@ -44,6 +47,10 @@ export function Layout({ runtime, mouseEmitter, headless, initialPrompt, initial
|
|
|
44
47
|
const [activeOverlay, setActiveOverlay] = useState("none");
|
|
45
48
|
const [resourceData, setResourceData] = useState(new Map());
|
|
46
49
|
const [updateAvailable, setUpdateAvailable] = useState(null);
|
|
50
|
+
// Refs for skipping unchanged polling state updates
|
|
51
|
+
const lastTaskIdsRef = useRef("");
|
|
52
|
+
const lastMetricKeyRef = useRef("");
|
|
53
|
+
const lastResourceKeyRef = useRef("");
|
|
47
54
|
// Check for updates on mount (non-blocking)
|
|
48
55
|
useEffect(() => {
|
|
49
56
|
checkForUpdate().then((v) => { if (v)
|
|
@@ -74,19 +81,46 @@ export function Layout({ runtime, mouseEmitter, headless, initialPrompt, initial
|
|
|
74
81
|
});
|
|
75
82
|
didCollect = true;
|
|
76
83
|
}
|
|
77
|
-
|
|
84
|
+
// Merge subagent entries into task list
|
|
85
|
+
if (subagentManager) {
|
|
86
|
+
for (const sa of subagentManager.listAll()) {
|
|
87
|
+
updated.push({
|
|
88
|
+
id: `sa:${sa.id}`,
|
|
89
|
+
name: truncate(sa.task, 40),
|
|
90
|
+
status: sa.status === "cancelled" ? "failed" : sa.status,
|
|
91
|
+
machineId: sa.model,
|
|
92
|
+
startedAt: sa.createdAt,
|
|
93
|
+
type: "subagent",
|
|
94
|
+
costUsd: sa.costUsd,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const newTaskIds = updated.map(t => `${t.id}:${t.status}:${t.costUsd ?? ""}`).join(",");
|
|
99
|
+
if (newTaskIds !== lastTaskIdsRef.current) {
|
|
100
|
+
lastTaskIdsRef.current = newTaskIds;
|
|
101
|
+
setTasks(updated);
|
|
102
|
+
}
|
|
78
103
|
}
|
|
79
104
|
// Collect metrics from all sources (skip if we already collected for finished tasks above)
|
|
80
105
|
if (metricCollector && metricStore) {
|
|
81
106
|
if (!didCollect) {
|
|
82
107
|
await metricCollector.collectAll().catch(() => { });
|
|
83
108
|
}
|
|
84
|
-
|
|
109
|
+
const newMetrics = metricStore.getAllSeries(50);
|
|
110
|
+
const newMetricKey = Array.from(newMetrics.entries()).map(([k, v]) => `${k}:${v.length}:${v.length > 0 ? v[v.length - 1] : ""}`).join(",");
|
|
111
|
+
if (newMetricKey !== lastMetricKeyRef.current) {
|
|
112
|
+
lastMetricKeyRef.current = newMetricKey;
|
|
113
|
+
setMetricData(newMetrics);
|
|
114
|
+
}
|
|
85
115
|
}
|
|
86
116
|
// Collect resource usage from connected machines
|
|
87
117
|
if (runtime.resourceCollector) {
|
|
88
118
|
const res = await runtime.resourceCollector.collectAll().catch(() => new Map());
|
|
89
|
-
|
|
119
|
+
const newResKey = Array.from(res.entries()).map(([k, v]) => `${k}:${v.cpuPercent}:${v.memoryUsed}`).join(",");
|
|
120
|
+
if (newResKey !== lastResourceKeyRef.current) {
|
|
121
|
+
lastResourceKeyRef.current = newResKey;
|
|
122
|
+
setResourceData(res);
|
|
123
|
+
}
|
|
90
124
|
}
|
|
91
125
|
};
|
|
92
126
|
let timer = null;
|
|
@@ -325,6 +359,23 @@ export function Layout({ runtime, mouseEmitter, headless, initialPrompt, initial
|
|
|
325
359
|
};
|
|
326
360
|
return () => { runtime.openaiOAuth.onAuthUrl = null; };
|
|
327
361
|
}, [runtime.openaiOAuth]);
|
|
362
|
+
// Subagent completion/failure events → inject system messages
|
|
363
|
+
useEffect(() => {
|
|
364
|
+
if (!subagentManager)
|
|
365
|
+
return;
|
|
366
|
+
const onDone = (info) => {
|
|
367
|
+
addMessageRef.current("system", `[Subagent ${info.id} completed — result at /subagents/${info.id}/result]`);
|
|
368
|
+
};
|
|
369
|
+
const onFail = (info) => {
|
|
370
|
+
addMessageRef.current("system", `[Subagent ${info.id} failed${info.error ? `: ${truncate(info.error, 80)}` : ""}]`);
|
|
371
|
+
};
|
|
372
|
+
subagentManager.on("completed", onDone);
|
|
373
|
+
subagentManager.on("failed", onFail);
|
|
374
|
+
return () => {
|
|
375
|
+
subagentManager.removeListener("completed", onDone);
|
|
376
|
+
subagentManager.removeListener("failed", onFail);
|
|
377
|
+
};
|
|
378
|
+
}, [subagentManager]);
|
|
328
379
|
useEffect(() => {
|
|
329
380
|
const onWake = (_session, _reason, wakeMessage) => {
|
|
330
381
|
if (isStreamingRef.current)
|
|
@@ -352,6 +403,7 @@ export function Layout({ runtime, mouseEmitter, headless, initialPrompt, initial
|
|
|
352
403
|
const metricsRows = metricData.size > 0 ? metricData.size : 1;
|
|
353
404
|
const tasksRows = tasks.length > 0 ? Math.min(tasks.length, 5) : 1;
|
|
354
405
|
const panelHeight = Math.max(metricsRows, tasksRows);
|
|
406
|
+
const verticalSeparator = useMemo(() => Array.from({ length: panelHeight }, () => "│").join("\n"), [panelHeight]);
|
|
355
407
|
const { height, width } = useScreenSize();
|
|
356
408
|
// ── Fullscreen overlays ───────────────────────────────────────
|
|
357
409
|
if (activeOverlay === "tasks") {
|
|
@@ -361,7 +413,7 @@ export function Layout({ runtime, mouseEmitter, headless, initialPrompt, initial
|
|
|
361
413
|
return (_jsx(Box, { flexDirection: "column", height: height, width: width, children: _jsx(MetricsOverlay, { metricData: metricData, metricStore: metricStore, width: width, height: height, onClose: () => setActiveOverlay("none") }) }));
|
|
362
414
|
}
|
|
363
415
|
// ── Normal layout ─────────────────────────────────────────────
|
|
364
|
-
return (_jsxs(Box, { flexDirection: "column", height: height, width: width, children: [_jsx(Box, { flexShrink: 0, children: headless && agentName ? (_jsx(HeadlessHeader, { agentName: agentName, width: width })) : (_jsx(HeaderWithPanels, { width: width })) }), _jsxs(Box, { flexShrink: 0, flexDirection: "row", children: [_jsx(Box, { flexGrow: 1, flexBasis: 0, flexDirection: "column", paddingX: 1, children: _jsx(MetricsDashboard, { metricData: metricData, width: Math.floor((width - 1) / 2) - 2 }) }), _jsx(Box, { width: 1, flexDirection: "column", alignItems: "center", children: _jsx(Text, { color: C.primary, wrap: "truncate", children:
|
|
416
|
+
return (_jsxs(Box, { flexDirection: "column", height: height, width: width, children: [_jsx(Box, { flexShrink: 0, children: headless && agentName ? (_jsx(HeadlessHeader, { agentName: agentName, width: width })) : (_jsx(HeaderWithPanels, { width: width })) }), _jsxs(Box, { flexShrink: 0, flexDirection: "row", children: [_jsx(Box, { flexGrow: 1, flexBasis: 0, flexDirection: "column", paddingX: 1, children: _jsx(MetricsDashboard, { metricData: metricData, width: Math.floor((width - 1) / 2) - 2 }) }), _jsx(Box, { width: 1, flexDirection: "column", alignItems: "center", children: _jsx(Text, { color: C.primary, wrap: "truncate", children: verticalSeparator }) }), _jsx(Box, { flexGrow: 1, flexBasis: 0, flexDirection: "column", paddingX: 1, children: _jsx(TaskListPanel, { tasks: tasks, resources: resourceData, width: Math.floor((width - 1) / 2) - 2 }) })] }), _jsx(Box, { flexShrink: 0, children: _jsx(HRule, {}) }), _jsxs(Box, { flexGrow: 1, flexShrink: 1, flexDirection: "row", children: [_jsx(Box, { flexGrow: 1, flexShrink: 1, children: messages.length === 0 && !headless ? (_jsxs(Box, { flexGrow: 1, alignItems: "center", justifyContent: "center", flexDirection: "column", children: [_jsx(Text, { color: C.primary, bold: true, children: G.brand }), _jsx(Text, { color: C.primary, bold: true, children: "H E L I O S" }), _jsx(Text, { color: C.dim, children: "autonomous ml research" }), _jsxs(Text, { color: C.dim, dimColor: true, children: ["v", VERSION] }), _jsx(Text, { color: C.dim, dimColor: true, children: "" }), _jsx(Text, { color: C.dim, dimColor: true, children: "/help for commands" }), updateAvailable && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: C.bright, children: ["update available: v", updateAvailable, " \u2014 npm i -g helios"] }) }))] })) : (_jsx(Box, { ref: viewportRef, overflow: "hidden", flexGrow: 1, flexShrink: 1, flexDirection: "column", justifyContent: "flex-end", children: _jsx(Box, { ref: contentRef, flexDirection: "column", flexShrink: 0, marginBottom: scrollUp > 0 ? -scrollUp : undefined, children: _jsx(MessageList, { messages: messages, isStreaming: isStreaming }) }) })) }), stickyNotes.length > 0 && (_jsx(Box, { flexShrink: 0, children: _jsx(StickyNotesPanel, { notes: stickyNotes, width: Math.min(30, Math.floor(width * 0.25)) }) }))] }), !headless && _jsx(Box, { flexShrink: 0, children: _jsx(KeyHintRule, {}) }), _jsx(Box, { flexShrink: 0, children: _jsx(StatusBar, { orchestrator: orchestrator, sleepManager: sleepManager, monitorManager: monitorManager, isStreaming: isStreaming, streamingStartedAt: streamingStartedAt }) }), !headless && (_jsx(Box, { flexShrink: 0, children: _jsx(InputBar, { onSubmit: handleSubmit, disabled: isStreaming, commands: allCommands, placeholder: isSleeping
|
|
365
417
|
? "type to wake agent..."
|
|
366
418
|
: "send a message... (/help for commands)" }) }))] }));
|
|
367
419
|
}
|
|
@@ -372,7 +424,7 @@ function HeadlessHeader({ agentName, width }) {
|
|
|
372
424
|
return (_jsxs(Box, { children: [_jsx(Text, { color: C.bright, bold: true, children: label }), _jsx(Text, { color: C.primary, children: G.rule.repeat(fill) })] }));
|
|
373
425
|
}
|
|
374
426
|
/** Single header line: logo on the left, panel labels right-aligned in each half. */
|
|
375
|
-
function HeaderWithPanels({ width }) {
|
|
427
|
+
const HeaderWithPanels = memo(function HeaderWithPanels({ width }) {
|
|
376
428
|
const logo = ` ▓▒░ ${G.brand} HELIOS ░▒▓ `;
|
|
377
429
|
const ver = `${VERSION} `;
|
|
378
430
|
const metricsLabel = ` ⣤⣸⣿ METRICS `;
|
|
@@ -381,10 +433,10 @@ function HeaderWithPanels({ width }) {
|
|
|
381
433
|
const leftFill = Math.max(0, half - logo.length - ver.length - metricsLabel.length - 1);
|
|
382
434
|
const rightFill = Math.max(0, width - half - tasksLabel.length - 1);
|
|
383
435
|
return (_jsxs(Box, { children: [_jsx(ShimmerLogo, { text: logo }), _jsx(Text, { color: C.dim, children: ver }), _jsx(Text, { color: C.primary, children: G.rule.repeat(leftFill) }), _jsx(Text, { color: C.primary, children: metricsLabel }), _jsx(Text, { color: C.primary, children: G.rule }), _jsx(Text, { color: C.primary, children: G.rule.repeat(rightFill) }), _jsx(Text, { color: C.primary, children: tasksLabel }), _jsx(Text, { color: C.primary, children: G.rule })] }));
|
|
384
|
-
}
|
|
436
|
+
});
|
|
385
437
|
const SHIMMER_INTERVAL = 80;
|
|
386
438
|
const SHIMMER_PAUSE = 20; // extra frames of pause after sweep
|
|
387
|
-
function ShimmerLogo({ text }) {
|
|
439
|
+
const ShimmerLogo = memo(function ShimmerLogo({ text }) {
|
|
388
440
|
const [frame, setFrame] = useState(0);
|
|
389
441
|
const len = text.length;
|
|
390
442
|
const cycleLen = len + 6 + SHIMMER_PAUSE; // 6 = shimmer tail width
|
|
@@ -415,5 +467,5 @@ function ShimmerLogo({ text }) {
|
|
|
415
467
|
}
|
|
416
468
|
}
|
|
417
469
|
return (_jsx(Text, { children: segments.map((seg, i) => (_jsx(Text, { color: seg.color, bold: true, children: seg.chars }, i))) }));
|
|
418
|
-
}
|
|
470
|
+
});
|
|
419
471
|
//# sourceMappingURL=layout.js.map
|