@victor-software-house/pi-acp 0.11.0 → 0.13.0
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.
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { a as removeStaleSocketIfAny, i as releaseLock, n as controlSocketPath, o as socketPath, r as ensureSocketParentDir, t as acquireLock } from "./socket-wvV053VI.mjs";
|
|
3
3
|
import { t as piChangelogPath } from "./pi-package-aHs6rWNo.mjs";
|
|
4
4
|
import { createServer } from "node:net";
|
|
5
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
6
|
-
import { homedir } from "node:os";
|
|
5
|
+
import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
6
|
+
import { homedir, tmpdir } from "node:os";
|
|
7
7
|
import { isAbsolute, join, resolve } from "node:path";
|
|
8
8
|
import { Hono } from "hono";
|
|
9
9
|
import { AgentSideConnection, RequestError, ndJsonStream } from "@agentclientprotocol/sdk";
|
|
@@ -876,6 +876,8 @@ var PiAcpSession = class {
|
|
|
876
876
|
lastAssistantStopReason = null;
|
|
877
877
|
lastEmit = Promise.resolve();
|
|
878
878
|
unsubscribe;
|
|
879
|
+
cleanups;
|
|
880
|
+
pendingDiagnosticsReport;
|
|
879
881
|
constructor(opts) {
|
|
880
882
|
this.sessionId = opts.sessionId;
|
|
881
883
|
this.cwd = opts.cwd;
|
|
@@ -883,11 +885,16 @@ var PiAcpSession = class {
|
|
|
883
885
|
this.piSession = opts.piSession;
|
|
884
886
|
this.conn = opts.conn;
|
|
885
887
|
this.supportsTerminalOutput = opts.supportsTerminalOutput ?? false;
|
|
888
|
+
this.cleanups = opts.cleanups ?? [];
|
|
889
|
+
this.pendingDiagnosticsReport = opts.diagnosticsReport !== void 0 && opts.diagnosticsReport !== "" ? opts.diagnosticsReport : null;
|
|
886
890
|
this.unsubscribe = this.piSession.subscribe((ev) => this.handlePiEvent(ev));
|
|
887
891
|
}
|
|
888
892
|
dispose() {
|
|
889
893
|
this.unsubscribe?.();
|
|
890
894
|
this.piSession.dispose();
|
|
895
|
+
for (const cleanup of this.cleanups) try {
|
|
896
|
+
cleanup();
|
|
897
|
+
} catch {}
|
|
891
898
|
}
|
|
892
899
|
/**
|
|
893
900
|
* Drop event subscription without disposing the underlying piSession.
|
|
@@ -925,6 +932,20 @@ var PiAcpSession = class {
|
|
|
925
932
|
};
|
|
926
933
|
});
|
|
927
934
|
const imageContents = Array.isArray(images) ? images.filter((img) => typeof img === "object" && img !== null && "type" in img && img.type === "image") : [];
|
|
935
|
+
if (this.pendingDiagnosticsReport !== null) {
|
|
936
|
+
const report = this.pendingDiagnosticsReport;
|
|
937
|
+
this.pendingDiagnosticsReport = null;
|
|
938
|
+
this.conn.sessionUpdate({
|
|
939
|
+
sessionId: this.sessionId,
|
|
940
|
+
update: {
|
|
941
|
+
sessionUpdate: "agent_message_chunk",
|
|
942
|
+
content: {
|
|
943
|
+
type: "text",
|
|
944
|
+
text: `${report}\n`
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
}).catch(() => {});
|
|
948
|
+
}
|
|
928
949
|
this.piSession.prompt(message, { images: imageContents }).catch(() => {
|
|
929
950
|
this.flushEmits().finally(() => {
|
|
930
951
|
const reason = this.cancelRequested ? "cancelled" : "error";
|
|
@@ -1340,6 +1361,43 @@ function acpPromptToPiMessage(blocks) {
|
|
|
1340
1361
|
};
|
|
1341
1362
|
}
|
|
1342
1363
|
//#endregion
|
|
1364
|
+
//#region src/resources/diagnostics.ts
|
|
1365
|
+
function buildDiagnosticsReport(input) {
|
|
1366
|
+
const sourceStats = input.sources.map((source) => {
|
|
1367
|
+
const skills = source.getSkills();
|
|
1368
|
+
const prompts = source.getPrompts();
|
|
1369
|
+
const failures = skills.diagnostics.filter((d) => d.type === "warning" || d.type === "error").map((d) => d.message);
|
|
1370
|
+
return {
|
|
1371
|
+
id: source.id,
|
|
1372
|
+
kind: source.kind,
|
|
1373
|
+
agentsFiles: source.getAgentsFiles().length,
|
|
1374
|
+
skills: skills.skills.length,
|
|
1375
|
+
prompts: prompts.prompts.length,
|
|
1376
|
+
failures
|
|
1377
|
+
};
|
|
1378
|
+
});
|
|
1379
|
+
const lines = [];
|
|
1380
|
+
if (sourceStats.length > 0) {
|
|
1381
|
+
lines.push("[pi-acp] resources active:");
|
|
1382
|
+
for (const s of sourceStats) lines.push(` ${s.id.padEnd(20)} kind=${s.kind} (${s.agentsFiles} AGENTS files, ${s.skills} skills, ${s.prompts} prompts)`);
|
|
1383
|
+
}
|
|
1384
|
+
const allFailures = [];
|
|
1385
|
+
for (const s of sourceStats) for (const f of s.failures) allFailures.push(` ${s.id.padEnd(20)} ${f}`);
|
|
1386
|
+
for (const d of input.manifestDiagnostics) {
|
|
1387
|
+
const where = d.path !== void 0 ? ` ${d.path}` : "";
|
|
1388
|
+
allFailures.push(` manifest[${d.source}${where}] ${d.message}`);
|
|
1389
|
+
}
|
|
1390
|
+
if (allFailures.length > 0) {
|
|
1391
|
+
if (lines.length > 0) lines.push("");
|
|
1392
|
+
lines.push("[pi-acp] resource failures:");
|
|
1393
|
+
lines.push(...allFailures);
|
|
1394
|
+
}
|
|
1395
|
+
return {
|
|
1396
|
+
text: lines.join("\n"),
|
|
1397
|
+
sourceStats
|
|
1398
|
+
};
|
|
1399
|
+
}
|
|
1400
|
+
//#endregion
|
|
1343
1401
|
//#region src/resources/sources/local.ts
|
|
1344
1402
|
/**
|
|
1345
1403
|
* LocalBackend: wraps pi's DefaultResourceLoader for one (cwd, agentDir) root.
|
|
@@ -1679,6 +1737,58 @@ function tryFromFile(path, source, diagnostics) {
|
|
|
1679
1737
|
return null;
|
|
1680
1738
|
}
|
|
1681
1739
|
//#endregion
|
|
1740
|
+
//#region src/resources/modes.ts
|
|
1741
|
+
/**
|
|
1742
|
+
* Cwd-independence modes (PRD-002 §FR-5).
|
|
1743
|
+
*
|
|
1744
|
+
* | Mode | cwd handling | Tool target |
|
|
1745
|
+
* |-----------|--------------------------------------------|---------------|
|
|
1746
|
+
* | `local` | ACP params.cwd (must be absolute) | params.cwd |
|
|
1747
|
+
* | `overlay` | same as local — manifest aux roots compose | params.cwd |
|
|
1748
|
+
* | `none` | substitute ephemeral tmpdir | tmpdir |
|
|
1749
|
+
*
|
|
1750
|
+
* `local` and `overlay` are functionally identical in the current substrate
|
|
1751
|
+
* because `VirtualResourceLoader` always overlays manifest roots on top of
|
|
1752
|
+
* the implicit local root. The `overlay` keyword is retained for
|
|
1753
|
+
* forward-compatibility and operator clarity (declaring `mode: overlay`
|
|
1754
|
+
* documents the intent even if the runtime path is the same).
|
|
1755
|
+
*
|
|
1756
|
+
* `none` mints `mkdtemp(...)` under the OS tmpdir and returns a cleanup
|
|
1757
|
+
* thunk the caller must invoke at session close. The cleanup is
|
|
1758
|
+
* best-effort — never throws — so a session dispose path that runs it
|
|
1759
|
+
* after the directory has already been removed is safe.
|
|
1760
|
+
*/
|
|
1761
|
+
const TMPDIR_PREFIX = "pi-acp-session-";
|
|
1762
|
+
function resolveMode(input) {
|
|
1763
|
+
const mode = input.manifest.mode;
|
|
1764
|
+
if (mode === "none") {
|
|
1765
|
+
const dir = mkdtempSync(join(tmpdir(), TMPDIR_PREFIX));
|
|
1766
|
+
let removed = false;
|
|
1767
|
+
const cleanup = () => {
|
|
1768
|
+
if (removed) return;
|
|
1769
|
+
removed = true;
|
|
1770
|
+
try {
|
|
1771
|
+
rmSync(dir, {
|
|
1772
|
+
recursive: true,
|
|
1773
|
+
force: true
|
|
1774
|
+
});
|
|
1775
|
+
} catch {}
|
|
1776
|
+
};
|
|
1777
|
+
return {
|
|
1778
|
+
mode,
|
|
1779
|
+
cwd: dir,
|
|
1780
|
+
cleanup,
|
|
1781
|
+
ephemeral: true
|
|
1782
|
+
};
|
|
1783
|
+
}
|
|
1784
|
+
return {
|
|
1785
|
+
mode,
|
|
1786
|
+
cwd: input.requestedCwd,
|
|
1787
|
+
cleanup: () => {},
|
|
1788
|
+
ephemeral: false
|
|
1789
|
+
};
|
|
1790
|
+
}
|
|
1791
|
+
//#endregion
|
|
1682
1792
|
//#region src/resources/sources/http.ts
|
|
1683
1793
|
const DEFAULT_CACHE_TTL_SECONDS = 300;
|
|
1684
1794
|
const DEFAULT_TIMEOUT_MS$1 = 5e3;
|
|
@@ -1897,7 +2007,7 @@ var SshBackend = class {
|
|
|
1897
2007
|
//#endregion
|
|
1898
2008
|
//#region package.json
|
|
1899
2009
|
var name = "@victor-software-house/pi-acp";
|
|
1900
|
-
var version = "0.
|
|
2010
|
+
var version = "0.13.0";
|
|
1901
2011
|
//#endregion
|
|
1902
2012
|
//#region src/acp/agent.ts
|
|
1903
2013
|
/** Builtin ACP slash commands handled directly by the adapter. */
|
|
@@ -2034,13 +2144,18 @@ var PiAcpAgent = class {
|
|
|
2034
2144
|
cwd,
|
|
2035
2145
|
sessionParams
|
|
2036
2146
|
});
|
|
2147
|
+
const modeResult = resolveMode({
|
|
2148
|
+
manifest: loaded.manifest,
|
|
2149
|
+
requestedCwd: cwd
|
|
2150
|
+
});
|
|
2151
|
+
const effectiveCwd = modeResult.cwd;
|
|
2037
2152
|
const diagnostics = [...loaded.diagnostics];
|
|
2038
2153
|
const sources = [];
|
|
2039
2154
|
for (const root of loaded.manifest.roots) {
|
|
2040
2155
|
if (root.kind === "local") {
|
|
2041
2156
|
sources.push(new LocalBackend({
|
|
2042
2157
|
id: root.id,
|
|
2043
|
-
cwd: root.paths.cwd ??
|
|
2158
|
+
cwd: root.paths.cwd ?? effectiveCwd,
|
|
2044
2159
|
agentDir: root.paths.agentDir ?? getAgentDir()
|
|
2045
2160
|
}));
|
|
2046
2161
|
continue;
|
|
@@ -2073,7 +2188,7 @@ var PiAcpAgent = class {
|
|
|
2073
2188
|
diagnostics.push(diag);
|
|
2074
2189
|
}
|
|
2075
2190
|
if (!sources.some((s) => s.kind === "local")) sources.unshift(new LocalBackend({
|
|
2076
|
-
cwd,
|
|
2191
|
+
cwd: effectiveCwd,
|
|
2077
2192
|
agentDir: getAgentDir()
|
|
2078
2193
|
}));
|
|
2079
2194
|
const loader = new VirtualResourceLoader({
|
|
@@ -2085,7 +2200,12 @@ var PiAcpAgent = class {
|
|
|
2085
2200
|
const where = d.path !== void 0 ? ` ${d.path}` : "";
|
|
2086
2201
|
process.stderr.write(`pi-acp manifest [${d.source}${where}]: ${d.message}\n`);
|
|
2087
2202
|
}
|
|
2088
|
-
return
|
|
2203
|
+
return {
|
|
2204
|
+
loader,
|
|
2205
|
+
modeResult,
|
|
2206
|
+
diagnosticsEnabled: loaded.manifest.diagnostics === true,
|
|
2207
|
+
manifestDiagnostics: diagnostics
|
|
2208
|
+
};
|
|
2089
2209
|
}
|
|
2090
2210
|
/**
|
|
2091
2211
|
* PRD-002 §FR-6 — `read` tool ACP-FS delegation overlay.
|
|
@@ -2158,13 +2278,26 @@ var PiAcpAgent = class {
|
|
|
2158
2278
|
};
|
|
2159
2279
|
}
|
|
2160
2280
|
async newSession(params) {
|
|
2161
|
-
|
|
2162
|
-
|
|
2281
|
+
const { loader: resourceLoader, modeResult, diagnosticsEnabled, manifestDiagnostics } = await this.buildResourceLoader(params.cwd, params).catch((e) => {
|
|
2282
|
+
const authErr = detectAuthError(e);
|
|
2283
|
+
if (authErr !== null) throw authErr;
|
|
2284
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
2285
|
+
throw RequestError.internalError({}, `Failed to load pi-acp manifest: ${msg}`);
|
|
2286
|
+
});
|
|
2287
|
+
const effectiveCwd = modeResult.cwd;
|
|
2288
|
+
if (modeResult.mode !== "none" && !isAbsolute(params.cwd)) {
|
|
2289
|
+
modeResult.cleanup();
|
|
2290
|
+
throw RequestError.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
|
|
2291
|
+
}
|
|
2292
|
+
const diagnosticsReport = diagnosticsEnabled ? buildDiagnosticsReport({
|
|
2293
|
+
sources: resourceLoader.listSources(),
|
|
2294
|
+
manifestDiagnostics
|
|
2295
|
+
}).text : "";
|
|
2296
|
+
const acpReadOverlay = this.buildAcpReadOverlay(effectiveCwd);
|
|
2163
2297
|
let result;
|
|
2164
2298
|
try {
|
|
2165
|
-
const resourceLoader = await this.buildResourceLoader(params.cwd, params);
|
|
2166
2299
|
result = await createAgentSession({
|
|
2167
|
-
cwd:
|
|
2300
|
+
cwd: effectiveCwd,
|
|
2168
2301
|
resourceLoader,
|
|
2169
2302
|
...acpReadOverlay ? {
|
|
2170
2303
|
tools: acpReadOverlay.tools,
|
|
@@ -2172,6 +2305,7 @@ var PiAcpAgent = class {
|
|
|
2172
2305
|
} : {}
|
|
2173
2306
|
});
|
|
2174
2307
|
} catch (e) {
|
|
2308
|
+
modeResult.cleanup();
|
|
2175
2309
|
const authErr = detectAuthError(e);
|
|
2176
2310
|
if (authErr !== null) throw authErr;
|
|
2177
2311
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -2181,6 +2315,7 @@ var PiAcpAgent = class {
|
|
|
2181
2315
|
if (acpReadOverlay !== null) acpReadOverlay.sessionIdRef.current = piSession.sessionManager.getSessionId();
|
|
2182
2316
|
if (piSession.modelRegistry.getAvailable().length === 0) {
|
|
2183
2317
|
piSession.dispose();
|
|
2318
|
+
modeResult.cleanup();
|
|
2184
2319
|
throw RequestError.authRequired({ authMethods: buildAuthMethods() }, "Configure an API key or log in with an OAuth provider.");
|
|
2185
2320
|
}
|
|
2186
2321
|
const sessionId = piSession.sessionManager.getSessionId();
|
|
@@ -2188,11 +2323,13 @@ var PiAcpAgent = class {
|
|
|
2188
2323
|
if (sessionFile !== void 0) this.sessionPaths.set(sessionId, sessionFile);
|
|
2189
2324
|
const session = new PiAcpSession({
|
|
2190
2325
|
sessionId,
|
|
2191
|
-
cwd:
|
|
2326
|
+
cwd: effectiveCwd,
|
|
2192
2327
|
mcpServers: params.mcpServers,
|
|
2193
2328
|
piSession,
|
|
2194
2329
|
conn: this.conn,
|
|
2195
|
-
supportsTerminalOutput: this.clientCapabilities.terminalOutput
|
|
2330
|
+
supportsTerminalOutput: this.clientCapabilities.terminalOutput,
|
|
2331
|
+
cleanups: modeResult.ephemeral ? [modeResult.cleanup] : [],
|
|
2332
|
+
...diagnosticsReport !== "" ? { diagnosticsReport } : {}
|
|
2196
2333
|
});
|
|
2197
2334
|
this.sessions.register(session);
|
|
2198
2335
|
this.registerWithDaemon({
|
|
@@ -2442,7 +2579,7 @@ var PiAcpAgent = class {
|
|
|
2442
2579
|
let result;
|
|
2443
2580
|
try {
|
|
2444
2581
|
const sm = SessionManager.open(sessionFile);
|
|
2445
|
-
const resourceLoader = await this.buildResourceLoader(params.cwd, params);
|
|
2582
|
+
const { loader: resourceLoader } = await this.buildResourceLoader(params.cwd, params);
|
|
2446
2583
|
result = await createAgentSession({
|
|
2447
2584
|
cwd: params.cwd,
|
|
2448
2585
|
sessionManager: sm,
|
|
@@ -2548,7 +2685,7 @@ var PiAcpAgent = class {
|
|
|
2548
2685
|
let result;
|
|
2549
2686
|
try {
|
|
2550
2687
|
const sm = SessionManager.open(sessionFile);
|
|
2551
|
-
const resourceLoader = await this.buildResourceLoader(params.cwd, params);
|
|
2688
|
+
const { loader: resourceLoader } = await this.buildResourceLoader(params.cwd, params);
|
|
2552
2689
|
result = await createAgentSession({
|
|
2553
2690
|
cwd: params.cwd,
|
|
2554
2691
|
sessionManager: sm,
|
|
@@ -2613,7 +2750,7 @@ var PiAcpAgent = class {
|
|
|
2613
2750
|
let result;
|
|
2614
2751
|
try {
|
|
2615
2752
|
const sm = SessionManager.forkFrom(sourceFile, params.cwd);
|
|
2616
|
-
const resourceLoader = await this.buildResourceLoader(params.cwd, params);
|
|
2753
|
+
const { loader: resourceLoader } = await this.buildResourceLoader(params.cwd, params);
|
|
2617
2754
|
result = await createAgentSession({
|
|
2618
2755
|
cwd: params.cwd,
|
|
2619
2756
|
sessionManager: sm,
|
|
@@ -3250,4 +3387,4 @@ async function runDaemon() {
|
|
|
3250
3387
|
//#endregion
|
|
3251
3388
|
export { runDaemon };
|
|
3252
3389
|
|
|
3253
|
-
//# sourceMappingURL=daemon-
|
|
3390
|
+
//# sourceMappingURL=daemon-BdW4nUzA.mjs.map
|