@adecore/agents 0.0.1 → 0.17.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +110 -0
- package/README.md +33 -0
- package/dist/async.d.ts +2 -0
- package/dist/async.js +31 -0
- package/dist/chat/attachment-store.d.ts +10 -0
- package/dist/chat/attachment-store.js +93 -0
- package/dist/chat/backend.d.ts +214 -0
- package/dist/chat/backend.js +1 -0
- package/dist/chat/background-work.d.ts +8 -0
- package/dist/chat/background-work.js +33 -0
- package/dist/chat/bookmark-store.d.ts +25 -0
- package/dist/chat/bookmark-store.js +141 -0
- package/dist/chat/chat-core.d.ts +311 -0
- package/dist/chat/chat-core.js +1025 -0
- package/dist/chat/chat-log.d.ts +33 -0
- package/dist/chat/chat-log.js +163 -0
- package/dist/chat/chat-process.d.ts +46 -0
- package/dist/chat/chat-process.js +190 -0
- package/dist/chat/chat-session.d.ts +209 -0
- package/dist/chat/chat-session.js +1511 -0
- package/dist/chat/chat-store.d.ts +37 -0
- package/dist/chat/chat-store.js +202 -0
- package/dist/chat/chat-title.d.ts +10 -0
- package/dist/chat/chat-title.js +74 -0
- package/dist/chat/claude-backend.d.ts +35 -0
- package/dist/chat/claude-backend.js +214 -0
- package/dist/chat/claude-protocol.d.ts +41 -0
- package/dist/chat/claude-protocol.js +642 -0
- package/dist/chat/claude-title.d.ts +11 -0
- package/dist/chat/claude-title.js +97 -0
- package/dist/chat/claude-transcript.d.ts +28 -0
- package/dist/chat/claude-transcript.js +211 -0
- package/dist/chat/codex-backend.d.ts +51 -0
- package/dist/chat/codex-backend.js +364 -0
- package/dist/chat/codex-protocol.d.ts +56 -0
- package/dist/chat/codex-protocol.js +767 -0
- package/dist/chat/codex-thread.d.ts +32 -0
- package/dist/chat/codex-thread.js +131 -0
- package/dist/chat/codex-transport.d.ts +42 -0
- package/dist/chat/codex-transport.js +188 -0
- package/dist/chat/composer-preferences.d.ts +15 -0
- package/dist/chat/composer-preferences.js +46 -0
- package/dist/chat/context-breakdown.d.ts +2 -0
- package/dist/chat/context-breakdown.js +74 -0
- package/dist/chat/delta-coalescer.d.ts +12 -0
- package/dist/chat/delta-coalescer.js +55 -0
- package/dist/chat/errors.d.ts +4 -0
- package/dist/chat/errors.js +4 -0
- package/dist/chat/fake-claude.d.ts +3 -0
- package/dist/chat/fake-claude.js +982 -0
- package/dist/chat/fake-cli.d.ts +25 -0
- package/dist/chat/fake-cli.js +157 -0
- package/dist/chat/fake-codex.d.ts +10 -0
- package/dist/chat/fake-codex.js +502 -0
- package/dist/chat/fixtures/claude-2.1.285-auto-fallback.json +24 -0
- package/dist/chat/fixtures/claude-2.1.285-native-children.json +6600 -0
- package/dist/chat/fixtures/claude-2.1.285-resume-direct-compact.json +202 -0
- package/dist/chat/fixtures/claude-2.1.285-resume-task-notification.json +57 -0
- package/dist/chat/fixtures/claude-projects/-work-demo/5f1c2a9e-0b7d-4c1e-9a53-3e2f8d6b7a10/subagents/agent-a4c2e8f10b3d5a7e9.jsonl +10 -0
- package/dist/chat/fixtures/claude-projects/-work-demo/5f1c2a9e-0b7d-4c1e-9a53-3e2f8d6b7a10/subagents/agent-a4c2e8f10b3d5a7e9.meta.json +1 -0
- package/dist/chat/fixtures/claude-projects/-work-demo/5f1c2a9e-0b7d-4c1e-9a53-3e2f8d6b7a10/subagents/agent-a9b8c7d6e5f4a3b21.jsonl +2 -0
- package/dist/chat/fixtures/claude-projects/-work-demo/5f1c2a9e-0b7d-4c1e-9a53-3e2f8d6b7a10/subagents/agent-a9b8c7d6e5f4a3b21.meta.json +1 -0
- package/dist/chat/fixtures/codex-0.159.2-native-approval.json +119 -0
- package/dist/chat/fixtures/codex-0.159.2-native-file-approval.json +136 -0
- package/dist/chat/fixtures/codex-0.159.2-native-interacted.json +220 -0
- package/dist/chat/fixtures/codex-0.159.2-usage-windows.json +74 -0
- package/dist/chat/input.d.ts +19 -0
- package/dist/chat/input.js +71 -0
- package/dist/chat/limit-resume.d.ts +11 -0
- package/dist/chat/limit-resume.js +68 -0
- package/dist/chat/projector.d.ts +60 -0
- package/dist/chat/projector.js +860 -0
- package/dist/chat/request-summary.d.ts +3 -0
- package/dist/chat/request-summary.js +143 -0
- package/dist/chat/subagent-projection.d.ts +8 -0
- package/dist/chat/subagent-projection.js +40 -0
- package/dist/chat/subagent-reader.d.ts +66 -0
- package/dist/chat/subagent-reader.js +396 -0
- package/dist/chat/subagent-settlement.d.ts +6 -0
- package/dist/chat/subagent-settlement.js +103 -0
- package/dist/chat/thread.d.ts +30 -0
- package/dist/chat/thread.js +147 -0
- package/dist/chat/wake-chat.d.ts +20 -0
- package/dist/chat/wake-chat.js +27 -0
- package/dist/client-sinks.d.ts +9 -0
- package/dist/client-sinks.js +34 -0
- package/dist/coded-error.d.ts +5 -0
- package/dist/coded-error.js +17 -0
- package/dist/context/argv.d.ts +11 -0
- package/dist/context/argv.js +58 -0
- package/dist/context/refusal.d.ts +9 -0
- package/dist/context/refusal.js +38 -0
- package/dist/context/verb.d.ts +85 -0
- package/dist/context/verb.js +233 -0
- package/dist/error-text.d.ts +5 -0
- package/dist/error-text.js +24 -0
- package/dist/events.d.ts +12 -0
- package/dist/events.js +1 -0
- package/dist/fs.d.ts +9 -0
- package/dist/fs.js +107 -0
- package/dist/host/agent-host.d.ts +28 -0
- package/dist/host/agent-host.js +105 -0
- package/dist/host/environment.d.ts +7 -0
- package/dist/host/environment.js +22 -0
- package/dist/host/handlers.d.ts +30 -0
- package/dist/host/handlers.js +111 -0
- package/dist/host/memory-port.d.ts +2 -0
- package/dist/host/memory-port.js +25 -0
- package/dist/host/wiring.d.ts +40 -0
- package/dist/host/wiring.js +120 -0
- package/dist/lineage.d.ts +44 -0
- package/dist/lineage.js +134 -0
- package/dist/messages/deliver-message.d.ts +21 -0
- package/dist/messages/deliver-message.js +42 -0
- package/dist/messages/deliver-notice.d.ts +25 -0
- package/dist/messages/deliver-notice.js +75 -0
- package/dist/messages/notice-notes.d.ts +15 -0
- package/dist/messages/notice-notes.js +26 -0
- package/dist/messages/notice-store.d.ts +30 -0
- package/dist/messages/notice-store.js +120 -0
- package/dist/modes.d.ts +11 -0
- package/dist/modes.js +28 -0
- package/dist/outbox/manual-clock.d.ts +10 -0
- package/dist/outbox/manual-clock.js +25 -0
- package/dist/outbox/outbox-worker.d.ts +44 -0
- package/dist/outbox/outbox-worker.js +173 -0
- package/dist/outbox/outbox.d.ts +37 -0
- package/dist/outbox/outbox.js +76 -0
- package/dist/providers/accounts/accounts.d.ts +20 -0
- package/dist/providers/accounts/accounts.js +158 -0
- package/dist/providers/accounts/launch.d.ts +17 -0
- package/dist/providers/accounts/launch.js +30 -0
- package/dist/providers/accounts/service.d.ts +87 -0
- package/dist/providers/accounts/service.js +538 -0
- package/dist/providers/accounts/shadow-home.d.ts +8 -0
- package/dist/providers/accounts/shadow-home.js +70 -0
- package/dist/providers/accounts/status.d.ts +12 -0
- package/dist/providers/accounts/status.js +85 -0
- package/dist/providers/accounts/store.d.ts +14 -0
- package/dist/providers/accounts/store.js +112 -0
- package/dist/providers/accounts/test-accounts.d.ts +12 -0
- package/dist/providers/accounts/test-accounts.js +38 -0
- package/dist/providers/accounts/variables.d.ts +27 -0
- package/dist/providers/accounts/variables.js +94 -0
- package/dist/providers/catalog.d.ts +17 -0
- package/dist/providers/catalog.js +76 -0
- package/dist/providers/claude-models.json +114 -0
- package/dist/providers/claude-provider.d.ts +4 -0
- package/dist/providers/claude-provider.js +29 -0
- package/dist/providers/claude.d.ts +15 -0
- package/dist/providers/claude.js +105 -0
- package/dist/providers/codex-models.json +135 -0
- package/dist/providers/codex-provider.d.ts +4 -0
- package/dist/providers/codex-provider.js +27 -0
- package/dist/providers/codex-rules.d.ts +9 -0
- package/dist/providers/codex-rules.js +35 -0
- package/dist/providers/codex.d.ts +14 -0
- package/dist/providers/codex.js +52 -0
- package/dist/providers/detect.d.ts +6 -0
- package/dist/providers/detect.js +30 -0
- package/dist/providers/provider.d.ts +25 -0
- package/dist/providers/provider.js +1 -0
- package/dist/providers/registry.d.ts +28 -0
- package/dist/providers/registry.js +118 -0
- package/dist/record-directory.d.ts +27 -0
- package/dist/record-directory.js +114 -0
- package/dist/run-process.d.ts +13 -0
- package/dist/run-process.js +42 -0
- package/dist/serializer.d.ts +9 -0
- package/dist/serializer.js +34 -0
- package/dist/skills.d.ts +21 -0
- package/dist/skills.js +174 -0
- package/dist/tasks/background-limit.d.ts +16 -0
- package/dist/tasks/background-limit.js +55 -0
- package/dist/tasks/end-children.d.ts +34 -0
- package/dist/tasks/end-children.js +53 -0
- package/dist/tasks/give-task.d.ts +14 -0
- package/dist/tasks/give-task.js +33 -0
- package/dist/tasks/task-coordinator.d.ts +52 -0
- package/dist/tasks/task-coordinator.js +323 -0
- package/dist/tasks/task-store.d.ts +49 -0
- package/dist/tasks/task-store.js +197 -0
- package/dist/tasks/task-work.d.ts +47 -0
- package/dist/tasks/task-work.js +28 -0
- package/dist/tasks/waiting-child.d.ts +51 -0
- package/dist/tasks/waiting-child.js +143 -0
- package/dist/tasks/wake-parent.d.ts +19 -0
- package/dist/tasks/wake-parent.js +109 -0
- package/dist/tasks/wiring.d.ts +51 -0
- package/dist/tasks/wiring.js +151 -0
- package/dist/title-file.d.ts +2 -0
- package/dist/title-file.js +55 -0
- package/dist/usage/accounts.d.ts +15 -0
- package/dist/usage/accounts.js +64 -0
- package/dist/usage/aggregate.d.ts +12 -0
- package/dist/usage/aggregate.js +154 -0
- package/dist/usage/exchange.d.ts +16 -0
- package/dist/usage/exchange.js +84 -0
- package/dist/usage/index-file.d.ts +15 -0
- package/dist/usage/index-file.js +123 -0
- package/dist/usage/limits/monitor.d.ts +50 -0
- package/dist/usage/limits/monitor.js +179 -0
- package/dist/usage/limits/normalize.d.ts +21 -0
- package/dist/usage/limits/normalize.js +160 -0
- package/dist/usage/limits/probe.d.ts +9 -0
- package/dist/usage/limits/probe.js +113 -0
- package/dist/usage/prices-snapshot.json +1071 -0
- package/dist/usage/pricing.d.ts +34 -0
- package/dist/usage/pricing.js +186 -0
- package/dist/usage/projects.d.ts +17 -0
- package/dist/usage/projects.js +49 -0
- package/dist/usage/readers/claude.d.ts +3 -0
- package/dist/usage/readers/claude.js +59 -0
- package/dist/usage/readers/codex.d.ts +23 -0
- package/dist/usage/readers/codex.js +155 -0
- package/dist/usage/record.d.ts +15 -0
- package/dist/usage/record.js +39 -0
- package/dist/usage/roots.d.ts +12 -0
- package/dist/usage/roots.js +29 -0
- package/dist/usage/scanner.d.ts +30 -0
- package/dist/usage/scanner.js +234 -0
- package/dist/usage/usage-service.d.ts +35 -0
- package/dist/usage/usage-service.js +130 -0
- package/dist/watch-seam.d.ts +29 -0
- package/dist/watch-seam.js +78 -0
- package/dist/watch-test-helpers.d.ts +28 -0
- package/dist/watch-test-helpers.js +86 -0
- package/package.json +42 -3
- package/src/async.ts +40 -0
- package/src/chat/attachment-store.ts +108 -0
- package/src/chat/backend.ts +199 -0
- package/src/chat/background-work.ts +42 -0
- package/src/chat/bookmark-store.ts +166 -0
- package/src/chat/chat-core.ts +1228 -0
- package/src/chat/chat-log.ts +187 -0
- package/src/chat/chat-process.ts +237 -0
- package/src/chat/chat-session.ts +1723 -0
- package/src/chat/chat-store.ts +261 -0
- package/src/chat/chat-title.ts +90 -0
- package/src/chat/claude-backend.ts +235 -0
- package/src/chat/claude-protocol.ts +684 -0
- package/src/chat/claude-title.ts +106 -0
- package/src/chat/claude-transcript.ts +233 -0
- package/src/chat/codex-backend.ts +397 -0
- package/src/chat/codex-protocol.ts +872 -0
- package/src/chat/codex-thread.ts +162 -0
- package/src/chat/codex-transport.ts +224 -0
- package/src/chat/composer-preferences.ts +67 -0
- package/src/chat/context-breakdown.ts +80 -0
- package/src/chat/delta-coalescer.ts +62 -0
- package/src/chat/errors.ts +25 -0
- package/src/chat/fake-claude.ts +1006 -0
- package/src/chat/fake-cli.ts +199 -0
- package/src/chat/fake-codex.ts +534 -0
- package/src/chat/fixtures/claude-2.1.285-auto-fallback.json +24 -0
- package/src/chat/fixtures/claude-2.1.285-native-children.json +6600 -0
- package/src/chat/fixtures/claude-2.1.285-resume-direct-compact.json +202 -0
- package/src/chat/fixtures/claude-2.1.285-resume-task-notification.json +57 -0
- package/src/chat/fixtures/claude-projects/-work-demo/5f1c2a9e-0b7d-4c1e-9a53-3e2f8d6b7a10/subagents/agent-a4c2e8f10b3d5a7e9.jsonl +10 -0
- package/src/chat/fixtures/claude-projects/-work-demo/5f1c2a9e-0b7d-4c1e-9a53-3e2f8d6b7a10/subagents/agent-a4c2e8f10b3d5a7e9.meta.json +1 -0
- package/src/chat/fixtures/claude-projects/-work-demo/5f1c2a9e-0b7d-4c1e-9a53-3e2f8d6b7a10/subagents/agent-a9b8c7d6e5f4a3b21.jsonl +2 -0
- package/src/chat/fixtures/claude-projects/-work-demo/5f1c2a9e-0b7d-4c1e-9a53-3e2f8d6b7a10/subagents/agent-a9b8c7d6e5f4a3b21.meta.json +1 -0
- package/src/chat/fixtures/codex-0.159.2-native-approval.json +119 -0
- package/src/chat/fixtures/codex-0.159.2-native-file-approval.json +136 -0
- package/src/chat/fixtures/codex-0.159.2-native-interacted.json +220 -0
- package/src/chat/fixtures/codex-0.159.2-usage-windows.json +74 -0
- package/src/chat/input.ts +89 -0
- package/src/chat/limit-resume.ts +74 -0
- package/src/chat/projector.ts +969 -0
- package/src/chat/request-summary.ts +168 -0
- package/src/chat/subagent-projection.ts +45 -0
- package/src/chat/subagent-reader.ts +469 -0
- package/src/chat/subagent-settlement.ts +111 -0
- package/src/chat/thread.ts +167 -0
- package/src/chat/wake-chat.ts +45 -0
- package/src/client-sinks.ts +39 -0
- package/src/coded-error.ts +18 -0
- package/src/context/argv.ts +61 -0
- package/src/context/refusal.ts +50 -0
- package/src/context/verb.ts +392 -0
- package/src/error-text.ts +28 -0
- package/src/events.ts +9 -0
- package/src/fs.ts +118 -0
- package/src/host/agent-host.ts +124 -0
- package/src/host/environment.ts +31 -0
- package/src/host/handlers.ts +142 -0
- package/src/host/memory-port.ts +27 -0
- package/src/host/wiring.ts +164 -0
- package/src/lineage.ts +159 -0
- package/src/messages/deliver-message.ts +61 -0
- package/src/messages/deliver-notice.ts +120 -0
- package/src/messages/notice-notes.ts +34 -0
- package/src/messages/notice-store.ts +142 -0
- package/src/modes.ts +38 -0
- package/src/outbox/manual-clock.ts +31 -0
- package/src/outbox/outbox-worker.ts +214 -0
- package/src/outbox/outbox.ts +106 -0
- package/src/providers/accounts/accounts.ts +192 -0
- package/src/providers/accounts/launch.ts +55 -0
- package/src/providers/accounts/service.ts +632 -0
- package/src/providers/accounts/shadow-home.ts +85 -0
- package/src/providers/accounts/status.ts +106 -0
- package/src/providers/accounts/store.ts +158 -0
- package/src/providers/accounts/test-accounts.ts +48 -0
- package/src/providers/accounts/variables.ts +132 -0
- package/src/providers/catalog.ts +90 -0
- package/src/providers/claude-models.json +114 -0
- package/src/providers/claude-provider.ts +32 -0
- package/src/providers/claude.ts +123 -0
- package/src/providers/codex-models.json +135 -0
- package/src/providers/codex-provider.ts +30 -0
- package/src/providers/codex-rules.ts +54 -0
- package/src/providers/codex.ts +69 -0
- package/src/providers/detect.ts +40 -0
- package/src/providers/provider.ts +46 -0
- package/src/providers/registry.ts +150 -0
- package/src/record-directory.ts +136 -0
- package/src/run-process.ts +61 -0
- package/src/serializer.ts +41 -0
- package/src/skills.ts +199 -0
- package/src/tasks/background-limit.ts +72 -0
- package/src/tasks/end-children.ts +100 -0
- package/src/tasks/give-task.ts +52 -0
- package/src/tasks/task-coordinator.ts +384 -0
- package/src/tasks/task-store.ts +236 -0
- package/src/tasks/task-work.ts +62 -0
- package/src/tasks/waiting-child.ts +203 -0
- package/src/tasks/wake-parent.ts +142 -0
- package/src/tasks/wiring.ts +231 -0
- package/src/title-file.ts +57 -0
- package/src/usage/accounts.ts +86 -0
- package/src/usage/aggregate.ts +220 -0
- package/src/usage/exchange.ts +93 -0
- package/src/usage/index-file.ts +178 -0
- package/src/usage/limits/monitor.ts +239 -0
- package/src/usage/limits/normalize.ts +188 -0
- package/src/usage/limits/probe.ts +120 -0
- package/src/usage/prices-snapshot.json +1071 -0
- package/src/usage/pricing.ts +236 -0
- package/src/usage/projects.ts +65 -0
- package/src/usage/readers/claude.ts +60 -0
- package/src/usage/readers/codex.ts +196 -0
- package/src/usage/record.ts +60 -0
- package/src/usage/roots.ts +39 -0
- package/src/usage/scanner.ts +265 -0
- package/src/usage/usage-service.ts +161 -0
- package/src/watch-seam.ts +111 -0
- package/src/watch-test-helpers.ts +102 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// Base arguments for a chat process; the session adds what the selection and the modes ask for.
|
|
2
|
+
const CLAUDE_CHAT_ARGS = [
|
|
3
|
+
'-p',
|
|
4
|
+
'--output-format',
|
|
5
|
+
'stream-json',
|
|
6
|
+
'--input-format',
|
|
7
|
+
'stream-json',
|
|
8
|
+
'--verbose',
|
|
9
|
+
'--include-partial-messages',
|
|
10
|
+
'--replay-user-messages',
|
|
11
|
+
'--permission-prompt-tool',
|
|
12
|
+
'stdio'
|
|
13
|
+
];
|
|
14
|
+
// Effort values the CLI takes on its flag; anything else is asked for in the prompt instead.
|
|
15
|
+
const FLAG_EFFORTS = new Set(['low', 'medium', 'high', 'xhigh', 'max']);
|
|
16
|
+
const PERMISSION_MODE = {
|
|
17
|
+
supervised: null,
|
|
18
|
+
'auto-accept-edits': 'acceptEdits',
|
|
19
|
+
auto: 'auto',
|
|
20
|
+
'full-access': 'bypassPermissions'
|
|
21
|
+
};
|
|
22
|
+
export function claudeRuntimeMode(mode) {
|
|
23
|
+
if (mode === 'default') {
|
|
24
|
+
return 'supervised';
|
|
25
|
+
}
|
|
26
|
+
return Object.keys(PERMISSION_MODE).find((key) => PERMISSION_MODE[key] === mode);
|
|
27
|
+
}
|
|
28
|
+
/* The argument list for one Claude Code chat process. */
|
|
29
|
+
export function claudeArgs(launch) {
|
|
30
|
+
// The `=` form matters, since the flag is variadic and would swallow a prompt argument after it (measured on Claude Code 2.1.274).
|
|
31
|
+
const args = [
|
|
32
|
+
...CLAUDE_CHAT_ARGS,
|
|
33
|
+
...(launch.allowedTools ?? []).map((tool) => `--allowedTools=${tool}`),
|
|
34
|
+
...(launch.folders ?? []).map((folder) => `--add-dir=${folder}`)
|
|
35
|
+
];
|
|
36
|
+
const contextWindow = launch.selection.options.contextWindow;
|
|
37
|
+
args.push('--model', `${launch.selection.model}${contextWindow === '1m' ? '[1m]' : ''}`);
|
|
38
|
+
const effort = launch.selection.options.effort;
|
|
39
|
+
if (typeof effort === 'string' && FLAG_EFFORTS.has(effort)) {
|
|
40
|
+
args.push('--effort', effort);
|
|
41
|
+
}
|
|
42
|
+
/*
|
|
43
|
+
* Fast mode has no flag of its own; the CLI reads it from the settings blob, which is also the
|
|
44
|
+
* opt-in the init frame asks for (without it the frame answers `sdk_opt_in_required`). It only
|
|
45
|
+
* takes on a model that offers it, so the catalog puts the option on those models alone.
|
|
46
|
+
* A 200k pick turns auto-compact on over the person's own setting, since `claudeEnv` only moves
|
|
47
|
+
* where it compacts and a CLI under `-p` never stops at a window (measured on Claude Code 2.1.283).
|
|
48
|
+
*/
|
|
49
|
+
const settings = {
|
|
50
|
+
...(launch.selection.options.fastMode === true ? { fastMode: true } : {}),
|
|
51
|
+
...(launch.selection.options.contextWindow === '200k' ? { autoCompactEnabled: true } : {})
|
|
52
|
+
};
|
|
53
|
+
if (Object.keys(settings).length > 0) {
|
|
54
|
+
args.push('--settings', JSON.stringify(settings));
|
|
55
|
+
}
|
|
56
|
+
const permissionMode = PERMISSION_MODE[launch.runtimeMode];
|
|
57
|
+
if (permissionMode) {
|
|
58
|
+
args.push('--permission-mode', permissionMode);
|
|
59
|
+
}
|
|
60
|
+
if (permissionMode === 'bypassPermissions') {
|
|
61
|
+
args.push('--allow-dangerously-skip-permissions');
|
|
62
|
+
}
|
|
63
|
+
if (launch.resume) {
|
|
64
|
+
args.push('--resume', launch.resume);
|
|
65
|
+
}
|
|
66
|
+
return args;
|
|
67
|
+
}
|
|
68
|
+
/*
|
|
69
|
+
* Leaving out `[1m]` does not cap a model the CLI runs natively on 1M on a subscription (Fable,
|
|
70
|
+
* Opus 5.5, Sonnet 5), and `autoCompactWindow` in `--settings` is ignored under `-p`: only this
|
|
71
|
+
* variable holds a 200k pick (measured on Claude Code 2.1.280). It holds it only with auto-compact
|
|
72
|
+
* on, which `claudeArgs` sees to.
|
|
73
|
+
*/
|
|
74
|
+
export function claudeEnv(selection) {
|
|
75
|
+
return selection.options.contextWindow === '200k' ? { CLAUDE_CODE_AUTO_COMPACT_WINDOW: '200000' } : {};
|
|
76
|
+
}
|
|
77
|
+
// What the CLI can do, as far as a client has to know.
|
|
78
|
+
export const CLAUDE_CAPABILITIES = {
|
|
79
|
+
chat: true,
|
|
80
|
+
terminal: true,
|
|
81
|
+
hooks: true,
|
|
82
|
+
streamsToolOutput: false,
|
|
83
|
+
diffs: 'before-after',
|
|
84
|
+
attachments: true,
|
|
85
|
+
mentions: true,
|
|
86
|
+
denyReason: true,
|
|
87
|
+
allowAlways: true,
|
|
88
|
+
asyncQuestions: false,
|
|
89
|
+
compaction: 'prompt',
|
|
90
|
+
reportsCost: true,
|
|
91
|
+
/*
|
|
92
|
+
* The CLI's `modelUsage.contextWindow` is the model's maximum, not the window a 200k pick compacts at:
|
|
93
|
+
* a run started without `[1m]` reports 1000000 too (measured on Claude Code 2.1.274). The catalog
|
|
94
|
+
* knows what the pick asked for, so the meter reads that and nothing here reports a window.
|
|
95
|
+
*/
|
|
96
|
+
reportsContextWindow: false,
|
|
97
|
+
reportsThinking: true,
|
|
98
|
+
slashCommands: true
|
|
99
|
+
};
|
|
100
|
+
// Claude Code takes its flags before `--resume`, which takes the id.
|
|
101
|
+
export const CLAUDE_RESUME_COMMAND = 'claude {flags} --resume {id}';
|
|
102
|
+
/* Words the model reads as instructions, prepended to the prompt for options the CLI has no flag for. */
|
|
103
|
+
export function promptPrefix(selection) {
|
|
104
|
+
return selection.options.effort === 'ultrathink' ? 'ultrathink\n\n' : '';
|
|
105
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
{
|
|
2
|
+
"updatedAt": "2026-09-29T17:26:43Z",
|
|
3
|
+
"defaultModel": "gpt-6-astra",
|
|
4
|
+
"profiles": {
|
|
5
|
+
"ultra": {
|
|
6
|
+
"options": [
|
|
7
|
+
{
|
|
8
|
+
"id": "effort",
|
|
9
|
+
"label": "Reasoning",
|
|
10
|
+
"type": "select",
|
|
11
|
+
"defaultChoice": "medium",
|
|
12
|
+
"choices": [
|
|
13
|
+
{ "id": "low", "label": "Low", "description": "Fast responses with lighter reasoning" },
|
|
14
|
+
{ "id": "medium", "label": "Medium", "description": "Balances speed and reasoning depth for everyday tasks" },
|
|
15
|
+
{ "id": "high", "label": "High", "description": "Greater reasoning depth for complex problems" },
|
|
16
|
+
{ "id": "xhigh", "label": "Extra high", "description": "Extra high reasoning depth for complex problems" },
|
|
17
|
+
{ "id": "max", "label": "Max", "description": "Maximum reasoning depth for the hardest problems" },
|
|
18
|
+
{ "id": "ultra", "label": "Ultra", "description": "Maximum reasoning with automatic task delegation" }
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "serviceTier",
|
|
23
|
+
"label": "Priority",
|
|
24
|
+
"type": "boolean",
|
|
25
|
+
"defaultValue": false,
|
|
26
|
+
"description": "Faster answers on the priority tier, at a higher usage cost"
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"contextWindowTokens": { "*": 258400 }
|
|
30
|
+
},
|
|
31
|
+
"ultra-low": {
|
|
32
|
+
"options": [
|
|
33
|
+
{
|
|
34
|
+
"id": "effort",
|
|
35
|
+
"label": "Reasoning",
|
|
36
|
+
"type": "select",
|
|
37
|
+
"defaultChoice": "low",
|
|
38
|
+
"choices": [
|
|
39
|
+
{ "id": "low", "label": "Low", "description": "Fast responses with lighter reasoning" },
|
|
40
|
+
{ "id": "medium", "label": "Medium", "description": "Balances speed and reasoning depth for everyday tasks" },
|
|
41
|
+
{ "id": "high", "label": "High", "description": "Greater reasoning depth for complex problems" },
|
|
42
|
+
{ "id": "xhigh", "label": "Extra high", "description": "Extra high reasoning depth for complex problems" },
|
|
43
|
+
{ "id": "max", "label": "Max", "description": "Maximum reasoning depth for the hardest problems" },
|
|
44
|
+
{ "id": "ultra", "label": "Ultra", "description": "Maximum reasoning with automatic task delegation" }
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"id": "serviceTier",
|
|
49
|
+
"label": "Priority",
|
|
50
|
+
"type": "boolean",
|
|
51
|
+
"defaultValue": false,
|
|
52
|
+
"description": "Faster answers on the priority tier, at a higher usage cost"
|
|
53
|
+
}
|
|
54
|
+
],
|
|
55
|
+
"contextWindowTokens": { "*": 258400 }
|
|
56
|
+
},
|
|
57
|
+
"max": {
|
|
58
|
+
"options": [
|
|
59
|
+
{
|
|
60
|
+
"id": "effort",
|
|
61
|
+
"label": "Reasoning",
|
|
62
|
+
"type": "select",
|
|
63
|
+
"defaultChoice": "medium",
|
|
64
|
+
"choices": [
|
|
65
|
+
{ "id": "low", "label": "Low", "description": "Fast responses with lighter reasoning" },
|
|
66
|
+
{ "id": "medium", "label": "Medium", "description": "Balances speed and reasoning depth for everyday tasks" },
|
|
67
|
+
{ "id": "high", "label": "High", "description": "Greater reasoning depth for complex problems" },
|
|
68
|
+
{ "id": "xhigh", "label": "Extra high", "description": "Extra high reasoning depth for complex problems" },
|
|
69
|
+
{ "id": "max", "label": "Max", "description": "Maximum reasoning depth for the hardest problems" }
|
|
70
|
+
]
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"id": "serviceTier",
|
|
74
|
+
"label": "Priority",
|
|
75
|
+
"type": "boolean",
|
|
76
|
+
"defaultValue": false,
|
|
77
|
+
"description": "Faster answers on the priority tier, at a higher usage cost"
|
|
78
|
+
}
|
|
79
|
+
],
|
|
80
|
+
"contextWindowTokens": { "*": 258400 }
|
|
81
|
+
},
|
|
82
|
+
"xhigh": {
|
|
83
|
+
"options": [
|
|
84
|
+
{
|
|
85
|
+
"id": "effort",
|
|
86
|
+
"label": "Reasoning",
|
|
87
|
+
"type": "select",
|
|
88
|
+
"defaultChoice": "medium",
|
|
89
|
+
"choices": [
|
|
90
|
+
{ "id": "low", "label": "Low", "description": "Fast responses with lighter reasoning" },
|
|
91
|
+
{ "id": "medium", "label": "Medium", "description": "Balances speed and reasoning depth for everyday tasks" },
|
|
92
|
+
{ "id": "high", "label": "High", "description": "Greater reasoning depth for complex problems" },
|
|
93
|
+
{ "id": "xhigh", "label": "Extra high", "description": "Extra high reasoning depth for complex problems" }
|
|
94
|
+
]
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"id": "serviceTier",
|
|
98
|
+
"label": "Priority",
|
|
99
|
+
"type": "boolean",
|
|
100
|
+
"defaultValue": false,
|
|
101
|
+
"description": "Faster answers on the priority tier, at a higher usage cost"
|
|
102
|
+
}
|
|
103
|
+
],
|
|
104
|
+
"contextWindowTokens": { "*": 258400 }
|
|
105
|
+
},
|
|
106
|
+
"spark": {
|
|
107
|
+
"options": [
|
|
108
|
+
{
|
|
109
|
+
"id": "effort",
|
|
110
|
+
"label": "Reasoning",
|
|
111
|
+
"type": "select",
|
|
112
|
+
"defaultChoice": "high",
|
|
113
|
+
"choices": [
|
|
114
|
+
{ "id": "low", "label": "Low", "description": "Fast responses with lighter reasoning" },
|
|
115
|
+
{ "id": "medium", "label": "Medium", "description": "Balances speed and reasoning depth for everyday tasks" },
|
|
116
|
+
{ "id": "high", "label": "High", "description": "Greater reasoning depth for complex problems" },
|
|
117
|
+
{ "id": "xhigh", "label": "Extra high", "description": "Extra high reasoning depth for complex problems" }
|
|
118
|
+
]
|
|
119
|
+
}
|
|
120
|
+
],
|
|
121
|
+
"contextWindowTokens": { "*": 121600 }
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
"models": [
|
|
125
|
+
{ "slug": "gpt-6-astra", "name": "GPT-6 Astra", "profile": "ultra", "aliases": ["astra", "gpt-6"] },
|
|
126
|
+
{ "slug": "gpt-6.1-sol", "name": "GPT-6.1 Sol", "badge": "new", "profile": "max", "aliases": ["sol"] },
|
|
127
|
+
{ "slug": "gpt-6-sol", "name": "GPT-6 Sol", "profile": "max" },
|
|
128
|
+
{ "slug": "gpt-6-luna", "name": "GPT-6 Luna", "badge": "new", "profile": "max", "aliases": ["luna"] },
|
|
129
|
+
{ "slug": "gpt-5.6-sol", "name": "GPT-5.6 Sol", "profile": "ultra-low", "legacy": true },
|
|
130
|
+
{ "slug": "gpt-5.6-terra", "name": "GPT-5.6 Terra", "profile": "ultra", "aliases": ["terra"], "badge": "retiring", "legacy": true },
|
|
131
|
+
{ "slug": "gpt-5.6-luna", "name": "GPT-5.6 Luna", "profile": "max", "legacy": true },
|
|
132
|
+
{ "slug": "gpt-5.5", "name": "GPT-5.5", "profile": "xhigh", "legacy": true },
|
|
133
|
+
{ "slug": "gpt-5.3-codex-spark", "name": "GPT-5.3 Codex Spark", "profile": "spark", "aliases": ["spark"], "legacy": true }
|
|
134
|
+
]
|
|
135
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { CodexBackend } from '../chat/codex-backend.js';
|
|
2
|
+
import { ModelCatalog } from './catalog.js';
|
|
3
|
+
import { CODEX_CAPABILITIES, CODEX_CHAT_ARGS, CODEX_RESUME_COMMAND } from './codex.js';
|
|
4
|
+
import codexManifest from './codex-models.json' with { type: 'json' };
|
|
5
|
+
import { detectCli } from './detect.js';
|
|
6
|
+
export function createCodexProvider(options = {}) {
|
|
7
|
+
return {
|
|
8
|
+
kind: 'codex',
|
|
9
|
+
name: 'Codex',
|
|
10
|
+
catalog: new ModelCatalog(codexManifest),
|
|
11
|
+
capabilities: CODEX_CAPABILITIES,
|
|
12
|
+
command: ['codex', ...CODEX_CHAT_ARGS],
|
|
13
|
+
resumeCommand: CODEX_RESUME_COMMAND,
|
|
14
|
+
// The auth variables Codex 0.157 names in its own "no Codex credentials were found" advice.
|
|
15
|
+
home: { env: 'CODEX_HOME', fallback: '.codex', loginEnv: ['OPENAI_API_KEY', 'CODEX_API_KEY', 'CODEX_ACCESS_TOKEN'], loginCommand: 'codex login' },
|
|
16
|
+
detect: detectCli,
|
|
17
|
+
// Read-only and without an approval to wait for: the run only has to read what it is handed. A chat's
|
|
18
|
+
// title is asked in a folder that need not be a repository, and ephemeral keeps the run out of Codex's thread list.
|
|
19
|
+
oneShotArgs: (prompt) => ['exec', '--color', 'never', '--sandbox', 'read-only', '--skip-git-repo-check', '--ephemeral', prompt],
|
|
20
|
+
// A prompt of `-` is read from stdin.
|
|
21
|
+
oneShotStdinArgs: ['exec', '--color', 'never', '--sandbox', 'read-only', '--skip-git-repo-check', '--ephemeral', '-'],
|
|
22
|
+
// `codex [OPTIONS] [PROMPT]`: the positional starts the interactive session on that prompt.
|
|
23
|
+
firstPromptArgs: (prompt) => [prompt],
|
|
24
|
+
createBackend: (launch, host) => new CodexBackend(launch, host, options)
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export const codexProvider = createCodexProvider();
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface CodexRules {
|
|
2
|
+
app: string;
|
|
3
|
+
commands: readonly string[];
|
|
4
|
+
}
|
|
5
|
+
export type CodexRulesResult = 'unchanged' | 'written';
|
|
6
|
+
export declare function codexRulesText(rules: CodexRules): string;
|
|
7
|
+
export declare function codexRulesPathIn(folder: string, rules: CodexRules): string;
|
|
8
|
+
export declare function defaultCodexHome(env?: Record<string, string | undefined>): string;
|
|
9
|
+
export declare function installCodexRules(path: string, rules: CodexRules): Promise<CodexRulesResult>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { mkdir, readFile } from 'node:fs/promises';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { errorText } from '../error-text.js';
|
|
5
|
+
import { isNotFound, writeAtomic } from '../fs.js';
|
|
6
|
+
export function codexRulesText(rules) {
|
|
7
|
+
return ([
|
|
8
|
+
`# Written by ${rules.app}; it is rewritten when it changes.`,
|
|
9
|
+
...rules.commands.map((command) => `prefix_rule(pattern=[${JSON.stringify(command)}], decision="allow")`)
|
|
10
|
+
].join('\n') + '\n');
|
|
11
|
+
}
|
|
12
|
+
// Codex loads every `*.rules` file in the `rules` folder of its home, and only from there, never from a flag.
|
|
13
|
+
export function codexRulesPathIn(folder, rules) {
|
|
14
|
+
return join(folder, 'rules', `${rules.app.toLowerCase().replace(/[^a-z0-9]+/g, '-')}.rules`);
|
|
15
|
+
}
|
|
16
|
+
export function defaultCodexHome(env = process.env) {
|
|
17
|
+
return env.CODEX_HOME ?? join(env.HOME ?? homedir(), '.codex');
|
|
18
|
+
}
|
|
19
|
+
/* Idempotent: a file that already says the same is left alone. */
|
|
20
|
+
export async function installCodexRules(path, rules) {
|
|
21
|
+
const text = codexRulesText(rules);
|
|
22
|
+
try {
|
|
23
|
+
if ((await readFile(path, 'utf8')) === text) {
|
|
24
|
+
return 'unchanged';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
if (!isNotFound(e)) {
|
|
29
|
+
throw new Error(`Cannot read ${path}: ${errorText(e)}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
await mkdir(dirname(path), { recursive: true });
|
|
33
|
+
await writeAtomic(path, text, 0o644);
|
|
34
|
+
return 'written';
|
|
35
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ModelSelection, ProviderCapabilities, RuntimeMode } from '@adecore/agent-contracts';
|
|
2
|
+
export declare const CODEX_CHAT_ARGS: string[];
|
|
3
|
+
type CodexApprovalPolicy = 'untrusted' | 'on-request' | 'never';
|
|
4
|
+
type CodexSandboxMode = 'read-only' | 'workspace-write' | 'danger-full-access';
|
|
5
|
+
interface CodexThreadOptions {
|
|
6
|
+
approvalPolicy: CodexApprovalPolicy;
|
|
7
|
+
sandbox: CodexSandboxMode;
|
|
8
|
+
}
|
|
9
|
+
export declare function codexThreadOptions(runtimeMode: RuntimeMode): CodexThreadOptions;
|
|
10
|
+
export declare function codexRuntimeMode(approvalPolicy: string, sandbox: string): RuntimeMode | undefined;
|
|
11
|
+
export declare function codexServiceTier(selection: ModelSelection): string | null;
|
|
12
|
+
export declare const CODEX_CAPABILITIES: ProviderCapabilities;
|
|
13
|
+
export declare const CODEX_RESUME_COMMAND = "codex resume {flags} {id}";
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// The app-server speaks JSON-RPC on stdio; the session adds nothing to the command line.
|
|
2
|
+
export const CODEX_CHAT_ARGS = ['app-server'];
|
|
3
|
+
/*
|
|
4
|
+
* Codex has two knobs, when it asks and where it may write, and no "ask for commands but not for
|
|
5
|
+
* edits" policy. `untrusted` inside a writable workspace comes closest: edits within the workspace
|
|
6
|
+
* pass the sandbox without a prompt, commands still ask unless Codex knows them as safe.
|
|
7
|
+
* `on-request` with the same sandbox is Codex's own default and stands in for `auto`.
|
|
8
|
+
*/
|
|
9
|
+
const THREAD_OPTIONS = {
|
|
10
|
+
supervised: { approvalPolicy: 'untrusted', sandbox: 'read-only' },
|
|
11
|
+
'auto-accept-edits': { approvalPolicy: 'untrusted', sandbox: 'workspace-write' },
|
|
12
|
+
auto: { approvalPolicy: 'on-request', sandbox: 'workspace-write' },
|
|
13
|
+
'full-access': { approvalPolicy: 'never', sandbox: 'danger-full-access' }
|
|
14
|
+
};
|
|
15
|
+
export function codexThreadOptions(runtimeMode) {
|
|
16
|
+
return THREAD_OPTIONS[runtimeMode];
|
|
17
|
+
}
|
|
18
|
+
export function codexRuntimeMode(approvalPolicy, sandbox) {
|
|
19
|
+
const names = { readOnly: 'read-only', workspaceWrite: 'workspace-write', dangerFullAccess: 'danger-full-access' };
|
|
20
|
+
return Object.keys(THREAD_OPTIONS).find((mode) => {
|
|
21
|
+
const options = THREAD_OPTIONS[mode];
|
|
22
|
+
return options.approvalPolicy === approvalPolicy && options.sandbox === (names[sandbox] ?? sandbox);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
// What the app-server calls the faster of the two tiers it lists per model; the standard tier is no id at all.
|
|
26
|
+
const CODEX_PRIORITY_TIER = 'priority';
|
|
27
|
+
/* The service tier a thread or a turn runs on, or null for the standard one the account defaults to. */
|
|
28
|
+
export function codexServiceTier(selection) {
|
|
29
|
+
return selection.options.serviceTier === true ? CODEX_PRIORITY_TIER : null;
|
|
30
|
+
}
|
|
31
|
+
// What the app-server can do, as far as a client has to know.
|
|
32
|
+
export const CODEX_CAPABILITIES = {
|
|
33
|
+
chat: true,
|
|
34
|
+
terminal: true,
|
|
35
|
+
hooks: true,
|
|
36
|
+
streamsToolOutput: true,
|
|
37
|
+
diffs: 'unified',
|
|
38
|
+
attachments: true,
|
|
39
|
+
// Codex has no mention part in its protocol; the picker sends the path as text, which is all
|
|
40
|
+
// the model needs to open the file with its own tools.
|
|
41
|
+
mentions: true,
|
|
42
|
+
denyReason: false,
|
|
43
|
+
allowAlways: true,
|
|
44
|
+
asyncQuestions: true,
|
|
45
|
+
compaction: 'native',
|
|
46
|
+
reportsCost: false,
|
|
47
|
+
reportsContextWindow: true,
|
|
48
|
+
reportsThinking: true,
|
|
49
|
+
slashCommands: false
|
|
50
|
+
};
|
|
51
|
+
// `codex resume` is a subcommand that reads `[OPTIONS] [SESSION_ID]`, so the flags go after it.
|
|
52
|
+
export const CODEX_RESUME_COMMAND = 'codex resume {flags} {id}';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type SpawnChatProcess } from '../chat/chat-process.ts';
|
|
2
|
+
export interface CliDetection {
|
|
3
|
+
installed: boolean;
|
|
4
|
+
version: string | null;
|
|
5
|
+
}
|
|
6
|
+
export declare function detectCli(command: string, env?: Record<string, string | undefined>, spawn?: SpawnChatProcess): Promise<CliDetection>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { spawnChatProcess } from '../chat/chat-process.js';
|
|
2
|
+
function definedOnly(env) {
|
|
3
|
+
const defined = {};
|
|
4
|
+
for (const [key, value] of Object.entries(env)) {
|
|
5
|
+
if (value !== undefined) {
|
|
6
|
+
defined[key] = value;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
return defined;
|
|
10
|
+
}
|
|
11
|
+
/* Asks a CLI for its version; a missing binary is a plain "not installed", never an error. */
|
|
12
|
+
export async function detectCli(command, env = process.env, spawn = spawnChatProcess) {
|
|
13
|
+
try {
|
|
14
|
+
let exited = () => undefined;
|
|
15
|
+
const code = new Promise((resolve) => {
|
|
16
|
+
exited = resolve;
|
|
17
|
+
});
|
|
18
|
+
const proc = spawn({ command: [command, '--version'], cwd: process.cwd(), env: definedOnly(env), onExit: (exitCode) => exited(exitCode) });
|
|
19
|
+
proc.stdin.end();
|
|
20
|
+
const output = await new Response(proc.stdout).text();
|
|
21
|
+
if ((await code) !== 0) {
|
|
22
|
+
return { installed: false, version: null };
|
|
23
|
+
}
|
|
24
|
+
const version = /\d+\.\d+\.\d+/.exec(output)?.[0] ?? output.trim() ?? null;
|
|
25
|
+
return { installed: true, version };
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return { installed: false, version: null };
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { AgentKind, ProviderCapabilities } from '@adecore/agent-contracts';
|
|
2
|
+
import type { BackendHost, BackendLaunch, ChatBackend } from '../chat/backend.ts';
|
|
3
|
+
import type { ModelCatalog } from './catalog.ts';
|
|
4
|
+
import type { CliDetection } from './detect.ts';
|
|
5
|
+
export interface ProviderHome {
|
|
6
|
+
readonly env: string;
|
|
7
|
+
readonly fallback: string;
|
|
8
|
+
readonly loginEnv: readonly string[];
|
|
9
|
+
readonly loginCommand: string;
|
|
10
|
+
}
|
|
11
|
+
export interface ChatProvider {
|
|
12
|
+
readonly kind: AgentKind;
|
|
13
|
+
readonly name: string;
|
|
14
|
+
readonly catalog: ModelCatalog;
|
|
15
|
+
readonly capabilities: ProviderCapabilities;
|
|
16
|
+
readonly command: string[];
|
|
17
|
+
readonly resumeCommand: string;
|
|
18
|
+
readonly home?: ProviderHome;
|
|
19
|
+
oneShotArgs?(prompt: string): string[];
|
|
20
|
+
readonly oneShotStdinArgs?: readonly string[];
|
|
21
|
+
firstPromptArgs(prompt: string): string[];
|
|
22
|
+
detect(command: string, env: Record<string, string | undefined>): Promise<CliDetection>;
|
|
23
|
+
enabled?(): boolean;
|
|
24
|
+
createBackend(launch: BackendLaunch, host: BackendHost): ChatBackend;
|
|
25
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { AgentKind, ProviderInfo } from '@adecore/agent-contracts';
|
|
2
|
+
import { ModelCatalog } from './catalog.ts';
|
|
3
|
+
import type { CliDetection } from './detect.ts';
|
|
4
|
+
import type { ChatProvider } from './provider.ts';
|
|
5
|
+
export declare function unofferedProvider(kind: AgentKind): ChatProvider;
|
|
6
|
+
export declare function providerFor(kind: AgentKind): ChatProvider;
|
|
7
|
+
export interface ProviderRegistryOptions {
|
|
8
|
+
providers?: ChatProvider[];
|
|
9
|
+
commands?: Partial<Record<AgentKind, string>>;
|
|
10
|
+
detect?: (command: string) => Promise<CliDetection>;
|
|
11
|
+
env?: Record<string, string | undefined>;
|
|
12
|
+
}
|
|
13
|
+
export declare class ProviderRegistry {
|
|
14
|
+
private readonly providers;
|
|
15
|
+
private readonly commands;
|
|
16
|
+
private readonly detect;
|
|
17
|
+
private readonly env;
|
|
18
|
+
private readonly cache;
|
|
19
|
+
constructor(options?: ProviderRegistryOptions);
|
|
20
|
+
list(): Promise<ProviderInfo[]>;
|
|
21
|
+
get(kind: AgentKind): ChatProvider;
|
|
22
|
+
oneShotProvider(preferred?: AgentKind): Promise<ChatProvider | null>;
|
|
23
|
+
catalogFor(kind: AgentKind): ModelCatalog;
|
|
24
|
+
enabled(kind: AgentKind): boolean;
|
|
25
|
+
invalidate(kind: AgentKind): void;
|
|
26
|
+
protected fallback(kind: AgentKind): ChatProvider;
|
|
27
|
+
private detection;
|
|
28
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { ModelCatalog } from './catalog.js';
|
|
2
|
+
import { claudeProvider } from './claude-provider.js';
|
|
3
|
+
import { codexProvider } from './codex-provider.js';
|
|
4
|
+
// How long a "is it installed" answer stays good; an install mid-session shows up on the next check.
|
|
5
|
+
const DETECTION_TTL_MS = 60_000;
|
|
6
|
+
const DISABLED = { installed: false, version: 'Disabled in Settings' };
|
|
7
|
+
const NO_CAPABILITIES = {
|
|
8
|
+
chat: false,
|
|
9
|
+
terminal: false,
|
|
10
|
+
hooks: false,
|
|
11
|
+
streamsToolOutput: false,
|
|
12
|
+
diffs: 'none',
|
|
13
|
+
attachments: false,
|
|
14
|
+
mentions: false,
|
|
15
|
+
denyReason: false,
|
|
16
|
+
allowAlways: false,
|
|
17
|
+
asyncQuestions: false,
|
|
18
|
+
compaction: 'none',
|
|
19
|
+
reportsCost: false,
|
|
20
|
+
reportsContextWindow: false,
|
|
21
|
+
reportsThinking: false,
|
|
22
|
+
slashCommands: false
|
|
23
|
+
};
|
|
24
|
+
/* A CLI of a kind the host does not offer: a record or an account may still name one, and it starts nothing. */
|
|
25
|
+
export function unofferedProvider(kind) {
|
|
26
|
+
return {
|
|
27
|
+
kind,
|
|
28
|
+
name: kind,
|
|
29
|
+
catalog: new ModelCatalog({ defaultModel: '', profiles: {}, models: [] }),
|
|
30
|
+
capabilities: NO_CAPABILITIES,
|
|
31
|
+
command: [kind],
|
|
32
|
+
resumeCommand: '',
|
|
33
|
+
detect: () => Promise.resolve({ installed: false, version: null }),
|
|
34
|
+
firstPromptArgs: () => {
|
|
35
|
+
throw new Error(`${kind} is not offered here`);
|
|
36
|
+
},
|
|
37
|
+
createBackend: () => {
|
|
38
|
+
throw new Error(`${kind} is not offered here`);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const BUILT_IN_PROVIDERS = [claudeProvider, codexProvider];
|
|
43
|
+
/* The provider of a kind, for the places that have no registry at hand. */
|
|
44
|
+
export function providerFor(kind) {
|
|
45
|
+
return BUILT_IN_PROVIDERS.find((provider) => provider.kind === kind) ?? unofferedProvider(kind);
|
|
46
|
+
}
|
|
47
|
+
/* What a host knows about each agent CLI: whether it is there, what it offers and what it can do. */
|
|
48
|
+
export class ProviderRegistry {
|
|
49
|
+
providers;
|
|
50
|
+
commands;
|
|
51
|
+
detect;
|
|
52
|
+
env;
|
|
53
|
+
cache = new Map();
|
|
54
|
+
constructor(options = {}) {
|
|
55
|
+
this.providers = options.providers ?? [...BUILT_IN_PROVIDERS];
|
|
56
|
+
this.commands = options.commands ?? {};
|
|
57
|
+
this.detect = options.detect ?? null;
|
|
58
|
+
this.env = options.env ?? process.env;
|
|
59
|
+
}
|
|
60
|
+
async list() {
|
|
61
|
+
return await Promise.all(this.providers.map(async (provider) => ({
|
|
62
|
+
kind: provider.kind,
|
|
63
|
+
name: provider.name,
|
|
64
|
+
...(await this.detection(provider)),
|
|
65
|
+
models: provider.catalog.list(),
|
|
66
|
+
defaultModel: provider.catalog.defaultModel || null,
|
|
67
|
+
capabilities: provider.capabilities,
|
|
68
|
+
resumeCommand: provider.resumeCommand
|
|
69
|
+
})));
|
|
70
|
+
}
|
|
71
|
+
/* The provider of a kind, one this host does not offer included. */
|
|
72
|
+
get(kind) {
|
|
73
|
+
return this.providers.find((provider) => provider.kind === kind) ?? this.fallback(kind);
|
|
74
|
+
}
|
|
75
|
+
/*
|
|
76
|
+
* The CLI that answers a single prompt here: the one asked for when it is installed, else the
|
|
77
|
+
* first installed provider that can, in the order the catalog lists them. Null on a machine
|
|
78
|
+
* with none, which is what hides the button that would ask.
|
|
79
|
+
*/
|
|
80
|
+
async oneShotProvider(preferred) {
|
|
81
|
+
const order = preferred ? [this.get(preferred), ...this.providers] : this.providers;
|
|
82
|
+
for (const provider of order) {
|
|
83
|
+
if (provider.oneShotArgs && (await this.detection(provider)).installed) {
|
|
84
|
+
return provider;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
catalogFor(kind) {
|
|
90
|
+
return this.get(kind).catalog;
|
|
91
|
+
}
|
|
92
|
+
enabled(kind) {
|
|
93
|
+
return this.get(kind).enabled?.() !== false;
|
|
94
|
+
}
|
|
95
|
+
invalidate(kind) {
|
|
96
|
+
this.cache.delete(kind);
|
|
97
|
+
}
|
|
98
|
+
fallback(kind) {
|
|
99
|
+
return unofferedProvider(kind);
|
|
100
|
+
}
|
|
101
|
+
async detection(provider) {
|
|
102
|
+
if (provider.enabled?.() === false) {
|
|
103
|
+
return DISABLED;
|
|
104
|
+
}
|
|
105
|
+
const cached = this.cache.get(provider.kind);
|
|
106
|
+
if (cached && Date.now() - cached.at < DETECTION_TTL_MS) {
|
|
107
|
+
return cached.detection;
|
|
108
|
+
}
|
|
109
|
+
const command = this.commands[provider.kind] ?? provider.command[0];
|
|
110
|
+
const detection = this.detect ? await this.detect(command) : await provider.detect(command, this.env);
|
|
111
|
+
// Turned off while the probe ran.
|
|
112
|
+
if (provider.enabled?.() === false) {
|
|
113
|
+
return DISABLED;
|
|
114
|
+
}
|
|
115
|
+
this.cache.set(provider.kind, { at: Date.now(), detection });
|
|
116
|
+
return detection;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { z } from 'zod';
|
|
2
|
+
export declare function recordFileName(id: string): string;
|
|
3
|
+
export interface RecordDirectoryOptions<T> {
|
|
4
|
+
dir: string;
|
|
5
|
+
schema: z.ZodType<T>;
|
|
6
|
+
idOf(record: T): string;
|
|
7
|
+
write?: (path: string, text: string) => Promise<void>;
|
|
8
|
+
keep?(record: T): T | null;
|
|
9
|
+
}
|
|
10
|
+
export declare class RecordDirectory<T> {
|
|
11
|
+
readonly dir: string;
|
|
12
|
+
private readonly schema;
|
|
13
|
+
private readonly idOf;
|
|
14
|
+
private readonly writeFile;
|
|
15
|
+
private readonly keep;
|
|
16
|
+
private readonly records;
|
|
17
|
+
private readonly writes;
|
|
18
|
+
constructor(options: RecordDirectoryOptions<T>);
|
|
19
|
+
load(): Promise<void>;
|
|
20
|
+
get(id: string): T | undefined;
|
|
21
|
+
has(id: string): boolean;
|
|
22
|
+
all(): T[];
|
|
23
|
+
write(record: T): Promise<boolean>;
|
|
24
|
+
remove(id: string): Promise<void>;
|
|
25
|
+
prune(drop: (record: T) => boolean): Promise<void>;
|
|
26
|
+
private pathOf;
|
|
27
|
+
}
|