aicodeman 1.28.2 → 1.29.0

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 (183) hide show
  1. package/README.md +1 -1
  2. package/dist/attachment-registry.d.ts +20 -0
  3. package/dist/attachment-registry.d.ts.map +1 -1
  4. package/dist/attachment-registry.js +75 -10
  5. package/dist/attachment-registry.js.map +1 -1
  6. package/dist/config/cli-registry/schema.d.ts +25 -0
  7. package/dist/config/cli-registry/schema.d.ts.map +1 -1
  8. package/dist/config/cli-registry/schema.js +43 -0
  9. package/dist/config/cli-registry/schema.js.map +1 -1
  10. package/dist/config/cli-registry/stock.d.ts.map +1 -1
  11. package/dist/config/cli-registry/stock.js +157 -2
  12. package/dist/config/cli-registry/stock.js.map +1 -1
  13. package/dist/config/cli-registry/types.d.ts +60 -0
  14. package/dist/config/cli-registry/types.d.ts.map +1 -1
  15. package/dist/custom-model-hosts.d.ts +39 -0
  16. package/dist/custom-model-hosts.d.ts.map +1 -0
  17. package/dist/custom-model-hosts.js +35 -0
  18. package/dist/custom-model-hosts.js.map +1 -0
  19. package/dist/custom-model-injection-apply.d.ts +49 -0
  20. package/dist/custom-model-injection-apply.d.ts.map +1 -0
  21. package/dist/custom-model-injection-apply.js +77 -0
  22. package/dist/custom-model-injection-apply.js.map +1 -0
  23. package/dist/custom-model-injection.d.ts +79 -0
  24. package/dist/custom-model-injection.d.ts.map +1 -0
  25. package/dist/custom-model-injection.js +169 -0
  26. package/dist/custom-model-injection.js.map +1 -0
  27. package/dist/docker-hosts.d.ts +42 -0
  28. package/dist/docker-hosts.d.ts.map +1 -1
  29. package/dist/docker-hosts.js +18 -0
  30. package/dist/docker-hosts.js.map +1 -1
  31. package/dist/generated-artifact-attachments.d.ts +3 -0
  32. package/dist/generated-artifact-attachments.d.ts.map +1 -1
  33. package/dist/generated-artifact-attachments.js +18 -8
  34. package/dist/generated-artifact-attachments.js.map +1 -1
  35. package/dist/mux-interface.d.ts +7 -0
  36. package/dist/mux-interface.d.ts.map +1 -1
  37. package/dist/remote-files.d.ts +145 -0
  38. package/dist/remote-files.d.ts.map +1 -0
  39. package/dist/remote-files.js +347 -0
  40. package/dist/remote-files.js.map +1 -0
  41. package/dist/remote-hosts.d.ts +12 -0
  42. package/dist/remote-hosts.d.ts.map +1 -1
  43. package/dist/remote-hosts.js +7 -1
  44. package/dist/remote-hosts.js.map +1 -1
  45. package/dist/remote-ssh-limiter.d.ts +42 -0
  46. package/dist/remote-ssh-limiter.d.ts.map +1 -0
  47. package/dist/remote-ssh-limiter.js +84 -0
  48. package/dist/remote-ssh-limiter.js.map +1 -0
  49. package/dist/session-manager.d.ts.map +1 -1
  50. package/dist/session-manager.js +8 -1
  51. package/dist/session-manager.js.map +1 -1
  52. package/dist/session.d.ts +79 -2
  53. package/dist/session.d.ts.map +1 -1
  54. package/dist/session.js +163 -2
  55. package/dist/session.js.map +1 -1
  56. package/dist/tmux-manager.d.ts.map +1 -1
  57. package/dist/tmux-manager.js +27 -13
  58. package/dist/tmux-manager.js.map +1 -1
  59. package/dist/types/api.d.ts +6 -0
  60. package/dist/types/api.d.ts.map +1 -1
  61. package/dist/types/api.js.map +1 -1
  62. package/dist/types/session.d.ts +30 -0
  63. package/dist/types/session.d.ts.map +1 -1
  64. package/dist/types/session.js.map +1 -1
  65. package/dist/web/middleware/auth.d.ts +11 -1
  66. package/dist/web/middleware/auth.d.ts.map +1 -1
  67. package/dist/web/middleware/auth.js +69 -1
  68. package/dist/web/middleware/auth.js.map +1 -1
  69. package/dist/web/public/admin-ui.js.gz +0 -0
  70. package/dist/web/public/api-client.c9b1cddc.js.gz +0 -0
  71. package/dist/web/public/{app.78bf0bf8.js → app.556be563.js} +7 -7
  72. package/dist/web/public/app.556be563.js.br +0 -0
  73. package/dist/web/public/app.556be563.js.gz +0 -0
  74. package/dist/web/public/approvals-ui.js.gz +0 -0
  75. package/dist/web/public/constants.258b140f.js.gz +0 -0
  76. package/dist/web/public/cron-ui.js.gz +0 -0
  77. package/dist/web/public/entrance-animations.js.gz +0 -0
  78. package/dist/web/public/home-sessions.js.gz +0 -0
  79. package/dist/web/public/i18n.561ca09c.js.gz +0 -0
  80. package/dist/web/public/image-input.cd4b97c4.js.gz +0 -0
  81. package/dist/web/public/index.html +14 -7
  82. package/dist/web/public/index.html.br +0 -0
  83. package/dist/web/public/index.html.gz +0 -0
  84. package/dist/web/public/input-cjk.8bc46081.js +1 -0
  85. package/dist/web/public/input-cjk.8bc46081.js.br +0 -0
  86. package/dist/web/public/input-cjk.8bc46081.js.gz +0 -0
  87. package/dist/web/public/{keyboard-accessory.1d0dda9b.js → keyboard-accessory.2cf04f17.js} +38 -3
  88. package/dist/web/public/keyboard-accessory.2cf04f17.js.br +0 -0
  89. package/dist/web/public/keyboard-accessory.2cf04f17.js.gz +0 -0
  90. package/dist/web/public/mobile-handlers.6f354a87.js.gz +0 -0
  91. package/dist/web/public/mobile-overview.js.gz +0 -0
  92. package/dist/web/public/mobile.e9d0b53e.css.gz +0 -0
  93. package/dist/web/public/notification-manager.36ea4624.js.gz +0 -0
  94. package/dist/web/public/orchestrator-panel.js.gz +0 -0
  95. package/dist/web/public/panels-ui.5b07ad14.js.gz +0 -0
  96. package/dist/web/public/ralph-panel.6de2d0f8.js.gz +0 -0
  97. package/dist/web/public/ralph-wizard.13a1831e.js.gz +0 -0
  98. package/dist/web/public/readmymind-ui.js.gz +0 -0
  99. package/dist/web/public/respawn-ui.ff0dae4c.js.gz +0 -0
  100. package/dist/web/public/sanitize-html.bc7078d6.js.gz +0 -0
  101. package/dist/web/public/session-lineage.js.gz +0 -0
  102. package/dist/web/public/{session-ui.5d0a7b15.js → session-ui.42b81477.js} +13 -13
  103. package/dist/web/public/session-ui.42b81477.js.br +0 -0
  104. package/dist/web/public/session-ui.42b81477.js.gz +0 -0
  105. package/dist/web/public/settings-ui.e0c7f6b4.js.gz +0 -0
  106. package/dist/web/public/{styles.5d36726d.css → styles.6add175d.css} +1 -1
  107. package/dist/web/public/styles.6add175d.css.br +0 -0
  108. package/dist/web/public/{styles.5d36726d.css.gz → styles.6add175d.css.gz} +0 -0
  109. package/dist/web/public/subagent-windows.e6ca799f.js.gz +0 -0
  110. package/dist/web/public/sw.js.gz +0 -0
  111. package/dist/web/public/tab-rail-resize.42c24949.js.gz +0 -0
  112. package/dist/web/public/terminal-keycode229-recovery.6ea8fe37.js.gz +0 -0
  113. package/dist/web/public/terminal-ui.38c49244.js +2 -0
  114. package/dist/web/public/terminal-ui.38c49244.js.br +0 -0
  115. package/dist/web/public/terminal-ui.38c49244.js.gz +0 -0
  116. package/dist/web/public/ultracode-panel.js.gz +0 -0
  117. package/dist/web/public/ultracode-windows.js.gz +0 -0
  118. package/dist/web/public/upload.html.gz +0 -0
  119. package/dist/web/public/vendor/dompurify.min.js.gz +0 -0
  120. package/dist/web/public/vendor/marked.min.js.gz +0 -0
  121. package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
  122. package/dist/web/public/vendor/xterm-addon-serialize.min.js.gz +0 -0
  123. package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
  124. package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
  125. package/dist/web/public/vendor/xterm-predictive-echo.bd6882b8.js.gz +0 -0
  126. package/dist/web/public/vendor/xterm-zerolag-input.6fee72f2.js.gz +0 -0
  127. package/dist/web/public/vendor/xterm.css.gz +0 -0
  128. package/dist/web/public/vendor/xterm.min.js.gz +0 -0
  129. package/dist/web/public/voice-input.c4b51eb6.js.gz +0 -0
  130. package/dist/web/public/voice-pcm-worklet.js.gz +0 -0
  131. package/dist/web/public/webview-tabs.js +56 -4
  132. package/dist/web/public/webview-tabs.js.br +0 -0
  133. package/dist/web/public/webview-tabs.js.gz +0 -0
  134. package/dist/web/route-helpers.d.ts +20 -0
  135. package/dist/web/route-helpers.d.ts.map +1 -1
  136. package/dist/web/route-helpers.js +29 -2
  137. package/dist/web/route-helpers.js.map +1 -1
  138. package/dist/web/routes/case-routes.d.ts.map +1 -1
  139. package/dist/web/routes/case-routes.js +23 -6
  140. package/dist/web/routes/case-routes.js.map +1 -1
  141. package/dist/web/routes/custom-model-routes.d.ts +18 -0
  142. package/dist/web/routes/custom-model-routes.d.ts.map +1 -0
  143. package/dist/web/routes/custom-model-routes.js +136 -0
  144. package/dist/web/routes/custom-model-routes.js.map +1 -0
  145. package/dist/web/routes/file-routes.d.ts.map +1 -1
  146. package/dist/web/routes/file-routes.js +484 -100
  147. package/dist/web/routes/file-routes.js.map +1 -1
  148. package/dist/web/routes/index.d.ts +1 -0
  149. package/dist/web/routes/index.d.ts.map +1 -1
  150. package/dist/web/routes/index.js +1 -0
  151. package/dist/web/routes/index.js.map +1 -1
  152. package/dist/web/routes/session-routes.d.ts.map +1 -1
  153. package/dist/web/routes/session-routes.js +81 -1
  154. package/dist/web/routes/session-routes.js.map +1 -1
  155. package/dist/web/routes/ws-routes.d.ts.map +1 -1
  156. package/dist/web/routes/ws-routes.js +26 -2
  157. package/dist/web/routes/ws-routes.js.map +1 -1
  158. package/dist/web/schemas.d.ts +20 -0
  159. package/dist/web/schemas.d.ts.map +1 -1
  160. package/dist/web/schemas.js +31 -0
  161. package/dist/web/schemas.js.map +1 -1
  162. package/dist/web/server.d.ts +8 -0
  163. package/dist/web/server.d.ts.map +1 -1
  164. package/dist/web/server.js +65 -3
  165. package/dist/web/server.js.map +1 -1
  166. package/dist/web/webview-proxy.d.ts +41 -0
  167. package/dist/web/webview-proxy.d.ts.map +1 -1
  168. package/dist/web/webview-proxy.js +102 -1
  169. package/dist/web/webview-proxy.js.map +1 -1
  170. package/package.json +2 -2
  171. package/dist/web/public/app.78bf0bf8.js.br +0 -0
  172. package/dist/web/public/app.78bf0bf8.js.gz +0 -0
  173. package/dist/web/public/input-cjk.87f14251.js +0 -1
  174. package/dist/web/public/input-cjk.87f14251.js.br +0 -0
  175. package/dist/web/public/input-cjk.87f14251.js.gz +0 -0
  176. package/dist/web/public/keyboard-accessory.1d0dda9b.js.br +0 -0
  177. package/dist/web/public/keyboard-accessory.1d0dda9b.js.gz +0 -0
  178. package/dist/web/public/session-ui.5d0a7b15.js.br +0 -0
  179. package/dist/web/public/session-ui.5d0a7b15.js.gz +0 -0
  180. package/dist/web/public/styles.5d36726d.css.br +0 -0
  181. package/dist/web/public/terminal-ui.0cbe8637.js +0 -2
  182. package/dist/web/public/terminal-ui.0cbe8637.js.br +0 -0
  183. package/dist/web/public/terminal-ui.0cbe8637.js.gz +0 -0
