@blackbelt-technology/pi-agent-dashboard 0.5.2 → 0.5.4
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/AGENTS.md +19 -30
- package/README.md +69 -1
- package/docs/architecture.md +89 -165
- package/package.json +11 -7
- package/packages/extension/package.json +2 -2
- package/packages/extension/src/__tests__/bridge-default-model-gate.test.ts +47 -0
- package/packages/extension/src/__tests__/bridge-followup-chat-order.test.ts +215 -0
- package/packages/extension/src/__tests__/bridge-followup-multi-entry.test.ts +202 -0
- package/packages/extension/src/__tests__/bridge-queue-update-forward.test.ts +77 -0
- package/packages/extension/src/__tests__/bridge-retry-ordering.test.ts +148 -0
- package/packages/extension/src/__tests__/bridge-shadow-queue-drain.test.ts +221 -0
- package/packages/extension/src/__tests__/bridge-shadow-queue-gate.test.ts +299 -0
- package/packages/extension/src/__tests__/bridge-shutdown-reset.test.ts +238 -0
- package/packages/extension/src/__tests__/bridge-slash-command-routing.test.ts +127 -31
- package/packages/extension/src/__tests__/command-handler.test.ts +105 -3
- package/packages/extension/src/__tests__/fixtures/usage-limit-error-strings.ts +127 -0
- package/packages/extension/src/__tests__/source-detector.test.ts +15 -0
- package/packages/extension/src/__tests__/usage-limit-orderer.test.ts +12 -0
- package/packages/extension/src/bridge-default-model-gate.ts +32 -0
- package/packages/extension/src/bridge.ts +299 -20
- package/packages/extension/src/command-handler.ts +53 -7
- package/packages/extension/src/dashboard-default-adapter.ts +5 -0
- package/packages/extension/src/prompt-bus.ts +15 -0
- package/packages/extension/src/slash-dispatch.ts +30 -15
- package/packages/extension/src/source-detector.ts +13 -5
- package/packages/extension/src/usage-limit-orderer.ts +18 -1
- package/packages/server/bin/pi-dashboard.mjs +62 -14
- package/packages/server/package.json +9 -5
- package/packages/server/src/__tests__/browser-gateway-register-handler.test.ts +69 -0
- package/packages/server/src/__tests__/cli-env-no-clobber.test.ts +46 -0
- package/packages/server/src/__tests__/cli-no-bootstrap-references.test.ts +69 -0
- package/packages/server/src/__tests__/cli-parse.test.ts +9 -10
- package/packages/server/src/__tests__/cli-version.test.ts +151 -0
- package/packages/server/src/__tests__/directory-service-openspec-enabled.test.ts +9 -0
- package/packages/server/src/__tests__/directory-service-refresh-force.test.ts +9 -0
- package/packages/server/src/__tests__/directory-service-specs-mtime.test.ts +9 -0
- package/packages/server/src/__tests__/directory-service-toctou.test.ts +9 -0
- package/packages/server/src/__tests__/directory-service.test.ts +9 -0
- package/packages/server/src/__tests__/doctor-route.test.ts +53 -0
- package/packages/server/src/__tests__/event-wiring-queue-state.test.ts +156 -0
- package/packages/server/src/__tests__/event-wiring-resume-clear.test.ts +105 -0
- package/packages/server/src/__tests__/health-shape.test.ts +35 -12
- package/packages/server/src/__tests__/installed-package-enricher.test.ts +12 -12
- package/packages/server/src/__tests__/is-activity-event.test.ts +4 -7
- package/packages/server/src/__tests__/package-routes.test.ts +6 -2
- package/packages/server/src/__tests__/pi-changelog-routes.test.ts +10 -13
- package/packages/server/src/__tests__/pi-core-checker.test.ts +2 -2
- package/packages/server/src/__tests__/pi-version-skew.test.ts +3 -2
- package/packages/server/src/__tests__/plugin-activation-routes.test.ts +267 -0
- package/packages/server/src/__tests__/plugin-intent-cache.test.ts +75 -0
- package/packages/server/src/__tests__/preferences-store.test.ts +196 -0
- package/packages/server/src/__tests__/reattach-placement.test.ts +9 -0
- package/packages/server/src/__tests__/recommended-routes.test.ts +2 -2
- package/packages/server/src/__tests__/recovery-server.test.ts +203 -0
- package/packages/server/src/__tests__/session-action-handler-clear-queue.test.ts +153 -0
- package/packages/server/src/__tests__/session-action-handler-headless-reload.test.ts +43 -0
- package/packages/server/src/__tests__/session-order-manager.test.ts +9 -0
- package/packages/server/src/__tests__/session-order-reboot.test.ts +9 -0
- package/packages/server/src/__tests__/session-ordering-integration.test.ts +9 -0
- package/packages/server/src/browser-gateway.ts +83 -5
- package/packages/server/src/browser-handlers/directory-handler.ts +69 -0
- package/packages/server/src/browser-handlers/session-action-handler.ts +89 -0
- package/packages/server/src/browser-handlers/subscription-handler.ts +23 -0
- package/packages/server/src/changelog-parser.ts +1 -1
- package/packages/server/src/cli.ts +68 -250
- package/packages/server/src/event-status-extraction.ts +14 -62
- package/packages/server/src/event-wiring.ts +23 -10
- package/packages/server/src/memory-session-manager.ts +4 -0
- package/packages/server/src/pi-core-checker.ts +1 -1
- package/packages/server/src/pi-dev-version-check.ts +1 -1
- package/packages/server/src/pi-version-skew.ts +24 -46
- package/packages/server/src/plugin-intent-cache.ts +67 -0
- package/packages/server/src/preferences-store.ts +199 -13
- package/packages/server/src/recovery-server.ts +366 -0
- package/packages/server/src/routes/__tests__/manifest-route.test.ts +138 -0
- package/packages/server/src/routes/doctor-routes.ts +26 -21
- package/packages/server/src/routes/manifest-route.ts +162 -0
- package/packages/server/src/routes/openspec-routes.ts +4 -25
- package/packages/server/src/routes/pi-changelog-routes.ts +5 -24
- package/packages/server/src/routes/pi-core-routes.ts +3 -23
- package/packages/server/src/routes/plugin-activation-routes.ts +193 -0
- package/packages/server/src/routes/recommended-routes.ts +21 -0
- package/packages/server/src/routes/system-routes.ts +73 -11
- package/packages/server/src/server.ts +105 -307
- package/packages/server/src/session-api.ts +5 -63
- package/packages/shared/package.json +1 -1
- package/packages/shared/src/__tests__/binary-lookup-resolveJiti.test.ts +28 -0
- package/packages/shared/src/__tests__/binary-lookup-spawn-env.test.ts +61 -0
- package/packages/shared/src/__tests__/binary-lookup.test.ts +16 -0
- package/packages/shared/src/__tests__/bridge-register.test.ts +67 -0
- package/packages/shared/src/__tests__/ci-electron-no-side-effects.test.ts +129 -0
- package/packages/shared/src/__tests__/config.test.ts +40 -0
- package/packages/shared/src/__tests__/dashboard-paths.test.ts +81 -0
- package/packages/shared/src/__tests__/ensure-windows-path.test.ts +112 -0
- package/packages/shared/src/__tests__/intent-types.test.ts +120 -0
- package/packages/shared/src/__tests__/jiti-packages-parity.test.ts +85 -0
- package/packages/shared/src/__tests__/legacy-managed-dir.test.ts +59 -0
- package/packages/shared/src/__tests__/no-direct-child-process.test.ts +12 -0
- package/packages/shared/src/__tests__/no-electron-execpath-spawn.test.ts +149 -0
- package/packages/shared/src/__tests__/no-flow-command-route-claims.test.ts +71 -0
- package/packages/shared/src/__tests__/no-flow-references-in-shell.test.ts +221 -0
- package/packages/shared/src/__tests__/no-managed-dir-reference.test.ts +134 -0
- package/packages/shared/src/__tests__/no-pi-dashboard-version-jiti-gate.test.ts +41 -0
- package/packages/shared/src/__tests__/no-primitive-direct-import.test.ts +235 -0
- package/packages/shared/src/__tests__/no-server-imports-in-resolver.test.ts +53 -0
- package/packages/shared/src/__tests__/node-spawn-jiti-contract.test.ts +54 -101
- package/packages/shared/src/__tests__/node-spawn.test.ts +29 -13
- package/packages/shared/src/__tests__/pi-package-resolver.test.ts +300 -0
- package/packages/shared/src/__tests__/plugin-activation-contracts.test.ts +74 -0
- package/packages/shared/src/__tests__/plugin-bridge-classify-source.test.ts +73 -0
- package/packages/shared/src/__tests__/plugin-bridge-register-extended.test.ts +17 -5
- package/packages/shared/src/__tests__/plugin-bridge-register-packages.test.ts +233 -0
- package/packages/shared/src/__tests__/plugin-bridge-register.test.ts +19 -9
- package/packages/shared/src/__tests__/publish-workflow-contract.test.ts +154 -15
- package/packages/shared/src/__tests__/recommended-extensions.test.ts +28 -10
- package/packages/shared/src/__tests__/resolver-parity-with-scanner.test.ts +76 -0
- package/packages/shared/src/__tests__/server-identity.test.ts +127 -0
- package/packages/shared/src/__tests__/server-launcher.test.ts +35 -0
- package/packages/shared/src/__tests__/source-matching.test.ts +5 -5
- package/packages/shared/src/__tests__/sync-versions-spec.test.ts +76 -0
- package/packages/shared/src/__tests__/tool-registry-definitions.test.ts +50 -2
- package/packages/shared/src/bridge-register.ts +35 -2
- package/packages/shared/src/browser-protocol.ts +176 -2
- package/packages/shared/src/config.ts +12 -0
- package/packages/shared/src/dashboard-paths.ts +69 -0
- package/packages/shared/src/dashboard-plugin/index.ts +2 -0
- package/packages/shared/src/dashboard-plugin/intent-types.ts +93 -0
- package/packages/shared/src/dashboard-plugin/manifest-types.ts +55 -1
- package/packages/shared/src/dashboard-plugin/plugin-status.ts +82 -0
- package/packages/shared/src/dashboard-plugin/slot-props.ts +11 -0
- package/packages/shared/src/dashboard-plugin/slot-types.ts +16 -2
- package/packages/shared/src/dashboard-plugin/ui-primitives.ts +287 -0
- package/packages/shared/src/dashboard-starter.ts +22 -0
- package/packages/shared/src/doctor-core.ts +49 -27
- package/packages/shared/src/launch-source-types.ts +9 -9
- package/packages/shared/src/legacy-managed-dir.ts +97 -0
- package/packages/shared/src/mdns-discovery.ts +4 -1
- package/packages/shared/src/pi-package-resolver.ts +388 -0
- package/packages/shared/src/platform/binary-lookup.ts +27 -3
- package/packages/shared/src/platform/ensure-windows-path.ts +95 -0
- package/packages/shared/src/platform/exec.ts +22 -0
- package/packages/shared/src/platform/node-spawn.ts +42 -41
- package/packages/shared/src/plugin-bridge-register.ts +275 -18
- package/packages/shared/src/protocol.ts +94 -2
- package/packages/shared/src/recommended-extensions.ts +34 -10
- package/packages/shared/src/server-identity.ts +74 -5
- package/packages/shared/src/server-launcher.ts +20 -0
- package/packages/shared/src/source-matching.ts +1 -1
- package/packages/shared/src/tool-registry/__tests__/node-script-toargv-fallback.test.ts +84 -0
- package/packages/shared/src/tool-registry/definitions.ts +91 -7
- package/packages/shared/src/types.ts +12 -8
- package/scripts/maybe-patch-package.cjs +44 -0
- package/packages/server/src/__tests__/bootstrap-install-from-list.test.ts +0 -263
- package/packages/server/src/__tests__/bootstrap-queue.test.ts +0 -120
- package/packages/server/src/__tests__/bootstrap-routes.test.ts +0 -125
- package/packages/server/src/__tests__/bootstrap-state.test.ts +0 -119
- package/packages/server/src/__tests__/cli-bootstrap.test.ts +0 -36
- package/packages/server/src/__tests__/event-status-extraction-flow.test.ts +0 -55
- package/packages/server/src/__tests__/legacy-pi-cleanup.test.ts +0 -149
- package/packages/server/src/__tests__/post-install-openspec-refresh.test.ts +0 -180
- package/packages/server/src/__tests__/post-install-rescan.test.ts +0 -134
- package/packages/server/src/__tests__/system-routes-reextract.test.ts +0 -91
- package/packages/server/src/bootstrap-install-from-list.ts +0 -232
- package/packages/server/src/bootstrap-queue.ts +0 -130
- package/packages/server/src/bootstrap-state.ts +0 -159
- package/packages/server/src/legacy-pi-cleanup.ts +0 -151
- package/packages/server/src/routes/bootstrap-routes.ts +0 -125
- package/packages/shared/src/__tests__/bootstrap/README.md +0 -133
- package/packages/shared/src/__tests__/bootstrap/__snapshots__/cube.test.ts.snap +0 -378
- package/packages/shared/src/__tests__/bootstrap/assertions.ts +0 -136
- package/packages/shared/src/__tests__/bootstrap/cube.test.ts +0 -47
- package/packages/shared/src/__tests__/bootstrap/cube.ts +0 -66
- package/packages/shared/src/__tests__/bootstrap/families/__snapshots__/a-electron.test.ts.snap +0 -84
- package/packages/shared/src/__tests__/bootstrap/families/__snapshots__/b-npm-global.test.ts.snap +0 -90
- package/packages/shared/src/__tests__/bootstrap/families/__snapshots__/c-dev-monorepo.test.ts.snap +0 -34
- package/packages/shared/src/__tests__/bootstrap/families/__snapshots__/d-overrides.test.ts.snap +0 -20
- package/packages/shared/src/__tests__/bootstrap/families/__snapshots__/e-stale-partial.test.ts.snap +0 -62
- package/packages/shared/src/__tests__/bootstrap/families/__snapshots__/f-cwd-variants.test.ts.snap +0 -34
- package/packages/shared/src/__tests__/bootstrap/families/__snapshots__/g-windows-specifics.test.ts.snap +0 -49
- package/packages/shared/src/__tests__/bootstrap/families/__snapshots__/j-path-gui-minimal.test.ts.snap +0 -12
- package/packages/shared/src/__tests__/bootstrap/families/a-electron.test.ts +0 -156
- package/packages/shared/src/__tests__/bootstrap/families/b-npm-global.test.ts +0 -157
- package/packages/shared/src/__tests__/bootstrap/families/c-dev-monorepo.test.ts +0 -102
- package/packages/shared/src/__tests__/bootstrap/families/d-overrides.test.ts +0 -76
- package/packages/shared/src/__tests__/bootstrap/families/e-stale-partial.test.ts +0 -94
- package/packages/shared/src/__tests__/bootstrap/families/f-cwd-variants.test.ts +0 -87
- package/packages/shared/src/__tests__/bootstrap/families/g-windows-specifics.test.ts +0 -143
- package/packages/shared/src/__tests__/bootstrap/families/h-home-drift.test.ts +0 -64
- package/packages/shared/src/__tests__/bootstrap/families/i-malformed-settings.test.ts +0 -77
- package/packages/shared/src/__tests__/bootstrap/families/index.ts +0 -19
- package/packages/shared/src/__tests__/bootstrap/families/j-path-gui-minimal.test.ts +0 -61
- package/packages/shared/src/__tests__/bootstrap/families/k-dashboard-absent.test.ts +0 -50
- package/packages/shared/src/__tests__/bootstrap/families/l-instance-coordination.test.ts +0 -272
- package/packages/shared/src/__tests__/bootstrap/fixtures/dev-monorepo.ts +0 -58
- package/packages/shared/src/__tests__/bootstrap/fixtures/electron-layout.ts +0 -84
- package/packages/shared/src/__tests__/bootstrap/fixtures/index.ts +0 -9
- package/packages/shared/src/__tests__/bootstrap/fixtures/managed-install.ts +0 -85
- package/packages/shared/src/__tests__/bootstrap/fixtures/npm-global-layout.ts +0 -122
- package/packages/shared/src/__tests__/bootstrap/fixtures/pi-versions.ts +0 -36
- package/packages/shared/src/__tests__/bootstrap/fixtures/settings-json.ts +0 -39
- package/packages/shared/src/__tests__/bootstrap/harness.smoke.test.ts +0 -220
- package/packages/shared/src/__tests__/bootstrap/harness.ts +0 -413
- package/packages/shared/src/__tests__/bootstrap/scenarios-skipped.ts +0 -125
- package/packages/shared/src/__tests__/bootstrap/scenarios.ts +0 -132
- package/packages/shared/src/__tests__/bootstrap-install-resolve-npm.test.ts +0 -72
- package/packages/shared/src/__tests__/install-managed-node-bootstrap-order.test.ts +0 -68
- package/packages/shared/src/__tests__/install-managed-node.test.ts +0 -192
- package/packages/shared/src/__tests__/installable-list.test.ts +0 -130
- package/packages/shared/src/__tests__/no-installable-list-in-bridge.test.ts +0 -52
- package/packages/shared/src/bootstrap-install.ts +0 -406
- package/packages/shared/src/installable-list.ts +0 -152
- package/packages/shared/src/launch-source-flag.ts +0 -14
|
@@ -66,10 +66,10 @@ import { createViewedSessionTracker, type ViewedSessionTracker } from "./viewed-
|
|
|
66
66
|
import type { TerminalManager } from "./terminal-manager.js";
|
|
67
67
|
import type { BrowserHandlerContext } from "./browser-handlers/handler-context.js";
|
|
68
68
|
import { handleSubscribe } from "./browser-handlers/subscription-handler.js";
|
|
69
|
-
import { handleSendPrompt, handleResumeSession, handleSpawnSession, handleShutdown, handleAbort, handleFlowControl, handleForceKill, handleKillProcess } from "./browser-handlers/session-action-handler.js";
|
|
69
|
+
import { handleSendPrompt, handleResumeSession, handleSpawnSession, handleShutdown, handleAbort, handleFlowControl, handleForceKill, handleKillProcess, handleClearSteeringQueue, handleClearFollowupSlot, handleEditFollowupSlot, handlePromoteFollowupEntry, handleRemoveFollowupEntry, handleEditFollowupEntry } from "./browser-handlers/session-action-handler.js";
|
|
70
70
|
import { handleRenameSession, handleHideSession, handleUnhideSession, handleAttachProposal, handleDetachProposal, handleFetchContent, handleListSessions } from "./browser-handlers/session-meta-handler.js";
|
|
71
71
|
import { handleCreateTerminal, handleKillTerminal, handleRenameTerminal } from "./browser-handlers/terminal-handler.js";
|
|
72
|
-
import { handlePinDirectory, handleUnpinDirectory, handleReorderPinnedDirs, handleReorderSessions, handleOpenSpecRefresh, handleOpenSpecBulkArchive, handleExtensionUiResponse, handlePiGatewayForward } from "./browser-handlers/directory-handler.js";
|
|
72
|
+
import { handlePinDirectory, handleUnpinDirectory, handleReorderPinnedDirs, handleReorderSessions, handleOpenSpecRefresh, handleOpenSpecBulkArchive, handleExtensionUiResponse, handlePiGatewayForward, handleCreateWorkspace, handleRenameWorkspace, handleDeleteWorkspace, handleSetWorkspaceCollapsed, handleAddFolderToWorkspace, handleRemoveFolderFromWorkspace, handleReorderWorkspaceFolders, handleReorderWorkspaces } from "./browser-handlers/directory-handler.js";
|
|
73
73
|
|
|
74
74
|
|
|
75
75
|
|
|
@@ -111,6 +111,17 @@ export interface BrowserGateway {
|
|
|
111
111
|
onConnect?: (ws: WebSocket) => void;
|
|
112
112
|
/** Broadcast a message to all connected clients */
|
|
113
113
|
broadcast(msg: ServerToBrowserMessage): void;
|
|
114
|
+
/**
|
|
115
|
+
* Register a handler for a Browser→Server message type the gateway does
|
|
116
|
+
* not natively handle. Used by plugins to receive `plugin_action`
|
|
117
|
+
* messages without modifying the gateway's switch statement.
|
|
118
|
+
* See change: adopt-server-driven-intent-rendering.
|
|
119
|
+
*/
|
|
120
|
+
registerHandler(
|
|
121
|
+
type: string,
|
|
122
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
123
|
+
handler: (msg: any, ws: WebSocket) => void,
|
|
124
|
+
): void;
|
|
114
125
|
}
|
|
115
126
|
|
|
116
127
|
export function createBrowserGateway(
|
|
@@ -131,6 +142,14 @@ export function createBrowserGateway(
|
|
|
131
142
|
): BrowserGateway {
|
|
132
143
|
const wss = new WebSocketServer({ noServer: true });
|
|
133
144
|
|
|
145
|
+
/**
|
|
146
|
+
* Plugin-registered handlers for custom Browser→Server message types.
|
|
147
|
+
* Lives outside subscriptions because handlers are global, not per-WS.
|
|
148
|
+
* See change: adopt-server-driven-intent-rendering.
|
|
149
|
+
*/
|
|
150
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
151
|
+
const customHandlers = new Map<string, (msg: any, ws: WebSocket) => void>();
|
|
152
|
+
|
|
134
153
|
// Track subscriptions: ws → Set<sessionId>
|
|
135
154
|
const subscriptions = new Map<WebSocket, Set<string>>();
|
|
136
155
|
// Track which sessions are mid-replay per WebSocket (suppress live events)
|
|
@@ -274,6 +293,12 @@ export function createBrowserGateway(
|
|
|
274
293
|
// Send pinned directories on connect
|
|
275
294
|
if (preferencesStore) {
|
|
276
295
|
sendTo(ws, { type: "pinned_dirs_updated", paths: preferencesStore.getPinnedDirectories() });
|
|
296
|
+
// Send current workspaces snapshot. See change: folder-workspaces.
|
|
297
|
+
// Guarded with `typeof` so old PreferencesStore stubs in tests that
|
|
298
|
+
// predate workspaces still work — they simply get no workspace snapshot.
|
|
299
|
+
if (typeof preferencesStore.getWorkspaces === "function") {
|
|
300
|
+
sendTo(ws, { type: "workspaces_updated", workspaces: preferencesStore.getWorkspaces() });
|
|
301
|
+
}
|
|
277
302
|
}
|
|
278
303
|
|
|
279
304
|
// Send OpenSpec data for every known directory — exactly one
|
|
@@ -358,6 +383,24 @@ export function createBrowserGateway(
|
|
|
358
383
|
case "abort":
|
|
359
384
|
handleAbort(msg, ctx);
|
|
360
385
|
break;
|
|
386
|
+
case "clear_steering_queue":
|
|
387
|
+
handleClearSteeringQueue(msg, ctx);
|
|
388
|
+
break;
|
|
389
|
+
case "clear_followup_slot":
|
|
390
|
+
handleClearFollowupSlot(msg, ctx);
|
|
391
|
+
break;
|
|
392
|
+
case "edit_followup_slot":
|
|
393
|
+
handleEditFollowupSlot(msg, ctx);
|
|
394
|
+
break;
|
|
395
|
+
case "promote_followup_entry":
|
|
396
|
+
handlePromoteFollowupEntry(msg, ctx);
|
|
397
|
+
break;
|
|
398
|
+
case "remove_followup_entry":
|
|
399
|
+
handleRemoveFollowupEntry(msg, ctx);
|
|
400
|
+
break;
|
|
401
|
+
case "edit_followup_entry":
|
|
402
|
+
handleEditFollowupEntry(msg, ctx);
|
|
403
|
+
break;
|
|
361
404
|
case "force_kill":
|
|
362
405
|
await handleForceKill(msg, ctx);
|
|
363
406
|
break;
|
|
@@ -409,6 +452,30 @@ export function createBrowserGateway(
|
|
|
409
452
|
case "reorder_pinned_dirs":
|
|
410
453
|
handleReorderPinnedDirs(msg, ctx);
|
|
411
454
|
break;
|
|
455
|
+
case "create_workspace":
|
|
456
|
+
handleCreateWorkspace(msg, ctx);
|
|
457
|
+
break;
|
|
458
|
+
case "rename_workspace":
|
|
459
|
+
handleRenameWorkspace(msg, ctx);
|
|
460
|
+
break;
|
|
461
|
+
case "delete_workspace":
|
|
462
|
+
handleDeleteWorkspace(msg, ctx);
|
|
463
|
+
break;
|
|
464
|
+
case "set_workspace_collapsed":
|
|
465
|
+
handleSetWorkspaceCollapsed(msg, ctx);
|
|
466
|
+
break;
|
|
467
|
+
case "add_folder_to_workspace":
|
|
468
|
+
handleAddFolderToWorkspace(msg, ctx);
|
|
469
|
+
break;
|
|
470
|
+
case "remove_folder_from_workspace":
|
|
471
|
+
handleRemoveFolderFromWorkspace(msg, ctx);
|
|
472
|
+
break;
|
|
473
|
+
case "reorder_workspace_folders":
|
|
474
|
+
handleReorderWorkspaceFolders(msg, ctx);
|
|
475
|
+
break;
|
|
476
|
+
case "reorder_workspaces":
|
|
477
|
+
handleReorderWorkspaces(msg, ctx);
|
|
478
|
+
break;
|
|
412
479
|
case "openspec_refresh":
|
|
413
480
|
handleOpenSpecRefresh(msg, ctx);
|
|
414
481
|
break;
|
|
@@ -532,10 +599,17 @@ export function createBrowserGateway(
|
|
|
532
599
|
viewedSessionTracker.unview(msg.sessionId, ws);
|
|
533
600
|
break;
|
|
534
601
|
}
|
|
535
|
-
default:
|
|
536
|
-
//
|
|
537
|
-
|
|
602
|
+
default: {
|
|
603
|
+
// Plugin-registered custom handler takes precedence over pi-gateway forward.
|
|
604
|
+
const type = (msg as { type?: string } | undefined)?.type;
|
|
605
|
+
if (type && customHandlers.has(type)) {
|
|
606
|
+
customHandlers.get(type)!(msg, ws);
|
|
607
|
+
} else {
|
|
608
|
+
// Forward simple pi-gateway commands
|
|
609
|
+
handlePiGatewayForward(msg, ctx);
|
|
610
|
+
}
|
|
538
611
|
break;
|
|
612
|
+
}
|
|
539
613
|
}
|
|
540
614
|
} catch (err) {
|
|
541
615
|
const type = (msg as { type?: string } | undefined)?.type ?? "unknown";
|
|
@@ -568,6 +642,10 @@ export function createBrowserGateway(
|
|
|
568
642
|
broadcast(msg);
|
|
569
643
|
},
|
|
570
644
|
|
|
645
|
+
registerHandler(type, handler) {
|
|
646
|
+
customHandlers.set(type, handler);
|
|
647
|
+
},
|
|
648
|
+
|
|
571
649
|
broadcastEvent(sessionId: string, seq: number, event: any) {
|
|
572
650
|
const subscribers = getSubscribers(sessionId);
|
|
573
651
|
const msg: ServerToBrowserMessage = {
|
|
@@ -75,6 +75,75 @@ export function handleReorderPinnedDirs(
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
// ── folder-workspaces handlers ──────────────────────────────────
|
|
79
|
+
//
|
|
80
|
+
// Each handler dispatches to PreferencesStore which returns true on
|
|
81
|
+
// mutation. Broadcast `workspaces_updated` only on actual mutation
|
|
82
|
+
// (no broadcast for no-op / invalid / unknown-id calls). See spec
|
|
83
|
+
// folder-workspaces.
|
|
84
|
+
|
|
85
|
+
function broadcastWorkspaces(ctx: BrowserHandlerContext): void {
|
|
86
|
+
if (!ctx.preferencesStore) return;
|
|
87
|
+
ctx.broadcast({ type: "workspaces_updated", workspaces: ctx.preferencesStore.getWorkspaces() });
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function handleCreateWorkspace(
|
|
91
|
+
msg: Extract<BrowserToServerMessage, { type: "create_workspace" }>,
|
|
92
|
+
ctx: BrowserHandlerContext,
|
|
93
|
+
): void {
|
|
94
|
+
const ws = ctx.preferencesStore?.createWorkspace(msg.name);
|
|
95
|
+
if (ws) broadcastWorkspaces(ctx);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function handleRenameWorkspace(
|
|
99
|
+
msg: Extract<BrowserToServerMessage, { type: "rename_workspace" }>,
|
|
100
|
+
ctx: BrowserHandlerContext,
|
|
101
|
+
): void {
|
|
102
|
+
if (ctx.preferencesStore?.renameWorkspace(msg.id, msg.name)) broadcastWorkspaces(ctx);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function handleDeleteWorkspace(
|
|
106
|
+
msg: Extract<BrowserToServerMessage, { type: "delete_workspace" }>,
|
|
107
|
+
ctx: BrowserHandlerContext,
|
|
108
|
+
): void {
|
|
109
|
+
if (ctx.preferencesStore?.deleteWorkspace(msg.id)) broadcastWorkspaces(ctx);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function handleSetWorkspaceCollapsed(
|
|
113
|
+
msg: Extract<BrowserToServerMessage, { type: "set_workspace_collapsed" }>,
|
|
114
|
+
ctx: BrowserHandlerContext,
|
|
115
|
+
): void {
|
|
116
|
+
if (ctx.preferencesStore?.setWorkspaceCollapsed(msg.id, msg.collapsed)) broadcastWorkspaces(ctx);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function handleAddFolderToWorkspace(
|
|
120
|
+
msg: Extract<BrowserToServerMessage, { type: "add_folder_to_workspace" }>,
|
|
121
|
+
ctx: BrowserHandlerContext,
|
|
122
|
+
): void {
|
|
123
|
+
if (ctx.preferencesStore?.addFolderToWorkspace(msg.id, msg.path)) broadcastWorkspaces(ctx);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function handleRemoveFolderFromWorkspace(
|
|
127
|
+
msg: Extract<BrowserToServerMessage, { type: "remove_folder_from_workspace" }>,
|
|
128
|
+
ctx: BrowserHandlerContext,
|
|
129
|
+
): void {
|
|
130
|
+
if (ctx.preferencesStore?.removeFolderFromWorkspace(msg.id, msg.path)) broadcastWorkspaces(ctx);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function handleReorderWorkspaceFolders(
|
|
134
|
+
msg: Extract<BrowserToServerMessage, { type: "reorder_workspace_folders" }>,
|
|
135
|
+
ctx: BrowserHandlerContext,
|
|
136
|
+
): void {
|
|
137
|
+
if (ctx.preferencesStore?.reorderWorkspaceFolders(msg.id, msg.paths)) broadcastWorkspaces(ctx);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function handleReorderWorkspaces(
|
|
141
|
+
msg: Extract<BrowserToServerMessage, { type: "reorder_workspaces" }>,
|
|
142
|
+
ctx: BrowserHandlerContext,
|
|
143
|
+
): void {
|
|
144
|
+
if (ctx.preferencesStore?.reorderWorkspaces(msg.ids)) broadcastWorkspaces(ctx);
|
|
145
|
+
}
|
|
146
|
+
|
|
78
147
|
export function handleReorderSessions(
|
|
79
148
|
msg: Extract<BrowserToServerMessage, { type: "reorder_sessions" }>,
|
|
80
149
|
ctx: BrowserHandlerContext,
|
|
@@ -256,6 +256,7 @@ export async function handleSendPrompt(
|
|
|
256
256
|
sessionId: msg.sessionId,
|
|
257
257
|
text: msg.text,
|
|
258
258
|
images: msg.images,
|
|
259
|
+
delivery: msg.delivery,
|
|
259
260
|
});
|
|
260
261
|
if (!sent) {
|
|
261
262
|
console.error(`[dashboard] send_prompt failed: no bridge connection for session ${msg.sessionId}`);
|
|
@@ -523,6 +524,94 @@ export function handleAbort(
|
|
|
523
524
|
ctx.piGateway.sendToSession(msg.sessionId, { type: "abort", sessionId: msg.sessionId });
|
|
524
525
|
}
|
|
525
526
|
|
|
527
|
+
/**
|
|
528
|
+
* Clear pi's steering queue for the given session. Forwards to bridge,
|
|
529
|
+
* which calls `pi.clearSteeringQueue()`. Idempotent. Drops silently when
|
|
530
|
+
* the session is unknown. See change: add-followup-edit-and-steer-cancel.
|
|
531
|
+
*/
|
|
532
|
+
export function handleClearSteeringQueue(
|
|
533
|
+
msg: Extract<BrowserToServerMessage, { type: "clear_steering_queue" }>,
|
|
534
|
+
ctx: BrowserHandlerContext,
|
|
535
|
+
): void {
|
|
536
|
+
if (!ctx.sessionManager.get(msg.sessionId)) return;
|
|
537
|
+
ctx.piGateway.sendToSession(msg.sessionId, { type: "clear_steering_queue", sessionId: msg.sessionId });
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Clear pi's follow-up slot for the given session. Forwards to bridge,
|
|
542
|
+
* which calls `pi.clearFollowUpQueue()`. Idempotent.
|
|
543
|
+
* See change: add-followup-edit-and-steer-cancel.
|
|
544
|
+
*/
|
|
545
|
+
export function handleClearFollowupSlot(
|
|
546
|
+
msg: Extract<BrowserToServerMessage, { type: "clear_followup_slot" }>,
|
|
547
|
+
ctx: BrowserHandlerContext,
|
|
548
|
+
): void {
|
|
549
|
+
if (!ctx.sessionManager.get(msg.sessionId)) return;
|
|
550
|
+
ctx.piGateway.sendToSession(msg.sessionId, { type: "clear_followup_slot", sessionId: msg.sessionId });
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* Atomic replace of pi's follow-up slot (clear-then-send). Forwards text +
|
|
555
|
+
* optional images to bridge, which calls clearFollowUpQueue then sendUserMessage.
|
|
556
|
+
* See change: add-followup-edit-and-steer-cancel.
|
|
557
|
+
*/
|
|
558
|
+
export function handleEditFollowupSlot(
|
|
559
|
+
msg: Extract<BrowserToServerMessage, { type: "edit_followup_slot" }>,
|
|
560
|
+
ctx: BrowserHandlerContext,
|
|
561
|
+
): void {
|
|
562
|
+
if (!ctx.sessionManager.get(msg.sessionId)) return;
|
|
563
|
+
ctx.piGateway.sendToSession(msg.sessionId, {
|
|
564
|
+
type: "edit_followup_slot",
|
|
565
|
+
sessionId: msg.sessionId,
|
|
566
|
+
text: msg.text,
|
|
567
|
+
images: msg.images,
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* Promote the follow-up entry at `index` to the head (position 0) of the queue.
|
|
573
|
+
* See change: add-followup-edit-and-steer-cancel (task 13.3).
|
|
574
|
+
*/
|
|
575
|
+
export function handlePromoteFollowupEntry(
|
|
576
|
+
msg: Extract<BrowserToServerMessage, { type: "promote_followup_entry" }>,
|
|
577
|
+
ctx: BrowserHandlerContext,
|
|
578
|
+
): void {
|
|
579
|
+
if (!ctx.sessionManager.get(msg.sessionId)) return;
|
|
580
|
+
ctx.piGateway.sendToSession(msg.sessionId, {
|
|
581
|
+
type: "promote_followup_entry",
|
|
582
|
+
sessionId: msg.sessionId,
|
|
583
|
+
index: msg.index,
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
/** Remove the follow-up entry at `index` from the queue. */
|
|
588
|
+
export function handleRemoveFollowupEntry(
|
|
589
|
+
msg: Extract<BrowserToServerMessage, { type: "remove_followup_entry" }>,
|
|
590
|
+
ctx: BrowserHandlerContext,
|
|
591
|
+
): void {
|
|
592
|
+
if (!ctx.sessionManager.get(msg.sessionId)) return;
|
|
593
|
+
ctx.piGateway.sendToSession(msg.sessionId, {
|
|
594
|
+
type: "remove_followup_entry",
|
|
595
|
+
sessionId: msg.sessionId,
|
|
596
|
+
index: msg.index,
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
/** Replace the follow-up entry at `index` with new text. */
|
|
601
|
+
export function handleEditFollowupEntry(
|
|
602
|
+
msg: Extract<BrowserToServerMessage, { type: "edit_followup_entry" }>,
|
|
603
|
+
ctx: BrowserHandlerContext,
|
|
604
|
+
): void {
|
|
605
|
+
if (!ctx.sessionManager.get(msg.sessionId)) return;
|
|
606
|
+
ctx.piGateway.sendToSession(msg.sessionId, {
|
|
607
|
+
type: "edit_followup_entry",
|
|
608
|
+
sessionId: msg.sessionId,
|
|
609
|
+
index: msg.index,
|
|
610
|
+
text: msg.text,
|
|
611
|
+
images: msg.images,
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
|
|
526
615
|
export function handleFlowControl(
|
|
527
616
|
msg: Extract<BrowserToServerMessage, { type: "flow_control" }>,
|
|
528
617
|
ctx: BrowserHandlerContext,
|
|
@@ -5,6 +5,7 @@ import type { WebSocket } from "ws";
|
|
|
5
5
|
import type { ServerToBrowserMessage, BrowserToServerMessage } from "@blackbelt-technology/pi-dashboard-shared/browser-protocol.js";
|
|
6
6
|
import type { BrowserHandlerContext } from "./handler-context.js";
|
|
7
7
|
import { extractStatsFromEvents } from "../event-status-extraction.js";
|
|
8
|
+
import { pluginIntentCache } from "../plugin-intent-cache.js";
|
|
8
9
|
import type { StoredEvent } from "../memory-event-store.js";
|
|
9
10
|
|
|
10
11
|
const REPLAY_BATCH_SIZE = 50;
|
|
@@ -94,6 +95,28 @@ export function replayUiState(
|
|
|
94
95
|
sendTo(ws, { type: "ext_ui_decorator", sessionId, descriptor } as any);
|
|
95
96
|
}
|
|
96
97
|
}
|
|
98
|
+
|
|
99
|
+
// Replay cached plugin intents for this session (per-session AND global).
|
|
100
|
+
// See change: adopt-server-driven-intent-rendering.
|
|
101
|
+
for (const entry of pluginIntentCache.getForSession(sessionId)) {
|
|
102
|
+
sendTo(ws, {
|
|
103
|
+
type: "plugin_intents",
|
|
104
|
+
pluginId: entry.pluginId,
|
|
105
|
+
sessionId: entry.sessionId,
|
|
106
|
+
slot: entry.slot,
|
|
107
|
+
intent: entry.intent,
|
|
108
|
+
} as any);
|
|
109
|
+
}
|
|
110
|
+
// Also replay global (sessionId === null) intents.
|
|
111
|
+
for (const entry of pluginIntentCache.getForSession(null)) {
|
|
112
|
+
sendTo(ws, {
|
|
113
|
+
type: "plugin_intents",
|
|
114
|
+
pluginId: entry.pluginId,
|
|
115
|
+
sessionId: null,
|
|
116
|
+
slot: entry.slot,
|
|
117
|
+
intent: entry.intent,
|
|
118
|
+
} as any);
|
|
119
|
+
}
|
|
97
120
|
}
|
|
98
121
|
|
|
99
122
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pure parser for Keep-a-Changelog-style markdown files.
|
|
3
3
|
*
|
|
4
|
-
* Pi (`@mariozechner/pi-coding-agent`) ships a `CHANGELOG.md` whose
|
|
4
|
+
* Pi (`@earendil-works/pi-coding-agent` (formerly `@mariozechner/pi-coding-agent`)) ships a `CHANGELOG.md` whose
|
|
5
5
|
* format is mechanically reliable:
|
|
6
6
|
* - H2 release headers: `## [<version>] - <date>`
|
|
7
7
|
* - H3 sub-section headers: `### Breaking Changes`, `### New Features`,
|