@hopgoldy/agent-bridge 0.2.1 → 0.3.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.
- package/README.md +2 -0
- package/dist/agent-bridge.js +186 -20
- package/dist/cli.js +186 -20
- package/dist/index.d.ts +16 -10
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/agent-bridge.js
CHANGED
|
@@ -409,6 +409,8 @@ var GatewayCore = class {
|
|
|
409
409
|
agentSessionId,
|
|
410
410
|
clientSessionId,
|
|
411
411
|
toolName: "toolName" in event ? event.toolName : void 0,
|
|
412
|
+
toolCallId: "toolCallId" in event ? event.toolCallId : void 0,
|
|
413
|
+
toolLabel: "toolLabel" in event ? event.toolLabel : void 0,
|
|
412
414
|
text: event.text
|
|
413
415
|
});
|
|
414
416
|
}
|
|
@@ -427,7 +429,7 @@ var GatewayCore = class {
|
|
|
427
429
|
});
|
|
428
430
|
}
|
|
429
431
|
#isToolRelatedEvent(event) {
|
|
430
|
-
return event.type === "assistant.tool.running" || event.type === "assistant.tool.done" || event.type === "assistant.tool.error" || event.type === "session.compacting";
|
|
432
|
+
return event.type === "assistant.tool.running" || event.type === "assistant.tool.update" || event.type === "assistant.tool.done" || event.type === "assistant.tool.error" || event.type === "session.compacting";
|
|
431
433
|
}
|
|
432
434
|
#touchRuntime(runtime) {
|
|
433
435
|
runtime.lastActiveAt = Date.now();
|
|
@@ -906,6 +908,8 @@ var PiCodingAgentAdapter = class {
|
|
|
906
908
|
#onOutput = null;
|
|
907
909
|
#inputQueue = [];
|
|
908
910
|
#processing = false;
|
|
911
|
+
#toolLabelByCallId = /* @__PURE__ */ new Map();
|
|
912
|
+
#toolInputByCallId = /* @__PURE__ */ new Map();
|
|
909
913
|
constructor({
|
|
910
914
|
agentSessionId,
|
|
911
915
|
cwd,
|
|
@@ -948,6 +952,8 @@ var PiCodingAgentAdapter = class {
|
|
|
948
952
|
}
|
|
949
953
|
async stop() {
|
|
950
954
|
this.#inputQueue.length = 0;
|
|
955
|
+
this.#toolLabelByCallId.clear();
|
|
956
|
+
this.#toolInputByCallId.clear();
|
|
951
957
|
await this.#client?.stop();
|
|
952
958
|
this.#client = null;
|
|
953
959
|
this.#processing = false;
|
|
@@ -1068,25 +1074,128 @@ var PiCodingAgentAdapter = class {
|
|
|
1068
1074
|
}
|
|
1069
1075
|
if (rpcEvent.type === "tool_execution_start") {
|
|
1070
1076
|
const toolName = typeof rpcEvent.toolName === "string" ? rpcEvent.toolName : "unknown";
|
|
1077
|
+
const toolCallId = typeof rpcEvent.toolCallId === "string" ? rpcEvent.toolCallId : void 0;
|
|
1078
|
+
const toolInput = "args" in rpcEvent ? rpcEvent.args : void 0;
|
|
1079
|
+
const toolLabel = this.#summarizeToolLabel(toolName, toolInput);
|
|
1080
|
+
if (toolCallId) {
|
|
1081
|
+
if (toolLabel) this.#toolLabelByCallId.set(toolCallId, toolLabel);
|
|
1082
|
+
if (toolInput !== void 0) this.#toolInputByCallId.set(toolCallId, toolInput);
|
|
1083
|
+
}
|
|
1071
1084
|
await this.#emitProgress({
|
|
1072
1085
|
type: "assistant.tool.running",
|
|
1073
1086
|
agentSessionId: this.#agentSessionId,
|
|
1074
1087
|
toolName,
|
|
1088
|
+
toolCallId,
|
|
1089
|
+
toolInput,
|
|
1090
|
+
toolLabel,
|
|
1091
|
+
text: `Running ${toolName}`
|
|
1092
|
+
});
|
|
1093
|
+
return;
|
|
1094
|
+
}
|
|
1095
|
+
if (rpcEvent.type === "tool_execution_update") {
|
|
1096
|
+
const toolName = typeof rpcEvent.toolName === "string" ? rpcEvent.toolName : "unknown";
|
|
1097
|
+
const toolCallId = typeof rpcEvent.toolCallId === "string" ? rpcEvent.toolCallId : void 0;
|
|
1098
|
+
const toolInput = "args" in rpcEvent ? rpcEvent.args : this.#toolInputForCall(toolCallId);
|
|
1099
|
+
const toolLabel = this.#toolLabelForCall(toolCallId, toolName, toolInput);
|
|
1100
|
+
if (toolCallId) {
|
|
1101
|
+
if (toolLabel) this.#toolLabelByCallId.set(toolCallId, toolLabel);
|
|
1102
|
+
if (toolInput !== void 0) this.#toolInputByCallId.set(toolCallId, toolInput);
|
|
1103
|
+
}
|
|
1104
|
+
await this.#emitProgress({
|
|
1105
|
+
type: "assistant.tool.update",
|
|
1106
|
+
agentSessionId: this.#agentSessionId,
|
|
1107
|
+
toolName,
|
|
1108
|
+
toolCallId,
|
|
1109
|
+
toolInput,
|
|
1110
|
+
toolLabel,
|
|
1111
|
+
partialResult: "partialResult" in rpcEvent ? rpcEvent.partialResult : void 0,
|
|
1075
1112
|
text: `Running ${toolName}`
|
|
1076
1113
|
});
|
|
1077
1114
|
return;
|
|
1078
1115
|
}
|
|
1079
1116
|
if (rpcEvent.type === "tool_execution_end") {
|
|
1080
1117
|
const toolName = typeof rpcEvent.toolName === "string" ? rpcEvent.toolName : "unknown";
|
|
1118
|
+
const toolCallId = typeof rpcEvent.toolCallId === "string" ? rpcEvent.toolCallId : void 0;
|
|
1081
1119
|
const isError = Boolean(rpcEvent.isError);
|
|
1120
|
+
const toolInput = this.#toolInputForCall(toolCallId);
|
|
1121
|
+
const toolLabel = this.#toolLabelForCall(toolCallId, toolName, toolInput);
|
|
1082
1122
|
await this.#emitProgress({
|
|
1083
1123
|
type: isError ? "assistant.tool.error" : "assistant.tool.done",
|
|
1084
1124
|
agentSessionId: this.#agentSessionId,
|
|
1085
1125
|
toolName,
|
|
1126
|
+
toolCallId,
|
|
1127
|
+
toolInput,
|
|
1128
|
+
toolLabel,
|
|
1129
|
+
result: "result" in rpcEvent ? rpcEvent.result : void 0,
|
|
1086
1130
|
text: isError ? `Failed ${toolName}` : `Finished ${toolName}`
|
|
1087
1131
|
});
|
|
1132
|
+
if (toolCallId) {
|
|
1133
|
+
this.#toolLabelByCallId.delete(toolCallId);
|
|
1134
|
+
this.#toolInputByCallId.delete(toolCallId);
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
#toolInputForCall(toolCallId) {
|
|
1139
|
+
return toolCallId ? this.#toolInputByCallId.get(toolCallId) : void 0;
|
|
1140
|
+
}
|
|
1141
|
+
#toolLabelForCall(toolCallId, toolName, toolInput) {
|
|
1142
|
+
return (toolCallId ? this.#toolLabelByCallId.get(toolCallId) : void 0) ?? this.#summarizeToolLabel(toolName, toolInput);
|
|
1143
|
+
}
|
|
1144
|
+
#summarizeToolLabel(toolName, toolInput) {
|
|
1145
|
+
if (!toolInput || typeof toolInput !== "object" || Array.isArray(toolInput)) {
|
|
1146
|
+
return void 0;
|
|
1147
|
+
}
|
|
1148
|
+
const input = toolInput;
|
|
1149
|
+
const stringField = (key) => {
|
|
1150
|
+
const value = input[key];
|
|
1151
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
1152
|
+
};
|
|
1153
|
+
const stringArrayField = (key) => {
|
|
1154
|
+
const value = input[key];
|
|
1155
|
+
if (!Array.isArray(value)) return void 0;
|
|
1156
|
+
const items = value.filter((item) => typeof item === "string" && item.trim().length > 0);
|
|
1157
|
+
return items.length > 0 ? items.map((item) => item.trim()) : void 0;
|
|
1158
|
+
};
|
|
1159
|
+
switch (toolName) {
|
|
1160
|
+
case "bash":
|
|
1161
|
+
return stringField("command");
|
|
1162
|
+
case "read":
|
|
1163
|
+
case "write":
|
|
1164
|
+
case "edit":
|
|
1165
|
+
case "find":
|
|
1166
|
+
case "ls":
|
|
1167
|
+
return stringField("path");
|
|
1168
|
+
case "grep": {
|
|
1169
|
+
const pattern = stringField("pattern");
|
|
1170
|
+
const path7 = stringField("path");
|
|
1171
|
+
if (pattern && path7) return `${pattern} in ${path7}`;
|
|
1172
|
+
return pattern ?? path7;
|
|
1173
|
+
}
|
|
1174
|
+
case "web_search": {
|
|
1175
|
+
const query = stringField("query");
|
|
1176
|
+
const queries = stringArrayField("queries");
|
|
1177
|
+
return query ?? (queries ? queries.join(" | ") : void 0);
|
|
1178
|
+
}
|
|
1179
|
+
case "fetch_content": {
|
|
1180
|
+
const url = stringField("url");
|
|
1181
|
+
const urls = stringArrayField("urls");
|
|
1182
|
+
return url ?? (urls ? urls.join(" | ") : void 0);
|
|
1183
|
+
}
|
|
1184
|
+
default:
|
|
1185
|
+
return this.#truncate(this.#safeJson(toolInput), 120);
|
|
1088
1186
|
}
|
|
1089
1187
|
}
|
|
1188
|
+
#safeJson(value) {
|
|
1189
|
+
try {
|
|
1190
|
+
return JSON.stringify(value);
|
|
1191
|
+
} catch {
|
|
1192
|
+
return void 0;
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
#truncate(value, maxLength) {
|
|
1196
|
+
if (!value) return void 0;
|
|
1197
|
+
return value.length > maxLength ? `${value.slice(0, maxLength - 1)}\u2026` : value;
|
|
1198
|
+
}
|
|
1090
1199
|
#isAssistantMessage(value) {
|
|
1091
1200
|
if (!value || typeof value !== "object") {
|
|
1092
1201
|
return false;
|
|
@@ -1215,12 +1324,13 @@ function getTypedAgentModule(config) {
|
|
|
1215
1324
|
|
|
1216
1325
|
// src/modules/client/utils/progress-renderer.ts
|
|
1217
1326
|
var DEFAULT_COLLAPSE_THRESHOLD = 10;
|
|
1327
|
+
var MAX_TOOL_LABEL_DISPLAY_LENGTH = 15;
|
|
1218
1328
|
var NO_PROGRESS_MARKDOWN = "No progress yet.";
|
|
1219
1329
|
var ProgressRenderer = class {
|
|
1220
1330
|
#collapseThreshold;
|
|
1221
|
-
#
|
|
1331
|
+
#entries = /* @__PURE__ */ new Map();
|
|
1332
|
+
#order = [];
|
|
1222
1333
|
#status = "running";
|
|
1223
|
-
#collapsedCount = 0;
|
|
1224
1334
|
constructor(options = {}) {
|
|
1225
1335
|
this.#collapseThreshold = options.collapseThreshold ?? DEFAULT_COLLAPSE_THRESHOLD;
|
|
1226
1336
|
}
|
|
@@ -1230,43 +1340,97 @@ var ProgressRenderer = class {
|
|
|
1230
1340
|
}
|
|
1231
1341
|
/** Records a progress event, formatting it into a line and collapsing older lines if needed. */
|
|
1232
1342
|
takeProgressEvent(event) {
|
|
1233
|
-
this.#
|
|
1234
|
-
if (
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
this.#
|
|
1343
|
+
const toolEntryId = this.#toolEntryId(event);
|
|
1344
|
+
if (toolEntryId) {
|
|
1345
|
+
this.#upsertToolEntry(toolEntryId, event);
|
|
1346
|
+
} else {
|
|
1347
|
+
this.#appendLineEntry(this.#formatProgressLine(event));
|
|
1238
1348
|
}
|
|
1239
1349
|
this.#status = this.#progressStatus(event);
|
|
1240
1350
|
}
|
|
1241
1351
|
/** Returns the current rendered markdown, status, and collapsed-line count. */
|
|
1242
1352
|
getCurrentProgress() {
|
|
1353
|
+
const collapsedCount = Math.max(0, this.#order.length - this.#collapseThreshold);
|
|
1243
1354
|
return {
|
|
1244
|
-
markdown: this.#renderMarkdown(),
|
|
1355
|
+
markdown: this.#renderMarkdown(collapsedCount),
|
|
1245
1356
|
status: this.#status,
|
|
1246
|
-
collapsedCount
|
|
1357
|
+
collapsedCount
|
|
1247
1358
|
};
|
|
1248
1359
|
}
|
|
1249
|
-
#renderMarkdown() {
|
|
1360
|
+
#renderMarkdown(collapsedCount) {
|
|
1250
1361
|
const contentLines = [];
|
|
1251
|
-
if (
|
|
1252
|
-
contentLines.push(`- Collapsed ${
|
|
1362
|
+
if (collapsedCount > 0) {
|
|
1363
|
+
contentLines.push(`- Collapsed ${collapsedCount} earlier updates.`);
|
|
1253
1364
|
}
|
|
1254
|
-
|
|
1255
|
-
|
|
1365
|
+
for (const id of this.#visibleOrder()) {
|
|
1366
|
+
const entry = this.#entries.get(id);
|
|
1367
|
+
if (!entry) continue;
|
|
1368
|
+
contentLines.push(entry.kind === "line" ? entry.line : this.#formatToolEntry(entry));
|
|
1256
1369
|
}
|
|
1257
1370
|
return contentLines.length > 0 ? contentLines.join("\n") : NO_PROGRESS_MARKDOWN;
|
|
1258
1371
|
}
|
|
1372
|
+
#visibleOrder() {
|
|
1373
|
+
return this.#order.slice(-this.#collapseThreshold);
|
|
1374
|
+
}
|
|
1375
|
+
#appendLineEntry(line) {
|
|
1376
|
+
const id = `line:${this.#order.length}`;
|
|
1377
|
+
this.#entries.set(id, { kind: "line", line });
|
|
1378
|
+
this.#order.push(id);
|
|
1379
|
+
}
|
|
1380
|
+
#upsertToolEntry(id, event) {
|
|
1381
|
+
if (!this.#entries.has(id)) {
|
|
1382
|
+
this.#order.push(id);
|
|
1383
|
+
} else {
|
|
1384
|
+
this.#order = this.#order.filter((entryId) => entryId !== id);
|
|
1385
|
+
this.#order.push(id);
|
|
1386
|
+
}
|
|
1387
|
+
this.#entries.set(id, {
|
|
1388
|
+
kind: "tool",
|
|
1389
|
+
toolName: event.toolName,
|
|
1390
|
+
toolLabel: event.toolLabel,
|
|
1391
|
+
status: event.type === "assistant.tool.error" ? "error" : event.type === "assistant.tool.done" ? "done" : "running",
|
|
1392
|
+
text: event.text
|
|
1393
|
+
});
|
|
1394
|
+
}
|
|
1395
|
+
#toolEntryId(event) {
|
|
1396
|
+
if (event.type === "assistant.tool.running" || event.type === "assistant.tool.update" || event.type === "assistant.tool.done" || event.type === "assistant.tool.error") {
|
|
1397
|
+
return event.toolCallId ? `tool:${event.toolCallId}` : null;
|
|
1398
|
+
}
|
|
1399
|
+
return null;
|
|
1400
|
+
}
|
|
1401
|
+
#formatToolEntry(entry) {
|
|
1402
|
+
const subject = this.#formatToolSubject(entry.toolName, entry.toolLabel);
|
|
1403
|
+
switch (entry.status) {
|
|
1404
|
+
case "running":
|
|
1405
|
+
return `- Running ${subject}`;
|
|
1406
|
+
case "done":
|
|
1407
|
+
return `- Finished ${subject}`;
|
|
1408
|
+
case "error":
|
|
1409
|
+
return this.#formatToolErrorLine(subject, entry.text);
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1259
1412
|
#formatProgressLine(event) {
|
|
1260
1413
|
switch (event.type) {
|
|
1261
1414
|
case "session.compacting":
|
|
1262
1415
|
return `- Compacting session${event.text ? `: ${event.text}` : ""}`;
|
|
1263
1416
|
case "assistant.tool.running":
|
|
1264
|
-
|
|
1417
|
+
case "assistant.tool.update":
|
|
1418
|
+
return `- Running ${this.#formatToolSubject(event.toolName, event.toolLabel)}`;
|
|
1265
1419
|
case "assistant.tool.done":
|
|
1266
|
-
return `- Finished ${event.toolName}`;
|
|
1420
|
+
return `- Finished ${this.#formatToolSubject(event.toolName, event.toolLabel)}`;
|
|
1267
1421
|
case "assistant.tool.error":
|
|
1268
|
-
return this.#formatToolErrorLine(event.toolName, event.text);
|
|
1422
|
+
return this.#formatToolErrorLine(this.#formatToolSubject(event.toolName, event.toolLabel), event.text);
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
#formatToolSubject(toolName, toolLabel) {
|
|
1426
|
+
const normalizedLabel = toolLabel?.trim();
|
|
1427
|
+
if (!normalizedLabel) {
|
|
1428
|
+
return toolName;
|
|
1269
1429
|
}
|
|
1430
|
+
return `${toolName}: ${this.#truncateToolLabel(normalizedLabel)}`;
|
|
1431
|
+
}
|
|
1432
|
+
#truncateToolLabel(toolLabel) {
|
|
1433
|
+
return toolLabel.length > MAX_TOOL_LABEL_DISPLAY_LENGTH ? `${toolLabel.slice(0, MAX_TOOL_LABEL_DISPLAY_LENGTH)}\u2026` : toolLabel;
|
|
1270
1434
|
}
|
|
1271
1435
|
#formatToolErrorLine(toolName, text2) {
|
|
1272
1436
|
const normalizedText = text2?.trim();
|
|
@@ -1275,7 +1439,7 @@ var ProgressRenderer = class {
|
|
|
1275
1439
|
}
|
|
1276
1440
|
const lowerText = normalizedText.toLowerCase();
|
|
1277
1441
|
const lowerToolName = toolName.toLowerCase();
|
|
1278
|
-
if (lowerText === lowerToolName || lowerText === `failed ${lowerToolName}`) {
|
|
1442
|
+
if (lowerText === lowerToolName || lowerText === `failed ${lowerToolName}` || lowerText === `running ${lowerToolName}` || lowerText === `finished ${lowerToolName}`) {
|
|
1279
1443
|
return `- ${this.#humanizeToolError(toolName)}`;
|
|
1280
1444
|
}
|
|
1281
1445
|
return `- ${this.#humanizeToolError(toolName)}: ${normalizedText}`;
|
|
@@ -1297,10 +1461,12 @@ var ProgressRenderer = class {
|
|
|
1297
1461
|
|
|
1298
1462
|
// src/modules/client/utils/slash-commands.ts
|
|
1299
1463
|
function parseSlashCommand(text2, clientSessionId) {
|
|
1300
|
-
switch (text2) {
|
|
1464
|
+
switch (text2.toLowerCase()) {
|
|
1301
1465
|
case "/new":
|
|
1466
|
+
case "/n":
|
|
1302
1467
|
return { type: "command.session.new", clientSessionId };
|
|
1303
1468
|
case "/compact":
|
|
1469
|
+
case "/c":
|
|
1304
1470
|
return { type: "command.session.compact", clientSessionId };
|
|
1305
1471
|
case "/stop":
|
|
1306
1472
|
return { type: "command.session.stop", clientSessionId };
|
package/dist/cli.js
CHANGED
|
@@ -409,6 +409,8 @@ var GatewayCore = class {
|
|
|
409
409
|
agentSessionId,
|
|
410
410
|
clientSessionId,
|
|
411
411
|
toolName: "toolName" in event ? event.toolName : void 0,
|
|
412
|
+
toolCallId: "toolCallId" in event ? event.toolCallId : void 0,
|
|
413
|
+
toolLabel: "toolLabel" in event ? event.toolLabel : void 0,
|
|
412
414
|
text: event.text
|
|
413
415
|
});
|
|
414
416
|
}
|
|
@@ -427,7 +429,7 @@ var GatewayCore = class {
|
|
|
427
429
|
});
|
|
428
430
|
}
|
|
429
431
|
#isToolRelatedEvent(event) {
|
|
430
|
-
return event.type === "assistant.tool.running" || event.type === "assistant.tool.done" || event.type === "assistant.tool.error" || event.type === "session.compacting";
|
|
432
|
+
return event.type === "assistant.tool.running" || event.type === "assistant.tool.update" || event.type === "assistant.tool.done" || event.type === "assistant.tool.error" || event.type === "session.compacting";
|
|
431
433
|
}
|
|
432
434
|
#touchRuntime(runtime) {
|
|
433
435
|
runtime.lastActiveAt = Date.now();
|
|
@@ -906,6 +908,8 @@ var PiCodingAgentAdapter = class {
|
|
|
906
908
|
#onOutput = null;
|
|
907
909
|
#inputQueue = [];
|
|
908
910
|
#processing = false;
|
|
911
|
+
#toolLabelByCallId = /* @__PURE__ */ new Map();
|
|
912
|
+
#toolInputByCallId = /* @__PURE__ */ new Map();
|
|
909
913
|
constructor({
|
|
910
914
|
agentSessionId,
|
|
911
915
|
cwd,
|
|
@@ -948,6 +952,8 @@ var PiCodingAgentAdapter = class {
|
|
|
948
952
|
}
|
|
949
953
|
async stop() {
|
|
950
954
|
this.#inputQueue.length = 0;
|
|
955
|
+
this.#toolLabelByCallId.clear();
|
|
956
|
+
this.#toolInputByCallId.clear();
|
|
951
957
|
await this.#client?.stop();
|
|
952
958
|
this.#client = null;
|
|
953
959
|
this.#processing = false;
|
|
@@ -1068,25 +1074,128 @@ var PiCodingAgentAdapter = class {
|
|
|
1068
1074
|
}
|
|
1069
1075
|
if (rpcEvent.type === "tool_execution_start") {
|
|
1070
1076
|
const toolName = typeof rpcEvent.toolName === "string" ? rpcEvent.toolName : "unknown";
|
|
1077
|
+
const toolCallId = typeof rpcEvent.toolCallId === "string" ? rpcEvent.toolCallId : void 0;
|
|
1078
|
+
const toolInput = "args" in rpcEvent ? rpcEvent.args : void 0;
|
|
1079
|
+
const toolLabel = this.#summarizeToolLabel(toolName, toolInput);
|
|
1080
|
+
if (toolCallId) {
|
|
1081
|
+
if (toolLabel) this.#toolLabelByCallId.set(toolCallId, toolLabel);
|
|
1082
|
+
if (toolInput !== void 0) this.#toolInputByCallId.set(toolCallId, toolInput);
|
|
1083
|
+
}
|
|
1071
1084
|
await this.#emitProgress({
|
|
1072
1085
|
type: "assistant.tool.running",
|
|
1073
1086
|
agentSessionId: this.#agentSessionId,
|
|
1074
1087
|
toolName,
|
|
1088
|
+
toolCallId,
|
|
1089
|
+
toolInput,
|
|
1090
|
+
toolLabel,
|
|
1091
|
+
text: `Running ${toolName}`
|
|
1092
|
+
});
|
|
1093
|
+
return;
|
|
1094
|
+
}
|
|
1095
|
+
if (rpcEvent.type === "tool_execution_update") {
|
|
1096
|
+
const toolName = typeof rpcEvent.toolName === "string" ? rpcEvent.toolName : "unknown";
|
|
1097
|
+
const toolCallId = typeof rpcEvent.toolCallId === "string" ? rpcEvent.toolCallId : void 0;
|
|
1098
|
+
const toolInput = "args" in rpcEvent ? rpcEvent.args : this.#toolInputForCall(toolCallId);
|
|
1099
|
+
const toolLabel = this.#toolLabelForCall(toolCallId, toolName, toolInput);
|
|
1100
|
+
if (toolCallId) {
|
|
1101
|
+
if (toolLabel) this.#toolLabelByCallId.set(toolCallId, toolLabel);
|
|
1102
|
+
if (toolInput !== void 0) this.#toolInputByCallId.set(toolCallId, toolInput);
|
|
1103
|
+
}
|
|
1104
|
+
await this.#emitProgress({
|
|
1105
|
+
type: "assistant.tool.update",
|
|
1106
|
+
agentSessionId: this.#agentSessionId,
|
|
1107
|
+
toolName,
|
|
1108
|
+
toolCallId,
|
|
1109
|
+
toolInput,
|
|
1110
|
+
toolLabel,
|
|
1111
|
+
partialResult: "partialResult" in rpcEvent ? rpcEvent.partialResult : void 0,
|
|
1075
1112
|
text: `Running ${toolName}`
|
|
1076
1113
|
});
|
|
1077
1114
|
return;
|
|
1078
1115
|
}
|
|
1079
1116
|
if (rpcEvent.type === "tool_execution_end") {
|
|
1080
1117
|
const toolName = typeof rpcEvent.toolName === "string" ? rpcEvent.toolName : "unknown";
|
|
1118
|
+
const toolCallId = typeof rpcEvent.toolCallId === "string" ? rpcEvent.toolCallId : void 0;
|
|
1081
1119
|
const isError = Boolean(rpcEvent.isError);
|
|
1120
|
+
const toolInput = this.#toolInputForCall(toolCallId);
|
|
1121
|
+
const toolLabel = this.#toolLabelForCall(toolCallId, toolName, toolInput);
|
|
1082
1122
|
await this.#emitProgress({
|
|
1083
1123
|
type: isError ? "assistant.tool.error" : "assistant.tool.done",
|
|
1084
1124
|
agentSessionId: this.#agentSessionId,
|
|
1085
1125
|
toolName,
|
|
1126
|
+
toolCallId,
|
|
1127
|
+
toolInput,
|
|
1128
|
+
toolLabel,
|
|
1129
|
+
result: "result" in rpcEvent ? rpcEvent.result : void 0,
|
|
1086
1130
|
text: isError ? `Failed ${toolName}` : `Finished ${toolName}`
|
|
1087
1131
|
});
|
|
1132
|
+
if (toolCallId) {
|
|
1133
|
+
this.#toolLabelByCallId.delete(toolCallId);
|
|
1134
|
+
this.#toolInputByCallId.delete(toolCallId);
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
#toolInputForCall(toolCallId) {
|
|
1139
|
+
return toolCallId ? this.#toolInputByCallId.get(toolCallId) : void 0;
|
|
1140
|
+
}
|
|
1141
|
+
#toolLabelForCall(toolCallId, toolName, toolInput) {
|
|
1142
|
+
return (toolCallId ? this.#toolLabelByCallId.get(toolCallId) : void 0) ?? this.#summarizeToolLabel(toolName, toolInput);
|
|
1143
|
+
}
|
|
1144
|
+
#summarizeToolLabel(toolName, toolInput) {
|
|
1145
|
+
if (!toolInput || typeof toolInput !== "object" || Array.isArray(toolInput)) {
|
|
1146
|
+
return void 0;
|
|
1147
|
+
}
|
|
1148
|
+
const input = toolInput;
|
|
1149
|
+
const stringField = (key) => {
|
|
1150
|
+
const value = input[key];
|
|
1151
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
1152
|
+
};
|
|
1153
|
+
const stringArrayField = (key) => {
|
|
1154
|
+
const value = input[key];
|
|
1155
|
+
if (!Array.isArray(value)) return void 0;
|
|
1156
|
+
const items = value.filter((item) => typeof item === "string" && item.trim().length > 0);
|
|
1157
|
+
return items.length > 0 ? items.map((item) => item.trim()) : void 0;
|
|
1158
|
+
};
|
|
1159
|
+
switch (toolName) {
|
|
1160
|
+
case "bash":
|
|
1161
|
+
return stringField("command");
|
|
1162
|
+
case "read":
|
|
1163
|
+
case "write":
|
|
1164
|
+
case "edit":
|
|
1165
|
+
case "find":
|
|
1166
|
+
case "ls":
|
|
1167
|
+
return stringField("path");
|
|
1168
|
+
case "grep": {
|
|
1169
|
+
const pattern = stringField("pattern");
|
|
1170
|
+
const path7 = stringField("path");
|
|
1171
|
+
if (pattern && path7) return `${pattern} in ${path7}`;
|
|
1172
|
+
return pattern ?? path7;
|
|
1173
|
+
}
|
|
1174
|
+
case "web_search": {
|
|
1175
|
+
const query = stringField("query");
|
|
1176
|
+
const queries = stringArrayField("queries");
|
|
1177
|
+
return query ?? (queries ? queries.join(" | ") : void 0);
|
|
1178
|
+
}
|
|
1179
|
+
case "fetch_content": {
|
|
1180
|
+
const url = stringField("url");
|
|
1181
|
+
const urls = stringArrayField("urls");
|
|
1182
|
+
return url ?? (urls ? urls.join(" | ") : void 0);
|
|
1183
|
+
}
|
|
1184
|
+
default:
|
|
1185
|
+
return this.#truncate(this.#safeJson(toolInput), 120);
|
|
1088
1186
|
}
|
|
1089
1187
|
}
|
|
1188
|
+
#safeJson(value) {
|
|
1189
|
+
try {
|
|
1190
|
+
return JSON.stringify(value);
|
|
1191
|
+
} catch {
|
|
1192
|
+
return void 0;
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
#truncate(value, maxLength) {
|
|
1196
|
+
if (!value) return void 0;
|
|
1197
|
+
return value.length > maxLength ? `${value.slice(0, maxLength - 1)}\u2026` : value;
|
|
1198
|
+
}
|
|
1090
1199
|
#isAssistantMessage(value) {
|
|
1091
1200
|
if (!value || typeof value !== "object") {
|
|
1092
1201
|
return false;
|
|
@@ -1215,12 +1324,13 @@ function getTypedAgentModule(config) {
|
|
|
1215
1324
|
|
|
1216
1325
|
// src/modules/client/utils/progress-renderer.ts
|
|
1217
1326
|
var DEFAULT_COLLAPSE_THRESHOLD = 10;
|
|
1327
|
+
var MAX_TOOL_LABEL_DISPLAY_LENGTH = 15;
|
|
1218
1328
|
var NO_PROGRESS_MARKDOWN = "No progress yet.";
|
|
1219
1329
|
var ProgressRenderer = class {
|
|
1220
1330
|
#collapseThreshold;
|
|
1221
|
-
#
|
|
1331
|
+
#entries = /* @__PURE__ */ new Map();
|
|
1332
|
+
#order = [];
|
|
1222
1333
|
#status = "running";
|
|
1223
|
-
#collapsedCount = 0;
|
|
1224
1334
|
constructor(options = {}) {
|
|
1225
1335
|
this.#collapseThreshold = options.collapseThreshold ?? DEFAULT_COLLAPSE_THRESHOLD;
|
|
1226
1336
|
}
|
|
@@ -1230,43 +1340,97 @@ var ProgressRenderer = class {
|
|
|
1230
1340
|
}
|
|
1231
1341
|
/** Records a progress event, formatting it into a line and collapsing older lines if needed. */
|
|
1232
1342
|
takeProgressEvent(event) {
|
|
1233
|
-
this.#
|
|
1234
|
-
if (
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
this.#
|
|
1343
|
+
const toolEntryId = this.#toolEntryId(event);
|
|
1344
|
+
if (toolEntryId) {
|
|
1345
|
+
this.#upsertToolEntry(toolEntryId, event);
|
|
1346
|
+
} else {
|
|
1347
|
+
this.#appendLineEntry(this.#formatProgressLine(event));
|
|
1238
1348
|
}
|
|
1239
1349
|
this.#status = this.#progressStatus(event);
|
|
1240
1350
|
}
|
|
1241
1351
|
/** Returns the current rendered markdown, status, and collapsed-line count. */
|
|
1242
1352
|
getCurrentProgress() {
|
|
1353
|
+
const collapsedCount = Math.max(0, this.#order.length - this.#collapseThreshold);
|
|
1243
1354
|
return {
|
|
1244
|
-
markdown: this.#renderMarkdown(),
|
|
1355
|
+
markdown: this.#renderMarkdown(collapsedCount),
|
|
1245
1356
|
status: this.#status,
|
|
1246
|
-
collapsedCount
|
|
1357
|
+
collapsedCount
|
|
1247
1358
|
};
|
|
1248
1359
|
}
|
|
1249
|
-
#renderMarkdown() {
|
|
1360
|
+
#renderMarkdown(collapsedCount) {
|
|
1250
1361
|
const contentLines = [];
|
|
1251
|
-
if (
|
|
1252
|
-
contentLines.push(`- Collapsed ${
|
|
1362
|
+
if (collapsedCount > 0) {
|
|
1363
|
+
contentLines.push(`- Collapsed ${collapsedCount} earlier updates.`);
|
|
1253
1364
|
}
|
|
1254
|
-
|
|
1255
|
-
|
|
1365
|
+
for (const id of this.#visibleOrder()) {
|
|
1366
|
+
const entry = this.#entries.get(id);
|
|
1367
|
+
if (!entry) continue;
|
|
1368
|
+
contentLines.push(entry.kind === "line" ? entry.line : this.#formatToolEntry(entry));
|
|
1256
1369
|
}
|
|
1257
1370
|
return contentLines.length > 0 ? contentLines.join("\n") : NO_PROGRESS_MARKDOWN;
|
|
1258
1371
|
}
|
|
1372
|
+
#visibleOrder() {
|
|
1373
|
+
return this.#order.slice(-this.#collapseThreshold);
|
|
1374
|
+
}
|
|
1375
|
+
#appendLineEntry(line) {
|
|
1376
|
+
const id = `line:${this.#order.length}`;
|
|
1377
|
+
this.#entries.set(id, { kind: "line", line });
|
|
1378
|
+
this.#order.push(id);
|
|
1379
|
+
}
|
|
1380
|
+
#upsertToolEntry(id, event) {
|
|
1381
|
+
if (!this.#entries.has(id)) {
|
|
1382
|
+
this.#order.push(id);
|
|
1383
|
+
} else {
|
|
1384
|
+
this.#order = this.#order.filter((entryId) => entryId !== id);
|
|
1385
|
+
this.#order.push(id);
|
|
1386
|
+
}
|
|
1387
|
+
this.#entries.set(id, {
|
|
1388
|
+
kind: "tool",
|
|
1389
|
+
toolName: event.toolName,
|
|
1390
|
+
toolLabel: event.toolLabel,
|
|
1391
|
+
status: event.type === "assistant.tool.error" ? "error" : event.type === "assistant.tool.done" ? "done" : "running",
|
|
1392
|
+
text: event.text
|
|
1393
|
+
});
|
|
1394
|
+
}
|
|
1395
|
+
#toolEntryId(event) {
|
|
1396
|
+
if (event.type === "assistant.tool.running" || event.type === "assistant.tool.update" || event.type === "assistant.tool.done" || event.type === "assistant.tool.error") {
|
|
1397
|
+
return event.toolCallId ? `tool:${event.toolCallId}` : null;
|
|
1398
|
+
}
|
|
1399
|
+
return null;
|
|
1400
|
+
}
|
|
1401
|
+
#formatToolEntry(entry) {
|
|
1402
|
+
const subject = this.#formatToolSubject(entry.toolName, entry.toolLabel);
|
|
1403
|
+
switch (entry.status) {
|
|
1404
|
+
case "running":
|
|
1405
|
+
return `- Running ${subject}`;
|
|
1406
|
+
case "done":
|
|
1407
|
+
return `- Finished ${subject}`;
|
|
1408
|
+
case "error":
|
|
1409
|
+
return this.#formatToolErrorLine(subject, entry.text);
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1259
1412
|
#formatProgressLine(event) {
|
|
1260
1413
|
switch (event.type) {
|
|
1261
1414
|
case "session.compacting":
|
|
1262
1415
|
return `- Compacting session${event.text ? `: ${event.text}` : ""}`;
|
|
1263
1416
|
case "assistant.tool.running":
|
|
1264
|
-
|
|
1417
|
+
case "assistant.tool.update":
|
|
1418
|
+
return `- Running ${this.#formatToolSubject(event.toolName, event.toolLabel)}`;
|
|
1265
1419
|
case "assistant.tool.done":
|
|
1266
|
-
return `- Finished ${event.toolName}`;
|
|
1420
|
+
return `- Finished ${this.#formatToolSubject(event.toolName, event.toolLabel)}`;
|
|
1267
1421
|
case "assistant.tool.error":
|
|
1268
|
-
return this.#formatToolErrorLine(event.toolName, event.text);
|
|
1422
|
+
return this.#formatToolErrorLine(this.#formatToolSubject(event.toolName, event.toolLabel), event.text);
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
#formatToolSubject(toolName, toolLabel) {
|
|
1426
|
+
const normalizedLabel = toolLabel?.trim();
|
|
1427
|
+
if (!normalizedLabel) {
|
|
1428
|
+
return toolName;
|
|
1269
1429
|
}
|
|
1430
|
+
return `${toolName}: ${this.#truncateToolLabel(normalizedLabel)}`;
|
|
1431
|
+
}
|
|
1432
|
+
#truncateToolLabel(toolLabel) {
|
|
1433
|
+
return toolLabel.length > MAX_TOOL_LABEL_DISPLAY_LENGTH ? `${toolLabel.slice(0, MAX_TOOL_LABEL_DISPLAY_LENGTH)}\u2026` : toolLabel;
|
|
1270
1434
|
}
|
|
1271
1435
|
#formatToolErrorLine(toolName, text2) {
|
|
1272
1436
|
const normalizedText = text2?.trim();
|
|
@@ -1275,7 +1439,7 @@ var ProgressRenderer = class {
|
|
|
1275
1439
|
}
|
|
1276
1440
|
const lowerText = normalizedText.toLowerCase();
|
|
1277
1441
|
const lowerToolName = toolName.toLowerCase();
|
|
1278
|
-
if (lowerText === lowerToolName || lowerText === `failed ${lowerToolName}`) {
|
|
1442
|
+
if (lowerText === lowerToolName || lowerText === `failed ${lowerToolName}` || lowerText === `running ${lowerToolName}` || lowerText === `finished ${lowerToolName}`) {
|
|
1279
1443
|
return `- ${this.#humanizeToolError(toolName)}`;
|
|
1280
1444
|
}
|
|
1281
1445
|
return `- ${this.#humanizeToolError(toolName)}: ${normalizedText}`;
|
|
@@ -1297,10 +1461,12 @@ var ProgressRenderer = class {
|
|
|
1297
1461
|
|
|
1298
1462
|
// src/modules/client/utils/slash-commands.ts
|
|
1299
1463
|
function parseSlashCommand(text2, clientSessionId) {
|
|
1300
|
-
switch (text2) {
|
|
1464
|
+
switch (text2.toLowerCase()) {
|
|
1301
1465
|
case "/new":
|
|
1466
|
+
case "/n":
|
|
1302
1467
|
return { type: "command.session.new", clientSessionId };
|
|
1303
1468
|
case "/compact":
|
|
1469
|
+
case "/c":
|
|
1304
1470
|
return { type: "command.session.compact", clientSessionId };
|
|
1305
1471
|
case "/stop":
|
|
1306
1472
|
return { type: "command.session.stop", clientSessionId };
|
package/dist/index.d.ts
CHANGED
|
@@ -24,6 +24,13 @@ interface OutboundAttachment {
|
|
|
24
24
|
fileName?: string;
|
|
25
25
|
caption?: string;
|
|
26
26
|
}
|
|
27
|
+
type ToolProgressPayload = {
|
|
28
|
+
toolName: string;
|
|
29
|
+
toolCallId?: string;
|
|
30
|
+
toolInput?: unknown;
|
|
31
|
+
toolLabel?: string;
|
|
32
|
+
text?: string;
|
|
33
|
+
};
|
|
27
34
|
type AgentOutputPayload = {
|
|
28
35
|
type: "assistant.message";
|
|
29
36
|
text: string;
|
|
@@ -31,19 +38,18 @@ type AgentOutputPayload = {
|
|
|
31
38
|
} | {
|
|
32
39
|
type: "assistant.thinking";
|
|
33
40
|
text?: string;
|
|
34
|
-
} | {
|
|
41
|
+
} | ({
|
|
35
42
|
type: "assistant.tool.running";
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
43
|
+
} & ToolProgressPayload) | ({
|
|
44
|
+
type: "assistant.tool.update";
|
|
45
|
+
partialResult?: unknown;
|
|
46
|
+
} & ToolProgressPayload) | ({
|
|
39
47
|
type: "assistant.tool.done";
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
} | {
|
|
48
|
+
result?: unknown;
|
|
49
|
+
} & ToolProgressPayload) | ({
|
|
43
50
|
type: "assistant.tool.error";
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
} | {
|
|
51
|
+
result?: unknown;
|
|
52
|
+
} & ToolProgressPayload) | {
|
|
47
53
|
type: "session.compacting";
|
|
48
54
|
text?: string;
|
|
49
55
|
};
|