@gmickel/gno 1.46.0 → 2.0.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 (230) hide show
  1. package/README.md +1 -1
  2. package/THIRD_PARTY_NOTICES.md +46 -0
  3. package/assets/skill/SKILL.md +7 -6
  4. package/assets/spa-production.json.gz +0 -0
  5. package/browser-extension/artifacts/gno-browser-clipper-v2.0.0.zip +0 -0
  6. package/browser-extension/artifacts/gno-browser-clipper-v2.0.0.zip.sha256 +1 -0
  7. package/browser-extension/dist/chunk-4tc9v0ja.js +74 -0
  8. package/browser-extension/dist/manifest.json +1 -1
  9. package/browser-extension/dist/preview.html +1 -1
  10. package/browser-extension/dist/service-worker.js +32 -33
  11. package/bunfig.toml +2 -0
  12. package/package.json +40 -26
  13. package/spec/cli.md +21 -4
  14. package/spec/db/schema.sql +146 -1
  15. package/spec/mcp.md +26 -0
  16. package/src/app/context-runtime-types.ts +3 -0
  17. package/src/app/context-runtime.ts +2 -0
  18. package/src/cli/commands/ask.ts +6 -1
  19. package/src/cli/commands/daemon.ts +21 -8
  20. package/src/cli/commands/embed.ts +77 -41
  21. package/src/cli/detach.ts +3 -2
  22. package/src/config/types.ts +3 -3
  23. package/src/converters/adapters/markitdownTs/adapter.ts +1 -2
  24. package/src/converters/adapters/officeparser/adapter.ts +1 -2
  25. package/src/converters/versions.ts +6 -8
  26. package/src/core/context-evidence.ts +8 -4
  27. package/src/core/job-manager.ts +95 -13
  28. package/src/core/network-boundary-inventory.ts +10 -0
  29. package/src/core/shutdown-budget.ts +45 -0
  30. package/src/embed/backlog.ts +107 -4
  31. package/src/embed/batch.ts +42 -2
  32. package/src/embed/fingerprint.ts +16 -0
  33. package/src/embed/retry.ts +113 -5
  34. package/src/embed/variant-backlog.ts +105 -0
  35. package/src/embed/variant-plan.ts +62 -0
  36. package/src/embed/variant-retry.ts +113 -0
  37. package/src/ingestion/graph-reconciliation.ts +327 -0
  38. package/src/ingestion/sync.ts +9 -272
  39. package/src/llm/http-inference.ts +6 -0
  40. package/src/llm/httpEmbedding.ts +37 -6
  41. package/src/llm/httpGeneration.ts +18 -3
  42. package/src/llm/httpRerank.ts +23 -5
  43. package/src/llm/inference-cancellation.ts +168 -0
  44. package/src/llm/inference-scope.ts +202 -0
  45. package/src/llm/lazy-ports.ts +115 -0
  46. package/src/llm/native-worker/client.ts +541 -0
  47. package/src/llm/native-worker/dispatcher.ts +228 -0
  48. package/src/llm/native-worker/embedding-identity.ts +33 -0
  49. package/src/llm/native-worker/entry.ts +173 -0
  50. package/src/llm/native-worker/errors.ts +32 -0
  51. package/src/llm/native-worker/evaluation.ts +16 -0
  52. package/src/llm/native-worker/owned-exit.ts +108 -0
  53. package/src/llm/native-worker/owner.ts +141 -0
  54. package/src/llm/native-worker/ports.ts +317 -0
  55. package/src/llm/native-worker/protocol.ts +442 -0
  56. package/src/llm/native-worker/runtime-config.ts +92 -0
  57. package/src/llm/nodeLlamaCpp/adapter.ts +77 -20
  58. package/src/llm/nodeLlamaCpp/embedding.ts +130 -46
  59. package/src/llm/nodeLlamaCpp/generation.ts +34 -5
  60. package/src/llm/nodeLlamaCpp/lifecycle-options.ts +99 -0
  61. package/src/llm/nodeLlamaCpp/lifecycle.ts +209 -204
  62. package/src/llm/nodeLlamaCpp/rerank-capacity.ts +111 -0
  63. package/src/llm/nodeLlamaCpp/rerank.ts +118 -27
  64. package/src/llm/nodeLlamaCpp/simulator-handle.ts +73 -0
  65. package/src/llm/nodeLlamaCpp/simulator-install.ts +124 -0
  66. package/src/llm/nodeLlamaCpp/simulator-session.ts +240 -0
  67. package/src/llm/nodeLlamaCpp/simulator-types.ts +80 -0
  68. package/src/llm/types.ts +35 -5
  69. package/src/mcp/context.ts +27 -0
  70. package/src/mcp/http-transport.ts +12 -10
  71. package/src/mcp/server.ts +3 -0
  72. package/src/mcp/tool-profile.ts +30 -8
  73. package/src/mcp/tools/context.ts +8 -11
  74. package/src/mcp/tools/embed.ts +1 -1
  75. package/src/mcp/tools/index-cmd.ts +1 -1
  76. package/src/mcp/tools/index.ts +10 -8
  77. package/src/mcp/tools/query.ts +14 -30
  78. package/src/mcp/tools/vsearch.ts +1 -1
  79. package/src/pipeline/answer.ts +23 -3
  80. package/src/pipeline/claim-verifier.ts +6 -0
  81. package/src/pipeline/expansion.ts +43 -40
  82. package/src/pipeline/explain.ts +6 -2
  83. package/src/pipeline/filters.ts +63 -0
  84. package/src/pipeline/fusion.ts +29 -9
  85. package/src/pipeline/graph-retrieval.ts +29 -9
  86. package/src/pipeline/hybrid.ts +198 -55
  87. package/src/pipeline/hydration.ts +161 -0
  88. package/src/pipeline/owner-fusion.ts +87 -0
  89. package/src/pipeline/rerank.ts +35 -11
  90. package/src/pipeline/search.ts +13 -2
  91. package/src/pipeline/types.ts +5 -3
  92. package/src/pipeline/vsearch.ts +87 -7
  93. package/src/sdk/client.ts +47 -3
  94. package/src/sdk/embed.ts +63 -39
  95. package/src/serve/background-runtime.ts +1 -1
  96. package/src/serve/context.ts +41 -56
  97. package/src/serve/embed-scheduler.ts +58 -35
  98. package/src/serve/public/components/IndexingProgress.tsx +46 -60
  99. package/src/serve/public/globals.built.css +1 -1
  100. package/src/serve/public/lib/shiki-language-ids.ts +14 -0
  101. package/src/serve/resident-admission.ts +36 -36
  102. package/src/serve/resident-background-work.ts +20 -2
  103. package/src/serve/resident-request.ts +11 -5
  104. package/src/serve/resident-runtime.ts +97 -61
  105. package/src/serve/resident-shutdown.ts +153 -0
  106. package/src/serve/routes/api.ts +3 -1
  107. package/src/serve/server.ts +47 -26
  108. package/src/store/migrations/028-vector-variants.ts +54 -0
  109. package/src/store/migrations/029-graph-reference-state.ts +77 -0
  110. package/src/store/migrations/index.ts +4 -0
  111. package/src/store/sqlite/adapter.ts +251 -183
  112. package/src/store/sqlite/eligibility.ts +174 -0
  113. package/src/store/sqlite/graph-edge-application.ts +66 -0
  114. package/src/store/sqlite/graph-reference-state.ts +194 -0
  115. package/src/store/sqlite/legacy-vector-ownership.ts +79 -0
  116. package/src/store/types.ts +80 -12
  117. package/src/store/vector/eligibility.ts +36 -0
  118. package/src/store/vector/freshness.ts +33 -6
  119. package/src/store/vector/lazy.ts +81 -0
  120. package/src/store/vector/sqlite-vec.ts +106 -54
  121. package/src/store/vector/stats.ts +14 -3
  122. package/src/store/vector/types.ts +35 -2
  123. package/src/store/vector/variant-search.ts +192 -0
  124. package/src/store/vector/variants.ts +451 -0
  125. package/vendor/converters/markitdown-ts/LICENSE +21 -0
  126. package/vendor/converters/markitdown-ts/dist/index.cjs +1180 -0
  127. package/vendor/converters/markitdown-ts/dist/index.d.cts +46 -0
  128. package/vendor/converters/markitdown-ts/dist/index.d.mts +46 -0
  129. package/vendor/converters/markitdown-ts/dist/index.d.ts +46 -0
  130. package/vendor/converters/markitdown-ts/dist/index.mjs +1152 -0
  131. package/vendor/converters/markitdown-ts/package.json +77 -0
  132. package/vendor/converters/officeparser/LICENSE +21 -0
  133. package/vendor/converters/officeparser/dist/OfficeConverter.d.ts +47 -0
  134. package/vendor/converters/officeparser/dist/OfficeConverter.js +76 -0
  135. package/vendor/converters/officeparser/dist/OfficeGenerator.d.ts +23 -0
  136. package/vendor/converters/officeparser/dist/OfficeGenerator.js +73 -0
  137. package/vendor/converters/officeparser/dist/OfficeParser.d.ts +106 -0
  138. package/vendor/converters/officeparser/dist/OfficeParser.js +332 -0
  139. package/vendor/converters/officeparser/dist/cli.d.ts +28 -0
  140. package/vendor/converters/officeparser/dist/cli.js +381 -0
  141. package/vendor/converters/officeparser/dist/defaults.d.ts +41 -0
  142. package/vendor/converters/officeparser/dist/defaults.js +218 -0
  143. package/vendor/converters/officeparser/dist/generators/BaseGenerator.d.ts +107 -0
  144. package/vendor/converters/officeparser/dist/generators/BaseGenerator.js +248 -0
  145. package/vendor/converters/officeparser/dist/generators/ChunkingGenerator.d.ts +82 -0
  146. package/vendor/converters/officeparser/dist/generators/ChunkingGenerator.js +797 -0
  147. package/vendor/converters/officeparser/dist/generators/CsvGenerator.d.ts +38 -0
  148. package/vendor/converters/officeparser/dist/generators/CsvGenerator.js +245 -0
  149. package/vendor/converters/officeparser/dist/generators/EpubGenerator.d.ts +43 -0
  150. package/vendor/converters/officeparser/dist/generators/EpubGenerator.js +315 -0
  151. package/vendor/converters/officeparser/dist/generators/HtmlGenerator.d.ts +59 -0
  152. package/vendor/converters/officeparser/dist/generators/HtmlGenerator.js +1942 -0
  153. package/vendor/converters/officeparser/dist/generators/MarkdownGenerator.d.ts +96 -0
  154. package/vendor/converters/officeparser/dist/generators/MarkdownGenerator.js +1175 -0
  155. package/vendor/converters/officeparser/dist/generators/PdfGenerator.d.ts +22 -0
  156. package/vendor/converters/officeparser/dist/generators/PdfGenerator.js +194 -0
  157. package/vendor/converters/officeparser/dist/generators/RtfGenerator.d.ts +29 -0
  158. package/vendor/converters/officeparser/dist/generators/RtfGenerator.js +316 -0
  159. package/vendor/converters/officeparser/dist/generators/TextGenerator.d.ts +13 -0
  160. package/vendor/converters/officeparser/dist/generators/TextGenerator.js +201 -0
  161. package/vendor/converters/officeparser/dist/index.d.ts +60 -0
  162. package/vendor/converters/officeparser/dist/index.js +72 -0
  163. package/vendor/converters/officeparser/dist/index.mjs +18 -0
  164. package/vendor/converters/officeparser/dist/officeparser.browser.d.ts +2621 -0
  165. package/vendor/converters/officeparser/dist/officeparser.browser.iife.js +1336 -0
  166. package/vendor/converters/officeparser/dist/officeparser.browser.mjs +1335 -0
  167. package/vendor/converters/officeparser/dist/officeparser.browser.slim.d.ts +2621 -0
  168. package/vendor/converters/officeparser/dist/officeparser.browser.slim.iife.js +1336 -0
  169. package/vendor/converters/officeparser/dist/officeparser.browser.slim.mjs +1335 -0
  170. package/vendor/converters/officeparser/dist/parsers/CsvParser.d.ts +9 -0
  171. package/vendor/converters/officeparser/dist/parsers/CsvParser.js +115 -0
  172. package/vendor/converters/officeparser/dist/parsers/EpubParser.d.ts +8 -0
  173. package/vendor/converters/officeparser/dist/parsers/EpubParser.js +217 -0
  174. package/vendor/converters/officeparser/dist/parsers/ExcelParser.d.ts +32 -0
  175. package/vendor/converters/officeparser/dist/parsers/ExcelParser.js +736 -0
  176. package/vendor/converters/officeparser/dist/parsers/HtmlParser.d.ts +2 -0
  177. package/vendor/converters/officeparser/dist/parsers/HtmlParser.js +1287 -0
  178. package/vendor/converters/officeparser/dist/parsers/MarkdownParser.d.ts +2 -0
  179. package/vendor/converters/officeparser/dist/parsers/MarkdownParser.js +1272 -0
  180. package/vendor/converters/officeparser/dist/parsers/OpenOfficeParser.d.ts +31 -0
  181. package/vendor/converters/officeparser/dist/parsers/OpenOfficeParser.js +1819 -0
  182. package/vendor/converters/officeparser/dist/parsers/PdfParser.d.ts +67 -0
  183. package/vendor/converters/officeparser/dist/parsers/PdfParser.js +848 -0
  184. package/vendor/converters/officeparser/dist/parsers/PowerPointParser.d.ts +32 -0
  185. package/vendor/converters/officeparser/dist/parsers/PowerPointParser.js +950 -0
  186. package/vendor/converters/officeparser/dist/parsers/RtfParser.d.ts +187 -0
  187. package/vendor/converters/officeparser/dist/parsers/RtfParser.js +1801 -0
  188. package/vendor/converters/officeparser/dist/parsers/WordParser.d.ts +79 -0
  189. package/vendor/converters/officeparser/dist/parsers/WordParser.js +1177 -0
  190. package/vendor/converters/officeparser/dist/sbom.cdx.json +1763 -0
  191. package/vendor/converters/officeparser/dist/types.d.ts +2507 -0
  192. package/vendor/converters/officeparser/dist/types.js +107 -0
  193. package/vendor/converters/officeparser/dist/utils/astUtils.d.ts +16 -0
  194. package/vendor/converters/officeparser/dist/utils/astUtils.js +33 -0
  195. package/vendor/converters/officeparser/dist/utils/chartUtils.d.ts +6 -0
  196. package/vendor/converters/officeparser/dist/utils/chartUtils.js +257 -0
  197. package/vendor/converters/officeparser/dist/utils/configUtils.d.ts +44 -0
  198. package/vendor/converters/officeparser/dist/utils/configUtils.js +315 -0
  199. package/vendor/converters/officeparser/dist/utils/dateUtils.d.ts +17 -0
  200. package/vendor/converters/officeparser/dist/utils/dateUtils.js +69 -0
  201. package/vendor/converters/officeparser/dist/utils/envUtils.d.ts +29 -0
  202. package/vendor/converters/officeparser/dist/utils/envUtils.js +152 -0
  203. package/vendor/converters/officeparser/dist/utils/errorUtils.d.ts +72 -0
  204. package/vendor/converters/officeparser/dist/utils/errorUtils.js +245 -0
  205. package/vendor/converters/officeparser/dist/utils/imageUtils.d.ts +66 -0
  206. package/vendor/converters/officeparser/dist/utils/imageUtils.js +133 -0
  207. package/vendor/converters/officeparser/dist/utils/mathUtils.d.ts +42 -0
  208. package/vendor/converters/officeparser/dist/utils/mathUtils.js +385 -0
  209. package/vendor/converters/officeparser/dist/utils/moduleLoader.d.ts +18 -0
  210. package/vendor/converters/officeparser/dist/utils/moduleLoader.js +106 -0
  211. package/vendor/converters/officeparser/dist/utils/ocrUtils.d.ts +42 -0
  212. package/vendor/converters/officeparser/dist/utils/ocrUtils.js +428 -0
  213. package/vendor/converters/officeparser/dist/utils/sanitize.d.ts +148 -0
  214. package/vendor/converters/officeparser/dist/utils/sanitize.js +344 -0
  215. package/vendor/converters/officeparser/dist/utils/sheetUtils.d.ts +7 -0
  216. package/vendor/converters/officeparser/dist/utils/sheetUtils.js +35 -0
  217. package/vendor/converters/officeparser/dist/utils/styleMapper.d.ts +36 -0
  218. package/vendor/converters/officeparser/dist/utils/styleMapper.js +224 -0
  219. package/vendor/converters/officeparser/dist/utils/xmlUtils.d.ts +163 -0
  220. package/vendor/converters/officeparser/dist/utils/xmlUtils.js +461 -0
  221. package/vendor/converters/officeparser/dist/utils/zipUtils.d.ts +134 -0
  222. package/vendor/converters/officeparser/dist/utils/zipUtils.js +337 -0
  223. package/vendor/converters/officeparser/package.json +147 -0
  224. package/vendor/converters/upstream-manifest.json +124 -0
  225. package/vendor/dependency-fixes/README.md +77 -0
  226. package/vendor/dependency-fixes/vendor-converters.py +83 -0
  227. package/browser-extension/artifacts/gno-browser-clipper-v1.46.0.zip +0 -0
  228. package/browser-extension/artifacts/gno-browser-clipper-v1.46.0.zip.sha256 +0 -1
  229. package/browser-extension/dist/chunk-627emwpj.js +0 -75
  230. /package/browser-extension/dist/{chunk-ydfx5d7p.css → chunk-z74y8n8c.css} +0 -0
