@zhushanwen/pi-plan 0.2.0 → 0.2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhushanwen/pi-plan",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Lightweight plan mode for Pi coding agent",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -76,7 +76,6 @@ describe("handlePlanComplete", () => {
76
76
  expect(pi.sendUserMessage).toHaveBeenCalledWith(expect.any(String), { deliverAs: "steer" });
77
77
  expect((pi as unknown as Record<string, unknown>).__goalInit).toHaveBeenCalledWith(
78
78
  expect.any(String),
79
- expect.arrayContaining([expect.any(String)]),
80
79
  undefined,
81
80
  ctx,
82
81
  );
@@ -107,7 +106,6 @@ describe("handlePlanComplete", () => {
107
106
  expect(ctx.ui.notify).not.toHaveBeenCalled();
108
107
  expect((pi as unknown as Record<string, unknown>).__goalInit).toHaveBeenCalledWith(
109
108
  expect.any(String),
110
- expect.arrayContaining([expect.any(String)]),
111
109
  undefined,
112
110
  ctx,
113
111
  );
package/src/command.ts CHANGED
@@ -175,3 +175,24 @@ function handleEnterPlanMode(
175
175
  `3. After plan complete: check subagent capability → suggest goal + wave or single-agent execution.`,
176
176
  );
177
177
  }
178
+
179
+ /**
180
+ * Programmatic entry to start plan mode (for `pi.__planStart`).
181
+ *
182
+ * Mirrors the `/plan` command's enter logic. Returns false if plan mode is
183
+ * already active (caller can then surface a message or wait).
184
+ *
185
+ * @returns true if plan mode started; false if already active
186
+ */
187
+ export function startPlanMode(
188
+ pi: ExtensionAPI,
189
+ sessions: PlanSessionMap,
190
+ ctx: ExtensionContext,
191
+ requirement: string,
192
+ ): boolean {
193
+ const sessionId = ctx.sessionManager.getSessionId();
194
+ const state = getPlanState(sessions, sessionId, ctx);
195
+ if (state.isActive) return false;
196
+ handleEnterPlanMode(pi, sessions, sessionId, ctx, state, requirement);
197
+ return true;
198
+ }
package/src/compact.ts CHANGED
@@ -76,11 +76,12 @@ export function detectGoalCapability(pi: ExtensionAPI): boolean {
76
76
 
77
77
  /** Try to initialize goal via programming interface */
78
78
  function tryGoalInit(pi: ExtensionAPI, planFilePath: string, ctx: ExtensionContext): boolean {
79
+ // Inline alias mirrors @zhushanwen/pi-goal's GoalInitFn (exported from goal/src/index.ts).
80
+ // Kept inline due to optional duck-typed coupling (pi.__goalInit) — update both if signature changes.
79
81
  type GoalInitFn = (
80
82
  objective: string,
81
- tasks: string[],
82
- budget?: { tokenBudget?: number; timeBudgetMinutes?: number; maxTurns?: number },
83
- ctx?: ExtensionContext,
83
+ budget: { tokenBudget?: number; timeBudgetMinutes?: number } | undefined,
84
+ ctx: ExtensionContext,
84
85
  ) => boolean;
85
86
 
86
87
  try {
@@ -95,7 +96,7 @@ function tryGoalInit(pi: ExtensionAPI, planFilePath: string, ctx: ExtensionConte
95
96
  const tasks = extractPlanSteps(planContent);
96
97
  if (tasks.length === 0) return false;
97
98
 
98
- return goalInit(objective, tasks, undefined, ctx);
99
+ return goalInit(objective, undefined, ctx);
99
100
  } catch {
100
101
  return false;
101
102
  }
package/src/index.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";
2
2
 
3
- import { registerPlanCommand } from "./command.js";
3
+ import { registerPlanCommand, startPlanMode } from "./command.js";
4
4
  import { type PlanSessionMap, reconstructPlanState } from "./state.js";
5
5
  import { registerPlanTool } from "./tool.js";
6
6
  import { updatePlanWidget } from "./widget.js";
@@ -13,6 +13,12 @@ export default function planExtension(pi: ExtensionAPI) {
13
13
  registerPlanTool(pi, sessions);
14
14
  registerPlanCommand(pi, sessions);
15
15
 
16
+ // External API: __planStart(allow other extensions to start plan mode programmatically, #9)
17
+ const api = pi as unknown as Record<string, unknown>;
18
+ api.__planStart = (requirement: string, ctx: ExtensionContext): boolean => {
19
+ return startPlanMode(pi, sessions, ctx, requirement);
20
+ };
21
+
16
22
  // Dynamic import compact handlers — avoids cross-group static import
17
23
  import("./compact.js").then(({ registerPlanEventHandlers }) => {
18
24
  registerPlanEventHandlers(pi, sessions);