@addai/node 0.30.12 → 0.30.14
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/auto-update.d.ts +3 -0
- package/dist/auto-update.js +15 -0
- package/dist/capabilities.d.ts +31 -6
- package/dist/capabilities.js +48 -26
- package/dist/claude-models.d.ts +71 -0
- package/dist/claude-models.js +330 -0
- package/dist/claude-print.d.ts +15 -0
- package/dist/claude-print.js +16 -0
- package/dist/codex-models.d.ts +81 -0
- package/dist/codex-models.js +385 -0
- package/dist/codex-spawn.d.ts +14 -8
- package/dist/codex-spawn.js +30 -10
- package/dist/command-runner.js +31 -9
- package/dist/desktop/docker.js +2 -0
- package/dist/desktop/manager.d.ts +2 -1
- package/dist/desktop/manager.js +51 -1
- package/dist/desktop/provider.d.ts +1 -1
- package/dist/desktop/provider.js +2 -0
- package/dist/desktop/relay-client.js +7 -0
- package/dist/desktop/spec.d.ts +2 -0
- package/dist/direct/aios-bridge.d.ts +13 -0
- package/dist/direct/aios-bridge.js +177 -0
- package/dist/direct/aios-mcp.d.ts +2 -0
- package/dist/direct/aios-mcp.js +132 -0
- package/dist/direct/aios-tools.d.ts +351 -0
- package/dist/direct/aios-tools.js +120 -0
- package/dist/direct/board-chat-provider.d.ts +64 -0
- package/dist/direct/board-chat-provider.js +151 -0
- package/dist/direct/board-chat.d.ts +40 -0
- package/dist/direct/board-chat.js +414 -0
- package/dist/direct/config.d.ts +2 -0
- package/dist/direct/config.js +60 -0
- package/dist/direct/launch.d.ts +14 -0
- package/dist/direct/launch.js +121 -0
- package/dist/direct/protocol.d.ts +46 -0
- package/dist/direct/protocol.js +84 -0
- package/dist/direct/relay-main.d.ts +1 -0
- package/dist/direct/relay-main.js +21 -0
- package/dist/direct/relay.d.ts +26 -0
- package/dist/direct/relay.js +334 -0
- package/dist/direct/sessions.d.ts +61 -0
- package/dist/direct/sessions.js +368 -0
- package/dist/direct/supervisor.d.ts +9 -0
- package/dist/direct/supervisor.js +137 -0
- package/dist/direct/terminal.d.ts +1 -0
- package/dist/direct/terminal.js +106 -0
- package/dist/direct/worker.d.ts +1 -0
- package/dist/direct/worker.js +278 -0
- package/dist/entitybox/container-action.cjs +85 -0
- package/dist/entitybox/container-watchdog.cjs +70 -0
- package/dist/entitybox/model-entry.d.ts +3 -0
- package/dist/entitybox/model-entry.js +233 -0
- package/dist/entitybox/model-mcp-proxy.d.ts +3 -0
- package/dist/entitybox/model-mcp-proxy.js +85 -0
- package/dist/entitybox-application-boundary.d.ts +59 -0
- package/dist/entitybox-application-boundary.js +161 -0
- package/dist/entitybox-application-guard-core.d.ts +44 -0
- package/dist/entitybox-application-guard-core.js +164 -0
- package/dist/entitybox-application-guard-process.d.ts +1 -0
- package/dist/entitybox-application-guard-process.js +83 -0
- package/dist/entitybox-application-guard.d.ts +46 -0
- package/dist/entitybox-application-guard.js +239 -0
- package/dist/entitybox-capacity-health-host.d.ts +12 -0
- package/dist/entitybox-capacity-health-host.js +80 -0
- package/dist/entitybox-capacity-health-worker.d.ts +22 -0
- package/dist/entitybox-capacity-health-worker.js +168 -0
- package/dist/entitybox-capacity-host.d.ts +17 -0
- package/dist/entitybox-capacity-host.js +155 -0
- package/dist/entitybox-capacity-owner-process.d.ts +1 -0
- package/dist/entitybox-capacity-owner-process.js +32 -0
- package/dist/entitybox-capacity-owner.d.ts +16 -0
- package/dist/entitybox-capacity-owner.js +90 -0
- package/dist/entitybox-capacity-programs.d.ts +7 -0
- package/dist/entitybox-capacity-programs.js +49 -0
- package/dist/entitybox-capacity-provisioner.d.ts +82 -0
- package/dist/entitybox-capacity-provisioner.js +404 -0
- package/dist/entitybox-capacity-publication.d.ts +29 -0
- package/dist/entitybox-capacity-publication.js +199 -0
- package/dist/entitybox-capacity-registration.d.ts +36 -0
- package/dist/entitybox-capacity-registration.js +75 -0
- package/dist/entitybox-capacity-worker.d.ts +29 -0
- package/dist/entitybox-capacity-worker.js +113 -0
- package/dist/entitybox-computer-task.d.ts +69 -0
- package/dist/entitybox-computer-task.js +176 -0
- package/dist/entitybox-controller-recovery.d.ts +40 -0
- package/dist/entitybox-controller-recovery.js +156 -0
- package/dist/entitybox-desktop-action-server.d.ts +34 -0
- package/dist/entitybox-desktop-action-server.js +176 -0
- package/dist/entitybox-desktop-admission.d.ts +32 -0
- package/dist/entitybox-desktop-admission.js +79 -0
- package/dist/entitybox-display-binding.d.ts +13 -0
- package/dist/entitybox-display-binding.js +31 -0
- package/dist/entitybox-execution-container.d.ts +82 -0
- package/dist/entitybox-execution-container.js +450 -0
- package/dist/entitybox-execution-host.d.ts +40 -0
- package/dist/entitybox-execution-host.js +168 -0
- package/dist/entitybox-execution-lease.d.ts +81 -0
- package/dist/entitybox-execution-lease.js +332 -0
- package/dist/entitybox-file-inputs.d.ts +51 -0
- package/dist/entitybox-file-inputs.js +182 -0
- package/dist/entitybox-file-session.d.ts +38 -0
- package/dist/entitybox-file-session.js +82 -0
- package/dist/entitybox-host-process.d.ts +12 -0
- package/dist/entitybox-host-process.js +120 -0
- package/dist/entitybox-install.d.ts +10 -0
- package/dist/entitybox-install.js +40 -0
- package/dist/entitybox-mcp-broker.d.ts +77 -0
- package/dist/entitybox-mcp-broker.js +420 -0
- package/dist/entitybox-mcp-contract.d.ts +10 -0
- package/dist/entitybox-mcp-contract.js +24 -0
- package/dist/entitybox-mcp-guard.d.ts +3 -0
- package/dist/entitybox-mcp-guard.js +167 -0
- package/dist/entitybox-model-artifact.d.ts +9 -0
- package/dist/entitybox-model-artifact.js +83 -0
- package/dist/entitybox-native-services.d.ts +33 -0
- package/dist/entitybox-native-services.js +172 -0
- package/dist/entitybox-operation.d.ts +4 -0
- package/dist/entitybox-operation.js +34 -0
- package/dist/entitybox-provider-broker.d.ts +41 -0
- package/dist/entitybox-provider-broker.js +149 -0
- package/dist/entitybox-queue-request.d.ts +32 -0
- package/dist/entitybox-queue-request.js +141 -0
- package/dist/entitybox-recovery-host.d.ts +12 -0
- package/dist/entitybox-recovery-host.js +80 -0
- package/dist/entitybox-recovery-store.d.ts +33 -0
- package/dist/entitybox-recovery-store.js +150 -0
- package/dist/entitybox-recovery-worker.d.ts +30 -0
- package/dist/entitybox-recovery-worker.js +134 -0
- package/dist/entitybox-vault-provider.d.ts +27 -0
- package/dist/entitybox-vault-provider.js +127 -0
- package/dist/harness-registry.js +3 -1
- package/dist/index.js +72 -38
- package/dist/install.d.ts +14 -2
- package/dist/install.js +115 -10
- package/dist/model-cache.d.ts +38 -0
- package/dist/model-cache.js +137 -0
- package/dist/request-pump.d.ts +3 -0
- package/dist/request-pump.js +21 -7
- package/dist/session-runner.d.ts +8 -1
- package/dist/session-runner.js +48 -3
- package/dist/supabase-client.js +4 -1
- package/package.json +5 -1
- package/scripts/copy-assets.js +4 -2
package/dist/auto-update.d.ts
CHANGED
|
@@ -103,6 +103,9 @@ type ProbeShape = Partial<Record<HarnessId, {
|
|
|
103
103
|
available?: boolean;
|
|
104
104
|
}>>;
|
|
105
105
|
export interface AutoUpdateDeps {
|
|
106
|
+
/** Optional admission gate for direct sessions. Legacy callers keep the existing update path. */
|
|
107
|
+
quiesceDirect?: () => Promise<boolean>;
|
|
108
|
+
releaseDirect?: () => void;
|
|
106
109
|
/** The daemon token — only used to derive this node's slot. */
|
|
107
110
|
token: () => string | null;
|
|
108
111
|
/** True while this node holds a child process for a live run. */
|
package/dist/auto-update.js
CHANGED
|
@@ -143,6 +143,21 @@ function installedHarnesses(probe) {
|
|
|
143
143
|
/** One pass. Exported so `ainode` can be made to do it on demand later, and
|
|
144
144
|
* so a test can drive it without waiting an hour. */
|
|
145
145
|
async function runOnce(d) {
|
|
146
|
+
if (!d.quiesceDirect || shouldRun({ enabled: d.enabled(), busy: d.isBusy(), breakerOpen: d.breakerOpen() })) {
|
|
147
|
+
return runUpdate(d);
|
|
148
|
+
}
|
|
149
|
+
if (!await d.quiesceDirect()) {
|
|
150
|
+
state = { ...state, last_result: 'skipped', skipped_reason: 'busy' };
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
try {
|
|
154
|
+
await runUpdate(d);
|
|
155
|
+
}
|
|
156
|
+
finally {
|
|
157
|
+
d.releaseDirect?.();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
async function runUpdate(d) {
|
|
146
161
|
const skip = shouldRun({ enabled: d.enabled(), busy: d.isBusy(), breakerOpen: d.breakerOpen() });
|
|
147
162
|
if (skip) {
|
|
148
163
|
state = { ...state, last_checked_at: new Date().toISOString(), last_result: 'skipped', skipped_reason: skip };
|
package/dist/capabilities.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import { entityboxFileCapabilities } from './entitybox-file-session';
|
|
1
2
|
import type { EngineInfo } from './desktop/provider';
|
|
3
|
+
import { type ClaudeModelEntry } from './claude-models';
|
|
4
|
+
import { type CodexModelEntry } from './codex-models';
|
|
2
5
|
import { type AutostartState } from './autostart';
|
|
3
6
|
import { type AutoUpdateState } from './auto-update';
|
|
4
7
|
import { type MachineSample } from './machine-metrics';
|
|
@@ -38,16 +41,15 @@ interface FlowsCapability {
|
|
|
38
41
|
max_concurrent: number;
|
|
39
42
|
}
|
|
40
43
|
interface CapabilitiesShape {
|
|
44
|
+
entitybox?: {
|
|
45
|
+
files: NonNullable<ReturnType<typeof entityboxFileCapabilities>>;
|
|
46
|
+
};
|
|
41
47
|
/** Version of @addai/node running. Lets the studio / CodeFlows
|
|
42
48
|
* UIs show "outdated daemon" hints and helps us debug field issues
|
|
43
49
|
* ("which version was this row produced by?"). */
|
|
44
50
|
daemon_version?: string;
|
|
45
|
-
claude: BinaryProbe &
|
|
46
|
-
|
|
47
|
-
};
|
|
48
|
-
codex: BinaryProbe & {
|
|
49
|
-
models?: string[];
|
|
50
|
-
};
|
|
51
|
+
claude: BinaryProbe & ClaudeModelFields;
|
|
52
|
+
codex: BinaryProbe & CodexModelFields;
|
|
51
53
|
kimi: BinaryProbe & {
|
|
52
54
|
models?: string[];
|
|
53
55
|
};
|
|
@@ -80,6 +82,29 @@ interface CapabilitiesShape {
|
|
|
80
82
|
* version silently changes with no explanation. */
|
|
81
83
|
auto_update?: AutoUpdateState;
|
|
82
84
|
}
|
|
85
|
+
/** What the heartbeat says about claude's models. `models` keeps its old
|
|
86
|
+
* shape — plain ids — because Studio and Flows read it as strings; the
|
|
87
|
+
* newer fields sit beside it and older readers simply never look. */
|
|
88
|
+
interface ClaudeModelFields {
|
|
89
|
+
models?: string[];
|
|
90
|
+
/** The CLI's own entries with their names ('Opus 5.5') and alias flags.
|
|
91
|
+
* Built-in extras in `models` have none, and are shown by id. */
|
|
92
|
+
model_catalog?: ClaudeModelEntry[];
|
|
93
|
+
/** 'cli' when the list came from the CLI, 'builtin' when it is the
|
|
94
|
+
* fallback above — so a stale picker can be told apart from a live one. */
|
|
95
|
+
models_source?: 'cli' | 'builtin';
|
|
96
|
+
}
|
|
97
|
+
interface CodexModelFields {
|
|
98
|
+
/** Asked of codex's app-server (codex-models.ts); empty until it answers.
|
|
99
|
+
* There is no built-in list: a blank model — codex's own default — is the
|
|
100
|
+
* one choice that always runs. */
|
|
101
|
+
models?: string[];
|
|
102
|
+
model_catalog?: CodexModelEntry[];
|
|
103
|
+
models_source?: 'cli' | 'builtin';
|
|
104
|
+
/** 'account' when the list is what this node's login can run, 'bundled'
|
|
105
|
+
* when the login was left alone and it is what the CLI ships with. */
|
|
106
|
+
models_scope?: 'account' | 'bundled';
|
|
107
|
+
}
|
|
83
108
|
/** Codex's credential store: $CODEX_HOME (or ~/.codex) + /auth.json. */
|
|
84
109
|
export declare function codexHome(): string;
|
|
85
110
|
/**
|
package/dist/capabilities.js
CHANGED
|
@@ -42,11 +42,14 @@ exports.codexHome = codexHome;
|
|
|
42
42
|
exports.codexAuthFromStore = codexAuthFromStore;
|
|
43
43
|
exports.probeCapabilities = probeCapabilities;
|
|
44
44
|
const engine_1 = require("./desktop/engine");
|
|
45
|
+
const entitybox_file_session_1 = require("./entitybox-file-session");
|
|
45
46
|
const child_process_1 = require("child_process");
|
|
46
47
|
const fs = __importStar(require("fs"));
|
|
47
48
|
const path = __importStar(require("path"));
|
|
48
49
|
const os = __importStar(require("os"));
|
|
49
50
|
const claude_binary_1 = require("./claude-binary");
|
|
51
|
+
const claude_models_1 = require("./claude-models");
|
|
52
|
+
const codex_models_1 = require("./codex-models");
|
|
50
53
|
const kimi_binary_1 = require("./kimi-binary");
|
|
51
54
|
const gemini_binary_1 = require("./gemini-binary");
|
|
52
55
|
const grok_binary_1 = require("./grok-binary");
|
|
@@ -92,25 +95,21 @@ function runCmd(cmd, args, timeoutMs = 5000) {
|
|
|
92
95
|
}
|
|
93
96
|
});
|
|
94
97
|
}
|
|
95
|
-
// Curated model lists baked into the daemon.
|
|
96
|
-
// non-interactive "list models" command, so this stays a constant — but
|
|
97
|
-
// WHAT goes in it is what decides whether the UI's dropdown rots.
|
|
98
|
+
// Curated model lists baked into the daemon.
|
|
98
99
|
//
|
|
99
|
-
//
|
|
100
|
-
//
|
|
101
|
-
//
|
|
102
|
-
//
|
|
103
|
-
//
|
|
100
|
+
// Claude's is now the FLOOR, not the source: the CLI itself is asked which
|
|
101
|
+
// models it offers (claude-models.ts, over the SDK control protocol), so a new
|
|
102
|
+
// Claude model reaches the pickers when a node's CLI updates, not when someone
|
|
103
|
+
// edits this file. This list is what a node reports until that answer arrives
|
|
104
|
+
// or when its CLI cannot give one — and its older pinned ids are kept beside
|
|
105
|
+
// the CLI's answer, which (asked without a login) lists only the aliases.
|
|
104
106
|
//
|
|
105
|
-
//
|
|
106
|
-
//
|
|
107
|
-
// a
|
|
107
|
+
// Do not "fix" the fallback by running `claude models` or `claude config
|
|
108
|
+
// list`. Neither exists (checked to 2.1.304): both strings are read as a
|
|
109
|
+
// PROMPT — the CLI starts a billed session and answers in prose.
|
|
108
110
|
//
|
|
109
|
-
//
|
|
110
|
-
// stale — the CLI resolves each to whatever is current in its tier
|
|
111
|
-
// staleness is exactly what went wrong before: this list was still
|
|
112
|
-
// offering claude-opus-4-1 and claude-sonnet-4-5 long after they were
|
|
113
|
-
// superseded, and no amount of heartbeating fixes a wrong constant.
|
|
111
|
+
// The ALIASES lead the list. They are the only entries that cannot go
|
|
112
|
+
// stale — the CLI resolves each to whatever is current in its tier.
|
|
114
113
|
// Pinned ids follow, newest first, for anyone who must hold one model.
|
|
115
114
|
//
|
|
116
115
|
// Availability is plan-gated (these nodes sign in with claude.ai
|
|
@@ -124,20 +123,17 @@ const CLAUDE_MODELS = [
|
|
|
124
123
|
'haiku',
|
|
125
124
|
'fable',
|
|
126
125
|
// Pinned ids, newest first.
|
|
126
|
+
'claude-opus-5-5',
|
|
127
|
+
'claude-sonnet-5-5',
|
|
128
|
+
'claude-haiku-5-5',
|
|
129
|
+
'claude-fable-5-1',
|
|
127
130
|
'claude-opus-5',
|
|
128
131
|
'claude-sonnet-5',
|
|
129
|
-
'claude-fable-5-1',
|
|
130
132
|
'claude-opus-4-8',
|
|
131
133
|
'claude-opus-4-7',
|
|
132
134
|
'claude-sonnet-4-6',
|
|
133
135
|
'claude-haiku-4-5',
|
|
134
136
|
];
|
|
135
|
-
const CODEX_MODELS = [
|
|
136
|
-
'gpt-5',
|
|
137
|
-
'gpt-5-mini',
|
|
138
|
-
'o4',
|
|
139
|
-
'o4-mini',
|
|
140
|
-
];
|
|
141
137
|
const KIMI_MODELS = [
|
|
142
138
|
'kimi-k2-instruct',
|
|
143
139
|
'kimi-k2-base',
|
|
@@ -178,7 +174,19 @@ async function probeClaude() {
|
|
|
178
174
|
}
|
|
179
175
|
catch { /* fall through unauthed */ }
|
|
180
176
|
}
|
|
181
|
-
|
|
177
|
+
// Asked once per binary and version — the probe never sees the login, so
|
|
178
|
+
// an account change cannot move its answer. Never waits; see
|
|
179
|
+
// claude-models.ts. No default model is reported: a CLI asked without a
|
|
180
|
+
// login cannot say what this node's account defaults to.
|
|
181
|
+
const live = (0, claude_models_1.claudeModelsFor)(bin, `${bin}|${version ?? ''}`);
|
|
182
|
+
return {
|
|
183
|
+
available: true,
|
|
184
|
+
version,
|
|
185
|
+
models: live ? (0, claude_models_1.withBuiltin)(live, CLAUDE_MODELS).models : CLAUDE_MODELS,
|
|
186
|
+
...(live ? { model_catalog: live.catalog } : {}),
|
|
187
|
+
models_source: live ? 'cli' : 'builtin',
|
|
188
|
+
...authShape,
|
|
189
|
+
};
|
|
182
190
|
}
|
|
183
191
|
/** Codex's credential store: $CODEX_HOME (or ~/.codex) + /auth.json. */
|
|
184
192
|
function codexHome() {
|
|
@@ -245,7 +253,18 @@ async function probeCodex() {
|
|
|
245
253
|
else {
|
|
246
254
|
authShape = codexAuthFromStore(codexHome());
|
|
247
255
|
}
|
|
248
|
-
|
|
256
|
+
// Asked once per binary and version, in the background; see codex-models.ts.
|
|
257
|
+
// Its efforts replace the registry's when it answers — they are per model,
|
|
258
|
+
// and newer codex takes xhigh and max.
|
|
259
|
+
const live = (0, codex_models_1.codexModelsFor)(bin, `${bin}|${ver.stdout}`);
|
|
260
|
+
return {
|
|
261
|
+
available: true,
|
|
262
|
+
version: ver.stdout,
|
|
263
|
+
models: live?.models ?? [],
|
|
264
|
+
...(live ? { model_catalog: live.catalog, models_scope: live.scope, efforts: (0, codex_models_1.offeredEfforts)(live) } : {}),
|
|
265
|
+
models_source: live ? 'cli' : 'builtin',
|
|
266
|
+
...authShape,
|
|
267
|
+
};
|
|
249
268
|
}
|
|
250
269
|
async function probeKimi() {
|
|
251
270
|
const bin = (0, kimi_binary_1.findKimiBinary)();
|
|
@@ -475,7 +494,8 @@ async function probeCapabilities() {
|
|
|
475
494
|
// login strategy) so Studio and the TUI render from one source of truth.
|
|
476
495
|
const deco = (id, probe) => ({
|
|
477
496
|
...probe,
|
|
478
|
-
|
|
497
|
+
// A list the CLI gave itself (codex) beats the registry's.
|
|
498
|
+
efforts: probe.efforts?.length ? probe.efforts : harness_registry_1.HARNESSES[id].efforts,
|
|
479
499
|
installable: (0, harness_registry_1.isInstallable)(id),
|
|
480
500
|
login_strategy: harness_registry_1.HARNESSES[id].login.strategy,
|
|
481
501
|
login_methods: [
|
|
@@ -483,7 +503,9 @@ async function probeCapabilities() {
|
|
|
483
503
|
...(harness_registry_1.HARNESSES[id].extraLogins ?? []).map(m => m.method),
|
|
484
504
|
],
|
|
485
505
|
});
|
|
506
|
+
const fileCapability = (0, entitybox_file_session_1.entityboxFileCapabilities)(claude);
|
|
486
507
|
return {
|
|
508
|
+
...(fileCapability ? { entitybox: { files: fileCapability } } : {}),
|
|
487
509
|
daemon_version: readDaemonVersion(),
|
|
488
510
|
autostart: (0, autostart_1.status)(),
|
|
489
511
|
container_engine: containerEngine,
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { type ModelProbeResult } from './model-cache';
|
|
2
|
+
import { type CliInvocation } from './win';
|
|
3
|
+
export interface ClaudeModelEntry {
|
|
4
|
+
/** What goes to `--model`: an alias ('opus') or a full id. */
|
|
5
|
+
id: string;
|
|
6
|
+
/** What the CLI runs for it today — the same as `id` for a full id. */
|
|
7
|
+
resolved: string;
|
|
8
|
+
/** The CLI's own label, e.g. 'Opus 5.5'. */
|
|
9
|
+
name: string;
|
|
10
|
+
/** An alias names a tier, not a version, and moves when the CLI updates. */
|
|
11
|
+
alias: boolean;
|
|
12
|
+
/** Effort levels this model takes, when the CLI says. */
|
|
13
|
+
efforts?: string[];
|
|
14
|
+
}
|
|
15
|
+
export interface ClaudeModelReport {
|
|
16
|
+
/** Plain ids, aliases first — the shape `capabilities.claude.models` has
|
|
17
|
+
* always had. Studio and Flows read it as strings; keep it that way. */
|
|
18
|
+
models: string[];
|
|
19
|
+
/** The same models with names, for the UIs that know this field. */
|
|
20
|
+
catalog: ClaudeModelEntry[];
|
|
21
|
+
/** What a run with no model set gets — for a logged-OUT CLI, which is all
|
|
22
|
+
* the probe ever sees, so it is not reported as this node's default. */
|
|
23
|
+
defaultModel?: string;
|
|
24
|
+
}
|
|
25
|
+
export type ProbeResult = ModelProbeResult<ClaudeModelReport>;
|
|
26
|
+
/**
|
|
27
|
+
* Turn the `models` array of an initialize response into a report.
|
|
28
|
+
*
|
|
29
|
+
* Every alias also gets a pinned entry for what it resolves to. The CLI lists
|
|
30
|
+
* `opus` → claude-opus-5-5 but no `claude-opus-5-5` of its own, and without one
|
|
31
|
+
* nobody could hold an entity on Opus 5.5 once `opus` moves on.
|
|
32
|
+
*
|
|
33
|
+
* `default` is left out of `models`: a blank model already means the default,
|
|
34
|
+
* and nobody has tested what `--model default` does.
|
|
35
|
+
*
|
|
36
|
+
* Returns null when nothing usable is in there.
|
|
37
|
+
*/
|
|
38
|
+
export declare function parseInitializeModels(raw: unknown): ClaudeModelReport | null;
|
|
39
|
+
/**
|
|
40
|
+
* What the heartbeat reports: the CLI's models first, then any built-in id it
|
|
41
|
+
* did not mention. A logged-out CLI lists only its aliases, and dropping the
|
|
42
|
+
* older pinned ids (Opus 4.8, Sonnet 4.6, …) from every picker would take
|
|
43
|
+
* options away from people who use them. The built-in extras carry no catalog
|
|
44
|
+
* entry — a UI shows them by id, exactly as it always has.
|
|
45
|
+
*/
|
|
46
|
+
export declare function withBuiltin(report: ClaudeModelReport, builtin: readonly string[]): ClaudeModelReport;
|
|
47
|
+
/**
|
|
48
|
+
* Ask one Claude binary for its models. Never throws; resolves within
|
|
49
|
+
* `timeoutMs` however the CLI behaves, and leaves no process behind.
|
|
50
|
+
*/
|
|
51
|
+
export declare function probeClaudeModels(bin: string, opts?: {
|
|
52
|
+
timeoutMs?: number;
|
|
53
|
+
/** Tests only: run something else in place of the CLI. */
|
|
54
|
+
resolve?: (bin: string, args: string[]) => CliInvocation;
|
|
55
|
+
/** Tests only: where the throwaway folder goes. */
|
|
56
|
+
dir?: string;
|
|
57
|
+
}): Promise<ProbeResult>;
|
|
58
|
+
/** Tests only. */
|
|
59
|
+
export declare function __resetIsolationForTests(): void;
|
|
60
|
+
export interface ModelCacheDeps {
|
|
61
|
+
probe: (bin: string) => Promise<ProbeResult>;
|
|
62
|
+
now: () => number;
|
|
63
|
+
log: (line: string) => void;
|
|
64
|
+
}
|
|
65
|
+
/** Refreshed every 6h, retried 30 min after a failure — see model-cache.ts. */
|
|
66
|
+
export declare function createClaudeModelCache(deps: ModelCacheDeps): {
|
|
67
|
+
get(bin: string, key: string): ClaudeModelReport | null;
|
|
68
|
+
last(): ClaudeModelReport | null;
|
|
69
|
+
};
|
|
70
|
+
/** What capabilities.ts reports for claude's models. */
|
|
71
|
+
export declare function claudeModelsFor(bin: string, key: string): ClaudeModelReport | null;
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Which models the installed Claude Code offers — asked of the CLI itself.
|
|
3
|
+
//
|
|
4
|
+
// Until 0.30.13 this was only the CLAUDE_MODELS constant in capabilities.ts,
|
|
5
|
+
// and a constant is only as current as the last release: Opus 5.5 shipped and
|
|
6
|
+
// every node went on offering Opus 5, because nobody had edited the list.
|
|
7
|
+
//
|
|
8
|
+
// The CLI has no `claude models` command (still true in 2.1.304, and anything
|
|
9
|
+
// it does not recognise is read as a PROMPT, which is billed). But it does
|
|
10
|
+
// answer the SDK control protocol: start it in stream-json mode, send the
|
|
11
|
+
// `initialize` control request, and the response carries `models` — the list
|
|
12
|
+
// its own /model picker shows, with what each alias resolves to today. No user
|
|
13
|
+
// message is ever sent, so nothing is billed.
|
|
14
|
+
//
|
|
15
|
+
// ⚠️ THE PROBE MUST NEVER SEE THE NODE'S LOGIN. A Claude process that starts
|
|
16
|
+
// with an expired access token refreshes it, which rotates the refresh token;
|
|
17
|
+
// one that exits a second later — as a probe does — can lose the rotated token,
|
|
18
|
+
// and the next process finds a dead login and wipes it. That logged popadom's
|
|
19
|
+
// Claude out on 2026-10-20 while this was being built. So the probe runs with
|
|
20
|
+
// a throwaway CLAUDE_CONFIG_DIR, `--bare` (no keychain reads — the macOS
|
|
21
|
+
// login lives there, not in the config dir), and no credential env vars. The
|
|
22
|
+
// CLI then reports `tokenSource: "none"` and still answers, with the
|
|
23
|
+
// account-independent list: the aliases and what they resolve to.
|
|
24
|
+
//
|
|
25
|
+
// 2.1.278 `opus[1m]` → claude-opus-5[1m], `sonnet` → claude-sonnet-5
|
|
26
|
+
// 2.1.304 `opus` → claude-opus-5-5, `sonnet` → claude-sonnet-5-5
|
|
27
|
+
//
|
|
28
|
+
// If a CLI ever answers WITH a login despite all that, isolation has failed:
|
|
29
|
+
// this process stops probing for good and says so in the log.
|
|
30
|
+
//
|
|
31
|
+
// A probe costs a CLI start (~1s) and the heartbeat runs every 30s, so the
|
|
32
|
+
// answer is cached per (binary, version) and the heartbeat never waits for it:
|
|
33
|
+
// the first beat after an install or upgrade still reports what it had, kicks
|
|
34
|
+
// the probe off in the background, and the next beat carries the answer. A
|
|
35
|
+
// probe that fails — an old CLI, a protocol change — leaves the built-in list
|
|
36
|
+
// in place (or the last answer that same binary gave) and is not retried for
|
|
37
|
+
// RETRY_AFTER_FAIL_MS, so a broken CLI never costs a spawn every 30 seconds.
|
|
38
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
39
|
+
if (k2 === undefined) k2 = k;
|
|
40
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
41
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
42
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
43
|
+
}
|
|
44
|
+
Object.defineProperty(o, k2, desc);
|
|
45
|
+
}) : (function(o, m, k, k2) {
|
|
46
|
+
if (k2 === undefined) k2 = k;
|
|
47
|
+
o[k2] = m[k];
|
|
48
|
+
}));
|
|
49
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
50
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
51
|
+
}) : function(o, v) {
|
|
52
|
+
o["default"] = v;
|
|
53
|
+
});
|
|
54
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
55
|
+
var ownKeys = function(o) {
|
|
56
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
57
|
+
var ar = [];
|
|
58
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
59
|
+
return ar;
|
|
60
|
+
};
|
|
61
|
+
return ownKeys(o);
|
|
62
|
+
};
|
|
63
|
+
return function (mod) {
|
|
64
|
+
if (mod && mod.__esModule) return mod;
|
|
65
|
+
var result = {};
|
|
66
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
67
|
+
__setModuleDefault(result, mod);
|
|
68
|
+
return result;
|
|
69
|
+
};
|
|
70
|
+
})();
|
|
71
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
72
|
+
exports.parseInitializeModels = parseInitializeModels;
|
|
73
|
+
exports.withBuiltin = withBuiltin;
|
|
74
|
+
exports.probeClaudeModels = probeClaudeModels;
|
|
75
|
+
exports.__resetIsolationForTests = __resetIsolationForTests;
|
|
76
|
+
exports.createClaudeModelCache = createClaudeModelCache;
|
|
77
|
+
exports.claudeModelsFor = claudeModelsFor;
|
|
78
|
+
const child_process_1 = require("child_process");
|
|
79
|
+
const fs = __importStar(require("fs"));
|
|
80
|
+
const model_cache_1 = require("./model-cache");
|
|
81
|
+
const win_1 = require("./win");
|
|
82
|
+
// What a model id may look like before it is passed on: `claude-opus-5-5`,
|
|
83
|
+
// `opus[1m]`, `claude-haiku-4-5-20251001`. Anything else is dropped rather
|
|
84
|
+
// than shipped to every picker.
|
|
85
|
+
const SAFE_ID = /^[A-Za-z0-9][A-Za-z0-9._:[\]-]{0,119}$/;
|
|
86
|
+
const MAX_ENTRIES = 64;
|
|
87
|
+
/** An alias carries no version number: `opus`, `sonnet`, `opus[1m]`. */
|
|
88
|
+
function isAlias(id) {
|
|
89
|
+
return !/\d/.test(id.replace(/\[[^\]]*\]$/, ''));
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Turn the `models` array of an initialize response into a report.
|
|
93
|
+
*
|
|
94
|
+
* Every alias also gets a pinned entry for what it resolves to. The CLI lists
|
|
95
|
+
* `opus` → claude-opus-5-5 but no `claude-opus-5-5` of its own, and without one
|
|
96
|
+
* nobody could hold an entity on Opus 5.5 once `opus` moves on.
|
|
97
|
+
*
|
|
98
|
+
* `default` is left out of `models`: a blank model already means the default,
|
|
99
|
+
* and nobody has tested what `--model default` does.
|
|
100
|
+
*
|
|
101
|
+
* Returns null when nothing usable is in there.
|
|
102
|
+
*/
|
|
103
|
+
function parseInitializeModels(raw) {
|
|
104
|
+
if (!Array.isArray(raw))
|
|
105
|
+
return null;
|
|
106
|
+
const aliases = [];
|
|
107
|
+
const pinned = [];
|
|
108
|
+
const derived = [];
|
|
109
|
+
let defaultModel;
|
|
110
|
+
for (const item of raw.slice(0, MAX_ENTRIES)) {
|
|
111
|
+
if (!item || typeof item !== 'object')
|
|
112
|
+
continue;
|
|
113
|
+
const o = item;
|
|
114
|
+
const id = typeof o.value === 'string' ? o.value.trim() : '';
|
|
115
|
+
if (!SAFE_ID.test(id))
|
|
116
|
+
continue;
|
|
117
|
+
const resolved = typeof o.resolvedModel === 'string' && SAFE_ID.test(o.resolvedModel.trim())
|
|
118
|
+
? o.resolvedModel.trim() : id;
|
|
119
|
+
const name = typeof o.displayName === 'string' && o.displayName.trim()
|
|
120
|
+
? o.displayName.trim().slice(0, 80) : id;
|
|
121
|
+
const efforts = Array.isArray(o.supportedEffortLevels)
|
|
122
|
+
? o.supportedEffortLevels.filter((e) => typeof e === 'string' && /^[a-z]{1,20}$/.test(e))
|
|
123
|
+
: [];
|
|
124
|
+
if (id === 'default') {
|
|
125
|
+
if (resolved !== 'default')
|
|
126
|
+
defaultModel = resolved;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
const entry = { id, resolved, name, alias: isAlias(id), ...(efforts.length ? { efforts } : {}) };
|
|
130
|
+
(entry.alias ? aliases : pinned).push(entry);
|
|
131
|
+
if (entry.alias && resolved !== id) {
|
|
132
|
+
derived.push({ id: resolved, resolved, name, alias: false, ...(efforts.length ? { efforts } : {}) });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// Aliases first (they never go stale), then what they point at (the newest
|
|
136
|
+
// models), then the CLI's own pinned list in its order.
|
|
137
|
+
const seen = new Set();
|
|
138
|
+
const catalog = [];
|
|
139
|
+
for (const e of [...aliases, ...derived, ...pinned]) {
|
|
140
|
+
if (seen.has(e.id))
|
|
141
|
+
continue;
|
|
142
|
+
seen.add(e.id);
|
|
143
|
+
catalog.push(e);
|
|
144
|
+
}
|
|
145
|
+
if (catalog.length === 0)
|
|
146
|
+
return null;
|
|
147
|
+
return { models: catalog.map(e => e.id), catalog, ...(defaultModel ? { defaultModel } : {}) };
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* What the heartbeat reports: the CLI's models first, then any built-in id it
|
|
151
|
+
* did not mention. A logged-out CLI lists only its aliases, and dropping the
|
|
152
|
+
* older pinned ids (Opus 4.8, Sonnet 4.6, …) from every picker would take
|
|
153
|
+
* options away from people who use them. The built-in extras carry no catalog
|
|
154
|
+
* entry — a UI shows them by id, exactly as it always has.
|
|
155
|
+
*/
|
|
156
|
+
function withBuiltin(report, builtin) {
|
|
157
|
+
const have = new Set(report.models);
|
|
158
|
+
return { ...report, models: [...report.models, ...builtin.filter(id => !have.has(id))] };
|
|
159
|
+
}
|
|
160
|
+
/** Never read a login: the CLI must not see, refresh or clear one. */
|
|
161
|
+
const CREDENTIAL_ENV = [
|
|
162
|
+
'ANTHROPIC_API_KEY', 'ANTHROPIC_AUTH_TOKEN', 'CLAUDE_CODE_OAUTH_TOKEN',
|
|
163
|
+
'CLAUDE_CODE_OAUTH_REFRESH_TOKEN', 'CLAUDE_CONFIG_DIR',
|
|
164
|
+
];
|
|
165
|
+
const PROBE_ARGS = [
|
|
166
|
+
'--print', '--input-format', 'stream-json', '--output-format', 'stream-json', '--verbose',
|
|
167
|
+
// No keychain reads (the macOS login), no hooks, no plugin sync, no
|
|
168
|
+
// background prefetches. A CLI too old to know --bare refuses to start,
|
|
169
|
+
// and that node keeps the built-in list — the safe way to be wrong.
|
|
170
|
+
'--bare',
|
|
171
|
+
// No MCP servers: the handshake needs none.
|
|
172
|
+
'--strict-mcp-config', '--mcp-config', '{"mcpServers":{}}',
|
|
173
|
+
];
|
|
174
|
+
const MAX_LINE = 2 * 1024 * 1024;
|
|
175
|
+
/** Set once a CLI answers with a login despite the isolation above. */
|
|
176
|
+
let isolationBroken = false;
|
|
177
|
+
/**
|
|
178
|
+
* Ask one Claude binary for its models. Never throws; resolves within
|
|
179
|
+
* `timeoutMs` however the CLI behaves, and leaves no process behind.
|
|
180
|
+
*/
|
|
181
|
+
function probeClaudeModels(bin, opts = {}) {
|
|
182
|
+
return new Promise(done => {
|
|
183
|
+
if (isolationBroken) {
|
|
184
|
+
done({ ok: false, reason: 'probing is off: a CLI saw a login despite the isolation' });
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
let settled = false;
|
|
188
|
+
let inv;
|
|
189
|
+
try {
|
|
190
|
+
inv = (opts.resolve ?? win_1.resolveCliInvocation)(bin, PROBE_ARGS);
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
done({ ok: false, reason: err.message || String(err) });
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
// Both the probe's cwd and its CLAUDE_CONFIG_DIR, so no project's
|
|
197
|
+
// settings or CLAUDE.md are read and nothing the CLI writes lands in the
|
|
198
|
+
// real ~/.claude.
|
|
199
|
+
const dir = opts.dir ?? (0, model_cache_1.makeProbeDir)();
|
|
200
|
+
if (!dir) {
|
|
201
|
+
done({ ok: false, reason: 'no folder to probe from' });
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
const cleanup = () => {
|
|
205
|
+
if (opts.dir)
|
|
206
|
+
return;
|
|
207
|
+
try {
|
|
208
|
+
fs.rmSync(dir, { recursive: true, force: true, maxRetries: 5, retryDelay: 200 });
|
|
209
|
+
}
|
|
210
|
+
catch { /* swept later */ }
|
|
211
|
+
};
|
|
212
|
+
const env = { ...process.env, TERM: 'dumb' };
|
|
213
|
+
for (const k of CREDENTIAL_ENV)
|
|
214
|
+
delete env[k];
|
|
215
|
+
env.CLAUDE_CONFIG_DIR = dir;
|
|
216
|
+
// A probe is read-only: it must never start a self-update of the CLI.
|
|
217
|
+
env.DISABLE_AUTOUPDATER = '1';
|
|
218
|
+
let child;
|
|
219
|
+
try {
|
|
220
|
+
child = (0, child_process_1.spawn)(inv.file, inv.args, { cwd: dir, env, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true });
|
|
221
|
+
}
|
|
222
|
+
catch (err) {
|
|
223
|
+
cleanup();
|
|
224
|
+
done({ ok: false, reason: err.message || String(err) });
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
child.once('close', cleanup);
|
|
228
|
+
const finish = (result) => {
|
|
229
|
+
if (settled)
|
|
230
|
+
return;
|
|
231
|
+
settled = true;
|
|
232
|
+
clearTimeout(timer);
|
|
233
|
+
// EOF first — in stream-json mode the CLI exits on its own when its
|
|
234
|
+
// input ends. The kill is the backstop for one that does not.
|
|
235
|
+
try {
|
|
236
|
+
child.stdin?.end();
|
|
237
|
+
}
|
|
238
|
+
catch { /* already closed */ }
|
|
239
|
+
const reap = setTimeout(() => {
|
|
240
|
+
if (child.exitCode === null && child.signalCode === null)
|
|
241
|
+
(0, win_1.killProcessTree)(child);
|
|
242
|
+
}, 3000);
|
|
243
|
+
reap.unref();
|
|
244
|
+
child.once('exit', () => clearTimeout(reap));
|
|
245
|
+
done(result);
|
|
246
|
+
};
|
|
247
|
+
const timer = setTimeout(() => {
|
|
248
|
+
finish({ ok: false, reason: `no answer within ${opts.timeoutMs ?? 30000}ms` });
|
|
249
|
+
(0, win_1.killProcessTree)(child);
|
|
250
|
+
}, opts.timeoutMs ?? 30000);
|
|
251
|
+
timer.unref();
|
|
252
|
+
child.on('error', err => finish({ ok: false, reason: err.message || String(err) }));
|
|
253
|
+
// 'close', not 'exit': close waits for stdout to drain, so an answer the
|
|
254
|
+
// CLI wrote just before exiting is read rather than reported missing.
|
|
255
|
+
child.on('close', (code, signal) => {
|
|
256
|
+
finish({ ok: false, reason: `exited ${code ?? signal} before answering${stderr ? `: ${stderr.trim().slice(0, 200)}` : ''}` });
|
|
257
|
+
});
|
|
258
|
+
child.stdin?.on('error', () => { });
|
|
259
|
+
let stderr = '';
|
|
260
|
+
child.stderr?.on('data', (d) => { if (stderr.length < 4096)
|
|
261
|
+
stderr += d.toString('utf8'); });
|
|
262
|
+
const requestId = `models-${process.pid}-${Date.now()}`;
|
|
263
|
+
let buf = '';
|
|
264
|
+
child.stdout?.on('data', (d) => {
|
|
265
|
+
buf += d.toString('utf8');
|
|
266
|
+
if (buf.length > MAX_LINE) {
|
|
267
|
+
finish({ ok: false, reason: 'oversized output' });
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
let nl;
|
|
271
|
+
while ((nl = buf.indexOf('\n')) >= 0) {
|
|
272
|
+
const line = buf.slice(0, nl).trim();
|
|
273
|
+
buf = buf.slice(nl + 1);
|
|
274
|
+
if (!line.startsWith('{'))
|
|
275
|
+
continue;
|
|
276
|
+
let msg;
|
|
277
|
+
try {
|
|
278
|
+
msg = JSON.parse(line);
|
|
279
|
+
}
|
|
280
|
+
catch {
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
if (msg.type !== 'control_response')
|
|
284
|
+
continue;
|
|
285
|
+
const res = msg.response ?? {};
|
|
286
|
+
if (res.request_id && res.request_id !== requestId)
|
|
287
|
+
continue;
|
|
288
|
+
if (res.subtype === 'error') {
|
|
289
|
+
finish({ ok: false, reason: `initialize refused: ${String(res.error ?? 'unknown').slice(0, 200)}` });
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
const tokenSource = res.response?.account?.tokenSource;
|
|
293
|
+
if (typeof tokenSource === 'string' && tokenSource !== 'none') {
|
|
294
|
+
isolationBroken = true;
|
|
295
|
+
finish({ ok: false, reason: `isolation failed — the CLI saw a login (${tokenSource}); probing is now off on this node` });
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
const report = parseInitializeModels(res.response?.models);
|
|
299
|
+
finish(report ? { ok: true, report } : { ok: false, reason: 'initialize answered without a model list' });
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
try {
|
|
304
|
+
child.stdin?.write(JSON.stringify({
|
|
305
|
+
type: 'control_request', request_id: requestId, request: { subtype: 'initialize' },
|
|
306
|
+
}) + '\n');
|
|
307
|
+
}
|
|
308
|
+
catch { /* reported via 'close' / 'error' */ }
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
/** Tests only. */
|
|
312
|
+
function __resetIsolationForTests() { isolationBroken = false; }
|
|
313
|
+
/** Refreshed every 6h, retried 30 min after a failure — see model-cache.ts. */
|
|
314
|
+
function createClaudeModelCache(deps) {
|
|
315
|
+
return (0, model_cache_1.createModelCache)({
|
|
316
|
+
...deps,
|
|
317
|
+
agent: 'claude',
|
|
318
|
+
describe: report => report.catalog.filter(e => e.alias && e.resolved !== e.id)
|
|
319
|
+
.map(e => `${e.id} → ${e.resolved}`).join(', '),
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
const sharedCache = createClaudeModelCache({
|
|
323
|
+
probe: bin => probeClaudeModels(bin),
|
|
324
|
+
now: () => Date.now(),
|
|
325
|
+
log: line => console.log(line),
|
|
326
|
+
});
|
|
327
|
+
/** What capabilities.ts reports for claude's models. */
|
|
328
|
+
function claudeModelsFor(bin, key) {
|
|
329
|
+
return sharedCache.get(bin, key);
|
|
330
|
+
}
|
package/dist/claude-print.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ import type { RuntimeEvent, RuntimePermissionMode, RuntimeEffortLevel } from './
|
|
|
2
2
|
export interface ClaudePrintInput {
|
|
3
3
|
workingDirectory: string;
|
|
4
4
|
prompt: string;
|
|
5
|
+
/** Verified original file blocks for explicitly marked EntityBox chat. */
|
|
6
|
+
inputBlocks?: readonly ClaudePrintInputBlock[];
|
|
5
7
|
permissionMode?: RuntimePermissionMode;
|
|
6
8
|
effortLevel?: RuntimeEffortLevel;
|
|
7
9
|
model?: string;
|
|
@@ -13,6 +15,19 @@ export interface ClaudePrintInput {
|
|
|
13
15
|
/** Restrict to a specific set of tools (claude only). null/undefined = inherit. */
|
|
14
16
|
allowedTools?: string[];
|
|
15
17
|
}
|
|
18
|
+
export type ClaudePrintInputBlock = {
|
|
19
|
+
type: 'text';
|
|
20
|
+
text: string;
|
|
21
|
+
} | {
|
|
22
|
+
type: 'image' | 'document';
|
|
23
|
+
source: {
|
|
24
|
+
type: 'base64';
|
|
25
|
+
media_type: string;
|
|
26
|
+
data: string;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
/** Stream JSON reaches stdin only; files never become command-line arguments. */
|
|
30
|
+
export declare function claudePrintInputMessage(prompt: string, blocks: readonly ClaudePrintInputBlock[]): string;
|
|
16
31
|
/**
|
|
17
32
|
* The text to emit for one flushed block, given what came before.
|
|
18
33
|
*
|