@trim21/personal-pi-extensions 0.0.330 → 0.0.332

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trim21/personal-pi-extensions",
3
- "version": "0.0.330",
3
+ "version": "0.0.332",
4
4
  "type": "module",
5
5
  "description": "Custom pi coding-agent extensions: bwrap sandbox, workspace guard, opencode edit, and more",
6
6
  "keywords": [
package/src/aft/index.ts CHANGED
@@ -1,14 +1,12 @@
1
1
  /**
2
2
  * AFT 扩展入口:感知工具(aft_outline / aft_zoom / aft_callgraph / aft_search)
3
- * + ast_edit(符号级编辑,套用本仓库写保护机制)+ aft_refactor / aft_import
4
- * (workspace-wide 重构与 import 管理,路径级写保护)。
3
+ * + aft_refactor / aft_import(workspace-wide 重构与 import 管理,路径级写保护)。
5
4
  *
6
5
  * 感知工具只读,不触碰本仓库自己的 read/write/edit/bash 工具及其安全机制
7
6
  * (bwrap 沙箱、write-guard、reads 记账)。aft_search 仅当用户级
8
7
  * aft.jsonc 开启 semantic_search 时注册(本地语义索引需 ONNX 运行时,
9
- * 内网默认关闭)。ast_edit 是写工具:用 AFTpreview 计算 diff,落盘走
10
- * 本仓库的 write-guard + reads 记账 + 写管线。aft_refactor / aft_import 的
11
- * Rust 命令不支持 preview,写保护退化为路径级审批。
8
+ * 内网默认关闭)。aft_refactor / aft_importRust 命令不支持 preview,
9
+ * 写保护退化为路径级审批。
12
10
  *
13
11
  * 二进制缺失或 pool 创建失败时降级:不注册任何工具并在 session 开始时报
14
12
  * 一次错,而不是让每个工具调用失败。
@@ -20,7 +18,6 @@
20
18
  import { resolveCortexKitConfigPaths } from "@cortexkit/aft-bridge";
21
19
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
22
20
 
23
- import { registerAstEditTool } from "./ast-edit.js";
24
21
  import { type AftPool, createAftPool, shutdownAftPool } from "./bridge.js";
25
22
  import { loadAftConfig } from "./config.js";
26
23
  import { registerImportTool } from "./imports.js";
@@ -55,7 +52,6 @@ export default async function aftReadTools(pi: ExtensionAPI): Promise<void> {
55
52
  registerOutlineTool(pi, toolCtx);
56
53
  registerZoomTool(pi, toolCtx);
57
54
  registerCallgraphTool(pi, toolCtx);
58
- registerAstEditTool(pi, toolCtx);
59
55
  registerRefactorTool(pi, toolCtx);
60
56
  registerImportTool(pi, toolCtx);
61
57
  if (cfg.semanticSearch) {
@@ -305,6 +305,25 @@ function toToolResult(
305
305
  };
306
306
  }
307
307
 
308
+ /**
309
+ * Pendant subtitle for a tool result: `repo=x/y` (when provided) plus the
310
+ * tool's id parameter, e.g. `repo=x/y number=123`. Returns undefined when
311
+ * neither is available, so the pendant is omitted rather than shown empty.
312
+ */
313
+ function subtitlePendant(
314
+ params: { repo?: string } & Record<string, unknown>,
315
+ idKey?: string,
316
+ ): ToolPendant | undefined {
317
+ const parts: string[] = [];
318
+ if (params.repo) parts.push(`repo=${params.repo}`);
319
+ if (idKey) {
320
+ const id = params[idKey];
321
+ if (typeof id === "string" || typeof id === "number") parts.push(`${idKey}=${id}`);
322
+ }
323
+ if (parts.length === 0) return undefined;
324
+ return { subtitle: parts.join(" ") };
325
+ }
326
+
308
327
  interface ListFilters {
309
328
  repo?: string;
310
329
  keywords?: string;
@@ -1121,7 +1140,7 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1121
1140
  }),
