@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/index.js CHANGED
@@ -91,6 +91,12 @@ function nanoid3(size = 21) {
91
91
  }
92
92
  var POOL_SIZE_MULTIPLIER = 128, pool, poolOffset;
93
93
  var init_nanoid = () => {};
94
+
95
+ // agent-driver/dist/contract.js
96
+ var SESSION_FILE_DISCOVERY_CAPABILITIES = ["supported", "unavailable"];
97
+
98
+ // agent-driver/dist/public-contract.js
99
+ var SESSION_FILE_DISCOVERY_CAPABILITIES2 = SESSION_FILE_DISCOVERY_CAPABILITIES;
94
100
  // agent-driver/dist/host/default-host.js
95
101
  import { randomUUID } from "node:crypto";
96
102
  function createDefaultAgentDriverHost(options = {}) {
@@ -1232,6 +1238,12 @@ function tryParseJsonLine(line) {
1232
1238
  return null;
1233
1239
  }
1234
1240
  }
1241
+ function asRecord(value) {
1242
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
1243
+ }
1244
+ function tryParseJsonRecord(line) {
1245
+ return asRecord(tryParseJsonLine(line));
1246
+ }
1235
1247
 
1236
1248
  // agent-driver/dist/adapters/claude/normalizer.js
1237
1249
  var API_ERROR_RE = /API Error:.*(?:Connection error|\b[45]\d{2}\b)/i;
@@ -1730,6 +1742,241 @@ class ClaudeTurnProtocol {
1730
1742
  }
1731
1743
  }
1732
1744
 
1745
+ // agent-driver/dist/adapters/claude/recent-context.js
1746
+ import { createReadStream as createReadStream2 } from "node:fs";
1747
+ import { homedir } from "node:os";
1748
+ import path6 from "node:path";
1749
+ import { createInterface } from "node:readline";
1750
+
1751
+ // agent-driver/dist/internal/recent-context.js
1752
+ import path5 from "node:path";
1753
+ import { createReadStream } from "node:fs";
1754
+ import { readdir, stat } from "node:fs/promises";
1755
+ function normalizeAbsolutePath(value) {
1756
+ if (typeof value !== "string" || !path5.isAbsolute(value))
1757
+ return null;
1758
+ return path5.normalize(value);
1759
+ }
1760
+ function normalizeModifiedAt(value) {
1761
+ const date = value instanceof Date ? value : typeof value === "string" || typeof value === "number" ? new Date(value) : null;
1762
+ if (!date || !Number.isFinite(date.getTime()))
1763
+ return null;
1764
+ return date.toISOString();
1765
+ }
1766
+ function isValidRecentContextTopK(value) {
1767
+ return Number.isSafeInteger(value) && value >= 0;
1768
+ }
1769
+ function isMissingPathError(error) {
1770
+ return error?.code === "ENOENT";
1771
+ }
1772
+ async function readFirstLine(filePath, maxBytes = 65536) {
1773
+ const stream = createReadStream(filePath, { highWaterMark: 1 });
1774
+ const bytes = [];
1775
+ let length = 0;
1776
+ try {
1777
+ for await (const chunk of stream) {
1778
+ const byte = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
1779
+ if (byte[0] === 10)
1780
+ break;
1781
+ if (length >= maxBytes)
1782
+ return null;
1783
+ bytes.push(byte);
1784
+ length += byte.length;
1785
+ }
1786
+ return length === 0 ? null : Buffer.concat(bytes, length).toString("utf8").replace(/\r$/, "");
1787
+ } catch (error) {
1788
+ if (isMissingPathError(error))
1789
+ return null;
1790
+ throw error;
1791
+ } finally {
1792
+ stream.destroy();
1793
+ }
1794
+ }
1795
+ async function collectJsonlFileCandidates(root, options = {}) {
1796
+ const candidates = [];
1797
+ const readDirectory = options.readDirectory ?? ((directory) => readdir(directory, { withFileTypes: true }));
1798
+ const statPath = options.statPath ?? stat;
1799
+ const visit = async (directory, remainingDepth, includeFiles) => {
1800
+ let entries;
1801
+ try {
1802
+ entries = await readDirectory(directory);
1803
+ } catch (error) {
1804
+ if (isMissingPathError(error))
1805
+ return;
1806
+ throw error;
1807
+ }
1808
+ await Promise.all(entries.map(async (entry) => {
1809
+ const entryPath = path5.join(directory, entry.name);
1810
+ if (entry.isDirectory() && remainingDepth > 0) {
1811
+ await visit(entryPath, remainingDepth - 1, true);
1812
+ } else if (includeFiles && entry.isFile() && entry.name.endsWith(".jsonl")) {
1813
+ try {
1814
+ const metadata = await statPath(entryPath);
1815
+ if (metadata.isFile())
1816
+ candidates.push({ filePath: entryPath, modifiedAt: metadata.mtime });
1817
+ } catch (error) {
1818
+ if (!isMissingPathError(error))
1819
+ throw error;
1820
+ }
1821
+ }
1822
+ }));
1823
+ };
1824
+ await visit(root, options.maxDepth ?? Number.POSITIVE_INFINITY, options.includeRootFiles ?? true);
1825
+ return candidates;
1826
+ }
1827
+ function retainNewest(values, key, value, topK) {
1828
+ const existing = values.get(key);
1829
+ if (existing) {
1830
+ if (value.modifiedAt > existing.modifiedAt)
1831
+ values.set(key, value);
1832
+ return;
1833
+ }
1834
+ if (values.size < topK) {
1835
+ values.set(key, value);
1836
+ return;
1837
+ }
1838
+ let oldest;
1839
+ for (const entry of values) {
1840
+ if (!oldest || entry[1].modifiedAt < oldest[1].modifiedAt)
1841
+ oldest = entry;
1842
+ }
1843
+ if (oldest && value.modifiedAt > oldest[1].modifiedAt) {
1844
+ values.delete(oldest[0]);
1845
+ values.set(key, value);
1846
+ }
1847
+ }
1848
+
1849
+ class RecentContextCollector {
1850
+ request;
1851
+ sessionFileCapability;
1852
+ sessions = new Map;
1853
+ projects = new Map;
1854
+ constructor(request, sessionFileCapability) {
1855
+ this.request = request;
1856
+ this.sessionFileCapability = sessionFileCapability;
1857
+ }
1858
+ add(candidate, target = "both") {
1859
+ const projectPath = normalizeAbsolutePath(candidate.projectPath);
1860
+ const modifiedAt = normalizeModifiedAt(candidate.modifiedAt);
1861
+ if (!projectPath || !modifiedAt)
1862
+ return;
1863
+ if (target !== "session") {
1864
+ retainNewest(this.projects, projectPath, { projectPath, modifiedAt }, this.request.recentProjectsTopK);
1865
+ }
1866
+ if (target === "project" || this.sessionFileCapability !== "supported")
1867
+ return;
1868
+ const sessionFilePath = normalizeAbsolutePath(candidate.sessionFilePath);
1869
+ if (!sessionFilePath)
1870
+ return;
1871
+ retainNewest(this.sessions, sessionFilePath, { sessionFilePath, projectPath, modifiedAt }, this.request.recentSessionFilesTopK);
1872
+ }
1873
+ get satisfied() {
1874
+ const sessionsSatisfied = this.sessionFileCapability === "unavailable" || this.sessions.size >= this.request.recentSessionFilesTopK;
1875
+ return sessionsSatisfied && this.projects.size >= this.request.recentProjectsTopK;
1876
+ }
1877
+ result() {
1878
+ const newestFirst = (left, right) => right.modifiedAt.localeCompare(left.modifiedAt);
1879
+ return {
1880
+ sessionFiles: {
1881
+ capability: this.sessionFileCapability,
1882
+ items: [...this.sessions.values()].sort(newestFirst).slice(0, this.request.recentSessionFilesTopK)
1883
+ },
1884
+ recentProjects: [...this.projects.values()].sort(newestFirst).slice(0, this.request.recentProjectsTopK)
1885
+ };
1886
+ }
1887
+ }
1888
+ function sanitizeRecentContextData(value, request) {
1889
+ if (!value || typeof value !== "object" || Array.isArray(value))
1890
+ return null;
1891
+ const candidate = value;
1892
+ if (!candidate.sessionFiles || typeof candidate.sessionFiles !== "object" || Array.isArray(candidate.sessionFiles)) {
1893
+ return null;
1894
+ }
1895
+ const sessionFiles = candidate.sessionFiles;
1896
+ const capability = sessionFiles.capability;
1897
+ if (capability !== "supported" && capability !== "unavailable" || !Array.isArray(sessionFiles.items)) {
1898
+ return null;
1899
+ }
1900
+ if (!Array.isArray(candidate.recentProjects))
1901
+ return null;
1902
+ const collector = new RecentContextCollector(request, capability);
1903
+ if (capability === "supported") {
1904
+ for (const item of sessionFiles.items) {
1905
+ if (!item || typeof item !== "object" || Array.isArray(item))
1906
+ continue;
1907
+ const record = item;
1908
+ collector.add({
1909
+ sessionFilePath: record.sessionFilePath,
1910
+ projectPath: record.projectPath,
1911
+ modifiedAt: record.modifiedAt
1912
+ }, "session");
1913
+ }
1914
+ }
1915
+ for (const item of candidate.recentProjects) {
1916
+ if (!item || typeof item !== "object" || Array.isArray(item))
1917
+ continue;
1918
+ const record = item;
1919
+ collector.add({ projectPath: record.projectPath, modifiedAt: record.modifiedAt }, "project");
1920
+ }
1921
+ return collector.result();
1922
+ }
1923
+
1924
+ // agent-driver/dist/adapters/claude/recent-context.js
1925
+ async function readClaudeProjectPath(filePath) {
1926
+ const input = createReadStream2(filePath);
1927
+ const lines = createInterface({ input, crlfDelay: Infinity });
1928
+ try {
1929
+ for await (const line of lines) {
1930
+ let record;
1931
+ try {
1932
+ record = JSON.parse(line);
1933
+ } catch {
1934
+ continue;
1935
+ }
1936
+ if (!record || typeof record !== "object")
1937
+ continue;
1938
+ const cwd = record.cwd;
1939
+ if (typeof cwd === "string" && path6.isAbsolute(cwd))
1940
+ return cwd;
1941
+ }
1942
+ return null;
1943
+ } catch (error) {
1944
+ if (isMissingPathError(error))
1945
+ return null;
1946
+ throw error;
1947
+ } finally {
1948
+ lines.close();
1949
+ input.destroy();
1950
+ }
1951
+ }
1952
+ async function discoverClaudeRecentContext(request, dependencies = {}) {
1953
+ const collector = new RecentContextCollector(request, "supported");
1954
+ if (collector.satisfied)
1955
+ return collector.result();
1956
+ const projectsRoot = path6.resolve(dependencies.projectsRoot ?? path6.join(process.env.CLAUDE_CONFIG_DIR || path6.join(homedir(), ".claude"), "projects"));
1957
+ const readProjectPath = dependencies.readProjectPath ?? readClaudeProjectPath;
1958
+ const candidates = await collectJsonlFileCandidates(projectsRoot, {
1959
+ includeRootFiles: false,
1960
+ maxDepth: 1,
1961
+ readDirectory: dependencies.readDirectory,
1962
+ statPath: dependencies.statPath
1963
+ });
1964
+ candidates.sort((left, right) => right.modifiedAt.getTime() - left.modifiedAt.getTime());
1965
+ for (const candidate of candidates) {
1966
+ const projectPath = await readProjectPath(candidate.filePath);
1967
+ if (!projectPath)
1968
+ continue;
1969
+ collector.add({
1970
+ sessionFilePath: candidate.filePath,
1971
+ projectPath,
1972
+ modifiedAt: candidate.modifiedAt
1973
+ });
1974
+ if (collector.satisfied)
1975
+ break;
1976
+ }
1977
+ return collector.result();
1978
+ }
1979
+
1733
1980
  // agent-driver/dist/adapters/claude/index.js
