@zixt/host 0.0.11 → 0.0.12

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/index.js +365 -88
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -31,7 +31,7 @@ import { homedir } from "node:os";
31
31
  // package.json
32
32
  var package_default = {
33
33
  name: "@zixt/host",
34
- version: "0.0.11",
34
+ version: "0.0.12",
35
35
  type: "module",
36
36
  exports: {
37
37
  ".": "./src/client.ts",
@@ -15047,6 +15047,15 @@ var TaskRunnerSelection = external_exports.object({
15047
15047
  model: runnerModel,
15048
15048
  effort: TaskRunnerEffort.optional()
15049
15049
  }).strict();
15050
+ var RunnerRuntimeBase = {
15051
+ type: RunnerType,
15052
+ /** Resolved model id as the CLI reports it (`gpt-5.6-sol`, `claude-opus-5`). */
15053
+ model: external_exports.string().min(1).max(120).refine(isSafeSingleLineDisplayText, "model must be a single display line").nullable(),
15054
+ /** Resolved reasoning effort; the CLI's own default when nothing was set. */
15055
+ effort: external_exports.string().min(1).max(40).refine(isSafeSingleLineDisplayText, "effort must be a single display line").nullable()
15056
+ };
15057
+ var TaskRunnerRuntimeObservation = external_exports.object(RunnerRuntimeBase).strict();
15058
+ var TaskRunnerRuntime = external_exports.object({ ...RunnerRuntimeBase, observedAt: IsoDate2 }).strict();
15050
15059
  var RunnerConfig = external_exports.discriminatedUnion("type", [
15051
15060
  external_exports.object({
15052
15061
  type: external_exports.literal("claude-code"),
@@ -15840,6 +15849,12 @@ var Task = external_exports.object({
15840
15849
  requestedHostId: HostId.nullable().default(null),
15841
15850
  /** TS-16: per-Task runner/model/effort selection; null runs the teammate's configuration. */
15842
15851
  runner: TaskRunnerSelection.nullable().default(null),
15852
+ /**
15853
+ * TS-16: what the runner CLI actually used on its newest attempt, as the
15854
+ * CLI itself reported it. Null until a run starts (or when the Machine
15855
+ * could not read the CLI's record), and replaced on every new attempt.
15856
+ */
15857
+ runnerRuntime: TaskRunnerRuntime.nullable().default(null),
15843
15858
  disposition: TaskDisposition.nullable(),
15844
15859
  /** Follow-ups accepted but not yet folded into a run; the thread renders
15845
15860
  * exactly this many trailing prompts as queued rather than answered. */
@@ -18320,6 +18335,12 @@ var TaskWorkingContextReport = external_exports.object({
18320
18335
  epoch: external_exports.number().int().min(1),
18321
18336
  context: TaskWorkingContextObservation
18322
18337
  });
18338
+ var TaskRunnerRuntimeReport = external_exports.object({
18339
+ type: external_exports.literal("task.runner_runtime"),
18340
+ taskId: TaskId,
18341
+ epoch: external_exports.number().int().min(1),
18342
+ runtime: TaskRunnerRuntimeObservation
18343
+ });
18323
18344
  var TaskTitle = external_exports.object({
18324
18345
  type: external_exports.literal("task.title"),
18325
18346
  taskId: TaskId,
@@ -18401,6 +18422,7 @@ var AgentOpRequest = external_exports.object({
18401
18422
  var UpMessage = external_exports.discriminatedUnion("type", [
18402
18423
  TaskEvent,
18403
18424
  TaskWorkingContextReport,
18425
+ TaskRunnerRuntimeReport,
18404
18426
  TaskTitle,
18405
18427
  TaskResult,
18406
18428
  HostReport,
@@ -18440,7 +18462,9 @@ var HelloAckFrame = external_exports.object({
18440
18462
  features: external_exports.object({
18441
18463
  browserSessions: external_exports.literal(true).optional(),
18442
18464
  /** Host may send task.working_context only after this advertisement. */
18443
- taskWorkingContext: external_exports.literal(true).optional()
18465
+ taskWorkingContext: external_exports.literal(true).optional(),
18466
+ /** Host may send task.runner_runtime only after this advertisement. */
18467
+ taskRunnerRuntime: external_exports.literal(true).optional()
18444
18468
  }).optional(),
18445
18469
  /**
18446
18470
  * Workspace paths configured for this organization's teammates. The Machine
@@ -19382,6 +19406,7 @@ var HostClient = class _HostClient {
19382
19406
  /** True only after the connected cloud's helloAck advertised the feature. */
19383
19407
  browserFeatureActive = false;
19384
19408
  workingContextFeatureActive = false;
19409
+ runnerRuntimeFeatureActive = false;
19385
19410
  /** TCP open is not protocol authority; only the current helloAck opens upstream delivery. */
19386
19411
  protocolReady = false;
19387
19412
  /** Workspace paths this organization configured, as of the last hello/update. */
@@ -19419,6 +19444,7 @@ var HostClient = class _HostClient {
19419
19444
  this.protocolReady = false;
19420
19445
  this.browserFeatureActive = false;
19421
19446
  this.workingContextFeatureActive = false;
19447
+ this.runnerRuntimeFeatureActive = false;
19422
19448
  this.opts.browser?.attach(null);
19423
19449
  await Promise.allSettled([
19424
19450
  this.unwindAllRuns("host client stopped", "client_shutdown"),
@@ -19678,6 +19704,7 @@ var HostClient = class _HostClient {
19678
19704
  if (this.ws !== void 0) return;
19679
19705
  this.browserFeatureActive = false;
19680
19706
  this.workingContextFeatureActive = false;
19707
+ this.runnerRuntimeFeatureActive = false;
19681
19708
  this.opts.browser?.attach(null);
19682
19709
  void this.opts.browser?.closeAll("machine_offline");
19683
19710
  if (code === CLOSE_CODES.revoked) {
@@ -19706,13 +19733,13 @@ var HostClient = class _HostClient {
19706
19733
  );
19707
19734
  if (this.stopped) return;
19708
19735
  if (!this.stopped && this.opts.reconnect !== false) {
19709
- const delay2 = reconnectBackoffDelay(this.reconnectFailures, this.opts.backoffMs);
19736
+ const delay4 = reconnectBackoffDelay(this.reconnectFailures, this.opts.backoffMs);
19710
19737
  this.reconnectFailures++;
19711
19738
  if (this.reconnectTimer) clearTimeout(this.reconnectTimer);
19712
19739
  this.reconnectTimer = setTimeout(() => {
19713
19740
  this.reconnectTimer = void 0;
19714
19741
  this.connect();
19715
- }, delay2);
19742
+ }, delay4);
19716
19743
  } else {
19717
19744
  this.stopped = true;
19718
19745
  }
@@ -19743,7 +19770,7 @@ var HostClient = class _HostClient {
19743
19770
  this.send(frame);
19744
19771
  }
19745
19772
  replaceablePendingUp(message) {
19746
- return message.type === "host.report" || message.type === "task.working_context" || message.type === "task.title" || message.type === "task.event" && message.event.ephemeral === true;
19773
+ return message.type === "host.report" || message.type === "task.working_context" || message.type === "task.runner_runtime" || message.type === "task.title" || message.type === "task.event" && message.event.ephemeral === true;
19747
19774
  }
19748
19775
  supersedesPendingUp(candidate, incoming) {
19749
19776
  if (candidate.type !== incoming.type) return false;
@@ -19754,7 +19781,7 @@ var HostClient = class _HostClient {
19754
19781
  if (incoming.type === "agent.op") {
19755
19782
  return candidate.type === "agent.op" && candidate.taskId === incoming.taskId && candidate.epoch === incoming.epoch && candidate.requestId === incoming.requestId;
19756
19783
  }
19757
- if (incoming.type === "task.working_context" || incoming.type === "task.title") {
19784
+ if (incoming.type === "task.working_context" || incoming.type === "task.runner_runtime" || incoming.type === "task.title") {
19758
19785
  return candidate.type === incoming.type && candidate.taskId === incoming.taskId && candidate.epoch === incoming.epoch;
19759
19786
  }
19760
19787
  return false;
@@ -19914,6 +19941,7 @@ var HostClient = class _HostClient {
19914
19941
  this.configuredWorkspaces = frame.workspaces ?? [];
19915
19942
  this.browserFeatureActive = frame.features?.browserSessions === true;
19916
19943
  this.workingContextFeatureActive = frame.features?.taskWorkingContext === true;
19944
+ this.runnerRuntimeFeatureActive = frame.features?.taskRunnerRuntime === true;
19917
19945
  if (this.browserFeatureActive && this.opts.browser) {
19918
19946
  this.opts.browser.attach({
19919
19947
  state: (state, openRequestId) => this.sendBrowserFrame({
@@ -20397,6 +20425,21 @@ var HostClient = class _HostClient {
20397
20425
  throw new Error("Working-context evidence could not be delivered before execution.");
20398
20426
  }
20399
20427
  };
20428
+ const emitRunnerRuntime = (runtime) => {
20429
+ if (!this.runnerRuntimeFeatureActive) return;
20430
+ const parsed = TaskRunnerRuntimeObservation.safeParse({
20431
+ type: runtime.type,
20432
+ model: runtime.model === null ? null : safe(runtime.model, 120),
20433
+ effort: runtime.effort === null ? null : safe(runtime.effort, 40)
20434
+ });
20435
+ if (!parsed.success) return;
20436
+ this.sendUp({
20437
+ type: "task.runner_runtime",
20438
+ taskId: assign.taskId,
20439
+ epoch: assign.epoch,
20440
+ runtime: parsed.data
20441
+ });
20442
+ };
20400
20443
  const secrets = () => {
20401
20444
  if (authorityController.signal.aborted) return Promise.resolve({});
20402
20445
  const entry = this.secretGrants.get(cancelKey) ?? { resolvers: [] };
@@ -20723,6 +20766,7 @@ var HostClient = class _HostClient {
20723
20766
  spec: assign.spec,
20724
20767
  event: emitEvent,
20725
20768
  workingContext: emitWorkingContext,
20769
+ runnerRuntime: emitRunnerRuntime,
20726
20770
  siblingTasks: () => [...this.liveTasks.values()].filter((live) => live.agentId === assign.agentId && live.taskId !== assign.taskId).map(({ taskId, title }) => ({ taskId, title })),
20727
20771
  fetchAttachment: (attachmentId) => this.fetchAttachment(attachmentId, authorityController.signal),
20728
20772
  secrets,
@@ -24403,7 +24447,7 @@ var BrowserManager = class {
24403
24447
  session.pendingFrame = frame;
24404
24448
  if (session.frameTimer) return;
24405
24449
  const elapsed = Date.now() - session.lastFrameSentAt;
24406
- const delay2 = Math.max(0, this.frameMinIntervalMs - elapsed);
24450
+ const delay4 = Math.max(0, this.frameMinIntervalMs - elapsed);
24407
24451
  session.frameTimer = setTimeout(() => {
24408
24452
  session.frameTimer = null;
24409
24453
  const pending = session.pendingFrame;
@@ -24418,7 +24462,7 @@ var BrowserManager = class {
24418
24462
  width: pending.width,
24419
24463
  height: pending.height
24420
24464
  });
24421
- }, delay2);
24465
+ }, delay4);
24422
24466
  session.frameTimer.unref?.();
24423
24467
  }
24424
24468
  markActivity(agentId) {
@@ -33376,7 +33420,10 @@ function createCliRunner(adapter, opts = {}) {
33376
33420
  // The trusted workspace facts describe where Zixt put provider clones,
33377
33421
  // which is always the Zixt-owned root — never a configured workspace.
33378
33422
  taskRoot,
33379
- cwd
33423
+ cwd,
33424
+ command: resolvedCommand,
33425
+ commandPrefixArgs: prefixArgs,
33426
+ env
33380
33427
  });
33381
33428
  const runEnv = prepared.env ? { ...env, ...prepared.env } : env;
33382
33429
  let attachmentSection = "";
@@ -34064,6 +34111,171 @@ function runCliProcess(options) {
34064
34111
 
34065
34112
  // src/runners/claude-code.ts
34066
34113
  import { randomUUID as randomUUID11 } from "node:crypto";
34114
+
34115
+ // src/runners/runtime-observation.ts
34116
+ import { open as open5, readdir as readdir4, realpath as realpath8 } from "node:fs/promises";
34117
+ import { homedir as homedir5 } from "node:os";
34118
+ import { join as join15 } from "node:path";
34119
+ var READ_WINDOW_BYTES = 1024 * 1024;
34120
+ var CATALOG_TIMEOUT_MS = 15e3;
34121
+ var CATALOG_OUTPUT_LIMIT_BYTES = 4 * 1024 * 1024;
34122
+ function homeFrom(env) {
34123
+ return env["HOME"] || env["USERPROFILE"] || homedir5();
34124
+ }
34125
+ async function readHead(path) {
34126
+ let handle;
34127
+ try {
34128
+ handle = await open5(path, "r");
34129
+ const buffer = Buffer.alloc(READ_WINDOW_BYTES);
34130
+ const { bytesRead } = await handle.read(buffer, 0, READ_WINDOW_BYTES, 0);
34131
+ return buffer.subarray(0, bytesRead).toString("utf8");
34132
+ } catch {
34133
+ return "";
34134
+ } finally {
34135
+ await handle?.close().catch(() => {
34136
+ });
34137
+ }
34138
+ }
34139
+ async function readTail(path) {
34140
+ let handle;
34141
+ try {
34142
+ handle = await open5(path, "r");
34143
+ const { size } = await handle.stat();
34144
+ const start = Math.max(0, size - READ_WINDOW_BYTES);
34145
+ const length = Math.min(size, READ_WINDOW_BYTES);
34146
+ const buffer = Buffer.alloc(length);
34147
+ const { bytesRead } = await handle.read(buffer, 0, length, start);
34148
+ const text = buffer.subarray(0, bytesRead).toString("utf8");
34149
+ return start === 0 ? text : text.slice(text.indexOf("\n") + 1);
34150
+ } catch {
34151
+ return "";
34152
+ } finally {
34153
+ await handle?.close().catch(() => {
34154
+ });
34155
+ }
34156
+ }
34157
+ function parseLines(text) {
34158
+ const records = [];
34159
+ for (const line of text.split(/\r?\n/)) {
34160
+ if (!line.trim()) continue;
34161
+ try {
34162
+ const value = JSON.parse(line);
34163
+ if (value && typeof value === "object") records.push(value);
34164
+ } catch {
34165
+ }
34166
+ }
34167
+ return records;
34168
+ }
34169
+ function displayValue(value, maxLength) {
34170
+ if (typeof value !== "string") return null;
34171
+ const trimmed = value.trim();
34172
+ if (!trimmed || trimmed.length > maxLength || /[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u.test(trimmed)) {
34173
+ return null;
34174
+ }
34175
+ return trimmed;
34176
+ }
34177
+ function claudeTranscriptPath(input) {
34178
+ const configDir = input.env["CLAUDE_CONFIG_DIR"] || join15(homeFrom(input.env), ".claude");
34179
+ const slug = input.resolvedCwd.replace(/[^a-zA-Z0-9]/g, "-");
34180
+ return join15(configDir, "projects", slug, `${input.sessionId}.jsonl`);
34181
+ }
34182
+ async function readClaudeSessionEffort(input) {
34183
+ const resolvedCwd = await realpath8(input.cwd).catch(() => input.cwd);
34184
+ const path = claudeTranscriptPath({ env: input.env, resolvedCwd, sessionId: input.sessionId });
34185
+ const records = parseLines(await readTail(path));
34186
+ for (let index = records.length - 1; index >= 0; index -= 1) {
34187
+ const record2 = records[index];
34188
+ if (record2["type"] !== "assistant") continue;
34189
+ const effort = displayValue(record2["effort"], 40);
34190
+ if (effort) return effort;
34191
+ }
34192
+ return null;
34193
+ }
34194
+ async function newestDirectories(root, limit) {
34195
+ const entries = await readdir4(root, { withFileTypes: true }).catch(() => []);
34196
+ return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort((left, right) => right.localeCompare(left)).slice(0, limit).map((name) => join15(root, name));
34197
+ }
34198
+ async function findCodexRolloutPath(input) {
34199
+ const codexHome = input.env["CODEX_HOME"] || join15(homeFrom(input.env), ".codex");
34200
+ const sessions = join15(codexHome, "sessions");
34201
+ const suffix = `-${input.threadId}.jsonl`;
34202
+ for (const year of await newestDirectories(sessions, 2)) {
34203
+ for (const month of await newestDirectories(year, 2)) {
34204
+ for (const day of await newestDirectories(month, 3)) {
34205
+ const files = await readdir4(day).catch(() => []);
34206
+ const match = files.find((name) => name.endsWith(suffix));
34207
+ if (match) return join15(day, match);
34208
+ }
34209
+ }
34210
+ }
34211
+ return null;
34212
+ }
34213
+ async function readCodexSessionRuntime(input) {
34214
+ const path = await findCodexRolloutPath(input);
34215
+ if (!path) return null;
34216
+ const contexts = parseLines(await readHead(path)).filter(
34217
+ (record2) => record2["type"] === "turn_context"
34218
+ );
34219
+ const payload = contexts.at(-1)?.["payload"];
34220
+ if (!payload || typeof payload !== "object") return null;
34221
+ const context = payload;
34222
+ const settings = context["collaboration_mode"]?.["settings"];
34223
+ return {
34224
+ model: displayValue(context["model"] ?? settings?.["model"], 120),
34225
+ effort: displayValue(context["effort"] ?? settings?.["reasoning_effort"], 40)
34226
+ };
34227
+ }
34228
+ var codexCatalogCache = /* @__PURE__ */ new Map();
34229
+ async function loadCodexModelCatalog(command, prefixArgs, env) {
34230
+ const output = await new Promise((resolve13) => {
34231
+ const child = spawnCli(command, [...prefixArgs, "debug", "models"], {
34232
+ stdio: ["ignore", "pipe", "ignore"],
34233
+ windowsHide: true,
34234
+ env
34235
+ });
34236
+ let text = "";
34237
+ child.stdout?.on("data", (chunk) => {
34238
+ if (text.length < CATALOG_OUTPUT_LIMIT_BYTES) text += chunk.toString("utf8");
34239
+ });
34240
+ let settled = false;
34241
+ const finish = (value) => {
34242
+ if (settled) return;
34243
+ settled = true;
34244
+ clearTimeout(timer);
34245
+ resolve13(value);
34246
+ };
34247
+ const timer = setTimeout(() => {
34248
+ child.kill();
34249
+ finish("");
34250
+ }, CATALOG_TIMEOUT_MS);
34251
+ timer.unref?.();
34252
+ child.on("error", () => finish(""));
34253
+ child.on("close", () => finish(text));
34254
+ });
34255
+ const defaults = /* @__PURE__ */ new Map();
34256
+ try {
34257
+ const catalog2 = JSON.parse(output);
34258
+ for (const model of catalog2.models ?? []) {
34259
+ const slug = displayValue(model["slug"], 120);
34260
+ const effort = displayValue(model["default_reasoning_level"], 40);
34261
+ if (slug && effort) defaults.set(slug, effort);
34262
+ }
34263
+ } catch {
34264
+ }
34265
+ return defaults;
34266
+ }
34267
+ async function codexModelDefaultEffort(input) {
34268
+ const prefixArgs = input.commandPrefixArgs ?? [];
34269
+ const cacheKey = [input.command, ...prefixArgs].join(" ");
34270
+ let catalog2 = codexCatalogCache.get(cacheKey);
34271
+ if (!catalog2) {
34272
+ catalog2 = loadCodexModelCatalog(input.command, prefixArgs, input.env);
34273
+ codexCatalogCache.set(cacheKey, catalog2);
34274
+ }
34275
+ return (await catalog2).get(input.model) ?? null;
34276
+ }
34277
+
34278
+ // src/runners/claude-code.ts
34067
34279
  var CLAUDE_SESSION_CRON_TOOLS = ["CronCreate", "CronList", "CronDelete"];
34068
34280
  var CLAUDE_REINVOCATION_TOOLS = ["Monitor", "ScheduleWakeup"];
34069
34281
  var SESSION_CONFLICT = /session/i;
@@ -34088,13 +34300,14 @@ var claudeCodeAdapter = {
34088
34300
  input.cwd
34089
34301
  );
34090
34302
  const sessionId = input.task.spec.sessionKey ?? randomUUID11();
34303
+ const observeRuntime = createRuntimeReporter(input, sessionId);
34091
34304
  return {
34092
34305
  argsFor: (mode) => [
34093
34306
  ...baseArgs,
34094
34307
  ...mode === "resume" ? ["--resume", sessionId] : ["--session-id", sessionId]
34095
34308
  ],
34096
34309
  prompt: buildRunnerPrompt(input.task),
34097
- createParser: createStreamParser,
34310
+ createParser: (onStream) => createStreamParser(onStream, { onSessionModel: observeRuntime }),
34098
34311
  // Self-heal both directions: a crashed first run leaves a transcript
34099
34312
  // (new → conflict), a lost workspace breaks resume (resume → not
34100
34313
  // found). One flip covers both.
@@ -34105,6 +34318,36 @@ var claudeCodeAdapter = {
34105
34318
  function createClaudeCodeRunner(opts = {}) {
34106
34319
  return createCliRunner(claudeCodeAdapter, opts);
34107
34320
  }
34321
+ function createRuntimeReporter(input, sessionId) {
34322
+ const { task, runner, env, cwd } = input;
34323
+ const chosenEffort = runner.effort ?? null;
34324
+ let reported = false;
34325
+ return (model) => {
34326
+ if (reported) return;
34327
+ reported = true;
34328
+ task.runnerRuntime?.({ type: "claude-code", model, effort: chosenEffort });
34329
+ if (chosenEffort) return;
34330
+ void (async () => {
34331
+ for (let attempt = 0; attempt < EFFORT_READ_ATTEMPTS; attempt += 1) {
34332
+ await delay2(EFFORT_READ_INTERVAL_MS);
34333
+ if (task.cancelledNow()) return;
34334
+ const effort = await readClaudeSessionEffort({ env, cwd, sessionId }).catch(() => null);
34335
+ if (effort) {
34336
+ task.runnerRuntime?.({ type: "claude-code", model, effort });
34337
+ return;
34338
+ }
34339
+ }
34340
+ })();
34341
+ };
34342
+ }
34343
+ var EFFORT_READ_ATTEMPTS = 5;
34344
+ var EFFORT_READ_INTERVAL_MS = 3e3;
34345
+ function delay2(ms) {
34346
+ return new Promise((resolve13) => {
34347
+ const timer = setTimeout(resolve13, ms);
34348
+ timer.unref?.();
34349
+ });
34350
+ }
34108
34351
  async function buildArgs(task, runner, artifacts, mcp, preparedWorkspace, taskRoot, workspacePath = taskRoot ?? "") {
34109
34352
  const args = [
34110
34353
  // Hermetic, non-interactive run — no local slash commands or global state.
@@ -34150,7 +34393,7 @@ async function buildArgs(task, runner, artifacts, mcp, preparedWorkspace, taskRo
34150
34393
  );
34151
34394
  return args;
34152
34395
  }
34153
- function createStreamParser(onStream) {
34396
+ function createStreamParser(onStream, hooks = {}) {
34154
34397
  let buffer = "";
34155
34398
  let responseText = "";
34156
34399
  let inputTokens = 0;
@@ -34175,7 +34418,9 @@ function createStreamParser(onStream) {
34175
34418
  return void 0;
34176
34419
  }
34177
34420
  const type = json2["type"];
34178
- if (type === "assistant") {
34421
+ if (type === "system" && json2["subtype"] === "init") {
34422
+ if (typeof json2["model"] === "string" && json2["model"]) hooks.onSessionModel?.(json2["model"]);
34423
+ } else if (type === "assistant") {
34179
34424
  const message = json2["message"];
34180
34425
  applyUsage(message?.["usage"]);
34181
34426
  const content = message?.["content"] ?? [];
@@ -34290,16 +34535,16 @@ function improveErrorMessage(error52) {
34290
34535
 
34291
34536
  // src/runners/codex.ts
34292
34537
  import { mkdir as mkdir11, readFile as readFile7, writeFile as writeFile6 } from "node:fs/promises";
34293
- import { homedir as homedir5 } from "node:os";
34294
- import { join as join15 } from "node:path";
34538
+ import { homedir as homedir6 } from "node:os";
34539
+ import { join as join16 } from "node:path";
34295
34540
  var CODEX_NOT_FOUND_MESSAGE = "The `codex` CLI was not found on this Machine. Install it (npm install -g @openai/codex) and sign in with `codex login`, or switch the agent to API-key auth.";
34296
34541
  function defaultCodexThreadIndexRoot() {
34297
- return join15(homedir5(), ".zixt", "codex-threads");
34542
+ return join16(homedir6(), ".zixt", "codex-threads");
34298
34543
  }
34299
34544
  var SAFE_SEGMENT3 = /^[A-Za-z0-9_-]{1,200}$/;
34300
34545
  function threadIndexPath(root, agentId, sessionKey) {
34301
34546
  if (!SAFE_SEGMENT3.test(agentId) || !SAFE_SEGMENT3.test(sessionKey)) return null;
34302
- return join15(root, agentId, `${sessionKey}.json`);
34547
+ return join16(root, agentId, `${sessionKey}.json`);
34303
34548
  }
34304
34549
  async function readThreadId(path) {
34305
34550
  try {
@@ -34389,9 +34634,12 @@ ${buildRunnerPrompt(task)}` : buildRunnerPrompt(task);
34389
34634
  const recordedThreadId = indexPath ? await readThreadId(indexPath) : null;
34390
34635
  const rememberThread = (threadId) => {
34391
34636
  if (!indexPath) return;
34392
- void mkdir11(join15(threadIndexRoot, task.agentId), { recursive: true }).then(() => writeFile6(indexPath, JSON.stringify({ threadId }), "utf8")).catch(() => {
34637
+ void mkdir11(join16(threadIndexRoot, task.agentId), { recursive: true }).then(() => writeFile6(indexPath, JSON.stringify({ threadId }), "utf8")).catch(() => {
34393
34638
  });
34394
34639
  };
34640
+ const observeRuntime = (threadId) => {
34641
+ void reportCodexRuntime({ input, threadId });
34642
+ };
34395
34643
  return {
34396
34644
  argsFor: (mode) => {
34397
34645
  if (mode === "resume") {
@@ -34401,7 +34649,12 @@ ${buildRunnerPrompt(task)}` : buildRunnerPrompt(task);
34401
34649
  },
34402
34650
  prompt,
34403
34651
  env,
34404
- createParser: (onStream) => createCodexStreamParser(onStream, { onThreadStarted: rememberThread }),
34652
+ createParser: (onStream) => createCodexStreamParser(onStream, {
34653
+ onThreadStarted: (threadId) => {
34654
+ rememberThread(threadId);
34655
+ observeRuntime(threadId);
34656
+ }
34657
+ }),
34405
34658
  // Only one flip is meaningful: a resume whose rollout vanished starts
34406
34659
  // over. Codex assigns new-session ids itself, so a new session can
34407
34660
  // never collide the way a pre-specified id can.
@@ -34410,6 +34663,30 @@ ${buildRunnerPrompt(task)}` : buildRunnerPrompt(task);
34410
34663
  }
34411
34664
  };
34412
34665
  }
34666
+ var RUNTIME_READ_ATTEMPTS = 5;
34667
+ var RUNTIME_READ_INTERVAL_MS = 2e3;
34668
+ function delay3(ms) {
34669
+ return new Promise((resolve13) => {
34670
+ const timer = setTimeout(resolve13, ms);
34671
+ timer.unref?.();
34672
+ });
34673
+ }
34674
+ async function reportCodexRuntime(args) {
34675
+ const { task, runner, env, command, commandPrefixArgs } = args.input;
34676
+ for (let attempt = 0; attempt < RUNTIME_READ_ATTEMPTS; attempt += 1) {
34677
+ if (task.cancelledNow()) return;
34678
+ const observed = await readCodexSessionRuntime({ env, threadId: args.threadId }).catch(
34679
+ () => null
34680
+ );
34681
+ const model = observed?.model ?? runner.model ?? null;
34682
+ if (model) {
34683
+ const effort = observed?.effort ?? runner.effort ?? (command ? await codexModelDefaultEffort({ command, commandPrefixArgs, env, model }) : null);
34684
+ task.runnerRuntime?.({ type: "codex", model, effort });
34685
+ return;
34686
+ }
34687
+ await delay3(RUNTIME_READ_INTERVAL_MS);
34688
+ }
34689
+ }
34413
34690
  function createCodexRunner(opts = {}) {
34414
34691
  const adapter = createCodexAdapter(opts.threadIndexRoot ?? defaultCodexThreadIndexRoot());
34415
34692
  return createCliRunner(adapter, opts);
@@ -34559,7 +34836,7 @@ function improveCodexErrorMessage(error52) {
34559
34836
 
34560
34837
  // src/runners/git-preflight.ts
34561
34838
  import { spawn as spawn9 } from "node:child_process";
34562
- import { realpath as realpath8 } from "node:fs/promises";
34839
+ import { realpath as realpath9 } from "node:fs/promises";
34563
34840
  import { isAbsolute as isAbsolute13, resolve as resolve7 } from "node:path";
34564
34841
  var OUTPUT_LIMIT = 8192;
34565
34842
  var DEFAULT_TIMEOUT_MS4 = 1e4;
@@ -34579,7 +34856,7 @@ async function preflightGit(options = {}) {
34579
34856
  if (configured !== void 0 && !isAbsolute13(configured)) {
34580
34857
  return unavailable("configured git command must be an absolute file", checkedAt);
34581
34858
  }
34582
- const trustedCwd = await realpath8(resolve7(options.trustedCwd ?? process.cwd())).catch(() => null);
34859
+ const trustedCwd = await realpath9(resolve7(options.trustedCwd ?? process.cwd())).catch(() => null);
34583
34860
  if (!trustedCwd)
34584
34861
  return unavailable("Host-owned git preflight directory is unavailable", checkedAt);
34585
34862
  const executablePath = await resolveTrustedCliCommand(configured ?? "git", {
@@ -34831,9 +35108,9 @@ function run2(command, args) {
34831
35108
  // src/linux-service.ts
34832
35109
  import { spawn as spawn10 } from "node:child_process";
34833
35110
  import { constants as constants2 } from "node:fs";
34834
- import { access as access4, chmod as chmod7, mkdir as mkdir12, open as open5, rename as rename5, rm as rm7 } from "node:fs/promises";
34835
- import { homedir as homedir6, userInfo } from "node:os";
34836
- import { basename as basename3, dirname as dirname7, join as join16, relative as relative8, resolve as resolve8, sep as sep4 } from "node:path";
35111
+ import { access as access4, chmod as chmod7, mkdir as mkdir12, open as open6, rename as rename5, rm as rm7 } from "node:fs/promises";
35112
+ import { homedir as homedir7, userInfo } from "node:os";
35113
+ import { basename as basename3, dirname as dirname7, join as join17, relative as relative8, resolve as resolve8, sep as sep4 } from "node:path";
34837
35114
  var SERVICE_NAME = "zixt-host.service";
34838
35115
  var SYSTEM_SERVICE_COMMAND_TIMEOUT_MS = 7e4;
34839
35116
  var SERVICE_STABILITY_DELAY_MS = 2e3;
@@ -34921,7 +35198,7 @@ function systemdDirectiveValue(value) {
34921
35198
  return systemdQuotedValue(value, false);
34922
35199
  }
34923
35200
  async function defaultSyncDirectory(path) {
34924
- const directory = await open5(path, "r");
35201
+ const directory = await open6(path, "r");
34925
35202
  try {
34926
35203
  await directory.sync();
34927
35204
  } finally {
@@ -34938,14 +35215,14 @@ async function ensureDirectory(path, mode, syncDirectory7) {
34938
35215
  const descendants = relative8(first, target);
34939
35216
  for (const part of descendants ? descendants.split(sep4) : []) {
34940
35217
  await syncDirectory7(current);
34941
- current = join16(current, part);
35218
+ current = join17(current, part);
34942
35219
  }
34943
35220
  }
34944
35221
  async function replacePrivateFile(path, contents, mode, syncDirectory7) {
34945
35222
  const parent = dirname7(path);
34946
35223
  await ensureDirectory(parent, 448, syncDirectory7);
34947
- const temporary = join16(parent, `.${basename3(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
34948
- const handle = await open5(temporary, "wx", mode);
35224
+ const temporary = join17(parent, `.${basename3(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
35225
+ const handle = await open6(temporary, "wx", mode);
34949
35226
  try {
34950
35227
  await handle.writeFile(contents, "utf8");
34951
35228
  await handle.sync();
@@ -34988,7 +35265,7 @@ async function installLinuxService(options) {
34988
35265
  throw new Error("Linux automatic startup is available only on Linux.");
34989
35266
  }
34990
35267
  const env = options.env ?? process.env;
34991
- const home = options.home ?? homedir6();
35268
+ const home = options.home ?? homedir7();
34992
35269
  const username = oneLine(options.username ?? userInfo().username, "user name");
34993
35270
  const token2 = oneLine(options.token, "pairing code");
34994
35271
  const path = oneLine(
@@ -34996,11 +35273,11 @@ async function installLinuxService(options) {
34996
35273
  "command search path"
34997
35274
  );
34998
35275
  const cloudUrl = options.cloudUrl ? oneLine(options.cloudUrl, "Zixt Cloud address") : void 0;
34999
- const xdgConfigHome = env.XDG_CONFIG_HOME ? oneLine(env.XDG_CONFIG_HOME, "Linux configuration path") : join16(home, ".config");
35000
- const configRoot = options.serviceConfigRoot ?? join16(xdgConfigHome, "zixt");
35001
- const unitRoot = options.userUnitRoot ?? join16(xdgConfigHome, "systemd", "user");
35002
- const environmentPath = join16(configRoot, "host.env");
35003
- const unitPath = join16(unitRoot, SERVICE_NAME);
35276
+ const xdgConfigHome = env.XDG_CONFIG_HOME ? oneLine(env.XDG_CONFIG_HOME, "Linux configuration path") : join17(home, ".config");
35277
+ const configRoot = options.serviceConfigRoot ?? join17(xdgConfigHome, "zixt");
35278
+ const unitRoot = options.userUnitRoot ?? join17(xdgConfigHome, "systemd", "user");
35279
+ const environmentPath = join17(configRoot, "host.env");
35280
+ const unitPath = join17(unitRoot, SERVICE_NAME);
35004
35281
  const installVersion = options.installVersion ?? installRelease;
35005
35282
  const activateVersion = options.activateVersion ?? (options.installVersion ? async (entry) => entry : activateInstalledRelease);
35006
35283
  const resolveCommand = options.resolveCommand ?? defaultResolveCommand;
@@ -35119,9 +35396,9 @@ async function installLinuxService(options) {
35119
35396
  // src/macos-service.ts
35120
35397
  import { spawn as spawn11 } from "node:child_process";
35121
35398
  import { constants as constants3 } from "node:fs";
35122
- import { access as access5, chmod as chmod8, mkdir as mkdir13, open as open6, rename as rename6, rm as rm8 } from "node:fs/promises";
35123
- import { homedir as homedir7, userInfo as userInfo2 } from "node:os";
35124
- import { basename as basename4, dirname as dirname8, join as join17, relative as relative9, resolve as resolve9, sep as sep5 } from "node:path";
35399
+ import { access as access5, chmod as chmod8, mkdir as mkdir13, open as open7, rename as rename6, rm as rm8 } from "node:fs/promises";
35400
+ import { homedir as homedir8, userInfo as userInfo2 } from "node:os";
35401
+ import { basename as basename4, dirname as dirname8, join as join18, relative as relative9, resolve as resolve9, sep as sep5 } from "node:path";
35125
35402
  var LAUNCH_AGENT_LABEL = "ai.zixt.host";
35126
35403
  var SERVICE_STABILITY_DELAY_MS2 = 2e3;
35127
35404
  var COMMAND_TIMEOUT_MS2 = 7e4;
@@ -35137,7 +35414,7 @@ function shellValue(value) {
35137
35414
  return `'${oneLine2(value, "service setting").replaceAll("'", `'"'"'`)}'`;
35138
35415
  }
35139
35416
  async function syncDirectory4(path) {
35140
- const directory = await open6(path, "r");
35417
+ const directory = await open7(path, "r");
35141
35418
  try {
35142
35419
  await directory.sync();
35143
35420
  } finally {
@@ -35153,14 +35430,14 @@ async function ensureDirectory2(path, sync) {
35153
35430
  let current = first;
35154
35431
  for (const part of relative9(first, target).split(sep5).filter(Boolean)) {
35155
35432
  await sync(current);
35156
- current = join17(current, part);
35433
+ current = join18(current, part);
35157
35434
  }
35158
35435
  }
35159
35436
  async function replacePrivateFile2(path, contents, mode, sync) {
35160
35437
  const parent = dirname8(path);
35161
35438
  await ensureDirectory2(parent, sync);
35162
- const temporary = join17(parent, `.${basename4(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
35163
- const handle = await open6(temporary, "wx", mode);
35439
+ const temporary = join18(parent, `.${basename4(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
35440
+ const handle = await open7(temporary, "wx", mode);
35164
35441
  try {
35165
35442
  await handle.writeFile(contents, "utf8");
35166
35443
  await handle.sync();
@@ -35247,7 +35524,7 @@ async function installMacosService(options) {
35247
35524
  throw new Error("macOS automatic startup is available only on macOS.");
35248
35525
  }
35249
35526
  const env = options.env ?? process.env;
35250
- const home = options.home ?? homedir7();
35527
+ const home = options.home ?? homedir8();
35251
35528
  const uid = options.uid ?? userInfo2().uid;
35252
35529
  if (!Number.isSafeInteger(uid) || uid < 0) throw new Error("macOS user id is invalid.");
35253
35530
  const token2 = oneLine2(options.token, "pairing code");
@@ -35256,20 +35533,20 @@ async function installMacosService(options) {
35256
35533
  options.path ?? env.PATH ?? "/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin",
35257
35534
  "command search path"
35258
35535
  );
35259
- const configRoot = options.configRoot ?? join17(home, "Library", "Application Support", "Zixt");
35260
- const launchAgentsRoot = options.launchAgentsRoot ?? join17(home, "Library", "LaunchAgents");
35261
- const logRoot = options.logRoot ?? join17(home, "Library", "Logs", "Zixt");
35262
- const configPath = join17(configRoot, "host.env");
35263
- const launcherPath = join17(configRoot, "host-launcher.sh");
35264
- const plistPath = join17(launchAgentsRoot, `${LAUNCH_AGENT_LABEL}.plist`);
35265
- const stdoutPath = join17(logRoot, "host.log");
35266
- const stderrPath = join17(logRoot, "host-error.log");
35536
+ const configRoot = options.configRoot ?? join18(home, "Library", "Application Support", "Zixt");
35537
+ const launchAgentsRoot = options.launchAgentsRoot ?? join18(home, "Library", "LaunchAgents");
35538
+ const logRoot = options.logRoot ?? join18(home, "Library", "Logs", "Zixt");
35539
+ const configPath = join18(configRoot, "host.env");
35540
+ const launcherPath = join18(configRoot, "host-launcher.sh");
35541
+ const plistPath = join18(launchAgentsRoot, `${LAUNCH_AGENT_LABEL}.plist`);
35542
+ const stdoutPath = join18(logRoot, "host.log");
35543
+ const stderrPath = join18(logRoot, "host-error.log");
35267
35544
  const installVersion = options.installVersion ?? installRelease;
35268
35545
  const activateVersion = options.activateVersion ?? (options.installVersion ? async (entry) => entry : (entry) => activateInstalledRelease(entry));
35269
35546
  const resolveCommand = options.resolveCommand ?? (async () => defaultResolveCommand2());
35270
35547
  const run3 = options.runCommand ?? ((command, args) => defaultRunCommand2(command, args, env));
35271
35548
  const sync = options.syncDirectory ?? syncDirectory4;
35272
- const delay2 = options.delay ?? ((ms) => new Promise((done) => setTimeout(done, ms)));
35549
+ const delay4 = options.delay ?? ((ms) => new Promise((done) => setTimeout(done, ms)));
35273
35550
  const launchctl = await resolveCommand("launchctl");
35274
35551
  if (!launchctl) throw new Error("macOS launchctl could not be found.");
35275
35552
  const releaseEntry = await installVersion(options.hostVersion);
@@ -35331,7 +35608,7 @@ async function installMacosService(options) {
35331
35608
  return status;
35332
35609
  };
35333
35610
  const first = await observe();
35334
- await delay2(options.serviceStabilityDelayMs ?? SERVICE_STABILITY_DELAY_MS2);
35611
+ await delay4(options.serviceStabilityDelayMs ?? SERVICE_STABILITY_DELAY_MS2);
35335
35612
  const second = await observe();
35336
35613
  if (first.pid !== second.pid || first.runs !== second.runs) {
35337
35614
  throw new Error("Zixt started but restarted during its readiness check.");
@@ -35350,9 +35627,9 @@ async function installMacosService(options) {
35350
35627
  // src/windows-service.ts
35351
35628
  import { spawn as spawn12 } from "node:child_process";
35352
35629
  import { constants as constants4 } from "node:fs";
35353
- import { access as access6, mkdir as mkdir14, open as open7, readFile as readFile8, rename as rename7, rm as rm9 } from "node:fs/promises";
35354
- import { homedir as homedir8 } from "node:os";
35355
- import { basename as basename5, dirname as dirname9, isAbsolute as isAbsolute14, join as join18, relative as relative10, resolve as resolve10, sep as sep6 } from "node:path";
35630
+ import { access as access6, mkdir as mkdir14, open as open8, readFile as readFile8, rename as rename7, rm as rm9 } from "node:fs/promises";
35631
+ import { homedir as homedir9 } from "node:os";
35632
+ import { basename as basename5, dirname as dirname9, isAbsolute as isAbsolute14, join as join19, relative as relative10, resolve as resolve10, sep as sep6 } from "node:path";
35356
35633
  var TASK_NAME = "Zixt Host";
35357
35634
  var COMMAND_TIMEOUT_MS3 = 7e4;
35358
35635
  var SERVICE_STABILITY_DELAY_MS3 = 2e3;
@@ -35370,7 +35647,7 @@ function psLiteral(value) {
35370
35647
  }
35371
35648
  async function syncDirectory5(path) {
35372
35649
  if (process.platform === "win32") return;
35373
- const directory = await open7(path, "r");
35650
+ const directory = await open8(path, "r");
35374
35651
  try {
35375
35652
  await directory.sync();
35376
35653
  } finally {
@@ -35386,14 +35663,14 @@ async function ensureDirectory3(path, sync) {
35386
35663
  let current = first;
35387
35664
  for (const part of relative10(first, target).split(sep6).filter(Boolean)) {
35388
35665
  await sync(current);
35389
- current = join18(current, part);
35666
+ current = join19(current, part);
35390
35667
  }
35391
35668
  }
35392
35669
  async function replacePrivateFile3(path, contents, sync) {
35393
35670
  const parent = dirname9(path);
35394
35671
  await ensureDirectory3(parent, sync);
35395
- const temporary = join18(parent, `.${basename5(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
35396
- const handle = await open7(temporary, "wx", 384);
35672
+ const temporary = join19(parent, `.${basename5(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
35673
+ const handle = await open8(temporary, "wx", 384);
35397
35674
  try {
35398
35675
  await handle.writeFile(contents, "utf8");
35399
35676
  await handle.sync();
@@ -35447,7 +35724,7 @@ async function runChild(command, args, env, input) {
35447
35724
  async function defaultResolveCommand3(name, env) {
35448
35725
  const root = env.SYSTEMROOT ?? env.WINDIR;
35449
35726
  if (!root || !isAbsolute14(root)) return null;
35450
- const candidate = name === "powershell" ? join18(root, "System32", "WindowsPowerShell", "v1.0", "powershell.exe") : join18(root, "System32", `${name}.exe`);
35727
+ const candidate = name === "powershell" ? join19(root, "System32", "WindowsPowerShell", "v1.0", "powershell.exe") : join19(root, "System32", `${name}.exe`);
35451
35728
  return access6(candidate, constants4.X_OK).then(
35452
35729
  () => candidate,
35453
35730
  () => null
@@ -35576,7 +35853,7 @@ async function installWindowsService(options) {
35576
35853
  throw new Error("Windows automatic startup is available only on Windows.");
35577
35854
  }
35578
35855
  const env = options.env ?? process.env;
35579
- const home = options.home ?? homedir8();
35856
+ const home = options.home ?? homedir9();
35580
35857
  const localAppData = options.localAppData ?? env.LOCALAPPDATA;
35581
35858
  if (!localAppData || !isAbsolute14(localAppData)) {
35582
35859
  throw new Error("Windows local application data path is unavailable.");
@@ -35584,17 +35861,17 @@ async function installWindowsService(options) {
35584
35861
  const token2 = oneLine3(options.token, "pairing code");
35585
35862
  const cloudUrl = options.cloudUrl ? oneLine3(options.cloudUrl, "Zixt Cloud address") : void 0;
35586
35863
  const path = oneLine3(options.path ?? env.PATH ?? "", "command search path");
35587
- const configRoot = options.configRoot ?? join18(localAppData, "Zixt", "Host");
35588
- const configPath = join18(configRoot, "host.json");
35589
- const launcherPath = join18(configRoot, "host-launcher.ps1");
35590
- const taskXmlPath = join18(configRoot, "host-task.xml");
35591
- const statusPath = join18(configRoot, "host-status.json");
35864
+ const configRoot = options.configRoot ?? join19(localAppData, "Zixt", "Host");
35865
+ const configPath = join19(configRoot, "host.json");
35866
+ const launcherPath = join19(configRoot, "host-launcher.ps1");
35867
+ const taskXmlPath = join19(configRoot, "host-task.xml");
35868
+ const statusPath = join19(configRoot, "host-status.json");
35592
35869
  const installVersion = options.installVersion ?? installRelease;
35593
35870
  const activateVersion = options.activateVersion ?? (options.installVersion ? async (entry) => entry : (entry) => activateInstalledRelease(entry));
35594
35871
  const resolveCommand = options.resolveCommand ?? ((name) => defaultResolveCommand3(name, env));
35595
35872
  const run3 = options.runCommand ?? ((command, args) => runChild(command, args, env));
35596
35873
  const sync = options.syncDirectory ?? syncDirectory5;
35597
- const delay2 = options.delay ?? ((ms) => new Promise((done) => setTimeout(done, ms)));
35874
+ const delay4 = options.delay ?? ((ms) => new Promise((done) => setTimeout(done, ms)));
35598
35875
  const observe = options.observeStatus ?? defaultObserveStatus;
35599
35876
  const [powershell, schtasks, icacls] = await Promise.all([
35600
35877
  resolveCommand("powershell"),
@@ -35657,10 +35934,10 @@ async function installWindowsService(options) {
35657
35934
  do {
35658
35935
  first = await observe(statusPath, generation);
35659
35936
  if (first) break;
35660
- await delay2(50);
35937
+ await delay4(50);
35661
35938
  } while (Date.now() < deadline);
35662
35939
  if (!first) throw new Error("Zixt started but did not reach a running process state.");
35663
- await delay2(options.serviceStabilityDelayMs ?? SERVICE_STABILITY_DELAY_MS3);
35940
+ await delay4(options.serviceStabilityDelayMs ?? SERVICE_STABILITY_DELAY_MS3);
35664
35941
  const second = await observe(statusPath, generation);
35665
35942
  if (!second || first.pid !== second.pid) {
35666
35943
  throw new Error("Zixt started but restarted during its readiness check.");
@@ -35689,27 +35966,27 @@ async function installSystemService(options) {
35689
35966
  }
35690
35967
 
35691
35968
  // src/terminal-outcomes.ts
35692
- import { chmod as chmod9, lstat as lstat10, mkdir as mkdir15, open as open8, readdir as readdir4, readFile as readFile9, rename as rename8, rm as rm10 } from "node:fs/promises";
35693
- import { homedir as homedir9 } from "node:os";
35694
- import { dirname as dirname10, join as join19, relative as relative11, resolve as resolve11, sep as sep7 } from "node:path";
35969
+ import { chmod as chmod9, lstat as lstat10, mkdir as mkdir15, open as open9, readdir as readdir5, readFile as readFile9, rename as rename8, rm as rm10 } from "node:fs/promises";
35970
+ import { homedir as homedir10 } from "node:os";
35971
+ import { dirname as dirname10, join as join20, relative as relative11, resolve as resolve11, sep as sep7 } from "node:path";
35695
35972
  var DIRECTORY_MODE5 = 448;
35696
35973
  var FILE_MODE4 = 384;
35697
35974
  var MAX_OUTCOME_BYTES = 4 * 1024 * 1024;
35698
35975
  var HOST_DIRECTORY = /^hst_[0-9a-f]{32}$/;
35699
35976
  var OUTCOME_FILE = /^(tsk_[0-9a-f]{32})\.([1-9][0-9]*)\.json$/;
35700
35977
  function defaultTerminalOutcomeRoot() {
35701
- return join19(homedir9(), ".zixt", "terminal-outcomes");
35978
+ return join20(homedir10(), ".zixt", "terminal-outcomes");
35702
35979
  }
35703
35980
  function hostOutcomeRoot(root, hostId) {
35704
35981
  if (!HOST_DIRECTORY.test(hostId)) throw new Error("terminal outcome Host identity is malformed");
35705
- return join19(root, hostId);
35982
+ return join20(root, hostId);
35706
35983
  }
35707
35984
  function outcomePath(root, hostId, taskId, epoch) {
35708
- return join19(hostOutcomeRoot(root, hostId), `${taskId}.${epoch}.json`);
35985
+ return join20(hostOutcomeRoot(root, hostId), `${taskId}.${epoch}.json`);
35709
35986
  }
35710
35987
  async function syncDirectory6(root) {
35711
35988
  if (process.platform === "win32") return;
35712
- const handle = await open8(root, "r");
35989
+ const handle = await open9(root, "r");
35713
35990
  try {
35714
35991
  await handle.sync();
35715
35992
  } finally {
@@ -35725,7 +36002,7 @@ async function requirePrivateRoot(root, sync = syncDirectory6) {
35725
36002
  let current = first;
35726
36003
  for (const part of relative11(first, target).split(sep7).filter(Boolean)) {
35727
36004
  await sync(current);
35728
- current = join19(current, part);
36005
+ current = join20(current, part);
35729
36006
  }
35730
36007
  }
35731
36008
  const stat3 = await lstat10(root);
@@ -35765,13 +36042,13 @@ async function recordTerminalOutcome(hostId, input, root = defaultTerminalOutcom
35765
36042
  } catch (error52) {
35766
36043
  if (error52.code !== "ENOENT") throw error52;
35767
36044
  }
35768
- const temporary = join19(
36045
+ const temporary = join20(
35769
36046
  scopedRoot,
35770
36047
  `.${outcome.taskId}.${outcome.epoch}.${process.pid}.${Date.now()}.${outcome.resultId}.tmp`
35771
36048
  );
35772
36049
  let handle;
35773
36050
  try {
35774
- handle = await open8(temporary, "wx", FILE_MODE4);
36051
+ handle = await open9(temporary, "wx", FILE_MODE4);
35775
36052
  await handle.writeFile(JSON.stringify(outcome), "utf8");
35776
36053
  await handle.sync();
35777
36054
  await handle.close();
@@ -35798,7 +36075,7 @@ async function readTerminalOutcomesStrict(root = defaultTerminalOutcomeRoot()) {
35798
36075
  throw new Error("terminal outcome journal root is not a trusted directory");
35799
36076
  }
35800
36077
  await chmod9(root, DIRECTORY_MODE5);
35801
- const hostEntries = await readdir4(root, { withFileTypes: true });
36078
+ const hostEntries = await readdir5(root, { withFileTypes: true });
35802
36079
  const outcomes = [];
35803
36080
  const resultIds = /* @__PURE__ */ new Set();
35804
36081
  for (const hostEntry of hostEntries) {
@@ -35811,14 +36088,14 @@ async function readTerminalOutcomesStrict(root = defaultTerminalOutcomeRoot()) {
35811
36088
  throw new Error("terminal outcome Host scope is not a trusted directory");
35812
36089
  }
35813
36090
  await chmod9(scopedRoot, DIRECTORY_MODE5);
35814
- const entries = await readdir4(scopedRoot, { withFileTypes: true });
36091
+ const entries = await readdir5(scopedRoot, { withFileTypes: true });
35815
36092
  for (const entry of entries) {
35816
36093
  if (!entry.name.endsWith(".json")) continue;
35817
36094
  const match = OUTCOME_FILE.exec(entry.name);
35818
36095
  if (!match || !entry.isFile() || entry.isSymbolicLink()) {
35819
36096
  throw new Error("committed terminal outcome is not a trusted regular file");
35820
36097
  }
35821
- const path = join19(scopedRoot, entry.name);
36098
+ const path = join20(scopedRoot, entry.name);
35822
36099
  const stat3 = await lstat10(path);
35823
36100
  if (!stat3.isFile() || stat3.isSymbolicLink() || stat3.size > MAX_OUTCOME_BYTES) {
35824
36101
  throw new Error("committed terminal outcome is not a trusted regular file");
@@ -35971,7 +36248,7 @@ function createHostLogger(options = {}) {
35971
36248
  }
35972
36249
 
35973
36250
  // src/demo-state.ts
35974
- import { isAbsolute as isAbsolute15, join as join20, parse as parse3, resolve as resolve12 } from "node:path";
36251
+ import { isAbsolute as isAbsolute15, join as join21, parse as parse3, resolve as resolve12 } from "node:path";
35975
36252
  var DEMO_STATE_ROOT_ENV = "ZIXT_DEMO_STATE_ROOT";
35976
36253
  function resolveDemoHostStatePaths(env = process.env) {
35977
36254
  const configured = env.ZIXT_RUNNER === "demo" ? env[DEMO_STATE_ROOT_ENV] : void 0;
@@ -35981,12 +36258,12 @@ function resolveDemoHostStatePaths(env = process.env) {
35981
36258
  throw new Error(`${DEMO_STATE_ROOT_ENV} must be a dedicated absolute directory`);
35982
36259
  }
35983
36260
  return {
35984
- runRegistryRoot: join20(root, "run-registry"),
35985
- terminalOutcomeRoot: join20(root, "terminal-outcomes"),
35986
- runArtifactRoot: join20(root, "run-artifacts"),
35987
- browserProfileRoot: join20(root, "browser-profiles"),
35988
- runnerWorkspaceRoot: join20(root, "workspaces"),
35989
- codexThreadIndexRoot: join20(root, "codex-threads")
36261
+ runRegistryRoot: join21(root, "run-registry"),
36262
+ terminalOutcomeRoot: join21(root, "terminal-outcomes"),
36263
+ runArtifactRoot: join21(root, "run-artifacts"),
36264
+ browserProfileRoot: join21(root, "browser-profiles"),
36265
+ runnerWorkspaceRoot: join21(root, "workspaces"),
36266
+ codexThreadIndexRoot: join21(root, "codex-threads")
35990
36267
  };
35991
36268
  }
35992
36269
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zixt/host",
3
- "version": "0.0.11",
3
+ "version": "0.0.12",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./src/client.ts",