@@ -0,0 +1,240 @@
1
+ /** Guarded simulator section from node-llama-cpp PR636 (MIT, Gilad S.).
2
+ * See simulator-handle.ts and THIRD_PARTY_NOTICES.md for source attribution.
3
+ * Retained on 3.20.0 for failed-load cleanup and joined session disposal,
4
+ * beyond upstream PR636. Estimation inputs and selection remain unchanged.
5
+ */
6
+ import type {
7
+ SimulatorBackend,
8
+ SimulatorCache,
9
+ SimulatorContextOptions,
10
+ SimulatorDependencies,
11
+ SimulatorDisposable,
12
+ SimulatorMemory,
13
+ SimulatorModelOptions,
14
+ } from "./simulator-types";
15
+
16
+ import { SimulatorModelHandle } from "./simulator-handle";
17
+
18
+ function defined(options: Record<string, unknown>): Record<string, unknown> {
19
+ return Object.fromEntries(
20
+ Object.entries(options).filter(([, value]) => value !== undefined)
21
+ );
22
+ }
23
+
24
+ export class GuardedSimulatorSession {
25
+ private readonly models: SimulatorCache<Promise<SimulatorModelHandle>>;
26
+ private isDisposed = false;
27
+ private disposal?: Promise<void>;
28
+
29
+ constructor(
30
+ private readonly llama: SimulatorBackend,
31
+ private readonly dependencies: SimulatorDependencies,
32
+ lruCacheSize = 10,
33
+ private readonly loadModelError?: Error
34
+ ) {
35
+ this.models = new dependencies.LruCache(lruCacheSize, {
36
+ async onDelete(_key, value) {
37
+ try {
38
+ const handle = await value;
39
+ // Give queued consumers the same acquisition turn as upstream PR636.
40
+ await Promise.resolve();
41
+ await handle.dispose();
42
+ } catch {
43
+ /* Failed loads have no live cached handle. */
44
+ }
45
+ },
46
+ });
47
+ }
48
+
49
+ async estimateModelResources({
50
+ modelSource,
51
+ gpuLayers,
52
+ useMmap = false,
53
+ }: SimulatorModelOptions): Promise<SimulatorMemory> {
54
+ const handle = await this.getModel({ modelSource, gpuLayers, useMmap });
55
+ const lease = this.acquire(handle);
56
+ try {
57
+ const result = handle.model.getMemoryBreakdown();
58
+ if (this.llama._shouldLog(this.dependencies.debug))
59
+ this.llama._log(
60
+ this.dependencies.debug,
61
+ `Simulating model resource usage. gpuLayers=${gpuLayers} useMmap=${useMmap} memoryBreakdownCpuRam=${this.dependencies.bytes(result.cpuRam)} memoryBreakdownGpuVram=${this.dependencies.bytes(result.gpuVram)}`
62
+ );
63
+ return result;
64
+ } finally {
65
+ await lease.dispose();
66
+ }
67
+ }
68
+
69
+ async estimateContextResources({
70
+ modelSource,
71
+ gpuLayers,
72
+ contextSize,
73
+ batchSize,
74
+ sequences,
75
+ isEmbeddingContext = false,
76
+ flashAttention = "auto",
77
+ swaFullCache = false,
78
+ useMmap = false,
79
+ kvCacheKeyType = this.dependencies.f16,
80
+ kvCacheValueType = this.dependencies.f16,
81
+ }: SimulatorContextOptions): Promise<SimulatorMemory> {
82
+ const handle = await this.getModel({ modelSource, gpuLayers, useMmap });
83
+ const lease = this.acquire(handle);
84
+ try {
85
+ const context = new this.llama._bindings.AddonContext(
86
+ handle.model,
87
+ defined({
88
+ contextSize,
89
+ batchSize,
90
+ sequences,
91
+ embeddings: isEmbeddingContext,
92
+ flashAttention,
93
+ kvCacheKeyType,
94
+ kvCacheValueType,
95
+ swaFullCache,
96
+ })
97
+ );
98
+ try {
99
+ const loadingLock = this.dependencies.needInitLock(this.llama.gpu)
100
+ ? await this.dependencies.acquireLock([
101
+ this.llama._memoryLock,
102
+ this.dependencies.addonInit,
103
+ ])
104
+ : undefined;
105
+ const restoreLog = this.llama._createLogLevelOverride(
106
+ this.dependencies.error
107
+ );
108
+ try {
109
+ if (!(await context.init()))
110
+ throw new Error("Failed to create context");
111
+ } finally {
112
+ restoreLog();
113
+ await loadingLock?.dispose();
114
+ }
115
+ const result = context.getMemoryBreakdown();
116
+ if (this.llama._shouldLog(this.dependencies.debug))
117
+ this.llama._log(
118
+ this.dependencies.debug,
119
+ `Simulating context resource usage. gpuLayers=${gpuLayers} contextSize=${contextSize.toLocaleString("en-US", { notation: "compact" })} batchSize=${batchSize} sequences=${sequences} isEmbeddingContext=${isEmbeddingContext} flashAttention=${flashAttention} swaFullCache=${swaFullCache} kvCacheKeyType=${kvCacheKeyType} kvCacheValueType=${kvCacheValueType} useMmap=${useMmap} memoryBreakdownCpuRam=${this.dependencies.bytes(result.cpuRam)} memoryBreakdownGpuVram=${this.dependencies.bytes(result.gpuVram)}`
120
+ );
121
+ return result;
122
+ } finally {
123
+ await context.dispose();
124
+ }
125
+ } finally {
126
+ await lease.dispose();
127
+ }
128
+ }
129
+
130
+ get disposed(): boolean {
131
+ return this.isDisposed;
132
+ }
133
+ [Symbol.asyncDispose](): Promise<void> {
134
+ return this.dispose();
135
+ }
136
+
137
+ dispose(): Promise<void> {
138
+ this.disposal ??= this.disposeInternal();
139
+ return this.disposal;
140
+ }
141
+
142
+ private async disposeInternal(): Promise<void> {
143
+ this.isDisposed = true;
144
+ const pending = [...this.models.values()];
145
+ this.models.clear();
146
+ const handles = await Promise.all(
147
+ pending.map((value) => value.catch(() => undefined))
148
+ );
149
+ await Promise.all(handles.map((handle) => handle?.dispose()));
150
+ }
151
+
152
+ private acquire(handle: SimulatorModelHandle): SimulatorDisposable {
153
+ try {
154
+ return handle.disposeGuard.createPreventDisposalHandle();
155
+ } catch {
156
+ throw new Error("Model is disposed");
157
+ }
158
+ }
159
+
160
+ private async getModel({
161
+ modelSource,
162
+ gpuLayers,
163
+ useMmap = this.llama.supportsMmap,
164
+ }: SimulatorModelOptions): Promise<SimulatorModelHandle> {
165
+ if (this.isDisposed) throw new Error("simulator session is disposed");
166
+ if (this.loadModelError) throw this.loadModelError;
167
+ let backendHandle: SimulatorDisposable;
168
+ try {
169
+ backendHandle =
170
+ this.llama._backendDisposeGuard.createPreventDisposalHandle();
171
+ } catch {
172
+ throw new Error("Llama instance is disposed");
173
+ }
174
+ try {
175
+ const key = `${gpuLayers}:${useMmap}`;
176
+ const existing = this.models.get(key);
177
+ if (existing) return await existing;
178
+ if (this.llama._shouldLog(this.dependencies.debug))
179
+ this.llama._log(
180
+ this.dependencies.debug,
181
+ `Loading model for simulator session. gpuLayers=${gpuLayers} useMmap=${useMmap}`
182
+ );
183
+ const pending = this.loadModel({ modelSource, gpuLayers, useMmap });
184
+ this.models.set(key, pending);
185
+ try {
186
+ return await pending;
187
+ } catch (error) {
188
+ this.models.delete(key);
189
+ throw error;
190
+ }
191
+ } finally {
192
+ await backendHandle.dispose();
193
+ }
194
+ }
195
+
196
+ private async loadModel({
197
+ modelSource,
198
+ gpuLayers,
199
+ useMmap = false,
200
+ }: SimulatorModelOptions): Promise<SimulatorModelHandle> {
201
+ const model = new this.llama._bindings.AddonModel(
202
+ typeof modelSource === "string" ? modelSource : "",
203
+ {
204
+ gpuLayers,
205
+ noAlloc: true,
206
+ useMmap,
207
+ useMlock: false,
208
+ }
209
+ );
210
+ const loadingLock = this.dependencies.needInitLock(this.llama.gpu)
211
+ ? await this.dependencies.acquireLock([
212
+ this.llama._memoryLock,
213
+ this.dependencies.addonInit,
214
+ ])
215
+ : undefined;
216
+ const restoreLog = this.llama._createLogLevelOverride(
217
+ this.dependencies.error
218
+ );
219
+ try {
220
+ if (
221
+ !(await (typeof modelSource === "string"
222
+ ? model.init()
223
+ : model.init(modelSource)))
224
+ )
225
+ throw new Error("Failed to load model");
226
+ } catch (error) {
227
+ await model.dispose().catch(() => {});
228
+ throw error;
229
+ } finally {
230
+ restoreLog();
231
+ await loadingLock?.dispose();
232
+ }
233
+ try {
234
+ return new SimulatorModelHandle(this.llama, model, this.dependencies);
235
+ } catch (error) {
236
+ await model.dispose().catch(() => {});
237
+ throw error;
238
+ }
239
+ }
240
+ }
@@ -0,0 +1,80 @@
1
+ /** Private compatibility shapes pinned to node-llama-cpp 3.20.0. */
2
+ export interface SimulatorDisposable {
3
+ dispose(): void | Promise<void>;
4
+ }
5
+ export interface SimulatorGuard {
6
+ createPreventDisposalHandle(): SimulatorDisposable;
7
+ acquireDisposeLock(): Promise<void>;
8
+ }
9
+ export interface SimulatorMemory {
10
+ cpuRam: number;
11
+ gpuVram: number;
12
+ }
13
+ export interface SimulatorModel {
14
+ init(source?: unknown): Promise<boolean>;
15
+ getMemoryBreakdown(): SimulatorMemory;
16
+ dispose(): Promise<void>;
17
+ }
18
+ export interface SimulatorContext {
19
+ init(): Promise<boolean>;
20
+ getMemoryBreakdown(): SimulatorMemory;
21
+ dispose(): Promise<void>;
22
+ }
23
+ export interface SimulatorBackend {
24
+ gpu: string | false;
25
+ supportsMmap: boolean;
26
+ _memoryLock: object;
27
+ _backendDisposeGuard: SimulatorGuard;
28
+ _bindings: {
29
+ AddonModel: new (
30
+ source: string,
31
+ options: Record<string, unknown>
32
+ ) => SimulatorModel;
33
+ AddonContext: new (
34
+ model: SimulatorModel,
35
+ options: Record<string, unknown>
36
+ ) => SimulatorContext;
37
+ };
38
+ onDispose: {
39
+ createListener(callback: () => void | Promise<void>): SimulatorDisposable;
40
+ };
41
+ _createLogLevelOverride(level: string): () => void;
42
+ _shouldLog(level: string): boolean;
43
+ _log(level: string, message: string): void;
44
+ }
45
+ export interface SimulatorCache<T> {
46
+ get(key: string): T | undefined;
47
+ set(key: string, value: T): unknown;
48
+ delete(key: string): unknown;
49
+ clear(): void;
50
+ values(): IterableIterator<T>;
51
+ }
52
+ export interface SimulatorDependencies {
53
+ DisposeGuard: new (parents: SimulatorGuard[]) => SimulatorGuard;
54
+ LruCache: new <T>(
55
+ size: number,
56
+ options?: { onDelete(key: string, value: T): Promise<void> }
57
+ ) => SimulatorCache<T>;
58
+ acquireLock(keys: unknown[]): Promise<SimulatorDisposable>;
59
+ needInitLock(gpu: string | false): boolean;
60
+ addonInit: string;
61
+ debug: string;
62
+ error: string;
63
+ f16: number;
64
+ bytes(value: number): string;
65
+ }
66
+ export interface SimulatorModelOptions {
67
+ modelSource: unknown;
68
+ gpuLayers: number;
69
+ useMmap?: boolean;
70
+ }
71
+ export interface SimulatorContextOptions extends SimulatorModelOptions {
72
+ contextSize: number;
73
+ batchSize: number;
74
+ sequences: number;
75
+ isEmbeddingContext?: boolean;
76
+ flashAttention?: boolean | "auto";
77
+ swaFullCache?: boolean;
78
+ kvCacheKeyType?: number;
79
+ kvCacheValueType?: number;
80
+ }
package/src/llm/types.ts CHANGED
@@ -15,6 +15,15 @@ export type LlmResult<T> =
15
15
  | { ok: true; value: T }
