tesseract-agent 0.10.8 → 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
|
@@ -4010,6 +4010,20 @@ var init_app_elements = __esm({
|
|
|
4010
4010
|
title: "Search",
|
|
4011
4011
|
description: "Opens search and the command palette \u2014 the fastest way to find anything."
|
|
4012
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
|
+
},
|
|
4013
4027
|
{
|
|
4014
4028
|
id: "titlebar.settings",
|
|
4015
4029
|
area: "titlebar",
|
|
@@ -4253,8 +4267,8 @@ function parseModelJsonArray(raw) {
|
|
|
4253
4267
|
function schemaRejected(status2) {
|
|
4254
4268
|
return status2 === 400 || status2 === 422;
|
|
4255
4269
|
}
|
|
4256
|
-
function anthropicBaseUrl() {
|
|
4257
|
-
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";
|
|
4258
4272
|
}
|
|
4259
4273
|
var OAUTH_BETA_HEADER;
|
|
4260
4274
|
var init_model_json = __esm({
|
|
@@ -4278,6 +4292,56 @@ var init_domain_id = __esm({
|
|
|
4278
4292
|
}
|
|
4279
4293
|
});
|
|
4280
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
|
+
|
|
4281
4345
|
// ../../packages/shared/dist/telemetry.js
|
|
4282
4346
|
var TELEMETRY_EVENTS, EVENT_CATEGORY;
|
|
4283
4347
|
var init_telemetry = __esm({
|
|
@@ -4705,14 +4769,67 @@ var init_hosting = __esm({
|
|
|
4705
4769
|
}
|
|
4706
4770
|
});
|
|
4707
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
|
+
|
|
4708
4815
|
// ../../packages/shared/dist/settings.js
|
|
4709
4816
|
function canCallDirectly(modelId) {
|
|
4710
4817
|
return !!modelId && MODEL_OPTIONS.some((m) => m.id === modelId);
|
|
4711
4818
|
}
|
|
4712
|
-
|
|
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;
|
|
4713
4829
|
var init_settings = __esm({
|
|
4714
4830
|
"../../packages/shared/dist/settings.js"() {
|
|
4715
4831
|
"use strict";
|
|
4832
|
+
init_model_long_context();
|
|
4716
4833
|
MODEL_OPTIONS = [
|
|
4717
4834
|
{ id: "claude-opus-5", label: "Claude Opus 5" },
|
|
4718
4835
|
{ id: "claude-sonnet-5", label: "Claude Sonnet 5" },
|
|
@@ -4722,6 +4839,7 @@ var init_settings = __esm({
|
|
|
4722
4839
|
{ id: "claude-haiku-4-5", label: "Claude Haiku 4.5" }
|
|
4723
4840
|
];
|
|
4724
4841
|
DEFAULT_VERIFIER_MODEL = MODEL_OPTIONS[0].id;
|
|
4842
|
+
CLI_MODEL_ALIASES = /^(?:default|sonnet|opus|haiku|fable)(?:\[1m\])?$/i;
|
|
4725
4843
|
}
|
|
4726
4844
|
});
|
|
4727
4845
|
|
|
@@ -6400,9 +6518,9 @@ function kebab(s) {
|
|
|
6400
6518
|
return s.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase();
|
|
6401
6519
|
}
|
|
6402
6520
|
function tokenCssVarName(path6, token3) {
|
|
6403
|
-
const
|
|
6404
|
-
if (
|
|
6405
|
-
const name =
|
|
6521
|
+
const override3 = token3 ? tessExt(token3)?.cssVar : void 0;
|
|
6522
|
+
if (override3) {
|
|
6523
|
+
const name = override3.startsWith("--") ? override3 : `--${override3}`;
|
|
6406
6524
|
if (/^--[A-Za-z0-9-]+$/.test(name))
|
|
6407
6525
|
return name;
|
|
6408
6526
|
}
|
|
@@ -7256,6 +7374,9 @@ var init_dist = __esm({
|
|
|
7256
7374
|
init_ws_protocol();
|
|
7257
7375
|
init_frame();
|
|
7258
7376
|
init_domain_id();
|
|
7377
|
+
init_run_directive();
|
|
7378
|
+
init_proactive_compaction();
|
|
7379
|
+
init_digit_recall();
|
|
7259
7380
|
init_telemetry();
|
|
7260
7381
|
init_error_report();
|
|
7261
7382
|
init_eula();
|
|
@@ -7947,8 +8068,9 @@ function materializeClaudeAuthHome(contents) {
|
|
|
7947
8068
|
return home;
|
|
7948
8069
|
}
|
|
7949
8070
|
function withClaudeModels(env, main2, fast) {
|
|
7950
|
-
if (main2)
|
|
7951
|
-
env.ANTHROPIC_MODEL = main2;
|
|
8071
|
+
if (main2) {
|
|
8072
|
+
env.ANTHROPIC_MODEL = process.env.TESSERACT_DISABLE_1M_CONTEXT === "1" ? main2 : withOneMillionContext(main2) ?? main2;
|
|
8073
|
+
}
|
|
7952
8074
|
if (fast)
|
|
7953
8075
|
env.ANTHROPIC_SMALL_FAST_MODEL = fast;
|
|
7954
8076
|
return env;
|
|
@@ -7975,14 +8097,14 @@ function resolveRunnerEnv(spec) {
|
|
|
7975
8097
|
return {};
|
|
7976
8098
|
const key2 = spec?.secret?.trim();
|
|
7977
8099
|
if (provider.claudeEnterprise) {
|
|
7978
|
-
const
|
|
7979
|
-
if (
|
|
7980
|
-
return { CCB_RUNNER_CONFIG_ERROR:
|
|
7981
|
-
if (!
|
|
7982
|
-
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;
|
|
7983
8105
|
try {
|
|
7984
|
-
const path6 = materializeEnterpriseCredential(
|
|
7985
|
-
return { ...
|
|
8106
|
+
const path6 = materializeEnterpriseCredential(run8.file.suggestedName, run8.file.contents);
|
|
8107
|
+
return { ...run8.env, [run8.file.envVar]: path6 };
|
|
7986
8108
|
} catch (e) {
|
|
7987
8109
|
return { CCB_RUNNER_CONFIG_ERROR: `Could not write the ${provider.label} credential on this machine: ${e.message}` };
|
|
7988
8110
|
}
|
|
@@ -8049,6 +8171,7 @@ var init_resolve = __esm({
|
|
|
8049
8171
|
"../../packages/host-core/dist/runners/resolve.js"() {
|
|
8050
8172
|
"use strict";
|
|
8051
8173
|
init_base_paths();
|
|
8174
|
+
init_model_long_context();
|
|
8052
8175
|
init_file_lock();
|
|
8053
8176
|
init_dist();
|
|
8054
8177
|
init_proxy_router();
|
|
@@ -8589,21 +8712,27 @@ function readDaemonAgentSettings() {
|
|
|
8589
8712
|
return snap;
|
|
8590
8713
|
}
|
|
8591
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
|
+
}
|
|
8592
8721
|
function gatewayTierRejection(model) {
|
|
8593
8722
|
if (!model)
|
|
8594
8723
|
return null;
|
|
8595
|
-
const
|
|
8596
|
-
if (
|
|
8724
|
+
const snap = readDaemonAgentSettings();
|
|
8725
|
+
if (gatewayCanCall(model, snap))
|
|
8597
8726
|
return null;
|
|
8598
|
-
return { model, tiers: [...
|
|
8727
|
+
return { model, tiers: [...snap.gatewayTiers ?? []] };
|
|
8599
8728
|
}
|
|
8600
8729
|
function gatewayTierClamp(model) {
|
|
8601
8730
|
if (!model)
|
|
8602
8731
|
return model;
|
|
8603
|
-
const
|
|
8604
|
-
if (
|
|
8732
|
+
const snap = readDaemonAgentSettings();
|
|
8733
|
+
if (gatewayCanCall(model, snap))
|
|
8605
8734
|
return model;
|
|
8606
|
-
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.`);
|
|
8607
8736
|
return void 0;
|
|
8608
8737
|
}
|
|
8609
8738
|
function chatSendToParams(msg, defaults) {
|
|
@@ -8630,6 +8759,10 @@ function chatSendToParams(msg, defaults) {
|
|
|
8630
8759
|
// one OFF for one conversation could not actually turn it off.
|
|
8631
8760
|
...msg.unattended !== void 0 ? { unattended: msg.unattended } : {},
|
|
8632
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 } : {},
|
|
8633
8766
|
...msg.autoContinuation ? { autoContinuation: true } : {},
|
|
8634
8767
|
...msg.model ? { model: msg.model } : {},
|
|
8635
8768
|
...msg.jsonSchema ? { jsonSchema: msg.jsonSchema } : {},
|
|
@@ -8699,11 +8832,15 @@ function mergeDaemonAgentSettings(params) {
|
|
|
8699
8832
|
// local override (single-config CLI). Enabled skills' env is folded in. Empty ⇒
|
|
8700
8833
|
// ambient Claude.
|
|
8701
8834
|
engineEnv: params.engineEnv ?? {
|
|
8702
|
-
...
|
|
8835
|
+
...daemonEngineEnv(),
|
|
8703
8836
|
...s.skillEnv ?? {}
|
|
8704
8837
|
}
|
|
8705
8838
|
};
|
|
8706
8839
|
}
|
|
8840
|
+
function daemonEngineEnv() {
|
|
8841
|
+
const s = readDaemonAgentSettings();
|
|
8842
|
+
return poolActiveEngineEnv() ?? (s.runnerSpec ? resolveRunnerEnv(s.runnerSpec) : resolveOverrideEngineEnv());
|
|
8843
|
+
}
|
|
8707
8844
|
var init_daemon_settings = __esm({
|
|
8708
8845
|
"../../packages/host-core/dist/daemon-settings.js"() {
|
|
8709
8846
|
"use strict";
|
|
@@ -12058,10 +12195,10 @@ var init_schemas = __esm({
|
|
|
12058
12195
|
$ZodType.init(inst, def);
|
|
12059
12196
|
const desc = Object.getOwnPropertyDescriptor(def, "shape");
|
|
12060
12197
|
if (!desc?.get) {
|
|
12061
|
-
const
|
|
12198
|
+
const sh3 = def.shape;
|
|
12062
12199
|
Object.defineProperty(def, "shape", {
|
|
12063
12200
|
get: () => {
|
|
12064
|
-
const newSh = { ...
|
|
12201
|
+
const newSh = { ...sh3 };
|
|
12065
12202
|
Object.defineProperty(def, "shape", {
|
|
12066
12203
|
value: newSh
|
|
12067
12204
|
});
|
|
@@ -28566,8 +28703,8 @@ function prompt(id, vars) {
|
|
|
28566
28703
|
}
|
|
28567
28704
|
return "";
|
|
28568
28705
|
}
|
|
28569
|
-
const
|
|
28570
|
-
return interpolatePrompt(typeof
|
|
28706
|
+
const override3 = snapshot2.entries[id];
|
|
28707
|
+
return interpolatePrompt(typeof override3 === "string" ? override3 : spec.content, vars);
|
|
28571
28708
|
}
|
|
28572
28709
|
function describedBy(idPrefix, specs, key2 = (s) => s.name) {
|
|
28573
28710
|
return specs.map((spec) => Object.defineProperty({ ...spec }, "description", {
|
|
@@ -28708,7 +28845,7 @@ function buildPack(s) {
|
|
|
28708
28845
|
const dual = (lv) => ({ $value: lv[0], $extensions: { "com.tesseract": { modes: { dark: lv[1] } } } });
|
|
28709
28846
|
const val = (v) => Array.isArray(v) ? dual(v) : { $value: v };
|
|
28710
28847
|
const r = s.radius ?? { sm: "6px", md: "10px", lg: "16px" };
|
|
28711
|
-
const
|
|
28848
|
+
const sh3 = s.shadow ?? {
|
|
28712
28849
|
sm: "0 1px 2px rgb(0 0 0 / 0.06)",
|
|
28713
28850
|
md: "0 4px 12px rgb(0 0 0 / 0.08)",
|
|
28714
28851
|
lg: "0 12px 32px rgb(0 0 0 / 0.12)"
|
|
@@ -28753,7 +28890,7 @@ function buildPack(s) {
|
|
|
28753
28890
|
xl: { $value: "40px" }
|
|
28754
28891
|
},
|
|
28755
28892
|
radius: { $type: "dimension", sm: { $value: r.sm }, md: { $value: r.md }, lg: { $value: r.lg }, full: { $value: "9999px" } },
|
|
28756
|
-
shadow: { $type: "shadow", sm: { $value:
|
|
28893
|
+
shadow: { $type: "shadow", sm: { $value: sh3.sm }, md: { $value: sh3.md }, lg: { $value: sh3.lg } }
|
|
28757
28894
|
};
|
|
28758
28895
|
return { $packSchema: DESIGN_PACK_SCHEMA, id: s.id, name: s.name, description: s.description, style: s.style, tokens: tokens3 };
|
|
28759
28896
|
}
|
|
@@ -31716,7 +31853,7 @@ var init_job_registry = __esm({
|
|
|
31716
31853
|
* the calling tool can return `{ id, logPath }` to the model in the same tick, so the
|
|
31717
31854
|
* turn continues instead of blocking. `run` is deliberately NOT awaited here.
|
|
31718
31855
|
*/
|
|
31719
|
-
start(kind, description,
|
|
31856
|
+
start(kind, description, run8) {
|
|
31720
31857
|
const id = makeId(++this.seq);
|
|
31721
31858
|
const logPath = join16(this.dir, `${id}.output`);
|
|
31722
31859
|
const abort = new AbortController();
|
|
@@ -31736,7 +31873,7 @@ var init_job_registry = __esm({
|
|
|
31736
31873
|
this.evict();
|
|
31737
31874
|
void (async () => {
|
|
31738
31875
|
try {
|
|
31739
|
-
const tail3 = await
|
|
31876
|
+
const tail3 = await run8((chunk) => this.write(id, chunk), abort.signal);
|
|
31740
31877
|
if (typeof tail3 === "string" && tail3)
|
|
31741
31878
|
this.write(id, tail3);
|
|
31742
31879
|
this.settle(id, abort.signal.aborted ? "stopped" : "completed", abort.signal.aborted ? 130 : 0);
|
|
@@ -33485,9 +33622,9 @@ function paginationSignature(engine) {
|
|
|
33485
33622
|
return [...engine.pagination.params].sort().join("+");
|
|
33486
33623
|
}
|
|
33487
33624
|
function pageStrategy(engine) {
|
|
33488
|
-
const
|
|
33489
|
-
if (
|
|
33490
|
-
return
|
|
33625
|
+
const override3 = OVERRIDES[engine.id];
|
|
33626
|
+
if (override3)
|
|
33627
|
+
return override3;
|
|
33491
33628
|
const sig = paginationSignature(engine);
|
|
33492
33629
|
if (!sig)
|
|
33493
33630
|
return { kind: "none", reason: "This engine declares no pagination parameters." };
|
|
@@ -36635,27 +36772,18 @@ function autoCompactEnvFor(pct2, supplied) {
|
|
|
36635
36772
|
function shouldCompactProactively(a) {
|
|
36636
36773
|
if (a.mode === "off")
|
|
36637
36774
|
return "skip";
|
|
36638
|
-
|
|
36639
|
-
return "skip";
|
|
36640
|
-
if (typeof a.pct !== "number" || !Number.isFinite(a.pct) || a.pct <= 0 || a.pct >= 100)
|
|
36641
|
-
return "skip";
|
|
36642
|
-
if (typeof a.usagePct !== "number" || !Number.isFinite(a.usagePct))
|
|
36643
|
-
return "skip";
|
|
36644
|
-
if (a.usagePct < a.pct)
|
|
36645
|
-
return "reset";
|
|
36646
|
-
if (typeof a.lastCompactPct === "number" && a.usagePct < a.lastCompactPct + PROACTIVE_REGROWTH_POINTS)
|
|
36647
|
-
return "skip";
|
|
36648
|
-
return "compact";
|
|
36775
|
+
return proactiveCompactionVerdict(a);
|
|
36649
36776
|
}
|
|
36650
|
-
var OVERFLOW_MAX_TRIES, OVERFLOW_COMPACT_MESSAGE, OVERFLOW_RESUME_MESSAGE
|
|
36777
|
+
var OVERFLOW_MAX_TRIES, OVERFLOW_COMPACT_MESSAGE, OVERFLOW_RESUME_MESSAGE;
|
|
36651
36778
|
var init_context_recovery = __esm({
|
|
36652
36779
|
"../../packages/agent-core/dist/context-recovery.js"() {
|
|
36653
36780
|
"use strict";
|
|
36781
|
+
init_dist();
|
|
36654
36782
|
init_unattended_log();
|
|
36783
|
+
init_dist();
|
|
36655
36784
|
OVERFLOW_MAX_TRIES = 3;
|
|
36656
36785
|
OVERFLOW_COMPACT_MESSAGE = "/compact";
|
|
36657
36786
|
OVERFLOW_RESUME_MESSAGE = "Continue.";
|
|
36658
|
-
PROACTIVE_REGROWTH_POINTS = 5;
|
|
36659
36787
|
}
|
|
36660
36788
|
});
|
|
36661
36789
|
|
|
@@ -37483,13 +37611,16 @@ async function fetchSessionUsage(env) {
|
|
|
37483
37611
|
}
|
|
37484
37612
|
async function anthropicHeaders(env) {
|
|
37485
37613
|
const apiKey = env?.ANTHROPIC_API_KEY?.trim() || process.env.ANTHROPIC_API_KEY?.trim() || "";
|
|
37486
|
-
const
|
|
37487
|
-
|
|
37614
|
+
const authToken = apiKey ? "" : env?.ANTHROPIC_AUTH_TOKEN?.trim() || "";
|
|
37615
|
+
const oauth = apiKey || authToken ? "" : await resolveOauthToken(env) || "";
|
|
37616
|
+
if (!apiKey && !authToken && !oauth)
|
|
37488
37617
|
return null;
|
|
37489
37618
|
const headers = { "content-type": "application/json", "anthropic-version": "2023-06-01" };
|
|
37490
37619
|
if (apiKey)
|
|
37491
37620
|
headers["x-api-key"] = apiKey;
|
|
37492
|
-
else {
|
|
37621
|
+
else if (authToken) {
|
|
37622
|
+
headers.authorization = `Bearer ${authToken}`;
|
|
37623
|
+
} else {
|
|
37493
37624
|
headers.authorization = `Bearer ${oauth}`;
|
|
37494
37625
|
headers["anthropic-beta"] = OAUTH_BETA_HEADER;
|
|
37495
37626
|
}
|
|
@@ -37499,27 +37630,31 @@ async function hasAnthropicCred(env) {
|
|
|
37499
37630
|
return await anthropicHeaders(env) !== null;
|
|
37500
37631
|
}
|
|
37501
37632
|
async function anthropicMessage(args) {
|
|
37633
|
+
return (await anthropicCall(args)).text;
|
|
37634
|
+
}
|
|
37635
|
+
async function anthropicCall(args) {
|
|
37502
37636
|
const { env, model, system, content, maxTokens, timeoutMs, label } = args;
|
|
37503
37637
|
const attempts = Math.max(1, args.attempts ?? 1);
|
|
37504
37638
|
const budgetMs = args.budgetMs ?? attempts * timeoutMs + 4e3;
|
|
37505
37639
|
const deadline = Date.now() + budgetMs;
|
|
37506
|
-
const base = { model, max_tokens: maxTokens, system, messages: [{ role: "user", content }] };
|
|
37507
|
-
|
|
37508
|
-
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;
|
|
37509
37644
|
const headers = await anthropicHeaders(env);
|
|
37510
37645
|
if (!headers)
|
|
37511
|
-
return null;
|
|
37646
|
+
return { text: null, rateLimited: false };
|
|
37512
37647
|
for (let attempt = 0; attempt < attempts; attempt++) {
|
|
37513
37648
|
const remaining = deadline - Date.now();
|
|
37514
37649
|
if (remaining < 1e3) {
|
|
37515
37650
|
log(`${label}: out of budget after ${attempt} attempt(s) \u2014 giving up rather than starting a leg that cannot finish.`);
|
|
37516
|
-
return null;
|
|
37651
|
+
return { text: null, rateLimited: false };
|
|
37517
37652
|
}
|
|
37518
37653
|
const ac = new AbortController();
|
|
37519
37654
|
const legMs = Math.min(timeoutMs, remaining);
|
|
37520
37655
|
const legTimer = setTimeout(() => ac.abort(new Error("The operation was aborted due to timeout")), legMs);
|
|
37521
37656
|
try {
|
|
37522
|
-
const res = await fetch(`${anthropicBaseUrl()}/v1/messages`, {
|
|
37657
|
+
const res = await fetch(`${anthropicBaseUrl(env)}/v1/messages`, {
|
|
37523
37658
|
method: "POST",
|
|
37524
37659
|
headers,
|
|
37525
37660
|
body,
|
|
@@ -37527,23 +37662,34 @@ async function anthropicMessage(args) {
|
|
|
37527
37662
|
});
|
|
37528
37663
|
if (res.ok) {
|
|
37529
37664
|
const j = await res.json();
|
|
37530
|
-
|
|
37665
|
+
const text12 = (j.content ?? []).filter((b) => b.type === "text").map((b) => b.text ?? "").join("").trim() || null;
|
|
37666
|
+
return { text: text12, rateLimited: false };
|
|
37531
37667
|
}
|
|
37532
37668
|
if (schemaRejected(res.status) && args.schema && !schemaDropped) {
|
|
37533
37669
|
schemaDropped = true;
|
|
37670
|
+
schemaUnsupported.add(schemaKey(anthropicBaseUrl(env), model));
|
|
37534
37671
|
body = JSON.stringify(base);
|
|
37535
37672
|
log(`${label}: the endpoint rejected output_config (${model}) \u2014 retrying without the schema and parsing the reply as text.`);
|
|
37536
37673
|
attempt--;
|
|
37537
37674
|
continue;
|
|
37538
37675
|
}
|
|
37539
|
-
|
|
37540
|
-
|
|
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()));
|
|
37541
37687
|
log(`${label}: HTTP ${res.status} (${model}) \u2014 retry ${attempt + 1} in ${wait}ms`);
|
|
37542
37688
|
await new Promise((r) => setTimeout(r, wait));
|
|
37543
37689
|
continue;
|
|
37544
37690
|
}
|
|
37545
37691
|
log(`${label}: HTTP ${res.status} (${model})`);
|
|
37546
|
-
return null;
|
|
37692
|
+
return { text: null, rateLimited, modelRejected };
|
|
37547
37693
|
} catch (err2) {
|
|
37548
37694
|
if (args.retryOnThrow && attempt < attempts - 1) {
|
|
37549
37695
|
const wait = Math.max(0, Math.min(800 * (attempt + 1) * (attempt + 1), deadline - Date.now()));
|
|
@@ -37552,19 +37698,27 @@ async function anthropicMessage(args) {
|
|
|
37552
37698
|
continue;
|
|
37553
37699
|
}
|
|
37554
37700
|
log(`${label}: call failed:`, err2 instanceof Error ? err2.message : String(err2));
|
|
37555
|
-
return null;
|
|
37701
|
+
return { text: null, rateLimited: false };
|
|
37556
37702
|
} finally {
|
|
37557
37703
|
clearTimeout(legTimer);
|
|
37558
37704
|
}
|
|
37559
37705
|
}
|
|
37560
|
-
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
|
+
}
|
|
37561
37714
|
}
|
|
37562
37715
|
async function buildClaudeNarrationLlm(env) {
|
|
37563
37716
|
if (!await hasAnthropicCred(env))
|
|
37564
37717
|
return null;
|
|
37718
|
+
const model = isDirectAnthropic(env) ? "claude-haiku-4-5" : env?.ANTHROPIC_SMALL_FAST_MODEL?.trim() || env?.ANTHROPIC_MODEL?.trim() || "";
|
|
37565
37719
|
const complete = ({ system, prompt: prompt2, maxTokens, schema }) => anthropicMessage({
|
|
37566
37720
|
env,
|
|
37567
|
-
model
|
|
37721
|
+
model,
|
|
37568
37722
|
system,
|
|
37569
37723
|
content: prompt2,
|
|
37570
37724
|
maxTokens,
|
|
@@ -37574,43 +37728,60 @@ async function buildClaudeNarrationLlm(env) {
|
|
|
37574
37728
|
});
|
|
37575
37729
|
return { complete, engineLabel: "Claude Code" };
|
|
37576
37730
|
}
|
|
37577
|
-
|
|
37578
|
-
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");
|
|
37579
37783
|
return null;
|
|
37580
|
-
|
|
37581
|
-
env,
|
|
37582
|
-
schema,
|
|
37583
|
-
// Only a model this endpoint actually serves. `/^claude-/` was a PROVIDER-NAME test
|
|
37584
|
-
// standing in for "can this be called": it passed a gateway tier alias or a dated id
|
|
37585
|
-
// straight through (400 → the schema-drop retry → 400 again → every verified run on that
|
|
37586
|
-
// model reporting "the verifier did not return a usable verdict"), and it FAILED
|
|
37587
|
-
// `us.anthropic.claude-*`, silently downgrading a Claude session's grader. The catalog
|
|
37588
|
-
// answers the question the regex was imitating.
|
|
37589
|
-
model: canCallDirectly(model) ? model : DEFAULT_VERIFIER_MODEL,
|
|
37590
|
-
// No `thinking` / `output_config` on purpose: the accepted shape differs per model
|
|
37591
|
-
// generation (adaptive-only, budget_tokens, disabled-at-effort), and a 400 here costs
|
|
37592
|
-
// the whole verification pass. The models we call think by default where it matters.
|
|
37593
|
-
system,
|
|
37594
|
-
content: prompt2,
|
|
37595
|
-
maxTokens,
|
|
37596
|
-
timeoutMs: SMART_TIMEOUT_MS,
|
|
37597
|
-
label: "verifier",
|
|
37598
|
-
// TWO attempts, not three (RV_GRADE_ATTEMPTS). The desktop gives a grade
|
|
37599
|
-
// RV_VERDICT_GRACE_MS before it stops waiting and ends the run itself; a third attempt
|
|
37600
|
-
// plus backoff pushes the sum past it, so the verdict would land after the client had
|
|
37601
|
-
// already moved on — and then dispatch a "continue and finish it" turn into whatever
|
|
37602
|
-
// the user started next.
|
|
37603
|
-
attempts: RV_GRADE_ATTEMPTS,
|
|
37604
|
-
retryOnThrow: true,
|
|
37605
|
-
// The ATTEMPT PLAN, not the client's grace — the two are different numbers on purpose.
|
|
37606
|
-
// The desktop stops waiting at RV_VERDICT_GRACE_MS (180s), ends the run itself, and a
|
|
37607
|
-
// late verdict then dispatches a "continue and finish it" turn on top of whatever the
|
|
37608
|
-
// user started next. The shared constants already encode the gap: 2 x 75s + 4s = 154s of
|
|
37609
|
-
// trying, leaving 26s for the verdict to actually get back and be applied. Budgeting to
|
|
37610
|
-
// the grace itself would spend that margin and land the answer exactly as the client
|
|
37611
|
-
// gives up, which is a race rather than a deadline.
|
|
37612
|
-
budgetMs: RV_GRADE_ATTEMPTS * RV_GRADE_TIMEOUT_MS + RV_GRADE_BACKOFF_MS
|
|
37613
|
-
});
|
|
37784
|
+
};
|
|
37614
37785
|
}
|
|
37615
37786
|
async function buildClaudeVisionLlm(env) {
|
|
37616
37787
|
if (!await hasAnthropicCred(env))
|
|
@@ -37630,7 +37801,7 @@ async function buildClaudeVisionLlm(env) {
|
|
|
37630
37801
|
]
|
|
37631
37802
|
});
|
|
37632
37803
|
}
|
|
37633
|
-
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;
|
|
37634
37805
|
var init_session_usage = __esm({
|
|
37635
37806
|
"../../packages/agent-core/dist/session-usage.js"() {
|
|
37636
37807
|
"use strict";
|
|
@@ -37642,6 +37813,8 @@ var init_session_usage = __esm({
|
|
|
37642
37813
|
FETCH_TIMEOUT_MS = 5e3;
|
|
37643
37814
|
cache4 = null;
|
|
37644
37815
|
TTL_MS = 2e4;
|
|
37816
|
+
schemaUnsupported = /* @__PURE__ */ new Set();
|
|
37817
|
+
schemaKey = (base, model) => `${base}|${model}`;
|
|
37645
37818
|
SMART_TIMEOUT_MS = RV_GRADE_TIMEOUT_MS;
|
|
37646
37819
|
VISION_TIMEOUT_MS = 2e4;
|
|
37647
37820
|
}
|
|
@@ -38088,6 +38261,26 @@ function sessionStoreFor(mode) {
|
|
|
38088
38261
|
function unattendedReportDirective(send4) {
|
|
38089
38262
|
return unattendedModeFor({ optedIn: send4.unattended, origin: send4.origin }) !== "off" ? prompt("agent.system.unattended-report") : "";
|
|
38090
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
|
+
}
|
|
38091
38284
|
function unknownModelEnv(model) {
|
|
38092
38285
|
const id = (model ?? "").trim();
|
|
38093
38286
|
if (!id || /^claude-/i.test(id))
|
|
@@ -38351,8 +38544,8 @@ function taskNotificationNotices(content) {
|
|
|
38351
38544
|
}
|
|
38352
38545
|
if (!text12.includes("<task-notification>"))
|
|
38353
38546
|
return [];
|
|
38354
|
-
const tag = (
|
|
38355
|
-
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);
|
|
38356
38549
|
return m ? m[1].trim() : "";
|
|
38357
38550
|
};
|
|
38358
38551
|
const specs = [];
|
|
@@ -38641,6 +38834,12 @@ function withPinnedSource(sources, pinned) {
|
|
|
38641
38834
|
return sources;
|
|
38642
38835
|
return [...sources, pinned];
|
|
38643
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
|
+
}
|
|
38644
38843
|
function buildMobileClause(dir2) {
|
|
38645
38844
|
try {
|
|
38646
38845
|
let fw = "";
|
|
@@ -38738,6 +38937,8 @@ var init_agent_manager = __esm({
|
|
|
38738
38937
|
init_reinforced_verification();
|
|
38739
38938
|
init_unattended_log();
|
|
38740
38939
|
init_context_recovery();
|
|
38940
|
+
init_model_long_context();
|
|
38941
|
+
init_dist();
|
|
38741
38942
|
init_dist();
|
|
38742
38943
|
init_dist();
|
|
38743
38944
|
init_base_paths();
|
|
@@ -39258,7 +39459,7 @@ var init_agent_manager = __esm({
|
|
|
39258
39459
|
* doing it would spend two turns on one reclaim.
|
|
39259
39460
|
*/
|
|
39260
39461
|
async maybeCompactProactively(live) {
|
|
39261
|
-
const pct2 = (() => {
|
|
39462
|
+
const pct2 = live.autoCompactPct ?? (() => {
|
|
39262
39463
|
try {
|
|
39263
39464
|
return this.autoCompactPct?.();
|
|
39264
39465
|
} catch {
|
|
@@ -39371,6 +39572,13 @@ var init_agent_manager = __esm({
|
|
|
39371
39572
|
this.narrator.setConfig(cfg2);
|
|
39372
39573
|
this.cheapLlm = cfg2?.complete ?? null;
|
|
39373
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
|
+
}
|
|
39374
39582
|
/** Summarize a session transcript into concise Markdown with the injected cheap
|
|
39375
39583
|
* (Haiku) model. Runs in the daemon — the desktop forwards the request rather
|
|
39376
39584
|
* than calling a model itself. Keeps the HEAD + TAIL of a long transcript. */
|
|
@@ -39380,7 +39588,7 @@ var init_agent_manager = __esm({
|
|
|
39380
39588
|
let llm = this.cheapLlm;
|
|
39381
39589
|
if (!llm) {
|
|
39382
39590
|
try {
|
|
39383
|
-
llm = (await buildClaudeNarrationLlm())?.complete ?? null;
|
|
39591
|
+
llm = (await buildClaudeNarrationLlm(this.hostEnv ?? void 0))?.complete ?? null;
|
|
39384
39592
|
} catch {
|
|
39385
39593
|
}
|
|
39386
39594
|
}
|
|
@@ -39577,7 +39785,15 @@ ${full.slice(-8e3)}`;
|
|
|
39577
39785
|
}
|
|
39578
39786
|
const todos = live.todos?.map((t) => ({ content: t.content, status: String(t.status) }));
|
|
39579
39787
|
const call3 = gate === "review" ? reviewGrade(rv, finalText, todos) : gate === "phase" ? phaseGrade(rv, rv.lastVerdict?.phaseName ?? "", finalText, todos) : completenessGrade(rv, finalText, todos);
|
|
39580
|
-
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
|
+
});
|
|
39581
39797
|
if (live.rv !== rv || live.reaped) {
|
|
39582
39798
|
if (live.reaped || live.rv === void 0) {
|
|
39583
39799
|
emitVerification({ action: "done", gate, cycle: rv.cycles, maxCycles: RV_MAX_CYCLES, unavailable: "This run ended before it could be verified." });
|
|
@@ -39655,6 +39871,8 @@ ${full.slice(-8e3)}`;
|
|
|
39655
39871
|
* and the 20-cycle cap silently stops capping anything. */
|
|
39656
39872
|
applyTurnPolicy(live, p) {
|
|
39657
39873
|
live.unattended = unattendedModeFor({ optedIn: p.unattended, origin: p.origin });
|
|
39874
|
+
if (p.autoCompactPct !== void 0)
|
|
39875
|
+
live.autoCompactPct = p.autoCompactPct;
|
|
39658
39876
|
live.autoDecisions = 0;
|
|
39659
39877
|
if (p.model !== void 0)
|
|
39660
39878
|
live.model = p.model || void 0;
|
|
@@ -40361,7 +40579,7 @@ ${lines}`;
|
|
|
40361
40579
|
if (opts.permissionMode)
|
|
40362
40580
|
await live.query.setPermissionMode(opts.permissionMode);
|
|
40363
40581
|
if (opts.model !== void 0) {
|
|
40364
|
-
await live.query.setModel(opts.model
|
|
40582
|
+
await live.query.setModel(sdkModelId(opts.model));
|
|
40365
40583
|
live.model = opts.model || void 0;
|
|
40366
40584
|
}
|
|
40367
40585
|
if (opts.maxThinkingTokens !== void 0)
|
|
@@ -40481,7 +40699,7 @@ ${lines}`;
|
|
|
40481
40699
|
live.windowId = params.windowId;
|
|
40482
40700
|
live.pendingTitle = params.message.trim().slice(0, 80);
|
|
40483
40701
|
if (params.model)
|
|
40484
|
-
void live.query.setModel(params.model
|
|
40702
|
+
void live.query.setModel(sdkModelId(params.model)).catch(() => {
|
|
40485
40703
|
});
|
|
40486
40704
|
if (params.permissionMode)
|
|
40487
40705
|
void live.query.setPermissionMode(params.permissionMode).catch(() => {
|
|
@@ -40656,6 +40874,7 @@ ${prompt("agent.system.project-dir", { dir: projectDir })}` : "";
|
|
|
40656
40874
|
windowId: params.windowId,
|
|
40657
40875
|
sources: params.sources,
|
|
40658
40876
|
unattended: params.unattended,
|
|
40877
|
+
autoCompactPct: params.autoCompactPct,
|
|
40659
40878
|
reinforcedVerification: params.reinforcedVerification,
|
|
40660
40879
|
task: params.message,
|
|
40661
40880
|
rvInjected: params.rvInjected,
|
|
@@ -40721,12 +40940,17 @@ ${prompt("agent.system.project-dir", { dir: projectDir })}` : "";
|
|
|
40721
40940
|
const lateDirective = live.unattendedReportSent ? "" : unattendedReportDirective(params);
|
|
40722
40941
|
if (lateDirective)
|
|
40723
40942
|
live.unattendedReportSent = true;
|
|
40943
|
+
const hostTurn = (params.autoContinuation || params.rvInjected) && !userText.trimStart().startsWith("/");
|
|
40724
40944
|
const sdkMsg = {
|
|
40725
40945
|
type: "user",
|
|
40726
40946
|
parent_tool_use_id: null,
|
|
40727
|
-
|
|
40728
|
-
|
|
40729
|
-
|
|
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
|
+
}
|
|
40730
40954
|
};
|
|
40731
40955
|
live.pump.push(sdkMsg);
|
|
40732
40956
|
}
|
|
@@ -40841,14 +41065,19 @@ ${lateDirective}` : userText }
|
|
|
40841
41065
|
// it. It only *permits* bypass — the active behavior is still governed by
|
|
40842
41066
|
// permissionMode, so it's safe to set unconditionally.
|
|
40843
41067
|
allowDangerouslySkipPermissions: true,
|
|
40844
|
-
|
|
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) } : {},
|
|
40845
41072
|
// Clamp to what THIS CLI accepts — an unsupported level is a hard exit-1, not
|
|
40846
41073
|
// a warning. See clampEffort.
|
|
40847
41074
|
...ultracodeEffort ? { effort: ultracodeEffort } : {},
|
|
40848
41075
|
// Model-level fallback. Ours rotates CREDENTIALS on failure; this rotates the
|
|
40849
41076
|
// MODEL before the turn fails at all, so an overloaded primary degrades instead
|
|
40850
41077
|
// of surfacing an error the user has to act on.
|
|
40851
|
-
|
|
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) } : {},
|
|
40852
41081
|
...params.enableFileCheckpointing ? { enableFileCheckpointing: true } : {},
|
|
40853
41082
|
...params.agentProgressSummaries ? { agentProgressSummaries: true } : {},
|
|
40854
41083
|
...params.includeHookEvents ? { includeHookEvents: true } : {},
|
|
@@ -41448,6 +41677,7 @@ ${lateDirective}` : userText }
|
|
|
41448
41677
|
...params.engineEnv ?? {},
|
|
41449
41678
|
CCB_IPC_PORT: String(live.ipcPort)
|
|
41450
41679
|
};
|
|
41680
|
+
live.endpointEnv = anthropicEnvOf(spawnEnv);
|
|
41451
41681
|
const child = spawn3(options.command, options.args, {
|
|
41452
41682
|
cwd: options.cwd,
|
|
41453
41683
|
env: spawnEnv,
|
|
@@ -42489,6 +42719,11 @@ ${err2.stack}` : ""}` : String(err2);
|
|
|
42489
42719
|
* the stream was actually alive. */
|
|
42490
42720
|
touchStream(live, firstFrame = false) {
|
|
42491
42721
|
live.lastFrameAt = monoNowMs();
|
|
42722
|
+
if (isCompactionPrompt(live.lastPrompt)) {
|
|
42723
|
+
live.stallWindowMs = void 0;
|
|
42724
|
+
this.clearStall(live);
|
|
42725
|
+
return;
|
|
42726
|
+
}
|
|
42492
42727
|
const window2 = firstFrame ? STREAM_FIRST_FRAME_MS : STREAM_STALL_MS;
|
|
42493
42728
|
live.stallWindowMs = window2;
|
|
42494
42729
|
if (!live.streaming) {
|
|
@@ -42533,7 +42768,7 @@ ${err2.stack}` : ""}` : String(err2);
|
|
|
42533
42768
|
this.armStall(live, decision.ms);
|
|
42534
42769
|
return;
|
|
42535
42770
|
}
|
|
42536
|
-
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`);
|
|
42537
42772
|
live.stalled = true;
|
|
42538
42773
|
this.hardKillSession(live);
|
|
42539
42774
|
}
|
|
@@ -43989,10 +44224,10 @@ async function startHostedToolset(deps) {
|
|
|
43989
44224
|
if (asyncTools) {
|
|
43990
44225
|
try {
|
|
43991
44226
|
hostedJobs = await Promise.resolve().then(() => (init_hosted_jobs(), hosted_jobs_exports));
|
|
43992
|
-
const { tmpdir:
|
|
44227
|
+
const { tmpdir: tmpdir9 } = await import("node:os");
|
|
43993
44228
|
const { join: joinPath3 } = await import("node:path");
|
|
43994
44229
|
const made = hostedJobs.createHostedJobRegistry({
|
|
43995
|
-
dir: joinPath3(
|
|
44230
|
+
dir: joinPath3(tmpdir9(), "tesseract-hosted-jobs", randomUUID9()),
|
|
43996
44231
|
notifyModel: deps.notifyModel
|
|
43997
44232
|
});
|
|
43998
44233
|
jobs = made.registry;
|
|
@@ -44059,7 +44294,7 @@ async function startHostedToolset(deps) {
|
|
|
44059
44294
|
await build();
|
|
44060
44295
|
return { endpoint: endpoint2, sendBrowserResponse, tasks, refresh: build };
|
|
44061
44296
|
}
|
|
44062
|
-
function buildHostTaskTools(registry3,
|
|
44297
|
+
function buildHostTaskTools(registry3, run8) {
|
|
44063
44298
|
const text12 = (t, isError = false) => ({ content: [{ type: "text", text: t }], ...isError ? { isError: true } : {} });
|
|
44064
44299
|
return [
|
|
44065
44300
|
{
|
|
@@ -44081,7 +44316,7 @@ function buildHostTaskTools(registry3, run5) {
|
|
|
44081
44316
|
const task = registry3.start("subagent", description);
|
|
44082
44317
|
task.messages.push({ role: "user", content: prompt2 });
|
|
44083
44318
|
try {
|
|
44084
|
-
const out = await
|
|
44319
|
+
const out = await run8(prompt2, { signal: task.abort.signal });
|
|
44085
44320
|
if (task.status === "stopped")
|
|
44086
44321
|
return text12(`Subagent "${description}" was stopped.`, true);
|
|
44087
44322
|
task.status = "done";
|
|
@@ -78701,8 +78936,8 @@ var mesh_ca_exports = {};
|
|
|
78701
78936
|
__export(mesh_ca_exports, {
|
|
78702
78937
|
netCaCommand: () => netCaCommand
|
|
78703
78938
|
});
|
|
78704
|
-
import { chmodSync as chmodSync8, existsSync as
|
|
78705
|
-
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";
|
|
78706
78941
|
import { createInterface } from "node:readline";
|
|
78707
78942
|
function die(msg) {
|
|
78708
78943
|
console.error(msg);
|
|
@@ -78733,7 +78968,7 @@ async function readPassphrase(prompt2) {
|
|
|
78733
78968
|
}
|
|
78734
78969
|
}
|
|
78735
78970
|
function writeSecretFile(p, bytes2) {
|
|
78736
|
-
|
|
78971
|
+
writeFileSync45(p, bytes2, { mode: 384 });
|
|
78737
78972
|
try {
|
|
78738
78973
|
chmodSync8(p, 384);
|
|
78739
78974
|
} catch {
|
|
@@ -78747,9 +78982,9 @@ function ensureDir(p) {
|
|
|
78747
78982
|
}
|
|
78748
78983
|
}
|
|
78749
78984
|
async function openCa(dir2) {
|
|
78750
|
-
const gPath =
|
|
78751
|
-
const sPath =
|
|
78752
|
-
if (!
|
|
78985
|
+
const gPath = join86(dir2, "genesis.bin");
|
|
78986
|
+
const sPath = join86(dir2, "ca.sealed");
|
|
78987
|
+
if (!existsSync48(gPath) || !existsSync48(sPath)) {
|
|
78753
78988
|
die(`No mesh CA in ${dir2}. Run: tesseract-agent net init --org NAME --ca-dir ${dir2}`);
|
|
78754
78989
|
}
|
|
78755
78990
|
const genesisBytes = new Uint8Array(readFileSync50(gPath));
|
|
@@ -78770,7 +79005,7 @@ async function netCaCommand(rest, flags) {
|
|
|
78770
79005
|
if (sub === "init") {
|
|
78771
79006
|
const org = typeof flags.org === "string" ? flags.org.trim() : "";
|
|
78772
79007
|
if (!org) die("Usage: tesseract-agent net init --org NAME [--ca-dir DIR]");
|
|
78773
|
-
if (
|
|
79008
|
+
if (existsSync48(join86(caDir, "ca.sealed"))) {
|
|
78774
79009
|
die(`A mesh CA already exists in ${caDir}. Refusing to overwrite it.`);
|
|
78775
79010
|
}
|
|
78776
79011
|
const pass = await readPassphrase("New CA passphrase: ");
|
|
@@ -78792,9 +79027,9 @@ async function netCaCommand(rest, flags) {
|
|
|
78792
79027
|
const genesisBytes = encodeGenesis(genesis);
|
|
78793
79028
|
const fp = await genesisFingerprint(genesis);
|
|
78794
79029
|
ensureDir(caDir);
|
|
78795
|
-
|
|
78796
|
-
writeSecretFile(
|
|
78797
|
-
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));
|
|
78798
79033
|
console.log(`
|
|
78799
79034
|
Mesh created for "${org}".`);
|
|
78800
79035
|
console.log(` fingerprint: ${hex3(fp)}`);
|
|
@@ -78809,7 +79044,7 @@ Mesh created for "${org}".`);
|
|
|
78809
79044
|
console.log(` ${hex3(disable.secret)}`);
|
|
78810
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");
|
|
78811
79046
|
console.log(`
|
|
78812
|
-
A copy of the disablement secret is in ${
|
|
79047
|
+
A copy of the disablement secret is in ${join86(caDir, "disablement.secret")}.`);
|
|
78813
79048
|
console.log("Move it somewhere the CA directory is not \u2014 holding both in one place");
|
|
78814
79049
|
console.log("defeats the point of having two.");
|
|
78815
79050
|
const caFlag = caDir === resolve13("./mesh-ca") ? "" : ` --ca-dir ${caDir}`;
|
|
@@ -78862,14 +79097,14 @@ Next, issue an identity for a machine (pick a free address in ${formatPrefix(gen
|
|
|
78862
79097
|
[{ keyIndex: 0, privateKey: ca.privateKey }]
|
|
78863
79098
|
);
|
|
78864
79099
|
ensureDir(outDir);
|
|
78865
|
-
|
|
78866
|
-
|
|
78867
|
-
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));
|
|
78868
79103
|
console.log(`Minted "${name}" at ${ip4}.`);
|
|
78869
79104
|
console.log(` ${outDir}`);
|
|
78870
79105
|
console.log("\nCopy that directory to the node and run there:");
|
|
78871
|
-
console.log(` tesseract-agent net enroll --genesis ${
|
|
78872
|
-
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")}`);
|
|
78873
79108
|
console.log("\nnode.key is the node's identity \u2014 send it over a channel you trust, and");
|
|
78874
79109
|
console.log("delete this copy once the node has it.");
|
|
78875
79110
|
return;
|
|
@@ -78905,8 +79140,8 @@ Next, issue an identity for a machine (pick a free address in ${formatPrefix(gen
|
|
|
78905
79140
|
ip4Exceptions: []
|
|
78906
79141
|
};
|
|
78907
79142
|
const signed = await signBundle(bundle, [{ keyIndex: 0, privateKey: ca.privateKey }]);
|
|
78908
|
-
const out = resolve13(typeof flags.out === "string" ? flags.out :
|
|
78909
|
-
|
|
79143
|
+
const out = resolve13(typeof flags.out === "string" ? flags.out : join86(caDir, "bundle.bin"));
|
|
79144
|
+
writeFileSync45(out, encodeSignedBundle(signed));
|
|
78910
79145
|
console.log(`Signed policy bundle (epoch ${epoch2}) \u2192 ${out}`);
|
|
78911
79146
|
console.log("Every node must receive it; the relay distributes it, or copy it to");
|
|
78912
79147
|
console.log(`each node's mesh directory as bundle.bin.`);
|
|
@@ -78928,12 +79163,12 @@ var init_mesh_ca = __esm({
|
|
|
78928
79163
|
|
|
78929
79164
|
// src/cli.ts
|
|
78930
79165
|
init_base_paths();
|
|
78931
|
-
import { existsSync as
|
|
79166
|
+
import { existsSync as existsSync49, mkdtempSync as mkdtempSync4, readFileSync as readFileSync52, rmSync as rmSync13 } from "node:fs";
|
|
78932
79167
|
import { createHash as createHash9 } from "node:crypto";
|
|
78933
|
-
import { execFileSync as execFileSync6, spawn as
|
|
78934
|
-
import { fileURLToPath as
|
|
78935
|
-
import { tmpdir as
|
|
78936
|
-
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";
|
|
78937
79172
|
import { createInterface as createInterface2 } from "node:readline/promises";
|
|
78938
79173
|
|
|
78939
79174
|
// ../../packages/host-core/dist/control-link.js
|
|
@@ -80492,6 +80727,7 @@ async function createClaudeCodeBackend(send4, onBrowserRequest, loadPluginRuntim
|
|
|
80492
80727
|
respondToPermission: (requestId, decision, callerOrigin) => manager2.respondToPermission(requestId, decision, callerOrigin),
|
|
80493
80728
|
setNarrationLlm: (cfg2) => manager2.setNarrationLlm(cfg2),
|
|
80494
80729
|
setVerifierLlm: (fn) => manager2.setVerifierLlm(fn),
|
|
80730
|
+
setHostEnv: (env) => manager2.setHostEnv(env),
|
|
80495
80731
|
setImageGen: (runner3) => manager2.setImageGen(runner3),
|
|
80496
80732
|
setSerpApi: (deps) => manager2.setSerpApi(deps),
|
|
80497
80733
|
setVideoGen: (runner3) => manager2.setVideoGen(runner3),
|
|
@@ -81796,9 +82032,9 @@ function resolveBundledMcpBin(basename14, envOverride) {
|
|
|
81796
82032
|
if (cached3 !== void 0)
|
|
81797
82033
|
return cached3;
|
|
81798
82034
|
const candidates = [];
|
|
81799
|
-
const
|
|
81800
|
-
if (
|
|
81801
|
-
candidates.push(
|
|
82035
|
+
const override3 = envOverride ? process.env[envOverride] : void 0;
|
|
82036
|
+
if (override3)
|
|
82037
|
+
candidates.push(override3);
|
|
81802
82038
|
const rp = process.resourcesPath;
|
|
81803
82039
|
if (rp)
|
|
81804
82040
|
candidates.push(join26(rp, "host-daemon", basename14));
|
|
@@ -83076,7 +83312,7 @@ function createAcpBackend(engine, send4, resolve16, onBrowserRequest, loadPlugin
|
|
|
83076
83312
|
return;
|
|
83077
83313
|
return sendMessage({ ...prev, message, sessionId: sid, autoContinuation: true });
|
|
83078
83314
|
},
|
|
83079
|
-
log: (m) => console.warn(`[${
|
|
83315
|
+
log: (m) => console.warn(`[${LABEL3}] ${m}`)
|
|
83080
83316
|
});
|
|
83081
83317
|
return noticeDispatcher;
|
|
83082
83318
|
};
|
|
@@ -83298,7 +83534,7 @@ function createAcpBackend(engine, send4, resolve16, onBrowserRequest, loadPlugin
|
|
|
83298
83534
|
...cappedOut ? { cappedOut: true } : {}
|
|
83299
83535
|
}, turn.origin);
|
|
83300
83536
|
},
|
|
83301
|
-
log: (m, e) => console.warn(`[${
|
|
83537
|
+
log: (m, e) => console.warn(`[${LABEL3}] ${m}`, e ?? "")
|
|
83302
83538
|
});
|
|
83303
83539
|
});
|
|
83304
83540
|
}
|
|
@@ -83536,7 +83772,7 @@ function createAcpBackend(engine, send4, resolve16, onBrowserRequest, loadPlugin
|
|
|
83536
83772
|
...cappedOut ? { cappedOut: true } : {}
|
|
83537
83773
|
}, turn.origin);
|
|
83538
83774
|
},
|
|
83539
|
-
log: (m, e) => console.warn(`[${
|
|
83775
|
+
log: (m, e) => console.warn(`[${LABEL3}] ${m}`, e ?? "")
|
|
83540
83776
|
});
|
|
83541
83777
|
});
|
|
83542
83778
|
});
|
|
@@ -83589,13 +83825,13 @@ function createAcpBackend(engine, send4, resolve16, onBrowserRequest, loadPlugin
|
|
|
83589
83825
|
agentMcp = agentCaps?.mcpCapabilities;
|
|
83590
83826
|
const authed = await withTimeout2(authenticateIfOffered(t, init?.authMethods), AUTH_TIMEOUT_MS, `${engine.label} did not finish authenticating.`).catch(() => false);
|
|
83591
83827
|
if (init?.authMethods?.length && !authed) {
|
|
83592
|
-
console.warn(`[${
|
|
83828
|
+
console.warn(`[${LABEL3}] no authentication method was accepted; session/load and resume may fail.`);
|
|
83593
83829
|
}
|
|
83594
83830
|
if (apiPort) {
|
|
83595
83831
|
const api = createEngineHttpApi(apiPort, engine.httpApi?.host ?? "127.0.0.1");
|
|
83596
83832
|
httpApi = await api.ready() ? api : null;
|
|
83597
83833
|
if (!httpApi)
|
|
83598
|
-
console.warn(`[${
|
|
83834
|
+
console.warn(`[${LABEL3}] its HTTP API did not come up on ${apiPort}; using the ACP path only.`);
|
|
83599
83835
|
}
|
|
83600
83836
|
} catch (e) {
|
|
83601
83837
|
try {
|
|
@@ -83942,7 +84178,9 @@ ${text12}`);
|
|
|
83942
84178
|
const usage2 = contextUsageFor(live);
|
|
83943
84179
|
const verdict = shouldCompactProactively({
|
|
83944
84180
|
mode: unattendedModeFor({ optedIn: params.unattended, origin: params.origin }),
|
|
83945
|
-
|
|
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,
|
|
83946
84184
|
usagePct: typeof usage2?.percentage === "number" ? usage2.percentage : null,
|
|
83947
84185
|
lastCompactPct: proactiveCompactedAt.get(live) ?? null,
|
|
83948
84186
|
inFlight: false
|
|
@@ -83954,7 +84192,7 @@ ${text12}`);
|
|
|
83954
84192
|
if (verdict !== "compact")
|
|
83955
84193
|
return;
|
|
83956
84194
|
proactiveCompactedAt.set(live, usage2?.percentage ?? 0);
|
|
83957
|
-
console.warn(`[${
|
|
84195
|
+
console.warn(`[${LABEL3}] auto-compact: ${Math.round(usage2?.percentage ?? 0)}% of the window used \u2014 compacting`);
|
|
83958
84196
|
await sendMessage({ ...params, message: OVERFLOW_COMPACT_MESSAGE, sessionId: live, autoContinuation: true });
|
|
83959
84197
|
const now2 = sessionRekey.get(live) ?? live;
|
|
83960
84198
|
if (now2 !== live) {
|
|
@@ -83962,7 +84200,7 @@ ${text12}`);
|
|
|
83962
84200
|
proactiveCompactedAt.delete(live);
|
|
83963
84201
|
}
|
|
83964
84202
|
} catch (err2) {
|
|
83965
|
-
console.warn(`[${
|
|
84203
|
+
console.warn(`[${LABEL3}] auto-compact failed:`, err2 instanceof Error ? err2.message : String(err2));
|
|
83966
84204
|
}
|
|
83967
84205
|
}
|
|
83968
84206
|
async function sendMessage(params) {
|
|
@@ -84281,7 +84519,7 @@ ${detail}` : detail, !overflow);
|
|
|
84281
84519
|
}
|
|
84282
84520
|
}
|
|
84283
84521
|
const declared = declaredCaps;
|
|
84284
|
-
const
|
|
84522
|
+
const LABEL3 = engine.label;
|
|
84285
84523
|
let hostedBoot = null;
|
|
84286
84524
|
async function ensureHostedToolset() {
|
|
84287
84525
|
if (!declared.toolInjection || hostedEndpoint)
|
|
@@ -84313,7 +84551,7 @@ ${detail}` : detail, !overflow);
|
|
|
84313
84551
|
// own permission gate, and it cannot disturb the parent's turn state.
|
|
84314
84552
|
runSubagent: async (prompt2, { signal }) => {
|
|
84315
84553
|
if (!transport || !spawnedCwd)
|
|
84316
|
-
throw new Error(`${
|
|
84554
|
+
throw new Error(`${LABEL3} is not running.`);
|
|
84317
84555
|
const res = await transport.request("session/new", { cwd: spawnedCwd, mcpServers: [] });
|
|
84318
84556
|
const sub = res?.sessionId;
|
|
84319
84557
|
if (!sub)
|
|
@@ -84340,7 +84578,7 @@ ${detail}` : detail, !overflow);
|
|
|
84340
84578
|
hostTasks = ht.tasks;
|
|
84341
84579
|
refreshHostedTools = ht.refresh;
|
|
84342
84580
|
} catch (e) {
|
|
84343
|
-
console.warn(`[${
|
|
84581
|
+
console.warn(`[${LABEL3}] host toolset unavailable:`, e);
|
|
84344
84582
|
}
|
|
84345
84583
|
})();
|
|
84346
84584
|
await hostedBoot;
|
|
@@ -85155,7 +85393,7 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
|
|
|
85155
85393
|
const HOSTED_TOKEN_ENV = "TESSERACT_MCP_TOKEN";
|
|
85156
85394
|
const label = engineById(ENGINE_ID2)?.label ?? "Codex";
|
|
85157
85395
|
const declared = engineById(ENGINE_ID2)?.capabilities ?? {};
|
|
85158
|
-
const
|
|
85396
|
+
const LABEL3 = label;
|
|
85159
85397
|
const lastSendParams = /* @__PURE__ */ new Map();
|
|
85160
85398
|
let noticeDispatcher = null;
|
|
85161
85399
|
const jobNotices = () => {
|
|
@@ -85243,7 +85481,7 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
|
|
|
85243
85481
|
hostTasks = ht.tasks;
|
|
85244
85482
|
refreshHostedTools = ht.refresh;
|
|
85245
85483
|
} catch (e) {
|
|
85246
|
-
console.warn(`[${
|
|
85484
|
+
console.warn(`[${LABEL3}] host toolset unavailable:`, e);
|
|
85247
85485
|
}
|
|
85248
85486
|
})();
|
|
85249
85487
|
await hostedBoot;
|
|
@@ -85769,7 +86007,9 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
|
|
|
85769
86007
|
const usage2 = contextUsageFor(threadId);
|
|
85770
86008
|
const verdict = shouldCompactProactively({
|
|
85771
86009
|
mode: unattendedModeFor({ optedIn: params.unattended, origin: params.origin }),
|
|
85772
|
-
|
|
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,
|
|
85773
86013
|
usagePct: typeof usage2?.percentage === "number" ? usage2.percentage : null,
|
|
85774
86014
|
lastCompactPct: proactiveCompactedAt.get(threadId) ?? null,
|
|
85775
86015
|
inFlight: false
|
|
@@ -85781,10 +86021,10 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
|
|
|
85781
86021
|
if (verdict !== "compact")
|
|
85782
86022
|
return;
|
|
85783
86023
|
proactiveCompactedAt.set(threadId, usage2?.percentage ?? 0);
|
|
85784
|
-
console.warn(`[${
|
|
86024
|
+
console.warn(`[${LABEL3}] auto-compact: ${Math.round(usage2?.percentage ?? 0)}% of the window used \u2014 compacting`);
|
|
85785
86025
|
await sendMessage({ ...params, message: OVERFLOW_COMPACT_MESSAGE, sessionId: threadId, autoContinuation: true });
|
|
85786
86026
|
} catch (err2) {
|
|
85787
|
-
console.warn(`[${
|
|
86027
|
+
console.warn(`[${LABEL3}] auto-compact failed:`, err2 instanceof Error ? err2.message : String(err2));
|
|
85788
86028
|
}
|
|
85789
86029
|
}
|
|
85790
86030
|
async function sendMessage(params) {
|
|
@@ -87243,8 +87483,8 @@ var pluginTtsProviders = [];
|
|
|
87243
87483
|
var loadedGeneration = [];
|
|
87244
87484
|
var loadQueue = Promise.resolve();
|
|
87245
87485
|
function loadPluginRuntime(opts) {
|
|
87246
|
-
const
|
|
87247
|
-
const next = loadQueue.then(
|
|
87486
|
+
const run8 = () => loadPluginRuntimeSerial(opts);
|
|
87487
|
+
const next = loadQueue.then(run8, run8);
|
|
87248
87488
|
loadQueue = next.catch(() => void 0);
|
|
87249
87489
|
return next;
|
|
87250
87490
|
}
|
|
@@ -89957,7 +90197,7 @@ var VoiceControl = class {
|
|
|
89957
90197
|
};
|
|
89958
90198
|
let llm = null;
|
|
89959
90199
|
try {
|
|
89960
|
-
const cfg2 = await buildClaudeNarrationLlm();
|
|
90200
|
+
const cfg2 = await buildClaudeNarrationLlm(daemonEngineEnv());
|
|
89961
90201
|
llm = cfg2?.complete ?? null;
|
|
89962
90202
|
} catch {
|
|
89963
90203
|
}
|
|
@@ -90164,17 +90404,17 @@ async function launchCompanionBrowser() {
|
|
|
90164
90404
|
if (!first) {
|
|
90165
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.');
|
|
90166
90406
|
}
|
|
90167
|
-
const { execFile:
|
|
90168
|
-
const
|
|
90169
|
-
|
|
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());
|
|
90170
90410
|
});
|
|
90171
90411
|
try {
|
|
90172
90412
|
if (process.platform === "darwin")
|
|
90173
|
-
await
|
|
90413
|
+
await run8("open", ["-a", first.launch]);
|
|
90174
90414
|
else if (process.platform === "win32")
|
|
90175
|
-
await
|
|
90415
|
+
await run8("cmd", ["/c", "start", "", first.launch]);
|
|
90176
90416
|
else
|
|
90177
|
-
await
|
|
90417
|
+
await run8(first.launch, []);
|
|
90178
90418
|
} catch (err2) {
|
|
90179
90419
|
throw new Error(`Could not start ${first.name}: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
90180
90420
|
}
|
|
@@ -91434,10 +91674,10 @@ function buildEnhanceChain(spec) {
|
|
|
91434
91674
|
steps.push(`upscale\xD7${f}`);
|
|
91435
91675
|
resizes = true;
|
|
91436
91676
|
}
|
|
91437
|
-
const
|
|
91438
|
-
if (
|
|
91439
|
-
parts.push(`cas=strength=${SHARPEN[
|
|
91440
|
-
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}`);
|
|
91441
91681
|
}
|
|
91442
91682
|
if (spec.deband) {
|
|
91443
91683
|
parts.push("deband");
|
|
@@ -92368,11 +92608,11 @@ function pickProvider(c) {
|
|
|
92368
92608
|
return null;
|
|
92369
92609
|
}
|
|
92370
92610
|
function modelFor(id, pc, quality) {
|
|
92371
|
-
const
|
|
92611
|
+
const override3 = pc.model?.trim();
|
|
92372
92612
|
if (id === "tesseract")
|
|
92373
|
-
return
|
|
92374
|
-
if (
|
|
92375
|
-
return
|
|
92613
|
+
return override3 || FREE_MODEL;
|
|
92614
|
+
if (override3)
|
|
92615
|
+
return override3;
|
|
92376
92616
|
return quality === "standard" ? STANDARD_MODEL : FAST_MODEL;
|
|
92377
92617
|
}
|
|
92378
92618
|
function estimateFor(id, model, durationSec) {
|
|
@@ -93212,8 +93452,8 @@ async function falTopazEnhance(path6, spec, opts) {
|
|
|
93212
93452
|
const dir2 = opts.outDir ?? workDir();
|
|
93213
93453
|
mkdirSync21(dir2, { recursive: true });
|
|
93214
93454
|
const outPath = join42(dir2, "enhanced.mp4");
|
|
93215
|
-
const { writeFileSync:
|
|
93216
|
-
|
|
93455
|
+
const { writeFileSync: writeFileSync46 } = await import("node:fs");
|
|
93456
|
+
writeFileSync46(outPath, Buffer.from(await dl.arrayBuffer()));
|
|
93217
93457
|
const out = await probeMedia(outPath).catch(() => null);
|
|
93218
93458
|
opts.onProgress?.(100, "Enhance complete");
|
|
93219
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}` };
|
|
@@ -95048,17 +95288,25 @@ function buildSharedBackend(engineId) {
|
|
|
95048
95288
|
return b;
|
|
95049
95289
|
backend = b;
|
|
95050
95290
|
refreshDaemonScheduling(b);
|
|
95051
|
-
|
|
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) => {
|
|
95052
95300
|
if (cfg2) {
|
|
95053
95301
|
b.setNarrationLlm?.(cfg2);
|
|
95054
|
-
log(
|
|
95302
|
+
log(`narration: enabled (${runnerEnv?.ANTHROPIC_BASE_URL ?? "api.anthropic.com"})`);
|
|
95055
95303
|
} else
|
|
95056
95304
|
log("narration: disabled \u2014 no Claude creds resolved");
|
|
95057
95305
|
}).catch((e) => log("narration: setup failed:", e instanceof Error ? e.message : String(e)));
|
|
95058
|
-
void buildClaudeSmartLlm().then((fn) => {
|
|
95306
|
+
void buildClaudeSmartLlm(runnerEnv).then((fn) => {
|
|
95059
95307
|
if (fn) {
|
|
95060
95308
|
b.setVerifierLlm?.(fn);
|
|
95061
|
-
log(
|
|
95309
|
+
log(`reinforced-verification: grader enabled (${runnerEnv?.ANTHROPIC_BASE_URL ?? "api.anthropic.com"})`);
|
|
95062
95310
|
} else
|
|
95063
95311
|
log("reinforced-verification: disabled \u2014 no Claude creds resolved");
|
|
95064
95312
|
}).catch((e) => log("reinforced-verification: setup failed:", e instanceof Error ? e.message : String(e)));
|
|
@@ -98827,9 +99075,9 @@ var NodeFsHandler = class {
|
|
|
98827
99075
|
if (this.fsw.closed) {
|
|
98828
99076
|
return;
|
|
98829
99077
|
}
|
|
98830
|
-
const
|
|
99078
|
+
const dirname39 = sysPath.dirname(file2);
|
|
98831
99079
|
const basename14 = sysPath.basename(file2);
|
|
98832
|
-
const parent = this.fsw._getWatchedDir(
|
|
99080
|
+
const parent = this.fsw._getWatchedDir(dirname39);
|
|
98833
99081
|
let prevStats = stats;
|
|
98834
99082
|
if (parent.has(basename14))
|
|
98835
99083
|
return;
|
|
@@ -98856,7 +99104,7 @@ var NodeFsHandler = class {
|
|
|
98856
99104
|
prevStats = newStats2;
|
|
98857
99105
|
}
|
|
98858
99106
|
} catch (error51) {
|
|
98859
|
-
this.fsw._remove(
|
|
99107
|
+
this.fsw._remove(dirname39, basename14);
|
|
98860
99108
|
}
|
|
98861
99109
|
} else if (parent.has(basename14)) {
|
|
98862
99110
|
const at = newStats.atimeMs;
|
|
@@ -103299,8 +103547,8 @@ async function wakeDisplay(log9) {
|
|
|
103299
103547
|
if (process.platform !== "darwin")
|
|
103300
103548
|
return;
|
|
103301
103549
|
try {
|
|
103302
|
-
const { spawn:
|
|
103303
|
-
|
|
103550
|
+
const { spawn: spawn15 } = await import("node:child_process");
|
|
103551
|
+
spawn15("caffeinate", ["-u", "-t", "5"], { detached: true, stdio: "ignore" }).unref();
|
|
103304
103552
|
log9?.("display was asleep \u2014 declared user activity to wake it");
|
|
103305
103553
|
await new Promise((r) => setTimeout(r, 1200));
|
|
103306
103554
|
} catch {
|
|
@@ -104136,9 +104384,9 @@ function hasRdeskPassword() {
|
|
|
104136
104384
|
function verifyRdeskPassword(password) {
|
|
104137
104385
|
if (!password)
|
|
104138
104386
|
return false;
|
|
104139
|
-
const
|
|
104140
|
-
if (
|
|
104141
|
-
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));
|
|
104142
104390
|
try {
|
|
104143
104391
|
const { salt, hash: hash2 } = JSON.parse(readFileSync40(pwFile(), "utf8"));
|
|
104144
104392
|
const got = scryptSync(password, Buffer.from(salt, "hex"), 32);
|
|
@@ -107563,6 +107811,16 @@ var LanDiscovery = class {
|
|
|
107563
107811
|
var _a3;
|
|
107564
107812
|
var requireCjs = createRequire4(import.meta.url);
|
|
107565
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
|
+
}
|
|
107566
107824
|
try {
|
|
107567
107825
|
return requireCjs("@fineguide-tesseract/mesh-core");
|
|
107568
107826
|
} catch (e) {
|
|
@@ -109475,12 +109733,12 @@ function watchForIdentity(deps) {
|
|
|
109475
109733
|
const wait = Math.min(max, Math.round(delay3 * (1 + (random() * 2 - 1) * JITTER)));
|
|
109476
109734
|
timer2 = setTimeout(() => {
|
|
109477
109735
|
timer2 = null;
|
|
109478
|
-
void
|
|
109736
|
+
void run8("backoff");
|
|
109479
109737
|
}, wait);
|
|
109480
109738
|
timer2.unref?.();
|
|
109481
109739
|
delay3 = Math.min(max, Math.round(delay3 * FACTOR));
|
|
109482
109740
|
};
|
|
109483
|
-
async function
|
|
109741
|
+
async function run8(reason) {
|
|
109484
109742
|
if (stopped2 || settled || inFlight2)
|
|
109485
109743
|
return;
|
|
109486
109744
|
inFlight2 = true;
|
|
@@ -109512,10 +109770,10 @@ function watchForIdentity(deps) {
|
|
|
109512
109770
|
return;
|
|
109513
109771
|
delay3 = first;
|
|
109514
109772
|
clear();
|
|
109515
|
-
void
|
|
109773
|
+
void run8(reason);
|
|
109516
109774
|
};
|
|
109517
109775
|
unsubscribe = (deps.subscribe ?? subscribeToWakeSignals)(nudge);
|
|
109518
|
-
void
|
|
109776
|
+
void run8("boot");
|
|
109519
109777
|
return {
|
|
109520
109778
|
ready,
|
|
109521
109779
|
nudge,
|
|
@@ -112114,9 +112372,8 @@ function meshIdOf(cert) {
|
|
|
112114
112372
|
// ../../packages/host-core/dist/mesh/full-tunnel.js
|
|
112115
112373
|
function fullTunnelState(i) {
|
|
112116
112374
|
const no2 = (reason) => ({ allowed: false, reason, warnings: [] });
|
|
112117
|
-
if (i.platform !== "linux") {
|
|
112118
|
-
|
|
112119
|
-
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.`);
|
|
112120
112377
|
}
|
|
112121
112378
|
if (!i.engineAvailable) {
|
|
112122
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.");
|
|
@@ -112169,21 +112426,685 @@ function bundleGrantsExitNode(bundle) {
|
|
|
112169
112426
|
// ../../packages/host-core/dist/mesh/machine-owner.js
|
|
112170
112427
|
init_credentials();
|
|
112171
112428
|
|
|
112172
|
-
// ../../packages/host-core/dist/service/
|
|
112173
|
-
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";
|
|
112174
112443
|
import { promisify as promisify6 } from "node:util";
|
|
112175
112444
|
var run4 = promisify6(execFile10);
|
|
112176
|
-
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) {
|
|
112177
112517
|
return new Promise((resolve16) => {
|
|
112178
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" });
|
|
112179
112613
|
p.on("error", () => resolve16());
|
|
112180
112614
|
p.on("close", () => resolve16());
|
|
112181
112615
|
});
|
|
112182
112616
|
}
|
|
112183
112617
|
|
|
112184
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
|
+
}
|
|
112185
112638
|
var UNIT = "tesseract-netd.service";
|
|
112186
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
|
+
}
|
|
112187
113108
|
|
|
112188
113109
|
// ../../packages/host-core/dist/clipboard/clipboard-sync.js
|
|
112189
113110
|
var MAX_IMAGE_BYTES3 = 10 * 1024 * 1024;
|
|
@@ -112202,24 +113123,24 @@ import { platform as platform6 } from "node:os";
|
|
|
112202
113123
|
|
|
112203
113124
|
// ../../packages/host-core/dist/service/launchd.js
|
|
112204
113125
|
init_credentials();
|
|
112205
|
-
import { writeFileSync as
|
|
112206
|
-
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";
|
|
112207
113128
|
import { homedir as homedir13, userInfo as userInfo2 } from "node:os";
|
|
112208
|
-
function
|
|
113129
|
+
function xml2(s) {
|
|
112209
113130
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
112210
113131
|
}
|
|
112211
113132
|
function makeLaunchd(instanceId) {
|
|
112212
113133
|
const suffix = instanceSuffix(instanceId);
|
|
112213
113134
|
const label = SERVICE_LABEL_BASE + (suffix ? `.${suffix}` : "");
|
|
112214
|
-
const plistPath = () =>
|
|
113135
|
+
const plistPath = () => join81(homedir13(), "Library", "LaunchAgents", `${label}.plist`);
|
|
112215
113136
|
const domainTarget = () => `gui/${userInfo2().uid}`;
|
|
112216
113137
|
const serviceTarget = () => `${domainTarget()}/${label}`;
|
|
112217
|
-
const logFile = () =>
|
|
113138
|
+
const logFile = () => join81(daemonDir2(), "daemon.log");
|
|
112218
113139
|
const workDirOf = (spec) => spec.workingDirectory ?? daemonDir2();
|
|
112219
|
-
function
|
|
112220
|
-
const args = [spec.exec, ...spec.args].map((a) => ` <string>${
|
|
112221
|
-
const env = Object.entries(spec.env).map(([k, v]) => ` <key>${
|
|
112222
|
-
<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");
|
|
112223
113144
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
112224
113145
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
112225
113146
|
<plist version="1.0">
|
|
@@ -112235,7 +113156,7 @@ ${args}
|
|
|
112235
113156
|
${env}
|
|
112236
113157
|
</dict>
|
|
112237
113158
|
<key>WorkingDirectory</key>
|
|
112238
|
-
<string>${
|
|
113159
|
+
<string>${xml2(workDirOf(spec))}</string>
|
|
112239
113160
|
<key>RunAtLoad</key>
|
|
112240
113161
|
<true/>
|
|
112241
113162
|
<key>KeepAlive</key>
|
|
@@ -112250,9 +113171,9 @@ ${env}
|
|
|
112250
113171
|
<key>LimitLoadToSessionType</key>
|
|
112251
113172
|
<string>Aqua</string>
|
|
112252
113173
|
<key>StandardOutPath</key>
|
|
112253
|
-
<string>${
|
|
113174
|
+
<string>${xml2(spec.logPath)}</string>
|
|
112254
113175
|
<key>StandardErrorPath</key>
|
|
112255
|
-
<string>${
|
|
113176
|
+
<string>${xml2(spec.logPath)}</string>
|
|
112256
113177
|
</dict>
|
|
112257
113178
|
</plist>
|
|
112258
113179
|
`;
|
|
@@ -112260,21 +113181,21 @@ ${env}
|
|
|
112260
113181
|
return {
|
|
112261
113182
|
async install(spec) {
|
|
112262
113183
|
mkdirSync41(workDirOf(spec), { recursive: true });
|
|
112263
|
-
mkdirSync41(
|
|
112264
|
-
mkdirSync41(
|
|
112265
|
-
|
|
112266
|
-
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(() => {
|
|
112267
113188
|
});
|
|
112268
|
-
await
|
|
112269
|
-
await
|
|
113189
|
+
await run5("launchctl", ["bootstrap", domainTarget(), plistPath()]);
|
|
113190
|
+
await run5("launchctl", ["enable", serviceTarget()]).catch(() => {
|
|
112270
113191
|
});
|
|
112271
|
-
await
|
|
113192
|
+
await run5("launchctl", ["kickstart", "-k", serviceTarget()]).catch(() => {
|
|
112272
113193
|
});
|
|
112273
113194
|
},
|
|
112274
113195
|
async uninstall() {
|
|
112275
|
-
await
|
|
113196
|
+
await run5("launchctl", ["bootout", serviceTarget()]).catch(() => {
|
|
112276
113197
|
});
|
|
112277
|
-
if (
|
|
113198
|
+
if (existsSync43(plistPath())) {
|
|
112278
113199
|
try {
|
|
112279
113200
|
unlinkSync7(plistPath());
|
|
112280
113201
|
} catch {
|
|
@@ -112285,16 +113206,16 @@ ${env}
|
|
|
112285
113206
|
await this.install(spec);
|
|
112286
113207
|
},
|
|
112287
113208
|
async isInstalled() {
|
|
112288
|
-
return
|
|
113209
|
+
return existsSync43(plistPath());
|
|
112289
113210
|
},
|
|
112290
113211
|
async start() {
|
|
112291
|
-
await
|
|
113212
|
+
await run5("launchctl", ["bootstrap", domainTarget(), plistPath()]).catch(() => {
|
|
112292
113213
|
});
|
|
112293
|
-
await
|
|
113214
|
+
await run5("launchctl", ["kickstart", serviceTarget()]).catch(() => {
|
|
112294
113215
|
});
|
|
112295
113216
|
},
|
|
112296
113217
|
async stop() {
|
|
112297
|
-
await
|
|
113218
|
+
await run5("launchctl", ["bootout", serviceTarget()]).catch(() => {
|
|
112298
113219
|
});
|
|
112299
113220
|
},
|
|
112300
113221
|
async status() {
|
|
@@ -112302,7 +113223,7 @@ ${env}
|
|
|
112302
113223
|
},
|
|
112303
113224
|
async logs(follow) {
|
|
112304
113225
|
const f = logFile();
|
|
112305
|
-
if (!
|
|
113226
|
+
if (!existsSync43(f)) {
|
|
112306
113227
|
console.log(`No log yet at ${f} \u2014 has the service started?`);
|
|
112307
113228
|
return;
|
|
112308
113229
|
}
|
|
@@ -112313,10 +113234,10 @@ ${env}
|
|
|
112313
113234
|
|
|
112314
113235
|
// ../../packages/host-core/dist/service/systemd.js
|
|
112315
113236
|
init_credentials();
|
|
112316
|
-
import { writeFileSync as
|
|
112317
|
-
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";
|
|
112318
113239
|
import { homedir as homedir14, userInfo as userInfo3 } from "node:os";
|
|
112319
|
-
function
|
|
113240
|
+
function unitVal2(v) {
|
|
112320
113241
|
return v.replace(/%/g, "%%");
|
|
112321
113242
|
}
|
|
112322
113243
|
function shq(s) {
|
|
@@ -112326,8 +113247,8 @@ function makeSystemd(instanceId) {
|
|
|
112326
113247
|
const suffix = instanceSuffix(instanceId);
|
|
112327
113248
|
const unit = `tesseract-host${suffix ? `-${suffix}` : ""}.service`;
|
|
112328
113249
|
const unitPath = () => {
|
|
112329
|
-
const base = process.env.XDG_CONFIG_HOME ||
|
|
112330
|
-
return
|
|
113250
|
+
const base = process.env.XDG_CONFIG_HOME || join82(homedir14(), ".config");
|
|
113251
|
+
return join82(base, "systemd", "user", unit);
|
|
112331
113252
|
};
|
|
112332
113253
|
const workDirOf = (spec) => spec.workingDirectory ?? daemonDir2();
|
|
112333
113254
|
function buildUnit2(spec) {
|
|
@@ -112341,7 +113262,7 @@ Wants=network-online.target
|
|
|
112341
113262
|
[Service]
|
|
112342
113263
|
Type=simple
|
|
112343
113264
|
${env}
|
|
112344
|
-
WorkingDirectory=${
|
|
113265
|
+
WorkingDirectory=${unitVal2(workDirOf(spec))}
|
|
112345
113266
|
ExecStart=${execStart}
|
|
112346
113267
|
Restart=on-failure
|
|
112347
113268
|
RestartSec=30
|
|
@@ -112355,40 +113276,40 @@ WantedBy=default.target
|
|
|
112355
113276
|
return {
|
|
112356
113277
|
async install(spec) {
|
|
112357
113278
|
mkdirSync42(workDirOf(spec), { recursive: true });
|
|
112358
|
-
mkdirSync42(
|
|
112359
|
-
mkdirSync42(
|
|
112360
|
-
|
|
112361
|
-
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(() => {
|
|
112362
113283
|
});
|
|
112363
|
-
await
|
|
113284
|
+
await run5("systemctl", ["--user", "daemon-reload"]).catch(() => {
|
|
112364
113285
|
});
|
|
112365
|
-
await
|
|
113286
|
+
await run5("systemctl", ["--user", "enable", unit]).catch(() => {
|
|
112366
113287
|
});
|
|
112367
|
-
await
|
|
113288
|
+
await run5("systemctl", ["--user", "restart", unit]);
|
|
112368
113289
|
},
|
|
112369
113290
|
async uninstall() {
|
|
112370
|
-
await
|
|
113291
|
+
await run5("systemctl", ["--user", "disable", "--now", unit]).catch(() => {
|
|
112371
113292
|
});
|
|
112372
|
-
if (
|
|
113293
|
+
if (existsSync44(unitPath())) {
|
|
112373
113294
|
try {
|
|
112374
113295
|
unlinkSync8(unitPath());
|
|
112375
113296
|
} catch {
|
|
112376
113297
|
}
|
|
112377
113298
|
}
|
|
112378
|
-
await
|
|
113299
|
+
await run5("systemctl", ["--user", "daemon-reload"]).catch(() => {
|
|
112379
113300
|
});
|
|
112380
113301
|
},
|
|
112381
113302
|
async restart(spec) {
|
|
112382
113303
|
await this.install(spec);
|
|
112383
113304
|
},
|
|
112384
113305
|
async isInstalled() {
|
|
112385
|
-
return
|
|
113306
|
+
return existsSync44(unitPath());
|
|
112386
113307
|
},
|
|
112387
113308
|
async start() {
|
|
112388
|
-
await
|
|
113309
|
+
await run5("systemctl", ["--user", "start", unit]);
|
|
112389
113310
|
},
|
|
112390
113311
|
async stop() {
|
|
112391
|
-
await
|
|
113312
|
+
await run5("systemctl", ["--user", "stop", unit]);
|
|
112392
113313
|
},
|
|
112393
113314
|
async status() {
|
|
112394
113315
|
await runInherit("systemctl", ["--user", "status", unit, "--no-pager"]);
|
|
@@ -112401,13 +113322,13 @@ WantedBy=default.target
|
|
|
112401
113322
|
|
|
112402
113323
|
// ../../packages/host-core/dist/service/windows.js
|
|
112403
113324
|
init_credentials();
|
|
112404
|
-
import { writeFileSync as
|
|
112405
|
-
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";
|
|
112406
113327
|
function makeWindowsTask(instanceId) {
|
|
112407
113328
|
const suffix = instanceSuffix(instanceId);
|
|
112408
113329
|
const task = `Fineguide\\TesseractHost${suffix ? `-${suffix}` : ""}`;
|
|
112409
|
-
const wrapperPath = () =>
|
|
112410
|
-
const logFile = () =>
|
|
113330
|
+
const wrapperPath = () => join83(daemonDir2(), `run-host${suffix ? `-${suffix}` : ""}.cmd`);
|
|
113331
|
+
const logFile = () => join83(daemonDir2(), "daemon.log");
|
|
112411
113332
|
const oneLine2 = (s) => s.replace(/[\r\n]+/g, " ");
|
|
112412
113333
|
const envVal = (v) => oneLine2(v).replace(/%/g, "%%").replace(/"/g, "");
|
|
112413
113334
|
const cmdArg = (a) => `"${oneLine2(a).replace(/"/g, "")}"`;
|
|
@@ -112424,17 +113345,17 @@ start "" /b ${cmd} >> "${oneLine2(spec.logPath).replace(/"/g, "")}" 2>&1\r
|
|
|
112424
113345
|
return {
|
|
112425
113346
|
async install(spec) {
|
|
112426
113347
|
mkdirSync43(spec.workingDirectory ?? daemonDir2(), { recursive: true });
|
|
112427
|
-
mkdirSync43(
|
|
112428
|
-
mkdirSync43(
|
|
112429
|
-
|
|
112430
|
-
await
|
|
112431
|
-
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(() => {
|
|
112432
113353
|
});
|
|
112433
113354
|
},
|
|
112434
113355
|
async uninstall() {
|
|
112435
|
-
await
|
|
113356
|
+
await run5("schtasks", ["/Delete", "/TN", task, "/F"]).catch(() => {
|
|
112436
113357
|
});
|
|
112437
|
-
if (
|
|
113358
|
+
if (existsSync45(wrapperPath())) {
|
|
112438
113359
|
try {
|
|
112439
113360
|
unlinkSync9(wrapperPath());
|
|
112440
113361
|
} catch {
|
|
@@ -112446,17 +113367,17 @@ start "" /b ${cmd} >> "${oneLine2(spec.logPath).replace(/"/g, "")}" 2>&1\r
|
|
|
112446
113367
|
},
|
|
112447
113368
|
async isInstalled() {
|
|
112448
113369
|
try {
|
|
112449
|
-
await
|
|
113370
|
+
await run5("schtasks", ["/Query", "/TN", task]);
|
|
112450
113371
|
return true;
|
|
112451
113372
|
} catch {
|
|
112452
113373
|
return false;
|
|
112453
113374
|
}
|
|
112454
113375
|
},
|
|
112455
113376
|
async start() {
|
|
112456
|
-
await
|
|
113377
|
+
await run5("schtasks", ["/Run", "/TN", task]);
|
|
112457
113378
|
},
|
|
112458
113379
|
async stop() {
|
|
112459
|
-
await
|
|
113380
|
+
await run5("schtasks", ["/End", "/TN", task]).catch(() => {
|
|
112460
113381
|
});
|
|
112461
113382
|
},
|
|
112462
113383
|
async status() {
|
|
@@ -112464,7 +113385,7 @@ start "" /b ${cmd} >> "${oneLine2(spec.logPath).replace(/"/g, "")}" 2>&1\r
|
|
|
112464
113385
|
},
|
|
112465
113386
|
async logs(follow) {
|
|
112466
113387
|
const f = logFile();
|
|
112467
|
-
if (!
|
|
113388
|
+
if (!existsSync45(f)) {
|
|
112468
113389
|
console.log(`No log yet at ${f} \u2014 has the task run?`);
|
|
112469
113390
|
return;
|
|
112470
113391
|
}
|
|
@@ -112496,8 +113417,8 @@ init_safe_kill();
|
|
|
112496
113417
|
// src/auth.ts
|
|
112497
113418
|
var import_qrcode_terminal = __toESM(require_main(), 1);
|
|
112498
113419
|
import { randomUUID as randomUUID29 } from "node:crypto";
|
|
112499
|
-
import { existsSync as
|
|
112500
|
-
import { join as
|
|
113420
|
+
import { existsSync as existsSync46, rmSync as rmSync12 } from "node:fs";
|
|
113421
|
+
import { join as join84 } from "node:path";
|
|
112501
113422
|
|
|
112502
113423
|
// src/config.ts
|
|
112503
113424
|
import { hostname as hostname6 } from "node:os";
|
|
@@ -112698,8 +113619,8 @@ async function logout() {
|
|
|
112698
113619
|
}
|
|
112699
113620
|
for (const f of ["credentials.json", "status.json", "daemon.lock"]) {
|
|
112700
113621
|
try {
|
|
112701
|
-
const p =
|
|
112702
|
-
if (
|
|
113622
|
+
const p = join84(daemonDir2(), f);
|
|
113623
|
+
if (existsSync46(p)) rmSync12(p);
|
|
112703
113624
|
} catch {
|
|
112704
113625
|
}
|
|
112705
113626
|
}
|
|
@@ -112719,7 +113640,7 @@ function whoami() {
|
|
|
112719
113640
|
}
|
|
112720
113641
|
|
|
112721
113642
|
// src/self-update.ts
|
|
112722
|
-
import { spawn as
|
|
113643
|
+
import { spawn as spawn13 } from "node:child_process";
|
|
112723
113644
|
import { createPublicKey, verify as cryptoVerify } from "node:crypto";
|
|
112724
113645
|
var RESTART_EXIT_CODE = 75;
|
|
112725
113646
|
var REGISTRY_BASE = "https://registry.npmjs.org/tesseract-agent";
|
|
@@ -112794,7 +113715,7 @@ function installVersion(target) {
|
|
|
112794
113715
|
log8(`installing tesseract-agent@${target} \u2026`);
|
|
112795
113716
|
let child;
|
|
112796
113717
|
try {
|
|
112797
|
-
child =
|
|
113718
|
+
child = spawn13(npm, ["install", "-g", `tesseract-agent@${target}`], { stdio: ["ignore", "inherit", "inherit"] });
|
|
112798
113719
|
} catch (e) {
|
|
112799
113720
|
log8("npm spawn threw:", e instanceof Error ? e.message : String(e));
|
|
112800
113721
|
resolve16(false);
|
|
@@ -112857,9 +113778,9 @@ function startSelfUpdater(current) {
|
|
|
112857
113778
|
}
|
|
112858
113779
|
|
|
112859
113780
|
// src/service.ts
|
|
112860
|
-
import { join as
|
|
113781
|
+
import { join as join85 } from "node:path";
|
|
112861
113782
|
import { platform as platform7 } from "node:os";
|
|
112862
|
-
import { existsSync as
|
|
113783
|
+
import { existsSync as existsSync47, readFileSync as readFileSync49 } from "node:fs";
|
|
112863
113784
|
function controller(instanceId) {
|
|
112864
113785
|
const c = getServiceController(instanceId);
|
|
112865
113786
|
if (!c) {
|
|
@@ -112872,7 +113793,7 @@ function buildSpec(cliEntry) {
|
|
|
112872
113793
|
exec: process.execPath,
|
|
112873
113794
|
args: [cliEntry, "run"],
|
|
112874
113795
|
env: { CCB_DAEMON_DIR: daemonDir2() },
|
|
112875
|
-
logPath:
|
|
113796
|
+
logPath: join85(daemonDir2(), "daemon.log")
|
|
112876
113797
|
};
|
|
112877
113798
|
}
|
|
112878
113799
|
var isAlive = (pid) => {
|
|
@@ -112884,9 +113805,9 @@ var isAlive = (pid) => {
|
|
|
112884
113805
|
}
|
|
112885
113806
|
};
|
|
112886
113807
|
function runningDaemonInfo() {
|
|
112887
|
-
const lock =
|
|
113808
|
+
const lock = join85(daemonDir2(), "daemon.lock");
|
|
112888
113809
|
try {
|
|
112889
|
-
if (!
|
|
113810
|
+
if (!existsSync47(lock)) return null;
|
|
112890
113811
|
const pid = Number(readFileSync49(lock, "utf-8").trim());
|
|
112891
113812
|
if (!pid || !isAlive(pid)) return null;
|
|
112892
113813
|
return { pid, device: readCredentials()?.deviceId };
|
|
@@ -112939,6 +113860,16 @@ function usage() {
|
|
|
112939
113860
|
Join a network. The token is all you need;
|
|
112940
113861
|
the name defaults to this machine's hostname.
|
|
112941
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.
|
|
112942
113873
|
|
|
112943
113874
|
Running a network (needs a signed-in account):
|
|
112944
113875
|
tesseract-agent net new [NAME] Create a network and print its join token.
|
|
@@ -113120,9 +114051,80 @@ async function netCommand(rest, flags) {
|
|
|
113120
114051
|
updateLocal(meshId, { enabled: sub === "up" });
|
|
113121
114052
|
console.log(`${meshId} ${sub === "up" ? "enabled" : "disabled"}`);
|
|
113122
114053
|
}
|
|
113123
|
-
|
|
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.");
|
|
113124
114068
|
return;
|
|
113125
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
|
+
}
|
|
113126
114128
|
if (sub === "join") {
|
|
113127
114129
|
const token3 = rest[1] ?? str2(flags.token);
|
|
113128
114130
|
const code = str2(flags.code);
|
|
@@ -113442,7 +114444,7 @@ async function netCommand(rest, flags) {
|
|
|
113442
114444
|
// src/cli.ts
|
|
113443
114445
|
function pkgVersion() {
|
|
113444
114446
|
try {
|
|
113445
|
-
const p =
|
|
114447
|
+
const p = join87(dirname38(fileURLToPath8(import.meta.url)), "..", "package.json");
|
|
113446
114448
|
return JSON.parse(readFileSync52(p, "utf8")).version ?? "0.0.0";
|
|
113447
114449
|
} catch {
|
|
113448
114450
|
return "0.0.0";
|
|
@@ -113499,7 +114501,7 @@ async function superviseDaemon(cliEntry) {
|
|
|
113499
114501
|
let stopping3 = false;
|
|
113500
114502
|
let child = null;
|
|
113501
114503
|
const spawnWorker = () => {
|
|
113502
|
-
const c =
|
|
114504
|
+
const c = spawn14(process.execPath, [cliEntry, "__worker"], { stdio: "inherit", env: process.env });
|
|
113503
114505
|
child = c;
|
|
113504
114506
|
let settled = false;
|
|
113505
114507
|
const settle = (fn) => {
|
|
@@ -113671,7 +114673,7 @@ async function linkCommand(rest, flags) {
|
|
|
113671
114673
|
process.exit(1);
|
|
113672
114674
|
}
|
|
113673
114675
|
async function captureClaudeSubscription(flags) {
|
|
113674
|
-
const home =
|
|
114676
|
+
const home = mkdtempSync4(join87(tmpdir8(), "tesseract-claude-login-"));
|
|
113675
114677
|
const binary = typeof flags["claude-path"] === "string" ? flags["claude-path"] : process.env.CCB_ENGINE_PATH_CLAUDE_CODE || "claude";
|
|
113676
114678
|
const args = ["auth", "login", "--claudeai"];
|
|
113677
114679
|
if (typeof flags.email === "string") args.push("--email", flags.email);
|
|
@@ -113680,7 +114682,7 @@ async function captureClaudeSubscription(flags) {
|
|
|
113680
114682
|
console.log("Open the authorization URL in any browser; paste the returned code here if Claude asks for it.");
|
|
113681
114683
|
try {
|
|
113682
114684
|
const code = await new Promise((resolveCode, reject) => {
|
|
113683
|
-
const child =
|
|
114685
|
+
const child = spawn14(binary, args, {
|
|
113684
114686
|
env: { ...process.env, CLAUDE_CONFIG_DIR: home },
|
|
113685
114687
|
stdio: "inherit"
|
|
113686
114688
|
});
|
|
@@ -113688,8 +114690,8 @@ async function captureClaudeSubscription(flags) {
|
|
|
113688
114690
|
child.once("close", (exitCode, signal) => resolveCode(signal ? 1 : exitCode ?? 1));
|
|
113689
114691
|
});
|
|
113690
114692
|
if (code !== 0) throw new Error(`Claude sign-in did not complete (exit ${code}).`);
|
|
113691
|
-
const file2 =
|
|
113692
|
-
if (
|
|
114693
|
+
const file2 = join87(home, ".credentials.json");
|
|
114694
|
+
if (existsSync49(file2)) return readFileSync52(file2, "utf8");
|
|
113693
114695
|
if (process.platform === "darwin") {
|
|
113694
114696
|
const value = execFileSync6("security", [
|
|
113695
114697
|
"find-generic-password",
|
|
@@ -113701,7 +114703,7 @@ async function captureClaudeSubscription(flags) {
|
|
|
113701
114703
|
}
|
|
113702
114704
|
throw new Error("Claude reported success but no credentials were captured.");
|
|
113703
114705
|
} finally {
|
|
113704
|
-
|
|
114706
|
+
rmSync13(home, { recursive: true, force: true });
|
|
113705
114707
|
}
|
|
113706
114708
|
}
|
|
113707
114709
|
async function runnerCommand(rest, flags) {
|
|
@@ -113816,7 +114818,7 @@ async function main() {
|
|
|
113816
114818
|
process.env.CCB_DAEMON_DIR = tessPath(`daemon-${instance}`);
|
|
113817
114819
|
}
|
|
113818
114820
|
const force = flags.yes === true || flags.force === true;
|
|
113819
|
-
const cliEntry =
|
|
114821
|
+
const cliEntry = fileURLToPath8(import.meta.url);
|
|
113820
114822
|
switch (cmd) {
|
|
113821
114823
|
case "login":
|
|
113822
114824
|
await login({
|