@zhushanwen/pi-goal 0.1.3 → 0.1.4
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/package.json +1 -1
- package/src/budget.ts +1 -1
- package/src/index.ts +6 -11
- package/src/templates.ts +3 -3
- package/src/tool-handler.ts +2 -2
- package/src/widget.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhushanwen/pi-goal",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Codex-style /goal command for Pi — persistent goal-driven autonomous loop with evidence-based completion, token/time budgets, blocked detection, and steering templates.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
package/src/budget.ts
CHANGED
|
@@ -147,7 +147,7 @@ export function checkProgress(state: GoalRuntimeState, tasksCompletedAtStart: nu
|
|
|
147
147
|
return {
|
|
148
148
|
allTasksDone: totalCount > 0 && incomplete.length === 0 && completedCount > 0,
|
|
149
149
|
noTasksCreated: totalCount === 0,
|
|
150
|
-
maxTurnsReached: state.
|
|
150
|
+
maxTurnsReached: state.currentTurnIndex >= state.budget.maxTurns,
|
|
151
151
|
isStalled: progressThisRound === 0,
|
|
152
152
|
budgetTight: Boolean(
|
|
153
153
|
state.budget.tokenBudget &&
|
package/src/index.ts
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* 健壮性保障:
|
|
13
13
|
* - goalId snapshot 防止旧回调操作新 goal
|
|
14
14
|
* - 时间累计统一由 persistState 管理,无双写
|
|
15
|
-
* -
|
|
15
|
+
* - before_agent_start 注入 context,agent_end 负责 continuation(预算检查/进度评估/续跑)
|
|
16
16
|
* - deserializeState 向后兼容旧格式
|
|
17
17
|
*/
|
|
18
18
|
|
|
@@ -159,7 +159,7 @@ async function handleGoalCommand(pi: ExtensionAPI, session: GoalSession, args: s
|
|
|
159
159
|
const lines = [
|
|
160
160
|
`Objective: ${session.state.objective}`,
|
|
161
161
|
`Status: ${session.state.status}`,
|
|
162
|
-
`Turn: ${session.state.
|
|
162
|
+
`Turn: ${session.state.currentTurnIndex}/${session.state.budget.maxTurns}`,
|
|
163
163
|
`Tasks: ${completed}/${total} completed`,
|
|
164
164
|
`Stall turns: ${session.state.stallCount}`,
|
|
165
165
|
`Time elapsed: ${Math.floor(elapsed / SECONDS_PER_MINUTE)}m${Math.floor(elapsed % SECONDS_PER_MINUTE)}s`,
|
|
@@ -306,6 +306,7 @@ Objective: ${session.state.objective}`,
|
|
|
306
306
|
session.state.tasks = [];
|
|
307
307
|
session.state.stallCount = 0;
|
|
308
308
|
session.state.turnCount = 0;
|
|
309
|
+
session.state.currentTurnIndex = 0;
|
|
309
310
|
session.state.lastProgressTurn = 0;
|
|
310
311
|
session.state.budgetLimitSteeringSent = false;
|
|
311
312
|
session.state.budgetWarning70Sent = false;
|
|
@@ -510,7 +511,7 @@ async function handleAgentEnd(pi: ExtensionAPI, session: GoalSession, ctx: Exten
|
|
|
510
511
|
if (checkStale()) return;
|
|
511
512
|
updateWidget(session, ctx);
|
|
512
513
|
ctx.ui.notify(
|
|
513
|
-
`Objective completed ✓ (${getCompletedCount(session.state.tasks)}/${session.state.tasks.length} tasks, ${session.state.
|
|
514
|
+
`Objective completed ✓ (${getCompletedCount(session.state.tasks)}/${session.state.tasks.length} tasks, ${session.state.currentTurnIndex} turns)`,
|
|
514
515
|
"info",
|
|
515
516
|
);
|
|
516
517
|
return;
|
|
@@ -526,12 +527,6 @@ async function handleAgentEnd(pi: ExtensionAPI, session: GoalSession, ctx: Exten
|
|
|
526
527
|
|
|
527
528
|
if (!isActiveStatus(session.state.status)) return;
|
|
528
529
|
|
|
529
|
-
// 防重入
|
|
530
|
-
if (session.hasPendingInjection) {
|
|
531
|
-
session.hasPendingInjection = false;
|
|
532
|
-
return;
|
|
533
|
-
}
|
|
534
|
-
|
|
535
530
|
if (checkStale()) return;
|
|
536
531
|
|
|
537
532
|
// ── 预算策略(集中检查)──
|
|
@@ -595,7 +590,7 @@ async function handleAgentEnd(pi: ExtensionAPI, session: GoalSession, ctx: Exten
|
|
|
595
590
|
if (checkStale()) return;
|
|
596
591
|
updateWidget(session, ctx);
|
|
597
592
|
ctx.ui.notify(
|
|
598
|
-
`All tasks completed, Goal auto-closed. (${progress.completedCount}/${progress.totalCount} tasks, ${session.state.
|
|
593
|
+
`All tasks completed, Goal auto-closed. (${progress.completedCount}/${progress.totalCount} tasks, ${session.state.currentTurnIndex} turns)`,
|
|
599
594
|
"info",
|
|
600
595
|
);
|
|
601
596
|
return;
|
|
@@ -666,7 +661,7 @@ async function handleAgentEnd(pi: ExtensionAPI, session: GoalSession, ctx: Exten
|
|
|
666
661
|
session.state.stallCount++;
|
|
667
662
|
} else {
|
|
668
663
|
session.state.stallCount = 0;
|
|
669
|
-
session.state.lastProgressTurn = session.state.
|
|
664
|
+
session.state.lastProgressTurn = session.state.currentTurnIndex;
|
|
670
665
|
}
|
|
671
666
|
|
|
672
667
|
if (session.state.stallCount >= session.state.budget.maxStallTurns) {
|
package/src/templates.ts
CHANGED
|
@@ -42,7 +42,7 @@ export function continuationPrompt(state: GoalRuntimeState): string {
|
|
|
42
42
|
|
|
43
43
|
return (
|
|
44
44
|
`<goal_context>\n` +
|
|
45
|
-
`[GOAL] Turn ${state.
|
|
45
|
+
`[GOAL] Turn ${state.currentTurnIndex}/${state.budget.maxTurns}${budgetLine}${stallLine}\n` +
|
|
46
46
|
`<objective>${objective}</objective>\n` +
|
|
47
47
|
`${taskLine}\n` +
|
|
48
48
|
`Rules: create_tasks→update_tasks(evidence)→complete_goal(evidence). blocked→report_blocked(reason). subtask: add_subtasks/update_subtasks (replaces todo tool).\n` +
|
|
@@ -117,7 +117,7 @@ export function contextInjectionPrompt(state: GoalRuntimeState): string {
|
|
|
117
117
|
`[GOAL mode activated]\n\n` +
|
|
118
118
|
`<objective>\n${objective}\n</objective>\n` +
|
|
119
119
|
`Status: ${state.status}\n` +
|
|
120
|
-
`Turn: ${state.
|
|
120
|
+
`Turn: ${state.currentTurnIndex}/${state.budget.maxTurns}${budgetInfo}\n` +
|
|
121
121
|
`Task progress: ${completedCount}/${total}\n\n` +
|
|
122
122
|
`Strict rules:\n` +
|
|
123
123
|
`1. First step: call goal_manager's create_tasks to decompose tasks (if not yet created)\n` +
|
|
@@ -160,7 +160,7 @@ export function stalenessReminderPrompt(
|
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
lines.push(`\nObjective: ${objective}`);
|
|
163
|
-
lines.push(`Turn: ${state.
|
|
163
|
+
lines.push(`Turn: ${state.currentTurnIndex}/${state.budget.maxTurns}`);
|
|
164
164
|
lines.push("</goal_context>");
|
|
165
165
|
|
|
166
166
|
return lines.join("\n");
|
package/src/tool-handler.ts
CHANGED
|
@@ -193,7 +193,7 @@ export function makeGoalResult(session: GoalSession, text: string) {
|
|
|
193
193
|
meta: {
|
|
194
194
|
...(state.budget.tokenBudget ? { "Token": `${state.tokensUsed}/${state.budget.tokenBudget}` } : {}),
|
|
195
195
|
...(state.budget.timeBudgetMinutes ? { "Time": `${Math.floor(getElapsedTimeSeconds(state) / SECONDS_PER_MINUTE)}m/${state.budget.timeBudgetMinutes}m` } : {}),
|
|
196
|
-
"Turn": `${state.
|
|
196
|
+
"Turn": `${state.currentTurnIndex}/${state.budget.maxTurns}`,
|
|
197
197
|
},
|
|
198
198
|
},
|
|
199
199
|
},
|
|
@@ -333,7 +333,7 @@ export async function executeGoalAction(
|
|
|
333
333
|
writeGoalHistoryEntry(pi, session);
|
|
334
334
|
persistGoalState(pi, session, ctx);
|
|
335
335
|
const budgetReport: string[] = [];
|
|
336
|
-
budgetReport.push(`Total turns: ${state.
|
|
336
|
+
budgetReport.push(`Total turns: ${state.currentTurnIndex}`);
|
|
337
337
|
budgetReport.push(`Tasks completed: ${getCompletedCount(state.tasks)}/${state.tasks.length}`);
|
|
338
338
|
if (state.budget.tokenBudget) {
|
|
339
339
|
budgetReport.push(`Token usage: ${state.tokensUsed}/${state.budget.tokenBudget}`);
|
package/src/widget.ts
CHANGED
|
@@ -39,7 +39,7 @@ export function renderStatusLine(state: GoalRuntimeState, th: ThemeLike): string
|
|
|
39
39
|
const completedCount = getCompletedCount(state.tasks);
|
|
40
40
|
const total = state.tasks.length;
|
|
41
41
|
|
|
42
|
-
let text = th.fg("accent", `◆ Goal`) + th.fg("muted", ` ${state.
|
|
42
|
+
let text = th.fg("accent", `◆ Goal`) + th.fg("muted", ` ${state.currentTurnIndex}/${state.budget.maxTurns}`);
|
|
43
43
|
|
|
44
44
|
if (total > 0) {
|
|
45
45
|
text += th.fg("muted", ` | ${completedCount}/${total} tasks`);
|