tesseract-agent 0.9.33 → 0.9.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-bundle/cli.js +1328 -514
- package/package.json +1 -1
package/dist-bundle/cli.js
CHANGED
|
@@ -27453,10 +27453,10 @@ var init_client = __esm({
|
|
|
27453
27453
|
* collect the result of an `async: true` submission. */
|
|
27454
27454
|
async archive(searchId, output2 = "json") {
|
|
27455
27455
|
const { apiKey, baseUrl } = await this.creds();
|
|
27456
|
-
const
|
|
27457
|
-
if (!/^[A-Za-z0-9_-]{6,128}$/.test(
|
|
27456
|
+
const safe2 = String(searchId).trim();
|
|
27457
|
+
if (!/^[A-Za-z0-9_-]{6,128}$/.test(safe2))
|
|
27458
27458
|
throw new SerpApiError(`Invalid search id "${searchId}".`, "bad_request");
|
|
27459
|
-
const u = _SerpClient.join(baseUrl ?? DEFAULT_BASE_URL, `searches/${
|
|
27459
|
+
const u = _SerpClient.join(baseUrl ?? DEFAULT_BASE_URL, `searches/${safe2}.${output2 === "md" ? "md" : "json"}`);
|
|
27460
27460
|
u.searchParams.set("api_key", apiKey);
|
|
27461
27461
|
return this.getJson(u.toString(), "archive", {}, { billed: false });
|
|
27462
27462
|
}
|
|
@@ -27465,10 +27465,10 @@ var init_client = __esm({
|
|
|
27465
27465
|
* the body is text, and feeding it to JSON.parse is how the markdown path used to throw. */
|
|
27466
27466
|
async archiveMarkdown(searchId) {
|
|
27467
27467
|
const { apiKey, baseUrl } = await this.creds();
|
|
27468
|
-
const
|
|
27469
|
-
if (!/^[A-Za-z0-9_-]{6,128}$/.test(
|
|
27468
|
+
const safe2 = String(searchId).trim();
|
|
27469
|
+
if (!/^[A-Za-z0-9_-]{6,128}$/.test(safe2))
|
|
27470
27470
|
throw new SerpApiError(`Invalid search id "${searchId}".`, "bad_request");
|
|
27471
|
-
const u = _SerpClient.join(baseUrl ?? DEFAULT_BASE_URL, `searches/${
|
|
27471
|
+
const u = _SerpClient.join(baseUrl ?? DEFAULT_BASE_URL, `searches/${safe2}.md`);
|
|
27472
27472
|
u.searchParams.set("api_key", apiKey);
|
|
27473
27473
|
const { text: text9 } = await this.fetchWithRetry(u.toString(), "archive", {}, false);
|
|
27474
27474
|
return { markdown: text9 };
|
|
@@ -29181,7 +29181,123 @@ var init_plan_splitter = __esm({
|
|
|
29181
29181
|
}
|
|
29182
29182
|
});
|
|
29183
29183
|
|
|
29184
|
+
// ../../packages/agent-core/dist/unattended-log.js
|
|
29185
|
+
var unattended_log_exports = {};
|
|
29186
|
+
__export(unattended_log_exports, {
|
|
29187
|
+
readUnattendedDecisions: () => readUnattendedDecisions,
|
|
29188
|
+
recordUnattendedDecision: () => recordUnattendedDecision,
|
|
29189
|
+
recordVerificationDecision: () => recordVerificationDecision,
|
|
29190
|
+
setUnattendedLogSink: () => setUnattendedLogSink,
|
|
29191
|
+
unattendedLogPath: () => unattendedLogPath
|
|
29192
|
+
});
|
|
29193
|
+
import { appendFileSync, closeSync as closeSync3, existsSync as existsSync7, mkdirSync as mkdirSync9, openSync as openSync3, readFileSync as readFileSync13, readSync as readSync2, renameSync as renameSync6, statSync as statSync5 } from "node:fs";
|
|
29194
|
+
import { dirname as dirname7 } from "node:path";
|
|
29195
|
+
function unattendedLogPath() {
|
|
29196
|
+
return daemonPath("unattended.jsonl");
|
|
29197
|
+
}
|
|
29198
|
+
function rolledPath() {
|
|
29199
|
+
return `${unattendedLogPath()}.1`;
|
|
29200
|
+
}
|
|
29201
|
+
function healPrefix(file2) {
|
|
29202
|
+
if (appended)
|
|
29203
|
+
return "";
|
|
29204
|
+
appended = true;
|
|
29205
|
+
try {
|
|
29206
|
+
const size = statSync5(file2).size;
|
|
29207
|
+
if (size === 0)
|
|
29208
|
+
return "";
|
|
29209
|
+
const fd = openSync3(file2, "r");
|
|
29210
|
+
try {
|
|
29211
|
+
const buf = Buffer.alloc(1);
|
|
29212
|
+
readSync2(fd, buf, 0, 1, size - 1);
|
|
29213
|
+
return buf[0] === 10 ? "" : "\n";
|
|
29214
|
+
} finally {
|
|
29215
|
+
closeSync3(fd);
|
|
29216
|
+
}
|
|
29217
|
+
} catch {
|
|
29218
|
+
return "";
|
|
29219
|
+
}
|
|
29220
|
+
}
|
|
29221
|
+
function setUnattendedLogSink(fn) {
|
|
29222
|
+
sink = fn;
|
|
29223
|
+
warned = false;
|
|
29224
|
+
appended = false;
|
|
29225
|
+
}
|
|
29226
|
+
function rotateIfNeeded(file2) {
|
|
29227
|
+
try {
|
|
29228
|
+
if (!existsSync7(file2) || statSync5(file2).size < MAX_BYTES)
|
|
29229
|
+
return;
|
|
29230
|
+
renameSync6(file2, rolledPath());
|
|
29231
|
+
} catch {
|
|
29232
|
+
}
|
|
29233
|
+
}
|
|
29234
|
+
function recordUnattendedDecision(entry) {
|
|
29235
|
+
if (sink) {
|
|
29236
|
+
try {
|
|
29237
|
+
sink(entry);
|
|
29238
|
+
} catch {
|
|
29239
|
+
}
|
|
29240
|
+
return;
|
|
29241
|
+
}
|
|
29242
|
+
try {
|
|
29243
|
+
const file2 = unattendedLogPath();
|
|
29244
|
+
mkdirSync9(dirname7(file2), { recursive: true });
|
|
29245
|
+
rotateIfNeeded(file2);
|
|
29246
|
+
appendFileSync(file2, `${healPrefix(file2)}${JSON.stringify(entry)}
|
|
29247
|
+
`, { mode: 384 });
|
|
29248
|
+
} catch (err2) {
|
|
29249
|
+
if (warned)
|
|
29250
|
+
return;
|
|
29251
|
+
warned = true;
|
|
29252
|
+
console.error("[unattended] decision log unavailable:", err2 instanceof Error ? err2.message : err2);
|
|
29253
|
+
}
|
|
29254
|
+
}
|
|
29255
|
+
function recordVerificationDecision(entry) {
|
|
29256
|
+
recordUnattendedDecision({ ts: (/* @__PURE__ */ new Date()).toISOString(), source: "verification", ...entry });
|
|
29257
|
+
}
|
|
29258
|
+
function readUnattendedDecisions(limit = 200, opts) {
|
|
29259
|
+
const out = [];
|
|
29260
|
+
for (const file2 of [rolledPath(), unattendedLogPath()]) {
|
|
29261
|
+
let text9;
|
|
29262
|
+
try {
|
|
29263
|
+
if (!existsSync7(file2))
|
|
29264
|
+
continue;
|
|
29265
|
+
text9 = readFileSync13(file2, "utf8");
|
|
29266
|
+
} catch {
|
|
29267
|
+
continue;
|
|
29268
|
+
}
|
|
29269
|
+
for (const line of text9.split("\n")) {
|
|
29270
|
+
if (!line.trim())
|
|
29271
|
+
continue;
|
|
29272
|
+
try {
|
|
29273
|
+
const entry = JSON.parse(line);
|
|
29274
|
+
if (opts?.sessionId && entry.sessionId !== opts.sessionId)
|
|
29275
|
+
continue;
|
|
29276
|
+
if (opts?.source && entry.source !== opts.source)
|
|
29277
|
+
continue;
|
|
29278
|
+
out.push(entry);
|
|
29279
|
+
} catch {
|
|
29280
|
+
}
|
|
29281
|
+
}
|
|
29282
|
+
}
|
|
29283
|
+
return limit > 0 && out.length > limit ? out.slice(-limit) : out;
|
|
29284
|
+
}
|
|
29285
|
+
var MAX_BYTES, appended, warned, sink;
|
|
29286
|
+
var init_unattended_log = __esm({
|
|
29287
|
+
"../../packages/agent-core/dist/unattended-log.js"() {
|
|
29288
|
+
"use strict";
|
|
29289
|
+
init_base_paths();
|
|
29290
|
+
MAX_BYTES = 4 * 1024 * 1024;
|
|
29291
|
+
appended = false;
|
|
29292
|
+
warned = false;
|
|
29293
|
+
sink = null;
|
|
29294
|
+
}
|
|
29295
|
+
});
|
|
29296
|
+
|
|
29184
29297
|
// ../../packages/agent-core/dist/unattended.js
|
|
29298
|
+
function errText(err2) {
|
|
29299
|
+
return err2 instanceof Error ? err2.message : String(err2);
|
|
29300
|
+
}
|
|
29185
29301
|
function unattendedModeFor(o) {
|
|
29186
29302
|
if (o.optedIn === true)
|
|
29187
29303
|
return "auto";
|
|
@@ -29232,18 +29348,48 @@ function unattendedAnswer(mode, prompt, opts) {
|
|
|
29232
29348
|
}
|
|
29233
29349
|
}
|
|
29234
29350
|
}
|
|
29351
|
+
function logSubject(prompt) {
|
|
29352
|
+
switch (prompt.kind) {
|
|
29353
|
+
case "permission":
|
|
29354
|
+
case "question":
|
|
29355
|
+
case "plan":
|
|
29356
|
+
return prompt.tool;
|
|
29357
|
+
case "elicitation":
|
|
29358
|
+
return prompt.serverName;
|
|
29359
|
+
case "dialog":
|
|
29360
|
+
return prompt.dialogKind;
|
|
29361
|
+
default:
|
|
29362
|
+
return void 0;
|
|
29363
|
+
}
|
|
29364
|
+
}
|
|
29235
29365
|
function scheduleUnattendedAnswer(prompt, deps) {
|
|
29236
29366
|
if (deps.mode() === "off")
|
|
29237
29367
|
return;
|
|
29368
|
+
const record2 = (mode, outcome, extra = {}) => {
|
|
29369
|
+
recordUnattendedDecision({
|
|
29370
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
29371
|
+
source: "prompt",
|
|
29372
|
+
...deps.context?.sessionId ? { sessionId: deps.context.sessionId } : {},
|
|
29373
|
+
...deps.context?.engine ? { engine: deps.context.engine } : {},
|
|
29374
|
+
mode,
|
|
29375
|
+
kind: prompt.kind,
|
|
29376
|
+
...logSubject(prompt) ? { subject: logSubject(prompt) } : {},
|
|
29377
|
+
outcome,
|
|
29378
|
+
...extra
|
|
29379
|
+
});
|
|
29380
|
+
};
|
|
29238
29381
|
const timer2 = setTimeout(() => {
|
|
29239
29382
|
const mode = deps.mode();
|
|
29240
|
-
if (mode === "off")
|
|
29383
|
+
if (mode === "off") {
|
|
29384
|
+
record2("off", "skipped", { reason: "unattended switched off before the answer landed" });
|
|
29241
29385
|
return;
|
|
29386
|
+
}
|
|
29242
29387
|
let spent;
|
|
29243
29388
|
try {
|
|
29244
29389
|
spent = deps.charge();
|
|
29245
29390
|
} catch (err2) {
|
|
29246
29391
|
deps.log?.("unattended budget charge failed:", err2);
|
|
29392
|
+
record2(mode, "failed", { reason: `budget charge failed: ${errText(err2)}` });
|
|
29247
29393
|
return;
|
|
29248
29394
|
}
|
|
29249
29395
|
const cappedOut = spent > UNATTENDED_MAX_DECISIONS;
|
|
@@ -29253,6 +29399,7 @@ function scheduleUnattendedAnswer(prompt, deps) {
|
|
|
29253
29399
|
deps.refund();
|
|
29254
29400
|
} catch {
|
|
29255
29401
|
}
|
|
29402
|
+
record2(mode, "skipped", { reason: "no policy answer for this prompt kind", spent });
|
|
29256
29403
|
return;
|
|
29257
29404
|
}
|
|
29258
29405
|
let applied = false;
|
|
@@ -29260,6 +29407,13 @@ function scheduleUnattendedAnswer(prompt, deps) {
|
|
|
29260
29407
|
applied = deps.apply(answer);
|
|
29261
29408
|
} catch (err2) {
|
|
29262
29409
|
deps.log?.("unattended auto-answer failed:", err2);
|
|
29410
|
+
record2(mode, "failed", {
|
|
29411
|
+
reason: `apply failed: ${errText(err2)}`,
|
|
29412
|
+
behavior: answer.behavior,
|
|
29413
|
+
decision: answer.decision,
|
|
29414
|
+
spent,
|
|
29415
|
+
...cappedOut ? { cappedOut } : {}
|
|
29416
|
+
});
|
|
29263
29417
|
return;
|
|
29264
29418
|
}
|
|
29265
29419
|
if (!applied) {
|
|
@@ -29267,9 +29421,21 @@ function scheduleUnattendedAnswer(prompt, deps) {
|
|
|
29267
29421
|
deps.refund();
|
|
29268
29422
|
} catch {
|
|
29269
29423
|
}
|
|
29424
|
+
record2(mode, "skipped", {
|
|
29425
|
+
reason: "prompt already resolved \u2014 answered by a human, or the turn ended",
|
|
29426
|
+
behavior: answer.behavior,
|
|
29427
|
+
decision: answer.decision,
|
|
29428
|
+
spent
|
|
29429
|
+
});
|
|
29270
29430
|
return;
|
|
29271
29431
|
}
|
|
29272
29432
|
deps.log?.(`unattended (${mode}) answered ${prompt.kind}: ${answer.behavior}${cappedOut ? " (budget spent)" : ""} \u2014 ${answer.decision}`);
|
|
29433
|
+
record2(mode, "answered", {
|
|
29434
|
+
behavior: answer.behavior,
|
|
29435
|
+
decision: answer.decision,
|
|
29436
|
+
spent,
|
|
29437
|
+
...cappedOut ? { cappedOut } : {}
|
|
29438
|
+
});
|
|
29273
29439
|
try {
|
|
29274
29440
|
deps.report(answer, cappedOut);
|
|
29275
29441
|
} catch (err2) {
|
|
@@ -29283,6 +29449,7 @@ var init_unattended = __esm({
|
|
|
29283
29449
|
"../../packages/agent-core/dist/unattended.js"() {
|
|
29284
29450
|
"use strict";
|
|
29285
29451
|
init_dist();
|
|
29452
|
+
init_unattended_log();
|
|
29286
29453
|
UNATTENDED_ANSWER_DELAY_MS = 700;
|
|
29287
29454
|
UNATTENDED_MAX_DECISIONS = 100;
|
|
29288
29455
|
UNATTENDED_DECIDE_NOTE = "This is an unattended run \u2014 nobody is at the keyboard to answer, and no answer is coming. Choose the best option yourself, proceed, and briefly note which decision you made and why.";
|
|
@@ -29304,8 +29471,11 @@ var init_unattended = __esm({
|
|
|
29304
29471
|
var reinforced_verification_exports = {};
|
|
29305
29472
|
__export(reinforced_verification_exports, {
|
|
29306
29473
|
RV_CLEAN_STREAK_TO_STOP: () => RV_CLEAN_STREAK_TO_STOP,
|
|
29474
|
+
RV_HISTORY_MAX: () => RV_HISTORY_MAX,
|
|
29307
29475
|
RV_MAX_CYCLES: () => RV_MAX_CYCLES,
|
|
29308
29476
|
RV_MIN_REVIEWED_PCT: () => RV_MIN_REVIEWED_PCT,
|
|
29477
|
+
RV_PHASE_DIRECTIVE: () => RV_PHASE_DIRECTIVE,
|
|
29478
|
+
RV_PHASE_EVIDENCE_ASKS: () => RV_PHASE_EVIDENCE_ASKS,
|
|
29309
29479
|
VERDICT_JSON_SCHEMA: () => VERDICT_JSON_SCHEMA,
|
|
29310
29480
|
blockingIssues: () => blockingIssues,
|
|
29311
29481
|
completenessGrade: () => completenessGrade,
|
|
@@ -29313,13 +29483,15 @@ __export(reinforced_verification_exports, {
|
|
|
29313
29483
|
fixPrompt: () => fixPrompt,
|
|
29314
29484
|
newRvState: () => newRvState,
|
|
29315
29485
|
parseVerdict: () => parseVerdict,
|
|
29486
|
+
phaseGrade: () => phaseGrade,
|
|
29487
|
+
phaseReviewPrompt: () => phaseReviewPrompt,
|
|
29316
29488
|
reviewGrade: () => reviewGrade,
|
|
29317
29489
|
reviewPrompt: () => reviewPrompt,
|
|
29318
29490
|
rvAdvance: () => rvAdvance,
|
|
29319
29491
|
rvDecision: () => rvDecision
|
|
29320
29492
|
});
|
|
29321
29493
|
function newRvState(task) {
|
|
29322
|
-
return { cycles: 0, phase: "idle", cleanStreak: 0, ...task ? { task } : {} };
|
|
29494
|
+
return { cycles: 0, phase: "idle", cleanStreak: 0, phasesDone: 0, phaseAsks: 0, history: [], ...task ? { task } : {} };
|
|
29323
29495
|
}
|
|
29324
29496
|
function blockingIssues(v) {
|
|
29325
29497
|
return v.issues.filter((i) => i.severity === "critical" || i.severity === "major");
|
|
@@ -29339,20 +29511,43 @@ function rvDecision(verdict, state3) {
|
|
|
29339
29511
|
return { kind: "review", prompt: reviewPrompt(state3, verdict) };
|
|
29340
29512
|
return { kind: "done" };
|
|
29341
29513
|
}
|
|
29342
|
-
if (
|
|
29514
|
+
if (state3.phase === "phase-review") {
|
|
29515
|
+
if (blocking.length > 0)
|
|
29516
|
+
return { kind: "fix", prompt: fixPrompt(verdict, state3) };
|
|
29517
|
+
if (!verdict.exercised && state3.phaseAsks < RV_PHASE_EVIDENCE_ASKS) {
|
|
29518
|
+
return { kind: "phase-review", prompt: phaseReviewPrompt(state3, verdict) };
|
|
29519
|
+
}
|
|
29520
|
+
return verdict.taskComplete ? { kind: "review", prompt: reviewPrompt(state3) } : { kind: "continue", prompt: continuePrompt(verdict, state3) };
|
|
29521
|
+
}
|
|
29522
|
+
if (!verdict.taskComplete) {
|
|
29523
|
+
if (verdict.phaseComplete)
|
|
29524
|
+
return { kind: "phase-review", prompt: phaseReviewPrompt(state3, verdict) };
|
|
29343
29525
|
return { kind: "continue", prompt: continuePrompt(verdict, state3) };
|
|
29526
|
+
}
|
|
29344
29527
|
if (blocking.length > 0)
|
|
29345
29528
|
return { kind: "fix", prompt: fixPrompt(verdict, state3) };
|
|
29346
29529
|
return { kind: "review", prompt: reviewPrompt(state3) };
|
|
29347
29530
|
})();
|
|
29348
|
-
if (action.kind === "done" || action.kind === "review")
|
|
29531
|
+
if (action.kind === "done" || action.kind === "review" || action.kind === "phase-review")
|
|
29349
29532
|
return action;
|
|
29350
29533
|
return state3.cycles >= RV_MAX_CYCLES ? { kind: "capped" } : action;
|
|
29351
29534
|
}
|
|
29352
29535
|
function rvAdvance(state3, action, verdict) {
|
|
29353
29536
|
const clean2 = verdict.taskComplete && blockingIssues(verdict).length === 0;
|
|
29354
29537
|
const cleanStreak = state3.phase === "review" ? clean2 ? state3.cleanStreak + 1 : 0 : clean2 ? state3.cleanStreak : 0;
|
|
29355
|
-
const
|
|
29538
|
+
const gate = state3.phase === "review" ? "review" : state3.phase === "phase-review" ? "phase" : "completeness";
|
|
29539
|
+
const next = {
|
|
29540
|
+
...state3,
|
|
29541
|
+
lastVerdict: verdict,
|
|
29542
|
+
cleanStreak,
|
|
29543
|
+
history: [...state3.history, {
|
|
29544
|
+
gate,
|
|
29545
|
+
phaseName: verdict.phaseName,
|
|
29546
|
+
taskComplete: verdict.taskComplete,
|
|
29547
|
+
exercised: verdict.exercised,
|
|
29548
|
+
summary: verdict.summary.slice(0, 200)
|
|
29549
|
+
}].slice(-RV_HISTORY_MAX)
|
|
29550
|
+
};
|
|
29356
29551
|
switch (action.kind) {
|
|
29357
29552
|
// Sending the agent back to work is what the budget counts — a review pass is the
|
|
29358
29553
|
// loop doing its own job, not the agent being given another attempt.
|
|
@@ -29361,12 +29556,59 @@ function rvAdvance(state3, action, verdict) {
|
|
|
29361
29556
|
return { ...next, cycles: state3.cycles + 1, phase: "idle" };
|
|
29362
29557
|
case "review":
|
|
29363
29558
|
return { ...next, phase: "review" };
|
|
29559
|
+
// No cycle, for the same reason a review costs none: the loop asking for evidence is not
|
|
29560
|
+
// the agent being given another attempt. The budget still binds, because every `continue`
|
|
29561
|
+
// and `fix` between phases charges one.
|
|
29562
|
+
case "phase-review":
|
|
29563
|
+
return {
|
|
29564
|
+
...next,
|
|
29565
|
+
phase: "phase-review",
|
|
29566
|
+
// Counted on ENTRY to a checkpoint only. The evidence re-ask stays inside the same
|
|
29567
|
+
// checkpoint, and phaseGrade is explicitly asked to answer `phaseComplete` there too —
|
|
29568
|
+
// so counting it again scored one phase twice, and did it for the phase that had just
|
|
29569
|
+
// failed to produce any evidence at all.
|
|
29570
|
+
phasesDone: state3.phasesDone + (state3.phase !== "phase-review" && verdict.phaseComplete ? 1 : 0),
|
|
29571
|
+
// Entering a checkpoint resets the counter; re-asking within one increments it.
|
|
29572
|
+
phaseAsks: state3.phase === "phase-review" ? state3.phaseAsks + 1 : 0
|
|
29573
|
+
};
|
|
29364
29574
|
case "done":
|
|
29365
29575
|
return { ...next, phase: "done" };
|
|
29366
29576
|
case "capped":
|
|
29367
29577
|
return { ...next, phase: "capped" };
|
|
29368
29578
|
}
|
|
29369
29579
|
}
|
|
29580
|
+
function phaseReviewPrompt(state3, verdict) {
|
|
29581
|
+
const name = verdict?.phaseName?.trim();
|
|
29582
|
+
const notRun = verdict && verdict.exercised === false;
|
|
29583
|
+
return promptLines([
|
|
29584
|
+
"AUTOMATED PHASE CHECKPOINT \u2014 prove this phase before building on it.",
|
|
29585
|
+
"",
|
|
29586
|
+
state3.task ? `The request you are working on:
|
|
29587
|
+
${state3.task}` : void 0,
|
|
29588
|
+
"",
|
|
29589
|
+
name ? `The phase you just finished: ${name}` : "You have just finished a phase of the work.",
|
|
29590
|
+
"",
|
|
29591
|
+
notRun ? "Your last pass did not RUN anything. Reading the code again is not a checkpoint \u2014 run it." : void 0,
|
|
29592
|
+
notRun ? "" : void 0,
|
|
29593
|
+
"Do these, in this order:",
|
|
29594
|
+
"1. RUN it. Execute the tests that cover this phase, or the command/script/request that",
|
|
29595
|
+
" exercises it. Actually run them \u2014 do not describe what would happen.",
|
|
29596
|
+
"2. Paste the command you ran and its real output. If it failed, that is the finding.",
|
|
29597
|
+
"3. Check that what worked BEFORE this phase still works: run the wider test suite, or",
|
|
29598
|
+
" the parts of it this phase could plausibly have broken, and say which you ran.",
|
|
29599
|
+
"4. Only then read the phase's diff for defects the run would not surface.",
|
|
29600
|
+
"",
|
|
29601
|
+
"If this phase genuinely cannot be exercised on its own, say so and say WHY, in one line.",
|
|
29602
|
+
"Do not substitute a description of the code for evidence that it works.",
|
|
29603
|
+
"",
|
|
29604
|
+
SERIOUSNESS_BAR,
|
|
29605
|
+
"",
|
|
29606
|
+
"Report, briefly:",
|
|
29607
|
+
"- what you ran, and the outcome",
|
|
29608
|
+
'- anything serious you found (or "nothing serious")',
|
|
29609
|
+
"- whether the phase is sound enough to build the next one on top of"
|
|
29610
|
+
]);
|
|
29611
|
+
}
|
|
29370
29612
|
function continuePrompt(verdict, state3) {
|
|
29371
29613
|
const missing = verdict.unfinished.length > 0 ? verdict.unfinished.map((u) => `- ${u}`).join("\n") : "- (the request has not been fully delivered \u2014 re-read it and identify what is missing)";
|
|
29372
29614
|
const defects = blockingIssues(verdict);
|
|
@@ -29459,21 +29701,42 @@ ${verdict.unfinished.map((u) => `- ${u}`).join("\n")}` : void 0,
|
|
|
29459
29701
|
function issueLine(i) {
|
|
29460
29702
|
return `- [${i.severity}/${i.kind}] ${i.summary}${i.where ? ` (${i.where})` : ""} \u2014 ${i.impact}`;
|
|
29461
29703
|
}
|
|
29462
|
-
function
|
|
29463
|
-
const
|
|
29464
|
-
|
|
29465
|
-
|
|
29466
|
-
|
|
29704
|
+
function gradeContext(state3, todos) {
|
|
29705
|
+
const out = [
|
|
29706
|
+
"## What the user asked for",
|
|
29707
|
+
state3.task || "(not captured \u2014 judge from the account below)"
|
|
29708
|
+
];
|
|
29709
|
+
if (state3.plan) {
|
|
29710
|
+
out.push("", "## The plan the agent laid out at the start", state3.plan.slice(0, 4e3));
|
|
29711
|
+
}
|
|
29712
|
+
if (state3.history.length > 0) {
|
|
29713
|
+
out.push("", "## What has already been established, oldest first");
|
|
29714
|
+
for (const h of state3.history) {
|
|
29715
|
+
const bits = [
|
|
29716
|
+
`[${h.gate}]`,
|
|
29717
|
+
h.phaseName ? `phase "${h.phaseName}"` : null,
|
|
29718
|
+
h.taskComplete ? "request complete" : "request outstanding",
|
|
29719
|
+
h.gate === "phase" ? h.exercised ? "RAN it" : "did NOT run it" : null,
|
|
29720
|
+
h.summary || null
|
|
29721
|
+
].filter(Boolean);
|
|
29722
|
+
out.push(`- ${bits.join(" \xB7 ")}`);
|
|
29723
|
+
}
|
|
29724
|
+
out.push("", "Use this to judge PROGRESS. If the same claim keeps recurring with nothing", "new established, say so in `summary` and do not keep the run open on it.");
|
|
29725
|
+
}
|
|
29726
|
+
if (todos && todos.length > 0) {
|
|
29727
|
+
out.push("", "## The agent's own checklist at the end of the turn", ...todos.map((t) => `- [${t.status}] ${t.content}`));
|
|
29728
|
+
}
|
|
29729
|
+
return out.join("\n");
|
|
29730
|
+
}
|
|
29731
|
+
function completenessGrade(state3, finalText, todos) {
|
|
29467
29732
|
return {
|
|
29468
29733
|
system: GRADER_SYSTEM,
|
|
29469
29734
|
schema: VERDICT_JSON_SCHEMA,
|
|
29470
29735
|
prompt: [
|
|
29471
|
-
|
|
29472
|
-
task || "(not captured \u2014 judge completeness from the agent's own account below)",
|
|
29736
|
+
gradeContext(state3, todos),
|
|
29473
29737
|
"",
|
|
29474
29738
|
"## What the agent said when it stopped",
|
|
29475
29739
|
finalText.slice(0, 24e3) || "(the agent produced no closing message)",
|
|
29476
|
-
plan,
|
|
29477
29740
|
"",
|
|
29478
29741
|
"## Your task",
|
|
29479
29742
|
"Decide whether the user's request has actually been delivered. Set `taskComplete`",
|
|
@@ -29482,18 +29745,68 @@ ${todos.map((t) => `- [${t.status}] ${t.content}`).join("\n")}` : "";
|
|
|
29482
29745
|
"expected here unless the account admits to something broken. Fill the percentages from",
|
|
29483
29746
|
'what the account evidences; if it evidences nothing, use 0 and confidence "low".',
|
|
29484
29747
|
"",
|
|
29748
|
+
"## The phase checkpoint",
|
|
29749
|
+
"This run is verified AS IT IS BUILT. Separately from whether the whole request is",
|
|
29750
|
+
"done, decide whether the agent has just finished one testable PHASE of it \u2014 a slice",
|
|
29751
|
+
"that leaves the project working and can be exercised on its own.",
|
|
29752
|
+
"",
|
|
29753
|
+
"Set `phaseComplete` true only when BOTH hold:",
|
|
29754
|
+
'- the account describes a coherent slice as finished (not "started", not "in progress"), and',
|
|
29755
|
+
"- `taskComplete` is false \u2014 the whole request is still outstanding.",
|
|
29756
|
+
"A finished REQUEST is not a phase checkpoint; the ordinary completeness path handles it.",
|
|
29757
|
+
"Name that slice in `phaseName` (a few words, the agent's own framing), and put the",
|
|
29758
|
+
"number of phases it still expects in `phasesRemaining` (null if it has not said).",
|
|
29759
|
+
"",
|
|
29760
|
+
"Set `exercised` true only if the account shows the work was actually RUN \u2014 a command",
|
|
29761
|
+
'and its output, a test that executed, an observed result. "I reviewed it", "this should',
|
|
29762
|
+
'work", or a description of what the code does is NOT exercised. When in doubt, false.',
|
|
29763
|
+
"",
|
|
29485
29764
|
"Return ONLY this JSON:",
|
|
29486
29765
|
VERDICT_SCHEMA
|
|
29487
29766
|
].join("\n")
|
|
29488
29767
|
};
|
|
29489
29768
|
}
|
|
29490
|
-
function
|
|
29769
|
+
function phaseGrade(state3, phaseName, reportText, todos) {
|
|
29491
29770
|
return {
|
|
29492
29771
|
system: GRADER_SYSTEM,
|
|
29493
29772
|
schema: VERDICT_JSON_SCHEMA,
|
|
29494
29773
|
prompt: [
|
|
29495
|
-
|
|
29496
|
-
|
|
29774
|
+
gradeContext(state3, todos),
|
|
29775
|
+
"",
|
|
29776
|
+
phaseName ? `## The phase being checked
|
|
29777
|
+
${phaseName}` : "## The phase being checked\n(unnamed)",
|
|
29778
|
+
"",
|
|
29779
|
+
"## The agent's checkpoint report",
|
|
29780
|
+
reportText.slice(0, 24e3) || "(the agent produced no report)",
|
|
29781
|
+
"",
|
|
29782
|
+
"## Your task",
|
|
29783
|
+
"This was a CHECKPOINT: the agent was told to prove the phase by running it.",
|
|
29784
|
+
"",
|
|
29785
|
+
"`exercised` is the field that matters. Set it true ONLY if the report shows something",
|
|
29786
|
+
"was actually executed \u2014 a command with its real output, a test run with a result, an",
|
|
29787
|
+
'observed behaviour. A description of the code, a claim that it "should work", or a',
|
|
29788
|
+
"read-through of the diff is NOT exercised, however confident it sounds. A report that",
|
|
29789
|
+
"says the phase cannot be exercised on its own, and says why, is also not exercised \u2014",
|
|
29790
|
+
"but that is an honest answer, so do not manufacture issues over it.",
|
|
29791
|
+
"",
|
|
29792
|
+
"Record in `issues` only what the report shows is genuinely broken \u2014 a failing test, a",
|
|
29793
|
+
"command that errored, a regression it found. Do not invent findings from silence.",
|
|
29794
|
+
"",
|
|
29795
|
+
"Set `taskComplete` for the WHOLE request (usually false at a phase checkpoint), and",
|
|
29796
|
+
"`phaseComplete` true if this phase is now sound enough to build on.",
|
|
29797
|
+
"Fill `manuallyTestedPct` from what was actually run, not from what exists.",
|
|
29798
|
+
"",
|
|
29799
|
+
"Return ONLY this JSON:",
|
|
29800
|
+
VERDICT_SCHEMA
|
|
29801
|
+
].join("\n")
|
|
29802
|
+
};
|
|
29803
|
+
}
|
|
29804
|
+
function reviewGrade(state3, reviewText, todos) {
|
|
29805
|
+
return {
|
|
29806
|
+
system: GRADER_SYSTEM,
|
|
29807
|
+
schema: VERDICT_JSON_SCHEMA,
|
|
29808
|
+
prompt: [
|
|
29809
|
+
gradeContext(state3, todos),
|
|
29497
29810
|
"",
|
|
29498
29811
|
"## The agent's review of its own work",
|
|
29499
29812
|
reviewText.slice(0, 32e3) || "(the agent produced no review)",
|
|
@@ -29535,6 +29848,15 @@ function parseVerdict(raw) {
|
|
|
29535
29848
|
})).slice(0, 40);
|
|
29536
29849
|
return {
|
|
29537
29850
|
taskComplete: o.taskComplete === true,
|
|
29851
|
+
// All four default to the CONSERVATIVE reading. `phaseComplete: false` means "no
|
|
29852
|
+
// checkpoint yet", which costs nothing; a defaulted `true` would fire a phase review at
|
|
29853
|
+
// every turn end. `exercised: false` means "nothing was run", which sends the phase
|
|
29854
|
+
// review back once — the safe direction, because the opposite lets "tested" quietly
|
|
29855
|
+
// come to mean "read", which is the one thing this gate exists to prevent.
|
|
29856
|
+
phaseComplete: o.phaseComplete === true,
|
|
29857
|
+
phaseName: typeof o.phaseName === "string" ? o.phaseName.trim().slice(0, 120) : "",
|
|
29858
|
+
phasesRemaining: typeof o.phasesRemaining === "number" && Number.isFinite(o.phasesRemaining) ? Math.max(0, Math.min(99, Math.round(o.phasesRemaining))) : null,
|
|
29859
|
+
exercised: o.exercised === true,
|
|
29538
29860
|
confidence: o.confidence === "high" || o.confidence === "medium" ? o.confidence : "low",
|
|
29539
29861
|
unfinished: strList(o.unfinished),
|
|
29540
29862
|
issues,
|
|
@@ -29549,13 +29871,14 @@ function parseVerdict(raw) {
|
|
|
29549
29871
|
summary: typeof o.summary === "string" ? o.summary.trim().slice(0, 2e3) : ""
|
|
29550
29872
|
};
|
|
29551
29873
|
}
|
|
29552
|
-
var RV_MIN_REVIEWED_PCT, RV_CLEAN_STREAK_TO_STOP, SEVERITY_LIST, KIND_LIST, SEVERITIES, KINDS2, SERIOUSNESS_BAR, promptLines, VERDICT_SCHEMA, GRADER_SYSTEM, VERDICT_JSON_SCHEMA, NON_BLOCKING_WORDS, pct, tri, strList;
|
|
29874
|
+
var RV_MIN_REVIEWED_PCT, RV_PHASE_EVIDENCE_ASKS, RV_CLEAN_STREAK_TO_STOP, SEVERITY_LIST, KIND_LIST, SEVERITIES, KINDS2, RV_HISTORY_MAX, SERIOUSNESS_BAR, RV_PHASE_DIRECTIVE, promptLines, VERDICT_SCHEMA, GRADER_SYSTEM, VERDICT_JSON_SCHEMA, NON_BLOCKING_WORDS, pct, tri, strList;
|
|
29553
29875
|
var init_reinforced_verification = __esm({
|
|
29554
29876
|
"../../packages/agent-core/dist/reinforced-verification.js"() {
|
|
29555
29877
|
"use strict";
|
|
29556
29878
|
init_dist();
|
|
29557
29879
|
init_dist();
|
|
29558
29880
|
RV_MIN_REVIEWED_PCT = 90;
|
|
29881
|
+
RV_PHASE_EVIDENCE_ASKS = 1;
|
|
29559
29882
|
RV_CLEAN_STREAK_TO_STOP = 2;
|
|
29560
29883
|
SEVERITY_LIST = ["critical", "major", "minor"];
|
|
29561
29884
|
KIND_LIST = [
|
|
@@ -29570,6 +29893,7 @@ var init_reinforced_verification = __esm({
|
|
|
29570
29893
|
];
|
|
29571
29894
|
SEVERITIES = new Set(SEVERITY_LIST);
|
|
29572
29895
|
KINDS2 = new Set(KIND_LIST);
|
|
29896
|
+
RV_HISTORY_MAX = 12;
|
|
29573
29897
|
SERIOUSNESS_BAR = `Only these count as problems worth reporting:
|
|
29574
29898
|
- It breaks functionality that is supposed to work \u2014 now, or for a realistic input.
|
|
29575
29899
|
- It is a regression: something that worked before this run does not work now.
|
|
@@ -29584,9 +29908,26 @@ var init_reinforced_verification = __esm({
|
|
|
29584
29908
|
Explicitly DO NOT report, and do not spend time on: naming, formatting, comment wording,
|
|
29585
29909
|
documentation gaps, test style, micro-optimisation, hypothetical futures, "could be
|
|
29586
29910
|
cleaner", or anything you would not stop a release for. Reporting those wastes the run.`;
|
|
29911
|
+
RV_PHASE_DIRECTIVE = `This run is verified as you build it. Work in PHASES.
|
|
29912
|
+
|
|
29913
|
+
Before you start, split the request into the smallest sequence of phases where each one:
|
|
29914
|
+
- leaves the project in a WORKING state (it builds, and what worked before still works), and
|
|
29915
|
+
- can be EXERCISED on its own \u2014 a test you can run, a command with observable output, a
|
|
29916
|
+
script, a request against a running service. Not "read the diff and see that it is right".
|
|
29917
|
+
|
|
29918
|
+
Then build one phase at a time. When a phase is done, say so plainly \u2014 name the phase, and
|
|
29919
|
+
say how it can be exercised. Do not start the next phase in the same turn: finishing one is
|
|
29920
|
+
a checkpoint, and the checkpoint is where it gets proven.
|
|
29921
|
+
|
|
29922
|
+
If the request is genuinely a single small change, that is one phase. Do not invent phases to
|
|
29923
|
+
look thorough; a phase that cannot be run on its own is not a phase.`;
|
|
29587
29924
|
promptLines = (lines) => lines.filter((l) => l !== void 0).join("\n");
|
|
29588
29925
|
VERDICT_SCHEMA = `{
|
|
29589
29926
|
"taskComplete": boolean,
|
|
29927
|
+
"phaseComplete": boolean,
|
|
29928
|
+
"phaseName": string,
|
|
29929
|
+
"phasesRemaining": number | null,
|
|
29930
|
+
"exercised": boolean,
|
|
29590
29931
|
"confidence": "low" | "medium" | "high",
|
|
29591
29932
|
"unfinished": string[],
|
|
29592
29933
|
"issues": [{
|
|
@@ -29625,9 +29966,16 @@ Respond with ONLY a JSON object matching the schema. No prose, no markdown fence
|
|
|
29625
29966
|
VERDICT_JSON_SCHEMA = {
|
|
29626
29967
|
type: "object",
|
|
29627
29968
|
additionalProperties: false,
|
|
29628
|
-
required: ["taskComplete", "confidence", "unfinished", "issues", "reviewedPct", "testCoveragePct", "manuallyTestedPct", "buildsClean", "testsPass", "verdict", "summary"],
|
|
29969
|
+
required: ["taskComplete", "phaseComplete", "phaseName", "phasesRemaining", "exercised", "confidence", "unfinished", "issues", "reviewedPct", "testCoveragePct", "manuallyTestedPct", "buildsClean", "testsPass", "verdict", "summary"],
|
|
29629
29970
|
properties: {
|
|
29630
29971
|
taskComplete: { type: "boolean" },
|
|
29972
|
+
// REQUIRED, so the grader has to take a position on the checkpoint every time rather
|
|
29973
|
+
// than omitting it and leaving the loop to guess (an omitted field parses to `false`,
|
|
29974
|
+
// which is silently "no checkpoint" — fine as a failure mode, useless as a default).
|
|
29975
|
+
phaseComplete: { type: "boolean" },
|
|
29976
|
+
phaseName: { type: "string" },
|
|
29977
|
+
phasesRemaining: { type: ["integer", "null"] },
|
|
29978
|
+
exercised: { type: "boolean" },
|
|
29631
29979
|
confidence: { type: "string", enum: ["low", "medium", "high"] },
|
|
29632
29980
|
unfinished: { type: "array", items: { type: "string" } },
|
|
29633
29981
|
issues: {
|
|
@@ -29667,6 +30015,90 @@ Respond with ONLY a JSON object matching the schema. No prose, no markdown fence
|
|
|
29667
30015
|
}
|
|
29668
30016
|
});
|
|
29669
30017
|
|
|
30018
|
+
// ../../packages/agent-core/dist/context-recovery.js
|
|
30019
|
+
async function recoverFromContextOverflow(deps) {
|
|
30020
|
+
const mode = safe(deps.mode, "off");
|
|
30021
|
+
if (mode === "off")
|
|
30022
|
+
return false;
|
|
30023
|
+
const record2 = (action, attempt2, reason) => {
|
|
30024
|
+
recordUnattendedDecision({
|
|
30025
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
30026
|
+
source: "recovery",
|
|
30027
|
+
...deps.context?.sessionId ? { sessionId: deps.context.sessionId } : {},
|
|
30028
|
+
...deps.context?.engine ? { engine: deps.context.engine } : {},
|
|
30029
|
+
mode,
|
|
30030
|
+
kind: "context-overflow",
|
|
30031
|
+
action,
|
|
30032
|
+
attempt: attempt2,
|
|
30033
|
+
...reason ? { reason } : {}
|
|
30034
|
+
});
|
|
30035
|
+
};
|
|
30036
|
+
if (!safe(deps.canCompact, false)) {
|
|
30037
|
+
record2("gave-up", safe(deps.tries, 0), "this engine cannot be asked to compact");
|
|
30038
|
+
return false;
|
|
30039
|
+
}
|
|
30040
|
+
const attempt = safe(deps.tries, 0) + 1;
|
|
30041
|
+
if (attempt > OVERFLOW_MAX_TRIES) {
|
|
30042
|
+
record2("gave-up", attempt, `compaction did not reclaim enough after ${OVERFLOW_MAX_TRIES} attempts`);
|
|
30043
|
+
deps.log?.(`context overflow: giving up after ${OVERFLOW_MAX_TRIES} compaction attempts`);
|
|
30044
|
+
return false;
|
|
30045
|
+
}
|
|
30046
|
+
try {
|
|
30047
|
+
deps.bump();
|
|
30048
|
+
} catch {
|
|
30049
|
+
}
|
|
30050
|
+
try {
|
|
30051
|
+
await deps.compactAndResume();
|
|
30052
|
+
} catch (err2) {
|
|
30053
|
+
deps.log?.("context overflow: compact-and-resume failed", err2);
|
|
30054
|
+
record2("gave-up", attempt, `compact-and-resume failed: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
30055
|
+
return false;
|
|
30056
|
+
}
|
|
30057
|
+
record2("compact-and-resume", attempt);
|
|
30058
|
+
deps.log?.(`context overflow: compacting and resuming (attempt ${attempt}/${OVERFLOW_MAX_TRIES})`);
|
|
30059
|
+
return true;
|
|
30060
|
+
}
|
|
30061
|
+
function safe(fn, fallback) {
|
|
30062
|
+
try {
|
|
30063
|
+
return fn();
|
|
30064
|
+
} catch {
|
|
30065
|
+
return fallback;
|
|
30066
|
+
}
|
|
30067
|
+
}
|
|
30068
|
+
function autoCompactEnvFor(pct2, supplied) {
|
|
30069
|
+
if (supplied?.CLAUDE_AUTOCOMPACT_PCT_OVERRIDE)
|
|
30070
|
+
return {};
|
|
30071
|
+
if (typeof pct2 !== "number" || !Number.isFinite(pct2) || pct2 <= 0 || pct2 >= 100)
|
|
30072
|
+
return {};
|
|
30073
|
+
return { CLAUDE_AUTOCOMPACT_PCT_OVERRIDE: String(Math.round(pct2)) };
|
|
30074
|
+
}
|
|
30075
|
+
function shouldCompactProactively(a) {
|
|
30076
|
+
if (a.mode === "off")
|
|
30077
|
+
return "skip";
|
|
30078
|
+
if (a.inFlight)
|
|
30079
|
+
return "skip";
|
|
30080
|
+
if (typeof a.pct !== "number" || !Number.isFinite(a.pct) || a.pct <= 0 || a.pct >= 100)
|
|
30081
|
+
return "skip";
|
|
30082
|
+
if (typeof a.usagePct !== "number" || !Number.isFinite(a.usagePct))
|
|
30083
|
+
return "skip";
|
|
30084
|
+
if (a.usagePct < a.pct)
|
|
30085
|
+
return "reset";
|
|
30086
|
+
if (typeof a.lastCompactPct === "number" && a.usagePct < a.lastCompactPct + PROACTIVE_REGROWTH_POINTS)
|
|
30087
|
+
return "skip";
|
|
30088
|
+
return "compact";
|
|
30089
|
+
}
|
|
30090
|
+
var OVERFLOW_MAX_TRIES, OVERFLOW_COMPACT_MESSAGE, OVERFLOW_RESUME_MESSAGE, PROACTIVE_REGROWTH_POINTS;
|
|
30091
|
+
var init_context_recovery = __esm({
|
|
30092
|
+
"../../packages/agent-core/dist/context-recovery.js"() {
|
|
30093
|
+
"use strict";
|
|
30094
|
+
init_unattended_log();
|
|
30095
|
+
OVERFLOW_MAX_TRIES = 3;
|
|
30096
|
+
OVERFLOW_COMPACT_MESSAGE = "/compact";
|
|
30097
|
+
OVERFLOW_RESUME_MESSAGE = "Continue.";
|
|
30098
|
+
PROACTIVE_REGROWTH_POINTS = 5;
|
|
30099
|
+
}
|
|
30100
|
+
});
|
|
30101
|
+
|
|
29670
30102
|
// ../../packages/agent-core/dist/session-edit.js
|
|
29671
30103
|
function deleteTranscriptEntry(entries, uuid3, mode = "single") {
|
|
29672
30104
|
const target = entries.find((e) => e.uuid === uuid3);
|
|
@@ -29833,7 +30265,7 @@ var init_session_edit = __esm({
|
|
|
29833
30265
|
});
|
|
29834
30266
|
|
|
29835
30267
|
// ../../packages/agent-core/dist/session-mirror.js
|
|
29836
|
-
import { appendFileSync, existsSync as
|
|
30268
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync8, mkdirSync as mkdirSync10, readFileSync as readFileSync14, readdirSync, statSync as statSync6, unlinkSync as unlinkSync2 } from "node:fs";
|
|
29837
30269
|
import { join as join16 } from "node:path";
|
|
29838
30270
|
function sessionsRoot() {
|
|
29839
30271
|
return tessPath("sessions");
|
|
@@ -29861,8 +30293,8 @@ function loadSeen(file2) {
|
|
|
29861
30293
|
if (cached3)
|
|
29862
30294
|
return cached3;
|
|
29863
30295
|
const set2 = /* @__PURE__ */ new Set();
|
|
29864
|
-
if (
|
|
29865
|
-
for (const line of
|
|
30296
|
+
if (existsSync8(file2)) {
|
|
30297
|
+
for (const line of readFileSync14(file2, "utf8").split("\n")) {
|
|
29866
30298
|
if (!line.trim())
|
|
29867
30299
|
continue;
|
|
29868
30300
|
try {
|
|
@@ -29883,7 +30315,7 @@ function createLocalSessionStore(opts = {}) {
|
|
|
29883
30315
|
return;
|
|
29884
30316
|
const file2 = fileFor(key2);
|
|
29885
30317
|
try {
|
|
29886
|
-
|
|
30318
|
+
mkdirSync10(join16(file2, ".."), { recursive: true });
|
|
29887
30319
|
withLock(`session-store-${safeSegment(key2.projectKey)}-${safeSegment(key2.sessionId)}`, () => {
|
|
29888
30320
|
const seen = loadSeen(file2);
|
|
29889
30321
|
const lines = [];
|
|
@@ -29897,7 +30329,7 @@ function createLocalSessionStore(opts = {}) {
|
|
|
29897
30329
|
lines.push(JSON.stringify(e));
|
|
29898
30330
|
}
|
|
29899
30331
|
if (lines.length)
|
|
29900
|
-
|
|
30332
|
+
appendFileSync2(file2, `${lines.join("\n")}
|
|
29901
30333
|
`, { mode: 384 });
|
|
29902
30334
|
}, 5e3);
|
|
29903
30335
|
} catch (err2) {
|
|
@@ -29906,11 +30338,11 @@ function createLocalSessionStore(opts = {}) {
|
|
|
29906
30338
|
},
|
|
29907
30339
|
async load(key2) {
|
|
29908
30340
|
const file2 = fileFor(key2);
|
|
29909
|
-
if (!
|
|
30341
|
+
if (!existsSync8(file2))
|
|
29910
30342
|
return null;
|
|
29911
30343
|
try {
|
|
29912
30344
|
const out = [];
|
|
29913
|
-
for (const line of
|
|
30345
|
+
for (const line of readFileSync14(file2, "utf8").split("\n")) {
|
|
29914
30346
|
if (!line.trim())
|
|
29915
30347
|
continue;
|
|
29916
30348
|
try {
|
|
@@ -29926,7 +30358,7 @@ function createLocalSessionStore(opts = {}) {
|
|
|
29926
30358
|
},
|
|
29927
30359
|
async listSessions(projectKey) {
|
|
29928
30360
|
const dir2 = join16(sessionsRoot(), safeSegment(projectKey));
|
|
29929
|
-
if (!
|
|
30361
|
+
if (!existsSync8(dir2))
|
|
29930
30362
|
return [];
|
|
29931
30363
|
const out = [];
|
|
29932
30364
|
for (const name of readdirSync(dir2)) {
|
|
@@ -29936,7 +30368,7 @@ function createLocalSessionStore(opts = {}) {
|
|
|
29936
30368
|
if (base.includes("__"))
|
|
29937
30369
|
continue;
|
|
29938
30370
|
try {
|
|
29939
|
-
out.push({ sessionId: base, mtime: Math.floor(
|
|
30371
|
+
out.push({ sessionId: base, mtime: Math.floor(statSync6(join16(dir2, name)).mtimeMs) });
|
|
29940
30372
|
} catch {
|
|
29941
30373
|
}
|
|
29942
30374
|
}
|
|
@@ -29944,7 +30376,7 @@ function createLocalSessionStore(opts = {}) {
|
|
|
29944
30376
|
},
|
|
29945
30377
|
async listSubkeys(key2) {
|
|
29946
30378
|
const dir2 = join16(sessionsRoot(), safeSegment(key2.projectKey));
|
|
29947
|
-
if (!
|
|
30379
|
+
if (!existsSync8(dir2))
|
|
29948
30380
|
return [];
|
|
29949
30381
|
const prefix = `${safeSegment(key2.sessionId)}__`;
|
|
29950
30382
|
return readdirSync(dir2).filter((n) => n.startsWith(prefix) && n.endsWith(".jsonl")).map((n) => n.slice(prefix.length, -".jsonl".length));
|
|
@@ -29952,13 +30384,13 @@ function createLocalSessionStore(opts = {}) {
|
|
|
29952
30384
|
async delete(key2) {
|
|
29953
30385
|
const file2 = fileFor(key2);
|
|
29954
30386
|
try {
|
|
29955
|
-
if (
|
|
30387
|
+
if (existsSync8(file2))
|
|
29956
30388
|
unlinkSync2(file2);
|
|
29957
30389
|
seenUuids.delete(file2);
|
|
29958
30390
|
if (!key2.subpath) {
|
|
29959
30391
|
const dir2 = join16(sessionsRoot(), safeSegment(key2.projectKey));
|
|
29960
30392
|
const prefix = `${safeSegment(key2.sessionId)}__`;
|
|
29961
|
-
if (
|
|
30393
|
+
if (existsSync8(dir2)) {
|
|
29962
30394
|
for (const n of readdirSync(dir2)) {
|
|
29963
30395
|
if (n.startsWith(prefix) && n.endsWith(".jsonl")) {
|
|
29964
30396
|
try {
|
|
@@ -30835,8 +31267,8 @@ import { query, createSdkMcpServer, startup } from "@anthropic-ai/claude-agent-s
|
|
|
30835
31267
|
import { writeFile as writeFile4, mkdir as mkdir4, readFile as readFile6 } from "node:fs/promises";
|
|
30836
31268
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
30837
31269
|
import { tmpdir as tmpdir3, homedir as homedir4, userInfo } from "node:os";
|
|
30838
|
-
import { join as join18, dirname as
|
|
30839
|
-
import { existsSync as
|
|
31270
|
+
import { join as join18, dirname as dirname8 } from "node:path";
|
|
31271
|
+
import { existsSync as existsSync9, readFileSync as readFileSync15, readdirSync as readdirSync2, openSync as openSync4, readSync as readSync3, closeSync as closeSync4, statSync as statSync7, writeFileSync as writeFileSync10, mkdirSync as mkdirSync11, copyFileSync, renameSync as renameSync7 } from "node:fs";
|
|
30840
31272
|
import { fileURLToPath } from "node:url";
|
|
30841
31273
|
import { createRequire as createRequire2 } from "node:module";
|
|
30842
31274
|
import { createServer as createServer2 } from "node:net";
|
|
@@ -30860,11 +31292,11 @@ function findUserInstalledClaude(binName) {
|
|
|
30860
31292
|
"/usr/bin/" + binName
|
|
30861
31293
|
];
|
|
30862
31294
|
for (const p of abs)
|
|
30863
|
-
if (
|
|
31295
|
+
if (existsSync9(p))
|
|
30864
31296
|
return p;
|
|
30865
31297
|
try {
|
|
30866
31298
|
const out = execFileSync2(process.platform === "win32" ? "where" : "which", [binName], { encoding: "utf8" }).split("\n")[0]?.trim();
|
|
30867
|
-
if (out &&
|
|
31299
|
+
if (out && existsSync9(out))
|
|
30868
31300
|
return out;
|
|
30869
31301
|
} catch {
|
|
30870
31302
|
}
|
|
@@ -30889,8 +31321,8 @@ function resolveClaudeCodeExecutable() {
|
|
|
30889
31321
|
for (const key2 of keys) {
|
|
30890
31322
|
try {
|
|
30891
31323
|
const pkgJson = require2.resolve(`@anthropic-ai/claude-agent-sdk-${key2}/package.json`);
|
|
30892
|
-
const bin = join18(
|
|
30893
|
-
if (
|
|
31324
|
+
const bin = join18(dirname8(pkgJson), binName);
|
|
31325
|
+
if (existsSync9(bin))
|
|
30894
31326
|
return cachedClaudeExe = bin;
|
|
30895
31327
|
} catch {
|
|
30896
31328
|
}
|
|
@@ -30900,7 +31332,7 @@ function resolveClaudeCodeExecutable() {
|
|
|
30900
31332
|
const platKey = process.platform === "darwin" ? "mac" : process.platform === "win32" ? "win" : "linux";
|
|
30901
31333
|
for (const dir2 of [`${platKey}-${process.arch}`, platKey]) {
|
|
30902
31334
|
const bundled = join18(resourcesPath, "claude-cli", dir2, binName);
|
|
30903
|
-
if (
|
|
31335
|
+
if (existsSync9(bundled))
|
|
30904
31336
|
return cachedClaudeExe = bundled;
|
|
30905
31337
|
}
|
|
30906
31338
|
}
|
|
@@ -30927,7 +31359,7 @@ function engineCapsPath() {
|
|
|
30927
31359
|
function claudeBinaryStamp() {
|
|
30928
31360
|
try {
|
|
30929
31361
|
const path6 = resolveClaudeCodeExecutable();
|
|
30930
|
-
const st =
|
|
31362
|
+
const st = statSync7(path6);
|
|
30931
31363
|
return `${path6}:${st.size}:${Math.round(st.mtimeMs)}`;
|
|
30932
31364
|
} catch {
|
|
30933
31365
|
return null;
|
|
@@ -30941,7 +31373,7 @@ function loadEngineCaps() {
|
|
|
30941
31373
|
if (!stamp2)
|
|
30942
31374
|
return;
|
|
30943
31375
|
try {
|
|
30944
|
-
const store = JSON.parse(
|
|
31376
|
+
const store = JSON.parse(readFileSync15(engineCapsPath(), "utf8"));
|
|
30945
31377
|
const entry = store[stamp2];
|
|
30946
31378
|
if (entry && (entry.v ?? 1) !== CAPS_VERSION) {
|
|
30947
31379
|
log(`Engine caps: discarding a v${entry.v ?? 1} entry for this binary \u2014 its flags cannot be read under the current rules; they will be re-learned if they still apply.`);
|
|
@@ -30965,7 +31397,7 @@ function saveEngineCaps() {
|
|
|
30965
31397
|
try {
|
|
30966
31398
|
let store = {};
|
|
30967
31399
|
try {
|
|
30968
|
-
store = JSON.parse(
|
|
31400
|
+
store = JSON.parse(readFileSync15(engineCapsPath(), "utf8"));
|
|
30969
31401
|
} catch {
|
|
30970
31402
|
}
|
|
30971
31403
|
store[stamp2] = {
|
|
@@ -30973,7 +31405,7 @@ function saveEngineCaps() {
|
|
|
30973
31405
|
unsupported: [...unsupportedCliOptions],
|
|
30974
31406
|
rejectedArgs: Object.fromEntries([...rejectedCliArgs].map(([f, v]) => [f, [...v]]))
|
|
30975
31407
|
};
|
|
30976
|
-
|
|
31408
|
+
mkdirSync11(tessPath(), { recursive: true });
|
|
30977
31409
|
writeFileSync10(engineCapsPath(), JSON.stringify(store, null, 2), { mode: 384 });
|
|
30978
31410
|
} catch {
|
|
30979
31411
|
}
|
|
@@ -31106,13 +31538,13 @@ function findSessionCwd(sessionId, configDir) {
|
|
|
31106
31538
|
}
|
|
31107
31539
|
for (const slug2 of slugs) {
|
|
31108
31540
|
const file2 = join18(base, slug2, `${sessionId}.jsonl`);
|
|
31109
|
-
if (!
|
|
31541
|
+
if (!existsSync9(file2))
|
|
31110
31542
|
continue;
|
|
31111
31543
|
try {
|
|
31112
|
-
const fd =
|
|
31544
|
+
const fd = openSync4(file2, "r");
|
|
31113
31545
|
const buf = Buffer.alloc(65536);
|
|
31114
|
-
const n =
|
|
31115
|
-
|
|
31546
|
+
const n = readSync3(fd, buf, 0, buf.length, 0);
|
|
31547
|
+
closeSync4(fd);
|
|
31116
31548
|
for (const line of buf.toString("utf-8", 0, n).split("\n")) {
|
|
31117
31549
|
if (!line.trim())
|
|
31118
31550
|
continue;
|
|
@@ -31138,7 +31570,7 @@ function newestVersionManagerNode() {
|
|
|
31138
31570
|
join18(home, "Library", "pnpm", "node"),
|
|
31139
31571
|
join18(home, ".local", "bin", "node")
|
|
31140
31572
|
])
|
|
31141
|
-
if (
|
|
31573
|
+
if (existsSync9(p))
|
|
31142
31574
|
return p;
|
|
31143
31575
|
const roots = [
|
|
31144
31576
|
{ dir: join18(home, ".nvm", "versions", "node"), bin: (v) => join18(v, "bin", "node") },
|
|
@@ -31156,7 +31588,7 @@ function newestVersionManagerNode() {
|
|
|
31156
31588
|
}
|
|
31157
31589
|
for (const name of names) {
|
|
31158
31590
|
const path6 = bin(join18(dir2, name));
|
|
31159
|
-
if (!
|
|
31591
|
+
if (!existsSync9(path6))
|
|
31160
31592
|
continue;
|
|
31161
31593
|
const parts = name.replace(/^v/, "").split(".").map((n) => Number.parseInt(n, 10) || 0);
|
|
31162
31594
|
const ver = [parts[0] ?? 0, parts[1] ?? 0, parts[2] ?? 0];
|
|
@@ -31171,12 +31603,12 @@ function loginShellNode() {
|
|
|
31171
31603
|
if (process.platform === "win32")
|
|
31172
31604
|
return null;
|
|
31173
31605
|
const shell = process.env.SHELL || "/bin/zsh";
|
|
31174
|
-
if (!
|
|
31606
|
+
if (!existsSync9(shell))
|
|
31175
31607
|
return null;
|
|
31176
31608
|
try {
|
|
31177
31609
|
const out = execFileSync2(shell, ["-lic", `printf '<<NODE:%s>>' "$(command -v node 2>/dev/null)"`], { encoding: "utf8", timeout: 4e3, stdio: ["ignore", "pipe", "ignore"] });
|
|
31178
31610
|
const path6 = out.match(/<<NODE:(.*?)>>/)?.[1]?.trim();
|
|
31179
|
-
return path6 &&
|
|
31611
|
+
return path6 && existsSync9(path6) ? path6 : null;
|
|
31180
31612
|
} catch {
|
|
31181
31613
|
return null;
|
|
31182
31614
|
}
|
|
@@ -31187,12 +31619,12 @@ function resolveNodeExecutable() {
|
|
|
31187
31619
|
if (!process.versions.electron)
|
|
31188
31620
|
return cachedNodeExe2 = process.execPath;
|
|
31189
31621
|
for (const p of [process.env.CCB_NODE_PATH, "/opt/homebrew/bin/node", "/usr/local/bin/node", "/usr/bin/node"]) {
|
|
31190
|
-
if (p &&
|
|
31622
|
+
if (p && existsSync9(p))
|
|
31191
31623
|
return cachedNodeExe2 = p;
|
|
31192
31624
|
}
|
|
31193
31625
|
try {
|
|
31194
31626
|
const found = execSync2(process.platform === "win32" ? "where node" : "command -v node", { encoding: "utf8", timeout: 3e3 }).split(/\r?\n/)[0].trim();
|
|
31195
|
-
if (found &&
|
|
31627
|
+
if (found && existsSync9(found))
|
|
31196
31628
|
return cachedNodeExe2 = found;
|
|
31197
31629
|
} catch {
|
|
31198
31630
|
}
|
|
@@ -31626,11 +32058,11 @@ function buildMobileClause(dir2) {
|
|
|
31626
32058
|
try {
|
|
31627
32059
|
let fw = "";
|
|
31628
32060
|
let runCmd = "";
|
|
31629
|
-
if (
|
|
32061
|
+
if (existsSync9(join18(dir2, "pubspec.yaml"))) {
|
|
31630
32062
|
fw = "Flutter";
|
|
31631
32063
|
runCmd = "flutter run -d chrome";
|
|
31632
|
-
} else if (
|
|
31633
|
-
const pkg = JSON.parse(
|
|
32064
|
+
} else if (existsSync9(join18(dir2, "package.json"))) {
|
|
32065
|
+
const pkg = JSON.parse(readFileSync15(join18(dir2, "package.json"), "utf8"));
|
|
31634
32066
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
31635
32067
|
if (deps.expo) {
|
|
31636
32068
|
fw = "Expo";
|
|
@@ -31713,6 +32145,8 @@ var init_agent_manager = __esm({
|
|
|
31713
32145
|
init_plan_splitter();
|
|
31714
32146
|
init_unattended();
|
|
31715
32147
|
init_reinforced_verification();
|
|
32148
|
+
init_unattended_log();
|
|
32149
|
+
init_context_recovery();
|
|
31716
32150
|
init_dist();
|
|
31717
32151
|
init_dist();
|
|
31718
32152
|
init_base_paths();
|
|
@@ -31887,6 +32321,15 @@ var init_agent_manager = __esm({
|
|
|
31887
32321
|
* the host (setVerifierLlm); null ⇒ reinforced verification cannot grade, and says so
|
|
31888
32322
|
* rather than letting a run pass unverified. */
|
|
31889
32323
|
verifierLlm = null;
|
|
32324
|
+
/** The user's auto-compact threshold, read from the DAEMON's settings snapshot.
|
|
32325
|
+
*
|
|
32326
|
+
* Exists because the desktop-only route does not cover an unattended run. The threshold
|
|
32327
|
+
* normally reaches the CLI as `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE` inside `params.env`,
|
|
32328
|
+
* which the desktop main process fills in per send (`getAgentSettings`) — so a turn the
|
|
32329
|
+
* DAEMON originates (a cron fire, or anything sent while the app is closed) carried no
|
|
32330
|
+
* threshold at all and ran at the CLI's own default instead of the number the user set.
|
|
32331
|
+
* The other three engines already read this daemon-side at spawn; this is Claude's. */
|
|
32332
|
+
autoCompactPct = null;
|
|
31890
32333
|
/** Plugin-contributed Pre/PostToolUse hooks (Epic G). Appended (never replacing) the
|
|
31891
32334
|
* built-in edit-capture hooks at session start. */
|
|
31892
32335
|
pluginHooks = [];
|
|
@@ -32158,7 +32601,7 @@ var init_agent_manager = __esm({
|
|
|
32158
32601
|
constructor(rawSend2, onBrowserRequest) {
|
|
32159
32602
|
this.rawSend = rawSend2;
|
|
32160
32603
|
this.onBrowserRequest = onBrowserRequest;
|
|
32161
|
-
const __dirname =
|
|
32604
|
+
const __dirname = dirname8(fileURLToPath(import.meta.url));
|
|
32162
32605
|
this.browserCliPath = join18(__dirname, "browser-cli.js");
|
|
32163
32606
|
this.narrator = new Narrator((sessionId, text9, engineLabel) => this.send({ type: "agent:narration", sessionId, text: text9, ...engineLabel ? { engineLabel } : {} }, this.liveSessions.get(sessionId)?.origin));
|
|
32164
32607
|
}
|
|
@@ -32168,6 +32611,131 @@ var init_agent_manager = __esm({
|
|
|
32168
32611
|
setVerifierLlm(fn) {
|
|
32169
32612
|
this.verifierLlm = fn;
|
|
32170
32613
|
}
|
|
32614
|
+
/**
|
|
32615
|
+
* PROACTIVE compaction: keep an unattended run comfortably inside the window instead of
|
|
32616
|
+
* letting it walk into the wall.
|
|
32617
|
+
*
|
|
32618
|
+
* The renderer already does this at the user's threshold — but only for a conversation
|
|
32619
|
+
* it has on screen. Headless there was nothing, and the fallback everyone assumed
|
|
32620
|
+
* (`CLAUDE_AUTOCOMPACT_PCT_OVERRIDE`, which the desktop also sets) turns out to be inert:
|
|
32621
|
+
* measured against Claude Code 2.1.241, setting it to 25 left `autoCompactThreshold` at
|
|
32622
|
+
* the CLI's own 167000 and the context climbed straight past 25%, 33%, 42%, 52% without
|
|
32623
|
+
* compacting. So an unattended run honoured no threshold at all; its only protection was
|
|
32624
|
+
* the wall-hit recovery, which is a last resort, not a setting.
|
|
32625
|
+
*
|
|
32626
|
+
* Only when NOBODY IS WATCHING. With a client attached the renderer owns this, and both
|
|
32627
|
+
* doing it would spend two turns on one reclaim.
|
|
32628
|
+
*/
|
|
32629
|
+
async maybeCompactProactively(live) {
|
|
32630
|
+
const pct2 = (() => {
|
|
32631
|
+
try {
|
|
32632
|
+
return this.autoCompactPct?.();
|
|
32633
|
+
} catch {
|
|
32634
|
+
return void 0;
|
|
32635
|
+
}
|
|
32636
|
+
})();
|
|
32637
|
+
const usage2 = await this.getContextUsage(live.sessionId).catch(() => null);
|
|
32638
|
+
const verdict = shouldCompactProactively({
|
|
32639
|
+
mode: live.unattended ?? "off",
|
|
32640
|
+
pct: pct2,
|
|
32641
|
+
usagePct: typeof usage2?.percentage === "number" ? usage2.percentage : null,
|
|
32642
|
+
lastCompactPct: live.proactiveCompactedAt ?? null,
|
|
32643
|
+
inFlight: live.overflowCompacting === true
|
|
32644
|
+
});
|
|
32645
|
+
if (verdict === "reset") {
|
|
32646
|
+
live.proactiveCompactedAt = void 0;
|
|
32647
|
+
return;
|
|
32648
|
+
}
|
|
32649
|
+
if (verdict !== "compact")
|
|
32650
|
+
return;
|
|
32651
|
+
live.proactiveCompactedAt = usage2?.percentage ?? 0;
|
|
32652
|
+
live.overflowCompacting = true;
|
|
32653
|
+
try {
|
|
32654
|
+
log(`auto-compact: ${Math.round(usage2?.percentage ?? 0)}% of the window used (threshold ${String(pct2)}%) \u2014 compacting`);
|
|
32655
|
+
await this.sendMessage({
|
|
32656
|
+
message: OVERFLOW_COMPACT_MESSAGE,
|
|
32657
|
+
url: "",
|
|
32658
|
+
sessionId: live.sessionId,
|
|
32659
|
+
projectDir: live.cwd,
|
|
32660
|
+
origin: live.origin,
|
|
32661
|
+
browserId: live.browserId,
|
|
32662
|
+
windowId: live.windowId,
|
|
32663
|
+
autoContinuation: true,
|
|
32664
|
+
...live.unattended === "auto" ? { unattended: true } : {},
|
|
32665
|
+
...live.model ? { model: live.model } : {}
|
|
32666
|
+
});
|
|
32667
|
+
} catch (err2) {
|
|
32668
|
+
log("auto-compact failed:", err2 instanceof Error ? err2.message : String(err2));
|
|
32669
|
+
} finally {
|
|
32670
|
+
live.overflowCompacting = false;
|
|
32671
|
+
}
|
|
32672
|
+
}
|
|
32673
|
+
/**
|
|
32674
|
+
* Compact and resume after this session outgrew the window, when nobody is watching.
|
|
32675
|
+
*
|
|
32676
|
+
* Returns true when the recovery was dispatched, in which case the caller must NOT report
|
|
32677
|
+
* the turn as finished — the run continues on a reclaimed window.
|
|
32678
|
+
*
|
|
32679
|
+
* The two sends mirror the renderer's `continueLastTurn(id, 'context_window')` exactly,
|
|
32680
|
+
* because they have to agree: `/compact` alone just compacts and stops, and the resume
|
|
32681
|
+
* alone overflows again. Both ride `autoContinuation`, which is what tells the rest of
|
|
32682
|
+
* the manager this is the SAME run — without it the verification loop would re-anchor on
|
|
32683
|
+
* the literal request "Continue.", which the very next turn satisfies by construction.
|
|
32684
|
+
*/
|
|
32685
|
+
async recoverContextOverflow(live, turnSid) {
|
|
32686
|
+
return recoverFromContextOverflow({
|
|
32687
|
+
mode: () => live.unattended ?? "off",
|
|
32688
|
+
// Claude takes `/compact` as a real slash command.
|
|
32689
|
+
canCompact: () => true,
|
|
32690
|
+
tries: () => live.overflowTries ?? 0,
|
|
32691
|
+
bump: () => {
|
|
32692
|
+
live.overflowTries = (live.overflowTries ?? 0) + 1;
|
|
32693
|
+
},
|
|
32694
|
+
context: { sessionId: turnSid, engine: "claude-code" },
|
|
32695
|
+
log: (m, err2) => log(m, err2 instanceof Error ? err2.message : err2 !== void 0 ? String(err2) : ""),
|
|
32696
|
+
compactAndResume: async () => {
|
|
32697
|
+
const base = {
|
|
32698
|
+
url: "",
|
|
32699
|
+
sessionId: live.sessionId,
|
|
32700
|
+
projectDir: live.cwd,
|
|
32701
|
+
origin: live.origin,
|
|
32702
|
+
browserId: live.browserId,
|
|
32703
|
+
windowId: live.windowId,
|
|
32704
|
+
autoContinuation: true,
|
|
32705
|
+
...live.unattended === "auto" ? { unattended: true } : {},
|
|
32706
|
+
...live.model ? { model: live.model } : {}
|
|
32707
|
+
};
|
|
32708
|
+
live.overflowCompacting = true;
|
|
32709
|
+
try {
|
|
32710
|
+
await this.sendMessage({ ...base, message: OVERFLOW_COMPACT_MESSAGE });
|
|
32711
|
+
} finally {
|
|
32712
|
+
live.overflowCompacting = false;
|
|
32713
|
+
}
|
|
32714
|
+
await this.sendMessage({ ...base, message: OVERFLOW_RESUME_MESSAGE });
|
|
32715
|
+
}
|
|
32716
|
+
});
|
|
32717
|
+
}
|
|
32718
|
+
/** Inject the daemon's view of the auto-compact threshold. Read at SPAWN, never
|
|
32719
|
+
* captured, so flipping the slider at 23:00 reaches a session started at 03:00. */
|
|
32720
|
+
setAutoCompactPct(fn) {
|
|
32721
|
+
this.autoCompactPct = fn;
|
|
32722
|
+
}
|
|
32723
|
+
/**
|
|
32724
|
+
* `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE` for a spawn the desktop did not configure.
|
|
32725
|
+
*
|
|
32726
|
+
* Empty whenever the caller already supplied one (the desktop's per-send env wins), when
|
|
32727
|
+
* no provider is wired, or when the number is not a usable percentage — 0 and 100 both
|
|
32728
|
+
* mean "no proactive compaction", and writing either would turn the CLI's own default
|
|
32729
|
+
* OFF rather than leaving it alone. Never throws: a settings read that fails must not
|
|
32730
|
+
* take the spawn with it.
|
|
32731
|
+
*/
|
|
32732
|
+
daemonCompactEnv(supplied) {
|
|
32733
|
+
try {
|
|
32734
|
+
return autoCompactEnvFor(this.autoCompactPct?.(), supplied);
|
|
32735
|
+
} catch {
|
|
32736
|
+
return {};
|
|
32737
|
+
}
|
|
32738
|
+
}
|
|
32171
32739
|
setNarrationLlm(cfg2) {
|
|
32172
32740
|
this.narrator.setConfig(cfg2);
|
|
32173
32741
|
this.cheapLlm = cfg2?.complete ?? null;
|
|
@@ -32353,7 +32921,7 @@ ${full.slice(-8e3)}`;
|
|
|
32353
32921
|
if (live.rvGrading === rv)
|
|
32354
32922
|
return;
|
|
32355
32923
|
live.rvGrading = rv;
|
|
32356
|
-
const gate = rv.phase === "review" ? "review" : "completeness";
|
|
32924
|
+
const gate = rv.phase === "review" ? "review" : rv.phase === "phase-review" ? "phase" : "completeness";
|
|
32357
32925
|
let owned = rv;
|
|
32358
32926
|
const evtSessionId = live.sessionId;
|
|
32359
32927
|
const evtCrid = live.clientRequestId;
|
|
@@ -32366,7 +32934,7 @@ ${full.slice(-8e3)}`;
|
|
|
32366
32934
|
this.send(evt, evtOrigin);
|
|
32367
32935
|
};
|
|
32368
32936
|
try {
|
|
32369
|
-
if (!didWork && gate
|
|
32937
|
+
if (!didWork && gate === "completeness") {
|
|
32370
32938
|
emitVerification({ action: "done", gate, cycle: rv.cycles, maxCycles: RV_MAX_CYCLES, unavailable: "This turn used no tools, so there was nothing to verify." });
|
|
32371
32939
|
return;
|
|
32372
32940
|
}
|
|
@@ -32377,7 +32945,7 @@ ${full.slice(-8e3)}`;
|
|
|
32377
32945
|
return;
|
|
32378
32946
|
}
|
|
32379
32947
|
const todos = live.todos?.map((t) => ({ content: t.content, status: String(t.status) }));
|
|
32380
|
-
const call3 = gate === "review" ? reviewGrade(rv.
|
|
32948
|
+
const call3 = gate === "review" ? reviewGrade(rv, finalText, todos) : gate === "phase" ? phaseGrade(rv, rv.lastVerdict?.phaseName ?? "", finalText, todos) : completenessGrade(rv, finalText, todos);
|
|
32381
32949
|
const raw = await llm({ model: live.model, system: call3.system, prompt: call3.prompt, maxTokens: 16e3, schema: call3.schema });
|
|
32382
32950
|
if (live.rv !== rv || live.reaped) {
|
|
32383
32951
|
if (live.reaped || live.rv === void 0) {
|
|
@@ -32391,14 +32959,31 @@ ${full.slice(-8e3)}`;
|
|
|
32391
32959
|
live.rv = { ...rv, phase: "done" };
|
|
32392
32960
|
return;
|
|
32393
32961
|
}
|
|
32962
|
+
if (!rv.plan && finalText.trim())
|
|
32963
|
+
rv.plan = finalText.slice(0, 4e3);
|
|
32394
32964
|
const action = rvDecision(verdict, rv);
|
|
32395
32965
|
const nextState = rvAdvance(rv, action, verdict);
|
|
32396
32966
|
live.rv = nextState;
|
|
32397
32967
|
owned = nextState;
|
|
32398
32968
|
emitVerification({ action: action.kind, gate, cycle: nextState.cycles, maxCycles: RV_MAX_CYCLES, verdict });
|
|
32399
32969
|
log(`reinforced-verification: ${gate} \u2192 ${action.kind} (cycle ${nextState.cycles}/${RV_MAX_CYCLES}, ${verdict.issues.length} issue(s), complete=${verdict.taskComplete})`);
|
|
32970
|
+
recordVerificationDecision({
|
|
32971
|
+
sessionId: live.sessionId,
|
|
32972
|
+
engine: "claude-code",
|
|
32973
|
+
gate,
|
|
32974
|
+
action: action.kind,
|
|
32975
|
+
cycle: nextState.cycles,
|
|
32976
|
+
phasesDone: nextState.phasesDone,
|
|
32977
|
+
phaseName: verdict.phaseName,
|
|
32978
|
+
taskComplete: verdict.taskComplete,
|
|
32979
|
+
phaseComplete: verdict.phaseComplete,
|
|
32980
|
+
exercised: verdict.exercised,
|
|
32981
|
+
blocking: blockingIssues(verdict).length,
|
|
32982
|
+
summary: verdict.summary
|
|
32983
|
+
});
|
|
32400
32984
|
if (action.kind === "done" || action.kind === "capped")
|
|
32401
32985
|
return;
|
|
32986
|
+
await this.maybeCompactProactively(live);
|
|
32402
32987
|
await this.sendMessage({
|
|
32403
32988
|
message: action.prompt,
|
|
32404
32989
|
url: "",
|
|
@@ -32476,6 +33061,7 @@ ${full.slice(-8e3)}`;
|
|
|
32476
33061
|
* Abandoning it is a hang — the precise failure this whole path exists to prevent. */
|
|
32477
33062
|
autoAnswerPrompt(live, requestId, prompt, apply2) {
|
|
32478
33063
|
scheduleUnattendedAnswer(prompt, {
|
|
33064
|
+
context: { sessionId: live.sessionId, engine: "claude-code" },
|
|
32479
33065
|
mode: () => live.unattended ?? "off",
|
|
32480
33066
|
charge: () => live.autoDecisions = (live.autoDecisions ?? 0) + 1,
|
|
32481
33067
|
// Relative, not absolute — siblings can be mid-window; see the deps doc.
|
|
@@ -32890,7 +33476,7 @@ ${qText}`;
|
|
|
32890
33476
|
if (!file2)
|
|
32891
33477
|
return { ok: false, reason: "This conversation has no transcript on this machine." };
|
|
32892
33478
|
try {
|
|
32893
|
-
const before = parseTranscript(
|
|
33479
|
+
const before = parseTranscript(readFileSync15(file2, "utf8"));
|
|
32894
33480
|
const want = typeof locator === "string" ? { uuid: locator } : locator;
|
|
32895
33481
|
const uuid3 = want.uuid ?? (want.text ? findUserEntryByText(before, want.text)?.uuid : void 0);
|
|
32896
33482
|
if (!uuid3) {
|
|
@@ -32905,7 +33491,7 @@ ${qText}`;
|
|
|
32905
33491
|
}
|
|
32906
33492
|
const tmp = `${file2}.tmp-${randomUUID6().slice(0, 8)}`;
|
|
32907
33493
|
writeFileSync10(tmp, serializeTranscript(res.entries), { mode: 384 });
|
|
32908
|
-
|
|
33494
|
+
renameSync7(tmp, file2);
|
|
32909
33495
|
log(`Removed ${res.removed.length} transcript entr${res.removed.length === 1 ? "y" : "ies"} from ${sessionId}; re-parented ${res.relinked.length}.`);
|
|
32910
33496
|
if (live) {
|
|
32911
33497
|
try {
|
|
@@ -33300,12 +33886,12 @@ ${qText}`;
|
|
|
33300
33886
|
const cli = `ELECTRON_RUN_AS_NODE=1 "${process.execPath}" "${this.browserCliPath}"`;
|
|
33301
33887
|
const pageInfo = url2 ? `
|
|
33302
33888
|
The user's current browser tab is: ${url2}` : "";
|
|
33303
|
-
const designClause = this.projectDir &&
|
|
33889
|
+
const designClause = this.projectDir && existsSync9(join18(this.projectDir, TOKENS_FILE)) ? `
|
|
33304
33890
|
|
|
33305
33891
|
DESIGN SYSTEM:
|
|
33306
33892
|
- This project has a design system at design-system/tokens.json. For any UI you build or edit, use those tokens (colors, spacing, typography, radius) \u2014 call read_design_tokens to read values, set them with write_design_token, and NEVER hardcode hex/sizes that duplicate a token.` : "";
|
|
33307
33893
|
const mobileClause = this.projectDir ? buildMobileClause(this.projectDir) : "";
|
|
33308
|
-
const buildClause = this.projectDir &&
|
|
33894
|
+
const buildClause = this.projectDir && existsSync9(join18(this.projectDir, ".tesseract", "brief.md")) ? `
|
|
33309
33895
|
|
|
33310
33896
|
WEBSITE BUILD MODE:
|
|
33311
33897
|
This is a guided website build. Read \`.tesseract/brief.md\` (the user's brief), \`design-system/reference.html\` (the chosen template \u2014 the visual/structural spec) and \`design-system/tokens.json\` (the theme). Protocol:
|
|
@@ -33359,8 +33945,8 @@ CRITICAL RULES:
|
|
|
33359
33945
|
const match = f.dataUrl.match(/^data:[^;]*;base64,(.+)$/);
|
|
33360
33946
|
if (!match)
|
|
33361
33947
|
continue;
|
|
33362
|
-
const
|
|
33363
|
-
const filePath = join18(fileDir, `${process.pid}-${Date.now()}-${randomUUID6().slice(0, 8)}-${i}-${
|
|
33948
|
+
const safe2 = (f.name || `file-${i}`).replace(/[^\w.\-]+/g, "_").slice(-100);
|
|
33949
|
+
const filePath = join18(fileDir, `${process.pid}-${Date.now()}-${randomUUID6().slice(0, 8)}-${i}-${safe2}`);
|
|
33364
33950
|
await writeFile4(filePath, Buffer.from(match[1], "base64"));
|
|
33365
33951
|
paths.push(filePath);
|
|
33366
33952
|
}
|
|
@@ -33518,7 +34104,7 @@ CRITICAL RULES:
|
|
|
33518
34104
|
let pinnedSource;
|
|
33519
34105
|
if (params.sessionId) {
|
|
33520
34106
|
const originCwd = findSessionCwd(params.sessionId, params.engineEnv?.CLAUDE_CONFIG_DIR ?? params.env?.CLAUDE_CONFIG_DIR);
|
|
33521
|
-
if (originCwd && originCwd !== openProject &&
|
|
34107
|
+
if (originCwd && originCwd !== openProject && existsSync9(originCwd)) {
|
|
33522
34108
|
log(`Resuming ${params.sessionId} in its ORIGINAL cwd ${originCwd} (open project ${openProject} added as a source)`);
|
|
33523
34109
|
cwd = originCwd;
|
|
33524
34110
|
pinnedSource = openProject;
|
|
@@ -34166,9 +34752,18 @@ CRITICAL RULES:
|
|
|
34166
34752
|
...identityEnv(),
|
|
34167
34753
|
...options.env,
|
|
34168
34754
|
// params.env carries CLAUDE_AUTOCOMPACT_PCT_OVERRIDE from the user's setting
|
|
34169
|
-
// (getAgentSettings)
|
|
34170
|
-
// at the
|
|
34755
|
+
// (getAgentSettings). MEASURED INERT on Claude Code 2.1.241: set to 25, the
|
|
34756
|
+
// reported `autoCompactThreshold` stayed at the CLI's own 167000 and the
|
|
34757
|
+
// conversation climbed past 25%, 33%, 42%, 52% without compacting once. Kept
|
|
34758
|
+
// because it costs nothing and other CLI versions may honour it — but nothing
|
|
34759
|
+
// depends on it: `maybeCompactProactively` is what actually holds an unattended
|
|
34760
|
+
// run to the user's threshold.
|
|
34171
34761
|
...params.env ?? {},
|
|
34762
|
+
// FALLBACK, not an override: `params.env` wins whenever the desktop supplied a
|
|
34763
|
+
// threshold. This fills the gap for a turn the daemon originated itself, which
|
|
34764
|
+
// carries no env — without it an unattended run compacts at the CLI's default
|
|
34765
|
+
// rather than the number in the run-mode menu.
|
|
34766
|
+
...this.daemonCompactEnv(params.env),
|
|
34172
34767
|
...params.engineEnv ?? {},
|
|
34173
34768
|
CCB_IPC_PORT: String(live.ipcPort)
|
|
34174
34769
|
};
|
|
@@ -34208,9 +34803,16 @@ CRITICAL RULES:
|
|
|
34208
34803
|
// restores the SDK's dynamic command list, gitStatus/date context,
|
|
34209
34804
|
// env-info and memory/CLAUDE.md preamble that a bare custom string
|
|
34210
34805
|
// prompt suppresses — while `append` keeps the Tesseract browser tools.
|
|
34806
|
+
// The phase directive rides here when verification is armed. It has to be in the
|
|
34807
|
+
// SYSTEM prompt, not prepended to the user's message: the loop only speaks at turn
|
|
34808
|
+
// END, so without this the agent has already built the whole thing monolithically by
|
|
34809
|
+
// the time anything can ask it to work in slices — and rewriting the user's message
|
|
34810
|
+
// is the mistake that made `/compact` the graded task.
|
|
34211
34811
|
systemPrompt: { type: "preset", preset: "claude_code", append: this.applyPromptHook(this.buildSystemPrompt(params.url) + (params.appendSystemPrompt ? `
|
|
34212
34812
|
|
|
34213
|
-
${params.appendSystemPrompt}` : "")
|
|
34813
|
+
${params.appendSystemPrompt}` : "") + (params.reinforcedVerification ? `
|
|
34814
|
+
|
|
34815
|
+
${RV_PHASE_DIRECTIVE}` : ""), live.sessionId) },
|
|
34214
34816
|
includePartialMessages: true,
|
|
34215
34817
|
// Emit a predicted follow-up prompt after each turn (git/context-aware) — rendered
|
|
34216
34818
|
// as a clickable suggestion chip. Off by default in the SDK, so opt in here.
|
|
@@ -34566,9 +35168,13 @@ ${params.appendSystemPrompt}` : ""), live.sessionId) },
|
|
|
34566
35168
|
});
|
|
34567
35169
|
}
|
|
34568
35170
|
const limitRejection = live.usageLimitRejection ?? (r.subtype === "success" ? assistantUsageLimitFallback(live.lastAssistantContent) : void 0);
|
|
35171
|
+
const resultText = typeof r.result === "string" ? r.result : "";
|
|
35172
|
+
const textOverflow = r.is_error === true && isContextOverflow(resultText);
|
|
34569
35173
|
if (limitRejection) {
|
|
34570
35174
|
reportUsageLimit(limitRejection, turnSid);
|
|
34571
|
-
} else if (r.subtype === "success") {
|
|
35175
|
+
} else if (r.subtype === "success" && !textOverflow) {
|
|
35176
|
+
if (!live.overflowCompacting)
|
|
35177
|
+
live.overflowTries = 0;
|
|
34572
35178
|
if (!turnStreamed && Array.isArray(live.lastAssistantContent)) {
|
|
34573
35179
|
for (const blk of live.lastAssistantContent) {
|
|
34574
35180
|
if (blk?.type === "thinking" && typeof blk.thinking === "string" && blk.thinking) {
|
|
@@ -34605,6 +35211,8 @@ ${params.appendSystemPrompt}` : ""), live.sessionId) },
|
|
|
34605
35211
|
const didWork = typeof r.num_turns !== "number" || r.num_turns > 1;
|
|
34606
35212
|
if (live.rv && !continuable)
|
|
34607
35213
|
void this.runVerification(live, typeof r.result === "string" ? r.result : "", didWork);
|
|
35214
|
+
else
|
|
35215
|
+
void this.maybeCompactProactively(live);
|
|
34608
35216
|
} else if (live.interrupted) {
|
|
34609
35217
|
live.interrupted = false;
|
|
34610
35218
|
this.clearStopWatchdog(live);
|
|
@@ -34613,13 +35221,16 @@ ${params.appendSystemPrompt}` : ""), live.sessionId) },
|
|
|
34613
35221
|
emit2({ type: "agent:status", sessionId: turnSid, status: "idle" });
|
|
34614
35222
|
} else {
|
|
34615
35223
|
const errors = Array.isArray(r.errors) ? r.errors.map(String).filter(Boolean) : [];
|
|
34616
|
-
const detail = errors.length > 0 ? errors.join("\n") : `Agent returned ${r.subtype}${r.stop_reason ? ` (stop_reason: ${r.stop_reason})` : ""}`;
|
|
34617
|
-
const contextHit = r.subtype === "error_max_turns" ? "max_turns" : String(r.subtype).includes("context") || r.stop_reason === "model_context_window_exceeded" ? "context_window" : void 0;
|
|
35224
|
+
const detail = textOverflow ? resultText : errors.length > 0 ? errors.join("\n") : `Agent returned ${r.subtype}${r.stop_reason ? ` (stop_reason: ${r.stop_reason})` : ""}`;
|
|
35225
|
+
const contextHit = r.subtype === "error_max_turns" ? "max_turns" : textOverflow || String(r.subtype).includes("context") || r.stop_reason === "model_context_window_exceeded" ? "context_window" : void 0;
|
|
34618
35226
|
const looksTransient = !contextHit && /overloaded|\b429\b|\b529\b|rate.?limit|too many requests|throttl|\b50[0234]\b|service unavailable|bad gateway|gateway timeout|timed? ?out|ETIMEDOUT|ECONNRESET|ECONNREFUSED|EPIPE|ENOTFOUND|ENETUNREACH|EAI_AGAIN|socket hang up|network error|temporarily unavailable/i.test(detail);
|
|
34619
35227
|
log("Session result error:", turnSid, JSON.stringify({ subtype: r.subtype, stop_reason: r.stop_reason, errors, looksTransient }));
|
|
34620
35228
|
live.resultErrorReported = true;
|
|
34621
|
-
|
|
34622
|
-
|
|
35229
|
+
const recovered = contextHit === "context_window" && await this.recoverContextOverflow(live, turnSid);
|
|
35230
|
+
if (!recovered) {
|
|
35231
|
+
emit2({ type: "chat:error", sessionId: turnSid, error: detail, ...contextHit ? { continuable: true, continueReason: contextHit } : looksTransient ? { transient: true } : {} });
|
|
35232
|
+
emit2({ type: "agent:status", sessionId: turnSid, status: contextHit ? "idle" : "error" });
|
|
35233
|
+
}
|
|
34623
35234
|
}
|
|
34624
35235
|
blockAcc.clear();
|
|
34625
35236
|
insideXmlByKey.clear();
|
|
@@ -35678,8 +36289,12 @@ __export(dist_exports2, {
|
|
|
35678
36289
|
DesignTokensSchema: () => DesignTokensSchema,
|
|
35679
36290
|
DtcgTokensSchema: () => DtcgTokensSchema,
|
|
35680
36291
|
HookBus: () => HookBus,
|
|
36292
|
+
OVERFLOW_COMPACT_MESSAGE: () => OVERFLOW_COMPACT_MESSAGE,
|
|
36293
|
+
OVERFLOW_MAX_TRIES: () => OVERFLOW_MAX_TRIES,
|
|
36294
|
+
OVERFLOW_RESUME_MESSAGE: () => OVERFLOW_RESUME_MESSAGE,
|
|
35681
36295
|
PRESENT_TOOL_NAMES: () => PRESENT_TOOL_NAMES,
|
|
35682
36296
|
PRESENT_TOOL_SPECS: () => PRESENT_TOOL_SPECS,
|
|
36297
|
+
PROACTIVE_REGROWTH_POINTS: () => PROACTIVE_REGROWTH_POINTS,
|
|
35683
36298
|
SCREEN_CONTROL_SPECS: () => SCREEN_CONTROL_SPECS,
|
|
35684
36299
|
SessionStore: () => SessionStore,
|
|
35685
36300
|
TOKENS_CSS_FILE: () => TOKENS_CSS_FILE,
|
|
@@ -35691,6 +36306,7 @@ __export(dist_exports2, {
|
|
|
35691
36306
|
appendImageArtifact: () => appendImageArtifact,
|
|
35692
36307
|
appendSurfaceArtifact: () => appendSurfaceArtifact,
|
|
35693
36308
|
applyDesignPack: () => applyDesignPack,
|
|
36309
|
+
autoCompactEnvFor: () => autoCompactEnvFor,
|
|
35694
36310
|
buildAppControlTools: () => buildAppControlTools,
|
|
35695
36311
|
buildClaudeNarrationLlm: () => buildClaudeNarrationLlm,
|
|
35696
36312
|
buildClaudeSmartLlm: () => buildClaudeSmartLlm,
|
|
@@ -35724,6 +36340,9 @@ __export(dist_exports2, {
|
|
|
35724
36340
|
normalizeTokens: () => normalizeTokens,
|
|
35725
36341
|
parseColorToRgb: () => parseColorToRgb,
|
|
35726
36342
|
readSessionArtifacts: () => readSessionArtifacts,
|
|
36343
|
+
readUnattendedDecisions: () => readUnattendedDecisions,
|
|
36344
|
+
recordUnattendedDecision: () => recordUnattendedDecision,
|
|
36345
|
+
recoverFromContextOverflow: () => recoverFromContextOverflow,
|
|
35727
36346
|
renderAppControlReference: () => renderAppControlReference,
|
|
35728
36347
|
resolveNodeExecutable: () => resolveNodeExecutable,
|
|
35729
36348
|
resolveOauthToken: () => resolveOauthToken,
|
|
@@ -35737,6 +36356,8 @@ __export(dist_exports2, {
|
|
|
35737
36356
|
setBrowserExtensionProbe: () => setBrowserExtensionProbe,
|
|
35738
36357
|
setTokenPath: () => setTokenPath,
|
|
35739
36358
|
setTokenSegments: () => setTokenSegments,
|
|
36359
|
+
setUnattendedLogSink: () => setUnattendedLogSink,
|
|
36360
|
+
shouldCompactProactively: () => shouldCompactProactively,
|
|
35740
36361
|
specParametersJsonSchema: () => specParametersJsonSchema,
|
|
35741
36362
|
stringifyValue: () => stringifyValue,
|
|
35742
36363
|
stripPromptPrefix: () => stripPromptPrefix,
|
|
@@ -35747,6 +36368,7 @@ __export(dist_exports2, {
|
|
|
35747
36368
|
toolSpecJsonSchema: () => specParametersJsonSchema,
|
|
35748
36369
|
transferSession: () => transferSession,
|
|
35749
36370
|
unattendedAnswer: () => unattendedAnswer,
|
|
36371
|
+
unattendedLogPath: () => unattendedLogPath,
|
|
35750
36372
|
unattendedModeFor: () => unattendedModeFor,
|
|
35751
36373
|
walkTokens: () => walkTokens,
|
|
35752
36374
|
wrapCtxTool: () => wrapCtxTool,
|
|
@@ -35759,6 +36381,8 @@ var init_dist5 = __esm({
|
|
|
35759
36381
|
init_session_store();
|
|
35760
36382
|
init_session_usage();
|
|
35761
36383
|
init_unattended();
|
|
36384
|
+
init_unattended_log();
|
|
36385
|
+
init_context_recovery();
|
|
35762
36386
|
init_session_transfer();
|
|
35763
36387
|
init_log();
|
|
35764
36388
|
init_kill_tree();
|
|
@@ -35789,7 +36413,7 @@ __export(tesseract_mcp_endpoint_exports, {
|
|
|
35789
36413
|
startTesseractMcpEndpoint: () => startTesseractMcpEndpoint
|
|
35790
36414
|
});
|
|
35791
36415
|
import { createServer as createServer3 } from "node:http";
|
|
35792
|
-
import { readFileSync as
|
|
36416
|
+
import { readFileSync as readFileSync16, writeFileSync as writeFileSync11 } from "node:fs";
|
|
35793
36417
|
import { join as join20 } from "node:path";
|
|
35794
36418
|
function readBody2(req, limitBytes = 4 * 1024 * 1024) {
|
|
35795
36419
|
return new Promise((resolve16, reject) => {
|
|
@@ -35818,7 +36442,7 @@ function portFile() {
|
|
|
35818
36442
|
}
|
|
35819
36443
|
function rememberedPort() {
|
|
35820
36444
|
try {
|
|
35821
|
-
const o = JSON.parse(
|
|
36445
|
+
const o = JSON.parse(readFileSync16(portFile(), "utf8"));
|
|
35822
36446
|
return typeof o.port === "number" && o.port > 1024 ? o.port : 0;
|
|
35823
36447
|
} catch {
|
|
35824
36448
|
return 0;
|
|
@@ -35959,7 +36583,7 @@ __export(serpapi_runner_exports, {
|
|
|
35959
36583
|
createDaemonSerpClient: () => createDaemonSerpClient,
|
|
35960
36584
|
resolveSerpCreds: () => resolveSerpCreds
|
|
35961
36585
|
});
|
|
35962
|
-
import { existsSync as
|
|
36586
|
+
import { existsSync as existsSync10, readFileSync as readFileSync17 } from "node:fs";
|
|
35963
36587
|
function resolveSerpCreds() {
|
|
35964
36588
|
const snap = readDaemonAgentSettings().serp;
|
|
35965
36589
|
if (snap?.apiKey?.trim()) {
|
|
@@ -35974,8 +36598,8 @@ function resolveSerpCreds() {
|
|
|
35974
36598
|
};
|
|
35975
36599
|
}
|
|
35976
36600
|
const file2 = daemonPath("serpapi.key");
|
|
35977
|
-
if (
|
|
35978
|
-
const k =
|
|
36601
|
+
if (existsSync10(file2)) {
|
|
36602
|
+
const k = readFileSync17(file2, "utf-8").trim();
|
|
35979
36603
|
if (k)
|
|
35980
36604
|
return { apiKey: k, tier: "own", source: "key-file" };
|
|
35981
36605
|
}
|
|
@@ -62997,8 +63621,8 @@ var require_selfsigned = __commonJS({
|
|
|
62997
63621
|
// ../../packages/host-core/dist/peer-link/tls-direct.js
|
|
62998
63622
|
import tls from "node:tls";
|
|
62999
63623
|
import { X509Certificate, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
|
|
63000
|
-
import { readFileSync as
|
|
63001
|
-
import { dirname as
|
|
63624
|
+
import { readFileSync as readFileSync33, writeFileSync as writeFileSync22, existsSync as existsSync20, mkdirSync as mkdirSync23 } from "node:fs";
|
|
63625
|
+
import { dirname as dirname18 } from "node:path";
|
|
63002
63626
|
function fingerprintOf(certPem) {
|
|
63003
63627
|
return new X509Certificate(certPem).fingerprint256;
|
|
63004
63628
|
}
|
|
@@ -63010,15 +63634,15 @@ function fingerprintsEqual(a, b) {
|
|
|
63010
63634
|
return ba.length === bb.length && timingSafeEqual2(ba, bb);
|
|
63011
63635
|
}
|
|
63012
63636
|
async function loadOrCreateIdentity(certPath, keyPath) {
|
|
63013
|
-
if (
|
|
63014
|
-
const cert =
|
|
63015
|
-
const key2 =
|
|
63637
|
+
if (existsSync20(certPath) && existsSync20(keyPath)) {
|
|
63638
|
+
const cert = readFileSync33(certPath, "utf8");
|
|
63639
|
+
const key2 = readFileSync33(keyPath, "utf8");
|
|
63016
63640
|
return { cert, key: key2, fingerprint256: fingerprintOf(cert) };
|
|
63017
63641
|
}
|
|
63018
63642
|
const tenYears = new Date(Date.now() + 10 * 365 * 24 * 60 * 60 * 1e3);
|
|
63019
63643
|
const pems = await (0, import_selfsigned.generate)([{ name: "commonName", value: "tesseract-peer" }], { keySize: 2048, notAfterDate: tenYears, algorithm: "sha256" });
|
|
63020
63644
|
try {
|
|
63021
|
-
|
|
63645
|
+
mkdirSync23(dirname18(certPath), { recursive: true });
|
|
63022
63646
|
} catch {
|
|
63023
63647
|
}
|
|
63024
63648
|
try {
|
|
@@ -70813,7 +71437,7 @@ var mesh_ca_exports = {};
|
|
|
70813
71437
|
__export(mesh_ca_exports, {
|
|
70814
71438
|
netCaCommand: () => netCaCommand
|
|
70815
71439
|
});
|
|
70816
|
-
import { chmodSync as chmodSync8, existsSync as
|
|
71440
|
+
import { chmodSync as chmodSync8, existsSync as existsSync42, mkdirSync as mkdirSync42, readFileSync as readFileSync48, writeFileSync as writeFileSync42 } from "node:fs";
|
|
70817
71441
|
import { join as join76, resolve as resolve13 } from "node:path";
|
|
70818
71442
|
import { createInterface } from "node:readline";
|
|
70819
71443
|
function die(msg) {
|
|
@@ -70852,7 +71476,7 @@ function writeSecretFile(p, bytes2) {
|
|
|
70852
71476
|
}
|
|
70853
71477
|
}
|
|
70854
71478
|
function ensureDir(p) {
|
|
70855
|
-
|
|
71479
|
+
mkdirSync42(p, { recursive: true, mode: 448 });
|
|
70856
71480
|
try {
|
|
70857
71481
|
chmodSync8(p, 448);
|
|
70858
71482
|
} catch {
|
|
@@ -70861,12 +71485,12 @@ function ensureDir(p) {
|
|
|
70861
71485
|
async function openCa(dir2) {
|
|
70862
71486
|
const gPath = join76(dir2, "genesis.bin");
|
|
70863
71487
|
const sPath = join76(dir2, "ca.sealed");
|
|
70864
|
-
if (!
|
|
71488
|
+
if (!existsSync42(gPath) || !existsSync42(sPath)) {
|
|
70865
71489
|
die(`No mesh CA in ${dir2}. Run: tesseract-agent net init --org NAME --ca-dir ${dir2}`);
|
|
70866
71490
|
}
|
|
70867
|
-
const genesisBytes = new Uint8Array(
|
|
71491
|
+
const genesisBytes = new Uint8Array(readFileSync48(gPath));
|
|
70868
71492
|
const genesis = decodeGenesis(genesisBytes);
|
|
70869
|
-
const sealed = decodeRecoveryBundle(new Uint8Array(
|
|
71493
|
+
const sealed = decodeRecoveryBundle(new Uint8Array(readFileSync48(sPath)));
|
|
70870
71494
|
const pass = await readPassphrase("CA passphrase: ");
|
|
70871
71495
|
let seed;
|
|
70872
71496
|
try {
|
|
@@ -70882,7 +71506,7 @@ async function netCaCommand(rest, flags) {
|
|
|
70882
71506
|
if (sub === "init") {
|
|
70883
71507
|
const org = typeof flags.org === "string" ? flags.org.trim() : "";
|
|
70884
71508
|
if (!org) die("Usage: tesseract-agent net init --org NAME [--ca-dir DIR]");
|
|
70885
|
-
if (
|
|
71509
|
+
if (existsSync42(join76(caDir, "ca.sealed"))) {
|
|
70886
71510
|
die(`A mesh CA already exists in ${caDir}. Refusing to overwrite it.`);
|
|
70887
71511
|
}
|
|
70888
71512
|
const pass = await readPassphrase("New CA passphrase: ");
|
|
@@ -71040,12 +71664,12 @@ var init_mesh_ca = __esm({
|
|
|
71040
71664
|
|
|
71041
71665
|
// src/cli.ts
|
|
71042
71666
|
init_base_paths();
|
|
71043
|
-
import { existsSync as
|
|
71667
|
+
import { existsSync as existsSync43, mkdtempSync as mkdtempSync2, readFileSync as readFileSync50, rmSync as rmSync11 } from "node:fs";
|
|
71044
71668
|
import { createHash as createHash8 } from "node:crypto";
|
|
71045
71669
|
import { execFileSync as execFileSync6, spawn as spawn16 } from "node:child_process";
|
|
71046
71670
|
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
71047
71671
|
import { tmpdir as tmpdir6 } from "node:os";
|
|
71048
|
-
import { dirname as
|
|
71672
|
+
import { dirname as dirname32, join as join77, resolve as resolve15 } from "node:path";
|
|
71049
71673
|
import { createInterface as createInterface2 } from "node:readline/promises";
|
|
71050
71674
|
|
|
71051
71675
|
// ../../packages/host-core/dist/control-link.js
|
|
@@ -71075,7 +71699,7 @@ function toRewindOutcome(res, noHistory) {
|
|
|
71075
71699
|
// ../../packages/host-core/dist/control-link.js
|
|
71076
71700
|
import { join as join53, basename as basename11 } from "node:path";
|
|
71077
71701
|
import { randomUUID as randomUUID22 } from "node:crypto";
|
|
71078
|
-
import { mkdirSync as
|
|
71702
|
+
import { mkdirSync as mkdirSync27 } from "node:fs";
|
|
71079
71703
|
|
|
71080
71704
|
// ../../node_modules/ws/wrapper.mjs
|
|
71081
71705
|
var import_stream = __toESM(require_stream(), 1);
|
|
@@ -72384,6 +73008,7 @@ async function createClaudeCodeBackend(send4, onBrowserRequest, loadPluginRuntim
|
|
|
72384
73008
|
send4(msg, origin);
|
|
72385
73009
|
};
|
|
72386
73010
|
const manager2 = new AgentManager2(sendWatchingSessions, onBrowserRequest);
|
|
73011
|
+
manager2.setAutoCompactPct(() => readDaemonAgentSettings().autoCompactPct);
|
|
72387
73012
|
const claudeSnapshots = createSnapshotStore(join19(daemonDir(), "engine-snapshots", "claude-code.json"));
|
|
72388
73013
|
const claudeTurnSeq = /* @__PURE__ */ new Map();
|
|
72389
73014
|
const pendingAlias = /* @__PURE__ */ new Map();
|
|
@@ -73162,7 +73787,7 @@ function geminiMessageText(m) {
|
|
|
73162
73787
|
}
|
|
73163
73788
|
|
|
73164
73789
|
// ../../packages/host-core/dist/engines/hosted-verification.js
|
|
73165
|
-
function createHostedVerification() {
|
|
73790
|
+
function createHostedVerification(engineId) {
|
|
73166
73791
|
let verifier = null;
|
|
73167
73792
|
return {
|
|
73168
73793
|
setVerifier: (fn) => {
|
|
@@ -73171,6 +73796,7 @@ function createHostedVerification() {
|
|
|
73171
73796
|
canGrade: () => verifier !== null,
|
|
73172
73797
|
async run({ sessionId, task, finalText, todos, reprompt, emit: emit2, model, clientRequestId, cancelled }) {
|
|
73173
73798
|
const rv = await Promise.resolve().then(() => (init_reinforced_verification(), reinforced_verification_exports));
|
|
73799
|
+
const ulog = await Promise.resolve().then(() => (init_unattended_log(), unattended_log_exports));
|
|
73174
73800
|
const base = { type: "agent:verification", sessionId, ...clientRequestId ? { clientRequestId } : {}, maxCycles: rv.RV_MAX_CYCLES };
|
|
73175
73801
|
const standDown = (cycle, unavailable) => {
|
|
73176
73802
|
emit2({ ...base, action: "done", gate: "completeness", cycle, unavailable });
|
|
@@ -73189,11 +73815,14 @@ function createHostedVerification() {
|
|
|
73189
73815
|
}
|
|
73190
73816
|
const grade = verifier;
|
|
73191
73817
|
let state3 = rv.newRvState(task);
|
|
73818
|
+
if (finalText.trim())
|
|
73819
|
+
state3 = { ...state3, plan: finalText.slice(0, 4e3) };
|
|
73192
73820
|
let text9 = finalText;
|
|
73193
73821
|
let reviewText = "";
|
|
73194
|
-
|
|
73195
|
-
|
|
73196
|
-
const
|
|
73822
|
+
let phaseText = "";
|
|
73823
|
+
for (let i = 0; i < rv.RV_MAX_CYCLES * 5 + 4; i++) {
|
|
73824
|
+
const gate = state3.phase === "review" ? "review" : state3.phase === "phase-review" ? "phase" : "completeness";
|
|
73825
|
+
const call3 = gate === "review" ? rv.reviewGrade(state3, reviewText || text9, todos) : gate === "phase" ? rv.phaseGrade(state3, state3.lastVerdict?.phaseName ?? "", phaseText || text9, todos) : rv.completenessGrade(state3, text9, todos);
|
|
73197
73826
|
let verdict = null;
|
|
73198
73827
|
try {
|
|
73199
73828
|
verdict = rv.parseVerdict(await grade({ model, system: call3.system, prompt: call3.prompt, maxTokens: 16e3, schema: call3.schema }));
|
|
@@ -73214,6 +73843,20 @@ function createHostedVerification() {
|
|
|
73214
73843
|
const action = rv.rvDecision(verdict, state3);
|
|
73215
73844
|
state3 = rv.rvAdvance(state3, action, verdict);
|
|
73216
73845
|
emit2({ ...base, action: action.kind, gate, cycle: state3.cycles, verdict });
|
|
73846
|
+
ulog.recordVerificationDecision({
|
|
73847
|
+
sessionId,
|
|
73848
|
+
...engineId ? { engine: engineId } : {},
|
|
73849
|
+
gate,
|
|
73850
|
+
action: action.kind,
|
|
73851
|
+
cycle: state3.cycles,
|
|
73852
|
+
phasesDone: state3.phasesDone,
|
|
73853
|
+
phaseName: verdict.phaseName,
|
|
73854
|
+
taskComplete: verdict.taskComplete,
|
|
73855
|
+
phaseComplete: verdict.phaseComplete,
|
|
73856
|
+
exercised: verdict.exercised,
|
|
73857
|
+
blocking: rv.blockingIssues(verdict).length,
|
|
73858
|
+
summary: verdict.summary
|
|
73859
|
+
});
|
|
73217
73860
|
if (action.kind === "done" || action.kind === "capped")
|
|
73218
73861
|
return text9;
|
|
73219
73862
|
try {
|
|
@@ -73224,15 +73867,18 @@ function createHostedVerification() {
|
|
|
73224
73867
|
return text9;
|
|
73225
73868
|
}
|
|
73226
73869
|
}
|
|
73227
|
-
const before = action.kind === "review" ? reviewText : text9;
|
|
73870
|
+
const before = action.kind === "review" ? reviewText : action.kind === "phase-review" ? phaseText : text9;
|
|
73228
73871
|
const reply3 = await reprompt(action.prompt);
|
|
73229
73872
|
if (!reply3 || reply3 === before) {
|
|
73230
73873
|
standDown(state3.cycles, "The agent did not produce anything new when sent back, so this run was not verified.");
|
|
73231
73874
|
return text9;
|
|
73232
73875
|
}
|
|
73233
|
-
if (action.kind
|
|
73876
|
+
if (action.kind === "review")
|
|
73877
|
+
reviewText = reply3;
|
|
73878
|
+
else if (action.kind === "phase-review")
|
|
73879
|
+
phaseText = reply3;
|
|
73880
|
+
else
|
|
73234
73881
|
text9 = reply3;
|
|
73235
|
-
reviewText = action.kind === "review" ? reply3 : reviewText;
|
|
73236
73882
|
} catch {
|
|
73237
73883
|
standDown(state3.cycles, "Verification could not be completed, so this run was not verified.");
|
|
73238
73884
|
return text9;
|
|
@@ -73246,7 +73892,7 @@ function createHostedVerification() {
|
|
|
73246
73892
|
|
|
73247
73893
|
// ../../packages/host-core/dist/engines/model-pricing.js
|
|
73248
73894
|
init_credentials();
|
|
73249
|
-
import { readFileSync as
|
|
73895
|
+
import { readFileSync as readFileSync18, writeFileSync as writeFileSync12 } from "node:fs";
|
|
73250
73896
|
import { join as join22 } from "node:path";
|
|
73251
73897
|
var LITELLM_URL = "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json";
|
|
73252
73898
|
var MODELS_DEV_URL = "https://models.dev/api.json";
|
|
@@ -73278,7 +73924,7 @@ var Source = class {
|
|
|
73278
73924
|
if (this.data || this.pinned)
|
|
73279
73925
|
return;
|
|
73280
73926
|
try {
|
|
73281
|
-
const o = JSON.parse(
|
|
73927
|
+
const o = JSON.parse(readFileSync18(this.path, "utf8"));
|
|
73282
73928
|
if (o.map && this.sane(o.map)) {
|
|
73283
73929
|
this.data = o.map;
|
|
73284
73930
|
this.fetchedAt = o.fetchedAt ?? 0;
|
|
@@ -73577,7 +74223,7 @@ var AcpTransport = class {
|
|
|
73577
74223
|
import { spawn as spawn5 } from "node:child_process";
|
|
73578
74224
|
import { mkdir as mkdir5, readFile as readFile8, writeFile as writeFile6 } from "node:fs/promises";
|
|
73579
74225
|
import { realpathSync as realpathSync3 } from "node:fs";
|
|
73580
|
-
import { basename as basename3, dirname as
|
|
74226
|
+
import { basename as basename3, dirname as dirname9, isAbsolute as isAbsolute4, resolve as resolve6, sep as sep4 } from "node:path";
|
|
73581
74227
|
var DEFAULT_OUTPUT_BYTE_LIMIT = 1024 * 1024;
|
|
73582
74228
|
var MAX_OUTPUT_BYTE_LIMIT = 8 * 1024 * 1024;
|
|
73583
74229
|
var MAX_TERMINALS = 16;
|
|
@@ -73597,7 +74243,7 @@ function realpathDeep(abs) {
|
|
|
73597
74243
|
return tail3.length ? resolve6(real, ...tail3) : real;
|
|
73598
74244
|
} catch {
|
|
73599
74245
|
}
|
|
73600
|
-
const parent =
|
|
74246
|
+
const parent = dirname9(head);
|
|
73601
74247
|
if (parent === head)
|
|
73602
74248
|
return abs;
|
|
73603
74249
|
tail3.unshift(basename3(head));
|
|
@@ -73665,7 +74311,7 @@ function installWorkspaceHandlers(t, opts) {
|
|
|
73665
74311
|
if (!target)
|
|
73666
74312
|
return null;
|
|
73667
74313
|
const content = p.content ?? "";
|
|
73668
|
-
await mkdir5(
|
|
74314
|
+
await mkdir5(dirname9(target), { recursive: true }).catch(() => {
|
|
73669
74315
|
});
|
|
73670
74316
|
await writeFile6(target, content, "utf8").catch(() => {
|
|
73671
74317
|
});
|
|
@@ -73784,9 +74430,9 @@ function installWorkspaceHandlers(t, opts) {
|
|
|
73784
74430
|
}
|
|
73785
74431
|
|
|
73786
74432
|
// ../../packages/host-core/dist/engines/mcp-injection.js
|
|
73787
|
-
import { copyFileSync as copyFileSync2, existsSync as
|
|
74433
|
+
import { copyFileSync as copyFileSync2, existsSync as existsSync11, mkdirSync as mkdirSync12, readFileSync as readFileSync19, readdirSync as readdirSync3, symlinkSync as symlinkSync2, writeFileSync as writeFileSync13 } from "node:fs";
|
|
73788
74434
|
import { homedir as homedir6 } from "node:os";
|
|
73789
|
-
import { dirname as
|
|
74435
|
+
import { dirname as dirname10, join as join23, resolve as resolve7 } from "node:path";
|
|
73790
74436
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
73791
74437
|
var BUNDLED_MCP_SERVERS = [
|
|
73792
74438
|
{ name: "tesseract-serp", basename: "serpapi-mcp.js", envOverride: "CCB_SERPAPI_MCP_JS" }
|
|
@@ -73804,7 +74450,7 @@ function resolveBundledMcpBin(basename14, envOverride) {
|
|
|
73804
74450
|
if (rp)
|
|
73805
74451
|
candidates.push(join23(rp, "host-daemon", basename14));
|
|
73806
74452
|
try {
|
|
73807
|
-
const here =
|
|
74453
|
+
const here = dirname10(fileURLToPath2(import.meta.url));
|
|
73808
74454
|
candidates.push(join23(here, basename14));
|
|
73809
74455
|
candidates.push(resolve7(here, "../../../../apps/host-daemon/dist-bundle", basename14));
|
|
73810
74456
|
candidates.push(resolve7(here, "../../../../apps/host-daemon/dist", basename14));
|
|
@@ -73812,7 +74458,7 @@ function resolveBundledMcpBin(basename14, envOverride) {
|
|
|
73812
74458
|
} catch {
|
|
73813
74459
|
}
|
|
73814
74460
|
for (const c of candidates) {
|
|
73815
|
-
if (
|
|
74461
|
+
if (existsSync11(c)) {
|
|
73816
74462
|
resolvedBins.set(basename14, c);
|
|
73817
74463
|
return c;
|
|
73818
74464
|
}
|
|
@@ -73874,7 +74520,7 @@ function specToSettingsServer(spec) {
|
|
|
73874
74520
|
}
|
|
73875
74521
|
function readJson(path6) {
|
|
73876
74522
|
try {
|
|
73877
|
-
return JSON.parse(
|
|
74523
|
+
return JSON.parse(readFileSync19(path6, "utf8"));
|
|
73878
74524
|
} catch {
|
|
73879
74525
|
return {};
|
|
73880
74526
|
}
|
|
@@ -73883,9 +74529,9 @@ function writeManagedMcpHome(engineId, layout, servers, projectDir, baseDir, use
|
|
|
73883
74529
|
try {
|
|
73884
74530
|
const home = join23(baseDir, "engine-mcp-home", engineId);
|
|
73885
74531
|
const cfg2 = join23(home, layout.configDir);
|
|
73886
|
-
|
|
74532
|
+
mkdirSync12(cfg2, { recursive: true });
|
|
73887
74533
|
if (layout.linkSiblingConfigs) {
|
|
73888
|
-
const realRoot =
|
|
74534
|
+
const realRoot = dirname10(join23(userHome2, layout.userConfigDirRel ?? layout.configDir));
|
|
73889
74535
|
let entries = [];
|
|
73890
74536
|
try {
|
|
73891
74537
|
entries = readdirSync3(realRoot);
|
|
@@ -73896,7 +74542,7 @@ function writeManagedMcpHome(engineId, layout, servers, projectDir, baseDir, use
|
|
|
73896
74542
|
if (name === layout.configDir)
|
|
73897
74543
|
continue;
|
|
73898
74544
|
const link = join23(home, name);
|
|
73899
|
-
if (
|
|
74545
|
+
if (existsSync11(link))
|
|
73900
74546
|
continue;
|
|
73901
74547
|
try {
|
|
73902
74548
|
symlinkSync2(join23(realRoot, name), link);
|
|
@@ -73920,7 +74566,7 @@ function writeManagedMcpHome(engineId, layout, servers, projectDir, baseDir, use
|
|
|
73920
74566
|
if ((layout.seedFiles ?? []).includes(name))
|
|
73921
74567
|
continue;
|
|
73922
74568
|
const link = join23(cfg2, name);
|
|
73923
|
-
if (
|
|
74569
|
+
if (existsSync11(link))
|
|
73924
74570
|
continue;
|
|
73925
74571
|
try {
|
|
73926
74572
|
symlinkSync2(join23(userCfg, name), link);
|
|
@@ -73931,7 +74577,7 @@ function writeManagedMcpHome(engineId, layout, servers, projectDir, baseDir, use
|
|
|
73931
74577
|
for (const f of layout.seedFiles ?? []) {
|
|
73932
74578
|
const src = join23(userCfg, f);
|
|
73933
74579
|
const dst = join23(cfg2, f);
|
|
73934
|
-
if (
|
|
74580
|
+
if (existsSync11(src) && !existsSync11(dst)) {
|
|
73935
74581
|
try {
|
|
73936
74582
|
copyFileSync2(src, dst);
|
|
73937
74583
|
} catch {
|
|
@@ -73940,7 +74586,7 @@ function writeManagedMcpHome(engineId, layout, servers, projectDir, baseDir, use
|
|
|
73940
74586
|
}
|
|
73941
74587
|
for (const f of layout.mirrorFiles ?? []) {
|
|
73942
74588
|
const src = join23(userCfg, f);
|
|
73943
|
-
if (!
|
|
74589
|
+
if (!existsSync11(src))
|
|
73944
74590
|
continue;
|
|
73945
74591
|
try {
|
|
73946
74592
|
copyFileSync2(src, join23(cfg2, f));
|
|
@@ -74537,7 +75183,7 @@ function httpApiArgs(spec, port) {
|
|
|
74537
75183
|
}
|
|
74538
75184
|
|
|
74539
75185
|
// ../../packages/host-core/dist/engines/session-index.js
|
|
74540
|
-
import { mkdirSync as
|
|
75186
|
+
import { mkdirSync as mkdirSync13, readFileSync as readFileSync20, writeFileSync as writeFileSync14 } from "node:fs";
|
|
74541
75187
|
import { join as join24 } from "node:path";
|
|
74542
75188
|
var MAX_ROWS = 500;
|
|
74543
75189
|
function createSessionIndex(engineId, baseDir, now2 = Date.now) {
|
|
@@ -74547,7 +75193,7 @@ function createSessionIndex(engineId, baseDir, now2 = Date.now) {
|
|
|
74547
75193
|
if (rows)
|
|
74548
75194
|
return rows;
|
|
74549
75195
|
try {
|
|
74550
|
-
const parsed = JSON.parse(
|
|
75196
|
+
const parsed = JSON.parse(readFileSync20(file2, "utf8"));
|
|
74551
75197
|
rows = (parsed.sessions ?? []).filter((r) => r && typeof r.id === "string");
|
|
74552
75198
|
} catch {
|
|
74553
75199
|
rows = [];
|
|
@@ -74561,7 +75207,7 @@ function createSessionIndex(engineId, baseDir, now2 = Date.now) {
|
|
|
74561
75207
|
if (rows.length > MAX_ROWS)
|
|
74562
75208
|
rows = rows.slice(0, MAX_ROWS);
|
|
74563
75209
|
try {
|
|
74564
|
-
|
|
75210
|
+
mkdirSync13(join24(baseDir, "engine-sessions"), { recursive: true });
|
|
74565
75211
|
writeFileSync14(file2, JSON.stringify({ sessions: rows }, null, 2), { mode: 384 });
|
|
74566
75212
|
} catch {
|
|
74567
75213
|
}
|
|
@@ -74637,7 +75283,7 @@ function wrapWithSeatbelt(command, args, profile) {
|
|
|
74637
75283
|
|
|
74638
75284
|
// ../../packages/host-core/dist/engines/opencode-acp.js
|
|
74639
75285
|
init_dist5();
|
|
74640
|
-
import { mkdirSync as
|
|
75286
|
+
import { mkdirSync as mkdirSync14, writeFileSync as writeFileSync15, readFileSync as readFileSync21 } from "node:fs";
|
|
74641
75287
|
import { join as join25, relative as relative4 } from "node:path";
|
|
74642
75288
|
import { homedir as homedir7, tmpdir as tmpdir4 } from "node:os";
|
|
74643
75289
|
var TESSERACT_INTERNAL_SECRET2 = /^(CCB_JWT_SECRET|JWT_SECRET|TESSERACT_TOKEN|CCB_RELAY_SECRET|TURN_SECRET|LIVEKIT_API_SECRET)$/;
|
|
@@ -74686,7 +75332,7 @@ function modelMemoPath(engineId) {
|
|
|
74686
75332
|
}
|
|
74687
75333
|
function lastKnownModel(engineId) {
|
|
74688
75334
|
try {
|
|
74689
|
-
return
|
|
75335
|
+
return readFileSync21(modelMemoPath(engineId), "utf8").trim() || void 0;
|
|
74690
75336
|
} catch {
|
|
74691
75337
|
return void 0;
|
|
74692
75338
|
}
|
|
@@ -74695,7 +75341,7 @@ function rememberModel(engineId, modelId) {
|
|
|
74695
75341
|
if (!modelId || modelId === lastKnownModel(engineId))
|
|
74696
75342
|
return;
|
|
74697
75343
|
try {
|
|
74698
|
-
|
|
75344
|
+
mkdirSync14(join25(daemonDir2(), "engine-config", engineId), { recursive: true });
|
|
74699
75345
|
writeFileSync15(modelMemoPath(engineId), modelId, { mode: 384 });
|
|
74700
75346
|
} catch {
|
|
74701
75347
|
}
|
|
@@ -74711,7 +75357,7 @@ async function writeTokenCompactionConfig(engineId, spec, modelId, pct2, baseDir
|
|
|
74711
75357
|
return {};
|
|
74712
75358
|
try {
|
|
74713
75359
|
const dir2 = join25(baseDir, "engine-config", engineId);
|
|
74714
|
-
|
|
75360
|
+
mkdirSync14(dir2, { recursive: true });
|
|
74715
75361
|
const file2 = join25(dir2, "tesseract.json");
|
|
74716
75362
|
const cfg2 = {};
|
|
74717
75363
|
let node = cfg2;
|
|
@@ -74796,7 +75442,15 @@ var OPENCODE_ACP = {
|
|
|
74796
75442
|
// Its own threshold, since ACP gives us no way to ASK it to compact. Without this the
|
|
74797
75443
|
// auto-compact slider could not reach OpenCode at all and it compacted only at its own
|
|
74798
75444
|
// hardcoded 95%.
|
|
74799
|
-
|
|
75445
|
+
// `reserved`, not `buffer` — read out of OpenCode's own bundle (1.18.21):
|
|
75446
|
+
// let l = cfg.compaction?.reserved ?? Math.min(20000, maxOutputTokens(model))
|
|
75447
|
+
// return model.limit.input ? max(0, model.limit.input - l) : max(0, context - maxOutput)
|
|
75448
|
+
// `buffer` was not a key it knows, so this reserve had never once taken effect. Note the
|
|
75449
|
+
// second branch: even under the right name the reserve is IGNORED for a model that does
|
|
75450
|
+
// not declare `limit.input` — which is most of them (1329 of 7482 on models.dev), gpt-4o
|
|
75451
|
+
// and gpt-4o-mini included. So this is worth writing correctly, and is NOT something the
|
|
75452
|
+
// slider can rely on; `shouldCompactProactively` is what actually holds the line.
|
|
75453
|
+
tokenCompaction: { configEnv: "OPENCODE_CONFIG", bufferPath: ["compaction", "reserved"] },
|
|
74800
75454
|
compactCommand: "/compact",
|
|
74801
75455
|
// ACP fallback; the HTTP RPC below is preferred
|
|
74802
75456
|
// `opencode acp` serves the full HTTP API on the same process — verified: the ACP session
|
|
@@ -75082,7 +75736,7 @@ function createAcpBackend(engine, send4, resolve16, onBrowserRequest, loadPlugin
|
|
|
75082
75736
|
let hostTasks = null;
|
|
75083
75737
|
let refreshHostedTools = null;
|
|
75084
75738
|
const lastTurnText = /* @__PURE__ */ new Map();
|
|
75085
|
-
const verification = createHostedVerification();
|
|
75739
|
+
const verification = createHostedVerification(engine.id);
|
|
75086
75740
|
const scheduling = createHostedScheduling(async (task) => {
|
|
75087
75741
|
const pol = scheduling.policy();
|
|
75088
75742
|
try {
|
|
@@ -75133,10 +75787,10 @@ function createAcpBackend(engine, send4, resolve16, onBrowserRequest, loadPlugin
|
|
|
75133
75787
|
collectReplay(replay, u);
|
|
75134
75788
|
return;
|
|
75135
75789
|
}
|
|
75136
|
-
const
|
|
75137
|
-
if (
|
|
75790
|
+
const sink2 = subagentSinks.get(sid);
|
|
75791
|
+
if (sink2) {
|
|
75138
75792
|
if (u.sessionUpdate === "agent_message_chunk")
|
|
75139
|
-
|
|
75793
|
+
sink2.push(u.content?.text ?? "");
|
|
75140
75794
|
return;
|
|
75141
75795
|
}
|
|
75142
75796
|
if (u.sessionUpdate === "usage_update") {
|
|
@@ -75257,6 +75911,7 @@ function createAcpBackend(engine, send4, resolve16, onBrowserRequest, loadPlugin
|
|
|
75257
75911
|
if (!turn)
|
|
75258
75912
|
return;
|
|
75259
75913
|
scheduleUnattendedAnswer({ kind: "elicitation", serverName: engine.label }, {
|
|
75914
|
+
context: { sessionId: sid, engine: engine.id },
|
|
75260
75915
|
mode: () => turn.unattended,
|
|
75261
75916
|
charge: () => turn.autoDecisions += 1,
|
|
75262
75917
|
refund: () => {
|
|
@@ -75434,6 +76089,7 @@ function createAcpBackend(engine, send4, resolve16, onBrowserRequest, loadPlugin
|
|
|
75434
76089
|
}, turn?.origin);
|
|
75435
76090
|
if (turn) {
|
|
75436
76091
|
scheduleUnattendedAnswer({ kind: "permission", tool: toolName }, {
|
|
76092
|
+
context: { sessionId: psid, engine: engine.id },
|
|
75437
76093
|
mode: () => turn.unattended,
|
|
75438
76094
|
charge: () => turn.autoDecisions += 1,
|
|
75439
76095
|
refund: () => {
|
|
@@ -75493,6 +76149,7 @@ function createAcpBackend(engine, send4, resolve16, onBrowserRequest, loadPlugin
|
|
|
75493
76149
|
if (!turn)
|
|
75494
76150
|
return;
|
|
75495
76151
|
scheduleUnattendedAnswer({ kind: "elicitation", serverName: "connector" }, {
|
|
76152
|
+
context: { sessionId: esid, engine: engine.id },
|
|
75496
76153
|
mode: () => turn.unattended,
|
|
75497
76154
|
charge: () => turn.autoDecisions += 1,
|
|
75498
76155
|
refund: () => {
|
|
@@ -75780,11 +76437,11 @@ ${text9}`);
|
|
|
75780
76437
|
await replayLoad(conn, sessionId);
|
|
75781
76438
|
}
|
|
75782
76439
|
async function promptForText(t, sid, prompt) {
|
|
75783
|
-
const
|
|
75784
|
-
subagentSinks.set(sid,
|
|
76440
|
+
const sink2 = [];
|
|
76441
|
+
subagentSinks.set(sid, sink2);
|
|
75785
76442
|
try {
|
|
75786
76443
|
for (let attempt = 0; attempt < RESEED_SUMMARY_ATTEMPTS; attempt++) {
|
|
75787
|
-
|
|
76444
|
+
sink2.length = 0;
|
|
75788
76445
|
let timer2;
|
|
75789
76446
|
const timedOut = Symbol("timeout");
|
|
75790
76447
|
const outcome = await Promise.race([
|
|
@@ -75807,7 +76464,7 @@ ${text9}`);
|
|
|
75807
76464
|
}
|
|
75808
76465
|
return null;
|
|
75809
76466
|
}
|
|
75810
|
-
const out =
|
|
76467
|
+
const out = sink2.join("").trim();
|
|
75811
76468
|
if (out)
|
|
75812
76469
|
return out;
|
|
75813
76470
|
if (attempt < RESEED_SUMMARY_ATTEMPTS - 1)
|
|
@@ -75889,6 +76546,56 @@ ${text9}`);
|
|
|
75889
76546
|
const all = await listSessionsFor(projectDir);
|
|
75890
76547
|
return all.filter((row) => row.title.toLowerCase().includes(q) || (sessionBodies.get(row.id) ?? "").includes(q));
|
|
75891
76548
|
}
|
|
76549
|
+
const proactiveCompactedAt = /* @__PURE__ */ new Map();
|
|
76550
|
+
const sessionRekey = /* @__PURE__ */ new Map();
|
|
76551
|
+
const overflowTries = /* @__PURE__ */ new Map();
|
|
76552
|
+
function contextUsageFor(sessionId) {
|
|
76553
|
+
const model = sessionResolvedModel.get(sessionId) ?? sessionConfig.get(sessionId)?.currentModel;
|
|
76554
|
+
const rep = sessionReported.get(sessionId);
|
|
76555
|
+
const total = rep?.used ?? sessionUsage.get(sessionId)?.total;
|
|
76556
|
+
const maxTokens = rep?.size ?? contextWindowFor(model) ?? void 0;
|
|
76557
|
+
if (total === void 0 || !maxTokens)
|
|
76558
|
+
return null;
|
|
76559
|
+
return {
|
|
76560
|
+
totalTokens: total,
|
|
76561
|
+
maxTokens,
|
|
76562
|
+
percentage: Math.min(100, Math.round(total / maxTokens * 1e3) / 10),
|
|
76563
|
+
...model ? { model } : {}
|
|
76564
|
+
};
|
|
76565
|
+
}
|
|
76566
|
+
async function maybeCompactProactively(sid, params) {
|
|
76567
|
+
try {
|
|
76568
|
+
if (params.autoContinuation)
|
|
76569
|
+
return;
|
|
76570
|
+
if (!declared.contextCompaction)
|
|
76571
|
+
return;
|
|
76572
|
+
const live = sessionRekey.get(sid) ?? sid;
|
|
76573
|
+
const usage2 = contextUsageFor(live);
|
|
76574
|
+
const verdict = shouldCompactProactively({
|
|
76575
|
+
mode: unattendedModeFor({ optedIn: params.unattended, origin: params.origin }),
|
|
76576
|
+
pct: readDaemonAgentSettings().autoCompactPct,
|
|
76577
|
+
usagePct: typeof usage2?.percentage === "number" ? usage2.percentage : null,
|
|
76578
|
+
lastCompactPct: proactiveCompactedAt.get(live) ?? null,
|
|
76579
|
+
inFlight: false
|
|
76580
|
+
});
|
|
76581
|
+
if (verdict === "reset") {
|
|
76582
|
+
proactiveCompactedAt.delete(live);
|
|
76583
|
+
return;
|
|
76584
|
+
}
|
|
76585
|
+
if (verdict !== "compact")
|
|
76586
|
+
return;
|
|
76587
|
+
proactiveCompactedAt.set(live, usage2?.percentage ?? 0);
|
|
76588
|
+
console.warn(`[${LABEL2}] auto-compact: ${Math.round(usage2?.percentage ?? 0)}% of the window used \u2014 compacting`);
|
|
76589
|
+
await sendMessage({ ...params, message: OVERFLOW_COMPACT_MESSAGE, sessionId: live, autoContinuation: true });
|
|
76590
|
+
const now2 = sessionRekey.get(live) ?? live;
|
|
76591
|
+
if (now2 !== live) {
|
|
76592
|
+
proactiveCompactedAt.set(now2, proactiveCompactedAt.get(live) ?? 0);
|
|
76593
|
+
proactiveCompactedAt.delete(live);
|
|
76594
|
+
}
|
|
76595
|
+
} catch (err2) {
|
|
76596
|
+
console.warn(`[${LABEL2}] auto-compact failed:`, err2 instanceof Error ? err2.message : String(err2));
|
|
76597
|
+
}
|
|
76598
|
+
}
|
|
75892
76599
|
async function sendMessage(params) {
|
|
75893
76600
|
const origin = params.origin;
|
|
75894
76601
|
const fail4 = (sessionId, error51, transient = false) => send4({ type: "chat:error", sessionId, clientRequestId: params.clientRequestId, error: error51, ...transient ? { transient: true } : {} }, origin);
|
|
@@ -76004,6 +76711,12 @@ ${text9}`);
|
|
|
76004
76711
|
}
|
|
76005
76712
|
sessionIndex.record({ id: next, cwd: params.projectDir, title, updatedAt: Date.now() });
|
|
76006
76713
|
sessionIndex.forget(from);
|
|
76714
|
+
sessionRekey.set(from, next);
|
|
76715
|
+
const spentTries = overflowTries.get(from);
|
|
76716
|
+
if (spentTries !== void 0) {
|
|
76717
|
+
overflowTries.set(next, spentTries);
|
|
76718
|
+
overflowTries.delete(from);
|
|
76719
|
+
}
|
|
76007
76720
|
send4({ type: "session:created", sessionId: next, clientRequestId: params.clientRequestId }, origin);
|
|
76008
76721
|
send4({ type: "chat:complete", sessionId: next, clientRequestId: params.clientRequestId, messageId: randomUUID11(), result: "Compacted this conversation to free up context.", turnId: randomUUID11() }, origin);
|
|
76009
76722
|
send4({ type: "agent:status", sessionId: next, clientRequestId: params.clientRequestId, status: "idle" }, origin);
|
|
@@ -76163,6 +76876,10 @@ ${text9}`);
|
|
|
76163
76876
|
}
|
|
76164
76877
|
}
|
|
76165
76878
|
}
|
|
76879
|
+
void maybeCompactProactively(sid, params);
|
|
76880
|
+
if (!(params.autoContinuation === true && params.message === OVERFLOW_COMPACT_MESSAGE)) {
|
|
76881
|
+
overflowTries.delete(sid);
|
|
76882
|
+
}
|
|
76166
76883
|
send4({ type: "chat:complete", sessionId: sid, clientRequestId: params.clientRequestId, messageId, result: finalText, turnId, ...res?.stopReason ? { stopReason: res.stopReason } : {} }, origin);
|
|
76167
76884
|
send4({ type: "agent:status", sessionId: sid, clientRequestId: params.clientRequestId, status: "idle" }, origin);
|
|
76168
76885
|
} catch (e) {
|
|
@@ -76170,6 +76887,19 @@ ${text9}`);
|
|
|
76170
76887
|
const detail = String(e?.message ?? e);
|
|
76171
76888
|
const overflow = isContextOverflow(detail);
|
|
76172
76889
|
if (overflow && declared.contextCompaction) {
|
|
76890
|
+
const recovered = await recoverFromContextOverflow({
|
|
76891
|
+
mode: () => unattendedModeFor({ optedIn: params.unattended, origin: params.origin }),
|
|
76892
|
+
canCompact: () => true,
|
|
76893
|
+
tries: () => overflowTries.get(sid) ?? 0,
|
|
76894
|
+
bump: () => overflowTries.set(sid, (overflowTries.get(sid) ?? 0) + 1),
|
|
76895
|
+
context: { sessionId: sid, engine: engine.id },
|
|
76896
|
+
compactAndResume: async () => {
|
|
76897
|
+
await sendMessage({ ...params, message: OVERFLOW_COMPACT_MESSAGE, sessionId: sid, autoContinuation: true });
|
|
76898
|
+
await sendMessage({ ...params, message: OVERFLOW_RESUME_MESSAGE, sessionId: sessionRekey.get(sid) ?? sid, autoContinuation: true });
|
|
76899
|
+
}
|
|
76900
|
+
});
|
|
76901
|
+
if (recovered)
|
|
76902
|
+
return;
|
|
76173
76903
|
send4({ type: "chat:error", sessionId: sid, clientRequestId: params.clientRequestId, error: detail, continuable: true, continueReason: "context_window" }, origin);
|
|
76174
76904
|
send4({ type: "agent:status", sessionId: sid, clientRequestId: params.clientRequestId, status: "idle" }, origin);
|
|
76175
76905
|
return;
|
|
@@ -76443,21 +77173,7 @@ ${detail}` : detail, !overflow);
|
|
|
76443
77173
|
}
|
|
76444
77174
|
},
|
|
76445
77175
|
...declared.contextUsage ? {
|
|
76446
|
-
getContextUsage: async (sessionId) =>
|
|
76447
|
-
const model = sessionResolvedModel.get(sessionId) ?? sessionConfig.get(sessionId)?.currentModel;
|
|
76448
|
-
const rep = sessionReported.get(sessionId);
|
|
76449
|
-
const total = rep?.used ?? sessionUsage.get(sessionId)?.total;
|
|
76450
|
-
const maxTokens = rep?.size ?? contextWindowFor(model) ?? void 0;
|
|
76451
|
-
if (total === void 0 || !maxTokens)
|
|
76452
|
-
return null;
|
|
76453
|
-
const usage2 = {
|
|
76454
|
-
totalTokens: total,
|
|
76455
|
-
maxTokens,
|
|
76456
|
-
percentage: Math.min(100, Math.round(total / maxTokens * 1e3) / 10),
|
|
76457
|
-
...model ? { model } : {}
|
|
76458
|
-
};
|
|
76459
|
-
return usage2;
|
|
76460
|
-
}
|
|
77176
|
+
getContextUsage: async (sessionId) => contextUsageFor(sessionId)
|
|
76461
77177
|
} : {},
|
|
76462
77178
|
...declared.costTracking ? {
|
|
76463
77179
|
getSessionCost: async (sessionId) => {
|
|
@@ -76889,7 +77605,7 @@ init_dist();
|
|
|
76889
77605
|
init_credentials();
|
|
76890
77606
|
import { spawn as spawn8 } from "node:child_process";
|
|
76891
77607
|
import { randomUUID as randomUUID12 } from "node:crypto";
|
|
76892
|
-
import { mkdirSync as
|
|
77608
|
+
import { mkdirSync as mkdirSync15, readFileSync as readFileSync22, writeFileSync as writeFileSync16 } from "node:fs";
|
|
76893
77609
|
import { join as join26 } from "node:path";
|
|
76894
77610
|
init_daemon_settings();
|
|
76895
77611
|
init_dist5();
|
|
@@ -77147,7 +77863,7 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
|
|
|
77147
77863
|
let hostedBearer = null;
|
|
77148
77864
|
let refreshHostedTools = null;
|
|
77149
77865
|
const lastTurnText = /* @__PURE__ */ new Map();
|
|
77150
|
-
const verification = createHostedVerification();
|
|
77866
|
+
const verification = createHostedVerification("codex");
|
|
77151
77867
|
const scheduling = createHostedScheduling(async (task) => {
|
|
77152
77868
|
try {
|
|
77153
77869
|
await sendMessage({ message: task.prompt, url: "", projectDir: spawnedCwd ?? void 0, sessionId: task.sessionId, origin: "cron" });
|
|
@@ -77220,6 +77936,7 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
|
|
|
77220
77936
|
if (!turn)
|
|
77221
77937
|
return;
|
|
77222
77938
|
scheduleUnattendedAnswer({ kind: "permission", tool: toolName }, {
|
|
77939
|
+
context: { sessionId: turn.threadId, engine: "codex" },
|
|
77223
77940
|
mode: () => turn.unattended,
|
|
77224
77941
|
charge: () => turn.autoDecisions += 1,
|
|
77225
77942
|
refund: () => {
|
|
@@ -77253,6 +77970,7 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
|
|
|
77253
77970
|
if (!turn)
|
|
77254
77971
|
return;
|
|
77255
77972
|
scheduleUnattendedAnswer(prompt, {
|
|
77973
|
+
context: { sessionId: turn.threadId, engine: "codex" },
|
|
77256
77974
|
mode: () => turn.unattended,
|
|
77257
77975
|
charge: () => turn.autoDecisions += 1,
|
|
77258
77976
|
refund: () => {
|
|
@@ -77284,10 +78002,10 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
|
|
|
77284
78002
|
function onNotification(method, raw) {
|
|
77285
78003
|
const p = raw ?? {};
|
|
77286
78004
|
const threadId = String(p.threadId ?? "");
|
|
77287
|
-
const
|
|
77288
|
-
if (
|
|
78005
|
+
const sink2 = subagentSinks.get(threadId);
|
|
78006
|
+
if (sink2) {
|
|
77289
78007
|
if (method === "item/agentMessage/delta")
|
|
77290
|
-
|
|
78008
|
+
sink2.push(String(p.delta ?? ""));
|
|
77291
78009
|
if (method === "turn/completed" || method === "error")
|
|
77292
78010
|
subagentDone.get(threadId)?.();
|
|
77293
78011
|
return;
|
|
@@ -77425,7 +78143,7 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
|
|
|
77425
78143
|
lastWindow = window2;
|
|
77426
78144
|
try {
|
|
77427
78145
|
const dir2 = join26(daemonDir2(), "engine-config", "openai-codex");
|
|
77428
|
-
|
|
78146
|
+
mkdirSync15(dir2, { recursive: true });
|
|
77429
78147
|
writeFileSync16(join26(dir2, "window"), String(window2), { mode: 384 });
|
|
77430
78148
|
} catch {
|
|
77431
78149
|
}
|
|
@@ -77434,7 +78152,7 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
|
|
|
77434
78152
|
if (lastWindow)
|
|
77435
78153
|
return lastWindow;
|
|
77436
78154
|
try {
|
|
77437
|
-
const n = Number(
|
|
78155
|
+
const n = Number(readFileSync22(join26(daemonDir2(), "engine-config", "openai-codex", "window"), "utf8").trim());
|
|
77438
78156
|
return Number.isFinite(n) && n > 0 ? lastWindow = n : void 0;
|
|
77439
78157
|
} catch {
|
|
77440
78158
|
return void 0;
|
|
@@ -77599,6 +78317,61 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
|
|
|
77599
78317
|
})();
|
|
77600
78318
|
return initPromise;
|
|
77601
78319
|
}
|
|
78320
|
+
const proactiveCompactedAt = /* @__PURE__ */ new Map();
|
|
78321
|
+
const overflowTries = /* @__PURE__ */ new Map();
|
|
78322
|
+
function contextUsageFor(sessionId) {
|
|
78323
|
+
const u = tokenUsage.get(sessionId);
|
|
78324
|
+
if (!u?.window)
|
|
78325
|
+
return null;
|
|
78326
|
+
const current = u.lastTotal || u.total;
|
|
78327
|
+
const usage2 = {
|
|
78328
|
+
// `last`, NOT `total`. Measured: `total` is CUMULATIVE over the conversation and grows
|
|
78329
|
+
// by exactly the previous turn's tokens (142,394 → 162,119 after a 19,725-token turn),
|
|
78330
|
+
// so it can never fall. Reporting it as context usage meant the meter climbed past
|
|
78331
|
+
// 100% of a 258k window on a conversation nowhere near full, never came down after a
|
|
78332
|
+
// compaction, and — because this figure is what the proactive threshold reads — asked
|
|
78333
|
+
// for compaction after compaction with the number refusing to move.
|
|
78334
|
+
//
|
|
78335
|
+
// `last.totalTokens` is the CURRENT context: the input the model actually saw on the
|
|
78336
|
+
// most recent turn, which is what a window is measured against and what drops when a
|
|
78337
|
+
// compaction succeeds.
|
|
78338
|
+
// `|| u.total`, not `?? u.total`: the single writer stores `u.last?.totalTokens ?? 0`,
|
|
78339
|
+
// so a missing `last` arrives here as 0 — which `??` passes straight through and the
|
|
78340
|
+
// meter reads 0% on a full conversation. Under-reporting is the dangerous direction,
|
|
78341
|
+
// because the proactive threshold then never fires and the context hits a hard
|
|
78342
|
+
// overflow instead of compacting. Observed live: a `thread/tokenUsage/updated` whose
|
|
78343
|
+
// `total` was all zeros while `last.totalTokens` was 4666, and the reverse.
|
|
78344
|
+
totalTokens: current,
|
|
78345
|
+
maxTokens: u.window,
|
|
78346
|
+
percentage: Math.min(100, Math.round(current / u.window * 1e3) / 10)
|
|
78347
|
+
};
|
|
78348
|
+
return usage2;
|
|
78349
|
+
}
|
|
78350
|
+
async function maybeCompactProactively(threadId, params) {
|
|
78351
|
+
try {
|
|
78352
|
+
if (params.autoContinuation)
|
|
78353
|
+
return;
|
|
78354
|
+
const usage2 = contextUsageFor(threadId);
|
|
78355
|
+
const verdict = shouldCompactProactively({
|
|
78356
|
+
mode: unattendedModeFor({ optedIn: params.unattended, origin: params.origin }),
|
|
78357
|
+
pct: readDaemonAgentSettings().autoCompactPct,
|
|
78358
|
+
usagePct: typeof usage2?.percentage === "number" ? usage2.percentage : null,
|
|
78359
|
+
lastCompactPct: proactiveCompactedAt.get(threadId) ?? null,
|
|
78360
|
+
inFlight: false
|
|
78361
|
+
});
|
|
78362
|
+
if (verdict === "reset") {
|
|
78363
|
+
proactiveCompactedAt.delete(threadId);
|
|
78364
|
+
return;
|
|
78365
|
+
}
|
|
78366
|
+
if (verdict !== "compact")
|
|
78367
|
+
return;
|
|
78368
|
+
proactiveCompactedAt.set(threadId, usage2?.percentage ?? 0);
|
|
78369
|
+
console.warn(`[${LABEL2}] auto-compact: ${Math.round(usage2?.percentage ?? 0)}% of the window used \u2014 compacting`);
|
|
78370
|
+
await sendMessage({ ...params, message: OVERFLOW_COMPACT_MESSAGE, sessionId: threadId, autoContinuation: true });
|
|
78371
|
+
} catch (err2) {
|
|
78372
|
+
console.warn(`[${LABEL2}] auto-compact failed:`, err2 instanceof Error ? err2.message : String(err2));
|
|
78373
|
+
}
|
|
78374
|
+
}
|
|
77602
78375
|
async function sendMessage(params) {
|
|
77603
78376
|
const origin = params.origin;
|
|
77604
78377
|
const cfg2 = resolve16(ENGINE_ID2);
|
|
@@ -77788,12 +78561,30 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
|
|
|
77788
78561
|
}
|
|
77789
78562
|
});
|
|
77790
78563
|
}
|
|
78564
|
+
void maybeCompactProactively(threadId, params);
|
|
78565
|
+
if (!(params.autoContinuation === true && params.message === OVERFLOW_COMPACT_MESSAGE)) {
|
|
78566
|
+
overflowTries.delete(threadId);
|
|
78567
|
+
}
|
|
77791
78568
|
send4({ type: "chat:complete", sessionId: threadId, clientRequestId: params.clientRequestId, messageId, result: finalText, turnId, ...stopReason ? { stopReason } : {} }, origin);
|
|
77792
78569
|
send4({ type: "agent:status", sessionId: threadId, clientRequestId: params.clientRequestId, status: "idle" }, origin);
|
|
77793
78570
|
} catch (e) {
|
|
77794
78571
|
turns.delete(threadId);
|
|
77795
78572
|
const detail = String(e?.message ?? e);
|
|
77796
78573
|
if (isContextOverflow(detail)) {
|
|
78574
|
+
const recovered = await recoverFromContextOverflow({
|
|
78575
|
+
mode: () => unattendedModeFor({ optedIn: params.unattended, origin: params.origin }),
|
|
78576
|
+
canCompact: () => true,
|
|
78577
|
+
// Codex maps '/compact' to thread/compact/start
|
|
78578
|
+
tries: () => overflowTries.get(threadId) ?? 0,
|
|
78579
|
+
bump: () => overflowTries.set(threadId, (overflowTries.get(threadId) ?? 0) + 1),
|
|
78580
|
+
context: { sessionId: threadId, engine: "codex" },
|
|
78581
|
+
compactAndResume: async () => {
|
|
78582
|
+
await sendMessage({ ...params, message: OVERFLOW_COMPACT_MESSAGE, sessionId: threadId, autoContinuation: true });
|
|
78583
|
+
await sendMessage({ ...params, message: OVERFLOW_RESUME_MESSAGE, sessionId: threadId, autoContinuation: true });
|
|
78584
|
+
}
|
|
78585
|
+
});
|
|
78586
|
+
if (recovered)
|
|
78587
|
+
return;
|
|
77797
78588
|
send4({ type: "chat:error", sessionId: threadId, clientRequestId: params.clientRequestId, error: detail, continuable: true, continueReason: "context_window" }, origin);
|
|
77798
78589
|
send4({ type: "agent:status", sessionId: threadId, clientRequestId: params.clientRequestId, status: "idle" }, origin);
|
|
77799
78590
|
return;
|
|
@@ -78117,34 +78908,7 @@ ${text9}`;
|
|
|
78117
78908
|
await transport.request("config/mcpServer/reload", {}).catch(() => {
|
|
78118
78909
|
});
|
|
78119
78910
|
},
|
|
78120
|
-
getContextUsage: async (sessionId) =>
|
|
78121
|
-
const u = tokenUsage.get(sessionId);
|
|
78122
|
-
if (!u?.window)
|
|
78123
|
-
return null;
|
|
78124
|
-
const current = u.lastTotal || u.total;
|
|
78125
|
-
const usage2 = {
|
|
78126
|
-
// `last`, NOT `total`. Measured: `total` is CUMULATIVE over the conversation and grows
|
|
78127
|
-
// by exactly the previous turn's tokens (142,394 → 162,119 after a 19,725-token turn),
|
|
78128
|
-
// so it can never fall. Reporting it as context usage meant the meter climbed past
|
|
78129
|
-
// 100% of a 258k window on a conversation nowhere near full, never came down after a
|
|
78130
|
-
// compaction, and — because this figure is what the proactive threshold reads — asked
|
|
78131
|
-
// for compaction after compaction with the number refusing to move.
|
|
78132
|
-
//
|
|
78133
|
-
// `last.totalTokens` is the CURRENT context: the input the model actually saw on the
|
|
78134
|
-
// most recent turn, which is what a window is measured against and what drops when a
|
|
78135
|
-
// compaction succeeds.
|
|
78136
|
-
// `|| u.total`, not `?? u.total`: the single writer stores `u.last?.totalTokens ?? 0`,
|
|
78137
|
-
// so a missing `last` arrives here as 0 — which `??` passes straight through and the
|
|
78138
|
-
// meter reads 0% on a full conversation. Under-reporting is the dangerous direction,
|
|
78139
|
-
// because the proactive threshold then never fires and the context hits a hard
|
|
78140
|
-
// overflow instead of compacting. Observed live: a `thread/tokenUsage/updated` whose
|
|
78141
|
-
// `total` was all zeros while `last.totalTokens` was 4666, and the reverse.
|
|
78142
|
-
totalTokens: current,
|
|
78143
|
-
maxTokens: u.window,
|
|
78144
|
-
percentage: Math.min(100, Math.round(current / u.window * 1e3) / 10)
|
|
78145
|
-
};
|
|
78146
|
-
return usage2;
|
|
78147
|
-
},
|
|
78911
|
+
getContextUsage: async (sessionId) => contextUsageFor(sessionId),
|
|
78148
78912
|
/** toolInjection, host half. Codex reads MCP servers from its config, so a change takes
|
|
78149
78913
|
* effect on the next install (the flag is reset so the write actually re-runs). */
|
|
78150
78914
|
setInjectedMcpServers: (servers) => {
|
|
@@ -78445,7 +79209,7 @@ async function createBackend(engineId, send4, onBrowserRequest, resolver, loadPl
|
|
|
78445
79209
|
// ../../packages/host-core/dist/session-recorder.js
|
|
78446
79210
|
init_base_paths();
|
|
78447
79211
|
import { join as join27 } from "node:path";
|
|
78448
|
-
import { mkdirSync as
|
|
79212
|
+
import { mkdirSync as mkdirSync16, writeFileSync as writeFileSync17, appendFileSync as appendFileSync3, readdirSync as readdirSync4, rmSync as rmSync2, statSync as statSync8 } from "node:fs";
|
|
78449
79213
|
init_dist5();
|
|
78450
79214
|
var dir = null;
|
|
78451
79215
|
var seq = 0;
|
|
@@ -78470,7 +79234,7 @@ function recordEvent(type, data = {}) {
|
|
|
78470
79234
|
if (!dir)
|
|
78471
79235
|
return;
|
|
78472
79236
|
try {
|
|
78473
|
-
|
|
79237
|
+
appendFileSync3(join27(dir, "events.jsonl"), `${JSON.stringify({ ts: now(), seq: seq++, type, ...data })}
|
|
78474
79238
|
`);
|
|
78475
79239
|
} catch {
|
|
78476
79240
|
}
|
|
@@ -78481,8 +79245,8 @@ init_dist5();
|
|
|
78481
79245
|
|
|
78482
79246
|
// ../../packages/host-core/dist/plugin-tools.js
|
|
78483
79247
|
init_base_paths();
|
|
78484
|
-
import { existsSync as
|
|
78485
|
-
import { join as join28, dirname as
|
|
79248
|
+
import { existsSync as existsSync12, readdirSync as readdirSync5 } from "node:fs";
|
|
79249
|
+
import { join as join28, dirname as dirname11 } from "node:path";
|
|
78486
79250
|
|
|
78487
79251
|
// ../../packages/plugin-host/dist/index.js
|
|
78488
79252
|
init_dist();
|
|
@@ -78816,7 +79580,7 @@ function convertTool(t) {
|
|
|
78816
79580
|
};
|
|
78817
79581
|
}
|
|
78818
79582
|
function createOpenClawAdapter(pluginId, config2, secretResolver, registry3) {
|
|
78819
|
-
const
|
|
79583
|
+
const warned2 = /* @__PURE__ */ new Set();
|
|
78820
79584
|
const impl = {
|
|
78821
79585
|
pluginId,
|
|
78822
79586
|
config: config2,
|
|
@@ -78887,8 +79651,8 @@ function createOpenClawAdapter(pluginId, config2, secretResolver, registry3) {
|
|
|
78887
79651
|
return Reflect.get(target, prop, recv);
|
|
78888
79652
|
if (typeof prop === "string") {
|
|
78889
79653
|
return (..._args) => {
|
|
78890
|
-
if (!
|
|
78891
|
-
|
|
79654
|
+
if (!warned2.has(prop)) {
|
|
79655
|
+
warned2.add(prop);
|
|
78892
79656
|
registry3.diagnostics.push(`[${pluginId}] api.${prop}() is not supported by the Tesseract host \u2014 ignored`);
|
|
78893
79657
|
}
|
|
78894
79658
|
};
|
|
@@ -79000,7 +79764,7 @@ function buildDaemonPluginLoader(pluginsDir) {
|
|
|
79000
79764
|
return async () => {
|
|
79001
79765
|
const skillsPlugin = daemonSkillsPluginConfig();
|
|
79002
79766
|
const snap = readDaemonAgentSettings();
|
|
79003
|
-
const desktopRoots = (snap.pluginRoots ?? []).filter((r) => r?.dir &&
|
|
79767
|
+
const desktopRoots = (snap.pluginRoots ?? []).filter((r) => r?.dir && existsSync12(r.dir));
|
|
79004
79768
|
if (desktopRoots.length > 0) {
|
|
79005
79769
|
const resDir = process.resourcesPath;
|
|
79006
79770
|
for (const r of desktopRoots) {
|
|
@@ -79009,7 +79773,7 @@ function buildDaemonPluginLoader(pluginsDir) {
|
|
|
79009
79773
|
if (resDir && r.dir.startsWith(resDir))
|
|
79010
79774
|
continue;
|
|
79011
79775
|
try {
|
|
79012
|
-
writeOpenClawShim(r.dir.endsWith("node_modules") ?
|
|
79776
|
+
writeOpenClawShim(r.dir.endsWith("node_modules") ? dirname11(r.dir) : r.dir);
|
|
79013
79777
|
} catch {
|
|
79014
79778
|
}
|
|
79015
79779
|
}
|
|
@@ -79023,7 +79787,7 @@ function buildDaemonPluginLoader(pluginsDir) {
|
|
|
79023
79787
|
return { ...rt2, skillsPlugin };
|
|
79024
79788
|
}
|
|
79025
79789
|
const scan = join28(pluginsDir, "node_modules");
|
|
79026
|
-
if (!
|
|
79790
|
+
if (!existsSync12(scan))
|
|
79027
79791
|
return { tools: [], hooks: [], messageHooks: [], commands: [], themeOps: [], engines: [], skillsPlugin };
|
|
79028
79792
|
writeOpenClawShim(pluginsDir);
|
|
79029
79793
|
const rt = await loadPluginRuntime({
|
|
@@ -79035,11 +79799,11 @@ function buildDaemonPluginLoader(pluginsDir) {
|
|
|
79035
79799
|
}
|
|
79036
79800
|
function daemonSkillsPluginConfig() {
|
|
79037
79801
|
const root = readDaemonAgentSettings().skillsRoot ?? tessPath("extensions-skills");
|
|
79038
|
-
if (!
|
|
79802
|
+
if (!existsSync12(join28(root, ".claude-plugin", "plugin.json")))
|
|
79039
79803
|
return null;
|
|
79040
79804
|
const enabled = join28(root, "skills");
|
|
79041
79805
|
try {
|
|
79042
|
-
const hasSkill = readdirSync5(enabled).some((slug2) =>
|
|
79806
|
+
const hasSkill = readdirSync5(enabled).some((slug2) => existsSync12(join28(enabled, slug2, "SKILL.md")));
|
|
79043
79807
|
return hasSkill ? { type: "local", path: root } : null;
|
|
79044
79808
|
} catch {
|
|
79045
79809
|
return null;
|
|
@@ -79241,10 +80005,10 @@ async function enableEditorMirror(browserId, onEvent) {
|
|
|
79241
80005
|
});
|
|
79242
80006
|
page.on("pageerror", (err2) => relay({ level: "error", kind: "console", message: err2.message }));
|
|
79243
80007
|
page.on("requestfailed", (req) => {
|
|
79244
|
-
const
|
|
79245
|
-
if (
|
|
80008
|
+
const errText2 = req.failure()?.errorText ?? "request failed";
|
|
80009
|
+
if (errText2.includes("ERR_ABORTED"))
|
|
79246
80010
|
return;
|
|
79247
|
-
relay({ level: "error", kind: "network", message: `Failed to load ${req.url()} \u2014 ${
|
|
80011
|
+
relay({ level: "error", kind: "network", message: `Failed to load ${req.url()} \u2014 ${errText2}` });
|
|
79248
80012
|
});
|
|
79249
80013
|
page.on("close", () => editorErrorTaps.delete(browserId));
|
|
79250
80014
|
}
|
|
@@ -79339,10 +80103,10 @@ import { join as join30 } from "node:path";
|
|
|
79339
80103
|
|
|
79340
80104
|
// ../../packages/host-core/dist/gui/daemon-gui.js
|
|
79341
80105
|
init_credentials();
|
|
79342
|
-
import { join as join29, dirname as
|
|
80106
|
+
import { join as join29, dirname as dirname12 } from "node:path";
|
|
79343
80107
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
79344
80108
|
import { spawn as spawn9, spawnSync } from "node:child_process";
|
|
79345
|
-
import { existsSync as
|
|
80109
|
+
import { existsSync as existsSync13 } from "node:fs";
|
|
79346
80110
|
|
|
79347
80111
|
// ../../packages/host-core/dist/gui/main-app-launch.js
|
|
79348
80112
|
var LAUNCH_MARKERS = [
|
|
@@ -79578,14 +80342,14 @@ function daemonUiDir() {
|
|
|
79578
80342
|
return resolvedUiDir;
|
|
79579
80343
|
const ok = (d) => {
|
|
79580
80344
|
try {
|
|
79581
|
-
return
|
|
80345
|
+
return existsSync13(join29(d, "preload.cjs"));
|
|
79582
80346
|
} catch {
|
|
79583
80347
|
return false;
|
|
79584
80348
|
}
|
|
79585
80349
|
};
|
|
79586
80350
|
let here = null;
|
|
79587
80351
|
try {
|
|
79588
|
-
here =
|
|
80352
|
+
here = dirname12(fileURLToPath4(import.meta.url));
|
|
79589
80353
|
} catch {
|
|
79590
80354
|
here = null;
|
|
79591
80355
|
}
|
|
@@ -79617,8 +80381,8 @@ function devAppPath() {
|
|
|
79617
80381
|
return env;
|
|
79618
80382
|
const daemonEntry = process.argv[1];
|
|
79619
80383
|
if (daemonEntry) {
|
|
79620
|
-
const cand = join29(
|
|
79621
|
-
if (
|
|
80384
|
+
const cand = join29(dirname12(daemonEntry), "..", "..", "desktop");
|
|
80385
|
+
if (existsSync13(join29(cand, "package.json")))
|
|
79622
80386
|
return cand;
|
|
79623
80387
|
}
|
|
79624
80388
|
return null;
|
|
@@ -80001,7 +80765,7 @@ function widgetDisplayBounds(w) {
|
|
|
80001
80765
|
}
|
|
80002
80766
|
|
|
80003
80767
|
// ../../packages/host-core/dist/gui/ai-control.js
|
|
80004
|
-
import { join as join31, dirname as
|
|
80768
|
+
import { join as join31, dirname as dirname13 } from "node:path";
|
|
80005
80769
|
import { randomUUID as randomUUID14 } from "node:crypto";
|
|
80006
80770
|
init_dist5();
|
|
80007
80771
|
init_credentials();
|
|
@@ -80081,7 +80845,7 @@ var MOONDREAM_URL = (process.env.CCB_MOONDREAM_URL?.trim() || "http://127.0.0.1:
|
|
|
80081
80845
|
|
|
80082
80846
|
// ../../packages/host-core/dist/voice-control.js
|
|
80083
80847
|
init_base_paths();
|
|
80084
|
-
import { existsSync as
|
|
80848
|
+
import { existsSync as existsSync14, readFileSync as readFileSync23 } from "node:fs";
|
|
80085
80849
|
import { basename as basename4, join as join32 } from "node:path";
|
|
80086
80850
|
|
|
80087
80851
|
// ../../packages/voice-core/dist/providers/tool-adapters.js
|
|
@@ -81332,8 +82096,8 @@ function readGeminiKeyFile() {
|
|
|
81332
82096
|
try {
|
|
81333
82097
|
const home = tesseractHome();
|
|
81334
82098
|
const f = join32(home, "daemon", "gemini.key");
|
|
81335
|
-
if (
|
|
81336
|
-
const k =
|
|
82099
|
+
if (existsSync14(f)) {
|
|
82100
|
+
const k = readFileSync23(f, "utf-8").trim();
|
|
81337
82101
|
if (k)
|
|
81338
82102
|
return k;
|
|
81339
82103
|
}
|
|
@@ -81751,13 +82515,13 @@ ${priorText}` : "";
|
|
|
81751
82515
|
};
|
|
81752
82516
|
|
|
81753
82517
|
// ../../packages/host-core/dist/daemon-agent.js
|
|
81754
|
-
import { mkdirSync as
|
|
82518
|
+
import { mkdirSync as mkdirSync22 } from "node:fs";
|
|
81755
82519
|
init_pool();
|
|
81756
82520
|
|
|
81757
82521
|
// ../../packages/host-core/dist/image-gen-runner.js
|
|
81758
82522
|
init_base_paths();
|
|
81759
82523
|
import { randomUUID as randomUUID16 } from "node:crypto";
|
|
81760
|
-
import { mkdirSync as
|
|
82524
|
+
import { mkdirSync as mkdirSync17, writeFileSync as writeFileSync18, readFileSync as readFileSync24 } from "node:fs";
|
|
81761
82525
|
import { join as join33 } from "node:path";
|
|
81762
82526
|
|
|
81763
82527
|
// ../../packages/image-edit-core/dist/transparent.js
|
|
@@ -82246,7 +83010,7 @@ function createDaemonImageGenRunner() {
|
|
|
82246
83010
|
let inputMime;
|
|
82247
83011
|
if (req.sourceImagePath) {
|
|
82248
83012
|
try {
|
|
82249
|
-
inputImageB64 =
|
|
83013
|
+
inputImageB64 = readFileSync24(req.sourceImagePath).toString("base64");
|
|
82250
83014
|
const lower = req.sourceImagePath.toLowerCase();
|
|
82251
83015
|
inputMime = lower.endsWith(".jpg") || lower.endsWith(".jpeg") ? "image/jpeg" : lower.endsWith(".webp") ? "image/webp" : "image/png";
|
|
82252
83016
|
} catch (e) {
|
|
@@ -82267,7 +83031,7 @@ function createDaemonImageGenRunner() {
|
|
|
82267
83031
|
if (!images.length)
|
|
82268
83032
|
return { ok: false, error: "The provider returned no image." };
|
|
82269
83033
|
const dir2 = req.outDir ?? join33(generatedImagesDir(), randomUUID16());
|
|
82270
|
-
|
|
83034
|
+
mkdirSync17(dir2, { recursive: true });
|
|
82271
83035
|
const files = images.map((img, i) => {
|
|
82272
83036
|
const ext = img.mime.split("/")[1]?.split("+")[0] || "png";
|
|
82273
83037
|
const path6 = join33(dir2, `${i + 1}.${ext}`);
|
|
@@ -82287,7 +83051,7 @@ function createDaemonImageGenRunner() {
|
|
|
82287
83051
|
init_serpapi_runner();
|
|
82288
83052
|
|
|
82289
83053
|
// ../../packages/host-core/dist/video-gen-runner.js
|
|
82290
|
-
import { readFileSync as
|
|
83054
|
+
import { readFileSync as readFileSync26 } from "node:fs";
|
|
82291
83055
|
|
|
82292
83056
|
// ../../packages/video-core/dist/cost.js
|
|
82293
83057
|
var VEO_RATES = [
|
|
@@ -83687,9 +84451,9 @@ init_daemon_settings();
|
|
|
83687
84451
|
|
|
83688
84452
|
// ../../packages/host-core/dist/video-jobs.js
|
|
83689
84453
|
init_base_paths();
|
|
83690
|
-
import { mkdirSync as
|
|
84454
|
+
import { mkdirSync as mkdirSync18, readdirSync as readdirSync6, readFileSync as readFileSync25, writeFileSync as writeFileSync19, rmSync as rmSync3 } from "node:fs";
|
|
83691
84455
|
import { mkdir as mkdir6, writeFile as writeFile7 } from "node:fs/promises";
|
|
83692
|
-
import { dirname as
|
|
84456
|
+
import { dirname as dirname14, join as join34 } from "node:path";
|
|
83693
84457
|
import { randomUUID as randomUUID17 } from "node:crypto";
|
|
83694
84458
|
function mediaJobsDir() {
|
|
83695
84459
|
const home = tesseractHome();
|
|
@@ -83738,7 +84502,7 @@ var VideoJobRegistry = class {
|
|
|
83738
84502
|
if (mem)
|
|
83739
84503
|
return { ...mem };
|
|
83740
84504
|
try {
|
|
83741
|
-
const raw =
|
|
84505
|
+
const raw = readFileSync25(join34(mediaJobsDir(), `${jobId}.json`), "utf-8");
|
|
83742
84506
|
return JSON.parse(raw);
|
|
83743
84507
|
} catch {
|
|
83744
84508
|
return null;
|
|
@@ -83790,7 +84554,7 @@ var VideoJobRegistry = class {
|
|
|
83790
84554
|
for (const f of files) {
|
|
83791
84555
|
const fp = join34(mediaJobsDir(), f);
|
|
83792
84556
|
try {
|
|
83793
|
-
const job = JSON.parse(
|
|
84557
|
+
const job = JSON.parse(readFileSync25(fp, "utf-8"));
|
|
83794
84558
|
if (TERMINAL.has(job.state)) {
|
|
83795
84559
|
if (now2 - (job.updatedAt ?? job.createdAt ?? now2) > DISK_RETENTION_MS)
|
|
83796
84560
|
rmSync3(fp, { force: true });
|
|
@@ -83874,7 +84638,7 @@ var VideoJobRegistry = class {
|
|
|
83874
84638
|
this.materializing.add(job.id);
|
|
83875
84639
|
try {
|
|
83876
84640
|
const res = await provider.fetchResult({ providerId: job.providerId, model: job.model, operationName: job.operationName });
|
|
83877
|
-
await mkdir6(
|
|
84641
|
+
await mkdir6(dirname14(job.outPath), { recursive: true });
|
|
83878
84642
|
await writeFile7(job.outPath, res.bytes);
|
|
83879
84643
|
this.update(job, { state: "succeeded", mime: res.mime, progressPct: 100 });
|
|
83880
84644
|
} catch (e) {
|
|
@@ -83910,7 +84674,7 @@ var VideoJobRegistry = class {
|
|
|
83910
84674
|
persist(job) {
|
|
83911
84675
|
this.jobs.set(job.id, job);
|
|
83912
84676
|
try {
|
|
83913
|
-
|
|
84677
|
+
mkdirSync18(mediaJobsDir(), { recursive: true });
|
|
83914
84678
|
writeFileSync19(join34(mediaJobsDir(), `${job.id}.json`), JSON.stringify(job, null, 2));
|
|
83915
84679
|
} catch {
|
|
83916
84680
|
}
|
|
@@ -83955,7 +84719,7 @@ function buildProvider(id, pc, model) {
|
|
|
83955
84719
|
function readFrame(path6) {
|
|
83956
84720
|
const lower = path6.toLowerCase();
|
|
83957
84721
|
const mime = lower.endsWith(".jpg") || lower.endsWith(".jpeg") ? "image/jpeg" : lower.endsWith(".webp") ? "image/webp" : "image/png";
|
|
83958
|
-
return { bytes: new Uint8Array(
|
|
84722
|
+
return { bytes: new Uint8Array(readFileSync26(path6)), mime };
|
|
83959
84723
|
}
|
|
83960
84724
|
function providerForJob(providerId, model) {
|
|
83961
84725
|
const c = creds2();
|
|
@@ -84063,7 +84827,7 @@ function createDaemonVideoGenRunner() {
|
|
|
84063
84827
|
|
|
84064
84828
|
// ../../packages/host-core/dist/video-edit-runner.js
|
|
84065
84829
|
init_base_paths();
|
|
84066
|
-
import { existsSync as
|
|
84830
|
+
import { existsSync as existsSync17, readFileSync as readFileSync31 } from "node:fs";
|
|
84067
84831
|
import { mkdir as mkdir7, writeFile as writeFile8 } from "node:fs/promises";
|
|
84068
84832
|
import { join as join38, basename as basename6 } from "node:path";
|
|
84069
84833
|
import { randomUUID as randomUUID19 } from "node:crypto";
|
|
@@ -84072,12 +84836,12 @@ init_daemon_settings();
|
|
|
84072
84836
|
// ../../packages/host-core/dist/video-edit.js
|
|
84073
84837
|
init_base_paths();
|
|
84074
84838
|
import { spawn as spawn11 } from "node:child_process";
|
|
84075
|
-
import { mkdirSync as
|
|
84839
|
+
import { mkdirSync as mkdirSync19, readFileSync as readFileSync27, rmSync as rmSync4, writeFileSync as writeFileSync20 } from "node:fs";
|
|
84076
84840
|
import { join as join35, isAbsolute as isAbsolute5 } from "node:path";
|
|
84077
84841
|
import { randomUUID as randomUUID18 } from "node:crypto";
|
|
84078
84842
|
|
|
84079
84843
|
// ../../packages/host-core/dist/ffmpeg.js
|
|
84080
|
-
import { existsSync as
|
|
84844
|
+
import { existsSync as existsSync15 } from "node:fs";
|
|
84081
84845
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
84082
84846
|
import { sep as sep5 } from "node:path";
|
|
84083
84847
|
import { createRequire as createRequire3 } from "node:module";
|
|
@@ -84090,7 +84854,7 @@ function fromPackage(name) {
|
|
|
84090
84854
|
if (typeof raw !== "string")
|
|
84091
84855
|
return null;
|
|
84092
84856
|
const p = unpacked(raw);
|
|
84093
|
-
return
|
|
84857
|
+
return existsSync15(p) ? p : null;
|
|
84094
84858
|
} catch {
|
|
84095
84859
|
return null;
|
|
84096
84860
|
}
|
|
@@ -84106,7 +84870,7 @@ function fromPath(cmd) {
|
|
|
84106
84870
|
function resolveBinary(envVar, pkg, cmd, hint) {
|
|
84107
84871
|
const env = process.env[envVar]?.trim();
|
|
84108
84872
|
if (env) {
|
|
84109
|
-
if (
|
|
84873
|
+
if (existsSync15(env) || fromPath(env))
|
|
84110
84874
|
return env;
|
|
84111
84875
|
throw new Error(`${envVar}=${env} does not exist or is not executable.`);
|
|
84112
84876
|
}
|
|
@@ -84148,14 +84912,14 @@ var mediaCwd;
|
|
|
84148
84912
|
function mediaSpawnCwd() {
|
|
84149
84913
|
if (!mediaCwd) {
|
|
84150
84914
|
mediaCwd = tessPath("media-work");
|
|
84151
|
-
|
|
84915
|
+
mkdirSync19(mediaCwd, { recursive: true });
|
|
84152
84916
|
}
|
|
84153
84917
|
return mediaCwd;
|
|
84154
84918
|
}
|
|
84155
84919
|
var workDir = () => {
|
|
84156
84920
|
const home = tesseractHome();
|
|
84157
84921
|
const dir2 = join35(home, "media-work", randomUUID18());
|
|
84158
|
-
|
|
84922
|
+
mkdirSync19(dir2, { recursive: true });
|
|
84159
84923
|
return dir2;
|
|
84160
84924
|
};
|
|
84161
84925
|
var MIME_BY_EXT = {
|
|
@@ -84244,7 +85008,7 @@ async function renderEdl(edl, opts) {
|
|
|
84244
85008
|
}
|
|
84245
85009
|
}
|
|
84246
85010
|
const dir2 = opts.outDir ?? workDir();
|
|
84247
|
-
|
|
85011
|
+
mkdirSync19(dir2, { recursive: true });
|
|
84248
85012
|
const format = edl.output?.format ?? "mp4";
|
|
84249
85013
|
const outPath = join35(dir2, `edit.${format}`);
|
|
84250
85014
|
let assFile;
|
|
@@ -84318,7 +85082,7 @@ async function enhanceVideo(path6, spec, opts) {
|
|
|
84318
85082
|
throw new Error("Nothing to enhance \u2014 request at least one of: upscale, denoise, deblock, deband, sharpen, or interpolate.");
|
|
84319
85083
|
}
|
|
84320
85084
|
const dir2 = opts?.outDir ?? workDir();
|
|
84321
|
-
|
|
85085
|
+
mkdirSync19(dir2, { recursive: true });
|
|
84322
85086
|
const outPath = join35(dir2, "enhanced.mp4");
|
|
84323
85087
|
const audioArgs = probe.hasAudio ? ["-c:a", "copy"] : ["-an"];
|
|
84324
85088
|
const args = [
|
|
@@ -84396,7 +85160,7 @@ ${stderrTail}`));
|
|
|
84396
85160
|
async function extractFrames(path6, timestamps, outDir) {
|
|
84397
85161
|
path6 = requireAbsolutePath(path6, "path");
|
|
84398
85162
|
const dir2 = outDir ?? workDir();
|
|
84399
|
-
|
|
85163
|
+
mkdirSync19(dir2, { recursive: true });
|
|
84400
85164
|
const out = [];
|
|
84401
85165
|
for (const [i, ts] of timestamps.slice(0, 20).entries()) {
|
|
84402
85166
|
const file2 = join35(dir2, `frame-${i + 1}-${Math.round(ts * 1e3)}ms.jpg`);
|
|
@@ -84431,7 +85195,7 @@ async function detectSilence(path6, opts) {
|
|
|
84431
85195
|
async function extractAudio(path6, format, outDir, opts) {
|
|
84432
85196
|
path6 = requireAbsolutePath(path6, "path");
|
|
84433
85197
|
const dir2 = outDir ?? workDir();
|
|
84434
|
-
|
|
85198
|
+
mkdirSync19(dir2, { recursive: true });
|
|
84435
85199
|
const out = join35(dir2, `audio.${format}`);
|
|
84436
85200
|
const codec2 = format === "mp3" ? ["-c:a", "libmp3lame", "-q:a", "2"] : format === "wav" ? ["-c:a", "pcm_s16le"] : ["-c:a", "aac", "-b:a", "192k"];
|
|
84437
85201
|
const gain = opts?.gainDb ? ["-af", `volume=${opts.gainDb}dB`] : [];
|
|
@@ -84447,7 +85211,7 @@ async function isolateSpeakerAudio(path6, windows2, outDir) {
|
|
|
84447
85211
|
const merged = mergeWindows(windows2).slice(0, 200);
|
|
84448
85212
|
const enable = merged.map((w) => `between(t,${w.startSec},${w.endSec})`).join("+");
|
|
84449
85213
|
const dir2 = outDir ?? workDir();
|
|
84450
|
-
|
|
85214
|
+
mkdirSync19(dir2, { recursive: true });
|
|
84451
85215
|
const out = join35(dir2, "speaker.m4a");
|
|
84452
85216
|
const r = await run2(resolveFfmpeg(), ["-y", "-i", path6, "-vn", "-af", `volume=enable='1-min(1,${enable})':volume=0`, "-c:a", "aac", "-b:a", "192k", out], {
|
|
84453
85217
|
timeoutMs: LONG_TIMEOUT_MS
|
|
@@ -84501,19 +85265,19 @@ function cleanupDir(dir2) {
|
|
|
84501
85265
|
}
|
|
84502
85266
|
}
|
|
84503
85267
|
function readChunkBase64(path6) {
|
|
84504
|
-
return
|
|
85268
|
+
return readFileSync27(path6).toString("base64");
|
|
84505
85269
|
}
|
|
84506
85270
|
|
|
84507
85271
|
// ../../packages/host-core/dist/video-upscale.js
|
|
84508
85272
|
init_base_paths();
|
|
84509
85273
|
import { spawn as spawn12 } from "node:child_process";
|
|
84510
|
-
import { existsSync as
|
|
84511
|
-
import { join as join36, dirname as
|
|
85274
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync20, readFileSync as readFileSync28, readdirSync as readdirSync7 } from "node:fs";
|
|
85275
|
+
import { join as join36, dirname as dirname15 } from "node:path";
|
|
84512
85276
|
var upscaleCwd;
|
|
84513
85277
|
function upscaleSpawnCwd() {
|
|
84514
85278
|
if (!upscaleCwd) {
|
|
84515
85279
|
upscaleCwd = tessPath("media-work");
|
|
84516
|
-
|
|
85280
|
+
mkdirSync20(upscaleCwd, { recursive: true });
|
|
84517
85281
|
}
|
|
84518
85282
|
return upscaleCwd;
|
|
84519
85283
|
}
|
|
@@ -84525,12 +85289,12 @@ function resolveRealesrgan() {
|
|
|
84525
85289
|
envBin,
|
|
84526
85290
|
// Packaged app: extraResources → Resources/vendor/realesrgan/<plat>/…
|
|
84527
85291
|
process.resourcesPath ? join36(process.resourcesPath, "vendor", "realesrgan", platDir, exe) : void 0
|
|
84528
|
-
].filter((p) => !!p &&
|
|
85292
|
+
].filter((p) => !!p && existsSync16(p));
|
|
84529
85293
|
const bin = candidates[0] ?? fromPath2("realesrgan-ncnn-vulkan");
|
|
84530
85294
|
if (!bin)
|
|
84531
85295
|
return null;
|
|
84532
|
-
const models = process.env.TESSERACT_REALESRGAN_MODELS?.trim() || join36(
|
|
84533
|
-
return
|
|
85296
|
+
const models = process.env.TESSERACT_REALESRGAN_MODELS?.trim() || join36(dirname15(bin), "models");
|
|
85297
|
+
return existsSync16(models) ? { bin, models } : null;
|
|
84534
85298
|
}
|
|
84535
85299
|
function fromPath2(cmd) {
|
|
84536
85300
|
try {
|
|
@@ -84552,8 +85316,8 @@ function installedRealesrModels() {
|
|
|
84552
85316
|
return [];
|
|
84553
85317
|
return REALESRGAN_MODELS.filter((m) => {
|
|
84554
85318
|
if (m.scales.length > 1)
|
|
84555
|
-
return m.scales.some((s) =>
|
|
84556
|
-
return
|
|
85319
|
+
return m.scales.some((s) => existsSync16(join36(re.models, `${m.id}-x${s}.bin`)));
|
|
85320
|
+
return existsSync16(join36(re.models, `${m.id}.bin`));
|
|
84557
85321
|
}).map((m) => m.id);
|
|
84558
85322
|
}
|
|
84559
85323
|
function upscaleAdvert() {
|
|
@@ -84574,7 +85338,7 @@ async function realesrganGpuWorks() {
|
|
|
84574
85338
|
const dir2 = workDir();
|
|
84575
85339
|
const inP = join36(dir2, "p.png"), outP = join36(dir2, "p2.png");
|
|
84576
85340
|
const gen = await run2(resolveFfmpeg(), ["-y", "-f", "lavfi", "-i", "testsrc=size=64x64:duration=1", "-frames:v", "1", inP], { timeoutMs: 15e3 });
|
|
84577
|
-
if (!gen.ok || !
|
|
85341
|
+
if (!gen.ok || !existsSync16(inP)) {
|
|
84578
85342
|
gpuProbe = false;
|
|
84579
85343
|
return false;
|
|
84580
85344
|
}
|
|
@@ -84593,7 +85357,7 @@ async function realesrganGpuWorks() {
|
|
|
84593
85357
|
code === 0 ? resolve16() : reject(new Error(`exit ${code}`));
|
|
84594
85358
|
});
|
|
84595
85359
|
});
|
|
84596
|
-
gpuProbe =
|
|
85360
|
+
gpuProbe = existsSync16(outP);
|
|
84597
85361
|
} catch {
|
|
84598
85362
|
gpuProbe = false;
|
|
84599
85363
|
}
|
|
@@ -84612,8 +85376,8 @@ async function upscaleCapabilities(opts) {
|
|
|
84612
85376
|
function resolveFalKey() {
|
|
84613
85377
|
const home = tesseractHome();
|
|
84614
85378
|
const file2 = join36(home, "daemon", "fal.key");
|
|
84615
|
-
if (
|
|
84616
|
-
const k =
|
|
85379
|
+
if (existsSync16(file2)) {
|
|
85380
|
+
const k = readFileSync28(file2, "utf-8").trim();
|
|
84617
85381
|
if (k)
|
|
84618
85382
|
return k;
|
|
84619
85383
|
}
|
|
@@ -84660,8 +85424,8 @@ async function realesrganUpscale(path6, opts) {
|
|
|
84660
85424
|
const scale = opts.scale ?? 2;
|
|
84661
85425
|
const dir2 = opts.outDir ?? workDir();
|
|
84662
85426
|
const fin = join36(dir2, "in"), fup = join36(dir2, "up");
|
|
84663
|
-
|
|
84664
|
-
|
|
85427
|
+
mkdirSync20(fin, { recursive: true });
|
|
85428
|
+
mkdirSync20(fup, { recursive: true });
|
|
84665
85429
|
const fps = p.fps ?? 30;
|
|
84666
85430
|
const src = path6;
|
|
84667
85431
|
let extractSrc = src;
|
|
@@ -84728,7 +85492,7 @@ async function falTopazEnhance(path6, spec, opts) {
|
|
|
84728
85492
|
path6 = requireAbsolutePath(path6, "path");
|
|
84729
85493
|
const p = await probeMedia(path6);
|
|
84730
85494
|
opts.onProgress?.(3, "Uploading to fal\u2026");
|
|
84731
|
-
const bytes2 =
|
|
85495
|
+
const bytes2 = readFileSync28(path6);
|
|
84732
85496
|
const videoUrl = await falUploadVideo(new Uint8Array(bytes2), "video/mp4", { apiKey: opts.apiKey });
|
|
84733
85497
|
opts.onProgress?.(12, "Submitting Topaz job\u2026");
|
|
84734
85498
|
const sub = await falTopazSubmit({ ...spec, videoUrl }, { apiKey: opts.apiKey });
|
|
@@ -84755,7 +85519,7 @@ async function falTopazEnhance(path6, spec, opts) {
|
|
|
84755
85519
|
if (!dl.ok)
|
|
84756
85520
|
throw new Error(`Downloading the fal result failed (HTTP ${dl.status}).`);
|
|
84757
85521
|
const dir2 = opts.outDir ?? workDir();
|
|
84758
|
-
|
|
85522
|
+
mkdirSync20(dir2, { recursive: true });
|
|
84759
85523
|
const outPath = join36(dir2, "enhanced.mp4");
|
|
84760
85524
|
const { writeFileSync: writeFileSync43 } = await import("node:fs");
|
|
84761
85525
|
writeFileSync43(outPath, Buffer.from(await dl.arrayBuffer()));
|
|
@@ -84801,7 +85565,7 @@ async function smartEnhance(path6, args) {
|
|
|
84801
85565
|
}
|
|
84802
85566
|
|
|
84803
85567
|
// ../../packages/host-core/dist/video-effects.js
|
|
84804
|
-
import { readFileSync as
|
|
85568
|
+
import { readFileSync as readFileSync29, mkdirSync as mkdirSync21, writeFileSync as writeFileSync21 } from "node:fs";
|
|
84805
85569
|
import { join as join37, basename as basename5, extname } from "node:path";
|
|
84806
85570
|
init_daemon_settings();
|
|
84807
85571
|
var IMG_MIME = { jpg: "image/jpeg", jpeg: "image/jpeg", png: "image/png", webp: "image/webp", heic: "image/heic" };
|
|
@@ -84840,11 +85604,11 @@ async function applyEffect(effectId, inputs, opts) {
|
|
|
84840
85604
|
const imageUrls = [];
|
|
84841
85605
|
for (const p of imgs.slice(0, needImgs || imgs.length)) {
|
|
84842
85606
|
const ext2 = extname(p).slice(1).toLowerCase();
|
|
84843
|
-
imageUrls.push(await falUploadVideo(new Uint8Array(
|
|
85607
|
+
imageUrls.push(await falUploadVideo(new Uint8Array(readFileSync29(p)), IMG_MIME[ext2] ?? "image/jpeg", { apiKey: key2, fileName: basename5(p) }));
|
|
84844
85608
|
}
|
|
84845
85609
|
let videoUrl;
|
|
84846
85610
|
if (inputs.videoPath)
|
|
84847
|
-
videoUrl = await falUploadVideo(new Uint8Array(
|
|
85611
|
+
videoUrl = await falUploadVideo(new Uint8Array(readFileSync29(inputs.videoPath)), "video/mp4", { apiKey: key2, fileName: basename5(inputs.videoPath) });
|
|
84848
85612
|
const body = { ...def.params };
|
|
84849
85613
|
const usesImageArray = def.modelPath.includes("/vidu/") || def.modelPath.includes("/kling-video/") || def.modelPath.includes("nano-banana");
|
|
84850
85614
|
const arrayKey = def.modelPath.includes("nano-banana") ? "image_urls" : "input_image_urls";
|
|
@@ -84888,7 +85652,7 @@ async function applyEffect(effectId, inputs, opts) {
|
|
|
84888
85652
|
if (!dl.ok)
|
|
84889
85653
|
throw new Error(`Downloading the result failed (HTTP ${dl.status}).`);
|
|
84890
85654
|
const dir2 = opts?.outDir ?? workDir();
|
|
84891
|
-
|
|
85655
|
+
mkdirSync21(dir2, { recursive: true });
|
|
84892
85656
|
const ext = media.isVideo ? "mp4" : extname(new URL(media.url).pathname).slice(1) || "png";
|
|
84893
85657
|
const outPath = join37(dir2, `${effectId}.${ext}`);
|
|
84894
85658
|
writeFileSync21(outPath, Buffer.from(await dl.arrayBuffer()));
|
|
@@ -84913,9 +85677,9 @@ async function applyGeminiImageEffect(def, inputs, opts) {
|
|
|
84913
85677
|
${inputs.prompt}` : "");
|
|
84914
85678
|
opts?.onProgress?.(10, `Generating ${def.label}\u2026`);
|
|
84915
85679
|
const provider = createImageEditProvider("google", { apiKey: key2, model: def.modelPath });
|
|
84916
|
-
const out = await runImageEdit(provider, { op: "prompt", imageB64:
|
|
85680
|
+
const out = await runImageEdit(provider, { op: "prompt", imageB64: readFileSync29(imgPath).toString("base64"), mime: IMG_MIME[ext] ?? "image/jpeg", prompt });
|
|
84917
85681
|
const dir2 = opts?.outDir ?? workDir();
|
|
84918
|
-
|
|
85682
|
+
mkdirSync21(dir2, { recursive: true });
|
|
84919
85683
|
const outPath = join37(dir2, `${def.id}.png`);
|
|
84920
85684
|
writeFileSync21(outPath, Buffer.from(out.bytes));
|
|
84921
85685
|
opts?.onProgress?.(100, "Done");
|
|
@@ -85035,13 +85799,13 @@ ${compact2}`;
|
|
|
85035
85799
|
}
|
|
85036
85800
|
|
|
85037
85801
|
// ../../packages/host-core/dist/video-vision.js
|
|
85038
|
-
import { readFileSync as
|
|
85802
|
+
import { readFileSync as readFileSync30 } from "node:fs";
|
|
85039
85803
|
var BASE_URL3 = "https://generativelanguage.googleapis.com/v1beta";
|
|
85040
85804
|
var MODEL = "gemini-3.5-flash";
|
|
85041
85805
|
var TIMEOUT_MS = 6e4;
|
|
85042
85806
|
async function reviewFrameGemini(framePath, intent, apiKey) {
|
|
85043
85807
|
try {
|
|
85044
|
-
const b642 =
|
|
85808
|
+
const b642 = readFileSync30(framePath).toString("base64");
|
|
85045
85809
|
const prompt = `This is a frame from an AI-generated video clip meant to show: "${intent}". Judge ONLY for obvious defects: melted/warped faces or hands, garbled text, broken anatomy, severe artifacts. Reply with STRICT JSON: {"acceptable": <true|false>, "note": "<\u226412 words, only if not acceptable>"}.`;
|
|
85046
85810
|
const res = await fetch(`${BASE_URL3}/models/${MODEL}:generateContent`, {
|
|
85047
85811
|
method: "POST",
|
|
@@ -85088,8 +85852,8 @@ function readDaemonKeyFile(name) {
|
|
|
85088
85852
|
try {
|
|
85089
85853
|
const home = tesseractHome();
|
|
85090
85854
|
const f = join38(home, "daemon", name);
|
|
85091
|
-
if (
|
|
85092
|
-
const k =
|
|
85855
|
+
if (existsSync17(f)) {
|
|
85856
|
+
const k = readFileSync31(f, "utf-8").trim();
|
|
85093
85857
|
if (k)
|
|
85094
85858
|
return k;
|
|
85095
85859
|
}
|
|
@@ -85248,7 +86012,7 @@ function createDaemonVideoEditRunner() {
|
|
|
85248
86012
|
if (!apiKey)
|
|
85249
86013
|
return { ok: false, error: "Voice cloning needs an ElevenLabs key (Settings \u2192 Voice)." };
|
|
85250
86014
|
try {
|
|
85251
|
-
const samples = sampleAudioPaths.slice(0, 25).map((p) => requireAbsolutePath(p, "sample audio path")).map((p) => ({ bytes: new Uint8Array(
|
|
86015
|
+
const samples = sampleAudioPaths.slice(0, 25).map((p) => requireAbsolutePath(p, "sample audio path")).map((p) => ({ bytes: new Uint8Array(readFileSync31(p)), mime: audioMimeForPath(p), filename: basename6(p) }));
|
|
85252
86016
|
const v = await cloneVoiceElevenLabs(name, samples, { apiKey, description });
|
|
85253
86017
|
return { ok: true, voiceId: v.voiceId, name: v.name };
|
|
85254
86018
|
} catch (e) {
|
|
@@ -85344,7 +86108,7 @@ function createDaemonVideoEditRunner() {
|
|
|
85344
86108
|
|
|
85345
86109
|
// ../../packages/host-core/dist/support-submit.js
|
|
85346
86110
|
init_credentials();
|
|
85347
|
-
import { openSync as
|
|
86111
|
+
import { openSync as openSync5, fstatSync, readSync as readSync4, closeSync as closeSync5 } from "node:fs";
|
|
85348
86112
|
import { join as join39 } from "node:path";
|
|
85349
86113
|
|
|
85350
86114
|
// ../../packages/host-core/dist/host-metrics.js
|
|
@@ -85384,19 +86148,19 @@ var LOG_TAIL_BYTES = 64 * 1024;
|
|
|
85384
86148
|
function tail2(path6, bytes2 = LOG_TAIL_BYTES) {
|
|
85385
86149
|
let fd = null;
|
|
85386
86150
|
try {
|
|
85387
|
-
fd =
|
|
86151
|
+
fd = openSync5(path6, "r");
|
|
85388
86152
|
const size = fstatSync(fd).size;
|
|
85389
86153
|
const len = Math.min(size, bytes2);
|
|
85390
86154
|
const start3 = Math.max(0, size - len);
|
|
85391
86155
|
const buf = Buffer.alloc(len);
|
|
85392
|
-
|
|
86156
|
+
readSync4(fd, buf, 0, len, start3);
|
|
85393
86157
|
return buf.toString("utf8");
|
|
85394
86158
|
} catch {
|
|
85395
86159
|
return "";
|
|
85396
86160
|
} finally {
|
|
85397
86161
|
if (fd !== null) {
|
|
85398
86162
|
try {
|
|
85399
|
-
|
|
86163
|
+
closeSync5(fd);
|
|
85400
86164
|
} catch {
|
|
85401
86165
|
}
|
|
85402
86166
|
}
|
|
@@ -86291,9 +87055,9 @@ async function replayTurn(turn) {
|
|
|
86291
87055
|
} catch {
|
|
86292
87056
|
}
|
|
86293
87057
|
for (const msg of terminal) {
|
|
86294
|
-
for (const
|
|
87058
|
+
for (const sink2 of [...sinks]) {
|
|
86295
87059
|
try {
|
|
86296
|
-
|
|
87060
|
+
sink2(msg, turn.params.origin);
|
|
86297
87061
|
} catch {
|
|
86298
87062
|
}
|
|
86299
87063
|
}
|
|
@@ -86333,10 +87097,10 @@ function drainBrowserEvents(params) {
|
|
|
86333
87097
|
return events;
|
|
86334
87098
|
}
|
|
86335
87099
|
setBrowserExtensionProbe(() => extensionBrowserConn != null);
|
|
86336
|
-
function registerAgentSink(
|
|
86337
|
-
sinks.add(
|
|
87100
|
+
function registerAgentSink(sink2) {
|
|
87101
|
+
sinks.add(sink2);
|
|
86338
87102
|
return () => {
|
|
86339
|
-
sinks.delete(
|
|
87103
|
+
sinks.delete(sink2);
|
|
86340
87104
|
};
|
|
86341
87105
|
}
|
|
86342
87106
|
function emitAgentEvent(msg, origin) {
|
|
@@ -86587,7 +87351,7 @@ function refreshDaemonScheduling(b) {
|
|
|
86587
87351
|
function daemonWorkspaceDir() {
|
|
86588
87352
|
const dir2 = tessPath("workspace");
|
|
86589
87353
|
try {
|
|
86590
|
-
|
|
87354
|
+
mkdirSync22(dir2, { recursive: true });
|
|
86591
87355
|
} catch {
|
|
86592
87356
|
}
|
|
86593
87357
|
return dir2;
|
|
@@ -86619,9 +87383,9 @@ function voiceUnavailableFrames(err2, reason) {
|
|
|
86619
87383
|
|
|
86620
87384
|
// ../../packages/host-core/dist/fs-remote.js
|
|
86621
87385
|
import { readdir as readdir4, readFile as readFile10, writeFile as writeFile9, mkdir as mkdir8, cp, rm as rm2, rename as renameAsync, stat as stat3 } from "node:fs/promises";
|
|
86622
|
-
import { openSync as
|
|
87386
|
+
import { openSync as openSync6, readSync as readSync5, writeSync, closeSync as closeSync6, statSync as statSync9, existsSync as existsSync18, mkdtempSync, rmSync as rmSync5, readFileSync as readFileSync32, readdirSync as readdirSync8, watch, realpathSync as realpathSync4, constants as fsConstants } from "node:fs";
|
|
86623
87387
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
86624
|
-
import { basename as basename7, dirname as
|
|
87388
|
+
import { basename as basename7, dirname as dirname16, join as join42, relative as relative5, resolve as resolve8, sep as sep6, isAbsolute as isAbsolute6 } from "node:path";
|
|
86625
87389
|
import { execFile as execFile5 } from "node:child_process";
|
|
86626
87390
|
import { promisify as promisify2 } from "node:util";
|
|
86627
87391
|
|
|
@@ -86673,12 +87437,12 @@ async function dirStats(root, opts) {
|
|
|
86673
87437
|
}
|
|
86674
87438
|
async function codeStats(root) {
|
|
86675
87439
|
const start3 = Date.now();
|
|
86676
|
-
const MAX_FILES = 25e3,
|
|
87440
|
+
const MAX_FILES = 25e3, MAX_BYTES3 = 256 * 1024 * 1024, TIME_MS = 12e3;
|
|
86677
87441
|
const byLang = /* @__PURE__ */ new Map();
|
|
86678
87442
|
let totalFiles = 0, totalLines = 0, bytes2 = 0, truncated = false;
|
|
86679
87443
|
const stack = [root];
|
|
86680
87444
|
while (stack.length) {
|
|
86681
|
-
if (totalFiles >= MAX_FILES || bytes2 >=
|
|
87445
|
+
if (totalFiles >= MAX_FILES || bytes2 >= MAX_BYTES3 || Date.now() - start3 > TIME_MS) {
|
|
86682
87446
|
truncated = true;
|
|
86683
87447
|
break;
|
|
86684
87448
|
}
|
|
@@ -86690,7 +87454,7 @@ async function codeStats(root) {
|
|
|
86690
87454
|
continue;
|
|
86691
87455
|
}
|
|
86692
87456
|
for (const e of ents) {
|
|
86693
|
-
if (totalFiles >= MAX_FILES || bytes2 >=
|
|
87457
|
+
if (totalFiles >= MAX_FILES || bytes2 >= MAX_BYTES3 || Date.now() - start3 > TIME_MS) {
|
|
86694
87458
|
truncated = true;
|
|
86695
87459
|
break;
|
|
86696
87460
|
}
|
|
@@ -86921,14 +87685,14 @@ function resolveParent(raw, root) {
|
|
|
86921
87685
|
}
|
|
86922
87686
|
function resolveUniqueName(dir2, name) {
|
|
86923
87687
|
const direct = join42(dir2, name);
|
|
86924
|
-
if (!
|
|
87688
|
+
if (!existsSync18(direct))
|
|
86925
87689
|
return direct;
|
|
86926
87690
|
const dot = name.lastIndexOf(".");
|
|
86927
87691
|
const base = dot > 0 ? name.slice(0, dot) : name;
|
|
86928
87692
|
const ext = dot > 0 ? name.slice(dot) : "";
|
|
86929
87693
|
for (let i = 2; i < 1e4; i++) {
|
|
86930
87694
|
const candidate = join42(dir2, `${base} ${i}${ext}`);
|
|
86931
|
-
if (!
|
|
87695
|
+
if (!existsSync18(candidate))
|
|
86932
87696
|
return candidate;
|
|
86933
87697
|
}
|
|
86934
87698
|
return direct;
|
|
@@ -86962,7 +87726,7 @@ async function readRemoteBytes(root, path6) {
|
|
|
86962
87726
|
if (!real)
|
|
86963
87727
|
return { error: "Path is outside the shared root." };
|
|
86964
87728
|
try {
|
|
86965
|
-
const s =
|
|
87729
|
+
const s = statSync9(real);
|
|
86966
87730
|
if (!s.isFile())
|
|
86967
87731
|
return { error: "Not a file" };
|
|
86968
87732
|
if (s.size > REMOTE_READ_CAP)
|
|
@@ -86974,7 +87738,7 @@ async function readRemoteBytes(root, path6) {
|
|
|
86974
87738
|
}
|
|
86975
87739
|
var trashSeq = 0;
|
|
86976
87740
|
function statId(real) {
|
|
86977
|
-
const s =
|
|
87741
|
+
const s = statSync9(real, { bigint: true });
|
|
86978
87742
|
return {
|
|
86979
87743
|
size: Number(s.size),
|
|
86980
87744
|
mtimeMs: Number(s.mtimeMs),
|
|
@@ -87005,7 +87769,7 @@ async function renderThumbnailImpl(real, maxPx) {
|
|
|
87005
87769
|
const produced = readdirSync8(dir2).find((f) => f.toLowerCase().endsWith(".png"));
|
|
87006
87770
|
if (!produced)
|
|
87007
87771
|
return { error: "No thumbnail available." };
|
|
87008
|
-
return { png:
|
|
87772
|
+
return { png: readFileSync32(join42(dir2, produced)).toString("base64") };
|
|
87009
87773
|
} catch (err2) {
|
|
87010
87774
|
return { error: String(err2.message) };
|
|
87011
87775
|
} finally {
|
|
@@ -87046,7 +87810,7 @@ var SAFE_SEG = /^[A-Za-z0-9._-]+$/;
|
|
|
87046
87810
|
var TRASH_RETENTION_MS = 14 * 24 * 60 * 60 * 1e3;
|
|
87047
87811
|
function pruneTrash(root) {
|
|
87048
87812
|
const trashDir = join42(root, TRASH_DIR);
|
|
87049
|
-
if (!
|
|
87813
|
+
if (!existsSync18(trashDir))
|
|
87050
87814
|
return;
|
|
87051
87815
|
const cutoff = Date.now() - TRASH_RETENTION_MS;
|
|
87052
87816
|
try {
|
|
@@ -87054,7 +87818,7 @@ function pruneTrash(root) {
|
|
|
87054
87818
|
if (!e.isDirectory())
|
|
87055
87819
|
continue;
|
|
87056
87820
|
try {
|
|
87057
|
-
const meta4 = JSON.parse(
|
|
87821
|
+
const meta4 = JSON.parse(readFileSync32(join42(trashDir, e.name, ".fp-meta.json"), "utf-8"));
|
|
87058
87822
|
if ((meta4.deletedAt ?? 0) < cutoff)
|
|
87059
87823
|
rmSync5(join42(trashDir, e.name), { recursive: true, force: true });
|
|
87060
87824
|
} catch {
|
|
@@ -87121,7 +87885,7 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
|
|
|
87121
87885
|
if (BINARY_EXT.has(ext))
|
|
87122
87886
|
return { error: "Binary file \u2014 not shown in the editor." };
|
|
87123
87887
|
try {
|
|
87124
|
-
const s =
|
|
87888
|
+
const s = statSync9(real);
|
|
87125
87889
|
if (s.size > TEXT_SIZE_LIMIT)
|
|
87126
87890
|
return { error: "File too large for text view." };
|
|
87127
87891
|
return { content: await readFile10(real, "utf-8") };
|
|
@@ -87136,7 +87900,7 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
|
|
|
87136
87900
|
if (!real)
|
|
87137
87901
|
return OUTSIDE("write");
|
|
87138
87902
|
try {
|
|
87139
|
-
await mkdir8(
|
|
87903
|
+
await mkdir8(dirname16(real), { recursive: true });
|
|
87140
87904
|
await writeFile9(real, content, "utf-8");
|
|
87141
87905
|
return { ok: true };
|
|
87142
87906
|
} catch (err2) {
|
|
@@ -87150,7 +87914,7 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
|
|
|
87150
87914
|
if (!real)
|
|
87151
87915
|
return OUTSIDE("write");
|
|
87152
87916
|
try {
|
|
87153
|
-
await mkdir8(
|
|
87917
|
+
await mkdir8(dirname16(real), { recursive: true });
|
|
87154
87918
|
await writeFile9(real, Buffer.from(base643, "base64"));
|
|
87155
87919
|
return { ok: true };
|
|
87156
87920
|
} catch (err2) {
|
|
@@ -87167,10 +87931,10 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
|
|
|
87167
87931
|
let fd = null;
|
|
87168
87932
|
try {
|
|
87169
87933
|
if (off === 0) {
|
|
87170
|
-
await mkdir8(
|
|
87171
|
-
fd =
|
|
87934
|
+
await mkdir8(dirname16(real), { recursive: true });
|
|
87935
|
+
fd = openSync6(real, "w");
|
|
87172
87936
|
} else
|
|
87173
|
-
fd =
|
|
87937
|
+
fd = openSync6(real, "r+");
|
|
87174
87938
|
if (buf.length > 0)
|
|
87175
87939
|
writeSync(fd, buf, 0, buf.length, off);
|
|
87176
87940
|
return { ok: true, bytesWritten: buf.length };
|
|
@@ -87179,7 +87943,7 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
|
|
|
87179
87943
|
} finally {
|
|
87180
87944
|
if (fd != null)
|
|
87181
87945
|
try {
|
|
87182
|
-
|
|
87946
|
+
closeSync6(fd);
|
|
87183
87947
|
} catch {
|
|
87184
87948
|
}
|
|
87185
87949
|
}
|
|
@@ -87221,16 +87985,16 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
|
|
|
87221
87985
|
return { base64: "", bytesRead: 0 };
|
|
87222
87986
|
let fd = null;
|
|
87223
87987
|
try {
|
|
87224
|
-
fd =
|
|
87988
|
+
fd = openSync6(real, "r");
|
|
87225
87989
|
const buf = Buffer.alloc(len);
|
|
87226
|
-
const bytesRead =
|
|
87990
|
+
const bytesRead = readSync5(fd, buf, 0, len, off);
|
|
87227
87991
|
return { base64: buf.subarray(0, bytesRead).toString("base64"), bytesRead };
|
|
87228
87992
|
} catch (err2) {
|
|
87229
87993
|
return { error: String(err2.message) };
|
|
87230
87994
|
} finally {
|
|
87231
87995
|
if (fd != null)
|
|
87232
87996
|
try {
|
|
87233
|
-
|
|
87997
|
+
closeSync6(fd);
|
|
87234
87998
|
} catch {
|
|
87235
87999
|
}
|
|
87236
88000
|
}
|
|
@@ -87241,7 +88005,7 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
|
|
|
87241
88005
|
if (!real)
|
|
87242
88006
|
return { error: "Path is outside the shared root." };
|
|
87243
88007
|
try {
|
|
87244
|
-
const s =
|
|
88008
|
+
const s = statSync9(real);
|
|
87245
88009
|
if (s.size > REMOTE_READ_CAP)
|
|
87246
88010
|
return { error: `File is too large to read whole over the network (${(s.size / 1024 / 1024).toFixed(1)} MB) \u2014 open it locally.` };
|
|
87247
88011
|
return { base64: (await readFile10(real)).toString("base64"), size: s.size };
|
|
@@ -87257,7 +88021,7 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
|
|
|
87257
88021
|
const target = join42(parent, name);
|
|
87258
88022
|
if (!insideOk(target))
|
|
87259
88023
|
return { ok: false, error: "Refusing to create a project outside the shared root." };
|
|
87260
|
-
if (
|
|
88024
|
+
if (existsSync18(target))
|
|
87261
88025
|
return { ok: false, error: `A folder named "${name}" already exists.` };
|
|
87262
88026
|
try {
|
|
87263
88027
|
await mkdir8(target, { recursive: true });
|
|
@@ -87275,7 +88039,7 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
|
|
|
87275
88039
|
const target = join42(parent, name);
|
|
87276
88040
|
if (!insideOk(target))
|
|
87277
88041
|
return OUTSIDE("create");
|
|
87278
|
-
if (
|
|
88042
|
+
if (existsSync18(target))
|
|
87279
88043
|
return { ok: false, error: `"${name}" already exists.` };
|
|
87280
88044
|
try {
|
|
87281
88045
|
if (op === "createFile")
|
|
@@ -87294,8 +88058,8 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
|
|
|
87294
88058
|
return { ok: false, error: "Invalid name." };
|
|
87295
88059
|
if (!insideOk(oldPath))
|
|
87296
88060
|
return OUTSIDE("rename");
|
|
87297
|
-
const newPath = join42(
|
|
87298
|
-
if (
|
|
88061
|
+
const newPath = join42(dirname16(oldPath), newName);
|
|
88062
|
+
if (existsSync18(newPath))
|
|
87299
88063
|
return { ok: false, error: `A file named "${newName}" already exists.` };
|
|
87300
88064
|
try {
|
|
87301
88065
|
await renameAsync(oldPath, newPath);
|
|
@@ -87341,7 +88105,7 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
|
|
|
87341
88105
|
}
|
|
87342
88106
|
case "listTrash": {
|
|
87343
88107
|
const trashDir = join42(root, TRASH_DIR);
|
|
87344
|
-
if (!
|
|
88108
|
+
if (!existsSync18(trashDir))
|
|
87345
88109
|
return [];
|
|
87346
88110
|
try {
|
|
87347
88111
|
const out = [];
|
|
@@ -87349,7 +88113,7 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
|
|
|
87349
88113
|
if (!e.isDirectory())
|
|
87350
88114
|
continue;
|
|
87351
88115
|
try {
|
|
87352
|
-
const meta4 = JSON.parse(
|
|
88116
|
+
const meta4 = JSON.parse(readFileSync32(join42(trashDir, e.name, ".fp-meta.json"), "utf-8"));
|
|
87353
88117
|
out.push({ trashId: e.name, name: meta4.name, path: join42(trashDir, e.name, meta4.name), originalPath: meta4.originalPath, deletedAt: meta4.deletedAt });
|
|
87354
88118
|
} catch {
|
|
87355
88119
|
}
|
|
@@ -87364,19 +88128,19 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
|
|
|
87364
88128
|
if (!SAFE_SEG.test(id))
|
|
87365
88129
|
return { ok: false, error: "Bad trash id." };
|
|
87366
88130
|
const itemDir = join42(root, TRASH_DIR, id);
|
|
87367
|
-
if (!
|
|
88131
|
+
if (!existsSync18(itemDir))
|
|
87368
88132
|
return { ok: false, error: "Not in trash." };
|
|
87369
88133
|
try {
|
|
87370
|
-
const meta4 = JSON.parse(
|
|
88134
|
+
const meta4 = JSON.parse(readFileSync32(join42(itemDir, ".fp-meta.json"), "utf-8"));
|
|
87371
88135
|
if (!validName(meta4.name))
|
|
87372
88136
|
return { ok: false, error: "Bad trashed name." };
|
|
87373
88137
|
const src = join42(itemDir, meta4.name);
|
|
87374
88138
|
let dest = meta4.originalPath;
|
|
87375
88139
|
if (!insideOk(dest))
|
|
87376
88140
|
return OUTSIDE("restore");
|
|
87377
|
-
if (
|
|
87378
|
-
dest = resolveUniqueName(
|
|
87379
|
-
await mkdir8(
|
|
88141
|
+
if (existsSync18(dest))
|
|
88142
|
+
dest = resolveUniqueName(dirname16(dest), meta4.name);
|
|
88143
|
+
await mkdir8(dirname16(dest), { recursive: true });
|
|
87380
88144
|
await moveItem(src, dest);
|
|
87381
88145
|
rmSync5(itemDir, { recursive: true, force: true });
|
|
87382
88146
|
return { ok: true, path: dest };
|
|
@@ -87397,7 +88161,7 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
|
|
|
87397
88161
|
continue;
|
|
87398
88162
|
if (!insideOk(src))
|
|
87399
88163
|
return OUTSIDE(op === "copyPaths" ? "copy from" : "move from");
|
|
87400
|
-
if (op === "movePaths" &&
|
|
88164
|
+
if (op === "movePaths" && dirname16(src) === destDir) {
|
|
87401
88165
|
newPaths.push(src);
|
|
87402
88166
|
continue;
|
|
87403
88167
|
}
|
|
@@ -87678,8 +88442,8 @@ function releaseDcClient(clientId) {
|
|
|
87678
88442
|
|
|
87679
88443
|
// ../../packages/host-core/dist/fs-transfer.js
|
|
87680
88444
|
import { readdir as readdir5, lstat as lstat2, mkdir as mkdir9, chmod, rm as rm3, readlink, symlink, stat as stat4 } from "node:fs/promises";
|
|
87681
|
-
import { openSync as
|
|
87682
|
-
import { basename as basename8, dirname as
|
|
88445
|
+
import { openSync as openSync7, readSync as readSync6, closeSync as closeSync7, existsSync as existsSync19, createWriteStream } from "node:fs";
|
|
88446
|
+
import { basename as basename8, dirname as dirname17, join as join44, relative as relative7, sep as sep8 } from "node:path";
|
|
87683
88447
|
|
|
87684
88448
|
// ../../packages/host-core/dist/active-link/paths.js
|
|
87685
88449
|
init_base_paths();
|
|
@@ -87735,7 +88499,7 @@ function clearTimer(t) {
|
|
|
87735
88499
|
}
|
|
87736
88500
|
function uniqueDir(parent, name) {
|
|
87737
88501
|
let candidate = join44(parent, name);
|
|
87738
|
-
for (let i = 2;
|
|
88502
|
+
for (let i = 2; existsSync19(candidate) && i < 1e4; i++)
|
|
87739
88503
|
candidate = join44(parent, `${name} ${i}`);
|
|
87740
88504
|
return candidate;
|
|
87741
88505
|
}
|
|
@@ -87744,7 +88508,7 @@ function uniqueFile(parent, name) {
|
|
|
87744
88508
|
const stem = dot > 0 ? name.slice(0, dot) : name;
|
|
87745
88509
|
const ext = dot > 0 ? name.slice(dot) : "";
|
|
87746
88510
|
let candidate = join44(parent, name);
|
|
87747
|
-
for (let i = 2;
|
|
88511
|
+
for (let i = 2; existsSync19(candidate) && i < 1e4; i++)
|
|
87748
88512
|
candidate = join44(parent, `${stem} ${i}${ext}`);
|
|
87749
88513
|
return candidate;
|
|
87750
88514
|
}
|
|
@@ -87874,7 +88638,7 @@ async function startOutboundTransfer(msg, controllerClientId, ownHostId2, hostRo
|
|
|
87874
88638
|
producers.delete(transferId);
|
|
87875
88639
|
return;
|
|
87876
88640
|
}
|
|
87877
|
-
const srcBase = manifest.singleFile ?
|
|
88641
|
+
const srcBase = manifest.singleFile ? dirname17(srcPath) : srcPath;
|
|
87878
88642
|
send4({
|
|
87879
88643
|
type: "fs:transferManifest",
|
|
87880
88644
|
transferId,
|
|
@@ -87902,7 +88666,7 @@ async function startOutboundTransfer(msg, controllerClientId, ownHostId2, hostRo
|
|
|
87902
88666
|
const abs = join44(srcBase, f.rel.split("/").join(sep8));
|
|
87903
88667
|
let fd = null;
|
|
87904
88668
|
try {
|
|
87905
|
-
fd =
|
|
88669
|
+
fd = openSync7(abs, "r");
|
|
87906
88670
|
if (f.size === 0) {
|
|
87907
88671
|
send4({ type: "fs:transferChunk", transferId, toHost, fileIx, rel: f.rel, mode: f.mode, kind: "file", offset: 0, base64: "", eof: true }, { hostId: toHost });
|
|
87908
88672
|
} else {
|
|
@@ -87912,7 +88676,7 @@ async function startOutboundTransfer(msg, controllerClientId, ownHostId2, hostRo
|
|
|
87912
88676
|
break;
|
|
87913
88677
|
const len = Math.min(CHUNK2, f.size - offset);
|
|
87914
88678
|
const buf = Buffer.alloc(len);
|
|
87915
|
-
const read =
|
|
88679
|
+
const read = readSync6(fd, buf, 0, len, offset);
|
|
87916
88680
|
send4({ type: "fs:transferChunk", transferId, toHost, fileIx, rel: f.rel, mode: f.mode, kind: "file", offset, base64: buf.subarray(0, read).toString("base64"), eof: offset + len >= f.size }, { hostId: toHost });
|
|
87917
88681
|
state3.sentBytes += read;
|
|
87918
88682
|
}
|
|
@@ -87920,7 +88684,7 @@ async function startOutboundTransfer(msg, controllerClientId, ownHostId2, hostRo
|
|
|
87920
88684
|
} catch (e) {
|
|
87921
88685
|
if (fd != null)
|
|
87922
88686
|
try {
|
|
87923
|
-
|
|
88687
|
+
closeSync7(fd);
|
|
87924
88688
|
} catch {
|
|
87925
88689
|
}
|
|
87926
88690
|
failProducer(transferId, `Couldn't read ${f.rel}: ${e.message}`);
|
|
@@ -87928,7 +88692,7 @@ async function startOutboundTransfer(msg, controllerClientId, ownHostId2, hostRo
|
|
|
87928
88692
|
} finally {
|
|
87929
88693
|
if (fd != null)
|
|
87930
88694
|
try {
|
|
87931
|
-
|
|
88695
|
+
closeSync7(fd);
|
|
87932
88696
|
} catch {
|
|
87933
88697
|
}
|
|
87934
88698
|
}
|
|
@@ -88041,7 +88805,7 @@ async function beginInboundTransfer(msg, hostRoot, send4) {
|
|
|
88041
88805
|
if (msg.singleFile) {
|
|
88042
88806
|
let destFile = join44(parent, msg.destName);
|
|
88043
88807
|
let createdFile = true;
|
|
88044
|
-
if (
|
|
88808
|
+
if (existsSync19(destFile)) {
|
|
88045
88809
|
if (msg.onCollision === "abort") {
|
|
88046
88810
|
failNoState(`"${msg.destName}" already exists on the destination.`);
|
|
88047
88811
|
return;
|
|
@@ -88066,7 +88830,7 @@ async function beginInboundTransfer(msg, hostRoot, send4) {
|
|
|
88066
88830
|
}
|
|
88067
88831
|
let destRoot = join44(parent, msg.destName);
|
|
88068
88832
|
let createdRoot = false;
|
|
88069
|
-
if (
|
|
88833
|
+
if (existsSync19(destRoot)) {
|
|
88070
88834
|
if (msg.onCollision === "abort") {
|
|
88071
88835
|
failNoState(`"${msg.destName}" already exists on the destination.`);
|
|
88072
88836
|
return;
|
|
@@ -88112,9 +88876,9 @@ async function writeInboundChunk(msg, send4) {
|
|
|
88112
88876
|
try {
|
|
88113
88877
|
if (msg.kind === "symlink") {
|
|
88114
88878
|
const target = Buffer.from(msg.base64, "base64").toString("utf-8");
|
|
88115
|
-
const resolved = join44(
|
|
88879
|
+
const resolved = join44(dirname17(abs), target);
|
|
88116
88880
|
if (isInsideRoot(resolved, s.destRoot)) {
|
|
88117
|
-
await mkdir9(
|
|
88881
|
+
await mkdir9(dirname17(abs), { recursive: true }).catch(() => {
|
|
88118
88882
|
});
|
|
88119
88883
|
await symlink(target, abs).catch(() => {
|
|
88120
88884
|
});
|
|
@@ -88127,7 +88891,7 @@ async function writeInboundChunk(msg, send4) {
|
|
|
88127
88891
|
if (s.curIx !== msg.fileIx || !s.curStream) {
|
|
88128
88892
|
if (s.curStream)
|
|
88129
88893
|
await new Promise((r) => s.curStream.end(r));
|
|
88130
|
-
await mkdir9(
|
|
88894
|
+
await mkdir9(dirname17(abs), { recursive: true }).catch(() => {
|
|
88131
88895
|
});
|
|
88132
88896
|
s.curStream = createWriteStream(abs);
|
|
88133
88897
|
s.curIx = msg.fileIx;
|
|
@@ -88723,12 +89487,12 @@ init_credentials();
|
|
|
88723
89487
|
init_credentials();
|
|
88724
89488
|
import { hostname as hostname3, platform } from "node:os";
|
|
88725
89489
|
import { randomUUID as randomUUID21 } from "node:crypto";
|
|
88726
|
-
import { chmodSync as chmodSync3, existsSync as
|
|
89490
|
+
import { chmodSync as chmodSync3, existsSync as existsSync21, mkdirSync as mkdirSync24, readFileSync as readFileSync34, writeFileSync as writeFileSync23 } from "node:fs";
|
|
88727
89491
|
import { join as join46 } from "node:path";
|
|
88728
89492
|
var FILE = () => join46(daemonDir2(), "machine-identity.json");
|
|
88729
89493
|
function readMachineIdentity() {
|
|
88730
89494
|
try {
|
|
88731
|
-
const m = JSON.parse(
|
|
89495
|
+
const m = JSON.parse(readFileSync34(FILE(), "utf-8"));
|
|
88732
89496
|
return m?.deviceToken && m?.publicId ? m : null;
|
|
88733
89497
|
} catch {
|
|
88734
89498
|
return null;
|
|
@@ -88736,7 +89500,7 @@ function readMachineIdentity() {
|
|
|
88736
89500
|
}
|
|
88737
89501
|
function write(m) {
|
|
88738
89502
|
try {
|
|
88739
|
-
|
|
89503
|
+
mkdirSync24(daemonDir2(), { recursive: true, mode: 448 });
|
|
88740
89504
|
writeFileSync23(FILE(), JSON.stringify(m, null, 2), { mode: 384 });
|
|
88741
89505
|
chmodSync3(FILE(), 384);
|
|
88742
89506
|
} catch {
|
|
@@ -88832,14 +89596,14 @@ function getMachinePublicId() {
|
|
|
88832
89596
|
|
|
88833
89597
|
// ../../packages/host-core/dist/active-link/engine.js
|
|
88834
89598
|
import { lstat as lstat7, readlink as readlink4, rm as rm4, mkdir as mkdir11, symlink as symlink2, rename as rename2, utimes as utimes2, writeFile as writeFile10 } from "node:fs/promises";
|
|
88835
|
-
import { existsSync as
|
|
88836
|
-
import { dirname as
|
|
89599
|
+
import { existsSync as existsSync23 } from "node:fs";
|
|
89600
|
+
import { dirname as dirname22, join as join51, resolve as resolve11 } from "node:path";
|
|
88837
89601
|
|
|
88838
89602
|
// ../../packages/host-core/dist/active-link/blocks.js
|
|
88839
89603
|
import { createHash as createHash4 } from "node:crypto";
|
|
88840
89604
|
import { createReadStream } from "node:fs";
|
|
88841
89605
|
import { open, mkdir as mkdir10, rename, chmod as chmod2, utimes, unlink } from "node:fs/promises";
|
|
88842
|
-
import { dirname as
|
|
89606
|
+
import { dirname as dirname19 } from "node:path";
|
|
88843
89607
|
var CHUNK3 = 1024 * 1024;
|
|
88844
89608
|
var MAX_INFLIGHT2 = 8 * CHUNK3;
|
|
88845
89609
|
var IDLE_MS2 = 6e4;
|
|
@@ -88967,7 +89731,7 @@ var StagingWriter = class {
|
|
|
88967
89731
|
}
|
|
88968
89732
|
async ensureOpen() {
|
|
88969
89733
|
if (!this.fh) {
|
|
88970
|
-
await mkdir10(
|
|
89734
|
+
await mkdir10(dirname19(this.stagingPath), { recursive: true });
|
|
88971
89735
|
this.fh = await open(this.stagingPath, "w");
|
|
88972
89736
|
}
|
|
88973
89737
|
return this.fh;
|
|
@@ -88997,7 +89761,7 @@ var StagingWriter = class {
|
|
|
88997
89761
|
});
|
|
88998
89762
|
await fh.close();
|
|
88999
89763
|
this.fh = null;
|
|
89000
|
-
await mkdir10(
|
|
89764
|
+
await mkdir10(dirname19(dest), { recursive: true });
|
|
89001
89765
|
await chmod2(this.stagingPath, mode & 511).catch(() => {
|
|
89002
89766
|
});
|
|
89003
89767
|
const secs = mtimeMs / 1e3;
|
|
@@ -89030,7 +89794,7 @@ var BlockAssembler = class {
|
|
|
89030
89794
|
this.stagingPath = stagingPath;
|
|
89031
89795
|
}
|
|
89032
89796
|
async open() {
|
|
89033
|
-
await mkdir10(
|
|
89797
|
+
await mkdir10(dirname19(this.stagingPath), { recursive: true });
|
|
89034
89798
|
this.fh = await open(this.stagingPath, "w");
|
|
89035
89799
|
}
|
|
89036
89800
|
/** Write a received block at its byte offset (index * CHUNK). */
|
|
@@ -89074,7 +89838,7 @@ var BlockAssembler = class {
|
|
|
89074
89838
|
});
|
|
89075
89839
|
return false;
|
|
89076
89840
|
}
|
|
89077
|
-
await mkdir10(
|
|
89841
|
+
await mkdir10(dirname19(dest), { recursive: true });
|
|
89078
89842
|
await chmod2(this.stagingPath, mode & 511).catch(() => {
|
|
89079
89843
|
});
|
|
89080
89844
|
const secs = mtimeMs / 1e3;
|
|
@@ -89097,7 +89861,7 @@ var BlockAssembler = class {
|
|
|
89097
89861
|
};
|
|
89098
89862
|
|
|
89099
89863
|
// ../../packages/host-core/dist/active-link/manifest.js
|
|
89100
|
-
import { readFileSync as
|
|
89864
|
+
import { readFileSync as readFileSync35, writeFileSync as writeFileSync24, mkdirSync as mkdirSync25, existsSync as existsSync22, renameSync as renameSync8 } from "node:fs";
|
|
89101
89865
|
import { join as join47 } from "node:path";
|
|
89102
89866
|
|
|
89103
89867
|
// ../../packages/host-core/dist/active-link/reconcile.js
|
|
@@ -89138,7 +89902,7 @@ var LinkManifest = class {
|
|
|
89138
89902
|
}
|
|
89139
89903
|
load() {
|
|
89140
89904
|
try {
|
|
89141
|
-
const raw = JSON.parse(
|
|
89905
|
+
const raw = JSON.parse(readFileSync35(this.file(), "utf-8"));
|
|
89142
89906
|
this.records = new Map(Object.entries(raw.records ?? {}));
|
|
89143
89907
|
this.tombstones = new Map(Object.entries(raw.tombstones ?? {}));
|
|
89144
89908
|
} catch {
|
|
@@ -89219,15 +89983,15 @@ var LinkManifest = class {
|
|
|
89219
89983
|
if (!this.dirty)
|
|
89220
89984
|
return;
|
|
89221
89985
|
try {
|
|
89222
|
-
if (!
|
|
89223
|
-
|
|
89986
|
+
if (!existsSync22(this.dir))
|
|
89987
|
+
mkdirSync25(this.dir, { recursive: true });
|
|
89224
89988
|
const json3 = {
|
|
89225
89989
|
records: Object.fromEntries(this.records),
|
|
89226
89990
|
tombstones: Object.fromEntries(this.tombstones)
|
|
89227
89991
|
};
|
|
89228
89992
|
const tmp = `${this.file()}.tmp`;
|
|
89229
89993
|
writeFileSync24(tmp, JSON.stringify(json3));
|
|
89230
|
-
|
|
89994
|
+
renameSync8(tmp, this.file());
|
|
89231
89995
|
this.dirty = false;
|
|
89232
89996
|
} catch {
|
|
89233
89997
|
}
|
|
@@ -90236,9 +91000,9 @@ var NodeFsHandler = class {
|
|
|
90236
91000
|
if (this.fsw.closed) {
|
|
90237
91001
|
return;
|
|
90238
91002
|
}
|
|
90239
|
-
const
|
|
91003
|
+
const dirname33 = sysPath.dirname(file2);
|
|
90240
91004
|
const basename14 = sysPath.basename(file2);
|
|
90241
|
-
const parent = this.fsw._getWatchedDir(
|
|
91005
|
+
const parent = this.fsw._getWatchedDir(dirname33);
|
|
90242
91006
|
let prevStats = stats;
|
|
90243
91007
|
if (parent.has(basename14))
|
|
90244
91008
|
return;
|
|
@@ -90265,7 +91029,7 @@ var NodeFsHandler = class {
|
|
|
90265
91029
|
prevStats = newStats2;
|
|
90266
91030
|
}
|
|
90267
91031
|
} catch (error51) {
|
|
90268
|
-
this.fsw._remove(
|
|
91032
|
+
this.fsw._remove(dirname33, basename14);
|
|
90269
91033
|
}
|
|
90270
91034
|
} else if (parent.has(basename14)) {
|
|
90271
91035
|
const at = newStats.atimeMs;
|
|
@@ -91710,13 +92474,13 @@ var ActiveLinkEngine = class {
|
|
|
91710
92474
|
* file so the path still exists — recorded as a FILE matching disk so the local
|
|
91711
92475
|
* watcher doesn't churn. The target is containment-checked, never dereferenced. */
|
|
91712
92476
|
async applySymlink(rel, dest, target, mtimeMs, mode) {
|
|
91713
|
-
const resolved = resolve11(
|
|
92477
|
+
const resolved = resolve11(dirname22(dest), target);
|
|
91714
92478
|
if (!isInsideRoot(resolved, this.opts.localRoot))
|
|
91715
92479
|
return;
|
|
91716
92480
|
const hash2 = hashString(target);
|
|
91717
92481
|
const secs = mtimeMs / 1e3;
|
|
91718
92482
|
try {
|
|
91719
|
-
await mkdir11(
|
|
92483
|
+
await mkdir11(dirname22(dest), { recursive: true });
|
|
91720
92484
|
await rm4(dest, { force: true, recursive: true });
|
|
91721
92485
|
try {
|
|
91722
92486
|
await symlink2(target, dest);
|
|
@@ -91768,7 +92532,7 @@ var ActiveLinkEngine = class {
|
|
|
91768
92532
|
return;
|
|
91769
92533
|
if (fromRec && fromRec.kind === "file") {
|
|
91770
92534
|
try {
|
|
91771
|
-
await mkdir11(
|
|
92535
|
+
await mkdir11(dirname22(toAbs2), { recursive: true });
|
|
91772
92536
|
await rename2(fromAbs, toAbs2);
|
|
91773
92537
|
const secs = mtimeMs / 1e3;
|
|
91774
92538
|
await utimes2(toAbs2, secs, secs).catch(() => {
|
|
@@ -91793,7 +92557,7 @@ var ActiveLinkEngine = class {
|
|
|
91793
92557
|
await this.maybeRefreshAllow(rels);
|
|
91794
92558
|
const state3 = /* @__PURE__ */ new Map();
|
|
91795
92559
|
for (const rel of rels) {
|
|
91796
|
-
if (
|
|
92560
|
+
if (existsSync23(absOf(this.opts.localRoot, rel)) && !this.isSynced(rel)) {
|
|
91797
92561
|
this.manifest.dropRecord(rel);
|
|
91798
92562
|
continue;
|
|
91799
92563
|
}
|
|
@@ -91897,7 +92661,7 @@ var ActiveLinkEngine = class {
|
|
|
91897
92661
|
for (const rel of this.manifest.recordRels()) {
|
|
91898
92662
|
if (records.has(rel))
|
|
91899
92663
|
continue;
|
|
91900
|
-
if (
|
|
92664
|
+
if (existsSync23(absOf(this.opts.localRoot, rel)))
|
|
91901
92665
|
this.manifest.dropRecord(rel);
|
|
91902
92666
|
else
|
|
91903
92667
|
this.manifest.setTombstone(rel, now2);
|
|
@@ -91968,14 +92732,14 @@ var ActiveLinkEngine = class {
|
|
|
91968
92732
|
};
|
|
91969
92733
|
|
|
91970
92734
|
// ../../packages/host-core/dist/active-link/config.js
|
|
91971
|
-
import { readFileSync as
|
|
92735
|
+
import { readFileSync as readFileSync36, writeFileSync as writeFileSync25, mkdirSync as mkdirSync26, existsSync as existsSync24, renameSync as renameSync9, watch as watch3 } from "node:fs";
|
|
91972
92736
|
import { join as join52 } from "node:path";
|
|
91973
92737
|
function configPath2() {
|
|
91974
92738
|
return join52(activeLinkRoot(), "links.json");
|
|
91975
92739
|
}
|
|
91976
92740
|
function loadLinkConfigs() {
|
|
91977
92741
|
try {
|
|
91978
|
-
const raw = JSON.parse(
|
|
92742
|
+
const raw = JSON.parse(readFileSync36(configPath2(), "utf-8"));
|
|
91979
92743
|
if (!Array.isArray(raw.links))
|
|
91980
92744
|
return [];
|
|
91981
92745
|
return raw.links.filter((c) => c && c.linkId && c.localRoot && c.peerHostId);
|
|
@@ -91986,11 +92750,11 @@ function loadLinkConfigs() {
|
|
|
91986
92750
|
function writeAll(links) {
|
|
91987
92751
|
try {
|
|
91988
92752
|
const dir2 = activeLinkRoot();
|
|
91989
|
-
if (!
|
|
91990
|
-
|
|
92753
|
+
if (!existsSync24(dir2))
|
|
92754
|
+
mkdirSync26(dir2, { recursive: true });
|
|
91991
92755
|
const tmp = `${configPath2()}.tmp`;
|
|
91992
92756
|
writeFileSync25(tmp, JSON.stringify({ links }, null, 2));
|
|
91993
|
-
|
|
92757
|
+
renameSync9(tmp, configPath2());
|
|
91994
92758
|
} catch {
|
|
91995
92759
|
}
|
|
91996
92760
|
}
|
|
@@ -92012,7 +92776,7 @@ function pendingPath() {
|
|
|
92012
92776
|
}
|
|
92013
92777
|
function loadPendingDeprovisions() {
|
|
92014
92778
|
try {
|
|
92015
|
-
const raw = JSON.parse(
|
|
92779
|
+
const raw = JSON.parse(readFileSync36(pendingPath(), "utf-8"));
|
|
92016
92780
|
return Array.isArray(raw.pending) ? raw.pending.filter((p) => p && p.linkId && p.peerHostId) : [];
|
|
92017
92781
|
} catch {
|
|
92018
92782
|
return [];
|
|
@@ -92021,11 +92785,11 @@ function loadPendingDeprovisions() {
|
|
|
92021
92785
|
function writePending(pending2) {
|
|
92022
92786
|
try {
|
|
92023
92787
|
const dir2 = activeLinkRoot();
|
|
92024
|
-
if (!
|
|
92025
|
-
|
|
92788
|
+
if (!existsSync24(dir2))
|
|
92789
|
+
mkdirSync26(dir2, { recursive: true });
|
|
92026
92790
|
const tmp = `${pendingPath()}.tmp`;
|
|
92027
92791
|
writeFileSync25(tmp, JSON.stringify({ pending: pending2 }, null, 2));
|
|
92028
|
-
|
|
92792
|
+
renameSync9(tmp, pendingPath());
|
|
92029
92793
|
} catch {
|
|
92030
92794
|
}
|
|
92031
92795
|
}
|
|
@@ -92037,8 +92801,8 @@ function removeLinkConfig(linkId) {
|
|
|
92037
92801
|
}
|
|
92038
92802
|
function watchLinkConfigs(onChange) {
|
|
92039
92803
|
const dir2 = activeLinkRoot();
|
|
92040
|
-
if (!
|
|
92041
|
-
|
|
92804
|
+
if (!existsSync24(dir2))
|
|
92805
|
+
mkdirSync26(dir2, { recursive: true });
|
|
92042
92806
|
let timer2 = null;
|
|
92043
92807
|
let watcher = null;
|
|
92044
92808
|
try {
|
|
@@ -92183,7 +92947,7 @@ function routeInboundLinkFrame(frame) {
|
|
|
92183
92947
|
init_dist5();
|
|
92184
92948
|
|
|
92185
92949
|
// ../../packages/host-core/dist/pty-manager.js
|
|
92186
|
-
import { existsSync as
|
|
92950
|
+
import { existsSync as existsSync25 } from "node:fs";
|
|
92187
92951
|
import { homedir as homedir8 } from "node:os";
|
|
92188
92952
|
var ptyPromise = null;
|
|
92189
92953
|
function loadPty() {
|
|
@@ -92205,7 +92969,7 @@ function key(clientId, ptyId) {
|
|
|
92205
92969
|
var sessions2 = /* @__PURE__ */ new Map();
|
|
92206
92970
|
var FLUSH_MS = 8;
|
|
92207
92971
|
var FLUSH_BYTES = 64 * 1024;
|
|
92208
|
-
function flush(ptyId, s,
|
|
92972
|
+
function flush(ptyId, s, sink2) {
|
|
92209
92973
|
if (s.timer) {
|
|
92210
92974
|
clearTimeout(s.timer);
|
|
92211
92975
|
s.timer = null;
|
|
@@ -92215,9 +92979,9 @@ function flush(ptyId, s, sink) {
|
|
|
92215
92979
|
const joined = s.buf.join("");
|
|
92216
92980
|
s.buf = [];
|
|
92217
92981
|
s.bytes = 0;
|
|
92218
|
-
|
|
92982
|
+
sink2.output(ptyId, Buffer.from(joined, "utf8").toString("base64"));
|
|
92219
92983
|
}
|
|
92220
|
-
async function openPty(opts,
|
|
92984
|
+
async function openPty(opts, sink2) {
|
|
92221
92985
|
const pty = await loadPty();
|
|
92222
92986
|
if (!pty)
|
|
92223
92987
|
throw new Error("Terminal support is unavailable on this machine.");
|
|
@@ -92247,14 +93011,14 @@ async function openPty(opts, sink) {
|
|
|
92247
93011
|
s.buf.push(data);
|
|
92248
93012
|
s.bytes += data.length;
|
|
92249
93013
|
if (s.bytes >= FLUSH_BYTES)
|
|
92250
|
-
flush(opts.ptyId, s,
|
|
93014
|
+
flush(opts.ptyId, s, sink2);
|
|
92251
93015
|
else if (!s.timer)
|
|
92252
|
-
s.timer = setTimeout(() => flush(opts.ptyId, s,
|
|
93016
|
+
s.timer = setTimeout(() => flush(opts.ptyId, s, sink2), FLUSH_MS);
|
|
92253
93017
|
});
|
|
92254
93018
|
proc.onExit(({ exitCode, signal }) => {
|
|
92255
|
-
flush(opts.ptyId, s,
|
|
93019
|
+
flush(opts.ptyId, s, sink2);
|
|
92256
93020
|
sessions2.delete(k);
|
|
92257
|
-
|
|
93021
|
+
sink2.exit(opts.ptyId, exitCode ?? null, signal ?? null);
|
|
92258
93022
|
});
|
|
92259
93023
|
return { pid: proc.pid };
|
|
92260
93024
|
}
|
|
@@ -92346,7 +93110,7 @@ function listUnix() {
|
|
|
92346
93110
|
const seen = /* @__PURE__ */ new Set();
|
|
92347
93111
|
const loginShell = process.env.SHELL || "";
|
|
92348
93112
|
const add2 = (id, path6) => {
|
|
92349
|
-
if (!path6 || seen.has(path6) || !
|
|
93113
|
+
if (!path6 || seen.has(path6) || !existsSync25(path6))
|
|
92350
93114
|
return;
|
|
92351
93115
|
seen.add(path6);
|
|
92352
93116
|
out.push(mk(id, path6, path6 === loginShell));
|
|
@@ -92378,7 +93142,7 @@ function listWindows() {
|
|
|
92378
93142
|
const gitBash = `${pf}\\Git\\bin\\bash.exe`;
|
|
92379
93143
|
const pwsh7 = `${pf}\\PowerShell\\7\\pwsh.exe`;
|
|
92380
93144
|
const add2 = (id, path6, label, isDefault = false) => {
|
|
92381
|
-
if (path6 &&
|
|
93145
|
+
if (path6 && existsSync25(path6))
|
|
92382
93146
|
out.push(mk(id, path6, isDefault, label));
|
|
92383
93147
|
};
|
|
92384
93148
|
add2("powershell", winPwsh, "Windows PowerShell", true);
|
|
@@ -92437,7 +93201,7 @@ function resolveCwd(cwd, hostRoot) {
|
|
|
92437
93201
|
const fallback = hostRoot || homedir8();
|
|
92438
93202
|
if (!cwd)
|
|
92439
93203
|
return fallback;
|
|
92440
|
-
if (!
|
|
93204
|
+
if (!existsSync25(cwd))
|
|
92441
93205
|
return fallback;
|
|
92442
93206
|
if (hostRoot && !isInsideRoot(cwd, hostRoot))
|
|
92443
93207
|
return hostRoot;
|
|
@@ -92498,7 +93262,12 @@ function setHostDaemonRole(on) {
|
|
|
92498
93262
|
teardownHostRole();
|
|
92499
93263
|
}
|
|
92500
93264
|
}
|
|
93265
|
+
function rdeskOrMeshOnlyBuild() {
|
|
93266
|
+
return process.env.CCB_RDESK_ONLY === "1" || process.env.CCB_MESH_ONLY === "1";
|
|
93267
|
+
}
|
|
92501
93268
|
function sharingEnabled() {
|
|
93269
|
+
if (rdeskOrMeshOnlyBuild())
|
|
93270
|
+
return false;
|
|
92502
93271
|
return sharing || hostDaemonRole || process.env.CCB_HOST_DAEMON === "1";
|
|
92503
93272
|
}
|
|
92504
93273
|
var serverSelected = false;
|
|
@@ -92900,7 +93669,7 @@ function provisionActiveLinkMirror(payload) {
|
|
|
92900
93669
|
if (!isInsideRoot(localRoot, HOST_ROOT))
|
|
92901
93670
|
return;
|
|
92902
93671
|
try {
|
|
92903
|
-
|
|
93672
|
+
mkdirSync27(localRoot, { recursive: true });
|
|
92904
93673
|
} catch {
|
|
92905
93674
|
}
|
|
92906
93675
|
saveLinkConfig({
|
|
@@ -93325,12 +94094,12 @@ async function serveInboundTerm(p, driverClientId) {
|
|
|
93325
94094
|
const route2 = driverClientId ? { clientId: driverClientId } : {};
|
|
93326
94095
|
switch (p.type) {
|
|
93327
94096
|
case "term:open": {
|
|
93328
|
-
const
|
|
94097
|
+
const sink2 = {
|
|
93329
94098
|
output: (ptyId, base643) => send3("term", { type: "term:output", ptyId, base64: base643 }, route2),
|
|
93330
94099
|
exit: (ptyId, exitCode, signal) => send3("term", { type: "term:exit", ptyId, exitCode, signal }, route2)
|
|
93331
94100
|
};
|
|
93332
94101
|
try {
|
|
93333
|
-
const { pid } = await openPty({ ptyId: p.ptyId, clientId: driverClientId, shell: p.shell, args: p.args, cwd: p.cwd, cols: p.cols, rows: p.rows, env: p.env, hostRoot: HOST_CONTAIN },
|
|
94102
|
+
const { pid } = await openPty({ ptyId: p.ptyId, clientId: driverClientId, shell: p.shell, args: p.args, cwd: p.cwd, cols: p.cols, rows: p.rows, env: p.env, hostRoot: HOST_CONTAIN }, sink2);
|
|
93334
94103
|
send3("term", { type: "term:opened", ptyId: p.ptyId, requestId: p.requestId, pid }, route2);
|
|
93335
94104
|
} catch (err2) {
|
|
93336
94105
|
send3("term", { type: "term:openError", ptyId: p.ptyId, requestId: p.requestId, error: err2 instanceof Error ? err2.message : String(err2) }, route2);
|
|
@@ -93474,6 +94243,8 @@ function stopHeartbeat() {
|
|
|
93474
94243
|
}
|
|
93475
94244
|
}
|
|
93476
94245
|
function registerAsHost() {
|
|
94246
|
+
if (rdeskOrMeshOnlyBuild())
|
|
94247
|
+
return;
|
|
93477
94248
|
void ensureP2pReady();
|
|
93478
94249
|
const kind = process.env.CCB_HOST_KIND === "cloud" ? "cloud" : void 0;
|
|
93479
94250
|
const name = kind === "cloud" ? "Cloud agent" : hostname4();
|
|
@@ -95313,7 +96084,7 @@ function setInProcConnector(fn) {
|
|
|
95313
96084
|
|
|
95314
96085
|
// ../../packages/host-core/dist/rdesk/server-prefs.js
|
|
95315
96086
|
init_credentials();
|
|
95316
|
-
import { readFileSync as
|
|
96087
|
+
import { readFileSync as readFileSync37, writeFileSync as writeFileSync26 } from "node:fs";
|
|
95317
96088
|
import { join as join55 } from "node:path";
|
|
95318
96089
|
function rdeskServerPrefsPath() {
|
|
95319
96090
|
return join55(daemonDir2(), "rdesk-server.json");
|
|
@@ -95328,7 +96099,7 @@ var DEFAULTS2 = {
|
|
|
95328
96099
|
};
|
|
95329
96100
|
function readRdeskServerPrefs() {
|
|
95330
96101
|
try {
|
|
95331
|
-
const p = JSON.parse(
|
|
96102
|
+
const p = JSON.parse(readFileSync37(rdeskServerPrefsPath(), "utf8"));
|
|
95332
96103
|
return {
|
|
95333
96104
|
// `!== false` (not `?? true`): only an explicit opt-out disables sharing, so a
|
|
95334
96105
|
// partially-written or older prefs file never silently turns the machine off.
|
|
@@ -95361,7 +96132,7 @@ function rdeskSharingEnabled() {
|
|
|
95361
96132
|
// ../../packages/host-core/dist/rdesk/password.js
|
|
95362
96133
|
init_credentials();
|
|
95363
96134
|
import { scryptSync, randomBytes as randomBytes5, timingSafeEqual as timingSafeEqual4, randomInt } from "node:crypto";
|
|
95364
|
-
import { readFileSync as
|
|
96135
|
+
import { readFileSync as readFileSync38, writeFileSync as writeFileSync27, existsSync as existsSync26, unlinkSync as unlinkSync3 } from "node:fs";
|
|
95365
96136
|
import { join as join56 } from "node:path";
|
|
95366
96137
|
function pwFile() {
|
|
95367
96138
|
return join56(daemonDir2(), "rdesk-password.json");
|
|
@@ -95379,27 +96150,27 @@ function generatePassword() {
|
|
|
95379
96150
|
}
|
|
95380
96151
|
function writePlain(password) {
|
|
95381
96152
|
try {
|
|
95382
|
-
const
|
|
95383
|
-
if (!
|
|
96153
|
+
const safe2 = electronModule()?.safeStorage;
|
|
96154
|
+
if (!safe2?.isEncryptionAvailable())
|
|
95384
96155
|
return;
|
|
95385
|
-
writeFileSync27(pwPlainFile(),
|
|
96156
|
+
writeFileSync27(pwPlainFile(), safe2.encryptString(password), { mode: 384 });
|
|
95386
96157
|
} catch {
|
|
95387
96158
|
}
|
|
95388
96159
|
}
|
|
95389
96160
|
function canRevealRdeskPassword() {
|
|
95390
96161
|
try {
|
|
95391
|
-
const
|
|
95392
|
-
return !!
|
|
96162
|
+
const safe2 = electronModule()?.safeStorage;
|
|
96163
|
+
return !!safe2?.isEncryptionAvailable() && existsSync26(pwPlainFile());
|
|
95393
96164
|
} catch {
|
|
95394
96165
|
return false;
|
|
95395
96166
|
}
|
|
95396
96167
|
}
|
|
95397
96168
|
function readRdeskPasswordPlain() {
|
|
95398
96169
|
try {
|
|
95399
|
-
const
|
|
95400
|
-
if (!
|
|
96170
|
+
const safe2 = electronModule()?.safeStorage;
|
|
96171
|
+
if (!safe2?.isEncryptionAvailable())
|
|
95401
96172
|
return null;
|
|
95402
|
-
return
|
|
96173
|
+
return safe2.decryptString(readFileSync38(pwPlainFile()));
|
|
95403
96174
|
} catch {
|
|
95404
96175
|
return null;
|
|
95405
96176
|
}
|
|
@@ -95432,7 +96203,7 @@ function ensureRdeskPassword() {
|
|
|
95432
96203
|
return regenerateRdeskPassword();
|
|
95433
96204
|
}
|
|
95434
96205
|
function hasRdeskPassword() {
|
|
95435
|
-
return !!process.env.CCB_RDESK_PASSWORD ||
|
|
96206
|
+
return !!process.env.CCB_RDESK_PASSWORD || existsSync26(pwFile());
|
|
95436
96207
|
}
|
|
95437
96208
|
function verifyRdeskPassword(password) {
|
|
95438
96209
|
if (!password)
|
|
@@ -95441,7 +96212,7 @@ function verifyRdeskPassword(password) {
|
|
|
95441
96212
|
if (override)
|
|
95442
96213
|
return password.length === override.length && timingSafeEqual4(Buffer.from(password), Buffer.from(override));
|
|
95443
96214
|
try {
|
|
95444
|
-
const { salt, hash: hash2 } = JSON.parse(
|
|
96215
|
+
const { salt, hash: hash2 } = JSON.parse(readFileSync38(pwFile(), "utf8"));
|
|
95445
96216
|
const got = scryptSync(password, Buffer.from(salt, "hex"), 32);
|
|
95446
96217
|
const want = Buffer.from(hash2, "hex");
|
|
95447
96218
|
return got.length === want.length && timingSafeEqual4(got, want);
|
|
@@ -96007,8 +96778,8 @@ function createPasskeyRegistration(rpId) {
|
|
|
96007
96778
|
|
|
96008
96779
|
// ../../packages/host-core/dist/vault/manager.js
|
|
96009
96780
|
init_base_paths();
|
|
96010
|
-
import { mkdirSync as
|
|
96011
|
-
import { dirname as
|
|
96781
|
+
import { mkdirSync as mkdirSync30, readFileSync as readFileSync41, writeFileSync as writeFileSync30 } from "node:fs";
|
|
96782
|
+
import { dirname as dirname24 } from "node:path";
|
|
96012
96783
|
|
|
96013
96784
|
// ../../packages/vault-core/dist/crypto.js
|
|
96014
96785
|
init_argon2();
|
|
@@ -97032,8 +97803,8 @@ function makeDaemonVaultApi(getOrigin, getToken2) {
|
|
|
97032
97803
|
|
|
97033
97804
|
// ../../packages/host-core/dist/vault/persistence.js
|
|
97034
97805
|
init_base_paths();
|
|
97035
|
-
import { existsSync as
|
|
97036
|
-
import { dirname as
|
|
97806
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync28, readFileSync as readFileSync39, writeFileSync as writeFileSync28, unlinkSync as unlinkSync4 } from "node:fs";
|
|
97807
|
+
import { dirname as dirname23 } from "node:path";
|
|
97037
97808
|
function vaultStoreFile() {
|
|
97038
97809
|
return homePath(".tesseract", "vault", "vault.json");
|
|
97039
97810
|
}
|
|
@@ -97044,9 +97815,9 @@ function makeVaultPersistence(file2 = vaultStoreFile, deviceKeyFile = vaultDevic
|
|
|
97044
97815
|
return {
|
|
97045
97816
|
load() {
|
|
97046
97817
|
try {
|
|
97047
|
-
if (!
|
|
97818
|
+
if (!existsSync27(file2()))
|
|
97048
97819
|
return null;
|
|
97049
|
-
const parsed = JSON.parse(
|
|
97820
|
+
const parsed = JSON.parse(readFileSync39(file2(), "utf8"));
|
|
97050
97821
|
if (!parsed || typeof parsed !== "object")
|
|
97051
97822
|
return null;
|
|
97052
97823
|
return { meta: parsed.meta ?? null, items: Array.isArray(parsed.items) ? parsed.items : [] };
|
|
@@ -97056,28 +97827,28 @@ function makeVaultPersistence(file2 = vaultStoreFile, deviceKeyFile = vaultDevic
|
|
|
97056
97827
|
},
|
|
97057
97828
|
save(state3) {
|
|
97058
97829
|
try {
|
|
97059
|
-
|
|
97830
|
+
mkdirSync28(dirname23(file2()), { recursive: true, mode: 448 });
|
|
97060
97831
|
writeFileSync28(file2(), JSON.stringify(state3), { mode: 384 });
|
|
97061
97832
|
} catch {
|
|
97062
97833
|
}
|
|
97063
97834
|
},
|
|
97064
97835
|
loadDeviceKey() {
|
|
97065
97836
|
try {
|
|
97066
|
-
return
|
|
97837
|
+
return existsSync27(deviceKeyFile()) ? readFileSync39(deviceKeyFile(), "utf8").trim() || null : null;
|
|
97067
97838
|
} catch {
|
|
97068
97839
|
return null;
|
|
97069
97840
|
}
|
|
97070
97841
|
},
|
|
97071
97842
|
saveDeviceKey(base64Key) {
|
|
97072
97843
|
try {
|
|
97073
|
-
|
|
97844
|
+
mkdirSync28(dirname23(deviceKeyFile()), { recursive: true, mode: 448 });
|
|
97074
97845
|
writeFileSync28(deviceKeyFile(), base64Key, { mode: 384 });
|
|
97075
97846
|
} catch {
|
|
97076
97847
|
}
|
|
97077
97848
|
},
|
|
97078
97849
|
clearDeviceKey() {
|
|
97079
97850
|
try {
|
|
97080
|
-
if (
|
|
97851
|
+
if (existsSync27(deviceKeyFile()))
|
|
97081
97852
|
unlinkSync4(deviceKeyFile());
|
|
97082
97853
|
} catch {
|
|
97083
97854
|
}
|
|
@@ -97087,7 +97858,7 @@ function makeVaultPersistence(file2 = vaultStoreFile, deviceKeyFile = vaultDevic
|
|
|
97087
97858
|
|
|
97088
97859
|
// ../../packages/host-core/dist/vault/biometric.js
|
|
97089
97860
|
init_base_paths();
|
|
97090
|
-
import { existsSync as
|
|
97861
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync29, readFileSync as readFileSync40, rmSync as rmSync6, writeFileSync as writeFileSync29 } from "node:fs";
|
|
97091
97862
|
import { join as join57 } from "node:path";
|
|
97092
97863
|
async function electronBio() {
|
|
97093
97864
|
if (!electronModule())
|
|
@@ -97105,7 +97876,7 @@ async function electronBio() {
|
|
|
97105
97876
|
}
|
|
97106
97877
|
function bioDir() {
|
|
97107
97878
|
const d = homePath(".tesseract", "vault-bio");
|
|
97108
|
-
|
|
97879
|
+
mkdirSync29(d, { recursive: true, mode: 448 });
|
|
97109
97880
|
return d;
|
|
97110
97881
|
}
|
|
97111
97882
|
function bioFile(id) {
|
|
@@ -97124,7 +97895,7 @@ async function biometricAvailable() {
|
|
|
97124
97895
|
}
|
|
97125
97896
|
}
|
|
97126
97897
|
function biometricEnrolled(id) {
|
|
97127
|
-
return
|
|
97898
|
+
return existsSync28(bioFile(id));
|
|
97128
97899
|
}
|
|
97129
97900
|
async function biometricEnroll(id, base64Key) {
|
|
97130
97901
|
const bio = await electronBio();
|
|
@@ -97135,13 +97906,13 @@ async function biometricEnroll(id, base64Key) {
|
|
|
97135
97906
|
}
|
|
97136
97907
|
async function biometricUnlock(id) {
|
|
97137
97908
|
const f = bioFile(id);
|
|
97138
|
-
if (!
|
|
97909
|
+
if (!existsSync28(f))
|
|
97139
97910
|
throw new Error("Touch ID is not set up for this vault.");
|
|
97140
97911
|
const bio = await electronBio();
|
|
97141
97912
|
if (!bio)
|
|
97142
97913
|
throw new Error("Touch ID is not available on this device.");
|
|
97143
97914
|
await bio.systemPreferences.promptTouchID("unlock your vault");
|
|
97144
|
-
return bio.safeStorage.decryptString(
|
|
97915
|
+
return bio.safeStorage.decryptString(readFileSync40(f));
|
|
97145
97916
|
}
|
|
97146
97917
|
function biometricDisable(id) {
|
|
97147
97918
|
try {
|
|
@@ -97171,7 +97942,7 @@ var VaultManager = class {
|
|
|
97171
97942
|
// ── auto-lock ────────────────────────────────────────────────────────────────────
|
|
97172
97943
|
loadAutoLock() {
|
|
97173
97944
|
try {
|
|
97174
|
-
const raw = JSON.parse(
|
|
97945
|
+
const raw = JSON.parse(readFileSync41(settingsFile(), "utf8"));
|
|
97175
97946
|
return Number.isFinite(raw.autoLockMinutes) ? Math.max(0, raw.autoLockMinutes) : 0;
|
|
97176
97947
|
} catch {
|
|
97177
97948
|
return 0;
|
|
@@ -97179,7 +97950,7 @@ var VaultManager = class {
|
|
|
97179
97950
|
}
|
|
97180
97951
|
saveAutoLock() {
|
|
97181
97952
|
try {
|
|
97182
|
-
|
|
97953
|
+
mkdirSync30(dirname24(settingsFile()), { recursive: true, mode: 448 });
|
|
97183
97954
|
writeFileSync30(settingsFile(), JSON.stringify({ autoLockMinutes: this.autoLockMinutes }), { mode: 384 });
|
|
97184
97955
|
} catch {
|
|
97185
97956
|
}
|
|
@@ -98218,7 +98989,7 @@ async function startLocalServer(opts) {
|
|
|
98218
98989
|
|
|
98219
98990
|
// ../../packages/host-core/dist/daemon-runtime.js
|
|
98220
98991
|
init_base_paths();
|
|
98221
|
-
import { readFileSync as
|
|
98992
|
+
import { readFileSync as readFileSync46, writeFileSync as writeFileSync38, existsSync as existsSync36, mkdirSync as mkdirSync38, unlinkSync as unlinkSync6, chmodSync as chmodSync7, statSync as statSync10 } from "node:fs";
|
|
98222
98993
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
98223
98994
|
import { join as join70 } from "node:path";
|
|
98224
98995
|
import { randomBytes as randomBytes10 } from "node:crypto";
|
|
@@ -98227,7 +98998,7 @@ import { hostname as hostname5 } from "node:os";
|
|
|
98227
98998
|
// ../../packages/shared/dist/daemon-registry.js
|
|
98228
98999
|
init_base_paths();
|
|
98229
99000
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
98230
|
-
import { existsSync as
|
|
99001
|
+
import { existsSync as existsSync29, mkdirSync as mkdirSync31, readdirSync as readdirSync9, readFileSync as readFileSync42, readlinkSync, unlinkSync as unlinkSync5, writeFileSync as writeFileSync31 } from "node:fs";
|
|
98231
99002
|
import { join as join58 } from "node:path";
|
|
98232
99003
|
var SUPERVISOR_PID = Number(process.env.CCB_DAEMON_SUPERVISOR_PID ?? 0) || 0;
|
|
98233
99004
|
delete process.env.CCB_DAEMON_SUPERVISOR_PID;
|
|
@@ -98323,7 +99094,7 @@ function pidStillMatches(pid, rec) {
|
|
|
98323
99094
|
}
|
|
98324
99095
|
function registerSelfAsDaemon(version2) {
|
|
98325
99096
|
try {
|
|
98326
|
-
|
|
99097
|
+
mkdirSync31(registryDir(), { recursive: true, mode: 448 });
|
|
98327
99098
|
const rec = {
|
|
98328
99099
|
pid: process.pid,
|
|
98329
99100
|
startedAt: procStartedAt(process.pid),
|
|
@@ -98352,7 +99123,7 @@ function unregisterSelfAsDaemon() {
|
|
|
98352
99123
|
}
|
|
98353
99124
|
function readRecord(pid) {
|
|
98354
99125
|
try {
|
|
98355
|
-
return JSON.parse(
|
|
99126
|
+
return JSON.parse(readFileSync42(recordPath(pid), "utf-8"));
|
|
98356
99127
|
} catch {
|
|
98357
99128
|
return null;
|
|
98358
99129
|
}
|
|
@@ -98366,7 +99137,7 @@ function allRegisteredPids() {
|
|
|
98366
99137
|
}
|
|
98367
99138
|
function registeredDaemons(selfPid) {
|
|
98368
99139
|
const out = [];
|
|
98369
|
-
if (!
|
|
99140
|
+
if (!existsSync29(registryDir()))
|
|
98370
99141
|
return out;
|
|
98371
99142
|
for (const pid of allRegisteredPids()) {
|
|
98372
99143
|
if (pid === selfPid)
|
|
@@ -98458,7 +99229,7 @@ function liveDaemons() {
|
|
|
98458
99229
|
|
|
98459
99230
|
// ../../packages/host-core/dist/device-identity.js
|
|
98460
99231
|
import { join as join59 } from "node:path";
|
|
98461
|
-
import { readFileSync as
|
|
99232
|
+
import { readFileSync as readFileSync43, writeFileSync as writeFileSync32, existsSync as existsSync30, mkdirSync as mkdirSync32, renameSync as renameSync10, chmodSync as chmodSync4 } from "node:fs";
|
|
98462
99233
|
init_credentials();
|
|
98463
99234
|
var cached2 = null;
|
|
98464
99235
|
function identityPath() {
|
|
@@ -98468,7 +99239,7 @@ async function loadOrCreateDeviceIdentity() {
|
|
|
98468
99239
|
if (cached2)
|
|
98469
99240
|
return cached2;
|
|
98470
99241
|
try {
|
|
98471
|
-
const stored = JSON.parse(
|
|
99242
|
+
const stored = JSON.parse(readFileSync43(identityPath(), "utf-8"));
|
|
98472
99243
|
if (stored?.privateJwk) {
|
|
98473
99244
|
cached2 = await importIdentity(stored.privateJwk);
|
|
98474
99245
|
return cached2;
|
|
@@ -98478,11 +99249,11 @@ async function loadOrCreateDeviceIdentity() {
|
|
|
98478
99249
|
const kp = await generateIdentityKeyPair(true);
|
|
98479
99250
|
const { privateJwk, publicRaw } = await exportIdentity(kp);
|
|
98480
99251
|
const dir2 = daemonDir2();
|
|
98481
|
-
if (!
|
|
98482
|
-
|
|
99252
|
+
if (!existsSync30(dir2))
|
|
99253
|
+
mkdirSync32(dir2, { recursive: true, mode: 448 });
|
|
98483
99254
|
const tmp = `${identityPath()}.tmp`;
|
|
98484
99255
|
writeFileSync32(tmp, JSON.stringify({ privateJwk, publicRaw, alg: "P256-ECDSA" }, null, 2), { mode: 384 });
|
|
98485
|
-
|
|
99256
|
+
renameSync10(tmp, identityPath());
|
|
98486
99257
|
try {
|
|
98487
99258
|
chmodSync4(identityPath(), 384);
|
|
98488
99259
|
} catch {
|
|
@@ -98500,7 +99271,7 @@ async function loadOrCreateSealingKey() {
|
|
|
98500
99271
|
return sealingCached;
|
|
98501
99272
|
const { subtle: subtle5 } = globalThis.crypto;
|
|
98502
99273
|
try {
|
|
98503
|
-
const stored = JSON.parse(
|
|
99274
|
+
const stored = JSON.parse(readFileSync43(sealingPath(), "utf-8"));
|
|
98504
99275
|
if (stored?.privateJwk && stored.publicRaw) {
|
|
98505
99276
|
const privateKey = await subtle5.importKey("jwk", stored.privateJwk, EC_DH, true, ["deriveBits"]);
|
|
98506
99277
|
sealingCached = { privateKey, publicRaw: unb64u(stored.publicRaw) };
|
|
@@ -98512,11 +99283,11 @@ async function loadOrCreateSealingKey() {
|
|
|
98512
99283
|
const publicRaw = new Uint8Array(await subtle5.exportKey("raw", kp.publicKey));
|
|
98513
99284
|
const privateJwk = await subtle5.exportKey("jwk", kp.privateKey);
|
|
98514
99285
|
const dir2 = daemonDir2();
|
|
98515
|
-
if (!
|
|
98516
|
-
|
|
99286
|
+
if (!existsSync30(dir2))
|
|
99287
|
+
mkdirSync32(dir2, { recursive: true, mode: 448 });
|
|
98517
99288
|
const tmp = `${sealingPath()}.tmp`;
|
|
98518
99289
|
writeFileSync32(tmp, JSON.stringify({ privateJwk, publicRaw: b64u(publicRaw), alg: "P256-ECDH" }, null, 2), { mode: 384 });
|
|
98519
|
-
|
|
99290
|
+
renameSync10(tmp, sealingPath());
|
|
98520
99291
|
try {
|
|
98521
99292
|
chmodSync4(sealingPath(), 384);
|
|
98522
99293
|
} catch {
|
|
@@ -98579,8 +99350,8 @@ import { createRequire as createRequire4 } from "node:module";
|
|
|
98579
99350
|
|
|
98580
99351
|
// ../../packages/host-core/dist/mesh/config.js
|
|
98581
99352
|
init_credentials();
|
|
98582
|
-
import { chmodSync as chmodSync5, existsSync as
|
|
98583
|
-
import { dirname as
|
|
99353
|
+
import { chmodSync as chmodSync5, existsSync as existsSync31, mkdirSync as mkdirSync33, readdirSync as readdirSync10, readFileSync as readFileSync44, renameSync as renameSync11, rmSync as rmSync7, writeFileSync as writeFileSync33 } from "node:fs";
|
|
99354
|
+
import { dirname as dirname25, join as join60 } from "node:path";
|
|
98584
99355
|
function meshDir() {
|
|
98585
99356
|
return join60(daemonDir2(), "mesh");
|
|
98586
99357
|
}
|
|
@@ -98623,27 +99394,27 @@ var FILES = {
|
|
|
98623
99394
|
function readIfPresent(name, dir2 = meshDir()) {
|
|
98624
99395
|
const p = join60(dir2, name);
|
|
98625
99396
|
try {
|
|
98626
|
-
return
|
|
99397
|
+
return existsSync31(p) ? new Uint8Array(readFileSync44(p)) : void 0;
|
|
98627
99398
|
} catch {
|
|
98628
99399
|
return void 0;
|
|
98629
99400
|
}
|
|
98630
99401
|
}
|
|
98631
99402
|
function migrateSingleMesh() {
|
|
98632
99403
|
const legacyGenesis = join60(meshDir(), FILES.genesis);
|
|
98633
|
-
if (!
|
|
99404
|
+
if (!existsSync31(legacyGenesis))
|
|
98634
99405
|
return null;
|
|
98635
99406
|
const id = meshIdFromCert(readIfPresent(FILES.cert)) ?? LEGACY_MESH_ID;
|
|
98636
99407
|
const dest = oneMeshDir(id);
|
|
98637
99408
|
try {
|
|
98638
|
-
|
|
99409
|
+
mkdirSync33(dest, { recursive: true, mode: 448 });
|
|
98639
99410
|
chmodSync5(dest, 448);
|
|
98640
99411
|
for (const f of Object.values(FILES)) {
|
|
98641
99412
|
const from = join60(meshDir(), f);
|
|
98642
|
-
if (
|
|
98643
|
-
|
|
99413
|
+
if (existsSync31(from))
|
|
99414
|
+
renameSync11(from, join60(dest, f));
|
|
98644
99415
|
}
|
|
98645
99416
|
const key2 = join60(dest, FILES.key);
|
|
98646
|
-
if (
|
|
99417
|
+
if (existsSync31(key2))
|
|
98647
99418
|
chmodSync5(key2, 384);
|
|
98648
99419
|
} catch {
|
|
98649
99420
|
return null;
|
|
@@ -98666,14 +99437,14 @@ function listMeshIds() {
|
|
|
98666
99437
|
}
|
|
98667
99438
|
function readLocal(meshId) {
|
|
98668
99439
|
try {
|
|
98669
|
-
return JSON.parse(
|
|
99440
|
+
return JSON.parse(readFileSync44(join60(oneMeshDir(meshId), FILES.local), "utf8"));
|
|
98670
99441
|
} catch {
|
|
98671
99442
|
return null;
|
|
98672
99443
|
}
|
|
98673
99444
|
}
|
|
98674
99445
|
function writeLocal(meshId, state3) {
|
|
98675
99446
|
try {
|
|
98676
|
-
|
|
99447
|
+
mkdirSync33(oneMeshDir(meshId), { recursive: true, mode: 448 });
|
|
98677
99448
|
writeFileSync33(join60(oneMeshDir(meshId), FILES.local), JSON.stringify(state3, null, 2), { mode: 384 });
|
|
98678
99449
|
} catch {
|
|
98679
99450
|
}
|
|
@@ -98720,7 +99491,7 @@ function saveMeshIdentity(id) {
|
|
|
98720
99491
|
saveMesh(meshId, id);
|
|
98721
99492
|
return;
|
|
98722
99493
|
}
|
|
98723
|
-
|
|
99494
|
+
mkdirSync33(meshDir(), { recursive: true, mode: 448 });
|
|
98724
99495
|
try {
|
|
98725
99496
|
chmodSync5(meshDir(), 448);
|
|
98726
99497
|
} catch {
|
|
@@ -98733,7 +99504,7 @@ function saveMeshIdentity(id) {
|
|
|
98733
99504
|
}
|
|
98734
99505
|
function saveMesh(meshId, id) {
|
|
98735
99506
|
const dir2 = oneMeshDir(meshId);
|
|
98736
|
-
|
|
99507
|
+
mkdirSync33(dir2, { recursive: true, mode: 448 });
|
|
98737
99508
|
try {
|
|
98738
99509
|
chmodSync5(meshDir(), 448);
|
|
98739
99510
|
} catch {
|
|
@@ -98767,7 +99538,7 @@ function statusPath(meshId) {
|
|
|
98767
99538
|
function writeStatus(status2, meshId) {
|
|
98768
99539
|
try {
|
|
98769
99540
|
const p = statusPath(meshId);
|
|
98770
|
-
|
|
99541
|
+
mkdirSync33(dirname25(p), { recursive: true, mode: 448 });
|
|
98771
99542
|
writeFileSync33(p, JSON.stringify({ ...status2, at: Date.now() }, null, 2));
|
|
98772
99543
|
} catch {
|
|
98773
99544
|
}
|
|
@@ -98780,7 +99551,7 @@ function clearStatus(meshId) {
|
|
|
98780
99551
|
}
|
|
98781
99552
|
function readStatus(meshId) {
|
|
98782
99553
|
try {
|
|
98783
|
-
const raw = JSON.parse(
|
|
99554
|
+
const raw = JSON.parse(readFileSync44(statusPath(meshId), "utf8"));
|
|
98784
99555
|
if (typeof raw.at !== "number")
|
|
98785
99556
|
return null;
|
|
98786
99557
|
return { ...raw, at: raw.at, stale: Date.now() - raw.at > STATUS_STALE_MS };
|
|
@@ -98792,7 +99563,7 @@ function cacheBundle(bundle, meshId) {
|
|
|
98792
99563
|
try {
|
|
98793
99564
|
const id = meshId ?? listMeshIds()[0];
|
|
98794
99565
|
const dir2 = id === void 0 ? meshDir() : oneMeshDir(id);
|
|
98795
|
-
|
|
99566
|
+
mkdirSync33(dir2, { recursive: true, mode: 448 });
|
|
98796
99567
|
writeFileSync33(join60(dir2, FILES.bundle), bundle);
|
|
98797
99568
|
} catch {
|
|
98798
99569
|
}
|
|
@@ -99845,7 +100616,7 @@ function startNodes(log9) {
|
|
|
99845
100616
|
}
|
|
99846
100617
|
|
|
99847
100618
|
// ../../packages/host-core/dist/drops/receive-ui.js
|
|
99848
|
-
import { basename as basename12, dirname as
|
|
100619
|
+
import { basename as basename12, dirname as dirname26 } from "node:path";
|
|
99849
100620
|
var log5 = (...a) => console.log("[drops]", ...a);
|
|
99850
100621
|
function formatBytes(n) {
|
|
99851
100622
|
if (!Number.isFinite(n) || n <= 0)
|
|
@@ -100187,7 +100958,7 @@ function createDropHandler(deps) {
|
|
|
100187
100958
|
// ../../packages/host-core/dist/drops/blob-fetch.js
|
|
100188
100959
|
import { createWriteStream as createWriteStream2 } from "node:fs";
|
|
100189
100960
|
import { mkdir as mkdir13, rm as rm5, chmod as chmod3 } from "node:fs/promises";
|
|
100190
|
-
import { dirname as
|
|
100961
|
+
import { dirname as dirname27, join as join63 } from "node:path";
|
|
100191
100962
|
import { Readable as Readable2 } from "node:stream";
|
|
100192
100963
|
import { pipeline } from "node:stream/promises";
|
|
100193
100964
|
|
|
@@ -100385,7 +101156,7 @@ async function fetchBlobDrop(opts) {
|
|
|
100385
101156
|
log7(`drop ${opts.dropId}: refusing a path outside the destination`);
|
|
100386
101157
|
continue;
|
|
100387
101158
|
}
|
|
100388
|
-
await mkdir13(
|
|
101159
|
+
await mkdir13(dirname27(abs), { recursive: true });
|
|
100389
101160
|
abs = await uniqueDropPath(abs);
|
|
100390
101161
|
const res = await fetchFn(new URL(item.url, opts.apiOrigin).toString(), { signal: opts.signal });
|
|
100391
101162
|
if (!res.ok || !res.body)
|
|
@@ -100657,13 +101428,13 @@ var RdeskServerChannel = class {
|
|
|
100657
101428
|
};
|
|
100658
101429
|
|
|
100659
101430
|
// ../../packages/host-core/dist/rdesk/channel-client.js
|
|
100660
|
-
import { readFileSync as
|
|
101431
|
+
import { readFileSync as readFileSync45 } from "node:fs";
|
|
100661
101432
|
import { join as join64 } from "node:path";
|
|
100662
101433
|
var RECONNECT_MS = 2e3;
|
|
100663
101434
|
var CLAIM_RETRY_MS = 5e3;
|
|
100664
101435
|
function readEndpoint(dir2, selfPid) {
|
|
100665
101436
|
try {
|
|
100666
|
-
const s = JSON.parse(
|
|
101437
|
+
const s = JSON.parse(readFileSync45(join64(dir2, "status.json"), "utf8"));
|
|
100667
101438
|
if (selfPid && s.pid === selfPid)
|
|
100668
101439
|
return null;
|
|
100669
101440
|
return s.localPort && s.localToken ? `ws://127.0.0.1:${s.localPort}/?token=${s.localToken}` : null;
|
|
@@ -101097,16 +101868,16 @@ function registerRdpEngine() {
|
|
|
101097
101868
|
init_credentials();
|
|
101098
101869
|
import { appendFile, stat as stat8, rename as rename3 } from "node:fs/promises";
|
|
101099
101870
|
import { join as join65 } from "node:path";
|
|
101100
|
-
var
|
|
101871
|
+
var MAX_BYTES2 = 2 * 1024 * 1024;
|
|
101101
101872
|
function rdeskAuditPath() {
|
|
101102
101873
|
return join65(daemonDir2(), "rdesk-audit.jsonl");
|
|
101103
101874
|
}
|
|
101104
101875
|
var queue = [];
|
|
101105
101876
|
var draining = false;
|
|
101106
|
-
async function
|
|
101877
|
+
async function rotateIfNeeded2(path6) {
|
|
101107
101878
|
try {
|
|
101108
101879
|
const st = await stat8(path6);
|
|
101109
|
-
if (st.size <
|
|
101880
|
+
if (st.size < MAX_BYTES2)
|
|
101110
101881
|
return;
|
|
101111
101882
|
await rename3(path6, `${path6}.1`);
|
|
101112
101883
|
} catch {
|
|
@@ -101121,7 +101892,7 @@ async function drain() {
|
|
|
101121
101892
|
const batch = queue.join("");
|
|
101122
101893
|
queue = [];
|
|
101123
101894
|
const path6 = rdeskAuditPath();
|
|
101124
|
-
await
|
|
101895
|
+
await rotateIfNeeded2(path6);
|
|
101125
101896
|
await appendFile(path6, batch, { mode: 384 });
|
|
101126
101897
|
}
|
|
101127
101898
|
} catch {
|
|
@@ -101140,7 +101911,7 @@ function appendRdeskAudit(e) {
|
|
|
101140
101911
|
}
|
|
101141
101912
|
|
|
101142
101913
|
// ../../packages/host-core/dist/fileprovider-bridge.js
|
|
101143
|
-
import { writeFileSync as writeFileSync34, mkdirSync as
|
|
101914
|
+
import { writeFileSync as writeFileSync34, mkdirSync as mkdirSync34, rmSync as rmSync8, existsSync as existsSync32 } from "node:fs";
|
|
101144
101915
|
import { homedir as homedir9 } from "node:os";
|
|
101145
101916
|
import { join as join66 } from "node:path";
|
|
101146
101917
|
var APPEX_BUNDLE_ID = "dev.tesseract.FileProvider";
|
|
@@ -101313,7 +102084,7 @@ function stopFileProviderBridge() {
|
|
|
101313
102084
|
|
|
101314
102085
|
// ../../packages/host-core/dist/vault/autofill-bridge.js
|
|
101315
102086
|
import { randomBytes as randomBytes9 } from "node:crypto";
|
|
101316
|
-
import { existsSync as
|
|
102087
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync35, writeFileSync as writeFileSync35, rmSync as rmSync9 } from "node:fs";
|
|
101317
102088
|
import { homedir as homedir10 } from "node:os";
|
|
101318
102089
|
import { join as join67 } from "node:path";
|
|
101319
102090
|
|
|
@@ -101388,7 +102159,7 @@ function writeBridgeInfo(port, token3, log9) {
|
|
|
101388
102159
|
return;
|
|
101389
102160
|
const containerData = appexContainerData();
|
|
101390
102161
|
try {
|
|
101391
|
-
if (!
|
|
102162
|
+
if (!existsSync33(containerData)) {
|
|
101392
102163
|
if (!infoLoggedOnce) {
|
|
101393
102164
|
infoLoggedOnce = true;
|
|
101394
102165
|
log9("autofill bridge-info SKIP: no appex container yet at", containerData);
|
|
@@ -101396,7 +102167,7 @@ function writeBridgeInfo(port, token3, log9) {
|
|
|
101396
102167
|
return;
|
|
101397
102168
|
}
|
|
101398
102169
|
const dir2 = join67(containerData, "Library", "Application Support");
|
|
101399
|
-
|
|
102170
|
+
mkdirSync35(dir2, { recursive: true });
|
|
101400
102171
|
writeFileSync35(bridgeInfoPath(), JSON.stringify({ port, token: token3, pid: process.pid, ts: Date.now() }), { mode: 384 });
|
|
101401
102172
|
if (!infoLoggedOnce) {
|
|
101402
102173
|
infoLoggedOnce = true;
|
|
@@ -101639,9 +102410,9 @@ function createNodePowerController() {
|
|
|
101639
102410
|
|
|
101640
102411
|
// ../../packages/host-core/dist/native-host.js
|
|
101641
102412
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
101642
|
-
import { chmodSync as chmodSync6, existsSync as
|
|
102413
|
+
import { chmodSync as chmodSync6, existsSync as existsSync34, mkdirSync as mkdirSync36, writeFileSync as writeFileSync36 } from "node:fs";
|
|
101643
102414
|
import { homedir as homedir11, platform as platform5 } from "node:os";
|
|
101644
|
-
import { dirname as
|
|
102415
|
+
import { dirname as dirname28, join as join68, resolve as resolve12 } from "node:path";
|
|
101645
102416
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
101646
102417
|
var HOST_NAME = "com.tesseract.companion";
|
|
101647
102418
|
var EXTENSION_IDS = ["icpnghhpcmaonjckkpilpajblfehpplo", "giolfpookdhjfafcchaflhmigghaeffn"];
|
|
@@ -101664,13 +102435,13 @@ function resolveBridge(log9) {
|
|
|
101664
102435
|
process.resourcesPath ? join68(process.resourcesPath, "companion-host", BRIDGE_BASENAME) : void 0
|
|
101665
102436
|
];
|
|
101666
102437
|
try {
|
|
101667
|
-
const here =
|
|
102438
|
+
const here = dirname28(fileURLToPath5(import.meta.url));
|
|
101668
102439
|
candidates.push(resolve12(here, "../../../apps/companion-host/dist", BRIDGE_BASENAME));
|
|
101669
102440
|
candidates.push(resolve12(here, "../../apps/companion-host/dist", BRIDGE_BASENAME));
|
|
101670
102441
|
} catch {
|
|
101671
102442
|
}
|
|
101672
102443
|
for (const c of candidates)
|
|
101673
|
-
if (c &&
|
|
102444
|
+
if (c && existsSync34(c))
|
|
101674
102445
|
return c;
|
|
101675
102446
|
log9("companion native-host: bridge not found; skipping registration (looked in", candidates.filter(Boolean).join(" , "), ")");
|
|
101676
102447
|
return null;
|
|
@@ -101699,7 +102470,7 @@ function registerNativeHost(opts) {
|
|
|
101699
102470
|
if (!bridge)
|
|
101700
102471
|
return;
|
|
101701
102472
|
const runtime = opts.runtime ?? process.execPath;
|
|
101702
|
-
|
|
102473
|
+
mkdirSync36(opts.daemonDir, { recursive: true });
|
|
101703
102474
|
const launcher = writeLauncher(opts.daemonDir, bridge, runtime);
|
|
101704
102475
|
const manifestJson = JSON.stringify({
|
|
101705
102476
|
name: HOST_NAME,
|
|
@@ -101712,11 +102483,11 @@ function registerNativeHost(opts) {
|
|
|
101712
102483
|
return registerWindows(opts.daemonDir, manifestJson, log9);
|
|
101713
102484
|
let wrote = 0;
|
|
101714
102485
|
for (const profile of browserProfileDirs()) {
|
|
101715
|
-
if (!
|
|
102486
|
+
if (!existsSync34(profile))
|
|
101716
102487
|
continue;
|
|
101717
102488
|
try {
|
|
101718
102489
|
const dir2 = join68(profile, "NativeMessagingHosts");
|
|
101719
|
-
|
|
102490
|
+
mkdirSync36(dir2, { recursive: true });
|
|
101720
102491
|
writeFileSync36(join68(dir2, `${HOST_NAME}.json`), manifestJson);
|
|
101721
102492
|
wrote++;
|
|
101722
102493
|
} catch {
|
|
@@ -101748,7 +102519,7 @@ init_daemon_settings();
|
|
|
101748
102519
|
|
|
101749
102520
|
// ../../packages/host-core/dist/activity/activity-tracker.js
|
|
101750
102521
|
init_credentials();
|
|
101751
|
-
import { promises as fsp, writeFileSync as writeFileSync37, mkdirSync as
|
|
102522
|
+
import { promises as fsp, writeFileSync as writeFileSync37, mkdirSync as mkdirSync37, existsSync as existsSync35 } from "node:fs";
|
|
101752
102523
|
import { join as join69 } from "node:path";
|
|
101753
102524
|
function activityProfilePath() {
|
|
101754
102525
|
return join69(daemonDir2(), "activity-profile.json");
|
|
@@ -101826,7 +102597,7 @@ function createActivityTracker(opts = {}) {
|
|
|
101826
102597
|
return;
|
|
101827
102598
|
const key2 = front.bundleId || front.name;
|
|
101828
102599
|
await ensureLoaded();
|
|
101829
|
-
if (profile && Object.keys(profile.apps).length && !
|
|
102600
|
+
if (profile && Object.keys(profile.apps).length && !existsSync35(activityProfilePath())) {
|
|
101830
102601
|
log9("activity profile cleared externally \u2014 resetting in-memory");
|
|
101831
102602
|
profile = { version: 1, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), apps: {} };
|
|
101832
102603
|
}
|
|
@@ -101862,7 +102633,7 @@ function createActivityTracker(opts = {}) {
|
|
|
101862
102633
|
if (profile) {
|
|
101863
102634
|
pruneProfile(profile);
|
|
101864
102635
|
profile.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
101865
|
-
|
|
102636
|
+
mkdirSync37(daemonDir2(), { recursive: true, mode: 448 });
|
|
101866
102637
|
writeFileSync37(activityProfilePath(), JSON.stringify(profile), { mode: 384 });
|
|
101867
102638
|
dirty = 0;
|
|
101868
102639
|
}
|
|
@@ -101933,13 +102704,21 @@ var reporting = false;
|
|
|
101933
102704
|
var surface = "daemon";
|
|
101934
102705
|
var logFn = () => {
|
|
101935
102706
|
};
|
|
101936
|
-
function endpoint() {
|
|
101937
|
-
const
|
|
101938
|
-
|
|
102707
|
+
function endpoint(apiOrigin) {
|
|
102708
|
+
const explicit = process.env.CCB_ERROR_ENDPOINT?.trim().replace(/\/$/, "");
|
|
102709
|
+
if (explicit)
|
|
102710
|
+
return `${explicit}/v1/reports`;
|
|
102711
|
+
const origin = apiOrigin?.trim().replace(/\/$/, "");
|
|
102712
|
+
return origin ? `${origin}/api/errors/v1/reports` : null;
|
|
101939
102713
|
}
|
|
101940
102714
|
function hasConsent() {
|
|
101941
102715
|
return process.env.CCB_CRASH_REPORT_CONSENT === "1";
|
|
101942
102716
|
}
|
|
102717
|
+
var LAUNCHER_SURFACES = /* @__PURE__ */ new Set(["daemon", "rdesk", "mesh"]);
|
|
102718
|
+
function surfaceFromEnv() {
|
|
102719
|
+
const s = process.env.CCB_ERROR_SURFACE?.trim();
|
|
102720
|
+
return s && LAUNCHER_SURFACES.has(s) ? s : "daemon";
|
|
102721
|
+
}
|
|
101943
102722
|
function initDaemonErrorReporter(opts = {}) {
|
|
101944
102723
|
if (timer)
|
|
101945
102724
|
return;
|
|
@@ -101990,16 +102769,16 @@ function captureDaemonError(error51, opts = {}) {
|
|
|
101990
102769
|
...opts.context ? { context: opts.context } : {},
|
|
101991
102770
|
fingerprint: ""
|
|
101992
102771
|
};
|
|
101993
|
-
const
|
|
101994
|
-
|
|
102772
|
+
const safe2 = redactError(report);
|
|
102773
|
+
safe2.fingerprint = computeFingerprint({
|
|
101995
102774
|
surface,
|
|
101996
|
-
type:
|
|
101997
|
-
message:
|
|
101998
|
-
stacktrace:
|
|
102775
|
+
type: safe2.exception.type,
|
|
102776
|
+
message: safe2.exception.message,
|
|
102777
|
+
stacktrace: safe2.exception.stacktrace
|
|
101999
102778
|
});
|
|
102000
102779
|
if (!hasConsent())
|
|
102001
102780
|
return;
|
|
102002
|
-
queue2.push(
|
|
102781
|
+
queue2.push(safe2);
|
|
102003
102782
|
if (queue2.length > MAX_QUEUE)
|
|
102004
102783
|
queue2.splice(0, queue2.length - MAX_QUEUE);
|
|
102005
102784
|
if (queue2.length >= 10)
|
|
@@ -102016,12 +102795,12 @@ async function flush2() {
|
|
|
102016
102795
|
return;
|
|
102017
102796
|
if (Date.now() < nextAttemptAt)
|
|
102018
102797
|
return;
|
|
102019
|
-
const url2 = endpoint();
|
|
102020
|
-
if (!url2)
|
|
102021
|
-
return;
|
|
102022
102798
|
const creds3 = readCredentials();
|
|
102023
102799
|
if (!creds3?.accessToken)
|
|
102024
102800
|
return;
|
|
102801
|
+
const url2 = endpoint(creds3.apiOrigin);
|
|
102802
|
+
if (!url2)
|
|
102803
|
+
return;
|
|
102025
102804
|
sending = true;
|
|
102026
102805
|
const batch = queue2.slice(0, 20);
|
|
102027
102806
|
try {
|
|
@@ -102072,7 +102851,7 @@ async function runDaemon(opts = {}) {
|
|
|
102072
102851
|
};
|
|
102073
102852
|
const lockHeldByAnother = () => {
|
|
102074
102853
|
try {
|
|
102075
|
-
const pid = Number(
|
|
102854
|
+
const pid = Number(readFileSync46(pidfile(), "utf-8").trim());
|
|
102076
102855
|
return Number.isFinite(pid) && pid > 0 && pid !== process.pid && isAlive2(pid);
|
|
102077
102856
|
} catch {
|
|
102078
102857
|
return false;
|
|
@@ -102081,8 +102860,8 @@ async function runDaemon(opts = {}) {
|
|
|
102081
102860
|
function acquireLock2() {
|
|
102082
102861
|
const f = pidfile();
|
|
102083
102862
|
try {
|
|
102084
|
-
if (!
|
|
102085
|
-
|
|
102863
|
+
if (!existsSync36(daemonDir2()))
|
|
102864
|
+
mkdirSync38(daemonDir2(), { recursive: true, mode: 448 });
|
|
102086
102865
|
} catch {
|
|
102087
102866
|
}
|
|
102088
102867
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
@@ -102091,7 +102870,7 @@ async function runDaemon(opts = {}) {
|
|
|
102091
102870
|
return true;
|
|
102092
102871
|
} catch {
|
|
102093
102872
|
try {
|
|
102094
|
-
const prev = Number(
|
|
102873
|
+
const prev = Number(readFileSync46(f, "utf-8").trim());
|
|
102095
102874
|
if (!prev)
|
|
102096
102875
|
return false;
|
|
102097
102876
|
if (prev !== process.pid && isAlive2(prev))
|
|
@@ -102107,7 +102886,7 @@ async function runDaemon(opts = {}) {
|
|
|
102107
102886
|
function releaseLock() {
|
|
102108
102887
|
try {
|
|
102109
102888
|
const f = pidfile();
|
|
102110
|
-
if (
|
|
102889
|
+
if (existsSync36(f) && Number(readFileSync46(f, "utf-8").trim()) === process.pid)
|
|
102111
102890
|
unlinkSync6(f);
|
|
102112
102891
|
} catch {
|
|
102113
102892
|
}
|
|
@@ -102117,11 +102896,11 @@ async function runDaemon(opts = {}) {
|
|
|
102117
102896
|
let lockPid = 0;
|
|
102118
102897
|
let status2 = {};
|
|
102119
102898
|
try {
|
|
102120
|
-
lockPid = Number(
|
|
102899
|
+
lockPid = Number(readFileSync46(pidfile(), "utf-8").trim());
|
|
102121
102900
|
} catch {
|
|
102122
102901
|
}
|
|
102123
102902
|
try {
|
|
102124
|
-
status2 = JSON.parse(
|
|
102903
|
+
status2 = JSON.parse(readFileSync46(statusFile(), "utf-8"));
|
|
102125
102904
|
} catch {
|
|
102126
102905
|
}
|
|
102127
102906
|
const statusPid = Number(status2.pid ?? 0);
|
|
@@ -102183,7 +102962,7 @@ async function runDaemon(opts = {}) {
|
|
|
102183
102962
|
forgetDaemon(p);
|
|
102184
102963
|
}
|
|
102185
102964
|
try {
|
|
102186
|
-
if (
|
|
102965
|
+
if (existsSync36(pidfile()))
|
|
102187
102966
|
unlinkSync6(pidfile());
|
|
102188
102967
|
} catch {
|
|
102189
102968
|
}
|
|
@@ -102392,7 +103171,7 @@ async function runDaemon(opts = {}) {
|
|
|
102392
103171
|
});
|
|
102393
103172
|
} catch {
|
|
102394
103173
|
}
|
|
102395
|
-
initDaemonErrorReporter({ surface:
|
|
103174
|
+
initDaemonErrorReporter({ surface: surfaceFromEnv(), log: log9 });
|
|
102396
103175
|
process.on("uncaughtException", (e) => {
|
|
102397
103176
|
try {
|
|
102398
103177
|
captureDaemonError(e, { severity: "error", context: { handler: "uncaughtException", keptAlive: true } });
|
|
@@ -102554,7 +103333,7 @@ async function runDaemon(opts = {}) {
|
|
|
102554
103333
|
}
|
|
102555
103334
|
} catch {
|
|
102556
103335
|
}
|
|
102557
|
-
if (ownsMachine)
|
|
103336
|
+
if (ownsMachine && !WE_ARE_RDESK_ONLY)
|
|
102558
103337
|
setHostDaemonRole(true);
|
|
102559
103338
|
const localToken = randomBytes10(24).toString("hex");
|
|
102560
103339
|
const sendToViewer = (kind, sessionId, clientId, msg) => {
|
|
@@ -103008,7 +103787,7 @@ async function runDaemon(opts = {}) {
|
|
|
103008
103787
|
let freeTicks = 0;
|
|
103009
103788
|
const lockHolder = () => {
|
|
103010
103789
|
try {
|
|
103011
|
-
return Number(
|
|
103790
|
+
return Number(readFileSync46(pidfile(), "utf-8").trim()) || 0;
|
|
103012
103791
|
} catch {
|
|
103013
103792
|
return 0;
|
|
103014
103793
|
}
|
|
@@ -103213,7 +103992,7 @@ async function runDaemon(opts = {}) {
|
|
|
103213
103992
|
if (appPid > 0 && appPid !== process.pid) {
|
|
103214
103993
|
const quitMarker = () => {
|
|
103215
103994
|
try {
|
|
103216
|
-
return Number(
|
|
103995
|
+
return Number(readFileSync46(join70(daemonDir2(), "app-quit.marker"), "utf-8").trim()) || 0;
|
|
103217
103996
|
} catch {
|
|
103218
103997
|
return 0;
|
|
103219
103998
|
}
|
|
@@ -103238,7 +104017,7 @@ async function runDaemon(opts = {}) {
|
|
|
103238
104017
|
log9(`desktop app (pid ${appPid}) is gone with NO clean-quit marker \u2014 reporting`);
|
|
103239
104018
|
const tail3 = (name) => {
|
|
103240
104019
|
try {
|
|
103241
|
-
const buf =
|
|
104020
|
+
const buf = readFileSync46(join70(daemonDir2(), name), "utf-8");
|
|
103242
104021
|
return buf.length > 4096 ? buf.slice(-4096) : buf;
|
|
103243
104022
|
} catch {
|
|
103244
104023
|
return void 0;
|
|
@@ -103272,8 +104051,8 @@ async function runDaemon(opts = {}) {
|
|
|
103272
104051
|
const daemonLogFile = join70(daemonDir2(), "daemon.log");
|
|
103273
104052
|
const capTimer = setInterval(() => {
|
|
103274
104053
|
try {
|
|
103275
|
-
if (
|
|
103276
|
-
const buf =
|
|
104054
|
+
if (existsSync36(daemonLogFile) && statSync10(daemonLogFile).size > DAEMON_LOG_CAP) {
|
|
104055
|
+
const buf = readFileSync46(daemonLogFile, "utf-8");
|
|
103277
104056
|
const kept = `\u2026[daemon.log capped at ${(/* @__PURE__ */ new Date()).toISOString()}]\u2026
|
|
103278
104057
|
` + buf.slice(-DAEMON_LOG_CAP / 2);
|
|
103279
104058
|
writeFileSync38(daemonLogFile, kept);
|
|
@@ -103604,8 +104383,8 @@ import { platform as platform6 } from "node:os";
|
|
|
103604
104383
|
|
|
103605
104384
|
// ../../packages/host-core/dist/service/launchd.js
|
|
103606
104385
|
init_credentials();
|
|
103607
|
-
import { writeFileSync as writeFileSync39, existsSync as
|
|
103608
|
-
import { dirname as
|
|
104386
|
+
import { writeFileSync as writeFileSync39, existsSync as existsSync37, mkdirSync as mkdirSync39, unlinkSync as unlinkSync7 } from "node:fs";
|
|
104387
|
+
import { dirname as dirname29, join as join71 } from "node:path";
|
|
103609
104388
|
import { homedir as homedir12, userInfo as userInfo2 } from "node:os";
|
|
103610
104389
|
|
|
103611
104390
|
// ../../packages/host-core/dist/service/types.js
|
|
@@ -103665,9 +104444,9 @@ ${env}
|
|
|
103665
104444
|
}
|
|
103666
104445
|
return {
|
|
103667
104446
|
async install(spec) {
|
|
103668
|
-
|
|
103669
|
-
|
|
103670
|
-
|
|
104447
|
+
mkdirSync39(workDirOf(spec), { recursive: true });
|
|
104448
|
+
mkdirSync39(dirname29(plistPath()), { recursive: true });
|
|
104449
|
+
mkdirSync39(dirname29(spec.logPath), { recursive: true });
|
|
103671
104450
|
writeFileSync39(plistPath(), buildPlist(spec));
|
|
103672
104451
|
await run4("launchctl", ["bootout", serviceTarget()]).catch(() => {
|
|
103673
104452
|
});
|
|
@@ -103680,7 +104459,7 @@ ${env}
|
|
|
103680
104459
|
async uninstall() {
|
|
103681
104460
|
await run4("launchctl", ["bootout", serviceTarget()]).catch(() => {
|
|
103682
104461
|
});
|
|
103683
|
-
if (
|
|
104462
|
+
if (existsSync37(plistPath())) {
|
|
103684
104463
|
try {
|
|
103685
104464
|
unlinkSync7(plistPath());
|
|
103686
104465
|
} catch {
|
|
@@ -103691,7 +104470,7 @@ ${env}
|
|
|
103691
104470
|
await this.install(spec);
|
|
103692
104471
|
},
|
|
103693
104472
|
async isInstalled() {
|
|
103694
|
-
return
|
|
104473
|
+
return existsSync37(plistPath());
|
|
103695
104474
|
},
|
|
103696
104475
|
async start() {
|
|
103697
104476
|
await run4("launchctl", ["bootstrap", domainTarget(), plistPath()]).catch(() => {
|
|
@@ -103708,7 +104487,7 @@ ${env}
|
|
|
103708
104487
|
},
|
|
103709
104488
|
async logs(follow) {
|
|
103710
104489
|
const f = logFile();
|
|
103711
|
-
if (!
|
|
104490
|
+
if (!existsSync37(f)) {
|
|
103712
104491
|
console.log(`No log yet at ${f} \u2014 has the service started?`);
|
|
103713
104492
|
return;
|
|
103714
104493
|
}
|
|
@@ -103719,8 +104498,8 @@ ${env}
|
|
|
103719
104498
|
|
|
103720
104499
|
// ../../packages/host-core/dist/service/systemd.js
|
|
103721
104500
|
init_credentials();
|
|
103722
|
-
import { writeFileSync as writeFileSync40, existsSync as
|
|
103723
|
-
import { dirname as
|
|
104501
|
+
import { writeFileSync as writeFileSync40, existsSync as existsSync38, mkdirSync as mkdirSync40, unlinkSync as unlinkSync8 } from "node:fs";
|
|
104502
|
+
import { dirname as dirname30, join as join72 } from "node:path";
|
|
103724
104503
|
import { homedir as homedir13, userInfo as userInfo3 } from "node:os";
|
|
103725
104504
|
function unitVal(v) {
|
|
103726
104505
|
return v.replace(/%/g, "%%");
|
|
@@ -103759,9 +104538,9 @@ WantedBy=default.target
|
|
|
103759
104538
|
}
|
|
103760
104539
|
return {
|
|
103761
104540
|
async install(spec) {
|
|
103762
|
-
|
|
103763
|
-
|
|
103764
|
-
|
|
104541
|
+
mkdirSync40(workDirOf(spec), { recursive: true });
|
|
104542
|
+
mkdirSync40(dirname30(unitPath()), { recursive: true });
|
|
104543
|
+
mkdirSync40(dirname30(spec.logPath), { recursive: true });
|
|
103765
104544
|
writeFileSync40(unitPath(), buildUnit2(spec));
|
|
103766
104545
|
await run4("loginctl", ["enable-linger", userInfo3().username]).catch(() => {
|
|
103767
104546
|
});
|
|
@@ -103774,7 +104553,7 @@ WantedBy=default.target
|
|
|
103774
104553
|
async uninstall() {
|
|
103775
104554
|
await run4("systemctl", ["--user", "disable", "--now", unit]).catch(() => {
|
|
103776
104555
|
});
|
|
103777
|
-
if (
|
|
104556
|
+
if (existsSync38(unitPath())) {
|
|
103778
104557
|
try {
|
|
103779
104558
|
unlinkSync8(unitPath());
|
|
103780
104559
|
} catch {
|
|
@@ -103787,7 +104566,7 @@ WantedBy=default.target
|
|
|
103787
104566
|
await this.install(spec);
|
|
103788
104567
|
},
|
|
103789
104568
|
async isInstalled() {
|
|
103790
|
-
return
|
|
104569
|
+
return existsSync38(unitPath());
|
|
103791
104570
|
},
|
|
103792
104571
|
async start() {
|
|
103793
104572
|
await run4("systemctl", ["--user", "start", unit]);
|
|
@@ -103806,8 +104585,8 @@ WantedBy=default.target
|
|
|
103806
104585
|
|
|
103807
104586
|
// ../../packages/host-core/dist/service/windows.js
|
|
103808
104587
|
init_credentials();
|
|
103809
|
-
import { writeFileSync as writeFileSync41, existsSync as
|
|
103810
|
-
import { dirname as
|
|
104588
|
+
import { writeFileSync as writeFileSync41, existsSync as existsSync39, mkdirSync as mkdirSync41, unlinkSync as unlinkSync9 } from "node:fs";
|
|
104589
|
+
import { dirname as dirname31, join as join73 } from "node:path";
|
|
103811
104590
|
function makeWindowsTask(instanceId) {
|
|
103812
104591
|
const task = `Fineguide\\TesseractHost${instanceId ? `-${instanceId}` : ""}`;
|
|
103813
104592
|
const wrapperPath = () => join73(daemonDir2(), `run-host${instanceId ? `-${instanceId}` : ""}.cmd`);
|
|
@@ -103827,9 +104606,9 @@ start "" /b ${cmd} >> "${oneLine2(spec.logPath).replace(/"/g, "")}" 2>&1\r
|
|
|
103827
104606
|
}
|
|
103828
104607
|
return {
|
|
103829
104608
|
async install(spec) {
|
|
103830
|
-
|
|
103831
|
-
|
|
103832
|
-
|
|
104609
|
+
mkdirSync41(spec.workingDirectory ?? daemonDir2(), { recursive: true });
|
|
104610
|
+
mkdirSync41(dirname31(spec.logPath), { recursive: true });
|
|
104611
|
+
mkdirSync41(dirname31(wrapperPath()), { recursive: true });
|
|
103833
104612
|
writeFileSync41(wrapperPath(), buildWrapper(spec));
|
|
103834
104613
|
await run4("schtasks", ["/Create", "/TN", task, "/SC", "ONLOGON", "/RL", "LIMITED", "/F", "/TR", `"${wrapperPath()}"`]);
|
|
103835
104614
|
await run4("schtasks", ["/Run", "/TN", task]).catch(() => {
|
|
@@ -103838,7 +104617,7 @@ start "" /b ${cmd} >> "${oneLine2(spec.logPath).replace(/"/g, "")}" 2>&1\r
|
|
|
103838
104617
|
async uninstall() {
|
|
103839
104618
|
await run4("schtasks", ["/Delete", "/TN", task, "/F"]).catch(() => {
|
|
103840
104619
|
});
|
|
103841
|
-
if (
|
|
104620
|
+
if (existsSync39(wrapperPath())) {
|
|
103842
104621
|
try {
|
|
103843
104622
|
unlinkSync9(wrapperPath());
|
|
103844
104623
|
} catch {
|
|
@@ -103868,7 +104647,7 @@ start "" /b ${cmd} >> "${oneLine2(spec.logPath).replace(/"/g, "")}" 2>&1\r
|
|
|
103868
104647
|
},
|
|
103869
104648
|
async logs(follow) {
|
|
103870
104649
|
const f = logFile();
|
|
103871
|
-
if (!
|
|
104650
|
+
if (!existsSync39(f)) {
|
|
103872
104651
|
console.log(`No log yet at ${f} \u2014 has the task run?`);
|
|
103873
104652
|
return;
|
|
103874
104653
|
}
|
|
@@ -103899,7 +104678,7 @@ init_serpapi_runner();
|
|
|
103899
104678
|
// src/auth.ts
|
|
103900
104679
|
var import_qrcode_terminal = __toESM(require_main(), 1);
|
|
103901
104680
|
import { randomUUID as randomUUID27 } from "node:crypto";
|
|
103902
|
-
import { existsSync as
|
|
104681
|
+
import { existsSync as existsSync40, rmSync as rmSync10 } from "node:fs";
|
|
103903
104682
|
import { join as join74 } from "node:path";
|
|
103904
104683
|
|
|
103905
104684
|
// src/config.ts
|
|
@@ -104102,7 +104881,7 @@ async function logout() {
|
|
|
104102
104881
|
for (const f of ["credentials.json", "status.json", "daemon.lock"]) {
|
|
104103
104882
|
try {
|
|
104104
104883
|
const p = join74(daemonDir2(), f);
|
|
104105
|
-
if (
|
|
104884
|
+
if (existsSync40(p)) rmSync10(p);
|
|
104106
104885
|
} catch {
|
|
104107
104886
|
}
|
|
104108
104887
|
}
|
|
@@ -104262,7 +105041,7 @@ function startSelfUpdater(current) {
|
|
|
104262
105041
|
// src/service.ts
|
|
104263
105042
|
import { join as join75 } from "node:path";
|
|
104264
105043
|
import { platform as platform7 } from "node:os";
|
|
104265
|
-
import { existsSync as
|
|
105044
|
+
import { existsSync as existsSync41, readFileSync as readFileSync47 } from "node:fs";
|
|
104266
105045
|
function controller(instanceId) {
|
|
104267
105046
|
const c = getServiceController(instanceId);
|
|
104268
105047
|
if (!c) {
|
|
@@ -104289,8 +105068,8 @@ var isAlive = (pid) => {
|
|
|
104289
105068
|
function runningDaemonInfo() {
|
|
104290
105069
|
const lock = join75(daemonDir2(), "daemon.lock");
|
|
104291
105070
|
try {
|
|
104292
|
-
if (!
|
|
104293
|
-
const pid = Number(
|
|
105071
|
+
if (!existsSync41(lock)) return null;
|
|
105072
|
+
const pid = Number(readFileSync47(lock, "utf-8").trim());
|
|
104294
105073
|
if (!pid || !isAlive(pid)) return null;
|
|
104295
105074
|
return { pid, device: readCredentials()?.deviceId };
|
|
104296
105075
|
} catch {
|
|
@@ -104324,7 +105103,7 @@ async function logs(instanceId, follow) {
|
|
|
104324
105103
|
}
|
|
104325
105104
|
|
|
104326
105105
|
// src/net.ts
|
|
104327
|
-
import { readFileSync as
|
|
105106
|
+
import { readFileSync as readFileSync49 } from "node:fs";
|
|
104328
105107
|
import { randomBytes as randomBytes11 } from "node:crypto";
|
|
104329
105108
|
import { hostname as hostname7 } from "node:os";
|
|
104330
105109
|
import { resolve as resolve14 } from "node:path";
|
|
@@ -104379,7 +105158,7 @@ function readOrDie(label, p) {
|
|
|
104379
105158
|
process.exit(1);
|
|
104380
105159
|
}
|
|
104381
105160
|
try {
|
|
104382
|
-
return new Uint8Array(
|
|
105161
|
+
return new Uint8Array(readFileSync49(resolve14(p)));
|
|
104383
105162
|
} catch (e) {
|
|
104384
105163
|
console.error(`net enroll: could not read --${label} ${p}: ${e instanceof Error ? e.message : e}`);
|
|
104385
105164
|
process.exit(1);
|
|
@@ -104845,8 +105624,8 @@ async function netCommand(rest, flags) {
|
|
|
104845
105624
|
// src/cli.ts
|
|
104846
105625
|
function pkgVersion() {
|
|
104847
105626
|
try {
|
|
104848
|
-
const p = join77(
|
|
104849
|
-
return JSON.parse(
|
|
105627
|
+
const p = join77(dirname32(fileURLToPath6(import.meta.url)), "..", "package.json");
|
|
105628
|
+
return JSON.parse(readFileSync50(p, "utf8")).version ?? "0.0.0";
|
|
104850
105629
|
} catch {
|
|
104851
105630
|
return "0.0.0";
|
|
104852
105631
|
}
|
|
@@ -104949,6 +105728,8 @@ Usage:
|
|
|
104949
105728
|
tesseract-agent start | stop | restart Control the service
|
|
104950
105729
|
tesseract-agent status Show the service status
|
|
104951
105730
|
tesseract-agent logs [--no-follow] Tail the service logs
|
|
105731
|
+
tesseract-agent decisions [--session ID] [--source prompt|verification|recovery] [-n N] [--json]
|
|
105732
|
+
What unattended mode decided while nobody was watching
|
|
104952
105733
|
tesseract-agent run [--engine ID] [--engine-path BIN] [--engine-env K=V ...] [--no-active-link]
|
|
104953
105734
|
Run the daemon in the foreground (Docker/manual)
|
|
104954
105735
|
tesseract-agent link add <folder> --peer <hostId> (--name <shared> | --id <id>)
|
|
@@ -105000,6 +105781,36 @@ async function confirm(question) {
|
|
|
105000
105781
|
rl.close();
|
|
105001
105782
|
}
|
|
105002
105783
|
}
|
|
105784
|
+
async function decisionsCommand(flags) {
|
|
105785
|
+
const { readUnattendedDecisions: readUnattendedDecisions2, unattendedLogPath: unattendedLogPath2 } = await Promise.resolve().then(() => (init_unattended_log(), unattended_log_exports));
|
|
105786
|
+
const limit = typeof flags.n === "string" ? Math.max(1, Number.parseInt(flags.n, 10) || 200) : 200;
|
|
105787
|
+
const source = flags.source === "prompt" || flags.source === "verification" || flags.source === "recovery" ? flags.source : void 0;
|
|
105788
|
+
const sessionId = typeof flags.session === "string" ? flags.session : void 0;
|
|
105789
|
+
const rows = readUnattendedDecisions2(limit, { ...sessionId ? { sessionId } : {}, ...source ? { source } : {} });
|
|
105790
|
+
if (flags.json === true) {
|
|
105791
|
+
for (const r of rows) console.log(JSON.stringify(r));
|
|
105792
|
+
return;
|
|
105793
|
+
}
|
|
105794
|
+
if (!rows.length) {
|
|
105795
|
+
console.log(`No unattended decisions recorded yet (${unattendedLogPath2()}).`);
|
|
105796
|
+
return;
|
|
105797
|
+
}
|
|
105798
|
+
for (const r of rows) {
|
|
105799
|
+
const when = r.ts.replace("T", " ").replace(/\.\d+Z$/, "");
|
|
105800
|
+
const who = r.engine ? ` ${r.engine}` : "";
|
|
105801
|
+
if (r.source === "verification") {
|
|
105802
|
+
const flag = r.exercised === false ? " NOT-RUN" : "";
|
|
105803
|
+
console.log(`${when}${who} verify ${r.gate} \u2192 ${r.action} (cycle ${r.cycle}${r.phaseName ? `, ${r.phaseName}` : ""}${r.blocking ? `, ${r.blocking} blocking` : ""})${flag}`);
|
|
105804
|
+
} else if (r.source === "recovery") {
|
|
105805
|
+
console.log(`${when}${who} recover ${r.kind} \u2192 ${r.action} (attempt ${r.attempt})${r.reason ? ` ${r.reason}` : ""}`);
|
|
105806
|
+
} else {
|
|
105807
|
+
const why = r.outcome === "answered" ? r.decision ?? "" : `${r.outcome}: ${r.reason ?? ""}`;
|
|
105808
|
+
console.log(`${when}${who} ${r.mode} ${r.kind}${r.subject ? `(${r.subject})` : ""} \u2192 ${r.behavior ?? "\u2014"}${r.cappedOut ? " [budget spent]" : ""} ${why}`);
|
|
105809
|
+
}
|
|
105810
|
+
}
|
|
105811
|
+
console.log(`
|
|
105812
|
+
${rows.length} decision(s) \u2014 ${unattendedLogPath2()}`);
|
|
105813
|
+
}
|
|
105003
105814
|
async function linkCommand(rest, flags) {
|
|
105004
105815
|
const sub = rest[0];
|
|
105005
105816
|
if (sub === "list") {
|
|
@@ -105060,7 +105871,7 @@ async function captureClaudeSubscription(flags) {
|
|
|
105060
105871
|
});
|
|
105061
105872
|
if (code !== 0) throw new Error(`Claude sign-in did not complete (exit ${code}).`);
|
|
105062
105873
|
const file2 = join77(home, ".credentials.json");
|
|
105063
|
-
if (
|
|
105874
|
+
if (existsSync43(file2)) return readFileSync50(file2, "utf8");
|
|
105064
105875
|
if (process.platform === "darwin") {
|
|
105065
105876
|
const value = execFileSync6("security", [
|
|
105066
105877
|
"find-generic-password",
|
|
@@ -105142,7 +105953,7 @@ async function runnerCommand(rest, flags) {
|
|
|
105142
105953
|
process.exit(1);
|
|
105143
105954
|
}
|
|
105144
105955
|
const oauthFilePath = typeof flags["oauth-file"] === "string" ? resolve15(flags["oauth-file"]) : void 0;
|
|
105145
|
-
const oauthAuthFile = oauthFilePath ?
|
|
105956
|
+
const oauthAuthFile = oauthFilePath ? readFileSync50(oauthFilePath, "utf8") : void 0;
|
|
105146
105957
|
if (oauthAuthFile) {
|
|
105147
105958
|
try {
|
|
105148
105959
|
JSON.parse(oauthAuthFile);
|
|
@@ -105251,6 +106062,9 @@ Re-run with --yes to replace it, or --instance <id> to install a SEPARATE agent.
|
|
|
105251
106062
|
case "logs":
|
|
105252
106063
|
await logs(instance, flags["no-follow"] !== true);
|
|
105253
106064
|
break;
|
|
106065
|
+
case "decisions":
|
|
106066
|
+
await decisionsCommand(flags);
|
|
106067
|
+
break;
|
|
105254
106068
|
case "link":
|
|
105255
106069
|
await linkCommand(rest, flags);
|
|
105256
106070
|
break;
|