@ariacompute/engine-ts 1.15.0 → 1.16.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 CHANGED
@@ -24,10 +24,12 @@ and then loads it. Dashboard is not used. A Dashboard `sk-` / `bfvk-` token is
24
24
  ignored for hub auth. Token is optional for public models. A valid cached bundle
25
25
  is reused without re-downloading.
26
26
 
27
- Gated files: pass `hfToken` (`.com`) or `modelscopeApiToken` (`.cn`) — same keys as
28
- `aria-engine auth`. If omitted, the SDK reads `~/.ariacompute/config.yml`.
27
+ Gated files: call `eng.auth({ hf_token })` (`.com`) or `eng.auth({ modelscope_api_token, site_url })` (`.cn`) **before** `open`. Same keys as `aria-engine auth`. Instance-only; does not write `config.yml`. If omitted, the SDK reads `~/.ariacompute/config.yml`.
29
28
 
30
29
  ```ts
31
30
  const eng = await Engine.open("gemma-4-e2b-it_q4");
32
- const gated = await Engine.open("gemma-4-e2b-it_q4", { hfToken: "hf_..." });
31
+
32
+ const gated = new Engine();
33
+ gated.auth({ hf_token: "hf_..." });
34
+ await gated.open("gemma-4-e2b-it_q4");
33
35
  ```
package/dist/index.d.ts CHANGED
@@ -38,6 +38,34 @@ export interface OpenOptions {
38
38
  /** Explicit path to the FFI library. */
39
39
  ffiLib?: string;
40
40
  }
41
+ export declare const INTL_CLOUD = "https://gateway.ariacompute.com";
42
+ export declare const INTL_SITE = "https://ariacompute.com";
43
+ export declare const INTL_UPGRADE = "https://github.com/ariacompute";
44
+ export declare const CN_CLOUD = "https://gateway.ariacompute.cn";
45
+ export declare const CN_SITE = "https://ariacompute.cn";
46
+ export declare const CN_UPGRADE = "https://gitee.com/ariacompute";
47
+ export interface AuthConfig {
48
+ cloud_api_key: string;
49
+ cloud_url: string;
50
+ site_url: string;
51
+ upgrade_url: string;
52
+ hybrid_mode: string;
53
+ hybrid_execution: string;
54
+ hybrid_semantic: boolean;
55
+ hybrid_semantic_timeout_ms: number;
56
+ hybrid_semantic_cache_size: number;
57
+ compute: string;
58
+ hf_token: string;
59
+ modelscope_api_token: string;
60
+ }
61
+ export declare function defaultAuthConfig(): AuthConfig;
62
+ export declare function fillAuthUrls(cfg: AuthConfig): AuthConfig;
63
+ /** Replace `authHooks.probeDashboard` in tests to avoid a real Dashboard probe. */
64
+ export declare const authHooks: {
65
+ probeDashboard: (siteUrl: string, apiKey: string) => boolean;
66
+ };
67
+ export declare function detectGatewayPair(apiKey: string): [string, string, string];
68
+ export declare function applyAuth(existing: AuthConfig, updates: Partial<AuthConfig>): AuthConfig;
41
69
  /** Parse `slug`/`quant` from a model name such as `gemma-4-e2b-it_q4`. */
