@openagt/agent-driver-claude 0.0.0-stage → 0.0.1
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 +21 -0
- package/dist/claude-code-models.d.ts +39 -0
- package/dist/claude-code-models.d.ts.map +1 -0
- package/dist/claude-code-models.js +97 -0
- package/dist/claude-code-models.js.map +1 -0
- package/dist/claude-code-quota.d.ts +39 -0
- package/dist/claude-code-quota.d.ts.map +1 -0
- package/dist/claude-code-quota.js +144 -0
- package/dist/claude-code-quota.js.map +1 -0
- package/dist/claude-code.d.ts +134 -0
- package/dist/claude-code.d.ts.map +1 -0
- package/dist/claude-code.js +493 -0
- package/dist/claude-code.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/package.json +37 -3
- package/README.md +0 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Suleiman Shahbari
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { DriverModel, SpawnLike } from '@openagt/agent-driver';
|
|
2
|
+
/** How long {@link readClaudeModels} waits for the CLI's answer. */
|
|
3
|
+
export declare const MODELS_TIMEOUT_MS = 30000;
|
|
4
|
+
/** Options for {@link readClaudeModels}. */
|
|
5
|
+
export interface ReadClaudeModelsOptions {
|
|
6
|
+
/** CLI binary to spawn. Default `"claude"` (resolved on `PATH`). */
|
|
7
|
+
bin?: string;
|
|
8
|
+
/** Extra CLI args, such as the switches that keep the person's own settings out. */
|
|
9
|
+
extraArgs?: string[];
|
|
10
|
+
/** Environment for the child process. Default `process.env`. */
|
|
11
|
+
env?: NodeJS.ProcessEnv;
|
|
12
|
+
/** `spawn` override for tests. Default `node:child_process.spawn`. */
|
|
13
|
+
spawn?: SpawnLike;
|
|
14
|
+
/** Abort the read. */
|
|
15
|
+
signal?: AbortSignal;
|
|
16
|
+
/** Override the timeout. Default {@link MODELS_TIMEOUT_MS}. */
|
|
17
|
+
timeoutMs?: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Ask Claude Code which models it offers: the list its own `/model` picker shows, for the person's
|
|
21
|
+
* login. The CLI is started in its stream-json mode and sent only its `initialize` control request,
|
|
22
|
+
* whose answer carries the list; no prompt is sent, so no model runs. The CLI is stopped once it
|
|
23
|
+
* has answered.
|
|
24
|
+
*/
|
|
25
|
+
export declare function readClaudeModels(opts?: ReadClaudeModelsOptions): Promise<DriverModel[]>;
|
|
26
|
+
/**
|
|
27
|
+
* Read one line of the CLI's output: the models when it is the answer to the `initialize` request,
|
|
28
|
+
* the CLI's own error when that request failed, `undefined` for any other line.
|
|
29
|
+
*
|
|
30
|
+
* The CLI's first entry, `default`, is not a model: it is "no pick", which a caller already has by
|
|
31
|
+
* passing no model. It is left out, so every entry names one model. An alias carries the full id
|
|
32
|
+
* it runs today (`claude-opus-5-5` for `opus`), the id a run on it names.
|
|
33
|
+
*/
|
|
34
|
+
export declare function parseInitializeLine(line: string): {
|
|
35
|
+
models: DriverModel[];
|
|
36
|
+
} | {
|
|
37
|
+
error: string;
|
|
38
|
+
} | undefined;
|
|
39
|
+
//# sourceMappingURL=claude-code-models.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code-models.d.ts","sourceRoot":"","sources":["../src/claude-code-models.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAEnE,oEAAoE;AACpE,eAAO,MAAM,iBAAiB,QAAS,CAAA;AAKvC,4CAA4C;AAC5C,MAAM,WAAW,uBAAuB;IACtC,oEAAoE;IACpE,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,oFAAoF;IACpF,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB,gEAAgE;IAChE,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;IACvB,sEAAsE;IACtE,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,sBAAsB;IACtB,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,GAAE,uBAA4B,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAwC3F;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,WAAW,EAAE,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAwB3G"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { spawn as nodeSpawn } from 'node:child_process';
|
|
2
|
+
/** How long {@link readClaudeModels} waits for the CLI's answer. */
|
|
3
|
+
export const MODELS_TIMEOUT_MS = 30_000;
|
|
4
|
+
/** The request that asks the CLI for its session setup, the model list among it. */
|
|
5
|
+
const INITIALIZE = { type: 'control_request', request_id: 'models', request: { subtype: 'initialize' } };
|
|
6
|
+
/**
|
|
7
|
+
* Ask Claude Code which models it offers: the list its own `/model` picker shows, for the person's
|
|
8
|
+
* login. The CLI is started in its stream-json mode and sent only its `initialize` control request,
|
|
9
|
+
* whose answer carries the list; no prompt is sent, so no model runs. The CLI is stopped once it
|
|
10
|
+
* has answered.
|
|
11
|
+
*/
|
|
12
|
+
export function readClaudeModels(opts = {}) {
|
|
13
|
+
return new Promise((resolvePromise, rejectPromise) => {
|
|
14
|
+
if (opts.signal?.aborted) {
|
|
15
|
+
rejectPromise(new Error('Claude Code was not asked for its models: the read was stopped'));
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const spawn = opts.spawn ?? nodeSpawn;
|
|
19
|
+
const args = ['-p', '--input-format', 'stream-json', '--output-format', 'stream-json', '--verbose', ...(opts.extraArgs ?? [])];
|
|
20
|
+
const child = spawn(opts.bin ?? 'claude', args, { cwd: process.cwd(), env: opts.env ?? process.env });
|
|
21
|
+
let settled = false;
|
|
22
|
+
const settle = (answer) => {
|
|
23
|
+
if (settled)
|
|
24
|
+
return;
|
|
25
|
+
settled = true;
|
|
26
|
+
clearTimeout(timer);
|
|
27
|
+
opts.signal?.removeEventListener('abort', onAbort);
|
|
28
|
+
child.kill('SIGTERM');
|
|
29
|
+
if ('models' in answer)
|
|
30
|
+
resolvePromise(answer.models);
|
|
31
|
+
else
|
|
32
|
+
rejectPromise(new Error(answer.error));
|
|
33
|
+
};
|
|
34
|
+
const onAbort = () => settle({ error: 'Claude Code was not asked for its models: the read was stopped' });
|
|
35
|
+
opts.signal?.addEventListener('abort', onAbort);
|
|
36
|
+
// Not unref'd: it is what guarantees the promise settles.
|
|
37
|
+
const timer = setTimeout(() => settle({ error: `Claude Code did not list its models within ${Math.round((opts.timeoutMs ?? MODELS_TIMEOUT_MS) / 1000)}s` }), opts.timeoutMs ?? MODELS_TIMEOUT_MS);
|
|
38
|
+
let pending = '';
|
|
39
|
+
child.stdout?.on('data', (chunk) => {
|
|
40
|
+
pending += String(chunk);
|
|
41
|
+
let newline;
|
|
42
|
+
while ((newline = pending.indexOf('\n')) >= 0) {
|
|
43
|
+
const line = pending.slice(0, newline);
|
|
44
|
+
pending = pending.slice(newline + 1);
|
|
45
|
+
const answer = parseInitializeLine(line);
|
|
46
|
+
if (answer)
|
|
47
|
+
settle(answer);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
child.on('error', err => settle({ error: `\`${opts.bin ?? 'claude'}\` could not start: ${err.message}` }));
|
|
51
|
+
child.on('close', code => settle({ error: `Claude Code exited (code ${code}) before it listed its models` }));
|
|
52
|
+
child.stdin?.write(`${JSON.stringify(INITIALIZE)}\n`);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Read one line of the CLI's output: the models when it is the answer to the `initialize` request,
|
|
57
|
+
* the CLI's own error when that request failed, `undefined` for any other line.
|
|
58
|
+
*
|
|
59
|
+
* The CLI's first entry, `default`, is not a model: it is "no pick", which a caller already has by
|
|
60
|
+
* passing no model. It is left out, so every entry names one model. An alias carries the full id
|
|
61
|
+
* it runs today (`claude-opus-5-5` for `opus`), the id a run on it names.
|
|
62
|
+
*/
|
|
63
|
+
export function parseInitializeLine(line) {
|
|
64
|
+
let message;
|
|
65
|
+
try {
|
|
66
|
+
message = JSON.parse(line);
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
const outer = record(message);
|
|
72
|
+
if (outer?.['type'] !== 'control_response')
|
|
73
|
+
return undefined;
|
|
74
|
+
const response = record(outer['response']);
|
|
75
|
+
if (response?.['request_id'] !== INITIALIZE.request_id)
|
|
76
|
+
return undefined;
|
|
77
|
+
if (response['subtype'] === 'error')
|
|
78
|
+
return { error: `Claude Code could not list its models: ${String(response['error'] ?? 'no reason given')}` };
|
|
79
|
+
const listed = record(response['response'])?.['models'];
|
|
80
|
+
if (!Array.isArray(listed))
|
|
81
|
+
return { error: 'Claude Code answered without a model list' };
|
|
82
|
+
const models = [];
|
|
83
|
+
for (const entry of listed) {
|
|
84
|
+
const model = record(entry);
|
|
85
|
+
const id = model?.['value'];
|
|
86
|
+
const name = model?.['displayName'];
|
|
87
|
+
const resolved = model?.['resolvedModel'];
|
|
88
|
+
if (typeof id !== 'string' || typeof name !== 'string' || id === 'default')
|
|
89
|
+
continue;
|
|
90
|
+
models.push({ id, name, ...(typeof resolved === 'string' && resolved !== id ? { resolvedId: resolved } : {}) });
|
|
91
|
+
}
|
|
92
|
+
return { models };
|
|
93
|
+
}
|
|
94
|
+
function record(value) {
|
|
95
|
+
return typeof value === 'object' && value !== null ? value : undefined;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=claude-code-models.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code-models.js","sourceRoot":"","sources":["../src/claude-code-models.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { DriverQuota, SpawnLike } from '@openagt/agent-driver';
|
|
2
|
+
/**
|
|
3
|
+
* Parse Claude Code's `/usage` readout (#521).
|
|
4
|
+
*
|
|
5
|
+
* The agent prints prose, so this is a text parse and a reworded readout is a
|
|
6
|
+
* real failure mode. It fails to `unrecognized` rather than to an empty reading:
|
|
7
|
+
* a silent zero would read as "nothing used" and let a consumption limit run the
|
|
8
|
+
* account dry.
|
|
9
|
+
*/
|
|
10
|
+
export declare function parseQuotaReadout(text: string): DriverQuota;
|
|
11
|
+
/** Options for {@link readClaudeQuota}. */
|
|
12
|
+
export interface ReadClaudeQuotaOptions {
|
|
13
|
+
/** CLI binary to spawn. Default `"claude"` (resolved on `PATH`). */
|
|
14
|
+
bin?: string;
|
|
15
|
+
/** Working directory for the child. The read is account-wide, so this is incidental. */
|
|
16
|
+
cwd?: string;
|
|
17
|
+
/** Environment for the child process. Default `process.env`. */
|
|
18
|
+
env?: NodeJS.ProcessEnv;
|
|
19
|
+
/** `spawn` override for tests. Default `node:child_process.spawn`. */
|
|
20
|
+
spawn?: SpawnLike;
|
|
21
|
+
/** Abort the read. */
|
|
22
|
+
signal?: AbortSignal;
|
|
23
|
+
/** Override the timeout. Default {@link READ_TIMEOUT_MS}. */
|
|
24
|
+
timeoutMs?: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Ask Claude Code where the account's subscription quota stands (#521).
|
|
28
|
+
*
|
|
29
|
+
* Runs the CLI's own `/usage` command in print mode. Costs nothing: verified on
|
|
30
|
+
* 2.1.210 as `total_cost_usd: 0` across zero turns and zero tokens, because the
|
|
31
|
+
* CLI answers it locally rather than by prompting a model. It reaches Anthropic
|
|
32
|
+
* itself, with its own credentials, so the caller never reads or handles the
|
|
33
|
+
* user's token.
|
|
34
|
+
*
|
|
35
|
+
* Never pass `--bare` here: it pins the CLI to API-key auth and never reads the
|
|
36
|
+
* OAuth credentials, so the subscription quota this reads would vanish.
|
|
37
|
+
*/
|
|
38
|
+
export declare function readClaudeQuota(opts?: ReadClaudeQuotaOptions): Promise<DriverQuota>;
|
|
39
|
+
//# sourceMappingURL=claude-code-quota.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code-quota.d.ts","sourceRoot":"","sources":["../src/claude-code-quota.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAqB,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAkCtF;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAqB3D;AAED,2CAA2C;AAC3C,MAAM,WAAW,sBAAsB;IACrC,oEAAoE;IACpE,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,wFAAwF;IACxF,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,gEAAgE;IAChE,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;IACvB,sEAAsE;IACtE,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,sBAAsB;IACtB,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,IAAI,GAAE,sBAA2B,GAAG,OAAO,CAAC,WAAW,CAAC,CAmDvF"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { spawn as nodeSpawn } from 'node:child_process';
|
|
2
|
+
/** How long we wait for the readout before calling it a timeout. */
|
|
3
|
+
const READ_TIMEOUT_MS = 20_000;
|
|
4
|
+
/**
|
|
5
|
+
* Present in both subscription headers Claude Code can print (`"your
|
|
6
|
+
* subscription"` and, mid-overage, `"your overages"`), and in neither
|
|
7
|
+
* non-subscription case. Matching the shared tail rather than the word
|
|
8
|
+
* "subscription" is deliberate: an account burning overage still has a quota to
|
|
9
|
+
* report, and keying on "subscription" would read it as having none.
|
|
10
|
+
*/
|
|
11
|
+
const SUBSCRIPTION_HEADER = /to power your Claude Code usage/;
|
|
12
|
+
/**
|
|
13
|
+
* One `"<label>: <n>% used · resets <when>"` line.
|
|
14
|
+
*
|
|
15
|
+
* Anchored and strict on `% used` immediately after the colon, because the same
|
|
16
|
+
* readout carries lines that are shaped just closely enough to match a lazier
|
|
17
|
+
* pattern (`"Top skills: /dataviz 2%, /claude-api 1%"`, `" 70% of your usage
|
|
18
|
+
* was at >150k context"`).
|
|
19
|
+
*/
|
|
20
|
+
const WINDOW_LINE = /^(.+?):\s+(\d+(?:\.\d+)?)% used(?:\s*·\s*(.+))?$/;
|
|
21
|
+
/** Strips the `resets` verb, which is prose framing rather than part of the value. */
|
|
22
|
+
const RESETS_PREFIX = /^resets\s+/;
|
|
23
|
+
function windowKind(label) {
|
|
24
|
+
if (/^current session$/i.test(label))
|
|
25
|
+
return 'session';
|
|
26
|
+
if (/^current week \(all models\)$/i.test(label))
|
|
27
|
+
return 'week';
|
|
28
|
+
if (/^current week \(.+\)$/i.test(label))
|
|
29
|
+
return 'week-model';
|
|
30
|
+
return 'unknown';
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Parse Claude Code's `/usage` readout (#521).
|
|
34
|
+
*
|
|
35
|
+
* The agent prints prose, so this is a text parse and a reworded readout is a
|
|
36
|
+
* real failure mode. It fails to `unrecognized` rather than to an empty reading:
|
|
37
|
+
* a silent zero would read as "nothing used" and let a consumption limit run the
|
|
38
|
+
* account dry.
|
|
39
|
+
*/
|
|
40
|
+
export function parseQuotaReadout(text) {
|
|
41
|
+
const windows = [];
|
|
42
|
+
for (const line of text.split('\n')) {
|
|
43
|
+
const match = WINDOW_LINE.exec(line.trim());
|
|
44
|
+
if (!match)
|
|
45
|
+
continue;
|
|
46
|
+
const [, label, percent, resets] = match;
|
|
47
|
+
if (label === undefined || percent === undefined)
|
|
48
|
+
continue;
|
|
49
|
+
const resetsAtText = resets?.replace(RESETS_PREFIX, '').trim();
|
|
50
|
+
windows.push({
|
|
51
|
+
label,
|
|
52
|
+
kind: windowKind(label),
|
|
53
|
+
percentUsed: Number(percent),
|
|
54
|
+
...(resetsAtText ? { resetsAtText } : {}),
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
if (windows.length > 0)
|
|
58
|
+
return { available: true, windows };
|
|
59
|
+
// No windows and no subscription header: the account has no quota to report
|
|
60
|
+
// (API-key auth). With the header, it does have one and we simply failed to
|
|
61
|
+
// read it, which is a parser problem and must not masquerade as the former.
|
|
62
|
+
return { available: false, reason: SUBSCRIPTION_HEADER.test(text) ? 'unrecognized' : 'no-subscription' };
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Ask Claude Code where the account's subscription quota stands (#521).
|
|
66
|
+
*
|
|
67
|
+
* Runs the CLI's own `/usage` command in print mode. Costs nothing: verified on
|
|
68
|
+
* 2.1.210 as `total_cost_usd: 0` across zero turns and zero tokens, because the
|
|
69
|
+
* CLI answers it locally rather than by prompting a model. It reaches Anthropic
|
|
70
|
+
* itself, with its own credentials, so the caller never reads or handles the
|
|
71
|
+
* user's token.
|
|
72
|
+
*
|
|
73
|
+
* Never pass `--bare` here: it pins the CLI to API-key auth and never reads the
|
|
74
|
+
* OAuth credentials, so the subscription quota this reads would vanish.
|
|
75
|
+
*/
|
|
76
|
+
export function readClaudeQuota(opts = {}) {
|
|
77
|
+
return new Promise(resolvePromise => {
|
|
78
|
+
if (opts.signal?.aborted) {
|
|
79
|
+
resolvePromise({ available: false, reason: 'timeout' });
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const spawn = opts.spawn ?? nodeSpawn;
|
|
83
|
+
const child = spawn(opts.bin ?? 'claude', ['-p', '/usage', '--output-format', 'json'], {
|
|
84
|
+
cwd: opts.cwd ?? process.cwd(),
|
|
85
|
+
env: opts.env ?? process.env,
|
|
86
|
+
});
|
|
87
|
+
let settled = false;
|
|
88
|
+
// Raw bytes, decoded once at the end: a per-chunk `String(chunk)` corrupts a multibyte
|
|
89
|
+
// UTF-8 codepoint split across two chunks (the readout's `·` is one), and a corrupted
|
|
90
|
+
// readout parses as 'unrecognized' instead of the real quota.
|
|
91
|
+
const chunks = [];
|
|
92
|
+
const settle = (quota) => {
|
|
93
|
+
if (settled)
|
|
94
|
+
return;
|
|
95
|
+
settled = true;
|
|
96
|
+
clearTimeout(timer);
|
|
97
|
+
opts.signal?.removeEventListener('abort', onAbort);
|
|
98
|
+
resolvePromise(quota);
|
|
99
|
+
};
|
|
100
|
+
const onAbort = () => {
|
|
101
|
+
child.kill('SIGTERM');
|
|
102
|
+
settle({ available: false, reason: 'timeout' });
|
|
103
|
+
};
|
|
104
|
+
opts.signal?.addEventListener('abort', onAbort);
|
|
105
|
+
// Deliberately not unref'd: this timer is the only thing guaranteeing the
|
|
106
|
+
// promise settles, and an unref'd one never fires once the loop goes idle,
|
|
107
|
+
// leaving the caller awaiting forever. `settle` clears it either way.
|
|
108
|
+
const timer = setTimeout(() => {
|
|
109
|
+
child.kill('SIGTERM');
|
|
110
|
+
settle({ available: false, reason: 'timeout' });
|
|
111
|
+
}, opts.timeoutMs ?? READ_TIMEOUT_MS);
|
|
112
|
+
child.stdout?.on('data', (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));
|
|
113
|
+
// ENOENT lands here rather than as a non-zero exit.
|
|
114
|
+
child.on('error', () => settle({ available: false, reason: 'agent-not-found' }));
|
|
115
|
+
child.on('close', code => {
|
|
116
|
+
if (code !== 0) {
|
|
117
|
+
settle({ available: false, reason: 'fetch-failed' });
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
settle(parseQuotaResponse(Buffer.concat(chunks).toString('utf8')));
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
/** Unwrap the CLI's `--output-format json` envelope and parse the readout inside it. */
|
|
125
|
+
function parseQuotaResponse(stdout) {
|
|
126
|
+
let envelope;
|
|
127
|
+
try {
|
|
128
|
+
envelope = JSON.parse(stdout);
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
return { available: false, reason: 'unrecognized' };
|
|
132
|
+
}
|
|
133
|
+
if (typeof envelope !== 'object' || envelope === null)
|
|
134
|
+
return { available: false, reason: 'unrecognized' };
|
|
135
|
+
const obj = envelope;
|
|
136
|
+
// The CLI's own failure arm, e.g. its usage fetch was refused upstream.
|
|
137
|
+
if (obj['is_error'] === true)
|
|
138
|
+
return { available: false, reason: 'fetch-failed' };
|
|
139
|
+
const result = obj['result'];
|
|
140
|
+
if (typeof result !== 'string')
|
|
141
|
+
return { available: false, reason: 'unrecognized' };
|
|
142
|
+
return parseQuotaReadout(result);
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=claude-code-quota.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code-quota.js","sourceRoot":"","sources":["../src/claude-code-quota.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { type DriverReadiness, type DriverReadyOptions, type PersonalSetup, type SpawnLike, type SessionLog, type Driver, type DriverEvent, type DriverModel, type DriverPromptOptions, type DriverQuota, type DriverSession, type DriverStartOptions, type DriverTurn } from '@openagt/agent-driver';
|
|
2
|
+
/** Claude Code permission modes we pass through to the CLI. */
|
|
3
|
+
export type PermissionMode = 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan';
|
|
4
|
+
/** A stdio MCP server spec, as written into the `--mcp-config` file (#452). */
|
|
5
|
+
export interface McpServerSpec {
|
|
6
|
+
command: string;
|
|
7
|
+
args?: string[];
|
|
8
|
+
env?: Record<string, string>;
|
|
9
|
+
}
|
|
10
|
+
/** Options for {@link ClaudeCodeDriver}. */
|
|
11
|
+
export interface ClaudeCodeDriverOptions {
|
|
12
|
+
/** CLI binary to spawn. Default `"claude"` (resolved on `PATH`). */
|
|
13
|
+
bin?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Permission mode. Default `"acceptEdits"` so file writes are non-interactive.
|
|
16
|
+
* A fully autonomous build that also runs installs / tests needs
|
|
17
|
+
* `"bypassPermissions"` (or {@link dangerouslySkipPermissions}).
|
|
18
|
+
*/
|
|
19
|
+
permissionMode?: PermissionMode;
|
|
20
|
+
/** Add `--dangerously-skip-permissions`. Only for sandboxes with no network. */
|
|
21
|
+
dangerouslySkipPermissions?: boolean;
|
|
22
|
+
/** Extra CLI args appended verbatim (escape hatch). */
|
|
23
|
+
extraArgs?: string[];
|
|
24
|
+
/**
|
|
25
|
+
* MCP servers to expose to the agent for this session (#452). Written to a
|
|
26
|
+
* temp config file passed via `--mcp-config`, so they merge with the user's
|
|
27
|
+
* own configured MCP servers rather than replacing them.
|
|
28
|
+
*/
|
|
29
|
+
mcpServers?: Record<string, McpServerSpec>;
|
|
30
|
+
/** Environment for the child process. Default `process.env`. */
|
|
31
|
+
env?: NodeJS.ProcessEnv;
|
|
32
|
+
/**
|
|
33
|
+
* Which parts of the person's own setup Claude Code loads. Default all of them, as Claude Code
|
|
34
|
+
* does on its own. `memory` off is `CLAUDE_CODE_DISABLE_AUTO_MEMORY=1`; `connectors` off is
|
|
35
|
+
* `ENABLE_CLAUDEAI_MCP_SERVERS=false`; `skills` off is `--setting-sources project,local`, which
|
|
36
|
+
* leaves out the person's `~/.claude` settings, `CLAUDE.md` and skills together.
|
|
37
|
+
*/
|
|
38
|
+
personal?: PersonalSetup;
|
|
39
|
+
/** `spawn` override for tests. Default `node:child_process.spawn`. */
|
|
40
|
+
spawn?: SpawnLike;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The first real {@link Driver}: wraps the **Claude Code CLI** in print mode
|
|
44
|
+
* (`claude -p --output-format stream-json`). Each {@link DriverSession.prompt}
|
|
45
|
+
* spawns a fresh non-interactive invocation, so every loop pass gets fresh
|
|
46
|
+
* context. We stream its JSON events to {@link DriverStartOptions.onEvent}
|
|
47
|
+
* for the caller's UI and return the final `result` text as the turn.
|
|
48
|
+
*
|
|
49
|
+
* True black box: we prompt and read the result; Claude Code owns its own loop,
|
|
50
|
+
* tools, and (subscription-based) auth. A second agent slots in behind the same
|
|
51
|
+
* `Driver` interface without touching the orchestration above it.
|
|
52
|
+
*/
|
|
53
|
+
export declare class ClaudeCodeDriver implements Driver {
|
|
54
|
+
private readonly opts;
|
|
55
|
+
readonly id = "claude-code";
|
|
56
|
+
constructor(opts?: ClaudeCodeDriverOptions);
|
|
57
|
+
start(opts: DriverStartOptions): Promise<DriverSession>;
|
|
58
|
+
/** Where the account's subscription quota stands (#521). Account-wide, so no session. */
|
|
59
|
+
readQuota(opts?: {
|
|
60
|
+
signal?: AbortSignal;
|
|
61
|
+
}): Promise<DriverQuota>;
|
|
62
|
+
/** The models Claude Code's own `/model` picker offers, with the person's setup parts as a session loads them. */
|
|
63
|
+
listModels(opts?: {
|
|
64
|
+
signal?: AbortSignal;
|
|
65
|
+
}): Promise<DriverModel[]>;
|
|
66
|
+
}
|
|
67
|
+
/** One workspace-bound Claude Code session. `prompt` is a fresh CLI invocation. */
|
|
68
|
+
export declare class ClaudeCodeSession implements DriverSession {
|
|
69
|
+
private readonly config;
|
|
70
|
+
readonly id: string;
|
|
71
|
+
readonly cwd: string;
|
|
72
|
+
/** Path to the written `--mcp-config` file, lazily created on first use. */
|
|
73
|
+
private mcpConfigPath;
|
|
74
|
+
/**
|
|
75
|
+
* The agent's own session id from the last turn (#714). Retained so a
|
|
76
|
+
* {@link DriverPromptOptions.resume} prompt can `--resume` the same
|
|
77
|
+
* conversation; resume keeps the id stable, so consecutive chat messages chain.
|
|
78
|
+
*/
|
|
79
|
+
private lastSessionId;
|
|
80
|
+
readonly log?: SessionLog;
|
|
81
|
+
private readonly startOpts;
|
|
82
|
+
constructor(config: ClaudeCodeDriverOptions, startOpts: DriverStartOptions);
|
|
83
|
+
prompt(text: string, opts?: DriverPromptOptions): Promise<DriverTurn>;
|
|
84
|
+
readCode(path: string): Promise<string>;
|
|
85
|
+
dispose(): Promise<void>;
|
|
86
|
+
private buildArgs;
|
|
87
|
+
/**
|
|
88
|
+
* Lazily materialize the `--mcp-config` file for {@link ClaudeCodeDriverOptions.mcpServers}.
|
|
89
|
+
* Written once and reused across the session's prompts; `undefined` when no
|
|
90
|
+
* servers are configured. Not `--strict-mcp-config`, so these merge with the
|
|
91
|
+
* user's own MCP servers rather than replacing them.
|
|
92
|
+
*/
|
|
93
|
+
private mcpConfigFile;
|
|
94
|
+
}
|
|
95
|
+
/** The one argument that says what a tool call did, on one line and cut short. */
|
|
96
|
+
export declare function toolDetail(input: unknown): string | undefined;
|
|
97
|
+
/**
|
|
98
|
+
* Incremental parser for Claude Code's `stream-json` output: newline-delimited
|
|
99
|
+
* JSON, one object per line. We surface assistant text, thinking, tool calls and what each call
|
|
100
|
+
* gave back as {@link DriverEvent}s and keep the final `result` line as the turn text.
|
|
101
|
+
* Kept separate from the process plumbing so it is unit-testable in isolation.
|
|
102
|
+
*/
|
|
103
|
+
export declare class StreamJsonParser {
|
|
104
|
+
private finalText;
|
|
105
|
+
private assistantText;
|
|
106
|
+
private sessionId?;
|
|
107
|
+
private usage?;
|
|
108
|
+
/** The text block being written, as far as its pieces have got. */
|
|
109
|
+
private partial;
|
|
110
|
+
/** Feed one line; returns the events it produced (may be empty). */
|
|
111
|
+
push(line: string): DriverEvent[];
|
|
112
|
+
/**
|
|
113
|
+
* One piece of the message being written: a text block starts empty, and each piece of it adds
|
|
114
|
+
* to the text so far. Thinking and tool input come in pieces too; they are said once whole.
|
|
115
|
+
*/
|
|
116
|
+
private handlePiece;
|
|
117
|
+
private handleAssistant;
|
|
118
|
+
/**
|
|
119
|
+
* The CLI's own line after a tool call: a `user` message whose `tool_result` blocks each name
|
|
120
|
+
* the call (`tool_use_id`) and hold what it gave back. A result with no text says nothing. The
|
|
121
|
+
* line of an edit or a write also says, beside the message, what the call did to the file
|
|
122
|
+
* (`tool_use_result`): that is the result's `changed`.
|
|
123
|
+
*/
|
|
124
|
+
private handleResults;
|
|
125
|
+
/** The final turn: the `result` text, falling back to accumulated assistant text. */
|
|
126
|
+
result(): DriverTurn;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Whether a Claude Code session can start here: the CLI installed and logged in. Every part of
|
|
130
|
+
* the person's setup has a switch in Claude Code, so no part is ever a warning here (running as
|
|
131
|
+
* root still is).
|
|
132
|
+
*/
|
|
133
|
+
export declare function claudeCodeReady(opts?: DriverReadyOptions): Promise<DriverReadiness>;
|
|
134
|
+
//# sourceMappingURL=claude-code.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../src/claude-code.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
import { spawn as nodeSpawn } from 'node:child_process';
|
|
2
|
+
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { dirname, join } from 'node:path';
|
|
5
|
+
import { readClaudeQuota } from './claude-code-quota.js';
|
|
6
|
+
import { readClaudeModels } from './claude-code-models.js';
|
|
7
|
+
import { combineFraming, combineSignals, makeEmit, promptSent, readWorkspaceFile, cutOutput, callArgument, lineCount, patchSize, runCliSession, checkCliReady, finishTurn, agentEnv, attachLog } from '@openagt/agent-driver';
|
|
8
|
+
/**
|
|
9
|
+
* The first real {@link Driver}: wraps the **Claude Code CLI** in print mode
|
|
10
|
+
* (`claude -p --output-format stream-json`). Each {@link DriverSession.prompt}
|
|
11
|
+
* spawns a fresh non-interactive invocation, so every loop pass gets fresh
|
|
12
|
+
* context. We stream its JSON events to {@link DriverStartOptions.onEvent}
|
|
13
|
+
* for the caller's UI and return the final `result` text as the turn.
|
|
14
|
+
*
|
|
15
|
+
* True black box: we prompt and read the result; Claude Code owns its own loop,
|
|
16
|
+
* tools, and (subscription-based) auth. A second agent slots in behind the same
|
|
17
|
+
* `Driver` interface without touching the orchestration above it.
|
|
18
|
+
*/
|
|
19
|
+
export class ClaudeCodeDriver {
|
|
20
|
+
opts;
|
|
21
|
+
id = 'claude-code';
|
|
22
|
+
constructor(opts = {}) {
|
|
23
|
+
this.opts = opts;
|
|
24
|
+
}
|
|
25
|
+
start(opts) {
|
|
26
|
+
return Promise.resolve(new ClaudeCodeSession(withPersonal(this.opts), opts));
|
|
27
|
+
}
|
|
28
|
+
/** Where the account's subscription quota stands (#521). Account-wide, so no session. */
|
|
29
|
+
readQuota(opts = {}) {
|
|
30
|
+
const env = withPersonal(this.opts).env;
|
|
31
|
+
return readClaudeQuota({
|
|
32
|
+
...(this.opts.bin !== undefined ? { bin: this.opts.bin } : {}),
|
|
33
|
+
...(env !== undefined ? { env } : {}),
|
|
34
|
+
...(this.opts.spawn !== undefined ? { spawn: this.opts.spawn } : {}),
|
|
35
|
+
...(opts.signal !== undefined ? { signal: opts.signal } : {}),
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/** The models Claude Code's own `/model` picker offers, with the person's setup parts as a session loads them. */
|
|
39
|
+
listModels(opts = {}) {
|
|
40
|
+
const { bin, env, extraArgs, spawn } = withPersonal(this.opts);
|
|
41
|
+
return readClaudeModels({
|
|
42
|
+
...(bin !== undefined ? { bin } : {}),
|
|
43
|
+
...(env !== undefined ? { env } : {}),
|
|
44
|
+
...(extraArgs !== undefined ? { extraArgs } : {}),
|
|
45
|
+
...(spawn !== undefined ? { spawn } : {}),
|
|
46
|
+
...(opts.signal !== undefined ? { signal: opts.signal } : {}),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** The options with the person's setup parts that are off turned into Claude Code's own switches. */
|
|
51
|
+
function withPersonal(opts) {
|
|
52
|
+
const personal = opts.personal;
|
|
53
|
+
if (!personal)
|
|
54
|
+
return opts;
|
|
55
|
+
const env = { ...(opts.env ?? process.env) };
|
|
56
|
+
if (!personal.memory)
|
|
57
|
+
env['CLAUDE_CODE_DISABLE_AUTO_MEMORY'] = '1';
|
|
58
|
+
if (!personal.connectors)
|
|
59
|
+
env['ENABLE_CLAUDEAI_MCP_SERVERS'] = 'false';
|
|
60
|
+
const extraArgs = [...(personal.skills ? [] : ['--setting-sources', 'project,local']), ...(opts.extraArgs ?? [])];
|
|
61
|
+
return { ...opts, env, ...(extraArgs.length > 0 ? { extraArgs } : {}) };
|
|
62
|
+
}
|
|
63
|
+
let sessionCounter = 0;
|
|
64
|
+
/** One workspace-bound Claude Code session. `prompt` is a fresh CLI invocation. */
|
|
65
|
+
export class ClaudeCodeSession {
|
|
66
|
+
config;
|
|
67
|
+
id;
|
|
68
|
+
cwd;
|
|
69
|
+
/** Path to the written `--mcp-config` file, lazily created on first use. */
|
|
70
|
+
mcpConfigPath;
|
|
71
|
+
/**
|
|
72
|
+
* The agent's own session id from the last turn (#714). Retained so a
|
|
73
|
+
* {@link DriverPromptOptions.resume} prompt can `--resume` the same
|
|
74
|
+
* conversation; resume keeps the id stable, so consecutive chat messages chain.
|
|
75
|
+
*/
|
|
76
|
+
lastSessionId;
|
|
77
|
+
log;
|
|
78
|
+
startOpts;
|
|
79
|
+
constructor(config, startOpts) {
|
|
80
|
+
this.config = config;
|
|
81
|
+
const attached = attachLog(startOpts);
|
|
82
|
+
this.startOpts = attached.opts;
|
|
83
|
+
if (attached.log)
|
|
84
|
+
this.log = attached.log;
|
|
85
|
+
this.cwd = startOpts.cwd;
|
|
86
|
+
this.id = `claude-code-${++sessionCounter}`;
|
|
87
|
+
// Resume a finished agent (#720): seeding lastSessionId makes the very first `resume` prompt
|
|
88
|
+
// `--resume` this conversation, exactly as a mid-run chat turn continues its own session.
|
|
89
|
+
this.lastSessionId = startOpts.resumeSessionId;
|
|
90
|
+
}
|
|
91
|
+
async prompt(text, opts = {}) {
|
|
92
|
+
const system = combineFraming(this.startOpts.system, opts.system);
|
|
93
|
+
const resumeId = opts.resume ? this.lastSessionId : undefined;
|
|
94
|
+
const emit = makeEmit(this.startOpts.onEvent, 'claude-code');
|
|
95
|
+
const signals = combineSignals(this.startOpts.signal, opts.signal);
|
|
96
|
+
const agent = (id, emitFn) => runCliSession({
|
|
97
|
+
bin: this.config.bin ?? 'claude',
|
|
98
|
+
args: this.buildArgs(system, id),
|
|
99
|
+
cwd: this.cwd,
|
|
100
|
+
env: agentEnv(this.config.env ?? process.env, this.log),
|
|
101
|
+
prompt: text,
|
|
102
|
+
...(opts.added !== undefined ? { added: opts.added } : {}),
|
|
103
|
+
stdin: stdinLines(promptSent(text, opts.added)),
|
|
104
|
+
spawn: this.config.spawn ?? nodeSpawn,
|
|
105
|
+
emit: emitFn,
|
|
106
|
+
signals,
|
|
107
|
+
parser: new StreamJsonParser(),
|
|
108
|
+
driver: 'claude-code',
|
|
109
|
+
});
|
|
110
|
+
let turn;
|
|
111
|
+
// On a resume attempt, hold the failure's `error` event back until the conversation-gone
|
|
112
|
+
// case (#778) is ruled out: a turn that recovers on the retry must not show a failed row.
|
|
113
|
+
// Safe to hold — runCliSession emits `error` exactly once, right before it rejects.
|
|
114
|
+
let heldError;
|
|
115
|
+
try {
|
|
116
|
+
turn = await agent(resumeId, resumeId === undefined ? emit : event => {
|
|
117
|
+
if (event.type === 'error')
|
|
118
|
+
heldError = event;
|
|
119
|
+
else
|
|
120
|
+
emit(event);
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
// The id we captured outlives what the CLI will resume (#778) — its retention, a
|
|
125
|
+
// cleared history, another machine. There is no way to ask first, so let it fail
|
|
126
|
+
// once and continue as a fresh conversation (which gets the system framing back)
|
|
127
|
+
// rather than losing the message the user already typed.
|
|
128
|
+
if (resumeId === undefined || !isConversationGone(err) || signals.some(s => s.aborted)) {
|
|
129
|
+
if (heldError)
|
|
130
|
+
emit(heldError);
|
|
131
|
+
throw err;
|
|
132
|
+
}
|
|
133
|
+
this.lastSessionId = undefined;
|
|
134
|
+
emit({ type: 'notice', message: 'That conversation is no longer available; continuing without its history.' });
|
|
135
|
+
// The retry re-sends the same prompt; swallow its duplicate `start` so the user's
|
|
136
|
+
// message appears once in the transcript, not twice.
|
|
137
|
+
let startSeen = false;
|
|
138
|
+
turn = await agent(undefined, event => {
|
|
139
|
+
if (event.type === 'start' && !startSeen)
|
|
140
|
+
startSeen = true;
|
|
141
|
+
else
|
|
142
|
+
emit(event);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
// Track the agent's session so a later resume continues this exact conversation.
|
|
146
|
+
if (turn.sessionId)
|
|
147
|
+
this.lastSessionId = turn.sessionId;
|
|
148
|
+
return finishTurn(this, turn, opts, emit);
|
|
149
|
+
}
|
|
150
|
+
readCode(path) {
|
|
151
|
+
return readWorkspaceFile(this.cwd, path);
|
|
152
|
+
}
|
|
153
|
+
dispose() {
|
|
154
|
+
// Each prompt spawns and reaps its own process, so the only durable thing is
|
|
155
|
+
// the temp MCP config file; drop it. The session id reaches the UI via the
|
|
156
|
+
// emitted result event.
|
|
157
|
+
if (this.mcpConfigPath) {
|
|
158
|
+
try {
|
|
159
|
+
rmSync(dirname(this.mcpConfigPath), { recursive: true, force: true });
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
// Best effort: the temp dir lands under the OS tmp and is reaped anyway.
|
|
163
|
+
}
|
|
164
|
+
this.mcpConfigPath = undefined;
|
|
165
|
+
}
|
|
166
|
+
return Promise.resolve();
|
|
167
|
+
}
|
|
168
|
+
buildArgs(system, resumeId) {
|
|
169
|
+
// `--include-partial-messages`: the reply also comes in pieces as it is written, before the whole message.
|
|
170
|
+
const args = ['-p', '--input-format', 'stream-json', '--output-format', 'stream-json', '--verbose', '--include-partial-messages'];
|
|
171
|
+
if (this.config.dangerouslySkipPermissions)
|
|
172
|
+
args.push('--dangerously-skip-permissions');
|
|
173
|
+
else
|
|
174
|
+
args.push('--permission-mode', this.config.permissionMode ?? 'acceptEdits');
|
|
175
|
+
// Resume the same conversation for a chat turn (#714). Skip the system append then:
|
|
176
|
+
// the resumed transcript already carries its framing, so re-appending only duplicates it.
|
|
177
|
+
if (resumeId)
|
|
178
|
+
args.push('--resume', resumeId);
|
|
179
|
+
else if (system)
|
|
180
|
+
args.push('--append-system-prompt', system);
|
|
181
|
+
if (this.startOpts.model)
|
|
182
|
+
args.push('--model', this.startOpts.model);
|
|
183
|
+
const mcpConfig = this.mcpConfigFile();
|
|
184
|
+
if (mcpConfig)
|
|
185
|
+
args.push('--mcp-config', mcpConfig);
|
|
186
|
+
if (this.config.extraArgs)
|
|
187
|
+
args.push(...this.config.extraArgs);
|
|
188
|
+
return args;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Lazily materialize the `--mcp-config` file for {@link ClaudeCodeDriverOptions.mcpServers}.
|
|
192
|
+
* Written once and reused across the session's prompts; `undefined` when no
|
|
193
|
+
* servers are configured. Not `--strict-mcp-config`, so these merge with the
|
|
194
|
+
* user's own MCP servers rather than replacing them.
|
|
195
|
+
*/
|
|
196
|
+
mcpConfigFile() {
|
|
197
|
+
const servers = this.config.mcpServers;
|
|
198
|
+
if (!servers || Object.keys(servers).length === 0)
|
|
199
|
+
return undefined;
|
|
200
|
+
if (!this.mcpConfigPath) {
|
|
201
|
+
const dir = mkdtempSync(join(tmpdir(), 'agent-driver-mcp-'));
|
|
202
|
+
this.mcpConfigPath = join(dir, 'mcp.json');
|
|
203
|
+
writeFileSync(this.mcpConfigPath, JSON.stringify({ mcpServers: servers }));
|
|
204
|
+
}
|
|
205
|
+
return this.mcpConfigPath;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* The prompt as the CLI's stream-json input: first the request that turns thinking text on, then
|
|
210
|
+
* the user's message. A plain `-p` run sends thinking blocks with their text empty; asked for
|
|
211
|
+
* `summarized`, it fills them with its own short summary.
|
|
212
|
+
*/
|
|
213
|
+
function stdinLines(text) {
|
|
214
|
+
const thinking = { type: 'control_request', request_id: 'thinking', request: { subtype: 'set_max_thinking_tokens', max_thinking_tokens: null, thinking_display: 'summarized' } };
|
|
215
|
+
const message = { type: 'user', message: { role: 'user', content: text } };
|
|
216
|
+
return `${JSON.stringify(thinking)}\n${JSON.stringify(message)}\n`;
|
|
217
|
+
}
|
|
218
|
+
/** The input keys, in order, whose value says what a tool call did; the first one present is the call's detail. */
|
|
219
|
+
const DETAIL_KEYS = ['skill', 'command', 'file_path', 'notebook_path', 'path', 'url', 'pattern', 'query', 'description', 'prompt'];
|
|
220
|
+
/**
|
|
221
|
+
* What an edit or a write did to its file, off the CLI's own account of the call: a file it made
|
|
222
|
+
* holds its content's lines, all added; a file it changed holds a patch, whose `+` and `-` lines
|
|
223
|
+
* are counted. Any other call's account names no file this way, and says nothing.
|
|
224
|
+
*/
|
|
225
|
+
function fileChange(result) {
|
|
226
|
+
if (typeof result !== 'object' || result === null)
|
|
227
|
+
return undefined;
|
|
228
|
+
const account = result;
|
|
229
|
+
const path = account['filePath'];
|
|
230
|
+
if (typeof path !== 'string')
|
|
231
|
+
return undefined;
|
|
232
|
+
if (account['type'] === 'create')
|
|
233
|
+
return { path, added: typeof account['content'] === 'string' ? lineCount(account['content']) : 0, removed: 0, created: true };
|
|
234
|
+
const patch = account['structuredPatch'];
|
|
235
|
+
if (!Array.isArray(patch))
|
|
236
|
+
return undefined;
|
|
237
|
+
const lines = patch.flatMap(hunk => (typeof hunk === 'object' && hunk !== null && Array.isArray(hunk['lines']) ? hunk['lines'] : []));
|
|
238
|
+
return { path, ...patchSize(lines.filter((line) => typeof line === 'string')) };
|
|
239
|
+
}
|
|
240
|
+
/** The one argument that says what a tool call did, as it was given. */
|
|
241
|
+
function toolArgument(input) {
|
|
242
|
+
if (typeof input !== 'object' || input === null)
|
|
243
|
+
return undefined;
|
|
244
|
+
const fields = input;
|
|
245
|
+
const key = DETAIL_KEYS.find(k => typeof fields[k] === 'string' && fields[k].trim() !== '');
|
|
246
|
+
return key === undefined ? undefined : fields[key];
|
|
247
|
+
}
|
|
248
|
+
/** The one argument that says what a tool call did, on one line and cut short. */
|
|
249
|
+
export function toolDetail(input) {
|
|
250
|
+
return callArgument(toolArgument(input)).detail;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* What a tool gave back, from a `tool_result` block: its `content` is the text itself, or a list
|
|
254
|
+
* of blocks whose text ones hold it (an image block holds none).
|
|
255
|
+
*/
|
|
256
|
+
function resultText(content) {
|
|
257
|
+
if (typeof content === 'string')
|
|
258
|
+
return content;
|
|
259
|
+
if (!Array.isArray(content))
|
|
260
|
+
return '';
|
|
261
|
+
return content
|
|
262
|
+
.map(part => (typeof part === 'object' && part !== null && part['type'] === 'text' ? part['text'] : undefined))
|
|
263
|
+
.filter(text => typeof text === 'string')
|
|
264
|
+
.join('\n');
|
|
265
|
+
}
|
|
266
|
+
/** How the CLI reports that the session id we asked it to resume is gone from its history (#778). */
|
|
267
|
+
const CONVERSATION_GONE = /No conversation found with session ID/i;
|
|
268
|
+
/** Whether a failed turn failed because the conversation we tried to resume no longer exists. */
|
|
269
|
+
function isConversationGone(err) {
|
|
270
|
+
return CONVERSATION_GONE.test(err instanceof Error ? err.message : String(err));
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Incremental parser for Claude Code's `stream-json` output: newline-delimited
|
|
274
|
+
* JSON, one object per line. We surface assistant text, thinking, tool calls and what each call
|
|
275
|
+
* gave back as {@link DriverEvent}s and keep the final `result` line as the turn text.
|
|
276
|
+
* Kept separate from the process plumbing so it is unit-testable in isolation.
|
|
277
|
+
*/
|
|
278
|
+
export class StreamJsonParser {
|
|
279
|
+
finalText = '';
|
|
280
|
+
assistantText = '';
|
|
281
|
+
sessionId;
|
|
282
|
+
usage;
|
|
283
|
+
/** The text block being written, as far as its pieces have got. */
|
|
284
|
+
partial = '';
|
|
285
|
+
/** Feed one line; returns the events it produced (may be empty). */
|
|
286
|
+
push(line) {
|
|
287
|
+
const trimmed = line.trim();
|
|
288
|
+
if (!trimmed)
|
|
289
|
+
return [];
|
|
290
|
+
let obj;
|
|
291
|
+
try {
|
|
292
|
+
obj = JSON.parse(trimmed);
|
|
293
|
+
}
|
|
294
|
+
catch {
|
|
295
|
+
return []; // Non-JSON noise (banners etc.); ignore.
|
|
296
|
+
}
|
|
297
|
+
// `null` parses, so the catch above lets it through and every field read below throws — from
|
|
298
|
+
// inside a readline handler, where nothing catches it. Noise is noise whatever it parses to.
|
|
299
|
+
if (typeof obj !== 'object' || obj === null)
|
|
300
|
+
return [];
|
|
301
|
+
// Announced on the very first stream line, so it must not wait for `result`: a turn that is
|
|
302
|
+
// stopped or dies mid-flight would take the id — the agent's `claude --resume` handle — with
|
|
303
|
+
// it (#1322). Emitted only when it changes; every subsequent line repeats the same id.
|
|
304
|
+
const announced = [];
|
|
305
|
+
if (typeof obj['session_id'] === 'string' && obj['session_id'] !== this.sessionId) {
|
|
306
|
+
this.sessionId = obj['session_id'];
|
|
307
|
+
announced.push({ type: 'session', sessionId: this.sessionId });
|
|
308
|
+
}
|
|
309
|
+
const type = obj['type'];
|
|
310
|
+
// The CLI's first line names the model it resolved the pick to (`claude-opus-5-5` for `opus`),
|
|
311
|
+
// or the one it chose when none was picked: what the turn runs on, said before it runs.
|
|
312
|
+
if (type === 'system' && obj['subtype'] === 'init' && typeof obj['model'] === 'string' && obj['model'] !== '') {
|
|
313
|
+
announced.push({ type: 'model', model: obj['model'] });
|
|
314
|
+
}
|
|
315
|
+
if (type === 'assistant')
|
|
316
|
+
return [...announced, ...this.handleAssistant(obj)];
|
|
317
|
+
if (type === 'user')
|
|
318
|
+
return [...announced, ...this.handleResults(obj)];
|
|
319
|
+
if (type === 'stream_event')
|
|
320
|
+
return [...announced, ...this.handlePiece(obj['event'])];
|
|
321
|
+
if (type === 'rate_limit_event') {
|
|
322
|
+
const limit = parseRateLimit(obj);
|
|
323
|
+
return limit ? [...announced, { type: 'rate-limit', limit }] : announced;
|
|
324
|
+
}
|
|
325
|
+
if (type === 'result') {
|
|
326
|
+
const result = obj['result'];
|
|
327
|
+
if (typeof result === 'string')
|
|
328
|
+
this.finalText = result;
|
|
329
|
+
const usage = parseUsage(obj);
|
|
330
|
+
if (usage)
|
|
331
|
+
this.usage = usage;
|
|
332
|
+
return announced; // The `result` event is emitted by the runner after `close`.
|
|
333
|
+
}
|
|
334
|
+
return announced;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* One piece of the message being written: a text block starts empty, and each piece of it adds
|
|
338
|
+
* to the text so far. Thinking and tool input come in pieces too; they are said once whole.
|
|
339
|
+
*/
|
|
340
|
+
handlePiece(event) {
|
|
341
|
+
if (typeof event !== 'object' || event === null)
|
|
342
|
+
return [];
|
|
343
|
+
const e = event;
|
|
344
|
+
if (e['type'] === 'content_block_start') {
|
|
345
|
+
this.partial = '';
|
|
346
|
+
return [];
|
|
347
|
+
}
|
|
348
|
+
const delta = e['delta'];
|
|
349
|
+
if (e['type'] !== 'content_block_delta' || typeof delta !== 'object' || delta === null)
|
|
350
|
+
return [];
|
|
351
|
+
const d = delta;
|
|
352
|
+
if (d['type'] !== 'text_delta' || typeof d['text'] !== 'string' || d['text'] === '')
|
|
353
|
+
return [];
|
|
354
|
+
this.partial += d['text'];
|
|
355
|
+
return [{ type: 'partial', text: this.partial }];
|
|
356
|
+
}
|
|
357
|
+
handleAssistant(obj) {
|
|
358
|
+
const message = obj['message'];
|
|
359
|
+
if (typeof message !== 'object' || message === null)
|
|
360
|
+
return [];
|
|
361
|
+
const content = message['content'];
|
|
362
|
+
if (!Array.isArray(content))
|
|
363
|
+
return [];
|
|
364
|
+
const events = [];
|
|
365
|
+
for (const item of content) {
|
|
366
|
+
if (typeof item !== 'object' || item === null)
|
|
367
|
+
continue;
|
|
368
|
+
const block = item;
|
|
369
|
+
if (block['type'] === 'text' && typeof block['text'] === 'string') {
|
|
370
|
+
this.assistantText += block['text'];
|
|
371
|
+
events.push({ type: 'text', text: block['text'] });
|
|
372
|
+
}
|
|
373
|
+
else if (block['type'] === 'tool_use' && typeof block['name'] === 'string') {
|
|
374
|
+
events.push({ type: 'action', label: block['name'], ...callArgument(toolArgument(block['input'])), ...(typeof block['id'] === 'string' ? { id: block['id'] } : {}) });
|
|
375
|
+
}
|
|
376
|
+
else if (block['type'] === 'thinking' && typeof block['thinking'] === 'string' && block['thinking'].trim() !== '') {
|
|
377
|
+
events.push({ type: 'thought', text: block['thinking'].trim() });
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
return events;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* The CLI's own line after a tool call: a `user` message whose `tool_result` blocks each name
|
|
384
|
+
* the call (`tool_use_id`) and hold what it gave back. A result with no text says nothing. The
|
|
385
|
+
* line of an edit or a write also says, beside the message, what the call did to the file
|
|
386
|
+
* (`tool_use_result`): that is the result's `changed`.
|
|
387
|
+
*/
|
|
388
|
+
handleResults(obj) {
|
|
389
|
+
const message = obj['message'];
|
|
390
|
+
if (typeof message !== 'object' || message === null)
|
|
391
|
+
return [];
|
|
392
|
+
const content = message['content'];
|
|
393
|
+
if (!Array.isArray(content))
|
|
394
|
+
return [];
|
|
395
|
+
const events = [];
|
|
396
|
+
// The line describes one call: with several results on it, there is no telling whose it is.
|
|
397
|
+
const change = content.length === 1 ? fileChange(obj['tool_use_result']) : undefined;
|
|
398
|
+
for (const item of content) {
|
|
399
|
+
if (typeof item !== 'object' || item === null)
|
|
400
|
+
continue;
|
|
401
|
+
const block = item;
|
|
402
|
+
if (block['type'] !== 'tool_result' || typeof block['tool_use_id'] !== 'string')
|
|
403
|
+
continue;
|
|
404
|
+
const text = cutOutput(resultText(block['content']));
|
|
405
|
+
const failed = block['is_error'] === true;
|
|
406
|
+
if (text === '' && !failed && !change)
|
|
407
|
+
continue;
|
|
408
|
+
events.push({ type: 'output', id: block['tool_use_id'], text, ...(failed ? { failed: true } : {}), ...(change && !failed ? { changed: [change] } : {}) });
|
|
409
|
+
}
|
|
410
|
+
return events;
|
|
411
|
+
}
|
|
412
|
+
/** The final turn: the `result` text, falling back to accumulated assistant text. */
|
|
413
|
+
result() {
|
|
414
|
+
const text = this.finalText || this.assistantText;
|
|
415
|
+
return {
|
|
416
|
+
text,
|
|
417
|
+
...(this.sessionId ? { sessionId: this.sessionId } : {}),
|
|
418
|
+
...(this.usage ? { usage: this.usage } : {}),
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Pull the account's quota standing off a `rate_limit_event` line (#517):
|
|
424
|
+
* `{status, resetsAt, rateLimitType}`. The agent emits one per turn, so this is
|
|
425
|
+
* free telemetry — no extra call, no polling. Returns undefined when the payload
|
|
426
|
+
* is missing the parts we'd gate on, so a malformed line stays silent rather
|
|
427
|
+
* than reporting a bogus reset.
|
|
428
|
+
*/
|
|
429
|
+
function parseRateLimit(obj) {
|
|
430
|
+
const raw = obj['rate_limit_info'];
|
|
431
|
+
if (typeof raw !== 'object' || raw === null)
|
|
432
|
+
return undefined;
|
|
433
|
+
const info = raw;
|
|
434
|
+
const status = info['status'];
|
|
435
|
+
const window = info['rateLimitType'];
|
|
436
|
+
const resetsAt = info['resetsAt'];
|
|
437
|
+
if (typeof status !== 'string' || typeof window !== 'string')
|
|
438
|
+
return undefined;
|
|
439
|
+
if (typeof resetsAt !== 'number' || !Number.isFinite(resetsAt))
|
|
440
|
+
return undefined;
|
|
441
|
+
// The agent reports epoch seconds; `resetsAt` is millis.
|
|
442
|
+
return { status, window, resetsAt: resetsAt * 1000 };
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Pull token + cost accounting off Claude Code's `result` line (#322):
|
|
446
|
+
* `total_cost_usd` plus a `usage` object of token counts. Returns undefined when
|
|
447
|
+
* the line carries neither, so a driver/agent that omits usage stays usage-free.
|
|
448
|
+
*/
|
|
449
|
+
function parseUsage(obj) {
|
|
450
|
+
const cost = obj['total_cost_usd'];
|
|
451
|
+
const raw = obj['usage'];
|
|
452
|
+
const hasUsage = typeof raw === 'object' && raw !== null;
|
|
453
|
+
if (typeof cost !== 'number' && !hasUsage)
|
|
454
|
+
return undefined;
|
|
455
|
+
const usage = (hasUsage ? raw : {});
|
|
456
|
+
const num = (v) => (typeof v === 'number' && Number.isFinite(v) ? v : 0);
|
|
457
|
+
// Omit costUsd when there is no price, never 0: a spending limit reads 0 as "free"
|
|
458
|
+
// and undefined as "unknown" (#540), and Codex reports tokens without a price.
|
|
459
|
+
return {
|
|
460
|
+
...(typeof cost === 'number' && Number.isFinite(cost) ? { costUsd: cost } : {}),
|
|
461
|
+
inputTokens: num(usage['input_tokens']),
|
|
462
|
+
outputTokens: num(usage['output_tokens']),
|
|
463
|
+
cacheReadTokens: num(usage['cache_read_input_tokens']),
|
|
464
|
+
cacheCreationTokens: num(usage['cache_creation_input_tokens']),
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
/** How the Claude Code CLI is asked whether a session can start. */
|
|
468
|
+
const CLAUDE_CLI = {
|
|
469
|
+
bin: 'claude',
|
|
470
|
+
install: 'install Claude Code and make sure `claude` is on your PATH: https://claude.com/claude-code',
|
|
471
|
+
authArgs: ['auth', 'status'],
|
|
472
|
+
// Prints JSON (`{"loggedIn": true, ...}`) and exits 0 either way, so the flag is the answer.
|
|
473
|
+
// A version too old to know the subcommand prints usage, which reads as "could not say".
|
|
474
|
+
loggedIn: ({ output }) => {
|
|
475
|
+
try {
|
|
476
|
+
const value = JSON.parse(output)?.['loggedIn'];
|
|
477
|
+
return typeof value === 'boolean' ? value : undefined;
|
|
478
|
+
}
|
|
479
|
+
catch {
|
|
480
|
+
return undefined;
|
|
481
|
+
}
|
|
482
|
+
},
|
|
483
|
+
login: 'claude auth login',
|
|
484
|
+
};
|
|
485
|
+
/**
|
|
486
|
+
* Whether a Claude Code session can start here: the CLI installed and logged in. Every part of
|
|
487
|
+
* the person's setup has a switch in Claude Code, so no part is ever a warning here (running as
|
|
488
|
+
* root still is).
|
|
489
|
+
*/
|
|
490
|
+
export function claudeCodeReady(opts = {}) {
|
|
491
|
+
return checkCliReady(CLAUDE_CLI, opts);
|
|
492
|
+
}
|
|
493
|
+
//# sourceMappingURL=claude-code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../src/claude-code.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { ClaudeCodeDriver, ClaudeCodeSession, StreamJsonParser, claudeCodeReady, type ClaudeCodeDriverOptions, type McpServerSpec, type PermissionMode } from './claude-code.js';
|
|
2
|
+
export { readClaudeQuota, parseQuotaReadout, type ReadClaudeQuotaOptions } from './claude-code-quota.js';
|
|
3
|
+
export { readClaudeModels, parseInitializeLine, type ReadClaudeModelsOptions } from './claude-code-models.js';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,eAAe,EAAE,KAAK,uBAAuB,EAAE,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAChL,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,wBAAwB,CAAA;AACxG,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,KAAK,uBAAuB,EAAE,MAAM,yBAAyB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { ClaudeCodeDriver, ClaudeCodeSession, StreamJsonParser, claudeCodeReady } from './claude-code.js';
|
|
2
|
+
export { readClaudeQuota, parseQuotaReadout } from './claude-code-quota.js';
|
|
3
|
+
export { readClaudeModels, parseInitializeLine } from './claude-code-models.js';
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,eAAe,EAAyE,MAAM,kBAAkB,CAAA;AAChL,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAA+B,MAAM,wBAAwB,CAAA;AACxG,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAgC,MAAM,yBAAyB,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,40 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openagt/agent-driver-claude",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Claude Code behind the agent-driver contract, on this machine; plus the reader of the account's quota.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/framework/the-framework.git",
|
|
9
|
+
"directory": "packages/agent-driver/claude"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=22.12.0"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"default": "./dist/index.js"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@openagt/agent-driver": "0.0.1"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^20.0.0",
|
|
29
|
+
"typescript": "^7.0.2"
|
|
30
|
+
},
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "tsc -p tsconfig.build.json",
|
|
36
|
+
"typecheck": "tsc --noEmit",
|
|
37
|
+
"test": "tsc -p tsconfig.test.json && node --test --test-timeout=60000 'dist-test/**/*.test.js'",
|
|
38
|
+
"clean": "rm -rf dist dist-test"
|
|
39
|
+
}
|
|
6
40
|
}
|
package/README.md
DELETED