@bacnh85/pi-plan 0.1.6 → 0.1.7

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.
Files changed (2) hide show
  1. package/index.ts +67 -17
  2. package/package.json +1 -1
package/index.ts CHANGED
@@ -30,9 +30,9 @@ interface PlanState {
30
30
  }
31
31
 
32
32
  interface PlanPreferences {
33
- version: 1;
34
- planThinking: ThinkingLevel;
35
- normalThinking: ThinkingLevel;
33
+ version: 2;
34
+ defaults: { planThinking: ThinkingLevel; normalThinking: ThinkingLevel };
35
+ perModel: Record<string, { planThinking: ThinkingLevel; normalThinking: ThinkingLevel }>;
36
36
  }
37
37
 
38
38
  interface WritePlanParams {
@@ -128,14 +128,35 @@ function hasOpenQuestionWarning(content: string): boolean {
128
128
  return /(^|\n)#{1,6}\s+.*open questions?.*\n[\s\S]*\?/i.test(content);
129
129
  }
130
130
 
131
+ function modelKey(model: { provider?: string; id?: string } | undefined): string | undefined {
132
+ if (!model?.provider || !model?.id) return undefined;
133
+ return `${model.provider}/${model.id}`;
134
+ }
135
+
136
+ function getEffectiveThinking(prefs: PlanPreferences, model: { provider?: string; id?: string } | undefined): { plan: ThinkingLevel; normal: ThinkingLevel } {
137
+ const key = modelKey(model);
138
+ const stored = key ? prefs.perModel[key] : undefined;
139
+ return {
140
+ plan: stored?.planThinking ?? prefs.defaults.planThinking,
141
+ normal: stored?.normalThinking ?? prefs.defaults.normalThinking,
142
+ };
143
+ }
144
+
131
145
  async function loadPreferences(): Promise<PlanPreferences | undefined> {
132
146
  try {
133
147
  const raw = await readFile(PREFERENCES_FILE, "utf8");
134
- const parsed = JSON.parse(raw) as Partial<PlanPreferences>;
135
- const savedPlanThinking = parsed.planThinking;
136
- const savedNormalThinking = parsed.normalThinking;
137
- if (parsed.version !== 1 || !savedPlanThinking || !savedNormalThinking || !isThinkingLevel(savedPlanThinking) || !isThinkingLevel(savedNormalThinking)) return undefined;
138
- return { version: 1, planThinking: savedPlanThinking, normalThinking: savedNormalThinking };
148
+ const parsed = JSON.parse(raw) as Record<string, any>;
149
+ if (parsed.version === 2 && isThinkingLevel(parsed.defaults?.planThinking) && isThinkingLevel(parsed.defaults?.normalThinking) && typeof parsed.perModel === "object" && parsed.perModel !== null) {
150
+ return { version: 2, defaults: parsed.defaults, perModel: parsed.perModel } as PlanPreferences;
151
+ }
152
+ if (parsed.version === 1 && isThinkingLevel(parsed.planThinking) && isThinkingLevel(parsed.normalThinking)) {
153
+ return {
154
+ version: 2,
155
+ defaults: { planThinking: parsed.planThinking as ThinkingLevel, normalThinking: parsed.normalThinking as ThinkingLevel },
156
+ perModel: {},
157
+ };
158
+ }
159
+ return undefined;
139
160
  } catch {
140
161
  return undefined;
141
162
  }
@@ -248,8 +269,11 @@ export default function piPlanExtension(pi: ExtensionAPI): void {
248
269
  } satisfies PlanState);
249
270
  }
250
271
 
272
+ let preferences: PlanPreferences | undefined;
273
+
251
274
  function persistPreferences(): void {
252
- void savePreferences({ version: 1, planThinking, normalThinking }).catch(() => undefined);
275
+ if (!preferences) return;
276
+ void savePreferences(preferences).catch(() => undefined);
253
277
  }
254
278
 