1122
1141
  async execute(_id, params, signal, _onUpdate, ctx) {
1123
1142
  const { number, repo } = params;
1124
- return toToolResult(
1143
+ const result = toToolResult(
1125
1144
  await ghExec(
1126
1145
  [
1127
1146
  "issue",
@@ -1135,6 +1154,8 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1135
1154
  ),
1136
1155
  params,
1137
1156
  );
1157
+ result.details.pendant = subtitlePendant(params, "number");
1158
+ return result;
1138
1159
  },
1139
1160
  });
1140
1161
 
@@ -1156,10 +1177,12 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1156
1177
  limit: Type.Optional(Type.Number({ description: "Max results (default 30)" })),
1157
1178
  }),
1158
1179
  async execute(_id, params, signal, _onUpdate, ctx) {
1159
- return toToolResult(
1180
+ const result = toToolResult(
1160
1181
  await listGithub("issue", params, { cwd: ctx.cwd, signal, input: params }),
1161
1182
  params,
1162
1183
  );
1184
+ result.details.pendant = subtitlePendant(params);
1185
+ return result;
1163
1186
  },
1164
1187
  });
1165
1188
 
@@ -1175,7 +1198,7 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1175
1198
  }),
1176
1199
  async execute(_id, params, signal, _onUpdate, ctx) {
1177
1200
  const { number, repo } = params;
1178
- return toToolResult(
1201
+ const result = toToolResult(
1179
1202
  await ghExec(
1180
1203
  [
1181
1204
  "pr",
@@ -1189,6 +1212,8 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1189
1212
  ),
1190
1213
  params,
1191
1214
  );
1215
+ result.details.pendant = subtitlePendant(params, "number");
1216
+ return result;
1192
1217
  },
1193
1218
  });
1194
1219
 
@@ -1212,10 +1237,12 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1212
1237
  limit: Type.Optional(Type.Number({ description: "Max results (default 30)" })),
1213
1238
  }),
1214
1239
  async execute(_id, params, signal, _onUpdate, ctx) {
1215
- return toToolResult(
1240
+ const result = toToolResult(
1216
1241
  await listGithub("pr", params, { cwd: ctx.cwd, signal, input: params }),
1217
1242
  params,
1218
1243
  );
1244
+ result.details.pendant = subtitlePendant(params);
1245
+ return result;
1219
1246
  },
1220
1247
  });
1221
1248
 
@@ -1232,7 +1259,12 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1232
1259
  async execute(_id, params, signal, _onUpdate, ctx) {
1233
1260
  const { number, repo } = params;
1234
1261
  const args = ["pr", "diff", String(number), ...repoArgs(repo)];
1235
- return toToolResult(await ghExec(args, { cwd: ctx.cwd, signal, input: params }), params);
1262
+ const result = toToolResult(
1263
+ await ghExec(args, { cwd: ctx.cwd, signal, input: params }),
1264
+ params,
1265
+ );
1266
+ result.details.pendant = subtitlePendant(params, "number");
1267
+ return result;
1236
1268
  },
1237
1269
  });
1238
1270
 
@@ -1260,7 +1292,9 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1260
1292
  // Anything else is a real error (cancelled, auth, network, ...)
1261
1293
  throw new GhError(args, result, params);
1262
1294
  }
1263
- return toToolResult(result.stdout, params);
1295
+ const toolResult = toToolResult(result.stdout, params);
1296
+ toolResult.details.pendant = subtitlePendant(params, "number");
1297
+ return toolResult;
1264
1298
  },
1265
1299
  });
1266
1300
 
@@ -1322,9 +1356,10 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1322
1356
  );
1323
1357
  }
1324
1358
  const { text, truncated } = truncate(out);
1359
+ const pendant = subtitlePendant(params, "number");
1325
1360
  return {
1326
1361
  content: [{ type: "text", text }],
1327
- details: { input: params, truncated },
1362
+ details: { input: params, truncated, ...(pendant && { pendant }) },
1328
1363
  };
1329
1364
  },
1330
1365
  });
@@ -1341,7 +1376,7 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1341
1376
  }),
1342
1377
  async execute(_id, params, signal, _onUpdate, ctx) {
1343
1378
  const { number, repo } = params;
1344
- return toToolResult(
1379
+ const result = toToolResult(
1345
1380
  await ghExec(["issue", "view", String(number), ...repoArgs(repo), "--json", "comments"], {
1346
1381
  cwd: ctx.cwd,
1347
1382
  signal,
@@ -1349,6 +1384,8 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1349
1384
  }),
1350
1385
  params,
1351
1386
  );
1387
+ result.details.pendant = subtitlePendant(params, "number");
1388
+ return result;
1352
1389
  },
1353
1390
  });
