pilotswarm 0.0.1 → 0.4.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 +37 -1
- package/mcp/README.md +484 -0
- package/mcp/dist/bin/pilotswarm-mcp.d.ts +3 -0
- package/mcp/dist/bin/pilotswarm-mcp.d.ts.map +1 -0
- package/mcp/dist/bin/pilotswarm-mcp.js +367 -0
- package/mcp/dist/bin/pilotswarm-mcp.js.map +1 -0
- package/mcp/dist/src/auth.d.ts +7 -0
- package/mcp/dist/src/auth.d.ts.map +1 -0
- package/mcp/dist/src/auth.js +99 -0
- package/mcp/dist/src/auth.js.map +1 -0
- package/mcp/dist/src/context.d.ts +48 -0
- package/mcp/dist/src/context.d.ts.map +1 -0
- package/mcp/dist/src/context.js +83 -0
- package/mcp/dist/src/context.js.map +1 -0
- package/mcp/dist/src/index.d.ts +4 -0
- package/mcp/dist/src/index.d.ts.map +1 -0
- package/mcp/dist/src/index.js +3 -0
- package/mcp/dist/src/index.js.map +1 -0
- package/mcp/dist/src/prompts/skills.d.ts +4 -0
- package/mcp/dist/src/prompts/skills.d.ts.map +1 -0
- package/mcp/dist/src/prompts/skills.js +11 -0
- package/mcp/dist/src/prompts/skills.js.map +1 -0
- package/mcp/dist/src/resources/agents.d.ts +4 -0
- package/mcp/dist/src/resources/agents.d.ts.map +1 -0
- package/mcp/dist/src/resources/agents.js +64 -0
- package/mcp/dist/src/resources/agents.js.map +1 -0
- package/mcp/dist/src/resources/facts.d.ts +4 -0
- package/mcp/dist/src/resources/facts.d.ts.map +1 -0
- package/mcp/dist/src/resources/facts.js +125 -0
- package/mcp/dist/src/resources/facts.js.map +1 -0
- package/mcp/dist/src/resources/models.d.ts +4 -0
- package/mcp/dist/src/resources/models.d.ts.map +1 -0
- package/mcp/dist/src/resources/models.js +43 -0
- package/mcp/dist/src/resources/models.js.map +1 -0
- package/mcp/dist/src/resources/sessions.d.ts +4 -0
- package/mcp/dist/src/resources/sessions.d.ts.map +1 -0
- package/mcp/dist/src/resources/sessions.js +190 -0
- package/mcp/dist/src/resources/sessions.js.map +1 -0
- package/mcp/dist/src/resources/subscriptions.d.ts +9 -0
- package/mcp/dist/src/resources/subscriptions.d.ts.map +1 -0
- package/mcp/dist/src/resources/subscriptions.js +157 -0
- package/mcp/dist/src/resources/subscriptions.js.map +1 -0
- package/mcp/dist/src/server.d.ts +4 -0
- package/mcp/dist/src/server.d.ts.map +1 -0
- package/mcp/dist/src/server.js +59 -0
- package/mcp/dist/src/server.js.map +1 -0
- package/mcp/dist/src/tools/agents.d.ts +4 -0
- package/mcp/dist/src/tools/agents.d.ts.map +1 -0
- package/mcp/dist/src/tools/agents.js +317 -0
- package/mcp/dist/src/tools/agents.js.map +1 -0
- package/mcp/dist/src/tools/facts.d.ts +4 -0
- package/mcp/dist/src/tools/facts.d.ts.map +1 -0
- package/mcp/dist/src/tools/facts.js +151 -0
- package/mcp/dist/src/tools/facts.js.map +1 -0
- package/mcp/dist/src/tools/models.d.ts +4 -0
- package/mcp/dist/src/tools/models.d.ts.map +1 -0
- package/mcp/dist/src/tools/models.js +256 -0
- package/mcp/dist/src/tools/models.js.map +1 -0
- package/mcp/dist/src/tools/sessions.d.ts +4 -0
- package/mcp/dist/src/tools/sessions.d.ts.map +1 -0
- package/mcp/dist/src/tools/sessions.js +606 -0
- package/mcp/dist/src/tools/sessions.js.map +1 -0
- package/mcp/dist/src/util/command.d.ts +52 -0
- package/mcp/dist/src/util/command.d.ts.map +1 -0
- package/mcp/dist/src/util/command.js +78 -0
- package/mcp/dist/src/util/command.js.map +1 -0
- package/package.json +82 -6
- package/tui/README.md +35 -0
- package/tui/bin/tui.js +30 -0
- package/tui/plugins/.mcp.json +7 -0
- package/tui/plugins/plugin.json +13 -0
- package/tui/plugins/session-policy.json +8 -0
- package/tui/src/app.js +850 -0
- package/tui/src/auth/cli.js +111 -0
- package/tui/src/auth/entra-auth.js +218 -0
- package/tui/src/bootstrap-env.js +176 -0
- package/tui/src/embedded-workers.js +79 -0
- package/tui/src/http-transport-host.js +106 -0
- package/tui/src/index.js +340 -0
- package/tui/src/node-sdk-transport.js +1794 -0
- package/tui/src/platform.js +984 -0
- package/tui/src/plugin-config.js +273 -0
- package/tui/src/portal.js +7 -0
- package/tui/src/version.js +7 -0
- package/tui/tui-splash-mobile.txt +7 -0
- package/tui/tui-splash.txt +11 -0
- package/ui/core/README.md +6 -0
- package/ui/core/src/commands.js +93 -0
- package/ui/core/src/context-usage.js +212 -0
- package/ui/core/src/controller.js +6201 -0
- package/ui/core/src/formatting.js +1036 -0
- package/ui/core/src/history.js +950 -0
- package/ui/core/src/index.js +13 -0
- package/ui/core/src/layout.js +332 -0
- package/ui/core/src/reducer.js +1952 -0
- package/ui/core/src/selectors.js +5419 -0
- package/ui/core/src/session-errors.js +14 -0
- package/ui/core/src/session-tree.js +151 -0
- package/ui/core/src/state.js +251 -0
- package/ui/core/src/store.js +23 -0
- package/ui/core/src/system-titles.js +24 -0
- package/ui/core/src/themes/catppuccin-mocha.js +56 -0
- package/ui/core/src/themes/cobalt2.js +56 -0
- package/ui/core/src/themes/dark-high-contrast.js +56 -0
- package/ui/core/src/themes/daylight.js +62 -0
- package/ui/core/src/themes/dracula.js +56 -0
- package/ui/core/src/themes/github-dark.js +56 -0
- package/ui/core/src/themes/github-light.js +59 -0
- package/ui/core/src/themes/gruvbox-dark.js +56 -0
- package/ui/core/src/themes/hacker-x-matrix.js +56 -0
- package/ui/core/src/themes/hacker-x-orion-prime.js +56 -0
- package/ui/core/src/themes/helpers.js +79 -0
- package/ui/core/src/themes/high-contrast-mono.js +59 -0
- package/ui/core/src/themes/index.js +52 -0
- package/ui/core/src/themes/light-high-contrast.js +62 -0
- package/ui/core/src/themes/noctis-obscuro.js +56 -0
- package/ui/core/src/themes/noctis.js +56 -0
- package/ui/core/src/themes/paper-ink.js +62 -0
- package/ui/core/src/themes/solarized-ops.js +59 -0
- package/ui/core/src/themes/terminal-green.js +59 -0
- package/ui/core/src/themes/tokyo-night.js +56 -0
- package/ui/react/README.md +5 -0
- package/ui/react/src/chat-status.js +39 -0
- package/ui/react/src/components.js +1989 -0
- package/ui/react/src/index.js +4 -0
- package/ui/react/src/platform.js +15 -0
- package/ui/react/src/use-controller-state.js +38 -0
- package/ui/react/src/web-app.js +4457 -0
- package/web/README.md +198 -0
- package/web/api/router.js +196 -0
- package/web/api/ws.js +152 -0
- package/web/auth/authz/engine.js +204 -0
- package/web/auth/config.js +115 -0
- package/web/auth/index.js +175 -0
- package/web/auth/normalize/entra.js +22 -0
- package/web/auth/providers/entra.js +76 -0
- package/web/auth/providers/none.js +24 -0
- package/web/auth.js +10 -0
- package/web/bin/serve.js +53 -0
- package/web/config.js +20 -0
- package/web/dist/app.js +469 -0
- package/web/dist/assets/index-DmGOcKR-.css +1 -0
- package/web/dist/assets/index-xJ8IzIZY.js +24 -0
- package/web/dist/assets/msal-CytV9RFv.js +7 -0
- package/web/dist/assets/pilotswarm-D9pEmenA.js +90 -0
- package/web/dist/assets/react-CEPDSRB6.js +1 -0
- package/web/dist/index.html +16 -0
- package/web/runtime.js +455 -0
- package/web/server.js +276 -0
- package/index.js +0 -1
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export function isRecoverableTransportErrorText(text) {
|
|
2
|
+
const value = String(text || "");
|
|
3
|
+
return /\bConnection is closed\b/i.test(value)
|
|
4
|
+
|| /\bLive Copilot connection lost\b/i.test(value);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function shouldKeepRecoverableTransportWarning(previousSession, nextSession) {
|
|
8
|
+
if (!isRecoverableTransportErrorText(previousSession?.error)) return false;
|
|
9
|
+
if (nextSession?.error !== undefined) return false;
|
|
10
|
+
const nextStatus = String(nextSession?.status || "");
|
|
11
|
+
if (nextStatus !== "running") return false;
|
|
12
|
+
if (["Completed", "Failed", "Terminated"].includes(String(nextSession?.orchestrationStatus || ""))) return false;
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { systemSessionSortOrder } from "./system-titles.js";
|
|
2
|
+
|
|
3
|
+
function systemSessionOrder(session) {
|
|
4
|
+
if (!session?.isSystem) return Number.MAX_SAFE_INTEGER;
|
|
5
|
+
return systemSessionSortOrder(session);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function buildPreviousOrderMap(previousFlat = []) {
|
|
9
|
+
const order = new Map();
|
|
10
|
+
for (let index = 0; index < previousFlat.length; index += 1) {
|
|
11
|
+
const sessionId = previousFlat[index]?.sessionId;
|
|
12
|
+
if (!sessionId || order.has(sessionId)) continue;
|
|
13
|
+
order.set(sessionId, index);
|
|
14
|
+
}
|
|
15
|
+
return order;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function buildStableOrderMap(orderSource = []) {
|
|
19
|
+
if (orderSource instanceof Map) {
|
|
20
|
+
return new Map(orderSource);
|
|
21
|
+
}
|
|
22
|
+
if (Array.isArray(orderSource)) {
|
|
23
|
+
return buildPreviousOrderMap(orderSource);
|
|
24
|
+
}
|
|
25
|
+
const order = new Map();
|
|
26
|
+
for (const [sessionId, index] of Object.entries(orderSource || {})) {
|
|
27
|
+
if (!sessionId || typeof index !== "number" || Number.isNaN(index)) continue;
|
|
28
|
+
order.set(sessionId, index);
|
|
29
|
+
}
|
|
30
|
+
return order;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function isTreePinnableSession(session) {
|
|
34
|
+
return Boolean(
|
|
35
|
+
session
|
|
36
|
+
&& !session.isSystem
|
|
37
|
+
&& (session.isGroup || (!session.parentSessionId && !session.groupId)),
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function isPinnedSession(session, pinnedIds) {
|
|
42
|
+
return Boolean(isTreePinnableSession(session) && pinnedIds && pinnedIds.has(session.sessionId));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function rankSessionBand(session, pinnedIds) {
|
|
46
|
+
if (session.isSystem) return 0;
|
|
47
|
+
if (session.isGroup && isPinnedSession(session, pinnedIds)) return 1;
|
|
48
|
+
if (isPinnedSession(session, pinnedIds)) return 2;
|
|
49
|
+
if (session.isGroup) return 3;
|
|
50
|
+
return 4;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function summaryTimestamp(session) {
|
|
54
|
+
const raw = session?.updatedAt
|
|
55
|
+
?? session?.summaryUpdatedAt
|
|
56
|
+
?? session?.latestSummaryUpdatedAt;
|
|
57
|
+
const value = typeof raw === "number" ? raw : Date.parse(raw || "");
|
|
58
|
+
return Number.isFinite(value) ? value : 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function sortSessions(a, b, stableOrderMap, pinnedIds) {
|
|
62
|
+
const aRank = rankSessionBand(a, pinnedIds);
|
|
63
|
+
const bRank = rankSessionBand(b, pinnedIds);
|
|
64
|
+
if (aRank !== bRank) return aRank - bRank;
|
|
65
|
+
|
|
66
|
+
const aSystemOrder = systemSessionOrder(a);
|
|
67
|
+
const bSystemOrder = systemSessionOrder(b);
|
|
68
|
+
if (aSystemOrder !== bSystemOrder) return aSystemOrder - bSystemOrder;
|
|
69
|
+
|
|
70
|
+
const aPreviousOrder = stableOrderMap.get(a.sessionId);
|
|
71
|
+
const bPreviousOrder = stableOrderMap.get(b.sessionId);
|
|
72
|
+
if (
|
|
73
|
+
typeof aPreviousOrder === "number"
|
|
74
|
+
&& typeof bPreviousOrder === "number"
|
|
75
|
+
&& aPreviousOrder !== bPreviousOrder
|
|
76
|
+
) {
|
|
77
|
+
return aPreviousOrder - bPreviousOrder;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const aSummaryAt = summaryTimestamp(a);
|
|
81
|
+
const bSummaryAt = summaryTimestamp(b);
|
|
82
|
+
if (aSummaryAt > 0 && bSummaryAt > 0 && aSummaryAt !== bSummaryAt) {
|
|
83
|
+
return bSummaryAt - aSummaryAt;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const createdDiff = (b.createdAt || 0) - (a.createdAt || 0);
|
|
87
|
+
if (createdDiff !== 0) return createdDiff;
|
|
88
|
+
|
|
89
|
+
const aTitle = String(a.title || "");
|
|
90
|
+
const bTitle = String(b.title || "");
|
|
91
|
+
const titleDiff = aTitle.localeCompare(bTitle);
|
|
92
|
+
if (titleDiff !== 0) return titleDiff;
|
|
93
|
+
|
|
94
|
+
return String(a.sessionId || "").localeCompare(String(b.sessionId || ""));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function buildSessionTree(sessions = [], collapsedIds = new Set(), orderSource = [], pinnedIds = null) {
|
|
98
|
+
const byId = new Map();
|
|
99
|
+
const children = new Map();
|
|
100
|
+
const stableOrderMap = buildStableOrderMap(orderSource);
|
|
101
|
+
const pinSet = pinnedIds instanceof Set
|
|
102
|
+
? pinnedIds
|
|
103
|
+
: new Set(Array.isArray(pinnedIds) ? pinnedIds : []);
|
|
104
|
+
|
|
105
|
+
for (const session of sessions) {
|
|
106
|
+
byId.set(session.sessionId, session);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
for (const session of sessions) {
|
|
110
|
+
const groupParentId = !session.isGroup && session.groupId && !session.parentSessionId && byId.has(`group:${session.groupId}`)
|
|
111
|
+
? `group:${session.groupId}`
|
|
112
|
+
: null;
|
|
113
|
+
const parentId = session.parentSessionId || groupParentId;
|
|
114
|
+
if (!parentId || !byId.has(parentId)) continue;
|
|
115
|
+
if (!children.has(parentId)) children.set(parentId, []);
|
|
116
|
+
children.get(parentId).push(session);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
for (const childList of children.values()) {
|
|
120
|
+
// Pins are a top-level concept. If a previously pinned session moves
|
|
121
|
+
// into a group, the reducer prunes the pin and the tree ignores any
|
|
122
|
+
// stale pin while ordering children.
|
|
123
|
+
childList.sort((a, b) => sortSessions(a, b, stableOrderMap, pinSet));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const roots = sessions
|
|
127
|
+
.filter((session) => {
|
|
128
|
+
if (session.parentSessionId && byId.has(session.parentSessionId)) return false;
|
|
129
|
+
if (!session.isGroup && session.groupId && !session.parentSessionId && byId.has(`group:${session.groupId}`)) return false;
|
|
130
|
+
return true;
|
|
131
|
+
})
|
|
132
|
+
.sort((a, b) => sortSessions(a, b, stableOrderMap, pinSet));
|
|
133
|
+
|
|
134
|
+
const flat = [];
|
|
135
|
+
|
|
136
|
+
function visit(session, depth) {
|
|
137
|
+
const childList = children.get(session.sessionId) || [];
|
|
138
|
+
flat.push({
|
|
139
|
+
sessionId: session.sessionId,
|
|
140
|
+
depth,
|
|
141
|
+
hasChildren: childList.length > 0,
|
|
142
|
+
collapsed: collapsedIds.has(session.sessionId),
|
|
143
|
+
});
|
|
144
|
+
if (collapsedIds.has(session.sessionId)) return;
|
|
145
|
+
for (const child of childList) visit(child, depth + 1);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
for (const root of roots) visit(root, 0);
|
|
149
|
+
|
|
150
|
+
return flat;
|
|
151
|
+
}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { FOCUS_REGIONS, INSPECTOR_TABS } from "./commands.js";
|
|
2
|
+
import { DEFAULT_THEME_ID, getTheme } from "./themes/index.js";
|
|
3
|
+
|
|
4
|
+
const ARTIFACT_SOURCES = new Set(["agent", "user", "system"]);
|
|
5
|
+
|
|
6
|
+
export function normalizeSessionOwnerFilter(filter) {
|
|
7
|
+
const ownerKeys = Array.isArray(filter?.ownerKeys)
|
|
8
|
+
? [...new Set(filter.ownerKeys.map((key) => String(key || "").trim()).filter(Boolean))]
|
|
9
|
+
: [];
|
|
10
|
+
const hasExplicitFilter = filter && typeof filter === "object";
|
|
11
|
+
return {
|
|
12
|
+
all: hasExplicitFilter ? filter?.all === true : true,
|
|
13
|
+
includeSystem: filter?.includeSystem === true,
|
|
14
|
+
includeUnowned: filter?.includeUnowned === true,
|
|
15
|
+
includeMe: filter?.includeMe === true,
|
|
16
|
+
ownerKeys,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function normalizeArtifactEntry(entry) {
|
|
21
|
+
if (typeof entry === "string") {
|
|
22
|
+
const filename = entry.trim();
|
|
23
|
+
if (!filename) return null;
|
|
24
|
+
return {
|
|
25
|
+
filename,
|
|
26
|
+
sizeBytes: null,
|
|
27
|
+
contentType: "",
|
|
28
|
+
isBinary: false,
|
|
29
|
+
uploadedAt: "",
|
|
30
|
+
source: "agent",
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
if (!entry || typeof entry !== "object") return null;
|
|
34
|
+
const filename = String(entry.filename || "").trim();
|
|
35
|
+
if (!filename) return null;
|
|
36
|
+
const sizeBytes = Number(entry.sizeBytes);
|
|
37
|
+
const contentType = typeof entry.contentType === "string" ? entry.contentType : "";
|
|
38
|
+
return {
|
|
39
|
+
filename,
|
|
40
|
+
sizeBytes: Number.isFinite(sizeBytes) && sizeBytes >= 0 ? sizeBytes : null,
|
|
41
|
+
contentType,
|
|
42
|
+
isBinary: entry.isBinary === true,
|
|
43
|
+
uploadedAt: typeof entry.uploadedAt === "string" ? entry.uploadedAt : "",
|
|
44
|
+
source: ARTIFACT_SOURCES.has(entry.source) ? entry.source : "agent",
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function normalizeArtifactEntries(entries) {
|
|
49
|
+
const list = Array.isArray(entries) ? entries : [];
|
|
50
|
+
const normalized = [];
|
|
51
|
+
const seen = new Set();
|
|
52
|
+
for (const entry of list) {
|
|
53
|
+
const candidate = normalizeArtifactEntry(entry);
|
|
54
|
+
if (!candidate || seen.has(candidate.filename)) continue;
|
|
55
|
+
seen.add(candidate.filename);
|
|
56
|
+
normalized.push(candidate);
|
|
57
|
+
}
|
|
58
|
+
return normalized;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function findArtifactEntry(entries, filename) {
|
|
62
|
+
const target = String(filename || "").trim();
|
|
63
|
+
if (!target) return null;
|
|
64
|
+
return normalizeArtifactEntries(entries).find((entry) => entry.filename === target) || null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function normalizeStoredLayoutAdjustments(layoutAdjustments) {
|
|
68
|
+
const candidate = layoutAdjustments && typeof layoutAdjustments === "object"
|
|
69
|
+
? layoutAdjustments
|
|
70
|
+
: {};
|
|
71
|
+
const paneAdjust = Number(candidate.paneAdjust);
|
|
72
|
+
const sessionPaneAdjust = Number(candidate.sessionPaneAdjust);
|
|
73
|
+
const portalSessionColumnAdjust = Number(candidate.portalSessionColumnAdjust);
|
|
74
|
+
const activityPaneAdjust = Number(candidate.activityPaneAdjust);
|
|
75
|
+
return {
|
|
76
|
+
paneAdjust: Number.isFinite(paneAdjust) ? Math.trunc(paneAdjust) : 0,
|
|
77
|
+
sessionPaneAdjust: Number.isFinite(sessionPaneAdjust) ? Math.trunc(sessionPaneAdjust) : 0,
|
|
78
|
+
portalSessionColumnAdjust: Number.isFinite(portalSessionColumnAdjust) ? Math.trunc(portalSessionColumnAdjust) : 0,
|
|
79
|
+
activityPaneAdjust: Number.isFinite(activityPaneAdjust) ? Math.trunc(activityPaneAdjust) : 0,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function normalizeStoredPinnedSessionIds(value) {
|
|
84
|
+
if (!Array.isArray(value)) return [];
|
|
85
|
+
const seen = new Set();
|
|
86
|
+
const out = [];
|
|
87
|
+
for (const entry of value) {
|
|
88
|
+
const id = String(entry || "").trim();
|
|
89
|
+
if (!id || seen.has(id)) continue;
|
|
90
|
+
seen.add(id);
|
|
91
|
+
out.push(id);
|
|
92
|
+
}
|
|
93
|
+
return out;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function normalizeStoredCollapsedSessionIds(value) {
|
|
97
|
+
if (!Array.isArray(value)) return new Set();
|
|
98
|
+
const out = new Set();
|
|
99
|
+
for (const entry of value) {
|
|
100
|
+
const id = String(entry || "").trim();
|
|
101
|
+
if (!id) continue;
|
|
102
|
+
out.add(id);
|
|
103
|
+
}
|
|
104
|
+
return out;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function normalizeStoredActiveSessionId(value) {
|
|
108
|
+
if (value == null) return null;
|
|
109
|
+
const id = String(value).trim();
|
|
110
|
+
return id ? id : null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function createInitialState({ mode = "local", branding = null, themeId = null, chatViewMode = null, sessionOwnerFilter = null, layoutAdjustments = null, pinnedSessionIds = null, collapsedSessionIds = null, activeSessionId = null } = {}) {
|
|
114
|
+
const hasStoredSessionOwnerFilter = sessionOwnerFilter != null;
|
|
115
|
+
const hasStoredCollapsedSessionIds = collapsedSessionIds != null;
|
|
116
|
+
const initialLayoutAdjustments = normalizeStoredLayoutAdjustments(layoutAdjustments);
|
|
117
|
+
return {
|
|
118
|
+
branding: branding || {
|
|
119
|
+
title: "PilotSwarm",
|
|
120
|
+
splash: "{bold}{cyan-fg}PilotSwarm{/cyan-fg}{/bold}",
|
|
121
|
+
},
|
|
122
|
+
auth: {
|
|
123
|
+
principal: null,
|
|
124
|
+
authorization: null,
|
|
125
|
+
},
|
|
126
|
+
ui: {
|
|
127
|
+
focusRegion: FOCUS_REGIONS.SESSIONS,
|
|
128
|
+
inspectorTab: INSPECTOR_TABS[0],
|
|
129
|
+
chatViewMode: chatViewMode === "summary" ? "summary" : "transcript",
|
|
130
|
+
statsViewMode: "session",
|
|
131
|
+
prompt: "",
|
|
132
|
+
promptCursor: 0,
|
|
133
|
+
promptRows: 1,
|
|
134
|
+
promptAttachments: [],
|
|
135
|
+
promptEdit: null,
|
|
136
|
+
statusText: "Starting PilotSwarm...",
|
|
137
|
+
// A persisted theme id may name a theme that no longer ships —
|
|
138
|
+
// fall back to the default instead of crashing theme consumers.
|
|
139
|
+
themeId: getTheme(themeId)?.id || DEFAULT_THEME_ID,
|
|
140
|
+
modal: null,
|
|
141
|
+
fullscreenPane: null,
|
|
142
|
+
layout: {
|
|
143
|
+
...initialLayoutAdjustments,
|
|
144
|
+
viewportWidth: 120,
|
|
145
|
+
viewportHeight: 40,
|
|
146
|
+
},
|
|
147
|
+
scroll: {
|
|
148
|
+
chat: 0,
|
|
149
|
+
inspector: 0,
|
|
150
|
+
activity: 0,
|
|
151
|
+
filePreview: 0,
|
|
152
|
+
},
|
|
153
|
+
// Per-session chat scroll memory (rows from bottom), restored on
|
|
154
|
+
// sessions/selected and evicted with the session's history.
|
|
155
|
+
chatScrollBySession: {},
|
|
156
|
+
followBottom: {
|
|
157
|
+
inspector: true,
|
|
158
|
+
activity: true,
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
connection: {
|
|
162
|
+
mode,
|
|
163
|
+
connected: false,
|
|
164
|
+
workersOnline: null,
|
|
165
|
+
error: null,
|
|
166
|
+
},
|
|
167
|
+
sessions: {
|
|
168
|
+
byId: {},
|
|
169
|
+
flat: [],
|
|
170
|
+
activeSessionId: normalizeStoredActiveSessionId(activeSessionId),
|
|
171
|
+
collapsedIds: normalizeStoredCollapsedSessionIds(collapsedSessionIds),
|
|
172
|
+
collapsedIdsExplicit: hasStoredCollapsedSessionIds,
|
|
173
|
+
pinnedIds: normalizeStoredPinnedSessionIds(pinnedSessionIds),
|
|
174
|
+
selectedIds: [],
|
|
175
|
+
selectMode: false,
|
|
176
|
+
orderById: {},
|
|
177
|
+
nextOrderOrdinal: 0,
|
|
178
|
+
filterQuery: "",
|
|
179
|
+
ownerFilterExplicit: hasStoredSessionOwnerFilter,
|
|
180
|
+
ownerFilter: normalizeSessionOwnerFilter(sessionOwnerFilter),
|
|
181
|
+
},
|
|
182
|
+
history: {
|
|
183
|
+
bySessionId: new Map(),
|
|
184
|
+
},
|
|
185
|
+
outbox: {
|
|
186
|
+
bySessionId: {},
|
|
187
|
+
},
|
|
188
|
+
orchestration: {
|
|
189
|
+
bySessionId: {},
|
|
190
|
+
},
|
|
191
|
+
executionHistory: {
|
|
192
|
+
bySessionId: {},
|
|
193
|
+
format: "pretty",
|
|
194
|
+
},
|
|
195
|
+
files: {
|
|
196
|
+
bySessionId: {},
|
|
197
|
+
fullscreen: false,
|
|
198
|
+
selectedArtifactId: null,
|
|
199
|
+
filter: {
|
|
200
|
+
scope: "selectedSession",
|
|
201
|
+
query: "",
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
logs: {
|
|
205
|
+
available: false,
|
|
206
|
+
availabilityReason: "Log tailing disabled: no K8S_CONTEXT configured in the env file.",
|
|
207
|
+
tailing: false,
|
|
208
|
+
entries: [],
|
|
209
|
+
filter: {
|
|
210
|
+
source: "allNodes",
|
|
211
|
+
level: "all",
|
|
212
|
+
format: "pretty",
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
sessionStats: {
|
|
216
|
+
bySessionId: {},
|
|
217
|
+
},
|
|
218
|
+
fleetStats: {
|
|
219
|
+
loading: false,
|
|
220
|
+
data: null,
|
|
221
|
+
userStats: null,
|
|
222
|
+
fetchedAt: 0,
|
|
223
|
+
},
|
|
224
|
+
admin: {
|
|
225
|
+
// Whether the Admin Console is taking over the workspace and
|
|
226
|
+
// hiding the session/chat panes. Persisted only in-memory.
|
|
227
|
+
visible: false,
|
|
228
|
+
loading: false,
|
|
229
|
+
loadError: null,
|
|
230
|
+
// Public profile snapshot from the management API. Never holds
|
|
231
|
+
// the raw GitHub Copilot key — only the `githubCopilotKeySet`
|
|
232
|
+
// boolean flag.
|
|
233
|
+
profile: null,
|
|
234
|
+
ghcpKey: {
|
|
235
|
+
// Editing flag is the single host-neutral signal that the
|
|
236
|
+
// user is composing a new key. Both the portal's inline
|
|
237
|
+
// form and the native TUI's overlay render against this.
|
|
238
|
+
editing: false,
|
|
239
|
+
draft: "",
|
|
240
|
+
// cursorIndex is only consumed by the native TUI overlay
|
|
241
|
+
// (browser <input> elements manage their own cursor). It
|
|
242
|
+
// is kept in shared state so the controller mutators can
|
|
243
|
+
// remain host-neutral.
|
|
244
|
+
cursorIndex: 0,
|
|
245
|
+
saving: false,
|
|
246
|
+
error: null,
|
|
247
|
+
lastSavedAt: 0,
|
|
248
|
+
},
|
|
249
|
+
},
|
|
250
|
+
};
|
|
251
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export function createStore(reducer, initialState) {
|
|
2
|
+
let state = initialState;
|
|
3
|
+
const listeners = new Set();
|
|
4
|
+
|
|
5
|
+
return {
|
|
6
|
+
getState() {
|
|
7
|
+
return state;
|
|
8
|
+
},
|
|
9
|
+
dispatch(action) {
|
|
10
|
+
const nextState = reducer(state, action);
|
|
11
|
+
if (Object.is(nextState, state)) {
|
|
12
|
+
return action;
|
|
13
|
+
}
|
|
14
|
+
state = nextState;
|
|
15
|
+
for (const listener of listeners) listener(state, action);
|
|
16
|
+
return action;
|
|
17
|
+
},
|
|
18
|
+
subscribe(listener) {
|
|
19
|
+
listeners.add(listener);
|
|
20
|
+
return () => listeners.delete(listener);
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export function canonicalSystemTitle(session, brandingTitle = "PilotSwarm") {
|
|
2
|
+
const brandedRootTitle = brandingTitle || "PilotSwarm";
|
|
3
|
+
const agentId = String(session?.agentId || "");
|
|
4
|
+
if (agentId === "pilotswarm") return brandedRootTitle;
|
|
5
|
+
if (agentId === "sweeper") return "Sweeper Agent";
|
|
6
|
+
if (agentId === "resourcemgr") return "Resource Manager Agent";
|
|
7
|
+
if (agentId === "facts-manager") return "Facts Manager";
|
|
8
|
+
|
|
9
|
+
const rawTitle = String(session?.title || "").trim();
|
|
10
|
+
if (/^pilotswarm(?: agent)?$/i.test(rawTitle)) return brandedRootTitle;
|
|
11
|
+
if (/^sweeper agent$/i.test(rawTitle) || /^sweeper$/i.test(rawTitle)) return "Sweeper Agent";
|
|
12
|
+
if (/^resource manager agent$/i.test(rawTitle) || /^resourcemgr$/i.test(rawTitle)) return "Resource Manager Agent";
|
|
13
|
+
if (/^facts manager$/i.test(rawTitle) || /^facts-manager$/i.test(rawTitle)) return "Facts Manager";
|
|
14
|
+
return rawTitle || "System Agent";
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function systemSessionSortOrder(session) {
|
|
18
|
+
const title = canonicalSystemTitle(session, "PilotSwarm");
|
|
19
|
+
if (title === "PilotSwarm") return 0;
|
|
20
|
+
if (title === "Sweeper Agent") return 1;
|
|
21
|
+
if (title === "Resource Manager Agent") return 2;
|
|
22
|
+
if (title === "Facts Manager") return 3;
|
|
23
|
+
return 10;
|
|
24
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { createTheme } from "./helpers.js";
|
|
2
|
+
|
|
3
|
+
const catppuccinMochaTheme = createTheme({
|
|
4
|
+
id: "catppuccin-mocha",
|
|
5
|
+
label: "Catppuccin Mocha",
|
|
6
|
+
description: "Creamy dark palette with soft pastels and high legibility.",
|
|
7
|
+
page: {
|
|
8
|
+
background: "#1e1e2e",
|
|
9
|
+
foreground: "#cdd6f4",
|
|
10
|
+
overlayBackground: "#1e1e2e",
|
|
11
|
+
overlayForeground: "#cdd6f4",
|
|
12
|
+
hintColor: "#bac2de",
|
|
13
|
+
modalBackdrop: "rgba(17, 17, 27, 0.74)",
|
|
14
|
+
modalBackground: "#313244",
|
|
15
|
+
modalBorder: "#585b70",
|
|
16
|
+
modalForeground: "#cdd6f4",
|
|
17
|
+
modalMuted: "#bac2de",
|
|
18
|
+
modalSelectedBackground: "#45475a",
|
|
19
|
+
modalSelectedBorder: "#89b4fa",
|
|
20
|
+
modalSelectedForeground: "#cdd6f4",
|
|
21
|
+
},
|
|
22
|
+
terminal: {
|
|
23
|
+
background: "#1e1e2e",
|
|
24
|
+
foreground: "#cdd6f4",
|
|
25
|
+
cursor: "#f5e0dc",
|
|
26
|
+
cursorAccent: "#1e1e2e",
|
|
27
|
+
selectionBackground: "rgba(137, 180, 250, 0.22)",
|
|
28
|
+
black: "#45475a",
|
|
29
|
+
red: "#f38ba8",
|
|
30
|
+
green: "#a6e3a1",
|
|
31
|
+
yellow: "#f9e2af",
|
|
32
|
+
blue: "#89b4fa",
|
|
33
|
+
magenta: "#f5c2e7",
|
|
34
|
+
cyan: "#94e2d5",
|
|
35
|
+
white: "#bac2de",
|
|
36
|
+
brightBlack: "#585b70",
|
|
37
|
+
brightRed: "#f38ba8",
|
|
38
|
+
brightGreen: "#a6e3a1",
|
|
39
|
+
brightYellow: "#f9e2af",
|
|
40
|
+
brightBlue: "#89b4fa",
|
|
41
|
+
brightMagenta: "#f5c2e7",
|
|
42
|
+
brightCyan: "#94e2d5",
|
|
43
|
+
brightWhite: "#f5e0dc",
|
|
44
|
+
},
|
|
45
|
+
tui: {
|
|
46
|
+
surface: "#1e1e2e",
|
|
47
|
+
activeHighlightBackground: "#45475a",
|
|
48
|
+
activeHighlightForeground: "#cdd6f4",
|
|
49
|
+
selectionBackground: "#89b4fa",
|
|
50
|
+
selectionForeground: "#1e1e2e",
|
|
51
|
+
promptCursorBackground: "#f5e0dc",
|
|
52
|
+
promptCursorForeground: "#1e1e2e",
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
export default catppuccinMochaTheme;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { createTheme } from "./helpers.js";
|
|
2
|
+
|
|
3
|
+
const cobalt2Theme = createTheme({
|
|
4
|
+
id: "cobalt2",
|
|
5
|
+
label: "Cobalt2",
|
|
6
|
+
description: "Electric blue shell with bright yellow accents and saturated syntax colors.",
|
|
7
|
+
page: {
|
|
8
|
+
background: "#193549",
|
|
9
|
+
foreground: "#ffffff",
|
|
10
|
+
overlayBackground: "#193549",
|
|
11
|
+
overlayForeground: "#ffffff",
|
|
12
|
+
hintColor: "#a8c5e6",
|
|
13
|
+
modalBackdrop: "rgba(7, 17, 28, 0.68)",
|
|
14
|
+
modalBackground: "#224b68",
|
|
15
|
+
modalBorder: "#2e6c99",
|
|
16
|
+
modalForeground: "#ffffff",
|
|
17
|
+
modalMuted: "#a8c5e6",
|
|
18
|
+
modalSelectedBackground: "#ffc600",
|
|
19
|
+
modalSelectedBorder: "#ffc600",
|
|
20
|
+
modalSelectedForeground: "#193549",
|
|
21
|
+
},
|
|
22
|
+
terminal: {
|
|
23
|
+
background: "#193549",
|
|
24
|
+
foreground: "#ffffff",
|
|
25
|
+
cursor: "#ffc600",
|
|
26
|
+
cursorAccent: "#193549",
|
|
27
|
+
selectionBackground: "rgba(255, 255, 255, 0.18)",
|
|
28
|
+
black: "#000000",
|
|
29
|
+
red: "#ff628c",
|
|
30
|
+
green: "#3ad900",
|
|
31
|
+
yellow: "#ff9d00",
|
|
32
|
+
blue: "#0088ff",
|
|
33
|
+
magenta: "#ff628c",
|
|
34
|
+
cyan: "#80ffbb",
|
|
35
|
+
white: "#ffffff",
|
|
36
|
+
brightBlack: "#666666",
|
|
37
|
+
brightRed: "#ff628c",
|
|
38
|
+
brightGreen: "#3ad900",
|
|
39
|
+
brightYellow: "#ff9d00",
|
|
40
|
+
brightBlue: "#0088ff",
|
|
41
|
+
brightMagenta: "#ff9d00",
|
|
42
|
+
brightCyan: "#80ffbb",
|
|
43
|
+
brightWhite: "#ffffff",
|
|
44
|
+
},
|
|
45
|
+
tui: {
|
|
46
|
+
surface: "#193549",
|
|
47
|
+
activeHighlightBackground: "#0f5f91",
|
|
48
|
+
activeHighlightForeground: "#ffffff",
|
|
49
|
+
selectionBackground: "#ffc600",
|
|
50
|
+
selectionForeground: "#193549",
|
|
51
|
+
promptCursorBackground: "#ffc600",
|
|
52
|
+
promptCursorForeground: "#193549",
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
export default cobalt2Theme;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { createTheme } from "./helpers.js";
|
|
2
|
+
|
|
3
|
+
const darkHighContrastTheme = createTheme({
|
|
4
|
+
id: "dark-high-contrast",
|
|
5
|
+
label: "Dark High Contrast",
|
|
6
|
+
description: "Pure black background with maximum contrast ANSI colors for accessibility.",
|
|
7
|
+
page: {
|
|
8
|
+
background: "#000000",
|
|
9
|
+
foreground: "#ffffff",
|
|
10
|
+
overlayBackground: "#000000",
|
|
11
|
+
overlayForeground: "#ffffff",
|
|
12
|
+
hintColor: "#3794ff",
|
|
13
|
+
modalBackdrop: "rgba(0, 0, 0, 0.85)",
|
|
14
|
+
modalBackground: "#0c0c0c",
|
|
15
|
+
modalBorder: "#6fc3df",
|
|
16
|
+
modalForeground: "#ffffff",
|
|
17
|
+
modalMuted: "#9d9d9d",
|
|
18
|
+
modalSelectedBackground: "#0f4a85",
|
|
19
|
+
modalSelectedBorder: "#f38518",
|
|
20
|
+
modalSelectedForeground: "#ffffff",
|
|
21
|
+
},
|
|
22
|
+
terminal: {
|
|
23
|
+
background: "#000000",
|
|
24
|
+
foreground: "#ffffff",
|
|
25
|
+
cursor: "#ffffff",
|
|
26
|
+
cursorAccent: "#000000",
|
|
27
|
+
selectionBackground: "rgba(255, 255, 255, 0.3)",
|
|
28
|
+
black: "#000000",
|
|
29
|
+
red: "#f44747",
|
|
30
|
+
green: "#73c991",
|
|
31
|
+
yellow: "#e5e510",
|
|
32
|
+
blue: "#3794ff",
|
|
33
|
+
magenta: "#bc3fbc",
|
|
34
|
+
cyan: "#29b8db",
|
|
35
|
+
white: "#e5e5e5",
|
|
36
|
+
brightBlack: "#666666",
|
|
37
|
+
brightRed: "#f14c4c",
|
|
38
|
+
brightGreen: "#89d185",
|
|
39
|
+
brightYellow: "#f5f543",
|
|
40
|
+
brightBlue: "#6fc3df",
|
|
41
|
+
brightMagenta: "#d670d6",
|
|
42
|
+
brightCyan: "#2ee2e2",
|
|
43
|
+
brightWhite: "#ffffff",
|
|
44
|
+
},
|
|
45
|
+
tui: {
|
|
46
|
+
surface: "#000000",
|
|
47
|
+
activeHighlightBackground: "#0f4a85",
|
|
48
|
+
activeHighlightForeground: "#ffffff",
|
|
49
|
+
selectionBackground: "#f38518",
|
|
50
|
+
selectionForeground: "#000000",
|
|
51
|
+
promptCursorBackground: "#ffffff",
|
|
52
|
+
promptCursorForeground: "#000000",
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
export default darkHighContrastTheme;
|