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.
Files changed (201) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +195 -0
  3. package/dist/app.js +210 -0
  4. package/dist/app.js.map +1 -0
  5. package/dist/app.test.js +117 -0
  6. package/dist/app.test.js.map +1 -0
  7. package/dist/cli.js +63 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/cli.test.js +91 -0
  10. package/dist/cli.test.js.map +1 -0
  11. package/dist/core/auditLog.js +65 -0
  12. package/dist/core/auditLog.js.map +1 -0
  13. package/dist/core/auditLog.test.js +124 -0
  14. package/dist/core/auditLog.test.js.map +1 -0
  15. package/dist/core/auth.js +106 -0
  16. package/dist/core/auth.js.map +1 -0
  17. package/dist/core/auth.test.js +216 -0
  18. package/dist/core/auth.test.js.map +1 -0
  19. package/dist/core/channelRegistry.js +119 -0
  20. package/dist/core/channelRegistry.js.map +1 -0
  21. package/dist/core/channelRegistry.test.js +114 -0
  22. package/dist/core/channelRegistry.test.js.map +1 -0
  23. package/dist/core/commandPolicy.js +6 -0
  24. package/dist/core/commandPolicy.js.map +1 -0
  25. package/dist/core/commandRouter.js +9 -0
  26. package/dist/core/commandRouter.js.map +1 -0
  27. package/dist/core/config.js +141 -0
  28. package/dist/core/config.js.map +1 -0
  29. package/dist/core/config.test.js +149 -0
  30. package/dist/core/config.test.js.map +1 -0
  31. package/dist/core/configResolver.js +90 -0
  32. package/dist/core/configResolver.js.map +1 -0
  33. package/dist/core/configResolver.test.js +138 -0
  34. package/dist/core/configResolver.test.js.map +1 -0
  35. package/dist/core/configSchema.js +164 -0
  36. package/dist/core/configSchema.js.map +1 -0
  37. package/dist/core/contracts.js +5 -0
  38. package/dist/core/contracts.js.map +1 -0
  39. package/dist/core/eventBus.js +42 -0
  40. package/dist/core/eventBus.js.map +1 -0
  41. package/dist/core/eventBus.test.js +72 -0
  42. package/dist/core/eventBus.test.js.map +1 -0
  43. package/dist/core/hookBridge.js +11 -0
  44. package/dist/core/hookBridge.js.map +1 -0
  45. package/dist/core/logger.js +116 -0
  46. package/dist/core/logger.js.map +1 -0
  47. package/dist/core/logger.test.js +88 -0
  48. package/dist/core/logger.test.js.map +1 -0
  49. package/dist/core/modeRegistry.js +33 -0
  50. package/dist/core/modeRegistry.js.map +1 -0
  51. package/dist/core/permissionResolver.js +43 -0
  52. package/dist/core/permissionResolver.js.map +1 -0
  53. package/dist/core/permissionResolver.test.js +136 -0
  54. package/dist/core/permissionResolver.test.js.map +1 -0
  55. package/dist/core/providerCatalog.js +240 -0
  56. package/dist/core/providerCatalog.js.map +1 -0
  57. package/dist/core/providerCatalog.test.js +230 -0
  58. package/dist/core/providerCatalog.test.js.map +1 -0
  59. package/dist/core/sessionOrchestrator.js +463 -0
  60. package/dist/core/sessionOrchestrator.js.map +1 -0
  61. package/dist/core/sessionOrchestrator.test.js +344 -0
  62. package/dist/core/sessionOrchestrator.test.js.map +1 -0
  63. package/dist/core/state/schema.js +49 -0
  64. package/dist/core/state/schema.js.map +1 -0
  65. package/dist/core/state/store.js +86 -0
  66. package/dist/core/state/store.js.map +1 -0
  67. package/dist/core/state/store.test.js +99 -0
  68. package/dist/core/state/store.test.js.map +1 -0
  69. package/dist/core/usageService.js +310 -0
  70. package/dist/core/usageService.js.map +1 -0
  71. package/dist/core/usageService.test.js +234 -0
  72. package/dist/core/usageService.test.js.map +1 -0
  73. package/dist/discord/alwaysAllow.test.js +181 -0
  74. package/dist/discord/alwaysAllow.test.js.map +1 -0
  75. package/dist/discord/client.js +666 -0
  76. package/dist/discord/client.js.map +1 -0
  77. package/dist/discord/client.test.js +256 -0
  78. package/dist/discord/client.test.js.map +1 -0
  79. package/dist/discord/configPanel.js +270 -0
  80. package/dist/discord/configPanel.js.map +1 -0
  81. package/dist/discord/configPanel.test.js +332 -0
  82. package/dist/discord/configPanel.test.js.map +1 -0
  83. package/dist/discord/directoryBrowser.js +151 -0
  84. package/dist/discord/directoryBrowser.js.map +1 -0
  85. package/dist/discord/directoryBrowser.test.js +163 -0
  86. package/dist/discord/directoryBrowser.test.js.map +1 -0
  87. package/dist/discord/favorites.js +10 -0
  88. package/dist/discord/favorites.js.map +1 -0
  89. package/dist/discord/fileDownload.js +94 -0
  90. package/dist/discord/fileDownload.js.map +1 -0
  91. package/dist/discord/fileDownload.test.js +59 -0
  92. package/dist/discord/fileDownload.test.js.map +1 -0
  93. package/dist/discord/format.js +104 -0
  94. package/dist/discord/format.js.map +1 -0
  95. package/dist/discord/format.test.js +40 -0
  96. package/dist/discord/format.test.js.map +1 -0
  97. package/dist/discord/guildChannels.js +97 -0
  98. package/dist/discord/guildChannels.js.map +1 -0
  99. package/dist/discord/guildChannels.test.js +231 -0
  100. package/dist/discord/guildChannels.test.js.map +1 -0
  101. package/dist/discord/i18n.js +207 -0
  102. package/dist/discord/i18n.js.map +1 -0
  103. package/dist/discord/i18n.test.js +31 -0
  104. package/dist/discord/i18n.test.js.map +1 -0
  105. package/dist/discord/interactionRouter.js +954 -0
  106. package/dist/discord/interactionRouter.js.map +1 -0
  107. package/dist/discord/interactionRouter.test.js +1245 -0
  108. package/dist/discord/interactionRouter.test.js.map +1 -0
  109. package/dist/discord/messageRouter.js +221 -0
  110. package/dist/discord/messageRouter.js.map +1 -0
  111. package/dist/discord/messageRouter.test.js +360 -0
  112. package/dist/discord/messageRouter.test.js.map +1 -0
  113. package/dist/discord/ports.js +12 -0
  114. package/dist/discord/ports.js.map +1 -0
  115. package/dist/discord/renderers/defaultSet.test.js +97 -0
  116. package/dist/discord/renderers/defaultSet.test.js.map +1 -0
  117. package/dist/discord/renderers/diffView.js +73 -0
  118. package/dist/discord/renderers/diffView.js.map +1 -0
  119. package/dist/discord/renderers/diffView.test.js +54 -0
  120. package/dist/discord/renderers/diffView.test.js.map +1 -0
  121. package/dist/discord/renderers/index.js +143 -0
  122. package/dist/discord/renderers/index.js.map +1 -0
  123. package/dist/discord/renderers/index.test.js +124 -0
  124. package/dist/discord/renderers/index.test.js.map +1 -0
  125. package/dist/discord/renderers/mentionOnComplete.js +19 -0
  126. package/dist/discord/renderers/mentionOnComplete.js.map +1 -0
  127. package/dist/discord/renderers/mentionOnComplete.test.js +35 -0
  128. package/dist/discord/renderers/mentionOnComplete.test.js.map +1 -0
  129. package/dist/discord/renderers/permissionButtons.js +150 -0
  130. package/dist/discord/renderers/permissionButtons.js.map +1 -0
  131. package/dist/discord/renderers/permissionButtons.test.js +108 -0
  132. package/dist/discord/renderers/permissionButtons.test.js.map +1 -0
  133. package/dist/discord/renderers/resultLine.js +25 -0
  134. package/dist/discord/renderers/resultLine.js.map +1 -0
  135. package/dist/discord/renderers/statusEmbed.js +20 -0
  136. package/dist/discord/renderers/statusEmbed.js.map +1 -0
  137. package/dist/discord/renderers/statusEmbed.test.js +32 -0
  138. package/dist/discord/renderers/statusEmbed.test.js.map +1 -0
  139. package/dist/discord/renderers/streamEmbed.js +134 -0
  140. package/dist/discord/renderers/streamEmbed.js.map +1 -0
  141. package/dist/discord/renderers/streamEmbed.test.js +97 -0
  142. package/dist/discord/renderers/streamEmbed.test.js.map +1 -0
  143. package/dist/discord/renderers/toolThread.js +65 -0
  144. package/dist/discord/renderers/toolThread.js.map +1 -0
  145. package/dist/discord/renderers/toolThread.test.js +54 -0
  146. package/dist/discord/renderers/toolThread.test.js.map +1 -0
  147. package/dist/discord/renderers/transcriptFeed.js +33 -0
  148. package/dist/discord/renderers/transcriptFeed.js.map +1 -0
  149. package/dist/discord/renderers/usageEmbed.js +78 -0
  150. package/dist/discord/renderers/usageEmbed.js.map +1 -0
  151. package/dist/discord/renderers/usageEmbed.test.js +42 -0
  152. package/dist/discord/renderers/usageEmbed.test.js.map +1 -0
  153. package/dist/discord/wiring.js +214 -0
  154. package/dist/discord/wiring.js.map +1 -0
  155. package/dist/discord/wiring.test.js +252 -0
  156. package/dist/discord/wiring.test.js.map +1 -0
  157. package/dist/discord/wizard/channelWizard.js +305 -0
  158. package/dist/discord/wizard/channelWizard.js.map +1 -0
  159. package/dist/discord/wizard/channelWizard.test.js +298 -0
  160. package/dist/discord/wizard/channelWizard.test.js.map +1 -0
  161. package/dist/discord/wizard/resumeWizard.js +123 -0
  162. package/dist/discord/wizard/resumeWizard.js.map +1 -0
  163. package/dist/modes/claude/index.js +80 -0
  164. package/dist/modes/claude/index.js.map +1 -0
  165. package/dist/modes/claude/listResumable.test.js +72 -0
  166. package/dist/modes/claude/listResumable.test.js.map +1 -0
  167. package/dist/modes/claude/mcpFileTool.js +82 -0
  168. package/dist/modes/claude/mcpFileTool.js.map +1 -0
  169. package/dist/modes/claude/permissions.js +35 -0
  170. package/dist/modes/claude/permissions.js.map +1 -0
  171. package/dist/modes/claude/plugins.js +56 -0
  172. package/dist/modes/claude/plugins.js.map +1 -0
  173. package/dist/modes/claude/session.js +324 -0
  174. package/dist/modes/claude/session.js.map +1 -0
  175. package/dist/modes/claude/session.test.js +415 -0
  176. package/dist/modes/claude/session.test.js.map +1 -0
  177. package/dist/modes/codex/discovery.js +221 -0
  178. package/dist/modes/codex/discovery.js.map +1 -0
  179. package/dist/modes/codex/discovery.test.js +213 -0
  180. package/dist/modes/codex/discovery.test.js.map +1 -0
  181. package/dist/modes/codex/eventMapper.js +262 -0
  182. package/dist/modes/codex/eventMapper.js.map +1 -0
  183. package/dist/modes/codex/index.js +132 -0
  184. package/dist/modes/codex/index.js.map +1 -0
  185. package/dist/modes/codex/index.test.js +170 -0
  186. package/dist/modes/codex/index.test.js.map +1 -0
  187. package/dist/modes/codex/runner.js +207 -0
  188. package/dist/modes/codex/runner.js.map +1 -0
  189. package/dist/modes/codex/runner.test.js +587 -0
  190. package/dist/modes/codex/runner.test.js.map +1 -0
  191. package/dist/modes/codex/sqliteReader.js +171 -0
  192. package/dist/modes/codex/sqliteReader.js.map +1 -0
  193. package/dist/modes/codex/sqliteReader.test.js +137 -0
  194. package/dist/modes/codex/sqliteReader.test.js.map +1 -0
  195. package/dist/setup/wizard.js +115 -0
  196. package/dist/setup/wizard.js.map +1 -0
  197. package/dist/setup/wizard.test.js +216 -0
  198. package/dist/setup/wizard.test.js.map +1 -0
  199. package/dist/startBot.test.js +78 -0
  200. package/dist/startBot.test.js.map +1 -0
  201. 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":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9D,OAAO,EACL,eAAe,EACf,+BAA+B,EAC/B,cAAc,EACd,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,uBAAuB,EACvB,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,uBAAuB,GAExB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAExD,sFAAsF;AACtF,oFAAoF;AACpF,4BAA4B;AAE5B,oFAAoF;AACpF,mFAAmF;AACnF,wCAAwC;AACxC,SAAS,WAAW,CAAC,SAAqC,EAAE,OAAoB;IAC9E,MAAM,KAAK,GAAG,EAAE,eAAe,EAAE,CAAC,EAAE,CAAC;IACrC,MAAM,OAAO,GAAG,CAAC,GAAG,EAAE;QACpB,MAAM,GAAG,GAAG,CAAC,KAAK,SAAS,CAAC;YAC1B,sDAAsD;QACxD,CAAC,CAAC,EAAE,CAAC;QACL,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE;YACxB,eAAe,EAAE,GAAG,EAAE;gBACpB,KAAK,CAAC,eAAe,IAAI,CAAC,CAAC;gBAC3B,OAAO,SAAS,EAAE,CAAC;YACrB,CAAC;YACD,KAAK,EAAE,GAAG,EAAE;gBACV,OAAO,EAAE,EAAE,CAAC;YACd,CAAC;SACF,CAAC,CAAC;IACL,CAAC,CAAuB,CAAC;IACzB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC5B,CAAC;AAED,SAAS,KAAK,CAAC,KAAa,EAAE,WAAmB;IAC/C,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,GAAG,WAAW,QAAQ,EAAE,CAAC;AACrE,CAAC;AAED,UAAU,CAAC,GAAG,EAAE;IACd,uBAAuB,EAAE,CAAC;AAC5B,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,uCAAuC,EAAE,GAAG,EAAE;IACrD,EAAE,CAAC,+EAA+E,EAAE,KAAK,IAAI,EAAE;QAC7F,MAAM,EAAE,OAAO,EAAE,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE,CAAC;YAC1C,KAAK,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;YAC3C,KAAK,CAAC,mBAAmB,EAAE,mBAAmB,CAAC;SAChD,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;QACnD,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC;YACtB,EAAE,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE,iBAAiB,EAAE;YACtD,EAAE,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,mBAAmB,EAAE;SAC3D,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,EAAE,OAAO,EAAE,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;YACzC,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACtB,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,KAAI,CAAC,EAAE,IAAI,KAAI,CAAC,EAAE,KAAK,KAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QACxG,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC;YACtB,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;YAChC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;YACpC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;SACnC,CAAC,CAAC;QACH,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,qBAAqB,CAAC,CAAC,CAAC;QACxE,iDAAiD;QACjD,MAAM,CAAC,KAAK,CAAC,CAAC,oBAAoB,EAAE,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;QAC3F,uEAAuE;QACvE,MAAM,EAAE,OAAO,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,OAAO,CAAc,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,CAAC;QAC1E,EAAE,CAAC,aAAa,EAAE,CAAC;QACnB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;YAC7C,MAAM,EAAE,CAAC,wBAAwB,CAAC,KAAK,CAAC,CAAC;YACzC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC;YAC9B,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,qBAAqB,CAAC,CAAC,CAAC;QAC1E,CAAC;gBAAS,CAAC;YACT,EAAE,CAAC,aAAa,EAAE,CAAC;QACrB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;QACnF,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;QAClG,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;QAClD,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC9B,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC3E,8EAA8E;QAC9E,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;YAChD,OAAO,IAAI,CAAC,CAAC;YACb,IAAI,OAAO,KAAK,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;YAC9C,OAAO,CAAC,KAAK,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;QACjD,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,qBAAqB,CAAC,CAAC,CAAC;QACtE,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;QAClD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAC,CAAC;QACjF,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACrD,MAAM,OAAO,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACxB,MAAM,EAAE,OAAO,EAAE,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACpG,MAAM,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;QACnC,MAAM,CAAC,OAAO,CAAC,CAAC,oBAAoB,EAAE,CAAC;IACzC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,gDAAgD,EAAE,GAAG,EAAE;IAC9D,EAAE,CAAC,gFAAgF,EAAE,KAAK,IAAI,EAAE;QAC9F,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;QAClG,MAAM,SAAS,GAAG,+BAA+B,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;QAC/D,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,qBAAqB,CAAC,CAAC,CAAC;QAC1E,kFAAkF;QAClF,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9D,MAAM,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,mCAAmC;QACvE,MAAM,MAAM,GAAG,+BAA+B,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;QAC5D,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAC,CAAC;IACnF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,qDAAqD,EAAE,GAAG,EAAE;IACnE,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACxE,MAAM,CAAC,CAAC,GAAG,uBAAuB,CAAC,CAAC,CAAC,OAAO,CAAC;YAC3C,SAAS;YACT,aAAa;YACb,mBAAmB;YACnB,MAAM;YACN,SAAS;YACT,MAAM;SACP,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;QAChD,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,uBAAuB,CAAC,CAAC,CAAC;QAC1E,wEAAwE;QACxE,MAAM,CAAC,mBAAmB,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;QAC9F,MAAM,MAAM,GAAG,OAAO,CAAC;QACvB,KAAK,MAAM,CAAC,IAAI,OAAO;YAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,CAAC,CAAC,GAAG,sBAAsB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,CAAC,CAAC,CAAC;QACrG,MAAM,KAAK,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACjE,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACvC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,KAAK,MAAM,IAAI,IAAI,uBAAuB,EAAE,CAAC;YAC3C,MAAM,CAAC,cAAc,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,KAAK,MAAM,IAAI,IAAI,sBAAsB,EAAE,CAAC;YAC1C,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;YAChC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QACzC,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,uDAAuD,EAAE,GAAG,EAAE;IACrE,EAAE,CAAC,oGAAoG,EAAE,GAAG,EAAE;QAC5G,MAAM,OAAO,GAAG,cAAc,CAAC,EAAE,CAAC,CAAC;QACnC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC;YACtB,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;YACtC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;YACtC,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,cAAc,EAAE;YAChD,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,eAAe,EAAE;SACnD,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,OAAO,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;QAC1C,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QACnE,8DAA8D;QAC9D,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACrE,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yGAAyG,EAAE,GAAG,EAAE;QACjH,MAAM,OAAO,GAAG,cAAc,CAAC,eAAe,CAAC,CAAC;QAChD,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAChD,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,4DAA4D,EAAE,GAAG,EAAE;IAC1E,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACvE,MAAM,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,iBAAiB,EAAE,oBAAoB,CAAC,CAAC,CAAC;IACnG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+EAA+E,EAAE,GAAG,EAAE;QACvF,MAAM,CAAC,kBAAkB,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzD,MAAM,CAAC,kBAAkB,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5D,MAAM,CAAC,kBAAkB,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtD,MAAM,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,GAAG,EAAE;QACrF,MAAM,OAAO,GAAG,mBAAmB,EAAE,CAAC;QACtC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,iBAAiB,EAAE,oBAAoB,CAAC,CAAC,CAAC;QACpG,MAAM,MAAM,GAAG,OAAO,CAAC;QACvB,KAAK,MAAM,CAAC,IAAI,OAAO;YAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,iBAAiB,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;IACjH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qFAAqF,EAAE,GAAG,EAAE;QAC7F,MAAM,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC;QAC5F,MAAM,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,uBAAuB,CAAC,CAAC,CAAC;IACnG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8EAA8E,EAAE,GAAG,EAAE;QACtF,MAAM,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,8BAA8B,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;QACrG,MAAM,CAAC,YAAY,CAAC,iBAAiB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,8BAA8B,EAAE,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC;QACjH,mEAAmE;QACnE,MAAM,CAAC,YAAY,CAAC,oBAAoB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,4CAA4C,CAAC,CAAC,CAAC;QACnG,KAAK,MAAM,CAAC,IAAI,mBAAmB,EAAE,CAAC;YACpC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAC5C,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,wCAAwC,EAAE,GAAG,EAAE;IACtD,EAAE,CAAC,+EAA+E,EAAE,GAAG,EAAE;QACvF,MAAM,CAAC,CAAC,GAAG,oBAAoB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;QACrF,MAAM,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACxE,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,oBAAoB,CAAC,CAAC,CAAC;QAC1F,MAAM,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC;IAC1F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kFAAkF,EAAE,GAAG,EAAE;QAC1F,MAAM,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;QACvE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;QACxE,oDAAoD;QACpD,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC;IACnG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}