codex-copilot-dx 0.6.21 → 0.7.1
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 +142 -323
- package/bin/cli.mjs +26 -130
- package/package.json +2 -8
- package/scripts/benchmark.mjs +0 -114
- package/src/adapter.mjs +22 -107
- package/src/auth-profile.mjs +18 -130
- package/src/cli-animation.mjs +108 -0
- package/src/cli-auth.mjs +44 -398
- package/src/cli-models.mjs +21 -49
- package/src/cli-options.mjs +53 -75
- package/src/cli-status.mjs +6 -23
- package/src/config.mjs +2 -8
- package/src/copilot.mjs +2 -2
- package/src/doctor.mjs +44 -291
- package/src/model-cache.mjs +4 -11
- package/src/models.mjs +0 -184
- package/src/observability.mjs +1 -38
- package/src/profile-model-runtime.mjs +61 -189
- package/src/profile-routing.mjs +2 -102
- package/src/profile-runtime.mjs +15 -68
- package/src/responses-handler.mjs +1 -1
- package/src/responses-proxy.mjs +1 -1
- package/src/running-adapter.mjs +2 -4
- package/src/stream-errors.mjs +3 -6
- package/src/stream-performance.mjs +1 -1
- package/src/terminal-activity.mjs +40 -34
- package/src/terminal-animation.mjs +249 -0
- package/src/usage.mjs +0 -31
- package/src/user-settings.mjs +50 -0
- package/src/anthropic-handler.mjs +0 -195
- package/src/anthropic.mjs +0 -387
- package/src/claude-config.mjs +0 -57
- package/src/claude-desktop-config.mjs +0 -317
- package/src/cli-error.mjs +0 -50
- package/src/pm-studio-asar.mjs +0 -1244
- package/src/pm-studio-bundle-content.mjs +0 -165
- package/src/pm-studio-relay.mjs +0 -563
- package/src/pm-studio-setup-lock.mjs +0 -336
- package/src/pm-studio-setup.mjs +0 -1581
- package/src/pm-studio-status.mjs +0 -369
- package/src/token-counter-service.mjs +0 -211
- package/src/token-counter-worker.mjs +0 -16
|
@@ -1,336 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import os from "node:os";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { createHash, randomBytes } from "node:crypto";
|
|
5
|
-
|
|
6
|
-
const LOCK_KIND = "ccdx-pm-studio-setup-lock";
|
|
7
|
-
const LOCK_SCHEMA_VERSION = 1;
|
|
8
|
-
const MAX_LOCK_BYTES = 2_048;
|
|
9
|
-
const MAX_ACQUIRE_ATTEMPTS = 8;
|
|
10
|
-
const LOCK_RECORD_KEYS = Object.freeze([
|
|
11
|
-
"app_path_sha256",
|
|
12
|
-
"kind",
|
|
13
|
-
"nonce",
|
|
14
|
-
"pid",
|
|
15
|
-
"schema_version",
|
|
16
|
-
"uid",
|
|
17
|
-
]);
|
|
18
|
-
|
|
19
|
-
function setupLockError(code, message, cause) {
|
|
20
|
-
const error = new Error(message, cause ? { cause } : undefined);
|
|
21
|
-
error.code = code;
|
|
22
|
-
return error;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function sha256Hex(value) {
|
|
26
|
-
return createHash("sha256").update(value).digest("hex");
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function currentUid() {
|
|
30
|
-
return typeof process.getuid === "function" ? process.getuid() : null;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function sameFile(left, right) {
|
|
34
|
-
return left?.dev === right?.dev && left?.ino === right?.ino;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function isOwnedRegularFile(stat, uid) {
|
|
38
|
-
return stat?.isFile?.() === true
|
|
39
|
-
&& stat?.isSymbolicLink?.() !== true
|
|
40
|
-
&& (uid === null || stat.uid === uid);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function strictLockRecord(text, appPathSha256, uid) {
|
|
44
|
-
let record;
|
|
45
|
-
try {
|
|
46
|
-
record = JSON.parse(text);
|
|
47
|
-
} catch {
|
|
48
|
-
return null;
|
|
49
|
-
}
|
|
50
|
-
if (!record || Array.isArray(record) || typeof record !== "object"
|
|
51
|
-
|| JSON.stringify(record) !== text
|
|
52
|
-
|| JSON.stringify(Object.keys(record).sort()) !== JSON.stringify(LOCK_RECORD_KEYS)
|
|
53
|
-
|| record.schema_version !== LOCK_SCHEMA_VERSION
|
|
54
|
-
|| record.kind !== LOCK_KIND
|
|
55
|
-
|| record.app_path_sha256 !== appPathSha256
|
|
56
|
-
|| !Number.isSafeInteger(record.pid)
|
|
57
|
-
|| record.pid <= 0
|
|
58
|
-
|| record.pid > 0x7fff_ffff
|
|
59
|
-
|| record.uid !== uid
|
|
60
|
-
|| typeof record.nonce !== "string"
|
|
61
|
-
|| !/^[0-9a-f]{32}$/.test(record.nonce)) {
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
|
-
return record;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function readLockSnapshot(lockPath, appPathSha256, io, uid) {
|
|
68
|
-
let before;
|
|
69
|
-
try {
|
|
70
|
-
before = io.lstatSync(lockPath, { bigint: false });
|
|
71
|
-
} catch (error) {
|
|
72
|
-
if (error?.code === "ENOENT") return null;
|
|
73
|
-
throw error;
|
|
74
|
-
}
|
|
75
|
-
if (!isOwnedRegularFile(before, uid)
|
|
76
|
-
|| !Number.isSafeInteger(before.size)
|
|
77
|
-
|| before.size <= 0
|
|
78
|
-
|| before.size > MAX_LOCK_BYTES) {
|
|
79
|
-
return { safe: false };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const noFollow = io.constants?.O_NOFOLLOW || 0;
|
|
83
|
-
let descriptor;
|
|
84
|
-
try {
|
|
85
|
-
descriptor = io.openSync(lockPath, io.constants.O_RDONLY | noFollow);
|
|
86
|
-
const opened = io.fstatSync(descriptor, { bigint: false });
|
|
87
|
-
if (!isOwnedRegularFile(opened, uid)
|
|
88
|
-
|| !sameFile(before, opened)
|
|
89
|
-
|| opened.size !== before.size) {
|
|
90
|
-
return { safe: false };
|
|
91
|
-
}
|
|
92
|
-
const text = io.readFileSync(descriptor, { encoding: "utf8" });
|
|
93
|
-
const after = io.fstatSync(descriptor, { bigint: false });
|
|
94
|
-
if (!sameFile(opened, after)
|
|
95
|
-
|| after.size !== opened.size
|
|
96
|
-
|| after.mtimeMs !== opened.mtimeMs
|
|
97
|
-
|| after.ctimeMs !== opened.ctimeMs) {
|
|
98
|
-
return { safe: false };
|
|
99
|
-
}
|
|
100
|
-
const record = strictLockRecord(text, appPathSha256, uid);
|
|
101
|
-
return record ? { safe: true, stat: opened, record } : { safe: false };
|
|
102
|
-
} catch (error) {
|
|
103
|
-
if (["ELOOP", "ENOENT"].includes(error?.code)) return { safe: false };
|
|
104
|
-
throw error;
|
|
105
|
-
} finally {
|
|
106
|
-
if (descriptor !== undefined) io.closeSync(descriptor);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function defaultProcessAlive(pid) {
|
|
111
|
-
try {
|
|
112
|
-
process.kill(pid, 0);
|
|
113
|
-
return true;
|
|
114
|
-
} catch (error) {
|
|
115
|
-
return error?.code !== "ESRCH";
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function writeCandidate(candidatePath, record, io) {
|
|
120
|
-
const noFollow = io.constants?.O_NOFOLLOW || 0;
|
|
121
|
-
const descriptor = io.openSync(
|
|
122
|
-
candidatePath,
|
|
123
|
-
io.constants.O_WRONLY | io.constants.O_CREAT | io.constants.O_EXCL | noFollow,
|
|
124
|
-
0o600,
|
|
125
|
-
);
|
|
126
|
-
try {
|
|
127
|
-
io.writeFileSync(descriptor, JSON.stringify(record), { encoding: "utf8" });
|
|
128
|
-
io.fsyncSync(descriptor);
|
|
129
|
-
return io.fstatSync(descriptor, { bigint: false });
|
|
130
|
-
} finally {
|
|
131
|
-
io.closeSync(descriptor);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function removeOwnLock(lockPath, ownership, appPathSha256, io, uid) {
|
|
136
|
-
let snapshot;
|
|
137
|
-
try {
|
|
138
|
-
snapshot = readLockSnapshot(lockPath, appPathSha256, io, uid);
|
|
139
|
-
} catch {
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
if (!snapshot?.safe
|
|
143
|
-
|| snapshot.record.nonce !== ownership.nonce
|
|
144
|
-
|| !sameFile(snapshot.stat, ownership.stat)) {
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
try {
|
|
148
|
-
io.unlinkSync(lockPath);
|
|
149
|
-
} catch (error) {
|
|
150
|
-
if (error?.code !== "ENOENT") throw error;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
function reclaimStaleLock(lockPath, snapshot, io, uid) {
|
|
155
|
-
const quarantinePath = `${lockPath}.stale-${randomBytes(16).toString("hex")}`;
|
|
156
|
-
try {
|
|
157
|
-
io.renameSync(lockPath, quarantinePath);
|
|
158
|
-
} catch (error) {
|
|
159
|
-
if (["ENOENT", "EEXIST"].includes(error?.code)) return false;
|
|
160
|
-
throw error;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
let moved;
|
|
164
|
-
try {
|
|
165
|
-
moved = readLockSnapshot(
|
|
166
|
-
quarantinePath,
|
|
167
|
-
snapshot.record.app_path_sha256,
|
|
168
|
-
io,
|
|
169
|
-
uid,
|
|
170
|
-
);
|
|
171
|
-
if (!moved) return false;
|
|
172
|
-
if (!moved.safe
|
|
173
|
-
|| !sameFile(moved.stat, snapshot.stat)
|
|
174
|
-
|| JSON.stringify(moved.record) !== JSON.stringify(snapshot.record)) {
|
|
175
|
-
try {
|
|
176
|
-
io.linkSync(quarantinePath, lockPath);
|
|
177
|
-
} catch (error) {
|
|
178
|
-
if (error?.code !== "EEXIST") {
|
|
179
|
-
throw setupLockError(
|
|
180
|
-
"PM_STUDIO_SETUP_LOCK_UNSAFE",
|
|
181
|
-
"PM Studio setup lock changed and could not be restored safely",
|
|
182
|
-
error,
|
|
183
|
-
);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
try {
|
|
187
|
-
io.unlinkSync(quarantinePath);
|
|
188
|
-
} catch (error) {
|
|
189
|
-
if (error?.code !== "ENOENT") throw error;
|
|
190
|
-
}
|
|
191
|
-
throw setupLockError(
|
|
192
|
-
"PM_STUDIO_SETUP_LOCK_UNSAFE",
|
|
193
|
-
"PM Studio setup lock changed while a stale record was being isolated",
|
|
194
|
-
);
|
|
195
|
-
}
|
|
196
|
-
io.unlinkSync(quarantinePath);
|
|
197
|
-
return true;
|
|
198
|
-
} catch (error) {
|
|
199
|
-
if (error?.code === "ENOENT") return false;
|
|
200
|
-
throw error;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
function createLockRecord(appPathSha256, uid) {
|
|
205
|
-
return {
|
|
206
|
-
app_path_sha256: appPathSha256,
|
|
207
|
-
kind: LOCK_KIND,
|
|
208
|
-
nonce: randomBytes(16).toString("hex"),
|
|
209
|
-
pid: process.pid,
|
|
210
|
-
schema_version: LOCK_SCHEMA_VERSION,
|
|
211
|
-
uid,
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
export function pmStudioSetupLockPath({ appPath, temporaryRoot = os.tmpdir() } = {}) {
|
|
216
|
-
if (typeof appPath !== "string" || appPath.length === 0) {
|
|
217
|
-
throw new TypeError("PM Studio app path is required for the setup lock");
|
|
218
|
-
}
|
|
219
|
-
if (typeof temporaryRoot !== "string" || temporaryRoot.length === 0) {
|
|
220
|
-
throw new TypeError("PM Studio setup lock temporary root is required");
|
|
221
|
-
}
|
|
222
|
-
const appPathSha256 = sha256Hex(path.resolve(appPath));
|
|
223
|
-
return path.join(path.resolve(temporaryRoot), `.ccdx-pm-studio-setup-${appPathSha256}.lock`);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
export async function withPmStudioSetupLock({
|
|
227
|
-
appPath,
|
|
228
|
-
temporaryRoot = os.tmpdir(),
|
|
229
|
-
fsImpl = fs,
|
|
230
|
-
processAlive = defaultProcessAlive,
|
|
231
|
-
} = {}, fn) {
|
|
232
|
-
if (typeof fn !== "function") throw new TypeError("PM Studio setup lock callback is required");
|
|
233
|
-
if (!fsImpl || typeof processAlive !== "function") {
|
|
234
|
-
throw new TypeError("PM Studio setup lock dependencies are invalid");
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
const lockPath = pmStudioSetupLockPath({ appPath, temporaryRoot });
|
|
238
|
-
const appPathSha256 = path.basename(lockPath).slice(
|
|
239
|
-
".ccdx-pm-studio-setup-".length,
|
|
240
|
-
-".lock".length,
|
|
241
|
-
);
|
|
242
|
-
const uid = currentUid();
|
|
243
|
-
let ownership = null;
|
|
244
|
-
|
|
245
|
-
for (let attempt = 0; attempt < MAX_ACQUIRE_ATTEMPTS && !ownership; attempt += 1) {
|
|
246
|
-
const record = createLockRecord(appPathSha256, uid);
|
|
247
|
-
const candidatePath = `${lockPath}.candidate-${record.nonce}`;
|
|
248
|
-
let publicationError = null;
|
|
249
|
-
try {
|
|
250
|
-
const candidateStat = writeCandidate(candidatePath, record, fsImpl);
|
|
251
|
-
try {
|
|
252
|
-
fsImpl.linkSync(candidatePath, lockPath);
|
|
253
|
-
ownership = { nonce: record.nonce, stat: candidateStat };
|
|
254
|
-
const stat = fsImpl.lstatSync(lockPath, { bigint: false });
|
|
255
|
-
if (!isOwnedRegularFile(stat, uid) || !sameFile(stat, candidateStat)) {
|
|
256
|
-
throw setupLockError(
|
|
257
|
-
"PM_STUDIO_SETUP_LOCK_UNSAFE",
|
|
258
|
-
"PM Studio setup lock was not published as an owned regular file",
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
} catch (error) {
|
|
262
|
-
if (error?.code !== "EEXIST") throw error;
|
|
263
|
-
}
|
|
264
|
-
} catch (error) {
|
|
265
|
-
publicationError = error;
|
|
266
|
-
} finally {
|
|
267
|
-
try {
|
|
268
|
-
fsImpl.unlinkSync(candidatePath);
|
|
269
|
-
} catch (error) {
|
|
270
|
-
if (error?.code !== "ENOENT" && !publicationError) publicationError = error;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
if (publicationError) {
|
|
274
|
-
if (ownership?.nonce === record.nonce) {
|
|
275
|
-
removeOwnLock(lockPath, ownership, appPathSha256, fsImpl, uid);
|
|
276
|
-
ownership = null;
|
|
277
|
-
}
|
|
278
|
-
throw publicationError;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
if (ownership) break;
|
|
282
|
-
let snapshot;
|
|
283
|
-
try {
|
|
284
|
-
snapshot = readLockSnapshot(lockPath, appPathSha256, fsImpl, uid);
|
|
285
|
-
} catch (error) {
|
|
286
|
-
throw setupLockError(
|
|
287
|
-
"PM_STUDIO_SETUP_LOCK_FAILED",
|
|
288
|
-
"PM Studio setup lock could not be inspected safely",
|
|
289
|
-
error,
|
|
290
|
-
);
|
|
291
|
-
}
|
|
292
|
-
if (!snapshot) continue;
|
|
293
|
-
if (!snapshot.safe) {
|
|
294
|
-
throw setupLockError(
|
|
295
|
-
"PM_STUDIO_SETUP_BUSY",
|
|
296
|
-
"PM Studio setup is locked by an unverified lock record; no files were changed",
|
|
297
|
-
);
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
let alive = true;
|
|
301
|
-
try {
|
|
302
|
-
alive = processAlive(snapshot.record.pid) !== false;
|
|
303
|
-
} catch {
|
|
304
|
-
alive = true;
|
|
305
|
-
}
|
|
306
|
-
if (alive) {
|
|
307
|
-
throw setupLockError(
|
|
308
|
-
"PM_STUDIO_SETUP_BUSY",
|
|
309
|
-
`PM Studio setup is already running in process ${snapshot.record.pid}; no files were changed`,
|
|
310
|
-
);
|
|
311
|
-
}
|
|
312
|
-
try {
|
|
313
|
-
reclaimStaleLock(lockPath, snapshot, fsImpl, uid);
|
|
314
|
-
} catch (error) {
|
|
315
|
-
if (error?.code === "PM_STUDIO_SETUP_LOCK_UNSAFE") throw error;
|
|
316
|
-
throw setupLockError(
|
|
317
|
-
"PM_STUDIO_SETUP_LOCK_FAILED",
|
|
318
|
-
"PM Studio stale setup lock could not be reclaimed safely",
|
|
319
|
-
error,
|
|
320
|
-
);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
if (!ownership) {
|
|
325
|
-
throw setupLockError(
|
|
326
|
-
"PM_STUDIO_SETUP_BUSY",
|
|
327
|
-
"PM Studio setup lock changed repeatedly; no files were changed",
|
|
328
|
-
);
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
try {
|
|
332
|
-
return await fn();
|
|
333
|
-
} finally {
|
|
334
|
-
removeOwnLock(lockPath, ownership, appPathSha256, fsImpl, uid);
|
|
335
|
-
}
|
|
336
|
-
}
|