@alook/daemon 0.1.46 → 0.1.48

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 (3) hide show
  1. package/dist/cli/index.js +488 -354
  2. package/dist/index.js +436 -318
  3. package/package.json +1 -1
package/dist/cli/index.js CHANGED
@@ -22343,8 +22343,8 @@ var MAX_PROFILE_ABOUT_LENGTH = 1000;
22343
22343
  var MAX_MESSAGE_CONTENT_LENGTH = 4000;
22344
22344
  var MAX_ATTACHMENTS_PER_MESSAGE = 10;
22345
22345
  var MAX_ATTACHMENT_SIZE_BYTES = 25 * 1024 * 1024;
22346
- var MAX_ATTACHMENT_THUMBNAIL_EDGE_PX = 1024;
22347
- var MAX_ATTACHMENT_THUMBNAIL_SIZE_BYTES = 512 * 1024;
22346
+ var MAX_ATTACHMENT_THUMBNAIL_EDGE_PX = 720;
22347
+ var MAX_ATTACHMENT_THUMBNAIL_SIZE_BYTES = 256 * 1024;
22348
22348
  var MAX_SERVER_ICON_SIZE_BYTES = 5 * 1024 * 1024;
22349
22349
  var ALLOWED_ICON_MIME_TYPES = [
22350
22350
  "image/png",
@@ -23492,6 +23492,7 @@ __export(exports_community_schema, {
23492
23492
  communityMessageTag: () => communityMessageTag,
23493
23493
  communityMessageSeq: () => communityMessageSeq,
23494
23494
  communityMessageMark: () => communityMessageMark,
23495
+ communityMessageAttachment: () => communityMessageAttachment,
23495
23496
  communityMessage: () => communityMessage,
23496
23497
  communityMention: () => communityMention,
23497
23498
  communityFriendship: () => communityFriendship,
@@ -23667,11 +23668,7 @@ var communityReaction = sqliteTable("community_reaction", {
23667
23668
  ]);
23668
23669
  var communityAttachment = sqliteTable("community_attachment", {
23669
23670
  id: text("id").primaryKey().$defaultFn(() => nanoid3()),
23670
- messageId: text("message_id").references(() => communityMessage.id, {
23671
- onDelete: "cascade"
23672
- }),
23673
23671
  uploaderId: text("uploader_id").notNull(),
23674
- targetId: text("target_id").notNull(),
23675
23672
  r2Key: text("r2_key").notNull(),
23676
23673
  thumbnailR2Key: text("thumbnail_r2_key"),
23677
23674
  filename: text("filename").notNull(),
@@ -23679,10 +23676,20 @@ var communityAttachment = sqliteTable("community_attachment", {
23679
23676
  size: integer2("size"),
23680
23677
  width: integer2("width"),
23681
23678
  height: integer2("height"),
23682
- position: integer2("position"),
23683
23679
  createdAt: text("created_at").notNull().$defaultFn(() => new Date().toISOString())
23684
23680
  }, (t) => [
23685
- index("idx_attachment_message").on(t.messageId, t.position)
23681
+ index("idx_attachment_uploader").on(t.uploaderId),
23682
+ index("idx_attachment_r2_key").on(t.r2Key),
23683
+ index("idx_attachment_thumbnail_r2_key").on(t.thumbnailR2Key)
23684
+ ]);
23685
+ var communityMessageAttachment = sqliteTable("community_message_attachment", {
23686
+ messageId: text("message_id").notNull().references(() => communityMessage.id, { onDelete: "cascade" }),
23687
+ attachmentId: text("attachment_id").notNull().references(() => communityAttachment.id, { onDelete: "restrict" }),
23688
+ position: integer2("position").notNull()
23689
+ }, (t) => [
23690
+ primaryKey({ columns: [t.messageId, t.attachmentId] }),
23691
+ unique("uq_message_attachment_position").on(t.messageId, t.position),
23692
+ index("idx_message_attachment_file").on(t.attachmentId, t.messageId)
23686
23693
  ]);
23687
23694
  var communityPin = sqliteTable("community_pin", {
23688
23695
  id: text("id").primaryKey().$defaultFn(() => nanoid3()),
@@ -23804,6 +23811,41 @@ var communityMessageTag = sqliteTable("community_message_tag", {
23804
23811
  index("idx_message_tag_tag").on(t.tag, t.messageId)
23805
23812
  ]);
23806
23813
 
23814
+ // ../shared/src/db/queries/_chunk.ts
23815
+ var D1_MAX_BIND_PARAMS = 100;
23816
+ function maxInParams(fixedParams) {
23817
+ if (!Number.isInteger(fixedParams) || fixedParams < 0) {
23818
+ throw new Error("fixed params must be a non-negative integer");
23819
+ }
23820
+ if (fixedParams >= D1_MAX_BIND_PARAMS) {
23821
+ throw new Error("fixed params must leave room for at least one IN parameter");
23822
+ }
23823
+ return D1_MAX_BIND_PARAMS - fixedParams;
23824
+ }
23825
+ function maxRowsPerInsert(paramsPerRow) {
23826
+ if (paramsPerRow < 1)
23827
+ throw new Error("paramsPerRow must be >= 1");
23828
+ return Math.floor(D1_MAX_BIND_PARAMS / paramsPerRow);
23829
+ }
23830
+
23831
+ // ../shared/src/db/queries/community/channel.ts
23832
+ var CHANNEL_COLUMNS = {
23833
+ id: communityChannel.id,
23834
+ serverId: communityChannel.serverId,
23835
+ categoryId: communityChannel.categoryId,
23836
+ name: communityChannel.name,
23837
+ type: communityChannel.type,
23838
+ topic: communityChannel.topic,
23839
+ position: communityChannel.position,
23840
+ parentChannelId: communityChannel.parentChannelId,
23841
+ creatorId: communityChannel.creatorId,
23842
+ messageCount: communityChannel.messageCount,
23843
+ archived: communityChannel.archived,
23844
+ parentMessageId: communityChannel.parentMessageId,
23845
+ lastMessageAt: communityChannel.lastMessageAt,
23846
+ createdAt: communityChannel.createdAt
23847
+ };
23848
+
23807
23849
  // ../shared/src/logger.ts
23808
23850
  var LEVELS = {
23809
23851
  debug: 0,
@@ -23884,23 +23926,6 @@ function createLogger(opts) {
23884
23926
  return new Logger(opts);
23885
23927
  }
23886
23928
 
23887
- // ../shared/src/db/queries/_chunk.ts
23888
- var D1_MAX_BIND_PARAMS = 100;
23889
- function maxInParams(fixedParams) {
23890
- if (!Number.isInteger(fixedParams) || fixedParams < 0) {
23891
- throw new Error("fixed params must be a non-negative integer");
23892
- }
23893
- if (fixedParams >= D1_MAX_BIND_PARAMS) {
23894
- throw new Error("fixed params must leave room for at least one IN parameter");
23895
- }
23896
- return D1_MAX_BIND_PARAMS - fixedParams;
23897
- }
23898
- function maxRowsPerInsert(paramsPerRow) {
23899
- if (paramsPerRow < 1)
23900
- throw new Error("paramsPerRow must be >= 1");
23901
- return Math.floor(D1_MAX_BIND_PARAMS / paramsPerRow);
23902
- }
23903
-
23904
23929
  // ../shared/src/db/queries/community/message.ts
23905
23930
  var log = createLogger({ service: "community-queries" });
23906
23931
  var messageProjection = {
@@ -23999,24 +24024,6 @@ var userProductPlan = sqliteTable("user_product_plan", {
23999
24024
  updatedAt: text("updated_at").notNull().$defaultFn(() => new Date().toISOString())
24000
24025
  }, (t) => [index("idx_user_product_plan_plan").on(t.planId)]);
24001
24026
 
24002
- // ../shared/src/db/queries/community/channel.ts
24003
- var CHANNEL_COLUMNS = {
24004
- id: communityChannel.id,
24005
- serverId: communityChannel.serverId,
24006
- categoryId: communityChannel.categoryId,
24007
- name: communityChannel.name,
24008
- type: communityChannel.type,
24009
- topic: communityChannel.topic,
24010
- position: communityChannel.position,
24011
- parentChannelId: communityChannel.parentChannelId,
24012
- creatorId: communityChannel.creatorId,
24013
- messageCount: communityChannel.messageCount,
24014
- archived: communityChannel.archived,
24015
- parentMessageId: communityChannel.parentMessageId,
24016
- lastMessageAt: communityChannel.lastMessageAt,
24017
- createdAt: communityChannel.createdAt
24018
- };
24019
-
24020
24027
  // ../shared/src/db/queries/community/thread.ts
24021
24028
  var NOTIFY_CONFLICT_TARGET = [
24022
24029
  communityChannelMember.channelId,
@@ -25170,7 +25177,8 @@ function createProxyServerApi(config2) {
25170
25177
  form.append("width", String(req.width));
25171
25178
  if (req.height !== undefined)
25172
25179
  form.append("height", String(req.height));
25173
- const url2 = `${base}/api/community/channels/${REF_PLACEHOLDER_ID}/attachments?target=${encodeURIComponent(req.target)}`;
25180
+ const query = req.target === undefined ? "" : `?target=${encodeURIComponent(req.target)}`;
25181
+ const url2 = `${base}/api/community/channels/${REF_PLACEHOLDER_ID}/attachments${query}`;
25174
25182
  const res = await fetchImpl(url2, {
25175
25183
  method: "POST",
25176
25184
  headers: { authorization: `Bearer ${config2.voucher}` },
@@ -25511,13 +25519,13 @@ function createProxyServerApi(config2) {
25511
25519
 
25512
25520
  // src/cli/daemonStart.ts
25513
25521
  import * as fs12 from "fs";
25514
- import * as path17 from "path";
25522
+ import * as path18 from "path";
25515
25523
  import * as crypto5 from "crypto";
25516
25524
  import * as os3 from "os";
25517
- import { homedir as homedir11 } from "os";
25525
+ import { homedir as homedir13 } from "os";
25518
25526
 
25519
25527
  // src/discovery.ts
25520
- import * as path13 from "path";
25528
+ import * as path14 from "path";
25521
25529
  import * as fs6 from "fs";
25522
25530
  import { fileURLToPath } from "url";
25523
25531
  // agent-driver/dist/host/default-host.js
@@ -25597,6 +25605,18 @@ function resolveLaunchFieldsOrDefault(input2) {
25597
25605
  // agent-driver/dist/internal/cliLink.js
25598
25606
  import * as fs2 from "fs";
25599
25607
  import * as path2 from "path";
25608
+ function shellQuote(value) {
25609
+ return `'${value.replaceAll("'", "'\\''")}'`;
25610
+ }
25611
+ function writeWindowsBashEnv(binDir, cliName, envPrefix, previous) {
25612
+ const startup = path2.join(binDir, `${cliName}.bash-env`).replaceAll("\\", "/");
25613
+ const envValue = startup.replace(/[$`]/g, "\\$&");
25614
+ const source = previous && previous !== envValue && previous.replaceAll("\\", "/") !== startup ? `. ${shellQuote(previous.replaceAll("\\", "/"))}
25615
+ ` : "";
25616
+ fs2.writeFileSync(startup, source + `export ${shellQuote(`${envPrefix}_CLI=${path2.join(binDir, cliName).replaceAll("\\", "/")}`)}
25617
+ `);
25618
+ return envValue;
25619
+ }
25600
25620
  function writeCliLink(stateDir, cliName, hostCliPath, platform = process.platform) {
25601
25621
  const binDir = path2.join(stateDir, "bin");
25602
25622
  fs2.mkdirSync(binDir, { recursive: true });
@@ -25604,10 +25624,15 @@ function writeCliLink(stateDir, cliName, hostCliPath, platform = process.platfor
25604
25624
  return binDir;
25605
25625
  if (platform === "win32") {
25606
25626
  const cmdFile = path2.join(binDir, `${cliName}.cmd`);
25627
+ const executable = /\.(?:c|m)?js$/i.test(hostCliPath) ? `"${process.execPath}" "${hostCliPath}"` : `"${hostCliPath}"`;
25607
25628
  const body = `@echo off\r
25608
- "${hostCliPath}" %*\r
25629
+ ${executable} %*\r
25609
25630
  `;
25610
25631
  fs2.writeFileSync(cmdFile, body);
25632
+ const bashExecutable = /\.(?:c|m)?js$/i.test(hostCliPath) ? `${shellQuote(process.execPath.replaceAll("\\", "/"))} ${shellQuote(hostCliPath.replaceAll("\\", "/"))}` : shellQuote(hostCliPath.replaceAll("\\", "/"));
25633
+ fs2.writeFileSync(path2.join(binDir, cliName), `#!/bin/sh
25634
+ MSYS2_ARG_CONV_EXCL='*' exec ${bashExecutable} "$@"
25635
+ `, { mode: 493 });
25611
25636
  return binDir;
25612
25637
  }
25613
25638
  const linkPath = path2.join(binDir, cliName);
@@ -25675,7 +25700,12 @@ async function prepareCliTransport(ctx, extraEnv = {}, cli = DEFAULT_CLI_CONFIG,
25675
25700
  {
25676
25701
  name: "platformProtected",
25677
25702
  precedence: 40,
25678
- vars: { ...resource.platformProtected, FORCE_COLOR: "0", NO_COLOR: "1" }
25703
+ vars: {
25704
+ ...resource.platformProtected,
25705
+ ...platform === "win32" && hostCliPath ? { [`${cli.envPrefix}_CLI`]: path3.join(binDir, `${cli.cliName}.cmd`).replaceAll("\\", "/") } : {},
25706
+ FORCE_COLOR: "0",
25707
+ NO_COLOR: "1"
25708
+ }
25679
25709
  },
25680
25710
  { name: "runtimeProtected", precedence: 50, vars: resource.runtimeProtected },
25681
25711
  {
@@ -25692,15 +25722,143 @@ async function prepareCliTransport(ctx, extraEnv = {}, cli = DEFAULT_CLI_CONFIG,
25692
25722
  }
25693
25723
  ];
25694
25724
  const { env: spawnEnv } = mergeEnvLayers(resource.base, layers);
25725
+ if (platform === "win32" && hostCliPath) {
25726
+ spawnEnv.BASH_ENV = writeWindowsBashEnv(binDir, cli.cliName, cli.envPrefix, spawnEnv.BASH_ENV);
25727
+ }
25695
25728
  const tokenFile = String(resource.credentialSensitive.ALOOK_PROXY_TOKEN_FILE ?? "");
25696
25729
  return { stateDir, tokenFile, spawnEnv };
25697
25730
  }
25698
25731
 
25699
25732
  // agent-driver/dist/internal/killTree.js
25700
- import { execFileSync, spawn } from "child_process";
25733
+ import { execFileSync as execFileSync2, spawn } from "child_process";
25701
25734
  import { randomUUID as randomUUID2 } from "node:crypto";
25702
25735
  import { createServer } from "node:net";
25703
25736
  import { PassThrough } from "node:stream";
25737
+
25738
+ // agent-driver/dist/internal/probe.js
25739
+ import { execFileSync } from "child_process";
25740
+ import * as fs4 from "fs";
25741
+ import * as path4 from "path";
25742
+ import { homedir } from "os";
25743
+ var PROBE_TIMEOUT_MS = 5000;
25744
+ var PROBE_OUTPUT_MAX_BYTES = 1024 * 1024;
25745
+ function resolveCommandOnPath(command, deps = {}) {
25746
+ if (deps.which)
25747
+ return deps.which(command);
25748
+ try {
25749
+ if (process.platform === "win32") {
25750
+ const out2 = execFileSync("where", [command], { encoding: "utf8", timeout: PROBE_TIMEOUT_MS });
25751
+ const first = out2.split(/\r?\n/).map((line) => line.trim()).find((line) => /\.(exe|com|cmd|bat)$/i.test(line));
25752
+ return first || null;
25753
+ }
25754
+ const out = execFileSync("which", [command], { encoding: "utf8", timeout: PROBE_TIMEOUT_MS });
25755
+ return out.trim() || null;
25756
+ } catch {
25757
+ return null;
25758
+ }
25759
+ }
25760
+ function firstExistingPath(candidates) {
25761
+ for (const c of candidates) {
25762
+ if (c && fs4.existsSync(c))
25763
+ return c;
25764
+ }
25765
+ return null;
25766
+ }
25767
+ function looksLikeVersion(line) {
25768
+ return /\d+\.\d+/.test(line);
25769
+ }
25770
+ function needsWindowsShimShell(command, platform) {
25771
+ return platform === "win32" && /\.(cmd|bat)$/i.test(command);
25772
+ }
25773
+ function quoteWindowsShimCommand(command, platform = process.platform) {
25774
+ return needsWindowsShimShell(command, platform) && /\s/.test(command) ? `"${command}"` : command;
25775
+ }
25776
+ function probeCommandVersion(command, args = [], deps = {}, platform = process.platform) {
25777
+ try {
25778
+ const shell = needsWindowsShimShell(command, platform);
25779
+ const out = execFileSync(quoteWindowsShimCommand(command, platform), [...args, "--version"], {
25780
+ encoding: "utf8",
25781
+ timeout: PROBE_TIMEOUT_MS,
25782
+ shell,
25783
+ input: "",
25784
+ env: { ...process.env, CI: "1" }
25785
+ });
25786
+ const line = out.split(`
25787
+ `)[0]?.trim();
25788
+ if (!line)
25789
+ return { ok: false, error: "empty_version_output" };
25790
+ if (!looksLikeVersion(line))
25791
+ return { ok: false, error: "invalid_version_output" };
25792
+ return { ok: true, version: line };
25793
+ } catch (err) {
25794
+ const code = err?.code ?? err?.code ?? "version_probe_failed";
25795
+ return { ok: false, error: String(code) };
25796
+ }
25797
+ }
25798
+ function probeCommandOutput(command, args, platform = process.platform) {
25799
+ try {
25800
+ const output2 = execFileSync(quoteWindowsShimCommand(command, platform), args, {
25801
+ encoding: "utf8",
25802
+ timeout: PROBE_TIMEOUT_MS,
25803
+ maxBuffer: PROBE_OUTPUT_MAX_BYTES,
25804
+ shell: needsWindowsShimShell(command, platform),
25805
+ stdio: ["pipe", "pipe", "ignore"],
25806
+ input: "",
25807
+ env: { ...process.env, CI: "1" }
25808
+ });
25809
+ return { ok: true, output: output2 };
25810
+ } catch (err) {
25811
+ const code = err?.code ?? "command_probe_failed";
25812
+ return { ok: false, error: String(code) };
25813
+ }
25814
+ }
25815
+ function resolveHomePath(relativePath, deps = {}) {
25816
+ return path4.join(deps.homeDir || process.env.HOME || ".", relativePath);
25817
+ }
25818
+ function resolveSpawnSpec(command, args, override, deps = {}, platform = process.platform) {
25819
+ const trimmed = override?.trim();
25820
+ const target2 = trimmed && trimmed.length > 0 ? trimmed : command;
25821
+ const looksLikePath = trimmed !== undefined && trimmed.length > 0 && /[\\/]/.test(trimmed);
25822
+ const resolved = looksLikePath ? target2 : resolveCommandOnPath(target2, deps) ?? target2;
25823
+ return { command: resolved, args, shell: needsWindowsShimShell(resolved, platform) };
25824
+ }
25825
+ function resolveClaudeCommand(deps = {}) {
25826
+ const onPath = resolveCommandOnPath("claude", deps);
25827
+ if (onPath)
25828
+ return onPath;
25829
+ if (process.platform === "win32") {
25830
+ const home = deps.homeDir || process.env.USERPROFILE || process.env.HOME || homedir();
25831
+ return firstExistingPath([path4.join(home, ".local", "bin", "claude.exe")]);
25832
+ }
25833
+ if (process.platform === "darwin") {
25834
+ return firstExistingPath([
25835
+ resolveHomePath("Applications/Claude Code URL Handler.app/Contents/MacOS/claude", deps),
25836
+ "/Applications/Claude Code URL Handler.app/Contents/MacOS/claude"
25837
+ ]);
25838
+ }
25839
+ return null;
25840
+ }
25841
+ function probeClaude(deps = {}) {
25842
+ const command = resolveClaudeCommand(deps);
25843
+ if (!command)
25844
+ return { status: "unhealthy", lastError: "not_on_path" };
25845
+ const r = probeCommandVersion(command, [], deps);
25846
+ if (!r.ok)
25847
+ return { status: "unhealthy", lastError: r.error };
25848
+ return { status: "healthy", version: r.version };
25849
+ }
25850
+ function probeCliRuntime(binary, deps = {}, override) {
25851
+ const explicit = override?.trim();
25852
+ const command = explicit || resolveCommandOnPath(binary, deps);
25853
+ if (!command)
25854
+ return { status: "unhealthy", lastError: "not_on_path" };
25855
+ const r = probeCommandVersion(command, [], deps);
25856
+ if (!r.ok)
25857
+ return { status: "unhealthy", lastError: r.error };
25858
+ return { status: "healthy", version: r.version };
25859
+ }
25860
+
25861
+ // agent-driver/dist/internal/killTree.js
25704
25862
  var POLL_MS = 100;
25705
25863
  var FORCE_EXIT_WAIT_MS = 2000;
25706
25864
  var TASKKILL_WAIT_MS = 2000;
@@ -26050,7 +26208,7 @@ function spawnAgentProcess(command, args, opts) {
26050
26208
  const env = {
26051
26209
  ...opts.env,
26052
26210
  [WINDOWS_JOB_NODE_ENV]: process.execPath,
26053
- [WINDOWS_JOB_PAYLOAD_ENV]: Buffer.from(JSON.stringify({ command, args, cwd: opts.cwd, shell: opts.shell ?? false })).toString("base64"),
26211
+ [WINDOWS_JOB_PAYLOAD_ENV]: Buffer.from(JSON.stringify({ command: opts.shell ? quoteWindowsShimCommand(command) : command, args, cwd: opts.cwd, shell: opts.shell ?? false })).toString("base64"),
26054
26212
  [WINDOWS_JOB_RUNNER_ENV]: WINDOWS_JOB_RUNNER,
26055
26213
  ...stdinPipe ? { [WINDOWS_JOB_STDIN_PIPE_ENV]: stdinPipe } : {}
26056
26214
  };
@@ -26112,7 +26270,7 @@ function capturePosixTreeTargets(rootPid, rootOwnsProcessGroup) {
26112
26270
  });
26113
26271
  let output2;
26114
26272
  try {
26115
- output2 = execFileSync("ps", ["-axo", "pid=,ppid=,pgid="], {
26273
+ output2 = execFileSync2("ps", ["-axo", "pid=,ppid=,pgid="], {
26116
26274
  encoding: "utf8",
26117
26275
  timeout: POSIX_TREE_CAPTURE_TIMEOUT_MS,
26118
26276
  maxBuffer: POSIX_TREE_CAPTURE_MAX_BUFFER
@@ -26176,6 +26334,9 @@ function signalPosixTargets(targets, signal) {
26176
26334
  } catch {}
26177
26335
  }
26178
26336
  }
26337
+
26338
+ class WindowsTreeExitError extends Error {
26339
+ }
26179
26340
  function taskkillTree(pid) {
26180
26341
  return new Promise((resolve, reject) => {
26181
26342
  const killer = spawn("taskkill.exe", ["/pid", String(pid), "/t", "/f"], {
@@ -26206,17 +26367,24 @@ function taskkillTree(pid) {
26206
26367
  settle2("resolve");
26207
26368
  return;
26208
26369
  }
26209
- settle2("reject", new Error(`Windows process-tree termination failed (exit=${String(code)}, signal=${String(signal)})`));
26370
+ settle2("reject", new WindowsTreeExitError(`Windows process-tree termination failed (exit=${String(code)}, signal=${String(signal)})`));
26210
26371
  });
26211
26372
  });
26212
26373
  }
26213
26374
  async function killWindowsProcessTree(pid) {
26214
26375
  if (!isAlive(pid))
26215
26376
  return;
26216
- await taskkillTree(pid);
26377
+ let terminationError;
26378
+ try {
26379
+ await taskkillTree(pid);
26380
+ } catch (error62) {
26381
+ if (!(error62 instanceof WindowsTreeExitError))
26382
+ throw error62;
26383
+ terminationError = error62;
26384
+ }
26217
26385
  await waitForProcessExit(pid, FORCE_EXIT_WAIT_MS);
26218
26386
  if (isAlive(pid))
26219
- throw new Error(`Windows process tree ${pid} remained alive after taskkill completed`);
26387
+ throw terminationError ?? new Error(`Windows process tree ${pid} remained alive after taskkill completed`);
26220
26388
  }
26221
26389
  async function waitForProcessExit(pid, timeoutMs) {
26222
26390
  const deadline = Date.now() + timeoutMs;
@@ -26259,8 +26427,8 @@ async function killProcessTree(pid, opts) {
26259
26427
 
26260
26428
  // agent-driver/dist/adapters/antigravity/usage.js
26261
26429
  import { createHash } from "node:crypto";
26262
- import { homedir } from "node:os";
26263
- import { resolve, join as join3 } from "node:path";
26430
+ import { homedir as homedir2 } from "node:os";
26431
+ import { resolve, join as join4 } from "node:path";
26264
26432
 
26265
26433
  // agent-driver/dist/adapters/antigravity/local-data.js
26266
26434
  async function readLocalCommand(command, args, limit = 256 * 1024) {
@@ -26358,7 +26526,7 @@ function parseNativeGeneration(data) {
26358
26526
  return { usage: { input: count(usage, 2), output: count(usage, 3), cache: count(usage, 5) }, occurredAt };
26359
26527
  }
26360
26528
  function nativeUsageHome(env, cwd) {
26361
- return resolve(cwd, env.GEMINI_HOME?.replace(/^~(?=[/\\]|$)/, homedir()) || join3(homedir(), ".gemini"));
26529
+ return resolve(cwd, env.GEMINI_HOME?.replace(/^~(?=[/\\]|$)/, homedir2()) || join4(homedir2(), ".gemini"));
26362
26530
  }
26363
26531
  var QUERY = "WITH pending AS (SELECT idx,data FROM gen_metadata WHERE idx>? ORDER BY idx LIMIT 128), batch AS (SELECT idx,data,sum(length(data)) OVER (ORDER BY idx) AS bytes FROM pending) SELECT idx,hex(substr(data,1,4194305)) AS data,(SELECT COUNT(*) FROM steps WHERE has_subtrajectory=1) AS has_children FROM batch WHERE bytes<=4194304 OR idx=(SELECT min(idx) FROM batch) ORDER BY idx";
26364
26532
 
@@ -26376,12 +26544,12 @@ class NativeUsageReader {
26376
26544
  throw new Error("Invalid native usage session identity");
26377
26545
  }
26378
26546
  async read() {
26379
- const path4 = join3(this.home, "antigravity-acp", "conversations", `${this.sessionId}.db`);
26547
+ const path5 = join4(this.home, "antigravity-acp", "conversations", `${this.sessionId}.db`);
26380
26548
  let cursor = this.cursor;
26381
26549
  let complete = false;
26382
26550
  const result = [];
26383
26551
  for (let batch = 0;batch < 16; batch++) {
26384
- const rows = await this.readRows(path4, cursor);
26552
+ const rows = await this.readRows(path5, cursor);
26385
26553
  for (const row of rows) {
26386
26554
  if (!Number.isSafeInteger(row.idx) || row.idx <= cursor || !/^(?:[a-f0-9]{2})*$/i.test(row.data) || row.data.length > 8 * 1024 * 1024)
26387
26555
  throw new Error("Invalid native usage row");
@@ -26402,11 +26570,11 @@ class NativeUsageReader {
26402
26570
  return { samples: result, complete, ...this.childTrajectories ? { incompleteScope: true } : {} };
26403
26571
  }
26404
26572
  }
26405
- async function queryNativeRowsWithCli(path4, cursor) {
26406
- const output2 = await readLocalCommand("sqlite3", ["-readonly", "-json", path4, QUERY.replace("idx>?", `idx>${cursor}`)], 16 * 1024 * 1024);
26573
+ async function queryNativeRowsWithCli(path5, cursor) {
26574
+ const output2 = await readLocalCommand("sqlite3", ["-readonly", "-json", path5, QUERY.replace("idx>?", `idx>${cursor}`)], 16 * 1024 * 1024);
26407
26575
  return output2.trim() ? JSON.parse(output2) : [];
26408
26576
  }
26409
- async function queryNativeRows(path4, cursor, loadSqlite = async () => {
26577
+ async function queryNativeRows(path5, cursor, loadSqlite = async () => {
26410
26578
  const module = "node:sqlite";
26411
26579
  return await import(module);
26412
26580
  }) {
@@ -26414,9 +26582,9 @@ async function queryNativeRows(path4, cursor, loadSqlite = async () => {
26414
26582
  try {
26415
26583
  sqlite = await loadSqlite();
26416
26584
  } catch {
26417
- return queryNativeRowsWithCli(path4, cursor);
26585
+ return queryNativeRowsWithCli(path5, cursor);
26418
26586
  }
26419
- const db = new sqlite.DatabaseSync(path4, { readOnly: true });
26587
+ const db = new sqlite.DatabaseSync(path5, { readOnly: true });
26420
26588
  try {
26421
26589
  return db.prepare(QUERY).all(cursor);
26422
26590
  } finally {
@@ -27304,132 +27472,15 @@ class AntigravityAcpLane {
27304
27472
  // agent-driver/dist/adapters/antigravity/probe.js
27305
27473
  import { createHash as createHash2, randomUUID as randomUUID4 } from "node:crypto";
27306
27474
  import { mkdirSync as mkdirSync3, readFileSync as readFileSync2, renameSync as renameSync2, writeFileSync as writeFileSync3 } from "node:fs";
27307
- import { homedir as homedir2 } from "node:os";
27475
+ import { homedir as homedir3 } from "node:os";
27308
27476
  import { join as join5 } from "node:path";
27309
-
27310
- // agent-driver/dist/internal/probe.js
27311
- import { execFileSync as execFileSync2 } from "child_process";
27312
- import * as fs4 from "fs";
27313
- import * as path4 from "path";
27314
- var PROBE_TIMEOUT_MS = 5000;
27315
- var PROBE_OUTPUT_MAX_BYTES = 1024 * 1024;
27316
- function resolveCommandOnPath(command, deps = {}) {
27317
- if (deps.which)
27318
- return deps.which(command);
27319
- try {
27320
- if (process.platform === "win32") {
27321
- const out2 = execFileSync2("where", [command], { encoding: "utf8", timeout: PROBE_TIMEOUT_MS });
27322
- const first = out2.split(/\r?\n/).find((line) => line.trim().length > 0);
27323
- return first?.trim() || null;
27324
- }
27325
- const out = execFileSync2("which", [command], { encoding: "utf8", timeout: PROBE_TIMEOUT_MS });
27326
- return out.trim() || null;
27327
- } catch {
27328
- return null;
27329
- }
27330
- }
27331
- function firstExistingPath(candidates) {
27332
- for (const c of candidates) {
27333
- if (c && fs4.existsSync(c))
27334
- return c;
27335
- }
27336
- return null;
27337
- }
27338
- function looksLikeVersion(line) {
27339
- return /\d+\.\d+/.test(line);
27340
- }
27341
- function needsWindowsShimShell(command, platform) {
27342
- return platform === "win32" && /\.(cmd|bat)$/i.test(command);
27343
- }
27344
- function probeCommandVersion(command, args = [], deps = {}, platform = process.platform) {
27345
- try {
27346
- const shell = needsWindowsShimShell(command, platform);
27347
- const out = execFileSync2(command, [...args, "--version"], {
27348
- encoding: "utf8",
27349
- timeout: PROBE_TIMEOUT_MS,
27350
- shell,
27351
- input: "",
27352
- env: { ...process.env, CI: "1" }
27353
- });
27354
- const line = out.split(`
27355
- `)[0]?.trim();
27356
- if (!line)
27357
- return { ok: false, error: "empty_version_output" };
27358
- if (!looksLikeVersion(line))
27359
- return { ok: false, error: "invalid_version_output" };
27360
- return { ok: true, version: line };
27361
- } catch (err) {
27362
- const code = err?.code ?? err?.code ?? "version_probe_failed";
27363
- return { ok: false, error: String(code) };
27364
- }
27365
- }
27366
- function probeCommandOutput(command, args, platform = process.platform) {
27367
- try {
27368
- const output2 = execFileSync2(command, args, {
27369
- encoding: "utf8",
27370
- timeout: PROBE_TIMEOUT_MS,
27371
- maxBuffer: PROBE_OUTPUT_MAX_BYTES,
27372
- shell: needsWindowsShimShell(command, platform),
27373
- stdio: ["pipe", "pipe", "ignore"],
27374
- input: "",
27375
- env: { ...process.env, CI: "1" }
27376
- });
27377
- return { ok: true, output: output2 };
27378
- } catch (err) {
27379
- const code = err?.code ?? "command_probe_failed";
27380
- return { ok: false, error: String(code) };
27381
- }
27382
- }
27383
- function resolveHomePath(relativePath, deps = {}) {
27384
- return path4.join(deps.homeDir || process.env.HOME || ".", relativePath);
27385
- }
27386
- function resolveSpawnSpec(command, args, override, deps = {}, platform = process.platform) {
27387
- const trimmed = override?.trim();
27388
- const target2 = trimmed && trimmed.length > 0 ? trimmed : command;
27389
- const looksLikePath = trimmed !== undefined && trimmed.length > 0 && /[\\/]/.test(trimmed);
27390
- const resolved = looksLikePath ? target2 : resolveCommandOnPath(target2, deps) ?? target2;
27391
- return { command: resolved, args, shell: needsWindowsShimShell(resolved, platform) };
27392
- }
27393
- function resolveClaudeCommand(deps = {}) {
27394
- const onPath = resolveCommandOnPath("claude", deps);
27395
- if (onPath)
27396
- return onPath;
27397
- if (process.platform === "darwin") {
27398
- return firstExistingPath([
27399
- resolveHomePath("Applications/Claude Code URL Handler.app/Contents/MacOS/claude", deps),
27400
- "/Applications/Claude Code URL Handler.app/Contents/MacOS/claude"
27401
- ]);
27402
- }
27403
- return null;
27404
- }
27405
- function probeClaude(deps = {}) {
27406
- const command = resolveClaudeCommand(deps);
27407
- if (!command)
27408
- return { status: "unhealthy", lastError: "not_on_path" };
27409
- const r = probeCommandVersion(command, [], deps);
27410
- if (!r.ok)
27411
- return { status: "unhealthy", lastError: r.error };
27412
- return { status: "healthy", version: r.version };
27413
- }
27414
- function probeCliRuntime(binary, deps = {}, override) {
27415
- const explicit = override?.trim();
27416
- const command = explicit || resolveCommandOnPath(binary, deps);
27417
- if (!command)
27418
- return { status: "unhealthy", lastError: "not_on_path" };
27419
- const r = probeCommandVersion(command, [], deps);
27420
- if (!r.ok)
27421
- return { status: "unhealthy", lastError: r.error };
27422
- return { status: "healthy", version: r.version };
27423
- }
27424
-
27425
- // agent-driver/dist/adapters/antigravity/probe.js
27426
27477
  function antigravitySpawnSpec(command, platform = process.platform) {
27427
27478
  return resolveSpawnSpec(platform === "win32" ? "agy_acp_server.exe" : "agy_acp_server.par", platform === "linux" ? ["--uid="] : [], command);
27428
27479
  }
27429
27480
  async function probeAntigravity(command, options = {}) {
27430
27481
  const spec = antigravitySpawnSpec(command);
27431
27482
  const identity = createHash2("sha256").update(JSON.stringify([spec.command, process.env.GEMINI_HOME ?? ""])).digest("hex").slice(0, 16);
27432
- const directory = options.cacheDirectory ?? join5(homedir2(), ".cache", "alook", "antigravity-probe", identity);
27483
+ const directory = options.cacheDirectory ?? join5(homedir3(), ".cache", "alook", "antigravity-probe", identity);
27433
27484
  const cacheFile = join5(directory, "session");
27434
27485
  let cachedSessionId;
27435
27486
  try {
@@ -27476,7 +27527,7 @@ async function probeAntigravity(command, options = {}) {
27476
27527
  cleanup(proc).then(() => resolve2(result), () => resolve2({ status: "unhealthy", lastError: "antigravity_acp_cleanup_failed" }));
27477
27528
  };
27478
27529
  const fail = (lastError) => finish({ status: "unhealthy", lastError });
27479
- const timer = setTimeout(() => fail("antigravity_acp_timeout"), options.timeoutMs ?? 1e4);
27530
+ const timer = setTimeout(() => fail("antigravity_acp_timeout"), options.timeoutMs ?? (process.platform === "win32" ? 30000 : 1e4));
27480
27531
  const write = (value) => {
27481
27532
  try {
27482
27533
  if (!proc.stdin || proc.stdin.destroyed || proc.stdin.writableEnded || proc.stdin.writable === false) {
@@ -28381,7 +28432,7 @@ class ClaudeTurnProtocol {
28381
28432
 
28382
28433
  // agent-driver/dist/adapters/claude/recent-context.js
28383
28434
  import { createReadStream as createReadStream2 } from "node:fs";
28384
- import { homedir as homedir3 } from "node:os";
28435
+ import { homedir as homedir4 } from "node:os";
28385
28436
  import path7 from "node:path";
28386
28437
  import { createInterface } from "node:readline";
28387
28438
 
@@ -28590,7 +28641,7 @@ async function discoverClaudeRecentContext(request, dependencies = {}) {
28590
28641
  const collector = new RecentContextCollector(request, "supported");
28591
28642
  if (collector.satisfied)
28592
28643
  return collector.result();
28593
- const projectsRoot = path7.resolve(dependencies.projectsRoot ?? path7.join(process.env.CLAUDE_CONFIG_DIR || path7.join(homedir3(), ".claude"), "projects"));
28644
+ const projectsRoot = path7.resolve(dependencies.projectsRoot ?? path7.join(process.env.CLAUDE_CONFIG_DIR || path7.join(homedir4(), ".claude"), "projects"));
28594
28645
  const readProjectPath = dependencies.readProjectPath ?? readClaudeProjectPath;
28595
28646
  const candidates = await collectJsonlFileCandidates(projectsRoot, {
28596
28647
  includeRootFiles: false,
@@ -33187,6 +33238,59 @@ class OpenCodeServiceLane {
33187
33238
  }
33188
33239
  }
33189
33240
 
33241
+ // agent-driver/dist/adapters/opencode/legacy-auth.js
33242
+ import { open as open2 } from "node:fs/promises";
33243
+ import { homedir as homedir6 } from "node:os";
33244
+ import path10 from "node:path";
33245
+ function record6(value) {
33246
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : undefined;
33247
+ }
33248
+ function parse5(value) {
33249
+ try {
33250
+ return record6(JSON.parse(value));
33251
+ } catch {
33252
+ return;
33253
+ }
33254
+ }
33255
+ async function readJson(filename, maxBytes) {
33256
+ try {
33257
+ const file2 = await open2(filename, "r");
33258
+ try {
33259
+ if ((await file2.stat()).size > maxBytes)
33260
+ return;
33261
+ return parse5(await file2.readFile("utf8"));
33262
+ } finally {
33263
+ await file2.close();
33264
+ }
33265
+ } catch {
33266
+ return;
33267
+ }
33268
+ }
33269
+ function xdgRoot(value, fallback) {
33270
+ return value && path10.isAbsolute(value) ? value : fallback;
33271
+ }
33272
+ async function legacyOpenCodeApiEnvironment(environment, model) {
33273
+ if (!model || model.indexOf("/") < 1)
33274
+ return {};
33275
+ if (environment.OPENCODE_MODELS_URL && environment.OPENCODE_MODELS_URL !== "https://models.opencode.ai" && !environment.OPENCODE_MODELS_PATH)
33276
+ return {};
33277
+ const provider = model.slice(0, model.indexOf("/"));
33278
+ const home = (process.platform === "win32" ? environment.USERPROFILE : undefined) || environment.HOME || homedir6();
33279
+ const cache = xdgRoot(environment.XDG_CACHE_HOME, path10.join(home, ".cache"));
33280
+ const catalog = await readJson(environment.OPENCODE_MODELS_PATH || path10.join(cache, "opencode", "models.json"), 16 * 1024 * 1024);
33281
+ const providerInfo = record6(catalog?.[provider]);
33282
+ const names = Array.isArray(providerInfo?.env) ? providerInfo.env.filter((name2) => typeof name2 === "string") : [];
33283
+ if (names.some((name2) => environment[name2] !== undefined))
33284
+ return {};
33285
+ const name = names.find((name2) => /^[A-Z][A-Z0-9_]*(?:_API_KEY|_TOKEN)$/.test(name2));
33286
+ if (!name)
33287
+ return {};
33288
+ const data = xdgRoot(environment.XDG_DATA_HOME, path10.join(home, ".local", "share"));
33289
+ const auth = (environment.OPENCODE_AUTH_CONTENT ? parse5(environment.OPENCODE_AUTH_CONTENT) : undefined) ?? await readJson(path10.join(data, "opencode", "auth.json"), 1024 * 1024);
33290
+ const credential = record6(auth?.[provider]);
33291
+ return credential?.type === "api" && typeof credential.key === "string" && credential.key.trim() ? { [name]: credential.key } : {};
33292
+ }
33293
+
33190
33294
  // agent-driver/dist/adapters/opencode/recent-context.js
33191
33295
  var OPENCODE_DISCOVERY_TIMEOUT_MS = 15000;
33192
33296
  var OPENCODE_DISCOVERY_OUTPUT_MAX_BYTES = 4 * 1024 * 1024;
@@ -33300,7 +33404,9 @@ class OpenCodeDriver {
33300
33404
  const { spawnEnv } = await prepareCliTransport(ctx, {
33301
33405
  OPENCODE_SERVER_PASSWORD: password
33302
33406
  });
33303
- const override = resolveLaunchFieldsOrDefault(ctx.config.runtimeConfig).command;
33407
+ const fields2 = resolveLaunchFieldsOrDefault(ctx.config.runtimeConfig);
33408
+ Object.assign(spawnEnv, await legacyOpenCodeApiEnvironment(spawnEnv, fields2.model));
33409
+ const override = fields2.command;
33304
33410
  const args = [
33305
33411
  "serve",
33306
33412
  "--pure",
@@ -33323,8 +33429,8 @@ class OpenCodeDriver {
33323
33429
  // agent-driver/dist/adapters/pi/index.js
33324
33430
  import { createRequire as createRequire2 } from "module";
33325
33431
  import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync4, realpathSync } from "fs";
33326
- import { homedir as homedir6 } from "os";
33327
- import * as path12 from "path";
33432
+ import { homedir as homedir8 } from "os";
33433
+ import * as path13 from "path";
33328
33434
 
33329
33435
  // agent-driver/dist/controller/sdk-host.js
33330
33436
  import { EventEmitter as EventEmitter6 } from "events";
@@ -33439,7 +33545,7 @@ class SdkLane {
33439
33545
 
33440
33546
  // agent-driver/dist/adapters/pi/sessionDeps.js
33441
33547
  import { readFileSync as readFileSync3 } from "fs";
33442
- import * as path10 from "path";
33548
+ import * as path11 from "path";
33443
33549
  import { pathToFileURL } from "url";
33444
33550
  var PI_SDK_PACKAGE_NAME = "@earendil-works/pi-coding-agent";
33445
33551
  var cachedSdkPromise = null;
@@ -33448,9 +33554,9 @@ async function importPiSdkFromGlobalInstall() {
33448
33554
  if (!dir) {
33449
33555
  throw new Error(`${PI_SDK_PACKAGE_NAME} not found — install it (e.g. \`npm install -g ${PI_SDK_PACKAGE_NAME}\`) before launching a pi agent`);
33450
33556
  }
33451
- const pkg = JSON.parse(readFileSync3(path10.join(dir, "package.json"), "utf-8"));
33557
+ const pkg = JSON.parse(readFileSync3(path11.join(dir, "package.json"), "utf-8"));
33452
33558
  const entry = pkg.exports?.["."]?.import ?? pkg.main ?? "./dist/index.js";
33453
- const entryPath = path10.join(dir, entry);
33559
+ const entryPath = path11.join(dir, entry);
33454
33560
  const barrel = await import(pathToFileURL(entryPath).href);
33455
33561
  return withSessionDirHelper(barrel, entryPath);
33456
33562
  }
@@ -33458,7 +33564,7 @@ async function withSessionDirHelper(barrel, entryPath) {
33458
33564
  if (typeof barrel.getDefaultSessionDir === "function")
33459
33565
  return barrel;
33460
33566
  try {
33461
- const deepPath = path10.join(path10.dirname(entryPath), "core", "session-manager.js");
33567
+ const deepPath = path11.join(path11.dirname(entryPath), "core", "session-manager.js");
33462
33568
  const deep = await import(pathToFileURL(deepPath).href);
33463
33569
  if (typeof deep.getDefaultSessionDir !== "function")
33464
33570
  return barrel;
@@ -33539,13 +33645,13 @@ function createPiSessionDependencies(ctx, loadSdk = loadPiSdkModule) {
33539
33645
  }
33540
33646
 
33541
33647
  // agent-driver/dist/adapters/pi/recent-context.js
33542
- import { homedir as homedir5 } from "node:os";
33543
- import path11 from "node:path";
33648
+ import { homedir as homedir7 } from "node:os";
33649
+ import path12 from "node:path";
33544
33650
  function expandTildePath(value) {
33545
33651
  if (value === "~")
33546
- return homedir5();
33652
+ return homedir7();
33547
33653
  if (value.startsWith("~/"))
33548
- return path11.join(homedir5(), value.slice(2));
33654
+ return path12.join(homedir7(), value.slice(2));
33549
33655
  return value;
33550
33656
  }
33551
33657
  async function discoverPiRecentContext(request, dependencies = {}) {
@@ -33553,7 +33659,7 @@ async function discoverPiRecentContext(request, dependencies = {}) {
33553
33659
  if (collector.satisfied)
33554
33660
  return collector.result();
33555
33661
  const customSessionDirectory = process.env.PI_CODING_AGENT_SESSION_DIR;
33556
- const sessionsRoot = path11.resolve(expandTildePath(dependencies.sessionsRoot ?? customSessionDirectory ?? path11.join(process.env.PI_CODING_AGENT_DIR || path11.join(homedir5(), ".pi", "agent"), "sessions")));
33662
+ const sessionsRoot = path12.resolve(expandTildePath(dependencies.sessionsRoot ?? customSessionDirectory ?? path12.join(process.env.PI_CODING_AGENT_DIR || path12.join(homedir7(), ".pi", "agent"), "sessions")));
33557
33663
  const scanDirectSessions = dependencies.sessionsRoot == null && customSessionDirectory != null;
33558
33664
  const readHeader = dependencies.readHeader ?? readFirstLine;
33559
33665
  const candidates = await collectJsonlFileCandidates(sessionsRoot, {
@@ -33601,15 +33707,15 @@ function resolvePiSdkPackageDir(deps = {}) {
33601
33707
  if (!binPath)
33602
33708
  return;
33603
33709
  try {
33604
- let dir = path12.dirname(realpathSync(binPath));
33710
+ let dir = path13.dirname(realpathSync(binPath));
33605
33711
  const MAX_DEPTH = 8;
33606
33712
  for (let i = 0;i < MAX_DEPTH; i++) {
33607
- if (isPiSdkPackageJson(path12.join(dir, "package.json")))
33713
+ if (isPiSdkPackageJson(path13.join(dir, "package.json")))
33608
33714
  return dir;
33609
- const siblingDir = path12.join(dir, "node_modules", PI_SDK_PACKAGE_NAME2);
33610
- if (isPiSdkPackageJson(path12.join(siblingDir, "package.json")))
33715
+ const siblingDir = path13.join(dir, "node_modules", PI_SDK_PACKAGE_NAME2);
33716
+ if (isPiSdkPackageJson(path13.join(siblingDir, "package.json")))
33611
33717
  return siblingDir;
33612
- const parent = path12.dirname(dir);
33718
+ const parent = path13.dirname(dir);
33613
33719
  if (parent === dir)
33614
33720
  break;
33615
33721
  dir = parent;
@@ -33626,21 +33732,21 @@ function findPiSessionFile(sessionDir, sessionId) {
33626
33732
  }
33627
33733
  const suffix = `_${sessionId}.jsonl`;
33628
33734
  const match = entries.find((entry) => entry.endsWith(suffix));
33629
- return match ? path12.join(sessionDir, match) : null;
33735
+ return match ? path13.join(sessionDir, match) : null;
33630
33736
  }
33631
33737
  function resolvePiSessionDir(sdk, cwd) {
33632
33738
  if (typeof sdk.getDefaultSessionDir === "function")
33633
33739
  return sdk.getDefaultSessionDir(cwd);
33634
- const agentDir = typeof sdk.getAgentDir === "function" ? sdk.getAgentDir() : path12.join(homedir6(), ".pi", "agent");
33635
- const encoded = `--${path12.resolve(cwd).replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--`;
33636
- return path12.join(agentDir, "sessions", encoded);
33740
+ const agentDir = typeof sdk.getAgentDir === "function" ? sdk.getAgentDir() : path13.join(homedir8(), ".pi", "agent");
33741
+ const encoded = `--${path13.resolve(cwd).replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--`;
33742
+ return path13.join(agentDir, "sessions", encoded);
33637
33743
  }
33638
33744
  function resolvePiSdkVersionFromPath(deps = {}) {
33639
33745
  const dir = resolvePiSdkPackageDir(deps);
33640
33746
  if (!dir)
33641
33747
  return;
33642
33748
  try {
33643
- const pkg = JSON.parse(readFileSync4(path12.join(dir, "package.json"), "utf-8"));
33749
+ const pkg = JSON.parse(readFileSync4(path13.join(dir, "package.json"), "utf-8"));
33644
33750
  return pkg.version;
33645
33751
  } catch {
33646
33752
  return;
@@ -35743,22 +35849,22 @@ function listRuntimeIds() {
35743
35849
 
35744
35850
  // src/discovery.ts
35745
35851
  function resolveAlookCliPath(moduleDir) {
35746
- const thisDir = moduleDir ?? path13.dirname(fileURLToPath(import.meta.url));
35747
- const target2 = path13.basename(thisDir) === "dist" ? path13.resolve(thisDir, "cli", "index.js") : path13.resolve(thisDir, "..", "scripts", "alook-shim.mjs");
35852
+ const thisDir = moduleDir ?? path14.dirname(fileURLToPath(import.meta.url));
35853
+ const target2 = path14.basename(thisDir) === "dist" ? path14.resolve(thisDir, "cli", "index.js") : path14.resolve(thisDir, "..", "scripts", "alook-shim.mjs");
35748
35854
  return fs6.existsSync(target2) ? target2 : null;
35749
35855
  }
35750
35856
  function deriveCliFallbackCandidates(cliPath) {
35751
35857
  if (!cliPath)
35752
35858
  return [];
35753
- const normalized = cliPath.split(path13.sep).join("/");
35859
+ const normalized = cliPath.split(path14.sep).join("/");
35754
35860
  const marker = "/node_modules/";
35755
35861
  const idx = normalized.indexOf(marker);
35756
35862
  if (idx === -1)
35757
35863
  return [];
35758
35864
  const globalRoot = cliPath.slice(0, idx + marker.length - 1);
35759
- const tail = path13.join("dist", "cli", "index.js");
35865
+ const tail = path14.join("dist", "cli", "index.js");
35760
35866
  return [
35761
- path13.join(globalRoot, "@alook", "daemon", tail)
35867
+ path14.join(globalRoot, "@alook", "daemon", tail)
35762
35868
  ].filter((candidate) => candidate !== cliPath);
35763
35869
  }
35764
35870
  function resolveAlookCliPathWithFallback(primary) {
@@ -35861,14 +35967,14 @@ function createLogger2(options = {}) {
35861
35967
  `));
35862
35968
  const err = options.err ?? ((line) => process.stderr.write(line + `
35863
35969
  `));
35864
- const record6 = options.record;
35970
+ const record7 = options.record;
35865
35971
  const emit = (level, message2, data) => {
35866
35972
  if (LEVEL_RANK[level] < minRank)
35867
35973
  return;
35868
35974
  const time3 = now();
35869
35975
  const line = `${time3} ${header} ${level.toUpperCase().padEnd(5)} ${message2}${formatData(data)}`;
35870
35976
  try {
35871
- record6?.({ time: time3, header, level, message: message2, fields: recordFields(data) });
35977
+ record7?.({ time: time3, header, level, message: message2, fields: recordFields(data) });
35872
35978
  } catch {}
35873
35979
  (level === "warn" || level === "error" ? err : out)(line);
35874
35980
  };
@@ -35900,11 +36006,11 @@ function readDaemonVersion() {
35900
36006
 
35901
36007
  // src/cli/daemonRunner.ts
35902
36008
  import * as fs11 from "node:fs";
35903
- import * as path16 from "node:path";
36009
+ import * as path17 from "node:path";
35904
36010
  import { WebSocket } from "ws";
35905
36011
 
35906
36012
  // src/daemon/createDaemon.ts
35907
- import { homedir as homedir10 } from "os";
36013
+ import { homedir as homedir12 } from "os";
35908
36014
  import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync9 } from "node:fs";
35909
36015
 
35910
36016
  // src/util/rotatingFileSink.ts
@@ -35921,7 +36027,7 @@ import {
35921
36027
  statSync,
35922
36028
  unlinkSync as unlinkSync3
35923
36029
  } from "node:fs";
35924
- function createRotatingFileSink(path14, maxBytes, opts = {}) {
36030
+ function createRotatingFileSink(path15, maxBytes, opts = {}) {
35925
36031
  const report = (operation, error62) => {
35926
36032
  try {
35927
36033
  opts.onError?.({ operation, error: error62 });
@@ -35957,9 +36063,9 @@ function createRotatingFileSink(path14, maxBytes, opts = {}) {
35957
36063
  };
35958
36064
  const rotate = () => {
35959
36065
  try {
35960
- renameSync3(path14, `${path14}.1`);
36066
+ renameSync3(path15, `${path15}.1`);
35961
36067
  if (opts.mode !== undefined)
35962
- chmodSync(`${path14}.1`, opts.mode);
36068
+ chmodSync(`${path15}.1`, opts.mode);
35963
36069
  return true;
35964
36070
  } catch (error62) {
35965
36071
  report("rotate", error62);
@@ -35968,7 +36074,7 @@ function createRotatingFileSink(path14, maxBytes, opts = {}) {
35968
36074
  };
35969
36075
  const currentSize = () => {
35970
36076
  try {
35971
- return existsSync6(path14) ? statSync(path14).size : 0;
36077
+ return existsSync6(path15) ? statSync(path15).size : 0;
35972
36078
  } catch (error62) {
35973
36079
  report("stat", error62);
35974
36080
  return null;
@@ -35976,7 +36082,7 @@ function createRotatingFileSink(path14, maxBytes, opts = {}) {
35976
36082
  };
35977
36083
  const sink = {
35978
36084
  secure() {
35979
- return secureGeneration(`${path14}.1`) && secureGeneration(path14);
36085
+ return secureGeneration(`${path15}.1`) && secureGeneration(path15);
35980
36086
  },
35981
36087
  write(line) {
35982
36088
  try {
@@ -35996,7 +36102,7 @@ function createRotatingFileSink(path14, maxBytes, opts = {}) {
35996
36102
  const shouldRotate = maxBytes > 0 && (opts.hardMaxBytes ? currentBytes > 0 && currentBytes + serializedBytes > maxBytes : currentBytes >= maxBytes);
35997
36103
  if (shouldRotate && !rotate() && opts.hardMaxBytes)
35998
36104
  return;
35999
- appendFileSync(path14, serialized, opts.mode === undefined ? undefined : { mode: opts.mode });
36105
+ appendFileSync(path15, serialized, opts.mode === undefined ? undefined : { mode: opts.mode });
36000
36106
  } catch (error62) {
36001
36107
  report("append", error62);
36002
36108
  }
@@ -36004,7 +36110,7 @@ function createRotatingFileSink(path14, maxBytes, opts = {}) {
36004
36110
  openSnapshot() {
36005
36111
  const files = [];
36006
36112
  try {
36007
- for (const candidate of [`${path14}.1`, path14]) {
36113
+ for (const candidate of [`${path15}.1`, path15]) {
36008
36114
  if (!existsSync6(candidate))
36009
36115
  continue;
36010
36116
  if (!secureGeneration(candidate))
@@ -36165,11 +36271,11 @@ function createTraceSampler(emit, throttleMs = DEFAULT_TRACE_SAMPLE_MS) {
36165
36271
 
36166
36272
  // src/util/statusFile.ts
36167
36273
  import { writeFileSync as writeFileSync5, renameSync as renameSync4 } from "node:fs";
36168
- function writeStatusFile(path14, snapshot) {
36274
+ function writeStatusFile(path15, snapshot) {
36169
36275
  try {
36170
- const tmp = `${path14}.tmp`;
36276
+ const tmp = `${path15}.tmp`;
36171
36277
  writeFileSync5(tmp, JSON.stringify(snapshot));
36172
- renameSync4(tmp, path14);
36278
+ renameSync4(tmp, path15);
36173
36279
  } catch {}
36174
36280
  }
36175
36281
 
@@ -36851,7 +36957,7 @@ import * as fs7 from "fs";
36851
36957
  import * as http from "http";
36852
36958
  import * as https from "https";
36853
36959
  import * as os2 from "os";
36854
- import * as path14 from "path";
36960
+ import * as path15 from "path";
36855
36961
  import { URL as URL2 } from "url";
36856
36962
  var LOCAL_MESSAGE_REMINDER_PATH = "/__alook/local/message-reminder";
36857
36963
  var LOCAL_MESSAGE_REMINDER_BODY_MAX_BYTES = 4 * 1024;
@@ -36883,15 +36989,15 @@ class CredentialBroker {
36883
36989
  this.voucherPrefix = config2.voucherPrefix ?? "vch_";
36884
36990
  this.clientLabel = config2.clientLabel ?? "cli";
36885
36991
  this.headerNames = config2.headerNames ?? DEFAULT_HEADER_NAMES;
36886
- this.voucherDir = config2.voucherDir ?? path14.join(os2.tmpdir(), "agent-vouchers");
36992
+ this.voucherDir = config2.voucherDir ?? path15.join(os2.tmpdir(), "agent-vouchers");
36887
36993
  }
36888
36994
  mint(agentId, launchId, capabilities2, runnerKey) {
36889
36995
  if (!runnerKey)
36890
36996
  throw new Error("CredentialBroker.mint: runnerKey is required (per-agent tier-2 credential)");
36891
36997
  const voucher = randomVoucher(this.voucherPrefix);
36892
- const dir = path14.join(this.voucherDir, sanitizeIdSegment(agentId));
36998
+ const dir = path15.join(this.voucherDir, sanitizeIdSegment(agentId));
36893
36999
  fs7.mkdirSync(dir, { recursive: true });
36894
- const voucherFile = path14.join(dir, `${sanitizeIdSegment(launchId)}.token`);
37000
+ const voucherFile = path15.join(dir, `${sanitizeIdSegment(launchId)}.token`);
36895
37001
  fs7.writeFileSync(voucherFile, voucher, { mode: 384 });
36896
37002
  this.registrations.set(voucher, {
36897
37003
  agentId,
@@ -37019,20 +37125,20 @@ function parseLocalMessageReminderBody(body, agentId) {
37019
37125
  }
37020
37126
  if (!value || typeof value !== "object" || Array.isArray(value))
37021
37127
  return null;
37022
- const record6 = value;
37023
- if (Object.keys(record6).sort().join(",") !== "channel,remindAfterMs,sentSeq")
37128
+ const record7 = value;
37129
+ if (Object.keys(record7).sort().join(",") !== "channel,remindAfterMs,sentSeq")
37024
37130
  return null;
37025
- if (typeof record6.channel !== "string" || !isCanonicalChannelScope(record6.channel))
37131
+ if (typeof record7.channel !== "string" || !isCanonicalChannelScope(record7.channel))
37026
37132
  return null;
37027
- if (!Number.isSafeInteger(record6.sentSeq) || record6.sentSeq < 1)
37133
+ if (!Number.isSafeInteger(record7.sentSeq) || record7.sentSeq < 1)
37028
37134
  return null;
37029
- if (!Number.isSafeInteger(record6.remindAfterMs) || record6.remindAfterMs !== 0 && record6.remindAfterMs < LOCAL_MESSAGE_REMINDER_MIN_MS || record6.remindAfterMs > LOCAL_MESSAGE_REMINDER_MAX_MS)
37135
+ if (!Number.isSafeInteger(record7.remindAfterMs) || record7.remindAfterMs !== 0 && record7.remindAfterMs < LOCAL_MESSAGE_REMINDER_MIN_MS || record7.remindAfterMs > LOCAL_MESSAGE_REMINDER_MAX_MS)
37030
37136
  return null;
37031
37137
  return {
37032
37138
  agentId,
37033
- channel: record6.channel,
37034
- sentSeq: record6.sentSeq,
37035
- remindAfterMs: record6.remindAfterMs
37139
+ channel: record7.channel,
37140
+ sentSeq: record7.sentSeq,
37141
+ remindAfterMs: record7.remindAfterMs
37036
37142
  };
37037
37143
  }
37038
37144
  async function handleLocalMessageReminder(req, res, agentId, onArm) {
@@ -37434,13 +37540,13 @@ function reduceManager(state, event) {
37434
37540
  const existing = state.agents[event.agentId];
37435
37541
  if (!existing || existing.execution.sessionInstanceId !== event.sessionInstanceId)
37436
37542
  return { state, effects: [] };
37437
- const record6 = existing.pendingAdmissions.find((entry) => entry.sessionInstanceId === event.sessionInstanceId && entry.commandId === event.commandId);
37438
- if (!record6)
37543
+ const record7 = existing.pendingAdmissions.find((entry) => entry.sessionInstanceId === event.sessionInstanceId && entry.commandId === event.commandId);
37544
+ if (!record7)
37439
37545
  return { state, effects: [] };
37440
37546
  const agent2 = clone2(existing);
37441
37547
  agent2.pendingAdmissions = agent2.pendingAdmissions.filter((entry) => entry.sessionInstanceId !== event.sessionInstanceId || entry.commandId !== event.commandId);
37442
37548
  syncExecutionProjection(agent2);
37443
- return commit(state, agent2, event.outcome === "failed" ? recoveryEffects(agent2, [record6]) : []);
37549
+ return commit(state, agent2, event.outcome === "failed" ? recoveryEffects(agent2, [record7]) : []);
37444
37550
  }
37445
37551
  case "admission_acknowledged": {
37446
37552
  const existing = state.agents[event.agentId];
@@ -37963,11 +38069,11 @@ function syncExecutionProjection(agent2) {
37963
38069
  agent2.lastDeliverAt = agent2.pendingAdmissions.length > 0 ? Math.max(...agent2.pendingAdmissions.map((entry) => entry.admittedAt)) : null;
37964
38070
  }
37965
38071
  function recoveryEffects(agent2, records) {
37966
- return records.filter((record6) => record6.requeueOnFailure).map((record6) => ({
38072
+ return records.filter((record7) => record7.requeueOnFailure).map((record7) => ({
37967
38073
  type: "requeue_delivery",
37968
38074
  agentId: agent2.agentId,
37969
- message: record6.exactAgentMsg,
37970
- mode: record6.mode
38075
+ message: record7.exactAgentMsg,
38076
+ mode: record7.mode
37971
38077
  }));
37972
38078
  }
37973
38079
  function commit(state, agent2, effects) {
@@ -38008,7 +38114,7 @@ function runtimeModelName(config2) {
38008
38114
  // agent-driver/dist/adapters/antigravity/quota.js
38009
38115
  import { createHash as createHash4, randomBytes as randomBytes6 } from "node:crypto";
38010
38116
  import { readFile } from "node:fs/promises";
38011
- import { homedir as homedir7 } from "node:os";
38117
+ import { homedir as homedir9 } from "node:os";
38012
38118
  import { isAbsolute, join as join13 } from "node:path";
38013
38119
  var PROD = "https://cloudcode-pa.googleapis.com";
38014
38120
  var DAILY = "https://daily-cloudcode-pa.googleapis.com";
@@ -38080,10 +38186,10 @@ function parseAntigravityQuota(value) {
38080
38186
  }
38081
38187
  async function readAntigravityQuota(options = {}) {
38082
38188
  const env = options.env ?? process.env;
38083
- const home = options.home ?? homedir7();
38189
+ const home = options.home ?? homedir9();
38084
38190
  const configuredHome = env.GEMINI_HOME?.replace(/^~(?=[/\\]|$)/, home);
38085
38191
  const root = configuredHome ? isAbsolute(configuredHome) ? configuredHome : join13(process.cwd(), configuredHome) : join13(home, ".gemini");
38086
- const read = options.readCredentialsFile ?? ((path15) => readFile(path15, "utf8"));
38192
+ const read = options.readCredentialsFile ?? ((path16) => readFile(path16, "utf8"));
38087
38193
  let credentials = null;
38088
38194
  let authType;
38089
38195
  let storageUnavailable = false;
@@ -38202,7 +38308,7 @@ async function readAntigravityQuota(options = {}) {
38202
38308
  // agent-driver/dist/provider-quota.js
38203
38309
  import { execFile } from "node:child_process";
38204
38310
  import { readFile as readFile2 } from "node:fs/promises";
38205
- import { homedir as homedir8 } from "node:os";
38311
+ import { homedir as homedir10 } from "node:os";
38206
38312
  import { join as join14 } from "node:path";
38207
38313
  import { promisify } from "node:util";
38208
38314
  import { randomBytes as randomBytes7 } from "node:crypto";
@@ -38231,7 +38337,7 @@ async function claudeCredentials(options) {
38231
38337
  } catch {}
38232
38338
  }
38233
38339
  const env = options.env ?? process.env;
38234
- const root = env.CLAUDE_CONFIG_DIR || join14(options.home ?? homedir8(), ".claude");
38340
+ const root = env.CLAUDE_CONFIG_DIR || join14(options.home ?? homedir10(), ".claude");
38235
38341
  try {
38236
38342
  const value = options.readCredentialsFile ? await options.readCredentialsFile(join14(root, ".credentials.json")) : await readFile2(join14(root, ".credentials.json"), "utf8");
38237
38343
  return parseCredentials(value);
@@ -38320,8 +38426,8 @@ async function readClaudeQuota(options) {
38320
38426
  if (!body || typeof body !== "object") {
38321
38427
  return { status: "error", sourceEpoch: claudeSourceEpoch, code: "invalid_response", retryable: true };
38322
38428
  }
38323
- const record6 = body;
38324
- const limits = ["five_hour", "seven_day", "seven_day_sonnet", "seven_day_opus"].map((key) => claudeLimit(key, record6[key])).filter((limit) => limit !== null);
38429
+ const record7 = body;
38430
+ const limits = ["five_hour", "seven_day", "seven_day_sonnet", "seven_day_opus"].map((key) => claudeLimit(key, record7[key])).filter((limit) => limit !== null);
38325
38431
  if (limits.length === 0) {
38326
38432
  return { status: "error", sourceEpoch: claudeSourceEpoch, code: "invalid_response", retryable: true };
38327
38433
  }
@@ -38396,9 +38502,9 @@ function cliCommandsSection() {
38396
38502
  "### Messaging",
38397
38503
  "",
38398
38504
  `1. \`${CLI} inbox pull\` — fetch unread messages and advance their read waterlines.`,
38399
- `2. \`${CLI} message send --target <ref> --remind-after <0|Nm|Nh> --stdin\` — send to a ` + `channel, DM, or thread. ` + `The body is required through \`--stdin\` and limited to 1 KiB of UTF-8. ` + `Attach uploaded files with \`--attachment <id>\` (repeatable, order matters). ` + `\`--remind-after\` accepts \`0\`, or a whole-number duration from \`1m\` to \`24h\`.`,
38400
- `3. \`${CLI} message attachment upload --target <ref> --file <path>\` — upload a file; ` + `returns an id stable across pending→persisted.`,
38401
- `4. \`${CLI} message attachment download --id <id> [--out <path>]\` — download any ` + `attachment you can see (or your own pending uploads).`,
38505
+ `2. \`${CLI} message send --target <ref> --remind-after <0|Nm|Nh> --stdin\` — send to a ` + `channel, DM, or thread. ` + `The body is required through \`--stdin\` and limited to 1 KiB of UTF-8. ` + `Attach files with \`--attachment <id>\` (repeatable, order matters). ` + `\`--remind-after\` accepts \`0\`, or a whole-number duration from \`1m\` to \`24h\`.`,
38506
+ `3. \`${CLI} message attachment upload --file <path>\` — upload a local file and get a reusable attachment ID.`,
38507
+ `4. \`${CLI} message attachment download --id <id> [--out <path>]\` — download an attachment you can read, including your own unsent uploads.`,
38402
38508
  `5. \`${CLI} message property set --target <full-message-ref> --json <json>\` — add a supported property value to a message.`,
38403
38509
  `6. \`${CLI} message property list --target <full-message-ref>\` — list the message's current properties and supported capabilities.`,
38404
38510
  `7. \`${CLI} message property remove --target <full-message-ref> --json <json>\` — remove a supported property value from a message.`,
@@ -38459,7 +38565,8 @@ function messagingSection() {
38459
38565
  "#### Sending mechanics",
38460
38566
  "",
38461
38567
  `- Send body: use \`${CLI} message send --target <ref> --remind-after T --stdin\` with the ` + "quoted-heredoc form under *Message formatting*.",
38462
- `- Long detail: upload it with \`${CLI} message attachment upload --target <ref> --file <path>.md\`; ` + "add the returned id as `--attachment <id>` on the short stdin send.",
38568
+ `- Long detail: upload it with \`${CLI} message attachment upload --file <path>.md\`; ` + "add the returned id as `--attachment <id>` on the short stdin send.",
38569
+ "- Reuse files: to forward an attachment or send the same file again, pass its existing ID with `--attachment <id>`. " + "Do not download and upload it again. Reuse works across channels, DMs, and threads while you can still read the file. " + "Upload only a new or changed file.",
38463
38570
  `- Cite a specific message: add \`--reply "#37"\` — \`--reply\` takes the \`#N\` seq ` + "(within `--target`) of the message you're answering.",
38464
38571
  "",
38465
38572
  "Reply where the message came from. Post results in the channel that owns the topic. " + "When uncertain, read history (below) or DM the relevant people.",
@@ -38575,7 +38682,19 @@ function utilsSection() {
38575
38682
  "",
38576
38683
  "### Join a new server",
38577
38684
  "",
38578
- `If a message contains a \`/c/invite/...\` link, just run \`${CLI} server join --invite <link>\`. ` + "The server enforces owner-only: it accepts only invites your owner created and rejects the " + "rest with a reason. Safe to attempt without reasoning about who sent it."
38685
+ `If a message contains a \`/c/invite/...\` link, just run \`${CLI} server join --invite <link>\`. ` + "The server enforces owner-only: it accepts only invites your owner created and rejects the " + "rest with a reason. Safe to attempt without reasoning about who sent it.",
38686
+ "",
38687
+ "### Answer questions about Alook itself",
38688
+ "",
38689
+ "Alook frontend source code: https://github.com/alookai/alook/tree/main/src/web/src",
38690
+ "",
38691
+ "Only when a user specifically asks for Alook product guidance or clarification about " + "the product, read the relevant frontend code before answering. " + "Check the page, visible labels, and interaction handlers to verify the steps.",
38692
+ "",
38693
+ "Give clear UI click instructions in the user's language. Start with the page they are on. " + "Use simple positions such as top-left or left sidebar, visible icons, and button labels " + "to identify exactly where to click. Explain each click in order and what appears next. " + "Keep frontend code names and layout terms out of the user's instructions.",
38694
+ "",
38695
+ 'Bad: "Click thisReactButton, on the same layer as serverRailContainer."',
38696
+ "",
38697
+ 'Good: "From the channel chat page in XX server, look at the top-left corner. Click the ' + "Home button with the Alook logo. After Home opens, click My Bots near the top-left " + 'of the left sidebar."'
38579
38698
  ].join(`
38580
38699
  `);
38581
38700
  }
@@ -41021,9 +41140,9 @@ function compactLines(input2) {
41021
41140
  }
41022
41141
  return suffix;
41023
41142
  }
41024
- function isRealDirectory(path15) {
41143
+ function isRealDirectory(path16) {
41025
41144
  try {
41026
- return fs9.lstatSync(path15).isDirectory();
41145
+ return fs9.lstatSync(path16).isDirectory();
41027
41146
  } catch {
41028
41147
  return false;
41029
41148
  }
@@ -42168,15 +42287,15 @@ class MessageReminderScheduler {
42168
42287
  const startedAt = this.now();
42169
42288
  const dueAt = startedAt + input2.remindAfterMs;
42170
42289
  const sentRef = `${input2.channel}#${input2.sentSeq}`;
42171
- const record6 = {
42290
+ const record7 = {
42172
42291
  ...input2,
42173
42292
  sentRef,
42174
42293
  startedAt,
42175
42294
  dueAt,
42176
42295
  timer: undefined
42177
42296
  };
42178
- record6.timer = this.setTimer(() => {
42179
- if (this.reminders.get(key) !== record6)
42297
+ record7.timer = this.setTimer(() => {
42298
+ if (this.reminders.get(key) !== record7)
42180
42299
  return;
42181
42300
  this.reminders.delete(key);
42182
42301
  try {
@@ -42187,8 +42306,8 @@ class MessageReminderScheduler {
42187
42306
  Promise.resolve(delivery).catch(() => {});
42188
42307
  } catch {}
42189
42308
  }, input2.remindAfterMs);
42190
- record6.timer.unref?.();
42191
- this.reminders.set(key, record6);
42309
+ record7.timer.unref?.();
42310
+ this.reminders.set(key, record7);
42192
42311
  return { armed: true, dueAt };
42193
42312
  }
42194
42313
  observe(agentId, channel2, latestSeq) {
@@ -42228,7 +42347,7 @@ class MessageReminderScheduler {
42228
42347
 
42229
42348
  // src/manager/agentDriverHost.ts
42230
42349
  import { randomUUID as randomUUID8 } from "node:crypto";
42231
- import { homedir as homedir9 } from "node:os";
42350
+ import { homedir as homedir11 } from "node:os";
42232
42351
  import { join as join16 } from "node:path";
42233
42352
 
42234
42353
  // src/drivers/gitIdentityEnv.ts
@@ -42354,7 +42473,7 @@ function createDaemonAgentDriverHost(ctx, onRawLine) {
42354
42473
  hostUser: readHostGitIdentity() ?? undefined
42355
42474
  }),
42356
42475
  platformProtected: {
42357
- ALOOK_HOME: process.env.ALOOK_HOME ?? join16(homedir9(), ".alook"),
42476
+ ALOOK_HOME: process.env.ALOOK_HOME ?? join16(homedir11(), ".alook"),
42358
42477
  ALOOK_ID: ctx.agentId,
42359
42478
  ALOOK_CLI: ctx.agentCliPath,
42360
42479
  ALOOK_SERVER_URL: ctx.config.serverUrl,
@@ -42460,7 +42579,7 @@ class DaemonSelfSleepScheduler {
42460
42579
  }
42461
42580
 
42462
42581
  // src/telemetry/dailyTokenUsage.ts
42463
- import { chmod, mkdir, open as open2, readFile as readFile3, rename, rm } from "node:fs/promises";
42582
+ import { chmod, mkdir, open as open3, readFile as readFile3, rename, rm } from "node:fs/promises";
42464
42583
  import { dirname as dirname6, join as join17 } from "node:path";
42465
42584
  import { randomUUID as randomUUID9 } from "node:crypto";
42466
42585
  var TOKEN_USAGE_WINDOW_DAYS = 30;
@@ -42713,7 +42832,7 @@ class DailyTokenUsageStore {
42713
42832
  await mkdir(directory, { recursive: true, mode: 448 });
42714
42833
  const temporary = `${this.filePath}.${randomUUID9()}.tmp`;
42715
42834
  try {
42716
- const file2 = await open2(temporary, "wx", 384);
42835
+ const file2 = await open3(temporary, "wx", 384);
42717
42836
  try {
42718
42837
  await file2.writeFile(JSON.stringify(this.data), { encoding: "utf8" });
42719
42838
  await file2.sync();
@@ -42723,7 +42842,7 @@ class DailyTokenUsageStore {
42723
42842
  await rename(temporary, this.filePath);
42724
42843
  await chmod(this.filePath, 384);
42725
42844
  try {
42726
- const directoryHandle = await open2(directory, "r");
42845
+ const directoryHandle = await open3(directory, "r");
42727
42846
  try {
42728
42847
  await directoryHandle.sync();
42729
42848
  } finally {
@@ -42818,13 +42937,13 @@ function createRuntimeRawLineTap(args) {
42818
42937
  const maxBytes = args.maxBytes ?? RUNTIME_RAW_TRACE_MAX_BYTES;
42819
42938
  const sinks = new Map;
42820
42939
  const warned = new Set;
42821
- const warnOnce = (agentId, path15, operation, error62) => {
42940
+ const warnOnce = (agentId, path16, operation, error62) => {
42822
42941
  if (warned.has(agentId))
42823
42942
  return;
42824
42943
  warned.add(agentId);
42825
42944
  args.logger.warn("runtime raw trace sink failed", {
42826
42945
  agentId,
42827
- path: path15,
42946
+ path: path16,
42828
42947
  operation,
42829
42948
  error: error62 instanceof Error ? error62.message : String(error62)
42830
42949
  });
@@ -42833,10 +42952,10 @@ function createRuntimeRawLineTap(args) {
42833
42952
  if (!args.enabledAgentIds.has(agentId))
42834
42953
  return;
42835
42954
  const encodedAgentId = encodeURIComponent(agentId).replace(/\./g, "%2E");
42836
- const path15 = `${traceDir}/runtime-raw-events-${encodedAgentId}.jsonl`;
42955
+ const path16 = `${traceDir}/runtime-raw-events-${encodedAgentId}.jsonl`;
42837
42956
  const serializedBytes = Buffer.byteLength(line, "utf8") + 1;
42838
42957
  if (serializedBytes > maxBytes) {
42839
- warnOnce(agentId, path15, "oversize", new Error(`raw line is ${serializedBytes} bytes; max is ${maxBytes}`));
42958
+ warnOnce(agentId, path16, "oversize", new Error(`raw line is ${serializedBytes} bytes; max is ${maxBytes}`));
42840
42959
  return;
42841
42960
  }
42842
42961
  let sink = sinks.get(agentId);
@@ -42844,12 +42963,12 @@ function createRuntimeRawLineTap(args) {
42844
42963
  try {
42845
42964
  mkdirSync9(traceDir, { recursive: true });
42846
42965
  } catch (error62) {
42847
- warnOnce(agentId, path15, "mkdir", error62);
42966
+ warnOnce(agentId, path16, "mkdir", error62);
42848
42967
  }
42849
- sink = createRotatingFileSink(path15, maxBytes, {
42968
+ sink = createRotatingFileSink(path16, maxBytes, {
42850
42969
  mode: 384,
42851
42970
  hardMaxBytes: true,
42852
- onError: ({ operation, error: error62 }) => warnOnce(agentId, path15, operation, error62)
42971
+ onError: ({ operation, error: error62 }) => warnOnce(agentId, path16, operation, error62)
42853
42972
  });
42854
42973
  sinks.set(agentId, sink);
42855
42974
  }
@@ -42943,7 +43062,7 @@ async function createDaemon(opts) {
42943
43062
  const log2 = opts.logger ?? createLogger2({ header: "@alook/daemon" });
42944
43063
  const recentContextSdk = createAgentDriverSdk();
42945
43064
  const appendRecentContext = createRecentContextPromptAppender((input2) => recentContextSdk.discoverRecentContext(input2));
42946
- const fallbackBase = (process.env.ALOOK_PROJECT_ROOT || `${homedir10()}/.alook`) + "/daemon";
43065
+ const fallbackBase = (process.env.ALOOK_PROJECT_ROOT || `${homedir12()}/.alook`) + "/daemon";
42947
43066
  const workingDirectoryBase = opts.workingDirectoryBase ?? fallbackBase;
42948
43067
  const workdirFor = (agentId) => `${workingDirectoryBase}/${agentId}`;
42949
43068
  const dailyTokenUsage2 = new DailyTokenUsageStore(workingDirectoryBase);
@@ -44334,7 +44453,7 @@ class CoordinatorError extends Error {
44334
44453
  function defaultFsOps() {
44335
44454
  return {
44336
44455
  randomSuffix: () => randomBytes9(12).toString("hex"),
44337
- open: (path15, flags, mode) => openSync4(path15, flags, mode),
44456
+ open: (path16, flags, mode) => openSync4(path16, flags, mode),
44338
44457
  write: (fd, bytes) => {
44339
44458
  writeSync(fd, bytes);
44340
44459
  },
@@ -44347,10 +44466,10 @@ function defaultFsOps() {
44347
44466
  rename: (from, to) => {
44348
44467
  renameSync6(from, to);
44349
44468
  },
44350
- fsyncDirectory: (path15) => {
44469
+ fsyncDirectory: (path16) => {
44351
44470
  if (process.platform === "win32")
44352
44471
  return;
44353
- const fd = openSync4(path15, "r");
44472
+ const fd = openSync4(path16, "r");
44354
44473
  try {
44355
44474
  fsyncSync2(fd);
44356
44475
  } finally {
@@ -44415,11 +44534,11 @@ function createDiagnosticReportCoordinator(args) {
44415
44534
  args.logger?.warn("diagnostic local artifact invalid", { reportId, code: "local_artifact_invalid" });
44416
44535
  } catch {}
44417
44536
  };
44418
- const removeExact = (path15) => {
44537
+ const removeExact = (path16) => {
44419
44538
  try {
44420
- const stat2 = lstatSync5(path15);
44539
+ const stat2 = lstatSync5(path16);
44421
44540
  if (stat2.isFile() && !stat2.isSymbolicLink())
44422
- unlinkSync6(path15);
44541
+ unlinkSync6(path16);
44423
44542
  } catch {}
44424
44543
  };
44425
44544
  const cleanup = (reportId) => {
@@ -44457,12 +44576,12 @@ function createDiagnosticReportCoordinator(args) {
44457
44576
  checkpoint(sidecar.phase === "collecting" ? "collecting_dir_fsynced" : "ready_dir_fsynced");
44458
44577
  };
44459
44578
  const committedArchive = (reportId) => {
44460
- const path15 = archivePath(reportId);
44579
+ const path16 = archivePath(reportId);
44461
44580
  try {
44462
- const stat2 = lstatSync5(path15);
44581
+ const stat2 = lstatSync5(path16);
44463
44582
  if (!stat2.isFile() || stat2.isSymbolicLink())
44464
44583
  return null;
44465
- const bytes = readFileSync7(path15);
44584
+ const bytes = readFileSync7(path16);
44466
44585
  return { sizeBytes: bytes.byteLength, sha256: createHash7("sha256").update(bytes).digest("hex") };
44467
44586
  } catch {
44468
44587
  return null;
@@ -44587,12 +44706,12 @@ function createDiagnosticReportCoordinator(args) {
44587
44706
  return uploadReady(ready);
44588
44707
  };
44589
44708
  const readSidecar = (reportId) => {
44590
- const path15 = sidecarPath(reportId);
44709
+ const path16 = sidecarPath(reportId);
44591
44710
  try {
44592
- const stat2 = lstatSync5(path15);
44711
+ const stat2 = lstatSync5(path16);
44593
44712
  if (!stat2.isFile() || stat2.isSymbolicLink())
44594
44713
  return null;
44595
- return parseSidecar(JSON.parse(readFileSync7(path15, "utf8")));
44714
+ return parseSidecar(JSON.parse(readFileSync7(path16, "utf8")));
44596
44715
  } catch {
44597
44716
  return null;
44598
44717
  }
@@ -44680,9 +44799,9 @@ function createDiagnosticReportCoordinator(args) {
44680
44799
  }
44681
44800
  // src/diagnostics/httpTransport.ts
44682
44801
  import { Readable as Readable2 } from "node:stream";
44683
- function endpoint(serverUrl, path15) {
44802
+ function endpoint(serverUrl, path16) {
44684
44803
  const base = serverUrl.endsWith("/") ? serverUrl : `${serverUrl}/`;
44685
- return new URL(path15.replace(/^\//, ""), base).toString();
44804
+ return new URL(path16.replace(/^\//, ""), base).toString();
44686
44805
  }
44687
44806
  async function strictOutcome(response, allowed) {
44688
44807
  try {
@@ -44690,11 +44809,11 @@ async function strictOutcome(response, allowed) {
44690
44809
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
44691
44810
  return { kind: "retryable" };
44692
44811
  }
44693
- const record6 = value;
44694
- if (Object.keys(record6).length !== 2 || record6.kind !== "terminal") {
44812
+ const record7 = value;
44813
+ if (Object.keys(record7).length !== 2 || record7.kind !== "terminal") {
44695
44814
  return { kind: "retryable" };
44696
44815
  }
44697
- const status = record6.status;
44816
+ const status = record7.status;
44698
44817
  if (status !== "uploaded" && status !== "failed" || allowed[status] !== response.status) {
44699
44818
  return { kind: "retryable" };
44700
44819
  }
@@ -44746,29 +44865,29 @@ function createDiagnosticHttpTransport(args) {
44746
44865
  // src/cli/daemonUpdate.ts
44747
44866
  import * as crypto4 from "node:crypto";
44748
44867
  import * as fs10 from "node:fs";
44749
- import * as path15 from "node:path";
44868
+ import * as path16 from "node:path";
44750
44869
  import { spawn as spawn2 } from "node:child_process";
44751
44870
  var UPDATE_INTENT_SCHEMA_VERSION = 1;
44752
44871
  var UPDATE_LOG_MAX_BYTES = 512 * 1024;
44753
44872
  var UPDATE_LOG_KEEP_BYTES = 256 * 1024;
44754
44873
  var REQUEST_ID_PATTERN = /^[A-Za-z0-9_-]{16,128}$/;
44755
44874
  function intentPath(baseDir, machineId) {
44756
- return path15.join(daemonDirById(baseDir, machineId), "update-intent.json");
44875
+ return path16.join(daemonDirById(baseDir, machineId), "update-intent.json");
44757
44876
  }
44758
44877
  function updateLogPath(baseDir, machineId) {
44759
- return path15.join(daemonDirById(baseDir, machineId), "update.log");
44878
+ return path16.join(daemonDirById(baseDir, machineId), "update.log");
44760
44879
  }
44761
44880
  function updatePackageMapPath(baseDir, machineId) {
44762
- return path15.join(daemonDirById(baseDir, machineId), "update-package-map.json");
44881
+ return path16.join(daemonDirById(baseDir, machineId), "update-package-map.json");
44763
44882
  }
44764
44883
  function ensurePrivateDir(dir) {
44765
44884
  fs10.mkdirSync(dir, { recursive: true, mode: 448 });
44766
44885
  fs10.chmodSync(dir, 448);
44767
44886
  }
44768
44887
  function writePrivateJsonAtomic(filePath, value) {
44769
- const dir = path15.dirname(filePath);
44888
+ const dir = path16.dirname(filePath);
44770
44889
  ensurePrivateDir(dir);
44771
- const tempPath = path15.join(dir, `.${path15.basename(filePath)}.${process.pid}.${crypto4.randomBytes(8).toString("hex")}.tmp`);
44890
+ const tempPath = path16.join(dir, `.${path16.basename(filePath)}.${process.pid}.${crypto4.randomBytes(8).toString("hex")}.tmp`);
44772
44891
  let fd = fs10.openSync(tempPath, "wx", 384);
44773
44892
  try {
44774
44893
  fs10.writeFileSync(fd, JSON.stringify(value));
@@ -44793,7 +44912,7 @@ function scrub(value) {
44793
44912
  }
44794
44913
  function appendUpdateLog(baseDir, machineId, event, fields2 = {}) {
44795
44914
  const filePath = updateLogPath(baseDir, machineId);
44796
- ensurePrivateDir(path15.dirname(filePath));
44915
+ ensurePrivateDir(path16.dirname(filePath));
44797
44916
  try {
44798
44917
  if (fs10.existsSync(filePath) && fs10.statSync(filePath).size > UPDATE_LOG_MAX_BYTES) {
44799
44918
  const data = fs10.readFileSync(filePath);
@@ -44860,7 +44979,7 @@ function pathEnvironment(env, platform) {
44860
44979
  return entry?.[1];
44861
44980
  }
44862
44981
  function launchFromNpmPath(args) {
44863
- const pathApi = args.platform === "win32" ? path15.win32 : path15.posix;
44982
+ const pathApi = args.platform === "win32" ? path16.win32 : path16.posix;
44864
44983
  if (!pathApi.isAbsolute(args.npmPath) || !args.probe.isFile(args.npmPath))
44865
44984
  return null;
44866
44985
  const extension = pathApi.extname(args.npmPath).toLowerCase();
@@ -44892,7 +45011,7 @@ function resolveNpmLaunchCommand(options = {}) {
44892
45011
  if (launch)
44893
45012
  return launch;
44894
45013
  }
44895
- const pathApi = platform === "win32" ? path15.win32 : path15.posix;
45014
+ const pathApi = platform === "win32" ? path16.win32 : path16.posix;
44896
45015
  const names = platform === "win32" ? ["npm.exe", "npm.cmd", "npm.bat", "npm"] : ["npm"];
44897
45016
  const pathValue = pathEnvironment(env, platform);
44898
45017
  for (const directory of pathValue?.split(pathApi.delimiter) ?? []) {
@@ -44931,7 +45050,7 @@ function readTestPackageMap(baseDir, machineId) {
44931
45050
  for (const [key, value] of Object.entries(parsed)) {
44932
45051
  if (key !== "latest" && !parseReleaseVersion(key))
44933
45052
  throw new Error("invalid daemon update package map key");
44934
- if (typeof value !== "string" || !path15.isAbsolute(value))
45053
+ if (typeof value !== "string" || !path16.isAbsolute(value))
44935
45054
  throw new Error("invalid daemon update package map value");
44936
45055
  result[key] = value;
44937
45056
  }
@@ -45240,7 +45359,7 @@ async function buildRunnerDiagnosticBundle(args) {
45240
45359
  function createDaemonProcessLogger(daemonDir, foreground) {
45241
45360
  fs11.mkdirSync(daemonDir, { recursive: true, mode: 448 });
45242
45361
  fs11.chmodSync(daemonDir, 448);
45243
- const logPath = path16.join(daemonDir, "daemon.log");
45362
+ const logPath = path17.join(daemonDir, "daemon.log");
45244
45363
  let warnedOversize = false;
45245
45364
  const sink = createRotatingFileSink(logPath, DAEMON_LOG_MAX_BYTES, {
45246
45365
  mode: 384,
@@ -45267,7 +45386,7 @@ function createDaemonProcessLogger(daemonDir, foreground) {
45267
45386
  `) : quiet,
45268
45387
  err: foreground ? (line2) => process.stderr.write(line2 + `
45269
45388
  `) : quiet,
45270
- record: (record6) => sink.write(JSON.stringify(record6))
45389
+ record: (record7) => sink.write(JSON.stringify(record7))
45271
45390
  });
45272
45391
  return { logger, logPath, sink };
45273
45392
  }
@@ -45476,16 +45595,16 @@ var LEGACY_DAEMON_ID_PATTERN = /^[a-f0-9]{12}$/;
45476
45595
  var DEFAULT_SERVER_URL = "https://alook.ai";
45477
45596
  var DEFAULT_WS_URL = "wss://alook.ai/api/ws/community-daemon";
45478
45597
  function resolveDefaultBaseDir() {
45479
- const root = process.env.ALOOK_PROJECT_ROOT || path17.join(homedir11(), ".alook");
45480
- return path17.join(root, "daemon");
45598
+ const root = process.env.ALOOK_PROJECT_ROOT || path18.join(homedir13(), ".alook");
45599
+ return path18.join(root, "daemon");
45481
45600
  }
45482
45601
  var DEFAULT_BASE_DIR = resolveDefaultBaseDir();
45483
45602
  var log2 = createLogger2({ header: "@alook/daemon" });
45484
45603
  function daemonsDir(baseDir) {
45485
- return path17.join(baseDir, "daemons");
45604
+ return path18.join(baseDir, "daemons");
45486
45605
  }
45487
45606
  function daemonDirById(baseDir, id3) {
45488
- return path17.join(daemonsDir(baseDir), validateDaemonId(id3));
45607
+ return path18.join(daemonsDir(baseDir), validateDaemonId(id3));
45489
45608
  }
45490
45609
  function validateMachineId(machineId) {
45491
45610
  if (!MACHINE_ID_PATTERN.test(machineId))
@@ -45501,10 +45620,10 @@ function validateDaemonId(id3) {
45501
45620
  return id3;
45502
45621
  }
45503
45622
  function pidfilePathById(baseDir, id3) {
45504
- return path17.join(daemonDirById(baseDir, id3), "daemon.pid");
45623
+ return path18.join(daemonDirById(baseDir, id3), "daemon.pid");
45505
45624
  }
45506
45625
  function statusFilePathById(baseDir, id3) {
45507
- return path17.join(daemonDirById(baseDir, id3), "status.json");
45626
+ return path18.join(daemonDirById(baseDir, id3), "status.json");
45508
45627
  }
45509
45628
  function isProcessAlive(pid) {
45510
45629
  try {
@@ -45564,9 +45683,9 @@ function syncDirectory(dir) {
45564
45683
  }
45565
45684
  }
45566
45685
  function writeExclusive(filePath, value) {
45567
- const dir = path17.dirname(filePath);
45686
+ const dir = path18.dirname(filePath);
45568
45687
  ensurePrivateDir2(dir);
45569
- const tempPath = path17.join(dir, `.${path17.basename(filePath)}.${process.pid}.${crypto5.randomBytes(12).toString("hex")}.tmp`);
45688
+ const tempPath = path18.join(dir, `.${path18.basename(filePath)}.${process.pid}.${crypto5.randomBytes(12).toString("hex")}.tmp`);
45570
45689
  let fd = fs12.openSync(tempPath, "wx", 384);
45571
45690
  try {
45572
45691
  fs12.writeFileSync(fd, JSON.stringify(value));
@@ -45588,9 +45707,9 @@ function writeExclusive(filePath, value) {
45588
45707
  }
45589
45708
  }
45590
45709
  function writePrivateJsonAtomic2(filePath, value) {
45591
- const dir = path17.dirname(filePath);
45710
+ const dir = path18.dirname(filePath);
45592
45711
  ensurePrivateDir2(dir);
45593
- const tempPath = path17.join(dir, `.${path17.basename(filePath)}.${process.pid}.${crypto5.randomBytes(12).toString("hex")}.tmp`);
45712
+ const tempPath = path18.join(dir, `.${path18.basename(filePath)}.${process.pid}.${crypto5.randomBytes(12).toString("hex")}.tmp`);
45594
45713
  let fd = fs12.openSync(tempPath, "wx", 384);
45595
45714
  try {
45596
45715
  fs12.writeFileSync(fd, JSON.stringify(value));
@@ -45677,7 +45796,7 @@ function clearStaleOwnership(filePath, liveError) {
45677
45796
  } catch {}
45678
45797
  }
45679
45798
  function replacementLockPathById(baseDir, machineId) {
45680
- return path17.join(daemonDirById(baseDir, machineId), "daemon.replace.lock");
45799
+ return path18.join(daemonDirById(baseDir, machineId), "daemon.replace.lock");
45681
45800
  }
45682
45801
  function readReplacementLock(filePath) {
45683
45802
  if (!fs12.existsSync(filePath))
@@ -45747,7 +45866,7 @@ function checkReplacementLock(baseDir, machineId, resumeRequestId) {
45747
45866
  }
45748
45867
  function acquireDaemonReplacementLock(args) {
45749
45868
  const lockPath = replacementLockPathById(args.baseDir, args.machineId);
45750
- ensurePrivateDir2(path17.dirname(lockPath));
45869
+ ensurePrivateDir2(path18.dirname(lockPath));
45751
45870
  checkReplacementLock(args.baseDir, args.machineId);
45752
45871
  const lock = {
45753
45872
  pid: process.pid,
@@ -45760,11 +45879,11 @@ function acquireDaemonReplacementLock(args) {
45760
45879
  return { path: lockPath, lock };
45761
45880
  }
45762
45881
  function coarseStartLockPath(baseDir) {
45763
- return path17.join(daemonsDir(baseDir), ".start.lock");
45882
+ return path18.join(daemonsDir(baseDir), ".start.lock");
45764
45883
  }
45765
45884
  function acquireCoarseLock(baseDir, ownerToken) {
45766
45885
  const lf = coarseStartLockPath(baseDir);
45767
- ensurePrivateDir2(path17.dirname(lf));
45886
+ ensurePrivateDir2(path18.dirname(lf));
45768
45887
  secureExistingFile(lf);
45769
45888
  clearStaleOwnership(lf, (pid) => new Error(`another daemon start is in progress on this machine (pid ${pid})`));
45770
45889
  writeExclusive(lf, { pid: process.pid, machineId: "coarse", startedAt: new Date().toISOString(), ownerToken });
@@ -45773,7 +45892,7 @@ function acquireCoarseLock(baseDir, ownerToken) {
45773
45892
  function acquireLaunchLock(baseDir, machineId, ownerToken, resumeRequestId) {
45774
45893
  const daemonDir = daemonDirById(baseDir, machineId);
45775
45894
  ensurePrivateDir2(daemonDir);
45776
- const lockPath = path17.join(daemonDir, "daemon.launch.lock");
45895
+ const lockPath = path18.join(daemonDir, "daemon.launch.lock");
45777
45896
  const finalPath = pidfilePathById(baseDir, machineId);
45778
45897
  checkReplacementLock(baseDir, machineId, resumeRequestId);
45779
45898
  secureExistingFile(lockPath);
@@ -45795,9 +45914,9 @@ function legacyPidfileCandidates(baseDir) {
45795
45914
  const candidates = [];
45796
45915
  for (const entry of fs12.readdirSync(dir, { withFileTypes: true })) {
45797
45916
  if (entry.isDirectory()) {
45798
- candidates.push(path17.join(dir, entry.name, "daemon.pid"));
45917
+ candidates.push(path18.join(dir, entry.name, "daemon.pid"));
45799
45918
  } else if (entry.isFile() && entry.name.endsWith(".pid")) {
45800
- candidates.push(path17.join(dir, entry.name));
45919
+ candidates.push(path18.join(dir, entry.name));
45801
45920
  }
45802
45921
  }
45803
45922
  return candidates;
@@ -45869,7 +45988,7 @@ function daemonList(opts) {
45869
45988
  for (const entry of fs12.readdirSync(dir, { withFileTypes: true })) {
45870
45989
  if (entry.isDirectory() && isDaemonId(entry.name)) {
45871
45990
  const id3 = entry.name;
45872
- pushRow(id3, path17.join(dir, id3, "daemon.pid"), path17.join(dir, id3, "status.json"));
45991
+ pushRow(id3, path18.join(dir, id3, "daemon.pid"), path18.join(dir, id3, "status.json"));
45873
45992
  }
45874
45993
  }
45875
45994
  return results;
@@ -45917,7 +46036,7 @@ function daemonIdsWithStatus(baseDir) {
45917
46036
  return [];
45918
46037
  const ids = [];
45919
46038
  for (const entry of fs12.readdirSync(dir, { withFileTypes: true })) {
45920
- if (entry.isDirectory() && isDaemonId(entry.name) && fs12.existsSync(path17.join(dir, entry.name, "status.json"))) {
46039
+ if (entry.isDirectory() && isDaemonId(entry.name) && fs12.existsSync(path18.join(dir, entry.name, "status.json"))) {
45921
46040
  ids.push(entry.name);
45922
46041
  }
45923
46042
  }
@@ -45980,10 +46099,10 @@ async function stopByPidfile(pf, notFoundHint) {
45980
46099
  }
45981
46100
  async function daemonStop(opts) {
45982
46101
  const baseDir = opts.baseDir || process.env.ALOOK_DATA_DIR || DEFAULT_BASE_DIR;
45983
- await stopByPidfile(path17.join(daemonDirById(baseDir, opts.id), "daemon.pid"), `no daemon with id '${opts.id}' (pidfile not found — check \`alook daemon list\`)`);
46102
+ await stopByPidfile(path18.join(daemonDirById(baseDir, opts.id), "daemon.pid"), `no daemon with id '${opts.id}' (pidfile not found — check \`alook daemon list\`)`);
45984
46103
  }
45985
46104
  function credentialFilePathByMachineId(baseDir, machineId) {
45986
- return path17.join(daemonsDir(baseDir), `${validateMachineId(machineId)}.credential.json`);
46105
+ return path18.join(daemonsDir(baseDir), `${validateMachineId(machineId)}.credential.json`);
45987
46106
  }
45988
46107
  function readCredentialFile(filePath) {
45989
46108
  if (!fs12.existsSync(filePath))
@@ -46010,18 +46129,18 @@ function readCredentialFile(filePath) {
46010
46129
  } catch {}
46011
46130
  return null;
46012
46131
  }
46013
- function writeCredentialFile(filePath, record6) {
46014
- writePrivateJsonAtomic2(filePath, record6);
46132
+ function writeCredentialFile(filePath, record7) {
46133
+ writePrivateJsonAtomic2(filePath, record7);
46015
46134
  }
46016
46135
  function readDaemonLaunchRecord(baseDir, machineId) {
46017
- const record6 = readCredentialFile(credentialFilePathByMachineId(baseDir, machineId));
46018
- if (!record6 || !("schemaVersion" in record6) || record6.schemaVersion !== 1 || !parseReleaseVersion(record6.daemonVersion)) {
46136
+ const record7 = readCredentialFile(credentialFilePathByMachineId(baseDir, machineId));
46137
+ if (!record7 || !("schemaVersion" in record7) || record7.schemaVersion !== 1 || !parseReleaseVersion(record7.daemonVersion)) {
46019
46138
  throw new Error("daemon launch record is missing or requires a manual start upgrade");
46020
46139
  }
46021
- validateMachineId(record6.machineId);
46022
- if (record6.machineId !== machineId)
46140
+ validateMachineId(record7.machineId);
46141
+ if (record7.machineId !== machineId)
46023
46142
  throw new Error("daemon launch record machine mismatch");
46024
- return record6;
46143
+ return record7;
46025
46144
  }
46026
46145
  function findExistingCredentialForBearer(baseDir, bearer) {
46027
46146
  const dir = daemonsDir(baseDir);
@@ -46030,7 +46149,7 @@ function findExistingCredentialForBearer(baseDir, bearer) {
46030
46149
  for (const file2 of fs12.readdirSync(dir)) {
46031
46150
  if (!file2.endsWith(".credential.json"))
46032
46151
  continue;
46033
- const parsed = readCredentialFile(path17.join(dir, file2));
46152
+ const parsed = readCredentialFile(path18.join(dir, file2));
46034
46153
  if (parsed && parsed.credential === bearer)
46035
46154
  return parsed;
46036
46155
  }
@@ -46186,23 +46305,23 @@ async function daemonResume(opts) {
46186
46305
  if (!/^[A-Za-z0-9_-]{16,128}$/.test(opts.requestId))
46187
46306
  throw new Error("invalid replacement request id");
46188
46307
  const baseDir = opts.baseDir || process.env.ALOOK_DATA_DIR || DEFAULT_BASE_DIR;
46189
- const record6 = readDaemonLaunchRecord(baseDir, opts.id);
46308
+ const record7 = readDaemonLaunchRecord(baseDir, opts.id);
46190
46309
  if (false) {}
46191
46310
  await daemonStart({
46192
- machineKey: record6.credential,
46193
- serverUrl: record6.serverUrl,
46194
- wsUrl: record6.wsUrl,
46311
+ machineKey: record7.credential,
46312
+ serverUrl: record7.serverUrl,
46313
+ wsUrl: record7.wsUrl,
46195
46314
  baseDir,
46196
46315
  resumeRequestId: opts.requestId
46197
46316
  });
46198
46317
  }
46199
46318
  async function daemonStartById(opts) {
46200
46319
  const baseDir = opts.baseDir || process.env.ALOOK_DATA_DIR || DEFAULT_BASE_DIR;
46201
- const record6 = readDaemonLaunchRecord(baseDir, opts.id);
46320
+ const record7 = readDaemonLaunchRecord(baseDir, opts.id);
46202
46321
  await daemonStart({
46203
- machineKey: record6.credential,
46204
- serverUrl: record6.serverUrl,
46205
- wsUrl: record6.wsUrl,
46322
+ machineKey: record7.credential,
46323
+ serverUrl: record7.serverUrl,
46324
+ wsUrl: record7.wsUrl,
46206
46325
  baseDir,
46207
46326
  foreground: opts.foreground
46208
46327
  });
@@ -46218,7 +46337,11 @@ async function daemonReconnect(opts, deps = {}) {
46218
46337
  }
46219
46338
  const machineId = validateMachineId(opts.id);
46220
46339
  const baseDir = opts.baseDir || process.env.ALOOK_DATA_DIR || DEFAULT_BASE_DIR;
46221
- const launch = readDaemonLaunchRecord(baseDir, machineId);
46340
+ const launch = readCredentialFile(credentialFilePathByMachineId(baseDir, machineId));
46341
+ if (launch && launch.machineId !== machineId)
46342
+ throw new Error("daemon launch record machine mismatch");
46343
+ const serverUrl = opts.serverUrl ?? (launch && "serverUrl" in launch ? launch.serverUrl : undefined);
46344
+ const wsUrl = opts.wsUrl ?? (launch && "wsUrl" in launch ? launch.wsUrl : undefined);
46222
46345
  const pidPath = pidfilePathById(baseDir, machineId);
46223
46346
  const before = readPidFile(pidPath);
46224
46347
  if (before && (before.machineId !== machineId || !before.startedAt || !before.ownerToken)) {
@@ -46234,6 +46357,9 @@ async function daemonReconnect(opts, deps = {}) {
46234
46357
  throw new Error("daemon ownership changed after reconnect lock acquisition");
46235
46358
  }
46236
46359
  if (owned && (deps.isProcessAlive ?? isProcessAlive)(owned.pid)) {
46360
+ if (!launch) {
46361
+ throw new Error(`cannot safely reconnect a running daemon without its saved credential; run daemon stop ${machineId}, then retry the reconnect command`);
46362
+ }
46237
46363
  await (deps.stopExactDaemonPid ?? stopExactDaemonPid)(owned.pid);
46238
46364
  oldStopped = true;
46239
46365
  removePidFileIfMatches(pidPath, owned);
@@ -46243,8 +46369,8 @@ async function daemonReconnect(opts, deps = {}) {
46243
46369
  try {
46244
46370
  await (deps.start ?? daemonStart)({
46245
46371
  machineKey: opts.machineKey,
46246
- serverUrl: opts.serverUrl ?? launch.serverUrl,
46247
- wsUrl: opts.wsUrl ?? launch.wsUrl,
46372
+ serverUrl,
46373
+ wsUrl,
46248
46374
  baseDir,
46249
46375
  resumeRequestId: requestId,
46250
46376
  expectedMachineId: machineId,
@@ -46256,7 +46382,17 @@ async function daemonReconnect(opts, deps = {}) {
46256
46382
  const canRestoreOldEpoch = !activationAttempted || error62 instanceof PairingActivationError && error62.sessionOutcome === "not_committed";
46257
46383
  if (oldStopped && canRestoreOldEpoch) {
46258
46384
  try {
46259
- await (deps.resume ?? daemonResume)({ id: machineId, baseDir, requestId });
46385
+ if (deps.resume || launch && "daemonVersion" in launch && parseReleaseVersion(launch.daemonVersion)) {
46386
+ await (deps.resume ?? daemonResume)({ id: machineId, baseDir, requestId });
46387
+ } else {
46388
+ await (deps.start ?? daemonStart)({
46389
+ machineKey: launch.credential,
46390
+ serverUrl,
46391
+ wsUrl,
46392
+ baseDir,
46393
+ resumeRequestId: requestId
46394
+ });
46395
+ }
46260
46396
  } catch (rollbackError) {
46261
46397
  throw new AggregateError([error62, rollbackError], "reconnect failed before rotation and the prior daemon could not be resumed");
46262
46398
  }
@@ -46311,7 +46447,7 @@ function waitForReceipt(child, prepared) {
46311
46447
  };
46312
46448
  const configuredTestTimeout = NaN;
46313
46449
  const receiptTimeoutMs = Number.isFinite(configuredTestTimeout) && configuredTestTimeout > 0 ? configuredTestTimeout : START_RECEIPT_TIMEOUT_MS;
46314
- const timeout = setTimeout(() => settle2(new Error(`daemon start timed out; inspect ${path17.join(prepared.daemonDir, "daemon.log")}`)), receiptTimeoutMs);
46450
+ const timeout = setTimeout(() => settle2(new Error(`daemon start timed out; inspect ${path18.join(prepared.daemonDir, "daemon.log")}`)), receiptTimeoutMs);
46315
46451
  child.on("message", (message2) => {
46316
46452
  const accepted = message2;
46317
46453
  if (accepted.type === "daemon:accepted") {
@@ -46330,7 +46466,7 @@ function waitForReceipt(child, prepared) {
46330
46466
  settle2(undefined, receipt);
46331
46467
  });
46332
46468
  child.once("exit", (code2, signal) => {
46333
- settle2(new Error(`daemon child exited before ready (${signal ?? code2}); inspect ${path17.join(prepared.daemonDir, "daemon.log")}`));
46469
+ settle2(new Error(`daemon child exited before ready (${signal ?? code2}); inspect ${path18.join(prepared.daemonDir, "daemon.log")}`));
46334
46470
  });
46335
46471
  child.once("error", (error62) => settle2(error62));
46336
46472
  });
@@ -46892,8 +47028,6 @@ async function cmdAttachmentUpload(opts) {
46892
47028
  const agent2 = agentId(opts);
46893
47029
  const target2 = opts.target;
46894
47030
  const filePath = opts.file;
46895
- if (!target2)
46896
- throw new CliError("message attachment upload: --target <ref> is required");
46897
47031
  if (!filePath)
46898
47032
  throw new CliError("message attachment upload: --file <path> is required");
46899
47033
  const fs13 = await import("fs/promises");
@@ -46930,7 +47064,7 @@ async function cmdAttachmentUpload(opts) {
46930
47064
  }
46931
47065
  const result = await api2.attachmentUpload({
46932
47066
  agentId: agent2,
46933
- target: target2,
47067
+ ...target2 !== undefined ? { target: target2 } : {},
46934
47068
  file: { data: new Uint8Array(bytes), filename, contentType },
46935
47069
  ...thumbnail ? { thumbnail } : {},
46936
47070
  ...width !== undefined ? { width } : {},
@@ -47214,7 +47348,7 @@ function buildProgram(stdin) {
47214
47348
  });
47215
47349
  const attachment = message2.command("attachment").description("attachment operations").exitOverride();
47216
47350
  attachment.configureOutput({ writeOut: () => {}, writeErr: () => {} });
47217
- attachment.command("upload").description("upload a local file as a pending attachment for a future send").option("--target <ref>", "destination (channel, DM, or thread ref)").option("--file <path>", "local file to upload").exitOverride().configureOutput({ writeOut: () => {}, writeErr: () => {} }).action(async function() {
47351
+ attachment.command("upload").description("upload a local file and get its reusable attachment id").option("--target <ref>", "optional legacy target (channel, DM, or thread ref)").option("--file <path>", "local file to upload").exitOverride().configureOutput({ writeOut: () => {}, writeErr: () => {} }).action(async function() {
47218
47352
  const localOpts = this.opts();
47219
47353
  const globalOpts = program.opts();
47220
47354
  const result = await cmdAttachmentUpload({ ...globalOpts, ...localOpts });