@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,114 @@
|
|
|
1
|
+
{
|
|
2
|
+
"updatedAt": "2026-09-28T19:00:00Z",
|
|
3
|
+
"defaultModel": "claude-sonnet-5-5",
|
|
4
|
+
"profiles": {
|
|
5
|
+
"frontier": {
|
|
6
|
+
"options": [
|
|
7
|
+
{
|
|
8
|
+
"id": "effort",
|
|
9
|
+
"label": "Reasoning",
|
|
10
|
+
"type": "select",
|
|
11
|
+
"defaultChoice": "high",
|
|
12
|
+
"choices": [
|
|
13
|
+
{ "id": "low", "label": "Low" },
|
|
14
|
+
{ "id": "medium", "label": "Medium" },
|
|
15
|
+
{ "id": "high", "label": "High" },
|
|
16
|
+
{ "id": "xhigh", "label": "Extra high" },
|
|
17
|
+
{ "id": "max", "label": "Max" },
|
|
18
|
+
{ "id": "ultrathink", "label": "Ultrathink", "description": "Asks for the longest thinking in the prompt itself" }
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "contextWindow",
|
|
23
|
+
"label": "Context window",
|
|
24
|
+
"type": "select",
|
|
25
|
+
"defaultChoice": "1m",
|
|
26
|
+
"choices": [
|
|
27
|
+
{ "id": "200k", "label": "200k" },
|
|
28
|
+
{ "id": "1m", "label": "1M" }
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
],
|
|
32
|
+
"contextWindowTokens": { "200k": 200000, "1m": 1000000 }
|
|
33
|
+
},
|
|
34
|
+
"opus": {
|
|
35
|
+
"options": [
|
|
36
|
+
{
|
|
37
|
+
"id": "effort",
|
|
38
|
+
"label": "Reasoning",
|
|
39
|
+
"type": "select",
|
|
40
|
+
"defaultChoice": "high",
|
|
41
|
+
"choices": [
|
|
42
|
+
{ "id": "low", "label": "Low" },
|
|
43
|
+
{ "id": "medium", "label": "Medium" },
|
|
44
|
+
{ "id": "high", "label": "High" },
|
|
45
|
+
{ "id": "xhigh", "label": "Extra high" },
|
|
46
|
+
{ "id": "max", "label": "Max" },
|
|
47
|
+
{ "id": "ultrathink", "label": "Ultrathink", "description": "Asks for the longest thinking in the prompt itself" }
|
|
48
|
+
]
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"id": "contextWindow",
|
|
52
|
+
"label": "Context window",
|
|
53
|
+
"type": "select",
|
|
54
|
+
"defaultChoice": "1m",
|
|
55
|
+
"choices": [
|
|
56
|
+
{ "id": "200k", "label": "200k" },
|
|
57
|
+
{ "id": "1m", "label": "1M" }
|
|
58
|
+
]
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"id": "fastMode",
|
|
62
|
+
"label": "Fast mode",
|
|
63
|
+
"type": "boolean",
|
|
64
|
+
"defaultValue": false,
|
|
65
|
+
"description": "Answers sooner and spends usage faster"
|
|
66
|
+
}
|
|
67
|
+
],
|
|
68
|
+
"contextWindowTokens": { "200k": 200000, "1m": 1000000 }
|
|
69
|
+
},
|
|
70
|
+
"sonnet": {
|
|
71
|
+
"options": [
|
|
72
|
+
{
|
|
73
|
+
"id": "effort",
|
|
74
|
+
"label": "Reasoning",
|
|
75
|
+
"type": "select",
|
|
76
|
+
"defaultChoice": "high",
|
|
77
|
+
"choices": [
|
|
78
|
+
{ "id": "low", "label": "Low" },
|
|
79
|
+
{ "id": "medium", "label": "Medium" },
|
|
80
|
+
{ "id": "high", "label": "High" },
|
|
81
|
+
{ "id": "xhigh", "label": "Extra high" },
|
|
82
|
+
{ "id": "max", "label": "Max" },
|
|
83
|
+
{ "id": "ultrathink", "label": "Ultrathink", "description": "Asks for the longest thinking in the prompt itself" }
|
|
84
|
+
]
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"id": "contextWindow",
|
|
88
|
+
"label": "Context window",
|
|
89
|
+
"type": "select",
|
|
90
|
+
"defaultChoice": "200k",
|
|
91
|
+
"choices": [
|
|
92
|
+
{ "id": "200k", "label": "200k" },
|
|
93
|
+
{ "id": "1m", "label": "1M" }
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
],
|
|
97
|
+
"contextWindowTokens": { "200k": 200000, "1m": 1000000 }
|
|
98
|
+
},
|
|
99
|
+
"haiku": {
|
|
100
|
+
"options": [{ "id": "thinking", "label": "Thinking", "type": "boolean", "defaultValue": true }],
|
|
101
|
+
"contextWindowTokens": { "*": 200000 }
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
"models": [
|
|
105
|
+
{ "slug": "claude-fable-5-1", "name": "Claude Fable 5.1", "profile": "frontier", "aliases": ["fable"] },
|
|
106
|
+
{ "slug": "claude-opus-5-5", "name": "Claude Opus 5.5", "badge": "new", "profile": "opus", "aliases": ["opus"] },
|
|
107
|
+
{ "slug": "claude-opus-5", "name": "Claude Opus 5", "profile": "opus" },
|
|
108
|
+
{ "slug": "claude-sonnet-5-5", "name": "Claude Sonnet 5.5", "badge": "new", "profile": "sonnet", "aliases": ["sonnet"] },
|
|
109
|
+
{ "slug": "claude-sonnet-5", "name": "Claude Sonnet 5", "profile": "sonnet" },
|
|
110
|
+
{ "slug": "claude-haiku-4-5", "name": "Claude Haiku 4.5", "profile": "haiku", "aliases": ["haiku"] },
|
|
111
|
+
{ "slug": "claude-opus-4-6", "name": "Claude Opus 4.6", "profile": "frontier", "legacy": true },
|
|
112
|
+
{ "slug": "claude-sonnet-4-6", "name": "Claude Sonnet 4.6", "profile": "sonnet", "legacy": true }
|
|
113
|
+
]
|
|
114
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ClaudeBackend, type ClaudeBackendOptions } from '../chat/claude-backend.ts';
|
|
2
|
+
import { ModelCatalog } from './catalog.ts';
|
|
3
|
+
import { CLAUDE_CAPABILITIES, CLAUDE_RESUME_COMMAND } from './claude.ts';
|
|
4
|
+
import { detectCli } from './detect.ts';
|
|
5
|
+
import type { ChatProvider } from './provider.ts';
|
|
6
|
+
|
|
7
|
+
export function createClaudeProvider(options: ClaudeBackendOptions = {}): ChatProvider {
|
|
8
|
+
return {
|
|
9
|
+
kind: 'claude',
|
|
10
|
+
name: 'Claude Code',
|
|
11
|
+
catalog: new ModelCatalog(),
|
|
12
|
+
capabilities: CLAUDE_CAPABILITIES,
|
|
13
|
+
command: ['claude'],
|
|
14
|
+
resumeCommand: CLAUDE_RESUME_COMMAND,
|
|
15
|
+
// Read from the strings of Claude Code 2.1.282; never HOME, which moves the keychain lookup along with it.
|
|
16
|
+
home: {
|
|
17
|
+
env: 'CLAUDE_CONFIG_DIR',
|
|
18
|
+
fallback: '.claude',
|
|
19
|
+
loginEnv: ['ANTHROPIC_API_KEY', 'ANTHROPIC_AUTH_TOKEN', 'CLAUDE_CODE_OAUTH_TOKEN'],
|
|
20
|
+
loginCommand: 'claude auth login'
|
|
21
|
+
},
|
|
22
|
+
detect: detectCli,
|
|
23
|
+
oneShotArgs: (prompt) => ['-p', prompt, '--output-format', 'text'],
|
|
24
|
+
// `-p` without a prompt argument reads the prompt from stdin.
|
|
25
|
+
oneShotStdinArgs: ['-p', '--output-format', 'text'],
|
|
26
|
+
// `claude [options] [prompt]`: the prompt is the positional, and without -p the session stays.
|
|
27
|
+
firstPromptArgs: (prompt) => [prompt],
|
|
28
|
+
createBackend: (launch, host) => new ClaudeBackend(launch, host, options)
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const claudeProvider = createClaudeProvider();
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import type { ModelSelection, ProviderCapabilities, RuntimeMode } from '@adecore/agent-contracts';
|
|
2
|
+
|
|
3
|
+
// Base arguments for a chat process; the session adds what the selection and the modes ask for.
|
|
4
|
+
const CLAUDE_CHAT_ARGS = [
|
|
5
|
+
'-p',
|
|
6
|
+
'--output-format',
|
|
7
|
+
'stream-json',
|
|
8
|
+
'--input-format',
|
|
9
|
+
'stream-json',
|
|
10
|
+
'--verbose',
|
|
11
|
+
'--include-partial-messages',
|
|
12
|
+
'--replay-user-messages',
|
|
13
|
+
'--permission-prompt-tool',
|
|
14
|
+
'stdio'
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
// Effort values the CLI takes on its flag; anything else is asked for in the prompt instead.
|
|
18
|
+
const FLAG_EFFORTS = new Set(['low', 'medium', 'high', 'xhigh', 'max']);
|
|
19
|
+
|
|
20
|
+
const PERMISSION_MODE: Record<RuntimeMode, string | null> = {
|
|
21
|
+
supervised: null,
|
|
22
|
+
'auto-accept-edits': 'acceptEdits',
|
|
23
|
+
auto: 'auto',
|
|
24
|
+
'full-access': 'bypassPermissions'
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export function claudeRuntimeMode(mode: string): RuntimeMode | undefined {
|
|
28
|
+
if (mode === 'default') {
|
|
29
|
+
return 'supervised';
|
|
30
|
+
}
|
|
31
|
+
return (Object.keys(PERMISSION_MODE) as RuntimeMode[]).find((key) => PERMISSION_MODE[key] === mode);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface ClaudeLaunch {
|
|
35
|
+
selection: ModelSelection;
|
|
36
|
+
runtimeMode: RuntimeMode;
|
|
37
|
+
resume: string | null;
|
|
38
|
+
allowedTools?: readonly string[];
|
|
39
|
+
folders?: readonly string[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* The argument list for one Claude Code chat process. */
|
|
43
|
+
export function claudeArgs(launch: ClaudeLaunch): string[] {
|
|
44
|
+
// The `=` form matters, since the flag is variadic and would swallow a prompt argument after it (measured on Claude Code 2.1.274).
|
|
45
|
+
const args = [
|
|
46
|
+
...CLAUDE_CHAT_ARGS,
|
|
47
|
+
...(launch.allowedTools ?? []).map((tool) => `--allowedTools=${tool}`),
|
|
48
|
+
...(launch.folders ?? []).map((folder) => `--add-dir=${folder}`)
|
|
49
|
+
];
|
|
50
|
+
const contextWindow = launch.selection.options.contextWindow;
|
|
51
|
+
args.push('--model', `${launch.selection.model}${contextWindow === '1m' ? '[1m]' : ''}`);
|
|
52
|
+
const effort = launch.selection.options.effort;
|
|
53
|
+
if (typeof effort === 'string' && FLAG_EFFORTS.has(effort)) {
|
|
54
|
+
args.push('--effort', effort);
|
|
55
|
+
}
|
|
56
|
+
/*
|
|
57
|
+
* Fast mode has no flag of its own; the CLI reads it from the settings blob, which is also the
|
|
58
|
+
* opt-in the init frame asks for (without it the frame answers `sdk_opt_in_required`). It only
|
|
59
|
+
* takes on a model that offers it, so the catalog puts the option on those models alone.
|
|
60
|
+
* A 200k pick turns auto-compact on over the person's own setting, since `claudeEnv` only moves
|
|
61
|
+
* where it compacts and a CLI under `-p` never stops at a window (measured on Claude Code 2.1.283).
|
|
62
|
+
*/
|
|
63
|
+
const settings = {
|
|
64
|
+
...(launch.selection.options.fastMode === true ? { fastMode: true } : {}),
|
|
65
|
+
...(launch.selection.options.contextWindow === '200k' ? { autoCompactEnabled: true } : {})
|
|
66
|
+
};
|
|
67
|
+
if (Object.keys(settings).length > 0) {
|
|
68
|
+
args.push('--settings', JSON.stringify(settings));
|
|
69
|
+
}
|
|
70
|
+
const permissionMode = PERMISSION_MODE[launch.runtimeMode];
|
|
71
|
+
if (permissionMode) {
|
|
72
|
+
args.push('--permission-mode', permissionMode);
|
|
73
|
+
}
|
|
74
|
+
if (permissionMode === 'bypassPermissions') {
|
|
75
|
+
args.push('--allow-dangerously-skip-permissions');
|
|
76
|
+
}
|
|
77
|
+
if (launch.resume) {
|
|
78
|
+
args.push('--resume', launch.resume);
|
|
79
|
+
}
|
|
80
|
+
return args;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/*
|
|
84
|
+
* Leaving out `[1m]` does not cap a model the CLI runs natively on 1M on a subscription (Fable,
|
|
85
|
+
* Opus 5.5, Sonnet 5), and `autoCompactWindow` in `--settings` is ignored under `-p`: only this
|
|
86
|
+
* variable holds a 200k pick (measured on Claude Code 2.1.280). It holds it only with auto-compact
|
|
87
|
+
* on, which `claudeArgs` sees to.
|
|
88
|
+
*/
|
|
89
|
+
export function claudeEnv(selection: ModelSelection): Record<string, string> {
|
|
90
|
+
return selection.options.contextWindow === '200k' ? { CLAUDE_CODE_AUTO_COMPACT_WINDOW: '200000' } : {};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// What the CLI can do, as far as a client has to know.
|
|
94
|
+
export const CLAUDE_CAPABILITIES: ProviderCapabilities = {
|
|
95
|
+
chat: true,
|
|
96
|
+
terminal: true,
|
|
97
|
+
hooks: true,
|
|
98
|
+
streamsToolOutput: false,
|
|
99
|
+
diffs: 'before-after',
|
|
100
|
+
attachments: true,
|
|
101
|
+
mentions: true,
|
|
102
|
+
denyReason: true,
|
|
103
|
+
allowAlways: true,
|
|
104
|
+
asyncQuestions: false,
|
|
105
|
+
compaction: 'prompt',
|
|
106
|
+
reportsCost: true,
|
|
107
|
+
/*
|
|
108
|
+
* The CLI's `modelUsage.contextWindow` is the model's maximum, not the window a 200k pick compacts at:
|
|
109
|
+
* a run started without `[1m]` reports 1000000 too (measured on Claude Code 2.1.274). The catalog
|
|
110
|
+
* knows what the pick asked for, so the meter reads that and nothing here reports a window.
|
|
111
|
+
*/
|
|
112
|
+
reportsContextWindow: false,
|
|
113
|
+
reportsThinking: true,
|
|
114
|
+
slashCommands: true
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// Claude Code takes its flags before `--resume`, which takes the id.
|
|
118
|
+
export const CLAUDE_RESUME_COMMAND = 'claude {flags} --resume {id}';
|
|
119
|
+
|
|
120
|
+
/* Words the model reads as instructions, prepended to the prompt for options the CLI has no flag for. */
|
|
121
|
+
export function promptPrefix(selection: ModelSelection): string {
|
|
122
|
+
return selection.options.effort === 'ultrathink' ? 'ultrathink\n\n' : '';
|
|
123
|
+
}
|
|
@@ -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,30 @@
|
|
|
1
|
+
import { CodexBackend, type CodexBackendOptions } from '../chat/codex-backend.ts';
|
|
2
|
+
import { ModelCatalog } from './catalog.ts';
|
|
3
|
+
import { CODEX_CAPABILITIES, CODEX_CHAT_ARGS, CODEX_RESUME_COMMAND } from './codex.ts';
|
|
4
|
+
import codexManifest from './codex-models.json' with { type: 'json' };
|
|
5
|
+
import { detectCli } from './detect.ts';
|
|
6
|
+
import type { ChatProvider } from './provider.ts';
|
|
7
|
+
|
|
8
|
+
export function createCodexProvider(options: CodexBackendOptions = {}): ChatProvider {
|
|
9
|
+
return {
|
|
10
|
+
kind: 'codex',
|
|
11
|
+
name: 'Codex',
|
|
12
|
+
catalog: new ModelCatalog(codexManifest as never),
|
|
13
|
+
capabilities: CODEX_CAPABILITIES,
|
|
14
|
+
command: ['codex', ...CODEX_CHAT_ARGS],
|
|
15
|
+
resumeCommand: CODEX_RESUME_COMMAND,
|
|
16
|
+
// The auth variables Codex 0.157 names in its own "no Codex credentials were found" advice.
|
|
17
|
+
home: { env: 'CODEX_HOME', fallback: '.codex', loginEnv: ['OPENAI_API_KEY', 'CODEX_API_KEY', 'CODEX_ACCESS_TOKEN'], loginCommand: 'codex login' },
|
|
18
|
+
detect: detectCli,
|
|
19
|
+
// Read-only and without an approval to wait for: the run only has to read what it is handed. A chat's
|
|
20
|
+
// title is asked in a folder that need not be a repository, and ephemeral keeps the run out of Codex's thread list.
|
|
21
|
+
oneShotArgs: (prompt) => ['exec', '--color', 'never', '--sandbox', 'read-only', '--skip-git-repo-check', '--ephemeral', prompt],
|
|
22
|
+
// A prompt of `-` is read from stdin.
|
|
23
|
+
oneShotStdinArgs: ['exec', '--color', 'never', '--sandbox', 'read-only', '--skip-git-repo-check', '--ephemeral', '-'],
|
|
24
|
+
// `codex [OPTIONS] [PROMPT]`: the positional starts the interactive session on that prompt.
|
|
25
|
+
firstPromptArgs: (prompt) => [prompt],
|
|
26
|
+
createBackend: (launch, host) => new CodexBackend(launch, host, options)
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const codexProvider = createCodexProvider();
|
|
@@ -0,0 +1,54 @@
|
|
|
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.ts';
|
|
5
|
+
import { isNotFound, writeAtomic } from '../fs.ts';
|
|
6
|
+
|
|
7
|
+
/*
|
|
8
|
+
* The commands a host lets Codex run outside its sandbox without asking: the seatbelt of
|
|
9
|
+
* workspace-write blocks every socket, loopback included, and Codex 0.157 has no setting that opens
|
|
10
|
+
* only the one a host's context CLI posts to. Opening the network for the whole sandbox would let
|
|
11
|
+
* every command out; this lets out only the named ones, which the host enforces on its side.
|
|
12
|
+
*/
|
|
13
|
+
export interface CodexRules {
|
|
14
|
+
/* Names the file and says who wrote it, so a person's `default.rules` is never touched. */
|
|
15
|
+
app: string;
|
|
16
|
+
commands: readonly string[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type CodexRulesResult = 'unchanged' | 'written';
|
|
20
|
+
|
|
21
|
+
export function codexRulesText(rules: CodexRules): string {
|
|
22
|
+
return (
|
|
23
|
+
[
|
|
24
|
+
`# Written by ${rules.app}; it is rewritten when it changes.`,
|
|
25
|
+
...rules.commands.map((command) => `prefix_rule(pattern=[${JSON.stringify(command)}], decision="allow")`)
|
|
26
|
+
].join('\n') + '\n'
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Codex loads every `*.rules` file in the `rules` folder of its home, and only from there, never from a flag.
|
|
31
|
+
export function codexRulesPathIn(folder: string, rules: CodexRules): string {
|
|
32
|
+
return join(folder, 'rules', `${rules.app.toLowerCase().replace(/[^a-z0-9]+/g, '-')}.rules`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function defaultCodexHome(env: Record<string, string | undefined> = process.env): string {
|
|
36
|
+
return env.CODEX_HOME ?? join(env.HOME ?? homedir(), '.codex');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/* Idempotent: a file that already says the same is left alone. */
|
|
40
|
+
export async function installCodexRules(path: string, rules: CodexRules): Promise<CodexRulesResult> {
|
|
41
|
+
const text = codexRulesText(rules);
|
|
42
|
+
try {
|
|
43
|
+
if ((await readFile(path, 'utf8')) === text) {
|
|
44
|
+
return 'unchanged';
|
|
45
|
+
}
|
|
46
|
+
} catch (e) {
|
|
47
|
+
if (!isNotFound(e)) {
|
|
48
|
+
throw new Error(`Cannot read ${path}: ${errorText(e)}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
await mkdir(dirname(path), { recursive: true });
|
|
52
|
+
await writeAtomic(path, text, 0o644);
|
|
53
|
+
return 'written';
|
|
54
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { ModelSelection, ProviderCapabilities, RuntimeMode } from '@adecore/agent-contracts';
|
|
2
|
+
|
|
3
|
+
// The app-server speaks JSON-RPC on stdio; the session adds nothing to the command line.
|
|
4
|
+
export const CODEX_CHAT_ARGS = ['app-server'];
|
|
5
|
+
|
|
6
|
+
type CodexApprovalPolicy = 'untrusted' | 'on-request' | 'never';
|
|
7
|
+
type CodexSandboxMode = 'read-only' | 'workspace-write' | 'danger-full-access';
|
|
8
|
+
|
|
9
|
+
interface CodexThreadOptions {
|
|
10
|
+
approvalPolicy: CodexApprovalPolicy;
|
|
11
|
+
sandbox: CodexSandboxMode;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/*
|
|
15
|
+
* Codex has two knobs, when it asks and where it may write, and no "ask for commands but not for
|
|
16
|
+
* edits" policy. `untrusted` inside a writable workspace comes closest: edits within the workspace
|
|
17
|
+
* pass the sandbox without a prompt, commands still ask unless Codex knows them as safe.
|
|
18
|
+
* `on-request` with the same sandbox is Codex's own default and stands in for `auto`.
|
|
19
|
+
*/
|
|
20
|
+
const THREAD_OPTIONS: Record<RuntimeMode, CodexThreadOptions> = {
|
|
21
|
+
supervised: { approvalPolicy: 'untrusted', sandbox: 'read-only' },
|
|
22
|
+
'auto-accept-edits': { approvalPolicy: 'untrusted', sandbox: 'workspace-write' },
|
|
23
|
+
auto: { approvalPolicy: 'on-request', sandbox: 'workspace-write' },
|
|
24
|
+
'full-access': { approvalPolicy: 'never', sandbox: 'danger-full-access' }
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export function codexThreadOptions(runtimeMode: RuntimeMode): CodexThreadOptions {
|
|
28
|
+
return THREAD_OPTIONS[runtimeMode];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function codexRuntimeMode(approvalPolicy: string, sandbox: string): RuntimeMode | undefined {
|
|
32
|
+
const names: Record<string, string> = { readOnly: 'read-only', workspaceWrite: 'workspace-write', dangerFullAccess: 'danger-full-access' };
|
|
33
|
+
return (Object.keys(THREAD_OPTIONS) as RuntimeMode[]).find((mode) => {
|
|
34
|
+
const options = THREAD_OPTIONS[mode];
|
|
35
|
+
return options.approvalPolicy === approvalPolicy && options.sandbox === (names[sandbox] ?? sandbox);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// What the app-server calls the faster of the two tiers it lists per model; the standard tier is no id at all.
|
|
40
|
+
const CODEX_PRIORITY_TIER = 'priority';
|
|
41
|
+
|
|
42
|
+
/* The service tier a thread or a turn runs on, or null for the standard one the account defaults to. */
|
|
43
|
+
export function codexServiceTier(selection: ModelSelection): string | null {
|
|
44
|
+
return selection.options.serviceTier === true ? CODEX_PRIORITY_TIER : null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// What the app-server can do, as far as a client has to know.
|
|
48
|
+
export const CODEX_CAPABILITIES: ProviderCapabilities = {
|
|
49
|
+
chat: true,
|
|
50
|
+
terminal: true,
|
|
51
|
+
hooks: true,
|
|
52
|
+
streamsToolOutput: true,
|
|
53
|
+
diffs: 'unified',
|
|
54
|
+
attachments: true,
|
|
55
|
+
// Codex has no mention part in its protocol; the picker sends the path as text, which is all
|
|
56
|
+
// the model needs to open the file with its own tools.
|
|
57
|
+
mentions: true,
|
|
58
|
+
denyReason: false,
|
|
59
|
+
allowAlways: true,
|
|
60
|
+
asyncQuestions: true,
|
|
61
|
+
compaction: 'native',
|
|
62
|
+
reportsCost: false,
|
|
63
|
+
reportsContextWindow: true,
|
|
64
|
+
reportsThinking: true,
|
|
65
|
+
slashCommands: false
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// `codex resume` is a subcommand that reads `[OPTIONS] [SESSION_ID]`, so the flags go after it.
|
|
69
|
+
export const CODEX_RESUME_COMMAND = 'codex resume {flags} {id}';
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { spawnChatProcess, type SpawnChatProcess } from '../chat/chat-process.ts';
|
|
2
|
+
|
|
3
|
+
export interface CliDetection {
|
|
4
|
+
installed: boolean;
|
|
5
|
+
version: string | null;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function definedOnly(env: Record<string, string | undefined>): Record<string, string> {
|
|
9
|
+
const defined: Record<string, string> = {};
|
|
10
|
+
for (const [key, value] of Object.entries(env)) {
|
|
11
|
+
if (value !== undefined) {
|
|
12
|
+
defined[key] = value;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return defined;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/* Asks a CLI for its version; a missing binary is a plain "not installed", never an error. */
|
|
19
|
+
export async function detectCli(
|
|
20
|
+
command: string,
|
|
21
|
+
env: Record<string, string | undefined> = process.env,
|
|
22
|
+
spawn: SpawnChatProcess = spawnChatProcess
|
|
23
|
+
): Promise<CliDetection> {
|
|
24
|
+
try {
|
|
25
|
+
let exited: (code: number | null) => void = () => undefined;
|
|
26
|
+
const code = new Promise<number | null>((resolve) => {
|
|
27
|
+
exited = resolve;
|
|
28
|
+
});
|
|
29
|
+
const proc = spawn({ command: [command, '--version'], cwd: process.cwd(), env: definedOnly(env), onExit: (exitCode) => exited(exitCode) });
|
|
30
|
+
proc.stdin.end();
|
|
31
|
+
const output = await new Response(proc.stdout).text();
|
|
32
|
+
if ((await code) !== 0) {
|
|
33
|
+
return { installed: false, version: null };
|
|
34
|
+
}
|
|
35
|
+
const version = /\d+\.\d+\.\d+/.exec(output)?.[0] ?? output.trim() ?? null;
|
|
36
|
+
return { installed: true, version };
|
|
37
|
+
} catch {
|
|
38
|
+
return { installed: false, version: null };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
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
|
+
|
|
6
|
+
export interface ProviderHome {
|
|
7
|
+
// The variable the CLI reads its config folder from.
|
|
8
|
+
readonly env: string;
|
|
9
|
+
// The folder it uses without that variable, under the person's home.
|
|
10
|
+
readonly fallback: string;
|
|
11
|
+
// Variables that sign the CLI in on their own, over whatever login the folder holds.
|
|
12
|
+
readonly loginEnv: readonly string[];
|
|
13
|
+
// What a person types in a terminal to sign in; the account's folder comes from the terminal's environment.
|
|
14
|
+
readonly loginCommand: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/*
|
|
18
|
+
* One agent CLI as a host knows it. Everything a provider does differently is either data on
|
|
19
|
+
* this value or behind the backend it makes, so a new CLI is a value plus a backend and nothing
|
|
20
|
+
* else changes: the session, the projector, the manager and the wire stay as they are.
|
|
21
|
+
*/
|
|
22
|
+
export interface ChatProvider {
|
|
23
|
+
readonly kind: AgentKind;
|
|
24
|
+
readonly name: string;
|
|
25
|
+
readonly catalog: ModelCatalog;
|
|
26
|
+
readonly capabilities: ProviderCapabilities;
|
|
27
|
+
// The executable and its leading arguments; a test points this at a fake CLI.
|
|
28
|
+
readonly command: string[];
|
|
29
|
+
// What a terminal runs to continue one of this CLI's sessions; `{id}` stands for the session id.
|
|
30
|
+
readonly resumeCommand: string;
|
|
31
|
+
/* Where this CLI keeps its login, settings and transcripts, which is what an account is. Absent on a
|
|
32
|
+
CLI with no variable to move that folder, which then only has its default account. */
|
|
33
|
+
readonly home?: ProviderHome;
|
|
34
|
+
/* The arguments for one prompt in and one answer out, no session and no chat, which is how a
|
|
35
|
+
host asks for a commit message or a title. Absent on a CLI that only runs interactively. */
|
|
36
|
+
oneShotArgs?(prompt: string): string[];
|
|
37
|
+
/* The same run with the prompt read from stdin, for a prompt too long for one argument (Linux
|
|
38
|
+
refuses one past 128 KiB) or too private for the process list. Absent on a CLI that cannot. */
|
|
39
|
+
readonly oneShotStdinArgs?: readonly string[];
|
|
40
|
+
/* The arguments that start this CLI interactively on a first prompt and then keep the session. */
|
|
41
|
+
firstPromptArgs(prompt: string): string[];
|
|
42
|
+
detect(command: string, env: Record<string, string | undefined>): Promise<CliDetection>;
|
|
43
|
+
// Whether a person turned this provider on, for one that is off until they do; absent is always on.
|
|
44
|
+
enabled?(): boolean;
|
|
45
|
+
createBackend(launch: BackendLaunch, host: BackendHost): ChatBackend;
|
|
46
|
+
}
|