@minniexcode/codex-switch 0.0.6 → 0.0.8

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 (53) hide show
  1. package/README.AI.md +5 -2
  2. package/README.md +12 -6
  3. package/dist/app/add-provider.js +90 -5
  4. package/dist/app/edit-provider.js +39 -11
  5. package/dist/app/get-status.js +31 -1
  6. package/dist/app/init-codex.js +68 -0
  7. package/dist/app/list-providers.js +1 -0
  8. package/dist/app/run-doctor.js +96 -1
  9. package/dist/app/setup-codex.js +18 -9
  10. package/dist/app/show-config.js +9 -1
  11. package/dist/app/switch-provider.js +61 -8
  12. package/dist/cli/add-interactive.js +4 -2
  13. package/dist/cli/args.js +3 -0
  14. package/dist/cli/help.js +3 -0
  15. package/dist/cli/interactive.js +3 -0
  16. package/dist/cli/output.js +20 -5
  17. package/dist/cli/prompt.js +3 -0
  18. package/dist/cli.js +1 -1
  19. package/dist/commands/handlers.js +107 -13
  20. package/dist/commands/help.js +2 -1
  21. package/dist/commands/registry.js +87 -15
  22. package/dist/domain/config.js +137 -0
  23. package/dist/domain/providers.js +90 -2
  24. package/dist/domain/setup.js +1 -0
  25. package/dist/infra/backup-repo.js +3 -0
  26. package/dist/infra/codex-cli.js +3 -0
  27. package/dist/infra/codex-paths.js +3 -0
  28. package/dist/infra/fs-utils.js +3 -0
  29. package/dist/infra/lock-repo.js +3 -0
  30. package/dist/infra/providers-repo.js +3 -0
  31. package/dist/interaction/add-interactive.js +9 -18
  32. package/dist/interaction/interactive.js +84 -11
  33. package/dist/runtime/codex-probe.js +7 -0
  34. package/dist/runtime/copilot-adapter.js +173 -0
  35. package/dist/runtime/copilot-bridge-worker.js +25 -0
  36. package/dist/runtime/copilot-bridge.js +433 -0
  37. package/dist/runtime/copilot-installer.js +125 -0
  38. package/dist/runtime/copilot-sdk-loader.js +59 -0
  39. package/dist/storage/auth-repo.js +160 -0
  40. package/dist/storage/config-repo.js +58 -0
  41. package/dist/storage/fs-utils.js +3 -0
  42. package/dist/storage/runtime-state-repo.js +80 -0
  43. package/docs/Design/codex-switch-v0.0.7-design.md +862 -0
  44. package/docs/Design/codex-switch-v0.0.8-design.md +132 -0
  45. package/docs/Design/codex-switch-v0.0.9-to-v0.0.12-roadmap.md +413 -0
  46. package/docs/PRD/codex-switch-prd-v0.0.5-to-v0.1.0.md +131 -25
  47. package/docs/PRD/codex-switch-prd-v0.0.8.md +62 -0
  48. package/docs/Reference/codex-config-reference.md +604 -0
  49. package/docs/Reference/codex-config-reference.zh-CN.md +633 -0
  50. package/docs/cli-usage.md +77 -29
  51. package/docs/test-report-0.0.7.md +118 -0
  52. package/docs/testing.md +67 -47
  53. package/package.json +1 -1
@@ -4,13 +4,12 @@ exports.COMMON_TAG_CHOICES = void 0;
4
4
  exports.collectAddInput = collectAddInput;
5
5
  exports.createNonInteractiveAddError = createNonInteractiveAddError;
6
6
  exports.promptTags = promptTags;
7
- exports.parseTags = parseTags;
8
7
  const errors_1 = require("../domain/errors");
9
8
  exports.COMMON_TAG_CHOICES = ["free", "paid", "daily", "backup"];
10
9
  /**
11
10
  * Collects add command inputs interactively when required values are missing.
12
11
  */