@@ -56,6 +56,9 @@ import { subagentWatcher, } from '../subagent-watcher.js';
56
56
  import { imageWatcher } from '../image-watcher.js';
57
57
  import { workflowRunWatcher, summarizeRun } from '../workflow-run-watcher.js';
58
58
  import { attachmentRegistry, buildFileThumbnailRoute, registerExternalAttachment } from '../attachment-registry.js';
59
+ import { getCli } from '../config/cli-registry/registry.js';
60
+ import { readCustomModelHosts } from '../custom-model-hosts.js';
61
+ import { applyCustomModelInjection, customModelConfigDir, removeConfigDir } from '../custom-model-injection-apply.js';
59
62
  import { registerGeneratedArtifactAttachment } from '../generated-artifact-attachments.js';
60
63
  import { buildDetectedAttachmentHistoryItem, buildExternalAttachmentHistoryItem, } from '../session-attachment-history.js';
61
64
  import { TranscriptWatcher } from '../transcript-watcher.js';
@@ -103,12 +106,13 @@ import { SseEvent } from './sse-events.js';
103
106
  import { getLatestPlanUsage, setLatestCodexPlanUsage } from './plan-usage-latest.js';
104
107
  import { telemetrySignature } from '../usage-telemetry.js';
105
108
  import { readCodexPlanUsage, resolveCodexBinaryPath } from '../utils/codex-cli-resolver.js';
