@runeya/runeya 2.0.122 → 2.0.123

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.
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  agentManager
3
- } from "./chunk-XTLQOYLT.js";
4
- import "./chunk-GL7WA5K3.js";
3
+ } from "./chunk-MSLFR2EN.js";
4
+ import "./chunk-HK5QNU6P.js";
5
5
  import "./chunk-T2BV5WZE.js";
6
6
  import "./chunk-ZFELQG4B.js";
7
7
  export {
8
8
  agentManager
9
9
  };
10
- //# sourceMappingURL=agent-manager-BSPEFZKZ.js.map
10
+ //# sourceMappingURL=agent-manager-2G55ZFCL.js.map
@@ -3,13 +3,13 @@ import {
3
3
  startClaudeCodeSession,
4
4
  startCliSession,
5
5
  startCodexSession
6
- } from "./chunk-BVBK2WII.js";
6
+ } from "./chunk-DUHCY3JU.js";
7
7
  import "./chunk-B7MABGQN.js";
8
- import "./chunk-VNLIA5PV.js";
8
+ import "./chunk-TNJFDWJX.js";
9
9
  import "./chunk-MD3VW4HQ.js";
10
- import "./chunk-XTLQOYLT.js";
11
- import "./chunk-NIU3CN5A.js";
12
- import "./chunk-GL7WA5K3.js";
10
+ import "./chunk-MSLFR2EN.js";
11
+ import "./chunk-N3ZI35SC.js";
12
+ import "./chunk-HK5QNU6P.js";
13
13
  import "./chunk-T2BV5WZE.js";
14
14
  import "./chunk-ZFELQG4B.js";
