@qredence/fleet 0.5.9 → 0.5.11

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 (121) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/web/client/assets/agent-activity-CwMDU7aP.js +1 -0
  3. package/dist/web/client/assets/artifacts-panel-CQmFEF_H.js +1 -0
  4. package/dist/web/client/assets/{button-BV9NafmI.js → button-BR2WWrFo.js} +1 -1
  5. package/dist/web/client/assets/{chat-command-palette-C_HgND2N.js → chat-command-palette-CmHTS3rs.js} +1 -1
  6. package/dist/web/client/assets/{chat-DdPRGn-U.js → chat-yh02zgA7.js} +2 -2
  7. package/dist/web/client/assets/{citations-BQ_pr_9_.js → citations-C_tPOJE_.js} +1 -1
  8. package/dist/web/client/assets/{command-Cx-UYeQ9.js → command-DPfiaYUL.js} +1 -1
  9. package/dist/web/client/assets/{dialog-Dh7WpGIu.js → dialog-BEZuZhzk.js} +1 -1
  10. package/dist/web/client/assets/{fleet-message-queue-DPBMIZSU.js → fleet-message-queue-DUz6Hfrf.js} +1 -1
  11. package/dist/web/client/assets/{fleet-pi-tool-renderer-DMjrKLi2.js → fleet-pi-tool-renderer-BEDIO3al.js} +4 -4
  12. package/dist/web/client/assets/fleet-reasoning-panel-CbkO7u-v.js +1 -0
  13. package/dist/web/client/assets/{fleet-subagent-list-BnRnrWKS.js → fleet-subagent-list-iKUtLJKZ.js} +1 -1
  14. package/dist/web/client/assets/fleet-tool-timeline-C8heL7ae.js +1 -0
  15. package/dist/web/client/assets/{fork-picker-dialog-CAhWx0G5.js → fork-picker-dialog-ByBOGVsa.js} +1 -1
  16. package/dist/web/client/assets/globals-B_I1Eq1u.css +2 -0
  17. package/dist/web/client/assets/horizontal-resize-qK6eRhIG.js +1 -0
  18. package/dist/web/client/assets/{index-CwtZA4hF.js → index-C1zOjrMK.js} +3 -3
  19. package/dist/web/client/assets/{input-Bol3TP4v.js → input-0wwjWjKq.js} +1 -1
  20. package/dist/web/client/assets/{input-group-D5gi9zBK.js → input-group-BFDsCVS9.js} +1 -1
  21. package/dist/web/client/assets/{ipython-tool-BrMePqD-.js → ipython-tool-ldJ9F1Cw.js} +1 -1
  22. package/dist/web/client/assets/model-selector-list-DsKTuAgS.js +1 -0
  23. package/dist/web/client/assets/{notify-BnNaNaBU.js → notify-DgMKgZZW.js} +1 -1
  24. package/dist/web/client/assets/{openui-renderer-nuOkzdau.js → openui-renderer-J3dhPpL4.js} +5 -5
  25. package/dist/web/client/assets/prompt-input-qPIXZ-Rb.js +1 -0
  26. package/dist/web/client/assets/prompt-suggestions-Cc--lSNR.js +1 -0
  27. package/dist/web/client/assets/{provider-catalog-CO1GxLYe.js → provider-catalog-D8G66gwc.js} +1 -1
  28. package/dist/web/client/assets/{provider-label-B0E-wWFV.js → provider-label-Dpr7djG9.js} +1 -1
  29. package/dist/web/client/assets/repl-panel-DsPX04Xr.js +1 -0
  30. package/dist/web/client/assets/{resources-panel-Bo8dfUdm.js → resources-panel-D867-goy.js} +1 -1
  31. package/dist/web/client/assets/right-panel-registry-DewpBWHM.js +2 -0
  32. package/dist/web/client/assets/routes-vNkVToAF.js +16 -0
  33. package/dist/web/client/assets/safe-storage-s25GrfpH.js +1 -0
  34. package/dist/web/client/assets/session-insights-panel-YnaXvTpi.js +1 -0
  35. package/dist/web/client/assets/settings-dialog-B-v4me3Y.js +1 -0
  36. package/dist/web/client/assets/skeleton-loaders-C9vHwAYV.js +1 -0
  37. package/dist/web/client/assets/{subagent-chat-panel-Ck06wcIJ.js → subagent-chat-panel-DkVUumrP.js} +1 -1
  38. package/dist/web/client/assets/subagent-transcript-D8wmQxXe.js +1 -0
  39. package/dist/web/client/assets/subagents-panel-BMp2Ego0.js +1 -0
  40. package/dist/web/client/assets/{surfaces-cW-gp56p.js → surfaces-DI-U-_2a.js} +1 -1
  41. package/dist/web/client/assets/{switch-J2Lvo_tF.js → switch-9rTeg6J6.js} +1 -1
  42. package/dist/web/client/assets/{toast-BzAKULar.js → toast-Bt9p2OL4.js} +1 -1
  43. package/dist/web/client/assets/tool-result-DfnPN0FQ.js +4 -0
  44. package/dist/web/client/assets/ui-preferences-CImQGZm_.js +1 -0
  45. package/dist/web/client/assets/virtualized-turn-list-DMJENRY0.js +6 -0
  46. package/dist/web/client/assets/{workspace-panel-DI1W3ce9.js → workspace-panel-G6yMpKJ8.js} +1 -1
  47. package/dist/web/client/bundle-budget.json +6 -6
  48. package/dist/web/server/{_tanstack-start-manifest_v-DkghjPW8-5E6WBVI6.js → _tanstack-start-manifest_v-po4woX6g-AUGCOEZ2.js} +20 -19
  49. package/dist/web/server/{agent-activity-B-JMvecd-SLE3GGY2.js → agent-activity-CS2rbF_C-A3R26CYH.js} +2 -2
  50. package/dist/web/server/{artifacts-panel-D20iI9ud-YGBYV6NF.js → artifacts-panel-8GGUCtOd-X5TNKTY2.js} +17 -17
  51. package/dist/web/server/{chat-command-palette-DmDvAEZe-CONFK6YH.js → chat-command-palette-Dgl5tqWn-72LLEWUD.js} +7 -7
  52. package/dist/web/server/{chunk-K5ESTT4A.js → chunk-7MDZVLIY.js} +11 -3
  53. package/dist/web/server/{chunk-EBCYJSBR.js → chunk-7SD2ZSEA.js} +3 -3
  54. package/dist/web/server/{chunk-BTXNB4CP.js → chunk-ABBWBBSS.js} +13 -13
  55. package/dist/web/server/{chunk-VMYYWXF4.js → chunk-AGFRJQZ7.js} +2 -2
  56. package/dist/web/server/{chunk-FZMWPQNE.js → chunk-BXWAUTTH.js} +4 -4
  57. package/dist/web/server/{chunk-54II5QXQ.js → chunk-ETTDO4UO.js} +6 -3
  58. package/dist/web/server/{chunk-EHNIN245.js → chunk-GETSIVNU.js} +5 -5
  59. package/dist/web/server/{chunk-NRDG2ISJ.js → chunk-GGT2ZKDB.js} +49 -49
  60. package/dist/web/server/{chunk-X2R5YPQZ.js → chunk-IJPCV6DH.js} +3 -2
  61. package/dist/web/server/{chunk-TFHXOWFX.js → chunk-JQDLJ7KI.js} +20 -20
  62. package/dist/web/server/{chunk-VHBFU4TG.js → chunk-JUROEEWM.js} +43 -14
  63. package/dist/web/server/{chunk-WQDG5ZM2.js → chunk-KOUEJ3NU.js} +2 -2
  64. package/dist/web/server/{chunk-JICJWC33.js → chunk-LZ4Q5KUJ.js} +10 -10
  65. package/dist/web/server/{chunk-W6IZDM2G.js → chunk-MIW4LJTV.js} +4 -4
  66. package/dist/web/server/{chunk-2TRF62K5.js → chunk-N6NOTURM.js} +3 -3
  67. package/dist/web/server/{chunk-5XX7RKJ6.js → chunk-NXJ32VFR.js} +5 -5
  68. package/dist/web/server/{chunk-EFNPNSDO.js → chunk-O4OTWWPF.js} +7 -7
  69. package/dist/web/server/{chunk-X6RKK47S.js → chunk-P6UMR32I.js} +2 -2
  70. package/dist/web/server/{chunk-QJQZLBLU.js → chunk-P7H2OPKF.js} +3 -3
  71. package/dist/web/server/{chunk-MLPLZVON.js → chunk-RNOJACWQ.js} +54 -30
  72. package/dist/web/server/chunk-SZJUXVWG.js +40 -0
  73. package/dist/web/server/{chunk-ZCJXHV2R.js → chunk-UAPNEWCA.js} +4 -4
  74. package/dist/web/server/{chunk-WVBBA2VV.js → chunk-WILCIZYU.js} +195 -11
  75. package/dist/web/server/{chunk-FED63ZHU.js → chunk-WKV2Z4KO.js} +10 -5
  76. package/dist/web/server/{chunk-TGZIE2T6.js → chunk-WM4PUT6M.js} +4 -4
  77. package/dist/web/server/{chunk-56NGD3FN.js → chunk-WYL2DW5R.js} +2 -2
  78. package/dist/web/server/{chunk-IMK45Q23.js → chunk-XKKXXG6N.js} +3 -3
  79. package/dist/web/server/{chunk-ANL4B775.js → chunk-XLNCWZMZ.js} +2 -2
  80. package/dist/web/server/{chunk-ZVL6TBG5.js → chunk-YKVGQBZA.js} +13 -9
  81. package/dist/web/server/{chunk-IFHABBJO.js → chunk-YXXRP3NS.js} +18 -10
  82. package/dist/web/server/{fleet-message-queue-BvMcWtLo-6CMMI73U.js → fleet-message-queue-j0DCU5Xy-5HKBHMPV.js} +5 -5
  83. package/dist/web/server/{fleet-pi-tool-renderer-CgbmlIoe-7MSJLEGU.js → fleet-pi-tool-renderer-umKunT3K-O4GBH35V.js} +5 -5
  84. package/dist/web/server/{fleet-reasoning-panel-D_K48UOT-GN2PA6KT.js → fleet-reasoning-panel-BxC2COxi-GPLMQSTT.js} +9 -9
  85. package/dist/web/server/{fleet-subagent-list-5luKtpds-3OTVFHJQ.js → fleet-subagent-list-CpSYzCIq-JDH2LHSS.js} +1 -1
  86. package/dist/web/server/{fleet-tool-timeline-DwRqQgOj-HUFLGMDV.js → fleet-tool-timeline-IB36_PB2-XJENTO6I.js} +1 -1
  87. package/dist/web/server/{fork-picker-dialog-DfSRzUI5-EBRK5HNO.js → fork-picker-dialog-DlINz9UQ-UWIXFDJX.js} +5 -5
  88. package/dist/web/server/{model-selector-list-wCp4_UWC-2NQUCAM3.js → model-selector-list-OYnzNbyu-HBGCNF2L.js} +10 -10
  89. package/dist/web/server/{openui-renderer-BNLpfzyj-JUPJXUWF.js → openui-renderer-Cj7kfqyL-EKJ6JTTQ.js} +9 -9
  90. package/dist/web/server/{prompt-suggestions-BOmHi4-J-C563CHFU.js → prompt-suggestions-D4AEEY7K-RZSP7PWV.js} +3 -3
  91. package/dist/web/server/{repl-panel-yyxhwe4c-7U6HXYPS.js → repl-panel-D5KsoJik-BQKO53JO.js} +9 -9
  92. package/dist/web/server/{resources-panel-j4fAIi9g-5C267IXV.js → resources-panel-CE5pD4vy-V5FXBTYC.js} +2 -2
  93. package/dist/web/server/{router-dnEmu1cU-LUH74TAC.js → router-Ci1wxI7I-E2AYMNON.js} +255 -78
  94. package/dist/web/server/{routes-Ci5_8lws-F54KB46D.js → routes-CRpm9-Sa-IYK6MUJO.js} +720 -549
  95. package/dist/web/server/server.js +2 -2
  96. package/dist/web/server/{session-insights-panel-BHZyKDTo-LRMAMA3O.js → session-insights-panel-CUhdgvRt-VB2HUCQP.js} +4 -4
  97. package/dist/web/server/{settings-dialog-CdFpyzR--JVYIS5OD.js → settings-dialog-BvkgNflv-GPJ6COQO.js} +22 -18
  98. package/dist/web/server/{subagent-chat-panel-DVgf-whR-6G2ASMGU.js → subagent-chat-panel-CMuvW9Sd-M5TEEGQW.js} +14 -14
  99. package/dist/web/server/{subagents-panel-D2CN0IYy-3L6ZNQ3Q.js → subagents-panel-DgfB6_Yy-4INEPE3Y.js} +16 -16
  100. package/dist/web/server/{workspace-panel-BOs-58Cv-SWQBMZSB.js → workspace-panel-bpwj-Veu-Q2CEJMN4.js} +4 -3
  101. package/package.json +1 -1
  102. package/dist/web/client/assets/agent-activity-CDcDNVC6.js +0 -1
  103. package/dist/web/client/assets/artifacts-panel-N4k9VcJr.js +0 -1
  104. package/dist/web/client/assets/fleet-reasoning-panel-MtbSdoCv.js +0 -1
  105. package/dist/web/client/assets/fleet-tool-timeline-COzPrwr8.js +0 -1
  106. package/dist/web/client/assets/generative-text-renderer-CzwNIs3b.js +0 -6
  107. package/dist/web/client/assets/globals-C7ovVTh2.css +0 -2
  108. package/dist/web/client/assets/horizontal-resize-Bl3AyBJg.js +0 -1
  109. package/dist/web/client/assets/model-selector-list-CJY9pyt2.js +0 -1
  110. package/dist/web/client/assets/prompt-input-BpuTiX7Z.js +0 -1
  111. package/dist/web/client/assets/prompt-suggestions-CXM6knMK.js +0 -1
  112. package/dist/web/client/assets/repl-panel-BDQ5MEgV.js +0 -1
  113. package/dist/web/client/assets/right-panel-registry-DOyEvIMD.js +0 -2
  114. package/dist/web/client/assets/routes-DkefU9yA.js +0 -16
  115. package/dist/web/client/assets/session-insights-panel-CQdT90Op.js +0 -1
  116. package/dist/web/client/assets/settings-dialog-B6rt69m_.js +0 -1
  117. package/dist/web/client/assets/skeleton-loaders-DjGv9LLA.js +0 -1
  118. package/dist/web/client/assets/subagent-transcript-BwCv3nTL.js +0 -1
  119. package/dist/web/client/assets/subagents-panel-BkOorzzy.js +0 -1
  120. package/dist/web/client/assets/tool-result-Cp13oeRn.js +0 -4
  121. package/dist/web/client/assets/ui-preferences-DUEFuJFj.js +0 -1
