@alook/daemon 0.1.30 → 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.
- package/dist/cli/index.js +989 -195
- package/dist/index.js +840 -118
- 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
|
|
2018
|
-
if (!
|
|
2267
|
+
const path7 = candidate.trim();
|
|
2268
|
+
if (!path7 || seen.has(path7))
|
|
2019
2269
|
continue;
|
|
2020
|
-
seen.add(
|
|
2021
|
-
paths.push(
|
|
2270
|
+
seen.add(path7);
|
|
2271
|
+
paths.push(path7);
|
|
2022
2272
|
}
|
|
2023
2273
|
if (paths.length === 0 && typeof item?.path === "string") {
|
|
2024
|
-
const
|
|
2025
|
-
if (
|
|
2026
|
-
paths.push(
|
|
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
|
|
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
|
|
2404
|
-
return
|
|
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((
|
|
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
|
|
4265
|
-
const response = await this.openStream(
|
|
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(
|
|
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}${
|
|
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(
|
|
4772
|
-
const response = await this.fetchWithTimeout(
|
|
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(
|
|
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}${
|
|
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(
|
|
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}${
|
|
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
|
|
4972
|
-
import * as
|
|
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
|
|
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(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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(
|
|
5813
|
+
if (isPiSdkPackageJson(path11.join(dir, "package.json")))
|
|
5208
5814
|
return dir;
|
|
5209
|
-
const siblingDir =
|
|
5210
|
-
if (isPiSdkPackageJson(
|
|
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 =
|
|
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 ?
|
|
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() :
|
|
5235
|
-
const encoded = `--${
|
|
5236
|
-
return
|
|
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(
|
|
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
|
|
5714
|
-
if (
|
|
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 (
|
|
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.
|
|
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
|
|
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 ??
|
|
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);
|
|
@@ -9777,7 +10446,19 @@ class AgentProcessManager {
|
|
|
9777
10446
|
const session = this.sessions.get(agentId);
|
|
9778
10447
|
if (!session)
|
|
9779
10448
|
return;
|
|
9780
|
-
await session.interrupt({ requestId: randomUUID6(), reason: "owner_request" });
|
|
10449
|
+
const result = await session.interrupt({ requestId: randomUUID6(), reason: "owner_request" });
|
|
10450
|
+
if (result.status !== "accepted")
|
|
10451
|
+
return;
|
|
10452
|
+
this.log.info("agent turn interrupt accepted", {
|
|
10453
|
+
agentId,
|
|
10454
|
+
sessionInstanceId: session.sessionInstanceId,
|
|
10455
|
+
turnId: result.turnId
|
|
10456
|
+
});
|
|
10457
|
+
try {
|
|
10458
|
+
this.opts.onBotAuditEvent?.(agentId, { kind: "turn_interrupt", payload: { status: "accepted" } }, this.auditContext(agentId));
|
|
10459
|
+
} catch (err) {
|
|
10460
|
+
this.log.debug("audit emit failed (turn interrupt)", { agentId, err: String(err) });
|
|
10461
|
+
}
|
|
9781
10462
|
}
|
|
9782
10463
|
async stopAll() {
|
|
9783
10464
|
if (this.tickTimer) {
|
|
@@ -10119,6 +10800,10 @@ ${this.opts.wakePromptFooter}` : text;
|
|
|
10119
10800
|
sent = session.send(input);
|
|
10120
10801
|
if (exactOwner)
|
|
10121
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
|
+
});
|
|
10122
10807
|
} catch (error) {
|
|
10123
10808
|
if (exactOwner) {
|
|
10124
10809
|
this.settlePendingDelivery(exactOwner, input.id);
|
|
@@ -10164,7 +10849,6 @@ ${this.opts.wakePromptFooter}` : text;
|
|
|
10164
10849
|
mode: effect.mode
|
|
10165
10850
|
});
|
|
10166
10851
|
}
|
|
10167
|
-
this.log.info("steering message sent to running agent", { agentId: effect.agentId, mode: effect.mode });
|
|
10168
10852
|
break;
|
|
10169
10853
|
}
|
|
10170
10854
|
case "stop":
|
|
@@ -11687,10 +12371,10 @@ function mergeDefs(...defs) {
|
|
|
11687
12371
|
function cloneDef(schema) {
|
|
11688
12372
|
return mergeDefs(schema._zod.def);
|
|
11689
12373
|
}
|
|
11690
|
-
function getElementAtPath(obj,
|
|
11691
|
-
if (!
|
|
12374
|
+
function getElementAtPath(obj, path12) {
|
|
12375
|
+
if (!path12)
|
|
11692
12376
|
return obj;
|
|
11693
|
-
return
|
|
12377
|
+
return path12.reduce((acc, key) => acc?.[key], obj);
|
|
11694
12378
|
}
|
|
11695
12379
|
function promiseAllObject(promisesObj) {
|
|
11696
12380
|
const keys = Object.keys(promisesObj);
|
|
@@ -12098,11 +12782,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
12098
12782
|
}
|
|
12099
12783
|
return false;
|
|
12100
12784
|
}
|
|
12101
|
-
function prefixIssues(
|
|
12785
|
+
function prefixIssues(path12, issues) {
|
|
12102
12786
|
return issues.map((iss) => {
|
|
12103
12787
|
var _a2;
|
|
12104
12788
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
12105
|
-
iss.path.unshift(
|
|
12789
|
+
iss.path.unshift(path12);
|
|
12106
12790
|
return iss;
|
|
12107
12791
|
});
|
|
12108
12792
|
}
|
|
@@ -12249,16 +12933,16 @@ function flattenError(error, mapper = (issue2) => issue2.message) {
|
|
|
12249
12933
|
}
|
|
12250
12934
|
function formatError(error, mapper = (issue2) => issue2.message) {
|
|
12251
12935
|
const fieldErrors = { _errors: [] };
|
|
12252
|
-
const processError = (error2,
|
|
12936
|
+
const processError = (error2, path12 = []) => {
|
|
12253
12937
|
for (const issue2 of error2.issues) {
|
|
12254
12938
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
12255
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
12939
|
+
issue2.errors.map((issues) => processError({ issues }, [...path12, ...issue2.path]));
|
|
12256
12940
|
} else if (issue2.code === "invalid_key") {
|
|
12257
|
-
processError({ issues: issue2.issues }, [...
|
|
12941
|
+
processError({ issues: issue2.issues }, [...path12, ...issue2.path]);
|
|
12258
12942
|
} else if (issue2.code === "invalid_element") {
|
|
12259
|
-
processError({ issues: issue2.issues }, [...
|
|
12943
|
+
processError({ issues: issue2.issues }, [...path12, ...issue2.path]);
|
|
12260
12944
|
} else {
|
|
12261
|
-
const fullpath = [...
|
|
12945
|
+
const fullpath = [...path12, ...issue2.path];
|
|
12262
12946
|
if (fullpath.length === 0) {
|
|
12263
12947
|
fieldErrors._errors.push(mapper(issue2));
|
|
12264
12948
|
} else {
|
|
@@ -12285,17 +12969,17 @@ function formatError(error, mapper = (issue2) => issue2.message) {
|
|
|
12285
12969
|
}
|
|
12286
12970
|
function treeifyError(error, mapper = (issue2) => issue2.message) {
|
|
12287
12971
|
const result = { errors: [] };
|
|
12288
|
-
const processError = (error2,
|
|
12972
|
+
const processError = (error2, path12 = []) => {
|
|
12289
12973
|
var _a2, _b;
|
|
12290
12974
|
for (const issue2 of error2.issues) {
|
|
12291
12975
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
12292
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
12976
|
+
issue2.errors.map((issues) => processError({ issues }, [...path12, ...issue2.path]));
|
|
12293
12977
|
} else if (issue2.code === "invalid_key") {
|
|
12294
|
-
processError({ issues: issue2.issues }, [...
|
|
12978
|
+
processError({ issues: issue2.issues }, [...path12, ...issue2.path]);
|
|
12295
12979
|
} else if (issue2.code === "invalid_element") {
|
|
12296
|
-
processError({ issues: issue2.issues }, [...
|
|
12980
|
+
processError({ issues: issue2.issues }, [...path12, ...issue2.path]);
|
|
12297
12981
|
} else {
|
|
12298
|
-
const fullpath = [...
|
|
12982
|
+
const fullpath = [...path12, ...issue2.path];
|
|
12299
12983
|
if (fullpath.length === 0) {
|
|
12300
12984
|
result.errors.push(mapper(issue2));
|
|
12301
12985
|
continue;
|
|
@@ -12327,8 +13011,8 @@ function treeifyError(error, mapper = (issue2) => issue2.message) {
|
|
|
12327
13011
|
}
|
|
12328
13012
|
function toDotPath(_path) {
|
|
12329
13013
|
const segs = [];
|
|
12330
|
-
const
|
|
12331
|
-
for (const seg of
|
|
13014
|
+
const path12 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
13015
|
+
for (const seg of path12) {
|
|
12332
13016
|
if (typeof seg === "number")
|
|
12333
13017
|
segs.push(`[${seg}]`);
|
|
12334
13018
|
else if (typeof seg === "symbol")
|
|
@@ -24787,13 +25471,13 @@ function resolveRef(ref, ctx) {
|
|
|
24787
25471
|
if (!ref.startsWith("#")) {
|
|
24788
25472
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
24789
25473
|
}
|
|
24790
|
-
const
|
|
24791
|
-
if (
|
|
25474
|
+
const path12 = ref.slice(1).split("/").filter(Boolean);
|
|
25475
|
+
if (path12.length === 0) {
|
|
24792
25476
|
return ctx.rootSchema;
|
|
24793
25477
|
}
|
|
24794
25478
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
24795
|
-
if (
|
|
24796
|
-
const key =
|
|
25479
|
+
if (path12[0] === defsKey) {
|
|
25480
|
+
const key = path12[1];
|
|
24797
25481
|
if (!key || !ctx.defs[key]) {
|
|
24798
25482
|
throw new Error(`Reference not found: ${ref}`);
|
|
24799
25483
|
}
|
|
@@ -26801,6 +27485,7 @@ var TERMINAL_MEETING_STATUSES = [
|
|
|
26801
27485
|
MeetingStatus.COMPLETED,
|
|
26802
27486
|
MeetingStatus.FAILED
|
|
26803
27487
|
];
|
|
27488
|
+
var COMMUNITY_BOT_LIMIT_PER_OWNER = 20;
|
|
26804
27489
|
var COMMUNITY_BOT_NAME_MIN = 1;
|
|
26805
27490
|
var COMMUNITY_BOT_NAME_MAX = 32;
|
|
26806
27491
|
var COMMUNITY_BOT_DESCRIPTION_MAX = 1024;
|
|
@@ -27675,6 +28360,13 @@ var HostCommandSchema = exports_external.discriminatedUnion("type", [
|
|
|
27675
28360
|
launchId: exports_external.string().min(1),
|
|
27676
28361
|
unreadNotice: exports_external.unknown()
|
|
27677
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
|
+
}),
|
|
27678
28370
|
exports_external.object({
|
|
27679
28371
|
type: exports_external.literal("agent:stop"),
|
|
27680
28372
|
agentId: exports_external.string().min(1)
|
|
@@ -28026,6 +28718,26 @@ class AgentRouter {
|
|
|
28026
28718
|
return;
|
|
28027
28719
|
}
|
|
28028
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;
|
|
28029
28741
|
case "agent:reset":
|
|
28030
28742
|
await this.runRestartCommand(cmd.agentId, cmd.launchId, "agent:reset", () => this.opts.manager.resetSession(cmd.agentId, {
|
|
28031
28743
|
runtimeConfig: cmd.config,
|
|
@@ -28143,7 +28855,7 @@ import * as fs5 from "fs";
|
|
|
28143
28855
|
import * as http from "http";
|
|
28144
28856
|
import * as https from "https";
|
|
28145
28857
|
import * as os2 from "os";
|
|
28146
|
-
import * as
|
|
28858
|
+
import * as path12 from "path";
|
|
28147
28859
|
import { URL as URL2 } from "url";
|
|
28148
28860
|
var LOCAL_MESSAGE_REMINDER_PATH = "/__alook/local/message-reminder";
|
|
28149
28861
|
var LOCAL_MESSAGE_REMINDER_BODY_MAX_BYTES = 4 * 1024;
|
|
@@ -28175,15 +28887,15 @@ class CredentialBroker {
|
|
|
28175
28887
|
this.voucherPrefix = config2.voucherPrefix ?? "vch_";
|
|
28176
28888
|
this.clientLabel = config2.clientLabel ?? "cli";
|
|
28177
28889
|
this.headerNames = config2.headerNames ?? DEFAULT_HEADER_NAMES;
|
|
28178
|
-
this.voucherDir = config2.voucherDir ??
|
|
28890
|
+
this.voucherDir = config2.voucherDir ?? path12.join(os2.tmpdir(), "agent-vouchers");
|
|
28179
28891
|
}
|
|
28180
28892
|
mint(agentId, launchId, capabilities2, runnerKey) {
|
|
28181
28893
|
if (!runnerKey)
|
|
28182
28894
|
throw new Error("CredentialBroker.mint: runnerKey is required (per-agent tier-2 credential)");
|
|
28183
28895
|
const voucher = randomVoucher(this.voucherPrefix);
|
|
28184
|
-
const dir =
|
|
28896
|
+
const dir = path12.join(this.voucherDir, sanitizeIdSegment(agentId));
|
|
28185
28897
|
fs5.mkdirSync(dir, { recursive: true });
|
|
28186
|
-
const voucherFile =
|
|
28898
|
+
const voucherFile = path12.join(dir, `${sanitizeIdSegment(launchId)}.token`);
|
|
28187
28899
|
fs5.writeFileSync(voucherFile, voucher, { mode: 384 });
|
|
28188
28900
|
this.registrations.set(voucher, {
|
|
28189
28901
|
agentId,
|
|
@@ -28578,7 +29290,7 @@ function joinPath(basePath, reqUrl) {
|
|
|
28578
29290
|
return base + reqPath || "/";
|
|
28579
29291
|
}
|
|
28580
29292
|
// src/daemon/createDaemon.ts
|
|
28581
|
-
import { homedir as
|
|
29293
|
+
import { homedir as homedir7 } from "os";
|
|
28582
29294
|
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync7 } from "node:fs";
|
|
28583
29295
|
|
|
28584
29296
|
// src/util/rotatingFileSink.ts
|
|
@@ -28595,7 +29307,7 @@ import {
|
|
|
28595
29307
|
statSync,
|
|
28596
29308
|
unlinkSync as unlinkSync3
|
|
28597
29309
|
} from "node:fs";
|
|
28598
|
-
function createRotatingFileSink(
|
|
29310
|
+
function createRotatingFileSink(path13, maxBytes, opts = {}) {
|
|
28599
29311
|
const report = (operation, error51) => {
|
|
28600
29312
|
try {
|
|
28601
29313
|
opts.onError?.({ operation, error: error51 });
|
|
@@ -28605,8 +29317,8 @@ function createRotatingFileSink(path9, maxBytes, opts = {}) {
|
|
|
28605
29317
|
if (!existsSync5(filePath))
|
|
28606
29318
|
return true;
|
|
28607
29319
|
try {
|
|
28608
|
-
const
|
|
28609
|
-
if (!
|
|
29320
|
+
const stat2 = lstatSync2(filePath);
|
|
29321
|
+
if (!stat2.isFile()) {
|
|
28610
29322
|
if (opts.mode === undefined && !opts.hardMaxBytes)
|
|
28611
29323
|
return true;
|
|
28612
29324
|
report("unsafe_generation", new Error("log generation is not a regular file"));
|
|
@@ -28614,7 +29326,7 @@ function createRotatingFileSink(path9, maxBytes, opts = {}) {
|
|
|
28614
29326
|
}
|
|
28615
29327
|
if (opts.mode !== undefined)
|
|
28616
29328
|
chmodSync(filePath, opts.mode);
|
|
28617
|
-
if (opts.hardMaxBytes && maxBytes > 0 &&
|
|
29329
|
+
if (opts.hardMaxBytes && maxBytes > 0 && stat2.size > maxBytes) {
|
|
28618
29330
|
try {
|
|
28619
29331
|
unlinkSync3(filePath);
|
|
28620
29332
|
} catch (error51) {
|
|
@@ -28631,9 +29343,9 @@ function createRotatingFileSink(path9, maxBytes, opts = {}) {
|
|
|
28631
29343
|
};
|
|
28632
29344
|
const rotate = () => {
|
|
28633
29345
|
try {
|
|
28634
|
-
renameSync(
|
|
29346
|
+
renameSync(path13, `${path13}.1`);
|
|
28635
29347
|
if (opts.mode !== undefined)
|
|
28636
|
-
chmodSync(`${
|
|
29348
|
+
chmodSync(`${path13}.1`, opts.mode);
|
|
28637
29349
|
return true;
|
|
28638
29350
|
} catch (error51) {
|
|
28639
29351
|
report("rotate", error51);
|
|
@@ -28642,7 +29354,7 @@ function createRotatingFileSink(path9, maxBytes, opts = {}) {
|
|
|
28642
29354
|
};
|
|
28643
29355
|
const currentSize = () => {
|
|
28644
29356
|
try {
|
|
28645
|
-
return existsSync5(
|
|
29357
|
+
return existsSync5(path13) ? statSync(path13).size : 0;
|
|
28646
29358
|
} catch (error51) {
|
|
28647
29359
|
report("stat", error51);
|
|
28648
29360
|
return null;
|
|
@@ -28650,7 +29362,7 @@ function createRotatingFileSink(path9, maxBytes, opts = {}) {
|
|
|
28650
29362
|
};
|
|
28651
29363
|
const sink = {
|
|
28652
29364
|
secure() {
|
|
28653
|
-
return secureGeneration(`${
|
|
29365
|
+
return secureGeneration(`${path13}.1`) && secureGeneration(path13);
|
|
28654
29366
|
},
|
|
28655
29367
|
write(line) {
|
|
28656
29368
|
try {
|
|
@@ -28670,7 +29382,7 @@ function createRotatingFileSink(path9, maxBytes, opts = {}) {
|
|
|
28670
29382
|
const shouldRotate = maxBytes > 0 && (opts.hardMaxBytes ? currentBytes > 0 && currentBytes + serializedBytes > maxBytes : currentBytes >= maxBytes);
|
|
28671
29383
|
if (shouldRotate && !rotate() && opts.hardMaxBytes)
|
|
28672
29384
|
return;
|
|
28673
|
-
appendFileSync(
|
|
29385
|
+
appendFileSync(path13, serialized, opts.mode === undefined ? undefined : { mode: opts.mode });
|
|
28674
29386
|
} catch (error51) {
|
|
28675
29387
|
report("append", error51);
|
|
28676
29388
|
}
|
|
@@ -28678,7 +29390,7 @@ function createRotatingFileSink(path9, maxBytes, opts = {}) {
|
|
|
28678
29390
|
openSnapshot() {
|
|
28679
29391
|
const files = [];
|
|
28680
29392
|
try {
|
|
28681
|
-
for (const candidate of [`${
|
|
29393
|
+
for (const candidate of [`${path13}.1`, path13]) {
|
|
28682
29394
|
if (!existsSync5(candidate))
|
|
28683
29395
|
continue;
|
|
28684
29396
|
if (!secureGeneration(candidate))
|
|
@@ -28686,10 +29398,10 @@ function createRotatingFileSink(path9, maxBytes, opts = {}) {
|
|
|
28686
29398
|
const noFollow = "O_NOFOLLOW" in constants ? constants.O_NOFOLLOW : 0;
|
|
28687
29399
|
const fd = openSync(candidate, constants.O_RDONLY | noFollow);
|
|
28688
29400
|
try {
|
|
28689
|
-
const
|
|
28690
|
-
if (!
|
|
29401
|
+
const stat2 = fstatSync(fd);
|
|
29402
|
+
if (!stat2.isFile())
|
|
28691
29403
|
throw new Error("snapshot source is not a regular file");
|
|
28692
|
-
files.push({ path: candidate, fd, size:
|
|
29404
|
+
files.push({ path: candidate, fd, size: stat2.size });
|
|
28693
29405
|
} catch (error51) {
|
|
28694
29406
|
closeSync(fd);
|
|
28695
29407
|
throw error51;
|
|
@@ -28839,11 +29551,11 @@ function createTraceSampler(emit, throttleMs = DEFAULT_TRACE_SAMPLE_MS) {
|
|
|
28839
29551
|
|
|
28840
29552
|
// src/util/statusFile.ts
|
|
28841
29553
|
import { writeFileSync as writeFileSync4, renameSync as renameSync2 } from "node:fs";
|
|
28842
|
-
function writeStatusFile(
|
|
29554
|
+
function writeStatusFile(path13, snapshot) {
|
|
28843
29555
|
try {
|
|
28844
|
-
const tmp = `${
|
|
29556
|
+
const tmp = `${path13}.tmp`;
|
|
28845
29557
|
writeFileSync4(tmp, JSON.stringify(snapshot));
|
|
28846
|
-
renameSync2(tmp,
|
|
29558
|
+
renameSync2(tmp, path13);
|
|
28847
29559
|
} catch {}
|
|
28848
29560
|
}
|
|
28849
29561
|
// ../shared/src/constants/community.ts
|
|
@@ -29687,6 +30399,10 @@ var CommunityBotPatchRequestSchema = exports_external.object({
|
|
|
29687
30399
|
var CommunityBotAddToServerRequestSchema = exports_external.object({
|
|
29688
30400
|
botId: exports_external.string().min(1)
|
|
29689
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
|
+
});
|
|
29690
30406
|
var CommunityAgentMessageContentSchema = exports_external.object({ text: exports_external.string().max(MAX_MESSAGE_CONTENT_LENGTH).default("") }).catchall(exports_external.unknown());
|
|
29691
30407
|
var CommunityAgentSeqSchema = exports_external.number().int().min(0);
|
|
29692
30408
|
var CommunityAgentPositiveSeqSchema = exports_external.number().int().min(1);
|
|
@@ -29781,6 +30497,9 @@ var AuditLogThinkingPayloadSchema = exports_external.object({
|
|
|
29781
30497
|
truncated: exports_external.boolean(),
|
|
29782
30498
|
chars: exports_external.number().int().nonnegative()
|
|
29783
30499
|
});
|
|
30500
|
+
var AuditLogTurnInterruptPayloadSchema = exports_external.object({
|
|
30501
|
+
status: exports_external.literal("accepted")
|
|
30502
|
+
});
|
|
29784
30503
|
var AuditLogWakeTriggerPayloadSchema = exports_external.object({
|
|
29785
30504
|
messageId: exports_external.string().min(1),
|
|
29786
30505
|
channel: exports_external.string().min(1),
|
|
@@ -29813,6 +30532,7 @@ var BotAuditEventSchema = exports_external.discriminatedUnion("kind", [
|
|
|
29813
30532
|
exports_external.object({ kind: exports_external.literal("cli_invocation"), payload: AuditLogCliInvocationPayloadSchema }),
|
|
29814
30533
|
exports_external.object({ kind: exports_external.literal("tool_call"), payload: AuditLogToolCallPayloadSchema }),
|
|
29815
30534
|
exports_external.object({ kind: exports_external.literal("thinking"), payload: AuditLogThinkingPayloadSchema }),
|
|
30535
|
+
exports_external.object({ kind: exports_external.literal("turn_interrupt"), payload: AuditLogTurnInterruptPayloadSchema }),
|
|
29816
30536
|
exports_external.object({ kind: exports_external.literal("wake_trigger"), payload: AuditLogWakeTriggerPayloadSchema }),
|
|
29817
30537
|
exports_external.object({ kind: exports_external.literal("session_reset"), payload: AuditLogSessionResetPayloadSchema }),
|
|
29818
30538
|
exports_external.object({ kind: exports_external.literal("nap"), payload: AuditLogNapPayloadSchema }),
|
|
@@ -29824,6 +30544,7 @@ var BotAuditEventKindSchema = exports_external.enum([
|
|
|
29824
30544
|
"cli_invocation",
|
|
29825
30545
|
"tool_call",
|
|
29826
30546
|
"thinking",
|
|
30547
|
+
"turn_interrupt",
|
|
29827
30548
|
"wake_trigger",
|
|
29828
30549
|
"session_reset",
|
|
29829
30550
|
"nap",
|
|
@@ -30780,7 +31501,7 @@ var communityBotAuditEventSchema = exports_external.strictObject({
|
|
|
30780
31501
|
type: exports_external.literal("community:bot.audit_event"),
|
|
30781
31502
|
botId: string4,
|
|
30782
31503
|
id: string4,
|
|
30783
|
-
kind: exports_external.enum(["cli_invocation", "tool_call", "thinking", "wake_trigger", "session_reset", "nap", "model_changed", "provider_changed", "error"]),
|
|
31504
|
+
kind: exports_external.enum(["cli_invocation", "tool_call", "thinking", "turn_interrupt", "wake_trigger", "session_reset", "nap", "model_changed", "provider_changed", "error"]),
|
|
30784
31505
|
payload: exports_external.unknown(),
|
|
30785
31506
|
sessionId: nullableString.optional(),
|
|
30786
31507
|
launchId: nullableString.optional(),
|
|
@@ -31806,11 +32527,11 @@ function timelineRowHash(line) {
|
|
|
31806
32527
|
}
|
|
31807
32528
|
function timelineFileGeneration(filePath, lines) {
|
|
31808
32529
|
try {
|
|
31809
|
-
const
|
|
31810
|
-
if (!
|
|
32530
|
+
const stat2 = fs7.lstatSync(filePath, { bigint: true });
|
|
32531
|
+
if (!stat2.isFile())
|
|
31811
32532
|
return null;
|
|
31812
32533
|
const digest = createHash4("sha256");
|
|
31813
|
-
digest.update(`${
|
|
32534
|
+
digest.update(`${stat2.dev}:${stat2.ino}:${stat2.size}:${stat2.mtimeNs}:${stat2.ctimeNs}
|
|
31814
32535
|
`);
|
|
31815
32536
|
for (const line of lines)
|
|
31816
32537
|
digest.update(line.text, "utf8").update(`
|
|
@@ -31868,9 +32589,9 @@ function compactLines(input) {
|
|
|
31868
32589
|
}
|
|
31869
32590
|
return suffix;
|
|
31870
32591
|
}
|
|
31871
|
-
function isRealDirectory(
|
|
32592
|
+
function isRealDirectory(path13) {
|
|
31872
32593
|
try {
|
|
31873
|
-
return fs7.lstatSync(
|
|
32594
|
+
return fs7.lstatSync(path13).isDirectory();
|
|
31874
32595
|
} catch {
|
|
31875
32596
|
return false;
|
|
31876
32597
|
}
|
|
@@ -31910,8 +32631,8 @@ function scanTimelineFile(filePath) {
|
|
|
31910
32631
|
let fd = null;
|
|
31911
32632
|
try {
|
|
31912
32633
|
fd = fs7.openSync(filePath, fs7.constants.O_RDONLY | (fs7.constants.O_NOFOLLOW ?? 0));
|
|
31913
|
-
const
|
|
31914
|
-
if (!
|
|
32634
|
+
const stat2 = fs7.fstatSync(fd);
|
|
32635
|
+
if (!stat2.isFile())
|
|
31915
32636
|
return null;
|
|
31916
32637
|
const chunk2 = Buffer.allocUnsafe(TIMELINE_READ_CHUNK_BYTES);
|
|
31917
32638
|
const newest = [];
|
|
@@ -31924,9 +32645,9 @@ function scanTimelineFile(filePath) {
|
|
|
31924
32645
|
let oversized = false;
|
|
31925
32646
|
let stop = false;
|
|
31926
32647
|
let discardIncompleteTail = false;
|
|
31927
|
-
if (
|
|
32648
|
+
if (stat2.size > 0) {
|
|
31928
32649
|
const last = Buffer.allocUnsafe(1);
|
|
31929
|
-
fs7.readSync(fd, last, 0, 1,
|
|
32650
|
+
fs7.readSync(fd, last, 0, 1, stat2.size - 1);
|
|
31930
32651
|
discardIncompleteTail = last[0] !== 10;
|
|
31931
32652
|
}
|
|
31932
32653
|
const resetPhysicalLine = () => {
|
|
@@ -31985,7 +32706,7 @@ function scanTimelineFile(filePath) {
|
|
|
31985
32706
|
}
|
|
31986
32707
|
resetPhysicalLine();
|
|
31987
32708
|
};
|
|
31988
|
-
let position =
|
|
32709
|
+
let position = stat2.size;
|
|
31989
32710
|
while (position > 0 && !stop) {
|
|
31990
32711
|
const start = Math.max(0, position - chunk2.length);
|
|
31991
32712
|
const requested = position - start;
|
|
@@ -32137,11 +32858,11 @@ function readResumeControlState(timelineDir) {
|
|
|
32137
32858
|
let fd = null;
|
|
32138
32859
|
try {
|
|
32139
32860
|
fd = fs7.openSync(filePath, fs7.constants.O_RDONLY | (fs7.constants.O_NOFOLLOW ?? 0));
|
|
32140
|
-
const
|
|
32141
|
-
if (!
|
|
32861
|
+
const stat2 = fs7.fstatSync(fd);
|
|
32862
|
+
if (!stat2.isFile() || stat2.size <= 0 || stat2.size > RESUME_CONTROL_MAX_BYTES) {
|
|
32142
32863
|
return { kind: "invalid" };
|
|
32143
32864
|
}
|
|
32144
|
-
const bounded = Buffer.allocUnsafe(
|
|
32865
|
+
const bounded = Buffer.allocUnsafe(stat2.size + 1);
|
|
32145
32866
|
let bytesRead = 0;
|
|
32146
32867
|
while (bytesRead < bounded.length) {
|
|
32147
32868
|
const count = fs7.readSync(fd, bounded, bytesRead, bounded.length - bytesRead, bytesRead);
|
|
@@ -32149,7 +32870,7 @@ function readResumeControlState(timelineDir) {
|
|
|
32149
32870
|
break;
|
|
32150
32871
|
bytesRead += count;
|
|
32151
32872
|
}
|
|
32152
|
-
if (bytesRead !==
|
|
32873
|
+
if (bytesRead !== stat2.size)
|
|
32153
32874
|
return { kind: "invalid" };
|
|
32154
32875
|
const raw = bounded.subarray(0, bytesRead).toString("utf8");
|
|
32155
32876
|
const value = JSON.parse(raw);
|
|
@@ -32936,26 +33657,26 @@ function createTimelineRecorder(opts) {
|
|
|
32936
33657
|
}
|
|
32937
33658
|
}
|
|
32938
33659
|
// src/discovery.ts
|
|
32939
|
-
import * as
|
|
33660
|
+
import * as path13 from "path";
|
|
32940
33661
|
import * as fs8 from "fs";
|
|
32941
33662
|
import { fileURLToPath } from "url";
|
|
32942
33663
|
function resolveAlookCliPath(moduleDir) {
|
|
32943
|
-
const thisDir = moduleDir ??
|
|
32944
|
-
const target2 =
|
|
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");
|
|
32945
33666
|
return fs8.existsSync(target2) ? target2 : null;
|
|
32946
33667
|
}
|
|
32947
33668
|
function deriveCliFallbackCandidates(cliPath) {
|
|
32948
33669
|
if (!cliPath)
|
|
32949
33670
|
return [];
|
|
32950
|
-
const normalized = cliPath.split(
|
|
33671
|
+
const normalized = cliPath.split(path13.sep).join("/");
|
|
32951
33672
|
const marker = "/node_modules/";
|
|
32952
33673
|
const idx = normalized.indexOf(marker);
|
|
32953
33674
|
if (idx === -1)
|
|
32954
33675
|
return [];
|
|
32955
33676
|
const globalRoot = cliPath.slice(0, idx + marker.length - 1);
|
|
32956
|
-
const tail =
|
|
33677
|
+
const tail = path13.join("dist", "cli", "index.js");
|
|
32957
33678
|
return [
|
|
32958
|
-
|
|
33679
|
+
path13.join(globalRoot, "@alook", "daemon", tail)
|
|
32959
33680
|
].filter((candidate) => candidate !== cliPath);
|
|
32960
33681
|
}
|
|
32961
33682
|
function resolveAlookCliPathWithFallback(primary) {
|
|
@@ -33150,7 +33871,7 @@ class MessageReminderScheduler {
|
|
|
33150
33871
|
|
|
33151
33872
|
// src/manager/agentDriverHost.ts
|
|
33152
33873
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
33153
|
-
import { homedir as
|
|
33874
|
+
import { homedir as homedir6 } from "node:os";
|
|
33154
33875
|
import { join as join13 } from "node:path";
|
|
33155
33876
|
|
|
33156
33877
|
// src/drivers/gitIdentityEnv.ts
|
|
@@ -33276,7 +33997,7 @@ function createDaemonAgentDriverHost(ctx, onRawLine) {
|
|
|
33276
33997
|
hostUser: readHostGitIdentity() ?? undefined
|
|
33277
33998
|
}),
|
|
33278
33999
|
platformProtected: {
|
|
33279
|
-
ALOOK_HOME: process.env.ALOOK_HOME ?? join13(
|
|
34000
|
+
ALOOK_HOME: process.env.ALOOK_HOME ?? join13(homedir6(), ".alook"),
|
|
33280
34001
|
ALOOK_ID: ctx.agentId,
|
|
33281
34002
|
ALOOK_CLI: ctx.agentCliPath,
|
|
33282
34003
|
ALOOK_SERVER_URL: ctx.config.serverUrl,
|
|
@@ -33597,13 +34318,13 @@ function createRuntimeRawLineTap(args) {
|
|
|
33597
34318
|
const maxBytes = args.maxBytes ?? RUNTIME_RAW_TRACE_MAX_BYTES;
|
|
33598
34319
|
const sinks = new Map;
|
|
33599
34320
|
const warned = new Set;
|
|
33600
|
-
const warnOnce = (agentId,
|
|
34321
|
+
const warnOnce = (agentId, path14, operation, error51) => {
|
|
33601
34322
|
if (warned.has(agentId))
|
|
33602
34323
|
return;
|
|
33603
34324
|
warned.add(agentId);
|
|
33604
34325
|
args.logger.warn("runtime raw trace sink failed", {
|
|
33605
34326
|
agentId,
|
|
33606
|
-
path:
|
|
34327
|
+
path: path14,
|
|
33607
34328
|
operation,
|
|
33608
34329
|
error: error51 instanceof Error ? error51.message : String(error51)
|
|
33609
34330
|
});
|
|
@@ -33612,10 +34333,10 @@ function createRuntimeRawLineTap(args) {
|
|
|
33612
34333
|
if (!args.enabledAgentIds.has(agentId))
|
|
33613
34334
|
return;
|
|
33614
34335
|
const encodedAgentId = encodeURIComponent(agentId).replace(/\./g, "%2E");
|
|
33615
|
-
const
|
|
34336
|
+
const path14 = `${traceDir}/runtime-raw-events-${encodedAgentId}.jsonl`;
|
|
33616
34337
|
const serializedBytes = Buffer.byteLength(line, "utf8") + 1;
|
|
33617
34338
|
if (serializedBytes > maxBytes) {
|
|
33618
|
-
warnOnce(agentId,
|
|
34339
|
+
warnOnce(agentId, path14, "oversize", new Error(`raw line is ${serializedBytes} bytes; max is ${maxBytes}`));
|
|
33619
34340
|
return;
|
|
33620
34341
|
}
|
|
33621
34342
|
let sink = sinks.get(agentId);
|
|
@@ -33623,12 +34344,12 @@ function createRuntimeRawLineTap(args) {
|
|
|
33623
34344
|
try {
|
|
33624
34345
|
mkdirSync7(traceDir, { recursive: true });
|
|
33625
34346
|
} catch (error51) {
|
|
33626
|
-
warnOnce(agentId,
|
|
34347
|
+
warnOnce(agentId, path14, "mkdir", error51);
|
|
33627
34348
|
}
|
|
33628
|
-
sink = createRotatingFileSink(
|
|
34349
|
+
sink = createRotatingFileSink(path14, maxBytes, {
|
|
33629
34350
|
mode: 384,
|
|
33630
34351
|
hardMaxBytes: true,
|
|
33631
|
-
onError: ({ operation, error: error51 }) => warnOnce(agentId,
|
|
34352
|
+
onError: ({ operation, error: error51 }) => warnOnce(agentId, path14, operation, error51)
|
|
33632
34353
|
});
|
|
33633
34354
|
sinks.set(agentId, sink);
|
|
33634
34355
|
}
|
|
@@ -33720,7 +34441,7 @@ function createBuiltinDaemonSessionFactory(onRuntimeRawLine) {
|
|
|
33720
34441
|
}
|
|
33721
34442
|
async function createDaemon(opts) {
|
|
33722
34443
|
const log2 = opts.logger ?? createLogger({ header: "@alook/daemon" });
|
|
33723
|
-
const fallbackBase = (process.env.ALOOK_PROJECT_ROOT || `${
|
|
34444
|
+
const fallbackBase = (process.env.ALOOK_PROJECT_ROOT || `${homedir7()}/.alook`) + "/daemon";
|
|
33724
34445
|
const workingDirectoryBase = opts.workingDirectoryBase ?? fallbackBase;
|
|
33725
34446
|
const workdirFor = (agentId) => `${workingDirectoryBase}/${agentId}`;
|
|
33726
34447
|
const dailyTokenUsage2 = new DailyTokenUsageStore(workingDirectoryBase);
|
|
@@ -34311,6 +35032,7 @@ export {
|
|
|
34311
35032
|
buildApmFreshnessDecisionProducerFactId,
|
|
34312
35033
|
UnknownRuntimeError,
|
|
34313
35034
|
UnknownBotError,
|
|
35035
|
+
SESSION_FILE_DISCOVERY_CAPABILITIES2 as SESSION_FILE_DISCOVERY_CAPABILITIES,
|
|
34314
35036
|
RuntimeProgressState,
|
|
34315
35037
|
RuntimeNotificationState,
|
|
34316
35038
|
RUNTIME_RAW_TRACE_AGENT_IDS_ENV,
|