@atomic-chat/core 0.13.2 → 0.13.6

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 (115) hide show
  1. package/dist/cli/main.d.ts +1 -1
  2. package/dist/core/atomic-core.d.ts +3 -1
  3. package/dist/core/atomic-core.js +1 -0
  4. package/dist/core/atomic-core.js.map +1 -1
  5. package/dist/core/create.js +6 -0
  6. package/dist/core/create.js.map +1 -1
  7. package/dist/core/prism.d.ts +2 -0
  8. package/dist/core/prism.js +1 -0
  9. package/dist/core/prism.js.map +1 -1
  10. package/dist/core/public-server.js +3 -2
  11. package/dist/core/public-server.js.map +1 -1
  12. package/dist/core/tensorrt-llm.d.ts +169 -0
  13. package/dist/core/tensorrt-llm.js +428 -0
  14. package/dist/core/tensorrt-llm.js.map +1 -0
  15. package/dist/core/types.d.ts +16 -0
  16. package/dist/core/types.js.map +1 -1
  17. package/dist/decision/process.d.ts +4 -0
  18. package/dist/decision/process.js +10 -1
  19. package/dist/decision/process.js.map +1 -1
  20. package/dist/diffusion/args.d.ts +3 -2
  21. package/dist/diffusion/args.js +21 -4
  22. package/dist/diffusion/args.js.map +1 -1
  23. package/dist/diffusion/compat.d.ts +1 -1
  24. package/dist/diffusion/compat.js +6 -2
  25. package/dist/diffusion/compat.js.map +1 -1
  26. package/dist/diffusion/jobs.js +4 -0
  27. package/dist/diffusion/jobs.js.map +1 -1
  28. package/dist/diffusion/tracker.d.ts +6 -0
  29. package/dist/diffusion/tracker.js +11 -0
  30. package/dist/diffusion/tracker.js.map +1 -1
  31. package/dist/diffusion/validate.js +2 -2
  32. package/dist/diffusion/validate.js.map +1 -1
  33. package/dist/diffusion/workflow.d.ts +8 -2
  34. package/dist/diffusion/workflow.js +13 -5
  35. package/dist/diffusion/workflow.js.map +1 -1
  36. package/dist/downloads/downloader.d.ts +22 -0
  37. package/dist/downloads/downloader.js +57 -2
  38. package/dist/downloads/downloader.js.map +1 -1
  39. package/dist/downloads/segmented.d.ts +40 -0
  40. package/dist/downloads/segmented.js +170 -0
  41. package/dist/downloads/segmented.js.map +1 -0
  42. package/dist/embedding/process.d.ts +4 -0
  43. package/dist/embedding/process.js +10 -1
  44. package/dist/embedding/process.js.map +1 -1
  45. package/dist/models/compatibility/inspect.d.ts +11 -2
  46. package/dist/models/compatibility/inspect.js +44 -13
  47. package/dist/models/compatibility/inspect.js.map +1 -1
  48. package/dist/models/compatibility/service.d.ts +3 -0
  49. package/dist/models/compatibility/service.js +1 -0
  50. package/dist/models/compatibility/service.js.map +1 -1
  51. package/dist/models/gguf/tensors.d.ts +1 -0
  52. package/dist/models/gguf/tensors.js +4 -1
  53. package/dist/models/gguf/tensors.js.map +1 -1
  54. package/dist/runtime/managed-text/adapter.d.ts +17 -0
  55. package/dist/runtime/managed-text/adapter.js.map +1 -1
  56. package/dist/runtime/managed-text/lifecycle.d.ts +8 -0
  57. package/dist/runtime/managed-text/lifecycle.js +38 -1
  58. package/dist/runtime/managed-text/lifecycle.js.map +1 -1
  59. package/dist/runtime/managed-text/readiness.d.ts +21 -1
  60. package/dist/runtime/managed-text/readiness.js +64 -0
  61. package/dist/runtime/managed-text/readiness.js.map +1 -1
  62. package/dist/runtime/shared/ports.d.ts +10 -0
  63. package/dist/runtime/shared/ports.js +30 -0
  64. package/dist/runtime/shared/ports.js.map +1 -1
  65. package/dist/runtime/tensorrt-llm/adapter.d.ts +1 -4
  66. package/dist/runtime/tensorrt-llm/adapter.js +28 -11
  67. package/dist/runtime/tensorrt-llm/adapter.js.map +1 -1
  68. package/dist/runtime/tensorrt-llm/check.js +1 -0
  69. package/dist/runtime/tensorrt-llm/check.js.map +1 -1
  70. package/dist/runtime/tensorrt-llm/compatibility.d.ts +30 -6
  71. package/dist/runtime/tensorrt-llm/compatibility.js +41 -9
  72. package/dist/runtime/tensorrt-llm/compatibility.js.map +1 -1
  73. package/dist/runtime/tensorrt-llm/cuda-graphs.d.ts +32 -0
  74. package/dist/runtime/tensorrt-llm/cuda-graphs.js +33 -0
  75. package/dist/runtime/tensorrt-llm/cuda-graphs.js.map +1 -0
  76. package/dist/runtime/tensorrt-llm/delete.d.ts +15 -0
  77. package/dist/runtime/tensorrt-llm/delete.js +60 -0
  78. package/dist/runtime/tensorrt-llm/delete.js.map +1 -0
  79. package/dist/runtime/tensorrt-llm/engine.js +11 -5
  80. package/dist/runtime/tensorrt-llm/engine.js.map +1 -1
  81. package/dist/runtime/tensorrt-llm/guest-files.d.ts +8 -0
  82. package/dist/runtime/tensorrt-llm/guest-files.js +49 -0
  83. package/dist/runtime/tensorrt-llm/guest-files.js.map +1 -0
  84. package/dist/runtime/tensorrt-llm/kv-cache.d.ts +16 -0
  85. package/dist/runtime/tensorrt-llm/kv-cache.js +21 -1
  86. package/dist/runtime/tensorrt-llm/kv-cache.js.map +1 -1
  87. package/dist/runtime/tensorrt-llm/location.d.ts +20 -0
  88. package/dist/runtime/tensorrt-llm/location.js +48 -0
  89. package/dist/runtime/tensorrt-llm/location.js.map +1 -0
  90. package/dist/runtime/tensorrt-llm/model-dir.d.ts +38 -0
  91. package/dist/runtime/tensorrt-llm/model-dir.js +137 -0
  92. package/dist/runtime/tensorrt-llm/model-dir.js.map +1 -0
  93. package/dist/runtime/tensorrt-llm/quant-format.d.ts +65 -0
  94. package/dist/runtime/tensorrt-llm/quant-format.js +189 -0
  95. package/dist/runtime/tensorrt-llm/quant-format.js.map +1 -0
  96. package/dist/runtime/tensorrt-llm/registry.d.ts +26 -0
  97. package/dist/runtime/tensorrt-llm/registry.js +68 -0
  98. package/dist/runtime/tensorrt-llm/registry.js.map +1 -0
  99. package/dist/runtime/tensorrt-llm/runtime.d.ts +130 -0
  100. package/dist/runtime/tensorrt-llm/runtime.js +395 -0
  101. package/dist/runtime/tensorrt-llm/runtime.js.map +1 -0
  102. package/dist/server/control/router.js +1 -1
  103. package/dist/server/control/router.js.map +1 -1
  104. package/dist/server/control/types.d.ts +5 -1
  105. package/dist/server/control/types.js.map +1 -1
  106. package/dist/server/public/gates.d.ts +6 -1
  107. package/dist/server/public/gates.js +7 -3
  108. package/dist/server/public/gates.js.map +1 -1
  109. package/dist/server/public/index.d.ts +1 -0
  110. package/dist/server/public/index.js +9 -6
  111. package/dist/server/public/index.js.map +1 -1
  112. package/dist/server/public/types.d.ts +7 -0
  113. package/dist/version.d.ts +1 -1
  114. package/dist/version.js +1 -1
  115. package/package.json +2 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quant-format.js","sourceRoot":"","sources":["../../../src/runtime/tensorrt-llm/quant-format.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { TensorrtLlmModelYmlDocument } from './model-dir.js';
