@jini-ai/agent-runtime 0.4.1 → 0.4.2
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/CHANGELOG.md +4 -0
- package/dist/acp-model-probe.d.ts +6 -27
- package/dist/acp-model-probe.js +6 -4
- package/dist/agent-protocol/acp/models.d.ts +8 -0
- package/dist/agent-protocol/acp/models.js +38 -6
- package/dist/agent-protocol/acp/session.js +15 -2
- package/dist/agent-protocol/pi-rpc/events.js +4 -0
- package/dist/amr-model-cache.d.ts +2 -12
- package/dist/amr-profile-resolver.d.ts +3 -14
- package/dist/anthropic-live-models.d.ts +1 -1
- package/dist/anthropic-live-models.js +0 -0
- package/dist/artifact-taxonomy.d.ts +3 -17
- package/dist/auth.d.ts +0 -6
- package/dist/auth.js +1 -30
- package/dist/claude-code-models.d.ts +3 -4
- package/dist/claude-code-models.js +5 -7
- package/dist/claude-stream.d.ts +0 -4
- package/dist/claude-stream.js +4 -4
- package/dist/copilot-stream.d.ts +0 -5
- package/dist/copilot-stream.js +0 -5
- package/dist/defs/aider.d.ts +15 -0
- package/dist/defs/aider.js +4 -2
- package/dist/defs/amp.d.ts +16 -0
- package/dist/defs/amp.js +5 -1
- package/dist/defs/amr.d.ts +15 -0
- package/dist/defs/amr.js +6 -15
- package/dist/defs/antigravity.d.ts +16 -1
- package/dist/defs/antigravity.js +3 -2
- package/dist/defs/auggie.d.ts +15 -0
- package/dist/defs/auggie.js +3 -0
- package/dist/defs/claude.d.ts +15 -0
- package/dist/defs/claude.js +26 -36
- package/dist/defs/cline.d.ts +15 -0
- package/dist/defs/cline.js +3 -0
- package/dist/defs/codebuddy.d.ts +15 -0
- package/dist/defs/codebuddy.js +3 -1
- package/dist/defs/codex.d.ts +15 -0
- package/dist/defs/codex.js +11 -48
- package/dist/defs/copilot.d.ts +15 -0
- package/dist/defs/copilot.js +5 -14
- package/dist/defs/crush.d.ts +15 -0
- package/dist/defs/crush.js +3 -0
- package/dist/defs/cursor-agent.d.ts +15 -0
- package/dist/defs/cursor-agent.js +3 -1
- package/dist/defs/deepseek.d.ts +15 -0
- package/dist/defs/deepseek.js +3 -1
- package/dist/defs/devin.d.ts +15 -0
- package/dist/defs/devin.js +3 -1
- package/dist/defs/droid.d.ts +15 -0
- package/dist/defs/droid.js +3 -0
- package/dist/defs/goose.d.ts +15 -0
- package/dist/defs/goose.js +3 -0
- package/dist/defs/grok-build.d.ts +15 -0
- package/dist/defs/grok-build.js +5 -9
- package/dist/defs/hermes.d.ts +15 -0
- package/dist/defs/hermes.js +3 -1
- package/dist/defs/index.d.ts +1 -6
- package/dist/defs/index.js +1 -6
- package/dist/defs/kilo.d.ts +15 -0
- package/dist/defs/kilo.js +3 -1
- package/dist/defs/kimi.d.ts +15 -0
- package/dist/defs/kimi.js +3 -1
- package/dist/defs/kiro.d.ts +15 -0
- package/dist/defs/kiro.js +3 -1
- package/dist/defs/mimo.d.ts +15 -0
- package/dist/defs/mimo.js +3 -1
- package/dist/defs/opencode.d.ts +15 -1
- package/dist/defs/opencode.js +2 -1
- package/dist/defs/pi.d.ts +15 -0
- package/dist/defs/pi.js +6 -5
- package/dist/defs/qoder.d.ts +15 -0
- package/dist/defs/qoder.js +3 -1
- package/dist/defs/qwen.d.ts +15 -0
- package/dist/defs/qwen.js +3 -1
- package/dist/defs/reasonix.d.ts +15 -0
- package/dist/defs/reasonix.js +7 -23
- package/dist/defs/shared.d.ts +3 -8
- package/dist/defs/shared.js +3 -8
- package/dist/defs/trae-cli.d.ts +15 -0
- package/dist/defs/trae-cli.js +3 -1
- package/dist/defs/vibe.d.ts +15 -0
- package/dist/defs/vibe.js +3 -1
- package/dist/detection.d.ts +23 -4
- package/dist/detection.js +41 -59
- package/dist/diagnostics.js +1 -9
- package/dist/env.js +5 -31
- package/dist/executables.js +0 -1
- package/dist/index.d.ts +10 -257
- package/dist/index.js +20 -278
- package/dist/json-event-stream.js +23 -29
- package/dist/launch.js +1 -5
- package/dist/log-file.js +0 -5
- package/dist/metadata.js +0 -4
- package/dist/mmd-routes.js +2 -6
- package/dist/model-discovery-adapters.d.ts +19 -0
- package/dist/model-discovery-adapters.js +387 -0
- package/dist/model-discovery-config.d.ts +17 -0
- package/dist/model-discovery-config.js +137 -0
- package/dist/model-discovery-sdk.d.ts +18 -0
- package/dist/model-discovery-sdk.js +56 -0
- package/dist/model-discovery-types.d.ts +139 -0
- package/dist/model-discovery-types.js +2 -0
- package/dist/model-discovery.d.ts +46 -0
- package/dist/model-discovery.js +258 -0
- package/dist/model-registry.d.ts +5 -36
- package/dist/models.d.ts +1 -4
- package/dist/models.js +3 -1
- package/dist/opencode-log.js +1 -3
- package/dist/paths.js +1 -4
- package/dist/pi-models.d.ts +1 -7
- package/dist/pi-models.js +1 -3
- package/dist/prompt-augmenter.d.ts +3 -17
- package/dist/prompt-augmenter.js +3 -17
- package/dist/providers/model-catalog.d.ts +2 -0
- package/dist/providers/model-catalog.js +76 -55
- package/dist/providers/sse-decode.d.ts +4 -48
- package/dist/providers/sse-decode.js +3 -108
- package/dist/qoder-stream.d.ts +0 -3
- package/dist/qoder-stream.js +0 -3
- package/dist/registry.d.ts +1 -1
- package/dist/registry.js +3 -3
- package/dist/resolution.js +1 -4
- package/dist/role-marker-guard.d.ts +0 -5
- package/dist/role-marker-guard.js +0 -5
- package/dist/telemetry-sink.d.ts +3 -14
- package/dist/types.d.ts +9 -2
- package/package.json +27 -6
|
@@ -321,66 +321,87 @@ export async function listProviderModels(requiredArgs, optionalArgs = {}) {
|
|
|
321
321
|
// assigns unconditionally.
|
|
322
322
|
let result;
|
|
323
323
|
try {
|
|
324
|
-
const
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
data =
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
324
|
+
const collected = [];
|
|
325
|
+
const cursors = new Set();
|
|
326
|
+
for (let page = 0; page < 100; page += 1) {
|
|
327
|
+
const response = await (input.fetchFn ?? fetch)(url, {
|
|
328
|
+
method: 'GET',
|
|
329
|
+
headers: providerModelsHeaders(input.protocol, input.apiKey),
|
|
330
|
+
...input.requestInit,
|
|
331
|
+
signal: controller.signal,
|
|
332
|
+
redirect: 'error',
|
|
333
|
+
});
|
|
334
|
+
const latencyMs = Date.now() - start;
|
|
335
|
+
const rawText = await response.text();
|
|
336
|
+
let data = {};
|
|
337
|
+
let parseError;
|
|
338
|
+
try {
|
|
339
|
+
data = rawText ? JSON.parse(rawText) : {};
|
|
340
|
+
}
|
|
341
|
+
catch (err) {
|
|
342
|
+
// JSON.parse only ever throws a SyntaxError (an Error); the cast
|
|
343
|
+
// documents that rather than adding an untestable non-Error branch.
|
|
344
|
+
parseError = err.message;
|
|
345
|
+
}
|
|
346
|
+
if (!response.ok) {
|
|
347
|
+
const detail = parseError
|
|
348
|
+
? rawText.trim().slice(0, 240) || parseError
|
|
349
|
+
: extractProviderErrorDetail(data, rawText);
|
|
350
|
+
return {
|
|
351
|
+
ok: false,
|
|
352
|
+
kind: statusToKind(response.status),
|
|
353
|
+
latencyMs,
|
|
354
|
+
status: response.status,
|
|
355
|
+
detail: redactSecrets({ input: detail }, { exactSecrets: [input.apiKey] }),
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
if (parseError) {
|
|
359
|
+
return {
|
|
360
|
+
ok: false,
|
|
361
|
+
kind: 'unknown',
|
|
362
|
+
latencyMs,
|
|
363
|
+
status: response.status,
|
|
364
|
+
detail: redactSecrets({ input: parseError }, { exactSecrets: [input.apiKey] }),
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
// Safe: `url` above only resolves for the five protocols
|
|
368
|
+
// `ModelListProtocol` covers (providerModelsUrl throws for every other
|
|
369
|
+
// ConnectionTestProtocol, and azure/bedrock already returned above).
|
|
370
|
+
collected.push(...extractModels(input.protocol, data));
|
|
371
|
+
const envelope = data && typeof data === 'object' ? data : {};
|
|
372
|
+
const cursor = input.protocol === 'google' && typeof envelope.nextPageToken === 'string' ? envelope.nextPageToken
|
|
373
|
+
: envelope.has_more === true && typeof envelope.last_id === 'string' ? envelope.last_id
|
|
374
|
+
: typeof envelope.next_cursor === 'string' ? envelope.next_cursor : undefined;
|
|
375
|
+
if (envelope.has_more === true && !cursor)
|
|
376
|
+
return { ok: false, kind: 'unknown', latencyMs, detail: 'Provider omitted its pagination cursor.' };
|
|
377
|
+
if (cursor) {
|
|
378
|
+
if (cursors.has(cursor))
|
|
379
|
+
return { ok: false, kind: 'unknown', latencyMs, detail: 'Provider repeated a pagination cursor.' };
|
|
380
|
+
cursors.add(cursor);
|
|
381
|
+
const next = new URL(url);
|
|
382
|
+
next.searchParams.set(input.protocol === 'google' ? 'pageToken' : input.protocol === 'anthropic' ? 'after_id' : 'cursor', cursor);
|
|
383
|
+
url = next.toString();
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
const models = uniqueModels(collected);
|
|
387
|
+
if (models.length === 0) {
|
|
388
|
+
return {
|
|
389
|
+
ok: false,
|
|
390
|
+
kind: 'no_models',
|
|
391
|
+
latencyMs,
|
|
392
|
+
status: response.status,
|
|
393
|
+
detail: 'Provider returned no usable text-generation models.',
|
|
394
|
+
};
|
|
395
|
+
}
|
|
369
396
|
return {
|
|
370
|
-
ok:
|
|
371
|
-
kind: '
|
|
397
|
+
ok: true,
|
|
398
|
+
kind: 'success',
|
|
372
399
|
latencyMs,
|
|
373
400
|
status: response.status,
|
|
374
|
-
|
|
401
|
+
models,
|
|
375
402
|
};
|
|
376
403
|
}
|
|
377
|
-
return {
|
|
378
|
-
ok: true,
|
|
379
|
-
kind: 'success',
|
|
380
|
-
latencyMs,
|
|
381
|
-
status: response.status,
|
|
382
|
-
models,
|
|
383
|
-
};
|
|
404
|
+
return { ok: false, kind: 'unknown', latencyMs: Date.now() - start, detail: 'Provider pagination exceeded its safety limit.' };
|
|
384
405
|
}
|
|
385
406
|
catch (err) {
|
|
386
407
|
const latencyMs = Date.now() - start;
|
|
@@ -1,49 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
* provider stream — the response body a call to the Anthropic Messages API
|
|
6
|
-
* or the OpenAI Chat Completions API sends back when `stream: true` is
|
|
7
|
-
* requested. This is deliberately not `@jini-ai/http-kit`'s `sse.ts`: that module
|
|
8
|
-
* is the OUTBOUND channel a route uses to push events to a browser client
|
|
9
|
-
* (bounded queue, backpressure, `Last-Event-ID` replay). This module has
|
|
10
|
-
* none of that — it only turns a raw byte/text stream into `{event, data}`
|
|
11
|
-
* frames per the SSE wire format (`text/event-stream`, RFC-ish: fields
|
|
12
|
-
* separated by `\n`, records separated by a blank line), so a provider-
|
|
13
|
-
* specific turn-runner (`anthropic-messages.ts`, `openai-chat.ts`) can
|
|
14
|
-
* `JSON.parse` each frame's `data` field without re-deriving line/record
|
|
15
|
-
* framing itself.
|
|
16
|
-
*
|
|
17
|
-
* New file, not a port — chat.ts's origin used the Node `fetch` global's
|
|
18
|
-
* response body directly with ad hoc inline buffering per call site; this
|
|
19
|
-
* factors that concern into one shared, independently-tested primitive so
|
|
20
|
-
* both provider turn-runners consume the same framing logic (the same
|
|
21
|
-
* "shared mechanism, one implementation" discipline `@jini-ai/http-kit`'s
|
|
22
|
-
* `sse.ts`/`origin-validation.ts` already apply to their own domains).
|
|
23
|
-
*/
|
|
24
|
-
/** One decoded SSE record. `event` is `null` when the record had no `event:` line (OpenAI's Chat Completions stream never sends one; every `data:` line is implicitly a plain message). `data` is the joined value of every `data:` line in the record (multi-line `data:` fields are joined with `\n`, per the SSE spec). */
|
|
25
|
-
export interface DecodedSseEvent {
|
|
26
|
-
readonly event: string | null;
|
|
27
|
-
readonly data: string;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Decodes an inbound byte/text stream into SSE records. Accepts either
|
|
31
|
-
* `Uint8Array` chunks (a real `fetch` response body) or `string` chunks (test
|
|
32
|
-
* fixtures, or any caller that already has decoded text) in the same
|
|
33
|
-
* iterable — this keeps unit tests free of any need to construct a real web
|
|
34
|
-
* `ReadableStream`, matching this package's existing `fetch`-mocking
|
|
35
|
-
* convention (`vi.stubGlobal('fetch', ...)`, see `model-catalog.test.ts`).
|
|
36
|
-
*
|
|
37
|
-
* Tolerant per the SSE spec: accepts both `\n` and `\r\n` line endings,
|
|
38
|
-
* ignores comment lines (leading `:`) and unrecognized field names (`id`/
|
|
39
|
-
* `retry` are parsed by real SSE clients for reconnect bookkeeping, which is
|
|
40
|
-
* meaningless for a single proxied request/response pair, so this decoder
|
|
41
|
-
* intentionally drops them), and flushes a trailing unterminated record —
|
|
42
|
-
* even one whose very last line has no trailing `\n` at all — once the
|
|
43
|
-
* source iterable ends, so a provider closing the connection immediately
|
|
44
|
-
* after its last byte never silently loses that last record.
|
|
45
|
-
*/
|
|
46
|
-
export declare function decodeSseStream({ source }: {
|
|
47
|
-
source: AsyncIterable<Uint8Array | string>;
|
|
48
|
-
}): AsyncGenerator<DecodedSseEvent>;
|
|
1
|
+
/** Compatibility entry. Inbound SSE framing is shared with CLI consumers through core's
|
|
2
|
+
* dependency-free primitives; providers keep their JSON interpretation and select the exported EOF policy. */
|
|
3
|
+
export { decodeSseFrames, decodeSseStream, parseSseRecord } from '@jini-ai/core/primitives';
|
|
4
|
+
export type { DecodedSseEvent, DecodedSseFrame, SseFramingOptions } from '@jini-ai/core/primitives';
|
|
49
5
|
//# sourceMappingURL=sse-decode.d.ts.map
|
|
@@ -1,109 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
|
|
4
|
-
* Minimal, tolerant Server-Sent-Events *frame decoder* for an INBOUND
|
|
5
|
-
* provider stream — the response body a call to the Anthropic Messages API
|
|
6
|
-
* or the OpenAI Chat Completions API sends back when `stream: true` is
|
|
7
|
-
* requested. This is deliberately not `@jini-ai/http-kit`'s `sse.ts`: that module
|
|
8
|
-
* is the OUTBOUND channel a route uses to push events to a browser client
|
|
9
|
-
* (bounded queue, backpressure, `Last-Event-ID` replay). This module has
|
|
10
|
-
* none of that — it only turns a raw byte/text stream into `{event, data}`
|
|
11
|
-
* frames per the SSE wire format (`text/event-stream`, RFC-ish: fields
|
|
12
|
-
* separated by `\n`, records separated by a blank line), so a provider-
|
|
13
|
-
* specific turn-runner (`anthropic-messages.ts`, `openai-chat.ts`) can
|
|
14
|
-
* `JSON.parse` each frame's `data` field without re-deriving line/record
|
|
15
|
-
* framing itself.
|
|
16
|
-
*
|
|
17
|
-
* New file, not a port — chat.ts's origin used the Node `fetch` global's
|
|
18
|
-
* response body directly with ad hoc inline buffering per call site; this
|
|
19
|
-
* factors that concern into one shared, independently-tested primitive so
|
|
20
|
-
* both provider turn-runners consume the same framing logic (the same
|
|
21
|
-
* "shared mechanism, one implementation" discipline `@jini-ai/http-kit`'s
|
|
22
|
-
* `sse.ts`/`origin-validation.ts` already apply to their own domains).
|
|
23
|
-
*/
|
|
24
|
-
/**
|
|
25
|
-
* Decodes an inbound byte/text stream into SSE records. Accepts either
|
|
26
|
-
* `Uint8Array` chunks (a real `fetch` response body) or `string` chunks (test
|
|
27
|
-
* fixtures, or any caller that already has decoded text) in the same
|
|
28
|
-
* iterable — this keeps unit tests free of any need to construct a real web
|
|
29
|
-
* `ReadableStream`, matching this package's existing `fetch`-mocking
|
|
30
|
-
* convention (`vi.stubGlobal('fetch', ...)`, see `model-catalog.test.ts`).
|
|
31
|
-
*
|
|
32
|
-
* Tolerant per the SSE spec: accepts both `\n` and `\r\n` line endings,
|
|
33
|
-
* ignores comment lines (leading `:`) and unrecognized field names (`id`/
|
|
34
|
-
* `retry` are parsed by real SSE clients for reconnect bookkeeping, which is
|
|
35
|
-
* meaningless for a single proxied request/response pair, so this decoder
|
|
36
|
-
* intentionally drops them), and flushes a trailing unterminated record —
|
|
37
|
-
* even one whose very last line has no trailing `\n` at all — once the
|
|
38
|
-
* source iterable ends, so a provider closing the connection immediately
|
|
39
|
-
* after its last byte never silently loses that last record.
|
|
40
|
-
*/
|
|
41
|
-
export async function* decodeSseStream({ source }) {
|
|
42
|
-
const decoder = new TextDecoder();
|
|
43
|
-
let buffer = '';
|
|
44
|
-
let eventType = null;
|
|
45
|
-
let dataLines = [];
|
|
46
|
-
let sawAnyField = false;
|
|
47
|
-
/** Processes one already-`\r`-stripped line, mutating the in-progress record. Returns the completed record when `line` is the blank line terminating a non-empty record; `null` otherwise (including a blank line with no preceding fields, which starts no record at all). */
|
|
48
|
-
function handleLine(line) {
|
|
49
|
-
if (line === '') {
|
|
50
|
-
if (!sawAnyField)
|
|
51
|
-
return null;
|
|
52
|
-
const completed = { event: eventType, data: dataLines.join('\n') };
|
|
53
|
-
eventType = null;
|
|
54
|
-
dataLines = [];
|
|
55
|
-
sawAnyField = false;
|
|
56
|
-
return completed;
|
|
57
|
-
}
|
|
58
|
-
if (line.startsWith(':'))
|
|
59
|
-
return null; // comment line, per spec
|
|
60
|
-
const colonIndex = line.indexOf(':');
|
|
61
|
-
const field = colonIndex === -1 ? line : line.slice(0, colonIndex);
|
|
62
|
-
let value = colonIndex === -1 ? '' : line.slice(colonIndex + 1);
|
|
63
|
-
if (value.startsWith(' '))
|
|
64
|
-
value = value.slice(1);
|
|
65
|
-
if (field === 'event') {
|
|
66
|
-
eventType = value;
|
|
67
|
-
sawAnyField = true;
|
|
68
|
-
}
|
|
69
|
-
else if (field === 'data') {
|
|
70
|
-
dataLines.push(value);
|
|
71
|
-
sawAnyField = true;
|
|
72
|
-
}
|
|
73
|
-
// Every other field name (id/retry/anything a future provider adds) is
|
|
74
|
-
// intentionally ignored — see module doc.
|
|
75
|
-
return null;
|
|
76
|
-
}
|
|
77
|
-
function* drainCompleteLines() {
|
|
78
|
-
let newlineIndex;
|
|
79
|
-
while ((newlineIndex = buffer.indexOf('\n')) !== -1) {
|
|
80
|
-
let line = buffer.slice(0, newlineIndex);
|
|
81
|
-
buffer = buffer.slice(newlineIndex + 1);
|
|
82
|
-
if (line.endsWith('\r'))
|
|
83
|
-
line = line.slice(0, -1);
|
|
84
|
-
const completed = handleLine(line);
|
|
85
|
-
if (completed)
|
|
86
|
-
yield completed;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
for await (const chunk of source) {
|
|
90
|
-
buffer += typeof chunk === 'string' ? chunk : decoder.decode(chunk, { stream: true });
|
|
91
|
-
yield* drainCompleteLines();
|
|
92
|
-
}
|
|
93
|
-
buffer += decoder.decode();
|
|
94
|
-
yield* drainCompleteLines();
|
|
95
|
-
// Flush whatever is left: either a trailing unterminated line (no final
|
|
96
|
-
// `\n` at all — `buffer` still holds it, never having been handed to
|
|
97
|
-
// `handleLine`), or a fully-parsed-but-not-blank-line-terminated record
|
|
98
|
-
// (`buffer` is empty, but `sawAnyField` is true from lines already
|
|
99
|
-
// processed above).
|
|
100
|
-
if (buffer.length > 0) {
|
|
101
|
-
const completed = handleLine(buffer.endsWith('\r') ? buffer.slice(0, -1) : buffer);
|
|
102
|
-
if (completed)
|
|
103
|
-
yield completed;
|
|
104
|
-
}
|
|
105
|
-
if (sawAnyField) {
|
|
106
|
-
yield { event: eventType, data: dataLines.join('\n') };
|
|
107
|
-
}
|
|
108
|
-
}
|
|
1
|
+
/** Compatibility entry. Inbound SSE framing is shared with CLI consumers through core's
|
|
2
|
+
* dependency-free primitives; providers keep their JSON interpretation and select the exported EOF policy. */
|
|
3
|
+
export { decodeSseFrames, decodeSseStream, parseSseRecord } from '@jini-ai/core/primitives';
|
|
109
4
|
//# sourceMappingURL=sse-decode.js.map
|
package/dist/qoder-stream.d.ts
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module qoder-stream
|
|
3
3
|
*
|
|
4
|
-
* Ported verbatim from OD's `apps/daemon/src/runtimes/qoder-stream.ts`
|
|
5
|
-
* (only `node:buffer` as a dependency). See `archived provenance ledger`.
|
|
6
|
-
*
|
|
7
4
|
* Parses Qoder CLI's `--output-format stream-json` JSONL stream into the
|
|
8
5
|
* small event set consumed by the chat UI. Qoder's top-level records are
|
|
9
6
|
* wrapper objects (`system`, `assistant`, `result`) with adapter-specific
|
package/dist/qoder-stream.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module qoder-stream
|
|
3
3
|
*
|
|
4
|
-
* Ported verbatim from OD's `apps/daemon/src/runtimes/qoder-stream.ts`
|
|
5
|
-
* (only `node:buffer` as a dependency). See `archived provenance ledger`.
|
|
6
|
-
*
|
|
7
4
|
* Parses Qoder CLI's `--output-format stream-json` JSONL stream into the
|
|
8
5
|
* small event set consumed by the chat UI. Qoder's top-level records are
|
|
9
6
|
* wrapper objects (`system`, `assistant`, `result`) with adapter-specific
|
package/dist/registry.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export declare function getAgentDef({ id }: {
|
|
|
10
10
|
* def, per its own `externalMcpInjection` declaration (`types.ts`'s own doc names the six wired
|
|
11
11
|
* strategies and the defs that leave the field `undefined` because the CLI has no mechanism to
|
|
12
12
|
* receive one — `aider`, `amp`, `copilot`, `crush`, `cursor-agent`, `deepseek`, `droid`,
|
|
13
|
-
* `
|
|
13
|
+
* `grok-build`, `pi`, `qoder`, and `qwen` today, each documenting why in its own def file).
|
|
14
14
|
*
|
|
15
15
|
* This is the single seam a tool-availability UI (e.g. the chat runtime picker's "No tools" badge)
|
|
16
16
|
* should read instead of hardcoding a runtime-id list: that list goes stale the moment a def gains
|
package/dist/registry.js
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* can reintroduce a de-branded, sandbox-free local-profile loader as an
|
|
18
18
|
* injected port if a consumer needs it. See `archived provenance ledger`.
|
|
19
19
|
*/
|
|
20
|
-
import { aiderAgentDef, ampAgentDef, amrAgentDef, antigravityAgentDef, auggieAgentDef, claudeAgentDef, clineAgentDef, codebuddyAgentDef, codexAgentDef, copilotAgentDef, crushAgentDef, cursorAgentDef, deepseekAgentDef, devinAgentDef, droidAgentDef,
|
|
20
|
+
import { aiderAgentDef, ampAgentDef, amrAgentDef, antigravityAgentDef, auggieAgentDef, claudeAgentDef, clineAgentDef, codebuddyAgentDef, codexAgentDef, copilotAgentDef, crushAgentDef, cursorAgentDef, deepseekAgentDef, devinAgentDef, droidAgentDef, gooseAgentDef, grokBuildAgentDef, hermesAgentDef, kiloAgentDef, kimiAgentDef, kiroAgentDef, mimoAgentDef, opencodeAgentDef, piAgentDef, qoderAgentDef, qwenAgentDef, reasonixAgentDef, traeCliAgentDef, vibeAgentDef, } from './defs/index.js';
|
|
21
21
|
export const BASE_AGENT_DEFS = [
|
|
22
22
|
amrAgentDef,
|
|
23
23
|
claudeAgentDef,
|
|
@@ -30,7 +30,7 @@ export const BASE_AGENT_DEFS = [
|
|
|
30
30
|
kimiAgentDef,
|
|
31
31
|
cursorAgentDef,
|
|
32
32
|
qwenAgentDef,
|
|
33
|
-
|
|
33
|
+
// Gemini CLI retired 2026-10-06; Antigravity (agy) is the Google CLI path.
|
|
34
34
|
qoderAgentDef,
|
|
35
35
|
copilotAgentDef,
|
|
36
36
|
ampAgentDef,
|
|
@@ -67,7 +67,7 @@ export function getAgentDef({ id }) {
|
|
|
67
67
|
* def, per its own `externalMcpInjection` declaration (`types.ts`'s own doc names the six wired
|
|
68
68
|
* strategies and the defs that leave the field `undefined` because the CLI has no mechanism to
|
|
69
69
|
* receive one — `aider`, `amp`, `copilot`, `crush`, `cursor-agent`, `deepseek`, `droid`,
|
|
70
|
-
* `
|
|
70
|
+
* `grok-build`, `pi`, `qoder`, and `qwen` today, each documenting why in its own def file).
|
|
71
71
|
*
|
|
72
72
|
* This is the single seam a tool-availability UI (e.g. the chat runtime picker's "No tools" badge)
|
|
73
73
|
* should read instead of hardcoding a runtime-id list: that list goes stale the moment a def gains
|
package/dist/resolution.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module resolution
|
|
3
|
-
*
|
|
4
|
-
* Resolve the absolute path of an agent's binary on the current PATH, by
|
|
5
|
-
* agent id, from the registry. Ported verbatim from OD's
|
|
6
|
-
* `apps/daemon/src/runtimes/resolution.ts`.
|
|
3
|
+
* Resolve an agent's absolute executable path from the current PATH and registry.
|
|
7
4
|
*/
|
|
8
5
|
import { getAgentDef } from './registry.js';
|
|
9
6
|
import { resolveAgentExecutable } from './executables.js';
|
|
@@ -9,11 +9,6 @@
|
|
|
9
9
|
* stream handlers that can track message boundaries (Claude, Copilot,
|
|
10
10
|
* Qoder, OpenCode/Codex, Pi, ACP). Returns `{ feedText, contaminated,
|
|
11
11
|
* warningEvent }`.
|
|
12
|
-
*
|
|
13
|
-
* Ported verbatim from OD's `apps/daemon/src/role-marker-guard.ts` (a
|
|
14
|
-
* top-level daemon file, not under `runtimes/`, but consumed by
|
|
15
|
-
* `claude-stream.ts` and self-contained with no product coupling — see
|
|
16
|
-
* `archived provenance ledger`).
|
|
17
12
|
*/
|
|
18
13
|
export declare const FABRICATED_ROLE_MARKER_RE: RegExp;
|
|
19
14
|
export type RoleMarkerWarningEvent = {
|
|
@@ -9,11 +9,6 @@
|
|
|
9
9
|
* stream handlers that can track message boundaries (Claude, Copilot,
|
|
10
10
|
* Qoder, OpenCode/Codex, Pi, ACP). Returns `{ feedText, contaminated,
|
|
11
11
|
* warningEvent }`.
|
|
12
|
-
*
|
|
13
|
-
* Ported verbatim from OD's `apps/daemon/src/role-marker-guard.ts` (a
|
|
14
|
-
* top-level daemon file, not under `runtimes/`, but consumed by
|
|
15
|
-
* `claude-stream.ts` and self-contained with no product coupling — see
|
|
16
|
-
* `archived provenance ledger`).
|
|
17
12
|
*/
|
|
18
13
|
// Regex matching fabricated role-marker lines injected by the model into
|
|
19
14
|
// its own output. Anchored to start-of-line via (?:^|\n) so we don't
|
package/dist/telemetry-sink.d.ts
CHANGED
|
@@ -1,19 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module telemetry-sink
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* `runAskedUserQuestion` → `run_finished.asked_user_question`,
|
|
7
|
-
* `deriveActivationMilestones`'s PostHog `$set_once` person-property
|
|
8
|
-
* scheme) and `run-lifecycle-analytics.ts` (not present as a separate file
|
|
9
|
-
* on this branch — its concerns are folded into `run-artifacts.ts` here).
|
|
10
|
-
* None of that OD-schema logic is ported.
|
|
11
|
-
*
|
|
12
|
-
* Per r1b §1b: the engine emits a generic run-lifecycle event stream; the
|
|
13
|
-
* host maps it to its own analytics schema. `data` is intentionally
|
|
14
|
-
* `Record<string, unknown>` — artifactCount, askedUserQuestion, stopReason,
|
|
15
|
-
* etc. are opaque to the engine, populated by whatever
|
|
16
|
-
* `ArtifactTaxonomy`/`PromptAugmenter` implementation the host wires in.
|
|
3
|
+
* The engine emits generic lifecycle events; hosts map them to their own analytics schema.
|
|
4
|
+
* data is opaque Record<string, unknown>: metrics supplied by ArtifactTaxonomy/PromptAugmenter
|
|
5
|
+
* must not install a product's analytics identity or event schema in the engine.
|
|
17
6
|
*/
|
|
18
7
|
export interface RunLifecycleEvent {
|
|
19
8
|
type: 'run_started' | 'run_finished' | 'run_failed' | 'tool_use' | 'artifact_written';
|
package/dist/types.d.ts
CHANGED
|
@@ -11,12 +11,15 @@
|
|
|
11
11
|
* Ported from OD's `apps/daemon/src/runtimes/types.ts`. Product-neutral
|
|
12
12
|
* as found — see `archived provenance ledger` for the full provenance table.
|
|
13
13
|
*/
|
|
14
|
+
import type { AgentModelDiscoveryPort, ModelCatalogSnapshot, DefaultModelResolution, ModelIdentityKind } from './model-discovery-types.js';
|
|
14
15
|
import type { ExecFileOptions } from 'node:child_process';
|
|
15
16
|
import type { AgentDiagnostic } from '@jini-ai/protocol';
|
|
16
17
|
export type RuntimeEnv = NodeJS.ProcessEnv | Record<string, string>;
|
|
17
18
|
export type RuntimeModelOption = {
|
|
18
19
|
id: string;
|
|
19
20
|
label: string;
|
|
21
|
+
identityKind?: ModelIdentityKind;
|
|
22
|
+
resolvedId?: string;
|
|
20
23
|
/**
|
|
21
24
|
* The reasoning-effort levels THIS model supports, when the runtime's own catalog reports them
|
|
22
25
|
* per model rather than per agent.
|
|
@@ -258,12 +261,14 @@ export type RuntimeLockHold = {
|
|
|
258
261
|
export type RuntimeLock = {
|
|
259
262
|
readonly acquire: (context: RuntimeLockAcquireContext) => Promise<RuntimeLockHold>;
|
|
260
263
|
};
|
|
261
|
-
export type RuntimeAgentDef = {
|
|
264
|
+
export type RuntimeAgentDef = Partial<AgentModelDiscoveryPort> & {
|
|
262
265
|
id: string;
|
|
263
266
|
name: string;
|
|
264
267
|
bin: string;
|
|
265
268
|
versionArgs: string[];
|
|
266
269
|
fallbackModels: RuntimeModelOption[];
|
|
270
|
+
/** False when the native CLI exposes only routing modes and cannot pin a concrete ID. */
|
|
271
|
+
supportsConcreteModelSelection?: boolean;
|
|
267
272
|
/**
|
|
268
273
|
* `YYYY-MM-DD` — when this def's hardcoded `fallbackModels` list was last checked against the
|
|
269
274
|
* vendor's own current list.
|
|
@@ -397,9 +402,11 @@ export type RuntimeAgentDef = {
|
|
|
397
402
|
stdoutPolicy?: RuntimeStdoutPolicy;
|
|
398
403
|
runtimeLock?: RuntimeLock;
|
|
399
404
|
};
|
|
400
|
-
export type DetectedAgent = Omit<RuntimeAgentDef, 'buildArgs' | 'listModels' | 'fetchModels' | 'deriveReasoningOptions' | 'fallbackModels' | 'fallbackModelsAssertedAt' | 'helpArgs' | 'capabilityFlags' | 'fallbackBins' | 'versionProbeTimeoutMs' | 'maxPromptArgBytes' | 'env' | 'inactivityTimeoutMs' | 'authProbe' | 'needsAgentLogFile' | 'stdoutPolicy' | 'runtimeLock'> & {
|
|
405
|
+
export type DetectedAgent = Omit<RuntimeAgentDef, 'discoverModels' | 'resolveDefaultModel' | 'buildArgs' | 'listModels' | 'fetchModels' | 'deriveReasoningOptions' | 'fallbackModels' | 'fallbackModelsAssertedAt' | 'helpArgs' | 'capabilityFlags' | 'fallbackBins' | 'versionProbeTimeoutMs' | 'maxPromptArgBytes' | 'env' | 'inactivityTimeoutMs' | 'authProbe' | 'needsAgentLogFile' | 'stdoutPolicy' | 'runtimeLock'> & {
|
|
401
406
|
models: RuntimeModelOption[];
|
|
402
407
|
modelsSource: RuntimeModelSource;
|
|
408
|
+
modelCatalog?: ModelCatalogSnapshot;
|
|
409
|
+
defaultModelResolution?: DefaultModelResolution;
|
|
403
410
|
available: boolean;
|
|
404
411
|
authStatus?: 'ok' | 'missing' | 'unknown';
|
|
405
412
|
authMessage?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jini-ai/agent-runtime",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "Coding-agent runtime adapters: runtime registry, detection, launch, stream parsers, and the ACP/pi-rpc subprocess transport.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -74,14 +74,35 @@
|
|
|
74
74
|
"access": "public",
|
|
75
75
|
"registry": "https://registry.npmjs.org"
|
|
76
76
|
},
|
|
77
|
-
"
|
|
77
|
+
"devDependencies": {
|
|
78
|
+
"@vitest/coverage-v8": "^2.1.9",
|
|
78
79
|
"@jini-ai/core": "^0.4.0",
|
|
79
|
-
"@jini-ai/
|
|
80
|
+
"@jini-ai/oauth": "^0.2.1",
|
|
81
|
+
"@jini-ai/platform": "^0.5.2",
|
|
82
|
+
"@jini-ai/protocol": "^0.4.2"
|
|
83
|
+
},
|
|
84
|
+
"dependencies": {
|
|
85
|
+
"@jini-ai/core": "^0.4.2"
|
|
86
|
+
},
|
|
87
|
+
"peerDependencies": {
|
|
88
|
+
"@github/copilot-sdk": "*",
|
|
89
|
+
"@jini-ai/oauth": "^0.2.0",
|
|
80
90
|
"@jini-ai/platform": "^0.5.1",
|
|
81
|
-
"@jini-ai/
|
|
91
|
+
"@jini-ai/protocol": "^0.4.1"
|
|
82
92
|
},
|
|
83
|
-
"
|
|
84
|
-
"@
|
|
93
|
+
"peerDependenciesMeta": {
|
|
94
|
+
"@github/copilot-sdk": {
|
|
95
|
+
"optional": true
|
|
96
|
+
},
|
|
97
|
+
"@jini-ai/oauth": {
|
|
98
|
+
"optional": true
|
|
99
|
+
},
|
|
100
|
+
"@jini-ai/platform": {
|
|
101
|
+
"optional": true
|
|
102
|
+
},
|
|
103
|
+
"@jini-ai/protocol": {
|
|
104
|
+
"optional": true
|
|
105
|
+
}
|
|
85
106
|
},
|
|
86
107
|
"scripts": {
|
|
87
108
|
"build": "tsc -p tsconfig.json",
|