@getpaseo/server 0.1.100 → 0.1.102-beta.2

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.
Files changed (172) hide show
  1. package/dist/scripts/supervisor.js +26 -8
  2. package/dist/server/executable-resolution/windows.js +3 -0
  3. package/dist/server/server/agent/activity-curator.d.ts +17 -0
  4. package/dist/server/server/agent/activity-curator.js +101 -24
  5. package/dist/server/server/agent/agent-manager.d.ts +10 -0
  6. package/dist/server/server/agent/agent-manager.js +69 -27
  7. package/dist/server/server/agent/agent-sdk-types.d.ts +15 -2
  8. package/dist/server/server/agent/mcp-server.d.ts +2 -45
  9. package/dist/server/server/agent/mcp-server.js +45 -1985
  10. package/dist/server/server/agent/prompt-attachments.js +6 -2
  11. package/dist/server/server/agent/provider-snapshot-manager.d.ts +12 -1
  12. package/dist/server/server/agent/provider-snapshot-manager.js +132 -42
  13. package/dist/server/server/agent/providers/acp-agent.d.ts +27 -1
  14. package/dist/server/server/agent/providers/acp-agent.js +178 -27
  15. package/dist/server/server/agent/providers/claude/agent.js +111 -24
  16. package/dist/server/server/agent/providers/claude/query.d.ts +3 -0
  17. package/dist/server/server/agent/providers/claude/query.js +4 -2
  18. package/dist/server/server/agent/providers/codex-app-server-agent.js +6 -57
  19. package/dist/server/server/agent/providers/diagnostic-utils.d.ts +1 -0
  20. package/dist/server/server/agent/providers/diagnostic-utils.js +1 -1
  21. package/dist/server/server/agent/providers/generic-acp-agent.d.ts +3 -0
  22. package/dist/server/server/agent/providers/generic-acp-agent.js +41 -23
  23. package/dist/server/server/agent/providers/mock-load-test-agent.js +12 -2
  24. package/dist/server/server/agent/providers/opencode/paths.d.ts +2 -0
  25. package/dist/server/server/agent/providers/opencode/paths.js +7 -0
  26. package/dist/server/server/agent/providers/opencode/server-manager.d.ts +2 -0
  27. package/dist/server/server/agent/providers/opencode/server-manager.js +34 -5
  28. package/dist/server/server/agent/providers/opencode-agent.d.ts +4 -0
  29. package/dist/server/server/agent/providers/opencode-agent.js +14 -2
  30. package/dist/server/server/agent/providers/pi/agent.d.ts +5 -1
  31. package/dist/server/server/agent/providers/pi/agent.js +12 -3
  32. package/dist/server/server/agent/providers/provider-image-output.d.ts +5 -0
  33. package/dist/server/server/agent/providers/provider-image-output.js +61 -1
  34. package/dist/server/server/agent/tools/paseo-tools.d.ts +48 -0
  35. package/dist/server/server/agent/tools/paseo-tools.js +2119 -0
  36. package/dist/server/server/agent/tools/types.d.ts +36 -0
  37. package/dist/server/server/agent/tools/types.js +2 -0
  38. package/dist/server/server/bootstrap.d.ts +7 -1
  39. package/dist/server/server/bootstrap.js +89 -62
  40. package/dist/server/server/config.d.ts +2 -0
  41. package/dist/server/server/config.js +57 -1
  42. package/dist/server/server/daemon-worker.js +19 -7
  43. package/dist/server/server/lifecycle-reasons.d.ts +4 -0
  44. package/dist/server/server/lifecycle-reasons.js +6 -0
  45. package/dist/server/server/persisted-config.d.ts +12 -0
  46. package/dist/server/server/persisted-config.js +18 -2
  47. package/dist/server/server/process-diagnostics.d.ts +17 -0
  48. package/dist/server/server/process-diagnostics.js +22 -0
  49. package/dist/server/server/relay-transport.js +1 -0
  50. package/dist/server/server/resolve-worktree-creation-intent.js +3 -1
  51. package/dist/server/server/session/agent-updates/agent-updates-service.d.ts +59 -0
  52. package/dist/server/server/session/agent-updates/agent-updates-service.js +220 -0
  53. package/dist/server/server/session/checkout/checkout-session.d.ts +13 -15
  54. package/dist/server/server/session/checkout/checkout-session.js +18 -16
  55. package/dist/server/server/session/checkout/git-metadata-generator.d.ts +53 -0
  56. package/dist/server/server/session/checkout/git-metadata-generator.js +159 -0
  57. package/dist/server/server/session/daemon/daemon-self-update-session-controller.d.ts +32 -0
  58. package/dist/server/server/session/daemon/daemon-self-update-session-controller.js +88 -0
  59. package/dist/server/server/session/daemon/daemon-self-updater.d.ts +32 -0
  60. package/dist/server/server/session/daemon/daemon-self-updater.js +56 -0
  61. package/dist/server/server/session/daemon/daemon-session.d.ts +26 -0
  62. package/dist/server/server/session/daemon/daemon-session.js +50 -0
  63. package/dist/server/server/session/daemon/diagnostics.d.ts +41 -0
  64. package/dist/server/server/session/daemon/diagnostics.js +431 -0
  65. package/dist/server/server/session/daemon/install-origin.d.ts +7 -0
  66. package/dist/server/server/session/daemon/install-origin.js +64 -0
  67. package/dist/server/server/session/daemon/npm-global-cli.d.ts +29 -0
  68. package/dist/server/server/session/daemon/npm-global-cli.js +98 -0
  69. package/dist/server/server/session/git-mutation/git-mutation-service.d.ts +34 -0
  70. package/dist/server/server/session/git-mutation/git-mutation-service.js +71 -0
  71. package/dist/server/server/session/provider/provider-catalog-session.js +8 -4
  72. package/dist/server/server/session/workspace-git-observer/workspace-git-observer-service.d.ts +36 -0
  73. package/dist/server/server/session/workspace-git-observer/workspace-git-observer-service.js +134 -0
  74. package/dist/server/server/session/workspace-provisioning/workspace-provisioning-service.d.ts +34 -0
  75. package/dist/server/server/session/workspace-provisioning/workspace-provisioning-service.js +190 -0
  76. package/dist/server/server/session/workspace-scripts/workspace-scripts-service.d.ts +41 -0
  77. package/dist/server/server/session/workspace-scripts/workspace-scripts-service.js +100 -0
  78. package/dist/server/server/session.d.ts +12 -54
  79. package/dist/server/server/session.js +187 -970
  80. package/dist/server/server/speech/providers/openai/config.d.ts +1 -2
  81. package/dist/server/server/speech/providers/openai/config.js +13 -9
  82. package/dist/server/server/speech/providers/openai/runtime.js +2 -16
  83. package/dist/server/server/speech/providers/openai/stt.d.ts +1 -0
  84. package/dist/server/server/speech/providers/openai/stt.js +4 -2
  85. package/dist/server/server/speech/providers/openai/tts.d.ts +1 -0
  86. package/dist/server/server/speech/providers/openai/tts.js +1 -0
  87. package/dist/server/server/web-ui.d.ts +10 -0
  88. package/dist/server/server/web-ui.js +205 -0
  89. package/dist/server/server/websocket/runtime-metrics.d.ts +23 -0
  90. package/dist/server/server/websocket-server.d.ts +4 -2
  91. package/dist/server/server/websocket-server.js +215 -52
  92. package/dist/server/server/worktree-bootstrap.d.ts +1 -1
  93. package/dist/server/server/worktree-branch-name-generator.js +3 -1
  94. package/dist/server/services/quota-fetcher/manifest.js +5 -0
  95. package/dist/server/services/quota-fetcher/providers/minimax.d.ts +29 -0
  96. package/dist/server/services/quota-fetcher/providers/minimax.js +227 -0
  97. package/dist/server/terminal/agent-hooks/agent-hook-installer.js +2 -2
  98. package/dist/server/utils/checkout-git.js +203 -25
  99. package/dist/server/utils/directory-suggestions.js +1 -4
  100. package/dist/server/utils/path.d.ts +2 -0
  101. package/dist/server/utils/path.js +13 -0
  102. package/dist/server/utils/worktree.d.ts +1 -0
  103. package/dist/server/utils/worktree.js +92 -11
  104. package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css +1 -0
  105. package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css.br +0 -0
  106. package/dist/server/web-ui/_expo/static/css/xterm-3bb1704bf6cb0876640973dc0244b4cb.css.gz +0 -0
  107. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-b01555c9b42665a03988c0a0032ef528.js +1 -0
  108. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-b01555c9b42665a03988c0a0032ef528.js.br +0 -0
  109. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-b01555c9b42665a03988c0a0032ef528.js.gz +0 -0
  110. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-648388eca5c510b496e1eddf523f70ff.js +1 -0
  111. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-648388eca5c510b496e1eddf523f70ff.js.br +0 -0
  112. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-648388eca5c510b496e1eddf523f70ff.js.gz +0 -0
  113. package/dist/server/web-ui/_expo/static/js/web/index-0ebbea2cd337f0c0680fdb3f8d4d5af3.js +16157 -0
  114. package/dist/server/web-ui/_expo/static/js/web/index-0ebbea2cd337f0c0680fdb3f8d4d5af3.js.br +0 -0
  115. package/dist/server/web-ui/_expo/static/js/web/index-0ebbea2cd337f0c0680fdb3f8d4d5af3.js.gz +0 -0
  116. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-c64fa2416284927857a39087fd8d1332.js +1 -0
  117. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-c64fa2416284927857a39087fd8d1332.js.br +0 -0
  118. package/dist/server/web-ui/_expo/static/js/web/indexeddb-attachment-store-c64fa2416284927857a39087fd8d1332.js.gz +0 -0
  119. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-a9784226715772edf87ef36c596599c2.js +3 -0
  120. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-a9784226715772edf87ef36c596599c2.js.br +0 -0
  121. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-a9784226715772edf87ef36c596599c2.js.gz +0 -0
  122. package/dist/server/web-ui/apple-touch-icon.png +0 -0
  123. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/back-icon-mask.0a328cd9c1afd0afe8e3b1ec5165b1b4.png +0 -0
  124. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/back-icon.35ba0eaec5a4f5ed12ca16fabeae451d.png +0 -0
  125. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55.png +0 -0
  126. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@2x.png +0 -0
  127. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@3x.png +0 -0
  128. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@4x.png +0 -0
  129. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7.png +0 -0
  130. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@2x.png +0 -0
  131. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@3x.png +0 -0
  132. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@4x.png +0 -0
  133. package/dist/server/web-ui/assets/__node_modules/@react-navigation/elements/lib/module/assets/search-icon.286d67d3f74808a60a78d3ebf1a5fb57.png +0 -0
  134. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/arrow_down.017bc6ba3fc25503e5eb5e53826d48a8.png +0 -0
  135. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/error.d1ea1496f9057eb392d5bbf3732a61b7.png +0 -0
  136. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/file.19eeb73b9593a38f8e9f418337fc7d10.png +0 -0
  137. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/forward.d8b800c443b8972542883e0b9de2bdc6.png +0 -0
  138. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/pkg.ab19f4cbc543357183a20571f68380a3.png +0 -0
  139. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/sitemap.412dd9275b6b48ad28f5e3d81bb1f626.png +0 -0
  140. package/dist/server/web-ui/assets/__node_modules/expo-router/assets/unmatched.20e71bdf79e3a97bf55fd9e164041578.png +0 -0
  141. package/dist/server/web-ui/assets/assets/images/editor-apps/antigravity.6e91a685c33435e0b466a56db86cf141.png +0 -0
  142. package/dist/server/web-ui/assets/assets/images/editor-apps/cursor.c31d6bce4fe9aadc3fe59962f4c4fcf3.png +0 -0
  143. package/dist/server/web-ui/assets/assets/images/editor-apps/file-explorer.3e15e8f72c825c85ce336bcb0cdef776.png +0 -0
  144. package/dist/server/web-ui/assets/assets/images/editor-apps/finder.7f68fc2c475621a672e1be09309d5567.png +0 -0
  145. package/dist/server/web-ui/assets/assets/images/editor-apps/vscode.832bdb4c685d930f1c864c793703600b.png +0 -0
  146. package/dist/server/web-ui/assets/assets/images/editor-apps/webstorm.aa5dc2cd8c20cc0a155c4c5c5ab3c5f5.png +0 -0
  147. package/dist/server/web-ui/assets/assets/images/editor-apps/zed.f3a670b7f9aa226da4fe53fb86f1abbd.png +0 -0
  148. package/dist/server/web-ui/assets/assets/images/favicon-dark-attention.882b3a27dcb2073e9e31b334f9ed9728.png +0 -0
  149. package/dist/server/web-ui/assets/assets/images/favicon-dark-running.8112342ff0d39e047a7f8d4fad9402f3.png +0 -0
  150. package/dist/server/web-ui/assets/assets/images/favicon-dark.8005ed36ac07a5a7c60de25780897bd4.png +0 -0
  151. package/dist/server/web-ui/assets/assets/images/favicon-light-attention.882b3a27dcb2073e9e31b334f9ed9728.png +0 -0
  152. package/dist/server/web-ui/assets/assets/images/favicon-light-running.8112342ff0d39e047a7f8d4fad9402f3.png +0 -0
  153. package/dist/server/web-ui/assets/assets/images/favicon-light.8005ed36ac07a5a7c60de25780897bd4.png +0 -0
  154. package/dist/server/web-ui/assets/assets/images/notification-icon.3bf81d33ddbf380606bdd248ba83e158.png +0 -0
  155. package/dist/server/web-ui/favicon.ico +0 -0
  156. package/dist/server/web-ui/index.html +90 -0
  157. package/dist/server/web-ui/index.html.br +0 -0
  158. package/dist/server/web-ui/index.html.gz +0 -0
  159. package/dist/server/web-ui/manifest.json +27 -0
  160. package/dist/server/web-ui/manifest.json.br +0 -0
  161. package/dist/server/web-ui/manifest.json.gz +0 -0
  162. package/dist/server/web-ui/metadata.json +1 -0
  163. package/dist/server/web-ui/metadata.json.br +1 -0
  164. package/dist/server/web-ui/metadata.json.gz +0 -0
  165. package/dist/server/web-ui/pwa-icon-192.png +0 -0
  166. package/dist/server/web-ui/pwa-icon-512.png +0 -0
  167. package/dist/server/web-ui/robots.txt +2 -0
  168. package/dist/src/executable-resolution/windows.js +3 -0
  169. package/dist/src/server/persisted-config.js +18 -2
  170. package/package.json +7 -7
  171. package/dist/server/server/speech/providers/openai/realtime-transcription-session.d.ts +0 -42
  172. package/dist/server/server/speech/providers/openai/realtime-transcription-session.js +0 -168