1354
1391
 
@@ -1372,7 +1409,12 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1372
1409
  if (limit) args.push("--limit", String(limit));
1373
1410
  if (status) args.push("--status", status);
1374
1411
  if (workflow) args.push("--workflow", workflow);
1375
- return toToolResult(await ghExec(args, { cwd: ctx.cwd, signal, input: params }), params);
1412
+ const result = toToolResult(
1413
+ await ghExec(args, { cwd: ctx.cwd, signal, input: params }),
1414
+ params,
1415
+ );
1416
+ result.details.pendant = subtitlePendant(params);
1417
+ return result;
1376
1418
  },
1377
1419
  });
1378
1420
 
@@ -1425,6 +1467,7 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1425
1467
  async execute(_id, params, signal, onUpdate, ctx) {
1426
1468
  const { run_id, repo, job, step, offset, limit, full, output_file } = params;
1427
1469
 
1470
+ const pendant = subtitlePendant(params, "run_id");
1428
1471
  const effectiveRepo = await resolveRepo(repo, signal, ctx.cwd, params);
1429
1472
  const jobsOut = await ghExec(["api", `/repos/${effectiveRepo}/actions/runs/${run_id}/jobs`], {
1430
1473
  cwd: ctx.cwd,
@@ -1438,13 +1481,14 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1438
1481
 
1439
1482
  // ── Write the complete log to a file ───────────────────────────────
1440
1483
  if (output_file !== undefined && output_file !== null && output_file !== "") {
1441
- return writeLogFile(
1484
+ const result = await writeLogFile(
1442
1485
  { runId: String(run_id), job, step, outputFile: output_file },
1443
1486
  jobs,
1444
1487
  fetchJobLog,
1445
1488
  ctx.cwd,
1446
1489
  params,
1447
1490
  );
1491
+ return { ...result, details: { ...result.details, ...(pendant && { pendant }) } };
1448
1492
  }
1449
1493
 
1450
1494
  // ── Fetch a specific step's logs (requires `job`) ─────────────────
@@ -1459,7 +1503,10 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1459
1503
  fetchJobLog,
1460
1504
  onUpdate,
1461
1505
  );
1462
- return { ...stepResult, details: { ...stepResult.details, input: params } };
1506
+ return {
1507
+ ...stepResult,
1508
+ details: { ...stepResult.details, input: params, ...(pendant && { pendant }) },
1509
+ };
1463
1510
  }
1464
1511
 
1465
1512
  // ── List jobs/steps, with failed step logs expanded ────────────────
@@ -1472,7 +1519,10 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1472
1519
  jobs,
1473
1520
  fetchJobLog,
1474
1521
  );
1475
- return { ...jobsResult, details: { ...jobsResult.details, input: params } };
1522
+ return {
1523
+ ...jobsResult,
1524
+ details: { ...jobsResult.details, input: params, ...(pendant && { pendant }) },
1525
+ };
1476
1526
  },
1477
1527
  });
1478
1528
 
@@ -1490,7 +1540,7 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1490
1540
  async execute(_id, params, signal, _onUpdate, ctx) {
1491
1541
  const { run_id, repo } = params;
1492
1542
  const effectiveRepo = await resolveRepo(repo, signal, ctx.cwd, params);
1493
- return toToolResult(
1543
+ const result = toToolResult(
1494
1544
  await ghExec(["api", `/repos/${effectiveRepo}/actions/runs/${run_id}/jobs`], {
1495
1545
  cwd: ctx.cwd,
1496
1546
  signal,
@@ -1498,6 +1548,8 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1498
1548
  }),
1499
1549
  params,
1500
1550
  );
1551
+ result.details.pendant = subtitlePendant(params, "run_id");
1552
+ return result;
1501
1553
  },
1502
1554
  });
1503
1555
 
@@ -1514,7 +1566,12 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1514
1566
  const { repo } = params;
1515
1567
  const args = ["repo", "view"];
