coding-tool-x 3.8.1 → 3.8.2
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/CHANGELOG.md +2 -0
- package/dist/web/assets/{Analytics-8dRv1aYW.js → Analytics-COEUXmd4.js} +1 -1
- package/dist/web/assets/{ConfigTemplates-BQRXSICO.js → ConfigTemplates-DLLkS53H.js} +1 -1
- package/dist/web/assets/{Home-BtzWhKIa.js → Home-DCEyLzwX.js} +1 -1
- package/dist/web/assets/{PluginManager-BTa-Ygf6.js → PluginManager-Oe1ZHoMO.js} +1 -1
- package/dist/web/assets/{ProjectList-F_cB8ldA.js → ProjectList-CWjuAFof.js} +1 -1
- package/dist/web/assets/{SessionList-LOrbPQvu.js → SessionList-v3ehGg9U.js} +1 -1
- package/dist/web/assets/{SkillManager-BzI_t-yV.js → SkillManager-DUF_qP5S.js} +1 -1
- package/dist/web/assets/{WorkspaceManager-Db9RGiz7.js → WorkspaceManager-CjAWBosO.js} +1 -1
- package/dist/web/assets/index-D5hyHPj7.js +2 -0
- package/dist/web/index.html +1 -1
- package/docs/superpowers/plans/2026-08-10-codex-conversion-compatibility.md +251 -0
- package/docs/superpowers/plans/2026-08-11-windows-command-window-hiding.md +90 -0
- package/docs/superpowers/specs/2026-08-10-codex-conversion-compatibility-design.md +61 -0
- package/docs/superpowers/specs/2026-08-11-windows-command-window-hiding-design.md +44 -0
- package/package.json +1 -1
- package/src/commands/update.js +1 -1
- package/src/server/opencode-proxy-server.js +55 -1037
- package/src/server/services/claude-wire.js +694 -0
- package/src/server/services/codex-wire.js +219 -0
- package/src/server/services/gemini-wire.js +759 -0
- package/src/server/services/model-detector.js +49 -131
- package/src/server/services/omp-channels.js +23 -4
- package/src/server/services/omp-gateway.js +29 -1
- package/src/server/services/omp-settings-manager.js +27 -3
- package/src/server/services/opencode-gateway-adapters.js +22 -1147
- package/src/server/services/opencode-normalization.js +546 -0
- package/src/server/services/session-history-index.js +1 -1
- package/src/server/services/session-history-worker.js +2 -1
- package/src/server/services/speed-test.js +85 -303
- package/dist/web/assets/index-DIWJmyL6.js +0 -2
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const crypto = require('crypto');
|
|
4
|
+
const os = require('os');
|
|
5
|
+
|
|
6
|
+
const CODEX_CLIENT_VERSION = '0.144.1';
|
|
7
|
+
const CODEX_ORIGINATOR = 'codex_exec';
|
|
8
|
+
const CODEX_RESERVED_METADATA_KEYS = new Set([
|
|
9
|
+
'x-codex-installation-id',
|
|
10
|
+
'x-codex-window-id',
|
|
11
|
+
'x-codex-turn-metadata',
|
|
12
|
+
'session_id',
|
|
13
|
+
'thread_id',
|
|
14
|
+
'turn_id'
|
|
15
|
+
]);
|
|
16
|
+
const CODEX_UNSUPPORTED_BODY_FIELDS = [
|
|
17
|
+
'max_output_tokens',
|
|
18
|
+
'max_completion_tokens',
|
|
19
|
+
'temperature',
|
|
20
|
+
'top_p',
|
|
21
|
+
'top_k',
|
|
22
|
+
'min_p',
|
|
23
|
+
'presence_penalty',
|
|
24
|
+
'frequency_penalty',
|
|
25
|
+
'repetition_penalty',
|
|
26
|
+
'stop',
|
|
27
|
+
'service_tier',
|
|
28
|
+
'user',
|
|
29
|
+
'previous_response_id',
|
|
30
|
+
'prompt_cache_retention',
|
|
31
|
+
'safety_identifier'
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
let installationId = '';
|
|
35
|
+
|
|
36
|
+
function cloneJsonCompatible(value) {
|
|
37
|
+
try {
|
|
38
|
+
return JSON.parse(JSON.stringify(value));
|
|
39
|
+
} catch {
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function createId() {
|
|
45
|
+
return typeof crypto.randomUUID === 'function'
|
|
46
|
+
? crypto.randomUUID()
|
|
47
|
+
: `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 14)}`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function getInstallationId() {
|
|
51
|
+
if (!installationId) installationId = createId();
|
|
52
|
+
return installationId;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function normalizeId(value, fallbackFactory = createId) {
|
|
56
|
+
const normalized = typeof value === 'string' ? value.trim() : '';
|
|
57
|
+
return normalized || fallbackFactory();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function normalizeCodexResponsesInput(inputValue) {
|
|
61
|
+
if (typeof inputValue === 'string') {
|
|
62
|
+
return [
|
|
63
|
+
{
|
|
64
|
+
type: 'message',
|
|
65
|
+
role: 'user',
|
|
66
|
+
content: [{ type: 'input_text', text: inputValue }]
|
|
67
|
+
}
|
|
68
|
+
];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (!Array.isArray(inputValue)) return undefined;
|
|
72
|
+
return inputValue.map(item => {
|
|
73
|
+
if (!item || typeof item !== 'object') return item;
|
|
74
|
+
const clonedItem = cloneJsonCompatible(item);
|
|
75
|
+
if (String(clonedItem?.role || '').trim().toLowerCase() === 'system') {
|
|
76
|
+
clonedItem.role = 'developer';
|
|
77
|
+
}
|
|
78
|
+
return clonedItem;
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function normalizeInclude(value) {
|
|
83
|
+
const include = Array.isArray(value)
|
|
84
|
+
? value.filter(item => typeof item === 'string' && item.trim())
|
|
85
|
+
: [];
|
|
86
|
+
if (!include.includes('reasoning.encrypted_content')) {
|
|
87
|
+
include.push('reasoning.encrypted_content');
|
|
88
|
+
}
|
|
89
|
+
return [...new Set(include)];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function normalizeClientMetadata(value) {
|
|
93
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return {};
|
|
94
|
+
return Object.fromEntries(
|
|
95
|
+
Object.entries(value)
|
|
96
|
+
.filter(([key, item]) => !CODEX_RESERVED_METADATA_KEYS.has(key) && typeof item === 'string')
|
|
97
|
+
.map(([key, item]) => [key, item])
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function resolveUserAgent(value) {
|
|
102
|
+
if (typeof value === 'string' && value.trim()) return value.trim();
|
|
103
|
+
const terminal = String(process.env.TERM_PROGRAM || process.env.TERM || 'Terminal').trim() || 'Terminal';
|
|
104
|
+
const platformName = process.platform === 'darwin' ? 'Mac OS' : process.platform;
|
|
105
|
+
return `${CODEX_ORIGINATOR}/${CODEX_CLIENT_VERSION} (${platformName} ${os.release()}; ${process.arch}) ${terminal} (${CODEX_ORIGINATOR}; ${CODEX_CLIENT_VERSION})`;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function buildTurnMetadata({ installationId: currentInstallationId, sessionId, threadId, turnId, windowId }) {
|
|
109
|
+
return JSON.stringify({
|
|
110
|
+
installation_id: currentInstallationId,
|
|
111
|
+
session_id: sessionId,
|
|
112
|
+
thread_id: threadId,
|
|
113
|
+
turn_id: turnId,
|
|
114
|
+
window_id: windowId,
|
|
115
|
+
request_kind: 'turn'
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function createCodexRequest(payload = {}, options = {}) {
|
|
120
|
+
const source = payload && typeof payload === 'object' && !Array.isArray(payload)
|
|
121
|
+
? payload
|
|
122
|
+
: {};
|
|
123
|
+
const body = cloneJsonCompatible(source);
|
|
124
|
+
const fallbackModel = typeof options.fallbackModel === 'string' ? options.fallbackModel.trim() : '';
|
|
125
|
+
const requestedSessionId = options.sessionId || body.prompt_cache_key;
|
|
126
|
+
if (body.model === undefined && fallbackModel) body.model = fallbackModel;
|
|
127
|
+
|
|
128
|
+
const sessionId = normalizeId(requestedSessionId, createId);
|
|
129
|
+
const threadId = normalizeId(options.threadId, () => sessionId);
|
|
130
|
+
const windowId = normalizeId(options.windowId, () => `${sessionId}:0`);
|
|
131
|
+
const turnId = normalizeId(options.turnId, createId);
|
|
132
|
+
const currentInstallationId = normalizeId(options.installationId, getInstallationId);
|
|
133
|
+
const normalizedInput = normalizeCodexResponsesInput(body.input);
|
|
134
|
+
if (normalizedInput !== undefined) body.input = normalizedInput;
|
|
135
|
+
body.stream = true;
|
|
136
|
+
if (body.parallel_tool_calls === undefined) body.parallel_tool_calls = true;
|
|
137
|
+
if (typeof body.instructions !== 'string') body.instructions = '';
|
|
138
|
+
body.store = false;
|
|
139
|
+
body.include = normalizeInclude(body.include);
|
|
140
|
+
const reasoningEffort = typeof body.reasoning_effort === 'string'
|
|
141
|
+
? body.reasoning_effort.trim().toLowerCase()
|
|
142
|
+
: '';
|
|
143
|
+
if (reasoningEffort && body.reasoning === undefined && ['minimal', 'low', 'medium', 'high', 'xhigh', 'max', 'none'].includes(reasoningEffort)) {
|
|
144
|
+
body.reasoning = { effort: reasoningEffort };
|
|
145
|
+
}
|
|
146
|
+
delete body.reasoning_effort;
|
|
147
|
+
body.prompt_cache_key = normalizeId(body.prompt_cache_key, () => sessionId);
|
|
148
|
+
|
|
149
|
+
const callerMetadata = normalizeClientMetadata(body.client_metadata);
|
|
150
|
+
const turnMetadata = buildTurnMetadata({
|
|
151
|
+
installationId: currentInstallationId,
|
|
152
|
+
sessionId,
|
|
153
|
+
threadId,
|
|
154
|
+
turnId,
|
|
155
|
+
windowId
|
|
156
|
+
});
|
|
157
|
+
body.client_metadata = {
|
|
158
|
+
...callerMetadata,
|
|
159
|
+
'x-codex-installation-id': currentInstallationId,
|
|
160
|
+
session_id: sessionId,
|
|
161
|
+
thread_id: threadId,
|
|
162
|
+
'x-codex-window-id': windowId,
|
|
163
|
+
turn_id: turnId,
|
|
164
|
+
'x-codex-turn-metadata': turnMetadata
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
CODEX_UNSUPPORTED_BODY_FIELDS.forEach(field => delete body[field]);
|
|
168
|
+
|
|
169
|
+
const headers = {
|
|
170
|
+
authorization: `Bearer ${String(options.apiKey || '')}`,
|
|
171
|
+
accept: 'text/event-stream',
|
|
172
|
+
'content-type': 'application/json',
|
|
173
|
+
originator: typeof options.originator === 'string' && options.originator.trim()
|
|
174
|
+
? options.originator.trim()
|
|
175
|
+
: CODEX_ORIGINATOR,
|
|
176
|
+
'user-agent': resolveUserAgent(options.userAgent),
|
|
177
|
+
'session-id': sessionId,
|
|
178
|
+
'thread-id': threadId,
|
|
179
|
+
'x-client-request-id': sessionId,
|
|
180
|
+
'x-codex-window-id': windowId,
|
|
181
|
+
'x-codex-turn-metadata': turnMetadata,
|
|
182
|
+
'x-codex-beta-features': 'remote_compaction_v2'
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
return {
|
|
186
|
+
body,
|
|
187
|
+
headers,
|
|
188
|
+
model: String(body.model || fallbackModel || '').trim()
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function buildCodexTargetUrl(baseUrl = '') {
|
|
193
|
+
let targetUrl;
|
|
194
|
+
try {
|
|
195
|
+
targetUrl = new URL(String(baseUrl || '').trim());
|
|
196
|
+
} catch {
|
|
197
|
+
return '';
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
let pathname = targetUrl.pathname.replace(/\/+$/, '');
|
|
201
|
+
if (!pathname || pathname === '/') {
|
|
202
|
+
pathname = '/responses';
|
|
203
|
+
} else if (pathname.endsWith('/responses') || pathname.endsWith('/v1/responses')) {
|
|
204
|
+
// Already an endpoint.
|
|
205
|
+
} else {
|
|
206
|
+
pathname = `${pathname}/responses`;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
targetUrl.pathname = pathname;
|
|
210
|
+
return targetUrl.toString();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
module.exports = {
|
|
214
|
+
CODEX_CLIENT_VERSION,
|
|
215
|
+
CODEX_ORIGINATOR,
|
|
216
|
+
buildCodexTargetUrl,
|
|
217
|
+
createCodexRequest,
|
|
218
|
+
normalizeCodexResponsesInput
|
|
219
|
+
};
|