@lazehq/cli 0.1.57 → 0.1.59

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 +178 -97
  2. package/package.json +1 -1
package/dist/laze.mjs CHANGED
@@ -3440,7 +3440,7 @@ var require_stream = __commonJS({
3440
3440
  };
3441
3441
  duplex._final = function(callback) {
3442
3442
  if (ws.readyState === ws.CONNECTING) {
3443
- ws.once("open", function open3() {
3443
+ ws.once("open", function open4() {
3444
3444
  duplex._final(callback);
3445
3445
  });
3446
3446
  return;
@@ -3461,7 +3461,7 @@ var require_stream = __commonJS({
3461
3461
  };
3462
3462
  duplex._write = function(chunk, encoding, callback) {
3463
3463
  if (ws.readyState === ws.CONNECTING) {
3464
- ws.once("open", function open3() {
3464
+ ws.once("open", function open4() {
3465
3465
  duplex._write(chunk, encoding, callback);
3466
3466
  });
3467
3467
  return;
@@ -35661,7 +35661,8 @@ function cliEnvironment({
35661
35661
  } = {}) {
35662
35662
  return {
35663
35663
  configPath: env.LAZE_CLI_CONFIG || join(homedir(), ".laze", "config.json"),
35664
- // Claude Code names a subagent's commands `claude-code_<version>_agent`.
35664
+ // `claude-code_<version>_agent` may be a subagent; from 2.1.310 the session itself too, so
35665
+ // refuseInSubagent reads the transcripts before it refuses.
35665
35666
  subagent: /^claude-code_.+_agent$/.test(env.AI_AGENT ?? ""),
35666
35667
  profile: env.LAZE_PROFILE || void 0,
35667
35668
  url: env.LAZE_URL || void 0,
@@ -35881,7 +35882,7 @@ function flagText({
35881
35882
  }
35882
35883
 
35883
35884
  // src/rules/cli-version.rules.ts
35884
- var STAMPED = "0.1.57";
35885
+ var STAMPED = "0.1.59";
35885
35886
  function cliVersionOf({ stamped = STAMPED } = {}) {
35886
35887
  return stamped.startsWith("__") ? "dev" : stamped;
35887
35888
  }
@@ -65390,6 +65391,8 @@ var agentMigrationSchemaDefinition = external_exports.object({
65390
65391
  completedAt: external_exports.iso.datetime().nullable(),
65391
65392
  /** When the agent's machine last called Laze; null when it never did. */
65392
65393
  machineLastSeenAt: external_exports.iso.datetime().nullable(),
65394
+ /** When the agent was connected locally again after this; null while it runs in Laze. */
65395
+ reversedAt: external_exports.iso.datetime().nullable(),
65393
65396
  /** The agent's DM, where the request and the notice are. */
65394
65397
  channelId: external_exports.string().nullable(),
65395
65398
  /** The notice's place in the DM, once done. */
@@ -68605,10 +68608,50 @@ import { mkdir as mkdir4, readFile as readFile5, rm, writeFile as writeFile4 } f
68605
68608
  import { dirname as dirname4, join as join5 } from "node:path";
68606
68609
 
68607
68610
  // src/services/harness-session.service.ts
68608
- import { mkdir as mkdir3, readdir, readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
68609
- import { hostname as hostname3 } from "node:os";
68611
+ import { mkdir as mkdir3, open as open2, readdir, readFile as readFile3, stat, writeFile as writeFile3 } from "node:fs/promises";
68612
+ import { homedir as homedir2, hostname as hostname3 } from "node:os";
68610
68613
  import { dirname as dirname3, join as join3 } from "node:path";
68611
68614
 
68615
+ // src/rules/claude-subagent.rules.ts
68616
+ function lastCallAtOf({ text: text2, command }) {
68617
+ const lines2 = text2.split("\n");
68618
+ for (let index = lines2.length - 1; index >= 0; index -= 1) {
68619
+ const line = lines2[index]?.trim();
68620
+ if (!line?.startsWith("{")) continue;
68621
+ let entry;
68622
+ try {
68623
+ entry = JSON.parse(line);
68624
+ } catch {
68625
+ continue;
68626
+ }
68627
+ const at = callAtOf({ entry, command });
68628
+ if (at !== null) return at;
68629
+ }
68630
+ return null;
68631
+ }
68632
+ function callAtOf({ entry, command }) {
68633
+ const { type, timestamp, message: message2 } = entry ?? {};
68634
+ if (type !== "assistant" || typeof timestamp !== "string") return null;
68635
+ const content = Array.isArray(message2?.content) ? message2.content : [];
68636
+ const runs = content.some((part) => {
68637
+ const { type: kind2, input: input2 } = part ?? {};
68638
+ return kind2 === "tool_use" && typeof input2?.command === "string" && command.test(input2.command);
68639
+ });
68640
+ if (!runs) return null;
68641
+ try {
68642
+ return Temporal3.Instant.from(timestamp).epochMilliseconds;
68643
+ } catch {
68644
+ return null;
68645
+ }
68646
+ }
68647
+ function newestIsSubagent({
68648
+ session,
68649
+ subagents
68650
+ }) {
68651
+ const newest = Math.max(...subagents.map((at) => at ?? Number.NEGATIVE_INFINITY));
68652
+ return Number.isFinite(newest) && newest >= (session ?? Number.NEGATIVE_INFINITY);
68653
+ }
68654
+
68612
68655
  // src/rules/rush-host.rules.ts
68613
68656
  function rushSessionOf({
68614
68657
  parentArgs
@@ -68897,8 +68940,63 @@ async function liveElsewhere({
68897
68940
  }
68898
68941
  return false;
68899
68942
  }
68900
- function refuseInSubagent({ context, args }) {
68943
+ async function claudeTranscriptOf({
68944
+ context,
68945
+ sessionId
68946
+ }) {
68947
+ const inherited = context.environment.inherited;
68948
+ const root = join3(
68949
+ inherited.CLAUDE_CONFIG_DIR || join3(inherited.HOME || homedir2(), ".claude"),
68950
+ "projects"
68951
+ );
68952
+ const folders = await readdir(root).catch(() => []);
68953
+ const found = await Promise.all(
68954
+ folders.map(async (folder) => {
68955
+ const path = join3(root, folder, `${sessionId}.jsonl`);
68956
+ return stat(path).then(
68957
+ (info) => info.isFile() ? [{ path, at: info.mtimeMs }] : [],
68958
+ () => []
68959
+ );
68960
+ })
68961
+ );
68962
+ return { root, path: found.flat().toSorted((a, b) => b.at - a.at)[0]?.path };
68963
+ }
68964
+ var TAIL_BYTES = 512 * 1024;
68965
+ async function tailOf({ path }) {
68966
+ const handle = await open2(path, "r").catch(() => void 0);
68967
+ if (!handle) return "";
68968
+ try {
68969
+ const { size } = await handle.stat();
68970
+ const length = Math.min(size, TAIL_BYTES);
68971
+ const buffer = Buffer.alloc(length);
68972
+ await handle.read({ buffer, position: size - length, length });
68973
+ return buffer.toString("utf8");
68974
+ } finally {
68975
+ await handle.close();
68976
+ }
68977
+ }
68978
+ async function runsInSubagent({ context, command }) {
68979
+ const sessionId = context.environment.inherited.CLAUDE_CODE_SESSION_ID ?? "";
68980
+ if (!sessionId) return false;
68981
+ const { path } = await claudeTranscriptOf({ context, sessionId });
68982
+ if (!path) return false;
68983
+ const folder = join3(dirname3(path), sessionId, "subagents");
68984
+ const files2 = await readdir(folder).catch(() => []);
68985
+ const subagents = await Promise.all(
68986
+ files2.filter((file3) => file3.endsWith(".jsonl")).map(
68987
+ async (file3) => lastCallAtOf({ text: await tailOf({ path: join3(folder, file3) }), command })
68988
+ )
68989
+ );
68990
+ const session = lastCallAtOf({ text: await tailOf({ path }), command });
68991
+ return newestIsSubagent({ session, subagents });
68992
+ }
68993
+ async function refuseInSubagent({
68994
+ context,
68995
+ args,
68996
+ command
68997
+ }) {
68901
68998
  if (!context.environment.subagent || flagText({ args, name: "session" })) return;
68999
+ if (!await runsInSubagent({ context, command })) return;
68902
69000
  throw new CliUsageError(
68903
69001
  "This runs inside a Claude Code subagent, which shares its parent's session: it would take that session. Run it in the session itself, or pass --session <id>."
68904
69002
  );
@@ -69557,20 +69655,24 @@ function waitSecondsOf({ args }) {
69557
69655
  async function refuseOtherSessionsInbox({
69558
69656
  context,
69559
69657
  args,
69560
- name: name3
69658
+ name: name3,
69659
+ client
69561
69660
  }) {
69562
69661
  if (args.flags.take) return;
69563
69662
  const bound = Object.entries((await context.store.read()).sessions ?? {}).filter(([, profile]) => profile === name3).map(([key]) => key);
69564
69663
  if (bound.length === 0) return;
69565
69664
  const here = await currentSessionOf({ context, args });
69566
69665
  if (here && bound.includes(sessionKeyOf({ session: here }))) return;
69666
+ await client.get("/api/agents/me").catch((error62) => {
69667
+ if (migratedNoticeOf(error62)) throw error62;
69668
+ });
69567
69669
  throw new CliUsageError(
69568
69670
  `${name3} is bound to the session ${bound.join(", ")}, and reading its inbox here would take those messages away from it. Read the channel with \`laze history <channel>\` instead, or pass --take to take them anyway.`
69569
69671
  );
69570
69672
  }
69571
69673
  async function inbox({ context, args }) {
69572
69674
  const { client, name: name3, profile } = await signedIn({ context, args });
69573
- if (profile.kind === "agent") await refuseOtherSessionsInbox({ context, args, name: name3 });
69675
+ if (profile.kind === "agent") await refuseOtherSessionsInbox({ context, args, name: name3, client });
69574
69676
  const waitSeconds = waitSecondsOf({ args });
69575
69677
  const messages = await receiveMessages({ context, client, waitSeconds });
69576
69678
  if (profile.kind === "agent" && context.environment.harness === "claude-code") {
@@ -69782,12 +69884,12 @@ function rolloutEventOf({
69782
69884
  }
69783
69885
 
69784
69886
  // src/services/connect-delivery.service.ts
69785
- import { mkdir as mkdir8, readFile as readFile9, rename as rename3, rm as rm2, stat as stat2, writeFile as writeFile7 } from "node:fs/promises";
69786
- import { homedir as homedir2, hostname as hostname4 } from "node:os";
69887
+ import { mkdir as mkdir8, readFile as readFile9, rename as rename3, rm as rm2, stat as stat3, writeFile as writeFile7 } from "node:fs/promises";
69888
+ import { homedir as homedir3, hostname as hostname4 } from "node:os";
69787
69889
  import { dirname as dirname9, join as join11 } from "node:path";
69788
69890
 
69789
69891
  // src/services/codex-turn-watch.service.ts
69790
- import { open as open2, readdir as readdir2 } from "node:fs/promises";
69892
+ import { open as open3, readdir as readdir2 } from "node:fs/promises";
69791
69893
  import { basename as basename3, join as join6 } from "node:path";
69792
69894
  var READ_MS = 1500;
69793
69895
  var KEEP_WORKING_MS = 3e4;
@@ -69806,7 +69908,7 @@ function rolloutPathOf({ delivery }) {
69806
69908
  return codexRolloutPathOf({ codexHome: delivery.codexHome, threadId: delivery.threadId });
69807
69909
  }
69808
69910
  async function readFrom({ path, offset }) {
69809
- const handle = await open2(path, "r");
69911
+ const handle = await open3(path, "r");
69810
69912
  try {
69811
69913
  const { size } = await handle.stat();
69812
69914
  if (size <= offset) return { text: "", size };
@@ -70217,18 +70319,18 @@ var RelaySession = class {
70217
70319
  if (!envelope) return;
70218
70320
  const { line, payload } = envelope;
70219
70321
  if (envelope.kind === "open") return this.dial(relay2, line);
70220
- const open3 = this.#lines.get(line);
70221
- if (!open3) return;
70322
+ const open4 = this.#lines.get(line);
70323
+ if (!open4) return;
70222
70324
  if (envelope.kind === "close") {
70223
70325
  this.#lines.delete(line);
70224
- open3.socket.close(1e3);
70326
+ open4.socket.close(1e3);
70225
70327
  return;
70226
70328
  }
70227
70329
  if (envelope.kind !== "text" && envelope.kind !== "binary") return;
70228
70330
  const frame = { data: Buffer.from(payload), binary: envelope.kind === "binary" };
70229
- if (open3.socket.readyState === wrapper_default.OPEN) {
70230
- open3.socket.send(frame.data, { binary: frame.binary });
70231
- } else open3.waiting.push(frame);
70331
+ if (open4.socket.readyState === wrapper_default.OPEN) {
70332
+ open4.socket.send(frame.data, { binary: frame.binary });
70333
+ } else open4.waiting.push(frame);
70232
70334
  }
70233
70335
  /** Dials the gateway for a line; its frames go back to Laze as they came. */
70234
70336
  dial(relay2, line) {
@@ -70322,7 +70424,7 @@ var RelayLoops = class _RelayLoops {
70322
70424
  };
70323
70425
 
70324
70426
  // src/services/rush-listeners.service.ts
70325
- import { readFile as readFile8, readdir as readdir3, stat } from "node:fs/promises";
70427
+ import { readFile as readFile8, readdir as readdir3, stat as stat2 } from "node:fs/promises";
70326
70428
  import { dirname as dirname7, join as join9 } from "node:path";
70327
70429
 
70328
70430
  // src/services/rush-host.service.ts
@@ -70390,7 +70492,7 @@ async function notesOf({ context }) {
70390
70492
  files2.map(async (file3) => {
70391
70493
  const pid = Number(file3.replace(/\.json$/, ""));
70392
70494
  const note = await jsonOf(join9(folder, file3));
70393
- const at = await stat(join9(folder, file3)).then(
70495
+ const at = await stat2(join9(folder, file3)).then(
70394
70496
  (info) => info.mtimeMs,
70395
70497
  () => 0
70396
70498
  );
@@ -70604,7 +70706,7 @@ var CLI_CHANGED_EXIT = 75;
70604
70706
  async function cliStampOf({ context }) {
70605
70707
  const file3 = context.program.at(-1);
70606
70708
  if (!file3) return "";
70607
- return stat2(file3).then(
70709
+ return stat3(file3).then(
70608
70710
  (info) => `${info.mtimeMs}:${info.size}`,
70609
70711
  () => ""
70610
70712
  );
@@ -70647,7 +70749,7 @@ async function takeRound({
70647
70749
  const session = {
70648
70750
  harness: "codex",
70649
70751
  sessionId: delivery.threadId,
70650
- folder: displayFolderOf({ folder: delivery.cwd, home: homedir2() }),
70752
+ folder: displayFolderOf({ folder: delivery.cwd, home: homedir3() }),
70651
70753
  host: hostname4()
70652
70754
  };
70653
70755
  try {
@@ -71305,13 +71407,13 @@ async function monitorServes({
71305
71407
 
71306
71408
  // src/services/codex-link.service.ts
71307
71409
  import { createReadStream } from "node:fs";
71308
- import { readdir as readdir5, rm as rm6, stat as stat4 } from "node:fs/promises";
71410
+ import { readdir as readdir5, rm as rm6, stat as stat5 } from "node:fs/promises";
71309
71411
  import { join as join14, resolve as resolve3 } from "node:path";
71310
71412
  import { createInterface as createInterface2 } from "node:readline";
71311
71413
 
71312
71414
  // src/services/codex-adopt.service.ts
71313
71415
  import { spawn as spawn2 } from "node:child_process";
71314
- import { mkdir as mkdir11, readdir as readdir4, readFile as readFile11, rm as rm5, stat as stat3, writeFile as writeFile10 } from "node:fs/promises";
71416
+ import { mkdir as mkdir11, readdir as readdir4, readFile as readFile11, rm as rm5, stat as stat4, writeFile as writeFile10 } from "node:fs/promises";
71315
71417
  import { dirname as dirname12, join as join13 } from "node:path";
71316
71418
  import { createInterface } from "node:readline";
71317
71419
 
@@ -71436,7 +71538,7 @@ async function newestThreadId({ codexHome }) {
71436
71538
  const files2 = await readdir4(root, { recursive: true }).catch(() => []);
71437
71539
  const rollouts = files2.filter((file3) => /rollout-.*\.jsonl$/.test(file3));
71438
71540
  const dated = await Promise.all(
71439
- rollouts.map(async (file3) => ({ file: file3, at: (await stat3(join13(root, file3))).mtimeMs }))
71541
+ rollouts.map(async (file3) => ({ file: file3, at: (await stat4(join13(root, file3))).mtimeMs }))
71440
71542
  );
71441
71543
  const newest = dated.toSorted((a, b) => b.at - a.at)[0]?.file ?? "";
71442
71544
  const id2 = /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/.exec(newest);
@@ -71711,7 +71813,7 @@ async function newestThreadIn({
71711
71813
  const dated = await Promise.all(
71712
71814
  rollouts.map(async (file3) => ({
71713
71815
  path: join14(root, file3),
71714
- at: await stat4(join14(root, file3)).then(
71816
+ at: await stat5(join14(root, file3)).then(
71715
71817
  (info) => info.mtimeMs,
71716
71818
  () => 0
71717
71819
  )
@@ -71782,7 +71884,7 @@ async function linkCodexSession({
71782
71884
 
71783
71885
  // src/services/laze-plugin.service.ts
71784
71886
  import { mkdir as mkdir12, readFile as readFile12, writeFile as writeFile11 } from "node:fs/promises";
71785
- import { homedir as homedir3 } from "node:os";
71887
+ import { homedir as homedir4 } from "node:os";
71786
71888
  import { dirname as dirname13, join as join15 } from "node:path";
71787
71889
 
71788
71890
  // src/rules/laze-plugin.rules.ts
@@ -71990,7 +72092,7 @@ async function registerWithClaude({ context, folder }) {
71990
72092
  var RUN_FILES = ["hooks/hooks.json", "monitors/monitors.json"];
71991
72093
  async function cachedPluginOf({ context }) {
71992
72094
  const inherited = context.environment.inherited;
71993
- const home = inherited.HOME || homedir3();
72095
+ const home = inherited.HOME || homedir4();
71994
72096
  const claude = inherited.CLAUDE_CONFIG_DIR || join15(home, ".claude");
71995
72097
  const listed = await readFile12(join15(claude, "plugins", "installed_plugins.json"), "utf8").then(
71996
72098
  (text2) => JSON.parse(text2),
@@ -72381,7 +72483,7 @@ function sandboxed({ context, error: error62 }) {
72381
72483
  async function linkAgent({ context, args }) {
72382
72484
  const token2 = flagText({ args, name: "token" });
72383
72485
  if (!token2) throw new CliUsageError("Usage: laze agent link --token <token>");
72384
- refuseInSubagent({ context, args });
72486
+ await refuseInSubagent({ context, args, command: /\bagent\s+link\b/ });
72385
72487
  const url2 = serverUrlOf({ context, args });
72386
72488
  const { harness, pid } = await harnessOf2({ context, args });
72387
72489
  const client = LazeClient.create({ baseUrl: url2, fetcher: context.fetcher });
@@ -73340,8 +73442,7 @@ async function setAgentPool({
73340
73442
  }
73341
73443
 
73342
73444
  // src/services/agent-migrate-commands.service.ts
73343
- import { readdir as readdir6, readFile as readFile16, stat as stat5 } from "node:fs/promises";
73344
- import { homedir as homedir4 } from "node:os";
73445
+ import { readFile as readFile16 } from "node:fs/promises";
73345
73446
  import { basename as basename4, join as join17 } from "node:path";
73346
73447
 
73347
73448
  // src/rules/migration-upload.rules.ts
@@ -73484,11 +73585,12 @@ async function migrate({ context, args }) {
73484
73585
  function statusLines(migration) {
73485
73586
  const removed = migration.removed;
73486
73587
  return [
73487
- `${migration.agentName}: ${migration.status}`,
73588
+ `${migration.agentName}: ${migration.reversedAt ? "connected locally again" : migration.status}`,
73488
73589
  `From ${HARNESS_NAMES3[migration.source] ?? migration.source} to ${targetOf(migration)}`,
73489
73590
  `Session: ${migration.mode === "resume" ? "resumed" : "started fresh from a summary"}`,
73490
73591
  `Asked: ${migration.requestedAt}`,
73491
73592
  ...migration.completedAt ? [`Done: ${migration.completedAt}`] : [],
73593
+ ...migration.reversedAt ? [`Connected locally again: ${migration.reversedAt}`] : [],
73492
73594
  ...removed ? [
73493
73595
  `Secrets removed: ${removed.local} on the machine, ${removed.vault} vault values, ${removed.patterns} key-shaped texts`
73494
73596
  ] : [],
@@ -73517,27 +73619,6 @@ async function cancelMigration({ context, args }) {
73517
73619
  context.out(`Cancelled ${migration.agentName}'s migration; it stays connected on its machine.
73518
73620
  `);
73519
73621
  }
73520
- async function claudeTranscriptOf({
73521
- context,
73522
- sessionId
73523
- }) {
73524
- const inherited = context.environment.inherited;
73525
- const root = join17(
73526
- inherited.CLAUDE_CONFIG_DIR || join17(inherited.HOME || homedir4(), ".claude"),
73527
- "projects"
73528
- );
73529
- const folders = await readdir6(root).catch(() => []);
73530
- const found = await Promise.all(
73531
- folders.map(async (folder) => {
73532
- const path = join17(root, folder, `${sessionId}.jsonl`);
73533
- return stat5(path).then(
73534
- (info) => info.isFile() ? [{ path, at: info.mtimeMs }] : [],
73535
- () => []
73536
- );
73537
- })
73538
- );
73539
- return { root, path: found.flat().toSorted((a, b) => b.at - a.at)[0]?.path };
73540
- }
73541
73622
  async function transcriptOf({ context, ticket }) {
73542
73623
  const inherited = context.environment.inherited;
73543
73624
  const own2 = ticket.source === "codex" ? inherited.CODEX_THREAD_ID : inherited.CLAUDE_CODE_SESSION_ID;
@@ -73677,7 +73758,7 @@ async function bindAgentSession({
73677
73758
  context,
73678
73759
  args
73679
73760
  }) {
73680
- refuseInSubagent({ context, args });
73761
+ await refuseInSubagent({ context, args, command: /\bagent\s+bind\b/ });
73681
73762
  const session = await currentSessionOf({ context, args });
73682
73763
  if (!session) throw new CliUsageError(NO_SESSION);
73683
73764
  const key = sessionKeyOf({ session });
@@ -73823,7 +73904,7 @@ async function requestAgent({ context, args }) {
73823
73904
  }
73824
73905
 
73825
73906
  // src/services/app-commands.service.ts
73826
- import { mkdir as mkdir16, readdir as readdir7, readFile as readFile18, writeFile as writeFile16 } from "node:fs/promises";
73907
+ import { mkdir as mkdir16, readdir as readdir6, readFile as readFile18, writeFile as writeFile16 } from "node:fs/promises";
73827
73908
  import { dirname as dirname16, join as join20, relative as relative3, resolve as resolve6, sep as sep3 } from "node:path";
73828
73909
 
73829
73910
  // ../../modules/app/contract/src/app.connections.ts
@@ -76260,16 +76341,16 @@ function print({
76260
76341
  async function appConnections({
76261
76342
  context,
76262
76343
  args,
76263
- open: open3
76344
+ open: open4
76264
76345
  }) {
76265
- const { client, appId, name: name3 } = await open3();
76346
+ const { client, appId, name: name3 } = await open4();
76266
76347
  const listed = await client.post("/api/apps/connections", { appId });
76267
76348
  print({ context, args, value: listed, text: connectionsText({ name: name3, listed }) });
76268
76349
  }
76269
76350
  async function appConnection({
76270
76351
  context,
76271
76352
  args,
76272
- open: open3
76353
+ open: open4
76273
76354
  }) {
76274
76355
  const [, , verb, connection] = args.words;
76275
76356
  if (verb !== "allow" && verb !== "revoke" || !connection) {
@@ -76278,7 +76359,7 @@ async function appConnection({
76278
76359
  if (verb) throw new CliUsageError(USAGE2);
76279
76360
  return;
76280
76361
  }
76281
- const { client, appId, name: name3 } = await open3();
76362
+ const { client, appId, name: name3 } = await open4();
76282
76363
  const listed = await client.post(`/api/apps/connections/${verb}`, { appId, connection }).catch((error62) => {
76283
76364
  if (!(error62 instanceof LazeApiError) || error62.code !== "permission_denied") throw error62;
76284
76365
  throw new CliUsageError(
@@ -76307,40 +76388,40 @@ function appAndWord({ args, usage }) {
76307
76388
  if (!word3) throw new CliUsageError(usage);
76308
76389
  return { app: app2, word: word3 };
76309
76390
  }
76310
- var rename4 = async ({ context, args, open: open3 }) => {
76391
+ var rename4 = async ({ context, args, open: open4 }) => {
76311
76392
  const { app: app2, word: word3 } = appAndWord({ args, usage: "Usage: laze app rename [app] <new name>" });
76312
- const { client, appId, name: name3 } = await open3(app2);
76393
+ const { client, appId, name: name3 } = await open4(app2);
76313
76394
  const renamed = await client.post("/api/apps/rename", { appId, name: word3 });
76314
76395
  print2({ context, args, value: renamed, text: `${name3} is now called ${renamed.name}.
76315
76396
  ` });
76316
76397
  };
76317
- var archive = async ({ context, args, open: open3 }) => {
76318
- const { client, appId } = await open3(args.words[2]);
76398
+ var archive = async ({ context, args, open: open4 }) => {
76399
+ const { client, appId } = await open4(args.words[2]);
76319
76400
  const archived = await client.post("/api/apps/archive", { appId });
76320
76401
  const text2 = `Archived ${archived.name}: it serves nothing and keeps its versions and data. laze app unarchive brings it back.
76321
76402
  `;
76322
76403
  print2({ context, args, value: archived, text: text2 });
76323
76404
  };
76324
- var unarchive = async ({ context, args, open: open3 }) => {
76325
- const { client, appId } = await open3(args.words[2]);
76405
+ var unarchive = async ({ context, args, open: open4 }) => {
76406
+ const { client, appId } = await open4(args.words[2]);
76326
76407
  const back = await client.post("/api/apps/unarchive", { appId });
76327
76408
  const text2 = `${back.name} is back at the same addresses.
76328
76409
  `;
76329
76410
  print2({ context, args, value: back, text: text2 });
76330
76411
  };
76331
- var remove = async ({ context, args, open: open3 }) => {
76412
+ var remove = async ({ context, args, open: open4 }) => {
76332
76413
  const confirmName = flagText({ args, name: "confirm" });
76333
76414
  if (!confirmName) {
76334
76415
  throw new CliUsageError("Usage: laze app delete [app] --confirm <the app's name>");
76335
76416
  }
76336
- const { client, appId, name: name3 } = await open3(args.words[2]);
76417
+ const { client, appId, name: name3 } = await open4(args.words[2]);
76337
76418
  await client.post("/api/apps/delete", { appId, confirmName });
76338
76419
  const text2 = `Deleted ${name3}: it stopped serving and is gone from the workspace.
76339
76420
  `;
76340
76421
  print2({ context, args, value: { deleted: appId }, text: text2 });
76341
76422
  };
76342
- var revokeLease = async ({ context, args, open: open3 }) => {
76343
- const { client, appId, name: name3 } = await open3(args.words[2]);
76423
+ var revokeLease = async ({ context, args, open: open4 }) => {
76424
+ const { client, appId, name: name3 } = await open4(args.words[2]);
76344
76425
  const app2 = await client.post("/api/apps/publish/revoke-lease", { appId });
76345
76426
  const text2 = `${name3}'s builder asks for an approval again before its next public publish.
76346
76427
  `;
@@ -76368,18 +76449,18 @@ function backupsText({ name: name3, status: status9 }) {
76368
76449
  return `${name3}: ${replicating} ${window2}
76369
76450
  ${restores.join("")}`;
76370
76451
  }
76371
- var backups = async ({ context, args, open: open3 }) => {
76372
- const { client, appId, name: name3 } = await open3(args.words[2]);
76452
+ var backups = async ({ context, args, open: open4 }) => {
76453
+ const { client, appId, name: name3 } = await open4(args.words[2]);
76373
76454
  const status9 = await client.post("/api/apps/backups", { appId });
76374
76455
  print2({ context, args, value: status9, text: backupsText({ name: name3, status: status9 }) });
76375
76456
  };
76376
- var restore = async ({ context, args, open: open3 }) => {
76457
+ var restore = async ({ context, args, open: open4 }) => {
76377
76458
  const to = flagText({ args, name: "to" });
76378
76459
  const undo = flagText({ args, name: "undo" });
76379
76460
  if (Boolean(to) === Boolean(undo)) {
76380
76461
  throw new CliUsageError("Usage: laze app restore [app] --to <ISO time> | --undo <restore-id>");
76381
76462
  }
76382
- const { client, appId, name: name3 } = await open3(args.words[2]);
76463
+ const { client, appId, name: name3 } = await open4(args.words[2]);
76383
76464
  const done = await client.post("/api/apps/backups/restore", {
76384
76465
  appId,
76385
76466
  ...to ? { to } : { undo }
@@ -76405,16 +76486,16 @@ function usersText({ name: name3, users: users2 }) {
76405
76486
  return `${name3}'s app users:
76406
76487
  ${lines2.join("")}`;
76407
76488
  }
76408
- var users = async ({ context, args, open: open3 }) => {
76409
- const { client, appId, name: name3 } = await open3(args.words[2]);
76489
+ var users = async ({ context, args, open: open4 }) => {
76490
+ const { client, appId, name: name3 } = await open4(args.words[2]);
76410
76491
  const listed = await client.post("/api/apps/users", { appId });
76411
76492
  print2({ context, args, value: listed, text: usersText({ name: name3, users: listed }) });
76412
76493
  };
76413
76494
  function blocking(blocked) {
76414
- return async ({ context, args, open: open3 }) => {
76495
+ return async ({ context, args, open: open4 }) => {
76415
76496
  const verb = blocked ? "block-user" : "unblock-user";
76416
76497
  const { app: app2, word: word3 } = appAndWord({ args, usage: `Usage: laze app ${verb} [app] <user-id>` });
76417
- const { client, appId, name: name3 } = await open3(app2);
76498
+ const { client, appId, name: name3 } = await open4(app2);
76418
76499
  const listed = await client.post("/api/apps/users/block", {
76419
76500
  appId,
76420
76501
  userId: word3,
@@ -76423,9 +76504,9 @@ function blocking(blocked) {
76423
76504
  print2({ context, args, value: listed, text: usersText({ name: name3, users: listed }) });
76424
76505
  };
76425
76506
  }
76426
- var deleteUser = async ({ context, args, open: open3 }) => {
76507
+ var deleteUser = async ({ context, args, open: open4 }) => {
76427
76508
  const { app: app2, word: word3 } = appAndWord({ args, usage: "Usage: laze app delete-user [app] <user-id>" });
76428
- const { client, appId, name: name3 } = await open3(app2);
76509
+ const { client, appId, name: name3 } = await open4(app2);
76429
76510
  const gone = await client.post("/api/apps/users/delete", { appId, userId: word3 });
76430
76511
  const text2 = `Deleted ${gone.userId} from ${name3} with the ${gone.removedRecords.toString()} records they owned.
76431
76512
  `;
@@ -76498,10 +76579,10 @@ async function appPinCommand({
76498
76579
  context,
76499
76580
  args,
76500
76581
  verb,
76501
- open: open3
76582
+ open: open4
76502
76583
  }) {
76503
76584
  const channel = flagText({ args, name: "channel" });
76504
- const { client, appId, name: name3 } = await open3();
76585
+ const { client, appId, name: name3 } = await open4();
76505
76586
  const role2 = verb === "pin" ? pinRoleOf(args) : void 0;
76506
76587
  const listed = await client.post(`/api/apps/${verb}`, {
76507
76588
  appId,
@@ -76793,26 +76874,26 @@ function print4({
76793
76874
  context.out(args.flags.json ? `${JSON.stringify(value, null, 2)}
76794
76875
  ` : text2);
76795
76876
  }
76796
- async function add({ context, args, open: open3, word: word3 }) {
76877
+ async function add({ context, args, open: open4, word: word3 }) {
76797
76878
  const prompt = flagText({ args, name: "prompt" }).trim();
76798
76879
  if (!prompt) throw new CliUsageError("--prompt says what the agent does with the records");
76799
76880
  const body = { collection: word3, on: onOf(args), where: whereOf3(args), prompt };
76800
- const { client, appId, name: name3 } = await open3();
76881
+ const { client, appId, name: name3 } = await open4();
76801
76882
  const trigger = await client.post("/api/apps/triggers/add", { appId, ...body });
76802
76883
  const text2 = `Added a trigger on ${name3}:
76803
76884
  ${triggerLine(trigger)}Matching changes to ${word3} records wake ${trigger.agentName} in ${trigger.channelName}.
76804
76885
  `;
76805
76886
  print4({ context, args, value: trigger, text: text2 });
76806
76887
  }
76807
- async function list({ context, args, open: open3 }) {
76808
- const { client, appId, name: name3 } = await open3();
76888
+ async function list({ context, args, open: open4 }) {
76889
+ const { client, appId, name: name3 } = await open4();
76809
76890
  const listed = await client.post("/api/apps/triggers", { appId });
76810
76891
  const text2 = listed.triggers.length === 0 ? `${name3} has no triggers. laze app trigger add <collection> adds one.
76811
76892
  ` : listed.triggers.map(triggerLine).join("");
76812
76893
  print4({ context, args, value: listed, text: text2 });
76813
76894
  }
76814
- async function setPaused({ context, args, open: open3, word: word3, paused }) {
76815
- const { client, appId } = await open3();
76895
+ async function setPaused({ context, args, open: open4, word: word3, paused }) {
76896
+ const { client, appId } = await open4();
76816
76897
  const trigger = await client.post("/api/apps/triggers/pause", {
76817
76898
  appId,
76818
76899
  triggerId: word3,
@@ -76820,8 +76901,8 @@ async function setPaused({ context, args, open: open3, word: word3, paused }) {
76820
76901
  });
76821
76902
  print4({ context, args, value: trigger, text: triggerLine(trigger) });
76822
76903
  }
76823
- async function remove2({ context, args, open: open3, word: word3 }) {
76824
- const { client, appId } = await open3();
76904
+ async function remove2({ context, args, open: open4, word: word3 }) {
76905
+ const { client, appId } = await open4();
76825
76906
  await client.post("/api/apps/triggers/remove", { appId, triggerId: word3 });
76826
76907
  print4({ context, args, value: { removed: word3 }, text: `Removed trigger ${word3}.
76827
76908
  ` });
@@ -76829,14 +76910,14 @@ async function remove2({ context, args, open: open3, word: word3 }) {
76829
76910
  async function appTrigger({
76830
76911
  context,
76831
76912
  args,
76832
- open: open3
76913
+ open: open4
76833
76914
  }) {
76834
76915
  const [, , verb, word3] = args.words;
76835
- if (verb === "list") return list({ context, args, open: open3 });
76916
+ if (verb === "list") return list({ context, args, open: open4 });
76836
76917
  const known = verb === "add" || verb === "pause" || verb === "resume" || verb === "remove";
76837
76918
  if (known && !word3) throw new CliUsageError(USAGE4);
76838
76919
  if (known && word3) {
76839
- const run4 = { context, args, open: open3, word: word3 };
76920
+ const run4 = { context, args, open: open4, word: word3 };
76840
76921
  if (verb === "add") return add(run4);
76841
76922
  if (verb === "remove") return remove2(run4);
76842
76923
  return setPaused({ ...run4, paused: verb === "pause" });
@@ -76957,7 +77038,7 @@ async function listFiles(folder) {
76957
77038
  const pending2 = [folder];
76958
77039
  while (pending2.length > 0 && found.length <= MAX_FILES) {
76959
77040
  const current2 = pending2.pop() ?? folder;
76960
- for (const entry of await readdir7(current2, { withFileTypes: true })) {
77041
+ for (const entry of await readdir6(current2, { withFileTypes: true })) {
76961
77042
  const path = join20(current2, entry.name);
76962
77043
  const rel = relative3(folder, path).split(sep3).join("/");
76963
77044
  if (isSkippedPath({ path: rel })) continue;
@@ -77173,7 +77254,7 @@ async function folderClaim({
77173
77254
  folder,
77174
77255
  appId
77175
77256
  }) {
77176
- const entries = await readdir7(folder).catch(() => []);
77257
+ const entries = await readdir6(folder).catch(() => []);
77177
77258
  if (entries.length === 0) return "empty";
77178
77259
  const manifest = await readManifest(folder).catch(() => void 0);
77179
77260
  if (!manifest) return "other-files";
@@ -89232,7 +89313,7 @@ async function schedule({ context, args }) {
89232
89313
  }
89233
89314
 
89234
89315
  // src/services/skill-commands.service.ts
89235
- import { readdir as readdir8, readFile as readFile38 } from "node:fs/promises";
89316
+ import { readdir as readdir7, readFile as readFile38 } from "node:fs/promises";
89236
89317
  import { join as join26, relative as relative6, resolve as resolve16 } from "node:path";
89237
89318
  var USAGE15 = `Usage:
89238
89319
  laze skill list [--agent <agentId>]
@@ -89250,7 +89331,7 @@ var USAGE15 = `Usage:
89250
89331
  --agent names the agent with a person's key; an agent's key works on its own skills.
89251
89332
  With a person's key, list without --agent shows every agent's skills.`;
89252
89333
  async function folderFiles({ root }) {
89253
- const entries = await readdir8(root, { recursive: true, withFileTypes: true });
89334
+ const entries = await readdir7(root, { recursive: true, withFileTypes: true });
89254
89335
  const files2 = [];
89255
89336
  for (const entry of entries) {
89256
89337
  if (!entry.isFile()) continue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lazehq/cli",
3
- "version": "0.1.57",
3
+ "version": "0.1.59",
4
4
  "description": "The Laze command line: sign in, read and post in chat, and connect your own Claude Code or Codex session as an agent.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",