discord-agent-bridge 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +195 -0
- package/dist/app.js +210 -0
- package/dist/app.js.map +1 -0
- package/dist/app.test.js +117 -0
- package/dist/app.test.js.map +1 -0
- package/dist/cli.js +63 -0
- package/dist/cli.js.map +1 -0
- package/dist/cli.test.js +91 -0
- package/dist/cli.test.js.map +1 -0
- package/dist/core/auditLog.js +65 -0
- package/dist/core/auditLog.js.map +1 -0
- package/dist/core/auditLog.test.js +124 -0
- package/dist/core/auditLog.test.js.map +1 -0
- package/dist/core/auth.js +106 -0
- package/dist/core/auth.js.map +1 -0
- package/dist/core/auth.test.js +216 -0
- package/dist/core/auth.test.js.map +1 -0
- package/dist/core/channelRegistry.js +119 -0
- package/dist/core/channelRegistry.js.map +1 -0
- package/dist/core/channelRegistry.test.js +114 -0
- package/dist/core/channelRegistry.test.js.map +1 -0
- package/dist/core/commandPolicy.js +6 -0
- package/dist/core/commandPolicy.js.map +1 -0
- package/dist/core/commandRouter.js +9 -0
- package/dist/core/commandRouter.js.map +1 -0
- package/dist/core/config.js +141 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/config.test.js +149 -0
- package/dist/core/config.test.js.map +1 -0
- package/dist/core/configResolver.js +90 -0
- package/dist/core/configResolver.js.map +1 -0
- package/dist/core/configResolver.test.js +138 -0
- package/dist/core/configResolver.test.js.map +1 -0
- package/dist/core/configSchema.js +164 -0
- package/dist/core/configSchema.js.map +1 -0
- package/dist/core/contracts.js +5 -0
- package/dist/core/contracts.js.map +1 -0
- package/dist/core/eventBus.js +42 -0
- package/dist/core/eventBus.js.map +1 -0
- package/dist/core/eventBus.test.js +72 -0
- package/dist/core/eventBus.test.js.map +1 -0
- package/dist/core/hookBridge.js +11 -0
- package/dist/core/hookBridge.js.map +1 -0
- package/dist/core/logger.js +116 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/logger.test.js +88 -0
- package/dist/core/logger.test.js.map +1 -0
- package/dist/core/modeRegistry.js +33 -0
- package/dist/core/modeRegistry.js.map +1 -0
- package/dist/core/permissionResolver.js +43 -0
- package/dist/core/permissionResolver.js.map +1 -0
- package/dist/core/permissionResolver.test.js +136 -0
- package/dist/core/permissionResolver.test.js.map +1 -0
- package/dist/core/providerCatalog.js +240 -0
- package/dist/core/providerCatalog.js.map +1 -0
- package/dist/core/providerCatalog.test.js +230 -0
- package/dist/core/providerCatalog.test.js.map +1 -0
- package/dist/core/sessionOrchestrator.js +463 -0
- package/dist/core/sessionOrchestrator.js.map +1 -0
- package/dist/core/sessionOrchestrator.test.js +344 -0
- package/dist/core/sessionOrchestrator.test.js.map +1 -0
- package/dist/core/state/schema.js +49 -0
- package/dist/core/state/schema.js.map +1 -0
- package/dist/core/state/store.js +86 -0
- package/dist/core/state/store.js.map +1 -0
- package/dist/core/state/store.test.js +99 -0
- package/dist/core/state/store.test.js.map +1 -0
- package/dist/core/usageService.js +310 -0
- package/dist/core/usageService.js.map +1 -0
- package/dist/core/usageService.test.js +234 -0
- package/dist/core/usageService.test.js.map +1 -0
- package/dist/discord/alwaysAllow.test.js +181 -0
- package/dist/discord/alwaysAllow.test.js.map +1 -0
- package/dist/discord/client.js +666 -0
- package/dist/discord/client.js.map +1 -0
- package/dist/discord/client.test.js +256 -0
- package/dist/discord/client.test.js.map +1 -0
- package/dist/discord/configPanel.js +270 -0
- package/dist/discord/configPanel.js.map +1 -0
- package/dist/discord/configPanel.test.js +332 -0
- package/dist/discord/configPanel.test.js.map +1 -0
- package/dist/discord/directoryBrowser.js +151 -0
- package/dist/discord/directoryBrowser.js.map +1 -0
- package/dist/discord/directoryBrowser.test.js +163 -0
- package/dist/discord/directoryBrowser.test.js.map +1 -0
- package/dist/discord/favorites.js +10 -0
- package/dist/discord/favorites.js.map +1 -0
- package/dist/discord/fileDownload.js +94 -0
- package/dist/discord/fileDownload.js.map +1 -0
- package/dist/discord/fileDownload.test.js +59 -0
- package/dist/discord/fileDownload.test.js.map +1 -0
- package/dist/discord/format.js +104 -0
- package/dist/discord/format.js.map +1 -0
- package/dist/discord/format.test.js +40 -0
- package/dist/discord/format.test.js.map +1 -0
- package/dist/discord/guildChannels.js +97 -0
- package/dist/discord/guildChannels.js.map +1 -0
- package/dist/discord/guildChannels.test.js +231 -0
- package/dist/discord/guildChannels.test.js.map +1 -0
- package/dist/discord/i18n.js +207 -0
- package/dist/discord/i18n.js.map +1 -0
- package/dist/discord/i18n.test.js +31 -0
- package/dist/discord/i18n.test.js.map +1 -0
- package/dist/discord/interactionRouter.js +954 -0
- package/dist/discord/interactionRouter.js.map +1 -0
- package/dist/discord/interactionRouter.test.js +1245 -0
- package/dist/discord/interactionRouter.test.js.map +1 -0
- package/dist/discord/messageRouter.js +221 -0
- package/dist/discord/messageRouter.js.map +1 -0
- package/dist/discord/messageRouter.test.js +360 -0
- package/dist/discord/messageRouter.test.js.map +1 -0
- package/dist/discord/ports.js +12 -0
- package/dist/discord/ports.js.map +1 -0
- package/dist/discord/renderers/defaultSet.test.js +97 -0
- package/dist/discord/renderers/defaultSet.test.js.map +1 -0
- package/dist/discord/renderers/diffView.js +73 -0
- package/dist/discord/renderers/diffView.js.map +1 -0
- package/dist/discord/renderers/diffView.test.js +54 -0
- package/dist/discord/renderers/diffView.test.js.map +1 -0
- package/dist/discord/renderers/index.js +143 -0
- package/dist/discord/renderers/index.js.map +1 -0
- package/dist/discord/renderers/index.test.js +124 -0
- package/dist/discord/renderers/index.test.js.map +1 -0
- package/dist/discord/renderers/mentionOnComplete.js +19 -0
- package/dist/discord/renderers/mentionOnComplete.js.map +1 -0
- package/dist/discord/renderers/mentionOnComplete.test.js +35 -0
- package/dist/discord/renderers/mentionOnComplete.test.js.map +1 -0
- package/dist/discord/renderers/permissionButtons.js +150 -0
- package/dist/discord/renderers/permissionButtons.js.map +1 -0
- package/dist/discord/renderers/permissionButtons.test.js +108 -0
- package/dist/discord/renderers/permissionButtons.test.js.map +1 -0
- package/dist/discord/renderers/resultLine.js +25 -0
- package/dist/discord/renderers/resultLine.js.map +1 -0
- package/dist/discord/renderers/statusEmbed.js +20 -0
- package/dist/discord/renderers/statusEmbed.js.map +1 -0
- package/dist/discord/renderers/statusEmbed.test.js +32 -0
- package/dist/discord/renderers/statusEmbed.test.js.map +1 -0
- package/dist/discord/renderers/streamEmbed.js +134 -0
- package/dist/discord/renderers/streamEmbed.js.map +1 -0
- package/dist/discord/renderers/streamEmbed.test.js +97 -0
- package/dist/discord/renderers/streamEmbed.test.js.map +1 -0
- package/dist/discord/renderers/toolThread.js +65 -0
- package/dist/discord/renderers/toolThread.js.map +1 -0
- package/dist/discord/renderers/toolThread.test.js +54 -0
- package/dist/discord/renderers/toolThread.test.js.map +1 -0
- package/dist/discord/renderers/transcriptFeed.js +33 -0
- package/dist/discord/renderers/transcriptFeed.js.map +1 -0
- package/dist/discord/renderers/usageEmbed.js +78 -0
- package/dist/discord/renderers/usageEmbed.js.map +1 -0
- package/dist/discord/renderers/usageEmbed.test.js +42 -0
- package/dist/discord/renderers/usageEmbed.test.js.map +1 -0
- package/dist/discord/wiring.js +214 -0
- package/dist/discord/wiring.js.map +1 -0
- package/dist/discord/wiring.test.js +252 -0
- package/dist/discord/wiring.test.js.map +1 -0
- package/dist/discord/wizard/channelWizard.js +305 -0
- package/dist/discord/wizard/channelWizard.js.map +1 -0
- package/dist/discord/wizard/channelWizard.test.js +298 -0
- package/dist/discord/wizard/channelWizard.test.js.map +1 -0
- package/dist/discord/wizard/resumeWizard.js +123 -0
- package/dist/discord/wizard/resumeWizard.js.map +1 -0
- package/dist/modes/claude/index.js +80 -0
- package/dist/modes/claude/index.js.map +1 -0
- package/dist/modes/claude/listResumable.test.js +72 -0
- package/dist/modes/claude/listResumable.test.js.map +1 -0
- package/dist/modes/claude/mcpFileTool.js +82 -0
- package/dist/modes/claude/mcpFileTool.js.map +1 -0
- package/dist/modes/claude/permissions.js +35 -0
- package/dist/modes/claude/permissions.js.map +1 -0
- package/dist/modes/claude/plugins.js +56 -0
- package/dist/modes/claude/plugins.js.map +1 -0
- package/dist/modes/claude/session.js +324 -0
- package/dist/modes/claude/session.js.map +1 -0
- package/dist/modes/claude/session.test.js +415 -0
- package/dist/modes/claude/session.test.js.map +1 -0
- package/dist/modes/codex/discovery.js +221 -0
- package/dist/modes/codex/discovery.js.map +1 -0
- package/dist/modes/codex/discovery.test.js +213 -0
- package/dist/modes/codex/discovery.test.js.map +1 -0
- package/dist/modes/codex/eventMapper.js +262 -0
- package/dist/modes/codex/eventMapper.js.map +1 -0
- package/dist/modes/codex/index.js +132 -0
- package/dist/modes/codex/index.js.map +1 -0
- package/dist/modes/codex/index.test.js +170 -0
- package/dist/modes/codex/index.test.js.map +1 -0
- package/dist/modes/codex/runner.js +207 -0
- package/dist/modes/codex/runner.js.map +1 -0
- package/dist/modes/codex/runner.test.js +587 -0
- package/dist/modes/codex/runner.test.js.map +1 -0
- package/dist/modes/codex/sqliteReader.js +171 -0
- package/dist/modes/codex/sqliteReader.js.map +1 -0
- package/dist/modes/codex/sqliteReader.test.js +137 -0
- package/dist/modes/codex/sqliteReader.test.js.map +1 -0
- package/dist/setup/wizard.js +115 -0
- package/dist/setup/wizard.js.map +1 -0
- package/dist/setup/wizard.test.js +216 -0
- package/dist/setup/wizard.test.js.map +1 -0
- package/dist/startBot.test.js +78 -0
- package/dist/startBot.test.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { query as realQuery, } from '@anthropic-ai/claude-agent-sdk';
|
|
2
|
+
// ---- Claude permission modes — TIED to the installed SDK's PermissionMode type ----
|
|
3
|
+
// `satisfies readonly PermissionMode[]` binds this list to the SDK: if a future SDK
|
|
4
|
+
// version adds or removes a mode, this constant fails to compile until it is synced,
|
|
5
|
+
// so new modes surface on upgrade instead of silently going missing. All SDK-declared
|
|
6
|
+
// modes are exposed; we pass `permissionMode` natively to the SDK, so every one works.
|
|
7
|
+
export const CLAUDE_PERMISSION_MODES = [
|
|
8
|
+
'default',
|
|
9
|
+
'acceptEdits',
|
|
10
|
+
'bypassPermissions',
|
|
11
|
+
'plan',
|
|
12
|
+
'dontAsk',
|
|
13
|
+
'auto',
|
|
14
|
+
];
|
|
15
|
+
// Codex permission modes = ONLY the subset that maps to codex approval/sandbox flags
|
|
16
|
+
// (see modes/codex/runner.ts permModeArgs). Codex has no mapping for 'dontAsk'/'auto',
|
|
17
|
+
// so they are deliberately excluded from the Codex list (honest per-backend limits).
|
|
18
|
+
export const CODEX_PERMISSION_MODES = [
|
|
19
|
+
'default',
|
|
20
|
+
'acceptEdits',
|
|
21
|
+
'bypassPermissions',
|
|
22
|
+
'plan',
|
|
23
|
+
];
|
|
24
|
+
// Short English hint appended in parens to a permission-mode label. NO Korean here —
|
|
25
|
+
// these are the selectable option labels the user wants in the original English.
|
|
26
|
+
const PERM_MODE_HINTS = {
|
|
27
|
+
default: 'ask each time',
|
|
28
|
+
acceptEdits: 'auto-approve edits',
|
|
29
|
+
bypassPermissions: 'auto-approve all',
|
|
30
|
+
plan: 'read-only planning',
|
|
31
|
+
dontAsk: 'deny if not pre-approved',
|
|
32
|
+
auto: 'model-classified',
|
|
33
|
+
};
|
|
34
|
+
// English label for a permission mode: the identifier plus a short English hint,
|
|
35
|
+
// e.g. `bypassPermissions (auto-approve all)`. Never localized.
|
|
36
|
+
export function permissionModeLabel(mode) {
|
|
37
|
+
return `${mode} (${PERM_MODE_HINTS[mode]})`;
|
|
38
|
+
}
|
|
39
|
+
// The permission-mode option list for a backend, as {value,label} with English labels.
|
|
40
|
+
export function permissionModeChoices(backend) {
|
|
41
|
+
const modes = backend === 'codex' ? CODEX_PERMISSION_MODES : CLAUDE_PERMISSION_MODES;
|
|
42
|
+
return modes.map((m) => ({ value: m, label: permissionModeLabel(m) }));
|
|
43
|
+
}
|
|
44
|
+
// ---- Codex-NATIVE sandbox permission choices --------------------------------
|
|
45
|
+
// Codex does NOT use Claude's permission-mode vocabulary; its own model is sandbox +
|
|
46
|
+
// approval. The permission step therefore offers Codex's actual `-s`/--sandbox values
|
|
47
|
+
// (verified against `codex exec`) so the operator sees Codex terms, not Claude ones.
|
|
48
|
+
// The runner (modes/codex/runner.ts permModeArgs) maps each to `-s <mode>` plus a
|
|
49
|
+
// sensible `-c approval_policy=…`. `danger-full-access` is the codex bypass equivalent.
|
|
50
|
+
export const CODEX_SANDBOX_MODES = ['read-only', 'workspace-write', 'danger-full-access'];
|
|
51
|
+
// True when `value` is a Codex-native sandbox mode (vs a Claude PermMode). Lets the
|
|
52
|
+
// runner and wizard tell the two vocabularies apart without a separate type channel.
|
|
53
|
+
export function isCodexSandboxMode(value) {
|
|
54
|
+
return CODEX_SANDBOX_MODES.includes(value);
|
|
55
|
+
}
|
|
56
|
+
// Short English hint appended in parens to a Codex sandbox label. English only — these
|
|
57
|
+
// are the selectable option labels, wanted verbatim.
|
|
58
|
+
const CODEX_SANDBOX_HINTS = {
|
|
59
|
+
'read-only': 'read-only, ask to run',
|
|
60
|
+
'workspace-write': 'write in workspace',
|
|
61
|
+
'danger-full-access': 'no sandbox (⚠ dangerous)',
|
|
62
|
+
};
|
|
63
|
+
// The Codex sandbox permission option list as English {value,label}, e.g.
|
|
64
|
+
// `workspace-write (write in workspace)`. Never localized.
|
|
65
|
+
export function codexSandboxChoices() {
|
|
66
|
+
return CODEX_SANDBOX_MODES.map((m) => ({ value: m, label: `${m} (${CODEX_SANDBOX_HINTS[m]})` }));
|
|
67
|
+
}
|
|
68
|
+
// The permission OPTION list for the wizard's permission step, keyed by backend: Codex
|
|
69
|
+
// shows its native sandbox modes; every other backend shows the Claude PermMode list.
|
|
70
|
+
export function permissionChoicesFor(backend) {
|
|
71
|
+
return backend === 'codex' ? codexSandboxChoices() : permissionModeChoices(backend);
|
|
72
|
+
}
|
|
73
|
+
// ---- Reasoning-effort choices (per-backend) ---------------------------------
|
|
74
|
+
// Claude effort levels — TIED to the SDK's EffortLevel so the list can't drift: if a
|
|
75
|
+
// future SDK adds/removes a level this fails to compile until synced. Passed to the
|
|
76
|
+
// SDK's `options.effort`. A model may narrow this via ModelInfo.supportedEffortLevels.
|
|
77
|
+
export const CLAUDE_EFFORT_LEVELS = [
|
|
78
|
+
'low',
|
|
79
|
+
'medium',
|
|
80
|
+
'high',
|
|
81
|
+
'xhigh',
|
|
82
|
+
'max',
|
|
83
|
+
];
|
|
84
|
+
// Codex reasoning-effort values accepted by `-c model_reasoning_effort="…"` (verified
|
|
85
|
+
// against developers.openai.com/codex/config-reference, 2026-07). The operator's own
|
|
86
|
+
// config uses 'medium', which is the sensible default here too.
|
|
87
|
+
export const CODEX_EFFORT_LEVELS = ['minimal', 'low', 'medium', 'high', 'xhigh'];
|
|
88
|
+
// The default reasoning effort offered pre-selected in the wizard per backend. Claude's
|
|
89
|
+
// SDK default is 'high'; Codex's practical default (and the operator's config) is 'medium'.
|
|
90
|
+
export function defaultEffortFor(backend) {
|
|
91
|
+
return backend === 'codex' ? 'medium' : 'high';
|
|
92
|
+
}
|
|
93
|
+
// The reasoning-effort OPTION list for the wizard's effort step, keyed by backend and —
|
|
94
|
+
// for Claude — narrowed to a model's supported levels when the SDK reports them. Labels
|
|
95
|
+
// are the plain English level names. `supportedClaudeLevels`, when non-empty, replaces
|
|
96
|
+
// the full Claude list (e.g. a model with only low/medium/high).
|
|
97
|
+
export function effortChoicesFor(backend, supportedClaudeLevels) {
|
|
98
|
+
if (backend === 'codex') {
|
|
99
|
+
return CODEX_EFFORT_LEVELS.map((e) => ({ value: e, label: e }));
|
|
100
|
+
}
|
|
101
|
+
const levels = supportedClaudeLevels && supportedClaudeLevels.length > 0
|
|
102
|
+
? supportedClaudeLevels
|
|
103
|
+
: CLAUDE_EFFORT_LEVELS;
|
|
104
|
+
return levels.map((e) => ({ value: e, label: e }));
|
|
105
|
+
}
|
|
106
|
+
// ---- Claude models — DYNAMIC (runtime, cached) -------------------------------
|
|
107
|
+
// Friendly aliases used as the graceful fallback when the SDK cannot report models
|
|
108
|
+
// (API-key-only auth, offline, timeout). English, so the dropdown never breaks.
|
|
109
|
+
export const CLAUDE_MODEL_FALLBACK = ['opus', 'sonnet', 'haiku'];
|
|
110
|
+
// How long we wait for supportedModels() before giving up and using the fallback.
|
|
111
|
+
const SUPPORTED_MODELS_TIMEOUT_MS = 5_000;
|
|
112
|
+
// Module-level cache: the resolved English model list is fetched ONCE and reused.
|
|
113
|
+
// We cache the ModelChoice[] itself (not the promise) so a failed fetch is not
|
|
114
|
+
// memoized — a later render can retry (and will still fall back safely meanwhile).
|
|
115
|
+
let cachedClaudeModels = null;
|
|
116
|
+
// In-flight fetch shared by concurrent callers so we never launch two probe queries.
|
|
117
|
+
let inFlight = null;
|
|
118
|
+
// Reset the cache (tests only) so each case starts from a cold catalog.
|
|
119
|
+
export function __resetClaudeModelCache() {
|
|
120
|
+
cachedClaudeModels = null;
|
|
121
|
+
inFlight = null;
|
|
122
|
+
}
|
|
123
|
+
// A prompt stream that yields nothing and ends immediately: we only need the query
|
|
124
|
+
// object alive long enough to answer the supportedModels() control request. No user
|
|
125
|
+
// turn is ever sent, so this never spends tokens.
|
|
126
|
+
async function* emptyPrompt() {
|
|
127
|
+
// Intentionally empty: end the stream at once.
|
|
128
|
+
}
|
|
129
|
+
// Fetch the Claude model list from the SDK's supportedModels() and map each to an
|
|
130
|
+
// English {value,label} (value = model id, label = the SDK's displayName). Runs a
|
|
131
|
+
// short-lived query() purely to reach the control request, races it against a
|
|
132
|
+
// timeout, and always closes the query. Any failure resolves to the alias fallback.
|
|
133
|
+
async function fetchClaudeModels(queryFn, logger) {
|
|
134
|
+
let q = null;
|
|
135
|
+
try {
|
|
136
|
+
q = queryFn({ prompt: emptyPrompt() });
|
|
137
|
+
const models = await withTimeout(q.supportedModels(), SUPPORTED_MODELS_TIMEOUT_MS);
|
|
138
|
+
const choices = models
|
|
139
|
+
.filter((m) => Boolean(m && typeof m.value === 'string' && m.value.length > 0))
|
|
140
|
+
.map((m) => ({
|
|
141
|
+
value: m.value,
|
|
142
|
+
label: m.displayName || m.value,
|
|
143
|
+
...(m.supportedEffortLevels && m.supportedEffortLevels.length > 0
|
|
144
|
+
? { supportedEffortLevels: [...m.supportedEffortLevels] }
|
|
145
|
+
: {}),
|
|
146
|
+
}));
|
|
147
|
+
if (choices.length === 0)
|
|
148
|
+
return fallbackChoices();
|
|
149
|
+
return choices;
|
|
150
|
+
}
|
|
151
|
+
catch (err) {
|
|
152
|
+
logger?.debug('providerCatalog: supportedModels() unavailable; using alias fallback', {
|
|
153
|
+
error: err instanceof Error ? err.message : String(err),
|
|
154
|
+
});
|
|
155
|
+
return fallbackChoices();
|
|
156
|
+
}
|
|
157
|
+
finally {
|
|
158
|
+
try {
|
|
159
|
+
q?.close();
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
// Closing an already-finished probe query is a no-op we can ignore.
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
function fallbackChoices() {
|
|
167
|
+
return CLAUDE_MODEL_FALLBACK.map((m) => ({ value: m, label: m }));
|
|
168
|
+
}
|
|
169
|
+
// Resolve a promise or the timeout, whichever comes first. A timeout rejects so the
|
|
170
|
+
// caller falls back to the aliases.
|
|
171
|
+
function withTimeout(promise, ms) {
|
|
172
|
+
return new Promise((resolve, reject) => {
|
|
173
|
+
const timer = setTimeout(() => reject(new Error(`supportedModels() timed out after ${ms}ms`)), ms);
|
|
174
|
+
promise.then((v) => {
|
|
175
|
+
clearTimeout(timer);
|
|
176
|
+
resolve(v);
|
|
177
|
+
}, (e) => {
|
|
178
|
+
clearTimeout(timer);
|
|
179
|
+
reject(e);
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
// The Claude model list as English {value,label}. Cached: the first call fetches
|
|
184
|
+
// (via the SDK), later calls reuse the cached list. Concurrent callers share one
|
|
185
|
+
// in-flight fetch. On failure the fallback is returned but NOT cached, so a later
|
|
186
|
+
// call can retry once auth/network is available.
|
|
187
|
+
export async function getClaudeModels(deps = {}) {
|
|
188
|
+
if (cachedClaudeModels)
|
|
189
|
+
return cachedClaudeModels;
|
|
190
|
+
if (inFlight)
|
|
191
|
+
return inFlight;
|
|
192
|
+
const queryFn = deps.queryFn ?? realQuery;
|
|
193
|
+
inFlight = fetchClaudeModels(queryFn, deps.logger)
|
|
194
|
+
.then((choices) => {
|
|
195
|
+
// Cache only a real (non-fallback) result so a transient failure can retry.
|
|
196
|
+
const isFallback = choices.length === CLAUDE_MODEL_FALLBACK.length &&
|
|
197
|
+
choices.every((c, i) => c.value === CLAUDE_MODEL_FALLBACK[i]);
|
|
198
|
+
if (!isFallback)
|
|
199
|
+
cachedClaudeModels = choices;
|
|
200
|
+
return choices;
|
|
201
|
+
})
|
|
202
|
+
.finally(() => {
|
|
203
|
+
inFlight = null;
|
|
204
|
+
});
|
|
205
|
+
return inFlight;
|
|
206
|
+
}
|
|
207
|
+
// The Claude model list WITHOUT blocking: returns the cached English list if present,
|
|
208
|
+
// otherwise kicks off the async fetch (fire-and-forget) and returns the alias fallback
|
|
209
|
+
// for THIS render. Lets an interaction ack immediately; the next render sees the cache.
|
|
210
|
+
export function getClaudeModelsCachedOrFallback(deps = {}) {
|
|
211
|
+
if (cachedClaudeModels)
|
|
212
|
+
return cachedClaudeModels;
|
|
213
|
+
void getClaudeModels(deps); // warm the cache for the next render
|
|
214
|
+
return fallbackChoices();
|
|
215
|
+
}
|
|
216
|
+
// ---- Codex models — honest static default (NOT auto-fetched) -----------------
|
|
217
|
+
// Codex has no model-list API and `codex exec -m` is FREE-FORM (any OpenAI model the
|
|
218
|
+
// account can reach works), so this is a documented convenience list, not a dynamic
|
|
219
|
+
// source. A configured non-empty codexModel is offered first (de-duplicated). English
|
|
220
|
+
// ids. The list below reflects the models currently used with the OpenAI Codex CLI as
|
|
221
|
+
// of 2026-07 (researched against developers.openai.com/codex/models): gpt-5.5 is the
|
|
222
|
+
// current default for ChatGPT-authenticated sessions, gpt-5.4 the fallback, gpt-5.4-mini
|
|
223
|
+
// for lighter tasks/subagents, and gpt-5.2-codex the Codex-specialized id kept for
|
|
224
|
+
// API-key workflows.
|
|
225
|
+
const CODEX_MODEL_DEFAULTS = [
|
|
226
|
+
'gpt-5.5',
|
|
227
|
+
'gpt-5.4',
|
|
228
|
+
'gpt-5.4-mini',
|
|
229
|
+
'gpt-5.2-codex',
|
|
230
|
+
];
|
|
231
|
+
// The Codex model option list as English {value,label} (label = id). `configured`
|
|
232
|
+
// is config.defaults.codexModel: when non-empty it leads the list.
|
|
233
|
+
export function getCodexModels(configured = '') {
|
|
234
|
+
const trimmed = configured.trim();
|
|
235
|
+
const ids = trimmed.length === 0
|
|
236
|
+
? [...CODEX_MODEL_DEFAULTS]
|
|
237
|
+
: [trimmed, ...CODEX_MODEL_DEFAULTS.filter((m) => m !== trimmed)];
|
|
238
|
+
return ids.map((id) => ({ value: id, label: id }));
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=providerCatalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providerCatalog.js","sourceRoot":"","sources":["../../src/core/providerCatalog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
2
|
+
import { getClaudeModels, getClaudeModelsCachedOrFallback, getCodexModels, permissionModeChoices, permissionModeLabel, permissionChoicesFor, codexSandboxChoices, isCodexSandboxMode, effortChoicesFor, defaultEffortFor, CLAUDE_PERMISSION_MODES, CODEX_PERMISSION_MODES, CLAUDE_EFFORT_LEVELS, CODEX_EFFORT_LEVELS, CODEX_SANDBOX_MODES, CLAUDE_MODEL_FALLBACK, __resetClaudeModelCache, } from './providerCatalog.js';
|
|
3
|
+
import { permModeSchema } from './configSchema.js';
|
|
4
|
+
import { permModeArgs } from '../modes/codex/runner.js';
|
|
5
|
+
// The provider catalog is the ONE source of the model + permission-mode option lists.
|
|
6
|
+
// These tests MOCK the SDK's supportedModels() — no real SDK, no network. Each case
|
|
7
|
+
// starts from a cold cache.
|
|
8
|
+
// Build a fake Query object exposing just what the catalog calls: an async iterable
|
|
9
|
+
// that ends at once, supportedModels(), and close(). `supported` is a factory so a
|
|
10
|
+
// case can resolve, reject, or hang it.
|
|
11
|
+
function fakeQueryFn(supported, onClose) {
|
|
12
|
+
const calls = { supportedModels: 0 };
|
|
13
|
+
const queryFn = (() => {
|
|
14
|
+
const gen = (async function* () {
|
|
15
|
+
// Yields nothing: the probe query never sends a turn.
|
|
16
|
+
})();
|
|
17
|
+
return Object.assign(gen, {
|
|
18
|
+
supportedModels: () => {
|
|
19
|
+
calls.supportedModels += 1;
|
|
20
|
+
return supported();
|
|
21
|
+
},
|
|
22
|
+
close: () => {
|
|
23
|
+
onClose?.();
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
return { queryFn, calls };
|
|
28
|
+
}
|
|
29
|
+
function model(value, displayName) {
|
|
30
|
+
return { value, displayName, description: `${displayName} model` };
|
|
31
|
+
}
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
__resetClaudeModelCache();
|
|
34
|
+
});
|
|
35
|
+
describe('getClaudeModels (dynamic, mocked SDK)', () => {
|
|
36
|
+
it('maps supportedModels() to English {value,label} (value=id, label=displayName)', async () => {
|
|
37
|
+
const { queryFn } = fakeQueryFn(async () => [
|
|
38
|
+
model('claude-opus-4-6', 'Claude Opus 4.6'),
|
|
39
|
+
model('claude-sonnet-4-5', 'Claude Sonnet 4.5'),
|
|
40
|
+
]);
|
|
41
|
+
const choices = await getClaudeModels({ queryFn });
|
|
42
|
+
expect(choices).toEqual([
|
|
43
|
+
{ value: 'claude-opus-4-6', label: 'Claude Opus 4.6' },
|
|
44
|
+
{ value: 'claude-sonnet-4-5', label: 'Claude Sonnet 4.5' },
|
|
45
|
+
]);
|
|
46
|
+
});
|
|
47
|
+
it('falls back to the English aliases when supportedModels() REJECTS', async () => {
|
|
48
|
+
const { queryFn } = fakeQueryFn(async () => {
|
|
49
|
+
throw new Error('unavailable (api-key-only)');
|
|
50
|
+
});
|
|
51
|
+
const debug = vi.fn();
|
|
52
|
+
const choices = await getClaudeModels({ queryFn, logger: { debug, info() { }, warn() { }, error() { } } });
|
|
53
|
+
expect(choices).toEqual([
|
|
54
|
+
{ value: 'opus', label: 'opus' },
|
|
55
|
+
{ value: 'sonnet', label: 'sonnet' },
|
|
56
|
+
{ value: 'haiku', label: 'haiku' },
|
|
57
|
+
]);
|
|
58
|
+
expect(choices.map((c) => c.value)).toEqual([...CLAUDE_MODEL_FALLBACK]);
|
|
59
|
+
// Logged at debug (not warn/error) as specified.
|
|
60
|
+
expect(debug).toHaveBeenCalledOnce();
|
|
61
|
+
});
|
|
62
|
+
it('falls back to the aliases when supportedModels() TIMES OUT (never resolves)', async () => {
|
|
63
|
+
// A promise that never settles → the internal timeout wins → fallback.
|
|
64
|
+
const { queryFn } = fakeQueryFn(() => new Promise(() => { }));
|
|
65
|
+
vi.useFakeTimers();
|
|
66
|
+
try {
|
|
67
|
+
const promise = getClaudeModels({ queryFn });
|
|
68
|
+
await vi.advanceTimersByTimeAsync(5_100);
|
|
69
|
+
const choices = await promise;
|
|
70
|
+
expect(choices.map((c) => c.value)).toEqual([...CLAUDE_MODEL_FALLBACK]);
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
vi.useRealTimers();
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
it('CACHES a real result: supportedModels() is called once across calls', async () => {
|
|
77
|
+
const { queryFn, calls } = fakeQueryFn(async () => [model('claude-opus-4-6', 'Claude Opus 4.6')]);
|
|
78
|
+
const first = await getClaudeModels({ queryFn });
|
|
79
|
+
const second = await getClaudeModels({ queryFn });
|
|
80
|
+
expect(first).toEqual(second);
|
|
81
|
+
expect(calls.supportedModels).toBe(1);
|
|
82
|
+
});
|
|
83
|
+
it('does NOT cache a fallback result, so a later call can retry', async () => {
|
|
84
|
+
// First call fails → fallback (not cached). Second call succeeds → real list.
|
|
85
|
+
let attempt = 0;
|
|
86
|
+
const { queryFn, calls } = fakeQueryFn(async () => {
|
|
87
|
+
attempt += 1;
|
|
88
|
+
if (attempt === 1)
|
|
89
|
+
throw new Error('offline');
|
|
90
|
+
return [model('claude-opus-4-6', 'Claude Opus 4.6')];
|
|
91
|
+
});
|
|
92
|
+
const first = await getClaudeModels({ queryFn });
|
|
93
|
+
expect(first.map((c) => c.value)).toEqual([...CLAUDE_MODEL_FALLBACK]);
|
|
94
|
+
const second = await getClaudeModels({ queryFn });
|
|
95
|
+
expect(second).toEqual([{ value: 'claude-opus-4-6', label: 'Claude Opus 4.6' }]);
|
|
96
|
+
expect(calls.supportedModels).toBe(2);
|
|
97
|
+
});
|
|
98
|
+
it('closes the probe query after fetching', async () => {
|
|
99
|
+
const onClose = vi.fn();
|
|
100
|
+
const { queryFn } = fakeQueryFn(async () => [model('claude-opus-4-6', 'Claude Opus 4.6')], onClose);
|
|
101
|
+
await getClaudeModels({ queryFn });
|
|
102
|
+
expect(onClose).toHaveBeenCalledOnce();
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
describe('getClaudeModelsCachedOrFallback (non-blocking)', () => {
|
|
106
|
+
it('returns the alias fallback synchronously when the cache is cold, then warms it', async () => {
|
|
107
|
+
const { queryFn, calls } = fakeQueryFn(async () => [model('claude-opus-4-6', 'Claude Opus 4.6')]);
|
|
108
|
+
const immediate = getClaudeModelsCachedOrFallback({ queryFn });
|
|
109
|
+
expect(immediate.map((c) => c.value)).toEqual([...CLAUDE_MODEL_FALLBACK]);
|
|
110
|
+
// The warm-up fetch was kicked off; let it resolve, then the cached list appears.
|
|
111
|
+
await vi.waitFor(() => expect(calls.supportedModels).toBe(1));
|
|
112
|
+
await getClaudeModels({ queryFn }); // resolves from the now-warm cache
|
|
113
|
+
const cached = getClaudeModelsCachedOrFallback({ queryFn });
|
|
114
|
+
expect(cached).toEqual([{ value: 'claude-opus-4-6', label: 'Claude Opus 4.6' }]);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
describe('permission modes (SDK-synced, English, per-backend)', () => {
|
|
118
|
+
it('the Claude list is the full SDK-synced set with English labels', () => {
|
|
119
|
+
expect([...CLAUDE_PERMISSION_MODES]).toEqual([
|
|
120
|
+
'default',
|
|
121
|
+
'acceptEdits',
|
|
122
|
+
'bypassPermissions',
|
|
123
|
+
'plan',
|
|
124
|
+
'dontAsk',
|
|
125
|
+
'auto',
|
|
126
|
+
]);
|
|
127
|
+
const choices = permissionModeChoices('claude');
|
|
128
|
+
expect(choices.map((c) => c.value)).toEqual([...CLAUDE_PERMISSION_MODES]);
|
|
129
|
+
// Labels are the English identifier + a short English hint (no Korean).
|
|
130
|
+
expect(permissionModeLabel('bypassPermissions')).toBe('bypassPermissions (auto-approve all)');
|
|
131
|
+
const hangul = /[가-힣]/;
|
|
132
|
+
for (const c of choices)
|
|
133
|
+
expect(hangul.test(c.label)).toBe(false);
|
|
134
|
+
});
|
|
135
|
+
it('the Codex list excludes dontAsk/auto (no codex mapping)', () => {
|
|
136
|
+
expect([...CODEX_PERMISSION_MODES]).toEqual(['default', 'acceptEdits', 'bypassPermissions', 'plan']);
|
|
137
|
+
const codex = permissionModeChoices('codex').map((c) => c.value);
|
|
138
|
+
expect(codex).not.toContain('dontAsk');
|
|
139
|
+
expect(codex).not.toContain('auto');
|
|
140
|
+
});
|
|
141
|
+
it('the config schema accepts ALL Claude permission modes', () => {
|
|
142
|
+
for (const mode of CLAUDE_PERMISSION_MODES) {
|
|
143
|
+
expect(permModeSchema.safeParse(mode).success).toBe(true);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
it('permModeArgs stays valid for every Codex permission mode', () => {
|
|
147
|
+
for (const mode of CODEX_PERMISSION_MODES) {
|
|
148
|
+
const args = permModeArgs(mode);
|
|
149
|
+
expect(Array.isArray(args)).toBe(true);
|
|
150
|
+
expect(args.length).toBeGreaterThan(0);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
describe('getCodexModels (researched convenience list, English)', () => {
|
|
155
|
+
it('returns the current researched list as English {value,label} (label=id) when nothing is configured', () => {
|
|
156
|
+
const choices = getCodexModels('');
|
|
157
|
+
expect(choices).toEqual([
|
|
158
|
+
{ value: 'gpt-5.5', label: 'gpt-5.5' },
|
|
159
|
+
{ value: 'gpt-5.4', label: 'gpt-5.4' },
|
|
160
|
+
{ value: 'gpt-5.4-mini', label: 'gpt-5.4-mini' },
|
|
161
|
+
{ value: 'gpt-5.2-codex', label: 'gpt-5.2-codex' },
|
|
162
|
+
]);
|
|
163
|
+
});
|
|
164
|
+
it('offers a configured codexModel FIRST, de-duplicated', () => {
|
|
165
|
+
const choices = getCodexModels('gpt-5.4');
|
|
166
|
+
expect(choices[0]).toEqual({ value: 'gpt-5.4', label: 'gpt-5.4' });
|
|
167
|
+
// No duplicate of the configured model further down the list.
|
|
168
|
+
expect(choices.filter((c) => c.value === 'gpt-5.4')).toHaveLength(1);
|
|
169
|
+
expect(choices).toHaveLength(4);
|
|
170
|
+
});
|
|
171
|
+
it('leads with a novel configured model (e.g. the operator config.toml model) without dropping the defaults', () => {
|
|
172
|
+
const choices = getCodexModels('gpt-5.5-codex');
|
|
173
|
+
expect(choices[0]?.value).toBe('gpt-5.5-codex');
|
|
174
|
+
expect(choices).toHaveLength(5);
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
describe('Codex-native sandbox permission choices (backend-specific)', () => {
|
|
178
|
+
it('CODEX_SANDBOX_MODES is exactly the three documented -s values', () => {
|
|
179
|
+
expect([...CODEX_SANDBOX_MODES]).toEqual(['read-only', 'workspace-write', 'danger-full-access']);
|
|
180
|
+
});
|
|
181
|
+
it('isCodexSandboxMode recognizes sandbox modes and rejects Claude PermMode names', () => {
|
|
182
|
+
expect(isCodexSandboxMode('workspace-write')).toBe(true);
|
|
183
|
+
expect(isCodexSandboxMode('danger-full-access')).toBe(true);
|
|
184
|
+
expect(isCodexSandboxMode('acceptEdits')).toBe(false);
|
|
185
|
+
expect(isCodexSandboxMode('default')).toBe(false);
|
|
186
|
+
});
|
|
187
|
+
it('codexSandboxChoices are English {value,label} with a short hint (no Korean)', () => {
|
|
188
|
+
const choices = codexSandboxChoices();
|
|
189
|
+
expect(choices.map((c) => c.value)).toEqual(['read-only', 'workspace-write', 'danger-full-access']);
|
|
190
|
+
const hangul = /[가-힣]/;
|
|
191
|
+
for (const c of choices)
|
|
192
|
+
expect(hangul.test(c.label)).toBe(false);
|
|
193
|
+
expect(choices.find((c) => c.value === 'workspace-write')?.label).toBe('workspace-write (write in workspace)');
|
|
194
|
+
});
|
|
195
|
+
it('permissionChoicesFor keys off the backend: Codex → sandbox terms, Claude → PermMode', () => {
|
|
196
|
+
expect(permissionChoicesFor('codex').map((c) => c.value)).toEqual([...CODEX_SANDBOX_MODES]);
|
|
197
|
+
expect(permissionChoicesFor('claude').map((c) => c.value)).toEqual([...CLAUDE_PERMISSION_MODES]);
|
|
198
|
+
});
|
|
199
|
+
it('permModeArgs maps each Codex sandbox choice to the right -s / approval flags', () => {
|
|
200
|
+
expect(permModeArgs('read-only')).toEqual(['-c', 'approval_policy="on-request"', '-s', 'read-only']);
|
|
201
|
+
expect(permModeArgs('workspace-write')).toEqual(['-c', 'approval_policy="on-request"', '-s', 'workspace-write']);
|
|
202
|
+
// danger-full-access → the single codex bypass flag (no -s/-c/-a).
|
|
203
|
+
expect(permModeArgs('danger-full-access')).toEqual(['--dangerously-bypass-approvals-and-sandbox']);
|
|
204
|
+
for (const m of CODEX_SANDBOX_MODES) {
|
|
205
|
+
expect(permModeArgs(m)).not.toContain('-a');
|
|
206
|
+
expect(permModeArgs(m)).not.toContain('--ask-for-approval');
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
describe('reasoning-effort choices (per-backend)', () => {
|
|
211
|
+
it('Claude effort levels are the SDK-synced set; Codex adds minimal and drops max', () => {
|
|
212
|
+
expect([...CLAUDE_EFFORT_LEVELS]).toEqual(['low', 'medium', 'high', 'xhigh', 'max']);
|
|
213
|
+
expect([...CODEX_EFFORT_LEVELS]).toEqual(['minimal', 'low', 'medium', 'high', 'xhigh']);
|
|
214
|
+
});
|
|
215
|
+
it('effortChoicesFor branches by backend with plain English labels', () => {
|
|
216
|
+
expect(effortChoicesFor('claude').map((c) => c.value)).toEqual([...CLAUDE_EFFORT_LEVELS]);
|
|
217
|
+
expect(effortChoicesFor('codex').map((c) => c.value)).toEqual([...CODEX_EFFORT_LEVELS]);
|
|
218
|
+
});
|
|
219
|
+
it('effortChoicesFor narrows Claude to a model’s supportedEffortLevels when provided', () => {
|
|
220
|
+
const narrowed = effortChoicesFor('claude', ['low', 'medium', 'high']);
|
|
221
|
+
expect(narrowed.map((c) => c.value)).toEqual(['low', 'medium', 'high']);
|
|
222
|
+
// Codex ignores the Claude-only narrowing argument.
|
|
223
|
+
expect(effortChoicesFor('codex', ['low']).map((c) => c.value)).toEqual([...CODEX_EFFORT_LEVELS]);
|
|
224
|
+
});
|
|
225
|
+
it('defaultEffortFor is high for Claude and medium for Codex', () => {
|
|
226
|
+
expect(defaultEffortFor('claude')).toBe('high');
|
|
227
|
+
expect(defaultEffortFor('codex')).toBe('medium');
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
//# sourceMappingURL=providerCatalog.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providerCatalog.test.js","sourceRoot":"","sources":["../../src/core/providerCatalog.test.ts"],"names":[],"mappings":"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"}
|