@thyn-ai/sqai 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE +8 -0
- package/README.md +13 -0
- package/dist/index.cjs +426 -82
- package/dist/index.d.cts +122 -21
- package/dist/index.d.ts +122 -21
- package/dist/index.js +384 -57
- package/dist/unsafe.cjs +0 -1
- package/dist/unsafe.js +0 -1
- package/package.json +9 -10
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/unsafe.cjs.map +0 -1
- package/dist/unsafe.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,15 +17,26 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
21
31
|
var index_exports = {};
|
|
22
32
|
__export(index_exports, {
|
|
23
33
|
ContractIndex: () => ContractIndex,
|
|
34
|
+
LoginError: () => LoginError,
|
|
24
35
|
ResultStore: () => ResultStore,
|
|
25
36
|
RuntimeProvisioner: () => RuntimeProvisioner,
|
|
26
37
|
SQAI: () => SQAI,
|
|
38
|
+
SQAI_CONNECTOR_TYPES: () => SQAI_CONNECTOR_TYPES,
|
|
39
|
+
SQAI_CONNECTOR_TYPE_ALIASES: () => SQAI_CONNECTOR_TYPE_ALIASES,
|
|
27
40
|
SQAI_ERROR_CODES: () => SQAI_ERROR_CODES,
|
|
28
41
|
SqaiError: () => SqaiError,
|
|
29
42
|
computationHash: () => computationHash,
|
|
@@ -31,15 +44,19 @@ __export(index_exports, {
|
|
|
31
44
|
currentPlatformKey: () => currentPlatformKey,
|
|
32
45
|
invocationHash: () => invocationHash,
|
|
33
46
|
isReadOnlyEligible: () => isReadOnlyEligible,
|
|
47
|
+
login: () => login,
|
|
48
|
+
logout: () => logout,
|
|
34
49
|
lookupCapability: () => lookupCapability,
|
|
50
|
+
readCachedApiKey: () => readCachedApiKey,
|
|
35
51
|
runtimeCacheDir: () => runtimeCacheDir,
|
|
52
|
+
sqaiHome: () => sqaiHome,
|
|
36
53
|
validateComputation: () => validateComputation
|
|
37
54
|
});
|
|
38
55
|
module.exports = __toCommonJS(index_exports);
|
|
39
56
|
|
|
40
57
|
// src/sqai.ts
|
|
41
|
-
var
|
|
42
|
-
var
|
|
58
|
+
var import_node_crypto7 = require("crypto");
|
|
59
|
+
var import_node_os3 = require("os");
|
|
43
60
|
var import_algenta_sdk3 = require("algenta-sdk");
|
|
44
61
|
|
|
45
62
|
// src/contract-data.json
|
|
@@ -151,13 +168,13 @@ var SQAI_ERROR_CODES = [
|
|
|
151
168
|
"contract_mismatch",
|
|
152
169
|
"invalid_intent"
|
|
153
170
|
];
|
|
154
|
-
var
|
|
171
|
+
var RETRYABLE_ENGINE_CODES = /* @__PURE__ */ new Set([
|
|
155
172
|
"network_error",
|
|
156
173
|
"timeout",
|
|
157
174
|
"rate_limited",
|
|
158
175
|
"service_unavailable"
|
|
159
176
|
]);
|
|
160
|
-
function
|
|
177
|
+
function fromEngineError(error) {
|
|
161
178
|
if (error instanceof SqaiError) {
|
|
162
179
|
return error;
|
|
163
180
|
}
|
|
@@ -167,7 +184,7 @@ function fromAlgentaError(error) {
|
|
|
167
184
|
const details = errorLike.details && typeof errorLike.details === "object" ? errorLike.details : {};
|
|
168
185
|
return new SqaiError(code, message, {
|
|
169
186
|
source: "engine",
|
|
170
|
-
retryable:
|
|
187
|
+
retryable: RETRYABLE_ENGINE_CODES.has(code),
|
|
171
188
|
details
|
|
172
189
|
});
|
|
173
190
|
}
|
|
@@ -176,12 +193,14 @@ function fromAlgentaError(error) {
|
|
|
176
193
|
var DEFAULT_BUILD_SERVICE_URL = "https://sqai-buildservice.fly.dev";
|
|
177
194
|
function readEnv(env = process.env) {
|
|
178
195
|
const apiKey = (env.SQAI_API_KEY ?? "").trim() || void 0;
|
|
179
|
-
const
|
|
196
|
+
const deploymentUrl = (env.SQAI_DEPLOYMENT_URL ?? "").trim() || void 0;
|
|
197
|
+
const legacyEngineUrl = (env.SQAI_ENGINE_URL ?? "").trim() || void 0;
|
|
198
|
+
const engineUrl = deploymentUrl ?? legacyEngineUrl;
|
|
180
199
|
const autoInstall = (env.SQAI_RUNTIME_AUTO_INSTALL ?? "").trim() !== "0";
|
|
181
200
|
const modulesRaw = (env.SQAI_RUNTIME_MODULES ?? "").split(",").map((m) => m.trim()).filter((m) => m.length > 0);
|
|
182
201
|
const runtimeModules = modulesRaw.length > 0 ? modulesRaw : void 0;
|
|
183
202
|
const buildServiceUrl = (env.SQAI_BUILD_SERVICE_URL ?? "").trim() || DEFAULT_BUILD_SERVICE_URL;
|
|
184
|
-
return { apiKey, engineUrl, autoInstall, runtimeModules, buildServiceUrl };
|
|
203
|
+
return { apiKey, engineUrl, deploymentUrl, autoInstall, runtimeModules, buildServiceUrl };
|
|
185
204
|
}
|
|
186
205
|
function inferMode(explicit, resolved) {
|
|
187
206
|
if (explicit) {
|
|
@@ -190,9 +209,6 @@ function inferMode(explicit, resolved) {
|
|
|
190
209
|
if (resolved.engineUrl) {
|
|
191
210
|
return "self_hosted";
|
|
192
211
|
}
|
|
193
|
-
if (resolved.apiKey) {
|
|
194
|
-
return "api";
|
|
195
|
-
}
|
|
196
212
|
return "local";
|
|
197
213
|
}
|
|
198
214
|
|
|
@@ -354,22 +370,180 @@ var ResultStore = class {
|
|
|
354
370
|
};
|
|
355
371
|
|
|
356
372
|
// src/runtime/provision.ts
|
|
357
|
-
var
|
|
358
|
-
var
|
|
359
|
-
var
|
|
360
|
-
var
|
|
373
|
+
var import_node_os2 = require("os");
|
|
374
|
+
var import_node_path3 = require("path");
|
|
375
|
+
var import_node_fs3 = require("fs");
|
|
376
|
+
var import_node_crypto6 = require("crypto");
|
|
361
377
|
var import_node_stream = require("stream");
|
|
362
378
|
var import_promises = require("stream/promises");
|
|
363
379
|
var import_algenta_sdk2 = require("algenta-sdk");
|
|
364
380
|
|
|
365
|
-
// src/runtime/
|
|
366
|
-
var
|
|
367
|
-
var import_node_crypto4 = require("crypto");
|
|
381
|
+
// src/runtime/auth.ts
|
|
382
|
+
var import_node_crypto3 = require("crypto");
|
|
368
383
|
var import_node_fs = require("fs");
|
|
384
|
+
var import_node_os = require("os");
|
|
369
385
|
var import_node_path = require("path");
|
|
386
|
+
var CLIENT_ID = "sqai-cli";
|
|
387
|
+
var SCOPE = "sqai";
|
|
388
|
+
var PRODUCT = "sqai";
|
|
389
|
+
var DEFAULT_PLAN = "sqai_developer";
|
|
390
|
+
var DEFAULT_ACCOUNTS_URL = "https://accounts.thyn.ai";
|
|
391
|
+
var DEFAULT_API_URL = "https://api.sqai.com";
|
|
392
|
+
var LoginError = class extends Error {
|
|
393
|
+
};
|
|
394
|
+
function sqaiHome() {
|
|
395
|
+
return process.env.SQAI_HOME ?? (0, import_node_path.join)((0, import_node_os.homedir)(), ".sqai");
|
|
396
|
+
}
|
|
397
|
+
var p = (name) => (0, import_node_path.join)(sqaiHome(), name);
|
|
398
|
+
var apiKeyPath = () => p("api_key");
|
|
399
|
+
var tokenPath = () => p("token");
|
|
400
|
+
var deviceIdPath = () => p("device_id");
|
|
401
|
+
var accountsUrl = () => (process.env.SQAI_ACCOUNTS_URL ?? DEFAULT_ACCOUNTS_URL).replace(/\/$/, "");
|
|
402
|
+
var apiUrl = () => (process.env.SQAI_API_URL ?? DEFAULT_API_URL).replace(/\/$/, "");
|
|
403
|
+
function readSecret(path) {
|
|
404
|
+
try {
|
|
405
|
+
const v = (0, import_node_fs.readFileSync)(path, "utf8").trim();
|
|
406
|
+
return v || void 0;
|
|
407
|
+
} catch {
|
|
408
|
+
return void 0;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
async function readCachedApiKey() {
|
|
412
|
+
return process.env.SQAI_API_KEY ?? process.env.ALGENTA_API_KEY ?? readSecret(apiKeyPath());
|
|
413
|
+
}
|
|
414
|
+
function cache(path, value) {
|
|
415
|
+
(0, import_node_fs.mkdirSync)(sqaiHome(), { recursive: true });
|
|
416
|
+
(0, import_node_fs.writeFileSync)(path, value.trim() + "\n", "utf8");
|
|
417
|
+
try {
|
|
418
|
+
(0, import_node_fs.chmodSync)(path, 384);
|
|
419
|
+
} catch {
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
function deviceId() {
|
|
423
|
+
const existing = readSecret(deviceIdPath());
|
|
424
|
+
if (existing) return existing;
|
|
425
|
+
const value = (0, import_node_crypto3.createHash)("sha256").update(`${(0, import_node_os.hostname)()}:${Date.now()}:${Math.random()}`).digest("hex");
|
|
426
|
+
cache(deviceIdPath(), value);
|
|
427
|
+
return value;
|
|
428
|
+
}
|
|
429
|
+
async function request(method, url, opts = {}) {
|
|
430
|
+
const headers = { Accept: "application/json", "User-Agent": "sqai-cli" };
|
|
431
|
+
if (opts.body !== void 0) headers["Content-Type"] = "application/json";
|
|
432
|
+
if (opts.bearer) headers["Authorization"] = `Bearer ${opts.bearer}`;
|
|
433
|
+
let res;
|
|
434
|
+
try {
|
|
435
|
+
res = await fetch(url, {
|
|
436
|
+
method,
|
|
437
|
+
headers,
|
|
438
|
+
body: opts.body !== void 0 ? JSON.stringify(opts.body) : void 0
|
|
439
|
+
});
|
|
440
|
+
} catch (e) {
|
|
441
|
+
throw new LoginError(`${method} ${url}: ${e instanceof Error ? e.message : String(e)}`);
|
|
442
|
+
}
|
|
443
|
+
let json = {};
|
|
444
|
+
try {
|
|
445
|
+
json = await res.json();
|
|
446
|
+
} catch {
|
|
447
|
+
json = {};
|
|
448
|
+
}
|
|
449
|
+
return { status: res.status, json };
|
|
450
|
+
}
|
|
451
|
+
async function deviceAuthorize(accounts, openBrowser, maxWaitMs = 3e5) {
|
|
452
|
+
const { json: start } = await request("POST", `${accounts}/oauth/device/code`, {
|
|
453
|
+
body: { client_id: CLIENT_ID, scope: SCOPE }
|
|
454
|
+
});
|
|
455
|
+
const deviceCode = start.device_code;
|
|
456
|
+
const userCode = start.user_code;
|
|
457
|
+
const verify = start.verification_uri_complete || start.verification_uri;
|
|
458
|
+
const interval = Number(start.interval ?? 5);
|
|
459
|
+
if (!deviceCode || !userCode || !verify) throw new LoginError("accounts device-code response missing fields");
|
|
460
|
+
process.stdout.write(`
|
|
461
|
+
Open ${verify}
|
|
462
|
+
and enter code: ${userCode}
|
|
463
|
+
|
|
464
|
+
`);
|
|
465
|
+
if (openBrowser) await tryOpenBrowser(verify);
|
|
466
|
+
const deadline = Date.now() + maxWaitMs;
|
|
467
|
+
while (Date.now() < deadline) {
|
|
468
|
+
await new Promise((r) => setTimeout(r, interval * 1e3));
|
|
469
|
+
const { status, json: tok } = await request("POST", `${accounts}/oauth/device/token`, {
|
|
470
|
+
body: {
|
|
471
|
+
client_id: CLIENT_ID,
|
|
472
|
+
device_code: deviceCode,
|
|
473
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code"
|
|
474
|
+
}
|
|
475
|
+
});
|
|
476
|
+
const access = tok.access_token;
|
|
477
|
+
if (access) return access;
|
|
478
|
+
const error = tok.error;
|
|
479
|
+
if (error === "authorization_pending" || error === "slow_down" || status === 400 || status === 428) continue;
|
|
480
|
+
throw new LoginError(`device authorization failed: ${error ?? `HTTP ${status}`}`);
|
|
481
|
+
}
|
|
482
|
+
throw new LoginError("timed out waiting for device authorization");
|
|
483
|
+
}
|
|
484
|
+
async function tryOpenBrowser(url) {
|
|
485
|
+
try {
|
|
486
|
+
const { spawn: spawn2 } = await import("child_process");
|
|
487
|
+
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
488
|
+
spawn2(cmd, [url], { stdio: "ignore", detached: true, shell: process.platform === "win32" }).unref();
|
|
489
|
+
} catch {
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
async function createApiKey(api, accessToken, plan) {
|
|
493
|
+
const { status, json } = await request("POST", `${api}/v1/products/${PRODUCT}/onboard`, {
|
|
494
|
+
bearer: accessToken,
|
|
495
|
+
body: { name: CLIENT_ID, product: PRODUCT, plan }
|
|
496
|
+
});
|
|
497
|
+
const key = json.raw_key || json.key || json.api_key;
|
|
498
|
+
if (status >= 400 || !key) {
|
|
499
|
+
const detail = json.error && typeof json.error === "object" ? json.error.message : void 0;
|
|
500
|
+
throw new LoginError(`could not create API key (HTTP ${status})${detail ? `: ${detail}` : ""}`);
|
|
501
|
+
}
|
|
502
|
+
return key;
|
|
503
|
+
}
|
|
504
|
+
async function login(opts = {}) {
|
|
505
|
+
const plan = opts.plan ?? DEFAULT_PLAN;
|
|
506
|
+
const accounts = accountsUrl();
|
|
507
|
+
const api = apiUrl();
|
|
508
|
+
let token = opts.accessToken ?? process.env.SQAI_TOKEN;
|
|
509
|
+
if (token) {
|
|
510
|
+
process.stdout.write("using supplied token (headless)\n");
|
|
511
|
+
} else {
|
|
512
|
+
process.stdout.write(`authenticating via ${accounts} \u2026
|
|
513
|
+
`);
|
|
514
|
+
token = await deviceAuthorize(accounts, opts.openBrowser ?? true);
|
|
515
|
+
}
|
|
516
|
+
cache(tokenPath(), token);
|
|
517
|
+
process.stdout.write("creating your free SQAI Developer API key \u2026\n");
|
|
518
|
+
const apiKey = await createApiKey(api, token, plan);
|
|
519
|
+
cache(apiKeyPath(), apiKey);
|
|
520
|
+
deviceId();
|
|
521
|
+
process.stdout.write(
|
|
522
|
+
"\n \u2713 sqai login complete \u2014 the local runtime will provision a device-bound offline license on first use.\n SQAI runs fully on your machine; no data leaves it.\n\n"
|
|
523
|
+
);
|
|
524
|
+
return {
|
|
525
|
+
device_id: deviceId(),
|
|
526
|
+
plan,
|
|
527
|
+
api_key_prefix: apiKey.includes("_") ? `${apiKey.split("_", 1)[0]}_\u2026` : `${apiKey.slice(0, 6)}\u2026`
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
function logout() {
|
|
531
|
+
for (const path of [tokenPath(), apiKeyPath()]) {
|
|
532
|
+
try {
|
|
533
|
+
(0, import_node_fs.rmSync)(path);
|
|
534
|
+
} catch {
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// src/runtime/bundle.ts
|
|
540
|
+
var import_node_child_process = require("child_process");
|
|
541
|
+
var import_node_crypto5 = require("crypto");
|
|
542
|
+
var import_node_fs2 = require("fs");
|
|
543
|
+
var import_node_path2 = require("path");
|
|
370
544
|
|
|
371
545
|
// src/runtime/trust.ts
|
|
372
|
-
var
|
|
546
|
+
var import_node_crypto4 = require("crypto");
|
|
373
547
|
var RELEASE_1_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----
|
|
374
548
|
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA7m4G1dEMi5FppLa5hu9N
|
|
375
549
|
4pUyoGELPaN5X7bO+9Qktgbv21+c8I4sQCufKouZEVNMNluKNrWcQ5dSwOuVxxS9
|
|
@@ -468,11 +642,11 @@ function keyValidNow(key, nowMs) {
|
|
|
468
642
|
}
|
|
469
643
|
function signatureVerifies(manifestBytes, signature, publicKeyPem) {
|
|
470
644
|
try {
|
|
471
|
-
const key = (0,
|
|
645
|
+
const key = (0, import_node_crypto4.createPublicKey)(publicKeyPem);
|
|
472
646
|
if (key.asymmetricKeyType !== "rsa") {
|
|
473
647
|
return false;
|
|
474
648
|
}
|
|
475
|
-
return (0,
|
|
649
|
+
return (0, import_node_crypto4.verify)("sha256", manifestBytes, key, signature);
|
|
476
650
|
} catch {
|
|
477
651
|
return false;
|
|
478
652
|
}
|
|
@@ -652,7 +826,7 @@ async function hashTarMember(tarball, member, cap) {
|
|
|
652
826
|
const child = (0, import_node_child_process.spawn)("tar", ["-xOf", tarball, "--", member], {
|
|
653
827
|
stdio: ["ignore", "pipe", "pipe"]
|
|
654
828
|
});
|
|
655
|
-
const digest = (0,
|
|
829
|
+
const digest = (0, import_node_crypto5.createHash)("sha256");
|
|
656
830
|
let total = 0;
|
|
657
831
|
let overflow = false;
|
|
658
832
|
child.stdout.on("data", (chunk) => {
|
|
@@ -686,7 +860,7 @@ async function hashTarMember(tarball, member, cap) {
|
|
|
686
860
|
});
|
|
687
861
|
}
|
|
688
862
|
async function extractTarball(tarball, destinationDir) {
|
|
689
|
-
await
|
|
863
|
+
await import_node_fs2.promises.mkdir(destinationDir, { recursive: true });
|
|
690
864
|
await new Promise((resolve, reject) => {
|
|
691
865
|
const child = (0, import_node_child_process.spawn)("tar", ["-xf", tarball, "-C", destinationDir], {
|
|
692
866
|
stdio: ["ignore", "ignore", "pipe"]
|
|
@@ -712,8 +886,8 @@ async function extractTarball(tarball, destinationDir) {
|
|
|
712
886
|
}
|
|
713
887
|
function sha256File(path) {
|
|
714
888
|
return new Promise((resolve, reject) => {
|
|
715
|
-
const digest = (0,
|
|
716
|
-
const stream = (0,
|
|
889
|
+
const digest = (0, import_node_crypto5.createHash)("sha256");
|
|
890
|
+
const stream = (0, import_node_fs2.createReadStream)(path);
|
|
717
891
|
stream.on("data", (chunk) => digest.update(chunk));
|
|
718
892
|
stream.on("error", reject);
|
|
719
893
|
stream.on("end", () => resolve(digest.digest("hex")));
|
|
@@ -722,7 +896,10 @@ function sha256File(path) {
|
|
|
722
896
|
function digestsEqual(actualHex, expectedHex) {
|
|
723
897
|
const actual = Buffer.from(actualHex.toLowerCase(), "utf-8");
|
|
724
898
|
const expected = Buffer.from(expectedHex.toLowerCase(), "utf-8");
|
|
725
|
-
return actual.length === expected.length && (0,
|
|
899
|
+
return actual.length === expected.length && (0, import_node_crypto5.timingSafeEqual)(actual, expected);
|
|
900
|
+
}
|
|
901
|
+
function isGeneratedBytecodeCache(path) {
|
|
902
|
+
return path.split("/").includes("__pycache__") && path.endsWith(".pyc") && isSafeRelativePath(path);
|
|
726
903
|
}
|
|
727
904
|
function parseVerifiedManifest(manifestBytes) {
|
|
728
905
|
let manifest;
|
|
@@ -872,7 +1049,7 @@ async function verifyBundleTarball(tarball, expectations) {
|
|
|
872
1049
|
return manifest;
|
|
873
1050
|
}
|
|
874
1051
|
async function listFilesRecursively(root, relative = "") {
|
|
875
|
-
const entries = await
|
|
1052
|
+
const entries = await import_node_fs2.promises.readdir((0, import_node_path2.join)(root, relative), { withFileTypes: true });
|
|
876
1053
|
const files = [];
|
|
877
1054
|
for (const entry of entries) {
|
|
878
1055
|
const relPath = relative === "" ? entry.name : `${relative}/${entry.name}`;
|
|
@@ -896,21 +1073,21 @@ async function listFilesRecursively(root, relative = "") {
|
|
|
896
1073
|
return files;
|
|
897
1074
|
}
|
|
898
1075
|
async function verifyInstalledBundleDir(installDir, expectations) {
|
|
899
|
-
const manifestPath = (0,
|
|
900
|
-
const signaturePath = (0,
|
|
1076
|
+
const manifestPath = (0, import_node_path2.join)(installDir, MANIFEST_NAME);
|
|
1077
|
+
const signaturePath = (0, import_node_path2.join)(installDir, MANIFEST_SIG_NAME);
|
|
901
1078
|
let manifestBytes;
|
|
902
1079
|
let signature;
|
|
903
1080
|
try {
|
|
904
|
-
const manifestStat = await
|
|
905
|
-
const signatureStat = await
|
|
1081
|
+
const manifestStat = await import_node_fs2.promises.lstat(manifestPath);
|
|
1082
|
+
const signatureStat = await import_node_fs2.promises.lstat(signaturePath);
|
|
906
1083
|
if (!manifestStat.isFile() || !signatureStat.isFile() || manifestStat.size > MAX_MANIFEST_BYTES || signatureStat.size > MAX_SIG_BYTES) {
|
|
907
1084
|
throw new BundleVerificationError(
|
|
908
1085
|
"member_unreadable",
|
|
909
1086
|
"installed bundle manifest/signature is not a capped regular file"
|
|
910
1087
|
);
|
|
911
1088
|
}
|
|
912
|
-
manifestBytes = await
|
|
913
|
-
signature = await
|
|
1089
|
+
manifestBytes = await import_node_fs2.promises.readFile(manifestPath);
|
|
1090
|
+
signature = await import_node_fs2.promises.readFile(signaturePath);
|
|
914
1091
|
} catch (error) {
|
|
915
1092
|
if (error instanceof BundleVerificationError) {
|
|
916
1093
|
throw error;
|
|
@@ -932,13 +1109,16 @@ async function verifyInstalledBundleDir(installDir, expectations) {
|
|
|
932
1109
|
}
|
|
933
1110
|
const entry = byPath.get(relPath);
|
|
934
1111
|
if (entry === void 0) {
|
|
1112
|
+
if (isGeneratedBytecodeCache(relPath)) {
|
|
1113
|
+
continue;
|
|
1114
|
+
}
|
|
935
1115
|
throw new BundleVerificationError(
|
|
936
1116
|
"unlisted_member",
|
|
937
1117
|
`installed file not listed in signed manifest: '${relPath}'`
|
|
938
1118
|
);
|
|
939
1119
|
}
|
|
940
|
-
const absolute = (0,
|
|
941
|
-
const stat = await
|
|
1120
|
+
const absolute = (0, import_node_path2.join)(installDir, relPath);
|
|
1121
|
+
const stat = await import_node_fs2.promises.lstat(absolute);
|
|
942
1122
|
if (stat.nlink > 1) {
|
|
943
1123
|
throw new BundleVerificationError(
|
|
944
1124
|
"unsafe_member",
|
|
@@ -994,28 +1174,28 @@ var LOCK_FRESH_MS = 10 * 60 * 1e3;
|
|
|
994
1174
|
var LOCK_WAIT_TIMEOUT_MS = 90 * 1e3;
|
|
995
1175
|
var LOCK_POLL_INTERVAL_MS = 1e3;
|
|
996
1176
|
function currentPlatformKey() {
|
|
997
|
-
const os = (0,
|
|
998
|
-
const arch = (0,
|
|
1177
|
+
const os = (0, import_node_os2.platform)();
|
|
1178
|
+
const arch = (0, import_node_os2.arch)();
|
|
999
1179
|
const osName = os === "darwin" ? "darwin" : os === "linux" ? "linux" : os;
|
|
1000
1180
|
return `${osName}-${arch}`;
|
|
1001
1181
|
}
|
|
1002
1182
|
function cacheDirFor(brand) {
|
|
1003
|
-
const os = (0,
|
|
1183
|
+
const os = (0, import_node_os2.platform)();
|
|
1004
1184
|
if (os === "darwin") {
|
|
1005
|
-
return (0,
|
|
1185
|
+
return (0, import_node_path3.join)((0, import_node_os2.homedir)(), "Library", "Caches", brand, "runtime");
|
|
1006
1186
|
}
|
|
1007
1187
|
if (os === "win32") {
|
|
1008
|
-
const localAppData = process.env.LOCALAPPDATA ?? (0,
|
|
1009
|
-
return (0,
|
|
1188
|
+
const localAppData = process.env.LOCALAPPDATA ?? (0, import_node_path3.join)((0, import_node_os2.homedir)(), "AppData", "Local");
|
|
1189
|
+
return (0, import_node_path3.join)(localAppData, brand, "runtime");
|
|
1010
1190
|
}
|
|
1011
|
-
const xdgCache = process.env.XDG_CACHE_HOME ?? (0,
|
|
1012
|
-
return (0,
|
|
1191
|
+
const xdgCache = process.env.XDG_CACHE_HOME ?? (0, import_node_path3.join)((0, import_node_os2.homedir)(), ".cache");
|
|
1192
|
+
return (0, import_node_path3.join)(xdgCache, brand.toLowerCase(), "runtime");
|
|
1013
1193
|
}
|
|
1014
1194
|
function runtimeCacheDir() {
|
|
1015
1195
|
const current = cacheDirFor("SQAI");
|
|
1016
|
-
if (!(0,
|
|
1196
|
+
if (!(0, import_node_fs3.existsSync)(current)) {
|
|
1017
1197
|
const legacy = cacheDirFor("Algenta");
|
|
1018
|
-
if (legacy !== current && (0,
|
|
1198
|
+
if (legacy !== current && (0, import_node_fs3.existsSync)(legacy)) {
|
|
1019
1199
|
return legacy;
|
|
1020
1200
|
}
|
|
1021
1201
|
}
|
|
@@ -1034,12 +1214,12 @@ async function defaultDownloadBundle(url, destination) {
|
|
|
1034
1214
|
}
|
|
1035
1215
|
await (0, import_promises.pipeline)(
|
|
1036
1216
|
import_node_stream.Readable.fromWeb(response.body),
|
|
1037
|
-
(0,
|
|
1217
|
+
(0, import_node_fs3.createWriteStream)(destination)
|
|
1038
1218
|
);
|
|
1039
1219
|
}
|
|
1040
1220
|
async function removeQuietly(path) {
|
|
1041
1221
|
try {
|
|
1042
|
-
await
|
|
1222
|
+
await import_node_fs3.promises.rm(path, { recursive: true, force: true });
|
|
1043
1223
|
} catch {
|
|
1044
1224
|
}
|
|
1045
1225
|
}
|
|
@@ -1100,6 +1280,21 @@ var RuntimeProvisioner = class _RuntimeProvisioner {
|
|
|
1100
1280
|
}
|
|
1101
1281
|
return new import_algenta_sdk2.MojoRuntime(config ?? {});
|
|
1102
1282
|
}
|
|
1283
|
+
async ensureLocalLoginKey() {
|
|
1284
|
+
if (this.options.runtimeFactory || process.env.ALGENTA_API_KEY || process.env.DE_API_KEY) {
|
|
1285
|
+
return;
|
|
1286
|
+
}
|
|
1287
|
+
const key = await readCachedApiKey();
|
|
1288
|
+
if (key) {
|
|
1289
|
+
process.env.ALGENTA_API_KEY = key;
|
|
1290
|
+
return;
|
|
1291
|
+
}
|
|
1292
|
+
throw new SqaiError(
|
|
1293
|
+
"login_required",
|
|
1294
|
+
"Local compute requires a free SQAI device login. Run `sqai login` once, or set SQAI_API_KEY in this process.",
|
|
1295
|
+
{ details: { reason: "login_key_missing" } }
|
|
1296
|
+
);
|
|
1297
|
+
}
|
|
1103
1298
|
cacheDir() {
|
|
1104
1299
|
return this.options.cacheDir ?? runtimeCacheDir();
|
|
1105
1300
|
}
|
|
@@ -1164,7 +1359,7 @@ var RuntimeProvisioner = class _RuntimeProvisioner {
|
|
|
1164
1359
|
localCacheKey(modules, platformKey) {
|
|
1165
1360
|
const canonical = modules.join(",");
|
|
1166
1361
|
const version = this.options.contract.runtime_bundle.version;
|
|
1167
|
-
return (0,
|
|
1362
|
+
return (0, import_node_crypto6.createHash)("sha256").update(`${canonical}|${platformKey}|${version}`).digest("hex").slice(0, 20);
|
|
1168
1363
|
}
|
|
1169
1364
|
/**
|
|
1170
1365
|
* Deterministic per-filter daemon endpoint so a filtered runtime never collides
|
|
@@ -1173,7 +1368,7 @@ var RuntimeProvisioner = class _RuntimeProvisioner {
|
|
|
1173
1368
|
filterEndpoint(cacheKey) {
|
|
1174
1369
|
const seed = parseInt(cacheKey.slice(0, 6), 16) || 0;
|
|
1175
1370
|
const port = 50100 + seed % 800;
|
|
1176
|
-
return { sock: (0,
|
|
1371
|
+
return { sock: (0, import_node_path3.join)(this.cacheDir(), `${cacheKey}.sock`), tcp: `127.0.0.1:${port}` };
|
|
1177
1372
|
}
|
|
1178
1373
|
static DAEMON_ENDPOINT_ENV = [
|
|
1179
1374
|
"ALGENTA_DAEMON_SOCK",
|
|
@@ -1190,7 +1385,7 @@ var RuntimeProvisioner = class _RuntimeProvisioner {
|
|
|
1190
1385
|
process.env.ALGENTA_DAEMON_SOCK = endpoint.sock;
|
|
1191
1386
|
process.env.ALGENTA_DAEMON_TCP = endpoint.tcp;
|
|
1192
1387
|
process.env.ALGENTA_MOJO_SOCK = `${endpoint.sock}.worker`;
|
|
1193
|
-
process.env.ALGENTA_RUNTIME_DIR = (0,
|
|
1388
|
+
process.env.ALGENTA_RUNTIME_DIR = (0, import_node_path3.join)(installDir, ".runtime");
|
|
1194
1389
|
return saved;
|
|
1195
1390
|
}
|
|
1196
1391
|
restoreEnv(saved) {
|
|
@@ -1205,6 +1400,7 @@ var RuntimeProvisioner = class _RuntimeProvisioner {
|
|
|
1205
1400
|
async doEnsure() {
|
|
1206
1401
|
const platformKey = currentPlatformKey();
|
|
1207
1402
|
const filter = this.filterModules();
|
|
1403
|
+
await this.ensureLocalLoginKey();
|
|
1208
1404
|
const probeEndpoint = filter ? this.filterEndpoint(this.localCacheKey(filter, platformKey)) : void 0;
|
|
1209
1405
|
const runtime = this.newRuntime(probeEndpoint ? { tcpAddress: probeEndpoint.tcp } : void 0);
|
|
1210
1406
|
try {
|
|
@@ -1232,7 +1428,7 @@ var RuntimeProvisioner = class _RuntimeProvisioner {
|
|
|
1232
1428
|
const supported = Object.keys(bundle.platforms);
|
|
1233
1429
|
throw new SqaiError(
|
|
1234
1430
|
"unsupported_platform",
|
|
1235
|
-
supported.length === 0 ? "No managed runtime bundle is published yet for any platform.
|
|
1431
|
+
supported.length === 0 ? "No managed runtime bundle is published yet for any platform. Run `sqai login`, or set SQAI_DEPLOYMENT_URL / SQAI_API_KEY for a managed SQAI deployment." : `No managed runtime bundle is published for '${platformKey}'.`,
|
|
1236
1432
|
{ details: { platform: platformKey, supported } }
|
|
1237
1433
|
);
|
|
1238
1434
|
}
|
|
@@ -1305,9 +1501,9 @@ var RuntimeProvisioner = class _RuntimeProvisioner {
|
|
|
1305
1501
|
}
|
|
1306
1502
|
/** Verify an existing install if present; returns null when absent/invalid. */
|
|
1307
1503
|
async verifiedInstallOrNull(platformKey, version, removeOnFailure, installKey = version) {
|
|
1308
|
-
const installDir = (0,
|
|
1504
|
+
const installDir = (0, import_node_path3.join)(this.cacheDir(), installKey);
|
|
1309
1505
|
try {
|
|
1310
|
-
await
|
|
1506
|
+
await import_node_fs3.promises.access((0, import_node_path3.join)(installDir, MANIFEST_NAME));
|
|
1311
1507
|
} catch {
|
|
1312
1508
|
return null;
|
|
1313
1509
|
}
|
|
@@ -1327,7 +1523,7 @@ var RuntimeProvisioner = class _RuntimeProvisioner {
|
|
|
1327
1523
|
async acquireLock(lockPath) {
|
|
1328
1524
|
const payload = JSON.stringify({ pid: process.pid, created_at: (/* @__PURE__ */ new Date()).toISOString() });
|
|
1329
1525
|
try {
|
|
1330
|
-
const handle = await
|
|
1526
|
+
const handle = await import_node_fs3.promises.open(lockPath, "wx");
|
|
1331
1527
|
try {
|
|
1332
1528
|
await handle.writeFile(payload, "utf-8");
|
|
1333
1529
|
} finally {
|
|
@@ -1340,12 +1536,22 @@ var RuntimeProvisioner = class _RuntimeProvisioner {
|
|
|
1340
1536
|
}
|
|
1341
1537
|
async lockIsStale(lockPath) {
|
|
1342
1538
|
const freshMs = this.options.lockFreshMs ?? LOCK_FRESH_MS;
|
|
1539
|
+
const ageFromMtime = async () => {
|
|
1540
|
+
try {
|
|
1541
|
+
const stat = await import_node_fs3.promises.stat(lockPath);
|
|
1542
|
+
return Date.now() - stat.mtimeMs;
|
|
1543
|
+
} catch (error) {
|
|
1544
|
+
const code = error.code;
|
|
1545
|
+
return code === "ENOENT" ? null : Number.POSITIVE_INFINITY;
|
|
1546
|
+
}
|
|
1547
|
+
};
|
|
1343
1548
|
try {
|
|
1344
|
-
const raw = await
|
|
1549
|
+
const raw = await import_node_fs3.promises.readFile(lockPath, "utf-8");
|
|
1345
1550
|
const parsed = JSON.parse(raw);
|
|
1346
1551
|
const createdAt = typeof parsed.created_at === "string" ? Date.parse(parsed.created_at) : NaN;
|
|
1347
1552
|
if (!Number.isFinite(createdAt)) {
|
|
1348
|
-
|
|
1553
|
+
const age = await ageFromMtime();
|
|
1554
|
+
return age !== null && age >= freshMs;
|
|
1349
1555
|
}
|
|
1350
1556
|
return Date.now() - createdAt >= freshMs;
|
|
1351
1557
|
} catch (error) {
|
|
@@ -1353,18 +1559,19 @@ var RuntimeProvisioner = class _RuntimeProvisioner {
|
|
|
1353
1559
|
if (code === "ENOENT") {
|
|
1354
1560
|
return false;
|
|
1355
1561
|
}
|
|
1356
|
-
|
|
1562
|
+
const age = await ageFromMtime();
|
|
1563
|
+
return age !== null && age >= freshMs;
|
|
1357
1564
|
}
|
|
1358
1565
|
}
|
|
1359
1566
|
/** Serialize installers on `<cacheDir>/<installKey>.lock`; returns the verified install. */
|
|
1360
1567
|
async ensureInstalled(platformKey, version, platformBundle, installKey = version) {
|
|
1361
1568
|
const cacheDir = this.cacheDir();
|
|
1362
|
-
await
|
|
1569
|
+
await import_node_fs3.promises.mkdir(cacheDir, { recursive: true });
|
|
1363
1570
|
const existing = await this.verifiedInstallOrNull(platformKey, version, true, installKey);
|
|
1364
1571
|
if (existing) {
|
|
1365
1572
|
return existing;
|
|
1366
1573
|
}
|
|
1367
|
-
const lockPath = (0,
|
|
1574
|
+
const lockPath = (0, import_node_path3.join)(cacheDir, `${installKey}.lock`);
|
|
1368
1575
|
const waitTimeoutMs = this.options.lockWaitTimeoutMs ?? LOCK_WAIT_TIMEOUT_MS;
|
|
1369
1576
|
const pollIntervalMs = this.options.lockPollIntervalMs ?? LOCK_POLL_INTERVAL_MS;
|
|
1370
1577
|
const deadline = Date.now() + waitTimeoutMs;
|
|
@@ -1409,10 +1616,10 @@ var RuntimeProvisioner = class _RuntimeProvisioner {
|
|
|
1409
1616
|
/** Holder-of-the-lock path: download → verify → extract → atomic rename. */
|
|
1410
1617
|
async downloadVerifyExtract(platformKey, version, platformBundle, installKey = version) {
|
|
1411
1618
|
const cacheDir = this.cacheDir();
|
|
1412
|
-
const token = (0,
|
|
1413
|
-
const tarballPath = (0,
|
|
1414
|
-
const extractDir = (0,
|
|
1415
|
-
const installDir = (0,
|
|
1619
|
+
const token = (0, import_node_crypto6.randomBytes)(6).toString("hex");
|
|
1620
|
+
const tarballPath = (0, import_node_path3.join)(cacheDir, `tmp-${token}.tgz`);
|
|
1621
|
+
const extractDir = (0, import_node_path3.join)(cacheDir, `tmp-${token}`);
|
|
1622
|
+
const installDir = (0, import_node_path3.join)(cacheDir, installKey);
|
|
1416
1623
|
const url = resolveBundleUrl(platformBundle.url, version, platformKey);
|
|
1417
1624
|
try {
|
|
1418
1625
|
const download = this.options.downloadBundle ?? defaultDownloadBundle;
|
|
@@ -1457,7 +1664,7 @@ var RuntimeProvisioner = class _RuntimeProvisioner {
|
|
|
1457
1664
|
throw this.wrapVerificationError(error, platformKey, version);
|
|
1458
1665
|
}
|
|
1459
1666
|
try {
|
|
1460
|
-
await
|
|
1667
|
+
await import_node_fs3.promises.rename(extractDir, installDir);
|
|
1461
1668
|
} catch (error) {
|
|
1462
1669
|
const raced = await this.verifiedInstallOrNull(platformKey, version, false, installKey);
|
|
1463
1670
|
if (raced) {
|
|
@@ -1487,10 +1694,11 @@ var RuntimeProvisioner = class _RuntimeProvisioner {
|
|
|
1487
1694
|
throw this.wrapVerificationError(error, platformKey, version);
|
|
1488
1695
|
}
|
|
1489
1696
|
const daemonCommand = [
|
|
1490
|
-
(0,
|
|
1697
|
+
(0, import_node_path3.join)(installed.installDir, ...entryRelative.split("/")),
|
|
1491
1698
|
"start",
|
|
1492
1699
|
"--foreground"
|
|
1493
1700
|
];
|
|
1701
|
+
await this.ensureLocalLoginKey();
|
|
1494
1702
|
const managed = this.newRuntime(
|
|
1495
1703
|
endpoint ? { autoStart: true, daemonCommand, tcpAddress: endpoint.tcp } : { autoStart: true, daemonCommand }
|
|
1496
1704
|
);
|
|
@@ -1524,8 +1732,8 @@ var RuntimeProvisioner = class _RuntimeProvisioner {
|
|
|
1524
1732
|
}
|
|
1525
1733
|
}
|
|
1526
1734
|
try {
|
|
1527
|
-
await
|
|
1528
|
-
(0,
|
|
1735
|
+
await import_node_fs3.promises.writeFile(
|
|
1736
|
+
(0, import_node_path3.join)(this.cacheDir(), "state.json"),
|
|
1529
1737
|
JSON.stringify(
|
|
1530
1738
|
{ pid: null, version, started_at: (/* @__PURE__ */ new Date()).toISOString() },
|
|
1531
1739
|
null,
|
|
@@ -1559,7 +1767,7 @@ async function dispatchComputation(target, entry, argsVector, seed, requestId, t
|
|
|
1559
1767
|
request_id: response.request_id ?? requestId
|
|
1560
1768
|
};
|
|
1561
1769
|
} catch (error) {
|
|
1562
|
-
throw
|
|
1770
|
+
throw fromEngineError(error);
|
|
1563
1771
|
}
|
|
1564
1772
|
}
|
|
1565
1773
|
return dispatchHttp(target, module2, functionName, args, requestId);
|
|
@@ -1596,7 +1804,7 @@ async function dispatchHttp(target, module2, functionName, args, requestId) {
|
|
|
1596
1804
|
} catch (error) {
|
|
1597
1805
|
throw new SqaiError(
|
|
1598
1806
|
"compute_runtime_unavailable",
|
|
1599
|
-
`The
|
|
1807
|
+
`The SQAI deployment endpoint is unreachable: ${error.message}. Check SQAI_DEPLOYMENT_URL / SQAI_API_KEY.`,
|
|
1600
1808
|
{ retryable: true }
|
|
1601
1809
|
);
|
|
1602
1810
|
}
|
|
@@ -1779,7 +1987,7 @@ var SQAI = class {
|
|
|
1779
1987
|
const env = readEnv();
|
|
1780
1988
|
this.mode = inferMode(config.mode, env);
|
|
1781
1989
|
this.apiKey = config.apiKey ?? env.apiKey;
|
|
1782
|
-
this.engineUrl = config.engineUrl ?? env.engineUrl;
|
|
1990
|
+
this.engineUrl = config.deploymentUrl ?? config.engineUrl ?? env.engineUrl;
|
|
1783
1991
|
this.tenantId = config.tenantId ?? null;
|
|
1784
1992
|
this.policy = config.policy;
|
|
1785
1993
|
this.configuredTarget = config.computeTarget;
|
|
@@ -1807,7 +2015,7 @@ var SQAI = class {
|
|
|
1807
2015
|
this.algentaRuntime = this.rawRuntime;
|
|
1808
2016
|
}
|
|
1809
2017
|
// ── Query plane ────────────────────────────────────────────────────────────
|
|
1810
|
-
async connect(source, options = {}) {
|
|
2018
|
+
async connect(source = null, options = {}) {
|
|
1811
2019
|
try {
|
|
1812
2020
|
const registration = await this.algentaRuntime.connect(source, options);
|
|
1813
2021
|
const mapped = mapSource(registration);
|
|
@@ -1826,7 +2034,84 @@ var SQAI = class {
|
|
|
1826
2034
|
this.sources.set(mapped.name, mapped);
|
|
1827
2035
|
return mapped;
|
|
1828
2036
|
} catch (error) {
|
|
1829
|
-
throw error instanceof SqaiError ? error :
|
|
2037
|
+
throw error instanceof SqaiError ? error : fromEngineError(error);
|
|
2038
|
+
}
|
|
2039
|
+
}
|
|
2040
|
+
async createConnector(request2) {
|
|
2041
|
+
const createConnector = this.algentaRuntime.createConnector;
|
|
2042
|
+
if (typeof createConnector !== "function") {
|
|
2043
|
+
throw unsupportedSubstrateOperation("createConnector");
|
|
2044
|
+
}
|
|
2045
|
+
try {
|
|
2046
|
+
return await createConnector.call(this.algentaRuntime, request2);
|
|
2047
|
+
} catch (error) {
|
|
2048
|
+
throw fromEngineError(error);
|
|
2049
|
+
}
|
|
2050
|
+
}
|
|
2051
|
+
async listConnectors(options = {}) {
|
|
2052
|
+
const listConnectors = this.algentaRuntime.listConnectors;
|
|
2053
|
+
if (typeof listConnectors !== "function") {
|
|
2054
|
+
throw unsupportedSubstrateOperation("listConnectors");
|
|
2055
|
+
}
|
|
2056
|
+
try {
|
|
2057
|
+
return await listConnectors.call(this.algentaRuntime, options);
|
|
2058
|
+
} catch (error) {
|
|
2059
|
+
throw fromEngineError(error);
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
async getConnector(connectorId) {
|
|
2063
|
+
const getConnector = this.algentaRuntime.getConnector;
|
|
2064
|
+
if (typeof getConnector !== "function") {
|
|
2065
|
+
throw unsupportedSubstrateOperation("getConnector");
|
|
2066
|
+
}
|
|
2067
|
+
try {
|
|
2068
|
+
return await getConnector.call(this.algentaRuntime, connectorId);
|
|
2069
|
+
} catch (error) {
|
|
2070
|
+
throw fromEngineError(error);
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
async updateConnector(connectorId, request2) {
|
|
2074
|
+
const updateConnector = this.algentaRuntime.updateConnector;
|
|
2075
|
+
if (typeof updateConnector !== "function") {
|
|
2076
|
+
throw unsupportedSubstrateOperation("updateConnector");
|
|
2077
|
+
}
|
|
2078
|
+
try {
|
|
2079
|
+
return await updateConnector.call(this.algentaRuntime, connectorId, request2);
|
|
2080
|
+
} catch (error) {
|
|
2081
|
+
throw fromEngineError(error);
|
|
2082
|
+
}
|
|
2083
|
+
}
|
|
2084
|
+
async testConnector(connectorIdOrConnector) {
|
|
2085
|
+
const testConnector = this.algentaRuntime.testConnector;
|
|
2086
|
+
if (typeof testConnector !== "function") {
|
|
2087
|
+
throw unsupportedSubstrateOperation("testConnector");
|
|
2088
|
+
}
|
|
2089
|
+
try {
|
|
2090
|
+
return await testConnector.call(this.algentaRuntime, connectorIdOrConnector);
|
|
2091
|
+
} catch (error) {
|
|
2092
|
+
throw fromEngineError(error);
|
|
2093
|
+
}
|
|
2094
|
+
}
|
|
2095
|
+
async browseConnector(connectorIdOrConnector) {
|
|
2096
|
+
const browseConnector = this.algentaRuntime.browseConnector;
|
|
2097
|
+
if (typeof browseConnector !== "function") {
|
|
2098
|
+
throw unsupportedSubstrateOperation("browseConnector");
|
|
2099
|
+
}
|
|
2100
|
+
try {
|
|
2101
|
+
return await browseConnector.call(this.algentaRuntime, connectorIdOrConnector);
|
|
2102
|
+
} catch (error) {
|
|
2103
|
+
throw fromEngineError(error);
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
2106
|
+
async deleteConnector(connectorId) {
|
|
2107
|
+
const deleteConnector = this.algentaRuntime.deleteConnector;
|
|
2108
|
+
if (typeof deleteConnector !== "function") {
|
|
2109
|
+
throw unsupportedSubstrateOperation("deleteConnector");
|
|
2110
|
+
}
|
|
2111
|
+
try {
|
|
2112
|
+
await deleteConnector.call(this.algentaRuntime, connectorId);
|
|
2113
|
+
} catch (error) {
|
|
2114
|
+
throw fromEngineError(error);
|
|
1830
2115
|
}
|
|
1831
2116
|
}
|
|
1832
2117
|
listSources() {
|
|
@@ -1837,28 +2122,28 @@ var SQAI = class {
|
|
|
1837
2122
|
try {
|
|
1838
2123
|
return await this.algentaRuntime.resolve(spec);
|
|
1839
2124
|
} catch (error) {
|
|
1840
|
-
throw
|
|
2125
|
+
throw fromEngineError(error);
|
|
1841
2126
|
}
|
|
1842
2127
|
}
|
|
1843
2128
|
async query(plan) {
|
|
1844
2129
|
try {
|
|
1845
2130
|
return await this.algentaRuntime.query(plan);
|
|
1846
2131
|
} catch (error) {
|
|
1847
|
-
throw
|
|
2132
|
+
throw fromEngineError(error);
|
|
1848
2133
|
}
|
|
1849
2134
|
}
|
|
1850
2135
|
async queryWithMetadata(plan) {
|
|
1851
2136
|
try {
|
|
1852
2137
|
return await this.algentaRuntime.queryWithMetadata(plan);
|
|
1853
2138
|
} catch (error) {
|
|
1854
|
-
throw
|
|
2139
|
+
throw fromEngineError(error);
|
|
1855
2140
|
}
|
|
1856
2141
|
}
|
|
1857
2142
|
async verify(plan) {
|
|
1858
2143
|
try {
|
|
1859
2144
|
return await this.algentaRuntime.verify(plan);
|
|
1860
2145
|
} catch (error) {
|
|
1861
|
-
throw
|
|
2146
|
+
throw fromEngineError(error);
|
|
1862
2147
|
}
|
|
1863
2148
|
}
|
|
1864
2149
|
async ask(spec) {
|
|
@@ -1880,21 +2165,21 @@ var SQAI = class {
|
|
|
1880
2165
|
if (typeof this.algentaRuntime.extractColumns !== "function") {
|
|
1881
2166
|
throw new SqaiError(
|
|
1882
2167
|
"unsupported_operation",
|
|
1883
|
-
"The installed
|
|
1884
|
-
{ details: { required: "
|
|
2168
|
+
"The installed SQAI package does not provide extractColumns; upgrade SQAI.",
|
|
2169
|
+
{ details: { required: "sqai.extractColumns" } }
|
|
1885
2170
|
);
|
|
1886
2171
|
}
|
|
1887
2172
|
try {
|
|
1888
2173
|
return await this.algentaRuntime.extractColumns(sourceName, columns, options);
|
|
1889
2174
|
} catch (error) {
|
|
1890
|
-
throw
|
|
2175
|
+
throw fromEngineError(error);
|
|
1891
2176
|
}
|
|
1892
2177
|
}
|
|
1893
2178
|
// ── Computation plane ──────────────────────────────────────────────────────
|
|
1894
2179
|
async compute(spec) {
|
|
1895
2180
|
const resolvedBindings = await this.resolveBindings(spec.bindings ?? []);
|
|
1896
2181
|
const validated = validateComputation(spec, this.contractIndex, this.policy, resolvedBindings);
|
|
1897
|
-
const requestId = `sqai_${(0,
|
|
2182
|
+
const requestId = `sqai_${(0, import_node_crypto7.randomBytes)(8).toString("hex")}`;
|
|
1898
2183
|
const target = await this.dispatchTarget();
|
|
1899
2184
|
const outcome = await dispatchComputation(
|
|
1900
2185
|
target,
|
|
@@ -1937,7 +2222,7 @@ var SQAI = class {
|
|
|
1937
2222
|
runtime_bundle_version: bundle.version || "unmanaged",
|
|
1938
2223
|
runtime_bundle_sha256: platformBundle?.sha256 ?? "unmanaged",
|
|
1939
2224
|
platform: currentPlatformKey(),
|
|
1940
|
-
architecture: (0,
|
|
2225
|
+
architecture: (0, import_node_os3.arch)(),
|
|
1941
2226
|
kernel_build: outcome.engine_used,
|
|
1942
2227
|
precision_mode: "float64",
|
|
1943
2228
|
thread_count: 1,
|
|
@@ -2017,7 +2302,7 @@ var SQAI = class {
|
|
|
2017
2302
|
"API mode requires SQAI_API_KEY for the computation plane."
|
|
2018
2303
|
);
|
|
2019
2304
|
}
|
|
2020
|
-
return { kind: "http", baseUrl: "https://api.
|
|
2305
|
+
return { kind: "http", baseUrl: "https://api.sqai.com", apiKey: this.apiKey };
|
|
2021
2306
|
}
|
|
2022
2307
|
const runtime = await this.provisioner.ensure();
|
|
2023
2308
|
return { kind: "local", runtime };
|
|
@@ -2075,6 +2360,13 @@ var SQAI = class {
|
|
|
2075
2360
|
function createSQAI(config = {}) {
|
|
2076
2361
|
return new SQAI(config);
|
|
2077
2362
|
}
|
|
2363
|
+
function unsupportedSubstrateOperation(operation) {
|
|
2364
|
+
return new SqaiError(
|
|
2365
|
+
"unsupported_operation",
|
|
2366
|
+
`The installed SQAI package does not provide ${operation}; upgrade SQAI.`,
|
|
2367
|
+
{ details: { required: `sqai.${operation}` } }
|
|
2368
|
+
);
|
|
2369
|
+
}
|
|
2078
2370
|
function mapSource(registration) {
|
|
2079
2371
|
const record = registration;
|
|
2080
2372
|
return {
|
|
@@ -2088,12 +2380,61 @@ function mapSource(registration) {
|
|
|
2088
2380
|
status: String(registration.status ?? "ready")
|
|
2089
2381
|
};
|
|
2090
2382
|
}
|
|
2383
|
+
|
|
2384
|
+
// src/types.ts
|
|
2385
|
+
var SQAI_CONNECTOR_TYPES = [
|
|
2386
|
+
"s3",
|
|
2387
|
+
"gcs",
|
|
2388
|
+
"azure",
|
|
2389
|
+
"clickhouse",
|
|
2390
|
+
"bigquery",
|
|
2391
|
+
"snowflake",
|
|
2392
|
+
"redshift",
|
|
2393
|
+
"postgres",
|
|
2394
|
+
"postgresql",
|
|
2395
|
+
"sqlite",
|
|
2396
|
+
"mysql",
|
|
2397
|
+
"mssql",
|
|
2398
|
+
"oracle",
|
|
2399
|
+
"neo4j",
|
|
2400
|
+
"redis",
|
|
2401
|
+
"elastic",
|
|
2402
|
+
"elasticsearch",
|
|
2403
|
+
"rest",
|
|
2404
|
+
"rest_api",
|
|
2405
|
+
"file",
|
|
2406
|
+
"file_upload",
|
|
2407
|
+
"github_repo",
|
|
2408
|
+
"gitlab_repo",
|
|
2409
|
+
"bitbucket_repo",
|
|
2410
|
+
"local_repo",
|
|
2411
|
+
"repo_archive"
|
|
2412
|
+
];
|
|
2413
|
+
var SQAI_CONNECTOR_TYPE_ALIASES = {
|
|
2414
|
+
postgresql: "postgres",
|
|
2415
|
+
click_house: "clickhouse",
|
|
2416
|
+
redis_cache: "redis",
|
|
2417
|
+
elastic: "elasticsearch",
|
|
2418
|
+
rest_api: "rest",
|
|
2419
|
+
file_upload: "file",
|
|
2420
|
+
github: "github_repo",
|
|
2421
|
+
github_repository: "github_repo",
|
|
2422
|
+
gitlab: "gitlab_repo",
|
|
2423
|
+
gitlab_repository: "gitlab_repo",
|
|
2424
|
+
bitbucket: "bitbucket_repo",
|
|
2425
|
+
bitbucket_repository: "bitbucket_repo",
|
|
2426
|
+
local_repository: "local_repo",
|
|
2427
|
+
archive_repository: "repo_archive"
|
|
2428
|
+
};
|
|
2091
2429
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2092
2430
|
0 && (module.exports = {
|
|
2093
2431
|
ContractIndex,
|
|
2432
|
+
LoginError,
|
|
2094
2433
|
ResultStore,
|
|
2095
2434
|
RuntimeProvisioner,
|
|
2096
2435
|
SQAI,
|
|
2436
|
+
SQAI_CONNECTOR_TYPES,
|
|
2437
|
+
SQAI_CONNECTOR_TYPE_ALIASES,
|
|
2097
2438
|
SQAI_ERROR_CODES,
|
|
2098
2439
|
SqaiError,
|
|
2099
2440
|
computationHash,
|
|
@@ -2101,8 +2442,11 @@ function mapSource(registration) {
|
|
|
2101
2442
|
currentPlatformKey,
|
|
2102
2443
|
invocationHash,
|
|
2103
2444
|
isReadOnlyEligible,
|
|
2445
|
+
login,
|
|
2446
|
+
logout,
|
|
2104
2447
|
lookupCapability,
|
|
2448
|
+
readCachedApiKey,
|
|
2105
2449
|
runtimeCacheDir,
|
|
2450
|
+
sqaiHome,
|
|
2106
2451
|
validateComputation
|
|
2107
2452
|
});
|
|
2108
|
-
//# sourceMappingURL=index.cjs.map
|