@i14ks/ccv 0.24.0 → 0.25.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 +2 -10
- package/bundle/ccv.mjs +139 -1033
- package/package.json +50 -53
- package/web/assets/{codemirror-BABguQzY.js → codemirror-BdKpW4CC.js} +1 -1
- package/web/assets/{index-BHEVBqv1.js → index-B2BGvdag.js} +1 -1
- package/web/assets/index-BCLbqlhA.js +134 -0
- package/web/assets/{index-CZppS1t2.js → index-BrkwvvWk.js} +1 -1
- package/web/assets/{index-BRzmWdWn.js → index-BroMLvyS.js} +1 -1
- package/web/assets/{index-BaKf7c69.js → index-C59b0_Vk.js} +1 -1
- package/web/assets/index-C6Y6TadO.css +1 -0
- package/web/assets/{index-BmRYCxGv.js → index-CRsndRFc.js} +1 -1
- package/web/assets/{index-DnlEeQVW.js → index-CWTFMuFd.js} +1 -1
- package/web/assets/{index-U9tL3Foh.js → index-CZuUjzhP.js} +1 -1
- package/web/assets/{index-Ck0zkLid.js → index-ChyP1fTD.js} +1 -1
- package/web/assets/{index-Di0Nghq9.js → index-D6DYiY6f.js} +1 -1
- package/web/assets/{index-BJQdUP7a.js → index-D83he8x-.js} +1 -1
- package/web/assets/{index-DW1Fnc9x.js → index-DPrfFlZq.js} +1 -1
- package/web/assets/{index-dSYnVYDn.js → index-DXHZO0ym.js} +1 -1
- package/web/assets/{index-BQiRpvdM.js → index-Dd7rh20x.js} +1 -1
- package/web/assets/{index-BnqCpVA0.js → index-DqnCWDLh.js} +1 -1
- package/web/assets/{index-BWAAro79.js → index-Si6no75_.js} +1 -1
- package/web/assets/{index-CIsgyM-R.js → index-UxKgaDrj.js} +1 -1
- package/web/assets/{index-CxF-ndAb.js → index-YCUybqa_.js} +1 -1
- package/web/assets/{index-DogVeywh.js → index-wsSNo9PM.js} +1 -1
- package/web/assets/{index-Bqjj9q2W.js → index-yXtesgZ4.js} +1 -1
- package/web/index.html +2 -2
- package/web/assets/index-DXMZoXqv.js +0 -136
- package/web/assets/index-DafZE925.css +0 -1
package/bundle/ccv.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// dist/ccv.js
|
|
4
|
-
import { spawn as
|
|
4
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
5
5
|
import { readFile as readFile17 } from "node:fs/promises";
|
|
6
|
-
import
|
|
6
|
+
import path24 from "node:path";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
8
|
import { parseArgs } from "node:util";
|
|
9
9
|
|
|
@@ -145,10 +145,10 @@ function envDefaults() {
|
|
|
145
145
|
|
|
146
146
|
// ../host/dist/server.js
|
|
147
147
|
import { createServer } from "node:http";
|
|
148
|
-
import { createReadStream, existsSync as
|
|
149
|
-
import
|
|
150
|
-
import { homedir as
|
|
151
|
-
import { randomUUID as
|
|
148
|
+
import { createReadStream, existsSync as existsSync4, statSync as statSync3 } from "node:fs";
|
|
149
|
+
import path23 from "node:path";
|
|
150
|
+
import { homedir as homedir6 } from "node:os";
|
|
151
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
152
152
|
import { WebSocketServer } from "ws";
|
|
153
153
|
import { renameSession as renameSession2 } from "@anthropic-ai/claude-agent-sdk";
|
|
154
154
|
|
|
@@ -187,12 +187,12 @@ function hashText(text) {
|
|
|
187
187
|
// ../host/dist/workspace-ids.js
|
|
188
188
|
function workspaceIdRemap(paths, sessionsOf) {
|
|
189
189
|
const byLegacy = /* @__PURE__ */ new Map();
|
|
190
|
-
for (const
|
|
191
|
-
const id = workspaceIdFromPath(
|
|
192
|
-
for (const legacy of formerWorkspaceIdsFromPath(
|
|
190
|
+
for (const path25 of paths) {
|
|
191
|
+
const id = workspaceIdFromPath(path25);
|
|
192
|
+
for (const legacy of formerWorkspaceIdsFromPath(path25)) {
|
|
193
193
|
const group = byLegacy.get(legacy) ?? [];
|
|
194
194
|
if (!group.some((target) => target.id === id))
|
|
195
|
-
group.push({ id, path:
|
|
195
|
+
group.push({ id, path: path25 });
|
|
196
196
|
byLegacy.set(legacy, group);
|
|
197
197
|
}
|
|
198
198
|
}
|
|
@@ -4217,865 +4217,18 @@ function describe2(error) {
|
|
|
4217
4217
|
return error instanceof Error ? error.message : String(error);
|
|
4218
4218
|
}
|
|
4219
4219
|
|
|
4220
|
-
// ../host/dist/codex-session.js
|
|
4221
|
-
import { EventEmitter as EventEmitter5 } from "node:events";
|
|
4222
|
-
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
4223
|
-
|
|
4224
|
-
// ../host/dist/codex-cli.js
|
|
4225
|
-
import { accessSync, constants as constants2, existsSync as existsSync2, readFileSync, statSync } from "node:fs";
|
|
4226
|
-
import { homedir as homedir4 } from "node:os";
|
|
4227
|
-
import path8 from "node:path";
|
|
4228
|
-
var CODEX_MISSING_HINT = "Codex CLI \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D. \u0423\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0435: npm install -g @openai/codex, \u0437\u0430\u0442\u0435\u043C \u0432\u044B\u043F\u043E\u043B\u043D\u0438\u0442\u0435 codex login. \u0415\u0441\u043B\u0438 CLI \u0443\u0436\u0435 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D, \u0437\u0430\u0434\u0430\u0439\u0442\u0435 CCV_CODEX_PATH \u0438 \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u0435 ccv.";
|
|
4229
|
-
function codexLauncher() {
|
|
4230
|
-
const forced = process.env.CCV_CODEX_PATH;
|
|
4231
|
-
if (forced)
|
|
4232
|
-
return launcherFor(path8.resolve(forced));
|
|
4233
|
-
const dirs = (process.env.PATH ?? "").split(path8.delimiter).filter(Boolean);
|
|
4234
|
-
if (process.platform === "win32") {
|
|
4235
|
-
const local = process.env.LOCALAPPDATA ?? path8.join(homedir4(), "AppData", "Local");
|
|
4236
|
-
dirs.push(path8.join(local, "Programs", "OpenAI", "Codex", "bin"));
|
|
4237
|
-
dirs.push(path8.join(process.env.APPDATA ?? path8.join(homedir4(), "AppData", "Roaming"), "npm"));
|
|
4238
|
-
} else {
|
|
4239
|
-
dirs.push(path8.join(homedir4(), ".local", "bin"), "/usr/local/bin", "/opt/homebrew/bin");
|
|
4240
|
-
}
|
|
4241
|
-
for (const dir of dirs) {
|
|
4242
|
-
for (const name of process.platform === "win32" ? ["codex.exe", "codex.cmd", "codex"] : ["codex"]) {
|
|
4243
|
-
const found = launcherFor(path8.join(dir.replace(/^"|"$/g, ""), name));
|
|
4244
|
-
if (found)
|
|
4245
|
-
return found;
|
|
4246
|
-
}
|
|
4247
|
-
}
|
|
4248
|
-
return null;
|
|
4249
|
-
}
|
|
4250
|
-
function launcherFor(file) {
|
|
4251
|
-
try {
|
|
4252
|
-
if (!statSync(file).isFile())
|
|
4253
|
-
return null;
|
|
4254
|
-
if (/\.[cm]?js$/i.test(file))
|
|
4255
|
-
return { file: process.execPath, prefix: [file] };
|
|
4256
|
-
if (process.platform === "win32" && /\.(cmd|bat|ps1)$/i.test(file)) {
|
|
4257
|
-
const root = path8.dirname(file);
|
|
4258
|
-
const candidates = [path8.join(root, "node_modules", "@openai", "codex", "bin", "codex.js")];
|
|
4259
|
-
const shim = readFileSync(file, "utf8");
|
|
4260
|
-
for (const match of shim.matchAll(/(?:%dp0%|%~dp0|\$basedir)[\\/]([^"\r\n]+?\.[cm]?js)/gi)) {
|
|
4261
|
-
candidates.push(path8.resolve(root, match[1]));
|
|
4262
|
-
}
|
|
4263
|
-
const script = candidates.find((candidate) => existsSync2(candidate));
|
|
4264
|
-
return script ? { file: process.execPath, prefix: [script] } : null;
|
|
4265
|
-
}
|
|
4266
|
-
if (process.platform === "win32" && !/\.exe$/i.test(file))
|
|
4267
|
-
return null;
|
|
4268
|
-
accessSync(file, constants2.X_OK);
|
|
4269
|
-
return { file, prefix: [] };
|
|
4270
|
-
} catch {
|
|
4271
|
-
return null;
|
|
4272
|
-
}
|
|
4273
|
-
}
|
|
4274
|
-
|
|
4275
|
-
// ../host/dist/codex-rpc.js
|
|
4276
|
-
import { EventEmitter as EventEmitter4 } from "node:events";
|
|
4277
|
-
import { execFile as execFile4, spawn as spawn3 } from "node:child_process";
|
|
4278
|
-
import { createInterface as createInterface2 } from "node:readline";
|
|
4279
|
-
var CodexRpc = class extends EventEmitter4 {
|
|
4280
|
-
#child;
|
|
4281
|
-
#pending = /* @__PURE__ */ new Map();
|
|
4282
|
-
#nextId = 0;
|
|
4283
|
-
#closed = false;
|
|
4284
|
-
#stderr = "";
|
|
4285
|
-
constructor(launcher, cwd) {
|
|
4286
|
-
super();
|
|
4287
|
-
this.#child = spawn3(launcher.file, [...launcher.prefix, "app-server", "--listen", "stdio://"], {
|
|
4288
|
-
cwd,
|
|
4289
|
-
windowsHide: true,
|
|
4290
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
4291
|
-
env: { ...process.env, NO_COLOR: "1" }
|
|
4292
|
-
});
|
|
4293
|
-
createInterface2({ input: this.#child.stdout }).on("line", (line) => {
|
|
4294
|
-
let message;
|
|
4295
|
-
try {
|
|
4296
|
-
message = JSON.parse(line);
|
|
4297
|
-
} catch {
|
|
4298
|
-
return;
|
|
4299
|
-
}
|
|
4300
|
-
if (!message || typeof message !== "object")
|
|
4301
|
-
return;
|
|
4302
|
-
if (message.method) {
|
|
4303
|
-
this.emit("message", message);
|
|
4304
|
-
return;
|
|
4305
|
-
}
|
|
4306
|
-
const pending = typeof message.id === "number" ? this.#pending.get(message.id) : void 0;
|
|
4307
|
-
if (!pending)
|
|
4308
|
-
return;
|
|
4309
|
-
this.#pending.delete(message.id);
|
|
4310
|
-
clearTimeout(pending.timer);
|
|
4311
|
-
if (message.error)
|
|
4312
|
-
pending.reject(new Error(message.error.message));
|
|
4313
|
-
else
|
|
4314
|
-
pending.resolve(message.result);
|
|
4315
|
-
});
|
|
4316
|
-
this.#child.stderr.on("data", (chunk) => {
|
|
4317
|
-
this.#stderr = (this.#stderr + chunk.toString()).slice(-4e3);
|
|
4318
|
-
this.emit("stderr", chunk.toString());
|
|
4319
|
-
});
|
|
4320
|
-
this.#child.stdin.on("error", (error) => this.#finish(error));
|
|
4321
|
-
this.#child.on("error", (error) => this.#finish(error));
|
|
4322
|
-
this.#child.on("exit", (code) => this.#finish(new Error(`Codex \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043B\u0441\u044F (${code ?? "signal"}). ${this.#stderr.trim()}`)));
|
|
4323
|
-
}
|
|
4324
|
-
request(method, params = {}) {
|
|
4325
|
-
if (this.#closed)
|
|
4326
|
-
return Promise.reject(new Error("\u0421\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435 \u0441 Codex \u0437\u0430\u043A\u0440\u044B\u0442\u043E"));
|
|
4327
|
-
const id = ++this.#nextId;
|
|
4328
|
-
return new Promise((resolve, reject) => {
|
|
4329
|
-
const timer = setTimeout(() => {
|
|
4330
|
-
this.#pending.delete(id);
|
|
4331
|
-
reject(new Error(`Codex \u043D\u0435 \u043E\u0442\u0432\u0435\u0442\u0438\u043B \u043D\u0430 ${method} \u0437\u0430 60 \u0441\u0435\u043A\u0443\u043D\u0434`));
|
|
4332
|
-
}, 6e4);
|
|
4333
|
-
this.#pending.set(id, { resolve: (value) => resolve(value), reject, timer });
|
|
4334
|
-
this.write({ id, method, params });
|
|
4335
|
-
});
|
|
4336
|
-
}
|
|
4337
|
-
write(message) {
|
|
4338
|
-
if (!this.#closed)
|
|
4339
|
-
this.#child.stdin.write(JSON.stringify(message) + "\n");
|
|
4340
|
-
}
|
|
4341
|
-
close() {
|
|
4342
|
-
this.#finish(new Error("\u0421\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435 \u0441 Codex \u0437\u0430\u043A\u0440\u044B\u0442\u043E"), false);
|
|
4343
|
-
this.#child.stdin.end();
|
|
4344
|
-
const child = this.#child;
|
|
4345
|
-
if (child.exitCode !== null)
|
|
4346
|
-
return;
|
|
4347
|
-
if (process.platform === "win32" && child.pid) {
|
|
4348
|
-
execFile4("taskkill", ["/pid", String(child.pid), "/T", "/F"], { windowsHide: true }, () => {
|
|
4349
|
-
if (child.exitCode === null)
|
|
4350
|
-
child.kill();
|
|
4351
|
-
});
|
|
4352
|
-
} else
|
|
4353
|
-
child.kill("SIGTERM");
|
|
4354
|
-
}
|
|
4355
|
-
#finish(error, notify = true) {
|
|
4356
|
-
if (this.#closed)
|
|
4357
|
-
return;
|
|
4358
|
-
this.#closed = true;
|
|
4359
|
-
for (const pending of this.#pending.values()) {
|
|
4360
|
-
clearTimeout(pending.timer);
|
|
4361
|
-
pending.reject(error);
|
|
4362
|
-
}
|
|
4363
|
-
this.#pending.clear();
|
|
4364
|
-
if (notify)
|
|
4365
|
-
this.emit("exit", error);
|
|
4366
|
-
}
|
|
4367
|
-
};
|
|
4368
|
-
|
|
4369
|
-
// ../host/dist/codex-session.js
|
|
4370
|
-
function codexPolicy(mode) {
|
|
4371
|
-
switch (mode) {
|
|
4372
|
-
case "default":
|
|
4373
|
-
return { approvalPolicy: "untrusted", sandbox: "workspace-write" };
|
|
4374
|
-
case "acceptEdits":
|
|
4375
|
-
return { approvalPolicy: "on-request", sandbox: "workspace-write" };
|
|
4376
|
-
case "plan":
|
|
4377
|
-
return { approvalPolicy: "untrusted", sandbox: "read-only" };
|
|
4378
|
-
case "bypassPermissions":
|
|
4379
|
-
return { approvalPolicy: "never", sandbox: "danger-full-access" };
|
|
4380
|
-
default:
|
|
4381
|
-
throw new Error(`Codex \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0440\u0435\u0436\u0438\u043C \u043F\u0440\u0430\u0432 \xAB${mode}\xBB`);
|
|
4382
|
-
}
|
|
4383
|
-
}
|
|
4384
|
-
function codexUsage(limits) {
|
|
4385
|
-
const window = (value) => value ? {
|
|
4386
|
-
utilization: Math.min(100, Math.max(0, value.usedPercent)),
|
|
4387
|
-
resetsAt: value.resetsAt ? new Date(value.resetsAt * 1e3).toISOString() : ""
|
|
4388
|
-
} : null;
|
|
4389
|
-
return {
|
|
4390
|
-
available: !!(limits.primary || limits.secondary),
|
|
4391
|
-
plan: limits.planType ?? "",
|
|
4392
|
-
fiveHour: window(limits.primary),
|
|
4393
|
-
sevenDay: window(limits.secondary),
|
|
4394
|
-
sevenDayOpus: null,
|
|
4395
|
-
fetchedAt: Date.now()
|
|
4396
|
-
};
|
|
4397
|
-
}
|
|
4398
|
-
var CodexSession = class extends EventEmitter5 {
|
|
4399
|
-
provider = "codex";
|
|
4400
|
-
id;
|
|
4401
|
-
workspaceId;
|
|
4402
|
-
cwd;
|
|
4403
|
-
journal = new Journal();
|
|
4404
|
-
#store;
|
|
4405
|
-
#record;
|
|
4406
|
-
#history = Promise.resolve([]);
|
|
4407
|
-
#rpc = null;
|
|
4408
|
-
#ready = Promise.resolve();
|
|
4409
|
-
#state = "starting";
|
|
4410
|
-
#lastTurn = null;
|
|
4411
|
-
#capabilities = null;
|
|
4412
|
-
#usage = null;
|
|
4413
|
-
#context = null;
|
|
4414
|
-
#turnId = null;
|
|
4415
|
-
#turnStartedAt = 0;
|
|
4416
|
-
#turnUsage = null;
|
|
4417
|
-
#totalUsage = null;
|
|
4418
|
-
#turnUsageBaseline = null;
|
|
4419
|
-
#interruptRequested = false;
|
|
4420
|
-
#busy = false;
|
|
4421
|
-
#startingTurn = false;
|
|
4422
|
-
#generation = 0;
|
|
4423
|
-
#queue = [];
|
|
4424
|
-
#pending = /* @__PURE__ */ new Map();
|
|
4425
|
-
#texts = /* @__PURE__ */ new Map();
|
|
4426
|
-
#tools = /* @__PURE__ */ new Set();
|
|
4427
|
-
#items = /* @__PURE__ */ new Map();
|
|
4428
|
-
#titleIsDefault;
|
|
4429
|
-
#unsaved = [];
|
|
4430
|
-
#flushTimer = null;
|
|
4431
|
-
constructor(options2) {
|
|
4432
|
-
super();
|
|
4433
|
-
this.workspaceId = options2.workspaceId;
|
|
4434
|
-
this.cwd = options2.cwd;
|
|
4435
|
-
this.#store = options2.store;
|
|
4436
|
-
this.#record = options2.record ? { ...options2.record } : {
|
|
4437
|
-
id: randomUUID3(),
|
|
4438
|
-
conversationId: null,
|
|
4439
|
-
workspaceId: options2.workspaceId,
|
|
4440
|
-
cwd: options2.cwd,
|
|
4441
|
-
title: options2.defaultTitle ?? null,
|
|
4442
|
-
model: options2.model ?? null,
|
|
4443
|
-
permissionMode: options2.permissionMode ?? "default",
|
|
4444
|
-
effort: null,
|
|
4445
|
-
createdAt: Date.now(),
|
|
4446
|
-
updatedAt: Date.now()
|
|
4447
|
-
};
|
|
4448
|
-
if (options2.permissionMode)
|
|
4449
|
-
this.#record.permissionMode = options2.permissionMode;
|
|
4450
|
-
if (options2.model)
|
|
4451
|
-
this.#record.model = options2.model;
|
|
4452
|
-
this.id = this.#record.id;
|
|
4453
|
-
this.#context = this.#record.context ?? null;
|
|
4454
|
-
if (!options2.record?.conversationId) {
|
|
4455
|
-
this.#totalUsage = { inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheCreationTokens: 0 };
|
|
4456
|
-
}
|
|
4457
|
-
this.#titleIsDefault = !options2.record;
|
|
4458
|
-
}
|
|
4459
|
-
get state() {
|
|
4460
|
-
return this.#state;
|
|
4461
|
-
}
|
|
4462
|
-
get capabilities() {
|
|
4463
|
-
return this.#capabilities;
|
|
4464
|
-
}
|
|
4465
|
-
get claudeSessionId() {
|
|
4466
|
-
return this.id;
|
|
4467
|
-
}
|
|
4468
|
-
get parentSessionId() {
|
|
4469
|
-
return null;
|
|
4470
|
-
}
|
|
4471
|
-
get usage() {
|
|
4472
|
-
return this.#usage;
|
|
4473
|
-
}
|
|
4474
|
-
get context() {
|
|
4475
|
-
return this.#context;
|
|
4476
|
-
}
|
|
4477
|
-
history() {
|
|
4478
|
-
return this.#history;
|
|
4479
|
-
}
|
|
4480
|
-
summary() {
|
|
4481
|
-
return {
|
|
4482
|
-
id: this.id,
|
|
4483
|
-
provider: this.provider,
|
|
4484
|
-
claudeSessionId: this.id,
|
|
4485
|
-
workspaceId: this.workspaceId,
|
|
4486
|
-
cwd: this.cwd,
|
|
4487
|
-
parentSessionId: null,
|
|
4488
|
-
title: this.#record.title,
|
|
4489
|
-
state: this.#state,
|
|
4490
|
-
lastTurn: this.#lastTurn,
|
|
4491
|
-
backgroundWork: false,
|
|
4492
|
-
tasks: [],
|
|
4493
|
-
model: this.#record.model,
|
|
4494
|
-
permissionMode: this.#record.permissionMode,
|
|
4495
|
-
effort: this.#record.effort,
|
|
4496
|
-
ultracode: false,
|
|
4497
|
-
thinking: true,
|
|
4498
|
-
switchModelsOnFlag: false,
|
|
4499
|
-
createdAt: this.#record.createdAt,
|
|
4500
|
-
updatedAt: this.#record.updatedAt,
|
|
4501
|
-
lastSeq: this.journal.lastSeq,
|
|
4502
|
-
totalCostUsd: 0
|
|
4503
|
-
};
|
|
4504
|
-
}
|
|
4505
|
-
start() {
|
|
4506
|
-
this.#history = this.#store.readEvents(this.id).then((entries) => {
|
|
4507
|
-
const pending = /* @__PURE__ */ new Set();
|
|
4508
|
-
for (const { event } of entries) {
|
|
4509
|
-
if (event.kind === "permission.request")
|
|
4510
|
-
pending.add(event.requestId);
|
|
4511
|
-
if (event.kind === "permission.resolved")
|
|
4512
|
-
pending.delete(event.requestId);
|
|
4513
|
-
}
|
|
4514
|
-
for (const requestId of pending)
|
|
4515
|
-
entries.push({ seq: entries.length + 1, ts: Date.now(), event: {
|
|
4516
|
-
kind: "permission.resolved",
|
|
4517
|
-
requestId,
|
|
4518
|
-
decision: "deny",
|
|
4519
|
-
reason: "\u041F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0438\u0439 \u043F\u0440\u043E\u0446\u0435\u0441\u0441 Codex \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043D"
|
|
4520
|
-
} });
|
|
4521
|
-
return entries;
|
|
4522
|
-
});
|
|
4523
|
-
this.#launch();
|
|
4524
|
-
}
|
|
4525
|
-
#launch() {
|
|
4526
|
-
const generation = ++this.#generation;
|
|
4527
|
-
this.#ready = this.#connect(generation);
|
|
4528
|
-
void this.#ready.catch((error) => {
|
|
4529
|
-
if (generation === this.#generation)
|
|
4530
|
-
this.#fail(error);
|
|
4531
|
-
});
|
|
4532
|
-
}
|
|
4533
|
-
async #connect(generation) {
|
|
4534
|
-
await this.#history;
|
|
4535
|
-
await this.#store.save(this.#record);
|
|
4536
|
-
if (generation !== this.#generation)
|
|
4537
|
-
return;
|
|
4538
|
-
const reason = networkGuard.blockedReason();
|
|
4539
|
-
if (reason)
|
|
4540
|
-
throw new Error(reason);
|
|
4541
|
-
const launcher = codexLauncher();
|
|
4542
|
-
if (!launcher)
|
|
4543
|
-
throw new Error(CODEX_MISSING_HINT);
|
|
4544
|
-
const rpc = new CodexRpc(launcher, this.cwd);
|
|
4545
|
-
this.#rpc = rpc;
|
|
4546
|
-
rpc.on("message", (message) => {
|
|
4547
|
-
if (this.#rpc === rpc)
|
|
4548
|
-
this.#message(message);
|
|
4549
|
-
});
|
|
4550
|
-
rpc.on("stderr", (data) => this.emit("stderr", data));
|
|
4551
|
-
rpc.on("exit", (error) => {
|
|
4552
|
-
if (this.#rpc === rpc)
|
|
4553
|
-
this.#fail(error);
|
|
4554
|
-
});
|
|
4555
|
-
await rpc.request("initialize", { clientInfo: { name: "ccv", title: "Claude Code Visual", version: "0.1.0" } });
|
|
4556
|
-
if (this.#rpc !== rpc)
|
|
4557
|
-
return;
|
|
4558
|
-
rpc.write({ method: "initialized", params: {} });
|
|
4559
|
-
const policy = codexPolicy(this.#record.permissionMode);
|
|
4560
|
-
const result = await rpc.request(this.#record.conversationId ? "thread/resume" : "thread/start", {
|
|
4561
|
-
...this.#record.conversationId ? { threadId: this.#record.conversationId } : {},
|
|
4562
|
-
cwd: this.cwd,
|
|
4563
|
-
...this.#record.model ? { model: this.#record.model } : {},
|
|
4564
|
-
approvalPolicy: policy.approvalPolicy,
|
|
4565
|
-
sandbox: policy.sandbox
|
|
4566
|
-
});
|
|
4567
|
-
if (this.#rpc !== rpc)
|
|
4568
|
-
return;
|
|
4569
|
-
this.#record.conversationId = result.thread.id;
|
|
4570
|
-
this.#record.model = result.model;
|
|
4571
|
-
if (!this.#record.effort && result.reasoningEffort)
|
|
4572
|
-
this.#record.effort = result.reasoningEffort;
|
|
4573
|
-
await this.#store.save(this.#record);
|
|
4574
|
-
if (this.#rpc !== rpc)
|
|
4575
|
-
return;
|
|
4576
|
-
this.#capabilities = {
|
|
4577
|
-
cwd: this.cwd,
|
|
4578
|
-
model: result.model,
|
|
4579
|
-
permissionMode: this.#record.permissionMode,
|
|
4580
|
-
slashCommands: [],
|
|
4581
|
-
commands: [],
|
|
4582
|
-
models: [],
|
|
4583
|
-
tools: ["Bash", "apply_patch", "web_search"],
|
|
4584
|
-
agents: [],
|
|
4585
|
-
mcpServers: [],
|
|
4586
|
-
flags: []
|
|
4587
|
-
};
|
|
4588
|
-
this.emit("capabilities");
|
|
4589
|
-
this.#setState("idle");
|
|
4590
|
-
void this.#loadModels(rpc).catch((error) => {
|
|
4591
|
-
if (this.#rpc === rpc)
|
|
4592
|
-
this.#notice(error);
|
|
4593
|
-
});
|
|
4594
|
-
void this.refreshUsage();
|
|
4595
|
-
}
|
|
4596
|
-
async #loadModels(rpc) {
|
|
4597
|
-
const models = [];
|
|
4598
|
-
let cursor = null;
|
|
4599
|
-
do {
|
|
4600
|
-
const page = await rpc.request("model/list", { cursor, limit: 100 });
|
|
4601
|
-
for (const model of page.data) {
|
|
4602
|
-
const levels = (model.supportedReasoningEfforts ?? []).map((e) => e.reasoningEffort).filter((e) => ["low", "medium", "high", "xhigh", "max"].includes(e));
|
|
4603
|
-
models.push({
|
|
4604
|
-
value: model.model,
|
|
4605
|
-
resolvedModel: model.model,
|
|
4606
|
-
displayName: model.displayName,
|
|
4607
|
-
description: model.description,
|
|
4608
|
-
supportsEffort: levels.length > 0,
|
|
4609
|
-
effortLevels: levels,
|
|
4610
|
-
supportsThinking: false,
|
|
4611
|
-
supportsAutoMode: false
|
|
4612
|
-
});
|
|
4613
|
-
}
|
|
4614
|
-
cursor = page.nextCursor;
|
|
4615
|
-
} while (cursor && this.#rpc === rpc);
|
|
4616
|
-
if (this.#capabilities && this.#rpc === rpc) {
|
|
4617
|
-
this.#capabilities.models = models;
|
|
4618
|
-
this.emit("capabilities");
|
|
4619
|
-
}
|
|
4620
|
-
}
|
|
4621
|
-
sendPrompt(text, images) {
|
|
4622
|
-
const reason = networkGuard.blockedReason();
|
|
4623
|
-
if (reason) {
|
|
4624
|
-
this.#notice(new Error(reason));
|
|
4625
|
-
return;
|
|
4626
|
-
}
|
|
4627
|
-
if (this.#state === "closed" || this.#state === "error") {
|
|
4628
|
-
this.#notice(new Error("\u041F\u0435\u0440\u0435\u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0438\u0442\u0435 \u0441\u0435\u0441\u0441\u0438\u044E Codex \u043F\u0435\u0440\u0435\u0434 \u043E\u0442\u043F\u0440\u0430\u0432\u043A\u043E\u0439"));
|
|
4629
|
-
return;
|
|
4630
|
-
}
|
|
4631
|
-
if (!text.trim() && !images?.length)
|
|
4632
|
-
return;
|
|
4633
|
-
this.#append({ kind: "user.message", text, ...images?.length ? { images } : {} });
|
|
4634
|
-
if (this.#titleIsDefault) {
|
|
4635
|
-
this.#record.title = text.trim().split("\n")[0].slice(0, 100) || "Codex";
|
|
4636
|
-
this.#titleIsDefault = false;
|
|
4637
|
-
this.emit("summary", this.summary());
|
|
4638
|
-
}
|
|
4639
|
-
this.#queue.push({ text, images });
|
|
4640
|
-
void this.#drain();
|
|
4641
|
-
}
|
|
4642
|
-
async #drain() {
|
|
4643
|
-
if (this.#busy || this.#startingTurn || !this.#queue.length)
|
|
4644
|
-
return;
|
|
4645
|
-
const generation = this.#generation;
|
|
4646
|
-
this.#busy = true;
|
|
4647
|
-
this.#startingTurn = true;
|
|
4648
|
-
try {
|
|
4649
|
-
await this.#ready;
|
|
4650
|
-
if (generation !== this.#generation)
|
|
4651
|
-
return;
|
|
4652
|
-
const prompt = this.#queue.shift();
|
|
4653
|
-
if (!prompt || !this.#rpc || this.#state === "closed" || this.#state === "error") {
|
|
4654
|
-
this.#busy = false;
|
|
4655
|
-
return;
|
|
4656
|
-
}
|
|
4657
|
-
const reason = networkGuard.blockedReason();
|
|
4658
|
-
if (reason)
|
|
4659
|
-
throw new Error(reason);
|
|
4660
|
-
this.#turnStartedAt = Date.now();
|
|
4661
|
-
this.#turnUsage = null;
|
|
4662
|
-
this.#turnUsageBaseline = this.#totalUsage;
|
|
4663
|
-
this.#lastTurn = null;
|
|
4664
|
-
this.#setState("running");
|
|
4665
|
-
const policy = codexPolicy(this.#record.permissionMode);
|
|
4666
|
-
const sandboxPolicy = this.#record.permissionMode === "bypassPermissions" ? { type: "dangerFullAccess" } : this.#record.permissionMode === "plan" ? { type: "readOnly", networkAccess: false } : {
|
|
4667
|
-
type: "workspaceWrite",
|
|
4668
|
-
writableRoots: [this.cwd],
|
|
4669
|
-
networkAccess: false,
|
|
4670
|
-
excludeTmpdirEnvVar: false,
|
|
4671
|
-
excludeSlashTmp: false
|
|
4672
|
-
};
|
|
4673
|
-
const result = await this.#rpc.request("turn/start", {
|
|
4674
|
-
threadId: this.#record.conversationId,
|
|
4675
|
-
cwd: this.cwd,
|
|
4676
|
-
input: [{ type: "text", text: prompt.text, text_elements: [] }, ...(prompt.images ?? []).map((image) => ({
|
|
4677
|
-
type: "image",
|
|
4678
|
-
url: `data:${image.mediaType};base64,${image.data}`
|
|
4679
|
-
}))],
|
|
4680
|
-
model: this.#record.model,
|
|
4681
|
-
effort: this.#record.effort,
|
|
4682
|
-
approvalPolicy: policy.approvalPolicy,
|
|
4683
|
-
sandboxPolicy
|
|
4684
|
-
});
|
|
4685
|
-
if (this.#busy)
|
|
4686
|
-
this.#turnId = result.turn.id;
|
|
4687
|
-
if (this.#interruptRequested && this.#turnId)
|
|
4688
|
-
await this.interrupt();
|
|
4689
|
-
} catch (error) {
|
|
4690
|
-
if (generation === this.#generation)
|
|
4691
|
-
this.#fail(error);
|
|
4692
|
-
} finally {
|
|
4693
|
-
if (generation === this.#generation) {
|
|
4694
|
-
this.#startingTurn = false;
|
|
4695
|
-
if (!this.#busy)
|
|
4696
|
-
void this.#drain();
|
|
4697
|
-
}
|
|
4698
|
-
}
|
|
4699
|
-
}
|
|
4700
|
-
#message(message) {
|
|
4701
|
-
const p = message.params ?? {};
|
|
4702
|
-
if (message.id !== void 0 && message.method) {
|
|
4703
|
-
this.#request(message.id, message.method, p);
|
|
4704
|
-
return;
|
|
4705
|
-
}
|
|
4706
|
-
if (p.threadId && p.threadId !== this.#record.conversationId)
|
|
4707
|
-
return;
|
|
4708
|
-
switch (message.method) {
|
|
4709
|
-
case "turn/started": {
|
|
4710
|
-
const turn = p.turn;
|
|
4711
|
-
this.#turnId = turn.id;
|
|
4712
|
-
break;
|
|
4713
|
-
}
|
|
4714
|
-
case "item/agentMessage/delta":
|
|
4715
|
-
case "item/reasoning/summaryTextDelta": {
|
|
4716
|
-
const id = String(p.itemId);
|
|
4717
|
-
const thinking = message.method !== "item/agentMessage/delta";
|
|
4718
|
-
const key = `${id}:${thinking ? "thinking" : "text"}`;
|
|
4719
|
-
const delta = String(p.delta ?? "");
|
|
4720
|
-
const block = this.#texts.get(key) ?? { text: "", thinking };
|
|
4721
|
-
block.text += delta;
|
|
4722
|
-
this.#texts.set(key, block);
|
|
4723
|
-
this.#append({ kind: thinking ? "thinking.delta" : "assistant.delta", blockId: key, text: delta });
|
|
4724
|
-
break;
|
|
4725
|
-
}
|
|
4726
|
-
case "item/started":
|
|
4727
|
-
this.#item(p.item, false);
|
|
4728
|
-
break;
|
|
4729
|
-
case "item/completed":
|
|
4730
|
-
this.#item(p.item, true);
|
|
4731
|
-
break;
|
|
4732
|
-
case "thread/tokenUsage/updated": {
|
|
4733
|
-
const usage = p.tokenUsage;
|
|
4734
|
-
if (usage?.last && usage.modelContextWindow) {
|
|
4735
|
-
this.#context = { tokens: usage.last.totalTokens, maxTokens: usage.modelContextWindow, fetchedAt: Date.now() };
|
|
4736
|
-
this.#record.context = this.#context;
|
|
4737
|
-
this.emit("context", this.#context);
|
|
4738
|
-
}
|
|
4739
|
-
if (usage?.total) {
|
|
4740
|
-
const total = {
|
|
4741
|
-
inputTokens: usage.total.inputTokens,
|
|
4742
|
-
outputTokens: usage.total.outputTokens,
|
|
4743
|
-
cacheReadTokens: usage.total.cachedInputTokens ?? 0,
|
|
4744
|
-
cacheCreationTokens: usage.total.cacheWriteInputTokens ?? 0
|
|
4745
|
-
};
|
|
4746
|
-
if (this.#busy && this.#turnUsageBaseline) {
|
|
4747
|
-
const baseline = this.#turnUsageBaseline;
|
|
4748
|
-
this.#turnUsage = {
|
|
4749
|
-
inputTokens: Math.max(0, total.inputTokens - baseline.inputTokens),
|
|
4750
|
-
outputTokens: Math.max(0, total.outputTokens - baseline.outputTokens),
|
|
4751
|
-
cacheReadTokens: Math.max(0, total.cacheReadTokens - baseline.cacheReadTokens),
|
|
4752
|
-
cacheCreationTokens: Math.max(0, total.cacheCreationTokens - baseline.cacheCreationTokens)
|
|
4753
|
-
};
|
|
4754
|
-
}
|
|
4755
|
-
this.#totalUsage = total;
|
|
4756
|
-
}
|
|
4757
|
-
break;
|
|
4758
|
-
}
|
|
4759
|
-
case "account/rateLimits/updated":
|
|
4760
|
-
if (p.rateLimits)
|
|
4761
|
-
this.#setUsage(p.rateLimits);
|
|
4762
|
-
break;
|
|
4763
|
-
case "serverRequest/resolved": {
|
|
4764
|
-
const requestId = String(p.requestId);
|
|
4765
|
-
if (this.#pending.delete(requestId)) {
|
|
4766
|
-
this.#append({ kind: "permission.resolved", requestId, decision: "deny", reason: "\u0417\u0430\u043F\u0440\u043E\u0441 \u0437\u0430\u043A\u0440\u044B\u0442 Codex" });
|
|
4767
|
-
this.#setState(this.#pending.size ? "waiting_permission" : "running");
|
|
4768
|
-
}
|
|
4769
|
-
break;
|
|
4770
|
-
}
|
|
4771
|
-
case "turn/completed": {
|
|
4772
|
-
const turn = p.turn;
|
|
4773
|
-
this.#lastTurn = turn.status === "completed" ? "completed" : turn.status === "interrupted" ? "interrupted" : "failed";
|
|
4774
|
-
if (turn.error?.message)
|
|
4775
|
-
this.#notice(new Error(turn.error.message));
|
|
4776
|
-
this.#finishTurn(turn.status, turn.durationMs);
|
|
4777
|
-
void this.refreshUsage();
|
|
4778
|
-
break;
|
|
4779
|
-
}
|
|
4780
|
-
case "error": {
|
|
4781
|
-
const error = p.error;
|
|
4782
|
-
this.#notice(new Error(error?.message ?? "\u041E\u0448\u0438\u0431\u043A\u0430 Codex"));
|
|
4783
|
-
break;
|
|
4784
|
-
}
|
|
4785
|
-
}
|
|
4786
|
-
}
|
|
4787
|
-
#item(item, done) {
|
|
4788
|
-
if (!item)
|
|
4789
|
-
return;
|
|
4790
|
-
this.#items.set(item.id, item);
|
|
4791
|
-
if (item.type === "agentMessage" || item.type === "reasoning" || item.type === "plan") {
|
|
4792
|
-
if (!done)
|
|
4793
|
-
return;
|
|
4794
|
-
const thinking = item.type === "reasoning";
|
|
4795
|
-
const key = `${item.id}:${thinking ? "thinking" : "text"}`;
|
|
4796
|
-
const text = item.text ?? item.summary?.join("\n") ?? this.#texts.get(key)?.text ?? "";
|
|
4797
|
-
this.#texts.delete(key);
|
|
4798
|
-
if (text)
|
|
4799
|
-
this.#append({ kind: thinking ? "assistant.thinking" : "assistant.text", text, blockId: key });
|
|
4800
|
-
return;
|
|
4801
|
-
}
|
|
4802
|
-
if (!["commandExecution", "fileChange", "mcpToolCall", "webSearch", "imageView", "collabAgentToolCall"].includes(item.type))
|
|
4803
|
-
return;
|
|
4804
|
-
if (!this.#tools.has(item.id)) {
|
|
4805
|
-
this.#tools.add(item.id);
|
|
4806
|
-
const name = item.type === "commandExecution" ? "Bash" : item.type === "fileChange" ? "apply_patch" : item.type === "mcpToolCall" ? `mcp__${item.server}__${item.tool}` : item.type;
|
|
4807
|
-
const input = item.type === "commandExecution" ? { command: item.command, cwd: item.cwd } : item.type === "fileChange" ? { changes: item.changes, file_path: item.changes?.[0]?.path } : item.arguments ?? item.action ?? { query: item.query };
|
|
4808
|
-
this.#append({ kind: "tool.use", toolUseId: item.id, name, input });
|
|
4809
|
-
}
|
|
4810
|
-
if (done) {
|
|
4811
|
-
this.#tools.delete(item.id);
|
|
4812
|
-
const output = item.aggregatedOutput ?? (item.changes ? item.changes.map((c) => `${c.path}
|
|
4813
|
-
${c.diff}`).join("\n") : typeof item.result === "string" ? item.result : JSON.stringify(item.error ?? item.result ?? item.action ?? "\u0413\u043E\u0442\u043E\u0432\u043E"));
|
|
4814
|
-
this.#append({
|
|
4815
|
-
kind: "tool.result",
|
|
4816
|
-
toolUseId: item.id,
|
|
4817
|
-
content: output,
|
|
4818
|
-
isError: ["failed", "declined"].includes(item.status ?? "") || item.exitCode != null && item.exitCode !== 0 || !!item.error
|
|
4819
|
-
});
|
|
4820
|
-
}
|
|
4821
|
-
}
|
|
4822
|
-
#request(id, method, params) {
|
|
4823
|
-
const requestId = String(id);
|
|
4824
|
-
const questions = method === "item/tool/requestUserInput" ? params.questions.map((q) => ({ ...q, options: q.options ?? [], multiSelect: false })) : void 0;
|
|
4825
|
-
const known = [
|
|
4826
|
-
"item/commandExecution/requestApproval",
|
|
4827
|
-
"item/fileChange/requestApproval",
|
|
4828
|
-
"item/permissions/requestApproval",
|
|
4829
|
-
"item/tool/requestUserInput"
|
|
4830
|
-
];
|
|
4831
|
-
if (!known.includes(method)) {
|
|
4832
|
-
this.#rpc?.write({ id, error: { code: -32601, message: `CCV does not support ${method}` } });
|
|
4833
|
-
this.#notice(new Error(`Codex \u0437\u0430\u043F\u0440\u043E\u0441\u0438\u043B \u043D\u0435\u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043C\u043E\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435: ${method}`));
|
|
4834
|
-
return;
|
|
4835
|
-
}
|
|
4836
|
-
this.#pending.set(requestId, { id, method, params, questions });
|
|
4837
|
-
this.#append({
|
|
4838
|
-
kind: "permission.request",
|
|
4839
|
-
requestId,
|
|
4840
|
-
toolUseId: String(params.itemId ?? requestId),
|
|
4841
|
-
toolName: questions ? "AskUserQuestion" : method.includes("commandExecution") ? "Bash" : method.includes("fileChange") ? "apply_patch" : "Codex permissions",
|
|
4842
|
-
input: { ...params, ...this.#items.get(String(params.itemId))?.changes ? { changes: this.#items.get(String(params.itemId)).changes } : {} },
|
|
4843
|
-
...typeof params.reason === "string" ? { reason: params.reason } : {},
|
|
4844
|
-
...questions ? { questions } : {}
|
|
4845
|
-
});
|
|
4846
|
-
this.#setState("waiting_permission");
|
|
4847
|
-
}
|
|
4848
|
-
respondPermission(requestId, decision, reason, answers) {
|
|
4849
|
-
const request2 = this.#pending.get(requestId);
|
|
4850
|
-
if (!request2)
|
|
4851
|
-
return;
|
|
4852
|
-
let result = { decision: decision === "allow" ? "accept" : "decline" };
|
|
4853
|
-
if (request2.questions) {
|
|
4854
|
-
result = { answers: Object.fromEntries(request2.questions.map((q) => [q.id, {
|
|
4855
|
-
answers: decision === "allow" ? [answers?.[q.question] ?? ""] : []
|
|
4856
|
-
}])) };
|
|
4857
|
-
} else if (request2.method === "item/permissions/requestApproval") {
|
|
4858
|
-
result = { permissions: decision === "allow" ? request2.params.permissions : {}, scope: "turn" };
|
|
4859
|
-
}
|
|
4860
|
-
this.#rpc?.write({ id: request2.id, result });
|
|
4861
|
-
this.#pending.delete(requestId);
|
|
4862
|
-
this.#append({ kind: "permission.resolved", requestId, decision, reason, answers });
|
|
4863
|
-
this.#setState(this.#pending.size ? "waiting_permission" : "running");
|
|
4864
|
-
}
|
|
4865
|
-
async interrupt() {
|
|
4866
|
-
this.#queue = [];
|
|
4867
|
-
if (!this.#busy)
|
|
4868
|
-
return;
|
|
4869
|
-
this.#interruptRequested = true;
|
|
4870
|
-
if (this.#turnId && this.#rpc) {
|
|
4871
|
-
await this.#rpc.request("turn/interrupt", { threadId: this.#record.conversationId, turnId: this.#turnId });
|
|
4872
|
-
}
|
|
4873
|
-
}
|
|
4874
|
-
#finishTurn(subtype, durationMs) {
|
|
4875
|
-
for (const [blockId, block] of this.#texts) {
|
|
4876
|
-
this.#append({ kind: block.thinking ? "assistant.thinking" : "assistant.text", text: block.text, blockId });
|
|
4877
|
-
}
|
|
4878
|
-
this.#texts.clear();
|
|
4879
|
-
for (const toolUseId of this.#tools) {
|
|
4880
|
-
this.#append({ kind: "tool.result", toolUseId, content: "\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043F\u0440\u0435\u0440\u0432\u0430\u043D\u043E", isError: true });
|
|
4881
|
-
}
|
|
4882
|
-
this.#tools.clear();
|
|
4883
|
-
this.#items.clear();
|
|
4884
|
-
this.#clearApprovals();
|
|
4885
|
-
this.#append({
|
|
4886
|
-
kind: "result",
|
|
4887
|
-
subtype,
|
|
4888
|
-
isError: this.#lastTurn === "failed",
|
|
4889
|
-
durationMs: durationMs ?? Math.max(0, Date.now() - this.#turnStartedAt),
|
|
4890
|
-
costUsd: null,
|
|
4891
|
-
usage: this.#turnUsage,
|
|
4892
|
-
contextTokens: this.#context?.tokens ?? null,
|
|
4893
|
-
text: null
|
|
4894
|
-
});
|
|
4895
|
-
this.#busy = false;
|
|
4896
|
-
this.#turnId = null;
|
|
4897
|
-
this.#interruptRequested = false;
|
|
4898
|
-
this.#setState("idle");
|
|
4899
|
-
void this.#drain();
|
|
4900
|
-
}
|
|
4901
|
-
async setPermissionMode(mode) {
|
|
4902
|
-
codexPolicy(mode);
|
|
4903
|
-
this.#record.permissionMode = mode;
|
|
4904
|
-
this.#settingsChanged();
|
|
4905
|
-
}
|
|
4906
|
-
async setModel(model) {
|
|
4907
|
-
this.#record.model = model;
|
|
4908
|
-
this.#record.effort = null;
|
|
4909
|
-
this.#settingsChanged();
|
|
4910
|
-
}
|
|
4911
|
-
async setEffort(effort) {
|
|
4912
|
-
const model = this.#capabilities?.models.find((m) => m.value === this.#record.model);
|
|
4913
|
-
if (model && !model.effortLevels.includes(effort))
|
|
4914
|
-
throw new Error("\u041C\u043E\u0434\u0435\u043B\u044C Codex \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u044D\u0442\u043E \u0443\u0441\u0438\u043B\u0438\u0435");
|
|
4915
|
-
this.#record.effort = effort;
|
|
4916
|
-
this.#settingsChanged();
|
|
4917
|
-
}
|
|
4918
|
-
#settingsChanged() {
|
|
4919
|
-
if (this.#capabilities) {
|
|
4920
|
-
this.#capabilities.model = this.#record.model ?? "";
|
|
4921
|
-
this.#capabilities.permissionMode = this.#record.permissionMode;
|
|
4922
|
-
this.emit("capabilities");
|
|
4923
|
-
}
|
|
4924
|
-
void this.#store.save(this.#record);
|
|
4925
|
-
this.emit("summary", this.summary());
|
|
4926
|
-
}
|
|
4927
|
-
setTitle(title) {
|
|
4928
|
-
this.#record.title = title;
|
|
4929
|
-
this.#titleIsDefault = false;
|
|
4930
|
-
this.#settingsChanged();
|
|
4931
|
-
}
|
|
4932
|
-
async refreshUsage(_force = false) {
|
|
4933
|
-
if (!this.#rpc || networkGuard.blockedReason())
|
|
4934
|
-
return;
|
|
4935
|
-
try {
|
|
4936
|
-
const reply = await this.#rpc.request("account/rateLimits/read");
|
|
4937
|
-
this.#setUsage(reply.rateLimits);
|
|
4938
|
-
} catch {
|
|
4939
|
-
}
|
|
4940
|
-
}
|
|
4941
|
-
#setUsage(limits) {
|
|
4942
|
-
this.#usage = codexUsage(limits);
|
|
4943
|
-
this.emit("usage", this.#usage);
|
|
4944
|
-
}
|
|
4945
|
-
async refreshContext(_force = false) {
|
|
4946
|
-
if (this.#context)
|
|
4947
|
-
this.emit("context", this.#context);
|
|
4948
|
-
}
|
|
4949
|
-
reconnect(_reason) {
|
|
4950
|
-
this.#disconnect();
|
|
4951
|
-
this.#setState("starting");
|
|
4952
|
-
this.#launch();
|
|
4953
|
-
}
|
|
4954
|
-
suspend(reason) {
|
|
4955
|
-
this.#disconnect();
|
|
4956
|
-
this.#notice(new Error(reason));
|
|
4957
|
-
this.#setState("error");
|
|
4958
|
-
}
|
|
4959
|
-
async close(_reason = "closed by client") {
|
|
4960
|
-
this.#disconnect();
|
|
4961
|
-
this.#setState("closed");
|
|
4962
|
-
await this.#flush();
|
|
4963
|
-
}
|
|
4964
|
-
#disconnect() {
|
|
4965
|
-
this.#generation += 1;
|
|
4966
|
-
this.#startingTurn = false;
|
|
4967
|
-
const rpc = this.#rpc;
|
|
4968
|
-
this.#rpc = null;
|
|
4969
|
-
rpc?.close();
|
|
4970
|
-
this.#queue = [];
|
|
4971
|
-
if (this.#busy) {
|
|
4972
|
-
this.#lastTurn = "interrupted";
|
|
4973
|
-
this.#finishTurn("interrupted");
|
|
4974
|
-
}
|
|
4975
|
-
this.#clearApprovals();
|
|
4976
|
-
}
|
|
4977
|
-
#clearApprovals() {
|
|
4978
|
-
for (const requestId of this.#pending.keys()) {
|
|
4979
|
-
this.#append({ kind: "permission.resolved", requestId, decision: "deny", reason: "\u0425\u043E\u0434 \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043D" });
|
|
4980
|
-
}
|
|
4981
|
-
this.#pending.clear();
|
|
4982
|
-
}
|
|
4983
|
-
#notice(error) {
|
|
4984
|
-
this.#append({ kind: "error", message: error instanceof Error ? error.message : String(error) });
|
|
4985
|
-
}
|
|
4986
|
-
#fail(error) {
|
|
4987
|
-
if (this.#state === "closed")
|
|
4988
|
-
return;
|
|
4989
|
-
this.#queue = [];
|
|
4990
|
-
if (this.#busy) {
|
|
4991
|
-
this.#lastTurn = "failed";
|
|
4992
|
-
this.#finishTurn("failed");
|
|
4993
|
-
}
|
|
4994
|
-
this.#notice(error);
|
|
4995
|
-
const rpc = this.#rpc;
|
|
4996
|
-
this.#rpc = null;
|
|
4997
|
-
rpc?.close();
|
|
4998
|
-
this.#setState("error");
|
|
4999
|
-
}
|
|
5000
|
-
#append(event) {
|
|
5001
|
-
this.#record.updatedAt = Date.now();
|
|
5002
|
-
const entry = this.journal.append(event);
|
|
5003
|
-
this.emit("event", entry);
|
|
5004
|
-
if (["assistant.delta", "thinking.delta", "state"].includes(event.kind))
|
|
5005
|
-
return;
|
|
5006
|
-
this.#unsaved.push({ ts: entry.ts, event });
|
|
5007
|
-
if (!this.#flushTimer) {
|
|
5008
|
-
this.#flushTimer = setTimeout(() => {
|
|
5009
|
-
void this.#flush();
|
|
5010
|
-
}, 500);
|
|
5011
|
-
this.#flushTimer.unref?.();
|
|
5012
|
-
}
|
|
5013
|
-
}
|
|
5014
|
-
async #flush() {
|
|
5015
|
-
if (this.#flushTimer)
|
|
5016
|
-
clearTimeout(this.#flushTimer);
|
|
5017
|
-
this.#flushTimer = null;
|
|
5018
|
-
const batch = this.#unsaved;
|
|
5019
|
-
this.#unsaved = [];
|
|
5020
|
-
await this.#store.appendEvents(this.id, batch);
|
|
5021
|
-
await this.#store.save(this.#record);
|
|
5022
|
-
}
|
|
5023
|
-
#setState(state) {
|
|
5024
|
-
this.#state = state;
|
|
5025
|
-
this.#append({ kind: "state", state });
|
|
5026
|
-
if (["idle", "error", "closed"].includes(state))
|
|
5027
|
-
void this.#flush();
|
|
5028
|
-
this.emit("summary", this.summary());
|
|
5029
|
-
}
|
|
5030
|
-
async editPrompt(_index, _text, _images) {
|
|
5031
|
-
throw new Error("\u0412 \u0441\u0435\u0441\u0441\u0438\u0438 Codex \u043F\u0440\u0430\u0432\u043A\u0430 \u043F\u0440\u043E\u0448\u043B\u044B\u0445 \u0440\u0435\u043F\u043B\u0438\u043A \u043F\u043E\u043A\u0430 \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F");
|
|
5032
|
-
}
|
|
5033
|
-
async setUltracode(_enabled) {
|
|
5034
|
-
}
|
|
5035
|
-
async setThinking(_enabled) {
|
|
5036
|
-
}
|
|
5037
|
-
async setSwitchModelsOnFlag(_enabled) {
|
|
5038
|
-
}
|
|
5039
|
-
async reloadPlugins() {
|
|
5040
|
-
}
|
|
5041
|
-
async mcpServerStatus() {
|
|
5042
|
-
return [];
|
|
5043
|
-
}
|
|
5044
|
-
async addMcpServer(_name, _config) {
|
|
5045
|
-
throw this.#mcpHint();
|
|
5046
|
-
}
|
|
5047
|
-
async removeMcpServer(_name) {
|
|
5048
|
-
throw this.#mcpHint();
|
|
5049
|
-
}
|
|
5050
|
-
async reconnectMcpServer(_name) {
|
|
5051
|
-
throw this.#mcpHint();
|
|
5052
|
-
}
|
|
5053
|
-
async toggleMcpServer(_name, _enabled) {
|
|
5054
|
-
throw this.#mcpHint();
|
|
5055
|
-
}
|
|
5056
|
-
async authenticateMcpServer(_name) {
|
|
5057
|
-
throw this.#mcpHint();
|
|
5058
|
-
}
|
|
5059
|
-
async submitMcpOAuthCallback(_name, _url) {
|
|
5060
|
-
throw this.#mcpHint();
|
|
5061
|
-
}
|
|
5062
|
-
#mcpHint() {
|
|
5063
|
-
return new Error("MCP Codex \u043D\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044F \u0447\u0435\u0440\u0435\u0437 codex mcp \u0438\u043B\u0438 ~/.codex/config.toml");
|
|
5064
|
-
}
|
|
5065
|
-
};
|
|
5066
|
-
|
|
5067
4220
|
// ../host/dist/antigravity-store.js
|
|
5068
4221
|
import { appendFile, mkdir as mkdir3, readFile as readFile4, rm as rm2, writeFile as writeFile3 } from "node:fs/promises";
|
|
5069
|
-
import
|
|
4222
|
+
import path8 from "node:path";
|
|
5070
4223
|
var AntigravityStore = class {
|
|
5071
4224
|
#dir;
|
|
5072
4225
|
#file;
|
|
5073
4226
|
#records = /* @__PURE__ */ new Map();
|
|
5074
4227
|
#loaded = null;
|
|
5075
4228
|
#writing = Promise.resolve();
|
|
5076
|
-
constructor(dataDir
|
|
5077
|
-
this.#dir =
|
|
5078
|
-
this.#file =
|
|
4229
|
+
constructor(dataDir) {
|
|
4230
|
+
this.#dir = path8.join(dataDir, "antigravity");
|
|
4231
|
+
this.#file = path8.join(this.#dir, "sessions.json");
|
|
5079
4232
|
}
|
|
5080
4233
|
#load() {
|
|
5081
4234
|
this.#loaded ??= (async () => {
|
|
@@ -5172,7 +4325,7 @@ var AntigravityStore = class {
|
|
|
5172
4325
|
return entries;
|
|
5173
4326
|
}
|
|
5174
4327
|
#eventsFile(id) {
|
|
5175
|
-
return
|
|
4328
|
+
return path8.join(this.#dir, `${id.replace(/[^\w-]/g, "_")}.jsonl`);
|
|
5176
4329
|
}
|
|
5177
4330
|
#persist() {
|
|
5178
4331
|
const snapshot = JSON.stringify([...this.#records.values()], null, 2);
|
|
@@ -5192,10 +4345,10 @@ var AntigravityStore = class {
|
|
|
5192
4345
|
};
|
|
5193
4346
|
|
|
5194
4347
|
// ../host/dist/git.js
|
|
5195
|
-
import { execFile as
|
|
4348
|
+
import { execFile as execFile4 } from "node:child_process";
|
|
5196
4349
|
import { mkdtemp, readFile as readFile5, rm as rm3, writeFile as writeFile4 } from "node:fs/promises";
|
|
5197
4350
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
5198
|
-
import
|
|
4351
|
+
import path9 from "node:path";
|
|
5199
4352
|
var TIMEOUT_MS = 2e4;
|
|
5200
4353
|
var NET_TIMEOUT_MS = 5 * 6e4;
|
|
5201
4354
|
var MAX_BUFFER = 32 * 1024 * 1024;
|
|
@@ -5511,7 +4664,7 @@ var GitRepo = class {
|
|
|
5511
4664
|
* важнее всего (см. `checkIgnored`).
|
|
5512
4665
|
*/
|
|
5513
4666
|
async #withoutRepo(args) {
|
|
5514
|
-
const dir = await mkdtemp(
|
|
4667
|
+
const dir = await mkdtemp(path9.join(tmpdir2(), "ccv-git-"));
|
|
5515
4668
|
try {
|
|
5516
4669
|
await this.#run(["init", "--bare", "--quiet", dir]);
|
|
5517
4670
|
return await this.#soft([`--git-dir=${dir}`, `--work-tree=${this.cwd}`, ...args]);
|
|
@@ -5557,7 +4710,7 @@ var GitRepo = class {
|
|
|
5557
4710
|
* исключил. Повторы отсеиваются, чтобы файл не рос от каждой публикации.
|
|
5558
4711
|
*/
|
|
5559
4712
|
async #appendGitignore(paths) {
|
|
5560
|
-
const file =
|
|
4713
|
+
const file = path9.join(this.cwd, ".gitignore");
|
|
5561
4714
|
const existing = await readFile5(file, "utf8").catch(() => "");
|
|
5562
4715
|
const known = new Set(existing.split(/\r?\n/).map((line) => line.trim()));
|
|
5563
4716
|
const lines = paths.map(ignorePattern).filter((line) => !known.has(line));
|
|
@@ -5582,7 +4735,7 @@ var GitRepo = class {
|
|
|
5582
4735
|
#run(args, options2 = {}) {
|
|
5583
4736
|
const token = options2.token ?? "";
|
|
5584
4737
|
return new Promise((resolve, reject) => {
|
|
5585
|
-
const child =
|
|
4738
|
+
const child = execFile4(
|
|
5586
4739
|
"git",
|
|
5587
4740
|
// core.quotepath=false — иначе кириллические пути приезжают в виде
|
|
5588
4741
|
// «\320\277\321\200…» и в панели читаются как мусор.
|
|
@@ -5763,9 +4916,9 @@ function parsePatch(raw) {
|
|
|
5763
4916
|
body = "";
|
|
5764
4917
|
}
|
|
5765
4918
|
total += body.length;
|
|
5766
|
-
const
|
|
4919
|
+
const path25 = status === "deleted" ? oldPath : newPath || oldPath;
|
|
5767
4920
|
files.push({
|
|
5768
|
-
path:
|
|
4921
|
+
path: path25,
|
|
5769
4922
|
oldPath: status === "renamed" ? oldPath : "",
|
|
5770
4923
|
status,
|
|
5771
4924
|
added: count(body, "+"),
|
|
@@ -5777,10 +4930,10 @@ function parsePatch(raw) {
|
|
|
5777
4930
|
return { files, truncated };
|
|
5778
4931
|
}
|
|
5779
4932
|
function stripPrefix(value) {
|
|
5780
|
-
const
|
|
5781
|
-
if (
|
|
4933
|
+
const path25 = unquote(value.trim());
|
|
4934
|
+
if (path25 === "/dev/null")
|
|
5782
4935
|
return "";
|
|
5783
|
-
return
|
|
4936
|
+
return path25.replace(/^[ab]\//, "");
|
|
5784
4937
|
}
|
|
5785
4938
|
function count(body, mark) {
|
|
5786
4939
|
let n = 0;
|
|
@@ -5792,9 +4945,9 @@ function count(body, mark) {
|
|
|
5792
4945
|
}
|
|
5793
4946
|
|
|
5794
4947
|
// ../host/dist/github.js
|
|
5795
|
-
import { execFile as
|
|
4948
|
+
import { execFile as execFile5 } from "node:child_process";
|
|
5796
4949
|
import { mkdir as mkdir4, readFile as readFile6, writeFile as writeFile5 } from "node:fs/promises";
|
|
5797
|
-
import
|
|
4950
|
+
import path10 from "node:path";
|
|
5798
4951
|
var API = "https://api.github.com";
|
|
5799
4952
|
var API_VERSION = "2022-11-28";
|
|
5800
4953
|
var API_TIMEOUT_MS = 2e4;
|
|
@@ -5815,7 +4968,7 @@ var GitHubAccount = class {
|
|
|
5815
4968
|
*/
|
|
5816
4969
|
#ghInstalled = null;
|
|
5817
4970
|
constructor(dataDir) {
|
|
5818
|
-
this.#storePath =
|
|
4971
|
+
this.#storePath = path10.join(dataDir, "github.json");
|
|
5819
4972
|
}
|
|
5820
4973
|
async load() {
|
|
5821
4974
|
try {
|
|
@@ -5829,7 +4982,7 @@ var GitHubAccount = class {
|
|
|
5829
4982
|
/** Сохранить токен или стереть его пустой строкой. */
|
|
5830
4983
|
async setToken(token) {
|
|
5831
4984
|
this.#token = token.trim();
|
|
5832
|
-
await mkdir4(
|
|
4985
|
+
await mkdir4(path10.dirname(this.#storePath), { recursive: true });
|
|
5833
4986
|
await writeFile5(this.#storePath, JSON.stringify({ token: this.#token }, null, 2), {
|
|
5834
4987
|
encoding: "utf8",
|
|
5835
4988
|
mode: 384
|
|
@@ -5981,7 +5134,7 @@ var GitHubAccount = class {
|
|
|
5981
5134
|
};
|
|
5982
5135
|
function gh(args) {
|
|
5983
5136
|
return new Promise((resolve, reject) => {
|
|
5984
|
-
|
|
5137
|
+
execFile5("gh", args, { timeout: GH_TIMEOUT_MS, windowsHide: true, encoding: "utf8" }, (error, stdout, stderr) => {
|
|
5985
5138
|
if (error)
|
|
5986
5139
|
return reject(new Error(stderr.trim() || error.message));
|
|
5987
5140
|
resolve(stdout);
|
|
@@ -6022,10 +5175,10 @@ function describe4(error) {
|
|
|
6022
5175
|
}
|
|
6023
5176
|
|
|
6024
5177
|
// ../host/dist/finder.js
|
|
6025
|
-
import { existsSync as
|
|
5178
|
+
import { existsSync as existsSync2, statSync } from "node:fs";
|
|
6026
5179
|
import { readdir as readdir2 } from "node:fs/promises";
|
|
6027
5180
|
import os2 from "node:os";
|
|
6028
|
-
import
|
|
5181
|
+
import path11 from "node:path";
|
|
6029
5182
|
import { listSessions } from "@anthropic-ai/claude-agent-sdk";
|
|
6030
5183
|
var CACHE_TTL = 6e4;
|
|
6031
5184
|
var FIND_LIMIT = 50;
|
|
@@ -6064,7 +5217,7 @@ var ProjectFinder = class {
|
|
|
6064
5217
|
if (needles.length === 0)
|
|
6065
5218
|
return { candidates: [], truncated: false };
|
|
6066
5219
|
const open = new Map(this.registry.list().map((workspace) => [workspace.path.toLowerCase(), workspace]));
|
|
6067
|
-
const byName = this.#dirs.filter((dir) => matches(
|
|
5220
|
+
const byName = this.#dirs.filter((dir) => matches(path11.basename(dir.path), needles));
|
|
6068
5221
|
const matched = byName.length > 0 ? byName : this.#dirs.filter((dir) => matches(dir.path, needles));
|
|
6069
5222
|
const sorted = [...matched].sort((a, b) => {
|
|
6070
5223
|
const aOpen = open.has(a.path.toLowerCase());
|
|
@@ -6075,7 +5228,7 @@ var ProjectFinder = class {
|
|
|
6075
5228
|
return a.sessions > 0 ? -1 : 1;
|
|
6076
5229
|
if (a.lastUsedAt !== b.lastUsedAt)
|
|
6077
5230
|
return b.lastUsedAt - a.lastUsedAt;
|
|
6078
|
-
return
|
|
5231
|
+
return path11.basename(a.path).localeCompare(path11.basename(b.path), void 0, {
|
|
6079
5232
|
numeric: true,
|
|
6080
5233
|
sensitivity: "base"
|
|
6081
5234
|
});
|
|
@@ -6083,7 +5236,7 @@ var ProjectFinder = class {
|
|
|
6083
5236
|
return {
|
|
6084
5237
|
candidates: sorted.slice(0, FIND_LIMIT).map((dir) => ({
|
|
6085
5238
|
path: dir.path,
|
|
6086
|
-
name:
|
|
5239
|
+
name: path11.basename(dir.path) || dir.path,
|
|
6087
5240
|
sessions: dir.sessions,
|
|
6088
5241
|
lastUsedAt: dir.lastUsedAt || null,
|
|
6089
5242
|
open: open.has(dir.path.toLowerCase()),
|
|
@@ -6107,7 +5260,7 @@ var ProjectFinder = class {
|
|
|
6107
5260
|
const candidates = [];
|
|
6108
5261
|
for (const entry of named) {
|
|
6109
5262
|
const absolute = entry.path.trim();
|
|
6110
|
-
if (!absolute || !
|
|
5263
|
+
if (!absolute || !path11.isAbsolute(absolute))
|
|
6111
5264
|
continue;
|
|
6112
5265
|
const key = absolute.toLowerCase();
|
|
6113
5266
|
if (seen.has(key))
|
|
@@ -6118,7 +5271,7 @@ var ProjectFinder = class {
|
|
|
6118
5271
|
const record = known.get(key);
|
|
6119
5272
|
candidates.push({
|
|
6120
5273
|
path: record?.path ?? absolute,
|
|
6121
|
-
name:
|
|
5274
|
+
name: path11.basename(absolute) || absolute,
|
|
6122
5275
|
sessions: record?.sessions ?? 0,
|
|
6123
5276
|
lastUsedAt: record?.lastUsedAt || null,
|
|
6124
5277
|
open: open.has(key),
|
|
@@ -6175,7 +5328,7 @@ var ProjectFinder = class {
|
|
|
6175
5328
|
if (!dirent.isDirectory() || SKIP_NAMES.has(dirent.name) || dirent.name.startsWith(".")) {
|
|
6176
5329
|
continue;
|
|
6177
5330
|
}
|
|
6178
|
-
const full =
|
|
5331
|
+
const full = path11.join(parent, dirent.name);
|
|
6179
5332
|
const key = full.toLowerCase();
|
|
6180
5333
|
if (dirs.has(key))
|
|
6181
5334
|
continue;
|
|
@@ -6196,7 +5349,7 @@ var ProjectFinder = class {
|
|
|
6196
5349
|
#parents(dirs) {
|
|
6197
5350
|
const counted = /* @__PURE__ */ new Map();
|
|
6198
5351
|
for (const dir of dirs) {
|
|
6199
|
-
const parent =
|
|
5352
|
+
const parent = path11.dirname(dir.path);
|
|
6200
5353
|
if (parent === dir.path || !usable(parent))
|
|
6201
5354
|
continue;
|
|
6202
5355
|
const key = parent.toLowerCase();
|
|
@@ -6210,7 +5363,7 @@ var ProjectFinder = class {
|
|
|
6210
5363
|
}
|
|
6211
5364
|
};
|
|
6212
5365
|
function usable(dir) {
|
|
6213
|
-
return !contains(os2.tmpdir(), dir) &&
|
|
5366
|
+
return !contains(os2.tmpdir(), dir) && existsSync2(dir);
|
|
6214
5367
|
}
|
|
6215
5368
|
function tokens(query2) {
|
|
6216
5369
|
return query2.toLowerCase().split(/[^a-z0-9а-яё]+/i).filter(Boolean);
|
|
@@ -6221,7 +5374,7 @@ function matches(value, needles) {
|
|
|
6221
5374
|
}
|
|
6222
5375
|
function isDirectory(dir) {
|
|
6223
5376
|
try {
|
|
6224
|
-
return
|
|
5377
|
+
return statSync(dir).isDirectory();
|
|
6225
5378
|
} catch {
|
|
6226
5379
|
return false;
|
|
6227
5380
|
}
|
|
@@ -6307,15 +5460,15 @@ function fromText(text) {
|
|
|
6307
5460
|
}
|
|
6308
5461
|
|
|
6309
5462
|
// ../host/dist/workspaces.js
|
|
6310
|
-
import { existsSync as
|
|
5463
|
+
import { existsSync as existsSync3, statSync as statSync2 } from "node:fs";
|
|
6311
5464
|
import { mkdir as mkdir5, readFile as readFile7, writeFile as writeFile6 } from "node:fs/promises";
|
|
6312
|
-
import
|
|
5465
|
+
import path12 from "node:path";
|
|
6313
5466
|
import { listSessions as listSessions2 } from "@anthropic-ai/claude-agent-sdk";
|
|
6314
5467
|
var WorkspaceRegistry = class {
|
|
6315
5468
|
#entries = [];
|
|
6316
5469
|
#storePath;
|
|
6317
5470
|
constructor(dataDir) {
|
|
6318
|
-
this.#storePath =
|
|
5471
|
+
this.#storePath = path12.join(dataDir, "workspaces.json");
|
|
6319
5472
|
}
|
|
6320
5473
|
async load() {
|
|
6321
5474
|
try {
|
|
@@ -6331,13 +5484,13 @@ var WorkspaceRegistry = class {
|
|
|
6331
5484
|
if (isEntry(item))
|
|
6332
5485
|
return item;
|
|
6333
5486
|
return null;
|
|
6334
|
-
}).filter((e) => e !== null &&
|
|
5487
|
+
}).filter((e) => e !== null && existsSync3(e.path));
|
|
6335
5488
|
} catch {
|
|
6336
5489
|
this.#entries = [];
|
|
6337
5490
|
}
|
|
6338
5491
|
}
|
|
6339
5492
|
async #persist() {
|
|
6340
|
-
await mkdir5(
|
|
5493
|
+
await mkdir5(path12.dirname(this.#storePath), { recursive: true });
|
|
6341
5494
|
await writeFile6(this.#storePath, JSON.stringify(this.#entries, null, 2), "utf8");
|
|
6342
5495
|
}
|
|
6343
5496
|
/** Активные проекты. */
|
|
@@ -6357,8 +5510,8 @@ var WorkspaceRegistry = class {
|
|
|
6357
5510
|
return entry ? toInfo(entry) : void 0;
|
|
6358
5511
|
}
|
|
6359
5512
|
async open(rawPath) {
|
|
6360
|
-
const absolute =
|
|
6361
|
-
if (!
|
|
5513
|
+
const absolute = path12.resolve(rawPath);
|
|
5514
|
+
if (!existsSync3(absolute)) {
|
|
6362
5515
|
throw new Error(`\u041A\u0430\u0442\u0430\u043B\u043E\u0433 \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D: ${absolute}`);
|
|
6363
5516
|
}
|
|
6364
5517
|
const existing = this.#entries.find((e) => e.path === absolute);
|
|
@@ -6424,24 +5577,24 @@ var WorkspaceRegistry = class {
|
|
|
6424
5577
|
async create(parentRaw, nameRaw, init) {
|
|
6425
5578
|
const name = nameRaw.trim();
|
|
6426
5579
|
requireName(name);
|
|
6427
|
-
const parent =
|
|
6428
|
-
if (!
|
|
5580
|
+
const parent = path12.resolve(parentRaw.trim());
|
|
5581
|
+
if (!existsSync3(parent)) {
|
|
6429
5582
|
throw new Error(`\u041A\u0430\u0442\u0430\u043B\u043E\u0433 \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D: ${parent}`);
|
|
6430
5583
|
}
|
|
6431
|
-
if (!
|
|
5584
|
+
if (!statSync2(parent).isDirectory()) {
|
|
6432
5585
|
throw new Error(`\u042D\u0442\u043E \u043D\u0435 \u043A\u0430\u0442\u0430\u043B\u043E\u0433: ${parent}`);
|
|
6433
5586
|
}
|
|
6434
|
-
const target =
|
|
6435
|
-
if (
|
|
5587
|
+
const target = path12.join(parent, name);
|
|
5588
|
+
if (existsSync3(target)) {
|
|
6436
5589
|
throw new Error(`\u0423\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442: ${target} \u2014 \u043E\u0442\u043A\u0440\u043E\u0439\u0442\u0435 \u0435\u0433\u043E \u043A\u0430\u043A \u043F\u0440\u043E\u0435\u043A\u0442`);
|
|
6437
5590
|
}
|
|
6438
5591
|
await mkdir5(target);
|
|
6439
5592
|
const warnings = [];
|
|
6440
5593
|
if (init.claudeMd) {
|
|
6441
|
-
await step(warnings, "CLAUDE.md", () => writeFile6(
|
|
5594
|
+
await step(warnings, "CLAUDE.md", () => writeFile6(path12.join(target, "CLAUDE.md"), claudeMdStub(name), "utf8"));
|
|
6442
5595
|
}
|
|
6443
5596
|
if (init.readme) {
|
|
6444
|
-
await step(warnings, "README.md", () => writeFile6(
|
|
5597
|
+
await step(warnings, "README.md", () => writeFile6(path12.join(target, "README.md"), readmeStub(name), "utf8"));
|
|
6445
5598
|
}
|
|
6446
5599
|
if (init.git) {
|
|
6447
5600
|
await step(warnings, "git init", () => new GitRepo(target).init());
|
|
@@ -6513,8 +5666,8 @@ function toInfo(entry) {
|
|
|
6513
5666
|
return {
|
|
6514
5667
|
id: workspaceIdFromPath(absolute),
|
|
6515
5668
|
path: absolute,
|
|
6516
|
-
name:
|
|
6517
|
-
hasClaudeMd:
|
|
5669
|
+
name: path12.basename(absolute) || absolute,
|
|
5670
|
+
hasClaudeMd: existsSync3(path12.join(absolute, "CLAUDE.md")),
|
|
6518
5671
|
...archivedAt ? { archivedAt } : {}
|
|
6519
5672
|
};
|
|
6520
5673
|
}
|
|
@@ -6524,13 +5677,13 @@ function isEntry(value) {
|
|
|
6524
5677
|
|
|
6525
5678
|
// ../host/dist/archive.js
|
|
6526
5679
|
import { mkdir as mkdir6, readFile as readFile8, writeFile as writeFile7 } from "node:fs/promises";
|
|
6527
|
-
import
|
|
5680
|
+
import path13 from "node:path";
|
|
6528
5681
|
var SessionArchive = class {
|
|
6529
5682
|
#archived = /* @__PURE__ */ new Map();
|
|
6530
5683
|
#restored = /* @__PURE__ */ new Map();
|
|
6531
5684
|
#storePath;
|
|
6532
5685
|
constructor(dataDir) {
|
|
6533
|
-
this.#storePath =
|
|
5686
|
+
this.#storePath = path13.join(dataDir, "session-archive.json");
|
|
6534
5687
|
}
|
|
6535
5688
|
async load() {
|
|
6536
5689
|
try {
|
|
@@ -6642,7 +5795,7 @@ var SessionArchive = class {
|
|
|
6642
5795
|
archived: Object.fromEntries(this.#archived),
|
|
6643
5796
|
restored: Object.fromEntries(this.#restored)
|
|
6644
5797
|
};
|
|
6645
|
-
await mkdir6(
|
|
5798
|
+
await mkdir6(path13.dirname(this.#storePath), { recursive: true });
|
|
6646
5799
|
await writeFile7(this.#storePath, JSON.stringify(file, null, 2), "utf8");
|
|
6647
5800
|
}
|
|
6648
5801
|
};
|
|
@@ -6652,7 +5805,7 @@ function isRecord(value) {
|
|
|
6652
5805
|
|
|
6653
5806
|
// ../host/dist/pins.js
|
|
6654
5807
|
import { mkdir as mkdir7, readFile as readFile9, writeFile as writeFile8 } from "node:fs/promises";
|
|
6655
|
-
import
|
|
5808
|
+
import path14 from "node:path";
|
|
6656
5809
|
var SessionPins = class {
|
|
6657
5810
|
#pinned = /* @__PURE__ */ new Map();
|
|
6658
5811
|
/**
|
|
@@ -6667,7 +5820,7 @@ var SessionPins = class {
|
|
|
6667
5820
|
#moved = /* @__PURE__ */ new Map();
|
|
6668
5821
|
#storePath;
|
|
6669
5822
|
constructor(dataDir) {
|
|
6670
|
-
this.#storePath =
|
|
5823
|
+
this.#storePath = path14.join(dataDir, "session-pins.json");
|
|
6671
5824
|
}
|
|
6672
5825
|
async load() {
|
|
6673
5826
|
try {
|
|
@@ -6824,7 +5977,7 @@ var SessionPins = class {
|
|
|
6824
5977
|
pinned: Object.fromEntries(this.#pinned),
|
|
6825
5978
|
...this.#moved.size > 0 ? { moved: Object.fromEntries(this.#moved) } : {}
|
|
6826
5979
|
};
|
|
6827
|
-
await mkdir7(
|
|
5980
|
+
await mkdir7(path14.dirname(this.#storePath), { recursive: true });
|
|
6828
5981
|
await writeFile8(this.#storePath, JSON.stringify(file, null, 2), "utf8");
|
|
6829
5982
|
}
|
|
6830
5983
|
};
|
|
@@ -6834,12 +5987,12 @@ function isRecord2(value) {
|
|
|
6834
5987
|
|
|
6835
5988
|
// ../host/dist/order.js
|
|
6836
5989
|
import { mkdir as mkdir8, readFile as readFile10, writeFile as writeFile9 } from "node:fs/promises";
|
|
6837
|
-
import
|
|
5990
|
+
import path15 from "node:path";
|
|
6838
5991
|
var ListOrderStore = class {
|
|
6839
5992
|
#order = emptyOrder();
|
|
6840
5993
|
#storePath;
|
|
6841
5994
|
constructor(dataDir) {
|
|
6842
|
-
this.#storePath =
|
|
5995
|
+
this.#storePath = path15.join(dataDir, "list-order.json");
|
|
6843
5996
|
}
|
|
6844
5997
|
async load() {
|
|
6845
5998
|
try {
|
|
@@ -6915,7 +6068,7 @@ var ListOrderStore = class {
|
|
|
6915
6068
|
return changed;
|
|
6916
6069
|
}
|
|
6917
6070
|
async #persist() {
|
|
6918
|
-
await mkdir8(
|
|
6071
|
+
await mkdir8(path15.dirname(this.#storePath), { recursive: true });
|
|
6919
6072
|
await writeFile9(this.#storePath, JSON.stringify(this.#order, null, 2), "utf8");
|
|
6920
6073
|
}
|
|
6921
6074
|
};
|
|
@@ -6946,8 +6099,8 @@ function sanitize(value) {
|
|
|
6946
6099
|
|
|
6947
6100
|
// ../host/dist/folders.js
|
|
6948
6101
|
import { mkdir as mkdir9, readFile as readFile11, writeFile as writeFile10 } from "node:fs/promises";
|
|
6949
|
-
import
|
|
6950
|
-
import { randomUUID as
|
|
6102
|
+
import path16 from "node:path";
|
|
6103
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
6951
6104
|
var COLOR_PATTERN = /^#[0-9a-f]{6}$/i;
|
|
6952
6105
|
var Folders = class {
|
|
6953
6106
|
#workspaceFolders = /* @__PURE__ */ new Map();
|
|
@@ -6958,7 +6111,7 @@ var Folders = class {
|
|
|
6958
6111
|
#pinnedAssignments = /* @__PURE__ */ new Map();
|
|
6959
6112
|
#storePath;
|
|
6960
6113
|
constructor(dataDir) {
|
|
6961
|
-
this.#storePath =
|
|
6114
|
+
this.#storePath = path16.join(dataDir, "folders.json");
|
|
6962
6115
|
}
|
|
6963
6116
|
async load() {
|
|
6964
6117
|
try {
|
|
@@ -7047,19 +6200,19 @@ var Folders = class {
|
|
|
7047
6200
|
};
|
|
7048
6201
|
}
|
|
7049
6202
|
async createWorkspaceFolder(name) {
|
|
7050
|
-
const id =
|
|
6203
|
+
const id = randomUUID3();
|
|
7051
6204
|
this.#workspaceFolders.set(id, { name });
|
|
7052
6205
|
await this.#persist();
|
|
7053
6206
|
return id;
|
|
7054
6207
|
}
|
|
7055
6208
|
async createSessionFolder(workspaceId, name) {
|
|
7056
|
-
const id =
|
|
6209
|
+
const id = randomUUID3();
|
|
7057
6210
|
this.#sessionFolders.set(id, { name, workspaceId });
|
|
7058
6211
|
await this.#persist();
|
|
7059
6212
|
return id;
|
|
7060
6213
|
}
|
|
7061
6214
|
async createPinnedFolder(name) {
|
|
7062
|
-
const id =
|
|
6215
|
+
const id = randomUUID3();
|
|
7063
6216
|
this.#pinnedFolders.set(id, { name });
|
|
7064
6217
|
await this.#persist();
|
|
7065
6218
|
return id;
|
|
@@ -7239,7 +6392,7 @@ var Folders = class {
|
|
|
7239
6392
|
sessionAssignments: Object.fromEntries(this.#sessionAssignments),
|
|
7240
6393
|
pinnedAssignments: Object.fromEntries(this.#pinnedAssignments)
|
|
7241
6394
|
};
|
|
7242
|
-
await mkdir9(
|
|
6395
|
+
await mkdir9(path16.dirname(this.#storePath), { recursive: true });
|
|
7243
6396
|
await writeFile10(this.#storePath, JSON.stringify(file, null, 2), "utf8");
|
|
7244
6397
|
}
|
|
7245
6398
|
};
|
|
@@ -7262,8 +6415,8 @@ function isPinnedFolder(value) {
|
|
|
7262
6415
|
|
|
7263
6416
|
// ../host/dist/app-settings.js
|
|
7264
6417
|
import { mkdir as mkdir10, readFile as readFile12, writeFile as writeFile11 } from "node:fs/promises";
|
|
7265
|
-
import { homedir as
|
|
7266
|
-
import
|
|
6418
|
+
import { homedir as homedir4 } from "node:os";
|
|
6419
|
+
import path17 from "node:path";
|
|
7267
6420
|
var DEFAULT_AUTO_ARCHIVE_AFTER_MS = 2 * 24 * 60 * 60 * 1e3;
|
|
7268
6421
|
var MIN_AUTO_ARCHIVE_AFTER_MS = 60 * 60 * 1e3;
|
|
7269
6422
|
var DEFAULT_AUTO_STOP_AFTER_MS = 10 * 60 * 1e3;
|
|
@@ -7271,7 +6424,7 @@ var MIN_AUTO_STOP_AFTER_MS = 60 * 1e3;
|
|
|
7271
6424
|
var MIN_AUTO_SAVE_AFTER_PAUSE_MS = 500;
|
|
7272
6425
|
var DEFAULT_BLOCKED_COUNTRIES = ["RU", "BY", "CN", "IR", "KP", "SY", "CU"];
|
|
7273
6426
|
var FOLDER_ACCESS = ["all", "projects", "project"];
|
|
7274
|
-
var PROVIDERS = ["claude", "antigravity"
|
|
6427
|
+
var PROVIDERS = ["claude", "antigravity"];
|
|
7275
6428
|
var PERMISSION_MODES = [
|
|
7276
6429
|
"default",
|
|
7277
6430
|
"acceptEdits",
|
|
@@ -7306,7 +6459,7 @@ var DEFAULT_APP_SETTINGS = {
|
|
|
7306
6459
|
limitStopFiveHourPct: 95,
|
|
7307
6460
|
limitStopSevenDayPct: 99,
|
|
7308
6461
|
// Оба: до появления настройки приложение предлагало обоих агентов.
|
|
7309
|
-
enabledProviders: ["claude", "antigravity"
|
|
6462
|
+
enabledProviders: ["claude", "antigravity"],
|
|
7310
6463
|
// Включено: запрос без VPN может стоить аккаунта, а тому, у кого маршрут и
|
|
7311
6464
|
// так из разрешённой страны, защита ничем не мешает.
|
|
7312
6465
|
networkGuardEnabled: true,
|
|
@@ -7316,7 +6469,7 @@ var AppSettingsStore = class {
|
|
|
7316
6469
|
#settings = { ...DEFAULT_APP_SETTINGS };
|
|
7317
6470
|
#storePath;
|
|
7318
6471
|
constructor(dataDir) {
|
|
7319
|
-
this.#storePath =
|
|
6472
|
+
this.#storePath = path17.join(dataDir, "app-settings.json");
|
|
7320
6473
|
}
|
|
7321
6474
|
async load() {
|
|
7322
6475
|
try {
|
|
@@ -7340,7 +6493,7 @@ var AppSettingsStore = class {
|
|
|
7340
6493
|
async update(patch) {
|
|
7341
6494
|
const next = sanitize2(patch, this.#settings);
|
|
7342
6495
|
this.#settings = next;
|
|
7343
|
-
await mkdir10(
|
|
6496
|
+
await mkdir10(path17.dirname(this.#storePath), { recursive: true });
|
|
7344
6497
|
await writeFile11(this.#storePath, JSON.stringify(next, null, 2), "utf8");
|
|
7345
6498
|
return this.current;
|
|
7346
6499
|
}
|
|
@@ -7407,7 +6560,7 @@ function sanitize2(value, fallback) {
|
|
|
7407
6560
|
return result;
|
|
7408
6561
|
}
|
|
7409
6562
|
function claudeHome() {
|
|
7410
|
-
return
|
|
6563
|
+
return path17.join(homedir4(), ".claude");
|
|
7411
6564
|
}
|
|
7412
6565
|
function writableRoots(mode, cwd, workspacePaths) {
|
|
7413
6566
|
if (mode === "all")
|
|
@@ -7417,7 +6570,7 @@ function writableRoots(mode, cwd, workspacePaths) {
|
|
|
7417
6570
|
return [...roots];
|
|
7418
6571
|
for (const workspace of [cwd, ...workspacePaths]) {
|
|
7419
6572
|
roots.add(workspace);
|
|
7420
|
-
const parent =
|
|
6573
|
+
const parent = path17.dirname(workspace);
|
|
7421
6574
|
if (parent !== workspace)
|
|
7422
6575
|
roots.add(parent);
|
|
7423
6576
|
}
|
|
@@ -7426,11 +6579,11 @@ function writableRoots(mode, cwd, workspacePaths) {
|
|
|
7426
6579
|
|
|
7427
6580
|
// ../host/dist/handoff-store.js
|
|
7428
6581
|
import { mkdir as mkdir11, readFile as readFile13, readdir as readdir3, rm as rm4, writeFile as writeFile12 } from "node:fs/promises";
|
|
7429
|
-
import
|
|
6582
|
+
import path18 from "node:path";
|
|
7430
6583
|
var HandoffStore = class {
|
|
7431
6584
|
#dir;
|
|
7432
6585
|
constructor(dataDir) {
|
|
7433
|
-
this.#dir =
|
|
6586
|
+
this.#dir = path18.join(dataDir, "handoffs");
|
|
7434
6587
|
}
|
|
7435
6588
|
async get(sessionId) {
|
|
7436
6589
|
const file = this.#file(sessionId);
|
|
@@ -7467,7 +6620,7 @@ var HandoffStore = class {
|
|
|
7467
6620
|
#file(sessionId) {
|
|
7468
6621
|
if (!/^[\w-]{1,128}$/.test(sessionId))
|
|
7469
6622
|
return null;
|
|
7470
|
-
return
|
|
6623
|
+
return path18.join(this.#dir, `${sessionId}.json`);
|
|
7471
6624
|
}
|
|
7472
6625
|
};
|
|
7473
6626
|
var SAME_WINDOW_MS = 5 * 6e4;
|
|
@@ -7475,7 +6628,7 @@ var LimitStopState = class {
|
|
|
7475
6628
|
#fired = {};
|
|
7476
6629
|
#storePath;
|
|
7477
6630
|
constructor(dataDir) {
|
|
7478
|
-
this.#storePath =
|
|
6631
|
+
this.#storePath = path18.join(dataDir, "limit-stop.json");
|
|
7479
6632
|
}
|
|
7480
6633
|
async load() {
|
|
7481
6634
|
try {
|
|
@@ -7511,7 +6664,7 @@ var LimitStopState = class {
|
|
|
7511
6664
|
/** Запомнить срабатывание до `until` (момент сброса окна). */
|
|
7512
6665
|
async mark(limit, until) {
|
|
7513
6666
|
this.#fired[limit] = until;
|
|
7514
|
-
await mkdir11(
|
|
6667
|
+
await mkdir11(path18.dirname(this.#storePath), { recursive: true });
|
|
7515
6668
|
await writeFile12(this.#storePath, JSON.stringify(this.#fired, null, 2), "utf8");
|
|
7516
6669
|
}
|
|
7517
6670
|
};
|
|
@@ -7617,8 +6770,8 @@ function capitalize(text) {
|
|
|
7617
6770
|
|
|
7618
6771
|
// ../host/dist/plugins.js
|
|
7619
6772
|
import { readFile as readFile14 } from "node:fs/promises";
|
|
7620
|
-
import { homedir as
|
|
7621
|
-
import
|
|
6773
|
+
import { homedir as homedir5 } from "node:os";
|
|
6774
|
+
import path19 from "node:path";
|
|
7622
6775
|
var TIMEOUT_MS2 = 12e4;
|
|
7623
6776
|
var SAFE_ARG = /^[A-Za-z0-9][A-Za-z0-9._@/-]*$/;
|
|
7624
6777
|
var PluginCli = class {
|
|
@@ -7717,10 +6870,10 @@ async function readCatalog(markets, installed) {
|
|
|
7717
6870
|
return lists.flat().sort((a, b) => a.name.localeCompare(b.name));
|
|
7718
6871
|
}
|
|
7719
6872
|
async function readMarketplace(market, installed) {
|
|
7720
|
-
const root = market.installLocation ||
|
|
6873
|
+
const root = market.installLocation || path19.join(homedir5(), ".claude", "plugins", "marketplaces", market.name);
|
|
7721
6874
|
let manifest;
|
|
7722
6875
|
try {
|
|
7723
|
-
const text = await readFile14(
|
|
6876
|
+
const text = await readFile14(path19.join(root, ".claude-plugin", "marketplace.json"), "utf8");
|
|
7724
6877
|
manifest = JSON.parse(text);
|
|
7725
6878
|
} catch {
|
|
7726
6879
|
return [];
|
|
@@ -7763,7 +6916,7 @@ function authorName(raw) {
|
|
|
7763
6916
|
}
|
|
7764
6917
|
|
|
7765
6918
|
// ../host/dist/auth.js
|
|
7766
|
-
import { EventEmitter as
|
|
6919
|
+
import { EventEmitter as EventEmitter4 } from "node:events";
|
|
7767
6920
|
var QUICK_TIMEOUT_MS = 3e4;
|
|
7768
6921
|
var LOGIN_TIMEOUT_MS = 10 * 6e4;
|
|
7769
6922
|
var URL_RE = /https:\/\/\S*\/oauth\/authorize\S*/;
|
|
@@ -7775,7 +6928,7 @@ var IDLE = {
|
|
|
7775
6928
|
output: "",
|
|
7776
6929
|
error: null
|
|
7777
6930
|
};
|
|
7778
|
-
var AuthCli = class extends
|
|
6931
|
+
var AuthCli = class extends EventEmitter4 {
|
|
7779
6932
|
#child = null;
|
|
7780
6933
|
#state = IDLE;
|
|
7781
6934
|
#timer = null;
|
|
@@ -7960,9 +7113,9 @@ function describe5(error) {
|
|
|
7960
7113
|
}
|
|
7961
7114
|
|
|
7962
7115
|
// ../host/dist/relay-link.js
|
|
7963
|
-
import { EventEmitter as
|
|
7116
|
+
import { EventEmitter as EventEmitter5 } from "node:events";
|
|
7964
7117
|
import { readFile as readFile15, writeFile as writeFile13, rm as rm5, mkdir as mkdir12 } from "node:fs/promises";
|
|
7965
|
-
import
|
|
7118
|
+
import path20 from "node:path";
|
|
7966
7119
|
import { hostname } from "node:os";
|
|
7967
7120
|
import WebSocket from "ws";
|
|
7968
7121
|
|
|
@@ -7979,7 +7132,7 @@ var SILENCE_TIMEOUT_MS = 95e3;
|
|
|
7979
7132
|
function jitter(delay2) {
|
|
7980
7133
|
return Math.round(delay2 * (0.8 + Math.random() * 0.4));
|
|
7981
7134
|
}
|
|
7982
|
-
var RelayLink = class extends
|
|
7135
|
+
var RelayLink = class extends EventEmitter5 {
|
|
7983
7136
|
#credentials = null;
|
|
7984
7137
|
#socket = null;
|
|
7985
7138
|
#retry = RETRY_MIN_MS;
|
|
@@ -8017,7 +7170,7 @@ var RelayLink = class extends EventEmitter7 {
|
|
|
8017
7170
|
#log;
|
|
8018
7171
|
constructor(options2) {
|
|
8019
7172
|
super();
|
|
8020
|
-
this.#file =
|
|
7173
|
+
this.#file = path20.join(options2.dataDir, "relay.json");
|
|
8021
7174
|
this.#defaultUrl = options2.defaultUrl.replace(/\/+$/, "");
|
|
8022
7175
|
this.#log = options2.log ?? ((msg) => console.log(`[relay] ${msg}`));
|
|
8023
7176
|
}
|
|
@@ -8111,7 +7264,7 @@ var RelayLink = class extends EventEmitter7 {
|
|
|
8111
7264
|
}
|
|
8112
7265
|
}
|
|
8113
7266
|
async #write(credentials) {
|
|
8114
|
-
await mkdir12(
|
|
7267
|
+
await mkdir12(path20.dirname(this.#file), { recursive: true });
|
|
8115
7268
|
await writeFile13(this.#file, `${JSON.stringify(credentials, null, 2)}
|
|
8116
7269
|
`, {
|
|
8117
7270
|
encoding: "utf8",
|
|
@@ -8367,14 +7520,14 @@ function humanize(error) {
|
|
|
8367
7520
|
}
|
|
8368
7521
|
|
|
8369
7522
|
// ../host/dist/terminal.js
|
|
8370
|
-
import { EventEmitter as
|
|
8371
|
-
import { access as access2, constants as
|
|
8372
|
-
import
|
|
8373
|
-
import { randomUUID as
|
|
7523
|
+
import { EventEmitter as EventEmitter6 } from "node:events";
|
|
7524
|
+
import { access as access2, constants as constants2 } from "node:fs/promises";
|
|
7525
|
+
import path21 from "node:path";
|
|
7526
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
8374
7527
|
var SCROLLBACK_BYTES = 256 * 1024;
|
|
8375
7528
|
var FLUSH_MS = 12;
|
|
8376
7529
|
var MAX_TERMINALS = 24;
|
|
8377
|
-
var TerminalHub = class extends
|
|
7530
|
+
var TerminalHub = class extends EventEmitter6 {
|
|
8378
7531
|
#terminals = /* @__PURE__ */ new Map();
|
|
8379
7532
|
#module = null;
|
|
8380
7533
|
list(workspaceId) {
|
|
@@ -8407,7 +7560,7 @@ var TerminalHub = class extends EventEmitter8 {
|
|
|
8407
7560
|
env: environment()
|
|
8408
7561
|
});
|
|
8409
7562
|
const info = {
|
|
8410
|
-
id:
|
|
7563
|
+
id: randomUUID4(),
|
|
8411
7564
|
workspaceId: options2.workspaceId,
|
|
8412
7565
|
title: shell.title,
|
|
8413
7566
|
shell: shell.file,
|
|
@@ -8539,36 +7692,36 @@ async function defaultShell() {
|
|
|
8539
7692
|
if (pwsh)
|
|
8540
7693
|
return { file: pwsh, args: [], title: "pwsh" };
|
|
8541
7694
|
const system = process.env.SystemRoot ?? "C:\\Windows";
|
|
8542
|
-
const powershell =
|
|
7695
|
+
const powershell = path21.join(system, "System32/WindowsPowerShell/v1.0/powershell.exe");
|
|
8543
7696
|
if (await exists2(powershell))
|
|
8544
7697
|
return { file: powershell, args: [], title: "powershell" };
|
|
8545
7698
|
return { file: process.env.COMSPEC ?? "cmd.exe", args: [], title: "cmd" };
|
|
8546
7699
|
}
|
|
8547
7700
|
const shell = process.env.SHELL;
|
|
8548
7701
|
if (shell && await exists2(shell))
|
|
8549
|
-
return { file: shell, args: [], title:
|
|
7702
|
+
return { file: shell, args: [], title: path21.basename(shell) };
|
|
8550
7703
|
if (await exists2("/bin/bash"))
|
|
8551
7704
|
return { file: "/bin/bash", args: [], title: "bash" };
|
|
8552
7705
|
return { file: "/bin/sh", args: [], title: "sh" };
|
|
8553
7706
|
}
|
|
8554
7707
|
async function findOnPath(name) {
|
|
8555
|
-
const dirs = (process.env.PATH ?? "").split(
|
|
7708
|
+
const dirs = (process.env.PATH ?? "").split(path21.delimiter).filter(Boolean);
|
|
8556
7709
|
for (const dir of dirs) {
|
|
8557
|
-
const candidate =
|
|
7710
|
+
const candidate = path21.join(dir, name);
|
|
8558
7711
|
if (await exists2(candidate))
|
|
8559
7712
|
return candidate;
|
|
8560
7713
|
}
|
|
8561
7714
|
return null;
|
|
8562
7715
|
}
|
|
8563
7716
|
function exists2(file) {
|
|
8564
|
-
return access2(file,
|
|
7717
|
+
return access2(file, constants2.X_OK).then(() => true, () => false);
|
|
8565
7718
|
}
|
|
8566
7719
|
|
|
8567
7720
|
// ../host/dist/mcp-config.js
|
|
8568
7721
|
import { readFile as readFile16, writeFile as writeFile14, mkdir as mkdir13 } from "node:fs/promises";
|
|
8569
|
-
import
|
|
7722
|
+
import path22 from "node:path";
|
|
8570
7723
|
var MCP_FILE = ".mcp.json";
|
|
8571
|
-
var LOCAL_SETTINGS2 =
|
|
7724
|
+
var LOCAL_SETTINGS2 = path22.join(".claude", "settings.local.json");
|
|
8572
7725
|
var queues = /* @__PURE__ */ new Map();
|
|
8573
7726
|
function serialize(cwd, work) {
|
|
8574
7727
|
const previous = queues.get(cwd) ?? Promise.resolve();
|
|
@@ -8577,7 +7730,7 @@ function serialize(cwd, work) {
|
|
|
8577
7730
|
return next;
|
|
8578
7731
|
}
|
|
8579
7732
|
async function readProjectServers(cwd) {
|
|
8580
|
-
const file = await readJson(
|
|
7733
|
+
const file = await readJson(path22.join(cwd, MCP_FILE));
|
|
8581
7734
|
const servers = file?.mcpServers;
|
|
8582
7735
|
if (!servers || typeof servers !== "object")
|
|
8583
7736
|
return {};
|
|
@@ -8585,23 +7738,23 @@ async function readProjectServers(cwd) {
|
|
|
8585
7738
|
}
|
|
8586
7739
|
function addProjectServer(cwd, name, config) {
|
|
8587
7740
|
return serialize(cwd, async () => {
|
|
8588
|
-
const file = await readJson(
|
|
7741
|
+
const file = await readJson(path22.join(cwd, MCP_FILE)) ?? {};
|
|
8589
7742
|
const servers = file.mcpServers ?? {};
|
|
8590
7743
|
servers[name] = config;
|
|
8591
7744
|
file.mcpServers = servers;
|
|
8592
|
-
await writeJson(
|
|
7745
|
+
await writeJson(path22.join(cwd, MCP_FILE), file);
|
|
8593
7746
|
await approve(cwd, name);
|
|
8594
7747
|
});
|
|
8595
7748
|
}
|
|
8596
7749
|
function removeProjectServer(cwd, name) {
|
|
8597
7750
|
return serialize(cwd, async () => {
|
|
8598
|
-
const file = await readJson(
|
|
7751
|
+
const file = await readJson(path22.join(cwd, MCP_FILE));
|
|
8599
7752
|
const servers = file?.mcpServers;
|
|
8600
7753
|
if (!servers || !(name in servers))
|
|
8601
7754
|
return false;
|
|
8602
7755
|
delete servers[name];
|
|
8603
|
-
await writeJson(
|
|
8604
|
-
const settingsPath =
|
|
7756
|
+
await writeJson(path22.join(cwd, MCP_FILE), file);
|
|
7757
|
+
const settingsPath = path22.join(cwd, LOCAL_SETTINGS2);
|
|
8605
7758
|
const settings = await readJson(settingsPath);
|
|
8606
7759
|
const enabled = settings?.enabledMcpjsonServers;
|
|
8607
7760
|
if (settings && Array.isArray(enabled) && enabled.includes(name)) {
|
|
@@ -8612,7 +7765,7 @@ function removeProjectServer(cwd, name) {
|
|
|
8612
7765
|
});
|
|
8613
7766
|
}
|
|
8614
7767
|
async function approve(cwd, name) {
|
|
8615
|
-
const file =
|
|
7768
|
+
const file = path22.join(cwd, LOCAL_SETTINGS2);
|
|
8616
7769
|
const settings = await readJson(file) ?? {};
|
|
8617
7770
|
const enabled = Array.isArray(settings.enabledMcpjsonServers) ? settings.enabledMcpjsonServers : [];
|
|
8618
7771
|
if (!enabled.includes(name))
|
|
@@ -8658,13 +7811,13 @@ async function readJson(file) {
|
|
|
8658
7811
|
if (error.code === "ENOENT")
|
|
8659
7812
|
return null;
|
|
8660
7813
|
if (error instanceof SyntaxError) {
|
|
8661
|
-
throw new Error(`\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u0440\u0430\u0437\u043E\u0431\u0440\u0430\u0442\u044C ${
|
|
7814
|
+
throw new Error(`\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u0440\u0430\u0437\u043E\u0431\u0440\u0430\u0442\u044C ${path22.basename(file)}: ${error.message}`);
|
|
8662
7815
|
}
|
|
8663
7816
|
throw error;
|
|
8664
7817
|
}
|
|
8665
7818
|
}
|
|
8666
7819
|
async function writeJson(file, data) {
|
|
8667
|
-
await mkdir13(
|
|
7820
|
+
await mkdir13(path22.dirname(file), { recursive: true });
|
|
8668
7821
|
await writeFile14(file, `${JSON.stringify(data, null, 2)}
|
|
8669
7822
|
`, "utf8");
|
|
8670
7823
|
}
|
|
@@ -8683,8 +7836,6 @@ var BUSY_STATES2 = /* @__PURE__ */ new Set([
|
|
|
8683
7836
|
"reconnecting"
|
|
8684
7837
|
]);
|
|
8685
7838
|
var HostServer = class {
|
|
8686
|
-
#httpServer = null;
|
|
8687
|
-
#webSockets = null;
|
|
8688
7839
|
#options;
|
|
8689
7840
|
#workspaces;
|
|
8690
7841
|
#archive;
|
|
@@ -8697,7 +7848,6 @@ var HostServer = class {
|
|
|
8697
7848
|
/** Опросы статуса для идущих OAuth-входов MCP, ключ — сессия и сервер. */
|
|
8698
7849
|
#mcpAuthWatch = /* @__PURE__ */ new Map();
|
|
8699
7850
|
#antigravity;
|
|
8700
|
-
#codex;
|
|
8701
7851
|
/** Боковые сессии («вопрос на полях») по id родителя — не больше одной на разговор. */
|
|
8702
7852
|
#sides = /* @__PURE__ */ new Map();
|
|
8703
7853
|
/**
|
|
@@ -8745,7 +7895,7 @@ var HostServer = class {
|
|
|
8745
7895
|
#limitHandoffBusy = /* @__PURE__ */ new Set();
|
|
8746
7896
|
/** Живые id сессий, у которых сейчас пишется ручной хэндофф. */
|
|
8747
7897
|
#handoffBusy = /* @__PURE__ */ new Set();
|
|
8748
|
-
#hostId =
|
|
7898
|
+
#hostId = randomUUID5();
|
|
8749
7899
|
#plugins = new PluginCli();
|
|
8750
7900
|
#auth = new AuthCli();
|
|
8751
7901
|
#relay;
|
|
@@ -8769,7 +7919,6 @@ var HostServer = class {
|
|
|
8769
7919
|
this.#folders = new Folders(options2.dataDir);
|
|
8770
7920
|
this.#settings = new AppSettingsStore(options2.dataDir);
|
|
8771
7921
|
this.#antigravity = new AntigravityStore(options2.dataDir);
|
|
8772
|
-
this.#codex = new AntigravityStore(options2.dataDir, "codex");
|
|
8773
7922
|
this.#handoffs = new HandoffStore(options2.dataDir);
|
|
8774
7923
|
this.#limitStop = new LimitStopState(options2.dataDir);
|
|
8775
7924
|
this.#finder = new ProjectFinder(this.#workspaces);
|
|
@@ -8796,11 +7945,9 @@ var HostServer = class {
|
|
|
8796
7945
|
const id = workspaceIdFromPath(dir);
|
|
8797
7946
|
const onDisk = await this.#workspaces.sessionsOnDisk(id);
|
|
8798
7947
|
const antigravity = await this.#antigravity.list(id);
|
|
8799
|
-
|
|
8800
|
-
return [...onDisk.map((s) => s.sessionId), ...antigravity.map((r) => r.id), ...codex.map((r) => r.id)];
|
|
7948
|
+
return [...onDisk.map((s) => s.sessionId), ...antigravity.map((r) => r.id)];
|
|
8801
7949
|
});
|
|
8802
7950
|
await this.#antigravity.remapWorkspaceIds(remap);
|
|
8803
|
-
await this.#codex.remapWorkspaceIds(remap);
|
|
8804
7951
|
await this.#archive.remapWorkspaceIds(remap);
|
|
8805
7952
|
await this.#pins.remapWorkspaceIds(remap);
|
|
8806
7953
|
await this.#order.remapWorkspaceIds(remap);
|
|
@@ -8835,8 +7982,6 @@ var HostServer = class {
|
|
|
8835
7982
|
resolve();
|
|
8836
7983
|
});
|
|
8837
7984
|
});
|
|
8838
|
-
this.#httpServer = httpServer;
|
|
8839
|
-
this.#webSockets = wss;
|
|
8840
7985
|
await this.#relay.start().catch((error) => {
|
|
8841
7986
|
console.error("[relay]", error instanceof Error ? error.message : String(error));
|
|
8842
7987
|
});
|
|
@@ -8875,16 +8020,6 @@ var HostServer = class {
|
|
|
8875
8020
|
await this.#relay.close();
|
|
8876
8021
|
await Promise.all([...this.#sessions.values()].map((s) => s.close("host shutdown")));
|
|
8877
8022
|
this.#sessions.clear();
|
|
8878
|
-
const wss = this.#webSockets;
|
|
8879
|
-
const http = this.#httpServer;
|
|
8880
|
-
this.#webSockets = null;
|
|
8881
|
-
this.#httpServer = null;
|
|
8882
|
-
for (const socket of wss?.clients ?? [])
|
|
8883
|
-
socket.terminate();
|
|
8884
|
-
await Promise.all([
|
|
8885
|
-
...wss ? [new Promise((resolve) => wss.close(() => resolve()))] : [],
|
|
8886
|
-
...http ? [new Promise((resolve) => http.close(() => resolve()))] : []
|
|
8887
|
-
]);
|
|
8888
8023
|
}
|
|
8889
8024
|
// -------------------------------------------------------------------------
|
|
8890
8025
|
// WebSocket
|
|
@@ -10284,31 +9419,7 @@ var HostServer = class {
|
|
|
10284
9419
|
throw new Error(`\u0412\u043E\u0440\u043A\u0441\u043F\u0435\u0439\u0441 \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D: ${frame.workspaceId}`);
|
|
10285
9420
|
const provider = frame.provider ?? "claude";
|
|
10286
9421
|
if (!frame.resume && !this.#settings.current.enabledProviders.includes(provider)) {
|
|
10287
|
-
throw new Error(`${provider === "antigravity" ? "Antigravity" :
|
|
10288
|
-
}
|
|
10289
|
-
const codexRecord = frame.resume ? await this.#codex.find(frame.resume) : null;
|
|
10290
|
-
if (codexRecord || !frame.resume && provider === "codex") {
|
|
10291
|
-
if (frame.fork)
|
|
10292
|
-
throw new Error("\u0412\u0435\u0442\u0432\u043B\u0435\u043D\u0438\u0435 \u0441\u0435\u0441\u0441\u0438\u0439 Codex \u043F\u043E\u043A\u0430 \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F");
|
|
10293
|
-
if (codexRecord && codexRecord.workspaceId !== workspace.id)
|
|
10294
|
-
throw new Error("\u0421\u0435\u0441\u0441\u0438\u044F Codex \u043F\u0440\u0438\u043D\u0430\u0434\u043B\u0435\u0436\u0438\u0442 \u0434\u0440\u0443\u0433\u043E\u043C\u0443 \u043F\u0440\u043E\u0435\u043A\u0442\u0443");
|
|
10295
|
-
if (codexRecord)
|
|
10296
|
-
await this.#archive.unarchive([codexRecord.id]);
|
|
10297
|
-
const session2 = new CodexSession({
|
|
10298
|
-
workspaceId: workspace.id,
|
|
10299
|
-
cwd: codexRecord?.cwd ?? workspace.path,
|
|
10300
|
-
store: this.#codex,
|
|
10301
|
-
...codexRecord ? { record: codexRecord } : {},
|
|
10302
|
-
...frame.permissionMode ? { permissionMode: frame.permissionMode } : {},
|
|
10303
|
-
...frame.model ? { model: frame.model } : {},
|
|
10304
|
-
defaultTitle: workspace.name
|
|
10305
|
-
});
|
|
10306
|
-
this.#wire(session2);
|
|
10307
|
-
this.#sessions.set(session2.id, session2);
|
|
10308
|
-
session2.start();
|
|
10309
|
-
this.#sendLive();
|
|
10310
|
-
this.#send(socket, { type: "session.summary", session: session2.summary() });
|
|
10311
|
-
return;
|
|
9422
|
+
throw new Error(`${provider === "antigravity" ? "Antigravity" : "Claude"} \u0432\u044B\u043A\u043B\u044E\u0447\u0435\u043D \u0432 \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0430\u0445`);
|
|
10312
9423
|
}
|
|
10313
9424
|
const agyRecord = frame.resume ? await this.#antigravity.find(frame.resume) : null;
|
|
10314
9425
|
if (agyRecord || !frame.resume && frame.provider === "antigravity") {
|
|
@@ -10472,7 +9583,7 @@ var HostServer = class {
|
|
|
10472
9583
|
this.#broadcast({ type: "context.state", sessionId: session.id, context });
|
|
10473
9584
|
});
|
|
10474
9585
|
session.on("stderr", (data) => {
|
|
10475
|
-
const tag = session instanceof AntigravitySession ? "agy" :
|
|
9586
|
+
const tag = session instanceof AntigravitySession ? "agy" : "claude";
|
|
10476
9587
|
process.stderr.write(`[${tag} ${session.id.slice(0, 8)}] ${data}`);
|
|
10477
9588
|
});
|
|
10478
9589
|
}
|
|
@@ -10492,7 +9603,7 @@ var HostServer = class {
|
|
|
10492
9603
|
* разговора пока и не было.
|
|
10493
9604
|
*/
|
|
10494
9605
|
#ensureSide(parent) {
|
|
10495
|
-
if (
|
|
9606
|
+
if (parent instanceof AntigravitySession) {
|
|
10496
9607
|
throw new Error("\u0412\u043E\u043F\u0440\u043E\u0441 \u043D\u0430 \u043F\u043E\u043B\u044F\u0445 \u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D \u0442\u043E\u043B\u044C\u043A\u043E \u0432 \u0441\u0435\u0441\u0441\u0438\u044F\u0445 Claude");
|
|
10497
9608
|
}
|
|
10498
9609
|
const existing = this.#sides.get(parent.id);
|
|
@@ -10550,7 +9661,7 @@ var HostServer = class {
|
|
|
10550
9661
|
*/
|
|
10551
9662
|
#roots() {
|
|
10552
9663
|
const roots = this.#finder.roots();
|
|
10553
|
-
return roots.length > 0 ? roots : [
|
|
9664
|
+
return roots.length > 0 ? roots : [homedir6()];
|
|
10554
9665
|
}
|
|
10555
9666
|
/**
|
|
10556
9667
|
* Где сессии этого каталога разрешено писать без вопроса.
|
|
@@ -10792,7 +9903,7 @@ var HostServer = class {
|
|
|
10792
9903
|
live.setTitle(title);
|
|
10793
9904
|
return;
|
|
10794
9905
|
}
|
|
10795
|
-
if (await this.#antigravity.rename(sessionId, title)
|
|
9906
|
+
if (await this.#antigravity.rename(sessionId, title)) {
|
|
10796
9907
|
if (workspaceId)
|
|
10797
9908
|
await this.#sendSessionList(workspaceId);
|
|
10798
9909
|
return;
|
|
@@ -10849,11 +9960,6 @@ var HostServer = class {
|
|
|
10849
9960
|
continue;
|
|
10850
9961
|
historical.push(antigravitySummary(record));
|
|
10851
9962
|
}
|
|
10852
|
-
for (const record of await this.#codex.list(workspaceId)) {
|
|
10853
|
-
if (liveIds.has(record.id))
|
|
10854
|
-
continue;
|
|
10855
|
-
historical.push({ ...antigravitySummary(record), provider: "codex", switchModelsOnFlag: false });
|
|
10856
|
-
}
|
|
10857
9963
|
const known = /* @__PURE__ */ new Set([...liveIds, ...historical.map((s) => s.id)]);
|
|
10858
9964
|
await this.#archive.sweep(workspaceId, historical.filter((s) => !this.#pins.has(s.id)).map((s) => ({ id: s.id, updatedAt: s.updatedAt })), known, this.#settings.current.autoArchiveAfterMs);
|
|
10859
9965
|
await this.#pins.sweep(workspaceId, known);
|
|
@@ -10900,15 +10006,15 @@ var HostServer = class {
|
|
|
10900
10006
|
}
|
|
10901
10007
|
#serveStatic(req, res) {
|
|
10902
10008
|
const webRoot = this.#options.webRoot;
|
|
10903
|
-
if (!webRoot || !
|
|
10009
|
+
if (!webRoot || !existsSync4(webRoot)) {
|
|
10904
10010
|
res.writeHead(200, { "content-type": "text/plain; charset=utf-8" });
|
|
10905
10011
|
res.end("CCV host is running. UI is served by the Vite dev server.\n");
|
|
10906
10012
|
return;
|
|
10907
10013
|
}
|
|
10908
10014
|
const url2 = new URL(req.url ?? "/", "http://localhost");
|
|
10909
|
-
const requested =
|
|
10910
|
-
const target = requested.startsWith(webRoot) &&
|
|
10911
|
-
if (!
|
|
10015
|
+
const requested = path23.join(webRoot, path23.normalize(url2.pathname));
|
|
10016
|
+
const target = requested.startsWith(webRoot) && existsSync4(requested) && statSync3(requested).isFile() ? requested : path23.join(webRoot, "index.html");
|
|
10017
|
+
if (!existsSync4(target)) {
|
|
10912
10018
|
res.writeHead(404).end("not found");
|
|
10913
10019
|
return;
|
|
10914
10020
|
}
|
|
@@ -10933,7 +10039,7 @@ function contentType(file) {
|
|
|
10933
10039
|
".svg": "image/svg+xml",
|
|
10934
10040
|
".woff2": "font/woff2"
|
|
10935
10041
|
};
|
|
10936
|
-
return types[
|
|
10042
|
+
return types[path23.extname(file)] ?? "application/octet-stream";
|
|
10937
10043
|
}
|
|
10938
10044
|
function antigravitySummary(record) {
|
|
10939
10045
|
return {
|
|
@@ -10962,9 +10068,9 @@ function antigravitySummary(record) {
|
|
|
10962
10068
|
}
|
|
10963
10069
|
|
|
10964
10070
|
// dist/ccv.js
|
|
10965
|
-
var HERE =
|
|
10966
|
-
var PACKAGE_ROOT =
|
|
10967
|
-
var USAGE = `ccv \u2014 Claude Code Visual: \u0438\u043D\u0442\u0435\u0440\u0444\u0435\u0439\u0441
|
|
10071
|
+
var HERE = path24.dirname(fileURLToPath(import.meta.url));
|
|
10072
|
+
var PACKAGE_ROOT = path24.resolve(HERE, "..");
|
|
10073
|
+
var USAGE = `ccv \u2014 Claude Code Visual: \u043B\u043E\u043A\u0430\u043B\u044C\u043D\u044B\u0439 \u0445\u043E\u0441\u0442 Claude Code \u0441 \u0438\u043D\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043E\u043C \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435.
|
|
10968
10074
|
|
|
10969
10075
|
\u0418\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u0435:
|
|
10970
10076
|
ccv [\u043E\u043F\u0446\u0438\u0438]
|
|
@@ -10973,12 +10079,12 @@ var USAGE = `ccv \u2014 Claude Code Visual: \u0438\u043D\u0442\u0435\u0440\u0444
|
|
|
10973
10079
|
-p, --port <\u043F\u043E\u0440\u0442> \u043F\u043E\u0440\u0442 \u0445\u043E\u0441\u0442\u0430 (\u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E 8787)
|
|
10974
10080
|
--host <\u0430\u0434\u0440\u0435\u0441> \u0430\u0434\u0440\u0435\u0441 \u043F\u0440\u043E\u0441\u043B\u0443\u0448\u0438\u0432\u0430\u043D\u0438\u044F (\u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E 127.0.0.1)
|
|
10975
10081
|
--no-open \u043D\u0435 \u043E\u0442\u043A\u0440\u044B\u0432\u0430\u0442\u044C \u0431\u0440\u0430\u0443\u0437\u0435\u0440
|
|
10976
|
-
--claude \u0447\u0435\u043C \u0431\u0443\u0434\u0443\u0442 \u043F\u043E\u0434\u043D\u0438\u043C\u0430\u0442\u044C\u0441\u044F \u0441\u0435\u0441\u0441\u0438\u0438
|
|
10082
|
+
--claude \u0447\u0435\u043C \u0431\u0443\u0434\u0443\u0442 \u043F\u043E\u0434\u043D\u0438\u043C\u0430\u0442\u044C\u0441\u044F \u0441\u0435\u0441\u0441\u0438\u0438, \u0438 \u0432\u044B\u0439\u0442\u0438
|
|
10977
10083
|
-v, --version \u0432\u0435\u0440\u0441\u0438\u044F
|
|
10978
10084
|
-h, --help \u044D\u0442\u0430 \u0441\u043F\u0440\u0430\u0432\u043A\u0430
|
|
10979
10085
|
|
|
10980
10086
|
\u041E\u043A\u0440\u0443\u0436\u0435\u043D\u0438\u0435: CCV_PORT, CCV_HOST, CCV_DATA_DIR, CCV_WEB_ROOT, CCV_RELAY_URL,
|
|
10981
|
-
CCV_CLAUDE_PATH, CCV_BUNDLED_CLAUDE
|
|
10087
|
+
CCV_CLAUDE_PATH, CCV_BUNDLED_CLAUDE.
|
|
10982
10088
|
\u0424\u043B\u0430\u0433 \u0432\u0430\u0436\u043D\u0435\u0435 \u043F\u0435\u0440\u0435\u043C\u0435\u043D\u043D\u043E\u0439 \u043E\u043A\u0440\u0443\u0436\u0435\u043D\u0438\u044F, \u043F\u0435\u0440\u0435\u043C\u0435\u043D\u043D\u0430\u044F \u0432\u0430\u0436\u043D\u0435\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E.`;
|
|
10983
10089
|
var options = {
|
|
10984
10090
|
port: { type: "string", short: "p" },
|
|
@@ -11030,7 +10136,7 @@ var server = new HostServer({
|
|
|
11030
10136
|
dataDir: defaults.dataDir,
|
|
11031
10137
|
// UI лежит в пакете рядом с бандлом — это и есть разница между установленной
|
|
11032
10138
|
// утилитой и запуском из репозитория, где сборка живёт в `apps/web/dist`.
|
|
11033
|
-
webRoot: process.env.CCV_WEB_ROOT ??
|
|
10139
|
+
webRoot: process.env.CCV_WEB_ROOT ?? path24.join(PACKAGE_ROOT, "web"),
|
|
11034
10140
|
version,
|
|
11035
10141
|
relayUrl: defaults.relayUrl
|
|
11036
10142
|
});
|
|
@@ -11059,7 +10165,7 @@ for (const signal of ["SIGINT", "SIGTERM"]) {
|
|
|
11059
10165
|
}
|
|
11060
10166
|
async function packageVersion() {
|
|
11061
10167
|
try {
|
|
11062
|
-
const text = await readFile17(
|
|
10168
|
+
const text = await readFile17(path24.join(PACKAGE_ROOT, "package.json"), "utf8");
|
|
11063
10169
|
return JSON.parse(text).version ?? "0.0.0";
|
|
11064
10170
|
} catch {
|
|
11065
10171
|
return "0.0.0";
|
|
@@ -11103,7 +10209,7 @@ function openBrowser(target) {
|
|
|
11103
10209
|
return;
|
|
11104
10210
|
}
|
|
11105
10211
|
const command = process.platform === "win32" ? { file: "cmd", args: ["/c", "start", "", target] } : process.platform === "darwin" ? { file: "open", args: [target] } : { file: "xdg-open", args: [target] };
|
|
11106
|
-
const child =
|
|
10212
|
+
const child = spawn3(command.file, command.args, {
|
|
11107
10213
|
stdio: "ignore",
|
|
11108
10214
|
detached: true,
|
|
11109
10215
|
windowsHide: true
|