tesseract-agent 0.10.7 → 0.10.8

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 +85 -23
  2. package/package.json +1 -1
@@ -80,16 +80,25 @@ function deriveSystemDirs(home) {
80
80
  music: join(home, "Music")
81
81
  };
82
82
  }
83
+ function expandTilde(p) {
84
+ if (p === "~")
85
+ return USER_HOME;
86
+ if (p.startsWith("~/") || p.startsWith("~\\"))
87
+ return join(USER_HOME, p.slice(2));
88
+ return p;
89
+ }
83
90
  function memoEnvRoot() {
84
91
  const memo = /* @__PURE__ */ new Map();
85
- return (envVar, fallback) => {
86
- const hit = memo.get(envVar);
92
+ return (envVars, fallback) => {
93
+ const names = Array.isArray(envVars) ? envVars : [envVars];
94
+ const memoKey = names.join("|");
95
+ const hit = memo.get(memoKey);
87
96
  if (hit !== void 0)
88
97
  return hit;
89
- const raw = process.env[envVar];
90
- const value = raw && raw.trim() ? resolve(STARTUP_CWD, raw.trim()) : fallback();
98
+ const raw = names.map((n) => process.env[n]).find((v) => v && v.trim());
99
+ const value = raw ? resolve(STARTUP_CWD, expandTilde(raw.trim())) : fallback();
91
100
  if (!peeking)
92
- memo.set(envVar, value);
101
+ memo.set(memoKey, value);
93
102
  return value;
94
103
  };
95
104
  }
@@ -100,13 +109,30 @@ function homePath(...segments) {
100
109
  return join(USER_HOME, ...segments);
101
110
  }
102
111
  function tesseractHome() {
103
- return envRoot("CCB_TESSERACT_DIR", () => join(USER_HOME, ".tesseract"));
112
+ return envRoot([...TESSERACT_HOME_ENV_VARS], () => join(USER_HOME, ".tesseract"));
113
+ }
114
+ function isAlternateHome() {
115
+ return tesseractHome() !== installedTesseractHome();
116
+ }
117
+ function homeTag() {
118
+ if (!isAlternateHome())
119
+ return "";
120
+ let h = 2166136261;
121
+ const path6 = tesseractHome();
122
+ for (let i = 0; i < path6.length; i++) {
123
+ h ^= path6.charCodeAt(i);
124
+ h = Math.imul(h, 16777619);
125
+ }
126
+ return (h >>> 0).toString(36);
127
+ }
128
+ function installedTesseractHome() {
129
+ return join(USER_HOME, ".tesseract");
104
130
  }
105
131
  function tessPath(...segments) {
106
132
  return join(tesseractHome(), ...segments);
107
133
  }
108
134
  function daemonDir() {
109
- return envRoot("CCB_DAEMON_DIR", () => join(tesseractHome(), "daemon"));
135
+ return envRoot(["TESSERACT_DAEMON_DIR", "CCB_DAEMON_DIR"], () => join(tesseractHome(), "daemon"));
110
136
  }
111
137
  function daemonPath(...segments) {
112
138
  return join(daemonDir(), ...segments);
@@ -140,7 +166,7 @@ function sealBasePaths() {
140
166
  claudeConfigDir();
141
167
  return snapshotBasePaths();
142
168
  }
143
- var STARTUP_CWD, USER_HOME, TEMP_DIR, systemDirs, envRoot, peeking, dropsDir;
169
+ var STARTUP_CWD, USER_HOME, TEMP_DIR, systemDirs, envRoot, peeking, dropsDir, TESSERACT_HOME_ENV_VARS;
144
170
  var init_base_paths = __esm({
145
171
  "../../packages/shared/dist/base-paths.js"() {
146
172
  "use strict";
@@ -151,6 +177,7 @@ var init_base_paths = __esm({
151
177
  envRoot = memoEnvRoot();
152
178
  peeking = false;
153
179
  dropsDir = () => join(systemDirs.downloads, "Tesseract");
180
+ TESSERACT_HOME_ENV_VARS = ["TESSERACT_HOMEDIR", "CCB_TESSERACT_DIR"];
154
181
  }
155
182
  });
156
183
 
@@ -39173,6 +39200,26 @@ var init_agent_manager = __esm({
39173
39200
  * to pick them up (the SDK can't hot-swap mcpServers mid-query). Discarding only forfeits a
39174
39201
  * ~2-3s pre-warm on the next new conversation, and only fires on infrequent plugin/project
39175
39202
  * changes — never on the per-turn hot path. */
39203
+ /**
39204
+ * THE QUERY FACTORY — a test seam, and nothing else.
39205
+ *
39206
+ * `sendMessage` builds its own Query through the SDK, which is why the one thing every stall
39207
+ * watchdog test assumed could not be tested: that a turn ARMS the clock. Those tests arm it by
39208
+ * hand (`touchStream(live, true)`) and assert what it does, so deleting the arming call left the
39209
+ * whole file green while a stalled turn hung forever — the exact outage the watchdog exists to
39210
+ * prevent. The gap was papered over with an empty `it.skip` whose note read "needs a spawn seam
39211
+ * AgentManager does not expose". This is that seam.
39212
+ *
39213
+ * Deliberately narrow: it replaces ONLY the construction of the Query, so everything before it —
39214
+ * policy, arming, session bookkeeping, the option build — is the real code path under test. It is
39215
+ * NOT an extension point: nothing in the app calls it, and a plugin that wants to change how a
39216
+ * turn runs should be an engine backend instead.
39217
+ */
39218
+ queryFactory = query;
39219
+ /** Replace the Query factory (pass null to restore the SDK's). Tests only — see queryFactory. */
39220
+ setQueryFactoryForTests(factory) {
39221
+ this.queryFactory = factory ?? query;
39222
+ }
39176
39223
  setPluginTools(tools) {
39177
39224
  this.pluginTools = tools;
39178
39225
  if (this.warmEmpty)
@@ -41520,7 +41567,7 @@ ${unattendedReportDirective(params)}` : ""), live.sessionId) },
41520
41567
  abortController,
41521
41568
  ...params.sessionId && { resume: params.sessionId }
41522
41569
  };
41523
- live.query = params.warm && params.sessionId ? (await startup({ options: queryOptions })).query(pump) : query({ prompt: pump, options: queryOptions });
41570
+ live.query = params.warm && params.sessionId ? (await startup({ options: queryOptions })).query(pump) : this.queryFactory({ prompt: pump, options: queryOptions });
41524
41571
  } catch (err2) {
41525
41572
  for (const s of live.ipcSockets) {
41526
41573
  try {
@@ -87565,8 +87612,22 @@ import { randomUUID as randomUUID13 } from "node:crypto";
87565
87612
  import { join as join34 } from "node:path";
87566
87613
 
87567
87614
  // ../../packages/host-core/dist/gui/daemon-gui.js
87568
- init_credentials();
87569
87615
  import { join as join33, dirname as dirname14 } from "node:path";
87616
+
87617
+ // ../../packages/shared/dist/debug-mode.js
87618
+ init_base_paths();
87619
+
87620
+ // ../../packages/host-core/dist/service/types.js
87621
+ init_base_paths();
87622
+ var SERVICE_LABEL_BASE = "dev.tesseract.app.host";
87623
+ function instanceSuffix(instanceId) {
87624
+ if (instanceId)
87625
+ return instanceId;
87626
+ return homeTag();
87627
+ }
87628
+
87629
+ // ../../packages/host-core/dist/gui/daemon-gui.js
87630
+ init_credentials();
87570
87631
  import { fileURLToPath as fileURLToPath5 } from "node:url";
87571
87632
  import { spawn as spawn5, spawnSync } from "node:child_process";
87572
87633
  import { existsSync as existsSync14 } from "node:fs";
@@ -87614,13 +87675,16 @@ function createDockPolicy(fx) {
87614
87675
  if (!armed)
87615
87676
  return;
87616
87677
  const want = count > 0 ? "regular" : "accessory";
87617
- if (want === applied)
87678
+ const transition = want !== applied;
87679
+ if (want === "accessory" && !transition)
87618
87680
  return;
87619
87681
  safely("setActivationPolicy", () => fx.setActivationPolicy(want));
87620
87682
  applied = want;
87621
- safely("log", () => fx.log?.(`dock policy \u2192 ${want} (${count} main window${count === 1 ? "" : "s"})`));
87622
- if (want === "regular")
87623
- safely("applyDockIcon", () => fx.applyDockIcon());
87683
+ if (transition) {
87684
+ safely("log", () => fx.log?.(`dock policy \u2192 ${want} (${count} main window${count === 1 ? "" : "s"})`));
87685
+ if (want === "regular")
87686
+ safely("applyDockIcon", () => fx.applyDockIcon());
87687
+ }
87624
87688
  };
87625
87689
  return {
87626
87690
  arm() {
@@ -112141,16 +112205,12 @@ init_credentials();
112141
112205
  import { writeFileSync as writeFileSync40, existsSync as existsSync39, mkdirSync as mkdirSync41, unlinkSync as unlinkSync7 } from "node:fs";
112142
112206
  import { dirname as dirname33, join as join77 } from "node:path";
112143
112207
  import { homedir as homedir13, userInfo as userInfo2 } from "node:os";
112144
-
112145
- // ../../packages/host-core/dist/service/types.js
112146
- var SERVICE_LABEL_BASE = "dev.tesseract.app.host";
112147
-
112148
- // ../../packages/host-core/dist/service/launchd.js
112149
112208
  function xml(s) {
112150
112209
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
112151
112210
  }
112152
112211
  function makeLaunchd(instanceId) {
112153
- const label = SERVICE_LABEL_BASE + (instanceId ? `.${instanceId}` : "");
112212
+ const suffix = instanceSuffix(instanceId);
112213
+ const label = SERVICE_LABEL_BASE + (suffix ? `.${suffix}` : "");
112154
112214
  const plistPath = () => join77(homedir13(), "Library", "LaunchAgents", `${label}.plist`);
112155
112215
  const domainTarget = () => `gui/${userInfo2().uid}`;
112156
112216
  const serviceTarget = () => `${domainTarget()}/${label}`;
@@ -112263,7 +112323,8 @@ function shq(s) {
112263
112323
  return `"${s.replace(/(["\\$`])/g, "\\$1")}"`;
112264
112324
  }
112265
112325
  function makeSystemd(instanceId) {
112266
- const unit = `tesseract-host${instanceId ? `-${instanceId}` : ""}.service`;
112326
+ const suffix = instanceSuffix(instanceId);
112327
+ const unit = `tesseract-host${suffix ? `-${suffix}` : ""}.service`;
112267
112328
  const unitPath = () => {
112268
112329
  const base = process.env.XDG_CONFIG_HOME || join78(homedir14(), ".config");
112269
112330
  return join78(base, "systemd", "user", unit);
@@ -112343,8 +112404,9 @@ init_credentials();
112343
112404
  import { writeFileSync as writeFileSync42, existsSync as existsSync41, mkdirSync as mkdirSync43, unlinkSync as unlinkSync9 } from "node:fs";
112344
112405
  import { dirname as dirname35, join as join79 } from "node:path";
112345
112406
  function makeWindowsTask(instanceId) {
112346
- const task = `Fineguide\\TesseractHost${instanceId ? `-${instanceId}` : ""}`;
112347
- const wrapperPath = () => join79(daemonDir2(), `run-host${instanceId ? `-${instanceId}` : ""}.cmd`);
112407
+ const suffix = instanceSuffix(instanceId);
112408
+ const task = `Fineguide\\TesseractHost${suffix ? `-${suffix}` : ""}`;
112409
+ const wrapperPath = () => join79(daemonDir2(), `run-host${suffix ? `-${suffix}` : ""}.cmd`);
112348
112410
  const logFile = () => join79(daemonDir2(), "daemon.log");
112349
112411
  const oneLine2 = (s) => s.replace(/[\r\n]+/g, " ");
112350
112412
  const envVal = (v) => oneLine2(v).replace(/%/g, "%%").replace(/"/g, "");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tesseract-agent",
3
- "version": "0.10.7",
3
+ "version": "0.10.8",
4
4
  "license": "UNLICENSED",
5
5
  "publishConfig": {
6
6
  "access": "public",