pi-goal-x 0.31.2 → 0.31.3
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 +1 -1
- package/assets/badge-dark.svg +2 -2
- package/assets/badge-light.svg +2 -2
- package/extensions/goal-events.ts +12 -1
- package/extensions/goal-task-confirmation.ts +15 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<a href="https://pi.dev/packages?type=extension" target="_blank" rel="noopener noreferrer">
|
|
7
7
|
<picture>
|
|
8
8
|
<source media="(prefers-color-scheme: dark)" srcset="assets/badge-dark.svg">
|
|
9
|
-
<img src="assets/badge-light.svg" alt="TOP 0.3% of Pi coding agent extensions: #7 of 3,
|
|
9
|
+
<img src="assets/badge-light.svg" alt="TOP 0.3% of Pi coding agent extensions: #7 of 3,200 by downloads · Sep 14, 2026 (best recorded rank)" width="480">
|
|
10
10
|
</picture>
|
|
11
11
|
</a>
|
|
12
12
|
</div>
|
package/assets/badge-dark.svg
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="480" height="54" viewBox="0 0 480 54" role="img" aria-label="TOP 0.3% of Pi coding agent extensions: #7 of 3,
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="480" height="54" viewBox="0 0 480 54" role="img" aria-label="TOP 0.3% of Pi coding agent extensions: #7 of 3,200 by downloads · Sep 14, 2026 (best recorded rank)">
|
|
2
2
|
<!-- Dark mode -->
|
|
3
3
|
<style>
|
|
4
4
|
.frame { fill: #14181f; stroke: #2a3040; stroke-width: 1; }
|
|
@@ -13,6 +13,6 @@
|
|
|
13
13
|
<text class="rank" x="18" y="34">TOP 0.3%</text>
|
|
14
14
|
<line class="divider" x1="128" y1="13" x2="128" y2="41"/>
|
|
15
15
|
<text class="label" x="143" y="25">of Pi coding agent extensions</text>
|
|
16
|
-
<text class="meta" x="143" y="41">#7 of 3,
|
|
16
|
+
<text class="meta" x="143" y="41">#7 of 3,200 by downloads · Sep 14, 2026</text>
|
|
17
17
|
</a>
|
|
18
18
|
</svg>
|
package/assets/badge-light.svg
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="480" height="54" viewBox="0 0 480 54" role="img" aria-label="TOP 0.3% of Pi coding agent extensions: #7 of 3,
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="480" height="54" viewBox="0 0 480 54" role="img" aria-label="TOP 0.3% of Pi coding agent extensions: #7 of 3,200 by downloads · Sep 14, 2026 (best recorded rank)">
|
|
2
2
|
<!-- Light mode -->
|
|
3
3
|
<style>
|
|
4
4
|
.frame { fill: #f6f8fa; stroke: #d0d7de; stroke-width: 1; }
|
|
@@ -13,6 +13,6 @@
|
|
|
13
13
|
<text class="rank" x="18" y="34">TOP 0.3%</text>
|
|
14
14
|
<line class="divider" x1="128" y1="13" x2="128" y2="41"/>
|
|
15
15
|
<text class="label" x="143" y="25">of Pi coding agent extensions</text>
|
|
16
|
-
<text class="meta" x="143" y="41">#7 of 3,
|
|
16
|
+
<text class="meta" x="143" y="41">#7 of 3,200 by downloads · Sep 14, 2026</text>
|
|
17
17
|
</a>
|
|
18
18
|
</svg>
|
|
@@ -86,6 +86,11 @@ export function registerGoalEvents(core: GoalCore): void {
|
|
|
86
86
|
const { pi } = core;
|
|
87
87
|
let continuationAfterSettleFor: string | null = null;
|
|
88
88
|
let networkErrorRecoveryAfterSettleFor: string | null = null;
|
|
89
|
+
// Run-scoped empty-turn gate: turn_start resets the per-turn flag, so a text-only
|
|
90
|
+
// last turn after earlier work must not wipe the run. before_agent_start starts a
|
|
91
|
+
// new run. agent_settled must not auto-continue a run that did no goal work, or
|
|
92
|
+
// empty replies ("Paused. No action.") loop forever.
|
|
93
|
+
let goalWorkThisRun = false;
|
|
89
94
|
|
|
90
95
|
pi.on("context", async (event) => {
|
|
91
96
|
const filtered = filterGoalSessionContext(event.messages);
|
|
@@ -128,9 +133,10 @@ export function registerGoalEvents(core: GoalCore): void {
|
|
|
128
133
|
`End the turn with a brief summary and yield to the user.`,
|
|
129
134
|
};
|
|
130
135
|
}
|
|
131
|
-
// Track for #4 empty-turn gate.
|
|
136
|
+
// Track for #4 empty-turn gate (per-turn and per-run).
|
|
132
137
|
if (isMeaningfulProgressToolCall(event.toolName, asRecord(event)?.args)) {
|
|
133
138
|
core.goalWorkToolCalledThisTurn = true;
|
|
139
|
+
goalWorkThisRun = true;
|
|
134
140
|
// Issue #26: record a meaningful work attempt against armed Oracle
|
|
135
141
|
// advice. get_goal / echo-only reads are excluded upstream by
|
|
136
142
|
// isMeaningfulProgressToolCall.
|
|
@@ -339,6 +345,7 @@ export function registerGoalEvents(core: GoalCore): void {
|
|
|
339
345
|
});
|
|
340
346
|
|
|
341
347
|
pi.on("before_agent_start", async (event, ctx) => {
|
|
348
|
+
goalWorkThisRun = false;
|
|
342
349
|
core.advanceTurnSeq();
|
|
343
350
|
if (!hasActiveDraft(core)) core.installGoalToolProfile(!loadGoalSettings(ctx.cwd).disableTasks);
|
|
344
351
|
const currentSystemPrompt = () => ctx.getSystemPrompt?.() || event.systemPrompt;
|
|
@@ -524,6 +531,10 @@ export function registerGoalEvents(core: GoalCore): void {
|
|
|
524
531
|
core.runtime.clearNetworkErrorBackoff();
|
|
525
532
|
core.persist(ctx);
|
|
526
533
|
core.updateUI(ctx);
|
|
534
|
+
// Empty-turn gate: agent_end clears any turn_end continuation timer, then
|
|
535
|
+
// agent_settled re-queues with force=true. Without this check, a no-tool
|
|
536
|
+
// reply (chat, or "Paused. No action." after resume) loops forever.
|
|
537
|
+
if (!goalWorkThisRun) return;
|
|
527
538
|
// agent_end runs before pi finishes retries, compaction, terminating-tool
|
|
528
539
|
// settlement, and queued messages. Starting the continuation timer here
|
|
529
540
|
// can poll a stale busy context for minutes on pi 0.84. agent_settled is
|
|
@@ -33,21 +33,24 @@ export interface TaskConfirmationResult {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
export async function showTaskConfirmation(ctx: ExtensionContext, proposalText: string): Promise<TaskConfirmationResult> {
|
|
36
|
-
|
|
37
|
-
if (
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (
|
|
41
|
-
} else if (!ctx.hasUI || autoConfirmEnv === "1") {
|
|
42
|
-
// Headless default, or forced auto-confirm even with a UI.
|
|
43
|
-
return { decision: "confirm" };
|
|
36
|
+
if (process.env.PI_GOAL_AUTO_CONFIRM === "1") return { decision: "confirm" };
|
|
37
|
+
if (!ctx.hasUI) return { decision: process.env.PI_GOAL_AUTO_CONFIRM === "0" ? "cancel" : "confirm" };
|
|
38
|
+
if (ctx.mode !== "rpc" && typeof ctx.ui.custom === "function") {
|
|
39
|
+
const result = await showTaskListConfirmationDialog(ctx, proposalText);
|
|
40
|
+
if (result) return result;
|
|
44
41
|
}
|
|
45
|
-
|
|
42
|
+
if (typeof ctx.ui.select !== "function") return { decision: "cancel" };
|
|
43
|
+
const answer = await ctx.ui.select(`Task list confirmation\n\n${proposalText}`, ["Confirm task list", "Keep current tasks"]);
|
|
44
|
+
return { decision: answer === "Confirm task list" ? "confirm" : "cancel" };
|
|
46
45
|
}
|
|
47
46
|
|
|
48
|
-
async function showTaskListConfirmationDialog(ctx: ExtensionContext, proposalText: string): Promise<TaskConfirmationResult> {
|
|
49
|
-
return await ctx.ui.custom<TaskConfirmationResult>(
|
|
50
|
-
(tui: TUI, theme: Theme, _keybindings: unknown, done: (result: TaskConfirmationResult) => void): Component => {
|
|
47
|
+
async function showTaskListConfirmationDialog(ctx: ExtensionContext, proposalText: string): Promise<TaskConfirmationResult | undefined> {
|
|
48
|
+
return await ctx.ui.custom<TaskConfirmationResult | undefined>(
|
|
49
|
+
(tui: TUI, theme: Theme, _keybindings: unknown, done: (result: TaskConfirmationResult | undefined) => void): Component => {
|
|
50
|
+
if (!tui || typeof tui.getShowHardwareCursor !== "function" || typeof tui.setShowHardwareCursor !== "function" || typeof tui.requestRender !== "function") {
|
|
51
|
+
done(undefined);
|
|
52
|
+
return { render: () => [], invalidate: () => {} };
|
|
53
|
+
}
|
|
51
54
|
const wasHardwareCursorShown = tui.getShowHardwareCursor();
|
|
52
55
|
tui.setShowHardwareCursor(false);
|
|
53
56
|
// Pause pi's working spinner for the dialog duration: its ~80ms re-renders
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-goal-x",
|
|
3
|
-
"version": "0.31.
|
|
3
|
+
"version": "0.31.3",
|
|
4
4
|
"description": "Adds /goal to pi: conversational goal planning, flexible or ordered goals, persistent progress, and an independent completion auditor.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "pi-goal-x contributors",
|