tesseract-agent 0.10.7 → 0.10.9
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
CHANGED
|
@@ -80,16 +80,25 @@ function deriveSystemDirs(home) {
|
|
|
80
80
|
music: join(home, "Music")
|
|
81
81
|
};
|
|
82
82
|
}
|
|
83
|
+
function expandTilde(p) {
|
|
84
|
+
if (p === "~")
|
|
85
|
+
return USER_HOME;
|
|
86
|
+
if (p.startsWith("~/") || p.startsWith("~\\"))
|
|
87
|
+
return join(USER_HOME, p.slice(2));
|
|
88
|
+
return p;
|
|
89
|
+
}
|
|
83
90
|
function memoEnvRoot() {
|
|
84
91
|
const memo = /* @__PURE__ */ new Map();
|
|
85
|
-
return (
|
|
86
|
-
const
|
|
92
|
+
return (envVars, fallback) => {
|
|
93
|
+
const names = Array.isArray(envVars) ? envVars : [envVars];
|
|
94
|
+
const memoKey = names.join("|");
|
|
95
|
+
const hit = memo.get(memoKey);
|
|
87
96
|
if (hit !== void 0)
|
|
88
97
|
return hit;
|
|
89
|
-
const raw = process.env[
|
|
90
|
-
const value = raw
|
|
98
|
+
const raw = names.map((n) => process.env[n]).find((v) => v && v.trim());
|
|
99
|
+
const value = raw ? resolve(STARTUP_CWD, expandTilde(raw.trim())) : fallback();
|
|
91
100
|
if (!peeking)
|
|
92
|
-
memo.set(
|
|
101
|
+
memo.set(memoKey, value);
|
|
93
102
|
return value;
|
|
94
103
|
};
|
|
95
104
|
}
|
|
@@ -100,13 +109,30 @@ function homePath(...segments) {
|
|
|
100
109
|
return join(USER_HOME, ...segments);
|
|
101
110
|
}
|
|
102
111
|
function tesseractHome() {
|
|
103
|
-
return envRoot(
|
|
112
|
+
return envRoot([...TESSERACT_HOME_ENV_VARS], () => join(USER_HOME, ".tesseract"));
|
|
113
|
+
}
|
|
114
|
+
function isAlternateHome() {
|
|
115
|
+
return tesseractHome() !== installedTesseractHome();
|
|
116
|
+
}
|
|
117
|
+
function homeTag() {
|
|
118
|
+
if (!isAlternateHome())
|
|
119
|
+
return "";
|
|
120
|
+
let h = 2166136261;
|
|
121
|
+
const path6 = tesseractHome();
|
|
122
|
+
for (let i = 0; i < path6.length; i++) {
|
|
123
|
+
h ^= path6.charCodeAt(i);
|
|
124
|
+
h = Math.imul(h, 16777619);
|
|
125
|
+
}
|
|
126
|
+
return (h >>> 0).toString(36);
|
|
127
|
+
}
|
|
128
|
+
function installedTesseractHome() {
|
|
129
|
+
return join(USER_HOME, ".tesseract");
|
|
104
130
|
}
|
|
105
131
|
function tessPath(...segments) {
|
|
106
132
|
return join(tesseractHome(), ...segments);
|
|
107
133
|
}
|
|
108
134
|
function daemonDir() {
|
|
109
|
-
return envRoot("CCB_DAEMON_DIR", () => join(tesseractHome(), "daemon"));
|
|
135
|
+
return envRoot(["TESSERACT_DAEMON_DIR", "CCB_DAEMON_DIR"], () => join(tesseractHome(), "daemon"));
|
|
110
136
|
}
|
|
111
137
|
function daemonPath(...segments) {
|
|
112
138
|
return join(daemonDir(), ...segments);
|
|
@@ -140,7 +166,7 @@ function sealBasePaths() {
|
|
|
140
166
|
claudeConfigDir();
|
|
141
167
|
return snapshotBasePaths();
|
|
142
168
|
}
|
|
143
|
-
var STARTUP_CWD, USER_HOME, TEMP_DIR, systemDirs, envRoot, peeking, dropsDir;
|
|
169
|
+
var STARTUP_CWD, USER_HOME, TEMP_DIR, systemDirs, envRoot, peeking, dropsDir, TESSERACT_HOME_ENV_VARS;
|
|
144
170
|
var init_base_paths = __esm({
|
|
145
171
|
"../../packages/shared/dist/base-paths.js"() {
|
|
146
172
|
"use strict";
|
|
@@ -151,6 +177,7 @@ var init_base_paths = __esm({
|
|
|
151
177
|
envRoot = memoEnvRoot();
|
|
152
178
|
peeking = false;
|
|
153
179
|
dropsDir = () => join(systemDirs.downloads, "Tesseract");
|
|
180
|
+
TESSERACT_HOME_ENV_VARS = ["TESSERACT_HOMEDIR", "CCB_TESSERACT_DIR"];
|
|
154
181
|
}
|
|
155
182
|
});
|
|
156
183
|
|
|
@@ -3983,6 +4010,20 @@ var init_app_elements = __esm({
|
|
|
3983
4010
|
title: "Search",
|
|
3984
4011
|
description: "Opens search and the command palette \u2014 the fastest way to find anything."
|
|
3985
4012
|
},
|
|
4013
|
+
{
|
|
4014
|
+
id: "guide.dock",
|
|
4015
|
+
area: "guide",
|
|
4016
|
+
title: "The guide",
|
|
4017
|
+
// No `reveal`: the dock only exists while the guide is summoned, and a tour step that
|
|
4018
|
+
// silently opened it would be pointing at something it had just conjured.
|
|
4019
|
+
description: "Sits in the bottom corner when summoned. Type or say what you want and she does it."
|
|
4020
|
+
},
|
|
4021
|
+
{
|
|
4022
|
+
id: "titlebar.guide",
|
|
4023
|
+
area: "titlebar",
|
|
4024
|
+
title: "Ask the guide",
|
|
4025
|
+
description: "Opens the guide \u2014 say or type what you want and she does it, or shows you where."
|
|
4026
|
+
},
|
|
3986
4027
|
{
|
|
3987
4028
|
id: "titlebar.settings",
|
|
3988
4029
|
area: "titlebar",
|
|
@@ -4226,8 +4267,8 @@ function parseModelJsonArray(raw) {
|
|
|
4226
4267
|
function schemaRejected(status2) {
|
|
4227
4268
|
return status2 === 400 || status2 === 422;
|
|
4228
4269
|
}
|
|
4229
|
-
function anthropicBaseUrl() {
|
|
4230
|
-
return process.env.ANTHROPIC_BASE_URL?.trim() || "https://api.anthropic.com";
|
|
4270
|
+
function anthropicBaseUrl(env) {
|
|
4271
|
+
return env?.ANTHROPIC_BASE_URL?.trim() || process.env.ANTHROPIC_BASE_URL?.trim() || "https://api.anthropic.com";
|
|
4231
4272
|
}
|
|
4232
4273
|
var OAUTH_BETA_HEADER;
|
|
4233
4274
|
var init_model_json = __esm({
|
|
@@ -4251,6 +4292,56 @@ var init_domain_id = __esm({
|
|
|
4251
4292
|
}
|
|
4252
4293
|
});
|
|
4253
4294
|
|
|
4295
|
+
// ../../packages/shared/dist/run-directive.js
|
|
4296
|
+
function withRunDirective(userText, directive) {
|
|
4297
|
+
if (!directive.trim())
|
|
4298
|
+
return userText;
|
|
4299
|
+
const head = userText ? `${userText}
|
|
4300
|
+
|
|
4301
|
+
` : "";
|
|
4302
|
+
return `${head}${RUN_DIRECTIVE_MARK}
|
|
4303
|
+
${directive}`;
|
|
4304
|
+
}
|
|
4305
|
+
var RUN_DIRECTIVE_MARK;
|
|
4306
|
+
var init_run_directive = __esm({
|
|
4307
|
+
"../../packages/shared/dist/run-directive.js"() {
|
|
4308
|
+
"use strict";
|
|
4309
|
+
RUN_DIRECTIVE_MARK = "<!-- tesseract:run-directive -->";
|
|
4310
|
+
}
|
|
4311
|
+
});
|
|
4312
|
+
|
|
4313
|
+
// ../../packages/shared/dist/proactive-compaction.js
|
|
4314
|
+
function proactiveCompactionVerdict(a) {
|
|
4315
|
+
if (a.inFlight)
|
|
4316
|
+
return "skip";
|
|
4317
|
+
if (typeof a.pct !== "number" || !Number.isFinite(a.pct) || a.pct <= 0 || a.pct >= 100)
|
|
4318
|
+
return "skip";
|
|
4319
|
+
if (typeof a.usagePct !== "number" || !Number.isFinite(a.usagePct))
|
|
4320
|
+
return "skip";
|
|
4321
|
+
if (a.usagePct > IMPOSSIBLE_FILL_PCT)
|
|
4322
|
+
return "skip";
|
|
4323
|
+
if (a.usagePct < a.pct)
|
|
4324
|
+
return "reset";
|
|
4325
|
+
if (typeof a.lastCompactPct === "number" && a.usagePct < a.lastCompactPct + PROACTIVE_REGROWTH_POINTS)
|
|
4326
|
+
return "skip";
|
|
4327
|
+
return "compact";
|
|
4328
|
+
}
|
|
4329
|
+
var PROACTIVE_REGROWTH_POINTS, IMPOSSIBLE_FILL_PCT;
|
|
4330
|
+
var init_proactive_compaction = __esm({
|
|
4331
|
+
"../../packages/shared/dist/proactive-compaction.js"() {
|
|
4332
|
+
"use strict";
|
|
4333
|
+
PROACTIVE_REGROWTH_POINTS = 5;
|
|
4334
|
+
IMPOSSIBLE_FILL_PCT = 100;
|
|
4335
|
+
}
|
|
4336
|
+
});
|
|
4337
|
+
|
|
4338
|
+
// ../../packages/shared/dist/digit-recall.js
|
|
4339
|
+
var init_digit_recall = __esm({
|
|
4340
|
+
"../../packages/shared/dist/digit-recall.js"() {
|
|
4341
|
+
"use strict";
|
|
4342
|
+
}
|
|
4343
|
+
});
|
|
4344
|
+
|
|
4254
4345
|
// ../../packages/shared/dist/telemetry.js
|
|
4255
4346
|
var TELEMETRY_EVENTS, EVENT_CATEGORY;
|
|
4256
4347
|
var init_telemetry = __esm({
|
|
@@ -4678,14 +4769,67 @@ var init_hosting = __esm({
|
|
|
4678
4769
|
}
|
|
4679
4770
|
});
|
|
4680
4771
|
|
|
4772
|
+
// ../../packages/shared/dist/model-long-context.js
|
|
4773
|
+
function supportsOneMillionContext(model) {
|
|
4774
|
+
const id = (model ?? "").trim();
|
|
4775
|
+
if (!id)
|
|
4776
|
+
return false;
|
|
4777
|
+
if (/haiku/i.test(id))
|
|
4778
|
+
return false;
|
|
4779
|
+
return ONE_MILLION_FAMILIES.some((re) => re.test(id));
|
|
4780
|
+
}
|
|
4781
|
+
function hasOneMillionSuffix(model) {
|
|
4782
|
+
return /\[1m\]$/i.test((model ?? "").trim());
|
|
4783
|
+
}
|
|
4784
|
+
function withOneMillionContext(model) {
|
|
4785
|
+
const id = model?.trim();
|
|
4786
|
+
if (!id)
|
|
4787
|
+
return model;
|
|
4788
|
+
if (hasOneMillionSuffix(id))
|
|
4789
|
+
return id;
|
|
4790
|
+
if (!supportsOneMillionContext(id))
|
|
4791
|
+
return id;
|
|
4792
|
+
return `${id}${SUFFIX}`;
|
|
4793
|
+
}
|
|
4794
|
+
function withoutOneMillionContext(model) {
|
|
4795
|
+
const id = model?.trim();
|
|
4796
|
+
if (!id)
|
|
4797
|
+
return model;
|
|
4798
|
+
return id.replace(/\[1m\]$/i, "");
|
|
4799
|
+
}
|
|
4800
|
+
var ONE_MILLION_FAMILIES, SUFFIX;
|
|
4801
|
+
var init_model_long_context = __esm({
|
|
4802
|
+
"../../packages/shared/dist/model-long-context.js"() {
|
|
4803
|
+
"use strict";
|
|
4804
|
+
ONE_MILLION_FAMILIES = [
|
|
4805
|
+
/(^|[/.])claude-sonnet-(4-6|4-7|4-8|5)\b/i,
|
|
4806
|
+
/(^|[/.])claude-opus-(4-6|4-7|4-8|5)\b/i,
|
|
4807
|
+
/(^|[/.])claude-fable-5\b/i,
|
|
4808
|
+
// The CLI's own short aliases.
|
|
4809
|
+
/^(sonnet|opus|fable)$/i
|
|
4810
|
+
];
|
|
4811
|
+
SUFFIX = "[1m]";
|
|
4812
|
+
}
|
|
4813
|
+
});
|
|
4814
|
+
|
|
4681
4815
|
// ../../packages/shared/dist/settings.js
|
|
4682
4816
|
function canCallDirectly(modelId) {
|
|
4683
4817
|
return !!modelId && MODEL_OPTIONS.some((m) => m.id === modelId);
|
|
4684
4818
|
}
|
|
4685
|
-
|
|
4819
|
+
function isCliModelAlias(model) {
|
|
4820
|
+
return CLI_MODEL_ALIASES.test((model ?? "").trim());
|
|
4821
|
+
}
|
|
4822
|
+
function verifierModelLadder(model) {
|
|
4823
|
+
const bare = withoutOneMillionContext(model) ?? model;
|
|
4824
|
+
const first = canCallDirectly(bare) ? bare : DEFAULT_VERIFIER_MODEL;
|
|
4825
|
+
const rest = MODEL_OPTIONS.map((m) => m.id).filter((id) => id !== first && !/haiku/i.test(id));
|
|
4826
|
+
return [first, ...rest];
|
|
4827
|
+
}
|
|
4828
|
+
var MODEL_OPTIONS, DEFAULT_VERIFIER_MODEL, CLI_MODEL_ALIASES;
|
|
4686
4829
|
var init_settings = __esm({
|
|
4687
4830
|
"../../packages/shared/dist/settings.js"() {
|
|
4688
4831
|
"use strict";
|
|
4832
|
+
init_model_long_context();
|
|
4689
4833
|
MODEL_OPTIONS = [
|
|
4690
4834
|
{ id: "claude-opus-5", label: "Claude Opus 5" },
|
|
4691
4835
|
{ id: "claude-sonnet-5", label: "Claude Sonnet 5" },
|
|
@@ -4695,6 +4839,7 @@ var init_settings = __esm({
|
|
|
4695
4839
|
{ id: "claude-haiku-4-5", label: "Claude Haiku 4.5" }
|
|
4696
4840
|
];
|
|
4697
4841
|
DEFAULT_VERIFIER_MODEL = MODEL_OPTIONS[0].id;
|
|
4842
|
+
CLI_MODEL_ALIASES = /^(?:default|sonnet|opus|haiku|fable)(?:\[1m\])?$/i;
|
|
4698
4843
|
}
|
|
4699
4844
|
});
|
|
4700
4845
|
|
|
@@ -6373,9 +6518,9 @@ function kebab(s) {
|
|
|
6373
6518
|
return s.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase();
|
|
6374
6519
|
}
|
|
6375
6520
|
function tokenCssVarName(path6, token3) {
|
|
6376
|
-
const
|
|
6377
|
-
if (
|
|
6378
|
-
const name =
|
|
6521
|
+
const override3 = token3 ? tessExt(token3)?.cssVar : void 0;
|
|
6522
|
+
if (override3) {
|
|
6523
|
+
const name = override3.startsWith("--") ? override3 : `--${override3}`;
|
|
6379
6524
|
if (/^--[A-Za-z0-9-]+$/.test(name))
|
|
6380
6525
|
return name;
|
|
6381
6526
|
}
|
|
@@ -7229,6 +7374,9 @@ var init_dist = __esm({
|
|
|
7229
7374
|
init_ws_protocol();
|
|
7230
7375
|
init_frame();
|
|
7231
7376
|
init_domain_id();
|
|
7377
|
+
init_run_directive();
|
|
7378
|
+
init_proactive_compaction();
|
|
7379
|
+
init_digit_recall();
|
|
7232
7380
|
init_telemetry();
|
|
7233
7381
|
init_error_report();
|
|
7234
7382
|
init_eula();
|
|
@@ -7920,8 +8068,9 @@ function materializeClaudeAuthHome(contents) {
|
|
|
7920
8068
|
return home;
|
|
7921
8069
|
}
|
|
7922
8070
|
function withClaudeModels(env, main2, fast) {
|
|
7923
|
-
if (main2)
|
|
7924
|
-
env.ANTHROPIC_MODEL = main2;
|
|
8071
|
+
if (main2) {
|
|
8072
|
+
env.ANTHROPIC_MODEL = process.env.TESSERACT_DISABLE_1M_CONTEXT === "1" ? main2 : withOneMillionContext(main2) ?? main2;
|
|
8073
|
+
}
|
|
7925
8074
|
if (fast)
|
|
7926
8075
|
env.ANTHROPIC_SMALL_FAST_MODEL = fast;
|
|
7927
8076
|
return env;
|
|
@@ -7948,14 +8097,14 @@ function resolveRunnerEnv(spec) {
|
|
|
7948
8097
|
return {};
|
|
7949
8098
|
const key2 = spec?.secret?.trim();
|
|
7950
8099
|
if (provider.claudeEnterprise) {
|
|
7951
|
-
const
|
|
7952
|
-
if (
|
|
7953
|
-
return { CCB_RUNNER_CONFIG_ERROR:
|
|
7954
|
-
if (!
|
|
7955
|
-
return
|
|
8100
|
+
const run8 = claudeEnterpriseRun(provider.claudeEnterprise, { secret: key2, baseUrl: spec?.baseUrl, main: main2, fast });
|
|
8101
|
+
if (run8.error)
|
|
8102
|
+
return { CCB_RUNNER_CONFIG_ERROR: run8.error };
|
|
8103
|
+
if (!run8.file)
|
|
8104
|
+
return run8.env;
|
|
7956
8105
|
try {
|
|
7957
|
-
const path6 = materializeEnterpriseCredential(
|
|
7958
|
-
return { ...
|
|
8106
|
+
const path6 = materializeEnterpriseCredential(run8.file.suggestedName, run8.file.contents);
|
|
8107
|
+
return { ...run8.env, [run8.file.envVar]: path6 };
|
|
7959
8108
|
} catch (e) {
|
|
7960
8109
|
return { CCB_RUNNER_CONFIG_ERROR: `Could not write the ${provider.label} credential on this machine: ${e.message}` };
|
|
7961
8110
|
}
|
|
@@ -8022,6 +8171,7 @@ var init_resolve = __esm({
|
|
|
8022
8171
|
"../../packages/host-core/dist/runners/resolve.js"() {
|
|
8023
8172
|
"use strict";
|
|
8024
8173
|
init_base_paths();
|
|
8174
|
+
init_model_long_context();
|
|
8025
8175
|
init_file_lock();
|
|
8026
8176
|
init_dist();
|
|
8027
8177
|
init_proxy_router();
|
|
@@ -8562,21 +8712,27 @@ function readDaemonAgentSettings() {
|
|
|
8562
8712
|
return snap;
|
|
8563
8713
|
}
|
|
8564
8714
|
}
|
|
8715
|
+
function gatewayCanCall(model, snapshot4) {
|
|
8716
|
+
const tiers2 = snapshot4.gatewayTiers;
|
|
8717
|
+
if (!tiers2?.length)
|
|
8718
|
+
return true;
|
|
8719
|
+
return tiers2.includes(model) || snapshot4.gatewayDirectNaming === true;
|
|
8720
|
+
}
|
|
8565
8721
|
function gatewayTierRejection(model) {
|
|
8566
8722
|
if (!model)
|
|
8567
8723
|
return null;
|
|
8568
|
-
const
|
|
8569
|
-
if (
|
|
8724
|
+
const snap = readDaemonAgentSettings();
|
|
8725
|
+
if (gatewayCanCall(model, snap))
|
|
8570
8726
|
return null;
|
|
8571
|
-
return { model, tiers: [...
|
|
8727
|
+
return { model, tiers: [...snap.gatewayTiers ?? []] };
|
|
8572
8728
|
}
|
|
8573
8729
|
function gatewayTierClamp(model) {
|
|
8574
8730
|
if (!model)
|
|
8575
8731
|
return model;
|
|
8576
|
-
const
|
|
8577
|
-
if (
|
|
8732
|
+
const snap = readDaemonAgentSettings();
|
|
8733
|
+
if (gatewayCanCall(model, snap))
|
|
8578
8734
|
return model;
|
|
8579
|
-
console.warn(`[gateway] Model "${model}" isn't served by this device's gateway key (${
|
|
8735
|
+
console.warn(`[gateway] Model "${model}" isn't served by this device's gateway key (${(snap.gatewayTiers ?? []).join(", ")}) \u2014 dropping it so the gateway picks one it can reach.`);
|
|
8580
8736
|
return void 0;
|
|
8581
8737
|
}
|
|
8582
8738
|
function chatSendToParams(msg, defaults) {
|
|
@@ -8603,6 +8759,10 @@ function chatSendToParams(msg, defaults) {
|
|
|
8603
8759
|
// one OFF for one conversation could not actually turn it off.
|
|
8604
8760
|
...msg.unattended !== void 0 ? { unattended: msg.unattended } : {},
|
|
8605
8761
|
...msg.reinforcedVerification !== void 0 ? { reinforcedVerification: msg.reinforcedVerification } : {},
|
|
8762
|
+
// Forwarded even at 0/100 (both mean "no proactive compaction"), for the same reason as
|
|
8763
|
+
// the two flags above: falling through to the machine-wide number would make a
|
|
8764
|
+
// conversation that opted out of compaction impossible to express.
|
|
8765
|
+
...msg.autoCompactPct !== void 0 ? { autoCompactPct: msg.autoCompactPct } : {},
|
|
8606
8766
|
...msg.autoContinuation ? { autoContinuation: true } : {},
|
|
8607
8767
|
...msg.model ? { model: msg.model } : {},
|
|
8608
8768
|
...msg.jsonSchema ? { jsonSchema: msg.jsonSchema } : {},
|
|
@@ -8672,11 +8832,15 @@ function mergeDaemonAgentSettings(params) {
|
|
|
8672
8832
|
// local override (single-config CLI). Enabled skills' env is folded in. Empty ⇒
|
|
8673
8833
|
// ambient Claude.
|
|
8674
8834
|
engineEnv: params.engineEnv ?? {
|
|
8675
|
-
...
|
|
8835
|
+
...daemonEngineEnv(),
|
|
8676
8836
|
...s.skillEnv ?? {}
|
|
8677
8837
|
}
|
|
8678
8838
|
};
|
|
8679
8839
|
}
|
|
8840
|
+
function daemonEngineEnv() {
|
|
8841
|
+
const s = readDaemonAgentSettings();
|
|
8842
|
+
return poolActiveEngineEnv() ?? (s.runnerSpec ? resolveRunnerEnv(s.runnerSpec) : resolveOverrideEngineEnv());
|
|
8843
|
+
}
|
|
8680
8844
|
var init_daemon_settings = __esm({
|
|
8681
8845
|
"../../packages/host-core/dist/daemon-settings.js"() {
|
|
8682
8846
|
"use strict";
|
|
@@ -12031,10 +12195,10 @@ var init_schemas = __esm({
|
|
|
12031
12195
|
$ZodType.init(inst, def);
|
|
12032
12196
|
const desc = Object.getOwnPropertyDescriptor(def, "shape");
|
|
12033
12197
|
if (!desc?.get) {
|
|
12034
|
-
const
|
|
12198
|
+
const sh3 = def.shape;
|
|
12035
12199
|
Object.defineProperty(def, "shape", {
|
|
12036
12200
|
get: () => {
|
|
12037
|
-
const newSh = { ...
|
|
12201
|
+
const newSh = { ...sh3 };
|
|
12038
12202
|
Object.defineProperty(def, "shape", {
|
|
12039
12203
|
value: newSh
|
|
12040
12204
|
});
|
|
@@ -28539,8 +28703,8 @@ function prompt(id, vars) {
|
|
|
28539
28703
|
}
|
|
28540
28704
|
return "";
|
|
28541
28705
|
}
|
|
28542
|
-
const
|
|
28543
|
-
return interpolatePrompt(typeof
|
|
28706
|
+
const override3 = snapshot2.entries[id];
|
|
28707
|
+
return interpolatePrompt(typeof override3 === "string" ? override3 : spec.content, vars);
|
|
28544
28708
|
}
|
|
28545
28709
|
function describedBy(idPrefix, specs, key2 = (s) => s.name) {
|
|
28546
28710
|
return specs.map((spec) => Object.defineProperty({ ...spec }, "description", {
|
|
@@ -28681,7 +28845,7 @@ function buildPack(s) {
|
|
|
28681
28845
|
const dual = (lv) => ({ $value: lv[0], $extensions: { "com.tesseract": { modes: { dark: lv[1] } } } });
|
|
28682
28846
|
const val = (v) => Array.isArray(v) ? dual(v) : { $value: v };
|
|
28683
28847
|
const r = s.radius ?? { sm: "6px", md: "10px", lg: "16px" };
|
|
28684
|
-
const
|
|
28848
|
+
const sh3 = s.shadow ?? {
|
|
28685
28849
|
sm: "0 1px 2px rgb(0 0 0 / 0.06)",
|
|
28686
28850
|
md: "0 4px 12px rgb(0 0 0 / 0.08)",
|
|
28687
28851
|
lg: "0 12px 32px rgb(0 0 0 / 0.12)"
|
|
@@ -28726,7 +28890,7 @@ function buildPack(s) {
|
|
|
28726
28890
|
xl: { $value: "40px" }
|
|
28727
28891
|
},
|
|
28728
28892
|
radius: { $type: "dimension", sm: { $value: r.sm }, md: { $value: r.md }, lg: { $value: r.lg }, full: { $value: "9999px" } },
|
|
28729
|
-
shadow: { $type: "shadow", sm: { $value:
|
|
28893
|
+
shadow: { $type: "shadow", sm: { $value: sh3.sm }, md: { $value: sh3.md }, lg: { $value: sh3.lg } }
|
|
28730
28894
|
};
|
|
28731
28895
|
return { $packSchema: DESIGN_PACK_SCHEMA, id: s.id, name: s.name, description: s.description, style: s.style, tokens: tokens3 };
|
|
28732
28896
|
}
|
|
@@ -31689,7 +31853,7 @@ var init_job_registry = __esm({
|
|
|
31689
31853
|
* the calling tool can return `{ id, logPath }` to the model in the same tick, so the
|
|
31690
31854
|
* turn continues instead of blocking. `run` is deliberately NOT awaited here.
|
|
31691
31855
|
*/
|
|
31692
|
-
start(kind, description,
|
|
31856
|
+
start(kind, description, run8) {
|
|
31693
31857
|
const id = makeId(++this.seq);
|
|
31694
31858
|
const logPath = join16(this.dir, `${id}.output`);
|
|
31695
31859
|
const abort = new AbortController();
|
|
@@ -31709,7 +31873,7 @@ var init_job_registry = __esm({
|
|
|
31709
31873
|
this.evict();
|
|
31710
31874
|
void (async () => {
|
|
31711
31875
|
try {
|
|
31712
|
-
const tail3 = await
|
|
31876
|
+
const tail3 = await run8((chunk) => this.write(id, chunk), abort.signal);
|
|
31713
31877
|
if (typeof tail3 === "string" && tail3)
|
|
31714
31878
|
this.write(id, tail3);
|
|
31715
31879
|
this.settle(id, abort.signal.aborted ? "stopped" : "completed", abort.signal.aborted ? 130 : 0);
|
|
@@ -33458,9 +33622,9 @@ function paginationSignature(engine) {
|
|
|
33458
33622
|
return [...engine.pagination.params].sort().join("+");
|
|
33459
33623
|
}
|
|
33460
33624
|
function pageStrategy(engine) {
|
|
33461
|
-
const
|
|
33462
|
-
if (
|
|
33463
|
-
return
|
|
33625
|
+
const override3 = OVERRIDES[engine.id];
|
|
33626
|
+
if (override3)
|
|
33627
|
+
return override3;
|
|
33464
33628
|
const sig = paginationSignature(engine);
|
|
33465
33629
|
if (!sig)
|
|
33466
33630
|
return { kind: "none", reason: "This engine declares no pagination parameters." };
|
|
@@ -36608,27 +36772,18 @@ function autoCompactEnvFor(pct2, supplied) {
|
|
|
36608
36772
|
function shouldCompactProactively(a) {
|
|
36609
36773
|
if (a.mode === "off")
|
|
36610
36774
|
return "skip";
|
|
36611
|
-
|
|
36612
|
-
return "skip";
|
|
36613
|
-
if (typeof a.pct !== "number" || !Number.isFinite(a.pct) || a.pct <= 0 || a.pct >= 100)
|
|
36614
|
-
return "skip";
|
|
36615
|
-
if (typeof a.usagePct !== "number" || !Number.isFinite(a.usagePct))
|
|
36616
|
-
return "skip";
|
|
36617
|
-
if (a.usagePct < a.pct)
|
|
36618
|
-
return "reset";
|
|
36619
|
-
if (typeof a.lastCompactPct === "number" && a.usagePct < a.lastCompactPct + PROACTIVE_REGROWTH_POINTS)
|
|
36620
|
-
return "skip";
|
|
36621
|
-
return "compact";
|
|
36775
|
+
return proactiveCompactionVerdict(a);
|
|
36622
36776
|
}
|
|
36623
|
-
var OVERFLOW_MAX_TRIES, OVERFLOW_COMPACT_MESSAGE, OVERFLOW_RESUME_MESSAGE
|
|
36777
|
+
var OVERFLOW_MAX_TRIES, OVERFLOW_COMPACT_MESSAGE, OVERFLOW_RESUME_MESSAGE;
|
|
36624
36778
|
var init_context_recovery = __esm({
|
|
36625
36779
|
"../../packages/agent-core/dist/context-recovery.js"() {
|
|
36626
36780
|
"use strict";
|
|
36781
|
+
init_dist();
|
|
36627
36782
|
init_unattended_log();
|
|
36783
|
+
init_dist();
|
|
36628
36784
|
OVERFLOW_MAX_TRIES = 3;
|
|
36629
36785
|
OVERFLOW_COMPACT_MESSAGE = "/compact";
|
|
36630
36786
|
OVERFLOW_RESUME_MESSAGE = "Continue.";
|
|
36631
|
-
PROACTIVE_REGROWTH_POINTS = 5;
|
|
36632
36787
|
}
|
|
36633
36788
|
});
|
|
36634
36789
|
|
|
@@ -37456,13 +37611,16 @@ async function fetchSessionUsage(env) {
|
|
|
37456
37611
|
}
|
|
37457
37612
|
async function anthropicHeaders(env) {
|
|
37458
37613
|
const apiKey = env?.ANTHROPIC_API_KEY?.trim() || process.env.ANTHROPIC_API_KEY?.trim() || "";
|
|
37459
|
-
const
|
|
37460
|
-
|
|
37614
|
+
const authToken = apiKey ? "" : env?.ANTHROPIC_AUTH_TOKEN?.trim() || "";
|
|
37615
|
+
const oauth = apiKey || authToken ? "" : await resolveOauthToken(env) || "";
|
|
37616
|
+
if (!apiKey && !authToken && !oauth)
|
|
37461
37617
|
return null;
|
|
37462
37618
|
const headers = { "content-type": "application/json", "anthropic-version": "2023-06-01" };
|
|
37463
37619
|
if (apiKey)
|
|
37464
37620
|
headers["x-api-key"] = apiKey;
|
|
37465
|
-
else {
|
|
37621
|
+
else if (authToken) {
|
|
37622
|
+
headers.authorization = `Bearer ${authToken}`;
|
|
37623
|
+
} else {
|
|
37466
37624
|
headers.authorization = `Bearer ${oauth}`;
|
|
37467
37625
|
headers["anthropic-beta"] = OAUTH_BETA_HEADER;
|
|
37468
37626
|
}
|
|
@@ -37472,27 +37630,31 @@ async function hasAnthropicCred(env) {
|
|
|
37472
37630
|
return await anthropicHeaders(env) !== null;
|
|
37473
37631
|
}
|
|
37474
37632
|
async function anthropicMessage(args) {
|
|
37633
|
+
return (await anthropicCall(args)).text;
|
|
37634
|
+
}
|
|
37635
|
+
async function anthropicCall(args) {
|
|
37475
37636
|
const { env, model, system, content, maxTokens, timeoutMs, label } = args;
|
|
37476
37637
|
const attempts = Math.max(1, args.attempts ?? 1);
|
|
37477
37638
|
const budgetMs = args.budgetMs ?? attempts * timeoutMs + 4e3;
|
|
37478
37639
|
const deadline = Date.now() + budgetMs;
|
|
37479
|
-
const base = { model, max_tokens: maxTokens, system, messages: [{ role: "user", content }] };
|
|
37480
|
-
|
|
37481
|
-
let
|
|
37640
|
+
const base = { ...model ? { model } : {}, max_tokens: maxTokens, system, messages: [{ role: "user", content }] };
|
|
37641
|
+
const useSchema = !!args.schema && !schemaUnsupported.has(schemaKey(anthropicBaseUrl(env), model));
|
|
37642
|
+
let body = JSON.stringify(useSchema ? { ...base, output_config: { format: { type: "json_schema", schema: args.schema } } } : base);
|
|
37643
|
+
let schemaDropped = !useSchema;
|
|
37482
37644
|
const headers = await anthropicHeaders(env);
|
|
37483
37645
|
if (!headers)
|
|
37484
|
-
return null;
|
|
37646
|
+
return { text: null, rateLimited: false };
|
|
37485
37647
|
for (let attempt = 0; attempt < attempts; attempt++) {
|
|
37486
37648
|
const remaining = deadline - Date.now();
|
|
37487
37649
|
if (remaining < 1e3) {
|
|
37488
37650
|
log(`${label}: out of budget after ${attempt} attempt(s) \u2014 giving up rather than starting a leg that cannot finish.`);
|
|
37489
|
-
return null;
|
|
37651
|
+
return { text: null, rateLimited: false };
|
|
37490
37652
|
}
|
|
37491
37653
|
const ac = new AbortController();
|
|
37492
37654
|
const legMs = Math.min(timeoutMs, remaining);
|
|
37493
37655
|
const legTimer = setTimeout(() => ac.abort(new Error("The operation was aborted due to timeout")), legMs);
|
|
37494
37656
|
try {
|
|
37495
|
-
const res = await fetch(`${anthropicBaseUrl()}/v1/messages`, {
|
|
37657
|
+
const res = await fetch(`${anthropicBaseUrl(env)}/v1/messages`, {
|
|
37496
37658
|
method: "POST",
|
|
37497
37659
|
headers,
|
|
37498
37660
|
body,
|
|
@@ -37500,23 +37662,34 @@ async function anthropicMessage(args) {
|
|
|
37500
37662
|
});
|
|
37501
37663
|
if (res.ok) {
|
|
37502
37664
|
const j = await res.json();
|
|
37503
|
-
|
|
37665
|
+
const text12 = (j.content ?? []).filter((b) => b.type === "text").map((b) => b.text ?? "").join("").trim() || null;
|
|
37666
|
+
return { text: text12, rateLimited: false };
|
|
37504
37667
|
}
|
|
37505
37668
|
if (schemaRejected(res.status) && args.schema && !schemaDropped) {
|
|
37506
37669
|
schemaDropped = true;
|
|
37670
|
+
schemaUnsupported.add(schemaKey(anthropicBaseUrl(env), model));
|
|
37507
37671
|
body = JSON.stringify(base);
|
|
37508
37672
|
log(`${label}: the endpoint rejected output_config (${model}) \u2014 retrying without the schema and parsing the reply as text.`);
|
|
37509
37673
|
attempt--;
|
|
37510
37674
|
continue;
|
|
37511
37675
|
}
|
|
37512
|
-
|
|
37513
|
-
|
|
37676
|
+
const rateLimited = res.status === 429 || res.status === 529;
|
|
37677
|
+
const modelRejected = (res.status === 400 || res.status === 403 || res.status === 404) && !!model;
|
|
37678
|
+
if (rateLimited && attempt < attempts - 1) {
|
|
37679
|
+
let stated = 0;
|
|
37680
|
+
try {
|
|
37681
|
+
stated = Number(res.headers?.get?.("retry-after")) * 1e3;
|
|
37682
|
+
} catch {
|
|
37683
|
+
stated = 0;
|
|
37684
|
+
}
|
|
37685
|
+
const backoff3 = Number.isFinite(stated) && stated > 0 ? stated : 800 * (attempt + 1) * (attempt + 1);
|
|
37686
|
+
const wait = Math.max(0, Math.min(backoff3, deadline - Date.now()));
|
|
37514
37687
|
log(`${label}: HTTP ${res.status} (${model}) \u2014 retry ${attempt + 1} in ${wait}ms`);
|
|
37515
37688
|
await new Promise((r) => setTimeout(r, wait));
|
|
37516
37689
|
continue;
|
|
37517
37690
|
}
|
|
37518
37691
|
log(`${label}: HTTP ${res.status} (${model})`);
|
|
37519
|
-
return null;
|
|
37692
|
+
return { text: null, rateLimited, modelRejected };
|
|
37520
37693
|
} catch (err2) {
|
|
37521
37694
|
if (args.retryOnThrow && attempt < attempts - 1) {
|
|
37522
37695
|
const wait = Math.max(0, Math.min(800 * (attempt + 1) * (attempt + 1), deadline - Date.now()));
|
|
@@ -37525,19 +37698,27 @@ async function anthropicMessage(args) {
|
|
|
37525
37698
|
continue;
|
|
37526
37699
|
}
|
|
37527
37700
|
log(`${label}: call failed:`, err2 instanceof Error ? err2.message : String(err2));
|
|
37528
|
-
return null;
|
|
37701
|
+
return { text: null, rateLimited: false };
|
|
37529
37702
|
} finally {
|
|
37530
37703
|
clearTimeout(legTimer);
|
|
37531
37704
|
}
|
|
37532
37705
|
}
|
|
37533
|
-
return null;
|
|
37706
|
+
return { text: null, rateLimited: false };
|
|
37707
|
+
}
|
|
37708
|
+
function isDirectAnthropic(env) {
|
|
37709
|
+
try {
|
|
37710
|
+
return /(^|\.)api\.anthropic\.com$/i.test(new URL(anthropicBaseUrl(env)).hostname);
|
|
37711
|
+
} catch {
|
|
37712
|
+
return false;
|
|
37713
|
+
}
|
|
37534
37714
|
}
|
|
37535
37715
|
async function buildClaudeNarrationLlm(env) {
|
|
37536
37716
|
if (!await hasAnthropicCred(env))
|
|
37537
37717
|
return null;
|
|
37718
|
+
const model = isDirectAnthropic(env) ? "claude-haiku-4-5" : env?.ANTHROPIC_SMALL_FAST_MODEL?.trim() || env?.ANTHROPIC_MODEL?.trim() || "";
|
|
37538
37719
|
const complete = ({ system, prompt: prompt2, maxTokens, schema }) => anthropicMessage({
|
|
37539
37720
|
env,
|
|
37540
|
-
model
|
|
37721
|
+
model,
|
|
37541
37722
|
system,
|
|
37542
37723
|
content: prompt2,
|
|
37543
37724
|
maxTokens,
|
|
@@ -37547,43 +37728,60 @@ async function buildClaudeNarrationLlm(env) {
|
|
|
37547
37728
|
});
|
|
37548
37729
|
return { complete, engineLabel: "Claude Code" };
|
|
37549
37730
|
}
|
|
37550
|
-
|
|
37551
|
-
if (
|
|
37731
|
+
function graderLadder(model, env) {
|
|
37732
|
+
if (isDirectAnthropic(env))
|
|
37733
|
+
return verifierModelLadder(model);
|
|
37734
|
+
const configured = env?.ANTHROPIC_MODEL?.trim();
|
|
37735
|
+
const named = model?.trim();
|
|
37736
|
+
const wanted2 = named && !isCliModelAlias(named) ? named : configured;
|
|
37737
|
+
return [...new Set([wanted2, configured].filter((m) => !!m))];
|
|
37738
|
+
}
|
|
37739
|
+
async function buildClaudeSmartLlm(builderEnv) {
|
|
37740
|
+
return async ({ model, system, prompt: prompt2, maxTokens, schema, env: callEnv }) => {
|
|
37741
|
+
const env = callEnv && Object.keys(callEnv).length ? callEnv : builderEnv;
|
|
37742
|
+
const deadline = Date.now() + RV_GRADE_ATTEMPTS * RV_GRADE_TIMEOUT_MS + RV_GRADE_BACKOFF_MS;
|
|
37743
|
+
const ladder = graderLadder(model, env);
|
|
37744
|
+
let rejectedOnce = false;
|
|
37745
|
+
for (let i = 0; i < Math.max(1, ladder.length); i++) {
|
|
37746
|
+
const remaining = deadline - Date.now();
|
|
37747
|
+
if (remaining < 2e3)
|
|
37748
|
+
break;
|
|
37749
|
+
const out = await anthropicCall({
|
|
37750
|
+
env,
|
|
37751
|
+
schema,
|
|
37752
|
+
model: ladder[i] ?? "",
|
|
37753
|
+
// No `thinking` on purpose: the accepted shape differs per model generation
|
|
37754
|
+
// (adaptive-only, budget_tokens, disabled-at-effort), and a 400 here costs the whole
|
|
37755
|
+
// verification pass. The models we call think by default where it matters.
|
|
37756
|
+
system,
|
|
37757
|
+
content: prompt2,
|
|
37758
|
+
maxTokens,
|
|
37759
|
+
timeoutMs: Math.min(SMART_TIMEOUT_MS, remaining),
|
|
37760
|
+
label: "verifier",
|
|
37761
|
+
// TWO attempts, not three (RV_GRADE_ATTEMPTS) — see the deadline above. Only the
|
|
37762
|
+
// FIRST model gets them: a fallback leg exists because the first was rate-limited,
|
|
37763
|
+
// and spending the remaining budget re-asking one model would leave none for the
|
|
37764
|
+
// model that can actually answer.
|
|
37765
|
+
attempts: i === 0 ? RV_GRADE_ATTEMPTS : 1,
|
|
37766
|
+
retryOnThrow: i === 0,
|
|
37767
|
+
budgetMs: remaining
|
|
37768
|
+
});
|
|
37769
|
+
if (out.text) {
|
|
37770
|
+
if (i > 0)
|
|
37771
|
+
log(`verifier: graded with ${ladder[i]} \u2014 ${ladder[0]} was unavailable`);
|
|
37772
|
+
return out.text;
|
|
37773
|
+
}
|
|
37774
|
+
if (out.rateLimited)
|
|
37775
|
+
continue;
|
|
37776
|
+
if (out.modelRejected && !rejectedOnce) {
|
|
37777
|
+
rejectedOnce = true;
|
|
37778
|
+
continue;
|
|
37779
|
+
}
|
|
37780
|
+
return null;
|
|
37781
|
+
}
|
|
37782
|
+
log("verifier: every model was rate-limited or out of budget \u2014 this run cannot be graded now");
|
|
37552
37783
|
return null;
|
|
37553
|
-
|
|
37554
|
-
env,
|
|
37555
|
-
schema,
|
|
37556
|
-
// Only a model this endpoint actually serves. `/^claude-/` was a PROVIDER-NAME test
|
|
37557
|
-
// standing in for "can this be called": it passed a gateway tier alias or a dated id
|
|
37558
|
-
// straight through (400 → the schema-drop retry → 400 again → every verified run on that
|
|
37559
|
-
// model reporting "the verifier did not return a usable verdict"), and it FAILED
|
|
37560
|
-
// `us.anthropic.claude-*`, silently downgrading a Claude session's grader. The catalog
|
|
37561
|
-
// answers the question the regex was imitating.
|
|
37562
|
-
model: canCallDirectly(model) ? model : DEFAULT_VERIFIER_MODEL,
|
|
37563
|
-
// No `thinking` / `output_config` on purpose: the accepted shape differs per model
|
|
37564
|
-
// generation (adaptive-only, budget_tokens, disabled-at-effort), and a 400 here costs
|
|
37565
|
-
// the whole verification pass. The models we call think by default where it matters.
|
|
37566
|
-
system,
|
|
37567
|
-
content: prompt2,
|
|
37568
|
-
maxTokens,
|
|
37569
|
-
timeoutMs: SMART_TIMEOUT_MS,
|
|
37570
|
-
label: "verifier",
|
|
37571
|
-
// TWO attempts, not three (RV_GRADE_ATTEMPTS). The desktop gives a grade
|
|
37572
|
-
// RV_VERDICT_GRACE_MS before it stops waiting and ends the run itself; a third attempt
|
|
37573
|
-
// plus backoff pushes the sum past it, so the verdict would land after the client had
|
|
37574
|
-
// already moved on — and then dispatch a "continue and finish it" turn into whatever
|
|
37575
|
-
// the user started next.
|
|
37576
|
-
attempts: RV_GRADE_ATTEMPTS,
|
|
37577
|
-
retryOnThrow: true,
|
|
37578
|
-
// The ATTEMPT PLAN, not the client's grace — the two are different numbers on purpose.
|
|
37579
|
-
// The desktop stops waiting at RV_VERDICT_GRACE_MS (180s), ends the run itself, and a
|
|
37580
|
-
// late verdict then dispatches a "continue and finish it" turn on top of whatever the
|
|
37581
|
-
// user started next. The shared constants already encode the gap: 2 x 75s + 4s = 154s of
|
|
37582
|
-
// trying, leaving 26s for the verdict to actually get back and be applied. Budgeting to
|
|
37583
|
-
// the grace itself would spend that margin and land the answer exactly as the client
|
|
37584
|
-
// gives up, which is a race rather than a deadline.
|
|
37585
|
-
budgetMs: RV_GRADE_ATTEMPTS * RV_GRADE_TIMEOUT_MS + RV_GRADE_BACKOFF_MS
|
|
37586
|
-
});
|
|
37784
|
+
};
|
|
37587
37785
|
}
|
|
37588
37786
|
async function buildClaudeVisionLlm(env) {
|
|
37589
37787
|
if (!await hasAnthropicCred(env))
|
|
@@ -37603,7 +37801,7 @@ async function buildClaudeVisionLlm(env) {
|
|
|
37603
37801
|
]
|
|
37604
37802
|
});
|
|
37605
37803
|
}
|
|
37606
|
-
var execFileP, USAGE_URL, FETCH_TIMEOUT_MS, cache4, TTL_MS, SMART_TIMEOUT_MS, VISION_TIMEOUT_MS;
|
|
37804
|
+
var execFileP, USAGE_URL, FETCH_TIMEOUT_MS, cache4, TTL_MS, schemaUnsupported, schemaKey, SMART_TIMEOUT_MS, VISION_TIMEOUT_MS;
|
|
37607
37805
|
var init_session_usage = __esm({
|
|
37608
37806
|
"../../packages/agent-core/dist/session-usage.js"() {
|
|
37609
37807
|
"use strict";
|
|
@@ -37615,6 +37813,8 @@ var init_session_usage = __esm({
|
|
|
37615
37813
|
FETCH_TIMEOUT_MS = 5e3;
|
|
37616
37814
|
cache4 = null;
|
|
37617
37815
|
TTL_MS = 2e4;
|
|
37816
|
+
schemaUnsupported = /* @__PURE__ */ new Set();
|
|
37817
|
+
schemaKey = (base, model) => `${base}|${model}`;
|
|
37618
37818
|
SMART_TIMEOUT_MS = RV_GRADE_TIMEOUT_MS;
|
|
37619
37819
|
VISION_TIMEOUT_MS = 2e4;
|
|
37620
37820
|
}
|
|
@@ -38061,6 +38261,26 @@ function sessionStoreFor(mode) {
|
|
|
38061
38261
|
function unattendedReportDirective(send4) {
|
|
38062
38262
|
return unattendedModeFor({ optedIn: send4.unattended, origin: send4.origin }) !== "off" ? prompt("agent.system.unattended-report") : "";
|
|
38063
38263
|
}
|
|
38264
|
+
function sdkModelId(model) {
|
|
38265
|
+
const id = model?.trim();
|
|
38266
|
+
if (!id)
|
|
38267
|
+
return void 0;
|
|
38268
|
+
if (process.env.TESSERACT_DISABLE_1M_CONTEXT === "1")
|
|
38269
|
+
return id;
|
|
38270
|
+
if (/[/]/.test(id) || /^[a-z]{2,}\./i.test(id))
|
|
38271
|
+
return id;
|
|
38272
|
+
return withOneMillionContext(id) ?? id;
|
|
38273
|
+
}
|
|
38274
|
+
function anthropicEnvOf(env) {
|
|
38275
|
+
const keys = ["ANTHROPIC_BASE_URL", "ANTHROPIC_AUTH_TOKEN", "ANTHROPIC_API_KEY", "ANTHROPIC_MODEL", "ANTHROPIC_SMALL_FAST_MODEL", "CLAUDE_CODE_OAUTH_TOKEN", "CLAUDE_CONFIG_DIR"];
|
|
38276
|
+
const out = {};
|
|
38277
|
+
for (const k of keys) {
|
|
38278
|
+
const v = env[k];
|
|
38279
|
+
if (typeof v === "string" && v.trim())
|
|
38280
|
+
out[k] = v;
|
|
38281
|
+
}
|
|
38282
|
+
return out;
|
|
38283
|
+
}
|
|
38064
38284
|
function unknownModelEnv(model) {
|
|
38065
38285
|
const id = (model ?? "").trim();
|
|
38066
38286
|
if (!id || /^claude-/i.test(id))
|
|
@@ -38324,8 +38544,8 @@ function taskNotificationNotices(content) {
|
|
|
38324
38544
|
}
|
|
38325
38545
|
if (!text12.includes("<task-notification>"))
|
|
38326
38546
|
return [];
|
|
38327
|
-
const tag = (
|
|
38328
|
-
const m = new RegExp(`<${name}>([\\s\\S]*?)</${name}>`).exec(
|
|
38547
|
+
const tag = (xml3, name) => {
|
|
38548
|
+
const m = new RegExp(`<${name}>([\\s\\S]*?)</${name}>`).exec(xml3);
|
|
38329
38549
|
return m ? m[1].trim() : "";
|
|
38330
38550
|
};
|
|
38331
38551
|
const specs = [];
|
|
@@ -38614,6 +38834,12 @@ function withPinnedSource(sources, pinned) {
|
|
|
38614
38834
|
return sources;
|
|
38615
38835
|
return [...sources, pinned];
|
|
38616
38836
|
}
|
|
38837
|
+
function isCompactionPrompt(prompt2) {
|
|
38838
|
+
const p = (prompt2 ?? "").trim();
|
|
38839
|
+
if (!p.startsWith("/compact"))
|
|
38840
|
+
return false;
|
|
38841
|
+
return p.length === "/compact".length || /^[\s\n]/.test(p.slice("/compact".length));
|
|
38842
|
+
}
|
|
38617
38843
|
function buildMobileClause(dir2) {
|
|
38618
38844
|
try {
|
|
38619
38845
|
let fw = "";
|
|
@@ -38711,6 +38937,8 @@ var init_agent_manager = __esm({
|
|
|
38711
38937
|
init_reinforced_verification();
|
|
38712
38938
|
init_unattended_log();
|
|
38713
38939
|
init_context_recovery();
|
|
38940
|
+
init_model_long_context();
|
|
38941
|
+
init_dist();
|
|
38714
38942
|
init_dist();
|
|
38715
38943
|
init_dist();
|
|
38716
38944
|
init_base_paths();
|
|
@@ -39173,6 +39401,26 @@ var init_agent_manager = __esm({
|
|
|
39173
39401
|
* to pick them up (the SDK can't hot-swap mcpServers mid-query). Discarding only forfeits a
|
|
39174
39402
|
* ~2-3s pre-warm on the next new conversation, and only fires on infrequent plugin/project
|
|
39175
39403
|
* changes — never on the per-turn hot path. */
|
|
39404
|
+
/**
|
|
39405
|
+
* THE QUERY FACTORY — a test seam, and nothing else.
|
|
39406
|
+
*
|
|
39407
|
+
* `sendMessage` builds its own Query through the SDK, which is why the one thing every stall
|
|
39408
|
+
* watchdog test assumed could not be tested: that a turn ARMS the clock. Those tests arm it by
|
|
39409
|
+
* hand (`touchStream(live, true)`) and assert what it does, so deleting the arming call left the
|
|
39410
|
+
* whole file green while a stalled turn hung forever — the exact outage the watchdog exists to
|
|
39411
|
+
* prevent. The gap was papered over with an empty `it.skip` whose note read "needs a spawn seam
|
|
39412
|
+
* AgentManager does not expose". This is that seam.
|
|
39413
|
+
*
|
|
39414
|
+
* Deliberately narrow: it replaces ONLY the construction of the Query, so everything before it —
|
|
39415
|
+
* policy, arming, session bookkeeping, the option build — is the real code path under test. It is
|
|
39416
|
+
* NOT an extension point: nothing in the app calls it, and a plugin that wants to change how a
|
|
39417
|
+
* turn runs should be an engine backend instead.
|
|
39418
|
+
*/
|
|
39419
|
+
queryFactory = query;
|
|
39420
|
+
/** Replace the Query factory (pass null to restore the SDK's). Tests only — see queryFactory. */
|
|
39421
|
+
setQueryFactoryForTests(factory) {
|
|
39422
|
+
this.queryFactory = factory ?? query;
|
|
39423
|
+
}
|
|
39176
39424
|
setPluginTools(tools) {
|
|
39177
39425
|
this.pluginTools = tools;
|
|
39178
39426
|
if (this.warmEmpty)
|
|
@@ -39211,7 +39459,7 @@ var init_agent_manager = __esm({
|
|
|
39211
39459
|
* doing it would spend two turns on one reclaim.
|
|
39212
39460
|
*/
|
|
39213
39461
|
async maybeCompactProactively(live) {
|
|
39214
|
-
const pct2 = (() => {
|
|
39462
|
+
const pct2 = live.autoCompactPct ?? (() => {
|
|
39215
39463
|
try {
|
|
39216
39464
|
return this.autoCompactPct?.();
|
|
39217
39465
|
} catch {
|
|
@@ -39324,6 +39572,13 @@ var init_agent_manager = __esm({
|
|
|
39324
39572
|
this.narrator.setConfig(cfg2);
|
|
39325
39573
|
this.cheapLlm = cfg2?.complete ?? null;
|
|
39326
39574
|
}
|
|
39575
|
+
/** The endpoint + credential this HOST runs agents against, for the manager's own
|
|
39576
|
+
* on-demand model calls (see summarizeSession). Injected by the host, which is the only
|
|
39577
|
+
* side that can resolve it — see host-core `daemonEngineEnv`. */
|
|
39578
|
+
hostEnv = null;
|
|
39579
|
+
setHostEnv(env) {
|
|
39580
|
+
this.hostEnv = env && Object.keys(env).length ? env : null;
|
|
39581
|
+
}
|
|
39327
39582
|
/** Summarize a session transcript into concise Markdown with the injected cheap
|
|
39328
39583
|
* (Haiku) model. Runs in the daemon — the desktop forwards the request rather
|
|
39329
39584
|
* than calling a model itself. Keeps the HEAD + TAIL of a long transcript. */
|
|
@@ -39333,7 +39588,7 @@ var init_agent_manager = __esm({
|
|
|
39333
39588
|
let llm = this.cheapLlm;
|
|
39334
39589
|
if (!llm) {
|
|
39335
39590
|
try {
|
|
39336
|
-
llm = (await buildClaudeNarrationLlm())?.complete ?? null;
|
|
39591
|
+
llm = (await buildClaudeNarrationLlm(this.hostEnv ?? void 0))?.complete ?? null;
|
|
39337
39592
|
} catch {
|
|
39338
39593
|
}
|
|
39339
39594
|
}
|
|
@@ -39530,7 +39785,15 @@ ${full.slice(-8e3)}`;
|
|
|
39530
39785
|
}
|
|
39531
39786
|
const todos = live.todos?.map((t) => ({ content: t.content, status: String(t.status) }));
|
|
39532
39787
|
const call3 = gate === "review" ? reviewGrade(rv, finalText, todos) : gate === "phase" ? phaseGrade(rv, rv.lastVerdict?.phaseName ?? "", finalText, todos) : completenessGrade(rv, finalText, todos);
|
|
39533
|
-
const raw = await llm({
|
|
39788
|
+
const raw = await llm({
|
|
39789
|
+
model: live.model,
|
|
39790
|
+
system: call3.system,
|
|
39791
|
+
prompt: call3.prompt,
|
|
39792
|
+
maxTokens: 16e3,
|
|
39793
|
+
schema: call3.schema,
|
|
39794
|
+
// Grade THIS session on the endpoint it is running on — see live.endpointEnv.
|
|
39795
|
+
env: live.endpointEnv
|
|
39796
|
+
});
|
|
39534
39797
|
if (live.rv !== rv || live.reaped) {
|
|
39535
39798
|
if (live.reaped || live.rv === void 0) {
|
|
39536
39799
|
emitVerification({ action: "done", gate, cycle: rv.cycles, maxCycles: RV_MAX_CYCLES, unavailable: "This run ended before it could be verified." });
|
|
@@ -39608,6 +39871,8 @@ ${full.slice(-8e3)}`;
|
|
|
39608
39871
|
* and the 20-cycle cap silently stops capping anything. */
|
|
39609
39872
|
applyTurnPolicy(live, p) {
|
|
39610
39873
|
live.unattended = unattendedModeFor({ optedIn: p.unattended, origin: p.origin });
|
|
39874
|
+
if (p.autoCompactPct !== void 0)
|
|
39875
|
+
live.autoCompactPct = p.autoCompactPct;
|
|
39611
39876
|
live.autoDecisions = 0;
|
|
39612
39877
|
if (p.model !== void 0)
|
|
39613
39878
|
live.model = p.model || void 0;
|
|
@@ -40314,7 +40579,7 @@ ${lines}`;
|
|
|
40314
40579
|
if (opts.permissionMode)
|
|
40315
40580
|
await live.query.setPermissionMode(opts.permissionMode);
|
|
40316
40581
|
if (opts.model !== void 0) {
|
|
40317
|
-
await live.query.setModel(opts.model
|
|
40582
|
+
await live.query.setModel(sdkModelId(opts.model));
|
|
40318
40583
|
live.model = opts.model || void 0;
|
|
40319
40584
|
}
|
|
40320
40585
|
if (opts.maxThinkingTokens !== void 0)
|
|
@@ -40434,7 +40699,7 @@ ${lines}`;
|
|
|
40434
40699
|
live.windowId = params.windowId;
|
|
40435
40700
|
live.pendingTitle = params.message.trim().slice(0, 80);
|
|
40436
40701
|
if (params.model)
|
|
40437
|
-
void live.query.setModel(params.model
|
|
40702
|
+
void live.query.setModel(sdkModelId(params.model)).catch(() => {
|
|
40438
40703
|
});
|
|
40439
40704
|
if (params.permissionMode)
|
|
40440
40705
|
void live.query.setPermissionMode(params.permissionMode).catch(() => {
|
|
@@ -40609,6 +40874,7 @@ ${prompt("agent.system.project-dir", { dir: projectDir })}` : "";
|
|
|
40609
40874
|
windowId: params.windowId,
|
|
40610
40875
|
sources: params.sources,
|
|
40611
40876
|
unattended: params.unattended,
|
|
40877
|
+
autoCompactPct: params.autoCompactPct,
|
|
40612
40878
|
reinforcedVerification: params.reinforcedVerification,
|
|
40613
40879
|
task: params.message,
|
|
40614
40880
|
rvInjected: params.rvInjected,
|
|
@@ -40674,12 +40940,17 @@ ${prompt("agent.system.project-dir", { dir: projectDir })}` : "";
|
|
|
40674
40940
|
const lateDirective = live.unattendedReportSent ? "" : unattendedReportDirective(params);
|
|
40675
40941
|
if (lateDirective)
|
|
40676
40942
|
live.unattendedReportSent = true;
|
|
40943
|
+
const hostTurn = (params.autoContinuation || params.rvInjected) && !userText.trimStart().startsWith("/");
|
|
40677
40944
|
const sdkMsg = {
|
|
40678
40945
|
type: "user",
|
|
40679
40946
|
parent_tool_use_id: null,
|
|
40680
|
-
|
|
40681
|
-
|
|
40682
|
-
|
|
40947
|
+
// MARKED, so a client can show the user's own words and not the instruction we
|
|
40948
|
+
// appended to them — the engine writes this combined text into its transcript, so it
|
|
40949
|
+
// comes back on every resume (see shared/run-directive).
|
|
40950
|
+
message: {
|
|
40951
|
+
role: "user",
|
|
40952
|
+
content: lateDirective ? withRunDirective(userText, lateDirective) : hostTurn ? withRunDirective("", userText) : userText
|
|
40953
|
+
}
|
|
40683
40954
|
};
|
|
40684
40955
|
live.pump.push(sdkMsg);
|
|
40685
40956
|
}
|
|
@@ -40794,14 +41065,19 @@ ${lateDirective}` : userText }
|
|
|
40794
41065
|
// it. It only *permits* bypass — the active behavior is still governed by
|
|
40795
41066
|
// permissionMode, so it's safe to set unconditionally.
|
|
40796
41067
|
allowDangerouslySkipPermissions: true,
|
|
40797
|
-
|
|
41068
|
+
// Suffixed for the long window where the family has one — see sdkModelId. Without
|
|
41069
|
+
// this the CLI reports a 200k window for a 1M model and compaction acts on a fill
|
|
41070
|
+
// that is up to five times too high.
|
|
41071
|
+
...params.model ? { model: sdkModelId(params.model) } : {},
|
|
40798
41072
|
// Clamp to what THIS CLI accepts — an unsupported level is a hard exit-1, not
|
|
40799
41073
|
// a warning. See clampEffort.
|
|
40800
41074
|
...ultracodeEffort ? { effort: ultracodeEffort } : {},
|
|
40801
41075
|
// Model-level fallback. Ours rotates CREDENTIALS on failure; this rotates the
|
|
40802
41076
|
// MODEL before the turn fails at all, so an overloaded primary degrades instead
|
|
40803
41077
|
// of surfacing an error the user has to act on.
|
|
40804
|
-
|
|
41078
|
+
// Same for the fallback: it REPLACES the main model on an overload, so a bare id here
|
|
41079
|
+
// would quietly move a long conversation onto a 200k window mid-run.
|
|
41080
|
+
...params.fallbackModel ? { fallbackModel: sdkModelId(params.fallbackModel) } : {},
|
|
40805
41081
|
...params.enableFileCheckpointing ? { enableFileCheckpointing: true } : {},
|
|
40806
41082
|
...params.agentProgressSummaries ? { agentProgressSummaries: true } : {},
|
|
40807
41083
|
...params.includeHookEvents ? { includeHookEvents: true } : {},
|
|
@@ -41401,6 +41677,7 @@ ${lateDirective}` : userText }
|
|
|
41401
41677
|
...params.engineEnv ?? {},
|
|
41402
41678
|
CCB_IPC_PORT: String(live.ipcPort)
|
|
41403
41679
|
};
|
|
41680
|
+
live.endpointEnv = anthropicEnvOf(spawnEnv);
|
|
41404
41681
|
const child = spawn3(options.command, options.args, {
|
|
41405
41682
|
cwd: options.cwd,
|
|
41406
41683
|
env: spawnEnv,
|
|
@@ -41520,7 +41797,7 @@ ${unattendedReportDirective(params)}` : ""), live.sessionId) },
|
|
|
41520
41797
|
abortController,
|
|
41521
41798
|
...params.sessionId && { resume: params.sessionId }
|
|
41522
41799
|
};
|
|
41523
|
-
live.query = params.warm && params.sessionId ? (await startup({ options: queryOptions })).query(pump) :
|
|
41800
|
+
live.query = params.warm && params.sessionId ? (await startup({ options: queryOptions })).query(pump) : this.queryFactory({ prompt: pump, options: queryOptions });
|
|
41524
41801
|
} catch (err2) {
|
|
41525
41802
|
for (const s of live.ipcSockets) {
|
|
41526
41803
|
try {
|
|
@@ -42442,6 +42719,11 @@ ${err2.stack}` : ""}` : String(err2);
|
|
|
42442
42719
|
* the stream was actually alive. */
|
|
42443
42720
|
touchStream(live, firstFrame = false) {
|
|
42444
42721
|
live.lastFrameAt = monoNowMs();
|
|
42722
|
+
if (isCompactionPrompt(live.lastPrompt)) {
|
|
42723
|
+
live.stallWindowMs = void 0;
|
|
42724
|
+
this.clearStall(live);
|
|
42725
|
+
return;
|
|
42726
|
+
}
|
|
42445
42727
|
const window2 = firstFrame ? STREAM_FIRST_FRAME_MS : STREAM_STALL_MS;
|
|
42446
42728
|
live.stallWindowMs = window2;
|
|
42447
42729
|
if (!live.streaming) {
|
|
@@ -42486,7 +42768,7 @@ ${err2.stack}` : ""}` : String(err2);
|
|
|
42486
42768
|
this.armStall(live, decision.ms);
|
|
42487
42769
|
return;
|
|
42488
42770
|
}
|
|
42489
|
-
log(`Stream stall: no frames for ${STREAM_STALL_MS}ms on session ${live.sessionId || "(pending)"} \u2014 killing the dead turn so it can be retried`);
|
|
42771
|
+
log(`Stream stall: no frames for ${live.stallWindowMs ?? STREAM_STALL_MS}ms on session ${live.sessionId || "(pending)"} \u2014 killing the dead turn so it can be retried`);
|
|
42490
42772
|
live.stalled = true;
|
|
42491
42773
|
this.hardKillSession(live);
|
|
42492
42774
|
}
|
|
@@ -43942,10 +44224,10 @@ async function startHostedToolset(deps) {
|
|
|
43942
44224
|
if (asyncTools) {
|
|
43943
44225
|
try {
|
|
43944
44226
|
hostedJobs = await Promise.resolve().then(() => (init_hosted_jobs(), hosted_jobs_exports));
|
|
43945
|
-
const { tmpdir:
|
|
44227
|
+
const { tmpdir: tmpdir9 } = await import("node:os");
|
|
43946
44228
|
const { join: joinPath3 } = await import("node:path");
|
|
43947
44229
|
const made = hostedJobs.createHostedJobRegistry({
|
|
43948
|
-
dir: joinPath3(
|
|
44230
|
+
dir: joinPath3(tmpdir9(), "tesseract-hosted-jobs", randomUUID9()),
|
|
43949
44231
|
notifyModel: deps.notifyModel
|
|
43950
44232
|
});
|
|
43951
44233
|
jobs = made.registry;
|
|
@@ -44012,7 +44294,7 @@ async function startHostedToolset(deps) {
|
|
|
44012
44294
|
await build();
|
|
44013
44295
|
return { endpoint: endpoint2, sendBrowserResponse, tasks, refresh: build };
|
|
44014
44296
|
}
|
|
44015
|
-
function buildHostTaskTools(registry3,
|
|
44297
|
+
function buildHostTaskTools(registry3, run8) {
|
|
44016
44298
|
const text12 = (t, isError = false) => ({ content: [{ type: "text", text: t }], ...isError ? { isError: true } : {} });
|
|
44017
44299
|
return [
|
|
44018
44300
|
{
|
|
@@ -44034,7 +44316,7 @@ function buildHostTaskTools(registry3, run5) {
|
|
|
44034
44316
|
const task = registry3.start("subagent", description);
|
|
44035
44317
|
task.messages.push({ role: "user", content: prompt2 });
|
|
44036
44318
|
try {
|
|
44037
|
-
const out = await
|
|
44319
|
+
const out = await run8(prompt2, { signal: task.abort.signal });
|
|
44038
44320
|
if (task.status === "stopped")
|
|
44039
44321
|
return text12(`Subagent "${description}" was stopped.`, true);
|
|
44040
44322
|
task.status = "done";
|
|
@@ -78654,8 +78936,8 @@ var mesh_ca_exports = {};
|
|
|
78654
78936
|
__export(mesh_ca_exports, {
|
|
78655
78937
|
netCaCommand: () => netCaCommand
|
|
78656
78938
|
});
|
|
78657
|
-
import { chmodSync as chmodSync8, existsSync as
|
|
78658
|
-
import { join as
|
|
78939
|
+
import { chmodSync as chmodSync8, existsSync as existsSync48, mkdirSync as mkdirSync44, readFileSync as readFileSync50, writeFileSync as writeFileSync45 } from "node:fs";
|
|
78940
|
+
import { join as join86, resolve as resolve13 } from "node:path";
|
|
78659
78941
|
import { createInterface } from "node:readline";
|
|
78660
78942
|
function die(msg) {
|
|
78661
78943
|
console.error(msg);
|
|
@@ -78686,7 +78968,7 @@ async function readPassphrase(prompt2) {
|
|
|
78686
78968
|
}
|
|
78687
78969
|
}
|
|
78688
78970
|
function writeSecretFile(p, bytes2) {
|
|
78689
|
-
|
|
78971
|
+
writeFileSync45(p, bytes2, { mode: 384 });
|
|
78690
78972
|
try {
|
|
78691
78973
|
chmodSync8(p, 384);
|
|
78692
78974
|
} catch {
|
|
@@ -78700,9 +78982,9 @@ function ensureDir(p) {
|
|
|
78700
78982
|
}
|
|
78701
78983
|
}
|
|
78702
78984
|
async function openCa(dir2) {
|
|
78703
|
-
const gPath =
|
|
78704
|
-
const sPath =
|
|
78705
|
-
if (!
|
|
78985
|
+
const gPath = join86(dir2, "genesis.bin");
|
|
78986
|
+
const sPath = join86(dir2, "ca.sealed");
|
|
78987
|
+
if (!existsSync48(gPath) || !existsSync48(sPath)) {
|
|
78706
78988
|
die(`No mesh CA in ${dir2}. Run: tesseract-agent net init --org NAME --ca-dir ${dir2}`);
|
|
78707
78989
|
}
|
|
78708
78990
|
const genesisBytes = new Uint8Array(readFileSync50(gPath));
|
|
@@ -78723,7 +79005,7 @@ async function netCaCommand(rest, flags) {
|
|
|
78723
79005
|
if (sub === "init") {
|
|
78724
79006
|
const org = typeof flags.org === "string" ? flags.org.trim() : "";
|
|
78725
79007
|
if (!org) die("Usage: tesseract-agent net init --org NAME [--ca-dir DIR]");
|
|
78726
|
-
if (
|
|
79008
|
+
if (existsSync48(join86(caDir, "ca.sealed"))) {
|
|
78727
79009
|
die(`A mesh CA already exists in ${caDir}. Refusing to overwrite it.`);
|
|
78728
79010
|
}
|
|
78729
79011
|
const pass = await readPassphrase("New CA passphrase: ");
|
|
@@ -78745,9 +79027,9 @@ async function netCaCommand(rest, flags) {
|
|
|
78745
79027
|
const genesisBytes = encodeGenesis(genesis);
|
|
78746
79028
|
const fp = await genesisFingerprint(genesis);
|
|
78747
79029
|
ensureDir(caDir);
|
|
78748
|
-
|
|
78749
|
-
writeSecretFile(
|
|
78750
|
-
writeSecretFile(
|
|
79030
|
+
writeFileSync45(join86(caDir, "genesis.bin"), genesisBytes);
|
|
79031
|
+
writeSecretFile(join86(caDir, "ca.sealed"), encodeRecoveryBundle(await sealCaKey(seed, pass, `${org} mesh CA`)));
|
|
79032
|
+
writeSecretFile(join86(caDir, "disablement.secret"), hex3(disable.secret));
|
|
78751
79033
|
console.log(`
|
|
78752
79034
|
Mesh created for "${org}".`);
|
|
78753
79035
|
console.log(` fingerprint: ${hex3(fp)}`);
|
|
@@ -78762,7 +79044,7 @@ Mesh created for "${org}".`);
|
|
|
78762
79044
|
console.log(` ${hex3(disable.secret)}`);
|
|
78763
79045
|
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
78764
79046
|
console.log(`
|
|
78765
|
-
A copy of the disablement secret is in ${
|
|
79047
|
+
A copy of the disablement secret is in ${join86(caDir, "disablement.secret")}.`);
|
|
78766
79048
|
console.log("Move it somewhere the CA directory is not \u2014 holding both in one place");
|
|
78767
79049
|
console.log("defeats the point of having two.");
|
|
78768
79050
|
const caFlag = caDir === resolve13("./mesh-ca") ? "" : ` --ca-dir ${caDir}`;
|
|
@@ -78815,14 +79097,14 @@ Next, issue an identity for a machine (pick a free address in ${formatPrefix(gen
|
|
|
78815
79097
|
[{ keyIndex: 0, privateKey: ca.privateKey }]
|
|
78816
79098
|
);
|
|
78817
79099
|
ensureDir(outDir);
|
|
78818
|
-
|
|
78819
|
-
|
|
78820
|
-
writeSecretFile(
|
|
79100
|
+
writeFileSync45(join86(outDir, "genesis.bin"), genesisBytes);
|
|
79101
|
+
writeFileSync45(join86(outDir, "node.cert"), encodeCert(cert));
|
|
79102
|
+
writeSecretFile(join86(outDir, "node.key"), await exportStaticPrivate(nodeKey));
|
|
78821
79103
|
console.log(`Minted "${name}" at ${ip4}.`);
|
|
78822
79104
|
console.log(` ${outDir}`);
|
|
78823
79105
|
console.log("\nCopy that directory to the node and run there:");
|
|
78824
|
-
console.log(` tesseract-agent net enroll --genesis ${
|
|
78825
|
-
console.log(` --cert ${
|
|
79106
|
+
console.log(` tesseract-agent net enroll --genesis ${join86(outDir, "genesis.bin")} \\`);
|
|
79107
|
+
console.log(` --cert ${join86(outDir, "node.cert")} --key ${join86(outDir, "node.key")}`);
|
|
78826
79108
|
console.log("\nnode.key is the node's identity \u2014 send it over a channel you trust, and");
|
|
78827
79109
|
console.log("delete this copy once the node has it.");
|
|
78828
79110
|
return;
|
|
@@ -78858,8 +79140,8 @@ Next, issue an identity for a machine (pick a free address in ${formatPrefix(gen
|
|
|
78858
79140
|
ip4Exceptions: []
|
|
78859
79141
|
};
|
|
78860
79142
|
const signed = await signBundle(bundle, [{ keyIndex: 0, privateKey: ca.privateKey }]);
|
|
78861
|
-
const out = resolve13(typeof flags.out === "string" ? flags.out :
|
|
78862
|
-
|
|
79143
|
+
const out = resolve13(typeof flags.out === "string" ? flags.out : join86(caDir, "bundle.bin"));
|
|
79144
|
+
writeFileSync45(out, encodeSignedBundle(signed));
|
|
78863
79145
|
console.log(`Signed policy bundle (epoch ${epoch2}) \u2192 ${out}`);
|
|
78864
79146
|
console.log("Every node must receive it; the relay distributes it, or copy it to");
|
|
78865
79147
|
console.log(`each node's mesh directory as bundle.bin.`);
|
|
@@ -78881,12 +79163,12 @@ var init_mesh_ca = __esm({
|
|
|
78881
79163
|
|
|
78882
79164
|
// src/cli.ts
|
|
78883
79165
|
init_base_paths();
|
|
78884
|
-
import { existsSync as
|
|
79166
|
+
import { existsSync as existsSync49, mkdtempSync as mkdtempSync4, readFileSync as readFileSync52, rmSync as rmSync13 } from "node:fs";
|
|
78885
79167
|
import { createHash as createHash9 } from "node:crypto";
|
|
78886
|
-
import { execFileSync as execFileSync6, spawn as
|
|
78887
|
-
import { fileURLToPath as
|
|
78888
|
-
import { tmpdir as
|
|
78889
|
-
import { dirname as
|
|
79168
|
+
import { execFileSync as execFileSync6, spawn as spawn14 } from "node:child_process";
|
|
79169
|
+
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
79170
|
+
import { tmpdir as tmpdir8 } from "node:os";
|
|
79171
|
+
import { dirname as dirname38, join as join87, resolve as resolve15 } from "node:path";
|
|
78890
79172
|
import { createInterface as createInterface2 } from "node:readline/promises";
|
|
78891
79173
|
|
|
78892
79174
|
// ../../packages/host-core/dist/control-link.js
|
|
@@ -80445,6 +80727,7 @@ async function createClaudeCodeBackend(send4, onBrowserRequest, loadPluginRuntim
|
|
|
80445
80727
|
respondToPermission: (requestId, decision, callerOrigin) => manager2.respondToPermission(requestId, decision, callerOrigin),
|
|
80446
80728
|
setNarrationLlm: (cfg2) => manager2.setNarrationLlm(cfg2),
|
|
80447
80729
|
setVerifierLlm: (fn) => manager2.setVerifierLlm(fn),
|
|
80730
|
+
setHostEnv: (env) => manager2.setHostEnv(env),
|
|
80448
80731
|
setImageGen: (runner3) => manager2.setImageGen(runner3),
|
|
80449
80732
|
setSerpApi: (deps) => manager2.setSerpApi(deps),
|
|
80450
80733
|
setVideoGen: (runner3) => manager2.setVideoGen(runner3),
|
|
@@ -81749,9 +82032,9 @@ function resolveBundledMcpBin(basename14, envOverride) {
|
|
|
81749
82032
|
if (cached3 !== void 0)
|
|
81750
82033
|
return cached3;
|
|
81751
82034
|
const candidates = [];
|
|
81752
|
-
const
|
|
81753
|
-
if (
|
|
81754
|
-
candidates.push(
|
|
82035
|
+
const override3 = envOverride ? process.env[envOverride] : void 0;
|
|
82036
|
+
if (override3)
|
|
82037
|
+
candidates.push(override3);
|
|
81755
82038
|
const rp = process.resourcesPath;
|
|
81756
82039
|
if (rp)
|
|
81757
82040
|
candidates.push(join26(rp, "host-daemon", basename14));
|
|
@@ -83029,7 +83312,7 @@ function createAcpBackend(engine, send4, resolve16, onBrowserRequest, loadPlugin
|
|
|
83029
83312
|
return;
|
|
83030
83313
|
return sendMessage({ ...prev, message, sessionId: sid, autoContinuation: true });
|
|
83031
83314
|
},
|
|
83032
|
-
log: (m) => console.warn(`[${
|
|
83315
|
+
log: (m) => console.warn(`[${LABEL3}] ${m}`)
|
|
83033
83316
|
});
|
|
83034
83317
|
return noticeDispatcher;
|
|
83035
83318
|
};
|
|
@@ -83251,7 +83534,7 @@ function createAcpBackend(engine, send4, resolve16, onBrowserRequest, loadPlugin
|
|
|
83251
83534
|
...cappedOut ? { cappedOut: true } : {}
|
|
83252
83535
|
}, turn.origin);
|
|
83253
83536
|
},
|
|
83254
|
-
log: (m, e) => console.warn(`[${
|
|
83537
|
+
log: (m, e) => console.warn(`[${LABEL3}] ${m}`, e ?? "")
|
|
83255
83538
|
});
|
|
83256
83539
|
});
|
|
83257
83540
|
}
|
|
@@ -83489,7 +83772,7 @@ function createAcpBackend(engine, send4, resolve16, onBrowserRequest, loadPlugin
|
|
|
83489
83772
|
...cappedOut ? { cappedOut: true } : {}
|
|
83490
83773
|
}, turn.origin);
|
|
83491
83774
|
},
|
|
83492
|
-
log: (m, e) => console.warn(`[${
|
|
83775
|
+
log: (m, e) => console.warn(`[${LABEL3}] ${m}`, e ?? "")
|
|
83493
83776
|
});
|
|
83494
83777
|
});
|
|
83495
83778
|
});
|
|
@@ -83542,13 +83825,13 @@ function createAcpBackend(engine, send4, resolve16, onBrowserRequest, loadPlugin
|
|
|
83542
83825
|
agentMcp = agentCaps?.mcpCapabilities;
|
|
83543
83826
|
const authed = await withTimeout2(authenticateIfOffered(t, init?.authMethods), AUTH_TIMEOUT_MS, `${engine.label} did not finish authenticating.`).catch(() => false);
|
|
83544
83827
|
if (init?.authMethods?.length && !authed) {
|
|
83545
|
-
console.warn(`[${
|
|
83828
|
+
console.warn(`[${LABEL3}] no authentication method was accepted; session/load and resume may fail.`);
|
|
83546
83829
|
}
|
|
83547
83830
|
if (apiPort) {
|
|
83548
83831
|
const api = createEngineHttpApi(apiPort, engine.httpApi?.host ?? "127.0.0.1");
|
|
83549
83832
|
httpApi = await api.ready() ? api : null;
|
|
83550
83833
|
if (!httpApi)
|
|
83551
|
-
console.warn(`[${
|
|
83834
|
+
console.warn(`[${LABEL3}] its HTTP API did not come up on ${apiPort}; using the ACP path only.`);
|
|
83552
83835
|
}
|
|
83553
83836
|
} catch (e) {
|
|
83554
83837
|
try {
|
|
@@ -83895,7 +84178,9 @@ ${text12}`);
|
|
|
83895
84178
|
const usage2 = contextUsageFor(live);
|
|
83896
84179
|
const verdict = shouldCompactProactively({
|
|
83897
84180
|
mode: unattendedModeFor({ optedIn: params.unattended, origin: params.origin }),
|
|
83898
|
-
|
|
84181
|
+
// The conversation's own threshold when its client sent one (per-conversation there),
|
|
84182
|
+
// else the machine-wide setting.
|
|
84183
|
+
pct: params.autoCompactPct ?? readDaemonAgentSettings().autoCompactPct,
|
|
83899
84184
|
usagePct: typeof usage2?.percentage === "number" ? usage2.percentage : null,
|
|
83900
84185
|
lastCompactPct: proactiveCompactedAt.get(live) ?? null,
|
|
83901
84186
|
inFlight: false
|
|
@@ -83907,7 +84192,7 @@ ${text12}`);
|
|
|
83907
84192
|
if (verdict !== "compact")
|
|
83908
84193
|
return;
|
|
83909
84194
|
proactiveCompactedAt.set(live, usage2?.percentage ?? 0);
|
|
83910
|
-
console.warn(`[${
|
|
84195
|
+
console.warn(`[${LABEL3}] auto-compact: ${Math.round(usage2?.percentage ?? 0)}% of the window used \u2014 compacting`);
|
|
83911
84196
|
await sendMessage({ ...params, message: OVERFLOW_COMPACT_MESSAGE, sessionId: live, autoContinuation: true });
|
|
83912
84197
|
const now2 = sessionRekey.get(live) ?? live;
|
|
83913
84198
|
if (now2 !== live) {
|
|
@@ -83915,7 +84200,7 @@ ${text12}`);
|
|
|
83915
84200
|
proactiveCompactedAt.delete(live);
|
|
83916
84201
|
}
|
|
83917
84202
|
} catch (err2) {
|
|
83918
|
-
console.warn(`[${
|
|
84203
|
+
console.warn(`[${LABEL3}] auto-compact failed:`, err2 instanceof Error ? err2.message : String(err2));
|
|
83919
84204
|
}
|
|
83920
84205
|
}
|
|
83921
84206
|
async function sendMessage(params) {
|
|
@@ -84234,7 +84519,7 @@ ${detail}` : detail, !overflow);
|
|
|
84234
84519
|
}
|
|
84235
84520
|
}
|
|
84236
84521
|
const declared = declaredCaps;
|
|
84237
|
-
const
|
|
84522
|
+
const LABEL3 = engine.label;
|
|
84238
84523
|
let hostedBoot = null;
|
|
84239
84524
|
async function ensureHostedToolset() {
|
|
84240
84525
|
if (!declared.toolInjection || hostedEndpoint)
|
|
@@ -84266,7 +84551,7 @@ ${detail}` : detail, !overflow);
|
|
|
84266
84551
|
// own permission gate, and it cannot disturb the parent's turn state.
|
|
84267
84552
|
runSubagent: async (prompt2, { signal }) => {
|
|
84268
84553
|
if (!transport || !spawnedCwd)
|
|
84269
|
-
throw new Error(`${
|
|
84554
|
+
throw new Error(`${LABEL3} is not running.`);
|
|
84270
84555
|
const res = await transport.request("session/new", { cwd: spawnedCwd, mcpServers: [] });
|
|
84271
84556
|
const sub = res?.sessionId;
|
|
84272
84557
|
if (!sub)
|
|
@@ -84293,7 +84578,7 @@ ${detail}` : detail, !overflow);
|
|
|
84293
84578
|
hostTasks = ht.tasks;
|
|
84294
84579
|
refreshHostedTools = ht.refresh;
|
|
84295
84580
|
} catch (e) {
|
|
84296
|
-
console.warn(`[${
|
|
84581
|
+
console.warn(`[${LABEL3}] host toolset unavailable:`, e);
|
|
84297
84582
|
}
|
|
84298
84583
|
})();
|
|
84299
84584
|
await hostedBoot;
|
|
@@ -85108,7 +85393,7 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
|
|
|
85108
85393
|
const HOSTED_TOKEN_ENV = "TESSERACT_MCP_TOKEN";
|
|
85109
85394
|
const label = engineById(ENGINE_ID2)?.label ?? "Codex";
|
|
85110
85395
|
const declared = engineById(ENGINE_ID2)?.capabilities ?? {};
|
|
85111
|
-
const
|
|
85396
|
+
const LABEL3 = label;
|
|
85112
85397
|
const lastSendParams = /* @__PURE__ */ new Map();
|
|
85113
85398
|
let noticeDispatcher = null;
|
|
85114
85399
|
const jobNotices = () => {
|
|
@@ -85196,7 +85481,7 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
|
|
|
85196
85481
|
hostTasks = ht.tasks;
|
|
85197
85482
|
refreshHostedTools = ht.refresh;
|
|
85198
85483
|
} catch (e) {
|
|
85199
|
-
console.warn(`[${
|
|
85484
|
+
console.warn(`[${LABEL3}] host toolset unavailable:`, e);
|
|
85200
85485
|
}
|
|
85201
85486
|
})();
|
|
85202
85487
|
await hostedBoot;
|
|
@@ -85722,7 +86007,9 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
|
|
|
85722
86007
|
const usage2 = contextUsageFor(threadId);
|
|
85723
86008
|
const verdict = shouldCompactProactively({
|
|
85724
86009
|
mode: unattendedModeFor({ optedIn: params.unattended, origin: params.origin }),
|
|
85725
|
-
|
|
86010
|
+
// The conversation's own threshold when its client sent one (per-conversation there),
|
|
86011
|
+
// else the machine-wide setting.
|
|
86012
|
+
pct: params.autoCompactPct ?? readDaemonAgentSettings().autoCompactPct,
|
|
85726
86013
|
usagePct: typeof usage2?.percentage === "number" ? usage2.percentage : null,
|
|
85727
86014
|
lastCompactPct: proactiveCompactedAt.get(threadId) ?? null,
|
|
85728
86015
|
inFlight: false
|
|
@@ -85734,10 +86021,10 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
|
|
|
85734
86021
|
if (verdict !== "compact")
|
|
85735
86022
|
return;
|
|
85736
86023
|
proactiveCompactedAt.set(threadId, usage2?.percentage ?? 0);
|
|
85737
|
-
console.warn(`[${
|
|
86024
|
+
console.warn(`[${LABEL3}] auto-compact: ${Math.round(usage2?.percentage ?? 0)}% of the window used \u2014 compacting`);
|
|
85738
86025
|
await sendMessage({ ...params, message: OVERFLOW_COMPACT_MESSAGE, sessionId: threadId, autoContinuation: true });
|
|
85739
86026
|
} catch (err2) {
|
|
85740
|
-
console.warn(`[${
|
|
86027
|
+
console.warn(`[${LABEL3}] auto-compact failed:`, err2 instanceof Error ? err2.message : String(err2));
|
|
85741
86028
|
}
|
|
85742
86029
|
}
|
|
85743
86030
|
async function sendMessage(params) {
|
|
@@ -87196,8 +87483,8 @@ var pluginTtsProviders = [];
|
|
|
87196
87483
|
var loadedGeneration = [];
|
|
87197
87484
|
var loadQueue = Promise.resolve();
|
|
87198
87485
|
function loadPluginRuntime(opts) {
|
|
87199
|
-
const
|
|
87200
|
-
const next = loadQueue.then(
|
|
87486
|
+
const run8 = () => loadPluginRuntimeSerial(opts);
|
|
87487
|
+
const next = loadQueue.then(run8, run8);
|
|
87201
87488
|
loadQueue = next.catch(() => void 0);
|
|
87202
87489
|
return next;
|
|
87203
87490
|
}
|
|
@@ -87565,8 +87852,22 @@ import { randomUUID as randomUUID13 } from "node:crypto";
|
|
|
87565
87852
|
import { join as join34 } from "node:path";
|
|
87566
87853
|
|
|
87567
87854
|
// ../../packages/host-core/dist/gui/daemon-gui.js
|
|
87568
|
-
init_credentials();
|
|
87569
87855
|
import { join as join33, dirname as dirname14 } from "node:path";
|
|
87856
|
+
|
|
87857
|
+
// ../../packages/shared/dist/debug-mode.js
|
|
87858
|
+
init_base_paths();
|
|
87859
|
+
|
|
87860
|
+
// ../../packages/host-core/dist/service/types.js
|
|
87861
|
+
init_base_paths();
|
|
87862
|
+
var SERVICE_LABEL_BASE = "dev.tesseract.app.host";
|
|
87863
|
+
function instanceSuffix(instanceId) {
|
|
87864
|
+
if (instanceId)
|
|
87865
|
+
return instanceId;
|
|
87866
|
+
return homeTag();
|
|
87867
|
+
}
|
|
87868
|
+
|
|
87869
|
+
// ../../packages/host-core/dist/gui/daemon-gui.js
|
|
87870
|
+
init_credentials();
|
|
87570
87871
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
87571
87872
|
import { spawn as spawn5, spawnSync } from "node:child_process";
|
|
87572
87873
|
import { existsSync as existsSync14 } from "node:fs";
|
|
@@ -87614,13 +87915,16 @@ function createDockPolicy(fx) {
|
|
|
87614
87915
|
if (!armed)
|
|
87615
87916
|
return;
|
|
87616
87917
|
const want = count > 0 ? "regular" : "accessory";
|
|
87617
|
-
|
|
87918
|
+
const transition = want !== applied;
|
|
87919
|
+
if (want === "accessory" && !transition)
|
|
87618
87920
|
return;
|
|
87619
87921
|
safely("setActivationPolicy", () => fx.setActivationPolicy(want));
|
|
87620
87922
|
applied = want;
|
|
87621
|
-
|
|
87622
|
-
|
|
87623
|
-
|
|
87923
|
+
if (transition) {
|
|
87924
|
+
safely("log", () => fx.log?.(`dock policy \u2192 ${want} (${count} main window${count === 1 ? "" : "s"})`));
|
|
87925
|
+
if (want === "regular")
|
|
87926
|
+
safely("applyDockIcon", () => fx.applyDockIcon());
|
|
87927
|
+
}
|
|
87624
87928
|
};
|
|
87625
87929
|
return {
|
|
87626
87930
|
arm() {
|
|
@@ -89893,7 +90197,7 @@ var VoiceControl = class {
|
|
|
89893
90197
|
};
|
|
89894
90198
|
let llm = null;
|
|
89895
90199
|
try {
|
|
89896
|
-
const cfg2 = await buildClaudeNarrationLlm();
|
|
90200
|
+
const cfg2 = await buildClaudeNarrationLlm(daemonEngineEnv());
|
|
89897
90201
|
llm = cfg2?.complete ?? null;
|
|
89898
90202
|
} catch {
|
|
89899
90203
|
}
|
|
@@ -90100,17 +90404,17 @@ async function launchCompanionBrowser() {
|
|
|
90100
90404
|
if (!first) {
|
|
90101
90405
|
throw new Error('No browser on this machine has the Tesseract Companion extension installed, so there is nothing to drive. Install the Companion in Chrome (or another Chromium browser), or use target:"internal" to use the browser inside Tesseract.');
|
|
90102
90406
|
}
|
|
90103
|
-
const { execFile:
|
|
90104
|
-
const
|
|
90105
|
-
|
|
90407
|
+
const { execFile: execFile15 } = await import("node:child_process");
|
|
90408
|
+
const run8 = (cmd, args) => new Promise((resolve16, reject) => {
|
|
90409
|
+
execFile15(cmd, args, { timeout: 15e3 }, (err2) => err2 ? reject(err2) : resolve16());
|
|
90106
90410
|
});
|
|
90107
90411
|
try {
|
|
90108
90412
|
if (process.platform === "darwin")
|
|
90109
|
-
await
|
|
90413
|
+
await run8("open", ["-a", first.launch]);
|
|
90110
90414
|
else if (process.platform === "win32")
|
|
90111
|
-
await
|
|
90415
|
+
await run8("cmd", ["/c", "start", "", first.launch]);
|
|
90112
90416
|
else
|
|
90113
|
-
await
|
|
90417
|
+
await run8(first.launch, []);
|
|
90114
90418
|
} catch (err2) {
|
|
90115
90419
|
throw new Error(`Could not start ${first.name}: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
90116
90420
|
}
|
|
@@ -91370,10 +91674,10 @@ function buildEnhanceChain(spec) {
|
|
|
91370
91674
|
steps.push(`upscale\xD7${f}`);
|
|
91371
91675
|
resizes = true;
|
|
91372
91676
|
}
|
|
91373
|
-
const
|
|
91374
|
-
if (
|
|
91375
|
-
parts.push(`cas=strength=${SHARPEN[
|
|
91376
|
-
steps.push(`sharpen:${
|
|
91677
|
+
const sh3 = spec.sharpen ?? "light";
|
|
91678
|
+
if (sh3 !== "none") {
|
|
91679
|
+
parts.push(`cas=strength=${SHARPEN[sh3]}`);
|
|
91680
|
+
steps.push(`sharpen:${sh3}`);
|
|
91377
91681
|
}
|
|
91378
91682
|
if (spec.deband) {
|
|
91379
91683
|
parts.push("deband");
|
|
@@ -92304,11 +92608,11 @@ function pickProvider(c) {
|
|
|
92304
92608
|
return null;
|
|
92305
92609
|
}
|
|
92306
92610
|
function modelFor(id, pc, quality) {
|
|
92307
|
-
const
|
|
92611
|
+
const override3 = pc.model?.trim();
|
|
92308
92612
|
if (id === "tesseract")
|
|
92309
|
-
return
|
|
92310
|
-
if (
|
|
92311
|
-
return
|
|
92613
|
+
return override3 || FREE_MODEL;
|
|
92614
|
+
if (override3)
|
|
92615
|
+
return override3;
|
|
92312
92616
|
return quality === "standard" ? STANDARD_MODEL : FAST_MODEL;
|
|
92313
92617
|
}
|
|
92314
92618
|
function estimateFor(id, model, durationSec) {
|
|
@@ -93148,8 +93452,8 @@ async function falTopazEnhance(path6, spec, opts) {
|
|
|
93148
93452
|
const dir2 = opts.outDir ?? workDir();
|
|
93149
93453
|
mkdirSync21(dir2, { recursive: true });
|
|
93150
93454
|
const outPath = join42(dir2, "enhanced.mp4");
|
|
93151
|
-
const { writeFileSync:
|
|
93152
|
-
|
|
93455
|
+
const { writeFileSync: writeFileSync46 } = await import("node:fs");
|
|
93456
|
+
writeFileSync46(outPath, Buffer.from(await dl.arrayBuffer()));
|
|
93153
93457
|
const out = await probeMedia(outPath).catch(() => null);
|
|
93154
93458
|
opts.onProgress?.(100, "Enhance complete");
|
|
93155
93459
|
return { path: outPath, mime: MIME, width: out?.width ?? null, height: out?.height ?? null, durationSec: out?.durationSec ?? p.durationSec, summary: `fal Topaz ${spec.model ?? "Proteus"} \xD7${spec.upscaleFactor ?? 2}` };
|
|
@@ -94984,17 +95288,25 @@ function buildSharedBackend(engineId) {
|
|
|
94984
95288
|
return b;
|
|
94985
95289
|
backend = b;
|
|
94986
95290
|
refreshDaemonScheduling(b);
|
|
94987
|
-
|
|
95291
|
+
const runnerEnv = (() => {
|
|
95292
|
+
try {
|
|
95293
|
+
return daemonEngineEnv();
|
|
95294
|
+
} catch {
|
|
95295
|
+
return void 0;
|
|
95296
|
+
}
|
|
95297
|
+
})();
|
|
95298
|
+
b.setHostEnv?.(runnerEnv ?? null);
|
|
95299
|
+
void buildClaudeNarrationLlm(runnerEnv).then((cfg2) => {
|
|
94988
95300
|
if (cfg2) {
|
|
94989
95301
|
b.setNarrationLlm?.(cfg2);
|
|
94990
|
-
log(
|
|
95302
|
+
log(`narration: enabled (${runnerEnv?.ANTHROPIC_BASE_URL ?? "api.anthropic.com"})`);
|
|
94991
95303
|
} else
|
|
94992
95304
|
log("narration: disabled \u2014 no Claude creds resolved");
|
|
94993
95305
|
}).catch((e) => log("narration: setup failed:", e instanceof Error ? e.message : String(e)));
|
|
94994
|
-
void buildClaudeSmartLlm().then((fn) => {
|
|
95306
|
+
void buildClaudeSmartLlm(runnerEnv).then((fn) => {
|
|
94995
95307
|
if (fn) {
|
|
94996
95308
|
b.setVerifierLlm?.(fn);
|
|
94997
|
-
log(
|
|
95309
|
+
log(`reinforced-verification: grader enabled (${runnerEnv?.ANTHROPIC_BASE_URL ?? "api.anthropic.com"})`);
|
|
94998
95310
|
} else
|
|
94999
95311
|
log("reinforced-verification: disabled \u2014 no Claude creds resolved");
|
|
95000
95312
|
}).catch((e) => log("reinforced-verification: setup failed:", e instanceof Error ? e.message : String(e)));
|
|
@@ -98763,9 +99075,9 @@ var NodeFsHandler = class {
|
|
|
98763
99075
|
if (this.fsw.closed) {
|
|
98764
99076
|
return;
|
|
98765
99077
|
}
|
|
98766
|
-
const
|
|
99078
|
+
const dirname39 = sysPath.dirname(file2);
|
|
98767
99079
|
const basename14 = sysPath.basename(file2);
|
|
98768
|
-
const parent = this.fsw._getWatchedDir(
|
|
99080
|
+
const parent = this.fsw._getWatchedDir(dirname39);
|
|
98769
99081
|
let prevStats = stats;
|
|
98770
99082
|
if (parent.has(basename14))
|
|
98771
99083
|
return;
|
|
@@ -98792,7 +99104,7 @@ var NodeFsHandler = class {
|
|
|
98792
99104
|
prevStats = newStats2;
|
|
98793
99105
|
}
|
|
98794
99106
|
} catch (error51) {
|
|
98795
|
-
this.fsw._remove(
|
|
99107
|
+
this.fsw._remove(dirname39, basename14);
|
|
98796
99108
|
}
|
|
98797
99109
|
} else if (parent.has(basename14)) {
|
|
98798
99110
|
const at = newStats.atimeMs;
|
|
@@ -103235,8 +103547,8 @@ async function wakeDisplay(log9) {
|
|
|
103235
103547
|
if (process.platform !== "darwin")
|
|
103236
103548
|
return;
|
|
103237
103549
|
try {
|
|
103238
|
-
const { spawn:
|
|
103239
|
-
|
|
103550
|
+
const { spawn: spawn15 } = await import("node:child_process");
|
|
103551
|
+
spawn15("caffeinate", ["-u", "-t", "5"], { detached: true, stdio: "ignore" }).unref();
|
|
103240
103552
|
log9?.("display was asleep \u2014 declared user activity to wake it");
|
|
103241
103553
|
await new Promise((r) => setTimeout(r, 1200));
|
|
103242
103554
|
} catch {
|
|
@@ -104072,9 +104384,9 @@ function hasRdeskPassword() {
|
|
|
104072
104384
|
function verifyRdeskPassword(password) {
|
|
104073
104385
|
if (!password)
|
|
104074
104386
|
return false;
|
|
104075
|
-
const
|
|
104076
|
-
if (
|
|
104077
|
-
return password.length ===
|
|
104387
|
+
const override3 = process.env.CCB_RDESK_PASSWORD;
|
|
104388
|
+
if (override3)
|
|
104389
|
+
return password.length === override3.length && timingSafeEqual4(Buffer.from(password), Buffer.from(override3));
|
|
104078
104390
|
try {
|
|
104079
104391
|
const { salt, hash: hash2 } = JSON.parse(readFileSync40(pwFile(), "utf8"));
|
|
104080
104392
|
const got = scryptSync(password, Buffer.from(salt, "hex"), 32);
|
|
@@ -107499,6 +107811,16 @@ var LanDiscovery = class {
|
|
|
107499
107811
|
var _a3;
|
|
107500
107812
|
var requireCjs = createRequire4(import.meta.url);
|
|
107501
107813
|
function loadMeshCore() {
|
|
107814
|
+
for (const spec of [
|
|
107815
|
+
"@fineguide-tesseract/mesh-core",
|
|
107816
|
+
"./mesh-core/index.js",
|
|
107817
|
+
"../mesh-core/index.js"
|
|
107818
|
+
]) {
|
|
107819
|
+
try {
|
|
107820
|
+
return requireCjs(spec);
|
|
107821
|
+
} catch {
|
|
107822
|
+
}
|
|
107823
|
+
}
|
|
107502
107824
|
try {
|
|
107503
107825
|
return requireCjs("@fineguide-tesseract/mesh-core");
|
|
107504
107826
|
} catch (e) {
|
|
@@ -109411,12 +109733,12 @@ function watchForIdentity(deps) {
|
|
|
109411
109733
|
const wait = Math.min(max, Math.round(delay3 * (1 + (random() * 2 - 1) * JITTER)));
|
|
109412
109734
|
timer2 = setTimeout(() => {
|
|
109413
109735
|
timer2 = null;
|
|
109414
|
-
void
|
|
109736
|
+
void run8("backoff");
|
|
109415
109737
|
}, wait);
|
|
109416
109738
|
timer2.unref?.();
|
|
109417
109739
|
delay3 = Math.min(max, Math.round(delay3 * FACTOR));
|
|
109418
109740
|
};
|
|
109419
|
-
async function
|
|
109741
|
+
async function run8(reason) {
|
|
109420
109742
|
if (stopped2 || settled || inFlight2)
|
|
109421
109743
|
return;
|
|
109422
109744
|
inFlight2 = true;
|
|
@@ -109448,10 +109770,10 @@ function watchForIdentity(deps) {
|
|
|
109448
109770
|
return;
|
|
109449
109771
|
delay3 = first;
|
|
109450
109772
|
clear();
|
|
109451
|
-
void
|
|
109773
|
+
void run8(reason);
|
|
109452
109774
|
};
|
|
109453
109775
|
unsubscribe = (deps.subscribe ?? subscribeToWakeSignals)(nudge);
|
|
109454
|
-
void
|
|
109776
|
+
void run8("boot");
|
|
109455
109777
|
return {
|
|
109456
109778
|
ready,
|
|
109457
109779
|
nudge,
|
|
@@ -112050,9 +112372,8 @@ function meshIdOf(cert) {
|
|
|
112050
112372
|
// ../../packages/host-core/dist/mesh/full-tunnel.js
|
|
112051
112373
|
function fullTunnelState(i) {
|
|
112052
112374
|
const no2 = (reason) => ({ allowed: false, reason, warnings: [] });
|
|
112053
|
-
if (i.platform !== "linux") {
|
|
112054
|
-
|
|
112055
|
-
return no2(`Routing all traffic needs the network helper, which does not exist on ${name} yet.`);
|
|
112375
|
+
if (i.platform !== "linux" && i.platform !== "darwin" && i.platform !== "win32") {
|
|
112376
|
+
return no2(`Routing all traffic needs the network helper, which does not exist on ${i.platform} yet.`);
|
|
112056
112377
|
}
|
|
112057
112378
|
if (!i.engineAvailable) {
|
|
112058
112379
|
return no2("This build shipped without the network engine, so no traffic can be routed. That is a packaging fault \u2014 please report it.");
|
|
@@ -112105,21 +112426,685 @@ function bundleGrantsExitNode(bundle) {
|
|
|
112105
112426
|
// ../../packages/host-core/dist/mesh/machine-owner.js
|
|
112106
112427
|
init_credentials();
|
|
112107
112428
|
|
|
112108
|
-
// ../../packages/host-core/dist/service/
|
|
112109
|
-
import { execFile as
|
|
112429
|
+
// ../../packages/host-core/dist/net-service/ensure-installed.js
|
|
112430
|
+
import { execFile as execFile14 } from "node:child_process";
|
|
112431
|
+
import { existsSync as existsSync42 } from "node:fs";
|
|
112432
|
+
import { dirname as dirname34, join as join80 } from "node:path";
|
|
112433
|
+
import { promisify as promisify10 } from "node:util";
|
|
112434
|
+
|
|
112435
|
+
// ../../packages/host-core/dist/net-service/launchd-system.js
|
|
112436
|
+
import { spawn as spawn9 } from "node:child_process";
|
|
112437
|
+
import { existsSync as existsSync39, mkdtempSync as mkdtempSync2, writeFileSync as writeFileSync40, rmSync as rmSync10 } from "node:fs";
|
|
112438
|
+
import { tmpdir as tmpdir6 } from "node:os";
|
|
112439
|
+
import { join as join77 } from "node:path";
|
|
112440
|
+
|
|
112441
|
+
// ../../packages/host-core/dist/net-service/elevation.js
|
|
112442
|
+
import { execFile as execFile10 } from "node:child_process";
|
|
112110
112443
|
import { promisify as promisify6 } from "node:util";
|
|
112111
112444
|
var run4 = promisify6(execFile10);
|
|
112112
|
-
function
|
|
112445
|
+
async function alreadyElevated() {
|
|
112446
|
+
if (process.platform === "win32") {
|
|
112447
|
+
try {
|
|
112448
|
+
const { stdout } = await run4("powershell.exe", [
|
|
112449
|
+
"-NoProfile",
|
|
112450
|
+
"-Command",
|
|
112451
|
+
"(New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)"
|
|
112452
|
+
]);
|
|
112453
|
+
return String(stdout).trim().toLowerCase() === "true";
|
|
112454
|
+
} catch {
|
|
112455
|
+
return false;
|
|
112456
|
+
}
|
|
112457
|
+
}
|
|
112458
|
+
return typeof process.getuid === "function" && process.getuid() === 0;
|
|
112459
|
+
}
|
|
112460
|
+
|
|
112461
|
+
// ../../packages/host-core/dist/net-service/launchd-system.js
|
|
112462
|
+
var LABEL2 = "dev.tesseract.netd";
|
|
112463
|
+
var PLIST = `/Library/LaunchDaemons/${LABEL2}.plist`;
|
|
112464
|
+
function xml(s) {
|
|
112465
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
112466
|
+
}
|
|
112467
|
+
function sh(s) {
|
|
112468
|
+
return `'${s.replace(/'/g, `'\\''`)}'`;
|
|
112469
|
+
}
|
|
112470
|
+
function buildPlist(spec) {
|
|
112471
|
+
const argv = [
|
|
112472
|
+
spec.exec,
|
|
112473
|
+
"--state-dir",
|
|
112474
|
+
spec.stateDir,
|
|
112475
|
+
"--socket",
|
|
112476
|
+
spec.socket,
|
|
112477
|
+
"--owner-uid",
|
|
112478
|
+
String(spec.ownerUid)
|
|
112479
|
+
];
|
|
112480
|
+
const args = argv.map((a) => ` <string>${xml(a)}</string>`).join("\n");
|
|
112481
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
112482
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
112483
|
+
<plist version="1.0">
|
|
112484
|
+
<dict>
|
|
112485
|
+
<key>Label</key>
|
|
112486
|
+
<string>${LABEL2}</string>
|
|
112487
|
+
<key>ProgramArguments</key>
|
|
112488
|
+
<array>
|
|
112489
|
+
${args}
|
|
112490
|
+
</array>
|
|
112491
|
+
<key>RunAtLoad</key>
|
|
112492
|
+
<true/>
|
|
112493
|
+
<!-- on-failure only, exactly like systemd's Restart=on-failure: a helper that exits 0
|
|
112494
|
+
has been asked to stop, and restarting it would fight the operator. -->
|
|
112495
|
+
<key>KeepAlive</key>
|
|
112496
|
+
<dict>
|
|
112497
|
+
<key>SuccessfulExit</key>
|
|
112498
|
+
<false/>
|
|
112499
|
+
</dict>
|
|
112500
|
+
<!-- launchd has no equivalent of systemd's StartLimitBurst, so a PERMANENT failure \u2014
|
|
112501
|
+
netd refusing to start on an unreadable journal \u2014 respawns forever rather than
|
|
112502
|
+
landing in a failed state. 30s keeps that out of the log and off the CPU; the
|
|
112503
|
+
remedy is still 'net doctor', which reads the real table. -->
|
|
112504
|
+
<key>ThrottleInterval</key>
|
|
112505
|
+
<integer>30</integer>
|
|
112506
|
+
<key>ProcessType</key>
|
|
112507
|
+
<string>Interactive</string>
|
|
112508
|
+
<key>StandardErrorPath</key>
|
|
112509
|
+
<string>${xml(join77(spec.stateDir, "netd.log"))}</string>
|
|
112510
|
+
<key>StandardOutPath</key>
|
|
112511
|
+
<string>${xml(join77(spec.stateDir, "netd.log"))}</string>
|
|
112512
|
+
</dict>
|
|
112513
|
+
</plist>
|
|
112514
|
+
`;
|
|
112515
|
+
}
|
|
112516
|
+
function runForCode(cmd, args) {
|
|
112113
112517
|
return new Promise((resolve16) => {
|
|
112114
112518
|
const p = spawn9(cmd, args, { stdio: "inherit" });
|
|
112519
|
+
p.on("error", () => resolve16(127));
|
|
112520
|
+
p.on("close", (code) => resolve16(code ?? 1));
|
|
112521
|
+
});
|
|
112522
|
+
}
|
|
112523
|
+
async function elevate(script) {
|
|
112524
|
+
const dir2 = mkdtempSync2(join77(tmpdir6(), "tesseract-netd-"));
|
|
112525
|
+
const path6 = join77(dir2, "install.sh");
|
|
112526
|
+
try {
|
|
112527
|
+
writeFileSync40(path6, script, { mode: 384 });
|
|
112528
|
+
if (await alreadyElevated()) {
|
|
112529
|
+
return { code: await runForCode("/bin/sh", [path6]), declined: false };
|
|
112530
|
+
}
|
|
112531
|
+
const code = await runForCode("osascript", [
|
|
112532
|
+
"-e",
|
|
112533
|
+
`do shell script "/bin/sh " & quoted form of "${path6}" with administrator privileges`
|
|
112534
|
+
]);
|
|
112535
|
+
return { code, declined: code === 1 };
|
|
112536
|
+
} finally {
|
|
112537
|
+
try {
|
|
112538
|
+
rmSync10(dir2, { recursive: true, force: true });
|
|
112539
|
+
} catch {
|
|
112540
|
+
}
|
|
112541
|
+
}
|
|
112542
|
+
}
|
|
112543
|
+
function makeLaunchDaemon() {
|
|
112544
|
+
return {
|
|
112545
|
+
supported: process.platform === "darwin",
|
|
112546
|
+
async install(spec) {
|
|
112547
|
+
const plist = buildPlist(spec);
|
|
112548
|
+
const script = [
|
|
112549
|
+
"set -e",
|
|
112550
|
+
`/usr/bin/install -d -m 0700 -o root -g wheel ${sh(spec.stateDir)}`,
|
|
112551
|
+
`cat > ${sh(PLIST)} <<'TESSERACT_PLIST_EOF'
|
|
112552
|
+
${plist}TESSERACT_PLIST_EOF`,
|
|
112553
|
+
// launchd REFUSES to load a plist that is group- or world-writable, and says so in
|
|
112554
|
+
// a way that reads as a permissions problem with the binary rather than the file.
|
|
112555
|
+
`chown root:wheel ${sh(PLIST)}`,
|
|
112556
|
+
`chmod 644 ${sh(PLIST)}`,
|
|
112557
|
+
// bootout first so a reinstall replaces a loaded job rather than failing with
|
|
112558
|
+
// "service already loaded". `|| true` because not-loaded is the ordinary case.
|
|
112559
|
+
`/bin/launchctl bootout system/${LABEL2} 2>/dev/null || true`,
|
|
112560
|
+
`/bin/launchctl bootstrap system ${sh(PLIST)}`,
|
|
112561
|
+
`/bin/launchctl enable system/${LABEL2}`
|
|
112562
|
+
].join("\n");
|
|
112563
|
+
const { code, declined } = await elevate(`${script}
|
|
112564
|
+
`);
|
|
112565
|
+
if (code !== 0) {
|
|
112566
|
+
return {
|
|
112567
|
+
ok: false,
|
|
112568
|
+
detail: declined ? "the elevation prompt was declined" : `installing the helper failed (exit ${code})`
|
|
112569
|
+
};
|
|
112570
|
+
}
|
|
112571
|
+
return { ok: true };
|
|
112572
|
+
},
|
|
112573
|
+
async uninstall() {
|
|
112574
|
+
const script = [
|
|
112575
|
+
`/bin/launchctl bootout system/${LABEL2} 2>/dev/null || true`,
|
|
112576
|
+
`rm -f ${sh(PLIST)}`
|
|
112577
|
+
].join("\n");
|
|
112578
|
+
const { code, declined } = await elevate(`${script}
|
|
112579
|
+
`);
|
|
112580
|
+
return code === 0 ? { ok: true } : {
|
|
112581
|
+
ok: false,
|
|
112582
|
+
detail: declined ? "the elevation prompt was declined" : `removing the helper failed (exit ${code})`
|
|
112583
|
+
};
|
|
112584
|
+
},
|
|
112585
|
+
async state() {
|
|
112586
|
+
if (!existsSync39(PLIST))
|
|
112587
|
+
return { installed: false, running: false };
|
|
112588
|
+
const running2 = await netdAvailable();
|
|
112589
|
+
return {
|
|
112590
|
+
installed: true,
|
|
112591
|
+
running: running2,
|
|
112592
|
+
...running2 ? {} : {
|
|
112593
|
+
detail: `the helper is installed but not answering \u2014 check ${LABEL2} in Console, or reinstall it`
|
|
112594
|
+
}
|
|
112595
|
+
};
|
|
112596
|
+
},
|
|
112597
|
+
async openApprovalSettings() {
|
|
112598
|
+
}
|
|
112599
|
+
};
|
|
112600
|
+
}
|
|
112601
|
+
|
|
112602
|
+
// ../../packages/host-core/dist/net-service/systemd-system.js
|
|
112603
|
+
import { spawn as spawn11 } from "node:child_process";
|
|
112604
|
+
import { existsSync as existsSync40 } from "node:fs";
|
|
112605
|
+
|
|
112606
|
+
// ../../packages/host-core/dist/service/exec.js
|
|
112607
|
+
import { execFile as execFile11, spawn as spawn10 } from "node:child_process";
|
|
112608
|
+
import { promisify as promisify7 } from "node:util";
|
|
112609
|
+
var run5 = promisify7(execFile11);
|
|
112610
|
+
function runInherit(cmd, args) {
|
|
112611
|
+
return new Promise((resolve16) => {
|
|
112612
|
+
const p = spawn10(cmd, args, { stdio: "inherit" });
|
|
112115
112613
|
p.on("error", () => resolve16());
|
|
112116
112614
|
p.on("close", () => resolve16());
|
|
112117
112615
|
});
|
|
112118
112616
|
}
|
|
112119
112617
|
|
|
112120
112618
|
// ../../packages/host-core/dist/net-service/systemd-system.js
|
|
112619
|
+
function runForCode2(cmd, args) {
|
|
112620
|
+
return new Promise((resolve16) => {
|
|
112621
|
+
const p = spawn11(cmd, args, { stdio: "inherit" });
|
|
112622
|
+
p.on("error", () => resolve16(127));
|
|
112623
|
+
p.on("close", (code) => resolve16(code ?? 1));
|
|
112624
|
+
});
|
|
112625
|
+
}
|
|
112626
|
+
async function tryRun(cmd, args) {
|
|
112627
|
+
try {
|
|
112628
|
+
const { stdout } = await run5(cmd, args);
|
|
112629
|
+
return { stdout: String(stdout), code: 0 };
|
|
112630
|
+
} catch (e) {
|
|
112631
|
+
const err2 = e;
|
|
112632
|
+
return { stdout: String(err2.stdout ?? ""), code: typeof err2.code === "number" ? err2.code : 1 };
|
|
112633
|
+
}
|
|
112634
|
+
}
|
|
112635
|
+
async function elevated(script) {
|
|
112636
|
+
return await alreadyElevated() ? runForCode2("sh", ["-c", script]) : runForCode2("pkexec", ["sh", "-c", script]);
|
|
112637
|
+
}
|
|
112121
112638
|
var UNIT = "tesseract-netd.service";
|
|
112122
112639
|
var UNIT_PATH = `/etc/systemd/system/${UNIT}`;
|
|
112640
|
+
function unitVal(v) {
|
|
112641
|
+
return v.replace(/%/g, "%%");
|
|
112642
|
+
}
|
|
112643
|
+
function buildUnit(spec) {
|
|
112644
|
+
const exec2 = [
|
|
112645
|
+
spec.exec,
|
|
112646
|
+
"--state-dir",
|
|
112647
|
+
spec.stateDir,
|
|
112648
|
+
"--socket",
|
|
112649
|
+
spec.socket,
|
|
112650
|
+
"--owner-uid",
|
|
112651
|
+
String(spec.ownerUid)
|
|
112652
|
+
].map(unitVal).join(" ");
|
|
112653
|
+
return `[Unit]
|
|
112654
|
+
Description=Tesseract network helper (mesh routes and tunnel device)
|
|
112655
|
+
Documentation=https://tesseract.dev/docs/mesh
|
|
112656
|
+
After=network-online.target
|
|
112657
|
+
Wants=network-online.target
|
|
112658
|
+
# A START LIMIT, because some failures are PERMANENT and restarting cannot fix them. An
|
|
112659
|
+
# unreadable journal is the one that proved it: netd refuses to start while routes may be
|
|
112660
|
+
# installed that it cannot identify, and without this the unit loops forever \u2014 measured at
|
|
112661
|
+
# 7 attempts in 30s on a real box, filling the log and never reaching a state an operator
|
|
112662
|
+
# can see as "stopped, needs attention". After 5 failures in 60s systemd gives up and marks
|
|
112663
|
+
# it failed, which is what state() reports.
|
|
112664
|
+
#
|
|
112665
|
+
# These belong in [Unit]: they are documented in systemd.unit(5), not systemd.service(5),
|
|
112666
|
+
# and systemd silently IGNORES them in the [Service] section \u2014 which is where I first put
|
|
112667
|
+
# them.
|
|
112668
|
+
StartLimitIntervalSec=60
|
|
112669
|
+
StartLimitBurst=5
|
|
112670
|
+
|
|
112671
|
+
[Service]
|
|
112672
|
+
# notify, so 'systemctl start' does not return before the socket exists \u2014 otherwise the
|
|
112673
|
+
# app connects to a service systemd calls started and gets ENOENT.
|
|
112674
|
+
Type=notify
|
|
112675
|
+
NotifyAccess=main
|
|
112676
|
+
ExecStart=${exec2}
|
|
112677
|
+
# Exactly what programming routes and opening a tun device need. NOT setcap: that grants
|
|
112678
|
+
# the capability to the FILE, so anything executing it inherits the grant, and it is
|
|
112679
|
+
# silently ignored on AppImage's nosuid FUSE mount \u2014 the only auto-updating Linux target.
|
|
112680
|
+
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_RAW
|
|
112681
|
+
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_RAW
|
|
112682
|
+
NoNewPrivileges=yes
|
|
112683
|
+
# This process is reachable over a socket by anything on the machine. Everything below
|
|
112684
|
+
# bounds what a bug in it could reach.
|
|
112685
|
+
ProtectSystem=strict
|
|
112686
|
+
ProtectHome=yes
|
|
112687
|
+
PrivateTmp=yes
|
|
112688
|
+
ProtectKernelModules=yes
|
|
112689
|
+
ProtectKernelLogs=yes
|
|
112690
|
+
ProtectControlGroups=yes
|
|
112691
|
+
RestrictSUIDSGID=yes
|
|
112692
|
+
RestrictNamespaces=yes
|
|
112693
|
+
LockPersonality=yes
|
|
112694
|
+
MemoryDenyWriteExecute=yes
|
|
112695
|
+
SystemCallArchitectures=native
|
|
112696
|
+
# The journal directory is the ONLY thing it may write.
|
|
112697
|
+
ReadWritePaths=${unitVal(spec.stateDir)}
|
|
112698
|
+
DeviceAllow=/dev/net/tun rw
|
|
112699
|
+
# on-failure, never always: a helper that exits 0 has been asked to stop, and restarting
|
|
112700
|
+
# it would fight the operator.
|
|
112701
|
+
Restart=on-failure
|
|
112702
|
+
RestartSec=5
|
|
112703
|
+
|
|
112704
|
+
[Install]
|
|
112705
|
+
WantedBy=multi-user.target
|
|
112706
|
+
`;
|
|
112707
|
+
}
|
|
112708
|
+
function makeSystemdSystem() {
|
|
112709
|
+
return {
|
|
112710
|
+
supported: process.platform === "linux",
|
|
112711
|
+
async install(spec) {
|
|
112712
|
+
const unit = buildUnit(spec);
|
|
112713
|
+
const script = [
|
|
112714
|
+
`install -d -m 0700 ${sh2(spec.stateDir)}`,
|
|
112715
|
+
`cat > ${sh2(UNIT_PATH)} <<'TESSERACT_UNIT_EOF'
|
|
112716
|
+
${unit}TESSERACT_UNIT_EOF`,
|
|
112717
|
+
"systemctl daemon-reload",
|
|
112718
|
+
`systemctl enable --now ${UNIT}`
|
|
112719
|
+
].join("\n");
|
|
112720
|
+
const code = await elevated(script);
|
|
112721
|
+
if (code !== 0) {
|
|
112722
|
+
const declined = code === 126 || code === 127;
|
|
112723
|
+
return {
|
|
112724
|
+
ok: false,
|
|
112725
|
+
detail: declined ? "the elevation prompt was declined" : `installing the helper failed (exit ${code})`
|
|
112726
|
+
};
|
|
112727
|
+
}
|
|
112728
|
+
return { ok: true };
|
|
112729
|
+
},
|
|
112730
|
+
async uninstall() {
|
|
112731
|
+
const script = [
|
|
112732
|
+
`systemctl disable --now ${UNIT} || true`,
|
|
112733
|
+
`rm -f ${sh2(UNIT_PATH)}`,
|
|
112734
|
+
"systemctl daemon-reload"
|
|
112735
|
+
].join("\n");
|
|
112736
|
+
const code = await elevated(script);
|
|
112737
|
+
return code === 0 ? { ok: true } : { ok: false, detail: `removing the helper failed (exit ${code})` };
|
|
112738
|
+
},
|
|
112739
|
+
async state() {
|
|
112740
|
+
if (!existsSync40(UNIT_PATH))
|
|
112741
|
+
return { installed: false, running: false };
|
|
112742
|
+
const active = await tryRun("systemctl", ["is-active", UNIT]);
|
|
112743
|
+
const running2 = active.stdout.trim() === "active";
|
|
112744
|
+
if (running2)
|
|
112745
|
+
return { installed: true, running: true };
|
|
112746
|
+
const show = await tryRun("systemctl", ["show", UNIT, "--property=Result", "--value"]);
|
|
112747
|
+
const result = show.stdout.trim();
|
|
112748
|
+
return {
|
|
112749
|
+
installed: true,
|
|
112750
|
+
running: false,
|
|
112751
|
+
...result && result !== "success" ? { detail: `the helper failed: ${result}` } : {}
|
|
112752
|
+
};
|
|
112753
|
+
},
|
|
112754
|
+
async openApprovalSettings() {
|
|
112755
|
+
}
|
|
112756
|
+
};
|
|
112757
|
+
}
|
|
112758
|
+
function sh2(s) {
|
|
112759
|
+
return `'${s.replace(/'/g, `'\\''`)}'`;
|
|
112760
|
+
}
|
|
112761
|
+
|
|
112762
|
+
// ../../packages/host-core/dist/net-service/windows-service.js
|
|
112763
|
+
import { execFile as execFile12, spawn as spawn12 } from "node:child_process";
|
|
112764
|
+
import { mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync41, rmSync as rmSync11 } from "node:fs";
|
|
112765
|
+
import { tmpdir as tmpdir7 } from "node:os";
|
|
112766
|
+
import { join as join78 } from "node:path";
|
|
112767
|
+
import { promisify as promisify8 } from "node:util";
|
|
112768
|
+
var run6 = promisify8(execFile12);
|
|
112769
|
+
var SERVICE = "TesseractNetd";
|
|
112770
|
+
var DISPLAY = "Tesseract network helper";
|
|
112771
|
+
var ERROR_CANCELLED = 1223;
|
|
112772
|
+
function ps(s) {
|
|
112773
|
+
return `'${s.replace(/'/g, "''")}'`;
|
|
112774
|
+
}
|
|
112775
|
+
function buildBinaryPath(spec) {
|
|
112776
|
+
const parts = [
|
|
112777
|
+
spec.exec,
|
|
112778
|
+
// NOT optional, and its absence is silent. The SCM launches the process and waits for it
|
|
112779
|
+
// to call `StartServiceCtrlDispatcher`; without this flag netd runs its console path
|
|
112780
|
+
// instead, never reports a status, and the SCM gives up — leaving a service that is
|
|
112781
|
+
// registered, visible in services.msc, refuses to start, and reports exit code 0. That
|
|
112782
|
+
// exact state was reproduced on the Windows build machine before the flag existed.
|
|
112783
|
+
"--service",
|
|
112784
|
+
"--state-dir",
|
|
112785
|
+
spec.stateDir,
|
|
112786
|
+
"--socket",
|
|
112787
|
+
spec.socket
|
|
112788
|
+
];
|
|
112789
|
+
if (spec.ownerSid)
|
|
112790
|
+
parts.push("--owner-sid", spec.ownerSid);
|
|
112791
|
+
return parts.map((p) => `"${p}"`).join(" ");
|
|
112792
|
+
}
|
|
112793
|
+
async function elevatePowerShell(script) {
|
|
112794
|
+
const dir2 = mkdtempSync3(join78(tmpdir7(), "tesseract-netd-"));
|
|
112795
|
+
const inner = join78(dir2, "install.ps1");
|
|
112796
|
+
writeFileSync41(inner, script, { encoding: "utf8" });
|
|
112797
|
+
if (await alreadyElevated()) {
|
|
112798
|
+
return new Promise((resolve16) => {
|
|
112799
|
+
const p = spawn12("powershell.exe", ["-NoProfile", "-ExecutionPolicy", "Bypass", "-File", inner], { stdio: "inherit" });
|
|
112800
|
+
const finish = (code) => {
|
|
112801
|
+
try {
|
|
112802
|
+
rmSync11(dir2, { recursive: true, force: true });
|
|
112803
|
+
} catch {
|
|
112804
|
+
}
|
|
112805
|
+
resolve16({ code, declined: false });
|
|
112806
|
+
};
|
|
112807
|
+
p.on("error", () => finish(127));
|
|
112808
|
+
p.on("close", (code) => finish(code ?? 1));
|
|
112809
|
+
});
|
|
112810
|
+
}
|
|
112811
|
+
const outer = join78(dir2, "elevate.ps1");
|
|
112812
|
+
writeFileSync41(outer, [
|
|
112813
|
+
'$ErrorActionPreference = "Stop"',
|
|
112814
|
+
"try {",
|
|
112815
|
+
` $p = Start-Process -FilePath "powershell.exe" -ArgumentList @("-NoProfile","-ExecutionPolicy","Bypass","-File",${ps(inner)}) -Verb RunAs -Wait -PassThru`,
|
|
112816
|
+
" exit $p.ExitCode",
|
|
112817
|
+
"} catch {",
|
|
112818
|
+
` exit ${ERROR_CANCELLED}`,
|
|
112819
|
+
"}"
|
|
112820
|
+
].join("\n"), { encoding: "utf8" });
|
|
112821
|
+
return new Promise((resolve16) => {
|
|
112822
|
+
const p = spawn12("powershell.exe", ["-NoProfile", "-ExecutionPolicy", "Bypass", "-File", outer], { stdio: "inherit" });
|
|
112823
|
+
const finish = (code) => {
|
|
112824
|
+
try {
|
|
112825
|
+
rmSync11(dir2, { recursive: true, force: true });
|
|
112826
|
+
} catch {
|
|
112827
|
+
}
|
|
112828
|
+
resolve16({ code, declined: code === ERROR_CANCELLED });
|
|
112829
|
+
};
|
|
112830
|
+
p.on("error", () => finish(127));
|
|
112831
|
+
p.on("close", (code) => finish(code ?? 1));
|
|
112832
|
+
});
|
|
112833
|
+
}
|
|
112834
|
+
function buildInstallScript(spec) {
|
|
112835
|
+
const bin = buildBinaryPath(spec);
|
|
112836
|
+
return [
|
|
112837
|
+
'$ErrorActionPreference = "Stop"',
|
|
112838
|
+
`New-Item -ItemType Directory -Force -Path ${ps(spec.stateDir)} | Out-Null`,
|
|
112839
|
+
// A reinstall must replace, not fail. Stop first: New-Service refuses a name that
|
|
112840
|
+
// exists, and sc.exe delete on a running service only marks it for deletion.
|
|
112841
|
+
`$existing = Get-Service -Name ${ps(SERVICE)} -ErrorAction SilentlyContinue`,
|
|
112842
|
+
"if ($existing) {",
|
|
112843
|
+
` Stop-Service -Name ${ps(SERVICE)} -Force -ErrorAction SilentlyContinue`,
|
|
112844
|
+
` & sc.exe delete ${SERVICE} | Out-Null`,
|
|
112845
|
+
" Start-Sleep -Milliseconds 500",
|
|
112846
|
+
"}",
|
|
112847
|
+
`New-Service -Name ${ps(SERVICE)} -BinaryPathName ${ps(bin)} -DisplayName ${ps(DISPLAY)} -Description ${ps("Programs the routes for Tesseract private networks and owns the tunnel device.")} -StartupType Automatic | Out-Null`,
|
|
112848
|
+
// Restart on failure, three times, then stop trying. The Windows equivalent of
|
|
112849
|
+
// systemd's Restart=on-failure with a start limit — netd refuses to start while an
|
|
112850
|
+
// unreadable journal may mean routes are installed, and that is a PERMANENT failure
|
|
112851
|
+
// no amount of restarting fixes.
|
|
112852
|
+
`& sc.exe failure ${SERVICE} reset= 86400 actions= restart/5000/restart/5000/restart/5000 | Out-Null`,
|
|
112853
|
+
`Start-Service -Name ${ps(SERVICE)}`,
|
|
112854
|
+
"exit 0"
|
|
112855
|
+
].join("\n");
|
|
112856
|
+
}
|
|
112857
|
+
function buildUninstallScript() {
|
|
112858
|
+
return [
|
|
112859
|
+
`Stop-Service -Name ${ps(SERVICE)} -Force -ErrorAction SilentlyContinue`,
|
|
112860
|
+
`& sc.exe delete ${SERVICE} | Out-Null`,
|
|
112861
|
+
"exit 0"
|
|
112862
|
+
].join("\n");
|
|
112863
|
+
}
|
|
112864
|
+
function makeWindowsService() {
|
|
112865
|
+
return {
|
|
112866
|
+
supported: process.platform === "win32",
|
|
112867
|
+
async install(spec) {
|
|
112868
|
+
const { code, declined } = await elevatePowerShell(`${buildInstallScript(spec)}
|
|
112869
|
+
`);
|
|
112870
|
+
if (code !== 0) {
|
|
112871
|
+
return {
|
|
112872
|
+
ok: false,
|
|
112873
|
+
detail: declined ? "the elevation prompt was declined" : `installing the helper failed (exit ${code})`
|
|
112874
|
+
};
|
|
112875
|
+
}
|
|
112876
|
+
return { ok: true };
|
|
112877
|
+
},
|
|
112878
|
+
async uninstall() {
|
|
112879
|
+
const { code, declined } = await elevatePowerShell(`${buildUninstallScript()}
|
|
112880
|
+
`);
|
|
112881
|
+
return code === 0 ? { ok: true } : {
|
|
112882
|
+
ok: false,
|
|
112883
|
+
detail: declined ? "the elevation prompt was declined" : `removing the helper failed (exit ${code})`
|
|
112884
|
+
};
|
|
112885
|
+
},
|
|
112886
|
+
async state() {
|
|
112887
|
+
try {
|
|
112888
|
+
const { stdout } = await run6("sc.exe", ["query", SERVICE]);
|
|
112889
|
+
const out = String(stdout);
|
|
112890
|
+
const running2 = /STATE\s*:\s*4\b/.test(out);
|
|
112891
|
+
if (running2)
|
|
112892
|
+
return { installed: true, running: true };
|
|
112893
|
+
return {
|
|
112894
|
+
installed: true,
|
|
112895
|
+
running: false,
|
|
112896
|
+
detail: "the helper is installed but not running \u2014 reinstall it, or start the Tesseract network helper service"
|
|
112897
|
+
};
|
|
112898
|
+
} catch {
|
|
112899
|
+
return { installed: false, running: false };
|
|
112900
|
+
}
|
|
112901
|
+
},
|
|
112902
|
+
async openApprovalSettings() {
|
|
112903
|
+
}
|
|
112904
|
+
};
|
|
112905
|
+
}
|
|
112906
|
+
|
|
112907
|
+
// ../../packages/host-core/dist/net-service/windows-nat.js
|
|
112908
|
+
import { execFile as execFile13 } from "node:child_process";
|
|
112909
|
+
import { promisify as promisify9 } from "node:util";
|
|
112910
|
+
var run7 = promisify9(execFile13);
|
|
112911
|
+
var NAT_FEATURE = "Containers-HNS";
|
|
112912
|
+
async function natCapability() {
|
|
112913
|
+
if (process.platform !== "win32") {
|
|
112914
|
+
return { available: true, reason: "", needsRestart: false };
|
|
112915
|
+
}
|
|
112916
|
+
try {
|
|
112917
|
+
const { stdout } = await run7("powershell.exe", [
|
|
112918
|
+
"-NoProfile",
|
|
112919
|
+
"-NonInteractive",
|
|
112920
|
+
"-Command",
|
|
112921
|
+
"if (Get-CimClass -Namespace root/StandardCimv2 -ClassName MSFT_NetNat -ErrorAction SilentlyContinue) { 'yes' } else { 'no' }"
|
|
112922
|
+
]);
|
|
112923
|
+
if (String(stdout).trim() === "yes") {
|
|
112924
|
+
return { available: true, reason: "", needsRestart: false };
|
|
112925
|
+
}
|
|
112926
|
+
} catch {
|
|
112927
|
+
}
|
|
112928
|
+
return {
|
|
112929
|
+
available: false,
|
|
112930
|
+
reason: "Windows needs one more component before this machine can be the way out for others. It is an optional Windows feature, and turning it on needs a restart. Nothing else about the private network needs it \u2014 this machine can already join, and route all of its own traffic through someone else.",
|
|
112931
|
+
needsRestart: true
|
|
112932
|
+
};
|
|
112933
|
+
}
|
|
112934
|
+
function buildEnableNatScript() {
|
|
112935
|
+
return [
|
|
112936
|
+
'$ErrorActionPreference = "Stop"',
|
|
112937
|
+
// -NoRestart, ALWAYS. We report that a restart is needed; we never perform one. An
|
|
112938
|
+
// application that reboots a machine is one nobody leaves running.
|
|
112939
|
+
`$r = Enable-WindowsOptionalFeature -Online -FeatureName ${NAT_FEATURE} -All -NoRestart`,
|
|
112940
|
+
// 3010 is ERROR_SUCCESS_REBOOT_REQUIRED and is a SUCCESS. Treating it as a failure
|
|
112941
|
+
// would tell the user their install failed on the machine where it worked.
|
|
112942
|
+
"if ($r.RestartNeeded) { exit 3010 }",
|
|
112943
|
+
"exit 0"
|
|
112944
|
+
].join("\n");
|
|
112945
|
+
}
|
|
112946
|
+
async function enableNatProvider() {
|
|
112947
|
+
if (process.platform !== "win32") {
|
|
112948
|
+
return { ok: false, reason: "unsupported", detail: "this is a Windows-only component" };
|
|
112949
|
+
}
|
|
112950
|
+
const { code, declined } = await elevatePowerShell(`${buildEnableNatScript()}
|
|
112951
|
+
`);
|
|
112952
|
+
if (code === 0)
|
|
112953
|
+
return { ok: true, restartRequired: false };
|
|
112954
|
+
if (code === 3010)
|
|
112955
|
+
return { ok: true, restartRequired: true };
|
|
112956
|
+
return {
|
|
112957
|
+
ok: false,
|
|
112958
|
+
reason: declined ? "declined" : "failed",
|
|
112959
|
+
detail: declined ? "the elevation prompt was declined" : `enabling the Windows NAT component failed (exit ${code})`
|
|
112960
|
+
};
|
|
112961
|
+
}
|
|
112962
|
+
|
|
112963
|
+
// ../../packages/host-core/dist/net-service/index.js
|
|
112964
|
+
function inert(reason) {
|
|
112965
|
+
return {
|
|
112966
|
+
supported: false,
|
|
112967
|
+
async install() {
|
|
112968
|
+
return { ok: false, detail: reason };
|
|
112969
|
+
},
|
|
112970
|
+
async uninstall() {
|
|
112971
|
+
return { ok: false, detail: reason };
|
|
112972
|
+
},
|
|
112973
|
+
async state() {
|
|
112974
|
+
return { installed: false, running: false, detail: reason };
|
|
112975
|
+
},
|
|
112976
|
+
async openApprovalSettings() {
|
|
112977
|
+
}
|
|
112978
|
+
};
|
|
112979
|
+
}
|
|
112980
|
+
function makeNetService() {
|
|
112981
|
+
switch (process.platform) {
|
|
112982
|
+
case "linux":
|
|
112983
|
+
return makeSystemdSystem();
|
|
112984
|
+
// A root LaunchDaemon, not a System Extension. The extension is still the right end
|
|
112985
|
+
// state — it brings split DNS, On-Demand and an OS kill switch — but it is an Xcode
|
|
112986
|
+
// project, a second signing identity and a user approval, and none of that is needed to
|
|
112987
|
+
// open a utun and program routes. See `launchd-system.ts`.
|
|
112988
|
+
case "darwin":
|
|
112989
|
+
return makeLaunchDaemon();
|
|
112990
|
+
// A LocalSystem service, separate from the daemon's per-user Scheduled Task, which stays
|
|
112991
|
+
// unprivileged. See `windows-service.ts`.
|
|
112992
|
+
case "win32":
|
|
112993
|
+
return makeWindowsService();
|
|
112994
|
+
default:
|
|
112995
|
+
return inert(`no network helper for ${process.platform}`);
|
|
112996
|
+
}
|
|
112997
|
+
}
|
|
112998
|
+
|
|
112999
|
+
// ../../packages/host-core/dist/net-service/netd-binary.js
|
|
113000
|
+
import { existsSync as existsSync41 } from "node:fs";
|
|
113001
|
+
import { dirname as dirname33, join as join79 } from "node:path";
|
|
113002
|
+
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
113003
|
+
function netdBinaryName() {
|
|
113004
|
+
return process.platform === "win32" ? "tesseract-netd.exe" : "tesseract-netd";
|
|
113005
|
+
}
|
|
113006
|
+
function override2() {
|
|
113007
|
+
const p = process.env.CCB_NETD_BIN;
|
|
113008
|
+
return p && existsSync41(p) ? p : null;
|
|
113009
|
+
}
|
|
113010
|
+
function netdBinaryPath() {
|
|
113011
|
+
const fromEnv = override2();
|
|
113012
|
+
if (fromEnv)
|
|
113013
|
+
return fromEnv;
|
|
113014
|
+
const name = netdBinaryName();
|
|
113015
|
+
const candidates = [];
|
|
113016
|
+
const resources = process.resourcesPath;
|
|
113017
|
+
if (resources)
|
|
113018
|
+
candidates.push(join79(resources, "netd", name));
|
|
113019
|
+
try {
|
|
113020
|
+
const here = dirname33(fileURLToPath7(import.meta.url));
|
|
113021
|
+
candidates.push(join79(here, "..", "..", "netd", name));
|
|
113022
|
+
candidates.push(join79(here, "..", "..", "..", "netd", name));
|
|
113023
|
+
const triple = `${process.platform}-${process.arch}`;
|
|
113024
|
+
for (const root of [here, join79(here, ".."), join79(here, "..", "..")]) {
|
|
113025
|
+
candidates.push(join79(root, "mesh-core", "prebuilds", triple, "netd", name));
|
|
113026
|
+
}
|
|
113027
|
+
} catch {
|
|
113028
|
+
}
|
|
113029
|
+
if (process.env.CCB_REPO_ROOT) {
|
|
113030
|
+
candidates.push(join79(process.env.CCB_REPO_ROOT, "crates", "target", "release", name));
|
|
113031
|
+
}
|
|
113032
|
+
candidates.push(join79(process.cwd(), "crates", "target", "release", name));
|
|
113033
|
+
for (const c of candidates) {
|
|
113034
|
+
try {
|
|
113035
|
+
if (existsSync41(c))
|
|
113036
|
+
return c;
|
|
113037
|
+
} catch {
|
|
113038
|
+
}
|
|
113039
|
+
}
|
|
113040
|
+
return null;
|
|
113041
|
+
}
|
|
113042
|
+
|
|
113043
|
+
// ../../packages/host-core/dist/net-service/ensure-installed.js
|
|
113044
|
+
function stateDir() {
|
|
113045
|
+
switch (process.platform) {
|
|
113046
|
+
case "win32":
|
|
113047
|
+
return "C:\\ProgramData\\Tesseract\\netd";
|
|
113048
|
+
case "darwin":
|
|
113049
|
+
return "/Library/Application Support/Tesseract/netd";
|
|
113050
|
+
default:
|
|
113051
|
+
return "/var/lib/tesseract-netd";
|
|
113052
|
+
}
|
|
113053
|
+
}
|
|
113054
|
+
async function ownerSid() {
|
|
113055
|
+
if (process.platform !== "win32")
|
|
113056
|
+
return void 0;
|
|
113057
|
+
try {
|
|
113058
|
+
const { stdout } = await promisify10(execFile14)("whoami", ["/user", "/fo", "csv", "/nh"]);
|
|
113059
|
+
const m = /"(S-1-[0-9-]+)"/.exec(String(stdout));
|
|
113060
|
+
return m?.[1];
|
|
113061
|
+
} catch {
|
|
113062
|
+
return void 0;
|
|
113063
|
+
}
|
|
113064
|
+
}
|
|
113065
|
+
async function ensureNetHelperInstalled() {
|
|
113066
|
+
const svc = makeNetService();
|
|
113067
|
+
if (!svc.supported) {
|
|
113068
|
+
const st2 = await svc.state();
|
|
113069
|
+
return { ok: false, reason: "unsupported", detail: st2.detail ?? "no helper on this platform" };
|
|
113070
|
+
}
|
|
113071
|
+
const st = await svc.state();
|
|
113072
|
+
if (st.installed)
|
|
113073
|
+
return { ok: true, already: true };
|
|
113074
|
+
const exec2 = netdBinaryPath();
|
|
113075
|
+
if (exec2 && process.platform === "win32" && !existsSync42(join80(dirname34(exec2), "wintun.dll"))) {
|
|
113076
|
+
return {
|
|
113077
|
+
ok: false,
|
|
113078
|
+
reason: "no-binary",
|
|
113079
|
+
detail: "this build shipped the network helper without wintun.dll, so it cannot open a tunnel"
|
|
113080
|
+
};
|
|
113081
|
+
}
|
|
113082
|
+
if (!exec2) {
|
|
113083
|
+
return {
|
|
113084
|
+
ok: false,
|
|
113085
|
+
reason: "no-binary",
|
|
113086
|
+
detail: "this build did not ship the network helper"
|
|
113087
|
+
};
|
|
113088
|
+
}
|
|
113089
|
+
const r = await svc.install({
|
|
113090
|
+
exec: exec2,
|
|
113091
|
+
stateDir: stateDir(),
|
|
113092
|
+
socket: netdEndpoint(),
|
|
113093
|
+
...await ownerSid().then((sid) => sid ? { ownerSid: sid } : {}),
|
|
113094
|
+
// The uid whose requests may mutate. Read HERE, at install time, by the process the
|
|
113095
|
+
// user is actually running — the helper starts as a system service with no session, so
|
|
113096
|
+
// reading it there would be wrong in every interesting case.
|
|
113097
|
+
ownerUid: typeof process.getuid === "function" ? process.getuid() : 0
|
|
113098
|
+
});
|
|
113099
|
+
if (r.ok)
|
|
113100
|
+
return { ok: true, already: false };
|
|
113101
|
+
const declined = /declin|cancel/i.test(r.detail ?? "");
|
|
113102
|
+
return {
|
|
113103
|
+
ok: false,
|
|
113104
|
+
reason: declined ? "declined" : "failed",
|
|
113105
|
+
detail: r.detail ?? "installing the helper failed"
|
|
113106
|
+
};
|
|
113107
|
+
}
|
|
112123
113108
|
|
|
112124
113109
|
// ../../packages/host-core/dist/clipboard/clipboard-sync.js
|
|
112125
113110
|
var MAX_IMAGE_BYTES3 = 10 * 1024 * 1024;
|
|
@@ -112138,28 +113123,24 @@ import { platform as platform6 } from "node:os";
|
|
|
112138
113123
|
|
|
112139
113124
|
// ../../packages/host-core/dist/service/launchd.js
|
|
112140
113125
|
init_credentials();
|
|
112141
|
-
import { writeFileSync as
|
|
112142
|
-
import { dirname as
|
|
113126
|
+
import { writeFileSync as writeFileSync42, existsSync as existsSync43, mkdirSync as mkdirSync41, unlinkSync as unlinkSync7 } from "node:fs";
|
|
113127
|
+
import { dirname as dirname35, join as join81 } from "node:path";
|
|
112143
113128
|
import { homedir as homedir13, userInfo as userInfo2 } from "node:os";
|
|
112144
|
-
|
|
112145
|
-
// ../../packages/host-core/dist/service/types.js
|
|
112146
|
-
var SERVICE_LABEL_BASE = "dev.tesseract.app.host";
|
|
112147
|
-
|
|
112148
|
-
// ../../packages/host-core/dist/service/launchd.js
|
|
112149
|
-
function xml(s) {
|
|
113129
|
+
function xml2(s) {
|
|
112150
113130
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
112151
113131
|
}
|
|
112152
113132
|
function makeLaunchd(instanceId) {
|
|
112153
|
-
const
|
|
112154
|
-
const
|
|
113133
|
+
const suffix = instanceSuffix(instanceId);
|
|
113134
|
+
const label = SERVICE_LABEL_BASE + (suffix ? `.${suffix}` : "");
|
|
113135
|
+
const plistPath = () => join81(homedir13(), "Library", "LaunchAgents", `${label}.plist`);
|
|
112155
113136
|
const domainTarget = () => `gui/${userInfo2().uid}`;
|
|
112156
113137
|
const serviceTarget = () => `${domainTarget()}/${label}`;
|
|
112157
|
-
const logFile = () =>
|
|
113138
|
+
const logFile = () => join81(daemonDir2(), "daemon.log");
|
|
112158
113139
|
const workDirOf = (spec) => spec.workingDirectory ?? daemonDir2();
|
|
112159
|
-
function
|
|
112160
|
-
const args = [spec.exec, ...spec.args].map((a) => ` <string>${
|
|
112161
|
-
const env = Object.entries(spec.env).map(([k, v]) => ` <key>${
|
|
112162
|
-
<string>${
|
|
113140
|
+
function buildPlist2(spec) {
|
|
113141
|
+
const args = [spec.exec, ...spec.args].map((a) => ` <string>${xml2(a)}</string>`).join("\n");
|
|
113142
|
+
const env = Object.entries(spec.env).map(([k, v]) => ` <key>${xml2(k)}</key>
|
|
113143
|
+
<string>${xml2(v)}</string>`).join("\n");
|
|
112163
113144
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
112164
113145
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
112165
113146
|
<plist version="1.0">
|
|
@@ -112175,7 +113156,7 @@ ${args}
|
|
|
112175
113156
|
${env}
|
|
112176
113157
|
</dict>
|
|
112177
113158
|
<key>WorkingDirectory</key>
|
|
112178
|
-
<string>${
|
|
113159
|
+
<string>${xml2(workDirOf(spec))}</string>
|
|
112179
113160
|
<key>RunAtLoad</key>
|
|
112180
113161
|
<true/>
|
|
112181
113162
|
<key>KeepAlive</key>
|
|
@@ -112190,9 +113171,9 @@ ${env}
|
|
|
112190
113171
|
<key>LimitLoadToSessionType</key>
|
|
112191
113172
|
<string>Aqua</string>
|
|
112192
113173
|
<key>StandardOutPath</key>
|
|
112193
|
-
<string>${
|
|
113174
|
+
<string>${xml2(spec.logPath)}</string>
|
|
112194
113175
|
<key>StandardErrorPath</key>
|
|
112195
|
-
<string>${
|
|
113176
|
+
<string>${xml2(spec.logPath)}</string>
|
|
112196
113177
|
</dict>
|
|
112197
113178
|
</plist>
|
|
112198
113179
|
`;
|
|
@@ -112200,21 +113181,21 @@ ${env}
|
|
|
112200
113181
|
return {
|
|
112201
113182
|
async install(spec) {
|
|
112202
113183
|
mkdirSync41(workDirOf(spec), { recursive: true });
|
|
112203
|
-
mkdirSync41(
|
|
112204
|
-
mkdirSync41(
|
|
112205
|
-
|
|
112206
|
-
await
|
|
113184
|
+
mkdirSync41(dirname35(plistPath()), { recursive: true });
|
|
113185
|
+
mkdirSync41(dirname35(spec.logPath), { recursive: true });
|
|
113186
|
+
writeFileSync42(plistPath(), buildPlist2(spec));
|
|
113187
|
+
await run5("launchctl", ["bootout", serviceTarget()]).catch(() => {
|
|
112207
113188
|
});
|
|
112208
|
-
await
|
|
112209
|
-
await
|
|
113189
|
+
await run5("launchctl", ["bootstrap", domainTarget(), plistPath()]);
|
|
113190
|
+
await run5("launchctl", ["enable", serviceTarget()]).catch(() => {
|
|
112210
113191
|
});
|
|
112211
|
-
await
|
|
113192
|
+
await run5("launchctl", ["kickstart", "-k", serviceTarget()]).catch(() => {
|
|
112212
113193
|
});
|
|
112213
113194
|
},
|
|
112214
113195
|
async uninstall() {
|
|
112215
|
-
await
|
|
113196
|
+
await run5("launchctl", ["bootout", serviceTarget()]).catch(() => {
|
|
112216
113197
|
});
|
|
112217
|
-
if (
|
|
113198
|
+
if (existsSync43(plistPath())) {
|
|
112218
113199
|
try {
|
|
112219
113200
|
unlinkSync7(plistPath());
|
|
112220
113201
|
} catch {
|
|
@@ -112225,16 +113206,16 @@ ${env}
|
|
|
112225
113206
|
await this.install(spec);
|
|
112226
113207
|
},
|
|
112227
113208
|
async isInstalled() {
|
|
112228
|
-
return
|
|
113209
|
+
return existsSync43(plistPath());
|
|
112229
113210
|
},
|
|
112230
113211
|
async start() {
|
|
112231
|
-
await
|
|
113212
|
+
await run5("launchctl", ["bootstrap", domainTarget(), plistPath()]).catch(() => {
|
|
112232
113213
|
});
|
|
112233
|
-
await
|
|
113214
|
+
await run5("launchctl", ["kickstart", serviceTarget()]).catch(() => {
|
|
112234
113215
|
});
|
|
112235
113216
|
},
|
|
112236
113217
|
async stop() {
|
|
112237
|
-
await
|
|
113218
|
+
await run5("launchctl", ["bootout", serviceTarget()]).catch(() => {
|
|
112238
113219
|
});
|
|
112239
113220
|
},
|
|
112240
113221
|
async status() {
|
|
@@ -112242,7 +113223,7 @@ ${env}
|
|
|
112242
113223
|
},
|
|
112243
113224
|
async logs(follow) {
|
|
112244
113225
|
const f = logFile();
|
|
112245
|
-
if (!
|
|
113226
|
+
if (!existsSync43(f)) {
|
|
112246
113227
|
console.log(`No log yet at ${f} \u2014 has the service started?`);
|
|
112247
113228
|
return;
|
|
112248
113229
|
}
|
|
@@ -112253,20 +113234,21 @@ ${env}
|
|
|
112253
113234
|
|
|
112254
113235
|
// ../../packages/host-core/dist/service/systemd.js
|
|
112255
113236
|
init_credentials();
|
|
112256
|
-
import { writeFileSync as
|
|
112257
|
-
import { dirname as
|
|
113237
|
+
import { writeFileSync as writeFileSync43, existsSync as existsSync44, mkdirSync as mkdirSync42, unlinkSync as unlinkSync8 } from "node:fs";
|
|
113238
|
+
import { dirname as dirname36, join as join82 } from "node:path";
|
|
112258
113239
|
import { homedir as homedir14, userInfo as userInfo3 } from "node:os";
|
|
112259
|
-
function
|
|
113240
|
+
function unitVal2(v) {
|
|
112260
113241
|
return v.replace(/%/g, "%%");
|
|
112261
113242
|
}
|
|
112262
113243
|
function shq(s) {
|
|
112263
113244
|
return `"${s.replace(/(["\\$`])/g, "\\$1")}"`;
|
|
112264
113245
|
}
|
|
112265
113246
|
function makeSystemd(instanceId) {
|
|
112266
|
-
const
|
|
113247
|
+
const suffix = instanceSuffix(instanceId);
|
|
113248
|
+
const unit = `tesseract-host${suffix ? `-${suffix}` : ""}.service`;
|
|
112267
113249
|
const unitPath = () => {
|
|
112268
|
-
const base = process.env.XDG_CONFIG_HOME ||
|
|
112269
|
-
return
|
|
113250
|
+
const base = process.env.XDG_CONFIG_HOME || join82(homedir14(), ".config");
|
|
113251
|
+
return join82(base, "systemd", "user", unit);
|
|
112270
113252
|
};
|
|
112271
113253
|
const workDirOf = (spec) => spec.workingDirectory ?? daemonDir2();
|
|
112272
113254
|
function buildUnit2(spec) {
|
|
@@ -112280,7 +113262,7 @@ Wants=network-online.target
|
|
|
112280
113262
|
[Service]
|
|
112281
113263
|
Type=simple
|
|
112282
113264
|
${env}
|
|
112283
|
-
WorkingDirectory=${
|
|
113265
|
+
WorkingDirectory=${unitVal2(workDirOf(spec))}
|
|
112284
113266
|
ExecStart=${execStart}
|
|
112285
113267
|
Restart=on-failure
|
|
112286
113268
|
RestartSec=30
|
|
@@ -112294,40 +113276,40 @@ WantedBy=default.target
|
|
|
112294
113276
|
return {
|
|
112295
113277
|
async install(spec) {
|
|
112296
113278
|
mkdirSync42(workDirOf(spec), { recursive: true });
|
|
112297
|
-
mkdirSync42(
|
|
112298
|
-
mkdirSync42(
|
|
112299
|
-
|
|
112300
|
-
await
|
|
113279
|
+
mkdirSync42(dirname36(unitPath()), { recursive: true });
|
|
113280
|
+
mkdirSync42(dirname36(spec.logPath), { recursive: true });
|
|
113281
|
+
writeFileSync43(unitPath(), buildUnit2(spec));
|
|
113282
|
+
await run5("loginctl", ["enable-linger", userInfo3().username]).catch(() => {
|
|
112301
113283
|
});
|
|
112302
|
-
await
|
|
113284
|
+
await run5("systemctl", ["--user", "daemon-reload"]).catch(() => {
|
|
112303
113285
|
});
|
|
112304
|
-
await
|
|
113286
|
+
await run5("systemctl", ["--user", "enable", unit]).catch(() => {
|
|
112305
113287
|
});
|
|
112306
|
-
await
|
|
113288
|
+
await run5("systemctl", ["--user", "restart", unit]);
|
|
112307
113289
|
},
|
|
112308
113290
|
async uninstall() {
|
|
112309
|
-
await
|
|
113291
|
+
await run5("systemctl", ["--user", "disable", "--now", unit]).catch(() => {
|
|
112310
113292
|
});
|
|
112311
|
-
if (
|
|
113293
|
+
if (existsSync44(unitPath())) {
|
|
112312
113294
|
try {
|
|
112313
113295
|
unlinkSync8(unitPath());
|
|
112314
113296
|
} catch {
|
|
112315
113297
|
}
|
|
112316
113298
|
}
|
|
112317
|
-
await
|
|
113299
|
+
await run5("systemctl", ["--user", "daemon-reload"]).catch(() => {
|
|
112318
113300
|
});
|
|
112319
113301
|
},
|
|
112320
113302
|
async restart(spec) {
|
|
112321
113303
|
await this.install(spec);
|
|
112322
113304
|
},
|
|
112323
113305
|
async isInstalled() {
|
|
112324
|
-
return
|
|
113306
|
+
return existsSync44(unitPath());
|
|
112325
113307
|
},
|
|
112326
113308
|
async start() {
|
|
112327
|
-
await
|
|
113309
|
+
await run5("systemctl", ["--user", "start", unit]);
|
|
112328
113310
|
},
|
|
112329
113311
|
async stop() {
|
|
112330
|
-
await
|
|
113312
|
+
await run5("systemctl", ["--user", "stop", unit]);
|
|
112331
113313
|
},
|
|
112332
113314
|
async status() {
|
|
112333
113315
|
await runInherit("systemctl", ["--user", "status", unit, "--no-pager"]);
|
|
@@ -112340,12 +113322,13 @@ WantedBy=default.target
|
|
|
112340
113322
|
|
|
112341
113323
|
// ../../packages/host-core/dist/service/windows.js
|
|
112342
113324
|
init_credentials();
|
|
112343
|
-
import { writeFileSync as
|
|
112344
|
-
import { dirname as
|
|
113325
|
+
import { writeFileSync as writeFileSync44, existsSync as existsSync45, mkdirSync as mkdirSync43, unlinkSync as unlinkSync9 } from "node:fs";
|
|
113326
|
+
import { dirname as dirname37, join as join83 } from "node:path";
|
|
112345
113327
|
function makeWindowsTask(instanceId) {
|
|
112346
|
-
const
|
|
112347
|
-
const
|
|
112348
|
-
const
|
|
113328
|
+
const suffix = instanceSuffix(instanceId);
|
|
113329
|
+
const task = `Fineguide\\TesseractHost${suffix ? `-${suffix}` : ""}`;
|
|
113330
|
+
const wrapperPath = () => join83(daemonDir2(), `run-host${suffix ? `-${suffix}` : ""}.cmd`);
|
|
113331
|
+
const logFile = () => join83(daemonDir2(), "daemon.log");
|
|
112349
113332
|
const oneLine2 = (s) => s.replace(/[\r\n]+/g, " ");
|
|
112350
113333
|
const envVal = (v) => oneLine2(v).replace(/%/g, "%%").replace(/"/g, "");
|
|
112351
113334
|
const cmdArg = (a) => `"${oneLine2(a).replace(/"/g, "")}"`;
|
|
@@ -112362,17 +113345,17 @@ start "" /b ${cmd} >> "${oneLine2(spec.logPath).replace(/"/g, "")}" 2>&1\r
|
|
|
112362
113345
|
return {
|
|
112363
113346
|
async install(spec) {
|
|
112364
113347
|
mkdirSync43(spec.workingDirectory ?? daemonDir2(), { recursive: true });
|
|
112365
|
-
mkdirSync43(
|
|
112366
|
-
mkdirSync43(
|
|
112367
|
-
|
|
112368
|
-
await
|
|
112369
|
-
await
|
|
113348
|
+
mkdirSync43(dirname37(spec.logPath), { recursive: true });
|
|
113349
|
+
mkdirSync43(dirname37(wrapperPath()), { recursive: true });
|
|
113350
|
+
writeFileSync44(wrapperPath(), buildWrapper(spec));
|
|
113351
|
+
await run5("schtasks", ["/Create", "/TN", task, "/SC", "ONLOGON", "/RL", "LIMITED", "/F", "/TR", `"${wrapperPath()}"`]);
|
|
113352
|
+
await run5("schtasks", ["/Run", "/TN", task]).catch(() => {
|
|
112370
113353
|
});
|
|
112371
113354
|
},
|
|
112372
113355
|
async uninstall() {
|
|
112373
|
-
await
|
|
113356
|
+
await run5("schtasks", ["/Delete", "/TN", task, "/F"]).catch(() => {
|
|
112374
113357
|
});
|
|
112375
|
-
if (
|
|
113358
|
+
if (existsSync45(wrapperPath())) {
|
|
112376
113359
|
try {
|
|
112377
113360
|
unlinkSync9(wrapperPath());
|
|
112378
113361
|
} catch {
|
|
@@ -112384,17 +113367,17 @@ start "" /b ${cmd} >> "${oneLine2(spec.logPath).replace(/"/g, "")}" 2>&1\r
|
|
|
112384
113367
|
},
|
|
112385
113368
|
async isInstalled() {
|
|
112386
113369
|
try {
|
|
112387
|
-
await
|
|
113370
|
+
await run5("schtasks", ["/Query", "/TN", task]);
|
|
112388
113371
|
return true;
|
|
112389
113372
|
} catch {
|
|
112390
113373
|
return false;
|
|
112391
113374
|
}
|
|
112392
113375
|
},
|
|
112393
113376
|
async start() {
|
|
112394
|
-
await
|
|
113377
|
+
await run5("schtasks", ["/Run", "/TN", task]);
|
|
112395
113378
|
},
|
|
112396
113379
|
async stop() {
|
|
112397
|
-
await
|
|
113380
|
+
await run5("schtasks", ["/End", "/TN", task]).catch(() => {
|
|
112398
113381
|
});
|
|
112399
113382
|
},
|
|
112400
113383
|
async status() {
|
|
@@ -112402,7 +113385,7 @@ start "" /b ${cmd} >> "${oneLine2(spec.logPath).replace(/"/g, "")}" 2>&1\r
|
|
|
112402
113385
|
},
|
|
112403
113386
|
async logs(follow) {
|
|
112404
113387
|
const f = logFile();
|
|
112405
|
-
if (!
|
|
113388
|
+
if (!existsSync45(f)) {
|
|
112406
113389
|
console.log(`No log yet at ${f} \u2014 has the task run?`);
|
|
112407
113390
|
return;
|
|
112408
113391
|
}
|
|
@@ -112434,8 +113417,8 @@ init_safe_kill();
|
|
|
112434
113417
|
// src/auth.ts
|
|
112435
113418
|
var import_qrcode_terminal = __toESM(require_main(), 1);
|
|
112436
113419
|
import { randomUUID as randomUUID29 } from "node:crypto";
|
|
112437
|
-
import { existsSync as
|
|
112438
|
-
import { join as
|
|
113420
|
+
import { existsSync as existsSync46, rmSync as rmSync12 } from "node:fs";
|
|
113421
|
+
import { join as join84 } from "node:path";
|
|
112439
113422
|
|
|
112440
113423
|
// src/config.ts
|
|
112441
113424
|
import { hostname as hostname6 } from "node:os";
|
|
@@ -112636,8 +113619,8 @@ async function logout() {
|
|
|
112636
113619
|
}
|
|
112637
113620
|
for (const f of ["credentials.json", "status.json", "daemon.lock"]) {
|
|
112638
113621
|
try {
|
|
112639
|
-
const p =
|
|
112640
|
-
if (
|
|
113622
|
+
const p = join84(daemonDir2(), f);
|
|
113623
|
+
if (existsSync46(p)) rmSync12(p);
|
|
112641
113624
|
} catch {
|
|
112642
113625
|
}
|
|
112643
113626
|
}
|
|
@@ -112657,7 +113640,7 @@ function whoami() {
|
|
|
112657
113640
|
}
|
|
112658
113641
|
|
|
112659
113642
|
// src/self-update.ts
|
|
112660
|
-
import { spawn as
|
|
113643
|
+
import { spawn as spawn13 } from "node:child_process";
|
|
112661
113644
|
import { createPublicKey, verify as cryptoVerify } from "node:crypto";
|
|
112662
113645
|
var RESTART_EXIT_CODE = 75;
|
|
112663
113646
|
var REGISTRY_BASE = "https://registry.npmjs.org/tesseract-agent";
|
|
@@ -112732,7 +113715,7 @@ function installVersion(target) {
|
|
|
112732
113715
|
log8(`installing tesseract-agent@${target} \u2026`);
|
|
112733
113716
|
let child;
|
|
112734
113717
|
try {
|
|
112735
|
-
child =
|
|
113718
|
+
child = spawn13(npm, ["install", "-g", `tesseract-agent@${target}`], { stdio: ["ignore", "inherit", "inherit"] });
|
|
112736
113719
|
} catch (e) {
|
|
112737
113720
|
log8("npm spawn threw:", e instanceof Error ? e.message : String(e));
|
|
112738
113721
|
resolve16(false);
|
|
@@ -112795,9 +113778,9 @@ function startSelfUpdater(current) {
|
|
|
112795
113778
|
}
|
|
112796
113779
|
|
|
112797
113780
|
// src/service.ts
|
|
112798
|
-
import { join as
|
|
113781
|
+
import { join as join85 } from "node:path";
|
|
112799
113782
|
import { platform as platform7 } from "node:os";
|
|
112800
|
-
import { existsSync as
|
|
113783
|
+
import { existsSync as existsSync47, readFileSync as readFileSync49 } from "node:fs";
|
|
112801
113784
|
function controller(instanceId) {
|
|
112802
113785
|
const c = getServiceController(instanceId);
|
|
112803
113786
|
if (!c) {
|
|
@@ -112810,7 +113793,7 @@ function buildSpec(cliEntry) {
|
|
|
112810
113793
|
exec: process.execPath,
|
|
112811
113794
|
args: [cliEntry, "run"],
|
|
112812
113795
|
env: { CCB_DAEMON_DIR: daemonDir2() },
|
|
112813
|
-
logPath:
|
|
113796
|
+
logPath: join85(daemonDir2(), "daemon.log")
|
|
112814
113797
|
};
|
|
112815
113798
|
}
|
|
112816
113799
|
var isAlive = (pid) => {
|
|
@@ -112822,9 +113805,9 @@ var isAlive = (pid) => {
|
|
|
112822
113805
|
}
|
|
112823
113806
|
};
|
|
112824
113807
|
function runningDaemonInfo() {
|
|
112825
|
-
const lock =
|
|
113808
|
+
const lock = join85(daemonDir2(), "daemon.lock");
|
|
112826
113809
|
try {
|
|
112827
|
-
if (!
|
|
113810
|
+
if (!existsSync47(lock)) return null;
|
|
112828
113811
|
const pid = Number(readFileSync49(lock, "utf-8").trim());
|
|
112829
113812
|
if (!pid || !isAlive(pid)) return null;
|
|
112830
113813
|
return { pid, device: readCredentials()?.deviceId };
|
|
@@ -112877,6 +113860,16 @@ function usage() {
|
|
|
112877
113860
|
Join a network. The token is all you need;
|
|
112878
113861
|
the name defaults to this machine's hostname.
|
|
112879
113862
|
tesseract-agent net leave MESH [--yes] Forget a mesh entirely, key included
|
|
113863
|
+
tesseract-agent net helper [status|install|uninstall|enable-nat]
|
|
113864
|
+
The privileged network helper, which is what
|
|
113865
|
+
actually programs the routes. Without it a
|
|
113866
|
+
machine joins, holds a certificate, shows a
|
|
113867
|
+
roster \u2014 and carries no packets. Run the
|
|
113868
|
+
install under sudo (Windows: an elevated
|
|
113869
|
+
shell); there is nothing to prompt on a server.
|
|
113870
|
+
enable-nat is WINDOWS ONLY and only needed to
|
|
113871
|
+
be the way out FOR OTHERS \u2014 it turns on a
|
|
113872
|
+
Windows optional feature and needs a restart.
|
|
112880
113873
|
|
|
112881
113874
|
Running a network (needs a signed-in account):
|
|
112882
113875
|
tesseract-agent net new [NAME] Create a network and print its join token.
|
|
@@ -113058,9 +114051,80 @@ async function netCommand(rest, flags) {
|
|
|
113058
114051
|
updateLocal(meshId, { enabled: sub === "up" });
|
|
113059
114052
|
console.log(`${meshId} ${sub === "up" ? "enabled" : "disabled"}`);
|
|
113060
114053
|
}
|
|
113061
|
-
|
|
114054
|
+
if (sub === "down") {
|
|
114055
|
+
const stillOn = listMeshIds().filter((id) => readLocal(id)?.enabled !== false);
|
|
114056
|
+
const r = await syncRoutes(stillOn);
|
|
114057
|
+
if (r.helperAbsent) {
|
|
114058
|
+
console.log("The network helper is not installed, so nothing was routed anyway.");
|
|
114059
|
+
} else {
|
|
114060
|
+
if (r.down.length) console.log(`routes removed: ${r.down.join(", ")}`);
|
|
114061
|
+
for (const f of r.failed) console.error(`routes ${f.meshId}: ${f.reason}`);
|
|
114062
|
+
}
|
|
114063
|
+
} else if (!await netdAvailable()) {
|
|
114064
|
+
console.log("The network helper is not installed, so nothing will be routed yet.");
|
|
114065
|
+
console.log("Install it with: sudo tesseract-agent net helper install");
|
|
114066
|
+
}
|
|
114067
|
+
console.log("Run `tesseract-agent restart` to start or stop the node itself.");
|
|
113062
114068
|
return;
|
|
113063
114069
|
}
|
|
114070
|
+
if (sub === "helper") {
|
|
114071
|
+
const action = rest[1] ?? "status";
|
|
114072
|
+
const svc = makeNetService();
|
|
114073
|
+
if (action === "status") {
|
|
114074
|
+
const st = await svc.state();
|
|
114075
|
+
const bin = netdBinaryPath();
|
|
114076
|
+
console.log(`platform ${process.platform}${svc.supported ? "" : " (no helper for this platform)"}`);
|
|
114077
|
+
console.log(`binary ${bin ?? "NOT SHIPPED IN THIS BUILD"}`);
|
|
114078
|
+
console.log(`installed ${st.installed ? "yes" : "no"}`);
|
|
114079
|
+
console.log(`running ${st.running ? "yes" : "no"}`);
|
|
114080
|
+
console.log(`answering ${await netdAvailable() ? "yes" : "no"}`);
|
|
114081
|
+
if (st.detail) console.log(`note ${st.detail}`);
|
|
114082
|
+
const nat = await natCapability();
|
|
114083
|
+
console.log(`way out for others ${nat.available ? "yes" : "NOT YET"}`);
|
|
114084
|
+
if (!nat.available) {
|
|
114085
|
+
console.log(` ${nat.reason}`);
|
|
114086
|
+
console.log(" Turn it on with: tesseract-agent net helper enable-nat");
|
|
114087
|
+
}
|
|
114088
|
+
return;
|
|
114089
|
+
}
|
|
114090
|
+
if (action === "enable-nat") {
|
|
114091
|
+
const nat = await natCapability();
|
|
114092
|
+
if (nat.available) {
|
|
114093
|
+
console.log("This machine can already be the way out for others. Nothing to do.");
|
|
114094
|
+
return;
|
|
114095
|
+
}
|
|
114096
|
+
const r = await enableNatProvider();
|
|
114097
|
+
if (r.ok) {
|
|
114098
|
+
console.log("The Windows NAT component is enabled.");
|
|
114099
|
+
if (r.restartRequired) {
|
|
114100
|
+
console.log("RESTART REQUIRED to finish. Nothing was restarted for you.");
|
|
114101
|
+
}
|
|
114102
|
+
return;
|
|
114103
|
+
}
|
|
114104
|
+
console.error(`net helper enable-nat: ${r.detail}`);
|
|
114105
|
+
process.exit(r.reason === "unsupported" ? 2 : 1);
|
|
114106
|
+
}
|
|
114107
|
+
if (action === "install") {
|
|
114108
|
+
const r = await ensureNetHelperInstalled();
|
|
114109
|
+
if (r.ok) {
|
|
114110
|
+
console.log(r.already ? "The network helper is already installed." : "The network helper is installed.");
|
|
114111
|
+
return;
|
|
114112
|
+
}
|
|
114113
|
+
console.error(`net helper install: ${r.detail}`);
|
|
114114
|
+
process.exit(r.reason === "unsupported" || r.reason === "no-binary" ? 2 : 1);
|
|
114115
|
+
}
|
|
114116
|
+
if (action === "uninstall") {
|
|
114117
|
+
const r = await svc.uninstall();
|
|
114118
|
+
if (r.ok) {
|
|
114119
|
+
console.log("The network helper is removed.");
|
|
114120
|
+
return;
|
|
114121
|
+
}
|
|
114122
|
+
console.error(`net helper uninstall: ${r.detail ?? "failed"}`);
|
|
114123
|
+
process.exit(1);
|
|
114124
|
+
}
|
|
114125
|
+
console.error(`net helper: unknown action ${action} (status | install | uninstall | enable-nat)`);
|
|
114126
|
+
process.exit(1);
|
|
114127
|
+
}
|
|
113064
114128
|
if (sub === "join") {
|
|
113065
114129
|
const token3 = rest[1] ?? str2(flags.token);
|
|
113066
114130
|
const code = str2(flags.code);
|
|
@@ -113380,7 +114444,7 @@ async function netCommand(rest, flags) {
|
|
|
113380
114444
|
// src/cli.ts
|
|
113381
114445
|
function pkgVersion() {
|
|
113382
114446
|
try {
|
|
113383
|
-
const p =
|
|
114447
|
+
const p = join87(dirname38(fileURLToPath8(import.meta.url)), "..", "package.json");
|
|
113384
114448
|
return JSON.parse(readFileSync52(p, "utf8")).version ?? "0.0.0";
|
|
113385
114449
|
} catch {
|
|
113386
114450
|
return "0.0.0";
|
|
@@ -113437,7 +114501,7 @@ async function superviseDaemon(cliEntry) {
|
|
|
113437
114501
|
let stopping3 = false;
|
|
113438
114502
|
let child = null;
|
|
113439
114503
|
const spawnWorker = () => {
|
|
113440
|
-
const c =
|
|
114504
|
+
const c = spawn14(process.execPath, [cliEntry, "__worker"], { stdio: "inherit", env: process.env });
|
|
113441
114505
|
child = c;
|
|
113442
114506
|
let settled = false;
|
|
113443
114507
|
const settle = (fn) => {
|
|
@@ -113609,7 +114673,7 @@ async function linkCommand(rest, flags) {
|
|
|
113609
114673
|
process.exit(1);
|
|
113610
114674
|
}
|
|
113611
114675
|
async function captureClaudeSubscription(flags) {
|
|
113612
|
-
const home =
|
|
114676
|
+
const home = mkdtempSync4(join87(tmpdir8(), "tesseract-claude-login-"));
|
|
113613
114677
|
const binary = typeof flags["claude-path"] === "string" ? flags["claude-path"] : process.env.CCB_ENGINE_PATH_CLAUDE_CODE || "claude";
|
|
113614
114678
|
const args = ["auth", "login", "--claudeai"];
|
|
113615
114679
|
if (typeof flags.email === "string") args.push("--email", flags.email);
|
|
@@ -113618,7 +114682,7 @@ async function captureClaudeSubscription(flags) {
|
|
|
113618
114682
|
console.log("Open the authorization URL in any browser; paste the returned code here if Claude asks for it.");
|
|
113619
114683
|
try {
|
|
113620
114684
|
const code = await new Promise((resolveCode, reject) => {
|
|
113621
|
-
const child =
|
|
114685
|
+
const child = spawn14(binary, args, {
|
|
113622
114686
|
env: { ...process.env, CLAUDE_CONFIG_DIR: home },
|
|
113623
114687
|
stdio: "inherit"
|
|
113624
114688
|
});
|
|
@@ -113626,8 +114690,8 @@ async function captureClaudeSubscription(flags) {
|
|
|
113626
114690
|
child.once("close", (exitCode, signal) => resolveCode(signal ? 1 : exitCode ?? 1));
|
|
113627
114691
|
});
|
|
113628
114692
|
if (code !== 0) throw new Error(`Claude sign-in did not complete (exit ${code}).`);
|
|
113629
|
-
const file2 =
|
|
113630
|
-
if (
|
|
114693
|
+
const file2 = join87(home, ".credentials.json");
|
|
114694
|
+
if (existsSync49(file2)) return readFileSync52(file2, "utf8");
|
|
113631
114695
|
if (process.platform === "darwin") {
|
|
113632
114696
|
const value = execFileSync6("security", [
|
|
113633
114697
|
"find-generic-password",
|
|
@@ -113639,7 +114703,7 @@ async function captureClaudeSubscription(flags) {
|
|
|
113639
114703
|
}
|
|
113640
114704
|
throw new Error("Claude reported success but no credentials were captured.");
|
|
113641
114705
|
} finally {
|
|
113642
|
-
|
|
114706
|
+
rmSync13(home, { recursive: true, force: true });
|
|
113643
114707
|
}
|
|
113644
114708
|
}
|
|
113645
114709
|
async function runnerCommand(rest, flags) {
|
|
@@ -113754,7 +114818,7 @@ async function main() {
|
|
|
113754
114818
|
process.env.CCB_DAEMON_DIR = tessPath(`daemon-${instance}`);
|
|
113755
114819
|
}
|
|
113756
114820
|
const force = flags.yes === true || flags.force === true;
|
|
113757
|
-
const cliEntry =
|
|
114821
|
+
const cliEntry = fileURLToPath8(import.meta.url);
|
|
113758
114822
|
switch (cmd) {
|
|
113759
114823
|
case "login":
|
|
113760
114824
|
await login({
|