15
15
  export {
@@ -18,4 +18,4 @@ export {
18
18
  startCliSession,
19
19
  startCodexSession
20
20
  };
21
- //# sourceMappingURL=chat-SE5GIT4B.js.map
21
+ //# sourceMappingURL=chat-MOAVENBI.js.map
@@ -31,7 +31,7 @@ import {
31
31
  runCompanionNow,
32
32
  syncConversationFromClaudeTranscript,
33
33
  verifyJwt
34
- } from "./chunk-VNLIA5PV.js";
34
+ } from "./chunk-TNJFDWJX.js";
35
35
  import {
36
36
  StoreDiskCoordinator,
37
37
  agentManager,
@@ -49,10 +49,10 @@ import {
49
49
  isEncryptedValue,
50
50
  refsOfProjectId,
51
51
  serviceStore
52
- } from "./chunk-XTLQOYLT.js";
52
+ } from "./chunk-MSLFR2EN.js";
53
53
  import {
54
54
  settingsManager
55
- } from "./chunk-NIU3CN5A.js";
55
+ } from "./chunk-N3ZI35SC.js";
56
56
  import {
57
57
  atomicWriteJsonSecure,
58
58
  atomicWriteSecure,
@@ -62,7 +62,7 @@ import {
62
62
  rememberFile,
63
63
  resolveConversationRunDir,
64
64
  wasRead
65
- } from "./chunk-GL7WA5K3.js";
65
+ } from "./chunk-HK5QNU6P.js";
66
66
  import {
67
67
  AGENT_STOP_FETCH_TIMEOUT,
68
68
  ApiKeysFileSchema,
@@ -5272,7 +5272,7 @@ function tailTranscript(opts) {
5272
5272
 
5273
5273
  // ../server/src/services/ai-runners/claude-pty-runner.ts
5274
5274
  async function getAgentManager() {
5275
- const { agentManager: agentManager2 } = await import("./agent-manager-BSPEFZKZ.js");
5275
+ const { agentManager: agentManager2 } = await import("./agent-manager-2G55ZFCL.js");
5276
5276
  return agentManager2;
5277
5277
  }
5278
5278
  function buildPtyArgs(params, sessionId, opts) {
@@ -5964,7 +5964,7 @@ async function shutdownCodexAppServer() {
5964
5964
  }
5965
5965
  }
5966
5966
  async function getAgentManager2() {
5967
- const { agentManager: agentManager2 } = await import("./agent-manager-BSPEFZKZ.js");
5967
+ const { agentManager: agentManager2 } = await import("./agent-manager-2G55ZFCL.js");
5968
5968
  return agentManager2;
5969
5969
  }
5970
5970
  function parseRuneyaCurlCommand(command) {
@@ -8006,4 +8006,4 @@ export {
8006
8006
  startCliSession,
8007
8007
  chatRouter
8008
8008
  };
8009
- //# sourceMappingURL=chunk-BVBK2WII.js.map
8009
+ //# sourceMappingURL=chunk-DUHCY3JU.js.map
@@ -40,8 +40,8 @@ async function fingerprintFiles(paths) {
40
40
 
41
41
  // ../server/src/services/run-store-utils.ts
42
42
  import { randomUUID } from "crypto";
43
- import { chmod, mkdir, rename, rm, writeFile, readFile } from "fs/promises";
44
- import { dirname, resolve, sep } from "path";
43
+ import { chmod, mkdir, readdir, rename, rm, stat as stat2, writeFile, readFile } from "fs/promises";
44
+ import { dirname, join, resolve, sep } from "path";
45
45
  var SAFE_PATH_SEGMENT_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/;
46
46
  function resolveConversationRunDir(rootDirName, conversationId) {
47
47
  if (!SAFE_PATH_SEGMENT_RE.test(conversationId)) {
@@ -67,6 +67,30 @@ async function atomicWriteSecure(filePath, content) {
67
67
  }
68
68
  await chmod(filePath, 384);
69
69
  }
70
+ var OWN_TEMP_RE = /\.\d+\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.tmp$/;
71
+ var STALE_TEMP_MS = 36e5;
72
+ async function sweepStaleTempFiles(dirs) {
73
+ let removed = 0;
74
+ const limit = Date.now() - STALE_TEMP_MS;
75
+ for (const dir of dirs) {
76
+ let names;
77
+ try {
78
+ names = await readdir(dir);
79
+ } catch {
80
+ continue;
81
+ }
82
+ for (const name of names.filter((n) => OWN_TEMP_RE.test(n))) {
83
+ const path = join(dir, name);
84
+ try {
85
+ if ((await stat2(path)).mtimeMs > limit) continue;
86
+ await rm(path, { force: true });
87
+ removed += 1;
88
+ } catch {
89
+ }
90
+ }
91
+ }
92
+ return removed;
93
+ }
70
94
  async function atomicWriteJsonSecure(filePath, data, pretty = false) {
71
95
  await atomicWriteSecure(filePath, JSON.stringify(data, null, pretty ? 2 : 0));
72
96
  }
@@ -86,7 +110,8 @@ export {
86
110
  fingerprintFiles,
87
111
  resolveConversationRunDir,
88
112
  atomicWriteSecure,
113
+ sweepStaleTempFiles,
89
114
  atomicWriteJsonSecure,
90
115
  readJsonFileSafe
91
116
  };
92
- //# sourceMappingURL=chunk-GL7WA5K3.js.map
117
+ //# sourceMappingURL=chunk-HK5QNU6P.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../server/src/services/disk-freshness.ts","../../server/src/services/run-store-utils.ts"],"sourcesContent":["import { stat } from 'node:fs/promises';\n\n/**\n * Le fichier a-t-il changé depuis qu'on l'a lu ?\n *\n * Les stores gardent de côté ce qu'ils n'ont pas su déchiffrer, pour le\n * réécrire tel quel plutôt que de l'effacer. Cette copie est la bonne réponse\n * tant que personne d'autre ne touche au fichier — et la mauvaise dès que\n * quelqu'un le répare par-dessous : la copie, elle, ne se périme jamais, et la\n * sauvegarde suivante réinstalle l'état d'avant la réparation.\n *\n * C'est arrivé deux fois de suite sur le même coffre : une conversion de clé\n * menée sur le disque, défaite quelques minutes plus tard par un store qui\n * tenait encore l'ancien chiffré en mémoire.\n *\n * D'où ce repère : l'empreinte du fichier au moment de la lecture. Si elle a\n * bougé, la copie mémoire ne fait plus foi et doit être abandonnée.\n */\n\ninterface Fingerprint {\n mtimeMs: number;\n size: number;\n /**\n * L'inode du chemin, qui change à chaque `rename` par-dessus.\n *\n * La date et la taille laissent passer le motif d'écriture de tout le dépôt :\n * les stores réécrivent le fichier entier, donc une modification rend souvent\n * le même nombre d'octets, et deux instances qui réagissent au même événement\n * écrivent dans la même milliseconde. Le fichier temporaire renommé\n * par-dessus, lui, installe toujours un autre inode.\n *\n * Là où le système n'en expose pas (il rend alors 0), le repère retombe sur\n * la date et la taille — ce qu'il valait avant.\n */\n ino: number;\n}\n\nconst seen = new Map<string, Fingerprint>();\n\n/** Retenir l'état d'un fichier au moment où on vient de le lire. */\nexport async function rememberFile(path: string): Promise<void> {\n try {\n const s = await stat(path);\n seen.set(path, { mtimeMs: s.mtimeMs, size: s.size, ino: s.ino });\n } catch {\n // Pas encore de fichier : rien à retenir, et rien à réémettre non plus.\n seen.delete(path);\n }\n}\n\n/**\n * Vrai si le fichier a changé — ou si l'on ne sait pas.\n *\n * L'ignorance compte comme un changement : réécrire une copie dont on ne peut\n * plus prouver qu'elle correspond au disque est précisément le geste à éviter.\n */\nexport async function hasChangedSinceRead(path: string): Promise<boolean> {\n const known = seen.get(path);\n if (!known) return true;\n try {\n const s = await stat(path);\n return s.mtimeMs !== known.mtimeMs || s.size !== known.size || s.ino !== known.ino;\n } catch {\n return true;\n }\n}\n\n/**\n * A-t-on lu ce fichier ?\n *\n * `hasChangedSinceRead` tient l'ignorance pour un changement : c'est juste\n * quand il s'agit de décider si une copie mémoire fait encore foi. Ça ne l'est\n * pas pour décider d'écrire — un fichier jamais lu est le cas d'un coffre neuf,\n * et le traiter comme « modifié sous nos pieds » revenait à ne jamais écrire la\n * première fois. Les appelants qui protègent une écriture demandent donc les\n * deux : connu, et inchangé.\n */\nexport function wasRead(path: string): boolean {\n return seen.has(path);\n}\n\n/** Oublier un fichier — après un rechargement complet, par exemple. */\nexport function forgetFile(path: string): void {\n seen.delete(path);\n}\n\n/**\n * L'empreinte d'un ensemble de fichiers : lesquels, et dans quel état.\n *\n * Le repère ci-dessus répond pour un fichier qu'on a lu soi-même ; celui-ci\n * répond pour un store dont le contenu vient de plusieurs fichiers à la fois —\n * un par coffre — et dont la question est « le disque a-t-il bougé depuis mon\n * dernier chargement ? ». Comparer deux empreintes coûte quelques `stat` ;\n * recharger coûte autant de lectures, d'analyses et de déchiffrements.\n *\n * L'absence d'un fichier en fait partie : un coffre disparu change l'empreinte\n * autant qu'un coffre modifié.\n */\nexport async function fingerprintFiles(paths: string[]): Promise<string> {\n const stamps = await Promise.all(paths.map(async (path) => {\n try {\n const s = await stat(path);\n // L'inode en fait partie pour la raison décrite sur `Fingerprint` : un\n // fichier renommé par-dessus la cible peut n'avoir bougé ni en taille ni\n // en date, et reste pourtant un autre contenu.\n return `${path}:${s.mtimeMs}:${s.size}:${s.ino}`;\n } catch {\n return `${path}:-`;\n }\n }));\n return stamps.sort().join('|');\n}\n","import { randomUUID } from 'node:crypto';\nimport { chmod, mkdir, readdir, rename, rm, stat, writeFile, readFile } from 'node:fs/promises';\nimport { dirname, join, resolve, sep } from 'node:path';\nimport { machineRoot } from './vault-resolver.js';\n\nconst SAFE_PATH_SEGMENT_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/;\n\nexport function resolveConversationRunDir(rootDirName: string, conversationId: string): string {\n if (!SAFE_PATH_SEGMENT_RE.test(conversationId)) {\n throw new Error('Invalid conversationId');\n }\n // Machine-wide, like the conversations these runs belong to: using the launch\n // directory would put a `.runeya` in a repository just for asking the AI a\n // question about a cloud project.\n const base = resolve(machineRoot(), rootDirName);\n const dir = resolve(base, conversationId);\n if (!dir.startsWith(base + sep)) {\n throw new Error('Invalid conversationId');\n }\n return dir;\n}\n\nexport async function atomicWriteSecure(filePath: string, content: string | Uint8Array): Promise<void> {\n await mkdir(dirname(filePath), { recursive: true });\n // Un nom par écriture : deux Runeya d'un même poste écrivent les mêmes\n // fichiers, et un `.tmp` commun se fait renommer sous le nez de l'autre.\n const tmpPath = `${filePath}.${process.pid}.${randomUUID()}.tmp`;\n try {\n await writeFile(tmpPath, content, typeof content === 'string' ? 'utf-8' : undefined);\n await rename(tmpPath, filePath);\n } catch (err) {\n // Un nom unique ne se réécrit jamais : laissé là, chaque échec en ajouterait un.\n await rm(tmpPath, { force: true }).catch(() => {});\n throw err;\n }\n await chmod(filePath, 0o600);\n}\n\n/** Le nom qu'`atomicWriteSecure` donne à ses fichiers temporaires : `<fichier>.<pid>.<uuid>.tmp`. */\nconst OWN_TEMP_RE = /\\.\\d+\\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\.tmp$/;\nconst STALE_TEMP_MS = 3600_000;\n\n/**\n * Retirer les fichiers temporaires qu'un arrêt brutal a laissés.\n *\n * Un nom par écriture ne se réécrit jamais : chaque arrêt en pleine écriture en\n * laissait un pour toujours. Seuls les nôtres sont concernés, et seulement\n * passé une heure — un plus récent peut appartenir à une écriture en cours,\n * celle d'une autre Runeya du même poste.\n */\nexport async function sweepStaleTempFiles(dirs: string[]): Promise<number> {\n let removed = 0;\n const limit = Date.now() - STALE_TEMP_MS;\n for (const dir of dirs) {\n let names: string[];\n try {\n names = await readdir(dir);\n } catch {\n continue;\n }\n for (const name of names.filter((n) => OWN_TEMP_RE.test(n))) {\n const path = join(dir, name);\n try {\n if ((await stat(path)).mtimeMs > limit) continue;\n await rm(path, { force: true });\n removed += 1;\n } catch {\n // Disparu entre-temps : rien à retirer.\n }\n }\n }\n return removed;\n}\n\nexport async function atomicWriteJsonSecure(filePath: string, data: unknown, pretty = false): Promise<void> {\n await atomicWriteSecure(filePath, JSON.stringify(data, null, pretty ? 2 : 0));\n}\n\nexport async function readJsonFileSafe<T>(filePath: string): Promise<T | null> {\n try {\n const raw = await readFile(filePath, 'utf-8');\n return JSON.parse(raw) as T;\n } catch {\n return null;\n }\n}\n"],"mappings":"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","names":["stat","stat"]}
@@ -4,7 +4,7 @@ import {
4
4
  hasChangedSinceRead,
5
5
  rememberFile,
6
6
  wasRead
7
- } from "./chunk-GL7WA5K3.js";
7
+ } from "./chunk-HK5QNU6P.js";
8
8
  import {
9
9
  AGENT_FETCH_TIMEOUT,
10
10
  AGENT_HEALTH_POLL_INTERVAL,
@@ -3095,4 +3095,4 @@ export {
3095
3095
  traefikManager,
3096
3096
  agentManager
3097
3097
  };
3098
- //# sourceMappingURL=chunk-XTLQOYLT.js.map
3098
+ //# sourceMappingURL=chunk-MSLFR2EN.js.map
@@ -3,7 +3,7 @@ import {
3
3
  hasChangedSinceRead,
4
4
  rememberFile,
5
5
  wasRead
6
- } from "./chunk-GL7WA5K3.js";
6
+ } from "./chunk-HK5QNU6P.js";
7
7
  import {
8
8
  SchemaVersionSchema,
9
9
  SettingsPrivateSchema,
@@ -171,4 +171,4 @@ var settingsManager = new SettingsManager();
171
171
  export {
172
172
  settingsManager
173
173
  };
174
- //# sourceMappingURL=chunk-NIU3CN5A.js.map
174
+ //# sourceMappingURL=chunk-N3ZI35SC.js.map
@@ -22,14 +22,14 @@ import {
22
22
  serviceStore,
23
23
  setProjectServices,
24
24
  setProjectVault
25
- } from "./chunk-XTLQOYLT.js";
25
+ } from "./chunk-MSLFR2EN.js";
26
26
  import {
27
27
  atomicWriteSecure,
28
28
  fingerprintFiles,
29
29
  hasChangedSinceRead,
30
30
  rememberFile,
31
31
  wasRead
32
- } from "./chunk-GL7WA5K3.js";
32
+ } from "./chunk-HK5QNU6P.js";
33
33
  import {
34
34
  COMPANION_RELAY_CLOSE,
35
35
  COMPANION_RELAY_OPEN,
@@ -2022,7 +2022,7 @@ async function runCompanionForTurn(conversationId) {
2022
2022
  if (!hasNew) {
2023
2023
  return skip(conversationId, "nothingNew", `rien de neuf \xE0 relire (${messageCount} messages)`);
2024
2024
  }
2025
- const { startCliSession } = await import("./chat-SE5GIT4B.js");
2025
+ const { startCliSession } = await import("./chat-MOAVENBI.js");
2026
2026
  const companionConv = await ensureCompanionConversation(conv);
2027
2027
  const isFirstTurn = (companionConv.messages?.length ?? 0) === 0;
2028
2028
  const exchange = formatExchange(conv.messages, from);
@@ -2136,7 +2136,7 @@ async function deliverToMainConversation(conv, message) {
2136
2136
  async function attemptDelivery(conv, message) {
2137
2137
  if (await writeToLivePty(conv.id, message)) return "pty";
2138
2138
  try {
2139
- const { startCliSession } = await import("./chat-SE5GIT4B.js");
2139
+ const { startCliSession } = await import("./chat-MOAVENBI.js");
2140
2140
  await startCliSession(conv.runner, conv.id, message, { jwt: await signJwt() });
2141
2141
  return "headless";
2142
2142
  } catch (err) {
@@ -2159,7 +2159,7 @@ async function writeToLivePty(conversationId, message) {
2159
2159
  }
2160
2160
  async function companionSettings() {
2161
2161
  try {
2162
- const { settingsManager } = await import("./settings-manager-4GAINSJO.js");
2162
+ const { settingsManager } = await import("./settings-manager-MAVD4GAS.js");
2163
2163
  const settings = await settingsManager.getSettings();
2164
2164
  return settings.companion ?? { enabledByDefault: false };
2165
2165
  } catch {
@@ -2288,4 +2288,4 @@ export {
2288
2288
  runCompanionNow,
2289
2289
  initCompanion
2290
2290
  };
2291
- //# sourceMappingURL=chunk-VNLIA5PV.js.map
2291
+ //# sourceMappingURL=chunk-TNJFDWJX.js.map
@@ -26,10 +26,10 @@ import {
26
26
  reviewWindow,
27
27
  runCompanionNow,
28
28
  takeRelaunchSlot
29
- } from "./chunk-VNLIA5PV.js";
29
+ } from "./chunk-TNJFDWJX.js";
30
30
  import "./chunk-MD3VW4HQ.js";
31
- import "./chunk-XTLQOYLT.js";
32
- import "./chunk-GL7WA5K3.js";
31
+ import "./chunk-MSLFR2EN.js";
32
+ import "./chunk-HK5QNU6P.js";
33
33
  import "./chunk-T2BV5WZE.js";
34
34
  import "./chunk-ZFELQG4B.js";
35
35
  export {
@@ -61,4 +61,4 @@ export {
61
61
  runCompanionNow,
62
62
  takeRelaunchSlot
63
63
  };
64
- //# sourceMappingURL=companion-HEJHC3UR.js.map
64
+ //# sourceMappingURL=companion-7VOV4W3T.js.map
package/index.js CHANGED
@@ -135,7 +135,7 @@ if (subCommand === "install-desktop" || subCommand === "uninstall-desktop") {
135
135
  }
136
136
  }
137
137
  if (subCommand === "instances") {
138
- const { listInstances, killInstance, restartInstance } = await import("./src-YUVA6WCM.js");
138
+ const { listInstances, killInstance, restartInstance } = await import("./src-DN2IGASI.js");
139
139
  const { runInstancesCommand } = await import("./instances-command-KZ5UGXOR.js");
140
140
  process.exit(await runInstancesCommand(args.slice(1), {
141
141
  listInstances,
@@ -299,7 +299,7 @@ async function main() {
299
299
  ensureNodeBinOnPath();
300
300
  await ensureUserBinsOnPath();
301
301
  if (!isPullEnv) stampConsole();
302
- const { createLocalServer, pullEnv, PullEnvError, registerInstance, registerCliLocation } = await import("./src-YUVA6WCM.js");
302
+ const { createLocalServer, pullEnv, PullEnvError, registerInstance, registerCliLocation } = await import("./src-DN2IGASI.js");
303
303
  registerCliLocation({ execPath: process.execPath, cliEntry: fileURLToPath(import.meta.url) });
304
304
  if (isPullEnv) {
305
305
  if (!serviceArg) {
@@ -408,7 +408,7 @@ async function main() {
408
408
  networkInfo,
409
409
  setLanMode,
410
410
  resolveTrayIcon
411
- } = await import("./src-YUVA6WCM.js");
411
+ } = await import("./src-DN2IGASI.js");
412
412
  tray = await startInstanceTray({
413
413
  info: { cwd: process.cwd(), port, version, url: appUrl },
414
414
  assetsDir: join(__dirname, "assets"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runeya/runeya",
3
- "version": "2.0.122",
3
+ "version": "2.0.123",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "runeya": "./index.js"
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  settingsManager
3
- } from "./chunk-NIU3CN5A.js";
4
- import "./chunk-GL7WA5K3.js";
3
+ } from "./chunk-N3ZI35SC.js";
4
+ import "./chunk-HK5QNU6P.js";
5
5
  import "./chunk-T2BV5WZE.js";
6
6
  import "./chunk-ZFELQG4B.js";
7
7
  export {
8
8
  settingsManager
9
9
  };
10
- //# sourceMappingURL=settings-manager-4GAINSJO.js.map
10
+ //# sourceMappingURL=settings-manager-MAVD4GAS.js.map
@@ -62,7 +62,7 @@ import {
62
62
  soleAccountScope,
63
63
  startCliSession,
64
64
  vaultOfProject
65
- } from "./chunk-BVBK2WII.js";
65
+ } from "./chunk-DUHCY3JU.js";
66
66
  import {
67
67
  resolveCliInvocation,
68
68
  whichCommand
@@ -85,7 +85,7 @@ import {
85
85
  stopClaudeTranscriptWatcher,
86
86
  stopCodexTranscriptWatcher,
87
87
  verifyJwt
88
- } from "./chunk-VNLIA5PV.js";
88
+ } from "./chunk-TNJFDWJX.js";
89
89
  import "./chunk-MD3VW4HQ.js";
90
90
  import {
91
91
  agentManager,
@@ -123,14 +123,15 @@ import {
123
123
  stableEncryptValue,
124
124
  traefikManager,
125
125
  unregisterInstance
126
- } from "./chunk-XTLQOYLT.js";
126
+ } from "./chunk-MSLFR2EN.js";
127
127
  import {
128
128
  settingsManager
129
- } from "./chunk-NIU3CN5A.js";
129
+ } from "./chunk-N3ZI35SC.js";
130
130
  import {
131
131
  atomicWriteSecure,
132
- resolveConversationRunDir
133
- } from "./chunk-GL7WA5K3.js";
132
+ resolveConversationRunDir,
133
+ sweepStaleTempFiles
134
+ } from "./chunk-HK5QNU6P.js";
134
135
  import {
135
136
  AGENT_LONG_FETCH_TIMEOUT,
136
137
  AGENT_STOP_FETCH_TIMEOUT,
@@ -166,6 +167,7 @@ import {
166
167
  writeEntity
167
168
  } from "./chunk-T2BV5WZE.js";
168
169
  import {
170
+ allVaultRoots,
169
171
  env,
170
172
  forgetOrgLogo,
171
173
  keyRoot,
@@ -6634,6 +6636,7 @@ function writeSyncDocSync(orgId, state) {
6634
6636
  var LOCAL_ORIGIN = "local-bridge";
6635
6637
  var REMOTE_ORIGIN = "remote";
6636
6638
  var CACHE_ORIGIN = "cache";
6639
+ var RESTORED_PROJECTS = "projectRestores";
6637
6640
  var PERSIST_DEBOUNCE_MS = 1e3;
6638
6641
  var RECONNECT_DELAY_MS = 3e3;
6639
6642
  var UNAUTHENTICATED_RETRY_MS = 5 * 6e4;
@@ -6717,6 +6720,14 @@ var OrgSyncConnection = class {
6717
6720
  * offline edit reverted, a service on disk erased by an older deletion.
6718
6721
  */
6719
6722
  seeded = false;
6723
+ markOpened;
6724
+ /**
6725
+ * Réglée quand le document tient l'état d'ouverture du cloud — ou quand il ne
6726
+ * l'aura pas : session refusée, app trop ancienne, connexion arrêtée.
6727
+ */
6728
+ opened = new Promise((resolve4) => {
6729
+ this.markOpened = resolve4;
6730
+ });
6720
6731
  /** Store applications started by remote events and not finished yet. */
6721
6732
  applying = /* @__PURE__ */ new Set();
6722
6733
  /**
@@ -6774,16 +6785,17 @@ var OrgSyncConnection = class {
6774
6785
  this.unsubscribes.push(environmentStore.onChange(this.onSaved));
6775
6786
  this.unsubscribes.push(logParserStore.onLocalChange(this.onSaved));
6776
6787
  const cached = await readSyncDoc(this.link.orgId);
6788
+ let cacheLoaded = false;
6777
6789
  if (cached) {
6778
6790
  try {
6779
6791
  Y2.applyUpdate(this.doc, cached, CACHE_ORIGIN);
6780
- this.initialDocApplied = true;
6792
+ cacheLoaded = true;
6781
6793
  } catch (err) {
6782
6794
  console.error("[cloud-sync] unreadable sync cache for org %s, ignored:", this.link.orgId, err.message);
6783
6795
  }
6784
6796
  }
6785
6797
  this.doc.on("update", () => this.schedulePersist());
6786
- if (cached && this.initialDocApplied) await this.seed();
6798
+ if (cacheLoaded) await this.seed();
6787
6799
  void this.streamLoop();
6788
6800
  }
6789
6801
  /** Write local state on top of the known history, then owe it to the cloud. */
@@ -6818,6 +6830,7 @@ var OrgSyncConnection = class {
6818
6830
  /** Resolves once any cache write already under way has landed. */
6819
6831
  stop() {
6820
6832
  this.stopped = true;
6833
+ this.markOpened();
6821
6834
  this.state = "stopped";
6822
6835
  projectStore.events.off("saved", this.onSaved);
6823
6836
  for (const off of this.unsubscribes.splice(0)) off();
@@ -6871,6 +6884,7 @@ var OrgSyncConnection = class {
6871
6884
  }
6872
6885
  /** Remember the floor and stop pretending sync will resume on its own. */
6873
6886
  markOutdated(err) {
6887
+ this.markOpened();
6874
6888
  const alreadyReported = this.state === "outdated";
6875
6889
  this.state = "outdated";
6876
6890
  this.lastIncompatibleVersion = err.lastIncompatibleVersion;
@@ -6883,6 +6897,7 @@ var OrgSyncConnection = class {
6883
6897
  * every slow retry: the point of retrying is to recover quietly.
6884
6898
  */
6885
6899
  markUnauthenticated(err) {
6900
+ this.markOpened();
6886
6901
  const alreadyReported = this.state === "unauthenticated";
6887
6902
  this.state = "unauthenticated";
6888
6903
  this.needsPush = true;
@@ -7002,8 +7017,9 @@ var OrgSyncConnection = class {
7002
7017
  } catch {
7003
7018
  continue;
7004
7019
  }
7020
+ this.initialDocApplied = true;
7021
+ this.markOpened();
7005
7022
  if (!this.seeded) {
7006
- this.initialDocApplied = true;
7007
7023
  await this.settleApplying();
7008
7024
  if (this.stopped) return;
7009
7025
  await this.seed();
@@ -7131,6 +7147,7 @@ var OrgSyncConnection = class {
7131
7147
  this.pulling = false;
7132
7148
  }
7133
7149
  await serviceStore.relocateAll();
7150
+ await environmentStore.relocateAll();
7134
7151
  await this.reconcileLocalToDoc();
7135
7152
  }
7136
7153
  // ---- Local ↔ Doc reconciliation --------------------------------------
@@ -7161,6 +7178,7 @@ var OrgSyncConnection = class {
7161
7178
  if (name === "projects" && !isInitial) {
7162
7179
  for (const id of added) {
7163
7180
  if (deleted.has(id) || this.tracked.has(id)) continue;
7181
+ if (this.doc.getMap(RESTORED_PROJECTS).has(id)) continue;
7164
7182
  try {
7165
7183
  await this.followProject(id);
7166
7184
  } catch (err) {
@@ -7524,6 +7542,25 @@ var CloudSyncBridge = class {
7524
7542
  this.connections.delete(orgId);
7525
7543
  }
7526
7544
  }
7545
+ /**
7546
+ * Attendre que le document d'une organisation tienne l'état du cloud.
7547
+ *
7548
+ * Suivre un projet juste après avoir ouvert la connexion ne trouvait rien : la
7549
+ * trame d'ouverture n'était pas arrivée, et l'app concluait à un échec. Rend la
7550
+ * main au plus tard après `timeoutMs` — l'appelant lit alors l'état.
7551
+ */
7552
+ async whenOpened(orgId, timeoutMs) {
7553
+ const conn = this.connections.get(orgId);
7554
+ if (!conn) return;
7555
+ let timer;
7556
+ await Promise.race([
7557
+ conn.opened,
7558
+ new Promise((resolve4) => {
7559
+ timer = setTimeout(resolve4, timeoutMs);
7560
+ })
7561
+ ]);
7562
+ clearTimeout(timer);
7563
+ }
7527
7564
  /** Stops at once; the promise only says when pending cache writes have landed. */
7528
7565
  stopAll() {
7529
7566
  const stopping = [...this.connections.values()].map((conn) => conn.stop());
@@ -7679,6 +7716,7 @@ async function accountScope(orgId) {
7679
7716
  const accountId = await accountForOrg(orgId);
7680
7717
  return accountId ? { accountId } : {};
7681
7718
  }
7719
+ var OPENING_TIMEOUT_MS = 1e4;
7682
7720
  async function assertOrgReadable(orgId) {
7683
7721
  try {
7684
7722
  await assertOrgVaultReadable(orgId);
@@ -7737,6 +7775,7 @@ var cloudSyncRouter = router({
7737
7775
  } else if (input.accountId) {
7738
7776
  await stampOrgCloud(input.orgId, input.cloudUrl, void 0, input.accountId);
7739
7777
  }
7778
+ await cloudSyncBridge.whenOpened(input.orgId, OPENING_TIMEOUT_MS);
7740
7779
  try {
7741
7780
  const pulled = await cloudSyncBridge.followProject(input.orgId, input.projectId);
7742
7781
  return { pulled, state: syncState(input.orgId) };
@@ -9897,6 +9936,11 @@ async function createLocalServer() {
9897
9936
  await serviceStore.list().catch((err) => {
9898
9937
  console.warn("[server] Failed to preload services:", err);
9899
9938
  });
9939
+ void (async () => {
9940
+ const orgRoots = (await listOrgVaults()).map((orgId) => orgVaultRoot(orgId));
9941
+ const removed = await sweepStaleTempFiles([machineRoot(), ...orgRoots, ...await allVaultRoots()]);
9942
+ if (removed > 0) console.log(`[server] ${removed} fichier(s) temporaire(s) orphelin(s) retir\xE9(s)`);
9943
+ })().catch((err) => console.warn("[server] Temp file sweep failed:", err));
9900
9944
  cloudSyncBridge.start().catch((err) => {
9901
9945
  console.warn("[server] Failed to start cloud sync bridge:", err);
9902
9946
  });
@@ -10529,7 +10573,7 @@ async function createLocalServer() {
10529
10573
  ]);
10530
10574
  console.log("[server] Shutdown complete");
10531
10575
  };
10532
- const { initCompanion } = await import("./companion-HEJHC3UR.js");
10576
+ const { initCompanion } = await import("./companion-7VOV4W3T.js");
10533
10577
  initCompanion();
10534
10578
  return { app, server, wss, shutdown };
10535
10579
  }
@@ -10976,4 +11020,4 @@ export {
10976
11020
  startProcess,
10977
11021
  stopProcess
10978
11022
  };
10979
- //# sourceMappingURL=src-YUVA6WCM.js.map
11023
+ //# sourceMappingURL=src-DN2IGASI.js.map