1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
/**
* Atuin extension for pi.
*
* Tracks bash commands executed by pi in Atuin history with author `pi`.
*
* Install with:
* atuin hook install pi
*
* Then restart pi or run /reload.
*/
import type { BashOperations, ExtensionAPI } from "@mariozechner/pi-coding-agent";
import { createBashTool, createLocalBashOperations } from "@mariozechner/pi-coding-agent";
const ATUIN_AUTHOR = "pi";
const ATUIN_TIMEOUT_MS = 10_000;
async function startHistory(
pi: ExtensionAPI,
cwd: string,
command: string,
): Promise<string | undefined> {
try {
const result = await pi.exec(
"atuin",
["history", "start", "--author", ATUIN_AUTHOR, "--", command],
{ cwd, timeout: ATUIN_TIMEOUT_MS },
);
if (result.code !== 0) return undefined;
const id = result.stdout.trim();
return id.length > 0 ? id : undefined;
} catch {
return undefined;
}
}
async function endHistory(
pi: ExtensionAPI,
cwd: string,
historyId: string,
exitCode: number,
): Promise<void> {
try {
await pi.exec(
"atuin",
["history", "end", historyId, "--exit", String(exitCode)],
{ cwd, timeout: ATUIN_TIMEOUT_MS },
);
} catch {
// Ignore Atuin failures so command execution is never blocked.
}
}
export default function atuinPiExtension(pi: ExtensionAPI) {
const cwd = process.cwd();
const local = createLocalBashOperations();
const trackedOperations: BashOperations = {
async exec(command, commandCwd, options) {
const historyId = await startHistory(pi, commandCwd, command);
let exitCode: number | null = null;
try {
const result = await local.exec(command, commandCwd, options);
exitCode = result.exitCode;
return result;
} finally {
if (historyId) {
await endHistory(
pi,
commandCwd,
historyId,
exitCode ?? (options.signal?.aborted ? 130 : 1),
);
}
}
},
};
pi.registerTool(
createBashTool(cwd, {
operations: trackedOperations,
}),
);
}
|