@runeya/runeya 2.0.140 → 2.0.142

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 (123) hide show
  1. package/agent/index.js.map +1 -1
  2. package/agent-manager-M4NA5YFD.js +11 -0
  3. package/{chat-L7RRHXX5.js → chat-X3X527EX.js} +9 -7
  4. package/{chunk-GOMF7NWS.js → chunk-7L6AQUBR.js} +2 -2
  5. package/{chunk-O2KOX4LU.js → chunk-C2BGNVBT.js} +35 -9
  6. package/chunk-C2BGNVBT.js.map +1 -0
  7. package/{chunk-SYCUQDA4.js → chunk-GXE5TLLJ.js} +10 -4
  8. package/chunk-GXE5TLLJ.js.map +1 -0
  9. package/{chunk-EV3TBM7E.js → chunk-IXO5KIO5.js} +9 -2
  10. package/{chunk-EV3TBM7E.js.map → chunk-IXO5KIO5.js.map} +1 -1
  11. package/{chunk-QWX6R6AW.js → chunk-NSS47H26.js} +71 -16
  12. package/chunk-NSS47H26.js.map +1 -0
  13. package/{chunk-G4TOLDZB.js → chunk-P73PTVII.js} +95 -63
  14. package/chunk-P73PTVII.js.map +1 -0
  15. package/{chunk-6HSZPK2W.js → chunk-UR3HL373.js} +3 -3
  16. package/{companion-LQVLEHU7.js → companion-2LHKU577.js} +5 -5
  17. package/{desktop-installer-page-OKE4WY5Q.js → desktop-installer-page-6JDSXK2E.js} +226 -33
  18. package/desktop-installer-page-6JDSXK2E.js.map +1 -0
  19. package/{free-port-565NMFIZ.js → free-port-5UNHDWGE.js} +2 -2
  20. package/index.js +70 -22
  21. package/index.js.map +1 -1
  22. package/install-gate-2NNH7RM2.js +60 -0
  23. package/install-gate-2NNH7RM2.js.map +1 -0
  24. package/mcp-server/index.js +84 -10
  25. package/mcp-server/index.js.map +1 -1
  26. package/mcp-server/launch.d.ts +5 -4
  27. package/mcp-server/launch.js.map +1 -1
  28. package/package.json +1 -1
  29. package/settings-manager-32SVMAFN.js +10 -0
  30. package/{src-NVQHFMTQ.js → src-5TEXF3SU.js} +938 -809
  31. package/src-5TEXF3SU.js.map +1 -0
  32. package/{vault-resolver-B5P2OUI5.js → vault-resolver-VK6W5J6W.js} +2 -2
  33. package/web/assets/{AgentScalarChatInterface.vue-Dgobg9wk.js → AgentScalarChatInterface.vue-uNy1P-l4.js} +1 -1
  34. package/web/assets/{AgentTerminalPage-B43nSPSz.js → AgentTerminalPage-CFnALyb1.js} +1 -1
  35. package/web/assets/{AiChatModals-CVZ5ilmt.js → AiChatModals-B6svb69W.js} +1 -1
  36. package/web/assets/{AppLayout-B5yKLUj9.js → AppLayout-BKlJtfuQ.js} +1 -1
  37. package/web/assets/{AuditPage-KR5ydSRG.js → AuditPage-BsSpX2TJ.js} +1 -1
  38. package/web/assets/{CloudAccountPage-RNosmi99.js → CloudAccountPage-DabrwDsa.js} +1 -1
  39. package/web/assets/{CloudMessagingPage-Dp-FDdoH.js → CloudMessagingPage-BtOJO5FB.js} +1 -1
  40. package/web/assets/{DashboardPage-Bjj11oP_.js → DashboardPage-DMByzpgW.js} +1 -1
  41. package/web/assets/{DirectoryPickerDialog-C28UH35_.js → DirectoryPickerDialog-CDyk4Z_Q.js} +1 -1
  42. package/web/assets/{EnvironmentForm-Dj2T2DuS.js → EnvironmentForm-BlGWpU2_.js} +1 -1
  43. package/web/assets/{EnvironmentFormPage-B4Bt1bXS.js → EnvironmentFormPage-B-dpyO0_.js} +1 -1
  44. package/web/assets/{EnvironmentListPage-B_V9mEhR.js → EnvironmentListPage-BlaOiTVh.js} +1 -1
  45. package/web/assets/{KanbanBoardPage-CQLiin5v.js → KanbanBoardPage-C52zM-Zw.js} +3 -3
  46. package/web/assets/{KanbanListPage-ChD0Zj0Y.js → KanbanListPage-BmNdd1aP.js} +1 -1
  47. package/web/assets/{LaunchProjectPage-ByIfq7ka.js → LaunchProjectPage-B5sXxaet.js} +1 -1
  48. package/web/assets/{LaunchServicesPage-BweD0CWu.js → LaunchServicesPage-C1u6lV4l.js} +1 -1
  49. package/web/assets/{LaunchShell-C9jV0DDh.js → LaunchShell-CeyVMzL2.js} +1 -1
  50. package/web/assets/{LogViewer-Cv024Meq.js → LogViewer-CAvRwSZu.js} +2 -2
  51. package/web/assets/{OrgKeyPrompt-D95Zm3Tl.js → OrgKeyPrompt-NDfCQ-In.js} +1 -1
  52. package/web/assets/{ProcessControls-84xtt8ud.js → ProcessControls-D23gTUiv.js} +1 -1
  53. package/web/assets/{ProcessDetailPage-CqMk8XQv.js → ProcessDetailPage-vHpK0Eer.js} +1 -1
  54. package/web/assets/{ProjectCreateDialog-C4rLTHw0.js → ProjectCreateDialog-2PZX7tq2.js} +1 -1
  55. package/web/assets/{ProjectLocationGate-BtI0T-GU.js → ProjectLocationGate-fMAxwT0y.js} +1 -1
  56. package/web/assets/{ProjectPublishDialog-v5xz8t4N.js → ProjectPublishDialog-BylWoa0n.js} +1 -1
  57. package/web/assets/{RandomJobTestPage-CzT3LSMu.js → RandomJobTestPage-DUclmkBw.js} +1 -1
  58. package/web/assets/ScenarioEditorPage-DbEsfuZa.js +14 -0
  59. package/web/assets/{SendToChatDialog-BtsCq9hv.js → SendToChatDialog-DGuOMMrS.js} +1 -1
  60. package/web/assets/{ServiceControlsBar-BFemdioZ.js → ServiceControlsBar-D6M8hYFk.js} +1 -1
  61. package/web/assets/{ServiceDetailPage-DsGHPdUc.js → ServiceDetailPage-G-A9ryZD.js} +1 -1
  62. package/web/assets/{ServiceFormPage-x3jtyV1A.js → ServiceFormPage-BgHSW1XX.js} +1 -1
  63. package/web/assets/{SettingsPage-3tVWDaUN.js → SettingsPage-CPFBr7QE.js} +6 -6
  64. package/web/assets/{UnlockPage-CPcll-ov.js → UnlockPage-B4VEN9LN.js} +1 -1
  65. package/web/assets/{VaultMigrationPage-BMS4BcsA.js → VaultMigrationPage-9qDGbF9X.js} +1 -1
  66. package/web/assets/VersionBadge-CqHdCnuJ.js +1 -0
  67. package/web/assets/VersionBadge-CtFji3sv.css +1 -0
  68. package/web/assets/{WikiPage-CM1-hJvF.js → WikiPage-Pjosr1Vn.js} +1 -1
  69. package/web/assets/{WikiView-MQLuO7ey.js → WikiView-Bcxq2mQW.js} +1 -1
  70. package/web/assets/{add-scalar-classes-BDJ0Zhvc.js → add-scalar-classes-BnJYThbS.js} +2 -2
  71. package/web/assets/{agent.store-CEmOZ8XE.js → agent.store-DTyu_McS.js} +1 -1
  72. package/web/assets/auth-D_pCPFq7.js +2 -0
  73. package/web/assets/{cloud-chat.store-DhCEhagv.js → cloud-chat.store-CMklOB48.js} +1 -1
  74. package/web/assets/{cloud-client-CmrptmtM.js → cloud-client-CX0pW7Kt.js} +2 -2
  75. package/web/assets/cloud-session-ja0-uvVS.js +2 -0
  76. package/web/assets/{editor.store-Be5P5Eur.js → editor.store-BAjGG8Ji.js} +1 -1
  77. package/web/assets/i18n-CXvcscXP.js +1 -0
  78. package/web/assets/{index-CXnyET_X.js → index-DTrxphh3.js} +101 -101
  79. package/web/assets/index-eb4FRryj.css +1 -0
  80. package/web/assets/{modal-9BC14oRF.js → modal-Cvv2YgUo.js} +1 -1
  81. package/web/assets/{project-launch.store-cO8Wr508.js → project-launch.store-C7xfTlMc.js} +1 -1
  82. package/web/assets/{project.store-CpUEwUgF.js → project.store-ZpH_PaSy.js} +1 -1
  83. package/web/assets/scenario.store-F78cizck.js +7 -0
  84. package/web/assets/{service.store-ve_P4_2O.js → service.store-Dti7eDhR.js} +1 -1
  85. package/web/assets/{settings-scope-CcYu-GYo.js → settings-scope-CUuHrUpc.js} +1 -1
  86. package/web/assets/{settings.store-CdCOUAsL.js → settings.store-De1-3IG8.js} +1 -1
  87. package/web/assets/{src-T5uKA02c.js → src-C0KK-qsF.js} +1 -1
  88. package/web/assets/{src-RO7PD0gR.js → src-DXlxwMXe.js} +1 -1
  89. package/web/assets/{theme-CPaZfI9r.js → theme-BZCAxfJD.js} +1 -1
  90. package/web/assets/trpc-B5Yw_z6v.js +3 -0
  91. package/web/assets/{useCloudOrg-DaFUgt9j.js → useCloudOrg-QzX8ryg1.js} +1 -1
  92. package/web/assets/{useEnvVarAutocomplete-CXlyG01r.js → useEnvVarAutocomplete-BdGgINv9.js} +1 -1
  93. package/web/assets/{useProjectCatalog-1vLcCQlh.js → useProjectCatalog-Cr90BND4.js} +1 -1
  94. package/web/assets/{useProjectCloudOrg-MAfohLuM.js → useProjectCloudOrg-2wwByg2k.js} +1 -1
  95. package/web/assets/{useServiceUrlHost-D9k9s21s.js → useServiceUrlHost-CxbARDeg.js} +1 -1
  96. package/web/assets/{vue-draggable-plus-SmOauPHy.js → vue-draggable-plus-pTwVkhnN.js} +1 -1
  97. package/web/favicon.svg +1 -5
  98. package/web/index.html +18 -18
  99. package/agent-manager-RZI65MSV.js +0 -11
  100. package/chunk-G4TOLDZB.js.map +0 -1
  101. package/chunk-O2KOX4LU.js.map +0 -1
  102. package/chunk-QWX6R6AW.js.map +0 -1
  103. package/chunk-SYCUQDA4.js.map +0 -1
  104. package/desktop-installer-page-OKE4WY5Q.js.map +0 -1
  105. package/settings-manager-5JHSSKQ2.js +0 -10
  106. package/src-NVQHFMTQ.js.map +0 -1
  107. package/web/assets/ScenarioEditorPage-DrWcVOHg.js +0 -14
  108. package/web/assets/VersionBadge-54viPqlY.css +0 -1
  109. package/web/assets/VersionBadge-prnLNUGg.js +0 -1
  110. package/web/assets/auth-BpxI0N26.js +0 -2
  111. package/web/assets/cloud-session-ByODsQrA.js +0 -2
  112. package/web/assets/i18n-m0G6Pfwe.js +0 -1
  113. package/web/assets/index-Dsh11_J0.css +0 -1
  114. package/web/assets/scenario.store-B5uv1DSO.js +0 -7
  115. package/web/assets/trpc-BFA-mSM8.js +0 -3
  116. /package/{agent-manager-RZI65MSV.js.map → agent-manager-M4NA5YFD.js.map} +0 -0
  117. /package/{chat-L7RRHXX5.js.map → chat-X3X527EX.js.map} +0 -0
  118. /package/{chunk-GOMF7NWS.js.map → chunk-7L6AQUBR.js.map} +0 -0
  119. /package/{chunk-6HSZPK2W.js.map → chunk-UR3HL373.js.map} +0 -0
  120. /package/{companion-LQVLEHU7.js.map → companion-2LHKU577.js.map} +0 -0
  121. /package/{free-port-565NMFIZ.js.map → free-port-5UNHDWGE.js.map} +0 -0
  122. /package/{settings-manager-5JHSSKQ2.js.map → settings-manager-32SVMAFN.js.map} +0 -0
  123. /package/{vault-resolver-B5P2OUI5.js.map → vault-resolver-VK6W5J6W.js.map} +0 -0
@@ -62,10 +62,10 @@ import {
62
62
  soleAccountScope,
63
63
  startCliSession,
64
64
  vaultOfProject
65
- } from "./chunk-G4TOLDZB.js";
65
+ } from "./chunk-P73PTVII.js";
66
66
  import {
67
67
  settingsManager
68
- } from "./chunk-6HSZPK2W.js";
68
+ } from "./chunk-UR3HL373.js";
69
69
  import {
70
70
  LocalProjectRefusedError,
71
71
  activeSessionRegistry,
@@ -87,7 +87,7 @@ import {
87
87
  stopClaudeTranscriptWatcher,
88
88
  stopCodexTranscriptWatcher,
89
89
  verifyJwt
90
- } from "./chunk-QWX6R6AW.js";
90
+ } from "./chunk-NSS47H26.js";
91
91
  import {
92
92
  agentManager,
93
93
  agentSpawner,
@@ -126,13 +126,13 @@ import {
126
126
  stableEncryptValue,
127
127
  traefikManager,
128
128
  unregisterInstance
129
- } from "./chunk-SYCUQDA4.js";
129
+ } from "./chunk-GXE5TLLJ.js";
130
130
  import {
131
131
  atomicWriteSecure,
132
132
  renameWithRetry,
133
133
  resolveConversationRunDir,
134
134
  sweepStaleTempFiles
135
- } from "./chunk-GOMF7NWS.js";
135
+ } from "./chunk-7L6AQUBR.js";
136
136
  import "./chunk-MD3VW4HQ.js";