106
- import { registerAuthMiddleware, registerSecurityHeaders, registerHostGuard } from './middleware/auth.js';
109
+ import { registerAuthMiddleware, registerSecurityHeaders, registerHostGuard, isLostWebviewRootFrame, sendLostWebviewFramePage, } from './middleware/auth.js';
107
110
  import { isMultiUserMode } from '../config/multiuser.js';
108
111
  import { bootstrapInitialAdmin, hasUsers, resolveClaudeModeForUsername } from '../user-store.js';
109
112
  import { installRouteErrorHandler } from './route-error-handler.js';
110
113
  import { isExplicitlyEnabled, isLoopbackBindHost, buildHostPolicy } from './network-auth-policy.js';
111
- import { registerPushRoutes, registerTeamRoutes, registerMuxRoutes, registerFileRoutes, registerScheduledRoutes, registerHookEventRoutes, registerApprovalRoutes, registerReadMyMindRoutes, registerStatusTelemetryRoutes, registerSystemRoutes, registerCaseRoutes, registerSessionRoutes, registerRespawnRoutes, registerRalphRoutes, registerPlanRoutes, registerClipboardRoutes, registerSearchRoutes, registerOrchestratorRoutes, registerCronRoutes, registerMeRoutes, registerAdminRoutes, registerWsRoutes, registerVoiceRoutes, registerWebviewRoutes, registerTabLayoutRoutes, tryWebviewRefererFallback, } from './routes/index.js';
114
+ import { registerPushRoutes, registerTeamRoutes, registerMuxRoutes, registerFileRoutes, registerScheduledRoutes, registerHookEventRoutes, registerApprovalRoutes, registerReadMyMindRoutes, registerStatusTelemetryRoutes, registerSystemRoutes, registerCaseRoutes, registerSessionRoutes, registerRespawnRoutes, registerRalphRoutes, registerPlanRoutes, registerClipboardRoutes, registerSearchRoutes, registerOrchestratorRoutes, registerCronRoutes, registerMeRoutes, registerAdminRoutes, registerWsRoutes, registerVoiceRoutes, registerWebviewRoutes, registerTabLayoutRoutes, registerCustomModelRoutes, tryWebviewRefererFallback, } from './routes/index.js';
115
+ import { isLostWebviewFrameNavigation } from './webview-proxy.js';
112
116
  import { CronService } from '../cron/cron-service.js';
