@umgbhalla/pi-gigaplan 0.1.2 → 0.1.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/extensions/index.ts +71 -2
- package/package.json +1 -1
package/extensions/index.ts
CHANGED
|
@@ -96,6 +96,11 @@ function inferNextSteps(state: PlanState): string[] {
|
|
|
96
96
|
case STATE_PLANNED: return ["critique"];
|
|
97
97
|
case STATE_CRITIQUED: return ["evaluate"];
|
|
98
98
|
case STATE_EVALUATED: {
|
|
99
|
+
const lastHistory = state.history[state.history.length - 1];
|
|
100
|
+
if (lastHistory?.step === "gate" && lastHistory.result === "failed") {
|
|
101
|
+
return ["integrate"];
|
|
102
|
+
}
|
|
103
|
+
|
|
99
104
|
const rec = (state.last_evaluation as Record<string, unknown>)?.recommendation as string;
|
|
100
105
|
if (rec === "CONTINUE") return ["integrate"];
|
|
101
106
|
if (rec === "SKIP") return ["gate"];
|
|
@@ -108,6 +113,19 @@ function inferNextSteps(state: PlanState): string[] {
|
|
|
108
113
|
}
|
|
109
114
|
}
|
|
110
115
|
|
|
116
|
+
const LLM_STEPS = new Set(["clarify", "plan", "critique", "integrate", "execute", "review"]);
|
|
117
|
+
const LOGIC_STEPS = new Set(["evaluate", "gate"]);
|
|
118
|
+
|
|
119
|
+
function requireAllowedStep(state: PlanState, step: string): void {
|
|
120
|
+
const nextSteps = inferNextSteps(state);
|
|
121
|
+
if (!nextSteps.includes(step)) {
|
|
122
|
+
throw new GigaplanError(
|
|
123
|
+
"invalid_state",
|
|
124
|
+
`Step "${step}" is not valid from state ${state.current_state}. Expected next step: ${nextSteps.join(", ") || "none"}`,
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
111
129
|
// ---------------------------------------------------------------------------
|
|
112
130
|
// Step handlers
|
|
113
131
|
// ---------------------------------------------------------------------------
|
|
@@ -194,6 +212,7 @@ function processStepOutput(
|
|
|
194
212
|
|
|
195
213
|
switch (step) {
|
|
196
214
|
case "clarify": {
|
|
215
|
+
requireState(state, STATE_INITIALIZED);
|
|
197
216
|
state.clarification = payload;
|
|
198
217
|
state.current_state = STATE_CLARIFIED;
|
|
199
218
|
state.history.push({
|
|
@@ -214,6 +233,9 @@ function processStepOutput(
|
|
|
214
233
|
|
|
215
234
|
case "plan":
|
|
216
235
|
case "integrate": {
|
|
236
|
+
if (step === "plan") requireState(state, STATE_CLARIFIED);
|
|
237
|
+
else requireState(state, STATE_EVALUATED);
|
|
238
|
+
|
|
217
239
|
const newIteration = iteration + 1;
|
|
218
240
|
state.iteration = newIteration;
|
|
219
241
|
|
|
@@ -276,6 +298,8 @@ function processStepOutput(
|
|
|
276
298
|
}
|
|
277
299
|
|
|
278
300
|
case "critique": {
|
|
301
|
+
requireState(state, STATE_PLANNED);
|
|
302
|
+
|
|
279
303
|
// Save critique artifact
|
|
280
304
|
const critiqueFile = `critique_v${iteration}.json`;
|
|
281
305
|
atomicWriteJson(path.join(planDir, critiqueFile), payload);
|
|
@@ -336,6 +360,7 @@ function processStepOutput(
|
|
|
336
360
|
}
|
|
337
361
|
|
|
338
362
|
case "execute": {
|
|
363
|
+
requireState(state, STATE_GATED);
|
|
339
364
|
atomicWriteJson(path.join(planDir, "execution.json"), payload);
|
|
340
365
|
state.current_state = STATE_EXECUTED;
|
|
341
366
|
state.history.push({
|
|
@@ -357,6 +382,7 @@ function processStepOutput(
|
|
|
357
382
|
}
|
|
358
383
|
|
|
359
384
|
case "review": {
|
|
385
|
+
requireState(state, STATE_EXECUTED);
|
|
360
386
|
atomicWriteJson(path.join(planDir, "review.json"), payload);
|
|
361
387
|
state.current_state = STATE_DONE;
|
|
362
388
|
state.history.push({
|
|
@@ -492,10 +518,27 @@ export default function gigaplanExtension(pi: ExtensionAPI) {
|
|
|
492
518
|
// Widget state
|
|
493
519
|
let activePlan: { name: string; state: string; step: string } | null = null;
|
|
494
520
|
|
|
521
|
+
function syncActivePlan(root: string): void {
|
|
522
|
+
try {
|
|
523
|
+
const [, state] = loadPlan(root);
|
|
524
|
+
if (TERMINAL_STATES.has(state.current_state)) {
|
|
525
|
+
activePlan = null;
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
activePlan = {
|
|
529
|
+
name: state.name,
|
|
530
|
+
state: state.current_state,
|
|
531
|
+
step: inferNextSteps(state)[0] ?? "done",
|
|
532
|
+
};
|
|
533
|
+
} catch {
|
|
534
|
+
activePlan = null;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
495
538
|
function updateWidget(ctx?: any) {
|
|
496
539
|
if (!ctx?.ui) return;
|
|
497
540
|
if (!activePlan) {
|
|
498
|
-
ctx.ui.setStatus("gigaplan",
|
|
541
|
+
ctx.ui.setStatus("gigaplan", undefined);
|
|
499
542
|
return;
|
|
500
543
|
}
|
|
501
544
|
ctx.ui.setStatus(
|
|
@@ -504,6 +547,21 @@ export default function gigaplanExtension(pi: ExtensionAPI) {
|
|
|
504
547
|
);
|
|
505
548
|
}
|
|
506
549
|
|
|
550
|
+
pi.on("session_start", (_event, ctx) => {
|
|
551
|
+
syncActivePlan(ctx.cwd);
|
|
552
|
+
updateWidget(ctx);
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
pi.on("session_switch", (_event, ctx) => {
|
|
556
|
+
syncActivePlan(ctx.cwd);
|
|
557
|
+
updateWidget(ctx);
|
|
558
|
+
});
|
|
559
|
+
|
|
560
|
+
pi.on("session_shutdown", (_event, ctx) => {
|
|
561
|
+
activePlan = null;
|
|
562
|
+
updateWidget(ctx);
|
|
563
|
+
});
|
|
564
|
+
|
|
507
565
|
// ── /gigaplan command ──
|
|
508
566
|
pi.registerCommand("gigaplan", {
|
|
509
567
|
description: "Start a structured planning session: /gigaplan <idea>",
|
|
@@ -572,7 +630,7 @@ For each LLM step, use the \`gigaplan_step\` tool which returns the subagent con
|
|
|
572
630
|
|
|
573
631
|
Start now with the **clarify** step.`;
|
|
574
632
|
|
|
575
|
-
pi.sendUserMessage(orchestrationPrompt);
|
|
633
|
+
pi.sendUserMessage(orchestrationPrompt, { deliverAs: "followUp" });
|
|
576
634
|
},
|
|
577
635
|
});
|
|
578
636
|
|
|
@@ -591,6 +649,10 @@ Start now with the **clarify** step.`;
|
|
|
591
649
|
async execute(_id, params) {
|
|
592
650
|
try {
|
|
593
651
|
const state = readJson(path.join(params.planDir, "state.json")) as PlanState;
|
|
652
|
+
if (!LLM_STEPS.has(params.step)) {
|
|
653
|
+
throw new GigaplanError("unsupported_step", `Unknown LLM step: ${params.step}`);
|
|
654
|
+
}
|
|
655
|
+
requireAllowedStep(state, params.step);
|
|
594
656
|
const config = buildStepConfig(params.step, state, params.planDir);
|
|
595
657
|
|
|
596
658
|
return {
|
|
@@ -640,6 +702,11 @@ Start now with the **clarify** step.`;
|
|
|
640
702
|
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
641
703
|
try {
|
|
642
704
|
const state = readJson(path.join(params.planDir, "state.json")) as PlanState;
|
|
705
|
+
if (!LLM_STEPS.has(params.step) && !LOGIC_STEPS.has(params.step)) {
|
|
706
|
+
throw new GigaplanError("unsupported_step", `Unknown step: ${params.step}`);
|
|
707
|
+
}
|
|
708
|
+
requireAllowedStep(state, params.step);
|
|
709
|
+
|
|
643
710
|
let result: StepResult;
|
|
644
711
|
|
|
645
712
|
if (params.step === "evaluate") {
|
|
@@ -805,6 +872,7 @@ Start now with the **clarify** step.`;
|
|
|
805
872
|
}
|
|
806
873
|
|
|
807
874
|
case "force-proceed": {
|
|
875
|
+
requireState(state, STATE_EVALUATED);
|
|
808
876
|
state.current_state = STATE_GATED;
|
|
809
877
|
state.meta.user_approved_gate = true;
|
|
810
878
|
state.history.push({
|
|
@@ -820,6 +888,7 @@ Start now with the **clarify** step.`;
|
|
|
820
888
|
}
|
|
821
889
|
|
|
822
890
|
case "skip": {
|
|
891
|
+
requireState(state, STATE_EVALUATED);
|
|
823
892
|
state.last_evaluation = { recommendation: "SKIP" };
|
|
824
893
|
state.current_state = STATE_EVALUATED;
|
|
825
894
|
state.history.push({
|