tesseract-agent 0.4.3 → 0.4.6
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 +840 -449
- package/package.json +1 -1
package/dist-bundle/cli.js
CHANGED
|
@@ -11517,8 +11517,8 @@ var capitalizeFirstCharacter, error28;
|
|
|
11517
11517
|
var init_lt = __esm({
|
|
11518
11518
|
"../../node_modules/zod/v4/locales/lt.js"() {
|
|
11519
11519
|
init_util();
|
|
11520
|
-
capitalizeFirstCharacter = (
|
|
11521
|
-
return
|
|
11520
|
+
capitalizeFirstCharacter = (text2) => {
|
|
11521
|
+
return text2.charAt(0).toUpperCase() + text2.slice(1);
|
|
11522
11522
|
};
|
|
11523
11523
|
error28 = () => {
|
|
11524
11524
|
const Sizable = {
|
|
@@ -19350,6 +19350,213 @@ var init_cron_tools = __esm({
|
|
|
19350
19350
|
}
|
|
19351
19351
|
});
|
|
19352
19352
|
|
|
19353
|
+
// ../../packages/agent-core/dist/design-tokens.js
|
|
19354
|
+
function colorVar(name, c) {
|
|
19355
|
+
return c.cssVar ?? `--color-${name}`;
|
|
19356
|
+
}
|
|
19357
|
+
function tokensToCss(tokens) {
|
|
19358
|
+
const lines = [
|
|
19359
|
+
"/* GENERATED from design-system/tokens.json \u2014 do not edit by hand. */",
|
|
19360
|
+
":root {"
|
|
19361
|
+
];
|
|
19362
|
+
const push = (k, v) => lines.push(` ${k}: ${v};`);
|
|
19363
|
+
for (const [name, c] of Object.entries(tokens.colors ?? {}))
|
|
19364
|
+
push(colorVar(name, c), c.value);
|
|
19365
|
+
for (const [role, fam] of Object.entries(tokens.typography?.fontFamilies ?? {}))
|
|
19366
|
+
push(`--font-${role}`, fam);
|
|
19367
|
+
for (const [step, s] of Object.entries(tokens.typography?.scale ?? {}))
|
|
19368
|
+
push(`--text-${step}`, s.size);
|
|
19369
|
+
for (const [name, w] of Object.entries(tokens.typography?.weights ?? {}))
|
|
19370
|
+
push(`--weight-${name}`, String(w));
|
|
19371
|
+
for (const [step, v] of Object.entries(tokens.spacing ?? {}))
|
|
19372
|
+
push(`--space-${step}`, v);
|
|
19373
|
+
for (const [name, v] of Object.entries(tokens.radius ?? {}))
|
|
19374
|
+
push(`--radius-${name}`, v);
|
|
19375
|
+
for (const [name, v] of Object.entries(tokens.shadow ?? {}))
|
|
19376
|
+
push(`--shadow-${name}`, v);
|
|
19377
|
+
lines.push("}", "");
|
|
19378
|
+
return lines.join("\n");
|
|
19379
|
+
}
|
|
19380
|
+
function getTokenPath(tokens, dotPath) {
|
|
19381
|
+
let cur = tokens;
|
|
19382
|
+
for (const key2 of dotPath.split(".")) {
|
|
19383
|
+
if (cur == null || typeof cur !== "object")
|
|
19384
|
+
return void 0;
|
|
19385
|
+
cur = cur[key2];
|
|
19386
|
+
}
|
|
19387
|
+
return cur;
|
|
19388
|
+
}
|
|
19389
|
+
function setTokenPath(tokens, dotPath, value) {
|
|
19390
|
+
const keys = dotPath.split(".").filter(Boolean);
|
|
19391
|
+
if (keys.length === 0)
|
|
19392
|
+
throw new Error("empty token path");
|
|
19393
|
+
const root = { ...tokens };
|
|
19394
|
+
let cur = root;
|
|
19395
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
19396
|
+
const k = keys[i];
|
|
19397
|
+
const next = cur[k];
|
|
19398
|
+
cur[k] = next && typeof next === "object" ? { ...next } : {};
|
|
19399
|
+
cur = cur[k];
|
|
19400
|
+
}
|
|
19401
|
+
cur[keys[keys.length - 1]] = value;
|
|
19402
|
+
return root;
|
|
19403
|
+
}
|
|
19404
|
+
var DESIGN_DIR, TOKENS_FILE, TOKENS_CSS_FILE, DESIGN_CLAUDE_MD, ColorToken, TypeStep, Component, DesignTokensSchema;
|
|
19405
|
+
var init_design_tokens = __esm({
|
|
19406
|
+
"../../packages/agent-core/dist/design-tokens.js"() {
|
|
19407
|
+
"use strict";
|
|
19408
|
+
init_zod();
|
|
19409
|
+
DESIGN_DIR = "design-system";
|
|
19410
|
+
TOKENS_FILE = "design-system/tokens.json";
|
|
19411
|
+
TOKENS_CSS_FILE = "design-system/tokens.css";
|
|
19412
|
+
DESIGN_CLAUDE_MD = "design-system/CLAUDE.md";
|
|
19413
|
+
ColorToken = external_exports.object({ value: external_exports.string(), cssVar: external_exports.string().optional(), role: external_exports.string().optional() });
|
|
19414
|
+
TypeStep = external_exports.object({ size: external_exports.string(), lineHeight: external_exports.string().optional(), weight: external_exports.number().optional() });
|
|
19415
|
+
Component = external_exports.object({
|
|
19416
|
+
selectorHint: external_exports.string().optional(),
|
|
19417
|
+
sourceFiles: external_exports.array(external_exports.string()).optional(),
|
|
19418
|
+
tokensUsed: external_exports.array(external_exports.string()).optional()
|
|
19419
|
+
});
|
|
19420
|
+
DesignTokensSchema = external_exports.object({
|
|
19421
|
+
$schema: external_exports.string().optional(),
|
|
19422
|
+
meta: external_exports.object({
|
|
19423
|
+
name: external_exports.string().optional(),
|
|
19424
|
+
framework: external_exports.enum(["tailwind", "css", "css-modules", "unknown"]).optional(),
|
|
19425
|
+
generatedAt: external_exports.string().optional()
|
|
19426
|
+
}).optional(),
|
|
19427
|
+
colors: external_exports.record(external_exports.string(), ColorToken).optional(),
|
|
19428
|
+
typography: external_exports.object({
|
|
19429
|
+
fontFamilies: external_exports.record(external_exports.string(), external_exports.string()).optional(),
|
|
19430
|
+
scale: external_exports.record(external_exports.string(), TypeStep).optional(),
|
|
19431
|
+
weights: external_exports.record(external_exports.string(), external_exports.number()).optional()
|
|
19432
|
+
}).optional(),
|
|
19433
|
+
spacing: external_exports.record(external_exports.string(), external_exports.string()).optional(),
|
|
19434
|
+
radius: external_exports.record(external_exports.string(), external_exports.string()).optional(),
|
|
19435
|
+
shadow: external_exports.record(external_exports.string(), external_exports.string()).optional(),
|
|
19436
|
+
components: external_exports.record(external_exports.string(), Component).optional()
|
|
19437
|
+
});
|
|
19438
|
+
}
|
|
19439
|
+
});
|
|
19440
|
+
|
|
19441
|
+
// ../../packages/agent-core/dist/design-tools.js
|
|
19442
|
+
import { tool as tool2 } from "@anthropic-ai/claude-agent-sdk";
|
|
19443
|
+
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
19444
|
+
import { join as join4, resolve as resolve2, relative as relative2, isAbsolute as isAbsolute2 } from "node:path";
|
|
19445
|
+
function within(root, p) {
|
|
19446
|
+
const rel = relative2(resolve2(root), resolve2(p));
|
|
19447
|
+
return rel !== "" && !rel.startsWith("..") && !isAbsolute2(rel);
|
|
19448
|
+
}
|
|
19449
|
+
async function loadTokens(root) {
|
|
19450
|
+
try {
|
|
19451
|
+
const parsed = DesignTokensSchema.safeParse(JSON.parse(await readFile(join4(root, TOKENS_FILE), "utf8")));
|
|
19452
|
+
return parsed.success ? parsed.data : {};
|
|
19453
|
+
} catch {
|
|
19454
|
+
return {};
|
|
19455
|
+
}
|
|
19456
|
+
}
|
|
19457
|
+
async function saveTokens(root, tokens, regenerateCss) {
|
|
19458
|
+
const tokensAbs = join4(root, TOKENS_FILE);
|
|
19459
|
+
const cssAbs = join4(root, TOKENS_CSS_FILE);
|
|
19460
|
+
if (!within(root, tokensAbs) || !within(root, cssAbs))
|
|
19461
|
+
throw new Error("refusing to write outside the project root");
|
|
19462
|
+
await mkdir(join4(root, DESIGN_DIR), { recursive: true });
|
|
19463
|
+
await writeFile(tokensAbs, JSON.stringify(tokens, null, 2) + "\n", "utf8");
|
|
19464
|
+
if (regenerateCss)
|
|
19465
|
+
await writeFile(cssAbs, tokensToCss(tokens), "utf8");
|
|
19466
|
+
}
|
|
19467
|
+
function buildDesignTools(deps) {
|
|
19468
|
+
const needRoot = () => {
|
|
19469
|
+
const root = deps.getProjectDir();
|
|
19470
|
+
if (!root)
|
|
19471
|
+
throw new Error("No project directory is open.");
|
|
19472
|
+
return root;
|
|
19473
|
+
};
|
|
19474
|
+
return [
|
|
19475
|
+
tool2("read_design_tokens", "Read the project design system from design-system/tokens.json (colors, typography, spacing, radius, shadow, components). Call this ONCE when you need token values \u2014 do not guess hardcoded hex/sizes.", { section: external_exports.enum(["all", "colors", "typography", "spacing", "radius", "shadow", "components"]).optional().describe("Limit to one section (default: all)") }, async (args) => {
|
|
19476
|
+
const tokens = await loadTokens(needRoot());
|
|
19477
|
+
const out = !args.section || args.section === "all" ? tokens : { [args.section]: tokens[args.section] ?? {} };
|
|
19478
|
+
return text(JSON.stringify(out, null, 2));
|
|
19479
|
+
}),
|
|
19480
|
+
tool2("write_design_token", 'Set one or more design tokens by dot-path (e.g. "colors.primary.value" = "#d97757", "spacing.2" = "0.5rem") and regenerate design-system/tokens.css. Batch related edits in one call. Path-guarded to the project root.', {
|
|
19481
|
+
edits: external_exports.array(external_exports.object({
|
|
19482
|
+
path: external_exports.string().describe("Dot-path into tokens.json, e.g. colors.primary.value"),
|
|
19483
|
+
value: external_exports.union([external_exports.string(), external_exports.number()]).describe("The new value")
|
|
19484
|
+
})).describe("Edits to apply"),
|
|
19485
|
+
regenerateCss: external_exports.boolean().optional().describe("Regenerate tokens.css from the result (default: true)")
|
|
19486
|
+
}, async (args) => {
|
|
19487
|
+
const root = needRoot();
|
|
19488
|
+
let tokens = await loadTokens(root);
|
|
19489
|
+
for (const e of args.edits)
|
|
19490
|
+
tokens = setTokenPath(tokens, e.path, e.value);
|
|
19491
|
+
const validated = DesignTokensSchema.safeParse(tokens);
|
|
19492
|
+
if (!validated.success)
|
|
19493
|
+
return text(`Edit produced an invalid tokens document: ${validated.error.message}`, true);
|
|
19494
|
+
const regen = args.regenerateCss !== false;
|
|
19495
|
+
await saveTokens(root, validated.data, regen);
|
|
19496
|
+
return text(`Updated ${args.edits.length} token(s): ${args.edits.map((e) => e.path).join(", ")}${regen ? " and regenerated tokens.css" : ""}.`);
|
|
19497
|
+
}),
|
|
19498
|
+
tool2("capture_element_styles", "Read the computed CSS of an element on the live preview by CSS selector (cheap \u2014 returns text, not a screenshot). Use to learn what styles/tokens an element currently uses before editing.", {
|
|
19499
|
+
selector: external_exports.string().describe("CSS selector of the element to inspect"),
|
|
19500
|
+
properties: external_exports.array(external_exports.string()).optional().describe("CSS properties to read (default: a common set)")
|
|
19501
|
+
}, async (args) => {
|
|
19502
|
+
const props = args.properties?.length ? args.properties : STYLE_PROPS;
|
|
19503
|
+
const expr = `(() => { const el = document.querySelector(${JSON.stringify(args.selector)}); if (!el) return { error: 'no element matches ${JSON.stringify(args.selector)}' }; const cs = getComputedStyle(el); const out = {}; for (const p of ${JSON.stringify(props)}) out[p] = cs.getPropertyValue(p).trim(); return { tag: el.tagName.toLowerCase(), styles: out }; })()`;
|
|
19504
|
+
try {
|
|
19505
|
+
const result = await deps.driveBrowser("evaluate", { expression: expr });
|
|
19506
|
+
return text(typeof result === "string" ? result : JSON.stringify(result, null, 2));
|
|
19507
|
+
} catch (err) {
|
|
19508
|
+
return text(`Could not read styles (is a preview open?): ${err instanceof Error ? err.message : String(err)}`, true);
|
|
19509
|
+
}
|
|
19510
|
+
}),
|
|
19511
|
+
tool2("notify_preview_ready", "Announce that a live preview / dev server / build is now running and reachable at a URL. Call this once the app is up (e.g. after starting a web build) \u2014 the desktop opens it in the device canvas, the mobile client shows it in-chat, and a build-ready push is sent.", {
|
|
19512
|
+
url: external_exports.string().describe("The reachable preview URL, e.g. http://localhost:3000"),
|
|
19513
|
+
kind: external_exports.enum(["web", "mobile"]).optional().describe("Framing hint (default: web)")
|
|
19514
|
+
}, async (args) => {
|
|
19515
|
+
deps.notifyPreviewReady?.(args.url, args.kind);
|
|
19516
|
+
return text(`Preview announced: ${args.url}`);
|
|
19517
|
+
}),
|
|
19518
|
+
tool2("list_components", "List the design-system components recorded in tokens.json (name, source files, tokens used).", {}, async () => {
|
|
19519
|
+
const comps = (await loadTokens(needRoot())).components ?? {};
|
|
19520
|
+
const names = Object.keys(comps);
|
|
19521
|
+
if (!names.length)
|
|
19522
|
+
return text('No components recorded yet. Run the "Import Design System" skill to populate them.');
|
|
19523
|
+
return text(names.map((n) => {
|
|
19524
|
+
const c = comps[n];
|
|
19525
|
+
const src = c.sourceFiles?.length ? ` (${c.sourceFiles.join(", ")})` : "";
|
|
19526
|
+
const used = c.tokensUsed?.length ? ` \u2014 uses ${c.tokensUsed.join(", ")}` : "";
|
|
19527
|
+
return `- ${n}${src}${used}`;
|
|
19528
|
+
}).join("\n"));
|
|
19529
|
+
})
|
|
19530
|
+
];
|
|
19531
|
+
}
|
|
19532
|
+
var STYLE_PROPS, text;
|
|
19533
|
+
var init_design_tools = __esm({
|
|
19534
|
+
"../../packages/agent-core/dist/design-tools.js"() {
|
|
19535
|
+
"use strict";
|
|
19536
|
+
init_zod();
|
|
19537
|
+
init_design_tokens();
|
|
19538
|
+
STYLE_PROPS = [
|
|
19539
|
+
"color",
|
|
19540
|
+
"background-color",
|
|
19541
|
+
"font-family",
|
|
19542
|
+
"font-size",
|
|
19543
|
+
"font-weight",
|
|
19544
|
+
"line-height",
|
|
19545
|
+
"letter-spacing",
|
|
19546
|
+
"padding",
|
|
19547
|
+
"margin",
|
|
19548
|
+
"border",
|
|
19549
|
+
"border-radius",
|
|
19550
|
+
"box-shadow",
|
|
19551
|
+
"width",
|
|
19552
|
+
"height",
|
|
19553
|
+
"display",
|
|
19554
|
+
"gap"
|
|
19555
|
+
];
|
|
19556
|
+
text = (t, isError = false) => ({ content: [{ type: "text", text: t }], ...isError ? { isError: true } : {} });
|
|
19557
|
+
}
|
|
19558
|
+
});
|
|
19559
|
+
|
|
19353
19560
|
// ../../packages/agent-core/dist/narrator.js
|
|
19354
19561
|
var COALESCE_MS, LOG_CAP, ACT_CAP, NARRATE_CAP, Narrator;
|
|
19355
19562
|
var init_narrator = __esm({
|
|
@@ -19449,13 +19656,13 @@ ${s.log.map((l) => `- ${l}`).join("\n")}` : "",
|
|
|
19449
19656
|
${activity}`,
|
|
19450
19657
|
"One-line status of what it is doing now:"
|
|
19451
19658
|
].filter(Boolean).join("\n\n");
|
|
19452
|
-
const
|
|
19453
|
-
if (
|
|
19454
|
-
s.lastText =
|
|
19455
|
-
s.log.push(
|
|
19659
|
+
const text2 = (await cfg2.complete({ system, prompt, maxTokens: 40 }))?.trim().replace(/^["']|["']$/g, "");
|
|
19660
|
+
if (text2 && text2 !== s.lastText) {
|
|
19661
|
+
s.lastText = text2;
|
|
19662
|
+
s.log.push(text2);
|
|
19456
19663
|
if (s.log.length > LOG_CAP)
|
|
19457
19664
|
s.log.shift();
|
|
19458
|
-
this.emit(id,
|
|
19665
|
+
this.emit(id, text2, cfg2.engineLabel);
|
|
19459
19666
|
}
|
|
19460
19667
|
} catch {
|
|
19461
19668
|
} finally {
|
|
@@ -19562,12 +19769,12 @@ var init_trace_store = __esm({
|
|
|
19562
19769
|
|
|
19563
19770
|
// ../../packages/agent-core/dist/session-transfer.js
|
|
19564
19771
|
import { homedir } from "node:os";
|
|
19565
|
-
import { join as
|
|
19566
|
-
import { readFile, writeFile, mkdir, readdir } from "node:fs/promises";
|
|
19772
|
+
import { join as join5, dirname as dirname3, sep, resolve as resolve3 } from "node:path";
|
|
19773
|
+
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, readdir } from "node:fs/promises";
|
|
19567
19774
|
import { existsSync } from "node:fs";
|
|
19568
19775
|
function isInside(parent, child) {
|
|
19569
|
-
const p =
|
|
19570
|
-
const c =
|
|
19776
|
+
const p = resolve3(parent);
|
|
19777
|
+
const c = resolve3(child);
|
|
19571
19778
|
return c === p || c.startsWith(p + sep);
|
|
19572
19779
|
}
|
|
19573
19780
|
function cwdHash(cwd) {
|
|
@@ -19581,13 +19788,13 @@ function sanitizeProjectDir(cwd) {
|
|
|
19581
19788
|
return s.length <= MAX_PROJECT_DIR_LEN ? s : `${s.slice(0, MAX_PROJECT_DIR_LEN)}-${cwdHash(cwd)}`;
|
|
19582
19789
|
}
|
|
19583
19790
|
function projectsRoot() {
|
|
19584
|
-
return
|
|
19791
|
+
return join5(homedir(), ".claude", "projects");
|
|
19585
19792
|
}
|
|
19586
19793
|
function sessionDir(cwd) {
|
|
19587
|
-
return
|
|
19794
|
+
return join5(projectsRoot(), sanitizeProjectDir(cwd));
|
|
19588
19795
|
}
|
|
19589
19796
|
function sessionFile(cwd, sessionId) {
|
|
19590
|
-
return
|
|
19797
|
+
return join5(sessionDir(cwd), `${sessionId}.jsonl`);
|
|
19591
19798
|
}
|
|
19592
19799
|
async function walkFiles(root) {
|
|
19593
19800
|
const out = [];
|
|
@@ -19596,7 +19803,7 @@ async function walkFiles(root) {
|
|
|
19596
19803
|
for (const e of entries) {
|
|
19597
19804
|
const rel = prefix ? `${prefix}/${e.name}` : e.name;
|
|
19598
19805
|
if (e.isDirectory())
|
|
19599
|
-
await rec(
|
|
19806
|
+
await rec(join5(dir, e.name), rel);
|
|
19600
19807
|
else if (e.isFile())
|
|
19601
19808
|
out.push(rel);
|
|
19602
19809
|
}
|
|
@@ -19608,13 +19815,13 @@ async function exportSession(sessionId, fromCwd) {
|
|
|
19608
19815
|
const file2 = sessionFile(fromCwd, sessionId);
|
|
19609
19816
|
if (!existsSync(file2))
|
|
19610
19817
|
return null;
|
|
19611
|
-
const raw = await
|
|
19818
|
+
const raw = await readFile2(file2, "utf-8");
|
|
19612
19819
|
const lines = raw.split("\n").filter((l) => l.trim().length > 0);
|
|
19613
19820
|
const sidecar = [];
|
|
19614
|
-
const sideDir =
|
|
19821
|
+
const sideDir = join5(sessionDir(fromCwd), sessionId);
|
|
19615
19822
|
if (existsSync(sideDir)) {
|
|
19616
19823
|
for (const rel of await walkFiles(sideDir)) {
|
|
19617
|
-
sidecar.push({ rel, data: await
|
|
19824
|
+
sidecar.push({ rel, data: await readFile2(join5(sideDir, rel.split("/").join(sep))) });
|
|
19618
19825
|
}
|
|
19619
19826
|
}
|
|
19620
19827
|
return { sessionId, fromCwd, lines, sidecar };
|
|
@@ -19622,22 +19829,22 @@ async function exportSession(sessionId, fromCwd) {
|
|
|
19622
19829
|
function escapeRe(s) {
|
|
19623
19830
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
19624
19831
|
}
|
|
19625
|
-
function rekey(
|
|
19626
|
-
return
|
|
19832
|
+
function rekey(text2, fromCwd, toCwd) {
|
|
19833
|
+
return text2.replace(new RegExp(escapeRe(fromCwd) + '(?=["/\\\\]|$)', "g"), () => toCwd);
|
|
19627
19834
|
}
|
|
19628
19835
|
async function importSession(exp, toCwd) {
|
|
19629
19836
|
const destDir = sessionDir(toCwd);
|
|
19630
|
-
await
|
|
19631
|
-
const destFile =
|
|
19632
|
-
await
|
|
19633
|
-
const sideRoot =
|
|
19837
|
+
await mkdir2(destDir, { recursive: true });
|
|
19838
|
+
const destFile = join5(destDir, `${exp.sessionId}.jsonl`);
|
|
19839
|
+
await writeFile2(destFile, exp.lines.map((l) => rekey(l, exp.fromCwd, toCwd)).join("\n") + "\n");
|
|
19840
|
+
const sideRoot = join5(destDir, exp.sessionId);
|
|
19634
19841
|
for (const s of exp.sidecar) {
|
|
19635
|
-
const dest =
|
|
19842
|
+
const dest = join5(sideRoot, s.rel.split("/").join(sep));
|
|
19636
19843
|
if (!isInside(sideRoot, dest))
|
|
19637
19844
|
continue;
|
|
19638
|
-
await
|
|
19845
|
+
await mkdir2(dirname3(dest), { recursive: true });
|
|
19639
19846
|
const data = s.rel.endsWith(".jsonl") || s.rel.endsWith(".json") ? Buffer.from(rekey(s.data.toString("utf-8"), exp.fromCwd, toCwd), "utf-8") : s.data;
|
|
19640
|
-
await
|
|
19847
|
+
await writeFile2(dest, data);
|
|
19641
19848
|
}
|
|
19642
19849
|
return destFile;
|
|
19643
19850
|
}
|
|
@@ -19656,7 +19863,7 @@ var init_session_transfer = __esm({
|
|
|
19656
19863
|
});
|
|
19657
19864
|
|
|
19658
19865
|
// ../../packages/agent-core/dist/session-store.js
|
|
19659
|
-
import { readFile as
|
|
19866
|
+
import { readFile as readFile3, stat } from "node:fs/promises";
|
|
19660
19867
|
import { listSessions, getSessionMessages, forkSession } from "@anthropic-ai/claude-agent-sdk";
|
|
19661
19868
|
function toSessionInfo(s) {
|
|
19662
19869
|
const fromFirst = stripPromptPrefix(s.firstPrompt ?? "").slice(0, 80);
|
|
@@ -19702,9 +19909,9 @@ function transcriptMatches(raw, q) {
|
|
|
19702
19909
|
}
|
|
19703
19910
|
return false;
|
|
19704
19911
|
}
|
|
19705
|
-
function stripPromptPrefix(
|
|
19912
|
+
function stripPromptPrefix(text2) {
|
|
19706
19913
|
const isMetadata = (l) => l.startsWith("I'm working on the page:") || l.startsWith("Selected elements:") || l.startsWith("Element ") || l.startsWith(" DOM Path:") || l.startsWith(" XPath:") || l.startsWith(" CSS:") || l.startsWith(" HTML:") || l.startsWith(" Text:") || l.startsWith(" Position:") || l.startsWith("Use the xpath") || l.startsWith("[") && l.includes("image(s) attached");
|
|
19707
|
-
const userLines =
|
|
19914
|
+
const userLines = text2.split("\n").filter((l) => !isMetadata(l));
|
|
19708
19915
|
return userLines.join("\n").trim();
|
|
19709
19916
|
}
|
|
19710
19917
|
function extractBlocks(message) {
|
|
@@ -19723,13 +19930,13 @@ function extractBlocks(message) {
|
|
|
19723
19930
|
continue;
|
|
19724
19931
|
const b = block;
|
|
19725
19932
|
if (b.type === "thinking" && typeof b.thinking === "string") {
|
|
19726
|
-
const
|
|
19727
|
-
if (
|
|
19728
|
-
blocks.push({ kind: "thinking", content:
|
|
19933
|
+
const text2 = b.thinking.trim();
|
|
19934
|
+
if (text2)
|
|
19935
|
+
blocks.push({ kind: "thinking", content: text2 });
|
|
19729
19936
|
} else if (b.type === "text" && typeof b.text === "string") {
|
|
19730
|
-
const
|
|
19731
|
-
if (
|
|
19732
|
-
blocks.push({ kind: "text", content:
|
|
19937
|
+
const text2 = b.text.trim();
|
|
19938
|
+
if (text2 && !text2.startsWith("<ide_") && !text2.startsWith("<system-reminder>")) {
|
|
19939
|
+
blocks.push({ kind: "text", content: text2 });
|
|
19733
19940
|
}
|
|
19734
19941
|
} else if (b.type === "tool_use") {
|
|
19735
19942
|
const name = b.name ?? "tool";
|
|
@@ -19821,7 +20028,7 @@ var init_session_store = __esm({
|
|
|
19821
20028
|
const file2 = sessionFile(s.cwd, s.sessionId);
|
|
19822
20029
|
const st = await stat(file2);
|
|
19823
20030
|
if (st.size <= SEARCH_MAX_FILE_BYTES) {
|
|
19824
|
-
const raw = await
|
|
20031
|
+
const raw = await readFile3(file2, "utf-8");
|
|
19825
20032
|
if (transcriptMatches(raw, q))
|
|
19826
20033
|
out.push(info);
|
|
19827
20034
|
}
|
|
@@ -19891,11 +20098,11 @@ var init_log = __esm({
|
|
|
19891
20098
|
});
|
|
19892
20099
|
|
|
19893
20100
|
// ../../packages/agent-core/dist/session-usage.js
|
|
19894
|
-
import { readFile as
|
|
20101
|
+
import { readFile as readFile4 } from "node:fs/promises";
|
|
19895
20102
|
import { execFile } from "node:child_process";
|
|
19896
20103
|
import { promisify } from "node:util";
|
|
19897
20104
|
import { homedir as homedir2 } from "node:os";
|
|
19898
|
-
import { join as
|
|
20105
|
+
import { join as join6 } from "node:path";
|
|
19899
20106
|
function tokenFromCredsBlob(raw) {
|
|
19900
20107
|
try {
|
|
19901
20108
|
const j = JSON.parse(raw);
|
|
@@ -19909,7 +20116,7 @@ async function tokenFromConfigDir(dir) {
|
|
|
19909
20116
|
if (!d)
|
|
19910
20117
|
return null;
|
|
19911
20118
|
try {
|
|
19912
|
-
return tokenFromCredsBlob(await
|
|
20119
|
+
return tokenFromCredsBlob(await readFile4(join6(d, ".credentials.json"), "utf8"));
|
|
19913
20120
|
} catch {
|
|
19914
20121
|
return null;
|
|
19915
20122
|
}
|
|
@@ -19924,7 +20131,7 @@ async function resolveOauthToken(env) {
|
|
|
19924
20131
|
const ambientTok = process.env.CLAUDE_CODE_OAUTH_TOKEN?.trim();
|
|
19925
20132
|
if (ambientTok)
|
|
19926
20133
|
return ambientTok;
|
|
19927
|
-
const fromAmbientDir = await tokenFromConfigDir(process.env.CLAUDE_CONFIG_DIR ??
|
|
20134
|
+
const fromAmbientDir = await tokenFromConfigDir(process.env.CLAUDE_CONFIG_DIR ?? join6(homedir2(), ".claude"));
|
|
19928
20135
|
if (fromAmbientDir)
|
|
19929
20136
|
return fromAmbientDir;
|
|
19930
20137
|
if (process.platform === "darwin") {
|
|
@@ -20042,11 +20249,11 @@ var init_session_usage = __esm({
|
|
|
20042
20249
|
|
|
20043
20250
|
// ../../packages/agent-core/dist/agent-manager.js
|
|
20044
20251
|
import { query, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
|
|
20045
|
-
import { writeFile as
|
|
20252
|
+
import { writeFile as writeFile3, mkdir as mkdir3, readFile as readFile5 } from "node:fs/promises";
|
|
20046
20253
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
20047
20254
|
import { tmpdir } from "node:os";
|
|
20048
|
-
import { join as
|
|
20049
|
-
import { existsSync as existsSync2 } from "node:fs";
|
|
20255
|
+
import { join as join7, dirname as dirname4 } from "node:path";
|
|
20256
|
+
import { existsSync as existsSync2, readFileSync as readFileSync3 } from "node:fs";
|
|
20050
20257
|
import { fileURLToPath } from "node:url";
|
|
20051
20258
|
import { createRequire } from "node:module";
|
|
20052
20259
|
import { createServer } from "node:net";
|
|
@@ -20054,7 +20261,7 @@ import { spawn, execSync } from "node:child_process";
|
|
|
20054
20261
|
function findClaudeCliJs() {
|
|
20055
20262
|
const require2 = createRequire(import.meta.url);
|
|
20056
20263
|
const sdkMain = require2.resolve("@anthropic-ai/claude-agent-sdk");
|
|
20057
|
-
const cliJs =
|
|
20264
|
+
const cliJs = join7(dirname4(sdkMain), "cli.js");
|
|
20058
20265
|
if (!existsSync2(cliJs)) {
|
|
20059
20266
|
throw new Error(`Claude Agent SDK cli.js not found at ${cliJs}. The installed SDK version may not ship cli.js \u2014 apps/host/package.json pins @anthropic-ai/claude-agent-sdk to a version that includes it.`);
|
|
20060
20267
|
}
|
|
@@ -20158,15 +20365,15 @@ ${plan}`;
|
|
|
20158
20365
|
}
|
|
20159
20366
|
}
|
|
20160
20367
|
function flattenToolResultContent(content) {
|
|
20161
|
-
let
|
|
20368
|
+
let text2 = "";
|
|
20162
20369
|
if (typeof content === "string")
|
|
20163
|
-
|
|
20370
|
+
text2 = content;
|
|
20164
20371
|
else if (Array.isArray(content)) {
|
|
20165
|
-
|
|
20372
|
+
text2 = content.filter((b) => b && typeof b === "object" && b.type === "text").map((b) => String(b.text ?? "")).join("\n");
|
|
20166
20373
|
}
|
|
20167
|
-
if (
|
|
20168
|
-
return { text:
|
|
20169
|
-
return { text, truncated: false };
|
|
20374
|
+
if (text2.length > TOOL_RESULT_CAP)
|
|
20375
|
+
return { text: text2.slice(0, TOOL_RESULT_CAP), truncated: true };
|
|
20376
|
+
return { text: text2, truncated: false };
|
|
20170
20377
|
}
|
|
20171
20378
|
function extractImages(content) {
|
|
20172
20379
|
if (!Array.isArray(content))
|
|
@@ -20209,7 +20416,7 @@ function editedPathOf(toolInput) {
|
|
|
20209
20416
|
}
|
|
20210
20417
|
async function snapshotFile(path5) {
|
|
20211
20418
|
try {
|
|
20212
|
-
const buf = await
|
|
20419
|
+
const buf = await readFile5(path5);
|
|
20213
20420
|
if (buf.length > EDIT_PREVIEW_CAP)
|
|
20214
20421
|
return { noPreview: true };
|
|
20215
20422
|
if (buf.subarray(0, 8192).includes(0))
|
|
@@ -20229,12 +20436,42 @@ function sourcesEqual(a, b) {
|
|
|
20229
20436
|
return false;
|
|
20230
20437
|
return true;
|
|
20231
20438
|
}
|
|
20439
|
+
function buildMobileClause(dir) {
|
|
20440
|
+
try {
|
|
20441
|
+
let fw = "";
|
|
20442
|
+
let runCmd = "";
|
|
20443
|
+
if (existsSync2(join7(dir, "pubspec.yaml"))) {
|
|
20444
|
+
fw = "Flutter";
|
|
20445
|
+
runCmd = "flutter run -d chrome";
|
|
20446
|
+
} else if (existsSync2(join7(dir, "package.json"))) {
|
|
20447
|
+
const pkg = JSON.parse(readFileSync3(join7(dir, "package.json"), "utf8"));
|
|
20448
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
20449
|
+
if (deps.expo) {
|
|
20450
|
+
fw = "Expo";
|
|
20451
|
+
runCmd = "npx expo start --web";
|
|
20452
|
+
} else if (deps["react-native"]) {
|
|
20453
|
+
fw = "React Native";
|
|
20454
|
+
runCmd = "npm run web (react-native-web)";
|
|
20455
|
+
}
|
|
20456
|
+
}
|
|
20457
|
+
if (!fw)
|
|
20458
|
+
return "";
|
|
20459
|
+
return `
|
|
20460
|
+
|
|
20461
|
+
MOBILE (${fw}):
|
|
20462
|
+
- For a fast live preview, run the app AS WEB (\`${runCmd}\`) and tell the user the localhost URL \u2014 Tesseract shows it in a phone-framed canvas where elements can be picked and edited. Use a real device/simulator only when native-specific behavior matters.`;
|
|
20463
|
+
} catch {
|
|
20464
|
+
return "";
|
|
20465
|
+
}
|
|
20466
|
+
}
|
|
20232
20467
|
var cachedNodeExe, HUMAN_READABLE_FIELDS, TOOL_RESULT_CAP, MAX_RESULT_IMAGES, MAX_IMAGE_BASE64, PERMISSION_MODES, EDIT_PREVIEW_CAP, AsyncMessagePump, IDLE_REAP_MS, MODERATE_IDLE_MS, STEER_COALESCE_MS, AgentManager;
|
|
20233
20468
|
var init_agent_manager = __esm({
|
|
20234
20469
|
"../../packages/agent-core/dist/agent-manager.js"() {
|
|
20235
20470
|
"use strict";
|
|
20236
20471
|
init_dist();
|
|
20237
20472
|
init_cron_tools();
|
|
20473
|
+
init_design_tools();
|
|
20474
|
+
init_design_tokens();
|
|
20238
20475
|
init_narrator();
|
|
20239
20476
|
init_plan_splitter();
|
|
20240
20477
|
init_trace_store();
|
|
@@ -20277,7 +20514,7 @@ var init_agent_manager = __esm({
|
|
|
20277
20514
|
if (this.closed) {
|
|
20278
20515
|
return Promise.resolve({ value: void 0, done: true });
|
|
20279
20516
|
}
|
|
20280
|
-
return new Promise((
|
|
20517
|
+
return new Promise((resolve9) => this.resolvers.push(resolve9));
|
|
20281
20518
|
},
|
|
20282
20519
|
return: () => {
|
|
20283
20520
|
this.end();
|
|
@@ -20303,6 +20540,10 @@ var init_agent_manager = __esm({
|
|
|
20303
20540
|
/** requestId → the originating browser-cli socket, for unicast responses.
|
|
20304
20541
|
* browser-cli is one-shot, so the entry is deleted on the first write. */
|
|
20305
20542
|
pendingResponses = /* @__PURE__ */ new Map();
|
|
20543
|
+
/** Resolvers for HOST-originated browser requests (design tools), keyed by
|
|
20544
|
+
* requestId — disjoint from pendingResponses (browser-cli sockets). Resolved by
|
|
20545
|
+
* sendBrowserResponse when the host replies. */
|
|
20546
|
+
pendingBrowserResolvers = /* @__PURE__ */ new Map();
|
|
20306
20547
|
/** requestId → a parked canUseTool decision. The Promise resolves when the
|
|
20307
20548
|
* client replies with chat:permission (→ respondToPermission) or the turn is
|
|
20308
20549
|
* aborted (→ deny). `suggestions` is echoed back as updatedPermissions when the
|
|
@@ -20415,8 +20656,8 @@ var init_agent_manager = __esm({
|
|
|
20415
20656
|
this.send = send2;
|
|
20416
20657
|
this.onBrowserRequest = onBrowserRequest;
|
|
20417
20658
|
const __dirname = dirname4(fileURLToPath(import.meta.url));
|
|
20418
|
-
this.browserCliPath =
|
|
20419
|
-
this.narrator = new Narrator((sessionId,
|
|
20659
|
+
this.browserCliPath = join7(__dirname, "browser-cli.js");
|
|
20660
|
+
this.narrator = new Narrator((sessionId, text2, engineLabel) => this.send({ type: "agent:narration", sessionId, text: text2, ...engineLabel ? { engineLabel } : {} }, this.liveSessions.get(sessionId)?.origin));
|
|
20420
20661
|
}
|
|
20421
20662
|
/** Inject (or clear) the cheap model used for the live status narration. The
|
|
20422
20663
|
* host resolves creds and builds the completion fn (keeping secrets host-side). */
|
|
@@ -20443,7 +20684,7 @@ var init_agent_manager = __esm({
|
|
|
20443
20684
|
* (no shared-socket "which session?" race) with ZERO changes to browser-cli.
|
|
20444
20685
|
*/
|
|
20445
20686
|
startSessionListener(live) {
|
|
20446
|
-
return new Promise((
|
|
20687
|
+
return new Promise((resolve9) => {
|
|
20447
20688
|
const server = createServer((socket2) => {
|
|
20448
20689
|
live.ipcSockets.add(socket2);
|
|
20449
20690
|
let buffer = "";
|
|
@@ -20475,11 +20716,21 @@ var init_agent_manager = __esm({
|
|
|
20475
20716
|
const addr = server.address();
|
|
20476
20717
|
live.ipcPort = typeof addr === "object" && addr ? addr.port : 0;
|
|
20477
20718
|
log("Session IPC listener on port", live.ipcPort, "for", live.sessionId || live.clientRequestId || "(pending)");
|
|
20478
|
-
|
|
20719
|
+
resolve9();
|
|
20479
20720
|
});
|
|
20480
20721
|
});
|
|
20481
20722
|
}
|
|
20482
20723
|
sendBrowserResponse(requestId, result, error51) {
|
|
20724
|
+
const pending = this.pendingBrowserResolvers.get(requestId);
|
|
20725
|
+
if (pending) {
|
|
20726
|
+
this.pendingBrowserResolvers.delete(requestId);
|
|
20727
|
+
clearTimeout(pending.timer);
|
|
20728
|
+
if (error51)
|
|
20729
|
+
pending.reject(new Error(error51));
|
|
20730
|
+
else
|
|
20731
|
+
pending.resolve(result);
|
|
20732
|
+
return;
|
|
20733
|
+
}
|
|
20483
20734
|
const socket2 = this.pendingResponses.get(requestId);
|
|
20484
20735
|
if (!socket2)
|
|
20485
20736
|
return;
|
|
@@ -20489,6 +20740,28 @@ var init_agent_manager = __esm({
|
|
|
20489
20740
|
} catch {
|
|
20490
20741
|
}
|
|
20491
20742
|
}
|
|
20743
|
+
/** Drive THIS session's connected browser from host-side tool code and await the
|
|
20744
|
+
* result (mirrors the browser-cli round-trip, but in-process). Used by the design
|
|
20745
|
+
* MCP tools (capture_element_styles). Rejects after 15s if the host never replies
|
|
20746
|
+
* (e.g. no preview open). Reuses the existing onBrowserRequest/sendBrowserResponse
|
|
20747
|
+
* pair — the host neither knows nor cares the requestId originated here. */
|
|
20748
|
+
requestBrowser(live, action, params) {
|
|
20749
|
+
return new Promise((resolve9, reject) => {
|
|
20750
|
+
const requestId = `design:${randomUUID2()}`;
|
|
20751
|
+
const timer = setTimeout(() => {
|
|
20752
|
+
this.pendingBrowserResolvers.delete(requestId);
|
|
20753
|
+
reject(new Error("browser request timed out"));
|
|
20754
|
+
}, 15e3);
|
|
20755
|
+
this.pendingBrowserResolvers.set(requestId, { resolve: resolve9, reject, timer });
|
|
20756
|
+
try {
|
|
20757
|
+
this.onBrowserRequest(requestId, action, params, live.browserId, live.windowId);
|
|
20758
|
+
} catch (err) {
|
|
20759
|
+
this.pendingBrowserResolvers.delete(requestId);
|
|
20760
|
+
clearTimeout(timer);
|
|
20761
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
20762
|
+
}
|
|
20763
|
+
});
|
|
20764
|
+
}
|
|
20492
20765
|
/** Resolve a parked canUseTool decision (client replied with chat:permission).
|
|
20493
20766
|
* No-op if the request is unknown (already resolved / aborted). On "allow &
|
|
20494
20767
|
* don't ask again" (persist) we hand the SDK its own suggested permission
|
|
@@ -20595,9 +20868,9 @@ var init_agent_manager = __esm({
|
|
|
20595
20868
|
const transcripts = [];
|
|
20596
20869
|
for (const sid of sessionIds) {
|
|
20597
20870
|
const msgs = await this.sessionStore.getSessionMessages(sid).catch(() => []);
|
|
20598
|
-
const
|
|
20599
|
-
if (
|
|
20600
|
-
transcripts.push(
|
|
20871
|
+
const text2 = msgs.map((m) => `${m.role === "user" ? "User" : "Assistant"}: ${m.content}`).join("\n").slice(0, PER_SOURCE_CAP);
|
|
20872
|
+
if (text2.trim())
|
|
20873
|
+
transcripts.push(text2);
|
|
20601
20874
|
}
|
|
20602
20875
|
if (transcripts.length === 0)
|
|
20603
20876
|
return;
|
|
@@ -20676,6 +20949,11 @@ ${t}`)
|
|
|
20676
20949
|
const cli = `ELECTRON_RUN_AS_NODE=1 "${process.execPath}" "${this.browserCliPath}"`;
|
|
20677
20950
|
const pageInfo = url2 ? `
|
|
20678
20951
|
The user's current browser tab is: ${url2}` : "";
|
|
20952
|
+
const designClause = this.projectDir && existsSync2(join7(this.projectDir, TOKENS_FILE)) ? `
|
|
20953
|
+
|
|
20954
|
+
DESIGN SYSTEM:
|
|
20955
|
+
- 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.` : "";
|
|
20956
|
+
const mobileClause = this.projectDir ? buildMobileClause(this.projectDir) : "";
|
|
20679
20957
|
return `You are Fineguide Tesseract, an AI assistant helping developers inspect and fix web pages.
|
|
20680
20958
|
You have direct access to the browser connected to this conversation via CLI tools. Use the Bash tool to call them:${pageInfo}
|
|
20681
20959
|
|
|
@@ -20692,19 +20970,19 @@ CRITICAL RULES:
|
|
|
20692
20970
|
- Use screenshot to see the visual state.
|
|
20693
20971
|
- When element selectors are provided, use click or evaluate to interact.
|
|
20694
20972
|
- You can read and edit project source files if a project directory is configured.
|
|
20695
|
-
- Always confirm before making destructive changes to source files
|
|
20973
|
+
- Always confirm before making destructive changes to source files.${designClause}${mobileClause}`;
|
|
20696
20974
|
}
|
|
20697
20975
|
async sendMessage(params) {
|
|
20698
20976
|
if (params.images && params.images.length > 0) {
|
|
20699
|
-
const imgDir =
|
|
20700
|
-
await
|
|
20977
|
+
const imgDir = join7(tmpdir(), "ccb-images");
|
|
20978
|
+
await mkdir3(imgDir, { recursive: true });
|
|
20701
20979
|
const paths = [];
|
|
20702
20980
|
for (let i = 0; i < params.images.length; i++) {
|
|
20703
20981
|
const match = params.images[i].match(/^data:image\/(\w+);base64,(.+)$/);
|
|
20704
20982
|
if (match) {
|
|
20705
20983
|
const ext = match[1] === "jpeg" ? "jpg" : match[1];
|
|
20706
|
-
const filePath =
|
|
20707
|
-
await
|
|
20984
|
+
const filePath = join7(imgDir, `img-${process.pid}-${Date.now()}-${randomUUID2().slice(0, 8)}-${i}.${ext}`);
|
|
20985
|
+
await writeFile3(filePath, Buffer.from(match[2], "base64"));
|
|
20708
20986
|
paths.push(filePath);
|
|
20709
20987
|
}
|
|
20710
20988
|
}
|
|
@@ -20713,8 +20991,8 @@ CRITICAL RULES:
|
|
|
20713
20991
|
}
|
|
20714
20992
|
}
|
|
20715
20993
|
if (params.files && params.files.length > 0) {
|
|
20716
|
-
const fileDir =
|
|
20717
|
-
await
|
|
20994
|
+
const fileDir = join7(tmpdir(), "ccb-files");
|
|
20995
|
+
await mkdir3(fileDir, { recursive: true });
|
|
20718
20996
|
const paths = [];
|
|
20719
20997
|
for (let i = 0; i < params.files.length; i++) {
|
|
20720
20998
|
const f = params.files[i];
|
|
@@ -20722,8 +21000,8 @@ CRITICAL RULES:
|
|
|
20722
21000
|
if (!match)
|
|
20723
21001
|
continue;
|
|
20724
21002
|
const safe = (f.name || `file-${i}`).replace(/[^\w.\-]+/g, "_").slice(-100);
|
|
20725
|
-
const filePath =
|
|
20726
|
-
await
|
|
21003
|
+
const filePath = join7(fileDir, `${process.pid}-${Date.now()}-${randomUUID2().slice(0, 8)}-${i}-${safe}`);
|
|
21004
|
+
await writeFile3(filePath, Buffer.from(match[1], "base64"));
|
|
20727
21005
|
paths.push(filePath);
|
|
20728
21006
|
}
|
|
20729
21007
|
if (paths.length > 0) {
|
|
@@ -20901,6 +21179,15 @@ CRITICAL RULES:
|
|
|
20901
21179
|
const cronTools = buildCronTools({ store: this.cronStore, pushEnabled: this.cronToolsDeps.pushEnabled, dispatchPush: this.cronToolsDeps.dispatchPush, getSessionId: () => live.sessionId || void 0 });
|
|
20902
21180
|
mcp["tesseract-cron"] = createSdkMcpServer({ name: "tesseract-cron", version: "0.1.0", tools: cronTools });
|
|
20903
21181
|
}
|
|
21182
|
+
if (this.projectDir) {
|
|
21183
|
+
const designTools = buildDesignTools({
|
|
21184
|
+
getProjectDir: () => this.projectDir,
|
|
21185
|
+
driveBrowser: (action, params2) => this.requestBrowser(live, action, params2),
|
|
21186
|
+
getSessionId: () => live.sessionId || void 0,
|
|
21187
|
+
notifyPreviewReady: (url2, kind) => this.send({ type: "agent:preview_ready", sessionId: live.sessionId, previewUrl: url2, kind, ts: Date.now() }, live.origin)
|
|
21188
|
+
});
|
|
21189
|
+
mcp["tesseract-design"] = createSdkMcpServer({ name: "tesseract-design", version: "0.1.0", tools: designTools });
|
|
21190
|
+
}
|
|
20904
21191
|
return Object.keys(mcp).length > 0 ? { mcpServers: mcp } : {};
|
|
20905
21192
|
})(),
|
|
20906
21193
|
// Skills (Epic H): a local plugin bundling the enabled ClawHub skills, so the SDK
|
|
@@ -20914,20 +21201,20 @@ CRITICAL RULES:
|
|
|
20914
21201
|
// in acceptEdits, everything risky in default/auto). We park a Promise and
|
|
20915
21202
|
// resolve it when the client replies via chat:permission (respondToPermission),
|
|
20916
21203
|
// or deny on abort so an interrupted turn never leaks a pending decision.
|
|
20917
|
-
canUseTool: (toolName, input, opts) => new Promise((
|
|
21204
|
+
canUseTool: (toolName, input, opts) => new Promise((resolve9) => {
|
|
20918
21205
|
const requestId = randomUUID2();
|
|
20919
21206
|
const onAbort = () => {
|
|
20920
21207
|
if (this.pendingPermissions.delete(requestId)) {
|
|
20921
|
-
|
|
21208
|
+
resolve9({ behavior: "deny", message: "Interrupted.", interrupt: true });
|
|
20922
21209
|
}
|
|
20923
21210
|
};
|
|
20924
21211
|
const cleanup2 = () => opts.signal.removeEventListener("abort", onAbort);
|
|
20925
21212
|
if (opts.signal.aborted) {
|
|
20926
|
-
|
|
21213
|
+
resolve9({ behavior: "deny", message: "Interrupted.", interrupt: true });
|
|
20927
21214
|
return;
|
|
20928
21215
|
}
|
|
20929
21216
|
opts.signal.addEventListener("abort", onAbort, { once: true });
|
|
20930
|
-
this.pendingPermissions.set(requestId, { resolve:
|
|
21217
|
+
this.pendingPermissions.set(requestId, { resolve: resolve9, suggestions: opts.suggestions, cleanup: cleanup2, origin: live.origin });
|
|
20931
21218
|
const evt = {
|
|
20932
21219
|
type: "agent:permission_request",
|
|
20933
21220
|
sessionId: live.sessionId,
|
|
@@ -20953,19 +21240,19 @@ CRITICAL RULES:
|
|
|
20953
21240
|
// M5 H6 — an MCP server requesting user input (a form, or url-based OAuth).
|
|
20954
21241
|
// Default is auto-cancel; we park a Promise and raise an inline card, then
|
|
20955
21242
|
// resolve it from chat:elicitation (respondToElicitation). Mirrors canUseTool.
|
|
20956
|
-
onElicitation: (request, opts) => new Promise((
|
|
21243
|
+
onElicitation: (request, opts) => new Promise((resolve9) => {
|
|
20957
21244
|
const requestId = randomUUID2();
|
|
20958
21245
|
const onAbort = () => {
|
|
20959
21246
|
if (this.pendingElicitations.delete(requestId))
|
|
20960
|
-
|
|
21247
|
+
resolve9({ action: "cancel" });
|
|
20961
21248
|
};
|
|
20962
21249
|
const cleanup2 = () => opts.signal.removeEventListener("abort", onAbort);
|
|
20963
21250
|
if (opts.signal.aborted) {
|
|
20964
|
-
|
|
21251
|
+
resolve9({ action: "cancel" });
|
|
20965
21252
|
return;
|
|
20966
21253
|
}
|
|
20967
21254
|
opts.signal.addEventListener("abort", onAbort, { once: true });
|
|
20968
|
-
this.pendingElicitations.set(requestId, { resolve:
|
|
21255
|
+
this.pendingElicitations.set(requestId, { resolve: resolve9, cleanup: cleanup2, origin: live.origin });
|
|
20969
21256
|
const evt = {
|
|
20970
21257
|
type: "agent:elicitation_request",
|
|
20971
21258
|
sessionId: live.sessionId,
|
|
@@ -21185,26 +21472,26 @@ CRITICAL RULES:
|
|
|
21185
21472
|
emit({ type: "chat:stream", sessionId: sid, delta: event.delta.thinking, messageId: message.uuid, kind: "thinking", ...parentField });
|
|
21186
21473
|
}
|
|
21187
21474
|
if (event.delta?.type === "text_delta" && event.delta.text) {
|
|
21188
|
-
const
|
|
21189
|
-
if (/<(?:tool_call|tool_result|function_calls|antml:function_calls)[\s>]/i.test(
|
|
21475
|
+
const text2 = event.delta.text;
|
|
21476
|
+
if (/<(?:tool_call|tool_result|function_calls|antml:function_calls)[\s>]/i.test(text2)) {
|
|
21190
21477
|
insideXmlByKey.set(key2, true);
|
|
21191
21478
|
break;
|
|
21192
21479
|
}
|
|
21193
21480
|
if (insideXmlByKey.get(key2)) {
|
|
21194
|
-
if (/<\/(?:tool_call|tool_result|function_calls|antml:function_calls)\s*>/i.test(
|
|
21481
|
+
if (/<\/(?:tool_call|tool_result|function_calls|antml:function_calls)\s*>/i.test(text2)) {
|
|
21195
21482
|
insideXmlByKey.set(key2, false);
|
|
21196
21483
|
}
|
|
21197
21484
|
break;
|
|
21198
21485
|
}
|
|
21199
|
-
if (/<\/?(?:invoke|antml:invoke|antml:parameter)[\s>]/.test(
|
|
21486
|
+
if (/<\/?(?:invoke|antml:invoke|antml:parameter)[\s>]/.test(text2))
|
|
21200
21487
|
break;
|
|
21201
|
-
if (/<parameter\s+name=/.test(
|
|
21488
|
+
if (/<parameter\s+name=/.test(text2))
|
|
21202
21489
|
break;
|
|
21203
|
-
if (/^\s*<\/(?:parameter|invoke|function_calls)>\s*$/.test(
|
|
21490
|
+
if (/^\s*<\/(?:parameter|invoke|function_calls)>\s*$/.test(text2))
|
|
21204
21491
|
break;
|
|
21205
21492
|
if (parentToolUseId === void 0)
|
|
21206
21493
|
turnStreamed = true;
|
|
21207
|
-
emit({ type: "chat:stream", sessionId: sid, delta:
|
|
21494
|
+
emit({ type: "chat:stream", sessionId: sid, delta: text2, messageId: message.uuid, kind: "text", ...parentField });
|
|
21208
21495
|
}
|
|
21209
21496
|
if (event.delta?.type === "input_json_delta" && event.delta.partial_json) {
|
|
21210
21497
|
const acc = blockAcc.get(key2);
|
|
@@ -21447,11 +21734,11 @@ Compacted earlier context.` });
|
|
|
21447
21734
|
case "files_persisted":
|
|
21448
21735
|
break;
|
|
21449
21736
|
default: {
|
|
21450
|
-
const
|
|
21737
|
+
const text2 = extractHumanReadable(m);
|
|
21451
21738
|
const header = systemHeader("system", subtype);
|
|
21452
|
-
const body =
|
|
21739
|
+
const body = text2 ? `${header}
|
|
21453
21740
|
|
|
21454
|
-
${
|
|
21741
|
+
${text2}` : header;
|
|
21455
21742
|
emit({ type: "agent:tool_use", sessionId: sid, toolName: "_notice_", summary: body });
|
|
21456
21743
|
log("best-effort surfaced unknown system subtype:", subtype ?? "?");
|
|
21457
21744
|
break;
|
|
@@ -21487,12 +21774,12 @@ ${text}` : header;
|
|
|
21487
21774
|
const tn = toolNameByUseId.get(toolUseId);
|
|
21488
21775
|
if (tn === "Edit" || tn === "Write" || tn === "MultiEdit" || tn === "NotebookEdit")
|
|
21489
21776
|
continue;
|
|
21490
|
-
const { text, truncated } = flattenToolResultContent(blk.content);
|
|
21777
|
+
const { text: text2, truncated } = flattenToolResultContent(blk.content);
|
|
21491
21778
|
const images = extractImages(blk.content);
|
|
21492
21779
|
const isError = blk.is_error === true;
|
|
21493
|
-
if (!
|
|
21780
|
+
if (!text2 && images.length === 0 && !isError)
|
|
21494
21781
|
continue;
|
|
21495
|
-
emit({ type: "agent:tool_result", sessionId: sid, toolUseId, isError, output:
|
|
21782
|
+
emit({ type: "agent:tool_result", sessionId: sid, toolUseId, isError, output: text2, images, truncated, ...agentId ? { agentId } : {} });
|
|
21496
21783
|
} else if (blk?.type === "web_search_tool_result") {
|
|
21497
21784
|
const toolUseId = blk.tool_use_id;
|
|
21498
21785
|
if (!toolUseId)
|
|
@@ -21509,11 +21796,11 @@ ${text}` : header;
|
|
|
21509
21796
|
break;
|
|
21510
21797
|
default: {
|
|
21511
21798
|
const m = message;
|
|
21512
|
-
const
|
|
21799
|
+
const text2 = extractHumanReadable(m);
|
|
21513
21800
|
const header = systemHeader(m.type || "unknown");
|
|
21514
|
-
const body =
|
|
21801
|
+
const body = text2 ? `${header}
|
|
21515
21802
|
|
|
21516
|
-
${
|
|
21803
|
+
${text2}` : header;
|
|
21517
21804
|
emit({ type: "agent:tool_use", sessionId: sid, toolName: "_notice_", summary: body });
|
|
21518
21805
|
log("best-effort surfaced unknown SDK message type:", m.type || "?");
|
|
21519
21806
|
break;
|
|
@@ -21818,6 +22105,8 @@ Element ${i + 1}:`);
|
|
|
21818
22105
|
parts.push(` XPath: ${a.xpath}`, ` CSS: ${a.selector}`, ` HTML: ${a.htmlSnippet}`);
|
|
21819
22106
|
if (a.textPreview)
|
|
21820
22107
|
parts.push(` Text: "${a.textPreview}"`);
|
|
22108
|
+
if (a.sourceLoc)
|
|
22109
|
+
parts.push(` Source: ${a.sourceLoc.file}:${a.sourceLoc.line}${a.sourceLoc.column != null ? `:${a.sourceLoc.column}` : ""} (edit the element here)`);
|
|
21821
22110
|
}
|
|
21822
22111
|
}
|
|
21823
22112
|
return parts.join("\n");
|
|
@@ -21830,15 +22119,23 @@ Element ${i + 1}:`);
|
|
|
21830
22119
|
var dist_exports = {};
|
|
21831
22120
|
__export(dist_exports, {
|
|
21832
22121
|
AgentManager: () => AgentManager,
|
|
22122
|
+
DESIGN_CLAUDE_MD: () => DESIGN_CLAUDE_MD,
|
|
22123
|
+
DESIGN_DIR: () => DESIGN_DIR,
|
|
22124
|
+
DesignTokensSchema: () => DesignTokensSchema,
|
|
21833
22125
|
SessionStore: () => SessionStore,
|
|
22126
|
+
TOKENS_CSS_FILE: () => TOKENS_CSS_FILE,
|
|
22127
|
+
TOKENS_FILE: () => TOKENS_FILE,
|
|
21834
22128
|
buildClaudeNarrationLlm: () => buildClaudeNarrationLlm,
|
|
21835
22129
|
exportSession: () => exportSession,
|
|
22130
|
+
getTokenPath: () => getTokenPath,
|
|
21836
22131
|
importSession: () => importSession,
|
|
21837
22132
|
log: () => log,
|
|
21838
22133
|
resolveOauthToken: () => resolveOauthToken,
|
|
21839
22134
|
sanitizeProjectDir: () => sanitizeProjectDir,
|
|
21840
22135
|
sessionDir: () => sessionDir,
|
|
21841
22136
|
sessionFile: () => sessionFile,
|
|
22137
|
+
setTokenPath: () => setTokenPath,
|
|
22138
|
+
tokensToCss: () => tokensToCss,
|
|
21842
22139
|
transferSession: () => transferSession
|
|
21843
22140
|
});
|
|
21844
22141
|
var init_dist2 = __esm({
|
|
@@ -21849,6 +22146,7 @@ var init_dist2 = __esm({
|
|
|
21849
22146
|
init_session_usage();
|
|
21850
22147
|
init_session_transfer();
|
|
21851
22148
|
init_log();
|
|
22149
|
+
init_design_tokens();
|
|
21852
22150
|
}
|
|
21853
22151
|
});
|
|
21854
22152
|
|
|
@@ -23056,11 +23354,11 @@ function __metadata(metadataKey, metadataValue) {
|
|
|
23056
23354
|
}
|
|
23057
23355
|
function __awaiter(thisArg, _arguments, P, generator) {
|
|
23058
23356
|
function adopt(value) {
|
|
23059
|
-
return value instanceof P ? value : new P(function(
|
|
23060
|
-
|
|
23357
|
+
return value instanceof P ? value : new P(function(resolve9) {
|
|
23358
|
+
resolve9(value);
|
|
23061
23359
|
});
|
|
23062
23360
|
}
|
|
23063
|
-
return new (P || (P = Promise))(function(
|
|
23361
|
+
return new (P || (P = Promise))(function(resolve9, reject) {
|
|
23064
23362
|
function fulfilled(value) {
|
|
23065
23363
|
try {
|
|
23066
23364
|
step(generator.next(value));
|
|
@@ -23076,7 +23374,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
|
|
|
23076
23374
|
}
|
|
23077
23375
|
}
|
|
23078
23376
|
function step(result) {
|
|
23079
|
-
result.done ?
|
|
23377
|
+
result.done ? resolve9(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
23080
23378
|
}
|
|
23081
23379
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
23082
23380
|
});
|
|
@@ -23267,14 +23565,14 @@ function __asyncValues(o) {
|
|
|
23267
23565
|
}, i);
|
|
23268
23566
|
function verb(n) {
|
|
23269
23567
|
i[n] = o[n] && function(v) {
|
|
23270
|
-
return new Promise(function(
|
|
23271
|
-
v = o[n](v), settle(
|
|
23568
|
+
return new Promise(function(resolve9, reject) {
|
|
23569
|
+
v = o[n](v), settle(resolve9, reject, v.done, v.value);
|
|
23272
23570
|
});
|
|
23273
23571
|
};
|
|
23274
23572
|
}
|
|
23275
|
-
function settle(
|
|
23573
|
+
function settle(resolve9, reject, d, v) {
|
|
23276
23574
|
Promise.resolve(v).then(function(v2) {
|
|
23277
|
-
|
|
23575
|
+
resolve9({ value: v2, done: d });
|
|
23278
23576
|
}, reject);
|
|
23279
23577
|
}
|
|
23280
23578
|
}
|
|
@@ -23552,8 +23850,8 @@ var require_build = __commonJS({
|
|
|
23552
23850
|
var BASE64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
|
|
23553
23851
|
var BASE64URL_REGEX = /^[a-zA-Z0-9-_]+$/;
|
|
23554
23852
|
var Utf8Converter = class {
|
|
23555
|
-
static fromString(
|
|
23556
|
-
const s = unescape(encodeURIComponent(
|
|
23853
|
+
static fromString(text2) {
|
|
23854
|
+
const s = unescape(encodeURIComponent(text2));
|
|
23557
23855
|
const uintArray = new Uint8Array(s.length);
|
|
23558
23856
|
for (let i = 0; i < s.length; i++) {
|
|
23559
23857
|
uintArray[i] = s.charCodeAt(i);
|
|
@@ -23581,11 +23879,11 @@ var require_build = __commonJS({
|
|
|
23581
23879
|
}
|
|
23582
23880
|
return res;
|
|
23583
23881
|
}
|
|
23584
|
-
static fromString(
|
|
23585
|
-
const res = new ArrayBuffer(
|
|
23882
|
+
static fromString(text2, littleEndian = false) {
|
|
23883
|
+
const res = new ArrayBuffer(text2.length * 2);
|
|
23586
23884
|
const dataView = new DataView(res);
|
|
23587
|
-
for (let i = 0; i <
|
|
23588
|
-
dataView.setUint16(i * 2,
|
|
23885
|
+
for (let i = 0; i < text2.length; i++) {
|
|
23886
|
+
dataView.setUint16(i * 2, text2.charCodeAt(i), littleEndian);
|
|
23589
23887
|
}
|
|
23590
23888
|
return res;
|
|
23591
23889
|
}
|
|
@@ -23682,18 +23980,18 @@ var require_build = __commonJS({
|
|
|
23682
23980
|
static ToBase64Url(data) {
|
|
23683
23981
|
return this.ToBase64(data).replace(/\+/g, "-").replace(/\//g, "_").replace(/\=/g, "");
|
|
23684
23982
|
}
|
|
23685
|
-
static FromUtf8String(
|
|
23983
|
+
static FromUtf8String(text2, encoding = _Convert.DEFAULT_UTF8_ENCODING) {
|
|
23686
23984
|
switch (encoding) {
|
|
23687
23985
|
case "ascii":
|
|
23688
|
-
return this.FromBinary(
|
|
23986
|
+
return this.FromBinary(text2);
|
|
23689
23987
|
case "utf8":
|
|
23690
|
-
return Utf8Converter.fromString(
|
|
23988
|
+
return Utf8Converter.fromString(text2);
|
|
23691
23989
|
case "utf16":
|
|
23692
23990
|
case "utf16be":
|
|
23693
|
-
return Utf16Converter.fromString(
|
|
23991
|
+
return Utf16Converter.fromString(text2);
|
|
23694
23992
|
case "utf16le":
|
|
23695
23993
|
case "usc2":
|
|
23696
|
-
return Utf16Converter.fromString(
|
|
23994
|
+
return Utf16Converter.fromString(text2, true);
|
|
23697
23995
|
default:
|
|
23698
23996
|
throw new Error(`Unknown type of encoding '${encoding}'`);
|
|
23699
23997
|
}
|
|
@@ -23714,11 +24012,11 @@ var require_build = __commonJS({
|
|
|
23714
24012
|
throw new Error(`Unknown type of encoding '${encoding}'`);
|
|
23715
24013
|
}
|
|
23716
24014
|
}
|
|
23717
|
-
static FromBinary(
|
|
23718
|
-
const stringLength =
|
|
24015
|
+
static FromBinary(text2) {
|
|
24016
|
+
const stringLength = text2.length;
|
|
23719
24017
|
const resultView = new Uint8Array(stringLength);
|
|
23720
24018
|
for (let i = 0; i < stringLength; i++) {
|
|
23721
|
-
resultView[i] =
|
|
24019
|
+
resultView[i] = text2.charCodeAt(i);
|
|
23722
24020
|
}
|
|
23723
24021
|
return resultView.buffer;
|
|
23724
24022
|
}
|
|
@@ -23764,8 +24062,8 @@ var require_build = __commonJS({
|
|
|
23764
24062
|
static ToUtf16String(buffer, littleEndian = false) {
|
|
23765
24063
|
return Utf16Converter.toString(buffer, littleEndian);
|
|
23766
24064
|
}
|
|
23767
|
-
static FromUtf16String(
|
|
23768
|
-
return Utf16Converter.fromString(
|
|
24065
|
+
static FromUtf16String(text2, littleEndian = false) {
|
|
24066
|
+
return Utf16Converter.fromString(text2, littleEndian);
|
|
23769
24067
|
}
|
|
23770
24068
|
static Base64Padding(base643) {
|
|
23771
24069
|
const padCount = 4 - base643.length % 4;
|
|
@@ -27526,15 +27824,15 @@ var require_sequence = __commonJS({
|
|
|
27526
27824
|
}
|
|
27527
27825
|
return normalized;
|
|
27528
27826
|
}
|
|
27529
|
-
function encodeAscii(
|
|
27530
|
-
const bytes = new Uint8Array(
|
|
27531
|
-
for (let i = 0; i <
|
|
27532
|
-
bytes[i] =
|
|
27827
|
+
function encodeAscii(text2) {
|
|
27828
|
+
const bytes = new Uint8Array(text2.length);
|
|
27829
|
+
for (let i = 0; i < text2.length; i++) {
|
|
27830
|
+
bytes[i] = text2.charCodeAt(i) & 255;
|
|
27533
27831
|
}
|
|
27534
27832
|
return bytes;
|
|
27535
27833
|
}
|
|
27536
|
-
function encodeUtf8(
|
|
27537
|
-
return new TextEncoder().encode(
|
|
27834
|
+
function encodeUtf8(text2) {
|
|
27835
|
+
return new TextEncoder().encode(text2);
|
|
27538
27836
|
}
|
|
27539
27837
|
function toPatternBytes(pattern, options) {
|
|
27540
27838
|
if (typeof pattern === "string") {
|
|
@@ -28909,15 +29207,15 @@ var require_binary = __commonJS({
|
|
|
28909
29207
|
}
|
|
28910
29208
|
return result;
|
|
28911
29209
|
}
|
|
28912
|
-
function decode3(
|
|
28913
|
-
const result = new Uint8Array(
|
|
28914
|
-
for (let i = 0; i <
|
|
28915
|
-
result[i] =
|
|
29210
|
+
function decode3(text2) {
|
|
29211
|
+
const result = new Uint8Array(text2.length);
|
|
29212
|
+
for (let i = 0; i < text2.length; i++) {
|
|
29213
|
+
result[i] = text2.charCodeAt(i) & 255;
|
|
28916
29214
|
}
|
|
28917
29215
|
return result;
|
|
28918
29216
|
}
|
|
28919
|
-
function is(
|
|
28920
|
-
return typeof
|
|
29217
|
+
function is(text2) {
|
|
29218
|
+
return typeof text2 === "string";
|
|
28921
29219
|
}
|
|
28922
29220
|
exports.binary = { encode: encode3, decode: decode3, is };
|
|
28923
29221
|
}
|
|
@@ -28952,31 +29250,31 @@ var require_hex = __commonJS({
|
|
|
28952
29250
|
throw new TypeError("Hex separators must be non-empty strings");
|
|
28953
29251
|
}
|
|
28954
29252
|
}
|
|
28955
|
-
function matchSeparator(
|
|
29253
|
+
function matchSeparator(text2, index, separators) {
|
|
28956
29254
|
for (const separator of separators) {
|
|
28957
|
-
if (
|
|
29255
|
+
if (text2.startsWith(separator, index)) {
|
|
28958
29256
|
return separator;
|
|
28959
29257
|
}
|
|
28960
29258
|
}
|
|
28961
29259
|
return void 0;
|
|
28962
29260
|
}
|
|
28963
|
-
function detectCase(
|
|
28964
|
-
const hasUpper = /[A-F]/.test(
|
|
28965
|
-
const hasLower = /[a-f]/.test(
|
|
29261
|
+
function detectCase(text2) {
|
|
29262
|
+
const hasUpper = /[A-F]/.test(text2);
|
|
29263
|
+
const hasLower = /[a-f]/.test(text2);
|
|
28966
29264
|
return hasUpper && !hasLower ? "upper" : "lower";
|
|
28967
29265
|
}
|
|
28968
|
-
function detectLineSeparator(
|
|
28969
|
-
const match = /\r\n|\n/.exec(
|
|
29266
|
+
function detectLineSeparator(text2) {
|
|
29267
|
+
const match = /\r\n|\n/.exec(text2);
|
|
28970
29268
|
if (!match) {
|
|
28971
29269
|
return void 0;
|
|
28972
29270
|
}
|
|
28973
29271
|
return match[0] === "\r\n" ? "\r\n" : "\n";
|
|
28974
29272
|
}
|
|
28975
|
-
function compactForDetection(
|
|
28976
|
-
return
|
|
29273
|
+
function compactForDetection(text2) {
|
|
29274
|
+
return text2.replace(/[^0-9a-f]/gi, "");
|
|
28977
29275
|
}
|
|
28978
|
-
function detectGroup(
|
|
28979
|
-
const segments =
|
|
29276
|
+
function detectGroup(text2) {
|
|
29277
|
+
const segments = text2.match(/[0-9A-Fa-f]+|[^0-9A-Fa-f]+/g) ?? [];
|
|
28980
29278
|
if (segments.length < 3) {
|
|
28981
29279
|
return void 0;
|
|
28982
29280
|
}
|
|
@@ -29004,8 +29302,8 @@ var require_hex = __commonJS({
|
|
|
29004
29302
|
separator
|
|
29005
29303
|
};
|
|
29006
29304
|
}
|
|
29007
|
-
function detectFormat(
|
|
29008
|
-
const trimmed =
|
|
29305
|
+
function detectFormat(text2) {
|
|
29306
|
+
const trimmed = text2.trim();
|
|
29009
29307
|
const prefix = /^0x/i.test(trimmed) ? "0x" : "";
|
|
29010
29308
|
const body = prefix ? trimmed.slice(2) : trimmed;
|
|
29011
29309
|
const lineSeparator = detectLineSeparator(body);
|
|
@@ -29030,13 +29328,13 @@ var require_hex = __commonJS({
|
|
|
29030
29328
|
}
|
|
29031
29329
|
return format2;
|
|
29032
29330
|
}
|
|
29033
|
-
function normalizeText(
|
|
29331
|
+
function normalizeText(text2, options) {
|
|
29034
29332
|
const allowPrefix = options.allowPrefix ?? true;
|
|
29035
29333
|
const separators = [...resolveSeparators(options)].sort((left, right) => right.length - left.length);
|
|
29036
29334
|
for (const separator of separators) {
|
|
29037
29335
|
validateSeparator(separator);
|
|
29038
29336
|
}
|
|
29039
|
-
let working =
|
|
29337
|
+
let working = text2.trim();
|
|
29040
29338
|
if (/^0x/i.test(working)) {
|
|
29041
29339
|
if (!allowPrefix) {
|
|
29042
29340
|
throw new TypeError("Hexadecimal text must not include a 0x prefix");
|
|
@@ -29087,15 +29385,15 @@ var require_hex = __commonJS({
|
|
|
29087
29385
|
}
|
|
29088
29386
|
return chunks.join(group.separator);
|
|
29089
29387
|
}
|
|
29090
|
-
function normalize2(
|
|
29091
|
-
return normalizeText(
|
|
29388
|
+
function normalize2(text2, options = {}) {
|
|
29389
|
+
return normalizeText(text2, options);
|
|
29092
29390
|
}
|
|
29093
|
-
function is(
|
|
29094
|
-
if (typeof
|
|
29391
|
+
function is(text2, options = {}) {
|
|
29392
|
+
if (typeof text2 !== "string") {
|
|
29095
29393
|
return false;
|
|
29096
29394
|
}
|
|
29097
29395
|
try {
|
|
29098
|
-
normalize2(
|
|
29396
|
+
normalize2(text2, options);
|
|
29099
29397
|
return true;
|
|
29100
29398
|
} catch {
|
|
29101
29399
|
return false;
|
|
@@ -29105,8 +29403,8 @@ var require_hex = __commonJS({
|
|
|
29105
29403
|
const bytes = (0, index_js_1.toUint8Array)(data);
|
|
29106
29404
|
const casing = options.case ?? "lower";
|
|
29107
29405
|
const pairs = Array.from(bytes, (byte) => {
|
|
29108
|
-
const
|
|
29109
|
-
return casing === "upper" ?
|
|
29406
|
+
const text2 = byte.toString(16).padStart(2, "0");
|
|
29407
|
+
return casing === "upper" ? text2.toUpperCase() : text2;
|
|
29110
29408
|
});
|
|
29111
29409
|
let body = "";
|
|
29112
29410
|
if (options.line) {
|
|
@@ -29125,19 +29423,19 @@ var require_hex = __commonJS({
|
|
|
29125
29423
|
}
|
|
29126
29424
|
return `${options.prefix ?? ""}${body}`;
|
|
29127
29425
|
}
|
|
29128
|
-
function decode3(
|
|
29129
|
-
const normalized = normalize2(
|
|
29426
|
+
function decode3(text2, options = {}) {
|
|
29427
|
+
const normalized = normalize2(text2, options);
|
|
29130
29428
|
const result = new Uint8Array(normalized.length / 2);
|
|
29131
29429
|
for (let i = 0; i < normalized.length; i += 2) {
|
|
29132
29430
|
result[i / 2] = Number.parseInt(normalized.slice(i, i + 2), 16);
|
|
29133
29431
|
}
|
|
29134
29432
|
return result;
|
|
29135
29433
|
}
|
|
29136
|
-
function parse3(
|
|
29137
|
-
const normalized = normalize2(
|
|
29434
|
+
function parse3(text2, options = {}) {
|
|
29435
|
+
const normalized = normalize2(text2, options);
|
|
29138
29436
|
return {
|
|
29139
29437
|
bytes: decode3(normalized),
|
|
29140
|
-
format: detectFormat(
|
|
29438
|
+
format: detectFormat(text2),
|
|
29141
29439
|
normalized
|
|
29142
29440
|
};
|
|
29143
29441
|
}
|
|
@@ -29165,8 +29463,8 @@ var require_utf8 = __commonJS({
|
|
|
29165
29463
|
exports.encode = encode3;
|
|
29166
29464
|
exports.decode = decode3;
|
|
29167
29465
|
var index_js_1 = require_bytes();
|
|
29168
|
-
function encode3(
|
|
29169
|
-
return new TextEncoder().encode(
|
|
29466
|
+
function encode3(text2) {
|
|
29467
|
+
return new TextEncoder().encode(text2);
|
|
29170
29468
|
}
|
|
29171
29469
|
function decode3(data) {
|
|
29172
29470
|
return new TextDecoder("utf-8", { fatal: false }).decode((0, index_js_1.toUint8Array)(data));
|
|
@@ -29184,11 +29482,11 @@ var require_utf16 = __commonJS({
|
|
|
29184
29482
|
exports.encode = encode3;
|
|
29185
29483
|
exports.decode = decode3;
|
|
29186
29484
|
var index_js_1 = require_bytes();
|
|
29187
|
-
function encode3(
|
|
29188
|
-
const result = new ArrayBuffer(
|
|
29485
|
+
function encode3(text2, options = {}) {
|
|
29486
|
+
const result = new ArrayBuffer(text2.length * 2);
|
|
29189
29487
|
const view = new DataView(result);
|
|
29190
|
-
for (let i = 0; i <
|
|
29191
|
-
view.setUint16(i * 2,
|
|
29488
|
+
for (let i = 0; i < text2.length; i++) {
|
|
29489
|
+
view.setUint16(i * 2, text2.charCodeAt(i), options.littleEndian ?? false);
|
|
29192
29490
|
}
|
|
29193
29491
|
return new Uint8Array(result);
|
|
29194
29492
|
}
|
|
@@ -29222,18 +29520,18 @@ var require_base64 = __commonJS({
|
|
|
29222
29520
|
function nodeBuffer() {
|
|
29223
29521
|
return globalThis.Buffer;
|
|
29224
29522
|
}
|
|
29225
|
-
function normalize2(
|
|
29226
|
-
return
|
|
29523
|
+
function normalize2(text2) {
|
|
29524
|
+
return text2.replace(/[\n\r\t ]/g, "");
|
|
29227
29525
|
}
|
|
29228
|
-
function pad(
|
|
29229
|
-
const remainder =
|
|
29230
|
-
return remainder ?
|
|
29526
|
+
function pad(text2) {
|
|
29527
|
+
const remainder = text2.length % 4;
|
|
29528
|
+
return remainder ? text2 + "=".repeat(4 - remainder) : text2;
|
|
29231
29529
|
}
|
|
29232
|
-
function is(
|
|
29233
|
-
if (typeof
|
|
29530
|
+
function is(text2) {
|
|
29531
|
+
if (typeof text2 !== "string") {
|
|
29234
29532
|
return false;
|
|
29235
29533
|
}
|
|
29236
|
-
const normalized = normalize2(
|
|
29534
|
+
const normalized = normalize2(text2);
|
|
29237
29535
|
return normalized === "" || BASE64_REGEX.test(normalized);
|
|
29238
29536
|
}
|
|
29239
29537
|
function encode3(data, _options) {
|
|
@@ -29244,8 +29542,8 @@ var require_base64 = __commonJS({
|
|
|
29244
29542
|
}
|
|
29245
29543
|
return btoa((0, binary_js_1.encode)(bytes));
|
|
29246
29544
|
}
|
|
29247
|
-
function decode3(
|
|
29248
|
-
const normalized = normalize2(
|
|
29545
|
+
function decode3(text2, _options) {
|
|
29546
|
+
const normalized = normalize2(text2);
|
|
29249
29547
|
if (!is(normalized)) {
|
|
29250
29548
|
throw new TypeError("Input is not valid Base64 text");
|
|
29251
29549
|
}
|
|
@@ -29271,17 +29569,17 @@ var require_base64url = __commonJS({
|
|
|
29271
29569
|
exports.decode = decode3;
|
|
29272
29570
|
var base64_js_1 = require_base64();
|
|
29273
29571
|
var BASE64URL_REGEX = /^[A-Za-z0-9_-]*$/;
|
|
29274
|
-
function normalize2(
|
|
29275
|
-
return
|
|
29572
|
+
function normalize2(text2) {
|
|
29573
|
+
return text2.replace(/[\n\r\t ]/g, "");
|
|
29276
29574
|
}
|
|
29277
|
-
function is(
|
|
29278
|
-
return typeof
|
|
29575
|
+
function is(text2) {
|
|
29576
|
+
return typeof text2 === "string" && BASE64URL_REGEX.test(normalize2(text2));
|
|
29279
29577
|
}
|
|
29280
29578
|
function encode3(data, _options) {
|
|
29281
29579
|
return base64_js_1.base64.encode(data).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
29282
29580
|
}
|
|
29283
|
-
function decode3(
|
|
29284
|
-
const normalized = normalize2(
|
|
29581
|
+
function decode3(text2, _options) {
|
|
29582
|
+
const normalized = normalize2(text2);
|
|
29285
29583
|
if (!is(normalized)) {
|
|
29286
29584
|
throw new TypeError("Input is not valid Base64Url text");
|
|
29287
29585
|
}
|
|
@@ -29402,8 +29700,8 @@ var require_ip_converter = __commonJS({
|
|
|
29402
29700
|
}
|
|
29403
29701
|
return ip;
|
|
29404
29702
|
}
|
|
29405
|
-
static parseCIDR(
|
|
29406
|
-
const [addr, prefixStr] =
|
|
29703
|
+
static parseCIDR(text2) {
|
|
29704
|
+
const [addr, prefixStr] = text2.split("/");
|
|
29407
29705
|
const prefix = parseInt(prefixStr, 10);
|
|
29408
29706
|
if (this.isIPv4(addr)) {
|
|
29409
29707
|
if (prefix < 0 || prefix > 32) {
|
|
@@ -29456,9 +29754,9 @@ var require_ip_converter = __commonJS({
|
|
|
29456
29754
|
}
|
|
29457
29755
|
return this.decodeIP(encoding_1.hex.encode(buf));
|
|
29458
29756
|
}
|
|
29459
|
-
static fromString(
|
|
29460
|
-
if (
|
|
29461
|
-
const [addr, prefix] = this.parseCIDR(
|
|
29757
|
+
static fromString(text2) {
|
|
29758
|
+
if (text2.includes("/")) {
|
|
29759
|
+
const [addr, prefix] = this.parseCIDR(text2);
|
|
29462
29760
|
const maskBytes = new Uint8Array(addr.length);
|
|
29463
29761
|
let bitsLeft = prefix;
|
|
29464
29762
|
for (let i = 0; i < maskBytes.length; i++) {
|
|
@@ -29475,7 +29773,7 @@ var require_ip_converter = __commonJS({
|
|
|
29475
29773
|
out.set(maskBytes, addr.length);
|
|
29476
29774
|
return out.buffer;
|
|
29477
29775
|
}
|
|
29478
|
-
const bytes = this.isIPv4(
|
|
29776
|
+
const bytes = this.isIPv4(text2) ? this.parseIPv4(text2) : this.parseIPv6(text2);
|
|
29479
29777
|
return new Uint8Array(bytes).buffer;
|
|
29480
29778
|
}
|
|
29481
29779
|
};
|
|
@@ -34286,11 +34584,11 @@ function __metadata2(metadataKey, metadataValue) {
|
|
|
34286
34584
|
}
|
|
34287
34585
|
function __awaiter2(thisArg, _arguments, P, generator) {
|
|
34288
34586
|
function adopt(value) {
|
|
34289
|
-
return value instanceof P ? value : new P(function(
|
|
34290
|
-
|
|
34587
|
+
return value instanceof P ? value : new P(function(resolve9) {
|
|
34588
|
+
resolve9(value);
|
|
34291
34589
|
});
|
|
34292
34590
|
}
|
|
34293
|
-
return new (P || (P = Promise))(function(
|
|
34591
|
+
return new (P || (P = Promise))(function(resolve9, reject) {
|
|
34294
34592
|
function fulfilled(value) {
|
|
34295
34593
|
try {
|
|
34296
34594
|
step(generator.next(value));
|
|
@@ -34306,7 +34604,7 @@ function __awaiter2(thisArg, _arguments, P, generator) {
|
|
|
34306
34604
|
}
|
|
34307
34605
|
}
|
|
34308
34606
|
function step(result) {
|
|
34309
|
-
result.done ?
|
|
34607
|
+
result.done ? resolve9(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
34310
34608
|
}
|
|
34311
34609
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
34312
34610
|
});
|
|
@@ -34484,14 +34782,14 @@ function __asyncValues2(o) {
|
|
|
34484
34782
|
}, i);
|
|
34485
34783
|
function verb(n) {
|
|
34486
34784
|
i[n] = o[n] && function(v) {
|
|
34487
|
-
return new Promise(function(
|
|
34488
|
-
v = o[n](v), settle(
|
|
34785
|
+
return new Promise(function(resolve9, reject) {
|
|
34786
|
+
v = o[n](v), settle(resolve9, reject, v.done, v.value);
|
|
34489
34787
|
});
|
|
34490
34788
|
};
|
|
34491
34789
|
}
|
|
34492
|
-
function settle(
|
|
34790
|
+
function settle(resolve9, reject, d, v) {
|
|
34493
34791
|
Promise.resolve(v).then(function(v2) {
|
|
34494
|
-
|
|
34792
|
+
resolve9({ value: v2, done: d });
|
|
34495
34793
|
}, reject);
|
|
34496
34794
|
}
|
|
34497
34795
|
}
|
|
@@ -37155,24 +37453,24 @@ var require_x509_cjs = __commonJS({
|
|
|
37155
37453
|
names.register("I", "2.5.4.43");
|
|
37156
37454
|
names.register("SN", "2.5.4.4");
|
|
37157
37455
|
names.register("T", "2.5.4.12");
|
|
37158
|
-
function replaceUnknownCharacter(
|
|
37456
|
+
function replaceUnknownCharacter(text2, char) {
|
|
37159
37457
|
return `\\${pvtsutils.Convert.ToHex(pvtsutils.Convert.FromUtf8String(char)).toUpperCase()}`;
|
|
37160
37458
|
}
|
|
37161
37459
|
function escape2(data) {
|
|
37162
37460
|
return data.replace(/([,+"\\<>;])/g, "\\$1").replace(/^([ #])/, "\\$1").replace(/([ ]$)/, "\\$1").replace(/([\r\n\t])/, replaceUnknownCharacter);
|
|
37163
37461
|
}
|
|
37164
37462
|
var Name = class _Name {
|
|
37165
|
-
static isASCII(
|
|
37166
|
-
for (let i = 0; i <
|
|
37167
|
-
const code =
|
|
37463
|
+
static isASCII(text2) {
|
|
37464
|
+
for (let i = 0; i < text2.length; i++) {
|
|
37465
|
+
const code = text2.charCodeAt(i);
|
|
37168
37466
|
if (code > 255) {
|
|
37169
37467
|
return false;
|
|
37170
37468
|
}
|
|
37171
37469
|
}
|
|
37172
37470
|
return true;
|
|
37173
37471
|
}
|
|
37174
|
-
static isPrintableString(
|
|
37175
|
-
return /^[A-Za-z0-9 '()+,-./:=?]*$/g.test(
|
|
37472
|
+
static isPrintableString(text2) {
|
|
37473
|
+
return /^[A-Za-z0-9 '()+,-./:=?]*$/g.test(text2);
|
|
37176
37474
|
}
|
|
37177
37475
|
constructor(data, extraNames = {}) {
|
|
37178
37476
|
this.extraNames = new NameIdentifier();
|
|
@@ -40394,7 +40692,6 @@ var init_stun = __esm({
|
|
|
40394
40692
|
// ../../packages/host-core/dist/peer-link/quic-transport.js
|
|
40395
40693
|
var quic_transport_exports = {};
|
|
40396
40694
|
__export(quic_transport_exports, {
|
|
40397
|
-
QUIC_ENABLED: () => QUIC_ENABLED,
|
|
40398
40695
|
discoverSrflx: () => discoverSrflx,
|
|
40399
40696
|
makeQuicSocket: () => makeQuicSocket,
|
|
40400
40697
|
nudgePunch: () => nudgePunch,
|
|
@@ -40404,7 +40701,6 @@ __export(quic_transport_exports, {
|
|
|
40404
40701
|
import { webcrypto } from "node:crypto";
|
|
40405
40702
|
import { createHmac } from "node:crypto";
|
|
40406
40703
|
import { EventEmitter } from "node:events";
|
|
40407
|
-
import { QUICClient, QUICServer, QUICSocket, events as quicEvents } from "@matrixai/quic";
|
|
40408
40704
|
function serverCrypto() {
|
|
40409
40705
|
const key2 = webcrypto.getRandomValues(new Uint8Array(32));
|
|
40410
40706
|
return {
|
|
@@ -40487,12 +40783,14 @@ function pinningVerify(expectedFingerprint256) {
|
|
|
40487
40783
|
};
|
|
40488
40784
|
}
|
|
40489
40785
|
async function makeQuicSocket(localPort) {
|
|
40490
|
-
const
|
|
40786
|
+
const { QUICSocket: QUICSocketCtor } = await loadQuic();
|
|
40787
|
+
const socket2 = new QUICSocketCtor({});
|
|
40491
40788
|
await socket2.start({ host: "0.0.0.0", port: localPort, reuseAddr: true });
|
|
40492
40789
|
return socket2;
|
|
40493
40790
|
}
|
|
40494
40791
|
async function quicDialLink(opts) {
|
|
40495
|
-
const
|
|
40792
|
+
const { QUICClient: QUICClientCtor } = await loadQuic();
|
|
40793
|
+
const client = await QUICClientCtor.createQUICClient({
|
|
40496
40794
|
socket: opts.socket,
|
|
40497
40795
|
host: opts.host,
|
|
40498
40796
|
port: opts.port,
|
|
@@ -40505,7 +40803,8 @@ async function quicDialLink(opts) {
|
|
|
40505
40803
|
return link;
|
|
40506
40804
|
}
|
|
40507
40805
|
async function startQuicServerOnSocket(opts) {
|
|
40508
|
-
const
|
|
40806
|
+
const { QUICServer: QUICServerCtor, events: quicEvents } = await loadQuic();
|
|
40807
|
+
const server = new QUICServerCtor({
|
|
40509
40808
|
crypto: serverCrypto(),
|
|
40510
40809
|
config: { applicationProtos: ALPN, key: opts.identity.key, cert: opts.identity.cert, verifyPeer: false },
|
|
40511
40810
|
socket: opts.socket
|
|
@@ -40523,7 +40822,7 @@ async function startQuicServerOnSocket(opts) {
|
|
|
40523
40822
|
function discoverSrflx(socket2, stunHost, stunPort, timeoutMs = 3e3) {
|
|
40524
40823
|
const dgramSock = socket2.socket;
|
|
40525
40824
|
const { packet, txId } = encodeBindingRequest();
|
|
40526
|
-
return new Promise((
|
|
40825
|
+
return new Promise((resolve9, reject) => {
|
|
40527
40826
|
const timer = setTimeout(() => {
|
|
40528
40827
|
dgramSock.removeListener("message", onMsg);
|
|
40529
40828
|
reject(new Error("quic: STUN timeout"));
|
|
@@ -40533,7 +40832,7 @@ function discoverSrflx(socket2, stunHost, stunPort, timeoutMs = 3e3) {
|
|
|
40533
40832
|
if (mapped) {
|
|
40534
40833
|
clearTimeout(timer);
|
|
40535
40834
|
dgramSock.removeListener("message", onMsg);
|
|
40536
|
-
|
|
40835
|
+
resolve9(`${mapped.ip}:${mapped.port}`);
|
|
40537
40836
|
}
|
|
40538
40837
|
};
|
|
40539
40838
|
dgramSock.on("message", onMsg);
|
|
@@ -40554,14 +40853,15 @@ async function nudgePunch(socket2, peerIp, peerPort, count = 12, intervalMs = 10
|
|
|
40554
40853
|
await new Promise((r) => setTimeout(r, intervalMs));
|
|
40555
40854
|
}
|
|
40556
40855
|
}
|
|
40557
|
-
var
|
|
40856
|
+
var ALPN, quicModP, loadQuic, clientCrypto;
|
|
40558
40857
|
var init_quic_transport = __esm({
|
|
40559
40858
|
"../../packages/host-core/dist/peer-link/quic-transport.js"() {
|
|
40560
40859
|
"use strict";
|
|
40561
40860
|
init_transport();
|
|
40562
40861
|
init_stun();
|
|
40563
|
-
QUIC_ENABLED = process.env.CCB_P2P_QUIC === "1";
|
|
40564
40862
|
ALPN = ["tesseract-peer"];
|
|
40863
|
+
quicModP = null;
|
|
40864
|
+
loadQuic = () => quicModP ??= import("@matrixai/quic");
|
|
40565
40865
|
clientCrypto = {
|
|
40566
40866
|
ops: { randomBytes: async (data) => {
|
|
40567
40867
|
webcrypto.getRandomValues(new Uint8Array(data));
|
|
@@ -41641,17 +41941,17 @@ var require_main = __commonJS({
|
|
|
41641
41941
|
});
|
|
41642
41942
|
|
|
41643
41943
|
// src/cli.ts
|
|
41644
|
-
import { readFileSync as
|
|
41944
|
+
import { readFileSync as readFileSync13 } from "node:fs";
|
|
41645
41945
|
import { createHash as createHash5 } from "node:crypto";
|
|
41646
41946
|
import { spawn as spawn7 } from "node:child_process";
|
|
41647
41947
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
41648
41948
|
import { homedir as homedir14 } from "node:os";
|
|
41649
|
-
import { dirname as dirname16, join as
|
|
41949
|
+
import { dirname as dirname16, join as join33, resolve as resolve8 } from "node:path";
|
|
41650
41950
|
import { createInterface } from "node:readline/promises";
|
|
41651
41951
|
|
|
41652
41952
|
// ../../packages/host-core/dist/control-link.js
|
|
41653
41953
|
import { hostname as hostname3, homedir as homedir10 } from "node:os";
|
|
41654
|
-
import { join as
|
|
41954
|
+
import { join as join26, basename as basename5 } from "node:path";
|
|
41655
41955
|
import { mkdirSync as mkdirSync9 } from "node:fs";
|
|
41656
41956
|
|
|
41657
41957
|
// ../../node_modules/ws/wrapper.mjs
|
|
@@ -41699,7 +41999,7 @@ function isInsideRoot(p, root) {
|
|
|
41699
41999
|
}
|
|
41700
42000
|
|
|
41701
42001
|
// ../../packages/host-core/dist/daemon-agent.js
|
|
41702
|
-
import { join as
|
|
42002
|
+
import { join as join15 } from "node:path";
|
|
41703
42003
|
|
|
41704
42004
|
// ../../packages/host-core/dist/agent-backend.js
|
|
41705
42005
|
async function createClaudeCodeBackend(send2, onBrowserRequest, loadPluginRuntime2) {
|
|
@@ -41768,10 +42068,10 @@ var CliAgentBackend = class {
|
|
|
41768
42068
|
id;
|
|
41769
42069
|
capabilities;
|
|
41770
42070
|
live = /* @__PURE__ */ new Map();
|
|
41771
|
-
constructor(adapter, send2,
|
|
42071
|
+
constructor(adapter, send2, resolve9) {
|
|
41772
42072
|
this.adapter = adapter;
|
|
41773
42073
|
this.send = send2;
|
|
41774
|
-
this.resolve =
|
|
42074
|
+
this.resolve = resolve9;
|
|
41775
42075
|
this.id = adapter.id;
|
|
41776
42076
|
this.capabilities = adapter.capabilities;
|
|
41777
42077
|
}
|
|
@@ -42039,9 +42339,9 @@ var geminiAdapter = {
|
|
|
42039
42339
|
},
|
|
42040
42340
|
translate(event, raw, emit, ctx) {
|
|
42041
42341
|
const o = asObj3(event);
|
|
42042
|
-
const
|
|
42043
|
-
if (
|
|
42044
|
-
emit({ type: "chat:stream", sessionId: ctx.sessionId, clientRequestId: ctx.clientRequestId, delta:
|
|
42342
|
+
const text2 = o ? typeof o.response === "string" ? o.response : bestEffortText(o) : typeof event === "string" ? event : raw;
|
|
42343
|
+
if (text2)
|
|
42344
|
+
emit({ type: "chat:stream", sessionId: ctx.sessionId, clientRequestId: ctx.clientRequestId, delta: text2, messageId: ctx.messageId, kind: "text" });
|
|
42045
42345
|
const tools = o?.tools;
|
|
42046
42346
|
if (Array.isArray(tools)) {
|
|
42047
42347
|
for (const t of tools) {
|
|
@@ -42067,25 +42367,25 @@ var openclawAdapter = {
|
|
|
42067
42367
|
translate(event, raw, emit, ctx) {
|
|
42068
42368
|
const o = asObj4(event);
|
|
42069
42369
|
const result = asObj4(o?.result) ?? o;
|
|
42070
|
-
let
|
|
42370
|
+
let text2 = "";
|
|
42071
42371
|
const payloads = result?.payloads;
|
|
42072
42372
|
if (Array.isArray(payloads)) {
|
|
42073
|
-
|
|
42373
|
+
text2 = payloads.map((p) => {
|
|
42074
42374
|
const t = asObj4(p)?.text;
|
|
42075
42375
|
return typeof t === "string" ? t : "";
|
|
42076
42376
|
}).filter(Boolean).join("\n");
|
|
42077
42377
|
}
|
|
42078
|
-
if (!
|
|
42378
|
+
if (!text2) {
|
|
42079
42379
|
const fav = asObj4(result?.meta)?.finalAssistantVisibleText;
|
|
42080
42380
|
if (typeof fav === "string")
|
|
42081
|
-
|
|
42381
|
+
text2 = fav;
|
|
42082
42382
|
}
|
|
42083
|
-
if (!
|
|
42084
|
-
|
|
42085
|
-
if (
|
|
42086
|
-
emit({ type: "chat:stream", sessionId: ctx.sessionId, clientRequestId: ctx.clientRequestId, delta:
|
|
42383
|
+
if (!text2)
|
|
42384
|
+
text2 = o ? bestEffortText(result ?? o) : typeof event === "string" ? event : raw;
|
|
42385
|
+
if (text2)
|
|
42386
|
+
emit({ type: "chat:stream", sessionId: ctx.sessionId, clientRequestId: ctx.clientRequestId, delta: text2, messageId: ctx.messageId, kind: "text" });
|
|
42087
42387
|
const status2 = typeof o?.status === "string" ? o.status : void 0;
|
|
42088
|
-
if (!
|
|
42388
|
+
if (!text2 && status2 && status2 !== "ok" && status2 !== "accepted") {
|
|
42089
42389
|
const summary = typeof o?.summary === "string" && o.summary ? o.summary : `OpenClaw run ${status2}.`;
|
|
42090
42390
|
emit({ type: "chat:error", sessionId: ctx.sessionId, clientRequestId: ctx.clientRequestId, error: summary });
|
|
42091
42391
|
}
|
|
@@ -42133,7 +42433,7 @@ init_dist2();
|
|
|
42133
42433
|
|
|
42134
42434
|
// ../../packages/host-core/dist/plugin-tools.js
|
|
42135
42435
|
import { existsSync as existsSync3 } from "node:fs";
|
|
42136
|
-
import { join as
|
|
42436
|
+
import { join as join8 } from "node:path";
|
|
42137
42437
|
|
|
42138
42438
|
// ../../packages/plugin-host/dist/discovery.js
|
|
42139
42439
|
import fs2 from "node:fs";
|
|
@@ -42303,8 +42603,8 @@ function createOpenClawAdapter(pluginId, config2, secretResolver, registry2) {
|
|
|
42303
42603
|
pluginId,
|
|
42304
42604
|
config: config2,
|
|
42305
42605
|
secret: (envKey2) => secretResolver(pluginId, envKey2),
|
|
42306
|
-
registerTool: (
|
|
42307
|
-
const got = typeof
|
|
42606
|
+
registerTool: (tool3) => {
|
|
42607
|
+
const got = typeof tool3 === "function" ? tool3({}) : tool3;
|
|
42308
42608
|
const arr = Array.isArray(got) ? got : got ? [got] : [];
|
|
42309
42609
|
for (const t of arr) {
|
|
42310
42610
|
const c = convertTool(t);
|
|
@@ -42373,10 +42673,10 @@ var HostPluginApi = class {
|
|
|
42373
42673
|
secret(envKey2) {
|
|
42374
42674
|
return this.secretResolver(this.pluginId, envKey2);
|
|
42375
42675
|
}
|
|
42376
|
-
registerTool(
|
|
42676
|
+
registerTool(tool3) {
|
|
42377
42677
|
const prefix = this.pluginId.replace(/[^a-zA-Z0-9_]/g, "_");
|
|
42378
|
-
const name =
|
|
42379
|
-
this.registry.tools.push({ ...
|
|
42678
|
+
const name = tool3.name.startsWith(`${prefix}_`) ? tool3.name : `${prefix}_${tool3.name}`;
|
|
42679
|
+
this.registry.tools.push({ ...tool3, name });
|
|
42380
42680
|
}
|
|
42381
42681
|
registerHook(reg) {
|
|
42382
42682
|
this.registry.hooks.push(reg);
|
|
@@ -42481,7 +42781,7 @@ async function loadPluginRuntime(opts) {
|
|
|
42481
42781
|
}
|
|
42482
42782
|
function buildDaemonPluginLoader(pluginsDir) {
|
|
42483
42783
|
return async () => {
|
|
42484
|
-
const scan =
|
|
42784
|
+
const scan = join8(pluginsDir, "node_modules");
|
|
42485
42785
|
if (!existsSync3(scan))
|
|
42486
42786
|
return { tools: [], hooks: [], engines: [] };
|
|
42487
42787
|
writeOpenClawShim(pluginsDir);
|
|
@@ -42493,18 +42793,18 @@ function buildDaemonPluginLoader(pluginsDir) {
|
|
|
42493
42793
|
}
|
|
42494
42794
|
|
|
42495
42795
|
// ../../packages/host-core/dist/credentials.js
|
|
42496
|
-
import { readFileSync as
|
|
42497
|
-
import { join as
|
|
42796
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, existsSync as existsSync4, renameSync as renameSync3, chmodSync } from "node:fs";
|
|
42797
|
+
import { join as join9 } from "node:path";
|
|
42498
42798
|
import { homedir as homedir3 } from "node:os";
|
|
42499
42799
|
function daemonDir() {
|
|
42500
|
-
return process.env.CCB_DAEMON_DIR ??
|
|
42800
|
+
return process.env.CCB_DAEMON_DIR ?? join9(homedir3(), ".tesseract", "daemon");
|
|
42501
42801
|
}
|
|
42502
42802
|
function credentialsPath() {
|
|
42503
|
-
return
|
|
42803
|
+
return join9(daemonDir(), "credentials.json");
|
|
42504
42804
|
}
|
|
42505
42805
|
function readCredentials() {
|
|
42506
42806
|
try {
|
|
42507
|
-
const c = JSON.parse(
|
|
42807
|
+
const c = JSON.parse(readFileSync4(credentialsPath(), "utf-8"));
|
|
42508
42808
|
if (c.accessToken && c.refreshSecret && c.dtid && c.deviceId && c.userId && c.backendOrigin && c.apiOrigin) {
|
|
42509
42809
|
return c;
|
|
42510
42810
|
}
|
|
@@ -42808,13 +43108,13 @@ async function closeEnginePage(browserId) {
|
|
|
42808
43108
|
}
|
|
42809
43109
|
|
|
42810
43110
|
// ../../packages/host-core/dist/daemon-settings.js
|
|
42811
|
-
import { readFileSync as
|
|
42812
|
-
import { join as
|
|
43111
|
+
import { readFileSync as readFileSync7 } from "node:fs";
|
|
43112
|
+
import { join as join14 } from "node:path";
|
|
42813
43113
|
|
|
42814
43114
|
// ../../packages/host-core/dist/runners/resolve.js
|
|
42815
|
-
import { readFileSync as
|
|
43115
|
+
import { readFileSync as readFileSync5, existsSync as existsSync6, statSync, mkdirSync as mkdirSync4, writeFileSync as writeFileSync5 } from "node:fs";
|
|
42816
43116
|
import { homedir as homedir5 } from "node:os";
|
|
42817
|
-
import { join as
|
|
43117
|
+
import { join as join11 } from "node:path";
|
|
42818
43118
|
import { createHash as createHash2 } from "node:crypto";
|
|
42819
43119
|
|
|
42820
43120
|
// ../../packages/shared/dist/ws-protocol.js
|
|
@@ -42837,6 +43137,8 @@ var MIRRORED_AGENT_EVENTS = /* @__PURE__ */ new Set([
|
|
|
42837
43137
|
// plan review — co-viewers see the sectioned plan
|
|
42838
43138
|
"agent:narration",
|
|
42839
43139
|
// live status strip — co-viewers see "what it's doing now"
|
|
43140
|
+
"agent:preview_ready",
|
|
43141
|
+
// co-viewers (incl. mobile) see the preview the moment it's ready
|
|
42840
43142
|
"agent:elicitation_complete",
|
|
42841
43143
|
// M5 — co-viewers clear a resolved url-mode card
|
|
42842
43144
|
"chat:echoed",
|
|
@@ -43286,22 +43588,22 @@ import { createRequire as createRequire2 } from "node:module";
|
|
|
43286
43588
|
import { randomUUID as randomUUID4, createHash } from "node:crypto";
|
|
43287
43589
|
import { existsSync as existsSync5, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "node:fs";
|
|
43288
43590
|
import { homedir as homedir4 } from "node:os";
|
|
43289
|
-
import { join as
|
|
43591
|
+
import { join as join10, dirname as dirname5, sep as sep2 } from "node:path";
|
|
43290
43592
|
import { request as httpRequest } from "node:http";
|
|
43291
43593
|
var requireFromHere = createRequire2(import.meta.url);
|
|
43292
43594
|
var ROUTER_PORT = 8787;
|
|
43293
43595
|
var BIND_HOST = "127.0.0.1";
|
|
43294
43596
|
var ROUTER_TOKEN = randomUUID4();
|
|
43295
|
-
var routerHomeDir =
|
|
43597
|
+
var routerHomeDir = join10(homedir4(), ".tesseract", "router-home");
|
|
43296
43598
|
var lastConfigHash = "";
|
|
43297
43599
|
var running = false;
|
|
43298
43600
|
var starting = null;
|
|
43299
43601
|
function configPath() {
|
|
43300
|
-
return
|
|
43602
|
+
return join10(routerHomeDir, ".claude-code-router", "config.json");
|
|
43301
43603
|
}
|
|
43302
43604
|
function ccrCliPath() {
|
|
43303
43605
|
const pkg = requireFromHere.resolve("@musistudio/claude-code-router/package.json");
|
|
43304
|
-
const cli =
|
|
43606
|
+
const cli = join10(dirname5(pkg), "dist", "cli.js");
|
|
43305
43607
|
return cli.replace(`app.asar${sep2}`, `app.asar.unpacked${sep2}`);
|
|
43306
43608
|
}
|
|
43307
43609
|
var cachedNodeExe2;
|
|
@@ -43391,39 +43693,39 @@ function buildRouterConfig(d) {
|
|
|
43391
43693
|
};
|
|
43392
43694
|
}
|
|
43393
43695
|
function writeConfig(cfg2) {
|
|
43394
|
-
const dir =
|
|
43696
|
+
const dir = join10(routerHomeDir, ".claude-code-router");
|
|
43395
43697
|
if (!existsSync5(dir))
|
|
43396
43698
|
mkdirSync3(dir, { recursive: true });
|
|
43397
43699
|
writeFileSync4(configPath(), JSON.stringify(cfg2, null, 2), { mode: 384 });
|
|
43398
43700
|
}
|
|
43399
43701
|
function ccr(args, timeout = 8e3) {
|
|
43400
43702
|
const { exe, asNode } = nodeExe();
|
|
43401
|
-
return new Promise((
|
|
43703
|
+
return new Promise((resolve9) => {
|
|
43402
43704
|
execFile2(exe, [ccrCliPath(), ...args], { env: ccrEnv(asNode), timeout }, (err, stdout, stderr) => {
|
|
43403
|
-
|
|
43705
|
+
resolve9({ ok: !err, out: `${stdout || ""}${stderr || ""}` });
|
|
43404
43706
|
});
|
|
43405
43707
|
});
|
|
43406
43708
|
}
|
|
43407
43709
|
function waitHealthy(timeoutMs = 8e3) {
|
|
43408
43710
|
const deadline = Date.now() + timeoutMs;
|
|
43409
|
-
const ping = () => new Promise((
|
|
43711
|
+
const ping = () => new Promise((resolve9) => {
|
|
43410
43712
|
const req = httpRequest({ host: BIND_HOST, port: ROUTER_PORT, path: "/", method: "GET", timeout: 1e3 }, (res) => {
|
|
43411
43713
|
res.resume();
|
|
43412
|
-
|
|
43714
|
+
resolve9(true);
|
|
43413
43715
|
});
|
|
43414
|
-
req.on("error", () =>
|
|
43716
|
+
req.on("error", () => resolve9(false));
|
|
43415
43717
|
req.on("timeout", () => {
|
|
43416
43718
|
req.destroy();
|
|
43417
|
-
|
|
43719
|
+
resolve9(false);
|
|
43418
43720
|
});
|
|
43419
43721
|
req.end();
|
|
43420
43722
|
});
|
|
43421
|
-
return new Promise((
|
|
43723
|
+
return new Promise((resolve9) => {
|
|
43422
43724
|
const tick = async () => {
|
|
43423
43725
|
if (await ping())
|
|
43424
|
-
return
|
|
43726
|
+
return resolve9(true);
|
|
43425
43727
|
if (Date.now() > deadline)
|
|
43426
|
-
return
|
|
43728
|
+
return resolve9(false);
|
|
43427
43729
|
setTimeout(() => void tick(), 400);
|
|
43428
43730
|
};
|
|
43429
43731
|
void tick();
|
|
@@ -43463,13 +43765,13 @@ function routerEndpointSync(desired) {
|
|
|
43463
43765
|
}
|
|
43464
43766
|
|
|
43465
43767
|
// ../../packages/host-core/dist/runners/resolve.js
|
|
43466
|
-
var runnerHomeBase =
|
|
43768
|
+
var runnerHomeBase = join11(homedir5(), ".tesseract", "runner-home");
|
|
43467
43769
|
function materializeClaudeAuthHome(contents) {
|
|
43468
43770
|
const id = createHash2("sha256").update(contents).digest("hex").slice(0, 16);
|
|
43469
|
-
const home =
|
|
43771
|
+
const home = join11(runnerHomeBase, id);
|
|
43470
43772
|
try {
|
|
43471
43773
|
mkdirSync4(home, { recursive: true });
|
|
43472
|
-
writeFileSync5(
|
|
43774
|
+
writeFileSync5(join11(home, ".credentials.json"), contents, { mode: 384 });
|
|
43473
43775
|
} catch {
|
|
43474
43776
|
}
|
|
43475
43777
|
return home;
|
|
@@ -43519,7 +43821,7 @@ function resolveRunnerEnv(spec) {
|
|
|
43519
43821
|
return { ANTHROPIC_BASE_URL: endpoint.baseUrl, ANTHROPIC_AUTH_TOKEN: endpoint.authToken, ANTHROPIC_API_KEY: "" };
|
|
43520
43822
|
}
|
|
43521
43823
|
function overridePath() {
|
|
43522
|
-
return
|
|
43824
|
+
return join11(process.env.CCB_TESSERACT_DIR ?? join11(homedir5(), ".tesseract"), "runners.json");
|
|
43523
43825
|
}
|
|
43524
43826
|
var cache2 = null;
|
|
43525
43827
|
var cachedMtime = -1;
|
|
@@ -43533,7 +43835,7 @@ function readOverride() {
|
|
|
43533
43835
|
}
|
|
43534
43836
|
const m = statSync(p).mtimeMs;
|
|
43535
43837
|
if (cachedMtime !== m) {
|
|
43536
|
-
cache2 = JSON.parse(
|
|
43838
|
+
cache2 = JSON.parse(readFileSync5(p, "utf-8"));
|
|
43537
43839
|
cachedMtime = m;
|
|
43538
43840
|
}
|
|
43539
43841
|
} catch {
|
|
@@ -43560,11 +43862,11 @@ function resolveOverrideEngineEnv() {
|
|
|
43560
43862
|
}
|
|
43561
43863
|
|
|
43562
43864
|
// ../../packages/host-core/dist/runners/pool.js
|
|
43563
|
-
import { readFileSync as
|
|
43564
|
-
import { join as
|
|
43865
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync6, existsSync as existsSync7, statSync as statSync2, mkdirSync as mkdirSync5, chmodSync as chmodSync2, renameSync as renameSync4 } from "node:fs";
|
|
43866
|
+
import { join as join12 } from "node:path";
|
|
43565
43867
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
43566
43868
|
function poolPath() {
|
|
43567
|
-
return
|
|
43869
|
+
return join12(daemonDir(), "runner-configs.json");
|
|
43568
43870
|
}
|
|
43569
43871
|
var cache3 = null;
|
|
43570
43872
|
var cachedMtime2 = -1;
|
|
@@ -43581,7 +43883,7 @@ function load() {
|
|
|
43581
43883
|
}
|
|
43582
43884
|
const m = statSync2(p).mtimeMs;
|
|
43583
43885
|
if (cachedMtime2 !== m || !cache3) {
|
|
43584
|
-
const parsed = JSON.parse(
|
|
43886
|
+
const parsed = JSON.parse(readFileSync6(p, "utf-8"));
|
|
43585
43887
|
cache3 = parsed && parsed.version === 1 && Array.isArray(parsed.configs) ? parsed : emptyStore();
|
|
43586
43888
|
cachedMtime2 = m;
|
|
43587
43889
|
}
|
|
@@ -43747,7 +44049,7 @@ function setActiveConfig(id) {
|
|
|
43747
44049
|
// ../../packages/host-core/dist/daemon-engine-spawn.js
|
|
43748
44050
|
import { execFileSync } from "node:child_process";
|
|
43749
44051
|
import { homedir as homedir6 } from "node:os";
|
|
43750
|
-
import { join as
|
|
44052
|
+
import { join as join13 } from "node:path";
|
|
43751
44053
|
function envKey(id) {
|
|
43752
44054
|
return id.toUpperCase().replace(/[^A-Z0-9]/g, "_");
|
|
43753
44055
|
}
|
|
@@ -43758,10 +44060,10 @@ function augmentedPath() {
|
|
|
43758
44060
|
"/opt/homebrew/bin",
|
|
43759
44061
|
"/usr/bin",
|
|
43760
44062
|
"/bin",
|
|
43761
|
-
|
|
43762
|
-
|
|
43763
|
-
|
|
43764
|
-
|
|
44063
|
+
join13(homedir6(), ".local", "bin"),
|
|
44064
|
+
join13(homedir6(), "bin"),
|
|
44065
|
+
join13(homedir6(), ".bun", "bin"),
|
|
44066
|
+
join13(homedir6(), ".npm-global", "bin")
|
|
43765
44067
|
];
|
|
43766
44068
|
const seen = /* @__PURE__ */ new Set();
|
|
43767
44069
|
const parts = [];
|
|
@@ -43774,9 +44076,9 @@ function augmentedPath() {
|
|
|
43774
44076
|
return parts.join(sep7);
|
|
43775
44077
|
}
|
|
43776
44078
|
function which(bin, path5) {
|
|
43777
|
-
const
|
|
44079
|
+
const tool3 = process.platform === "win32" ? "where" : "which";
|
|
43778
44080
|
try {
|
|
43779
|
-
const out = execFileSync(
|
|
44081
|
+
const out = execFileSync(tool3, [bin], { env: { ...process.env, PATH: path5 }, timeout: 4e3, encoding: "utf-8" });
|
|
43780
44082
|
return out.split(/\r?\n/).map((l) => l.trim()).find(Boolean) || void 0;
|
|
43781
44083
|
} catch {
|
|
43782
44084
|
return void 0;
|
|
@@ -43818,14 +44120,14 @@ function readDaemonEngineSpawn(engineId) {
|
|
|
43818
44120
|
return readDaemonAgentSettings().engineSpawn?.[engineId] ?? resolveDaemonEngineSpawn(engineId);
|
|
43819
44121
|
}
|
|
43820
44122
|
function agentSettingsPath() {
|
|
43821
|
-
return
|
|
44123
|
+
return join14(daemonDir(), "agent-settings.json");
|
|
43822
44124
|
}
|
|
43823
44125
|
function readDaemonSchedulingEnabled() {
|
|
43824
44126
|
return readDaemonAgentSettings().schedulingEnabled === true;
|
|
43825
44127
|
}
|
|
43826
44128
|
function readDaemonAgentSettings() {
|
|
43827
44129
|
try {
|
|
43828
|
-
return JSON.parse(
|
|
44130
|
+
return JSON.parse(readFileSync7(agentSettingsPath(), "utf-8"));
|
|
43829
44131
|
} catch {
|
|
43830
44132
|
const snap = {};
|
|
43831
44133
|
const raw = process.env.CCB_MCP_SERVERS;
|
|
@@ -43932,7 +44234,7 @@ function buildSharedBackend(engineId) {
|
|
|
43932
44234
|
},
|
|
43933
44235
|
resolver,
|
|
43934
44236
|
// Daemon plugins (review #3): operator-controlled <daemonDir>/plugins, env-var secrets.
|
|
43935
|
-
buildDaemonPluginLoader(
|
|
44237
|
+
buildDaemonPluginLoader(join15(daemonDir(), "plugins"))
|
|
43936
44238
|
).then((b) => {
|
|
43937
44239
|
if (token !== buildToken)
|
|
43938
44240
|
return b;
|
|
@@ -43983,16 +44285,16 @@ function refreshDaemonScheduling(b) {
|
|
|
43983
44285
|
}
|
|
43984
44286
|
b.configureScheduling({
|
|
43985
44287
|
enabled,
|
|
43986
|
-
file:
|
|
44288
|
+
file: join15(dir, "scheduled_tasks.json"),
|
|
43987
44289
|
// projectDir omitted ⇒ fires track the daemon's currently-open project (setConfig).
|
|
43988
44290
|
isOwner: schedulingLock ? () => schedulingLock.isOwner() : void 0
|
|
43989
44291
|
});
|
|
43990
44292
|
}
|
|
43991
44293
|
|
|
43992
44294
|
// ../../packages/host-core/dist/fs-remote.js
|
|
43993
|
-
import { readdir as readdir2, readFile as
|
|
44295
|
+
import { readdir as readdir2, readFile as readFile6, writeFile as writeFile4, mkdir as mkdir4, cp, rm, rename as renameAsync, stat as stat2 } from "node:fs/promises";
|
|
43994
44296
|
import { openSync as openSync2, readSync, closeSync as closeSync2, statSync as statSync3, existsSync as existsSync8, watch } from "node:fs";
|
|
43995
|
-
import { basename as basename2, dirname as dirname6, join as
|
|
44297
|
+
import { basename as basename2, dirname as dirname6, join as join16, relative as relative3, resolve as resolve4, sep as sep3, isAbsolute as isAbsolute3 } from "node:path";
|
|
43996
44298
|
import { execFile as execFile3 } from "node:child_process";
|
|
43997
44299
|
import { promisify as promisify2 } from "node:util";
|
|
43998
44300
|
var execFileAsync = promisify2(execFile3);
|
|
@@ -44039,12 +44341,12 @@ async function listAllFilesUnder(dir) {
|
|
|
44039
44341
|
return;
|
|
44040
44342
|
if (ent.name === ".DS_Store")
|
|
44041
44343
|
continue;
|
|
44042
|
-
const full =
|
|
44344
|
+
const full = join16(d, ent.name);
|
|
44043
44345
|
if (ent.isDirectory()) {
|
|
44044
44346
|
if (!LISTALL_SKIP_DIRS.has(ent.name))
|
|
44045
44347
|
await walk(full);
|
|
44046
44348
|
} else if (ent.isFile())
|
|
44047
|
-
out.push(
|
|
44349
|
+
out.push(relative3(dir, full).split(sep3).join("/"));
|
|
44048
44350
|
}
|
|
44049
44351
|
};
|
|
44050
44352
|
await walk(dir);
|
|
@@ -44155,18 +44457,18 @@ function resolveParent(raw, root) {
|
|
|
44155
44457
|
if (raw === "" || raw === "~")
|
|
44156
44458
|
return root;
|
|
44157
44459
|
if (raw.startsWith("~/"))
|
|
44158
|
-
return
|
|
44159
|
-
return
|
|
44460
|
+
return join16(root, raw.slice(2));
|
|
44461
|
+
return isAbsolute3(raw) ? raw : join16(root, raw);
|
|
44160
44462
|
}
|
|
44161
44463
|
function resolveUniqueName(dir, name) {
|
|
44162
|
-
const direct =
|
|
44464
|
+
const direct = join16(dir, name);
|
|
44163
44465
|
if (!existsSync8(direct))
|
|
44164
44466
|
return direct;
|
|
44165
44467
|
const dot = name.lastIndexOf(".");
|
|
44166
44468
|
const base = dot > 0 ? name.slice(0, dot) : name;
|
|
44167
44469
|
const ext = dot > 0 ? name.slice(dot) : "";
|
|
44168
44470
|
for (let i = 2; i < 1e4; i++) {
|
|
44169
|
-
const candidate =
|
|
44471
|
+
const candidate = join16(dir, `${base} ${i}${ext}`);
|
|
44170
44472
|
if (!existsSync8(candidate))
|
|
44171
44473
|
return candidate;
|
|
44172
44474
|
}
|
|
@@ -44183,7 +44485,7 @@ async function readRemoteBytes(root, path5) {
|
|
|
44183
44485
|
return { error: "Not a file" };
|
|
44184
44486
|
if (s.size > REMOTE_READ_CAP)
|
|
44185
44487
|
return { error: `File is too large to read whole over the network (${(s.size / 1024 / 1024).toFixed(1)} MB) \u2014 open it locally.` };
|
|
44186
|
-
return { bytes: await
|
|
44488
|
+
return { bytes: await readFile6(path5), size: s.size };
|
|
44187
44489
|
} catch (err) {
|
|
44188
44490
|
return { error: String(err.message) };
|
|
44189
44491
|
}
|
|
@@ -44198,7 +44500,7 @@ async function runRemoteFsOp(root, op, args) {
|
|
|
44198
44500
|
try {
|
|
44199
44501
|
const entries = (await readdir2(dir, { withFileTypes: true })).filter((e) => e.name !== ".DS_Store");
|
|
44200
44502
|
const ignored = await gitIgnoredNames(dir, entries.map((e) => e.name));
|
|
44201
|
-
return entries.map((e) => ({ name: e.name, path:
|
|
44503
|
+
return entries.map((e) => ({ name: e.name, path: join16(dir, e.name), isDir: e.isDirectory(), ignored: ignored.has(e.name) })).sort((x, y) => x.isDir === y.isDir ? x.name.localeCompare(y.name) : x.isDir ? -1 : 1);
|
|
44202
44504
|
} catch {
|
|
44203
44505
|
return [];
|
|
44204
44506
|
}
|
|
@@ -44224,7 +44526,7 @@ async function runRemoteFsOp(root, op, args) {
|
|
|
44224
44526
|
const s = statSync3(p);
|
|
44225
44527
|
if (s.size > TEXT_SIZE_LIMIT)
|
|
44226
44528
|
return { error: "File too large for text view." };
|
|
44227
|
-
return { content: await
|
|
44529
|
+
return { content: await readFile6(p, "utf-8") };
|
|
44228
44530
|
} catch (err) {
|
|
44229
44531
|
return { error: String(err.message) };
|
|
44230
44532
|
}
|
|
@@ -44235,8 +44537,8 @@ async function runRemoteFsOp(root, op, args) {
|
|
|
44235
44537
|
if (!isInsideRoot(p, root))
|
|
44236
44538
|
return OUTSIDE("write");
|
|
44237
44539
|
try {
|
|
44238
|
-
await
|
|
44239
|
-
await
|
|
44540
|
+
await mkdir4(dirname6(p), { recursive: true });
|
|
44541
|
+
await writeFile4(p, content, "utf-8");
|
|
44240
44542
|
return { ok: true };
|
|
44241
44543
|
} catch (err) {
|
|
44242
44544
|
return { ok: false, error: String(err.message) };
|
|
@@ -44248,8 +44550,8 @@ async function runRemoteFsOp(root, op, args) {
|
|
|
44248
44550
|
if (!isInsideRoot(p, root))
|
|
44249
44551
|
return OUTSIDE("write");
|
|
44250
44552
|
try {
|
|
44251
|
-
await
|
|
44252
|
-
await
|
|
44553
|
+
await mkdir4(dirname6(p), { recursive: true });
|
|
44554
|
+
await writeFile4(p, Buffer.from(base643, "base64"));
|
|
44253
44555
|
return { ok: true };
|
|
44254
44556
|
} catch (err) {
|
|
44255
44557
|
return { ok: false, error: String(err.message) };
|
|
@@ -44301,7 +44603,7 @@ async function runRemoteFsOp(root, op, args) {
|
|
|
44301
44603
|
const s = statSync3(p);
|
|
44302
44604
|
if (s.size > REMOTE_READ_CAP)
|
|
44303
44605
|
return { error: `File is too large to read whole over the network (${(s.size / 1024 / 1024).toFixed(1)} MB) \u2014 open it locally.` };
|
|
44304
|
-
return { base64: (await
|
|
44606
|
+
return { base64: (await readFile6(p)).toString("base64"), size: s.size };
|
|
44305
44607
|
} catch (err) {
|
|
44306
44608
|
return { error: String(err.message) };
|
|
44307
44609
|
}
|
|
@@ -44311,13 +44613,13 @@ async function runRemoteFsOp(root, op, args) {
|
|
|
44311
44613
|
const name = String(a[1] ?? "").trim();
|
|
44312
44614
|
if (!validName(name))
|
|
44313
44615
|
return { ok: false, error: "Invalid project name." };
|
|
44314
|
-
const target =
|
|
44616
|
+
const target = join16(parent, name);
|
|
44315
44617
|
if (!isInsideRoot(target, root))
|
|
44316
44618
|
return { ok: false, error: "Refusing to create a project outside the shared root." };
|
|
44317
44619
|
if (existsSync8(target))
|
|
44318
44620
|
return { ok: false, error: `A folder named "${name}" already exists.` };
|
|
44319
44621
|
try {
|
|
44320
|
-
await
|
|
44622
|
+
await mkdir4(target, { recursive: true });
|
|
44321
44623
|
return { ok: true, path: target };
|
|
44322
44624
|
} catch (err) {
|
|
44323
44625
|
return { ok: false, error: String(err.message) };
|
|
@@ -44331,14 +44633,14 @@ async function runRemoteFsOp(root, op, args) {
|
|
|
44331
44633
|
return { ok: false, error: "Invalid name." };
|
|
44332
44634
|
if (!isInsideRoot(parent, root))
|
|
44333
44635
|
return OUTSIDE("create");
|
|
44334
|
-
const target =
|
|
44636
|
+
const target = join16(parent, name);
|
|
44335
44637
|
if (existsSync8(target))
|
|
44336
44638
|
return { ok: false, error: `"${name}" already exists.` };
|
|
44337
44639
|
try {
|
|
44338
44640
|
if (op === "createFile")
|
|
44339
|
-
await
|
|
44641
|
+
await writeFile4(target, "", "utf-8");
|
|
44340
44642
|
else
|
|
44341
|
-
await
|
|
44643
|
+
await mkdir4(target);
|
|
44342
44644
|
return { ok: true, path: target };
|
|
44343
44645
|
} catch (err) {
|
|
44344
44646
|
return { ok: false, error: String(err.message) };
|
|
@@ -44351,7 +44653,7 @@ async function runRemoteFsOp(root, op, args) {
|
|
|
44351
44653
|
return { ok: false, error: "Invalid name." };
|
|
44352
44654
|
if (!isInsideRoot(oldPath, root))
|
|
44353
44655
|
return OUTSIDE("rename");
|
|
44354
|
-
const newPath =
|
|
44656
|
+
const newPath = join16(dirname6(oldPath), newName);
|
|
44355
44657
|
if (existsSync8(newPath))
|
|
44356
44658
|
return { ok: false, error: `A file named "${newName}" already exists.` };
|
|
44357
44659
|
try {
|
|
@@ -44367,7 +44669,7 @@ async function runRemoteFsOp(root, op, args) {
|
|
|
44367
44669
|
return { ok: false, error: "Bad request" };
|
|
44368
44670
|
if (!isInsideRoot(p, root))
|
|
44369
44671
|
return OUTSIDE("delete");
|
|
44370
|
-
if (
|
|
44672
|
+
if (resolve4(p) === resolve4(root))
|
|
44371
44673
|
return { ok: false, error: "Refusing to delete the shared root." };
|
|
44372
44674
|
try {
|
|
44373
44675
|
await rm(p, { recursive: true, force: false });
|
|
@@ -44413,7 +44715,7 @@ async function runRemoteFsOp(root, op, args) {
|
|
|
44413
44715
|
const s = await stat2(p);
|
|
44414
44716
|
if (!s.isDirectory())
|
|
44415
44717
|
return { error: "not_dir" };
|
|
44416
|
-
return { root:
|
|
44718
|
+
return { root: resolve4(p), name: basename2(p) };
|
|
44417
44719
|
} catch {
|
|
44418
44720
|
return { error: "not_found" };
|
|
44419
44721
|
}
|
|
@@ -44421,14 +44723,14 @@ async function runRemoteFsOp(root, op, args) {
|
|
|
44421
44723
|
case "currentRoot":
|
|
44422
44724
|
return { root, name: basename2(root) };
|
|
44423
44725
|
case "homeDir":
|
|
44424
|
-
return { root:
|
|
44726
|
+
return { root: resolve4(root), name: basename2(root) };
|
|
44425
44727
|
default:
|
|
44426
44728
|
return { error: `Unsupported fs op: ${op}` };
|
|
44427
44729
|
}
|
|
44428
44730
|
}
|
|
44429
44731
|
var remoteWatches = /* @__PURE__ */ new Map();
|
|
44430
44732
|
function watchRemoteRoot(root, key2, onChange) {
|
|
44431
|
-
const resolved =
|
|
44733
|
+
const resolved = resolve4(root);
|
|
44432
44734
|
const existing = remoteWatches.get(resolved);
|
|
44433
44735
|
if (existing) {
|
|
44434
44736
|
existing.listeners.set(key2, onChange);
|
|
@@ -44443,7 +44745,7 @@ function watchRemoteRoot(root, key2, onChange) {
|
|
|
44443
44745
|
const rel = String(filename);
|
|
44444
44746
|
if (rel.split(sep3).some((seg) => IGNORED.has(seg)))
|
|
44445
44747
|
return;
|
|
44446
|
-
pending.add(
|
|
44748
|
+
pending.add(join16(resolved, rel));
|
|
44447
44749
|
if (timer)
|
|
44448
44750
|
clearTimeout(timer);
|
|
44449
44751
|
timer = setTimeout(() => {
|
|
@@ -44688,15 +44990,15 @@ function dynamicMetrics() {
|
|
|
44688
44990
|
}
|
|
44689
44991
|
|
|
44690
44992
|
// ../../packages/host-core/dist/fs-transfer.js
|
|
44691
|
-
import { readdir as readdir3, lstat, mkdir as
|
|
44993
|
+
import { readdir as readdir3, lstat, mkdir as mkdir5, chmod, rm as rm2, readlink, symlink, stat as stat3 } from "node:fs/promises";
|
|
44692
44994
|
import { openSync as openSync3, readSync as readSync2, closeSync as closeSync3, existsSync as existsSync9, createWriteStream } from "node:fs";
|
|
44693
|
-
import { dirname as dirname7, join as
|
|
44995
|
+
import { dirname as dirname7, join as join18, relative as relative5, sep as sep5 } from "node:path";
|
|
44694
44996
|
|
|
44695
44997
|
// ../../packages/host-core/dist/active-link/paths.js
|
|
44696
44998
|
import { homedir as homedir7 } from "node:os";
|
|
44697
|
-
import { join as
|
|
44999
|
+
import { join as join17, relative as relative4, sep as sep4 } from "node:path";
|
|
44698
45000
|
function activeLinkEnabled() {
|
|
44699
|
-
return process.env.CCB_ACTIVE_LINK
|
|
45001
|
+
return process.env.CCB_ACTIVE_LINK !== "0";
|
|
44700
45002
|
}
|
|
44701
45003
|
var HEAVY_DIRS = /* @__PURE__ */ new Set([
|
|
44702
45004
|
".git",
|
|
@@ -44717,10 +45019,10 @@ function isExcludedName(name) {
|
|
|
44717
45019
|
return HEAVY_DIRS.has(name) || ALWAYS_SKIP.has(name);
|
|
44718
45020
|
}
|
|
44719
45021
|
function toPosixRel(root, abs) {
|
|
44720
|
-
return
|
|
45022
|
+
return relative4(root, abs).split(sep4).join("/");
|
|
44721
45023
|
}
|
|
44722
45024
|
function fromPosixRel(root, rel) {
|
|
44723
|
-
return
|
|
45025
|
+
return join17(root, rel.split("/").join(sep4));
|
|
44724
45026
|
}
|
|
44725
45027
|
function isExcludedAbs(abs, root) {
|
|
44726
45028
|
const rel = toPosixRel(root, abs);
|
|
@@ -44729,10 +45031,10 @@ function isExcludedAbs(abs, root) {
|
|
|
44729
45031
|
return rel.split("/").some(isExcludedName);
|
|
44730
45032
|
}
|
|
44731
45033
|
function activeLinkRoot() {
|
|
44732
|
-
return process.env.CCB_ACTIVE_LINK_DIR ??
|
|
45034
|
+
return process.env.CCB_ACTIVE_LINK_DIR ?? join17(homedir7(), ".tesseract", "active-link");
|
|
44733
45035
|
}
|
|
44734
45036
|
function linkStateDir(linkId) {
|
|
44735
|
-
return
|
|
45037
|
+
return join17(activeLinkRoot(), linkId);
|
|
44736
45038
|
}
|
|
44737
45039
|
|
|
44738
45040
|
// ../../packages/host-core/dist/fs-transfer.js
|
|
@@ -44745,9 +45047,9 @@ function clearTimer(t) {
|
|
|
44745
45047
|
return null;
|
|
44746
45048
|
}
|
|
44747
45049
|
function uniqueDir(parent, name) {
|
|
44748
|
-
let candidate =
|
|
45050
|
+
let candidate = join18(parent, name);
|
|
44749
45051
|
for (let i = 2; existsSync9(candidate) && i < 1e4; i++)
|
|
44750
|
-
candidate =
|
|
45052
|
+
candidate = join18(parent, `${name} ${i}`);
|
|
44751
45053
|
return candidate;
|
|
44752
45054
|
}
|
|
44753
45055
|
var producers = /* @__PURE__ */ new Map();
|
|
@@ -44790,8 +45092,8 @@ async function buildManifest(root, followSymlinks, excludeHeavy) {
|
|
|
44790
45092
|
continue;
|
|
44791
45093
|
if (e.isDirectory() && excludeHeavy && HEAVY_DIRS.has(e.name))
|
|
44792
45094
|
continue;
|
|
44793
|
-
const abs =
|
|
44794
|
-
const rel =
|
|
45095
|
+
const abs = join18(dir, e.name);
|
|
45096
|
+
const rel = relative5(root, abs).split(sep5).join("/");
|
|
44795
45097
|
const st = await lstat(abs).catch(() => null);
|
|
44796
45098
|
if (!st)
|
|
44797
45099
|
continue;
|
|
@@ -44851,17 +45153,17 @@ async function startOutboundTransfer(msg, controllerClientId, ownHostId2, hostRo
|
|
|
44851
45153
|
totalBytes: manifest.totalBytes,
|
|
44852
45154
|
dirs: manifest.dirs
|
|
44853
45155
|
}, { hostId: toHost });
|
|
44854
|
-
const waitWindow = () => state.sentBytes - state.ackedBytes < MAX_INFLIGHT ? Promise.resolve() : new Promise((
|
|
44855
|
-
state.wake =
|
|
45156
|
+
const waitWindow = () => state.sentBytes - state.ackedBytes < MAX_INFLIGHT ? Promise.resolve() : new Promise((resolve9) => {
|
|
45157
|
+
state.wake = resolve9;
|
|
44856
45158
|
});
|
|
44857
45159
|
for (let fileIx = 0; fileIx < manifest.files.length && !state.cancelled; fileIx++) {
|
|
44858
45160
|
const f = manifest.files[fileIx];
|
|
44859
45161
|
if (f.kind === "symlink") {
|
|
44860
|
-
const target = await readlink(
|
|
45162
|
+
const target = await readlink(join18(srcPath, f.rel.split("/").join(sep5))).catch(() => "");
|
|
44861
45163
|
send2({ type: "fs:transferChunk", transferId, toHost, fileIx, rel: f.rel, mode: f.mode, kind: "symlink", offset: 0, base64: Buffer.from(target, "utf-8").toString("base64"), eof: true }, { hostId: toHost });
|
|
44862
45164
|
continue;
|
|
44863
45165
|
}
|
|
44864
|
-
const abs =
|
|
45166
|
+
const abs = join18(srcPath, f.rel.split("/").join(sep5));
|
|
44865
45167
|
let fd = null;
|
|
44866
45168
|
try {
|
|
44867
45169
|
fd = openSync3(abs, "r");
|
|
@@ -44973,7 +45275,7 @@ async function beginInboundTransfer(msg, hostRoot, send2) {
|
|
|
44973
45275
|
failNoState("Invalid destination name.");
|
|
44974
45276
|
return;
|
|
44975
45277
|
}
|
|
44976
|
-
let destRoot =
|
|
45278
|
+
let destRoot = join18(parent, msg.destName);
|
|
44977
45279
|
let createdRoot = false;
|
|
44978
45280
|
if (existsSync9(destRoot)) {
|
|
44979
45281
|
if (msg.onCollision === "abort") {
|
|
@@ -45013,11 +45315,11 @@ async function beginInboundTransfer(msg, hostRoot, send2) {
|
|
|
45013
45315
|
return;
|
|
45014
45316
|
}
|
|
45015
45317
|
try {
|
|
45016
|
-
await
|
|
45318
|
+
await mkdir5(destRoot, { recursive: true });
|
|
45017
45319
|
for (const d of msg.dirs) {
|
|
45018
|
-
const abs =
|
|
45320
|
+
const abs = join18(destRoot, d.rel.split("/").join(sep5));
|
|
45019
45321
|
if (isInsideRoot(abs, destRoot))
|
|
45020
|
-
await
|
|
45322
|
+
await mkdir5(abs, { recursive: true }).catch(() => {
|
|
45021
45323
|
});
|
|
45022
45324
|
}
|
|
45023
45325
|
} catch (e) {
|
|
@@ -45029,7 +45331,7 @@ async function writeInboundChunk(msg, send2) {
|
|
|
45029
45331
|
if (!s || s.cancelled)
|
|
45030
45332
|
return;
|
|
45031
45333
|
armConsumerWatchdog(msg.transferId, send2);
|
|
45032
|
-
const abs =
|
|
45334
|
+
const abs = join18(s.destRoot, msg.rel.split("/").join(sep5));
|
|
45033
45335
|
if (msg.rel.includes("..") || !isInsideRoot(abs, s.destRoot)) {
|
|
45034
45336
|
failConsumer(msg.transferId, `Refusing a path outside the destination: ${msg.rel}`, send2);
|
|
45035
45337
|
return;
|
|
@@ -45037,9 +45339,9 @@ async function writeInboundChunk(msg, send2) {
|
|
|
45037
45339
|
try {
|
|
45038
45340
|
if (msg.kind === "symlink") {
|
|
45039
45341
|
const target = Buffer.from(msg.base64, "base64").toString("utf-8");
|
|
45040
|
-
const resolved =
|
|
45342
|
+
const resolved = join18(dirname7(abs), target);
|
|
45041
45343
|
if (isInsideRoot(resolved, s.destRoot)) {
|
|
45042
|
-
await
|
|
45344
|
+
await mkdir5(dirname7(abs), { recursive: true }).catch(() => {
|
|
45043
45345
|
});
|
|
45044
45346
|
await symlink(target, abs).catch(() => {
|
|
45045
45347
|
});
|
|
@@ -45052,14 +45354,14 @@ async function writeInboundChunk(msg, send2) {
|
|
|
45052
45354
|
if (s.curIx !== msg.fileIx || !s.curStream) {
|
|
45053
45355
|
if (s.curStream)
|
|
45054
45356
|
await new Promise((r) => s.curStream.end(r));
|
|
45055
|
-
await
|
|
45357
|
+
await mkdir5(dirname7(abs), { recursive: true }).catch(() => {
|
|
45056
45358
|
});
|
|
45057
45359
|
s.curStream = createWriteStream(abs);
|
|
45058
45360
|
s.curIx = msg.fileIx;
|
|
45059
45361
|
}
|
|
45060
45362
|
if (msg.base64) {
|
|
45061
45363
|
const buf = Buffer.from(msg.base64, "base64");
|
|
45062
|
-
await new Promise((
|
|
45364
|
+
await new Promise((resolve9, reject) => s.curStream.write(buf, (err) => err ? reject(err) : resolve9()));
|
|
45063
45365
|
s.bytesDone += buf.length;
|
|
45064
45366
|
}
|
|
45065
45367
|
if (msg.eof) {
|
|
@@ -45113,7 +45415,7 @@ function cancelTransfersForClient(clientId, send2) {
|
|
|
45113
45415
|
|
|
45114
45416
|
// ../../packages/host-core/dist/peer-link/index.js
|
|
45115
45417
|
import { homedir as homedir8 } from "node:os";
|
|
45116
|
-
import { join as
|
|
45418
|
+
import { join as join19 } from "node:path";
|
|
45117
45419
|
|
|
45118
45420
|
// ../../packages/host-core/dist/peer-link/manager.js
|
|
45119
45421
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
@@ -45122,15 +45424,15 @@ import { randomBytes as randomBytes2 } from "node:crypto";
|
|
|
45122
45424
|
var import_selfsigned = __toESM(require_selfsigned(), 1);
|
|
45123
45425
|
import tls from "node:tls";
|
|
45124
45426
|
import { X509Certificate } from "node:crypto";
|
|
45125
|
-
import { readFileSync as
|
|
45427
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync7, existsSync as existsSync10, mkdirSync as mkdirSync6 } from "node:fs";
|
|
45126
45428
|
import { dirname as dirname8 } from "node:path";
|
|
45127
45429
|
function fingerprintOf(certPem) {
|
|
45128
45430
|
return new X509Certificate(certPem).fingerprint256;
|
|
45129
45431
|
}
|
|
45130
45432
|
async function loadOrCreateIdentity(certPath, keyPath) {
|
|
45131
45433
|
if (existsSync10(certPath) && existsSync10(keyPath)) {
|
|
45132
|
-
const cert =
|
|
45133
|
-
const key2 =
|
|
45434
|
+
const cert = readFileSync8(certPath, "utf8");
|
|
45435
|
+
const key2 = readFileSync8(keyPath, "utf8");
|
|
45134
45436
|
return { cert, key: key2, fingerprint256: fingerprintOf(cert) };
|
|
45135
45437
|
}
|
|
45136
45438
|
const tenYears = new Date(Date.now() + 10 * 365 * 24 * 60 * 60 * 1e3);
|
|
@@ -45147,7 +45449,7 @@ async function loadOrCreateIdentity(certPath, keyPath) {
|
|
|
45147
45449
|
return { cert: pems.cert, key: pems.private, fingerprint256: fingerprintOf(pems.cert) };
|
|
45148
45450
|
}
|
|
45149
45451
|
function pinnedConnect(opts) {
|
|
45150
|
-
return new Promise((
|
|
45452
|
+
return new Promise((resolve9, reject) => {
|
|
45151
45453
|
let settled = false;
|
|
45152
45454
|
const done = (err, sock) => {
|
|
45153
45455
|
if (settled)
|
|
@@ -45160,7 +45462,7 @@ function pinnedConnect(opts) {
|
|
|
45160
45462
|
}
|
|
45161
45463
|
reject(err);
|
|
45162
45464
|
} else
|
|
45163
|
-
|
|
45465
|
+
resolve9(sock);
|
|
45164
45466
|
};
|
|
45165
45467
|
const socket2 = tls.connect({
|
|
45166
45468
|
host: opts.host,
|
|
@@ -45276,6 +45578,11 @@ var PeerLinkManager = class {
|
|
|
45276
45578
|
quicSrflx = null;
|
|
45277
45579
|
quicInitP = null;
|
|
45278
45580
|
quicKeepalive = null;
|
|
45581
|
+
/** Set once if the QUIC native dep (@matrixai/quic) can't be loaded on this host —
|
|
45582
|
+
* e.g. the desktop app doesn't ship it, or an arch with no prebuilt binding. The
|
|
45583
|
+
* QUIC tier then no-ops permanently and the TCP tiers carry every link (fail-closed,
|
|
45584
|
+
* exactly what the lazy-load design in quic-transport.ts promises). */
|
|
45585
|
+
quicUnavailable = false;
|
|
45279
45586
|
constructor(certPath, keyPath) {
|
|
45280
45587
|
this.certPath = certPath;
|
|
45281
45588
|
this.keyPath = keyPath;
|
|
@@ -45322,22 +45629,28 @@ var PeerLinkManager = class {
|
|
|
45322
45629
|
return;
|
|
45323
45630
|
const stunPort = Number(process.env.CCB_STUN_PORT ?? 3478);
|
|
45324
45631
|
const identity = await this.identity();
|
|
45325
|
-
|
|
45326
|
-
|
|
45327
|
-
|
|
45328
|
-
|
|
45329
|
-
|
|
45330
|
-
|
|
45331
|
-
|
|
45332
|
-
|
|
45333
|
-
|
|
45334
|
-
|
|
45335
|
-
|
|
45336
|
-
|
|
45337
|
-
|
|
45338
|
-
|
|
45339
|
-
|
|
45340
|
-
|
|
45632
|
+
try {
|
|
45633
|
+
const q = await Promise.resolve().then(() => (init_quic_transport(), quic_transport_exports));
|
|
45634
|
+
const socket2 = await q.makeQuicSocket(this.udpPort);
|
|
45635
|
+
this.quicSocket = socket2;
|
|
45636
|
+
await q.startQuicServerOnSocket({ socket: socket2, identity, onStream: (bs) => this.acceptInbound(bs, "punch") });
|
|
45637
|
+
const refresh = async () => {
|
|
45638
|
+
try {
|
|
45639
|
+
const s = await q.discoverSrflx(socket2, stunHost, stunPort);
|
|
45640
|
+
const i = s.lastIndexOf(":");
|
|
45641
|
+
this.quicSrflx = { type: "srflx", ip: s.slice(0, i), port: Number(s.slice(i + 1)), proto: "udp", priority: 40 };
|
|
45642
|
+
} catch {
|
|
45643
|
+
}
|
|
45644
|
+
};
|
|
45645
|
+
await refresh();
|
|
45646
|
+
this.quicKeepalive = setInterval(() => {
|
|
45647
|
+
void refresh();
|
|
45648
|
+
}, 2e4);
|
|
45649
|
+
} catch (e) {
|
|
45650
|
+
this.quicUnavailable = true;
|
|
45651
|
+
this.quicSocket = null;
|
|
45652
|
+
console.warn(`[peer-link] QUIC tier unavailable \u2014 using TCP tiers only: ${e?.message ?? e}`);
|
|
45653
|
+
}
|
|
45341
45654
|
}
|
|
45342
45655
|
async nudgeQuic(peer) {
|
|
45343
45656
|
if (!this.quicSocket)
|
|
@@ -45367,7 +45680,7 @@ var PeerLinkManager = class {
|
|
|
45367
45680
|
if (this.server)
|
|
45368
45681
|
return this.listenPort;
|
|
45369
45682
|
this.server = createListener(identity, LISTEN_PORT, (sock) => this.acceptInbound(sock, "reverse"));
|
|
45370
|
-
await new Promise((
|
|
45683
|
+
await new Promise((resolve9) => this.server.once("listening", () => resolve9()));
|
|
45371
45684
|
const addr = this.server.address();
|
|
45372
45685
|
if (addr && typeof addr === "object")
|
|
45373
45686
|
this.listenPort = addr.port;
|
|
@@ -45434,12 +45747,12 @@ var PeerLinkManager = class {
|
|
|
45434
45747
|
* peer to dial in. Resolves with the authed link, or rejects on timeout. */
|
|
45435
45748
|
awaitInbound(token, peerHostId) {
|
|
45436
45749
|
const h = toHex(token);
|
|
45437
|
-
return new Promise((
|
|
45750
|
+
return new Promise((resolve9, reject) => {
|
|
45438
45751
|
const timer = setTimeout(() => {
|
|
45439
45752
|
this.pendingInbound.delete(h);
|
|
45440
45753
|
reject(new Error("peer-link: inbound dial-in timeout"));
|
|
45441
45754
|
}, INBOUND_WAIT_MS);
|
|
45442
|
-
this.pendingInbound.set(h, { peerHostId, resolve:
|
|
45755
|
+
this.pendingInbound.set(h, { peerHostId, resolve: resolve9, reject, timer });
|
|
45443
45756
|
});
|
|
45444
45757
|
}
|
|
45445
45758
|
/** Obey one `p2p:go` (initiator OR unsolicited responder): dial the peer's
|
|
@@ -45453,7 +45766,7 @@ var PeerLinkManager = class {
|
|
|
45453
45766
|
async handleGo(msg) {
|
|
45454
45767
|
const token = Buffer.from(msg.token, "hex");
|
|
45455
45768
|
const udp = msg.peerCandidates.filter((c) => c.proto === "udp");
|
|
45456
|
-
const quicOn = this.quicEnabled() && udp.length > 0;
|
|
45769
|
+
const quicOn = this.quicEnabled() && udp.length > 0 && !this.quicUnavailable;
|
|
45457
45770
|
if (msg.role === "listen") {
|
|
45458
45771
|
if (quicOn) {
|
|
45459
45772
|
await this.initQuic();
|
|
@@ -45466,7 +45779,7 @@ var PeerLinkManager = class {
|
|
|
45466
45779
|
];
|
|
45467
45780
|
if (quicOn)
|
|
45468
45781
|
attempts.push(this.quicDial(msg, token, udp[0]));
|
|
45469
|
-
return new Promise((
|
|
45782
|
+
return new Promise((resolve9, reject) => {
|
|
45470
45783
|
let done = false, failed = 0;
|
|
45471
45784
|
const errs = [];
|
|
45472
45785
|
for (const p of attempts) {
|
|
@@ -45480,7 +45793,7 @@ var PeerLinkManager = class {
|
|
|
45480
45793
|
}
|
|
45481
45794
|
done = true;
|
|
45482
45795
|
this.cache(msg.peerHostId, l);
|
|
45483
|
-
|
|
45796
|
+
resolve9(l);
|
|
45484
45797
|
}, (e) => {
|
|
45485
45798
|
errs.push(e);
|
|
45486
45799
|
if (++failed === attempts.length && !done)
|
|
@@ -45531,7 +45844,7 @@ var PeerLinkManager = class {
|
|
|
45531
45844
|
const myFingerprint = (await this.identity()).fingerprint256;
|
|
45532
45845
|
const rid = randomBytes2(8).toString("hex");
|
|
45533
45846
|
const myCandidates = gatherTcpCandidates(this.listenPort, this.observedIp);
|
|
45534
|
-
return new Promise((
|
|
45847
|
+
return new Promise((resolve9, reject) => {
|
|
45535
45848
|
let settled = false;
|
|
45536
45849
|
const overall = setTimeout(() => finish(new Error("peer-link: rendezvous timeout")), RENDEZVOUS_TIMEOUT_MS);
|
|
45537
45850
|
const finish = (err, link) => {
|
|
@@ -45543,7 +45856,7 @@ var PeerLinkManager = class {
|
|
|
45543
45856
|
if (err || !link)
|
|
45544
45857
|
reject(err ?? new Error("peer-link: no link"));
|
|
45545
45858
|
else
|
|
45546
|
-
|
|
45859
|
+
resolve9(link);
|
|
45547
45860
|
};
|
|
45548
45861
|
this.pendingOpens.set(rid, {
|
|
45549
45862
|
// Our attempt failed: tell the broker (it forwards `failed` to the peer +
|
|
@@ -45613,8 +45926,8 @@ var PeerLinkManager = class {
|
|
|
45613
45926
|
// ../../packages/host-core/dist/peer-link/index.js
|
|
45614
45927
|
var P2P_ENABLED = process.env.CCB_P2P !== "0";
|
|
45615
45928
|
function identityPaths() {
|
|
45616
|
-
const dir = process.env.CCB_P2P_DIR ??
|
|
45617
|
-
return { certPath:
|
|
45929
|
+
const dir = process.env.CCB_P2P_DIR ?? join19(homedir8(), ".tesseract");
|
|
45930
|
+
return { certPath: join19(dir, "peer-cert.pem"), keyPath: join19(dir, "peer-key.pem") };
|
|
45618
45931
|
}
|
|
45619
45932
|
var manager = null;
|
|
45620
45933
|
function peerLinkManager() {
|
|
@@ -45629,14 +45942,14 @@ async function openPeerLink(peerHostId, ctx) {
|
|
|
45629
45942
|
}
|
|
45630
45943
|
|
|
45631
45944
|
// ../../packages/host-core/dist/active-link/engine.js
|
|
45632
|
-
import { lstat as lstat6, readlink as readlink4, rm as rm3, mkdir as
|
|
45945
|
+
import { lstat as lstat6, readlink as readlink4, rm as rm3, mkdir as mkdir7, symlink as symlink2, rename as rename2, utimes as utimes2, writeFile as writeFile5 } from "node:fs/promises";
|
|
45633
45946
|
import { existsSync as existsSync12 } from "node:fs";
|
|
45634
|
-
import { dirname as dirname12, join as
|
|
45947
|
+
import { dirname as dirname12, join as join24, resolve as resolve7 } from "node:path";
|
|
45635
45948
|
|
|
45636
45949
|
// ../../packages/host-core/dist/active-link/blocks.js
|
|
45637
45950
|
import { createHash as createHash3 } from "node:crypto";
|
|
45638
45951
|
import { createReadStream } from "node:fs";
|
|
45639
|
-
import { open, mkdir as
|
|
45952
|
+
import { open, mkdir as mkdir6, rename, chmod as chmod2, utimes, unlink } from "node:fs/promises";
|
|
45640
45953
|
import { dirname as dirname9 } from "node:path";
|
|
45641
45954
|
var CHUNK3 = 1024 * 1024;
|
|
45642
45955
|
var MAX_INFLIGHT2 = 8 * CHUNK3;
|
|
@@ -45648,16 +45961,16 @@ function hashString(s) {
|
|
|
45648
45961
|
return createHash3("sha256").update(s, "utf-8").digest("hex");
|
|
45649
45962
|
}
|
|
45650
45963
|
function hashFile(abs) {
|
|
45651
|
-
return new Promise((
|
|
45964
|
+
return new Promise((resolve9, reject) => {
|
|
45652
45965
|
const h = createHash3("sha256");
|
|
45653
45966
|
const rs = createReadStream(abs);
|
|
45654
45967
|
rs.on("data", (d) => h.update(d));
|
|
45655
|
-
rs.on("end", () =>
|
|
45968
|
+
rs.on("end", () => resolve9(h.digest("hex")));
|
|
45656
45969
|
rs.on("error", reject);
|
|
45657
45970
|
});
|
|
45658
45971
|
}
|
|
45659
45972
|
function hashFileBlocks(abs) {
|
|
45660
|
-
return new Promise((
|
|
45973
|
+
return new Promise((resolve9, reject) => {
|
|
45661
45974
|
const whole = createHash3("sha256");
|
|
45662
45975
|
const blocks = [];
|
|
45663
45976
|
let cur = createHash3("sha256");
|
|
@@ -45684,7 +45997,7 @@ function hashFileBlocks(abs) {
|
|
|
45684
45997
|
rs.on("end", () => {
|
|
45685
45998
|
if (curLen > 0)
|
|
45686
45999
|
blocks.push(cur.digest("hex"));
|
|
45687
|
-
|
|
46000
|
+
resolve9({ wholeHash: whole.digest("hex"), blocks, size });
|
|
45688
46001
|
});
|
|
45689
46002
|
rs.on("error", reject);
|
|
45690
46003
|
});
|
|
@@ -45715,8 +46028,8 @@ var SendWindow = class {
|
|
|
45715
46028
|
wait() {
|
|
45716
46029
|
if (this.cancelled || this.sent - this.acked < this.maxInflight)
|
|
45717
46030
|
return Promise.resolve();
|
|
45718
|
-
return new Promise((
|
|
45719
|
-
this.wake =
|
|
46031
|
+
return new Promise((resolve9) => {
|
|
46032
|
+
this.wake = resolve9;
|
|
45720
46033
|
});
|
|
45721
46034
|
}
|
|
45722
46035
|
cancel() {
|
|
@@ -45765,7 +46078,7 @@ var StagingWriter = class {
|
|
|
45765
46078
|
}
|
|
45766
46079
|
async ensureOpen() {
|
|
45767
46080
|
if (!this.fh) {
|
|
45768
|
-
await
|
|
46081
|
+
await mkdir6(dirname9(this.stagingPath), { recursive: true });
|
|
45769
46082
|
this.fh = await open(this.stagingPath, "w");
|
|
45770
46083
|
}
|
|
45771
46084
|
return this.fh;
|
|
@@ -45795,7 +46108,7 @@ var StagingWriter = class {
|
|
|
45795
46108
|
});
|
|
45796
46109
|
await fh.close();
|
|
45797
46110
|
this.fh = null;
|
|
45798
|
-
await
|
|
46111
|
+
await mkdir6(dirname9(dest), { recursive: true });
|
|
45799
46112
|
await chmod2(this.stagingPath, mode & 511).catch(() => {
|
|
45800
46113
|
});
|
|
45801
46114
|
const secs = mtimeMs / 1e3;
|
|
@@ -45828,7 +46141,7 @@ var BlockAssembler = class {
|
|
|
45828
46141
|
this.stagingPath = stagingPath;
|
|
45829
46142
|
}
|
|
45830
46143
|
async open() {
|
|
45831
|
-
await
|
|
46144
|
+
await mkdir6(dirname9(this.stagingPath), { recursive: true });
|
|
45832
46145
|
this.fh = await open(this.stagingPath, "w");
|
|
45833
46146
|
}
|
|
45834
46147
|
/** Write a received block at its byte offset (index * CHUNK). */
|
|
@@ -45872,7 +46185,7 @@ var BlockAssembler = class {
|
|
|
45872
46185
|
});
|
|
45873
46186
|
return false;
|
|
45874
46187
|
}
|
|
45875
|
-
await
|
|
46188
|
+
await mkdir6(dirname9(dest), { recursive: true });
|
|
45876
46189
|
await chmod2(this.stagingPath, mode & 511).catch(() => {
|
|
45877
46190
|
});
|
|
45878
46191
|
const secs = mtimeMs / 1e3;
|
|
@@ -45895,8 +46208,8 @@ var BlockAssembler = class {
|
|
|
45895
46208
|
};
|
|
45896
46209
|
|
|
45897
46210
|
// ../../packages/host-core/dist/active-link/manifest.js
|
|
45898
|
-
import { readFileSync as
|
|
45899
|
-
import { join as
|
|
46211
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync8, mkdirSync as mkdirSync7, existsSync as existsSync11, renameSync as renameSync5 } from "node:fs";
|
|
46212
|
+
import { join as join20 } from "node:path";
|
|
45900
46213
|
|
|
45901
46214
|
// ../../packages/host-core/dist/active-link/reconcile.js
|
|
45902
46215
|
var ABSENT = { kind: "absent", t: -Infinity, hash: "" };
|
|
@@ -45932,11 +46245,11 @@ var LinkManifest = class {
|
|
|
45932
46245
|
this.dir = dir;
|
|
45933
46246
|
}
|
|
45934
46247
|
file() {
|
|
45935
|
-
return
|
|
46248
|
+
return join20(this.dir, "manifest.json");
|
|
45936
46249
|
}
|
|
45937
46250
|
load() {
|
|
45938
46251
|
try {
|
|
45939
|
-
const raw = JSON.parse(
|
|
46252
|
+
const raw = JSON.parse(readFileSync9(this.file(), "utf-8"));
|
|
45940
46253
|
this.records = new Map(Object.entries(raw.records ?? {}));
|
|
45941
46254
|
this.tombstones = new Map(Object.entries(raw.tombstones ?? {}));
|
|
45942
46255
|
} catch {
|
|
@@ -46034,7 +46347,7 @@ var LinkManifest = class {
|
|
|
46034
46347
|
|
|
46035
46348
|
// ../../packages/host-core/dist/active-link/scanner.js
|
|
46036
46349
|
import { readdir as readdir4, lstat as lstat2, readlink as readlink2 } from "node:fs/promises";
|
|
46037
|
-
import { join as
|
|
46350
|
+
import { join as join21, sep as sep6 } from "node:path";
|
|
46038
46351
|
async function walkRels(root, extraIgnore) {
|
|
46039
46352
|
const out = [];
|
|
46040
46353
|
async function rec(dir) {
|
|
@@ -46049,7 +46362,7 @@ async function walkRels(root, extraIgnore) {
|
|
|
46049
46362
|
continue;
|
|
46050
46363
|
if (e.isDirectory() && HEAVY_DIRS.has(e.name))
|
|
46051
46364
|
continue;
|
|
46052
|
-
const abs =
|
|
46365
|
+
const abs = join21(dir, e.name);
|
|
46053
46366
|
if (extraIgnore?.(abs))
|
|
46054
46367
|
continue;
|
|
46055
46368
|
if (e.isDirectory())
|
|
@@ -46088,7 +46401,7 @@ async function scanTree(root, prior, allow, extraIgnore) {
|
|
|
46088
46401
|
return { records };
|
|
46089
46402
|
}
|
|
46090
46403
|
function absOf(root, rel) {
|
|
46091
|
-
return
|
|
46404
|
+
return join21(root, rel.split("/").join(sep6));
|
|
46092
46405
|
}
|
|
46093
46406
|
|
|
46094
46407
|
// ../../packages/host-core/dist/active-link/gitignore.js
|
|
@@ -47151,7 +47464,7 @@ var NodeFsHandler = class {
|
|
|
47151
47464
|
this._addToNodeFs(path5, initialAdd, wh, depth + 1);
|
|
47152
47465
|
}
|
|
47153
47466
|
}).on(EV.ERROR, this._boundHandleError);
|
|
47154
|
-
return new Promise((
|
|
47467
|
+
return new Promise((resolve9, reject) => {
|
|
47155
47468
|
if (!stream)
|
|
47156
47469
|
return reject();
|
|
47157
47470
|
stream.once(STR_END, () => {
|
|
@@ -47160,7 +47473,7 @@ var NodeFsHandler = class {
|
|
|
47160
47473
|
return;
|
|
47161
47474
|
}
|
|
47162
47475
|
const wasThrottled = throttler ? throttler.clear() : false;
|
|
47163
|
-
|
|
47476
|
+
resolve9(void 0);
|
|
47164
47477
|
previous.getChildren().filter((item) => {
|
|
47165
47478
|
return item !== directory && !current.has(item);
|
|
47166
47479
|
}).forEach((item) => {
|
|
@@ -47304,11 +47617,11 @@ function createPattern(matcher) {
|
|
|
47304
47617
|
if (matcher.path === string4)
|
|
47305
47618
|
return true;
|
|
47306
47619
|
if (matcher.recursive) {
|
|
47307
|
-
const
|
|
47308
|
-
if (!
|
|
47620
|
+
const relative8 = sysPath2.relative(matcher.path, string4);
|
|
47621
|
+
if (!relative8) {
|
|
47309
47622
|
return false;
|
|
47310
47623
|
}
|
|
47311
|
-
return !
|
|
47624
|
+
return !relative8.startsWith("..") && !sysPath2.isAbsolute(relative8);
|
|
47312
47625
|
}
|
|
47313
47626
|
return false;
|
|
47314
47627
|
};
|
|
@@ -48016,8 +48329,8 @@ var LinkWatcher = class {
|
|
|
48016
48329
|
this.fsw.on("unlinkDir", onEvent);
|
|
48017
48330
|
this.fsw.on("error", () => {
|
|
48018
48331
|
});
|
|
48019
|
-
await new Promise((
|
|
48020
|
-
this.fsw.once("ready", () =>
|
|
48332
|
+
await new Promise((resolve9) => {
|
|
48333
|
+
this.fsw.once("ready", () => resolve9());
|
|
48021
48334
|
});
|
|
48022
48335
|
}
|
|
48023
48336
|
enqueue(abs) {
|
|
@@ -48105,7 +48418,7 @@ var ActiveLinkEngine = class {
|
|
|
48105
48418
|
}
|
|
48106
48419
|
async start() {
|
|
48107
48420
|
this.emit({ type: "status", linkId: this.opts.linkId, state: "scanning" });
|
|
48108
|
-
await rm3(
|
|
48421
|
+
await rm3(join24(this.stateDir, ".staging"), { recursive: true, force: true }).catch(() => {
|
|
48109
48422
|
});
|
|
48110
48423
|
this.manifest.load();
|
|
48111
48424
|
await this.reconcileScan();
|
|
@@ -48498,20 +48811,20 @@ var ActiveLinkEngine = class {
|
|
|
48498
48811
|
* file so the path still exists — recorded as a FILE matching disk so the local
|
|
48499
48812
|
* watcher doesn't churn. The target is containment-checked, never dereferenced. */
|
|
48500
48813
|
async applySymlink(rel, dest, target, mtimeMs, mode) {
|
|
48501
|
-
const resolved =
|
|
48814
|
+
const resolved = resolve7(dirname12(dest), target);
|
|
48502
48815
|
if (!isInsideRoot(resolved, this.opts.localRoot))
|
|
48503
48816
|
return;
|
|
48504
48817
|
const hash2 = hashString(target);
|
|
48505
48818
|
const secs = mtimeMs / 1e3;
|
|
48506
48819
|
try {
|
|
48507
|
-
await
|
|
48820
|
+
await mkdir7(dirname12(dest), { recursive: true });
|
|
48508
48821
|
await rm3(dest, { force: true, recursive: true });
|
|
48509
48822
|
try {
|
|
48510
48823
|
await symlink2(target, dest);
|
|
48511
48824
|
this.manifest.setRecord(rel, { kind: "symlink", mtimeMs, size: 0, mode, hash: hash2, blocks: [] });
|
|
48512
48825
|
} catch {
|
|
48513
48826
|
const buf = Buffer.from(target, "utf-8");
|
|
48514
|
-
await
|
|
48827
|
+
await writeFile5(dest, buf);
|
|
48515
48828
|
await utimes2(dest, secs, secs).catch(() => {
|
|
48516
48829
|
});
|
|
48517
48830
|
this.manifest.setRecord(rel, { kind: "file", mtimeMs, size: buf.length, mode, hash: hash2, blocks: [hash2] });
|
|
@@ -48554,7 +48867,7 @@ var ActiveLinkEngine = class {
|
|
|
48554
48867
|
return;
|
|
48555
48868
|
if (fromRec && fromRec.kind === "file") {
|
|
48556
48869
|
try {
|
|
48557
|
-
await
|
|
48870
|
+
await mkdir7(dirname12(toAbs), { recursive: true });
|
|
48558
48871
|
await rename2(fromAbs, toAbs);
|
|
48559
48872
|
const secs = mtimeMs / 1e3;
|
|
48560
48873
|
await utimes2(toAbs, secs, secs).catch(() => {
|
|
@@ -48729,7 +49042,7 @@ var ActiveLinkEngine = class {
|
|
|
48729
49042
|
this.inboundWatchdog.clear();
|
|
48730
49043
|
}
|
|
48731
49044
|
stagingPath(rel, tag) {
|
|
48732
|
-
return
|
|
49045
|
+
return join24(this.stateDir, ".staging", `${hashString(rel)}.${tag}`);
|
|
48733
49046
|
}
|
|
48734
49047
|
pruneSuppress() {
|
|
48735
49048
|
const now = this.now();
|
|
@@ -48754,14 +49067,14 @@ var ActiveLinkEngine = class {
|
|
|
48754
49067
|
};
|
|
48755
49068
|
|
|
48756
49069
|
// ../../packages/host-core/dist/active-link/config.js
|
|
48757
|
-
import { readFileSync as
|
|
48758
|
-
import { join as
|
|
49070
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync9, mkdirSync as mkdirSync8, existsSync as existsSync13, renameSync as renameSync6, watch as watch3 } from "node:fs";
|
|
49071
|
+
import { join as join25 } from "node:path";
|
|
48759
49072
|
function configPath2() {
|
|
48760
|
-
return
|
|
49073
|
+
return join25(activeLinkRoot(), "links.json");
|
|
48761
49074
|
}
|
|
48762
49075
|
function loadLinkConfigs() {
|
|
48763
49076
|
try {
|
|
48764
|
-
const raw = JSON.parse(
|
|
49077
|
+
const raw = JSON.parse(readFileSync10(configPath2(), "utf-8"));
|
|
48765
49078
|
if (!Array.isArray(raw.links))
|
|
48766
49079
|
return [];
|
|
48767
49080
|
return raw.links.filter((c) => c && c.linkId && c.localRoot && c.peerHostId);
|
|
@@ -48782,9 +49095,42 @@ function writeAll(links) {
|
|
|
48782
49095
|
}
|
|
48783
49096
|
function saveLinkConfig(cfg2) {
|
|
48784
49097
|
const links = loadLinkConfigs().filter((c) => c.linkId !== cfg2.linkId);
|
|
48785
|
-
links.push({
|
|
49098
|
+
links.push({
|
|
49099
|
+
linkId: cfg2.linkId,
|
|
49100
|
+
localRoot: cfg2.localRoot,
|
|
49101
|
+
peerHostId: cfg2.peerHostId,
|
|
49102
|
+
...cfg2.initiated ? { initiated: true } : {},
|
|
49103
|
+
...cfg2.workspaceLinkId ? { workspaceLinkId: cfg2.workspaceLinkId } : {},
|
|
49104
|
+
...cfg2.remoteParent ? { remoteParent: cfg2.remoteParent } : {},
|
|
49105
|
+
...cfg2.remoteSubfolder ? { remoteSubfolder: cfg2.remoteSubfolder } : {}
|
|
49106
|
+
});
|
|
48786
49107
|
writeAll(links);
|
|
48787
49108
|
}
|
|
49109
|
+
function pendingPath() {
|
|
49110
|
+
return join25(activeLinkRoot(), "pending-deprovisions.json");
|
|
49111
|
+
}
|
|
49112
|
+
function loadPendingDeprovisions() {
|
|
49113
|
+
try {
|
|
49114
|
+
const raw = JSON.parse(readFileSync10(pendingPath(), "utf-8"));
|
|
49115
|
+
return Array.isArray(raw.pending) ? raw.pending.filter((p) => p && p.linkId && p.peerHostId) : [];
|
|
49116
|
+
} catch {
|
|
49117
|
+
return [];
|
|
49118
|
+
}
|
|
49119
|
+
}
|
|
49120
|
+
function writePending(pending) {
|
|
49121
|
+
try {
|
|
49122
|
+
const dir = activeLinkRoot();
|
|
49123
|
+
if (!existsSync13(dir))
|
|
49124
|
+
mkdirSync8(dir, { recursive: true });
|
|
49125
|
+
const tmp = `${pendingPath()}.tmp`;
|
|
49126
|
+
writeFileSync9(tmp, JSON.stringify({ pending }, null, 2));
|
|
49127
|
+
renameSync6(tmp, pendingPath());
|
|
49128
|
+
} catch {
|
|
49129
|
+
}
|
|
49130
|
+
}
|
|
49131
|
+
function removePendingDeprovision(linkId) {
|
|
49132
|
+
writePending(loadPendingDeprovisions().filter((p) => p.linkId !== linkId));
|
|
49133
|
+
}
|
|
48788
49134
|
function removeLinkConfig(linkId) {
|
|
48789
49135
|
writeAll(loadLinkConfigs().filter((c) => c.linkId !== linkId));
|
|
48790
49136
|
}
|
|
@@ -49437,6 +49783,7 @@ function resumeActiveLinks() {
|
|
|
49437
49783
|
if (cfg2.initiated && isHostOnline(cfg2.peerHostId))
|
|
49438
49784
|
sendActiveLinkProvision(cfg2);
|
|
49439
49785
|
}
|
|
49786
|
+
flushPendingDeprovisions();
|
|
49440
49787
|
} catch (e) {
|
|
49441
49788
|
console.warn("[active-link] resume failed:", e.message);
|
|
49442
49789
|
}
|
|
@@ -49445,11 +49792,21 @@ function isHostOnline(hostId) {
|
|
|
49445
49792
|
return serverHosts.some((h) => h.hostId === hostId && h.online);
|
|
49446
49793
|
}
|
|
49447
49794
|
function sendActiveLinkProvision(cfg2) {
|
|
49448
|
-
send("activelink", {
|
|
49795
|
+
send("activelink", {
|
|
49796
|
+
type: "provision",
|
|
49797
|
+
linkId: cfg2.linkId,
|
|
49798
|
+
fromHost: ownHostId(),
|
|
49799
|
+
projectName: cfg2.remoteSubfolder ?? basename5(cfg2.localRoot),
|
|
49800
|
+
...cfg2.remoteParent ? { remoteParent: cfg2.remoteParent } : {},
|
|
49801
|
+
...cfg2.remoteSubfolder ? { remoteSubfolder: cfg2.remoteSubfolder } : {},
|
|
49802
|
+
...cfg2.workspaceLinkId ? { workspaceLinkId: cfg2.workspaceLinkId } : {}
|
|
49803
|
+
}, { hostId: cfg2.peerHostId });
|
|
49449
49804
|
}
|
|
49450
49805
|
function safeFolderName(name) {
|
|
49451
49806
|
const cleaned = name.replace(/[/\\]/g, "-").replace(/\.\.+/g, ".").trim();
|
|
49452
|
-
|
|
49807
|
+
if (!cleaned || /^\.+$/.test(cleaned))
|
|
49808
|
+
return "project";
|
|
49809
|
+
return cleaned;
|
|
49453
49810
|
}
|
|
49454
49811
|
function provisionActiveLinkMirror(payload) {
|
|
49455
49812
|
if (!activeLinkEnabled())
|
|
@@ -49461,9 +49818,17 @@ function provisionActiveLinkMirror(payload) {
|
|
|
49461
49818
|
resumeActiveLinks();
|
|
49462
49819
|
return;
|
|
49463
49820
|
}
|
|
49464
|
-
|
|
49821
|
+
const workspaceLinkId = typeof payload.workspaceLinkId === "string" ? payload.workspaceLinkId : void 0;
|
|
49822
|
+
const remoteParent = typeof payload.remoteParent === "string" ? payload.remoteParent : void 0;
|
|
49823
|
+
const remoteSubfolder = typeof payload.remoteSubfolder === "string" ? payload.remoteSubfolder : void 0;
|
|
49824
|
+
let localRoot;
|
|
49825
|
+
if (remoteParent && remoteSubfolder) {
|
|
49826
|
+
localRoot = join26(remoteParent, safeFolderName(remoteSubfolder));
|
|
49827
|
+
} else {
|
|
49828
|
+
localRoot = join26(HOST_ROOT, "Tesseract Mirrors", safeFolderName(projectName));
|
|
49829
|
+
}
|
|
49465
49830
|
if (loadLinkConfigs().some((c) => c.localRoot === localRoot && c.linkId !== linkId)) {
|
|
49466
|
-
localRoot =
|
|
49831
|
+
localRoot = `${localRoot}-${linkId.slice(0, 6)}`;
|
|
49467
49832
|
}
|
|
49468
49833
|
if (!isInsideRoot(localRoot, HOST_ROOT))
|
|
49469
49834
|
return;
|
|
@@ -49471,9 +49836,31 @@ function provisionActiveLinkMirror(payload) {
|
|
|
49471
49836
|
mkdirSync9(localRoot, { recursive: true });
|
|
49472
49837
|
} catch {
|
|
49473
49838
|
}
|
|
49474
|
-
saveLinkConfig({
|
|
49839
|
+
saveLinkConfig({
|
|
49840
|
+
linkId,
|
|
49841
|
+
localRoot,
|
|
49842
|
+
peerHostId: fromHost,
|
|
49843
|
+
...workspaceLinkId ? { workspaceLinkId } : {},
|
|
49844
|
+
...remoteParent ? { remoteParent } : {},
|
|
49845
|
+
...remoteSubfolder ? { remoteSubfolder } : {}
|
|
49846
|
+
});
|
|
49475
49847
|
resumeActiveLinks();
|
|
49476
49848
|
}
|
|
49849
|
+
function flushPendingDeprovisions() {
|
|
49850
|
+
for (const d of loadPendingDeprovisions()) {
|
|
49851
|
+
if (isHostOnline(d.peerHostId))
|
|
49852
|
+
send("activelink", { type: "deprovision", linkId: d.linkId, fromHost: ownHostId() }, { hostId: d.peerHostId });
|
|
49853
|
+
}
|
|
49854
|
+
}
|
|
49855
|
+
function deprovisionActiveLinkMirror(payload) {
|
|
49856
|
+
const { linkId, fromHost } = payload;
|
|
49857
|
+
if (typeof linkId !== "string")
|
|
49858
|
+
return;
|
|
49859
|
+
void disconnectActiveLink(linkId);
|
|
49860
|
+
removeLinkConfig(linkId);
|
|
49861
|
+
if (typeof fromHost === "string")
|
|
49862
|
+
send("activelink", { type: "deprovisionAck", linkId }, { hostId: fromHost });
|
|
49863
|
+
}
|
|
49477
49864
|
function handleActiveLinkChannel(payload, inbound) {
|
|
49478
49865
|
if (!inbound)
|
|
49479
49866
|
return;
|
|
@@ -49481,8 +49868,12 @@ function handleActiveLinkChannel(payload, inbound) {
|
|
|
49481
49868
|
const p = payload;
|
|
49482
49869
|
if (p?.type === "provision")
|
|
49483
49870
|
provisionActiveLinkMirror(p);
|
|
49871
|
+
else if (p?.type === "deprovision")
|
|
49872
|
+
deprovisionActiveLinkMirror(p);
|
|
49873
|
+
else if (p?.type === "deprovisionAck" && typeof p.linkId === "string")
|
|
49874
|
+
removePendingDeprovision(p.linkId);
|
|
49484
49875
|
} catch (e) {
|
|
49485
|
-
console.warn("[active-link]
|
|
49876
|
+
console.warn("[active-link] channel handler failed:", e.message);
|
|
49486
49877
|
}
|
|
49487
49878
|
}
|
|
49488
49879
|
async function beginOutboundTransfer(p, clientId) {
|
|
@@ -49498,8 +49889,8 @@ async function beginOutboundTransfer(p, clientId) {
|
|
|
49498
49889
|
}
|
|
49499
49890
|
var fsWaiters = /* @__PURE__ */ new Map();
|
|
49500
49891
|
function rejectAllFsWaiters() {
|
|
49501
|
-
for (const [,
|
|
49502
|
-
|
|
49892
|
+
for (const [, resolve9] of fsWaiters)
|
|
49893
|
+
resolve9({ error: "Disconnected from the remote machine." });
|
|
49503
49894
|
fsWaiters.clear();
|
|
49504
49895
|
}
|
|
49505
49896
|
function clientIdFor(msg) {
|
|
@@ -49834,7 +50225,8 @@ function stopHeartbeat() {
|
|
|
49834
50225
|
function registerAsHost() {
|
|
49835
50226
|
void ensureP2pReady();
|
|
49836
50227
|
const kind = process.env.CCB_HOST_KIND === "cloud" ? "cloud" : void 0;
|
|
49837
|
-
|
|
50228
|
+
const name = kind === "cloud" ? "Cloud agent" : hostname3();
|
|
50229
|
+
send("host", { type: "host:register", name, platform: process.platform, deviceId, caps: ["agent", "fs", "term"], ...kind ? { kind } : {}, ...staticMetrics(hostVersion), ...p2pAdvert ?? {} });
|
|
49838
50230
|
if (!heartbeat)
|
|
49839
50231
|
heartbeat = setInterval(() => send("host", { type: "host:heartbeat", ...dynamicMetrics() }), 2e4);
|
|
49840
50232
|
}
|
|
@@ -50132,8 +50524,8 @@ async function startLocalServer(opts) {
|
|
|
50132
50524
|
const log3 = opts.log ?? (() => {
|
|
50133
50525
|
});
|
|
50134
50526
|
const wss = new import_websocket_server.default({ host: "127.0.0.1", port: 0 });
|
|
50135
|
-
await new Promise((
|
|
50136
|
-
wss.once("listening",
|
|
50527
|
+
await new Promise((resolve9, reject) => {
|
|
50528
|
+
wss.once("listening", resolve9);
|
|
50137
50529
|
wss.once("error", reject);
|
|
50138
50530
|
});
|
|
50139
50531
|
const addr = wss.address();
|
|
@@ -50368,8 +50760,8 @@ async function startLocalServer(opts) {
|
|
|
50368
50760
|
}
|
|
50369
50761
|
|
|
50370
50762
|
// ../../packages/host-core/dist/daemon-runtime.js
|
|
50371
|
-
import { readFileSync as
|
|
50372
|
-
import { join as
|
|
50763
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync10, existsSync as existsSync15, mkdirSync as mkdirSync10, unlinkSync as unlinkSync2, chmodSync as chmodSync3 } from "node:fs";
|
|
50764
|
+
import { join as join27 } from "node:path";
|
|
50373
50765
|
import { homedir as homedir11 } from "node:os";
|
|
50374
50766
|
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
50375
50767
|
|
|
@@ -50436,8 +50828,8 @@ async function runDaemon(opts = {}) {
|
|
|
50436
50828
|
const VERSION = opts.version ?? process.env.CCB_DAEMON_VERSION ?? "dev";
|
|
50437
50829
|
const TAG = opts.tag ?? "host-daemon";
|
|
50438
50830
|
const log3 = (...args) => console.log(`[${TAG} ${(/* @__PURE__ */ new Date()).toISOString()}]`, ...args);
|
|
50439
|
-
const pidfile = () =>
|
|
50440
|
-
const statusFile = () =>
|
|
50831
|
+
const pidfile = () => join27(daemonDir(), "daemon.lock");
|
|
50832
|
+
const statusFile = () => join27(daemonDir(), "status.json");
|
|
50441
50833
|
const isAlive2 = (pid) => {
|
|
50442
50834
|
try {
|
|
50443
50835
|
process.kill(pid, 0);
|
|
@@ -50450,7 +50842,7 @@ async function runDaemon(opts = {}) {
|
|
|
50450
50842
|
const f = pidfile();
|
|
50451
50843
|
try {
|
|
50452
50844
|
if (existsSync15(f)) {
|
|
50453
|
-
const prev = Number(
|
|
50845
|
+
const prev = Number(readFileSync11(f, "utf-8").trim());
|
|
50454
50846
|
if (prev && prev !== process.pid && isAlive2(prev))
|
|
50455
50847
|
return false;
|
|
50456
50848
|
}
|
|
@@ -50467,14 +50859,14 @@ async function runDaemon(opts = {}) {
|
|
|
50467
50859
|
function releaseLock() {
|
|
50468
50860
|
try {
|
|
50469
50861
|
const f = pidfile();
|
|
50470
|
-
if (existsSync15(f) && Number(
|
|
50862
|
+
if (existsSync15(f) && Number(readFileSync11(f, "utf-8").trim()) === process.pid)
|
|
50471
50863
|
unlinkSync2(f);
|
|
50472
50864
|
} catch {
|
|
50473
50865
|
}
|
|
50474
50866
|
}
|
|
50475
50867
|
function writeStatus(s) {
|
|
50476
50868
|
try {
|
|
50477
|
-
writeFileSync10(statusFile(), JSON.stringify({ pid: process.pid, version: VERSION, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), ...localInfo ?? {}, ...s }));
|
|
50869
|
+
writeFileSync10(statusFile(), JSON.stringify({ pid: process.pid, version: VERSION, execPath: process.execPath, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), ...localInfo ?? {}, ...s }));
|
|
50478
50870
|
chmodSync3(statusFile(), 384);
|
|
50479
50871
|
} catch {
|
|
50480
50872
|
}
|
|
@@ -50537,7 +50929,7 @@ async function runDaemon(opts = {}) {
|
|
|
50537
50929
|
if (r.status === 401) {
|
|
50538
50930
|
log3("device token no longer valid \u2014 dropping to local-only on restart");
|
|
50539
50931
|
try {
|
|
50540
|
-
unlinkSync2(
|
|
50932
|
+
unlinkSync2(join27(daemonDir(), "credentials.json"));
|
|
50541
50933
|
} catch {
|
|
50542
50934
|
}
|
|
50543
50935
|
shutdown(0);
|
|
@@ -50583,7 +50975,7 @@ import { platform as platform2 } from "node:os";
|
|
|
50583
50975
|
|
|
50584
50976
|
// ../../packages/host-core/dist/service/launchd.js
|
|
50585
50977
|
import { writeFileSync as writeFileSync11, existsSync as existsSync16, mkdirSync as mkdirSync11, unlinkSync as unlinkSync3 } from "node:fs";
|
|
50586
|
-
import { dirname as dirname13, join as
|
|
50978
|
+
import { dirname as dirname13, join as join28 } from "node:path";
|
|
50587
50979
|
import { homedir as homedir12, userInfo } from "node:os";
|
|
50588
50980
|
|
|
50589
50981
|
// ../../packages/host-core/dist/service/exec.js
|
|
@@ -50591,10 +50983,10 @@ import { execFile as execFile5, spawn as spawn5 } from "node:child_process";
|
|
|
50591
50983
|
import { promisify as promisify4 } from "node:util";
|
|
50592
50984
|
var run = promisify4(execFile5);
|
|
50593
50985
|
function runInherit(cmd, args) {
|
|
50594
|
-
return new Promise((
|
|
50986
|
+
return new Promise((resolve9) => {
|
|
50595
50987
|
const p = spawn5(cmd, args, { stdio: "inherit" });
|
|
50596
|
-
p.on("error", () =>
|
|
50597
|
-
p.on("close", () =>
|
|
50988
|
+
p.on("error", () => resolve9());
|
|
50989
|
+
p.on("close", () => resolve9());
|
|
50598
50990
|
});
|
|
50599
50991
|
}
|
|
50600
50992
|
|
|
@@ -50607,10 +50999,10 @@ function xml(s) {
|
|
|
50607
50999
|
}
|
|
50608
51000
|
function makeLaunchd(instanceId) {
|
|
50609
51001
|
const label = SERVICE_LABEL_BASE + (instanceId ? `.${instanceId}` : "");
|
|
50610
|
-
const plistPath = () =>
|
|
51002
|
+
const plistPath = () => join28(homedir12(), "Library", "LaunchAgents", `${label}.plist`);
|
|
50611
51003
|
const domainTarget = () => `gui/${userInfo().uid}`;
|
|
50612
51004
|
const serviceTarget = () => `${domainTarget()}/${label}`;
|
|
50613
|
-
const logFile = () =>
|
|
51005
|
+
const logFile = () => join28(daemonDir(), "daemon.log");
|
|
50614
51006
|
function buildPlist(spec) {
|
|
50615
51007
|
const args = [spec.exec, ...spec.args].map((a) => ` <string>${xml(a)}</string>`).join("\n");
|
|
50616
51008
|
const env = Object.entries(spec.env).map(([k, v]) => ` <key>${xml(k)}</key>
|
|
@@ -50703,7 +51095,7 @@ ${env}
|
|
|
50703
51095
|
|
|
50704
51096
|
// ../../packages/host-core/dist/service/systemd.js
|
|
50705
51097
|
import { writeFileSync as writeFileSync12, existsSync as existsSync17, mkdirSync as mkdirSync12, unlinkSync as unlinkSync4 } from "node:fs";
|
|
50706
|
-
import { dirname as dirname14, join as
|
|
51098
|
+
import { dirname as dirname14, join as join29 } from "node:path";
|
|
50707
51099
|
import { homedir as homedir13, userInfo as userInfo2 } from "node:os";
|
|
50708
51100
|
function shq(s) {
|
|
50709
51101
|
return `"${s.replace(/(["\\$`])/g, "\\$1")}"`;
|
|
@@ -50711,8 +51103,8 @@ function shq(s) {
|
|
|
50711
51103
|
function makeSystemd(instanceId) {
|
|
50712
51104
|
const unit = `tesseract-host${instanceId ? `-${instanceId}` : ""}.service`;
|
|
50713
51105
|
const unitPath = () => {
|
|
50714
|
-
const base = process.env.XDG_CONFIG_HOME ||
|
|
50715
|
-
return
|
|
51106
|
+
const base = process.env.XDG_CONFIG_HOME || join29(homedir13(), ".config");
|
|
51107
|
+
return join29(base, "systemd", "user", unit);
|
|
50716
51108
|
};
|
|
50717
51109
|
function buildUnit(spec) {
|
|
50718
51110
|
const execStart = [spec.exec, ...spec.args].map(shq).join(" ");
|
|
@@ -50783,11 +51175,11 @@ WantedBy=default.target
|
|
|
50783
51175
|
|
|
50784
51176
|
// ../../packages/host-core/dist/service/windows.js
|
|
50785
51177
|
import { writeFileSync as writeFileSync13, existsSync as existsSync18, mkdirSync as mkdirSync13, unlinkSync as unlinkSync5 } from "node:fs";
|
|
50786
|
-
import { dirname as dirname15, join as
|
|
51178
|
+
import { dirname as dirname15, join as join30 } from "node:path";
|
|
50787
51179
|
function makeWindowsTask(instanceId) {
|
|
50788
51180
|
const task = `Fineguide\\TesseractHost${instanceId ? `-${instanceId}` : ""}`;
|
|
50789
|
-
const wrapperPath = () =>
|
|
50790
|
-
const logFile = () =>
|
|
51181
|
+
const wrapperPath = () => join30(daemonDir(), `run-host${instanceId ? `-${instanceId}` : ""}.cmd`);
|
|
51182
|
+
const logFile = () => join30(daemonDir(), "daemon.log");
|
|
50791
51183
|
function buildWrapper(spec) {
|
|
50792
51184
|
const env = Object.entries(spec.env).map(([k, v]) => `set "${k}=${v}"`).join("\r\n");
|
|
50793
51185
|
const cmd = [spec.exec, ...spec.args].map((a) => `"${a}"`).join(" ");
|
|
@@ -50866,7 +51258,7 @@ function getServiceController(instanceId) {
|
|
|
50866
51258
|
var import_qrcode_terminal = __toESM(require_main(), 1);
|
|
50867
51259
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
50868
51260
|
import { existsSync as existsSync19, rmSync } from "node:fs";
|
|
50869
|
-
import { join as
|
|
51261
|
+
import { join as join31 } from "node:path";
|
|
50870
51262
|
|
|
50871
51263
|
// src/config.ts
|
|
50872
51264
|
import { hostname as hostname4 } from "node:os";
|
|
@@ -50898,7 +51290,7 @@ var BS = String.fromCharCode(8);
|
|
|
50898
51290
|
var ERASE = BS + " " + BS;
|
|
50899
51291
|
function ask(question) {
|
|
50900
51292
|
const { stdin, stdout } = process;
|
|
50901
|
-
return new Promise((
|
|
51293
|
+
return new Promise((resolve9) => {
|
|
50902
51294
|
stdout.write(question);
|
|
50903
51295
|
stdin.setEncoding("utf8");
|
|
50904
51296
|
if (!stdin.isTTY || typeof stdin.setRawMode !== "function") {
|
|
@@ -50911,7 +51303,7 @@ function ask(question) {
|
|
|
50911
51303
|
stdin.pause();
|
|
50912
51304
|
let line = data.slice(0, nl);
|
|
50913
51305
|
if (line.endsWith(CR)) line = line.slice(0, -1);
|
|
50914
|
-
|
|
51306
|
+
resolve9(line.trim());
|
|
50915
51307
|
}
|
|
50916
51308
|
};
|
|
50917
51309
|
stdin.resume();
|
|
@@ -50926,7 +51318,7 @@ function ask(question) {
|
|
|
50926
51318
|
stdin.pause();
|
|
50927
51319
|
stdin.removeListener("data", onData);
|
|
50928
51320
|
stdout.write(LF);
|
|
50929
|
-
|
|
51321
|
+
resolve9(buf.trim());
|
|
50930
51322
|
}
|
|
50931
51323
|
function onData(chunk) {
|
|
50932
51324
|
for (const ch of chunk) {
|
|
@@ -50982,7 +51374,7 @@ function persist2(api, relay, deviceId2, dt) {
|
|
|
50982
51374
|
async function login(opts) {
|
|
50983
51375
|
const api = (opts.api ?? DEFAULT_API).replace(/\/$/, "");
|
|
50984
51376
|
const relay = (opts.relay ?? defaultRelay(api)).replace(/\/$/, "");
|
|
50985
|
-
const deviceId2 = readCredentials()?.deviceId ?? randomUUID6().slice(0, 8);
|
|
51377
|
+
const deviceId2 = readCredentials()?.deviceId ?? process.env.CCB_DEVICE_ID ?? randomUUID6().slice(0, 8);
|
|
50986
51378
|
const label = opts.name ?? defaultLabel();
|
|
50987
51379
|
if (opts.token) {
|
|
50988
51380
|
const dt = await fetchJson(`${api}/auth/device-token`, {
|
|
@@ -51043,7 +51435,7 @@ async function logout() {
|
|
|
51043
51435
|
}
|
|
51044
51436
|
for (const f of ["credentials.json", "status.json", "daemon.lock"]) {
|
|
51045
51437
|
try {
|
|
51046
|
-
const p =
|
|
51438
|
+
const p = join31(daemonDir(), f);
|
|
51047
51439
|
if (existsSync19(p)) rmSync(p);
|
|
51048
51440
|
} catch {
|
|
51049
51441
|
}
|
|
@@ -51105,7 +51497,7 @@ async function fetchLatest() {
|
|
|
51105
51497
|
}
|
|
51106
51498
|
}
|
|
51107
51499
|
function installVersion(target) {
|
|
51108
|
-
return new Promise((
|
|
51500
|
+
return new Promise((resolve9) => {
|
|
51109
51501
|
const npm = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
51110
51502
|
log2(`installing tesseract-agent@${target} \u2026`);
|
|
51111
51503
|
let child;
|
|
@@ -51113,20 +51505,20 @@ function installVersion(target) {
|
|
|
51113
51505
|
child = spawn6(npm, ["install", "-g", `tesseract-agent@${target}`], { stdio: ["ignore", "inherit", "inherit"] });
|
|
51114
51506
|
} catch (e) {
|
|
51115
51507
|
log2("npm spawn threw:", e instanceof Error ? e.message : String(e));
|
|
51116
|
-
|
|
51508
|
+
resolve9(false);
|
|
51117
51509
|
return;
|
|
51118
51510
|
}
|
|
51119
51511
|
child.on("error", (e) => {
|
|
51120
51512
|
log2("npm not runnable:", e.message);
|
|
51121
|
-
|
|
51513
|
+
resolve9(false);
|
|
51122
51514
|
});
|
|
51123
51515
|
child.on("close", (code) => {
|
|
51124
51516
|
if (code === 0) {
|
|
51125
51517
|
log2(`installed ${target}`);
|
|
51126
|
-
|
|
51518
|
+
resolve9(true);
|
|
51127
51519
|
} else {
|
|
51128
51520
|
log2(`npm install exited ${code} \u2014 staying on the current version`);
|
|
51129
|
-
|
|
51521
|
+
resolve9(false);
|
|
51130
51522
|
}
|
|
51131
51523
|
});
|
|
51132
51524
|
});
|
|
@@ -51167,9 +51559,9 @@ function startSelfUpdater(current) {
|
|
|
51167
51559
|
}
|
|
51168
51560
|
|
|
51169
51561
|
// src/service.ts
|
|
51170
|
-
import { join as
|
|
51562
|
+
import { join as join32 } from "node:path";
|
|
51171
51563
|
import { platform as platform3 } from "node:os";
|
|
51172
|
-
import { existsSync as existsSync20, readFileSync as
|
|
51564
|
+
import { existsSync as existsSync20, readFileSync as readFileSync12 } from "node:fs";
|
|
51173
51565
|
function controller(instanceId) {
|
|
51174
51566
|
const c = getServiceController(instanceId);
|
|
51175
51567
|
if (!c) {
|
|
@@ -51182,7 +51574,7 @@ function buildSpec(cliEntry) {
|
|
|
51182
51574
|
exec: process.execPath,
|
|
51183
51575
|
args: [cliEntry, "run"],
|
|
51184
51576
|
env: { CCB_DAEMON_DIR: daemonDir() },
|
|
51185
|
-
logPath:
|
|
51577
|
+
logPath: join32(daemonDir(), "daemon.log")
|
|
51186
51578
|
};
|
|
51187
51579
|
}
|
|
51188
51580
|
var isAlive = (pid) => {
|
|
@@ -51194,10 +51586,10 @@ var isAlive = (pid) => {
|
|
|
51194
51586
|
}
|
|
51195
51587
|
};
|
|
51196
51588
|
function runningDaemonInfo() {
|
|
51197
|
-
const lock =
|
|
51589
|
+
const lock = join32(daemonDir(), "daemon.lock");
|
|
51198
51590
|
try {
|
|
51199
51591
|
if (!existsSync20(lock)) return null;
|
|
51200
|
-
const pid = Number(
|
|
51592
|
+
const pid = Number(readFileSync12(lock, "utf-8").trim());
|
|
51201
51593
|
if (!pid || !isAlive(pid)) return null;
|
|
51202
51594
|
return { pid, device: readCredentials()?.deviceId };
|
|
51203
51595
|
} catch {
|
|
@@ -51233,8 +51625,8 @@ async function logs(instanceId, follow) {
|
|
|
51233
51625
|
// src/cli.ts
|
|
51234
51626
|
function pkgVersion() {
|
|
51235
51627
|
try {
|
|
51236
|
-
const p =
|
|
51237
|
-
return JSON.parse(
|
|
51628
|
+
const p = join33(dirname16(fileURLToPath2(import.meta.url)), "..", "package.json");
|
|
51629
|
+
return JSON.parse(readFileSync13(p, "utf8")).version ?? "0.0.0";
|
|
51238
51630
|
} catch {
|
|
51239
51631
|
return "0.0.0";
|
|
51240
51632
|
}
|
|
@@ -51285,7 +51677,6 @@ function applyRunFlags(rest, flags) {
|
|
|
51285
51677
|
}
|
|
51286
51678
|
if (flags["no-active-link"] === true) process.env.CCB_ACTIVE_LINK = "0";
|
|
51287
51679
|
else if (flags["active-link"] === true) process.env.CCB_ACTIVE_LINK = "1";
|
|
51288
|
-
else if (process.env.CCB_ACTIVE_LINK === void 0) process.env.CCB_ACTIVE_LINK = "1";
|
|
51289
51680
|
}
|
|
51290
51681
|
async function superviseDaemon(cliEntry) {
|
|
51291
51682
|
let stopping = false;
|
|
@@ -51400,7 +51791,7 @@ async function linkCommand(rest, flags) {
|
|
|
51400
51791
|
return;
|
|
51401
51792
|
}
|
|
51402
51793
|
if (sub === "add") {
|
|
51403
|
-
const folder = rest[1] && !rest[1].startsWith("--") ?
|
|
51794
|
+
const folder = rest[1] && !rest[1].startsWith("--") ? resolve8(rest[1]) : void 0;
|
|
51404
51795
|
const peer = typeof flags.peer === "string" ? flags.peer : void 0;
|
|
51405
51796
|
if (!folder || !peer) {
|
|
51406
51797
|
console.error("Usage: tesseract-agent link add <folder> --peer <hostId> (--name <shared> | --id <sharedId>)");
|
|
@@ -51497,7 +51888,7 @@ async function main() {
|
|
|
51497
51888
|
process.exit(1);
|
|
51498
51889
|
}
|
|
51499
51890
|
instance = flags.instance;
|
|
51500
|
-
process.env.CCB_DAEMON_DIR =
|
|
51891
|
+
process.env.CCB_DAEMON_DIR = join33(homedir14(), ".tesseract", `daemon-${instance}`);
|
|
51501
51892
|
}
|
|
51502
51893
|
const force = flags.yes === true || flags.force === true;
|
|
51503
51894
|
const cliEntry = fileURLToPath2(import.meta.url);
|