@getpaseo/server 0.1.101 → 0.1.102
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/.env.example +8 -0
- package/dist/scripts/supervisor.js +26 -8
- package/dist/server/server/agent/activity-curator.d.ts +17 -0
- package/dist/server/server/agent/activity-curator.js +101 -24
- package/dist/server/server/agent/agent-manager.js +5 -1
- package/dist/server/server/agent/agent-sdk-types.d.ts +7 -2
- package/dist/server/server/agent/provider-registry.js +12 -11
- package/dist/server/server/agent/provider-snapshot-manager.d.ts +8 -1
- package/dist/server/server/agent/provider-snapshot-manager.js +78 -33
- package/dist/server/server/agent/providers/acp-agent.d.ts +13 -0
- package/dist/server/server/agent/providers/acp-agent.js +37 -1
- package/dist/server/server/agent/providers/claude/agent.js +51 -14
- package/dist/server/server/agent/providers/claude/query.d.ts +3 -0
- package/dist/server/server/agent/providers/claude/query.js +4 -2
- package/dist/server/server/agent/providers/generic-acp-agent.d.ts +2 -1
- package/dist/server/server/agent/providers/generic-acp-agent.js +2 -1
- package/dist/server/server/agent/providers/kiro-acp-agent.d.ts +17 -0
- package/dist/server/server/agent/providers/kiro-acp-agent.js +78 -0
- package/dist/server/server/agent/providers/mock-load-test-agent.js +8 -0
- package/dist/server/server/agent/providers/opencode/paths.d.ts +2 -0
- package/dist/server/server/agent/providers/opencode/paths.js +7 -0
- package/dist/server/server/agent/providers/opencode/server-manager.d.ts +2 -0
- package/dist/server/server/agent/providers/opencode/server-manager.js +34 -5
- package/dist/server/server/agent/providers/opencode-agent.d.ts +4 -0
- package/dist/server/server/agent/providers/opencode-agent.js +14 -2
- package/dist/server/server/agent/providers/pi/agent.d.ts +3 -0
- package/dist/server/server/agent/providers/pi/agent.js +9 -3
- package/dist/server/server/agent/providers/provider-image-output.js +11 -6
- package/dist/server/server/agent/tools/paseo-tools.d.ts +1 -1
- package/dist/server/server/agent/tools/paseo-tools.js +0 -2
- package/dist/server/server/bootstrap.d.ts +7 -1
- package/dist/server/server/bootstrap.js +18 -0
- package/dist/server/server/config.d.ts +2 -0
- package/dist/server/server/config.js +57 -1
- package/dist/server/server/daemon-worker.js +19 -7
- package/dist/server/server/lifecycle-reasons.d.ts +4 -0
- package/dist/server/server/lifecycle-reasons.js +6 -0
- package/dist/server/server/persisted-config.d.ts +13 -2
- package/dist/server/server/persisted-config.js +30 -11
- package/dist/server/server/process-diagnostics.d.ts +17 -0
- package/dist/server/server/process-diagnostics.js +22 -0
- package/dist/server/server/relay-transport.js +1 -0
- package/dist/server/server/resolve-worktree-creation-intent.js +3 -1
- package/dist/server/server/session/daemon/daemon-self-update-session-controller.d.ts +32 -0
- package/dist/server/server/session/daemon/daemon-self-update-session-controller.js +88 -0
- package/dist/server/server/session/daemon/daemon-self-updater.d.ts +32 -0
- package/dist/server/server/session/daemon/daemon-self-updater.js +56 -0
- package/dist/server/server/session/daemon/daemon-session.d.ts +12 -0
- package/dist/server/server/session/daemon/daemon-session.js +12 -0
- package/dist/server/server/session/daemon/diagnostics.js +10 -0
- package/dist/server/server/session/daemon/install-origin.d.ts +7 -0
- package/dist/server/server/session/daemon/install-origin.js +64 -0
- package/dist/server/server/session/daemon/npm-global-cli.d.ts +29 -0
- package/dist/server/server/session/daemon/npm-global-cli.js +98 -0
- package/dist/server/server/session/provider/provider-catalog-session.js +8 -4
- package/dist/server/server/session.d.ts +5 -3
- package/dist/server/server/session.js +74 -32
- package/dist/server/server/speech/providers/openai/config.d.ts +0 -2
- package/dist/server/server/speech/providers/openai/config.js +71 -34
- package/dist/server/server/speech/providers/openai/runtime.js +4 -4
- package/dist/server/server/web-ui.d.ts +10 -0
- package/dist/server/server/web-ui.js +205 -0
- package/dist/server/server/websocket/runtime-metrics.d.ts +3 -0
- package/dist/server/server/websocket-server.d.ts +3 -0
- package/dist/server/server/websocket-server.js +190 -32
- package/dist/server/services/quota-fetcher/manifest.js +5 -0
- package/dist/server/services/quota-fetcher/providers/minimax.d.ts +29 -0
- package/dist/server/services/quota-fetcher/providers/minimax.js +227 -0
- package/dist/server/terminal/agent-hooks/agent-hook-installer.js +2 -2
- package/dist/server/utils/checkout-git.js +156 -3
- package/dist/server/utils/directory-suggestions.js +1 -4
- package/dist/server/utils/path.d.ts +2 -0
- package/dist/server/utils/path.js +13 -0
- package/dist/server/utils/worktree.d.ts +1 -0
- package/dist/server/utils/worktree.js +92 -11
- package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css +1 -0
- package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css.br +0 -0
- package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css.gz +0 -0
- package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-5fa9347afb28c7d61bbf73684f3bdafa.js +1 -0
- package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-5fa9347afb28c7d61bbf73684f3bdafa.js.br +0 -0
- package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-5fa9347afb28c7d61bbf73684f3bdafa.js.gz +0 -0
- package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-35159ed50cf218b741c5dab5a6f4a889.js +1 -0
- package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-35159ed50cf218b741c5dab5a6f4a889.js.br +0 -0
- package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-35159ed50cf218b741c5dab5a6f4a889.js.gz +0 -0
- package/dist/server/web-ui/_expo/static/js/web/index-cf63ba3f4de4164d2d9c3738e1b791b2.js +16157 -0
- package/dist/server/web-ui/_expo/static/js/web/index-cf63ba3f4de4164d2d9c3738e1b791b2.js.br +0 -0
- package/dist/server/web-ui/_expo/static/js/web/index-cf63ba3f4de4164d2d9c3738e1b791b2.js.gz +0 -0
- package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-6a6cfdd9f06d4fd2b05adc1a8771c58c.js +1 -0
- package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-6a6cfdd9f06d4fd2b05adc1a8771c58c.js.br +0 -0
- package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-6a6cfdd9f06d4fd2b05adc1a8771c58c.js.gz +0 -0
- package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-b31888f9a7de4f0c52d6a58fcddbcb20.js +3 -0
- package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-b31888f9a7de4f0c52d6a58fcddbcb20.js.br +0 -0
- package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-b31888f9a7de4f0c52d6a58fcddbcb20.js.gz +0 -0
- package/dist/server/web-ui/apple-touch-icon.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/back-icon-mask.0a328cd9c1afd0afe8e3b1ec5165b1b4.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/back-icon.35ba0eaec5a4f5ed12ca16fabeae451d.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@2x.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@3x.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@4x.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@2x.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@3x.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@4x.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/search-icon.286d67d3f74808a60a78d3ebf1a5fb57.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/expo-router/assets/arrow_down.017bc6ba3fc25503e5eb5e53826d48a8.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/expo-router/assets/error.d1ea1496f9057eb392d5bbf3732a61b7.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/expo-router/assets/file.19eeb73b9593a38f8e9f418337fc7d10.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/expo-router/assets/forward.d8b800c443b8972542883e0b9de2bdc6.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/expo-router/assets/pkg.ab19f4cbc543357183a20571f68380a3.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/expo-router/assets/sitemap.412dd9275b6b48ad28f5e3d81bb1f626.png +0 -0
- package/dist/server/web-ui/assets/__node_modules/expo-router/assets/unmatched.20e71bdf79e3a97bf55fd9e164041578.png +0 -0
- package/dist/server/web-ui/assets/assets/images/editor-apps/antigravity.6e91a685c33435e0b466a56db86cf141.png +0 -0
- package/dist/server/web-ui/assets/assets/images/editor-apps/cursor.c31d6bce4fe9aadc3fe59962f4c4fcf3.png +0 -0
- package/dist/server/web-ui/assets/assets/images/editor-apps/file-explorer.3e15e8f72c825c85ce336bcb0cdef776.png +0 -0
- package/dist/server/web-ui/assets/assets/images/editor-apps/finder.7f68fc2c475621a672e1be09309d5567.png +0 -0
- package/dist/server/web-ui/assets/assets/images/editor-apps/vscode.832bdb4c685d930f1c864c793703600b.png +0 -0
- package/dist/server/web-ui/assets/assets/images/editor-apps/webstorm.aa5dc2cd8c20cc0a155c4c5c5ab3c5f5.png +0 -0
- package/dist/server/web-ui/assets/assets/images/editor-apps/zed.f3a670b7f9aa226da4fe53fb86f1abbd.png +0 -0
- package/dist/server/web-ui/assets/assets/images/favicon-dark-attention.882b3a27dcb2073e9e31b334f9ed9728.png +0 -0
- package/dist/server/web-ui/assets/assets/images/favicon-dark-running.8112342ff0d39e047a7f8d4fad9402f3.png +0 -0
- package/dist/server/web-ui/assets/assets/images/favicon-dark.8005ed36ac07a5a7c60de25780897bd4.png +0 -0
- package/dist/server/web-ui/assets/assets/images/favicon-light-attention.882b3a27dcb2073e9e31b334f9ed9728.png +0 -0
- package/dist/server/web-ui/assets/assets/images/favicon-light-running.8112342ff0d39e047a7f8d4fad9402f3.png +0 -0
- package/dist/server/web-ui/assets/assets/images/favicon-light.8005ed36ac07a5a7c60de25780897bd4.png +0 -0
- package/dist/server/web-ui/assets/assets/images/notification-icon.3bf81d33ddbf380606bdd248ba83e158.png +0 -0
- package/dist/server/web-ui/favicon.ico +0 -0
- package/dist/server/web-ui/index.html +90 -0
- package/dist/server/web-ui/index.html.br +0 -0
- package/dist/server/web-ui/index.html.gz +0 -0
- package/dist/server/web-ui/manifest.json +27 -0
- package/dist/server/web-ui/manifest.json.br +0 -0
- package/dist/server/web-ui/manifest.json.gz +0 -0
- package/dist/server/web-ui/metadata.json +1 -0
- package/dist/server/web-ui/metadata.json.br +1 -0
- package/dist/server/web-ui/metadata.json.gz +0 -0
- package/dist/server/web-ui/pwa-icon-192.png +0 -0
- package/dist/server/web-ui/pwa-icon-512.png +0 -0
- package/dist/server/web-ui/robots.txt +2 -0
- package/dist/src/server/persisted-config.js +30 -11
- package/package.json +7 -7
|
@@ -18,11 +18,13 @@ import { createWorkspaceScriptsService, } from "./session/workspace-scripts/work
|
|
|
18
18
|
import { getErrorMessage, getErrorMessageOr } from "@getpaseo/protocol/error-utils";
|
|
19
19
|
import { getAgentStatusPriority } from "@getpaseo/protocol/agent-state-bucket";
|
|
20
20
|
import { getParentAgentIdFromLabels } from "@getpaseo/protocol/agent-labels";
|
|
21
|
+
import { CLIENT_SHUTDOWN_RPC_REASON, normalizeClientRestartRpcReason, } from "./lifecycle-reasons.js";
|
|
21
22
|
import { createAgentCommand } from "./agent/create-agent/create.js";
|
|
22
23
|
import { archiveAgentCommand, cancelAgentRunCommand, closeAgentCommand, detachAgentCommand, setAgentModeCommand, updateAgentCommand, } from "./agent/lifecycle-command.js";
|
|
23
24
|
import { buildStoredAgentPayload, resolveStoredAgentPayloadUpdatedAt, toAgentPayload, } from "./agent/agent-projections.js";
|
|
24
25
|
import { appendTimelineItemIfAgentKnown, emitLiveTimelineItemIfAgentKnown, } from "./agent/timeline-append.js";
|
|
25
26
|
import { projectTimelineRows, selectProjectedTimelinePage, } from "./agent/timeline-projection.js";
|
|
27
|
+
import { buildAgentForkContextAttachment } from "./agent/activity-curator.js";
|
|
26
28
|
import { getAgentStreamEventTurnId, } from "./agent/agent-sdk-types.js";
|
|
27
29
|
import { ImportSessionsRequestError, importProviderSession, listImportableProviderSessions, normalizeImportAgentRequest, } from "./agent/import-sessions.js";
|
|
28
30
|
import { checkoutLiteFromGitSnapshot, deriveWorkspaceDisplayName, } from "./workspace-registry-model.js";
|
|
@@ -355,7 +357,9 @@ export class Session {
|
|
|
355
357
|
this.daemonSession = new DaemonSession({
|
|
356
358
|
host: {
|
|
357
359
|
emit: (msg) => this.emit(msg),
|
|
360
|
+
emitLifecycleIntent: (intent) => this.emitLifecycleIntent(intent),
|
|
358
361
|
},
|
|
362
|
+
clientId: this.clientId,
|
|
359
363
|
paseoHome: this.paseoHome,
|
|
360
364
|
serverId,
|
|
361
365
|
daemonVersion,
|
|
@@ -746,12 +750,6 @@ export class Session {
|
|
|
746
750
|
};
|
|
747
751
|
}
|
|
748
752
|
async buildProjectPlacementForWorkspaceId(workspaceId) {
|
|
749
|
-
const workspace = await this.workspaceRegistry.get(workspaceId);
|
|
750
|
-
if (!workspace)
|
|
751
|
-
return null;
|
|
752
|
-
return this.buildProjectPlacementForWorkspace(workspace);
|
|
753
|
-
}
|
|
754
|
-
async buildProjectPlacementForExistingWorkspaceProject(workspaceId) {
|
|
755
753
|
const workspace = await this.workspaceRegistry.get(workspaceId);
|
|
756
754
|
if (!workspace)
|
|
757
755
|
return null;
|
|
@@ -815,6 +813,7 @@ export class Session {
|
|
|
815
813
|
const promise = this.dispatchVoiceAndControlMessage(msg) ??
|
|
816
814
|
this.dispatchAgentRewindMessage(msg) ??
|
|
817
815
|
this.dispatchAgentRelationshipMessage(msg) ??
|
|
816
|
+
this.dispatchAgentTimelineMessage(msg) ??
|
|
818
817
|
this.dispatchAgentLifecycleMessage(msg) ??
|
|
819
818
|
this.dispatchAgentConfigMessage(msg) ??
|
|
820
819
|
this.dispatchCheckoutMessage(msg) ??
|
|
@@ -891,6 +890,16 @@ export class Session {
|
|
|
891
890
|
return undefined;
|
|
892
891
|
}
|
|
893
892
|
}
|
|
893
|
+
dispatchAgentTimelineMessage(msg) {
|
|
894
|
+
switch (msg.type) {
|
|
895
|
+
case "fetch_agent_timeline_request":
|
|
896
|
+
return this.handleFetchAgentTimelineRequest(msg);
|
|
897
|
+
case "agent.fork_context.request":
|
|
898
|
+
return this.handleAgentForkContextRequest(msg);
|
|
899
|
+
default:
|
|
900
|
+
return undefined;
|
|
901
|
+
}
|
|
902
|
+
}
|
|
894
903
|
dispatchAgentLifecycleMessage(msg) {
|
|
895
904
|
switch (msg.type) {
|
|
896
905
|
case "fetch_agents_request":
|
|
@@ -925,8 +934,6 @@ export class Session {
|
|
|
925
934
|
return this.handleRefreshAgentRequest(msg);
|
|
926
935
|
case "cancel_agent_request":
|
|
927
936
|
return this.handleCancelAgentRequest(msg.agentId, msg.requestId);
|
|
928
|
-
case "fetch_agent_timeline_request":
|
|
929
|
-
return this.handleFetchAgentTimelineRequest(msg);
|
|
930
937
|
case "agent_permission_response":
|
|
931
938
|
return this.handleAgentPermissionResponse(msg.agentId, msg.requestId, msg.response);
|
|
932
939
|
case "clear_agent_attention":
|
|
@@ -957,6 +964,8 @@ export class Session {
|
|
|
957
964
|
return this.daemonSession.handleGetPairingOfferRequest(msg);
|
|
958
965
|
case "diagnostics.request":
|
|
959
966
|
return this.daemonSession.handleDiagnosticsRequest(msg);
|
|
967
|
+
case "daemon.update.request":
|
|
968
|
+
return this.daemonSession.handleUpdateRequest(msg);
|
|
960
969
|
case "set_daemon_config_request":
|
|
961
970
|
this.emit({
|
|
962
971
|
type: "set_daemon_config_response",
|
|
@@ -1164,6 +1173,9 @@ export class Session {
|
|
|
1164
1173
|
resetPeakInflight() {
|
|
1165
1174
|
this.peakInflightRequests = this.inflightRequests;
|
|
1166
1175
|
}
|
|
1176
|
+
getSessionId() {
|
|
1177
|
+
return this.sessionId;
|
|
1178
|
+
}
|
|
1167
1179
|
async handleBinaryFrame(binaryFrame) {
|
|
1168
1180
|
if (binaryFrame.kind === "file_transfer") {
|
|
1169
1181
|
await this.workspaceFilesSession.handleFileTransferFrame(binaryFrame.frame);
|
|
@@ -1172,6 +1184,7 @@ export class Session {
|
|
|
1172
1184
|
this.terminalController.handleBinaryFrame(binaryFrame.frame);
|
|
1173
1185
|
}
|
|
1174
1186
|
async handleRestartServerRequest(requestId, reason) {
|
|
1187
|
+
const lifecycleReason = normalizeClientRestartRpcReason(reason);
|
|
1175
1188
|
const payload = {
|
|
1176
1189
|
status: "restart_requested",
|
|
1177
1190
|
clientId: this.clientId,
|
|
@@ -1180,7 +1193,7 @@ export class Session {
|
|
|
1180
1193
|
payload.reason = reason;
|
|
1181
1194
|
}
|
|
1182
1195
|
payload.requestId = requestId;
|
|
1183
|
-
this.sessionLogger.warn({ reason }, "Restart requested via websocket");
|
|
1196
|
+
this.sessionLogger.warn({ reason: lifecycleReason }, "Restart requested via websocket");
|
|
1184
1197
|
this.emit({
|
|
1185
1198
|
type: "status",
|
|
1186
1199
|
payload,
|
|
@@ -1189,11 +1202,12 @@ export class Session {
|
|
|
1189
1202
|
type: "restart",
|
|
1190
1203
|
clientId: this.clientId,
|
|
1191
1204
|
requestId,
|
|
1192
|
-
|
|
1205
|
+
reason: lifecycleReason,
|
|
1193
1206
|
});
|
|
1194
1207
|
}
|
|
1195
1208
|
async handleShutdownServerRequest(requestId) {
|
|
1196
|
-
|
|
1209
|
+
const reason = CLIENT_SHUTDOWN_RPC_REASON;
|
|
1210
|
+
this.sessionLogger.warn({ reason }, "Shutdown requested via websocket");
|
|
1197
1211
|
this.emit({
|
|
1198
1212
|
type: "status",
|
|
1199
1213
|
payload: {
|
|
@@ -1206,6 +1220,7 @@ export class Session {
|
|
|
1206
1220
|
type: "shutdown",
|
|
1207
1221
|
clientId: this.clientId,
|
|
1208
1222
|
requestId,
|
|
1223
|
+
reason,
|
|
1209
1224
|
});
|
|
1210
1225
|
}
|
|
1211
1226
|
emitLifecycleIntent(intent) {
|
|
@@ -1691,6 +1706,7 @@ export class Session {
|
|
|
1691
1706
|
cwd: createAgentConfig.cwd,
|
|
1692
1707
|
initialTitle: workspacePromptTitle,
|
|
1693
1708
|
});
|
|
1709
|
+
const createdDirectoryWorkspaceForAgent = !createdWorktree && !msg.workspaceId;
|
|
1694
1710
|
const { snapshot, liveSnapshot } = await createAgentCommand({
|
|
1695
1711
|
agentManager: this.agentManager,
|
|
1696
1712
|
agentStorage: this.agentStorage,
|
|
@@ -1716,11 +1732,8 @@ export class Session {
|
|
|
1716
1732
|
buildSessionConfig: (sessionConfig, gitOptions, legacyWorktreeName, ctx) => this.buildAgentSessionConfig(sessionConfig, gitOptions, legacyWorktreeName, ctx),
|
|
1717
1733
|
});
|
|
1718
1734
|
createdAgentId = snapshot.id;
|
|
1719
|
-
if (!createdWorktree && msg.workspaceId) {
|
|
1720
|
-
await this.writeInitialWorkspaceTitleIfUntitled(workspaceId, workspacePromptTitle);
|
|
1721
|
-
}
|
|
1722
1735
|
await this.agentUpdates.forwardLiveAgent(snapshot);
|
|
1723
|
-
if (
|
|
1736
|
+
if (createdDirectoryWorkspaceForAgent && trimmedPrompt) {
|
|
1724
1737
|
await this.scheduleAutoNameLocalWorkspaceTitleForFirstAgent({
|
|
1725
1738
|
workspaceId,
|
|
1726
1739
|
cwd: createAgentConfig.cwd,
|
|
@@ -2118,20 +2131,6 @@ export class Session {
|
|
|
2118
2131
|
updatedAt: new Date().toISOString(),
|
|
2119
2132
|
});
|
|
2120
2133
|
}
|
|
2121
|
-
async writeInitialWorkspaceTitleIfUntitled(workspaceId, title) {
|
|
2122
|
-
if (!title) {
|
|
2123
|
-
return;
|
|
2124
|
-
}
|
|
2125
|
-
const current = await this.workspaceRegistry.get(workspaceId);
|
|
2126
|
-
if (!current || current.title) {
|
|
2127
|
-
return;
|
|
2128
|
-
}
|
|
2129
|
-
await this.workspaceRegistry.upsert({
|
|
2130
|
-
...current,
|
|
2131
|
-
title,
|
|
2132
|
-
updatedAt: new Date().toISOString(),
|
|
2133
|
-
});
|
|
2134
|
-
}
|
|
2135
2134
|
// Wraps the injected workspace-name generator for a directory workspace.
|
|
2136
2135
|
async generateWorkspaceTitleFromContext(input) {
|
|
2137
2136
|
return this.generateWorkspaceName({
|
|
@@ -2624,9 +2623,7 @@ export class Session {
|
|
|
2624
2623
|
if (existing) {
|
|
2625
2624
|
return existing;
|
|
2626
2625
|
}
|
|
2627
|
-
const placementPromise =
|
|
2628
|
-
? this.buildProjectPlacementForExistingWorkspaceProject(workspaceId)
|
|
2629
|
-
: this.buildProjectPlacementForWorkspaceId(workspaceId);
|
|
2626
|
+
const placementPromise = this.buildProjectPlacementForWorkspaceId(workspaceId);
|
|
2630
2627
|
placementByWorkspaceId.set(workspaceId, placementPromise);
|
|
2631
2628
|
return placementPromise;
|
|
2632
2629
|
};
|
|
@@ -4038,6 +4035,51 @@ export class Session {
|
|
|
4038
4035
|
});
|
|
4039
4036
|
}
|
|
4040
4037
|
}
|
|
4038
|
+
async handleAgentForkContextRequest(msg) {
|
|
4039
|
+
try {
|
|
4040
|
+
const snapshot = await ensureAgentLoaded(msg.agentId, {
|
|
4041
|
+
agentManager: this.agentManager,
|
|
4042
|
+
agentStorage: this.agentStorage,
|
|
4043
|
+
logger: this.sessionLogger,
|
|
4044
|
+
});
|
|
4045
|
+
const agentPayload = await this.buildAgentPayload(snapshot);
|
|
4046
|
+
const rows = this.agentManager.fetchTimeline(msg.agentId, {
|
|
4047
|
+
direction: "tail",
|
|
4048
|
+
limit: 0,
|
|
4049
|
+
}).rows;
|
|
4050
|
+
const forkContext = buildAgentForkContextAttachment({
|
|
4051
|
+
rows,
|
|
4052
|
+
boundaryMessageId: msg.boundaryMessageId,
|
|
4053
|
+
agentTitle: agentPayload.title,
|
|
4054
|
+
cwd: snapshot.cwd,
|
|
4055
|
+
});
|
|
4056
|
+
this.emit({
|
|
4057
|
+
type: "agent.fork_context.response",
|
|
4058
|
+
payload: {
|
|
4059
|
+
requestId: msg.requestId,
|
|
4060
|
+
agentId: msg.agentId,
|
|
4061
|
+
attachment: forkContext.attachment,
|
|
4062
|
+
itemCount: forkContext.itemCount,
|
|
4063
|
+
boundaryMessageId: forkContext.boundaryMessageId,
|
|
4064
|
+
error: null,
|
|
4065
|
+
},
|
|
4066
|
+
});
|
|
4067
|
+
}
|
|
4068
|
+
catch (error) {
|
|
4069
|
+
this.sessionLogger.error({ err: error, agentId: msg.agentId }, "Failed to handle agent.fork_context.request");
|
|
4070
|
+
this.emit({
|
|
4071
|
+
type: "agent.fork_context.response",
|
|
4072
|
+
payload: {
|
|
4073
|
+
requestId: msg.requestId,
|
|
4074
|
+
agentId: msg.agentId,
|
|
4075
|
+
attachment: null,
|
|
4076
|
+
itemCount: 0,
|
|
4077
|
+
boundaryMessageId: msg.boundaryMessageId ?? null,
|
|
4078
|
+
error: error instanceof Error ? error.message : String(error),
|
|
4079
|
+
},
|
|
4080
|
+
});
|
|
4081
|
+
}
|
|
4082
|
+
}
|
|
4041
4083
|
async handleSendAgentMessageRequest(msg) {
|
|
4042
4084
|
const resolved = await this.resolveAgentIdentifier(msg.agentId);
|
|
4043
4085
|
if (!resolved.ok) {
|
|
@@ -4,8 +4,6 @@ import type { STTConfig } from "./stt.js";
|
|
|
4
4
|
import type { TTSConfig } from "./tts.js";
|
|
5
5
|
export declare const DEFAULT_OPENAI_TTS_MODEL = "tts-1";
|
|
6
6
|
export interface OpenAiSpeechProviderConfig {
|
|
7
|
-
apiKey?: string;
|
|
8
|
-
baseUrl?: string;
|
|
9
7
|
stt?: Partial<STTConfig> & {
|
|
10
8
|
apiKey?: string;
|
|
11
9
|
};
|
|
@@ -9,11 +9,21 @@ const OptionalTrimmedStringSchema = z
|
|
|
9
9
|
.trim()
|
|
10
10
|
.optional()
|
|
11
11
|
.transform((value) => (value && value.length > 0 ? value : undefined));
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
// Endpoint credentials only — plain trimmed strings, so this never throws on a
|
|
13
|
+
// malformed value. The STT/TTS option groups parse separately and only for the
|
|
14
|
+
// endpoint that is actually configured, so a stale env var for an unused endpoint
|
|
15
|
+
// (e.g. a leftover TTS_VOICE in an STT-only setup) can't break the other one.
|
|
16
|
+
const OpenAiEndpointKeysSchema = z.object({
|
|
17
|
+
sttApiKey: OptionalTrimmedStringSchema,
|
|
18
|
+
sttBaseUrl: OptionalTrimmedStringSchema,
|
|
19
|
+
ttsApiKey: OptionalTrimmedStringSchema,
|
|
20
|
+
ttsBaseUrl: OptionalTrimmedStringSchema,
|
|
21
|
+
});
|
|
22
|
+
const OpenAiSttOptionsSchema = z.object({
|
|
15
23
|
sttConfidenceThreshold: OptionalFiniteNumberSchema,
|
|
16
24
|
sttModel: OptionalTrimmedStringSchema,
|
|
25
|
+
});
|
|
26
|
+
const OpenAiTtsOptionsSchema = z.object({
|
|
17
27
|
ttsVoice: z.string().trim().toLowerCase().pipe(OpenAiTtsVoiceSchema).default("alloy"),
|
|
18
28
|
ttsModel: z
|
|
19
29
|
.string()
|
|
@@ -30,9 +40,15 @@ function pickIfOpenAi(provider, value) {
|
|
|
30
40
|
}
|
|
31
41
|
function firstDefined(values) {
|
|
32
42
|
for (const value of values) {
|
|
33
|
-
if (value
|
|
34
|
-
|
|
43
|
+
if (value === undefined || value === null) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
// Empty/whitespace env vars (e.g. a copied .env.example with OPENAI_STT_API_KEY=)
|
|
47
|
+
// must not shadow a later fallback such as OPENAI_API_KEY.
|
|
48
|
+
if (typeof value === "string" && value.trim().length === 0) {
|
|
49
|
+
continue;
|
|
35
50
|
}
|
|
51
|
+
return value;
|
|
36
52
|
}
|
|
37
53
|
return undefined;
|
|
38
54
|
}
|
|
@@ -66,46 +82,67 @@ function buildOpenAiTtsInput(params) {
|
|
|
66
82
|
};
|
|
67
83
|
}
|
|
68
84
|
function buildOpenAiResolutionInput(params) {
|
|
85
|
+
const { env } = params;
|
|
86
|
+
const openai = params.persisted.providers?.openai;
|
|
69
87
|
return {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
88
|
+
sttApiKey: firstDefined([
|
|
89
|
+
openai?.stt?.apiKey,
|
|
90
|
+
env.OPENAI_STT_API_KEY,
|
|
91
|
+
openai?.apiKey,
|
|
92
|
+
env.OPENAI_API_KEY,
|
|
75
93
|
]),
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
94
|
+
sttBaseUrl: firstDefined([
|
|
95
|
+
openai?.stt?.baseUrl,
|
|
96
|
+
env.OPENAI_STT_BASE_URL,
|
|
97
|
+
openai?.baseUrl,
|
|
98
|
+
env.OPENAI_BASE_URL,
|
|
99
|
+
]),
|
|
100
|
+
ttsApiKey: firstDefined([
|
|
101
|
+
openai?.tts?.apiKey,
|
|
102
|
+
env.OPENAI_TTS_API_KEY,
|
|
103
|
+
openai?.apiKey,
|
|
104
|
+
env.OPENAI_API_KEY,
|
|
105
|
+
]),
|
|
106
|
+
ttsBaseUrl: firstDefined([
|
|
107
|
+
openai?.tts?.baseUrl,
|
|
108
|
+
env.OPENAI_TTS_BASE_URL,
|
|
109
|
+
openai?.baseUrl,
|
|
110
|
+
env.OPENAI_BASE_URL,
|
|
81
111
|
]),
|
|
82
112
|
...buildOpenAiSttInput(params),
|
|
83
113
|
...buildOpenAiTtsInput(params),
|
|
84
114
|
};
|
|
85
115
|
}
|
|
86
116
|
export function resolveOpenAiSpeechConfig(params) {
|
|
87
|
-
const
|
|
88
|
-
|
|
117
|
+
const input = buildOpenAiResolutionInput(params);
|
|
118
|
+
const keys = OpenAiEndpointKeysSchema.parse(input);
|
|
119
|
+
if (!keys.sttApiKey && !keys.ttsApiKey) {
|
|
89
120
|
return undefined;
|
|
90
121
|
}
|
|
91
122
|
return {
|
|
92
|
-
|
|
93
|
-
...(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
123
|
+
...(keys.sttApiKey ? { stt: buildSttConfig(keys.sttApiKey, keys.sttBaseUrl, input) } : {}),
|
|
124
|
+
...(keys.ttsApiKey ? { tts: buildTtsConfig(keys.ttsApiKey, keys.ttsBaseUrl, input) } : {}),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function buildSttConfig(apiKey, baseUrl, input) {
|
|
128
|
+
const options = OpenAiSttOptionsSchema.parse(input);
|
|
129
|
+
return {
|
|
130
|
+
apiKey,
|
|
131
|
+
...(baseUrl ? { baseUrl } : {}),
|
|
132
|
+
...(options.sttConfidenceThreshold !== undefined
|
|
133
|
+
? { confidenceThreshold: options.sttConfidenceThreshold }
|
|
134
|
+
: {}),
|
|
135
|
+
...(options.sttModel ? { model: options.sttModel } : {}),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function buildTtsConfig(apiKey, baseUrl, input) {
|
|
139
|
+
const options = OpenAiTtsOptionsSchema.parse(input);
|
|
140
|
+
return {
|
|
141
|
+
apiKey,
|
|
142
|
+
...(baseUrl ? { baseUrl } : {}),
|
|
143
|
+
voice: options.ttsVoice,
|
|
144
|
+
model: options.ttsModel,
|
|
145
|
+
responseFormat: "pcm",
|
|
109
146
|
};
|
|
110
147
|
}
|
|
111
148
|
//# sourceMappingURL=config.js.map
|
|
@@ -2,11 +2,11 @@ import { DEFAULT_OPENAI_TTS_MODEL } from "./config.js";
|
|
|
2
2
|
import { OpenAISTT } from "./stt.js";
|
|
3
3
|
import { OpenAITTS } from "./tts.js";
|
|
4
4
|
function resolveOpenAiCredentials(openaiConfig) {
|
|
5
|
-
const
|
|
5
|
+
const sttApiKey = openaiConfig?.stt?.apiKey;
|
|
6
6
|
return {
|
|
7
|
-
openaiSttApiKey:
|
|
8
|
-
openaiTtsApiKey: openaiConfig?.tts?.apiKey
|
|
9
|
-
openaiDictationApiKey:
|
|
7
|
+
openaiSttApiKey: sttApiKey,
|
|
8
|
+
openaiTtsApiKey: openaiConfig?.tts?.apiKey,
|
|
9
|
+
openaiDictationApiKey: sttApiKey,
|
|
10
10
|
};
|
|
11
11
|
}
|
|
12
12
|
export function getOpenAiSpeechAvailability(openaiConfig) {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { RequestHandler } from "express";
|
|
2
|
+
import type { Logger } from "pino";
|
|
3
|
+
export interface WebUiMiddlewareOptions {
|
|
4
|
+
enabled: boolean;
|
|
5
|
+
distDir: string | null;
|
|
6
|
+
label: string;
|
|
7
|
+
logger: Logger;
|
|
8
|
+
}
|
|
9
|
+
export declare function createWebUiMiddleware(options: WebUiMiddlewareOptions): RequestHandler;
|
|
10
|
+
//# sourceMappingURL=web-ui.d.ts.map
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { createReadStream, readFileSync, statSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
const EXCLUDED_PATH_PREFIXES = ["/api/", "/mcp/", "/public/"];
|
|
4
|
+
const EXCLUDED_PATHS = new Set(["/api", "/mcp", "/public"]);
|
|
5
|
+
function isExcludedPath(requestPath) {
|
|
6
|
+
for (const prefix of EXCLUDED_PATH_PREFIXES) {
|
|
7
|
+
if (requestPath.startsWith(prefix)) {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return EXCLUDED_PATHS.has(requestPath);
|
|
12
|
+
}
|
|
13
|
+
const CONTENT_TYPES = {
|
|
14
|
+
".html": "text/html; charset=utf-8",
|
|
15
|
+
".js": "application/javascript; charset=utf-8",
|
|
16
|
+
".mjs": "application/javascript; charset=utf-8",
|
|
17
|
+
".css": "text/css; charset=utf-8",
|
|
18
|
+
".json": "application/json; charset=utf-8",
|
|
19
|
+
".png": "image/png",
|
|
20
|
+
".jpg": "image/jpeg",
|
|
21
|
+
".jpeg": "image/jpeg",
|
|
22
|
+
".gif": "image/gif",
|
|
23
|
+
".svg": "image/svg+xml",
|
|
24
|
+
".ico": "image/x-icon",
|
|
25
|
+
".woff": "font/woff",
|
|
26
|
+
".woff2": "font/woff2",
|
|
27
|
+
".ttf": "font/ttf",
|
|
28
|
+
".otf": "font/otf",
|
|
29
|
+
".eot": "application/vnd.ms-fontobject",
|
|
30
|
+
".map": "application/json",
|
|
31
|
+
};
|
|
32
|
+
function getContentType(filePath) {
|
|
33
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
34
|
+
return CONTENT_TYPES[ext] ?? "application/octet-stream";
|
|
35
|
+
}
|
|
36
|
+
function selectEncoding(acceptEncoding) {
|
|
37
|
+
if (!acceptEncoding) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
const normalized = acceptEncoding.toLowerCase();
|
|
41
|
+
if (normalized.includes("br")) {
|
|
42
|
+
return "br";
|
|
43
|
+
}
|
|
44
|
+
if (normalized.includes("gzip")) {
|
|
45
|
+
return "gzip";
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
function isHashedAsset(filePath) {
|
|
50
|
+
const base = path.basename(filePath);
|
|
51
|
+
// Match content hashes like index-abc123def456.js or main.abc123def456.css.
|
|
52
|
+
return /[-.][0-9a-f]{16,}[-.]/i.test(base);
|
|
53
|
+
}
|
|
54
|
+
function isInsideDir(targetPath, dirPath) {
|
|
55
|
+
const resolvedDir = path.resolve(dirPath);
|
|
56
|
+
const resolvedTarget = path.resolve(targetPath);
|
|
57
|
+
return resolvedTarget === resolvedDir || resolvedTarget.startsWith(resolvedDir + path.sep);
|
|
58
|
+
}
|
|
59
|
+
function resolveTargetFile(distDir, requestPath) {
|
|
60
|
+
const safePath = path.normalize(requestPath).replace(/^(\.\.[/\\])+/, "");
|
|
61
|
+
let filePath = path.join(distDir, safePath);
|
|
62
|
+
const stat = safeStat(filePath);
|
|
63
|
+
if (stat?.isDirectory()) {
|
|
64
|
+
filePath = path.join(filePath, "index.html");
|
|
65
|
+
}
|
|
66
|
+
const finalStat = safeStat(filePath);
|
|
67
|
+
if (!finalStat?.isFile()) {
|
|
68
|
+
filePath = path.join(distDir, "index.html");
|
|
69
|
+
const fallbackStat = safeStat(filePath);
|
|
70
|
+
if (!fallbackStat?.isFile()) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (!isInsideDir(filePath, distDir)) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
const resolvedFile = path.resolve(filePath);
|
|
78
|
+
const isIndexHtml = path.basename(resolvedFile).toLowerCase() === "index.html";
|
|
79
|
+
return { resolvedFile, isIndexHtml };
|
|
80
|
+
}
|
|
81
|
+
function safeStat(filePath) {
|
|
82
|
+
try {
|
|
83
|
+
return statSync(filePath);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function resolveContentEncoding(resolvedFile, acceptEncoding) {
|
|
90
|
+
const encoding = selectEncoding(acceptEncoding);
|
|
91
|
+
if (!encoding) {
|
|
92
|
+
return { finalFile: resolvedFile, contentEncoding: null };
|
|
93
|
+
}
|
|
94
|
+
const compressedFile = `${resolvedFile}.${encoding === "br" ? "br" : "gz"}`;
|
|
95
|
+
const compressedStat = safeStat(compressedFile);
|
|
96
|
+
if (compressedStat?.isFile()) {
|
|
97
|
+
return { finalFile: compressedFile, contentEncoding: encoding };
|
|
98
|
+
}
|
|
99
|
+
return { finalFile: resolvedFile, contentEncoding: null };
|
|
100
|
+
}
|
|
101
|
+
function setResponseCacheHeaders(res, isIndexHtml, resolvedFile) {
|
|
102
|
+
if (isIndexHtml) {
|
|
103
|
+
res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate");
|
|
104
|
+
res.setHeader("Pragma", "no-cache");
|
|
105
|
+
res.setHeader("Expires", "0");
|
|
106
|
+
}
|
|
107
|
+
else if (isHashedAsset(resolvedFile)) {
|
|
108
|
+
res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
res.setHeader("Cache-Control", "no-cache");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
export function createWebUiMiddleware(options) {
|
|
115
|
+
const { enabled, distDir, label, logger } = options;
|
|
116
|
+
const childLogger = logger.child({ module: "web-ui" });
|
|
117
|
+
if (!enabled || !distDir) {
|
|
118
|
+
childLogger.info({ enabled, hasDistDir: !!distDir }, "Daemon web UI disabled or missing dist directory");
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
childLogger.info({ distDir }, "Daemon web UI mounted");
|
|
122
|
+
}
|
|
123
|
+
return (req, res, next) => {
|
|
124
|
+
if (req.method !== "GET" && req.method !== "HEAD") {
|
|
125
|
+
next();
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (isExcludedPath(req.path)) {
|
|
129
|
+
next();
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (!enabled || !distDir) {
|
|
133
|
+
res.status(404).end();
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
serveWebUiFile({ distDir, requestPath: req.path, label, req, res });
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
function serveWebUiFile(options) {
|
|
140
|
+
const { distDir, requestPath, label, req, res } = options;
|
|
141
|
+
const target = resolveTargetFile(distDir, requestPath);
|
|
142
|
+
if (!target) {
|
|
143
|
+
res.status(404).end();
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const { resolvedFile, isIndexHtml } = target;
|
|
147
|
+
const acceptEncoding = isIndexHtml ? undefined : req.headers["accept-encoding"];
|
|
148
|
+
const { finalFile, contentEncoding } = resolveContentEncoding(resolvedFile, acceptEncoding);
|
|
149
|
+
res.setHeader("Content-Type", getContentType(resolvedFile));
|
|
150
|
+
if (contentEncoding) {
|
|
151
|
+
res.setHeader("Content-Encoding", contentEncoding);
|
|
152
|
+
res.setHeader("Vary", "Accept-Encoding");
|
|
153
|
+
}
|
|
154
|
+
setResponseCacheHeaders(res, isIndexHtml, resolvedFile);
|
|
155
|
+
if (req.method === "HEAD") {
|
|
156
|
+
res.status(200).end();
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
if (isIndexHtml) {
|
|
160
|
+
sendIndexHtml(res, finalFile, req, label);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const stream = createReadStream(finalFile);
|
|
164
|
+
stream.on("error", () => {
|
|
165
|
+
if (!res.headersSent) {
|
|
166
|
+
res.status(500).end();
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
res.end();
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
stream.pipe(res);
|
|
173
|
+
}
|
|
174
|
+
function sendIndexHtml(res, filePath, req, label) {
|
|
175
|
+
try {
|
|
176
|
+
const html = readFileSync(filePath, "utf-8");
|
|
177
|
+
const injected = injectConnectionHint(html, req, label);
|
|
178
|
+
res.status(200).send(injected);
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
res.status(500).end();
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
function serializeInlineScriptJson(value) {
|
|
185
|
+
return JSON.stringify(value)
|
|
186
|
+
.replace(/</g, "\\u003C")
|
|
187
|
+
.replace(/>/g, "\\u003E")
|
|
188
|
+
.replace(/&/g, "\\u0026");
|
|
189
|
+
}
|
|
190
|
+
function injectConnectionHint(html, req, label) {
|
|
191
|
+
const host = typeof req.headers.host === "string" ? req.headers.host : "";
|
|
192
|
+
const useTls = req.protocol === "https";
|
|
193
|
+
const hint = {
|
|
194
|
+
listen: host,
|
|
195
|
+
useTls,
|
|
196
|
+
label,
|
|
197
|
+
};
|
|
198
|
+
const script = `<script>window.__PASEO_INITIAL_DAEMON_CONNECTION__=${serializeInlineScriptJson(hint)}</script>`;
|
|
199
|
+
const headClose = /<\/head>/i;
|
|
200
|
+
if (headClose.test(html)) {
|
|
201
|
+
return html.replace(headClose, `${script}</head>`);
|
|
202
|
+
}
|
|
203
|
+
return script + html;
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=web-ui.js.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { WSOutboundMessage } from "../messages.js";
|
|
2
|
+
import type { ProcessMemoryDiagnostics } from "../process-diagnostics.js";
|
|
2
3
|
export interface WebSocketRuntimeCounters {
|
|
3
4
|
connectedAwaitingHello: number;
|
|
4
5
|
helloResumed: number;
|
|
@@ -56,6 +57,8 @@ export interface WebSocketRuntimeDiagnosticSnapshot<TRuntime = unknown, TAgents
|
|
|
56
57
|
p99Ms: number;
|
|
57
58
|
maxMs: number;
|
|
58
59
|
} | null;
|
|
60
|
+
uptimeSeconds: number;
|
|
61
|
+
memory: ProcessMemoryDiagnostics;
|
|
59
62
|
runtime: TRuntime;
|
|
60
63
|
agents: TAgents;
|
|
61
64
|
}
|
|
@@ -26,6 +26,7 @@ import { type DaemonAuthConfig } from "./auth.js";
|
|
|
26
26
|
export interface ExternalSocketMetadata {
|
|
27
27
|
transport: "relay";
|
|
28
28
|
externalSessionKey?: string;
|
|
29
|
+
relayConnectionId?: string;
|
|
29
30
|
}
|
|
30
31
|
interface WebSocketServerConfig {
|
|
31
32
|
allowedOrigins: Set<string>;
|
|
@@ -50,6 +51,7 @@ export declare class VoiceAssistantWebSocketServer {
|
|
|
50
51
|
private readonly wss;
|
|
51
52
|
private readonly pendingConnections;
|
|
52
53
|
private readonly sessions;
|
|
54
|
+
private readonly socketIdentities;
|
|
53
55
|
private readonly externalSessionsByKey;
|
|
54
56
|
private readonly serverId;
|
|
55
57
|
private readonly daemonVersion;
|
|
@@ -156,5 +158,6 @@ export declare class VoiceAssistantWebSocketServer {
|
|
|
156
158
|
private broadcastAgentAttention;
|
|
157
159
|
private broadcastTerminalAttention;
|
|
158
160
|
}
|
|
161
|
+
export declare function isWebSocketSameOrigin(origin: string | undefined, requestHost: string | null): boolean;
|
|
159
162
|
export {};
|
|
160
163
|
//# sourceMappingURL=websocket-server.d.ts.map
|