@shanepadgett/tau-agent 0.39.0 → 0.39.2
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/extensions/auto-compact/README.md +1 -1
- package/extensions/auto-compact/index.ts +20 -0
- package/extensions/branch/README.md +6 -2
- package/extensions/branch/index.ts +7 -0
- package/extensions/silent-command-runner/README.md +2 -0
- package/extensions/silent-command-runner/index.ts +50 -11
- package/extensions/tau-help/help.md +3 -1
- package/package.json +2 -2
- package/shared/events.ts +9 -0
|
@@ -6,4 +6,4 @@ Set `extensions.autoCompact.tokenLimit` to change the limit. It defaults to 175,
|
|
|
6
6
|
|
|
7
7
|
After changing this extension, run `/reload` before testing it.
|
|
8
8
|
|
|
9
|
-
Automatic compaction holds attention notifications while it runs and while the hidden continuation resumes the interrupted work. The notification is released only after that resumed work settles.
|
|
9
|
+
Automatic compaction holds attention notifications while it runs and while the hidden continuation resumes the interrupted work. The notification is released only after that resumed work settles. It also pauses silent post-edit checks across the compact so they do not run on incomplete work.
|
|
@@ -14,6 +14,7 @@ export default function autoCompactExtension(pi: ExtensionAPI): void {
|
|
|
14
14
|
let sessionVersion = 0;
|
|
15
15
|
let attentionHoldSequence = 0;
|
|
16
16
|
let attentionHoldId: string | undefined;
|
|
17
|
+
let silentCheckPauseId: string | undefined;
|
|
17
18
|
let continuationPending = false;
|
|
18
19
|
|
|
19
20
|
function releaseAttentionHold(disposition: "notify" | "discard"): void {
|
|
@@ -22,6 +23,18 @@ export default function autoCompactExtension(pi: ExtensionAPI): void {
|
|
|
22
23
|
if (holdId) emitTauEvent(pi, "tau:attention.hold.release", { id: holdId, disposition });
|
|
23
24
|
}
|
|
24
25
|
|
|
26
|
+
function pauseSilentChecks(): void {
|
|
27
|
+
if (silentCheckPauseId) return;
|
|
28
|
+
silentCheckPauseId = `auto-compact:${++attentionHoldSequence}`;
|
|
29
|
+
emitTauEvent(pi, "tau:silent-command-runner.pause", { id: silentCheckPauseId });
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function resumeSilentChecks(disposition: "continue" | "settle"): void {
|
|
33
|
+
const pauseId = silentCheckPauseId;
|
|
34
|
+
silentCheckPauseId = undefined;
|
|
35
|
+
if (pauseId) emitTauEvent(pi, "tau:silent-command-runner.resume", { id: pauseId, disposition });
|
|
36
|
+
}
|
|
37
|
+
|
|
25
38
|
pi.on("session_start", async (_event, ctx) => {
|
|
26
39
|
const version = ++sessionVersion;
|
|
27
40
|
const settings = await loadTauExtensionSettings(ctx, autoCompactSettings);
|
|
@@ -31,6 +44,7 @@ export default function autoCompactExtension(pi: ExtensionAPI): void {
|
|
|
31
44
|
compacting = false;
|
|
32
45
|
attentionHoldSequence = 0;
|
|
33
46
|
attentionHoldId = undefined;
|
|
47
|
+
silentCheckPauseId = undefined;
|
|
34
48
|
continuationPending = false;
|
|
35
49
|
});
|
|
36
50
|
pi.on("session_shutdown", () => {
|
|
@@ -38,6 +52,7 @@ export default function autoCompactExtension(pi: ExtensionAPI): void {
|
|
|
38
52
|
armed = true;
|
|
39
53
|
compacting = false;
|
|
40
54
|
attentionHoldId = undefined;
|
|
55
|
+
silentCheckPauseId = undefined;
|
|
41
56
|
continuationPending = false;
|
|
42
57
|
});
|
|
43
58
|
pi.on("session_tree", () => {
|
|
@@ -64,6 +79,8 @@ export default function autoCompactExtension(pi: ExtensionAPI): void {
|
|
|
64
79
|
|
|
65
80
|
armed = false;
|
|
66
81
|
compacting = true;
|
|
82
|
+
// Pause before compact: compact aborts the agent, and that agent_end must not run checks.
|
|
83
|
+
pauseSilentChecks();
|
|
67
84
|
if (ctx.mode !== "print") {
|
|
68
85
|
attentionHoldId = `auto-compact:${++attentionHoldSequence}`;
|
|
69
86
|
emitTauEvent(pi, "tau:attention.hold.acquire", { id: attentionHoldId });
|
|
@@ -72,6 +89,8 @@ export default function autoCompactExtension(pi: ExtensionAPI): void {
|
|
|
72
89
|
const continueWork = (): void => {
|
|
73
90
|
if (version !== sessionVersion) return;
|
|
74
91
|
compacting = false;
|
|
92
|
+
// Keep the silent-check baseline across the new agent run started below.
|
|
93
|
+
resumeSilentChecks("continue");
|
|
75
94
|
continuationPending = true;
|
|
76
95
|
pi.sendMessage(
|
|
77
96
|
{
|
|
@@ -90,6 +109,7 @@ export default function autoCompactExtension(pi: ExtensionAPI): void {
|
|
|
90
109
|
if (version !== sessionVersion) return;
|
|
91
110
|
compacting = false;
|
|
92
111
|
if (error.name === "AbortError" || error.message === "Compaction cancelled") {
|
|
112
|
+
resumeSilentChecks("settle");
|
|
93
113
|
releaseAttentionHold("notify");
|
|
94
114
|
return;
|
|
95
115
|
}
|
|
@@ -11,6 +11,10 @@ Press `Ctrl+F` in the picker to fetch all configured remotes and refresh the
|
|
|
11
11
|
open list. Selecting a remote branch creates a local branch that tracks it.
|
|
12
12
|
Cancelling the picker does not switch branches.
|
|
13
13
|
|
|
14
|
+
After you pick a branch, Tau asks you to confirm. On confirm it switches, then
|
|
15
|
+
runs `git clean -fd` so untracked files and folders left from other branches
|
|
16
|
+
are removed. Ignored files such as `.env` stay.
|
|
17
|
+
|
|
14
18
|
Run `/branch new`, choose `feature`, `fix`, or `chore`, then enter a branch
|
|
15
19
|
name. The name is lowercased, punctuation and whitespace become hyphens, and
|
|
16
20
|
leading or trailing hyphens are removed.
|
|
@@ -18,5 +22,5 @@ leading or trailing hyphens are removed.
|
|
|
18
22
|
For example, selecting `fix` and entering `Fix login. Please` creates and
|
|
19
23
|
switches to `fix/fix-login-please`.
|
|
20
24
|
|
|
21
|
-
Cancelling either creation prompt creates nothing. Uncommitted changes
|
|
22
|
-
normal `git switch` behavior for both switching and creation.
|
|
25
|
+
Cancelling either creation prompt creates nothing. Uncommitted tracked changes
|
|
26
|
+
follow normal `git switch` behavior for both switching and creation.
|
|
@@ -99,8 +99,15 @@ async function chooseBranch(git: GitRunner, ctx: ExtensionCommandContext): Promi
|
|
|
99
99
|
});
|
|
100
100
|
if (!choice) return;
|
|
101
101
|
|
|
102
|
+
const confirmed = await ctx.ui.confirm(
|
|
103
|
+
`Switch to ${choice.name}?`,
|
|
104
|
+
"After switch, untracked files and folders will be removed. Ignored files like .env stay.",
|
|
105
|
+
);
|
|
106
|
+
if (!confirmed) return;
|
|
107
|
+
|
|
102
108
|
if (choice.kind === "local") await git.run(["switch", choice.name], { cwd: root });
|
|
103
109
|
else await git.run(["switch", "--track", "-c", choice.name, choice.upstream], { cwd: root });
|
|
110
|
+
await git.run(["clean", "-fd"], { cwd: root });
|
|
104
111
|
ctx.ui.notify(`Switched to ${choice.name}.`, "info");
|
|
105
112
|
}
|
|
106
113
|
|
|
@@ -23,3 +23,5 @@ Configure it in Tau settings under `extensions.silentCommandRunner`:
|
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
Passes are notifications only. Failures are shown in chat and sent to the agent. Tau's ready-for-input notification waits for these checks and stays quiet when a failure starts another agent turn.
|
|
26
|
+
|
|
27
|
+
When auto-compact pauses a long run to compact context, checks wait until that work chain finishes. They do not run on the compact abort, and file changes from before the compact still count.
|
|
@@ -2,7 +2,7 @@ import { readdir, stat } from "node:fs/promises";
|
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
import { type ExecResult, type ExtensionAPI, keyText, type Theme } from "@earendil-works/pi-coding-agent";
|
|
4
4
|
import { Box, Text } from "@earendil-works/pi-tui";
|
|
5
|
-
import { emitTauEvent } from "../../shared/events.ts";
|
|
5
|
+
import { emitTauEvent, onTauEvent } from "../../shared/events.ts";
|
|
6
6
|
import { matchGlob, posixPath } from "../../shared/glob.ts";
|
|
7
7
|
import { loadTauExtensionSettings } from "../../shared/settings/load.ts";
|
|
8
8
|
import { resolveProjectRoot } from "../../shared/settings/paths.ts";
|
|
@@ -84,11 +84,40 @@ export default function silentCommandRunnerExtension(pi: ExtensionAPI): void {
|
|
|
84
84
|
let chainActive = false;
|
|
85
85
|
let attentionHoldSequence = 0;
|
|
86
86
|
let attentionHoldId: string | undefined;
|
|
87
|
+
const checkPauses = new Set<string>();
|
|
88
|
+
let settleDeferred = false;
|
|
89
|
+
|
|
90
|
+
function checksPaused(): boolean {
|
|
91
|
+
return checkPauses.size > 0;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function finalizeChain(): void {
|
|
95
|
+
settleDeferred = false;
|
|
96
|
+
chainActive = false;
|
|
97
|
+
const holdId = attentionHoldId;
|
|
98
|
+
attentionHoldId = undefined;
|
|
99
|
+
if (holdId) emitTauEvent(pi, "tau:attention.hold.release", { id: holdId, disposition: "notify" });
|
|
100
|
+
}
|
|
87
101
|
|
|
88
102
|
pi.registerMessageRenderer<FailureDetails>(MESSAGE_TYPE, (message, { expanded }, theme) =>
|
|
89
103
|
renderFailure(asFailureDetails(message.details), expanded, theme),
|
|
90
104
|
);
|
|
91
105
|
|
|
106
|
+
onTauEvent(pi, "silent-command-runner.pause", "tau:silent-command-runner.pause", ({ id }) => {
|
|
107
|
+
checkPauses.add(id);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
onTauEvent(pi, "silent-command-runner.resume", "tau:silent-command-runner.resume", ({ id, disposition }) => {
|
|
111
|
+
checkPauses.delete(id);
|
|
112
|
+
if (checksPaused()) return;
|
|
113
|
+
if (disposition === "continue") {
|
|
114
|
+
// Compact will start a new agent run on the same work chain; keep baseline + hold.
|
|
115
|
+
settleDeferred = false;
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (settleDeferred || chainActive) finalizeChain();
|
|
119
|
+
});
|
|
120
|
+
|
|
92
121
|
pi.on("session_start", async (_event, ctx) => {
|
|
93
122
|
settings = normalizeSettings(await loadTauExtensionSettings(ctx, silentCommandRunnerSettings));
|
|
94
123
|
sessionActive = true;
|
|
@@ -97,6 +126,8 @@ export default function silentCommandRunnerExtension(pi: ExtensionAPI): void {
|
|
|
97
126
|
chainActive = false;
|
|
98
127
|
attentionHoldSequence = 0;
|
|
99
128
|
attentionHoldId = undefined;
|
|
129
|
+
checkPauses.clear();
|
|
130
|
+
settleDeferred = false;
|
|
100
131
|
});
|
|
101
132
|
|
|
102
133
|
pi.on("before_agent_start", async (event, ctx) => {
|
|
@@ -108,20 +139,24 @@ export default function silentCommandRunnerExtension(pi: ExtensionAPI): void {
|
|
|
108
139
|
pi.on("agent_start", async (_event, ctx) => {
|
|
109
140
|
const startingChain = !chainActive;
|
|
110
141
|
chainActive = true;
|
|
111
|
-
|
|
142
|
+
settleDeferred = false;
|
|
112
143
|
if (!settings.enabled || settings.commands.length === 0) {
|
|
113
|
-
|
|
144
|
+
if (startingChain) {
|
|
145
|
+
turnStart = Date.now();
|
|
146
|
+
turnPaths = new Set();
|
|
147
|
+
}
|
|
114
148
|
return;
|
|
115
149
|
}
|
|
116
|
-
if (startingChain)
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
150
|
+
if (!startingChain) return;
|
|
151
|
+
attentionHoldId = `silent-command-runner:${++attentionHoldSequence}`;
|
|
152
|
+
emitTauEvent(pi, "tau:attention.hold.acquire", { id: attentionHoldId });
|
|
153
|
+
turnStart = Date.now();
|
|
120
154
|
const projectRoot = await resolveProjectRoot(ctx.cwd);
|
|
121
155
|
turnPaths = new Set(await walkFiles(projectRoot));
|
|
122
156
|
});
|
|
123
157
|
|
|
124
158
|
pi.on("agent_end", async (event, ctx) => {
|
|
159
|
+
if (checksPaused()) return;
|
|
125
160
|
if (hasAbortedAssistantMessage(event.messages)) return;
|
|
126
161
|
try {
|
|
127
162
|
await runChangedCommands(ctx.cwd, turnStart, ctx.ui.notify);
|
|
@@ -131,10 +166,12 @@ export default function silentCommandRunnerExtension(pi: ExtensionAPI): void {
|
|
|
131
166
|
});
|
|
132
167
|
|
|
133
168
|
pi.on("agent_settled", () => {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
169
|
+
if (checksPaused()) {
|
|
170
|
+
// Compact aborted this run; keep chain + file baseline until resume.
|
|
171
|
+
settleDeferred = true;
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
finalizeChain();
|
|
138
175
|
});
|
|
139
176
|
|
|
140
177
|
pi.on("session_shutdown", () => {
|
|
@@ -144,6 +181,8 @@ export default function silentCommandRunnerExtension(pi: ExtensionAPI): void {
|
|
|
144
181
|
turnPaths = new Set();
|
|
145
182
|
chainActive = false;
|
|
146
183
|
attentionHoldId = undefined;
|
|
184
|
+
checkPauses.clear();
|
|
185
|
+
settleDeferred = false;
|
|
147
186
|
});
|
|
148
187
|
|
|
149
188
|
async function collectCommandFailures(
|
|
@@ -24,7 +24,9 @@ Uses Pi's native compaction before a model turn when the current context reaches
|
|
|
24
24
|
|
|
25
25
|
## branch
|
|
26
26
|
|
|
27
|
-
Adds `/branch` to create and switch Git branches from the TUI.
|
|
27
|
+
Adds `/branch` to create and switch Git branches from the TUI. Switching
|
|
28
|
+
confirms first, then removes untracked files with `git clean -fd` while keeping
|
|
29
|
+
ignored files. Press `Ctrl+F` in the picker to fetch remotes and refresh.
|
|
28
30
|
|
|
29
31
|
## cache-diagnostics
|
|
30
32
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shanepadgett/tau-agent",
|
|
3
|
-
"version": "0.39.
|
|
3
|
+
"version": "0.39.2",
|
|
4
4
|
"description": "Tau is a custom agentic harness built with pi extensions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@ast-grep/wasm": "0.45.1",
|
|
38
|
-
"@shanepadgett/tau-tui": "0.39.
|
|
38
|
+
"@shanepadgett/tau-tui": "0.39.2",
|
|
39
39
|
"@vscode/tree-sitter-wasm": "0.3.1",
|
|
40
40
|
"image-size": "2.0.2",
|
|
41
41
|
"smol-toml": "1.8.0",
|
package/shared/events.ts
CHANGED
|
@@ -16,6 +16,15 @@ export type TauAgentEvents = {
|
|
|
16
16
|
id: string;
|
|
17
17
|
disposition: "notify" | "discard";
|
|
18
18
|
};
|
|
19
|
+
/** Pause silent post-edit checks across a compact that will resume the same work chain. */
|
|
20
|
+
"tau:silent-command-runner.pause": {
|
|
21
|
+
id: string;
|
|
22
|
+
};
|
|
23
|
+
/** End a silent-check pause. continue keeps the chain open; settle finalizes a deferred settle. */
|
|
24
|
+
"tau:silent-command-runner.resume": {
|
|
25
|
+
id: string;
|
|
26
|
+
disposition: "continue" | "settle";
|
|
27
|
+
};
|
|
19
28
|
"tau:file-mutation.applied": {
|
|
20
29
|
source: "patch";
|
|
21
30
|
toolCallId: string;
|