113
117
  const __dirname = dirname(fileURLToPath(import.meta.url));
114
118
  // Bounded, predictable shape for SSE client identifiers: alphanumerics, `_`, `-`.
@@ -648,7 +652,15 @@ export class WebServer extends EventEmitter {
648
652
  });
649
653
  // Security headers + CORS
650
654
  registerSecurityHeaders(this.app, this.https, this.basePath);
651
- this.app.get('/', async (_req, reply) => {
655
+ this.app.get('/', async (req, reply) => {
656
+ // A web-tab frame that reloaded on its dashboard's landing page. The proxy's
657
+ // runtime shim maps `/webview/<cap>/` to exactly `/`, so that reload asks for
658
+ // Codeman's own root as an iframe navigation, and it used to get the app
659
+ // shell rendered inside the web tab. Only the credential-free form is taken
660
+ // (nothing in Codeman frames its root; the sandboxed frame has no cookie and
661
+ // no Authorization); under a password the auth hook has answered it already.
662
+ if (isLostWebviewRootFrame(req))
663
+ return sendLostWebviewFramePage(reply);
652
664
  return reply
653
665
  .header('Cache-Control', 'no-cache')
654
666
  .type('text/html; charset=utf-8')
@@ -813,6 +825,12 @@ export class WebServer extends EventEmitter {
813
825
  // genuinely unknown `/api` paths still get the envelope below.
814
826
  if (await tryWebviewRefererFallback(req, reply, this.basePath))
815
827
  return reply;
828
+ // An authenticated web-tab frame (Basic auth, or trusted mode with a cookie)
829
+ // that navigated itself off its proxy prefix: the runtime shim masks the
830
+ // prefix so the page's router sees its own path, and a reload of that page
831
+ // lands here. The unauthenticated form is answered in the auth middleware.
832
+ if (!req.url.startsWith('/api') && isLostWebviewFrameNavigation(req))
833
+ return sendLostWebviewFramePage(reply);
816
834
  if (req.url.startsWith('/api')) {
817
835
  return reply.code(404).send(createErrorResponse(ApiErrorCode.NOT_FOUND, notFound));
818
836
  }
@@ -890,6 +908,7 @@ export class WebServer extends EventEmitter {
890
908
  registerOrchestratorRoutes(this.app, ctx);
891
909
  registerWebviewRoutes(this.app, ctx, this.basePath);
892
910
  registerTabLayoutRoutes(this.app, ctx);
911
+ registerCustomModelRoutes(this.app);
893
912
  // Cron: build the service from the same context, recompute
894
913
  // due times for any persisted jobs, then expose it to its routes.
895
914
  this.cronService = new CronService(ctx);
@@ -986,6 +1005,30 @@ export class WebServer extends EventEmitter {
986
1005
  }
987
1006
  });
988
1007
  }
1008
+ /**
1009
+ * Recovery half of Custom Model Endpoint Profiles: the env values a selection injects
1010
+ * are never persisted (they carry the API key), so they are computed again from the
1011
+ * endpoint store, through the SAME apply path the route uses. Undefined when the
1012
+ * endpoint is gone or the CLI is unregistered: the bookkeeping is still restored so
1013
+ * the selection can be cleared, and the pane keeps running on tmux's retained env.
1014
+ */
1015
+ async _rebuildCustomModelEnv(session, saved) {
1016
+ const entry = getCli(session.mode);
1017
+ if (!entry)
1018
+ return undefined;
1019
+ const endpoint = (await readCustomModelHosts(getDataDir())).find((h) => h.id === saved.endpointId);
1020
+ if (!endpoint) {
1021
+ console.warn(`[WebServer] custom-model endpoint ${saved.endpointId} no longer exists; selection kept for clearing`);
1022
+ return undefined;
1023
+ }
1024
+ try {
1025
+ return applyCustomModelInjection(entry, endpoint, saved.modelId, session.id)?.envOverrides;
1026
+ }
1027
+ catch (err) {
1028
+ console.warn('[WebServer] Failed to rebuild custom-model env on recovery:', err);
1029
+ return undefined;
1030
+ }
1031
+ }
989
1032
  /** Persists full session state including respawn config to state.json */
990
1033
  _persistSessionStateNow(session) {
991
1034
  // See session-manager.updateSessionState: __envOverrides is an internal disk-only
@@ -995,10 +1038,14 @@ export class WebServer extends EventEmitter {
995
1038
  // __attachmentHistory keeps the private (externalPath-bearing) history on disk,
996
1039
  // separate from the sanitized public attachmentHistory in toState().
997
1040
  const attachmentHistory = session.getAttachmentHistoryForPersist();
1041
+ // __customModel keeps the selection's bookkeeping (injected env KEYS, config dir,
1042
+ // launch model; never the values) so recovery can restore and later clear it.
1043
+ const customModel = session.getCustomModelForPersist();
998
1044
  const state = {
999
1045
  ...base,
1000
1046
  ...(envOverrides ? { __envOverrides: envOverrides } : {}),
1001
1047
  ...(attachmentHistory ? { __attachmentHistory: attachmentHistory } : {}),
1048
+ ...(customModel ? { __customModel: customModel } : {}),
1002
1049
  };
1003
1050
  const controller = this.respawnControllers.get(session.id);
1004
1051
  if (controller) {
@@ -1177,6 +1224,9 @@ export class WebServer extends EventEmitter {
1177
1224
  // come back to a loader whose file we deleted.
1178
1225
  if (killMux) {
1179
1226
  void removeAgentSessionPreamble(sessionId);
1227
+ // The per-session custom-model config dir carries the endpoint's API key (pi and
1228
+ // omp embed it literally); it must not outlive the session it was written for.
1229
+ removeConfigDir(customModelConfigDir(sessionId));
1180
1230
  }
1181
1231
  await session.stop(killMux);
1182
1232
  this.sessions.delete(sessionId);
@@ -1465,10 +1515,12 @@ export class WebServer extends EventEmitter {
1465
1515
  sessionId,
1466
1516
  filePath,
1467
1517
  sessionWorkingDir: session.workingDir,
1518
+ remote: session.remote,
1468
1519
  })
1469
1520
  : await registerExternalAttachment(sessionId, filePath, {
1470
1521
  sessionWorkingDir: session.workingDir,
1471
1522
  forceWorkspaceConfinement: true,
1523
+ remote: session.remote,
1472
1524
  });
1473
1525
  const record = attachmentRegistry.get(sessionId, event.attachmentId);
1474
1526
  if (record) {
@@ -2449,6 +2501,7 @@ export class WebServer extends EventEmitter {
2449
2501
  // Note: a legacy CLAUDE_CODE_EFFORT_LEVEL entry is auto-migrated to `effort`
2450
2502
  // by the Session constructor (env var would hard-lock /effort switching).
2451
2503
  const savedEnvOverrides = savedState?.__envOverrides;
2504
+ const savedCustomModel = savedState?.__customModel;
2452
2505
  // Prefer the private (externalPath-bearing) history; fall back to the
2453
2506
  // sanitized public copy for sessions persisted before that split.
2454
2507
  const savedAttachmentHistory = savedState?.__attachmentHistory ??
@@ -2509,6 +2562,15 @@ export class WebServer extends EventEmitter {
2509
2562
  // when both tabs are on screen.
2510
2563
  parentSessionId: savedState?.parentSessionId,
2511
2564
  });
2565
+ // Custom-model selection survives the restart. The tmux session still carries
2566
+ // the injected `setenv`s (that is what kept the pane on the endpoint across the
2567
+ // restart), but `_envOverrides` is rebuilt from a persist that deliberately
2568
+ // excludes them, so re-derive the values from the endpoint store and re-write
2569
+ // the isolated config dir; an endpoint that has since been deleted still gets
2570
+ // the bookkeeping restored, which is what a later clear needs to unset.
2571
+ if (savedCustomModel) {
2572
+ session.setCustomModel(savedCustomModel, await this._rebuildCustomModelEnv(session, savedCustomModel));
2573
+ }
2512
2574
  // Update session name if it was a "Restored:" placeholder or doesn't match saved name
2513
2575
  if (savedState?.name && muxSession.name !== savedState.name) {
2514
2576
  this.mux.updateSessionName(muxSession.sessionId, savedState.name);