@lazehq/cli 0.1.17 → 0.1.18

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 +501 -436
  2. package/package.json +1 -1
package/dist/laze.mjs CHANGED
@@ -18733,7 +18733,7 @@ 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: writeFile21, readFile: readFile34, mkdir: mkdir19 } = __require("node:fs/promises");
18736
+ var { writeFile: writeFile21, readFile: readFile35, mkdir: mkdir19 } = __require("node:fs/promises");
18737
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();
@@ -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 readFile34(resolve17(path), "utf8");
18953
+ const data = await readFile35(resolve17(path), "utf8");
18954
18954
  const parsed = JSON.parse(data);
18955
18955
  if (Array.isArray(parsed)) {
18956
18956
  this.#snapshots.clear();
@@ -35606,7 +35606,7 @@ function flagText({
35606
35606
  }
35607
35607
 
35608
35608
  // src/rules/cli-version.rules.ts
35609
- var STAMPED = "0.1.17";
35609
+ var STAMPED = "0.1.18";
35610
35610
  function cliVersionOf({ stamped = STAMPED } = {}) {
35611
35611
  return stamped.startsWith("__") ? "dev" : stamped;
35612
35612
  }
@@ -65390,8 +65390,8 @@ async function copyAgent({
65390
65390
  }
65391
65391
 
65392
65392
  // src/services/agent-commands.service.ts
65393
- import { mkdir as mkdir13, readFile as readFile11, writeFile as writeFile13 } from "node:fs/promises";
65394
- import { join as join12, resolve as resolve4 } from "node:path";
65393
+ import { mkdir as mkdir13, readFile as readFile12, writeFile as writeFile13 } from "node:fs/promises";
65394
+ import { join as join13, resolve as resolve4 } from "node:path";
65395
65395
 
65396
65396
  // src/rules/agent-profile.rules.ts
65397
65397
  var LEVELS = { fast: "Laze Fast", frontier: "Laze Frontier" };
@@ -65486,7 +65486,8 @@ function lazeCommandOf({ program }) {
65486
65486
 
65487
65487
  // src/rules/hook-settings.rules.ts
65488
65488
  var LAZE_HOOK_MARKER = "laze-cli-hook";
65489
- var TIMEOUTS = { Stop: 30, PreToolUse: 5, SessionStart: 30 };
65489
+ var HOOK_TIMEOUTS = { Stop: 30, PreToolUse: 5, SessionStart: 30 };
65490
+ var TIMEOUTS = HOOK_TIMEOUTS;
65490
65491
  var WAIT_HOOK_TIMEOUT_SECONDS = 7 * 24 * 60 * 60;
65491
65492
  function withHooks({
65492
65493
  hooks,
@@ -65549,12 +65550,17 @@ function hookCommand({
65549
65550
  const words = [...program, "hook", hook, "--profile", profile].map(quote4).join(" ");
65550
65551
  return `${words} # ${LAZE_HOOK_MARKER}`;
65551
65552
  }
65552
- function lacksSessionStartWaiter({ settings: settings2 }) {
65553
+ function holdsOurs({ settings: settings2, event }) {
65553
65554
  const hooks = settings2.hooks ?? {};
65554
- const ours = (event) => Array.isArray(hooks[event]) && hooks[event].some(
65555
+ return Array.isArray(hooks[event]) && hooks[event].some(
65555
65556
  (entry) => entry.hooks?.some((hook) => hook.command?.includes(LAZE_HOOK_MARKER))
65556
65557
  );
65557
- return ours("Stop") && !ours("SessionStart");
65558
+ }
65559
+ function lacksSessionStartWaiter({ settings: settings2 }) {
65560
+ return holdsOurs({ settings: settings2, event: "Stop" }) && !holdsOurs({ settings: settings2, event: "SessionStart" });
65561
+ }
65562
+ function hasLazeHooks({ settings: settings2 }) {
65563
+ return holdsOurs({ settings: settings2, event: "Stop" });
65558
65564
  }
65559
65565
 
65560
65566
  // src/rules/inbox-format.rules.ts
@@ -66516,15 +66522,323 @@ function formatSearch({
66516
66522
  }
66517
66523
 
66518
66524
  // src/services/claude-turn.service.ts
66519
- import { mkdir as mkdir2, readFile as readFile2, rm, writeFile as writeFile2 } from "node:fs/promises";
66525
+ import { mkdir as mkdir4, readFile as readFile5, rm, writeFile as writeFile4 } from "node:fs/promises";
66526
+ import { dirname as dirname4, join as join5 } from "node:path";
66527
+
66528
+ // src/services/harness-session.service.ts
66529
+ import { mkdir as mkdir3, readdir, readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
66530
+ import { hostname as hostname3 } from "node:os";
66531
+ import { dirname as dirname3, join as join3 } from "node:path";
66532
+
66533
+ // src/rules/session-headers.rules.ts
66534
+ import { relative, sep } from "node:path";
66535
+ function sessionKeyOf({ session }) {
66536
+ return `${session.harness}:${session.sessionId}`;
66537
+ }
66538
+ function sessionHeadersOf({
66539
+ session
66540
+ }) {
66541
+ if (!session) return {};
66542
+ return {
66543
+ [AGENT_SESSION_HEADER]: sessionKeyOf({ session }),
66544
+ [AGENT_SESSION_FOLDER_HEADER]: encodeURIComponent(session.folder),
66545
+ [AGENT_SESSION_HOST_HEADER]: encodeURIComponent(session.host)
66546
+ };
66547
+ }
66548
+ function displayFolderOf({ folder, home }) {
66549
+ if (!home) return folder;
66550
+ const below = relative(home, folder);
66551
+ if (below === "") return "~";
66552
+ if (below.startsWith("..") || below.startsWith(sep)) return folder;
66553
+ return `~/${below.split(sep).join("/")}`;
66554
+ }
66555
+
66556
+ // src/services/claude-project.service.ts
66557
+ import { basename, isAbsolute, relative as relative2, resolve as resolve2 } from "node:path";
66558
+ function harnessIn({ words }) {
66559
+ const names = words.slice(0, 2).map((word3) => basename(word3).replace(/\.(js|mjs|cjs)$/, ""));
66560
+ if (names.includes("codex")) return "codex";
66561
+ if (words.some((word3) => word3.includes("@openai/codex"))) return "codex";
66562
+ const claude = words.some((word3) => word3.includes("@anthropic-ai/claude-code"));
66563
+ return claude || names.includes("claude") ? "claude-code" : void 0;
66564
+ }
66565
+ async function nearestHarnessOf({
66566
+ context,
66567
+ from = context.processes.pid
66568
+ }) {
66569
+ let pid = await context.processes.parentOf(from);
66570
+ for (let depth = 0; pid !== void 0 && pid > 1 && depth < 12; depth += 1) {
66571
+ const harness = harnessIn({ words: await context.processes.argsOf(pid) ?? [] });
66572
+ if (harness) return { harness, pid };
66573
+ pid = await context.processes.parentOf(pid);
66574
+ }
66575
+ return void 0;
66576
+ }
66577
+ function holds({ folder, inner }) {
66578
+ const rel = relative2(resolve2(folder), resolve2(inner));
66579
+ return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
66580
+ }
66581
+ async function claudeProjectOf({
66582
+ context,
66583
+ claudePid
66584
+ }) {
66585
+ const env = context.environment.inherited;
66586
+ const pid = Number(env.CLAUDE_PID);
66587
+ const candidates = [
66588
+ claudePid ? await context.processes.cwdOf(claudePid) : void 0,
66589
+ env.CLAUDE_PROJECT_DIR ? resolve2(env.CLAUDE_PROJECT_DIR) : void 0,
66590
+ pid > 0 ? await context.processes.cwdOf(pid) : void 0
66591
+ ].filter((folder) => Boolean(folder));
66592
+ return candidates.find((folder) => holds({ folder, inner: context.cwd })) ?? resolve2(context.cwd);
66593
+ }
66594
+
66595
+ // src/services/inbox-spool.service.ts
66596
+ import { mkdir as mkdir2, readFile as readFile2, rename as rename2, writeFile as writeFile2 } from "node:fs/promises";
66520
66597
  import { dirname as dirname2, join as join2 } from "node:path";
66598
+ var PUSH_GRACE_MS = 3 * 6e4;
66599
+ function fileNameOf({ profile }) {
66600
+ return profile.replace(/[^a-zA-Z0-9_-]/g, "_");
66601
+ }
66602
+ function statePathOf({
66603
+ context,
66604
+ kind,
66605
+ profile,
66606
+ extension: extension2 = "json"
66607
+ }) {
66608
+ const directory = join2(dirname2(context.environment.configPath), kind);
66609
+ return join2(directory, `${fileNameOf({ profile })}.${extension2}`);
66610
+ }
66611
+ async function readSpool({ path }) {
66612
+ return readFile2(path, "utf8").then(
66613
+ (text2) => JSON.parse(text2),
66614
+ () => []
66615
+ );
66616
+ }
66617
+ async function writeSpool({ path, entries }) {
66618
+ await mkdir2(dirname2(path), { recursive: true, mode: 448 });
66619
+ const temporary = `${path}.${process.pid}.tmp`;
66620
+ await writeFile2(temporary, JSON.stringify(entries), { mode: 384 });
66621
+ await rename2(temporary, path);
66622
+ }
66623
+ async function keepTaken({
66624
+ context,
66625
+ profile,
66626
+ messages,
66627
+ pushed = false
66628
+ }) {
66629
+ if (messages.length === 0) return;
66630
+ const path = statePathOf({ context, kind: "spool", profile });
66631
+ const ids = new Set(messages.map((message2) => message2.messageId));
66632
+ const kept = (await readSpool({ path })).filter((entry) => !ids.has(entry.message.messageId));
66633
+ const now = context.nowMs();
66634
+ const taken = messages.map((message2) => ({
66635
+ message: message2,
66636
+ takenAt: now,
66637
+ ...pushed ? { pushedAt: now } : {}
66638
+ }));
66639
+ await writeSpool({ path, entries: [...kept, ...taken] });
66640
+ }
66641
+ async function dropFromSpool({
66642
+ context,
66643
+ profile,
66644
+ messageIds
66645
+ }) {
66646
+ if (messageIds.length === 0) return;
66647
+ const path = statePathOf({ context, kind: "spool", profile });
66648
+ const entries = await readSpool({ path });
66649
+ const ids = new Set(messageIds);
66650
+ const kept = entries.filter((entry) => !ids.has(entry.message.messageId));
66651
+ if (kept.length !== entries.length) await writeSpool({ path, entries: kept });
66652
+ }
66653
+ async function dueFromSpool({
66654
+ context,
66655
+ profile,
66656
+ seen,
66657
+ pushedToo
66658
+ }) {
66659
+ const path = statePathOf({ context, kind: "spool", profile });
66660
+ const entries = await readSpool({ path });
66661
+ const pushed = entries.some((entry) => entry.pushedAt !== void 0);
66662
+ const text2 = pushed ? await seen().catch(() => "") : "";
66663
+ const shown = entries.filter(
66664
+ (entry) => entry.pushedAt !== void 0 && text2.includes(entry.message.messageId)
66665
+ );
66666
+ await dropFromSpool({
66667
+ context,
66668
+ profile,
66669
+ messageIds: shown.map((entry) => entry.message.messageId)
66670
+ });
66671
+ const late = context.nowMs() - PUSH_GRACE_MS;
66672
+ return entries.filter((entry) => !shown.includes(entry)).filter((entry) => entry.pushedAt === void 0 || pushedToo && entry.pushedAt <= late).map((entry) => entry.message);
66673
+ }
66674
+
66675
+ // src/services/harness-session.service.ts
66676
+ function sessionOf({
66677
+ context,
66678
+ harness,
66679
+ sessionId
66680
+ }) {
66681
+ if (!sessionId) return void 0;
66682
+ const inherited = context.environment.inherited;
66683
+ const folder = inherited.CLAUDE_PROJECT_DIR || context.cwd;
66684
+ return {
66685
+ harness,
66686
+ sessionId,
66687
+ folder: displayFolderOf({ folder, home: inherited.HOME }),
66688
+ host: hostname3()
66689
+ };
66690
+ }
66691
+ function forSession({
66692
+ client,
66693
+ session
66694
+ }) {
66695
+ return client.withHeaders(sessionHeadersOf({ session }));
66696
+ }
66697
+ async function rememberSession({
66698
+ context,
66699
+ claudePid,
66700
+ session
66701
+ }) {
66702
+ if (!session || !claudePid) return;
66703
+ const path = statePathOf({ context, kind: "sessions", profile: String(claudePid) });
66704
+ await mkdir3(dirname3(path), { recursive: true, mode: 448 });
66705
+ await writeFile3(path, JSON.stringify(session), { mode: 384 });
66706
+ }
66707
+ async function currentSessionOf({
66708
+ context,
66709
+ args
66710
+ }) {
66711
+ const inherited = context.environment.inherited;
66712
+ const named = flagText({ args, name: "session" });
66713
+ const harness = context.environment.harness;
66714
+ if (named) return sessionOf({ context, harness, sessionId: named });
66715
+ if (harness === "claude-code" && inherited.CLAUDE_CODE_SESSION_ID) {
66716
+ return sessionOf({ context, harness, sessionId: inherited.CLAUDE_CODE_SESSION_ID });
66717
+ }
66718
+ if (harness === "codex" && inherited.CODEX_THREAD_ID) {
66719
+ return sessionOf({ context, harness, sessionId: inherited.CODEX_THREAD_ID });
66720
+ }
66721
+ const nearest = await nearestHarnessOf({ context });
66722
+ if (!nearest) return void 0;
66723
+ const path = statePathOf({ context, kind: "sessions", profile: String(nearest.pid) });
66724
+ return readFile3(path, "utf8").then(
66725
+ (text2) => JSON.parse(text2),
66726
+ () => void 0
66727
+ );
66728
+ }
66729
+ async function sessionProfileArgs({
66730
+ context,
66731
+ args,
66732
+ session
66733
+ }) {
66734
+ if (!session) return args;
66735
+ const key = sessionKeyOf({ session });
66736
+ const config2 = await context.store.read();
66737
+ const bound = config2.sessions?.[key];
66738
+ if (bound && config2.profiles[bound]) {
66739
+ return { ...args, flags: { ...args.flags, profile: bound } };
66740
+ }
66741
+ const own2 = flagText({ args, name: "profile" });
66742
+ if (own2 && config2.profiles[own2]?.kind === "agent") {
66743
+ await context.store.bindSession({ session: key, profile: own2 });
66744
+ }
66745
+ return args;
66746
+ }
66747
+ async function liveElsewhere({
66748
+ context,
66749
+ key,
66750
+ claudePid
66751
+ }) {
66752
+ const folder = dirname3(statePathOf({ context, kind: "sessions", profile: "x" }));
66753
+ for (const file3 of await readdir(folder).catch(() => [])) {
66754
+ const pid = Number(file3.replace(/\.json$/, ""));
66755
+ if (!pid || pid === claudePid || !context.processes.alive(pid)) continue;
66756
+ const noted = await readFile3(join3(folder, file3), "utf8").then(
66757
+ (text2) => JSON.parse(text2),
66758
+ () => void 0
66759
+ );
66760
+ if (noted && sessionKeyOf({ session: noted }) === key) return true;
66761
+ }
66762
+ return false;
66763
+ }
66764
+ function notBoundText({ meta: meta3 }) {
66765
+ 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.`;
66766
+ }
66767
+ async function notBoundNotice({
66768
+ context,
66769
+ client,
66770
+ session,
66771
+ error: error62
66772
+ }) {
66773
+ if (!(error62 instanceof LazeApiError) || error62.code !== "session_not_bound") return void 0;
66774
+ const meta3 = error62.meta ?? {};
66775
+ if (client && session && meta3.session && meta3.host === session.host) {
66776
+ const claudePid = (await nearestHarnessOf({ context }))?.pid;
66777
+ if (!await liveElsewhere({ context, key: meta3.session, claudePid })) {
66778
+ await client.post("/api/agents/me/bind", {});
66779
+ return { notice: void 0, rebound: true };
66780
+ }
66781
+ }
66782
+ const key = session ? sessionKeyOf({ session }) : "unknown";
66783
+ const path = statePathOf({ context, kind: "told", profile: key });
66784
+ const told = await readFile3(path, "utf8").then(
66785
+ () => true,
66786
+ () => false
66787
+ );
66788
+ if (told) return { notice: void 0 };
66789
+ await mkdir3(dirname3(path), { recursive: true, mode: 448 });
66790
+ await writeFile3(path, String(context.nowMs()), { mode: 384 });
66791
+ return { notice: notBoundText({ meta: meta3 }) };
66792
+ }
66793
+
66794
+ // src/services/plugin-hook.service.ts
66795
+ import { readFile as readFile4 } from "node:fs/promises";
66796
+ import { join as join4 } from "node:path";
66797
+ async function agentProfileHere({
66798
+ context,
66799
+ args,
66800
+ session,
66801
+ claudePid
66802
+ }) {
66803
+ const config2 = await context.store.read();
66804
+ const cwd = (claudePid ? await context.processes.cwdOf(claudePid) : void 0) ?? (context.environment.inherited.CLAUDE_PROJECT_DIR || context.cwd);
66805
+ const folder = boundProfileOf({ bindings: config2.bindings, cwd });
66806
+ if (!folder && !session) return void 0;
66807
+ const asked = { ...args, flags: { ...args.flags, ...folder ? { profile: folder } : {} } };
66808
+ const name2 = flagText({
66809
+ args: await sessionProfileArgs({ context, args: asked, session }),
66810
+ name: "profile"
66811
+ });
66812
+ return name2 && config2.profiles[name2]?.kind === "agent" ? name2 : void 0;
66813
+ }
66814
+ async function projectHooksHere({ context }) {
66815
+ const directory = context.environment.inherited.CLAUDE_PROJECT_DIR || context.cwd;
66816
+ const path = join4(directory, ".claude", "settings.local.json");
66817
+ return readFile4(path, "utf8").then(
66818
+ (text2) => hasLazeHooks({ settings: JSON.parse(text2) }),
66819
+ () => false
66820
+ );
66821
+ }
66822
+ async function pluginHookArgs({
66823
+ context,
66824
+ args,
66825
+ session,
66826
+ claudePid
66827
+ }) {
66828
+ if (!args.flags.plugin) return args;
66829
+ if (await projectHooksHere({ context })) return void 0;
66830
+ const profile = await agentProfileHere({ context, args, session, claudePid });
66831
+ return profile ? { ...args, flags: { ...args.flags, profile } } : void 0;
66832
+ }
66833
+
66834
+ // src/services/claude-turn.service.ts
66521
66835
  var PRE_TOOL_TIMEOUT_MS = 3e3;
66522
66836
  function statePath({ context, agent: agent2 }) {
66523
66837
  const safe = agent2.replace(/[^a-zA-Z0-9_-]/g, "_");
66524
- return join2(dirname2(context.environment.configPath), "turns", `${safe}.json`);
66838
+ return join5(dirname4(context.environment.configPath), "turns", `${safe}.json`);
66525
66839
  }
66526
66840
  async function readState({ context, agent: agent2 }) {
66527
- return readFile2(statePath({ context, agent: agent2 }), "utf8").then(
66841
+ return readFile5(statePath({ context, agent: agent2 }), "utf8").then(
66528
66842
  (text2) => JSON.parse(text2),
66529
66843
  () => void 0
66530
66844
  );
@@ -66560,8 +66874,8 @@ async function turnStarted({
66560
66874
  await beat({ client, state: before, working: false }).catch(() => void 0);
66561
66875
  }
66562
66876
  const path = statePath({ context, agent: agent2 });
66563
- await mkdir2(dirname2(path), { recursive: true, mode: 448 });
66564
- await writeFile2(path, JSON.stringify(state));
66877
+ await mkdir4(dirname4(path), { recursive: true, mode: 448 });
66878
+ await writeFile4(path, JSON.stringify(state));
66565
66879
  await beat({ client, state, working: true }).catch(() => void 0);
66566
66880
  }
66567
66881
  async function turnEnded({
@@ -66576,12 +66890,16 @@ async function turnEnded({
66576
66890
  }
66577
66891
  async function preToolHook({ context, args }) {
66578
66892
  try {
66579
- await context.readStdin();
66580
- const { name: name2, profile } = await signedIn({ context, args });
66893
+ const raw = await context.readStdin();
66894
+ const input2 = raw.trim() ? JSON.parse(raw) : {};
66895
+ const session = sessionOf({ context, harness: "claude-code", sessionId: input2.session_id });
66896
+ const asked = await pluginHookArgs({ context, args, session, claudePid: 0 });
66897
+ if (!asked) return;
66898
+ const { name: name2, profile } = await signedIn({ context, args: asked });
66581
66899
  const client = LazeClient.create({
66582
66900
  baseUrl: profile.url,
66583
66901
  token: profile.token,
66584
- fetcher: (input2, init) => context.fetcher(input2, { ...init, signal: AbortSignal.timeout(PRE_TOOL_TIMEOUT_MS) })
66902
+ fetcher: (input3, init) => context.fetcher(input3, { ...init, signal: AbortSignal.timeout(PRE_TOOL_TIMEOUT_MS) })
66585
66903
  });
66586
66904
  const state = await readState({ context, agent: name2 });
66587
66905
  const answer4 = await beat({ client, state, working: true });
@@ -66605,86 +66923,6 @@ async function preToolHook({ context, args }) {
66605
66923
  }
66606
66924
  }
66607
66925
 
66608
- // src/services/inbox-spool.service.ts
66609
- import { mkdir as mkdir3, readFile as readFile3, rename as rename2, writeFile as writeFile3 } from "node:fs/promises";
66610
- import { dirname as dirname3, join as join3 } from "node:path";
66611
- var PUSH_GRACE_MS = 3 * 6e4;
66612
- function fileNameOf({ profile }) {
66613
- return profile.replace(/[^a-zA-Z0-9_-]/g, "_");
66614
- }
66615
- function statePathOf({
66616
- context,
66617
- kind,
66618
- profile,
66619
- extension: extension2 = "json"
66620
- }) {
66621
- const directory = join3(dirname3(context.environment.configPath), kind);
66622
- return join3(directory, `${fileNameOf({ profile })}.${extension2}`);
66623
- }
66624
- async function readSpool({ path }) {
66625
- return readFile3(path, "utf8").then(
66626
- (text2) => JSON.parse(text2),
66627
- () => []
66628
- );
66629
- }
66630
- async function writeSpool({ path, entries }) {
66631
- await mkdir3(dirname3(path), { recursive: true, mode: 448 });
66632
- const temporary = `${path}.${process.pid}.tmp`;
66633
- await writeFile3(temporary, JSON.stringify(entries), { mode: 384 });
66634
- await rename2(temporary, path);
66635
- }
66636
- async function keepTaken({
66637
- context,
66638
- profile,
66639
- messages,
66640
- pushed = false
66641
- }) {
66642
- if (messages.length === 0) return;
66643
- const path = statePathOf({ context, kind: "spool", profile });
66644
- const ids = new Set(messages.map((message2) => message2.messageId));
66645
- const kept = (await readSpool({ path })).filter((entry) => !ids.has(entry.message.messageId));
66646
- const now = context.nowMs();
66647
- const taken = messages.map((message2) => ({
66648
- message: message2,
66649
- takenAt: now,
66650
- ...pushed ? { pushedAt: now } : {}
66651
- }));
66652
- await writeSpool({ path, entries: [...kept, ...taken] });
66653
- }
66654
- async function dropFromSpool({
66655
- context,
66656
- profile,
66657
- messageIds
66658
- }) {
66659
- if (messageIds.length === 0) return;
66660
- const path = statePathOf({ context, kind: "spool", profile });
66661
- const entries = await readSpool({ path });
66662
- const ids = new Set(messageIds);
66663
- const kept = entries.filter((entry) => !ids.has(entry.message.messageId));
66664
- if (kept.length !== entries.length) await writeSpool({ path, entries: kept });
66665
- }
66666
- async function dueFromSpool({
66667
- context,
66668
- profile,
66669
- seen,
66670
- pushedToo
66671
- }) {
66672
- const path = statePathOf({ context, kind: "spool", profile });
66673
- const entries = await readSpool({ path });
66674
- const pushed = entries.some((entry) => entry.pushedAt !== void 0);
66675
- const text2 = pushed ? await seen().catch(() => "") : "";
66676
- const shown = entries.filter(
66677
- (entry) => entry.pushedAt !== void 0 && text2.includes(entry.message.messageId)
66678
- );
66679
- await dropFromSpool({
66680
- context,
66681
- profile,
66682
- messageIds: shown.map((entry) => entry.message.messageId)
66683
- });
66684
- const late = context.nowMs() - PUSH_GRACE_MS;
66685
- return entries.filter((entry) => !shown.includes(entry)).filter((entry) => entry.pushedAt === void 0 || pushedToo && entry.pushedAt <= late).map((entry) => entry.message);
66686
- }
66687
-
66688
66926
  // src/rules/activity-format.rules.ts
66689
66927
  function utcTimeOf(iso) {
66690
66928
  return `${iso.slice(0, 10)} ${iso.slice(11, 16)} UTC`;
@@ -67225,202 +67463,14 @@ function channelLabelIn(channel) {
67225
67463
  return `#${channel.name}`;
67226
67464
  }
67227
67465
 
67228
- // src/services/claude-project.service.ts
67229
- import { basename, isAbsolute, relative, resolve as resolve2 } from "node:path";
67230
- function harnessIn({ words }) {
67231
- const names = words.slice(0, 2).map((word3) => basename(word3).replace(/\.(js|mjs|cjs)$/, ""));
67232
- if (names.includes("codex")) return "codex";
67233
- if (words.some((word3) => word3.includes("@openai/codex"))) return "codex";
67234
- const claude = words.some((word3) => word3.includes("@anthropic-ai/claude-code"));
67235
- return claude || names.includes("claude") ? "claude-code" : void 0;
67236
- }
67237
- async function nearestHarnessOf({
67238
- context,
67239
- from = context.processes.pid
67240
- }) {
67241
- let pid = await context.processes.parentOf(from);
67242
- for (let depth = 0; pid !== void 0 && pid > 1 && depth < 12; depth += 1) {
67243
- const harness = harnessIn({ words: await context.processes.argsOf(pid) ?? [] });
67244
- if (harness) return { harness, pid };
67245
- pid = await context.processes.parentOf(pid);
67246
- }
67247
- return void 0;
67248
- }
67249
- function holds({ folder, inner }) {
67250
- const rel = relative(resolve2(folder), resolve2(inner));
67251
- return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
67252
- }
67253
- async function claudeProjectOf({
67254
- context,
67255
- claudePid
67256
- }) {
67257
- const env = context.environment.inherited;
67258
- const pid = Number(env.CLAUDE_PID);
67259
- const candidates = [
67260
- claudePid ? await context.processes.cwdOf(claudePid) : void 0,
67261
- env.CLAUDE_PROJECT_DIR ? resolve2(env.CLAUDE_PROJECT_DIR) : void 0,
67262
- pid > 0 ? await context.processes.cwdOf(pid) : void 0
67263
- ].filter((folder) => Boolean(folder));
67264
- return candidates.find((folder) => holds({ folder, inner: context.cwd })) ?? resolve2(context.cwd);
67265
- }
67266
-
67267
67466
  // src/services/claude-wait.service.ts
67268
- import { readFile as readFile5, rm as rm2, writeFile as writeFile5, mkdir as mkdir5 } from "node:fs/promises";
67467
+ import { readFile as readFile6, rm as rm2, writeFile as writeFile5, mkdir as mkdir5 } from "node:fs/promises";
67269
67468
  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
67469
  var ROUND_SECONDS = 50;
67420
67470
  var WATCH_MS = 2e3;
67421
67471
  var CHANNEL_CHECK_MS = 5e3;
67422
67472
  async function holderOf({ path }) {
67423
- return readFile5(path, "utf8").then(
67473
+ return readFile6(path, "utf8").then(
67424
67474
  (text2) => JSON.parse(text2),
67425
67475
  () => void 0
67426
67476
  );
@@ -67543,13 +67593,15 @@ async function waitForMessages({ context, args }) {
67543
67593
  const raw = await context.readStdin();
67544
67594
  const input2 = raw.trim() ? JSON.parse(raw) : {};
67545
67595
  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
67596
  const claudePid = await claudePidOf({ context });
67597
+ const asked = await pluginHookArgs({ context, args, session, claudePid });
67598
+ if (!asked) return 0;
67599
+ const named = await sessionProfileArgs({ context, args: asked, session });
67600
+ const { client, name: name2 } = await signedIn({ context, args: named });
67549
67601
  await rememberSession({ context, claudePid, session });
67550
67602
  const lock = statePathOf({ context, kind: "waiters", profile: name2 });
67551
67603
  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("");
67604
+ const seen = () => input2.transcript_path ? readFile6(input2.transcript_path, "utf8") : Promise.resolve("");
67553
67605
  const deadline = context.nowMs() + (WAIT_HOOK_TIMEOUT_SECONDS - 60) * 1e3;
67554
67606
  try {
67555
67607
  while (context.nowMs() < deadline) {
@@ -67584,7 +67636,7 @@ async function monitorServes({
67584
67636
  // src/services/codex-link.service.ts
67585
67637
  import { createReadStream } from "node:fs";
67586
67638
  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";
67639
+ import { join as join11, resolve as resolve3 } from "node:path";
67588
67640
  import { createInterface as createInterface2 } from "node:readline";
67589
67641
 
67590
67642
  // src/rules/connect-service.rules.ts
@@ -67704,8 +67756,8 @@ function rolloutEventOf({
67704
67756
 
67705
67757
  // src/services/codex-adopt.service.ts
67706
67758
  import { spawn as spawn2 } from "node:child_process";
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";
67759
+ import { mkdir as mkdir6, readdir as readdir2, readFile as readFile7, rm as rm3, stat, writeFile as writeFile6 } from "node:fs/promises";
67760
+ import { dirname as dirname6, join as join6 } from "node:path";
67709
67761
  import { createInterface } from "node:readline";
67710
67762
 
67711
67763
  // src/rules/codex-requests.rules.ts
@@ -67825,11 +67877,11 @@ var CodexAppServer = class _CodexAppServer {
67825
67877
  }
67826
67878
  };
67827
67879
  async function newestThreadId({ codexHome }) {
67828
- const root = join5(codexHome, "sessions");
67880
+ const root = join6(codexHome, "sessions");
67829
67881
  const files2 = await readdir2(root, { recursive: true }).catch(() => []);
67830
67882
  const rollouts = files2.filter((file3) => /rollout-.*\.jsonl$/.test(file3));
67831
67883
  const dated = await Promise.all(
67832
- rollouts.map(async (file3) => ({ file: file3, at: (await stat(join5(root, file3))).mtimeMs }))
67884
+ rollouts.map(async (file3) => ({ file: file3, at: (await stat(join6(root, file3))).mtimeMs }))
67833
67885
  );
67834
67886
  const newest = dated.toSorted((a, b) => b.at - a.at)[0]?.file ?? "";
67835
67887
  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);
@@ -67904,7 +67956,7 @@ async function answer({
67904
67956
  var MAX_RESTART_WAIT_SECONDS = 60;
67905
67957
  var HEALTHY_RUN_MS = 6e4;
67906
67958
  async function recordOf({ path }) {
67907
- return readFile6(path, "utf8").then(
67959
+ return readFile7(path, "utf8").then(
67908
67960
  (text2) => JSON.parse(text2),
67909
67961
  () => void 0
67910
67962
  );
@@ -68007,7 +68059,7 @@ async function adoptedThreadOf({
68007
68059
  );
68008
68060
  if (!held) return threadId;
68009
68061
  const path = statePathOf({ context, kind: "adopt", profile, extension: "forks.json" });
68010
- const forks = await readFile6(path, "utf8").then(
68062
+ const forks = await readFile7(path, "utf8").then(
68011
68063
  (text2) => JSON.parse(text2),
68012
68064
  () => ({})
68013
68065
  );
@@ -68078,20 +68130,20 @@ async function adoptCodex({ context, args }) {
68078
68130
  }
68079
68131
 
68080
68132
  // src/services/connect-delivery.service.ts
68081
- import { mkdir as mkdir8, readFile as readFile8, rename as rename3, rm as rm4, writeFile as writeFile8 } from "node:fs/promises";
68133
+ import { mkdir as mkdir8, readFile as readFile9, rename as rename3, rm as rm4, writeFile as writeFile8 } from "node:fs/promises";
68082
68134
  import { homedir as homedir2, hostname as hostname4 } from "node:os";
68083
- import { dirname as dirname8, join as join8 } from "node:path";
68135
+ import { dirname as dirname8, join as join9 } from "node:path";
68084
68136
 
68085
68137
  // src/services/codex-turn-watch.service.ts
68086
68138
  import { open as open2, readdir as readdir3 } from "node:fs/promises";
68087
- import { join as join6 } from "node:path";
68139
+ import { join as join7 } from "node:path";
68088
68140
  var READ_MS = 1500;
68089
68141
  var KEEP_WORKING_MS = 3e4;
68090
68142
  async function rolloutPathOf({ delivery }) {
68091
- const root = join6(delivery.codexHome, "sessions");
68143
+ const root = join7(delivery.codexHome, "sessions");
68092
68144
  const files2 = await readdir3(root, { recursive: true }).catch(() => []);
68093
68145
  const file3 = files2.find((name2) => name2.endsWith(`-${delivery.threadId}.jsonl`));
68094
- return file3 ? join6(root, file3) : void 0;
68146
+ return file3 ? join7(root, file3) : void 0;
68095
68147
  }
68096
68148
  async function readFrom({ path, offset }) {
68097
68149
  const handle = await open2(path, "r");
@@ -68177,8 +68229,8 @@ var CodexTurnWatch = class _CodexTurnWatch {
68177
68229
  };
68178
68230
 
68179
68231
  // src/services/openclaw-relay.service.ts
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";
68232
+ import { chmod as chmod2, mkdir as mkdir7, readFile as readFile8, writeFile as writeFile7 } from "node:fs/promises";
68233
+ import { dirname as dirname7, join as join8 } from "node:path";
68182
68234
 
68183
68235
  // ../../modules/openclaw/contract/src/openclaw.ts
68184
68236
  var workspaceIdSchema14 = external_exports.string().min(1);
@@ -68406,11 +68458,11 @@ var STOPS = /* @__PURE__ */ new Map([
68406
68458
  [OPENCLAW_RELAY_CLOSE.replaced.code, "another relay for this gateway took over"]
68407
68459
  ]);
68408
68460
  function relaysPathOf({ context }) {
68409
- return join7(dirname7(context.environment.configPath), "connect", "openclaw-relays.json");
68461
+ return join8(dirname7(context.environment.configPath), "connect", "openclaw-relays.json");
68410
68462
  }
68411
68463
  async function readRelays({ context }) {
68412
68464
  try {
68413
- return JSON.parse(await readFile7(relaysPathOf({ context }), "utf8"));
68465
+ return JSON.parse(await readFile8(relaysPathOf({ context }), "utf8"));
68414
68466
  } catch {
68415
68467
  return {};
68416
68468
  }
@@ -68607,14 +68659,14 @@ var RelayLoops = class _RelayLoops {
68607
68659
 
68608
68660
  // src/services/connect-delivery.service.ts
68609
68661
  function connectFolderOf({ context }) {
68610
- return join8(dirname8(context.environment.configPath), "connect");
68662
+ return join9(dirname8(context.environment.configPath), "connect");
68611
68663
  }
68612
68664
  function runStatePathOf({ context }) {
68613
- return join8(connectFolderOf({ context }), "run.json");
68665
+ return join9(connectFolderOf({ context }), "run.json");
68614
68666
  }
68615
68667
  async function readJson({ path }) {
68616
68668
  try {
68617
- return JSON.parse(await readFile8(path, "utf8"));
68669
+ return JSON.parse(await readFile9(path, "utf8"));
68618
68670
  } catch {
68619
68671
  return void 0;
68620
68672
  }
@@ -68848,7 +68900,7 @@ async function runConnectLoop({ context }) {
68848
68900
  // src/services/connect-service.service.ts
68849
68901
  import { createHash } from "node:crypto";
68850
68902
  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";
68903
+ import { dirname as dirname9, join as join10 } from "node:path";
68852
68904
  var CONNECT_SERVICE_USAGE = `laze connect install|status|stop|uninstall|run: the service that delivers to linked Codex sessions.
68853
68905
 
68854
68906
  laze connect install install and start it (systemd --user, a LaunchAgent, or detached)
@@ -68861,17 +68913,17 @@ var CONNECT_SERVICE_USAGE = `laze connect install|status|stop|uninstall|run: the
68861
68913
  \`laze openclaw connect --local\`, whose OpenClaw relay it also runs.
68862
68914
  `;
68863
68915
  function installedPathOf({ context }) {
68864
- return join9(connectFolderOf({ context }), "service.json");
68916
+ return join10(connectFolderOf({ context }), "service.json");
68865
68917
  }
68866
68918
  function logPathOf({ context }) {
68867
- return join9(connectFolderOf({ context }), "connect.log");
68919
+ return join10(connectFolderOf({ context }), "connect.log");
68868
68920
  }
68869
68921
  function homeOf({ context }) {
68870
68922
  return context.environment.inherited.HOME ?? dirname9(dirname9(context.environment.configPath));
68871
68923
  }
68872
68924
  function serviceNameOf({ context }) {
68873
68925
  const { configPath } = context.environment;
68874
- if (configPath === join9(homeOf({ context }), ".laze", "config.json")) return "laze-connect";
68926
+ if (configPath === join10(homeOf({ context }), ".laze", "config.json")) return "laze-connect";
68875
68927
  return `laze-connect-${createHash("sha256").update(configPath).digest("hex").slice(0, 8)}`;
68876
68928
  }
68877
68929
  function serviceEnvOf({ context }) {
@@ -68894,8 +68946,8 @@ async function run({ context, command }) {
68894
68946
  async function installSystemd({ context }) {
68895
68947
  const name2 = serviceNameOf({ context });
68896
68948
  const env = context.environment.inherited;
68897
- const base = env.XDG_CONFIG_HOME || join9(homeOf({ context }), ".config");
68898
- const file3 = join9(base, "systemd", "user", `${name2}.service`);
68949
+ const base = env.XDG_CONFIG_HOME || join10(homeOf({ context }), ".config");
68950
+ const file3 = join10(base, "systemd", "user", `${name2}.service`);
68899
68951
  await mkdir9(dirname9(file3), { recursive: true });
68900
68952
  await writeFile9(
68901
68953
  file3,
@@ -68910,7 +68962,7 @@ async function installSystemd({ context }) {
68910
68962
  async function installLaunchd({ context }) {
68911
68963
  const name2 = serviceNameOf({ context });
68912
68964
  const label2 = `ai.laze.${name2}`;
68913
- const file3 = join9(homeOf({ context }), "Library", "LaunchAgents", `${label2}.plist`);
68965
+ const file3 = join10(homeOf({ context }), "Library", "LaunchAgents", `${label2}.plist`);
68914
68966
  const log = logPathOf({ context });
68915
68967
  await mkdir9(dirname9(file3), { recursive: true });
68916
68968
  await writeFile9(
@@ -69078,13 +69130,13 @@ async function newestThreadIn({
69078
69130
  codexHome,
69079
69131
  directory
69080
69132
  }) {
69081
- const root = join10(codexHome, "sessions");
69133
+ const root = join11(codexHome, "sessions");
69082
69134
  const files2 = await readdir4(root, { recursive: true }).catch(() => []);
69083
69135
  const rollouts = files2.filter((file3) => /rollout-.*\.jsonl$/.test(file3));
69084
69136
  const dated = await Promise.all(
69085
69137
  rollouts.map(async (file3) => ({
69086
- path: join10(root, file3),
69087
- at: await stat2(join10(root, file3)).then(
69138
+ path: join11(root, file3),
69139
+ at: await stat2(join11(root, file3)).then(
69088
69140
  (info) => info.mtimeMs,
69089
69141
  () => 0
69090
69142
  )
@@ -69152,17 +69204,22 @@ async function linkCodexSession({
69152
69204
  }
69153
69205
 
69154
69206
  // src/services/laze-plugin.service.ts
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";
69207
+ import { mkdir as mkdir10, readFile as readFile10, writeFile as writeFile10 } from "node:fs/promises";
69208
+ import { dirname as dirname10, join as join12 } from "node:path";
69157
69209
 
69158
69210
  // src/rules/laze-plugin.rules.ts
69159
69211
  var LAZE_PLUGIN = "laze";
69160
69212
  var NPX_CLI = ["npx", "-y", "@lazehq/cli@latest"];
69161
69213
  var quote = (value) => `'${value.replaceAll("'", "'\\''")}'`;
69162
- function cliLineOf({ program, args }) {
69214
+ function cliLineOf({
69215
+ program,
69216
+ args,
69217
+ configPath
69218
+ }) {
69163
69219
  const here = [...program, ...args].map(quote).join(" ");
69164
69220
  const fallback = [...NPX_CLI, ...args].join(" ");
69165
- return `if [ -e ${quote(program.at(-1) ?? "")} ]; then exec ${here}; else exec ${fallback}; fi`;
69221
+ const run4 = `if [ -e ${quote(program.at(-1) ?? "")} ]; then exec ${here}; else exec ${fallback}; fi`;
69222
+ return `export LAZE_CLI_CONFIG=${quote(configPath)}; ${run4}`;
69166
69223
  }
69167
69224
  var SKILL = `---
69168
69225
  name: laze
@@ -69196,10 +69253,28 @@ are waiting, if you think one was missed.
69196
69253
  If \`laze\` is not on the PATH, run the same commands through \`npx -y @lazehq/cli@latest\`.
69197
69254
  Never print or repeat your Laze key.
69198
69255
  `;
69256
+ function pluginHooksOf({ line }) {
69257
+ const hook = (name2, timeout) => ({
69258
+ type: "command",
69259
+ command: line(["hook", name2, "--plugin"]),
69260
+ timeout
69261
+ });
69262
+ const waiter = { ...hook("wait", WAIT_HOOK_TIMEOUT_SECONDS), async: true, asyncRewake: true };
69263
+ return {
69264
+ description: "Hands Laze messages to the session and wakes it when one arrives",
69265
+ hooks: {
69266
+ Stop: [{ hooks: [hook("stop", HOOK_TIMEOUTS.Stop), waiter] }],
69267
+ SessionStart: [{ hooks: [waiter] }],
69268
+ PreToolUse: [{ hooks: [hook("pre-tool", HOOK_TIMEOUTS.PreToolUse)] }]
69269
+ }
69270
+ };
69271
+ }
69199
69272
  function lazePluginFiles({
69200
69273
  program,
69201
- version: version2
69274
+ version: version2,
69275
+ configPath
69202
69276
  }) {
69277
+ const line = (args) => cliLineOf({ program, args, configPath });
69203
69278
  const json5 = (value) => `${JSON.stringify(value, null, 2)}
69204
69279
  `;
69205
69280
  const description = "Laze messages reach this session, and the laze tools to answer them";
@@ -69234,10 +69309,11 @@ function lazePluginFiles({
69234
69309
  "laze/monitors/monitors.json": json5([
69235
69310
  {
69236
69311
  name: "laze-messages",
69237
- command: cliLineOf({ program, args: ["hook", "monitor"] }),
69312
+ command: line(["hook", "monitor"]),
69238
69313
  description: "Laze messages for this session"
69239
69314
  }
69240
- ])
69315
+ ]),
69316
+ "laze/hooks/hooks.json": json5(pluginHooksOf({ line }))
69241
69317
  };
69242
69318
  }
69243
69319
 
@@ -69245,11 +69321,11 @@ function lazePluginFiles({
69245
69321
  var REGISTER_LIMIT_MS = 6e4;
69246
69322
  var quote2 = (value) => `'${value.replaceAll("'", "'\\''")}'`;
69247
69323
  function pluginFolderOf({ context }) {
69248
- return join11(dirname10(context.environment.configPath), "plugins");
69324
+ return join12(dirname10(context.environment.configPath), "plugins");
69249
69325
  }
69250
69326
  async function pluginIsCurrent({ context }) {
69251
- const manifest = join11(pluginFolderOf({ context }), LAZE_PLUGIN, ".claude-plugin", "plugin.json");
69252
- const written = await readFile9(manifest, "utf8").then(
69327
+ const manifest = join12(pluginFolderOf({ context }), LAZE_PLUGIN, ".claude-plugin", "plugin.json");
69328
+ const written = await readFile10(manifest, "utf8").then(
69253
69329
  (text2) => JSON.parse(text2).version,
69254
69330
  () => void 0
69255
69331
  );
@@ -69257,9 +69333,13 @@ async function pluginIsCurrent({ context }) {
69257
69333
  }
69258
69334
  async function writeLazePlugin({ context }) {
69259
69335
  const folder = pluginFolderOf({ context });
69260
- const files2 = lazePluginFiles({ program: context.program, version: cliVersionOf() });
69336
+ const files2 = lazePluginFiles({
69337
+ program: context.program,
69338
+ version: cliVersionOf(),
69339
+ configPath: context.environment.configPath
69340
+ });
69261
69341
  for (const [path, text2] of Object.entries(files2)) {
69262
- const target = join11(folder, path);
69342
+ const target = join12(folder, path);
69263
69343
  await mkdir10(dirname10(target), { recursive: true });
69264
69344
  await writeFile10(target, text2);
69265
69345
  }
@@ -69280,10 +69360,10 @@ async function registerWithClaude({ context, folder }) {
69280
69360
  return code === 0;
69281
69361
  }
69282
69362
  function registeredMarkOf({ context }) {
69283
- return join11(pluginFolderOf({ context }), "registered");
69363
+ return join12(pluginFolderOf({ context }), "registered");
69284
69364
  }
69285
69365
  async function pluginRegistered({ context }) {
69286
- return readFile9(registeredMarkOf({ context }), "utf8").then(
69366
+ return readFile10(registeredMarkOf({ context }), "utf8").then(
69287
69367
  () => true,
69288
69368
  () => false
69289
69369
  );
@@ -69297,7 +69377,7 @@ async function installLazePlugin({ context }) {
69297
69377
  async function plugin({ context, args }) {
69298
69378
  const action = args.words[1] ?? "install";
69299
69379
  if (action === "path") {
69300
- context.out(`${join11(pluginFolderOf({ context }), LAZE_PLUGIN)}
69380
+ context.out(`${join12(pluginFolderOf({ context }), LAZE_PLUGIN)}
69301
69381
  `);
69302
69382
  return 0;
69303
69383
  }
@@ -69434,7 +69514,7 @@ async function pushInbox({
69434
69514
  }
69435
69515
 
69436
69516
  // src/services/plugin-tip.service.ts
69437
- import { mkdir as mkdir12, readFile as readFile10, writeFile as writeFile12 } from "node:fs/promises";
69517
+ import { mkdir as mkdir12, readFile as readFile11, writeFile as writeFile12 } from "node:fs/promises";
69438
69518
  import { dirname as dirname12 } from "node:path";
69439
69519
  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
69520
  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.";
@@ -69478,7 +69558,7 @@ async function reloadTipOnce({
69478
69558
  }) {
69479
69559
  if (!session || !monitorsRunHere({ context })) return void 0;
69480
69560
  if (!await pluginRegistered({ context })) return void 0;
69481
- const told = await readFile10(toldPathOf({ context, session }), "utf8").then(
69561
+ const told = await readFile11(toldPathOf({ context, session }), "utf8").then(
69482
69562
  () => true,
69483
69563
  () => false
69484
69564
  );
@@ -69544,9 +69624,9 @@ async function installHooks({
69544
69624
  directory,
69545
69625
  profile
69546
69626
  }) {
69547
- const folder = join12(directory, ".claude");
69548
- const path = join12(folder, "settings.local.json");
69549
- const current2 = await readFile11(path, "utf8").then(
69627
+ const folder = join13(directory, ".claude");
69628
+ const path = join13(folder, "settings.local.json");
69629
+ const current2 = await readFile12(path, "utf8").then(
69550
69630
  (text2) => JSON.parse(text2),
69551
69631
  () => ({})
69552
69632
  );
@@ -69747,7 +69827,7 @@ async function reportTranscript({
69747
69827
  input: input2
69748
69828
  }) {
69749
69829
  if (!input2.transcript_path || !input2.session_id) return;
69750
- const lines = (await readFile11(input2.transcript_path, "utf8")).split("\n");
69830
+ const lines = (await readFile12(input2.transcript_path, "utf8")).split("\n");
69751
69831
  const context = readTranscript({ lines });
69752
69832
  await client.post("/api/agents/me/activity", {
69753
69833
  sessionId: input2.session_id,
@@ -69764,21 +69844,23 @@ async function handOver({ context, args }) {
69764
69844
  const raw = await context.readStdin();
69765
69845
  const input2 = raw.trim() ? JSON.parse(raw) : {};
69766
69846
  const session = sessionOf({ context, harness: "claude-code", sessionId: input2.session_id });
69767
- const named = await sessionProfileArgs({ context, args, session });
69847
+ const claudePid = await claudePidOf({ context });
69848
+ const asked = await pluginHookArgs({ context, args, session, claudePid });
69849
+ if (!asked) return;
69850
+ const named = await sessionProfileArgs({ context, args: asked, session });
69768
69851
  const { client, name: agent2 } = await signedIn({ context, args: named });
69769
69852
  await reportTranscript({ client, input: input2 }).catch(
69770
69853
  (error62) => context.err(`laze: could not report context: ${String(error62)}
69771
69854
  `)
69772
69855
  );
69773
69856
  if (input2.stop_hook_active) return;
69774
- const claudePid = await claudePidOf({ context });
69775
69857
  if (await monitorServes({ context, profile: agent2, claudePid })) {
69776
69858
  return turnEnded({ context, client, agent: agent2 });
69777
69859
  }
69778
69860
  const kept = await dueFromSpool({
69779
69861
  context,
69780
69862
  profile: agent2,
69781
- seen: () => input2.transcript_path ? readFile11(input2.transcript_path, "utf8") : Promise.resolve(""),
69863
+ seen: () => input2.transcript_path ? readFile12(input2.transcript_path, "utf8") : Promise.resolve(""),
69782
69864
  pushedToo: false
69783
69865
  });
69784
69866
  const claim3 = forSession({ client, session });
@@ -69812,8 +69894,8 @@ async function addSessionStartWaiter({ context, args }) {
69812
69894
  const directory = context.environment.inherited.CLAUDE_PROJECT_DIR;
69813
69895
  const profile = flagText({ args, name: "profile" });
69814
69896
  if (!directory || !profile) return;
69815
- const path = join12(directory, ".claude", "settings.local.json");
69816
- const settings2 = await readFile11(path, "utf8").then(
69897
+ const path = join13(directory, ".claude", "settings.local.json");
69898
+ const settings2 = await readFile12(path, "utf8").then(
69817
69899
  (text2) => JSON.parse(text2),
69818
69900
  () => void 0
69819
69901
  );
@@ -69822,7 +69904,7 @@ async function addSessionStartWaiter({ context, args }) {
69822
69904
  }
69823
69905
  async function refreshPlugin({ context }) {
69824
69906
  if (await pluginIsCurrent({ context })) return;
69825
- const logPath = join12(pluginFolderOf({ context }), "install.log");
69907
+ const logPath = join13(pluginFolderOf({ context }), "install.log");
69826
69908
  context.processes.spawnDetached({ argv: [...context.program, "plugin", "install"], logPath });
69827
69909
  }
69828
69910
  async function stopHook({ context, args }) {
@@ -69840,7 +69922,7 @@ async function stopHook({ context, args }) {
69840
69922
  }
69841
69923
 
69842
69924
  // src/services/agent-manage-commands.service.ts
69843
- import { readFile as readFile12 } from "node:fs/promises";
69925
+ import { readFile as readFile13 } from "node:fs/promises";
69844
69926
  import { extname, resolve as resolve5 } from "node:path";
69845
69927
 
69846
69928
  // src/rules/login-format.rules.ts
@@ -69969,7 +70051,7 @@ async function avatarOf({
69969
70051
  }) {
69970
70052
  const path = flagText({ args, name: "avatar" });
69971
70053
  if (!path) return void 0;
69972
- const bytes = await readFile12(resolve5(context.cwd, path)).catch(() => {
70054
+ const bytes = await readFile13(resolve5(context.cwd, path)).catch(() => {
69973
70055
  throw new CliUsageError(`laze: cannot read the avatar file ${path}.`);
69974
70056
  });
69975
70057
  const uploaded = await client.post("/api/agents/avatars", {
@@ -70659,8 +70741,8 @@ async function requestAgent({ context, args }) {
70659
70741
  }
70660
70742
 
70661
70743
  // src/services/app-commands.service.ts
70662
- import { mkdir as mkdir14, readdir as readdir5, readFile as readFile13, writeFile as writeFile15 } from "node:fs/promises";
70663
- import { dirname as dirname13, join as join14, relative as relative3, resolve as resolve6, sep as sep2 } from "node:path";
70744
+ import { mkdir as mkdir14, readdir as readdir5, readFile as readFile14, writeFile as writeFile15 } from "node:fs/promises";
70745
+ import { dirname as dirname13, join as join15, relative as relative3, resolve as resolve6, sep as sep2 } from "node:path";
70664
70746
 
70665
70747
  // ../../modules/app/contract/src/app.connections.ts
70666
70748
  var appFunctionNameSchema = external_exports.string().regex(/^[a-z0-9][a-z0-9_-]{0,63}$/);
@@ -73053,7 +73135,7 @@ async function appPinsCommand({
73053
73135
  import { execFile } from "node:child_process";
73054
73136
  import { mkdtemp, rm as rm8, writeFile as writeFile14 } from "node:fs/promises";
73055
73137
  import { tmpdir } from "node:os";
73056
- import { join as join13 } from "node:path";
73138
+ import { join as join14 } from "node:path";
73057
73139
  import { promisify } from "node:util";
73058
73140
  var run2 = promisify(execFile);
73059
73141
  var MODULE_SYNTAX = /^\s*(import|export)\s/m;
@@ -73082,11 +73164,11 @@ async function scriptErrorsOf({
73082
73164
  const unknown2 = unknownCollectionsOf({ files: files2, collections });
73083
73165
  const scripts = files2.flatMap(scriptsOf);
73084
73166
  if (scripts.length === 0) return unknown2;
73085
- const dir = await mkdtemp(join13(tmpdir(), "laze-app-check-"));
73167
+ const dir = await mkdtemp(join14(tmpdir(), "laze-app-check-"));
73086
73168
  try {
73087
73169
  const errors = await Promise.all(
73088
73170
  scripts.map(async (script, index) => {
73089
- const file3 = join13(dir, `${index}.${script.module ? "mjs" : "cjs"}`);
73171
+ const file3 = join14(dir, `${index}.${script.module ? "mjs" : "cjs"}`);
73090
73172
  await writeFile14(file3, script.code);
73091
73173
  try {
73092
73174
  await run2(process.execPath, ["--check", file3]);
@@ -73236,7 +73318,7 @@ async function turnTokenOf({
73236
73318
  const pinned = env.LAZE_TURN_TOKEN?.trim();
73237
73319
  if (pinned) return pinned;
73238
73320
  if (env.LAZE_TURN_FILE) {
73239
- return readFile13(env.LAZE_TURN_FILE, "utf8").then(
73321
+ return readFile14(env.LAZE_TURN_FILE, "utf8").then(
73240
73322
  (text2) => text2.trim(),
73241
73323
  () => ""
73242
73324
  );
@@ -73262,7 +73344,7 @@ function folderOf({ context, word: word3 }) {
73262
73344
  return resolve6(context.cwd, word3 ?? ".");
73263
73345
  }
73264
73346
  async function readManifest(folder) {
73265
- const text2 = await readFile13(join14(folder, APP_MANIFEST_FILE), "utf8").catch(() => void 0);
73347
+ const text2 = await readFile14(join15(folder, APP_MANIFEST_FILE), "utf8").catch(() => void 0);
73266
73348
  if (text2 === void 0) return void 0;
73267
73349
  const parsed = appManifestSchema.safeParse(JSON.parse(text2));
73268
73350
  if (!parsed.success) {
@@ -73297,7 +73379,7 @@ async function jsonFlag({
73297
73379
  }) {
73298
73380
  const raw = flagText({ args, name: name2 });
73299
73381
  if (!raw) return void 0;
73300
- const text2 = raw.startsWith("@") ? await readFile13(resolve6(context.cwd, raw.slice(1)), "utf8") : raw;
73382
+ const text2 = raw.startsWith("@") ? await readFile14(resolve6(context.cwd, raw.slice(1)), "utf8") : raw;
73301
73383
  try {
73302
73384
  return JSON.parse(text2);
73303
73385
  } catch {
@@ -73310,7 +73392,7 @@ async function listFiles(folder) {
73310
73392
  while (pending.length > 0 && found.length <= MAX_FILES) {
73311
73393
  const current2 = pending.pop() ?? folder;
73312
73394
  for (const entry of await readdir5(current2, { withFileTypes: true })) {
73313
- const path = join14(current2, entry.name);
73395
+ const path = join15(current2, entry.name);
73314
73396
  const rel = relative3(folder, path).split(sep2).join("/");
73315
73397
  if (isSkippedPath({ path: rel })) continue;
73316
73398
  if (entry.isDirectory()) pending.push(path);
@@ -73354,8 +73436,8 @@ var appCreate = async ({ context, args }) => {
73354
73436
  await mkdir14(folder, { recursive: true });
73355
73437
  const files2 = template ? templateFiles({ template, name: name2 }) : {};
73356
73438
  for (const [path, content] of Object.entries(files2)) {
73357
- await mkdir14(dirname13(join14(folder, path)), { recursive: true });
73358
- await writeFile15(join14(folder, path), content);
73439
+ await mkdir14(dirname13(join15(folder, path)), { recursive: true });
73440
+ await writeFile15(join15(folder, path), content);
73359
73441
  }
73360
73442
  const manifest = {
73361
73443
  app: { id: app2.id, name: app2.name, slug: app2.slug },
@@ -73363,7 +73445,7 @@ var appCreate = async ({ context, args }) => {
73363
73445
  views: template?.views ? [...template.views] : [],
73364
73446
  seed: template ? { ...template.seed } : {}
73365
73447
  };
73366
- await writeFile15(join14(folder, APP_MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}
73448
+ await writeFile15(join15(folder, APP_MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}
73367
73449
  `);
73368
73450
  print5({
73369
73451
  context,
@@ -73400,7 +73482,7 @@ var appPush = async ({ context, args }) => {
73400
73482
  paths.map(
73401
73483
  async (path) => buildFileOf({
73402
73484
  path: relative3(folder, path).split(sep2).join("/"),
73403
- bytes: await readFile13(path)
73485
+ bytes: await readFile14(path)
73404
73486
  })
73405
73487
  )
73406
73488
  );
@@ -73783,7 +73865,7 @@ var appImport = async ({ context, args }) => {
73783
73865
  const words = args.words.slice(2);
73784
73866
  const [named, collection, file3] = words.length >= 3 ? words : [void 0, ...words];
73785
73867
  if (!collection || !file3) throw new CliUsageError(USAGE5);
73786
- const csv = await readFile13(resolve6(context.cwd, file3), "utf8").catch(() => {
73868
+ const csv = await readFile14(resolve6(context.cwd, file3), "utf8").catch(() => {
73787
73869
  throw new CliUsageError(`Cannot read ${file3}`);
73788
73870
  });
73789
73871
  const scoped = named ? { ...args, flags: { ...args.flags, app: named } } : args;
@@ -74349,8 +74431,8 @@ async function billing({ context, args }) {
74349
74431
 
74350
74432
  // src/services/browser-commands.service.ts
74351
74433
  import { randomBytes } from "node:crypto";
74352
- import { mkdir as mkdir15, readFile as readFile14, writeFile as writeFile16 } from "node:fs/promises";
74353
- import { dirname as dirname14, join as join15 } from "node:path";
74434
+ import { mkdir as mkdir15, readFile as readFile15, writeFile as writeFile16 } from "node:fs/promises";
74435
+ import { dirname as dirname14, join as join16 } from "node:path";
74354
74436
 
74355
74437
  // src/services/browser-tab-commands.service.ts
74356
74438
  var BROWSER_TAB_PATHS = {
@@ -74896,7 +74978,7 @@ async function turnTokenOf2({ context }) {
74896
74978
  const pinned = env.LAZE_TURN_TOKEN?.trim();
74897
74979
  if (pinned) return pinned;
74898
74980
  if (!env.LAZE_TURN_FILE) return "";
74899
- return readFile14(env.LAZE_TURN_FILE, "utf8").then(
74981
+ return readFile15(env.LAZE_TURN_FILE, "utf8").then(
74900
74982
  (text2) => text2.trim(),
74901
74983
  () => ""
74902
74984
  );
@@ -74970,7 +75052,7 @@ async function cdp({ context, args }) {
74970
75052
  }
74971
75053
  function bridgeStatePath({ context, machine: machine2 }) {
74972
75054
  const safe = machine2.replace(/[^a-zA-Z0-9_-]/g, "_");
74973
- return join15(dirname14(context.environment.configPath), "bridges", `${safe}.json`);
75055
+ return join16(dirname14(context.environment.configPath), "bridges", `${safe}.json`);
74974
75056
  }
74975
75057
  async function bridgePort({
74976
75058
  context,
@@ -74978,7 +75060,7 @@ async function bridgePort({
74978
75060
  access
74979
75061
  }) {
74980
75062
  const path = bridgeStatePath({ context, machine: machine2 });
74981
- const live = await readFile14(path, "utf8").then(
75063
+ const live = await readFile15(path, "utf8").then(
74982
75064
  (text2) => JSON.parse(text2),
74983
75065
  () => void 0
74984
75066
  );
@@ -75636,7 +75718,7 @@ async function channelSettings({ context, args }) {
75636
75718
  }
75637
75719
 
75638
75720
  // src/services/chat-actions-commands.service.ts
75639
- import { readFile as readFile15 } from "node:fs/promises";
75721
+ import { readFile as readFile16 } from "node:fs/promises";
75640
75722
  import { basename as basename2, isAbsolute as isAbsolute2, relative as relative4, resolve as resolve7 } from "node:path";
75641
75723
 
75642
75724
  // src/services/file-upload.service.ts
@@ -75941,7 +76023,7 @@ function uploadNameOf({ cwd, path }) {
75941
76023
  }
75942
76024
  var fileUpload = async ({ context, args, client }) => {
75943
76025
  const path = resolve7(context.cwd, wordAt(args, 3));
75944
- const bytes = new Uint8Array(await readFile15(path));
76026
+ const bytes = new Uint8Array(await readFile16(path));
75945
76027
  const answer4 = await uploadFile({
75946
76028
  context,
75947
76029
  client,
@@ -76106,26 +76188,9 @@ async function chatActions({
76106
76188
  }
76107
76189
 
76108
76190
  // src/services/claude-monitor.service.ts
76109
- import { readFile as readFile16, rm as rm9 } from "node:fs/promises";
76191
+ import { readFile as readFile17, rm as rm9 } from "node:fs/promises";
76110
76192
  var MONITOR_IDLE_MS = 3e4;
76111
76193
  var MONITOR_OUTRANKED_MS = 3e3;
76112
- async function agentProfileHere({
76113
- context,
76114
- args,
76115
- session,
76116
- claudePid
76117
- }) {
76118
- const config2 = await context.store.read();
76119
- const cwd = (claudePid ? await context.processes.cwdOf(claudePid) : void 0) ?? context.cwd;
76120
- const folder = boundProfileOf({ bindings: config2.bindings, cwd });
76121
- if (!folder && !session) return void 0;
76122
- const asked = { ...args, flags: { ...args.flags, ...folder ? { profile: folder } : {} } };
76123
- const name2 = flagText({
76124
- args: await sessionProfileArgs({ context, args: asked, session }),
76125
- name: "profile"
76126
- });
76127
- return name2 && config2.profiles[name2]?.kind === "agent" ? name2 : void 0;
76128
- }
76129
76194
  async function deliverOnce({
76130
76195
  context,
76131
76196
  args,
@@ -76212,7 +76277,7 @@ async function monitorSessionOf({
76212
76277
  const fromEnv = sessionOf({ context, harness: "claude-code", sessionId });
76213
76278
  if (fromEnv || !claudePid) return fromEnv;
76214
76279
  const path = statePathOf({ context, kind: "sessions", profile: String(claudePid) });
76215
- return readFile16(path, "utf8").then(
76280
+ return readFile17(path, "utf8").then(
76216
76281
  (text2) => JSON.parse(text2),
76217
76282
  () => void 0
76218
76283
  );
@@ -77699,10 +77764,10 @@ async function computer({ context, args }) {
77699
77764
  }
77700
77765
 
77701
77766
  // src/services/connect-commands.service.ts
77702
- import { readFile as readFile18 } from "node:fs/promises";
77767
+ import { readFile as readFile19 } from "node:fs/promises";
77703
77768
 
77704
77769
  // src/services/mcp-gateway.service.ts
77705
- import { readFile as readFile17 } from "node:fs/promises";
77770
+ import { readFile as readFile18 } from "node:fs/promises";
77706
77771
  import { createInterface as createInterface3 } from "node:readline";
77707
77772
  var TURN_HEADER = "x-laze-turn";
77708
77773
  function serveMcpGateway({
@@ -77745,7 +77810,7 @@ async function relayMcpLines({
77745
77810
  const github3 = env.LAZE_GITHUB_CONNECTION;
77746
77811
  const url2 = `${profile.url.replace(/\/+$/, "")}/api/connectors/mcp/${encodeURIComponent(profile.agentId)}${github3 ? `?github=${encodeURIComponent(github3)}` : ""}`;
77747
77812
  const turnFile = env.LAZE_TURN_FILE;
77748
- const readTurn = () => readFile17(turnFile, "utf8").then(
77813
+ const readTurn = () => readFile18(turnFile, "utf8").then(
77749
77814
  (text2) => text2.trim(),
77750
77815
  () => ""
77751
77816
  );
@@ -77835,7 +77900,7 @@ async function turnOf({ context }) {
77835
77900
  const pinned = env.LAZE_TURN_TOKEN?.trim();
77836
77901
  if (pinned) return pinned;
77837
77902
  const file3 = env.LAZE_TURN_FILE;
77838
- const turn = file3 ? await readFile18(file3, "utf8").then(
77903
+ const turn = file3 ? await readFile19(file3, "utf8").then(
77839
77904
  (text2) => text2.trim(),
77840
77905
  () => ""
77841
77906
  ) : "";
@@ -77893,11 +77958,11 @@ async function connect({
77893
77958
  }
77894
77959
 
77895
77960
  // src/services/connector-commands.service.ts
77896
- import { readFile as readFile20 } from "node:fs/promises";
77961
+ import { readFile as readFile21 } from "node:fs/promises";
77897
77962
  import { resolve as resolve8 } from "node:path";
77898
77963
 
77899
77964
  // src/services/vault-keychain-commands.service.ts
77900
- import { readFile as readFile19 } from "node:fs/promises";
77965
+ import { readFile as readFile20 } from "node:fs/promises";
77901
77966
 
77902
77967
  // src/rules/vault-input.rules.ts
77903
77968
  function secondsOf(text2) {
@@ -78208,7 +78273,7 @@ async function secretText({ context, args }) {
78208
78273
  );
78209
78274
  }
78210
78275
  const file3 = flagText({ args, name: "from-file" });
78211
- const text2 = file3 ? await readFile19(file3, "utf8") : await context.readStdin();
78276
+ const text2 = file3 ? await readFile20(file3, "utf8") : await context.readStdin();
78212
78277
  const trimmed = text2.replace(/\r?\n$/, "");
78213
78278
  if (!trimmed.trim()) throw new CliUsageError("No value: pipe it on stdin or use --from-file.");
78214
78279
  return trimmed;
@@ -78406,7 +78471,7 @@ async function keyText({ context, args }) {
78406
78471
  throw new CliUsageError("A key never goes in a flag: pipe it on stdin or use --from-file.");
78407
78472
  }
78408
78473
  const file3 = flagText({ args, name: "from-file" });
78409
- const text2 = file3 ? await readFile20(resolve8(context.cwd, file3), "utf8") : await context.readStdin();
78474
+ const text2 = file3 ? await readFile21(resolve8(context.cwd, file3), "utf8") : await context.readStdin();
78410
78475
  const trimmed = text2.trim();
78411
78476
  if (!trimmed) throw new CliUsageError("No key: pipe it on stdin or use --from-file.");
78412
78477
  return trimmed;
@@ -78792,8 +78857,8 @@ var DOMAINS_USAGE = `Usage:
78792
78857
  var printJson4 = (context, data) => context.out(`${JSON.stringify(data, null, 2)}
78793
78858
  `);
78794
78859
  function printDomain(context, row) {
78795
- const join19 = row.autoJoin ? "auto-join on" : "auto-join off";
78796
- context.out(`${row.domain} ${join19}${row.enforced ? " single sign-on enforced" : ""}
78860
+ const join20 = row.autoJoin ? "auto-join on" : "auto-join off";
78861
+ context.out(`${row.domain} ${join20}${row.enforced ? " single sign-on enforced" : ""}
78797
78862
  `);
78798
78863
  }
78799
78864
  async function list4({ context, args }) {
@@ -78825,7 +78890,7 @@ async function domains({ context, args }) {
78825
78890
  }
78826
78891
 
78827
78892
  // src/services/feed-commands.service.ts
78828
- import { readFile as readFile22 } from "node:fs/promises";
78893
+ import { readFile as readFile23 } from "node:fs/promises";
78829
78894
  import { resolve as resolve10 } from "node:path";
78830
78895
 
78831
78896
  // src/rules/feed-input.rules.ts
@@ -78950,7 +79015,7 @@ function feedFlagsOf({ args }) {
78950
79015
  }
78951
79016
 
78952
79017
  // src/services/feed-files.service.ts
78953
- import { readFile as readFile21 } from "node:fs/promises";
79018
+ import { readFile as readFile22 } from "node:fs/promises";
78954
79019
  import { basename as basename3, resolve as resolve9 } from "node:path";
78955
79020
 
78956
79021
  // ../../modules/feed/contract/src/feed.ts
@@ -79543,7 +79608,7 @@ async function local({ context, path }) {
79543
79608
  return {
79544
79609
  fileName,
79545
79610
  contentType: contentTypeOf(fileName),
79546
- bytes: new Uint8Array(await readFile21(full))
79611
+ bytes: new Uint8Array(await readFile22(full))
79547
79612
  };
79548
79613
  }
79549
79614
  async function directWith({ client, to }) {
@@ -79621,7 +79686,7 @@ async function bodyOf2({
79621
79686
  flags: flags2
79622
79687
  }) {
79623
79688
  const body = { ...flags2.fields };
79624
- const read3 = (source) => "file" in source ? readFile22(resolve10(context.cwd, source.file), "utf8") : source.text;
79689
+ const read3 = (source) => "file" in source ? readFile23(resolve10(context.cwd, source.file), "utf8") : source.text;
79625
79690
  for (const [field, source] of Object.entries(flags2.texts)) body[field] = await read3(source);
79626
79691
  if (flags2.rich) {
79627
79692
  const text2 = await read3(flags2.rich.source);
@@ -79783,7 +79848,7 @@ async function textFlag({
79783
79848
  }) {
79784
79849
  const value = flagText({ args, name: name2 });
79785
79850
  if (!value.startsWith("@")) return value;
79786
- return readFile22(resolve10(context.cwd, value.slice(1)), "utf8");
79851
+ return readFile23(resolve10(context.cwd, value.slice(1)), "utf8");
79787
79852
  }
79788
79853
  async function feedList({ context, args }) {
79789
79854
  const { client } = await signedIn({ context, args });
@@ -79893,7 +79958,7 @@ async function feed({ context, args }) {
79893
79958
  }
79894
79959
 
79895
79960
  // src/services/github-commands.service.ts
79896
- import { readFile as readFile23 } from "node:fs/promises";
79961
+ import { readFile as readFile24 } from "node:fs/promises";
79897
79962
 
79898
79963
  // src/rules/github-signature.rules.ts
79899
79964
  var TURN_SEPARATOR = "~";
@@ -79963,7 +80028,7 @@ var REAL_GH = "/usr/bin/gh";
79963
80028
  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>`.";
79964
80029
  async function turnFileToken({ env }) {
79965
80030
  if (!env.LAZE_TURN_FILE) return "";
79966
- return readFile23(env.LAZE_TURN_FILE, "utf8").then(
80031
+ return readFile24(env.LAZE_TURN_FILE, "utf8").then(
79967
80032
  (text2) => text2.trim(),
79968
80033
  () => ""
79969
80034
  );
@@ -79997,7 +80062,7 @@ async function githubGh({
79997
80062
  args: args.rest,
79998
80063
  agentName: profile.name ?? "An agent",
79999
80064
  threadUrl: threadUrlOf({ env, workspaceId: profile.workspaceId }),
80000
- readBodyFile: (path) => path === "-" ? context.readStdin() : readFile23(path, "utf8")
80065
+ readBodyFile: (path) => path === "-" ? context.readStdin() : readFile24(path, "utf8")
80001
80066
  });
80002
80067
  return context.runCommand({
80003
80068
  command: [REAL_GH, ...ghArgs],
@@ -80096,7 +80161,7 @@ async function setAgentGithub({
80096
80161
  }
80097
80162
 
80098
80163
  // src/services/history-commands.service.ts
80099
- import { readFile as readFile24 } from "node:fs/promises";
80164
+ import { readFile as readFile25 } from "node:fs/promises";
80100
80165
 
80101
80166
  // src/rules/history-format.rules.ts
80102
80167
  function timeOf2(iso) {
@@ -80192,7 +80257,7 @@ async function turnTokenOf3({ context }) {
80192
80257
  const pinned = env.LAZE_TURN_TOKEN?.trim();
80193
80258
  if (pinned) return pinned;
80194
80259
  if (!env.LAZE_TURN_FILE) return "";
80195
- return readFile24(env.LAZE_TURN_FILE, "utf8").then(
80260
+ return readFile25(env.LAZE_TURN_FILE, "utf8").then(
80196
80261
  (text2) => text2.trim(),
80197
80262
  () => ""
80198
80263
  );
@@ -80384,19 +80449,19 @@ async function ip({ context, args }) {
80384
80449
  }
80385
80450
 
80386
80451
  // src/services/join-commands.service.ts
80387
- import { mkdir as mkdir16, readFile as readFile25, rename as rename5, rm as rm10, writeFile as writeFile17 } from "node:fs/promises";
80388
- import { dirname as dirname15, join as join16 } from "node:path";
80452
+ import { mkdir as mkdir16, readFile as readFile26, rename as rename5, rm as rm10, writeFile as writeFile17 } from "node:fs/promises";
80453
+ import { dirname as dirname15, join as join17 } from "node:path";
80389
80454
  var DEFAULT_WAIT_SECONDS2 = 100;
80390
80455
  var JOIN_USAGE = "Usage: laze join [--workspace <name|id|invite link>] [--for <email>] [--name <name>] [--note <text>] [--timeout <seconds>] [--project <folder>]";
80391
80456
  function pendingPathOf({ context }) {
80392
- return join16(dirname15(context.environment.configPath), "join", "pending.json");
80457
+ return join17(dirname15(context.environment.configPath), "join", "pending.json");
80393
80458
  }
80394
80459
  async function readPending({
80395
80460
  context,
80396
80461
  url: url2,
80397
80462
  args
80398
80463
  }) {
80399
- const pending = await readFile25(pendingPathOf({ context }), "utf8").then(
80464
+ const pending = await readFile26(pendingPathOf({ context }), "utf8").then(
80400
80465
  (text2) => JSON.parse(text2),
80401
80466
  () => void 0
80402
80467
  );
@@ -80726,9 +80791,9 @@ function machineAccessCommand(name2) {
80726
80791
 
80727
80792
  // src/services/vault-commands.service.ts
80728
80793
  import { createHash as createHash2 } from "node:crypto";
80729
- import { mkdir as mkdir17, readFile as readFile26, rm as rm11, writeFile as writeFile18 } from "node:fs/promises";
80794
+ import { mkdir as mkdir17, readFile as readFile27, rm as rm11, writeFile as writeFile18 } from "node:fs/promises";
80730
80795
  import { tmpdir as tmpdir2 } from "node:os";
80731
- import { dirname as dirname16, join as join17 } from "node:path";
80796
+ import { dirname as dirname16, join as join18 } from "node:path";
80732
80797
  var USAGE10 = `Usage: laze vault run <connection> --reason "<one plain sentence>" [--wait <s>] -- <command> [args...]
80733
80798
  Runs the command with the connection's values in its environment, on a Laze agent's computer
80734
80799
  or on a machine it runs on.`;
@@ -80767,7 +80832,7 @@ async function turnTokenOf4({
80767
80832
  if (pinned) return pinned;
80768
80833
  if (!turnFile) throw new CliUsageError(`${command} works only during an agent's turn`);
80769
80834
  try {
80770
- return (await readFile26(turnFile, "utf8")).trim();
80835
+ return (await readFile27(turnFile, "utf8")).trim();
80771
80836
  } catch {
80772
80837
  throw new CliUsageError(`${command} works only during an agent's turn`);
80773
80838
  }
@@ -80777,11 +80842,11 @@ function runKeyPathOf({
80777
80842
  connection
80778
80843
  }) {
80779
80844
  const name2 = createHash2("sha256").update(connection).digest("hex");
80780
- const base = turnFile ? dirname16(turnFile) : join17(tmpdir2(), "laze-vault");
80781
- return join17(base, "vault-run-keys", `${name2}.json`);
80845
+ const base = turnFile ? dirname16(turnFile) : join18(tmpdir2(), "laze-vault");
80846
+ return join18(base, "vault-run-keys", `${name2}.json`);
80782
80847
  }
80783
80848
  async function runKeyAt({ path }) {
80784
- const saved3 = await readFile26(path, "utf8").then(
80849
+ const saved3 = await readFile27(path, "utf8").then(
80785
80850
  (text2) => JSON.parse(text2),
80786
80851
  () => void 0
80787
80852
  );
@@ -81463,14 +81528,14 @@ async function serveMcp({
81463
81528
  }
81464
81529
 
81465
81530
  // src/services/mount-files.service.ts
81466
- import { mkdir as mkdir18, readFile as readFile27, rm as rm12, writeFile as writeFile19 } from "node:fs/promises";
81531
+ import { mkdir as mkdir18, readFile as readFile28, rm as rm12, writeFile as writeFile19 } from "node:fs/promises";
81467
81532
  import { dirname as dirname17, relative as relative5, resolve as resolve11 } from "node:path";
81468
81533
  async function textArgument({
81469
81534
  context,
81470
81535
  value
81471
81536
  }) {
81472
81537
  if (value === "-") return context.readStdin();
81473
- if (value.startsWith("@")) return readFile27(resolve11(context.cwd, value.slice(1)), "utf8");
81538
+ if (value.startsWith("@")) return readFile28(resolve11(context.cwd, value.slice(1)), "utf8");
81474
81539
  return value;
81475
81540
  }
81476
81541
  function turnChannel({ context, args }) {
@@ -82368,8 +82433,8 @@ async function schedule({ context, args }) {
82368
82433
  }
82369
82434
 
82370
82435
  // src/services/skill-commands.service.ts
82371
- import { readdir as readdir6, readFile as readFile28 } from "node:fs/promises";
82372
- import { join as join18, relative as relative6, resolve as resolve12 } from "node:path";
82436
+ import { readdir as readdir6, readFile as readFile29 } from "node:fs/promises";
82437
+ import { join as join19, relative as relative6, resolve as resolve12 } from "node:path";
82373
82438
  var USAGE16 = `Usage:
82374
82439
  laze skill list [--agent <agentId>]
82375
82440
  laze skill install <catalogue-id> [--as <name>] [--agent <agentId>]
@@ -82390,8 +82455,8 @@ async function folderFiles({ root }) {
82390
82455
  const files2 = [];
82391
82456
  for (const entry of entries) {
82392
82457
  if (!entry.isFile()) continue;
82393
- const full = join18(entry.parentPath, entry.name);
82394
- files2.push({ path: relative6(root, full), content: await readFile28(full, "utf8") });
82458
+ const full = join19(entry.parentPath, entry.name);
82459
+ files2.push({ path: relative6(root, full), content: await readFile29(full, "utf8") });
82395
82460
  }
82396
82461
  return files2.toSorted((a, b) => a.path.localeCompare(b.path));
82397
82462
  }
@@ -82489,7 +82554,7 @@ async function skillUpdate({ context, args }) {
82489
82554
  if (!name2 || !newName && description === void 0 && !skillMdFile) {
82490
82555
  throw new CliUsageError(USAGE16);
82491
82556
  }
82492
- const skillMd = skillMdFile ? await readFile28(resolve12(context.cwd, skillMdFile), "utf8") : void 0;
82557
+ const skillMd = skillMdFile ? await readFile29(resolve12(context.cwd, skillMdFile), "utf8") : void 0;
82493
82558
  const { client } = await signedIn({ context, args });
82494
82559
  const updated = await client.post("/api/skills/update", {
82495
82560
  name: name2,
@@ -82535,7 +82600,7 @@ async function skill({ context, args }) {
82535
82600
  }
82536
82601
 
82537
82602
  // src/services/slack-commands.service.ts
82538
- import { readFile as readFile29 } from "node:fs/promises";
82603
+ import { readFile as readFile30 } from "node:fs/promises";
82539
82604
  import { resolve as resolve13 } from "node:path";
82540
82605
  var SLACK_USAGE = `Usage (a person's key; Slack stays the source, the bot joins no channel by itself):
82541
82606
  laze slack overview connected Slack workspaces, mirrors, your link
@@ -82583,7 +82648,7 @@ async function secretLines({ context, args }) {
82583
82648
  throw new CliUsageError("A secret never goes in a flag: pipe it on stdin or use --from-file.");
82584
82649
  }
82585
82650
  const file3 = flagText({ args, name: "from-file" });
82586
- const text2 = file3 ? await readFile29(resolve13(context.cwd, file3), "utf8") : await context.readStdin();
82651
+ const text2 = file3 ? await readFile30(resolve13(context.cwd, file3), "utf8") : await context.readStdin();
82587
82652
  return text2.split("\n").map((line) => line.trim()).filter(Boolean);
82588
82653
  }
82589
82654
  async function secretsOf({
@@ -82887,7 +82952,7 @@ async function slack({
82887
82952
  }
82888
82953
 
82889
82954
  // src/services/sso-commands.service.ts
82890
- import { readFile as readFile30 } from "node:fs/promises";
82955
+ import { readFile as readFile31 } from "node:fs/promises";
82891
82956
  var SSO_USAGE = `Usage:
82892
82957
  laze sso domains claimed domains and how each signs in (admins)
82893
82958
  laze sso claim <domain> the TXT record that proves the domain
@@ -82974,7 +83039,7 @@ function refuseSecretFlags({ args }) {
82974
83039
  }
82975
83040
  async function clientSecretOf({ context, args }) {
82976
83041
  const file3 = flagText({ args, name: "from-file" });
82977
- const text2 = file3 ? await readFile30(file3, "utf8") : await context.readStdin();
83042
+ const text2 = file3 ? await readFile31(file3, "utf8") : await context.readStdin();
82978
83043
  const secret = text2.trim();
82979
83044
  if (!secret) throw new CliUsageError("No client secret: pipe it on stdin or use --from-file.");
82980
83045
  return secret;
@@ -83307,7 +83372,7 @@ async function vaultScrub({ context, args }) {
83307
83372
  }
83308
83373
 
83309
83374
  // src/services/whatsapp-business-commands.service.ts
83310
- import { readFile as readFile31 } from "node:fs/promises";
83375
+ import { readFile as readFile32 } from "node:fs/promises";
83311
83376
  import { resolve as resolve14 } from "node:path";
83312
83377
 
83313
83378
  // ../../modules/whatsapp-business/contract/src/whatsapp-business.prices.ts
@@ -83727,7 +83792,7 @@ async function secretsOf2({ context, args }) {
83727
83792
  const fromConnection = flagText({ args, name: "from-vault" });
83728
83793
  if (fromConnection) return { fromConnection };
83729
83794
  const file3 = flagText({ args, name: "from-file" });
83730
- const text2 = file3 ? await readFile31(resolve14(context.cwd, file3), "utf8") : await context.readStdin();
83795
+ const text2 = file3 ? await readFile32(resolve14(context.cwd, file3), "utf8") : await context.readStdin();
83731
83796
  const lines = text2.split("\n").map((line) => line.trim()).filter(Boolean);
83732
83797
  if (lines.length !== 2) {
83733
83798
  throw new CliUsageError(
@@ -84308,7 +84373,7 @@ async function flags({ context, args }) {
84308
84373
  }
84309
84374
 
84310
84375
  // src/services/workspace-commands.service.ts
84311
- import { readFile as readFile32 } from "node:fs/promises";
84376
+ import { readFile as readFile33 } from "node:fs/promises";
84312
84377
  import { resolve as resolve16 } from "node:path";
84313
84378
  var ROLE_NAMES2 = {
84314
84379
  OWNER: "Owner",
@@ -84491,7 +84556,7 @@ var LOGO_USAGE = "Usage: laze workspace logo set <file.png|jpg|webp> | laze work
84491
84556
  async function readLogo({ context, file: file3 }) {
84492
84557
  let bytes;
84493
84558
  try {
84494
- bytes = new Uint8Array(await readFile32(resolve16(context.cwd, file3)));
84559
+ bytes = new Uint8Array(await readFile33(resolve16(context.cwd, file3)));
84495
84560
  } catch {
84496
84561
  throw new CliUsageError(`No file to read at ${file3}.`);
84497
84562
  }
@@ -85152,7 +85217,7 @@ async function runCli({
85152
85217
  // src/services/processes.service.ts
85153
85218
  import { execFile as execFile2, spawn as spawn4 } from "node:child_process";
85154
85219
  import { mkdirSync, openSync } from "node:fs";
85155
- import { readFile as readFile33, readlink } from "node:fs/promises";
85220
+ import { readFile as readFile34, readlink } from "node:fs/promises";
85156
85221
  import { dirname as dirname18 } from "node:path";
85157
85222
  import { promisify as promisify2 } from "node:util";
85158
85223
  var run3 = promisify2(execFile2);
@@ -85166,14 +85231,14 @@ function alive(pid) {
85166
85231
  }
85167
85232
  }
85168
85233
  async function argsOf(pid) {
85169
- const raw = await readFile33(`/proc/${pid}/cmdline`, "utf8").catch(() => void 0);
85234
+ const raw = await readFile34(`/proc/${pid}/cmdline`, "utf8").catch(() => void 0);
85170
85235
  if (raw) return raw.split("\0").filter(Boolean);
85171
85236
  const listed = await run3("ps", ["-o", "args=", "-p", String(pid)]).catch(() => void 0);
85172
85237
  const line = listed?.stdout.trim();
85173
85238
  return line ? line.split(/\s+/) : void 0;
85174
85239
  }
85175
85240
  async function parentOf(pid) {
85176
- const stat3 = await readFile33(`/proc/${pid}/stat`, "utf8").catch(() => void 0);
85241
+ const stat3 = await readFile34(`/proc/${pid}/stat`, "utf8").catch(() => void 0);
85177
85242
  const fromStat = stat3 ? Number(stat3.slice(stat3.lastIndexOf(")") + 2).split(" ")[1]) : NaN;
85178
85243
  if (fromStat > 0) return fromStat;
85179
85244
  const listed = await run3("ps", ["-o", "ppid=", "-p", String(pid)]).catch(() => void 0);