pilotswarm 0.5.1 → 0.5.3
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/mcp/dist/src/session-id.d.ts +13 -0
- package/mcp/dist/src/session-id.d.ts.map +1 -0
- package/mcp/dist/src/session-id.js +15 -0
- package/mcp/dist/src/session-id.js.map +1 -0
- package/mcp/dist/src/tools/artifacts.d.ts.map +1 -1
- package/mcp/dist/src/tools/artifacts.js +5 -4
- package/mcp/dist/src/tools/artifacts.js.map +1 -1
- package/mcp/dist/src/tools/observability.d.ts.map +1 -1
- package/mcp/dist/src/tools/observability.js +2 -1
- package/mcp/dist/src/tools/observability.js.map +1 -1
- package/mcp/dist/src/tools/sessions.d.ts.map +1 -1
- package/mcp/dist/src/tools/sessions.js +9 -8
- package/mcp/dist/src/tools/sessions.js.map +1 -1
- package/mcp/dist/src/tools/turn-control.d.ts.map +1 -1
- package/mcp/dist/src/tools/turn-control.js +5 -4
- package/mcp/dist/src/tools/turn-control.js.map +1 -1
- package/package.json +3 -3
- package/tui/plugins/.mcp.json +1 -7
- package/tui/src/app.js +12 -1
- package/tui/src/node-sdk-transport.js +17 -0
- package/ui/core/src/controller.js +62 -11
- package/ui/core/src/history.js +34 -0
- package/ui/core/src/reducer.js +87 -0
- package/ui/core/src/selectors.js +281 -174
- package/ui/core/src/state.js +15 -0
- package/ui/react/src/components.js +27 -8
- package/ui/react/src/web-app.js +83 -38
- package/web/dist/assets/index-BKai0rVp.js +24 -0
- package/web/dist/assets/index-BRbv6TsU.css +1 -0
- package/web/dist/assets/pilotswarm-PUVWBejV.js +90 -0
- package/web/dist/assets/{react-CRYBfNR4.js → react-BouHbnso.js} +1 -1
- package/web/dist/index.html +4 -4
- package/web/runtime.js +23 -2
- package/web/dist/assets/index-BmqU2WsR.js +0 -24
- package/web/dist/assets/index-D2-7fi56.css +0 -1
- package/web/dist/assets/pilotswarm-cIaYAE9e.js +0 -90
|
@@ -2160,6 +2160,7 @@ export class PilotSwarmUiController {
|
|
|
2160
2160
|
try {
|
|
2161
2161
|
const profile = await this.transport.getCurrentUserProfile();
|
|
2162
2162
|
this.dispatch({ type: "admin/profile/loaded", profile });
|
|
2163
|
+
await this.refreshSystemGhcpKeyStatus(profile);
|
|
2163
2164
|
return profile || null;
|
|
2164
2165
|
} catch (error) {
|
|
2165
2166
|
this.dispatch({ type: "admin/profile/loadFailed", error: error?.message || String(error) });
|
|
@@ -2167,6 +2168,35 @@ export class PilotSwarmUiController {
|
|
|
2167
2168
|
}
|
|
2168
2169
|
}
|
|
2169
2170
|
|
|
2171
|
+
/**
|
|
2172
|
+
* Load the SYSTEM user's Copilot key status (admins only). Quietly a
|
|
2173
|
+
* no-op when the caller is not admin or the transport predates the
|
|
2174
|
+
* feature, so the Admin Console degrades to the per-user-only view.
|
|
2175
|
+
*/
|
|
2176
|
+
async refreshSystemGhcpKeyStatus(profile = null) {
|
|
2177
|
+
const effective = profile || this.getState().admin?.profile || null;
|
|
2178
|
+
if (!effective?.isAdmin) return null;
|
|
2179
|
+
if (typeof this.transport.getSystemGitHubCopilotKeyStatus !== "function") return null;
|
|
2180
|
+
this.dispatch({ type: "admin/systemGhcpKey/loading" });
|
|
2181
|
+
try {
|
|
2182
|
+
const status = await this.transport.getSystemGitHubCopilotKeyStatus();
|
|
2183
|
+
this.dispatch({ type: "admin/systemGhcpKey/loaded", status });
|
|
2184
|
+
return status || null;
|
|
2185
|
+
} catch (error) {
|
|
2186
|
+
this.dispatch({ type: "admin/systemGhcpKey/loadFailed", error: error?.message || String(error) });
|
|
2187
|
+
return null;
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
|
|
2191
|
+
/**
|
|
2192
|
+
* Admin-only: switch the key editor between "your key" and
|
|
2193
|
+
* "System key" (the key ownerless system sessions run on).
|
|
2194
|
+
*/
|
|
2195
|
+
setAdminGhcpKeyStoreAsSystem(value) {
|
|
2196
|
+
if (value && !this.getState().admin?.profile?.isAdmin) return;
|
|
2197
|
+
this.dispatch({ type: "admin/ghcpKey/setSystemTarget", value: Boolean(value) });
|
|
2198
|
+
}
|
|
2199
|
+
|
|
2170
2200
|
beginAdminEditGhcpKey() {
|
|
2171
2201
|
this.dispatch({ type: "admin/ghcpKey/beginEdit", draft: "" });
|
|
2172
2202
|
}
|
|
@@ -2218,8 +2248,12 @@ export class PilotSwarmUiController {
|
|
|
2218
2248
|
* use `clearAdminGhcpKey()` for that.
|
|
2219
2249
|
*/
|
|
2220
2250
|
async saveAdminGhcpKey() {
|
|
2221
|
-
|
|
2222
|
-
|
|
2251
|
+
const storeAsSystem = Boolean(this.getState().admin.ghcpKey.storeAsSystem);
|
|
2252
|
+
const setter = storeAsSystem ? "setSystemGitHubCopilotKey" : "setCurrentUserGitHubCopilotKey";
|
|
2253
|
+
if (typeof this.transport[setter] !== "function") {
|
|
2254
|
+
this.dispatch({ type: "admin/ghcpKey/saveFailed", error: storeAsSystem
|
|
2255
|
+
? "This deployment does not support System keys yet."
|
|
2256
|
+
: "Admin Console is not available on this transport." });
|
|
2223
2257
|
return;
|
|
2224
2258
|
}
|
|
2225
2259
|
const draft = String(this.getState().admin.ghcpKey.draft || "").trim();
|
|
@@ -2229,8 +2263,13 @@ export class PilotSwarmUiController {
|
|
|
2229
2263
|
}
|
|
2230
2264
|
this.dispatch({ type: "admin/ghcpKey/saving" });
|
|
2231
2265
|
try {
|
|
2232
|
-
|
|
2233
|
-
|
|
2266
|
+
if (storeAsSystem) {
|
|
2267
|
+
const status = await this.transport.setSystemGitHubCopilotKey({ key: draft });
|
|
2268
|
+
this.dispatch({ type: "admin/systemGhcpKey/saved", status });
|
|
2269
|
+
} else {
|
|
2270
|
+
const profile = await this.transport.setCurrentUserGitHubCopilotKey({ key: draft });
|
|
2271
|
+
this.dispatch({ type: "admin/ghcpKey/saved", profile });
|
|
2272
|
+
}
|
|
2234
2273
|
} catch (error) {
|
|
2235
2274
|
this.dispatch({ type: "admin/ghcpKey/saveFailed", error: error?.message || String(error) });
|
|
2236
2275
|
}
|
|
@@ -2241,14 +2280,23 @@ export class PilotSwarmUiController {
|
|
|
2241
2280
|
* worker's env-supplied default token.
|
|
2242
2281
|
*/
|
|
2243
2282
|
async clearAdminGhcpKey() {
|
|
2244
|
-
|
|
2245
|
-
|
|
2283
|
+
const storeAsSystem = Boolean(this.getState().admin.ghcpKey.storeAsSystem);
|
|
2284
|
+
const setter = storeAsSystem ? "setSystemGitHubCopilotKey" : "setCurrentUserGitHubCopilotKey";
|
|
2285
|
+
if (typeof this.transport[setter] !== "function") {
|
|
2286
|
+
this.dispatch({ type: "admin/ghcpKey/saveFailed", error: storeAsSystem
|
|
2287
|
+
? "This deployment does not support System keys yet."
|
|
2288
|
+
: "Admin Console is not available on this transport." });
|
|
2246
2289
|
return;
|
|
2247
2290
|
}
|
|
2248
2291
|
this.dispatch({ type: "admin/ghcpKey/saving" });
|
|
2249
2292
|
try {
|
|
2250
|
-
|
|
2251
|
-
|
|
2293
|
+
if (storeAsSystem) {
|
|
2294
|
+
const status = await this.transport.setSystemGitHubCopilotKey({ key: null });
|
|
2295
|
+
this.dispatch({ type: "admin/systemGhcpKey/saved", status });
|
|
2296
|
+
} else {
|
|
2297
|
+
const profile = await this.transport.setCurrentUserGitHubCopilotKey({ key: null });
|
|
2298
|
+
this.dispatch({ type: "admin/ghcpKey/saved", profile });
|
|
2299
|
+
}
|
|
2252
2300
|
} catch (error) {
|
|
2253
2301
|
this.dispatch({ type: "admin/ghcpKey/saveFailed", error: error?.message || String(error) });
|
|
2254
2302
|
}
|
|
@@ -5172,11 +5220,14 @@ export class PilotSwarmUiController {
|
|
|
5172
5220
|
|
|
5173
5221
|
const contentWidth = Math.max(20, layout.leftWidth - 4);
|
|
5174
5222
|
const contentHeight = Math.max(1, layout.chatPaneHeight - 2);
|
|
5175
|
-
const lines =
|
|
5176
|
-
|
|
5223
|
+
const lines = selectChatLines(state, contentWidth);
|
|
5224
|
+
// The live "Working" strip and the queued-prompt overlay are both
|
|
5225
|
+
// pinned in the bottom-sticky region (matching the ChatPane render),
|
|
5226
|
+
// so the transcript scroll math must reserve them here — not inline.
|
|
5227
|
+
const bottomStickyLines = [
|
|
5228
|
+
...selectOutboxOverlayLines(state, contentWidth),
|
|
5177
5229
|
...selectLiveActivityLines(state),
|
|
5178
5230
|
];
|
|
5179
|
-
const bottomStickyLines = selectOutboxOverlayLines(state, contentWidth);
|
|
5180
5231
|
const bottomStickyHeight = Math.min(
|
|
5181
5232
|
Math.max(0, Math.floor(contentHeight * 0.34)),
|
|
5182
5233
|
countWrappedRenderableLines(bottomStickyLines, contentWidth),
|
package/ui/core/src/history.js
CHANGED
|
@@ -360,12 +360,16 @@ function buildChatMessage(event, role) {
|
|
|
360
360
|
|
|
361
361
|
const text = extractVisibleChatText(rawText, role);
|
|
362
362
|
if (!hasVisibleMessageText(text)) return null;
|
|
363
|
+
const clientMessageIds = Array.isArray(event?.data?.clientMessageIds)
|
|
364
|
+
? event.data.clientMessageIds.filter((id) => typeof id === "string" && id)
|
|
365
|
+
: [];
|
|
363
366
|
return {
|
|
364
367
|
id: `${event.sessionId}:${event.seq}`,
|
|
365
368
|
role: deriveChatRole(event, role, text),
|
|
366
369
|
text,
|
|
367
370
|
time: formatTimestamp(event.createdAt),
|
|
368
371
|
createdAt: event.createdAt instanceof Date ? event.createdAt.getTime() : new Date(event.createdAt).getTime(),
|
|
372
|
+
...(clientMessageIds.length > 0 ? { clientMessageIds } : {}),
|
|
369
373
|
};
|
|
370
374
|
}
|
|
371
375
|
|
|
@@ -873,13 +877,43 @@ export function appendEventToHistory(history, event) {
|
|
|
873
877
|
loadedEventLimit,
|
|
874
878
|
loadedEventCount: Math.max(Number(history?.loadedEventCount || 0), nextEvents.length),
|
|
875
879
|
hasOlderEvents: Boolean(history?.hasOlderEvents),
|
|
880
|
+
// clientMessageIds whose turn was user-stopped mid-flight. Carried
|
|
881
|
+
// across appends so a prompt stays flagged even as the transcript
|
|
882
|
+
// clamps/reloads.
|
|
883
|
+
stoppedMessageIds: Array.isArray(history?.stoppedMessageIds) ? history.stoppedMessageIds : [],
|
|
876
884
|
};
|
|
877
885
|
|
|
886
|
+
// A stopped turn leaves a durable session.turn_stopped carrying the
|
|
887
|
+
// interrupted prompt's clientMessageIds. Record them and retroactively
|
|
888
|
+
// flag any matching transcript message (the user.message usually lands
|
|
889
|
+
// first, at turn start; the stop lands at turn end).
|
|
890
|
+
if (event.eventType === "session.turn_stopped") {
|
|
891
|
+
const ids = Array.isArray(event?.data?.clientMessageIds)
|
|
892
|
+
? event.data.clientMessageIds.filter((id) => typeof id === "string" && id)
|
|
893
|
+
: [];
|
|
894
|
+
if (ids.length > 0) {
|
|
895
|
+
const merged = new Set([...next.stoppedMessageIds, ...ids]);
|
|
896
|
+
next.stoppedMessageIds = Array.from(merged);
|
|
897
|
+
next.chat = next.chat.map((m) => (
|
|
898
|
+
Array.isArray(m.clientMessageIds) && m.clientMessageIds.some((id) => merged.has(id))
|
|
899
|
+
? { ...m, stopped: true }
|
|
900
|
+
: m
|
|
901
|
+
));
|
|
902
|
+
}
|
|
903
|
+
return next;
|
|
904
|
+
}
|
|
905
|
+
|
|
878
906
|
if (event.eventType === "user.message") {
|
|
879
907
|
next.activity.push(...buildEmbeddedSystemNoticeActivityItems(event, "user"));
|
|
880
908
|
next.activity = clampHistoryItems(next.activity, loadedEventLimit);
|
|
881
909
|
const message = buildChatMessage(event, "user");
|
|
882
910
|
if (!message) return next;
|
|
911
|
+
// Prospective flag: covers a bulk load where the stop event arrived
|
|
912
|
+
// before this message in the reduce order.
|
|
913
|
+
if (Array.isArray(message.clientMessageIds)
|
|
914
|
+
&& message.clientMessageIds.some((id) => next.stoppedMessageIds.includes(id))) {
|
|
915
|
+
message.stopped = true;
|
|
916
|
+
}
|
|
883
917
|
next.chat = reconcileOptimisticMessage(next.chat, message);
|
|
884
918
|
next.chat.push(message);
|
|
885
919
|
next.chat = clampHistoryItems(dedupeChatMessages(next.chat), loadedEventLimit);
|
package/ui/core/src/reducer.js
CHANGED
|
@@ -1488,6 +1488,7 @@ export function appReducer(state, action) {
|
|
|
1488
1488
|
saving: false,
|
|
1489
1489
|
error: null,
|
|
1490
1490
|
lastSavedAt: state.admin.ghcpKey.lastSavedAt,
|
|
1491
|
+
storeAsSystem: Boolean(state.admin.ghcpKey.storeAsSystem),
|
|
1491
1492
|
},
|
|
1492
1493
|
},
|
|
1493
1494
|
};
|
|
@@ -1524,6 +1525,7 @@ export function appReducer(state, action) {
|
|
|
1524
1525
|
saving: false,
|
|
1525
1526
|
error: null,
|
|
1526
1527
|
lastSavedAt: state.admin.ghcpKey.lastSavedAt,
|
|
1528
|
+
storeAsSystem: Boolean(state.admin.ghcpKey.storeAsSystem),
|
|
1527
1529
|
},
|
|
1528
1530
|
},
|
|
1529
1531
|
};
|
|
@@ -1567,6 +1569,91 @@ export function appReducer(state, action) {
|
|
|
1567
1569
|
saving: false,
|
|
1568
1570
|
error: null,
|
|
1569
1571
|
lastSavedAt: Date.now(),
|
|
1572
|
+
storeAsSystem: Boolean(state.admin.ghcpKey.storeAsSystem),
|
|
1573
|
+
},
|
|
1574
|
+
},
|
|
1575
|
+
};
|
|
1576
|
+
}
|
|
1577
|
+
case "admin/ghcpKey/setSystemTarget": {
|
|
1578
|
+
const storeAsSystem = Boolean(action.value);
|
|
1579
|
+
if (Boolean(state.admin.ghcpKey.storeAsSystem) === storeAsSystem) return state;
|
|
1580
|
+
return {
|
|
1581
|
+
...state,
|
|
1582
|
+
admin: {
|
|
1583
|
+
...state.admin,
|
|
1584
|
+
ghcpKey: {
|
|
1585
|
+
...state.admin.ghcpKey,
|
|
1586
|
+
storeAsSystem,
|
|
1587
|
+
error: null,
|
|
1588
|
+
},
|
|
1589
|
+
},
|
|
1590
|
+
};
|
|
1591
|
+
}
|
|
1592
|
+
case "admin/systemGhcpKey/loading": {
|
|
1593
|
+
return {
|
|
1594
|
+
...state,
|
|
1595
|
+
admin: {
|
|
1596
|
+
...state.admin,
|
|
1597
|
+
systemGhcpKey: {
|
|
1598
|
+
...state.admin.systemGhcpKey,
|
|
1599
|
+
loading: true,
|
|
1600
|
+
error: null,
|
|
1601
|
+
},
|
|
1602
|
+
},
|
|
1603
|
+
};
|
|
1604
|
+
}
|
|
1605
|
+
case "admin/systemGhcpKey/loaded": {
|
|
1606
|
+
const status = action.status || {};
|
|
1607
|
+
return {
|
|
1608
|
+
...state,
|
|
1609
|
+
admin: {
|
|
1610
|
+
...state.admin,
|
|
1611
|
+
systemGhcpKey: {
|
|
1612
|
+
supported: true,
|
|
1613
|
+
loading: false,
|
|
1614
|
+
configured: Boolean(status.configured),
|
|
1615
|
+
changedBy: status.changedBy || null,
|
|
1616
|
+
changedAt: status.changedAt || null,
|
|
1617
|
+
error: null,
|
|
1618
|
+
},
|
|
1619
|
+
},
|
|
1620
|
+
};
|
|
1621
|
+
}
|
|
1622
|
+
case "admin/systemGhcpKey/loadFailed": {
|
|
1623
|
+
return {
|
|
1624
|
+
...state,
|
|
1625
|
+
admin: {
|
|
1626
|
+
...state.admin,
|
|
1627
|
+
systemGhcpKey: {
|
|
1628
|
+
...state.admin.systemGhcpKey,
|
|
1629
|
+
loading: false,
|
|
1630
|
+
error: action.error ? String(action.error) : "Failed to load System key status",
|
|
1631
|
+
},
|
|
1632
|
+
},
|
|
1633
|
+
};
|
|
1634
|
+
}
|
|
1635
|
+
case "admin/systemGhcpKey/saved": {
|
|
1636
|
+
const status = action.status || {};
|
|
1637
|
+
return {
|
|
1638
|
+
...state,
|
|
1639
|
+
admin: {
|
|
1640
|
+
...state.admin,
|
|
1641
|
+
ghcpKey: {
|
|
1642
|
+
editing: false,
|
|
1643
|
+
draft: "",
|
|
1644
|
+
cursorIndex: 0,
|
|
1645
|
+
saving: false,
|
|
1646
|
+
error: null,
|
|
1647
|
+
lastSavedAt: Date.now(),
|
|
1648
|
+
storeAsSystem: Boolean(state.admin.ghcpKey.storeAsSystem),
|
|
1649
|
+
},
|
|
1650
|
+
systemGhcpKey: {
|
|
1651
|
+
supported: true,
|
|
1652
|
+
loading: false,
|
|
1653
|
+
configured: Boolean(status.configured),
|
|
1654
|
+
changedBy: status.changedBy || null,
|
|
1655
|
+
changedAt: status.changedAt || null,
|
|
1656
|
+
error: null,
|
|
1570
1657
|
},
|
|
1571
1658
|
},
|
|
1572
1659
|
};
|