@@ -12,18 +12,19 @@ import {
12
12
  domAnimation,
13
13
  initAnalytics,
14
14
  isServer
15
- } from "./chunk-VHBFU4TG.js";
15
+ } from "./chunk-JUROEEWM.js";
16
16
  import {
17
17
  DEFAULT_UI_PREFERENCES,
18
18
  isModelPatternEnabled,
19
19
  readUiPreferences
20
- } from "./chunk-54II5QXQ.js";
20
+ } from "./chunk-ETTDO4UO.js";
21
21
  import {
22
22
  Toaster
23
- } from "./chunk-WQDG5ZM2.js";
23
+ } from "./chunk-KOUEJ3NU.js";
24
24
  import {
25
25
  redactSessionLabelSecrets
26
26
  } from "./chunk-QK4CHLVV.js";
27
+ import "./chunk-SZJUXVWG.js";
27
28
  import "./chunk-TNL4YV63.js";
28
29
  import {
29
30
  drag,
@@ -36,7 +37,7 @@ import {
36
37
  CardHeader,
37
38
  CardTitle,
38
39
  validateAndNormalizeOpenUIHtmlArtifact
39
- } from "./chunk-K5ESTT4A.js";
40
+ } from "./chunk-7MDZVLIY.js";
40
41
  import {
41
42
  ChatNewRequestSchema,
42
43
  ChatOpenUIArtifactUpsertRequestSchema,
@@ -54,8 +55,9 @@ import {
54
55
  ProjectRenameRequestSchema,
55
56
  SessionIdSchema,
56
57
  UploadedAttachmentSchema,
58
+ ZodError,
57
59
  external_exports
58
- } from "./chunk-NRDG2ISJ.js";
60
+ } from "./chunk-GGT2ZKDB.js";
59
61
  import {
60
62
  KNOWN_PROVIDERS,
61
63
  OPENAI_CHAT_COMPLETIONS_PROVIDER_ID,
@@ -70,7 +72,7 @@ import {
70
72
  toInstanceSlug,
71
73
  toOccInstanceId
72
74
  } from "./chunk-RJOANOT4.js";
73
- import "./chunk-JICJWC33.js";
75
+ import "./chunk-LZ4Q5KUJ.js";
74
76
  import "./chunk-JBLHIEVG.js";
75
77
  import "./chunk-C5X6G26O.js";
76
78
  import "./chunk-HFQZLPU2.js";
@@ -89,7 +91,7 @@ import "./chunk-JDCCC7A7.js";
89
91
  import "./chunk-L547YHC4.js";
90
92
  import "./chunk-MLKGABMK.js";
91
93
 
92
- // web/app/dist/server/assets/router-dnEmu1cU.js
94
+ // web/app/dist/server/assets/router-Ci1wxI7I.js
93
95
  import { useEffect, useLayoutEffect } from "react";
94
96
  import { jsx, jsxs } from "react/jsx-runtime";
95
97
  import { basename, dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
@@ -123,7 +125,8 @@ function NotFoundPage({ title = "404", description = "The requested page could n
123
125
  })
124
126
  });