255
279
  function enablePlanTools(): void {
@@ -279,6 +303,10 @@ export default function piPlanExtension(pi: ExtensionAPI): void {
279
303
  if (normalThinking === level) return;
280
304
  normalThinking = level;
281
305
  }
306
+ const key = modelKey(ctx.model);
307
+ if (key && preferences) {
308
+ preferences.perModel[key] = { planThinking, normalThinking };
309
+ }
282
310
  setStatus(ctx);
283
311
  persistState();
284
312
  persistPreferences();
@@ -501,26 +529,29 @@ export default function piPlanExtension(pi: ExtensionAPI): void {
501
529
  });
502
530
 
503
531
  pi.on("session_start", async (_event, ctx) => {
504
- const preferences = await loadPreferences();
532
+ preferences = await loadPreferences();
533
+ if (!preferences) {
534
+ preferences = { version: 2, defaults: { planThinking, normalThinking }, perModel: {} };
535
+ }
536
+ const effective = getEffectiveThinking(preferences, ctx.model);
537
+ planThinking = effective.plan;
538
+ normalThinking = effective.normal;
539
+
505
540
  const entries = ctx.sessionManager.getEntries();
506
541
  const saved = entries
507
542
  .filter((entry: { type: string; customType?: string }) => entry.type === "custom" && entry.customType === "pi-plan")
508
543
  .pop() as { data?: PlanState } | undefined;
509
- if (preferences) {
510
- planThinking = preferences.planThinking;
511
- normalThinking = preferences.normalThinking;
512
- }
513
544
  if (saved?.data) {
514
545
  planModeEnabled = saved.data.enabled ?? planModeEnabled;
515
546
  executionMode = saved.data.executing ?? executionMode;
516
- if (!preferences && isThinkingLevel(saved.data.planThinking)) planThinking = saved.data.planThinking;
517
- if (!preferences && isThinkingLevel(saved.data.normalThinking)) normalThinking = saved.data.normalThinking;
547
+ if (isThinkingLevel(saved.data.planThinking)) planThinking = saved.data.planThinking;
548
+ if (isThinkingLevel(saved.data.normalThinking)) normalThinking = saved.data.normalThinking;
518
549
  toolsBeforePlan = saved.data.toolsBeforePlan ?? toolsBeforePlan;
519
550
  lastPlanPath = saved.data.lastPlanPath ?? lastPlanPath;
520
551
  lastPlanTitle = saved.data.lastPlanTitle ?? lastPlanTitle;
521
552
  lastPlanStatus = saved.data.lastPlanStatus ?? lastPlanStatus;
522
553
  }
523
- if (!preferences) persistPreferences();
554
+ persistPreferences();
524
555
  if (pi.getFlag("plan") === true) planModeEnabled = true;
525
556
  if (planModeEnabled) {
526
557
  enablePlanTools();
@@ -532,6 +563,25 @@ export default function piPlanExtension(pi: ExtensionAPI): void {
532
563
  clearPlanWidget(ctx);
533
564
  });
534
565
 
566
+ pi.on("model_select", async (event, ctx) => {
567
+ if (executionMode) return;
568
+ if (!preferences) return;
569
+ const effective = getEffectiveThinking(preferences, event.model);
570
+ if (planModeEnabled) {
571
+ if (planThinking !== effective.plan) {
572
+ planThinking = effective.plan;
573
+ applyThinking(planThinking);
574
+ }
575
+ } else {
576
+ if (normalThinking !== effective.normal) {
577
+ normalThinking = effective.normal;
578
+ applyThinking(normalThinking);
579
+ }
580
+ }
581
+ setStatus(ctx);
582
+ persistState();
583
+ });
584
+
535
585
  pi.on("thinking_level_select", async (event, ctx) => {
536
586
  if (applyingStoredThinking) return;
537
587
  if (!isThinkingLevel(event.level)) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bacnh85/pi-plan",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "Pi extension that adds a plan mode with workspace markdown plans and thinking-level presets.",
5
5
  "license": "MIT",
6
6
  "publishConfig": {