42
70
  export declare function parseBundleName(model: string): {
43
71
  slug: string;
@@ -70,8 +98,18 @@ export declare class Engine {
70
98
  private fnEmbed;
71
99
  private fnTranscribe;
72
100
  private fnLastError;
73
- /** Construct from a local bundle directory. */
74
- constructor(bundle: string, opts?: OpenOptions);
101
+ private cfg;
102
+ private opts;
103
+ /** Empty construct, or a local bundle directory. */
104
+ constructor(bundle?: string, opts?: OpenOptions);
105
+ /** Set Config / Run fields on this instance only. Does not write config.yml. */
106
+ auth(updates: Partial<AuthConfig>): this;
107
+ authStatus(): AuthConfig;
108
+ /** Reset instance defaults. Does not delete ~/.ariacompute/config.yml. */
109
+ authClear(): this;
110
+ private bindAndInit;
111
+ /** Download (if needed) and load a model using instance auth. */
112
+ open(modelRef: string): Promise<this>;
75
113
  /** Auto-detect: a value containing a separator or already on disk is a local
76
114
  * path; otherwise it is a model name downloaded from the regional public hub. */
77
115
  static open(modelRef: string, opts?: OpenOptions): Promise<Engine>;
package/dist/index.js CHANGED
@@ -33,7 +33,11 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports._internal = exports.Engine = void 0;
36
+ exports._internal = exports.Engine = exports.authHooks = exports.CN_UPGRADE = exports.CN_SITE = exports.CN_CLOUD = exports.INTL_UPGRADE = exports.INTL_SITE = exports.INTL_CLOUD = void 0;
37
+ exports.defaultAuthConfig = defaultAuthConfig;
38
+ exports.fillAuthUrls = fillAuthUrls;
39
+ exports.detectGatewayPair = detectGatewayPair;
40
+ exports.applyAuth = applyAuth;
37
41
  exports.parseBundleName = parseBundleName;
38
42
  exports.preferredPublicHub = preferredPublicHub;
39
43
  exports.hubBearer = hubBearer;
@@ -56,6 +60,127 @@ const promises_1 = require("node:stream/promises");
56
60
  const node_stream_1 = require("node:stream");
57
61
  const zlib = __importStar(require("node:zlib"));
58
62
  const DEFAULT_SITE = "https://ariacompute.com";
63
+ exports.INTL_CLOUD = "https://gateway.ariacompute.com";
64
+ exports.INTL_SITE = "https://ariacompute.com";
65
+ exports.INTL_UPGRADE = "https://github.com/ariacompute";
66
+ exports.CN_CLOUD = "https://gateway.ariacompute.cn";
67
+ exports.CN_SITE = "https://ariacompute.cn";
68
+ exports.CN_UPGRADE = "https://gitee.com/ariacompute";
69
+ function defaultAuthConfig() {
70
+ return {
71
+ cloud_api_key: "",
72
+ cloud_url: "",
73
+ site_url: "",
74
+ upgrade_url: "",
75
+ hybrid_mode: "balance",
76
+ hybrid_execution: "hybrid",
77
+ hybrid_semantic: true,
78
+ hybrid_semantic_timeout_ms: 800,
79
+ hybrid_semantic_cache_size: 512,
80
+ compute: "auto",
81
+ hf_token: "",
82
+ modelscope_api_token: "",
83
+ };
84
+ }
85
+ function gatewayRegion(url) {
86
+ const lower = (url || "").toLowerCase();
87
+ if (lower.includes("ariacompute.cn") || lower.includes("gitee.com/ariacompute"))
88
+ return "cn";
89
+ if (lower.includes("ariacompute.com") || lower.includes("github.com/ariacompute"))
90
+ return "intl";
91
+ return undefined;
92
+ }
93
+ function pairUrls(region) {
94
+ return region === "cn" ? [exports.CN_CLOUD, exports.CN_SITE, exports.CN_UPGRADE] : [exports.INTL_CLOUD, exports.INTL_SITE, exports.INTL_UPGRADE];
95
+ }
96
+ function fillAuthUrls(cfg) {
97
+ const out = { ...cfg };
98
+ const region = gatewayRegion(out.site_url) || gatewayRegion(out.cloud_url) || gatewayRegion(out.upgrade_url);
99
+ if (!region)
100
+ return out;
101
+ const [cloud, site, upgrade] = pairUrls(region);
102
+ if (!out.cloud_url)
103
+ out.cloud_url = cloud;
104
+ if (!out.site_url)
105
+ out.site_url = site;
106
+ if (!out.upgrade_url)
107
+ out.upgrade_url = upgrade;
108
+ return out;
109
+ }
110
+ function localePrefersCn() {
111
+ const lang = `${process.env.LANG || ""}${process.env.LC_ALL || ""}`.toLowerCase();
112
+ return lang.includes("zh") || lang.includes(".cn") || lang.startsWith("cn");
113
+ }
114
+ function defaultProbeDashboard(siteUrl, apiKey) {
115
+ const url = `${(siteUrl || "").replace(/\/$/, "")}/api/dashboard/models`;
116
+ const script = 'fetch(process.env.ARIA_PROBE_URL,{headers:{"User-Agent":"aria-engine-sdk/0.1.0","Authorization":"Bearer "+process.env.ARIA_PROBE_KEY},redirect:"follow"}).then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))';
117
+ const r = (0, node_child_process_1.spawnSync)(process.execPath, ["-e", script], {
118
+ env: { ...process.env, ARIA_PROBE_URL: url, ARIA_PROBE_KEY: apiKey },
119
+ timeout: 10000,
120
+ });
121
+ return r.status === 0;
122
+ }
123
+ /** Replace `authHooks.probeDashboard` in tests to avoid a real Dashboard probe. */
124
+ exports.authHooks = {
125
+ probeDashboard: defaultProbeDashboard,
126
+ };
127
+ function detectGatewayPair(apiKey) {
128
+ const key = (apiKey || "").trim();
129
+ const first = localePrefersCn() ? "cn" : "intl";
130
+ const second = first === "cn" ? "intl" : "cn";
131
+ for (const region of [first, second]) {
132
+ const [cloud, site, upgrade] = pairUrls(region);
133
+ if (key && exports.authHooks.probeDashboard(site, key))
134
+ return [cloud, site, upgrade];
135
+ }
136
+ return pairUrls(first);
137
+ }
138
+ function applyAuth(existing, updates) {
139
+ const out = { ...existing };
140
+ for (const [k, v] of Object.entries(updates)) {
141
+ if (v === undefined)
142
+ continue;
143
+ out[k] = v;
144
+ }
145
+ if (!["cost", "balance", "intelligence"].includes(out.hybrid_mode)) {
146
+ throw new Error(`invalid hybrid_mode: ${out.hybrid_mode}`);
147
+ }
148
+ if (!["hybrid", "device", "cloud"].includes(out.hybrid_execution)) {
149
+ throw new Error(`invalid hybrid_execution: ${out.hybrid_execution}`);
150
+ }
151
+ if (!["auto", "cpu", "cuda"].includes(out.compute)) {
152
+ throw new Error(`invalid compute: ${out.compute}`);
153
+ }
154
+ const timeout = Number(out.hybrid_semantic_timeout_ms);
155
+ const cache = Number(out.hybrid_semantic_cache_size);
156
+ if (!Number.isInteger(timeout) || !Number.isInteger(cache) || timeout <= 0 || cache <= 0) {
157
+ throw new Error("hybrid_semantic_timeout_ms / cache_size must be positive integers");
158
+ }
159
+ out.hybrid_semantic = Boolean(out.hybrid_semantic);
160
+ out.hybrid_semantic_timeout_ms = timeout;
161
+ out.hybrid_semantic_cache_size = cache;
162
+ for (const key of [
163
+ "cloud_api_key",
164
+ "cloud_url",
165
+ "site_url",
166
+ "upgrade_url",
167
+ "hf_token",
168
+ "modelscope_api_token",
169
+ ]) {
170
+ out[key] = out[key] == null ? "" : String(out[key]);
171
+ }
172
+ const filled = fillAuthUrls(out);
173
+ if (filled.cloud_api_key && !(filled.cloud_url && filled.site_url && filled.upgrade_url)) {
174
+ const [cloud, site, upgrade] = detectGatewayPair(filled.cloud_api_key);
175
+ if (!filled.cloud_url)
176
+ filled.cloud_url = cloud;
177
+ if (!filled.site_url)
178
+ filled.site_url = site;
179
+ if (!filled.upgrade_url)
180
+ filled.upgrade_url = upgrade;
181
+ }
182
+ return filled;
183
+ }
59
184
  const DEFAULT_SDK = "v1.0";
60
185
  const HUB_REQUIRED = ["config.json", "weight.bin"];
61
186
  const HUB_OPTIONAL = [
@@ -508,9 +633,38 @@ function isLocalRef(modelRef) {
508
633
  return modelRef.includes("/") || modelRef.includes("\\") || fs.existsSync(modelRef);
509
634
  }
510
635
  class Engine {
511
- /** Construct from a local bundle directory. */
636
+ /** Empty construct, or a local bundle directory. */
512
637
  constructor(bundle, opts = {}) {
513
- this.lib = loadLib(opts.ffiLib, opts.site);
638
+ this.lib = null;
639
+ this.handle = null;
640
+ this.cfg = defaultAuthConfig();
641
+ this.opts = {};
642
+ this.opts = opts;
643
+ if (opts.site || opts.hfToken || opts.modelscopeApiToken) {
644
+ this.auth({
645
+ site_url: opts.site,
646
+ hf_token: opts.hfToken,
647
+ modelscope_api_token: opts.modelscopeApiToken,
648
+ });
649
+ }
650
+ if (bundle)
651
+ this.bindAndInit(bundle, opts.ffiLib);
652
+ }
653
+ /** Set Config / Run fields on this instance only. Does not write config.yml. */
654
+ auth(updates) {
655
+ this.cfg = applyAuth(this.cfg, updates);
656
+ return this;
657
+ }
658
+ authStatus() {
659
+ return { ...this.cfg };
660
+ }
661
+ /** Reset instance defaults. Does not delete ~/.ariacompute/config.yml. */
662
+ authClear() {
663
+ this.cfg = defaultAuthConfig();
664
+ return this;
665
+ }
666
+ bindAndInit(bundle, ffiLib) {
667
+ this.lib = loadLib(ffiLib || this.opts.ffiLib, this.cfg.site_url || this.opts.site);
514
668
  this.fnInit = this.lib.func("aria_model_init", "void*", ["str"]);
515
669
  this.fnDestroy = this.lib.func("aria_model_destroy", "void", ["void*"]);
516
670
  this.fnComplete = this.lib.func("aria_complete", "int", ["void*", "str", "str", "str", "void*", "size_t"]);
@@ -523,14 +677,27 @@ class Engine {
523
677
  throw new Error(err || "init failed");
524
678
  }
525
679
  }
680
+ /** Download (if needed) and load a model using instance auth. */
681
+ async open(modelRef) {
682
+ await ensureFfiLib(this.cfg.site_url || this.opts.site);
683
+ const openOpts = {
684
+ ...this.opts,
685
+ site: this.cfg.site_url || this.opts.site,
686
+ hfToken: this.cfg.hf_token || this.opts.hfToken,
687
+ modelscopeApiToken: this.cfg.modelscope_api_token || this.opts.modelscopeApiToken,
688
+ };
689
+ const bundle = isLocalRef(modelRef) ? modelRef : await downloadModel(modelRef, openOpts);
690
+ if (this.handle)
691
+ this.close();
692
+ this.bindAndInit(bundle, this.opts.ffiLib);
693
+ return this;
694
+ }
526
695
  /** Auto-detect: a value containing a separator or already on disk is a local
527
696
  * path; otherwise it is a model name downloaded from the regional public hub. */
528
697
  static async open(modelRef, opts = {}) {
529
- await ensureFfiLib(opts.site);
530
- if (isLocalRef(modelRef))
531
- return new Engine(modelRef, opts);
532
- const bundle = await downloadModel(modelRef, opts);
533
- return new Engine(bundle, opts);
698
+ const eng = new Engine(undefined, opts);
699
+ await eng.open(modelRef);
700
+ return eng;
534
701
  }
535
702
  complete(messages, opts = {}) {
536
703
  const messagesJson = JSON.stringify(messages);
@@ -569,7 +736,7 @@ class Engine {
569
736
  return buf.toString("utf8").replace(/\0+$/, "");
570
737
  }
571
738
  close() {
572
- if (this.handle)
739
+ if (this.handle && this.fnDestroy)
573
740
  this.fnDestroy(this.handle);
574
741
  this.handle = null;
575
742
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ariacompute/engine-ts",
3
- "version": "1.15.0",
3
+ "version": "1.16.0",
4
4
  "description": "TypeScript/Node SDK for Aria Engine",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",