@alpacakit/agents 0.2.0-beta.2 → 0.2.0-beta.3
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/README.md +21 -0
- package/dist/agents/builtin.d.ts +2 -2
- package/dist/agents/builtin.d.ts.map +1 -1
- package/dist/agents/builtin.js +6 -4
- package/dist/agents/claude/cli.d.ts +133 -0
- package/dist/agents/claude/cli.d.ts.map +1 -0
- package/dist/agents/{claude-stream.js → claude/cli.js} +81 -10
- package/dist/agents/claude/host.d.ts +14 -0
- package/dist/agents/claude/host.d.ts.map +1 -0
- package/dist/agents/{claude.js → claude/host.js} +51 -174
- package/dist/agents/{claude.d.ts → claude/index.d.ts} +10 -11
- package/dist/agents/claude/index.d.ts.map +1 -0
- package/dist/agents/claude/index.js +134 -0
- package/dist/agents/{claude-session.d.ts → claude/session.d.ts} +3 -15
- package/dist/agents/claude/session.d.ts.map +1 -0
- package/dist/agents/claude/session.js +321 -0
- package/dist/agents/codex/cli.d.ts +132 -0
- package/dist/agents/codex/cli.d.ts.map +1 -0
- package/dist/agents/codex/cli.js +110 -0
- package/dist/agents/codex/host.d.ts +14 -0
- package/dist/agents/codex/host.d.ts.map +1 -0
- package/dist/agents/codex/host.js +221 -0
- package/dist/agents/codex/index.d.ts +14 -0
- package/dist/agents/codex/index.d.ts.map +1 -0
- package/dist/agents/codex/index.js +127 -0
- package/dist/agents/codex/session.d.ts +21 -0
- package/dist/agents/codex/session.d.ts.map +1 -0
- package/dist/agents/codex/session.js +390 -0
- package/dist/agents/openai-compatible/fetch-engine.d.ts.map +1 -1
- package/dist/agents/openai-compatible/fetch-engine.js +3 -2
- package/dist/agents/openai-compatible/pi/engine.js +1 -1
- package/dist/agents/openai-compatible/pi/{session.d.ts → run.d.ts} +1 -1
- package/dist/agents/openai-compatible/pi/run.d.ts.map +1 -0
- package/dist/agents/openai-compatible/pi/sandbox.d.ts.map +1 -1
- package/dist/auth/login-probe.d.ts +6 -4
- package/dist/auth/login-probe.d.ts.map +1 -1
- package/dist/auth/login-probe.js +19 -13
- package/dist/auth/material.d.ts +1 -1
- package/dist/auth/material.d.ts.map +1 -1
- package/dist/codex/app-server.d.ts.map +1 -1
- package/dist/codex/app-server.js +13 -42
- package/dist/codex/index.d.ts +1 -1
- package/dist/codex/index.d.ts.map +1 -1
- package/dist/config/agent-config-validation.d.ts +1 -1
- package/dist/config/agent-config-validation.d.ts.map +1 -1
- package/dist/config/agent-configs.d.ts.map +1 -1
- package/dist/config/agent-configs.js +3 -3
- package/dist/config/compose.d.ts.map +1 -1
- package/dist/config/config.d.ts +1 -1
- package/dist/config/config.d.ts.map +1 -1
- package/dist/config/index.d.ts +2 -2
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +1 -1
- package/dist/config/model.d.ts +0 -1
- package/dist/config/model.d.ts.map +1 -1
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +1 -1
- package/dist/config/store.d.ts.map +1 -1
- package/dist/config/store.js +6 -24
- package/dist/config/support.d.ts +0 -1
- package/dist/config/support.d.ts.map +1 -1
- package/dist/config/support.js +0 -9
- package/dist/core/cli-child.d.ts +56 -0
- package/dist/core/cli-child.d.ts.map +1 -0
- package/dist/core/cli-child.js +105 -0
- package/dist/core/fs.d.ts +1 -1
- package/dist/core/fs.d.ts.map +1 -1
- package/dist/core/fs.js +10 -2
- package/dist/core/node-ports.d.ts.map +1 -1
- package/dist/core/node-ports.js +1 -5
- package/dist/core/session.d.ts +4 -0
- package/dist/core/session.d.ts.map +1 -1
- package/dist/fleet/store.d.ts.map +1 -1
- package/dist/fleet/store.js +4 -3
- package/dist/host/availability.d.ts +2 -1
- package/dist/host/availability.d.ts.map +1 -1
- package/dist/host/github-dir.d.ts.map +1 -1
- package/dist/host/github-dir.js +2 -1
- package/dist/host/mcp-list.d.ts.map +1 -1
- package/dist/host/mcp-list.js +5 -6
- package/dist/host/run-command.d.ts +2 -1
- package/dist/host/run-command.d.ts.map +1 -1
- package/dist/host/run-command.js +10 -19
- package/dist/host/session-files.d.ts +2 -1
- package/dist/host/session-files.d.ts.map +1 -1
- package/dist/host/session-files.js +2 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -5
- package/dist/kernel/classify.d.ts +1 -2
- package/dist/kernel/classify.d.ts.map +1 -1
- package/dist/kernel/classify.js +1 -1
- package/dist/kernel/cli-agent.d.ts.map +1 -1
- package/dist/kernel/cli-agent.js +26 -85
- package/dist/kernel/cli-login.d.ts.map +1 -1
- package/dist/kernel/cli-login.js +9 -30
- package/dist/kernel/facets.d.ts +1 -1
- package/dist/kernel/facets.d.ts.map +1 -1
- package/dist/kernel/login.d.ts.map +1 -1
- package/dist/kernel/login.js +2 -1
- package/dist/kernel/options.d.ts +1 -1
- package/dist/kernel/options.d.ts.map +1 -1
- package/dist/kernel/run.d.ts.map +1 -1
- package/dist/kernel/run.js +2 -1
- package/dist/kernel/session.d.ts +46 -39
- package/dist/kernel/session.d.ts.map +1 -1
- package/dist/kernel/session.js +128 -69
- package/dist/testing/fake-exec.d.ts +9 -10
- package/dist/testing/fake-exec.d.ts.map +1 -1
- package/dist/testing/fake-exec.js +14 -1
- package/dist/testing/index.d.ts +1 -1
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +1 -1
- package/package.json +2 -2
- package/dist/agents/claude-session.d.ts.map +0 -1
- package/dist/agents/claude-session.js +0 -419
- package/dist/agents/claude-stream.d.ts +0 -65
- package/dist/agents/claude-stream.d.ts.map +0 -1
- package/dist/agents/claude.d.ts.map +0 -1
- package/dist/agents/codex-session.d.ts +0 -52
- package/dist/agents/codex-session.d.ts.map +0 -1
- package/dist/agents/codex-session.js +0 -495
- package/dist/agents/codex.d.ts +0 -20
- package/dist/agents/codex.d.ts.map +0 -1
- package/dist/agents/codex.js +0 -379
- package/dist/agents/openai-compatible/pi/session.d.ts.map +0 -1
- package/dist/core/process-close.d.ts +0 -11
- package/dist/core/process-close.d.ts.map +0 -1
- package/dist/core/process-close.js +0 -27
- /package/dist/agents/openai-compatible/pi/{session.js → run.js} +0 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Codex vocabulary, spelled once: the `codex exec` flags, the app-server
|
|
3
|
+
* notification and file fields the session reads, the permission words, and
|
|
4
|
+
* the host's own file names. The run adapter (`index.ts`), the session
|
|
5
|
+
* adapter (`session.ts`), and the host plane (`host.ts`) all read from here;
|
|
6
|
+
* JSON-RPC method names and sandbox words come from `codex/protocol.ts`.
|
|
7
|
+
*/
|
|
8
|
+
export const CODEX_HOME_ENV_VAR = "CODEX_HOME";
|
|
9
|
+
export const CODEX_API_KEY_ENV_VAR = "OPENAI_API_KEY";
|
|
10
|
+
export const CODEX = {
|
|
11
|
+
id: "codex",
|
|
12
|
+
command: "codex",
|
|
13
|
+
cli: {
|
|
14
|
+
exec: "exec",
|
|
15
|
+
model: "--model",
|
|
16
|
+
config: "-c",
|
|
17
|
+
reasoningEffortConfigKey: "model_reasoning_effort",
|
|
18
|
+
json: "--json",
|
|
19
|
+
skipGitRepoCheck: "--skip-git-repo-check",
|
|
20
|
+
sandbox: "--sandbox",
|
|
21
|
+
workspace: "-C",
|
|
22
|
+
},
|
|
23
|
+
auth: {
|
|
24
|
+
// Exit-code-only login probe (E12): `codex login status` exits 0 when a
|
|
25
|
+
// credential is present, nonzero otherwise. The output format is not
|
|
26
|
+
// parsed — only the exit code decides valid/invalid, like claude's.
|
|
27
|
+
statusArgs: ["login", "status"],
|
|
28
|
+
oauthLoginArgs: ["login"],
|
|
29
|
+
deviceLoginArgs: ["login", "--device-auth"],
|
|
30
|
+
},
|
|
31
|
+
json: {
|
|
32
|
+
field: {
|
|
33
|
+
type: "type",
|
|
34
|
+
text: "text",
|
|
35
|
+
item: "item",
|
|
36
|
+
},
|
|
37
|
+
event: {
|
|
38
|
+
turnCompleted: "turn.completed",
|
|
39
|
+
agentMessage: "agent_message",
|
|
40
|
+
itemCompleted: "item.completed",
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
mcp: {
|
|
44
|
+
add: "add",
|
|
45
|
+
env: "--env",
|
|
46
|
+
executableSeparator: "--",
|
|
47
|
+
mcp: "mcp",
|
|
48
|
+
remove: "remove",
|
|
49
|
+
},
|
|
50
|
+
notification: {
|
|
51
|
+
threadId: "threadId",
|
|
52
|
+
turnId: "turnId",
|
|
53
|
+
turn: "turn",
|
|
54
|
+
item: "item",
|
|
55
|
+
id: "id",
|
|
56
|
+
type: "type",
|
|
57
|
+
text: "text",
|
|
58
|
+
status: "status",
|
|
59
|
+
items: "items",
|
|
60
|
+
phase: "phase",
|
|
61
|
+
finalAnswer: "final_answer",
|
|
62
|
+
agentMessage: "agentMessage",
|
|
63
|
+
userMessage: "userMessage",
|
|
64
|
+
reasoning: "reasoning",
|
|
65
|
+
command: "command",
|
|
66
|
+
reason: "reason",
|
|
67
|
+
},
|
|
68
|
+
turnStatus: {
|
|
69
|
+
completed: "completed",
|
|
70
|
+
interrupted: "interrupted",
|
|
71
|
+
failed: "failed",
|
|
72
|
+
},
|
|
73
|
+
decision: { accept: "accept", decline: "decline" },
|
|
74
|
+
error: {
|
|
75
|
+
archived: "is archived",
|
|
76
|
+
methodNotFound: -32601,
|
|
77
|
+
unsupported: "unsupported server request",
|
|
78
|
+
},
|
|
79
|
+
files: {
|
|
80
|
+
root: ".codex",
|
|
81
|
+
sessions: "sessions",
|
|
82
|
+
archivedSessions: "archived_sessions",
|
|
83
|
+
writerLocks: "thread-writer-locks",
|
|
84
|
+
lockExtension: ".lock",
|
|
85
|
+
rolloutExtension: ".jsonl",
|
|
86
|
+
type: "type",
|
|
87
|
+
payload: "payload",
|
|
88
|
+
sessionMeta: "session_meta",
|
|
89
|
+
turnContext: "turn_context",
|
|
90
|
+
cwd: "cwd",
|
|
91
|
+
approvalPolicy: "approval_policy",
|
|
92
|
+
approvalsReviewer: "approvals_reviewer",
|
|
93
|
+
sandboxPolicy: "sandbox_policy",
|
|
94
|
+
writableRoots: "writable_roots",
|
|
95
|
+
networkAccess: "network_access",
|
|
96
|
+
excludeTmpdirEnvVar: "exclude_tmpdir_env_var",
|
|
97
|
+
excludeSlashTmp: "exclude_slash_tmp",
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
/** `approval_policy` words (codex 0.153.4 `AskForApproval`; the granular object form is not modeled). */
|
|
101
|
+
export const CODEX_APPROVAL_POLICY = {
|
|
102
|
+
untrusted: "untrusted",
|
|
103
|
+
onRequest: "on-request",
|
|
104
|
+
never: "never",
|
|
105
|
+
};
|
|
106
|
+
export const CODEX_APPROVALS_REVIEWER = {
|
|
107
|
+
user: "user",
|
|
108
|
+
autoReview: "auto_review",
|
|
109
|
+
guardianSubagent: "guardian_subagent",
|
|
110
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The codex host plane: auth materials and sign-in, skills and plugins
|
|
3
|
+
* through a short-lived app-server client, and MCP registration through
|
|
4
|
+
* the CLI. Outside a run and a session; every path comes from
|
|
5
|
+
* `HostContext.location`, never `os.homedir()`.
|
|
6
|
+
*/
|
|
7
|
+
import { type LoginCapability } from "../../auth/login.js";
|
|
8
|
+
import type { MaterialHandlers } from "../../auth/material.js";
|
|
9
|
+
import { type McpCapability, type SkillsCapability } from "../../host/capabilities.js";
|
|
10
|
+
export declare const codexAuth: MaterialHandlers;
|
|
11
|
+
export declare const codexLogin: LoginCapability;
|
|
12
|
+
export declare const codexSkills: SkillsCapability;
|
|
13
|
+
export declare const codexMcp: McpCapability;
|
|
14
|
+
//# sourceMappingURL=host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../../src/agents/codex/host.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAEL,KAAK,eAAe,EAErB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAmB/D,OAAO,EAOL,KAAK,aAAa,EAKlB,KAAK,gBAAgB,EAEtB,MAAM,4BAA4B,CAAC;AAkOpC,eAAO,MAAM,SAAS,EAAE,gBAqBvB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,eAKxB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,gBAKzB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,aAMtB,CAAC"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The codex host plane: auth materials and sign-in, skills and plugins
|
|
3
|
+
* through a short-lived app-server client, and MCP registration through
|
|
4
|
+
* the CLI. Outside a run and a session; every path comes from
|
|
5
|
+
* `HostContext.location`, never `os.homedir()`.
|
|
6
|
+
*/
|
|
7
|
+
import { LOGIN_METHOD, } from "../../auth/login.js";
|
|
8
|
+
import { cliLoginProbe } from "../../auth/login-probe.js";
|
|
9
|
+
import { AUTH_MATERIAL_KIND, envVarAuthMaterial } from "../../auth/material.js";
|
|
10
|
+
import { requireSecret } from "../../auth/secrets.js";
|
|
11
|
+
import { listAllCodexMcpServerStatuses, withCodexAppServer, } from "../../codex/app-server.js";
|
|
12
|
+
import { CODEX_APP_SERVER_METHOD } from "../../codex/protocol.js";
|
|
13
|
+
import { AGENT_ERROR_CODE, AgentError, AUTH_FAILURE_REASON, } from "../../core/error.js";
|
|
14
|
+
import { INSTALL_STATUS, MCP_SCOPE, MCP_TRANSPORT, SKILL_SOURCE_KIND, } from "../../host/capabilities.js";
|
|
15
|
+
import { runHostCommand } from "../../host/run-command.js";
|
|
16
|
+
import { cliLoginCommand } from "../../kernel/cli-login.js";
|
|
17
|
+
import { CODEX, CODEX_API_KEY_ENV_VAR, CODEX_HOME_ENV_VAR } from "./cli.js";
|
|
18
|
+
const COMPETING_API_KEY_VARS = [CODEX_API_KEY_ENV_VAR, "CODEX_API_KEY"];
|
|
19
|
+
const COMPETING_HOME_VARS = [CODEX_HOME_ENV_VAR, "CODEX_API_KEY"];
|
|
20
|
+
const UNSUPPORTED_CWD_REASON = "unsupported codex stdio mcp cwd";
|
|
21
|
+
const UNSUPPORTED_SCOPE_REASON_PREFIX = "unsupported codex mcp scope";
|
|
22
|
+
const UNSUPPORTED_PLUGIN_OVERWRITE_REASON = "plugin install does not support overwrite";
|
|
23
|
+
const CODEX_PLUGIN_AUTH_REQUIRED_MESSAGE = "Codex plugin installation requires app authorization";
|
|
24
|
+
const CODEX_ALREADY_INSTALLED_STATUS = /already/i;
|
|
25
|
+
const CODEX_MCP_UNUSABLE_STATUS = /failed|error|invalid|missing|required/i;
|
|
26
|
+
function codexAppServerCwd(ctx) {
|
|
27
|
+
return ctx.location.projectDir ?? ctx.location.homeDir;
|
|
28
|
+
}
|
|
29
|
+
function codexAppServerCwds(ctx) {
|
|
30
|
+
return [codexAppServerCwd(ctx)];
|
|
31
|
+
}
|
|
32
|
+
async function listCodexSkills(ctx) {
|
|
33
|
+
return withCodexAppServer(codexAppServerOptions(ctx), async (client) => {
|
|
34
|
+
const result = await client.request(CODEX_APP_SERVER_METHOD.skillsList, {
|
|
35
|
+
cwds: codexAppServerCwds(ctx),
|
|
36
|
+
forceReload: true,
|
|
37
|
+
});
|
|
38
|
+
return skillsFromCodexResult(result);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
async function installCodexPlugin(ctx, source, options) {
|
|
42
|
+
if (options.overwrite === true) {
|
|
43
|
+
// `plugin/install` has no overwrite semantics; refusing is honest,
|
|
44
|
+
// silently ignoring the request is not (same contract as claude).
|
|
45
|
+
throw new AgentError({
|
|
46
|
+
code: AGENT_ERROR_CODE.invalidInput,
|
|
47
|
+
classification: AgentError.agentFailure(AGENT_ERROR_CODE.invalidInput),
|
|
48
|
+
message: "Codex plugin installation cannot overwrite an installed plugin",
|
|
49
|
+
data: { reason: UNSUPPORTED_PLUGIN_OVERWRITE_REASON },
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return withCodexAppServer(codexAppServerOptions(ctx), async (client) => {
|
|
53
|
+
const result = await client.request(CODEX_APP_SERVER_METHOD.pluginInstall, {
|
|
54
|
+
pluginName: source.name,
|
|
55
|
+
marketplacePath: null,
|
|
56
|
+
remoteMarketplaceName: null,
|
|
57
|
+
});
|
|
58
|
+
return installOutcomeFromCodexPlugin(source.name, result);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
async function listCodexMcp(ctx) {
|
|
62
|
+
return withCodexAppServer(codexAppServerOptions(ctx), async (client) => (await listAllCodexMcpServerStatuses(client)).map(codexMcpState));
|
|
63
|
+
}
|
|
64
|
+
async function addCodexStdioMcp(ctx, name, spec, options) {
|
|
65
|
+
assertCodexStdioMcpSupported(spec, options);
|
|
66
|
+
await runHostCommand(ctx, {
|
|
67
|
+
command: CODEX.command,
|
|
68
|
+
args: [
|
|
69
|
+
CODEX.mcp.mcp,
|
|
70
|
+
CODEX.mcp.add,
|
|
71
|
+
name,
|
|
72
|
+
...Object.entries(spec.env).flatMap(([key, value]) => [
|
|
73
|
+
CODEX.mcp.env,
|
|
74
|
+
`${key}=${value}`,
|
|
75
|
+
]),
|
|
76
|
+
CODEX.mcp.executableSeparator,
|
|
77
|
+
spec.command,
|
|
78
|
+
...spec.args,
|
|
79
|
+
],
|
|
80
|
+
});
|
|
81
|
+
return {
|
|
82
|
+
status: INSTALL_STATUS.installed,
|
|
83
|
+
location: `codex:${options.scope}:${name}`,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
async function removeCodexMcp(ctx, name, options) {
|
|
87
|
+
assertCodexMcpScopeSupported(options.scope);
|
|
88
|
+
await runHostCommand(ctx, {
|
|
89
|
+
command: CODEX.command,
|
|
90
|
+
args: [CODEX.mcp.mcp, CODEX.mcp.remove, name],
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
function assertCodexStdioMcpSupported(spec, options) {
|
|
94
|
+
assertCodexMcpScopeSupported(options.scope);
|
|
95
|
+
if (spec.cwd !== null) {
|
|
96
|
+
throw new AgentError({
|
|
97
|
+
code: AGENT_ERROR_CODE.invalidInput,
|
|
98
|
+
classification: AgentError.agentFailure(AGENT_ERROR_CODE.invalidInput),
|
|
99
|
+
message: "Codex stdio MCP registration does not support server cwd",
|
|
100
|
+
data: { reason: UNSUPPORTED_CWD_REASON },
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function assertCodexMcpScopeSupported(scope) {
|
|
105
|
+
if (scope === MCP_SCOPE.user) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const reason = [UNSUPPORTED_SCOPE_REASON_PREFIX, scope].join(": ");
|
|
109
|
+
throw new AgentError({
|
|
110
|
+
code: AGENT_ERROR_CODE.invalidInput,
|
|
111
|
+
classification: AgentError.agentFailure(AGENT_ERROR_CODE.invalidInput),
|
|
112
|
+
message: `Codex MCP registration does not support scope "${scope}"`,
|
|
113
|
+
data: { reason },
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
function codexAppServerOptions(ctx) {
|
|
117
|
+
return {
|
|
118
|
+
exec: ctx.exec,
|
|
119
|
+
clock: ctx.clock,
|
|
120
|
+
env: ctx.env,
|
|
121
|
+
cwd: codexAppServerCwd(ctx),
|
|
122
|
+
command: CODEX.command,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function skillsFromCodexResult(result) {
|
|
126
|
+
return result.data.flatMap((entry) => entry.skills.map((skill) => ({
|
|
127
|
+
id: skill.name,
|
|
128
|
+
name: skill.name,
|
|
129
|
+
description: skill.description,
|
|
130
|
+
location: skill.path,
|
|
131
|
+
source: `codex:${skill.scope}`,
|
|
132
|
+
})));
|
|
133
|
+
}
|
|
134
|
+
function installOutcomeFromCodexPlugin(name, result) {
|
|
135
|
+
if (result.appsNeedingAuth.length > 0) {
|
|
136
|
+
throw new AgentError({
|
|
137
|
+
code: AGENT_ERROR_CODE.auth,
|
|
138
|
+
classification: AgentError.agentFailure(AGENT_ERROR_CODE.auth),
|
|
139
|
+
message: CODEX_PLUGIN_AUTH_REQUIRED_MESSAGE,
|
|
140
|
+
data: {
|
|
141
|
+
reason: AUTH_FAILURE_REASON.notLoggedIn,
|
|
142
|
+
detail: result.authPolicy,
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
const location = result.location ?? `codex:plugin:${name}`;
|
|
147
|
+
const alreadyInstalled = result.alreadyInstalled === true ||
|
|
148
|
+
(result.status !== null &&
|
|
149
|
+
CODEX_ALREADY_INSTALLED_STATUS.test(result.status));
|
|
150
|
+
return {
|
|
151
|
+
status: alreadyInstalled
|
|
152
|
+
? INSTALL_STATUS.alreadyInstalled
|
|
153
|
+
: INSTALL_STATUS.installed,
|
|
154
|
+
location,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
function codexMcpState(status) {
|
|
158
|
+
// tools === null = the app-server did not enumerate tools; McpServerState
|
|
159
|
+
// keeps that distinct from an enumerated-but-empty tool list.
|
|
160
|
+
const tools = status.tools === null
|
|
161
|
+
? null
|
|
162
|
+
: Object.entries(status.tools).map(([key, tool]) => tool.name ?? key);
|
|
163
|
+
return {
|
|
164
|
+
name: status.name,
|
|
165
|
+
transport: MCP_TRANSPORT.stdio,
|
|
166
|
+
usable: !CODEX_MCP_UNUSABLE_STATUS.test(status.authStatus),
|
|
167
|
+
tools,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
function codexLoginCommand(args) {
|
|
171
|
+
return (request, ctx) => cliLoginCommand({
|
|
172
|
+
command: CODEX.command,
|
|
173
|
+
args,
|
|
174
|
+
envPatch: {
|
|
175
|
+
set: { [CODEX_HOME_ENV_VAR]: request.homeDir },
|
|
176
|
+
unset: COMPETING_API_KEY_VARS,
|
|
177
|
+
},
|
|
178
|
+
request,
|
|
179
|
+
ctx,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
export const codexAuth = {
|
|
183
|
+
[AUTH_MATERIAL_KIND.homeDir]: envVarAuthMaterial({
|
|
184
|
+
set: (material) => ({ [CODEX_HOME_ENV_VAR]: material.path }),
|
|
185
|
+
unset: COMPETING_API_KEY_VARS,
|
|
186
|
+
check: (material, ctx) => cliLoginProbe({
|
|
187
|
+
command: CODEX.command,
|
|
188
|
+
args: CODEX.auth.statusArgs,
|
|
189
|
+
envPatch: {
|
|
190
|
+
set: { [CODEX_HOME_ENV_VAR]: material.path },
|
|
191
|
+
unset: COMPETING_API_KEY_VARS,
|
|
192
|
+
},
|
|
193
|
+
ctx,
|
|
194
|
+
}),
|
|
195
|
+
}),
|
|
196
|
+
[AUTH_MATERIAL_KIND.apiKey]: envVarAuthMaterial({
|
|
197
|
+
set: async (material, secrets) => ({
|
|
198
|
+
[CODEX_API_KEY_ENV_VAR]: await requireSecret(secrets, material.secret),
|
|
199
|
+
}),
|
|
200
|
+
unset: COMPETING_HOME_VARS,
|
|
201
|
+
}),
|
|
202
|
+
};
|
|
203
|
+
export const codexLogin = {
|
|
204
|
+
methods: {
|
|
205
|
+
[LOGIN_METHOD.oauth]: codexLoginCommand(CODEX.auth.oauthLoginArgs),
|
|
206
|
+
[LOGIN_METHOD.device]: codexLoginCommand(CODEX.auth.deviceLoginArgs),
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
export const codexSkills = {
|
|
210
|
+
list: listCodexSkills,
|
|
211
|
+
install: {
|
|
212
|
+
[SKILL_SOURCE_KIND.plugin]: installCodexPlugin,
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
export const codexMcp = {
|
|
216
|
+
list: listCodexMcp,
|
|
217
|
+
add: {
|
|
218
|
+
[MCP_TRANSPORT.stdio]: addCodexStdioMcp,
|
|
219
|
+
},
|
|
220
|
+
remove: removeCodexMcp,
|
|
221
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The built-in codex agent: the one-shot run contract
|
|
3
|
+
* (`codex exec [--model m] [-c model_reasoning_effort="e"] --json
|
|
4
|
+
* --skip-git-repo-check --sandbox <mode> -C <workspace>`, prompt on
|
|
5
|
+
* stdin; sandboxing is filesystem-level, so read-only grants have no argv
|
|
6
|
+
* mapping) composed with the session adapter and the host plane.
|
|
7
|
+
* Vocabulary lives in `cli.ts`.
|
|
8
|
+
*/
|
|
9
|
+
import { type FailureMatcher } from "../../kernel/classify.js";
|
|
10
|
+
import type { AgentDefinition } from "../../kernel/definition.js";
|
|
11
|
+
import { type CodexSessionPermissions } from "./cli.js";
|
|
12
|
+
export declare function capacityTextMatcher(): FailureMatcher;
|
|
13
|
+
export declare function codex(): AgentDefinition<"codex", CodexSessionPermissions>;
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agents/codex/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH,OAAO,EACL,KAAK,cAAc,EAEpB,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAElE,OAAO,EAAS,KAAK,uBAAuB,EAAE,MAAM,UAAU,CAAC;AA2D/D,wBAAgB,mBAAmB,IAAI,cAAc,CAepD;AAED,wBAAgB,KAAK,IAAI,eAAe,CAAC,OAAO,EAAE,uBAAuB,CAAC,CA8CzE"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The built-in codex agent: the one-shot run contract
|
|
3
|
+
* (`codex exec [--model m] [-c model_reasoning_effort="e"] --json
|
|
4
|
+
* --skip-git-repo-check --sandbox <mode> -C <workspace>`, prompt on
|
|
5
|
+
* stdin; sandboxing is filesystem-level, so read-only grants have no argv
|
|
6
|
+
* mapping) composed with the session adapter and the host plane.
|
|
7
|
+
* Vocabulary lives in `cli.ts`.
|
|
8
|
+
*/
|
|
9
|
+
import { CODEX_SANDBOX_MODE } from "../../codex/protocol.js";
|
|
10
|
+
import { AGENT_ERROR_CODE } from "../../core/error.js";
|
|
11
|
+
import { readJsonRecord, readRecord, readString } from "../../core/json.js";
|
|
12
|
+
import { AGENT_EVENT_TYPE } from "../../core/run.js";
|
|
13
|
+
import { cliAvailability } from "../../host/availability.js";
|
|
14
|
+
import { parseCooldownHint, } from "../../kernel/classify.js";
|
|
15
|
+
import { defineCliAgent } from "../../kernel/cli-agent.js";
|
|
16
|
+
import { SANDBOX_MODE } from "../../kernel/options.js";
|
|
17
|
+
import { CODEX } from "./cli.js";
|
|
18
|
+
import { codexAuth, codexLogin, codexMcp, codexSkills } from "./host.js";
|
|
19
|
+
import { codexSessions } from "./session.js";
|
|
20
|
+
function sharedArgs(ctx, sandboxValue) {
|
|
21
|
+
return [
|
|
22
|
+
CODEX.cli.exec,
|
|
23
|
+
...(ctx.model === null ? [] : [CODEX.cli.model, ctx.model]),
|
|
24
|
+
...(ctx.effort === null
|
|
25
|
+
? []
|
|
26
|
+
: [
|
|
27
|
+
CODEX.cli.config,
|
|
28
|
+
`${CODEX.cli.reasoningEffortConfigKey}="${ctx.effort}"`,
|
|
29
|
+
]),
|
|
30
|
+
CODEX.cli.json,
|
|
31
|
+
CODEX.cli.skipGitRepoCheck,
|
|
32
|
+
CODEX.cli.sandbox,
|
|
33
|
+
sandboxValue,
|
|
34
|
+
CODEX.cli.workspace,
|
|
35
|
+
ctx.workspace,
|
|
36
|
+
];
|
|
37
|
+
}
|
|
38
|
+
function parseCodexLine(line) {
|
|
39
|
+
const record = readJsonRecord(line);
|
|
40
|
+
if (record === null) {
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
const type = readString(record, CODEX.json.field.type);
|
|
44
|
+
if (type === CODEX.json.event.turnCompleted) {
|
|
45
|
+
return [{ type: AGENT_EVENT_TYPE.turn }];
|
|
46
|
+
}
|
|
47
|
+
if (type === CODEX.json.event.agentMessage) {
|
|
48
|
+
const text = readString(record, CODEX.json.field.text);
|
|
49
|
+
return text === null ? [] : [{ type: AGENT_EVENT_TYPE.message, text }];
|
|
50
|
+
}
|
|
51
|
+
if (type === CODEX.json.event.itemCompleted) {
|
|
52
|
+
const item = readRecord(record, CODEX.json.field.item);
|
|
53
|
+
if (item !== null &&
|
|
54
|
+
readString(item, CODEX.json.field.type) === CODEX.json.event.agentMessage) {
|
|
55
|
+
const text = readString(item, CODEX.json.field.text);
|
|
56
|
+
return text === null ? [] : [{ type: AGENT_EVENT_TYPE.message, text }];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Codex "selected model is at capacity" phrasing, plus the looser
|
|
63
|
+
* "model ... at capacity" combination. Exported for custom agents that
|
|
64
|
+
* surface the same provider text.
|
|
65
|
+
*/
|
|
66
|
+
/** Codex capacity phrasing (v1 F5 signals, kept verbatim). */
|
|
67
|
+
const CAPACITY_TEXT = /selected model is at capacity|model is at capacity/i;
|
|
68
|
+
const CAPACITY_COMBINED = /at capacity/i;
|
|
69
|
+
const CAPACITY_MODEL = /model/i;
|
|
70
|
+
export function capacityTextMatcher() {
|
|
71
|
+
return (evidence) => {
|
|
72
|
+
const text = `${evidence.stderr}\n${evidence.stdout}`;
|
|
73
|
+
const matches = CAPACITY_TEXT.test(text) ||
|
|
74
|
+
(CAPACITY_COMBINED.test(text) && CAPACITY_MODEL.test(text));
|
|
75
|
+
if (!matches) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
code: AGENT_ERROR_CODE.capacity,
|
|
80
|
+
message: "Provider is at capacity",
|
|
81
|
+
data: { cooldownUntil: parseCooldownHint(text, evidence.now) },
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
export function codex() {
|
|
86
|
+
const definition = defineCliAgent({
|
|
87
|
+
id: CODEX.id,
|
|
88
|
+
command: CODEX.command,
|
|
89
|
+
args: {
|
|
90
|
+
[SANDBOX_MODE.full]: (_sandbox, ctx) => sharedArgs(ctx, CODEX_SANDBOX_MODE.dangerFullAccess),
|
|
91
|
+
[SANDBOX_MODE.readOnly]: (_sandbox, ctx) => sharedArgs(ctx, CODEX_SANDBOX_MODE.readOnly),
|
|
92
|
+
},
|
|
93
|
+
parseLine: parseCodexLine,
|
|
94
|
+
classify: [capacityTextMatcher()],
|
|
95
|
+
detectCompletion: (line, state) => {
|
|
96
|
+
if (state.messages.length === 0) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
const record = readJsonRecord(line);
|
|
100
|
+
return (record !== null &&
|
|
101
|
+
readString(record, CODEX.json.field.type) ===
|
|
102
|
+
CODEX.json.event.turnCompleted);
|
|
103
|
+
},
|
|
104
|
+
availability: cliAvailability({
|
|
105
|
+
command: CODEX.command,
|
|
106
|
+
commandMissingRemediation: {
|
|
107
|
+
detail: "Install Codex and ensure `codex` is on PATH.",
|
|
108
|
+
command: null,
|
|
109
|
+
},
|
|
110
|
+
authentication: {
|
|
111
|
+
args: CODEX.auth.statusArgs,
|
|
112
|
+
remediation: {
|
|
113
|
+
detail: "Sign in to Codex.",
|
|
114
|
+
command: {
|
|
115
|
+
executable: CODEX.command,
|
|
116
|
+
args: CODEX.auth.oauthLoginArgs,
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
}),
|
|
121
|
+
auth: codexAuth,
|
|
122
|
+
login: codexLogin,
|
|
123
|
+
skills: codexSkills,
|
|
124
|
+
mcp: codexMcp,
|
|
125
|
+
});
|
|
126
|
+
return { ...definition, session: codexSessions() };
|
|
127
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex session adapter: one `codex app-server` process holding one thread.
|
|
3
|
+
*
|
|
4
|
+
* Protocol facts (codex 0.153.4, T53 / T57 / T61 lab runs):
|
|
5
|
+
* - `thread/start {cwd, sandbox, approvalPolicy, approvalsReviewer}` creates
|
|
6
|
+
* the thread and takes its writer lock; with a writable sandbox Codex also
|
|
7
|
+
* appends a `trust_level` entry for `cwd` to `~/.codex/config.toml`;
|
|
8
|
+
* - `thread/resume` must repeat the permissions — without `sandbox` the
|
|
9
|
+
* resumed turns ran as danger-full-access; it answers -32600 "already has
|
|
10
|
+
* an active writer" while another process holds the thread and -32600
|
|
11
|
+
* "… is archived" for an archived one (`thread/unarchive` first, opt-in);
|
|
12
|
+
* - `turn/start` answers the turn id at once; `turn/steer {expectedTurnId}`
|
|
13
|
+
* appends to it; `turn/interrupt` ends it with `turn/completed`
|
|
14
|
+
* status `interrupted` (the command's own `item/completed` may trail by ~36 s);
|
|
15
|
+
* - `item/commandExecution/requestApproval` is a server request answered by
|
|
16
|
+
* `{"decision": "accept" | "decline"}`; closing stdin releases the lock.
|
|
17
|
+
*/
|
|
18
|
+
import { type SessionCapability } from "../../kernel/session.js";
|
|
19
|
+
import { type CodexSessionPermissions } from "./cli.js";
|
|
20
|
+
export declare function codexSessions(): SessionCapability<CodexSessionPermissions>;
|
|
21
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../src/agents/codex/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAyCH,OAAO,EAKL,KAAK,iBAAiB,EAIvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAKL,KAAK,uBAAuB,EAC7B,MAAM,UAAU,CAAC;AAielB,wBAAgB,aAAa,IAAI,iBAAiB,CAAC,uBAAuB,CAAC,CAM1E"}
|