1516
1568
  if (repo) args.push(repo);
1517
- return toToolResult(await ghExec(args, { cwd: ctx.cwd, signal, input: params }), params);
1569
+ const result = toToolResult(
1570
+ await ghExec(args, { cwd: ctx.cwd, signal, input: params }),
1571
+ params,
1572
+ );
1573
+ result.details.pendant = subtitlePendant(params);
1574
+ return result;
1518
1575
  },
1519
1576
  });
1520
1577
 
@@ -1536,9 +1593,7 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1536
1593
  await ghExec(args, { cwd: ctx.cwd, signal, input: params }),
1537
1594
  params,
1538
1595
  );
1539
- result.details.pendant = {
1540
- subtitle: `repo=${params.repo}`,
1541
- } satisfies ToolPendant;
1596
+ result.details.pendant = subtitlePendant(params);
1542
1597
  return result;
1543
1598
  },
1544
1599
  });
@@ -1555,7 +1610,7 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1555
1610
  }),
1556
1611
  async execute(_id, params, signal, _onUpdate, ctx) {
1557
1612
  const { tag, repo } = params;
1558
- return toToolResult(
1613
+ const result = toToolResult(
1559
1614
  await ghExec(["release", "view", tag, ...repoArgs(repo)], {
1560
1615
  cwd: ctx.cwd,
1561
1616
  signal,
@@ -1563,6 +1618,8 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1563
1618
  }),
1564
1619
  params,
1565
1620
  );
1621
+ result.details.pendant = subtitlePendant(params, "tag");
1622
+ return result;
1566
1623
  },
1567
1624
  });
1568
1625
 
@@ -1584,6 +1641,7 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1584
1641
  async execute(_id, params, signal, onUpdate, ctx) {
1585
1642
  const { number, repo, fail_fast } = params;
1586
1643
 
1644
+ const pendant = subtitlePendant(params, "number");
1587
1645
  onUpdate?.({
1588
1646
  content: [{ type: "text", text: `Watching CI checks for PR #${number}...` }],
1589
1647
  details: {},
@@ -1665,7 +1723,12 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1665
1723
  text: `## PR #${number} CI Checks\n\nNo workflow runs found for head commit ${headRefOid.slice(0, 7)}.`,
1666
1724
  },
1667
1725
  ],
1668
- details: { status: "no-jobs", totalJobs: 0, input: params },
1726
+ details: {
1727
+ status: "no-jobs",
1728
+ totalJobs: 0,
1729
+ input: params,
1730
+ ...(pendant && { pendant }),
1731
+ },
1669
1732
  };
1670
1733
  }
1671
1734
 
@@ -1689,6 +1752,7 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1689
1752
  totalJobs,
1690
1753
  failedJobs,
1691
1754
  input: params,
1755
+ ...(pendant && { pendant }),
1692
1756
  },
1693
1757
  };
1694
1758
  }
@@ -1700,7 +1764,7 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1700
1764
  text: `## PR #${number} CI Checks - PASSED\n\nAll ${totalJobs} job(s) succeeded.`,
1701
1765
  },
1702
1766
  ],
1703
- details: { status: "success", totalJobs, input: params },
1767
+ details: { status: "success", totalJobs, input: params, ...(pendant && { pendant }) },
1704
1768
  };
1705
1769
  },
1706
1770
  });
@@ -1720,6 +1784,7 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1720
1784
  async execute(_id, params, signal, onUpdate, ctx) {
1721
1785
  const { run_id, repo } = params;
1722
1786
 
1787
+ const pendant = subtitlePendant(params, "run_id");
1723
1788
  onUpdate?.({
1724
1789
  content: [{ type: "text", text: `Watching workflow run ${run_id}...` }],
1725
1790
  details: {},
@@ -1739,7 +1804,7 @@ export default function ghReadonlyTools(pi: ExtensionAPI) {
1739
1804
  content: [
1740
1805
  { type: "text", text: `## Workflow Run ${run_id} Completed\n\n${result.stdout}` },
1741
1806
  ],
1742
- details: { exitCode: 0, input: params },
1807
+ details: { exitCode: 0, input: params, ...(pendant && { pendant }) },
1743
1808
  };
1744
1809
  },
1745
1810
  });