@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,141 @@
|
|
|
1
|
+
import type { InferenceSettlement } from "../inference-cancellation";
|
|
2
|
+
import type { LlmResult } from "../types";
|
|
3
|
+
import type { OwnedExitControl } from "./owned-exit";
|
|
4
|
+
import type {
|
|
5
|
+
NativeRequest,
|
|
6
|
+
NativeResponse,
|
|
7
|
+
NativeRequestLedger,
|
|
8
|
+
NativeFrameDecoder,
|
|
9
|
+
} from "./protocol";
|
|
10
|
+
|
|
11
|
+
import { NativeWorkerError } from "./errors";
|
|
12
|
+
import { NATIVE_QUEUE_LIMIT } from "./protocol";
|
|
13
|
+
import { wireError } from "./runtime-config";
|
|
14
|
+
|
|
15
|
+
export function wireResult(
|
|
16
|
+
result: LlmResult<Extract<NativeResponse["result"], { ok: true }>["value"]>
|
|
17
|
+
): NativeResponse["result"] {
|
|
18
|
+
return result.ok ? result : { ok: false, error: wireError(result.error) };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
type Child = ReturnType<typeof Bun.spawn>;
|
|
22
|
+
export interface Pending {
|
|
23
|
+
background: boolean;
|
|
24
|
+
request: NativeRequest;
|
|
25
|
+
settlement: InferenceSettlement<
|
|
26
|
+
Extract<NativeResponse["result"], { ok: true }>["value"]
|
|
27
|
+
>;
|
|
28
|
+
resolve(value: NativeResponse["result"]): void;
|
|
29
|
+
executionStarted?: boolean;
|
|
30
|
+
loadDeadline?: number;
|
|
31
|
+
cancelTimer?: ReturnType<typeof setTimeout>;
|
|
32
|
+
}
|
|
33
|
+
export interface Owner {
|
|
34
|
+
foregroundCompletions: number;
|
|
35
|
+
generation: number;
|
|
36
|
+
child: Child;
|
|
37
|
+
ledger: NativeRequestLedger;
|
|
38
|
+
decoder: NativeFrameDecoder;
|
|
39
|
+
pending: Pending[];
|
|
40
|
+
ready: boolean;
|
|
41
|
+
busy: boolean;
|
|
42
|
+
quarantined: boolean;
|
|
43
|
+
waiters: Set<() => void>;
|
|
44
|
+
retiring: boolean;
|
|
45
|
+
timer?: ReturnType<typeof setTimeout>;
|
|
46
|
+
retirement?: Promise<void>;
|
|
47
|
+
retirementControl?: OwnedExitControl;
|
|
48
|
+
drain: Set<() => void>;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Only waiting work may move; the active request remains pending[0] through ACK. */
|
|
52
|
+
export function selectNext(owner: Owner): void {
|
|
53
|
+
if (owner.busy) return;
|
|
54
|
+
const backgroundIndex = owner.pending.findIndex((entry) => entry.background);
|
|
55
|
+
const foregroundIndex = owner.pending.findIndex((entry) => !entry.background);
|
|
56
|
+
const index =
|
|
57
|
+
backgroundIndex >= 0 &&
|
|
58
|
+
(foregroundIndex < 0 || owner.foregroundCompletions >= 8)
|
|
59
|
+
? backgroundIndex
|
|
60
|
+
: foregroundIndex;
|
|
61
|
+
if (index > 0) owner.pending.unshift(owner.pending.splice(index, 1)[0]!);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function recordCompletion(owner: Owner, pending: Pending): void {
|
|
65
|
+
// Metadata prepares a batch but does not perform inference or pay its debt.
|
|
66
|
+
if (pending.request.op === "init" || pending.request.op === "dispose") return;
|
|
67
|
+
if (pending.background) owner.foregroundCompletions = 0;
|
|
68
|
+
else if (owner.pending.some((entry) => entry.background))
|
|
69
|
+
owner.foregroundCompletions = Math.min(8, owner.foregroundCompletions + 1);
|
|
70
|
+
// Preserve earned service across a metadata/partition preparation gap. Only
|
|
71
|
+
// actual background inference pays it; an empty queue is not completed work.
|
|
72
|
+
}
|
|
73
|
+
export function cancelPending(
|
|
74
|
+
owner: Owner,
|
|
75
|
+
pending: Pending,
|
|
76
|
+
fail: (owner: Owner, error: NativeWorkerError) => void,
|
|
77
|
+
sendNext: (owner: Owner) => void
|
|
78
|
+
): void {
|
|
79
|
+
const index = owner.pending.indexOf(pending);
|
|
80
|
+
if (index < 0 || owner.retiring) return;
|
|
81
|
+
if (index === 0 && owner.busy) {
|
|
82
|
+
owner.quarantined = true;
|
|
83
|
+
clearTimeout(owner.timer);
|
|
84
|
+
try {
|
|
85
|
+
owner.child.send({
|
|
86
|
+
version: 1,
|
|
87
|
+
generation: owner.generation,
|
|
88
|
+
requestId: pending.request.requestId,
|
|
89
|
+
cancel:
|
|
90
|
+
pending.settlement.signal.reason?.name === "TimeoutError"
|
|
91
|
+
? "timeout"
|
|
92
|
+
: "abort",
|
|
93
|
+
});
|
|
94
|
+
} catch {
|
|
95
|
+
fail(owner, new NativeWorkerError("exited"));
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
// This owner runs exactly one native operation. Quarantine it until that
|
|
99
|
+
// operation settles; after grace, only this owned child may be retired.
|
|
100
|
+
pending.cancelTimer = setTimeout(
|
|
101
|
+
() => fail(owner, new NativeWorkerError("timeout")),
|
|
102
|
+
5000
|
|
103
|
+
);
|
|
104
|
+
} else {
|
|
105
|
+
owner.pending.splice(index, 1);
|
|
106
|
+
owner.ledger.cancelQueued(pending.request.requestId);
|
|
107
|
+
void pending.settlement.completion.then((result) =>
|
|
108
|
+
pending.resolve(wireResult(result))
|
|
109
|
+
);
|
|
110
|
+
if (!owner.busy) {
|
|
111
|
+
if (!owner.pending.length) {
|
|
112
|
+
for (const resolve of owner.drain) resolve();
|
|
113
|
+
owner.drain.clear();
|
|
114
|
+
}
|
|
115
|
+
sendNext(owner);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Admission remains bounded while a canceled owner cannot accept new work. */
|
|
121
|
+
export function waitForQuarantine(
|
|
122
|
+
owner: Owner,
|
|
123
|
+
settlement: Pending["settlement"]
|
|
124
|
+
): Promise<void> {
|
|
125
|
+
if (owner.ledger.size + owner.waiters.size >= NATIVE_QUEUE_LIMIT + 1)
|
|
126
|
+
throw new NativeWorkerError("overloaded");
|
|
127
|
+
return new Promise((resolve) => {
|
|
128
|
+
const finish = () => {
|
|
129
|
+
owner.waiters.delete(finish);
|
|
130
|
+
settlement.signal.removeEventListener("abort", finish);
|
|
131
|
+
resolve();
|
|
132
|
+
};
|
|
133
|
+
owner.waiters.add(finish);
|
|
134
|
+
settlement.signal.addEventListener("abort", finish, { once: true });
|
|
135
|
+
if (settlement.signal.aborted) finish();
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
export function releaseQuarantine(owner: Owner): void {
|
|
139
|
+
owner.quarantined = false;
|
|
140
|
+
for (const finish of owner.waiters) finish();
|
|
141
|
+
}
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
import type { InferenceOptions } from "../types";
|
|
4
|
+
import type {
|
|
5
|
+
EmbeddingPort,
|
|
6
|
+
EmbeddingIdentity,
|
|
7
|
+
GenerationPort,
|
|
8
|
+
GenParams,
|
|
9
|
+
LlmResult,
|
|
10
|
+
RerankPort,
|
|
11
|
+
RerankScore,
|
|
12
|
+
} from "../types";
|
|
13
|
+
import type { NativeWorkerClient } from "./client";
|
|
14
|
+
import type { NativeResponse } from "./protocol";
|
|
15
|
+
|
|
16
|
+
import { inferenceOptions, finishInferenceCleanup } from "../inference-scope";
|
|
17
|
+
import { NativeWorkerError } from "./errors";
|
|
18
|
+
import { EmbeddingIdentitySchema } from "./protocol";
|
|
19
|
+
|
|
20
|
+
const vector = z.array(z.number().finite()).min(1);
|
|
21
|
+
const scores = z.array(
|
|
22
|
+
z.strictObject({
|
|
23
|
+
index: z.number().int().nonnegative(),
|
|
24
|
+
score: z.number().finite(),
|
|
25
|
+
rank: z.number().int().positive(),
|
|
26
|
+
})
|
|
27
|
+
);
|
|
28
|
+
const metadata = z.object({
|
|
29
|
+
dimensions: z.number().int().positive(),
|
|
30
|
+
embeddingIdentity: EmbeddingIdentitySchema,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
function decode<T>(
|
|
34
|
+
result: NativeResponse["result"],
|
|
35
|
+
schema: z.ZodType<T>
|
|
36
|
+
): LlmResult<T> {
|
|
37
|
+
if (!result.ok) return result;
|
|
38
|
+
const parsed = schema.safeParse(result.value);
|
|
39
|
+
return parsed.success
|
|
40
|
+
? { ok: true, value: parsed.data }
|
|
41
|
+
: { ok: false, error: new NativeWorkerError("protocol").detail };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
class NativePort {
|
|
45
|
+
constructor(
|
|
46
|
+
protected readonly client: NativeWorkerClient,
|
|
47
|
+
protected readonly modelId: string,
|
|
48
|
+
readonly modelUri: string
|
|
49
|
+
) {}
|
|
50
|
+
|
|
51
|
+
async dispose(): Promise<void> {
|
|
52
|
+
// Disposing an unused/retired port must not launch a child.
|
|
53
|
+
if (this.client.processId === undefined) return;
|
|
54
|
+
return finishInferenceCleanup(async () => {
|
|
55
|
+
const result = await this.client.request({
|
|
56
|
+
op: "dispose",
|
|
57
|
+
modelId: this.modelId,
|
|
58
|
+
});
|
|
59
|
+
if (!result.ok) throw new Error(result.error.message);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Metadata and complete vectors cross IPC; no tokenizer/native objects in parent. */
|
|
65
|
+
export class NativeEmbeddingPort extends NativePort implements EmbeddingPort {
|
|
66
|
+
private dims: number | undefined;
|
|
67
|
+
private generation = 0;
|
|
68
|
+
private identity?: EmbeddingIdentity;
|
|
69
|
+
private initializing?: Promise<LlmResult<void>>;
|
|
70
|
+
private version = 0;
|
|
71
|
+
private disposing = false;
|
|
72
|
+
|
|
73
|
+
async init(options?: InferenceOptions): Promise<LlmResult<void>> {
|
|
74
|
+
return this.withIdentity(
|
|
75
|
+
async () => ({ ok: true, value: undefined }),
|
|
76
|
+
options
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private async loadIdentity(
|
|
81
|
+
version: number,
|
|
82
|
+
options?: InferenceOptions
|
|
83
|
+
): Promise<LlmResult<void>> {
|
|
84
|
+
const result = decode(
|
|
85
|
+
await this.client.request(
|
|
86
|
+
{ op: "init", modelId: this.modelId },
|
|
87
|
+
undefined,
|
|
88
|
+
options
|
|
89
|
+
),
|
|
90
|
+
metadata
|
|
91
|
+
);
|
|
92
|
+
if (!result.ok) return result;
|
|
93
|
+
if (
|
|
94
|
+
version !== this.version ||
|
|
95
|
+
this.disposing ||
|
|
96
|
+
this.client.processId === undefined
|
|
97
|
+
)
|
|
98
|
+
return {
|
|
99
|
+
ok: false,
|
|
100
|
+
error: new NativeWorkerError("stale_generation").detail,
|
|
101
|
+
};
|
|
102
|
+
this.dims = result.value.dimensions;
|
|
103
|
+
this.identity = result.value.embeddingIdentity;
|
|
104
|
+
this.generation = this.client.currentGeneration;
|
|
105
|
+
return { ok: true, value: undefined };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private async ensureIdentity(
|
|
109
|
+
options?: InferenceOptions
|
|
110
|
+
): Promise<LlmResult<void>> {
|
|
111
|
+
if (this.getIdentity()) return { ok: true, value: undefined };
|
|
112
|
+
if (options?.signal || options?.deadlineAt !== undefined)
|
|
113
|
+
return this.loadIdentity(this.version, options);
|
|
114
|
+
if (this.initializing) return this.initializing;
|
|
115
|
+
this.identity = undefined;
|
|
116
|
+
this.dims = undefined;
|
|
117
|
+
const pending = this.loadIdentity(this.version);
|
|
118
|
+
this.initializing = pending;
|
|
119
|
+
try {
|
|
120
|
+
return await pending;
|
|
121
|
+
} finally {
|
|
122
|
+
if (this.initializing === pending) this.initializing = undefined;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
private async withIdentity<T>(
|
|
127
|
+
operation: (generation: number) => Promise<LlmResult<T>>,
|
|
128
|
+
options?: InferenceOptions
|
|
129
|
+
): Promise<LlmResult<T>> {
|
|
130
|
+
let lease: { release(): void } | undefined;
|
|
131
|
+
const version = this.version;
|
|
132
|
+
try {
|
|
133
|
+
lease = this.client.acquireLease();
|
|
134
|
+
if (this.disposing)
|
|
135
|
+
return {
|
|
136
|
+
ok: false,
|
|
137
|
+
error: new NativeWorkerError("stale_generation").detail,
|
|
138
|
+
};
|
|
139
|
+
options = inferenceOptions(options);
|
|
140
|
+
const initialized = await this.ensureIdentity(options);
|
|
141
|
+
if (!initialized.ok) return initialized;
|
|
142
|
+
if (version !== this.version || this.disposing)
|
|
143
|
+
return {
|
|
144
|
+
ok: false,
|
|
145
|
+
error: new NativeWorkerError("stale_generation").detail,
|
|
146
|
+
};
|
|
147
|
+
const generation = this.generation;
|
|
148
|
+
const identity = this.identity;
|
|
149
|
+
const result = await operation(generation);
|
|
150
|
+
if (!result.ok) {
|
|
151
|
+
this.identity = undefined;
|
|
152
|
+
return result;
|
|
153
|
+
}
|
|
154
|
+
if (
|
|
155
|
+
version !== this.version ||
|
|
156
|
+
generation !== this.client.currentGeneration ||
|
|
157
|
+
this.client.processId === undefined
|
|
158
|
+
) {
|
|
159
|
+
this.identity = undefined;
|
|
160
|
+
return {
|
|
161
|
+
ok: false,
|
|
162
|
+
error: new NativeWorkerError("stale_generation").detail,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
this.identity = identity;
|
|
166
|
+
return result;
|
|
167
|
+
} catch (cause) {
|
|
168
|
+
this.identity = undefined;
|
|
169
|
+
return {
|
|
170
|
+
ok: false,
|
|
171
|
+
error: (cause instanceof NativeWorkerError
|
|
172
|
+
? cause
|
|
173
|
+
: new NativeWorkerError("exited")
|
|
174
|
+
).detail,
|
|
175
|
+
};
|
|
176
|
+
} finally {
|
|
177
|
+
lease?.release();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private acceptDimensions(length: number): boolean {
|
|
182
|
+
return (
|
|
183
|
+
this.generation === this.client.currentGeneration && this.dims === length
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
async embed(
|
|
188
|
+
text: string,
|
|
189
|
+
options?: InferenceOptions
|
|
190
|
+
): Promise<LlmResult<number[]>> {
|
|
191
|
+
return this.withIdentity(async (generation) => {
|
|
192
|
+
const result = decode(
|
|
193
|
+
await this.client.request(
|
|
194
|
+
{ op: "embed", modelId: this.modelId, text },
|
|
195
|
+
generation,
|
|
196
|
+
options
|
|
197
|
+
),
|
|
198
|
+
vector
|
|
199
|
+
);
|
|
200
|
+
if (result.ok && !this.acceptDimensions(result.value.length)) {
|
|
201
|
+
await this.client.disposeModel(this.modelUri);
|
|
202
|
+
return { ok: false, error: new NativeWorkerError("protocol").detail };
|
|
203
|
+
}
|
|
204
|
+
return result;
|
|
205
|
+
}, options);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
async embedBatch(
|
|
209
|
+
texts: string[],
|
|
210
|
+
options?: InferenceOptions
|
|
211
|
+
): Promise<LlmResult<number[][]>> {
|
|
212
|
+
if (!texts.length) return { ok: true, value: [] };
|
|
213
|
+
return this.withIdentity(async (generation) => {
|
|
214
|
+
const result = decode(
|
|
215
|
+
await this.client.request(
|
|
216
|
+
{
|
|
217
|
+
op: "embedBatch",
|
|
218
|
+
modelId: this.modelId,
|
|
219
|
+
texts,
|
|
220
|
+
},
|
|
221
|
+
generation,
|
|
222
|
+
options
|
|
223
|
+
),
|
|
224
|
+
z.array(vector).length(texts.length)
|
|
225
|
+
);
|
|
226
|
+
if (
|
|
227
|
+
result.ok &&
|
|
228
|
+
result.value.some((item) => !this.acceptDimensions(item.length))
|
|
229
|
+
) {
|
|
230
|
+
await this.client.disposeModel(this.modelUri);
|
|
231
|
+
return { ok: false, error: new NativeWorkerError("protocol").detail };
|
|
232
|
+
}
|
|
233
|
+
return result;
|
|
234
|
+
}, options);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
dimensions(): number {
|
|
238
|
+
if (this.dims === undefined)
|
|
239
|
+
throw new Error("Call init() or embed() first to initialize dimensions");
|
|
240
|
+
return this.dims;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
getIdentity(): EmbeddingIdentity | undefined {
|
|
244
|
+
if (
|
|
245
|
+
this.generation !== this.client.currentGeneration ||
|
|
246
|
+
this.client.processId === undefined ||
|
|
247
|
+
this.disposing
|
|
248
|
+
)
|
|
249
|
+
return;
|
|
250
|
+
return this.identity && { ...this.identity };
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
override async dispose(): Promise<void> {
|
|
254
|
+
this.version++;
|
|
255
|
+
this.disposing = true;
|
|
256
|
+
this.initializing = undefined;
|
|
257
|
+
this.dims = undefined;
|
|
258
|
+
this.identity = undefined;
|
|
259
|
+
try {
|
|
260
|
+
await super.dispose();
|
|
261
|
+
} finally {
|
|
262
|
+
this.disposing = false;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export class NativeGenerationPort extends NativePort implements GenerationPort {
|
|
268
|
+
readonly structuredOutput = "json_schema" as const;
|
|
269
|
+
|
|
270
|
+
async generate(
|
|
271
|
+
prompt: string,
|
|
272
|
+
params?: GenParams,
|
|
273
|
+
options?: InferenceOptions
|
|
274
|
+
): Promise<LlmResult<string>> {
|
|
275
|
+
const schema = z
|
|
276
|
+
.record(z.string(), z.json())
|
|
277
|
+
.optional()
|
|
278
|
+
.safeParse(params?.jsonSchema);
|
|
279
|
+
if (!schema.success)
|
|
280
|
+
return { ok: false, error: new NativeWorkerError("protocol").detail };
|
|
281
|
+
return decode(
|
|
282
|
+
await this.client.request(
|
|
283
|
+
{
|
|
284
|
+
op: "generate",
|
|
285
|
+
modelId: this.modelId,
|
|
286
|
+
prompt,
|
|
287
|
+
params: params && { ...params, jsonSchema: schema.data },
|
|
288
|
+
},
|
|
289
|
+
undefined,
|
|
290
|
+
options
|
|
291
|
+
),
|
|
292
|
+
z.string()
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
export class NativeRerankPort extends NativePort implements RerankPort {
|
|
298
|
+
async rerank(
|
|
299
|
+
query: string,
|
|
300
|
+
documents: string[],
|
|
301
|
+
options?: InferenceOptions
|
|
302
|
+
): Promise<LlmResult<RerankScore[]>> {
|
|
303
|
+
return decode(
|
|
304
|
+
await this.client.request(
|
|
305
|
+
{
|
|
306
|
+
op: "rerank",
|
|
307
|
+
modelId: this.modelId,
|
|
308
|
+
query,
|
|
309
|
+
documents,
|
|
310
|
+
},
|
|
311
|
+
undefined,
|
|
312
|
+
options
|
|
313
|
+
),
|
|
314
|
+
scores.length(documents.length)
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
}
|