125
127
  }
126
- var globals_default = "/assets/globals-C7ovVTh2.css";
128
+ var globals_default = "/assets/globals-B_I1Eq1u.css";
129
+ var inter_latin_wght_normal_default = "/assets/inter-latin-wght-normal-Dx4kXJAl.woff2";
127
130
  function makeQueryClient() {
128
131
  return new QueryClient({ defaultOptions: { queries: {
129
132
  staleTime: 6e4,
@@ -152,6 +155,13 @@ var Route$27 = createRootRoute({
152
155
  rel: "stylesheet",
153
156
  href: globals_default
154
157
  },
158
+ {
159
+ rel: "preload",
160
+ href: inter_latin_wght_normal_default,
161
+ as: "font",
162
+ type: "font/woff2",
163
+ crossOrigin: "anonymous"
164
+ },
155
165
  {
156
166
  rel: "icon",
157
167
  href: "/favicon-dark.svg",
@@ -200,7 +210,7 @@ function RootDocument({ children }) {
200
210
  ] })]
201
211
  });
202
212
  }
203
- var $$splitComponentImporter = () => import("./routes-Ci5_8lws-F54KB46D.js");
213
+ var $$splitComponentImporter = () => import("./routes-CRpm9-Sa-IYK6MUJO.js");
204
214
  var Route$26 = createFileRoute("/")({ component: lazyRouteComponent($$splitComponentImporter, "component") });
205
215
  var ManagedAttachmentValidationError = class extends Error {
206
216
  status;
@@ -1950,6 +1960,34 @@ var defaultPersistence = {
1950
1960
  };
1951
1961
  var TOKEN_TTL_MS = 6e5;
1952
1962
  var MAX_DIRECTORY_ENTRIES = 200;
1963
+ var SENSITIVE_HOME_DIRECTORY_NAMES = [
1964
+ ".ssh",
1965
+ ".gnupg",
1966
+ ".aws",
1967
+ ".pki",
1968
+ ".docker",
1969
+ ".kube",
1970
+ ".azure",
1971
+ ".gcloud",
1972
+ ".gsutil",
1973
+ ".password-store",
1974
+ ".config/gh"
1975
+ ];
1976
+ function isSameOrWithin(candidate, ancestor) {
1977
+ return candidate === ancestor || candidate.startsWith(`${ancestor}${sep}`);
1978
+ }
1979
+ async function assertAllowedProjectDirectory(canonical) {
1980
+ if (dirname(canonical) === canonical) throw new Error("Project path must not be a filesystem root");
1981
+ const home = await realpath(homedir()).catch(() => homedir());
1982
+ if (canonical === home) throw new Error("Project path must not be the home directory");
1983
+ for (const name of SENSITIVE_HOME_DIRECTORY_NAMES) if (isSameOrWithin(canonical, join(home, name))) throw new Error("Project path must not be a credentials directory");
1984
+ const xdgConfigHome = process.env.XDG_CONFIG_HOME;
1985
+ if (xdgConfigHome && isAbsolute(xdgConfigHome)) {
1986
+ const canonicalConfigHome = await realpath(xdgConfigHome).catch(() => resolve(xdgConfigHome));
1987
+ if (isSameOrWithin(canonical, join(canonicalConfigHome, "gh"))) throw new Error("Project path must not be a credentials directory");
1988
+ }
1989
+ if (isSameOrWithin(canonical, await realpath("/etc").catch(() => "/etc"))) throw new Error("Project path must not be a system directory");
1990
+ }
1953
1991
  var ProjectRegistryPersistenceError = class extends Error {
1954
1992
  constructor(operation, cause) {
1955
1993
  super(`Could not ${operation}. Please try again.`, { cause });
@@ -2047,6 +2085,7 @@ var ProjectRegistry = class {
2047
2085
  if (!candidate || !isAbsolute(candidate)) throw new Error("Project path must be absolute");
2048
2086
  const canonical = await realpath(candidate);
2049
2087
  if (!(await stat(canonical)).isDirectory()) throw new Error("Project path must be a directory");
2088
+ await assertAllowedProjectDirectory(canonical);
2050
2089
  return canonical;
2051
2090
  }
2052
2091
  #findByPath(canonicalPath) {
@@ -2167,7 +2206,7 @@ var ProjectRegistry = class {
2167
2206
  if (options.token) {
2168
2207
  const token = this.#directoryTokens.get(options.token);
2169
2208
  if (!token || token.expiresAt < Date.now()) throw new Error("Directory token expired");
2170
- path = token.path;
2209
+ path = await this.#canonicalDirectory(token.path);
2171
2210
  } else path = await this.#canonicalDirectory(options.path ?? this.#initialPath);
2172
2211
  const entries = await readdir(path, { withFileTypes: true });
2173
2212
  const directories = [];
@@ -4689,6 +4728,13 @@ function fallbackSessionPath(connectionState, cwd) {
4689
4728
  const sessionDir = connectionState.sessionDir ?? sessionDirectoryForCwd(cwd);
4690
4729
  return resolve(sessionDir, `${connectionState.sessionId}.jsonl`);
4691
4730
  }
4731
+ var SessionExportPathError = class extends Error {
4732
+ status = 400;
4733
+ constructor() {
4734
+ super("Export path must stay inside the session project directory");
4735
+ this.name = "SessionExportPathError";
4736
+ }
4737
+ };
4692
4738
  function findSessionTreeEntry(nodes, entryId) {
4693
4739
  for (const node of nodes) {
4694
4740
  if (node.entry.id === entryId) return node.entry;
@@ -5094,10 +5140,7 @@ var PrimeBridge = class {
5094
5140
  async resumeSessionById(sessionId, requestedProjectId, options) {
5095
5141
  const live = this.#sessions.get(sessionId);
5096
5142
  if (live) {
5097
- if (requestedProjectId && live.projectId !== requestedProjectId) {
5098
- const forkedId = await this.forkSessionIntoProject(sessionId, requestedProjectId);
5099
- return this.#requireSession(forkedId);
5100
- }
5143
+ if (requestedProjectId && live.projectId !== requestedProjectId) return void 0;
5101
5144
  return live;
5102
5145
  }
5103
5146
  const match = (await this.#sessionLister()).find((info) => info.sessionId === sessionId || info.id === sessionId);
@@ -5110,10 +5153,7 @@ var PrimeBridge = class {
5110
5153
  if (isSessionNotResumableError(error)) return void 0;
5111
5154
  throw error;
5112
5155
  }
5113
- if (requestedProjectId && resumed.projectId !== requestedProjectId) {
5114
- const forkedId = await this.forkSessionIntoProject(resumed.sessionId, requestedProjectId);
5115
- return this.#requireSession(forkedId);
5116
- }
5156
+ if (requestedProjectId && resumed.projectId !== requestedProjectId) return void 0;
5117
5157
  return resumed;
5118
5158
  }
5119
5159
  async listSessions(cwd) {
@@ -5714,15 +5754,43 @@ var PrimeBridge = class {
5714
5754
  /** /export — write the session to HTML (default) or JSONL (path ends with .jsonl). */
5715
5755
  async exportSession(sessionId, outputPath) {
5716
5756
  const session = this.#requireSession(sessionId);
5757
+ const confinedPath = await this.#confineExportPath(session, outputPath);
5717
5758
  if (outputPath?.endsWith(".jsonl")) return {
5718
- path: await session.connection.exportToJsonl(outputPath),
5759
+ path: await session.connection.exportToJsonl(confinedPath),
5719
5760
  format: "jsonl"
5720
5761
  };
5721
5762
  return {
5722
- path: await session.connection.exportToHtml(outputPath),
5763
+ path: await session.connection.exportToHtml(confinedPath),
5723
5764
  format: "html"
5724
5765
  };
5725
5766
  }
5767
+ /**
5768
+ * Confine an explicit /export path inside the session's project directory
5769
+ * (the connection's live cwd). Absolute paths and `..` escapes that leave
5770
+ * the directory throw a 400-status error; an omitted path passes through
5771
+ * untouched so the default export location is unchanged.
5772
+ */
5773
+ async #confineExportPath(session, outputPath) {
5774
+ if (outputPath === void 0) return void 0;
5775
+ const { cwd } = await session.connection.getState();
5776
+ const root2 = resolve(cwd);
5777
+ const canonicalRoot = await realpath(root2).catch(() => root2);
5778
+ const candidate = resolve(root2, outputPath);
5779
+ const existingCandidate = await realpath(candidate).catch(() => void 0);
5780
+ if (existingCandidate && existingCandidate !== canonicalRoot && !existingCandidate.startsWith(`${canonicalRoot}${sep}`)) throw new SessionExportPathError();
5781
+ let ancestor = dirname(candidate);
5782
+ while (true) {
5783
+ const resolvedAncestor = await realpath(ancestor).catch(() => void 0);
5784
+ if (resolvedAncestor) {
5785
+ if (resolvedAncestor !== canonicalRoot && !resolvedAncestor.startsWith(`${canonicalRoot}${sep}`)) throw new SessionExportPathError();
5786
+ break;
5787
+ }
5788
+ const parent = dirname(ancestor);
5789
+ if (parent === ancestor) throw new SessionExportPathError();
5790
+ ancestor = parent;
5791
+ }
5792
+ return candidate;
5793
+ }
5726
5794
  /** /reload — re-scan keybindings, extensions, skills, prompts, themes. */
5727
5795
  async reloadResources(_sessionId) {
5728
5796
  await Promise.all([...this.#sessions.values()].map((session) => session.connection.reload?.()));
@@ -5815,9 +5883,9 @@ var PrimeBridge = class {
5815
5883
  }
5816
5884
  /** Fork the complete persisted history into another registered project. */
5817
5885
  async forkSessionIntoProject(sessionId, targetProjectId) {
5886
+ const targetCwd = await getPrimeConfig().projectRegistry.cwdForProject(targetProjectId);
5818
5887
  const source = this.#sessions.get(sessionId) ?? await this.resumeSessionById(sessionId);
5819
5888
  if (!source) throw new Error(`Unknown session: ${sessionId}`);
5820
- const targetCwd = await getPrimeConfig().projectRegistry.cwdForProject(targetProjectId);
5821
5889
  await source.connection.waitForIdle();
5822
5890
  const sourceState = await source.connection.getState();
5823
5891
  const sourcePath = sourceState.sessionFile;
@@ -5838,7 +5906,7 @@ var PrimeBridge = class {
5838
5906
  await copyManagedPlanPresentationsForFork(source, forked, (await this.getMessages(forked.sessionId)).length);
5839
5907
  forked.mapperState.presentation = source.mapperState.presentation;
5840
5908
  this.#persistPresentation(forked.sessionId, forked.sessionPath, forked.mapperState.presentation);
5841
- return forked.sessionId;
5909
+ return this.#requireProjectSession(forked.sessionId, targetProjectId).sessionId;
5842
5910
  }
5843
5911
  /** Reads message history from a live session, or from the JSONL transcript for a cold session. */
5844
5912
  async getMessages(sessionId) {
@@ -5880,6 +5948,17 @@ var PrimeBridge = class {
5880
5948
  if (!session) throw new Error(`Unknown session: ${sessionId}`);
5881
5949
  return session;
5882
5950
  }
5951
+ /**
5952
+ * Project-membership gate over the bridge's session records. Returns the
5953
+ * live session only when its project linkage matches the caller-asserted
5954
+ * project, and throws `Unknown session` otherwise so foreign sessions are
5955
+ * indistinguishable from missing ones.
5956
+ */
5957
+ #requireProjectSession(sessionId, projectId) {
5958
+ const session = this.#requireSession(sessionId);
5959
+ if (session.projectId !== projectId) throw new Error(`Unknown session: ${sessionId}`);
5960
+ return session;
5961
+ }
5883
5962
  };
5884
5963
  var globalStore = globalThis;
5885
5964
  function getBridge() {
@@ -5890,7 +5969,20 @@ function getBridge() {
5890
5969
  });
5891
5970
  return globalStore.__primeBridge;
5892
5971
  }
5972
+ function isLoopbackHostname(hostname) {
5973
+ const host = hostname.toLowerCase().replace(/\.$/, "");
5974
+ if (host === "localhost") return true;
5975
+ const bare = host.startsWith("[") && host.endsWith("]") ? host.slice(1, -1) : host;
5976
+ const mapped = bare.startsWith("::ffff:") ? bare.slice(7) : bare;
5977
+ if (mapped === "::1" || mapped === "0:0:0:0:0:0:0:1") return true;
5978
+ if (mapped.startsWith("127.")) {
5979
+ const parts = mapped.split(".");
5980
+ if (parts.length === 4 && parts.every((p) => /^\d{1,3}$/.test(p) && Number(p) <= 255)) return true;
5981
+ }
5982
+ return false;
5983
+ }
5893
5984
  function getResponseStatus(error) {
5985
+ if (error instanceof ZodError || error instanceof Error && error.name === "ZodError") return 422;
5894
5986
  if (error && typeof error === "object" && "status" in error) {
5895
5987
  const status = error.status;
5896
5988
  if (typeof status === "number" && status >= 400 && status < 600) return status;
@@ -5907,8 +5999,14 @@ function getErrorMessage(error) {
5907
5999
  }
5908
6000
  }
5909
6001
  function safeErrorMessage(error) {
5910
- return getErrorMessage(error).replace(/(['"])(\/(?!\/)[^'"\n]*|[A-Za-z]:\\[^'"\n]*)\1/g, "$1[local path]$1").replace(/(^|[\s'"(])\/(?!\/)[^'"\s)]+/g, "$1[local path]").replace(/[A-Za-z]:\\[^'"\s)]+/g, "[local path]");
6002
+ const message = getErrorMessage(error);
6003
+ return SECRET_PATTERNS.reduce((scrubbed, [pattern, replacement]) => scrubbed.replace(pattern, replacement), message.replace(/(['"])(\/(?!\/)[^'"\n]*|[A-Za-z]:\\[^'"\n]*)\1/g, "$1[local path]$1").replace(/(^|[\s'"(])\/(?!\/)[^'"\s)]+/g, "$1[local path]").replace(/[A-Za-z]:\\[^'"\s)]+/g, "[local path]"));
5911
6004
  }
6005
+ var SECRET_PATTERNS = [
6006
+ [/\b(bearer\s+)[A-Za-z0-9\-._~+/=]{8,}/gi, "$1[redacted]"],
6007
+ [/(api[_-]?key\s*[:=]\s*)["']?[^"'\s;,]+["']?/gi, "$1[redacted]"],
6008
+ [/\bkey(\s*=\s*)[^"'\s;&,]+/gi, "key$1[redacted]"]
6009
+ ];
5912
6010
  var DAEMON_DISCONNECT_PATTERNS = [/cannot send daemon command/i, /daemon is not connected/i];
5913
6011
  function isDaemonDisconnectError(error) {
5914
6012
  const message = getErrorMessage(error);
@@ -5928,14 +6026,43 @@ function chatErrorEnvelope(error) {
5928
6026
  message: safeErrorMessage(error)
5929
6027
  };
5930
6028
  }
5931
- function wrapApiHandler(handler) {
6029
+ function isOriginAllowed(request) {
6030
+ const origin = request.headers.get("origin");
6031
+ if (!origin) return true;
6032
+ let originUrl;
6033
+ try {
6034
+ originUrl = new URL(origin);
6035
+ } catch {
6036
+ return false;
6037
+ }
6038
+ if (isLoopbackHostname(originUrl.hostname)) return true;
6039
+ try {
6040
+ return originUrl.host.toLowerCase() === new URL(request.url).host.toLowerCase();
6041
+ } catch {
6042
+ return true;
6043
+ }
6044
+ }
6045
+ function wrapApiHandler(handler, request) {
6046
+ if (request && request.method.toUpperCase() !== "GET" && !isOriginAllowed(request)) return Promise.resolve(Response.json({
6047
+ code: "UNKNOWN_ERROR",
6048
+ message: "Cross-origin request rejected."
6049
+ }, { status: 403 }));
5932
6050
  return handler().catch((error) => {
5933
6051
  const envelope = chatErrorEnvelope(error);
5934
- if (envelope.code === "NETWORK_DISCONNECTED") process.stderr.write(`[api] daemon transport failure: ${getErrorMessage(error)}
6052
+ if (envelope.code === "NETWORK_DISCONNECTED") process.stderr.write(`[api] daemon transport failure: ${safeErrorMessage(error)}
5935
6053
  `);
5936
6054
  return Response.json(envelope, { status: getResponseStatus(error) });
5937
6055
  });
5938
6056
  }
6057
+ async function requireProjectSession(session) {
6058
+ if (!session?.projectId) return false;
6059
+ try {
6060
+ await getPrimeConfig().projectRegistry.get(session.projectId);
6061
+ } catch {
6062
+ return false;
6063
+ }
6064
+ return true;
6065
+ }
5939
6066
  function resolveChatStreamingBehavior(streamingBehavior) {
5940
6067
  return streamingBehavior ?? "steer";
5941
6068
  }
@@ -5944,7 +6071,8 @@ function chooseChatStartId(mapperState, streamingBehavior, sessionIsStreaming =
5944
6071
  return crypto.randomUUID();
5945
6072
  }
5946
6073
  async function handleChatChildPost(bridge, parentSessionId, childId, message, streamingBehavior) {
5947
- if (!(bridge.getSession(parentSessionId) ?? await bridge.resumeSessionById(parentSessionId, void 0, {}))) return Response.json({ message: `Unknown session: ${parentSessionId}` }, { status: 404 });
6074
+ const session = bridge.getSession(parentSessionId) ?? await bridge.resumeSessionById(parentSessionId, void 0, {});
6075
+ if (!session || !await requireProjectSession(session)) return Response.json({ message: `Unknown session: ${parentSessionId}` }, { status: 404 });
5948
6076
  const encoder = new TextEncoder();
5949
6077
  const stream = new ReadableStream({ start(controller) {
5950
6078
  let closed = false;
@@ -6032,7 +6160,7 @@ function handleChatPost(request) {
6032
6160
  if (process.env.PRIME_BRIDGE_DEBUG === "1") process.stderr.write(`[chat] received session=${targetSessionId.slice(0, 8)} bytes=${message.length}
6033
6161
  `);
6034
6162
  const session = bridge.getSession(targetSessionId) ?? await bridge.resumeSessionById(targetSessionId, void 0, { openUI });
6035
- if (!session) return Response.json({ message: `Unknown session: ${targetSessionId}` }, { status: 404 });
6163
+ if (!session || !await requireProjectSession(session)) return Response.json({ message: `Unknown session: ${targetSessionId}` }, { status: 404 });
6036
6164
  const uploadAttachments = (body.attachments ?? []).filter((attachment) => attachment.kind === "upload");
6037
6165
  let uploadInspections;
6038
6166
  try {
@@ -6186,7 +6314,7 @@ ${attachmentContext.join("\n\n")}` : message;
6186
6314
  Connection: "keep-alive",
6187
6315
  "X-Accel-Buffering": "no"
6188
6316
  } });
6189
- });
6317
+ }, request);
6190
6318
  }
6191
6319
  var BodySchema$3 = external_exports.object({
6192
6320
  sessionId: SessionIdSchema.optional(),
@@ -6199,6 +6327,7 @@ function handleChatAbortPost(request) {
6199
6327
  const sessionId = body.sessionId;
6200
6328
  if (!sessionId) return Response.json({ message: "abort requires sessionId" }, { status: 400 });
6201
6329
  const bridge = getBridge();
6330
+ if (!await requireProjectSession(bridge.getSession(sessionId) ?? await bridge.resumeSessionById(sessionId))) return Response.json({ message: `Unknown session: ${sessionId}` }, { status: 404 });
6202
6331
  if (body.childId) {
6203
6332
  if (!await bridge.abortRlmChild(sessionId, body.childId)) return Response.json({ message: `No active subagent turn: ${body.childId}` }, { status: 404 });
6204
6333
  return Response.json({
@@ -6212,13 +6341,33 @@ function handleChatAbortPost(request) {
6212
6341
  ok: true,
6213
6342
  sessionId
6214
6343
  });
6215
- });
6344
+ }, request);
6216
6345
  }
6217
6346
  var AttachmentIdSchema = external_exports.uuid();
6218
6347
  var ATTACHMENT_WRITE_CONCURRENCY = 8;
6348
+ function isSafeRasterImage(mimeType, data) {
6349
+ if (mimeType === "image/png") return data.length >= 8 && data.subarray(0, 8).every((byte, index) => byte === [
6350
+ 137,
6351
+ 80,
6352
+ 78,
6353
+ 71,
6354
+ 13,
6355
+ 10,
6356
+ 26,
6357
+ 10
6358
+ ][index]);
6359
+ if (mimeType === "image/jpeg") return data.length >= 3 && data[0] === 255 && data[1] === 216 && data[2] === 255;
6360
+ if (mimeType === "image/gif") {
6361
+ const header = new TextDecoder().decode(data.subarray(0, 6));
6362
+ return header === "GIF87a" || header === "GIF89a";
6363
+ }
6364
+ return mimeType === "image/webp" && data.length >= 12 && new TextDecoder().decode(data.subarray(0, 4)) === "RIFF" && new TextDecoder().decode(data.subarray(8, 12)) === "WEBP";
6365
+ }
6219
6366
  async function resolveSession(sessionId) {
6220
6367
  const bridge = getBridge();
6221
- return bridge.getSession(sessionId) ?? await bridge.resumeSessionById(sessionId);
6368
+ const session = bridge.getSession(sessionId) ?? await bridge.resumeSessionById(sessionId);
6369
+ if (!await requireProjectSession(session)) return void 0;
6370
+ return session;
6222
6371
  }
6223
6372
  function handleChatAttachmentsPost(request) {
6224
6373
  return wrapApiHandler(async () => {
@@ -6241,7 +6390,7 @@ function handleChatAttachmentsPost(request) {
6241
6390
  }
6242
6391
  const attachments = settled.flatMap((result) => result.status === "fulfilled" ? [result.value] : []);
6243
6392
  return Response.json({ attachments });
6244
- });
6393
+ }, request);
6245
6394
  }
6246
6395
  function handleChatAttachmentGet(request) {
6247
6396
  return wrapApiHandler(async () => {
@@ -6252,18 +6401,19 @@ function handleChatAttachmentGet(request) {
6252
6401
  if (!session) return Response.json({ message: `Unknown session: ${sessionId}` }, { status: 404 });
6253
6402
  const attachment = await readManagedAttachment(session, attachmentId).catch(() => void 0);
6254
6403
  if (!attachment) return Response.json({ message: "Attachment not found" }, { status: 404 });
6404
+ const safeRasterImage = isSafeRasterImage(attachment.metadata.mimeType, attachment.data);
6255
6405
  return new Response(attachment.data, { headers: {
6256
- "Content-Type": attachment.metadata.mimeType,
6257
- "Content-Disposition": `inline; filename*=UTF-8''${encodeURIComponent(attachment.metadata.name)}`,
6406
+ "Content-Type": safeRasterImage ? attachment.metadata.mimeType : "application/octet-stream",
6407
+ ...safeRasterImage ? {} : { "Content-Disposition": `attachment; filename*=UTF-8''${encodeURIComponent(attachment.metadata.name)}` },
6258
6408
  "Cache-Control": "private, no-store",
6259
6409
  "X-Content-Type-Options": "nosniff"
6260
6410
  } });
6261
- });
6411
+ }, request);
6262
6412
  }
6263
6413
  var BodySchema$2 = external_exports.object({
6264
6414
  sessionId: SessionIdSchema,
6265
6415
  command: external_exports.string(),
6266
- args: external_exports.string().optional()
6416
+ args: external_exports.string().max(1024).optional()
6267
6417
  });
6268
6418
  function handleChatCommandPost(request) {
6269
6419
  return wrapApiHandler(async () => {
@@ -6338,7 +6488,7 @@ function handleChatCommandPost(request) {
6338
6488
  default:
6339
6489
  return Response.json({ message: `Unknown slash command: /${body.command}` }, { status: 404 });
6340
6490
  }
6341
- });
6491
+ }, request);
6342
6492
  }
6343
6493
  async function cwdForRequest(request) {
6344
6494
  const projectIdParam = new URL(request.url).searchParams.get("projectId");
@@ -6556,7 +6706,7 @@ function handleChatCommandsGet(request) {
6556
6706
  ],
6557
6707
  diagnostics
6558
6708
  });
6559
- });
6709
+ }, request);
6560
6710
  }
6561
6711
  function shouldReplaySseEvent(event, pendingQuestionIds) {
6562
6712
  if (!pendingQuestionIds) return true;
@@ -6705,7 +6855,10 @@ function handleChatEventsGet(request) {
6705
6855
  const childId = SessionIdSchema.safeParse(childIdParam);
6706
6856
  if (!parentSessionId.success || !childId.success) return Response.json({ message: "Invalid subagent stream identifiers" }, { status: 400 });
6707
6857
  if (streamGenerationParam !== null && !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(streamGenerationParam)) return Response.json({ message: "Invalid child stream generation" }, { status: 400 });
6708
- const childStream = await getBridge().openRlmChildStream(parentSessionId.data, childId.data, {
6858
+ const bridge = getBridge();
6859
+ const parent = bridge.getSession(parentSessionId.data) ?? await bridge.resumeSessionById(parentSessionId.data);
6860
+ if (!parent || !await requireProjectSession(parent)) return Response.json({ message: "Unknown live subagent stream" }, { status: 404 });
6861
+ const childStream = await bridge.openRlmChildStream(parentSessionId.data, childId.data, {
6709
6862
  ...streamGenerationParam ? { streamGeneration: streamGenerationParam } : {},
6710
6863
  lastEventId: lastEventIdFor(request, url)
6711
6864
  });
@@ -6725,8 +6878,13 @@ function handleChatEventsGet(request) {
6725
6878
  if (!sessionIdParam) return Response.json({ message: "SSE requires ?sessionId=" }, { status: 400 });
6726
6879
  const sessionId = SessionIdSchema.safeParse(sessionIdParam);
6727
6880
  if (!sessionId.success) return Response.json({ message: "Invalid session identifier" }, { status: 400 });
6881
+ {
6882
+ const bridge = getBridge();
6883
+ const session = bridge.getSession(sessionId.data) ?? await bridge.resumeSessionById(sessionId.data);
6884
+ if (!session || !await requireProjectSession(session)) return Response.json({ message: `Unknown session: ${sessionId.data}` }, { status: 404 });
6885
+ }
6728
6886
  return createSseResponse(request, getBridge(), { sessionId: sessionId.data }, lastEventIdFor(request, url));
6729
- });
6887
+ }, request);
6730
6888
  }
6731
6889
  var BodySchema$1 = external_exports.object({
6732
6890
  sessionId: SessionIdSchema,
@@ -6739,12 +6897,15 @@ function handleChatModelPost(request) {
6739
6897
  return wrapApiHandler(async () => {
6740
6898
  const raw = await request.json().catch(() => ({}));
6741
6899
  const body = BodySchema$1.parse(raw);
6742
- await getBridge().setModel(body.sessionId, {
6900
+ const bridge = getBridge();
6901
+ const session = bridge.getSession(body.sessionId) ?? await bridge.resumeSessionById(body.sessionId);
6902
+ if (!session || !await requireProjectSession(session)) return Response.json({ message: `Unknown session: ${body.sessionId}` }, { status: 404 });
6903
+ await bridge.setModel(body.sessionId, {
6743
6904
  provider: body.model.provider,
6744
6905
  id: body.model.id
6745
6906
  });
6746
6907
  return Response.json({ ok: true });
6747
- });
6908
+ }, request);
6748
6909
  }
6749
6910
  function toPatternCandidate(model) {
6750
6911
  return {
@@ -6797,7 +6958,7 @@ function handleChatModelsGet(request) {
6797
6958
  ...defaultThinkingLevel ? { defaultThinkingLevel } : {},
6798
6959
  diagnostics
6799
6960
  });
6800
- });
6961
+ }, request);
6801
6962
  }
