@cortexkit/aft-pi 0.14.0 → 0.14.1

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 CHANGED
@@ -3,7 +3,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
3
3
 
4
4
  // src/index.ts
5
5
  import { createRequire as createRequire3 } from "node:module";
6
- import { homedir as homedir5 } from "node:os";
6
+ import { homedir as homedir6 } from "node:os";
7
7
  import { join as join8 } from "node:path";
8
8
 
9
9
  // src/shared/status.ts
@@ -1471,8 +1471,117 @@ function registerFsTools(pi, ctx, surface) {
1471
1471
 
1472
1472
  // src/tools/hoisted.ts
1473
1473
  import { stat } from "node:fs/promises";
1474
+ import { homedir as homedir5 } from "node:os";
1474
1475
  import { resolve } from "node:path";
1476
+ import {
1477
+ renderDiff
1478
+ } from "@mariozechner/pi-coding-agent";
1479
+ import { Container, Spacer, Text } from "@mariozechner/pi-tui";
1475
1480
  import { Type as Type4 } from "@sinclair/typebox";
1481
+
1482
+ // src/tools/diff-format.ts
1483
+ import { diffLines } from "diff";
1484
+ var DEFAULT_CONTEXT_LINES = 4;
1485
+ function formatDiffForPi(oldContent, newContent, contextLines = DEFAULT_CONTEXT_LINES) {
1486
+ const parts = diffLines(oldContent, newContent);
1487
+ const output = [];
1488
+ const oldLines = oldContent.split(`
1489
+ `);
1490
+ const newLines = newContent.split(`
1491
+ `);
1492
+ const maxLineNum = Math.max(oldLines.length, newLines.length);
1493
+ const lineNumWidth = String(maxLineNum).length;
1494
+ const pad = (n) => String(n).padStart(lineNumWidth, " ");
1495
+ const blank = " ".repeat(lineNumWidth);
1496
+ let oldLineNum = 1;
1497
+ let newLineNum = 1;
1498
+ let lastWasChange = false;
1499
+ let firstChangedLine;
1500
+ for (let i = 0;i < parts.length; i++) {
1501
+ const part = parts[i];
1502
+ const raw = part.value.split(`
1503
+ `);
1504
+ if (raw[raw.length - 1] === "")
1505
+ raw.pop();
1506
+ if (part.added || part.removed) {
1507
+ if (firstChangedLine === undefined)
1508
+ firstChangedLine = newLineNum;
1509
+ for (const line of raw) {
1510
+ if (part.added) {
1511
+ output.push(`+${pad(newLineNum)} ${line}`);
1512
+ newLineNum++;
1513
+ } else {
1514
+ output.push(`-${pad(oldLineNum)} ${line}`);
1515
+ oldLineNum++;
1516
+ }
1517
+ }
1518
+ lastWasChange = true;
1519
+ continue;
1520
+ }
1521
+ const nextIsChange = i < parts.length - 1 && (parts[i + 1].added || parts[i + 1].removed);
1522
+ const hasLeading = lastWasChange;
1523
+ const hasTrailing = nextIsChange;
1524
+ if (hasLeading && hasTrailing) {
1525
+ if (raw.length <= contextLines * 2) {
1526
+ for (const line of raw) {
1527
+ output.push(` ${pad(oldLineNum)} ${line}`);
1528
+ oldLineNum++;
1529
+ newLineNum++;
1530
+ }
1531
+ } else {
1532
+ for (const line of raw.slice(0, contextLines)) {
1533
+ output.push(` ${pad(oldLineNum)} ${line}`);
1534
+ oldLineNum++;
1535
+ newLineNum++;
1536
+ }
1537
+ const skipped = raw.length - contextLines * 2;
1538
+ output.push(` ${blank} ...`);
1539
+ oldLineNum += skipped;
1540
+ newLineNum += skipped;
1541
+ for (const line of raw.slice(raw.length - contextLines)) {
1542
+ output.push(` ${pad(oldLineNum)} ${line}`);
1543
+ oldLineNum++;
1544
+ newLineNum++;
1545
+ }
1546
+ }
1547
+ } else if (hasLeading) {
1548
+ const shown = raw.slice(0, contextLines);
1549
+ for (const line of shown) {
1550
+ output.push(` ${pad(oldLineNum)} ${line}`);
1551
+ oldLineNum++;
1552
+ newLineNum++;
1553
+ }
1554
+ const skipped = raw.length - shown.length;
1555
+ if (skipped > 0) {
1556
+ output.push(` ${blank} ...`);
1557
+ oldLineNum += skipped;
1558
+ newLineNum += skipped;
1559
+ }
1560
+ } else if (hasTrailing) {
1561
+ const shownCount = Math.min(contextLines, raw.length);
1562
+ const shown = raw.slice(raw.length - shownCount);
1563
+ const skipped = raw.length - shown.length;
1564
+ if (skipped > 0) {
1565
+ output.push(` ${blank} ...`);
1566
+ oldLineNum += skipped;
1567
+ newLineNum += skipped;
1568
+ }
1569
+ for (const line of shown) {
1570
+ output.push(` ${pad(oldLineNum)} ${line}`);
1571
+ oldLineNum++;
1572
+ newLineNum++;
1573
+ }
1574
+ } else {
1575
+ oldLineNum += raw.length;
1576
+ newLineNum += raw.length;
1577
+ }
1578
+ lastWasChange = false;
1579
+ }
1580
+ return { diff: output.join(`
1581
+ `), firstChangedLine };
1582
+ }
1583
+
1584
+ // src/tools/hoisted.ts
1476
1585
  var ReadParams = Type4.Object({
1477
1586
  path: Type4.String({ description: "Path to the file to read (relative or absolute)" }),
1478
1587
  offset: Type4.Optional(Type4.Number({ description: "Line number to start reading from (1-indexed)" })),
@@ -1504,6 +1613,8 @@ function registerHoistedTools(pi, ctx, surface) {
1504
1613
  name: "read",
1505
1614
  label: "read",
1506
1615
  description: "Read file contents with line numbers. Backed by AFT's indexed Rust reader — faster than the built-in `read` on large repos and correctly handles images/PDFs as attachments.",
1616
+ promptSnippet: "Read file contents (supports offset/limit for large files)",
1617
+ promptGuidelines: ["Use read to examine files instead of cat or sed."],
1507
1618
  parameters: ReadParams,
1508
1619
  async execute(_toolCallId, params, _signal, _onUpdate, extCtx) {
1509
1620
  const bridge = bridgeFor(ctx, extCtx.cwd);
@@ -1530,30 +1641,24 @@ function registerHoistedTools(pi, ctx, surface) {
1530
1641
  pi.registerTool({
1531
1642
  name: "write",
1532
1643
  label: "write",
1533
- description: "Write a file atomically with per-file backup, optional auto-format, and inline LSP diagnostics. Parent directories are created automatically. Overwrites existing files.",
1644
+ description: "Write a file atomically with per-file backup, optional auto-format, and inline LSP diagnostics. Parent directories are created automatically. Overwrites existing files. Uses `filePath` (not `path`).",
1645
+ promptSnippet: "Create or overwrite files (uses filePath; auto-formats; returns LSP diagnostics inline)",
1646
+ promptGuidelines: ["Use write only for new files or complete rewrites."],
1534
1647
  parameters: WriteParams,
1535
1648
  async execute(_toolCallId, params, _signal, _onUpdate, extCtx) {
1536
1649
  const bridge = bridgeFor(ctx, extCtx.cwd);
1537
1650
  const response = await callBridge(bridge, "write", {
1538
1651
  file: params.filePath,
1539
- content: params.content
1540
- });
1541
- const diffAdd = response.diff?.additions ?? 0;
1542
- const diffDel = response.diff?.deletions ?? 0;
1543
- const diagnostics = response.lsp_diagnostics;
1544
- let summary = `Wrote ${params.filePath} (+${diffAdd}/-${diffDel})`;
1545
- if (diagnostics && diagnostics.length > 0) {
1546
- summary += `
1547
-
1548
- LSP diagnostics:
1549
- ${JSON.stringify(diagnostics, null, 2)}`;
1550
- }
1551
- return textResult(summary, {
1552
- filePath: params.filePath,
1553
- additions: diffAdd,
1554
- deletions: diffDel,
1555
- diagnostics
1652
+ content: params.content,
1653
+ include_diff: true
1556
1654
  });
1655
+ return buildMutationResult(params.filePath, response);
1656
+ },
1657
+ renderCall(args, theme, context) {
1658
+ return renderMutationCall("write", args?.filePath, theme, context);
1659
+ },
1660
+ renderResult(result, _options, theme, context) {
1661
+ return renderMutationResult(result, theme, context);
1557
1662
  }
1558
1663
  });
1559
1664
  }
@@ -1561,39 +1666,33 @@ ${JSON.stringify(diagnostics, null, 2)}`;
1561
1666
  pi.registerTool({
1562
1667
  name: "edit",
1563
1668
  label: "edit",
1564
- description: "Find-and-replace edit with progressive fuzzy matching (handles whitespace and Unicode drift). Returns an error if multiple matches are found — use `occurrence` to select one, or `replaceAll: true` to replace all. Always returns inline LSP diagnostics for the edited file.",
1669
+ description: "Find-and-replace edit with progressive fuzzy matching (handles whitespace and Unicode drift). Uses `filePath`, `oldString`, `newString`. Errors on multiple matches — use `occurrence` to pick one, or `replaceAll: true`. Always returns LSP diagnostics inline.",
1670
+ promptSnippet: "Targeted find-and-replace (uses filePath/oldString/newString; occurrence or replaceAll for disambiguation; fuzzy whitespace matching)",
1671
+ promptGuidelines: [
1672
+ "Prefer edit over write when changing part of an existing file.",
1673
+ "Include enough surrounding context in oldString to make the match unique, or set replaceAll/occurrence explicitly."
1674
+ ],
1565
1675
  parameters: EditParams,
1566
1676
  async execute(_toolCallId, params, _signal, _onUpdate, extCtx) {
1567
1677
  const bridge = bridgeFor(ctx, extCtx.cwd);
1568
1678
  const req = {
1569
1679
  file: params.filePath,
1570
1680
  match: params.oldString ?? "",
1571
- replacement: params.newString ?? ""
1681
+ replacement: params.newString ?? "",
1682
+ include_diff: true
1572
1683
  };
1573
1684
  if (params.replaceAll === true)
1574
1685
  req.replace_all = true;
1575
1686
  if (params.occurrence !== undefined)
1576
1687
  req.occurrence = params.occurrence;
1577
1688
  const response = await callBridge(bridge, "edit_match", req);
1578
- const diff = response.diff;
1579
- const diffAdd = diff?.additions ?? 0;
1580
- const diffDel = diff?.deletions ?? 0;
1581
- const replacements = response.replacements;
1582
- const diagnostics = response.lsp_diagnostics;
1583
- let summary = `Edited ${params.filePath} (+${diffAdd}/-${diffDel}, ${replacements ?? 1} replacement${replacements === 1 ? "" : "s"})`;
1584
- if (diagnostics && diagnostics.length > 0) {
1585
- summary += `
1586
-
1587
- LSP diagnostics:
1588
- ${JSON.stringify(diagnostics, null, 2)}`;
1589
- }
1590
- return textResult(summary, {
1591
- filePath: params.filePath,
1592
- additions: diffAdd,
1593
- deletions: diffDel,
1594
- replacements,
1595
- diagnostics
1596
- });
1689
+ return buildMutationResult(params.filePath, response);
1690
+ },
1691
+ renderCall(args, theme, context) {
1692
+ return renderMutationCall("edit", args?.filePath, theme, context);
1693
+ },
1694
+ renderResult(result, _options, theme, context) {
1695
+ return renderMutationResult(result, theme, context);
1597
1696
  }
1598
1697
  });
1599
1698
  }
@@ -1602,6 +1701,8 @@ ${JSON.stringify(diagnostics, null, 2)}`;
1602
1701
  name: "grep",
1603
1702
  label: "grep",
1604
1703
  description: "Search for a regex pattern across files. Uses AFT's trigram index inside the project root for fast repeated queries, and falls back to ripgrep for paths outside the project root.",
1704
+ promptSnippet: "Fast regex search across files (trigram-indexed inside the project root)",
1705
+ promptGuidelines: ["Prefer grep over bash-invoked find/rg for in-project searches."],
1605
1706
  parameters: GrepParams,
1606
1707
  async execute(_toolCallId, params, _signal, _onUpdate, extCtx) {
1607
1708
  const bridge = bridgeFor(ctx, extCtx.cwd);
@@ -1621,6 +1722,112 @@ ${JSON.stringify(diagnostics, null, 2)}`;
1621
1722
  });
1622
1723
  }
1623
1724
  }
1725
+ function buildMutationResult(filePath, response) {
1726
+ const diffObj = response.diff;
1727
+ const additions = diffObj?.additions ?? 0;
1728
+ const deletions = diffObj?.deletions ?? 0;
1729
+ const replacements = response.replacements;
1730
+ const diagnostics = response.lsp_diagnostics;
1731
+ const truncated = diffObj?.truncated === true;
1732
+ let diffText;
1733
+ let firstChangedLine;
1734
+ if (diffObj && !truncated && typeof diffObj.before === "string" && typeof diffObj.after === "string") {
1735
+ const formatted = formatDiffForPi(diffObj.before, diffObj.after);
1736
+ diffText = formatted.diff;
1737
+ firstChangedLine = formatted.firstChangedLine;
1738
+ }
1739
+ const summaryHeader = replacements !== undefined ? `Edited ${filePath} (+${additions}/-${deletions}, ${replacements} replacement${replacements === 1 ? "" : "s"})` : `Wrote ${filePath} (+${additions}/-${deletions})`;
1740
+ let text = summaryHeader;
1741
+ if (diffText)
1742
+ text += `
1743
+
1744
+ ${diffText}`;
1745
+ if (truncated) {
1746
+ text += `
1747
+
1748
+ (diff truncated — file too large to include before/after content)`;
1749
+ }
1750
+ if (diagnostics && diagnostics.length > 0) {
1751
+ text += `
1752
+
1753
+ LSP diagnostics:
1754
+ ${formatDiagnosticsText(diagnostics)}`;
1755
+ }
1756
+ return {
1757
+ content: [{ type: "text", text }],
1758
+ details: {
1759
+ diff: diffText,
1760
+ firstChangedLine,
1761
+ additions,
1762
+ deletions,
1763
+ replacements,
1764
+ diagnostics,
1765
+ truncated: truncated || undefined
1766
+ }
1767
+ };
1768
+ }
1769
+ function formatDiagnosticsText(diagnostics) {
1770
+ try {
1771
+ return diagnostics.map((d) => {
1772
+ if (d && typeof d === "object") {
1773
+ const obj = d;
1774
+ const line = obj.line ?? obj.startLine ?? "?";
1775
+ const severity = obj.severity ?? "info";
1776
+ const msg = obj.message ?? JSON.stringify(obj);
1777
+ return ` [${severity}] line ${line}: ${msg}`;
1778
+ }
1779
+ return ` ${String(d)}`;
1780
+ }).join(`
1781
+ `);
1782
+ } catch {
1783
+ return JSON.stringify(diagnostics, null, 2);
1784
+ }
1785
+ }
1786
+ function reuseText(last) {
1787
+ return last instanceof Text ? last : new Text("", 0, 0);
1788
+ }
1789
+ function reuseContainer(last) {
1790
+ return last instanceof Container ? last : new Container;
1791
+ }
1792
+ function renderMutationCall(toolName, filePath, theme, context) {
1793
+ const text = reuseText(context.lastComponent);
1794
+ const pathDisplay = filePath ? theme.fg("accent", shortenPath(filePath)) : theme.fg("toolOutput", "...");
1795
+ text.setText(`${theme.fg("toolTitle", theme.bold(toolName))} ${pathDisplay}`);
1796
+ return text;
1797
+ }
1798
+ function renderMutationResult(result, theme, context) {
1799
+ if (context.isError) {
1800
+ const errorText = result.content.filter((c) => c.type === "text").map((c) => c.text ?? "").join(`
1801
+ `).trim();
1802
+ const text = reuseText(context.lastComponent);
1803
+ text.setText(`
1804
+ ${theme.fg("error", errorText || "edit failed")}`);
1805
+ return text;
1806
+ }
1807
+ const details = result.details;
1808
+ const diff = typeof details?.diff === "string" ? details.diff : undefined;
1809
+ if (!diff) {
1810
+ const additions = details?.additions ?? 0;
1811
+ const deletions = details?.deletions ?? 0;
1812
+ const text = reuseText(context.lastComponent);
1813
+ const summary = theme.fg("success", `+${additions}/-${deletions}`);
1814
+ const suffix = details?.truncated ? ` ${theme.fg("muted", "(diff truncated)")}` : "";
1815
+ text.setText(`
1816
+ ${summary}${suffix}`);
1817
+ return text;
1818
+ }
1819
+ const container = reuseContainer(context.lastComponent);
1820
+ container.clear();
1821
+ container.addChild(new Spacer(1));
1822
+ container.addChild(new Text(renderDiff(diff), 1, 0));
1823
+ return container;
1824
+ }
1825
+ function shortenPath(path2) {
1826
+ const home = homedir5();
1827
+ if (path2.startsWith(home))
1828
+ return `~${path2.slice(home.length)}`;
1829
+ return path2;
1830
+ }
1624
1831
  async function resolvePathArg(cwd, path2) {
1625
1832
  const abs = resolve(cwd, path2);
1626
1833
  try {
@@ -2038,12 +2245,20 @@ function registerSafetyTool(pi, ctx) {
2038
2245
  list: "list_checkpoints"
2039
2246
  };
2040
2247
  const req = {};
2041
- if (params.filePath)
2042
- req.file = params.filePath;
2043
2248
  if (params.name)
2044
2249
  req.name = params.name;
2045
- if (params.files)
2046
- req.files = params.files;
2250
+ if (params.op === "checkpoint") {
2251
+ if (params.files) {
2252
+ req.files = params.files;
2253
+ } else if (params.filePath) {
2254
+ req.files = [params.filePath];
2255
+ }
2256
+ } else {
2257
+ if (params.filePath)
2258
+ req.file = params.filePath;
2259
+ if (params.files)
2260
+ req.files = params.files;
2261
+ }
2047
2262
  const response = await callBridge(bridge, commandMap[params.op], req);
2048
2263
  return textResult(JSON.stringify(response, null, 2));
2049
2264
  }
@@ -2145,7 +2360,7 @@ var PLUGIN_VERSION = (() => {
2145
2360
  }
2146
2361
  })();
2147
2362
  function resolveStorageDir() {
2148
- return join8(homedir5(), ".pi", "agent", "aft");
2363
+ return join8(homedir6(), ".pi", "agent", "aft");
2149
2364
  }
2150
2365
  function resolveToolSurface(config) {
2151
2366
  const surface = config.tool_surface ?? "recommended";
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Diff formatting helpers for Pi hoisted tool renderers.
3
+ *
4
+ * Mirrors the output shape Pi's built-in `renderDiff` expects:
5
+ * "+NN content" for added lines
6
+ * "-NN content" for removed lines
7
+ * " NN content" for context lines
8
+ * " NN ..." for context truncation markers
9
+ *
10
+ * We don't re-export Pi's internal `generateDiffString` because it isn't
11
+ * public. Reimplementing it as a thin wrapper around the `diff` npm package
12
+ * (also used by Pi itself) is ~40 lines and keeps us decoupled from Pi's
13
+ * private internals.
14
+ */
15
+ export interface FormattedDiff {
16
+ diff: string;
17
+ firstChangedLine: number | undefined;
18
+ }
19
+ /**
20
+ * Generate a line-numbered diff string suitable for Pi's `renderDiff`.
21
+ * Matches the format of Pi's built-in edit tool result.
22
+ */
23
+ export declare function formatDiffForPi(oldContent: string, newContent: string, contextLines?: number): FormattedDiff;
24
+ //# sourceMappingURL=diff-format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff-format.d.ts","sourceRoot":"","sources":["../../src/tools/diff-format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;CACtC;AAID;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,YAAY,SAAwB,GACnC,aAAa,CAsGf"}
@@ -2,8 +2,21 @@
2
2
  * Hoisted tool overrides — replace Pi's built-in read/write/edit/grep with
3
3
  * AFT-backed Rust implementations. Registering a tool with the same name as
4
4
  * a built-in replaces the built-in entirely.
5
+ *
6
+ * Each tool provides:
7
+ * - `promptSnippet` / `promptGuidelines`: teach the model our argument shape
8
+ * in Pi's system prompt (Pi's built-ins use generic one-liners otherwise).
9
+ * - `renderCall` / `renderResult` for `write` and `edit`: without these,
10
+ * Pi's ToolExecutionComponent falls back to the *built-in* renderer for
11
+ * same-named tools, which reads `path` and `edits[]` and garbles our
12
+ * `filePath` / `oldString` / `newString` output (issue #15).
13
+ * - Structured `details: { diff, firstChangedLine }` so the rendered diff
14
+ * also ends up in the agent's message stream, matching Pi's convention.
15
+ *
16
+ * `read` and `grep` keep the default text-only result rendering because our
17
+ * payload (`path`, `pattern`) already aligns with Pi's built-in arg shape.
5
18
  */
6
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
19
+ import { type AgentToolResult, type ExtensionAPI } from "@mariozechner/pi-coding-agent";
7
20
  import type { PluginContext } from "../types.js";
8
21
  export interface ToolSurfaceFlags {
9
22
  hoistRead: boolean;
@@ -11,5 +24,28 @@ export interface ToolSurfaceFlags {
11
24
  hoistEdit: boolean;
12
25
  hoistGrep: boolean;
13
26
  }
27
+ /** Details surfaced to both renderer and agent message stream. */
28
+ interface FileMutationDetails {
29
+ diff?: string;
30
+ firstChangedLine?: number;
31
+ additions: number;
32
+ deletions: number;
33
+ replacements?: number;
34
+ diagnostics?: unknown[];
35
+ /**
36
+ * True when Rust returned `diff.truncated = true` — the before/after strings
37
+ * were omitted because the file exceeded the diff size cap, so we have no
38
+ * line-level diff to render. Both the agent-facing text and the TUI renderer
39
+ * surface this explicitly rather than silently showing a summary.
40
+ */
41
+ truncated?: boolean;
42
+ }
14
43
  export declare function registerHoistedTools(pi: ExtensionAPI, ctx: PluginContext, surface: ToolSurfaceFlags): void;
44
+ /**
45
+ * Shape the bridge `edit_match` / `write` response into an `AgentToolResult`
46
+ * Pi can render. Exported for unit tests covering truncation and diagnostics
47
+ * behavior without spinning up a real bridge.
48
+ */
49
+ export declare function buildMutationResult(filePath: string, response: Record<string, unknown>): AgentToolResult<FileMutationDetails>;
50
+ export {};
15
51
  //# sourceMappingURL=hoisted.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hoisted.d.ts","sourceRoot":"","sources":["../../src/tools/hoisted.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAElE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AA0CjD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,YAAY,EAChB,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,gBAAgB,GACxB,IAAI,CAgJN"}
1
+ {"version":3,"file":"hoisted.d.ts","sourceRoot":"","sources":["../../src/tools/hoisted.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAKH,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,YAAY,EAGlB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAqDjD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,kEAAkE;AAClE,UAAU,mBAAmB;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC;IACxB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,YAAY,EAChB,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,gBAAgB,GACxB,IAAI,CA8IN;AAMD;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,eAAe,CAAC,mBAAmB,CAAC,CA6DtC"}
@@ -1 +1 @@
1
- {"version":3,"file":"safety.d.ts","sourceRoot":"","sources":["../../src/tools/safety.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAElE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAkBjD,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,aAAa,GAAG,IAAI,CAoC7E"}
1
+ {"version":3,"file":"safety.d.ts","sourceRoot":"","sources":["../../src/tools/safety.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAElE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAkBjD,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,aAAa,GAAG,IAAI,CAkD7E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/aft-pi",
3
- "version": "0.14.0",
3
+ "version": "0.14.1",
4
4
  "type": "module",
5
5
  "description": "Pi coding agent extension for Agent File Tools (AFT) — tree-sitter and LSP-powered code analysis",
6
6
  "main": "dist/index.js",
@@ -15,29 +15,32 @@
15
15
  "README.md"
16
16
  ],
17
17
  "scripts": {
18
- "build": "bun build src/index.ts --outdir dist --target node --format esm --external @mariozechner/pi-coding-agent --external @mariozechner/pi-ai --external @mariozechner/pi-tui --external @sinclair/typebox && tsc --emitDeclarationOnly",
18
+ "build": "bun build src/index.ts --outdir dist --target node --format esm --external @mariozechner/pi-coding-agent --external @mariozechner/pi-ai --external @mariozechner/pi-tui --external @sinclair/typebox --external diff && tsc --emitDeclarationOnly",
19
19
  "typecheck": "tsc --noEmit",
20
20
  "test": "bun test src/__tests__/",
21
21
  "prepublishOnly": "bun run build"
22
22
  },
23
23
  "dependencies": {
24
- "@sinclair/typebox": "^0.34.33"
24
+ "@sinclair/typebox": "^0.34.33",
25
+ "diff": "^8.0.4"
25
26
  },
26
27
  "optionalDependencies": {
27
- "@cortexkit/aft-darwin-arm64": "0.14.0",
28
- "@cortexkit/aft-darwin-x64": "0.14.0",
29
- "@cortexkit/aft-linux-arm64": "0.14.0",
30
- "@cortexkit/aft-linux-x64": "0.14.0",
31
- "@cortexkit/aft-win32-x64": "0.14.0"
28
+ "@cortexkit/aft-darwin-arm64": "0.14.1",
29
+ "@cortexkit/aft-darwin-x64": "0.14.1",
30
+ "@cortexkit/aft-linux-arm64": "0.14.1",
31
+ "@cortexkit/aft-linux-x64": "0.14.1",
32
+ "@cortexkit/aft-win32-x64": "0.14.1"
32
33
  },
33
34
  "devDependencies": {
34
35
  "@mariozechner/pi-coding-agent": "*",
35
36
  "@mariozechner/pi-ai": "*",
37
+ "@mariozechner/pi-tui": "*",
36
38
  "@types/node": "^22.0.0",
37
39
  "typescript": "^5.8.0"
38
40
  },
39
41
  "peerDependencies": {
40
- "@mariozechner/pi-coding-agent": "*"
42
+ "@mariozechner/pi-coding-agent": "*",
43
+ "@mariozechner/pi-tui": "*"
41
44
  },
42
45
  "exports": {
43
46
  ".": {