pilotswarm 0.5.44 → 0.5.47
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/README.md +12 -0
- package/mcp/dist/src/context.d.ts.map +1 -1
- package/mcp/dist/src/context.js +9 -1
- package/mcp/dist/src/context.js.map +1 -1
- package/mcp/dist/src/tools/agent-packages.d.ts.map +1 -1
- package/mcp/dist/src/tools/agent-packages.js +31 -0
- package/mcp/dist/src/tools/agent-packages.js.map +1 -1
- package/mcp/dist/src/tools/providers.d.ts.map +1 -1
- package/mcp/dist/src/tools/providers.js +15 -3
- package/mcp/dist/src/tools/providers.js.map +1 -1
- package/mcp/dist/src/util/respond.d.ts.map +1 -1
- package/mcp/dist/src/util/respond.js +6 -0
- package/mcp/dist/src/util/respond.js.map +1 -1
- package/package.json +2 -2
- package/tui/src/agents-cli.js +35 -0
- package/tui/src/app.js +7 -11
- package/tui/src/node-sdk-transport.js +70 -0
- package/ui/core/src/controller.js +313 -74
- package/ui/core/src/history.js +65 -10
- package/ui/core/src/reducer.js +51 -4
- package/ui/core/src/selectors.js +101 -20
- package/ui/core/src/state.js +11 -0
- package/ui/react/src/components.js +1 -0
- package/ui/react/src/web-app.js +938 -127
- package/web/api/canvas-plane.js +18 -6
- package/web/api/ws.js +22 -2
- package/web/auth/index.js +8 -1
- package/web/auth/normalize/entra.js +5 -1
- package/web/dist/assets/{abnfDiagram-VRR7QNED-67Q0WWge.js → abnfDiagram-VRR7QNED-VPL8m_9W.js} +1 -1
- package/web/dist/assets/{arc-BvcYFngS.js → arc-T5I3-c1B.js} +1 -1
- package/web/dist/assets/{architectureDiagram-ZJ3FMSHR-CPBN0rk8.js → architectureDiagram-ZJ3FMSHR-DEP70bg6.js} +1 -1
- package/web/dist/assets/{blockDiagram-677ZJIJ3-D_hp1Oah.js → blockDiagram-677ZJIJ3-CvBu1MbO.js} +1 -1
- package/web/dist/assets/{c4Diagram-LMCZKHZV-DAOVGMIW.js → c4Diagram-LMCZKHZV-B5qwF4gm.js} +1 -1
- package/web/dist/assets/channel-D5LojeMw.js +1 -0
- package/web/dist/assets/{chunk-2Q5K7J3B-DajZuaot.js → chunk-2Q5K7J3B-zVW8dS7X.js} +1 -1
- package/web/dist/assets/{chunk-32BRIVSS-C6pXBsgt.js → chunk-32BRIVSS-DWctxZZS.js} +1 -1
- package/web/dist/assets/{chunk-5VM5RSS4-780edrmi.js → chunk-5VM5RSS4-Bq7_Vmf9.js} +1 -1
- package/web/dist/assets/{chunk-EX3LRPZG-C0e4NVuz.js → chunk-EX3LRPZG-B8CFB3v-.js} +1 -1
- package/web/dist/assets/{chunk-JWPE2WC7-uRe83I6C.js → chunk-JWPE2WC7-B7gLPjgZ.js} +1 -1
- package/web/dist/assets/{chunk-MOJQB5TN-B0WPoPjh.js → chunk-MOJQB5TN-B2x6q12r.js} +1 -1
- package/web/dist/assets/{chunk-RYQCIY6F-eRFuHHyG.js → chunk-RYQCIY6F-XorU9Stx.js} +1 -1
- package/web/dist/assets/{chunk-V7JOEXUC-C8FDXprk.js → chunk-V7JOEXUC-CsLa6pw5.js} +1 -1
- package/web/dist/assets/{chunk-VR4S4FIN-DPFpLQdB.js → chunk-VR4S4FIN-BBv9mwmj.js} +1 -1
- package/web/dist/assets/{chunk-XXDRQBXY-CoGQOPKW.js → chunk-XXDRQBXY-Cjm4mm6l.js} +1 -1
- package/web/dist/assets/classDiagram-OUVF2IWQ-C5edc5Or.js +1 -0
- package/web/dist/assets/classDiagram-v2-EOCWNBFH-C5edc5Or.js +1 -0
- package/web/dist/assets/{cose-bilkent-JH36ORCC-BTBSfO5v.js → cose-bilkent-JH36ORCC-Zw9ZQbVl.js} +1 -1
- package/web/dist/assets/{cynefin-VYW2F7L2-DgTkQEoK.js → cynefin-VYW2F7L2-BYnR9YLM.js} +1 -1
- package/web/dist/assets/{cynefinDiagram-TSTJHNR4-DiBMlKoP.js → cynefinDiagram-TSTJHNR4-Cx8L0dOv.js} +1 -1
- package/web/dist/assets/{dagre-VKFMJZFB-Qv-4dcbk.js → dagre-VKFMJZFB-7GaqVcqz.js} +1 -1
- package/web/dist/assets/{diagram-FQU43EPY-CgyAb7yx.js → diagram-FQU43EPY-BWSRPJvU.js} +1 -1
- package/web/dist/assets/{diagram-G47NLZAW-BxN-KcGp.js → diagram-G47NLZAW-BELuAE1e.js} +1 -1
- package/web/dist/assets/{diagram-NH7WQ7WH-BiellpWz.js → diagram-NH7WQ7WH-DGXhPpri.js} +1 -1
- package/web/dist/assets/{diagram-OA4YK3LP-C8Ktgrwv.js → diagram-OA4YK3LP-DV8HqN0T.js} +1 -1
- package/web/dist/assets/{diagram-WEI45ONY-Bj5K1X91.js → diagram-WEI45ONY-Clv1X3ZL.js} +1 -1
- package/web/dist/assets/{ebnfDiagram-CCIWWBDH-DNQI2XT9.js → ebnfDiagram-CCIWWBDH-TpQx36oi.js} +1 -1
- package/web/dist/assets/{erDiagram-Q63AITRT-D5Xkllu6.js → erDiagram-Q63AITRT-DVVWd00c.js} +1 -1
- package/web/dist/assets/{flowDiagram-23GEKE2U-DJpTtMuj.js → flowDiagram-23GEKE2U-Cdz_8_Dw.js} +1 -1
- package/web/dist/assets/{ganttDiagram-NO4QXBWP-C-EQlCJf.js → ganttDiagram-NO4QXBWP-zlco-o7u.js} +1 -1
- package/web/dist/assets/{gitGraphDiagram-IHSO6WYX-C8vpSbvW.js → gitGraphDiagram-IHSO6WYX-CfAZW1En.js} +1 -1
- package/web/dist/assets/index-CMtzFJre.css +1 -0
- package/web/dist/assets/index-tQXCQojP.js +24 -0
- package/web/dist/assets/{infoDiagram-FWYZ7A6U-CKNzsR3r.js → infoDiagram-FWYZ7A6U-0R-8efwI.js} +1 -1
- package/web/dist/assets/{ishikawaDiagram-FXEZZL3T-CjyQq3lf.js → ishikawaDiagram-FXEZZL3T-lPpoXGlp.js} +1 -1
- package/web/dist/assets/{journeyDiagram-5HDEW3XC-CK3EEkJt.js → journeyDiagram-5HDEW3XC-D05vSVqu.js} +1 -1
- package/web/dist/assets/{kanban-definition-HUTT4EX6-CHQ8YkPx.js → kanban-definition-HUTT4EX6-ClaDdESv.js} +1 -1
- package/web/dist/assets/{linear-CUYirs1h.js → linear-CUnhHMvY.js} +1 -1
- package/web/dist/assets/{mermaid.core-Di8sQC4g.js → mermaid.core-DaYS-X8Y.js} +4 -4
- package/web/dist/assets/{mindmap-definition-LN4V7U3C-D38dmHP5.js → mindmap-definition-LN4V7U3C-N480VHds.js} +1 -1
- package/web/dist/assets/{papaparse.min-DWBU_pXS.js → papaparse.min-CNTcNgd8.js} +1 -1
- package/web/dist/assets/{pegDiagram-2B236MQR-BU759QCo.js → pegDiagram-2B236MQR-CVWyJ5ck.js} +1 -1
- package/web/dist/assets/{pieDiagram-ENE6RG2P-BbpfHbsj.js → pieDiagram-ENE6RG2P-UR9uohPf.js} +1 -1
- package/web/dist/assets/pilotswarm-BG6hk0oE.js +97 -0
- package/web/dist/assets/{quadrantDiagram-ABIIQ3AL-BYZ3XHZn.js → quadrantDiagram-ABIIQ3AL-D2SIOetn.js} +1 -1
- package/web/dist/assets/{railroadDiagram-RFXS5EU6-D18gkZBJ.js → railroadDiagram-RFXS5EU6-OgN6qgOU.js} +1 -1
- package/web/dist/assets/{requirementDiagram-TGXJPOKE-D6vo26Ib.js → requirementDiagram-TGXJPOKE-BSUURBBz.js} +1 -1
- package/web/dist/assets/{sankeyDiagram-HTMAVEWB-CxQwXnRE.js → sankeyDiagram-HTMAVEWB-BBZhmSBZ.js} +1 -1
- package/web/dist/assets/{sequenceDiagram-DBY2YBRQ-CfGisw4A.js → sequenceDiagram-DBY2YBRQ-C10IDNdW.js} +1 -1
- package/web/dist/assets/{sizeCapture-X5ZJPWSS-BDK7-yA-.js → sizeCapture-X5ZJPWSS-B9787MHa.js} +1 -1
- package/web/dist/assets/{stateDiagram-2N3HPSRC-8IyidYSV.js → stateDiagram-2N3HPSRC-BmSBo7es.js} +1 -1
- package/web/dist/assets/stateDiagram-v2-6OUMAXLB-BqpsfoJI.js +1 -0
- package/web/dist/assets/{swimlanes-5IMT3BWC-CgNqXCvM.js → swimlanes-5IMT3BWC-DOXpv_KQ.js} +2 -2
- package/web/dist/assets/swimlanesDiagram-G3AALYLV-k8WG_bWt.js +8 -0
- package/web/dist/assets/{timeline-definition-FHXFAJF6-DAJsGj6d.js → timeline-definition-FHXFAJF6-SjhGfPdI.js} +1 -1
- package/web/dist/assets/{vennDiagram-L72KCM5P-DDVdvG5k.js → vennDiagram-L72KCM5P-BiujYen6.js} +1 -1
- package/web/dist/assets/{wardleyDiagram-EHGQE667-CiAs_m72.js → wardleyDiagram-EHGQE667-6nLXBvwc.js} +1 -1
- package/web/dist/assets/{xychartDiagram-FW5EYKEG-D6OLJtsD.js → xychartDiagram-FW5EYKEG-Di7ioTvW.js} +1 -1
- package/web/dist/index.html +3 -3
- package/web/runtime.js +192 -6
- package/web/server.js +22 -0
- package/web/dist/assets/channel-DiW7lUT8.js +0 -1
- package/web/dist/assets/classDiagram-OUVF2IWQ-CpAhBd5x.js +0 -1
- package/web/dist/assets/classDiagram-v2-EOCWNBFH-CpAhBd5x.js +0 -1
- package/web/dist/assets/index-C2ioXNJJ.js +0 -24
- package/web/dist/assets/index-CVYm02UI.css +0 -1
- package/web/dist/assets/pilotswarm-DrM3pXOV.js +0 -97
- package/web/dist/assets/stateDiagram-v2-6OUMAXLB-F7qYkvpr.js +0 -1
- package/web/dist/assets/swimlanesDiagram-G3AALYLV-CUKrHLkY.js +0 -8
package/ui/core/src/reducer.js
CHANGED
|
@@ -832,6 +832,17 @@ export function appReducer(state, action) {
|
|
|
832
832
|
if (Boolean(action.enabled) === Boolean(state.ui.touchScale)) return state;
|
|
833
833
|
return { ...state, ui: { ...state.ui, touchScale: Boolean(action.enabled) } };
|
|
834
834
|
|
|
835
|
+
case "ui/agentPickerUsage": {
|
|
836
|
+
const usage = action.usage && typeof action.usage === "object" && !Array.isArray(action.usage)
|
|
837
|
+
? action.usage
|
|
838
|
+
: {};
|
|
839
|
+
return { ...state, ui: { ...state.ui, agentPickerUsage: usage } };
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
case "ui/sessionDetailCollapsed":
|
|
843
|
+
if (Boolean(action.collapsed) === Boolean(state.ui.sessionDetailCollapsed)) return state;
|
|
844
|
+
return { ...state, ui: { ...state.ui, sessionDetailCollapsed: Boolean(action.collapsed) } };
|
|
845
|
+
|
|
835
846
|
case "profileSettings/apply": {
|
|
836
847
|
const settings = action.settings && typeof action.settings === "object" && !Array.isArray(action.settings)
|
|
837
848
|
? action.settings
|
|
@@ -845,6 +856,11 @@ export function appReducer(state, action) {
|
|
|
845
856
|
// say "rich" fall through to the transcript below.
|
|
846
857
|
const hasTouchScale = Object.prototype.hasOwnProperty.call(settings, "touchScale")
|
|
847
858
|
&& typeof settings.touchScale === "boolean";
|
|
859
|
+
const hasSessionDetailCollapsed = Object.prototype.hasOwnProperty.call(settings, "sessionDetailCollapsed")
|
|
860
|
+
&& typeof settings.sessionDetailCollapsed === "boolean";
|
|
861
|
+
const hasAgentPickerUsage = Object.prototype.hasOwnProperty.call(settings, "agentPickerUsage")
|
|
862
|
+
&& settings.agentPickerUsage && typeof settings.agentPickerUsage === "object"
|
|
863
|
+
&& !Array.isArray(settings.agentPickerUsage);
|
|
848
864
|
const hasRightPaneMode = Object.prototype.hasOwnProperty.call(settings, "rightPaneMode")
|
|
849
865
|
&& (settings.rightPaneMode === "canvas" || settings.rightPaneMode === "panes");
|
|
850
866
|
// The two independent columns. A profile written by a build that
|
|
@@ -921,6 +937,12 @@ export function appReducer(state, action) {
|
|
|
921
937
|
...selection.ui,
|
|
922
938
|
themeId: hasTheme ? settings.themeId.trim() : selection.ui.themeId,
|
|
923
939
|
touchScale: hasTouchScale ? settings.touchScale : selection.ui.touchScale,
|
|
940
|
+
sessionDetailCollapsed: hasSessionDetailCollapsed
|
|
941
|
+
? settings.sessionDetailCollapsed
|
|
942
|
+
: selection.ui.sessionDetailCollapsed,
|
|
943
|
+
agentPickerUsage: hasAgentPickerUsage
|
|
944
|
+
? settings.agentPickerUsage
|
|
945
|
+
: selection.ui.agentPickerUsage,
|
|
924
946
|
rightPaneMode: hasRightPaneMode ? settings.rightPaneMode : selection.ui.rightPaneMode,
|
|
925
947
|
...(nextDesktopPanes
|
|
926
948
|
? { canvasOpen: nextDesktopPanes.canvasOpen, diagnosticsOpen: nextDesktopPanes.diagnosticsOpen, canvasZen: nextDesktopPanes.zen === true }
|
|
@@ -2458,6 +2480,29 @@ export function appReducer(state, action) {
|
|
|
2458
2480
|
},
|
|
2459
2481
|
};
|
|
2460
2482
|
}
|
|
2483
|
+
/**
|
|
2484
|
+
* Put the banner down.
|
|
2485
|
+
*
|
|
2486
|
+
* A failed mutation writes mutation.error, which the Model Providers
|
|
2487
|
+
* pane renders as a red band. Nothing cleared it except the NEXT
|
|
2488
|
+
* mutation, so cancelling a failed sheet left the band sitting there
|
|
2489
|
+
* over an unchanged list, and it survived until something else
|
|
2490
|
+
* succeeded. The sheet that raised it owns it; when that sheet goes,
|
|
2491
|
+
* so does this.
|
|
2492
|
+
*/
|
|
2493
|
+
case "admin/modelProviders/mutationDismissed": {
|
|
2494
|
+
if (!state.admin?.modelProviders?.mutation?.error) return state;
|
|
2495
|
+
return {
|
|
2496
|
+
...state,
|
|
2497
|
+
admin: {
|
|
2498
|
+
...state.admin,
|
|
2499
|
+
modelProviders: {
|
|
2500
|
+
...state.admin.modelProviders,
|
|
2501
|
+
mutation: { ...state.admin.modelProviders.mutation, error: null },
|
|
2502
|
+
},
|
|
2503
|
+
},
|
|
2504
|
+
};
|
|
2505
|
+
}
|
|
2461
2506
|
case "admin/modelProviders/select": {
|
|
2462
2507
|
return {
|
|
2463
2508
|
...state,
|
|
@@ -2495,6 +2540,7 @@ export function appReducer(state, action) {
|
|
|
2495
2540
|
}
|
|
2496
2541
|
case "admin/modelProviders/createBegin": {
|
|
2497
2542
|
const draft = String(action.name || "");
|
|
2543
|
+
const update = action.mode === "update";
|
|
2498
2544
|
return {
|
|
2499
2545
|
...state,
|
|
2500
2546
|
admin: {
|
|
@@ -2503,12 +2549,13 @@ export function appReducer(state, action) {
|
|
|
2503
2549
|
...state.admin.modelProviders,
|
|
2504
2550
|
create: {
|
|
2505
2551
|
editing: true,
|
|
2506
|
-
|
|
2507
|
-
|
|
2552
|
+
mode: update ? "update" : "create",
|
|
2553
|
+
stage: update || action.stage === "credential" ? "credential" : "name",
|
|
2554
|
+
name: update ? draft : "",
|
|
2508
2555
|
typeId: String(action.typeId || ""),
|
|
2509
2556
|
shared: action.shared === true,
|
|
2510
|
-
draft,
|
|
2511
|
-
cursorIndex: draft.length,
|
|
2557
|
+
draft: update ? "" : draft,
|
|
2558
|
+
cursorIndex: update ? 0 : draft.length,
|
|
2512
2559
|
saving: false,
|
|
2513
2560
|
error: null,
|
|
2514
2561
|
},
|
package/ui/core/src/selectors.js
CHANGED
|
@@ -1812,6 +1812,21 @@ function prefixRuns(text, color = "gray", options = {}) {
|
|
|
1812
1812
|
// (block) chat renderer can consume the same labeling rules without the
|
|
1813
1813
|
// terminal run/prefix shape. Returns { time, glyph, glyphColor, roleLabel,
|
|
1814
1814
|
// roleColor }.
|
|
1815
|
+
/**
|
|
1816
|
+
* Is this the agent's own opening instruction rather than something a person
|
|
1817
|
+
* sent? The kickoff goes onto the queue as a user-role prompt — that is how a
|
|
1818
|
+
* turn starts — but it is stamped with a SYSTEM sender at the origin
|
|
1819
|
+
* (client.ts, createAgentSession). Anything a person actually sends carries a
|
|
1820
|
+
* `kind: "user"` sender stamped from the validated auth context.
|
|
1821
|
+
*
|
|
1822
|
+
* Sessions created before the stamp existed have no sender on that message, so
|
|
1823
|
+
* their kickoff still reads as "You". Nothing can distinguish it after the
|
|
1824
|
+
* fact; only new sessions are correct.
|
|
1825
|
+
*/
|
|
1826
|
+
export function isAgentKickoffMessage(message) {
|
|
1827
|
+
return message?.role === "user" && message?.sender?.kind === "system";
|
|
1828
|
+
}
|
|
1829
|
+
|
|
1815
1830
|
function describeChatMessageHeader(message, options = {}) {
|
|
1816
1831
|
const time = formatTimestamp(message?.createdAt || message?.time);
|
|
1817
1832
|
// A user.message is labeled from the CURRENT VIEWER's perspective: "You"
|
|
@@ -1837,7 +1852,12 @@ function describeChatMessageHeader(message, options = {}) {
|
|
|
1837
1852
|
);
|
|
1838
1853
|
const ownerSuffix = senderIsOwner ? " (owner)" : "";
|
|
1839
1854
|
|
|
1840
|
-
const roleLabel =
|
|
1855
|
+
const roleLabel = isAgentKickoffMessage(message)
|
|
1856
|
+
// Belt and braces: the chat pane collapses a kickoff before it reaches
|
|
1857
|
+
// here, but the TUI and any other renderer share this labeling, and
|
|
1858
|
+
// "You" is the one label this message must never carry.
|
|
1859
|
+
? (sender?.display || "System")
|
|
1860
|
+
: isUser
|
|
1841
1861
|
? ((fromOtherPerson ? (sender.display || sender.subject || "User") : "You") + ownerSuffix)
|
|
1842
1862
|
: message?.role === "assistant"
|
|
1843
1863
|
? "Agent"
|
|
@@ -2440,6 +2460,22 @@ function buildChatMessageLines(message, maxWidth, options = {}) {
|
|
|
2440
2460
|
}
|
|
2441
2461
|
}
|
|
2442
2462
|
|
|
2463
|
+
// An agent's opening instruction is plumbing, not conversation. It rides
|
|
2464
|
+
// the queue as a user-role prompt (that is how a turn starts), so without
|
|
2465
|
+
// this it rendered as a full chat message attributed to "You" — the
|
|
2466
|
+
// reader's own transcript opening with a wall of instructions they never
|
|
2467
|
+
// wrote. Collapsed to one line, openable, same affordance as a sub-agent
|
|
2468
|
+
// response.
|
|
2469
|
+
if (isAgentKickoffMessage(message)) {
|
|
2470
|
+
return [buildSystemNoticeLine({
|
|
2471
|
+
title: message?.sender?.display || "Agent kickoff",
|
|
2472
|
+
summary: "opening instruction",
|
|
2473
|
+
timestamp: formatTimestamp(message?.createdAt || message?.time),
|
|
2474
|
+
body: message?.text || "",
|
|
2475
|
+
color: "gray",
|
|
2476
|
+
})];
|
|
2477
|
+
}
|
|
2478
|
+
|
|
2443
2479
|
if (message?.role !== "user" && message?.role !== "assistant") {
|
|
2444
2480
|
const strippedSystemText = stripLeadingRehydrationNoticeText(message?.text || "");
|
|
2445
2481
|
if (message?.role === "system" && !strippedSystemText) {
|
|
@@ -2950,16 +2986,28 @@ export function selectCanvasView(state) {
|
|
|
2950
2986
|
}
|
|
2951
2987
|
|
|
2952
2988
|
/**
|
|
2953
|
-
* A validated canvas response on its way to the agent. Flagged
|
|
2954
|
-
*
|
|
2955
|
-
*
|
|
2956
|
-
*
|
|
2989
|
+
* A validated canvas response on its way to the agent. Flagged `canvasAction`
|
|
2990
|
+
* so each host renders it its own way: the TUI prints the compact dim line
|
|
2991
|
+
* below, while the portal collapses it to a single row that opens to show the
|
|
2992
|
+
* payload. Both need the same facts, so the action name and the full payload
|
|
2993
|
+
* ride on the line rather than only inside the truncated runs.
|
|
2957
2994
|
*/
|
|
2958
2995
|
function buildCanvasActionLine(message) {
|
|
2959
2996
|
const dataKeys = message?.data && typeof message.data === "object" ? Object.keys(message.data) : [];
|
|
2960
2997
|
const detail = dataKeys.length === 1 && typeof message.data[dataKeys[0]] === "string"
|
|
2961
2998
|
? message.data[dataKeys[0]].slice(0, 120)
|
|
2962
2999
|
: (dataKeys.length ? JSON.stringify(message.data).slice(0, 120) : "");
|
|
3000
|
+
let payload = "";
|
|
3001
|
+
if (dataKeys.length) {
|
|
3002
|
+
// A page can post anything that survives structured clone; JSON.stringify
|
|
3003
|
+
// throws on a cycle or a BigInt, and this runs inside the transcript
|
|
3004
|
+
// render path where a throw blanks the whole conversation.
|
|
3005
|
+
try {
|
|
3006
|
+
payload = JSON.stringify(message.data, null, 2);
|
|
3007
|
+
} catch {
|
|
3008
|
+
payload = "";
|
|
3009
|
+
}
|
|
3010
|
+
}
|
|
2963
3011
|
return {
|
|
2964
3012
|
runs: [
|
|
2965
3013
|
{ text: "[canvas] ", color: "cyan", bold: true },
|
|
@@ -2967,6 +3015,10 @@ function buildCanvasActionLine(message) {
|
|
|
2967
3015
|
...(detail ? [{ text: ` — ${detail}`, color: "gray" }] : []),
|
|
2968
3016
|
],
|
|
2969
3017
|
canvasAction: true,
|
|
3018
|
+
canvasActionName: message?.action || "action",
|
|
3019
|
+
canvasActionDetail: detail,
|
|
3020
|
+
canvasActionPayload: payload,
|
|
3021
|
+
canvasActionTime: message?.time || "",
|
|
2970
3022
|
};
|
|
2971
3023
|
}
|
|
2972
3024
|
|
|
@@ -4005,6 +4057,11 @@ export function selectAdminConsole(state) {
|
|
|
4005
4057
|
&& pkg.owner.provider === principal.provider
|
|
4006
4058
|
&& pkg.owner.subject === principal.subject),
|
|
4007
4059
|
);
|
|
4060
|
+
// Editor-level: may change contents and rollout (publish, pin,
|
|
4061
|
+
// enable/disable). The server computes `canEdit` per viewer (admin, owner
|
|
4062
|
+
// or a granted editor); ownsPackage stays the owner-only gate for scope,
|
|
4063
|
+
// delete and the editor list.
|
|
4064
|
+
const canEditPackage = (pkg) => ownsPackage(pkg) || Boolean(pkg?.canEdit);
|
|
4008
4065
|
// Built once per render, not per row.
|
|
4009
4066
|
const ownerDirectory = ownerDirectoryFromSessions(state?.sessions?.byId);
|
|
4010
4067
|
// Same rule as the session list: the owner chip only earns its place when
|
|
@@ -4046,7 +4103,7 @@ export function selectAdminConsole(state) {
|
|
|
4046
4103
|
semver: pkg.active?.semver || null,
|
|
4047
4104
|
sha7: pkg.active?.sha256 ? String(pkg.active.sha256).slice(0, 7) : null,
|
|
4048
4105
|
agentCount: Array.isArray(pkg.active?.manifest?.agents) ? pkg.active.manifest.agents.length : 0,
|
|
4049
|
-
canManage:
|
|
4106
|
+
canManage: canEditPackage(pkg),
|
|
4050
4107
|
// A user-scope package belongs to a PERSON, so it carries the same
|
|
4051
4108
|
// owner-initials chip the session rows use. Shared packages belong to
|
|
4052
4109
|
// the deployment and keep the scope badge instead.
|
|
@@ -4157,13 +4214,25 @@ export function selectAdminConsole(state) {
|
|
|
4157
4214
|
&& installedRowFor(worker)?.status === "ok").length
|
|
4158
4215
|
: 0;
|
|
4159
4216
|
const canManage = detail ? ownsPackage(detail) : (summary ? ownsPackage(summary) : false);
|
|
4217
|
+
const canEdit = detail ? canEditPackage(detail) : (summary ? canEditPackage(summary) : false);
|
|
4160
4218
|
packageDetail = {
|
|
4161
4219
|
name: pkgState.selectedName,
|
|
4162
4220
|
loading: Boolean(pkgState.detailLoading),
|
|
4163
4221
|
error: pkgState.detailError || null,
|
|
4164
4222
|
scope: (detail?.scope || summary?.scope) === "shared" ? "shared" : "user",
|
|
4165
4223
|
enabled: detail ? Boolean(detail.enabled) : Boolean(summary?.enabled),
|
|
4224
|
+
// canManage = owner/admin (scope, delete, editors);
|
|
4225
|
+
// canEdit = canManage OR granted editor (publish, pin, enable).
|
|
4166
4226
|
canManage,
|
|
4227
|
+
canEdit,
|
|
4228
|
+
editors: Array.isArray(detail?.editors)
|
|
4229
|
+
? detail.editors.map((e) => ({
|
|
4230
|
+
provider: e.provider,
|
|
4231
|
+
subject: e.subject,
|
|
4232
|
+
label: e.displayName || e.email || e.subject,
|
|
4233
|
+
grantedByDisplay: e.grantedByDisplay || null,
|
|
4234
|
+
}))
|
|
4235
|
+
: [],
|
|
4167
4236
|
createdBy: detail?.createdBy || summary?.createdBy || null,
|
|
4168
4237
|
createdAtText: adminPkgDate(detail?.createdAt || summary?.createdAt),
|
|
4169
4238
|
description: typeof manifest.description === "string" ? manifest.description : "",
|
|
@@ -4605,6 +4674,7 @@ export function selectAdminProviderCreateModal(state, maxWidth = 76) {
|
|
|
4605
4674
|
const create = admin.modelProviders?.create || {};
|
|
4606
4675
|
if (!admin.visible || !create.editing) return null;
|
|
4607
4676
|
const credentialStage = create.stage === "credential";
|
|
4677
|
+
const updating = create.mode === "update";
|
|
4608
4678
|
const shared = create.shared === true;
|
|
4609
4679
|
const ownTitle = /github/i.test(create.typeId || "")
|
|
4610
4680
|
? "Add GitHub Copilot provider"
|
|
@@ -4612,7 +4682,9 @@ export function selectAdminProviderCreateModal(state, maxWidth = 76) {
|
|
|
4612
4682
|
const value = String(create.draft || "");
|
|
4613
4683
|
return {
|
|
4614
4684
|
type: "adminProviderCreate",
|
|
4615
|
-
title:
|
|
4685
|
+
title: updating
|
|
4686
|
+
? `Update key for ${create.name}`
|
|
4687
|
+
: credentialStage
|
|
4616
4688
|
? (shared ? "Add shared model provider" : ownTitle)
|
|
4617
4689
|
: (shared ? "Name the shared provider" : ownTitle),
|
|
4618
4690
|
label: credentialStage ? "credential" : "provider name",
|
|
@@ -4634,7 +4706,7 @@ export function selectAdminProviderCreateModal(state, maxWidth = 76) {
|
|
|
4634
4706
|
{ text: "Letters, numbers, dot, dash, and underscore only.", color: "gray" },
|
|
4635
4707
|
],
|
|
4636
4708
|
helpLines: credentialStage
|
|
4637
|
-
? ["Type/paste credential",
|
|
4709
|
+
? ["Type/paste credential", `Enter ${updating ? "update key" : "create provider"}`, "Esc cancel and clear"]
|
|
4638
4710
|
: ["Type provider name", "Tab next provider type", "Enter continue to credential", "Esc cancel"],
|
|
4639
4711
|
};
|
|
4640
4712
|
}
|
|
@@ -5194,16 +5266,17 @@ export function selectStatusBar(state) {
|
|
|
5194
5266
|
}
|
|
5195
5267
|
if (state.ui.modal?.type === "themePicker") {
|
|
5196
5268
|
return {
|
|
5197
|
-
left: "Select a
|
|
5269
|
+
left: "Select a theme",
|
|
5198
5270
|
right: "up/down move · enter apply · esc close",
|
|
5199
5271
|
};
|
|
5200
5272
|
}
|
|
5201
5273
|
if (state.ui.modal?.type === "sessionAgentPicker") {
|
|
5202
5274
|
return {
|
|
5203
5275
|
left: "Select an agent for the new session",
|
|
5204
|
-
//
|
|
5205
|
-
//
|
|
5206
|
-
|
|
5276
|
+
// Every row is an agent now, so Enter always starts one. The
|
|
5277
|
+
// arrows are no longer named because they no longer do anything
|
|
5278
|
+
// here — they belong to the search box, where they move the caret.
|
|
5279
|
+
right: "type to search · up/down move · enter start · esc cancel",
|
|
5207
5280
|
};
|
|
5208
5281
|
}
|
|
5209
5282
|
if (state.ui.modal?.type === "sessionGroupPicker") {
|
|
@@ -6470,15 +6543,23 @@ export function selectSessionAgentPickerModal(state, maxWidth = 76) {
|
|
|
6470
6543
|
], contentWidth);
|
|
6471
6544
|
} else {
|
|
6472
6545
|
const callable = item?.kind === "generic" || item?.supportsDirectStart !== false;
|
|
6473
|
-
//
|
|
6474
|
-
//
|
|
6475
|
-
//
|
|
6476
|
-
//
|
|
6477
|
-
|
|
6478
|
-
const
|
|
6546
|
+
// ONE LINE PER AGENT. The package is trailing metadata rather than a
|
|
6547
|
+
// row of its own, so the list is as long as the number of agents —
|
|
6548
|
+
// the grouped shape spent a second row on every single-agent package
|
|
6549
|
+
// saying the same thing twice.
|
|
6550
|
+
const glyph = item?.kind === "generic" ? "○ " : "★ ";
|
|
6551
|
+
const name = item?.title || item?.agentName || item?.id || "Agent";
|
|
6552
|
+
const pkg = item?.kind === "generic" ? "" : (item?.packageTitle || item?.packageName || "");
|
|
6553
|
+
// Only shown while sorting BY use, where the number is the sort key
|
|
6554
|
+
// and therefore explains the order. Everywhere else it is noise.
|
|
6555
|
+
const uses = modal.sort === "used" && Number(item?.usageCount) > 0
|
|
6556
|
+
? ` ${item.usageCount}×`
|
|
6557
|
+
: "";
|
|
6479
6558
|
labelRuns = fitRuns([
|
|
6480
6559
|
{ text: `${indent}${glyph}`, color: callable ? "yellow" : "gray" },
|
|
6481
|
-
{ text:
|
|
6560
|
+
{ text: name, color: callable ? "white" : "gray", bold: callable },
|
|
6561
|
+
...(pkg ? [{ text: ` ${pkg}`, color: "gray" }] : []),
|
|
6562
|
+
...(uses ? [{ text: uses, color: "cyan" }] : []),
|
|
6482
6563
|
], contentWidth);
|
|
6483
6564
|
}
|
|
6484
6565
|
|
|
@@ -8537,7 +8618,7 @@ export function selectThemePickerModal(state, maxWidth = 80) {
|
|
|
8537
8618
|
[{
|
|
8538
8619
|
text: previewingTheme
|
|
8539
8620
|
? `Previewing now. Cancel reverts to ${originalTheme?.label || "the previous theme"}.`
|
|
8540
|
-
: "Currently active
|
|
8621
|
+
: "Currently active.",
|
|
8541
8622
|
color: previewingTheme ? "yellow" : "green",
|
|
8542
8623
|
}],
|
|
8543
8624
|
buildThemeSwatchRuns([
|
package/ui/core/src/state.js
CHANGED
|
@@ -359,6 +359,17 @@ export function createInitialState({ mode = "local", branding = null, docs = nul
|
|
|
359
359
|
// portrait is not the only case — a wall display or a shared screen wants
|
|
360
360
|
// the same thing — so it is a preference, not a viewport query.
|
|
361
361
|
touchScale: false,
|
|
362
|
+
// The session detail box starts folded to its one-line summary. It
|
|
363
|
+
// is ten rows of reference detail against a list you are trying to
|
|
364
|
+
// read, and most of it is looked up once per session, not per
|
|
365
|
+
// glance. Expanding is one click and the choice persists.
|
|
366
|
+
sessionDetailCollapsed: true,
|
|
367
|
+
// Per-person agent start counts, {agentName: n}. Drives the
|
|
368
|
+
// picker's default "Most used" sort. State-owned so every writer
|
|
369
|
+
// of the profile document sees the same value at the same moment;
|
|
370
|
+
// a preserved ref refreshed by a 5s poll lost the count to the
|
|
371
|
+
// very next save.
|
|
372
|
+
agentPickerUsage: {},
|
|
362
373
|
modal: null,
|
|
363
374
|
fullscreenPane: null,
|
|
364
375
|
layout: {
|
|
@@ -2152,6 +2152,7 @@ function buildAdminModelProviderLines(view) {
|
|
|
2152
2152
|
if (providers.page !== "shared") {
|
|
2153
2153
|
lines.push([
|
|
2154
2154
|
{ text: " e ", color: "green", bold: true }, { text: "add ", color: "gray" },
|
|
2155
|
+
{ text: "U ", color: "yellow", bold: true }, { text: "update key ", color: "gray" },
|
|
2155
2156
|
{ text: "d ", color: "red", bold: true }, { text: "delete ", color: "gray" },
|
|
2156
2157
|
{ text: "u ", color: "cyan", bold: true }, { text: "my default ", color: "gray" },
|
|
2157
2158
|
...(view.isAdmin ? [{ text: "t ", color: "yellow", bold: true }, { text: "system use ", color: "gray" }] : []),
|