pi-acp 0.0.31 → 0.0.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/index.js +188 -18
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -526,6 +526,52 @@ function expandSlashCommand(text, fileCommands) {
|
|
|
526
526
|
return substituteArgs(cmd.content, args);
|
|
527
527
|
}
|
|
528
528
|
|
|
529
|
+
// src/acp/translate/bash.ts
|
|
530
|
+
function isBashTool(toolName) {
|
|
531
|
+
return toolName.toLowerCase() === "bash";
|
|
532
|
+
}
|
|
533
|
+
function bashCommand(value) {
|
|
534
|
+
const record = value;
|
|
535
|
+
const command = record?.command ?? record?.cmd ?? record?.args?.command ?? record?.args?.cmd ?? record?.input?.command ?? record?.input?.cmd ?? record?.rawInput?.command ?? record?.rawInput?.cmd ?? record?.toolInput?.command ?? record?.toolInput?.cmd ?? record?.details?.command ?? record?.details?.cmd;
|
|
536
|
+
return typeof command === "string" && command.trim() ? command : void 0;
|
|
537
|
+
}
|
|
538
|
+
function bashResultText(result) {
|
|
539
|
+
const record = result;
|
|
540
|
+
const content = record?.content;
|
|
541
|
+
if (Array.isArray(content)) {
|
|
542
|
+
const texts = content.map((c) => {
|
|
543
|
+
const block = c;
|
|
544
|
+
return block.type === "text" && typeof block.text === "string" ? block.text : "";
|
|
545
|
+
}).filter(Boolean);
|
|
546
|
+
if (texts.length) return texts.join("");
|
|
547
|
+
}
|
|
548
|
+
const details = record?.details;
|
|
549
|
+
const stdout = (typeof details?.stdout === "string" ? details.stdout : void 0) ?? (typeof record?.stdout === "string" ? record.stdout : void 0) ?? (typeof details?.output === "string" ? details.output : void 0) ?? (typeof record?.output === "string" ? record.output : void 0);
|
|
550
|
+
const stderr = (typeof details?.stderr === "string" ? details.stderr : void 0) ?? (typeof record?.stderr === "string" ? record.stderr : void 0);
|
|
551
|
+
return [stdout, stderr].filter((part) => typeof part === "string" && part.length > 0).join("\n");
|
|
552
|
+
}
|
|
553
|
+
function bashExitCode(result, isError) {
|
|
554
|
+
const record = result;
|
|
555
|
+
const details = record?.details;
|
|
556
|
+
const exitCode = details?.exitCode ?? record?.exitCode ?? details?.code ?? record?.code;
|
|
557
|
+
return typeof exitCode === "number" ? exitCode : isError ? 1 : 0;
|
|
558
|
+
}
|
|
559
|
+
function bashOutputDelta(previous, next) {
|
|
560
|
+
return next.startsWith(previous) ? next.slice(previous.length) : next;
|
|
561
|
+
}
|
|
562
|
+
function bashTerminalContent(toolCallId) {
|
|
563
|
+
return [{ type: "terminal", terminalId: toolCallId }];
|
|
564
|
+
}
|
|
565
|
+
function bashTerminalInfoMeta(toolCallId, cwd) {
|
|
566
|
+
return { terminal_info: { terminal_id: toolCallId, cwd } };
|
|
567
|
+
}
|
|
568
|
+
function bashTerminalOutputMeta(toolCallId, data) {
|
|
569
|
+
return { terminal_output: { terminal_id: toolCallId, data } };
|
|
570
|
+
}
|
|
571
|
+
function bashTerminalExitMeta(toolCallId, exitCode) {
|
|
572
|
+
return { terminal_exit: { terminal_id: toolCallId, exit_code: exitCode, signal: null } };
|
|
573
|
+
}
|
|
574
|
+
|
|
529
575
|
// src/acp/translate/pi-tools.ts
|
|
530
576
|
function toolResultToText(result) {
|
|
531
577
|
if (!result) return "";
|
|
@@ -749,6 +795,8 @@ var PiAcpSession = class {
|
|
|
749
795
|
// events may need to be implemented in pi in the future.
|
|
750
796
|
fileSnapshots = /* @__PURE__ */ new Map();
|
|
751
797
|
fileMutationToolCallIds = /* @__PURE__ */ new Set();
|
|
798
|
+
bashToolCallIds = /* @__PURE__ */ new Set();
|
|
799
|
+
bashOutputSnapshots = /* @__PURE__ */ new Map();
|
|
752
800
|
// Ensure `session/update` notifications are sent in order and can be awaited
|
|
753
801
|
// before completing a `session/prompt` request.
|
|
754
802
|
lastEmit = Promise.resolve();
|
|
@@ -832,6 +880,41 @@ var PiAcpSession = class {
|
|
|
832
880
|
async flushEmits() {
|
|
833
881
|
await this.lastEmit;
|
|
834
882
|
}
|
|
883
|
+
emitBashToolCall(params) {
|
|
884
|
+
this.bashToolCallIds.add(params.toolCallId);
|
|
885
|
+
this.emit({
|
|
886
|
+
sessionUpdate: params.sessionUpdate,
|
|
887
|
+
toolCallId: params.toolCallId,
|
|
888
|
+
title: bashCommand(params.args) ?? params.toolName,
|
|
889
|
+
kind: "execute",
|
|
890
|
+
status: params.status,
|
|
891
|
+
locations: params.locations,
|
|
892
|
+
...params.includeTerminal ? { content: bashTerminalContent(params.toolCallId) } : {},
|
|
893
|
+
...params.includeTerminal ? { _meta: bashTerminalInfoMeta(params.toolCallId, this.cwd) } : {}
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
emitBashOutputUpdate(params) {
|
|
897
|
+
const text = bashResultText(params.result);
|
|
898
|
+
const previous = this.bashOutputSnapshots.get(params.toolCallId) ?? "";
|
|
899
|
+
const delta = bashOutputDelta(previous, text);
|
|
900
|
+
this.bashOutputSnapshots.set(params.toolCallId, text);
|
|
901
|
+
this.emit({
|
|
902
|
+
sessionUpdate: "tool_call_update",
|
|
903
|
+
toolCallId: params.toolCallId,
|
|
904
|
+
status: params.status,
|
|
905
|
+
_meta: {
|
|
906
|
+
...delta ? bashTerminalOutputMeta(params.toolCallId, delta) : {},
|
|
907
|
+
...params.status === "completed" || params.status === "failed" ? bashTerminalExitMeta(params.toolCallId, bashExitCode(params.result, Boolean(params.isError))) : {}
|
|
908
|
+
}
|
|
909
|
+
});
|
|
910
|
+
}
|
|
911
|
+
cleanupToolCall(toolCallId) {
|
|
912
|
+
this.currentToolCalls.delete(toolCallId);
|
|
913
|
+
this.fileSnapshots.delete(toolCallId);
|
|
914
|
+
this.fileMutationToolCallIds.delete(toolCallId);
|
|
915
|
+
this.bashToolCallIds.delete(toolCallId);
|
|
916
|
+
this.bashOutputSnapshots.delete(toolCallId);
|
|
917
|
+
}
|
|
835
918
|
startTurn(t) {
|
|
836
919
|
this.cancelRequested = false;
|
|
837
920
|
this.inAgentLoop = false;
|
|
@@ -899,7 +982,18 @@ var PiAcpSession = class {
|
|
|
899
982
|
const locations = toToolCallLocations(rawInput, this.cwd);
|
|
900
983
|
const existingStatus = this.currentToolCalls.get(toolCallId);
|
|
901
984
|
const status = existingStatus ?? "pending";
|
|
902
|
-
if (
|
|
985
|
+
if (isBashTool(toolName)) {
|
|
986
|
+
if (!existingStatus) this.currentToolCalls.set(toolCallId, "pending");
|
|
987
|
+
this.emitBashToolCall({
|
|
988
|
+
sessionUpdate: existingStatus ? "tool_call_update" : "tool_call",
|
|
989
|
+
toolCallId,
|
|
990
|
+
toolName,
|
|
991
|
+
args: rawInput,
|
|
992
|
+
status,
|
|
993
|
+
locations,
|
|
994
|
+
includeTerminal: !existingStatus
|
|
995
|
+
});
|
|
996
|
+
} else if (!existingStatus) {
|
|
903
997
|
this.currentToolCalls.set(toolCallId, "pending");
|
|
904
998
|
this.emit({
|
|
905
999
|
sessionUpdate: "tool_call",
|
|
@@ -929,6 +1023,21 @@ var PiAcpSession = class {
|
|
|
929
1023
|
const toolName = String(ev.toolName ?? "tool");
|
|
930
1024
|
const args = ev.args;
|
|
931
1025
|
let line;
|
|
1026
|
+
if (isBashTool(toolName)) {
|
|
1027
|
+
const locations2 = toToolCallLocations(args, this.cwd);
|
|
1028
|
+
const existingStatus = this.currentToolCalls.get(toolCallId);
|
|
1029
|
+
this.currentToolCalls.set(toolCallId, "in_progress");
|
|
1030
|
+
this.emitBashToolCall({
|
|
1031
|
+
sessionUpdate: existingStatus ? "tool_call_update" : "tool_call",
|
|
1032
|
+
toolCallId,
|
|
1033
|
+
toolName,
|
|
1034
|
+
args,
|
|
1035
|
+
status: "in_progress",
|
|
1036
|
+
locations: locations2,
|
|
1037
|
+
includeTerminal: !existingStatus
|
|
1038
|
+
});
|
|
1039
|
+
break;
|
|
1040
|
+
}
|
|
932
1041
|
const isFileMutation = toolName === "edit" || toolName === "write";
|
|
933
1042
|
let snapshotOldText;
|
|
934
1043
|
if (isFileMutation) {
|
|
@@ -979,6 +1088,10 @@ var PiAcpSession = class {
|
|
|
979
1088
|
const toolCallId = String(ev.toolCallId ?? "");
|
|
980
1089
|
if (!toolCallId) break;
|
|
981
1090
|
const partial = ev.partialResult;
|
|
1091
|
+
if (this.bashToolCallIds.has(toolCallId)) {
|
|
1092
|
+
this.emitBashOutputUpdate({ toolCallId, status: "in_progress", result: partial });
|
|
1093
|
+
break;
|
|
1094
|
+
}
|
|
982
1095
|
const text = this.fileMutationToolCallIds.has(toolCallId) ? "" : toolResultToText(partial);
|
|
983
1096
|
this.emit({
|
|
984
1097
|
sessionUpdate: "tool_call_update",
|
|
@@ -994,6 +1107,16 @@ var PiAcpSession = class {
|
|
|
994
1107
|
if (!toolCallId) break;
|
|
995
1108
|
const result = ev.result;
|
|
996
1109
|
const isError = Boolean(ev.isError);
|
|
1110
|
+
if (this.bashToolCallIds.has(toolCallId)) {
|
|
1111
|
+
this.emitBashOutputUpdate({
|
|
1112
|
+
toolCallId,
|
|
1113
|
+
status: isError ? "failed" : "completed",
|
|
1114
|
+
result,
|
|
1115
|
+
isError
|
|
1116
|
+
});
|
|
1117
|
+
this.cleanupToolCall(toolCallId);
|
|
1118
|
+
break;
|
|
1119
|
+
}
|
|
997
1120
|
const text = toolResultToText(result);
|
|
998
1121
|
const snapshot = this.fileSnapshots.get(toolCallId);
|
|
999
1122
|
let content;
|
|
@@ -1026,9 +1149,7 @@ var PiAcpSession = class {
|
|
|
1026
1149
|
content,
|
|
1027
1150
|
...hasStructuredDiff ? {} : { rawOutput: result }
|
|
1028
1151
|
});
|
|
1029
|
-
this.
|
|
1030
|
-
this.fileSnapshots.delete(toolCallId);
|
|
1031
|
-
this.fileMutationToolCallIds.delete(toolCallId);
|
|
1152
|
+
this.cleanupToolCall(toolCallId);
|
|
1032
1153
|
break;
|
|
1033
1154
|
}
|
|
1034
1155
|
case "extension_ui_request": {
|
|
@@ -1137,7 +1258,8 @@ var PiAcpSession = class {
|
|
|
1137
1258
|
if (method === "notify") {
|
|
1138
1259
|
this.emit({
|
|
1139
1260
|
sessionUpdate: "agent_message_chunk",
|
|
1140
|
-
content: { type: "text", text: stringProp(ev, "message") ?? "Pi notification" }
|
|
1261
|
+
content: { type: "text", text: stringProp(ev, "message") ?? "Pi notification" },
|
|
1262
|
+
_meta: { piAcp: { notify: { level: stringProp(ev, "notifyType") ?? "info" } } }
|
|
1141
1263
|
});
|
|
1142
1264
|
await this.proc.sendExtensionUiResponse({ id, cancelled: true });
|
|
1143
1265
|
return;
|
|
@@ -1238,7 +1360,7 @@ function toToolKind(toolName) {
|
|
|
1238
1360
|
case "edit":
|
|
1239
1361
|
return "edit";
|
|
1240
1362
|
case "bash":
|
|
1241
|
-
return "
|
|
1363
|
+
return "execute";
|
|
1242
1364
|
default:
|
|
1243
1365
|
return "other";
|
|
1244
1366
|
}
|
|
@@ -1815,7 +1937,8 @@ var PiAcpAgent = class {
|
|
|
1815
1937
|
sessionCapabilities: {
|
|
1816
1938
|
// **UNSTABLE** ACP capability used by Zed's codex-acp adapter.
|
|
1817
1939
|
// Enables a native session picker in clients that support it.
|
|
1818
|
-
list: {}
|
|
1940
|
+
list: {},
|
|
1941
|
+
delete: {}
|
|
1819
1942
|
}
|
|
1820
1943
|
}
|
|
1821
1944
|
};
|
|
@@ -2384,6 +2507,35 @@ ${JSON.stringify(stats, null, 2)}`;
|
|
|
2384
2507
|
const toolName = String(m?.toolName ?? "tool");
|
|
2385
2508
|
const toolCallId = String(m?.toolCallId ?? crypto.randomUUID());
|
|
2386
2509
|
const isError = Boolean(m?.isError);
|
|
2510
|
+
const isBash = isBashTool(toolName);
|
|
2511
|
+
if (isBash) {
|
|
2512
|
+
const text2 = bashResultText(m);
|
|
2513
|
+
await this.conn.sessionUpdate({
|
|
2514
|
+
sessionId: session.sessionId,
|
|
2515
|
+
update: {
|
|
2516
|
+
sessionUpdate: "tool_call",
|
|
2517
|
+
toolCallId,
|
|
2518
|
+
title: bashCommand(m) ?? toolName,
|
|
2519
|
+
kind: "execute",
|
|
2520
|
+
status: "completed",
|
|
2521
|
+
content: bashTerminalContent(toolCallId),
|
|
2522
|
+
_meta: bashTerminalInfoMeta(toolCallId, params.cwd)
|
|
2523
|
+
}
|
|
2524
|
+
});
|
|
2525
|
+
await this.conn.sessionUpdate({
|
|
2526
|
+
sessionId: session.sessionId,
|
|
2527
|
+
update: {
|
|
2528
|
+
sessionUpdate: "tool_call_update",
|
|
2529
|
+
toolCallId,
|
|
2530
|
+
status: isError ? "failed" : "completed",
|
|
2531
|
+
_meta: {
|
|
2532
|
+
...text2 ? bashTerminalOutputMeta(toolCallId, text2) : {},
|
|
2533
|
+
...bashTerminalExitMeta(toolCallId, bashExitCode(m, isError))
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2536
|
+
});
|
|
2537
|
+
continue;
|
|
2538
|
+
}
|
|
2387
2539
|
await this.conn.sessionUpdate({
|
|
2388
2540
|
sessionId: session.sessionId,
|
|
2389
2541
|
update: {
|
|
@@ -2449,6 +2601,22 @@ ${JSON.stringify(stats, null, 2)}`;
|
|
|
2449
2601
|
}, 0);
|
|
2450
2602
|
return response;
|
|
2451
2603
|
}
|
|
2604
|
+
async deleteSession(params) {
|
|
2605
|
+
const stored = this.store.get(params.sessionId);
|
|
2606
|
+
const piSession = findPiSession(params.sessionId);
|
|
2607
|
+
if (!stored && !piSession) {
|
|
2608
|
+
return {};
|
|
2609
|
+
}
|
|
2610
|
+
const sessionFile = stored?.sessionFile ?? piSession?.sessionFile;
|
|
2611
|
+
if (sessionFile) {
|
|
2612
|
+
try {
|
|
2613
|
+
if (existsSync4(sessionFile)) unlinkSync(sessionFile);
|
|
2614
|
+
} catch {
|
|
2615
|
+
}
|
|
2616
|
+
}
|
|
2617
|
+
this.store.delete(params.sessionId);
|
|
2618
|
+
return {};
|
|
2619
|
+
}
|
|
2452
2620
|
async unstable_setSessionModel(params) {
|
|
2453
2621
|
const session = await this.restoreSession(params.sessionId);
|
|
2454
2622
|
await setSessionModel(session.proc, params.modelId);
|
|
@@ -2764,20 +2932,22 @@ function buildStartupInfo(opts) {
|
|
|
2764
2932
|
for (const f of exts) extItems.push(join5(extDir, f));
|
|
2765
2933
|
} catch {
|
|
2766
2934
|
}
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
const
|
|
2773
|
-
|
|
2774
|
-
|
|
2935
|
+
const settingsPaths = [join5(getAgentDir(), "settings.json"), join5(opts.cwd, ".pi", "settings.json")];
|
|
2936
|
+
for (const settingsPath of settingsPaths) {
|
|
2937
|
+
try {
|
|
2938
|
+
const settings = JSON.parse(readFileSync6(settingsPath, "utf-8"));
|
|
2939
|
+
const pkgs = Array.isArray(settings?.packages) ? settings.packages : [];
|
|
2940
|
+
for (const pkg2 of pkgs) {
|
|
2941
|
+
const s = String(pkg2);
|
|
2942
|
+
if (s.startsWith("npm:")) {
|
|
2943
|
+
extItems.push(`${s}
|
|
2775
2944
|
- index.ts`);
|
|
2776
|
-
|
|
2777
|
-
|
|
2945
|
+
} else {
|
|
2946
|
+
extItems.push(s);
|
|
2947
|
+
}
|
|
2778
2948
|
}
|
|
2949
|
+
} catch {
|
|
2779
2950
|
}
|
|
2780
|
-
} catch {
|
|
2781
2951
|
}
|
|
2782
2952
|
addSection("Extensions", extItems);
|
|
2783
2953
|
if (opts.updateNotice) {
|