@alisio/plugin-semantic 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.es.md +152 -0
- package/README.md +144 -2
- package/THIRD_PARTY_NOTICES.md +42 -0
- package/assets/architecture.svg +1 -0
- package/assets/ask-flow.svg +1 -0
- package/cover.svg +53 -0
- package/dist/apps.d.ts +26 -0
- package/dist/apps.d.ts.map +1 -0
- package/dist/apps.js +135 -0
- package/dist/apps.js.map +1 -0
- package/dist/embedded.html +2194 -0
- package/dist/engine/download.d.ts +77 -0
- package/dist/engine/download.d.ts.map +1 -0
- package/dist/engine/download.js +213 -0
- package/dist/engine/download.js.map +1 -0
- package/dist/engine/embedder.d.ts +55 -0
- package/dist/engine/embedder.d.ts.map +1 -0
- package/dist/engine/embedder.js +182 -0
- package/dist/engine/embedder.js.map +1 -0
- package/dist/engine/infer.d.ts +22 -0
- package/dist/engine/infer.d.ts.map +1 -0
- package/dist/engine/infer.js +53 -0
- package/dist/engine/infer.js.map +1 -0
- package/dist/engine/models.d.ts +45 -0
- package/dist/engine/models.d.ts.map +1 -0
- package/dist/engine/models.js +132 -0
- package/dist/engine/models.js.map +1 -0
- package/dist/engine/runtime.d.ts +46 -0
- package/dist/engine/runtime.d.ts.map +1 -0
- package/dist/engine/runtime.js +172 -0
- package/dist/engine/runtime.js.map +1 -0
- package/dist/engine/setup.d.ts +82 -0
- package/dist/engine/setup.d.ts.map +1 -0
- package/dist/engine/setup.js +183 -0
- package/dist/engine/setup.js.map +1 -0
- package/dist/engine/store.d.ts +46 -0
- package/dist/engine/store.d.ts.map +1 -0
- package/dist/engine/store.js +280 -0
- package/dist/engine/store.js.map +1 -0
- package/dist/engine/tar.d.ts +18 -0
- package/dist/engine/tar.d.ts.map +1 -0
- package/dist/engine/tar.js +198 -0
- package/dist/engine/tar.js.map +1 -0
- package/dist/engine/worker.d.ts +2 -0
- package/dist/engine/worker.d.ts.map +1 -0
- package/dist/engine/worker.js +64 -0
- package/dist/engine/worker.js.map +1 -0
- package/dist/errors.d.ts +15 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +58 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +258 -0
- package/dist/index.js.map +1 -0
- package/dist/messages.d.ts +53 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/messages.js +118 -0
- package/dist/messages.js.map +1 -0
- package/dist/notebook/answer.d.ts +33 -0
- package/dist/notebook/answer.d.ts.map +1 -0
- package/dist/notebook/answer.js +77 -0
- package/dist/notebook/answer.js.map +1 -0
- package/dist/notebook/chunk.d.ts +23 -0
- package/dist/notebook/chunk.d.ts.map +1 -0
- package/dist/notebook/chunk.js +124 -0
- package/dist/notebook/chunk.js.map +1 -0
- package/dist/notebook/db.d.ts +98 -0
- package/dist/notebook/db.d.ts.map +1 -0
- package/dist/notebook/db.js +328 -0
- package/dist/notebook/db.js.map +1 -0
- package/dist/notebook/docx.d.ts +3 -0
- package/dist/notebook/docx.d.ts.map +1 -0
- package/dist/notebook/docx.js +16 -0
- package/dist/notebook/docx.js.map +1 -0
- package/dist/notebook/extract.d.ts +11 -0
- package/dist/notebook/extract.d.ts.map +1 -0
- package/dist/notebook/extract.js +99 -0
- package/dist/notebook/extract.js.map +1 -0
- package/dist/notebook/jobs.d.ts +31 -0
- package/dist/notebook/jobs.d.ts.map +1 -0
- package/dist/notebook/jobs.js +84 -0
- package/dist/notebook/jobs.js.map +1 -0
- package/dist/notebook/ooxml.d.ts +6 -0
- package/dist/notebook/ooxml.d.ts.map +1 -0
- package/dist/notebook/ooxml.js +131 -0
- package/dist/notebook/ooxml.js.map +1 -0
- package/dist/notebook/retrieve.d.ts +14 -0
- package/dist/notebook/retrieve.d.ts.map +1 -0
- package/dist/notebook/retrieve.js +37 -0
- package/dist/notebook/retrieve.js.map +1 -0
- package/dist/notebook/service.d.ts +72 -0
- package/dist/notebook/service.d.ts.map +1 -0
- package/dist/notebook/service.js +620 -0
- package/dist/notebook/service.js.map +1 -0
- package/dist/notebook/workspace.d.ts +17 -0
- package/dist/notebook/workspace.d.ts.map +1 -0
- package/dist/notebook/workspace.js +75 -0
- package/dist/notebook/workspace.js.map +1 -0
- package/dist/notebook/zip.d.ts +33 -0
- package/dist/notebook/zip.d.ts.map +1 -0
- package/dist/notebook/zip.js +154 -0
- package/dist/notebook/zip.js.map +1 -0
- package/dist/paths.d.ts +17 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +28 -0
- package/dist/paths.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/icon.svg +16 -0
- package/package.json +62 -3
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
// Streaming, allow-list tar.gz extraction for the pinned ONNX Runtime npm tarballs (owner O9).
|
|
2
|
+
// Rejects absolute paths, `..`, backslashes, links and device entries anywhere in the archive, caps
|
|
3
|
+
// entry count and sizes, and writes only the files `select` keeps.
|
|
4
|
+
import { createHash } from "node:crypto";
|
|
5
|
+
import { createReadStream } from "node:fs";
|
|
6
|
+
import { mkdir, open } from "node:fs/promises";
|
|
7
|
+
import { dirname, join } from "node:path";
|
|
8
|
+
import { createGunzip } from "node:zlib";
|
|
9
|
+
import { isAbort, SemanticPluginError } from "../errors.js";
|
|
10
|
+
const corrupt = () => {
|
|
11
|
+
throw new SemanticPluginError("model_corrupt");
|
|
12
|
+
};
|
|
13
|
+
/** Archive path checks applied to every entry, selected or not. */
|
|
14
|
+
export function safeEntryPath(name) {
|
|
15
|
+
const path = name.replace(/\/+$/, "");
|
|
16
|
+
if (!path || path.includes("\0") || path.includes("\\") || path.startsWith("/"))
|
|
17
|
+
corrupt();
|
|
18
|
+
if (/^[A-Za-z]:/.test(path))
|
|
19
|
+
corrupt();
|
|
20
|
+
for (const part of path.split("/"))
|
|
21
|
+
if (part === "" || part === "." || part === "..")
|
|
22
|
+
corrupt();
|
|
23
|
+
return path;
|
|
24
|
+
}
|
|
25
|
+
const field = (block, start, length) => {
|
|
26
|
+
const raw = block.subarray(start, start + length);
|
|
27
|
+
const end = raw.indexOf(0);
|
|
28
|
+
return raw.subarray(0, end === -1 ? length : end).toString("utf8");
|
|
29
|
+
};
|
|
30
|
+
const octal = (block, start, length) => {
|
|
31
|
+
const text = field(block, start, length).trim();
|
|
32
|
+
if (!/^[0-7]*$/.test(text))
|
|
33
|
+
corrupt();
|
|
34
|
+
return text ? Number.parseInt(text, 8) : 0;
|
|
35
|
+
};
|
|
36
|
+
function checksumOk(block) {
|
|
37
|
+
let sum = 0;
|
|
38
|
+
for (let i = 0; i < 512; i++)
|
|
39
|
+
sum += i >= 148 && i < 156 ? 32 : block[i];
|
|
40
|
+
return sum === octal(block, 148, 8);
|
|
41
|
+
}
|
|
42
|
+
function paxPath(data) {
|
|
43
|
+
let at = 0;
|
|
44
|
+
let path;
|
|
45
|
+
while (at < data.length) {
|
|
46
|
+
const space = data.indexOf(0x20, at);
|
|
47
|
+
if (space === -1)
|
|
48
|
+
corrupt();
|
|
49
|
+
const length = Number(data.toString("utf8", at, space));
|
|
50
|
+
if (!Number.isInteger(length) || length <= 0 || at + length > data.length)
|
|
51
|
+
corrupt();
|
|
52
|
+
const record = data.toString("utf8", space + 1, at + length - 1);
|
|
53
|
+
const eq = record.indexOf("=");
|
|
54
|
+
if (record.slice(0, eq) === "path")
|
|
55
|
+
path = record.slice(eq + 1);
|
|
56
|
+
at += length;
|
|
57
|
+
}
|
|
58
|
+
return path;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Extracts `archive` (gzip + ustar/pax) into `dest`. `select` maps an archive path to the path to
|
|
62
|
+
* write under `dest`, or null to skip. Returns size and SHA-256 of every written file.
|
|
63
|
+
*/
|
|
64
|
+
export async function extractTarGz(archive, dest, select, limits) {
|
|
65
|
+
const maxEntries = limits.maxEntries ?? 5000;
|
|
66
|
+
const maxFileBytes = limits.maxFileBytes ?? 256 * 1024 * 1024;
|
|
67
|
+
const maxTotalBytes = limits.maxTotalBytes ?? 400 * 1024 * 1024;
|
|
68
|
+
const out = {};
|
|
69
|
+
let buffer = Buffer.alloc(0);
|
|
70
|
+
let entries = 0;
|
|
71
|
+
let total = 0;
|
|
72
|
+
let ended = false;
|
|
73
|
+
let nextPath;
|
|
74
|
+
// Current entry state.
|
|
75
|
+
let remaining = 0;
|
|
76
|
+
let padding = 0;
|
|
77
|
+
let meta;
|
|
78
|
+
let metaKind;
|
|
79
|
+
let target;
|
|
80
|
+
const finishEntry = async () => {
|
|
81
|
+
if (target) {
|
|
82
|
+
await target.handle.close();
|
|
83
|
+
out[target.path] = { bytes: target.bytes, sha256: target.hash.digest("hex") };
|
|
84
|
+
target = undefined;
|
|
85
|
+
}
|
|
86
|
+
if (meta) {
|
|
87
|
+
const data = Buffer.concat(meta);
|
|
88
|
+
nextPath = metaKind === "x" ? (paxPath(data) ?? nextPath) : field(data, 0, data.length);
|
|
89
|
+
meta = undefined;
|
|
90
|
+
metaKind = undefined;
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
const startEntry = async (block) => {
|
|
94
|
+
if (block.every((b) => b === 0)) {
|
|
95
|
+
ended = true;
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (!checksumOk(block))
|
|
99
|
+
corrupt();
|
|
100
|
+
if (++entries > maxEntries)
|
|
101
|
+
corrupt();
|
|
102
|
+
const type = String.fromCharCode(block[156]) || "0";
|
|
103
|
+
const size = octal(block, 124, 12);
|
|
104
|
+
const prefix = field(block, 345, 155);
|
|
105
|
+
const headerName = prefix ? `${prefix}/${field(block, 0, 100)}` : field(block, 0, 100);
|
|
106
|
+
remaining = size;
|
|
107
|
+
padding = (512 - (size % 512)) % 512;
|
|
108
|
+
if (type === "x" || type === "L") {
|
|
109
|
+
if (size > 64 * 1024)
|
|
110
|
+
corrupt();
|
|
111
|
+
meta = [];
|
|
112
|
+
metaKind = type;
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (type === "g")
|
|
116
|
+
return;
|
|
117
|
+
const name = nextPath ?? headerName;
|
|
118
|
+
nextPath = undefined;
|
|
119
|
+
const path = safeEntryPath(name);
|
|
120
|
+
if (type === "5")
|
|
121
|
+
return;
|
|
122
|
+
if (type !== "0" && type !== "\0" && type !== "7")
|
|
123
|
+
corrupt(); // links, devices, fifos
|
|
124
|
+
if (size > maxFileBytes)
|
|
125
|
+
corrupt();
|
|
126
|
+
const keep = select(path);
|
|
127
|
+
if (keep === null)
|
|
128
|
+
return;
|
|
129
|
+
const relative = safeEntryPath(keep);
|
|
130
|
+
total += size;
|
|
131
|
+
if (total > maxTotalBytes)
|
|
132
|
+
corrupt();
|
|
133
|
+
const file = join(dest, relative);
|
|
134
|
+
await mkdir(dirname(file), { recursive: true, mode: 0o700 });
|
|
135
|
+
target = {
|
|
136
|
+
handle: await open(file, "wx", 0o600),
|
|
137
|
+
hash: createHash("sha256"),
|
|
138
|
+
path: relative,
|
|
139
|
+
bytes: 0,
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
try {
|
|
143
|
+
limits.signal.throwIfAborted();
|
|
144
|
+
const source = createReadStream(archive).pipe(createGunzip());
|
|
145
|
+
for await (const chunk of source) {
|
|
146
|
+
limits.signal.throwIfAborted();
|
|
147
|
+
buffer = buffer.length ? Buffer.concat([buffer, chunk]) : chunk;
|
|
148
|
+
while (!ended) {
|
|
149
|
+
if (remaining > 0) {
|
|
150
|
+
if (buffer.length === 0)
|
|
151
|
+
break;
|
|
152
|
+
const piece = buffer.subarray(0, Math.min(remaining, buffer.length));
|
|
153
|
+
buffer = buffer.subarray(piece.length);
|
|
154
|
+
remaining -= piece.length;
|
|
155
|
+
if (meta)
|
|
156
|
+
meta.push(Buffer.from(piece));
|
|
157
|
+
else if (target) {
|
|
158
|
+
target.hash.update(piece);
|
|
159
|
+
target.bytes += piece.length;
|
|
160
|
+
await target.handle.write(piece);
|
|
161
|
+
}
|
|
162
|
+
if (remaining > 0)
|
|
163
|
+
break;
|
|
164
|
+
await finishEntry();
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (padding > 0) {
|
|
168
|
+
if (buffer.length < padding)
|
|
169
|
+
break;
|
|
170
|
+
buffer = buffer.subarray(padding);
|
|
171
|
+
padding = 0;
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
if (buffer.length < 512)
|
|
175
|
+
break;
|
|
176
|
+
const block = buffer.subarray(0, 512);
|
|
177
|
+
buffer = buffer.subarray(512);
|
|
178
|
+
await startEntry(block);
|
|
179
|
+
if (remaining === 0 && !ended)
|
|
180
|
+
await finishEntry();
|
|
181
|
+
}
|
|
182
|
+
if (ended)
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
if (!ended || remaining > 0)
|
|
186
|
+
corrupt();
|
|
187
|
+
return out;
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
await target?.handle.close().catch(() => { });
|
|
191
|
+
if (isAbort(error) || limits.signal.aborted)
|
|
192
|
+
throw new SemanticPluginError("cancelled");
|
|
193
|
+
if (error instanceof SemanticPluginError)
|
|
194
|
+
throw error;
|
|
195
|
+
throw new SemanticPluginError("model_corrupt");
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=tar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tar.js","sourceRoot":"","sources":["../../src/engine/tar.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/engine/worker.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Worker thread entry (D5): loads the cached ONNX Runtime (downloaded on first use, owner O9), the
|
|
2
|
+
// pinned ONNX model (CPU) and the tokenizer (@huggingface/tokenizers), then embeds batches posted by
|
|
3
|
+
// `embedder.ts`.
|
|
4
|
+
import { readFile } from "node:fs/promises";
|
|
5
|
+
import { availableParallelism } from "node:os";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
import { parentPort, workerData } from "node:worker_threads";
|
|
8
|
+
import { batchInputs, encodeBatch, meanPoolNormalize } from "./infer.js";
|
|
9
|
+
import { loadRuntime } from "./runtime.js";
|
|
10
|
+
const { modelDir, runtimeDir, maxTokens } = workerData;
|
|
11
|
+
const port = parentPort;
|
|
12
|
+
async function start() {
|
|
13
|
+
if (!port)
|
|
14
|
+
return;
|
|
15
|
+
try {
|
|
16
|
+
const ort = loadRuntime(runtimeDir);
|
|
17
|
+
const { Tokenizer } = await import("@huggingface/tokenizers");
|
|
18
|
+
const readJson = async (name) => JSON.parse(await readFile(join(modelDir, name), "utf8"));
|
|
19
|
+
const [tokenizerJson, tokenizerConfig, config] = await Promise.all([
|
|
20
|
+
readJson("tokenizer.json"),
|
|
21
|
+
readJson("tokenizer_config.json"),
|
|
22
|
+
readJson("config.json"),
|
|
23
|
+
]);
|
|
24
|
+
const tokenizer = new Tokenizer(tokenizerJson, tokenizerConfig);
|
|
25
|
+
const padToken = typeof tokenizerConfig.pad_token === "string" ? tokenizerConfig.pad_token : "<pad>";
|
|
26
|
+
const padId = tokenizer.token_to_id(padToken) ?? (Number(config.pad_token_id) || 0);
|
|
27
|
+
const session = await ort.InferenceSession.create(join(modelDir, "onnx/model_quantized.onnx"), {
|
|
28
|
+
executionProviders: ["cpu"],
|
|
29
|
+
intraOpNumThreads: Math.max(1, Math.min(4, availableParallelism() - 1)),
|
|
30
|
+
interOpNumThreads: 1,
|
|
31
|
+
});
|
|
32
|
+
const output = session.outputNames[0];
|
|
33
|
+
port.on("message", async (message) => {
|
|
34
|
+
if (message?.type !== "embed")
|
|
35
|
+
return;
|
|
36
|
+
try {
|
|
37
|
+
const encoded = encodeBatch(tokenizer, message.texts, maxTokens);
|
|
38
|
+
const input = batchInputs(encoded, padId);
|
|
39
|
+
const shape = [input.batch, input.length];
|
|
40
|
+
const feeds = {
|
|
41
|
+
input_ids: new ort.Tensor("int64", input.inputIds, shape),
|
|
42
|
+
attention_mask: new ort.Tensor("int64", input.attention, shape),
|
|
43
|
+
};
|
|
44
|
+
if (session.inputNames.includes("token_type_ids"))
|
|
45
|
+
feeds.token_type_ids = new ort.Tensor("int64", input.tokenTypes, shape);
|
|
46
|
+
const result = await session.run(feeds);
|
|
47
|
+
const hidden = result[output];
|
|
48
|
+
if (!hidden)
|
|
49
|
+
throw new Error("no output");
|
|
50
|
+
const vectors = meanPoolNormalize(hidden.data, hidden.dims, input.lengths);
|
|
51
|
+
port.postMessage({ type: "vectors", id: message.id, vectors }, vectors.map((v) => v.buffer));
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
port.postMessage({ type: "error", id: message.id, code: "inference_failed" });
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
port.postMessage({ type: "ready", dimensions: Number(config.hidden_size) });
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
port.postMessage({ type: "error", code: "load_failed" });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
void start();
|
|
64
|
+
//# sourceMappingURL=worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/engine/worker.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Error codes the plugin returns (§8). Never carry inputs, paths or stacks. */
|
|
2
|
+
export declare const ERROR_CODES: readonly ["invalid_input", "not_found", "limit_exceeded", "unsupported_format", "invalid_encoding", "no_text", "path_outside_workspace", "file_too_large", "zip_invalid", "engine_unavailable", "model_missing", "model_corrupt", "unknown_model", "model_mismatch", "download_failed", "cancelled", "answer_failed", "operation_failed"];
|
|
3
|
+
export type SemanticPluginErrorCode = (typeof ERROR_CODES)[number];
|
|
4
|
+
export declare class SemanticPluginError extends Error {
|
|
5
|
+
readonly code: SemanticPluginErrorCode;
|
|
6
|
+
constructor(code: SemanticPluginErrorCode, message?: string);
|
|
7
|
+
}
|
|
8
|
+
/** True for an abort raised by an `AbortSignal` (DOMException or a plain AbortError). */
|
|
9
|
+
export declare function isAbort(error: unknown): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Maps any error to a plugin code. The host's `SemanticError` is matched by `name`/`code`, not
|
|
12
|
+
* `instanceof`, because the host and the plugin may load different copies of the SDK.
|
|
13
|
+
*/
|
|
14
|
+
export declare function errorCode(error: unknown): SemanticPluginErrorCode;
|
|
15
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,eAAO,MAAM,WAAW,YACtB,eAAe,EACf,WAAW,EACX,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,EAClB,SAAS,EACT,wBAAwB,EACxB,gBAAgB,EAChB,aAAa,EACb,oBAAoB,EACpB,eAAe,EACf,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,WAAW,EACX,eAAe,EACf,kBAAkB,CACV,CAAC;AACX,MAAM,MAAM,uBAAuB,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnE,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,IAAI,EAAE,uBAAuB,CAAC;IACvC,YAAY,IAAI,EAAE,uBAAuB,EAAE,OAAO,CAAC,EAAE,MAAM,EAI1D;CACF;AAED,yFAAyF;AACzF,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAO/C;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,uBAAuB,CAcjE"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/** Error codes the plugin returns (§8). Never carry inputs, paths or stacks. */
|
|
2
|
+
export const ERROR_CODES = [
|
|
3
|
+
"invalid_input",
|
|
4
|
+
"not_found",
|
|
5
|
+
"limit_exceeded",
|
|
6
|
+
"unsupported_format",
|
|
7
|
+
"invalid_encoding",
|
|
8
|
+
"no_text",
|
|
9
|
+
"path_outside_workspace",
|
|
10
|
+
"file_too_large",
|
|
11
|
+
"zip_invalid",
|
|
12
|
+
"engine_unavailable",
|
|
13
|
+
"model_missing",
|
|
14
|
+
"model_corrupt",
|
|
15
|
+
"unknown_model",
|
|
16
|
+
"model_mismatch",
|
|
17
|
+
"download_failed",
|
|
18
|
+
"cancelled",
|
|
19
|
+
"answer_failed",
|
|
20
|
+
"operation_failed",
|
|
21
|
+
];
|
|
22
|
+
export class SemanticPluginError extends Error {
|
|
23
|
+
code;
|
|
24
|
+
constructor(code, message) {
|
|
25
|
+
super(message ?? code);
|
|
26
|
+
this.name = "SemanticPluginError";
|
|
27
|
+
this.code = code;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** True for an abort raised by an `AbortSignal` (DOMException or a plain AbortError). */
|
|
31
|
+
export function isAbort(error) {
|
|
32
|
+
return (!!error &&
|
|
33
|
+
typeof error === "object" &&
|
|
34
|
+
(error.name === "AbortError" ||
|
|
35
|
+
error.name === "TimeoutError"));
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Maps any error to a plugin code. The host's `SemanticError` is matched by `name`/`code`, not
|
|
39
|
+
* `instanceof`, because the host and the plugin may load different copies of the SDK.
|
|
40
|
+
*/
|
|
41
|
+
export function errorCode(error) {
|
|
42
|
+
if (error instanceof SemanticPluginError)
|
|
43
|
+
return error.code;
|
|
44
|
+
if (isAbort(error))
|
|
45
|
+
return "cancelled";
|
|
46
|
+
if (error &&
|
|
47
|
+
typeof error === "object" &&
|
|
48
|
+
error.name === "SemanticError") {
|
|
49
|
+
const code = error.code;
|
|
50
|
+
if (code === "model_mismatch" || code === "dimension_mismatch")
|
|
51
|
+
return "model_mismatch";
|
|
52
|
+
if (code === "invalid_request")
|
|
53
|
+
return "invalid_input";
|
|
54
|
+
return "engine_unavailable";
|
|
55
|
+
}
|
|
56
|
+
return "operation_failed";
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,eAAe;IACf,WAAW;IACX,gBAAgB;IAChB,oBAAoB;IACpB,kBAAkB;IAClB,SAAS;IACT,wBAAwB;IACxB,gBAAgB;IAChB,aAAa;IACb,oBAAoB;IACpB,eAAe;IACf,eAAe;IACf,eAAe;IACf,gBAAgB;IAChB,iBAAiB;IACjB,WAAW;IACX,eAAe;IACf,kBAAkB;CACV,CAAC;AAGX,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IACnC,IAAI,CAA0B;IACvC,YAAY,IAA6B,EAAE,OAAgB;QACzD,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED,yFAAyF;AACzF,MAAM,UAAU,OAAO,CAAC,KAAc;IACpC,OAAO,CACL,CAAC,CAAC,KAAK;QACP,OAAO,KAAK,KAAK,QAAQ;QACzB,CAAE,KAA4B,CAAC,IAAI,KAAK,YAAY;YACjD,KAA4B,CAAC,IAAI,KAAK,cAAc,CAAC,CACzD,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,KAAc;IACtC,IAAI,KAAK,YAAY,mBAAmB;QAAE,OAAO,KAAK,CAAC,IAAI,CAAC;IAC5D,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,WAAW,CAAC;IACvC,IACE,KAAK;QACL,OAAO,KAAK,KAAK,QAAQ;QACxB,KAA4B,CAAC,IAAI,KAAK,eAAe,EACtD,CAAC;QACD,MAAM,IAAI,GAAI,KAA4B,CAAC,IAAI,CAAC;QAChD,IAAI,IAAI,KAAK,gBAAgB,IAAI,IAAI,KAAK,oBAAoB;YAAE,OAAO,gBAAgB,CAAC;QACxF,IAAI,IAAI,KAAK,iBAAiB;YAAE,OAAO,eAAe,CAAC;QACvD,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IACD,OAAO,kBAAkB,CAAC;AAC5B,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type PluginAPI } from "@alisio/sdk";
|
|
2
|
+
export declare const MIN_HOST = "0.11.7";
|
|
3
|
+
declare const _default: {
|
|
4
|
+
id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
version: string;
|
|
7
|
+
apiVersion: 1;
|
|
8
|
+
description: string;
|
|
9
|
+
categories: ("search" | "storage")[];
|
|
10
|
+
setup(api: PluginAPI): void;
|
|
11
|
+
dispose(): void;
|
|
12
|
+
};
|
|
13
|
+
export default _default;
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,SAAS,EAAc,MAAM,aAAa,CAAC;AAavE,eAAO,MAAM,QAAQ,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { definePlugin, textResult } from "@alisio/sdk";
|
|
4
|
+
import { buildActions } from "./apps.js";
|
|
5
|
+
import { E5Embedder } from "./engine/embedder.js";
|
|
6
|
+
import { resolveModel } from "./engine/models.js";
|
|
7
|
+
import { SetupManager } from "./engine/setup.js";
|
|
8
|
+
import { LanceStore } from "./engine/store.js";
|
|
9
|
+
import { errorCode, SemanticPluginError } from "./errors.js";
|
|
10
|
+
import { messagesFor, resolveLocale } from "./messages.js";
|
|
11
|
+
import { NotebookDb } from "./notebook/db.js";
|
|
12
|
+
import { NotebookService } from "./notebook/service.js";
|
|
13
|
+
import { diskUse, resolvePaths } from "./paths.js";
|
|
14
|
+
import { VERSION } from "./version.js";
|
|
15
|
+
export const MIN_HOST = "0.11.7";
|
|
16
|
+
let current;
|
|
17
|
+
function createRuntime(api) {
|
|
18
|
+
const options = api.options ?? {};
|
|
19
|
+
const locale = resolveLocale(options.locale);
|
|
20
|
+
const m = messagesFor(locale);
|
|
21
|
+
const paths = resolvePaths(api.paths);
|
|
22
|
+
const disposers = [];
|
|
23
|
+
let spec;
|
|
24
|
+
try {
|
|
25
|
+
spec = resolveModel(options.model);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
spec = undefined;
|
|
29
|
+
}
|
|
30
|
+
const store = new LanceStore({ dir: paths.lance });
|
|
31
|
+
const embedder = spec ? new E5Embedder({ spec, cacheRoot: paths.models }) : undefined;
|
|
32
|
+
const setup = spec && embedder
|
|
33
|
+
? new SetupManager({ spec, cacheRoot: paths.models, embedder, semantic: api.semantic })
|
|
34
|
+
: undefined;
|
|
35
|
+
if (api.semantic && embedder) {
|
|
36
|
+
try {
|
|
37
|
+
disposers.push(api.semantic.registerEmbedding(embedder));
|
|
38
|
+
disposers.push(api.semantic.registerStore(store));
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
// A duplicate id (another copy of this plugin) keeps the previous registration (core SE-R2).
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
let service;
|
|
45
|
+
const notebooks = () => {
|
|
46
|
+
if (!service) {
|
|
47
|
+
if (!api.storage?.sqlite)
|
|
48
|
+
throw new Error("storage unavailable");
|
|
49
|
+
service = new NotebookService({
|
|
50
|
+
db: new NotebookDb(api.storage.sqlite(paths.notebook)),
|
|
51
|
+
semantic: () => api.semantic,
|
|
52
|
+
complete: (request) => api.model.complete(request),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return service;
|
|
56
|
+
};
|
|
57
|
+
disposers.push(api.tools.register({
|
|
58
|
+
name: "notebook_search",
|
|
59
|
+
description: "Search one of the user's Notebook notebooks (by title or id) and return the most relevant passages with their source name and page. Read-only.",
|
|
60
|
+
effect: "read",
|
|
61
|
+
inputSchema: {
|
|
62
|
+
type: "object",
|
|
63
|
+
properties: {
|
|
64
|
+
notebook: {
|
|
65
|
+
type: "string",
|
|
66
|
+
minLength: 1,
|
|
67
|
+
maxLength: 200,
|
|
68
|
+
description: "Notebook title or id",
|
|
69
|
+
},
|
|
70
|
+
query: { type: "string", minLength: 1, maxLength: 4000 },
|
|
71
|
+
topK: { type: "integer", minimum: 1, maximum: 8 },
|
|
72
|
+
},
|
|
73
|
+
required: ["notebook", "query"],
|
|
74
|
+
additionalProperties: false,
|
|
75
|
+
},
|
|
76
|
+
async execute(input, context) {
|
|
77
|
+
const reference = typeof input.notebook === "string" ? input.notebook.trim() : "";
|
|
78
|
+
const query = typeof input.query === "string" ? input.query.slice(0, 4000) : "";
|
|
79
|
+
const topK = Number.isInteger(input.topK)
|
|
80
|
+
? Math.min(8, Math.max(1, input.topK))
|
|
81
|
+
: 8;
|
|
82
|
+
if (!reference || !query)
|
|
83
|
+
return textResult("invalid_input", true);
|
|
84
|
+
// Read-only: never create the notebook database from the tool.
|
|
85
|
+
if (!service && !existsSync(paths.notebook))
|
|
86
|
+
return textResult("not_found", true);
|
|
87
|
+
try {
|
|
88
|
+
const nb = notebooks();
|
|
89
|
+
const found = nb.db.findNotebook(reference);
|
|
90
|
+
if (!found)
|
|
91
|
+
return textResult("not_found", true);
|
|
92
|
+
const { passages, keywordOnly } = await nb.retrieve(found.id, query, {
|
|
93
|
+
signal: context.signal,
|
|
94
|
+
keep: topK,
|
|
95
|
+
});
|
|
96
|
+
const out = [];
|
|
97
|
+
let budget = 16_000;
|
|
98
|
+
for (const p of passages) {
|
|
99
|
+
if (budget <= 0)
|
|
100
|
+
break;
|
|
101
|
+
const text = p.text.slice(0, budget);
|
|
102
|
+
budget -= text.length;
|
|
103
|
+
out.push({ n: p.n, source: p.sourceName, page: p.page, text });
|
|
104
|
+
}
|
|
105
|
+
return textResult(JSON.stringify({ notebook: found.title, keywordOnly, passages: out }));
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
return textResult(errorCode(error), true);
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
}));
|
|
112
|
+
disposers.push(api.commands.register("setup", async (args) => {
|
|
113
|
+
if (!setup)
|
|
114
|
+
return m.unknownModel;
|
|
115
|
+
if (args.trim() === "cancel") {
|
|
116
|
+
return setup.cancelRunning() ? m.cancelled : m.nothingToCancel;
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
return await setup.commandText(locale);
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
return m.failed(errorCode(error));
|
|
123
|
+
}
|
|
124
|
+
}, {
|
|
125
|
+
description: "Download the local model once and activate semantic search.",
|
|
126
|
+
argumentHint: "[cancel]",
|
|
127
|
+
}));
|
|
128
|
+
disposers.push(api.commands.register("status", async () => {
|
|
129
|
+
const lines = [];
|
|
130
|
+
const st = m.status;
|
|
131
|
+
const semantic = api.semantic;
|
|
132
|
+
const available = semantic?.available() ?? false;
|
|
133
|
+
if (!semantic)
|
|
134
|
+
lines.push(st.noApi);
|
|
135
|
+
else {
|
|
136
|
+
const active = semantic.active();
|
|
137
|
+
lines.push(available
|
|
138
|
+
? st.available(active.embedding?.id ?? "?", active.store?.id ?? "?")
|
|
139
|
+
: st.unavailable);
|
|
140
|
+
if (active.embedding)
|
|
141
|
+
lines.push(st.activeModel(active.embedding.modelId, active.embedding.dimensions));
|
|
142
|
+
}
|
|
143
|
+
if (!spec)
|
|
144
|
+
lines.push(st.unknownModel);
|
|
145
|
+
else {
|
|
146
|
+
const plan = await setup?.plan();
|
|
147
|
+
lines.push(st.model(spec.label, !!plan?.prepared, plan?.bytes ?? 0));
|
|
148
|
+
if (embedder) {
|
|
149
|
+
const health = (await embedder.health()).status;
|
|
150
|
+
lines.push(st.embedder(st.health[health] ?? health));
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const storeHealth = (await store.health()).status;
|
|
154
|
+
lines.push(st.store(st.health[storeHealth] ?? storeHealth));
|
|
155
|
+
if (existsSync(paths.notebook) || service) {
|
|
156
|
+
try {
|
|
157
|
+
lines.push(st.notebooks(notebooks().db.countNotebooks()));
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
lines.push(st.notebooks(null));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
else
|
|
164
|
+
lines.push(st.notebooks(0));
|
|
165
|
+
lines.push(st.disk(await diskUse(paths.models), await diskUse(paths.lance)));
|
|
166
|
+
return lines.join("\n");
|
|
167
|
+
}, { description: "Show semantic engine health, model, disk use and notebooks." }));
|
|
168
|
+
disposers.push(api.commands.register("help", async () => (api.apps ? m.help.withApp : m.help.withoutApp), {
|
|
169
|
+
description: "Explain the Notebook app and semantic search.",
|
|
170
|
+
}));
|
|
171
|
+
if (api.apps) {
|
|
172
|
+
const actions = buildActions({
|
|
173
|
+
service: notebooks,
|
|
174
|
+
engine: {
|
|
175
|
+
async status() {
|
|
176
|
+
const semantic = api.semantic;
|
|
177
|
+
const available = semantic?.available() ?? false;
|
|
178
|
+
const plan = await setup?.plan();
|
|
179
|
+
const running = setup?.running() ? setup.currentId() : undefined;
|
|
180
|
+
return {
|
|
181
|
+
semanticApi: !!semantic,
|
|
182
|
+
available,
|
|
183
|
+
keywordOnly: !available,
|
|
184
|
+
active: semantic?.active() ?? { embedding: null, store: null },
|
|
185
|
+
model: plan
|
|
186
|
+
? { key: plan.key, label: plan.label, bytes: plan.bytes, prepared: plan.prepared }
|
|
187
|
+
: null,
|
|
188
|
+
modelError: spec ? null : "unknown_model",
|
|
189
|
+
setupJob: running ? (setup?.get(running) ?? null) : null,
|
|
190
|
+
minHost: MIN_HOST,
|
|
191
|
+
};
|
|
192
|
+
},
|
|
193
|
+
setup() {
|
|
194
|
+
if (!setup)
|
|
195
|
+
throw new SemanticPluginError("unknown_model");
|
|
196
|
+
return { jobId: setup.start().id };
|
|
197
|
+
},
|
|
198
|
+
job: (id) => setup?.get(id),
|
|
199
|
+
cancel: (id) => setup?.cancel(id) ?? false,
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
disposers.push(api.apps.register({
|
|
203
|
+
id: "notebook",
|
|
204
|
+
label: { en: "Notebook", es: "Cuaderno" },
|
|
205
|
+
html: () => readFile(new URL("./embedded.html", import.meta.url), "utf8"),
|
|
206
|
+
actions,
|
|
207
|
+
busy: () => (service?.busy() ?? false) || (setup?.running() ?? false),
|
|
208
|
+
dispose: () => closeNotebooks(),
|
|
209
|
+
}));
|
|
210
|
+
}
|
|
211
|
+
function closeNotebooks() {
|
|
212
|
+
const closing = service;
|
|
213
|
+
service = undefined;
|
|
214
|
+
if (!closing)
|
|
215
|
+
return;
|
|
216
|
+
closing.dispose();
|
|
217
|
+
void closing
|
|
218
|
+
.idle()
|
|
219
|
+
.catch(() => { })
|
|
220
|
+
.then(() => closing.db.close());
|
|
221
|
+
}
|
|
222
|
+
let disposed = false;
|
|
223
|
+
return {
|
|
224
|
+
dispose() {
|
|
225
|
+
if (disposed)
|
|
226
|
+
return;
|
|
227
|
+
disposed = true;
|
|
228
|
+
setup?.dispose();
|
|
229
|
+
embedder?.close();
|
|
230
|
+
closeNotebooks();
|
|
231
|
+
for (const dispose of disposers.splice(0)) {
|
|
232
|
+
try {
|
|
233
|
+
dispose();
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
// Host already removed it.
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
export default definePlugin({
|
|
243
|
+
id: "semantic",
|
|
244
|
+
name: "Semantic",
|
|
245
|
+
version: VERSION,
|
|
246
|
+
apiVersion: 1,
|
|
247
|
+
description: "Local semantic search (LanceDB + multilingual-e5-small) and a Notebook app grounded in your sources.",
|
|
248
|
+
categories: ["search", "storage"],
|
|
249
|
+
setup(api) {
|
|
250
|
+
current?.dispose();
|
|
251
|
+
current = createRuntime(api);
|
|
252
|
+
},
|
|
253
|
+
dispose() {
|
|
254
|
+
current?.dispose();
|
|
255
|
+
current = undefined;
|
|
256
|
+
},
|
|
257
|
+
});
|
|
258
|
+
//# sourceMappingURL=index.js.map
|