6802
6963
  function storedApiForCustomProvider(api) {
6803
6964
  return api === "google-genai" ? "google-generative-ai" : api;
@@ -6919,6 +7080,7 @@ function isDiscoverableEntry(entry) {
6919
7080
  function openAiModelsUrl(baseUrl) {
6920
7081
  const parsed = new URL(baseUrl);
6921
7082
  if (parsed.protocol !== "https:" && parsed.protocol !== "http:") throw new Error("model discovery requires an http(s) URL");
7083
+ if (parsed.protocol === "http:" && !isLoopbackHostname(parsed.hostname)) throw new Error("model discovery requires https for non-loopback hosts");
6922
7084
  const path = parsed.pathname.replace(/\/+$/, "");
6923
7085
  parsed.pathname = path.endsWith("/v1") ? `${path}/models` : `${path}/v1/models`;
6924
7086
  parsed.search = "";
@@ -6951,6 +7113,7 @@ function handleChatModelsDiscoverPost(request) {
6951
7113
  const modelsUrl = openAiModelsUrl(baseUrl);
6952
7114
  const response = await fetch(modelsUrl, {
6953
7115
  headers: { Authorization: `Bearer ${apiKey}` },
7116
+ redirect: "error",
6954
7117
  signal: AbortSignal.timeout(1e4)
6955
7118
  });
6956
7119
  if (!response.ok) return Response.json({
@@ -6982,7 +7145,7 @@ function handleChatModelsDiscoverPost(request) {
6982
7145
  models: []
6983
7146
  });
6984
7147
  }
6985
- });
7148
+ }, request);
6986
7149
  }