@@ -0,0 +1,36 @@
1
+ import type { z } from "zod";
2
+ export interface PaseoToolExecutionContext {
3
+ signal?: AbortSignal;
4
+ }
5
+ export interface PaseoToolResult {
6
+ content: Array<{
7
+ type: string;
8
+ text?: string;
9
+ [key: string]: unknown;
10
+ }>;
11
+ structuredContent?: unknown;
12
+ isError?: boolean;
13
+ }
14
+ export interface PaseoToolConfig {
15
+ title?: string;
16
+ description?: string;
17
+ inputSchema?: z.ZodRawShape | z.ZodType;
18
+ outputSchema?: z.ZodRawShape | z.ZodType;
19
+ }
20
+ export interface PaseoToolDefinition extends PaseoToolConfig {
21
+ name: string;
22
+ description: string;
23
+ handler: (input: unknown, context: PaseoToolExecutionContext) => Promise<PaseoToolResult>;
24
+ }
25
+ export interface PaseoToolCatalog {
26
+ tools: ReadonlyMap<string, PaseoToolDefinition>;
27
+ getTool(name: string): PaseoToolDefinition | undefined;
28
+ executeTool(name: string, input: unknown, context?: PaseoToolExecutionContext): Promise<PaseoToolResult>;
29
+ }
30
+ export interface PaseoToolRuntimeContext {
31
+ callerAgentId?: string;
32
+ enableVoiceTools?: boolean;
33
+ voiceOnly?: boolean;
34
+ }
35
+ export type PaseoToolCatalogFactory = (context: PaseoToolRuntimeContext) => PaseoToolCatalog | Promise<PaseoToolCatalog>;
36
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -44,11 +44,12 @@ export type DaemonLifecycleIntent = {
44
44
  type: "shutdown";
45
45
  clientId: string;
46
46
  requestId: string;
47
+ reason: string;
47
48
  } | {
48
49
  type: "restart";
49
50
  clientId: string;
50
51
  requestId: string;
51
- reason?: string;
52
+ reason: string;
52
53
  };
