@iicp/client 0.5.7 → 0.6.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/dist/availability.d.ts +30 -0
- package/dist/availability.d.ts.map +1 -0
- package/dist/availability.js +64 -0
- package/dist/availability.js.map +1 -0
- package/dist/backends/base.d.ts +35 -0
- package/dist/backends/base.d.ts.map +1 -0
- package/dist/backends/base.js +97 -0
- package/dist/backends/base.js.map +1 -0
- package/dist/backends/index.d.ts +13 -0
- package/dist/backends/index.d.ts.map +1 -0
- package/dist/backends/index.js +30 -0
- package/dist/backends/index.js.map +1 -0
- package/dist/backends/llamacpp.d.ts +18 -0
- package/dist/backends/llamacpp.d.ts.map +1 -0
- package/dist/backends/llamacpp.js +17 -0
- package/dist/backends/llamacpp.js.map +1 -0
- package/dist/backends/openai_compat.d.ts +6 -10
- package/dist/backends/openai_compat.d.ts.map +1 -1
- package/dist/backends/openai_compat.js +5 -78
- package/dist/backends/openai_compat.js.map +1 -1
- package/dist/backends/vllm.d.ts +19 -0
- package/dist/backends/vllm.d.ts.map +1 -0
- package/dist/backends/vllm.js +17 -0
- package/dist/backends/vllm.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +10 -2
- package/dist/cli.js.map +1 -1
- package/dist/idempotency.d.ts +17 -0
- package/dist/idempotency.d.ts.map +1 -0
- package/dist/idempotency.js +39 -0
- package/dist/idempotency.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -1
- package/dist/index.js.map +1 -1
- package/dist/nat_detection.d.ts +4 -0
- package/dist/nat_detection.d.ts.map +1 -1
- package/dist/nat_detection.js +19 -0
- package/dist/nat_detection.js.map +1 -1
- package/dist/node.d.ts +35 -1
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +267 -59
- package/dist/node.js.map +1 -1
- package/dist/otel_tracer.d.ts +26 -0
- package/dist/otel_tracer.d.ts.map +1 -0
- package/dist/otel_tracer.js +96 -0
- package/dist/otel_tracer.js.map +1 -0
- package/dist/peer_manager.d.ts +37 -0
- package/dist/peer_manager.d.ts.map +1 -0
- package/dist/peer_manager.js +135 -0
- package/dist/peer_manager.js.map +1 -0
- package/dist/scheduler.d.ts +23 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +42 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/token_validator.d.ts +15 -0
- package/dist/token_validator.d.ts.map +1 -0
- package/dist/token_validator.js +34 -0
- package/dist/token_validator.js.map +1 -0
- package/dist/trust_auditor.d.ts +34 -0
- package/dist/trust_auditor.d.ts.map +1 -0
- package/dist/trust_auditor.js +123 -0
- package/dist/trust_auditor.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Time-based availability windows — operator capacity shaping by time-of-day.
|
|
3
|
+
*
|
|
4
|
+
* Port of iicp-adapter `scheduling/availability.py` (parity Block D, #340). Lets an
|
|
5
|
+
* operator dedicate different fractions of `maxConcurrent` at different times.
|
|
6
|
+
*
|
|
7
|
+
* - start/end: "HH:MM" in local time.
|
|
8
|
+
* - share: fraction of maxConcurrent (0.0 = closed, 1.0 = full).
|
|
9
|
+
* - Outside all windows: 0.5 (available but not primary).
|
|
10
|
+
* - No windows: always 1.0.
|
|
11
|
+
*
|
|
12
|
+
* The directory learns live load via heartbeats and scores accordingly (ADR-001) — it
|
|
13
|
+
* doesn't push scheduling to nodes.
|
|
14
|
+
*/
|
|
15
|
+
export interface Window {
|
|
16
|
+
start: string;
|
|
17
|
+
end: string;
|
|
18
|
+
share: number;
|
|
19
|
+
}
|
|
20
|
+
export declare class AvailabilityEvaluator {
|
|
21
|
+
private readonly windows;
|
|
22
|
+
constructor(windows?: Window[] | null);
|
|
23
|
+
/** Capacity share [0,1] for the current local time-of-day. */
|
|
24
|
+
currentShare(now?: Date): number;
|
|
25
|
+
/** Scale base maxConcurrent by the current share (floor 1 when share > 0).
|
|
26
|
+
* A base of 0 (operator explicitly disabled) stays 0. */
|
|
27
|
+
effectiveMaxConcurrent(baseMax: number, now?: Date): number;
|
|
28
|
+
isWithinWindow(now?: Date): boolean;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=availability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"availability.d.ts","sourceRoot":"","sources":["../src/availability.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,MAAM;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAQD,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAW;gBAEvB,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI;IAIrC,8DAA8D;IAC9D,YAAY,CAAC,GAAG,GAAE,IAAiB,GAAG,MAAM;IAc5C;6DACyD;IACzD,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,GAAE,IAAiB,GAAG,MAAM;IAOvE,cAAc,CAAC,GAAG,GAAE,IAAiB,GAAG,OAAO;CAIhD"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Time-based availability windows — operator capacity shaping by time-of-day.
|
|
5
|
+
*
|
|
6
|
+
* Port of iicp-adapter `scheduling/availability.py` (parity Block D, #340). Lets an
|
|
7
|
+
* operator dedicate different fractions of `maxConcurrent` at different times.
|
|
8
|
+
*
|
|
9
|
+
* - start/end: "HH:MM" in local time.
|
|
10
|
+
* - share: fraction of maxConcurrent (0.0 = closed, 1.0 = full).
|
|
11
|
+
* - Outside all windows: 0.5 (available but not primary).
|
|
12
|
+
* - No windows: always 1.0.
|
|
13
|
+
*
|
|
14
|
+
* The directory learns live load via heartbeats and scores accordingly (ADR-001) — it
|
|
15
|
+
* doesn't push scheduling to nodes.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.AvailabilityEvaluator = void 0;
|
|
19
|
+
function hhmm(d) {
|
|
20
|
+
const h = String(d.getHours()).padStart(2, "0");
|
|
21
|
+
const m = String(d.getMinutes()).padStart(2, "0");
|
|
22
|
+
return `${h}:${m}`;
|
|
23
|
+
}
|
|
24
|
+
class AvailabilityEvaluator {
|
|
25
|
+
windows;
|
|
26
|
+
constructor(windows) {
|
|
27
|
+
this.windows = windows ?? [];
|
|
28
|
+
}
|
|
29
|
+
/** Capacity share [0,1] for the current local time-of-day. */
|
|
30
|
+
currentShare(now = new Date()) {
|
|
31
|
+
if (this.windows.length === 0)
|
|
32
|
+
return 1.0;
|
|
33
|
+
const current = hhmm(now);
|
|
34
|
+
for (const w of this.windows) {
|
|
35
|
+
if (w.start <= w.end) {
|
|
36
|
+
if (w.start <= current && current <= w.end)
|
|
37
|
+
return w.share;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
// Midnight-spanning window (e.g. 22:00–06:00)
|
|
41
|
+
if (current >= w.start || current <= w.end)
|
|
42
|
+
return w.share;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return 0.5; // outside all windows
|
|
46
|
+
}
|
|
47
|
+
/** Scale base maxConcurrent by the current share (floor 1 when share > 0).
|
|
48
|
+
* A base of 0 (operator explicitly disabled) stays 0. */
|
|
49
|
+
effectiveMaxConcurrent(baseMax, now = new Date()) {
|
|
50
|
+
if (baseMax <= 0)
|
|
51
|
+
return 0;
|
|
52
|
+
const share = this.currentShare(now);
|
|
53
|
+
if (share <= 0.0)
|
|
54
|
+
return 0;
|
|
55
|
+
return Math.max(1, Math.floor(baseMax * share));
|
|
56
|
+
}
|
|
57
|
+
isWithinWindow(now = new Date()) {
|
|
58
|
+
if (this.windows.length === 0)
|
|
59
|
+
return true;
|
|
60
|
+
return this.currentShare(now) > 0.0;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.AvailabilityEvaluator = AvailabilityEvaluator;
|
|
64
|
+
//# sourceMappingURL=availability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"availability.js","sourceRoot":"","sources":["../src/availability.ts"],"names":[],"mappings":";AAAA,sCAAsC;AACtC;;;;;;;;;;;;;GAaG;;;AAQH,SAAS,IAAI,CAAC,CAAO;IACnB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAChD,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAClD,OAAO,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;AACrB,CAAC;AAED,MAAa,qBAAqB;IACf,OAAO,CAAW;IAEnC,YAAY,OAAyB;QACnC,IAAI,CAAC,OAAO,GAAG,OAAO,IAAI,EAAE,CAAC;IAC/B,CAAC;IAED,8DAA8D;IAC9D,YAAY,CAAC,MAAY,IAAI,IAAI,EAAE;QACjC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,GAAG,CAAC;QAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC7B,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC;gBACrB,IAAI,CAAC,CAAC,KAAK,IAAI,OAAO,IAAI,OAAO,IAAI,CAAC,CAAC,GAAG;oBAAE,OAAO,CAAC,CAAC,KAAK,CAAC;YAC7D,CAAC;iBAAM,CAAC;gBACN,8CAA8C;gBAC9C,IAAI,OAAO,IAAI,CAAC,CAAC,KAAK,IAAI,OAAO,IAAI,CAAC,CAAC,GAAG;oBAAE,OAAO,CAAC,CAAC,KAAK,CAAC;YAC7D,CAAC;QACH,CAAC;QACD,OAAO,GAAG,CAAC,CAAC,sBAAsB;IACpC,CAAC;IAED;6DACyD;IACzD,sBAAsB,CAAC,OAAe,EAAE,MAAY,IAAI,IAAI,EAAE;QAC5D,IAAI,OAAO,IAAI,CAAC;YAAE,OAAO,CAAC,CAAC;QAC3B,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,KAAK,IAAI,GAAG;YAAE,OAAO,CAAC,CAAC;QAC3B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,cAAc,CAAC,MAAY,IAAI,IAAI,EAAE;QACnC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAC3C,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;IACtC,CAAC;CACF;AAnCD,sDAmCC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared core for OpenAI-dialect backend handlers.
|
|
3
|
+
*
|
|
4
|
+
* vLLM, llama.cpp, LM Studio and Ollama all speak the OpenAI `/v1/*` HTTP dialect, so
|
|
5
|
+
* the request/response plumbing is identical — only the default port and the engine
|
|
6
|
+
* label in error messages differ. This module hosts that shared plumbing so the
|
|
7
|
+
* per-engine modules (openai_compat, vllm, llamacpp) stay thin.
|
|
8
|
+
*
|
|
9
|
+
* Port of iicp-adapter backends/{base,vllm,llamacpp,openai_compat} into the SDK's
|
|
10
|
+
* handler-factory style (tracker iicp.network#340; parity Block B).
|
|
11
|
+
*/
|
|
12
|
+
export declare const INTENT_TO_PATH: Record<string, string>;
|
|
13
|
+
export interface BackendOptions {
|
|
14
|
+
/** Provider HTTP root (no trailing slash needed). */
|
|
15
|
+
baseUrl?: string;
|
|
16
|
+
/** Default model name. If unset, the task payload MUST include `model`. */
|
|
17
|
+
model?: string;
|
|
18
|
+
/** Bearer token for the provider. Empty for local Ollama/vLLM. */
|
|
19
|
+
apiKey?: string;
|
|
20
|
+
/** Per-request HTTP timeout in milliseconds. Default 30000. */
|
|
21
|
+
timeoutMs?: number;
|
|
22
|
+
}
|
|
23
|
+
export type TaskHandlerInput = {
|
|
24
|
+
task_id?: string;
|
|
25
|
+
intent?: string;
|
|
26
|
+
payload?: Record<string, unknown>;
|
|
27
|
+
};
|
|
28
|
+
export type TaskHandlerOutput = Record<string, unknown>;
|
|
29
|
+
export type BackendHandler = (task: TaskHandlerInput) => Promise<TaskHandlerOutput>;
|
|
30
|
+
/**
|
|
31
|
+
* Build a TaskHandler that proxies CALLs to an OpenAI-dialect server. `engine` is the
|
|
32
|
+
* label used in error messages (e.g. "vllm"); all engines share this body.
|
|
33
|
+
*/
|
|
34
|
+
export declare function buildOpenAiDialectHandler(engine: string, baseUrlRaw: string, model: string | undefined, apiKey: string, timeoutMs: number): BackendHandler;
|
|
35
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/backends/base.ts"],"names":[],"mappings":"AACA;;;;;;;;;;GAUG;AAEH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAIjD,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAExD,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,gBAAgB,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAEpF;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,cAAc,CA+EhB"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Shared core for OpenAI-dialect backend handlers.
|
|
5
|
+
*
|
|
6
|
+
* vLLM, llama.cpp, LM Studio and Ollama all speak the OpenAI `/v1/*` HTTP dialect, so
|
|
7
|
+
* the request/response plumbing is identical — only the default port and the engine
|
|
8
|
+
* label in error messages differ. This module hosts that shared plumbing so the
|
|
9
|
+
* per-engine modules (openai_compat, vllm, llamacpp) stay thin.
|
|
10
|
+
*
|
|
11
|
+
* Port of iicp-adapter backends/{base,vllm,llamacpp,openai_compat} into the SDK's
|
|
12
|
+
* handler-factory style (tracker iicp.network#340; parity Block B).
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.INTENT_TO_PATH = void 0;
|
|
16
|
+
exports.buildOpenAiDialectHandler = buildOpenAiDialectHandler;
|
|
17
|
+
exports.INTENT_TO_PATH = {
|
|
18
|
+
"urn:iicp:intent:llm:chat:v1": "/chat/completions",
|
|
19
|
+
"urn:iicp:intent:llm:completion:v1": "/completions",
|
|
20
|
+
"urn:iicp:intent:llm:embedding:v1": "/embeddings",
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Build a TaskHandler that proxies CALLs to an OpenAI-dialect server. `engine` is the
|
|
24
|
+
* label used in error messages (e.g. "vllm"); all engines share this body.
|
|
25
|
+
*/
|
|
26
|
+
function buildOpenAiDialectHandler(engine, baseUrlRaw, model, apiKey, timeoutMs) {
|
|
27
|
+
const baseUrl = baseUrlRaw.replace(/\/$/, "");
|
|
28
|
+
return async function handler(task) {
|
|
29
|
+
const intent = String(task.intent ?? "");
|
|
30
|
+
const payload = task.payload;
|
|
31
|
+
if (payload !== undefined &&
|
|
32
|
+
payload !== null &&
|
|
33
|
+
(typeof payload !== "object" || Array.isArray(payload))) {
|
|
34
|
+
return {
|
|
35
|
+
error_code: 400,
|
|
36
|
+
error_message: `${engine}: task.payload must be a dict, got ${typeof payload}`,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
const path = exports.INTENT_TO_PATH[intent];
|
|
40
|
+
if (!path) {
|
|
41
|
+
return {
|
|
42
|
+
error_code: 400,
|
|
43
|
+
error_message: `${engine}: unsupported intent ${JSON.stringify(intent)}; supported: ${JSON.stringify(Object.keys(exports.INTENT_TO_PATH).sort())}`,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const body = { ...(payload ?? {}) };
|
|
47
|
+
if (body.model === undefined && model !== undefined)
|
|
48
|
+
body.model = model;
|
|
49
|
+
if (!body.model) {
|
|
50
|
+
return {
|
|
51
|
+
error_code: 400,
|
|
52
|
+
error_message: `${engine}: no model — either pass \`model\` to the backend factory ` +
|
|
53
|
+
"or include `model` in the task payload",
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const headers = { "Content-Type": "application/json" };
|
|
57
|
+
if (apiKey)
|
|
58
|
+
headers["Authorization"] = `Bearer ${apiKey}`;
|
|
59
|
+
const ctrl = new AbortController();
|
|
60
|
+
const t = setTimeout(() => ctrl.abort(), timeoutMs);
|
|
61
|
+
let resp;
|
|
62
|
+
try {
|
|
63
|
+
resp = await fetch(`${baseUrl}${path}`, {
|
|
64
|
+
method: "POST",
|
|
65
|
+
headers,
|
|
66
|
+
body: JSON.stringify(body),
|
|
67
|
+
signal: ctrl.signal,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
catch (exc) {
|
|
71
|
+
clearTimeout(t);
|
|
72
|
+
const msg = exc instanceof Error ? exc.message : String(exc);
|
|
73
|
+
if (ctrl.signal.aborted) {
|
|
74
|
+
return { error_code: 408, error_message: `${engine}: backend timed out` };
|
|
75
|
+
}
|
|
76
|
+
return { error_code: 502, error_message: `${engine}: HTTP transport error: ${msg}` };
|
|
77
|
+
}
|
|
78
|
+
clearTimeout(t);
|
|
79
|
+
if (!resp.ok) {
|
|
80
|
+
const text = await resp.text().catch(() => "");
|
|
81
|
+
return {
|
|
82
|
+
error_code: resp.status,
|
|
83
|
+
error_message: `${engine}: upstream ${resp.status}: ${text.slice(0, 512)}`,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
let data;
|
|
87
|
+
try {
|
|
88
|
+
data = await resp.json();
|
|
89
|
+
}
|
|
90
|
+
catch (exc) {
|
|
91
|
+
const msg = exc instanceof Error ? exc.message : String(exc);
|
|
92
|
+
return { error_code: 502, error_message: `${engine}: upstream returned non-JSON: ${msg}` };
|
|
93
|
+
}
|
|
94
|
+
return { result: data };
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/backends/base.ts"],"names":[],"mappings":";AAAA,sCAAsC;AACtC;;;;;;;;;;GAUG;;;AAiCH,8DAqFC;AApHY,QAAA,cAAc,GAA2B;IACpD,6BAA6B,EAAE,mBAAmB;IAClD,mCAAmC,EAAE,cAAc;IACnD,kCAAkC,EAAE,aAAa;CAClD,CAAC;AAuBF;;;GAGG;AACH,SAAgB,yBAAyB,CACvC,MAAc,EACd,UAAkB,EAClB,KAAyB,EACzB,MAAc,EACd,SAAiB;IAEjB,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAE9C,OAAO,KAAK,UAAU,OAAO,CAAC,IAAsB;QAClD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;QACzC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC7B,IACE,OAAO,KAAK,SAAS;YACrB,OAAO,KAAK,IAAI;YAChB,CAAC,OAAO,OAAO,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,EACvD,CAAC;YACD,OAAO;gBACL,UAAU,EAAE,GAAG;gBACf,aAAa,EAAE,GAAG,MAAM,sCAAsC,OAAO,OAAO,EAAE;aAC/E,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,sBAAc,CAAC,MAAM,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;gBACL,UAAU,EAAE,GAAG;gBACf,aAAa,EAAE,GAAG,MAAM,wBAAwB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,gBAAgB,IAAI,CAAC,SAAS,CAClG,MAAM,CAAC,IAAI,CAAC,sBAAc,CAAC,CAAC,IAAI,EAAE,CACnC,EAAE;aACJ,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAA4B,EAAE,GAAG,CAAE,OAAmC,IAAI,EAAE,CAAC,EAAE,CAAC;QAC1F,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS;YAAE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACxE,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAChB,OAAO;gBACL,UAAU,EAAE,GAAG;gBACf,aAAa,EACX,GAAG,MAAM,4DAA4D;oBACrE,wCAAwC;aAC3C,CAAC;QACJ,CAAC;QAED,MAAM,OAAO,GAA2B,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC;QAC/E,IAAI,MAAM;YAAE,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,MAAM,EAAE,CAAC;QAE1D,MAAM,IAAI,GAAG,IAAI,eAAe,EAAE,CAAC;QACnC,MAAM,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAC;QACpD,IAAI,IAAc,CAAC;QACnB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,GAAG,IAAI,EAAE,EAAE;gBACtC,MAAM,EAAE,MAAM;gBACd,OAAO;gBACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;gBAC1B,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,YAAY,CAAC,CAAC,CAAC,CAAC;YAChB,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7D,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACxB,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,aAAa,EAAE,GAAG,MAAM,qBAAqB,EAAE,CAAC;YAC5E,CAAC;YACD,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,aAAa,EAAE,GAAG,MAAM,2BAA2B,GAAG,EAAE,EAAE,CAAC;QACvF,CAAC;QACD,YAAY,CAAC,CAAC,CAAC,CAAC;QAEhB,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC/C,OAAO;gBACL,UAAU,EAAE,IAAI,CAAC,MAAM;gBACvB,aAAa,EAAE,GAAG,MAAM,cAAc,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;aAC3E,CAAC;QACJ,CAAC;QAED,IAAI,IAAa,CAAC;QAClB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAC3B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7D,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,aAAa,EAAE,GAAG,MAAM,iCAAiC,GAAG,EAAE,EAAE,CAAC;QAC7F,CAAC;QAED,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAC1B,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Backend handler registry + selector.
|
|
3
|
+
*
|
|
4
|
+
* Each helper returns a TaskHandler suitable for IicpNode.serve() or IicpTcpServer.
|
|
5
|
+
* Use `getBackendHandler(type, opts)` to select one by name (e.g. from a CLI
|
|
6
|
+
* `--backend-type` flag).
|
|
7
|
+
*/
|
|
8
|
+
import { type BackendHandler, type BackendOptions } from "./base.js";
|
|
9
|
+
export declare const BACKEND_TYPES: readonly ["openai_compat", "vllm", "llamacpp"];
|
|
10
|
+
export type BackendType = (typeof BACKEND_TYPES)[number];
|
|
11
|
+
/** Return a backend handler by name. Throws on an unknown type. */
|
|
12
|
+
export declare function getBackendHandler(backendType: string, opts?: BackendOptions): BackendHandler;
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/backends/index.ts"],"names":[],"mappings":"AACA;;;;;;GAMG;AAEH,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAKrE,eAAO,MAAM,aAAa,gDAAiD,CAAC;AAC5E,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAQzD,mEAAmE;AACnE,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,GAAE,cAAmB,GAAG,cAAc,CAQhG"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Backend handler registry + selector.
|
|
5
|
+
*
|
|
6
|
+
* Each helper returns a TaskHandler suitable for IicpNode.serve() or IicpTcpServer.
|
|
7
|
+
* Use `getBackendHandler(type, opts)` to select one by name (e.g. from a CLI
|
|
8
|
+
* `--backend-type` flag).
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.BACKEND_TYPES = void 0;
|
|
12
|
+
exports.getBackendHandler = getBackendHandler;
|
|
13
|
+
const openai_compat_js_1 = require("./openai_compat.js");
|
|
14
|
+
const vllm_js_1 = require("./vllm.js");
|
|
15
|
+
const llamacpp_js_1 = require("./llamacpp.js");
|
|
16
|
+
exports.BACKEND_TYPES = ["openai_compat", "vllm", "llamacpp"];
|
|
17
|
+
const FACTORIES = {
|
|
18
|
+
openai_compat: openai_compat_js_1.openaiCompatHandler,
|
|
19
|
+
vllm: vllm_js_1.vllmHandler,
|
|
20
|
+
llamacpp: llamacpp_js_1.llamacppHandler,
|
|
21
|
+
};
|
|
22
|
+
/** Return a backend handler by name. Throws on an unknown type. */
|
|
23
|
+
function getBackendHandler(backendType, opts = {}) {
|
|
24
|
+
const factory = FACTORIES[backendType];
|
|
25
|
+
if (!factory) {
|
|
26
|
+
throw new Error(`unknown backend_type ${JSON.stringify(backendType)}; choose one of ${JSON.stringify(exports.BACKEND_TYPES)}`);
|
|
27
|
+
}
|
|
28
|
+
return factory(opts);
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/backends/index.ts"],"names":[],"mappings":";AAAA,sCAAsC;AACtC;;;;;;GAMG;;;AAiBH,8CAQC;AAtBD,yDAAyD;AACzD,uCAAwC;AACxC,+CAAgD;AAEnC,QAAA,aAAa,GAAG,CAAC,eAAe,EAAE,MAAM,EAAE,UAAU,CAAU,CAAC;AAG5E,MAAM,SAAS,GAAkE;IAC/E,aAAa,EAAE,sCAAmB;IAClC,IAAI,EAAE,qBAAW;IACjB,QAAQ,EAAE,6BAAe;CAC1B,CAAC;AAEF,mEAAmE;AACnE,SAAgB,iBAAiB,CAAC,WAAmB,EAAE,OAAuB,EAAE;IAC9E,MAAM,OAAO,GAAG,SAAS,CAAC,WAA0B,CAAC,CAAC;IACtD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,wBAAwB,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,mBAAmB,IAAI,CAAC,SAAS,CAAC,qBAAa,CAAC,EAAE,CACtG,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* llama.cpp backend handler.
|
|
3
|
+
*
|
|
4
|
+
* The `llama-server` binary exposes an OpenAI-compatible `/v1/*` API, so this is a thin
|
|
5
|
+
* factory over the shared core with llama.cpp's default port (8080). Kept as a dedicated
|
|
6
|
+
* module so operators can select `backendType=llamacpp` explicitly. Port of iicp-adapter
|
|
7
|
+
* backends/llamacpp.py (parity Block B).
|
|
8
|
+
*/
|
|
9
|
+
import { type BackendHandler } from "./base.js";
|
|
10
|
+
export interface LlamaCppOptions {
|
|
11
|
+
/** Provider HTTP root. Default: llama.cpp `http://localhost:8080/v1`. */
|
|
12
|
+
baseUrl?: string;
|
|
13
|
+
model?: string;
|
|
14
|
+
apiKey?: string;
|
|
15
|
+
timeoutMs?: number;
|
|
16
|
+
}
|
|
17
|
+
export declare function llamacppHandler(opts?: LlamaCppOptions): BackendHandler;
|
|
18
|
+
//# sourceMappingURL=llamacpp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llamacpp.d.ts","sourceRoot":"","sources":["../../src/backends/llamacpp.ts"],"names":[],"mappings":"AACA;;;;;;;GAOG;AAEH,OAAO,EAA6B,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3E,MAAM,WAAW,eAAe;IAC9B,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,eAAe,CAAC,IAAI,GAAE,eAAoB,GAAG,cAAc,CAQ1E"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* llama.cpp backend handler.
|
|
5
|
+
*
|
|
6
|
+
* The `llama-server` binary exposes an OpenAI-compatible `/v1/*` API, so this is a thin
|
|
7
|
+
* factory over the shared core with llama.cpp's default port (8080). Kept as a dedicated
|
|
8
|
+
* module so operators can select `backendType=llamacpp` explicitly. Port of iicp-adapter
|
|
9
|
+
* backends/llamacpp.py (parity Block B).
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.llamacppHandler = llamacppHandler;
|
|
13
|
+
const base_js_1 = require("./base.js");
|
|
14
|
+
function llamacppHandler(opts = {}) {
|
|
15
|
+
return (0, base_js_1.buildOpenAiDialectHandler)("llamacpp", opts.baseUrl ?? "http://localhost:8080/v1", opts.model, opts.apiKey ?? "", opts.timeoutMs ?? 30000);
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=llamacpp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llamacpp.js","sourceRoot":"","sources":["../../src/backends/llamacpp.ts"],"names":[],"mappings":";AAAA,sCAAsC;AACtC;;;;;;;GAOG;;AAYH,0CAQC;AAlBD,uCAA2E;AAU3E,SAAgB,eAAe,CAAC,OAAwB,EAAE;IACxD,OAAO,IAAA,mCAAyB,EAC9B,UAAU,EACV,IAAI,CAAC,OAAO,IAAI,0BAA0B,EAC1C,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,MAAM,IAAI,EAAE,EACjB,IAAI,CAAC,SAAS,IAAI,KAAK,CACxB,CAAC;AACJ,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* OpenAI-compatible backend helper (Ollama /
|
|
2
|
+
* OpenAI-compatible backend helper (Ollama / LM Studio / OpenAI / ...).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Thin factory over the shared `buildOpenAiDialectHandler` core. Returns a TaskHandler
|
|
5
|
+
* suitable for IicpNode.serve() AND IicpTcpServer.
|
|
6
6
|
*
|
|
7
7
|
* import { openaiCompatHandler } from "@iicp/client";
|
|
8
8
|
*
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
* urn:iicp:intent:llm:completion:v1 → /completions
|
|
19
19
|
* urn:iicp:intent:llm:embedding:v1 → /embeddings
|
|
20
20
|
*/
|
|
21
|
+
import { type BackendHandler, type TaskHandlerInput, type TaskHandlerOutput } from "./base.js";
|
|
21
22
|
export interface OpenAiCompatOptions {
|
|
22
23
|
/** Provider HTTP root (no trailing slash needed). Default: Ollama `http://localhost:11434/v1`. */
|
|
23
24
|
baseUrl?: string;
|
|
@@ -28,11 +29,6 @@ export interface OpenAiCompatOptions {
|
|
|
28
29
|
/** Per-request HTTP timeout in milliseconds. Default 30000. */
|
|
29
30
|
timeoutMs?: number;
|
|
30
31
|
}
|
|
31
|
-
export type TaskHandlerInput
|
|
32
|
-
|
|
33
|
-
intent?: string;
|
|
34
|
-
payload?: Record<string, unknown>;
|
|
35
|
-
};
|
|
36
|
-
export type TaskHandlerOutput = Record<string, unknown>;
|
|
37
|
-
export declare function openaiCompatHandler(opts?: OpenAiCompatOptions): (task: TaskHandlerInput) => Promise<TaskHandlerOutput>;
|
|
32
|
+
export type { TaskHandlerInput, TaskHandlerOutput };
|
|
33
|
+
export declare function openaiCompatHandler(opts?: OpenAiCompatOptions): BackendHandler;
|
|
38
34
|
//# sourceMappingURL=openai_compat.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai_compat.d.ts","sourceRoot":"","sources":["../../src/backends/openai_compat.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;GAmBG;
|
|
1
|
+
{"version":3,"file":"openai_compat.d.ts","sourceRoot":"","sources":["../../src/backends/openai_compat.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACvB,MAAM,WAAW,CAAC;AAEnB,MAAM,WAAW,mBAAmB;IAClC,kGAAkG;IAClG,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,CAAC;AAEpD,wBAAgB,mBAAmB,CAAC,IAAI,GAAE,mBAAwB,GAAG,cAAc,CAQlF"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
/**
|
|
4
|
-
* OpenAI-compatible backend helper (Ollama /
|
|
4
|
+
* OpenAI-compatible backend helper (Ollama / LM Studio / OpenAI / ...).
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* Thin factory over the shared `buildOpenAiDialectHandler` core. Returns a TaskHandler
|
|
7
|
+
* suitable for IicpNode.serve() AND IicpTcpServer.
|
|
8
8
|
*
|
|
9
9
|
* import { openaiCompatHandler } from "@iicp/client";
|
|
10
10
|
*
|
|
@@ -22,81 +22,8 @@
|
|
|
22
22
|
*/
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
24
|
exports.openaiCompatHandler = openaiCompatHandler;
|
|
25
|
-
const
|
|
26
|
-
"urn:iicp:intent:llm:chat:v1": "/chat/completions",
|
|
27
|
-
"urn:iicp:intent:llm:completion:v1": "/completions",
|
|
28
|
-
"urn:iicp:intent:llm:embedding:v1": "/embeddings",
|
|
29
|
-
};
|
|
25
|
+
const base_js_1 = require("./base.js");
|
|
30
26
|
function openaiCompatHandler(opts = {}) {
|
|
31
|
-
|
|
32
|
-
const model = opts.model;
|
|
33
|
-
const apiKey = opts.apiKey ?? "";
|
|
34
|
-
const timeoutMs = opts.timeoutMs ?? 30000;
|
|
35
|
-
return async function handler(task) {
|
|
36
|
-
const intent = String(task.intent ?? "");
|
|
37
|
-
const payload = task.payload;
|
|
38
|
-
if (payload !== undefined && payload !== null && (typeof payload !== "object" || Array.isArray(payload))) {
|
|
39
|
-
return {
|
|
40
|
-
error_code: 400,
|
|
41
|
-
error_message: `openai_compat: task.payload must be a dict, got ${typeof payload}`,
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
const path = INTENT_TO_PATH[intent];
|
|
45
|
-
if (!path) {
|
|
46
|
-
return {
|
|
47
|
-
error_code: 400,
|
|
48
|
-
error_message: `openai_compat: unsupported intent ${JSON.stringify(intent)}; supported: ${JSON.stringify(Object.keys(INTENT_TO_PATH).sort())}`,
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
const body = { ...(payload ?? {}) };
|
|
52
|
-
if (body.model === undefined && model !== undefined)
|
|
53
|
-
body.model = model;
|
|
54
|
-
if (!body.model) {
|
|
55
|
-
return {
|
|
56
|
-
error_code: 400,
|
|
57
|
-
error_message: "openai_compat: no model — either pass `model` to openaiCompatHandler(...) " +
|
|
58
|
-
"or include `model` in the task payload",
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
const headers = { "Content-Type": "application/json" };
|
|
62
|
-
if (apiKey)
|
|
63
|
-
headers["Authorization"] = `Bearer ${apiKey}`;
|
|
64
|
-
const ctrl = new AbortController();
|
|
65
|
-
const t = setTimeout(() => ctrl.abort(), timeoutMs);
|
|
66
|
-
let resp;
|
|
67
|
-
try {
|
|
68
|
-
resp = await fetch(`${baseUrl}${path}`, {
|
|
69
|
-
method: "POST",
|
|
70
|
-
headers,
|
|
71
|
-
body: JSON.stringify(body),
|
|
72
|
-
signal: ctrl.signal,
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
catch (exc) {
|
|
76
|
-
clearTimeout(t);
|
|
77
|
-
const msg = exc instanceof Error ? exc.message : String(exc);
|
|
78
|
-
if (ctrl.signal.aborted) {
|
|
79
|
-
return { error_code: 408, error_message: "openai_compat: backend timed out" };
|
|
80
|
-
}
|
|
81
|
-
return { error_code: 502, error_message: `openai_compat: HTTP transport error: ${msg}` };
|
|
82
|
-
}
|
|
83
|
-
clearTimeout(t);
|
|
84
|
-
if (!resp.ok) {
|
|
85
|
-
const text = await resp.text().catch(() => "");
|
|
86
|
-
return {
|
|
87
|
-
error_code: resp.status,
|
|
88
|
-
error_message: `openai_compat: upstream ${resp.status}: ${text.slice(0, 512)}`,
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
let data;
|
|
92
|
-
try {
|
|
93
|
-
data = await resp.json();
|
|
94
|
-
}
|
|
95
|
-
catch (exc) {
|
|
96
|
-
const msg = exc instanceof Error ? exc.message : String(exc);
|
|
97
|
-
return { error_code: 502, error_message: `openai_compat: upstream returned non-JSON: ${msg}` };
|
|
98
|
-
}
|
|
99
|
-
return { result: data };
|
|
100
|
-
};
|
|
27
|
+
return (0, base_js_1.buildOpenAiDialectHandler)("openai_compat", opts.baseUrl ?? "http://localhost:11434/v1", opts.model, opts.apiKey ?? "", opts.timeoutMs ?? 30000);
|
|
101
28
|
}
|
|
102
29
|
//# sourceMappingURL=openai_compat.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai_compat.js","sourceRoot":"","sources":["../../src/backends/openai_compat.ts"],"names":[],"mappings":";AAAA,sCAAsC;AACtC;;;;;;;;;;;;;;;;;;;GAmBG;;
|
|
1
|
+
{"version":3,"file":"openai_compat.js","sourceRoot":"","sources":["../../src/backends/openai_compat.ts"],"names":[],"mappings":";AAAA,sCAAsC;AACtC;;;;;;;;;;;;;;;;;;;GAmBG;;AAsBH,kDAQC;AA5BD,uCAKmB;AAenB,SAAgB,mBAAmB,CAAC,OAA4B,EAAE;IAChE,OAAO,IAAA,mCAAyB,EAC9B,eAAe,EACf,IAAI,CAAC,OAAO,IAAI,2BAA2B,EAC3C,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,MAAM,IAAI,EAAE,EACjB,IAAI,CAAC,SAAS,IAAI,KAAK,CACxB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vLLM backend handler.
|
|
3
|
+
*
|
|
4
|
+
* vLLM's OpenAI server (`python -m vllm.entrypoints.openai.api_server`) speaks the
|
|
5
|
+
* standard `/v1/*` dialect, so this is a thin factory over the shared core with vLLM's
|
|
6
|
+
* default port (8000). Kept as a dedicated module so operators can select
|
|
7
|
+
* `backendType=vllm` explicitly. Port of iicp-adapter backends/vllm.py (parity Block B).
|
|
8
|
+
*/
|
|
9
|
+
import { type BackendHandler } from "./base.js";
|
|
10
|
+
export interface VllmOptions {
|
|
11
|
+
/** Provider HTTP root. Default: vLLM `http://localhost:8000/v1`. */
|
|
12
|
+
baseUrl?: string;
|
|
13
|
+
model?: string;
|
|
14
|
+
/** Optional — set only when vLLM was started with `--api-key`. */
|
|
15
|
+
apiKey?: string;
|
|
16
|
+
timeoutMs?: number;
|
|
17
|
+
}
|
|
18
|
+
export declare function vllmHandler(opts?: VllmOptions): BackendHandler;
|
|
19
|
+
//# sourceMappingURL=vllm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vllm.d.ts","sourceRoot":"","sources":["../../src/backends/vllm.ts"],"names":[],"mappings":"AACA;;;;;;;GAOG;AAEH,OAAO,EAA6B,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3E,MAAM,WAAW,WAAW;IAC1B,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,WAAW,CAAC,IAAI,GAAE,WAAgB,GAAG,cAAc,CAQlE"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* vLLM backend handler.
|
|
5
|
+
*
|
|
6
|
+
* vLLM's OpenAI server (`python -m vllm.entrypoints.openai.api_server`) speaks the
|
|
7
|
+
* standard `/v1/*` dialect, so this is a thin factory over the shared core with vLLM's
|
|
8
|
+
* default port (8000). Kept as a dedicated module so operators can select
|
|
9
|
+
* `backendType=vllm` explicitly. Port of iicp-adapter backends/vllm.py (parity Block B).
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.vllmHandler = vllmHandler;
|
|
13
|
+
const base_js_1 = require("./base.js");
|
|
14
|
+
function vllmHandler(opts = {}) {
|
|
15
|
+
return (0, base_js_1.buildOpenAiDialectHandler)("vllm", opts.baseUrl ?? "http://localhost:8000/v1", opts.model, opts.apiKey ?? "", opts.timeoutMs ?? 30000);
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=vllm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vllm.js","sourceRoot":"","sources":["../../src/backends/vllm.ts"],"names":[],"mappings":";AAAA,sCAAsC;AACtC;;;;;;;GAOG;;AAaH,kCAQC;AAnBD,uCAA2E;AAW3E,SAAgB,WAAW,CAAC,OAAoB,EAAE;IAChD,OAAO,IAAA,mCAAyB,EAC9B,MAAM,EACN,IAAI,CAAC,OAAO,IAAI,0BAA0B,EAC1C,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,MAAM,IAAI,EAAE,EACjB,IAAI,CAAC,SAAS,IAAI,KAAK,CACxB,CAAC;AACJ,CAAC"}
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAweA,wBAAsB,IAAI,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,CAyElF"}
|
package/dist/cli.js
CHANGED
|
@@ -26,7 +26,7 @@ const readline = require("node:readline/promises");
|
|
|
26
26
|
const node_process_1 = require("node:process");
|
|
27
27
|
const node_js_1 = require("./node.js");
|
|
28
28
|
const cip_policy_js_1 = require("./cip_policy.js");
|
|
29
|
-
const
|
|
29
|
+
const index_js_1 = require("./backends/index.js");
|
|
30
30
|
const identity_js_1 = require("./identity.js");
|
|
31
31
|
function envOr(name, fallback) {
|
|
32
32
|
const v = process.env[name];
|
|
@@ -57,6 +57,7 @@ function printHelp() {
|
|
|
57
57
|
` --model NAME IICP_BACKEND_MODEL — model name (e.g. qwen2.5:0.5b)\n` +
|
|
58
58
|
` (or --node NAME load both from ~/.iicp/nodes/<NAME>.json after \`iicp-node init\`)\n\n` +
|
|
59
59
|
`serve optional:\n` +
|
|
60
|
+
` --backend-type TYPE IICP_BACKEND_TYPE — openai_compat | vllm | llamacpp (default openai_compat)\n` +
|
|
60
61
|
` --public-endpoint URL IICP_PUBLIC_ENDPOINT — externally reachable URL of this node\n` +
|
|
61
62
|
` --directory-url URL IICP_DIRECTORY_URL (default https://iicp.network/api)\n` +
|
|
62
63
|
` --region REGION IICP_REGION (default eu-central)\n` +
|
|
@@ -283,6 +284,10 @@ async function runServe(opts) {
|
|
|
283
284
|
process.stderr.write("ERROR: --backend-url and --model are required (or IICP_BACKEND_URL / IICP_BACKEND_MODEL, or --node NAME).\n");
|
|
284
285
|
return 2;
|
|
285
286
|
}
|
|
287
|
+
if (!index_js_1.BACKEND_TYPES.includes(opts.backendType)) {
|
|
288
|
+
process.stderr.write(`ERROR: --backend-type must be one of ${JSON.stringify(index_js_1.BACKEND_TYPES)}.\n`);
|
|
289
|
+
return 2;
|
|
290
|
+
}
|
|
286
291
|
const nodeId = opts.nodeId ||
|
|
287
292
|
`sdk-${opts.model.replace(/:/g, "-")}-${(0, node_crypto_1.randomBytes)(4).toString("hex")}`;
|
|
288
293
|
let publicEndpoint = opts.publicEndpoint || `http://localhost:${opts.port}`;
|
|
@@ -355,7 +360,7 @@ async function runServe(opts) {
|
|
|
355
360
|
console.warn(`[iicp-node] NAT auto-detect failed: ${msg} — continuing with configured endpoint`);
|
|
356
361
|
}
|
|
357
362
|
}
|
|
358
|
-
const handler = (0,
|
|
363
|
+
const handler = (0, index_js_1.getBackendHandler)(opts.backendType, {
|
|
359
364
|
baseUrl: opts.backendUrl,
|
|
360
365
|
model: opts.model,
|
|
361
366
|
});
|
|
@@ -428,6 +433,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
428
433
|
options: {
|
|
429
434
|
node: { type: "string" },
|
|
430
435
|
"backend-url": { type: "string" },
|
|
436
|
+
"backend-type": { type: "string" },
|
|
431
437
|
model: { type: "string" },
|
|
432
438
|
"public-endpoint": { type: "string" },
|
|
433
439
|
"directory-url": { type: "string" },
|
|
@@ -451,6 +457,8 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
451
457
|
const opts = {
|
|
452
458
|
node: values.node ?? envOr("IICP_NODE_NAME") ?? "",
|
|
453
459
|
backendUrl: values["backend-url"] ?? envOr("IICP_BACKEND_URL") ?? "",
|
|
460
|
+
backendType: values["backend-type"] ??
|
|
461
|
+
envOr("IICP_BACKEND_TYPE", "openai_compat"),
|
|
454
462
|
model: values.model ?? envOr("IICP_BACKEND_MODEL") ?? "",
|
|
455
463
|
publicEndpoint: values["public-endpoint"] ?? envOr("IICP_PUBLIC_ENDPOINT") ?? "",
|
|
456
464
|
directoryUrl: values["directory-url"] ??
|