6987
7150
  function toThinkingLevel(level) {
6988
7151
  return level;
@@ -7018,7 +7181,7 @@ function handleChatNewPost(request) {
7018
7181
  planPresentations: [],
7019
7182
  presentation: bridge.getPresentation(session.sessionId)
7020
7183
  });
7021
- });
7184
+ }, request);
7022
7185
  }
7023
7186
  function record(value) {
7024
7187
  return typeof value === "object" && value !== null ? value : void 0;
@@ -7037,7 +7200,7 @@ function handleChatOpenUIArtifactPut(request) {
7037
7200
  if (!validation.ok) return Response.json({ message: validation.reason }, { status: validation.status ?? 400 });
7038
7201
  const bridge = getBridge();
7039
7202
  const session = bridge.getSession(body.sessionId) ?? await bridge.resumeSessionById(body.sessionId);
7040
- if (!session) return Response.json({ message: `Unknown session: ${body.sessionId}` }, { status: 404 });
7203
+ if (!session || !await requireProjectSession(session)) return Response.json({ message: `Unknown session: ${body.sessionId}` }, { status: 404 });
7041
7204
  const messages = await bridge.getMessages(session.sessionId);
7042
7205
  const incomingId = body.assistantMessageId;
7043
7206
  const exact = messages.find((message) => message.role === "assistant" && message.id === incomingId);
@@ -7064,14 +7227,14 @@ function handleChatOpenUIArtifactPut(request) {
7064
7227
  artifact,
7065
7228
  presentation
7066
7229
  });
7067
- });
7230
+ }, request);
7068
7231
  }
