@kindgi/handler-runtime 0.0.0-bootstrap.0 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +218 -2
- package/dist/build-extensions.d.ts +75 -0
- package/dist/build-extensions.d.ts.map +1 -0
- package/dist/build-extensions.js +27 -0
- package/dist/build-extensions.js.map +1 -0
- package/dist/discovery.d.ts +19 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +81 -0
- package/dist/discovery.js.map +1 -0
- package/dist/entrypoint.d.ts +10 -0
- package/dist/entrypoint.d.ts.map +1 -0
- package/dist/entrypoint.js +24 -0
- package/dist/entrypoint.js.map +1 -0
- package/dist/handler-runner.d.ts +127 -0
- package/dist/handler-runner.d.ts.map +1 -0
- package/dist/handler-runner.js +318 -0
- package/dist/handler-runner.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/kindgi-index-main.d.ts +2 -0
- package/dist/kindgi-index-main.d.ts.map +1 -0
- package/dist/kindgi-index-main.js +15 -0
- package/dist/kindgi-index-main.js.map +1 -0
- package/dist/kindgi-index.d.ts +316 -0
- package/dist/kindgi-index.d.ts.map +1 -0
- package/dist/kindgi-index.js +1201 -0
- package/dist/kindgi-index.js.map +1 -0
- package/dist/pack-env.d.ts +66 -0
- package/dist/pack-env.d.ts.map +1 -0
- package/dist/pack-env.js +97 -0
- package/dist/pack-env.js.map +1 -0
- package/dist/pack-service/index.d.ts +7 -0
- package/dist/pack-service/index.d.ts.map +1 -0
- package/dist/pack-service/index.js +6 -0
- package/dist/pack-service/index.js.map +1 -0
- package/dist/pack-service/main.d.ts +47 -0
- package/dist/pack-service/main.d.ts.map +1 -0
- package/dist/pack-service/main.js +201 -0
- package/dist/pack-service/main.js.map +1 -0
- package/dist/pack-service/service.d.ts +61 -0
- package/dist/pack-service/service.d.ts.map +1 -0
- package/dist/pack-service/service.js +341 -0
- package/dist/pack-service/service.js.map +1 -0
- package/dist/pack-service/supervisor.d.ts +138 -0
- package/dist/pack-service/supervisor.d.ts.map +1 -0
- package/dist/pack-service/supervisor.js +424 -0
- package/dist/pack-service/supervisor.js.map +1 -0
- package/dist/protocol.d.ts +104 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +116 -0
- package/dist/protocol.js.map +1 -0
- package/package.json +87 -4
- package/src/build-extensions.ts +100 -0
- package/src/discovery.ts +89 -0
- package/src/entrypoint.ts +23 -0
- package/src/handler-runner.ts +500 -0
- package/src/index.ts +66 -0
- package/src/kindgi-index-main.ts +17 -0
- package/src/kindgi-index.ts +1605 -0
- package/src/pack-env.ts +148 -0
- package/src/pack-service/index.ts +17 -0
- package/src/pack-service/main.ts +246 -0
- package/src/pack-service/service.ts +478 -0
- package/src/pack-service/supervisor.ts +600 -0
- package/src/protocol.ts +214 -0
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
/**
|
|
4
|
+
* The pack service: an HTTP server that runs a pack's code — its tool
|
|
5
|
+
* handlers and guardrail checks — for a Kindgi runtime, speaking pack
|
|
6
|
+
* protocol v2 (`../protocol.ts`).
|
|
7
|
+
*
|
|
8
|
+
* Long-lived and warm: modules are imported once (at `prewarm`) and
|
|
9
|
+
* reused across calls, and calls run concurrently up to a cap. Handler
|
|
10
|
+
* console output goes to the process's own stdout/stderr and can never
|
|
11
|
+
* corrupt a response.
|
|
12
|
+
*
|
|
13
|
+
* Routes:
|
|
14
|
+
* - `POST /v1/invoke` (token) — body: a `PackRequest`; 200 with a `PackResponse`
|
|
15
|
+
* - `GET /v1/info` (token) — the pack's identity, protocol, tools and checks,
|
|
16
|
+
* and the required env names it lacks (`missingEnv`)
|
|
17
|
+
* - `GET /healthz` — the process is up
|
|
18
|
+
* - `GET /readyz` — prewarmed, not draining, and (under the
|
|
19
|
+
* `strict` env check) every required env name set
|
|
20
|
+
*
|
|
21
|
+
* Non-2xx statuses are transport-level only: 401 (token), 404, 405, 413
|
|
22
|
+
* (body too large), 415 (not JSON), 503 with `Retry-After` (not ready,
|
|
23
|
+
* draining or at the concurrency cap), and 500 if the service itself
|
|
24
|
+
* fails while handling a call.
|
|
25
|
+
*/
|
|
26
|
+
import { timingSafeEqual } from 'node:crypto';
|
|
27
|
+
import { pathToFileURL } from 'node:url';
|
|
28
|
+
import { runCheck, runHandler } from '../handler-runner.js';
|
|
29
|
+
import { missingPackEnv } from '../pack-env.js';
|
|
30
|
+
import { PACK_HEADERS, PACK_PROTOCOL_VERSION, packError, parsePackRequest, } from '../protocol.js';
|
|
31
|
+
const DEFAULT_MAX_CONCURRENCY = 32;
|
|
32
|
+
const DEFAULT_MAX_BODY_BYTES = 10 * 1024 * 1024;
|
|
33
|
+
const DEFAULT_TIMEOUT_MS = 120_000;
|
|
34
|
+
export function createPackService(options) {
|
|
35
|
+
const maxConcurrency = options.maxConcurrency ?? DEFAULT_MAX_CONCURRENCY;
|
|
36
|
+
const maxBodyBytes = options.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES;
|
|
37
|
+
const defaultTimeoutMs = options.defaultTimeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
38
|
+
const logger = options.logger ?? (() => undefined);
|
|
39
|
+
const importModule = options.importModule ?? ((p) => import(pathToFileURL(p).href));
|
|
40
|
+
const expectedToken = Buffer.from(options.token);
|
|
41
|
+
const tools = new Map(options.index.tools.map((t) => [t.id, t]));
|
|
42
|
+
const checks = new Map(options.index.guardrails.map((g) => [g.checkId ?? g.id, g]));
|
|
43
|
+
let inFlight = 0;
|
|
44
|
+
let ready = false;
|
|
45
|
+
let draining = false;
|
|
46
|
+
const envCheck = options.envCheck ?? 'strict';
|
|
47
|
+
const missingEnv = missingPackEnv(options.index.env, options.env ?? process.env);
|
|
48
|
+
if (missingEnv.length > 0)
|
|
49
|
+
logger({ kind: 'missing-env', check: envCheck, names: missingEnv });
|
|
50
|
+
/** Why the service can't take calls now, or `undefined` when it can. */
|
|
51
|
+
function notReady() {
|
|
52
|
+
if (draining)
|
|
53
|
+
return unavailable('draining');
|
|
54
|
+
if (envCheck === 'strict' && missingEnv.length > 0) {
|
|
55
|
+
return unavailable('missing env', { missingEnv });
|
|
56
|
+
}
|
|
57
|
+
if (!ready)
|
|
58
|
+
return unavailable('not ready');
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
function authorized(req) {
|
|
62
|
+
const got = req.headers[PACK_HEADERS.token];
|
|
63
|
+
if (typeof got !== 'string')
|
|
64
|
+
return false;
|
|
65
|
+
const buf = Buffer.from(got);
|
|
66
|
+
return buf.length === expectedToken.length && timingSafeEqual(buf, expectedToken);
|
|
67
|
+
}
|
|
68
|
+
async function prewarm() {
|
|
69
|
+
const failures = [];
|
|
70
|
+
const targets = [
|
|
71
|
+
...[...tools.values()].map((t) => ({ id: t.id, modulePath: t.modulePath, check: false })),
|
|
72
|
+
...[...checks.entries()].map(([id, g]) => ({
|
|
73
|
+
id,
|
|
74
|
+
modulePath: g.checkModulePath,
|
|
75
|
+
check: true,
|
|
76
|
+
})),
|
|
77
|
+
];
|
|
78
|
+
for (const target of targets) {
|
|
79
|
+
try {
|
|
80
|
+
await importModule(options.resolveModule(target.modulePath));
|
|
81
|
+
}
|
|
82
|
+
catch (cause) {
|
|
83
|
+
failures.push(packError('handler-import-failed', `${target.id}: ${describe(cause)}`, {
|
|
84
|
+
...(target.check ? { checkId: target.id } : { toolId: target.id }),
|
|
85
|
+
}));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
ready = failures.length === 0;
|
|
89
|
+
return failures;
|
|
90
|
+
}
|
|
91
|
+
async function drain(graceMs) {
|
|
92
|
+
draining = true;
|
|
93
|
+
const deadline = Date.now() + graceMs;
|
|
94
|
+
while (inFlight > 0 && Date.now() < deadline) {
|
|
95
|
+
await new Promise((r) => setTimeout(r, 25));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function info() {
|
|
99
|
+
return {
|
|
100
|
+
protocol: PACK_PROTOCOL_VERSION,
|
|
101
|
+
packId: options.index.packId,
|
|
102
|
+
packVersion: options.index.packVersion,
|
|
103
|
+
artifactVersion: options.index.artifactVersion,
|
|
104
|
+
tools: [...tools.values()].map((t) => ({
|
|
105
|
+
id: t.id,
|
|
106
|
+
...(t.version && { version: t.version }),
|
|
107
|
+
})),
|
|
108
|
+
checks: [...checks.keys()],
|
|
109
|
+
missingEnv,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function callTool(message, signal) {
|
|
113
|
+
const tool = tools.get(message.tool.id);
|
|
114
|
+
if (tool === undefined) {
|
|
115
|
+
return Promise.resolve(packError('tool-not-in-pack', `This pack has no tool "${message.tool.id}"`, {
|
|
116
|
+
toolId: message.tool.id,
|
|
117
|
+
}));
|
|
118
|
+
}
|
|
119
|
+
if (message.tool.version !== undefined && message.tool.version !== tool.version) {
|
|
120
|
+
return Promise.resolve(packError('tool-version-mismatch', `Tool "${tool.id}" is ${tool.version ?? 'unversioned'} in this pack; the caller asked for ${message.tool.version}`, { toolId: tool.id }));
|
|
121
|
+
}
|
|
122
|
+
return runHandler({
|
|
123
|
+
tool: {
|
|
124
|
+
id: tool.id,
|
|
125
|
+
modulePath: options.resolveModule(tool.modulePath),
|
|
126
|
+
inputSchema: tool.input,
|
|
127
|
+
outputSchema: tool.output,
|
|
128
|
+
},
|
|
129
|
+
input: message.input,
|
|
130
|
+
ctx: { ...message.ctx, abortSignal: signal },
|
|
131
|
+
importHandler: (p) => importModule(p),
|
|
132
|
+
}).then((r) => r.kind === 'ok'
|
|
133
|
+
? { v: PACK_PROTOCOL_VERSION, kind: 'result', output: r.value }
|
|
134
|
+
: fromHandlerError(r.error, { toolId: tool.id }));
|
|
135
|
+
}
|
|
136
|
+
function callCheck(message, signal) {
|
|
137
|
+
const guardrail = checks.get(message.check.id);
|
|
138
|
+
if (guardrail === undefined) {
|
|
139
|
+
return Promise.resolve(packError('check-not-in-pack', `This pack has no check "${message.check.id}"`, {
|
|
140
|
+
checkId: message.check.id,
|
|
141
|
+
}));
|
|
142
|
+
}
|
|
143
|
+
return runCheck({
|
|
144
|
+
check: { id: message.check.id, modulePath: options.resolveModule(guardrail.checkModulePath) },
|
|
145
|
+
config: message.config,
|
|
146
|
+
trace: message.trace,
|
|
147
|
+
abortSignal: signal,
|
|
148
|
+
importCheck: (p) => importModule(p),
|
|
149
|
+
}).then((r) => r.kind === 'ok'
|
|
150
|
+
? { v: PACK_PROTOCOL_VERSION, kind: 'check-result', result: r.value }
|
|
151
|
+
: fromHandlerError(r.error, { checkId: message.check.id }));
|
|
152
|
+
}
|
|
153
|
+
/** Why a call can't be taken right now, if it can't. */
|
|
154
|
+
function refuseInvoke(req) {
|
|
155
|
+
const unready = notReady();
|
|
156
|
+
if (unready !== undefined)
|
|
157
|
+
return unready;
|
|
158
|
+
if (inFlight >= maxConcurrency)
|
|
159
|
+
return unavailable('overloaded');
|
|
160
|
+
if (!(req.headers['content-type'] ?? '').includes('application/json')) {
|
|
161
|
+
return { status: 415, body: { error: 'Content-Type must be application/json' } };
|
|
162
|
+
}
|
|
163
|
+
return undefined;
|
|
164
|
+
}
|
|
165
|
+
async function invoke(req, res) {
|
|
166
|
+
const refused = refuseInvoke(req);
|
|
167
|
+
if (refused !== undefined) {
|
|
168
|
+
reply(res, refused);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
inFlight += 1;
|
|
172
|
+
const started = Date.now();
|
|
173
|
+
try {
|
|
174
|
+
const body = await readBody(req, maxBodyBytes);
|
|
175
|
+
const response = body === undefined ? undefined : await dispatch(req, res, body);
|
|
176
|
+
if (res.writableEnded || res.destroyed)
|
|
177
|
+
return;
|
|
178
|
+
reply(res, response === undefined
|
|
179
|
+
? { status: 413, body: { error: 'Request body too large' } }
|
|
180
|
+
: {
|
|
181
|
+
status: 200,
|
|
182
|
+
body: response,
|
|
183
|
+
headers: {
|
|
184
|
+
[PACK_HEADERS.durationMs]: String(Date.now() - started),
|
|
185
|
+
[PACK_HEADERS.artifactVersion]: options.index.artifactVersion,
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
finally {
|
|
190
|
+
inFlight -= 1;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
async function dispatch(req, res, body) {
|
|
194
|
+
let json;
|
|
195
|
+
try {
|
|
196
|
+
json = JSON.parse(body);
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
return packError('malformed-message', 'Request body is not valid JSON');
|
|
200
|
+
}
|
|
201
|
+
const parsed = parsePackRequest(json);
|
|
202
|
+
if (parsed.kind === 'err')
|
|
203
|
+
return parsed.error;
|
|
204
|
+
const message = parsed.value;
|
|
205
|
+
const target = message.kind === 'invoke' ? 'tool' : 'check';
|
|
206
|
+
const id = message.kind === 'invoke' ? message.tool.id : message.check.id;
|
|
207
|
+
const controller = new AbortController();
|
|
208
|
+
const timeoutMs = parseTimeout(req.headers[PACK_HEADERS.timeoutMs]) ?? defaultTimeoutMs;
|
|
209
|
+
const timer = setTimeout(() => controller.abort('deadline-exceeded'), timeoutMs);
|
|
210
|
+
// The caller gave up (closed the connection) before we answered.
|
|
211
|
+
res.on('close', () => {
|
|
212
|
+
if (!res.writableEnded)
|
|
213
|
+
controller.abort('cancelled');
|
|
214
|
+
});
|
|
215
|
+
const started = Date.now();
|
|
216
|
+
const work = message.kind === 'invoke'
|
|
217
|
+
? callTool(message, controller.signal)
|
|
218
|
+
: callCheck(message, controller.signal);
|
|
219
|
+
const outcome = await Promise.race([work, aborted(controller.signal, id, target)]);
|
|
220
|
+
clearTimeout(timer);
|
|
221
|
+
if (controller.signal.aborted) {
|
|
222
|
+
void work.then(() => logger({ kind: 'handler-finished-late', target, id, afterMs: Date.now() - started }));
|
|
223
|
+
}
|
|
224
|
+
logger({
|
|
225
|
+
kind: 'call',
|
|
226
|
+
target,
|
|
227
|
+
id,
|
|
228
|
+
durationMs: Date.now() - started,
|
|
229
|
+
outcome: outcome.kind === 'error' ? outcome.code : 'ok',
|
|
230
|
+
});
|
|
231
|
+
return outcome;
|
|
232
|
+
}
|
|
233
|
+
/** The transport-level answer for a request before any route runs, if any. */
|
|
234
|
+
function refuseRequest(req, route) {
|
|
235
|
+
if (route === undefined)
|
|
236
|
+
return { status: 404, body: { error: `No route ${req.url ?? '/'}` } };
|
|
237
|
+
if (req.method !== route.method)
|
|
238
|
+
return { status: 405, body: { error: `Use ${route.method}` } };
|
|
239
|
+
if (route.auth && !authorized(req))
|
|
240
|
+
return { status: 401, body: { error: 'Bad pack token' } };
|
|
241
|
+
return undefined;
|
|
242
|
+
}
|
|
243
|
+
function probe(name) {
|
|
244
|
+
if (name === 'healthz')
|
|
245
|
+
return { status: 200, body: { status: 'ok' } };
|
|
246
|
+
if (name === 'readyz')
|
|
247
|
+
return notReady() ?? { status: 200, body: { status: 'ready' } };
|
|
248
|
+
return { status: 200, body: info() };
|
|
249
|
+
}
|
|
250
|
+
function handle(req, res) {
|
|
251
|
+
const route = ROUTES[(req.url ?? '/').split('?')[0] ?? ''];
|
|
252
|
+
const refused = refuseRequest(req, route);
|
|
253
|
+
if (refused !== undefined || route === undefined) {
|
|
254
|
+
reply(res, refused ?? { status: 404, body: {} });
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
if (route.name !== 'invoke') {
|
|
258
|
+
reply(res, probe(route.name));
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
void invoke(req, res).catch((cause) => {
|
|
262
|
+
if (!res.writableEnded)
|
|
263
|
+
reply(res, { status: 500, body: { error: describe(cause) } });
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
return {
|
|
267
|
+
handle,
|
|
268
|
+
prewarm,
|
|
269
|
+
drain,
|
|
270
|
+
inFlight: () => inFlight,
|
|
271
|
+
ready: () => notReady() === undefined,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
const ROUTES = {
|
|
275
|
+
'/v1/invoke': { name: 'invoke', method: 'POST', auth: true },
|
|
276
|
+
'/v1/info': { name: 'info', method: 'GET', auth: true },
|
|
277
|
+
'/healthz': { name: 'healthz', method: 'GET', auth: false },
|
|
278
|
+
'/readyz': { name: 'readyz', method: 'GET', auth: false },
|
|
279
|
+
};
|
|
280
|
+
function aborted(signal, id, target) {
|
|
281
|
+
return new Promise((resolve) => {
|
|
282
|
+
const settle = () => {
|
|
283
|
+
const reason = signal.reason === 'deadline-exceeded' ? 'deadline-exceeded' : 'cancelled';
|
|
284
|
+
const message = reason === 'deadline-exceeded' ? `${id} passed its deadline` : `${id} was cancelled`;
|
|
285
|
+
resolve(packError(reason, message, target === 'tool' ? { toolId: id } : { checkId: id }));
|
|
286
|
+
};
|
|
287
|
+
if (signal.aborted)
|
|
288
|
+
settle();
|
|
289
|
+
else
|
|
290
|
+
signal.addEventListener('abort', settle, { once: true });
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
function fromHandlerError(error, ids) {
|
|
294
|
+
return packError(error.code, error.message, {
|
|
295
|
+
...ids,
|
|
296
|
+
...(error.cause !== undefined && { cause: error.cause }),
|
|
297
|
+
...(error.issues !== undefined && { issues: error.issues }),
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
function parseTimeout(raw) {
|
|
301
|
+
if (typeof raw !== 'string')
|
|
302
|
+
return undefined;
|
|
303
|
+
const ms = Number(raw);
|
|
304
|
+
return Number.isInteger(ms) && ms > 0 ? ms : undefined;
|
|
305
|
+
}
|
|
306
|
+
/** The body as text, or `undefined` once it exceeds `limit` (the rest is drained). */
|
|
307
|
+
function readBody(req, limit) {
|
|
308
|
+
return new Promise((resolve, reject) => {
|
|
309
|
+
const chunks = [];
|
|
310
|
+
let size = 0;
|
|
311
|
+
let tooLarge = false;
|
|
312
|
+
req.on('data', (chunk) => {
|
|
313
|
+
size += chunk.length;
|
|
314
|
+
if (size > limit)
|
|
315
|
+
tooLarge = true;
|
|
316
|
+
if (!tooLarge)
|
|
317
|
+
chunks.push(chunk);
|
|
318
|
+
});
|
|
319
|
+
req.on('end', () => resolve(tooLarge ? undefined : Buffer.concat(chunks).toString('utf8')));
|
|
320
|
+
req.on('error', reject);
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
function unavailable(reason, details) {
|
|
324
|
+
return { status: 503, body: { error: reason, ...details }, headers: { 'retry-after': '1' } };
|
|
325
|
+
}
|
|
326
|
+
function reply(res, r) {
|
|
327
|
+
sendJson(res, r.status, r.body, r.headers);
|
|
328
|
+
}
|
|
329
|
+
function sendJson(res, status, body, headers = {}) {
|
|
330
|
+
const text = JSON.stringify(body);
|
|
331
|
+
res.writeHead(status, {
|
|
332
|
+
'content-type': 'application/json; charset=utf-8',
|
|
333
|
+
'content-length': Buffer.byteLength(text),
|
|
334
|
+
...headers,
|
|
335
|
+
});
|
|
336
|
+
res.end(text);
|
|
337
|
+
}
|
|
338
|
+
function describe(cause) {
|
|
339
|
+
return cause instanceof Error ? cause.message : String(cause);
|
|
340
|
+
}
|
|
341
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/pack-service/service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import type { Result } from '@kindgi/types';
|
|
2
|
+
export interface PackServiceSupervisorOptions {
|
|
3
|
+
/**
|
|
4
|
+
* The pack-service process as an argv — the program, then its arguments.
|
|
5
|
+
* The supervisor appends `--index`, `--module-root` and `--host`. Any pack
|
|
6
|
+
* service with that process contract works (`pack-protocol.schema.json`):
|
|
7
|
+
*
|
|
8
|
+
* - Node: `[process.execPath, '--enable-source-maps', <@kindgi/handler-runtime/pack-service-main>]`
|
|
9
|
+
* - Python: `[<the pack's python>, '-m', 'kindgi.pack', 'serve']`
|
|
10
|
+
*/
|
|
11
|
+
readonly command: readonly [string, ...string[]];
|
|
12
|
+
/** Where the index's module paths resolve — the pack directory. */
|
|
13
|
+
readonly moduleRoot: string;
|
|
14
|
+
/** The child's whole environment, read at every start. */
|
|
15
|
+
readonly env: () => Promise<Readonly<Record<string, string>>>;
|
|
16
|
+
/** Where the front listens. Default `127.0.0.1`. */
|
|
17
|
+
readonly host?: string;
|
|
18
|
+
/** The front's port. Default `0`: any free port, fixed while the front listens. */
|
|
19
|
+
readonly port?: number;
|
|
20
|
+
/**
|
|
21
|
+
* The token callers of the front send. Default: a new random one for
|
|
22
|
+
* each supervisor. Pass the previous supervisor's (with its `port`) so
|
|
23
|
+
* a caller started with both, such as a runtime running from source
|
|
24
|
+
* for `kindgi dev --runtime-url`, keeps reaching the front across
|
|
25
|
+
* restarts. At least 32 URL-safe base64 characters.
|
|
26
|
+
*/
|
|
27
|
+
readonly token?: string;
|
|
28
|
+
/** Each line pack code writes; the service's own JSON log lines arrive as `onEvent`. */
|
|
29
|
+
readonly onLog?: (line: string, stream: 'stdout' | 'stderr') => void;
|
|
30
|
+
readonly onEvent?: (event: PackServiceSupervisorEvent) => void;
|
|
31
|
+
/** How long a child may take to listen. Default 60 000 ms. */
|
|
32
|
+
readonly bootTimeoutMs?: number;
|
|
33
|
+
/**
|
|
34
|
+
* How long a stopping child may drain before it is killed. Default: the
|
|
35
|
+
* child's own drain (`PACK_SERVICE_DRAIN_MS`) plus 2 s, so a call the
|
|
36
|
+
* child would still finish is never cut off by the kill.
|
|
37
|
+
*/
|
|
38
|
+
readonly stopGraceMs?: number;
|
|
39
|
+
/** Restarts after a child exits on its own, before giving up. Default 3. */
|
|
40
|
+
readonly maxRestarts?: number;
|
|
41
|
+
/** Wait before such a restart. Default 500 ms. */
|
|
42
|
+
readonly restartDelayMs?: number;
|
|
43
|
+
/** Largest request body the front accepts. Default 10 MiB (the pack service's own limit). */
|
|
44
|
+
readonly maxBodyBytes?: number;
|
|
45
|
+
}
|
|
46
|
+
export type PackServiceSupervisorEvent = {
|
|
47
|
+
readonly kind: 'started';
|
|
48
|
+
readonly port: number;
|
|
49
|
+
readonly indexPath: string;
|
|
50
|
+
} | {
|
|
51
|
+
readonly kind: 'boot-failed';
|
|
52
|
+
readonly problems: readonly string[];
|
|
53
|
+
} | {
|
|
54
|
+
readonly kind: 'exited';
|
|
55
|
+
readonly code: number | null;
|
|
56
|
+
readonly signal: string | null;
|
|
57
|
+
} | {
|
|
58
|
+
readonly kind: 'restarting';
|
|
59
|
+
readonly attempt: number;
|
|
60
|
+
} | {
|
|
61
|
+
readonly kind: 'gave-up';
|
|
62
|
+
readonly attempts: number;
|
|
63
|
+
}
|
|
64
|
+
/** One of the service's own JSON log lines (a call, draining, …). */
|
|
65
|
+
| {
|
|
66
|
+
readonly kind: 'log';
|
|
67
|
+
readonly event: Readonly<Record<string, unknown>>;
|
|
68
|
+
};
|
|
69
|
+
export interface BootFailure {
|
|
70
|
+
readonly problems: readonly string[];
|
|
71
|
+
}
|
|
72
|
+
/** One call to forward: a request body and the call's options. */
|
|
73
|
+
export interface PackRelayCall {
|
|
74
|
+
readonly route: 'invoke' | 'info';
|
|
75
|
+
/** The protocol v2 request (JSON text) for `invoke`; absent for `info`. */
|
|
76
|
+
readonly body?: string;
|
|
77
|
+
/** Cancels the call: the child sees its connection close. */
|
|
78
|
+
readonly signal?: AbortSignal;
|
|
79
|
+
/** The call's deadline, passed on to the child. */
|
|
80
|
+
readonly timeoutMs?: number;
|
|
81
|
+
readonly runId?: string;
|
|
82
|
+
readonly requestId?: string;
|
|
83
|
+
/** The caller's protocol version (`kindgi-protocol`), passed on as is. */
|
|
84
|
+
readonly protocol?: string;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* What became of a forwarded call:
|
|
88
|
+
* - `answer` — the child answered (any status, passed through as is);
|
|
89
|
+
* - `unavailable` — not delivered (no child serving, or the connection
|
|
90
|
+
* was refused), so it provably did not run and may be retried;
|
|
91
|
+
* - `failed` — delivered, but no answer came back (the child died
|
|
92
|
+
* mid-call); it may have run, so it must not be retried;
|
|
93
|
+
* - `cancelled` — the caller cancelled it.
|
|
94
|
+
*/
|
|
95
|
+
export type PackRelayOutcome = {
|
|
96
|
+
readonly kind: 'answer';
|
|
97
|
+
readonly status: number;
|
|
98
|
+
readonly headers: Readonly<Record<string, string>>;
|
|
99
|
+
readonly body: string;
|
|
100
|
+
} | {
|
|
101
|
+
readonly kind: 'unavailable';
|
|
102
|
+
readonly reason: string;
|
|
103
|
+
} | {
|
|
104
|
+
readonly kind: 'failed';
|
|
105
|
+
readonly reason: string;
|
|
106
|
+
} | {
|
|
107
|
+
readonly kind: 'cancelled';
|
|
108
|
+
};
|
|
109
|
+
/** Forwards calls to the serving child. */
|
|
110
|
+
export interface PackRelay {
|
|
111
|
+
/** Whether a child is serving. */
|
|
112
|
+
readonly serving: () => boolean;
|
|
113
|
+
forward(call: PackRelayCall): Promise<PackRelayOutcome>;
|
|
114
|
+
}
|
|
115
|
+
export interface PackServiceSupervisor {
|
|
116
|
+
/** The token callers send (`kindgi-pack-token`); the children use it too. */
|
|
117
|
+
readonly token: string;
|
|
118
|
+
/** Forwards one call to the serving child; the front's HTTP listener uses it. */
|
|
119
|
+
readonly relay: PackRelay;
|
|
120
|
+
/** Open the front. Idempotent: later calls return the same address. */
|
|
121
|
+
listen(): Promise<{
|
|
122
|
+
readonly url: string;
|
|
123
|
+
readonly port: number;
|
|
124
|
+
}>;
|
|
125
|
+
/**
|
|
126
|
+
* Boot a child on `indexPath` and switch calls to it once it listens.
|
|
127
|
+
* On failure the previous child, if any, keeps serving.
|
|
128
|
+
*/
|
|
129
|
+
start(indexPath: string): Promise<Result<{
|
|
130
|
+
readonly port: number;
|
|
131
|
+
}, BootFailure>>;
|
|
132
|
+
/** Stop the serving child; the front then answers 503. */
|
|
133
|
+
stop(): Promise<void>;
|
|
134
|
+
/** Stop the serving child and close the front. */
|
|
135
|
+
close(): Promise<void>;
|
|
136
|
+
}
|
|
137
|
+
export declare function createPackServiceSupervisor(options: PackServiceSupervisorOptions): PackServiceSupervisor;
|
|
138
|
+
//# sourceMappingURL=supervisor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supervisor.d.ts","sourceRoot":"","sources":["../../src/pack-service/supervisor.ts"],"names":[],"mappings":"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"}
|