tesseract-agent 0.9.28 → 0.9.30

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.
Files changed (2) hide show
  1. package/dist-bundle/cli.js +197 -67
  2. package/package.json +1 -1
@@ -70555,15 +70555,24 @@ async function restore(dir2, tree) {
70555
70555
  try {
70556
70556
  if (await git(dir2, ["read-tree", tree], { GIT_INDEX_FILE: indexFile }) === null)
70557
70557
  return null;
70558
- const diff = await git(dir2, ["diff-index", "--name-status", tree], { GIT_INDEX_FILE: indexFile });
70558
+ await git(dir2, ["update-index", "--refresh", "-q"], { GIT_INDEX_FILE: indexFile });
70559
+ const diff = await git(dir2, ["diff-index", "-z", "--name-status", tree], { GIT_INDEX_FILE: indexFile });
70559
70560
  const restored = [];
70560
70561
  const recreated = [];
70561
- for (const line of (diff ?? "").split("\n").filter(Boolean)) {
70562
- const [status2, ...rest] = line.split(/\s+/);
70563
- const path6 = rest.join(" ");
70564
- if (!path6)
70562
+ const fields = (diff ?? "").split("\0").filter((f) => f !== "");
70563
+ for (let i = 0; i < fields.length; ) {
70564
+ const code = fields[i++];
70565
+ if (code.startsWith("R") || code.startsWith("C")) {
70566
+ i++;
70567
+ const to = fields[i++];
70568
+ if (to !== void 0)
70569
+ restored.push(to);
70565
70570
  continue;
70566
- (status2.startsWith("D") ? recreated : restored).push(path6);
70571
+ }
70572
+ const path6 = fields[i++];
70573
+ if (path6 === void 0)
70574
+ break;
70575
+ (code.startsWith("D") ? recreated : restored).push(path6);
70567
70576
  }
70568
70577
  if (await git(dir2, ["checkout-index", "-a", "-f"], { GIT_INDEX_FILE: indexFile }) === null)
70569
70578
  return null;
@@ -70581,8 +70590,9 @@ async function preview(dir2, tree) {
70581
70590
  try {
70582
70591
  if (await git(dir2, ["read-tree", tree], { GIT_INDEX_FILE: indexFile }) === null)
70583
70592
  return null;
70584
- const diff = await git(dir2, ["diff-index", "--name-only", tree], { GIT_INDEX_FILE: indexFile });
70585
- return { changed: (diff ?? "").split("\n").filter(Boolean) };
70593
+ await git(dir2, ["update-index", "--refresh", "-q"], { GIT_INDEX_FILE: indexFile });
70594
+ const diff = await git(dir2, ["diff-index", "-z", "--name-only", tree], { GIT_INDEX_FILE: indexFile });
70595
+ return { changed: (diff ?? "").split("\0").filter((f) => f !== "") };
70586
70596
  } finally {
70587
70597
  await rm(tmp, { recursive: true, force: true }).catch(() => {
70588
70598
  });
@@ -71226,26 +71236,42 @@ async function createClaudeCodeBackend(send4, onBrowserRequest, loadPluginRuntim
71226
71236
  const sendWatchingSessions = (msg, origin) => {
71227
71237
  if (msg.type === "chat:complete" && msg.sessionId) {
71228
71238
  const sid = msg.sessionId;
71229
- const seq3 = (claudeTurnSeq.get(sid) ?? 1) - 1;
71230
- if (seq3 >= 0 && claudeSnapshots.treeFor(sid, `claude-user-${seq3}`)) {
71231
- void (async () => {
71239
+ const queue3 = pendingAlias.get(sid);
71240
+ if (queue3?.length) {
71241
+ aliasChain.set(sid, (aliasChain.get(sid) ?? Promise.resolve()).then(async () => {
71242
+ const job = queue3.shift();
71243
+ if (!job)
71244
+ return;
71232
71245
  for (let attempt = 0; attempt < 12; attempt++) {
71233
71246
  const rows = await store.getSessionMessages(sid).catch(() => []);
71234
- const lastUser = [...rows].reverse().find((m) => m.role === "user" && m.uuid)?.uuid;
71235
- if (lastUser) {
71236
- claudeSnapshots.alias(sid, `claude-user-${seq3}`, lastUser);
71247
+ const fresh = rows.find((m) => m.role === "user" && m.uuid && !job.knownUuids.has(m.uuid))?.uuid;
71248
+ if (fresh) {
71249
+ claudeSnapshots.alias(sid, job.key, fresh);
71237
71250
  return;
71238
71251
  }
71239
71252
  await new Promise((r) => setTimeout(r, 200));
71240
71253
  }
71241
- })();
71254
+ }).catch(() => {
71255
+ }).finally(() => {
71256
+ if (!pendingAlias.get(sid)?.length) {
71257
+ pendingAlias.delete(sid);
71258
+ aliasChain.delete(sid);
71259
+ }
71260
+ }));
71242
71261
  }
71243
71262
  }
71244
71263
  if (msg.type === "session:created" && msg.sessionId) {
71245
- claudeSnapshots.transfer(PENDING_SESSION, msg.sessionId);
71246
- claudeSnapshots.forget(PENDING_SESSION);
71247
- claudeTurnSeq.set(msg.sessionId, claudeTurnSeq.get(PENDING_SESSION) ?? 0);
71248
- claudeTurnSeq.delete(PENDING_SESSION);
71264
+ const from = pendingKey(msg.clientRequestId);
71265
+ claudeSnapshots.transfer(from, msg.sessionId);
71266
+ claudeSnapshots.forget(from);
71267
+ claudeTurnSeq.set(msg.sessionId, claudeTurnSeq.get(from) ?? 0);
71268
+ claudeTurnSeq.delete(from);
71269
+ const carried = pendingAlias.get(from);
71270
+ if (carried?.length)
71271
+ pendingAlias.set(msg.sessionId, [...pendingAlias.get(msg.sessionId) ?? [], ...carried]);
71272
+ pendingAlias.delete(from);
71273
+ pendingOpened.delete(from);
71274
+ sweepPending();
71249
71275
  pendingSessionId = msg.sessionId;
71250
71276
  }
71251
71277
  send4(msg, origin);
@@ -71253,7 +71279,24 @@ async function createClaudeCodeBackend(send4, onBrowserRequest, loadPluginRuntim
71253
71279
  const manager2 = new AgentManager2(sendWatchingSessions, onBrowserRequest);
71254
71280
  const claudeSnapshots = createSnapshotStore(join19(daemonDir(), "engine-snapshots", "claude-code.json"));
71255
71281
  const claudeTurnSeq = /* @__PURE__ */ new Map();
71282
+ const pendingAlias = /* @__PURE__ */ new Map();
71283
+ const aliasChain = /* @__PURE__ */ new Map();
71284
+ const ALIAS_QUEUE_CAP = 16;
71256
71285
  const PENDING_SESSION = "\0pending";
71286
+ const pendingKey = (clientRequestId) => clientRequestId ? `${PENDING_SESSION}:${clientRequestId}` : PENDING_SESSION;
71287
+ const pendingOpened = /* @__PURE__ */ new Map();
71288
+ const PENDING_TTL_MS = 5 * 6e4;
71289
+ const sweepPending = () => {
71290
+ const cutoff = Date.now() - PENDING_TTL_MS;
71291
+ for (const [key2, at] of [...pendingOpened]) {
71292
+ if (at > cutoff)
71293
+ continue;
71294
+ pendingOpened.delete(key2);
71295
+ claudeSnapshots.forget(key2);
71296
+ claudeTurnSeq.delete(key2);
71297
+ pendingAlias.delete(key2);
71298
+ }
71299
+ };
71257
71300
  let pendingSessionId;
71258
71301
  const hookBus = new HookBus2();
71259
71302
  manager2.setHookBus(hookBus);
@@ -71324,11 +71367,29 @@ async function createClaudeCodeBackend(send4, onBrowserRequest, loadPluginRuntim
71324
71367
  */
71325
71368
  sendMessage: async (params) => {
71326
71369
  if (params.projectDir && !params.autoContinuation) {
71327
- const key2 = params.sessionId ?? PENDING_SESSION;
71370
+ const key2 = params.sessionId ?? pendingKey(params.clientRequestId);
71371
+ if (!params.sessionId) {
71372
+ pendingOpened.set(key2, Date.now());
71373
+ sweepPending();
71374
+ }
71328
71375
  const seq3 = claudeTurnSeq.get(key2) ?? 0;
71329
71376
  claudeTurnSeq.set(key2, seq3 + 1);
71330
- await claudeSnapshots.take(key2, `claude-user-${seq3}`, params.projectDir).catch(() => {
71377
+ const snapKey = `claude-user-${seq3}`;
71378
+ await claudeSnapshots.take(key2, snapKey, params.projectDir).catch(() => {
71331
71379
  });
71380
+ if (params.sessionId) {
71381
+ const rows = await store.getSessionMessages(params.sessionId).catch(() => []);
71382
+ const known = new Set(rows.filter((m) => m.role === "user" && m.uuid).map((m) => m.uuid));
71383
+ const q = pendingAlias.get(params.sessionId) ?? [];
71384
+ q.push({ key: snapKey, knownUuids: known });
71385
+ while (q.length > ALIAS_QUEUE_CAP)
71386
+ q.shift();
71387
+ pendingAlias.set(params.sessionId, q);
71388
+ } else {
71389
+ const q = pendingAlias.get(key2) ?? [];
71390
+ q.push({ key: snapKey, knownUuids: /* @__PURE__ */ new Set() });
71391
+ pendingAlias.set(key2, q);
71392
+ }
71332
71393
  }
71333
71394
  const result = await manager2.sendMessage(params);
71334
71395
  return result;
@@ -72835,7 +72896,7 @@ function writeManagedMcpHome(engineId, layout, servers, projectDir, baseDir, use
72835
72896
  if (modern || !t.legacyBudget)
72836
72897
  node[t.levelKey] = level;
72837
72898
  else
72838
- node[t.legacyBudget.key] = thinkingBudget === "off" ? 0 : thinkingBudget;
72899
+ node[t.legacyBudget.key] = t.legacyBudget.clamp(model, thinkingBudget === "off" ? 0 : thinkingBudget);
72839
72900
  let parent = settings;
72840
72901
  for (const k of t.overridesPath.slice(0, -1)) {
72841
72902
  const next = parent[k];
@@ -73738,6 +73799,16 @@ var GEMINI_ACP = {
73738
73799
  if (!model.startsWith("gemini-"))
73739
73800
  return true;
73740
73801
  return /^gemini-(?:[3-9]|\d{2,})/.test(model);
73802
+ },
73803
+ clamp: (model, budget) => {
73804
+ const lite = /flash-lite/.test(model ?? "");
73805
+ const pro = /-pro\b/.test(model ?? "");
73806
+ const zeroOk = !pro;
73807
+ const min = pro ? 128 : lite ? 512 : /flash/.test(model ?? "") ? 0 : 512;
73808
+ const max = pro ? 32768 : 24576;
73809
+ if (budget <= 0)
73810
+ return zeroOk ? 0 : min;
73811
+ return Math.min(max, Math.max(min, Math.round(budget)));
73741
73812
  }
73742
73813
  },
73743
73814
  // Non-empty, because an empty match is DISCARDED. `overrideScope: 'core'` matches when
@@ -75727,15 +75798,15 @@ function compactionVerdict(method, p, state3) {
75727
75798
  if (method === "turn/started" && state3.turnId === void 0 && !state3.userTurnOnThread) {
75728
75799
  return tn.id ? { verdict: "claim", turnId: tn.id } : { verdict: "ignore" };
75729
75800
  }
75730
- const id = method === "error" ? String(p.turnId ?? "") : tn.id ?? "";
75731
- if (state3.turnId === void 0 || id !== state3.turnId)
75801
+ const id = String(tn.id ?? p.turnId ?? "");
75802
+ if (state3.turnId === void 0 || !id || id !== state3.turnId)
75732
75803
  return { verdict: "ignore" };
75733
75804
  if (method === "turn/completed")
75734
75805
  return { verdict: tn.status === "completed" ? "ok" : "failed" };
75735
75806
  if (method === "error") {
75736
- return p.willRetry === true ? { verdict: "ignore" } : { verdict: "failed" };
75807
+ return p.willRetry === true ? { verdict: "alive" } : { verdict: "failed" };
75737
75808
  }
75738
- return { verdict: "ignore" };
75809
+ return { verdict: "alive" };
75739
75810
  }
75740
75811
  function approvalPolicyFor(mode) {
75741
75812
  switch (mode) {
@@ -75951,7 +76022,8 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
75951
76022
  const verifyOff = /* @__PURE__ */ new Set();
75952
76023
  const lastTurnDiff = /* @__PURE__ */ new Map();
75953
76024
  const compactWaiters = /* @__PURE__ */ new Map();
75954
- const COMPACT_TIMEOUT_MS = 18e4;
76025
+ const COMPACT_IDLE_MS = 18e4;
76026
+ const COMPACT_CEILING_MS = 9e5;
75955
76027
  const tokenUsage = /* @__PURE__ */ new Map();
75956
76028
  let lastWindow;
75957
76029
  const snapshots = createSnapshotStore(join26(daemonDir2(), "engine-snapshots", "openai-codex.json"));
@@ -76121,6 +76193,7 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
76121
76193
  });
76122
76194
  if (verdict === "claim") {
76123
76195
  pendingCompact.turnId = turnId;
76196
+ pendingCompact.keepAlive();
76124
76197
  return;
76125
76198
  }
76126
76199
  if (verdict === "ok") {
@@ -76131,6 +76204,10 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
76131
76204
  pendingCompact.settle(false);
76132
76205
  return;
76133
76206
  }
76207
+ if (verdict === "alive") {
76208
+ pendingCompact.keepAlive();
76209
+ return;
76210
+ }
76134
76211
  }
76135
76212
  const turn = threadId ? turns.get(threadId) : void 0;
76136
76213
  if (!turn)
@@ -76485,13 +76562,20 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
76485
76562
  return;
76486
76563
  }
76487
76564
  const compacted = await new Promise((resolve17) => {
76565
+ let idle;
76488
76566
  const finish = (ok2) => {
76489
76567
  compactWaiters.delete(threadId);
76490
- clearTimeout(timer2);
76568
+ clearTimeout(idle);
76569
+ clearTimeout(ceiling);
76491
76570
  resolve17(ok2);
76492
76571
  };
76493
- const timer2 = setTimeout(() => finish(false), COMPACT_TIMEOUT_MS);
76494
- compactWaiters.set(threadId, { settle: finish });
76572
+ const arm = () => {
76573
+ clearTimeout(idle);
76574
+ idle = setTimeout(() => finish(false), COMPACT_IDLE_MS);
76575
+ };
76576
+ const ceiling = setTimeout(() => finish(false), COMPACT_CEILING_MS);
76577
+ arm();
76578
+ compactWaiters.set(threadId, { settle: finish, keepAlive: arm });
76495
76579
  });
76496
76580
  if (!compacted) {
76497
76581
  fail3(threadId, params.clientRequestId, `${label} did not finish compacting this conversation in time.`, origin);
@@ -100757,8 +100841,21 @@ async function runDaemon(opts = {}) {
100757
100841
  process.exit(code);
100758
100842
  }
100759
100843
  startSystemEvents({ version: VERSION2, log: (m) => log9(m) });
100760
- process.on("SIGTERM", () => shutdown(0, "signal:SIGTERM"));
100761
- process.on("SIGINT", () => shutdown(0, "signal:SIGINT"));
100844
+ const mergedProcess = opts.merged ?? (process.env.CCB_MERGED_PROCESS === "1" || process.argv.includes("--merged"));
100845
+ const deliberateMergedQuit = () => !!globalThis.__ccbDeliberateQuit;
100846
+ const onTermSignal = (sig) => {
100847
+ if (mergedProcess && !deliberateMergedQuit()) {
100848
+ try {
100849
+ log9(`${sig} received \u2014 IGNORED (merged: always-on app; a rival daemon's takeover must never kill the window)`);
100850
+ snapshotProcs(`${sig}-ignored`);
100851
+ } catch {
100852
+ }
100853
+ return;
100854
+ }
100855
+ shutdown(0, `signal:${sig}`);
100856
+ };
100857
+ process.on("SIGTERM", () => onTermSignal("SIGTERM"));
100858
+ process.on("SIGINT", () => onTermSignal("SIGINT"));
100762
100859
  try {
100763
100860
  process.on("SIGHUP", () => {
100764
100861
  try {
@@ -100795,8 +100892,6 @@ async function runDaemon(opts = {}) {
100795
100892
  try {
100796
100893
  const eapp = electronModule()?.app;
100797
100894
  if (eapp) {
100798
- const mergedProcess = opts.merged ?? (process.env.CCB_MERGED_PROCESS === "1" || process.argv.includes("--merged"));
100799
- const deliberateMergedQuit = () => !!globalThis.__ccbDeliberateQuit;
100800
100895
  eapp.on("before-quit", (e) => {
100801
100896
  if (mergedProcess) {
100802
100897
  if (deliberateMergedQuit()) {
@@ -100925,13 +101020,15 @@ async function runDaemon(opts = {}) {
100925
101020
  log9("local listener failed to start", e.message);
100926
101021
  }
100927
101022
  writeStatus2({ deviceId: deviceId2, connected: false });
100928
- try {
100929
- registerNativeHost({ daemonDir: daemonDir2(), log: log9 });
100930
- } catch {
101023
+ if (ownsMachine) {
101024
+ try {
101025
+ registerNativeHost({ daemonDir: daemonDir2(), log: log9 });
101026
+ } catch {
101027
+ }
100931
101028
  }
100932
101029
  const syncActivity = () => {
100933
101030
  try {
100934
- if (readActivityTrackingEnabled())
101031
+ if (ownsMachine && readActivityTrackingEnabled())
100935
101032
  activityTracker.start();
100936
101033
  else
100937
101034
  activityTracker.stop();
@@ -101615,6 +101712,22 @@ async function runDaemon(opts = {}) {
101615
101712
  log9("mesh app: no daemon owns this machine \u2014 running the node here");
101616
101713
  startMeshes(log9);
101617
101714
  }
101715
+ if (meshAppShouldRun) {
101716
+ let handedBack = false;
101717
+ const handover = setInterval(() => {
101718
+ if (handedBack || !lockHeldByAnother())
101719
+ return;
101720
+ handedBack = true;
101721
+ log9("mesh app: a daemon now owns this machine \u2014 handing the node back to it");
101722
+ try {
101723
+ meshManager().stopAll();
101724
+ meshNode().stop();
101725
+ } catch {
101726
+ }
101727
+ clearInterval(handover);
101728
+ }, 15e3);
101729
+ handover.unref?.();
101730
+ }
101618
101731
  const who = c.userId ? `user ${c.userId}` : "no account (unclaimed machine)";
101619
101732
  log9(`started \u2014 device ${c.deviceId}, ${who}, relay ${c.backendOrigin}, local :${localInfo?.localPort ?? "off"}, version ${VERSION2}`);
101620
101733
  await refresh();
@@ -101696,6 +101809,10 @@ async function listMeshes() {
101696
101809
  const r = await call("/meshes", { method: "GET" });
101697
101810
  return r.ok ? { ok: true, meshes: r.data } : r;
101698
101811
  }
101812
+ async function deleteMesh(args) {
101813
+ const r = await call(`/meshes/${encodeURIComponent(args.meshId)}?confirm=${encodeURIComponent(args.confirm)}`, { method: "DELETE" });
101814
+ return r.ok ? { ok: true, deleted: r.data.deleted } : r;
101815
+ }
101699
101816
  async function createMesh(args = {}) {
101700
101817
  const r = await call("/meshes", {
101701
101818
  method: "POST",
@@ -101739,7 +101856,7 @@ async function enrolWith(requested, post) {
101739
101856
  const sig = await generateSigningKey();
101740
101857
  const staticPrivate = await rawPrivate(stat9.privateKey);
101741
101858
  const sigPrivate = await rawPrivate(sig.privateKey);
101742
- const r = await post(hex4(stat9.publicRaw), hex4(sig.publicRaw));
101859
+ const r = await post(hex4(stat9.publicRaw), hex4(sig.publicRaw), name);
101743
101860
  if (!r.ok)
101744
101861
  return r;
101745
101862
  const cert = fromHexOrB64(r.data.cert);
@@ -101770,13 +101887,13 @@ async function enrolWith(requested, post) {
101770
101887
  };
101771
101888
  }
101772
101889
  async function enrol(args) {
101773
- return enrolWith(args.name, (staticPub, sigPub) => call(`/meshes/${encodeURIComponent(args.meshId)}/nodes`, {
101890
+ return enrolWith(args.name, (staticPub, sigPub, name) => call(`/meshes/${encodeURIComponent(args.meshId)}/nodes`, {
101774
101891
  method: "POST",
101775
- body: { name: args.name, staticPub, sigPub }
101892
+ body: { name, staticPub, sigPub }
101776
101893
  }));
101777
101894
  }
101778
101895
  async function joinWithToken(args) {
101779
- return enrolWith(args.name, async (staticPub, sigPub) => postJoin(args.origin, { token: args.token, name: args.name, staticPub, sigPub }));
101896
+ return enrolWith(args.name, async (staticPub, sigPub, name) => postJoin(args.origin, { token: args.token, name, staticPub, sigPub }));
101780
101897
  }
101781
101898
  async function postJoin(origin, body) {
101782
101899
  const base = origin ?? readCredentials()?.apiOrigin;
@@ -101807,7 +101924,7 @@ async function postJoin(origin, body) {
101807
101924
  return { ok: true, data: JSON.parse(text9) };
101808
101925
  }
101809
101926
  async function enrolWithCode(args) {
101810
- return enrolWith(args.name, async (staticPub, sigPub) => postJoin(args.origin, { code: args.code, name: args.name, staticPub, sigPub }));
101927
+ return enrolWith(args.name, async (staticPub, sigPub, name) => postJoin(args.origin, { code: args.code, name, staticPub, sigPub }));
101811
101928
  }
101812
101929
  async function rawPrivate(key2) {
101813
101930
  const pkcs8 = new Uint8Array(await crypto.subtle.exportKey("pkcs8", key2));
@@ -101835,6 +101952,22 @@ function meshIdOf(cert) {
101835
101952
  // ../../packages/host-core/dist/mesh/netd-client.js
101836
101953
  var MAX_LINE = 1024 * 1024;
101837
101954
 
101955
+ // ../../packages/host-core/dist/service/exec.js
101956
+ import { execFile as execFile10, spawn as spawn14 } from "node:child_process";
101957
+ import { promisify as promisify6 } from "node:util";
101958
+ var run4 = promisify6(execFile10);
101959
+ function runInherit(cmd, args) {
101960
+ return new Promise((resolve16) => {
101961
+ const p = spawn14(cmd, args, { stdio: "inherit" });
101962
+ p.on("error", () => resolve16());
101963
+ p.on("close", () => resolve16());
101964
+ });
101965
+ }
101966
+
101967
+ // ../../packages/host-core/dist/net-service/systemd-system.js
101968
+ var UNIT = "tesseract-netd.service";
101969
+ var UNIT_PATH = `/etc/systemd/system/${UNIT}`;
101970
+
101838
101971
  // ../../packages/host-core/dist/host-daemon-entry.js
101839
101972
  init_credentials();
101840
101973
 
@@ -101851,18 +101984,6 @@ import { writeFileSync as writeFileSync39, existsSync as existsSync36, mkdirSync
101851
101984
  import { dirname as dirname28, join as join71 } from "node:path";
101852
101985
  import { homedir as homedir12, userInfo as userInfo2 } from "node:os";
101853
101986
 
101854
- // ../../packages/host-core/dist/service/exec.js
101855
- import { execFile as execFile10, spawn as spawn14 } from "node:child_process";
101856
- import { promisify as promisify6 } from "node:util";
101857
- var run4 = promisify6(execFile10);
101858
- function runInherit(cmd, args) {
101859
- return new Promise((resolve16) => {
101860
- const p = spawn14(cmd, args, { stdio: "inherit" });
101861
- p.on("error", () => resolve16());
101862
- p.on("close", () => resolve16());
101863
- });
101864
- }
101865
-
101866
101987
  // ../../packages/host-core/dist/service/types.js
101867
101988
  var SERVICE_LABEL_BASE = "dev.tesseract.app.host";
101868
101989
 
@@ -102147,10 +102268,6 @@ function getServiceController(instanceId) {
102147
102268
  }
102148
102269
  }
102149
102270
 
102150
- // ../../packages/host-core/dist/net-service/systemd-system.js
102151
- var UNIT = "tesseract-netd.service";
102152
- var UNIT_PATH = `/etc/systemd/system/${UNIT}`;
102153
-
102154
102271
  // ../../packages/host-core/dist/index.js
102155
102272
  init_dist();
102156
102273
  init_serpapi_runner();
@@ -102611,6 +102728,8 @@ Running a network (needs a signed-in account):
102611
102728
  tesseract-agent net token MESH [--rotate] Show the join token again, or replace it
102612
102729
  tesseract-agent net approve MESH NODE Let a waiting machine on
102613
102730
  tesseract-agent net remove MESH NODE Cut a machine off for good
102731
+ tesseract-agent net destroy MESH --confirm NAME
102732
+ Delete a network for good. Irreversible.
102614
102733
  tesseract-agent net code new MESH [--uses N] [--ttl MIN] [--json]
102615
102734
  A ONE-SHOT code, for anyone who wants one
102616
102735
  tesseract-agent net join-me MESH [--name N]
@@ -102805,10 +102924,6 @@ async function netCommand(rest, flags) {
102805
102924
  if (r.name !== name) {
102806
102925
  console.log(`(another machine on this network is already called "${name}")`);
102807
102926
  }
102808
- console.log(`
102809
- Six-word check \u2014 these must match on your admin's screen:`);
102810
- console.log(` ${r.sas.join(" ")}
102811
- `);
102812
102927
  if (!r.approved) {
102813
102928
  console.log("This network requires an admin to approve new machines.");
102814
102929
  console.log("You are enrolled and waiting \u2014 nothing else to do on this machine.");
@@ -102858,6 +102973,25 @@ Six-word check \u2014 these must match on your admin's screen:`);
102858
102973
  }
102859
102974
  return;
102860
102975
  }
102976
+ if (sub === "destroy" || sub === "mesh" && rest[1] === "delete") {
102977
+ const meshId = sub === "destroy" ? rest[1] : rest[2];
102978
+ const confirm2 = str2(flags.confirm);
102979
+ if (!meshId) {
102980
+ console.error("net destroy: name the network \u2014 tesseract-agent net destroy <ID> --confirm <NAME>");
102981
+ process.exit(1);
102982
+ }
102983
+ if (!confirm2) {
102984
+ console.error("net destroy: pass --confirm with the network's exact name. This cannot be undone.");
102985
+ process.exit(1);
102986
+ }
102987
+ const r = await deleteMesh({ meshId, confirm: confirm2 });
102988
+ if (!r.ok) {
102989
+ console.error(`net destroy: ${r.detail}`);
102990
+ process.exit(1);
102991
+ }
102992
+ console.log(`Deleted "${r.deleted}". Every machine that was on it now holds a certificate for a network that no longer exists.`);
102993
+ return;
102994
+ }
102861
102995
  if (sub === "new" || sub === "mesh" && rest[1] === "create") {
102862
102996
  const name = sub === "new" ? rest[1] : str2(flags.name);
102863
102997
  const approve = str2(flags.approve);
@@ -102993,10 +103127,6 @@ Six-word check \u2014 these must match on your admin's screen:`);
102993
103127
  }
102994
103128
  console.log(`Joined ${r.meshId} as "${r.name}" \u2014 this machine is ${r.overlayIp4}.`);
102995
103129
  if (r.name !== nm) console.log(`(another machine here is already called "${nm}")`);
102996
- console.log(`
102997
- Six-word check:
102998
- ${r.sas.join(" ")}
102999
- `);
103000
103130
  return;
103001
103131
  }
103002
103132
  if (sub === "peers") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tesseract-agent",
3
- "version": "0.9.28",
3
+ "version": "0.9.30",
4
4
  "license": "UNLICENSED",
5
5
  "publishConfig": {
6
6
  "access": "public",