pi-goal 0.1.1 → 0.1.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/.pi/extensions/pi-goal/index.ts +33 -11
- package/README.md +2 -0
- package/package.json +1 -1
|
@@ -21,6 +21,7 @@ type GoalState = {
|
|
|
21
21
|
type GoalEventKind = "active" | "continuation" | "paused" | "resumed" | "cleared" | "budget_limited" | "complete";
|
|
22
22
|
|
|
23
23
|
let goal: GoalState | null = null;
|
|
24
|
+
let statusBarEnabled = true;
|
|
24
25
|
let activeTurnStartedAt: number | null = null;
|
|
25
26
|
let continuationQueued = false;
|
|
26
27
|
let pendingControlPrompt: string | null = null;
|
|
@@ -118,22 +119,33 @@ function emitGoalEvent(
|
|
|
118
119
|
);
|
|
119
120
|
}
|
|
120
121
|
|
|
121
|
-
function
|
|
122
|
+
function latestStateFromSession(ctx: ExtensionContext): { goal: GoalState | null; statusBarEnabled: boolean } {
|
|
122
123
|
const entries = ctx.sessionManager.getBranch?.() ?? ctx.sessionManager.getEntries();
|
|
123
124
|
for (let i = entries.length - 1; i >= 0; i--) {
|
|
124
125
|
const entry = entries[i] as any;
|
|
125
126
|
if (entry.type === "custom" && entry.customType === CUSTOM_TYPE) {
|
|
126
|
-
return
|
|
127
|
+
return {
|
|
128
|
+
goal: entry.data?.goal ?? null,
|
|
129
|
+
statusBarEnabled: entry.data?.statusBarEnabled ?? true,
|
|
130
|
+
};
|
|
127
131
|
}
|
|
128
132
|
}
|
|
129
|
-
return null;
|
|
133
|
+
return { goal: null, statusBarEnabled: true };
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function updateStatusBar(ctx: ExtensionContext) {
|
|
137
|
+
ctx.ui.setStatus(CUSTOM_TYPE, statusBarEnabled ? statusLine(goal) ?? "" : "");
|
|
130
138
|
}
|
|
131
139
|
|
|
132
140
|
function persist(pi: ExtensionAPI, ctx: ExtensionContext, next: GoalState | null) {
|
|
133
141
|
goal = next;
|
|
134
|
-
pi.appendEntry(CUSTOM_TYPE, { goal: next });
|
|
135
|
-
|
|
136
|
-
|
|
142
|
+
pi.appendEntry(CUSTOM_TYPE, { goal: next, statusBarEnabled });
|
|
143
|
+
updateStatusBar(ctx);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function persistSettings(pi: ExtensionAPI, ctx: ExtensionContext) {
|
|
147
|
+
pi.appendEntry(CUSTOM_TYPE, { goal, statusBarEnabled });
|
|
148
|
+
updateStatusBar(ctx);
|
|
137
149
|
}
|
|
138
150
|
|
|
139
151
|
function continuationPrompt(state: GoalState): string {
|
|
@@ -286,9 +298,9 @@ export default function piGoal(pi: ExtensionAPI) {
|
|
|
286
298
|
});
|
|
287
299
|
|
|
288
300
|
pi.registerCommand("goal", {
|
|
289
|
-
description: "Set, view, pause, resume, or
|
|
301
|
+
description: "Set, view, pause, resume, clear, or configure a long-running goal",
|
|
290
302
|
getArgumentCompletions: (prefix) => {
|
|
291
|
-
const values = ["pause", "resume", "clear", "status"];
|
|
303
|
+
const values = ["pause", "resume", "clear", "status", "statusbar", "statusbar on", "statusbar off"];
|
|
292
304
|
const filtered = values.filter((value) => value.startsWith(prefix));
|
|
293
305
|
return filtered.length ? filtered.map((value) => ({ value, label: value })) : null;
|
|
294
306
|
},
|
|
@@ -298,7 +310,15 @@ export default function piGoal(pi: ExtensionAPI) {
|
|
|
298
310
|
|
|
299
311
|
if (!trimmed || trimmed === "status") {
|
|
300
312
|
if (!goal) ctx.ui.notify("Usage: /goal [--tokens 50k] <objective>", "info");
|
|
301
|
-
else ctx.ui.notify(`${statusLine(goal)}\nObjective: ${goal.objective}`, "info");
|
|
313
|
+
else ctx.ui.notify(`${statusLine(goal)}\nObjective: ${goal.objective}\nStatus bar: ${statusBarEnabled ? "on" : "off"}`, "info");
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (trimmed === "statusbar" || trimmed === "statusbar toggle" || trimmed === "statusbar on" || trimmed === "statusbar off") {
|
|
318
|
+
const [, value] = trimmed.split(/\s+/, 2);
|
|
319
|
+
statusBarEnabled = value === "on" ? true : value === "off" ? false : !statusBarEnabled;
|
|
320
|
+
persistSettings(pi, ctx);
|
|
321
|
+
ctx.ui.notify(`Goal status bar ${statusBarEnabled ? "enabled" : "disabled"}.`, "info");
|
|
302
322
|
return;
|
|
303
323
|
}
|
|
304
324
|
|
|
@@ -357,7 +377,9 @@ export default function piGoal(pi: ExtensionAPI) {
|
|
|
357
377
|
});
|
|
358
378
|
|
|
359
379
|
pi.on("session_start", (event, ctx) => {
|
|
360
|
-
|
|
380
|
+
const restored = latestStateFromSession(ctx);
|
|
381
|
+
goal = restored.goal;
|
|
382
|
+
statusBarEnabled = restored.statusBarEnabled;
|
|
361
383
|
pendingControlPrompt = null;
|
|
362
384
|
continuationQueued = false;
|
|
363
385
|
activeTurnStartedAt = null;
|
|
@@ -372,7 +394,7 @@ export default function piGoal(pi: ExtensionAPI) {
|
|
|
372
394
|
);
|
|
373
395
|
return;
|
|
374
396
|
}
|
|
375
|
-
ctx
|
|
397
|
+
updateStatusBar(ctx);
|
|
376
398
|
if (goal?.status === "active") {
|
|
377
399
|
emitGoalEvent(
|
|
378
400
|
pi,
|
package/README.md
CHANGED
|
@@ -25,6 +25,7 @@ pi install git:github.com/Michaelliv/pi-goal
|
|
|
25
25
|
/goal pause
|
|
26
26
|
/goal resume
|
|
27
27
|
/goal clear
|
|
28
|
+
/goal statusbar off
|
|
28
29
|
```
|
|
29
30
|
|
|
30
31
|
When a goal is active, the extension shows compact visible lifecycle markers like `Goal active` and `Goal continuing`; expand them with `ctrl+o` to inspect the objective and usage. The actual continuation instructions are injected into the next turn's system prompt, so the full prompt does not clutter the transcript.
|
|
@@ -38,6 +39,7 @@ The same Pi agent keeps running normal turns in the same session context until i
|
|
|
38
39
|
- `/goal pause`: stop autonomous continuation without deleting the goal
|
|
39
40
|
- `/goal resume`: reactivate a paused goal
|
|
40
41
|
- `/goal clear`: remove the goal
|
|
42
|
+
- `/goal statusbar on|off`: show or hide the footer status line
|
|
41
43
|
- `get_goal` tool: read current goal state
|
|
42
44
|
- `update_goal` tool: model can only mark the goal `complete`
|
|
43
45
|
- footer status: `Pursuing goal`, `Goal paused`, `Goal achieved`, or `Goal unmet`
|