@lazehq/cli 0.1.14 → 0.1.16

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/laze.mjs +592 -497
  2. package/package.json +1 -1
package/dist/laze.mjs CHANGED
@@ -18733,8 +18733,8 @@ var require_snapshot_utils = __commonJS({
18733
18733
  var require_snapshot_recorder = __commonJS({
18734
18734
  "../../node_modules/.pnpm/undici@8.10.0/node_modules/undici/lib/mock/snapshot-recorder.js"(exports, module) {
18735
18735
  "use strict";
18736
- var { writeFile: writeFile20, readFile: readFile32, mkdir: mkdir18 } = __require("node:fs/promises");
18737
- var { dirname: dirname18, resolve: resolve17 } = __require("node:path");
18736
+ var { writeFile: writeFile21, readFile: readFile34, mkdir: mkdir19 } = __require("node:fs/promises");
18737
+ var { dirname: dirname19, resolve: resolve17 } = __require("node:path");
18738
18738
  var { setTimeout: setTimeout2, clearTimeout: clearTimeout2 } = __require("node:timers");
18739
18739
  var { InvalidArgumentError, UndiciError } = require_errors();
18740
18740
  var { hashId, isUrlExcludedFactory, normalizeHeaders, createHeaderFilters } = require_snapshot_utils();
@@ -18950,7 +18950,7 @@ var require_snapshot_recorder = __commonJS({
18950
18950
  throw new InvalidArgumentError("Snapshot path is required");
18951
18951
  }
18952
18952
  try {
18953
- const data = await readFile32(resolve17(path), "utf8");
18953
+ const data = await readFile34(resolve17(path), "utf8");
18954
18954
  const parsed = JSON.parse(data);
18955
18955
  if (Array.isArray(parsed)) {
18956
18956
  this.#snapshots.clear();
@@ -18980,12 +18980,12 @@ var require_snapshot_recorder = __commonJS({
18980
18980
  throw new InvalidArgumentError("Snapshot path is required");
18981
18981
  }
18982
18982
  const resolvedPath = resolve17(path);
18983
- await mkdir18(dirname18(resolvedPath), { recursive: true });
18983
+ await mkdir19(dirname19(resolvedPath), { recursive: true });
18984
18984
  const data = Array.from(this.#snapshots.entries()).map(([hash2, snapshot]) => ({
18985
18985
  hash: hash2,
18986
18986
  snapshot
18987
18987
  }));
18988
- await writeFile20(resolvedPath, JSON.stringify(data, null, 2), { flush: true });
18988
+ await writeFile21(resolvedPath, JSON.stringify(data, null, 2), { flush: true });
18989
18989
  }
18990
18990
  /**
18991
18991
  * Clears all recorded snapshots
@@ -35606,7 +35606,7 @@ function flagText({
35606
35606
  }
35607
35607
 
35608
35608
  // src/rules/cli-version.rules.ts
35609
- var STAMPED = "0.1.14";
35609
+ var STAMPED = "0.1.16";
35610
35610
  function cliVersionOf({ stamped = STAMPED } = {}) {
35611
35611
  return stamped.startsWith("__") ? "dev" : stamped;
35612
35612
  }
@@ -65390,7 +65390,7 @@ async function copyAgent({
65390
65390
  }
65391
65391
 
65392
65392
  // src/services/agent-commands.service.ts
65393
- import { mkdir as mkdir11, readFile as readFile9, writeFile as writeFile11 } from "node:fs/promises";
65393
+ import { mkdir as mkdir13, readFile as readFile11, writeFile as writeFile13 } from "node:fs/promises";
65394
65394
  import { join as join12, resolve as resolve4 } from "node:path";
65395
65395
 
65396
65396
  // src/rules/agent-profile.rules.ts
@@ -67264,10 +67264,327 @@ async function claudeProjectOf({
67264
67264
  return candidates.find((folder) => holds({ folder, inner: context.cwd })) ?? resolve2(context.cwd);
67265
67265
  }
67266
67266
 
67267
+ // src/services/claude-wait.service.ts
67268
+ import { readFile as readFile5, rm as rm2, writeFile as writeFile5, mkdir as mkdir5 } from "node:fs/promises";
67269
+ import { dirname as dirname5 } from "node:path";
67270
+
67271
+ // src/services/harness-session.service.ts
67272
+ import { mkdir as mkdir4, readdir, readFile as readFile4, writeFile as writeFile4 } from "node:fs/promises";
67273
+ import { hostname as hostname3 } from "node:os";
67274
+ import { dirname as dirname4, join as join4 } from "node:path";
67275
+
67276
+ // src/rules/session-headers.rules.ts
67277
+ import { relative as relative2, sep } from "node:path";
67278
+ function sessionKeyOf({ session }) {
67279
+ return `${session.harness}:${session.sessionId}`;
67280
+ }
67281
+ function sessionHeadersOf({
67282
+ session
67283
+ }) {
67284
+ if (!session) return {};
67285
+ return {
67286
+ [AGENT_SESSION_HEADER]: sessionKeyOf({ session }),
67287
+ [AGENT_SESSION_FOLDER_HEADER]: encodeURIComponent(session.folder),
67288
+ [AGENT_SESSION_HOST_HEADER]: encodeURIComponent(session.host)
67289
+ };
67290
+ }
67291
+ function displayFolderOf({ folder, home }) {
67292
+ if (!home) return folder;
67293
+ const below = relative2(home, folder);
67294
+ if (below === "") return "~";
67295
+ if (below.startsWith("..") || below.startsWith(sep)) return folder;
67296
+ return `~/${below.split(sep).join("/")}`;
67297
+ }
67298
+
67299
+ // src/services/harness-session.service.ts
67300
+ function sessionOf({
67301
+ context,
67302
+ harness,
67303
+ sessionId
67304
+ }) {
67305
+ if (!sessionId) return void 0;
67306
+ const inherited = context.environment.inherited;
67307
+ const folder = inherited.CLAUDE_PROJECT_DIR || context.cwd;
67308
+ return {
67309
+ harness,
67310
+ sessionId,
67311
+ folder: displayFolderOf({ folder, home: inherited.HOME }),
67312
+ host: hostname3()
67313
+ };
67314
+ }
67315
+ function forSession({
67316
+ client,
67317
+ session
67318
+ }) {
67319
+ return client.withHeaders(sessionHeadersOf({ session }));
67320
+ }
67321
+ async function rememberSession({
67322
+ context,
67323
+ claudePid,
67324
+ session
67325
+ }) {
67326
+ if (!session || !claudePid) return;
67327
+ const path = statePathOf({ context, kind: "sessions", profile: String(claudePid) });
67328
+ await mkdir4(dirname4(path), { recursive: true, mode: 448 });
67329
+ await writeFile4(path, JSON.stringify(session), { mode: 384 });
67330
+ }
67331
+ async function currentSessionOf({
67332
+ context,
67333
+ args
67334
+ }) {
67335
+ const inherited = context.environment.inherited;
67336
+ const named = flagText({ args, name: "session" });
67337
+ const harness = context.environment.harness;
67338
+ if (named) return sessionOf({ context, harness, sessionId: named });
67339
+ if (harness === "claude-code" && inherited.CLAUDE_CODE_SESSION_ID) {
67340
+ return sessionOf({ context, harness, sessionId: inherited.CLAUDE_CODE_SESSION_ID });
67341
+ }
67342
+ if (harness === "codex" && inherited.CODEX_THREAD_ID) {
67343
+ return sessionOf({ context, harness, sessionId: inherited.CODEX_THREAD_ID });
67344
+ }
67345
+ const nearest = await nearestHarnessOf({ context });
67346
+ if (!nearest) return void 0;
67347
+ const path = statePathOf({ context, kind: "sessions", profile: String(nearest.pid) });
67348
+ return readFile4(path, "utf8").then(
67349
+ (text2) => JSON.parse(text2),
67350
+ () => void 0
67351
+ );
67352
+ }
67353
+ async function sessionProfileArgs({
67354
+ context,
67355
+ args,
67356
+ session
67357
+ }) {
67358
+ if (!session) return args;
67359
+ const key = sessionKeyOf({ session });
67360
+ const config2 = await context.store.read();
67361
+ const bound = config2.sessions?.[key];
67362
+ if (bound && config2.profiles[bound]) {
67363
+ return { ...args, flags: { ...args.flags, profile: bound } };
67364
+ }
67365
+ const own2 = flagText({ args, name: "profile" });
67366
+ if (own2 && config2.profiles[own2]?.kind === "agent") {
67367
+ await context.store.bindSession({ session: key, profile: own2 });
67368
+ }
67369
+ return args;
67370
+ }
67371
+ async function liveElsewhere({
67372
+ context,
67373
+ key,
67374
+ claudePid
67375
+ }) {
67376
+ const folder = dirname4(statePathOf({ context, kind: "sessions", profile: "x" }));
67377
+ for (const file3 of await readdir(folder).catch(() => [])) {
67378
+ const pid = Number(file3.replace(/\.json$/, ""));
67379
+ if (!pid || pid === claudePid || !context.processes.alive(pid)) continue;
67380
+ const noted = await readFile4(join4(folder, file3), "utf8").then(
67381
+ (text2) => JSON.parse(text2),
67382
+ () => void 0
67383
+ );
67384
+ if (noted && sessionKeyOf({ session: noted }) === key) return true;
67385
+ }
67386
+ return false;
67387
+ }
67388
+ function notBoundText({ meta: meta3 }) {
67389
+ return `Laze: this agent listens in another session${meta3.bound ? `: ${meta3.bound}` : ""}. Create a new Laze agent with this session: laze agent request. Or move this agent here: laze agent bind.`;
67390
+ }
67391
+ async function notBoundNotice({
67392
+ context,
67393
+ client,
67394
+ session,
67395
+ error: error62
67396
+ }) {
67397
+ if (!(error62 instanceof LazeApiError) || error62.code !== "session_not_bound") return void 0;
67398
+ const meta3 = error62.meta ?? {};
67399
+ if (client && session && meta3.session && meta3.host === session.host) {
67400
+ const claudePid = (await nearestHarnessOf({ context }))?.pid;
67401
+ if (!await liveElsewhere({ context, key: meta3.session, claudePid })) {
67402
+ await client.post("/api/agents/me/bind", {});
67403
+ return { notice: void 0, rebound: true };
67404
+ }
67405
+ }
67406
+ const key = session ? sessionKeyOf({ session }) : "unknown";
67407
+ const path = statePathOf({ context, kind: "told", profile: key });
67408
+ const told = await readFile4(path, "utf8").then(
67409
+ () => true,
67410
+ () => false
67411
+ );
67412
+ if (told) return { notice: void 0 };
67413
+ await mkdir4(dirname4(path), { recursive: true, mode: 448 });
67414
+ await writeFile4(path, String(context.nowMs()), { mode: 384 });
67415
+ return { notice: notBoundText({ meta: meta3 }) };
67416
+ }
67417
+
67418
+ // src/services/claude-wait.service.ts
67419
+ var ROUND_SECONDS = 50;
67420
+ var WATCH_MS = 2e3;
67421
+ var CHANNEL_CHECK_MS = 5e3;
67422
+ async function holderOf({ path }) {
67423
+ return readFile5(path, "utf8").then(
67424
+ (text2) => JSON.parse(text2),
67425
+ () => void 0
67426
+ );
67427
+ }
67428
+ async function holderClaudeOf({ context, holder }) {
67429
+ if (holder.claudePid) return holder.claudePid;
67430
+ return (await nearestHarnessOf({ context, from: holder.pid }))?.pid;
67431
+ }
67432
+ async function takeLock({
67433
+ context,
67434
+ path,
67435
+ sessionId,
67436
+ claudePid,
67437
+ preempt = false
67438
+ }) {
67439
+ const holder = await holderOf({ path });
67440
+ const self2 = context.processes.pid;
67441
+ if (holder && holder.pid !== self2 && context.processes.alive(holder.pid)) {
67442
+ const served = await holderClaudeOf({ context, holder });
67443
+ const mine3 = preempt && served === claudePid && !holder.monitor;
67444
+ if (served && context.processes.alive(served) && !mine3) return false;
67445
+ context.processes.stop(holder.pid);
67446
+ }
67447
+ await mkdir5(dirname5(path), { recursive: true, mode: 448 });
67448
+ await writeFile5(
67449
+ path,
67450
+ JSON.stringify({
67451
+ pid: self2,
67452
+ claudePid,
67453
+ ...sessionId ? { sessionId } : {},
67454
+ ...preempt ? { monitor: true } : {}
67455
+ })
67456
+ );
67457
+ return true;
67458
+ }
67459
+ async function channelLive({ context, profile }) {
67460
+ const holder = await holderOf({ path: statePathOf({ context, kind: "channels", profile }) });
67461
+ return holder !== void 0 && context.processes.alive(holder.pid);
67462
+ }
67463
+ async function takeRound({
67464
+ context,
67465
+ client,
67466
+ claudePid,
67467
+ session
67468
+ }) {
67469
+ const controller = new AbortController();
67470
+ const { signal } = controller;
67471
+ const watch = (async () => {
67472
+ while (!signal.aborted) {
67473
+ await context.sleep(WATCH_MS, signal);
67474
+ if (claudePid && !context.processes.alive(claudePid)) controller.abort();
67475
+ }
67476
+ })();
67477
+ try {
67478
+ return await forSession({ client, session }).post(
67479
+ "/api/agents/me/inbox",
67480
+ { waitSeconds: ROUND_SECONDS },
67481
+ { signal }
67482
+ );
67483
+ } catch (error62) {
67484
+ if (signal.aborted) return [];
67485
+ throw error62;
67486
+ } finally {
67487
+ controller.abort();
67488
+ await watch;
67489
+ }
67490
+ }
67491
+ async function roundOf({ context, client, name: name2, lock, claudePid, session, seen }) {
67492
+ if ((await holderOf({ path: lock }))?.pid !== context.processes.pid) return void 0;
67493
+ if (claudePid && !context.processes.alive(claudePid)) return void 0;
67494
+ const due = await dueFromSpool({ context, profile: name2, seen, pushedToo: true });
67495
+ if (due.length > 0) return due;
67496
+ if (await channelLive({ context, profile: name2 })) {
67497
+ await context.sleep(CHANNEL_CHECK_MS);
67498
+ return [];
67499
+ }
67500
+ const taken = await takeRound({ context, client, claudePid, session });
67501
+ if (taken.length === 0) {
67502
+ await context.sleep(1e3);
67503
+ return [];
67504
+ }
67505
+ await keepTaken({ context, profile: name2, messages: taken });
67506
+ return taken;
67507
+ }
67508
+ async function claudePidOf({ context }) {
67509
+ const harness = await nearestHarnessOf({ context });
67510
+ if (harness?.harness === "claude-code") return harness.pid;
67511
+ return await context.processes.parentOf(context.processes.pid) ?? 0;
67512
+ }
67513
+ async function settleRound(round) {
67514
+ const { context, client, name: name2, session } = round;
67515
+ const messages = await roundOf(round).catch(async (error62) => {
67516
+ const refused = await notBoundNotice({
67517
+ context,
67518
+ client: forSession({ client, session }),
67519
+ session,
67520
+ error: error62
67521
+ });
67522
+ if (!refused) throw error62;
67523
+ return refused;
67524
+ });
67525
+ if (messages === void 0) return 0;
67526
+ if (!Array.isArray(messages)) {
67527
+ if (messages.rebound) return "again";
67528
+ if (!messages.notice) return 0;
67529
+ context.err(`${messages.notice}
67530
+ `);
67531
+ return 2;
67532
+ }
67533
+ if (messages.length === 0) return "again";
67534
+ await turnStarted({ context, client, agent: name2, messages }).catch(() => void 0);
67535
+ const self2 = await currentNameOf({ context, client, profile: name2 });
67536
+ context.err(`${hookContextOf({ messages, self: self2 })}
67537
+ `);
67538
+ const messageIds = messages.map((message2) => message2.messageId);
67539
+ await dropFromSpool({ context, profile: name2, messageIds });
67540
+ return 2;
67541
+ }
67542
+ async function waitForMessages({ context, args }) {
67543
+ const raw = await context.readStdin();
67544
+ const input2 = raw.trim() ? JSON.parse(raw) : {};
67545
+ const session = sessionOf({ context, harness: "claude-code", sessionId: input2.session_id });
67546
+ const named = await sessionProfileArgs({ context, args, session });
67547
+ const { client, name: name2 } = await signedIn({ context, args: named });
67548
+ const claudePid = await claudePidOf({ context });
67549
+ await rememberSession({ context, claudePid, session });
67550
+ const lock = statePathOf({ context, kind: "waiters", profile: name2 });
67551
+ if (!await takeLock({ context, path: lock, sessionId: input2.session_id, claudePid })) return 0;
67552
+ const seen = () => input2.transcript_path ? readFile5(input2.transcript_path, "utf8") : Promise.resolve("");
67553
+ const deadline = context.nowMs() + (WAIT_HOOK_TIMEOUT_SECONDS - 60) * 1e3;
67554
+ try {
67555
+ while (context.nowMs() < deadline) {
67556
+ const code = await settleRound({ context, client, name: name2, lock, claudePid, session, seen });
67557
+ if (code !== "again") return code;
67558
+ }
67559
+ return 0;
67560
+ } finally {
67561
+ if ((await holderOf({ path: lock }))?.pid === context.processes.pid)
67562
+ await rm2(lock, { force: true });
67563
+ }
67564
+ }
67565
+ async function waitHook({ context, args }) {
67566
+ try {
67567
+ return await waitForMessages({ context, args });
67568
+ } catch (error62) {
67569
+ context.err(`laze: the background waiter stopped: ${String(error62)}
67570
+ `);
67571
+ return 0;
67572
+ }
67573
+ }
67574
+ async function monitorServes({
67575
+ context,
67576
+ profile,
67577
+ claudePid
67578
+ }) {
67579
+ const holder = await holderOf({ path: statePathOf({ context, kind: "waiters", profile }) });
67580
+ if (!holder?.monitor || !context.processes.alive(holder.pid)) return false;
67581
+ return await holderClaudeOf({ context, holder }) === claudePid;
67582
+ }
67583
+
67267
67584
  // src/services/codex-link.service.ts
67268
67585
  import { createReadStream } from "node:fs";
67269
- import { readdir as readdir3, rm as rm5, stat as stat2 } from "node:fs/promises";
67270
- import { join as join9, resolve as resolve3 } from "node:path";
67586
+ import { readdir as readdir4, rm as rm6, stat as stat2 } from "node:fs/promises";
67587
+ import { join as join10, resolve as resolve3 } from "node:path";
67271
67588
  import { createInterface as createInterface2 } from "node:readline";
67272
67589
 
67273
67590
  // src/rules/connect-service.rules.ts
@@ -67387,8 +67704,8 @@ function rolloutEventOf({
67387
67704
 
67388
67705
  // src/services/codex-adopt.service.ts
67389
67706
  import { spawn as spawn2 } from "node:child_process";
67390
- import { mkdir as mkdir4, readdir, readFile as readFile4, rm as rm2, stat, writeFile as writeFile4 } from "node:fs/promises";
67391
- import { dirname as dirname4, join as join4 } from "node:path";
67707
+ import { mkdir as mkdir6, readdir as readdir2, readFile as readFile6, rm as rm3, stat, writeFile as writeFile6 } from "node:fs/promises";
67708
+ import { dirname as dirname6, join as join5 } from "node:path";
67392
67709
  import { createInterface } from "node:readline";
67393
67710
 
67394
67711
  // src/rules/codex-requests.rules.ts
@@ -67508,11 +67825,11 @@ var CodexAppServer = class _CodexAppServer {
67508
67825
  }
67509
67826
  };
67510
67827
  async function newestThreadId({ codexHome }) {
67511
- const root = join4(codexHome, "sessions");
67512
- const files2 = await readdir(root, { recursive: true }).catch(() => []);
67828
+ const root = join5(codexHome, "sessions");
67829
+ const files2 = await readdir2(root, { recursive: true }).catch(() => []);
67513
67830
  const rollouts = files2.filter((file3) => /rollout-.*\.jsonl$/.test(file3));
67514
67831
  const dated = await Promise.all(
67515
- rollouts.map(async (file3) => ({ file: file3, at: (await stat(join4(root, file3))).mtimeMs }))
67832
+ rollouts.map(async (file3) => ({ file: file3, at: (await stat(join5(root, file3))).mtimeMs }))
67516
67833
  );
67517
67834
  const newest = dated.toSorted((a, b) => b.at - a.at)[0]?.file ?? "";
67518
67835
  const id = /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/.exec(newest);
@@ -67587,7 +67904,7 @@ async function answer({
67587
67904
  var MAX_RESTART_WAIT_SECONDS = 60;
67588
67905
  var HEALTHY_RUN_MS = 6e4;
67589
67906
  async function recordOf({ path }) {
67590
- return readFile4(path, "utf8").then(
67907
+ return readFile6(path, "utf8").then(
67591
67908
  (text2) => JSON.parse(text2),
67592
67909
  () => void 0
67593
67910
  );
@@ -67609,8 +67926,8 @@ async function startAdoptInBackground({
67609
67926
  const adopt = ["adopt", "codex", "--profile", profile, ...threadFlag({ thread: thread2 })];
67610
67927
  const argv = [...context.program, ...adopt, "--supervise"];
67611
67928
  const pid = context.processes.spawnDetached({ argv, logPath: log });
67612
- await mkdir4(dirname4(path), { recursive: true, mode: 448 });
67613
- await writeFile4(path, JSON.stringify({ pid, thread: thread2, log, startedAt: context.nowMs() }));
67929
+ await mkdir6(dirname6(path), { recursive: true, mode: 448 });
67930
+ await writeFile6(path, JSON.stringify({ pid, thread: thread2, log, startedAt: context.nowMs() }));
67614
67931
  return [
67615
67932
  `Started \`${laze} adopt codex\` in the background (pid ${pid}). It answers each Laze message`,
67616
67933
  `as a turn in ${thread2 ? `this Codex thread (${thread2})` : "the newest Codex thread"}, and starts again if it stops.`,
@@ -67665,7 +67982,7 @@ Log: ${record4.log}
67665
67982
  async function adoptStop({ context, profile }) {
67666
67983
  const path = statePathOf({ context, kind: "adopt", profile });
67667
67984
  const record4 = await recordOf({ path });
67668
- await rm2(path, { force: true });
67985
+ await rm3(path, { force: true });
67669
67986
  if (!record4 || !context.processes.stop(record4.pid)) {
67670
67987
  context.out(`laze adopt codex was not running in the background for profile "${profile}".
67671
67988
  `);
@@ -67690,7 +68007,7 @@ async function adoptedThreadOf({
67690
68007
  );
67691
68008
  if (!held) return threadId;
67692
68009
  const path = statePathOf({ context, kind: "adopt", profile, extension: "forks.json" });
67693
- const forks = await readFile4(path, "utf8").then(
68010
+ const forks = await readFile6(path, "utf8").then(
67694
68011
  (text2) => JSON.parse(text2),
67695
68012
  () => ({})
67696
68013
  );
@@ -67705,8 +68022,8 @@ async function adoptedThreadOf({
67705
68022
  }
67706
68023
  const forked = record3((await codex.call("thread/fork", { threadId })).thread).id;
67707
68024
  if (typeof forked !== "string") throw new Error("thread/fork answered no thread id");
67708
- await mkdir4(dirname4(path), { recursive: true, mode: 448 });
67709
- await writeFile4(path, JSON.stringify({ ...forks, [threadId]: forked }));
68025
+ await mkdir6(dirname6(path), { recursive: true, mode: 448 });
68026
+ await writeFile6(path, JSON.stringify({ ...forks, [threadId]: forked }));
67710
68027
  context.out(
67711
68028
  `Codex holds thread ${threadId} open elsewhere; answering in its new fork ${forked}.
67712
68029
  `
@@ -67761,43 +68078,20 @@ async function adoptCodex({ context, args }) {
67761
68078
  }
67762
68079
 
67763
68080
  // src/services/connect-delivery.service.ts
67764
- import { mkdir as mkdir6, readFile as readFile6, rename as rename3, rm as rm3, writeFile as writeFile6 } from "node:fs/promises";
67765
- import { homedir as homedir2, hostname as hostname3 } from "node:os";
67766
- import { dirname as dirname6, join as join7 } from "node:path";
67767
-
67768
- // src/rules/session-headers.rules.ts
67769
- import { relative as relative2, sep } from "node:path";
67770
- function sessionKeyOf({ session }) {
67771
- return `${session.harness}:${session.sessionId}`;
67772
- }
67773
- function sessionHeadersOf({
67774
- session
67775
- }) {
67776
- if (!session) return {};
67777
- return {
67778
- [AGENT_SESSION_HEADER]: sessionKeyOf({ session }),
67779
- [AGENT_SESSION_FOLDER_HEADER]: encodeURIComponent(session.folder),
67780
- [AGENT_SESSION_HOST_HEADER]: encodeURIComponent(session.host)
67781
- };
67782
- }
67783
- function displayFolderOf({ folder, home }) {
67784
- if (!home) return folder;
67785
- const below = relative2(home, folder);
67786
- if (below === "") return "~";
67787
- if (below.startsWith("..") || below.startsWith(sep)) return folder;
67788
- return `~/${below.split(sep).join("/")}`;
67789
- }
68081
+ import { mkdir as mkdir8, readFile as readFile8, rename as rename3, rm as rm4, writeFile as writeFile8 } from "node:fs/promises";
68082
+ import { homedir as homedir2, hostname as hostname4 } from "node:os";
68083
+ import { dirname as dirname8, join as join8 } from "node:path";
67790
68084
 
67791
68085
  // src/services/codex-turn-watch.service.ts
67792
- import { open as open2, readdir as readdir2 } from "node:fs/promises";
67793
- import { join as join5 } from "node:path";
68086
+ import { open as open2, readdir as readdir3 } from "node:fs/promises";
68087
+ import { join as join6 } from "node:path";
67794
68088
  var READ_MS = 1500;
67795
68089
  var KEEP_WORKING_MS = 3e4;
67796
68090
  async function rolloutPathOf({ delivery }) {
67797
- const root = join5(delivery.codexHome, "sessions");
67798
- const files2 = await readdir2(root, { recursive: true }).catch(() => []);
68091
+ const root = join6(delivery.codexHome, "sessions");
68092
+ const files2 = await readdir3(root, { recursive: true }).catch(() => []);
67799
68093
  const file3 = files2.find((name2) => name2.endsWith(`-${delivery.threadId}.jsonl`));
67800
- return file3 ? join5(root, file3) : void 0;
68094
+ return file3 ? join6(root, file3) : void 0;
67801
68095
  }
67802
68096
  async function readFrom({ path, offset }) {
67803
68097
  const handle = await open2(path, "r");
@@ -67883,8 +68177,8 @@ var CodexTurnWatch = class _CodexTurnWatch {
67883
68177
  };
67884
68178
 
67885
68179
  // src/services/openclaw-relay.service.ts
67886
- import { chmod as chmod2, mkdir as mkdir5, readFile as readFile5, writeFile as writeFile5 } from "node:fs/promises";
67887
- import { dirname as dirname5, join as join6 } from "node:path";
68180
+ import { chmod as chmod2, mkdir as mkdir7, readFile as readFile7, writeFile as writeFile7 } from "node:fs/promises";
68181
+ import { dirname as dirname7, join as join7 } from "node:path";
67888
68182
 
67889
68183
  // ../../modules/openclaw/contract/src/openclaw.ts
67890
68184
  var workspaceIdSchema14 = external_exports.string().min(1);
@@ -68112,11 +68406,11 @@ var STOPS = /* @__PURE__ */ new Map([
68112
68406
  [OPENCLAW_RELAY_CLOSE.replaced.code, "another relay for this gateway took over"]
68113
68407
  ]);
68114
68408
  function relaysPathOf({ context }) {
68115
- return join6(dirname5(context.environment.configPath), "connect", "openclaw-relays.json");
68409
+ return join7(dirname7(context.environment.configPath), "connect", "openclaw-relays.json");
68116
68410
  }
68117
68411
  async function readRelays({ context }) {
68118
68412
  try {
68119
- return JSON.parse(await readFile5(relaysPathOf({ context }), "utf8"));
68413
+ return JSON.parse(await readFile7(relaysPathOf({ context }), "utf8"));
68120
68414
  } catch {
68121
68415
  return {};
68122
68416
  }
@@ -68126,8 +68420,8 @@ async function saveRelays({
68126
68420
  relays
68127
68421
  }) {
68128
68422
  const path = relaysPathOf({ context });
68129
- await mkdir5(dirname5(path), { recursive: true, mode: 448 });
68130
- await writeFile5(path, `${JSON.stringify(relays, null, 2)}
68423
+ await mkdir7(dirname7(path), { recursive: true, mode: 448 });
68424
+ await writeFile7(path, `${JSON.stringify(relays, null, 2)}
68131
68425
  `, { mode: 384 });
68132
68426
  await chmod2(path, 384);
68133
68427
  }
@@ -68313,14 +68607,14 @@ var RelayLoops = class _RelayLoops {
68313
68607
 
68314
68608
  // src/services/connect-delivery.service.ts
68315
68609
  function connectFolderOf({ context }) {
68316
- return join7(dirname6(context.environment.configPath), "connect");
68610
+ return join8(dirname8(context.environment.configPath), "connect");
68317
68611
  }
68318
68612
  function runStatePathOf({ context }) {
68319
- return join7(connectFolderOf({ context }), "run.json");
68613
+ return join8(connectFolderOf({ context }), "run.json");
68320
68614
  }
68321
68615
  async function readJson({ path }) {
68322
68616
  try {
68323
- return JSON.parse(await readFile6(path, "utf8"));
68617
+ return JSON.parse(await readFile8(path, "utf8"));
68324
68618
  } catch {
68325
68619
  return void 0;
68326
68620
  }
@@ -68328,7 +68622,7 @@ async function readJson({ path }) {
68328
68622
  async function runStateOf({ context }) {
68329
68623
  return readJson({ path: runStatePathOf({ context }) });
68330
68624
  }
68331
- var ROUND_SECONDS = 50;
68625
+ var ROUND_SECONDS2 = 50;
68332
68626
  var REFRESH_MS = 3e4;
68333
68627
  var MAX_RETRY_SECONDS2 = 60;
68334
68628
  var CodexQueueError = class extends Error {
@@ -68360,7 +68654,7 @@ async function queueInCodex({
68360
68654
  throw new CodexQueueError(codexQueueFailureOf({ stderr: stderr2 }), stderr2.trim() || `exit ${code}`);
68361
68655
  }
68362
68656
  }
68363
- async function takeRound({
68657
+ async function takeRound2({
68364
68658
  client,
68365
68659
  signal,
68366
68660
  delivery
@@ -68369,10 +68663,10 @@ async function takeRound({
68369
68663
  harness: "codex",
68370
68664
  sessionId: delivery.threadId,
68371
68665
  folder: displayFolderOf({ folder: delivery.cwd, home: homedir2() }),
68372
- host: hostname3()
68666
+ host: hostname4()
68373
68667
  };
68374
68668
  try {
68375
- return await client.withHeaders(sessionHeadersOf({ session })).post("/api/agents/me/inbox", { waitSeconds: ROUND_SECONDS }, { signal });
68669
+ return await client.withHeaders(sessionHeadersOf({ session })).post("/api/agents/me/inbox", { waitSeconds: ROUND_SECONDS2 }, { signal });
68376
68670
  } catch (error62) {
68377
68671
  if (signal.aborted) return [];
68378
68672
  throw error62;
@@ -68387,7 +68681,7 @@ async function deliverRound({
68387
68681
  watch
68388
68682
  }) {
68389
68683
  const kept = await dueFromSpool({ context, profile, seen: async () => "", pushedToo: true });
68390
- const messages = kept.length > 0 ? kept : await takeRound({ client, signal, delivery });
68684
+ const messages = kept.length > 0 ? kept : await takeRound2({ client, signal, delivery });
68391
68685
  if (messages.length === 0) return 0;
68392
68686
  if (kept.length === 0) await keepTaken({ context, profile, messages });
68393
68687
  const self2 = await currentNameOf({ context, client, profile });
@@ -68470,9 +68764,9 @@ async function serveRounds({
68470
68764
  }
68471
68765
  var saves = 0;
68472
68766
  async function save(run4) {
68473
- await mkdir6(dirname6(run4.path), { recursive: true, mode: 448 });
68767
+ await mkdir8(dirname8(run4.path), { recursive: true, mode: 448 });
68474
68768
  const temporary = `${run4.path}.${run4.self}.${saves += 1}.tmp`;
68475
- await writeFile6(temporary, JSON.stringify(run4.state));
68769
+ await writeFile8(temporary, JSON.stringify(run4.state));
68476
68770
  await rename3(temporary, run4.path);
68477
68771
  }
68478
68772
  async function holdsLock(run4) {
@@ -68546,15 +68840,15 @@ async function runConnectLoop({ context }) {
68546
68840
  await relays.stopAll();
68547
68841
  for (const current2 of run4.served.values()) current2.stop.abort();
68548
68842
  await Promise.all([...run4.served.values()].map((current2) => current2.done));
68549
- if (await holdsLock(run4)) await rm3(run4.path, { force: true });
68843
+ if (await holdsLock(run4)) await rm4(run4.path, { force: true });
68550
68844
  }
68551
68845
  return 0;
68552
68846
  }
68553
68847
 
68554
68848
  // src/services/connect-service.service.ts
68555
68849
  import { createHash } from "node:crypto";
68556
- import { mkdir as mkdir7, rm as rm4, writeFile as writeFile7 } from "node:fs/promises";
68557
- import { dirname as dirname7, join as join8 } from "node:path";
68850
+ import { mkdir as mkdir9, rm as rm5, writeFile as writeFile9 } from "node:fs/promises";
68851
+ import { dirname as dirname9, join as join9 } from "node:path";
68558
68852
  var CONNECT_SERVICE_USAGE = `laze connect install|status|stop|uninstall|run: the service that delivers to linked Codex sessions.
68559
68853
 
68560
68854
  laze connect install install and start it (systemd --user, a LaunchAgent, or detached)
@@ -68567,17 +68861,17 @@ var CONNECT_SERVICE_USAGE = `laze connect install|status|stop|uninstall|run: the
68567
68861
  \`laze openclaw connect --local\`, whose OpenClaw relay it also runs.
68568
68862
  `;
68569
68863
  function installedPathOf({ context }) {
68570
- return join8(connectFolderOf({ context }), "service.json");
68864
+ return join9(connectFolderOf({ context }), "service.json");
68571
68865
  }
68572
68866
  function logPathOf({ context }) {
68573
- return join8(connectFolderOf({ context }), "connect.log");
68867
+ return join9(connectFolderOf({ context }), "connect.log");
68574
68868
  }
68575
68869
  function homeOf({ context }) {
68576
- return context.environment.inherited.HOME ?? dirname7(dirname7(context.environment.configPath));
68870
+ return context.environment.inherited.HOME ?? dirname9(dirname9(context.environment.configPath));
68577
68871
  }
68578
68872
  function serviceNameOf({ context }) {
68579
68873
  const { configPath } = context.environment;
68580
- if (configPath === join8(homeOf({ context }), ".laze", "config.json")) return "laze-connect";
68874
+ if (configPath === join9(homeOf({ context }), ".laze", "config.json")) return "laze-connect";
68581
68875
  return `laze-connect-${createHash("sha256").update(configPath).digest("hex").slice(0, 8)}`;
68582
68876
  }
68583
68877
  function serviceEnvOf({ context }) {
@@ -68600,10 +68894,10 @@ async function run({ context, command }) {
68600
68894
  async function installSystemd({ context }) {
68601
68895
  const name2 = serviceNameOf({ context });
68602
68896
  const env = context.environment.inherited;
68603
- const base = env.XDG_CONFIG_HOME || join8(homeOf({ context }), ".config");
68604
- const file3 = join8(base, "systemd", "user", `${name2}.service`);
68605
- await mkdir7(dirname7(file3), { recursive: true });
68606
- await writeFile7(
68897
+ const base = env.XDG_CONFIG_HOME || join9(homeOf({ context }), ".config");
68898
+ const file3 = join9(base, "systemd", "user", `${name2}.service`);
68899
+ await mkdir9(dirname9(file3), { recursive: true });
68900
+ await writeFile9(
68607
68901
  file3,
68608
68902
  systemdUnitOf({ argv: runArgvOf({ context }), env: serviceEnvOf({ context }) })
68609
68903
  );
@@ -68616,10 +68910,10 @@ async function installSystemd({ context }) {
68616
68910
  async function installLaunchd({ context }) {
68617
68911
  const name2 = serviceNameOf({ context });
68618
68912
  const label2 = `ai.laze.${name2}`;
68619
- const file3 = join8(homeOf({ context }), "Library", "LaunchAgents", `${label2}.plist`);
68913
+ const file3 = join9(homeOf({ context }), "Library", "LaunchAgents", `${label2}.plist`);
68620
68914
  const log = logPathOf({ context });
68621
- await mkdir7(dirname7(file3), { recursive: true });
68622
- await writeFile7(
68915
+ await mkdir9(dirname9(file3), { recursive: true });
68916
+ await writeFile9(
68623
68917
  file3,
68624
68918
  launchAgentOf({
68625
68919
  label: label2,
@@ -68671,8 +68965,8 @@ async function installConnectService({ context }) {
68671
68965
  const manager = await managerOf({ context });
68672
68966
  const install = { systemd: installSystemd, launchd: installLaunchd, detached: installDetached };
68673
68967
  const installed = await install[manager]({ context });
68674
- await mkdir7(dirname7(path), { recursive: true, mode: 448 });
68675
- await writeFile7(path, JSON.stringify(installed));
68968
+ await mkdir9(dirname9(path), { recursive: true, mode: 448 });
68969
+ await writeFile9(path, JSON.stringify(installed));
68676
68970
  return describeInstalled({ installed });
68677
68971
  }
68678
68972
  function describeInstalled({ installed }) {
@@ -68738,11 +69032,11 @@ async function uninstall({ context }) {
68738
69032
  command: ["systemctl", "--user", "disable", `${installed.name}.service`]
68739
69033
  });
68740
69034
  }
68741
- if (installed.file) await rm4(installed.file, { force: true });
69035
+ if (installed.file) await rm5(installed.file, { force: true });
68742
69036
  if (installed.manager === "systemd") {
68743
69037
  await run({ context, command: ["systemctl", "--user", "daemon-reload"] });
68744
69038
  }
68745
- await rm4(path, { force: true });
69039
+ await rm5(path, { force: true });
68746
69040
  context.out(
68747
69041
  `Removed the connect service (${installed.manager}, ${installed.name}). Linked Codex agents get no messages until \`laze connect install\`.
68748
69042
  `
@@ -68784,13 +69078,13 @@ async function newestThreadIn({
68784
69078
  codexHome,
68785
69079
  directory
68786
69080
  }) {
68787
- const root = join9(codexHome, "sessions");
68788
- const files2 = await readdir3(root, { recursive: true }).catch(() => []);
69081
+ const root = join10(codexHome, "sessions");
69082
+ const files2 = await readdir4(root, { recursive: true }).catch(() => []);
68789
69083
  const rollouts = files2.filter((file3) => /rollout-.*\.jsonl$/.test(file3));
68790
69084
  const dated = await Promise.all(
68791
69085
  rollouts.map(async (file3) => ({
68792
- path: join9(root, file3),
68793
- at: await stat2(join9(root, file3)).then(
69086
+ path: join10(root, file3),
69087
+ at: await stat2(join10(root, file3)).then(
68794
69088
  (info) => info.mtimeMs,
68795
69089
  () => 0
68796
69090
  )
@@ -68821,7 +69115,7 @@ async function stopAdopt({ context, profile }) {
68821
69115
  const running = await readJson({ path });
68822
69116
  if (!running) return;
68823
69117
  context.processes.stop(running.pid);
68824
- await rm5(path, { force: true });
69118
+ await rm6(path, { force: true });
68825
69119
  }
68826
69120
  async function linkCodexSession({
68827
69121
  context,
@@ -68857,131 +69151,9 @@ async function linkCodexSession({
68857
69151
  ].join("\n");
68858
69152
  }
68859
69153
 
68860
- // src/services/harness-session.service.ts
68861
- import { mkdir as mkdir8, readdir as readdir4, readFile as readFile7, writeFile as writeFile8 } from "node:fs/promises";
68862
- import { hostname as hostname4 } from "node:os";
68863
- import { dirname as dirname8, join as join10 } from "node:path";
68864
- function sessionOf({
68865
- context,
68866
- harness,
68867
- sessionId
68868
- }) {
68869
- if (!sessionId) return void 0;
68870
- const inherited = context.environment.inherited;
68871
- const folder = inherited.CLAUDE_PROJECT_DIR || context.cwd;
68872
- return {
68873
- harness,
68874
- sessionId,
68875
- folder: displayFolderOf({ folder, home: inherited.HOME }),
68876
- host: hostname4()
68877
- };
68878
- }
68879
- function forSession({
68880
- client,
68881
- session
68882
- }) {
68883
- return client.withHeaders(sessionHeadersOf({ session }));
68884
- }
68885
- async function rememberSession({
68886
- context,
68887
- claudePid,
68888
- session
68889
- }) {
68890
- if (!session || !claudePid) return;
68891
- const path = statePathOf({ context, kind: "sessions", profile: String(claudePid) });
68892
- await mkdir8(dirname8(path), { recursive: true, mode: 448 });
68893
- await writeFile8(path, JSON.stringify(session), { mode: 384 });
68894
- }
68895
- async function currentSessionOf({
68896
- context,
68897
- args
68898
- }) {
68899
- const inherited = context.environment.inherited;
68900
- const named = flagText({ args, name: "session" });
68901
- const harness = context.environment.harness;
68902
- if (named) return sessionOf({ context, harness, sessionId: named });
68903
- if (harness === "claude-code" && inherited.CLAUDE_CODE_SESSION_ID) {
68904
- return sessionOf({ context, harness, sessionId: inherited.CLAUDE_CODE_SESSION_ID });
68905
- }
68906
- if (harness === "codex" && inherited.CODEX_THREAD_ID) {
68907
- return sessionOf({ context, harness, sessionId: inherited.CODEX_THREAD_ID });
68908
- }
68909
- const nearest = await nearestHarnessOf({ context });
68910
- if (!nearest) return void 0;
68911
- const path = statePathOf({ context, kind: "sessions", profile: String(nearest.pid) });
68912
- return readFile7(path, "utf8").then(
68913
- (text2) => JSON.parse(text2),
68914
- () => void 0
68915
- );
68916
- }
68917
- async function sessionProfileArgs({
68918
- context,
68919
- args,
68920
- session
68921
- }) {
68922
- if (!session) return args;
68923
- const key = sessionKeyOf({ session });
68924
- const config2 = await context.store.read();
68925
- const bound = config2.sessions?.[key];
68926
- if (bound && config2.profiles[bound]) {
68927
- return { ...args, flags: { ...args.flags, profile: bound } };
68928
- }
68929
- const own2 = flagText({ args, name: "profile" });
68930
- if (own2 && config2.profiles[own2]?.kind === "agent") {
68931
- await context.store.bindSession({ session: key, profile: own2 });
68932
- }
68933
- return args;
68934
- }
68935
- async function liveElsewhere({
68936
- context,
68937
- key,
68938
- claudePid
68939
- }) {
68940
- const folder = dirname8(statePathOf({ context, kind: "sessions", profile: "x" }));
68941
- for (const file3 of await readdir4(folder).catch(() => [])) {
68942
- const pid = Number(file3.replace(/\.json$/, ""));
68943
- if (!pid || pid === claudePid || !context.processes.alive(pid)) continue;
68944
- const noted = await readFile7(join10(folder, file3), "utf8").then(
68945
- (text2) => JSON.parse(text2),
68946
- () => void 0
68947
- );
68948
- if (noted && sessionKeyOf({ session: noted }) === key) return true;
68949
- }
68950
- return false;
68951
- }
68952
- function notBoundText({ meta: meta3 }) {
68953
- return `Laze: this agent listens in another session${meta3.bound ? `: ${meta3.bound}` : ""}. Create a new Laze agent with this session: laze agent request. Or move this agent here: laze agent bind.`;
68954
- }
68955
- async function notBoundNotice({
68956
- context,
68957
- client,
68958
- session,
68959
- error: error62
68960
- }) {
68961
- if (!(error62 instanceof LazeApiError) || error62.code !== "session_not_bound") return void 0;
68962
- const meta3 = error62.meta ?? {};
68963
- if (client && session && meta3.session && meta3.host === session.host) {
68964
- const claudePid = (await nearestHarnessOf({ context }))?.pid;
68965
- if (!await liveElsewhere({ context, key: meta3.session, claudePid })) {
68966
- await client.post("/api/agents/me/bind", {});
68967
- return { notice: void 0, rebound: true };
68968
- }
68969
- }
68970
- const key = session ? sessionKeyOf({ session }) : "unknown";
68971
- const path = statePathOf({ context, kind: "told", profile: key });
68972
- const told = await readFile7(path, "utf8").then(
68973
- () => true,
68974
- () => false
68975
- );
68976
- if (told) return { notice: void 0 };
68977
- await mkdir8(dirname8(path), { recursive: true, mode: 448 });
68978
- await writeFile8(path, String(context.nowMs()), { mode: 384 });
68979
- return { notice: notBoundText({ meta: meta3 }) };
68980
- }
68981
-
68982
69154
  // src/services/laze-plugin.service.ts
68983
- import { mkdir as mkdir9, readFile as readFile8, writeFile as writeFile9 } from "node:fs/promises";
68984
- import { dirname as dirname9, join as join11 } from "node:path";
69155
+ import { mkdir as mkdir10, readFile as readFile9, writeFile as writeFile10 } from "node:fs/promises";
69156
+ import { dirname as dirname10, join as join11 } from "node:path";
68985
69157
 
68986
69158
  // src/rules/laze-plugin.rules.ts
68987
69159
  var LAZE_PLUGIN = "laze";
@@ -69073,11 +69245,11 @@ function lazePluginFiles({
69073
69245
  var REGISTER_LIMIT_MS = 6e4;
69074
69246
  var quote2 = (value) => `'${value.replaceAll("'", "'\\''")}'`;
69075
69247
  function pluginFolderOf({ context }) {
69076
- return join11(dirname9(context.environment.configPath), "plugins");
69248
+ return join11(dirname10(context.environment.configPath), "plugins");
69077
69249
  }
69078
69250
  async function pluginIsCurrent({ context }) {
69079
69251
  const manifest = join11(pluginFolderOf({ context }), LAZE_PLUGIN, ".claude-plugin", "plugin.json");
69080
- const written = await readFile8(manifest, "utf8").then(
69252
+ const written = await readFile9(manifest, "utf8").then(
69081
69253
  (text2) => JSON.parse(text2).version,
69082
69254
  () => void 0
69083
69255
  );
@@ -69088,8 +69260,8 @@ async function writeLazePlugin({ context }) {
69088
69260
  const files2 = lazePluginFiles({ program: context.program, version: cliVersionOf() });
69089
69261
  for (const [path, text2] of Object.entries(files2)) {
69090
69262
  const target = join11(folder, path);
69091
- await mkdir9(dirname9(target), { recursive: true });
69092
- await writeFile9(target, text2);
69263
+ await mkdir10(dirname10(target), { recursive: true });
69264
+ await writeFile10(target, text2);
69093
69265
  }
69094
69266
  return folder;
69095
69267
  }
@@ -69107,9 +69279,19 @@ async function registerWithClaude({ context, folder }) {
69107
69279
  done.abort();
69108
69280
  return code === 0;
69109
69281
  }
69282
+ function registeredMarkOf({ context }) {
69283
+ return join11(pluginFolderOf({ context }), "registered");
69284
+ }
69285
+ async function pluginRegistered({ context }) {
69286
+ return readFile9(registeredMarkOf({ context }), "utf8").then(
69287
+ () => true,
69288
+ () => false
69289
+ );
69290
+ }
69110
69291
  async function installLazePlugin({ context }) {
69111
69292
  const folder = await writeLazePlugin({ context });
69112
69293
  const registered = await registerWithClaude({ context, folder });
69294
+ if (registered) await writeFile10(registeredMarkOf({ context }), cliVersionOf());
69113
69295
  return { folder, registered };
69114
69296
  }
69115
69297
  async function plugin({ context, args }) {
@@ -69133,11 +69315,11 @@ async function plugin({ context, args }) {
69133
69315
  }
69134
69316
 
69135
69317
  // src/services/mcp-channel.service.ts
69136
- import { mkdir as mkdir10, rm as rm6, writeFile as writeFile10 } from "node:fs/promises";
69137
- import { dirname as dirname10 } from "node:path";
69318
+ import { mkdir as mkdir11, rm as rm7, writeFile as writeFile11 } from "node:fs/promises";
69319
+ import { dirname as dirname11 } from "node:path";
69138
69320
  var LAZE_MCP_SERVER = "laze";
69139
69321
  var DEV_CHANNELS_FLAG = "--dangerously-load-development-channels";
69140
- var ROUND_SECONDS2 = 50;
69322
+ var ROUND_SECONDS3 = 50;
69141
69323
  var RETRY_MS = 5e3;
69142
69324
  function channelInstructionsOf({ server }) {
69143
69325
  return [
@@ -69224,11 +69406,11 @@ async function pushInbox({
69224
69406
  signal
69225
69407
  }) {
69226
69408
  const marker = statePathOf({ context, kind: "channels", profile });
69227
- await mkdir10(dirname10(marker), { recursive: true, mode: 448 });
69228
- await writeFile10(marker, JSON.stringify({ pid: context.processes.pid }));
69409
+ await mkdir11(dirname11(marker), { recursive: true, mode: 448 });
69410
+ await writeFile11(marker, JSON.stringify({ pid: context.processes.pid }));
69229
69411
  try {
69230
69412
  while (!signal.aborted) {
69231
- const messages = await client.post("/api/agents/me/inbox", { waitSeconds: ROUND_SECONDS2 }, { signal }).catch(async (error62) => {
69413
+ const messages = await client.post("/api/agents/me/inbox", { waitSeconds: ROUND_SECONDS3 }, { signal }).catch(async (error62) => {
69232
69414
  if (signal.aborted) return [];
69233
69415
  context.err(`laze mcp: could not read the inbox: ${String(error62)}
69234
69416
  `);
@@ -69247,10 +69429,41 @@ async function pushInbox({
69247
69429
  `);
69248
69430
  }
69249
69431
  } finally {
69250
- await rm6(marker, { force: true });
69432
+ await rm7(marker, { force: true });
69251
69433
  }
69252
69434
  }
69253
69435
 
69436
+ // src/services/plugin-tip.service.ts
69437
+ import { mkdir as mkdir12, readFile as readFile10, writeFile as writeFile12 } from "node:fs/promises";
69438
+ import { dirname as dirname12 } from "node:path";
69439
+ var RELOAD_TIP = "Laze: the Laze plugin is installed in Claude Code, and this session has not loaded it yet. Tell the user once, in one plain line, that it is optional: typing /reload-plugins makes Laze messages arrive right away; until then they still arrive through the hooks.";
69440
+ var LINK_RELOAD_TIP = "Tell the user once, in one plain line, that it is optional: typing /reload-plugins makes Laze messages arrive right away; until then they still arrive through the hooks.";
69441
+ function toldPathOf({ context, session }) {
69442
+ return statePathOf({ context, kind: "told", profile: `plugin-${sessionKeyOf({ session })}` });
69443
+ }
69444
+ async function markReloadTipTold({
69445
+ context,
69446
+ session
69447
+ }) {
69448
+ if (!session) return;
69449
+ const path = toldPathOf({ context, session });
69450
+ await mkdir12(dirname12(path), { recursive: true, mode: 448 });
69451
+ await writeFile12(path, String(context.nowMs()), { mode: 384 });
69452
+ }
69453
+ async function reloadTipOnce({
69454
+ context,
69455
+ session
69456
+ }) {
69457
+ if (!session || !await pluginRegistered({ context })) return void 0;
69458
+ const told = await readFile10(toldPathOf({ context, session }), "utf8").then(
69459
+ () => true,
69460
+ () => false
69461
+ );
69462
+ if (told) return void 0;
69463
+ await markReloadTipTold({ context, session });
69464
+ return RELOAD_TIP;
69465
+ }
69466
+
69254
69467
  // src/services/agent-commands.service.ts
69255
69468
  function percentOf(agent2) {
69256
69469
  const { contextTokens, contextWindow } = agent2.context;
@@ -69310,7 +69523,7 @@ async function installHooks({
69310
69523
  }) {
69311
69524
  const folder = join12(directory, ".claude");
69312
69525
  const path = join12(folder, "settings.local.json");
69313
- const current2 = await readFile9(path, "utf8").then(
69526
+ const current2 = await readFile11(path, "utf8").then(
69314
69527
  (text2) => JSON.parse(text2),
69315
69528
  () => ({})
69316
69529
  );
@@ -69321,8 +69534,8 @@ async function installHooks({
69321
69534
  waitCommand: command("wait"),
69322
69535
  preToolCommand: command("pre-tool")
69323
69536
  });
69324
- await mkdir11(folder, { recursive: true });
69325
- await writeFile11(path, `${JSON.stringify(settings2, null, 2)}
69537
+ await mkdir13(folder, { recursive: true });
69538
+ await writeFile13(path, `${JSON.stringify(settings2, null, 2)}
69326
69539
  `);
69327
69540
  return path;
69328
69541
  }
@@ -69350,7 +69563,8 @@ function pluginLinesOf({ plugin: plugin2 }) {
69350
69563
  if (plugin2 === void 0) return [];
69351
69564
  if (!plugin2) return ["Claude Code did not take the Laze plugin; the hooks deliver on their own."];
69352
69565
  return [
69353
- "The Laze plugin is installed in Claude Code: from the next start or resume it delivers too."
69566
+ "The Laze plugin is installed in Claude Code: from the next start or resume it delivers too.",
69567
+ LINK_RELOAD_TIP
69354
69568
  ];
69355
69569
  }
69356
69570
  function mcpLinesOf({
@@ -69505,6 +69719,9 @@ async function nextStepsFor({
69505
69719
  if (harness === "codex") return linkCodexSession({ context, args, profile, laze, directory });
69506
69720
  if (!hooked) return waiterStepsOf({ profile, laze });
69507
69721
  const plugin2 = args.flags["no-plugin"] ? void 0 : await installLazePlugin({ context });
69722
+ if (plugin2?.registered) {
69723
+ await markReloadTipTold({ context, session: await currentSessionOf({ context, args }) });
69724
+ }
69508
69725
  const mcp2 = args.flags.mcp ? await registerMcp({ context, directory, profile }) : void 0;
69509
69726
  const mcpAdd2 = mcpAddCommandOf({ context, profile });
69510
69727
  return claudeStepsOf({ profile, laze, directory, mcp: mcp2, mcpAdd: mcpAdd2, plugin: plugin2?.registered });
@@ -69514,7 +69731,7 @@ async function reportTranscript({
69514
69731
  input: input2
69515
69732
  }) {
69516
69733
  if (!input2.transcript_path || !input2.session_id) return;
69517
- const lines = (await readFile9(input2.transcript_path, "utf8")).split("\n");
69734
+ const lines = (await readFile11(input2.transcript_path, "utf8")).split("\n");
69518
69735
  const context = readTranscript({ lines });
69519
69736
  await client.post("/api/agents/me/activity", {
69520
69737
  sessionId: input2.session_id,
@@ -69523,6 +69740,10 @@ async function reportTranscript({
69523
69740
  compactions: context.compactions.slice(-20)
69524
69741
  });
69525
69742
  }
69743
+ function stopContext({ context, text: text2 }) {
69744
+ const hookSpecificOutput = { hookEventName: "Stop", additionalContext: text2 };
69745
+ context.out(JSON.stringify({ hookSpecificOutput }));
69746
+ }
69526
69747
  async function handOver({ context, args }) {
69527
69748
  const raw = await context.readStdin();
69528
69749
  const input2 = raw.trim() ? JSON.parse(raw) : {};
@@ -69534,10 +69755,14 @@ async function handOver({ context, args }) {
69534
69755
  `)
69535
69756
  );
69536
69757
  if (input2.stop_hook_active) return;
69758
+ const claudePid = await claudePidOf({ context });
69759
+ if (await monitorServes({ context, profile: agent2, claudePid })) {
69760
+ return turnEnded({ context, client, agent: agent2 });
69761
+ }
69537
69762
  const kept = await dueFromSpool({
69538
69763
  context,
69539
69764
  profile: agent2,
69540
- seen: () => input2.transcript_path ? readFile9(input2.transcript_path, "utf8") : Promise.resolve(""),
69765
+ seen: () => input2.transcript_path ? readFile11(input2.transcript_path, "utf8") : Promise.resolve(""),
69541
69766
  pushedToo: false
69542
69767
  });
69543
69768
  const claim3 = forSession({ client, session });
@@ -69547,20 +69772,23 @@ async function handOver({ context, args }) {
69547
69772
  } catch (error62) {
69548
69773
  const refused = await notBoundNotice({ context, client: claim3, session, error: error62 });
69549
69774
  if (!refused) throw error62;
69550
- if (!refused.notice) return;
69551
- const additionalContext2 = refused.notice;
69552
- context.out(
69553
- JSON.stringify({ hookSpecificOutput: { hookEventName: "Stop", additionalContext: additionalContext2 } })
69554
- );
69775
+ if (refused.notice) stopContext({ context, text: refused.notice });
69555
69776
  return;
69556
69777
  }
69557
69778
  await keepTaken({ context, profile: agent2, messages: fresh });
69558
69779
  const messages = [...kept, ...fresh];
69559
- if (messages.length === 0) return turnEnded({ context, client, agent: agent2 });
69780
+ const tip = await reloadTipOnce({ context, session });
69781
+ if (messages.length === 0) {
69782
+ await turnEnded({ context, client, agent: agent2 });
69783
+ if (tip) stopContext({ context, text: tip });
69784
+ return;
69785
+ }
69560
69786
  await turnStarted({ context, client, agent: agent2, messages });
69561
69787
  const self2 = await currentNameOf({ context, client, profile: agent2 });
69562
- const additionalContext = hookContextOf({ messages, self: self2 });
69563
- context.out(JSON.stringify({ hookSpecificOutput: { hookEventName: "Stop", additionalContext } }));
69788
+ stopContext({
69789
+ context,
69790
+ text: [hookContextOf({ messages, self: self2 }), tip].filter(Boolean).join("\n\n")
69791
+ });
69564
69792
  const messageIds = messages.map((message2) => message2.messageId);
69565
69793
  await dropFromSpool({ context, profile: agent2, messageIds });
69566
69794
  }
@@ -69569,7 +69797,7 @@ async function addSessionStartWaiter({ context, args }) {
69569
69797
  const profile = flagText({ args, name: "profile" });
69570
69798
  if (!directory || !profile) return;
69571
69799
  const path = join12(directory, ".claude", "settings.local.json");
69572
- const settings2 = await readFile9(path, "utf8").then(
69800
+ const settings2 = await readFile11(path, "utf8").then(
69573
69801
  (text2) => JSON.parse(text2),
69574
69802
  () => void 0
69575
69803
  );
@@ -69596,7 +69824,7 @@ async function stopHook({ context, args }) {
69596
69824
  }
69597
69825
 
69598
69826
  // src/services/agent-manage-commands.service.ts
69599
- import { readFile as readFile10 } from "node:fs/promises";
69827
+ import { readFile as readFile12 } from "node:fs/promises";
69600
69828
  import { extname, resolve as resolve5 } from "node:path";
69601
69829
 
69602
69830
  // src/rules/login-format.rules.ts
@@ -69725,7 +69953,7 @@ async function avatarOf({
69725
69953
  }) {
69726
69954
  const path = flagText({ args, name: "avatar" });
69727
69955
  if (!path) return void 0;
69728
- const bytes = await readFile10(resolve5(context.cwd, path)).catch(() => {
69956
+ const bytes = await readFile12(resolve5(context.cwd, path)).catch(() => {
69729
69957
  throw new CliUsageError(`laze: cannot read the avatar file ${path}.`);
69730
69958
  });
69731
69959
  const uploaded = await client.post("/api/agents/avatars", {
@@ -70415,8 +70643,8 @@ async function requestAgent({ context, args }) {
70415
70643
  }
70416
70644
 
70417
70645
  // src/services/app-commands.service.ts
70418
- import { mkdir as mkdir12, readdir as readdir5, readFile as readFile11, writeFile as writeFile13 } from "node:fs/promises";
70419
- import { dirname as dirname11, join as join14, relative as relative3, resolve as resolve6, sep as sep2 } from "node:path";
70646
+ import { mkdir as mkdir14, readdir as readdir5, readFile as readFile13, writeFile as writeFile15 } from "node:fs/promises";
70647
+ import { dirname as dirname13, join as join14, relative as relative3, resolve as resolve6, sep as sep2 } from "node:path";
70420
70648
 
70421
70649
  // ../../modules/app/contract/src/app.connections.ts
70422
70650
  var appFunctionNameSchema = external_exports.string().regex(/^[a-z0-9][a-z0-9_-]{0,63}$/);
@@ -72807,7 +73035,7 @@ async function appPinsCommand({
72807
73035
 
72808
73036
  // src/services/app-script-check.service.ts
72809
73037
  import { execFile } from "node:child_process";
72810
- import { mkdtemp, rm as rm7, writeFile as writeFile12 } from "node:fs/promises";
73038
+ import { mkdtemp, rm as rm8, writeFile as writeFile14 } from "node:fs/promises";
72811
73039
  import { tmpdir } from "node:os";
72812
73040
  import { join as join13 } from "node:path";
72813
73041
  import { promisify } from "node:util";
@@ -72843,7 +73071,7 @@ async function scriptErrorsOf({
72843
73071
  const errors = await Promise.all(
72844
73072
  scripts.map(async (script, index) => {
72845
73073
  const file3 = join13(dir, `${index}.${script.module ? "mjs" : "cjs"}`);
72846
- await writeFile12(file3, script.code);
73074
+ await writeFile14(file3, script.code);
72847
73075
  try {
72848
73076
  await run2(process.execPath, ["--check", file3]);
72849
73077
  return null;
@@ -72855,7 +73083,7 @@ async function scriptErrorsOf({
72855
73083
  );
72856
73084
  return [...errors.filter((error62) => error62 !== null), ...unknown2];
72857
73085
  } finally {
72858
- await rm7(dir, { recursive: true, force: true });
73086
+ await rm8(dir, { recursive: true, force: true });
72859
73087
  }
72860
73088
  }
72861
73089
 
@@ -72992,7 +73220,7 @@ async function turnTokenOf({
72992
73220
  const pinned = env.LAZE_TURN_TOKEN?.trim();
72993
73221
  if (pinned) return pinned;
72994
73222
  if (env.LAZE_TURN_FILE) {
72995
- return readFile11(env.LAZE_TURN_FILE, "utf8").then(
73223
+ return readFile13(env.LAZE_TURN_FILE, "utf8").then(
72996
73224
  (text2) => text2.trim(),
72997
73225
  () => ""
72998
73226
  );
@@ -73018,7 +73246,7 @@ function folderOf({ context, word: word3 }) {
73018
73246
  return resolve6(context.cwd, word3 ?? ".");
73019
73247
  }
73020
73248
  async function readManifest(folder) {
73021
- const text2 = await readFile11(join14(folder, APP_MANIFEST_FILE), "utf8").catch(() => void 0);
73249
+ const text2 = await readFile13(join14(folder, APP_MANIFEST_FILE), "utf8").catch(() => void 0);
73022
73250
  if (text2 === void 0) return void 0;
73023
73251
  const parsed = appManifestSchema.safeParse(JSON.parse(text2));
73024
73252
  if (!parsed.success) {
@@ -73053,7 +73281,7 @@ async function jsonFlag({
73053
73281
  }) {
73054
73282
  const raw = flagText({ args, name: name2 });
73055
73283
  if (!raw) return void 0;
73056
- const text2 = raw.startsWith("@") ? await readFile11(resolve6(context.cwd, raw.slice(1)), "utf8") : raw;
73284
+ const text2 = raw.startsWith("@") ? await readFile13(resolve6(context.cwd, raw.slice(1)), "utf8") : raw;
73057
73285
  try {
73058
73286
  return JSON.parse(text2);
73059
73287
  } catch {
@@ -73107,11 +73335,11 @@ var appCreate = async ({ context, args }) => {
73107
73335
  ...visibility ? { visibility } : {}
73108
73336
  });
73109
73337
  const folder = resolve6(context.cwd, flagText({ args, name: "dir", fallback: app2.slug }));
73110
- await mkdir12(folder, { recursive: true });
73338
+ await mkdir14(folder, { recursive: true });
73111
73339
  const files2 = template ? templateFiles({ template, name: name2 }) : {};
73112
73340
  for (const [path, content] of Object.entries(files2)) {
73113
- await mkdir12(dirname11(join14(folder, path)), { recursive: true });
73114
- await writeFile13(join14(folder, path), content);
73341
+ await mkdir14(dirname13(join14(folder, path)), { recursive: true });
73342
+ await writeFile15(join14(folder, path), content);
73115
73343
  }
73116
73344
  const manifest = {
73117
73345
  app: { id: app2.id, name: app2.name, slug: app2.slug },
@@ -73119,7 +73347,7 @@ var appCreate = async ({ context, args }) => {
73119
73347
  views: template?.views ? [...template.views] : [],
73120
73348
  seed: template ? { ...template.seed } : {}
73121
73349
  };
73122
- await writeFile13(join14(folder, APP_MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}
73350
+ await writeFile15(join14(folder, APP_MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}
73123
73351
  `);
73124
73352
  print5({
73125
73353
  context,
@@ -73156,7 +73384,7 @@ var appPush = async ({ context, args }) => {
73156
73384
  paths.map(
73157
73385
  async (path) => buildFileOf({
73158
73386
  path: relative3(folder, path).split(sep2).join("/"),
73159
- bytes: await readFile11(path)
73387
+ bytes: await readFile13(path)
73160
73388
  })
73161
73389
  )
73162
73390
  );
@@ -73531,7 +73759,7 @@ var appExport = async ({ context, args }) => {
73531
73759
  const out = flagText({ args, name: "out" });
73532
73760
  if (!out) return context.out(exported.body);
73533
73761
  const target = resolve6(context.cwd, out);
73534
- await writeFile13(target, exported.body);
73762
+ await writeFile15(target, exported.body);
73535
73763
  context.out(`Wrote ${exported.rows} records to ${relative3(context.cwd, target)}
73536
73764
  `);
73537
73765
  };
@@ -73539,7 +73767,7 @@ var appImport = async ({ context, args }) => {
73539
73767
  const words = args.words.slice(2);
73540
73768
  const [named, collection, file3] = words.length >= 3 ? words : [void 0, ...words];
73541
73769
  if (!collection || !file3) throw new CliUsageError(USAGE5);
73542
- const csv = await readFile11(resolve6(context.cwd, file3), "utf8").catch(() => {
73770
+ const csv = await readFile13(resolve6(context.cwd, file3), "utf8").catch(() => {
73543
73771
  throw new CliUsageError(`Cannot read ${file3}`);
73544
73772
  });
73545
73773
  const scoped = named ? { ...args, flags: { ...args.flags, app: named } } : args;
@@ -73558,7 +73786,7 @@ var appImport = async ({ context, args }) => {
73558
73786
  });
73559
73787
  const refusedOut = flagText({ args, name: "refused" });
73560
73788
  if (refusedOut && result.refusedCsv) {
73561
- await writeFile13(resolve6(context.cwd, refusedOut), result.refusedCsv);
73789
+ await writeFile15(resolve6(context.cwd, refusedOut), result.refusedCsv);
73562
73790
  }
73563
73791
  const fitting = result.rows - result.refused.length;
73564
73792
  const skipped = result.refused.slice(0, 20).map((row) => ` line ${row.line}: ${row.reason}
@@ -74105,8 +74333,8 @@ async function billing({ context, args }) {
74105
74333
 
74106
74334
  // src/services/browser-commands.service.ts
74107
74335
  import { randomBytes } from "node:crypto";
74108
- import { mkdir as mkdir13, readFile as readFile12, writeFile as writeFile14 } from "node:fs/promises";
74109
- import { dirname as dirname12, join as join15 } from "node:path";
74336
+ import { mkdir as mkdir15, readFile as readFile14, writeFile as writeFile16 } from "node:fs/promises";
74337
+ import { dirname as dirname14, join as join15 } from "node:path";
74110
74338
 
74111
74339
  // src/services/browser-tab-commands.service.ts
74112
74340
  var BROWSER_TAB_PATHS = {
@@ -74652,7 +74880,7 @@ async function turnTokenOf2({ context }) {
74652
74880
  const pinned = env.LAZE_TURN_TOKEN?.trim();
74653
74881
  if (pinned) return pinned;
74654
74882
  if (!env.LAZE_TURN_FILE) return "";
74655
- return readFile12(env.LAZE_TURN_FILE, "utf8").then(
74883
+ return readFile14(env.LAZE_TURN_FILE, "utf8").then(
74656
74884
  (text2) => text2.trim(),
74657
74885
  () => ""
74658
74886
  );
@@ -74726,7 +74954,7 @@ async function cdp({ context, args }) {
74726
74954
  }
74727
74955
  function bridgeStatePath({ context, machine: machine2 }) {
74728
74956
  const safe = machine2.replace(/[^a-zA-Z0-9_-]/g, "_");
74729
- return join15(dirname12(context.environment.configPath), "bridges", `${safe}.json`);
74957
+ return join15(dirname14(context.environment.configPath), "bridges", `${safe}.json`);
74730
74958
  }
74731
74959
  async function bridgePort({
74732
74960
  context,
@@ -74734,7 +74962,7 @@ async function bridgePort({
74734
74962
  access
74735
74963
  }) {
74736
74964
  const path = bridgeStatePath({ context, machine: machine2 });
74737
- const live = await readFile12(path, "utf8").then(
74965
+ const live = await readFile14(path, "utf8").then(
74738
74966
  (text2) => JSON.parse(text2),
74739
74967
  () => void 0
74740
74968
  );
@@ -74747,8 +74975,8 @@ async function bridgePort({
74747
74975
  key,
74748
74976
  ...target
74749
74977
  });
74750
- await mkdir13(dirname12(path), { recursive: true, mode: 448 });
74751
- await writeFile14(path, JSON.stringify({ port, key }), { mode: 384 });
74978
+ await mkdir15(dirname14(path), { recursive: true, mode: 448 });
74979
+ await writeFile16(path, JSON.stringify({ port, key }), { mode: 384 });
74752
74980
  return port;
74753
74981
  }
74754
74982
  async function bridge({ context }) {
@@ -75392,7 +75620,7 @@ async function channelSettings({ context, args }) {
75392
75620
  }
75393
75621
 
75394
75622
  // src/services/chat-actions-commands.service.ts
75395
- import { readFile as readFile13 } from "node:fs/promises";
75623
+ import { readFile as readFile15 } from "node:fs/promises";
75396
75624
  import { basename as basename2, isAbsolute as isAbsolute2, relative as relative4, resolve as resolve7 } from "node:path";
75397
75625
 
75398
75626
  // src/services/file-upload.service.ts
@@ -75697,7 +75925,7 @@ function uploadNameOf({ cwd, path }) {
75697
75925
  }
75698
75926
  var fileUpload = async ({ context, args, client }) => {
75699
75927
  const path = resolve7(context.cwd, wordAt(args, 3));
75700
- const bytes = new Uint8Array(await readFile13(path));
75928
+ const bytes = new Uint8Array(await readFile15(path));
75701
75929
  const answer4 = await uploadFile({
75702
75930
  context,
75703
75931
  client,
@@ -75862,176 +76090,18 @@ async function chatActions({
75862
76090
  }
75863
76091
 
75864
76092
  // src/services/claude-monitor.service.ts
75865
- import { rm as rm9 } from "node:fs/promises";
75866
-
75867
- // src/services/claude-wait.service.ts
75868
- import { readFile as readFile14, rm as rm8, writeFile as writeFile15, mkdir as mkdir14 } from "node:fs/promises";
75869
- import { dirname as dirname13 } from "node:path";
75870
- var ROUND_SECONDS3 = 50;
75871
- var WATCH_MS = 2e3;
75872
- var CHANNEL_CHECK_MS = 5e3;
75873
- async function holderOf({ path }) {
75874
- return readFile14(path, "utf8").then(
75875
- (text2) => JSON.parse(text2),
75876
- () => void 0
75877
- );
75878
- }
75879
- async function holderClaudeOf({ context, holder }) {
75880
- if (holder.claudePid) return holder.claudePid;
75881
- return (await nearestHarnessOf({ context, from: holder.pid }))?.pid;
75882
- }
75883
- async function takeLock({
75884
- context,
75885
- path,
75886
- sessionId,
75887
- claudePid,
75888
- preempt = false
75889
- }) {
75890
- const holder = await holderOf({ path });
75891
- const self2 = context.processes.pid;
75892
- if (holder && holder.pid !== self2 && context.processes.alive(holder.pid)) {
75893
- const served = await holderClaudeOf({ context, holder });
75894
- const mine3 = preempt && served === claudePid && !holder.monitor;
75895
- if (served && context.processes.alive(served) && !mine3) return false;
75896
- context.processes.stop(holder.pid);
75897
- }
75898
- await mkdir14(dirname13(path), { recursive: true, mode: 448 });
75899
- await writeFile15(
75900
- path,
75901
- JSON.stringify({
75902
- pid: self2,
75903
- claudePid,
75904
- ...sessionId ? { sessionId } : {},
75905
- ...preempt ? { monitor: true } : {}
75906
- })
75907
- );
75908
- return true;
75909
- }
75910
- async function channelLive({ context, profile }) {
75911
- const holder = await holderOf({ path: statePathOf({ context, kind: "channels", profile }) });
75912
- return holder !== void 0 && context.processes.alive(holder.pid);
75913
- }
75914
- async function takeRound2({
75915
- context,
75916
- client,
75917
- claudePid,
75918
- session
75919
- }) {
75920
- const controller = new AbortController();
75921
- const { signal } = controller;
75922
- const watch = (async () => {
75923
- while (!signal.aborted) {
75924
- await context.sleep(WATCH_MS, signal);
75925
- if (claudePid && !context.processes.alive(claudePid)) controller.abort();
75926
- }
75927
- })();
75928
- try {
75929
- return await forSession({ client, session }).post(
75930
- "/api/agents/me/inbox",
75931
- { waitSeconds: ROUND_SECONDS3 },
75932
- { signal }
75933
- );
75934
- } catch (error62) {
75935
- if (signal.aborted) return [];
75936
- throw error62;
75937
- } finally {
75938
- controller.abort();
75939
- await watch;
75940
- }
75941
- }
75942
- async function roundOf({ context, client, name: name2, lock, claudePid, session, seen }) {
75943
- if ((await holderOf({ path: lock }))?.pid !== context.processes.pid) return void 0;
75944
- if (claudePid && !context.processes.alive(claudePid)) return void 0;
75945
- const due = await dueFromSpool({ context, profile: name2, seen, pushedToo: true });
75946
- if (due.length > 0) return due;
75947
- if (await channelLive({ context, profile: name2 })) {
75948
- await context.sleep(CHANNEL_CHECK_MS);
75949
- return [];
75950
- }
75951
- const taken = await takeRound2({ context, client, claudePid, session });
75952
- if (taken.length === 0) {
75953
- await context.sleep(1e3);
75954
- return [];
75955
- }
75956
- await keepTaken({ context, profile: name2, messages: taken });
75957
- return taken;
75958
- }
75959
- async function claudePidOf({ context }) {
75960
- const harness = await nearestHarnessOf({ context });
75961
- if (harness?.harness === "claude-code") return harness.pid;
75962
- return await context.processes.parentOf(context.processes.pid) ?? 0;
75963
- }
75964
- async function settleRound(round) {
75965
- const { context, client, name: name2, session } = round;
75966
- const messages = await roundOf(round).catch(async (error62) => {
75967
- const refused = await notBoundNotice({
75968
- context,
75969
- client: forSession({ client, session }),
75970
- session,
75971
- error: error62
75972
- });
75973
- if (!refused) throw error62;
75974
- return refused;
75975
- });
75976
- if (messages === void 0) return 0;
75977
- if (!Array.isArray(messages)) {
75978
- if (messages.rebound) return "again";
75979
- if (!messages.notice) return 0;
75980
- context.err(`${messages.notice}
75981
- `);
75982
- return 2;
75983
- }
75984
- if (messages.length === 0) return "again";
75985
- await turnStarted({ context, client, agent: name2, messages }).catch(() => void 0);
75986
- const self2 = await currentNameOf({ context, client, profile: name2 });
75987
- context.err(`${hookContextOf({ messages, self: self2 })}
75988
- `);
75989
- const messageIds = messages.map((message2) => message2.messageId);
75990
- await dropFromSpool({ context, profile: name2, messageIds });
75991
- return 2;
75992
- }
75993
- async function waitForMessages({ context, args }) {
75994
- const raw = await context.readStdin();
75995
- const input2 = raw.trim() ? JSON.parse(raw) : {};
75996
- const session = sessionOf({ context, harness: "claude-code", sessionId: input2.session_id });
75997
- const named = await sessionProfileArgs({ context, args, session });
75998
- const { client, name: name2 } = await signedIn({ context, args: named });
75999
- const claudePid = await claudePidOf({ context });
76000
- await rememberSession({ context, claudePid, session });
76001
- const lock = statePathOf({ context, kind: "waiters", profile: name2 });
76002
- if (!await takeLock({ context, path: lock, sessionId: input2.session_id, claudePid })) return 0;
76003
- const seen = () => input2.transcript_path ? readFile14(input2.transcript_path, "utf8") : Promise.resolve("");
76004
- const deadline = context.nowMs() + (WAIT_HOOK_TIMEOUT_SECONDS - 60) * 1e3;
76005
- try {
76006
- while (context.nowMs() < deadline) {
76007
- const code = await settleRound({ context, client, name: name2, lock, claudePid, session, seen });
76008
- if (code !== "again") return code;
76009
- }
76010
- return 0;
76011
- } finally {
76012
- if ((await holderOf({ path: lock }))?.pid === context.processes.pid)
76013
- await rm8(lock, { force: true });
76014
- }
76015
- }
76016
- async function waitHook({ context, args }) {
76017
- try {
76018
- return await waitForMessages({ context, args });
76019
- } catch (error62) {
76020
- context.err(`laze: the background waiter stopped: ${String(error62)}
76021
- `);
76022
- return 0;
76023
- }
76024
- }
76025
-
76026
- // src/services/claude-monitor.service.ts
76093
+ import { readFile as readFile16, rm as rm9 } from "node:fs/promises";
76027
76094
  var MONITOR_IDLE_MS = 3e4;
76095
+ var MONITOR_OUTRANKED_MS = 3e3;
76028
76096
  async function agentProfileHere({
76029
76097
  context,
76030
76098
  args,
76031
- session
76099
+ session,
76100
+ claudePid
76032
76101
  }) {
76033
76102
  const config2 = await context.store.read();
76034
- const folder = boundProfileOf({ bindings: config2.bindings, cwd: context.cwd });
76103
+ const cwd = (claudePid ? await context.processes.cwdOf(claudePid) : void 0) ?? context.cwd;
76104
+ const folder = boundProfileOf({ bindings: config2.bindings, cwd });
76035
76105
  if (!folder && !session) return void 0;
76036
76106
  const asked = { ...args, flags: { ...args.flags, ...folder ? { profile: folder } : {} } };
76037
76107
  const name2 = flagText({
@@ -76049,11 +76119,13 @@ async function deliverOnce({
76049
76119
  }) {
76050
76120
  const lock = statePathOf({ context, kind: "waiters", profile });
76051
76121
  const mine3 = (await holderOf({ path: lock }))?.pid === context.processes.pid;
76052
- if (!mine3 && !await takeLock({ context, path: lock, claudePid, preempt: true })) return false;
76122
+ if (!mine3 && !await takeLock({ context, path: lock, claudePid, preempt: true })) {
76123
+ return "outranked";
76124
+ }
76053
76125
  const named = { ...args, flags: { ...args.flags, profile } };
76054
76126
  const { client } = await signedIn({ context, args: named });
76055
76127
  const due = await dueFromSpool({ context, profile, seen: async () => "", pushedToo: true });
76056
- const taken = due.length > 0 ? [] : await takeRound2({ context, client, claudePid, session });
76128
+ const taken = due.length > 0 ? [] : await takeRound({ context, client, claudePid, session });
76057
76129
  const messages = [...due, ...taken];
76058
76130
  if (messages.length === 0) {
76059
76131
  await context.sleep(1e3);
@@ -76089,23 +76161,46 @@ async function release({ context, profile }) {
76089
76161
  }
76090
76162
  async function monitorHook({ context, args }) {
76091
76163
  const claudePid = await claudePidOf({ context });
76092
- const sessionId = context.environment.inherited.CLAUDE_CODE_SESSION_ID;
76093
- const session = sessionOf({ context, harness: "claude-code", sessionId });
76094
- await rememberSession({ context, claudePid, session });
76164
+ const session = await monitorSessionOf({ context, claudePid });
76165
+ await rememberSession({ context, claudePid, session }).catch(() => void 0);
76095
76166
  const held = /* @__PURE__ */ new Set();
76096
76167
  const turn = { context, args, claudePid, session };
76097
76168
  try {
76098
76169
  while (claudePid && context.processes.alive(claudePid)) {
76099
- const profile = await agentProfileHere({ context, args, session });
76100
- const busy = profile ? await monitorRound({ ...turn, profile }) : false;
76101
- if (profile && busy) held.add(profile);
76102
- if (!busy) await context.sleep(MONITOR_IDLE_MS);
76170
+ const round = await oneRound({ turn, held });
76171
+ if (round === "outranked") await context.sleep(MONITOR_OUTRANKED_MS);
76172
+ else if (!round) await context.sleep(MONITOR_IDLE_MS);
76103
76173
  }
76104
76174
  return 0;
76105
76175
  } finally {
76106
- for (const profile of held) await release({ context, profile });
76176
+ for (const profile of held) await release({ context, profile }).catch(() => void 0);
76177
+ }
76178
+ }
76179
+ async function oneRound({ turn, held }) {
76180
+ try {
76181
+ const profile = await agentProfileHere(turn);
76182
+ const round = profile ? await monitorRound({ ...turn, profile }) : false;
76183
+ if (profile && round === true) held.add(profile);
76184
+ return round;
76185
+ } catch (error62) {
76186
+ turn.context.err(`laze: the monitor will try again: ${String(error62)}
76187
+ `);
76188
+ return false;
76107
76189
  }
76108
76190
  }
76191
+ async function monitorSessionOf({
76192
+ context,
76193
+ claudePid
76194
+ }) {
76195
+ const sessionId = context.environment.inherited.CLAUDE_CODE_SESSION_ID;
76196
+ const fromEnv = sessionOf({ context, harness: "claude-code", sessionId });
76197
+ if (fromEnv || !claudePid) return fromEnv;
76198
+ const path = statePathOf({ context, kind: "sessions", profile: String(claudePid) });
76199
+ return readFile16(path, "utf8").then(
76200
+ (text2) => JSON.parse(text2),
76201
+ () => void 0
76202
+ );
76203
+ }
76109
76204
 
76110
76205
  // ../../modules/compute/contract/src/browser-tab.ts
76111
76206
  var browserTabSharingSchema = external_exports.enum(["private", "watch", "use"]);
@@ -77588,10 +77683,10 @@ async function computer({ context, args }) {
77588
77683
  }
77589
77684
 
77590
77685
  // src/services/connect-commands.service.ts
77591
- import { readFile as readFile16 } from "node:fs/promises";
77686
+ import { readFile as readFile18 } from "node:fs/promises";
77592
77687
 
77593
77688
  // src/services/mcp-gateway.service.ts
77594
- import { readFile as readFile15 } from "node:fs/promises";
77689
+ import { readFile as readFile17 } from "node:fs/promises";
77595
77690
  import { createInterface as createInterface3 } from "node:readline";
77596
77691
  var TURN_HEADER = "x-laze-turn";
77597
77692
  function serveMcpGateway({
@@ -77634,7 +77729,7 @@ async function relayMcpLines({
77634
77729
  const github3 = env.LAZE_GITHUB_CONNECTION;
77635
77730
  const url2 = `${profile.url.replace(/\/+$/, "")}/api/connectors/mcp/${encodeURIComponent(profile.agentId)}${github3 ? `?github=${encodeURIComponent(github3)}` : ""}`;
77636
77731
  const turnFile = env.LAZE_TURN_FILE;
77637
- const readTurn = () => readFile15(turnFile, "utf8").then(
77732
+ const readTurn = () => readFile17(turnFile, "utf8").then(
77638
77733
  (text2) => text2.trim(),
77639
77734
  () => ""
77640
77735
  );
@@ -77724,7 +77819,7 @@ async function turnOf({ context }) {
77724
77819
  const pinned = env.LAZE_TURN_TOKEN?.trim();
77725
77820
  if (pinned) return pinned;
77726
77821
  const file3 = env.LAZE_TURN_FILE;
77727
- const turn = file3 ? await readFile16(file3, "utf8").then(
77822
+ const turn = file3 ? await readFile18(file3, "utf8").then(
77728
77823
  (text2) => text2.trim(),
77729
77824
  () => ""
77730
77825
  ) : "";
@@ -77782,11 +77877,11 @@ async function connect({
77782
77877
  }
77783
77878
 
77784
77879
  // src/services/connector-commands.service.ts
77785
- import { readFile as readFile18 } from "node:fs/promises";
77880
+ import { readFile as readFile20 } from "node:fs/promises";
77786
77881
  import { resolve as resolve8 } from "node:path";
77787
77882
 
77788
77883
  // src/services/vault-keychain-commands.service.ts
77789
- import { readFile as readFile17 } from "node:fs/promises";
77884
+ import { readFile as readFile19 } from "node:fs/promises";
77790
77885
 
77791
77886
  // src/rules/vault-input.rules.ts
77792
77887
  function secondsOf(text2) {
@@ -78097,7 +78192,7 @@ async function secretText({ context, args }) {
78097
78192
  );
78098
78193
  }
78099
78194
  const file3 = flagText({ args, name: "from-file" });
78100
- const text2 = file3 ? await readFile17(file3, "utf8") : await context.readStdin();
78195
+ const text2 = file3 ? await readFile19(file3, "utf8") : await context.readStdin();
78101
78196
  const trimmed = text2.replace(/\r?\n$/, "");
78102
78197
  if (!trimmed.trim()) throw new CliUsageError("No value: pipe it on stdin or use --from-file.");
78103
78198
  return trimmed;
@@ -78295,7 +78390,7 @@ async function keyText({ context, args }) {
78295
78390
  throw new CliUsageError("A key never goes in a flag: pipe it on stdin or use --from-file.");
78296
78391
  }
78297
78392
  const file3 = flagText({ args, name: "from-file" });
78298
- const text2 = file3 ? await readFile18(resolve8(context.cwd, file3), "utf8") : await context.readStdin();
78393
+ const text2 = file3 ? await readFile20(resolve8(context.cwd, file3), "utf8") : await context.readStdin();
78299
78394
  const trimmed = text2.trim();
78300
78395
  if (!trimmed) throw new CliUsageError("No key: pipe it on stdin or use --from-file.");
78301
78396
  return trimmed;
@@ -78714,7 +78809,7 @@ async function domains({ context, args }) {
78714
78809
  }
78715
78810
 
78716
78811
  // src/services/feed-commands.service.ts
78717
- import { readFile as readFile20 } from "node:fs/promises";
78812
+ import { readFile as readFile22 } from "node:fs/promises";
78718
78813
  import { resolve as resolve10 } from "node:path";
78719
78814
 
78720
78815
  // src/rules/feed-input.rules.ts
@@ -78839,7 +78934,7 @@ function feedFlagsOf({ args }) {
78839
78934
  }
78840
78935
 
78841
78936
  // src/services/feed-files.service.ts
78842
- import { readFile as readFile19 } from "node:fs/promises";
78937
+ import { readFile as readFile21 } from "node:fs/promises";
78843
78938
  import { basename as basename3, resolve as resolve9 } from "node:path";
78844
78939
 
78845
78940
  // ../../modules/feed/contract/src/feed.ts
@@ -79432,7 +79527,7 @@ async function local({ context, path }) {
79432
79527
  return {
79433
79528
  fileName,
79434
79529
  contentType: contentTypeOf(fileName),
79435
- bytes: new Uint8Array(await readFile19(full))
79530
+ bytes: new Uint8Array(await readFile21(full))
79436
79531
  };
79437
79532
  }
79438
79533
  async function directWith({ client, to }) {
@@ -79510,7 +79605,7 @@ async function bodyOf2({
79510
79605
  flags: flags2
79511
79606
  }) {
79512
79607
  const body = { ...flags2.fields };
79513
- const read3 = (source) => "file" in source ? readFile20(resolve10(context.cwd, source.file), "utf8") : source.text;
79608
+ const read3 = (source) => "file" in source ? readFile22(resolve10(context.cwd, source.file), "utf8") : source.text;
79514
79609
  for (const [field, source] of Object.entries(flags2.texts)) body[field] = await read3(source);
79515
79610
  if (flags2.rich) {
79516
79611
  const text2 = await read3(flags2.rich.source);
@@ -79672,7 +79767,7 @@ async function textFlag({
79672
79767
  }) {
79673
79768
  const value = flagText({ args, name: name2 });
79674
79769
  if (!value.startsWith("@")) return value;
79675
- return readFile20(resolve10(context.cwd, value.slice(1)), "utf8");
79770
+ return readFile22(resolve10(context.cwd, value.slice(1)), "utf8");
79676
79771
  }
79677
79772
  async function feedList({ context, args }) {
79678
79773
  const { client } = await signedIn({ context, args });
@@ -79782,7 +79877,7 @@ async function feed({ context, args }) {
79782
79877
  }
79783
79878
 
79784
79879
  // src/services/github-commands.service.ts
79785
- import { readFile as readFile21 } from "node:fs/promises";
79880
+ import { readFile as readFile23 } from "node:fs/promises";
79786
79881
 
79787
79882
  // src/rules/github-signature.rules.ts
79788
79883
  var TURN_SEPARATOR = "~";
@@ -79852,7 +79947,7 @@ var REAL_GH = "/usr/bin/gh";
79852
79947
  var NOT_SET = "laze: agent_github_not_set: this agent has no GitHub connection. Its owner sets one on the agent's settings page or with `laze agent set-github <agent> <connection>`.";
79853
79948
  async function turnFileToken({ env }) {
79854
79949
  if (!env.LAZE_TURN_FILE) return "";
79855
- return readFile21(env.LAZE_TURN_FILE, "utf8").then(
79950
+ return readFile23(env.LAZE_TURN_FILE, "utf8").then(
79856
79951
  (text2) => text2.trim(),
79857
79952
  () => ""
79858
79953
  );
@@ -79886,7 +79981,7 @@ async function githubGh({
79886
79981
  args: args.rest,
79887
79982
  agentName: profile.name ?? "An agent",
79888
79983
  threadUrl: threadUrlOf({ env, workspaceId: profile.workspaceId }),
79889
- readBodyFile: (path) => path === "-" ? context.readStdin() : readFile21(path, "utf8")
79984
+ readBodyFile: (path) => path === "-" ? context.readStdin() : readFile23(path, "utf8")
79890
79985
  });
79891
79986
  return context.runCommand({
79892
79987
  command: [REAL_GH, ...ghArgs],
@@ -79985,7 +80080,7 @@ async function setAgentGithub({
79985
80080
  }
79986
80081
 
79987
80082
  // src/services/history-commands.service.ts
79988
- import { readFile as readFile22 } from "node:fs/promises";
80083
+ import { readFile as readFile24 } from "node:fs/promises";
79989
80084
 
79990
80085
  // src/rules/history-format.rules.ts
79991
80086
  function timeOf2(iso) {
@@ -80081,7 +80176,7 @@ async function turnTokenOf3({ context }) {
80081
80176
  const pinned = env.LAZE_TURN_TOKEN?.trim();
80082
80177
  if (pinned) return pinned;
80083
80178
  if (!env.LAZE_TURN_FILE) return "";
80084
- return readFile22(env.LAZE_TURN_FILE, "utf8").then(
80179
+ return readFile24(env.LAZE_TURN_FILE, "utf8").then(
80085
80180
  (text2) => text2.trim(),
80086
80181
  () => ""
80087
80182
  );
@@ -80273,19 +80368,19 @@ async function ip({ context, args }) {
80273
80368
  }
80274
80369
 
80275
80370
  // src/services/join-commands.service.ts
80276
- import { mkdir as mkdir15, readFile as readFile23, rename as rename5, rm as rm10, writeFile as writeFile16 } from "node:fs/promises";
80277
- import { dirname as dirname14, join as join16 } from "node:path";
80371
+ import { mkdir as mkdir16, readFile as readFile25, rename as rename5, rm as rm10, writeFile as writeFile17 } from "node:fs/promises";
80372
+ import { dirname as dirname15, join as join16 } from "node:path";
80278
80373
  var DEFAULT_WAIT_SECONDS2 = 100;
80279
80374
  var JOIN_USAGE = "Usage: laze join [--workspace <name|id|invite link>] [--for <email>] [--name <name>] [--note <text>] [--timeout <seconds>] [--project <folder>]";
80280
80375
  function pendingPathOf({ context }) {
80281
- return join16(dirname14(context.environment.configPath), "join", "pending.json");
80376
+ return join16(dirname15(context.environment.configPath), "join", "pending.json");
80282
80377
  }
80283
80378
  async function readPending({
80284
80379
  context,
80285
80380
  url: url2,
80286
80381
  args
80287
80382
  }) {
80288
- const pending = await readFile23(pendingPathOf({ context }), "utf8").then(
80383
+ const pending = await readFile25(pendingPathOf({ context }), "utf8").then(
80289
80384
  (text2) => JSON.parse(text2),
80290
80385
  () => void 0
80291
80386
  );
@@ -80295,9 +80390,9 @@ async function readPending({
80295
80390
  }
80296
80391
  async function keepPending({ context, pending }) {
80297
80392
  const path = pendingPathOf({ context });
80298
- await mkdir15(dirname14(path), { recursive: true, mode: 448 });
80393
+ await mkdir16(dirname15(path), { recursive: true, mode: 448 });
80299
80394
  const temporary = `${path}.${process.pid}.tmp`;
80300
- await writeFile16(temporary, JSON.stringify(pending), { mode: 384 });
80395
+ await writeFile17(temporary, JSON.stringify(pending), { mode: 384 });
80301
80396
  await rename5(temporary, path);
80302
80397
  }
80303
80398
  async function dropPending({ context }) {
@@ -80615,9 +80710,9 @@ function machineAccessCommand(name2) {
80615
80710
 
80616
80711
  // src/services/vault-commands.service.ts
80617
80712
  import { createHash as createHash2 } from "node:crypto";
80618
- import { mkdir as mkdir16, readFile as readFile24, rm as rm11, writeFile as writeFile17 } from "node:fs/promises";
80713
+ import { mkdir as mkdir17, readFile as readFile26, rm as rm11, writeFile as writeFile18 } from "node:fs/promises";
80619
80714
  import { tmpdir as tmpdir2 } from "node:os";
80620
- import { dirname as dirname15, join as join17 } from "node:path";
80715
+ import { dirname as dirname16, join as join17 } from "node:path";
80621
80716
  var USAGE10 = `Usage: laze vault run <connection> --reason "<one plain sentence>" [--wait <s>] -- <command> [args...]
80622
80717
  Runs the command with the connection's values in its environment, on a Laze agent's computer
80623
80718
  or on a machine it runs on.`;
@@ -80656,7 +80751,7 @@ async function turnTokenOf4({
80656
80751
  if (pinned) return pinned;
80657
80752
  if (!turnFile) throw new CliUsageError(`${command} works only during an agent's turn`);
80658
80753
  try {
80659
- return (await readFile24(turnFile, "utf8")).trim();
80754
+ return (await readFile26(turnFile, "utf8")).trim();
80660
80755
  } catch {
80661
80756
  throw new CliUsageError(`${command} works only during an agent's turn`);
80662
80757
  }
@@ -80666,11 +80761,11 @@ function runKeyPathOf({
80666
80761
  connection
80667
80762
  }) {
80668
80763
  const name2 = createHash2("sha256").update(connection).digest("hex");
80669
- const base = turnFile ? dirname15(turnFile) : join17(tmpdir2(), "laze-vault");
80764
+ const base = turnFile ? dirname16(turnFile) : join17(tmpdir2(), "laze-vault");
80670
80765
  return join17(base, "vault-run-keys", `${name2}.json`);
80671
80766
  }
80672
80767
  async function runKeyAt({ path }) {
80673
- const saved3 = await readFile24(path, "utf8").then(
80768
+ const saved3 = await readFile26(path, "utf8").then(
80674
80769
  (text2) => JSON.parse(text2),
80675
80770
  () => void 0
80676
80771
  );
@@ -80680,8 +80775,8 @@ async function runKeyAt({ path }) {
80680
80775
  }
80681
80776
  const fresh = await generateEcdhKeys();
80682
80777
  const jwk = await globalThis.crypto.subtle.exportKey("jwk", fresh.privateKey);
80683
- await mkdir16(dirname15(path), { recursive: true, mode: 448 });
80684
- await writeFile17(path, JSON.stringify({ publicKey: fresh.publicKey, privateKey: jwk }), {
80778
+ await mkdir17(dirname16(path), { recursive: true, mode: 448 });
80779
+ await writeFile18(path, JSON.stringify({ publicKey: fresh.publicKey, privateKey: jwk }), {
80685
80780
  mode: 384
80686
80781
  });
80687
80782
  return fresh;
@@ -81352,14 +81447,14 @@ async function serveMcp({
81352
81447
  }
81353
81448
 
81354
81449
  // src/services/mount-files.service.ts
81355
- import { mkdir as mkdir17, readFile as readFile25, rm as rm12, writeFile as writeFile18 } from "node:fs/promises";
81356
- import { dirname as dirname16, relative as relative5, resolve as resolve11 } from "node:path";
81450
+ import { mkdir as mkdir18, readFile as readFile27, rm as rm12, writeFile as writeFile19 } from "node:fs/promises";
81451
+ import { dirname as dirname17, relative as relative5, resolve as resolve11 } from "node:path";
81357
81452
  async function textArgument({
81358
81453
  context,
81359
81454
  value
81360
81455
  }) {
81361
81456
  if (value === "-") return context.readStdin();
81362
- if (value.startsWith("@")) return readFile25(resolve11(context.cwd, value.slice(1)), "utf8");
81457
+ if (value.startsWith("@")) return readFile27(resolve11(context.cwd, value.slice(1)), "utf8");
81363
81458
  return value;
81364
81459
  }
81365
81460
  function turnChannel({ context, args }) {
@@ -81373,14 +81468,14 @@ async function writeMount({
81373
81468
  }) {
81374
81469
  const root = resolve11(context.cwd, flagText({ args, name: "dir", fallback: ".laze" }), folder);
81375
81470
  await rm12(root, { recursive: true, force: true });
81376
- await mkdir17(root, { recursive: true });
81471
+ await mkdir18(root, { recursive: true });
81377
81472
  for (const file3 of files2) {
81378
81473
  const target = resolve11(root, file3.path);
81379
81474
  const inside = relative5(root, target);
81380
81475
  if (!inside || inside.startsWith(".."))
81381
81476
  throw new Error(`Refusing to write outside ${root}: ${file3.path}`);
81382
- await mkdir17(dirname16(target), { recursive: true });
81383
- await writeFile18(target, file3.content);
81477
+ await mkdir18(dirname17(target), { recursive: true });
81478
+ await writeFile19(target, file3.content);
81384
81479
  }
81385
81480
  return root;
81386
81481
  }
@@ -82257,7 +82352,7 @@ async function schedule({ context, args }) {
82257
82352
  }
82258
82353
 
82259
82354
  // src/services/skill-commands.service.ts
82260
- import { readdir as readdir6, readFile as readFile26 } from "node:fs/promises";
82355
+ import { readdir as readdir6, readFile as readFile28 } from "node:fs/promises";
82261
82356
  import { join as join18, relative as relative6, resolve as resolve12 } from "node:path";
82262
82357
  var USAGE16 = `Usage:
82263
82358
  laze skill list [--agent <agentId>]
@@ -82280,7 +82375,7 @@ async function folderFiles({ root }) {
82280
82375
  for (const entry of entries) {
82281
82376
  if (!entry.isFile()) continue;
82282
82377
  const full = join18(entry.parentPath, entry.name);
82283
- files2.push({ path: relative6(root, full), content: await readFile26(full, "utf8") });
82378
+ files2.push({ path: relative6(root, full), content: await readFile28(full, "utf8") });
82284
82379
  }
82285
82380
  return files2.toSorted((a, b) => a.path.localeCompare(b.path));
82286
82381
  }
@@ -82378,7 +82473,7 @@ async function skillUpdate({ context, args }) {
82378
82473
  if (!name2 || !newName && description === void 0 && !skillMdFile) {
82379
82474
  throw new CliUsageError(USAGE16);
82380
82475
  }
82381
- const skillMd = skillMdFile ? await readFile26(resolve12(context.cwd, skillMdFile), "utf8") : void 0;
82476
+ const skillMd = skillMdFile ? await readFile28(resolve12(context.cwd, skillMdFile), "utf8") : void 0;
82382
82477
  const { client } = await signedIn({ context, args });
82383
82478
  const updated = await client.post("/api/skills/update", {
82384
82479
  name: name2,
@@ -82424,7 +82519,7 @@ async function skill({ context, args }) {
82424
82519
  }
82425
82520
 
82426
82521
  // src/services/slack-commands.service.ts
82427
- import { readFile as readFile27 } from "node:fs/promises";
82522
+ import { readFile as readFile29 } from "node:fs/promises";
82428
82523
  import { resolve as resolve13 } from "node:path";
82429
82524
  var SLACK_USAGE = `Usage (a person's key; Slack stays the source, the bot joins no channel by itself):
82430
82525
  laze slack overview connected Slack workspaces, mirrors, your link
@@ -82472,7 +82567,7 @@ async function secretLines({ context, args }) {
82472
82567
  throw new CliUsageError("A secret never goes in a flag: pipe it on stdin or use --from-file.");
82473
82568
  }
82474
82569
  const file3 = flagText({ args, name: "from-file" });
82475
- const text2 = file3 ? await readFile27(resolve13(context.cwd, file3), "utf8") : await context.readStdin();
82570
+ const text2 = file3 ? await readFile29(resolve13(context.cwd, file3), "utf8") : await context.readStdin();
82476
82571
  return text2.split("\n").map((line) => line.trim()).filter(Boolean);
82477
82572
  }
82478
82573
  async function secretsOf({
@@ -82776,7 +82871,7 @@ async function slack({
82776
82871
  }
82777
82872
 
82778
82873
  // src/services/sso-commands.service.ts
82779
- import { readFile as readFile28 } from "node:fs/promises";
82874
+ import { readFile as readFile30 } from "node:fs/promises";
82780
82875
  var SSO_USAGE = `Usage:
82781
82876
  laze sso domains claimed domains and how each signs in (admins)
82782
82877
  laze sso claim <domain> the TXT record that proves the domain
@@ -82863,7 +82958,7 @@ function refuseSecretFlags({ args }) {
82863
82958
  }
82864
82959
  async function clientSecretOf({ context, args }) {
82865
82960
  const file3 = flagText({ args, name: "from-file" });
82866
- const text2 = file3 ? await readFile28(file3, "utf8") : await context.readStdin();
82961
+ const text2 = file3 ? await readFile30(file3, "utf8") : await context.readStdin();
82867
82962
  const secret = text2.trim();
82868
82963
  if (!secret) throw new CliUsageError("No client secret: pipe it on stdin or use --from-file.");
82869
82964
  return secret;
@@ -83196,7 +83291,7 @@ async function vaultScrub({ context, args }) {
83196
83291
  }
83197
83292
 
83198
83293
  // src/services/whatsapp-business-commands.service.ts
83199
- import { readFile as readFile29 } from "node:fs/promises";
83294
+ import { readFile as readFile31 } from "node:fs/promises";
83200
83295
  import { resolve as resolve14 } from "node:path";
83201
83296
 
83202
83297
  // ../../modules/whatsapp-business/contract/src/whatsapp-business.prices.ts
@@ -83616,7 +83711,7 @@ async function secretsOf2({ context, args }) {
83616
83711
  const fromConnection = flagText({ args, name: "from-vault" });
83617
83712
  if (fromConnection) return { fromConnection };
83618
83713
  const file3 = flagText({ args, name: "from-file" });
83619
- const text2 = file3 ? await readFile29(resolve14(context.cwd, file3), "utf8") : await context.readStdin();
83714
+ const text2 = file3 ? await readFile31(resolve14(context.cwd, file3), "utf8") : await context.readStdin();
83620
83715
  const lines = text2.split("\n").map((line) => line.trim()).filter(Boolean);
83621
83716
  if (lines.length !== 2) {
83622
83717
  throw new CliUsageError(
@@ -83817,7 +83912,7 @@ async function whatsappBusiness({
83817
83912
  }
83818
83913
 
83819
83914
  // src/services/whatsapp-pairing-commands.service.ts
83820
- import { writeFile as writeFile19 } from "node:fs/promises";
83915
+ import { writeFile as writeFile20 } from "node:fs/promises";
83821
83916
  import { resolve as resolve15 } from "node:path";
83822
83917
  var WHATSAPP_PAIRING_USAGE = [
83823
83918
  " laze whatsapp pair <machine> [--qr <file.svg>] link WhatsApp on your machine; scan the code (owner)",
@@ -83838,7 +83933,7 @@ function svgOf(dataUrl) {
83838
83933
  }
83839
83934
  async function report({ context, args, pairing: pairing2 }) {
83840
83935
  const qrFile = pairing2.qrSvg ? resolve15(context.cwd, flagText({ args, name: "qr", fallback: "whatsapp-qr.svg" })) : null;
83841
- if (qrFile && pairing2.qrSvg) await writeFile19(qrFile, svgOf(pairing2.qrSvg), "utf8");
83936
+ if (qrFile && pairing2.qrSvg) await writeFile20(qrFile, svgOf(pairing2.qrSvg), "utf8");
83842
83937
  if (args.flags.json) return context.out(`${JSON.stringify({ ...pairing2, qrFile }, null, 2)}
83843
83938
  `);
83844
83939
  context.out(`${pairing2.pairingId} ${pairing2.state}
@@ -84197,7 +84292,7 @@ async function flags({ context, args }) {
84197
84292
  }
84198
84293
 
84199
84294
  // src/services/workspace-commands.service.ts
84200
- import { readFile as readFile30 } from "node:fs/promises";
84295
+ import { readFile as readFile32 } from "node:fs/promises";
84201
84296
  import { resolve as resolve16 } from "node:path";
84202
84297
  var ROLE_NAMES2 = {
84203
84298
  OWNER: "Owner",
@@ -84380,7 +84475,7 @@ var LOGO_USAGE = "Usage: laze workspace logo set <file.png|jpg|webp> | laze work
84380
84475
  async function readLogo({ context, file: file3 }) {
84381
84476
  let bytes;
84382
84477
  try {
84383
- bytes = new Uint8Array(await readFile30(resolve16(context.cwd, file3)));
84478
+ bytes = new Uint8Array(await readFile32(resolve16(context.cwd, file3)));
84384
84479
  } catch {
84385
84480
  throw new CliUsageError(`No file to read at ${file3}.`);
84386
84481
  }
@@ -85041,8 +85136,8 @@ async function runCli({
85041
85136
  // src/services/processes.service.ts
85042
85137
  import { execFile as execFile2, spawn as spawn4 } from "node:child_process";
85043
85138
  import { mkdirSync, openSync } from "node:fs";
85044
- import { readFile as readFile31, readlink } from "node:fs/promises";
85045
- import { dirname as dirname17 } from "node:path";
85139
+ import { readFile as readFile33, readlink } from "node:fs/promises";
85140
+ import { dirname as dirname18 } from "node:path";
85046
85141
  import { promisify as promisify2 } from "node:util";
85047
85142
  var run3 = promisify2(execFile2);
85048
85143
  function alive(pid) {
@@ -85055,14 +85150,14 @@ function alive(pid) {
85055
85150
  }
85056
85151
  }
85057
85152
  async function argsOf(pid) {
85058
- const raw = await readFile31(`/proc/${pid}/cmdline`, "utf8").catch(() => void 0);
85153
+ const raw = await readFile33(`/proc/${pid}/cmdline`, "utf8").catch(() => void 0);
85059
85154
  if (raw) return raw.split("\0").filter(Boolean);
85060
85155
  const listed = await run3("ps", ["-o", "args=", "-p", String(pid)]).catch(() => void 0);
85061
85156
  const line = listed?.stdout.trim();
85062
85157
  return line ? line.split(/\s+/) : void 0;
85063
85158
  }
85064
85159
  async function parentOf(pid) {
85065
- const stat3 = await readFile31(`/proc/${pid}/stat`, "utf8").catch(() => void 0);
85160
+ const stat3 = await readFile33(`/proc/${pid}/stat`, "utf8").catch(() => void 0);
85066
85161
  const fromStat = stat3 ? Number(stat3.slice(stat3.lastIndexOf(")") + 2).split(" ")[1]) : NaN;
85067
85162
  if (fromStat > 0) return fromStat;
85068
85163
  const listed = await run3("ps", ["-o", "ppid=", "-p", String(pid)]).catch(() => void 0);
@@ -85079,7 +85174,7 @@ async function cwdOf(pid) {
85079
85174
  return line ? line.slice(1) : void 0;
85080
85175
  }
85081
85176
  function spawnDetached({ argv, logPath }) {
85082
- mkdirSync(dirname17(logPath), { recursive: true, mode: 448 });
85177
+ mkdirSync(dirname18(logPath), { recursive: true, mode: 448 });
85083
85178
  const log = openSync(logPath, "a", 384);
85084
85179
  const [program = "", ...rest] = argv;
85085
85180
  const child = spawn4(program, rest, { detached: true, stdio: ["ignore", log, log] });