@xynogen/pix-hunk 0.1.2 → 0.2.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 +24 -8
- package/package.json +4 -4
- package/src/index.ts +29 -22
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# pix-hunk
|
|
2
2
|
|
|
3
3
|
Pi tool for driving a live [Hunk](https://github.com/modem-dev/hunk) diff review.
|
|
4
4
|
One `hunk` call accepts ordered `ops[]`, so an agent can inspect, navigate,
|
|
@@ -7,7 +7,10 @@ quoting.
|
|
|
7
7
|
|
|
8
8
|
## Requirements
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Launch Hunk's interactive TUI in another terminal. If `hunk` isn't found
|
|
11
|
+
(`~/.pi/agent/binary.json` → `~/.pi/agent/bin` → `PATH`), pix downloads the
|
|
12
|
+
official `modem-dev/hunk` release on first use and verifies it against
|
|
13
|
+
`SHA256SUMS`, with a visible status. This extension
|
|
11
14
|
only calls `hunk session *`; it never starts `hunk diff`, `show`, `patch`, or
|
|
12
15
|
another interactive command.
|
|
13
16
|
|
|
@@ -54,20 +57,33 @@ Model-facing output defaults to 10,000 characters. Set `maxCharacters` between
|
|
|
54
57
|
quota, so a large patch cannot hide later results. Full structured results
|
|
55
58
|
remain available in tool details for inspection.
|
|
56
59
|
|
|
60
|
+
## Scope ceiling
|
|
61
|
+
|
|
62
|
+
`comment apply`, STML markup, and comment clearing are intentionally omitted.
|
|
63
|
+
Use Hunk's CLI directly until repeated demand justifies extending the schema.
|
|
64
|
+
|
|
57
65
|
## Install
|
|
58
66
|
|
|
59
67
|
```bash
|
|
60
68
|
pi install npm:@xynogen/pix-hunk
|
|
61
69
|
```
|
|
62
70
|
|
|
63
|
-
Standalone
|
|
64
|
-
package is not bundled by `@xynogen/pix-core`.
|
|
71
|
+
> Standalone and opt-in. [`@xynogen/pix-core`](https://www.npmjs.com/package/@xynogen/pix-core) does not bundle it. It needs the external Hunk CLI and a live review session.
|
|
65
72
|
|
|
66
|
-
##
|
|
73
|
+
## Full distro
|
|
67
74
|
|
|
68
|
-
|
|
69
|
-
|
|
75
|
+
This package is part of [Pix](https://github.com/xynogen/pix-mono). The installer sets up Pi and the full distro. See [Install](https://github.com/xynogen/pix-mono#install) for the notes for each OS.
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# Linux / macOS
|
|
79
|
+
curl -fsSL https://raw.githubusercontent.com/xynogen/pix-mono/main/scripts/install.sh | sh
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
```powershell
|
|
83
|
+
# Windows
|
|
84
|
+
irm https://raw.githubusercontent.com/xynogen/pix-mono/main/scripts/install.ps1 | iex
|
|
85
|
+
```
|
|
70
86
|
|
|
71
87
|
## License
|
|
72
88
|
|
|
73
|
-
MIT
|
|
89
|
+
MIT. See [LICENSE](LICENSE).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xynogen/pix-hunk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Pi tool — drive live Hunk diff reviews with ordered bulk operations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -44,11 +44,11 @@
|
|
|
44
44
|
"access": "public"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@xynogen/pix-pretty": "^1.
|
|
48
|
-
"@xynogen/pix-runtime": "^0.
|
|
49
|
-
"typebox": "^1.1.38"
|
|
47
|
+
"@xynogen/pix-pretty": "^1.29.0",
|
|
48
|
+
"@xynogen/pix-runtime": "^0.12.0"
|
|
50
49
|
},
|
|
51
50
|
"peerDependencies": {
|
|
51
|
+
"typebox": "*",
|
|
52
52
|
"@earendil-works/pi-coding-agent": "*",
|
|
53
53
|
"@earendil-works/pi-tui": "*"
|
|
54
54
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import { execFile } from "node:child_process";
|
|
2
1
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
3
2
|
import { Text } from "@earendil-works/pi-tui";
|
|
3
|
+
import { reportToolStatus, type ToolStatusUI } from "@xynogen/pix-pretty/tool-status";
|
|
4
4
|
import {
|
|
5
5
|
dotJoin,
|
|
6
6
|
formatCollapsedToolRow,
|
|
7
7
|
frameToolResult,
|
|
8
|
+
getErrorMessage,
|
|
8
9
|
hideCollapsedToolCall,
|
|
9
10
|
} from "@xynogen/pix-pretty/utils";
|
|
10
11
|
import { type CollapseState, tickCollapse } from "@xynogen/pix-runtime/collapse";
|
|
12
|
+
import { runTool } from "@xynogen/pix-runtime/exec";
|
|
11
13
|
import { Type } from "typebox";
|
|
12
14
|
import {
|
|
13
15
|
buildHunkArgs,
|
|
@@ -26,22 +28,29 @@ export interface HunkRunResult {
|
|
|
26
28
|
code: number;
|
|
27
29
|
}
|
|
28
30
|
|
|
29
|
-
export type HunkRunner = (
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
31
|
+
export type HunkRunner = (
|
|
32
|
+
args: string[],
|
|
33
|
+
signal?: AbortSignal,
|
|
34
|
+
ui?: ToolStatusUI,
|
|
35
|
+
) => Promise<HunkRunResult>;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Default runner: resolve hunk via pix-runtime (binary.json → agent bin →
|
|
39
|
+
* PATH), downloading the official release on first use with a visible status.
|
|
40
|
+
* runTool also runs the npm `hunk.cmd` shim on Windows. A missing binary
|
|
41
|
+
* throws BinaryMissingError carrying the install hint.
|
|
42
|
+
*/
|
|
43
|
+
export const runHunk: HunkRunner = async (args, signal, ui) => {
|
|
44
|
+
const r = await runTool("hunk", args, {
|
|
45
|
+
signal,
|
|
46
|
+
onStatus: reportToolStatus(ui),
|
|
47
|
+
maxBuffer: MAX_OUTPUT_BYTES,
|
|
44
48
|
});
|
|
49
|
+
if (signal?.aborted) throw signal.reason ?? new Error("aborted");
|
|
50
|
+
if (r.truncated)
|
|
51
|
+
return { stdout: r.stdout, stderr: `hunk output exceeded ${MAX_OUTPUT_BYTES} bytes`, code: 1 };
|
|
52
|
+
return { stdout: r.stdout, stderr: r.stderr, code: r.code ?? 1 };
|
|
53
|
+
};
|
|
45
54
|
|
|
46
55
|
type JsonValue = null | boolean | number | string | JsonValue[] | { [key: string]: JsonValue };
|
|
47
56
|
|
|
@@ -361,10 +370,7 @@ function modelText(results: HunkOperationResult[], ops: ToolOp[], maxCharacters:
|
|
|
361
370
|
}
|
|
362
371
|
|
|
363
372
|
function executionError(run: HunkRunResult): string {
|
|
364
|
-
|
|
365
|
-
return /(?:^|\s)(?:spawn\s+)?hunk\s+ENOENT(?:\s|$)/i.test(raw)
|
|
366
|
-
? "Hunk CLI not found. Install Hunk, launch a review session, then retry."
|
|
367
|
-
: raw;
|
|
373
|
+
return (run.stderr || run.stdout || `hunk exited ${run.code}`).trim();
|
|
368
374
|
}
|
|
369
375
|
|
|
370
376
|
function actionSummary(actions: HunkAction[]): string {
|
|
@@ -440,6 +446,7 @@ function renderExpanded(details: HunkResultDetails, theme: HunkTheme): string {
|
|
|
440
446
|
export default function registerHunk(pi: ExtensionAPI, runner: HunkRunner = runHunk): void {
|
|
441
447
|
pi.registerTool({
|
|
442
448
|
name: "hunk",
|
|
449
|
+
...({ exposure: "deferred" } as const),
|
|
443
450
|
label: "Hunk",
|
|
444
451
|
renderShell: "self",
|
|
445
452
|
description:
|
|
@@ -505,7 +512,7 @@ export default function registerHunk(pi: ExtensionAPI, runner: HunkRunner = runH
|
|
|
505
512
|
const results: HunkOperationResult[] = [];
|
|
506
513
|
for (const op of ops) {
|
|
507
514
|
try {
|
|
508
|
-
const run = await runner(buildHunkArgs(op, ctx.cwd), signal);
|
|
515
|
+
const run = await runner(buildHunkArgs(op, ctx.cwd), signal, ctx.ui);
|
|
509
516
|
results.push(
|
|
510
517
|
run.code === 0
|
|
511
518
|
? { action: op.action, ok: true, data: parseOutput(run.stdout || run.stderr) }
|
|
@@ -516,7 +523,7 @@ export default function registerHunk(pi: ExtensionAPI, runner: HunkRunner = runH
|
|
|
516
523
|
results.push({
|
|
517
524
|
action: op.action,
|
|
518
525
|
ok: false,
|
|
519
|
-
error:
|
|
526
|
+
error: getErrorMessage(error),
|
|
520
527
|
});
|
|
521
528
|
}
|
|
522
529
|
}
|