@alpacakit/agents 0.1.0-beta.19
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/README.md +224 -0
- package/dist/agents/builtin.d.ts +19 -0
- package/dist/agents/builtin.d.ts.map +1 -0
- package/dist/agents/builtin.js +14 -0
- package/dist/agents/claude.d.ts +20 -0
- package/dist/agents/claude.d.ts.map +1 -0
- package/dist/agents/claude.js +480 -0
- package/dist/agents/codex.d.ts +19 -0
- package/dist/agents/codex.d.ts.map +1 -0
- package/dist/agents/codex.js +355 -0
- package/dist/agents/openai-compatible/config.d.ts +16 -0
- package/dist/agents/openai-compatible/config.d.ts.map +1 -0
- package/dist/agents/openai-compatible/config.js +160 -0
- package/dist/agents/openai-compatible/engine.d.ts +18 -0
- package/dist/agents/openai-compatible/engine.d.ts.map +1 -0
- package/dist/agents/openai-compatible/engine.js +10 -0
- package/dist/agents/openai-compatible/fetch-engine.d.ts +38 -0
- package/dist/agents/openai-compatible/fetch-engine.d.ts.map +1 -0
- package/dist/agents/openai-compatible/fetch-engine.js +216 -0
- package/dist/agents/openai-compatible/pi/engine.d.ts +32 -0
- package/dist/agents/openai-compatible/pi/engine.d.ts.map +1 -0
- package/dist/agents/openai-compatible/pi/engine.js +98 -0
- package/dist/agents/openai-compatible/pi/module.d.ts +87 -0
- package/dist/agents/openai-compatible/pi/module.d.ts.map +1 -0
- package/dist/agents/openai-compatible/pi/module.js +43 -0
- package/dist/agents/openai-compatible/pi/sandbox.d.ts +25 -0
- package/dist/agents/openai-compatible/pi/sandbox.d.ts.map +1 -0
- package/dist/agents/openai-compatible/pi/sandbox.js +69 -0
- package/dist/agents/openai-compatible/pi/session.d.ts +17 -0
- package/dist/agents/openai-compatible/pi/session.d.ts.map +1 -0
- package/dist/agents/openai-compatible/pi/session.js +354 -0
- package/dist/agents/openai-compatible/response.d.ts +19 -0
- package/dist/agents/openai-compatible/response.d.ts.map +1 -0
- package/dist/agents/openai-compatible/response.js +203 -0
- package/dist/agents/openai-compatible/types.d.ts +34 -0
- package/dist/agents/openai-compatible/types.d.ts.map +1 -0
- package/dist/agents/openai-compatible/types.js +1 -0
- package/dist/agents/openai-compatible.d.ts +12 -0
- package/dist/agents/openai-compatible.d.ts.map +1 -0
- package/dist/agents/openai-compatible.js +45 -0
- package/dist/auth/login-probe.d.ts +21 -0
- package/dist/auth/login-probe.d.ts.map +1 -0
- package/dist/auth/login-probe.js +47 -0
- package/dist/auth/login.d.ts +79 -0
- package/dist/auth/login.d.ts.map +1 -0
- package/dist/auth/login.js +9 -0
- package/dist/auth/material.d.ts +87 -0
- package/dist/auth/material.d.ts.map +1 -0
- package/dist/auth/material.js +59 -0
- package/dist/auth/profile-store.d.ts +14 -0
- package/dist/auth/profile-store.d.ts.map +1 -0
- package/dist/auth/profile-store.js +101 -0
- package/dist/auth/secrets.d.ts +14 -0
- package/dist/auth/secrets.d.ts.map +1 -0
- package/dist/auth/secrets.js +40 -0
- package/dist/codex/app-server.d.ts +30 -0
- package/dist/codex/app-server.d.ts.map +1 -0
- package/dist/codex/app-server.js +322 -0
- package/dist/codex/index.d.ts +3 -0
- package/dist/codex/index.d.ts.map +1 -0
- package/dist/codex/index.js +1 -0
- package/dist/codex/protocol.d.ts +124 -0
- package/dist/codex/protocol.d.ts.map +1 -0
- package/dist/codex/protocol.js +283 -0
- package/dist/config/agent-config-validation.d.ts +22 -0
- package/dist/config/agent-config-validation.d.ts.map +1 -0
- package/dist/config/agent-config-validation.js +31 -0
- package/dist/config/agent-configs.d.ts +37 -0
- package/dist/config/agent-configs.d.ts.map +1 -0
- package/dist/config/agent-configs.js +214 -0
- package/dist/config/compose.d.ts +10 -0
- package/dist/config/compose.d.ts.map +1 -0
- package/dist/config/compose.js +89 -0
- package/dist/config/config.d.ts +21 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +33 -0
- package/dist/config/errors.d.ts +45 -0
- package/dist/config/errors.d.ts.map +1 -0
- package/dist/config/errors.js +37 -0
- package/dist/config/extension.d.ts +3 -0
- package/dist/config/extension.d.ts.map +1 -0
- package/dist/config/extension.js +1 -0
- package/dist/config/ids.d.ts +8 -0
- package/dist/config/ids.d.ts.map +1 -0
- package/dist/config/ids.js +4 -0
- package/dist/config/index.d.ts +12 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +6 -0
- package/dist/config/model.d.ts +105 -0
- package/dist/config/model.d.ts.map +1 -0
- package/dist/config/model.js +1 -0
- package/dist/config/paths.d.ts +7 -0
- package/dist/config/paths.d.ts.map +1 -0
- package/dist/config/paths.js +10 -0
- package/dist/config/schema.d.ts +59 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +83 -0
- package/dist/config/store.d.ts +34 -0
- package/dist/config/store.d.ts.map +1 -0
- package/dist/config/store.js +420 -0
- package/dist/config/support.d.ts +14 -0
- package/dist/config/support.d.ts.map +1 -0
- package/dist/config/support.js +32 -0
- package/dist/config/values.d.ts +21 -0
- package/dist/config/values.d.ts.map +1 -0
- package/dist/config/values.js +22 -0
- package/dist/config/xdg.d.ts +20 -0
- package/dist/config/xdg.d.ts.map +1 -0
- package/dist/config/xdg.js +23 -0
- package/dist/core/async-queue.d.ts +14 -0
- package/dist/core/async-queue.d.ts.map +1 -0
- package/dist/core/async-queue.js +46 -0
- package/dist/core/env.d.ts +19 -0
- package/dist/core/env.d.ts.map +1 -0
- package/dist/core/env.js +39 -0
- package/dist/core/error.d.ts +121 -0
- package/dist/core/error.d.ts.map +1 -0
- package/dist/core/error.js +88 -0
- package/dist/core/fs.d.ts +16 -0
- package/dist/core/fs.d.ts.map +1 -0
- package/dist/core/fs.js +30 -0
- package/dist/core/json.d.ts +20 -0
- package/dist/core/json.d.ts.map +1 -0
- package/dist/core/json.js +42 -0
- package/dist/core/node-ports.d.ts +9 -0
- package/dist/core/node-ports.d.ts.map +1 -0
- package/dist/core/node-ports.js +135 -0
- package/dist/core/ports.d.ts +71 -0
- package/dist/core/ports.d.ts.map +1 -0
- package/dist/core/ports.js +19 -0
- package/dist/core/redact.d.ts +8 -0
- package/dist/core/redact.d.ts.map +1 -0
- package/dist/core/redact.js +66 -0
- package/dist/core/run.d.ts +125 -0
- package/dist/core/run.d.ts.map +1 -0
- package/dist/core/run.js +27 -0
- package/dist/core/values.d.ts +12 -0
- package/dist/core/values.d.ts.map +1 -0
- package/dist/core/values.js +9 -0
- package/dist/corpus/failure-corpus.d.ts +21 -0
- package/dist/corpus/failure-corpus.d.ts.map +1 -0
- package/dist/corpus/failure-corpus.js +89 -0
- package/dist/fleet/fleet.d.ts +120 -0
- package/dist/fleet/fleet.d.ts.map +1 -0
- package/dist/fleet/fleet.js +409 -0
- package/dist/fleet/policy.d.ts +45 -0
- package/dist/fleet/policy.d.ts.map +1 -0
- package/dist/fleet/policy.js +50 -0
- package/dist/fleet/store.d.ts +28 -0
- package/dist/fleet/store.d.ts.map +1 -0
- package/dist/fleet/store.js +225 -0
- package/dist/host/capabilities.d.ts +146 -0
- package/dist/host/capabilities.d.ts.map +1 -0
- package/dist/host/capabilities.js +59 -0
- package/dist/host/context.d.ts +29 -0
- package/dist/host/context.d.ts.map +1 -0
- package/dist/host/context.js +11 -0
- package/dist/host/github-dir.d.ts +16 -0
- package/dist/host/github-dir.d.ts.map +1 -0
- package/dist/host/github-dir.js +164 -0
- package/dist/host/mcp-list.d.ts +12 -0
- package/dist/host/mcp-list.d.ts.map +1 -0
- package/dist/host/mcp-list.js +122 -0
- package/dist/host/requirement-ref.d.ts +12 -0
- package/dist/host/requirement-ref.d.ts.map +1 -0
- package/dist/host/requirement-ref.js +40 -0
- package/dist/host/run-command.d.ts +27 -0
- package/dist/host/run-command.d.ts.map +1 -0
- package/dist/host/run-command.js +66 -0
- package/dist/host/validate-spec.d.ts +10 -0
- package/dist/host/validate-spec.d.ts.map +1 -0
- package/dist/host/validate-spec.js +69 -0
- package/dist/index.d.ts +69 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/kernel/classify.d.ts +44 -0
- package/dist/kernel/classify.d.ts.map +1 -0
- package/dist/kernel/classify.js +136 -0
- package/dist/kernel/cli-agent.d.ts +62 -0
- package/dist/kernel/cli-agent.d.ts.map +1 -0
- package/dist/kernel/cli-agent.js +281 -0
- package/dist/kernel/cli-login.d.ts +13 -0
- package/dist/kernel/cli-login.d.ts.map +1 -0
- package/dist/kernel/cli-login.js +199 -0
- package/dist/kernel/definition.d.ts +41 -0
- package/dist/kernel/definition.d.ts.map +1 -0
- package/dist/kernel/definition.js +13 -0
- package/dist/kernel/env-template.d.ts +17 -0
- package/dist/kernel/env-template.d.ts.map +1 -0
- package/dist/kernel/env-template.js +78 -0
- package/dist/kernel/facets.d.ts +58 -0
- package/dist/kernel/facets.d.ts.map +1 -0
- package/dist/kernel/facets.js +102 -0
- package/dist/kernel/guard.d.ts +24 -0
- package/dist/kernel/guard.d.ts.map +1 -0
- package/dist/kernel/guard.js +69 -0
- package/dist/kernel/handle.d.ts +29 -0
- package/dist/kernel/handle.d.ts.map +1 -0
- package/dist/kernel/handle.js +97 -0
- package/dist/kernel/keyed.d.ts +19 -0
- package/dist/kernel/keyed.d.ts.map +1 -0
- package/dist/kernel/keyed.js +35 -0
- package/dist/kernel/login.d.ts +20 -0
- package/dist/kernel/login.d.ts.map +1 -0
- package/dist/kernel/login.js +74 -0
- package/dist/kernel/options.d.ts +73 -0
- package/dist/kernel/options.d.ts.map +1 -0
- package/dist/kernel/options.js +41 -0
- package/dist/kernel/run.d.ts +20 -0
- package/dist/kernel/run.d.ts.map +1 -0
- package/dist/kernel/run.js +245 -0
- package/dist/kernel/runtime.d.ts +48 -0
- package/dist/kernel/runtime.d.ts.map +1 -0
- package/dist/kernel/runtime.js +108 -0
- package/dist/keyring/index.d.ts +2 -0
- package/dist/keyring/index.d.ts.map +1 -0
- package/dist/keyring/index.js +1 -0
- package/dist/keyring/resolver.d.ts +9 -0
- package/dist/keyring/resolver.d.ts.map +1 -0
- package/dist/keyring/resolver.js +62 -0
- package/dist/run-agent.d.ts +19 -0
- package/dist/run-agent.d.ts.map +1 -0
- package/dist/run-agent.js +25 -0
- package/dist/structured/extract.d.ts +27 -0
- package/dist/structured/extract.d.ts.map +1 -0
- package/dist/structured/extract.js +188 -0
- package/dist/structured/run-structured.d.ts +83 -0
- package/dist/structured/run-structured.d.ts.map +1 -0
- package/dist/structured/run-structured.js +202 -0
- package/dist/structured/standard-schema.d.ts +34 -0
- package/dist/structured/standard-schema.d.ts.map +1 -0
- package/dist/structured/standard-schema.js +6 -0
- package/dist/testing/fake-agent.d.ts +32 -0
- package/dist/testing/fake-agent.d.ts.map +1 -0
- package/dist/testing/fake-agent.js +43 -0
- package/dist/testing/fake-clock.d.ts +8 -0
- package/dist/testing/fake-clock.d.ts.map +1 -0
- package/dist/testing/fake-clock.js +44 -0
- package/dist/testing/fake-exec.d.ts +26 -0
- package/dist/testing/fake-exec.d.ts.map +1 -0
- package/dist/testing/fake-exec.js +69 -0
- package/dist/testing/fake-secrets.d.ts +3 -0
- package/dist/testing/fake-secrets.d.ts.map +1 -0
- package/dist/testing/fake-secrets.js +5 -0
- package/dist/testing/index.d.ts +10 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +9 -0
- package/package.json +75 -0
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in claude adapter (v1 E1/E2 argv kept verbatim):
|
|
3
|
+
* `claude -p [--model m] [--effort e] --output-format stream-json
|
|
4
|
+
* --permission-mode <mode> [tool args] --verbose`, prompt on stdin.
|
|
5
|
+
* Read-only grants map to `--allowedTools` (`Bash(cmd:*)` for shell
|
|
6
|
+
* grants, the bare tool name otherwise); no grants means `--tools ""`.
|
|
7
|
+
*/
|
|
8
|
+
import { cp, mkdir, readdir, readFile, rm, stat } from "node:fs/promises";
|
|
9
|
+
import path from "node:path";
|
|
10
|
+
import { cliLoginProbe } from "../auth/login-probe.js";
|
|
11
|
+
import { AUTH_MATERIAL_KIND, envVarAuthMaterial } from "../auth/material.js";
|
|
12
|
+
import { requireSecret } from "../auth/secrets.js";
|
|
13
|
+
import { AGENT_ERROR_CODE, AgentError } from "../core/error.js";
|
|
14
|
+
import { isErrnoCode } from "../core/fs.js";
|
|
15
|
+
import { readBoolean, readJsonRecord, readNumber, readRecord, readString, readUnknownRecord, } from "../core/json.js";
|
|
16
|
+
import { AGENT_EVENT_TYPE } from "../core/run.js";
|
|
17
|
+
import { TEXT_ENCODING } from "../core/values.js";
|
|
18
|
+
import { INSTALL_STATUS, MCP_TRANSPORT, SKILL_SOURCE_KIND, } from "../host/capabilities.js";
|
|
19
|
+
import { withStagedGithubDirectory, } from "../host/github-dir.js";
|
|
20
|
+
import { listMcpServersViaCli } from "../host/mcp-list.js";
|
|
21
|
+
import { hostCommandFailedError, runHostCommand, runHostCommandResult, } from "../host/run-command.js";
|
|
22
|
+
import { parseEpochTimestamp, } from "../kernel/classify.js";
|
|
23
|
+
import { defineCliAgent, } from "../kernel/cli-agent.js";
|
|
24
|
+
import { GRANT_KIND, SANDBOX_MODE } from "../kernel/options.js";
|
|
25
|
+
export const CLAUDE_CONFIG_DIR_ENV_VAR = "CLAUDE_CONFIG_DIR";
|
|
26
|
+
export const CLAUDE_API_KEY_ENV_VAR = "ANTHROPIC_API_KEY";
|
|
27
|
+
const CLAUDE = {
|
|
28
|
+
id: "claude",
|
|
29
|
+
command: "claude",
|
|
30
|
+
cli: {
|
|
31
|
+
prompt: "-p",
|
|
32
|
+
model: "--model",
|
|
33
|
+
effort: "--effort",
|
|
34
|
+
outputFormat: "--output-format",
|
|
35
|
+
streamJson: "stream-json",
|
|
36
|
+
permissionMode: "--permission-mode",
|
|
37
|
+
bypassPermissions: "bypassPermissions",
|
|
38
|
+
defaultPermissionMode: "default",
|
|
39
|
+
verbose: "--verbose",
|
|
40
|
+
tools: "--tools",
|
|
41
|
+
allowedTools: "--allowedTools",
|
|
42
|
+
},
|
|
43
|
+
auth: {
|
|
44
|
+
statusArgs: ["auth", "status", "--json"],
|
|
45
|
+
},
|
|
46
|
+
mcp: {
|
|
47
|
+
addJson: "add-json",
|
|
48
|
+
mcp: "mcp",
|
|
49
|
+
remove: "remove",
|
|
50
|
+
scope: "--scope",
|
|
51
|
+
},
|
|
52
|
+
plugin: {
|
|
53
|
+
plugin: "plugin",
|
|
54
|
+
install: "install",
|
|
55
|
+
},
|
|
56
|
+
json: {
|
|
57
|
+
field: {
|
|
58
|
+
type: "type",
|
|
59
|
+
message: "message",
|
|
60
|
+
content: "content",
|
|
61
|
+
text: "text",
|
|
62
|
+
name: "name",
|
|
63
|
+
usage: "usage",
|
|
64
|
+
result: "result",
|
|
65
|
+
inputTokens: "input_tokens",
|
|
66
|
+
outputTokens: "output_tokens",
|
|
67
|
+
totalCost: "total_cost_usd",
|
|
68
|
+
},
|
|
69
|
+
type: {
|
|
70
|
+
assistant: "assistant",
|
|
71
|
+
result: "result",
|
|
72
|
+
text: "text",
|
|
73
|
+
toolUse: "tool_use",
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
const COMPETING_TOKEN_VARS = [
|
|
78
|
+
"ANTHROPIC_API_KEY",
|
|
79
|
+
"ANTHROPIC_AUTH_TOKEN",
|
|
80
|
+
"CLAUDE_CODE_OAUTH_TOKEN",
|
|
81
|
+
];
|
|
82
|
+
const COMPETING_CONFIG_VARS = [
|
|
83
|
+
"CLAUDE_CONFIG_DIR",
|
|
84
|
+
"ANTHROPIC_AUTH_TOKEN",
|
|
85
|
+
"CLAUDE_CODE_OAUTH_TOKEN",
|
|
86
|
+
];
|
|
87
|
+
const CLAUDE_PROJECT_SKILL_ROOT = ".claude";
|
|
88
|
+
const SKILLS_DIRECTORY = "skills";
|
|
89
|
+
const SKILL_MARKDOWN = "SKILL.md";
|
|
90
|
+
const PLUGIN_ALREADY_INSTALLED = /already installed/i;
|
|
91
|
+
const CLAUDE_SKILL_SOURCE = {
|
|
92
|
+
project: "claude:project",
|
|
93
|
+
user: "claude:user",
|
|
94
|
+
};
|
|
95
|
+
function grantToToolArg(grant) {
|
|
96
|
+
return grant.kind === GRANT_KIND.shell
|
|
97
|
+
? `Bash(${grant.command}:*)`
|
|
98
|
+
: grant.name;
|
|
99
|
+
}
|
|
100
|
+
function sharedArgs(ctx) {
|
|
101
|
+
return [
|
|
102
|
+
CLAUDE.cli.prompt,
|
|
103
|
+
...(ctx.model === null ? [] : [CLAUDE.cli.model, ctx.model]),
|
|
104
|
+
...(ctx.effort === null ? [] : [CLAUDE.cli.effort, ctx.effort]),
|
|
105
|
+
CLAUDE.cli.outputFormat,
|
|
106
|
+
CLAUDE.cli.streamJson,
|
|
107
|
+
];
|
|
108
|
+
}
|
|
109
|
+
function parseClaudeLine(line) {
|
|
110
|
+
const record = readJsonRecord(line);
|
|
111
|
+
if (record === null ||
|
|
112
|
+
readString(record, CLAUDE.json.field.type) !== CLAUDE.json.type.assistant) {
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
115
|
+
const message = readRecord(record, CLAUDE.json.field.message);
|
|
116
|
+
const content = message?.[CLAUDE.json.field.content];
|
|
117
|
+
if (!Array.isArray(content)) {
|
|
118
|
+
return [{ type: AGENT_EVENT_TYPE.turn }];
|
|
119
|
+
}
|
|
120
|
+
const events = [{ type: AGENT_EVENT_TYPE.turn }];
|
|
121
|
+
for (const block of content) {
|
|
122
|
+
const blockRecord = readUnknownRecord(block);
|
|
123
|
+
if (blockRecord === null) {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
const blockType = readString(blockRecord, CLAUDE.json.field.type);
|
|
127
|
+
if (blockType === CLAUDE.json.type.text) {
|
|
128
|
+
const text = readString(blockRecord, CLAUDE.json.field.text);
|
|
129
|
+
if (text !== null) {
|
|
130
|
+
events.push({ type: AGENT_EVENT_TYPE.message, text });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (blockType === CLAUDE.json.type.toolUse) {
|
|
134
|
+
const name = readString(blockRecord, CLAUDE.json.field.name);
|
|
135
|
+
if (name !== null) {
|
|
136
|
+
events.push({ type: AGENT_EVENT_TYPE.tool, name });
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return events;
|
|
141
|
+
}
|
|
142
|
+
function parseClaudeResult(line) {
|
|
143
|
+
const record = readJsonRecord(line);
|
|
144
|
+
if (record === null ||
|
|
145
|
+
readString(record, CLAUDE.json.field.type) !== CLAUDE.json.type.result) {
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
const usageRecord = readRecord(record, CLAUDE.json.field.usage);
|
|
149
|
+
const usage = usageRecord === null
|
|
150
|
+
? null
|
|
151
|
+
: {
|
|
152
|
+
inputTokens: readNumber(usageRecord, CLAUDE.json.field.inputTokens),
|
|
153
|
+
outputTokens: readNumber(usageRecord, CLAUDE.json.field.outputTokens),
|
|
154
|
+
costUsd: readNumber(record, CLAUDE.json.field.totalCost),
|
|
155
|
+
};
|
|
156
|
+
return { text: readString(record, CLAUDE.json.field.result), usage };
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Structured quota signals in Claude CLI NDJSON output (v1 F2), scanned
|
|
160
|
+
* per line: rate_limit_event rejected (with resetsAt), api_error_status
|
|
161
|
+
* 429, and error === "rate_limit". Exported for custom agents that speak
|
|
162
|
+
* the same stream format.
|
|
163
|
+
*/
|
|
164
|
+
export function structuredQuotaMatcher() {
|
|
165
|
+
return (evidence) => {
|
|
166
|
+
let fallbackCooldownUntil = null;
|
|
167
|
+
for (const line of evidence.stdout.split(/\r?\n/)) {
|
|
168
|
+
const record = readJsonRecord(line.trim());
|
|
169
|
+
if (record === null) {
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
const rateLimitInfo = readRecord(record, "rate_limit_info");
|
|
173
|
+
const resetsAt = rateLimitInfo === null ? null : readNumber(rateLimitInfo, "resetsAt");
|
|
174
|
+
const cooldownUntil = resetsAt === null ? null : parseEpochTimestamp(resetsAt);
|
|
175
|
+
const rejected = rateLimitInfo !== null &&
|
|
176
|
+
readString(rateLimitInfo, "status") === "rejected";
|
|
177
|
+
if (readString(record, "type") === "rate_limit_event" && rejected) {
|
|
178
|
+
return {
|
|
179
|
+
code: AGENT_ERROR_CODE.quota,
|
|
180
|
+
message: "Provider rejected the request for rate limiting",
|
|
181
|
+
data: { cooldownUntil },
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
if (cooldownUntil !== null) {
|
|
185
|
+
fallbackCooldownUntil = cooldownUntil;
|
|
186
|
+
}
|
|
187
|
+
const apiError = readBoolean(record, "is_error") === true &&
|
|
188
|
+
readNumber(record, "api_error_status") === 429;
|
|
189
|
+
const rateLimitError = readString(record, "error") === "rate_limit" &&
|
|
190
|
+
readString(record, "type") !== null;
|
|
191
|
+
if (apiError || rateLimitError) {
|
|
192
|
+
return {
|
|
193
|
+
code: AGENT_ERROR_CODE.quota,
|
|
194
|
+
message: "Provider reported a rate-limit error",
|
|
195
|
+
data: { cooldownUntil: fallbackCooldownUntil },
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return null;
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
const homeDirHandler = envVarAuthMaterial({
|
|
203
|
+
set: (material) => ({ [CLAUDE_CONFIG_DIR_ENV_VAR]: material.path }),
|
|
204
|
+
unset: COMPETING_TOKEN_VARS,
|
|
205
|
+
check: (material, ctx) => cliLoginProbe({
|
|
206
|
+
command: CLAUDE.command,
|
|
207
|
+
args: CLAUDE.auth.statusArgs,
|
|
208
|
+
envPatch: {
|
|
209
|
+
set: { [CLAUDE_CONFIG_DIR_ENV_VAR]: material.path },
|
|
210
|
+
unset: COMPETING_TOKEN_VARS,
|
|
211
|
+
},
|
|
212
|
+
ctx,
|
|
213
|
+
}),
|
|
214
|
+
});
|
|
215
|
+
/** Install/list roots in priority order; the first is the install target. */
|
|
216
|
+
function claudeSkillRoots(ctx) {
|
|
217
|
+
const userRoot = {
|
|
218
|
+
root: path.join(ctx.location.homeDir, CLAUDE_PROJECT_SKILL_ROOT, SKILLS_DIRECTORY),
|
|
219
|
+
source: CLAUDE_SKILL_SOURCE.user,
|
|
220
|
+
};
|
|
221
|
+
if (ctx.location.projectDir === null) {
|
|
222
|
+
return [userRoot];
|
|
223
|
+
}
|
|
224
|
+
return [
|
|
225
|
+
{
|
|
226
|
+
root: path.join(ctx.location.projectDir, CLAUDE_PROJECT_SKILL_ROOT, SKILLS_DIRECTORY),
|
|
227
|
+
source: CLAUDE_SKILL_SOURCE.project,
|
|
228
|
+
},
|
|
229
|
+
userRoot,
|
|
230
|
+
];
|
|
231
|
+
}
|
|
232
|
+
function parseSkillMetadata(markdown) {
|
|
233
|
+
const frontmatter = markdown.match(/^---\r?\n([\s\S]*?)\r?\n---/u);
|
|
234
|
+
if (frontmatter?.[1] === undefined) {
|
|
235
|
+
return { name: null, description: null };
|
|
236
|
+
}
|
|
237
|
+
let name = null;
|
|
238
|
+
let description = null;
|
|
239
|
+
for (const line of frontmatter[1].split(/\r?\n/u)) {
|
|
240
|
+
const separator = line.indexOf(":");
|
|
241
|
+
if (separator < 0) {
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
const key = line.slice(0, separator).trim();
|
|
245
|
+
const value = line
|
|
246
|
+
.slice(separator + 1)
|
|
247
|
+
.trim()
|
|
248
|
+
.replace(/^["']|["']$/gu, "");
|
|
249
|
+
if (key === "name") {
|
|
250
|
+
name = value;
|
|
251
|
+
}
|
|
252
|
+
if (key === "description") {
|
|
253
|
+
description = value;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return { name, description };
|
|
257
|
+
}
|
|
258
|
+
function skillListReadError(target, cause) {
|
|
259
|
+
return new AgentError({
|
|
260
|
+
code: AGENT_ERROR_CODE.failed,
|
|
261
|
+
message: `Could not read installed claude skills: ${target}`,
|
|
262
|
+
data: { exitCode: null, stdoutTail: null, stderrTail: null },
|
|
263
|
+
cause,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
async function readSkillRootEntries(root) {
|
|
267
|
+
try {
|
|
268
|
+
return await readdir(root, { withFileTypes: true });
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
// D5 discipline: only "the root does not exist" reads as empty.
|
|
272
|
+
if (isErrnoCode(error, "ENOENT") || isErrnoCode(error, "ENOTDIR")) {
|
|
273
|
+
return [];
|
|
274
|
+
}
|
|
275
|
+
throw skillListReadError(root, error);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
async function readSkillMarkdown(location) {
|
|
279
|
+
try {
|
|
280
|
+
return await readFile(path.join(location, SKILL_MARKDOWN), TEXT_ENCODING);
|
|
281
|
+
}
|
|
282
|
+
catch (error) {
|
|
283
|
+
// A directory without SKILL.md is simply not a skill; anything else
|
|
284
|
+
// (permissions, I/O) must surface instead of hiding installed skills.
|
|
285
|
+
if (isErrnoCode(error, "ENOENT")) {
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
throw skillListReadError(location, error);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
async function listClaudeSkills(ctx) {
|
|
292
|
+
const byId = new Map();
|
|
293
|
+
for (const { root, source } of claudeSkillRoots(ctx)) {
|
|
294
|
+
for (const entry of await readSkillRootEntries(root)) {
|
|
295
|
+
if (!entry.isDirectory() || byId.has(entry.name)) {
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
const location = path.join(root, entry.name);
|
|
299
|
+
const markdown = await readSkillMarkdown(location);
|
|
300
|
+
if (markdown === null) {
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
const metadata = parseSkillMetadata(markdown);
|
|
304
|
+
byId.set(entry.name, {
|
|
305
|
+
id: entry.name,
|
|
306
|
+
name: metadata.name ?? entry.name,
|
|
307
|
+
description: metadata.description ?? "",
|
|
308
|
+
location,
|
|
309
|
+
source,
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return [...byId.values()];
|
|
314
|
+
}
|
|
315
|
+
async function installLocalClaudeSkill(ctx, source, options) {
|
|
316
|
+
await assertSkillDirectory(source.path);
|
|
317
|
+
const skillId = path.basename(path.resolve(source.path));
|
|
318
|
+
const location = path.join(claudeSkillRoot(ctx), skillId);
|
|
319
|
+
if ((await pathExists(location)) && options.overwrite !== true) {
|
|
320
|
+
return { status: INSTALL_STATUS.alreadyInstalled, location };
|
|
321
|
+
}
|
|
322
|
+
if (options.overwrite === true) {
|
|
323
|
+
await rm(location, { recursive: true, force: true });
|
|
324
|
+
}
|
|
325
|
+
await mkdir(path.dirname(location), { recursive: true });
|
|
326
|
+
await cp(source.path, location, { recursive: true });
|
|
327
|
+
return { status: INSTALL_STATUS.installed, location };
|
|
328
|
+
}
|
|
329
|
+
function claudeSkillRoot(ctx) {
|
|
330
|
+
return claudeSkillRoots(ctx)[0].root;
|
|
331
|
+
}
|
|
332
|
+
async function assertSkillDirectory(directory) {
|
|
333
|
+
try {
|
|
334
|
+
const skill = await stat(path.join(directory, SKILL_MARKDOWN));
|
|
335
|
+
if (skill.isFile()) {
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
catch {
|
|
340
|
+
// Convert below to the library's typed boundary error.
|
|
341
|
+
}
|
|
342
|
+
throw new AgentError({
|
|
343
|
+
code: AGENT_ERROR_CODE.invalidInput,
|
|
344
|
+
message: `Skill source does not contain ${SKILL_MARKDOWN}: ${directory}`,
|
|
345
|
+
data: { reason: `missing ${SKILL_MARKDOWN}` },
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
async function pathExists(target) {
|
|
349
|
+
try {
|
|
350
|
+
await stat(target);
|
|
351
|
+
return true;
|
|
352
|
+
}
|
|
353
|
+
catch {
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
async function installGithubClaudeSkill(ctx, source, options) {
|
|
358
|
+
return withStagedGithubDirectory(ctx, source, (stagedSkill) => installLocalClaudeSkill(ctx, { kind: SKILL_SOURCE_KIND.localDir, path: stagedSkill }, options));
|
|
359
|
+
}
|
|
360
|
+
async function installClaudePlugin(ctx, source, options) {
|
|
361
|
+
if (options.overwrite === true) {
|
|
362
|
+
// `claude plugin install` has no overwrite semantics; refusing is
|
|
363
|
+
// honest, silently ignoring the request is not.
|
|
364
|
+
throw new AgentError({
|
|
365
|
+
code: AGENT_ERROR_CODE.invalidInput,
|
|
366
|
+
message: "Claude plugin installation cannot overwrite an installed plugin",
|
|
367
|
+
data: { reason: "plugin install does not support overwrite" },
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
const result = await runHostCommandResult(ctx, {
|
|
371
|
+
command: CLAUDE.command,
|
|
372
|
+
args: [CLAUDE.plugin.plugin, CLAUDE.plugin.install, source.name],
|
|
373
|
+
});
|
|
374
|
+
const output = `${result.stdout}\n${result.stderr}`;
|
|
375
|
+
if (result.exit.code === 0) {
|
|
376
|
+
return {
|
|
377
|
+
status: INSTALL_STATUS.installed,
|
|
378
|
+
location: `claude:plugin:${source.name}`,
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
if (PLUGIN_ALREADY_INSTALLED.test(output)) {
|
|
382
|
+
return {
|
|
383
|
+
status: INSTALL_STATUS.alreadyInstalled,
|
|
384
|
+
location: `claude:plugin:${source.name}`,
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
throw hostCommandFailedError(CLAUDE.command, result);
|
|
388
|
+
}
|
|
389
|
+
async function addClaudeStdioMcp(ctx, name, spec, options) {
|
|
390
|
+
await runHostCommand(ctx, {
|
|
391
|
+
command: CLAUDE.command,
|
|
392
|
+
args: [
|
|
393
|
+
CLAUDE.mcp.mcp,
|
|
394
|
+
CLAUDE.mcp.addJson,
|
|
395
|
+
name,
|
|
396
|
+
JSON.stringify({
|
|
397
|
+
command: spec.command,
|
|
398
|
+
args: spec.args,
|
|
399
|
+
env: spec.env,
|
|
400
|
+
...(spec.cwd === null ? {} : { cwd: spec.cwd }),
|
|
401
|
+
}),
|
|
402
|
+
CLAUDE.mcp.scope,
|
|
403
|
+
options.scope,
|
|
404
|
+
],
|
|
405
|
+
});
|
|
406
|
+
return {
|
|
407
|
+
status: INSTALL_STATUS.installed,
|
|
408
|
+
location: `claude:${options.scope}:${name}`,
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
async function removeClaudeMcp(ctx, name, options) {
|
|
412
|
+
await runHostCommand(ctx, {
|
|
413
|
+
command: CLAUDE.command,
|
|
414
|
+
args: [
|
|
415
|
+
CLAUDE.mcp.mcp,
|
|
416
|
+
CLAUDE.mcp.remove,
|
|
417
|
+
name,
|
|
418
|
+
CLAUDE.mcp.scope,
|
|
419
|
+
options.scope,
|
|
420
|
+
],
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
async function listClaudeMcp(ctx) {
|
|
424
|
+
return listMcpServersViaCli(ctx, { command: CLAUDE.command });
|
|
425
|
+
}
|
|
426
|
+
export function claude() {
|
|
427
|
+
return defineCliAgent({
|
|
428
|
+
id: CLAUDE.id,
|
|
429
|
+
command: CLAUDE.command,
|
|
430
|
+
args: {
|
|
431
|
+
[SANDBOX_MODE.full]: (_sandbox, ctx) => [
|
|
432
|
+
...sharedArgs(ctx),
|
|
433
|
+
CLAUDE.cli.permissionMode,
|
|
434
|
+
CLAUDE.cli.bypassPermissions,
|
|
435
|
+
CLAUDE.cli.verbose,
|
|
436
|
+
],
|
|
437
|
+
[SANDBOX_MODE.readOnly]: (sandbox, ctx) => [
|
|
438
|
+
...sharedArgs(ctx),
|
|
439
|
+
CLAUDE.cli.permissionMode,
|
|
440
|
+
CLAUDE.cli.defaultPermissionMode,
|
|
441
|
+
...(sandbox.grants.length === 0
|
|
442
|
+
? [CLAUDE.cli.tools, ""]
|
|
443
|
+
: [
|
|
444
|
+
CLAUDE.cli.allowedTools,
|
|
445
|
+
sandbox.grants.map(grantToToolArg).join(","),
|
|
446
|
+
]),
|
|
447
|
+
CLAUDE.cli.verbose,
|
|
448
|
+
],
|
|
449
|
+
},
|
|
450
|
+
parseLine: parseClaudeLine,
|
|
451
|
+
parseResult: parseClaudeResult,
|
|
452
|
+
classify: [structuredQuotaMatcher()],
|
|
453
|
+
// F6: Claude CLI can report a structured quota rejection on exit 0.
|
|
454
|
+
classifyOnSuccess: [structuredQuotaMatcher()],
|
|
455
|
+
auth: {
|
|
456
|
+
[AUTH_MATERIAL_KIND.homeDir]: homeDirHandler,
|
|
457
|
+
[AUTH_MATERIAL_KIND.apiKey]: envVarAuthMaterial({
|
|
458
|
+
set: async (material, secrets) => ({
|
|
459
|
+
[CLAUDE_API_KEY_ENV_VAR]: await requireSecret(secrets, material.secret),
|
|
460
|
+
}),
|
|
461
|
+
unset: COMPETING_CONFIG_VARS,
|
|
462
|
+
}),
|
|
463
|
+
},
|
|
464
|
+
skills: {
|
|
465
|
+
list: listClaudeSkills,
|
|
466
|
+
install: {
|
|
467
|
+
[SKILL_SOURCE_KIND.localDir]: installLocalClaudeSkill,
|
|
468
|
+
[SKILL_SOURCE_KIND.githubDir]: installGithubClaudeSkill,
|
|
469
|
+
[SKILL_SOURCE_KIND.plugin]: installClaudePlugin,
|
|
470
|
+
},
|
|
471
|
+
},
|
|
472
|
+
mcp: {
|
|
473
|
+
list: listClaudeMcp,
|
|
474
|
+
add: {
|
|
475
|
+
[MCP_TRANSPORT.stdio]: addClaudeStdioMcp,
|
|
476
|
+
},
|
|
477
|
+
remove: removeClaudeMcp,
|
|
478
|
+
},
|
|
479
|
+
});
|
|
480
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in codex adapter (v1 E1/E2 argv kept verbatim):
|
|
3
|
+
* `codex exec [--model m] [-c model_reasoning_effort="e"] --json
|
|
4
|
+
* --skip-git-repo-check --sandbox <mode> -C <workspace>`, prompt on
|
|
5
|
+
* stdin. Codex sandboxing is filesystem-level, so read-only grants have
|
|
6
|
+
* no argv mapping and are ignored here.
|
|
7
|
+
*/
|
|
8
|
+
import { type FailureMatcher } from "../kernel/classify.js";
|
|
9
|
+
import type { AgentDefinition } from "../kernel/definition.js";
|
|
10
|
+
export declare const CODEX_HOME_ENV_VAR = "CODEX_HOME";
|
|
11
|
+
export declare const CODEX_API_KEY_ENV_VAR = "OPENAI_API_KEY";
|
|
12
|
+
/**
|
|
13
|
+
* Codex "selected model is at capacity" phrasing, plus the looser
|
|
14
|
+
* "model ... at capacity" combination. Exported for custom agents that
|
|
15
|
+
* surface the same provider text.
|
|
16
|
+
*/
|
|
17
|
+
export declare function capacityTextMatcher(): FailureMatcher;
|
|
18
|
+
export declare function codex(): AgentDefinition<"codex">;
|
|
19
|
+
//# sourceMappingURL=codex.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../src/agents/codex.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAwCH,OAAO,EAAE,KAAK,cAAc,EAAqB,MAAM,uBAAuB,CAAC;AAG/E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAG/D,eAAO,MAAM,kBAAkB,eAAe,CAAC;AAC/C,eAAO,MAAM,qBAAqB,mBAAmB,CAAC;AA6GtD;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,cAAc,CAepD;AAyMD,wBAAgB,KAAK,IAAI,eAAe,CAAC,OAAO,CAAC,CAoEhD"}
|