13
- async function collectAddInput(runtime, defaults, providerExists) {
12
+ async function collectAddInput(runtime, defaults, providerExists, profileExists) {
14
13
  runtime.writeLine("Interactive add mode");
15
14
  runtime.writeLine("Provide the missing required fields. Press Enter to skip optional fields.");
16
15
  const providerName = defaults.providerName
@@ -20,13 +19,19 @@ async function collectAddInput(runtime, defaults, providerExists) {
20
19
  const apiKey = defaults.apiKey
21
20
  ? normalizeRequiredValue(defaults.apiKey)
22
21
  : await promptConfirmedSecret(runtime, "API key", "Confirm API key");
23
- const baseUrl = defaults.baseUrl ?? normalizeOptionalValue(await runtime.inputText("Base URL (optional)"));
22
+ const createProfile = !profileExists(profile);
23
+ const model = createProfile ? await promptRequiredValue(runtime, `Model for new profile "${profile}"`) : null;
24
+ const baseUrl = createProfile
25
+ ? (defaults.baseUrl ? normalizeRequiredValue(defaults.baseUrl) : await promptRequiredValue(runtime, `Base URL for new profile "${profile}"`))
26
+ : defaults.baseUrl ?? normalizeOptionalValue(await runtime.inputText("Base URL (optional)"));
24
27
  const note = defaults.note ?? normalizeOptionalValue(await runtime.inputText("Note (optional)"));
25
28
  const tags = defaults.tags.length > 0 ? defaults.tags : await promptTags(runtime);
26
29
  return {
27
30
  providerName,
28
31
  profile,
29
32
  apiKey,
33
+ createProfile,
34
+ model,
30
35
  baseUrl,
31
36
  note,
32
37
  tags,
@@ -87,22 +92,8 @@ function normalizeOptionalValue(value) {
87
92
  }
88
93
  async function promptTags(runtime, defaults = []) {
89
94
  const defaultPresetTags = defaults.filter(isCommonTag);
90
- const defaultCustomTags = defaults.filter((tag) => !isCommonTag(tag));
91
- const presetTags = await runtime.selectMany("Select tags (optional)", exports.COMMON_TAG_CHOICES.map((tag) => ({ value: tag, label: tag })), { defaultValues: defaultPresetTags });
92
- const customTags = parseTags(await runtime.inputText("Custom tags (optional, comma-separated)", {
93
- defaultValue: defaultCustomTags.join(", "),
94
- }));
95
- return dedupeTags([...presetTags, ...customTags]);
96
- }
97
- function parseTags(value) {
98
- return dedupeTags(value
99
- .split(",")
100
- .map((tag) => tag.trim())
101
- .filter((tag) => tag.length > 0));
95
+ return runtime.selectMany("Select tags (optional)", exports.COMMON_TAG_CHOICES.map((tag) => ({ value: tag, label: tag })), { defaultValues: defaultPresetTags });
102
96
  }
103
97
  function isCommonTag(tag) {
104
98
  return exports.COMMON_TAG_CHOICES.includes(tag);
105
99
  }
106
- function dedupeTags(tags) {
107
- return Array.from(new Set(tags));
108
- }
@@ -44,6 +44,7 @@ exports.getRollbackSummaryById = getRollbackSummaryById;
44
44
  exports.confirmRollback = confirmRollback;
45
45
  exports.chooseSetupStrategy = chooseSetupStrategy;
46
46
  exports.chooseCodexDir = chooseCodexDir;
47
+ exports.confirmCreateCodexDir = confirmCreateCodexDir;
47
48
  exports.chooseSetupProfiles = chooseSetupProfiles;
48
49
  exports.collectSetupProviderDetails = collectSetupProviderDetails;
49
50
  exports.collectEditInput = collectEditInput;
@@ -61,6 +62,9 @@ const add_interactive_1 = require("./add-interactive");
61
62
  function canPrompt(runtime, jsonMode) {
62
63
  return !jsonMode && runtime.isInteractive();
63
64
  }
65
+ /**
66
+ * Prompts the user to choose one configured provider when a command omitted its target.
67
+ */
64
68
  async function promptForProviderSelection(runtime, providersPath, message) {
65
69
  const providers = (0, providers_repo_1.readProvidersFile)(providersPath);
66
70
  const choices = Object.entries(providers.providers)
@@ -75,6 +79,9 @@ async function promptForProviderSelection(runtime, providersPath, message) {
75
79
  }
76
80
  return runtime.selectOne(message, choices);
77
81
  }
82
+ /**
83
+ * Confirms destructive provider removal and turns a declined prompt into a typed cancellation.
84
+ */
78
85
  async function confirmProviderRemoval(runtime, providerName) {
79
86
  const confirmed = await runtime.confirmAction(`Remove provider "${providerName}"?`, {
80
87
  defaultValue: false,
@@ -83,6 +90,9 @@ async function confirmProviderRemoval(runtime, providerName) {
83
90
  throw (0, errors_1.cliError)("PROMPT_CANCELLED", `Removal cancelled for provider "${providerName}".`);
84
91
  }
85
92
  }
93
+ /**
94
+ * Confirms provider import semantics, including whether the file will merge or replace the registry.
95
+ */
86
96
  async function confirmImport(runtime, sourceFile, merge = false) {
87
97
  const confirmed = await runtime.confirmAction(merge
88
98
  ? `Import providers from ${path.resolve(sourceFile)} and merge into the current registry?`
@@ -91,22 +101,37 @@ async function confirmImport(runtime, sourceFile, merge = false) {
91
101
  throw (0, errors_1.cliError)("PROMPT_CANCELLED", "Import cancelled.");
92
102
  }
93
103
  }
104
+ /**
105
+ * Confirms whether an existing export target may be overwritten.
106
+ */
94
107
  async function confirmExportOverwrite(runtime, targetFile) {
95
108
  return runtime.confirmAction(`Overwrite existing export target ${path.resolve(targetFile)}?`, {
96
109
  defaultValue: false,
97
110
  });
98
111
  }
112
+ /**
113
+ * Resolves whether the export target already exists after normalizing to an absolute path.
114
+ */
99
115
  function exportTargetExists(targetFile) {
100
116
  return fs.existsSync(path.resolve(targetFile));
101
117
  }
118
+ /**
119
+ * Builds a rollback preview for the latest managed backup.
120
+ */
102
121
  function getRollbackSummary(latestBackupPath) {
103
122
  const manifest = (0, backup_repo_1.loadLatestManifest)(latestBackupPath);
104
123
  return buildRollbackSummary(manifest);
105
124
  }
125
+ /**
126
+ * Builds a rollback preview for one explicit backup id.
127
+ */
106
128
  function getRollbackSummaryById(backupsDir, backupId) {
107
129
  const manifest = (0, backup_repo_1.loadManifestById)(backupsDir, backupId);
108
130
  return buildRollbackSummary(manifest);
109
131
  }
132
+ /**
133
+ * Converts a backup manifest into the human preview shown before rollback confirmation.
134
+ */
110
135
  function buildRollbackSummary(manifest) {
111
136
  const previewLines = [
112
137
  "Rollback preview",
@@ -119,6 +144,9 @@ function buildRollbackSummary(manifest) {
119
144
  ];
120
145
  return { manifest, previewLines };
121
146
  }
147
+ /**
148
+ * Prints the rollback preview and requires explicit confirmation before restore proceeds.
149
+ */
122
150
  async function confirmRollback(runtime, latestBackupPath, backupsDir, backupId) {
123
151
  const { previewLines } = backupId && backupsDir
124
152
  ? getRollbackSummaryById(backupsDir, backupId)
@@ -133,13 +161,19 @@ async function confirmRollback(runtime, latestBackupPath, backupsDir, backupId)
133
161
  throw (0, errors_1.cliError)("PROMPT_CANCELLED", "Rollback cancelled.");
134
162
  }
135
163
  }
164
+ /**
165
+ * Prompts for setup merge strategy when providers.json already exists.
166
+ */
136
167
  async function chooseSetupStrategy(runtime) {
137
- return runtime.selectOne("providers.json already exists. Choose a setup strategy.", [
168
+ return runtime.selectOne("providers.json already exists. Choose a migrate strategy.", [
138
169
  { value: "merge", label: "merge", hint: "keep existing providers and override by imported names" },
139
170
  { value: "overwrite", label: "overwrite", hint: "replace the existing registry" },
140
- { value: "cancel", label: "cancel", hint: "abort setup without writing" },
171
+ { value: "cancel", label: "cancel", hint: "abort migrate without writing" },
141
172
  ]);
142
173
  }
174
+ /**
175
+ * Resolves the Codex directory from discovered candidates or a manually entered path.
176
+ */
143
177
  async function chooseCodexDir(runtime, candidates) {
144
178
  if (candidates.length === 0) {
145
179
  const manual = (await runtime.inputText("Codex directory path")).trim();
@@ -170,6 +204,17 @@ async function chooseCodexDir(runtime, candidates) {
170
204
  }
171
205
  return (0, codex_paths_1.resolveCodexDir)(manual);
172
206
  }
207
+ /**
208
+ * Confirms whether a missing Codex directory should be created during init.
209
+ */
210
+ async function confirmCreateCodexDir(runtime, codexDir) {
211
+ return runtime.confirmAction(`Create missing Codex directory ${codexDir}?`, {
212
+ defaultValue: false,
213
+ });
214
+ }
215
+ /**
216
+ * Lets setup adopt a subset of unmanaged config profiles into providers.json.
217
+ */
173
218
  async function chooseSetupProfiles(runtime, profiles) {
174
219
  if (profiles.length === 0) {
175
220
  return [];
@@ -177,29 +222,57 @@ async function chooseSetupProfiles(runtime, profiles) {
177
222
  return runtime.selectMany("Choose unmanaged config profiles to adopt into providers.json.", profiles.map((profile) => ({
178
223
  value: profile.name,
179
224
  label: profile.name,
180
- hint: `${profile.model} | ${profile.baseUrl}`,
225
+ hint: `${profile.model} | ${profile.baseUrl} | ${profile.envKey}`,
181
226
  })));
182
227
  }
183
- async function collectSetupProviderDetails(runtime, profiles) {
228
+ /**
229
+ * Collects provider metadata for each adopted config profile during setup.
230
+ */
231
+ async function collectSetupProviderDetails(runtime, profiles, defaultsByProfile = {}) {
184
232
  const result = {};
185
233
  for (const profile of profiles) {
234
+ const defaults = defaultsByProfile[profile] ?? {};
186
235
  const providerName = (await runtime.inputText(`Provider name for profile "${profile}"`, {
187
- defaultValue: profile,
236
+ defaultValue: defaults.providerName ?? profile,
237
+ })).trim();
238
+ if (defaults.envKey) {
239
+ runtime.writeLine(`Runtime env key for "${profile}": ${defaults.envKey}`);
240
+ }
241
+ const apiKey = await promptRequiredSecret(runtime, `API key for profile "${profile}"`, defaults.apiKey?.trim() || undefined);
242
+ const baseUrl = (await runtime.inputText(`Base URL note for profile "${profile}" (optional)`, {
243
+ defaultValue: defaults.baseUrl ?? "",
244
+ })).trim();
245
+ const note = (await runtime.inputText(`Note for profile "${profile}" (optional)`, {
246
+ defaultValue: defaults.note ?? "",
188
247
  })).trim();
189
- const apiKey = (await runtime.inputSecret(`API key for profile "${profile}"`)).trim();
190
- const baseUrl = (await runtime.inputText(`Base URL for profile "${profile}" (optional)`)).trim();
191
- const note = (await runtime.inputText(`Note for profile "${profile}" (optional)`)).trim();
192
248
  const tags = await (0, add_interactive_1.promptTags)(runtime);
193
249
  result[profile] = {
194
- providerName: providerName || profile,
250
+ providerName: providerName || defaults.providerName || profile,
195
251
  apiKey,
196
- baseUrl: baseUrl || undefined,
197
- note: note || undefined,
252
+ envKey: defaults.envKey,
253
+ baseUrl: baseUrl || defaults.baseUrl || undefined,
254
+ note: note || defaults.note || undefined,
255
+ // Empty selections are omitted so downstream setup validation can distinguish unset from explicit data.
198
256
  tags: tags.length > 0 ? tags : undefined,
199
257
  };
200
258
  }
201
259
  return result;
202
260
  }
261
+ /**
262
+ * Re-prompts until a required secret value is provided, optionally falling back to a non-empty default.
263
+ */
264
+ async function promptRequiredSecret(runtime, label, defaultValue) {
265
+ while (true) {
266
+ const value = (await runtime.inputSecret(label)).trim() || defaultValue || "";
267
+ if (value.length > 0) {
268
+ return value;
269
+ }
270
+ runtime.writeLine(`${label} is required.`);
271
+ }
272
+ }
273
+ /**
274
+ * Collects editable provider fields, preserving current values when prompts are left blank.
275
+ */
203
276
  async function collectEditInput(runtime, current) {
204
277
  const profile = (await runtime.inputText("Profile", { defaultValue: current.profile })).trim();
205
278
  const apiKey = (await runtime.inputSecret("API key")).trim() || current.apiKey;
@@ -3,6 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.codexRuntimeProbe = void 0;
4
4
  exports.probeCodexRuntime = probeCodexRuntime;
5
5
  const codex_cli_1 = require("./codex-cli");
6
+ /**
7
+ * Default dependency probe implementation for the local codex CLI runtime.
8
+ */
6
9
  exports.codexRuntimeProbe = {
7
10
  probe(options) {
8
11
  if (options?.minVersion) {
@@ -11,6 +14,9 @@ exports.codexRuntimeProbe = {
11
14
  return probeCodexRuntime();
12
15
  },
13
16
  };
17
+ /**
18
+ * Checks whether the codex CLI is installed and, optionally, satisfies a minimum version.
19
+ */
14
20
  function probeCodexRuntime(minVersion) {
15
21
  const availability = (0, codex_cli_1.checkCodexAvailable)();
16
22
  if (!availability.ok) {
@@ -31,6 +37,7 @@ function probeCodexRuntime(minVersion) {
31
37
  };
32
38
  }
33
39
  if (minVersion) {
40
+ // Reuse the dedicated semver check so doctor and setup report the same unsupported-version behavior.
34
41
  const versionCheck = (0, codex_cli_1.checkCodexVersion)(minVersion);
35
42
  if (!versionCheck.ok) {
36
43
  return {
@@ -0,0 +1,173 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.probeCopilotSdkRuntime = probeCopilotSdkRuntime;
4
+ exports.requireCopilotSdk = requireCopilotSdk;
5
+ exports.readCopilotAuthState = readCopilotAuthState;
6
+ exports.sendCopilotChatCompletion = sendCopilotChatCompletion;
7
+ const errors_1 = require("../domain/errors");
8
+ const copilot_sdk_loader_1 = require("./copilot-sdk-loader");
9
+ const copilot_installer_1 = require("./copilot-installer");
10
+ /**
11
+ * Probes whether the optional Copilot SDK runtime is installed and loadable.
12
+ */
13
+ function probeCopilotSdkRuntime() {
14
+ const status = (0, copilot_installer_1.probeCopilotSdkInstall)();
15
+ if (!status.installed) {
16
+ return {
17
+ ok: false,
18
+ runtime: "copilot-sdk",
19
+ reason: "missing",
20
+ cause: "The optional Copilot SDK runtime is not installed.",
21
+ details: {
22
+ installDir: status.installDir,
23
+ packageName: status.packageName,
24
+ },
25
+ };
26
+ }
27
+ return {
28
+ ok: true,
29
+ runtime: "copilot-sdk",
30
+ version: status.packageVersion ?? undefined,
31
+ details: {
32
+ installDir: status.installDir,
33
+ packageName: status.packageName,
34
+ },
35
+ };
36
+ }
37
+ /**
38
+ * Loads the lazily installed Copilot SDK and returns the module.
39
+ */
40
+ async function requireCopilotSdk() {
41
+ return (0, copilot_sdk_loader_1.loadCopilotSdk)();
42
+ }
43
+ /**
44
+ * Probes whether the lazily installed Copilot SDK can create a usable session.
45
+ */
46
+ async function readCopilotAuthState() {
47
+ const runtime = probeCopilotSdkRuntime();
48
+ if (!runtime.ok) {
49
+ throw (0, errors_1.cliError)("COPILOT_SDK_MISSING", "The optional Copilot SDK runtime is not installed.", runtime.details);
50
+ }
51
+ const { client, session } = await createCopilotSession();
52
+ await stopCopilotClient(client);
53
+ return {
54
+ ready: Boolean(session),
55
+ source: "official-sdk",
56
+ mode: "session",
57
+ };
58
+ }
59
+ /**
60
+ * Executes a single chat-completions style request through the optional Copilot SDK when available.
61
+ */
62
+ async function sendCopilotChatCompletion(args) {
63
+ const { client, session, sdk } = await createCopilotSession();
64
+ try {
65
+ const sendAndWait = resolveCallable(session, "sendAndWait") ?? resolveCallable(sdk, "sendAndWait");
66
+ if (!sendAndWait) {
67
+ throw (0, errors_1.cliError)("COPILOT_SDK_UNSUPPORTED", "The installed Copilot SDK does not expose a supported sendAndWait API.", {
68
+ provider: args.provider,
69
+ });
70
+ }
71
+ const prompt = Array.isArray(args.payload.messages)
72
+ ? args.payload.messages
73
+ .map((entry) => {
74
+ const message = entry;
75
+ return `${String(message.role ?? "user")}: ${String(message.content ?? "")}`;
76
+ })
77
+ .join("\n")
78
+ : "";
79
+ const result = await Promise.resolve(sendAndWait({ model: args.payload.model, prompt }));
80
+ const content = typeof result === "string"
81
+ ? result
82
+ : typeof result?.content === "string"
83
+ ? String(result.content)
84
+ : typeof result?.data === "object" &&
85
+ typeof result.data.content === "string"
86
+ ? String(result.data.content)
87
+ : JSON.stringify(result);
88
+ return {
89
+ id: `copilot-${Date.now()}`,
90
+ object: "chat.completion",
91
+ created: Math.floor(Date.now() / 1000),
92
+ model: args.payload.model ?? "copilot",
93
+ choices: [
94
+ {
95
+ index: 0,
96
+ message: {
97
+ role: "assistant",
98
+ content,
99
+ },
100
+ finish_reason: "stop",
101
+ },
102
+ ],
103
+ };
104
+ }
105
+ finally {
106
+ await stopCopilotClient(client);
107
+ }
108
+ }
109
+ async function createCopilotSession() {
110
+ const sdk = (await requireCopilotSdk());
111
+ const client = createCopilotClient(sdk);
112
+ const createSession = resolveCallable(client ? client : null, "createSession") ?? resolveCallable(sdk, "createSession");
113
+ if (!createSession) {
114
+ throw (0, errors_1.cliError)("COPILOT_SDK_UNSUPPORTED", "The installed Copilot SDK does not expose a supported createSession API.", {});
115
+ }
116
+ try {
117
+ const session = (await Promise.resolve(createSession({})));
118
+ return {
119
+ sdk,
120
+ client,
121
+ session,
122
+ };
123
+ }
124
+ catch (error) {
125
+ throw (0, errors_1.cliError)("COPILOT_AUTH_REQUIRED", "Copilot authentication is required before the local bridge can be used.", {
126
+ cause: error instanceof Error ? error.message : String(error),
127
+ });
128
+ }
129
+ }
130
+ function createCopilotClient(sdk) {
131
+ const ClientCtor = resolveConstructor(sdk, "CopilotClient");
132
+ if (!ClientCtor) {
133
+ return null;
134
+ }
135
+ try {
136
+ return new ClientCtor();
137
+ }
138
+ catch (error) {
139
+ throw (0, errors_1.cliError)("COPILOT_SDK_UNSUPPORTED", "The installed Copilot SDK CopilotClient could not be constructed.", {
140
+ cause: error instanceof Error ? error.message : String(error),
141
+ });
142
+ }
143
+ }
144
+ async function stopCopilotClient(client) {
145
+ if (client && typeof client.stop === "function") {
146
+ await Promise.resolve(client.stop());
147
+ }
148
+ }
149
+ function resolveCallable(target, name) {
150
+ if (!target) {
151
+ return null;
152
+ }
153
+ const direct = target[name];
154
+ if (typeof direct === "function") {
155
+ return direct;
156
+ }
157
+ const nestedDefault = target.default;
158
+ if (nestedDefault && typeof nestedDefault[name] === "function") {
159
+ return nestedDefault[name];
160
+ }
161
+ return null;
162
+ }
163
+ function resolveConstructor(target, name) {
164
+ const direct = target[name];
165
+ if (typeof direct === "function") {
166
+ return direct;
167
+ }
168
+ const nestedDefault = target.default;
169
+ if (nestedDefault && typeof nestedDefault[name] === "function") {
170
+ return nestedDefault[name];
171
+ }
172
+ return null;
173
+ }
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const copilot_bridge_1 = require("./copilot-bridge");
4
+ const copilot_adapter_1 = require("./copilot-adapter");
5
+ async function main() {
6
+ const provider = process.env.CODEX_SWITCH_BRIDGE_PROVIDER ?? "copilot";
7
+ const host = process.env.CODEX_SWITCH_BRIDGE_HOST ?? "127.0.0.1";
8
+ const port = Number(process.env.CODEX_SWITCH_BRIDGE_PORT ?? "4141");
9
+ const apiKey = process.env.CODEX_SWITCH_BRIDGE_API_KEY ?? "";
10
+ await (0, copilot_bridge_1.startCopilotBridgeServer)({
11
+ host,
12
+ port,
13
+ apiKey,
14
+ executeChatCompletion: async (payload) => (0, copilot_adapter_1.sendCopilotChatCompletion)({
15
+ provider,
16
+ payload,
17
+ }),
18
+ });
19
+ }
20
+ if (require.main === module) {
21
+ void main().catch((error) => {
22
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
23
+ process.exit(1);
24
+ });
25
+ }