pilotswarm-cli 0.1.11 → 0.1.12

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/bin/tui.js CHANGED
@@ -143,11 +143,14 @@ if (fs.existsSync(envFile)) {
143
143
  const DEFAULT_SYSTEM_MESSAGE = `You are a helpful assistant running in a durable execution environment. Be concise.
144
144
 
145
145
  CRITICAL RULES:
146
- 1. You have a 'wait' tool. You MUST use it whenever you need to wait, pause, sleep, delay, poll, check back later, schedule a future action, or implement any recurring/periodic task.
146
+ 1. You have 'wait', 'wait_on_worker', and 'cron' tools. Use 'cron' for recurring or periodic schedules, and use 'wait'/'wait_on_worker' for one-shot delays.
147
147
  2. NEVER say you cannot wait or set timers. You CAN — use the 'wait' tool.
148
148
  3. NEVER use bash sleep, setTimeout, setInterval, cron, or any other timing mechanism.
149
- 4. The 'wait' tool enables durable timers that survive process restarts and node migrations.
150
- 5. For recurring tasks: use the 'wait' tool in a loop complete the action, then call wait(seconds), then repeat.`;
149
+ 4. The 'wait' and 'cron' tools enable durable timers that survive process restarts and node migrations.
150
+ 5. For recurring tasks, call cron(seconds=<N>, reason="...") once. The orchestration handles future wake-ups automatically.
151
+ 6. Use wait(seconds=<N>) only for one-shot delays within a turn.
152
+ 7. Use cron(action="cancel") to stop a recurring schedule.
153
+ 8. If facts tools are available, use them for durable memory, checkpoints, and resumable task state when helpful.`;
151
154
 
152
155
  function resolveSystemMessage() {
153
156
  // 1. CLI flag (string or file path)
@@ -0,0 +1,80 @@
1
+ export function computeContextPercent(contextUsage) {
2
+ const utilization = typeof contextUsage?.utilization === "number"
3
+ ? contextUsage.utilization
4
+ : (typeof contextUsage?.tokenLimit === "number" && contextUsage.tokenLimit > 0
5
+ && typeof contextUsage?.currentTokens === "number"
6
+ ? contextUsage.currentTokens / contextUsage.tokenLimit
7
+ : null);
8
+ if (typeof utilization !== "number" || !Number.isFinite(utilization)) return null;
9
+ return Math.max(0, Math.min(100, Math.round(utilization * 100)));
10
+ }
11
+
12
+ export function formatTokenCount(value) {
13
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0) return "?";
14
+ if (value >= 1_000_000) {
15
+ const compact = value >= 10_000_000
16
+ ? Math.round(value / 1_000_000)
17
+ : Math.round(value / 100_000) / 10;
18
+ return `${compact}`.replace(/\.0$/, "") + "m";
19
+ }
20
+ if (value >= 1_000) {
21
+ const compact = value >= 100_000
22
+ ? Math.round(value / 1_000)
23
+ : Math.round(value / 100) / 10;
24
+ return `${compact}`.replace(/\.0$/, "") + "k";
25
+ }
26
+ return String(Math.round(value));
27
+ }
28
+
29
+ export function getContextMeterColor(contextUsage) {
30
+ const percent = computeContextPercent(contextUsage);
31
+ if (percent == null) return "gray";
32
+ if (percent >= 85) return "red";
33
+ if (percent >= 70) return "yellow";
34
+ return "gray";
35
+ }
36
+
37
+ export function formatContextHeaderBadge(contextUsage) {
38
+ if (!contextUsage) return "";
39
+ if (!(typeof contextUsage.tokenLimit === "number" && contextUsage.tokenLimit > 0
40
+ && typeof contextUsage.currentTokens === "number" && contextUsage.currentTokens >= 0)) {
41
+ return "";
42
+ }
43
+ const percent = computeContextPercent(contextUsage);
44
+ if (percent == null) return "";
45
+ const color = getContextMeterColor(contextUsage);
46
+ return ` {${color}-fg}ctx ${formatTokenCount(contextUsage.currentTokens)}/${formatTokenCount(contextUsage.tokenLimit)} ${percent}%{/${color}-fg}`;
47
+ }
48
+
49
+ export function formatContextListBadge(contextUsage) {
50
+ if (!contextUsage) return "";
51
+ const compaction = contextUsage.compaction;
52
+ if (compaction?.state === "running") return " {magenta-fg}[compact]{/magenta-fg}";
53
+ if (compaction?.state === "failed") return " {red-fg}[compact !]{/red-fg}";
54
+ const percent = computeContextPercent(contextUsage);
55
+ if (percent == null || percent < 70) return "";
56
+ const color = percent >= 85 ? "red" : "yellow";
57
+ return ` {${color}-fg}[ctx ${percent}%]{/${color}-fg}`;
58
+ }
59
+
60
+ export function formatContextCompactionBadge(contextUsage) {
61
+ const compaction = contextUsage?.compaction;
62
+ if (!compaction || typeof compaction !== "object") return "";
63
+ if (compaction.state === "running") return " {magenta-fg}[compacting]{/magenta-fg}";
64
+ if (compaction.state === "failed") return " {red-fg}[compact failed]{/red-fg}";
65
+ return "";
66
+ }
67
+
68
+ export function formatCompactionActivityMarkup(timestamp, eventType, data = {}) {
69
+ if (eventType === "session.compaction_start") {
70
+ return `{white-fg}[${timestamp}]{/white-fg} {magenta-fg}[compaction]{/magenta-fg} started`;
71
+ }
72
+ if (data.success === false) {
73
+ const reason = typeof data.error === "string" && data.error ? `: ${data.error}` : "";
74
+ return `{white-fg}[${timestamp}]{/white-fg} {red-fg}[compaction]{/red-fg} failed${reason}`;
75
+ }
76
+ const removed = typeof data.tokensRemoved === "number"
77
+ ? ` freed ${formatTokenCount(data.tokensRemoved)}`
78
+ : "";
79
+ return `{white-fg}[${timestamp}]{/white-fg} {magenta-fg}[compaction]{/magenta-fg} complete${removed}`;
80
+ }