53
54
  export interface PaseoDaemonConfig {
54
55
  listen: string;
@@ -57,6 +58,7 @@ export interface PaseoDaemonConfig {
57
58
  corsAllowedOrigins: string[];
58
59
  allowedHosts?: HostnamesConfig;
59
60
  hostnames?: HostnamesConfig;
61
+ trustedProxies?: true | string[];
60
62
  mcpEnabled?: boolean;
61
63
  mcpInjectIntoAgents?: boolean;
62
64
  autoArchiveAfterMerge?: boolean;
@@ -77,6 +79,10 @@ export interface PaseoDaemonConfig {
77
79
  publicBaseUrl: string | null;
78
80
  standaloneListen: string | null;
79
81
  };
82
+ webUi?: {
83
+ enabled: boolean;
84
+ distDir: string | null;
85
+ };
80
86
  appBaseUrl?: string;
81
87
  auth?: DaemonAuthConfig;
82
88
  openai?: PaseoOpenAIConfig;
@@ -83,6 +83,7 @@ import { AgentManager } from "./agent/agent-manager.js";
83
83
  import { AgentStorage } from "./agent/agent-storage.js";
84
84
  import { attachAgentStoragePersistence } from "./persistence-hooks.js";
85
85
  import { createAgentMcpServer } from "./agent/mcp-server.js";
86
+ import { createPaseoToolCatalog, } from "./agent/tools/paseo-tools.js";
86
87
  import { ProviderSnapshotManager } from "./agent/provider-snapshot-manager.js";
87
88
  import { bootstrapWorkspaceRegistries } from "./workspace-registry-bootstrap.js";
88
89
  import { WorkspaceReconciliationService } from "./workspace-reconciliation-service.js";
@@ -112,6 +113,7 @@ import { createManagedProcessRegistry, createSystemManagedProcessTable, } from "
112
113
  import { terminateWithTreeKill } from "../utils/tree-kill.js";
113
114
  import { isHostnameAllowed } from "./hostnames.js";
114
115
  import { createRequireBearerMiddleware, isAgentMcpRequestAuthorized, } from "./auth.js";
116
+ import { createWebUiMiddleware } from "./web-ui.js";
115
117
  const MAX_MCP_DEBUG_BATCH_ITEMS = 10;
116
118
  const REDACTED_LOG_VALUE = "[redacted]";
117
119
  const DOWNLOAD_OPEN_FLAGS = process.platform === "win32" ? constants.O_RDONLY : constants.O_RDONLY | constants.O_NOFOLLOW;
@@ -229,6 +231,17 @@ async function reconcileManagedProcessLedger(managedProcesses, logger) {
229
231
  logger.info(reapResult, "Managed helper process ledger reconciled");
230
232
  }
231
233
  }
234
+ function mountWebUi(app, config, logger) {
235
+ app.use(createWebUiMiddleware({
236
+ enabled: config.webUi?.enabled ?? false,
237
+ distDir: config.webUi?.distDir ?? null,
238
+ label: getHostname(),
239
+ logger,
240
+ }));
241
+ }
242
+ function resolveExpressTrustProxySetting(config) {
243
+ return config.trustedProxies ?? ["loopback"];
244
+ }
232
245
  export async function createPaseoDaemon(config, rootLogger) {
233
246
  const logger = rootLogger.child({ module: "bootstrap" });
234
247
  const bootstrapStart = performance.now();
@@ -278,6 +291,7 @@ export async function createPaseoDaemon(config, rootLogger) {
278
291
  const agentMcpAuthToken = randomUUID();
279
292
  const listenTarget = parseListenString(config.listen);
280
293
  const app = express();
294
+ app.set("trust proxy", resolveExpressTrustProxySetting(config));
281
295
  let boundListenTarget = null;
282
296
  let workspaceRegistry = null;
283
297
  const terminalManager = createConfiguredTerminalManager({
@@ -362,6 +376,11 @@ export async function createPaseoDaemon(config, rootLogger) {
362
376
  });
363
377
  // Local, harmless, and token-gated; deliberately skips daemon auth.
364
378
  app.post("/api/terminal-activity", express.json(), createTerminalActivityRouteHandler(terminalManager));
379
+ // Serve the bundled browser web UI when enabled. Mounted after service-proxy
380
+ // classification and host/CORS handling, but before daemon bearer auth, so
381
+ // static app files load without the daemon password while API/WebSocket calls
382
+ // remain protected.
383
+ mountWebUi(app, config, logger);
365
384
  app.use(createRequireBearerMiddleware(config.auth, (context) => {
366
385
  logger.warn(context, "Rejected HTTP request with invalid daemon password");
367
386
  }));
@@ -612,73 +631,79 @@ export async function createPaseoDaemon(config, rootLogger) {
612
631
  clearWorkspaceArchiving: clearWorkspaceArchivingExternal,
613
632
  emitWorkspaceUpdatesForWorkspaceIds: emitWorkspaceUpdatesExternal,
614
633
  });
634
+ const createPaseoWorktreeForTools = async (input, serviceOptions) => {
635
+ return createPaseoWorktreeWorkflow({
636
+ paseoHome: config.paseoHome,
637
+ worktreesRoot: config.worktreesRoot,
638
+ createPaseoWorktree: async (workflowInput, workflowOptions) => {
639
+ return createRegisteredPaseoWorktree(workflowInput, {
640
+ github,
641
+ ...(workflowOptions?.resolveDefaultBranch
642
+ ? {
643
+ resolveDefaultBranch: workflowOptions.resolveDefaultBranch,
644
+ }
645
+ : {}),
646
+ projectRegistry,
647
+ workspaceRegistry,
648
+ workspaceGitService,
649
+ });
650
+ },
651
+ warmWorkspaceGitData: async (workspace) => {
652
+ await Promise.all(wsServer
653
+ ?.listActiveSessions()
654
+ .map((session) => session.warmWorkspaceGitDataForWorkspace(workspace)) ?? []);
655
+ },
656
+ emitWorkspaceUpdateForWorkspaceId: async (workspaceId) => {
657
+ await emitWorkspaceUpdatesExternal([workspaceId]);
658
+ },
659
+ cacheWorkspaceSetupSnapshot: () => { },
660
+ emit: emitExternalSessionMessage,
661
+ sessionLogger: logger,
662
+ terminalManager,
663
+ archiveWorkspaceRecord: archiveWorkspaceRecordExternal,
664
+ serviceProxy,
665
+ scriptRuntimeStore,
666
+ getDaemonTcpPort: () => (boundListenTarget?.type === "tcp" ? boundListenTarget.port : null),
667
+ getDaemonTcpHost: () => (boundListenTarget?.type === "tcp" ? boundListenTarget.host : null),
668
+ serviceProxyPublicBaseUrl,
669
+ onScriptsChanged: null,
670
+ }, input, serviceOptions);
671
+ };
672
+ const createAgentToolHostDependencies = (runtime) => ({
673
+ agentManager,
674
+ agentStorage,
675
+ terminalManager,
676
+ getDaemonTcpPort: () => (boundListenTarget?.type === "tcp" ? boundListenTarget.port : null),
677
+ scheduleService,
678
+ providerSnapshotManager,
679
+ github,
680
+ workspaceGitService,
681
+ findWorkspaceIdForCwd: findWorkspaceIdForCwdExternal,
682
+ listActiveWorkspaces: listActiveWorkspacesExternal,
683
+ archiveWorkspaceRecord: archiveWorkspaceRecordExternal,
684
+ emitWorkspaceUpdatesForWorkspaceIds: emitWorkspaceUpdatesExternal,
685
+ markWorkspaceArchiving: markWorkspaceArchivingExternal,
686
+ clearWorkspaceArchiving: clearWorkspaceArchivingExternal,
687
+ ensureWorkspaceForCreate: ensureWorkspaceForCreateExternal,
688
+ createPaseoWorktree: createPaseoWorktreeForTools,
689
+ paseoHome: config.paseoHome,
690
+ worktreesRoot: config.worktreesRoot,
691
+ callerAgentId: runtime.callerAgentId,
692
+ enableVoiceTools: runtime.enableVoiceTools,
693
+ voiceOnly: runtime.voiceOnly,
694
+ resolveSpeakHandler: (agentId) => wsServer?.resolveVoiceSpeakHandler(agentId) ?? null,
695
+ resolveCallerContext: (agentId) => wsServer?.resolveVoiceCallerContext(agentId) ?? null,
696
+ logger,
697
+ });
698
+ const createAgentToolCatalog = (runtime) => createPaseoToolCatalog(createAgentToolHostDependencies(runtime));
699
+ agentManager.setPaseoToolCatalogFactory(createAgentToolCatalog);
700
+ agentManager.setPaseoToolsEnabled(config.mcpInjectIntoAgents !== false);
615
701
  const mcpEnabled = config.mcpEnabled ?? true;
616
702
  let agentMcpBaseUrl = null;
617
703
  if (mcpEnabled) {
618
704
  const agentMcpRoute = "/mcp/agents";
619
705
  const createAgentMcpSession = async (callerAgentId) => {
620
- const agentMcpServer = await createAgentMcpServer({
621
- agentManager,
622
- agentStorage,
623
- terminalManager,
624
- getDaemonTcpPort: () => (boundListenTarget?.type === "tcp" ? boundListenTarget.port : null),
625
- scheduleService,
626
- providerSnapshotManager,
627
- github,
628
- workspaceGitService,
629
- findWorkspaceIdForCwd: findWorkspaceIdForCwdExternal,
630
- listActiveWorkspaces: listActiveWorkspacesExternal,
631
- archiveWorkspaceRecord: archiveWorkspaceRecordExternal,
632
- emitWorkspaceUpdatesForWorkspaceIds: emitWorkspaceUpdatesExternal,
633
- markWorkspaceArchiving: markWorkspaceArchivingExternal,
634
- clearWorkspaceArchiving: clearWorkspaceArchivingExternal,
635
- ensureWorkspaceForCreate: ensureWorkspaceForCreateExternal,
636
- createPaseoWorktree: async (input, serviceOptions) => {
637
- return createPaseoWorktreeWorkflow({
638
- paseoHome: config.paseoHome,
639
- worktreesRoot: config.worktreesRoot,
640
- createPaseoWorktree: async (workflowInput, workflowOptions) => {
641
- return createRegisteredPaseoWorktree(workflowInput, {
642
- github,
643
- ...(workflowOptions?.resolveDefaultBranch
644
- ? {
645
- resolveDefaultBranch: workflowOptions.resolveDefaultBranch,
646
- }
647
- : {}),
648
- projectRegistry,
649
- workspaceRegistry,
650
- workspaceGitService,
651
- });
652
- },
653
- warmWorkspaceGitData: async (workspace) => {
654
- await Promise.all(wsServer
655
- ?.listActiveSessions()
656
- .map((session) => session.warmWorkspaceGitDataForWorkspace(workspace)) ?? []);
657
- },
658
- emitWorkspaceUpdateForWorkspaceId: async (workspaceId) => {
659
- await emitWorkspaceUpdatesExternal([workspaceId]);
660
- },
661
- cacheWorkspaceSetupSnapshot: () => { },
662
- emit: emitExternalSessionMessage,
663
- sessionLogger: logger,
664
- terminalManager,
665
- archiveWorkspaceRecord: archiveWorkspaceRecordExternal,
666
- serviceProxy,
667
- scriptRuntimeStore,
668
- getDaemonTcpPort: () => boundListenTarget?.type === "tcp" ? boundListenTarget.port : null,
669
- getDaemonTcpHost: () => boundListenTarget?.type === "tcp" ? boundListenTarget.host : null,
670
- serviceProxyPublicBaseUrl,
671
- onScriptsChanged: null,
672
- }, input, serviceOptions);
673
- },
674
- paseoHome: config.paseoHome,
675
- worktreesRoot: config.worktreesRoot,
676
- callerAgentId,
677
- enableVoiceTools: false,
678
- resolveSpeakHandler: (agentId) => wsServer?.resolveVoiceSpeakHandler(agentId) ?? null,
679
- resolveCallerContext: (agentId) => wsServer?.resolveVoiceCallerContext(agentId) ?? null,
680
- logger,
681
- });
706
+ const agentMcpServer = await createAgentMcpServer(createAgentToolHostDependencies({ callerAgentId }));
682
707
  // Stateless mode: each HTTP request builds a fresh server + transport that is
683
708
  // torn down when the response closes, so no per-session state is retained between
684
709
  // requests. The agent control plane only lists and calls tools, neither of which
@@ -810,8 +835,10 @@ export async function createPaseoDaemon(config, rootLogger) {
810
835
  const mcpBaseUrl = mcpEnabled ? createAgentMcpBaseUrl(boundListenTarget) : null;
811
836
  agentMcpBaseUrl = config.mcpInjectIntoAgents === false ? null : mcpBaseUrl;
812
837
  agentManager.setMcpBaseUrl(agentMcpBaseUrl);
838
+ agentManager.setPaseoToolsEnabled(config.mcpInjectIntoAgents !== false);
813
839
  daemonConfigStore.onFieldChange("mcp.injectIntoAgents", (value) => {
814
840
  agentManager.setMcpBaseUrl(value ? mcpBaseUrl : null);
841
+ agentManager.setPaseoToolsEnabled(value !== false);
815
842
  });
816
843
  daemonConfigStore.onFieldChange("appendSystemPrompt", (value) => {
817
844
  agentManager.setAppendSystemPrompt(typeof value === "string" ? value : "");
@@ -1,11 +1,13 @@
1
1
  import type { PaseoDaemonConfig } from "./bootstrap.js";
2
2
  import { type HostnamesConfig } from "./hostnames.js";
3
+ export declare function resolveBundledWebUiDistDir(moduleUrl?: string | URL): string;
3
4
  export type CliConfigOverrides = Partial<{
4
5
  listen: string;
5
6
  relayEnabled: boolean;
6
7
  relayUseTls: boolean;
7
8
  mcpEnabled: boolean;
8
9
  mcpInjectIntoAgents: boolean;
10
+ webUiEnabled: boolean;
9
11
  hostnames: HostnamesConfig;
10
12
  }>;
11
13
  export declare function loadConfig(paseoHome: string, options?: {
@@ -1,4 +1,5 @@
1
1
  import path from "node:path";
2
+ import { fileURLToPath } from "node:url";
2
3
  import { resolvePaseoNodeEnv } from "./paseo-env.js";
3
4
  import { z } from "zod";
4
5
  import { expandTilde } from "../utils/path.js";
@@ -11,6 +12,20 @@ import { mergeHostnames, parseHostnamesEnv } from "./hostnames.js";
11
12
  const DEFAULT_PORT = 6767;
12
13
  const DEFAULT_RELAY_ENDPOINT = "relay.paseo.sh:443";
13
14
  const DEFAULT_APP_BASE_URL = "https://app.paseo.sh";
15
+ const DEFAULT_TRUSTED_PROXIES = ["loopback"];
16
+ export function resolveBundledWebUiDistDir(moduleUrl = import.meta.url) {
17
+ const moduleDir = path.dirname(fileURLToPath(moduleUrl));
18
+ if (path.basename(moduleDir) === "server" && path.basename(path.dirname(moduleDir)) === "src") {
19
+ return path.resolve(moduleDir, "..", "..", "dist", "server", "web-ui");
20
+ }
21
+ if (path.basename(moduleDir) === "server" &&
22
+ path.basename(path.dirname(moduleDir)) === "server" &&
23
+ path.basename(path.dirname(path.dirname(moduleDir))) === "dist") {
24
+ return path.resolve(moduleDir, "..", "web-ui");
25
+ }
26
+ return path.resolve(moduleDir, "web-ui");
27
+ }
28
+ const BUNDLED_WEB_UI_DIST_DIR = resolveBundledWebUiDistDir();
14
29
  function parseBooleanEnv(value) {
15
30
  if (value === undefined) {
16
31
  return undefined;
@@ -137,6 +152,21 @@ function resolveServiceProxyConfig(env, persisted) {
137
152
  : null;
138
153
  return { publicBaseUrl, standaloneListen };
139
154
  }
155
+ function resolveWebUiConfig(paseoHome, env, cli, persisted) {
156
+ const enabled = cli?.webUiEnabled ??
157
+ parseBooleanEnv(env.PASEO_WEB_UI_ENABLED) ??
158
+ persisted.features?.webUi?.enabled ??
159
+ false;
160
+ const rawDistDir = env.PASEO_WEB_UI_DIST_DIR ?? persisted.features?.webUi?.distDir;
161
+ const trimmedDistDir = rawDistDir?.trim();
162
+ const distDir = trimmedDistDir
163
+ ? path.resolve(path.isAbsolute(trimmedDistDir) ? trimmedDistDir : paseoHome, trimmedDistDir)
164
+ : BUNDLED_WEB_UI_DIST_DIR;
165
+ return {
166
+ enabled,
167
+ distDir,
168
+ };
169
+ }
140
170
  function resolveVoiceLlmConfig(env, persisted) {
141
171
  const envVoiceLlmProvider = parseOptionalVoiceLlmProvider(env.PASEO_VOICE_LLM_PROVIDER);
142
172
  const persistedVoiceLlmProvider = parseOptionalVoiceLlmProvider(persisted.features?.voiceMode?.llm?.provider);
@@ -153,6 +183,28 @@ function resolveCorsAllowedOrigins(env, persisted) {
153
183
  const persistedCorsOrigins = persisted.daemon?.cors?.allowedOrigins ?? [];
154
184
  return Array.from(new Set([...persistedCorsOrigins, ...envCorsOrigins].filter((s) => s.length > 0)));
155
185
  }
186
+ function parseTrustedProxiesEnv(value) {
187
+ const trimmed = value?.trim();
188
+ if (!trimmed) {
189
+ return undefined;
190
+ }
191
+ const normalized = trimmed.toLowerCase();
192
+ if (["1", "true", "yes", "on"].includes(normalized)) {
193
+ return true;
194
+ }
195
+ if (["0", "false", "no", "off"].includes(normalized)) {
196
+ return [];
197
+ }
198
+ return trimmed
199
+ .split(",")
200
+ .map((proxy) => proxy.trim())
201
+ .filter((proxy) => proxy.length > 0);
202
+ }
203
+ function resolveTrustedProxiesConfig(env, persisted) {
204
+ return (parseTrustedProxiesEnv(env.PASEO_TRUSTED_PROXIES) ??
205
+ persisted.daemon?.trustedProxies ??
206
+ DEFAULT_TRUSTED_PROXIES);
207
+ }
156
208
  // PASEO_LISTEN can be:
157
209
  // - host:port (TCP)
158
210
  // - /path/to/socket (Unix socket)
@@ -198,6 +250,7 @@ function resolveStaticLoadConfigSettings(env, cli, persisted) {
198
250
  parseHostnamesEnv(env.PASEO_HOSTNAMES ?? env.PASEO_ALLOWED_HOSTS),
199
251
  cli?.hostnames,
200
252
  ]),
253
+ trustedProxies: resolveTrustedProxiesConfig(env, persisted),
201
254
  appBaseUrl: env.PASEO_APP_BASE_URL ?? persisted.app?.baseUrl ?? DEFAULT_APP_BASE_URL,
202
255
  };
203
256
  }
@@ -205,7 +258,7 @@ export function loadConfig(paseoHome, options) {
205
258
  const env = options?.env ?? process.env;
206
259
  const persisted = loadPersistedConfig(paseoHome);
207
260
  const listen = resolveListenAddress(env, options?.cli, persisted);
208
- const { mcpEnabled, mcpInjectIntoAgents, autoArchiveAfterMerge, appendSystemPrompt, terminalProfiles, hostnames, appBaseUrl, } = resolveStaticLoadConfigSettings(env, options?.cli, persisted);
261
+ const { mcpEnabled, mcpInjectIntoAgents, autoArchiveAfterMerge, appendSystemPrompt, terminalProfiles, hostnames, trustedProxies, appBaseUrl, } = resolveStaticLoadConfigSettings(env, options?.cli, persisted);
209
262
  const relay = resolveRelayConfig({
210
263
  env,
211
264
  persisted,
@@ -213,6 +266,7 @@ export function loadConfig(paseoHome, options) {
213
266
  cliRelayUseTls: options?.cli?.relayUseTls,
214
267
  });
215
268
  const serviceProxy = resolveServiceProxyConfig(env, persisted);
269
+ const webUi = resolveWebUiConfig(paseoHome, env, options?.cli, persisted);
216
270
  const { openai, speech } = resolveSpeechConfig({
217
271
  paseoHome,
218
272
  env,
@@ -226,6 +280,7 @@ export function loadConfig(paseoHome, options) {
226
280
  worktreesRoot: resolveWorktreesRoot(paseoHome, persisted),
227
281
  corsAllowedOrigins: resolveCorsAllowedOrigins(env, persisted),
228
282
  hostnames,
283
+ trustedProxies,
229
284
  mcpEnabled,
230
285
  mcpInjectIntoAgents,
231
286
  autoArchiveAfterMerge,
@@ -243,6 +298,7 @@ export function loadConfig(paseoHome, options) {
243
298
  relayUseTls: relay.useTls,
244
299
  relayPublicUseTls: relay.publicUseTls,
245
300
  serviceProxy,
301
+ webUi,
246
302
  appBaseUrl,
247
303
  auth: resolveAuthConfig(env, persisted),
248
304
  openai,
@@ -4,6 +4,7 @@ import { createPaseoDaemon } from "./bootstrap.js";
4
4
  import { loadConfig } from "./config.js";
5
5
  import { resolvePaseoHome } from "./paseo-home.js";
6
6
  import { createRootLogger } from "./logger.js";
7
+ import { getProcessDiagnostics } from "./process-diagnostics.js";
7
8
  process.title = "Paseo Daemon";
8
9
  function isPidAlive(pid) {
9
10
  try {
@@ -60,6 +61,12 @@ function applyCliFlagOverrides(config) {
60
61
  if (process.argv.includes("--no-inject-mcp")) {
61
62
  config.mcpInjectIntoAgents = false;
62
63
  }
64
+ if (process.argv.includes("--web-ui")) {
65
+ config.webUi = { ...(config.webUi ?? { distDir: null }), enabled: true };
66
+ }
67
+ if (process.argv.includes("--no-web-ui")) {
68
+ config.webUi = { ...(config.webUi ?? { distDir: null }), enabled: false };
69
+ }
63
70
  }
64
71
  async function main() {
65
72
  const { paseoHome, logger, config } = bootstrapFromEnvironment();
@@ -77,11 +84,12 @@ async function main() {
77
84
  });
78
85
  };
79
86
  const beginShutdown = (signal, options) => {
87
+ const reason = options?.reason ?? `worker_received_${signal}`;
80
88
  if (!shutdownPromise) {
81
- logger.info(`${signal} received, shutting down gracefully...`);
89
+ logger.info({ signal, reason, ...getProcessDiagnostics() }, `${signal} received, shutting down gracefully...`);
82
90
  shutdownPromise = (async () => {
83
91
  const forceExit = setTimeout(() => {
84
- logger.warn("Forcing shutdown - HTTP server didn't close in time");
92
+ logger.warn({ signal, reason, ...getProcessDiagnostics() }, "Forcing shutdown - HTTP server didn't close in time");
85
93
  process.exit(1);
86
94
  }, 10000);
87
95
  try {
@@ -103,7 +111,7 @@ async function main() {
103
111
  })();
104
112
  }
105
113
  else {
106
- logger.info(`${signal} received while shutdown is already in progress`);
114
+ logger.info({ signal, reason, ...getProcessDiagnostics() }, `${signal} received while shutdown is already in progress`);
107
115
  }
108
116
  installExitHook();
109
117
  };
@@ -122,11 +130,11 @@ async function main() {
122
130
  };
123
131
  const handleLifecycleIntent = (intent) => {
124
132
  if (intent.type === "shutdown") {
125
- logger.warn({ clientId: intent.clientId, requestId: intent.requestId }, "Shutdown requested via websocket");
126
- if (sendSupervisorLifecycleMessage({ type: "paseo:shutdown" })) {
133
+ logger.warn({ clientId: intent.clientId, requestId: intent.requestId, reason: intent.reason }, "Shutdown requested via websocket");
134
+ if (sendSupervisorLifecycleMessage({ type: "paseo:shutdown", reason: intent.reason })) {
127
135
  return;
128
136
  }
129
- beginShutdown("shutdown lifecycle intent");
137
+ beginShutdown("shutdown lifecycle intent", { reason: intent.reason });
130
138
  return;
131
139
  }
132
140
  logger.warn({ clientId: intent.clientId, requestId: intent.requestId, reason: intent.reason }, "Restart requested via websocket");
@@ -136,7 +144,10 @@ async function main() {
136
144
  })) {
137
145
  return;
138
146
  }
139
- beginShutdown("restart lifecycle intent", { successExitCode: 0 });
147
+ beginShutdown("restart lifecycle intent", {
148
+ reason: intent.reason,
149
+ successExitCode: 0,
150
+ });
140
151
  };
141
152
  const installSupervisorLivenessGuard = () => {
142
153
  if (typeof process.send !== "function") {
@@ -152,6 +163,7 @@ async function main() {
152
163
  supervisorExitRequested = true;
153
164
  writeWorkerLifecycleLog(paseoHome, "Supervisor liveness lost; worker exiting", {
154
165
  reason,
166
+ ...getProcessDiagnostics(),
155
167
  supervisorPid,
156
168
  currentParentPid: process.ppid,
157
169
  ipcConnected: typeof process.connected === "boolean" ? process.connected : null,
@@ -0,0 +1,4 @@
1
+ export declare const CLIENT_SHUTDOWN_RPC_REASON = "client_shutdown_rpc";
2
+ export declare const DEFAULT_CLIENT_RESTART_RPC_REASON = "client_restart_rpc";
3
+ export declare function normalizeClientRestartRpcReason(reason: string | undefined): string;
4
+ //# sourceMappingURL=lifecycle-reasons.d.ts.map
@@ -0,0 +1,6 @@
1
+ export const CLIENT_SHUTDOWN_RPC_REASON = "client_shutdown_rpc";
2
+ export const DEFAULT_CLIENT_RESTART_RPC_REASON = "client_restart_rpc";
3
+ export function normalizeClientRestartRpcReason(reason) {
4
+ return reason?.trim() || DEFAULT_CLIENT_RESTART_RPC_REASON;
5
+ }
6
+ //# sourceMappingURL=lifecycle-reasons.js.map
@@ -19,6 +19,7 @@ export declare const PersistedConfigSchema: z.ZodObject<{
19
19
  listen: z.ZodOptional<z.ZodString>;
20
20
  hostnames: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<true>, z.ZodArray<z.ZodString>]>>;
21
21
  allowedHosts: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<true>, z.ZodArray<z.ZodString>]>>;
22
+ trustedProxies: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<true>, z.ZodArray<z.ZodString>]>>;
22
23
  mcp: z.ZodOptional<z.ZodObject<{
23
24
  enabled: z.ZodOptional<z.ZodBoolean>;
24
25
  injectIntoAgents: z.ZodOptional<z.ZodBoolean>;
@@ -54,6 +55,7 @@ export declare const PersistedConfigSchema: z.ZodObject<{
54
55
  }, z.core.$strict>, z.ZodTransform<{
55
56
  listen?: string | undefined;
56
57
  hostnames?: true | string[] | undefined;
58
+ trustedProxies?: true | string[] | undefined;
57
59
  mcp?: {
58
60
  [x: string]: unknown;
59
61
  enabled?: boolean | undefined;
@@ -92,6 +94,7 @@ export declare const PersistedConfigSchema: z.ZodObject<{
92
94
  listen?: string | undefined;
93
95
  hostnames?: true | string[] | undefined;
94
96
  allowedHosts?: true | string[] | undefined;
97
+ trustedProxies?: true | string[] | undefined;
95
98
  mcp?: {
96
99
  [x: string]: unknown;
97
100
  enabled?: boolean | undefined;
@@ -133,6 +136,11 @@ export declare const PersistedConfigSchema: z.ZodObject<{
133
136
  providers: z.ZodOptional<z.ZodObject<{
134
137
  openai: z.ZodOptional<z.ZodObject<{
135
138
  apiKey: z.ZodOptional<z.ZodString>;
139
+ voice: z.ZodOptional<z.ZodObject<{
140
+ apiKey: z.ZodOptional<z.ZodString>;
141
+ baseUrl: z.ZodOptional<z.ZodString>;
142
+ }, z.core.$strict>>;
143
+ baseUrl: z.ZodOptional<z.ZodString>;
136
144
  }, z.core.$strict>>;
137
145
  local: z.ZodOptional<z.ZodObject<{
138
146
  modelsDir: z.ZodOptional<z.ZodString>;
@@ -236,6 +244,10 @@ export declare const PersistedConfigSchema: z.ZodObject<{
236
244
  speed: z.ZodOptional<z.ZodNumber>;
237
245
  }, z.core.$strict>>;
238
246
  }, z.core.$strict>>;
247
+ webUi: z.ZodOptional<z.ZodObject<{
248
+ enabled: z.ZodOptional<z.ZodBoolean>;
249
+ distDir: z.ZodOptional<z.ZodString>;
250
+ }, z.core.$strict>>;
239
251
  }, z.core.$strict>>;
240
252
  log: z.ZodOptional<z.ZodObject<{
241
253
  level: z.ZodOptional<z.ZodEnum<{
@@ -34,9 +34,17 @@ const LogConfigSchema = z
34
34
  .optional(),
35
35
  })
36
36
  .strict();
37
- const ProviderCredentialsSchema = z
37
+ const OpenAiVoiceProviderSchema = z
38
+ .object({
39
+ apiKey: z.string().trim().min(1).optional(),
40
+ baseUrl: z.string().trim().min(1).optional(),
41
+ })
42
+ .strict();
43
+ const OpenAiProviderSchema = z
38
44
  .object({
39
45
  apiKey: z.string().min(1).optional(),
46
+ voice: OpenAiVoiceProviderSchema.optional(),
47
+ baseUrl: z.string().trim().min(1).optional(),
40
48
  })
41
49
  .strict();
42
50
  const LocalSpeechProviderSchema = z
@@ -46,7 +54,7 @@ const LocalSpeechProviderSchema = z
46
54
  .strict();
47
55
  const ProvidersSchema = z
48
56
  .object({
49
- openai: ProviderCredentialsSchema.optional(),
57
+ openai: OpenAiProviderSchema.optional(),
50
58
  local: LocalSpeechProviderSchema.optional(),
51
59
  })
52
60
  .strict();
@@ -118,6 +126,12 @@ const FeatureVoiceModeSchema = z
118
126
  .optional(),
119
127
  })
120
128
  .strict();
129
+ const FeatureWebUiSchema = z
130
+ .object({
131
+ enabled: z.boolean().optional(),
132
+ distDir: z.string().min(1).optional(),
133
+ })
134
+ .strict();
121
135
  const StructuredGenerationProviderConfigSchema = z
122
136
  .object({
123
137
  provider: z.string().min(1),
@@ -179,6 +193,7 @@ export const PersistedConfigSchema = z
179
193
  listen: z.string().optional(),
180
194
  hostnames: z.union([z.literal(true), z.array(z.string())]).optional(),
181
195
  allowedHosts: z.union([z.literal(true), z.array(z.string())]).optional(),
196
+ trustedProxies: z.union([z.literal(true), z.array(z.string())]).optional(),
182
197
  mcp: z
183
198
  .object({
184
199
  enabled: z.boolean().optional(),
@@ -244,6 +259,7 @@ export const PersistedConfigSchema = z
244
259
  .object({
245
260
  dictation: FeatureDictationSchema.optional(),
246
261
  voiceMode: FeatureVoiceModeSchema.optional(),
262
+ webUi: FeatureWebUiSchema.optional(),
247
263
  })
248
264
  .strict()
249
265
  .optional(),
@@ -0,0 +1,17 @@
1
+ export interface ProcessMemoryDiagnostics {
2
+ rss: number;
3
+ heapTotal: number;
4
+ heapUsed: number;
5
+ external: number;
6
+ arrayBuffers: number;
7
+ }
8
+ export interface ProcessDiagnostics {
9
+ pid: number;
10
+ ppid: number;
11
+ uptimeSeconds: number;
12
+ memory: ProcessMemoryDiagnostics;
13
+ }
14
+ export declare function getProcessMemoryDiagnostics(): ProcessMemoryDiagnostics;
15
+ export declare function getProcessUptimeSeconds(): number;
16
+ export declare function getProcessDiagnostics(): ProcessDiagnostics;
17
+ //# sourceMappingURL=process-diagnostics.d.ts.map
@@ -0,0 +1,22 @@
1
+ export function getProcessMemoryDiagnostics() {
2
+ const memory = process.memoryUsage();
3
+ return {
4
+ rss: memory.rss,
5
+ heapTotal: memory.heapTotal,
6
+ heapUsed: memory.heapUsed,
7
+ external: memory.external,
8
+ arrayBuffers: memory.arrayBuffers,
9
+ };
10
+ }
11
+ export function getProcessUptimeSeconds() {
12
+ return Math.round(process.uptime() * 1000) / 1000;
13
+ }
14
+ export function getProcessDiagnostics() {
15
+ return {
16
+ pid: process.pid,
17
+ ppid: process.ppid,
18
+ uptimeSeconds: getProcessUptimeSeconds(),
19
+ memory: getProcessMemoryDiagnostics(),
20
+ };
21
+ }
22
+ //# sourceMappingURL=process-diagnostics.js.map
@@ -335,6 +335,7 @@ export function startRelayTransport({ logger, attachSocket, relayEndpoint, relay
335
335
  const externalMetadata = {
336
336
  transport: "relay",
337
337
  externalSessionKey: `session:${connectionId}`,
338
+ relayConnectionId: connectionId,
338
339
  };
339
340
  if (daemonKeyPair) {
340
341
  void attachEncryptedSocket(socket, daemonKeyPair, relayLogger.child({ connectionId }), attachSocket, externalMetadata);