pilotswarm-cli 0.1.15 → 0.1.17
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 +3 -0
- package/node_modules/pilotswarm-ui-core/README.md +6 -0
- package/node_modules/pilotswarm-ui-core/package.json +32 -0
- package/node_modules/pilotswarm-ui-core/src/commands.js +72 -0
- package/node_modules/pilotswarm-ui-core/src/context-usage.js +212 -0
- package/node_modules/pilotswarm-ui-core/src/controller.js +3676 -0
- package/node_modules/pilotswarm-ui-core/src/formatting.js +872 -0
- package/node_modules/pilotswarm-ui-core/src/history.js +589 -0
- package/node_modules/pilotswarm-ui-core/src/index.js +13 -0
- package/node_modules/pilotswarm-ui-core/src/layout.js +196 -0
- package/node_modules/pilotswarm-ui-core/src/reducer.js +1030 -0
- package/node_modules/pilotswarm-ui-core/src/selectors.js +2921 -0
- package/node_modules/pilotswarm-ui-core/src/session-tree.js +109 -0
- package/node_modules/pilotswarm-ui-core/src/state.js +80 -0
- package/node_modules/pilotswarm-ui-core/src/store.js +23 -0
- package/node_modules/pilotswarm-ui-core/src/system-titles.js +24 -0
- package/node_modules/pilotswarm-ui-core/src/themes/catppuccin-mocha.js +56 -0
- package/node_modules/pilotswarm-ui-core/src/themes/cobalt2.js +56 -0
- package/node_modules/pilotswarm-ui-core/src/themes/dark-high-contrast.js +56 -0
- package/node_modules/pilotswarm-ui-core/src/themes/dracula.js +56 -0
- package/node_modules/pilotswarm-ui-core/src/themes/github-dark.js +56 -0
- package/node_modules/pilotswarm-ui-core/src/themes/gruvbox-dark.js +56 -0
- package/node_modules/pilotswarm-ui-core/src/themes/hacker-x-matrix.js +56 -0
- package/node_modules/pilotswarm-ui-core/src/themes/hacker-x-orion-prime.js +56 -0
- package/node_modules/pilotswarm-ui-core/src/themes/helpers.js +77 -0
- package/node_modules/pilotswarm-ui-core/src/themes/index.js +44 -0
- package/node_modules/pilotswarm-ui-core/src/themes/noctis-obscuro.js +56 -0
- package/node_modules/pilotswarm-ui-core/src/themes/noctis-viola.js +56 -0
- package/node_modules/pilotswarm-ui-core/src/themes/noctis.js +56 -0
- package/node_modules/pilotswarm-ui-core/src/themes/nord.js +56 -0
- package/node_modules/pilotswarm-ui-core/src/themes/solarized-dark.js +56 -0
- package/node_modules/pilotswarm-ui-core/src/themes/tokyo-night.js +56 -0
- package/node_modules/pilotswarm-ui-react/README.md +5 -0
- package/node_modules/pilotswarm-ui-react/package.json +36 -0
- package/node_modules/pilotswarm-ui-react/src/components.js +1430 -0
- package/node_modules/pilotswarm-ui-react/src/index.js +4 -0
- package/node_modules/pilotswarm-ui-react/src/platform.js +15 -0
- package/node_modules/pilotswarm-ui-react/src/use-controller-state.js +38 -0
- package/node_modules/pilotswarm-ui-react/src/web-app.js +2776 -0
- package/package.json +7 -2
- package/src/app.js +16 -1
- package/src/node-sdk-transport.js +174 -1
- package/src/sync-workspace-ui.js +53 -0
- package/src/version.js +7 -0
package/bin/tui.js
CHANGED
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
// explicitly opts into another environment for debugging.
|
|
5
5
|
process.env.NODE_ENV ??= "production";
|
|
6
6
|
|
|
7
|
+
const { syncBundledWorkspaceUiPackages } = await import("../src/sync-workspace-ui.js");
|
|
8
|
+
syncBundledWorkspaceUiPackages();
|
|
9
|
+
|
|
7
10
|
const { parseCliIntoEnv } = await import("../src/bootstrap-env.js");
|
|
8
11
|
const config = parseCliIntoEnv(process.argv.slice(2));
|
|
9
12
|
const { startTuiApp } = await import("../src/index.js");
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pilotswarm-ui-core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"description": "Framework-free shared UI core for PilotSwarm hosts.",
|
|
7
|
+
"main": "./src/index.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./src/index.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"src/**/*",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "echo 'pilotswarm-ui-core: no build step (plain JS)'",
|
|
17
|
+
"clean": "true"
|
|
18
|
+
},
|
|
19
|
+
"author": "Affan Dar",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/affandar/PilotSwarm"
|
|
24
|
+
},
|
|
25
|
+
"homepage": "https://github.com/affandar/PilotSwarm",
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/affandar/PilotSwarm/issues"
|
|
28
|
+
},
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=24.0.0"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export const FOCUS_REGIONS = {
|
|
2
|
+
SESSIONS: "sessions",
|
|
3
|
+
CHAT: "chat",
|
|
4
|
+
INSPECTOR: "inspector",
|
|
5
|
+
ACTIVITY: "activity",
|
|
6
|
+
PROMPT: "prompt",
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const INSPECTOR_TABS = ["sequence", "logs", "nodes", "history", "files"];
|
|
10
|
+
|
|
11
|
+
export const UI_COMMANDS = {
|
|
12
|
+
REFRESH: "refresh",
|
|
13
|
+
NEW_SESSION: "newSession",
|
|
14
|
+
OPEN_MODEL_PICKER: "openModelPicker",
|
|
15
|
+
OPEN_THEME_PICKER: "openThemePicker",
|
|
16
|
+
OPEN_RENAME_SESSION: "openRenameSession",
|
|
17
|
+
OPEN_ARTIFACT_UPLOAD: "openArtifactUpload",
|
|
18
|
+
CLOSE_MODAL: "closeModal",
|
|
19
|
+
MODAL_PREV: "modalPrev",
|
|
20
|
+
MODAL_NEXT: "modalNext",
|
|
21
|
+
MODAL_PANE_PREV: "modalPanePrev",
|
|
22
|
+
MODAL_PANE_NEXT: "modalPaneNext",
|
|
23
|
+
MODAL_CONFIRM: "modalConfirm",
|
|
24
|
+
SEND_PROMPT: "sendPrompt",
|
|
25
|
+
FOCUS_NEXT: "focusNext",
|
|
26
|
+
FOCUS_PREV: "focusPrev",
|
|
27
|
+
FOCUS_LEFT: "focusLeft",
|
|
28
|
+
FOCUS_RIGHT: "focusRight",
|
|
29
|
+
FOCUS_PROMPT: "focusPrompt",
|
|
30
|
+
FOCUS_SESSIONS: "focusSessions",
|
|
31
|
+
MOVE_SESSION_UP: "moveSessionUp",
|
|
32
|
+
MOVE_SESSION_DOWN: "moveSessionDown",
|
|
33
|
+
EXPAND_SESSION: "expandSession",
|
|
34
|
+
COLLAPSE_SESSION: "collapseSession",
|
|
35
|
+
NEXT_INSPECTOR_TAB: "nextInspectorTab",
|
|
36
|
+
PREV_INSPECTOR_TAB: "prevInspectorTab",
|
|
37
|
+
CYCLE_INSPECTOR_TAB: "cycleInspectorTab",
|
|
38
|
+
GROW_LEFT_PANE: "growLeftPane",
|
|
39
|
+
GROW_RIGHT_PANE: "growRightPane",
|
|
40
|
+
GROW_SESSION_PANE: "growSessionPane",
|
|
41
|
+
SHRINK_SESSION_PANE: "shrinkSessionPane",
|
|
42
|
+
OPEN_ARTIFACT_PICKER: "openArtifactPicker",
|
|
43
|
+
TOGGLE_LOG_TAIL: "toggleLogTail",
|
|
44
|
+
OPEN_LOG_FILTER: "openLogFilter",
|
|
45
|
+
OPEN_FILES_FILTER: "openFilesFilter",
|
|
46
|
+
MOVE_FILE_UP: "moveFileUp",
|
|
47
|
+
MOVE_FILE_DOWN: "moveFileDown",
|
|
48
|
+
DOWNLOAD_SELECTED_FILE: "downloadSelectedFile",
|
|
49
|
+
OPEN_SELECTED_FILE: "openSelectedFile",
|
|
50
|
+
TOGGLE_FILE_PREVIEW_FULLSCREEN: "toggleFilePreviewFullscreen",
|
|
51
|
+
TOGGLE_PANE_FULLSCREEN: "togglePaneFullscreen",
|
|
52
|
+
SCROLL_UP: "scrollUp",
|
|
53
|
+
SCROLL_DOWN: "scrollDown",
|
|
54
|
+
PAGE_UP: "pageUp",
|
|
55
|
+
PAGE_DOWN: "pageDown",
|
|
56
|
+
EXPAND_HISTORY: "expandHistory",
|
|
57
|
+
SCROLL_TOP: "scrollTop",
|
|
58
|
+
SCROLL_BOTTOM: "scrollBottom",
|
|
59
|
+
DONE_SESSION: "doneSession",
|
|
60
|
+
CANCEL_SESSION: "cancelSession",
|
|
61
|
+
DELETE_SESSION: "deleteSession",
|
|
62
|
+
OPEN_HISTORY_FORMAT: "openHistoryFormat",
|
|
63
|
+
REFRESH_EXECUTION_HISTORY: "refreshExecutionHistory",
|
|
64
|
+
EXPORT_EXECUTION_HISTORY: "exportExecutionHistory",
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export function cycleValue(values, current, delta) {
|
|
68
|
+
const index = values.indexOf(current);
|
|
69
|
+
const safeIndex = index === -1 ? 0 : index;
|
|
70
|
+
const nextIndex = (safeIndex + delta + values.length) % values.length;
|
|
71
|
+
return values[nextIndex];
|
|
72
|
+
}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
export function computeContextPercent(contextUsage) {
|
|
2
|
+
const utilization = typeof contextUsage?.utilization === "number"
|
|
3
|
+
? contextUsage.utilization
|
|
4
|
+
: (typeof contextUsage?.tokenLimit === "number"
|
|
5
|
+
&& contextUsage.tokenLimit > 0
|
|
6
|
+
&& typeof contextUsage?.currentTokens === "number"
|
|
7
|
+
? contextUsage.currentTokens / contextUsage.tokenLimit
|
|
8
|
+
: null);
|
|
9
|
+
|
|
10
|
+
if (typeof utilization !== "number" || !Number.isFinite(utilization)) return null;
|
|
11
|
+
return Math.max(0, Math.min(100, Math.round(utilization * 100)));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function formatTokenCount(value) {
|
|
15
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) return "?";
|
|
16
|
+
if (value >= 1_000_000) {
|
|
17
|
+
const compact = value >= 10_000_000
|
|
18
|
+
? Math.round(value / 1_000_000)
|
|
19
|
+
: Math.round(value / 100_000) / 10;
|
|
20
|
+
return `${compact}`.replace(/\.0$/, "") + "m";
|
|
21
|
+
}
|
|
22
|
+
if (value >= 1_000) {
|
|
23
|
+
const compact = value >= 100_000
|
|
24
|
+
? Math.round(value / 1_000)
|
|
25
|
+
: Math.round(value / 100) / 10;
|
|
26
|
+
return `${compact}`.replace(/\.0$/, "") + "k";
|
|
27
|
+
}
|
|
28
|
+
return String(Math.round(value));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function getContextMeterColor(contextUsage) {
|
|
32
|
+
const percent = computeContextPercent(contextUsage);
|
|
33
|
+
if (percent == null) return "gray";
|
|
34
|
+
if (percent >= 85) return "red";
|
|
35
|
+
if (percent >= 70) return "yellow";
|
|
36
|
+
return "gray";
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function getContextHeaderBadge(contextUsage) {
|
|
40
|
+
if (!contextUsage) return null;
|
|
41
|
+
if (!(typeof contextUsage.tokenLimit === "number"
|
|
42
|
+
&& contextUsage.tokenLimit > 0
|
|
43
|
+
&& typeof contextUsage.currentTokens === "number"
|
|
44
|
+
&& contextUsage.currentTokens >= 0)) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const percent = computeContextPercent(contextUsage);
|
|
49
|
+
if (percent == null) return null;
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
text: `ctx ${formatTokenCount(contextUsage.currentTokens)}/${formatTokenCount(contextUsage.tokenLimit)} ${percent}%`,
|
|
53
|
+
color: getContextMeterColor(contextUsage),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function getContextListBadge(contextUsage) {
|
|
58
|
+
if (!contextUsage) return null;
|
|
59
|
+
|
|
60
|
+
const compaction = contextUsage.compaction;
|
|
61
|
+
if (compaction?.state === "running") {
|
|
62
|
+
return { text: "[compact]", color: "magenta" };
|
|
63
|
+
}
|
|
64
|
+
if (compaction?.state === "failed") {
|
|
65
|
+
return { text: "[compact !]", color: "red" };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const percent = computeContextPercent(contextUsage);
|
|
69
|
+
if (percent == null || percent < 70) return null;
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
text: `[ctx ${percent}%]`,
|
|
73
|
+
color: percent >= 85 ? "red" : "yellow",
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function getContextCompactionBadge(contextUsage) {
|
|
78
|
+
const compaction = contextUsage?.compaction;
|
|
79
|
+
if (!compaction || typeof compaction !== "object") return null;
|
|
80
|
+
|
|
81
|
+
if (compaction.state === "running") {
|
|
82
|
+
return { text: "[compacting]", color: "magenta" };
|
|
83
|
+
}
|
|
84
|
+
if (compaction.state === "failed") {
|
|
85
|
+
return { text: "[compact failed]", color: "red" };
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function cloneContextUsageSnapshot(contextUsage) {
|
|
91
|
+
if (!contextUsage || typeof contextUsage !== "object") return null;
|
|
92
|
+
return {
|
|
93
|
+
...contextUsage,
|
|
94
|
+
...(contextUsage.compaction && typeof contextUsage.compaction === "object"
|
|
95
|
+
? { compaction: { ...contextUsage.compaction } }
|
|
96
|
+
: {}),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function normalizeUsageTimestamp(value) {
|
|
101
|
+
if (value instanceof Date) return value.getTime();
|
|
102
|
+
const numeric = new Date(value).getTime();
|
|
103
|
+
return Number.isFinite(numeric) ? numeric : Date.now();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function applySessionUsageEvent(contextUsage, eventType, data = {}, options = {}) {
|
|
107
|
+
if (!eventType) return null;
|
|
108
|
+
const current = cloneContextUsageSnapshot(contextUsage) || {};
|
|
109
|
+
const timestamp = normalizeUsageTimestamp(options.timestamp);
|
|
110
|
+
|
|
111
|
+
if (eventType === "session.usage_info") {
|
|
112
|
+
if (typeof data.tokenLimit !== "number"
|
|
113
|
+
|| typeof data.currentTokens !== "number"
|
|
114
|
+
|| typeof data.messagesLength !== "number") {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
current.tokenLimit = data.tokenLimit;
|
|
118
|
+
current.currentTokens = data.currentTokens;
|
|
119
|
+
current.messagesLength = data.messagesLength;
|
|
120
|
+
current.utilization = data.tokenLimit > 0 ? data.currentTokens / data.tokenLimit : 0;
|
|
121
|
+
if (typeof data.systemTokens === "number") current.systemTokens = data.systemTokens;
|
|
122
|
+
if (typeof data.conversationTokens === "number") current.conversationTokens = data.conversationTokens;
|
|
123
|
+
if (typeof data.toolDefinitionsTokens === "number") current.toolDefinitionsTokens = data.toolDefinitionsTokens;
|
|
124
|
+
if (typeof data.isInitial === "boolean") current.isInitial = data.isInitial;
|
|
125
|
+
return current;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (eventType === "assistant.usage") {
|
|
129
|
+
if (typeof data.inputTokens === "number") current.lastInputTokens = data.inputTokens;
|
|
130
|
+
if (typeof data.outputTokens === "number") current.lastOutputTokens = data.outputTokens;
|
|
131
|
+
if (typeof data.cacheReadTokens === "number") current.lastCacheReadTokens = data.cacheReadTokens;
|
|
132
|
+
if (typeof data.cacheWriteTokens === "number") current.lastCacheWriteTokens = data.cacheWriteTokens;
|
|
133
|
+
return current;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (eventType === "session.compaction_start") {
|
|
137
|
+
current.compaction = {
|
|
138
|
+
...(current.compaction || {}),
|
|
139
|
+
state: "running",
|
|
140
|
+
startedAt: timestamp,
|
|
141
|
+
completedAt: undefined,
|
|
142
|
+
error: undefined,
|
|
143
|
+
};
|
|
144
|
+
return current;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (eventType === "session.compaction_complete") {
|
|
148
|
+
current.compaction = {
|
|
149
|
+
...(current.compaction || {}),
|
|
150
|
+
state: data.success === false ? "failed" : "succeeded",
|
|
151
|
+
completedAt: timestamp,
|
|
152
|
+
error: typeof data.error === "string" ? data.error : undefined,
|
|
153
|
+
preCompactionTokens: typeof data.preCompactionTokens === "number" ? data.preCompactionTokens : undefined,
|
|
154
|
+
postCompactionTokens: typeof data.postCompactionTokens === "number" ? data.postCompactionTokens : undefined,
|
|
155
|
+
preCompactionMessagesLength: typeof data.preCompactionMessagesLength === "number" ? data.preCompactionMessagesLength : undefined,
|
|
156
|
+
messagesRemoved: typeof data.messagesRemoved === "number" ? data.messagesRemoved : undefined,
|
|
157
|
+
tokensRemoved: typeof data.tokensRemoved === "number" ? data.tokensRemoved : undefined,
|
|
158
|
+
systemTokens: typeof data.systemTokens === "number" ? data.systemTokens : undefined,
|
|
159
|
+
conversationTokens: typeof data.conversationTokens === "number" ? data.conversationTokens : undefined,
|
|
160
|
+
toolDefinitionsTokens: typeof data.toolDefinitionsTokens === "number" ? data.toolDefinitionsTokens : undefined,
|
|
161
|
+
inputTokens: typeof data.compactionTokensUsed?.input === "number" ? data.compactionTokensUsed.input : undefined,
|
|
162
|
+
outputTokens: typeof data.compactionTokensUsed?.output === "number" ? data.compactionTokensUsed.output : undefined,
|
|
163
|
+
cachedInputTokens: typeof data.compactionTokensUsed?.cachedInput === "number" ? data.compactionTokensUsed.cachedInput : undefined,
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
if (typeof data.postCompactionTokens === "number" && typeof current.tokenLimit === "number" && current.tokenLimit > 0) {
|
|
167
|
+
current.currentTokens = data.postCompactionTokens;
|
|
168
|
+
current.utilization = data.postCompactionTokens / current.tokenLimit;
|
|
169
|
+
}
|
|
170
|
+
if (typeof data.preCompactionMessagesLength === "number" && typeof data.messagesRemoved === "number") {
|
|
171
|
+
current.messagesLength = Math.max(0, data.preCompactionMessagesLength - data.messagesRemoved);
|
|
172
|
+
}
|
|
173
|
+
if (typeof data.systemTokens === "number") current.systemTokens = data.systemTokens;
|
|
174
|
+
if (typeof data.conversationTokens === "number") current.conversationTokens = data.conversationTokens;
|
|
175
|
+
if (typeof data.toolDefinitionsTokens === "number") current.toolDefinitionsTokens = data.toolDefinitionsTokens;
|
|
176
|
+
return current;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export function formatCompactionActivityRuns(timestamp, eventType, data = {}) {
|
|
183
|
+
const prefix = timestamp ? [{ text: `[${timestamp}] `, color: "white" }] : [];
|
|
184
|
+
|
|
185
|
+
if (eventType === "session.compaction_start") {
|
|
186
|
+
return [
|
|
187
|
+
...prefix,
|
|
188
|
+
{ text: "[compaction]", color: "magenta" },
|
|
189
|
+
{ text: " started", color: "white" },
|
|
190
|
+
];
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (data.success === false) {
|
|
194
|
+
return [
|
|
195
|
+
...prefix,
|
|
196
|
+
{ text: "[compaction]", color: "red" },
|
|
197
|
+
{ text: " failed", color: "white" },
|
|
198
|
+
...(typeof data.error === "string" && data.error
|
|
199
|
+
? [{ text: `: ${data.error}`, color: "red" }]
|
|
200
|
+
: []),
|
|
201
|
+
];
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return [
|
|
205
|
+
...prefix,
|
|
206
|
+
{ text: "[compaction]", color: "magenta" },
|
|
207
|
+
{ text: " complete", color: "white" },
|
|
208
|
+
...(typeof data.tokensRemoved === "number"
|
|
209
|
+
? [{ text: ` freed ${formatTokenCount(data.tokensRemoved)}`, color: "gray" }]
|
|
210
|
+
: []),
|
|
211
|
+
];
|
|
212
|
+
}
|