@codemieai/code 0.13.0 → 0.14.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/README.md +78 -4
- package/dist/agents/core/AgentCLI.d.ts.map +1 -1
- package/dist/agents/core/AgentCLI.js +53 -4
- package/dist/agents/core/AgentCLI.js.map +1 -1
- package/dist/agents/plugins/claude/claude.models.d.ts +12 -0
- package/dist/agents/plugins/claude/claude.models.d.ts.map +1 -0
- package/dist/agents/plugins/claude/claude.models.js +191 -0
- package/dist/agents/plugins/claude/claude.models.js.map +1 -0
- package/dist/agents/plugins/claude/claude.plugin.d.ts.map +1 -1
- package/dist/agents/plugins/claude/claude.plugin.js +45 -1
- package/dist/agents/plugins/claude/claude.plugin.js.map +1 -1
- package/dist/agents/plugins/codex/codex-models.d.ts +11 -0
- package/dist/agents/plugins/codex/codex-models.d.ts.map +1 -1
- package/dist/agents/plugins/codex/codex-models.js +71 -0
- package/dist/agents/plugins/codex/codex-models.js.map +1 -1
- package/dist/agents/plugins/gemini/gemini.paths.d.ts +11 -0
- package/dist/agents/plugins/gemini/gemini.paths.d.ts.map +1 -0
- package/dist/agents/plugins/gemini/gemini.paths.js +21 -0
- package/dist/agents/plugins/gemini/gemini.paths.js.map +1 -0
- package/dist/agents/plugins/gemini/gemini.session-adapter.d.ts +20 -0
- package/dist/agents/plugins/gemini/gemini.session-adapter.d.ts.map +1 -1
- package/dist/agents/plugins/gemini/gemini.session-adapter.js +119 -3
- package/dist/agents/plugins/gemini/gemini.session-adapter.js.map +1 -1
- package/dist/agents/plugins/pi/pi.models.d.ts +14 -0
- package/dist/agents/plugins/pi/pi.models.d.ts.map +1 -1
- package/dist/agents/plugins/pi/pi.models.js +89 -0
- package/dist/agents/plugins/pi/pi.models.js.map +1 -1
- package/dist/cli/commands/analytics/agent-labels.d.ts.map +1 -1
- package/dist/cli/commands/analytics/agent-labels.js +1 -0
- package/dist/cli/commands/analytics/agent-labels.js.map +1 -1
- package/dist/cli/commands/analytics/aggregator.js +1 -1
- package/dist/cli/commands/analytics/aggregator.js.map +1 -1
- package/dist/cli/commands/analytics/cost/cost-calculator.d.ts +1 -1
- package/dist/cli/commands/analytics/cost/cost-calculator.d.ts.map +1 -1
- package/dist/cli/commands/analytics/cost/cost-enricher.js +2 -2
- package/dist/cli/commands/analytics/cost/cost-enricher.js.map +1 -1
- package/dist/cli/commands/analytics/data-loader.d.ts.map +1 -1
- package/dist/cli/commands/analytics/data-loader.js +9 -0
- package/dist/cli/commands/analytics/data-loader.js.map +1 -1
- package/dist/cli/commands/analytics/native-loader.js +1 -1
- package/dist/cli/commands/analytics/native-loader.js.map +1 -1
- package/dist/cli/commands/analytics/otel-loader.js +1 -1
- package/dist/cli/commands/analytics/otel-loader.js.map +1 -1
- package/dist/cli/commands/analytics/report/client/app.js +1 -1
- package/dist/cli/commands/hook.d.ts.map +1 -1
- package/dist/cli/commands/hook.js +70 -1
- package/dist/cli/commands/hook.js.map +1 -1
- package/dist/cli/commands/proxy/connect-orchestrator.d.ts +95 -0
- package/dist/cli/commands/proxy/connect-orchestrator.d.ts.map +1 -0
- package/dist/cli/commands/proxy/connect-orchestrator.js +501 -0
- package/dist/cli/commands/proxy/connect-orchestrator.js.map +1 -0
- package/dist/cli/commands/proxy/connectors/codex-config-toml.d.ts +81 -0
- package/dist/cli/commands/proxy/connectors/codex-config-toml.d.ts.map +1 -0
- package/dist/cli/commands/proxy/connectors/codex-config-toml.js +218 -0
- package/dist/cli/commands/proxy/connectors/codex-config-toml.js.map +1 -0
- package/dist/cli/commands/proxy/connectors/codex-desktop.d.ts +85 -0
- package/dist/cli/commands/proxy/connectors/codex-desktop.d.ts.map +1 -0
- package/dist/cli/commands/proxy/connectors/codex-desktop.js +299 -0
- package/dist/cli/commands/proxy/connectors/codex-desktop.js.map +1 -0
- package/dist/cli/commands/proxy/connectors/desktop.d.ts +94 -4
- package/dist/cli/commands/proxy/connectors/desktop.d.ts.map +1 -1
- package/dist/cli/commands/proxy/connectors/desktop.js +244 -17
- package/dist/cli/commands/proxy/connectors/desktop.js.map +1 -1
- package/dist/cli/commands/proxy/connectors/managed-mcp-remote.d.ts +25 -0
- package/dist/cli/commands/proxy/connectors/managed-mcp-remote.d.ts.map +1 -1
- package/dist/cli/commands/proxy/connectors/managed-mcp-remote.js +59 -1
- package/dist/cli/commands/proxy/connectors/managed-mcp-remote.js.map +1 -1
- package/dist/cli/commands/proxy/connectors/vscode-claude-code.d.ts +26 -0
- package/dist/cli/commands/proxy/connectors/vscode-claude-code.d.ts.map +1 -0
- package/dist/cli/commands/proxy/connectors/vscode-claude-code.js +132 -0
- package/dist/cli/commands/proxy/connectors/vscode-claude-code.js.map +1 -0
- package/dist/cli/commands/proxy/connectors/vscode.d.ts +2 -0
- package/dist/cli/commands/proxy/connectors/vscode.d.ts.map +1 -1
- package/dist/cli/commands/proxy/connectors/vscode.js +2 -2
- package/dist/cli/commands/proxy/connectors/vscode.js.map +1 -1
- package/dist/cli/commands/proxy/disconnect-orchestrator.d.ts +8 -0
- package/dist/cli/commands/proxy/disconnect-orchestrator.d.ts.map +1 -0
- package/dist/cli/commands/proxy/disconnect-orchestrator.js +43 -0
- package/dist/cli/commands/proxy/disconnect-orchestrator.js.map +1 -0
- package/dist/cli/commands/proxy/index.d.ts.map +1 -1
- package/dist/cli/commands/proxy/index.js +91 -361
- package/dist/cli/commands/proxy/index.js.map +1 -1
- package/dist/cli/index.js +7 -7
- package/dist/providers/integration/setup-ui.d.ts +14 -2
- package/dist/providers/integration/setup-ui.d.ts.map +1 -1
- package/dist/providers/integration/setup-ui.js +70 -33
- package/dist/providers/integration/setup-ui.js.map +1 -1
- package/dist/providers/plugins/anthropic-subscription/anthropic-subscription.setup-steps.d.ts.map +1 -1
- package/dist/providers/plugins/anthropic-subscription/anthropic-subscription.setup-steps.js +9 -2
- package/dist/providers/plugins/anthropic-subscription/anthropic-subscription.setup-steps.js.map +1 -1
- package/dist/providers/plugins/anthropic-subscription/anthropic-subscription.template.d.ts.map +1 -1
- package/dist/providers/plugins/anthropic-subscription/anthropic-subscription.template.js +18 -28
- package/dist/providers/plugins/anthropic-subscription/anthropic-subscription.template.js.map +1 -1
- package/dist/providers/plugins/bedrock/bedrock.setup-steps.d.ts.map +1 -1
- package/dist/providers/plugins/bedrock/bedrock.setup-steps.js +4 -4
- package/dist/providers/plugins/bedrock/bedrock.setup-steps.js.map +1 -1
- package/dist/providers/plugins/litellm/litellm.setup-steps.d.ts.map +1 -1
- package/dist/providers/plugins/litellm/litellm.setup-steps.js +3 -1
- package/dist/providers/plugins/litellm/litellm.setup-steps.js.map +1 -1
- package/dist/providers/plugins/moonshot-subscription/moonshot-subscription.setup-steps.d.ts.map +1 -1
- package/dist/providers/plugins/moonshot-subscription/moonshot-subscription.setup-steps.js +5 -1
- package/dist/providers/plugins/moonshot-subscription/moonshot-subscription.setup-steps.js.map +1 -1
- package/dist/providers/plugins/ollama/ollama.setup-steps.d.ts.map +1 -1
- package/dist/providers/plugins/ollama/ollama.setup-steps.js +3 -2
- package/dist/providers/plugins/ollama/ollama.setup-steps.js.map +1 -1
- package/dist/providers/plugins/sso/proxy/plugins/codex-encrypted-content-sanitizer.plugin.d.ts.map +1 -1
- package/dist/providers/plugins/sso/proxy/plugins/codex-encrypted-content-sanitizer.plugin.js +4 -0
- package/dist/providers/plugins/sso/proxy/plugins/codex-encrypted-content-sanitizer.plugin.js.map +1 -1
- package/dist/providers/plugins/sso/proxy/plugins/codex-model-resolver.d.ts +45 -0
- package/dist/providers/plugins/sso/proxy/plugins/codex-model-resolver.d.ts.map +1 -0
- package/dist/providers/plugins/sso/proxy/plugins/codex-model-resolver.js +129 -0
- package/dist/providers/plugins/sso/proxy/plugins/codex-model-resolver.js.map +1 -0
- package/dist/providers/plugins/sso/proxy/plugins/codex-request-normalizer.plugin.d.ts +27 -0
- package/dist/providers/plugins/sso/proxy/plugins/codex-request-normalizer.plugin.d.ts.map +1 -0
- package/dist/providers/plugins/sso/proxy/plugins/codex-request-normalizer.plugin.js +242 -0
- package/dist/providers/plugins/sso/proxy/plugins/codex-request-normalizer.plugin.js.map +1 -0
- package/dist/providers/plugins/sso/proxy/plugins/index.d.ts +2 -1
- package/dist/providers/plugins/sso/proxy/plugins/index.d.ts.map +1 -1
- package/dist/providers/plugins/sso/proxy/plugins/index.js +3 -1
- package/dist/providers/plugins/sso/proxy/plugins/index.js.map +1 -1
- package/dist/providers/plugins/sso/session/processors/metrics/metrics-api-client.d.ts.map +1 -1
- package/dist/providers/plugins/sso/session/processors/metrics/metrics-api-client.js +15 -1
- package/dist/providers/plugins/sso/session/processors/metrics/metrics-api-client.js.map +1 -1
- package/dist/providers/plugins/sso/sso.auth.d.ts.map +1 -1
- package/dist/providers/plugins/sso/sso.auth.js +3 -0
- package/dist/providers/plugins/sso/sso.auth.js.map +1 -1
- package/dist/telemetry/clients/claude-desktop/claude-desktop.discovery.d.ts.map +1 -1
- package/dist/telemetry/clients/claude-desktop/claude-desktop.discovery.js +13 -1
- package/dist/telemetry/clients/claude-desktop/claude-desktop.discovery.js.map +1 -1
- package/dist/telemetry/clients/claude-desktop/claude-desktop.paths.d.ts +12 -0
- package/dist/telemetry/clients/claude-desktop/claude-desktop.paths.d.ts.map +1 -1
- package/dist/telemetry/clients/claude-desktop/claude-desktop.paths.js +28 -1
- package/dist/telemetry/clients/claude-desktop/claude-desktop.paths.js.map +1 -1
- package/dist/utils/analytics-auth-status.d.ts +48 -0
- package/dist/utils/analytics-auth-status.d.ts.map +1 -0
- package/dist/utils/analytics-auth-status.js +89 -0
- package/dist/utils/analytics-auth-status.js.map +1 -0
- package/dist/utils/model-normalizer.d.ts.map +1 -0
- package/dist/utils/model-normalizer.js.map +1 -0
- package/dist/utils/pricing.d.ts.map +1 -0
- package/dist/{cli/commands/analytics/cost → utils}/pricing.js +3 -3
- package/dist/utils/pricing.js.map +1 -0
- package/package.json +1 -1
- package/scripts/copy-plugins.js +3 -3
- package/dist/cli/commands/analytics/cost/pricing.d.ts.map +0 -1
- package/dist/cli/commands/analytics/cost/pricing.js.map +0 -1
- package/dist/cli/commands/analytics/model-normalizer.d.ts.map +0 -1
- package/dist/cli/commands/analytics/model-normalizer.js.map +0 -1
- /package/dist/{cli/commands/analytics → utils}/model-normalizer.d.ts +0 -0
- /package/dist/{cli/commands/analytics → utils}/model-normalizer.js +0 -0
- /package/dist/{cli/commands/analytics/cost → utils}/pricing.d.ts +0 -0
- /package/dist/{cli/commands/analytics/cost → utils}/pricing.json +0 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure string surgery for the CodeMie-managed regions of `~/.codex/config.toml`.
|
|
3
|
+
*
|
|
4
|
+
* Nothing here touches the filesystem, the network, or the logger. The Codex
|
|
5
|
+
* config file is user-owned, so the managed content is spliced in as delimited
|
|
6
|
+
* text rather than round-tripped through a TOML serializer: `@iarna/toml`'s
|
|
7
|
+
* `stringify` discards comments and key order, which would silently rewrite the
|
|
8
|
+
* user's file on every connect.
|
|
9
|
+
*
|
|
10
|
+
* TOML permits bare top-level keys only *before* the first table header, so the
|
|
11
|
+
* managed content cannot be one contiguous block. It is two regions: a header
|
|
12
|
+
* region prepended to the file (holding `model_provider` and `model`) and a
|
|
13
|
+
* table region appended to it (holding `[model_providers.codemie]`).
|
|
14
|
+
*/
|
|
15
|
+
export const HEADER_OPEN = '# >>> codemie proxy connect (codex-desktop) header - managed block, do not edit';
|
|
16
|
+
export const HEADER_CLOSE = '# <<< codemie proxy connect (codex-desktop) header';
|
|
17
|
+
export const TABLE_OPEN = '# >>> codemie proxy connect (codex-desktop) provider - managed block, do not edit';
|
|
18
|
+
export const TABLE_CLOSE = '# <<< codemie proxy connect (codex-desktop) provider';
|
|
19
|
+
/**
|
|
20
|
+
* A line is a sentinel when it equals one after trimming.
|
|
21
|
+
*
|
|
22
|
+
* Trailing whitespace and a stray `\r` are tolerated because this file is
|
|
23
|
+
* rewritten by the Codex desktop app and by editors on Windows, a supported
|
|
24
|
+
* platform. Matching strictly would make a sentinel unrecognizable to the
|
|
25
|
+
* cutter while still looking managed to the reader — which duplicates the
|
|
26
|
+
* managed block into the user's file.
|
|
27
|
+
*/
|
|
28
|
+
function isSentinel(line, sentinel) {
|
|
29
|
+
return line.trim() === sentinel;
|
|
30
|
+
}
|
|
31
|
+
function locate(text, open, close) {
|
|
32
|
+
const lines = text.split('\n');
|
|
33
|
+
const openLine = lines.findIndex((line) => isSentinel(line, open));
|
|
34
|
+
if (openLine === -1)
|
|
35
|
+
return null;
|
|
36
|
+
const closeLine = lines.findIndex((line, index) => index > openLine && isSentinel(line, close));
|
|
37
|
+
if (closeLine === -1)
|
|
38
|
+
return null;
|
|
39
|
+
// Character offsets of the whole-line span, so callers can slice text.
|
|
40
|
+
const start = lines.slice(0, openLine).reduce((n, line) => n + line.length + 1, 0);
|
|
41
|
+
const end = lines.slice(0, closeLine + 1).reduce((n, line) => n + line.length + 1, 0) - 1;
|
|
42
|
+
return { start, end };
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Locate both managed regions. A region whose close sentinel is missing is
|
|
46
|
+
* reported as absent rather than guessed at — a truncated block is treated as
|
|
47
|
+
* unmanaged text so the writer never deletes content it cannot delimit.
|
|
48
|
+
*/
|
|
49
|
+
export function findManagedRegions(text) {
|
|
50
|
+
return {
|
|
51
|
+
header: locate(text, HEADER_OPEN, HEADER_CLOSE),
|
|
52
|
+
table: locate(text, TABLE_OPEN, TABLE_CLOSE),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/** Marks a user key the connector commented out so it can be restored verbatim. */
|
|
56
|
+
export const DISPLACED_PREFIX = '#codemie-displaced# ';
|
|
57
|
+
/** Top-level keys the managed header region owns and therefore must displace. */
|
|
58
|
+
const DISPLACED_KEYS = ['model', 'model_provider'];
|
|
59
|
+
const DISPLACED_KEY_PATTERN = new RegExp(`^\\s*(?:${DISPLACED_KEYS.join('|')})\\s*=`);
|
|
60
|
+
/** A line opening a TOML table, after which bare keys belong to that table. */
|
|
61
|
+
function isTableHeader(line) {
|
|
62
|
+
return /^\s*\[/.test(line);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Comment out unmanaged root-level `model` / `model_provider` assignments.
|
|
66
|
+
*
|
|
67
|
+
* Only the document root matters: once the scan passes the first table header,
|
|
68
|
+
* any same-named key belongs to that table and is none of our business.
|
|
69
|
+
* Idempotent — a line already carrying `DISPLACED_PREFIX` is left alone.
|
|
70
|
+
*/
|
|
71
|
+
export function commentDisplacedKeys(text) {
|
|
72
|
+
let inRootScope = true;
|
|
73
|
+
return text
|
|
74
|
+
.split('\n')
|
|
75
|
+
.map((line) => {
|
|
76
|
+
if (isTableHeader(line)) {
|
|
77
|
+
inRootScope = false;
|
|
78
|
+
return line;
|
|
79
|
+
}
|
|
80
|
+
if (!inRootScope)
|
|
81
|
+
return line;
|
|
82
|
+
if (line.startsWith(DISPLACED_PREFIX))
|
|
83
|
+
return line;
|
|
84
|
+
if (!DISPLACED_KEY_PATTERN.test(line))
|
|
85
|
+
return line;
|
|
86
|
+
return `${DISPLACED_PREFIX}${line}`;
|
|
87
|
+
})
|
|
88
|
+
.join('\n');
|
|
89
|
+
}
|
|
90
|
+
/** Exact inverse of `commentDisplacedKeys`. */
|
|
91
|
+
export function restoreDisplacedKeys(text) {
|
|
92
|
+
return text
|
|
93
|
+
.split('\n')
|
|
94
|
+
.map((line) => (line.startsWith(DISPLACED_PREFIX) ? line.slice(DISPLACED_PREFIX.length) : line))
|
|
95
|
+
.join('\n');
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Remove both managed regions, line by line.
|
|
99
|
+
*
|
|
100
|
+
* Line-based rather than offset-based on purpose: `spliceManagedBlocks` inserts
|
|
101
|
+
* each region as whole lines plus exactly one blank separator line, so removing
|
|
102
|
+
* whole lines plus exactly one separator is its precise inverse. Slicing by
|
|
103
|
+
* character offset cannot express "and the blank line that came with it", which
|
|
104
|
+
* is what makes `strip(splice(x)) === x` hold here.
|
|
105
|
+
*/
|
|
106
|
+
/** Index of the matching close sentinel after `from`, or -1 when unterminated. */
|
|
107
|
+
function findClose(lines, from, close) {
|
|
108
|
+
for (let i = from + 1; i < lines.length; i++) {
|
|
109
|
+
if (isSentinel(lines[i], close))
|
|
110
|
+
return i;
|
|
111
|
+
}
|
|
112
|
+
return -1;
|
|
113
|
+
}
|
|
114
|
+
function cutRegionLines(text) {
|
|
115
|
+
const lines = text.split('\n');
|
|
116
|
+
const keep = [];
|
|
117
|
+
let i = 0;
|
|
118
|
+
while (i < lines.length) {
|
|
119
|
+
if (isSentinel(lines[i], HEADER_OPEN)) {
|
|
120
|
+
const closeAt = findClose(lines, i, HEADER_CLOSE);
|
|
121
|
+
if (closeAt === -1) {
|
|
122
|
+
// Unterminated region: keep the line verbatim rather than consuming the
|
|
123
|
+
// rest of the file. Deleting to EOF here would destroy a user config
|
|
124
|
+
// whose close marker was removed, and would contradict
|
|
125
|
+
// findManagedRegions, which reports such a region as absent.
|
|
126
|
+
keep.push(lines[i]);
|
|
127
|
+
i++;
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
i = closeAt + 1;
|
|
131
|
+
// The header chunk owns exactly one blank line after it.
|
|
132
|
+
if (i < lines.length && lines[i].trim() === '')
|
|
133
|
+
i++;
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (isSentinel(lines[i], TABLE_OPEN)) {
|
|
137
|
+
const closeAt = findClose(lines, i, TABLE_CLOSE);
|
|
138
|
+
if (closeAt === -1) {
|
|
139
|
+
keep.push(lines[i]);
|
|
140
|
+
i++;
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
// The table chunk owns exactly one blank line before it.
|
|
144
|
+
if (keep.length > 0 && keep[keep.length - 1].trim() === '')
|
|
145
|
+
keep.pop();
|
|
146
|
+
i = closeAt + 1;
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
keep.push(lines[i]);
|
|
150
|
+
i++;
|
|
151
|
+
}
|
|
152
|
+
return keep.join('\n');
|
|
153
|
+
}
|
|
154
|
+
/** Normalize to `''` or text terminated by exactly one newline. */
|
|
155
|
+
function normalizeBase(text) {
|
|
156
|
+
if (text.trim() === '')
|
|
157
|
+
return '';
|
|
158
|
+
return text.endsWith('\n') ? text : `${text}\n`;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Insert both managed regions, replacing any that already exist. The header is
|
|
162
|
+
* prepended (TOML bare keys must precede the first table header) and the table
|
|
163
|
+
* is appended. Every line outside the two regions is preserved verbatim.
|
|
164
|
+
*/
|
|
165
|
+
export function spliceManagedBlocks(text, blocks) {
|
|
166
|
+
const base = normalizeBase(commentDisplacedKeys(cutRegionLines(text)));
|
|
167
|
+
const header = [HEADER_OPEN, blocks.header, HEADER_CLOSE].join('\n');
|
|
168
|
+
const table = [TABLE_OPEN, blocks.table, TABLE_CLOSE].join('\n');
|
|
169
|
+
if (base === '')
|
|
170
|
+
return `${header}\n\n${table}\n`;
|
|
171
|
+
return `${header}\n\n${base}\n${table}\n`;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Remove both managed regions and restore any keys the splice displaced,
|
|
175
|
+
* yielding the text the file held before `spliceManagedBlocks` ran.
|
|
176
|
+
*/
|
|
177
|
+
export function stripManagedRegions(text) {
|
|
178
|
+
const restored = restoreDisplacedKeys(cutRegionLines(text));
|
|
179
|
+
if (restored.trim() === '')
|
|
180
|
+
return '';
|
|
181
|
+
return restored.endsWith('\n') ? restored : `${restored}\n`;
|
|
182
|
+
}
|
|
183
|
+
/** The provider id CodeMie owns in the user's Codex config. */
|
|
184
|
+
export const CODEMIE_PROVIDER_ID = 'codemie';
|
|
185
|
+
/** Escape a value for a TOML basic string. */
|
|
186
|
+
function toTomlString(value) {
|
|
187
|
+
const escaped = value
|
|
188
|
+
.replace(/\\/g, '\\\\')
|
|
189
|
+
.replace(/"/g, '\\"')
|
|
190
|
+
.replace(/\n/g, '\\n');
|
|
191
|
+
return `"${escaped}"`;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Render the two managed region bodies.
|
|
195
|
+
*
|
|
196
|
+
* `wire_api` is always `responses`: Codex removed the `chat` wire API in
|
|
197
|
+
* February 2026, so a custom provider declaring anything else fails at startup.
|
|
198
|
+
* The gateway key travels as a static `http_headers` entry rather than an
|
|
199
|
+
* `env_key`, because a desktop app does not inherit the shell environment — and
|
|
200
|
+
* never via `~/.codex/auth.json`, because writing there flips the app into
|
|
201
|
+
* API-key auth mode and disables its ChatGPT-account features.
|
|
202
|
+
*/
|
|
203
|
+
export function buildManagedBlocks(input) {
|
|
204
|
+
const header = [
|
|
205
|
+
`model_provider = ${toTomlString(CODEMIE_PROVIDER_ID)}`,
|
|
206
|
+
`model = ${toTomlString(input.model)}`,
|
|
207
|
+
].join('\n');
|
|
208
|
+
const table = [
|
|
209
|
+
`[model_providers.${CODEMIE_PROVIDER_ID}]`,
|
|
210
|
+
`name = ${toTomlString('CodeMie')}`,
|
|
211
|
+
`base_url = ${toTomlString(input.baseUrl)}`,
|
|
212
|
+
'wire_api = "responses"',
|
|
213
|
+
`[model_providers.${CODEMIE_PROVIDER_ID}.http_headers]`,
|
|
214
|
+
`Authorization = ${toTomlString(`Bearer ${input.gatewayKey}`)}`,
|
|
215
|
+
].join('\n');
|
|
216
|
+
return { header, table };
|
|
217
|
+
}
|
|
218
|
+
//# sourceMappingURL=codex-config-toml.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-config-toml.js","sourceRoot":"","sources":["../../../../../src/cli/commands/proxy/connectors/codex-config-toml.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the config file the desktop app reads.
|
|
3
|
+
*
|
|
4
|
+
* Deliberately NOT `getCodexHomePath()` from the codex agent plugin. That helper
|
|
5
|
+
* is used by code paths which redirect `CODEX_HOME` to a CodeMie-isolated home
|
|
6
|
+
* for the CLI they spawn, and the desktop app never reads that home. A
|
|
7
|
+
* `CODEX_HOME` visible here belongs to the user, and upstream documents the app
|
|
8
|
+
* respecting it, so it is honoured.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getCodexDesktopConfigPath(): string;
|
|
11
|
+
/** Where the connector records what it owns, mirroring the Claude Desktop precedent. */
|
|
12
|
+
export declare function getCodexDesktopStatePath(): string;
|
|
13
|
+
/** Install locations for the ChatGPT desktop app, which is what ships Codex. */
|
|
14
|
+
export declare function getCodexDesktopAppCandidates(): string[];
|
|
15
|
+
/** First candidate path that exists, or null. */
|
|
16
|
+
export declare function findCodexDesktopApp(candidates?: string[]): string | null;
|
|
17
|
+
/** Suffix for the pre-connect snapshot of the user's Codex config. */
|
|
18
|
+
export declare const BACKUP_SUFFIX = ".codemie-backup";
|
|
19
|
+
/**
|
|
20
|
+
* Snapshot the config only when CodeMie does not already own part of it.
|
|
21
|
+
*
|
|
22
|
+
* Keyed on marker presence rather than backup presence on purpose. Once our
|
|
23
|
+
* block is in the file, the existing backup is the true pre-CodeMie original and
|
|
24
|
+
* must not be replaced by a copy that already contains our block — which is the
|
|
25
|
+
* bug the Kimi hook injector's create-once backup has.
|
|
26
|
+
*/
|
|
27
|
+
export declare function backupIfUnmanaged(configPath: string, currentText: string): Promise<string | null>;
|
|
28
|
+
/**
|
|
29
|
+
* Discover Codex-compatible model ids through the local proxy.
|
|
30
|
+
*
|
|
31
|
+
* Discovery goes through the proxy rather than the backend so the connector
|
|
32
|
+
* exercises exactly the path the app will use — a broken proxy fails here,
|
|
33
|
+
* before the config is written, rather than after.
|
|
34
|
+
*/
|
|
35
|
+
export declare function discoverCodexModels(proxyUrl: string, gatewayKey: string): Promise<string[]>;
|
|
36
|
+
/**
|
|
37
|
+
* Choose the model to pin.
|
|
38
|
+
*
|
|
39
|
+
* An explicit request is resolved with the same rule the proxy applies to
|
|
40
|
+
* in-flight requests, so `--model gpt-5.6-luna` — the undated name the app's
|
|
41
|
+
* model picker displays — pins the dated deployment behind it rather than being
|
|
42
|
+
* rejected. Anything with no CodeMie equivalent is an error here: at connect
|
|
43
|
+
* time the user is present and can be told, so silently substituting would mean
|
|
44
|
+
* they run something other than what they asked for.
|
|
45
|
+
*/
|
|
46
|
+
export declare function selectCodexModel(discovered: string[], requested?: string): string;
|
|
47
|
+
export interface CodexDesktopState {
|
|
48
|
+
configPath: string;
|
|
49
|
+
backupPath: string | null;
|
|
50
|
+
model: string;
|
|
51
|
+
writtenAt: string;
|
|
52
|
+
}
|
|
53
|
+
export interface WriteCodexDesktopConfigOptions {
|
|
54
|
+
configPath: string;
|
|
55
|
+
statePath: string;
|
|
56
|
+
proxyUrl: string;
|
|
57
|
+
baseUrl: string;
|
|
58
|
+
gatewayKey: string;
|
|
59
|
+
model: string;
|
|
60
|
+
force?: boolean;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Splice the managed block into the user's Codex config and record ownership.
|
|
64
|
+
*
|
|
65
|
+
* The marker state is written BEFORE the config on purpose. If the config write
|
|
66
|
+
* then fails, the marker over-claims — and removal is idempotent, so that is
|
|
67
|
+
* harmless. The reverse order is genuinely unsafe: a written config with no
|
|
68
|
+
* marker is one CodeMie can no longer recognize as its own.
|
|
69
|
+
*/
|
|
70
|
+
export declare function writeCodexDesktopConfig(options: WriteCodexDesktopConfigOptions): Promise<CodexDesktopState>;
|
|
71
|
+
export interface RemoveCodexDesktopResult {
|
|
72
|
+
removed: boolean;
|
|
73
|
+
usedBackup: boolean;
|
|
74
|
+
configPath: string | null;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Remove the managed block, restoring the file to its pre-connect content.
|
|
78
|
+
*
|
|
79
|
+
* The surgical strip is the primary path rather than a wholesale backup restore:
|
|
80
|
+
* a blind restore would also throw away any edits the user made to their Codex
|
|
81
|
+
* config while connected. The backup is the fallback for when stripping cannot
|
|
82
|
+
* produce a parseable file.
|
|
83
|
+
*/
|
|
84
|
+
export declare function removeCodexDesktopConfig(statePath?: string): Promise<RemoveCodexDesktopResult>;
|
|
85
|
+
//# sourceMappingURL=codex-desktop.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-desktop.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/proxy/connectors/codex-desktop.ts"],"names":[],"mappings":"AAiCA;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAGlD;AAED,wFAAwF;AACxF,wBAAgB,wBAAwB,IAAI,MAAM,CAEjD;AAED,gFAAgF;AAChF,wBAAgB,4BAA4B,IAAI,MAAM,EAAE,CAiBvD;AAED,iDAAiD;AACjD,wBAAgB,mBAAmB,CACjC,UAAU,GAAE,MAAM,EAAmC,GACpD,MAAM,GAAG,IAAI,CAEf;AAKD,sEAAsE;AACtE,eAAO,MAAM,aAAa,oBAAoB,CAAC;AAE/C;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAwBxB;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,EAAE,CAAC,CAqCnB;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAYjF;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,8BAA8B;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAoBD;;;;;;;GAOG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,8BAA8B,GACtC,OAAO,CAAC,iBAAiB,CAAC,CA6D5B;AAoBD,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,wBAAsB,wBAAwB,CAC5C,SAAS,GAAE,MAAmC,GAC7C,OAAO,CAAC,wBAAwB,CAAC,CA2DnC"}
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connector that points the Codex desktop app (Codex inside the ChatGPT desktop
|
|
3
|
+
* app) at the local CodeMie proxy by splicing a managed provider block into the
|
|
4
|
+
* user's `~/.codex/config.toml`.
|
|
5
|
+
*
|
|
6
|
+
* CodeMie never installs, launches or patches the app — the shared config file
|
|
7
|
+
* that the app and the Codex CLI both read is the whole integration seam.
|
|
8
|
+
*/
|
|
9
|
+
import { existsSync } from 'node:fs';
|
|
10
|
+
import { copyFile, readFile } from 'node:fs/promises';
|
|
11
|
+
import { homedir } from 'node:os';
|
|
12
|
+
import { join } from 'node:path';
|
|
13
|
+
import TOML from '@iarna/toml';
|
|
14
|
+
import { rankCodexModelIdsByRecency } from '../../../../agents/plugins/codex/codex-models.js';
|
|
15
|
+
import { ConfigurationError } from '../../../../utils/errors.js';
|
|
16
|
+
import { logger } from '../../../../utils/logger.js';
|
|
17
|
+
import { getCodemiePath } from '../../../../utils/paths.js';
|
|
18
|
+
import { sanitizeLogArgs } from '../../../../utils/security.js';
|
|
19
|
+
import { CODEMIE_PROVIDER_ID, buildManagedBlocks, findManagedRegions, spliceManagedBlocks, stripManagedRegions, } from './codex-config-toml.js';
|
|
20
|
+
import { resolveCodexDeployment } from '../../../../providers/plugins/sso/proxy/plugins/codex-model-resolver.js';
|
|
21
|
+
import { writeAtomically } from './vscode.js';
|
|
22
|
+
/**
|
|
23
|
+
* Resolve the config file the desktop app reads.
|
|
24
|
+
*
|
|
25
|
+
* Deliberately NOT `getCodexHomePath()` from the codex agent plugin. That helper
|
|
26
|
+
* is used by code paths which redirect `CODEX_HOME` to a CodeMie-isolated home
|
|
27
|
+
* for the CLI they spawn, and the desktop app never reads that home. A
|
|
28
|
+
* `CODEX_HOME` visible here belongs to the user, and upstream documents the app
|
|
29
|
+
* respecting it, so it is honoured.
|
|
30
|
+
*/
|
|
31
|
+
export function getCodexDesktopConfigPath() {
|
|
32
|
+
const codexHome = process.env.CODEX_HOME || join(homedir(), '.codex');
|
|
33
|
+
return join(codexHome, 'config.toml');
|
|
34
|
+
}
|
|
35
|
+
/** Where the connector records what it owns, mirroring the Claude Desktop precedent. */
|
|
36
|
+
export function getCodexDesktopStatePath() {
|
|
37
|
+
return getCodemiePath('proxy', 'codex-desktop-state.json');
|
|
38
|
+
}
|
|
39
|
+
/** Install locations for the ChatGPT desktop app, which is what ships Codex. */
|
|
40
|
+
export function getCodexDesktopAppCandidates() {
|
|
41
|
+
const home = homedir();
|
|
42
|
+
if (process.platform === 'darwin') {
|
|
43
|
+
return [
|
|
44
|
+
'/Applications/ChatGPT.app',
|
|
45
|
+
join(home, 'Applications', 'ChatGPT.app'),
|
|
46
|
+
];
|
|
47
|
+
}
|
|
48
|
+
if (process.platform === 'win32') {
|
|
49
|
+
const localAppData = process.env.LOCALAPPDATA ?? join(home, 'AppData', 'Local');
|
|
50
|
+
const programFiles = process.env.ProgramFiles ?? 'C:\\Program Files';
|
|
51
|
+
return [
|
|
52
|
+
join(localAppData, 'Programs', 'ChatGPT'),
|
|
53
|
+
join(programFiles, 'ChatGPT'),
|
|
54
|
+
];
|
|
55
|
+
}
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
/** First candidate path that exists, or null. */
|
|
59
|
+
export function findCodexDesktopApp(candidates = getCodexDesktopAppCandidates()) {
|
|
60
|
+
return candidates.find((candidate) => existsSync(candidate)) ?? null;
|
|
61
|
+
}
|
|
62
|
+
/** Bound on the connect-time model listing. */
|
|
63
|
+
const MODEL_LIST_TIMEOUT_MS = 15000;
|
|
64
|
+
/** Suffix for the pre-connect snapshot of the user's Codex config. */
|
|
65
|
+
export const BACKUP_SUFFIX = '.codemie-backup';
|
|
66
|
+
/**
|
|
67
|
+
* Snapshot the config only when CodeMie does not already own part of it.
|
|
68
|
+
*
|
|
69
|
+
* Keyed on marker presence rather than backup presence on purpose. Once our
|
|
70
|
+
* block is in the file, the existing backup is the true pre-CodeMie original and
|
|
71
|
+
* must not be replaced by a copy that already contains our block — which is the
|
|
72
|
+
* bug the Kimi hook injector's create-once backup has.
|
|
73
|
+
*/
|
|
74
|
+
export async function backupIfUnmanaged(configPath, currentText) {
|
|
75
|
+
if (!existsSync(configPath))
|
|
76
|
+
return null;
|
|
77
|
+
const backupPath = `${configPath}${BACKUP_SUFFIX}`;
|
|
78
|
+
const regions = findManagedRegions(currentText);
|
|
79
|
+
const alreadyManaged = regions.header !== null || regions.table !== null;
|
|
80
|
+
if (alreadyManaged) {
|
|
81
|
+
if (existsSync(backupPath)) {
|
|
82
|
+
logger.debug('[proxy] Codex config already managed; keeping existing backup', { backupPath });
|
|
83
|
+
return backupPath;
|
|
84
|
+
}
|
|
85
|
+
// Managed but the backup is gone. Copying the file as-is would enshrine our
|
|
86
|
+
// own block — bearer token included — as the "pre-connect original", and a
|
|
87
|
+
// later disconnect fallback would restore the credential. Reconstruct the
|
|
88
|
+
// original by stripping the managed regions instead.
|
|
89
|
+
await writeAtomically(backupPath, stripManagedRegions(currentText));
|
|
90
|
+
logger.debug('[proxy] Rebuilt missing Codex config backup without managed content', { backupPath });
|
|
91
|
+
return backupPath;
|
|
92
|
+
}
|
|
93
|
+
await copyFile(configPath, backupPath);
|
|
94
|
+
logger.debug('[proxy] Backed up Codex config', { configPath, backupPath });
|
|
95
|
+
return backupPath;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Discover Codex-compatible model ids through the local proxy.
|
|
99
|
+
*
|
|
100
|
+
* Discovery goes through the proxy rather than the backend so the connector
|
|
101
|
+
* exercises exactly the path the app will use — a broken proxy fails here,
|
|
102
|
+
* before the config is written, rather than after.
|
|
103
|
+
*/
|
|
104
|
+
export async function discoverCodexModels(proxyUrl, gatewayKey) {
|
|
105
|
+
const url = new URL('/v1/llm_models?include_all=true', proxyUrl).toString();
|
|
106
|
+
let response;
|
|
107
|
+
try {
|
|
108
|
+
response = await fetch(url, {
|
|
109
|
+
headers: { Authorization: `Bearer ${gatewayKey}` },
|
|
110
|
+
// A proxy that accepts the socket but never answers would otherwise hang
|
|
111
|
+
// `proxy connect` indefinitely, after the daemon has already started.
|
|
112
|
+
signal: AbortSignal.timeout(MODEL_LIST_TIMEOUT_MS),
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
throw new ConfigurationError(`Could not reach the local proxy at ${proxyUrl} to list models: ` +
|
|
117
|
+
`${error instanceof Error ? error.message : String(error)}`);
|
|
118
|
+
}
|
|
119
|
+
if (!response.ok) {
|
|
120
|
+
throw new ConfigurationError(`Local proxy returned ${response.status} for ${url}.`);
|
|
121
|
+
}
|
|
122
|
+
const payload = (await response.json());
|
|
123
|
+
const entries = Array.isArray(payload) ? payload : (payload.data ?? []);
|
|
124
|
+
// Ranked newest-first. The gateway's own order is arbitrary and in practice
|
|
125
|
+
// lists the oldest GPT-5 first, so taking entries[0] would pin a stale model.
|
|
126
|
+
const ids = rankCodexModelIdsByRecency(entries);
|
|
127
|
+
if (ids.length === 0) {
|
|
128
|
+
throw new ConfigurationError('The local proxy exposes no GPT/Codex-compatible model. ' +
|
|
129
|
+
'Enable a GPT-5/Codex deployment in CodeMie, then re-run this command.');
|
|
130
|
+
}
|
|
131
|
+
return ids;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Choose the model to pin.
|
|
135
|
+
*
|
|
136
|
+
* An explicit request is resolved with the same rule the proxy applies to
|
|
137
|
+
* in-flight requests, so `--model gpt-5.6-luna` — the undated name the app's
|
|
138
|
+
* model picker displays — pins the dated deployment behind it rather than being
|
|
139
|
+
* rejected. Anything with no CodeMie equivalent is an error here: at connect
|
|
140
|
+
* time the user is present and can be told, so silently substituting would mean
|
|
141
|
+
* they run something other than what they asked for.
|
|
142
|
+
*/
|
|
143
|
+
export function selectCodexModel(discovered, requested) {
|
|
144
|
+
if (requested === undefined)
|
|
145
|
+
return discovered[0];
|
|
146
|
+
if (requested.trim() === '') {
|
|
147
|
+
throw new ConfigurationError('--model was given an empty value.');
|
|
148
|
+
}
|
|
149
|
+
const resolution = resolveCodexDeployment(requested.trim(), discovered, undefined);
|
|
150
|
+
if (resolution.kind === 'exact' || resolution.kind === 'resolved')
|
|
151
|
+
return resolution.model;
|
|
152
|
+
throw new ConfigurationError(`Model "${requested}" is not available through the proxy. Available: ${discovered.join(', ')}`);
|
|
153
|
+
}
|
|
154
|
+
/** Read the config, or empty text when the file does not exist yet. */
|
|
155
|
+
async function readConfigText(configPath) {
|
|
156
|
+
if (!existsSync(configPath))
|
|
157
|
+
return '';
|
|
158
|
+
return readFile(configPath, 'utf-8');
|
|
159
|
+
}
|
|
160
|
+
/** Parse for validation only — the file itself is never re-serialized. */
|
|
161
|
+
function parseOrThrow(text, configPath) {
|
|
162
|
+
try {
|
|
163
|
+
return TOML.parse(text);
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
throw new ConfigurationError(`Codex config at ${configPath} is not valid TOML and was not changed: ` +
|
|
167
|
+
`${error instanceof Error ? error.message : String(error)}`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Splice the managed block into the user's Codex config and record ownership.
|
|
172
|
+
*
|
|
173
|
+
* The marker state is written BEFORE the config on purpose. If the config write
|
|
174
|
+
* then fails, the marker over-claims — and removal is idempotent, so that is
|
|
175
|
+
* harmless. The reverse order is genuinely unsafe: a written config with no
|
|
176
|
+
* marker is one CodeMie can no longer recognize as its own.
|
|
177
|
+
*/
|
|
178
|
+
export async function writeCodexDesktopConfig(options) {
|
|
179
|
+
const currentText = await readConfigText(options.configPath);
|
|
180
|
+
// Validate and check for conflicts before touching anything on disk.
|
|
181
|
+
if (currentText.trim() !== '') {
|
|
182
|
+
const parsed = parseOrThrow(currentText, options.configPath);
|
|
183
|
+
const active = parsed.model_provider;
|
|
184
|
+
if (!options.force && typeof active === 'string' && active !== CODEMIE_PROVIDER_ID) {
|
|
185
|
+
throw new ConfigurationError(`Codex config already selects model_provider "${active}". ` +
|
|
186
|
+
'Re-run with --force to replace it with the CodeMie provider.');
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
const backupPath = await backupIfUnmanaged(options.configPath, currentText);
|
|
190
|
+
const state = {
|
|
191
|
+
configPath: options.configPath,
|
|
192
|
+
backupPath,
|
|
193
|
+
model: options.model,
|
|
194
|
+
writtenAt: new Date().toISOString(),
|
|
195
|
+
};
|
|
196
|
+
await writeAtomically(options.statePath, `${JSON.stringify(state, null, 2)}\n`);
|
|
197
|
+
const blocks = buildManagedBlocks({
|
|
198
|
+
baseUrl: options.baseUrl,
|
|
199
|
+
gatewayKey: options.gatewayKey,
|
|
200
|
+
model: options.model,
|
|
201
|
+
});
|
|
202
|
+
const next = spliceManagedBlocks(currentText, blocks);
|
|
203
|
+
// Validate what we are about to write, not just what we read. Every splice
|
|
204
|
+
// edge case — a duplicated region, an unrecognized quoted key, a value that
|
|
205
|
+
// escaping did not cover — surfaces here instead of landing a broken
|
|
206
|
+
// config.toml on the user's disk.
|
|
207
|
+
try {
|
|
208
|
+
TOML.parse(next);
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
throw new ConfigurationError(`Refusing to write ${options.configPath}: the result would not be valid TOML ` +
|
|
212
|
+
`(${error instanceof Error ? error.message : String(error)}). The file is unchanged.`);
|
|
213
|
+
}
|
|
214
|
+
await writeAtomically(options.configPath, next);
|
|
215
|
+
// The gateway key is deliberately absent: sanitizeLogArgs redacts by key name,
|
|
216
|
+
// and `gatewayKey` matches none of its patterns, so passing it would write the
|
|
217
|
+
// credential to the log in cleartext. Nothing here needs it.
|
|
218
|
+
logger.info('[proxy] Codex desktop configuration written', ...sanitizeLogArgs({
|
|
219
|
+
configPath: options.configPath,
|
|
220
|
+
backupPath,
|
|
221
|
+
model: options.model,
|
|
222
|
+
baseUrl: options.baseUrl,
|
|
223
|
+
}));
|
|
224
|
+
return state;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Throw when a stripped config still carries CodeMie-owned keys.
|
|
228
|
+
*
|
|
229
|
+
* The post-strip check for disconnect: a parseable result that still selects the
|
|
230
|
+
* CodeMie provider means removal did not actually happen, which is what occurs
|
|
231
|
+
* when the managed sentinels have been lost.
|
|
232
|
+
*/
|
|
233
|
+
function assertNoCodeMieKeys(parsed) {
|
|
234
|
+
if (parsed.model_provider === CODEMIE_PROVIDER_ID) {
|
|
235
|
+
throw new Error(`model_provider is still "${CODEMIE_PROVIDER_ID}"`);
|
|
236
|
+
}
|
|
237
|
+
const providers = parsed.model_providers;
|
|
238
|
+
if (providers !== null && typeof providers === 'object'
|
|
239
|
+
&& CODEMIE_PROVIDER_ID in providers) {
|
|
240
|
+
throw new Error(`model_providers.${CODEMIE_PROVIDER_ID} is still present`);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Remove the managed block, restoring the file to its pre-connect content.
|
|
245
|
+
*
|
|
246
|
+
* The surgical strip is the primary path rather than a wholesale backup restore:
|
|
247
|
+
* a blind restore would also throw away any edits the user made to their Codex
|
|
248
|
+
* config while connected. The backup is the fallback for when stripping cannot
|
|
249
|
+
* produce a parseable file.
|
|
250
|
+
*/
|
|
251
|
+
export async function removeCodexDesktopConfig(statePath = getCodexDesktopStatePath()) {
|
|
252
|
+
if (!existsSync(statePath)) {
|
|
253
|
+
return { removed: false, usedBackup: false, configPath: null };
|
|
254
|
+
}
|
|
255
|
+
const raw = await readFile(statePath, 'utf-8');
|
|
256
|
+
if (raw.trim() === '') {
|
|
257
|
+
return { removed: false, usedBackup: false, configPath: null };
|
|
258
|
+
}
|
|
259
|
+
let state;
|
|
260
|
+
try {
|
|
261
|
+
state = JSON.parse(raw);
|
|
262
|
+
}
|
|
263
|
+
catch (error) {
|
|
264
|
+
throw new ConfigurationError(`CodeMie Codex desktop state at ${statePath} is unreadable: ` +
|
|
265
|
+
`${error instanceof Error ? error.message : String(error)}`);
|
|
266
|
+
}
|
|
267
|
+
if (!existsSync(state.configPath)) {
|
|
268
|
+
await writeAtomically(statePath, '');
|
|
269
|
+
return { removed: false, usedBackup: false, configPath: state.configPath };
|
|
270
|
+
}
|
|
271
|
+
const currentText = await readFile(state.configPath, 'utf-8');
|
|
272
|
+
const stripped = stripManagedRegions(currentText);
|
|
273
|
+
let nextText = stripped;
|
|
274
|
+
let usedBackup = false;
|
|
275
|
+
try {
|
|
276
|
+
if (stripped.trim() !== '') {
|
|
277
|
+
const parsed = TOML.parse(stripped);
|
|
278
|
+
// Parsing is not enough: if the sentinels were lost the strip is a silent
|
|
279
|
+
// no-op, and reporting success would leave the CodeMie provider — and its
|
|
280
|
+
// bearer header — in the user's config.
|
|
281
|
+
assertNoCodeMieKeys(parsed);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
catch {
|
|
285
|
+
if (!state.backupPath || !existsSync(state.backupPath)) {
|
|
286
|
+
throw new ConfigurationError(`Could not cleanly remove the CodeMie block from ${state.configPath} ` +
|
|
287
|
+
'(the managed markers appear to be damaged or missing) and no backup is ' +
|
|
288
|
+
`available to restore. Remove the model_provider and [model_providers.${CODEMIE_PROVIDER_ID}] ` +
|
|
289
|
+
'entries by hand.');
|
|
290
|
+
}
|
|
291
|
+
nextText = await readFile(state.backupPath, 'utf-8');
|
|
292
|
+
usedBackup = true;
|
|
293
|
+
logger.warn('[proxy] Surgical removal of the CodeMie Codex block failed; restored the backup', ...sanitizeLogArgs({ configPath: state.configPath, backupPath: state.backupPath }));
|
|
294
|
+
}
|
|
295
|
+
await writeAtomically(state.configPath, nextText);
|
|
296
|
+
await writeAtomically(statePath, '');
|
|
297
|
+
return { removed: true, usedBackup, configPath: state.configPath };
|
|
298
|
+
}
|
|
299
|
+
//# sourceMappingURL=codex-desktop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-desktop.js","sourceRoot":"","sources":["../../../../../src/cli/commands/proxy/connectors/codex-desktop.ts"],"names":[],"mappings":"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"}
|