1734
1981
  var CLAUDE_MODEL_CATALOG = {
1735
1982
  updateMode: "unsupported",
@@ -1751,6 +1998,9 @@ class ClaudeDriver {
1751
1998
  turnProtocol = new ClaudeTurnProtocol;
1752
1999
  eventNormalizer = new ClaudeEventNormalizer(this.turnProtocol);
1753
2000
  pendingInterrupt;
2001
+ discoverRecentContext(request) {
2002
+ return discoverClaudeRecentContext(request);
2003
+ }
1754
2004
  beginTurn() {
1755
2005
  this.pendingInterrupt = undefined;
1756
2006
  const receipt = this.turnProtocol.beginTurn();
@@ -2014,16 +2264,16 @@ function normalizeFileChangeInput(item) {
2014
2264
  for (const candidate of changePaths) {
2015
2265
  if (typeof candidate !== "string")
2016
2266
  continue;
2017
- const path5 = candidate.trim();
2018
- if (!path5 || seen.has(path5))
2267
+ const path7 = candidate.trim();
2268
+ if (!path7 || seen.has(path7))
2019
2269
  continue;
2020
- seen.add(path5);
2021
- paths.push(path5);
2270
+ seen.add(path7);
2271
+ paths.push(path7);
2022
2272
  }
2023
2273
  if (paths.length === 0 && typeof item?.path === "string") {
2024
- const path5 = item.path.trim();
2025
- if (path5)
2026
- paths.push(path5);
2274
+ const path7 = item.path.trim();
2275
+ if (path7)
2276
+ paths.push(path7);
2027
2277
  }
2028
2278
  return paths.length > 0 ? { path: paths.join(", ") } : {};
2029
2279
  }
@@ -2392,7 +2642,7 @@ class CodexEventNormalizer {
2392
2642
 
2393
2643
  // agent-driver/dist/adapters/codex/home.js
2394
2644
  import * as os from "os";
2395
- import * as path5 from "path";
2645
+ import * as path7 from "path";
2396
2646
  function readConfiguredCodexHome(env) {
2397
2647
  const raw = env.CODEX_HOME;
2398
2648
  return typeof raw === "string" && raw.trim().length > 0 ? raw : null;
@@ -2400,8 +2650,8 @@ function readConfiguredCodexHome(env) {
2400
2650
  function resolveCodexHomeRootFromEnv(env = process.env, opts = {}) {
2401
2651
  const raw = readConfiguredCodexHome(env);
2402
2652
  if (raw)
2403
- return path5.resolve(opts.cwd ?? process.cwd(), raw);
2404
- return path5.join(opts.defaultHomeDir ?? os.homedir(), ".codex");
2653
+ return path7.resolve(opts.cwd ?? process.cwd(), raw);
2654
+ return path7.join(opts.defaultHomeDir ?? os.homedir(), ".codex");
2405
2655
  }
2406
2656
 
2407
2657
  // agent-driver/dist/internal/errors.js
@@ -2494,6 +2744,49 @@ function parsePiModelCatalog(values) {
2494
2744
  return catalogFromIds(ids);
2495
2745
  }
2496
2746
 
2747
+ // agent-driver/dist/adapters/codex/recent-context.js
2748
+ import path8 from "node:path";
2749
+ function isChildSession(payload) {
2750
+ if (payload.parentThreadId != null || payload.parent_thread_id != null)
2751
+ return true;
2752
+ const source = payload.source;
2753
+ if (typeof source === "string")
2754
+ return source.toLowerCase().startsWith("subagent");
2755
+ const sourceRecord = asRecord(source);
2756
+ return sourceRecord != null && (("subagent" in sourceRecord) || ("subAgent" in sourceRecord));
2757
+ }
2758
+ async function discoverCodexRecentContext(request, dependencies = {}) {
2759
+ const collector = new RecentContextCollector(request, "supported");
2760
+ if (collector.satisfied)
2761
+ return collector.result();
2762
+ const sessionsRoot = path8.resolve(dependencies.sessionsRoot ?? path8.join(resolveCodexHomeRootFromEnv(), "sessions"));
2763
+ const readHeader = dependencies.readHeader ?? readFirstLine;
2764
+ const candidates = await collectJsonlFileCandidates(sessionsRoot, {
2765
+ readDirectory: dependencies.readDirectory,
2766
+ statPath: dependencies.statPath
2767
+ });
2768
+ candidates.sort((left, right) => right.modifiedAt.getTime() - left.modifiedAt.getTime());
2769
+ for (const candidate of candidates) {
2770
+ const line = await readHeader(candidate.filePath);
2771
+ if (!line)
2772
+ continue;
2773
+ const header = tryParseJsonRecord(line);
2774
+ if (!header)
2775
+ continue;
2776
+ const payload = asRecord(header.payload);
2777
+ if (header.type !== "session_meta" || !payload || isChildSession(payload))
2778
+ continue;
2779
+ collector.add({
2780
+ sessionFilePath: candidate.filePath,
2781
+ projectPath: payload.cwd,
2782
+ modifiedAt: candidate.modifiedAt
2783
+ });
2784
+ if (collector.satisfied)
2785
+ break;
2786
+ }
2787
+ return collector.result();
2788
+ }
2789
+
2497
2790
  // agent-driver/dist/adapters/codex/index.js
2498
2791
  var SETTINGS_UPDATE_TIMEOUT_MS = 5000;
2499
2792
  var MODEL_LIST_TIMEOUT_MS = 5000;
@@ -2522,6 +2815,9 @@ class CodexDriver {
2522
2815
  eventNormalizer = new CodexEventNormalizer;
2523
2816
  pendingAccountReadRequestIds = new Set;
2524
2817
  requestId = 0;
2818
+ discoverRecentContext(request) {
2819
+ return discoverCodexRecentContext(request);
2820
+ }
2525
2821
  codexHomeRoot = null;
2526
2822
  proc = null;
2527
2823
  pendingInitialPrompt = null;
@@ -3698,6 +3994,196 @@ class CursorAcpLane {
3698
3994
  }
3699
3995
  }
3700
3996
 
3997
+ // agent-driver/dist/internal/discovery-process.js
3998
+ import { StringDecoder } from "node:string_decoder";
3999
+ function toBuffer(chunk) {
4000
+ if (Buffer.isBuffer(chunk))
4001
+ return chunk;
4002
+ if (chunk instanceof Uint8Array)
4003
+ return Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength);
4004
+ return Buffer.from(String(chunk));
4005
+ }
4006
+ async function cleanupProcess(process2, label) {
4007
+ if (process2.pid)
4008
+ await killProcessTree(process2.pid, { graceMs: 250 });
4009
+ else if (process2.exitCode === null && process2.signalCode === null && !process2.kill("SIGTERM")) {
4010
+ throw new Error(`${label} discovery cleanup failed`);
4011
+ }
4012
+ }
4013
+ function onStream(stream, event, listener) {
4014
+ stream?.on?.(event, listener);
4015
+ }
4016
+ function runBoundedDiscoveryProcess(options) {
4017
+ return new Promise((resolve2, reject) => {
4018
+ const decoder = new StringDecoder("utf8");
4019
+ let settled = false;
4020
+ let decoderEnded = false;
4021
+ let outputBytes = 0;
4022
+ const settle = (result, error) => {
4023
+ if (settled)
4024
+ return;
4025
+ settled = true;
4026
+ clearTimeout(timer);
4027
+ if (!decoderEnded)
4028
+ decoder.end();
4029
+ Promise.resolve().then(() => options.cleanup?.(options.process) ?? cleanupProcess(options.process, options.label)).then(() => error ? reject(error) : resolve2(result), () => reject(error ?? new Error(`${options.label} discovery cleanup failed`)));
4030
+ };
4031
+ const control = {
4032
+ get outputBytes() {
4033
+ return outputBytes;
4034
+ },
4035
+ finish: (result) => settle(result),
4036
+ fail: (message) => settle(undefined, new Error(message)),
4037
+ flushStdout: () => {
4038
+ if (settled || decoderEnded)
4039
+ return;
4040
+ decoderEnded = true;
4041
+ options.onStdout(decoder.end(), true, control);
4042
+ },
4043
+ write: (line) => {
4044
+ const stdin = options.process.stdin;
4045
+ if (!stdin || stdin.destroyed || stdin.writableEnded || stdin.writable === false) {
4046
+ return control.fail(`${options.label} discovery transport is unavailable`);
4047
+ }
4048
+ try {
4049
+ stdin.write(line);
4050
+ } catch {
4051
+ control.fail(`${options.label} discovery transport write failed`);
4052
+ }
4053
+ }
4054
+ };
4055
+ const addBytes = (chunk, decode) => {
4056
+ if (settled)
4057
+ return;
4058
+ const bytes = toBuffer(chunk);
4059
+ outputBytes += bytes.byteLength;
4060
+ if (outputBytes > options.outputMaxBytes) {
4061
+ control.fail(`${options.label} discovery output exceeded its bound`);
4062
+ } else if (decode)
4063
+ options.onStdout(decoder.write(bytes), false, control);
4064
+ };
4065
+ const timer = setTimeout(() => control.fail(`${options.label} discovery timed out`), Math.max(1, options.timeoutMs));
4066
+ timer.unref?.();
4067
+ options.process.stdout?.on("data", (chunk) => addBytes(chunk, true));
4068
+ options.process.stderr?.on("data", (chunk) => addBytes(chunk, false));
4069
+ onStream(options.process.stdout, "end", control.flushStdout);
4070
+ for (const stream of [options.process.stdin, options.process.stdout, options.process.stderr]) {
4071
+ onStream(stream, "error", () => control.fail(`${options.label} discovery transport failed`));
4072
+ }
4073
+ options.process.on("error", () => control.fail(`${options.label} discovery process failed`));
4074
+ options.process.on(options.exitEvent, (code, signal) => options.onExit(code, signal, control));
4075
+ options.onStart?.(control);
4076
+ });
4077
+ }
4078
+
4079
+ // agent-driver/dist/adapters/cursor/recent-context.js
4080
+ var ACP_PROTOCOL_VERSION3 = 1;
4081
+ var AUTH_METHOD_ID3 = "cursor_login";
4082
+ var CURSOR_DISCOVERY_TIMEOUT_MS = 30000;
4083
+ var CURSOR_DISCOVERY_OUTPUT_MAX_BYTES = 4 * 1024 * 1024;
4084
+ async function discoverCursorRecentContext(request, dependencies = {}) {
4085
+ const collector = new RecentContextCollector(request, "unavailable");
4086
+ if (collector.satisfied)
4087
+ return collector.result();
4088
+ const spec = resolveSpawnSpec("cursor-agent", ["acp"], request.command);
4089
+ const processHandle = (dependencies.spawn ?? spawnAgentProcess)(spec.command, spec.args, {
4090
+ cwd: dependencies.cwd ?? process.cwd(),
4091
+ env: { ...process.env, CI: "1" },
4092
+ shell: spec.shell
4093
+ });
4094
+ let buffer = "";
4095
+ let requestId = 0;
4096
+ let expectedId = 0;
4097
+ let expectedMethod = "";
4098
+ const seenCursors = new Set;
4099
+ const requestRpc = (method, params, control) => {
4100
+ expectedId = ++requestId;
4101
+ expectedMethod = method;
4102
+ control.write(`${jsonRpcRequest(method, params, expectedId)}
4103
+ `);
4104
+ };
4105
+ const requestPage = (control, cursor) => requestRpc("session/list", cursor ? { cursor } : {}, control);
4106
+ const onLine = (line, control) => {
4107
+ const message = asRecord(tryParseJsonLine(line));
4108
+ if (!message || message.id !== expectedId)
4109
+ return;
4110
+ if (message.error !== undefined)
4111
+ return control.fail("Cursor discovery request failed");
4112
+ const result = asRecord(message.result);
4113
+ if (!result)
4114
+ return control.fail("Cursor discovery returned an invalid response");
4115
+ if (expectedMethod === "initialize") {
4116
+ if (result.protocolVersion !== ACP_PROTOCOL_VERSION3) {
4117
+ return control.fail("Cursor discovery protocol is incompatible");
4118
+ }
4119
+ const capabilities = asRecord(result.agentCapabilities);
4120
+ const sessionCapabilities = asRecord(capabilities?.sessionCapabilities);
4121
+ if (sessionCapabilities?.list !== true && !asRecord(sessionCapabilities?.list)) {
4122
+ return control.fail("Cursor session listing is unavailable");
4123
+ }
4124
+ const authMethods = Array.isArray(result.authMethods) ? result.authMethods : [];
4125
+ if (!authMethods.some((method) => asRecord(method)?.id === AUTH_METHOD_ID3)) {
4126
+ return control.fail("Cursor discovery authentication is unavailable");
4127
+ }
4128
+ requestRpc("authenticate", { methodId: AUTH_METHOD_ID3 }, control);
4129
+ return;
4130
+ }
4131
+ if (expectedMethod === "authenticate") {
4132
+ requestPage(control);
4133
+ return;
4134
+ }
4135
+ if (expectedMethod !== "session/list")
4136
+ return control.fail("Cursor discovery state is invalid");
4137
+ const sessions = Array.isArray(result.sessions) ? result.sessions : Array.isArray(result.data) ? result.data : [];
4138
+ for (const value of sessions) {
4139
+ const session = asRecord(value);
4140
+ if (!session)
4141
+ continue;
4142
+ collector.add({ projectPath: session.cwd, modifiedAt: session.updatedAt });
4143
+ if (collector.satisfied)
4144
+ return control.finish(collector.result());
4145
+ }
4146
+ const nextCursor = typeof result.nextCursor === "string" && result.nextCursor ? result.nextCursor : undefined;
4147
+ if (!nextCursor)
4148
+ return control.finish(collector.result());
4149
+ if (seenCursors.has(nextCursor))
4150
+ return control.fail("Cursor discovery cursor repeated");
4151
+ seenCursors.add(nextCursor);
4152
+ requestPage(control, nextCursor);
4153
+ };
4154
+ return runBoundedDiscoveryProcess({
4155
+ process: processHandle,
4156
+ label: "Cursor",
4157
+ timeoutMs: dependencies.timeoutMs ?? CURSOR_DISCOVERY_TIMEOUT_MS,
4158
+ outputMaxBytes: dependencies.outputMaxBytes ?? CURSOR_DISCOVERY_OUTPUT_MAX_BYTES,
4159
+ cleanup: dependencies.cleanup,
4160
+ exitEvent: "exit",
4161
+ onStdout: (text, final, control) => {
4162
+ buffer += text;
4163
+ const lines = buffer.split(`
4164
+ `);
4165
+ buffer = lines.pop() ?? "";
4166
+ for (const line of lines)
4167
+ if (line.trim())
4168
+ onLine(line, control);
4169
+ if (final && buffer.trim()) {
4170
+ const line = buffer;
4171
+ buffer = "";
4172
+ onLine(line, control);
4173
+ }
4174
+ },
4175
+ onExit: (_code, _signal, control) => control.fail("Cursor discovery process exited early"),
4176
+ onStart: (control) => requestRpc("initialize", {
4177
+ protocolVersion: ACP_PROTOCOL_VERSION3,
4178
+ clientCapabilities: {
4179
+ fs: { readTextFile: false, writeTextFile: false },
4180
+ terminal: false
4181
+ },
4182
+ clientInfo: { name: "alook-agent-driver-discovery", version: "0.1.31" }
4183
+ }, control)
4184
+ });
4185
+ }
4186
+
3701
4187
  // agent-driver/dist/adapters/cursor/index.js
3702
4188
  class CursorDriver {
3703
4189
  catalogProbe;
@@ -3709,6 +4195,9 @@ class CursorDriver {
3709
4195
  wakeStart: "immediate",
3710
4196
  terminalOwnership: "transport_request"
3711
4197
  };
4198
+ discoverRecentContext(request) {
4199
+ return discoverCursorRecentContext(request);
4200
+ }
3712
4201
  constructor(catalogProbe = probeCursorAcpCatalog) {
3713
4202
  this.catalogProbe = catalogProbe;
3714
4203
  }
@@ -4203,7 +4692,7 @@ class OpenCodeServiceLane {
4203
4692
  "/api/session/{sessionID}/permission/{requestID}/reply",
4204
4693
  "/api/event"
4205
4694
  ];
4206
- if (!paths || required.some((path6) => !record3(paths[path6]))) {
4695
+ if (!paths || required.some((path9) => !record3(paths[path9]))) {
4207
4696
  throw new OpenCodeIncompatibleError("Installed OpenCode service is missing required v2 session capabilities");
4208
4697
  }
4209
4698
  }
@@ -4261,8 +4750,8 @@ class OpenCodeServiceLane {
4261
4750
  const controller = new AbortController;
4262
4751
  this.durableAbort = controller;
4263
4752
  try {
4264
- const path6 = `/api/session/${encodeURIComponent(this.sessionId)}/event?after=${this.lastDurableSeq}`;
4265
- const response = await this.openStream(path6, controller, "durable event stream");
4753
+ const path9 = `/api/session/${encodeURIComponent(this.sessionId)}/event?after=${this.lastDurableSeq}`;
4754
+ const response = await this.openStream(path9, controller, "durable event stream");
4266
4755
  await this.catchUpHistory(true);
4267
4756
  if (!this.isIdentity(identity))
4268
4757
  return;
@@ -4336,12 +4825,12 @@ class OpenCodeServiceLane {
4336
4825
  return;
4337
4826
  this.protocolFailure(`OpenCode ${kind} stream stopped unexpectedly`, error);
4338
4827
  }
4339
- async openStream(path6, lifecycle, operation) {
4828
+ async openStream(path9, lifecycle, operation) {
4340
4829
  const deadline = new AbortController;
4341
4830
  const timeout = setTimeout(() => deadline.abort(), this.options.requestTimeoutMs ?? REQUEST_TIMEOUT_MS);
4342
4831
  timeout.unref?.();
4343
4832
  try {
4344
- const response = await this.fetchFn(`${this.baseUrl}${path6}`, {
4833
+ const response = await this.fetchFn(`${this.baseUrl}${path9}`, {
4345
4834
  method: "GET",
4346
4835
  headers: this.headers({ accept: "text/event-stream" }),
4347
4836
  signal: AbortSignal.any([lifecycle.signal, deadline.signal])
@@ -4768,8 +5257,8 @@ class OpenCodeServiceLane {
4768
5257
  turnOwner: root.receipt
4769
5258
  });
4770
5259
  }
4771
- async requestNoContent(path6, method, body, operation) {
4772
- const response = await this.fetchWithTimeout(path6, {
5260
+ async requestNoContent(path9, method, body, operation) {
5261
+ const response = await this.fetchWithTimeout(path9, {
4773
5262
  method,
4774
5263
  ...body ? {
4775
5264
  headers: { "content-type": "application/json" },
@@ -4779,7 +5268,7 @@ class OpenCodeServiceLane {
4779
5268
  if (!response.ok)
4780
5269
  throw new OpenCodeHttpError(response.status, operation);
4781
5270
  }
4782
- async fetchWithTimeout(path6, init, operation, timeoutMs = this.options.requestTimeoutMs ?? REQUEST_TIMEOUT_MS) {
5271
+ async fetchWithTimeout(path9, init, operation, timeoutMs = this.options.requestTimeoutMs ?? REQUEST_TIMEOUT_MS) {
4783
5272
  if (this.stopping)
4784
5273
  throw new Error("OpenCode service lane is stopping");
4785
5274
  const controller = new AbortController;
@@ -4787,7 +5276,7 @@ class OpenCodeServiceLane {
4787
5276
  const timer = setTimeout(() => controller.abort(), timeoutMs);
4788
5277
  timer.unref?.();
4789
5278
  try {
4790
- return await this.fetchFn(`${this.baseUrl}${path6}`, {
5279
+ return await this.fetchFn(`${this.baseUrl}${path9}`, {
4791
5280
  ...init,
4792
5281
  headers: this.headers(init.headers),
4793
5282
  signal: controller.signal
@@ -4799,7 +5288,7 @@ class OpenCodeServiceLane {
4799
5288
  this.requestControllers.delete(controller);
4800
5289
  }
4801
5290
  }
4802
- async fetchJsonWithTimeout(path6, init, operation, timeoutMs = this.options.requestTimeoutMs ?? REQUEST_TIMEOUT_MS) {
5291
+ async fetchJsonWithTimeout(path9, init, operation, timeoutMs = this.options.requestTimeoutMs ?? REQUEST_TIMEOUT_MS) {
4803
5292
  if (this.stopping)
4804
5293
  throw new OpenCodeStoppedError("OpenCode service lane is stopping");
4805
5294
  const controller = new AbortController;
@@ -4811,7 +5300,7 @@ class OpenCodeServiceLane {
4811
5300
  }, timeoutMs);
4812
5301
  timer.unref?.();
4813
5302
  try {
4814
- const response = await this.fetchFn(`${this.baseUrl}${path6}`, {
5303
+ const response = await this.fetchFn(`${this.baseUrl}${path9}`, {
4815
5304
  ...init,
4816
5305
  headers: this.headers(init.headers),
4817
5306
  signal: controller.signal
@@ -4904,6 +5393,75 @@ class OpenCodeServiceLane {
4904
5393
  }
4905
5394
  }
4906
5395
 
5396
+ // agent-driver/dist/adapters/opencode/recent-context.js
5397
+ var OPENCODE_DISCOVERY_TIMEOUT_MS = 15000;
5398
+ var OPENCODE_DISCOVERY_OUTPUT_MAX_BYTES = 4 * 1024 * 1024;
5399
+ function collectCommandOutput(command, args, shell, dependencies, timeoutMs, outputMaxBytes) {
5400
+ const processHandle = (dependencies.spawn ?? spawnAgentProcess)(command, args, {
5401
+ cwd: dependencies.cwd ?? process.cwd(),
5402
+ env: { ...process.env, CI: "1" },
5403
+ shell,
5404
+ stdin: "ignore"
5405
+ });
5406
+ let output = "";
5407
+ return runBoundedDiscoveryProcess({
5408
+ process: processHandle,
5409
+ label: "OpenCode",
5410
+ timeoutMs,
5411
+ outputMaxBytes,
5412
+ cleanup: dependencies.cleanup,
5413
+ exitEvent: "close",
5414
+ onStdout: (text) => {
5415
+ output += text;
5416
+ },
5417
+ onExit: (code, _signal, control) => {
5418
+ if (code !== 0)
5419
+ return control.fail("OpenCode session listing failed");
5420
+ control.flushStdout();
5421
+ control.finish({ output, outputBytes: control.outputBytes });
5422
+ }
5423
+ });
5424
+ }
5425
+ async function discoverOpenCodeRecentContext(request, dependencies = {}) {
5426
+ const collector = new RecentContextCollector(request, "unavailable");
5427
+ if (collector.satisfied)
5428
+ return collector.result();
5429
+ const startedAt = Date.now();
5430
+ const timeoutMs = dependencies.timeoutMs ?? OPENCODE_DISCOVERY_TIMEOUT_MS;
5431
+ let remainingOutputBytes = dependencies.outputMaxBytes ?? OPENCODE_DISCOVERY_OUTPUT_MAX_BYTES;
5432
+ let maxCount = Math.max(1, Math.min(Number.MAX_SAFE_INTEGER, request.recentProjectsTopK * 10));
5433
+ while (!collector.satisfied) {
5434
+ const remainingTimeoutMs = timeoutMs - (Date.now() - startedAt);
5435
+ if (remainingTimeoutMs <= 0)
5436
+ throw new Error("OpenCode discovery timed out");
5437
+ const spec = resolveSpawnSpec("opencode", ["session", "list", "--format", "json", "--max-count", String(maxCount), "--pure"], request.command);
5438
+ const commandOutput = await collectCommandOutput(spec.command, spec.args, spec.shell, dependencies, remainingTimeoutMs, remainingOutputBytes);
5439
+ remainingOutputBytes -= commandOutput.outputBytes;
5440
+ let parsed;
5441
+ try {
5442
+ parsed = JSON.parse(commandOutput.output);
5443
+ } catch {
5444
+ throw new Error("OpenCode session listing returned invalid JSON");
5445
+ }
5446
+ if (!Array.isArray(parsed))
5447
+ throw new Error("OpenCode session listing returned an invalid response");
5448
+ for (const value of parsed) {
5449
+ const session = asRecord(value);
5450
+ if (!session)
5451
+ continue;
5452
+ const modifiedAt = session.updated ?? session.updatedAt;
5453
+ collector.add({ projectPath: session.directory, modifiedAt });
5454
+ }
5455
+ if (collector.satisfied || parsed.length < maxCount)
5456
+ break;
5457
+ const nextMaxCount = Math.min(Number.MAX_SAFE_INTEGER, maxCount * 2);
5458
+ if (nextMaxCount === maxCount)
5459
+ throw new Error("OpenCode session listing could not prove the requested Top-K");
5460
+ maxCount = nextMaxCount;
5461
+ }
5462
+ return collector.result();
5463
+ }
5464
+
4907
5465
  // agent-driver/dist/adapters/opencode/index.js
4908
5466
  function createOpenCodeMessageId() {
4909
5467
  return `msg_${randomBytes3(16).toString("hex")}`;
@@ -4922,6 +5480,9 @@ class OpenCodeDriver {
4922
5480
  constructor(outputProbe = probeCommandOutput) {
4923
5481
  this.outputProbe = outputProbe;
4924
5482
  }
5483
+ discoverRecentContext(request) {
5484
+ return discoverOpenCodeRecentContext(request);
5485
+ }
4925
5486
  probe(command) {
4926
5487
  const result = probeCliRuntime("opencode", {}, command);
4927
5488
  if (result.status !== "healthy")
@@ -4968,8 +5529,8 @@ class OpenCodeDriver {
4968
5529
  // agent-driver/dist/adapters/pi/index.js
4969
5530
  import { createRequire } from "module";
4970
5531
  import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync2, realpathSync } from "fs";
4971
- import { homedir as homedir2 } from "os";
4972
- import * as path7 from "path";
5532
+ import { homedir as homedir4 } from "os";
5533
+ import * as path11 from "path";
4973
5534
 
4974
5535
  // agent-driver/dist/controller/sdk-host.js
4975
5536
  import { EventEmitter as EventEmitter4 } from "events";
@@ -5084,7 +5645,7 @@ class SdkLane {
5084
5645
 
5085
5646
  // agent-driver/dist/adapters/pi/sessionDeps.js
5086
5647
  import { readFileSync } from "fs";
5087
- import * as path6 from "path";
5648
+ import * as path9 from "path";
5088
5649
  import { pathToFileURL } from "url";
5089
5650
  var PI_SDK_PACKAGE_NAME = "@earendil-works/pi-coding-agent";
5090
5651
  var cachedSdkPromise = null;
@@ -5093,9 +5654,9 @@ async function importPiSdkFromGlobalInstall() {
5093
5654
  if (!dir) {
5094
5655
  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`);
5095
5656
  }
5096
- const pkg = JSON.parse(readFileSync(path6.join(dir, "package.json"), "utf-8"));
5657
+ const pkg = JSON.parse(readFileSync(path9.join(dir, "package.json"), "utf-8"));
5097
5658
  const entry = pkg.exports?.["."]?.import ?? pkg.main ?? "./dist/index.js";
5098
- const entryPath = path6.join(dir, entry);
5659
+ const entryPath = path9.join(dir, entry);
5099
5660
  const barrel = await import(pathToFileURL(entryPath).href);
5100
5661
  return withSessionDirHelper(barrel, entryPath);
5101
5662
  }
@@ -5103,7 +5664,7 @@ async function withSessionDirHelper(barrel, entryPath) {
5103
5664
  if (typeof barrel.getDefaultSessionDir === "function")
5104
5665
  return barrel;
5105
5666
  try {
5106
- const deepPath = path6.join(path6.dirname(entryPath), "core", "session-manager.js");
5667
+ const deepPath = path9.join(path9.dirname(entryPath), "core", "session-manager.js");
5107
5668
  const deep = await import(pathToFileURL(deepPath).href);
5108
5669
  if (typeof deep.getDefaultSessionDir !== "function")
5109
5670
  return barrel;
@@ -5183,6 +5744,51 @@ function createPiSessionDependencies(ctx, loadSdk = loadPiSdkModule) {
5183
5744
  };
5184
5745
  }
5185
5746
 
5747
+ // agent-driver/dist/adapters/pi/recent-context.js
5748
+ import { homedir as homedir3 } from "node:os";
5749
+ import path10 from "node:path";
5750
+ function expandTildePath(value) {
5751
+ if (value === "~")
5752
+ return homedir3();
5753
+ if (value.startsWith("~/"))
5754
+ return path10.join(homedir3(), value.slice(2));
5755
+ return value;
5756
+ }
5757
+ async function discoverPiRecentContext(request, dependencies = {}) {
5758
+ const collector = new RecentContextCollector(request, "supported");
5759
+ if (collector.satisfied)
5760
+ return collector.result();
5761
+ const customSessionDirectory = process.env.PI_CODING_AGENT_SESSION_DIR;
5762
+ const sessionsRoot = path10.resolve(expandTildePath(dependencies.sessionsRoot ?? customSessionDirectory ?? path10.join(process.env.PI_CODING_AGENT_DIR || path10.join(homedir3(), ".pi", "agent"), "sessions")));
5763
+ const scanDirectSessions = dependencies.sessionsRoot == null && customSessionDirectory != null;
5764
+ const readHeader = dependencies.readHeader ?? readFirstLine;
5765
+ const candidates = await collectJsonlFileCandidates(sessionsRoot, {
5766
+ includeRootFiles: scanDirectSessions,
5767
+ maxDepth: 1,
5768
+ readDirectory: dependencies.readDirectory,
5769
+ statPath: dependencies.statPath
5770
+ });
5771
+ candidates.sort((left, right) => right.modifiedAt.getTime() - left.modifiedAt.getTime());
5772
+ for (const candidate of candidates) {
5773
+ const line = await readHeader(candidate.filePath);
5774
+ if (!line)
5775
+ continue;
5776
+ const header = tryParseJsonRecord(line);
5777
+ if (!header)
5778
+ continue;
5779
+ if (header.type !== "session" || header.parentSession != null)
5780
+ continue;
5781
+ collector.add({
5782
+ sessionFilePath: candidate.filePath,
5783
+ projectPath: header.cwd,
5784
+ modifiedAt: candidate.modifiedAt
5785
+ });
5786
+ if (collector.satisfied)
5787
+ break;
5788
+ }
5789
+ return collector.result();
5790
+ }
5791
+
5186
5792
  // agent-driver/dist/adapters/pi/index.js
5187
5793
  var PI_SDK_PACKAGE_NAME2 = "@earendil-works/pi-coding-agent";
5188
5794
  var PI_MODEL_PROBE_TIMEOUT_MS = 5000;
@@ -5201,15 +5807,15 @@ function resolvePiSdkPackageDir(deps = {}) {
5201
5807
  if (!binPath)
5202
5808
  return;
5203
5809
  try {
5204
- let dir = path7.dirname(realpathSync(binPath));
5810
+ let dir = path11.dirname(realpathSync(binPath));
5205
5811
  const MAX_DEPTH = 8;
5206
5812
  for (let i = 0;i < MAX_DEPTH; i++) {
5207
- if (isPiSdkPackageJson(path7.join(dir, "package.json")))
5813
+ if (isPiSdkPackageJson(path11.join(dir, "package.json")))
5208
5814
  return dir;
5209
- const siblingDir = path7.join(dir, "node_modules", PI_SDK_PACKAGE_NAME2);
5210
- if (isPiSdkPackageJson(path7.join(siblingDir, "package.json")))
5815
+ const siblingDir = path11.join(dir, "node_modules", PI_SDK_PACKAGE_NAME2);
5816
+ if (isPiSdkPackageJson(path11.join(siblingDir, "package.json")))
5211
5817
  return siblingDir;
5212
- const parent = path7.dirname(dir);
5818
+ const parent = path11.dirname(dir);
5213
5819
  if (parent === dir)
5214
5820
  break;
5215
5821
  dir = parent;
@@ -5226,21 +5832,21 @@ function findPiSessionFile(sessionDir, sessionId) {
5226
5832
  }
5227
5833
  const suffix = `_${sessionId}.jsonl`;
5228
5834
  const match = entries.find((entry) => entry.endsWith(suffix));
5229
- return match ? path7.join(sessionDir, match) : null;
5835
+ return match ? path11.join(sessionDir, match) : null;
5230
5836
  }
5231
5837
  function resolvePiSessionDir(sdk, cwd) {
5232
5838
  if (typeof sdk.getDefaultSessionDir === "function")
5233
5839
  return sdk.getDefaultSessionDir(cwd);
5234
- const agentDir = typeof sdk.getAgentDir === "function" ? sdk.getAgentDir() : path7.join(homedir2(), ".pi", "agent");
5235
- const encoded = `--${path7.resolve(cwd).replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--`;
5236
- return path7.join(agentDir, "sessions", encoded);
5840
+ const agentDir = typeof sdk.getAgentDir === "function" ? sdk.getAgentDir() : path11.join(homedir4(), ".pi", "agent");
5841
+ const encoded = `--${path11.resolve(cwd).replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--`;
5842
+ return path11.join(agentDir, "sessions", encoded);
5237
5843
  }
5238
5844
  function resolvePiSdkVersionFromPath(deps = {}) {
5239
5845
  const dir = resolvePiSdkPackageDir(deps);
5240
5846
  if (!dir)
5241
5847
  return;
5242
5848
  try {
5243
- const pkg = JSON.parse(readFileSync2(path7.join(dir, "package.json"), "utf-8"));
5849
+ const pkg = JSON.parse(readFileSync2(path11.join(dir, "package.json"), "utf-8"));
5244
5850
  return pkg.version;
5245
5851
  } catch {
5246
5852
  return;
@@ -5344,6 +5950,9 @@ class PiDriver {
5344
5950
  };
5345
5951
  sessionId = null;
5346
5952
  terminalSequence = 0;
5953
+ discoverRecentContext(request) {
5954
+ return discoverPiRecentContext(request);
5955
+ }
5347
5956
  constructor(dependenciesFor = createPiSessionDependencies, loadSdk = loadPiSdkModule, readVersion = readPiSdkVersion) {
5348
5957
  this.dependenciesFor = dependenciesFor;
5349
5958
  this.loadSdk = loadSdk;
@@ -5489,6 +6098,9 @@ function assertAdapterCompatibility(registrationId, registeredCapabilities, adap
5489
6098
  if (typeof candidate[method] !== "function")
5490
6099
  throw new Error(`Adapter ${registrationId} is missing ${method}()`);
5491
6100
  }
6101
+ if (candidate.discoverRecentContext !== undefined && typeof candidate.discoverRecentContext !== "function") {
6102
+ throw new Error(`Adapter ${registrationId} has an invalid discoverRecentContext()`);
6103
+ }
5492
6104
  const instruction = candidate.instructionDelivery;
5493
6105
  if (!instruction || instruction.kind !== "native" && instruction.kind !== "workspace_file") {
5494
6106
  throw new Error(`Adapter ${registrationId} has an invalid instructionDelivery declaration`);
@@ -5710,8 +6322,8 @@ function ensureSymlinks(workDir, canonical = CANONICAL_FILE, aliases = SYMLINK_A
5710
6322
  continue;
5711
6323
  const aliasPath = join8(workDir, alias);
5712
6324
  try {
5713
- const stat = lstatSync(aliasPath);
5714
- if (stat.isSymbolicLink()) {
6325
+ const stat2 = lstatSync(aliasPath);
6326
+ if (stat2.isSymbolicLink()) {
5715
6327
  const target = readlinkSync(aliasPath);
5716
6328
  if (target === canonical)
5717
6329
  continue;
@@ -5874,6 +6486,7 @@ class LogicalAgentSession {
5874
6486
  steeringDeliveries = new Set;
5875
6487
  laneAdmissionTail = Promise.resolve();
5876
6488
  laneAdmissionPending = 0;
6489
+ toolBoundaryOpen = true;
5877
6490
  toolBoundaryFlushDisabled = false;
5878
6491
  safeBoundaryFlush;
5879
6492
  safeBoundaryDelivery;
@@ -6154,6 +6767,8 @@ class LogicalAgentSession {
6154
6767
  this.turnError = undefined;
6155
6768
  this.interruptedTurnId = undefined;
6156
6769
  this.processTurnEnded = false;
6770
+ this.toolBoundaryOpen = true;
6771
+ this.toolBoundaryFlushDisabled = false;
6157
6772
  this.state = "starting";
6158
6773
  const generation = this.lifecycleGeneration;
6159
6774
  const text = messages.map((message) => message.text).join(`
@@ -6386,6 +7001,7 @@ class LogicalAgentSession {
6386
7001
  }
6387
7002
  if (!this.startToolUse(event.callId))
6388
7003
  return;
7004
+ this.toolBoundaryOpen = false;
6389
7005
  const startedCallId = this.toolCallId(event.callId);
6390
7006
  this.emit({
6391
7007
  type: "tool_started",
@@ -6402,6 +7018,7 @@ class LogicalAgentSession {
6402
7018
  }
6403
7019
  if (!this.finishToolUse(event.callId))
6404
7020
  return;
7021
+ this.toolBoundaryOpen = true;
6405
7022
  const finishedCallId = this.toolCallId(event.callId);
6406
7023
  this.emit({
6407
7024
  type: "tool_finished",
@@ -6409,7 +7026,7 @@ class LogicalAgentSession {
6409
7026
  ...finishedCallId ? { callId: finishedCallId } : {},
6410
7027
  name: event.name
6411
7028
  });
6412
- if (this.outstandingToolUseCount() === 0 && !this.toolBoundaryFlushDisabled)
7029
+ if (!this.toolBoundaryFlushDisabled)
6413
7030
  this.flushSafeBoundaryQueue();
6414
7031
  return;
6415
7032
  case "compaction_started":
@@ -6555,6 +7172,7 @@ class LogicalAgentSession {
6555
7172
  this.clearOutstandingToolUses();
6556
7173
  this.compacting = false;
6557
7174
  this.reviewing = false;
7175
+ this.toolBoundaryOpen = true;
6558
7176
  this.toolBoundaryFlushDisabled = false;
6559
7177
  this.state = "idle";
6560
7178
  if (this.adapter.execution.lifetime === "turn") {
@@ -6576,7 +7194,7 @@ class LogicalAgentSession {
6576
7194
  return this.safeBoundaryFlush;
6577
7195
  }
6578
7196
  canFlushSafeBoundaryQueue() {
6579
- 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;
7197
+ 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;
6580
7198
  }
6581
7199
  async drainSafeBoundaryQueue() {
6582
7200
  while (this.canFlushSafeBoundaryQueue()) {
@@ -7091,6 +7709,57 @@ function createAgentDriverSdkWithRegistry(options) {
7091
7709
  const registry = options.registry;
7092
7710
  return {
7093
7711
  backendIds: registry.backendIds,
7712
+ async discoverRecentContext(input) {
7713
+ if (!isValidRecentContextTopK(input.recentSessionFilesTopK) || !isValidRecentContextTopK(input.recentProjectsTopK)) {
7714
+ return {
7715
+ ok: false,
7716
+ error: {
7717
+ category: "configuration",
7718
+ code: "invalid_recent_context_top_k",
7719
+ message: "Recent-context Top-K values must be non-negative safe integers",
7720
+ retryable: false
7721
+ }
7722
+ };
7723
+ }
7724
+ const registration = registry.get(input.backend);
7725
+ try {
7726
+ assertRegistrationShape(registration);
7727
+ const adapter = registration.createAdapter();
7728
+ assertAdapterCompatibility(String(registration.id), registration.capabilities, adapter);
7729
+ if (!adapter.discoverRecentContext) {
7730
+ return {
7731
+ ok: false,
7732
+ error: {
7733
+ category: "configuration",
7734
+ code: "recent_context_discovery_unsupported",
7735
+ message: `Backend ${input.backend} does not support recent-context discovery`,
7736
+ retryable: false
7737
+ }
7738
+ };
7739
+ }
7740
+ const command = registration.capabilities.commandOverride ? input.command : undefined;
7741
+ const discovered = await adapter.discoverRecentContext({
7742
+ recentSessionFilesTopK: input.recentSessionFilesTopK,
7743
+ recentProjectsTopK: input.recentProjectsTopK,
7744
+ ...command ? { command } : {}
7745
+ });
7746
+ const sanitized = sanitizeRecentContextData(discovered, input);
7747
+ if (!sanitized)
7748
+ throw new Error(`Adapter ${input.backend} returned invalid recent-context data`);
7749
+ return { ok: true, ...sanitized };
7750
+ } catch (error) {
7751
+ const contractInvalid = error instanceof Error && (error.message.startsWith("Adapter ") || error.message.startsWith("Agent backend registration "));
7752
+ return {
7753
+ ok: false,
7754
+ error: {
7755
+ category: contractInvalid ? "internal" : "runtime_unavailable",
7756
+ code: contractInvalid ? "adapter_contract_invalid" : "recent_context_discovery_failed",
7757
+ message: contractInvalid ? `Backend ${input.backend} adapter contract is invalid` : `Backend ${input.backend} recent-context discovery failed`,
7758
+ retryable: !contractInvalid
7759
+ }
7760
+ };
7761
+ }
7762
+ },
7094
7763
  async probe(input) {
7095
7764
  const registration = registry.get(input.backend);
7096
7765
  const capabilities2 = registration.capabilities;
@@ -7353,7 +8022,7 @@ import { createHash as createHash2 } from "crypto";
7353
8022
  // agent-driver/dist/provider-quota.js
7354
8023
  import { execFile } from "node:child_process";
7355
8024
  import { readFile } from "node:fs/promises";
7356
- import { homedir as homedir3 } from "node:os";
8025
+ import { homedir as homedir5 } from "node:os";
7357
8026
  import { join as join9 } from "node:path";
7358
8027
  import { promisify } from "node:util";
7359
8028
  import { randomBytes as randomBytes4 } from "node:crypto";
@@ -7382,7 +8051,7 @@ async function claudeCredentials(options) {
7382
8051
  } catch {}
7383
8052
  }
7384
8053
  const env = options.env ?? process.env;
7385
- const root = env.CLAUDE_CONFIG_DIR || join9(options.home ?? homedir3(), ".claude");
8054
+ const root = env.CLAUDE_CONFIG_DIR || join9(options.home ?? homedir5(), ".claude");
7386
8055
  try {
7387
8056
  const value = options.readCredentialsFile ? await options.readCredentialsFile(join9(root, ".credentials.json")) : await readFile(join9(root, ".credentials.json"), "utf8");
7388
8057
  return parseCredentials(value);
@@ -10131,6 +10800,10 @@ ${this.opts.wakePromptFooter}` : text;
10131
10800
  sent = session.send(input);
10132
10801
  if (exactOwner)
10133
10802
  this.markPendingDeliveryObserved(exactOwner, input.id);
10803
+ this.log.info("steering message submitted to logical session", {
10804
+ agentId: effect.agentId,
10805
+ mode: effect.mode
10806
+ });
10134
10807
  } catch (error) {
10135
10808
  if (exactOwner) {
10136
10809
  this.settlePendingDelivery(exactOwner, input.id);
@@ -10176,7 +10849,6 @@ ${this.opts.wakePromptFooter}` : text;
10176
10849
  mode: effect.mode
10177
10850
  });
10178
10851
  }
10179
- this.log.info("steering message sent to running agent", { agentId: effect.agentId, mode: effect.mode });
10180
10852
  break;
10181
10853
  }
10182
10854
  case "stop":
@@ -11699,10 +12371,10 @@ function mergeDefs(...defs) {
11699
12371
  function cloneDef(schema) {
11700
12372
  return mergeDefs(schema._zod.def);
11701
12373
  }
11702
- function getElementAtPath(obj, path8) {
11703
- if (!path8)
12374
+ function getElementAtPath(obj, path12) {
12375
+ if (!path12)
11704
12376
  return obj;
11705
- return path8.reduce((acc, key) => acc?.[key], obj);
12377
+ return path12.reduce((acc, key) => acc?.[key], obj);
11706
12378
  }
11707
12379
  function promiseAllObject(promisesObj) {
11708
12380
  const keys = Object.keys(promisesObj);
@@ -12110,11 +12782,11 @@ function explicitlyAborted(x, startIndex = 0) {
12110
12782
  }
12111
12783
  return false;
12112
12784
  }
12113
- function prefixIssues(path8, issues) {
12785
+ function prefixIssues(path12, issues) {
12114
12786
  return issues.map((iss) => {
12115
12787
  var _a2;
12116
12788
  (_a2 = iss).path ?? (_a2.path = []);
12117
- iss.path.unshift(path8);
12789
+ iss.path.unshift(path12);
12118
12790
  return iss;
12119
12791
  });
12120
12792
  }
@@ -12261,16 +12933,16 @@ function flattenError(error, mapper = (issue2) => issue2.message) {
12261
12933
  }
12262
12934
  function formatError(error, mapper = (issue2) => issue2.message) {
12263
12935
  const fieldErrors = { _errors: [] };
12264
- const processError = (error2, path8 = []) => {
12936
+ const processError = (error2, path12 = []) => {
12265
12937
  for (const issue2 of error2.issues) {
12266
12938
  if (issue2.code === "invalid_union" && issue2.errors.length) {
12267
- issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
12939
+ issue2.errors.map((issues) => processError({ issues }, [...path12, ...issue2.path]));
12268
12940
  } else if (issue2.code === "invalid_key") {
12269
- processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
12941
+ processError({ issues: issue2.issues }, [...path12, ...issue2.path]);
12270
12942
  } else if (issue2.code === "invalid_element") {
12271
- processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
12943
+ processError({ issues: issue2.issues }, [...path12, ...issue2.path]);
12272
12944
  } else {
12273
- const fullpath = [...path8, ...issue2.path];
12945
+ const fullpath = [...path12, ...issue2.path];
12274
12946
  if (fullpath.length === 0) {
12275
12947
  fieldErrors._errors.push(mapper(issue2));
12276
12948
  } else {
@@ -12297,17 +12969,17 @@ function formatError(error, mapper = (issue2) => issue2.message) {
12297
12969
  }
12298
12970
  function treeifyError(error, mapper = (issue2) => issue2.message) {
12299
12971
  const result = { errors: [] };
12300
- const processError = (error2, path8 = []) => {
12972
+ const processError = (error2, path12 = []) => {
12301
12973
  var _a2, _b;
12302
12974
  for (const issue2 of error2.issues) {
12303
12975
  if (issue2.code === "invalid_union" && issue2.errors.length) {
12304
- issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
12976
+ issue2.errors.map((issues) => processError({ issues }, [...path12, ...issue2.path]));
12305
12977
  } else if (issue2.code === "invalid_key") {
12306
- processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
12978
+ processError({ issues: issue2.issues }, [...path12, ...issue2.path]);
12307
12979
  } else if (issue2.code === "invalid_element") {
12308
- processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
12980
+ processError({ issues: issue2.issues }, [...path12, ...issue2.path]);
12309
12981
  } else {
12310
- const fullpath = [...path8, ...issue2.path];
12982
+ const fullpath = [...path12, ...issue2.path];
12311
12983
  if (fullpath.length === 0) {
12312
12984
  result.errors.push(mapper(issue2));
12313
12985
  continue;
@@ -12339,8 +13011,8 @@ function treeifyError(error, mapper = (issue2) => issue2.message) {
12339
13011
  }
12340
13012
  function toDotPath(_path) {
12341
13013
  const segs = [];
12342
- const path8 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
12343
- for (const seg of path8) {
13014
+ const path12 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
13015
+ for (const seg of path12) {
12344
13016
  if (typeof seg === "number")
12345
13017
  segs.push(`[${seg}]`);
12346
13018
  else if (typeof seg === "symbol")
@@ -24799,13 +25471,13 @@ function resolveRef(ref, ctx) {
24799
25471
  if (!ref.startsWith("#")) {
24800
25472
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
24801
25473
  }
24802
- const path8 = ref.slice(1).split("/").filter(Boolean);
24803
- if (path8.length === 0) {
25474
+ const path12 = ref.slice(1).split("/").filter(Boolean);
25475
+ if (path12.length === 0) {
24804
25476
  return ctx.rootSchema;
24805
25477
  }
24806
25478
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
24807
- if (path8[0] === defsKey) {
24808
- const key = path8[1];
25479
+ if (path12[0] === defsKey) {
25480
+ const key = path12[1];
24809
25481
  if (!key || !ctx.defs[key]) {
24810
25482
  throw new Error(`Reference not found: ${ref}`);
24811
25483
  }
@@ -26813,6 +27485,7 @@ var TERMINAL_MEETING_STATUSES = [
26813
27485
  MeetingStatus.COMPLETED,
26814
27486
  MeetingStatus.FAILED
26815
27487
  ];
27488
+ var COMMUNITY_BOT_LIMIT_PER_OWNER = 20;
26816
27489
  var COMMUNITY_BOT_NAME_MIN = 1;
26817
27490
  var COMMUNITY_BOT_NAME_MAX = 32;
26818
27491
  var COMMUNITY_BOT_DESCRIPTION_MAX = 1024;
@@ -27687,6 +28360,13 @@ var HostCommandSchema = exports_external.discriminatedUnion("type", [
27687
28360
  launchId: exports_external.string().min(1),
27688
28361
  unreadNotice: exports_external.unknown()
27689
28362
  }),
28363
+ exports_external.object({
28364
+ type: exports_external.literal("agent:event"),
28365
+ agentId: exports_external.string().min(1),
28366
+ config: exports_external.unknown(),
28367
+ launchId: exports_external.string().min(1),
28368
+ prompt: exports_external.string().min(1).max(32768)
28369
+ }),
27690
28370
  exports_external.object({
27691
28371
  type: exports_external.literal("agent:stop"),
27692
28372
  agentId: exports_external.string().min(1)
@@ -28038,6 +28718,26 @@ class AgentRouter {
28038
28718
  return;
28039
28719
  }
28040
28720
  break;
28721
+ case "agent:event":
28722
+ this.log.info("agent:event received", { agentId: cmd.agentId });
28723
+ try {
28724
+ await this.opts.onBeforeAgent?.(cmd.agentId);
28725
+ this.opts.manager.register(cmd.agentId, {
28726
+ runtimeConfig: cmd.config,
28727
+ launchId: cmd.launchId
28728
+ });
28729
+ this.running.add(cmd.agentId);
28730
+ this.opts.manager.deliver(cmd.agentId, {
28731
+ id: `${cmd.agentId}:event:${cmd.launchId}`,
28732
+ text: cmd.prompt
28733
+ });
28734
+ } catch (err) {
28735
+ this.log.warn("agent:event failed", {
28736
+ agentId: cmd.agentId,
28737
+ err: err instanceof Error ? err.message : String(err)
28738
+ });
28739
+ }
28740
+ break;
28041
28741
  case "agent:reset":
28042
28742
  await this.runRestartCommand(cmd.agentId, cmd.launchId, "agent:reset", () => this.opts.manager.resetSession(cmd.agentId, {
28043
28743
  runtimeConfig: cmd.config,
@@ -28155,7 +28855,7 @@ import * as fs5 from "fs";
28155
28855
  import * as http from "http";
28156
28856
  import * as https from "https";
28157
28857
  import * as os2 from "os";
28158
- import * as path8 from "path";
28858
+ import * as path12 from "path";
28159
28859
  import { URL as URL2 } from "url";
28160
28860
  var LOCAL_MESSAGE_REMINDER_PATH = "/__alook/local/message-reminder";
28161
28861
  var LOCAL_MESSAGE_REMINDER_BODY_MAX_BYTES = 4 * 1024;
@@ -28187,15 +28887,15 @@ class CredentialBroker {
28187
28887
  this.voucherPrefix = config2.voucherPrefix ?? "vch_";
28188
28888
  this.clientLabel = config2.clientLabel ?? "cli";
28189
28889
  this.headerNames = config2.headerNames ?? DEFAULT_HEADER_NAMES;
28190
- this.voucherDir = config2.voucherDir ?? path8.join(os2.tmpdir(), "agent-vouchers");
28890
+ this.voucherDir = config2.voucherDir ?? path12.join(os2.tmpdir(), "agent-vouchers");
28191
28891
  }
28192
28892
  mint(agentId, launchId, capabilities2, runnerKey) {
28193
28893
  if (!runnerKey)
28194
28894
  throw new Error("CredentialBroker.mint: runnerKey is required (per-agent tier-2 credential)");
28195
28895
  const voucher = randomVoucher(this.voucherPrefix);
28196
- const dir = path8.join(this.voucherDir, sanitizeIdSegment(agentId));
28896
+ const dir = path12.join(this.voucherDir, sanitizeIdSegment(agentId));
28197
28897
  fs5.mkdirSync(dir, { recursive: true });
28198
- const voucherFile = path8.join(dir, `${sanitizeIdSegment(launchId)}.token`);
28898
+ const voucherFile = path12.join(dir, `${sanitizeIdSegment(launchId)}.token`);
28199
28899
  fs5.writeFileSync(voucherFile, voucher, { mode: 384 });
28200
28900
  this.registrations.set(voucher, {
28201
28901
  agentId,
@@ -28590,7 +29290,7 @@ function joinPath(basePath, reqUrl) {
28590
29290
  return base + reqPath || "/";
28591
29291
  }
28592
29292
  // src/daemon/createDaemon.ts
28593
- import { homedir as homedir5 } from "os";
29293
+ import { homedir as homedir7 } from "os";
28594
29294
  import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync7 } from "node:fs";
28595
29295
 
28596
29296
  // src/util/rotatingFileSink.ts
@@ -28607,7 +29307,7 @@ import {
28607
29307
  statSync,
28608
29308
  unlinkSync as unlinkSync3
28609
29309
  } from "node:fs";
28610
- function createRotatingFileSink(path9, maxBytes, opts = {}) {
29310
+ function createRotatingFileSink(path13, maxBytes, opts = {}) {
28611
29311
  const report = (operation, error51) => {
28612
29312
  try {
28613
29313
  opts.onError?.({ operation, error: error51 });
@@ -28617,8 +29317,8 @@ function createRotatingFileSink(path9, maxBytes, opts = {}) {
28617
29317
  if (!existsSync5(filePath))
28618
29318
  return true;
28619
29319
  try {
28620
- const stat = lstatSync2(filePath);
28621
- if (!stat.isFile()) {
29320
+ const stat2 = lstatSync2(filePath);
29321
+ if (!stat2.isFile()) {
28622
29322
  if (opts.mode === undefined && !opts.hardMaxBytes)
28623
29323
  return true;
28624
29324
  report("unsafe_generation", new Error("log generation is not a regular file"));
@@ -28626,7 +29326,7 @@ function createRotatingFileSink(path9, maxBytes, opts = {}) {
28626
29326
  }
28627
29327
  if (opts.mode !== undefined)
28628
29328
  chmodSync(filePath, opts.mode);
28629
- if (opts.hardMaxBytes && maxBytes > 0 && stat.size > maxBytes) {
29329
+ if (opts.hardMaxBytes && maxBytes > 0 && stat2.size > maxBytes) {
28630
29330
  try {
28631
29331
  unlinkSync3(filePath);
28632
29332
  } catch (error51) {
@@ -28643,9 +29343,9 @@ function createRotatingFileSink(path9, maxBytes, opts = {}) {
28643
29343
  };
28644
29344
  const rotate = () => {
28645
29345
  try {
28646
- renameSync(path9, `${path9}.1`);
29346
+ renameSync(path13, `${path13}.1`);
28647
29347
  if (opts.mode !== undefined)
28648
- chmodSync(`${path9}.1`, opts.mode);
29348
+ chmodSync(`${path13}.1`, opts.mode);
28649
29349
  return true;
28650
29350
  } catch (error51) {
28651
29351
  report("rotate", error51);
@@ -28654,7 +29354,7 @@ function createRotatingFileSink(path9, maxBytes, opts = {}) {
28654
29354
  };
28655
29355
  const currentSize = () => {
28656
29356
  try {
28657
- return existsSync5(path9) ? statSync(path9).size : 0;
29357
+ return existsSync5(path13) ? statSync(path13).size : 0;
28658
29358
  } catch (error51) {
28659
29359
  report("stat", error51);
28660
29360
  return null;
@@ -28662,7 +29362,7 @@ function createRotatingFileSink(path9, maxBytes, opts = {}) {
28662
29362
  };
28663
29363
  const sink = {
28664
29364
  secure() {
28665
- return secureGeneration(`${path9}.1`) && secureGeneration(path9);
29365
+ return secureGeneration(`${path13}.1`) && secureGeneration(path13);
28666
29366
  },
28667
29367
  write(line) {
28668
29368
  try {
@@ -28682,7 +29382,7 @@ function createRotatingFileSink(path9, maxBytes, opts = {}) {
28682
29382
  const shouldRotate = maxBytes > 0 && (opts.hardMaxBytes ? currentBytes > 0 && currentBytes + serializedBytes > maxBytes : currentBytes >= maxBytes);
28683
29383
  if (shouldRotate && !rotate() && opts.hardMaxBytes)
28684
29384
  return;
28685
- appendFileSync(path9, serialized, opts.mode === undefined ? undefined : { mode: opts.mode });
29385
+ appendFileSync(path13, serialized, opts.mode === undefined ? undefined : { mode: opts.mode });
28686
29386
  } catch (error51) {
28687
29387
  report("append", error51);
28688
29388
  }
@@ -28690,7 +29390,7 @@ function createRotatingFileSink(path9, maxBytes, opts = {}) {
28690
29390
  openSnapshot() {
28691
29391
  const files = [];
28692
29392
  try {
28693
- for (const candidate of [`${path9}.1`, path9]) {
29393
+ for (const candidate of [`${path13}.1`, path13]) {
28694
29394
  if (!existsSync5(candidate))
28695
29395
  continue;
28696
29396
  if (!secureGeneration(candidate))
@@ -28698,10 +29398,10 @@ function createRotatingFileSink(path9, maxBytes, opts = {}) {
28698
29398
  const noFollow = "O_NOFOLLOW" in constants ? constants.O_NOFOLLOW : 0;
28699
29399
  const fd = openSync(candidate, constants.O_RDONLY | noFollow);
28700
29400
  try {
28701
- const stat = fstatSync(fd);
28702
- if (!stat.isFile())
29401
+ const stat2 = fstatSync(fd);
29402
+ if (!stat2.isFile())
28703
29403
  throw new Error("snapshot source is not a regular file");
28704
- files.push({ path: candidate, fd, size: stat.size });
29404
+ files.push({ path: candidate, fd, size: stat2.size });
28705
29405
  } catch (error51) {
28706
29406
  closeSync(fd);
28707
29407
  throw error51;
@@ -28851,11 +29551,11 @@ function createTraceSampler(emit, throttleMs = DEFAULT_TRACE_SAMPLE_MS) {
28851
29551
 
28852
29552
  // src/util/statusFile.ts
28853
29553
  import { writeFileSync as writeFileSync4, renameSync as renameSync2 } from "node:fs";
28854
- function writeStatusFile(path9, snapshot) {
29554
+ function writeStatusFile(path13, snapshot) {
28855
29555
  try {
28856
- const tmp = `${path9}.tmp`;
29556
+ const tmp = `${path13}.tmp`;
28857
29557
  writeFileSync4(tmp, JSON.stringify(snapshot));
28858
- renameSync2(tmp, path9);
29558
+ renameSync2(tmp, path13);
28859
29559
  } catch {}
28860
29560
  }
28861
29561
  // ../shared/src/constants/community.ts
@@ -29699,6 +30399,10 @@ var CommunityBotPatchRequestSchema = exports_external.object({
29699
30399
  var CommunityBotAddToServerRequestSchema = exports_external.object({
29700
30400
  botId: exports_external.string().min(1)
29701
30401
  });
30402
+ var CommunityServerOnboardRequestSchema = exports_external.strictObject({
30403
+ 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"),
30404
+ wakePrompt: exports_external.string().max(32768).refine((value) => value.trim().length > 0, "wakePrompt is required")
30405
+ });
29702
30406
  var CommunityAgentMessageContentSchema = exports_external.object({ text: exports_external.string().max(MAX_MESSAGE_CONTENT_LENGTH).default("") }).catchall(exports_external.unknown());
29703
30407
  var CommunityAgentSeqSchema = exports_external.number().int().min(0);
29704
30408
  var CommunityAgentPositiveSeqSchema = exports_external.number().int().min(1);
@@ -31823,11 +32527,11 @@ function timelineRowHash(line) {
31823
32527
  }
31824
32528
  function timelineFileGeneration(filePath, lines) {
31825
32529
  try {
31826
- const stat = fs7.lstatSync(filePath, { bigint: true });
31827
- if (!stat.isFile())
32530
+ const stat2 = fs7.lstatSync(filePath, { bigint: true });
32531
+ if (!stat2.isFile())
31828
32532
  return null;
31829
32533
  const digest = createHash4("sha256");
31830
- digest.update(`${stat.dev}:${stat.ino}:${stat.size}:${stat.mtimeNs}:${stat.ctimeNs}
32534
+ digest.update(`${stat2.dev}:${stat2.ino}:${stat2.size}:${stat2.mtimeNs}:${stat2.ctimeNs}
31831
32535
  `);
31832
32536
  for (const line of lines)
31833
32537
  digest.update(line.text, "utf8").update(`
@@ -31885,9 +32589,9 @@ function compactLines(input) {
31885
32589
  }
31886
32590
  return suffix;
31887
32591
  }
31888
- function isRealDirectory(path9) {
32592
+ function isRealDirectory(path13) {
31889
32593
  try {
31890
- return fs7.lstatSync(path9).isDirectory();
32594
+ return fs7.lstatSync(path13).isDirectory();
31891
32595
  } catch {
31892
32596
  return false;
31893
32597
  }
@@ -31927,8 +32631,8 @@ function scanTimelineFile(filePath) {
31927
32631
  let fd = null;
31928
32632
  try {
31929
32633
  fd = fs7.openSync(filePath, fs7.constants.O_RDONLY | (fs7.constants.O_NOFOLLOW ?? 0));
31930
- const stat = fs7.fstatSync(fd);
31931
- if (!stat.isFile())
32634
+ const stat2 = fs7.fstatSync(fd);
32635
+ if (!stat2.isFile())
31932
32636
  return null;
31933
32637
  const chunk2 = Buffer.allocUnsafe(TIMELINE_READ_CHUNK_BYTES);
31934
32638
  const newest = [];
@@ -31941,9 +32645,9 @@ function scanTimelineFile(filePath) {
31941
32645
  let oversized = false;
31942
32646
  let stop = false;
31943
32647
  let discardIncompleteTail = false;
31944
- if (stat.size > 0) {
32648
+ if (stat2.size > 0) {
31945
32649
  const last = Buffer.allocUnsafe(1);
31946
- fs7.readSync(fd, last, 0, 1, stat.size - 1);
32650
+ fs7.readSync(fd, last, 0, 1, stat2.size - 1);
31947
32651
  discardIncompleteTail = last[0] !== 10;
31948
32652
  }
31949
32653
  const resetPhysicalLine = () => {
@@ -32002,7 +32706,7 @@ function scanTimelineFile(filePath) {
32002
32706
  }
32003
32707
  resetPhysicalLine();
32004
32708
  };
32005
- let position = stat.size;
32709
+ let position = stat2.size;
32006
32710
  while (position > 0 && !stop) {
32007
32711
  const start = Math.max(0, position - chunk2.length);
32008
32712
  const requested = position - start;
@@ -32154,11 +32858,11 @@ function readResumeControlState(timelineDir) {
32154
32858
  let fd = null;
32155
32859
  try {
32156
32860
  fd = fs7.openSync(filePath, fs7.constants.O_RDONLY | (fs7.constants.O_NOFOLLOW ?? 0));
32157
- const stat = fs7.fstatSync(fd);
32158
- if (!stat.isFile() || stat.size <= 0 || stat.size > RESUME_CONTROL_MAX_BYTES) {
32861
+ const stat2 = fs7.fstatSync(fd);
32862
+ if (!stat2.isFile() || stat2.size <= 0 || stat2.size > RESUME_CONTROL_MAX_BYTES) {
32159
32863
  return { kind: "invalid" };
32160
32864
  }
32161
- const bounded = Buffer.allocUnsafe(stat.size + 1);
32865
+ const bounded = Buffer.allocUnsafe(stat2.size + 1);
32162
32866
  let bytesRead = 0;
32163
32867
  while (bytesRead < bounded.length) {
32164
32868
  const count = fs7.readSync(fd, bounded, bytesRead, bounded.length - bytesRead, bytesRead);
@@ -32166,7 +32870,7 @@ function readResumeControlState(timelineDir) {
32166
32870
  break;
32167
32871
  bytesRead += count;
32168
32872
  }
32169
- if (bytesRead !== stat.size)
32873
+ if (bytesRead !== stat2.size)
32170
32874
  return { kind: "invalid" };
32171
32875
  const raw = bounded.subarray(0, bytesRead).toString("utf8");
32172
32876
  const value = JSON.parse(raw);
@@ -32953,26 +33657,26 @@ function createTimelineRecorder(opts) {
32953
33657
  }
32954
33658
  }
32955
33659
  // src/discovery.ts
32956
- import * as path9 from "path";
33660
+ import * as path13 from "path";
32957
33661
  import * as fs8 from "fs";
32958
33662
  import { fileURLToPath } from "url";
32959
33663
  function resolveAlookCliPath(moduleDir) {
32960
- const thisDir = moduleDir ?? path9.dirname(fileURLToPath(import.meta.url));
32961
- const target2 = path9.basename(thisDir) === "dist" ? path9.resolve(thisDir, "cli", "index.js") : path9.resolve(thisDir, "..", "scripts", "alook-shim.mjs");
33664
+ const thisDir = moduleDir ?? path13.dirname(fileURLToPath(import.meta.url));
33665
+ const target2 = path13.basename(thisDir) === "dist" ? path13.resolve(thisDir, "cli", "index.js") : path13.resolve(thisDir, "..", "scripts", "alook-shim.mjs");
32962
33666
  return fs8.existsSync(target2) ? target2 : null;
32963
33667
  }
32964
33668
  function deriveCliFallbackCandidates(cliPath) {
32965
33669
  if (!cliPath)
32966
33670
  return [];
32967
- const normalized = cliPath.split(path9.sep).join("/");
33671
+ const normalized = cliPath.split(path13.sep).join("/");
32968
33672
  const marker = "/node_modules/";
32969
33673
  const idx = normalized.indexOf(marker);
32970
33674
  if (idx === -1)
32971
33675
  return [];
32972
33676
  const globalRoot = cliPath.slice(0, idx + marker.length - 1);
32973
- const tail = path9.join("dist", "cli", "index.js");
33677
+ const tail = path13.join("dist", "cli", "index.js");
32974
33678
  return [
32975
- path9.join(globalRoot, "@alook", "daemon", tail)
33679
+ path13.join(globalRoot, "@alook", "daemon", tail)
32976
33680
  ].filter((candidate) => candidate !== cliPath);
32977
33681
  }
32978
33682
  function resolveAlookCliPathWithFallback(primary) {
@@ -33167,7 +33871,7 @@ class MessageReminderScheduler {
33167
33871
 
33168
33872
  // src/manager/agentDriverHost.ts
33169
33873
  import { randomUUID as randomUUID7 } from "node:crypto";
33170
- import { homedir as homedir4 } from "node:os";
33874
+ import { homedir as homedir6 } from "node:os";
33171
33875
  import { join as join13 } from "node:path";
33172
33876
 
33173
33877
  // src/drivers/gitIdentityEnv.ts
@@ -33293,7 +33997,7 @@ function createDaemonAgentDriverHost(ctx, onRawLine) {
33293
33997
  hostUser: readHostGitIdentity() ?? undefined
33294
33998
  }),
33295
33999
  platformProtected: {
33296
- ALOOK_HOME: process.env.ALOOK_HOME ?? join13(homedir4(), ".alook"),
34000
+ ALOOK_HOME: process.env.ALOOK_HOME ?? join13(homedir6(), ".alook"),
33297
34001
  ALOOK_ID: ctx.agentId,
33298
34002
  ALOOK_CLI: ctx.agentCliPath,
33299
34003
  ALOOK_SERVER_URL: ctx.config.serverUrl,
@@ -33614,13 +34318,13 @@ function createRuntimeRawLineTap(args) {
33614
34318
  const maxBytes = args.maxBytes ?? RUNTIME_RAW_TRACE_MAX_BYTES;
33615
34319
  const sinks = new Map;
33616
34320
  const warned = new Set;
33617
- const warnOnce = (agentId, path10, operation, error51) => {
34321
+ const warnOnce = (agentId, path14, operation, error51) => {
33618
34322
  if (warned.has(agentId))
33619
34323
  return;
33620
34324
  warned.add(agentId);
33621
34325
  args.logger.warn("runtime raw trace sink failed", {
33622
34326
  agentId,
33623
- path: path10,
34327
+ path: path14,
33624
34328
  operation,
33625
34329
  error: error51 instanceof Error ? error51.message : String(error51)
33626
34330
  });
@@ -33629,10 +34333,10 @@ function createRuntimeRawLineTap(args) {
33629
34333
  if (!args.enabledAgentIds.has(agentId))
33630
34334
  return;
33631
34335
  const encodedAgentId = encodeURIComponent(agentId).replace(/\./g, "%2E");
33632
- const path10 = `${traceDir}/runtime-raw-events-${encodedAgentId}.jsonl`;
34336
+ const path14 = `${traceDir}/runtime-raw-events-${encodedAgentId}.jsonl`;
33633
34337
  const serializedBytes = Buffer.byteLength(line, "utf8") + 1;
33634
34338
  if (serializedBytes > maxBytes) {
33635
- warnOnce(agentId, path10, "oversize", new Error(`raw line is ${serializedBytes} bytes; max is ${maxBytes}`));
34339
+ warnOnce(agentId, path14, "oversize", new Error(`raw line is ${serializedBytes} bytes; max is ${maxBytes}`));
33636
34340
  return;
33637
34341
  }
33638
34342
  let sink = sinks.get(agentId);
@@ -33640,12 +34344,12 @@ function createRuntimeRawLineTap(args) {
33640
34344
  try {
33641
34345
  mkdirSync7(traceDir, { recursive: true });
33642
34346
  } catch (error51) {
33643
- warnOnce(agentId, path10, "mkdir", error51);
34347
+ warnOnce(agentId, path14, "mkdir", error51);
33644
34348
  }
33645
- sink = createRotatingFileSink(path10, maxBytes, {
34349
+ sink = createRotatingFileSink(path14, maxBytes, {
33646
34350
  mode: 384,
33647
34351
  hardMaxBytes: true,
33648
- onError: ({ operation, error: error51 }) => warnOnce(agentId, path10, operation, error51)
34352
+ onError: ({ operation, error: error51 }) => warnOnce(agentId, path14, operation, error51)
33649
34353
  });
33650
34354
  sinks.set(agentId, sink);
33651
34355
  }
@@ -33737,7 +34441,7 @@ function createBuiltinDaemonSessionFactory(onRuntimeRawLine) {
33737
34441
  }
33738
34442
  async function createDaemon(opts) {
33739
34443
  const log2 = opts.logger ?? createLogger({ header: "@alook/daemon" });
33740
- const fallbackBase = (process.env.ALOOK_PROJECT_ROOT || `${homedir5()}/.alook`) + "/daemon";
34444
+ const fallbackBase = (process.env.ALOOK_PROJECT_ROOT || `${homedir7()}/.alook`) + "/daemon";
33741
34445
  const workingDirectoryBase = opts.workingDirectoryBase ?? fallbackBase;
33742
34446
  const workdirFor = (agentId) => `${workingDirectoryBase}/${agentId}`;
33743
34447
  const dailyTokenUsage2 = new DailyTokenUsageStore(workingDirectoryBase);
@@ -34328,6 +35032,7 @@ export {
34328
35032
  buildApmFreshnessDecisionProducerFactId,
34329
35033
  UnknownRuntimeError,
34330
35034
  UnknownBotError,
35035
+ SESSION_FILE_DISCOVERY_CAPABILITIES2 as SESSION_FILE_DISCOVERY_CAPABILITIES,
34331
35036
  RuntimeProgressState,
34332
35037
  RuntimeNotificationState,
34333
35038
  RUNTIME_RAW_TRACE_AGENT_IDS_ENV,