@0xmaxma/claude-gateway 1.7.9 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (258) hide show
  1. package/README.md +178 -44
  2. package/dist/agent/builtin-commands.js +2 -2
  3. package/dist/agent/builtin-commands.js.map +1 -1
  4. package/dist/agent/dreaming/accept.d.ts.map +1 -1
  5. package/dist/agent/dreaming/accept.js +4 -1
  6. package/dist/agent/dreaming/accept.js.map +1 -1
  7. package/dist/agent/dreaming/config.d.ts.map +1 -1
  8. package/dist/agent/dreaming/config.js +2 -0
  9. package/dist/agent/dreaming/config.js.map +1 -1
  10. package/dist/agent/dreaming/reviewer.d.ts.map +1 -1
  11. package/dist/agent/dreaming/reviewer.js +9 -2
  12. package/dist/agent/dreaming/reviewer.js.map +1 -1
  13. package/dist/agent/dreaming/staleness.d.ts +7 -1
  14. package/dist/agent/dreaming/staleness.d.ts.map +1 -1
  15. package/dist/agent/dreaming/staleness.js +17 -2
  16. package/dist/agent/dreaming/staleness.js.map +1 -1
  17. package/dist/agent/dreaming/types.d.ts +17 -1
  18. package/dist/agent/dreaming/types.d.ts.map +1 -1
  19. package/dist/agent/knowledge/archive-db.d.ts +43 -0
  20. package/dist/agent/knowledge/archive-db.d.ts.map +1 -1
  21. package/dist/agent/knowledge/archive-db.js +130 -0
  22. package/dist/agent/knowledge/archive-db.js.map +1 -1
  23. package/dist/agent/knowledge/config.d.ts +3 -1
  24. package/dist/agent/knowledge/config.d.ts.map +1 -1
  25. package/dist/agent/knowledge/config.js +32 -10
  26. package/dist/agent/knowledge/config.js.map +1 -1
  27. package/dist/agent/knowledge/index.d.ts +11 -4
  28. package/dist/agent/knowledge/index.d.ts.map +1 -1
  29. package/dist/agent/knowledge/index.js +22 -1
  30. package/dist/agent/knowledge/index.js.map +1 -1
  31. package/dist/agent/knowledge/indexer.d.ts +0 -7
  32. package/dist/agent/knowledge/indexer.d.ts.map +1 -1
  33. package/dist/agent/knowledge/indexer.js +34 -7
  34. package/dist/agent/knowledge/indexer.js.map +1 -1
  35. package/dist/agent/knowledge/lifecycle.d.ts +20 -4
  36. package/dist/agent/knowledge/lifecycle.d.ts.map +1 -1
  37. package/dist/agent/knowledge/lifecycle.js +33 -4
  38. package/dist/agent/knowledge/lifecycle.js.map +1 -1
  39. package/dist/agent/knowledge/reflection.d.ts +114 -0
  40. package/dist/agent/knowledge/reflection.d.ts.map +1 -0
  41. package/dist/agent/knowledge/reflection.js +447 -0
  42. package/dist/agent/knowledge/reflection.js.map +1 -0
  43. package/dist/agent/knowledge/shared-dedup.d.ts +85 -0
  44. package/dist/agent/knowledge/shared-dedup.d.ts.map +1 -0
  45. package/dist/agent/knowledge/shared-dedup.js +187 -0
  46. package/dist/agent/knowledge/shared-dedup.js.map +1 -0
  47. package/dist/agent/knowledge/shared-promote.d.ts +82 -7
  48. package/dist/agent/knowledge/shared-promote.d.ts.map +1 -1
  49. package/dist/agent/knowledge/shared-promote.js +244 -11
  50. package/dist/agent/knowledge/shared-promote.js.map +1 -1
  51. package/dist/agent/knowledge/shared-staleness.d.ts +51 -0
  52. package/dist/agent/knowledge/shared-staleness.d.ts.map +1 -0
  53. package/dist/agent/knowledge/shared-staleness.js +149 -0
  54. package/dist/agent/knowledge/shared-staleness.js.map +1 -0
  55. package/dist/agent/knowledge/shared-writer.d.ts +19 -0
  56. package/dist/agent/knowledge/shared-writer.d.ts.map +1 -1
  57. package/dist/agent/knowledge/shared-writer.js +42 -0
  58. package/dist/agent/knowledge/shared-writer.js.map +1 -1
  59. package/dist/agent/knowledge/types.d.ts +24 -0
  60. package/dist/agent/knowledge/types.d.ts.map +1 -1
  61. package/dist/agent/model-catalog.d.ts +62 -0
  62. package/dist/agent/model-catalog.d.ts.map +1 -0
  63. package/dist/agent/model-catalog.js +264 -0
  64. package/dist/agent/model-catalog.js.map +1 -0
  65. package/dist/agent/runner.d.ts +83 -0
  66. package/dist/agent/runner.d.ts.map +1 -1
  67. package/dist/agent/runner.js +281 -51
  68. package/dist/agent/runner.js.map +1 -1
  69. package/dist/agent/workspace-loader.d.ts +17 -2
  70. package/dist/agent/workspace-loader.d.ts.map +1 -1
  71. package/dist/agent/workspace-loader.js +17 -1
  72. package/dist/agent/workspace-loader.js.map +1 -1
  73. package/dist/api/cron-router.d.ts +12 -8
  74. package/dist/api/cron-router.d.ts.map +1 -1
  75. package/dist/api/cron-router.js +82 -16
  76. package/dist/api/cron-router.js.map +1 -1
  77. package/dist/api/gateway-router.d.ts +4 -0
  78. package/dist/api/gateway-router.d.ts.map +1 -1
  79. package/dist/api/gateway-router.js +16 -1
  80. package/dist/api/gateway-router.js.map +1 -1
  81. package/dist/api/manifest-sources.d.ts +15 -0
  82. package/dist/api/manifest-sources.d.ts.map +1 -0
  83. package/dist/api/manifest-sources.js +27 -0
  84. package/dist/api/manifest-sources.js.map +1 -0
  85. package/dist/api/meta-router.d.ts +13 -0
  86. package/dist/api/meta-router.d.ts.map +1 -0
  87. package/dist/api/meta-router.js +26 -0
  88. package/dist/api/meta-router.js.map +1 -0
  89. package/dist/api/packages.d.ts.map +1 -1
  90. package/dist/api/packages.js +18 -198
  91. package/dist/api/packages.js.map +1 -1
  92. package/dist/api/route-registry.d.ts +81 -0
  93. package/dist/api/route-registry.d.ts.map +1 -0
  94. package/dist/api/route-registry.js +44 -0
  95. package/dist/api/route-registry.js.map +1 -0
  96. package/dist/api/router.d.ts.map +1 -1
  97. package/dist/api/router.js +21 -3
  98. package/dist/api/router.js.map +1 -1
  99. package/dist/apps/compose-generator.js +7 -4
  100. package/dist/apps/compose-generator.js.map +1 -1
  101. package/dist/apps/installer.d.ts +154 -0
  102. package/dist/apps/installer.d.ts.map +1 -1
  103. package/dist/apps/installer.js +657 -54
  104. package/dist/apps/installer.js.map +1 -1
  105. package/dist/cli/args.d.ts +25 -0
  106. package/dist/cli/args.d.ts.map +1 -0
  107. package/dist/cli/args.js +55 -0
  108. package/dist/cli/args.js.map +1 -0
  109. package/dist/cli/colors.d.ts +37 -0
  110. package/dist/cli/colors.d.ts.map +1 -0
  111. package/dist/cli/colors.js +63 -0
  112. package/dist/cli/colors.js.map +1 -0
  113. package/dist/cli/command-names.d.ts +98 -0
  114. package/dist/cli/command-names.d.ts.map +1 -0
  115. package/dist/cli/command-names.js +109 -0
  116. package/dist/cli/command-names.js.map +1 -0
  117. package/dist/cli/commands/agents.d.ts +28 -0
  118. package/dist/cli/commands/agents.d.ts.map +1 -0
  119. package/dist/cli/commands/agents.js +321 -0
  120. package/dist/cli/commands/agents.js.map +1 -0
  121. package/dist/cli/commands/channels.d.ts +17 -0
  122. package/dist/cli/commands/channels.d.ts.map +1 -0
  123. package/dist/cli/commands/channels.js +101 -0
  124. package/dist/cli/commands/channels.js.map +1 -0
  125. package/dist/cli/commands/debug-bundle.d.ts +6 -0
  126. package/dist/cli/commands/debug-bundle.d.ts.map +1 -0
  127. package/dist/cli/commands/debug-bundle.js +220 -0
  128. package/dist/cli/commands/debug-bundle.js.map +1 -0
  129. package/dist/cli/commands/doctor.d.ts +3 -0
  130. package/dist/cli/commands/doctor.d.ts.map +1 -0
  131. package/dist/cli/commands/doctor.js +104 -0
  132. package/dist/cli/commands/doctor.js.map +1 -0
  133. package/dist/cli/commands/gateway.d.ts +12 -0
  134. package/dist/cli/commands/gateway.d.ts.map +1 -0
  135. package/dist/cli/commands/gateway.js +145 -0
  136. package/dist/cli/commands/gateway.js.map +1 -0
  137. package/dist/cli/commands/service.d.ts +33 -0
  138. package/dist/cli/commands/service.d.ts.map +1 -0
  139. package/dist/cli/commands/service.js +513 -0
  140. package/dist/cli/commands/service.js.map +1 -0
  141. package/dist/cli/commands/update.d.ts +16 -0
  142. package/dist/cli/commands/update.d.ts.map +1 -0
  143. package/dist/cli/commands/update.js +149 -0
  144. package/dist/cli/commands/update.js.map +1 -0
  145. package/dist/cli/commands.generated.d.ts +4 -0
  146. package/dist/cli/commands.generated.d.ts.map +1 -0
  147. package/dist/cli/commands.generated.js +220 -0
  148. package/dist/cli/commands.generated.js.map +1 -0
  149. package/dist/cli/health.d.ts +31 -0
  150. package/dist/cli/health.d.ts.map +1 -0
  151. package/dist/cli/health.js +49 -0
  152. package/dist/cli/health.js.map +1 -0
  153. package/dist/cli/http-client.d.ts +140 -0
  154. package/dist/cli/http-client.d.ts.map +1 -0
  155. package/dist/cli/http-client.js +332 -0
  156. package/dist/cli/http-client.js.map +1 -0
  157. package/dist/cli/index.d.ts +27 -0
  158. package/dist/cli/index.d.ts.map +1 -0
  159. package/dist/cli/index.js +372 -0
  160. package/dist/cli/index.js.map +1 -0
  161. package/dist/cli/manager.d.ts +64 -0
  162. package/dist/cli/manager.d.ts.map +1 -0
  163. package/dist/cli/manager.js +181 -0
  164. package/dist/cli/manager.js.map +1 -0
  165. package/dist/cli/output.d.ts +49 -0
  166. package/dist/cli/output.d.ts.map +1 -0
  167. package/dist/cli/output.js +101 -0
  168. package/dist/cli/output.js.map +1 -0
  169. package/dist/cli/prompt.d.ts +29 -0
  170. package/dist/cli/prompt.d.ts.map +1 -0
  171. package/dist/cli/prompt.js +154 -0
  172. package/dist/cli/prompt.js.map +1 -0
  173. package/dist/cli/redact.d.ts +3 -0
  174. package/dist/cli/redact.d.ts.map +1 -0
  175. package/dist/cli/redact.js +33 -0
  176. package/dist/cli/redact.js.map +1 -0
  177. package/dist/cli/types.d.ts +22 -0
  178. package/dist/cli/types.d.ts.map +1 -0
  179. package/dist/cli/types.js +4 -0
  180. package/dist/cli/types.js.map +1 -0
  181. package/dist/config/bootstrap.d.ts +33 -0
  182. package/dist/config/bootstrap.d.ts.map +1 -0
  183. package/dist/config/bootstrap.js +117 -0
  184. package/dist/config/bootstrap.js.map +1 -0
  185. package/dist/config/loader.d.ts.map +1 -1
  186. package/dist/config/loader.js +5 -1
  187. package/dist/config/loader.js.map +1 -1
  188. package/dist/config/watcher.d.ts.map +1 -1
  189. package/dist/config/watcher.js +2 -35
  190. package/dist/config/watcher.js.map +1 -1
  191. package/dist/discord/receiver.d.ts +6 -1
  192. package/dist/discord/receiver.d.ts.map +1 -1
  193. package/dist/discord/receiver.js +9 -1
  194. package/dist/discord/receiver.js.map +1 -1
  195. package/dist/entry.d.ts +3 -0
  196. package/dist/entry.d.ts.map +1 -0
  197. package/dist/entry.js +83 -0
  198. package/dist/entry.js.map +1 -0
  199. package/dist/index.js +197 -47
  200. package/dist/index.js.map +1 -1
  201. package/dist/load-dotenv.d.ts +2 -0
  202. package/dist/load-dotenv.d.ts.map +1 -0
  203. package/dist/load-dotenv.js +68 -0
  204. package/dist/load-dotenv.js.map +1 -0
  205. package/dist/packages/registry.d.ts +50 -0
  206. package/dist/packages/registry.d.ts.map +1 -0
  207. package/dist/packages/registry.js +209 -0
  208. package/dist/packages/registry.js.map +1 -0
  209. package/dist/session/process.d.ts +20 -3
  210. package/dist/session/process.d.ts.map +1 -1
  211. package/dist/session/process.js +120 -5
  212. package/dist/session/process.js.map +1 -1
  213. package/dist/shell/claude-pty-shell.js +146 -27
  214. package/dist/shell/claude-pty-shell.js.map +1 -1
  215. package/dist/shell/draft-phantom.d.ts +49 -0
  216. package/dist/shell/draft-phantom.d.ts.map +1 -0
  217. package/dist/shell/draft-phantom.js +59 -0
  218. package/dist/shell/draft-phantom.js.map +1 -0
  219. package/dist/shell/submit-diag.d.ts +67 -0
  220. package/dist/shell/submit-diag.d.ts.map +1 -0
  221. package/dist/shell/submit-diag.js +69 -0
  222. package/dist/shell/submit-diag.js.map +1 -0
  223. package/dist/shutdown-signals.d.ts +47 -0
  224. package/dist/shutdown-signals.d.ts.map +1 -0
  225. package/dist/shutdown-signals.js +62 -0
  226. package/dist/shutdown-signals.js.map +1 -0
  227. package/dist/telegram/receiver.d.ts +6 -1
  228. package/dist/telegram/receiver.d.ts.map +1 -1
  229. package/dist/telegram/receiver.js +9 -1
  230. package/dist/telegram/receiver.js.map +1 -1
  231. package/dist/types.d.ts +25 -0
  232. package/dist/types.d.ts.map +1 -1
  233. package/dist/utils/orphan-receivers.d.ts +90 -0
  234. package/dist/utils/orphan-receivers.d.ts.map +1 -0
  235. package/dist/utils/orphan-receivers.js +218 -0
  236. package/dist/utils/orphan-receivers.js.map +1 -0
  237. package/dist/utils/paths.d.ts +16 -0
  238. package/dist/utils/paths.d.ts.map +1 -0
  239. package/dist/utils/paths.js +60 -0
  240. package/dist/utils/paths.js.map +1 -0
  241. package/dist/utils/stop-child.d.ts +21 -0
  242. package/dist/utils/stop-child.d.ts.map +1 -0
  243. package/dist/utils/stop-child.js +64 -0
  244. package/dist/utils/stop-child.js.map +1 -0
  245. package/lib/pairing.ts +1 -1
  246. package/mcp/tools/agent/handlers.ts +1 -1
  247. package/mcp/tools/discord/module.ts +23 -15
  248. package/mcp/tools/discord/receiver-server.ts +4 -0
  249. package/mcp/tools/memory/archive-reader.test.ts +25 -1
  250. package/mcp/tools/memory/archive-reader.ts +70 -12
  251. package/mcp/tools/memory/archive-writer.test.ts +168 -0
  252. package/mcp/tools/memory/archive-writer.ts +137 -0
  253. package/mcp/tools/memory/module.test.ts +187 -0
  254. package/mcp/tools/memory/module.ts +192 -6
  255. package/mcp/tools/telegram/module.ts +10 -2
  256. package/mcp/tools/telegram/receiver-server.ts +15 -6
  257. package/mcp/tools/telegram/typing.ts +178 -34
  258. package/package.json +6 -4
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Version detection and self-update for the two packages the gateway manages:
3
+ * itself and the Claude Code binary it drives.
4
+ *
5
+ * Shared by the HTTP API (src/api/packages.ts) and the CLI (`claude-gateway
6
+ * update`, `claude-gateway claude update`) so both apply exactly the same
7
+ * detect/update strategy — the CLI must never invent a second way to install
8
+ * a package, or the dashboard and the terminal would disagree about what is
9
+ * running.
10
+ */
11
+ export interface PackageConfig {
12
+ npm: string;
13
+ detect: 'npm' | 'binary';
14
+ bin?: string;
15
+ update: 'npm' | 'native';
16
+ }
17
+ /**
18
+ * Package id (URL param / CLI noun) → config.
19
+ * claude-gateway is a genuine npm global — keep npm detect/update.
20
+ * claude-code ships via the native installer (no longer an npm global), so
21
+ * detect from the `claude` binary and update via its native updater.
22
+ */
23
+ export declare const PACKAGES: Record<string, PackageConfig>;
24
+ export interface PackageInfo {
25
+ package: string;
26
+ current: string | null;
27
+ latest: string | null;
28
+ hasUpdate: boolean;
29
+ }
30
+ export declare function getNpmListVersion(packageName: string): string | null;
31
+ /** Resolve the currently-installed version per the package's detect strategy. */
32
+ export declare function resolveCurrent(config: PackageConfig): string | null;
33
+ export declare function updateAvailable(current: string | null, latest: string | null): boolean;
34
+ export declare function getLatestVersion(packageName: string): Promise<string | null>;
35
+ export declare function fetchAllPackageVersions(): Promise<PackageInfo[]>;
36
+ /**
37
+ * Run the package's own native updater (`<bin> update`).
38
+ * Returns null on success, or the updater's error text.
39
+ */
40
+ export declare function runNativeUpdate(config: PackageConfig): string | null;
41
+ /**
42
+ * Install the latest version of an npm-global package.
43
+ *
44
+ * A previously interrupted install can leave `.<pkg>-<hash>` staging dirs in the
45
+ * npm global root that make the next install fail with ENOTEMPTY/ENOTDIR, so
46
+ * those are pre-cleaned and the install is retried once after removing the
47
+ * half-written package directory. Returns null on success, or the error text.
48
+ */
49
+ export declare function installNpmLatest(packageName: string): string | null;
50
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/packages/registry.ts"],"names":[],"mappings":"AAKA;;;;;;;;;GASG;AAYH,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,KAAK,GAAG,QAAQ,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,KAAK,GAAG,QAAQ,CAAC;CAC1B;AAED;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAQlD,CAAC;AAEF,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYpE;AAwBD,iFAAiF;AACjF,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAKnE;AAMD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAEtF;AAED,wBAAsB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAMlF;AAED,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAgBtE;AAsDD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAUpE;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA8BnE"}
@@ -0,0 +1,209 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PACKAGES = void 0;
4
+ exports.getNpmListVersion = getNpmListVersion;
5
+ exports.resolveCurrent = resolveCurrent;
6
+ exports.updateAvailable = updateAvailable;
7
+ exports.getLatestVersion = getLatestVersion;
8
+ exports.fetchAllPackageVersions = fetchAllPackageVersions;
9
+ exports.runNativeUpdate = runNativeUpdate;
10
+ exports.installNpmLatest = installNpmLatest;
11
+ const child_process_1 = require("child_process");
12
+ const fs_1 = require("fs");
13
+ const path_1 = require("path");
14
+ const migrator_1 = require("../config/migrator");
15
+ /**
16
+ * Package id (URL param / CLI noun) → config.
17
+ * claude-gateway is a genuine npm global — keep npm detect/update.
18
+ * claude-code ships via the native installer (no longer an npm global), so
19
+ * detect from the `claude` binary and update via its native updater.
20
+ */
21
+ exports.PACKAGES = {
22
+ 'claude-gateway': { npm: '@0xmaxma/claude-gateway', detect: 'npm', update: 'npm' },
23
+ 'claude-code': {
24
+ npm: '@anthropic-ai/claude-code',
25
+ detect: 'binary',
26
+ bin: 'claude',
27
+ update: 'native',
28
+ },
29
+ };
30
+ function getNpmListVersion(packageName) {
31
+ try {
32
+ const output = (0, child_process_1.execSync)(`npm list -g ${packageName} --depth=0 --json`, {
33
+ encoding: 'utf-8',
34
+ stdio: ['pipe', 'pipe', 'pipe'],
35
+ timeout: 10000,
36
+ });
37
+ const parsed = JSON.parse(output);
38
+ return parsed.dependencies?.[packageName]?.version ?? null;
39
+ }
40
+ catch {
41
+ return null;
42
+ }
43
+ }
44
+ // Resolve the installed version by shelling out to the binary on PATH
45
+ // (e.g. `claude --version` → "2.1.207 (Claude Code)"). Parses the leading
46
+ // semver (with optional prerelease) and returns null on any failure —
47
+ // binary missing, non-zero exit, or unparseable output. `bin` is always a
48
+ // trusted constant from PACKAGES, never request-derived.
49
+ function getBinaryVersion(bin) {
50
+ try {
51
+ const output = (0, child_process_1.execSync)(`${bin} --version`, {
52
+ encoding: 'utf-8',
53
+ stdio: ['pipe', 'pipe', 'pipe'],
54
+ timeout: 10000,
55
+ });
56
+ // `claude --version` prints the version first (e.g. "2.1.207 (Claude Code)").
57
+ // Anchor to the start of the trimmed output so a version-like token later in
58
+ // the line can never be mistaken for the installed version.
59
+ const match = output.trim().match(/^(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)/);
60
+ return match ? match[1] : null;
61
+ }
62
+ catch {
63
+ return null;
64
+ }
65
+ }
66
+ /** Resolve the currently-installed version per the package's detect strategy. */
67
+ function resolveCurrent(config) {
68
+ if (config.detect === 'binary' && config.bin) {
69
+ return getBinaryVersion(config.bin);
70
+ }
71
+ return getNpmListVersion(config.npm);
72
+ }
73
+ // An update is available only when `latest` is strictly newer than `current`.
74
+ // Using semver ordering (not `current !== latest`) avoids a false "update
75
+ // available" when the installed version is *ahead* of the npm-registry latest
76
+ // — e.g. a native-installer channel that leads the npm dist-tag.
77
+ function updateAvailable(current, latest) {
78
+ return !!(current && latest && (0, migrator_1.compareSemver)(latest, current) > 0);
79
+ }
80
+ async function getLatestVersion(packageName) {
81
+ const encodedName = packageName.replace('/', '%2F');
82
+ const res = await fetch(`https://registry.npmjs.org/${encodedName}/latest`);
83
+ if (!res.ok)
84
+ return null;
85
+ const data = (await res.json());
86
+ return data.version ?? null;
87
+ }
88
+ async function fetchAllPackageVersions() {
89
+ const configs = Object.values(exports.PACKAGES);
90
+ // Run all synchronous current-version lookups before entering async Promise.all
91
+ const currents = configs.map(resolveCurrent);
92
+ return Promise.all(configs.map(async (config, i) => {
93
+ const current = currents[i];
94
+ const latest = await getLatestVersion(config.npm);
95
+ return {
96
+ package: config.npm,
97
+ current,
98
+ latest,
99
+ hasUpdate: updateAvailable(current, latest),
100
+ };
101
+ }));
102
+ }
103
+ function getNpmGlobalRoot() {
104
+ return (0, child_process_1.execSync)('npm root -g', {
105
+ encoding: 'utf-8',
106
+ stdio: ['pipe', 'pipe', 'pipe'],
107
+ timeout: 10000,
108
+ }).trim();
109
+ }
110
+ function cleanStaleNpmTempDirs(npmRoot, packageName) {
111
+ const match = packageName.match(/^(@[^/]+)\/(.+)$/);
112
+ if (!match)
113
+ return;
114
+ const [, scope, basename] = match;
115
+ const scopeDir = (0, path_1.join)(npmRoot, scope);
116
+ let entries;
117
+ try {
118
+ entries = (0, fs_1.readdirSync)(scopeDir, { withFileTypes: false });
119
+ }
120
+ catch {
121
+ return;
122
+ }
123
+ const prefix = `.${basename}-`;
124
+ for (const entry of entries) {
125
+ if (entry.startsWith(prefix)) {
126
+ try {
127
+ (0, fs_1.rmSync)((0, path_1.join)(scopeDir, entry), { recursive: true, force: true });
128
+ }
129
+ catch {
130
+ // best-effort: ignore errors on individual temp dir removal
131
+ }
132
+ }
133
+ }
134
+ }
135
+ function removePackageDir(npmRoot, packageName) {
136
+ const match = packageName.match(/^(@[^/]+)\/(.+)$/);
137
+ if (!match)
138
+ return;
139
+ const [, scope, basename] = match;
140
+ try {
141
+ (0, fs_1.rmSync)((0, path_1.join)(npmRoot, scope, basename), { recursive: true, force: true });
142
+ }
143
+ catch {
144
+ // best-effort
145
+ }
146
+ }
147
+ function errorText(err, fallback) {
148
+ return (err.stderr?.toString() ||
149
+ err.message ||
150
+ fallback);
151
+ }
152
+ /**
153
+ * Run the package's own native updater (`<bin> update`).
154
+ * Returns null on success, or the updater's error text.
155
+ */
156
+ function runNativeUpdate(config) {
157
+ // Guarded here as well as at the call sites: without a bin there is no
158
+ // updater to run, and shelling out would execute `undefined update`.
159
+ if (!config.bin)
160
+ return `no native updater configured for ${config.npm}`;
161
+ try {
162
+ (0, child_process_1.execSync)(`${config.bin} update`, { stdio: ['pipe', 'pipe', 'pipe'], timeout: 300000 });
163
+ return null;
164
+ }
165
+ catch (err) {
166
+ return errorText(err, 'update failed');
167
+ }
168
+ }
169
+ /**
170
+ * Install the latest version of an npm-global package.
171
+ *
172
+ * A previously interrupted install can leave `.<pkg>-<hash>` staging dirs in the
173
+ * npm global root that make the next install fail with ENOTEMPTY/ENOTDIR, so
174
+ * those are pre-cleaned and the install is retried once after removing the
175
+ * half-written package directory. Returns null on success, or the error text.
176
+ */
177
+ function installNpmLatest(packageName) {
178
+ let npmRoot = '';
179
+ try {
180
+ npmRoot = getNpmGlobalRoot();
181
+ }
182
+ catch {
183
+ // non-fatal: skip pre-clean if npm root unavailable
184
+ }
185
+ if (npmRoot) {
186
+ cleanStaleNpmTempDirs(npmRoot, packageName);
187
+ }
188
+ try {
189
+ (0, child_process_1.execSync)(`npm install -g ${packageName}@latest`, { stdio: ['pipe', 'pipe', 'pipe'], timeout: 300000 });
190
+ return null;
191
+ }
192
+ catch (err) {
193
+ const stderr = err.stderr?.toString() ?? '';
194
+ if (!npmRoot || !(stderr.includes('ENOTEMPTY') || stderr.includes('ENOTDIR'))) {
195
+ return errorText(err, 'install failed');
196
+ }
197
+ // Remove stale temp dirs and the partially-installed package dir, then retry once
198
+ cleanStaleNpmTempDirs(npmRoot, packageName);
199
+ removePackageDir(npmRoot, packageName);
200
+ try {
201
+ (0, child_process_1.execSync)(`npm install -g ${packageName}@latest`, { stdio: ['pipe', 'pipe', 'pipe'], timeout: 300000 });
202
+ return null;
203
+ }
204
+ catch (retryErr) {
205
+ return errorText(retryErr, 'install failed');
206
+ }
207
+ }
208
+ }
209
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/packages/registry.ts"],"names":[],"mappings":"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"}
@@ -18,6 +18,8 @@ export declare class SessionProcess extends EventEmitter {
18
18
  readonly source: ChatChannelOrApi;
19
19
  private readonly sessionChannel;
20
20
  lastActivityAt: number;
21
+ private lastBackgroundAgentDispatchAt;
22
+ private backgroundWaitTimer;
21
23
  readonly spawnedAt: number;
22
24
  /** Backend used to run the subprocess. Set during start(); 'headless' until then. */
23
25
  backend: 'pty-shell' | 'headless';
@@ -100,9 +102,8 @@ export declare class SessionProcess extends EventEmitter {
100
102
  private resolveSharedKbDir;
101
103
  /**
102
104
  * "1" when the read-path retrieval recorder should log memory_search hits into
103
- * kb_retrieval_log (planning-66) — the LRU/feedback signal the nightly staleness
104
- * GC folds into per-entry recency. Off unless staleness AND recordRetrievals are
105
- * both enabled. Mirrors resolveSharedKbDir's env-gate pattern.
105
+ * kb_retrieval_log. Either enabled lifecycle tier can consume the same
106
+ * append-only log: personal dreaming staleness or shared-KB staleness.
106
107
  */
107
108
  private resolveRecordRetrievals;
108
109
  private buildArgs;
@@ -143,6 +144,13 @@ export declare class SessionProcess extends EventEmitter {
143
144
  sendInput(data: string): boolean;
144
145
  query(prompt: string, timeoutMs?: number): Promise<string>;
145
146
  get isProcessing(): boolean;
147
+ private clearBackgroundWaitTimer;
148
+ /**
149
+ * Extend Telegram's working state only while a parent session is waiting for
150
+ * background Agent/Workflow work. A bounded expiry releases the state if the
151
+ * child task never sends its completion notification.
152
+ */
153
+ retainBackgroundWorkingState(): boolean;
146
154
  setProcessing(active: boolean): void;
147
155
  interrupt(): boolean;
148
156
  /**
@@ -175,6 +183,15 @@ export declare class SessionProcess extends EventEmitter {
175
183
  isRestartScheduled(): boolean;
176
184
  touch(): void;
177
185
  isIdle(idleMs: number): boolean;
186
+ /**
187
+ * True when this session's own turn has ended (not `isProcessing`) but it
188
+ * recently dispatched a BACKGROUND_DISPATCH_TOOLS tool_use — i.e. it looks
189
+ * idle from the outside while a sub-agent it launched may still be doing
190
+ * real work. `restartOrDefer` treats this the same as `isProcessing` so a
191
+ * config-driven restart never SIGKILLs a session mid-dispatch, regardless of
192
+ * which restart tier triggered it.
193
+ */
194
+ hasLikelyOutstandingBackgroundWork(): boolean;
178
195
  isRunning(): boolean;
179
196
  stop(): Promise<void>;
180
197
  }
@@ -1 +1 @@
1
- {"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../src/session/process.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../src/session/process.ts"],"names":[],"mappings":"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"}
@@ -62,6 +62,22 @@ const CHANNEL_REPLY_TOOLS = new Set([
62
62
  'mcp__gateway__discord_reply',
63
63
  'mcp__gateway__line_reply',
64
64
  ]);
65
+ // Tool names whose tool_use dispatches genuinely background work: the call
66
+ // itself returns immediately (a task/agent id), and completion is delivered
67
+ // later as a separate, asynchronously-injected turn (a task-notification) —
68
+ // never as this tool_use's own tool_result. A session that ends its own turn
69
+ // right after dispatching one of these is legitimately idle *from the CLI's
70
+ // perspective* while real work is still in flight elsewhere. See
71
+ // BACKGROUND_AGENT_GRACE_MS and hasLikelyOutstandingBackgroundWork() below.
72
+ const BACKGROUND_DISPATCH_TOOLS = new Set(['Agent', 'Workflow']);
73
+ // How long a session is treated as "may still have outstanding background
74
+ // work" after dispatching one of BACKGROUND_DISPATCH_TOOLS, once its own turn
75
+ // has ended. Generous enough to cover a multi-agent review of a large diff
76
+ // (the incident that motivated this — a config-driven restart SIGHUP'd a
77
+ // session mid-review, killing 3 in-flight review sub-agents with it, see
78
+ // issue referenced in restartOrDefer below); bounded so a dispatch that never
79
+ // reports back (crashed, errored) can't block a config rollout forever.
80
+ const BACKGROUND_AGENT_GRACE_MS = 15 * 60 * 1000;
65
81
  // Shared wording for a turn that ended (gracefully or via a mid-turn exit) with no
66
82
  // assistant text at all — used both to patch the in-memory prompt fed to the next
67
83
  // spawn (buildInitialPrompt below) and, in AgentRunner, to persist a real assistant
@@ -122,6 +138,15 @@ class SessionProcess extends events_1.EventEmitter {
122
138
  constructor(sessionId, source, agentConfig, gatewayConfig, sessionStore, chatId) {
123
139
  super();
124
140
  this.lastActivityAt = Date.now(); // accessible by AgentRunner for eviction sort
141
+ // Wall-clock time of the most recent BACKGROUND_DISPATCH_TOOLS tool_use seen
142
+ // in this session's own turn, while no NEWER turn has started since. Cleared
143
+ // whenever a fresh turn begins (setProcessing(true)) since by then the
144
+ // dispatch either reported back (the notification woke this turn) or has
145
+ // been superseded by unrelated new work — either way the idle-window concern
146
+ // this field exists for no longer applies. Read via
147
+ // hasLikelyOutstandingBackgroundWork().
148
+ this.lastBackgroundAgentDispatchAt = null;
149
+ this.backgroundWaitTimer = null;
125
150
  this.spawnedAt = Date.now();
126
151
  /** Backend used to run the subprocess. Set during start(); 'headless' until then. */
127
152
  this.backend = 'headless';
@@ -443,6 +468,13 @@ class SessionProcess extends events_1.EventEmitter {
443
468
  // Shared KB vault dir (planning-64 K3), so memory_search corpus:"shared"
444
469
  // can reach the cross-agent vault. Empty when shared KB is disabled.
445
470
  GATEWAY_SHARED_KB_DIR: this.resolveSharedKbDir(),
471
+ // The Bun MCP subprocess's own `process.execPath` is the `bun` binary, not
472
+ // `node` — spawning the compiled reindex-cli.js (needs `node:sqlite`) with
473
+ // that would fail (`No such built-in module: node:sqlite`), silently, since
474
+ // memory_shared_create/_update/_delete's reindex trigger runs detached/stdio:'ignore'. Forward the
475
+ // GATEWAY PROCESS's own execPath (real Node, guaranteed >=22 by `engines`) so
476
+ // the mcp side can spawn the CLI with the right runtime.
477
+ GATEWAY_NODE_EXEC_PATH: process.execPath,
446
478
  // planning-66: gate the read-path retrieval recorder (memory_search →
447
479
  // kb_retrieval_log) so the staleness GC's LRU/feedback signal is only
448
480
  // collected when the agent actually runs the GC.
@@ -499,13 +531,13 @@ class SessionProcess extends events_1.EventEmitter {
499
531
  }
500
532
  /**
501
533
  * "1" when the read-path retrieval recorder should log memory_search hits into
502
- * kb_retrieval_log (planning-66) — the LRU/feedback signal the nightly staleness
503
- * GC folds into per-entry recency. Off unless staleness AND recordRetrievals are
504
- * both enabled. Mirrors resolveSharedKbDir's env-gate pattern.
534
+ * kb_retrieval_log. Either enabled lifecycle tier can consume the same
535
+ * append-only log: personal dreaming staleness or shared-KB staleness.
505
536
  */
506
537
  resolveRecordRetrievals() {
507
- const s = (0, config_1.resolveDreamingConfig)(this.agentConfig.dreaming, this.gatewayConfig.gateway.dreaming).staleness;
508
- return s.enabled && s.recordRetrievals ? '1' : '';
538
+ const personal = (0, config_1.resolveDreamingConfig)(this.agentConfig.dreaming, this.gatewayConfig.gateway.dreaming).staleness;
539
+ const shared = (0, knowledge_1.resolveSharedConfig)(this.agentConfig.knowledge?.shared, this.gatewayConfig.gateway.knowledge?.shared).staleness;
540
+ return (personal.enabled && personal.recordRetrievals) || (shared.enabled && shared.recordRetrievals) ? '1' : '';
509
541
  }
510
542
  buildArgs(mcpConfigPath, model) {
511
543
  const args = [
@@ -810,6 +842,19 @@ class SessionProcess extends events_1.EventEmitter {
810
842
  }
811
843
  lastPartialText = '';
812
844
  }
845
+ // Record a background-dispatch tool_use (see BACKGROUND_DISPATCH_TOOLS)
846
+ // so restartOrDefer can tell "genuinely idle" apart from "idle because
847
+ // it just fired off async work and is waiting on a task-notification".
848
+ // Only the final (non-partial) message carries a fully materialised
849
+ // tool_use block, same as the reply-mirror check above.
850
+ if (!isPartial && !this.queryMode) {
851
+ for (const block of obj.message.content) {
852
+ if (block.type === 'tool_use' && BACKGROUND_DISPATCH_TOOLS.has(block.name)) {
853
+ this.lastBackgroundAgentDispatchAt = Date.now();
854
+ break;
855
+ }
856
+ }
857
+ }
813
858
  // Mirror channel replies (telegram_reply/discord_reply/line_reply) into
814
859
  // the resumable session store at delivery time. The user-facing text is
815
860
  // carried in the tool_use input, not a text block, so assistantBuffer
@@ -991,6 +1036,8 @@ class SessionProcess extends events_1.EventEmitter {
991
1036
  pty_stream_registry_1.ptyStreamRegistry.close(ptyStreamSocketPath);
992
1037
  this.process = null;
993
1038
  this._exited = true;
1039
+ this.lastBackgroundAgentDispatchAt = null;
1040
+ this.clearBackgroundWaitTimer();
994
1041
  // Notify listeners that the underlying subprocess died. The runner relies
995
1042
  // on this to tear down per-chat typing/processing state when a session is
996
1043
  // stopped or restarted mid-turn (without a final result/session_idle).
@@ -1221,9 +1268,60 @@ class SessionProcess extends events_1.EventEmitter {
1221
1268
  });
1222
1269
  }
1223
1270
  get isProcessing() { return this._processing; }
1271
+ clearBackgroundWaitTimer() {
1272
+ if (this.backgroundWaitTimer !== null) {
1273
+ clearTimeout(this.backgroundWaitTimer);
1274
+ this.backgroundWaitTimer = null;
1275
+ }
1276
+ }
1277
+ /**
1278
+ * Extend Telegram's working state only while a parent session is waiting for
1279
+ * background Agent/Workflow work. A bounded expiry releases the state if the
1280
+ * child task never sends its completion notification.
1281
+ */
1282
+ retainBackgroundWorkingState() {
1283
+ if (this.source !== 'telegram' || !this.hasLikelyOutstandingBackgroundWork())
1284
+ return false;
1285
+ const processingPath = path.join(this.typingDir, `${this.chatId}.processing`);
1286
+ try {
1287
+ fs.mkdirSync(this.typingDir, { recursive: true });
1288
+ fs.writeFileSync(processingPath, String(Date.now()));
1289
+ }
1290
+ catch (err) {
1291
+ this.logger.warn('Failed to retain .processing sentinel for background work', {
1292
+ chatId: this.chatId,
1293
+ error: err.message,
1294
+ });
1295
+ }
1296
+ if (this.backgroundWaitTimer === null) {
1297
+ const elapsed = Date.now() - this.lastBackgroundAgentDispatchAt;
1298
+ const remaining = Math.max(0, BACKGROUND_AGENT_GRACE_MS - elapsed);
1299
+ this.backgroundWaitTimer = setTimeout(() => {
1300
+ this.backgroundWaitTimer = null;
1301
+ this.lastBackgroundAgentDispatchAt = null;
1302
+ if (!this._processing) {
1303
+ try {
1304
+ fs.rmSync(processingPath, { force: true });
1305
+ }
1306
+ catch { }
1307
+ this.emit('backgroundWorkExpired');
1308
+ }
1309
+ }, remaining);
1310
+ this.backgroundWaitTimer.unref();
1311
+ }
1312
+ return true;
1313
+ }
1224
1314
  setProcessing(active) {
1225
1315
  if (this._processing !== active) {
1226
1316
  this._processing = active;
1317
+ if (active) {
1318
+ // A fresh turn is starting — either the notification this dispatch was
1319
+ // waiting on just woke it (resolved), or unrelated new work superseded
1320
+ // it (moot either way). isProcessing now covers this session correctly
1321
+ // on its own, so the idle-window concern this field exists for is over.
1322
+ this.lastBackgroundAgentDispatchAt = null;
1323
+ this.clearBackgroundWaitTimer();
1324
+ }
1227
1325
  this.emit('processingChange', active);
1228
1326
  if (this.source === 'telegram') {
1229
1327
  const processingPath = path.join(this.typingDir, `${this.chatId}.processing`);
@@ -1306,6 +1404,21 @@ class SessionProcess extends events_1.EventEmitter {
1306
1404
  isIdle(idleMs) {
1307
1405
  return Date.now() - this.lastActivityAt > idleMs;
1308
1406
  }
1407
+ /**
1408
+ * True when this session's own turn has ended (not `isProcessing`) but it
1409
+ * recently dispatched a BACKGROUND_DISPATCH_TOOLS tool_use — i.e. it looks
1410
+ * idle from the outside while a sub-agent it launched may still be doing
1411
+ * real work. `restartOrDefer` treats this the same as `isProcessing` so a
1412
+ * config-driven restart never SIGKILLs a session mid-dispatch, regardless of
1413
+ * which restart tier triggered it.
1414
+ */
1415
+ hasLikelyOutstandingBackgroundWork() {
1416
+ if (this._processing)
1417
+ return false;
1418
+ if (this.lastBackgroundAgentDispatchAt === null)
1419
+ return false;
1420
+ return Date.now() - this.lastBackgroundAgentDispatchAt < BACKGROUND_AGENT_GRACE_MS;
1421
+ }
1309
1422
  isRunning() {
1310
1423
  // Use _exited (child's 'exit' observed), NOT .killed — .killed is true after
1311
1424
  // any signal send, including a /stop SIGINT the pty-shell survives, which
@@ -1314,6 +1427,8 @@ class SessionProcess extends events_1.EventEmitter {
1314
1427
  }
1315
1428
  async stop() {
1316
1429
  this.stopping = true;
1430
+ this.lastBackgroundAgentDispatchAt = null;
1431
+ this.clearBackgroundWaitTimer();
1317
1432
  await this.restartWatcher?.close();
1318
1433
  this.restartWatcher = null;
1319
1434
  try {