7069
7232
  function handleChatPlanPresentationPut(request) {
7070
7233
  return wrapApiHandler(async () => {
7071
7234
  const body = ChatPlanPresentationUpsertRequestSchema.parse(await request.json().catch(() => ({})));
7072
7235
  const bridge = getBridge();
7073
7236
  const session = bridge.getSession(body.sessionId) ?? await bridge.resumeSessionById(body.sessionId);
7074
- if (!session) return Response.json({ message: `Unknown session: ${body.sessionId}` }, { status: 404 });
7237
+ if (!session || !await requireProjectSession(session)) return Response.json({ message: `Unknown session: ${body.sessionId}` }, { status: 404 });
7075
7238
  const messages = await bridge.getMessages(body.sessionId);
7076
7239
  const incomingId = body.presentation.assistantMessageId;
7077
7240
  const known = messages.find((message) => message.id === incomingId && message.role === "assistant");
@@ -7085,7 +7248,7 @@ function handleChatPlanPresentationPut(request) {
7085
7248
  assistantMessageId,
7086
7249
  ...clientMessageId ? { clientMessageId } : {}
7087
7250
  }) });
7088
- });
7251
+ }, request);
7089
7252
  }
7090
7253
  var PRIME_BUTTERFLY_SVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 178 178" aria-hidden="true"><path fill="currentColor" d="m 123.322,84.092671 c -0.192,0.0065 -0.43,0.0147 -0.74,0.0147 l -0.018,-0.0247 c -0.873,0.1977 -1.958,0.1266 -3.067,0.0537 -3.29,-0.216 -6.799,-0.4465 -5.635,6.2824 0.259,1.4822 -1.538,1.8465 -2.73,1.9082 -3.384,0.1853 -6.78,0.2594 -10.171,0.1915 -0.641,-0.0106 -1.2979,-0.5506 -1.8904,-1.0388 -0.1022,-0.0844 -0.2034,-0.1673 -0.3016,-0.2457 -0.1052,-0.0865 0.2898,-1.2042 0.4942,-1.2166 3.3078,-0.1931 4.5068,-2.4361 5.7028,-4.6724 0.603,-1.1253 1.204,-2.2488 2.072,-3.1088 7.856,-7.7874 15.878,-15.4265 25.054,-21.7008 0.895,-0.6114 1.989,-1.1733 2.73,-0.1111 0.571,0.8205 0.036,1.2854 -0.512,1.7627 -0.24,0.2088 -0.482,0.4199 -0.637,0.6642 -0.554,0.8792 -1.538,1.5273 -2.514,2.1717 -1.92,1.2655 -3.82,2.5172 -2.408,5.4798 1.225,2.5651 0.129,3.0202 -1.555,3.7198 l -0.069,0.0287 c -0.72,0.3021 -1.458,0.5764 -2.194,0.8506 -1.568,0.5835 -3.134,1.1662 -4.537,2.0149 -1.408,0.8522 -2.081,2.5134 0.222,3.4954 5.033,2.1428 18.064,-1.2784 20.608,-5.9965 2.377,-4.4147 5.931,-7.6891 9.481,-10.9611 1.992,-1.836 3.984,-3.6712 5.767,-5.7067 3.844,-4.3849 8.344,-8.1939 12.846,-12.005 2.239,-1.8944 4.478,-3.78938 6.637,-5.75588 1.624,-1.48207 2.297,-3.43353 1.026,-5.56412 -1.267,-2.118215 -3.416,-2.402287 -5.435,-1.926802 -13.309,3.130982 -26.166,7.355122 -37.585,15.241302 -18.23,12.5919 -36.4911,25.1406 -54.9002,37.4669 -6.2743,4.2056 -10.0723,2.1491 -12.1657,-5.1318 -4.6502,-16.1676 -11.4681,-30.2664 -31.0569,-32.4587 -7.1574,-0.8028 -12.4066,3.6807 -11.3692,10.7949 0.5249,3.6065 0.0495,7.003 -1.6858,10.3872 -0.3827,0.7472 -0.7689,1.4947 -1.1556,2.243 -2.672,5.1706 -5.3671,10.3857 -7.0394,15.8885 -0.1399,0.4602 -0.3002,0.9444 -0.4654,1.4437 -1.4909,4.5052 -3.3862,10.2323 5.659,10.5492 0.3705,0.0123 1.0808,0.944799 0.9943,1.290699 -0.1976,0.8213 -0.5991,1.797 -1.2413,2.2725 -8.6705,6.3917 -15.79706,14.1294 -18.860151,24.5971 -1.550066,5.2865 -0.524909,10.7765 3.989391,14.8705 3.22984,2.928 7.35516,4.625 10.97396,2.162 3.3009,-2.247 6.9232,-3.754 10.538,-5.259 3.1819,-1.324 6.358,-2.646 9.3041,-4.468 0.7101,-0.439 1.5727,-0.841 2.4456,-1.248 2.4138,-1.1228 4.9063,-2.2843 4.4709,-4.3841 -0.6854,-3.2908 -4.1623,-6.3418 -7.0586,-8.7384 -2.8716,-2.3769 -10.1897,-18.3411 -9.3189,-22.176099 1.2193,-5.3704 3.9645,-10.0201 6.7125,-14.6744 2.3458,-3.9731 4.6935,-7.9497 6.0956,-12.3806 0.5804,-1.828 2.8037,-2.8284 4.9466,-2.0997 1.4543,0.4928 1.2068,1.8278 0.9762,3.0715 -0.0063,0.0344 -0.0127,0.0685 -0.019,0.1027 -0.8688,4.7802 -1.721,9.566 -2.5733,14.3517 -0.4261,2.3924 -0.8521,4.7847 -1.2803,7.1762 -0.2717,1.5316 0.2038,2.7544 1.7909,3.0631 3.0569,0.599 2.989,1.9762 1.6119,4.341499 -1.4636,2.5072 -1.6674,5.5703 -0.0309,7.8861 1.6427,2.3282 4.3908,2.8161 7.1821,1.4204 1.7415,-0.8646 3.094,-0.0927 3.0755,1.6612 -0.1112,9.3688 3.8103,7.2561 8.584,3.1681 0.439,-0.3763 1.0373,-0.5846 1.6152,-0.7857 0.1048,-0.0366 0.2091,-0.0728 0.3116,-0.1098 0.4529,-0.1616 0.9062,-0.3224 1.3595,-0.4833 8.986,-3.1884 17.9603,-6.3725 23.0334,-15.573099 0.392,-0.7187 1.6783,-1.0669 2.6795,-1.3377 0.057,-0.0154 0.113,-0.0307 0.1681,-0.0456 5.8013,-1.5766 11.7248,-1.6001 17.6438,-1.6237 4.445,-0.0176 8.888,-0.0352 13.277,-0.7107 4.329,-0.667 9.047,-3.1928 9.084,-7.3736 0.035,-3.3707 -2.546,-3.1612 -5.123,-2.9519 -1.115,0.0906 -2.231,0.1811 -3.134,-0.0185 -0.182,-0.0381 -0.375,-0.0316 -0.686,-0.0209 z"/><path fill="currentColor" d="m 55.1325,131.29447 c -1.0745,7.1515 1.6551,13.2715 12.8266,13.1915 h -0.0062 c 9.5413,-0.389 20.3365,-6.164 30.8838,-13.5492 6.9653,-4.8787 12.9873,-10.0236 16.8903,-17.6253 2.872,-5.5889 1.395,-10.0723 -2.933,-13.993799 -1.908,-1.7291 -3.73,-1.9205 -5.867,0.1667 -7.5842,7.423099 -17.0261,11.474299 -26.7218,15.550099 -2.4706,1.0393 -5.2847,1.5582 -8.1187,2.0809 -7.5511,1.3924 -15.2431,2.8103 -16.954,14.1791 z"/></svg>`;