137
137
  import {
138
138
  AGENT_LONG_FETCH_TIMEOUT,
@@ -196,7 +196,7 @@ import {
196
196
  rememberOrgName,
197
197
  stampOrgCloud,
198
198
  vaultFor
199
- } from "./chunk-EV3TBM7E.js";
199
+ } from "./chunk-IXO5KIO5.js";
200
200
  import {
201
201
  decryptValueWith,
202
202
  encryptValueWith,
@@ -215,24 +215,74 @@ import { applyWSSHandler } from "@trpc/server/adapters/ws";
215
215
 
216
216
  // ../server/src/trpc/routers/health.ts
217
217
  import os from "os";
218
+ import { execFile as execFile2 } from "child_process";
219
+ import { promisify as promisify2 } from "util";
220
+ import { z } from "zod";
221
+
222
+ // ../server/src/services/npm-cli.ts
218
223
  import { execFile } from "child_process";
219
224
  import { promisify } from "util";
220
- import { z } from "zod";
225
+ import { existsSync, mkdtempSync, readFileSync, rmdirSync } from "fs";
226
+ import { dirname, isAbsolute, join, relative } from "path";
221
227
  var execFileAsync = promisify(execFile);
222
- async function getDockerVersion() {
228
+ var PACKAGE_NAME = "@runeya/runeya";
229
+ var INSTALL_TIMEOUT_MS = 10 * 6e4;
230
+ function resolveNpm() {
231
+ const nodeDir = dirname(process.execPath);
232
+ const candidates = [
233
+ // Windows (installateur officiel, nvm-windows, volta) : npm est un dossier
234
+ // frère de node.exe.
235
+ join(nodeDir, "node_modules", "npm", "bin", "npm-cli.js"),
236
+ // Unix : node est dans `bin/`, npm sous `lib/node_modules/`.
237
+ join(nodeDir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js")
238
+ ];
239
+ for (const cli2 of candidates) {
240
+ if (existsSync(cli2)) return { command: process.execPath, args: [cli2], shell: false };
241
+ }
242
+ if (process.platform === "win32") {
243
+ for (const entry of (process.env["PATH"] ?? "").split(";").filter(Boolean)) {
244
+ const cliCandidates = [
245
+ join(entry, "node_modules", "npm", "bin", "npm-cli.js"),
246
+ join(entry, "..", "npm", "bin", "npm-cli.js")
247
+ ];
248
+ for (const cli2 of cliCandidates) {
249
+ if (existsSync(cli2)) return { command: process.execPath, args: [cli2], shell: false };
250
+ }
251
+ }
252
+ throw new Error("Impossible de trouver npm-cli.js dans les emplacements connus du PATH Windows.");
253
+ }
254
+ return { command: "npm", args: [], shell: false };
255
+ }
256
+ function npmLabel(npm) {
257
+ return [npm.command, ...npm.args].join(" ");
258
+ }
259
+ async function probeVersion(npm, args) {
223
260
  try {
224
- const { stdout } = await execFileAsync("docker", ["--version"], {
225
- timeout: 3e3,
226
- windowsHide: true
261
+ const { stdout } = await execFileAsync(npm.command, [...npm.args, ...args], {
262
+ timeout: 1e4,
263
+ windowsHide: true,
264
+ shell: npm.shell
227
265
  });
228
- const match = /Docker version\s+([^,\s]+)/i.exec(stdout);
229
- return match?.[1] ?? (stdout.trim() || null);
266
+ return stdout.trim().split("\n")[0]?.trim() || null;
230
267
  } catch {
231
268
  return null;
232
269
  }
233
270
  }
234
- var startedAt = Date.now();
235
- var NPM_LATEST_URL = "https://registry.npmjs.org/@runeya%2Fruneya/latest";
271
+ async function installRuneyaGlobally(npm, prefix) {
272
+ try {
273
+ const { stdout, stderr } = await execFileAsync(
274
+ npm.command,
275
+ [...npm.args, "install", "-g", "--prefix", prefix, `${PACKAGE_NAME}@latest`],
276
+ { timeout: INSTALL_TIMEOUT_MS, windowsHide: true, shell: npm.shell, maxBuffer: 10 * 1024 * 1024 }
277
+ );
278
+ const installedVersion = await probeVersion(npm, ["view", `${PACKAGE_NAME}`, "version"]);
279
+ return { ok: true, output: [stdout, stderr].filter(Boolean).join("\n").trim(), installedVersion };
280
+ } catch (err) {
281
+ const e = err;
282
+ const output = [e.stdout, e.stderr, e.message].filter(Boolean).join("\n").trim();
283
+ return { ok: false, output, installedVersion: null };
284
+ }
285
+ }
236
286
  function compareSemver(a, b) {
237
287
  const pa = a.split(".").map((n) => Number.parseInt(n, 10) || 0);
238
288
  const pb = b.split(".").map((n) => Number.parseInt(n, 10) || 0);
@@ -244,6 +294,68 @@ function compareSemver(a, b) {
244
294
  }
245
295
  return 0;
246
296
  }
297
+ function installedRuneya(prefix, platform = process.platform) {
298
+ const modules = platform === "win32" ? join(prefix, "node_modules") : join(prefix, "lib", "node_modules");
299
+ const pkgDir = join(modules, ...PACKAGE_NAME.split("/"));
300
+ try {
301
+ const pkg = JSON.parse(readFileSync(join(pkgDir, "package.json"), "utf8"));
302
+ const bin = typeof pkg.bin === "string" ? pkg.bin : pkg.bin?.["runeya"];
303
+ return bin ? { entry: join(pkgDir, bin), version: pkg.version ?? "0.0.0" } : null;
304
+ } catch {
305
+ return null;
306
+ }
307
+ }
308
+ function globalCliEntry(prefix, platform = process.platform) {
309
+ return installedRuneya(prefix, platform)?.entry ?? null;
310
+ }
311
+ function userPrefix() {
312
+ return join(machineRoot(), "npm");
313
+ }
314
+ function isWritable(dir) {
315
+ let current2 = dir;
316
+ while (!existsSync(current2)) {
317
+ const parent = dirname(current2);
318
+ if (parent === current2) return false;
319
+ current2 = parent;
320
+ }
321
+ try {
322
+ rmdirSync(mkdtempSync(join(current2, ".runeya-write-test-")));
323
+ return true;
324
+ } catch {
325
+ return false;
326
+ }
327
+ }
328
+ function installPrefix(globalPrefix, platform = process.platform) {
329
+ const modules = platform === "win32" ? join(globalPrefix, "node_modules") : join(globalPrefix, "lib", "node_modules");
330
+ return isWritable(modules) ? globalPrefix : userPrefix();
331
+ }
332
+ function isInside(dir, path) {
333
+ const rel = relative(dir, path);
334
+ return rel !== "" && !rel.startsWith("..") && !isAbsolute(rel);
335
+ }
336
+ function updatePrefix(globalPrefix, runningEntry) {
337
+ if (isInside(userPrefix(), runningEntry)) return userPrefix();
338
+ if (!globalPrefix) return null;
339
+ if (isInside(globalPrefix, runningEntry)) return globalPrefix;
340
+ return installPrefix(globalPrefix);
341
+ }
342
+
343
+ // ../server/src/trpc/routers/health.ts
344
+ var execFileAsync2 = promisify2(execFile2);
345
+ async function getDockerVersion() {
346
+ try {
347
+ const { stdout } = await execFileAsync2("docker", ["--version"], {
348
+ timeout: 3e3,
349
+ windowsHide: true
350
+ });
351
+ const match = /Docker version\s+([^,\s]+)/i.exec(stdout);
352
+ return match?.[1] ?? (stdout.trim() || null);
353
+ } catch {
354
+ return null;
355
+ }
356
+ }
357
+ var startedAt = Date.now();
358
+ var NPM_LATEST_URL = "https://registry.npmjs.org/@runeya%2Fruneya/latest";
247
359
  var VERSION_CACHE_MS = 4 * 60 * 1e3;
248
360
  var versionCache = null;
249
361
  var FORCED_CHECK_FLOOR_MS = 2e3;
@@ -336,48 +448,37 @@ var healthRouter = router({
336
448
  })
337
449
  });
338
450
 
339
- // ../server/src/trpc/routers/app-update.ts
340
- import { spawn, execFile as execFile2 } from "child_process";
341
- import { promisify as promisify2 } from "util";
342
- import { existsSync } from "fs";
343
- import { dirname, join } from "path";
451
+ // ../server/src/trpc/routers/session.ts
344
452
  import { z as z2 } from "zod";
345
453
  import { TRPCError } from "@trpc/server";
346
- var execFileAsync2 = promisify2(execFile2);
347
- var PACKAGE_NAME = "@runeya/runeya";
348
- var INSTALL_TIMEOUT_MS = 10 * 6e4;
349
- function resolveNpm() {
350
- const nodeDir = dirname(process.execPath);
351
- const candidates = [
352
- // Windows (installateur officiel, nvm-windows, volta) : npm est un dossier
353
- // frère de node.exe.
354
- join(nodeDir, "node_modules", "npm", "bin", "npm-cli.js"),
355
- // Unix : node est dans `bin/`, npm sous `lib/node_modules/`.
356
- join(nodeDir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js")
357
- ];
358
- for (const cli2 of candidates) {
359
- if (existsSync(cli2)) return { command: process.execPath, args: [cli2], shell: false };
360
- }
361
- return process.platform === "win32" ? { command: "npm.cmd", args: [], shell: true } : { command: "npm", args: [], shell: false };
362
- }
363
- function npmLabel(npm) {
364
- return [npm.command, ...npm.args].join(" ");
365
- }
366
- async function probeVersion(npm, args) {
367
- try {
368
- const { stdout } = await execFileAsync2(npm.command, [...npm.args, ...args], {
369
- timeout: 1e4,
370
- windowsHide: true,
371
- shell: npm.shell
372
- });
373
- return stdout.trim().split("\n")[0]?.trim() || null;
374
- } catch {
375
- return null;
376
- }
377
- }
454
+ var sessionRouter = router({
455
+ /**
456
+ * Donne au WebSocket le jeton que l'onglet vient de renouveler.
457
+ *
458
+ * Le contexte d'un WebSocket est créé une fois, à la connexion : sans cet
459
+ * appel, chaque requête passée par la socket présenterait le jeton d'origine
460
+ * et serait refusée dès qu'il expire.
461
+ */
462
+ renewSocket: publicProcedure.input(z2.object({ token: z2.string().min(1).max(4096) })).mutation(async ({ ctx, input }) => {
463
+ if (!ctx.renewSocketToken) {
464
+ throw new TRPCError({ code: "BAD_REQUEST", message: "Only available over the WebSocket" });
465
+ }
466
+ try {
467
+ await ctx.renewSocketToken(input.token);
468
+ } catch {
469
+ throw new TRPCError({ code: "UNAUTHORIZED", message: "Invalid or expired token" });
470
+ }
471
+ return { ok: true };
472
+ })
473
+ });
474
+
475
+ // ../server/src/trpc/routers/app-update.ts
476
+ import { spawn } from "child_process";
477
+ import { z as z3 } from "zod";
478
+ import { TRPCError as TRPCError2 } from "@trpc/server";
378
479
  function requireDesktop() {
379
480
  if (!env.FROM_DESKTOP) {
380
- throw new TRPCError({
481
+ throw new TRPCError2({
381
482
  code: "PRECONDITION_FAILED",
382
483
  message: "Update from the app is only available for desktop launches."
383
484
  });
@@ -386,19 +487,20 @@ function requireDesktop() {
386
487
  var appUpdateRouter = router({
387
488
  /** De quoi la mise à jour a besoin, et ce que la machine en offre. */
388
489
  prerequisites: publicProcedure.output(
389
- z2.object({
390
- fromDesktop: z2.boolean(),
391
- nodeVersion: z2.string(),
392
- npmVersion: z2.string().nullable(),
393
- npmPath: z2.string(),
394
- globalPrefix: z2.string().nullable(),
395
- ready: z2.boolean()
490
+ z3.object({
491
+ fromDesktop: z3.boolean(),
492
+ nodeVersion: z3.string(),
493
+ npmVersion: z3.string().nullable(),
494
+ npmPath: z3.string(),
495
+ globalPrefix: z3.string().nullable(),
496
+ ready: z3.boolean()
396
497
  })
397
498
  ).query(async ({ ctx }) => {
398
499
  await requireLoopbackOrToken(ctx);
399
500
  const npm = resolveNpm();
400
501
  const npmVersion = await probeVersion(npm, ["--version"]);
401
- const globalPrefix = npmVersion ? await probeVersion(npm, ["prefix", "-g"]) : null;
502
+ const npmPrefix = npmVersion ? await probeVersion(npm, ["prefix", "-g"]) : null;
503
+ const globalPrefix = updatePrefix(npmPrefix, process.argv[1] ?? "");
402
504
  return {
403
505
  fromDesktop: env.FROM_DESKTOP,
404
506
  nodeVersion: process.version,
@@ -416,28 +518,18 @@ var appUpdateRouter = router({
416
518
  * est la seule chose qui dit à l'utilisateur quoi faire.
417
519
  */
418
520
  install: publicProcedure.output(
419
- z2.object({
420
- ok: z2.boolean(),
421
- output: z2.string(),
422
- installedVersion: z2.string().nullable()
521
+ z3.object({
522
+ ok: z3.boolean(),
523
+ output: z3.string(),
524
+ installedVersion: z3.string().nullable()
423
525
  })
424
526
  ).mutation(async ({ ctx }) => {
425
527
  await requireLoopbackOrToken(ctx);
426
528
  requireDesktop();
427
529
  const npm = resolveNpm();
428
- try {
429
- const { stdout, stderr } = await execFileAsync2(
430
- npm.command,
431
- [...npm.args, "install", "-g", `${PACKAGE_NAME}@latest`],
432
- { timeout: INSTALL_TIMEOUT_MS, windowsHide: true, shell: npm.shell, maxBuffer: 10 * 1024 * 1024 }
433
- );
434
- const installedVersion = await probeVersion(npm, ["view", `${PACKAGE_NAME}`, "version"]);
435
- return { ok: true, output: [stdout, stderr].filter(Boolean).join("\n").trim(), installedVersion };
436
- } catch (err) {
437
- const e = err;
438
- const output = [e.stdout, e.stderr, e.message].filter(Boolean).join("\n").trim();
439
- return { ok: false, output, installedVersion: null };
440
- }
530
+ const prefix = updatePrefix(await probeVersion(npm, ["prefix", "-g"]), process.argv[1] ?? "");
531
+ if (!prefix) return { ok: false, output: "npm ne r\xE9pond pas : impossible de trouver o\xF9 installer Runeya.", installedVersion: null };
532
+ return installRuneyaGlobally(npm, prefix);
441
533
  }),
442
534
  /**
443
535
  * Relance Runeya, puis rend la main au nouveau process.
@@ -447,7 +539,7 @@ var appUpdateRouter = router({
447
539
  * quelques instants — le démarrage réessaie déjà sur EADDRINUSE, c'est ce qui
448
540
  * rend ce relais possible sans temporisation ici.
449
541
  */
450
- restart: publicProcedure.output(z2.object({ restarting: z2.literal(true), version: z2.string() })).mutation(async ({ ctx }) => {
542
+ restart: publicProcedure.output(z3.object({ restarting: z3.literal(true), version: z3.string() })).mutation(async ({ ctx }) => {
451
543
  await requireLoopbackOrToken(ctx);
452
544
  requireDesktop();
453
545
  const child = spawn(process.execPath, process.argv.slice(1), {
@@ -472,7 +564,7 @@ var appUpdateRouter = router({
472
564
  });
473
565
 
474
566
  // ../server/src/trpc/routers/changelog.ts
475
- import { z as z3 } from "zod";
567
+ import { z as z4 } from "zod";
476
568
  var CACHE_MS = 5 * 60 * 1e3;
477
569
  var cache = /* @__PURE__ */ new Map();
478
570
  async function cloudChangelog(path, params) {
@@ -493,38 +585,38 @@ async function cloudChangelog(path, params) {
493
585
  function appCeiling() {
494
586
  return appVersion === "dev" ? null : appVersion;
495
587
  }
496
- var inputSchema = z3.object({
588
+ var inputSchema = z4.object({
497
589
  surface: ChangelogSurfaceSchema,
498
590
  /** Dernière version déjà vue par ce navigateur, exclue du résultat. */
499
- since: z3.string().max(32).nullish()
591
+ since: z4.string().max(32).nullish()
500
592
  });
501
593
  var changelogRouter = router({
502
594
  /** Ce qu'il y a à lire, sans les corps. */
503
- index: publicProcedure.input(inputSchema).output(z3.object({ releases: z3.array(ChangelogIndexItemSchema), currentAppVersion: z3.string() })).query(async ({ input }) => {
595
+ index: publicProcedure.input(inputSchema).output(z4.object({ releases: z4.array(ChangelogIndexItemSchema), currentAppVersion: z4.string() })).query(async ({ input }) => {
504
596
  const data = await cloudChangelog("/api/changelog", {
505
597
  surface: input.surface,
506
598
  since: input.since ?? null,
507
599
  until: input.surface === "app" ? appCeiling() : null
508
600
  });
509
- const parsed = z3.object({ releases: z3.array(ChangelogIndexItemSchema) }).parse(data);
601
+ const parsed = z4.object({ releases: z4.array(ChangelogIndexItemSchema) }).parse(data);
510
602
  return { releases: parsed.releases, currentAppVersion: appVersion };
511
603
  }),
512
604
  /** Les entrées complètes. */
513
- releases: publicProcedure.input(inputSchema).output(z3.object({ releases: z3.array(ChangelogReleaseSchema), currentAppVersion: z3.string() })).query(async ({ input }) => {
605
+ releases: publicProcedure.input(inputSchema).output(z4.object({ releases: z4.array(ChangelogReleaseSchema), currentAppVersion: z4.string() })).query(async ({ input }) => {
514
606
  const data = await cloudChangelog("/api/changelog/releases", {
515
607
  surface: input.surface,
516
608
  since: input.since ?? null,
517
609
  until: input.surface === "app" ? appCeiling() : null
518
610
  });
519
- const parsed = z3.object({ releases: z3.array(ChangelogReleaseSchema) }).parse(data);
611
+ const parsed = z4.object({ releases: z4.array(ChangelogReleaseSchema) }).parse(data);
520
612
  return { releases: parsed.releases, currentAppVersion: appVersion };
521
613
  })
522
614
  });
523
615
 
524
616
  // ../server/src/trpc/routers/project.ts
525
- import { z as z4 } from "zod";
526
- import { dirname as dirname2, isAbsolute } from "path";
527
- import { TRPCError as TRPCError2 } from "@trpc/server";
617
+ import { z as z5 } from "zod";
618
+ import { dirname as dirname2, isAbsolute as isAbsolute2 } from "path";
619
+ import { TRPCError as TRPCError3 } from "@trpc/server";
528
620
 
529
621
  // ../server/src/services/current-project.ts
530
622
  var current = null;
@@ -850,7 +942,7 @@ async function assertReadable(orgId) {
850
942
  await assertOrgVaultReadable(orgId);
851
943
  } catch (err) {
852
944
  if (err instanceof OrgVaultUnreadableError) {
853
- throw new TRPCError2({ code: "FORBIDDEN", message: err.message });
945
+ throw new TRPCError3({ code: "FORBIDDEN", message: err.message });
854
946
  }
855
947
  throw err;
856
948
  }
@@ -863,10 +955,10 @@ var projectRouter = router({
863
955
  * `orgId` names which project — the same id can exist in several
864
956
  * organizations. Left out, the id must answer for exactly one project.
865
957
  */
866
- get: protectedProcedure.input(z4.object({ id: z4.string().max(128), orgId: z4.string().max(128).nullable().optional() })).query(async ({ input }) => {
958
+ get: protectedProcedure.input(z5.object({ id: z5.string().max(128), orgId: z5.string().max(128).nullable().optional() })).query(async ({ input }) => {
867
959
  const project = await projectStore.get(input);
868
960
  if (!project) {
869
- throw new TRPCError2({ code: "NOT_FOUND", message: `Project ${input.id} not found` });
961
+ throw new TRPCError3({ code: "NOT_FOUND", message: `Project ${input.id} not found` });
870
962
  }
871
963
  await assertReadable(project.orgId);
872
964
  return project;
@@ -877,23 +969,23 @@ var projectRouter = router({
877
969
  * Environments are intentionally excluded — they carry secret values that
878
970
  * stay local.
879
971
  */
880
- export: protectedProcedure.input(z4.object({ id: z4.string().max(128), orgId: z4.string().max(128).nullable().optional() })).query(async ({ input }) => {
972
+ export: protectedProcedure.input(z5.object({ id: z5.string().max(128), orgId: z5.string().max(128).nullable().optional() })).query(async ({ input }) => {
881
973
  const project = await projectStore.get(input);
882
974
  if (!project) {
883
- throw new TRPCError2({ code: "NOT_FOUND", message: `Project ${input.id} not found` });
975
+ throw new TRPCError3({ code: "NOT_FOUND", message: `Project ${input.id} not found` });
884
976
  }
885
977
  await assertReadable(project.orgId);
886
978
  const services = (await Promise.all(project.serviceIds.map((sid) => serviceStore.getSanitized(sid)))).filter((s) => s !== null);
887
979
  return { project, services };
888
980
  }),
889
981
  create: protectedProcedure.input(
890
- z4.object({
891
- name: z4.string().min(1).max(200),
892
- description: z4.string().max(1e4).optional(),
893
- orgId: z4.string().max(128).nullable().optional(),
894
- serviceIds: z4.array(z4.string().max(128)).max(1e4).optional(),
982
+ z5.object({
983
+ name: z5.string().min(1).max(200),
984
+ description: z5.string().max(1e4).optional(),
985
+ orgId: z5.string().max(128).nullable().optional(),
986
+ serviceIds: z5.array(z5.string().max(128)).max(1e4).optional(),
895
987
  /** Le dossier d'un projet local. Omis : le dossier de lancement. */
896
- localPath: z4.string().min(1).max(4096).refine(isAbsolute, "Chemin absolu attendu").optional()
988
+ localPath: z5.string().min(1).max(4096).refine(isAbsolute2, "Chemin absolu attendu").optional()
897
989
  })
898
990
  ).mutation(async ({ input }) => {
899
991
  const { localPath, ...fields } = input;
@@ -907,9 +999,9 @@ var projectRouter = router({
907
999
  }, fields.orgId ? void 0 : localPath);
908
1000
  } catch (err) {
909
1001
  if (err instanceof LocalProjectRefusedError) {
910
- throw new TRPCError2({ code: "CONFLICT", message: err.code, cause: err });
1002
+ throw new TRPCError3({ code: "CONFLICT", message: err.code, cause: err });
911
1003
  }
912
- throw new TRPCError2({ code: "CONFLICT", message: err.message });
1004
+ throw new TRPCError3({ code: "CONFLICT", message: err.message });
913
1005
  }
914
1006
  const localEnv = await environmentStore.create({
915
1007
  projectId: project.id,
@@ -928,38 +1020,38 @@ var projectRouter = router({
928
1020
  return result;
929
1021
  }),
930
1022
  update: protectedProcedure.input(
931
- z4.object({
932
- id: z4.string().max(128),
933
- name: z4.string().min(1).max(200).optional(),
934
- description: z4.string().max(1e4).optional(),
935
- orgId: z4.string().max(128).nullable().optional(),
936
- serviceIds: z4.array(z4.string().max(128)).max(1e4).optional(),
937
- groupOrder: z4.array(z4.string().max(200)).max(100).optional()
1023
+ z5.object({
1024
+ id: z5.string().max(128),
1025
+ name: z5.string().min(1).max(200).optional(),
1026
+ description: z5.string().max(1e4).optional(),
1027
+ orgId: z5.string().max(128).nullable().optional(),
1028
+ serviceIds: z5.array(z5.string().max(128)).max(1e4).optional(),
1029
+ groupOrder: z5.array(z5.string().max(200)).max(100).optional()
938
1030
  })
939
1031
  ).mutation(async ({ input }) => {
940
1032
  const project = await projectStore.update(input);
941
1033
  if (!project) {
942
- throw new TRPCError2({ code: "NOT_FOUND", message: `Project ${input.id} not found` });
1034
+ throw new TRPCError3({ code: "NOT_FOUND", message: `Project ${input.id} not found` });
943
1035
  }
944
1036
  await auditService.log({ userId: "local", action: "update", entityType: "project", entityId: input.id });
945
1037
  return project;
946
1038
  }),
947
- delete: protectedProcedure.input(z4.object({ id: z4.string().max(128), orgId: z4.string().max(128).nullable().optional() })).mutation(async ({ input }) => {
1039
+ delete: protectedProcedure.input(z5.object({ id: z5.string().max(128), orgId: z5.string().max(128).nullable().optional() })).mutation(async ({ input }) => {
948
1040
  const deleted = await projectStore.delete(input);
949
1041
  if (!deleted) {
950
- throw new TRPCError2({ code: "NOT_FOUND", message: `Project ${input.id} not found` });
1042
+ throw new TRPCError3({ code: "NOT_FOUND", message: `Project ${input.id} not found` });
951
1043
  }
952
1044
  await auditService.log({ userId: "local", action: "delete", entityType: "project", entityId: input.id });
953
1045
  return { success: true };
954
1046
  }),
955
- addService: protectedProcedure.input(z4.object({
956
- projectId: z4.string().max(128),
957
- orgId: z4.string().max(128).nullable().optional(),
958
- serviceId: z4.string().max(128)
1047
+ addService: protectedProcedure.input(z5.object({
1048
+ projectId: z5.string().max(128),
1049
+ orgId: z5.string().max(128).nullable().optional(),
1050
+ serviceId: z5.string().max(128)
959
1051
  })).mutation(async ({ input }) => {
960
1052
  const project = await attachServiceToProject({ id: input.projectId, orgId: input.orgId }, input.serviceId);
961
1053
  if (!project) {
962
- throw new TRPCError2({ code: "NOT_FOUND", message: `Project ${input.projectId} not found` });
1054
+ throw new TRPCError3({ code: "NOT_FOUND", message: `Project ${input.projectId} not found` });
963
1055
  }
964
1056
  await auditService.log({
965
1057
  userId: "local",
@@ -970,17 +1062,17 @@ var projectRouter = router({
970
1062
  });
971
1063
  return project;
972
1064
  }),
973
- removeService: protectedProcedure.input(z4.object({
974
- projectId: z4.string().max(128),
975
- orgId: z4.string().max(128).nullable().optional(),
976
- serviceId: z4.string().max(128)
1065
+ removeService: protectedProcedure.input(z5.object({
1066
+ projectId: z5.string().max(128),
1067
+ orgId: z5.string().max(128).nullable().optional(),
1068
+ serviceId: z5.string().max(128)
977
1069
  })).mutation(async ({ input }) => {
978
1070
  const project = await projectStore.removeService(
979
1071
  { id: input.projectId, orgId: input.orgId },
980
1072
  input.serviceId
981
1073
  );
982
1074
  if (!project) {
983
- throw new TRPCError2({ code: "NOT_FOUND", message: `Project ${input.projectId} not found` });
1075
+ throw new TRPCError3({ code: "NOT_FOUND", message: `Project ${input.projectId} not found` });
984
1076
  }
985
1077
  await auditService.log({
986
1078
  userId: "local",
@@ -991,21 +1083,21 @@ var projectRouter = router({
991
1083
  });
992
1084
  return project;
993
1085
  }),
994
- setActiveEnvironment: protectedProcedure.input(z4.object({
995
- projectId: z4.string().max(128),
996
- orgId: z4.string().max(128).nullable().optional(),
997
- environmentId: z4.string().max(128)
1086
+ setActiveEnvironment: protectedProcedure.input(z5.object({
1087
+ projectId: z5.string().max(128),
1088
+ orgId: z5.string().max(128).nullable().optional(),
1089
+ environmentId: z5.string().max(128)
998
1090
  })).mutation(async ({ input }) => {
999
1091
  const project = await projectStore.get({ id: input.projectId, orgId: input.orgId });
1000
1092
  if (!project) {
1001
- throw new TRPCError2({ code: "NOT_FOUND", message: `Project ${input.projectId} not found` });
1093
+ throw new TRPCError3({ code: "NOT_FOUND", message: `Project ${input.projectId} not found` });
1002
1094
  }
1003
1095
  const environment = await environmentStore.get(input.environmentId);
1004
1096
  if (!environment) {
1005
- throw new TRPCError2({ code: "NOT_FOUND", message: `Environment ${input.environmentId} not found` });
1097
+ throw new TRPCError3({ code: "NOT_FOUND", message: `Environment ${input.environmentId} not found` });
1006
1098
  }
1007
1099
  if (environment.projectId !== input.projectId) {
1008
- throw new TRPCError2({ code: "FORBIDDEN", message: "Environment does not belong to this project" });
1100
+ throw new TRPCError3({ code: "FORBIDDEN", message: "Environment does not belong to this project" });
1009
1101
  }
1010
1102
  const runningServices = [];
1011
1103
  for (const serviceId of project.serviceIds) {
@@ -1030,7 +1122,7 @@ var projectRouter = router({
1030
1122
  input.environmentId
1031
1123
  );
1032
1124
  if (!updated) {
1033
- throw new TRPCError2({ code: "INTERNAL_SERVER_ERROR", message: "Failed to set active environment" });
1125
+ throw new TRPCError3({ code: "INTERNAL_SERVER_ERROR", message: "Failed to set active environment" });
1034
1126
  }
1035
1127
  for (const serviceId of project.serviceIds) {
1036
1128
  const service = await serviceStore.get(serviceId);
@@ -1079,7 +1171,7 @@ var projectRouter = router({
1079
1171
  * système s'en sert, pour montrer les services du projet ouvert plutôt que
1080
1172
  * ceux de toute la machine.
1081
1173
  */
1082
- setCurrent: protectedProcedure.input(z4.object({ id: z4.string().max(128), orgId: z4.string().max(128).nullable().default(null) }).nullable()).mutation(({ input }) => {
1174
+ setCurrent: protectedProcedure.input(z5.object({ id: z5.string().max(128), orgId: z5.string().max(128).nullable().default(null) }).nullable()).mutation(({ input }) => {
1083
1175
  setCurrentProject(input ? { id: input.id, orgId: input.orgId } : null);
1084
1176
  return { ok: true };
1085
1177
  }),
@@ -1095,13 +1187,13 @@ var projectRouter = router({
1095
1187
  * des secrets déchiffrés : elles servent à détecter la référence, et
1096
1188
  * s'arrêtent là.
1097
1189
  */
1098
- graph: protectedProcedure.input(z4.object({
1099
- id: z4.string().min(1).max(128),
1100
- orgId: z4.string().max(128).nullable().optional()
1190
+ graph: protectedProcedure.input(z5.object({
1191
+ id: z5.string().min(1).max(128),
1192
+ orgId: z5.string().max(128).nullable().optional()
1101
1193
  })).query(async ({ ctx, input }) => {
1102
1194
  const project = await projectStore.get(input);
1103
1195
  if (!project) {
1104
- throw new TRPCError2({ code: "NOT_FOUND", message: `Project ${input.id} not found` });
1196
+ throw new TRPCError3({ code: "NOT_FOUND", message: `Project ${input.id} not found` });
1105
1197
  }
1106
1198
  await assertReadable(project.orgId);
1107
1199
  const allowed = getAllowedServiceIds(ctx);
@@ -1143,9 +1235,9 @@ var projectRouter = router({
1143
1235
  }
1144
1236
  return paths;
1145
1237
  }),
1146
- getLocalPath: protectedProcedure.input(z4.object({
1147
- id: z4.string().min(1).max(128),
1148
- orgId: z4.string().max(128).nullable().optional()
1238
+ getLocalPath: protectedProcedure.input(z5.object({
1239
+ id: z5.string().min(1).max(128),
1240
+ orgId: z5.string().max(128).nullable().optional()
1149
1241
  })).query(async ({ input }) => {
1150
1242
  return { path: await projectPathStore.get(input) };
1151
1243
  }),
@@ -1157,34 +1249,34 @@ var projectRouter = router({
1157
1249
  * makes services run against the wrong code.
1158
1250
  */
1159
1251
  /** Ajouter à la liste le projet local déjà présent dans un dossier. */
1160
- importLocal: protectedProcedure.input(z4.object({ path: z4.string().min(1).max(4096).refine(isAbsolute, "Chemin absolu attendu") })).mutation(async ({ input }) => {
1252
+ importLocal: protectedProcedure.input(z5.object({ path: z5.string().min(1).max(4096).refine(isAbsolute2, "Chemin absolu attendu") })).mutation(async ({ input }) => {
1161
1253
  try {
1162
1254
  const project = await projectStore.importLocal(input.path);
1163
1255
  await auditService.log({ userId: "local", action: "update", entityType: "project", entityId: project.id, metadata: { importedFrom: input.path } });
1164
1256
  return project;
1165
1257
  } catch (err) {
1166
1258
  if (err instanceof LocalProjectRefusedError) {
1167
- throw new TRPCError2({ code: "CONFLICT", message: err.code, cause: err });
1259
+ throw new TRPCError3({ code: "CONFLICT", message: err.code, cause: err });
1168
1260
  }
1169
1261
  throw err;
1170
1262
  }
1171
1263
  }),
1172
- setLocalPath: protectedProcedure.input(z4.object({
1173
- id: z4.string().min(1).max(128),
1174
- orgId: z4.string().max(128).nullable().optional(),
1175
- path: z4.string().min(1).max(4096)
1264
+ setLocalPath: protectedProcedure.input(z5.object({
1265
+ id: z5.string().min(1).max(128),
1266
+ orgId: z5.string().max(128).nullable().optional(),
1267
+ path: z5.string().min(1).max(4096)
1176
1268
  })).mutation(async ({ input }) => {
1177
1269
  const project = await projectStore.get(input);
1178
- if (!project) throw new TRPCError2({ code: "NOT_FOUND", message: "Projet introuvable" });
1270
+ if (!project) throw new TRPCError3({ code: "NOT_FOUND", message: "Projet introuvable" });
1179
1271
  if (await holdsRuneyaProject(input.path)) {
1180
- throw new TRPCError2({
1272
+ throw new TRPCError3({
1181
1273
  code: "CONFLICT",
1182
1274
  message: "Ce r\xE9pertoire contient d\xE9j\xE0 un projet Runeya"
1183
1275
  });
1184
1276
  }
1185
- const taken = await projectPathStore.projectAt(input.path, project);
1277
+ const taken = await projectStore.projectAtPath(input.path, project);
1186
1278
  if (taken) {
1187
- throw new TRPCError2({
1279
+ throw new TRPCError3({
1188
1280
  code: "CONFLICT",
1189
1281
  message: "Un autre projet est d\xE9j\xE0 rattach\xE9 \xE0 ce r\xE9pertoire"
1190
1282
  });
@@ -1253,8 +1345,8 @@ var projectRouter = router({
1253
1345
  });
1254
1346
 
1255
1347
  // ../server/src/trpc/routers/agent.ts
1256
- import { z as z5 } from "zod";
1257
- import { TRPCError as TRPCError3 } from "@trpc/server";
1348
+ import { z as z6 } from "zod";
1349
+ import { TRPCError as TRPCError4 } from "@trpc/server";
1258
1350
  var SUBSCRIPTION_QUEUE_MAX = LOG_BUFFER_SIZE;
1259
1351
  var agentRouter = router({
1260
1352
  /** List all registered agents with their connection status */
@@ -1262,10 +1354,10 @@ var agentRouter = router({
1262
1354
  return agentManager.listAgents();
1263
1355
  }),
1264
1356
  /** Get a single agent's config and status */
1265
- get: protectedProcedure.input(z5.object({ id: z5.string().max(128) })).query(({ input }) => {
1357
+ get: protectedProcedure.input(z6.object({ id: z6.string().max(128) })).query(({ input }) => {
1266
1358
  const agent = agentManager.getAgent(input.id);
1267
1359
  if (!agent) {
1268
- throw new TRPCError3({ code: "NOT_FOUND", message: `Agent ${input.id} not found` });
1360
+ throw new TRPCError4({ code: "NOT_FOUND", message: `Agent ${input.id} not found` });
1269
1361
  }
1270
1362
  return {
1271
1363
  config: { ...agent.config, passphrase: "***" },
@@ -1274,10 +1366,10 @@ var agentRouter = router({
1274
1366
  }),
1275
1367
  /** Test connectivity to an agent given url + passphrase */
1276
1368
  testConnection: protectedProcedure.input(
1277
- z5.object({
1278
- url: z5.string().url().max(2048),
1279
- passphrase: z5.string().min(1).max(1024).optional(),
1280
- agentId: z5.string().max(128).optional()
1369
+ z6.object({
1370
+ url: z6.string().url().max(2048),
1371
+ passphrase: z6.string().min(1).max(1024).optional(),
1372
+ agentId: z6.string().max(128).optional()
1281
1373
  })
1282
1374
  ).mutation(async ({ input }) => {
1283
1375
  let passphrase = input.passphrase;
@@ -1285,13 +1377,13 @@ var agentRouter = router({
1285
1377
  if (!passphrase && input.agentId) {
1286
1378
  const agent = agentManager.getAgentConfig(input.agentId);
1287
1379
  if (!agent) {
1288
- throw new TRPCError3({ code: "NOT_FOUND", message: "Agent not found" });
1380
+ throw new TRPCError4({ code: "NOT_FOUND", message: "Agent not found" });
1289
1381
  }
1290
1382
  passphrase = agent.passphrase;
1291
1383
  targetUrl = agent.url;
1292
1384
  }
1293
1385
  if (!passphrase) {
1294
- throw new TRPCError3({ code: "BAD_REQUEST", message: "Passphrase is required" });
1386
+ throw new TRPCError4({ code: "BAD_REQUEST", message: "Passphrase is required" });
1295
1387
  }
1296
1388
  const url = new URL("/api/trpc/health.check", targetUrl);
1297
1389
  try {
@@ -1314,13 +1406,13 @@ var agentRouter = router({
1314
1406
  }),
1315
1407
  /** Register a new agent */
1316
1408
  register: protectedProcedure.input(
1317
- z5.object({
1318
- name: z5.string().min(1).max(100),
1319
- url: z5.string().url().max(2048),
1320
- passphrase: z5.string().min(1).max(1024),
1409
+ z6.object({
1410
+ name: z6.string().min(1).max(100),
1411
+ url: z6.string().url().max(2048),
1412
+ passphrase: z6.string().min(1).max(1024),
1321
1413
  // À quelle organisation rattacher l'agent. Absent = la machine, ce que
1322
1414
  // font l'agent local et tout client antérieur à ce champ.
1323
- orgId: z5.string().min(1).max(128).nullable().optional()
1415
+ orgId: z6.string().min(1).max(128).nullable().optional()
1324
1416
  })
1325
1417
  ).mutation(async ({ input }) => {
1326
1418
  const config = await agentManager.register(
@@ -1333,13 +1425,13 @@ var agentRouter = router({
1333
1425
  }),
1334
1426
  /** Update an existing agent */
1335
1427
  update: protectedProcedure.input(
1336
- z5.object({
1337
- id: z5.string().max(128),
1338
- name: z5.string().min(1).max(100).optional(),
1339
- url: z5.string().url().max(2048).optional(),
1340
- passphrase: z5.string().min(1).max(1024).optional(),
1341
- passthroughEnv: z5.array(
1342
- z5.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/).max(256)
1428
+ z6.object({
1429
+ id: z6.string().max(128),
1430
+ name: z6.string().min(1).max(100).optional(),
1431
+ url: z6.string().url().max(2048).optional(),
1432
+ passphrase: z6.string().min(1).max(1024).optional(),
1433
+ passthroughEnv: z6.array(
1434
+ z6.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/).max(256)
1343
1435
  ).max(100).optional()
1344
1436
  })
1345
1437
  ).mutation(async ({ input }) => {
@@ -1350,17 +1442,17 @@ var agentRouter = router({
1350
1442
  } catch (err) {
1351
1443
  if (err instanceof Error) {
1352
1444
  if (err.message.includes("not found")) {
1353
- throw new TRPCError3({ code: "NOT_FOUND", message: err.message });
1445
+ throw new TRPCError4({ code: "NOT_FOUND", message: err.message });
1354
1446
  }
1355
1447
  if (err.message.includes("Cannot modify")) {
1356
- throw new TRPCError3({ code: "FORBIDDEN", message: err.message });
1448
+ throw new TRPCError4({ code: "FORBIDDEN", message: err.message });
1357
1449
  }
1358
1450
  }
1359
1451
  throw err;
1360
1452
  }
1361
1453
  }),
1362
1454
  /** Get resolved passthrough env values from an agent */
1363
- getPassthroughEnv: protectedProcedure.input(z5.object({ id: z5.string().max(128) })).query(async ({ input }) => {
1455
+ getPassthroughEnv: protectedProcedure.input(z6.object({ id: z6.string().max(128) })).query(async ({ input }) => {
1364
1456
  try {
1365
1457
  return await agentManager.agentQuery(input.id, "config.getPassthroughEnv");
1366
1458
  } catch {
@@ -1368,16 +1460,16 @@ var agentRouter = router({
1368
1460
  }
1369
1461
  }),
1370
1462
  /** Remove a registered agent */
1371
- remove: protectedProcedure.input(z5.object({ id: z5.string().max(128) })).mutation(async ({ input }) => {
1463
+ remove: protectedProcedure.input(z6.object({ id: z6.string().max(128) })).mutation(async ({ input }) => {
1372
1464
  try {
1373
1465
  const removed = await agentManager.remove(input.id);
1374
1466
  if (!removed) {
1375
- throw new TRPCError3({ code: "NOT_FOUND", message: `Agent ${input.id} not found` });
1467
+ throw new TRPCError4({ code: "NOT_FOUND", message: `Agent ${input.id} not found` });
1376
1468
  }
1377
1469
  return { success: true };
1378
1470
  } catch (err) {
1379
1471
  if (err instanceof Error && err.message === "Cannot remove the local agent") {
1380
- throw new TRPCError3({ code: "FORBIDDEN", message: err.message });
1472
+ throw new TRPCError4({ code: "FORBIDDEN", message: err.message });
1381
1473
  }
1382
1474
  throw err;
1383
1475
  }
@@ -1415,16 +1507,16 @@ var agentRouter = router({
1415
1507
  });
1416
1508
 
1417
1509
  // ../server/src/trpc/routers/process.ts
1418
- import { z as z6 } from "zod";
1419
- import { TRPCError as TRPCError5 } from "@trpc/server";
1510
+ import { z as z7 } from "zod";
1511
+ import { TRPCError as TRPCError6 } from "@trpc/server";
1420
1512
 
1421
1513
  // ../server/src/services/process-control.ts
1422
- import { TRPCError as TRPCError4 } from "@trpc/server";
1514
+ import { TRPCError as TRPCError5 } from "@trpc/server";
1423
1515
  async function resolveTarget(processId, fallbackAgentId) {
1424
1516
  const service = await serviceStore.get(processId) ?? null;
1425
1517
  const agentId = (service ? await resolveEffectiveAgentId(service) : null) ?? fallbackAgentId ?? null;
1426
1518
  if (!agentId) {
1427
- throw new TRPCError4({
1519
+ throw new TRPCError5({
1428
1520
  code: "BAD_REQUEST",
1429
1521
  message: "No agent assigned to this service. Set an agent on the service or on the active environment."
1430
1522
  });
@@ -1440,7 +1532,7 @@ async function assertEnvironmentComplete(service) {
1440
1532
  activeEnvironmentId: project.activeEnvironmentId
1441
1533
  });
1442
1534
  if (missing.length === 0) return;
1443
- throw new TRPCError4({
1535
+ throw new TRPCError5({
1444
1536
  code: "PRECONDITION_FAILED",
1445
1537
  message: `Missing environment variables: ${missing.map((m) => m.key).join(", ")}`,
1446
1538
  cause: { missingVariables: missing, environmentId: project.activeEnvironmentId }
@@ -1474,7 +1566,7 @@ async function startProcess(processId, fallbackAgentId) {
1474
1566
  } catch (err) {
1475
1567
  const err_ = err;
1476
1568
  const isFetchError = err_?.cause?.code === "ECONNREFUSED" || err_?.message === "fetch failed" || err_?.name === "TypeError";
1477
- throw new TRPCError4({
1569
+ throw new TRPCError5({
1478
1570
  code: "INTERNAL_SERVER_ERROR",
1479
1571
  message: isFetchError ? `Cannot reach agent \u2014 make sure the agent is running` : err_?.message ?? "Failed to start process"
1480
1572
  });
@@ -1581,13 +1673,13 @@ async function* forwardLogBatches(agentId, processId) {
1581
1673
  }
1582
1674
  var processRouter = router({
1583
1675
  /** List all processes across all connected agents */
1584
- list: protectedProcedure.meta({ openapi: { method: "GET", path: "/processes", tags: ["processes"], summary: "List all processes", protect: true } }).output(z6.any()).query(() => listAllProcesses()),
1676
+ list: protectedProcedure.meta({ openapi: { method: "GET", path: "/processes", tags: ["processes"], summary: "List all processes", protect: true } }).output(z7.any()).query(() => listAllProcesses()),
1585
1677
  /** Get a single process from a specific agent */
1586
- get: protectedProcedure.meta({ openapi: { method: "GET", path: "/processes/{agentId}/{id}", tags: ["processes"], summary: "Get a process by agent and ID", protect: true } }).input(z6.object({ agentId: z6.string().max(128), id: z6.string().max(128) })).output(z6.any()).query(async ({ input, ctx }) => {
1678
+ get: protectedProcedure.meta({ openapi: { method: "GET", path: "/processes/{agentId}/{id}", tags: ["processes"], summary: "Get a process by agent and ID", protect: true } }).input(z7.object({ agentId: z7.string().max(128), id: z7.string().max(128) })).output(z7.any()).query(async ({ input, ctx }) => {
1587
1679
  requireServiceAction(ctx, input.id, "service:read");
1588
1680
  const status = agentManager.getStatus(input.agentId);
1589
1681
  if (!status) {
1590
- throw new TRPCError5({ code: "NOT_FOUND", message: `Agent ${input.agentId} not found` });
1682
+ throw new TRPCError6({ code: "NOT_FOUND", message: `Agent ${input.agentId} not found` });
1591
1683
  }
1592
1684
  const proc = await agentManager.agentQuery(input.agentId, "process.get", { id: input.id });
1593
1685
  return { ...proc, agentId: input.agentId };
@@ -1597,37 +1689,37 @@ var processRouter = router({
1597
1689
  * (or restarted). This avoids pushing configs for every service at agent boot,
1598
1690
  * which would be wasteful when many services are never started.
1599
1691
  * The deploy call is idempotent — creates the process if missing, updates config if it exists. */
1600
- start: protectedProcedure.meta({ openapi: { method: "POST", path: "/processes/{agentId}/{processId}/start", tags: ["processes"], summary: "Start a process", protect: true } }).input(z6.object({ agentId: z6.string().max(128).optional(), processId: z6.string().max(128) })).output(z6.any()).mutation(async ({ input, ctx }) => {
1692
+ start: protectedProcedure.meta({ openapi: { method: "POST", path: "/processes/{agentId}/{processId}/start", tags: ["processes"], summary: "Start a process", protect: true } }).input(z7.object({ agentId: z7.string().max(128).optional(), processId: z7.string().max(128) })).output(z7.any()).mutation(async ({ input, ctx }) => {
1601
1693
  requireServiceAction(ctx, input.processId, "service:start");
1602
1694
  return startProcess(input.processId, input.agentId);
1603
1695
  }),
1604
1696
  /** Stop a process on an agent */
1605
- stop: protectedProcedure.meta({ openapi: { method: "POST", path: "/processes/{agentId}/{processId}/stop", tags: ["processes"], summary: "Stop a process", protect: true } }).input(z6.object({ agentId: z6.string().max(128), processId: z6.string().max(128) })).output(z6.any()).mutation(async ({ input, ctx }) => {
1697
+ stop: protectedProcedure.meta({ openapi: { method: "POST", path: "/processes/{agentId}/{processId}/stop", tags: ["processes"], summary: "Stop a process", protect: true } }).input(z7.object({ agentId: z7.string().max(128), processId: z7.string().max(128) })).output(z7.any()).mutation(async ({ input, ctx }) => {
1606
1698
  requireServiceAction(ctx, input.processId, "service:stop");
1607
1699
  return stopProcess(input.processId, input.agentId);
1608
1700
  }),
1609
1701
  /** Restart a process on an agent.
1610
1702
  * Sends stop → deploy (latest resolved config) → start so that
1611
1703
  * config/variable changes take effect. Same lazy deploy pattern as start. */
1612
- restart: protectedProcedure.meta({ openapi: { method: "POST", path: "/processes/{agentId}/{processId}/restart", tags: ["processes"], summary: "Restart a process", protect: true } }).input(z6.object({ agentId: z6.string().max(128).optional(), processId: z6.string().max(128) })).output(z6.any()).mutation(async ({ input, ctx }) => {
1704
+ restart: protectedProcedure.meta({ openapi: { method: "POST", path: "/processes/{agentId}/{processId}/restart", tags: ["processes"], summary: "Restart a process", protect: true } }).input(z7.object({ agentId: z7.string().max(128).optional(), processId: z7.string().max(128) })).output(z7.any()).mutation(async ({ input, ctx }) => {
1613
1705
  requireServiceAction(ctx, input.processId, "service:restart");
1614
1706
  return restartProcess(input.processId, input.agentId);
1615
1707
  }),
1616
1708
  /** Get buffered logs for a process from an agent */
1617
- logs: protectedProcedure.meta({ openapi: { method: "GET", path: "/processes/{agentId}/{processId}/logs", tags: ["processes"], summary: "Get buffered logs for a process", protect: true } }).input(z6.object({ agentId: z6.string().max(128), processId: z6.string().max(128) })).output(z6.any()).query(async ({ input, ctx }) => {
1709
+ logs: protectedProcedure.meta({ openapi: { method: "GET", path: "/processes/{agentId}/{processId}/logs", tags: ["processes"], summary: "Get buffered logs for a process", protect: true } }).input(z7.object({ agentId: z7.string().max(128), processId: z7.string().max(128) })).output(z7.any()).query(async ({ input, ctx }) => {
1618
1710
  requireServiceAction(ctx, input.processId, "logs:read");
1619
1711
  return agentManager.agentQuery(input.agentId, "process.logs", { id: input.processId });
1620
1712
  }),
1621
1713
  /** Clear buffered logs for a process on an agent */
1622
- clearLogBuffer: protectedProcedure.input(z6.object({ agentId: z6.string().max(128), processId: z6.string().max(128) })).mutation(async ({ input }) => {
1714
+ clearLogBuffer: protectedProcedure.input(z7.object({ agentId: z7.string().max(128), processId: z7.string().max(128) })).mutation(async ({ input }) => {
1623
1715
  await agentManager.agentMutation(input.agentId, "process.clearLogBuffer", { id: input.processId });
1624
1716
  await auditService.log({ userId: "local", action: "clearLogBuffer", entityType: "process", entityId: input.processId, metadata: { agentId: input.agentId } });
1625
1717
  return { success: true };
1626
1718
  }),
1627
1719
  /** Execute a shortcut command on an agent, streaming output into the process log */
1628
- executeShortcut: protectedProcedure.input(z6.object({
1629
- agentId: z6.string().max(128),
1630
- processId: z6.string().max(128),
1720
+ executeShortcut: protectedProcedure.input(z7.object({
1721
+ agentId: z7.string().max(128),
1722
+ processId: z7.string().max(128),
1631
1723
  shortcut: ServiceShortcutSchema
1632
1724
  })).mutation(async ({ input }) => {
1633
1725
  const service = await serviceStore.get(input.processId);
@@ -1655,12 +1747,12 @@ var processRouter = router({
1655
1747
  return result;
1656
1748
  }),
1657
1749
  /** Execute an ad-hoc command on an agent, streaming output into the process log */
1658
- executeAdHocCommand: protectedProcedure.input(z6.object({
1659
- agentId: z6.string().max(128),
1660
- processId: z6.string().max(128),
1661
- command: z6.string().min(1).max(4096),
1662
- cwd: z6.string().max(4096).optional(),
1663
- commandId: z6.string().max(128).optional()
1750
+ executeAdHocCommand: protectedProcedure.input(z7.object({
1751
+ agentId: z7.string().max(128),
1752
+ processId: z7.string().max(128),
1753
+ command: z7.string().min(1).max(4096),
1754
+ cwd: z7.string().max(4096).optional(),
1755
+ commandId: z7.string().max(128).optional()
1664
1756
  })).mutation(async ({ input }) => {
1665
1757
  const service = await serviceStore.get(input.processId);
1666
1758
  if (service) {
@@ -1694,25 +1786,25 @@ var processRouter = router({
1694
1786
  return result;
1695
1787
  }),
1696
1788
  /** Cancel a running shortcut command on an agent */
1697
- cancelShortcut: protectedProcedure.input(z6.object({
1698
- agentId: z6.string().max(128),
1699
- processId: z6.string().max(128),
1700
- shortcutId: z6.string().max(128)
1789
+ cancelShortcut: protectedProcedure.input(z7.object({
1790
+ agentId: z7.string().max(128),
1791
+ processId: z7.string().max(128),
1792
+ shortcutId: z7.string().max(128)
1701
1793
  })).mutation(async ({ input }) => {
1702
1794
  await agentManager.agentMutation(input.agentId, "process.cancelShortcut", { id: input.processId, shortcutId: input.shortcutId });
1703
1795
  return { success: true };
1704
1796
  }),
1705
1797
  /** Cancel a running ad-hoc command on an agent */
1706
- cancelAdHocCommand: protectedProcedure.input(z6.object({
1707
- agentId: z6.string().max(128),
1708
- processId: z6.string().max(128),
1709
- commandId: z6.string().max(128).optional()
1798
+ cancelAdHocCommand: protectedProcedure.input(z7.object({
1799
+ agentId: z7.string().max(128),
1800
+ processId: z7.string().max(128),
1801
+ commandId: z7.string().max(128).optional()
1710
1802
  })).mutation(async ({ input }) => {
1711
1803
  await agentManager.agentMutation(input.agentId, "process.cancelAdHocCommand", { id: input.processId, commandId: input.commandId });
1712
1804
  return { success: true };
1713
1805
  }),
1714
1806
  /** Get current metrics for a process from an agent */
1715
- metrics: protectedProcedure.input(z6.object({ agentId: z6.string().max(128), processId: z6.string().max(128) })).query(async ({ input }) => {
1807
+ metrics: protectedProcedure.input(z7.object({ agentId: z7.string().max(128), processId: z7.string().max(128) })).query(async ({ input }) => {
1716
1808
  return agentManager.agentQuery(input.agentId, "process.metrics", { id: input.processId });
1717
1809
  }),
1718
1810
  /**
@@ -1720,7 +1812,7 @@ var processRouter = router({
1720
1812
  * Forwards batched events from the AgentWSBridge in real-time.
1721
1813
  * Historical logs are fetched separately via process.logs query.
1722
1814
  */
1723
- onLog: protectedProcedure.input(z6.object({ agentId: z6.string().max(128), processId: z6.string().max(128) })).subscription(async function* ({ input, ctx }) {
1815
+ onLog: protectedProcedure.input(z7.object({ agentId: z7.string().max(128), processId: z7.string().max(128) })).subscription(async function* ({ input, ctx }) {
1724
1816
  requireServiceAction(ctx, input.processId, "logs:read");
1725
1817
  yield* forwardLogBatches(input.agentId, input.processId);
1726
1818
  }),
@@ -1729,9 +1821,9 @@ var processRouter = router({
1729
1821
  * Input is optional — omit agentId/processId for global monitoring (dashboard).
1730
1822
  * Forwards events from the AgentWSBridge in real-time.
1731
1823
  */
1732
- onStatus: protectedProcedure.input(z6.object({
1733
- agentId: z6.string().max(128).optional(),
1734
- processId: z6.string().max(128).optional()
1824
+ onStatus: protectedProcedure.input(z7.object({
1825
+ agentId: z7.string().max(128).optional(),
1826
+ processId: z7.string().max(128).optional()
1735
1827
  }).optional()).subscription(async function* ({ input, ctx }) {
1736
1828
  const allowedIds = getAllowedServiceIds(ctx);
1737
1829
  if (input?.processId) requireServiceAction(ctx, input.processId, "service:status");
@@ -1759,9 +1851,9 @@ var processRouter = router({
1759
1851
  });
1760
1852
  }),
1761
1853
  /** Subscribe to real-time metrics for a process. */
1762
- onMetrics: protectedProcedure.input(z6.object({
1763
- agentId: z6.string().max(128).optional(),
1764
- processId: z6.string().max(128).optional()
1854
+ onMetrics: protectedProcedure.input(z7.object({
1855
+ agentId: z7.string().max(128).optional(),
1856
+ processId: z7.string().max(128).optional()
1765
1857
  }).optional()).subscription(async function* ({ input, ctx }) {
1766
1858
  const allowedIds = getAllowedServiceIds(ctx);
1767
1859
  if (input?.processId) requireServiceAction(ctx, input.processId, "service:status");
@@ -1773,9 +1865,9 @@ var processRouter = router({
1773
1865
  });
1774
1866
  }),
1775
1867
  /** Subscribe to real-time health status changes. */
1776
- onHealth: protectedProcedure.input(z6.object({
1777
- agentId: z6.string().max(128).optional(),
1778
- processId: z6.string().max(128).optional()
1868
+ onHealth: protectedProcedure.input(z7.object({
1869
+ agentId: z7.string().max(128).optional(),
1870
+ processId: z7.string().max(128).optional()
1779
1871
  }).optional()).subscription(async function* ({ input, ctx }) {
1780
1872
  const allowedIds = getAllowedServiceIds(ctx);
1781
1873
  if (input?.processId) requireServiceAction(ctx, input.processId, "service:healthcheck");
@@ -1789,21 +1881,21 @@ var processRouter = router({
1789
1881
  });
1790
1882
 
1791
1883
  // ../server/src/trpc/routers/audit.ts
1792
- import { z as z7 } from "zod";
1884
+ import { z as z8 } from "zod";
1793
1885
  var auditRouter = router({
1794
- list: protectedProcedure.input(z7.object({
1795
- action: z7.string().max(50).optional(),
1796
- entityType: z7.string().max(50).optional(),
1797
- entityId: z7.string().max(100).optional(),
1798
- limit: z7.number().int().positive().max(100).default(50),
1799
- offset: z7.number().int().nonnegative().default(0)
1886
+ list: protectedProcedure.input(z8.object({
1887
+ action: z8.string().max(50).optional(),
1888
+ entityType: z8.string().max(50).optional(),
1889
+ entityId: z8.string().max(100).optional(),
1890
+ limit: z8.number().int().positive().max(100).default(50),
1891
+ offset: z8.number().int().nonnegative().default(0)
1800
1892
  }).optional()).query(async ({ input }) => {
1801
1893
  return auditService.list(input ?? {});
1802
1894
  })
1803
1895
  });
1804
1896
 
1805
1897
  // ../server/src/trpc/routers/setup.ts
1806
- import { z as z8 } from "zod";
1898
+ import { z as z9 } from "zod";
1807
1899
  var setupRouter = router({
1808
1900
  /**
1809
1901
  * Check if encryption key is required (project initialized but no key).
@@ -1907,9 +1999,9 @@ var setupRouter = router({
1907
1999
  * une validation de la clé à adopter rendait le parcours impossible : vert
1908
2000
  * quand le geste est inutile, rouge sinon.
1909
2001
  */
1910
- checkOrgKeyLocal: protectedProcedure.input(z8.object({
1911
- orgId: z8.string().min(1).max(128),
1912
- keyHex: z8.string().length(64).regex(/^[0-9a-f]+$/i, "Invalid hex format")
2002
+ checkOrgKeyLocal: protectedProcedure.input(z9.object({
2003
+ orgId: z9.string().min(1).max(128),
2004
+ keyHex: z9.string().length(64).regex(/^[0-9a-f]+$/i, "Invalid hex format")
1913
2005
  })).query(async ({ input }) => {
1914
2006
  const canary = await readVerifyFile(orgVaultRoot(input.orgId));
1915
2007
  const locked = isVaultLocked(input.orgId);
@@ -1926,8 +2018,8 @@ var setupRouter = router({
1926
2018
  * Spawns the local agent if in local-simple mode.
1927
2019
  */
1928
2020
  submitEncryptionKey: publicProcedure.input(
1929
- z8.object({
1930
- keyHex: z8.string().length(64).regex(/^[0-9a-f]+$/i, "Invalid hex format")
2021
+ z9.object({
2022
+ keyHex: z9.string().length(64).regex(/^[0-9a-f]+$/i, "Invalid hex format")
1931
2023
  })
1932
2024
  ).mutation(async ({ input }) => {
1933
2025
  try {
@@ -1947,8 +2039,8 @@ var setupRouter = router({
1947
2039
 
1948
2040
  // ../server/src/trpc/routers/environment.ts
1949
2041
  import { randomUUID } from "crypto";
1950
- import { z as z9 } from "zod";
1951
- import { TRPCError as TRPCError6 } from "@trpc/server";
2042
+ import { z as z10 } from "zod";
2043
+ import { TRPCError as TRPCError7 } from "@trpc/server";
1952
2044
 
1953
2045
  // ../server/src/services/ai-variable-write.ts
1954
2046
  var AiVariableWriteError = class extends Error {
@@ -2027,29 +2119,29 @@ async function builtinsForEnvironment(environment) {
2027
2119
  return own ? values : Object.fromEntries(Object.entries(values).filter(([name]) => name.startsWith("services.")));
2028
2120
  }
2029
2121
  var environmentRouter = router({
2030
- list: protectedProcedure.input(z9.object({
2031
- projectId: z9.string().max(128),
2032
- orgId: z9.string().max(128).nullable().optional()
2122
+ list: protectedProcedure.input(z10.object({
2123
+ projectId: z10.string().max(128),
2124
+ orgId: z10.string().max(128).nullable().optional()
2033
2125
  })).query(async ({ input }) => {
2034
2126
  return await environmentStore.list(input.projectId, input.orgId);
2035
2127
  }),
2036
- get: protectedProcedure.input(z9.object({ id: z9.string().max(128) })).query(async ({ input }) => {
2128
+ get: protectedProcedure.input(z10.object({ id: z10.string().max(128) })).query(async ({ input }) => {
2037
2129
  const env2 = await environmentStore.get(input.id);
2038
- if (!env2) throw new TRPCError6({ code: "NOT_FOUND", message: `Environment ${input.id} not found` });
2130
+ if (!env2) throw new TRPCError7({ code: "NOT_FOUND", message: `Environment ${input.id} not found` });
2039
2131
  return env2;
2040
2132
  }),
2041
- listByScope: protectedProcedure.input(z9.object({
2042
- projectId: z9.string().max(128),
2043
- orgId: z9.string().max(128).nullable().optional(),
2044
- scope: z9.enum(["global", "service"])
2133
+ listByScope: protectedProcedure.input(z10.object({
2134
+ projectId: z10.string().max(128),
2135
+ orgId: z10.string().max(128).nullable().optional(),
2136
+ scope: z10.enum(["global", "service"])
2045
2137
  })).query(async ({ input }) => {
2046
2138
  return await environmentStore.listByScope(input.projectId, input.scope, input.orgId);
2047
2139
  }),
2048
- findServiceEnvironment: protectedProcedure.input(z9.object({ serviceId: z9.string().max(128), globalEnvId: z9.string().max(128) })).query(async ({ input }) => {
2140
+ findServiceEnvironment: protectedProcedure.input(z10.object({ serviceId: z10.string().max(128), globalEnvId: z10.string().max(128) })).query(async ({ input }) => {
2049
2141
  return await environmentStore.findServiceEnvironment(input.serviceId, input.globalEnvId);
2050
2142
  }),
2051
2143
  create: protectedProcedure.input(CreateEnvironmentSchema.extend({
2052
- orgId: z9.string().max(128).nullable().optional()
2144
+ orgId: z10.string().max(128).nullable().optional()
2053
2145
  })).mutation(async ({ input }) => {
2054
2146
  const { orgId, ...environment } = input;
2055
2147
  const target = { id: input.projectId, orgId };
@@ -2085,9 +2177,9 @@ var environmentRouter = router({
2085
2177
  }),
2086
2178
  update: protectedProcedure.input(UpdateEnvironmentSchema).mutation(async ({ input }) => {
2087
2179
  const existing = await environmentStore.get(input.id);
2088
- if (!existing) throw new TRPCError6({ code: "NOT_FOUND", message: `Environment ${input.id} not found` });
2180
+ if (!existing) throw new TRPCError7({ code: "NOT_FOUND", message: `Environment ${input.id} not found` });
2089
2181
  const env2 = await environmentStore.update(input);
2090
- if (!env2) throw new TRPCError6({ code: "NOT_FOUND", message: `Environment ${input.id} not found` });
2182
+ if (!env2) throw new TRPCError7({ code: "NOT_FOUND", message: `Environment ${input.id} not found` });
2091
2183
  if (env2.scope === "global" && input.name && input.name !== existing.name) {
2092
2184
  const project = await projectStore.get(environmentStore.projectRefOf(env2) ?? env2.projectId);
2093
2185
  if (project) {
@@ -2101,24 +2193,24 @@ var environmentRouter = router({
2101
2193
  }
2102
2194
  return env2;
2103
2195
  }),
2104
- delete: protectedProcedure.input(z9.object({ id: z9.string().max(128) })).mutation(async ({ input }) => {
2196
+ delete: protectedProcedure.input(z10.object({ id: z10.string().max(128) })).mutation(async ({ input }) => {
2105
2197
  const env2 = await environmentStore.get(input.id);
2106
- if (!env2) throw new TRPCError6({ code: "NOT_FOUND", message: `Environment ${input.id} not found` });
2198
+ if (!env2) throw new TRPCError7({ code: "NOT_FOUND", message: `Environment ${input.id} not found` });
2107
2199
  if (env2.immutable) {
2108
- throw new TRPCError6({ code: "FORBIDDEN", message: "Cannot delete immutable environment" });
2200
+ throw new TRPCError7({ code: "FORBIDDEN", message: "Cannot delete immutable environment" });
2109
2201
  }
2110
2202
  if (env2.scope === "global") {
2111
2203
  await environmentStore.deleteByActivateOn(input.id);
2112
2204
  }
2113
2205
  const deleted = await environmentStore.delete(input.id);
2114
- if (!deleted) throw new TRPCError6({ code: "INTERNAL_SERVER_ERROR", message: "Failed to delete environment" });
2206
+ if (!deleted) throw new TRPCError7({ code: "INTERNAL_SERVER_ERROR", message: "Failed to delete environment" });
2115
2207
  await projectStore.removeEnvironment(environmentStore.projectRefOf(env2) ?? env2.projectId, input.id);
2116
2208
  return { success: true };
2117
2209
  }),
2118
- resolve: protectedProcedure.input(z9.object({ environmentId: z9.string().max(128) })).query(async ({ input, ctx }) => {
2210
+ resolve: protectedProcedure.input(z10.object({ environmentId: z10.string().max(128) })).query(async ({ input, ctx }) => {
2119
2211
  const { includeSecrets } = requireEnvAction(ctx, input.environmentId, "env:read");
2120
2212
  const env2 = await environmentStore.get(input.environmentId);
2121
- if (!env2) throw new TRPCError6({ code: "NOT_FOUND", message: `Environment ${input.environmentId} not found` });
2213
+ if (!env2) throw new TRPCError7({ code: "NOT_FOUND", message: `Environment ${input.environmentId} not found` });
2122
2214
  const resolved = await environmentResolver.resolveEnvironmentWithSources(input.environmentId);
2123
2215
  if (!includeSecrets) {
2124
2216
  const sanitized = { ...resolved };
@@ -2134,10 +2226,10 @@ var environmentRouter = router({
2134
2226
  }
2135
2227
  return resolved;
2136
2228
  }),
2137
- resolveFlat: protectedProcedure.meta({ openapi: { method: "GET", path: "/environments/{environmentId}/resolve-flat", tags: ["environments"], summary: "Resolve environment variables as a flat key-value map", protect: true } }).input(z9.object({ environmentId: z9.string().max(128) })).output(z9.record(z9.string(), z9.string())).query(async ({ input, ctx }) => {
2229
+ resolveFlat: protectedProcedure.meta({ openapi: { method: "GET", path: "/environments/{environmentId}/resolve-flat", tags: ["environments"], summary: "Resolve environment variables as a flat key-value map", protect: true } }).input(z10.object({ environmentId: z10.string().max(128) })).output(z10.record(z10.string(), z10.string())).query(async ({ input, ctx }) => {
2138
2230
  const { includeSecrets } = requireEnvAction(ctx, input.environmentId, "env:read");
2139
2231
  const env2 = await environmentStore.get(input.environmentId);
2140
- if (!env2) throw new TRPCError6({ code: "NOT_FOUND", message: `Environment ${input.environmentId} not found` });
2232
+ if (!env2) throw new TRPCError7({ code: "NOT_FOUND", message: `Environment ${input.environmentId} not found` });
2141
2233
  const { env: resolved, envSecrets } = await environmentResolver.resolveEnvironment(input.environmentId);
2142
2234
  const result = {};
2143
2235
  for (const [key, value] of Object.entries(resolved)) {
@@ -2159,10 +2251,10 @@ var environmentRouter = router({
2159
2251
  * motif. C'est ce que l'assistant de complétion affiche, et il n'a pas
2160
2252
  * besoin de connaître ce qui est déjà rempli ailleurs.
2161
2253
  */
2162
- missingVariables: protectedProcedure.input(z9.object({ environmentId: z9.string().max(128) })).query(async ({ input, ctx }) => {
2254
+ missingVariables: protectedProcedure.input(z10.object({ environmentId: z10.string().max(128) })).query(async ({ input, ctx }) => {
2163
2255
  requireEnvAction(ctx, input.environmentId, "env:read");
2164
2256
  const env2 = await environmentStore.get(input.environmentId);
2165
- if (!env2) throw new TRPCError6({ code: "NOT_FOUND", message: `Environment ${input.environmentId} not found` });
2257
+ if (!env2) throw new TRPCError7({ code: "NOT_FOUND", message: `Environment ${input.environmentId} not found` });
2166
2258
  const missing = await environmentResolver.findMissingForActiveEnvironment(input.environmentId);
2167
2259
  return missing.filter((item) => canEnvAction(ctx, item.environmentId, "env:read"));
2168
2260
  }),
@@ -2181,17 +2273,17 @@ var environmentRouter = router({
2181
2273
  * poste, en recopiant depuis la définition la forme (`pre`, `post`) et le
2182
2274
  * caractère secret que la surcharge ne porte pas d'elle-même.
2183
2275
  */
2184
- fillVariable: protectedProcedure.input(z9.object({
2185
- environmentId: z9.string().max(128),
2186
- variableId: z9.string().max(128),
2187
- value: z9.string().max(8192),
2276
+ fillVariable: protectedProcedure.input(z10.object({
2277
+ environmentId: z10.string().max(128),
2278
+ variableId: z10.string().max(128),
2279
+ value: z10.string().max(8192),
2188
2280
  reason: MissingVariableReasonSchema
2189
2281
  })).mutation(async ({ input, ctx }) => {
2190
2282
  requireEnvAction(ctx, input.environmentId, "env:write");
2191
2283
  const env2 = await environmentStore.get(input.environmentId);
2192
- if (!env2) throw new TRPCError6({ code: "NOT_FOUND", message: `Environment ${input.environmentId} not found` });
2284
+ if (!env2) throw new TRPCError7({ code: "NOT_FOUND", message: `Environment ${input.environmentId} not found` });
2193
2285
  const variable = env2.variables[input.variableId];
2194
- if (!variable) throw new TRPCError6({ code: "NOT_FOUND", message: `Variable ${input.variableId} not found` });
2286
+ if (!variable) throw new TRPCError7({ code: "NOT_FOUND", message: `Variable ${input.variableId} not found` });
2195
2287
  const slot = variable.value;
2196
2288
  if (input.reason === "overrideOnly") {
2197
2289
  await environmentOverridesStore.setOverride(input.variableId, {
@@ -2203,11 +2295,11 @@ var environmentRouter = router({
2203
2295
  ...variable,
2204
2296
  value: { ...slot, value: input.value }
2205
2297
  });
2206
- if (!result) throw new TRPCError6({ code: "INTERNAL_SERVER_ERROR", message: "Failed to fill variable" });
2298
+ if (!result) throw new TRPCError7({ code: "INTERNAL_SERVER_ERROR", message: "Failed to fill variable" });
2207
2299
  return { success: true };
2208
2300
  }),
2209
- setOverride: protectedProcedure.input(z9.object({
2210
- variableId: z9.string().max(128),
2301
+ setOverride: protectedProcedure.input(z10.object({
2302
+ variableId: z10.string().max(128),
2211
2303
  // Only the value slot: the env var name comes from the variable
2212
2304
  // definition (a `key` sent by an older client is stripped here).
2213
2305
  variable: VariableOverrideSchema
@@ -2215,8 +2307,8 @@ var environmentRouter = router({
2215
2307
  await environmentOverridesStore.setOverride(input.variableId, input.variable);
2216
2308
  return { success: true };
2217
2309
  }),
2218
- removeOverride: protectedProcedure.input(z9.object({
2219
- variableId: z9.string().max(128)
2310
+ removeOverride: protectedProcedure.input(z10.object({
2311
+ variableId: z10.string().max(128)
2220
2312
  })).mutation(async ({ input }) => {
2221
2313
  await environmentOverridesStore.removeOverride(input.variableId);
2222
2314
  return { success: true };
@@ -2224,16 +2316,16 @@ var environmentRouter = router({
2224
2316
  getOverrides: protectedProcedure.query(async () => {
2225
2317
  return await environmentOverridesStore.getAll();
2226
2318
  }),
2227
- upsertVariable: protectedProcedure.meta({ openapi: { method: "PUT", path: "/environments/{environmentId}/variables/{variableId}", tags: ["environments"], summary: "Upsert a variable in an environment", protect: true } }).output(z9.any()).input(z9.object({
2228
- environmentId: z9.string().max(128),
2229
- variableId: z9.string().max(128),
2319
+ upsertVariable: protectedProcedure.meta({ openapi: { method: "PUT", path: "/environments/{environmentId}/variables/{variableId}", tags: ["environments"], summary: "Upsert a variable in an environment", protect: true } }).output(z10.any()).input(z10.object({
2320
+ environmentId: z10.string().max(128),
2321
+ variableId: z10.string().max(128),
2230
2322
  variable: VariableSchema
2231
2323
  })).mutation(async ({ input, ctx }) => {
2232
2324
  requireEnvAction(ctx, input.environmentId, "env:write");
2233
2325
  const env2 = await environmentStore.get(input.environmentId);
2234
- if (!env2) throw new TRPCError6({ code: "NOT_FOUND", message: `Environment ${input.environmentId} not found` });
2326
+ if (!env2) throw new TRPCError7({ code: "NOT_FOUND", message: `Environment ${input.environmentId} not found` });
2235
2327
  const result = await environmentStore.upsertVariable(input.environmentId, input.variableId, input.variable);
2236
- if (!result) throw new TRPCError6({ code: "INTERNAL_SERVER_ERROR", message: "Failed to update variable" });
2328
+ if (!result) throw new TRPCError7({ code: "INTERNAL_SERVER_ERROR", message: "Failed to update variable" });
2237
2329
  return result;
2238
2330
  }),
2239
2331
  /**
@@ -2241,15 +2333,15 @@ var environmentRouter = router({
2241
2333
  * hérite de qui, lequel est actif — sans aucune valeur (`describeEnvironmentsForAi`).
2242
2334
  * Une clé d'API n'y voit que les environnements qu'elle peut lire.
2243
2335
  */
2244
- listForAi: protectedProcedure.input(z9.object({
2245
- projectId: z9.string().max(128),
2246
- orgId: z9.string().max(128).nullable().optional()
2336
+ listForAi: protectedProcedure.input(z10.object({
2337
+ projectId: z10.string().max(128),
2338
+ orgId: z10.string().max(128).nullable().optional()
2247
2339
  })).query(async ({ input, ctx }) => {
2248
2340
  const project = await projectStore.get({
2249
2341
  id: input.projectId,
2250
2342
  ...input.orgId !== void 0 ? { orgId: input.orgId } : {}
2251
2343
  });
2252
- if (!project) throw new TRPCError6({ code: "NOT_FOUND", message: `Project ${input.projectId} not found` });
2344
+ if (!project) throw new TRPCError7({ code: "NOT_FOUND", message: `Project ${input.projectId} not found` });
2253
2345
  const environments = (await environmentStore.list(input.projectId, input.orgId)).filter((env2) => canEnvAction(ctx, env2.id, "env:read"));
2254
2346
  const serviceNames = {};
2255
2347
  for (const serviceId of project.serviceIds) {
@@ -2265,10 +2357,10 @@ var environmentRouter = router({
2265
2357
  * remplies — elles dépendent du service qui les reçoit — mais une référence
2266
2358
  * qui ne correspond à rien est nommée.
2267
2359
  */
2268
- resolveForAi: protectedProcedure.input(z9.object({ environmentId: z9.string().max(128) })).query(async ({ input, ctx }) => {
2360
+ resolveForAi: protectedProcedure.input(z10.object({ environmentId: z10.string().max(128) })).query(async ({ input, ctx }) => {
2269
2361
  requireEnvAction(ctx, input.environmentId, "env:read");
2270
2362
  const env2 = await environmentStore.get(input.environmentId);
2271
- if (!env2) throw new TRPCError6({ code: "NOT_FOUND", message: `Environment ${input.environmentId} not found` });
2363
+ if (!env2) throw new TRPCError7({ code: "NOT_FOUND", message: `Environment ${input.environmentId} not found` });
2272
2364
  const [resolved, shared] = await Promise.all([
2273
2365
  environmentResolver.resolveEnvironment(input.environmentId),
2274
2366
  environmentResolver.resolveAiSharedKeys(input.environmentId)
@@ -2290,29 +2382,29 @@ var environmentRouter = router({
2290
2382
  * pas un secret public et ne le partage jamais avec les IA. La réponse ne
2291
2383
  * porte aucune valeur : ce qui vient d'être écrit peut être un secret.
2292
2384
  */
2293
- setVariableBlind: protectedProcedure.input(z9.object({
2294
- environmentId: z9.string().max(128),
2295
- key: z9.string().min(1).max(256),
2296
- value: z9.string().max(8192).optional(),
2297
- pre: z9.string().max(8192).optional(),
2298
- post: z9.string().max(8192).optional(),
2299
- isSecret: z9.boolean().optional(),
2300
- description: z9.string().max(2e3).optional()
2385
+ setVariableBlind: protectedProcedure.input(z10.object({
2386
+ environmentId: z10.string().max(128),
2387
+ key: z10.string().min(1).max(256),
2388
+ value: z10.string().max(8192).optional(),
2389
+ pre: z10.string().max(8192).optional(),
2390
+ post: z10.string().max(8192).optional(),
2391
+ isSecret: z10.boolean().optional(),
2392
+ description: z10.string().max(2e3).optional()
2301
2393
  })).mutation(async ({ input, ctx }) => {
2302
2394
  requireEnvAction(ctx, input.environmentId, "env:write");
2303
2395
  const env2 = await environmentStore.get(input.environmentId);
2304
- if (!env2) throw new TRPCError6({ code: "NOT_FOUND", message: `Environment ${input.environmentId} not found` });
2396
+ if (!env2) throw new TRPCError7({ code: "NOT_FOUND", message: `Environment ${input.environmentId} not found` });
2305
2397
  const found = Object.entries(env2.variables).find(([, v]) => v.key === input.key);
2306
2398
  const variableId = found?.[0] ?? randomUUID();
2307
2399
  let variable;
2308
2400
  try {
2309
2401
  variable = planAiVariableWrite(found?.[1], input);
2310
2402
  } catch (err) {
2311
- if (err instanceof AiVariableWriteError) throw new TRPCError6({ code: "FORBIDDEN", message: err.message });
2403
+ if (err instanceof AiVariableWriteError) throw new TRPCError7({ code: "FORBIDDEN", message: err.message });
2312
2404
  throw err;
2313
2405
  }
2314
2406
  const result = await environmentStore.upsertVariable(input.environmentId, variableId, variable);
2315
- if (!result) throw new TRPCError6({ code: "INTERNAL_SERVER_ERROR", message: "Failed to write variable" });
2407
+ if (!result) throw new TRPCError7({ code: "INTERNAL_SERVER_ERROR", message: "Failed to write variable" });
2316
2408
  const written = `${variable.value.pre}${variable.value.value}${variable.value.post}`;
2317
2409
  let suggestions = [];
2318
2410
  if (!variable.value.isSecret) {
@@ -2338,26 +2430,26 @@ var environmentRouter = router({
2338
2430
  * une route dédiée parce que `update` rend l'environnement entier, valeurs
2339
2431
  * comprises.
2340
2432
  */
2341
- setInheritanceBlind: protectedProcedure.input(z9.object({ environmentId: z9.string().max(128), inherit: z9.boolean() })).mutation(async ({ input, ctx }) => {
2433
+ setInheritanceBlind: protectedProcedure.input(z10.object({ environmentId: z10.string().max(128), inherit: z10.boolean() })).mutation(async ({ input, ctx }) => {
2342
2434
  requireEnvAction(ctx, input.environmentId, "env:write");
2343
2435
  const env2 = await environmentStore.get(input.environmentId);
2344
- if (!env2) throw new TRPCError6({ code: "NOT_FOUND", message: `Environment ${input.environmentId} not found` });
2436
+ if (!env2) throw new TRPCError7({ code: "NOT_FOUND", message: `Environment ${input.environmentId} not found` });
2345
2437
  if (env2.scope !== "service" || !env2.activateOn) {
2346
- throw new TRPCError6({ code: "BAD_REQUEST", message: `Environment ${input.environmentId} is not a service environment: only those inherit from, or are isolated from, the global environment that activates them` });
2438
+ throw new TRPCError7({ code: "BAD_REQUEST", message: `Environment ${input.environmentId} is not a service environment: only those inherit from, or are isolated from, the global environment that activates them` });
2347
2439
  }
2348
2440
  const updated = await environmentStore.update({ id: env2.id, parentIds: input.inherit ? [env2.activateOn] : [] });
2349
- if (!updated) throw new TRPCError6({ code: "INTERNAL_SERVER_ERROR", message: "Failed to update inheritance" });
2441
+ if (!updated) throw new TRPCError7({ code: "INTERNAL_SERVER_ERROR", message: "Failed to update inheritance" });
2350
2442
  return { environmentId: env2.id, isolated: !input.inherit };
2351
2443
  }),
2352
2444
  /** Retirer une variable par son nom, pour le compte d'une IA : la réponse ne porte aucune valeur. */
2353
- removeVariableBlind: protectedProcedure.input(z9.object({ environmentId: z9.string().max(128), key: z9.string().min(1).max(256) })).mutation(async ({ input, ctx }) => {
2445
+ removeVariableBlind: protectedProcedure.input(z10.object({ environmentId: z10.string().max(128), key: z10.string().min(1).max(256) })).mutation(async ({ input, ctx }) => {
2354
2446
  requireEnvAction(ctx, input.environmentId, "env:write");
2355
2447
  const env2 = await environmentStore.get(input.environmentId);
2356
- if (!env2) throw new TRPCError6({ code: "NOT_FOUND", message: `Environment ${input.environmentId} not found` });
2448
+ if (!env2) throw new TRPCError7({ code: "NOT_FOUND", message: `Environment ${input.environmentId} not found` });
2357
2449
  const found = Object.entries(env2.variables).find(([, v]) => v.key === input.key);
2358
- if (!found) throw new TRPCError6({ code: "NOT_FOUND", message: `Variable ${input.key} not found in environment ${input.environmentId}` });
2450
+ if (!found) throw new TRPCError7({ code: "NOT_FOUND", message: `Variable ${input.key} not found in environment ${input.environmentId}` });
2359
2451
  const result = await environmentStore.removeVariable(input.environmentId, found[0]);
2360
- if (!result) throw new TRPCError6({ code: "INTERNAL_SERVER_ERROR", message: "Failed to remove variable" });
2452
+ if (!result) throw new TRPCError7({ code: "INTERNAL_SERVER_ERROR", message: "Failed to remove variable" });
2361
2453
  return { environmentId: input.environmentId, key: input.key, removed: true };
2362
2454
  }),
2363
2455
  /**
@@ -2365,12 +2457,12 @@ var environmentRouter = router({
2365
2457
  * define it, and variables that reference it through {{environment.KEY}}.
2366
2458
  * Used by the UI to warn before editing a shared variable from a resolved view.
2367
2459
  */
2368
- keyUsages: protectedProcedure.input(z9.object({
2369
- projectId: z9.string().max(128),
2370
- orgId: z9.string().max(128).nullable().optional(),
2371
- key: z9.string().min(1).max(256),
2460
+ keyUsages: protectedProcedure.input(z10.object({
2461
+ projectId: z10.string().max(128),
2462
+ orgId: z10.string().max(128).nullable().optional(),
2463
+ key: z10.string().min(1).max(256),
2372
2464
  /** Environment holding the variable about to be edited — enables inherited-impact detection */
2373
- environmentId: z9.string().max(128).optional()
2465
+ environmentId: z10.string().max(128).optional()
2374
2466
  })).query(async ({ input }) => {
2375
2467
  const environments = await environmentStore.list(input.projectId, input.orgId);
2376
2468
  const services = await serviceStore.list();
@@ -2427,22 +2519,22 @@ var environmentRouter = router({
2427
2519
  }
2428
2520
  return { definedIn, referencedBy, inheritedBy };
2429
2521
  }),
2430
- removeVariable: protectedProcedure.input(z9.object({
2431
- environmentId: z9.string().max(128),
2432
- variableId: z9.string().max(128)
2522
+ removeVariable: protectedProcedure.input(z10.object({
2523
+ environmentId: z10.string().max(128),
2524
+ variableId: z10.string().max(128)
2433
2525
  })).mutation(async ({ input }) => {
2434
2526
  const env2 = await environmentStore.get(input.environmentId);
2435
- if (!env2) throw new TRPCError6({ code: "NOT_FOUND", message: `Environment ${input.environmentId} not found` });
2527
+ if (!env2) throw new TRPCError7({ code: "NOT_FOUND", message: `Environment ${input.environmentId} not found` });
2436
2528
  const result = await environmentStore.removeVariable(input.environmentId, input.variableId);
2437
- if (!result) throw new TRPCError6({ code: "INTERNAL_SERVER_ERROR", message: "Failed to remove variable" });
2529
+ if (!result) throw new TRPCError7({ code: "INTERNAL_SERVER_ERROR", message: "Failed to remove variable" });
2438
2530
  return result;
2439
2531
  })
2440
2532
  });
2441
2533
 
2442
2534
  // ../server/src/trpc/routers/settings.ts
2443
2535
  import { promises as dns } from "dns";
2444
- import { z as z10 } from "zod";
2445
- import { TRPCError as TRPCError7 } from "@trpc/server";
2536
+ import { z as z11 } from "zod";
2537
+ import { TRPCError as TRPCError8 } from "@trpc/server";
2446
2538
  var NotificationPreferencesPatchSchema = NotificationPreferencesSchema.partial().strict();
2447
2539
  function listWithOrigin(parsers, vault) {
2448
2540
  return [
@@ -2455,8 +2547,8 @@ function maskApiKey2(plaintext) {
2455
2547
  return plaintext.slice(0, 4) + "****" + plaintext.slice(-4);
2456
2548
  }
2457
2549
  var ScopeShape = {
2458
- orgId: z10.string().max(128).nullable().optional(),
2459
- projectId: z10.string().max(128).optional()
2550
+ orgId: z11.string().max(128).nullable().optional(),
2551
+ projectId: z11.string().max(128).optional()
2460
2552
  };
2461
2553
  async function scopeOf(input) {
2462
2554
  return input?.orgId ?? await vaultOfProject(input?.projectId);
@@ -2499,11 +2591,11 @@ var settingsRouter = router({
2499
2591
  * celle de l'onglet qui bascule, ne sont pas coupées. Le choix est mémorisé
2500
2592
  * dans les réglages, donc conservé au prochain démarrage.
2501
2593
  */
2502
- setLanMode: protectedProcedure.input(z10.object({ enabled: z10.boolean() })).mutation(async ({ input }) => {
2594
+ setLanMode: protectedProcedure.input(z11.object({ enabled: z11.boolean() })).mutation(async ({ input }) => {
2503
2595
  try {
2504
2596
  return await setLanMode(input.enabled);
2505
2597
  } catch (err) {
2506
- throw new TRPCError7({
2598
+ throw new TRPCError8({
2507
2599
  code: "INTERNAL_SERVER_ERROR",
2508
2600
  message: `Impossible de changer l'adresse d'\xE9coute : ${err.message}`
2509
2601
  });
@@ -2524,7 +2616,7 @@ var settingsRouter = router({
2524
2616
  /**
2525
2617
  * Get notification preferences
2526
2618
  */
2527
- getNotificationPreferences: protectedProcedure.input(z10.object(ScopeShape).optional()).query(async ({ input }) => {
2619
+ getNotificationPreferences: protectedProcedure.input(z11.object(ScopeShape).optional()).query(async ({ input }) => {
2528
2620
  const priv = await settingsManager.getPrivateSettings(await scopeOf(input));
2529
2621
  return NotificationPreferencesSchema.parse(priv.notifications ?? {});
2530
2622
  }),
@@ -2552,7 +2644,7 @@ var settingsRouter = router({
2552
2644
  * parseur d'organisation se modifie pour toute l'équipe, et l'interface doit
2553
2645
  * pouvoir le dire avant que quelqu'un le change sans le savoir.
2554
2646
  */
2555
- listParsers: protectedProcedure.input(z10.object(ScopeShape).optional()).query(async ({ input }) => {
2647
+ listParsers: protectedProcedure.input(z11.object(ScopeShape).optional()).query(async ({ input }) => {
2556
2648
  const vault = await scopeOf(input);
2557
2649
  return listWithOrigin(await logParserStore.list(vault), vault);
2558
2650
  }),
@@ -2564,7 +2656,7 @@ var settingsRouter = router({
2564
2656
  * retard — affichant une liste dans laquelle le parseur qu'un service vient
2565
2657
  * de référencer n'existe pas encore.
2566
2658
  */
2567
- onParsersChanged: protectedProcedure.input(z10.object(ScopeShape).optional()).subscription(async function* ({ input, signal }) {
2659
+ onParsersChanged: protectedProcedure.input(z11.object(ScopeShape).optional()).subscription(async function* ({ input, signal }) {
2568
2660
  const vault = await scopeOf(input);
2569
2661
  let pending = true;
2570
2662
  let wake = null;
@@ -2602,10 +2694,10 @@ var settingsRouter = router({
2602
2694
  /**
2603
2695
  * Get single parser by ID
2604
2696
  */
2605
- getParser: protectedProcedure.input(z10.object({ id: z10.string().max(128), ...ScopeShape })).query(async ({ input }) => {
2697
+ getParser: protectedProcedure.input(z11.object({ id: z11.string().max(128), ...ScopeShape })).query(async ({ input }) => {
2606
2698
  const parser = await logParserStore.get(input.id, await scopeOf(input));
2607
2699
  if (!parser) {
2608
- throw new TRPCError7({ code: "NOT_FOUND", message: `Parser not found: ${input.id}` });
2700
+ throw new TRPCError8({ code: "NOT_FOUND", message: `Parser not found: ${input.id}` });
2609
2701
  }
2610
2702
  return parser;
2611
2703
  }),
@@ -2621,7 +2713,7 @@ var settingsRouter = router({
2621
2713
  ).mutation(async ({ input }) => {
2622
2714
  const { orgId, projectId, ...fields } = input;
2623
2715
  if (!fields.code.trim()) {
2624
- throw new TRPCError7({ code: "BAD_REQUEST", message: "Parser code cannot be empty" });
2716
+ throw new TRPCError8({ code: "BAD_REQUEST", message: "Parser code cannot be empty" });
2625
2717
  }
2626
2718
  return logParserStore.create(fields, await scopeOf({ orgId, projectId }));
2627
2719
  }),
@@ -2636,27 +2728,27 @@ var settingsRouter = router({
2636
2728
  ).mutation(async ({ input }) => {
2637
2729
  const { id, orgId, projectId, ...patch } = input;
2638
2730
  if (id.startsWith("native:")) {
2639
- throw new TRPCError7({ code: "FORBIDDEN", message: "Cannot modify built-in parsers" });
2731
+ throw new TRPCError8({ code: "FORBIDDEN", message: "Cannot modify built-in parsers" });
2640
2732
  }
2641
2733
  if (patch.code !== void 0 && !patch.code.trim()) {
2642
- throw new TRPCError7({ code: "BAD_REQUEST", message: "Parser code cannot be empty" });
2734
+ throw new TRPCError8({ code: "BAD_REQUEST", message: "Parser code cannot be empty" });
2643
2735
  }
2644
2736
  const updated = await logParserStore.update(id, patch, await scopeOf({ orgId, projectId }));
2645
2737
  if (!updated) {
2646
- throw new TRPCError7({ code: "NOT_FOUND", message: `Parser not found: ${id}` });
2738
+ throw new TRPCError8({ code: "NOT_FOUND", message: `Parser not found: ${id}` });
2647
2739
  }
2648
2740
  return updated;
2649
2741
  }),
2650
2742
  /**
2651
2743
  * Delete parser by ID
2652
2744
  */
2653
- deleteParser: protectedProcedure.input(z10.object({ id: z10.string().max(128), ...ScopeShape })).mutation(async ({ input }) => {
2745
+ deleteParser: protectedProcedure.input(z11.object({ id: z11.string().max(128), ...ScopeShape })).mutation(async ({ input }) => {
2654
2746
  if (input.id.startsWith("native:")) {
2655
- throw new TRPCError7({ code: "FORBIDDEN", message: "Cannot delete built-in parsers" });
2747
+ throw new TRPCError8({ code: "FORBIDDEN", message: "Cannot delete built-in parsers" });
2656
2748
  }
2657
2749
  const deleted = await logParserStore.delete(input.id, await scopeOf(input));
2658
2750
  if (!deleted) {
2659
- throw new TRPCError7({ code: "NOT_FOUND", message: `Parser not found: ${input.id}` });
2751
+ throw new TRPCError8({ code: "NOT_FOUND", message: `Parser not found: ${input.id}` });
2660
2752
  }
2661
2753
  return { deleted: true };
2662
2754
  }),
@@ -2688,11 +2780,11 @@ var settingsRouter = router({
2688
2780
  defaultPrompt: companionDefaultPrompt()
2689
2781
  };
2690
2782
  }),
2691
- setCompanionSettings: protectedProcedure.input(z10.object({
2692
- enabledByDefault: z10.boolean().optional(),
2783
+ setCompanionSettings: protectedProcedure.input(z11.object({
2784
+ enabledByDefault: z11.boolean().optional(),
2693
2785
  // Rejeté au-delà, jamais tronqué : un prompt coupé produirait des
2694
2786
  // relectures incohérentes sans rien signaler.
2695
- prompt: z10.string().max(2e4).optional()
2787
+ prompt: z11.string().max(2e4).optional()
2696
2788
  })).mutation(async ({ input }) => {
2697
2789
  const settings = await settingsManager.getSettings();
2698
2790
  const current2 = settings.companion ?? { enabledByDefault: false };
@@ -2711,7 +2803,7 @@ var settingsRouter = router({
2711
2803
  /**
2712
2804
  * List AI providers (API keys are masked)
2713
2805
  */
2714
- listAIProviders: protectedProcedure.input(z10.object(ScopeShape).optional()).query(async ({ input }) => {
2806
+ listAIProviders: protectedProcedure.input(z11.object(ScopeShape).optional()).query(async ({ input }) => {
2715
2807
  const vault = await scopeOf(input);
2716
2808
  const priv = await settingsManager.getPrivateSettings(vault);
2717
2809
  return (priv.aiProviders ?? []).map((p) => {
@@ -2729,16 +2821,16 @@ var settingsRouter = router({
2729
2821
  /**
2730
2822
  * Create AI provider
2731
2823
  */
2732
- createAIProvider: protectedProcedure.input(z10.object({
2733
- name: z10.string().min(1).max(200),
2824
+ createAIProvider: protectedProcedure.input(z11.object({
2825
+ name: z11.string().min(1).max(200),
2734
2826
  provider: AIProviderSchema.shape.provider,
2735
- apiKey: z10.string().max(500).optional(),
2827
+ apiKey: z11.string().max(500).optional(),
2736
2828
  // optional for providers like Ollama
2737
- model: z10.string().max(200).optional(),
2829
+ model: z11.string().max(200).optional(),
2738
2830
  ...ScopeShape
2739
2831
  })).mutation(async ({ input }) => {
2740
2832
  if (input.provider !== "ollama" && !input.apiKey?.trim()) {
2741
- throw new TRPCError7({ code: "BAD_REQUEST", message: "Une cl\xE9 API est requise pour ce provider." });
2833
+ throw new TRPCError8({ code: "BAD_REQUEST", message: "Une cl\xE9 API est requise pour ce provider." });
2742
2834
  }
2743
2835
  const vault = await scopeOf(input);
2744
2836
  const priv = await settingsManager.getPrivateSettings(vault);
@@ -2767,19 +2859,19 @@ var settingsRouter = router({
2767
2859
  /**
2768
2860
  * Update AI provider (apiKey optional — omit to keep existing)
2769
2861
  */
2770
- updateAIProvider: protectedProcedure.input(z10.object({
2771
- id: z10.string().min(1).max(128),
2772
- name: z10.string().min(1).max(200).optional(),
2862
+ updateAIProvider: protectedProcedure.input(z11.object({
2863
+ id: z11.string().min(1).max(128),
2864
+ name: z11.string().min(1).max(200).optional(),
2773
2865
  provider: AIProviderSchema.shape.provider.optional(),
2774
- apiKey: z10.string().min(1).max(500).optional(),
2775
- model: z10.string().max(200).optional(),
2866
+ apiKey: z11.string().min(1).max(500).optional(),
2867
+ model: z11.string().max(200).optional(),
2776
2868
  ...ScopeShape
2777
2869
  })).mutation(async ({ input }) => {
2778
2870
  const vault = await scopeOf(input);
2779
2871
  const priv = await settingsManager.getPrivateSettings(vault);
2780
2872
  const providers = priv.aiProviders ?? [];
2781
2873
  const idx = providers.findIndex((p) => p.id === input.id);
2782
- if (idx === -1) throw new TRPCError7({ code: "NOT_FOUND", message: `AI provider not found: ${input.id}` });
2874
+ if (idx === -1) throw new TRPCError8({ code: "NOT_FOUND", message: `AI provider not found: ${input.id}` });
2783
2875
  const existing = providers[idx];
2784
2876
  const encryptedApiKey = input.apiKey ? stableEncryptValue(input.apiKey, existing.encryptedApiKey, vault) : existing.encryptedApiKey;
2785
2877
  const updated = {
@@ -2805,12 +2897,12 @@ var settingsRouter = router({
2805
2897
  /**
2806
2898
  * Delete AI provider
2807
2899
  */
2808
- deleteAIProvider: protectedProcedure.input(z10.object({ id: z10.string().min(1).max(128), ...ScopeShape })).mutation(async ({ input }) => {
2900
+ deleteAIProvider: protectedProcedure.input(z11.object({ id: z11.string().min(1).max(128), ...ScopeShape })).mutation(async ({ input }) => {
2809
2901
  const vault = await scopeOf(input);
2810
2902
  const priv = await settingsManager.getPrivateSettings(vault);
2811
2903
  const providers = priv.aiProviders ?? [];
2812
2904
  const filtered = providers.filter((p) => p.id !== input.id);
2813
- if (filtered.length === providers.length) throw new TRPCError7({ code: "NOT_FOUND", message: `AI provider not found: ${input.id}` });
2905
+ if (filtered.length === providers.length) throw new TRPCError8({ code: "NOT_FOUND", message: `AI provider not found: ${input.id}` });
2814
2906
  const deletedWasActive = providers.find((p) => p.id === input.id)?.active ?? false;
2815
2907
  if (deletedWasActive && filtered.length > 0) filtered[0].active = true;
2816
2908
  await settingsManager.savePrivateSettings({ ...priv, aiProviders: filtered }, vault);
@@ -2819,12 +2911,12 @@ var settingsRouter = router({
2819
2911
  /**
2820
2912
  * Set one provider as active (clears active flag on all others)
2821
2913
  */
2822
- setActiveAIProvider: protectedProcedure.input(z10.object({ id: z10.string().min(1).max(128), ...ScopeShape })).mutation(async ({ input }) => {
2914
+ setActiveAIProvider: protectedProcedure.input(z11.object({ id: z11.string().min(1).max(128), ...ScopeShape })).mutation(async ({ input }) => {
2823
2915
  const vault = await scopeOf(input);
2824
2916
  const priv = await settingsManager.getPrivateSettings(vault);
2825
2917
  const providers = priv.aiProviders ?? [];
2826
2918
  const idx = providers.findIndex((p) => p.id === input.id);
2827
- if (idx === -1) throw new TRPCError7({ code: "NOT_FOUND", message: `AI provider not found: ${input.id}` });
2919
+ if (idx === -1) throw new TRPCError8({ code: "NOT_FOUND", message: `AI provider not found: ${input.id}` });
2828
2920
  const updated = providers.map((p) => ({ ...p, active: p.id === input.id }));
2829
2921
  await settingsManager.savePrivateSettings({ ...priv, aiProviders: updated }, vault);
2830
2922
  return { id: input.id, active: true };
@@ -2835,7 +2927,7 @@ var settingsRouter = router({
2835
2927
  /**
2836
2928
  * Get Traefik config for a specific agent (never returns credentials or cert key in plain text)
2837
2929
  */
2838
- getAgentTraefikConfig: protectedProcedure.input(z10.object({ agentId: z10.string().max(128) })).query(async ({ input }) => {
2930
+ getAgentTraefikConfig: protectedProcedure.input(z11.object({ agentId: z11.string().max(128) })).query(async ({ input }) => {
2839
2931
  const raw = agentStore.getTraefikConfig(input.agentId);
2840
2932
  const parsed = raw ? TraefikConfigSchema.safeParse(raw) : null;
2841
2933
  const config = parsed?.success ? parsed.data : null;
@@ -2855,16 +2947,16 @@ var settingsRouter = router({
2855
2947
  /**
2856
2948
  * Update Traefik config for a specific agent (credentials are encrypted before saving)
2857
2949
  */
2858
- updateAgentTraefikConfig: protectedProcedure.input(z10.object({
2859
- agentId: z10.string().max(128),
2860
- enabled: z10.boolean().optional(),
2861
- acmeEmail: z10.string().email().max(256).optional(),
2862
- wildcardDomain: z10.string().max(253).optional(),
2863
- httpPort: z10.number().int().min(1).max(65535).optional(),
2864
- httpsPort: z10.number().int().min(1).max(65535).optional(),
2865
- dnsProvider: z10.string().max(64).optional(),
2866
- dnsCredentials: z10.record(z10.string().max(64), z10.string().max(2048)).optional(),
2867
- acmeStaging: z10.boolean().optional()
2950
+ updateAgentTraefikConfig: protectedProcedure.input(z11.object({
2951
+ agentId: z11.string().max(128),
2952
+ enabled: z11.boolean().optional(),
2953
+ acmeEmail: z11.string().email().max(256).optional(),
2954
+ wildcardDomain: z11.string().max(253).optional(),
2955
+ httpPort: z11.number().int().min(1).max(65535).optional(),
2956
+ httpsPort: z11.number().int().min(1).max(65535).optional(),
2957
+ dnsProvider: z11.string().max(64).optional(),
2958
+ dnsCredentials: z11.record(z11.string().max(64), z11.string().max(2048)).optional(),
2959
+ acmeStaging: z11.boolean().optional()
2868
2960
  })).mutation(async ({ input }) => {
2869
2961
  const { agentId, ...fields } = input;
2870
2962
  const raw = agentStore.getTraefikConfig(agentId);
@@ -2893,13 +2985,13 @@ var settingsRouter = router({
2893
2985
  /**
2894
2986
  * Get Traefik config files content for a specific agent
2895
2987
  */
2896
- getAgentTraefikConfigFiles: protectedProcedure.input(z10.object({ agentId: z10.string().max(128) })).query(async ({ input }) => {
2988
+ getAgentTraefikConfigFiles: protectedProcedure.input(z11.object({ agentId: z11.string().max(128) })).query(async ({ input }) => {
2897
2989
  return agentManager.agentQuery(
2898
2990
  input.agentId,
2899
2991
  "config.getTraefikConfigFiles"
2900
2992
  );
2901
2993
  }),
2902
- getAgentTraefikFileTree: protectedProcedure.input(z10.object({ agentId: z10.string().max(128) })).query(async ({ input }) => {
2994
+ getAgentTraefikFileTree: protectedProcedure.input(z11.object({ agentId: z11.string().max(128) })).query(async ({ input }) => {
2903
2995
  return agentManager.agentQuery(
2904
2996
  input.agentId,
2905
2997
  "config.getTraefikFileTree"
@@ -2908,7 +3000,7 @@ var settingsRouter = router({
2908
3000
  /**
2909
3001
  * Get Traefik container logs for a specific agent (snapshot)
2910
3002
  */
2911
- getAgentTraefikLogs: protectedProcedure.input(z10.object({ agentId: z10.string().max(128), lines: z10.number().int().min(1).max(500).default(100) })).query(async ({ input }) => {
3003
+ getAgentTraefikLogs: protectedProcedure.input(z11.object({ agentId: z11.string().max(128), lines: z11.number().int().min(1).max(500).default(100) })).query(async ({ input }) => {
2912
3004
  const result = await agentManager.agentQuery(
2913
3005
  input.agentId,
2914
3006
  "config.getTraefikLogs",
@@ -2919,7 +3011,7 @@ var settingsRouter = router({
2919
3011
  /**
2920
3012
  * Stream Traefik logs in real-time (subscription, yields new lines every 500ms)
2921
3013
  */
2922
- streamAgentTraefikLogs: protectedProcedure.input(z10.object({ agentId: z10.string().max(128) })).subscription(async function* ({ input, signal }) {
3014
+ streamAgentTraefikLogs: protectedProcedure.input(z11.object({ agentId: z11.string().max(128) })).subscription(async function* ({ input, signal }) {
2923
3015
  let seen = 0;
2924
3016
  while (!signal?.aborted) {
2925
3017
  try {
@@ -2942,11 +3034,11 @@ var settingsRouter = router({
2942
3034
  /**
2943
3035
  * Restart Traefik container on a specific agent (re-pushes config first to handle agent restarts)
2944
3036
  */
2945
- restartAgentTraefik: protectedProcedure.input(z10.object({ agentId: z10.string().max(128) })).mutation(async ({ input }) => {
3037
+ restartAgentTraefik: protectedProcedure.input(z11.object({ agentId: z11.string().max(128) })).mutation(async ({ input }) => {
2946
3038
  const raw = agentStore.getTraefikConfig(input.agentId);
2947
3039
  const parsed = raw ? TraefikConfigSchema.safeParse(raw) : null;
2948
3040
  const config = parsed?.success ? parsed.data : null;
2949
- if (!config?.enabled) throw new TRPCError7({ code: "BAD_REQUEST", message: "Traefik non activ\xE9 sur cet agent" });
3041
+ if (!config?.enabled) throw new TRPCError8({ code: "BAD_REQUEST", message: "Traefik non activ\xE9 sur cet agent" });
2950
3042
  const decrypted = { ...config, dnsCredentials: traefikManager.decryptDnsCredentials(config.dnsCredentials ?? {}) };
2951
3043
  await agentManager.agentMutation(input.agentId, "config.initTraefikConfig", decrypted, 5e3);
2952
3044
  await agentManager.agentMutation(input.agentId, "config.restartTraefik", void 0, 3e4);
@@ -2955,11 +3047,11 @@ var settingsRouter = router({
2955
3047
  /**
2956
3048
  * Force certificate renewal for a specific agent (wipes acme.json + restarts container)
2957
3049
  */
2958
- renewAgentTraefikCert: protectedProcedure.input(z10.object({ agentId: z10.string().max(128) })).mutation(async ({ input }) => {
3050
+ renewAgentTraefikCert: protectedProcedure.input(z11.object({ agentId: z11.string().max(128) })).mutation(async ({ input }) => {
2959
3051
  const raw = agentStore.getTraefikConfig(input.agentId);
2960
3052
  const parsed = raw ? TraefikConfigSchema.safeParse(raw) : null;
2961
3053
  const config = parsed?.success ? parsed.data : null;
2962
- if (!config?.enabled) throw new TRPCError7({ code: "BAD_REQUEST", message: "Traefik non activ\xE9 sur cet agent" });
3054
+ if (!config?.enabled) throw new TRPCError8({ code: "BAD_REQUEST", message: "Traefik non activ\xE9 sur cet agent" });
2963
3055
  const decrypted = { ...config, dnsCredentials: traefikManager.decryptDnsCredentials(config.dnsCredentials ?? {}) };
2964
3056
  await agentManager.agentMutation(input.agentId, "config.initTraefikConfig", decrypted, 5e3);
2965
3057
  await agentManager.agentMutation(input.agentId, "config.renewTraefikCert", void 0, 3e4);
@@ -2968,7 +3060,7 @@ var settingsRouter = router({
2968
3060
  /**
2969
3061
  * Validate Traefik configuration for a specific agent
2970
3062
  */
2971
- validateAgentTraefikConfig: protectedProcedure.input(z10.object({ agentId: z10.string().max(128) })).query(async ({ input }) => {
3063
+ validateAgentTraefikConfig: protectedProcedure.input(z11.object({ agentId: z11.string().max(128) })).query(async ({ input }) => {
2972
3064
  const raw = agentStore.getTraefikConfig(input.agentId);
2973
3065
  const parsed = raw ? TraefikConfigSchema.safeParse(raw) : null;
2974
3066
  const config = parsed?.success ? parsed.data : null;
@@ -3070,12 +3162,12 @@ var settingsRouter = router({
3070
3162
  * Test parser code: compile and run it against sample logs, return per-line results
3071
3163
  */
3072
3164
  testParser: protectedProcedure.input(
3073
- z10.object({
3074
- code: z10.string().max(5e4),
3075
- sampleLogs: z10.array(
3076
- z10.object({
3077
- raw: z10.string().max(16384),
3078
- stream: z10.enum(["stdout", "stderr"])
3165
+ z11.object({
3166
+ code: z11.string().max(5e4),
3167
+ sampleLogs: z11.array(
3168
+ z11.object({
3169
+ raw: z11.string().max(16384),
3170
+ stream: z11.enum(["stdout", "stderr"])
3079
3171
  })
3080
3172
  ).max(100).default([])
3081
3173
  })
@@ -3091,7 +3183,7 @@ var settingsRouter = router({
3091
3183
  updatedAt: /* @__PURE__ */ new Date()
3092
3184
  }]);
3093
3185
  } catch (err) {
3094
- throw new TRPCError7({
3186
+ throw new TRPCError8({
3095
3187
  code: "BAD_REQUEST",
3096
3188
  message: err instanceof Error ? err.message : String(err)
3097
3189
  });
@@ -3119,8 +3211,8 @@ var settingsRouter = router({
3119
3211
  });
3120
3212
 
3121
3213
  // ../server/src/trpc/routers/editor.ts
3122
- import { z as z12 } from "zod";
3123
- import { TRPCError as TRPCError8 } from "@trpc/server";
3214
+ import { z as z13 } from "zod";
3215
+ import { TRPCError as TRPCError9 } from "@trpc/server";
3124
3216
  import { execFile as execFile3, spawn as spawn2 } from "child_process";
3125
3217
  import { stat as stat2 } from "fs/promises";
3126
3218
  import { resolve, join as join4 } from "path";
@@ -3130,19 +3222,19 @@ import { homedir as homedir2 } from "os";
3130
3222
  import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, chmod as chmod2 } from "fs/promises";
3131
3223
  import { join as join3 } from "path";
3132
3224
  import { homedir } from "os";
3133
- import { z as z11 } from "zod";
3225
+ import { z as z12 } from "zod";
3134
3226
  var CONFIG_DIR = join3(homedir(), ".runeya");
3135
3227
  var CONFIG_FILE = "runeya.conf";
3136
- var EditorPreferencesSchema = z11.object({
3137
- default: z11.string().max(64).optional()
3138
- }).catchall(z11.string().max(64)).refine((obj) => Object.keys(obj).length <= 500, "Too many editor preferences");
3139
- var ProjectSettingsSchema = z11.object({
3140
- settings: z11.object({
3228
+ var EditorPreferencesSchema = z12.object({
3229
+ default: z12.string().max(64).optional()
3230
+ }).catchall(z12.string().max(64)).refine((obj) => Object.keys(obj).length <= 500, "Too many editor preferences");
3231
+ var ProjectSettingsSchema = z12.object({
3232
+ settings: z12.object({
3141
3233
  editors: EditorPreferencesSchema.optional()
3142
3234
  }).optional()
3143
3235
  });
3144
- var UserConfigSchema = z11.record(
3145
- z11.string().max(128),
3236
+ var UserConfigSchema = z12.record(
3237
+ z12.string().max(128),
3146
3238
  ProjectSettingsSchema
3147
3239
  ).refine((obj) => Object.keys(obj).length <= 100, "Too many projects in config");
3148
3240
  function configKey(ref) {
@@ -3213,7 +3305,7 @@ async function getServiceCwd(serviceId) {
3213
3305
  const services = await serviceStore.list();
3214
3306
  const service = services.find((s) => s.id === serviceId);
3215
3307
  if (!service) {
3216
- throw new TRPCError8({ code: "NOT_FOUND", message: "Service not found" });
3308
+ throw new TRPCError9({ code: "NOT_FOUND", message: "Service not found" });
3217
3309
  }
3218
3310
  return resolveCwd(await resolveWorkspaceCwd({ serviceId }));
3219
3311
  }
@@ -3234,19 +3326,19 @@ var editorRouter = router({
3234
3326
  );
3235
3327
  return results;
3236
3328
  }),
3237
- getPreferences: protectedProcedure.input(z12.object({
3238
- projectId: z12.string().max(128),
3239
- orgId: z12.string().max(128).nullable().optional()
3329
+ getPreferences: protectedProcedure.input(z13.object({
3330
+ projectId: z13.string().max(128),
3331
+ orgId: z13.string().max(128).nullable().optional()
3240
3332
  })).query(async ({ input }) => {
3241
3333
  return userConfigManager.getEditorPreferences({ id: input.projectId, orgId: input.orgId });
3242
3334
  }),
3243
- setDefault: protectedProcedure.input(z12.object({
3244
- projectId: z12.string().max(128),
3245
- orgId: z12.string().max(128).nullable().optional(),
3246
- editorKey: z12.string().max(64)
3335
+ setDefault: protectedProcedure.input(z13.object({
3336
+ projectId: z13.string().max(128),
3337
+ orgId: z13.string().max(128).nullable().optional(),
3338
+ editorKey: z13.string().max(64)
3247
3339
  })).mutation(async ({ input }) => {
3248
3340
  if (!EDITOR_BY_KEY.has(input.editorKey)) {
3249
- throw new TRPCError8({ code: "BAD_REQUEST", message: `Unknown editor: ${input.editorKey}` });
3341
+ throw new TRPCError9({ code: "BAD_REQUEST", message: `Unknown editor: ${input.editorKey}` });
3250
3342
  }
3251
3343
  await userConfigManager.setEditorPreference(
3252
3344
  { id: input.projectId, orgId: input.orgId },
@@ -3255,14 +3347,14 @@ var editorRouter = router({
3255
3347
  );
3256
3348
  return { success: true };
3257
3349
  }),
3258
- setServiceEditor: protectedProcedure.input(z12.object({
3259
- projectId: z12.string().max(128),
3260
- orgId: z12.string().max(128).nullable().optional(),
3261
- serviceId: z12.string().max(128),
3262
- editorKey: z12.string().max(64)
3350
+ setServiceEditor: protectedProcedure.input(z13.object({
3351
+ projectId: z13.string().max(128),
3352
+ orgId: z13.string().max(128).nullable().optional(),
3353
+ serviceId: z13.string().max(128),
3354
+ editorKey: z13.string().max(64)
3263
3355
  })).mutation(async ({ input }) => {
3264
3356
  if (!EDITOR_BY_KEY.has(input.editorKey)) {
3265
- throw new TRPCError8({ code: "BAD_REQUEST", message: `Unknown editor: ${input.editorKey}` });
3357
+ throw new TRPCError9({ code: "BAD_REQUEST", message: `Unknown editor: ${input.editorKey}` });
3266
3358
  }
3267
3359
  await userConfigManager.setEditorPreference(
3268
3360
  { id: input.projectId, orgId: input.orgId },
@@ -3271,10 +3363,10 @@ var editorRouter = router({
3271
3363
  );
3272
3364
  return { success: true };
3273
3365
  }),
3274
- removeServiceEditor: protectedProcedure.input(z12.object({
3275
- projectId: z12.string().max(128),
3276
- orgId: z12.string().max(128).nullable().optional(),
3277
- serviceId: z12.string().max(128)
3366
+ removeServiceEditor: protectedProcedure.input(z13.object({
3367
+ projectId: z13.string().max(128),
3368
+ orgId: z13.string().max(128).nullable().optional(),
3369
+ serviceId: z13.string().max(128)
3278
3370
  })).mutation(async ({ input }) => {
3279
3371
  await userConfigManager.removeEditorPreference(
3280
3372
  { id: input.projectId, orgId: input.orgId },
@@ -3282,21 +3374,21 @@ var editorRouter = router({
3282
3374
  );
3283
3375
  return { success: true };
3284
3376
  }),
3285
- open: protectedProcedure.input(z12.object({
3286
- editorKey: z12.string().max(64),
3287
- path: z12.string().max(4096)
3377
+ open: protectedProcedure.input(z13.object({
3378
+ editorKey: z13.string().max(64),
3379
+ path: z13.string().max(4096)
3288
3380
  })).mutation(async ({ input }) => {
3289
3381
  const editor = EDITOR_BY_KEY.get(input.editorKey);
3290
3382
  if (!editor) {
3291
- throw new TRPCError8({ code: "BAD_REQUEST", message: `Unknown editor: ${input.editorKey}` });
3383
+ throw new TRPCError9({ code: "BAD_REQUEST", message: `Unknown editor: ${input.editorKey}` });
3292
3384
  }
3293
3385
  const expanded = input.path.replace(/^~(\/|$)/, `${process.env["HOME"] ?? "/tmp"}$1`).replace(/\$\{(\w+)\}|\$(\w+)/g, (_, a, b) => process.env[a || b] ?? "");
3294
3386
  const resolvedPath = resolve(expanded || ".");
3295
3387
  try {
3296
3388
  await stat2(resolvedPath);
3297
3389
  } catch (err) {
3298
- if (err instanceof TRPCError8) throw err;
3299
- throw new TRPCError8({ code: "BAD_REQUEST", message: `Path does not exist: ${resolvedPath}` });
3390
+ if (err instanceof TRPCError9) throw err;
3391
+ throw new TRPCError9({ code: "BAD_REQUEST", message: `Path does not exist: ${resolvedPath}` });
3300
3392
  }
3301
3393
  const invocation = resolveCliInvocation(editor.command, [resolvedPath]);
3302
3394
  const child = spawn2(invocation.command, invocation.args, {
@@ -3308,24 +3400,24 @@ var editorRouter = router({
3308
3400
  child.unref();
3309
3401
  return { success: true };
3310
3402
  }),
3311
- openFile: protectedProcedure.input(z12.object({
3312
- editorKey: z12.string().max(64),
3313
- serviceId: z12.string().max(128),
3314
- relativePath: z12.string().max(4096)
3403
+ openFile: protectedProcedure.input(z13.object({
3404
+ editorKey: z13.string().max(64),
3405
+ serviceId: z13.string().max(128),
3406
+ relativePath: z13.string().max(4096)
3315
3407
  })).mutation(async ({ input }) => {
3316
3408
  const editor = EDITOR_BY_KEY.get(input.editorKey);
3317
3409
  if (!editor) {
3318
- throw new TRPCError8({ code: "BAD_REQUEST", message: `Unknown editor: ${input.editorKey}` });
3410
+ throw new TRPCError9({ code: "BAD_REQUEST", message: `Unknown editor: ${input.editorKey}` });
3319
3411
  }
3320
3412
  const cwd = await getServiceCwd(input.serviceId);
3321
3413
  const filePath = join4(cwd, input.relativePath);
3322
3414
  if (!filePath.startsWith(cwd)) {
3323
- throw new TRPCError8({ code: "BAD_REQUEST", message: "Path traversal not allowed" });
3415
+ throw new TRPCError9({ code: "BAD_REQUEST", message: "Path traversal not allowed" });
3324
3416
  }
3325
3417
  try {
3326
3418
  await stat2(filePath);
3327
3419
  } catch {
3328
- throw new TRPCError8({ code: "BAD_REQUEST", message: `File does not exist: ${filePath}` });
3420
+ throw new TRPCError9({ code: "BAD_REQUEST", message: `File does not exist: ${filePath}` });
3329
3421
  }
3330
3422
  const invocation = resolveCliInvocation(editor.command, [filePath]);
3331
3423
  const child = spawn2(invocation.command, invocation.args, {
@@ -3340,8 +3432,8 @@ var editorRouter = router({
3340
3432
  });
3341
3433
 
3342
3434
  // ../server/src/trpc/routers/api-keys.ts
3343
- import { z as z13 } from "zod";
3344
- import { TRPCError as TRPCError9 } from "@trpc/server";
3435
+ import { z as z14 } from "zod";
3436
+ import { TRPCError as TRPCError10 } from "@trpc/server";
3345
3437
  import { mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
3346
3438
  import { join as join5, dirname as dirname3 } from "path";
3347
3439
  var ALLOWED_SKILL_PATHS = /* @__PURE__ */ new Set([
@@ -3349,46 +3441,46 @@ var ALLOWED_SKILL_PATHS = /* @__PURE__ */ new Set([
3349
3441
  ".cursor/rules/runeya.mdc",
3350
3442
  ".windsurf/rules/runeya.md"
3351
3443
  ]);
3352
- var KeyInputSchema = z13.object({
3353
- name: z13.string().min(1).max(200),
3444
+ var KeyInputSchema = z14.object({
3445
+ name: z14.string().min(1).max(200),
3354
3446
  scopes: ApiKeyScopeSchema,
3355
- isPublic: z13.boolean().default(false)
3447
+ isPublic: z14.boolean().default(false)
3356
3448
  });
3357
3449
  var apiKeysRouter = router({
3358
3450
  list: protectedProcedure.query(() => apiKeyStore.list()),
3359
- create: protectedProcedure.input(KeyInputSchema.extend({ orgId: z13.string().min(1).max(128).nullable().optional() })).mutation(
3451
+ create: protectedProcedure.input(KeyInputSchema.extend({ orgId: z14.string().min(1).max(128).nullable().optional() })).mutation(
3360
3452
  ({ input }) => apiKeyStore.create(input.name, input.scopes, input.isPublic, input.orgId ?? null)
3361
3453
  ),
3362
3454
  /**
3363
3455
  * Renvoie le secret d'une seule clé, sur demande explicite. `list` ne le
3364
3456
  * contient pas : une clé ne doit jamais être re-servie en masse.
3365
3457
  */
3366
- reveal: protectedProcedure.input(z13.object({ id: z13.string().max(128) })).query(async ({ input }) => {
3458
+ reveal: protectedProcedure.input(z14.object({ id: z14.string().max(128) })).query(async ({ input }) => {
3367
3459
  const key = await apiKeyStore.reveal(input.id);
3368
- if (!key) throw new TRPCError9({ code: "NOT_FOUND", message: "API key not found" });
3460
+ if (!key) throw new TRPCError10({ code: "NOT_FOUND", message: "API key not found" });
3369
3461
  return { key };
3370
3462
  }),
3371
- update: protectedProcedure.input(KeyInputSchema.extend({ id: z13.string().max(128) })).mutation(async ({ input }) => {
3463
+ update: protectedProcedure.input(KeyInputSchema.extend({ id: z14.string().max(128) })).mutation(async ({ input }) => {
3372
3464
  const updated = await apiKeyStore.update(input.id, input.name, input.scopes, input.isPublic);
3373
- if (!updated) throw new TRPCError9({ code: "NOT_FOUND", message: "API key not found" });
3465
+ if (!updated) throw new TRPCError10({ code: "NOT_FOUND", message: "API key not found" });
3374
3466
  return maskApiKey(updated);
3375
3467
  }),
3376
- remove: protectedProcedure.input(z13.object({ id: z13.string().max(128) })).mutation(async ({ input }) => {
3468
+ remove: protectedProcedure.input(z14.object({ id: z14.string().max(128) })).mutation(async ({ input }) => {
3377
3469
  const removed = await apiKeyStore.remove(input.id);
3378
- if (!removed) throw new TRPCError9({ code: "NOT_FOUND", message: "API key not found" });
3470
+ if (!removed) throw new TRPCError10({ code: "NOT_FOUND", message: "API key not found" });
3379
3471
  return { success: true };
3380
3472
  }),
3381
- renewKey: protectedProcedure.input(z13.object({ id: z13.string().max(128) })).mutation(async ({ input }) => {
3473
+ renewKey: protectedProcedure.input(z14.object({ id: z14.string().max(128) })).mutation(async ({ input }) => {
3382
3474
  const renewed = await apiKeyStore.renewKey(input.id);
3383
- if (!renewed) throw new TRPCError9({ code: "NOT_FOUND", message: "API key not found" });
3475
+ if (!renewed) throw new TRPCError10({ code: "NOT_FOUND", message: "API key not found" });
3384
3476
  return renewed;
3385
3477
  }),
3386
- writeSkillFile: protectedProcedure.input(z13.object({
3387
- relativePath: z13.string().max(256),
3388
- content: z13.string().max(32768)
3478
+ writeSkillFile: protectedProcedure.input(z14.object({
3479
+ relativePath: z14.string().max(256),
3480
+ content: z14.string().max(32768)
3389
3481
  })).mutation(async ({ input }) => {
3390
3482
  if (!ALLOWED_SKILL_PATHS.has(input.relativePath)) {
3391
- throw new TRPCError9({ code: "BAD_REQUEST", message: "Chemin non autoris\xE9" });
3483
+ throw new TRPCError10({ code: "BAD_REQUEST", message: "Chemin non autoris\xE9" });
3392
3484
  }
3393
3485
  const abs = join5(await resolveWorkspaceCwd({}), input.relativePath);
3394
3486
  await mkdir3(dirname3(abs), { recursive: true });
@@ -3398,133 +3490,133 @@ var apiKeysRouter = router({
3398
3490
  });
3399
3491
 
3400
3492
  // ../server/src/trpc/routers/git.ts
3401
- import { z as z14 } from "zod";
3402
- import { TRPCError as TRPCError10 } from "@trpc/server";
3493
+ import { z as z15 } from "zod";
3494
+ import { TRPCError as TRPCError11 } from "@trpc/server";
3403
3495
  import Anthropic from "@anthropic-ai/sdk";
3404
3496
  import OpenAI from "openai";
3405
- var SERVICE_ID_SCHEMA = z14.string().max(128);
3406
- var SAFE_PATH_SCHEMA = z14.string().min(1).max(4096).refine((p) => !p.startsWith("/") && !p.includes("../"), {
3497
+ var SERVICE_ID_SCHEMA = z15.string().max(128);
3498
+ var SAFE_PATH_SCHEMA = z15.string().min(1).max(4096).refine((p) => !p.startsWith("/") && !p.includes("../"), {
3407
3499
  message: "Path must be relative and not traverse up"
3408
3500
  });
3409
- var REMOTE_SCHEMA = z14.string().min(1).max(128).regex(/^[a-zA-Z0-9_\-.]+$/);
3410
- var BRANCH_SCHEMA = z14.string().min(1).max(256).regex(/^[a-zA-Z0-9._\-/]+$/);
3501
+ var REMOTE_SCHEMA = z15.string().min(1).max(128).regex(/^[a-zA-Z0-9_\-.]+$/);
3502
+ var BRANCH_SCHEMA = z15.string().min(1).max(256).regex(/^[a-zA-Z0-9._\-/]+$/);
3411
3503
  async function resolveServiceContext(serviceId) {
3412
3504
  const service = await serviceStore.get(serviceId);
3413
3505
  if (!service) {
3414
- throw new TRPCError10({ code: "NOT_FOUND", message: "Service not found" });
3506
+ throw new TRPCError11({ code: "NOT_FOUND", message: "Service not found" });
3415
3507
  }
3416
3508
  const agentId = await resolveEffectiveAgentId(service);
3417
3509
  if (!agentId) {
3418
- throw new TRPCError10({ code: "BAD_REQUEST", message: "No agent configured for this service" });
3510
+ throw new TRPCError11({ code: "BAD_REQUEST", message: "No agent configured for this service" });
3419
3511
  }
3420
3512
  return { agentId, cwd: await resolveWorkspaceCwd({ serviceId }) };
3421
3513
  }
3422
3514
  var gitTargetShape = {
3423
3515
  serviceId: SERVICE_ID_SCHEMA.optional(),
3424
- agentId: z14.string().max(128).optional(),
3516
+ agentId: z15.string().max(128).optional(),
3425
3517
  /** Anchors on a project when no service is targeted (e.g. from the AI chat). */
3426
- projectId: z14.string().max(128).optional(),
3518
+ projectId: z15.string().max(128).optional(),
3427
3519
  /** Son organisation : un id de projet seul peut en nommer un par organisation. */
3428
- orgId: z14.string().max(128).nullable().optional()
3520
+ orgId: z15.string().max(128).nullable().optional()
3429
3521
  };
3430
3522
  async function resolveGitContext(input) {
3431
3523
  if (input.serviceId) return resolveServiceContext(input.serviceId);
3432
3524
  const agentId = input.agentId ?? agentManager.getDefaultAgentId();
3433
3525
  if (!agentId) {
3434
- throw new TRPCError10({ code: "BAD_REQUEST", message: "No agent available" });
3526
+ throw new TRPCError11({ code: "BAD_REQUEST", message: "No agent available" });
3435
3527
  }
3436
3528
  const cwd = await resolveAgentCwd({ projectId: input.projectId, orgId: input.orgId }) ?? ".";
3437
3529
  return { agentId, cwd };
3438
3530
  }
3439
3531
  var gitRouter = router({
3440
3532
  /** Get full git status */
3441
- status: protectedProcedure.input(z14.object({ ...gitTargetShape })).query(async ({ input }) => {
3533
+ status: protectedProcedure.input(z15.object({ ...gitTargetShape })).query(async ({ input }) => {
3442
3534
  const { agentId, cwd } = await resolveGitContext(input);
3443
3535
  return agentManager.agentQuery(agentId, "git.status", { cwd });
3444
3536
  }),
3445
3537
  /** Get commit log */
3446
- log: protectedProcedure.input(z14.object({ ...gitTargetShape, limit: z14.number().int().min(1).max(200).default(50) })).query(async ({ input }) => {
3538
+ log: protectedProcedure.input(z15.object({ ...gitTargetShape, limit: z15.number().int().min(1).max(200).default(50) })).query(async ({ input }) => {
3447
3539
  const { agentId, cwd } = await resolveGitContext(input);
3448
3540
  return agentManager.agentQuery(agentId, "git.log", { cwd, limit: input.limit });
3449
3541
  }),
3450
3542
  /** List local and remote branches */
3451
- branches: protectedProcedure.input(z14.object({ ...gitTargetShape })).query(async ({ input }) => {
3543
+ branches: protectedProcedure.input(z15.object({ ...gitTargetShape })).query(async ({ input }) => {
3452
3544
  const { agentId, cwd } = await resolveGitContext(input);
3453
3545
  return agentManager.agentQuery(agentId, "git.branches", { cwd });
3454
3546
  }),
3455
3547
  /** Checkout a branch */
3456
- checkout: protectedProcedure.input(z14.object({ ...gitTargetShape, branch: BRANCH_SCHEMA, create: z14.boolean().default(false) })).mutation(async ({ input }) => {
3548
+ checkout: protectedProcedure.input(z15.object({ ...gitTargetShape, branch: BRANCH_SCHEMA, create: z15.boolean().default(false) })).mutation(async ({ input }) => {
3457
3549
  const { agentId, cwd } = await resolveGitContext(input);
3458
3550
  return agentManager.agentMutation(agentId, "git.checkout", { cwd, branch: input.branch, create: input.create });
3459
3551
  }),
3460
3552
  /** Stage files */
3461
- stage: protectedProcedure.input(z14.object({ ...gitTargetShape, paths: z14.array(SAFE_PATH_SCHEMA).min(1).max(500) })).mutation(async ({ input }) => {
3553
+ stage: protectedProcedure.input(z15.object({ ...gitTargetShape, paths: z15.array(SAFE_PATH_SCHEMA).min(1).max(500) })).mutation(async ({ input }) => {
3462
3554
  const { agentId, cwd } = await resolveGitContext(input);
3463
3555
  return agentManager.agentMutation(agentId, "git.stage", { cwd, paths: input.paths });
3464
3556
  }),
3465
3557
  /** Stage all files */
3466
- stageAll: protectedProcedure.input(z14.object({ ...gitTargetShape })).mutation(async ({ input }) => {
3558
+ stageAll: protectedProcedure.input(z15.object({ ...gitTargetShape })).mutation(async ({ input }) => {
3467
3559
  const { agentId, cwd } = await resolveGitContext(input);
3468
3560
  return agentManager.agentMutation(agentId, "git.stageAll", { cwd });
3469
3561
  }),
3470
3562
  /** Unstage files */
3471
- unstage: protectedProcedure.input(z14.object({ ...gitTargetShape, paths: z14.array(SAFE_PATH_SCHEMA).min(1).max(500) })).mutation(async ({ input }) => {
3563
+ unstage: protectedProcedure.input(z15.object({ ...gitTargetShape, paths: z15.array(SAFE_PATH_SCHEMA).min(1).max(500) })).mutation(async ({ input }) => {
3472
3564
  const { agentId, cwd } = await resolveGitContext(input);
3473
3565
  return agentManager.agentMutation(agentId, "git.unstage", { cwd, paths: input.paths });
3474
3566
  }),
3475
3567
  /** Unstage all files */
3476
- unstageAll: protectedProcedure.input(z14.object({ ...gitTargetShape })).mutation(async ({ input }) => {
3568
+ unstageAll: protectedProcedure.input(z15.object({ ...gitTargetShape })).mutation(async ({ input }) => {
3477
3569
  const { agentId, cwd } = await resolveGitContext(input);
3478
3570
  return agentManager.agentMutation(agentId, "git.unstageAll", { cwd });
3479
3571
  }),
3480
3572
  /** Commit staged changes */
3481
- commit: protectedProcedure.input(z14.object({ ...gitTargetShape, message: z14.string().min(1).max(4096) })).mutation(async ({ input }) => {
3573
+ commit: protectedProcedure.input(z15.object({ ...gitTargetShape, message: z15.string().min(1).max(4096) })).mutation(async ({ input }) => {
3482
3574
  const { agentId, cwd } = await resolveGitContext(input);
3483
3575
  return agentManager.agentMutation(agentId, "git.commit", { cwd, message: input.message });
3484
3576
  }),
3485
3577
  /** Push to remote */
3486
- push: protectedProcedure.input(z14.object({ ...gitTargetShape, remote: REMOTE_SCHEMA.default("origin"), setUpstream: z14.boolean().default(false) })).mutation(async ({ input }) => {
3578
+ push: protectedProcedure.input(z15.object({ ...gitTargetShape, remote: REMOTE_SCHEMA.default("origin"), setUpstream: z15.boolean().default(false) })).mutation(async ({ input }) => {
3487
3579
  const { agentId, cwd } = await resolveGitContext(input);
3488
3580
  return agentManager.agentMutation(agentId, "git.push", { cwd, remote: input.remote, setUpstream: input.setUpstream });
3489
3581
  }),
3490
3582
  /** Pull from remote */
3491
- pull: protectedProcedure.input(z14.object({ ...gitTargetShape, remote: REMOTE_SCHEMA.default("origin") })).mutation(async ({ input }) => {
3583
+ pull: protectedProcedure.input(z15.object({ ...gitTargetShape, remote: REMOTE_SCHEMA.default("origin") })).mutation(async ({ input }) => {
3492
3584
  const { agentId, cwd } = await resolveGitContext(input);
3493
3585
  return agentManager.agentMutation(agentId, "git.pull", { cwd, remote: input.remote });
3494
3586
  }),
3495
3587
  /** Fetch from remote */
3496
- fetch: protectedProcedure.input(z14.object({ ...gitTargetShape, remote: REMOTE_SCHEMA.default("origin") })).mutation(async ({ input }) => {
3588
+ fetch: protectedProcedure.input(z15.object({ ...gitTargetShape, remote: REMOTE_SCHEMA.default("origin") })).mutation(async ({ input }) => {
3497
3589
  const { agentId, cwd } = await resolveGitContext(input);
3498
3590
  return agentManager.agentMutation(agentId, "git.fetch", { cwd, remote: input.remote });
3499
3591
  }),
3500
3592
  /** Get diff for a file or the whole index */
3501
- diff: protectedProcedure.input(z14.object({
3593
+ diff: protectedProcedure.input(z15.object({
3502
3594
  ...gitTargetShape,
3503
- path: z14.string().max(4096).optional(),
3504
- staged: z14.boolean().default(false),
3505
- untracked: z14.boolean().default(false)
3595
+ path: z15.string().max(4096).optional(),
3596
+ staged: z15.boolean().default(false),
3597
+ untracked: z15.boolean().default(false)
3506
3598
  })).query(async ({ input }) => {
3507
3599
  const { agentId, cwd } = await resolveGitContext(input);
3508
3600
  return agentManager.agentQuery(agentId, "git.diff", { cwd, path: input.path, staged: input.staged, untracked: input.untracked });
3509
3601
  }),
3510
3602
  /** Discard changes to working tree files */
3511
- discard: protectedProcedure.input(z14.object({ ...gitTargetShape, paths: z14.array(SAFE_PATH_SCHEMA).min(1).max(500) })).mutation(async ({ input }) => {
3603
+ discard: protectedProcedure.input(z15.object({ ...gitTargetShape, paths: z15.array(SAFE_PATH_SCHEMA).min(1).max(500) })).mutation(async ({ input }) => {
3512
3604
  const { agentId, cwd } = await resolveGitContext(input);
3513
3605
  return agentManager.agentMutation(agentId, "git.discard", { cwd, paths: input.paths });
3514
3606
  }),
3515
3607
  /** Generate a commit message from staged diffs using AI (diff fetched from agent, AI runs on server) */
3516
- generateCommitMessage: protectedProcedure.input(z14.object({ ...gitTargetShape, providerId: OptionalProviderIdSchema, model: z14.string().max(200).optional() })).mutation(async ({ input }) => {
3608
+ generateCommitMessage: protectedProcedure.input(z15.object({ ...gitTargetShape, providerId: OptionalProviderIdSchema, model: z15.string().max(200).optional() })).mutation(async ({ input }) => {
3517
3609
  const { agentId, cwd } = await resolveGitContext(input);
3518
3610
  const { diff } = await agentManager.agentQuery(agentId, "git.stagedDiff", { cwd });
3519
3611
  if (!diff.trim()) {
3520
- throw new TRPCError10({ code: "BAD_REQUEST", message: "No staged changes to generate a commit message from" });
3612
+ throw new TRPCError11({ code: "BAD_REQUEST", message: "No staged changes to generate a commit message from" });
3521
3613
  }
3522
3614
  const active = await getActiveProvider(
3523
3615
  input.providerId,
3524
3616
  input.orgId ?? await vaultOfProject(input.projectId)
3525
3617
  );
3526
3618
  if (!active) {
3527
- throw new TRPCError10({ code: "BAD_REQUEST", message: "No AI provider configured" });
3619
+ throw new TRPCError11({ code: "BAD_REQUEST", message: "No AI provider configured" });
3528
3620
  }
3529
3621
  const systemPrompt = `You are a git commit message generator. Given a git diff, write a concise and meaningful conventional commit message (e.g. feat:, fix:, refactor:, chore:, docs:, style:, test:).
3530
3622
  Rules:
@@ -3557,45 +3649,45 @@ Rules:
3557
3649
  });
3558
3650
  return { message: res.choices[0]?.message?.content?.trim() ?? "" };
3559
3651
  }
3560
- throw new TRPCError10({ code: "BAD_REQUEST", message: "Unsupported AI provider" });
3652
+ throw new TRPCError11({ code: "BAD_REQUEST", message: "Unsupported AI provider" });
3561
3653
  }),
3562
3654
  /** Merge a branch into the current branch */
3563
- merge: protectedProcedure.input(z14.object({ ...gitTargetShape, branch: BRANCH_SCHEMA, noFf: z14.boolean().default(false) })).mutation(async ({ input }) => {
3655
+ merge: protectedProcedure.input(z15.object({ ...gitTargetShape, branch: BRANCH_SCHEMA, noFf: z15.boolean().default(false) })).mutation(async ({ input }) => {
3564
3656
  const { agentId, cwd } = await resolveGitContext(input);
3565
3657
  return agentManager.agentMutation(agentId, "git.merge", { cwd, branch: input.branch, noFf: input.noFf });
3566
3658
  }),
3567
3659
  /** Rebase current branch onto another branch */
3568
- rebase: protectedProcedure.input(z14.object({ ...gitTargetShape, branch: BRANCH_SCHEMA })).mutation(async ({ input }) => {
3660
+ rebase: protectedProcedure.input(z15.object({ ...gitTargetShape, branch: BRANCH_SCHEMA })).mutation(async ({ input }) => {
3569
3661
  const { agentId, cwd } = await resolveGitContext(input);
3570
3662
  return agentManager.agentMutation(agentId, "git.rebase", { cwd, branch: input.branch });
3571
3663
  }),
3572
3664
  /** List stash entries */
3573
- stashList: protectedProcedure.input(z14.object({ ...gitTargetShape })).query(async ({ input }) => {
3665
+ stashList: protectedProcedure.input(z15.object({ ...gitTargetShape })).query(async ({ input }) => {
3574
3666
  const { agentId, cwd } = await resolveGitContext(input);
3575
3667
  return agentManager.agentQuery(agentId, "git.stashList", { cwd });
3576
3668
  }),
3577
3669
  /** Stash current changes */
3578
- stashPush: protectedProcedure.input(z14.object({ ...gitTargetShape, message: z14.string().max(4096).optional(), includeUntracked: z14.boolean().default(true) })).mutation(async ({ input }) => {
3670
+ stashPush: protectedProcedure.input(z15.object({ ...gitTargetShape, message: z15.string().max(4096).optional(), includeUntracked: z15.boolean().default(true) })).mutation(async ({ input }) => {
3579
3671
  const { agentId, cwd } = await resolveGitContext(input);
3580
3672
  return agentManager.agentMutation(agentId, "git.stashPush", { cwd, message: input.message, includeUntracked: input.includeUntracked });
3581
3673
  }),
3582
3674
  /** Pop a stash entry */
3583
- stashPop: protectedProcedure.input(z14.object({ ...gitTargetShape, index: z14.number().int().min(0).max(1e3).default(0) })).mutation(async ({ input }) => {
3675
+ stashPop: protectedProcedure.input(z15.object({ ...gitTargetShape, index: z15.number().int().min(0).max(1e3).default(0) })).mutation(async ({ input }) => {
3584
3676
  const { agentId, cwd } = await resolveGitContext(input);
3585
3677
  return agentManager.agentMutation(agentId, "git.stashPop", { cwd, index: input.index });
3586
3678
  }),
3587
3679
  /** Apply a stash entry without dropping it */
3588
- stashApply: protectedProcedure.input(z14.object({ ...gitTargetShape, index: z14.number().int().min(0).max(1e3).default(0) })).mutation(async ({ input }) => {
3680
+ stashApply: protectedProcedure.input(z15.object({ ...gitTargetShape, index: z15.number().int().min(0).max(1e3).default(0) })).mutation(async ({ input }) => {
3589
3681
  const { agentId, cwd } = await resolveGitContext(input);
3590
3682
  return agentManager.agentMutation(agentId, "git.stashApply", { cwd, index: input.index });
3591
3683
  }),
3592
3684
  /** Drop a stash entry */
3593
- stashDrop: protectedProcedure.input(z14.object({ ...gitTargetShape, index: z14.number().int().min(0).max(1e3).default(0) })).mutation(async ({ input }) => {
3685
+ stashDrop: protectedProcedure.input(z15.object({ ...gitTargetShape, index: z15.number().int().min(0).max(1e3).default(0) })).mutation(async ({ input }) => {
3594
3686
  const { agentId, cwd } = await resolveGitContext(input);
3595
3687
  return agentManager.agentMutation(agentId, "git.stashDrop", { cwd, index: input.index });
3596
3688
  }),
3597
3689
  /** Watch .git/ for changes and stream updated status */
3598
- onStatusChange: protectedProcedure.input(z14.object({ ...gitTargetShape })).subscription(async function* ({ input }) {
3690
+ onStatusChange: protectedProcedure.input(z15.object({ ...gitTargetShape })).subscription(async function* ({ input }) {
3599
3691
  const { agentId, cwd } = await resolveGitContext(input);
3600
3692
  const queue = [];
3601
3693
  let resolve4 = null;
@@ -3622,7 +3714,7 @@ Rules:
3622
3714
  }
3623
3715
  );
3624
3716
  } catch (err) {
3625
- throw new TRPCError10({
3717
+ throw new TRPCError11({
3626
3718
  code: "BAD_REQUEST",
3627
3719
  message: `Cannot subscribe to git status: ${err.message}`
3628
3720
  });
@@ -3642,7 +3734,7 @@ Rules:
3642
3734
  }
3643
3735
  }),
3644
3736
  /** List remotes */
3645
- remotes: protectedProcedure.input(z14.object({ ...gitTargetShape })).query(async ({ input }) => {
3737
+ remotes: protectedProcedure.input(z15.object({ ...gitTargetShape })).query(async ({ input }) => {
3646
3738
  const { agentId, cwd } = await resolveGitContext(input);
3647
3739
  return agentManager.agentQuery(agentId, "git.remotes", { cwd });
3648
3740
  })
@@ -3650,41 +3742,41 @@ Rules:
3650
3742
 
3651
3743
  // ../server/src/trpc/routers/scenario.ts
3652
3744
  import { randomUUID as randomUUID3 } from "crypto";
3653
- import { TRPCError as TRPCError13 } from "@trpc/server";
3654
- import { z as z15 } from "zod";
3745
+ import { TRPCError as TRPCError14 } from "@trpc/server";
3746
+ import { z as z16 } from "zod";
3655
3747
 
3656
3748
  // ../server/src/trpc/crud-procedure-utils.ts
3657
- import { TRPCError as TRPCError11 } from "@trpc/server";
3749
+ import { TRPCError as TRPCError12 } from "@trpc/server";
3658
3750
  async function getOrNotFound(getter, notFoundMessage) {
3659
3751
  const entity = await getter();
3660
- if (!entity) throw new TRPCError11({ code: "NOT_FOUND", message: notFoundMessage });
3752
+ if (!entity) throw new TRPCError12({ code: "NOT_FOUND", message: notFoundMessage });
3661
3753
  return entity;
3662
3754
  }
3663
3755
  async function createOrBadRequest(creator) {
3664
3756
  try {
3665
3757
  return await creator();
3666
3758
  } catch (err) {
3667
- throw new TRPCError11({ code: "BAD_REQUEST", message: err.message });
3759
+ throw new TRPCError12({ code: "BAD_REQUEST", message: err.message });
3668
3760
  }
3669
3761
  }
3670
3762
  async function updateOrThrow(updater, notFoundMessage) {
3671
3763
  try {
3672
3764
  const entity = await updater();
3673
- if (!entity) throw new TRPCError11({ code: "NOT_FOUND", message: notFoundMessage });
3765
+ if (!entity) throw new TRPCError12({ code: "NOT_FOUND", message: notFoundMessage });
3674
3766
  return entity;
3675
3767
  } catch (err) {
3676
- if (err instanceof TRPCError11) throw err;
3677
- throw new TRPCError11({ code: "BAD_REQUEST", message: err.message });
3768
+ if (err instanceof TRPCError12) throw err;
3769
+ throw new TRPCError12({ code: "BAD_REQUEST", message: err.message });
3678
3770
  }
3679
3771
  }
3680
3772
  async function deleteOrNotFound(deleter, notFoundMessage) {
3681
3773
  const deleted = await deleter();
3682
- if (!deleted) throw new TRPCError11({ code: "NOT_FOUND", message: notFoundMessage });
3774
+ if (!deleted) throw new TRPCError12({ code: "NOT_FOUND", message: notFoundMessage });
3683
3775
  return { ok: true };
3684
3776
  }
3685
3777
 
3686
3778
  // ../server/src/trpc/ai-generation-procedure-utils.ts
3687
- import { TRPCError as TRPCError12 } from "@trpc/server";
3779
+ import { TRPCError as TRPCError13 } from "@trpc/server";
3688
3780
 
3689
3781
  // ../server/src/services/ai-generation.ts
3690
3782
  import Anthropic2 from "@anthropic-ai/sdk";
@@ -3740,7 +3832,7 @@ async function* streamProviderText(input) {
3740
3832
  // ../server/src/trpc/ai-generation-procedure-utils.ts
3741
3833
  async function* streamWithActiveProvider(opts) {
3742
3834
  const active = await getActiveProvider(opts.providerId, opts.vault);
3743
- if (!active) throw new TRPCError12({ code: "BAD_REQUEST", message: "Aucun fournisseur IA configur\xE9" });
3835
+ if (!active) throw new TRPCError13({ code: "BAD_REQUEST", message: "Aucun fournisseur IA configur\xE9" });
3744
3836
  const { provider, plaintextKey } = active;
3745
3837
  const model = opts.model || provider.model || DEFAULT_MODELS[provider.provider] || "";
3746
3838
  try {
@@ -3758,7 +3850,7 @@ async function* streamWithActiveProvider(opts) {
3758
3850
  yield { type: "done", text: "" };
3759
3851
  } catch (err) {
3760
3852
  if (String(err?.message ?? "").startsWith("Unsupported provider:")) {
3761
- throw new TRPCError12({ code: "BAD_REQUEST", message: `Fournisseur non support\xE9: ${provider.provider}` });
3853
+ throw new TRPCError13({ code: "BAD_REQUEST", message: `Fournisseur non support\xE9: ${provider.provider}` });
3762
3854
  }
3763
3855
  throw err;
3764
3856
  }
@@ -5250,28 +5342,28 @@ Modify the scenario. Keep existing ids when possible.`;
5250
5342
  return `Generate an scenario org-chart based on: ${userPrompt}`;
5251
5343
  }
5252
5344
  var ScopeShape2 = {
5253
- orgId: z15.string().max(128).nullable().optional(),
5345
+ orgId: z16.string().max(128).nullable().optional(),
5254
5346
  projectId: Id128Schema.optional()
5255
5347
  };
5256
5348
  async function scopeOf2(input) {
5257
5349
  return input?.orgId ?? await vaultOfProject(input?.projectId);
5258
5350
  }
5259
5351
  var scenarioRouter = router({
5260
- list: protectedProcedure.input(z15.object(ScopeShape2).optional()).query(async ({ input }) => scenarioStore.list(await scopeOf2(input))),
5261
- get: protectedProcedure.input(z15.object({ id: Id128Schema, ...ScopeShape2 })).query(async ({ input }) => getOrNotFound(
5352
+ list: protectedProcedure.input(z16.object(ScopeShape2).optional()).query(async ({ input }) => scenarioStore.list(await scopeOf2(input))),
5353
+ get: protectedProcedure.input(z16.object({ id: Id128Schema, ...ScopeShape2 })).query(async ({ input }) => getOrNotFound(
5262
5354
  async () => scenarioStore.get(input.id, await scopeOf2(input)),
5263
5355
  "Scenario not found"
5264
5356
  )),
5265
- create: protectedProcedure.input(z15.object({
5357
+ create: protectedProcedure.input(z16.object({
5266
5358
  name: NameSchema,
5267
- icon: z15.string().max(64).optional(),
5359
+ icon: z16.string().max(64).optional(),
5268
5360
  description: DescriptionSchema.optional(),
5269
5361
  leaderId: Id128Schema,
5270
- groups: z15.array(ScenarioGroupSchema).max(100).optional(),
5271
- nodes: z15.array(ScenarioNodeSchema).min(1).max(500),
5272
- traversalMode: z15.enum(["hierarchical", "topological"]).optional(),
5273
- presetId: z15.string().max(128).optional(),
5274
- isPublished: z15.boolean().optional(),
5362
+ groups: z16.array(ScenarioGroupSchema).max(100).optional(),
5363
+ nodes: z16.array(ScenarioNodeSchema).min(1).max(500),
5364
+ traversalMode: z16.enum(["hierarchical", "topological"]).optional(),
5365
+ presetId: z16.string().max(128).optional(),
5366
+ isPublished: z16.boolean().optional(),
5275
5367
  ...ScopeShape2
5276
5368
  })).mutation(({ input }) => {
5277
5369
  const now = Date.now();
@@ -5290,17 +5382,17 @@ var scenarioRouter = router({
5290
5382
  updatedAt: now
5291
5383
  }));
5292
5384
  }),
5293
- update: protectedProcedure.input(z15.object({
5385
+ update: protectedProcedure.input(z16.object({
5294
5386
  id: Id128Schema,
5295
5387
  name: NameSchema.optional(),
5296
- icon: z15.string().max(64).optional(),
5388
+ icon: z16.string().max(64).optional(),
5297
5389
  description: DescriptionSchema.optional(),
5298
5390
  leaderId: Id128Schema.optional(),
5299
- groups: z15.array(ScenarioGroupSchema).max(100).optional(),
5300
- nodes: z15.array(ScenarioNodeSchema).min(1).max(500).optional(),
5301
- traversalMode: z15.enum(["hierarchical", "topological"]).optional(),
5302
- presetId: z15.string().max(128).optional(),
5303
- isPublished: z15.boolean().optional(),
5391
+ groups: z16.array(ScenarioGroupSchema).max(100).optional(),
5392
+ nodes: z16.array(ScenarioNodeSchema).min(1).max(500).optional(),
5393
+ traversalMode: z16.enum(["hierarchical", "topological"]).optional(),
5394
+ presetId: z16.string().max(128).optional(),
5395
+ isPublished: z16.boolean().optional(),
5304
5396
  ...ScopeShape2
5305
5397
  })).mutation(({ input }) => updateOrThrow(
5306
5398
  async () => scenarioStore.update(input.id, {
@@ -5317,25 +5409,25 @@ var scenarioRouter = router({
5317
5409
  }, await scopeOf2(input)),
5318
5410
  "Scenario not found"
5319
5411
  )),
5320
- delete: protectedProcedure.input(z15.object({ id: Id128Schema, ...ScopeShape2 })).mutation(({ input }) => deleteOrNotFound(
5412
+ delete: protectedProcedure.input(z16.object({ id: Id128Schema, ...ScopeShape2 })).mutation(({ input }) => deleteOrNotFound(
5321
5413
  async () => scenarioStore.delete(input.id, await scopeOf2(input)),
5322
5414
  "Scenario not found"
5323
5415
  )),
5324
- run: protectedProcedure.input(z15.object({
5416
+ run: protectedProcedure.input(z16.object({
5325
5417
  conversationId: ConversationIdSchema,
5326
5418
  scenarioId: Id128Schema,
5327
- userRequest: z15.string().max(1e5),
5328
- runnerOverride: z15.enum(["claude-code", "codex"]).optional(),
5419
+ userRequest: z16.string().max(1e5),
5420
+ runnerOverride: z16.enum(["claude-code", "codex"]).optional(),
5329
5421
  modelOverride: Id128Schema.optional(),
5330
5422
  agentId: Id128Schema.optional(),
5331
5423
  /** Anchors the run's working directory on the project it belongs to. */
5332
5424
  projectId: Id128Schema.optional(),
5333
5425
  /** Son organisation : sans elle, un id partagé désignerait un projet au hasard. */
5334
- orgId: z15.string().max(128).nullable().optional(),
5335
- resume: z15.boolean().optional()
5426
+ orgId: z16.string().max(128).nullable().optional(),
5427
+ resume: z16.boolean().optional()
5336
5428
  })).subscription(async function* ({ input, signal }) {
5337
5429
  const scenario = await scenarioStore.get(input.scenarioId, await scopeOf2(input));
5338
- if (!scenario) throw new TRPCError13({ code: "NOT_FOUND", message: "Scenario not found" });
5430
+ if (!scenario) throw new TRPCError14({ code: "NOT_FOUND", message: "Scenario not found" });
5339
5431
  const canStart = input.userRequest.trim().length > 0 || !!input.resume;
5340
5432
  if (!isScenarioRunning(input.conversationId) && canStart) {
5341
5433
  let userRequest = input.userRequest;
@@ -5352,41 +5444,41 @@ var scenarioRouter = router({
5352
5444
  }
5353
5445
  yield* tapBus(input.conversationId, signal ?? new AbortController().signal);
5354
5446
  }),
5355
- stop: protectedProcedure.input(z15.object({ conversationId: ConversationIdSchema })).mutation(({ input }) => {
5447
+ stop: protectedProcedure.input(z16.object({ conversationId: ConversationIdSchema })).mutation(({ input }) => {
5356
5448
  abortScenario(input.conversationId);
5357
5449
  return { ok: true };
5358
5450
  }),
5359
- sendNodeInput: protectedProcedure.input(z15.object({
5451
+ sendNodeInput: protectedProcedure.input(z16.object({
5360
5452
  conversationId: ConversationIdSchema,
5361
5453
  nodeId: Id128Schema,
5362
- text: z15.string().min(1).max(1e5)
5454
+ text: z16.string().min(1).max(1e5)
5363
5455
  })).mutation(({ input }) => {
5364
5456
  const resolved = resolveNodeInput(input.conversationId, input.nodeId, input.text);
5365
- if (!resolved) throw new TRPCError13({ code: "NOT_FOUND", message: "No pending input request for this node" });
5457
+ if (!resolved) throw new TRPCError14({ code: "NOT_FOUND", message: "No pending input request for this node" });
5366
5458
  return { ok: true };
5367
5459
  }),
5368
- isRunning: protectedProcedure.input(z15.object({ conversationId: ConversationIdSchema })).query(({ input }) => ({ running: isScenarioRunning(input.conversationId) })),
5369
- runState: protectedProcedure.input(z15.object({ conversationId: ConversationIdSchema })).query(({ input }) => {
5460
+ isRunning: protectedProcedure.input(z16.object({ conversationId: ConversationIdSchema })).query(({ input }) => ({ running: isScenarioRunning(input.conversationId) })),
5461
+ runState: protectedProcedure.input(z16.object({ conversationId: ConversationIdSchema })).query(({ input }) => {
5370
5462
  const runState = scenarioRunStore.getRunState(input.conversationId);
5371
5463
  return runState ?? { nodeStates: {}, nodeOutputs: {}, activeNodeId: void 0 };
5372
5464
  }),
5373
- getPersistedRunState: protectedProcedure.input(z15.object({ conversationId: ConversationIdSchema })).query(async ({ input }) => {
5465
+ getPersistedRunState: protectedProcedure.input(z16.object({ conversationId: ConversationIdSchema })).query(async ({ input }) => {
5374
5466
  return await scenarioRunStore.loadPersistedRunState(input.conversationId);
5375
5467
  }),
5376
- getReadme: protectedProcedure.input(z15.object({ conversationId: ConversationIdSchema })).query(async ({ input }) => {
5468
+ getReadme: protectedProcedure.input(z16.object({ conversationId: ConversationIdSchema })).query(async ({ input }) => {
5377
5469
  return await scenarioRunStore.readReadme(input.conversationId);
5378
5470
  }),
5379
- getSnapshot: protectedProcedure.input(z15.object({ conversationId: ConversationIdSchema })).query(async ({ input }) => {
5471
+ getSnapshot: protectedProcedure.input(z16.object({ conversationId: ConversationIdSchema })).query(async ({ input }) => {
5380
5472
  return await scenarioRunStore.loadScenarioSnapshot(input.conversationId);
5381
5473
  }),
5382
- streamGenerateWithAI: protectedProcedure.input(z15.object({
5383
- prompt: z15.string().min(1).max(1e4),
5474
+ streamGenerateWithAI: protectedProcedure.input(z16.object({
5475
+ prompt: z16.string().min(1).max(1e4),
5384
5476
  providerId: OptionalProviderIdSchema,
5385
- model: z15.string().max(200).optional(),
5386
- current: z15.object({
5477
+ model: z16.string().max(200).optional(),
5478
+ current: z16.object({
5387
5479
  leaderId: Id128Schema,
5388
- groups: z15.array(ScenarioGroupSchema).max(100),
5389
- nodes: z15.array(ScenarioNodeSchema).max(500)
5480
+ groups: z16.array(ScenarioGroupSchema).max(100),
5481
+ nodes: z16.array(ScenarioNodeSchema).max(500)
5390
5482
  }).optional()
5391
5483
  })).subscription(async function* ({ input, signal }) {
5392
5484
  const userMessage = buildScenarioUserMessage(input.prompt, input.current);
@@ -5399,7 +5491,7 @@ var scenarioRouter = router({
5399
5491
  signal: signal ?? void 0
5400
5492
  });
5401
5493
  }),
5402
- streamRunEvents: protectedProcedure.input(z15.object({ conversationId: ConversationIdSchema })).subscription(async function* ({ input }) {
5494
+ streamRunEvents: protectedProcedure.input(z16.object({ conversationId: ConversationIdSchema })).subscription(async function* ({ input }) {
5403
5495
  const convId = input.conversationId;
5404
5496
  const runState = scenarioRunStore.getRunState(convId);
5405
5497
  if (runState) {
@@ -5413,24 +5505,24 @@ var scenarioRouter = router({
5413
5505
  * open a debug PTY with `claude --resume <sessionId>` on the right agent.
5414
5506
  * Falls back to the persisted run-state for past nodes.
5415
5507
  */
5416
- getNodeSession: protectedProcedure.input(z15.object({
5508
+ getNodeSession: protectedProcedure.input(z16.object({
5417
5509
  conversationId: ConversationIdSchema,
5418
5510
  nodeId: Id128Schema
5419
5511
  })).query(async ({ input }) => {
5420
5512
  return await scenarioRunStore.getNodeSessionPersistent(input.conversationId, input.nodeId);
5421
5513
  }),
5422
5514
  listPresets: protectedProcedure.query(() => listPresets()),
5423
- getPreset: protectedProcedure.input(z15.object({ id: Id128Schema })).query(({ input }) => {
5515
+ getPreset: protectedProcedure.input(z16.object({ id: Id128Schema })).query(({ input }) => {
5424
5516
  const preset = getPreset(input.id);
5425
- if (!preset) throw new TRPCError13({ code: "NOT_FOUND", message: "Preset not found" });
5517
+ if (!preset) throw new TRPCError14({ code: "NOT_FOUND", message: "Preset not found" });
5426
5518
  return preset;
5427
5519
  })
5428
5520
  });
5429
5521
 
5430
5522
  // ../server/src/trpc/routers/debug.ts
5431
5523
  import { randomUUID as randomUUID4 } from "crypto";
5432
- import { TRPCError as TRPCError14 } from "@trpc/server";
5433
- import { z as z16 } from "zod";
5524
+ import { TRPCError as TRPCError15 } from "@trpc/server";
5525
+ import { z as z17 } from "zod";
5434
5526
  var MAX_BUFFER2 = 300;
5435
5527
  var jobs = /* @__PURE__ */ new Map();
5436
5528
  function publish(job, event) {
@@ -5487,9 +5579,9 @@ async function* tapJob(job, signal) {
5487
5579
  }
5488
5580
  }
5489
5581
  var debugRouter = router({
5490
- startRandomJob: protectedProcedure.input(z16.object({
5491
- intervalMs: z16.number().int().min(100).max(5e3).optional(),
5492
- maxTicks: z16.number().int().min(1).max(1e4).optional()
5582
+ startRandomJob: protectedProcedure.input(z17.object({
5583
+ intervalMs: z17.number().int().min(100).max(5e3).optional(),
5584
+ maxTicks: z17.number().int().min(1).max(1e4).optional()
5493
5585
  }).optional()).mutation(({ input }) => {
5494
5586
  const jobId = randomUUID4();
5495
5587
  const intervalMs = input?.intervalMs ?? 400;
@@ -5523,15 +5615,15 @@ var debugRouter = router({
5523
5615
  jobs.set(jobId, job);
5524
5616
  return { jobId, intervalMs, maxTicks, startedAt: job.startedAt };
5525
5617
  }),
5526
- streamRandomJob: protectedProcedure.input(z16.object({ jobId: z16.string().max(128) })).subscription(async function* ({ input, signal }) {
5618
+ streamRandomJob: protectedProcedure.input(z17.object({ jobId: z17.string().max(128) })).subscription(async function* ({ input, signal }) {
5527
5619
  const job = jobs.get(input.jobId);
5528
5620
  if (!job) {
5529
- throw new TRPCError14({ code: "NOT_FOUND", message: "Random job not found" });
5621
+ throw new TRPCError15({ code: "NOT_FOUND", message: "Random job not found" });
5530
5622
  }
5531
5623
  yield* tapJob(job, signal ?? new AbortController().signal);
5532
5624
  }),
5533
- stopRandomJob: protectedProcedure.input(z16.object({ jobId: z16.string().max(128) })).mutation(({ input }) => ({ ok: stopJob(input.jobId, "stopped") })),
5534
- randomJobStatus: protectedProcedure.input(z16.object({ jobId: z16.string().max(128) })).query(({ input }) => {
5625
+ stopRandomJob: protectedProcedure.input(z17.object({ jobId: z17.string().max(128) })).mutation(({ input }) => ({ ok: stopJob(input.jobId, "stopped") })),
5626
+ randomJobStatus: protectedProcedure.input(z17.object({ jobId: z17.string().max(128) })).query(({ input }) => {
5535
5627
  const job = jobs.get(input.jobId);
5536
5628
  return {
5537
5629
  running: !!job && !job.done,
@@ -5541,8 +5633,8 @@ var debugRouter = router({
5541
5633
  });
5542
5634
 
5543
5635
  // ../server/src/trpc/routers/diagnostics.ts
5544
- import { z as z17 } from "zod";
5545
- import { TRPCError as TRPCError15 } from "@trpc/server";
5636
+ import { z as z18 } from "zod";
5637
+ import { TRPCError as TRPCError16 } from "@trpc/server";
5546
5638
 
5547
5639
  // ../server/src/services/log-buffer.ts
5548
5640
  import { EventEmitter } from "events";
@@ -5613,7 +5705,7 @@ function onEntry(listener) {
5613
5705
  // ../server/src/trpc/routers/diagnostics.ts
5614
5706
  var diagnosticsRouter = router({
5615
5707
  /** Backlog for a client that just opened the panel. */
5616
- recentLogs: protectedProcedure.input(z17.object({ limit: z17.number().int().min(1).max(2e3).default(500) }).optional()).query(({ input }) => recentEntries(input?.limit ?? 500)),
5708
+ recentLogs: protectedProcedure.input(z18.object({ limit: z18.number().int().min(1).max(2e3).default(500) }).optional()).query(({ input }) => recentEntries(input?.limit ?? 500)),
5617
5709
  /**
5618
5710
  * Live log stream.
5619
5711
  *
@@ -5622,7 +5714,7 @@ var diagnosticsRouter = router({
5622
5714
  * silently loses lines, which is precisely what someone watching a boot
5623
5715
  * failure cannot afford.
5624
5716
  */
5625
- streamLogs: protectedProcedure.input(z17.object({ afterSeq: z17.number().int().nonnegative().default(0) }).optional()).subscription(async function* ({ input, signal }) {
5717
+ streamLogs: protectedProcedure.input(z18.object({ afterSeq: z18.number().int().nonnegative().default(0) }).optional()).subscription(async function* ({ input, signal }) {
5626
5718
  for (const entry of entriesSince(input?.afterSeq ?? 0)) yield entry;
5627
5719
  const queue = [];
5628
5720
  let wake = null;
@@ -5656,18 +5748,18 @@ var diagnosticsRouter = router({
5656
5748
  * refused. That is what keeps this from being a way to signal arbitrary
5657
5749
  * processes with the server's privileges.
5658
5750
  */
5659
- killInstance: protectedProcedure.input(z17.object({ pid: z17.number().int().positive() })).mutation(async ({ input }) => {
5751
+ killInstance: protectedProcedure.input(z18.object({ pid: z18.number().int().positive() })).mutation(async ({ input }) => {
5660
5752
  try {
5661
5753
  return await killInstance(input.pid);
5662
5754
  } catch (err) {
5663
5755
  const reason = err.message;
5664
5756
  if (reason === "instance-not-found") {
5665
- throw new TRPCError15({ code: "NOT_FOUND", message: "No live Runeya instance with this pid." });
5757
+ throw new TRPCError16({ code: "NOT_FOUND", message: "No live Runeya instance with this pid." });
5666
5758
  }
5667
5759
  if (reason === "instance-is-current") {
5668
- throw new TRPCError15({ code: "BAD_REQUEST", message: "This instance cannot stop itself." });
5760
+ throw new TRPCError16({ code: "BAD_REQUEST", message: "This instance cannot stop itself." });
5669
5761
  }
5670
- throw new TRPCError15({ code: "INTERNAL_SERVER_ERROR", message: reason });
5762
+ throw new TRPCError16({ code: "INTERNAL_SERVER_ERROR", message: reason });
5671
5763
  }
5672
5764
  }),
5673
5765
  /**
@@ -5684,7 +5776,7 @@ var diagnosticsRouter = router({
5684
5776
  * reproductible : instance trop ancienne pour avoir publié sa ligne de
5685
5777
  * commande, ou lancée avec un secret que le registre ne conserve pas.
5686
5778
  */
5687
- restartInstance: protectedProcedure.input(z17.object({ pid: z17.number().int().positive() })).mutation(async ({ input }) => {
5779
+ restartInstance: protectedProcedure.input(z18.object({ pid: z18.number().int().positive() })).mutation(async ({ input }) => {
5688
5780
  try {
5689
5781
  if (input.pid === process.pid) {
5690
5782
  const { relauncherPid, port } = await scheduleSelfRestart();
@@ -5694,21 +5786,21 @@ var diagnosticsRouter = router({
5694
5786
  } catch (err) {
5695
5787
  const reason = err.message;
5696
5788
  if (reason === "instance-not-found") {
5697
- throw new TRPCError15({ code: "NOT_FOUND", message: "No live Runeya instance with this pid." });
5789
+ throw new TRPCError16({ code: "NOT_FOUND", message: "No live Runeya instance with this pid." });
5698
5790
  }
5699
5791
  if (reason.startsWith("instance-not-restartable:")) {
5700
- throw new TRPCError15({
5792
+ throw new TRPCError16({
5701
5793
  code: "BAD_REQUEST",
5702
5794
  message: `This instance cannot be restarted (${reason.split(":")[1]}).`
5703
5795
  });
5704
5796
  }
5705
- throw new TRPCError15({ code: "INTERNAL_SERVER_ERROR", message: reason });
5797
+ throw new TRPCError16({ code: "INTERNAL_SERVER_ERROR", message: reason });
5706
5798
  }
5707
5799
  })
5708
5800
  });
5709
5801
 
5710
5802
  // ../server/src/trpc/routers/kanban-queue.ts
5711
- import { z as z18 } from "zod";
5803
+ import { z as z19 } from "zod";
5712
5804
 
5713
5805
  // ../server/src/services/kanban-queue.ts
5714
5806
  import { randomUUID as randomUUID5 } from "crypto";
@@ -5900,38 +5992,38 @@ var kanbanQueue = new KanbanQueueService();
5900
5992
  // ../server/src/trpc/routers/kanban-queue.ts
5901
5993
  var kanbanQueueRouter = router({
5902
5994
  getState: protectedProcedure.query(() => kanbanQueue.getState()),
5903
- add: protectedProcedure.input(z18.object({
5904
- boardId: z18.string().max(128),
5905
- cardId: z18.string().max(128),
5906
- runner: z18.enum(["claude-code", "codex"]).optional(),
5907
- model: z18.string().max(128).optional(),
5908
- scenarioId: z18.string().max(128).optional(),
5995
+ add: protectedProcedure.input(z19.object({
5996
+ boardId: z19.string().max(128),
5997
+ cardId: z19.string().max(128),
5998
+ runner: z19.enum(["claude-code", "codex"]).optional(),
5999
+ model: z19.string().max(128).optional(),
6000
+ scenarioId: z19.string().max(128).optional(),
5909
6001
  // Le projet ouvert quand la carte a été mise en file : la conversation
5910
6002
  // qui en naîtra lui appartient, plutôt que de rester orpheline et de
5911
6003
  // s'afficher dans tous les projets.
5912
- projectId: z18.string().max(128).optional(),
5913
- orgId: z18.string().max(128).nullable().optional()
6004
+ projectId: z19.string().max(128).optional(),
6005
+ orgId: z19.string().max(128).nullable().optional()
5914
6006
  })).mutation(({ input }) => kanbanQueue.add(input)),
5915
- addColumn: protectedProcedure.input(z18.object({
5916
- boardId: z18.string().max(128),
5917
- columnId: z18.string().max(128),
6007
+ addColumn: protectedProcedure.input(z19.object({
6008
+ boardId: z19.string().max(128),
6009
+ columnId: z19.string().max(128),
5918
6010
  // Les cartes visibles côté écran : une colonne filtrée n'envoie qu'elles.
5919
- cardIds: z18.array(z18.string().max(128)).max(5e3).optional(),
5920
- runner: z18.enum(["claude-code", "codex"]).optional(),
5921
- model: z18.string().max(128).optional(),
5922
- scenarioId: z18.string().max(128).optional(),
5923
- projectId: z18.string().max(128).optional(),
5924
- orgId: z18.string().max(128).nullable().optional()
6011
+ cardIds: z19.array(z19.string().max(128)).max(5e3).optional(),
6012
+ runner: z19.enum(["claude-code", "codex"]).optional(),
6013
+ model: z19.string().max(128).optional(),
6014
+ scenarioId: z19.string().max(128).optional(),
6015
+ projectId: z19.string().max(128).optional(),
6016
+ orgId: z19.string().max(128).nullable().optional()
5925
6017
  })).mutation(async ({ input }) => {
5926
6018
  const { boardId, columnId, ...options } = input;
5927
6019
  return kanbanQueue.addColumn(boardId, columnId, options);
5928
6020
  }),
5929
- remove: protectedProcedure.input(z18.object({ itemId: z18.string().max(128) })).mutation(({ input }) => ({ removed: kanbanQueue.remove(input.itemId) })),
6021
+ remove: protectedProcedure.input(z19.object({ itemId: z19.string().max(128) })).mutation(({ input }) => ({ removed: kanbanQueue.remove(input.itemId) })),
5930
6022
  stopAll: protectedProcedure.mutation(() => {
5931
6023
  kanbanQueue.stopAll();
5932
6024
  return { ok: true };
5933
6025
  }),
5934
- setMaxConcurrent: protectedProcedure.input(z18.object({ max: z18.number().int().min(1).max(20) })).mutation(({ input }) => {
6026
+ setMaxConcurrent: protectedProcedure.input(z19.object({ max: z19.number().int().min(1).max(20) })).mutation(({ input }) => {
5935
6027
  kanbanQueue.setMaxConcurrent(input.max);
5936
6028
  return kanbanQueue.getState();
5937
6029
  }),
@@ -5969,8 +6061,8 @@ import { mkdir as mkdir5, readdir, rm, stat as stat3, writeFile as writeFile4 }
5969
6061
  import { createHash } from "crypto";
5970
6062
  import { tmpdir } from "os";
5971
6063
  import { join as join7 } from "path";
5972
- import { z as z19 } from "zod";
5973
- import { TRPCError as TRPCError16 } from "@trpc/server";
6064
+ import { z as z20 } from "zod";
6065
+ import { TRPCError as TRPCError17 } from "@trpc/server";
5974
6066
  function summarizeCard(card, boardId, columnTitle) {
5975
6067
  return {
5976
6068
  boardId,
@@ -6041,7 +6133,7 @@ async function storeAttachment(id, name, body, dirs = attachmentCacheDirs()) {
6041
6133
  refusals.push(`${dir} (${err instanceof Error ? err.message : String(err)})`);
6042
6134
  }
6043
6135
  }
6044
- throw new TRPCError16({
6136
+ throw new TRPCError17({
6045
6137
  code: "INTERNAL_SERVER_ERROR",
6046
6138
  message: `Impossible d'\xE9crire la pi\xE8ce jointe sur cette machine. Emplacements essay\xE9s : ${refusals.join(" ; ")}. V\xE9rifiez les droits d'\xE9criture, ou l'espace disque.`
6047
6139
  });
@@ -6062,9 +6154,9 @@ var kanbanRouter = router({
6062
6154
  * card graph, so listing them in full would be megabytes to answer "which
6063
6155
  * boards exist?". Use `getBoard` for the cards of one.
6064
6156
  */
6065
- listBoards: protectedProcedure.input(z19.object({
6066
- includeArchived: z19.boolean().optional(),
6067
- organizationId: z19.string().max(128).optional()
6157
+ listBoards: protectedProcedure.input(z20.object({
6158
+ includeArchived: z20.boolean().optional(),
6159
+ organizationId: z20.string().max(128).optional()
6068
6160
  }).optional()).query(async ({ input }) => {
6069
6161
  const { organizationId, boards } = await kanbanStore.list(
6070
6162
  input?.includeArchived ?? false,
@@ -6090,7 +6182,7 @@ var kanbanRouter = router({
6090
6182
  };
6091
6183
  }),
6092
6184
  /** One board: its columns, and the cards in each. */
6093
- getBoard: protectedProcedure.input(z19.object({ boardId: z19.string().max(128) })).query(async ({ input }) => {
6185
+ getBoard: protectedProcedure.input(z20.object({ boardId: z20.string().max(128) })).query(async ({ input }) => {
6094
6186
  const board = await kanbanStore.get(input.boardId);
6095
6187
  if (!board) return { board: null };
6096
6188
  const { links } = await kanbanStore.cardLinks(input.boardId);
@@ -6129,12 +6221,12 @@ var kanbanRouter = router({
6129
6221
  * organization — or one board when `boardId` is given. Archived boards are
6130
6222
  * left out: they are what the team decided to stop looking at.
6131
6223
  */
6132
- searchCards: protectedProcedure.input(z19.object({
6133
- query: z19.string().max(256).optional(),
6134
- createdBy: z19.string().min(1).max(200).optional(),
6135
- boardId: z19.string().max(128).optional(),
6136
- limit: z19.number().int().min(1).max(100).optional(),
6137
- organizationId: z19.string().max(128).optional()
6224
+ searchCards: protectedProcedure.input(z20.object({
6225
+ query: z20.string().max(256).optional(),
6226
+ createdBy: z20.string().min(1).max(200).optional(),
6227
+ boardId: z20.string().max(128).optional(),
6228
+ limit: z20.number().int().min(1).max(100).optional(),
6229
+ organizationId: z20.string().max(128).optional()
6138
6230
  }).refine((i) => !!i.query?.trim() || !!i.createdBy?.trim(), { message: "query or createdBy is required." })).query(async ({ input }) => {
6139
6231
  return kanbanStore.searchCards(input);
6140
6232
  }),
@@ -6142,10 +6234,10 @@ var kanbanRouter = router({
6142
6234
  * Les conversations de support liées à une carte, avec leur fil — ce que
6143
6235
  * le client a écrit à l'équipe, séparé des commentaires de la carte.
6144
6236
  */
6145
- getCardConversations: protectedProcedure.input(z19.object({
6146
- boardId: z19.string().max(128),
6147
- cardId: z19.string().max(128),
6148
- limit: z19.number().int().min(1).max(500).optional()
6237
+ getCardConversations: protectedProcedure.input(z20.object({
6238
+ boardId: z20.string().max(128),
6239
+ cardId: z20.string().max(128),
6240
+ limit: z20.number().int().min(1).max(500).optional()
6149
6241
  })).query(async ({ input }) => {
6150
6242
  const conversations = await kanbanStore.cardConversations(input.boardId, input.cardId);
6151
6243
  const limit = input.limit ?? 100;
@@ -6158,13 +6250,13 @@ var kanbanRouter = router({
6158
6250
  };
6159
6251
  }),
6160
6252
  /** Chercher une conversation chez les fournisseurs de l'organisation (lecture seule côté fournisseur). */
6161
- searchConversations: protectedProcedure.input(z19.object({ boardId: z19.string().max(128), query: z19.string().trim().min(1).max(500) })).query(async ({ input }) => ({ results: await kanbanStore.searchConversations(input.boardId, input.query) })),
6253
+ searchConversations: protectedProcedure.input(z20.object({ boardId: z20.string().max(128), query: z20.string().trim().min(1).max(500) })).query(async ({ input }) => ({ results: await kanbanStore.searchConversations(input.boardId, input.query) })),
6162
6254
  /** Lier une conversation trouvée à une carte. N'écrit rien chez le fournisseur. */
6163
- linkConversation: protectedProcedure.input(z19.object({
6164
- boardId: z19.string().max(128),
6165
- cardId: z19.string().max(128),
6166
- connectionId: z19.string().max(128),
6167
- externalId: z19.string().max(128)
6255
+ linkConversation: protectedProcedure.input(z20.object({
6256
+ boardId: z20.string().max(128),
6257
+ cardId: z20.string().max(128),
6258
+ connectionId: z20.string().max(128),
6259
+ externalId: z20.string().max(128)
6168
6260
  })).mutation(async ({ input }) => ({ conversations: await kanbanStore.linkConversation(input) })),
6169
6261
  /**
6170
6262
  * Le fil de commentaires d'une carte, relu à la demande.
@@ -6175,10 +6267,10 @@ var kanbanRouter = router({
6175
6267
  * qu'un `commentCount`, et rien n'en donnait le texte. Cette route est la
6176
6268
  * relecture, pour une seule carte : c'est le journal qui pèse, pas le reste.
6177
6269
  */
6178
- getCardComments: protectedProcedure.input(z19.object({
6179
- boardId: z19.string().max(128),
6180
- cardId: z19.string().max(128),
6181
- limit: z19.number().int().min(1).max(200).optional()
6270
+ getCardComments: protectedProcedure.input(z20.object({
6271
+ boardId: z20.string().max(128),
6272
+ cardId: z20.string().max(128),
6273
+ limit: z20.number().int().min(1).max(200).optional()
6182
6274
  })).query(async ({ input }) => {
6183
6275
  const history = await kanbanStore.cardHistory(input.boardId, input.cardId);
6184
6276
  const comments = history.filter((e) => e.type === "comment");
@@ -6207,18 +6299,18 @@ var kanbanRouter = router({
6207
6299
  * `getBoard` en donne déjà l'essentiel carte par carte ; cette route sert
6208
6300
  * quand c'est l'arbre lui-même qu'on veut, dates et auteurs compris.
6209
6301
  */
6210
- getCardLinks: protectedProcedure.input(z19.object({ boardId: z19.string().max(128) })).query(async ({ input }) => kanbanStore.cardLinks(input.boardId)),
6302
+ getCardLinks: protectedProcedure.input(z20.object({ boardId: z20.string().max(128) })).query(async ({ input }) => kanbanStore.cardLinks(input.boardId)),
6211
6303
  /**
6212
6304
  * Rattacher une carte à une carte parente, ou l'en détacher.
6213
6305
  *
6214
6306
  * Sans `parentCardId`, le lien est retiré. Le parent peut vivre sur un autre
6215
6307
  * tableau : `parentBoardId` le désigne alors, sinon c'est celui de la carte.
6216
6308
  */
6217
- setCardParent: protectedProcedure.input(z19.object({
6218
- boardId: z19.string().max(128),
6219
- cardId: z19.string().max(128),
6220
- parentCardId: z19.string().max(128).optional(),
6221
- parentBoardId: z19.string().max(128).optional()
6309
+ setCardParent: protectedProcedure.input(z20.object({
6310
+ boardId: z20.string().max(128),
6311
+ cardId: z20.string().max(128),
6312
+ parentCardId: z20.string().max(128).optional(),
6313
+ parentBoardId: z20.string().max(128).optional()
6222
6314
  })).mutation(async ({ input }) => {
6223
6315
  const ok = await kanbanStore.setCardParent(
6224
6316
  input.boardId,
@@ -6226,7 +6318,7 @@ var kanbanRouter = router({
6226
6318
  input.parentCardId ? { boardId: input.parentBoardId ?? input.boardId, cardId: input.parentCardId } : null
6227
6319
  );
6228
6320
  if (!ok) {
6229
- throw new TRPCError16({ code: "BAD_REQUEST", message: "The cloud refused the link (unknown card, or a cycle)." });
6321
+ throw new TRPCError17({ code: "BAD_REQUEST", message: "The cloud refused the link (unknown card, or a cycle)." });
6230
6322
  }
6231
6323
  return { ok: true };
6232
6324
  }),
@@ -6235,48 +6327,48 @@ var kanbanRouter = router({
6235
6327
  * `boardId` est le tableau où on la pose (ou d'où on la retire) ; la carte
6236
6328
  * reste sur son tableau d'origine.
6237
6329
  */
6238
- getCardPlacements: protectedProcedure.input(z19.object({ boardId: z19.string().max(128), cardId: z19.string().max(128) })).query(async ({ input }) => ({ placements: await kanbanStore.cardPlacements(input.boardId, input.cardId) })),
6239
- placeCard: protectedProcedure.input(z19.object({ boardId: z19.string().max(128), cardId: z19.string().max(128), column: z19.string().min(1).max(200) })).mutation(async ({ input }) => {
6330
+ getCardPlacements: protectedProcedure.input(z20.object({ boardId: z20.string().max(128), cardId: z20.string().max(128) })).query(async ({ input }) => ({ placements: await kanbanStore.cardPlacements(input.boardId, input.cardId) })),
6331
+ placeCard: protectedProcedure.input(z20.object({ boardId: z20.string().max(128), cardId: z20.string().max(128), column: z20.string().min(1).max(200) })).mutation(async ({ input }) => {
6240
6332
  const res = await kanbanStore.placeCard(input.boardId, input.cardId, input.column);
6241
6333
  if (!res.ok) {
6242
- throw new TRPCError16({
6334
+ throw new TRPCError17({
6243
6335
  code: "BAD_REQUEST",
6244
6336
  message: res.reason ?? "The cloud refused the placement (unknown card or column, archived card, or already on this board)."
6245
6337
  });
6246
6338
  }
6247
6339
  return { ok: true };
6248
6340
  }),
6249
- unplaceCard: protectedProcedure.input(z19.object({ boardId: z19.string().max(128), cardId: z19.string().max(128) })).mutation(async ({ input }) => {
6341
+ unplaceCard: protectedProcedure.input(z20.object({ boardId: z20.string().max(128), cardId: z20.string().max(128) })).mutation(async ({ input }) => {
6250
6342
  if (!await kanbanStore.unplaceCard(input.boardId, input.cardId)) {
6251
- throw new TRPCError16({ code: "NOT_FOUND", message: "This card is not placed on this board." });
6343
+ throw new TRPCError17({ code: "NOT_FOUND", message: "This card is not placed on this board." });
6252
6344
  }
6253
6345
  return { ok: true };
6254
6346
  }),
6255
- moveCard: protectedProcedure.input(z19.object({
6256
- boardId: z19.string().max(128),
6257
- cardId: z19.string().max(128),
6258
- targetColumn: z19.string().max(256)
6347
+ moveCard: protectedProcedure.input(z20.object({
6348
+ boardId: z20.string().max(128),
6349
+ cardId: z20.string().max(128),
6350
+ targetColumn: z20.string().max(256)
6259
6351
  })).mutation(async ({ input }) => {
6260
6352
  await executeKanbanCommands(input.boardId, input.cardId, [
6261
6353
  { type: "move_card", columnTitle: input.targetColumn }
6262
6354
  ]);
6263
6355
  return { ok: true };
6264
6356
  }),
6265
- addComment: protectedProcedure.input(z19.object({
6266
- boardId: z19.string().max(128),
6267
- cardId: z19.string().max(128),
6268
- comment: z19.string().max(1e5)
6357
+ addComment: protectedProcedure.input(z20.object({
6358
+ boardId: z20.string().max(128),
6359
+ cardId: z20.string().max(128),
6360
+ comment: z20.string().max(1e5)
6269
6361
  })).mutation(async ({ input }) => {
6270
6362
  await executeKanbanCommands(input.boardId, input.cardId, [
6271
6363
  { type: "add_comment", comment: input.comment }
6272
6364
  ]);
6273
6365
  return { ok: true };
6274
6366
  }),
6275
- addCard: protectedProcedure.input(z19.object({
6276
- boardId: z19.string().max(128),
6277
- column: z19.string().max(256),
6278
- title: z19.string().max(512),
6279
- content: z19.string().max(2e4).optional()
6367
+ addCard: protectedProcedure.input(z20.object({
6368
+ boardId: z20.string().max(128),
6369
+ column: z20.string().max(256),
6370
+ title: z20.string().max(512),
6371
+ content: z20.string().max(2e4).optional()
6280
6372
  })).mutation(async ({ input }) => {
6281
6373
  await executeKanbanBoardCommands(input.boardId, [
6282
6374
  { type: "add_card", columnTitle: input.column, cardTitle: input.title, cardContent: input.content }
@@ -6289,7 +6381,7 @@ var kanbanRouter = router({
6289
6381
  * `getBoard` rapatrie le tableau entier pour n'en regarder qu'une ; et il ne
6290
6382
  * porte pas les cartes rangées. Une carte s'adresse par son identifiant.
6291
6383
  */
6292
- getCard: protectedProcedure.input(z19.object({ boardId: z19.string().max(128), cardId: z19.string().max(128) })).query(async ({ input }) => {
6384
+ getCard: protectedProcedure.input(z20.object({ boardId: z20.string().max(128), cardId: z20.string().max(128) })).query(async ({ input }) => {
6293
6385
  const found = await kanbanStore.card(input.boardId, input.cardId);
6294
6386
  if (!found) throw new Error(`Carte ${input.cardId} introuvable sur le tableau ${input.boardId}.`);
6295
6387
  return { ...summarizeCard(found.card, input.boardId, ""), columnId: found.columnId };
@@ -6303,16 +6395,16 @@ var kanbanRouter = router({
6303
6395
  * Un champ absent n'est pas touché ; `null` l'efface. La distinction compte —
6304
6396
  * changer un titre ne doit pas vider une couleur.
6305
6397
  */
6306
- updateCard: protectedProcedure.input(z19.object({
6307
- boardId: z19.string().max(128),
6308
- cardId: z19.string().max(128),
6309
- title: z19.string().min(1).max(512).optional(),
6310
- content: z19.string().max(1e5).optional(),
6311
- priority: z19.number().int().min(1).max(10).nullable().optional(),
6312
- color: z19.string().max(32).nullable().optional(),
6313
- groups: z19.array(z19.string().min(1).max(60)).max(30).optional(),
6314
- deadline: z19.string().regex(/^\d{4}-\d{2}-\d{2}$/).nullable().optional(),
6315
- assignees: z19.array(z19.string().max(128)).max(50).optional()
6398
+ updateCard: protectedProcedure.input(z20.object({
6399
+ boardId: z20.string().max(128),
6400
+ cardId: z20.string().max(128),
6401
+ title: z20.string().min(1).max(512).optional(),
6402
+ content: z20.string().max(1e5).optional(),
6403
+ priority: z20.number().int().min(1).max(10).nullable().optional(),
6404
+ color: z20.string().max(32).nullable().optional(),
6405
+ groups: z20.array(z20.string().min(1).max(60)).max(30).optional(),
6406
+ deadline: z20.string().regex(/^\d{4}-\d{2}-\d{2}$/).nullable().optional(),
6407
+ assignees: z20.array(z20.string().max(128)).max(50).optional()
6316
6408
  })).mutation(async ({ input }) => {
6317
6409
  const { boardId, cardId, content, ...rest } = input;
6318
6410
  const patch = { ...rest };
@@ -6323,10 +6415,10 @@ var kanbanRouter = router({
6323
6415
  return summarizeCard(card, boardId, "");
6324
6416
  }),
6325
6417
  /** Ranger une carte, ou la reprendre. */
6326
- setCardArchived: protectedProcedure.input(z19.object({
6327
- boardId: z19.string().max(128),
6328
- cardId: z19.string().max(128),
6329
- archived: z19.boolean()
6418
+ setCardArchived: protectedProcedure.input(z20.object({
6419
+ boardId: z20.string().max(128),
6420
+ cardId: z20.string().max(128),
6421
+ archived: z20.boolean()
6330
6422
  })).mutation(async ({ input }) => {
6331
6423
  const ok = await kanbanStore.setCardArchived(input.boardId, input.cardId, input.archived);
6332
6424
  if (!ok) throw new Error(`La carte ${input.cardId} n'a pas pu \xEAtre ${input.archived ? "archiv\xE9e" : "reprise"}.`);
@@ -6338,48 +6430,48 @@ var kanbanRouter = router({
6338
6430
  * Sans cette liste, assigner revient à deviner un identifiant — et l'agent
6339
6431
  * n'a aucun moyen de le trouver.
6340
6432
  */
6341
- listMembers: protectedProcedure.input(z19.object({ organizationId: z19.string().max(128).optional() })).query(async ({ input }) => ({ members: await kanbanStore.members(input.organizationId) })),
6433
+ listMembers: protectedProcedure.input(z20.object({ organizationId: z20.string().max(128).optional() })).query(async ({ input }) => ({ members: await kanbanStore.members(input.organizationId) })),
6342
6434
  /**
6343
6435
  * Fetch one card attachment from the cloud and drop it on this machine, so an
6344
6436
  * agent can open it with its own file tools. The bytes never go through the
6345
6437
  * prompt: the card context lists the attachments, this returns a path.
6346
6438
  */
6347
- downloadAttachment: protectedProcedure.input(z19.object({
6348
- attachmentId: z19.string().max(128),
6439
+ downloadAttachment: protectedProcedure.input(z20.object({
6440
+ attachmentId: z20.string().max(128),
6349
6441
  // La pièce jointe appartient à une organisation : la nommer dit sous quel
6350
6442
  // compte la demander.
6351
- orgId: z19.string().max(128).optional(),
6443
+ orgId: z20.string().max(128).optional(),
6352
6444
  // À défaut, le tableau d'où vient la carte suffit : il désigne un compte
6353
6445
  // comme le fait n'importe quel autre appel du kanban. Sans lui, la route
6354
6446
  // retombait sur le compte unique du poste et refusait de servir dès qu'il
6355
6447
  // y en avait plusieurs — alors que l'agent, qui n'a qu'un identifiant de
6356
6448
  // fichier, n'avait aucun moyen de nommer l'organisation.
6357
- boardId: z19.string().max(128).optional()
6449
+ boardId: z20.string().max(128).optional()
6358
6450
  })).mutation(async ({ input }) => {
6359
6451
  const id = input.attachmentId;
6360
6452
  if (!ATTACHMENT_ID_REGEX.test(id)) {
6361
- throw new TRPCError16({ code: "BAD_REQUEST", message: "Invalid attachment id" });
6453
+ throw new TRPCError17({ code: "BAD_REQUEST", message: "Invalid attachment id" });
6362
6454
  }
6363
6455
  const res = await cloudFetch2(`/api/kanban/file/${id}`, {
6364
6456
  timeoutMs: 12e4,
6365
6457
  accountId: await attachmentScope(input)
6366
6458
  });
6367
6459
  if (res.status === 404) {
6368
- throw new TRPCError16({ code: "NOT_FOUND", message: `Attachment ${id} not found` });
6460
+ throw new TRPCError17({ code: "NOT_FOUND", message: `Attachment ${id} not found` });
6369
6461
  }
6370
6462
  if (!res.ok) {
6371
- throw new TRPCError16({
6463
+ throw new TRPCError17({
6372
6464
  code: res.status === 403 ? "FORBIDDEN" : "INTERNAL_SERVER_ERROR",
6373
6465
  message: `Cloud refused the attachment (HTTP ${res.status})`
6374
6466
  });
6375
6467
  }
6376
6468
  const declared = Number(res.headers.get("content-length") ?? 0);
6377
6469
  if (declared > MAX_ATTACHMENT_BYTES) {
6378
- throw new TRPCError16({ code: "PAYLOAD_TOO_LARGE", message: "Attachment too large to download" });
6470
+ throw new TRPCError17({ code: "PAYLOAD_TOO_LARGE", message: "Attachment too large to download" });
6379
6471
  }
6380
6472
  const body = Buffer.from(await res.arrayBuffer());
6381
6473
  if (body.length > MAX_ATTACHMENT_BYTES) {
6382
- throw new TRPCError16({ code: "PAYLOAD_TOO_LARGE", message: "Attachment too large to download" });
6474
+ throw new TRPCError17({ code: "PAYLOAD_TOO_LARGE", message: "Attachment too large to download" });
6383
6475
  }
6384
6476
  const contentType = res.headers.get("content-type") ?? "application/octet-stream";
6385
6477
  const disposition = res.headers.get("content-disposition") ?? "";
@@ -6391,21 +6483,21 @@ var kanbanRouter = router({
6391
6483
  });
6392
6484
 
6393
6485
  // ../server/src/trpc/routers/terminal.ts
6394
- import { z as z20 } from "zod";
6395
- import { TRPCError as TRPCError17 } from "@trpc/server";
6486
+ import { z as z21 } from "zod";
6487
+ import { TRPCError as TRPCError18 } from "@trpc/server";
6396
6488
  var terminalRouter = router({
6397
6489
  /** Create a PTY shell session on the target agent */
6398
- create: protectedProcedure.input(z20.object({
6399
- agentId: z20.string().max(128),
6400
- cwd: z20.string().max(512).optional(),
6490
+ create: protectedProcedure.input(z21.object({
6491
+ agentId: z21.string().max(128),
6492
+ cwd: z21.string().max(512).optional(),
6401
6493
  /** Anchors the terminal when no explicit cwd is given. */
6402
- serviceId: z20.string().max(128).optional(),
6403
- projectId: z20.string().max(128).optional(),
6494
+ serviceId: z21.string().max(128).optional(),
6495
+ projectId: z21.string().max(128).optional(),
6404
6496
  /** L'organisation du projet : un id seul peut en nommer un par organisation. */
6405
- orgId: z20.string().max(128).nullable().optional(),
6406
- cols: z20.number().int().min(1).max(512).optional(),
6407
- rows: z20.number().int().min(1).max(256).optional(),
6408
- title: z20.string().max(128).optional()
6497
+ orgId: z21.string().max(128).nullable().optional(),
6498
+ cols: z21.number().int().min(1).max(512).optional(),
6499
+ rows: z21.number().int().min(1).max(256).optional(),
6500
+ title: z21.string().max(128).optional()
6409
6501
  })).mutation(async ({ input }) => {
6410
6502
  const result = await agentManager.agentMutation(
6411
6503
  input.agentId,
@@ -6426,17 +6518,17 @@ var terminalRouter = router({
6426
6518
  return result;
6427
6519
  }),
6428
6520
  /** Les sessions PTY encore vivantes sur l'agent (onglets à retrouver) */
6429
- list: protectedProcedure.input(z20.object({ agentId: z20.string().max(128) })).query(async ({ input }) => {
6521
+ list: protectedProcedure.input(z21.object({ agentId: z21.string().max(128) })).query(async ({ input }) => {
6430
6522
  return agentManager.agentQuery(
6431
6523
  input.agentId,
6432
6524
  "terminal.list"
6433
6525
  );
6434
6526
  }),
6435
6527
  /** Renommer un onglet */
6436
- rename: protectedProcedure.input(z20.object({
6437
- agentId: z20.string().max(128),
6438
- sessionId: z20.string().max(128),
6439
- title: z20.string().max(128)
6528
+ rename: protectedProcedure.input(z21.object({
6529
+ agentId: z21.string().max(128),
6530
+ sessionId: z21.string().max(128),
6531
+ title: z21.string().max(128)
6440
6532
  })).mutation(async ({ input }) => {
6441
6533
  await agentManager.agentMutation(
6442
6534
  input.agentId,
@@ -6446,10 +6538,10 @@ var terminalRouter = router({
6446
6538
  return { ok: true };
6447
6539
  }),
6448
6540
  /** Send keystrokes / data to a PTY session */
6449
- write: protectedProcedure.input(z20.object({
6450
- agentId: z20.string().max(128),
6451
- sessionId: z20.string().max(128),
6452
- data: z20.string().max(65536)
6541
+ write: protectedProcedure.input(z21.object({
6542
+ agentId: z21.string().max(128),
6543
+ sessionId: z21.string().max(128),
6544
+ data: z21.string().max(65536)
6453
6545
  })).mutation(async ({ input }) => {
6454
6546
  await agentManager.agentMutation(
6455
6547
  input.agentId,
@@ -6459,11 +6551,11 @@ var terminalRouter = router({
6459
6551
  return { ok: true };
6460
6552
  }),
6461
6553
  /** Resize the PTY */
6462
- resize: protectedProcedure.input(z20.object({
6463
- agentId: z20.string().max(128),
6464
- sessionId: z20.string().max(128),
6465
- cols: z20.number().int().min(1).max(512),
6466
- rows: z20.number().int().min(1).max(256)
6554
+ resize: protectedProcedure.input(z21.object({
6555
+ agentId: z21.string().max(128),
6556
+ sessionId: z21.string().max(128),
6557
+ cols: z21.number().int().min(1).max(512),
6558
+ rows: z21.number().int().min(1).max(256)
6467
6559
  })).mutation(async ({ input }) => {
6468
6560
  await agentManager.agentMutation(
6469
6561
  input.agentId,
@@ -6473,9 +6565,9 @@ var terminalRouter = router({
6473
6565
  return { ok: true };
6474
6566
  }),
6475
6567
  /** Destroy a PTY session */
6476
- destroy: protectedProcedure.input(z20.object({
6477
- agentId: z20.string().max(128),
6478
- sessionId: z20.string().max(128)
6568
+ destroy: protectedProcedure.input(z21.object({
6569
+ agentId: z21.string().max(128),
6570
+ sessionId: z21.string().max(128)
6479
6571
  })).mutation(async ({ input }) => {
6480
6572
  await agentManager.agentMutation(
6481
6573
  input.agentId,
@@ -6485,11 +6577,11 @@ var terminalRouter = router({
6485
6577
  return { ok: true };
6486
6578
  }),
6487
6579
  /** Stream PTY output — proxied via AgentWSBridge dynamic subscription */
6488
- onData: protectedProcedure.input(z20.object({
6489
- agentId: z20.string().max(128),
6490
- sessionId: z20.string().max(128),
6580
+ onData: protectedProcedure.input(z21.object({
6581
+ agentId: z21.string().max(128),
6582
+ sessionId: z21.string().max(128),
6491
6583
  /** Rejouer l'historique de la session avant le flux temps réel. */
6492
- replay: z20.boolean().optional()
6584
+ replay: z21.boolean().optional()
6493
6585
  })).subscription(async function* ({ input }) {
6494
6586
  const queue = [];
6495
6587
  let resolve4 = null;
@@ -6516,7 +6608,7 @@ var terminalRouter = router({
6516
6608
  }
6517
6609
  );
6518
6610
  } catch (err) {
6519
- throw new TRPCError17({
6611
+ throw new TRPCError18({
6520
6612
  code: "BAD_REQUEST",
6521
6613
  message: `Cannot subscribe to terminal: ${err.message}`
6522
6614
  });
@@ -6538,11 +6630,11 @@ var terminalRouter = router({
6538
6630
  });
6539
6631
 
6540
6632
  // ../server/src/trpc/routers/utility.ts
6541
- import { z as z21 } from "zod";
6633
+ import { z as z22 } from "zod";
6542
6634
  var MAX_WAIT_MS = 5 * 60 * 1e3;
6543
6635
  var utilityRouter = router({
6544
- wait: protectedProcedure.input(z21.object({
6545
- ms: z21.number().int().min(0).max(MAX_WAIT_MS)
6636
+ wait: protectedProcedure.input(z22.object({
6637
+ ms: z22.number().int().min(0).max(MAX_WAIT_MS)
6546
6638
  })).mutation(async ({ input }) => {
6547
6639
  await new Promise((resolve4) => setTimeout(resolve4, input.ms));
6548
6640
  return { waited: input.ms };
@@ -6550,15 +6642,15 @@ var utilityRouter = router({
6550
6642
  });
6551
6643
 
6552
6644
  // ../server/src/trpc/routers/wiki.ts
6553
- import { z as z22 } from "zod";
6554
- import { TRPCError as TRPCError18 } from "@trpc/server";
6645
+ import { z as z23 } from "zod";
6646
+ import { TRPCError as TRPCError19 } from "@trpc/server";
6555
6647
  import { readFile as readFile3, readdir as readdir2, stat as stat4, realpath, writeFile as writeFile5, mkdir as mkdir6, rename, rm as rm2 } from "fs/promises";
6556
- import { resolve as resolvePath, join as join8, relative, sep, dirname as dirname4 } from "path";
6557
- var SCOPE_SCHEMA = z22.union([
6558
- z22.literal("global"),
6559
- z22.string().regex(/^service:[A-Za-z0-9_-]{1,128}$/, "Invalid service scope")
6648
+ import { resolve as resolvePath, join as join8, relative as relative2, sep, dirname as dirname4 } from "path";
6649
+ var SCOPE_SCHEMA = z23.union([
6650
+ z23.literal("global"),
6651
+ z23.string().regex(/^service:[A-Za-z0-9_-]{1,128}$/, "Invalid service scope")
6560
6652
  ]);
6561
- var REL_PATH_SCHEMA = z22.string().min(1).max(512).regex(/^[A-Za-z0-9_./-]+$/).refine((p) => !p.includes("..") && !p.startsWith("/"), {
6653
+ var REL_PATH_SCHEMA = z23.string().min(1).max(512).regex(/^[A-Za-z0-9_./-]+$/).refine((p) => !p.includes("..") && !p.startsWith("/"), {
6562
6654
  message: "Path must be a relative path without traversal"
6563
6655
  });
6564
6656
  var MAX_FILES = 500;
@@ -6578,36 +6670,36 @@ var IGNORED_DIRS = /* @__PURE__ */ new Set([
6578
6670
  "target",
6579
6671
  "out"
6580
6672
  ]);
6581
- var DocsEntrySchema = z22.lazy(() => z22.union([
6582
- z22.object({ type: z22.literal("file"), name: z22.string(), path: z22.string() }),
6583
- z22.object({ type: z22.literal("dir"), name: z22.string(), path: z22.string(), children: z22.array(DocsEntrySchema) })
6673
+ var DocsEntrySchema = z23.lazy(() => z23.union([
6674
+ z23.object({ type: z23.literal("file"), name: z23.string(), path: z23.string() }),
6675
+ z23.object({ type: z23.literal("dir"), name: z23.string(), path: z23.string(), children: z23.array(DocsEntrySchema) })
6584
6676
  ]));
6585
6677
  async function resolveScope(scope) {
6586
6678
  if (scope === "global") {
6587
6679
  const settings = await settingsManager.getSettings();
6588
6680
  const sub = (settings.globalDocsPath?.trim() || "wiki").replace(/^[\\/]+|[\\/]+$/g, "");
6589
6681
  if (sub.includes("..") || sub.includes("\0")) {
6590
- throw new TRPCError18({ code: "BAD_REQUEST", message: "Sous-chemin invalide" });
6682
+ throw new TRPCError19({ code: "BAD_REQUEST", message: "Sous-chemin invalide" });
6591
6683
  }
6592
6684
  const dataDirAbs = resolvePath(env.DATA_DIR);
6593
6685
  await mkdir6(dataDirAbs, { recursive: true });
6594
6686
  const base = dirname4(await realpath(dataDirAbs));
6595
6687
  const target = resolvePath(base, sub);
6596
6688
  if (target !== base && !(target + sep).startsWith(base + sep)) {
6597
- throw new TRPCError18({ code: "FORBIDDEN", message: "Hors du dossier de donn\xE9es du serveur" });
6689
+ throw new TRPCError19({ code: "FORBIDDEN", message: "Hors du dossier de donn\xE9es du serveur" });
6598
6690
  }
6599
6691
  await mkdir6(target, { recursive: true });
6600
6692
  const root = await realpath(target);
6601
6693
  if (root !== base && !(root + sep).startsWith(base + sep)) {
6602
- throw new TRPCError18({ code: "FORBIDDEN", message: "Le dossier wiki r\xE9sout hors du dossier de donn\xE9es" });
6694
+ throw new TRPCError19({ code: "FORBIDDEN", message: "Le dossier wiki r\xE9sout hors du dossier de donn\xE9es" });
6603
6695
  }
6604
6696
  return { mode: "local", root };
6605
6697
  }
6606
6698
  const serviceId = scope.slice("service:".length);
6607
6699
  const service = await serviceStore.get(serviceId);
6608
- if (!service) throw new TRPCError18({ code: "NOT_FOUND", message: "Service introuvable" });
6700
+ if (!service) throw new TRPCError19({ code: "NOT_FOUND", message: "Service introuvable" });
6609
6701
  const agentId = await resolveEffectiveAgentId(service);
6610
- if (!agentId) throw new TRPCError18({ code: "BAD_REQUEST", message: "Aucun agent configur\xE9 pour ce service" });
6702
+ if (!agentId) throw new TRPCError19({ code: "BAD_REQUEST", message: "Aucun agent configur\xE9 pour ce service" });
6611
6703
  const cwd = await resolveWorkspaceCwd({ serviceId, override: service.docsPath?.trim() || void 0 });
6612
6704
  return { mode: "agent", agentId, cwd };
6613
6705
  }
@@ -6624,7 +6716,7 @@ async function walkLocal(root, dir, depth, counter) {
6624
6716
  if (counter.n >= MAX_FILES) break;
6625
6717
  if (e.name.startsWith(".") && e.name !== ".") continue;
6626
6718
  const abs = join8(dir, e.name);
6627
- const rel = relative(root, abs).split(sep).join("/");
6719
+ const rel = relative2(root, abs).split(sep).join("/");
6628
6720
  if (e.isDirectory()) {
6629
6721
  if (IGNORED_DIRS.has(e.name)) continue;
6630
6722
  const children = await walkLocal(root, abs, depth + 1, counter);
@@ -6642,7 +6734,7 @@ async function walkLocal(root, dir, depth, counter) {
6642
6734
  }
6643
6735
  async function resolveSafeLocal(root, relPath, requireExist) {
6644
6736
  if (relPath.includes("..") || relPath.startsWith("/")) {
6645
- throw new TRPCError18({ code: "BAD_REQUEST", message: "Chemin invalide" });
6737
+ throw new TRPCError19({ code: "BAD_REQUEST", message: "Chemin invalide" });
6646
6738
  }
6647
6739
  const target = resolvePath(root, relPath);
6648
6740
  if (requireExist) {
@@ -6650,10 +6742,10 @@ async function resolveSafeLocal(root, relPath, requireExist) {
6650
6742
  try {
6651
6743
  real = await realpath(target);
6652
6744
  } catch {
6653
- throw new TRPCError18({ code: "NOT_FOUND", message: "Chemin introuvable" });
6745
+ throw new TRPCError19({ code: "NOT_FOUND", message: "Chemin introuvable" });
6654
6746
  }
6655
6747
  if (real !== root && !(real + sep).startsWith(root + sep)) {
6656
- throw new TRPCError18({ code: "FORBIDDEN", message: "Hors du dossier autoris\xE9" });
6748
+ throw new TRPCError19({ code: "FORBIDDEN", message: "Hors du dossier autoris\xE9" });
6657
6749
  }
6658
6750
  return real;
6659
6751
  }
@@ -6665,12 +6757,12 @@ async function resolveSafeLocal(root, relPath, requireExist) {
6665
6757
  realParent = parent;
6666
6758
  }
6667
6759
  if (realParent !== root && !(realParent + sep).startsWith(root + sep)) {
6668
- throw new TRPCError18({ code: "FORBIDDEN", message: "Hors du dossier autoris\xE9" });
6760
+ throw new TRPCError19({ code: "FORBIDDEN", message: "Hors du dossier autoris\xE9" });
6669
6761
  }
6670
6762
  return resolvePath(realParent, target.slice(parent.length).replace(/^[\\/]+/, ""));
6671
6763
  }
6672
6764
  var wikiRouter = router({
6673
- list: protectedProcedure.input(z22.object({ scope: SCOPE_SCHEMA })).output(z22.object({ root: z22.string(), entries: z22.array(DocsEntrySchema), truncated: z22.boolean() })).query(async ({ input }) => {
6765
+ list: protectedProcedure.input(z23.object({ scope: SCOPE_SCHEMA })).output(z23.object({ root: z23.string(), entries: z23.array(DocsEntrySchema), truncated: z23.boolean() })).query(async ({ input }) => {
6674
6766
  const target = await resolveScope(input.scope);
6675
6767
  if (target.mode === "agent") {
6676
6768
  return agentManager.agentQuery(target.agentId, "wiki.listRepoMarkdown", { cwd: target.cwd });
@@ -6679,9 +6771,9 @@ var wikiRouter = router({
6679
6771
  const entries2 = await walkLocal(target.root, target.root, 0, counter);
6680
6772
  return { root: target.root, entries: entries2, truncated: counter.n >= MAX_FILES };
6681
6773
  }),
6682
- read: protectedProcedure.input(z22.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA })).output(z22.object({ path: z22.string(), content: z22.string() })).query(async ({ input }) => {
6774
+ read: protectedProcedure.input(z23.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA })).output(z23.object({ path: z23.string(), content: z23.string() })).query(async ({ input }) => {
6683
6775
  if (!/\.(md|markdown)$/i.test(input.path)) {
6684
- throw new TRPCError18({ code: "BAD_REQUEST", message: "Seuls les .md/.markdown sont autoris\xE9s" });
6776
+ throw new TRPCError19({ code: "BAD_REQUEST", message: "Seuls les .md/.markdown sont autoris\xE9s" });
6685
6777
  }
6686
6778
  const target = await resolveScope(input.scope);
6687
6779
  if (target.mode === "agent") {
@@ -6689,14 +6781,14 @@ var wikiRouter = router({
6689
6781
  }
6690
6782
  const file = await resolveSafeLocal(target.root, input.path, true);
6691
6783
  const s = await stat4(file);
6692
- if (!s.isFile()) throw new TRPCError18({ code: "BAD_REQUEST", message: "Pas un fichier" });
6693
- if (s.size > MAX_FILE_BYTES) throw new TRPCError18({ code: "PAYLOAD_TOO_LARGE", message: "Fichier trop volumineux" });
6784
+ if (!s.isFile()) throw new TRPCError19({ code: "BAD_REQUEST", message: "Pas un fichier" });
6785
+ if (s.size > MAX_FILE_BYTES) throw new TRPCError19({ code: "PAYLOAD_TOO_LARGE", message: "Fichier trop volumineux" });
6694
6786
  const content = await readFile3(file, "utf-8");
6695
6787
  return { path: input.path, content };
6696
6788
  }),
6697
- write: protectedProcedure.input(z22.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA, content: z22.string().max(5e6) })).mutation(async ({ input }) => {
6789
+ write: protectedProcedure.input(z23.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA, content: z23.string().max(5e6) })).mutation(async ({ input }) => {
6698
6790
  if (!/\.(md|markdown)$/i.test(input.path)) {
6699
- throw new TRPCError18({ code: "BAD_REQUEST", message: "Seuls les .md/.markdown sont autoris\xE9s" });
6791
+ throw new TRPCError19({ code: "BAD_REQUEST", message: "Seuls les .md/.markdown sont autoris\xE9s" });
6700
6792
  }
6701
6793
  const target = await resolveScope(input.scope);
6702
6794
  if (target.mode === "agent") {
@@ -6707,9 +6799,9 @@ var wikiRouter = router({
6707
6799
  await writeFile5(file, input.content, "utf-8");
6708
6800
  return { path: input.path, ok: true };
6709
6801
  }),
6710
- createFile: protectedProcedure.input(z22.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA })).mutation(async ({ input }) => {
6802
+ createFile: protectedProcedure.input(z23.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA })).mutation(async ({ input }) => {
6711
6803
  if (!/\.(md|markdown)$/i.test(input.path)) {
6712
- throw new TRPCError18({ code: "BAD_REQUEST", message: "Seuls les .md/.markdown sont autoris\xE9s" });
6804
+ throw new TRPCError19({ code: "BAD_REQUEST", message: "Seuls les .md/.markdown sont autoris\xE9s" });
6713
6805
  }
6714
6806
  const target = await resolveScope(input.scope);
6715
6807
  if (target.mode === "agent") {
@@ -6718,15 +6810,15 @@ var wikiRouter = router({
6718
6810
  const file = await resolveSafeLocal(target.root, input.path, false);
6719
6811
  try {
6720
6812
  await stat4(file);
6721
- throw new TRPCError18({ code: "CONFLICT", message: "Fichier d\xE9j\xE0 existant" });
6813
+ throw new TRPCError19({ code: "CONFLICT", message: "Fichier d\xE9j\xE0 existant" });
6722
6814
  } catch (err) {
6723
- if (err instanceof TRPCError18) throw err;
6815
+ if (err instanceof TRPCError19) throw err;
6724
6816
  }
6725
6817
  await mkdir6(dirname4(file), { recursive: true });
6726
6818
  await writeFile5(file, "", "utf-8");
6727
6819
  return { path: input.path, ok: true };
6728
6820
  }),
6729
- createDir: protectedProcedure.input(z22.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA })).mutation(async ({ input }) => {
6821
+ createDir: protectedProcedure.input(z23.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA })).mutation(async ({ input }) => {
6730
6822
  const target = await resolveScope(input.scope);
6731
6823
  if (target.mode === "agent") {
6732
6824
  return agentManager.agentMutation(target.agentId, "wiki.createDir", { cwd: target.cwd, path: input.path });
@@ -6735,7 +6827,7 @@ var wikiRouter = router({
6735
6827
  await mkdir6(dir, { recursive: true });
6736
6828
  return { path: input.path, ok: true };
6737
6829
  }),
6738
- rename: protectedProcedure.input(z22.object({ scope: SCOPE_SCHEMA, fromPath: REL_PATH_SCHEMA, toPath: REL_PATH_SCHEMA })).mutation(async ({ input }) => {
6830
+ rename: protectedProcedure.input(z23.object({ scope: SCOPE_SCHEMA, fromPath: REL_PATH_SCHEMA, toPath: REL_PATH_SCHEMA })).mutation(async ({ input }) => {
6739
6831
  const target = await resolveScope(input.scope);
6740
6832
  if (target.mode === "agent") {
6741
6833
  return agentManager.agentMutation(target.agentId, "wiki.renamePath", { cwd: target.cwd, fromPath: input.fromPath, toPath: input.toPath });
@@ -6744,34 +6836,34 @@ var wikiRouter = router({
6744
6836
  const to = await resolveSafeLocal(target.root, input.toPath, false);
6745
6837
  try {
6746
6838
  await stat4(to);
6747
- throw new TRPCError18({ code: "CONFLICT", message: "La cible existe d\xE9j\xE0" });
6839
+ throw new TRPCError19({ code: "CONFLICT", message: "La cible existe d\xE9j\xE0" });
6748
6840
  } catch (err) {
6749
- if (err instanceof TRPCError18) throw err;
6841
+ if (err instanceof TRPCError19) throw err;
6750
6842
  }
6751
6843
  await mkdir6(dirname4(to), { recursive: true });
6752
6844
  await rename(from, to);
6753
6845
  return { fromPath: input.fromPath, toPath: input.toPath, ok: true };
6754
6846
  }),
6755
- ensureRoot: protectedProcedure.input(z22.object({ scope: SCOPE_SCHEMA })).mutation(async ({ input }) => {
6847
+ ensureRoot: protectedProcedure.input(z23.object({ scope: SCOPE_SCHEMA })).mutation(async ({ input }) => {
6756
6848
  if (input.scope === "global") {
6757
6849
  await resolveScope("global");
6758
6850
  return { ok: true };
6759
6851
  }
6760
6852
  const serviceId = input.scope.slice("service:".length);
6761
6853
  const service = await serviceStore.get(serviceId);
6762
- if (!service) throw new TRPCError18({ code: "NOT_FOUND", message: "Service introuvable" });
6854
+ if (!service) throw new TRPCError19({ code: "NOT_FOUND", message: "Service introuvable" });
6763
6855
  const agentId = await resolveEffectiveAgentId(service);
6764
- if (!agentId) throw new TRPCError18({ code: "BAD_REQUEST", message: "Aucun agent configur\xE9" });
6856
+ if (!agentId) throw new TRPCError19({ code: "BAD_REQUEST", message: "Aucun agent configur\xE9" });
6765
6857
  const cwd = await resolveWorkspaceCwd({ serviceId, override: service.docsPath?.trim() || void 0 });
6766
6858
  return agentManager.agentMutation(agentId, "wiki.ensureRoot", { cwd });
6767
6859
  }),
6768
- delete: protectedProcedure.input(z22.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA })).mutation(async ({ input }) => {
6860
+ delete: protectedProcedure.input(z23.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA })).mutation(async ({ input }) => {
6769
6861
  const target = await resolveScope(input.scope);
6770
6862
  if (target.mode === "agent") {
6771
6863
  return agentManager.agentMutation(target.agentId, "wiki.deletePath", { cwd: target.cwd, path: input.path });
6772
6864
  }
6773
6865
  const fp = await resolveSafeLocal(target.root, input.path, true);
6774
- if (fp === target.root) throw new TRPCError18({ code: "FORBIDDEN", message: "Impossible de supprimer la racine" });
6866
+ if (fp === target.root) throw new TRPCError19({ code: "FORBIDDEN", message: "Impossible de supprimer la racine" });
6775
6867
  await rm2(fp, { recursive: true, force: true });
6776
6868
  return { path: input.path, ok: true };
6777
6869
  })
@@ -6791,8 +6883,8 @@ var configRouter = router({
6791
6883
  });
6792
6884
 
6793
6885
  // ../server/src/trpc/routers/cloud-sync.ts
6794
- import { z as z23 } from "zod";
6795
- import { TRPCError as TRPCError19 } from "@trpc/server";
6886
+ import { z as z24 } from "zod";
6887
+ import { TRPCError as TRPCError20 } from "@trpc/server";
6796
6888
 
6797
6889
  // ../server/src/services/org-sync-scope.ts
6798
6890
  import { access } from "fs/promises";
@@ -6878,7 +6970,7 @@ import { mkdir as mkdir7, rm as rm3 } from "fs/promises";
6878
6970
  import * as Y2 from "yjs";
6879
6971
 
6880
6972
  // ../server/src/services/sync-doc-cache.ts
6881
- import { readFileSync, renameSync, rmSync, writeFileSync, mkdirSync } from "fs";
6973
+ import { readFileSync as readFileSync2, renameSync, rmSync, writeFileSync, mkdirSync } from "fs";
6882
6974
  import { readFile as readFile4 } from "fs/promises";
6883
6975
  import { dirname as dirname5, join as join10 } from "path";
6884
6976
  import { randomUUID as randomUUID6 } from "crypto";
@@ -6909,7 +7001,7 @@ function writeSyncDocSync(orgId, state) {
6909
7001
  const path = cachePath(orgId);
6910
7002
  let existing = null;
6911
7003
  try {
6912
- existing = new Uint8Array(readFileSync(path));
7004
+ existing = new Uint8Array(readFileSync2(path));
6913
7005
  } catch {
6914
7006
  }
6915
7007
  mkdirSync(dirname5(path), { recursive: true });
@@ -7098,7 +7190,7 @@ var OrgSyncConnection = class {
7098
7190
  }
7099
7191
  track(work) {
7100
7192
  this.applying.add(work);
7101
- void work.finally(() => this.applying.delete(work));
7193
+ void work.catch((err) => console.error("[cloud-sync] \xE9chec en appliquant un changement distant :", err)).finally(() => this.applying.delete(work));
7102
7194
  }
7103
7195
  async settleApplying() {
7104
7196
  while (this.applying.size > 0) await Promise.allSettled(this.applying);
@@ -8073,7 +8165,7 @@ async function assertOrgReadable(orgId) {
8073
8165
  await assertOrgVaultReadable(orgId);
8074
8166
  } catch (err) {
8075
8167
  if (err instanceof OrgVaultUnreadableError) {
8076
- throw new TRPCError19({ code: "FORBIDDEN", message: err.message });
8168
+ throw new TRPCError20({ code: "FORBIDDEN", message: err.message });
8077
8169
  }
8078
8170
  throw err;
8079
8171
  }
@@ -8083,10 +8175,10 @@ async function assertOrgKey(orgId) {
8083
8175
  await reconcileOrgCanary(orgId);
8084
8176
  } catch (err) {
8085
8177
  if (err instanceof OrgKeyMismatchError) {
8086
- throw new TRPCError19({ code: "FORBIDDEN", message: err.message });
8178
+ throw new TRPCError20({ code: "FORBIDDEN", message: err.message });
8087
8179
  }
8088
8180
  if (err instanceof CanaryUnavailableError) {
8089
- throw new TRPCError19({ code: "PRECONDITION_FAILED", message: err.message });
8181
+ throw new TRPCError20({ code: "PRECONDITION_FAILED", message: err.message });
8090
8182
  }
8091
8183
  throw err;
8092
8184
  }
@@ -8103,14 +8195,14 @@ var cloudSyncRouter = router({
8103
8195
  * "open this project" is the whole gesture.
8104
8196
  */
8105
8197
  trackProject: protectedProcedure.input(
8106
- z23.object({
8107
- orgId: z23.string().min(1).max(128),
8108
- cloudUrl: z23.string().url().max(2048),
8109
- projectId: z23.string().min(1).max(128),
8198
+ z24.object({
8199
+ orgId: z24.string().min(1).max(128),
8200
+ cloudUrl: z24.string().url().max(2048),
8201
+ projectId: z24.string().min(1).max(128),
8110
8202
  // Le compte sous lequel cette organisation a été listée. Tamponné avec
8111
8203
  // elle : c'est ce qui permettra à tout appel ultérieur de retrouver le
8112
8204
  // bon token sans qu'on ait à le lui redire.
8113
- accountId: z23.string().max(64).optional()
8205
+ accountId: z24.string().max(64).optional()
8114
8206
  })
8115
8207
  ).mutation(async ({ input }) => {
8116
8208
  await assertOrgReadable(input.orgId);
@@ -8132,7 +8224,7 @@ var cloudSyncRouter = router({
8132
8224
  return { pulled, state: syncState(input.orgId) };
8133
8225
  } catch (err) {
8134
8226
  if (err instanceof ProjectHeldElsewhereError) {
8135
- throw new TRPCError19({ code: "CONFLICT", message: err.code, cause: err });
8227
+ throw new TRPCError20({ code: "CONFLICT", message: err.code, cause: err });
8136
8228
  }
8137
8229
  throw err;
8138
8230
  }
@@ -8151,22 +8243,22 @@ var cloudSyncRouter = router({
8151
8243
  * fusionné.
8152
8244
  */
8153
8245
  publishProject: protectedProcedure.input(
8154
- z23.object({
8155
- orgId: z23.string().min(1).max(128),
8156
- cloudUrl: z23.string().url().max(2048),
8157
- projectId: z23.string().min(1).max(128),
8246
+ z24.object({
8247
+ orgId: z24.string().min(1).max(128),
8248
+ cloudUrl: z24.string().url().max(2048),
8249
+ projectId: z24.string().min(1).max(128),
8158
8250
  // Le compte sous lequel cette organisation a été listée. Tamponné avec
8159
8251
  // elle : c'est ce qui permettra à tout appel ultérieur de retrouver le
8160
8252
  // bon token sans qu'on ait à le lui redire.
8161
- accountId: z23.string().max(64).optional()
8253
+ accountId: z24.string().max(64).optional()
8162
8254
  })
8163
8255
  ).mutation(async ({ input }) => {
8164
8256
  const local = await projectStore.get({ id: input.projectId, orgId: null });
8165
8257
  if (!local) {
8166
- throw new TRPCError19({ code: "NOT_FOUND", message: "PROJECT_NOT_LOCAL" });
8258
+ throw new TRPCError20({ code: "NOT_FOUND", message: "PROJECT_NOT_LOCAL" });
8167
8259
  }
8168
8260
  if (await projectStore.get({ id: input.projectId, orgId: input.orgId })) {
8169
- throw new TRPCError19({ code: "CONFLICT", message: "PROJECT_ALREADY_IN_ORG" });
8261
+ throw new TRPCError20({ code: "CONFLICT", message: "PROJECT_ALREADY_IN_ORG" });
8170
8262
  }
8171
8263
  await assertOrgReadable(input.orgId);
8172
8264
  const connected = cloudSyncBridge.states().some((s) => s.orgId === input.orgId);
@@ -8191,7 +8283,7 @@ var cloudSyncRouter = router({
8191
8283
  await cloudSyncBridge.followProject(input.orgId, input.projectId);
8192
8284
  } catch (err) {
8193
8285
  if (err instanceof ProjectHeldElsewhereError) {
8194
- throw new TRPCError19({ code: "CONFLICT", message: err.code, cause: err });
8286
+ throw new TRPCError20({ code: "CONFLICT", message: err.code, cause: err });
8195
8287
  }
8196
8288
  throw err;
8197
8289
  }
@@ -8205,16 +8297,16 @@ var cloudSyncRouter = router({
8205
8297
  * publié. Le cloud, lui, ne peut pas répondre — il n'a que du chiffré sous
8206
8298
  * les yeux — donc le canari est rapatrié et jugé ici.
8207
8299
  */
8208
- checkOrgKey: protectedProcedure.input(z23.object({
8209
- orgId: z23.string().min(1).max(128),
8210
- keyHex: z23.string().length(64).regex(/^[0-9a-f]+$/i)
8300
+ checkOrgKey: protectedProcedure.input(z24.object({
8301
+ orgId: z24.string().min(1).max(128),
8302
+ keyHex: z24.string().length(64).regex(/^[0-9a-f]+$/i)
8211
8303
  })).query(async ({ input }) => {
8212
8304
  const res = await cloudFetch2(
8213
8305
  `/api/auth/organization/canary?organizationId=${encodeURIComponent(input.orgId)}`,
8214
8306
  { method: "GET", accountId: await accountForOrgScope(input.orgId) }
8215
8307
  );
8216
8308
  if (!res.ok) {
8217
- throw new TRPCError19({ code: "BAD_GATEWAY", message: await cloudMessage(res) || `CANARY_READ_FAILED (${res.status})` });
8309
+ throw new TRPCError20({ code: "BAD_GATEWAY", message: await cloudMessage(res) || `CANARY_READ_FAILED (${res.status})` });
8218
8310
  }
8219
8311
  const { canary } = await res.json();
8220
8312
  if (typeof canary !== "string") return { matches: false, published: false };
@@ -8229,7 +8321,7 @@ var cloudSyncRouter = router({
8229
8321
  * que l'interface puisse proposer ni l'adoption ni la remise à zéro — le seul
8230
8322
  * chemin qui la répare. Rien n'est écrit ici, ni sur le disque ni sur le cloud.
8231
8323
  */
8232
- orgKeyStatus: protectedProcedure.input(z23.object({ orgId: z23.string().min(1).max(128) })).query(async ({ input }) => {
8324
+ orgKeyStatus: protectedProcedure.input(z24.object({ orgId: z24.string().min(1).max(128) })).query(async ({ input }) => {
8233
8325
  const key = getEncryptionKey(input.orgId);
8234
8326
  if (!key) return { status: "unknown" };
8235
8327
  const res = await cloudFetch2(
@@ -8252,10 +8344,10 @@ var cloudSyncRouter = router({
8252
8344
  * Bornée au coffre de l'organisation et à ceux de ses projets : les autres
8253
8345
  * organisations et la machine gardent leur clé.
8254
8346
  */
8255
- adoptOrgKey: protectedProcedure.input(z23.object({
8256
- orgId: z23.string().min(1).max(128),
8257
- keyHex: z23.string().length(64).regex(/^[0-9a-f]+$/i),
8258
- masterPassword: z23.string().min(1).max(1024)
8347
+ adoptOrgKey: protectedProcedure.input(z24.object({
8348
+ orgId: z24.string().min(1).max(128),
8349
+ keyHex: z24.string().length(64).regex(/^[0-9a-f]+$/i),
8350
+ masterPassword: z24.string().min(1).max(1024)
8259
8351
  })).mutation(async ({ input }) => {
8260
8352
  const report = await adoptOrgKey(
8261
8353
  input.orgId,
@@ -8285,14 +8377,14 @@ var cloudSyncRouter = router({
8285
8377
  * Ce qui a déjà été synchronisé sous l'ancienne clé de référence reste
8286
8378
  * illisible : aucune clé d'ici ne l'ouvre. L'interface le dit avant.
8287
8379
  */
8288
- resetOrgKey: protectedProcedure.input(z23.object({
8289
- orgId: z23.string().min(1).max(128),
8290
- masterPassword: z23.string().min(1).max(1024)
8380
+ resetOrgKey: protectedProcedure.input(z24.object({
8381
+ orgId: z24.string().min(1).max(128),
8382
+ masterPassword: z24.string().min(1).max(1024)
8291
8383
  })).mutation(async ({ input }) => {
8292
8384
  const { keyHex } = await resetOrgKeyToFresh(input.orgId, input.masterPassword, /* @__PURE__ */ new Date());
8293
8385
  const canary = await readVerifyFile(orgVaultRoot(input.orgId));
8294
8386
  if (!canary) {
8295
- throw new TRPCError19({
8387
+ throw new TRPCError20({
8296
8388
  code: "PRECONDITION_FAILED",
8297
8389
  message: "Le coffre de cette organisation n'a pas re\xE7u sa cl\xE9."
8298
8390
  });
@@ -8304,7 +8396,7 @@ var cloudSyncRouter = router({
8304
8396
  });
8305
8397
  if (!res.ok) {
8306
8398
  const detail = await cloudMessage(res);
8307
- throw new TRPCError19({
8399
+ throw new TRPCError20({
8308
8400
  code: res.status === 403 ? "FORBIDDEN" : "BAD_GATEWAY",
8309
8401
  message: detail || `ORG_KEY_RESET_FAILED (${res.status})`
8310
8402
  });
@@ -8320,9 +8412,9 @@ var cloudSyncRouter = router({
8320
8412
  * every other member and for this one on another machine.
8321
8413
  */
8322
8414
  untrackProject: protectedProcedure.input(
8323
- z23.object({
8324
- orgId: z23.string().min(1).max(128),
8325
- projectId: z23.string().min(1).max(128)
8415
+ z24.object({
8416
+ orgId: z24.string().min(1).max(128),
8417
+ projectId: z24.string().min(1).max(128)
8326
8418
  })
8327
8419
  ).mutation(async ({ input }) => {
8328
8420
  await cloudSyncBridge.unfollowProject(input.orgId, input.projectId);
@@ -8338,9 +8430,9 @@ var cloudSyncRouter = router({
8338
8430
  * membre, ce qui évite d'effacer les fichiers si le cloud a refusé l'ordre.
8339
8431
  */
8340
8432
  deleteProjectFromOrg: protectedProcedure.input(
8341
- z23.object({
8342
- orgId: z23.string().min(1).max(128),
8343
- projectId: z23.string().min(1).max(128)
8433
+ z24.object({
8434
+ orgId: z24.string().min(1).max(128),
8435
+ projectId: z24.string().min(1).max(128)
8344
8436
  })
8345
8437
  ).mutation(async ({ input }) => {
8346
8438
  let res;
@@ -8353,8 +8445,8 @@ var cloudSyncRouter = router({
8353
8445
  accountId: await accountForOrgScope(input.orgId)
8354
8446
  });
8355
8447
  } catch (err) {
8356
- if (err instanceof TRPCError19 && err.code === "PRECONDITION_FAILED") {
8357
- throw new TRPCError19({ code: "PRECONDITION_FAILED", message: "CLOUD_NOT_LINKED" });
8448
+ if (err instanceof TRPCError20 && err.code === "PRECONDITION_FAILED") {
8449
+ throw new TRPCError20({ code: "PRECONDITION_FAILED", message: "CLOUD_NOT_LINKED" });
8358
8450
  }
8359
8451
  throw err;
8360
8452
  }
@@ -8362,12 +8454,12 @@ var cloudSyncRouter = router({
8362
8454
  const detail = await cloudMessage(res);
8363
8455
  if (res.status === 403) {
8364
8456
  const code = /not a member/i.test(detail) ? "PROJECT_NOT_MEMBER" : "PROJECT_DELETE_FORBIDDEN";
8365
- throw new TRPCError19({ code: "FORBIDDEN", message: code, cause: new Error(detail) });
8457
+ throw new TRPCError20({ code: "FORBIDDEN", message: code, cause: new Error(detail) });
8366
8458
  }
8367
8459
  if (res.status === 404) {
8368
- throw new TRPCError19({ code: "NOT_FOUND", message: "PROJECT_NOT_IN_ORG", cause: new Error(detail) });
8460
+ throw new TRPCError20({ code: "NOT_FOUND", message: "PROJECT_NOT_IN_ORG", cause: new Error(detail) });
8369
8461
  }
8370
- throw new TRPCError19({
8462
+ throw new TRPCError20({
8371
8463
  code: "BAD_GATEWAY",
8372
8464
  message: detail || `PROJECT_DELETE_FAILED (${res.status})`
8373
8465
  });
@@ -8396,10 +8488,10 @@ var cloudSyncRouter = router({
8396
8488
  * d'un autre. Même forme que `rememberOrgNames`, et pour la même raison :
8397
8489
  * ce que seul le cloud sait, on le recopie quand il le dit.
8398
8490
  */
8399
- rememberOrgAccounts: protectedProcedure.input(z23.object({
8400
- orgs: z23.array(z23.object({
8401
- orgId: z23.string().min(1).max(128),
8402
- accountId: z23.string().min(1).max(64)
8491
+ rememberOrgAccounts: protectedProcedure.input(z24.object({
8492
+ orgs: z24.array(z24.object({
8493
+ orgId: z24.string().min(1).max(128),
8494
+ accountId: z24.string().min(1).max(64)
8403
8495
  })).max(200)
8404
8496
  })).mutation(async ({ input }) => {
8405
8497
  const candidates = /* @__PURE__ */ new Map();
@@ -8426,10 +8518,10 @@ var cloudSyncRouter = router({
8426
8518
  }
8427
8519
  return { remembered };
8428
8520
  }),
8429
- rememberOrgNames: protectedProcedure.input(z23.object({
8430
- orgs: z23.array(z23.object({
8431
- orgId: z23.string().min(1).max(128),
8432
- name: z23.string().min(1).max(100)
8521
+ rememberOrgNames: protectedProcedure.input(z24.object({
8522
+ orgs: z24.array(z24.object({
8523
+ orgId: z24.string().min(1).max(128),
8524
+ name: z24.string().min(1).max(100)
8433
8525
  })).max(200)
8434
8526
  })).mutation(async ({ input }) => {
8435
8527
  for (const { orgId, name } of input.orgs) await rememberOrgName(orgId, name);
@@ -8459,7 +8551,7 @@ var cloudSyncRouter = router({
8459
8551
  * Un 404 efface le logo retenu — l'organisation en a retiré un — tandis qu'un
8460
8552
  * réseau muet laisse en place ce qui est déjà là : hors ligne, on garde.
8461
8553
  */
8462
- cacheOrgLogos: protectedProcedure.input(z23.object({ orgIds: z23.array(z23.string().min(1).max(128)).max(200) })).mutation(async ({ input }) => {
8554
+ cacheOrgLogos: protectedProcedure.input(z24.object({ orgIds: z24.array(z24.string().min(1).max(128)).max(200) })).mutation(async ({ input }) => {
8463
8555
  let cached = 0;
8464
8556
  for (const orgId of input.orgIds) {
8465
8557
  const base = await orgCloudUrl(orgId);
@@ -8517,14 +8609,14 @@ var cloudSyncRouter = router({
8517
8609
  // ../server/src/trpc/routers/filesystem.ts
8518
8610
  import { readdir as readdir4, stat as stat6 } from "fs/promises";
8519
8611
  import { homedir as homedir3 } from "os";
8520
- import { isAbsolute as isAbsolute2, join as join12, resolve as resolve2, dirname as dirname6, basename } from "path";
8521
- import { z as z24 } from "zod";
8612
+ import { isAbsolute as isAbsolute3, join as join12, resolve as resolve2, dirname as dirname6, basename } from "path";
8613
+ import { z as z25 } from "zod";
8522
8614
  var MAX_ENTRIES2 = 500;
8523
- var PATH_SCHEMA = z24.string().min(1).max(4096);
8615
+ var PATH_SCHEMA = z25.string().min(1).max(4096);
8524
8616
  function safeResolve(input) {
8525
8617
  if (input.includes("\0")) throw new Error("Chemin invalide");
8526
8618
  const expanded = input.startsWith("~") ? join12(homedir3(), input.slice(1)) : input;
8527
- if (!isAbsolute2(expanded)) throw new Error("Le chemin doit \xEAtre absolu");
8619
+ if (!isAbsolute3(expanded)) throw new Error("Le chemin doit \xEAtre absolu");
8528
8620
  return resolve2(expanded);
8529
8621
  }
8530
8622
  var filesystemRouter = router({
@@ -8544,7 +8636,7 @@ var filesystemRouter = router({
8544
8636
  * Hidden entries are skipped: they are noise for choosing a workspace, and
8545
8637
  * `.runeya` itself would invite placing a project inside another's data.
8546
8638
  */
8547
- listDirectories: protectedProcedure.input(z24.object({ path: PATH_SCHEMA })).query(async ({ input }) => {
8639
+ listDirectories: protectedProcedure.input(z25.object({ path: PATH_SCHEMA })).query(async ({ input }) => {
8548
8640
  const dir = safeResolve(input.path);
8549
8641
  const info = await stat6(dir).catch(() => null);
8550
8642
  if (!info?.isDirectory()) {
@@ -8577,7 +8669,7 @@ var filesystemRouter = router({
8577
8669
  * qui s'y trouve, ou rien (déjà dans la liste, lié à un projet d'organisation,
8578
8670
  * racine machine).
8579
8671
  */
8580
- checkLocalProjectTarget: protectedProcedure.input(z24.object({ path: PATH_SCHEMA })).query(async ({ input }) => {
8672
+ checkLocalProjectTarget: protectedProcedure.input(z25.object({ path: PATH_SCHEMA })).query(async ({ input }) => {
8581
8673
  const dir = safeResolve(input.path);
8582
8674
  const info = await stat6(dir).catch(() => null);
8583
8675
  if (!info?.isDirectory()) return { path: dir, status: "missing", projectName: null };
@@ -8589,10 +8681,10 @@ var filesystemRouter = router({
8589
8681
  * Two projects in one directory is what makes services run against the wrong
8590
8682
  * code, so a directory that already holds one is refused outright.
8591
8683
  */
8592
- checkProjectTarget: protectedProcedure.input(z24.object({
8684
+ checkProjectTarget: protectedProcedure.input(z25.object({
8593
8685
  path: PATH_SCHEMA,
8594
- projectId: z24.string().min(1).max(128),
8595
- orgId: z24.string().max(128).nullable().optional()
8686
+ projectId: z25.string().min(1).max(128),
8687
+ orgId: z25.string().max(128).nullable().optional()
8596
8688
  })).query(async ({ input }) => {
8597
8689
  const dir = safeResolve(input.path);
8598
8690
  const info = await stat6(dir).catch(() => null);
@@ -8602,7 +8694,7 @@ var filesystemRouter = router({
8602
8694
  if (await holdsRuneyaProject(dir)) {
8603
8695
  return { ok: false, reason: "has-runeya-project", path: dir, otherProjectId: null };
8604
8696
  }
8605
- const otherProjectId = await projectPathStore.projectAt(dir, { id: input.projectId, orgId: input.orgId });
8697
+ const otherProjectId = await projectStore.projectAtPath(dir, { id: input.projectId, orgId: input.orgId });
8606
8698
  if (otherProjectId) {
8607
8699
  return { ok: false, reason: "taken", path: dir, otherProjectId };
8608
8700
  }
@@ -8611,13 +8703,13 @@ var filesystemRouter = router({
8611
8703
  });
8612
8704
 
8613
8705
  // ../server/src/trpc/routers/desktop.ts
8614
- import { z as z25 } from "zod";
8615
- import { isAbsolute as isAbsolute4 } from "path";
8616
- import { TRPCError as TRPCError20 } from "@trpc/server";
8706
+ import { z as z26 } from "zod";
8707
+ import { isAbsolute as isAbsolute5 } from "path";
8708
+ import { TRPCError as TRPCError21 } from "@trpc/server";
8617
8709
 
8618
8710
  // ../server/src/services/desktop-launcher.ts
8619
8711
  import { execFile as execFile4 } from "child_process";
8620
- import { isAbsolute as isAbsolute3 } from "path";
8712
+ import { isAbsolute as isAbsolute4 } from "path";
8621
8713
  import { promisify as promisify3 } from "util";
8622
8714
  var exec = promisify3(execFile4);
8623
8715
  var INSTALL_TIMEOUT_MS2 = 3e4;
@@ -8638,7 +8730,7 @@ function suggestLauncher() {
8638
8730
  }
8639
8731
  async function installLauncher(input) {
8640
8732
  if (!cli) throw new Error("launcher-unavailable");
8641
- if (input.workingDir !== null && !isAbsolute3(input.workingDir)) {
8733
+ if (input.workingDir !== null && !isAbsolute4(input.workingDir)) {
8642
8734
  throw new Error("launcher-working-dir-not-absolute");
8643
8735
  }
8644
8736
  const args = [
@@ -8696,43 +8788,43 @@ var desktopRouter = router({
8696
8788
  * dessinée par le serveur. Sans cette annonce elle garderait la teinte figée
8697
8789
  * du fichier livré avec le CLI. Rien n'est persisté — voir `tray-accent.ts`.
8698
8790
  */
8699
- setTrayAccent: protectedProcedure.input(z25.object({
8791
+ setTrayAccent: protectedProcedure.input(z26.object({
8700
8792
  // `#rgb` ou `#rrggbb` : la forme est vérifiée ici, pas rabotée plus loin.
8701
- color: z25.string().regex(/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/).nullable()
8793
+ color: z26.string().regex(/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/).nullable()
8702
8794
  })).mutation(({ input }) => {
8703
8795
  setTrayAccent(input.color);
8704
8796
  return { ok: true };
8705
8797
  }),
8706
- installLauncher: protectedProcedure.input(z25.object({
8707
- name: z25.string().trim().min(1).max(120),
8798
+ installLauncher: protectedProcedure.input(z26.object({
8799
+ name: z26.string().trim().min(1).max(120),
8708
8800
  /**
8709
8801
  * `null` : raccourci global, sans dossier épinglé. Sinon un chemin
8710
8802
  * absolu, refusé autrement : le dossier devient un argument positionnel
8711
8803
  * du CLI, où une valeur commençant par un tiret passerait pour un drapeau.
8712
8804
  */
8713
- workingDir: z25.string().max(4096).refine(isAbsolute4, {
8805
+ workingDir: z26.string().max(4096).refine(isAbsolute5, {
8714
8806
  message: "Le dossier de travail doit \xEAtre un chemin absolu."
8715
8807
  }).nullable(),
8716
- port: z25.number().int().min(1).max(65535),
8717
- agentPort: z25.number().int().min(1).max(65535)
8808
+ port: z26.number().int().min(1).max(65535),
8809
+ agentPort: z26.number().int().min(1).max(65535)
8718
8810
  })).mutation(async ({ input }) => {
8719
8811
  try {
8720
8812
  return await installLauncher(input);
8721
8813
  } catch (err) {
8722
8814
  const message = err.message;
8723
8815
  if (message === "launcher-working-dir-not-absolute") {
8724
- throw new TRPCError20({
8816
+ throw new TRPCError21({
8725
8817
  code: "BAD_REQUEST",
8726
8818
  message: "Le dossier de travail doit \xEAtre un chemin absolu."
8727
8819
  });
8728
8820
  }
8729
8821
  if (message === "launcher-unavailable") {
8730
- throw new TRPCError20({
8822
+ throw new TRPCError21({
8731
8823
  code: "PRECONDITION_FAILED",
8732
8824
  message: "Cette Runeya ne sait pas o\xF9 trouver son CLI : cr\xE9ez le raccourci avec `runeya install-desktop`."
8733
8825
  });
8734
8826
  }
8735
- throw new TRPCError20({ code: "INTERNAL_SERVER_ERROR", message });
8827
+ throw new TRPCError21({ code: "INTERNAL_SERVER_ERROR", message });
8736
8828
  }
8737
8829
  })
8738
8830
  });
@@ -8740,6 +8832,7 @@ var desktopRouter = router({
8740
8832
  // ../server/src/trpc/router.ts
8741
8833
  var appRouter = router({
8742
8834
  health: healthRouter,
8835
+ session: sessionRouter,
8743
8836
  appUpdate: appUpdateRouter,
8744
8837
  changelog: changelogRouter,
8745
8838
  diagnostics: diagnosticsRouter,
@@ -10184,6 +10277,13 @@ var authLimiter = rateLimit({
10184
10277
  legacyHeaders: false,
10185
10278
  message: { error: "Trop de tentatives. R\xE9essayez dans 15 minutes." }
10186
10279
  });
10280
+ var refreshLimiter = rateLimit({
10281
+ windowMs: 60 * 1e3,
10282
+ max: 120,
10283
+ standardHeaders: true,
10284
+ legacyHeaders: false,
10285
+ message: { error: "Trop de renouvellements de session." }
10286
+ });
10187
10287
  var llmsLimiter = rateLimit({
10188
10288
  windowMs: 60 * 1e3,
10189
10289
  // 1 minute
@@ -10553,6 +10653,17 @@ async function createLocalServer() {
10553
10653
  });
10554
10654
  proxyCloudStream("/api/cloud/chat/stream", "/api/chat/stream");
10555
10655
  proxyCloudStream("/api/cloud/kanban/stream", "/api/kanban/stream");
10656
+ app.post("/api/auth/refresh", refreshLimiter, async (req, res) => {
10657
+ const auth = req.headers.authorization;
10658
+ const jwt = typeof auth === "string" && auth.startsWith("Bearer ") ? auth.slice(7) : "";
10659
+ try {
10660
+ await verifyJwt(jwt);
10661
+ } catch {
10662
+ res.status(401).json({ error: "Session invalide" });
10663
+ return;
10664
+ }
10665
+ res.json({ token: await signJwt() });
10666
+ });
10556
10667
  app.post("/api/unlock", authLimiter, csrfMiddleware, express.json({ limit: "10kb" }), async (req, res) => {
10557
10668
  try {
10558
10669
  const body = req.body;
@@ -10848,12 +10959,22 @@ async function createLocalServer() {
10848
10959
  applyWSSHandler({
10849
10960
  wss,
10850
10961
  router: appRouter,
10851
- createContext: ({ req }) => {
10962
+ createContext: ({ req, res: ws }) => {
10852
10963
  const headerAuth = req.headers.authorization ?? null;
10853
10964
  const urlObj = new URL(req.url ?? "/", `http://localhost:${env.PORT}`);
10854
10965
  const queryToken = urlObj.searchParams.get("token");
10855
10966
  const queryAuth = queryToken ? `Bearer ${queryToken}` : null;
10856
- return { authorization: headerAuth ?? queryAuth };
10967
+ let authorization = headerAuth ?? queryAuth;
10968
+ return {
10969
+ get authorization() {
10970
+ return authorization;
10971
+ },
10972
+ renewSocketToken: async (token) => {
10973
+ const { exp, iat } = await verifyJwt(token);
10974
+ authorization = `Bearer ${token}`;
10975
+ if (ws.readyState === ws.OPEN) wsConnRegistry.set(ws, { exp, iat });
10976
+ }
10977
+ };
10857
10978
  }
10858
10979
  });
10859
10980
  const wsConnRegistry = /* @__PURE__ */ new Map();
@@ -10931,7 +11052,7 @@ async function createLocalServer() {
10931
11052
  ]);
10932
11053
  console.log("[server] Shutdown complete");
10933
11054
  };
10934
- const { initCompanion } = await import("./companion-LQVLEHU7.js");
11055
+ const { initCompanion } = await import("./companion-2LHKU577.js");
10935
11056
  initCompanion();
10936
11057
  return { app, server, wss, shutdown };
10937
11058
  }
@@ -11361,21 +11482,29 @@ if (import.meta.url === `file://${process.argv[1]}`) {
11361
11482
  }
11362
11483
  export {
11363
11484
  PullEnvError,
11485
+ compareSemver,
11364
11486
  createLocalServer,
11487
+ globalCliEntry,
11488
+ installPrefix,
11489
+ installRuneyaGlobally,
11490
+ installedRuneya,
11365
11491
  killInstance,
11366
11492
  listInstances,
11367
11493
  listTrayServices,
11368
11494
  networkInfo,
11369
11495
  onTrayServicesChanged,
11496
+ probeVersion,
11370
11497
  pullEnv,
11371
11498
  registerCli as registerCliLocation,
11372
11499
  registerInstance,
11500
+ resolveNpm,
11373
11501
  resolveTrayIcon,
11374
11502
  restartInstance,
11375
11503
  restartProcess,
11376
11504
  scheduleSelfRestart,
11377
11505
  setLanMode,
11378
11506
  startProcess,
11379
- stopProcess
11507
+ stopProcess,
11508
+ userPrefix
11380
11509
  };
11381
- //# sourceMappingURL=src-NVQHFMTQ.js.map
11510
+ //# sourceMappingURL=src-5TEXF3SU.js.map