@tomradex/engine-claude-code 0.0.0-stage → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +204 -0
- package/dist/availability.d.ts +50 -0
- package/dist/cli.d.ts +32 -0
- package/dist/engine.d.ts +32 -0
- package/dist/index.d.ts +20 -0
- package/dist/lend-cli.d.ts +30 -0
- package/dist/lend.d.ts +14 -0
- package/dist/locate.d.ts +146 -0
- package/dist/mcp-link.d.ts +45 -0
- package/dist/permissions.d.ts +7 -0
- package/dist/runtime.d.ts +48 -0
- package/dist/runtime.js +1 -0
- package/dist/sdk.d.ts +37 -0
- package/dist/system.d.ts +18 -0
- package/dist/usage.d.ts +75 -0
- package/package.json +42 -4
- package/README.md +0 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
Copyright 2026 Haoyuan Tang
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
Apache License
|
|
5
|
+
Version 2.0, January 2004
|
|
6
|
+
http://www.apache.org/licenses/
|
|
7
|
+
|
|
8
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
9
|
+
|
|
10
|
+
1. Definitions.
|
|
11
|
+
|
|
12
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
13
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
14
|
+
|
|
15
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
16
|
+
the copyright owner that is granting the License.
|
|
17
|
+
|
|
18
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
19
|
+
other entities that control, are controlled by, or are under common
|
|
20
|
+
control with that entity. For the purposes of this definition,
|
|
21
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
22
|
+
direction or management of such entity, whether by contract or
|
|
23
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
24
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
25
|
+
|
|
26
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
27
|
+
exercising permissions granted by this License.
|
|
28
|
+
|
|
29
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
30
|
+
including but not limited to software source code, documentation
|
|
31
|
+
source, and configuration files.
|
|
32
|
+
|
|
33
|
+
"Object" form shall mean any form resulting from mechanical
|
|
34
|
+
transformation or translation of a Source form, including but
|
|
35
|
+
not limited to compiled object code, generated documentation,
|
|
36
|
+
and conversions to other media types.
|
|
37
|
+
|
|
38
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
39
|
+
Object form, made available under the License, as indicated by a
|
|
40
|
+
copyright notice that is included in or attached to the work
|
|
41
|
+
(an example is provided in the Appendix below).
|
|
42
|
+
|
|
43
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
44
|
+
form, that is based on (or derived from) the Work and for which the
|
|
45
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
46
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
47
|
+
of this License, Derivative Works shall not include works that remain
|
|
48
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
49
|
+
the Work and Derivative Works thereof.
|
|
50
|
+
|
|
51
|
+
"Contribution" shall mean any work of authorship, including
|
|
52
|
+
the original version of the Work and any modifications or additions
|
|
53
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
54
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
55
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
56
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
57
|
+
means any form of electronic, verbal, or written communication sent
|
|
58
|
+
to the Licensor or its representatives, including but not limited to
|
|
59
|
+
communication on electronic mailing lists, source code control systems,
|
|
60
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
61
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
62
|
+
excluding communication that is conspicuously marked or otherwise
|
|
63
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
64
|
+
|
|
65
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
66
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
67
|
+
subsequently incorporated within the Work.
|
|
68
|
+
|
|
69
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
70
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
71
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
72
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
73
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
74
|
+
Work and such Derivative Works in Source or Object form.
|
|
75
|
+
|
|
76
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
77
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
78
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
79
|
+
(except as stated in this section) patent license to make, have made,
|
|
80
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
81
|
+
where such license applies only to those patent claims licensable
|
|
82
|
+
by such Contributor that are necessarily infringed by their
|
|
83
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
84
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
85
|
+
institute patent litigation against any entity (including a
|
|
86
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
87
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
88
|
+
or contributory patent infringement, then any patent licenses
|
|
89
|
+
granted to You under this License for that Work shall terminate
|
|
90
|
+
as of the date such litigation is filed.
|
|
91
|
+
|
|
92
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
93
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
94
|
+
modifications, and in Source or Object form, provided that You
|
|
95
|
+
meet the following conditions:
|
|
96
|
+
|
|
97
|
+
(a) You must give any other recipients of the Work or
|
|
98
|
+
Derivative Works a copy of this License; and
|
|
99
|
+
|
|
100
|
+
(b) You must cause any modified files to carry prominent notices
|
|
101
|
+
stating that You changed the files; and
|
|
102
|
+
|
|
103
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
104
|
+
that You distribute, all copyright, patent, trademark, and
|
|
105
|
+
attribution notices from the Source form of the Work,
|
|
106
|
+
excluding those notices that do not pertain to any part of
|
|
107
|
+
the Derivative Works; and
|
|
108
|
+
|
|
109
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
110
|
+
distribution, then any Derivative Works that You distribute must
|
|
111
|
+
include a readable copy of the attribution notices contained
|
|
112
|
+
within such NOTICE file, excluding those notices that do not
|
|
113
|
+
pertain to any part of the Derivative Works, in at least one
|
|
114
|
+
of the following places: within a NOTICE text file distributed
|
|
115
|
+
as part of the Derivative Works; within the Source form or
|
|
116
|
+
documentation, if provided along with the Derivative Works; or,
|
|
117
|
+
within a display generated by the Derivative Works, if and
|
|
118
|
+
wherever such third-party notices normally appear. The contents
|
|
119
|
+
of the NOTICE file are for informational purposes only and
|
|
120
|
+
do not modify the License. You may add Your own attribution
|
|
121
|
+
notices within Derivative Works that You distribute, alongside
|
|
122
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
123
|
+
that such additional attribution notices cannot be construed
|
|
124
|
+
as modifying the License.
|
|
125
|
+
|
|
126
|
+
You may add Your own copyright statement to Your modifications and
|
|
127
|
+
may provide additional or different license terms and conditions
|
|
128
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
129
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
130
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
131
|
+
the conditions stated in this License.
|
|
132
|
+
|
|
133
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
134
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
135
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
136
|
+
this License, without any additional terms or conditions.
|
|
137
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
138
|
+
the terms of any separate license agreement you may have executed
|
|
139
|
+
with Licensor regarding such Contributions.
|
|
140
|
+
|
|
141
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
142
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
143
|
+
except as required for reasonable and customary use in describing the
|
|
144
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
145
|
+
|
|
146
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
147
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
148
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
149
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
150
|
+
implied, including, without limitation, any warranties or conditions
|
|
151
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
152
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
153
|
+
appropriateness of using or redistributing the Work and assume any
|
|
154
|
+
risks associated with Your exercise of permissions under this License.
|
|
155
|
+
|
|
156
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
157
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
158
|
+
unless required by applicable law (such as deliberate and grossly
|
|
159
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
160
|
+
liable to You for damages, including any direct, indirect, special,
|
|
161
|
+
incidental, or consequential damages of any character arising as a
|
|
162
|
+
result of this License or out of the use or inability to use the
|
|
163
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
164
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
165
|
+
other commercial damages or losses), even if such Contributor
|
|
166
|
+
has been advised of the possibility of such damages.
|
|
167
|
+
|
|
168
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
169
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
170
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
171
|
+
or other liability obligations and/or rights consistent with this
|
|
172
|
+
License. However, in accepting such obligations, You may act only
|
|
173
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
174
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
175
|
+
defend, and hold each Contributor harmless for any liability
|
|
176
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
177
|
+
of your accepting any such warranty or additional liability.
|
|
178
|
+
|
|
179
|
+
END OF TERMS AND CONDITIONS
|
|
180
|
+
|
|
181
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
182
|
+
|
|
183
|
+
To apply the Apache License to your work, attach the following
|
|
184
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
185
|
+
replaced with your own identifying information. (Don't include
|
|
186
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
187
|
+
comment syntax for the file format. We also recommend that a
|
|
188
|
+
file or class name and description of purpose be included on the
|
|
189
|
+
same "printed page" as the copyright notice for easier
|
|
190
|
+
identification within third-party archives.
|
|
191
|
+
|
|
192
|
+
Copyright [yyyy] [name of copyright owner]
|
|
193
|
+
|
|
194
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
195
|
+
you may not use this file except in compliance with the License.
|
|
196
|
+
You may obtain a copy of the License at
|
|
197
|
+
|
|
198
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
199
|
+
|
|
200
|
+
Unless required by applicable law or agreed to in writing, software
|
|
201
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
202
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
203
|
+
See the License for the specific language governing permissions and
|
|
204
|
+
limitations under the License.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { Context } from "cordis";
|
|
2
|
+
import type { EngineAvailability, EngineNeed } from "@tomradex/agent";
|
|
3
|
+
import { type CliLocator } from "./locate.js";
|
|
4
|
+
interface LocalEngine {
|
|
5
|
+
engineId: string;
|
|
6
|
+
title: string;
|
|
7
|
+
cli: CliLocator;
|
|
8
|
+
/** The English tail of "not found — …". */
|
|
9
|
+
install: string;
|
|
10
|
+
/**
|
|
11
|
+
* Whether the CLI can work yet: a run whose output answers, or the engine's own `ask` (null: no clear answer,
|
|
12
|
+
* taken as yes). `need` is what a "no" means (default: signing in).
|
|
13
|
+
*/
|
|
14
|
+
signIn?: ({
|
|
15
|
+
args: string[];
|
|
16
|
+
says(output: string): boolean | null;
|
|
17
|
+
} | {
|
|
18
|
+
ask(command: string | undefined): Promise<boolean | null>;
|
|
19
|
+
}) & {
|
|
20
|
+
reason: string;
|
|
21
|
+
need?: EngineNeed;
|
|
22
|
+
};
|
|
23
|
+
/** Where the CLI reads its sign-in and settings from, shown when it is not signed in. */
|
|
24
|
+
configDir?(): string;
|
|
25
|
+
/** A desktop app of the same agent that does not include the CLI: named when the CLI is missing but the app is there. */
|
|
26
|
+
desktopApp?: DesktopApp;
|
|
27
|
+
}
|
|
28
|
+
export interface DesktopApp {
|
|
29
|
+
title: string;
|
|
30
|
+
/** macOS bundle names, looked for in /Applications and ~/Applications. */
|
|
31
|
+
mac?: string[];
|
|
32
|
+
/** Windows install folders, relative to %LOCALAPPDATA% or Program Files. */
|
|
33
|
+
windows?: string[];
|
|
34
|
+
/** Further places, as absolute paths. */
|
|
35
|
+
paths?: string[];
|
|
36
|
+
}
|
|
37
|
+
/** Where a desktop app may be installed on this machine, whether or not it is. */
|
|
38
|
+
export declare function desktopAppPaths(app: DesktopApp, host?: {
|
|
39
|
+
platform: NodeJS.Platform;
|
|
40
|
+
env: NodeJS.ProcessEnv;
|
|
41
|
+
home: string;
|
|
42
|
+
}): string[];
|
|
43
|
+
/** The CLI path the person chose in Settings, if any. */
|
|
44
|
+
export declare function chosenCommand(ctx: Context, engineId: string): string | undefined;
|
|
45
|
+
/** A local agent is ready when its CLI runs, the MCP server it calls back on is up, and it is signed in. */
|
|
46
|
+
export declare function localAvailability(ctx: Context, engine: LocalEngine): (opts?: {
|
|
47
|
+
fresh?: boolean;
|
|
48
|
+
}) => Promise<EngineAvailability>;
|
|
49
|
+
export {};
|
|
50
|
+
//# sourceMappingURL=availability.d.ts.map
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ChildProcess } from "node:child_process";
|
|
2
|
+
import { type CliLaunch, type CliLocator } from "./locate.js";
|
|
3
|
+
/**
|
|
4
|
+
* Whether a CLI that is installed is also signed in. Only a clear "no" says
|
|
5
|
+
* so: a version without the subcommand, a timeout or an answer that cannot be
|
|
6
|
+
* read is taken as signed in, so the check never locks out an account it does
|
|
7
|
+
* not understand (an API key in the environment, a cloud provider).
|
|
8
|
+
*/
|
|
9
|
+
export declare function signedIn(cli: CliLocator, command: string | undefined, args: string[], says: (output: string) => boolean | null): Promise<boolean>;
|
|
10
|
+
/** Claude Code cannot resume a session that is not under the current CLAUDE_CONFIG_DIR (moved, cleared, another folder). */
|
|
11
|
+
export declare const lostConversation: (text: string | undefined) => boolean;
|
|
12
|
+
/** `claude auth status` prints JSON with `loggedIn`; a first-party account that is not logged in cannot run. */
|
|
13
|
+
export declare function claudeSignedIn(output: string): boolean | null;
|
|
14
|
+
export interface CliRun {
|
|
15
|
+
child: ChildProcess;
|
|
16
|
+
/** Resolves when the process exits; each stdout line is handed to onLine as parsed JSON. */
|
|
17
|
+
done: Promise<{
|
|
18
|
+
code: number | null;
|
|
19
|
+
stderr: string;
|
|
20
|
+
}>;
|
|
21
|
+
}
|
|
22
|
+
/** Spawn a JSONL-speaking CLI: stdin closed, stdout parsed by line, SIGINT then SIGKILL on abort. */
|
|
23
|
+
export declare function runJsonl(launch: CliLaunch, args: string[], opts: {
|
|
24
|
+
cwd: string;
|
|
25
|
+
env?: NodeJS.ProcessEnv;
|
|
26
|
+
stdin?: string;
|
|
27
|
+
signal: AbortSignal;
|
|
28
|
+
onLine(event: Record<string, unknown>): void;
|
|
29
|
+
}): CliRun;
|
|
30
|
+
/** Splits on LF only: readline also breaks on U+2028/U+2029, which are legal inside JSON strings. */
|
|
31
|
+
export declare function lineSplitter(onLine: (line: string) => void): (chunk: Buffer) => void;
|
|
32
|
+
//# sourceMappingURL=cli.d.ts.map
|
package/dist/engine.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Context } from "cordis";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import type { Engine } from "@tomradex/agent";
|
|
4
|
+
export declare const ClaudeCodeOptions: z.ZodObject<{
|
|
5
|
+
command: z.ZodDefault<z.ZodString>;
|
|
6
|
+
model: z.ZodOptional<z.ZodString>;
|
|
7
|
+
effort: z.ZodOptional<z.ZodString>;
|
|
8
|
+
maxTurns: z.ZodDefault<z.ZodNumber>;
|
|
9
|
+
maxBudgetUsd: z.ZodOptional<z.ZodNumber>;
|
|
10
|
+
allowTools: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
11
|
+
codeMaxTurns: z.ZodOptional<z.ZodNumber>;
|
|
12
|
+
codePermissionMode: z.ZodOptional<z.ZodEnum<{
|
|
13
|
+
default: "default";
|
|
14
|
+
acceptEdits: "acceptEdits";
|
|
15
|
+
bypassPermissions: "bypassPermissions";
|
|
16
|
+
dontAsk: "dontAsk";
|
|
17
|
+
auto: "auto";
|
|
18
|
+
plan: "plan";
|
|
19
|
+
}>>;
|
|
20
|
+
}, z.core.$strip>;
|
|
21
|
+
export type ClaudeCodeOptions = z.infer<typeof ClaudeCodeOptions>;
|
|
22
|
+
/** Why Claude Code is sending a request again (its `api_retry` message), in a few words. */
|
|
23
|
+
export declare function retryReason(message: {
|
|
24
|
+
error_status: number | null;
|
|
25
|
+
error: string;
|
|
26
|
+
no_response?: {
|
|
27
|
+
waited_ms: number;
|
|
28
|
+
};
|
|
29
|
+
}): string;
|
|
30
|
+
/** Everything about the Claude Code engine except how a turn runs: identity, options, availability, setup. */
|
|
31
|
+
export declare function claudeCodeEngineInfo(ctx: Context): Omit<Engine, "turn">;
|
|
32
|
+
//# sourceMappingURL=engine.d.ts.map
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Context } from "cordis";
|
|
2
|
+
import type { Engine } from "@tomradex/agent";
|
|
3
|
+
export declare function createClaudeCodeEngine(ctx: Context): Engine;
|
|
4
|
+
declare const _default: {
|
|
5
|
+
name: string;
|
|
6
|
+
inject: string[];
|
|
7
|
+
apply(ctx: Context): void;
|
|
8
|
+
};
|
|
9
|
+
export default _default;
|
|
10
|
+
export { ClaudeCodeOptions, claudeCodeEngineInfo, retryReason } from "./engine.js";
|
|
11
|
+
export { claudeSignedIn, lineSplitter, runJsonl, signedIn } from "./cli.js";
|
|
12
|
+
export { localAvailability, chosenCommand, desktopAppPaths, type DesktopApp } from "./availability.js";
|
|
13
|
+
export { claudeLentModel, LENT_IDLE_MS } from "./lend.js";
|
|
14
|
+
export { cliLentModel, NotSignedIn, SIGN_IN_RECHECK_MS, type CliAnswer } from "./lend-cli.js";
|
|
15
|
+
export { MCP_NAME, claudeConfigDirOf, claudeConfigDirs, claudeMcpLink, claudeProfileEnv, claudeProjectServerApproval, claudeUserFile, userMcpLink, type UserMcpConfig } from "./mcp-link.js";
|
|
16
|
+
export { bashRuleMatches, claudeCommands, userSettingsFile } from "./permissions.js";
|
|
17
|
+
export { CliLocator, localCli, launchFor, bundledLaunch, spawnCli, stopCli, cliReason, describeRun, fileNames, shimTarget, cmdArgument, cmdLine, parseRegPath, expandWindowsVars, splitPath, knownDirs, type BundledCli, type CliHost, type CliLaunch, type CliRunResult } from "./locate.js";
|
|
18
|
+
export { promptOf, sessionSystem, staticSystem, turnPrompt } from "./system.js";
|
|
19
|
+
export { RuntimePool, runtimeFingerprint, runtimeDirectory, bindTurn, type Runtime } from "./runtime.js";
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type ChatRequest, type LentModel } from "@tomradex/llm";
|
|
2
|
+
/** The CLI said, in its own words, that it is not signed in. */
|
|
3
|
+
export declare class NotSignedIn extends Error {
|
|
4
|
+
}
|
|
5
|
+
export interface CliAnswer {
|
|
6
|
+
text: string;
|
|
7
|
+
/** All of the input, what the cache read included. */
|
|
8
|
+
inputTokens: number;
|
|
9
|
+
cacheReadTokens?: number;
|
|
10
|
+
outputTokens: number;
|
|
11
|
+
}
|
|
12
|
+
/** A CLI found signed out, or whose check said nothing clear, is asked again after this long. */
|
|
13
|
+
export declare const SIGN_IN_RECHECK_MS = 30000;
|
|
14
|
+
/**
|
|
15
|
+
* A lent model over a CLI with no sign-in status command, each call a process
|
|
16
|
+
* of its own. Whether it is signed in is learned by asking: one tiny prompt the
|
|
17
|
+
* first time (a signed-out CLI refuses it at once, before any model call), then
|
|
18
|
+
* what each call says. Only a clear "not signed in" makes it unready.
|
|
19
|
+
*/
|
|
20
|
+
export declare function cliLentModel(opts: {
|
|
21
|
+
id: string;
|
|
22
|
+
title: string;
|
|
23
|
+
rank?: number;
|
|
24
|
+
/** Whether the CLI is there to run. */
|
|
25
|
+
found(): Promise<boolean>;
|
|
26
|
+
/** One answer; throws NotSignedIn when the CLI says it is not signed in. */
|
|
27
|
+
ask(request: ChatRequest, signal?: AbortSignal): Promise<CliAnswer>;
|
|
28
|
+
recheckMs?: number;
|
|
29
|
+
}): LentModel;
|
|
30
|
+
//# sourceMappingURL=lend-cli.d.ts.map
|
package/dist/lend.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Context } from "cordis";
|
|
2
|
+
import { type LentModel } from "@tomradex/llm";
|
|
3
|
+
/** A kept session that answered nothing for this long exits; the next call starts one again. */
|
|
4
|
+
export declare const LENT_IDLE_MS: number;
|
|
5
|
+
/**
|
|
6
|
+
* The signed-in Claude Code answering worker calls. One session is kept warm
|
|
7
|
+
* between calls; a call arriving while it is busy runs in a process of its own.
|
|
8
|
+
*/
|
|
9
|
+
export declare function claudeLentModel(ctx: Context, ready: () => Promise<boolean>, opts?: {
|
|
10
|
+
idleMs?: number;
|
|
11
|
+
}): LentModel & {
|
|
12
|
+
close(): void;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=lend.d.ts.map
|
package/dist/locate.d.ts
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { type ChildProcess, type SpawnOptions } from "node:child_process";
|
|
2
|
+
import type { CliCheck, LocalCliStatus } from "@tomradex/agent";
|
|
3
|
+
/**
|
|
4
|
+
* Finding a local agent's CLI the way a person's terminal would, and starting
|
|
5
|
+
* it the way that terminal would. An app opened from the Dock or the Start menu
|
|
6
|
+
* has a thinner PATH than the terminal the CLI was installed from, and on
|
|
7
|
+
* Windows npm installs `codex.cmd`, which Node can neither find without PATHEXT
|
|
8
|
+
* nor start without a shell.
|
|
9
|
+
*/
|
|
10
|
+
/** What the locator needs from the machine; tests swap it for a fake one. */
|
|
11
|
+
export interface CliHost {
|
|
12
|
+
platform: NodeJS.Platform;
|
|
13
|
+
arch: string;
|
|
14
|
+
env: NodeJS.ProcessEnv;
|
|
15
|
+
home: string;
|
|
16
|
+
/** PATH as a new terminal would see it now: the registry on Windows, a login shell elsewhere. */
|
|
17
|
+
freshPath(): Promise<string[]>;
|
|
18
|
+
/** Where `npm i -g` puts commands, if npm answers. */
|
|
19
|
+
npmPrefix(): Promise<string | null>;
|
|
20
|
+
/** The CLI's path inside WSL, when Windows has WSL and the CLI is installed there. */
|
|
21
|
+
wsl(name: string): Promise<string | null>;
|
|
22
|
+
/** Where Windows' installed-apps list says apps whose display name matches were installed; none elsewhere. */
|
|
23
|
+
installs(displayName: RegExp): Promise<string[]>;
|
|
24
|
+
run(launch: CliLaunch, args: string[], timeoutMs: number): Promise<CliRunResult>;
|
|
25
|
+
}
|
|
26
|
+
export interface CliRunResult {
|
|
27
|
+
code: number | null;
|
|
28
|
+
stdout: string;
|
|
29
|
+
stderr: string;
|
|
30
|
+
/** Set when there was no exit to report: the file did not start, or it was stopped for taking too long. */
|
|
31
|
+
error?: {
|
|
32
|
+
code?: string | number | null;
|
|
33
|
+
killed?: boolean;
|
|
34
|
+
message: string;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** How to start one resolved CLI file. */
|
|
38
|
+
export interface CliLaunch {
|
|
39
|
+
file: string;
|
|
40
|
+
/** The program and arguments that run `file` with these arguments. */
|
|
41
|
+
argv(args: string[]): {
|
|
42
|
+
command: string;
|
|
43
|
+
args: string[];
|
|
44
|
+
verbatim?: boolean;
|
|
45
|
+
};
|
|
46
|
+
/** The environment to start it with: the CLI's own folder (and its node) first on PATH. */
|
|
47
|
+
env(base?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
|
48
|
+
}
|
|
49
|
+
export declare function splitPath(value: string | undefined, platform: NodeJS.Platform): string[];
|
|
50
|
+
/** The file names a bare command may have in one directory: PATHEXT's runnable kinds on Windows. */
|
|
51
|
+
export declare function fileNames(name: string, platform: NodeJS.Platform, pathext?: string): string[];
|
|
52
|
+
/** `%APPDATA%\npm` → the folder itself. Unknown names stay as written, like cmd does. */
|
|
53
|
+
export declare function expandWindowsVars(value: string, env: NodeJS.ProcessEnv): string;
|
|
54
|
+
/** The Path value out of `reg query … /v Path`. */
|
|
55
|
+
export declare function parseRegPath(output: string): string | null;
|
|
56
|
+
/**
|
|
57
|
+
* The install folders in `reg query …\Uninstall /s` output of the apps whose
|
|
58
|
+
* DisplayName matches: InstallLocation, else the folder of the icon or the uninstaller.
|
|
59
|
+
*/
|
|
60
|
+
export declare function parseRegInstalls(output: string, displayName: RegExp): string[];
|
|
61
|
+
/**
|
|
62
|
+
* npm, pnpm and yarn install a command on Windows as a `.cmd` file that runs
|
|
63
|
+
* `node <script> %*`. Read the script out of it, so the CLI can be started as
|
|
64
|
+
* node + script — no cmd.exe in between to mangle arguments or outlive a cancel.
|
|
65
|
+
*/
|
|
66
|
+
export declare function shimTarget(shim: string, text: string): string | null;
|
|
67
|
+
/** One argument for `cmd /s /c "…"` reaching a batch file that hands `%*` on — the escaping cross-spawn uses. */
|
|
68
|
+
export declare function cmdArgument(arg: string): string;
|
|
69
|
+
export declare function cmdLine(file: string, args: string[]): string;
|
|
70
|
+
/** How to start `file` on this platform, with `dirs` put ahead of PATH for the CLI and whatever it starts. */
|
|
71
|
+
export declare function launchFor(file: string, host: Pick<CliHost, "platform" | "env">, dirs?: string[], depth?: number): CliLaunch;
|
|
72
|
+
/** A CLI shipped inside a desktop app as a Node script, which that app's own Electron binary runs as Node. */
|
|
73
|
+
export interface BundledCli {
|
|
74
|
+
file: string;
|
|
75
|
+
/** The app's binary that runs `file` as Node; absent when `file` is the app's own launcher script, run as it is. */
|
|
76
|
+
runtime?: string;
|
|
77
|
+
}
|
|
78
|
+
/** Where a desktop app may keep its copy of the CLI — every place looked, installed there or not. */
|
|
79
|
+
export type BundledApps = (host: CliHost) => BundledCli[] | Promise<BundledCli[]>;
|
|
80
|
+
/** How to start a bundled CLI: the app's binary with `ELECTRON_RUN_AS_NODE`, so the machine needs no Node of its own. */
|
|
81
|
+
export declare function bundledLaunch(cli: Required<BundledCli>, host: Pick<CliHost, "platform" | "env">): CliLaunch;
|
|
82
|
+
/** Start a resolved CLI: no console window on Windows, its own folder first on PATH. */
|
|
83
|
+
export declare function spawnCli(launch: CliLaunch, args: string[], options?: SpawnOptions & {
|
|
84
|
+
env?: NodeJS.ProcessEnv;
|
|
85
|
+
}): ChildProcess;
|
|
86
|
+
/** On Windows a signal reaches only the process itself; a CLI's own children (node → codex.exe) need the tree taken down. */
|
|
87
|
+
export declare function stopCli(child: ChildProcess, signal?: NodeJS.Signals): void;
|
|
88
|
+
/** The login shell did not answer in time, so the folders its startup files add to PATH are unknown. */
|
|
89
|
+
export declare class ShellTimeout extends Error {
|
|
90
|
+
readonly shell: string;
|
|
91
|
+
constructor(shell: string);
|
|
92
|
+
}
|
|
93
|
+
export declare const machineHost: () => CliHost;
|
|
94
|
+
/** Where installers and version managers put commands when PATH does not (yet) say so. */
|
|
95
|
+
export declare function knownDirs(host: CliHost): Promise<string[]>;
|
|
96
|
+
/** The version a CLI printed, or why it did not answer — short enough for a settings row. */
|
|
97
|
+
export declare function describeRun(result: CliRunResult, timeoutMs: number): {
|
|
98
|
+
ok: boolean;
|
|
99
|
+
detail: string;
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* One locator per CLI for the whole app, so the engine's views and its turns
|
|
103
|
+
* share what was found. `bundled` names copies that ship inside a desktop app,
|
|
104
|
+
* tried after every folder a terminal would search.
|
|
105
|
+
*/
|
|
106
|
+
export declare function localCli(name: string, opts?: {
|
|
107
|
+
bundled?: BundledApps;
|
|
108
|
+
}): CliLocator;
|
|
109
|
+
/**
|
|
110
|
+
* Looks for one CLI — `claude`, `codex` — in the order a person would expect:
|
|
111
|
+
* the path they chose, PATH, PATH as a new terminal sees it, then the folders
|
|
112
|
+
* installers use. Each file found is run with `--version`; the first that
|
|
113
|
+
* answers wins. Results are kept briefly so every view and turn does not spawn.
|
|
114
|
+
*/
|
|
115
|
+
export declare class CliLocator {
|
|
116
|
+
readonly name: string;
|
|
117
|
+
private host;
|
|
118
|
+
private timeoutMs;
|
|
119
|
+
private bundled;
|
|
120
|
+
private cache;
|
|
121
|
+
private pending;
|
|
122
|
+
constructor(name: string, host?: CliHost, timeoutMs?: number, bundled?: BundledApps);
|
|
123
|
+
private apps?;
|
|
124
|
+
findBundled(bundled: BundledApps): void;
|
|
125
|
+
private bundledApps;
|
|
126
|
+
/** How to start `file`: through its app's runtime when it is a bundled copy, the way a terminal would otherwise. */
|
|
127
|
+
private launchOf;
|
|
128
|
+
/** A command setting that names something other than the default is the person's choice. */
|
|
129
|
+
manualOf(command: string | undefined): string | undefined;
|
|
130
|
+
locate(opts?: {
|
|
131
|
+
manual?: string;
|
|
132
|
+
fresh?: boolean;
|
|
133
|
+
}): Promise<LocalCliStatus>;
|
|
134
|
+
/** How a turn starts the CLI that `command` names — the located file when there is one. */
|
|
135
|
+
launch(command?: string): Promise<CliLaunch>;
|
|
136
|
+
check(file: string): Promise<CliCheck>;
|
|
137
|
+
/** Runs `args` on the CLI `command` names — a sign-in check. */
|
|
138
|
+
run(command: string | undefined, args: string[], timeoutMs: number, envFor?: (env: NodeJS.ProcessEnv) => NodeJS.ProcessEnv): Promise<CliRunResult>;
|
|
139
|
+
private found;
|
|
140
|
+
private manualCandidates;
|
|
141
|
+
private inDirs;
|
|
142
|
+
private search;
|
|
143
|
+
}
|
|
144
|
+
/** The English line for logs and errors; the app words each state itself. */
|
|
145
|
+
export declare function cliReason(title: string, cli: LocalCliStatus, install: string): string;
|
|
146
|
+
//# sourceMappingURL=locate.d.ts.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Context } from "cordis";
|
|
2
|
+
import type { EngineMcpLink } from "@tomradex/agent";
|
|
3
|
+
import type { CliLocator } from "./locate.js";
|
|
4
|
+
export declare const MCP_NAME = "tomrade";
|
|
5
|
+
/** What a person (or a test) needs to know about one agent's user-level MCP configuration. */
|
|
6
|
+
export interface UserMcpConfig {
|
|
7
|
+
/** The file the agent keeps it in. */
|
|
8
|
+
file(profile?: string): string;
|
|
9
|
+
/** The address its `tomrade` entry names; null when there is none; throws when the file cannot be read. */
|
|
10
|
+
configuredUrl(profile?: string): string | null;
|
|
11
|
+
add(url: string): string[];
|
|
12
|
+
remove(): string[];
|
|
13
|
+
cli: CliLocator;
|
|
14
|
+
engineId: string;
|
|
15
|
+
/** An agent with several configuration folders: each one, the agent's own first. */
|
|
16
|
+
profiles?(): string[];
|
|
17
|
+
/** The environment that points the CLI at `profile`, and the same as a shell prefix (empty for the agent's own). */
|
|
18
|
+
profileEnv?(profile: string): {
|
|
19
|
+
env(base: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
|
20
|
+
prefix: string;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/** Status reads the agent's file; changes go through its own CLI, which owns that file's format. */
|
|
24
|
+
export declare function userMcpLink(ctx: Context, config: UserMcpConfig): EngineMcpLink;
|
|
25
|
+
/** Claude Code keeps user-scope servers in `.claude.json`, beside CLAUDE_CONFIG_DIR's settings or in the home folder. */
|
|
26
|
+
export declare function claudeUserFile(env?: NodeJS.ProcessEnv): string;
|
|
27
|
+
/** The environment Claude Code needs to run under one config folder: none for the default `~/.claude`. */
|
|
28
|
+
export declare function claudeProfileEnv(dir: string, home?: string): NodeJS.ProcessEnv;
|
|
29
|
+
/** The config folder a session ran under, from its transcript: `<dir>/projects/<folder>/<session>.jsonl`. */
|
|
30
|
+
export declare function claudeConfigDirOf(transcript: string): string | null;
|
|
31
|
+
/**
|
|
32
|
+
* Every Claude Code config folder in use here, the one this process would use
|
|
33
|
+
* first. Several accounts are often one alias each (`CLAUDE_CONFIG_DIR=~/.claude-work claude`),
|
|
34
|
+
* which an app opened from the Dock never sees: such folders are found beside
|
|
35
|
+
* the default one, and from the transcripts sessions report through their hooks.
|
|
36
|
+
*/
|
|
37
|
+
export declare function claudeConfigDirs(env?: NodeJS.ProcessEnv, home?: string, seen?: Iterable<string>): string[];
|
|
38
|
+
export declare function claudeMcpLink(ctx: Context, cli: CliLocator): EngineMcpLink;
|
|
39
|
+
/**
|
|
40
|
+
* Whether Claude Code will load a repository's `.mcp.json` server: it asks
|
|
41
|
+
* once per folder, and remembers the answer in `.claude.json` or in a
|
|
42
|
+
* settings file. `pending` until the person answers.
|
|
43
|
+
*/
|
|
44
|
+
export declare function claudeProjectServerApproval(dir: string, name?: string, env?: NodeJS.ProcessEnv): "approved" | "rejected" | "pending";
|
|
45
|
+
//# sourceMappingURL=mcp-link.d.ts.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { EngineCommands } from "@tomradex/agent";
|
|
2
|
+
export declare const userSettingsFile: () => string;
|
|
3
|
+
/** Claude Code's Bash rule forms: `Bash`, `Bash(cmd)`, `Bash(prefix:*)` and `*` wildcards (`Bash(gh pr merge *)`). */
|
|
4
|
+
export declare function bashRuleMatches(rule: string, command: string): boolean;
|
|
5
|
+
/** Read Claude Code's own settings files the way the CLI layers them, and add an allow rule to the user's. */
|
|
6
|
+
export declare const claudeCommands: EngineCommands;
|
|
7
|
+
//# sourceMappingURL=permissions.d.ts.map
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Context } from "cordis";
|
|
2
|
+
import { type TurnInput, type TurnIO, type TurnResult } from "@tomradex/agent";
|
|
3
|
+
export interface Runtime {
|
|
4
|
+
readonly token: string;
|
|
5
|
+
readonly cwd: string;
|
|
6
|
+
alive: boolean;
|
|
7
|
+
busy: boolean;
|
|
8
|
+
session?: string;
|
|
9
|
+
close(): void;
|
|
10
|
+
turn(input: TurnInput, io: TurnIO, warm: boolean): Promise<TurnResult>;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Warm runtimes per thread. `limit` bounds the idle ones: a turn is never refused for a slot,
|
|
14
|
+
* and once turns finish the least recently used idle runtimes past it are closed.
|
|
15
|
+
* Session history belongs to the provider on disk.
|
|
16
|
+
*/
|
|
17
|
+
export declare class RuntimePool<T extends Runtime> {
|
|
18
|
+
private readonly limit;
|
|
19
|
+
private readonly idleMs;
|
|
20
|
+
private entries;
|
|
21
|
+
constructor(limit?: number, idleMs?: number);
|
|
22
|
+
run(key: string, fingerprint: string, create: () => T, input: TurnInput, io: TurnIO): Promise<TurnResult>;
|
|
23
|
+
/** Close the least recently used idle runtimes past `limit`. */
|
|
24
|
+
private trim;
|
|
25
|
+
evict(key: string): void;
|
|
26
|
+
close(): void;
|
|
27
|
+
}
|
|
28
|
+
/** Hash secrets; never persist or log the fingerprint inputs. */
|
|
29
|
+
export declare function runtimeFingerprint(input: TurnInput, io: TurnIO, url: string | null): string;
|
|
30
|
+
export declare function runtimeDirectory(input: TurnInput): {
|
|
31
|
+
token: string;
|
|
32
|
+
cwd: string;
|
|
33
|
+
dispose(): void;
|
|
34
|
+
};
|
|
35
|
+
export declare function bindTurn(ctx: Context, token: string, io: TurnIO, input: TurnInput): {
|
|
36
|
+
asked: () => boolean;
|
|
37
|
+
release(): Promise<void>;
|
|
38
|
+
};
|
|
39
|
+
/** Producer remains open between user turns; closing releases a waiting reader. */
|
|
40
|
+
export declare class MessageQueue<T> implements AsyncIterable<T> {
|
|
41
|
+
private values;
|
|
42
|
+
private waiter?;
|
|
43
|
+
private closed;
|
|
44
|
+
push(value: T): void;
|
|
45
|
+
close(): void;
|
|
46
|
+
[Symbol.asyncIterator](): AsyncIterator<T>;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=runtime.d.ts.map
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
throw new Error("@tomradex/engine-claude-code is Tomrade's own code: a full-mode plugin gets the running app's copy, so load the plugin in Tomrade");
|
package/dist/sdk.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type Options } from "@anthropic-ai/claude-agent-sdk";
|
|
2
|
+
import type { Context } from "cordis";
|
|
3
|
+
import type { TurnIO, TurnInput, TurnResult } from "@tomradex/agent";
|
|
4
|
+
import { type CliLaunch } from "./locate.js";
|
|
5
|
+
import { type Runtime } from "./runtime.js";
|
|
6
|
+
/**
|
|
7
|
+
* The SDK starts a native path itself; a Windows `.cmd` shim needs our launch
|
|
8
|
+
* (node + script), which the SDK only takes as a custom spawn.
|
|
9
|
+
*/
|
|
10
|
+
export declare function sdkLaunch(launch: CliLaunch, onStderr?: (data: string) => void): Pick<Options, "pathToClaudeCodeExecutable" | "spawnClaudeCodeProcess">;
|
|
11
|
+
export declare class ClaudeRuntime implements Runtime {
|
|
12
|
+
private ctx;
|
|
13
|
+
token: string;
|
|
14
|
+
cwd: string;
|
|
15
|
+
alive: boolean;
|
|
16
|
+
busy: boolean;
|
|
17
|
+
session?: string;
|
|
18
|
+
/** The files index this session was opened with, so a later turn can notice it went stale. */
|
|
19
|
+
indexDigest: string | null;
|
|
20
|
+
private queue;
|
|
21
|
+
private query?;
|
|
22
|
+
private onMessage?;
|
|
23
|
+
private onFailure?;
|
|
24
|
+
private cost;
|
|
25
|
+
/** This session was started without resume and has not had its first message yet. */
|
|
26
|
+
private fresh;
|
|
27
|
+
/** Cumulative counters from the last result; the SDK reports running totals, so a turn is the difference. */
|
|
28
|
+
private tokens;
|
|
29
|
+
private activeIO?;
|
|
30
|
+
private stderr;
|
|
31
|
+
private keepStderr;
|
|
32
|
+
constructor(ctx: Context, input: TurnInput);
|
|
33
|
+
close(): void;
|
|
34
|
+
turn(input: TurnInput, io: TurnIO, warm: boolean): Promise<TurnResult>;
|
|
35
|
+
private consume;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=sdk.d.ts.map
|
package/dist/system.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type TurnIO, type TurnInput } from "@tomradex/agent";
|
|
2
|
+
export declare function staticSystem(agentName: string): string;
|
|
3
|
+
/**
|
|
4
|
+
* What an external agent is told once, when its session opens: its identity,
|
|
5
|
+
* the house rules, and the index of the project's files. The index belongs
|
|
6
|
+
* here and not in the per-turn prompt — this text is cached by the provider,
|
|
7
|
+
* while everything in a user message is paid for again on every turn.
|
|
8
|
+
*/
|
|
9
|
+
export declare function sessionSystem(input: TurnInput, agentName: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* The per-turn state. `staleIndex` is set when the files have moved on since
|
|
12
|
+
* the session's index was written, which is one line rather than a fresh copy.
|
|
13
|
+
*/
|
|
14
|
+
export declare const turnPrompt: (input: TurnInput, io: TurnIO, opts?: {
|
|
15
|
+
staleIndex?: boolean;
|
|
16
|
+
}) => string;
|
|
17
|
+
export declare const promptOf: (input: TurnInput) => string;
|
|
18
|
+
//# sourceMappingURL=system.d.ts.map
|
package/dist/usage.d.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token accounting for a Claude Code turn. Live numbers come from the API's
|
|
3
|
+
* own streaming events: message_start carries the request's prompt tokens,
|
|
4
|
+
* cache included, and message_delta the reply so far. Final numbers come from
|
|
5
|
+
* the result's modelUsage — every model call, cumulative across the turns one
|
|
6
|
+
* process serves, so a turn is the difference from the previous result — with
|
|
7
|
+
* the main-loop `usage` as the fallback for builds that lack it. Input means
|
|
8
|
+
* every prompt token the model processed: cached ones are context, not free.
|
|
9
|
+
*/
|
|
10
|
+
export interface Tokens {
|
|
11
|
+
input: number;
|
|
12
|
+
output: number;
|
|
13
|
+
cacheRead: number;
|
|
14
|
+
cacheWrite: number;
|
|
15
|
+
}
|
|
16
|
+
export interface ApiUsage {
|
|
17
|
+
input_tokens?: number | null;
|
|
18
|
+
output_tokens?: number | null;
|
|
19
|
+
cache_read_input_tokens?: number | null;
|
|
20
|
+
cache_creation_input_tokens?: number | null;
|
|
21
|
+
}
|
|
22
|
+
interface ModelTokens {
|
|
23
|
+
inputTokens: number;
|
|
24
|
+
outputTokens: number;
|
|
25
|
+
cacheReadInputTokens: number;
|
|
26
|
+
cacheCreationInputTokens: number;
|
|
27
|
+
}
|
|
28
|
+
export interface ResultCounters {
|
|
29
|
+
usage?: ApiUsage;
|
|
30
|
+
modelUsage?: Record<string, ModelTokens>;
|
|
31
|
+
}
|
|
32
|
+
/** Every prompt token the model read this turn, cached or not. */
|
|
33
|
+
export declare const promptTokens: (t: Tokens) => number;
|
|
34
|
+
/** Whether the provider said anything about caching; absent fields stay absent in the metrics. */
|
|
35
|
+
export declare const cacheKnown: (r: ResultCounters) => boolean;
|
|
36
|
+
/**
|
|
37
|
+
* This turn's counters, and the cumulative figure to diff the next result
|
|
38
|
+
* against (null when the result carried no modelUsage).
|
|
39
|
+
*/
|
|
40
|
+
export declare function turnTokens(result: ResultCounters, previous: Tokens | null): {
|
|
41
|
+
turn: Tokens;
|
|
42
|
+
cumulative: Tokens | null;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* The running total of one turn, fed by streaming events as they arrive. Each
|
|
46
|
+
* stream (the main loop, every subagent) has one open request at a time. One
|
|
47
|
+
* that drops mid-stream is sent again whole, so its figures leave the total
|
|
48
|
+
* when the retry is announced instead of counting the prompt twice.
|
|
49
|
+
*/
|
|
50
|
+
export declare class LiveUsage {
|
|
51
|
+
private prompt;
|
|
52
|
+
private finished;
|
|
53
|
+
/** Each stream's open request: its prompt, and its reply so far. */
|
|
54
|
+
private open;
|
|
55
|
+
/** The total after this event, or null when the event says nothing about tokens. */
|
|
56
|
+
observe(event: {
|
|
57
|
+
type?: string;
|
|
58
|
+
message?: {
|
|
59
|
+
usage?: ApiUsage;
|
|
60
|
+
};
|
|
61
|
+
usage?: ApiUsage;
|
|
62
|
+
} | undefined, stream?: string | null): {
|
|
63
|
+
inputTokens: number;
|
|
64
|
+
outputTokens: number;
|
|
65
|
+
} | null;
|
|
66
|
+
/** The main loop's open request failed and will be sent again. */
|
|
67
|
+
retry(): {
|
|
68
|
+
inputTokens: number;
|
|
69
|
+
outputTokens: number;
|
|
70
|
+
};
|
|
71
|
+
private close;
|
|
72
|
+
private total;
|
|
73
|
+
}
|
|
74
|
+
export {};
|
|
75
|
+
//# sourceMappingURL=usage.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,44 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tomradex/engine-claude-code",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.15.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"author": "Haoyuan Tang",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=22"
|
|
8
|
+
},
|
|
9
|
+
"publishConfig": {
|
|
10
|
+
"access": "public"
|
|
11
|
+
},
|
|
12
|
+
"license": "Apache-2.0",
|
|
13
|
+
"description": "Claude Agent SDK conductor with one reusable local runtime per hot thread, MCP tools, and resumable sessions — declarations for full-mode plugins; Tomrade provides the code at run time",
|
|
14
|
+
"keywords": [
|
|
15
|
+
"tomrade",
|
|
16
|
+
"tomrade-plugin",
|
|
17
|
+
"types"
|
|
18
|
+
],
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"default": "./dist/runtime.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist"
|
|
28
|
+
],
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@tomradex/agent": "0.15.0",
|
|
31
|
+
"@tomradex/llm": "0.15.0",
|
|
32
|
+
"@tomradex/mcp": "0.15.0",
|
|
33
|
+
"cordis": "4.0.0-rc.8",
|
|
34
|
+
"zod": "^4.4.3"
|
|
35
|
+
},
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"@anthropic-ai/claude-agent-sdk": "0.3.263"
|
|
38
|
+
},
|
|
39
|
+
"peerDependenciesMeta": {
|
|
40
|
+
"@anthropic-ai/claude-agent-sdk": {
|
|
41
|
+
"optional": true
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
package/README.md
DELETED