7091
7254
  function escapeHtml(value) {
@@ -35072,7 +35235,7 @@ function listChatProviders() {
35072
35235
  function handleChatProvidersGet(_request) {
35073
35236
  return wrapApiHandler(async () => {
35074
35237
  return Response.json({ providers: buildProviders() });
35075
- });
35238
+ }, _request);
35076
35239
  }
35077
35240
  function requireBaseUrl(baseUrl, providerId) {
35078
35241
  const trimmed = baseUrl?.trim() ?? "";
@@ -35141,7 +35304,7 @@ function handleChatProvidersPost(request) {
35141
35304
  success: true,
35142
35305
  providers: buildProviders()
35143
35306
  });
35144
- });
35307
+ }, request);
35145
35308
  }
35146
35309
  function handleChatProvidersDelete(request) {
35147
35310
  return wrapApiHandler(async () => {
@@ -35155,7 +35318,7 @@ function handleChatProvidersDelete(request) {
35155
35318
  success: true,
35156
35319
  providers: buildProviders()
35157
35320
  });
35158
- });
35321
+ }, request);
35159
35322
  }
35160
35323
  var LOGIN_TTL_MS = 96e4;
35161
35324
  var sessions = /* @__PURE__ */ new Map();
@@ -35313,7 +35476,7 @@ function handleChatProvidersOAuthPost(request) {
35313
35476
  error: `Unknown OAuth provider: ${body.providerId}`
35314
35477
  }, { status: 400 });
35315
35478
  return Response.json(startOAuthLogin(body.providerId, oauthDeps()));
35316
- });
35479
+ }, request);
35317
35480
  }
35318
35481
  function handleChatQuestionPost(request) {
35319
35482
  return wrapApiHandler(async () => {
@@ -35325,19 +35488,26 @@ function handleChatQuestionPost(request) {
35325
35488
  ok: false,
35326
35489
  message: "answer requires sessionId and toolCallId"
35327
35490
  }, { status: 400 });
35328
- if (!getBridge().answerDialog(sessionId, toolCallId, body.answer)) return Response.json({
35491
+ const bridge = getBridge();
35492
+ if (!await requireProjectSession(bridge.getSession(sessionId) ?? await bridge.resumeSessionById(sessionId))) return Response.json({
35493
+ ok: false,
35494
+ message: `Unknown session: ${sessionId}`
35495
+ }, { status: 404 });
35496
+ if (!bridge.answerDialog(sessionId, toolCallId, body.answer)) return Response.json({
35329
35497
  ok: false,
35330
35498
  message: "Question is no longer active"
35331
35499
  }, { status: 404 });
35332
35500
  return Response.json({ ok: true });
35333
- });
35501
+ }, request);
35334
35502
  }
35335
35503
  function handleChatQueueMutationPost(request) {
35336
35504
  return wrapApiHandler(async () => {
35337
35505
  const body = ChatQueueMutationRequestSchema.parse(await request.json().catch(() => ({})));
35338
- const result = await getBridge().deleteQueuedMessage(body.sessionId, body.lane, body.index, body.expectedText);
35506
+ const bridge = getBridge();
35507
+ if (!await requireProjectSession(bridge.getSession(body.sessionId) ?? await bridge.resumeSessionById(body.sessionId))) return Response.json({ message: `Unknown session: ${body.sessionId}` }, { status: 404 });
35508
+ const result = await bridge.deleteQueuedMessage(body.sessionId, body.lane, body.index, body.expectedText);
35339
35509
  return Response.json(ChatQueueMutationResponseSchema.parse(result));
35340
- });
35510
+ }, request);
35341
35511
  }
35342
35512
  function packageSourceToString(source) {
35343
35513
  if (typeof source === "string") return { name: source };
@@ -35394,7 +35564,7 @@ function handleChatResourcesGet(request) {
35394
35564
  })),
35395
35565
  diagnostics
35396
35566
  });
35397
- });
35567
+ }, request);
35398
35568
  }
35399
35569
  var BodySchema = ChatSessionMetadataSchema.extend({ sessionId: SessionIdSchema });
35400
35570
  function handleChatResumePost(request) {
@@ -35416,7 +35586,7 @@ function handleChatResumePost(request) {
35416
35586
  });
35417
35587
  }
35418
35588
  return Response.json({ message: "resume requires sessionId" }, { status: 400 });
35419
- });
35589
+ }, request);
35420
35590
  }
