@alook/daemon 0.1.31 → 0.1.32

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 +970 -193
  2. package/dist/index.js +821 -116
  3. package/package.json +1 -1
package/dist/cli/index.js CHANGED
@@ -15979,6 +15979,7 @@ var TERMINAL_MEETING_STATUSES = [
15979
15979
  MeetingStatus.COMPLETED,
15980
15980
  MeetingStatus.FAILED
15981
15981
  ];
15982
+ var COMMUNITY_BOT_LIMIT_PER_OWNER = 20;
15982
15983
  var COMMUNITY_BOT_NAME_MIN = 1;
15983
15984
  var COMMUNITY_BOT_NAME_MAX = 32;
15984
15985
  var COMMUNITY_BOT_DESCRIPTION_MAX = 1024;
@@ -16853,6 +16854,13 @@ var HostCommandSchema = exports_external.discriminatedUnion("type", [
16853
16854
  launchId: exports_external.string().min(1),
16854
16855
  unreadNotice: exports_external.unknown()
16855
16856
  }),
16857
+ exports_external.object({
16858
+ type: exports_external.literal("agent:event"),
16859
+ agentId: exports_external.string().min(1),
16860
+ config: exports_external.unknown(),
16861
+ launchId: exports_external.string().min(1),
16862
+ prompt: exports_external.string().min(1).max(32768)
16863
+ }),
16856
16864
  exports_external.object({
16857
16865
  type: exports_external.literal("agent:stop"),
16858
16866
  agentId: exports_external.string().min(1)
@@ -17762,6 +17770,10 @@ var CommunityBotPatchRequestSchema = exports_external.object({
17762
17770
  var CommunityBotAddToServerRequestSchema = exports_external.object({
17763
17771
  botId: exports_external.string().min(1)
17764
17772
  });
17773
+ var CommunityServerOnboardRequestSchema = exports_external.strictObject({
17774
+ botIds: exports_external.array(exports_external.string().min(1).max(128)).min(1).max(COMMUNITY_BOT_LIMIT_PER_OWNER).refine((ids) => new Set(ids).size === ids.length, "botIds must be unique"),
17775
+ wakePrompt: exports_external.string().max(32768).refine((value) => value.trim().length > 0, "wakePrompt is required")
17776
+ });
17765
17777
  var CommunityAgentMessageContentSchema = exports_external.object({ text: exports_external.string().max(MAX_MESSAGE_CONTENT_LENGTH).default("") }).catchall(exports_external.unknown());
17766
17778
  var CommunityAgentSeqSchema = exports_external.number().int().min(0);
17767
17779
  var CommunityAgentPositiveSeqSchema = exports_external.number().int().min(1);
@@ -19557,13 +19569,13 @@ function createProxyServerApi(config2) {
19557
19569
 
19558
19570
  // src/cli/daemonStart.ts
19559
19571
  import * as fs12 from "fs";
19560
- import * as path13 from "path";
19572
+ import * as path17 from "path";
19561
19573
  import * as crypto5 from "crypto";
19562
19574
  import * as os3 from "os";
19563
- import { homedir as homedir6 } from "os";
19575
+ import { homedir as homedir8 } from "os";
19564
19576
 
19565
19577
  // src/discovery.ts
19566
- import * as path9 from "path";
19578
+ import * as path13 from "path";
19567
19579
  import * as fs6 from "fs";
19568
19580
  import { fileURLToPath } from "url";
19569
19581
  // agent-driver/dist/host/default-host.js
@@ -20707,6 +20719,12 @@ function tryParseJsonLine(line) {
20707
20719
  return null;
20708
20720
  }
20709
20721
  }
20722
+ function asRecord(value) {
20723
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
20724
+ }
20725
+ function tryParseJsonRecord(line) {
20726
+ return asRecord(tryParseJsonLine(line));
20727
+ }
20710
20728
 
20711
20729
  // agent-driver/dist/adapters/claude/normalizer.js
20712
20730
  var API_ERROR_RE = /API Error:.*(?:Connection error|\b[45]\d{2}\b)/i;
@@ -21205,6 +21223,241 @@ class ClaudeTurnProtocol {
21205
21223
  }
21206
21224
  }
21207
21225
 
21226
+ // agent-driver/dist/adapters/claude/recent-context.js
21227
+ import { createReadStream as createReadStream2 } from "node:fs";
21228
+ import { homedir } from "node:os";
21229
+ import path7 from "node:path";
21230
+ import { createInterface } from "node:readline";
21231
+
21232
+ // agent-driver/dist/internal/recent-context.js
21233
+ import path6 from "node:path";
21234
+ import { createReadStream } from "node:fs";
21235
+ import { readdir, stat } from "node:fs/promises";
21236
+ function normalizeAbsolutePath(value) {
21237
+ if (typeof value !== "string" || !path6.isAbsolute(value))
21238
+ return null;
21239
+ return path6.normalize(value);
21240
+ }
21241
+ function normalizeModifiedAt(value) {
21242
+ const date5 = value instanceof Date ? value : typeof value === "string" || typeof value === "number" ? new Date(value) : null;
21243
+ if (!date5 || !Number.isFinite(date5.getTime()))
21244
+ return null;
21245
+ return date5.toISOString();
21246
+ }
21247
+ function isValidRecentContextTopK(value) {
21248
+ return Number.isSafeInteger(value) && value >= 0;
21249
+ }
21250
+ function isMissingPathError(error51) {
21251
+ return error51?.code === "ENOENT";
21252
+ }
21253
+ async function readFirstLine(filePath, maxBytes = 65536) {
21254
+ const stream = createReadStream(filePath, { highWaterMark: 1 });
21255
+ const bytes = [];
21256
+ let length = 0;
21257
+ try {
21258
+ for await (const chunk2 of stream) {
21259
+ const byte = Buffer.isBuffer(chunk2) ? chunk2 : Buffer.from(chunk2);
21260
+ if (byte[0] === 10)
21261
+ break;
21262
+ if (length >= maxBytes)
21263
+ return null;
21264
+ bytes.push(byte);
21265
+ length += byte.length;
21266
+ }
21267
+ return length === 0 ? null : Buffer.concat(bytes, length).toString("utf8").replace(/\r$/, "");
21268
+ } catch (error51) {
21269
+ if (isMissingPathError(error51))
21270
+ return null;
21271
+ throw error51;
21272
+ } finally {
21273
+ stream.destroy();
21274
+ }
21275
+ }
21276
+ async function collectJsonlFileCandidates(root, options = {}) {
21277
+ const candidates = [];
21278
+ const readDirectory = options.readDirectory ?? ((directory) => readdir(directory, { withFileTypes: true }));
21279
+ const statPath = options.statPath ?? stat;
21280
+ const visit = async (directory, remainingDepth, includeFiles) => {
21281
+ let entries;
21282
+ try {
21283
+ entries = await readDirectory(directory);
21284
+ } catch (error51) {
21285
+ if (isMissingPathError(error51))
21286
+ return;
21287
+ throw error51;
21288
+ }
21289
+ await Promise.all(entries.map(async (entry) => {
21290
+ const entryPath = path6.join(directory, entry.name);
21291
+ if (entry.isDirectory() && remainingDepth > 0) {
21292
+ await visit(entryPath, remainingDepth - 1, true);
21293
+ } else if (includeFiles && entry.isFile() && entry.name.endsWith(".jsonl")) {
21294
+ try {
21295
+ const metadata = await statPath(entryPath);
21296
+ if (metadata.isFile())
21297
+ candidates.push({ filePath: entryPath, modifiedAt: metadata.mtime });
21298
+ } catch (error51) {
21299
+ if (!isMissingPathError(error51))
21300
+ throw error51;
21301
+ }
21302
+ }
21303
+ }));
21304
+ };
21305
+ await visit(root, options.maxDepth ?? Number.POSITIVE_INFINITY, options.includeRootFiles ?? true);
21306
+ return candidates;
21307
+ }
21308
+ function retainNewest(values, key, value, topK) {
21309
+ const existing = values.get(key);
21310
+ if (existing) {
21311
+ if (value.modifiedAt > existing.modifiedAt)
21312
+ values.set(key, value);
21313
+ return;
21314
+ }
21315
+ if (values.size < topK) {
21316
+ values.set(key, value);
21317
+ return;
21318
+ }
21319
+ let oldest;
21320
+ for (const entry of values) {
21321
+ if (!oldest || entry[1].modifiedAt < oldest[1].modifiedAt)
21322
+ oldest = entry;
21323
+ }
21324
+ if (oldest && value.modifiedAt > oldest[1].modifiedAt) {
21325
+ values.delete(oldest[0]);
21326
+ values.set(key, value);
21327
+ }
21328
+ }
21329
+
21330
+ class RecentContextCollector {
21331
+ request;
21332
+ sessionFileCapability;
21333
+ sessions = new Map;
21334
+ projects = new Map;
21335
+ constructor(request, sessionFileCapability) {
21336
+ this.request = request;
21337
+ this.sessionFileCapability = sessionFileCapability;
21338
+ }
21339
+ add(candidate, target2 = "both") {
21340
+ const projectPath = normalizeAbsolutePath(candidate.projectPath);
21341
+ const modifiedAt = normalizeModifiedAt(candidate.modifiedAt);
21342
+ if (!projectPath || !modifiedAt)
21343
+ return;
21344
+ if (target2 !== "session") {
21345
+ retainNewest(this.projects, projectPath, { projectPath, modifiedAt }, this.request.recentProjectsTopK);
21346
+ }
21347
+ if (target2 === "project" || this.sessionFileCapability !== "supported")
21348
+ return;
21349
+ const sessionFilePath = normalizeAbsolutePath(candidate.sessionFilePath);
21350
+ if (!sessionFilePath)
21351
+ return;
21352
+ retainNewest(this.sessions, sessionFilePath, { sessionFilePath, projectPath, modifiedAt }, this.request.recentSessionFilesTopK);
21353
+ }
21354
+ get satisfied() {
21355
+ const sessionsSatisfied = this.sessionFileCapability === "unavailable" || this.sessions.size >= this.request.recentSessionFilesTopK;
21356
+ return sessionsSatisfied && this.projects.size >= this.request.recentProjectsTopK;
21357
+ }
21358
+ result() {
21359
+ const newestFirst = (left, right) => right.modifiedAt.localeCompare(left.modifiedAt);
21360
+ return {
21361
+ sessionFiles: {
21362
+ capability: this.sessionFileCapability,
21363
+ items: [...this.sessions.values()].sort(newestFirst).slice(0, this.request.recentSessionFilesTopK)
21364
+ },
21365
+ recentProjects: [...this.projects.values()].sort(newestFirst).slice(0, this.request.recentProjectsTopK)
21366
+ };
21367
+ }
21368
+ }
21369
+ function sanitizeRecentContextData(value, request) {
21370
+ if (!value || typeof value !== "object" || Array.isArray(value))
21371
+ return null;
21372
+ const candidate = value;
21373
+ if (!candidate.sessionFiles || typeof candidate.sessionFiles !== "object" || Array.isArray(candidate.sessionFiles)) {
21374
+ return null;
21375
+ }
21376
+ const sessionFiles = candidate.sessionFiles;
21377
+ const capability = sessionFiles.capability;
21378
+ if (capability !== "supported" && capability !== "unavailable" || !Array.isArray(sessionFiles.items)) {
21379
+ return null;
21380
+ }
21381
+ if (!Array.isArray(candidate.recentProjects))
21382
+ return null;
21383
+ const collector = new RecentContextCollector(request, capability);
21384
+ if (capability === "supported") {
21385
+ for (const item of sessionFiles.items) {
21386
+ if (!item || typeof item !== "object" || Array.isArray(item))
21387
+ continue;
21388
+ const record2 = item;
21389
+ collector.add({
21390
+ sessionFilePath: record2.sessionFilePath,
21391
+ projectPath: record2.projectPath,
21392
+ modifiedAt: record2.modifiedAt
21393
+ }, "session");
21394
+ }
21395
+ }
21396
+ for (const item of candidate.recentProjects) {
21397
+ if (!item || typeof item !== "object" || Array.isArray(item))
21398
+ continue;
21399
+ const record2 = item;
21400
+ collector.add({ projectPath: record2.projectPath, modifiedAt: record2.modifiedAt }, "project");
21401
+ }
21402
+ return collector.result();
21403
+ }
21404
+
21405
+ // agent-driver/dist/adapters/claude/recent-context.js
21406
+ async function readClaudeProjectPath(filePath) {
21407
+ const input = createReadStream2(filePath);
21408
+ const lines = createInterface({ input, crlfDelay: Infinity });
21409
+ try {
21410
+ for await (const line of lines) {
21411
+ let record2;
21412
+ try {
21413
+ record2 = JSON.parse(line);
21414
+ } catch {
21415
+ continue;
21416
+ }
21417
+ if (!record2 || typeof record2 !== "object")
21418
+ continue;
21419
+ const cwd = record2.cwd;
21420
+ if (typeof cwd === "string" && path7.isAbsolute(cwd))
21421
+ return cwd;
21422
+ }
21423
+ return null;
21424
+ } catch (error51) {
21425
+ if (isMissingPathError(error51))
21426
+ return null;
21427
+ throw error51;
21428
+ } finally {
21429
+ lines.close();
21430
+ input.destroy();
21431
+ }
21432
+ }
21433
+ async function discoverClaudeRecentContext(request, dependencies = {}) {
21434
+ const collector = new RecentContextCollector(request, "supported");
21435
+ if (collector.satisfied)
21436
+ return collector.result();
21437
+ const projectsRoot = path7.resolve(dependencies.projectsRoot ?? path7.join(process.env.CLAUDE_CONFIG_DIR || path7.join(homedir(), ".claude"), "projects"));
21438
+ const readProjectPath = dependencies.readProjectPath ?? readClaudeProjectPath;
21439
+ const candidates = await collectJsonlFileCandidates(projectsRoot, {
21440
+ includeRootFiles: false,
21441
+ maxDepth: 1,
21442
+ readDirectory: dependencies.readDirectory,
21443
+ statPath: dependencies.statPath
21444
+ });
21445
+ candidates.sort((left, right) => right.modifiedAt.getTime() - left.modifiedAt.getTime());
21446
+ for (const candidate of candidates) {
21447
+ const projectPath = await readProjectPath(candidate.filePath);
21448
+ if (!projectPath)
21449
+ continue;
21450
+ collector.add({
21451
+ sessionFilePath: candidate.filePath,
21452
+ projectPath,
21453
+ modifiedAt: candidate.modifiedAt
21454
+ });
21455
+ if (collector.satisfied)
21456
+ break;
21457
+ }
21458
+ return collector.result();
21459
+ }
21460
+
21208
21461
  // agent-driver/dist/adapters/claude/index.js
21209
21462
  var CLAUDE_MODEL_CATALOG = {
21210
21463
  updateMode: "unsupported",
@@ -21226,6 +21479,9 @@ class ClaudeDriver {
21226
21479
  turnProtocol = new ClaudeTurnProtocol;
21227
21480
  eventNormalizer = new ClaudeEventNormalizer(this.turnProtocol);
21228
21481
  pendingInterrupt;
21482
+ discoverRecentContext(request) {
21483
+ return discoverClaudeRecentContext(request);
21484
+ }
21229
21485
  beginTurn() {
21230
21486
  this.pendingInterrupt = undefined;
21231
21487
  const receipt = this.turnProtocol.beginTurn();
@@ -21489,16 +21745,16 @@ function normalizeFileChangeInput(item) {
21489
21745
  for (const candidate of changePaths) {
21490
21746
  if (typeof candidate !== "string")
21491
21747
  continue;
21492
- const path6 = candidate.trim();
21493
- if (!path6 || seen.has(path6))
21748
+ const path8 = candidate.trim();
21749
+ if (!path8 || seen.has(path8))
21494
21750
  continue;
21495
- seen.add(path6);
21496
- paths.push(path6);
21751
+ seen.add(path8);
21752
+ paths.push(path8);
21497
21753
  }
21498
21754
  if (paths.length === 0 && typeof item?.path === "string") {
21499
- const path6 = item.path.trim();
21500
- if (path6)
21501
- paths.push(path6);
21755
+ const path8 = item.path.trim();
21756
+ if (path8)
21757
+ paths.push(path8);
21502
21758
  }
21503
21759
  return paths.length > 0 ? { path: paths.join(", ") } : {};
21504
21760
  }
@@ -21867,7 +22123,7 @@ class CodexEventNormalizer {
21867
22123
 
21868
22124
  // agent-driver/dist/adapters/codex/home.js
21869
22125
  import * as os from "os";
21870
- import * as path6 from "path";
22126
+ import * as path8 from "path";
21871
22127
  function readConfiguredCodexHome(env) {
21872
22128
  const raw = env.CODEX_HOME;
21873
22129
  return typeof raw === "string" && raw.trim().length > 0 ? raw : null;
@@ -21875,8 +22131,8 @@ function readConfiguredCodexHome(env) {
21875
22131
  function resolveCodexHomeRootFromEnv(env = process.env, opts = {}) {
21876
22132
  const raw = readConfiguredCodexHome(env);
21877
22133
  if (raw)
21878
- return path6.resolve(opts.cwd ?? process.cwd(), raw);
21879
- return path6.join(opts.defaultHomeDir ?? os.homedir(), ".codex");
22134
+ return path8.resolve(opts.cwd ?? process.cwd(), raw);
22135
+ return path8.join(opts.defaultHomeDir ?? os.homedir(), ".codex");
21880
22136
  }
21881
22137
 
21882
22138
  // agent-driver/dist/internal/errors.js
@@ -21969,6 +22225,49 @@ function parsePiModelCatalog(values) {
21969
22225
  return catalogFromIds(ids);
21970
22226
  }
21971
22227
 
22228
+ // agent-driver/dist/adapters/codex/recent-context.js
22229
+ import path9 from "node:path";
22230
+ function isChildSession(payload) {
22231
+ if (payload.parentThreadId != null || payload.parent_thread_id != null)
22232
+ return true;
22233
+ const source = payload.source;
22234
+ if (typeof source === "string")
22235
+ return source.toLowerCase().startsWith("subagent");
22236
+ const sourceRecord = asRecord(source);
22237
+ return sourceRecord != null && (("subagent" in sourceRecord) || ("subAgent" in sourceRecord));
22238
+ }
22239
+ async function discoverCodexRecentContext(request, dependencies = {}) {
22240
+ const collector = new RecentContextCollector(request, "supported");
22241
+ if (collector.satisfied)
22242
+ return collector.result();
22243
+ const sessionsRoot = path9.resolve(dependencies.sessionsRoot ?? path9.join(resolveCodexHomeRootFromEnv(), "sessions"));
22244
+ const readHeader = dependencies.readHeader ?? readFirstLine;
22245
+ const candidates = await collectJsonlFileCandidates(sessionsRoot, {
22246
+ readDirectory: dependencies.readDirectory,
22247
+ statPath: dependencies.statPath
22248
+ });
22249
+ candidates.sort((left, right) => right.modifiedAt.getTime() - left.modifiedAt.getTime());
22250
+ for (const candidate of candidates) {
22251
+ const line = await readHeader(candidate.filePath);
22252
+ if (!line)
22253
+ continue;
22254
+ const header = tryParseJsonRecord(line);
22255
+ if (!header)
22256
+ continue;
22257
+ const payload = asRecord(header.payload);
22258
+ if (header.type !== "session_meta" || !payload || isChildSession(payload))
22259
+ continue;
22260
+ collector.add({
22261
+ sessionFilePath: candidate.filePath,
22262
+ projectPath: payload.cwd,
22263
+ modifiedAt: candidate.modifiedAt
22264
+ });
22265
+ if (collector.satisfied)
22266
+ break;
22267
+ }
22268
+ return collector.result();
22269
+ }
22270
+
21972
22271
  // agent-driver/dist/adapters/codex/index.js
21973
22272
  var SETTINGS_UPDATE_TIMEOUT_MS = 5000;
21974
22273
  var MODEL_LIST_TIMEOUT_MS = 5000;
@@ -21997,6 +22296,9 @@ class CodexDriver {
21997
22296
  eventNormalizer = new CodexEventNormalizer;
21998
22297
  pendingAccountReadRequestIds = new Set;
21999
22298
  requestId = 0;
22299
+ discoverRecentContext(request) {
22300
+ return discoverCodexRecentContext(request);
22301
+ }
22000
22302
  codexHomeRoot = null;
22001
22303
  proc = null;
22002
22304
  pendingInitialPrompt = null;
@@ -23173,6 +23475,196 @@ class CursorAcpLane {
23173
23475
  }
23174
23476
  }
23175
23477
 
23478
+ // agent-driver/dist/internal/discovery-process.js
23479
+ import { StringDecoder } from "node:string_decoder";
23480
+ function toBuffer(chunk2) {
23481
+ if (Buffer.isBuffer(chunk2))
23482
+ return chunk2;
23483
+ if (chunk2 instanceof Uint8Array)
23484
+ return Buffer.from(chunk2.buffer, chunk2.byteOffset, chunk2.byteLength);
23485
+ return Buffer.from(String(chunk2));
23486
+ }
23487
+ async function cleanupProcess(process3, label) {
23488
+ if (process3.pid)
23489
+ await killProcessTree(process3.pid, { graceMs: 250 });
23490
+ else if (process3.exitCode === null && process3.signalCode === null && !process3.kill("SIGTERM")) {
23491
+ throw new Error(`${label} discovery cleanup failed`);
23492
+ }
23493
+ }
23494
+ function onStream(stream, event, listener) {
23495
+ stream?.on?.(event, listener);
23496
+ }
23497
+ function runBoundedDiscoveryProcess(options) {
23498
+ return new Promise((resolve2, reject) => {
23499
+ const decoder = new StringDecoder("utf8");
23500
+ let settled = false;
23501
+ let decoderEnded = false;
23502
+ let outputBytes = 0;
23503
+ const settle = (result, error51) => {
23504
+ if (settled)
23505
+ return;
23506
+ settled = true;
23507
+ clearTimeout(timer);
23508
+ if (!decoderEnded)
23509
+ decoder.end();
23510
+ Promise.resolve().then(() => options.cleanup?.(options.process) ?? cleanupProcess(options.process, options.label)).then(() => error51 ? reject(error51) : resolve2(result), () => reject(error51 ?? new Error(`${options.label} discovery cleanup failed`)));
23511
+ };
23512
+ const control = {
23513
+ get outputBytes() {
23514
+ return outputBytes;
23515
+ },
23516
+ finish: (result) => settle(result),
23517
+ fail: (message2) => settle(undefined, new Error(message2)),
23518
+ flushStdout: () => {
23519
+ if (settled || decoderEnded)
23520
+ return;
23521
+ decoderEnded = true;
23522
+ options.onStdout(decoder.end(), true, control);
23523
+ },
23524
+ write: (line) => {
23525
+ const stdin = options.process.stdin;
23526
+ if (!stdin || stdin.destroyed || stdin.writableEnded || stdin.writable === false) {
23527
+ return control.fail(`${options.label} discovery transport is unavailable`);
23528
+ }
23529
+ try {
23530
+ stdin.write(line);
23531
+ } catch {
23532
+ control.fail(`${options.label} discovery transport write failed`);
23533
+ }
23534
+ }
23535
+ };
23536
+ const addBytes = (chunk2, decode3) => {
23537
+ if (settled)
23538
+ return;
23539
+ const bytes = toBuffer(chunk2);
23540
+ outputBytes += bytes.byteLength;
23541
+ if (outputBytes > options.outputMaxBytes) {
23542
+ control.fail(`${options.label} discovery output exceeded its bound`);
23543
+ } else if (decode3)
23544
+ options.onStdout(decoder.write(bytes), false, control);
23545
+ };
23546
+ const timer = setTimeout(() => control.fail(`${options.label} discovery timed out`), Math.max(1, options.timeoutMs));
23547
+ timer.unref?.();
23548
+ options.process.stdout?.on("data", (chunk2) => addBytes(chunk2, true));
23549
+ options.process.stderr?.on("data", (chunk2) => addBytes(chunk2, false));
23550
+ onStream(options.process.stdout, "end", control.flushStdout);
23551
+ for (const stream of [options.process.stdin, options.process.stdout, options.process.stderr]) {
23552
+ onStream(stream, "error", () => control.fail(`${options.label} discovery transport failed`));
23553
+ }
23554
+ options.process.on("error", () => control.fail(`${options.label} discovery process failed`));
23555
+ options.process.on(options.exitEvent, (code, signal) => options.onExit(code, signal, control));
23556
+ options.onStart?.(control);
23557
+ });
23558
+ }
23559
+
23560
+ // agent-driver/dist/adapters/cursor/recent-context.js
23561
+ var ACP_PROTOCOL_VERSION3 = 1;
23562
+ var AUTH_METHOD_ID3 = "cursor_login";
23563
+ var CURSOR_DISCOVERY_TIMEOUT_MS = 30000;
23564
+ var CURSOR_DISCOVERY_OUTPUT_MAX_BYTES = 4 * 1024 * 1024;
23565
+ async function discoverCursorRecentContext(request, dependencies = {}) {
23566
+ const collector = new RecentContextCollector(request, "unavailable");
23567
+ if (collector.satisfied)
23568
+ return collector.result();
23569
+ const spec = resolveSpawnSpec("cursor-agent", ["acp"], request.command);
23570
+ const processHandle = (dependencies.spawn ?? spawnAgentProcess)(spec.command, spec.args, {
23571
+ cwd: dependencies.cwd ?? process.cwd(),
23572
+ env: { ...process.env, CI: "1" },
23573
+ shell: spec.shell
23574
+ });
23575
+ let buffer = "";
23576
+ let requestId = 0;
23577
+ let expectedId = 0;
23578
+ let expectedMethod = "";
23579
+ const seenCursors = new Set;
23580
+ const requestRpc = (method, params, control) => {
23581
+ expectedId = ++requestId;
23582
+ expectedMethod = method;
23583
+ control.write(`${jsonRpcRequest(method, params, expectedId)}
23584
+ `);
23585
+ };
23586
+ const requestPage = (control, cursor) => requestRpc("session/list", cursor ? { cursor } : {}, control);
23587
+ const onLine = (line, control) => {
23588
+ const message2 = asRecord(tryParseJsonLine(line));
23589
+ if (!message2 || message2.id !== expectedId)
23590
+ return;
23591
+ if (message2.error !== undefined)
23592
+ return control.fail("Cursor discovery request failed");
23593
+ const result = asRecord(message2.result);
23594
+ if (!result)
23595
+ return control.fail("Cursor discovery returned an invalid response");
23596
+ if (expectedMethod === "initialize") {
23597
+ if (result.protocolVersion !== ACP_PROTOCOL_VERSION3) {
23598
+ return control.fail("Cursor discovery protocol is incompatible");
23599
+ }
23600
+ const capabilities = asRecord(result.agentCapabilities);
23601
+ const sessionCapabilities = asRecord(capabilities?.sessionCapabilities);
23602
+ if (sessionCapabilities?.list !== true && !asRecord(sessionCapabilities?.list)) {
23603
+ return control.fail("Cursor session listing is unavailable");
23604
+ }
23605
+ const authMethods = Array.isArray(result.authMethods) ? result.authMethods : [];
23606
+ if (!authMethods.some((method) => asRecord(method)?.id === AUTH_METHOD_ID3)) {
23607
+ return control.fail("Cursor discovery authentication is unavailable");
23608
+ }
23609
+ requestRpc("authenticate", { methodId: AUTH_METHOD_ID3 }, control);
23610
+ return;
23611
+ }
23612
+ if (expectedMethod === "authenticate") {
23613
+ requestPage(control);
23614
+ return;
23615
+ }
23616
+ if (expectedMethod !== "session/list")
23617
+ return control.fail("Cursor discovery state is invalid");
23618
+ const sessions = Array.isArray(result.sessions) ? result.sessions : Array.isArray(result.data) ? result.data : [];
23619
+ for (const value of sessions) {
23620
+ const session2 = asRecord(value);
23621
+ if (!session2)
23622
+ continue;
23623
+ collector.add({ projectPath: session2.cwd, modifiedAt: session2.updatedAt });
23624
+ if (collector.satisfied)
23625
+ return control.finish(collector.result());
23626
+ }
23627
+ const nextCursor = typeof result.nextCursor === "string" && result.nextCursor ? result.nextCursor : undefined;
23628
+ if (!nextCursor)
23629
+ return control.finish(collector.result());
23630
+ if (seenCursors.has(nextCursor))
23631
+ return control.fail("Cursor discovery cursor repeated");
23632
+ seenCursors.add(nextCursor);
23633
+ requestPage(control, nextCursor);
23634
+ };
23635
+ return runBoundedDiscoveryProcess({
23636
+ process: processHandle,
23637
+ label: "Cursor",
23638
+ timeoutMs: dependencies.timeoutMs ?? CURSOR_DISCOVERY_TIMEOUT_MS,
23639
+ outputMaxBytes: dependencies.outputMaxBytes ?? CURSOR_DISCOVERY_OUTPUT_MAX_BYTES,
23640
+ cleanup: dependencies.cleanup,
23641
+ exitEvent: "exit",
23642
+ onStdout: (text2, final, control) => {
23643
+ buffer += text2;
23644
+ const lines = buffer.split(`
23645
+ `);
23646
+ buffer = lines.pop() ?? "";
23647
+ for (const line of lines)
23648
+ if (line.trim())
23649
+ onLine(line, control);
23650
+ if (final && buffer.trim()) {
23651
+ const line = buffer;
23652
+ buffer = "";
23653
+ onLine(line, control);
23654
+ }
23655
+ },
23656
+ onExit: (_code, _signal, control) => control.fail("Cursor discovery process exited early"),
23657
+ onStart: (control) => requestRpc("initialize", {
23658
+ protocolVersion: ACP_PROTOCOL_VERSION3,
23659
+ clientCapabilities: {
23660
+ fs: { readTextFile: false, writeTextFile: false },
23661
+ terminal: false
23662
+ },
23663
+ clientInfo: { name: "alook-agent-driver-discovery", version: "0.1.31" }
23664
+ }, control)
23665
+ });
23666
+ }
23667
+
23176
23668
  // agent-driver/dist/adapters/cursor/index.js
23177
23669
  class CursorDriver {
23178
23670
  catalogProbe;
@@ -23184,6 +23676,9 @@ class CursorDriver {
23184
23676
  wakeStart: "immediate",
23185
23677
  terminalOwnership: "transport_request"
23186
23678
  };
23679
+ discoverRecentContext(request) {
23680
+ return discoverCursorRecentContext(request);
23681
+ }
23187
23682
  constructor(catalogProbe = probeCursorAcpCatalog) {
23188
23683
  this.catalogProbe = catalogProbe;
23189
23684
  }
@@ -23678,7 +24173,7 @@ class OpenCodeServiceLane {
23678
24173
  "/api/session/{sessionID}/permission/{requestID}/reply",
23679
24174
  "/api/event"
23680
24175
  ];
23681
- if (!paths || required2.some((path7) => !record4(paths[path7]))) {
24176
+ if (!paths || required2.some((path10) => !record4(paths[path10]))) {
23682
24177
  throw new OpenCodeIncompatibleError("Installed OpenCode service is missing required v2 session capabilities");
23683
24178
  }
23684
24179
  }
@@ -23736,8 +24231,8 @@ class OpenCodeServiceLane {
23736
24231
  const controller = new AbortController;
23737
24232
  this.durableAbort = controller;
23738
24233
  try {
23739
- const path7 = `/api/session/${encodeURIComponent(this.sessionId)}/event?after=${this.lastDurableSeq}`;
23740
- const response = await this.openStream(path7, controller, "durable event stream");
24234
+ const path10 = `/api/session/${encodeURIComponent(this.sessionId)}/event?after=${this.lastDurableSeq}`;
24235
+ const response = await this.openStream(path10, controller, "durable event stream");
23741
24236
  await this.catchUpHistory(true);
23742
24237
  if (!this.isIdentity(identity))
23743
24238
  return;
@@ -23811,12 +24306,12 @@ class OpenCodeServiceLane {
23811
24306
  return;
23812
24307
  this.protocolFailure(`OpenCode ${kind} stream stopped unexpectedly`, error51);
23813
24308
  }
23814
- async openStream(path7, lifecycle, operation) {
24309
+ async openStream(path10, lifecycle, operation) {
23815
24310
  const deadline = new AbortController;
23816
24311
  const timeout = setTimeout(() => deadline.abort(), this.options.requestTimeoutMs ?? REQUEST_TIMEOUT_MS);
23817
24312
  timeout.unref?.();
23818
24313
  try {
23819
- const response = await this.fetchFn(`${this.baseUrl}${path7}`, {
24314
+ const response = await this.fetchFn(`${this.baseUrl}${path10}`, {
23820
24315
  method: "GET",
23821
24316
  headers: this.headers({ accept: "text/event-stream" }),
23822
24317
  signal: AbortSignal.any([lifecycle.signal, deadline.signal])
@@ -24243,8 +24738,8 @@ class OpenCodeServiceLane {
24243
24738
  turnOwner: root.receipt
24244
24739
  });
24245
24740
  }
24246
- async requestNoContent(path7, method, body, operation) {
24247
- const response = await this.fetchWithTimeout(path7, {
24741
+ async requestNoContent(path10, method, body, operation) {
24742
+ const response = await this.fetchWithTimeout(path10, {
24248
24743
  method,
24249
24744
  ...body ? {
24250
24745
  headers: { "content-type": "application/json" },
@@ -24254,7 +24749,7 @@ class OpenCodeServiceLane {
24254
24749
  if (!response.ok)
24255
24750
  throw new OpenCodeHttpError(response.status, operation);
24256
24751
  }
24257
- async fetchWithTimeout(path7, init, operation, timeoutMs = this.options.requestTimeoutMs ?? REQUEST_TIMEOUT_MS) {
24752
+ async fetchWithTimeout(path10, init, operation, timeoutMs = this.options.requestTimeoutMs ?? REQUEST_TIMEOUT_MS) {
24258
24753
  if (this.stopping)
24259
24754
  throw new Error("OpenCode service lane is stopping");
24260
24755
  const controller = new AbortController;
@@ -24262,7 +24757,7 @@ class OpenCodeServiceLane {
24262
24757
  const timer = setTimeout(() => controller.abort(), timeoutMs);
24263
24758
  timer.unref?.();
24264
24759
  try {
24265
- return await this.fetchFn(`${this.baseUrl}${path7}`, {
24760
+ return await this.fetchFn(`${this.baseUrl}${path10}`, {
24266
24761
  ...init,
24267
24762
  headers: this.headers(init.headers),
24268
24763
  signal: controller.signal
@@ -24274,7 +24769,7 @@ class OpenCodeServiceLane {
24274
24769
  this.requestControllers.delete(controller);
24275
24770
  }
24276
24771
  }
24277
- async fetchJsonWithTimeout(path7, init, operation, timeoutMs = this.options.requestTimeoutMs ?? REQUEST_TIMEOUT_MS) {
24772
+ async fetchJsonWithTimeout(path10, init, operation, timeoutMs = this.options.requestTimeoutMs ?? REQUEST_TIMEOUT_MS) {
24278
24773
  if (this.stopping)
24279
24774
  throw new OpenCodeStoppedError("OpenCode service lane is stopping");
24280
24775
  const controller = new AbortController;
@@ -24286,7 +24781,7 @@ class OpenCodeServiceLane {
24286
24781
  }, timeoutMs);
24287
24782
  timer.unref?.();
24288
24783
  try {
24289
- const response = await this.fetchFn(`${this.baseUrl}${path7}`, {
24784
+ const response = await this.fetchFn(`${this.baseUrl}${path10}`, {
24290
24785
  ...init,
24291
24786
  headers: this.headers(init.headers),
24292
24787
  signal: controller.signal
@@ -24379,6 +24874,75 @@ class OpenCodeServiceLane {
24379
24874
  }
24380
24875
  }
24381
24876
 
24877
+ // agent-driver/dist/adapters/opencode/recent-context.js
24878
+ var OPENCODE_DISCOVERY_TIMEOUT_MS = 15000;
24879
+ var OPENCODE_DISCOVERY_OUTPUT_MAX_BYTES = 4 * 1024 * 1024;
24880
+ function collectCommandOutput(command, args, shell, dependencies, timeoutMs, outputMaxBytes) {
24881
+ const processHandle = (dependencies.spawn ?? spawnAgentProcess)(command, args, {
24882
+ cwd: dependencies.cwd ?? process.cwd(),
24883
+ env: { ...process.env, CI: "1" },
24884
+ shell,
24885
+ stdin: "ignore"
24886
+ });
24887
+ let output = "";
24888
+ return runBoundedDiscoveryProcess({
24889
+ process: processHandle,
24890
+ label: "OpenCode",
24891
+ timeoutMs,
24892
+ outputMaxBytes,
24893
+ cleanup: dependencies.cleanup,
24894
+ exitEvent: "close",
24895
+ onStdout: (text2) => {
24896
+ output += text2;
24897
+ },
24898
+ onExit: (code, _signal, control) => {
24899
+ if (code !== 0)
24900
+ return control.fail("OpenCode session listing failed");
24901
+ control.flushStdout();
24902
+ control.finish({ output, outputBytes: control.outputBytes });
24903
+ }
24904
+ });
24905
+ }
24906
+ async function discoverOpenCodeRecentContext(request, dependencies = {}) {
24907
+ const collector = new RecentContextCollector(request, "unavailable");
24908
+ if (collector.satisfied)
24909
+ return collector.result();
24910
+ const startedAt = Date.now();
24911
+ const timeoutMs = dependencies.timeoutMs ?? OPENCODE_DISCOVERY_TIMEOUT_MS;
24912
+ let remainingOutputBytes = dependencies.outputMaxBytes ?? OPENCODE_DISCOVERY_OUTPUT_MAX_BYTES;
24913
+ let maxCount = Math.max(1, Math.min(Number.MAX_SAFE_INTEGER, request.recentProjectsTopK * 10));
24914
+ while (!collector.satisfied) {
24915
+ const remainingTimeoutMs = timeoutMs - (Date.now() - startedAt);
24916
+ if (remainingTimeoutMs <= 0)
24917
+ throw new Error("OpenCode discovery timed out");
24918
+ const spec = resolveSpawnSpec("opencode", ["session", "list", "--format", "json", "--max-count", String(maxCount), "--pure"], request.command);
24919
+ const commandOutput = await collectCommandOutput(spec.command, spec.args, spec.shell, dependencies, remainingTimeoutMs, remainingOutputBytes);
24920
+ remainingOutputBytes -= commandOutput.outputBytes;
24921
+ let parsed;
24922
+ try {
24923
+ parsed = JSON.parse(commandOutput.output);
24924
+ } catch {
24925
+ throw new Error("OpenCode session listing returned invalid JSON");
24926
+ }
24927
+ if (!Array.isArray(parsed))
24928
+ throw new Error("OpenCode session listing returned an invalid response");
24929
+ for (const value of parsed) {
24930
+ const session2 = asRecord(value);
24931
+ if (!session2)
24932
+ continue;
24933
+ const modifiedAt = session2.updated ?? session2.updatedAt;
24934
+ collector.add({ projectPath: session2.directory, modifiedAt });
24935
+ }
24936
+ if (collector.satisfied || parsed.length < maxCount)
24937
+ break;
24938
+ const nextMaxCount = Math.min(Number.MAX_SAFE_INTEGER, maxCount * 2);
24939
+ if (nextMaxCount === maxCount)
24940
+ throw new Error("OpenCode session listing could not prove the requested Top-K");
24941
+ maxCount = nextMaxCount;
24942
+ }
24943
+ return collector.result();
24944
+ }
24945
+
24382
24946
  // agent-driver/dist/adapters/opencode/index.js
24383
24947
  function createOpenCodeMessageId() {
24384
24948
  return `msg_${randomBytes3(16).toString("hex")}`;
@@ -24397,6 +24961,9 @@ class OpenCodeDriver {
24397
24961
  constructor(outputProbe = probeCommandOutput) {
24398
24962
  this.outputProbe = outputProbe;
24399
24963
  }
24964
+ discoverRecentContext(request) {
24965
+ return discoverOpenCodeRecentContext(request);
24966
+ }
24400
24967
  probe(command) {
24401
24968
  const result = probeCliRuntime("opencode", {}, command);
24402
24969
  if (result.status !== "healthy")
@@ -24443,8 +25010,8 @@ class OpenCodeDriver {
24443
25010
  // agent-driver/dist/adapters/pi/index.js
24444
25011
  import { createRequire as createRequire2 } from "module";
24445
25012
  import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync3, realpathSync } from "fs";
24446
- import { homedir as homedir2 } from "os";
24447
- import * as path8 from "path";
25013
+ import { homedir as homedir4 } from "os";
25014
+ import * as path12 from "path";
24448
25015
 
24449
25016
  // agent-driver/dist/controller/sdk-host.js
24450
25017
  import { EventEmitter as EventEmitter4 } from "events";
@@ -24559,7 +25126,7 @@ class SdkLane {
24559
25126
 
24560
25127
  // agent-driver/dist/adapters/pi/sessionDeps.js
24561
25128
  import { readFileSync as readFileSync2 } from "fs";
24562
- import * as path7 from "path";
25129
+ import * as path10 from "path";
24563
25130
  import { pathToFileURL } from "url";
24564
25131
  var PI_SDK_PACKAGE_NAME = "@earendil-works/pi-coding-agent";
24565
25132
  var cachedSdkPromise = null;
@@ -24568,9 +25135,9 @@ async function importPiSdkFromGlobalInstall() {
24568
25135
  if (!dir) {
24569
25136
  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`);
24570
25137
  }
24571
- const pkg = JSON.parse(readFileSync2(path7.join(dir, "package.json"), "utf-8"));
25138
+ const pkg = JSON.parse(readFileSync2(path10.join(dir, "package.json"), "utf-8"));
24572
25139
  const entry = pkg.exports?.["."]?.import ?? pkg.main ?? "./dist/index.js";
24573
- const entryPath = path7.join(dir, entry);
25140
+ const entryPath = path10.join(dir, entry);
24574
25141
  const barrel = await import(pathToFileURL(entryPath).href);
24575
25142
  return withSessionDirHelper(barrel, entryPath);
24576
25143
  }
@@ -24578,7 +25145,7 @@ async function withSessionDirHelper(barrel, entryPath) {
24578
25145
  if (typeof barrel.getDefaultSessionDir === "function")
24579
25146
  return barrel;
24580
25147
  try {
24581
- const deepPath = path7.join(path7.dirname(entryPath), "core", "session-manager.js");
25148
+ const deepPath = path10.join(path10.dirname(entryPath), "core", "session-manager.js");
24582
25149
  const deep = await import(pathToFileURL(deepPath).href);
24583
25150
  if (typeof deep.getDefaultSessionDir !== "function")
24584
25151
  return barrel;
@@ -24658,6 +25225,51 @@ function createPiSessionDependencies(ctx, loadSdk = loadPiSdkModule) {
24658
25225
  };
24659
25226
  }
24660
25227
 
25228
+ // agent-driver/dist/adapters/pi/recent-context.js
25229
+ import { homedir as homedir3 } from "node:os";
25230
+ import path11 from "node:path";
25231
+ function expandTildePath(value) {
25232
+ if (value === "~")
25233
+ return homedir3();
25234
+ if (value.startsWith("~/"))
25235
+ return path11.join(homedir3(), value.slice(2));
25236
+ return value;
25237
+ }
25238
+ async function discoverPiRecentContext(request, dependencies = {}) {
25239
+ const collector = new RecentContextCollector(request, "supported");
25240
+ if (collector.satisfied)
25241
+ return collector.result();
25242
+ const customSessionDirectory = process.env.PI_CODING_AGENT_SESSION_DIR;
25243
+ const sessionsRoot = path11.resolve(expandTildePath(dependencies.sessionsRoot ?? customSessionDirectory ?? path11.join(process.env.PI_CODING_AGENT_DIR || path11.join(homedir3(), ".pi", "agent"), "sessions")));
25244
+ const scanDirectSessions = dependencies.sessionsRoot == null && customSessionDirectory != null;
25245
+ const readHeader = dependencies.readHeader ?? readFirstLine;
25246
+ const candidates = await collectJsonlFileCandidates(sessionsRoot, {
25247
+ includeRootFiles: scanDirectSessions,
25248
+ maxDepth: 1,
25249
+ readDirectory: dependencies.readDirectory,
25250
+ statPath: dependencies.statPath
25251
+ });
25252
+ candidates.sort((left, right) => right.modifiedAt.getTime() - left.modifiedAt.getTime());
25253
+ for (const candidate of candidates) {
25254
+ const line = await readHeader(candidate.filePath);
25255
+ if (!line)
25256
+ continue;
25257
+ const header = tryParseJsonRecord(line);
25258
+ if (!header)
25259
+ continue;
25260
+ if (header.type !== "session" || header.parentSession != null)
25261
+ continue;
25262
+ collector.add({
25263
+ sessionFilePath: candidate.filePath,
25264
+ projectPath: header.cwd,
25265
+ modifiedAt: candidate.modifiedAt
25266
+ });
25267
+ if (collector.satisfied)
25268
+ break;
25269
+ }
25270
+ return collector.result();
25271
+ }
25272
+
24661
25273
  // agent-driver/dist/adapters/pi/index.js
24662
25274
  var PI_SDK_PACKAGE_NAME2 = "@earendil-works/pi-coding-agent";
24663
25275
  var PI_MODEL_PROBE_TIMEOUT_MS = 5000;
@@ -24676,15 +25288,15 @@ function resolvePiSdkPackageDir(deps = {}) {
24676
25288
  if (!binPath)
24677
25289
  return;
24678
25290
  try {
24679
- let dir = path8.dirname(realpathSync(binPath));
25291
+ let dir = path12.dirname(realpathSync(binPath));
24680
25292
  const MAX_DEPTH = 8;
24681
25293
  for (let i = 0;i < MAX_DEPTH; i++) {
24682
- if (isPiSdkPackageJson(path8.join(dir, "package.json")))
25294
+ if (isPiSdkPackageJson(path12.join(dir, "package.json")))
24683
25295
  return dir;
24684
- const siblingDir = path8.join(dir, "node_modules", PI_SDK_PACKAGE_NAME2);
24685
- if (isPiSdkPackageJson(path8.join(siblingDir, "package.json")))
25296
+ const siblingDir = path12.join(dir, "node_modules", PI_SDK_PACKAGE_NAME2);
25297
+ if (isPiSdkPackageJson(path12.join(siblingDir, "package.json")))
24686
25298
  return siblingDir;
24687
- const parent = path8.dirname(dir);
25299
+ const parent = path12.dirname(dir);
24688
25300
  if (parent === dir)
24689
25301
  break;
24690
25302
  dir = parent;
@@ -24701,21 +25313,21 @@ function findPiSessionFile(sessionDir, sessionId) {
24701
25313
  }
24702
25314
  const suffix = `_${sessionId}.jsonl`;
24703
25315
  const match = entries.find((entry) => entry.endsWith(suffix));
24704
- return match ? path8.join(sessionDir, match) : null;
25316
+ return match ? path12.join(sessionDir, match) : null;
24705
25317
  }
24706
25318
  function resolvePiSessionDir(sdk, cwd) {
24707
25319
  if (typeof sdk.getDefaultSessionDir === "function")
24708
25320
  return sdk.getDefaultSessionDir(cwd);
24709
- const agentDir = typeof sdk.getAgentDir === "function" ? sdk.getAgentDir() : path8.join(homedir2(), ".pi", "agent");
24710
- const encoded = `--${path8.resolve(cwd).replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--`;
24711
- return path8.join(agentDir, "sessions", encoded);
25321
+ const agentDir = typeof sdk.getAgentDir === "function" ? sdk.getAgentDir() : path12.join(homedir4(), ".pi", "agent");
25322
+ const encoded = `--${path12.resolve(cwd).replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--`;
25323
+ return path12.join(agentDir, "sessions", encoded);
24712
25324
  }
24713
25325
  function resolvePiSdkVersionFromPath(deps = {}) {
24714
25326
  const dir = resolvePiSdkPackageDir(deps);
24715
25327
  if (!dir)
24716
25328
  return;
24717
25329
  try {
24718
- const pkg = JSON.parse(readFileSync3(path8.join(dir, "package.json"), "utf-8"));
25330
+ const pkg = JSON.parse(readFileSync3(path12.join(dir, "package.json"), "utf-8"));
24719
25331
  return pkg.version;
24720
25332
  } catch {
24721
25333
  return;
@@ -24819,6 +25431,9 @@ class PiDriver {
24819
25431
  };
24820
25432
  sessionId = null;
24821
25433
  terminalSequence = 0;
25434
+ discoverRecentContext(request) {
25435
+ return discoverPiRecentContext(request);
25436
+ }
24822
25437
  constructor(dependenciesFor = createPiSessionDependencies, loadSdk = loadPiSdkModule, readVersion = readPiSdkVersion) {
24823
25438
  this.dependenciesFor = dependenciesFor;
24824
25439
  this.loadSdk = loadSdk;
@@ -24964,6 +25579,9 @@ function assertAdapterCompatibility(registrationId, registeredCapabilities, adap
24964
25579
  if (typeof candidate[method] !== "function")
24965
25580
  throw new Error(`Adapter ${registrationId} is missing ${method}()`);
24966
25581
  }
25582
+ if (candidate.discoverRecentContext !== undefined && typeof candidate.discoverRecentContext !== "function") {
25583
+ throw new Error(`Adapter ${registrationId} has an invalid discoverRecentContext()`);
25584
+ }
24967
25585
  const instruction = candidate.instructionDelivery;
24968
25586
  if (!instruction || instruction.kind !== "native" && instruction.kind !== "workspace_file") {
24969
25587
  throw new Error(`Adapter ${registrationId} has an invalid instructionDelivery declaration`);
@@ -25185,8 +25803,8 @@ function ensureSymlinks(workDir, canonical = CANONICAL_FILE, aliases = SYMLINK_A
25185
25803
  continue;
25186
25804
  const aliasPath = join8(workDir, alias2);
25187
25805
  try {
25188
- const stat = lstatSync(aliasPath);
25189
- if (stat.isSymbolicLink()) {
25806
+ const stat2 = lstatSync(aliasPath);
25807
+ if (stat2.isSymbolicLink()) {
25190
25808
  const target2 = readlinkSync(aliasPath);
25191
25809
  if (target2 === canonical)
25192
25810
  continue;
@@ -25349,6 +25967,7 @@ class LogicalAgentSession {
25349
25967
  steeringDeliveries = new Set;
25350
25968
  laneAdmissionTail = Promise.resolve();
25351
25969
  laneAdmissionPending = 0;
25970
+ toolBoundaryOpen = true;
25352
25971
  toolBoundaryFlushDisabled = false;
25353
25972
  safeBoundaryFlush;
25354
25973
  safeBoundaryDelivery;
@@ -25629,6 +26248,8 @@ class LogicalAgentSession {
25629
26248
  this.turnError = undefined;
25630
26249
  this.interruptedTurnId = undefined;
25631
26250
  this.processTurnEnded = false;
26251
+ this.toolBoundaryOpen = true;
26252
+ this.toolBoundaryFlushDisabled = false;
25632
26253
  this.state = "starting";
25633
26254
  const generation = this.lifecycleGeneration;
25634
26255
  const text2 = messages.map((message2) => message2.text).join(`
@@ -25861,6 +26482,7 @@ class LogicalAgentSession {
25861
26482
  }
25862
26483
  if (!this.startToolUse(event.callId))
25863
26484
  return;
26485
+ this.toolBoundaryOpen = false;
25864
26486
  const startedCallId = this.toolCallId(event.callId);
25865
26487
  this.emit({
25866
26488
  type: "tool_started",
@@ -25877,6 +26499,7 @@ class LogicalAgentSession {
25877
26499
  }
25878
26500
  if (!this.finishToolUse(event.callId))
25879
26501
  return;
26502
+ this.toolBoundaryOpen = true;
25880
26503
  const finishedCallId = this.toolCallId(event.callId);
25881
26504
  this.emit({
25882
26505
  type: "tool_finished",
@@ -25884,7 +26507,7 @@ class LogicalAgentSession {
25884
26507
  ...finishedCallId ? { callId: finishedCallId } : {},
25885
26508
  name: event.name
25886
26509
  });
25887
- if (this.outstandingToolUseCount() === 0 && !this.toolBoundaryFlushDisabled)
26510
+ if (!this.toolBoundaryFlushDisabled)
25888
26511
  this.flushSafeBoundaryQueue();
25889
26512
  return;
25890
26513
  case "compaction_started":
@@ -26030,6 +26653,7 @@ class LogicalAgentSession {
26030
26653
  this.clearOutstandingToolUses();
26031
26654
  this.compacting = false;
26032
26655
  this.reviewing = false;
26656
+ this.toolBoundaryOpen = true;
26033
26657
  this.toolBoundaryFlushDisabled = false;
26034
26658
  this.state = "idle";
26035
26659
  if (this.adapter.execution.lifetime === "turn") {
@@ -26051,7 +26675,7 @@ class LogicalAgentSession {
26051
26675
  return this.safeBoundaryFlush;
26052
26676
  }
26053
26677
  canFlushSafeBoundaryQueue() {
26054
- return this.state === "working" && this.behavior.midTurnDelivery === "safe_boundary_queue" && this.outstandingToolUseCount() === 0 && !this.compacting && !this.reviewing && this.activeTurn !== undefined && this.lane !== null && this.queued.length > 0;
26678
+ return this.state === "working" && this.behavior.midTurnDelivery === "safe_boundary_queue" && this.toolBoundaryOpen && !this.toolBoundaryFlushDisabled && !this.compacting && !this.reviewing && this.activeTurn !== undefined && this.lane !== null && this.queued.length > 0;
26055
26679
  }
26056
26680
  async drainSafeBoundaryQueue() {
26057
26681
  while (this.canFlushSafeBoundaryQueue()) {
@@ -26566,6 +27190,57 @@ function createAgentDriverSdkWithRegistry(options) {
26566
27190
  const registry2 = options.registry;
26567
27191
  return {
26568
27192
  backendIds: registry2.backendIds,
27193
+ async discoverRecentContext(input) {
27194
+ if (!isValidRecentContextTopK(input.recentSessionFilesTopK) || !isValidRecentContextTopK(input.recentProjectsTopK)) {
27195
+ return {
27196
+ ok: false,
27197
+ error: {
27198
+ category: "configuration",
27199
+ code: "invalid_recent_context_top_k",
27200
+ message: "Recent-context Top-K values must be non-negative safe integers",
27201
+ retryable: false
27202
+ }
27203
+ };
27204
+ }
27205
+ const registration = registry2.get(input.backend);
27206
+ try {
27207
+ assertRegistrationShape(registration);
27208
+ const adapter = registration.createAdapter();
27209
+ assertAdapterCompatibility(String(registration.id), registration.capabilities, adapter);
27210
+ if (!adapter.discoverRecentContext) {
27211
+ return {
27212
+ ok: false,
27213
+ error: {
27214
+ category: "configuration",
27215
+ code: "recent_context_discovery_unsupported",
27216
+ message: `Backend ${input.backend} does not support recent-context discovery`,
27217
+ retryable: false
27218
+ }
27219
+ };
27220
+ }
27221
+ const command = registration.capabilities.commandOverride ? input.command : undefined;
27222
+ const discovered = await adapter.discoverRecentContext({
27223
+ recentSessionFilesTopK: input.recentSessionFilesTopK,
27224
+ recentProjectsTopK: input.recentProjectsTopK,
27225
+ ...command ? { command } : {}
27226
+ });
27227
+ const sanitized = sanitizeRecentContextData(discovered, input);
27228
+ if (!sanitized)
27229
+ throw new Error(`Adapter ${input.backend} returned invalid recent-context data`);
27230
+ return { ok: true, ...sanitized };
27231
+ } catch (error51) {
27232
+ const contractInvalid = error51 instanceof Error && (error51.message.startsWith("Adapter ") || error51.message.startsWith("Agent backend registration "));
27233
+ return {
27234
+ ok: false,
27235
+ error: {
27236
+ category: contractInvalid ? "internal" : "runtime_unavailable",
27237
+ code: contractInvalid ? "adapter_contract_invalid" : "recent_context_discovery_failed",
27238
+ message: contractInvalid ? `Backend ${input.backend} adapter contract is invalid` : `Backend ${input.backend} recent-context discovery failed`,
27239
+ retryable: !contractInvalid
27240
+ }
27241
+ };
27242
+ }
27243
+ },
26569
27244
  async probe(input) {
26570
27245
  const registration = registry2.get(input.backend);
26571
27246
  const capabilities2 = registration.capabilities;
@@ -26704,22 +27379,22 @@ function listRuntimeIds() {
26704
27379
 
26705
27380
  // src/discovery.ts
26706
27381
  function resolveAlookCliPath(moduleDir) {
26707
- const thisDir = moduleDir ?? path9.dirname(fileURLToPath(import.meta.url));
26708
- const target2 = path9.basename(thisDir) === "dist" ? path9.resolve(thisDir, "cli", "index.js") : path9.resolve(thisDir, "..", "scripts", "alook-shim.mjs");
27382
+ const thisDir = moduleDir ?? path13.dirname(fileURLToPath(import.meta.url));
27383
+ const target2 = path13.basename(thisDir) === "dist" ? path13.resolve(thisDir, "cli", "index.js") : path13.resolve(thisDir, "..", "scripts", "alook-shim.mjs");
26709
27384
  return fs6.existsSync(target2) ? target2 : null;
26710
27385
  }
26711
27386
  function deriveCliFallbackCandidates(cliPath) {
26712
27387
  if (!cliPath)
26713
27388
  return [];
26714
- const normalized = cliPath.split(path9.sep).join("/");
27389
+ const normalized = cliPath.split(path13.sep).join("/");
26715
27390
  const marker = "/node_modules/";
26716
27391
  const idx = normalized.indexOf(marker);
26717
27392
  if (idx === -1)
26718
27393
  return [];
26719
27394
  const globalRoot = cliPath.slice(0, idx + marker.length - 1);
26720
- const tail = path9.join("dist", "cli", "index.js");
27395
+ const tail = path13.join("dist", "cli", "index.js");
26721
27396
  return [
26722
- path9.join(globalRoot, "@alook", "daemon", tail)
27397
+ path13.join(globalRoot, "@alook", "daemon", tail)
26723
27398
  ].filter((candidate) => candidate !== cliPath);
26724
27399
  }
26725
27400
  function resolveAlookCliPathWithFallback(primary) {
@@ -26861,11 +27536,11 @@ function readDaemonVersion() {
26861
27536
 
26862
27537
  // src/cli/daemonRunner.ts
26863
27538
  import * as fs11 from "node:fs";
26864
- import * as path12 from "node:path";
27539
+ import * as path16 from "node:path";
26865
27540
  import { WebSocket } from "ws";
26866
27541
 
26867
27542
  // src/daemon/createDaemon.ts
26868
- import { homedir as homedir5 } from "os";
27543
+ import { homedir as homedir7 } from "os";
26869
27544
  import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync8 } from "node:fs";
26870
27545
 
26871
27546
  // src/util/rotatingFileSink.ts
@@ -26882,7 +27557,7 @@ import {
26882
27557
  statSync,
26883
27558
  unlinkSync as unlinkSync3
26884
27559
  } from "node:fs";
26885
- function createRotatingFileSink(path10, maxBytes, opts = {}) {
27560
+ function createRotatingFileSink(path14, maxBytes, opts = {}) {
26886
27561
  const report = (operation, error51) => {
26887
27562
  try {
26888
27563
  opts.onError?.({ operation, error: error51 });
@@ -26892,8 +27567,8 @@ function createRotatingFileSink(path10, maxBytes, opts = {}) {
26892
27567
  if (!existsSync6(filePath))
26893
27568
  return true;
26894
27569
  try {
26895
- const stat = lstatSync2(filePath);
26896
- if (!stat.isFile()) {
27570
+ const stat2 = lstatSync2(filePath);
27571
+ if (!stat2.isFile()) {
26897
27572
  if (opts.mode === undefined && !opts.hardMaxBytes)
26898
27573
  return true;
26899
27574
  report("unsafe_generation", new Error("log generation is not a regular file"));
@@ -26901,7 +27576,7 @@ function createRotatingFileSink(path10, maxBytes, opts = {}) {
26901
27576
  }
26902
27577
  if (opts.mode !== undefined)
26903
27578
  chmodSync(filePath, opts.mode);
26904
- if (opts.hardMaxBytes && maxBytes > 0 && stat.size > maxBytes) {
27579
+ if (opts.hardMaxBytes && maxBytes > 0 && stat2.size > maxBytes) {
26905
27580
  try {
26906
27581
  unlinkSync3(filePath);
26907
27582
  } catch (error51) {
@@ -26918,9 +27593,9 @@ function createRotatingFileSink(path10, maxBytes, opts = {}) {
26918
27593
  };
26919
27594
  const rotate = () => {
26920
27595
  try {
26921
- renameSync2(path10, `${path10}.1`);
27596
+ renameSync2(path14, `${path14}.1`);
26922
27597
  if (opts.mode !== undefined)
26923
- chmodSync(`${path10}.1`, opts.mode);
27598
+ chmodSync(`${path14}.1`, opts.mode);
26924
27599
  return true;
26925
27600
  } catch (error51) {
26926
27601
  report("rotate", error51);
@@ -26929,7 +27604,7 @@ function createRotatingFileSink(path10, maxBytes, opts = {}) {
26929
27604
  };
26930
27605
  const currentSize = () => {
26931
27606
  try {
26932
- return existsSync6(path10) ? statSync(path10).size : 0;
27607
+ return existsSync6(path14) ? statSync(path14).size : 0;
26933
27608
  } catch (error51) {
26934
27609
  report("stat", error51);
26935
27610
  return null;
@@ -26937,7 +27612,7 @@ function createRotatingFileSink(path10, maxBytes, opts = {}) {
26937
27612
  };
26938
27613
  const sink = {
26939
27614
  secure() {
26940
- return secureGeneration(`${path10}.1`) && secureGeneration(path10);
27615
+ return secureGeneration(`${path14}.1`) && secureGeneration(path14);
26941
27616
  },
26942
27617
  write(line) {
26943
27618
  try {
@@ -26957,7 +27632,7 @@ function createRotatingFileSink(path10, maxBytes, opts = {}) {
26957
27632
  const shouldRotate = maxBytes > 0 && (opts.hardMaxBytes ? currentBytes > 0 && currentBytes + serializedBytes > maxBytes : currentBytes >= maxBytes);
26958
27633
  if (shouldRotate && !rotate() && opts.hardMaxBytes)
26959
27634
  return;
26960
- appendFileSync(path10, serialized, opts.mode === undefined ? undefined : { mode: opts.mode });
27635
+ appendFileSync(path14, serialized, opts.mode === undefined ? undefined : { mode: opts.mode });
26961
27636
  } catch (error51) {
26962
27637
  report("append", error51);
26963
27638
  }
@@ -26965,7 +27640,7 @@ function createRotatingFileSink(path10, maxBytes, opts = {}) {
26965
27640
  openSnapshot() {
26966
27641
  const files = [];
26967
27642
  try {
26968
- for (const candidate of [`${path10}.1`, path10]) {
27643
+ for (const candidate of [`${path14}.1`, path14]) {
26969
27644
  if (!existsSync6(candidate))
26970
27645
  continue;
26971
27646
  if (!secureGeneration(candidate))
@@ -26973,10 +27648,10 @@ function createRotatingFileSink(path10, maxBytes, opts = {}) {
26973
27648
  const noFollow = "O_NOFOLLOW" in constants ? constants.O_NOFOLLOW : 0;
26974
27649
  const fd = openSync(candidate, constants.O_RDONLY | noFollow);
26975
27650
  try {
26976
- const stat = fstatSync(fd);
26977
- if (!stat.isFile())
27651
+ const stat2 = fstatSync(fd);
27652
+ if (!stat2.isFile())
26978
27653
  throw new Error("snapshot source is not a regular file");
26979
- files.push({ path: candidate, fd, size: stat.size });
27654
+ files.push({ path: candidate, fd, size: stat2.size });
26980
27655
  } catch (error51) {
26981
27656
  closeSync(fd);
26982
27657
  throw error51;
@@ -27126,11 +27801,11 @@ function createTraceSampler(emit, throttleMs = DEFAULT_TRACE_SAMPLE_MS) {
27126
27801
 
27127
27802
  // src/util/statusFile.ts
27128
27803
  import { writeFileSync as writeFileSync4, renameSync as renameSync3 } from "node:fs";
27129
- function writeStatusFile(path10, snapshot) {
27804
+ function writeStatusFile(path14, snapshot) {
27130
27805
  try {
27131
- const tmp = `${path10}.tmp`;
27806
+ const tmp = `${path14}.tmp`;
27132
27807
  writeFileSync4(tmp, JSON.stringify(snapshot));
27133
- renameSync3(tmp, path10);
27808
+ renameSync3(tmp, path14);
27134
27809
  } catch {}
27135
27810
  }
27136
27811
 
@@ -27812,7 +28487,7 @@ import * as fs7 from "fs";
27812
28487
  import * as http from "http";
27813
28488
  import * as https from "https";
27814
28489
  import * as os2 from "os";
27815
- import * as path10 from "path";
28490
+ import * as path14 from "path";
27816
28491
  import { URL as URL2 } from "url";
27817
28492
  var LOCAL_MESSAGE_REMINDER_PATH = "/__alook/local/message-reminder";
27818
28493
  var LOCAL_MESSAGE_REMINDER_BODY_MAX_BYTES = 4 * 1024;
@@ -27844,15 +28519,15 @@ class CredentialBroker {
27844
28519
  this.voucherPrefix = config2.voucherPrefix ?? "vch_";
27845
28520
  this.clientLabel = config2.clientLabel ?? "cli";
27846
28521
  this.headerNames = config2.headerNames ?? DEFAULT_HEADER_NAMES;
27847
- this.voucherDir = config2.voucherDir ?? path10.join(os2.tmpdir(), "agent-vouchers");
28522
+ this.voucherDir = config2.voucherDir ?? path14.join(os2.tmpdir(), "agent-vouchers");
27848
28523
  }
27849
28524
  mint(agentId, launchId, capabilities2, runnerKey) {
27850
28525
  if (!runnerKey)
27851
28526
  throw new Error("CredentialBroker.mint: runnerKey is required (per-agent tier-2 credential)");
27852
28527
  const voucher = randomVoucher(this.voucherPrefix);
27853
- const dir = path10.join(this.voucherDir, sanitizeIdSegment(agentId));
28528
+ const dir = path14.join(this.voucherDir, sanitizeIdSegment(agentId));
27854
28529
  fs7.mkdirSync(dir, { recursive: true });
27855
- const voucherFile = path10.join(dir, `${sanitizeIdSegment(launchId)}.token`);
28530
+ const voucherFile = path14.join(dir, `${sanitizeIdSegment(launchId)}.token`);
27856
28531
  fs7.writeFileSync(voucherFile, voucher, { mode: 384 });
27857
28532
  this.registrations.set(voucher, {
27858
28533
  agentId,
@@ -28920,7 +29595,7 @@ function runtimeModelName(config2) {
28920
29595
  // agent-driver/dist/provider-quota.js
28921
29596
  import { execFile } from "node:child_process";
28922
29597
  import { readFile } from "node:fs/promises";
28923
- import { homedir as homedir3 } from "node:os";
29598
+ import { homedir as homedir5 } from "node:os";
28924
29599
  import { join as join11 } from "node:path";
28925
29600
  import { promisify } from "node:util";
28926
29601
  import { randomBytes as randomBytes5 } from "node:crypto";
@@ -28949,7 +29624,7 @@ async function claudeCredentials(options) {
28949
29624
  } catch {}
28950
29625
  }
28951
29626
  const env = options.env ?? process.env;
28952
- const root = env.CLAUDE_CONFIG_DIR || join11(options.home ?? homedir3(), ".claude");
29627
+ const root = env.CLAUDE_CONFIG_DIR || join11(options.home ?? homedir5(), ".claude");
28953
29628
  try {
28954
29629
  const value = options.readCredentialsFile ? await options.readCredentialsFile(join11(root, ".credentials.json")) : await readFile(join11(root, ".credentials.json"), "utf8");
28955
29630
  return parseCredentials(value);
@@ -30305,6 +30980,10 @@ ${this.opts.wakePromptFooter}` : text2;
30305
30980
  sent = session2.send(input);
30306
30981
  if (exactOwner)
30307
30982
  this.markPendingDeliveryObserved(exactOwner, input.id);
30983
+ this.log.info("steering message submitted to logical session", {
30984
+ agentId: effect.agentId,
30985
+ mode: effect.mode
30986
+ });
30308
30987
  } catch (error51) {
30309
30988
  if (exactOwner) {
30310
30989
  this.settlePendingDelivery(exactOwner, input.id);
@@ -30350,7 +31029,6 @@ ${this.opts.wakePromptFooter}` : text2;
30350
31029
  mode: effect.mode
30351
31030
  });
30352
31031
  }
30353
- this.log.info("steering message sent to running agent", { agentId: effect.agentId, mode: effect.mode });
30354
31032
  break;
30355
31033
  }
30356
31034
  case "stop":
@@ -31396,6 +32074,26 @@ class AgentRouter {
31396
32074
  return;
31397
32075
  }
31398
32076
  break;
32077
+ case "agent:event":
32078
+ this.log.info("agent:event received", { agentId: cmd.agentId });
32079
+ try {
32080
+ await this.opts.onBeforeAgent?.(cmd.agentId);
32081
+ this.opts.manager.register(cmd.agentId, {
32082
+ runtimeConfig: cmd.config,
32083
+ launchId: cmd.launchId
32084
+ });
32085
+ this.running.add(cmd.agentId);
32086
+ this.opts.manager.deliver(cmd.agentId, {
32087
+ id: `${cmd.agentId}:event:${cmd.launchId}`,
32088
+ text: cmd.prompt
32089
+ });
32090
+ } catch (err) {
32091
+ this.log.warn("agent:event failed", {
32092
+ agentId: cmd.agentId,
32093
+ err: err instanceof Error ? err.message : String(err)
32094
+ });
32095
+ }
32096
+ break;
31399
32097
  case "agent:reset":
31400
32098
  await this.runRestartCommand(cmd.agentId, cmd.launchId, "agent:reset", () => this.opts.manager.resetSession(cmd.agentId, {
31401
32099
  runtimeConfig: cmd.config,
@@ -31626,11 +32324,11 @@ function timelineRowHash(line) {
31626
32324
  }
31627
32325
  function timelineFileGeneration(filePath, lines) {
31628
32326
  try {
31629
- const stat = fs9.lstatSync(filePath, { bigint: true });
31630
- if (!stat.isFile())
32327
+ const stat2 = fs9.lstatSync(filePath, { bigint: true });
32328
+ if (!stat2.isFile())
31631
32329
  return null;
31632
32330
  const digest = createHash2("sha256");
31633
- digest.update(`${stat.dev}:${stat.ino}:${stat.size}:${stat.mtimeNs}:${stat.ctimeNs}
32331
+ digest.update(`${stat2.dev}:${stat2.ino}:${stat2.size}:${stat2.mtimeNs}:${stat2.ctimeNs}
31634
32332
  `);
31635
32333
  for (const line of lines)
31636
32334
  digest.update(line.text, "utf8").update(`
@@ -31688,9 +32386,9 @@ function compactLines(input) {
31688
32386
  }
31689
32387
  return suffix;
31690
32388
  }
31691
- function isRealDirectory(path11) {
32389
+ function isRealDirectory(path15) {
31692
32390
  try {
31693
- return fs9.lstatSync(path11).isDirectory();
32391
+ return fs9.lstatSync(path15).isDirectory();
31694
32392
  } catch {
31695
32393
  return false;
31696
32394
  }
@@ -31730,8 +32428,8 @@ function scanTimelineFile(filePath) {
31730
32428
  let fd = null;
31731
32429
  try {
31732
32430
  fd = fs9.openSync(filePath, fs9.constants.O_RDONLY | (fs9.constants.O_NOFOLLOW ?? 0));
31733
- const stat = fs9.fstatSync(fd);
31734
- if (!stat.isFile())
32431
+ const stat2 = fs9.fstatSync(fd);
32432
+ if (!stat2.isFile())
31735
32433
  return null;
31736
32434
  const chunk2 = Buffer.allocUnsafe(TIMELINE_READ_CHUNK_BYTES);
31737
32435
  const newest = [];
@@ -31744,9 +32442,9 @@ function scanTimelineFile(filePath) {
31744
32442
  let oversized = false;
31745
32443
  let stop = false;
31746
32444
  let discardIncompleteTail = false;
31747
- if (stat.size > 0) {
32445
+ if (stat2.size > 0) {
31748
32446
  const last = Buffer.allocUnsafe(1);
31749
- fs9.readSync(fd, last, 0, 1, stat.size - 1);
32447
+ fs9.readSync(fd, last, 0, 1, stat2.size - 1);
31750
32448
  discardIncompleteTail = last[0] !== 10;
31751
32449
  }
31752
32450
  const resetPhysicalLine = () => {
@@ -31805,7 +32503,7 @@ function scanTimelineFile(filePath) {
31805
32503
  }
31806
32504
  resetPhysicalLine();
31807
32505
  };
31808
- let position = stat.size;
32506
+ let position = stat2.size;
31809
32507
  while (position > 0 && !stop) {
31810
32508
  const start = Math.max(0, position - chunk2.length);
31811
32509
  const requested = position - start;
@@ -31957,11 +32655,11 @@ function readResumeControlState(timelineDir) {
31957
32655
  let fd = null;
31958
32656
  try {
31959
32657
  fd = fs9.openSync(filePath, fs9.constants.O_RDONLY | (fs9.constants.O_NOFOLLOW ?? 0));
31960
- const stat = fs9.fstatSync(fd);
31961
- if (!stat.isFile() || stat.size <= 0 || stat.size > RESUME_CONTROL_MAX_BYTES) {
32658
+ const stat2 = fs9.fstatSync(fd);
32659
+ if (!stat2.isFile() || stat2.size <= 0 || stat2.size > RESUME_CONTROL_MAX_BYTES) {
31962
32660
  return { kind: "invalid" };
31963
32661
  }
31964
- const bounded = Buffer.allocUnsafe(stat.size + 1);
32662
+ const bounded = Buffer.allocUnsafe(stat2.size + 1);
31965
32663
  let bytesRead = 0;
31966
32664
  while (bytesRead < bounded.length) {
31967
32665
  const count = fs9.readSync(fd, bounded, bytesRead, bounded.length - bytesRead, bytesRead);
@@ -31969,7 +32667,7 @@ function readResumeControlState(timelineDir) {
31969
32667
  break;
31970
32668
  bytesRead += count;
31971
32669
  }
31972
- if (bytesRead !== stat.size)
32670
+ if (bytesRead !== stat2.size)
31973
32671
  return { kind: "invalid" };
31974
32672
  const raw = bounded.subarray(0, bytesRead).toString("utf8");
31975
32673
  const value = JSON.parse(raw);
@@ -32895,7 +33593,7 @@ class MessageReminderScheduler {
32895
33593
 
32896
33594
  // src/manager/agentDriverHost.ts
32897
33595
  import { randomUUID as randomUUID7 } from "node:crypto";
32898
- import { homedir as homedir4 } from "node:os";
33596
+ import { homedir as homedir6 } from "node:os";
32899
33597
  import { join as join13 } from "node:path";
32900
33598
 
32901
33599
  // src/drivers/gitIdentityEnv.ts
@@ -33021,7 +33719,7 @@ function createDaemonAgentDriverHost(ctx, onRawLine) {
33021
33719
  hostUser: readHostGitIdentity() ?? undefined
33022
33720
  }),
33023
33721
  platformProtected: {
33024
- ALOOK_HOME: process.env.ALOOK_HOME ?? join13(homedir4(), ".alook"),
33722
+ ALOOK_HOME: process.env.ALOOK_HOME ?? join13(homedir6(), ".alook"),
33025
33723
  ALOOK_ID: ctx.agentId,
33026
33724
  ALOOK_CLI: ctx.agentCliPath,
33027
33725
  ALOOK_SERVER_URL: ctx.config.serverUrl,
@@ -33342,13 +34040,13 @@ function createRuntimeRawLineTap(args) {
33342
34040
  const maxBytes = args.maxBytes ?? RUNTIME_RAW_TRACE_MAX_BYTES;
33343
34041
  const sinks = new Map;
33344
34042
  const warned = new Set;
33345
- const warnOnce = (agentId, path11, operation, error51) => {
34043
+ const warnOnce = (agentId, path15, operation, error51) => {
33346
34044
  if (warned.has(agentId))
33347
34045
  return;
33348
34046
  warned.add(agentId);
33349
34047
  args.logger.warn("runtime raw trace sink failed", {
33350
34048
  agentId,
33351
- path: path11,
34049
+ path: path15,
33352
34050
  operation,
33353
34051
  error: error51 instanceof Error ? error51.message : String(error51)
33354
34052
  });
@@ -33357,10 +34055,10 @@ function createRuntimeRawLineTap(args) {
33357
34055
  if (!args.enabledAgentIds.has(agentId))
33358
34056
  return;
33359
34057
  const encodedAgentId = encodeURIComponent(agentId).replace(/\./g, "%2E");
33360
- const path11 = `${traceDir}/runtime-raw-events-${encodedAgentId}.jsonl`;
34058
+ const path15 = `${traceDir}/runtime-raw-events-${encodedAgentId}.jsonl`;
33361
34059
  const serializedBytes = Buffer.byteLength(line, "utf8") + 1;
33362
34060
  if (serializedBytes > maxBytes) {
33363
- warnOnce(agentId, path11, "oversize", new Error(`raw line is ${serializedBytes} bytes; max is ${maxBytes}`));
34061
+ warnOnce(agentId, path15, "oversize", new Error(`raw line is ${serializedBytes} bytes; max is ${maxBytes}`));
33364
34062
  return;
33365
34063
  }
33366
34064
  let sink = sinks.get(agentId);
@@ -33368,12 +34066,12 @@ function createRuntimeRawLineTap(args) {
33368
34066
  try {
33369
34067
  mkdirSync8(traceDir, { recursive: true });
33370
34068
  } catch (error51) {
33371
- warnOnce(agentId, path11, "mkdir", error51);
34069
+ warnOnce(agentId, path15, "mkdir", error51);
33372
34070
  }
33373
- sink = createRotatingFileSink(path11, maxBytes, {
34071
+ sink = createRotatingFileSink(path15, maxBytes, {
33374
34072
  mode: 384,
33375
34073
  hardMaxBytes: true,
33376
- onError: ({ operation, error: error51 }) => warnOnce(agentId, path11, operation, error51)
34074
+ onError: ({ operation, error: error51 }) => warnOnce(agentId, path15, operation, error51)
33377
34075
  });
33378
34076
  sinks.set(agentId, sink);
33379
34077
  }
@@ -33465,7 +34163,7 @@ function createBuiltinDaemonSessionFactory(onRuntimeRawLine) {
33465
34163
  }
33466
34164
  async function createDaemon(opts) {
33467
34165
  const log2 = opts.logger ?? createLogger2({ header: "@alook/daemon" });
33468
- const fallbackBase = (process.env.ALOOK_PROJECT_ROOT || `${homedir5()}/.alook`) + "/daemon";
34166
+ const fallbackBase = (process.env.ALOOK_PROJECT_ROOT || `${homedir7()}/.alook`) + "/daemon";
33469
34167
  const workingDirectoryBase = opts.workingDirectoryBase ?? fallbackBase;
33470
34168
  const workdirFor = (agentId) => `${workingDirectoryBase}/${agentId}`;
33471
34169
  const dailyTokenUsage2 = new DailyTokenUsageStore(workingDirectoryBase);
@@ -34171,12 +34869,12 @@ async function readPinnedJsonFile(args) {
34171
34869
  }
34172
34870
  }
34173
34871
  fd = openSync3(args.path, constants3.O_RDONLY | noFollow);
34174
- const stat = fstatSync3(fd);
34175
- if (!stat.isFile())
34872
+ const stat2 = fstatSync3(fd);
34873
+ if (!stat2.isFile())
34176
34874
  return { value: null, warnings: ["source_unavailable"] };
34177
- if (stat.size > args.maxBytes)
34875
+ if (stat2.size > args.maxBytes)
34178
34876
  return { value: null, warnings: ["line_too_long"] };
34179
- const bytes = readPinnedBytes(fd, stat.size);
34877
+ const bytes = readPinnedBytes(fd, stat2.size);
34180
34878
  try {
34181
34879
  return { value: JSON.parse(bytes.toString("utf8")), warnings: [] };
34182
34880
  } catch {
@@ -34254,7 +34952,7 @@ var DAEMON_LOG_DIAGNOSTIC_POLICY = [
34254
34952
  reason: string5(32, { values: ["turn_end", "stopped", "terminate_stalled", "exit"] }),
34255
34953
  sessionId: string5(256, { scrub: true })
34256
34954
  } },
34257
- { header: "@alook/daemon:manager", message: "steering message sent to running agent", scope: "target", fields: {
34955
+ { header: "@alook/daemon:manager", message: "steering message submitted to logical session", scope: "target", fields: {
34258
34956
  agentId: AGENT,
34259
34957
  mode: string5(8, { values: ["busy", "idle"] })
34260
34958
  } },
@@ -34809,7 +35507,7 @@ import { createHash as createHash4, randomBytes as randomBytes7 } from "node:cry
34809
35507
  import {
34810
35508
  chmodSync as chmodSync2,
34811
35509
  closeSync as closeSync4,
34812
- createReadStream,
35510
+ createReadStream as createReadStream3,
34813
35511
  existsSync as existsSync7,
34814
35512
  fsyncSync as fsyncSync2,
34815
35513
  lstatSync as lstatSync5,
@@ -34832,7 +35530,7 @@ class CoordinatorError extends Error {
34832
35530
  function defaultFsOps() {
34833
35531
  return {
34834
35532
  randomSuffix: () => randomBytes7(12).toString("hex"),
34835
- open: (path11, flags, mode) => openSync4(path11, flags, mode),
35533
+ open: (path15, flags, mode) => openSync4(path15, flags, mode),
34836
35534
  write: (fd, bytes) => {
34837
35535
  writeSync(fd, bytes);
34838
35536
  },
@@ -34845,10 +35543,10 @@ function defaultFsOps() {
34845
35543
  rename: (from, to) => {
34846
35544
  renameSync5(from, to);
34847
35545
  },
34848
- fsyncDirectory: (path11) => {
35546
+ fsyncDirectory: (path15) => {
34849
35547
  if (process.platform === "win32")
34850
35548
  return;
34851
- const fd = openSync4(path11, "r");
35549
+ const fd = openSync4(path15, "r");
34852
35550
  try {
34853
35551
  fsyncSync2(fd);
34854
35552
  } finally {
@@ -34899,8 +35597,8 @@ function createDiagnosticReportCoordinator(args) {
34899
35597
  const sidecarPath = (reportId) => join15(dir, `report-${reportId}.json`);
34900
35598
  const ensureDir = () => {
34901
35599
  if (existsSync7(dir)) {
34902
- const stat = lstatSync5(dir);
34903
- if (!stat.isDirectory() || stat.isSymbolicLink())
35600
+ const stat2 = lstatSync5(dir);
35601
+ if (!stat2.isDirectory() || stat2.isSymbolicLink())
34904
35602
  throw new CoordinatorError("local_artifact_invalid");
34905
35603
  if (process.platform !== "win32")
34906
35604
  chmodSync2(dir, 448);
@@ -34913,11 +35611,11 @@ function createDiagnosticReportCoordinator(args) {
34913
35611
  args.logger?.warn("diagnostic local artifact invalid", { reportId, code: "local_artifact_invalid" });
34914
35612
  } catch {}
34915
35613
  };
34916
- const removeExact = (path11) => {
35614
+ const removeExact = (path15) => {
34917
35615
  try {
34918
- const stat = lstatSync5(path11);
34919
- if (stat.isFile() && !stat.isSymbolicLink())
34920
- unlinkSync6(path11);
35616
+ const stat2 = lstatSync5(path15);
35617
+ if (stat2.isFile() && !stat2.isSymbolicLink())
35618
+ unlinkSync6(path15);
34921
35619
  } catch {}
34922
35620
  };
34923
35621
  const cleanup = (reportId) => {
@@ -34955,12 +35653,12 @@ function createDiagnosticReportCoordinator(args) {
34955
35653
  checkpoint(sidecar.phase === "collecting" ? "collecting_dir_fsynced" : "ready_dir_fsynced");
34956
35654
  };
34957
35655
  const committedArchive = (reportId) => {
34958
- const path11 = archivePath(reportId);
35656
+ const path15 = archivePath(reportId);
34959
35657
  try {
34960
- const stat = lstatSync5(path11);
34961
- if (!stat.isFile() || stat.isSymbolicLink())
35658
+ const stat2 = lstatSync5(path15);
35659
+ if (!stat2.isFile() || stat2.isSymbolicLink())
34962
35660
  return null;
34963
- const bytes = readFileSync6(path11);
35661
+ const bytes = readFileSync6(path15);
34964
35662
  return { sizeBytes: bytes.byteLength, sha256: createHash4("sha256").update(bytes).digest("hex") };
34965
35663
  } catch {
34966
35664
  return null;
@@ -35021,7 +35719,7 @@ function createDiagnosticReportCoordinator(args) {
35021
35719
  if (stopped)
35022
35720
  throw new CoordinatorError("coordinator_shutdown");
35023
35721
  checkpoint("before_upload");
35024
- const result = await args.transport.upload({ reportId: sidecar.reportId, sizeBytes: sidecar.sizeBytes, sha256: sidecar.sha256 }, createReadStream(archivePath(sidecar.reportId)));
35722
+ const result = await args.transport.upload({ reportId: sidecar.reportId, sizeBytes: sidecar.sizeBytes, sha256: sidecar.sha256 }, createReadStream3(archivePath(sidecar.reportId)));
35025
35723
  checkpoint("after_upload");
35026
35724
  if (result.kind === "terminal") {
35027
35725
  cleanup(sidecar.reportId);
@@ -35085,12 +35783,12 @@ function createDiagnosticReportCoordinator(args) {
35085
35783
  return uploadReady(ready);
35086
35784
  };
35087
35785
  const readSidecar = (reportId) => {
35088
- const path11 = sidecarPath(reportId);
35786
+ const path15 = sidecarPath(reportId);
35089
35787
  try {
35090
- const stat = lstatSync5(path11);
35091
- if (!stat.isFile() || stat.isSymbolicLink())
35788
+ const stat2 = lstatSync5(path15);
35789
+ if (!stat2.isFile() || stat2.isSymbolicLink())
35092
35790
  return null;
35093
- return parseSidecar(JSON.parse(readFileSync6(path11, "utf8")));
35791
+ return parseSidecar(JSON.parse(readFileSync6(path15, "utf8")));
35094
35792
  } catch {
35095
35793
  return null;
35096
35794
  }
@@ -35178,9 +35876,9 @@ function createDiagnosticReportCoordinator(args) {
35178
35876
  }
35179
35877
  // src/diagnostics/httpTransport.ts
35180
35878
  import { Readable as Readable2 } from "node:stream";
35181
- function endpoint(serverUrl, path11) {
35879
+ function endpoint(serverUrl, path15) {
35182
35880
  const base = serverUrl.endsWith("/") ? serverUrl : `${serverUrl}/`;
35183
- return new URL(path11.replace(/^\//, ""), base).toString();
35881
+ return new URL(path15.replace(/^\//, ""), base).toString();
35184
35882
  }
35185
35883
  async function strictOutcome(response, allowed) {
35186
35884
  try {
@@ -35244,29 +35942,29 @@ function createDiagnosticHttpTransport(args) {
35244
35942
  // src/cli/daemonUpdate.ts
35245
35943
  import * as crypto4 from "node:crypto";
35246
35944
  import * as fs10 from "node:fs";
35247
- import * as path11 from "node:path";
35945
+ import * as path15 from "node:path";
35248
35946
  import { spawn as spawn2 } from "node:child_process";
35249
35947
  var UPDATE_INTENT_SCHEMA_VERSION = 1;
35250
35948
  var UPDATE_LOG_MAX_BYTES = 512 * 1024;
35251
35949
  var UPDATE_LOG_KEEP_BYTES = 256 * 1024;
35252
35950
  var REQUEST_ID_PATTERN = /^[A-Za-z0-9_-]{16,128}$/;
35253
35951
  function intentPath(baseDir, machineId) {
35254
- return path11.join(daemonDirById(baseDir, machineId), "update-intent.json");
35952
+ return path15.join(daemonDirById(baseDir, machineId), "update-intent.json");
35255
35953
  }
35256
35954
  function updateLogPath(baseDir, machineId) {
35257
- return path11.join(daemonDirById(baseDir, machineId), "update.log");
35955
+ return path15.join(daemonDirById(baseDir, machineId), "update.log");
35258
35956
  }
35259
35957
  function updatePackageMapPath(baseDir, machineId) {
35260
- return path11.join(daemonDirById(baseDir, machineId), "update-package-map.json");
35958
+ return path15.join(daemonDirById(baseDir, machineId), "update-package-map.json");
35261
35959
  }
35262
35960
  function ensurePrivateDir(dir) {
35263
35961
  fs10.mkdirSync(dir, { recursive: true, mode: 448 });
35264
35962
  fs10.chmodSync(dir, 448);
35265
35963
  }
35266
35964
  function writePrivateJsonAtomic(filePath, value) {
35267
- const dir = path11.dirname(filePath);
35965
+ const dir = path15.dirname(filePath);
35268
35966
  ensurePrivateDir(dir);
35269
- const tempPath = path11.join(dir, `.${path11.basename(filePath)}.${process.pid}.${crypto4.randomBytes(8).toString("hex")}.tmp`);
35967
+ const tempPath = path15.join(dir, `.${path15.basename(filePath)}.${process.pid}.${crypto4.randomBytes(8).toString("hex")}.tmp`);
35270
35968
  let fd = fs10.openSync(tempPath, "wx", 384);
35271
35969
  try {
35272
35970
  fs10.writeFileSync(fd, JSON.stringify(value));
@@ -35291,7 +35989,7 @@ function scrub(value) {
35291
35989
  }
35292
35990
  function appendUpdateLog(baseDir, machineId, event, fields = {}) {
35293
35991
  const filePath = updateLogPath(baseDir, machineId);
35294
- ensurePrivateDir(path11.dirname(filePath));
35992
+ ensurePrivateDir(path15.dirname(filePath));
35295
35993
  try {
35296
35994
  if (fs10.existsSync(filePath) && fs10.statSync(filePath).size > UPDATE_LOG_MAX_BYTES) {
35297
35995
  const data = fs10.readFileSync(filePath);
@@ -35318,8 +36016,8 @@ function tuplesEqual(value, expected) {
35318
36016
  }
35319
36017
  function readIntent(baseDir, machineId) {
35320
36018
  const filePath = intentPath(baseDir, machineId);
35321
- const stat = fs10.lstatSync(filePath);
35322
- if (!stat.isFile())
36019
+ const stat2 = fs10.lstatSync(filePath);
36020
+ if (!stat2.isFile())
35323
36021
  throw new Error("unsafe daemon update intent type");
35324
36022
  fs10.chmodSync(filePath, 384);
35325
36023
  const value = JSON.parse(fs10.readFileSync(filePath, "utf8"));
@@ -35334,12 +36032,81 @@ function removeIntentIfMatches(baseDir, machineId, requestId) {
35334
36032
  fs10.unlinkSync(intentPath(baseDir, machineId));
35335
36033
  } catch {}
35336
36034
  }
35337
- function npmExecPath(explicit) {
35338
- const value = explicit ?? process.env.npm_execpath;
35339
- if (!value || !path11.isAbsolute(value) || !fs10.existsSync(value)) {
35340
- throw new Error("npm launch context unavailable; daemon remains online");
36035
+ var defaultNpmLaunchFileProbe = {
36036
+ isFile(filePath) {
36037
+ try {
36038
+ return fs10.statSync(filePath).isFile();
36039
+ } catch {
36040
+ return false;
36041
+ }
36042
+ },
36043
+ isExecutable(filePath) {
36044
+ try {
36045
+ fs10.accessSync(filePath, fs10.constants.X_OK);
36046
+ return true;
36047
+ } catch {
36048
+ return false;
36049
+ }
35341
36050
  }
35342
- return value;
36051
+ };
36052
+ function pathEnvironment(env, platform) {
36053
+ if (platform !== "win32")
36054
+ return env.PATH;
36055
+ const entry = Object.entries(env).find(([key]) => key.toLowerCase() === "path");
36056
+ return entry?.[1];
36057
+ }
36058
+ function launchFromNpmPath(args) {
36059
+ const pathApi = args.platform === "win32" ? path15.win32 : path15.posix;
36060
+ if (!pathApi.isAbsolute(args.npmPath) || !args.probe.isFile(args.npmPath))
36061
+ return null;
36062
+ const extension = pathApi.extname(args.npmPath).toLowerCase();
36063
+ if ([".js", ".cjs", ".mjs"].includes(extension)) {
36064
+ return { file: args.nodePath, prefixArgs: [args.npmPath] };
36065
+ }
36066
+ if (args.platform === "win32" && [".cmd", ".bat"].includes(extension)) {
36067
+ const cliPath = pathApi.join(pathApi.dirname(args.npmPath), "node_modules", "npm", "bin", "npm-cli.js");
36068
+ return args.probe.isFile(cliPath) ? { file: args.nodePath, prefixArgs: [cliPath] } : null;
36069
+ }
36070
+ if (args.requireExecutable && !args.probe.isExecutable(args.npmPath))
36071
+ return null;
36072
+ return { file: args.npmPath, prefixArgs: [] };
36073
+ }
36074
+ function resolveNpmLaunchCommand(options = {}) {
36075
+ const env = options.env ?? process.env;
36076
+ const platform = options.platform ?? process.platform;
36077
+ const nodePath = options.nodePath ?? process.execPath;
36078
+ const probe = options.probe ?? defaultNpmLaunchFileProbe;
36079
+ const inherited = options.npmExecPath ?? env.npm_execpath;
36080
+ if (inherited) {
36081
+ const launch = launchFromNpmPath({
36082
+ npmPath: inherited,
36083
+ platform,
36084
+ nodePath,
36085
+ probe,
36086
+ requireExecutable: platform !== "win32"
36087
+ });
36088
+ if (launch)
36089
+ return launch;
36090
+ }
36091
+ const pathApi = platform === "win32" ? path15.win32 : path15.posix;
36092
+ const names = platform === "win32" ? ["npm.exe", "npm.cmd", "npm.bat", "npm"] : ["npm"];
36093
+ const pathValue = pathEnvironment(env, platform);
36094
+ for (const directory of pathValue?.split(pathApi.delimiter) ?? []) {
36095
+ if (!directory || !pathApi.isAbsolute(directory))
36096
+ continue;
36097
+ for (const name of names) {
36098
+ const launch = launchFromNpmPath({
36099
+ npmPath: pathApi.join(directory, name),
36100
+ platform,
36101
+ nodePath,
36102
+ probe,
36103
+ requireExecutable: platform !== "win32"
36104
+ });
36105
+ if (launch)
36106
+ return launch;
36107
+ }
36108
+ }
36109
+ throw new Error("npm launch context unavailable and no safe npm executable was found on PATH; daemon remains online");
35343
36110
  }
35344
36111
  function readTestPackageMap(baseDir, machineId) {
35345
36112
  if (true)
@@ -35347,10 +36114,10 @@ function readTestPackageMap(baseDir, machineId) {
35347
36114
  const filePath = updatePackageMapPath(baseDir, machineId);
35348
36115
  if (!fs10.existsSync(filePath))
35349
36116
  return null;
35350
- const stat = fs10.lstatSync(filePath);
35351
- if (!stat.isFile())
36117
+ const stat2 = fs10.lstatSync(filePath);
36118
+ if (!stat2.isFile())
35352
36119
  throw new Error("unsafe daemon update package map type");
35353
- if (process.platform !== "win32" && (stat.mode & 63) !== 0) {
36120
+ if (process.platform !== "win32" && (stat2.mode & 63) !== 0) {
35354
36121
  throw new Error("daemon update package map must be mode 0600");
35355
36122
  }
35356
36123
  const parsed = JSON.parse(fs10.readFileSync(filePath, "utf8"));
@@ -35360,7 +36127,7 @@ function readTestPackageMap(baseDir, machineId) {
35360
36127
  for (const [key, value] of Object.entries(parsed)) {
35361
36128
  if (key !== "latest" && !parseReleaseVersion(key))
35362
36129
  throw new Error("invalid daemon update package map key");
35363
- if (typeof value !== "string" || !path11.isAbsolute(value))
36130
+ if (typeof value !== "string" || !path15.isAbsolute(value))
35364
36131
  throw new Error("invalid daemon update package map value");
35365
36132
  result[key] = value;
35366
36133
  }
@@ -35374,9 +36141,9 @@ function packageSpec(baseDir, machineId, version3) {
35374
36141
  }
35375
36142
  function fixedNpmArgs(args) {
35376
36143
  return [
35377
- args.npmPath,
35378
36144
  "exec",
35379
36145
  "--yes",
36146
+ "--no-audit",
35380
36147
  `--package=${args.packageSpec}`,
35381
36148
  "--",
35382
36149
  "alook-daemon",
@@ -35407,7 +36174,13 @@ function createDaemonSelfUpdateHandler(context, deps = {}) {
35407
36174
  const current = pidTuple(readPidFile(pidfilePathById(context.baseDir, context.machineId)));
35408
36175
  if (!current || current.pid !== context.pid || current.machineId !== context.machineId || current.startedAt !== context.startedAt || current.ownerToken !== context.ownerToken)
35409
36176
  throw new Error("daemon ownership changed before update launch");
35410
- const npmPath = npmExecPath(deps.npmExecPath);
36177
+ const npmLaunch = resolveNpmLaunchCommand({
36178
+ npmExecPath: deps.npmExecPath,
36179
+ env: deps.npmLaunchEnv,
36180
+ platform: deps.npmLaunchPlatform,
36181
+ nodePath: deps.npmLaunchNodePath,
36182
+ probe: deps.npmLaunchFileProbe
36183
+ });
35411
36184
  requestId = crypto4.randomUUID();
35412
36185
  const intent = {
35413
36186
  schemaVersion: UPDATE_INTENT_SCHEMA_VERSION,
@@ -35417,14 +36190,16 @@ function createDaemonSelfUpdateHandler(context, deps = {}) {
35417
36190
  writePrivateJsonAtomic(intentPath(context.baseDir, context.machineId), intent);
35418
36191
  const logFd = openUpdateLog(context.baseDir, context.machineId);
35419
36192
  try {
35420
- const child = (deps.spawnProcess ?? spawn2)(process.execPath, fixedNpmArgs({
35421
- npmPath,
35422
- packageSpec: packageSpec(context.baseDir, context.machineId, "latest"),
35423
- command: "replace",
35424
- machineId: context.machineId,
35425
- baseDir: context.baseDir,
35426
- requestId
35427
- }), {
36193
+ const child = (deps.spawnProcess ?? spawn2)(npmLaunch.file, [
36194
+ ...npmLaunch.prefixArgs,
36195
+ ...fixedNpmArgs({
36196
+ packageSpec: packageSpec(context.baseDir, context.machineId, "latest"),
36197
+ command: "replace",
36198
+ machineId: context.machineId,
36199
+ baseDir: context.baseDir,
36200
+ requestId
36201
+ })
36202
+ ], {
35428
36203
  detached: true,
35429
36204
  shell: false,
35430
36205
  stdio: ["ignore", logFd, logFd]
@@ -35465,14 +36240,16 @@ function removeOldPidfileIfMatches(baseDir, intent) {
35465
36240
  async function runPinnedResume(args) {
35466
36241
  const fd = openUpdateLog(args.baseDir, args.machineId);
35467
36242
  try {
35468
- const child = spawn2(process.execPath, fixedNpmArgs({
35469
- npmPath: args.npmPath,
35470
- packageSpec: packageSpec(args.baseDir, args.machineId, args.version),
35471
- command: "resume",
35472
- machineId: args.machineId,
35473
- baseDir: args.baseDir,
35474
- requestId: args.requestId
35475
- }), {
36243
+ const child = spawn2(args.npmLaunch.file, [
36244
+ ...args.npmLaunch.prefixArgs,
36245
+ ...fixedNpmArgs({
36246
+ packageSpec: packageSpec(args.baseDir, args.machineId, args.version),
36247
+ command: "resume",
36248
+ machineId: args.machineId,
36249
+ baseDir: args.baseDir,
36250
+ requestId: args.requestId
36251
+ })
36252
+ ], {
35476
36253
  shell: false,
35477
36254
  stdio: ["ignore", fd, fd]
35478
36255
  });
@@ -35516,7 +36293,7 @@ async function daemonReplace(opts) {
35516
36293
  removeIntentIfMatches(baseDir, opts.id, opts.requestId);
35517
36294
  throw new Error("daemon ownership changed before replacement");
35518
36295
  }
35519
- const npmPath = npmExecPath();
36296
+ const npmLaunch = resolveNpmLaunchCommand();
35520
36297
  const acquired = acquireDaemonReplacementLock({ baseDir, machineId: opts.id, requestId: opts.requestId });
35521
36298
  let oldStopped = false;
35522
36299
  try {
@@ -35536,7 +36313,7 @@ async function daemonReplace(opts) {
35536
36313
  } catch (error51) {
35537
36314
  appendUpdateLog(baseDir, opts.id, "replacement_start_failed", { error: error51 });
35538
36315
  await runPinnedResume({
35539
- npmPath,
36316
+ npmLaunch,
35540
36317
  version: launch.daemonVersion,
35541
36318
  machineId: opts.id,
35542
36319
  baseDir,
@@ -35659,7 +36436,7 @@ async function buildRunnerDiagnosticBundle(args) {
35659
36436
  function createDaemonProcessLogger(daemonDir, foreground) {
35660
36437
  fs11.mkdirSync(daemonDir, { recursive: true, mode: 448 });
35661
36438
  fs11.chmodSync(daemonDir, 448);
35662
- const logPath = path12.join(daemonDir, "daemon.log");
36439
+ const logPath = path16.join(daemonDir, "daemon.log");
35663
36440
  let warnedOversize = false;
35664
36441
  const sink = createRotatingFileSink(logPath, DAEMON_LOG_MAX_BYTES, {
35665
36442
  mode: 384,
@@ -35895,16 +36672,16 @@ var LEGACY_DAEMON_ID_PATTERN = /^[a-f0-9]{12}$/;
35895
36672
  var DEFAULT_SERVER_URL = "https://alook.ai";
35896
36673
  var DEFAULT_WS_URL = "wss://alook.ai/api/ws/community-daemon";
35897
36674
  function resolveDefaultBaseDir() {
35898
- const root = process.env.ALOOK_PROJECT_ROOT || path13.join(homedir6(), ".alook");
35899
- return path13.join(root, "daemon");
36675
+ const root = process.env.ALOOK_PROJECT_ROOT || path17.join(homedir8(), ".alook");
36676
+ return path17.join(root, "daemon");
35900
36677
  }
35901
36678
  var DEFAULT_BASE_DIR = resolveDefaultBaseDir();
35902
36679
  var log2 = createLogger2({ header: "@alook/daemon" });
35903
36680
  function daemonsDir(baseDir) {
35904
- return path13.join(baseDir, "daemons");
36681
+ return path17.join(baseDir, "daemons");
35905
36682
  }
35906
36683
  function daemonDirById(baseDir, id) {
35907
- return path13.join(daemonsDir(baseDir), validateDaemonId(id));
36684
+ return path17.join(daemonsDir(baseDir), validateDaemonId(id));
35908
36685
  }
35909
36686
  function validateMachineId(machineId) {
35910
36687
  if (!MACHINE_ID_PATTERN.test(machineId))
@@ -35920,10 +36697,10 @@ function validateDaemonId(id) {
35920
36697
  return id;
35921
36698
  }
35922
36699
  function pidfilePathById(baseDir, id) {
35923
- return path13.join(daemonDirById(baseDir, id), "daemon.pid");
36700
+ return path17.join(daemonDirById(baseDir, id), "daemon.pid");
35924
36701
  }
35925
36702
  function statusFilePathById(baseDir, id) {
35926
- return path13.join(daemonDirById(baseDir, id), "status.json");
36703
+ return path17.join(daemonDirById(baseDir, id), "status.json");
35927
36704
  }
35928
36705
  function isProcessAlive(pid) {
35929
36706
  try {
@@ -35983,9 +36760,9 @@ function syncDirectory(dir) {
35983
36760
  }
35984
36761
  }
35985
36762
  function writeExclusive(filePath, value) {
35986
- const dir = path13.dirname(filePath);
36763
+ const dir = path17.dirname(filePath);
35987
36764
  ensurePrivateDir2(dir);
35988
- const tempPath = path13.join(dir, `.${path13.basename(filePath)}.${process.pid}.${crypto5.randomBytes(12).toString("hex")}.tmp`);
36765
+ const tempPath = path17.join(dir, `.${path17.basename(filePath)}.${process.pid}.${crypto5.randomBytes(12).toString("hex")}.tmp`);
35989
36766
  let fd = fs12.openSync(tempPath, "wx", 384);
35990
36767
  try {
35991
36768
  fs12.writeFileSync(fd, JSON.stringify(value));
@@ -36007,9 +36784,9 @@ function writeExclusive(filePath, value) {
36007
36784
  }
36008
36785
  }
36009
36786
  function writePrivateJsonAtomic2(filePath, value) {
36010
- const dir = path13.dirname(filePath);
36787
+ const dir = path17.dirname(filePath);
36011
36788
  ensurePrivateDir2(dir);
36012
- const tempPath = path13.join(dir, `.${path13.basename(filePath)}.${process.pid}.${crypto5.randomBytes(12).toString("hex")}.tmp`);
36789
+ const tempPath = path17.join(dir, `.${path17.basename(filePath)}.${process.pid}.${crypto5.randomBytes(12).toString("hex")}.tmp`);
36013
36790
  let fd = fs12.openSync(tempPath, "wx", 384);
36014
36791
  try {
36015
36792
  fs12.writeFileSync(fd, JSON.stringify(value));
@@ -36033,8 +36810,8 @@ function writePrivateJsonAtomic2(filePath, value) {
36033
36810
  function secureExistingFile(filePath) {
36034
36811
  if (!fs12.existsSync(filePath))
36035
36812
  return;
36036
- const stat = fs12.lstatSync(filePath);
36037
- if (!stat.isFile())
36813
+ const stat2 = fs12.lstatSync(filePath);
36814
+ if (!stat2.isFile())
36038
36815
  throw new Error("unsafe daemon ownership file type");
36039
36816
  fs12.chmodSync(filePath, 384);
36040
36817
  }
@@ -36096,14 +36873,14 @@ function clearStaleOwnership(filePath, liveError) {
36096
36873
  } catch {}
36097
36874
  }
36098
36875
  function replacementLockPathById(baseDir, machineId) {
36099
- return path13.join(daemonDirById(baseDir, machineId), "daemon.replace.lock");
36876
+ return path17.join(daemonDirById(baseDir, machineId), "daemon.replace.lock");
36100
36877
  }
36101
36878
  function readReplacementLock(filePath) {
36102
36879
  if (!fs12.existsSync(filePath))
36103
36880
  return null;
36104
36881
  try {
36105
- const stat = fs12.lstatSync(filePath);
36106
- if (!stat.isFile())
36882
+ const stat2 = fs12.lstatSync(filePath);
36883
+ if (!stat2.isFile())
36107
36884
  throw new Error("unsafe daemon replacement lock type");
36108
36885
  fs12.chmodSync(filePath, 384);
36109
36886
  const content = JSON.parse(fs12.readFileSync(filePath, "utf8"));
@@ -36166,7 +36943,7 @@ function checkReplacementLock(baseDir, machineId, resumeRequestId) {
36166
36943
  }
36167
36944
  function acquireDaemonReplacementLock(args) {
36168
36945
  const lockPath = replacementLockPathById(args.baseDir, args.machineId);
36169
- ensurePrivateDir2(path13.dirname(lockPath));
36946
+ ensurePrivateDir2(path17.dirname(lockPath));
36170
36947
  checkReplacementLock(args.baseDir, args.machineId);
36171
36948
  const lock = {
36172
36949
  pid: process.pid,
@@ -36179,11 +36956,11 @@ function acquireDaemonReplacementLock(args) {
36179
36956
  return { path: lockPath, lock };
36180
36957
  }
36181
36958
  function coarseStartLockPath(baseDir) {
36182
- return path13.join(daemonsDir(baseDir), ".start.lock");
36959
+ return path17.join(daemonsDir(baseDir), ".start.lock");
36183
36960
  }
36184
36961
  function acquireCoarseLock(baseDir, ownerToken) {
36185
36962
  const lf = coarseStartLockPath(baseDir);
36186
- ensurePrivateDir2(path13.dirname(lf));
36963
+ ensurePrivateDir2(path17.dirname(lf));
36187
36964
  secureExistingFile(lf);
36188
36965
  clearStaleOwnership(lf, (pid) => new Error(`another daemon start is in progress on this machine (pid ${pid})`));
36189
36966
  writeExclusive(lf, { pid: process.pid, machineId: "coarse", startedAt: new Date().toISOString(), ownerToken });
@@ -36192,7 +36969,7 @@ function acquireCoarseLock(baseDir, ownerToken) {
36192
36969
  function acquireLaunchLock(baseDir, machineId, ownerToken, resumeRequestId) {
36193
36970
  const daemonDir = daemonDirById(baseDir, machineId);
36194
36971
  ensurePrivateDir2(daemonDir);
36195
- const lockPath = path13.join(daemonDir, "daemon.launch.lock");
36972
+ const lockPath = path17.join(daemonDir, "daemon.launch.lock");
36196
36973
  const finalPath = pidfilePathById(baseDir, machineId);
36197
36974
  checkReplacementLock(baseDir, machineId, resumeRequestId);
36198
36975
  secureExistingFile(lockPath);
@@ -36214,9 +36991,9 @@ function legacyPidfileCandidates(baseDir) {
36214
36991
  const candidates = [];
36215
36992
  for (const entry of fs12.readdirSync(dir, { withFileTypes: true })) {
36216
36993
  if (entry.isDirectory()) {
36217
- candidates.push(path13.join(dir, entry.name, "daemon.pid"));
36994
+ candidates.push(path17.join(dir, entry.name, "daemon.pid"));
36218
36995
  } else if (entry.isFile() && entry.name.endsWith(".pid")) {
36219
- candidates.push(path13.join(dir, entry.name));
36996
+ candidates.push(path17.join(dir, entry.name));
36220
36997
  }
36221
36998
  }
36222
36999
  return candidates;
@@ -36288,7 +37065,7 @@ function daemonList(opts) {
36288
37065
  for (const entry of fs12.readdirSync(dir, { withFileTypes: true })) {
36289
37066
  if (entry.isDirectory() && isDaemonId(entry.name)) {
36290
37067
  const id = entry.name;
36291
- pushRow(id, path13.join(dir, id, "daemon.pid"), path13.join(dir, id, "status.json"));
37068
+ pushRow(id, path17.join(dir, id, "daemon.pid"), path17.join(dir, id, "status.json"));
36292
37069
  }
36293
37070
  }
36294
37071
  return results;
@@ -36336,7 +37113,7 @@ function daemonIdsWithStatus(baseDir) {
36336
37113
  return [];
36337
37114
  const ids = [];
36338
37115
  for (const entry of fs12.readdirSync(dir, { withFileTypes: true })) {
36339
- if (entry.isDirectory() && isDaemonId(entry.name) && fs12.existsSync(path13.join(dir, entry.name, "status.json"))) {
37116
+ if (entry.isDirectory() && isDaemonId(entry.name) && fs12.existsSync(path17.join(dir, entry.name, "status.json"))) {
36340
37117
  ids.push(entry.name);
36341
37118
  }
36342
37119
  }
@@ -36399,16 +37176,16 @@ async function stopByPidfile(pf, notFoundHint) {
36399
37176
  }
36400
37177
  async function daemonStop(opts) {
36401
37178
  const baseDir = opts.baseDir || process.env.ALOOK_DATA_DIR || DEFAULT_BASE_DIR;
36402
- await stopByPidfile(path13.join(daemonDirById(baseDir, opts.id), "daemon.pid"), `no daemon with id '${opts.id}' (pidfile not found — check \`alook daemon list\`)`);
37179
+ await stopByPidfile(path17.join(daemonDirById(baseDir, opts.id), "daemon.pid"), `no daemon with id '${opts.id}' (pidfile not found — check \`alook daemon list\`)`);
36403
37180
  }
36404
37181
  function credentialFilePathByMachineId(baseDir, machineId) {
36405
- return path13.join(daemonsDir(baseDir), `${validateMachineId(machineId)}.credential.json`);
37182
+ return path17.join(daemonsDir(baseDir), `${validateMachineId(machineId)}.credential.json`);
36406
37183
  }
36407
37184
  function readCredentialFile(filePath) {
36408
37185
  if (!fs12.existsSync(filePath))
36409
37186
  return null;
36410
- const stat = fs12.lstatSync(filePath);
36411
- if (!stat.isFile())
37187
+ const stat2 = fs12.lstatSync(filePath);
37188
+ if (!stat2.isFile())
36412
37189
  throw new Error("unsafe daemon credential file type");
36413
37190
  fs12.chmodSync(filePath, 384);
36414
37191
  try {
@@ -36449,7 +37226,7 @@ function findExistingCredentialForBearer(baseDir, bearer) {
36449
37226
  for (const file2 of fs12.readdirSync(dir)) {
36450
37227
  if (!file2.endsWith(".credential.json"))
36451
37228
  continue;
36452
- const parsed = readCredentialFile(path13.join(dir, file2));
37229
+ const parsed = readCredentialFile(path17.join(dir, file2));
36453
37230
  if (parsed && parsed.credential === bearer)
36454
37231
  return parsed;
36455
37232
  }
@@ -36730,7 +37507,7 @@ function waitForReceipt(child, prepared) {
36730
37507
  };
36731
37508
  const configuredTestTimeout = NaN;
36732
37509
  const receiptTimeoutMs = Number.isFinite(configuredTestTimeout) && configuredTestTimeout > 0 ? configuredTestTimeout : START_RECEIPT_TIMEOUT_MS;
36733
- const timeout = setTimeout(() => settle(new Error(`daemon start timed out; inspect ${path13.join(prepared.daemonDir, "daemon.log")}`)), receiptTimeoutMs);
37510
+ const timeout = setTimeout(() => settle(new Error(`daemon start timed out; inspect ${path17.join(prepared.daemonDir, "daemon.log")}`)), receiptTimeoutMs);
36734
37511
  child.on("message", (message2) => {
36735
37512
  const accepted = message2;
36736
37513
  if (accepted.type === "daemon:accepted") {
@@ -36749,7 +37526,7 @@ function waitForReceipt(child, prepared) {
36749
37526
  settle(undefined, receipt);
36750
37527
  });
36751
37528
  child.once("exit", (code, signal) => {
36752
- settle(new Error(`daemon child exited before ready (${signal ?? code}); inspect ${path13.join(prepared.daemonDir, "daemon.log")}`));
37529
+ settle(new Error(`daemon child exited before ready (${signal ?? code}); inspect ${path17.join(prepared.daemonDir, "daemon.log")}`));
36753
37530
  });
36754
37531
  child.once("error", (error51) => settle(error51));
36755
37532
  });