@gmickel/gno 1.45.1 → 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.
- package/README.md +1 -1
- package/THIRD_PARTY_NOTICES.md +46 -0
- package/assets/skill/SKILL.md +7 -6
- package/assets/skill/cli-reference.md +14 -6
- package/assets/skill/mcp-reference.md +4 -1
- package/assets/spa-production.json.gz +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v2.0.0.zip +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v2.0.0.zip.sha256 +1 -0
- package/browser-extension/dist/chunk-4tc9v0ja.js +74 -0
- package/browser-extension/dist/manifest.json +1 -1
- package/browser-extension/dist/preview.html +1 -1
- package/browser-extension/dist/service-worker.js +32 -33
- package/bunfig.toml +2 -0
- package/package.json +40 -26
- package/spec/cli.md +30 -11
- package/spec/db/schema.sql +146 -1
- package/spec/mcp.md +26 -0
- package/src/app/context-runtime-types.ts +3 -0
- package/src/app/context-runtime.ts +2 -0
- package/src/cli/commands/ask.ts +6 -1
- package/src/cli/commands/daemon.ts +21 -8
- package/src/cli/commands/embed.ts +77 -41
- package/src/cli/commands/mcp/install.ts +20 -0
- package/src/cli/commands/mcp/paths.ts +25 -0
- package/src/cli/commands/mcp/status.ts +6 -0
- package/src/cli/detach.ts +3 -2
- package/src/cli/program.ts +6 -0
- package/src/config/types.ts +3 -3
- package/src/converters/adapters/markitdownTs/adapter.ts +1 -2
- package/src/converters/adapters/officeparser/adapter.ts +1 -2
- package/src/converters/versions.ts +6 -8
- package/src/core/context-evidence.ts +8 -4
- package/src/core/job-manager.ts +95 -13
- package/src/core/network-boundary-inventory.ts +10 -0
- package/src/core/shutdown-budget.ts +45 -0
- package/src/embed/backlog.ts +107 -4
- package/src/embed/batch.ts +42 -2
- package/src/embed/fingerprint.ts +16 -0
- package/src/embed/retry.ts +113 -5
- package/src/embed/variant-backlog.ts +105 -0
- package/src/embed/variant-plan.ts +62 -0
- package/src/embed/variant-retry.ts +113 -0
- package/src/ingestion/graph-reconciliation.ts +327 -0
- package/src/ingestion/sync.ts +9 -272
- package/src/llm/http-inference.ts +6 -0
- package/src/llm/httpEmbedding.ts +37 -6
- package/src/llm/httpGeneration.ts +18 -3
- package/src/llm/httpRerank.ts +23 -5
- package/src/llm/inference-cancellation.ts +168 -0
- package/src/llm/inference-scope.ts +202 -0
- package/src/llm/lazy-ports.ts +115 -0
- package/src/llm/native-worker/client.ts +541 -0
- package/src/llm/native-worker/dispatcher.ts +228 -0
- package/src/llm/native-worker/embedding-identity.ts +33 -0
- package/src/llm/native-worker/entry.ts +173 -0
- package/src/llm/native-worker/errors.ts +32 -0
- package/src/llm/native-worker/evaluation.ts +16 -0
- package/src/llm/native-worker/owned-exit.ts +108 -0
- package/src/llm/native-worker/owner.ts +141 -0
- package/src/llm/native-worker/ports.ts +317 -0
- package/src/llm/native-worker/protocol.ts +442 -0
- package/src/llm/native-worker/runtime-config.ts +92 -0
- package/src/llm/nodeLlamaCpp/adapter.ts +77 -20
- package/src/llm/nodeLlamaCpp/embedding.ts +130 -46
- package/src/llm/nodeLlamaCpp/generation.ts +34 -5
- package/src/llm/nodeLlamaCpp/lifecycle-options.ts +99 -0
- package/src/llm/nodeLlamaCpp/lifecycle.ts +209 -204
- package/src/llm/nodeLlamaCpp/rerank-capacity.ts +111 -0
- package/src/llm/nodeLlamaCpp/rerank.ts +118 -27
- package/src/llm/nodeLlamaCpp/simulator-handle.ts +73 -0
- package/src/llm/nodeLlamaCpp/simulator-install.ts +124 -0
- package/src/llm/nodeLlamaCpp/simulator-session.ts +240 -0
- package/src/llm/nodeLlamaCpp/simulator-types.ts +80 -0
- package/src/llm/types.ts +35 -5
- package/src/mcp/context.ts +27 -0
- package/src/mcp/http-transport.ts +12 -10
- package/src/mcp/server.ts +3 -0
- package/src/mcp/tool-profile.ts +30 -8
- package/src/mcp/tools/context.ts +8 -11
- package/src/mcp/tools/embed.ts +1 -1
- package/src/mcp/tools/index-cmd.ts +1 -1
- package/src/mcp/tools/index.ts +10 -8
- package/src/mcp/tools/query.ts +14 -30
- package/src/mcp/tools/vsearch.ts +1 -1
- package/src/pipeline/answer.ts +23 -3
- package/src/pipeline/claim-verifier.ts +6 -0
- package/src/pipeline/expansion.ts +43 -40
- package/src/pipeline/explain.ts +6 -2
- package/src/pipeline/filters.ts +63 -0
- package/src/pipeline/fusion.ts +29 -9
- package/src/pipeline/graph-retrieval.ts +29 -9
- package/src/pipeline/hybrid.ts +198 -55
- package/src/pipeline/hydration.ts +161 -0
- package/src/pipeline/owner-fusion.ts +87 -0
- package/src/pipeline/rerank.ts +35 -11
- package/src/pipeline/search.ts +13 -2
- package/src/pipeline/types.ts +5 -3
- package/src/pipeline/vsearch.ts +87 -7
- package/src/sdk/client.ts +47 -3
- package/src/sdk/embed.ts +63 -39
- package/src/serve/background-runtime.ts +1 -1
- package/src/serve/context.ts +41 -56
- package/src/serve/embed-scheduler.ts +58 -35
- package/src/serve/public/components/IndexingProgress.tsx +46 -60
- package/src/serve/public/globals.built.css +1 -1
- package/src/serve/public/lib/shiki-language-ids.ts +14 -0
- package/src/serve/resident-admission.ts +36 -36
- package/src/serve/resident-background-work.ts +20 -2
- package/src/serve/resident-request.ts +11 -5
- package/src/serve/resident-runtime.ts +97 -61
- package/src/serve/resident-shutdown.ts +153 -0
- package/src/serve/routes/api.ts +3 -1
- package/src/serve/server.ts +47 -26
- package/src/store/migrations/028-vector-variants.ts +54 -0
- package/src/store/migrations/029-graph-reference-state.ts +77 -0
- package/src/store/migrations/index.ts +4 -0
- package/src/store/sqlite/adapter.ts +251 -183
- package/src/store/sqlite/eligibility.ts +174 -0
- package/src/store/sqlite/graph-edge-application.ts +66 -0
- package/src/store/sqlite/graph-reference-state.ts +194 -0
- package/src/store/sqlite/legacy-vector-ownership.ts +79 -0
- package/src/store/types.ts +80 -12
- package/src/store/vector/eligibility.ts +36 -0
- package/src/store/vector/freshness.ts +33 -6
- package/src/store/vector/lazy.ts +81 -0
- package/src/store/vector/sqlite-vec.ts +106 -54
- package/src/store/vector/stats.ts +14 -3
- package/src/store/vector/types.ts +35 -2
- package/src/store/vector/variant-search.ts +192 -0
- package/src/store/vector/variants.ts +451 -0
- package/vendor/converters/markitdown-ts/LICENSE +21 -0
- package/vendor/converters/markitdown-ts/dist/index.cjs +1180 -0
- package/vendor/converters/markitdown-ts/dist/index.d.cts +46 -0
- package/vendor/converters/markitdown-ts/dist/index.d.mts +46 -0
- package/vendor/converters/markitdown-ts/dist/index.d.ts +46 -0
- package/vendor/converters/markitdown-ts/dist/index.mjs +1152 -0
- package/vendor/converters/markitdown-ts/package.json +77 -0
- package/vendor/converters/officeparser/LICENSE +21 -0
- package/vendor/converters/officeparser/dist/OfficeConverter.d.ts +47 -0
- package/vendor/converters/officeparser/dist/OfficeConverter.js +76 -0
- package/vendor/converters/officeparser/dist/OfficeGenerator.d.ts +23 -0
- package/vendor/converters/officeparser/dist/OfficeGenerator.js +73 -0
- package/vendor/converters/officeparser/dist/OfficeParser.d.ts +106 -0
- package/vendor/converters/officeparser/dist/OfficeParser.js +332 -0
- package/vendor/converters/officeparser/dist/cli.d.ts +28 -0
- package/vendor/converters/officeparser/dist/cli.js +381 -0
- package/vendor/converters/officeparser/dist/defaults.d.ts +41 -0
- package/vendor/converters/officeparser/dist/defaults.js +218 -0
- package/vendor/converters/officeparser/dist/generators/BaseGenerator.d.ts +107 -0
- package/vendor/converters/officeparser/dist/generators/BaseGenerator.js +248 -0
- package/vendor/converters/officeparser/dist/generators/ChunkingGenerator.d.ts +82 -0
- package/vendor/converters/officeparser/dist/generators/ChunkingGenerator.js +797 -0
- package/vendor/converters/officeparser/dist/generators/CsvGenerator.d.ts +38 -0
- package/vendor/converters/officeparser/dist/generators/CsvGenerator.js +245 -0
- package/vendor/converters/officeparser/dist/generators/EpubGenerator.d.ts +43 -0
- package/vendor/converters/officeparser/dist/generators/EpubGenerator.js +315 -0
- package/vendor/converters/officeparser/dist/generators/HtmlGenerator.d.ts +59 -0
- package/vendor/converters/officeparser/dist/generators/HtmlGenerator.js +1942 -0
- package/vendor/converters/officeparser/dist/generators/MarkdownGenerator.d.ts +96 -0
- package/vendor/converters/officeparser/dist/generators/MarkdownGenerator.js +1175 -0
- package/vendor/converters/officeparser/dist/generators/PdfGenerator.d.ts +22 -0
- package/vendor/converters/officeparser/dist/generators/PdfGenerator.js +194 -0
- package/vendor/converters/officeparser/dist/generators/RtfGenerator.d.ts +29 -0
- package/vendor/converters/officeparser/dist/generators/RtfGenerator.js +316 -0
- package/vendor/converters/officeparser/dist/generators/TextGenerator.d.ts +13 -0
- package/vendor/converters/officeparser/dist/generators/TextGenerator.js +201 -0
- package/vendor/converters/officeparser/dist/index.d.ts +60 -0
- package/vendor/converters/officeparser/dist/index.js +72 -0
- package/vendor/converters/officeparser/dist/index.mjs +18 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.d.ts +2621 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.iife.js +1336 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.mjs +1335 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.slim.d.ts +2621 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.slim.iife.js +1336 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.slim.mjs +1335 -0
- package/vendor/converters/officeparser/dist/parsers/CsvParser.d.ts +9 -0
- package/vendor/converters/officeparser/dist/parsers/CsvParser.js +115 -0
- package/vendor/converters/officeparser/dist/parsers/EpubParser.d.ts +8 -0
- package/vendor/converters/officeparser/dist/parsers/EpubParser.js +217 -0
- package/vendor/converters/officeparser/dist/parsers/ExcelParser.d.ts +32 -0
- package/vendor/converters/officeparser/dist/parsers/ExcelParser.js +736 -0
- package/vendor/converters/officeparser/dist/parsers/HtmlParser.d.ts +2 -0
- package/vendor/converters/officeparser/dist/parsers/HtmlParser.js +1287 -0
- package/vendor/converters/officeparser/dist/parsers/MarkdownParser.d.ts +2 -0
- package/vendor/converters/officeparser/dist/parsers/MarkdownParser.js +1272 -0
- package/vendor/converters/officeparser/dist/parsers/OpenOfficeParser.d.ts +31 -0
- package/vendor/converters/officeparser/dist/parsers/OpenOfficeParser.js +1819 -0
- package/vendor/converters/officeparser/dist/parsers/PdfParser.d.ts +67 -0
- package/vendor/converters/officeparser/dist/parsers/PdfParser.js +848 -0
- package/vendor/converters/officeparser/dist/parsers/PowerPointParser.d.ts +32 -0
- package/vendor/converters/officeparser/dist/parsers/PowerPointParser.js +950 -0
- package/vendor/converters/officeparser/dist/parsers/RtfParser.d.ts +187 -0
- package/vendor/converters/officeparser/dist/parsers/RtfParser.js +1801 -0
- package/vendor/converters/officeparser/dist/parsers/WordParser.d.ts +79 -0
- package/vendor/converters/officeparser/dist/parsers/WordParser.js +1177 -0
- package/vendor/converters/officeparser/dist/sbom.cdx.json +1763 -0
- package/vendor/converters/officeparser/dist/types.d.ts +2507 -0
- package/vendor/converters/officeparser/dist/types.js +107 -0
- package/vendor/converters/officeparser/dist/utils/astUtils.d.ts +16 -0
- package/vendor/converters/officeparser/dist/utils/astUtils.js +33 -0
- package/vendor/converters/officeparser/dist/utils/chartUtils.d.ts +6 -0
- package/vendor/converters/officeparser/dist/utils/chartUtils.js +257 -0
- package/vendor/converters/officeparser/dist/utils/configUtils.d.ts +44 -0
- package/vendor/converters/officeparser/dist/utils/configUtils.js +315 -0
- package/vendor/converters/officeparser/dist/utils/dateUtils.d.ts +17 -0
- package/vendor/converters/officeparser/dist/utils/dateUtils.js +69 -0
- package/vendor/converters/officeparser/dist/utils/envUtils.d.ts +29 -0
- package/vendor/converters/officeparser/dist/utils/envUtils.js +152 -0
- package/vendor/converters/officeparser/dist/utils/errorUtils.d.ts +72 -0
- package/vendor/converters/officeparser/dist/utils/errorUtils.js +245 -0
- package/vendor/converters/officeparser/dist/utils/imageUtils.d.ts +66 -0
- package/vendor/converters/officeparser/dist/utils/imageUtils.js +133 -0
- package/vendor/converters/officeparser/dist/utils/mathUtils.d.ts +42 -0
- package/vendor/converters/officeparser/dist/utils/mathUtils.js +385 -0
- package/vendor/converters/officeparser/dist/utils/moduleLoader.d.ts +18 -0
- package/vendor/converters/officeparser/dist/utils/moduleLoader.js +106 -0
- package/vendor/converters/officeparser/dist/utils/ocrUtils.d.ts +42 -0
- package/vendor/converters/officeparser/dist/utils/ocrUtils.js +428 -0
- package/vendor/converters/officeparser/dist/utils/sanitize.d.ts +148 -0
- package/vendor/converters/officeparser/dist/utils/sanitize.js +344 -0
- package/vendor/converters/officeparser/dist/utils/sheetUtils.d.ts +7 -0
- package/vendor/converters/officeparser/dist/utils/sheetUtils.js +35 -0
- package/vendor/converters/officeparser/dist/utils/styleMapper.d.ts +36 -0
- package/vendor/converters/officeparser/dist/utils/styleMapper.js +224 -0
- package/vendor/converters/officeparser/dist/utils/xmlUtils.d.ts +163 -0
- package/vendor/converters/officeparser/dist/utils/xmlUtils.js +461 -0
- package/vendor/converters/officeparser/dist/utils/zipUtils.d.ts +134 -0
- package/vendor/converters/officeparser/dist/utils/zipUtils.js +337 -0
- package/vendor/converters/officeparser/package.json +147 -0
- package/vendor/converters/upstream-manifest.json +124 -0
- package/vendor/dependency-fixes/README.md +77 -0
- package/vendor/dependency-fixes/vendor-converters.py +83 -0
- package/browser-extension/artifacts/gno-browser-clipper-v1.45.1.zip +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v1.45.1.zip.sha256 +0 -1
- package/browser-extension/dist/chunk-627emwpj.js +0 -75
- /package/browser-extension/dist/{chunk-ydfx5d7p.css → chunk-z74y8n8c.css} +0 -0
|
@@ -0,0 +1,541 @@
|
|
|
1
|
+
import type { ModelLifecycleStats } from "../nodeLlamaCpp/lifecycle";
|
|
2
|
+
import type { InferenceOptions } from "../types";
|
|
3
|
+
import type { Owner, Pending } from "./owner";
|
|
4
|
+
import type { ApprovedModel, NativeRequest, NativeResponse } from "./protocol";
|
|
5
|
+
import type { NativeRuntimeConfig } from "./runtime-config";
|
|
6
|
+
|
|
7
|
+
import { InferenceSettlement } from "../inference-cancellation";
|
|
8
|
+
import {
|
|
9
|
+
inferenceOptions,
|
|
10
|
+
recordInferenceTimeout,
|
|
11
|
+
isBackgroundInference,
|
|
12
|
+
} from "../inference-scope";
|
|
13
|
+
import { NativeWorkerError } from "./errors";
|
|
14
|
+
import { retireOwnedChild, type NativeDisposeOptions } from "./owned-exit";
|
|
15
|
+
import {
|
|
16
|
+
cancelPending,
|
|
17
|
+
wireResult,
|
|
18
|
+
waitForQuarantine,
|
|
19
|
+
releaseQuarantine,
|
|
20
|
+
selectNext,
|
|
21
|
+
recordCompletion,
|
|
22
|
+
} from "./owner";
|
|
23
|
+
import {
|
|
24
|
+
frameNativeMessage,
|
|
25
|
+
NativeFrameDecoder,
|
|
26
|
+
NativeRequestLedger,
|
|
27
|
+
parseNativeRequest,
|
|
28
|
+
NativeExecutionStartedSchema,
|
|
29
|
+
} from "./protocol";
|
|
30
|
+
import {
|
|
31
|
+
nativeWorkerEnvironment,
|
|
32
|
+
NativeRuntimeConfigSchema,
|
|
33
|
+
NativeRegistrationSchema,
|
|
34
|
+
wireError,
|
|
35
|
+
} from "./runtime-config";
|
|
36
|
+
|
|
37
|
+
type Input = NativeRequest extends infer R
|
|
38
|
+
? R extends NativeRequest
|
|
39
|
+
? Omit<R, "version" | "generation" | "requestId">
|
|
40
|
+
: never
|
|
41
|
+
: never;
|
|
42
|
+
export interface NativeWorkerClientOptions {
|
|
43
|
+
models: readonly ApprovedModel[];
|
|
44
|
+
loadTimeout: number;
|
|
45
|
+
inferenceTimeout: number;
|
|
46
|
+
warmModelTtl?: number;
|
|
47
|
+
/** Internal fault-test launch seam; never populated from caller configuration. */
|
|
48
|
+
entryPath?: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** One process generation, one active operation and 64 waiting logical calls. */
|
|
52
|
+
export class NativeWorkerClient {
|
|
53
|
+
private owner?: Owner;
|
|
54
|
+
private lifecycle?: ModelLifecycleStats;
|
|
55
|
+
private generation = 0;
|
|
56
|
+
private requestId = 0;
|
|
57
|
+
private closed = false;
|
|
58
|
+
private leases = 0;
|
|
59
|
+
private idleOwner?: Owner;
|
|
60
|
+
private registration: Promise<void> = Promise.resolve();
|
|
61
|
+
private readonly options: NativeWorkerClientOptions;
|
|
62
|
+
|
|
63
|
+
constructor(options: NativeWorkerClientOptions) {
|
|
64
|
+
this.options = { ...options, models: structuredClone(options.models) };
|
|
65
|
+
process.once("exit", this.onParentExit);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private readonly onParentExit = (): void => {
|
|
69
|
+
this.owner?.child.kill("SIGKILL");
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
get processId(): number | undefined {
|
|
73
|
+
return this.owner?.child.pid;
|
|
74
|
+
}
|
|
75
|
+
get currentGeneration(): number {
|
|
76
|
+
return this.generation;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Last child-reported snapshot; reading it sends no IPC and cannot extend idle. */
|
|
80
|
+
getLifecycleStats(): ModelLifecycleStats {
|
|
81
|
+
const snapshot = this.lifecycle ?? {
|
|
82
|
+
activeLeases: 0,
|
|
83
|
+
leaseAcquisitions: 0,
|
|
84
|
+
leaseReleases: 0,
|
|
85
|
+
loadedModels: 0,
|
|
86
|
+
loadAttempts: 0,
|
|
87
|
+
loadSuccesses: 0,
|
|
88
|
+
loadFailures: 0,
|
|
89
|
+
inflightLoads: 0,
|
|
90
|
+
};
|
|
91
|
+
return this.owner
|
|
92
|
+
? { ...snapshot }
|
|
93
|
+
: {
|
|
94
|
+
...snapshot,
|
|
95
|
+
activeLeases: 0,
|
|
96
|
+
loadedModels: 0,
|
|
97
|
+
inflightLoads: 0,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
acquireLease(): { release(): void } {
|
|
102
|
+
if (this.closed) throw new NativeWorkerError("exited");
|
|
103
|
+
this.leases++;
|
|
104
|
+
let released = false;
|
|
105
|
+
return {
|
|
106
|
+
release: () => {
|
|
107
|
+
if (released) return;
|
|
108
|
+
released = true;
|
|
109
|
+
this.leases--;
|
|
110
|
+
const owner = this.idleOwner;
|
|
111
|
+
if (
|
|
112
|
+
!this.leases &&
|
|
113
|
+
owner &&
|
|
114
|
+
this.owner === owner &&
|
|
115
|
+
!owner.pending.length &&
|
|
116
|
+
!owner.busy
|
|
117
|
+
)
|
|
118
|
+
void this.retire(owner).catch((error: unknown) =>
|
|
119
|
+
console.error(error)
|
|
120
|
+
);
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async disposeModel(uri: string): Promise<void> {
|
|
126
|
+
const operation = this.registration.then(async () => {
|
|
127
|
+
const owner = this.owner;
|
|
128
|
+
if (
|
|
129
|
+
!owner ||
|
|
130
|
+
!this.options.models.some((entry) => entry.modelUri === uri)
|
|
131
|
+
)
|
|
132
|
+
return;
|
|
133
|
+
if (owner.retiring) {
|
|
134
|
+
await owner.retirement;
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (owner.pending.length || owner.busy)
|
|
138
|
+
await new Promise<void>((resolve) => owner.drain.add(resolve));
|
|
139
|
+
// Explicit disposal reclaims the complete process allocation. Individual
|
|
140
|
+
// model idle timers may already have evicted weights within this owner.
|
|
141
|
+
await this.retire(owner);
|
|
142
|
+
});
|
|
143
|
+
this.registration = operation.catch(() => {});
|
|
144
|
+
await operation;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** Only the parent model-selection/policy layer may approve these descriptors. */
|
|
148
|
+
registerModel(model: ApprovedModel): Promise<void> {
|
|
149
|
+
const descriptor = NativeRegistrationSchema.parse({
|
|
150
|
+
register: model,
|
|
151
|
+
}).register;
|
|
152
|
+
const operation = this.registration.then(async () => {
|
|
153
|
+
if (this.closed) throw new NativeWorkerError("exited");
|
|
154
|
+
const existing = this.options.models.find(
|
|
155
|
+
(entry) => entry.id === descriptor.id
|
|
156
|
+
);
|
|
157
|
+
if (existing && JSON.stringify(existing) === JSON.stringify(descriptor))
|
|
158
|
+
return;
|
|
159
|
+
const models = [
|
|
160
|
+
...this.options.models.filter((entry) => entry.id !== descriptor.id),
|
|
161
|
+
descriptor,
|
|
162
|
+
];
|
|
163
|
+
NativeRuntimeConfigSchema.parse({
|
|
164
|
+
generation: Math.max(1, this.generation),
|
|
165
|
+
models,
|
|
166
|
+
loadTimeout: this.options.loadTimeout,
|
|
167
|
+
inferenceTimeout: this.options.inferenceTimeout,
|
|
168
|
+
warmModelTtl: this.options.warmModelTtl ?? 300_000,
|
|
169
|
+
});
|
|
170
|
+
const owner = this.owner;
|
|
171
|
+
if (owner?.retiring) await owner.retirement;
|
|
172
|
+
if (existing && owner) {
|
|
173
|
+
if (owner.pending.length || owner.busy)
|
|
174
|
+
await new Promise<void>((resolve) => owner.drain.add(resolve));
|
|
175
|
+
await this.retire(owner);
|
|
176
|
+
} else if (owner && !owner.retiring) {
|
|
177
|
+
owner.child.send({ register: descriptor });
|
|
178
|
+
}
|
|
179
|
+
this.options.models = models;
|
|
180
|
+
});
|
|
181
|
+
this.registration = operation.catch(() => {});
|
|
182
|
+
return operation;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async request(
|
|
186
|
+
input: Input,
|
|
187
|
+
expectedGeneration?: number,
|
|
188
|
+
options?: InferenceOptions
|
|
189
|
+
): Promise<NativeResponse["result"]> {
|
|
190
|
+
const operational = inferenceOptions({
|
|
191
|
+
...options,
|
|
192
|
+
deadlineAt: options?.deadlineAt ?? input.deadlineAt,
|
|
193
|
+
});
|
|
194
|
+
const settlement = new InferenceSettlement<
|
|
195
|
+
Extract<NativeResponse["result"], { ok: true }>["value"]
|
|
196
|
+
>(operational, this.options.inferenceTimeout);
|
|
197
|
+
void this.enqueue(
|
|
198
|
+
{ ...input, deadlineAt: operational.deadlineAt },
|
|
199
|
+
expectedGeneration,
|
|
200
|
+
settlement
|
|
201
|
+
).catch(() => {
|
|
202
|
+
settlement.fail(new NativeWorkerError("exited").detail);
|
|
203
|
+
});
|
|
204
|
+
return settlement.completion.then((result) => {
|
|
205
|
+
if (!result.ok && result.error.code === "TIMEOUT")
|
|
206
|
+
recordInferenceTimeout();
|
|
207
|
+
return wireResult(result);
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
private async enqueue(
|
|
212
|
+
input: Input,
|
|
213
|
+
expectedGeneration: number | undefined,
|
|
214
|
+
settlement: Pending["settlement"]
|
|
215
|
+
): Promise<void> {
|
|
216
|
+
const result = await this.admit(input, expectedGeneration, settlement);
|
|
217
|
+
if (settlement.phase === "queued") settlement.startNative();
|
|
218
|
+
settlement.nativeSettled(result);
|
|
219
|
+
settlement.publish();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
private async admit(
|
|
223
|
+
input: Input,
|
|
224
|
+
expectedGeneration: number | undefined,
|
|
225
|
+
settlement: Pending["settlement"]
|
|
226
|
+
): Promise<NativeResponse["result"]> {
|
|
227
|
+
await this.registration;
|
|
228
|
+
if (settlement.signal.aborted)
|
|
229
|
+
return settlement.completion.then(wireResult);
|
|
230
|
+
if (this.closed)
|
|
231
|
+
return {
|
|
232
|
+
ok: false,
|
|
233
|
+
error: wireError(new NativeWorkerError("exited").detail),
|
|
234
|
+
};
|
|
235
|
+
while (this.owner?.quarantined && !this.owner.retiring) {
|
|
236
|
+
try {
|
|
237
|
+
await waitForQuarantine(this.owner, settlement);
|
|
238
|
+
} catch (cause) {
|
|
239
|
+
return {
|
|
240
|
+
ok: false,
|
|
241
|
+
error: wireError(
|
|
242
|
+
(cause instanceof NativeWorkerError
|
|
243
|
+
? cause
|
|
244
|
+
: new NativeWorkerError("exited")
|
|
245
|
+
).detail
|
|
246
|
+
),
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
if (settlement.signal.aborted)
|
|
250
|
+
return settlement.completion.then(wireResult);
|
|
251
|
+
}
|
|
252
|
+
if (this.owner?.retiring) await this.owner.retirement;
|
|
253
|
+
if (this.closed)
|
|
254
|
+
return {
|
|
255
|
+
ok: false,
|
|
256
|
+
error: wireError(new NativeWorkerError("exited").detail),
|
|
257
|
+
};
|
|
258
|
+
if (settlement.signal.aborted)
|
|
259
|
+
return settlement.completion.then(wireResult);
|
|
260
|
+
if (input.op === "dispose" && !this.owner) return { ok: true, value: null };
|
|
261
|
+
try {
|
|
262
|
+
// Metadata-dependent inference must never start/replay on a replacement
|
|
263
|
+
// owner. All asynchronous registration/retirement waits precede this fence.
|
|
264
|
+
if (
|
|
265
|
+
expectedGeneration !== undefined &&
|
|
266
|
+
(!this.owner ||
|
|
267
|
+
this.owner.retiring ||
|
|
268
|
+
this.owner.generation !== expectedGeneration)
|
|
269
|
+
)
|
|
270
|
+
throw new NativeWorkerError("stale_generation");
|
|
271
|
+
const owner = this.owner ?? this.start();
|
|
272
|
+
const request = parseNativeRequest(
|
|
273
|
+
{
|
|
274
|
+
...input,
|
|
275
|
+
deadlineAt: input.deadlineAt,
|
|
276
|
+
version: 1,
|
|
277
|
+
generation: owner.generation,
|
|
278
|
+
requestId: ++this.requestId,
|
|
279
|
+
},
|
|
280
|
+
owner.generation,
|
|
281
|
+
this.options.models
|
|
282
|
+
);
|
|
283
|
+
owner.ledger.admit(request);
|
|
284
|
+
return new Promise((resolve) => {
|
|
285
|
+
const pending: Pending = {
|
|
286
|
+
request,
|
|
287
|
+
resolve,
|
|
288
|
+
settlement,
|
|
289
|
+
background: isBackgroundInference(),
|
|
290
|
+
};
|
|
291
|
+
owner.pending.push(pending);
|
|
292
|
+
settlement.signal.addEventListener(
|
|
293
|
+
"abort",
|
|
294
|
+
() => this.cancel(owner, pending),
|
|
295
|
+
{ once: true }
|
|
296
|
+
);
|
|
297
|
+
if (settlement.signal.aborted) this.cancel(owner, pending);
|
|
298
|
+
if (owner.pending.length === 1 && owner.ready) this.sendNext(owner);
|
|
299
|
+
});
|
|
300
|
+
} catch (cause) {
|
|
301
|
+
return {
|
|
302
|
+
ok: false,
|
|
303
|
+
error: wireError(
|
|
304
|
+
(cause instanceof NativeWorkerError
|
|
305
|
+
? cause
|
|
306
|
+
: new NativeWorkerError("exited")
|
|
307
|
+
).detail
|
|
308
|
+
),
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
private start(): Owner {
|
|
314
|
+
this.lifecycle = undefined;
|
|
315
|
+
// A compiled executable cannot interpret an external TS entry: invoking it
|
|
316
|
+
// here would recursively launch the CLI. npm/desktop ship the source runtime.
|
|
317
|
+
if (import.meta.dir.includes("$bunfs"))
|
|
318
|
+
throw new NativeWorkerError("exited");
|
|
319
|
+
const config: NativeRuntimeConfig = NativeRuntimeConfigSchema.parse({
|
|
320
|
+
generation: ++this.generation,
|
|
321
|
+
models: this.options.models,
|
|
322
|
+
loadTimeout: this.options.loadTimeout,
|
|
323
|
+
inferenceTimeout: this.options.inferenceTimeout,
|
|
324
|
+
warmModelTtl: this.options.warmModelTtl ?? 300_000,
|
|
325
|
+
});
|
|
326
|
+
// IPC callbacks execute after this synchronous ownership publication.
|
|
327
|
+
const child = Bun.spawn({
|
|
328
|
+
cmd: [
|
|
329
|
+
process.execPath,
|
|
330
|
+
"--no-env-file",
|
|
331
|
+
this.options.entryPath ?? `${import.meta.dir}/entry.ts`,
|
|
332
|
+
JSON.stringify(config),
|
|
333
|
+
],
|
|
334
|
+
env: nativeWorkerEnvironment(),
|
|
335
|
+
stdin: "ignore",
|
|
336
|
+
stdout: "ignore",
|
|
337
|
+
stderr: "inherit",
|
|
338
|
+
serialization: "advanced",
|
|
339
|
+
ipc: (message) => this.receive(owner, message),
|
|
340
|
+
});
|
|
341
|
+
const owner: Owner = {
|
|
342
|
+
generation: config.generation,
|
|
343
|
+
child,
|
|
344
|
+
ledger: new NativeRequestLedger(config.generation),
|
|
345
|
+
decoder: new NativeFrameDecoder(config.generation),
|
|
346
|
+
pending: [],
|
|
347
|
+
foregroundCompletions: 0,
|
|
348
|
+
ready: false,
|
|
349
|
+
busy: false,
|
|
350
|
+
quarantined: false,
|
|
351
|
+
waiters: new Set(),
|
|
352
|
+
retiring: false,
|
|
353
|
+
drain: new Set(),
|
|
354
|
+
};
|
|
355
|
+
this.owner = owner;
|
|
356
|
+
owner.timer = setTimeout(
|
|
357
|
+
() => this.fail(owner, new NativeWorkerError("timeout")),
|
|
358
|
+
this.options.loadTimeout
|
|
359
|
+
);
|
|
360
|
+
void child.exited.then(() => {
|
|
361
|
+
this.fail(owner, new NativeWorkerError("exited"));
|
|
362
|
+
this.finishOwner(owner, new NativeWorkerError("exited"));
|
|
363
|
+
if (this.owner === owner) this.owner = undefined;
|
|
364
|
+
releaseQuarantine(owner);
|
|
365
|
+
});
|
|
366
|
+
return owner;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
private receive(owner: Owner, message: unknown): void {
|
|
370
|
+
if (owner.retiring || this.owner !== owner) return;
|
|
371
|
+
try {
|
|
372
|
+
if (message === "ready") {
|
|
373
|
+
if (owner.ready) throw new NativeWorkerError("protocol");
|
|
374
|
+
owner.ready = true;
|
|
375
|
+
clearTimeout(owner.timer);
|
|
376
|
+
this.sendNext(owner);
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
if (message === "idle") {
|
|
380
|
+
this.idleOwner = owner;
|
|
381
|
+
if (!this.leases && !owner.pending.length && !owner.busy)
|
|
382
|
+
void this.retire(owner).catch((error: unknown) =>
|
|
383
|
+
console.error(error)
|
|
384
|
+
);
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
if (
|
|
388
|
+
typeof message === "object" &&
|
|
389
|
+
message !== null &&
|
|
390
|
+
"executionStarted" in message
|
|
391
|
+
) {
|
|
392
|
+
const parsed = NativeExecutionStartedSchema.safeParse(message);
|
|
393
|
+
const pending = owner.pending[0];
|
|
394
|
+
if (
|
|
395
|
+
!parsed.success ||
|
|
396
|
+
!owner.busy ||
|
|
397
|
+
!pending ||
|
|
398
|
+
pending.executionStarted ||
|
|
399
|
+
["init", "dispose"].includes(pending.request.op) ||
|
|
400
|
+
parsed.data.generation !== owner.generation ||
|
|
401
|
+
parsed.data.requestId !== pending.request.requestId
|
|
402
|
+
)
|
|
403
|
+
throw new NativeWorkerError("protocol");
|
|
404
|
+
if (
|
|
405
|
+
pending.loadDeadline !== undefined &&
|
|
406
|
+
performance.now() >= pending.loadDeadline
|
|
407
|
+
)
|
|
408
|
+
pending.settlement.cancel("timeout");
|
|
409
|
+
pending.loadDeadline = undefined;
|
|
410
|
+
pending.executionStarted = true;
|
|
411
|
+
clearTimeout(owner.timer);
|
|
412
|
+
pending.settlement.startExecution();
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
if (!(message instanceof Uint8Array))
|
|
416
|
+
throw new NativeWorkerError("protocol");
|
|
417
|
+
const decoded = owner.decoder.push(message);
|
|
418
|
+
if (decoded === undefined) return;
|
|
419
|
+
const response = owner.ledger.settle(decoded);
|
|
420
|
+
const pending = owner.pending[0];
|
|
421
|
+
if (pending?.request.requestId !== response.requestId)
|
|
422
|
+
throw new NativeWorkerError("protocol");
|
|
423
|
+
clearTimeout(owner.timer);
|
|
424
|
+
if (
|
|
425
|
+
pending.loadDeadline !== undefined &&
|
|
426
|
+
performance.now() >= pending.loadDeadline
|
|
427
|
+
)
|
|
428
|
+
pending.settlement.cancel("timeout");
|
|
429
|
+
clearTimeout(pending.cancelTimer);
|
|
430
|
+
owner.pending.shift();
|
|
431
|
+
recordCompletion(owner, pending);
|
|
432
|
+
releaseQuarantine(owner);
|
|
433
|
+
if (response.lifecycle) this.lifecycle = response.lifecycle;
|
|
434
|
+
pending.resolve(response.result);
|
|
435
|
+
// Promise delivery has been queued before acknowledging settlement.
|
|
436
|
+
queueMicrotask(() => {
|
|
437
|
+
if (owner.retiring) return;
|
|
438
|
+
try {
|
|
439
|
+
owner.child.send({ ack: response.requestId });
|
|
440
|
+
owner.busy = false;
|
|
441
|
+
if (!owner.pending.length) {
|
|
442
|
+
for (const resolve of owner.drain) resolve();
|
|
443
|
+
owner.drain.clear();
|
|
444
|
+
}
|
|
445
|
+
this.sendNext(owner);
|
|
446
|
+
} catch {
|
|
447
|
+
this.fail(owner, new NativeWorkerError("exited"));
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
} catch (cause) {
|
|
451
|
+
this.fail(
|
|
452
|
+
owner,
|
|
453
|
+
cause instanceof NativeWorkerError
|
|
454
|
+
? cause
|
|
455
|
+
: new NativeWorkerError("protocol")
|
|
456
|
+
);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
private sendNext(owner: Owner): void {
|
|
461
|
+
if (!owner.ready || owner.retiring || owner.busy) return;
|
|
462
|
+
selectNext(owner);
|
|
463
|
+
const pending = owner.pending[0];
|
|
464
|
+
if (!pending) return;
|
|
465
|
+
this.idleOwner = undefined;
|
|
466
|
+
if (!pending.settlement.startNative()) {
|
|
467
|
+
this.cancel(owner, pending);
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
owner.busy = true;
|
|
471
|
+
pending.loadDeadline = performance.now() + this.options.loadTimeout;
|
|
472
|
+
clearTimeout(owner.timer);
|
|
473
|
+
owner.timer = setTimeout(
|
|
474
|
+
() => pending.settlement.cancel("timeout"),
|
|
475
|
+
this.options.loadTimeout
|
|
476
|
+
);
|
|
477
|
+
try {
|
|
478
|
+
for (const frame of frameNativeMessage(pending.request))
|
|
479
|
+
owner.child.send(frame);
|
|
480
|
+
} catch {
|
|
481
|
+
this.fail(owner, new NativeWorkerError("exited"));
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
private cancel(owner: Owner, pending: Pending): void {
|
|
486
|
+
cancelPending(
|
|
487
|
+
owner,
|
|
488
|
+
pending,
|
|
489
|
+
(current, error) => this.fail(current, error),
|
|
490
|
+
(current) => this.sendNext(current)
|
|
491
|
+
);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
private fail(owner: Owner, error: NativeWorkerError): void {
|
|
495
|
+
if (owner.retiring) return;
|
|
496
|
+
// Delivery can fail now; ownership is acknowledged only after child exit.
|
|
497
|
+
for (const pending of owner.pending) {
|
|
498
|
+
clearTimeout(pending.cancelTimer);
|
|
499
|
+
pending.settlement.fail(error.detail);
|
|
500
|
+
}
|
|
501
|
+
void this.retire(owner, { force: true }).catch((cause: unknown) =>
|
|
502
|
+
console.error(cause)
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
private retire(
|
|
507
|
+
owner: Owner,
|
|
508
|
+
options: NativeDisposeOptions = {}
|
|
509
|
+
): Promise<void> {
|
|
510
|
+
return retireOwnedChild(owner, options).then(() => {
|
|
511
|
+
if (this.owner === owner) this.owner = undefined;
|
|
512
|
+
releaseQuarantine(owner);
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
async dispose(options: NativeDisposeOptions = {}): Promise<void> {
|
|
517
|
+
this.closed = true;
|
|
518
|
+
const owner = this.owner;
|
|
519
|
+
if (!owner) {
|
|
520
|
+
process.removeListener("exit", this.onParentExit);
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
const failure = new NativeWorkerError("exited");
|
|
524
|
+
for (const pending of owner.pending) {
|
|
525
|
+
clearTimeout(pending.cancelTimer);
|
|
526
|
+
pending.settlement.fail(failure.detail);
|
|
527
|
+
}
|
|
528
|
+
await this.retire(owner, options);
|
|
529
|
+
process.removeListener("exit", this.onParentExit);
|
|
530
|
+
this.finishOwner(owner, failure);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
private finishOwner(owner: Owner, failure: NativeWorkerError): void {
|
|
534
|
+
for (const response of owner.ledger.failAll(failure))
|
|
535
|
+
owner.pending
|
|
536
|
+
.find((entry) => entry.request.requestId === response.requestId)
|
|
537
|
+
?.resolve(response.result);
|
|
538
|
+
owner.pending.length = 0;
|
|
539
|
+
owner.busy = false;
|
|
540
|
+
}
|
|
541
|
+
}
|