35421
35591
  function handleChatSessionGet(request) {
35422
35592
  return wrapApiHandler(async () => {
@@ -35428,7 +35598,10 @@ function handleChatSessionGet(request) {
35428
35598
  const parsedParentSessionId = SessionIdSchema.safeParse(parentSessionId);
35429
35599
  const parsedChildId = SessionIdSchema.safeParse(childId);
35430
35600
  if (!parsedParentSessionId.success || !parsedChildId.success) return Response.json({ message: "Invalid subagent session identifiers" }, { status: 400 });
35431
- const child = await getBridge().loadRlmChildTranscript(parsedParentSessionId.data, parsedChildId.data);
35601
+ const bridge2 = getBridge();
35602
+ const liveParent = bridge2.getSession(parsedParentSessionId.data);
35603
+ if (liveParent && !await requireProjectSession(liveParent)) return Response.json({ message: `Unknown session: ${parsedParentSessionId.data}` }, { status: 404 });
35604
+ const child = await bridge2.loadRlmChildTranscript(parsedParentSessionId.data, parsedChildId.data);
35432
35605
  if (!child) return Response.json({ message: "Unknown subagent transcript" }, { status: 404 });
35433
35606
  return Response.json({
35434
35607
  session: {
@@ -35447,7 +35620,7 @@ function handleChatSessionGet(request) {
35447
35620
  const bridge = getBridge();
35448
35621
  const projectId = requestedProjectId ? ProjectIdSchema.parse(requestedProjectId) : void 0;
35449
35622
  const existing = projectId ? await bridge.resumeSessionById(sessionId, projectId, { openUI }) : bridge.getSession(sessionId) ?? await bridge.resumeSessionById(sessionId, void 0, { openUI });
35450
- if (!existing) return Response.json({ message: `Unknown session: ${sessionId}` }, { status: 404 });
35623
+ if (!existing || !await requireProjectSession(existing)) return Response.json({ message: `Unknown session: ${sessionId}` }, { status: 404 });
35451
35624
  return Response.json({
35452
35625
  session: {
35453
35626
  sessionId: existing.sessionId,
@@ -35457,7 +35630,7 @@ function handleChatSessionGet(request) {
35457
35630
  planPresentations: await loadManagedPlanPresentations(existing),
35458
35631
  presentation: bridge.getPresentation(existing.sessionId)
35459
35632
  });
35460
- });
35633
+ }, request);
35461
35634
  }
35462
35635
  var RenameSessionSchema = external_exports.object({
35463
35636
  sessionId: SessionIdSchema,
@@ -35468,24 +35641,28 @@ function handleChatSessionRenamePatch(request) {
35468
35641
  return wrapApiHandler(async () => {
35469
35642
  const body = RenameSessionSchema.parse(await request.json().catch(() => ({})));
35470
35643
  const bridge = getBridge();
35471
- if (!(bridge.getSession(body.sessionId) ?? await bridge.resumeSessionById(body.sessionId))) return Response.json({ message: `Unknown session: ${body.sessionId}` }, { status: 404 });
35644
+ const session = bridge.getSession(body.sessionId) ?? await bridge.resumeSessionById(body.sessionId);
35645
+ if (!session || !await requireProjectSession(session)) return Response.json({ message: `Unknown session: ${body.sessionId}` }, { status: 404 });
35472
35646
  bridge.setSessionName(body.sessionId, body.title);
35473
35647
  return Response.json({
35474
35648
  ok: true,
35475
35649
  sessionId: body.sessionId,
35476
35650
  title: body.title
35477
35651
  });
35478
- });
35652
+ }, request);
35479
35653
  }
35480
35654
  function handleChatSessionDelete(request) {
35481
35655
  return wrapApiHandler(async () => {
35482
35656
  const body = DeleteSessionSchema.parse(await request.json().catch(() => ({})));
35483
- if (!await getBridge().deleteSession(body.sessionId)) return Response.json({ message: `Unknown session: ${body.sessionId}` }, { status: 404 });
35657
+ const bridge = getBridge();
35658
+ const session = bridge.getSession(body.sessionId) ?? await bridge.resumeSessionById(body.sessionId);
35659
+ if (!session || !await requireProjectSession(session)) return Response.json({ message: `Unknown session: ${body.sessionId}` }, { status: 404 });
35660
+ if (!await bridge.deleteSession(body.sessionId)) return Response.json({ message: `Unknown session: ${body.sessionId}` }, { status: 404 });
35484
35661
  return Response.json({
35485
35662
  ok: true,
35486
35663
  sessionId: body.sessionId
35487
35664
  });
35488
- });
35665
+ }, request);
35489
35666
  }
35490
35667
  function stringValue(value) {
35491
35668
  return typeof value === "string" && value.length > 0 ? value : void 0;
@@ -35559,7 +35736,7 @@ function handleProjectsGet(_request) {
35559
35736
  };
35560
35737
  })
35561
35738
  });
35562
- });
35739
+ }, _request);
35563
35740
  }
35564
35741
  function handleProjectsPost(request) {
35565
35742
  return wrapApiHandler(async () => {
@@ -35567,20 +35744,20 @@ function handleProjectsPost(request) {
35567
35744
  const registry = getPrimeConfig().projectRegistry;
35568
35745
  const path = await registry.resolveDirectoryInput(body);
35569
35746
  return Response.json({ project: await registry.register(path, body.name) }, { status: 201 });
35570
- });
35747
+ }, request);
35571
35748
  }
35572
35749
  function handleProjectPatch(request) {
35573
35750
  return wrapApiHandler(async () => {
35574
35751
  const projectId = ProjectIdSchema.parse(new URL(request.url).searchParams.get("projectId") ?? "");
35575
35752
  const body = ProjectRenameRequestSchema.parse(await request.json().catch(() => ({})));
35576
35753
  return Response.json({ project: await getPrimeConfig().projectRegistry.rename(projectId, body.name) });
35577
- });
35754
+ }, request);
35578
35755
  }
35579
35756
  function handleProjectDelete(request) {
35580
35757
  return wrapApiHandler(async () => {
35581
35758
  const projectId = ProjectIdSchema.parse(new URL(request.url).searchParams.get("projectId") ?? "");
35582
35759
  return Response.json({ project: await getPrimeConfig().projectRegistry.unregister(projectId) });
35583
- });
35760
+ }, request);
35584
35761
  }
35585
35762
  function handleProjectSessionFork(request) {
35586
35763
  return wrapApiHandler(async () => {
@@ -35590,7 +35767,7 @@ function handleProjectSessionFork(request) {
35590
35767
  sessionId,
35591
35768
  projectId: body.targetProjectId
35592
35769
  }, { status: 201 });
35593
- });
35770
+ }, request);
35594
35771
  }
35595
35772
  function handleProjectBrowseGet(request) {
35596
35773
  return wrapApiHandler(async () => {
@@ -35600,7 +35777,7 @@ function handleProjectBrowseGet(request) {
35600
35777
  token: url.searchParams.get("token") ?? void 0
35601
35778
  });
35602
35779
  return Response.json(result);
35603
- });
35780
+ }, request);
35604
35781
  }
35605
35782
  function handleChatSessionsGet(_request) {
35606
35783
  return wrapApiHandler(async () => {
@@ -35624,7 +35801,7 @@ function handleChatSessionsGet(_request) {
35624
35801
  };
35625
35802
  }));
35626
35803
  return Response.json({ sessions: projectId ? formatted.filter((session) => session.projectId === projectId) : formatted });
35627
- });
35804
+ }, _request);
35628
35805
  }
35629
35806
  function toProjectShape(project) {
35630
35807
  const out = {};
@@ -35694,7 +35871,7 @@ function handleChatSettingsGet(request) {
35694
35871
  return wrapApiHandler(async () => {
35695
35872
  const cwd = await cwdForRequest(request);
35696
35873
  return Response.json(buildResponse(cwd));
35697
- });
35874
+ }, request);
35698
35875
  }
35699
35876
  function handleChatSettingsPatch(request) {
35700
35877
  return wrapApiHandler(async () => {
@@ -35719,7 +35896,7 @@ function handleChatSettingsPatch(request) {
35719
35896
  if (patch.themes !== void 0) manager.setThemePaths(patch.themes);
35720
35897
  if (patch.packages !== void 0) manager.setPackages(patch.packages);
35721
35898
  return Response.json(buildResponse(cwd));
35722
- });
35899
+ }, request);
35723
35900
  }
35724
35901
  function handleHealthGet(request) {
35725
35902
  return wrapApiHandler(async () => {
@@ -35729,12 +35906,12 @@ function handleHealthGet(request) {
35729
35906
  kernel,
35730
35907
  uptimeMs: process.uptime() * 1e3
35731
35908
  });
35732
- });
35909
+ }, request);
35733
35910
  }
35734
35911
  function handleWorkspaceBrowseGet(request) {
35735
35912
  return wrapApiHandler(async () => {
35736
35913
  return Response.json({ message: "Workspace root switching is disabled; use /api/projects/browse for opaque directory tokens." }, { status: 410 });
35737
- });
35914
+ }, request);
35738
35915
  }
35739
35916
  function canonicalizePath(path) {
35740
35917
  try {
@@ -35855,7 +36032,7 @@ function handleWorkspaceFileGet(request) {
35855
36032
  const result = await readWorkspaceFile(await cwdForRequest(request), path);
35856
36033
  if (result.kind === "error") return Response.json({ message: result.message }, { status: result.status });
35857
36034
  return Response.json(result.body);
35858
- });
36035
+ }, request);
35859
36036
  }
35860
36037
  var IGNORED = /* @__PURE__ */ new Set([
35861
36038
  ".git",
@@ -35935,7 +36112,7 @@ function handleWorkspaceTreeGet(_request) {
35935
36112
  nodes,
35936
36113
  diagnostics
35937
36114
  });
35938
- });
36115
+ }, _request);
35939
36116
  }
35940
36117
  var Route$25 = createFileRoute("/api/chat")({ server: { handlers: { POST: ({ request }) => handleChatPost(request) } } });
35941
36118
  var Route$24 = createFileRoute("/api/health")({ server: { handlers: { GET: ({ request }) => handleHealthGet(request) } } });