2
+ export interface TensorrtLlmModelEntry {
3
+ id: string;
4
+ /** Directory holding `model.yml`. */
5
+ dir: string;
6
+ yml: TensorrtLlmModelYmlDocument;
7
+ }
8
+ /** Scan errors are collected rather than thrown: one broken model must not hide the rest of the list. */
9
+ export interface TensorrtLlmScanResult {
10
+ entries: TensorrtLlmModelEntry[];
11
+ skipped: Array<{
12
+ dir: string;
13
+ error: string;
14
+ }>;
15
+ }
16
+ export declare class TensorrtLlmModelRegistry {
17
+ private readonly modelsDir;
18
+ /**
19
+ * The models root, or how to learn it at each scan (change `add-tensorrt-llm-windows`, task 2.8): on
20
+ * Windows it is a folder in Atomic Chat's WSL distribution, known only once that exists — `null`
21
+ * until then, which lists nothing.
22
+ */
23
+ constructor(modelsDir: string | (() => Promise<string | null>));
24
+ scan(): Promise<TensorrtLlmScanResult>;
25
+ list(): Promise<TensorrtLlmModelEntry[]>;
26
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * The `tensorrt-llm` model registry (task 2.16, spec `tensorrt-llm-models`, "Модель — каталог
3
+ * провайдера с манифестом"): a depth-first scan of `<data>/tensorrt-llm/models`, following the same
4
+ * rules `src/models/registry.ts`'s `ModelRegistry` already uses for llama.cpp so all three surfaces
5
+ * (core, the app, the CLI) see the same ids for the same folders — a directory holding `model.yml`
6
+ * *is* a model and is never descended into, the id is its path relative to the models root with `\`
7
+ * rewritten to `/`, ids sort ascending, and an unreadable or invalid `model.yml` is skipped rather
8
+ * than failing the whole scan (spec "Недокачанный каталог": a directory with files but no
9
+ * `model.yml` is not shown at all).
10
+ *
11
+ * There is no caching here, by design: every call re-walks the directory, so a model the app finishes
12
+ * downloading and writes `model.yml` for appears on the very next `list()` with no restart needed
13
+ * (spec "Модель докачана в app"). `model.yml` itself is a different shape from llama.cpp's
14
+ * (`repository`, `revision`, `files`, `architectures`, `quantization` — no `model_path`), which is
15
+ * why this is its own registry rather than a reuse of the llama.cpp one; `parseTensorrtLlmModelYml`
16
+ * (`model-dir.ts`) is the one parser both this scan and the single-id load-path lookup
17
+ * (`readTensorrtLlmModel`) share, so they can never disagree about what a `model.yml` means.
18
+ */
19
+ import { readdir, readFile } from 'node:fs/promises';
20
+ import { join } from 'node:path';
21
+ import { MODEL_YML, modelIdFromDir } from '../../config/index.js';
22
+ import { parseTensorrtLlmModelYml } from './model-dir.js';
23
+ export class TensorrtLlmModelRegistry {
24
+ modelsDir;
25
+ /**
26
+ * The models root, or how to learn it at each scan (change `add-tensorrt-llm-windows`, task 2.8): on
27
+ * Windows it is a folder in Atomic Chat's WSL distribution, known only once that exists — `null`
28
+ * until then, which lists nothing.
29
+ */
30
+ constructor(modelsDir) {
31
+ this.modelsDir = modelsDir;
32
+ }
33
+ async scan() {
34
+ const result = { entries: [], skipped: [] };
35
+ const root = typeof this.modelsDir === 'string' ? this.modelsDir : await this.modelsDir().catch(() => null);
36
+ if (root === null)
37
+ return result;
38
+ const stack = [root];
39
+ while (stack.length) {
40
+ const dir = stack.pop();
41
+ const ymlPath = join(dir, MODEL_YML);
42
+ const text = await readFile(ymlPath, 'utf8').catch(() => undefined);
43
+ if (text !== undefined) {
44
+ try {
45
+ result.entries.push({
46
+ id: modelIdFromDir(root, dir),
47
+ dir,
48
+ yml: parseTensorrtLlmModelYml(text, ymlPath),
49
+ });
50
+ }
51
+ catch (e) {
52
+ result.skipped.push({ dir, error: e.message });
53
+ }
54
+ continue; // a model directory is a leaf, whether or not it parsed
55
+ }
56
+ const children = await readdir(dir, { withFileTypes: true }).catch(() => []);
57
+ for (const child of children)
58
+ if (child.isDirectory())
59
+ stack.push(join(dir, child.name));
60
+ }
61
+ result.entries.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
62
+ return result;
63
+ }
64
+ async list() {
65
+ return (await this.scan()).entries;
66
+ }
67
+ }
68
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/runtime/tensorrt-llm/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACjE,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAA;AAgBzD,MAAM,OAAO,wBAAwB;IAMN;IAL7B;;;;OAIG;IACH,YAA6B,SAAkD;QAAlD,cAAS,GAAT,SAAS,CAAyC;IAAG,CAAC;IAEnF,KAAK,CAAC,IAAI;QACR,MAAM,MAAM,GAA0B,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAA;QAClE,MAAM,IAAI,GACR,OAAO,IAAI,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;QAChG,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO,MAAM,CAAA;QAChC,MAAM,KAAK,GAAa,CAAC,IAAI,CAAC,CAAA;QAC9B,OAAO,KAAK,CAAC,MAAM,EAAE,CAAC;YACpB,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,EAAY,CAAA;YACjC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAA;YACpC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAA;YACnE,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACvB,IAAI,CAAC;oBACH,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;wBAClB,EAAE,EAAE,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC;wBAC7B,GAAG;wBACH,GAAG,EAAE,wBAAwB,CAAC,IAAI,EAAE,OAAO,CAAC;qBAC7C,CAAC,CAAA;gBACJ,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAG,CAAW,CAAC,OAAO,EAAE,CAAC,CAAA;gBAC3D,CAAC;gBACD,SAAQ,CAAC,wDAAwD;YACnE,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAA;YAC5E,KAAK,MAAM,KAAK,IAAI,QAAQ;gBAAE,IAAI,KAAK,CAAC,WAAW,EAAE;oBAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAA;QAC1F,CAAC;QACD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QACvE,OAAO,MAAM,CAAA;IACf,CAAC;IAED,KAAK,CAAC,IAAI;QACR,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAA;IACpC,CAAC;CACF"}
@@ -0,0 +1,130 @@
1
+ import type { SessionInfo, UnloadResult } from '../../contracts/index.js';
2
+ import type { ModelCapabilities } from '../../models/index.js';
3
+ import type { ManagedLastAttempt, ManagedTextCapabilities, ManagedTextLifecycle } from '../managed-text/index.js';
4
+ import type { CtxIncreaseResult, GpuClaimHook, GpuOccupancy, LocalLoadOptions, LocalRuntime, RecreateResult, SessionRoutePolicy } from '../shared/index.js';
5
+ import type { TensorrtLlmHostFacts } from './host-facts.js';
6
+ import type { ReadyInstallation } from './installation.js';
7
+ import type { TensorrtLlmModel } from './model-dir.js';
8
+ export interface TensorrtLlmRuntimeDeps {
9
+ /**
10
+ * The lifecycle over the core's one Docker executor and journal (the startup handle the setup
11
+ * operation shares), asked at every load: `null` while this host has no docker CLI — a setup that
12
+ * installs Docker later makes the next load find it, with no restart; rejected, with the cause,
13
+ * when wiring the executor failed. The same instance every time it resolves non-null.
14
+ */
15
+ lifecycle: () => Promise<ManagedTextLifecycle | null>;
16
+ /** The `ready` installation, its pinned descriptor and image; rejects with why there is none. */
17
+ readyInstallation: () => Promise<ReadyInstallation>;
18
+ /** The cards and SELinux, asked right before each load: a card can disappear between two loads. */
19
+ hostFacts: () => Promise<TensorrtLlmHostFacts>;
20
+ model: (modelId: string) => Promise<TensorrtLlmModel>;
21
+ /** The provider's stored settings (`settings.get('tensorrt-llm')`), read at every load. */
22
+ settings: () => Record<string, unknown>;
23
+ /**
24
+ * Core's GPU residency (spec `gpu-residency`), run as the `stopping-previous` stage: frees the chosen
25
+ * card of every other engine and this provider's other session. Absent, the stage stops only the
26
+ * other `tensorrt-llm` models, itself.
27
+ */
28
+ claimGpu?: GpuClaimHook;
29
+ }
30
+ /**
31
+ * `GET /models/tensorrt-llm/:id/capabilities`: the fields every provider's answer has (all false for
32
+ * this engine — no projector, no embedding, no speculative decoding), and the managed engine's own,
33
+ * which the app gates Agent, tools and attachments on (task 3.8).
34
+ */
35
+ export type TensorrtLlmModelCapabilities = ModelCapabilities & ManagedTextCapabilities & {
36
+ /** The architecture `model.yml` names, which picked the descriptor's `model_families` entry. */
37
+ architecture: string | null;
38
+ };
39
+ /** `GET /models/tensorrt-llm/:id/logs`: the loaded container's live tail, or the last failed attempt's. */
40
+ export type TensorrtLlmModelLogs = {
41
+ model_id: string;
42
+ source: 'session';
43
+ generation: string;
44
+ log_tail: string;
45
+ } | {
46
+ model_id: string;
47
+ source: 'last-attempt';
48
+ generation: string;
49
+ log_tail: string;
50
+ error: ManagedLastAttempt['error'];
51
+ at: number;
52
+ } | {
53
+ model_id: string;
54
+ source: null;
55
+ log_tail: '';
56
+ };
57
+ export declare class TensorrtLlmRuntime implements LocalRuntime {
58
+ private readonly deps;
59
+ private current;
60
+ private closed;
61
+ /** Removals of the engine in progress: while any holds loads off, every load is refused (M-1). */
62
+ private loadHolds;
63
+ /** Deletions of one model in progress (task 2.24): each refuses loads of that model only, counted. */
64
+ private readonly modelHolds;
65
+ /** Generations whose GPU claim succeeded: a load only holds its card from then on. */
66
+ private readonly claimed;
67
+ /** What each loaded session can do, keyed by model and pinned to the generation it was computed for. */
68
+ private readonly sessionCapabilities;
69
+ constructor(deps: TensorrtLlmRuntimeDeps);
70
+ list(): SessionInfo[];
71
+ findSession(modelId: string): SessionInfo | undefined;
72
+ getLoadedModels(): string[];
73
+ isLoading(modelId: string): boolean;
74
+ load(modelId: string, opts?: LocalLoadOptions): Promise<SessionInfo>;
75
+ /**
76
+ * Throws `MANAGED_STOP_UNCONFIRMED` when Docker will not confirm the stop: the card stays reserved
77
+ * and the caller is told, rather than handed a success that is not one.
78
+ */
79
+ unload(modelId: string): Promise<UnloadResult>;
80
+ /**
81
+ * Every model holding a card through this provider — loading, ready, stopping, or stopped without
82
+ * Docker's confirmation: what a removal of the engine must unload first (task 2.6), through core's
83
+ * own unload so each model's cross-process claim is released with it (final review M-1).
84
+ */
85
+ residentModels(): string[];
86
+ /**
87
+ * Refuses every load with `MANAGED_OPERATION_CONFLICT` until the returned release is called (final
88
+ * review M-1): a removal of the engine holds loads off for as long as it runs, so no load creates
89
+ * a container on an installation being removed. Holds nest; each release counts once.
90
+ */
91
+ holdOffLoads(): () => void;
92
+ /**
93
+ * Refuses loads of this one model with `MANAGED_OPERATION_CONFLICT` until the returned release is
94
+ * called (task 2.24): a deletion holds them off from before it stops the model until its files are
95
+ * gone, so no load mounts a folder being removed. Other models load as usual. Holds nest.
96
+ */
97
+ holdOffModel(modelId: string): () => void;
98
+ /** Never: the context is fixed when the container starts (design D9, spec "без авто-роста"). */
99
+ autoIncreaseCtx(_modelId: string): Promise<CtxIncreaseResult>;
100
+ recreateSession(modelId: string): Promise<RecreateResult>;
101
+ shutdown(): Promise<void>;
102
+ routePolicy(modelId: string): SessionRoutePolicy | undefined;
103
+ /** Answers rather than throws, like every provider's capabilities: all false while nothing resolves. */
104
+ capabilities(modelId: string): Promise<TensorrtLlmModelCapabilities>;
105
+ logs(modelId: string): Promise<TensorrtLlmModelLogs>;
106
+ private assertOpen;
107
+ private assertNotHeldOff;
108
+ /**
109
+ * The card each container holds, for core's residency rule: every model past its claim — loading,
110
+ * ready, stopping, or stopped without Docker's confirmation, which still holds the card.
111
+ */
112
+ gpuOccupancy(): GpuOccupancy[];
113
+ /**
114
+ * The `stopping-previous` stage. With core's residency: its claim on `gpuId`, which stops every other
115
+ * `tensorrt-llm` model (one session at a time) and every other engine on that card, each with a
116
+ * confirmed exit, and refuses with `GPU_BUSY` while one will not stop. Without it: every other
117
+ * `tensorrt-llm` model, loading or loaded, stopped with confirmation. Either way the load holds its
118
+ * card from then on — with residency, from the moment core grants the claim, inside core's turn.
119
+ */
120
+ private stopOthers;
121
+ /**
122
+ * The lifecycle's `beforeCreate` hook (task 2.16w round 1, finding 1 (Critical)): the pre-launch
123
+ * check's memory line, re-probed fresh right before the container is actually created — after
124
+ * `stopPrevious` has run, so a model switch on a single-GPU host sees the card the previous
125
+ * session just freed, never a snapshot `load()` took before eviction. `MANAGED_PREREQUISITE_
126
+ * BLOCKED` when the chosen card is no longer on the host at all (the same code a missing card gets
127
+ * earlier in `load()`); `MODEL_INCOMPATIBLE` when it is still there but does not have room.
128
+ */
129
+ private checkMemoryBeforeCreate;
130
+ }
@@ -0,0 +1,395 @@
1
+ /**
2
+ * The `tensorrt-llm` provider (task 2.14, spec `tensorrt-llm-runtime`): a `LocalRuntime` on the
3
+ * engine-neutral managed-text lifecycle (`../managed-text/`), registered by core only on Linux. What
4
+ * this file adds on top of the lifecycle is the provider's own part of a load:
5
+ *
6
+ * - refusing it before any container exists — no Docker, no `ready` installation
7
+ * (`MANAGED_ADAPTER_UNAVAILABLE`), settings the adapter rejects (`INVALID_ARGUMENT`), a model that
8
+ * is not installed, a host with no NVIDIA card, an embedding request;
9
+ * - the card: the saved `gpu_id` when the probe still finds it, otherwise the one with the most free
10
+ * memory, ties by the most total memory (`selectLaunchGpu`, the same rule `POST /check` uses,
11
+ * design D12b), with the replacement reported on every load event;
12
+ * - one session at a time, and one resident model per card: the lifecycle's `stopping-previous`
13
+ * stage asks core's GPU residency (`claimGpu`, task 2.15) to stop every other `tensorrt-llm`
14
+ * model and every other engine on the chosen card, each with a confirmed exit, before this one's
15
+ * container is created — or, with no residency wired, stops the other `tensorrt-llm` models itself;
16
+ * - what a session can do (`routePolicy`, `capabilities`), read off the pinned descriptor's
17
+ * `model_families` entry for the model's architecture — never guessed (design D9);
18
+ * - never growing a context or recreating a session: a restart of a multi-minute container in the
19
+ * middle of a conversation is worse than an honest `context_length_exceeded` (design D9);
20
+ * - the pre-launch check (task 2.16), split in two (round 1, finding 1 (Critical)): before
21
+ * `stopPrevious` runs, `verifyModelFilesAndCompatibility` (`prelaunch.ts`) re-verifies every file
22
+ * `model.yml` recorded present on disk at its size, and recomputes architecture/format/compute-
23
+ * capability against `config.json`/`hf_quant_config.json` as they sit in the model's directory
24
+ * right now — never memory, which the model this load is about to replace may still be holding on
25
+ * the very same card. Memory is checked after `stopPrevious`, through the lifecycle's own
26
+ * `beforeCreate` hook (`checkMemoryBeforeCreate` below), which re-probes the chosen card's free
27
+ * memory once whatever `stopPrevious` freed is actually free;
28
+ * - `family` (tools/structured output/route policy) is read off the descriptor's `model_families`
29
+ * entry for the *verified* `config.json` architecture (finding 5) — `model.yml`'s own copy of the
30
+ * architecture is never consulted for this, since the pre-launch check may have found it stale.
31
+ *
32
+ * Everything that touches the machine arrives injected: the lifecycle over the core's one Docker
33
+ * executor, the ready installation, the host facts, the model lookup and the stored settings.
34
+ */
35
+ import { AtomicCoreError } from '../../contracts/index.js';
36
+ import { throwIfLoadCancelled } from '../shared/index.js';
37
+ import { tensorrtLlmAdapter } from './adapter.js';
38
+ import { checkModelMemory, selectLaunchGpu } from './compatibility.js';
39
+ import { verifyModelFilesAndCompatibility } from './prelaunch.js';
40
+ import { tensorrtLlmRoutePolicy } from './route-policy.js';
41
+ import { tensorrtLlmSettings } from './settings.js';
42
+ const NONE = {
43
+ tools: false,
44
+ reasoning: false,
45
+ structured_output: false,
46
+ vision: false,
47
+ embeddings: false,
48
+ responses: false,
49
+ };
50
+ /** `capabilities()`'s own lookup, off `model.yml`'s architecture: no disk verification runs for it. */
51
+ function familyOf(ready, model) {
52
+ if (model.architecture === null)
53
+ return null;
54
+ return ready.descriptor.model_families[model.architecture] ?? null;
55
+ }
56
+ /**
57
+ * The load path's own lookup (finding 5): off the *verified* `config.json` architecture
58
+ * (`ResolvedCheckpoint.architectures[0]`, from the pre-launch check), never `model.yml`'s — the two
59
+ * can disagree (a stale `model.yml`, or none at all), and only the one the compatibility check just
60
+ * confirmed against the descriptor's `supported_architectures` is trustworthy enough to gate what a
61
+ * session is allowed to do.
62
+ */
63
+ function familyFromResolved(ready, resolved) {
64
+ const architecture = resolved.architectures[0];
65
+ return architecture === undefined ? null : (ready.descriptor.model_families[architecture] ?? null);
66
+ }
67
+ export class TensorrtLlmRuntime {
68
+ deps;
69
+ current = null;
70
+ closed = false;
71
+ /** Removals of the engine in progress: while any holds loads off, every load is refused (M-1). */
72
+ loadHolds = 0;
73
+ /** Deletions of one model in progress (task 2.24): each refuses loads of that model only, counted. */
74
+ modelHolds = new Map();
75
+ /** Generations whose GPU claim succeeded: a load only holds its card from then on. */
76
+ claimed = new Set();
77
+ /** What each loaded session can do, keyed by model and pinned to the generation it was computed for. */
78
+ sessionCapabilities = new Map();
79
+ constructor(deps) {
80
+ this.deps = deps;
81
+ }
82
+ list() {
83
+ return this.current?.list() ?? [];
84
+ }
85
+ findSession(modelId) {
86
+ return this.current?.findSession(modelId);
87
+ }
88
+ getLoadedModels() {
89
+ return this.list().map((session) => session.model_id);
90
+ }
91
+ isLoading(modelId) {
92
+ return this.current?.isLoading(modelId) ?? false;
93
+ }
94
+ async load(modelId, opts = {}) {
95
+ const { signal } = opts;
96
+ this.assertOpen();
97
+ this.assertNotHeldOff(modelId);
98
+ throwIfLoadCancelled(signal);
99
+ if (opts.isEmbedding) {
100
+ throw new AtomicCoreError('INVALID_ARGUMENT', 'tensorrt-llm models do not serve embeddings.', modelId);
101
+ }
102
+ // Validated first, before anything is asked of the machine (spec: schema validation before start).
103
+ const settings = tensorrtLlmSettings(this.deps.settings(), opts.overrides);
104
+ const lifecycle = await this.deps.lifecycle().catch((cause) => {
105
+ throw new AtomicCoreError('MANAGED_ADAPTER_UNAVAILABLE', 'The managed container runtime failed to initialise, so tensorrt-llm cannot run models.', cause instanceof Error ? cause.message : String(cause));
106
+ });
107
+ if (lifecycle === null) {
108
+ throw new AtomicCoreError('MANAGED_ADAPTER_UNAVAILABLE', 'Docker is not installed on this machine, so tensorrt-llm cannot run models.');
109
+ }
110
+ // Kept from the first load on: what `list`, `unload` and `shutdown` act on. Nothing is loaded
111
+ // before that, so there is nothing for them to find earlier either.
112
+ this.current = lifecycle;
113
+ const ready = await this.deps.readyInstallation();
114
+ throwIfLoadCancelled(signal);
115
+ const model = await this.deps.model(modelId);
116
+ const facts = await this.deps.hostFacts();
117
+ throwIfLoadCancelled(signal);
118
+ this.assertOpen();
119
+ const gpu = selectLaunchGpu(facts.gpus, facts.memory, settings.gpu_id ?? undefined);
120
+ if (gpu === null) {
121
+ throw new AtomicCoreError('MANAGED_PREREQUISITE_BLOCKED', 'No NVIDIA GPU was found on this machine, so tensorrt-llm cannot load a model.');
122
+ }
123
+ const substituted = settings.gpu_id !== null && gpu.gpu_id !== settings.gpu_id
124
+ ? { requested_gpu_id: settings.gpu_id, gpu_id: gpu.gpu_id }
125
+ : undefined;
126
+ const memory = {
127
+ contextLength: settings.context_length,
128
+ kvCacheFreeGpuMemoryFraction: settings.kv_cache_free_gpu_memory_fraction,
129
+ };
130
+ // Pre-launch check, phase 1 (task 2.16, spec "Проверка файлов при загрузке"; round 1, finding 1
131
+ // (Critical)): every file model.yml recorded is still on disk at its size, and architecture/
132
+ // format/compute-capability are recomputed against config.json/hf_quant_config.json as they sit
133
+ // on disk right now — never model.yml's word for it, and never memory, which the model this load
134
+ // is about to replace may still be holding on this very card. No container exists yet; a failure
135
+ // here never creates one.
136
+ const resolved = await verifyModelFilesAndCompatibility(model, ready.descriptor, facts.gpus, facts.memory, { gpuId: gpu.gpu_id, memory });
137
+ throwIfLoadCancelled(signal);
138
+ this.assertOpen();
139
+ // family from the *verified* config.json architecture, never model.yml's own (finding 5).
140
+ const family = familyFromResolved(ready, resolved);
141
+ const { descriptor } = ready;
142
+ // Again right before the lifecycle registers this load (synchronously, inside `lifecycle.load`):
143
+ // a removal that began while this load was probing the host must not find it past the check.
144
+ this.assertNotHeldOff(modelId);
145
+ const session = await lifecycle.load({
146
+ modelId,
147
+ modelPath: model.dir,
148
+ weightBytes: model.weightBytes,
149
+ installation: {
150
+ descriptor_id: descriptor.descriptor_id,
151
+ engine_id: descriptor.engine_id,
152
+ adapter_id: descriptor.adapter_id,
153
+ adapter_contract_version: descriptor.adapter_contract_version,
154
+ image: ready.image,
155
+ },
156
+ family,
157
+ gpuUuid: gpu.gpu_id,
158
+ // No VRAM of its own (design D13): the launch bounds the KV cache by tokens, as the memory
159
+ // check (`checkModelMemory`, same rule) reserved for it.
160
+ unifiedMemory: gpu.total_vram_bytes === null,
161
+ gpuTotalVramBytes: gpu.total_vram_bytes,
162
+ gpuComputeCapability: gpu.compute_capability,
163
+ selinux: facts.selinux,
164
+ settings,
165
+ // Always passed, evaluated when the stage runs: a second model that arrived a moment earlier
166
+ // is still found, so two loads racing each other can never both end up running.
167
+ stopPrevious: (stageSignal, generation) => this.stopOthers(lifecycle, { modelId, generation, gpuId: gpu.gpu_id }, stageSignal),
168
+ // Pre-launch check, phase 2 (finding 1): the memory line alone, re-probed fresh once
169
+ // stopPrevious (above) has actually freed the card — never the snapshot `facts` took before
170
+ // eviction, which is why this is a lifecycle hook and not just more code in this function.
171
+ beforeCreate: () => this.checkMemoryBeforeCreate(gpu.gpu_id, descriptor, resolved, memory),
172
+ ...(opts.timeoutSecs !== undefined ? { timeoutMs: opts.timeoutSecs * 1000 } : {}),
173
+ ...(signal !== undefined ? { signal } : {}),
174
+ ...(substituted !== undefined ? { gpuSubstituted: substituted } : {}),
175
+ });
176
+ this.sessionCapabilities.set(modelId, {
177
+ generation: session.generation ?? '',
178
+ capabilities: tensorrtLlmAdapter.capabilities({ settings, family }),
179
+ limits: { contextLength: settings.context_length, maxOutputTokens: settings.max_output_tokens },
180
+ });
181
+ return session;
182
+ }
183
+ /**
184
+ * Throws `MANAGED_STOP_UNCONFIRMED` when Docker will not confirm the stop: the card stays reserved
185
+ * and the caller is told, rather than handed a success that is not one.
186
+ */
187
+ async unload(modelId) {
188
+ // Read before the stop: an id this provider never had answers `was_loaded: false` (spec
189
+ // `tensorrt-llm-runtime`), so a client's wrong id never reads as a stopped model (G-app-4).
190
+ const wasLoaded = this.residentModels().includes(modelId);
191
+ await this.current?.unload(modelId);
192
+ this.sessionCapabilities.delete(modelId);
193
+ return { success: true, was_loaded: wasLoaded };
194
+ }
195
+ /**
196
+ * Every model holding a card through this provider — loading, ready, stopping, or stopped without
197
+ * Docker's confirmation: what a removal of the engine must unload first (task 2.6), through core's
198
+ * own unload so each model's cross-process claim is released with it (final review M-1).
199
+ */
200
+ residentModels() {
201
+ return [...new Set((this.current?.reservations() ?? []).map((r) => r.model_id))];
202
+ }
203
+ /**
204
+ * Refuses every load with `MANAGED_OPERATION_CONFLICT` until the returned release is called (final
205
+ * review M-1): a removal of the engine holds loads off for as long as it runs, so no load creates
206
+ * a container on an installation being removed. Holds nest; each release counts once.
207
+ */
208
+ holdOffLoads() {
209
+ this.loadHolds += 1;
210
+ let released = false;
211
+ return () => {
212
+ if (released)
213
+ return;
214
+ released = true;
215
+ this.loadHolds -= 1;
216
+ };
217
+ }
218
+ /**
219
+ * Refuses loads of this one model with `MANAGED_OPERATION_CONFLICT` until the returned release is
220
+ * called (task 2.24): a deletion holds them off from before it stops the model until its files are
221
+ * gone, so no load mounts a folder being removed. Other models load as usual. Holds nest.
222
+ */
223
+ holdOffModel(modelId) {
224
+ this.modelHolds.set(modelId, (this.modelHolds.get(modelId) ?? 0) + 1);
225
+ let released = false;
226
+ return () => {
227
+ if (released)
228
+ return;
229
+ released = true;
230
+ const left = (this.modelHolds.get(modelId) ?? 1) - 1;
231
+ if (left > 0)
232
+ this.modelHolds.set(modelId, left);
233
+ else
234
+ this.modelHolds.delete(modelId);
235
+ };
236
+ }
237
+ /** Never: the context is fixed when the container starts (design D9, spec "без авто-роста"). */
238
+ autoIncreaseCtx(_modelId) {
239
+ return Promise.resolve({ ok: false, reason: 'unsupported' });
240
+ }
241
+ recreateSession(modelId) {
242
+ return Promise.reject(new AtomicCoreError('INVALID_ARGUMENT', 'A tensorrt-llm session is not recreated in place; unload the model and load it again.', modelId));
243
+ }
244
+ async shutdown() {
245
+ this.closed = true;
246
+ await this.current?.shutdown();
247
+ this.sessionCapabilities.clear();
248
+ }
249
+ routePolicy(modelId) {
250
+ const session = this.findSession(modelId);
251
+ if (session === undefined)
252
+ return undefined;
253
+ const known = this.sessionCapabilities.get(modelId);
254
+ // A session with no record of what it can do is treated as able to do nothing optional.
255
+ if (known === undefined || known.generation !== session.generation)
256
+ return tensorrtLlmRoutePolicy(NONE);
257
+ return tensorrtLlmRoutePolicy(known.capabilities, known.limits);
258
+ }
259
+ /** Answers rather than throws, like every provider's capabilities: all false while nothing resolves. */
260
+ async capabilities(modelId) {
261
+ const base = {
262
+ modelId,
263
+ mmprojExists: false,
264
+ isEmbedding: false,
265
+ isDecision: false,
266
+ audio: false,
267
+ gemmaMtp: false,
268
+ dflash: false,
269
+ dflashDrafts: [],
270
+ ...NONE,
271
+ architecture: null,
272
+ };
273
+ try {
274
+ const [ready, model] = await Promise.all([this.deps.readyInstallation(), this.deps.model(modelId)]);
275
+ const settings = tensorrtLlmSettings({});
276
+ return {
277
+ ...base,
278
+ ...tensorrtLlmAdapter.capabilities({ settings, family: familyOf(ready, model) }),
279
+ architecture: model.architecture,
280
+ };
281
+ }
282
+ catch {
283
+ return base;
284
+ }
285
+ }
286
+ async logs(modelId) {
287
+ const lifecycle = this.current;
288
+ const session = lifecycle?.findSession(modelId);
289
+ if (lifecycle && session) {
290
+ return {
291
+ model_id: modelId,
292
+ source: 'session',
293
+ generation: session.generation ?? '',
294
+ log_tail: (await lifecycle.logs(modelId)) ?? '',
295
+ };
296
+ }
297
+ const attempt = lifecycle?.lastAttempt(modelId);
298
+ if (attempt === undefined)
299
+ return { model_id: modelId, source: null, log_tail: '' };
300
+ return {
301
+ model_id: modelId,
302
+ source: 'last-attempt',
303
+ generation: attempt.generation,
304
+ log_tail: attempt.log_tail,
305
+ error: attempt.error,
306
+ at: attempt.at,
307
+ };
308
+ }
309
+ assertOpen() {
310
+ if (this.closed) {
311
+ throw new AtomicCoreError('CORE_NOT_RUNNING', 'The tensorrt-llm provider is shutting down.');
312
+ }
313
+ }
314
+ assertNotHeldOff(modelId) {
315
+ if (this.loadHolds > 0) {
316
+ throw new AtomicCoreError('MANAGED_OPERATION_CONFLICT', 'The TensorRT-LLM engine is being removed; load the model once the removal has finished.', modelId);
317
+ }
318
+ if (this.modelHolds.has(modelId)) {
319
+ throw new AtomicCoreError('MANAGED_OPERATION_CONFLICT', 'The model is being deleted.', modelId);
320
+ }
321
+ }
322
+ /**
323
+ * The card each container holds, for core's residency rule: every model past its claim — loading,
324
+ * ready, stopping, or stopped without Docker's confirmation, which still holds the card.
325
+ */
326
+ gpuOccupancy() {
327
+ return (this.current?.reservations() ?? [])
328
+ .filter((r) => r.state !== 'loading' || this.claimed.has(r.generation))
329
+ .map((r) => ({
330
+ model_id: r.model_id,
331
+ cards: [r.gpu_uuid],
332
+ auxiliary: false,
333
+ state: r.state,
334
+ ...(r.state === 'stop-unconfirmed' && r.container_id !== null
335
+ ? {
336
+ remedy: `Loading again retries the stop; if Docker keeps failing, restart Docker or remove ` +
337
+ `container ${r.container_id} (docker rm -f ${r.container_id}).`,
338
+ }
339
+ : {}),
340
+ }));
341
+ }
342
+ /**
343
+ * The `stopping-previous` stage. With core's residency: its claim on `gpuId`, which stops every other
344
+ * `tensorrt-llm` model (one session at a time) and every other engine on that card, each with a
345
+ * confirmed exit, and refuses with `GPU_BUSY` while one will not stop. Without it: every other
346
+ * `tensorrt-llm` model, loading or loaded, stopped with confirmation. Either way the load holds its
347
+ * card from then on — with residency, from the moment core grants the claim, inside core's turn.
348
+ */
349
+ async stopOthers(lifecycle, load, signal) {
350
+ // Generations whose reservation is gone are forgotten here, never while answering a read.
351
+ const live = new Set(lifecycle.reservations().map((r) => r.generation));
352
+ for (const generation of this.claimed)
353
+ if (!live.has(generation))
354
+ this.claimed.delete(generation);
355
+ const hold = () => {
356
+ this.claimed.add(load.generation);
357
+ };
358
+ if (this.deps.claimGpu) {
359
+ const claim = {
360
+ model_id: load.modelId,
361
+ cards: [load.gpuId],
362
+ auxiliary: false,
363
+ soleSessionOfProvider: true,
364
+ };
365
+ await this.deps.claimGpu(claim, signal, hold);
366
+ }
367
+ else {
368
+ const others = new Set(lifecycle.reservations().map((r) => r.model_id));
369
+ others.delete(load.modelId);
370
+ for (const other of others)
371
+ await this.unload(other);
372
+ }
373
+ hold();
374
+ }
375
+ /**
376
+ * The lifecycle's `beforeCreate` hook (task 2.16w round 1, finding 1 (Critical)): the pre-launch
377
+ * check's memory line, re-probed fresh right before the container is actually created — after
378
+ * `stopPrevious` has run, so a model switch on a single-GPU host sees the card the previous
379
+ * session just freed, never a snapshot `load()` took before eviction. `MANAGED_PREREQUISITE_
380
+ * BLOCKED` when the chosen card is no longer on the host at all (the same code a missing card gets
381
+ * earlier in `load()`); `MODEL_INCOMPATIBLE` when it is still there but does not have room.
382
+ */
383
+ async checkMemoryBeforeCreate(gpuId, descriptor, resolved, memory) {
384
+ const facts = await this.deps.hostFacts();
385
+ if (!facts.gpus.some((gpu) => gpu.gpu_id === gpuId)) {
386
+ throw new AtomicCoreError('MANAGED_PREREQUISITE_BLOCKED', 'The selected GPU disappeared before the container could start.', gpuId);
387
+ }
388
+ const verdict = checkModelMemory(resolved, descriptor, facts.gpus, facts.memory, memory);
389
+ if (!verdict.verdict.ok) {
390
+ const { code, message, details } = verdict.verdict.error;
391
+ throw new AtomicCoreError(code, message, details);
392
+ }
393
+ }
394
+ }
395
+ //# sourceMappingURL=runtime.js.map