@czottmann/pi-automode 1.4.0 → 1.5.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
CHANGED
|
@@ -141,6 +141,12 @@ GitHub Actions publishes the package to npm when a GitHub Release is published.
|
|
|
141
141
|
|
|
142
142
|
The workflow uses npm Trusted Publishing, so it does not need an npm token secret. Configure this package on npm with this repository and workflow file (`.github/workflows/publish.yml`). The workflow builds the package, runs `npm run check`, and publishes with npm provenance.
|
|
143
143
|
|
|
144
|
+
### Release tag must point at the version bump
|
|
145
|
+
|
|
146
|
+
The publish workflow checks out the commit the release tag points at and compares `package.json` against the tag name. **The tag must point at a commit where `package.json` already carries the new version.** Concretely: commit the version bump (`chore: release X.Y.Z`), push `main`, then create the GitHub release targeting that pushed commit. Creating the release before pushing the version bump — or targeting a commit that still has the old version — fails the `Check release tag` step with `Release tag (vX.Y.Z) does not match package.json version (x.y.z)`.
|
|
147
|
+
|
|
148
|
+
If the tag was cut against the wrong commit, fix it by force-moving it to the version-bump commit and pushing, then trigger the workflow via `gh workflow run publish.yml --ref vX.Y.Z` (the `release` event fires on tag creation; re-running a failed `release`-triggered run reuses the original ref and won't pick up the moved tag).
|
|
149
|
+
|
|
144
150
|
## Author
|
|
145
151
|
|
|
146
152
|
Carlo Zottmann, <carlo@zottmann.dev>
|
|
@@ -69,6 +69,7 @@ export function createPiAutomode(options: PiAutomodeOptions = {}) {
|
|
|
69
69
|
let state: AutoModeState = {
|
|
70
70
|
checkedActions: 0,
|
|
71
71
|
blockedActions: 0,
|
|
72
|
+
classifierChecks: 0,
|
|
72
73
|
recentDenials: [],
|
|
73
74
|
};
|
|
74
75
|
let loadedContext = "";
|
|
@@ -215,6 +216,7 @@ export function createPiAutomode(options: PiAutomodeOptions = {}) {
|
|
|
215
216
|
if (event.toolName === "write" || event.toolName === "edit") {
|
|
216
217
|
const path = resolveInputPath(ctx.cwd, input.path);
|
|
217
218
|
if (path && isProtectedPath(path, ctx.cwd, cfg.protectedPaths)) {
|
|
219
|
+
state.classifierChecks += 1;
|
|
218
220
|
const decision = await classify(ctx, cfg, summary, loadedContext);
|
|
219
221
|
if (decision.decision === "allow") {
|
|
220
222
|
state.lastDecision = "allow";
|
|
@@ -233,6 +235,7 @@ export function createPiAutomode(options: PiAutomodeOptions = {}) {
|
|
|
233
235
|
}
|
|
234
236
|
}
|
|
235
237
|
|
|
238
|
+
state.classifierChecks += 1;
|
|
236
239
|
const decision = await classify(ctx, cfg, summary, loadedContext);
|
|
237
240
|
if (decision.decision === "allow") {
|
|
238
241
|
state.lastDecision = "allow";
|
|
@@ -295,6 +298,7 @@ export function createPiAutomode(options: PiAutomodeOptions = {}) {
|
|
|
295
298
|
state = {
|
|
296
299
|
checkedActions: 0,
|
|
297
300
|
blockedActions: 0,
|
|
301
|
+
classifierChecks: 0,
|
|
298
302
|
recentDenials: [],
|
|
299
303
|
enabledOverride: state.enabledOverride,
|
|
300
304
|
};
|
|
@@ -15,15 +15,12 @@ export function statusLine(
|
|
|
15
15
|
state: AutoModeState,
|
|
16
16
|
): string {
|
|
17
17
|
const enabled = state.enabledOverride ?? config.enabled;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (last) line += ` · last: ${truncateMiddle(last.reason, 60)}`;
|
|
25
|
-
}
|
|
26
|
-
return line;
|
|
18
|
+
const circle = enabled ? "●" : "○";
|
|
19
|
+
const allowed = state.checkedActions - state.blockedActions;
|
|
20
|
+
const classifier = state.classifierChecks > 0
|
|
21
|
+
? ` c:${state.classifierChecks}`
|
|
22
|
+
: "";
|
|
23
|
+
return `AM${circle} a:${allowed} d:${state.blockedActions}${classifier}`;
|
|
27
24
|
}
|
|
28
25
|
|
|
29
26
|
export function statusText(
|
|
@@ -35,6 +32,7 @@ export function statusText(
|
|
|
35
32
|
`classifier: ${config.classifierModel ?? "current session model"}`,
|
|
36
33
|
`checked actions: ${state.checkedActions}`,
|
|
37
34
|
`blocked actions: ${state.blockedActions}`,
|
|
35
|
+
`classifier checks: ${state.classifierChecks}`,
|
|
38
36
|
`permissions.deny rules: ${config.permissionDeny.length}`,
|
|
39
37
|
`permissions.ask rules: ${config.permissionAsk.length}`,
|
|
40
38
|
`environment entries: ${config.environment.length}`,
|
|
@@ -90,10 +88,11 @@ export function restoreState(ctx: ExtensionContext): AutoModeState {
|
|
|
90
88
|
lastReason: entry.data.lastReason,
|
|
91
89
|
checkedActions: entry.data.checkedActions ?? 0,
|
|
92
90
|
blockedActions: entry.data.blockedActions ?? 0,
|
|
91
|
+
classifierChecks: entry.data.classifierChecks ?? 0,
|
|
93
92
|
recentDenials: Array.isArray(entry.data.recentDenials)
|
|
94
93
|
? entry.data.recentDenials.slice(-DENIAL_HISTORY_LIMIT)
|
|
95
94
|
: [],
|
|
96
95
|
};
|
|
97
96
|
}
|
|
98
|
-
return { checkedActions: 0, blockedActions: 0, recentDenials: [] };
|
|
97
|
+
return { checkedActions: 0, blockedActions: 0, classifierChecks: 0, recentDenials: [] };
|
|
99
98
|
}
|