@iicp/client 0.7.64 → 0.7.65

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
@@ -18,11 +18,16 @@ urn:iicp:intent:llm:chat:v1 → discover → select → submit
18
18
  ## Install
19
19
 
20
20
  ```bash
21
- npm install @iicp/client
22
- # yarn add @iicp/client
23
- # pnpm add @iicp/client
21
+ npm install @iicp/client@latest
22
+ # yarn add @iicp/client@latest
23
+ # pnpm add @iicp/client@latest
24
24
  ```
25
25
 
26
+ > **Upgrade note (0.7.65)** — upgrade clients and nodes so discovery prefers the canonical
27
+ > IICP-CX `cx_public_key` field while still accepting the temporary `public_key` alias.
28
+ > This prevents keyed live nodes from being treated as plaintext-only during the migration
29
+ > and prepares your install for the later removal of the ambiguous alias.
30
+
26
31
  > **Upgrade note (0.5.3)** — if you operate a node and use the native IICP
27
32
  > TCP transport on port 9484, upgrade to `^0.5.3`. Releases 0.5.0–0.5.2
28
33
  > emitted a non-standard CBOR dialect that does not interoperate with the
@@ -0,0 +1,40 @@
1
+ /** Provider-local backend stability observer and drain guard (#553).
2
+ *
3
+ * Conservative by design: read-only probes only, coarse public output, no
4
+ * automatic model load/unload orchestration and no host-safety guarantee.
5
+ */
6
+ export type BackendState = "ok" | "degraded" | "draining";
7
+ export type BackendReason = "ok" | "backend_cold" | "backend_loading" | "backend_unstable" | "observer_error";
8
+ export interface BackendStabilityObservationInit {
9
+ backendState?: BackendState;
10
+ reasonClass?: BackendReason;
11
+ drainUntilMs?: number | null;
12
+ observedAtMs?: number;
13
+ diagnostics?: Record<string, unknown>;
14
+ }
15
+ export declare class BackendStabilityObservation {
16
+ backendState: BackendState;
17
+ reasonClass: BackendReason;
18
+ drainUntilMs: number | null;
19
+ observedAtMs: number;
20
+ diagnostics: Record<string, unknown>;
21
+ constructor(init?: BackendStabilityObservationInit);
22
+ retryAfterS(nowMs?: number): number | null;
23
+ isDraining(nowMs?: number): boolean;
24
+ publicDict(nowMs?: number): Record<string, unknown>;
25
+ }
26
+ export declare function parseOllamaPs(data: unknown, expectedModel?: string): BackendStabilityObservation;
27
+ export declare function parseLmStudioModels(data: unknown, expectedModel?: string, opts?: {
28
+ nowMs?: number;
29
+ loadingRetryS?: number;
30
+ unstableRetryS?: number;
31
+ }): BackendStabilityObservation;
32
+ export declare function observeBackendStability(opts: {
33
+ backendUrl: string;
34
+ backend?: string;
35
+ expectedModel?: string;
36
+ apiKey?: string;
37
+ timeoutMs?: number;
38
+ fetchImpl?: typeof fetch;
39
+ }): Promise<BackendStabilityObservation>;
40
+ //# sourceMappingURL=backend_stability.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend_stability.d.ts","sourceRoot":"","sources":["../src/backend_stability.ts"],"names":[],"mappings":"AACA;;;;GAIG;AAEH,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,UAAU,GAAG,UAAU,CAAC;AAC1D,MAAM,MAAM,aAAa,GAAG,IAAI,GAAG,cAAc,GAAG,iBAAiB,GAAG,kBAAkB,GAAG,gBAAgB,CAAC;AAE9G,MAAM,WAAW,+BAA+B;IAC9C,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,WAAW,CAAC,EAAE,aAAa,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AAED,qBAAa,2BAA2B;IACtC,YAAY,EAAE,YAAY,CAAC;IAC3B,WAAW,EAAE,aAAa,CAAC;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAEzB,IAAI,GAAE,+BAAoC;IAQtD,WAAW,CAAC,KAAK,SAAa,GAAG,MAAM,GAAG,IAAI;IAO9C,UAAU,CAAC,KAAK,SAAa,GAAG,OAAO;IAIvC,UAAU,CAAC,KAAK,SAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAYxD;AAWD,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,2BAA2B,CAmBhG;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,OAAO,EACb,aAAa,CAAC,EAAE,MAAM,EACtB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAO,GAC7E,2BAA2B,CAyD7B;AAED,wBAAsB,uBAAuB,CAAC,IAAI,EAAE;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAuBvC"}
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /** Provider-local backend stability observer and drain guard (#553).
4
+ *
5
+ * Conservative by design: read-only probes only, coarse public output, no
6
+ * automatic model load/unload orchestration and no host-safety guarantee.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.BackendStabilityObservation = void 0;
10
+ exports.parseOllamaPs = parseOllamaPs;
11
+ exports.parseLmStudioModels = parseLmStudioModels;
12
+ exports.observeBackendStability = observeBackendStability;
13
+ class BackendStabilityObservation {
14
+ backendState;
15
+ reasonClass;
16
+ drainUntilMs;
17
+ observedAtMs;
18
+ diagnostics;
19
+ constructor(init = {}) {
20
+ this.backendState = init.backendState ?? "ok";
21
+ this.reasonClass = init.reasonClass ?? "ok";
22
+ this.drainUntilMs = init.drainUntilMs ?? null;
23
+ this.observedAtMs = init.observedAtMs ?? Date.now();
24
+ this.diagnostics = init.diagnostics ?? {};
25
+ }
26
+ retryAfterS(nowMs = Date.now()) {
27
+ if (this.drainUntilMs === null)
28
+ return null;
29
+ const remaining = this.drainUntilMs - nowMs;
30
+ if (remaining <= 0)
31
+ return null;
32
+ return Math.max(1, Math.round(remaining / 1000));
33
+ }
34
+ isDraining(nowMs = Date.now()) {
35
+ return this.backendState === "draining" && this.retryAfterS(nowMs) !== null;
36
+ }
37
+ publicDict(nowMs = Date.now()) {
38
+ const body = {
39
+ backend_state: this.backendState,
40
+ reason_class: this.reasonClass,
41
+ };
42
+ const retry = this.retryAfterS(nowMs);
43
+ if (retry !== null) {
44
+ body.retry_after_s = retry;
45
+ body.drain_until = Math.floor((this.drainUntilMs ?? 0) / 1000);
46
+ }
47
+ return body;
48
+ }
49
+ }
50
+ exports.BackendStabilityObservation = BackendStabilityObservation;
51
+ function norm(value) {
52
+ return String(value ?? "").trim().toLowerCase().replace(/-/g, "_");
53
+ }
54
+ function modelMatches(candidate, expectedModel) {
55
+ if (!expectedModel)
56
+ return true;
57
+ return candidate === expectedModel || candidate.split(":", 1)[0] === expectedModel.split(":", 1)[0];
58
+ }
59
+ function parseOllamaPs(data, expectedModel) {
60
+ const models = typeof data === "object" && data !== null && Array.isArray(data.models)
61
+ ? data.models
62
+ : null;
63
+ if (!models)
64
+ return new BackendStabilityObservation({ backendState: "degraded", reasonClass: "observer_error" });
65
+ const names = models.flatMap((m) => {
66
+ if (typeof m !== "object" || m === null)
67
+ return [];
68
+ const name = m.name;
69
+ return typeof name === "string" ? [name] : [];
70
+ });
71
+ const loadedExpected = names.some((name) => modelMatches(name, expectedModel));
72
+ if (expectedModel && !loadedExpected) {
73
+ return new BackendStabilityObservation({
74
+ backendState: "degraded",
75
+ reasonClass: "backend_cold",
76
+ diagnostics: { loaded_model_count: names.length, expected_model_loaded: false },
77
+ });
78
+ }
79
+ return new BackendStabilityObservation({ diagnostics: { loaded_model_count: names.length } });
80
+ }
81
+ function parseLmStudioModels(data, expectedModel, opts = {}) {
82
+ const nowMs = opts.nowMs ?? Date.now();
83
+ const obj = typeof data === "object" && data !== null ? data : {};
84
+ const rawModels = Array.isArray(obj.data) ? obj.data : Array.isArray(obj.models) ? obj.models : null;
85
+ if (!rawModels) {
86
+ return new BackendStabilityObservation({ backendState: "degraded", reasonClass: "observer_error", observedAtMs: nowMs });
87
+ }
88
+ let sawExpected = !expectedModel;
89
+ let sawLoadedExpected = false;
90
+ let sawLoading = false;
91
+ let sawUnstable = false;
92
+ let loadedCount = 0;
93
+ for (const item of rawModels) {
94
+ if (typeof item !== "object" || item === null)
95
+ continue;
96
+ const rec = item;
97
+ const modelId = String(rec.id ?? rec.model_key ?? rec.path ?? "");
98
+ const expected = modelMatches(modelId, expectedModel);
99
+ sawExpected = sawExpected || expected;
100
+ const instancesRaw = Array.isArray(rec.loaded_instances)
101
+ ? rec.loaded_instances
102
+ : Array.isArray(rec.loadedInstances) ? rec.loadedInstances : [];
103
+ for (const inst of instancesRaw) {
104
+ if (typeof inst !== "object" || inst === null)
105
+ continue;
106
+ loadedCount += 1;
107
+ if (expected)
108
+ sawLoadedExpected = true;
109
+ const state = norm(inst.state ?? inst.status ?? inst.load_status);
110
+ if (["loading", "initializing", "starting", "warming", "warming_up"].includes(state))
111
+ sawLoading = true;
112
+ if (["error", "failed", "crashed", "unhealthy", "oom", "out_of_memory"].includes(state))
113
+ sawUnstable = true;
114
+ }
115
+ }
116
+ if (sawUnstable) {
117
+ return new BackendStabilityObservation({
118
+ backendState: "draining",
119
+ reasonClass: "backend_unstable",
120
+ drainUntilMs: nowMs + (opts.unstableRetryS ?? 60) * 1000,
121
+ observedAtMs: nowMs,
122
+ diagnostics: { loaded_instance_count: loadedCount },
123
+ });
124
+ }
125
+ if (sawLoading) {
126
+ return new BackendStabilityObservation({
127
+ backendState: "draining",
128
+ reasonClass: "backend_loading",
129
+ drainUntilMs: nowMs + (opts.loadingRetryS ?? 30) * 1000,
130
+ observedAtMs: nowMs,
131
+ diagnostics: { loaded_instance_count: loadedCount },
132
+ });
133
+ }
134
+ if (expectedModel && (!sawExpected || !sawLoadedExpected)) {
135
+ return new BackendStabilityObservation({
136
+ backendState: "degraded",
137
+ reasonClass: "backend_cold",
138
+ observedAtMs: nowMs,
139
+ diagnostics: { loaded_instance_count: loadedCount, expected_model_loaded: false },
140
+ });
141
+ }
142
+ return new BackendStabilityObservation({ observedAtMs: nowMs, diagnostics: { loaded_instance_count: loadedCount } });
143
+ }
144
+ async function observeBackendStability(opts) {
145
+ const base = opts.backendUrl.replace(/\/$/, "");
146
+ if (!base)
147
+ return new BackendStabilityObservation({ backendState: "degraded", reasonClass: "observer_error" });
148
+ const root = base.endsWith("/v1") ? base.slice(0, -3) : base;
149
+ const flavor = norm(opts.backend);
150
+ const headers = opts.apiKey ? { Authorization: `Bearer ${opts.apiKey}` } : {};
151
+ const f = opts.fetchImpl ?? fetch;
152
+ const signal = () => AbortSignal.timeout(opts.timeoutMs ?? 2000);
153
+ try {
154
+ if (flavor === "ollama" || flavor === "") {
155
+ const r = await f(`${root}/api/ps`, { headers, signal: signal() });
156
+ if (r.ok)
157
+ return parseOllamaPs(await r.json(), opts.expectedModel);
158
+ if (flavor === "ollama")
159
+ return new BackendStabilityObservation({ backendState: "degraded", reasonClass: "observer_error" });
160
+ }
161
+ if (["lmstudio", "lm_studio", "lm_studio_server", ""].includes(flavor)) {
162
+ const r = await f(`${root}/api/v1/models`, { headers, signal: signal() });
163
+ if (r.ok)
164
+ return parseLmStudioModels(await r.json(), opts.expectedModel);
165
+ if (flavor)
166
+ return new BackendStabilityObservation({ backendState: "degraded", reasonClass: "observer_error" });
167
+ }
168
+ }
169
+ catch {
170
+ return new BackendStabilityObservation({ backendState: "degraded", reasonClass: "observer_error" });
171
+ }
172
+ return new BackendStabilityObservation();
173
+ }
174
+ //# sourceMappingURL=backend_stability.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend_stability.js","sourceRoot":"","sources":["../src/backend_stability.ts"],"names":[],"mappings":";AAAA,sCAAsC;AACtC;;;;GAIG;;;AA8DH,sCAmBC;AAED,kDA6DC;AAED,0DA8BC;AAnKD,MAAa,2BAA2B;IACtC,YAAY,CAAe;IAC3B,WAAW,CAAgB;IAC3B,YAAY,CAAgB;IAC5B,YAAY,CAAS;IACrB,WAAW,CAA0B;IAErC,YAAY,OAAwC,EAAE;QACpD,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC;QAC9C,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC;QAC5C,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC;QAC9C,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QACpD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC;IAC5C,CAAC;IAED,WAAW,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE;QAC5B,IAAI,IAAI,CAAC,YAAY,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAC5C,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAC5C,IAAI,SAAS,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QAChC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC;IACnD,CAAC;IAED,UAAU,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE;QAC3B,OAAO,IAAI,CAAC,YAAY,KAAK,UAAU,IAAI,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC;IAC9E,CAAC;IAED,UAAU,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE;QAC3B,MAAM,IAAI,GAA4B;YACpC,aAAa,EAAE,IAAI,CAAC,YAAY;YAChC,YAAY,EAAE,IAAI,CAAC,WAAW;SAC/B,CAAC;QACF,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACtC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;YAC3B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAtCD,kEAsCC;AAED,SAAS,IAAI,CAAC,KAAc;IAC1B,OAAO,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AACrE,CAAC;AAED,SAAS,YAAY,CAAC,SAAiB,EAAE,aAAsB;IAC7D,IAAI,CAAC,aAAa;QAAE,OAAO,IAAI,CAAC;IAChC,OAAO,SAAS,KAAK,aAAa,IAAI,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,aAAa,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACtG,CAAC;AAED,SAAgB,aAAa,CAAC,IAAa,EAAE,aAAsB;IACjE,MAAM,MAAM,GAAG,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAE,IAA6B,CAAC,MAAM,CAAC;QAC9G,CAAC,CAAE,IAA8B,CAAC,MAAM;QACxC,CAAC,CAAC,IAAI,CAAC;IACT,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,2BAA2B,CAAC,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,gBAAgB,EAAE,CAAC,CAAC;IACjH,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;QACjC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI;YAAE,OAAO,EAAE,CAAC;QACnD,MAAM,IAAI,GAAI,CAAwB,CAAC,IAAI,CAAC;QAC5C,OAAO,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAChD,CAAC,CAAC,CAAC;IACH,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC;IAC/E,IAAI,aAAa,IAAI,CAAC,cAAc,EAAE,CAAC;QACrC,OAAO,IAAI,2BAA2B,CAAC;YACrC,YAAY,EAAE,UAAU;YACxB,WAAW,EAAE,cAAc;YAC3B,WAAW,EAAE,EAAE,kBAAkB,EAAE,KAAK,CAAC,MAAM,EAAE,qBAAqB,EAAE,KAAK,EAAE;SAChF,CAAC,CAAC;IACL,CAAC;IACD,OAAO,IAAI,2BAA2B,CAAC,EAAE,WAAW,EAAE,EAAE,kBAAkB,EAAE,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAChG,CAAC;AAED,SAAgB,mBAAmB,CACjC,IAAa,EACb,aAAsB,EACtB,OAA4E,EAAE;IAE9E,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;IACvC,MAAM,GAAG,GAAG,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAA+B,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7F,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IACrG,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,IAAI,2BAA2B,CAAC,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,gBAAgB,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3H,CAAC;IACD,IAAI,WAAW,GAAG,CAAC,aAAa,CAAC;IACjC,IAAI,iBAAiB,GAAG,KAAK,CAAC;IAC9B,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;YAAE,SAAS;QACxD,MAAM,GAAG,GAAG,IAA+B,CAAC;QAC5C,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QAClE,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;QACtD,WAAW,GAAG,WAAW,IAAI,QAAQ,CAAC;QACtC,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;YACtD,CAAC,CAAC,GAAG,CAAC,gBAAgB;YACtB,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;QAClE,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;YAChC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;gBAAE,SAAS;YACxD,WAAW,IAAI,CAAC,CAAC;YACjB,IAAI,QAAQ;gBAAE,iBAAiB,GAAG,IAAI,CAAC;YACvC,MAAM,KAAK,GAAG,IAAI,CAAE,IAAgC,CAAC,KAAK,IAAK,IAAgC,CAAC,MAAM,IAAK,IAAgC,CAAC,WAAW,CAAC,CAAC;YACzJ,IAAI,CAAC,SAAS,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,UAAU,GAAG,IAAI,CAAC;YACxG,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,WAAW,GAAG,IAAI,CAAC;QAC9G,CAAC;IACH,CAAC;IACD,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,IAAI,2BAA2B,CAAC;YACrC,YAAY,EAAE,UAAU;YACxB,WAAW,EAAE,kBAAkB;YAC/B,YAAY,EAAE,KAAK,GAAG,CAAC,IAAI,CAAC,cAAc,IAAI,EAAE,CAAC,GAAG,IAAI;YACxD,YAAY,EAAE,KAAK;YACnB,WAAW,EAAE,EAAE,qBAAqB,EAAE,WAAW,EAAE;SACpD,CAAC,CAAC;IACL,CAAC;IACD,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,IAAI,2BAA2B,CAAC;YACrC,YAAY,EAAE,UAAU;YACxB,WAAW,EAAE,iBAAiB;YAC9B,YAAY,EAAE,KAAK,GAAG,CAAC,IAAI,CAAC,aAAa,IAAI,EAAE,CAAC,GAAG,IAAI;YACvD,YAAY,EAAE,KAAK;YACnB,WAAW,EAAE,EAAE,qBAAqB,EAAE,WAAW,EAAE;SACpD,CAAC,CAAC;IACL,CAAC;IACD,IAAI,aAAa,IAAI,CAAC,CAAC,WAAW,IAAI,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAC1D,OAAO,IAAI,2BAA2B,CAAC;YACrC,YAAY,EAAE,UAAU;YACxB,WAAW,EAAE,cAAc;YAC3B,YAAY,EAAE,KAAK;YACnB,WAAW,EAAE,EAAE,qBAAqB,EAAE,WAAW,EAAE,qBAAqB,EAAE,KAAK,EAAE;SAClF,CAAC,CAAC;IACL,CAAC;IACD,OAAO,IAAI,2BAA2B,CAAC,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,qBAAqB,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;AACvH,CAAC;AAEM,KAAK,UAAU,uBAAuB,CAAC,IAO7C;IACC,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAChD,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,2BAA2B,CAAC,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,gBAAgB,EAAE,CAAC,CAAC;IAC/G,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC7D,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAClC,MAAM,OAAO,GAA2B,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACtG,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,IAAI,KAAK,CAAC;IAClC,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC;IACjE,IAAI,CAAC;QACH,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;YACzC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,IAAI,SAAS,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;YACnE,IAAI,CAAC,CAAC,EAAE;gBAAE,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;YACnE,IAAI,MAAM,KAAK,QAAQ;gBAAE,OAAO,IAAI,2BAA2B,CAAC,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,gBAAgB,EAAE,CAAC,CAAC;QAC/H,CAAC;QACD,IAAI,CAAC,UAAU,EAAE,WAAW,EAAE,kBAAkB,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACvE,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,IAAI,gBAAgB,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;YAC1E,IAAI,CAAC,CAAC,EAAE;gBAAE,OAAO,mBAAmB,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;YACzE,IAAI,MAAM;gBAAE,OAAO,IAAI,2BAA2B,CAAC,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,gBAAgB,EAAE,CAAC,CAAC;QAClH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,2BAA2B,CAAC,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,gBAAgB,EAAE,CAAC,CAAC;IACtG,CAAC;IACD,OAAO,IAAI,2BAA2B,EAAE,CAAC;AAC3C,CAAC"}
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAyCA,OAAO,EAeL,KAAK,YAAY,EAClB,MAAM,eAAe,CAAC;AAGvB,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,qGAAqG;IACrG,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,OAAO,CAAC;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,EAAE,OAAO,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iGAAiG;IACjG,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA4VD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,eAAe,EAAE,OAAO,EACxB,aAAa,EAAE,OAAO,GACrB,KAAK,CAAC,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC,CAGtC;AAiFD,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,GAAG,SAAS,CAsB9E;AAyvBD;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CA+D5D;AA8dD,wBAAsB,IAAI,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,CAmBlF"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AA2CA,OAAO,EAeL,KAAK,YAAY,EAClB,MAAM,eAAe,CAAC;AAGvB,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,qGAAqG;IACrG,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,OAAO,CAAC;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,EAAE,OAAO,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iGAAiG;IACjG,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA6VD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,eAAe,EAAE,OAAO,EACxB,aAAa,EAAE,OAAO,GACrB,KAAK,CAAC,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC,CAGtC;AAiFD,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,GAAG,SAAS,CAsB9E;AAyvBD;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CA+D5D;AA8dD,wBAAsB,IAAI,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,CAmBlF"}
package/dist/cli.js CHANGED
@@ -28,6 +28,8 @@ const node_crypto_1 = require("node:crypto");
28
28
  const SDK_VERSION = require("../package.json").version;
29
29
  const net = require("node:net");
30
30
  const http = require("node:http");
31
+ const fs = require("node:fs");
32
+ const path = require("node:path");
31
33
  const node_child_process_1 = require("node:child_process");
32
34
  const readline = require("node:readline/promises");
33
35
  const node_process_1 = require("node:process");
@@ -67,6 +69,7 @@ function printHelp() {
67
69
  ` credits Show this node's earned / spent / balance credits\n` +
68
70
  ` proxy Run the local OpenAI/Ollama/Anthropic-compat gateway (loopback; no registration)\n` +
69
71
  ` mcp-gateway Bridge a local MCP server as an IICP provider node (registers + serves)\n` +
72
+ ` service Generate/install OS supervisor units for unattended node serving\n` +
70
73
  ` operator rename <name> Change your public display_name (signed by your operator key)\n` +
71
74
  ` operator encrypt Password-encrypt the operator secret at rest ($IICP_OPERATOR_PASSPHRASE)\n` +
72
75
  ` operator decrypt Remove at-rest encryption of the operator secret\n\n` +
@@ -1921,6 +1924,63 @@ async function runUpdate() {
1921
1924
  process.stdout.write(`@iicp/client ${v.current} — up to date (latest: ${v.latest}).\n`);
1922
1925
  return 0;
1923
1926
  }
1927
+ async function runService(argv) {
1928
+ const subcmd = argv[0];
1929
+ if (!subcmd || subcmd === "--help" || subcmd === "-h" || subcmd === "help") {
1930
+ process.stdout.write(`usage: iicp-node service <install|status|restart|uninstall> --node NAME [options]\n\n` +
1931
+ `Generate user-level launchd/systemd supervisor units. The service runs foreground:\n` +
1932
+ ` iicp-node serve --node <NAME>\n\n` +
1933
+ `Options:\n` +
1934
+ ` --node NAME Saved node name to serve (required)\n` +
1935
+ ` --name NAME Override service label/unit name\n` +
1936
+ ` --platform KIND auto | launchd | systemd (default auto)\n` +
1937
+ ` --dry-run For install: print the generated unit without writing files\n`);
1938
+ return subcmd ? 0 : 2;
1939
+ }
1940
+ if (!["install", "status", "restart", "uninstall"].includes(subcmd)) {
1941
+ throw new CliError(`unknown service subcommand '${subcmd}'`);
1942
+ }
1943
+ const { values } = safeParseArgs({
1944
+ args: argv.slice(1),
1945
+ options: {
1946
+ node: { type: "string" },
1947
+ name: { type: "string" },
1948
+ platform: { type: "string" },
1949
+ "dry-run": { type: "boolean" },
1950
+ help: { type: "boolean", short: "h" },
1951
+ },
1952
+ allowPositionals: false,
1953
+ });
1954
+ if (values.help)
1955
+ return runService(["help"]);
1956
+ const node = values.node;
1957
+ if (!node)
1958
+ throw new CliError("service requires --node NAME");
1959
+ const { renderServiceUnit } = await import("./service.js");
1960
+ const unit = renderServiceUnit(node, values.name, values.platform ?? "auto");
1961
+ if (subcmd === "install") {
1962
+ if (values["dry-run"]) {
1963
+ process.stdout.write(`# ${unit.platform} service: ${unit.name}\n# path: ${unit.path}\n${unit.content}`);
1964
+ }
1965
+ else {
1966
+ fs.mkdirSync(path.dirname(unit.path), { recursive: true });
1967
+ fs.writeFileSync(unit.path, unit.content);
1968
+ process.stdout.write(`Installed ${unit.platform} service unit: ${unit.path}\n`);
1969
+ }
1970
+ process.stdout.write(`status: ${unit.statusHint}\n`);
1971
+ process.stdout.write(`restart: ${unit.restartHint}\n`);
1972
+ process.stdout.write(`logs: ${unit.logHint}\n`);
1973
+ process.stdout.write("Note: no classic --daemon fork is used; the OS supervisor runs foreground `iicp-node serve`.\n");
1974
+ return 0;
1975
+ }
1976
+ if (subcmd === "status")
1977
+ process.stdout.write(`${unit.statusHint}\n`);
1978
+ if (subcmd === "restart")
1979
+ process.stdout.write(`${unit.restartHint}\n`);
1980
+ if (subcmd === "uninstall")
1981
+ process.stdout.write(`${unit.uninstallHint}\n`);
1982
+ return 0;
1983
+ }
1924
1984
  async function dispatch(argv) {
1925
1985
  const cmd = argv[0];
1926
1986
  if (cmd === "init")
@@ -1939,6 +1999,8 @@ async function dispatch(argv) {
1939
1999
  return runMcpGateway(argv.slice(1));
1940
2000
  if (cmd === "update")
1941
2001
  return runUpdate();
2002
+ if (cmd === "service")
2003
+ return runService(argv.slice(1));
1942
2004
  if (cmd !== "serve") {
1943
2005
  process.stderr.write(`unknown command: ${cmd}\n`);
1944
2006
  printHelp();