@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.
- package/dist/cli/index.js +970 -193
- package/dist/index.js +821 -116
- 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);
|
|
@@ -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,
|
|
11703
|
-
if (!
|
|
12374
|
+
function getElementAtPath(obj, path12) {
|
|
12375
|
+
if (!path12)
|
|
11704
12376
|
return obj;
|
|
11705
|
-
return
|
|
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(
|
|
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(
|
|
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,
|
|
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 }, [...
|
|
12939
|
+
issue2.errors.map((issues) => processError({ issues }, [...path12, ...issue2.path]));
|
|
12268
12940
|
} else if (issue2.code === "invalid_key") {
|
|
12269
|
-
processError({ issues: issue2.issues }, [...
|
|
12941
|
+
processError({ issues: issue2.issues }, [...path12, ...issue2.path]);
|
|
12270
12942
|
} else if (issue2.code === "invalid_element") {
|
|
12271
|
-
processError({ issues: issue2.issues }, [...
|
|
12943
|
+
processError({ issues: issue2.issues }, [...path12, ...issue2.path]);
|
|
12272
12944
|
} else {
|
|
12273
|
-
const fullpath = [...
|
|
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,
|
|
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 }, [...
|
|
12976
|
+
issue2.errors.map((issues) => processError({ issues }, [...path12, ...issue2.path]));
|
|
12305
12977
|
} else if (issue2.code === "invalid_key") {
|
|
12306
|
-
processError({ issues: issue2.issues }, [...
|
|
12978
|
+
processError({ issues: issue2.issues }, [...path12, ...issue2.path]);
|
|
12307
12979
|
} else if (issue2.code === "invalid_element") {
|
|
12308
|
-
processError({ issues: issue2.issues }, [...
|
|
12980
|
+
processError({ issues: issue2.issues }, [...path12, ...issue2.path]);
|
|
12309
12981
|
} else {
|
|
12310
|
-
const fullpath = [...
|
|
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
|
|
12343
|
-
for (const seg of
|
|
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
|
|
24803
|
-
if (
|
|
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 (
|
|
24808
|
-
const key =
|
|
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
|
|
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 ??
|
|
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 =
|
|
28896
|
+
const dir = path12.join(this.voucherDir, sanitizeIdSegment(agentId));
|
|
28197
28897
|
fs5.mkdirSync(dir, { recursive: true });
|
|
28198
|
-
const voucherFile =
|
|
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
|
|
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(
|
|
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
|
|
28621
|
-
if (!
|
|
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 &&
|
|
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(
|
|
29346
|
+
renameSync(path13, `${path13}.1`);
|
|
28647
29347
|
if (opts.mode !== undefined)
|
|
28648
|
-
chmodSync(`${
|
|
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(
|
|
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(`${
|
|
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(
|
|
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 [`${
|
|
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
|
|
28702
|
-
if (!
|
|
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:
|
|
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(
|
|
29554
|
+
function writeStatusFile(path13, snapshot) {
|
|
28855
29555
|
try {
|
|
28856
|
-
const tmp = `${
|
|
29556
|
+
const tmp = `${path13}.tmp`;
|
|
28857
29557
|
writeFileSync4(tmp, JSON.stringify(snapshot));
|
|
28858
|
-
renameSync2(tmp,
|
|
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
|
|
31827
|
-
if (!
|
|
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(`${
|
|
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(
|
|
32592
|
+
function isRealDirectory(path13) {
|
|
31889
32593
|
try {
|
|
31890
|
-
return fs7.lstatSync(
|
|
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
|
|
31931
|
-
if (!
|
|
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 (
|
|
32648
|
+
if (stat2.size > 0) {
|
|
31945
32649
|
const last = Buffer.allocUnsafe(1);
|
|
31946
|
-
fs7.readSync(fd, last, 0, 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 =
|
|
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
|
|
32158
|
-
if (!
|
|
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(
|
|
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 !==
|
|
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
|
|
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 ??
|
|
32961
|
-
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");
|
|
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(
|
|
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 =
|
|
33677
|
+
const tail = path13.join("dist", "cli", "index.js");
|
|
32974
33678
|
return [
|
|
32975
|
-
|
|
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
|
|
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(
|
|
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,
|
|
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:
|
|
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
|
|
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,
|
|
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,
|
|
34347
|
+
warnOnce(agentId, path14, "mkdir", error51);
|
|
33644
34348
|
}
|
|
33645
|
-
sink = createRotatingFileSink(
|
|
34349
|
+
sink = createRotatingFileSink(path14, maxBytes, {
|
|
33646
34350
|
mode: 384,
|
|
33647
34351
|
hardMaxBytes: true,
|
|
33648
|
-
onError: ({ operation, error: error51 }) => warnOnce(agentId,
|
|
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 || `${
|
|
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,
|