16
16
  | { ok: false; error: LlmError };
17
17
 
18
+ /** Optional caller lifetime; distinct from the configured native execution timeout.
19
+ * Adapters must retain native ownership until work settles, even after abort.
20
+ */
21
+ export interface InferenceOptions {
22
+ signal?: AbortSignal;
23
+ /** Absolute Unix epoch milliseconds; includes admission, queue and model load. */
24
+ deadlineAt?: number;
25
+ }
26
+
18
27
  // ─────────────────────────────────────────────────────────────────────────────
19
28
  // Model Types
20
29
  // ─────────────────────────────────────────────────────────────────────────────
@@ -81,14 +90,27 @@ export interface RerankScore {
81
90
  // Port Interfaces
82
91
  // ─────────────────────────────────────────────────────────────────────────────
83
92
 
93
+ export interface EmbeddingIdentity {
94
+ contextSize: number;
95
+ /** Versioned policy including the effective token limit. */
96
+ truncationPolicy: string;
97
+ modelFingerprint: string;
98
+ runtimeFingerprint: string;
99
+ }
100
+
84
101
  export interface EmbeddingPort {
85
102
  readonly modelUri: string;
86
103
  /** Initialize the embedding context (loads model). Call before dimensions(). */
87
- init(): Promise<LlmResult<void>>;
88
- embed(text: string): Promise<LlmResult<number[]>>;
89
- embedBatch(texts: string[]): Promise<LlmResult<number[][]>>;
104
+ init(options?: InferenceOptions): Promise<LlmResult<void>>;
105
+ embed(text: string, options?: InferenceOptions): Promise<LlmResult<number[]>>;
106
+ embedBatch(
107
+ texts: string[],
108
+ options?: InferenceOptions
109
+ ): Promise<LlmResult<number[][]>>;
90
110
  /** Returns embedding dimensions. Must call init() first. */
91
111
  dimensions(): number;
112
+ /** Verified native identity after init; absent for unverified/HTTP backends. */
113
+ getIdentity?(): EmbeddingIdentity | undefined;
92
114
  dispose(): Promise<void>;
93
115
  }
94
116
 
@@ -96,13 +118,21 @@ export interface GenerationPort {
96
118
  readonly modelUri: string;
97
119
  /** Undefined is treated as unsupported for backwards-compatible ports. */
98
120
  readonly structuredOutput?: StructuredOutputCapability;
99
- generate(prompt: string, params?: GenParams): Promise<LlmResult<string>>;
121
+ generate(
122
+ prompt: string,
123
+ params?: GenParams,
124
+ options?: InferenceOptions
125
+ ): Promise<LlmResult<string>>;
100
126
  dispose(): Promise<void>;
101
127
  }
102
128
 
103
129
  export interface RerankPort {
104
130
  readonly modelUri: string;
105
- rerank(query: string, documents: string[]): Promise<LlmResult<RerankScore[]>>;
131
+ rerank(
132
+ query: string,
133
+ documents: string[],
134
+ options?: InferenceOptions
135
+ ): Promise<LlmResult<RerankScore[]>>;
106
136
  dispose(): Promise<void>;
107
137
  }
108
138
 
@@ -11,6 +11,7 @@ import type {
11
11
  } from "../core/egress-policy";
12
12
  import type { EgressLineage } from "../core/egress-provenance";
13
13
  import type { JobManager } from "../core/job-manager";
14
+ import type { NativeDisposeOptions } from "../llm/native-worker/owned-exit";
14
15
  import type { ModelLease } from "../llm/nodeLlamaCpp/lifecycle";
15
16
  import type { ResidentStatus } from "../serve/status-model";
16
17
  import type { SqliteAdapter } from "../store/sqlite/adapter";
@@ -18,6 +19,7 @@ import type { StoreResult } from "../store/types";
18
19
  import type { McpToolProfile } from "./tool-profile";
19
20
 
20
21
  import { MCP_SERVER_NAME, VERSION } from "../app/constants";
22
+ import { LlmAdapter } from "../llm/nodeLlamaCpp/adapter";
21
23
  import { createStandaloneResidentStatus } from "../serve/resident-status";
22
24
  import { registerResources } from "./resources/index";
23
25
  import { registerTools } from "./tools/index";
@@ -86,6 +88,8 @@ export interface ToolContext {
86
88
  toolProfile?: McpToolProfile;
87
89
  isShuttingDown: () => boolean;
88
90
  getResidentStatus?: () => ResidentStatus;
91
+ getModelAdapter?: () => LlmAdapter;
92
+ disposeModels?: (options?: NativeDisposeOptions) => Promise<void>;
89
93
  acquireModelLease?: () => ModelLease;
90
94
  markContentMutation?: () => void;
91
95
  markIndexMutation?: () => void;
@@ -125,6 +129,8 @@ export interface CreateToolContextOptions {
125
129
  toolProfile?: McpToolProfile;
126
130
  isShuttingDown: () => boolean;
127
131
  getResidentStatus?: () => ResidentStatus;
132
+ getModelAdapter?: (config: Config) => LlmAdapter | undefined;
133
+ disposeModels?: (options?: NativeDisposeOptions) => Promise<void>;
128
134
  acquireModelLease?: () => ModelLease;
129
135
  markContentMutation?: () => void;
130
136
  markIndexMutation?: () => void;
@@ -141,6 +147,8 @@ export interface CreateToolContextOptions {
141
147
  export function createToolContext(
142
148
  options: CreateToolContextOptions
143
149
  ): ToolContext {
150
+ const adapters = new Map<Config, LlmAdapter>();
151
+ let modelsClosed = false;
144
152
  const requestSnapshot = new AsyncLocalStorage<ToolContextSnapshot>();
145
153
  const currentSnapshot = (): ToolContextSnapshot =>
146
154
  requestSnapshot.getStore() ??
@@ -176,6 +184,25 @@ export function createToolContext(
176
184
  getResidentStatus:
177
185
  options.getResidentStatus ??
178
186
  (() => createStandaloneResidentStatus("stdio")),
187
+ getModelAdapter: () => {
188
+ if (modelsClosed) throw new Error("Resident runtime is shutting down");
189
+ const config = currentSnapshot().config;
190
+ const shared = options.getModelAdapter?.(config);
191
+ if (shared) return shared;
192
+ let adapter = adapters.get(config);
193
+ if (!adapter) {
194
+ adapter = new LlmAdapter(config);
195
+ adapters.set(config, adapter);
196
+ }
197
+ return adapter;
198
+ },
199
+ disposeModels: async (disposeOptions) => {
200
+ modelsClosed = true;
201
+ await Promise.all(
202
+ [...adapters.values()].map((adapter) => adapter.dispose(disposeOptions))
203
+ );
204
+ adapters.clear();
205
+ },
179
206
  acquireModelLease: options.acquireModelLease,
180
207
  markContentMutation: options.markContentMutation,
181
208
  markIndexMutation: options.markIndexMutation,
@@ -1,9 +1,8 @@
1
- /** Web Standard Streamable HTTP request routing for the resident MCP runtime. */
2
-
3
1
  import {
4
2
  isInitializeRequest,
5
3
  type McpServer,
6
4
  } from "@modelcontextprotocol/server";
5
+ /** Web Standard Streamable HTTP request routing for the resident MCP runtime. */
7
6
 
8
7
  import type { DestinationClassification } from "../core/destination-classifier";
9
8
  import type { ResidentRequestHandle } from "../serve/resident-runtime";
@@ -16,6 +15,7 @@ import type {
16
15
 
17
16
  import { MCP_SERVER_NAME, VERSION } from "../app/constants";
18
17
  import { EgressDeniedError } from "../core/egress-enforcement";
18
+ import { withInferenceScope } from "../llm/inference-scope";
19
19
  import { createMcpServerSurface, type ToolContext } from "./context";
20
20
  import {
21
21
  enforceHttpMcpEgress,
@@ -416,14 +416,16 @@ export class HttpMcpTransport {
416
416
  throw error;
417
417
  }
418
418
  const handle = () =>
419
- transport
420
- ? transport.handleRequest(
421
- request,
422
- requestBody === undefined
423
- ? undefined
424
- : { parsedBody: requestBody }
425
- )
426
- : this.#modern.fetch(request, requestBody);
419
+ withInferenceScope({ signal: admission.signal }, async () =>
420
+ transport
421
+ ? transport.handleRequest(
422
+ request,
423
+ requestBody === undefined
424
+ ? undefined
425
+ : { parsedBody: requestBody }
426
+ )
427
+ : this.#modern.fetch(request, requestBody)
428
+ );
427
429
  const destinationZone =
428
430
  context.peerClassification?.zone ??
429
431
  (context.identity === "loopback" ? "loopback" : "remote");
package/src/mcp/server.ts CHANGED
@@ -164,6 +164,8 @@ export async function startMcpServer(options: McpServerOptions): Promise<void> {
164
164
  // Best-effort - server may already be closed
165
165
  }
166
166
 
167
+ await ctx.disposeModels?.();
168
+
167
169
  // 4. Close DB (safe now - no tool or job is running)
168
170
  await store.close();
169
171
 
@@ -214,4 +216,5 @@ export async function startMcpServer(options: McpServerOptions): Promise<void> {
214
216
  });
215
217
  // Also resolve on SIGTERM/SIGINT (already handled by shutdown())
216
218
  });
219
+ await shutdown();
217
220
  }
@@ -1,3 +1,11 @@
1
+ import type {
2
+ Icon,
3
+ McpServer,
4
+ StandardSchemaWithJSON,
5
+ ToolAnnotations,
6
+ ToolCallback,
7
+ ServerContext,
8
+ } from "@modelcontextprotocol/server";
1
9
  /**
2
10
  * MCP tool profiles.
3
11
  *
@@ -9,13 +17,7 @@
9
17
  * @module src/mcp/tool-profile
10
18
  */
11
19
 
12
- import type {
13
- Icon,
14
- McpServer,
15
- StandardSchemaWithJSON,
16
- ToolAnnotations,
17
- ToolCallback,
18
- } from "@modelcontextprotocol/server";
20
+ import { withInferenceScope } from "../llm/inference-scope";
19
21
 
20
22
  export const MCP_TOOL_PROFILES = ["core", "full"] as const;
21
23
 
@@ -105,8 +107,28 @@ export function createProfileToolRegistrar(
105
107
  profile: McpToolProfile
106
108
  ): ProfileToolRegistrar {
107
109
  const allowlist = mcpToolProfileAllowlist(profile);
110
+ const connection = new AbortController();
111
+ const previousClose = server.server.onclose;
112
+ server.server.onclose = () => {
113
+ connection.abort();
114
+ previousClose?.();
115
+ };
108
116
  return (name, config, cb) => {
109
117
  if (allowlist !== null && !allowlist.has(name)) return;
110
- server.registerTool(name, config, cb);
118
+ // The SDK callback is conditional on schema presence: the last argument
119
+ // is always ServerContext, while a schema-bearing call also has input.
120
+ const wrapped = (...args: unknown[]) => {
121
+ const request = args.at(-1) as ServerContext;
122
+ return withInferenceScope(
123
+ {
124
+ signal: AbortSignal.any([connection.signal, request.mcpReq.signal]),
125
+ },
126
+ async () =>
127
+ args.length === 1
128
+ ? (cb as ToolCallback<undefined>)(request)
129
+ : (cb as ToolCallback<StandardSchemaWithJSON>)(args[0], request)
130
+ );
131
+ };
132
+ server.registerTool(name, config, wrapped as unknown as typeof cb);
111
133
  };
112
134
  }
@@ -37,7 +37,7 @@ import {
37
37
  import { LlmAdapter } from "../../llm/nodeLlamaCpp/adapter";
38
38
  import { resolveDownloadPolicy } from "../../llm/policy";
39
39
  import { resolveModelUri } from "../../llm/registry";
40
- import { createVectorIndexPort } from "../../store/vector";
40
+ import { createLazyVectorIndex } from "../../store/vector/lazy";
41
41
 
42
42
  interface ContextToolResultData {
43
43
  structuredContent: Record<string, unknown>;
@@ -123,7 +123,7 @@ export const createMcpModelPorts = async (
123
123
  factoryOverride?: McpModelPortFactory,
124
124
  options: { generation?: boolean } = {}
125
125
  ): Promise<McpModelPorts> => {
126
- const llm = new LlmAdapter(context.config);
126
+ const llm = context.getModelAdapter?.() ?? new LlmAdapter(context.config);
127
127
  const factory = factoryOverride ?? llm;
128
128
  const lease = factory.acquireModelLease?.();
129
129
  const policy = resolveDownloadPolicy(process.env, {});
@@ -152,15 +152,12 @@ export const createMcpModelPorts = async (
152
152
  if (embedResult.ok) {
153
153
  // Take ownership before init: init failures must not leak the port.
154
154
  ownedEmbedPort = embedResult.value;
155
- const initialized = await ownedEmbedPort.init();
156
- if (initialized.ok) {
157
- embedPort = ownedEmbedPort;
158
- const vectorResult = await createVectorIndexPort(
159
- context.store.getRawDb(),
160
- { model: embedUri, dimensions: ownedEmbedPort.dimensions() }
161
- );
162
- if (vectorResult.ok) vectorIndex = vectorResult.value;
163
- }
155
+ embedPort = ownedEmbedPort;
156
+ vectorIndex = await createLazyVectorIndex(
157
+ context.store.getRawDb(),
158
+ embedUri,
159
+ ownedEmbedPort
160
+ );
164
161
  }
165
162
  const rerankResult = await factory.createRerankPort(
166
163
  resolveModelUri(context.config, "rerank", undefined, collection),
@@ -85,7 +85,7 @@ export function handleEmbed(
85
85
  const lease = ctx.acquireModelLease?.();
86
86
  try {
87
87
  // Create LLM adapter with offline policy (fail-fast, no download)
88
- const llm = new LlmAdapter(ctx.config);
88
+ const llm = ctx.getModelAdapter?.() ?? new LlmAdapter(ctx.config);
89
89
  const embedResult = await llm.createEmbeddingPort(modelUri, {
90
90
  egressCollections: collection ? [collection.name] : "all",
91
91
  policy: { offline: true, allowDownload: false },
@@ -148,7 +148,7 @@ export function handleIndex(
148
148
  recordContentMutation(syncResult, ctx.markContentMutation);
149
149
 
150
150
  // Phase 2: Embed
151
- const llm = new LlmAdapter(ctx.config);
151
+ const llm = ctx.getModelAdapter?.() ?? new LlmAdapter(ctx.config);
152
152
  const embedResult = await llm.createEmbeddingPort(modelUri, {
153
153
  egressCollections: collections,
154
154
  policy: { offline: true, allowDownload: false },