@tvps/agw-client-cli 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/dist/fs.js ADDED
@@ -0,0 +1,123 @@
1
+ import crypto from "node:crypto";
2
+ import fs from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { backupPath } from "./paths.js";
5
+ export async function pathExists(target) {
6
+ try {
7
+ await fs.access(target);
8
+ return true;
9
+ }
10
+ catch {
11
+ return false;
12
+ }
13
+ }
14
+ export async function readIfExists(target) {
15
+ try {
16
+ return await fs.readFile(target, "utf8");
17
+ }
18
+ catch (err) {
19
+ if (err.code === "ENOENT")
20
+ return null;
21
+ throw err;
22
+ }
23
+ }
24
+ export async function removeIfExists(target) {
25
+ try {
26
+ await fs.rm(target, { force: true });
27
+ return true;
28
+ }
29
+ catch (err) {
30
+ if (err.code === "ENOENT")
31
+ return false;
32
+ throw err;
33
+ }
34
+ }
35
+ export function sha256Text(text) {
36
+ return crypto.createHash("sha256").update(text).digest("hex");
37
+ }
38
+ export async function sha256File(target) {
39
+ const body = await readIfExists(target);
40
+ return body === null ? undefined : sha256Text(body);
41
+ }
42
+ export async function chmod600(target) {
43
+ if (process.platform === "win32")
44
+ return;
45
+ try {
46
+ await fs.chmod(target, 0o600);
47
+ }
48
+ catch {
49
+ }
50
+ }
51
+ export async function atomicWriteFile(target, data) {
52
+ await fs.mkdir(path.dirname(target), { recursive: true, mode: 0o700 });
53
+ const tmp = path.join(path.dirname(target), `.${path.basename(target)}.${process.pid}.${Date.now()}.tmp`);
54
+ const fh = await fs.open(tmp, "w", 0o600);
55
+ try {
56
+ await fh.writeFile(data);
57
+ await fh.sync();
58
+ }
59
+ finally {
60
+ await fh.close();
61
+ }
62
+ await chmod600(tmp);
63
+ for (let attempt = 1; attempt <= 5; attempt += 1) {
64
+ try {
65
+ await fs.rename(tmp, target);
66
+ await chmod600(target);
67
+ return sha256Text(data);
68
+ }
69
+ catch (err) {
70
+ if (attempt === 5)
71
+ throw err;
72
+ await new Promise((resolve) => setTimeout(resolve, 50 * attempt));
73
+ }
74
+ }
75
+ return sha256Text(data);
76
+ }
77
+ export async function backupIfFirstApply(target) {
78
+ const backup = backupPath(target);
79
+ if (await pathExists(backup))
80
+ return false;
81
+ if (!(await pathExists(target)))
82
+ return false;
83
+ await fs.mkdir(path.dirname(backup), { recursive: true, mode: 0o700 });
84
+ await fs.rename(target, backup);
85
+ await chmod600(backup);
86
+ return true;
87
+ }
88
+ export async function writeManagedFile(target, body, opts) {
89
+ const currentSha = await sha256File(target);
90
+ if (currentSha && opts?.previousSha256 && currentSha !== opts.previousSha256) {
91
+ const ok = await opts.confirmDrift?.(`${target} changed since agw-client-cli last wrote it. Overwrite it?`);
92
+ if (!ok) {
93
+ throw new Error(`Refusing to overwrite changed config: ${target}`);
94
+ }
95
+ }
96
+ const backupCreated = await backupIfFirstApply(target);
97
+ const sha256 = await atomicWriteFile(target, body.endsWith("\n") ? body : `${body}\n`);
98
+ return { path: target, backupCreated, sha256 };
99
+ }
100
+ export async function restoreOrDeleteManagedFile(target, opts) {
101
+ const currentBody = await readIfExists(target);
102
+ const currentSha = currentBody === null ? undefined : sha256Text(currentBody);
103
+ if (currentSha && opts?.previousSha256 && currentSha !== opts.previousSha256) {
104
+ const ok = await opts.confirmDrift?.(`${target} changed since agw-client-cli last wrote it. Restore/delete it?`);
105
+ if (!ok) {
106
+ throw new Error(`Refusing to restore/delete changed config: ${target}`);
107
+ }
108
+ }
109
+ const backup = backupPath(target);
110
+ if (await pathExists(backup)) {
111
+ await fs.mkdir(path.dirname(target), { recursive: true, mode: 0o700 });
112
+ await removeIfExists(target);
113
+ await fs.rename(backup, target);
114
+ await chmod600(target);
115
+ return { path: target, restored: true, deleted: false };
116
+ }
117
+ if (currentBody !== null && opts?.isManagedContent?.(currentBody)) {
118
+ await removeIfExists(target);
119
+ return { path: target, restored: false, deleted: true };
120
+ }
121
+ return { path: target, restored: false, deleted: false };
122
+ }
123
+ //# sourceMappingURL=fs.js.map
package/dist/fs.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.js","sourceRoot":"","sources":["../src/fs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { ClientFormat, GatewayProvider, ModelCatalog, ModelEntry, ProbeStepResult, ProbeSummary } from "./types.js";
2
+ export declare const PROBE_PROMPT = "Reply with OK.";
3
+ export declare class GatewayHttpError extends Error {
4
+ readonly status: number;
5
+ readonly path: string;
6
+ readonly body?: string | undefined;
7
+ constructor(message: string, status: number, path: string, body?: string | undefined);
8
+ }
9
+ export type FetchLike = typeof fetch;
10
+ export declare function normalizeGatewayUrl(value: string): string;
11
+ export declare class GatewayClient {
12
+ readonly gatewayUrl: string;
13
+ readonly virtualKey: string;
14
+ readonly fetchImpl: FetchLike;
15
+ constructor(gatewayUrl: string, virtualKey: string, fetchImpl?: FetchLike);
16
+ fetchModelCatalog(): Promise<ModelCatalog>;
17
+ fetchModels(provider: GatewayProvider, format: ClientFormat): Promise<ModelEntry[]>;
18
+ runModelListProbe(provider: GatewayProvider, format: ClientFormat): Promise<{
19
+ models: ModelEntry[];
20
+ result: ProbeStepResult;
21
+ }>;
22
+ runGenerationProbe(provider: GatewayProvider, format: Exclude<ClientFormat, "verbose">, model: string): Promise<ProbeStepResult>;
23
+ requestJson(route: string, init: RequestInit): Promise<unknown>;
24
+ }
25
+ export declare function runFullProbeMatrix(client: GatewayClient): Promise<{
26
+ catalog: ModelCatalog;
27
+ summary: ProbeSummary;
28
+ }>;
29
+ export declare function modelListRoute(provider: GatewayProvider, format: ClientFormat): string;
30
+ export declare function generationRoute(provider: GatewayProvider, format: Exclude<ClientFormat, "verbose">): string;
@@ -0,0 +1,257 @@
1
+ import { allProviderModels, emptyProviderCatalog, selectFastProbeModel, } from "./models.js";
2
+ import { GATEWAY_PROVIDERS } from "./types.js";
3
+ export const PROBE_PROMPT = "Reply with OK.";
4
+ const DEFAULT_TIMEOUT_MS = 30_000;
5
+ export class GatewayHttpError extends Error {
6
+ status;
7
+ path;
8
+ body;
9
+ constructor(message, status, path, body) {
10
+ super(message);
11
+ this.status = status;
12
+ this.path = path;
13
+ this.body = body;
14
+ this.name = "GatewayHttpError";
15
+ }
16
+ }
17
+ export function normalizeGatewayUrl(value) {
18
+ const trimmed = value.trim().replace(/\/+$/, "");
19
+ if (!trimmed)
20
+ throw new Error("Gateway URL is required.");
21
+ const parsed = new URL(trimmed);
22
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
23
+ throw new Error("Gateway URL must start with http:// or https://.");
24
+ }
25
+ return parsed.toString().replace(/\/+$/, "");
26
+ }
27
+ export class GatewayClient {
28
+ gatewayUrl;
29
+ virtualKey;
30
+ fetchImpl;
31
+ constructor(gatewayUrl, virtualKey, fetchImpl = fetch) {
32
+ this.gatewayUrl = gatewayUrl;
33
+ this.virtualKey = virtualKey;
34
+ this.fetchImpl = fetchImpl;
35
+ }
36
+ async fetchModelCatalog() {
37
+ const catalog = {
38
+ kiro: emptyProviderCatalog(),
39
+ codex: emptyProviderCatalog(),
40
+ };
41
+ await Promise.all(GATEWAY_PROVIDERS.flatMap((provider) => [
42
+ this.fetchModels(provider, "verbose").then((models) => {
43
+ catalog[provider].verbose = models;
44
+ }),
45
+ this.fetchModels(provider, "openai").then((models) => {
46
+ catalog[provider].openai = models;
47
+ }),
48
+ this.fetchModels(provider, "anthropic").then((models) => {
49
+ catalog[provider].anthropic = models;
50
+ }),
51
+ ]));
52
+ return catalog;
53
+ }
54
+ async fetchModels(provider, format) {
55
+ const route = modelListRoute(provider, format);
56
+ const body = await this.requestJson(route, { method: "GET" });
57
+ return parseModels(body, provider, format);
58
+ }
59
+ async runModelListProbe(provider, format) {
60
+ const route = modelListRoute(provider, format);
61
+ try {
62
+ const models = await this.fetchModels(provider, format);
63
+ return {
64
+ models,
65
+ result: {
66
+ name: `${provider} ${format} models`,
67
+ ok: true,
68
+ provider,
69
+ format,
70
+ path: route,
71
+ },
72
+ };
73
+ }
74
+ catch (err) {
75
+ return {
76
+ models: [],
77
+ result: errorToProbeResult(err, `${provider} ${format} models`, provider, format, route),
78
+ };
79
+ }
80
+ }
81
+ async runGenerationProbe(provider, format, model) {
82
+ const route = generationRoute(provider, format);
83
+ const body = format === "openai"
84
+ ? {
85
+ model,
86
+ input: PROBE_PROMPT,
87
+ max_output_tokens: 8,
88
+ stream: false,
89
+ }
90
+ : {
91
+ model,
92
+ max_tokens: 8,
93
+ messages: [{ role: "user", content: PROBE_PROMPT }],
94
+ stream: false,
95
+ };
96
+ try {
97
+ await this.requestJson(route, {
98
+ method: "POST",
99
+ body: JSON.stringify(body),
100
+ });
101
+ return {
102
+ name: `${provider} ${format} generation`,
103
+ ok: true,
104
+ provider,
105
+ format,
106
+ path: route,
107
+ model,
108
+ };
109
+ }
110
+ catch (err) {
111
+ return errorToProbeResult(err, `${provider} ${format} generation`, provider, format, route, model);
112
+ }
113
+ }
114
+ async requestJson(route, init) {
115
+ const controller = new AbortController();
116
+ const timer = setTimeout(() => controller.abort(), DEFAULT_TIMEOUT_MS);
117
+ try {
118
+ const response = await this.fetchImpl(`${this.gatewayUrl}${route}`, {
119
+ ...init,
120
+ signal: controller.signal,
121
+ headers: {
122
+ "Authorization": `Bearer ${this.virtualKey}`,
123
+ "Content-Type": "application/json",
124
+ ...(init.headers ?? {}),
125
+ },
126
+ });
127
+ const text = await response.text();
128
+ if (!response.ok) {
129
+ throw new GatewayHttpError(`Gateway request failed with HTTP ${response.status}`, response.status, route, sanitizeGatewayBody(text));
130
+ }
131
+ return text ? JSON.parse(text) : {};
132
+ }
133
+ catch (err) {
134
+ if (err.name === "AbortError") {
135
+ throw new Error(`Gateway request timed out: ${route}`);
136
+ }
137
+ throw err;
138
+ }
139
+ finally {
140
+ clearTimeout(timer);
141
+ }
142
+ }
143
+ }
144
+ export async function runFullProbeMatrix(client) {
145
+ const steps = [];
146
+ const catalog = {
147
+ kiro: emptyProviderCatalog(),
148
+ codex: emptyProviderCatalog(),
149
+ };
150
+ await Promise.all(GATEWAY_PROVIDERS.flatMap((provider) => ["verbose", "openai", "anthropic"].map(async (format) => {
151
+ const { models, result } = await client.runModelListProbe(provider, format);
152
+ catalog[provider][format] = models;
153
+ steps.push(result);
154
+ })));
155
+ if (!steps.every((step) => step.ok)) {
156
+ return {
157
+ catalog,
158
+ summary: {
159
+ checkedAt: new Date().toISOString(),
160
+ ok: false,
161
+ steps,
162
+ },
163
+ };
164
+ }
165
+ for (const provider of GATEWAY_PROVIDERS) {
166
+ const model = selectFastProbeModel(allProviderModels(catalog, provider)).id;
167
+ steps.push(await client.runGenerationProbe(provider, "anthropic", model));
168
+ steps.push(await client.runGenerationProbe(provider, "openai", model));
169
+ }
170
+ const summary = {
171
+ checkedAt: new Date().toISOString(),
172
+ ok: steps.every((step) => step.ok),
173
+ steps,
174
+ };
175
+ return { catalog, summary };
176
+ }
177
+ export function modelListRoute(provider, format) {
178
+ if (format === "verbose")
179
+ return `/${provider}/models-verbose`;
180
+ return `/${provider}/${format}/v1/models`;
181
+ }
182
+ export function generationRoute(provider, format) {
183
+ return format === "openai"
184
+ ? `/${provider}/openai/v1/responses`
185
+ : `/${provider}/anthropic/v1/messages`;
186
+ }
187
+ function parseModels(body, provider, format) {
188
+ const data = asRecord(body)?.data;
189
+ if (!Array.isArray(data))
190
+ return [];
191
+ return data
192
+ .map((item) => parseModel(item, provider, format))
193
+ .filter((model) => model !== null);
194
+ }
195
+ function parseModel(item, provider, format) {
196
+ const record = asRecord(item);
197
+ const id = typeof record?.id === "string" ? record.id : "";
198
+ if (!id)
199
+ return null;
200
+ const label = stringField(record, "display_name") ??
201
+ stringField(record, "displayName") ??
202
+ stringField(record, "name") ??
203
+ id;
204
+ return {
205
+ id,
206
+ label,
207
+ provider,
208
+ format,
209
+ contextLength: numberField(record, "context_length") ?? numberField(record, "contextLength"),
210
+ maxOutputTokens: numberField(record, "max_output_tokens") ?? numberField(record, "maxOutputTokens"),
211
+ inputModalities: inputModalities(record?.capabilities),
212
+ };
213
+ }
214
+ function inputModalities(capabilities) {
215
+ const record = asRecord(capabilities);
216
+ if (!record)
217
+ return ["text"];
218
+ const modalities = asRecord(record.modalities);
219
+ const image = record.image_input === true ||
220
+ modalities?.image_input === true ||
221
+ arrayHasImage(record.supported_input_types) ||
222
+ arrayHasImage(record.supportedInputTypes);
223
+ return image ? ["text", "image"] : ["text"];
224
+ }
225
+ function arrayHasImage(value) {
226
+ return Array.isArray(value) && value.some((item) => String(item).toLowerCase().includes("image"));
227
+ }
228
+ function asRecord(value) {
229
+ return value !== null && typeof value === "object" && !Array.isArray(value)
230
+ ? value
231
+ : null;
232
+ }
233
+ function stringField(record, key) {
234
+ const value = record?.[key];
235
+ return typeof value === "string" && value.length > 0 ? value : undefined;
236
+ }
237
+ function numberField(record, key) {
238
+ const value = record?.[key];
239
+ return typeof value === "number" && Number.isFinite(value) ? value : undefined;
240
+ }
241
+ function errorToProbeResult(err, name, provider, format, route, model) {
242
+ const httpErr = err instanceof GatewayHttpError ? err : null;
243
+ return {
244
+ name,
245
+ ok: false,
246
+ provider,
247
+ format,
248
+ path: route,
249
+ model,
250
+ status: httpErr?.status,
251
+ error: httpErr?.body ? `${httpErr.message}: ${httpErr.body}` : err.message,
252
+ };
253
+ }
254
+ function sanitizeGatewayBody(body) {
255
+ return body.replace(/[A-Za-z0-9_-]{24,}/g, "<redacted>").slice(0, 600);
256
+ }
257
+ //# sourceMappingURL=gateway.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway.js","sourceRoot":"","sources":["../src/gateway.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { ClientFormat, GatewayProvider, ModelCatalog, ModelEntry, ProviderModelCatalog } from "./types.js";
2
+ export declare function emptyProviderCatalog(): ProviderModelCatalog;
3
+ export declare function allProviderModels(catalog: ModelCatalog, provider: GatewayProvider): ModelEntry[];
4
+ export declare function allModels(catalog: ModelCatalog): ModelEntry[];
5
+ export declare function dedupeModels(models: ModelEntry[]): ModelEntry[];
6
+ export declare function modelsForFormat(catalog: ModelCatalog, provider: GatewayProvider, format: ClientFormat): ModelEntry[];
7
+ export declare function requireAvailableModel(catalog: ModelCatalog, provider: GatewayProvider, modelId: string): string | null;
8
+ export declare function selectFastProbeModel(models: ModelEntry[]): ModelEntry;
9
+ export declare function modelChoices(models: ModelEntry[]): Array<{
10
+ title: string;
11
+ value: string;
12
+ description?: string;
13
+ }>;
14
+ export declare function formatCatalog(catalog: ModelCatalog): string;
package/dist/models.js ADDED
@@ -0,0 +1,113 @@
1
+ export function emptyProviderCatalog() {
2
+ return { verbose: [], openai: [], anthropic: [] };
3
+ }
4
+ export function allProviderModels(catalog, provider) {
5
+ return dedupeModels([
6
+ ...catalog[provider].verbose,
7
+ ...catalog[provider].openai,
8
+ ...catalog[provider].anthropic,
9
+ ]);
10
+ }
11
+ export function allModels(catalog) {
12
+ return dedupeModels([
13
+ ...allProviderModels(catalog, "kiro"),
14
+ ...allProviderModels(catalog, "codex"),
15
+ ]);
16
+ }
17
+ export function dedupeModels(models) {
18
+ const byKey = new Map();
19
+ for (const model of models) {
20
+ const key = `${model.provider}:${model.id}`;
21
+ const existing = byKey.get(key);
22
+ if (!existing) {
23
+ byKey.set(key, model);
24
+ continue;
25
+ }
26
+ byKey.set(key, {
27
+ ...existing,
28
+ ...model,
29
+ label: existing.label !== existing.id ? existing.label : model.label,
30
+ format: existing.format === "verbose" ? existing.format : model.format,
31
+ contextLength: model.contextLength ?? existing.contextLength,
32
+ maxOutputTokens: model.maxOutputTokens ?? existing.maxOutputTokens,
33
+ inputModalities: [...new Set([...existing.inputModalities, ...model.inputModalities])],
34
+ });
35
+ }
36
+ return [...byKey.values()].sort((a, b) => {
37
+ const byProvider = a.provider.localeCompare(b.provider);
38
+ return byProvider === 0 ? a.id.localeCompare(b.id) : byProvider;
39
+ });
40
+ }
41
+ export function modelsForFormat(catalog, provider, format) {
42
+ return catalog[provider][format];
43
+ }
44
+ export function requireAvailableModel(catalog, provider, modelId) {
45
+ return allProviderModels(catalog, provider).some((model) => model.id === modelId) ? modelId : null;
46
+ }
47
+ export function selectFastProbeModel(models) {
48
+ if (models.length === 0) {
49
+ throw new Error("No models are available for gateway probing.");
50
+ }
51
+ const scored = [...models].map((model) => ({
52
+ model,
53
+ score: speedScore(model),
54
+ }));
55
+ scored.sort((a, b) => a.score - b.score || a.model.id.localeCompare(b.model.id));
56
+ return scored[0].model;
57
+ }
58
+ function speedScore(model) {
59
+ const id = model.id.toLowerCase();
60
+ let score = 100;
61
+ if (id.includes("haiku"))
62
+ score -= 60;
63
+ if (id.includes("mini"))
64
+ score -= 55;
65
+ if (id.includes("flash"))
66
+ score -= 45;
67
+ if (id.includes("fast"))
68
+ score -= 35;
69
+ if (id.includes("qwen"))
70
+ score -= 25;
71
+ if (id.includes("glm"))
72
+ score -= 20;
73
+ if (id.includes("sonnet"))
74
+ score += 10;
75
+ if (id.includes("opus"))
76
+ score += 35;
77
+ if (id.includes("gpt-5.4-mini"))
78
+ score -= 50;
79
+ if (id.includes("gpt-5.4") || id.includes("gpt-5.3"))
80
+ score += 15;
81
+ if (typeof model.maxOutputTokens === "number")
82
+ score += Math.min(model.maxOutputTokens / 100000, 15);
83
+ if (typeof model.contextLength === "number")
84
+ score += Math.min(model.contextLength / 1000000, 10);
85
+ return score;
86
+ }
87
+ export function modelChoices(models) {
88
+ return dedupeModels(models).map((model) => ({
89
+ title: model.label === model.id ? model.id : `${model.label} (${model.id})`,
90
+ value: model.id,
91
+ description: `${model.provider} ${model.format}`,
92
+ }));
93
+ }
94
+ export function formatCatalog(catalog) {
95
+ const lines = [];
96
+ for (const provider of ["kiro", "codex"]) {
97
+ lines.push(`${provider.toUpperCase()}`);
98
+ for (const format of ["verbose", "openai", "anthropic"]) {
99
+ const models = modelsForFormat(catalog, provider, format);
100
+ lines.push(` ${format}:`);
101
+ if (models.length === 0) {
102
+ lines.push(" (none)");
103
+ continue;
104
+ }
105
+ for (const model of models) {
106
+ const label = model.label === model.id ? model.id : `${model.id} - ${model.label}`;
107
+ lines.push(` - ${label}`);
108
+ }
109
+ }
110
+ }
111
+ return lines.join("\n");
112
+ }
113
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { RuntimePaths } from "./types.js";
2
+ export declare function resolveRuntimePaths(options?: {
3
+ homeDir?: string;
4
+ platform?: NodeJS.Platform;
5
+ env?: NodeJS.ProcessEnv;
6
+ }): RuntimePaths;
7
+ export declare function backupPath(target: string): string;
package/dist/paths.js ADDED
@@ -0,0 +1,36 @@
1
+ import os from "node:os";
2
+ import path from "node:path";
3
+ export function resolveRuntimePaths(options) {
4
+ const homeDir = options?.homeDir ?? os.homedir();
5
+ const platform = options?.platform ?? process.platform;
6
+ const env = options?.env ?? process.env;
7
+ let appConfigDir;
8
+ if (platform === "darwin") {
9
+ appConfigDir = path.join(homeDir, "Library", "Application Support", "agw-client-cli");
10
+ }
11
+ else if (platform === "win32") {
12
+ appConfigDir = path.join(nonEmptyEnv(env.LOCALAPPDATA) ?? path.join(homeDir, "AppData", "Local"), "agw-client-cli");
13
+ }
14
+ else {
15
+ appConfigDir = path.join(nonEmptyEnv(env.XDG_CONFIG_HOME) ?? path.join(homeDir, ".config"), "agw-client-cli");
16
+ }
17
+ if (!path.isAbsolute(appConfigDir)) {
18
+ appConfigDir = path.resolve(homeDir, appConfigDir);
19
+ }
20
+ return {
21
+ homeDir,
22
+ appConfigDir,
23
+ stateFile: path.join(appConfigDir, "state.json"),
24
+ claudeConfig: path.join(homeDir, ".claude", "settings.json"),
25
+ codexConfig: path.join(homeDir, ".codex", "config.toml"),
26
+ codexModelCatalog: path.join(homeDir, ".codex", "agw-client-cli-model-catalog.json"),
27
+ };
28
+ }
29
+ export function backupPath(target) {
30
+ return `${target}.egw-backup`;
31
+ }
32
+ function nonEmptyEnv(value) {
33
+ const trimmed = value?.trim();
34
+ return trimmed ? trimmed : undefined;
35
+ }
36
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAI7B,MAAM,UAAU,mBAAmB,CAAC,OAInC;IACC,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;IACjD,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC;IACvD,MAAM,GAAG,GAAG,OAAO,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IAExC,IAAI,YAAoB,CAAC;IACzB,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,qBAAqB,EAAE,gBAAgB,CAAC,CAAC;IACxF,CAAC;SAAM,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QAChC,YAAY,GAAG,IAAI,CAAC,IAAI,CACtB,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,EACvE,gBAAgB,CACjB,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,gBAAgB,CAAC,CAAC;IAChH,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QACnC,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IACrD,CAAC;IAED,OAAO;QACL,OAAO;QACP,YAAY;QACZ,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC;QAChD,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,eAAe,CAAC;QAC5D,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,aAAa,CAAC;QACxD,iBAAiB,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,mCAAmC,CAAC;KACrF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAc;IACvC,OAAO,GAAG,MAAM,aAAa,CAAC;AAChC,CAAC;AAED,SAAS,WAAW,CAAC,KAAyB;IAC5C,MAAM,OAAO,GAAG,KAAK,EAAE,IAAI,EAAE,CAAC;IAC9B,OAAO,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;AACvC,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { ClaudeSelection, CodexSelection, ModelCatalog, Target, TargetProvider } from "./types.js";
2
+ export interface PromptIO {
3
+ stdin: NodeJS.ReadStream;
4
+ stdout: NodeJS.WriteStream;
5
+ }
6
+ export declare function assertInteractive(stdin: NodeJS.ReadStream, stdout: NodeJS.WriteStream, command: string): void;
7
+ export declare function promptGatewayUrl(): Promise<string>;
8
+ export declare function promptVirtualKey(): Promise<string>;
9
+ export declare function promptTargets(): Promise<Target[]>;
10
+ export declare function promptTargetForSwitch(): Promise<Target>;
11
+ export declare function promptProvider(target: Target): Promise<TargetProvider>;
12
+ export declare function promptClaudeSelection(catalog: ModelCatalog, existing?: ClaudeSelection, options?: {
13
+ allowOfficial?: boolean;
14
+ provider?: TargetProvider;
15
+ }): Promise<ClaudeSelection>;
16
+ export declare function promptCodexSelection(catalog: ModelCatalog, existing?: CodexSelection, options?: {
17
+ allowOfficial?: boolean;
18
+ provider?: TargetProvider;
19
+ }): Promise<CodexSelection>;
20
+ export declare function confirm(message: string, initial?: boolean): Promise<boolean>;
21
+ export declare function confirmSetupSummary(summary: string): Promise<boolean>;
22
+ export declare function targetsFromStateOrDefault(targets?: Target[]): Target[];