@leing2021/super-pi 0.19.2 → 0.19.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/README.md +16 -12
- package/extensions/ce-core/index.ts +117 -6
- package/package.json +1 -1
- package/skills/references/pipeline-config.md +15 -25
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ Super Pi's answers:
|
|
|
35
35
|
|
|
36
36
|
Each step has a dedicated skill + tool pair. Not just prompts — structured toolchains.
|
|
37
37
|
|
|
38
|
-
### New: Stage model routing
|
|
38
|
+
### New: Stage model routing
|
|
39
39
|
|
|
40
40
|
Configure once in `.pi/settings.json`:
|
|
41
41
|
|
|
@@ -48,24 +48,22 @@ Configure once in `.pi/settings.json`:
|
|
|
48
48
|
"04-review": "claude-sonnet-4-20250514",
|
|
49
49
|
"05-learn": "claude-haiku-4-20250414",
|
|
50
50
|
"default": "claude-sonnet-4-20250514"
|
|
51
|
-
},
|
|
52
|
-
"pipeline": {
|
|
53
|
-
"autoContinue": false
|
|
54
51
|
}
|
|
55
52
|
}
|
|
56
53
|
```
|
|
57
54
|
|
|
58
55
|
How it works:
|
|
59
|
-
-
|
|
56
|
+
- Model switching is handled automatically by the ce-core extension `input` hook — no manual `/model` needed.
|
|
57
|
+
- When you type `/skill:01-brainstorm` through `/skill:05-learn`, the extension reads `modelStrategy[stage]` (or `modelStrategy.default`) and switches before the skill runs.
|
|
58
|
+
- Supported formats: full reference (`"anthropic/claude-opus-4-1"`) or bare model id (`"claude-opus-4-1"`, reuses current provider).
|
|
60
59
|
- Every stage prints a `📊 Pipeline Status` block with `Current / Output / Next`.
|
|
61
|
-
-
|
|
62
|
-
- Auto-continue is gate-aware: it will NOT skip required approvals (brainstorm approval, plan/review A/B/C choices).
|
|
60
|
+
- A `Switched model for <stage>: <provider>/<model>` notification appears when the model changes.
|
|
63
61
|
|
|
64
62
|
Quick example:
|
|
65
|
-
1. Run `/skill:01-brainstorm`
|
|
63
|
+
1. Run `/skill:01-brainstorm` — model auto-switches to the configured brainstorm model
|
|
66
64
|
2. Approve the design
|
|
67
|
-
3.
|
|
68
|
-
4.
|
|
65
|
+
3. Run `/skill:02-plan` — model auto-switches to the configured plan model
|
|
66
|
+
4. Continue through each stage — model switches automatically at each step
|
|
69
67
|
|
|
70
68
|
---
|
|
71
69
|
|
|
@@ -383,6 +381,13 @@ Not a fork. Not a wrapper. Methodologies extracted and rebuilt with Pi's native
|
|
|
383
381
|
|
|
384
382
|
## Changelog
|
|
385
383
|
|
|
384
|
+
### 0.19.3 — Terminate fix + runtime model routing + autoContinue removal
|
|
385
|
+
- Fixed 6 ce-core tools (`brainstorm_dialog`, `workflow_state`, `review_router`, `session_checkpoint`, `session_history`, `pattern_extractor`) incorrectly returning `terminate: true`, which caused agent turns to end prematurely (brainstorm questions not shown, "type continue to proceed" interruptions).
|
|
386
|
+
- Implemented runtime stage model routing via ce-core extension `input` hook: reads `.pi/settings.json` `modelStrategy`, auto-switches model before skill execution. Supports full reference (`anthropic/claude-opus-4-1`) and bare model id (`claude-opus-4-1`).
|
|
387
|
+
- Removed `pipeline.autoContinue` configuration (never had runtime implementation; Pi lacks `skill_end` event for auto-continue).
|
|
388
|
+
- Updated `skills/references/pipeline-config.md`, `README.md`, `README_CN.md` to reflect runtime model routing behavior.
|
|
389
|
+
- Added 4 new tests covering terminate regression, input hook model routing, and bare model id parsing.
|
|
390
|
+
|
|
386
391
|
### 0.19.2 — Evidence-first handoff-lite + docs tracking rule
|
|
387
392
|
- Added `context_handoff` with evidence-first default handoff-lite generation when markdown is omitted.
|
|
388
393
|
- Standardized the shared handoff-lite template across 01-05 workflow handoffs via `skills/references/pipeline-config.md`.
|
|
@@ -391,8 +396,7 @@ Not a fork. Not a wrapper. Methodologies extracted and rebuilt with Pi's native
|
|
|
391
396
|
|
|
392
397
|
### 0.19.1 — Pipeline config + typecheck baseline fix
|
|
393
398
|
- Added shared pipeline config (`skills/references/pipeline-config.md`) for stage model routing via `.pi/settings.json`.
|
|
394
|
-
- Added
|
|
395
|
-
- Added explicit README usage examples for `modelStrategy` and `pipeline.autoContinue`.
|
|
399
|
+
- Added runtime stage model routing via ce-core extension `input` hook (reads `modelStrategy` from `.pi/settings.json`, auto-switches model before skill execution).
|
|
396
400
|
- Fixed TypeScript baseline issues so `bunx tsc --noEmit` passes.
|
|
397
401
|
|
|
398
402
|
### 0.19.0 — 0.69.0 alignment + learn rename
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises"
|
|
2
|
+
import path from "node:path"
|
|
1
3
|
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent"
|
|
2
4
|
import { Type } from "typebox"
|
|
3
5
|
import { createArtifactHelperTool, type ArtifactType } from "./tools/artifact-helper"
|
|
@@ -20,6 +22,65 @@ import { AsyncMutex } from "./tools/async-mutex"
|
|
|
20
22
|
import type { SubagentExecOptions, SubagentRunner } from "./tools/subagent"
|
|
21
23
|
|
|
22
24
|
const _subagentEnvMutex = new AsyncMutex()
|
|
25
|
+
const PIPELINE_STAGE_KEYS = new Set([
|
|
26
|
+
"01-brainstorm",
|
|
27
|
+
"02-plan",
|
|
28
|
+
"03-work",
|
|
29
|
+
"04-review",
|
|
30
|
+
"05-learn",
|
|
31
|
+
])
|
|
32
|
+
|
|
33
|
+
interface ModelStrategySettings {
|
|
34
|
+
modelStrategy?: Record<string, string>
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function readProjectSettings(cwd: string): Promise<ModelStrategySettings | null> {
|
|
38
|
+
const settingsPath = path.join(cwd, ".pi", "settings.json")
|
|
39
|
+
try {
|
|
40
|
+
const content = await readFile(settingsPath, "utf8")
|
|
41
|
+
return JSON.parse(content) as ModelStrategySettings
|
|
42
|
+
} catch {
|
|
43
|
+
return null
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function parseStageSkillName(text: string): string | null {
|
|
48
|
+
const trimmed = text.trim()
|
|
49
|
+
const match = trimmed.match(/^\/skill:([^\s]+)/)
|
|
50
|
+
if (!match) {
|
|
51
|
+
return null
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const skillName = match[1]
|
|
55
|
+
return PIPELINE_STAGE_KEYS.has(skillName) ? skillName : null
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function parseModelRef(
|
|
59
|
+
modelRef: string,
|
|
60
|
+
currentProvider?: string,
|
|
61
|
+
): { provider: string, id: string } | null {
|
|
62
|
+
const trimmed = modelRef.trim()
|
|
63
|
+
if (!trimmed) {
|
|
64
|
+
return null
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const slashIndex = trimmed.indexOf("/")
|
|
68
|
+
if (slashIndex > 0 && slashIndex < trimmed.length - 1) {
|
|
69
|
+
return {
|
|
70
|
+
provider: trimmed.slice(0, slashIndex),
|
|
71
|
+
id: trimmed.slice(slashIndex + 1),
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (!currentProvider) {
|
|
76
|
+
return null
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
provider: currentProvider,
|
|
81
|
+
id: trimmed,
|
|
82
|
+
}
|
|
83
|
+
}
|
|
23
84
|
|
|
24
85
|
/**
|
|
25
86
|
* Create a subagent runner that handles env injection with mutex protection
|
|
@@ -223,6 +284,62 @@ const patternExtractorParams = Type.Object({
|
|
|
223
284
|
})
|
|
224
285
|
|
|
225
286
|
export default function ceCoreExtension(pi: ExtensionAPI) {
|
|
287
|
+
pi.on("input", async (event, ctx) => {
|
|
288
|
+
if (event.source === "extension") {
|
|
289
|
+
return { action: "continue" as const }
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const stageKey = parseStageSkillName(event.text)
|
|
293
|
+
if (!stageKey) {
|
|
294
|
+
return { action: "continue" as const }
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const settings = await readProjectSettings(ctx.cwd)
|
|
298
|
+
const modelStrategy = settings?.modelStrategy
|
|
299
|
+
if (!modelStrategy) {
|
|
300
|
+
return { action: "continue" as const }
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const targetModelRef = modelStrategy[stageKey] ?? modelStrategy.default
|
|
304
|
+
if (!targetModelRef) {
|
|
305
|
+
return { action: "continue" as const }
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const parsed = parseModelRef(targetModelRef, ctx.model?.provider)
|
|
309
|
+
if (!parsed) {
|
|
310
|
+
if (ctx.hasUI) {
|
|
311
|
+
ctx.ui.notify(`Invalid modelStrategy entry for ${stageKey}: ${targetModelRef}`, "warning")
|
|
312
|
+
}
|
|
313
|
+
return { action: "continue" as const }
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (ctx.model?.provider === parsed.provider && ctx.model?.id === parsed.id) {
|
|
317
|
+
return { action: "continue" as const }
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const model = ctx.modelRegistry.find(parsed.provider, parsed.id)
|
|
321
|
+
if (!model) {
|
|
322
|
+
if (ctx.hasUI) {
|
|
323
|
+
ctx.ui.notify(`Configured model not found for ${stageKey}: ${targetModelRef}`, "warning")
|
|
324
|
+
}
|
|
325
|
+
return { action: "continue" as const }
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const switched = await pi.setModel(model)
|
|
329
|
+
if (switched) {
|
|
330
|
+
if (ctx.hasUI) {
|
|
331
|
+
ctx.ui.notify(`Switched model for ${stageKey}: ${model.provider}/${model.id}`, "info")
|
|
332
|
+
}
|
|
333
|
+
return { action: "continue" as const }
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if (ctx.hasUI) {
|
|
337
|
+
ctx.ui.notify(`No API key available for configured model: ${model.provider}/${model.id}`, "warning")
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return { action: "continue" as const }
|
|
341
|
+
})
|
|
342
|
+
|
|
226
343
|
const artifactHelper = createArtifactHelperTool()
|
|
227
344
|
const askUserQuestion = createAskUserQuestionTool()
|
|
228
345
|
const subagent = createSubagentTool()
|
|
@@ -338,7 +455,6 @@ export default function ceCoreExtension(pi: ExtensionAPI) {
|
|
|
338
455
|
return {
|
|
339
456
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
340
457
|
details: result,
|
|
341
|
-
terminate: true,
|
|
342
458
|
}
|
|
343
459
|
},
|
|
344
460
|
})
|
|
@@ -393,7 +509,6 @@ export default function ceCoreExtension(pi: ExtensionAPI) {
|
|
|
393
509
|
return {
|
|
394
510
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
395
511
|
details: result,
|
|
396
|
-
terminate: true,
|
|
397
512
|
}
|
|
398
513
|
},
|
|
399
514
|
})
|
|
@@ -449,7 +564,6 @@ export default function ceCoreExtension(pi: ExtensionAPI) {
|
|
|
449
564
|
return {
|
|
450
565
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
451
566
|
details: result,
|
|
452
|
-
terminate: true,
|
|
453
567
|
}
|
|
454
568
|
},
|
|
455
569
|
})
|
|
@@ -489,7 +603,6 @@ export default function ceCoreExtension(pi: ExtensionAPI) {
|
|
|
489
603
|
return {
|
|
490
604
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
491
605
|
details: result,
|
|
492
|
-
terminate: true,
|
|
493
606
|
}
|
|
494
607
|
},
|
|
495
608
|
})
|
|
@@ -531,7 +644,6 @@ export default function ceCoreExtension(pi: ExtensionAPI) {
|
|
|
531
644
|
return {
|
|
532
645
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
533
646
|
details: result,
|
|
534
|
-
terminate: true,
|
|
535
647
|
}
|
|
536
648
|
},
|
|
537
649
|
})
|
|
@@ -553,7 +665,6 @@ export default function ceCoreExtension(pi: ExtensionAPI) {
|
|
|
553
665
|
return {
|
|
554
666
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
555
667
|
details: result,
|
|
556
|
-
terminate: true,
|
|
557
668
|
}
|
|
558
669
|
},
|
|
559
670
|
})
|
package/package.json
CHANGED
|
@@ -4,21 +4,21 @@ Use these rules in all Phase 1 skills: `01-brainstorm` → `02-plan` → `03-wor
|
|
|
4
4
|
|
|
5
5
|
## Start of skill: model routing
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
## End of skill: status + context
|
|
7
|
+
Model routing is handled automatically by the ce-core extension's `input` hook.
|
|
8
|
+
When a user types `/skill:01-brainstorm` through `/skill:05-learn`, the extension:
|
|
9
|
+
|
|
10
|
+
1. Reads `.pi/settings.json` from the project root.
|
|
11
|
+
2. Parses `modelStrategy[stageKey]` or falls back to `modelStrategy.default`.
|
|
12
|
+
3. If the target model differs from the current model, calls `pi.setModel()`.
|
|
13
|
+
4. If switching fails, notifies the user and continues with the current model.
|
|
14
|
+
|
|
15
|
+
No manual `/model` command is needed. The skill itself does not need to handle model switching.
|
|
16
|
+
|
|
17
|
+
Supported `modelStrategy` formats in `.pi/settings.json`:
|
|
18
|
+
- Full reference: `"02-plan": "anthropic/claude-opus-4-1"`
|
|
19
|
+
- Bare model id (reuses current provider): `"02-plan": "claude-opus-4-1"`
|
|
20
|
+
|
|
21
|
+
## End of skill: status + context
|
|
22
22
|
|
|
23
23
|
Before final completion, always output these blocks (replace placeholders with real values, never output angle-bracket placeholders literally):
|
|
24
24
|
|
|
@@ -45,16 +45,6 @@ Next step mapping:
|
|
|
45
45
|
- `04-review` → `/skill:05-learn`
|
|
46
46
|
- `05-learn` → `Completed`
|
|
47
47
|
|
|
48
|
-
Then read `.pi/settings.json` → `pipeline.autoContinue`:
|
|
49
|
-
- If `false` or missing, stop after the status block and wait for user input.
|
|
50
|
-
- If current stage is `05-learn`, stop after status block.
|
|
51
|
-
- If `true` and current stage is not `05-learn`, auto-continue is allowed only after stage-specific gates are satisfied:
|
|
52
|
-
- `01-brainstorm`: user has explicitly approved the design handoff.
|
|
53
|
-
- `02-plan`: review choice is resolved (A/B/C flow completed) and user confirmed to proceed.
|
|
54
|
-
- `04-review`: optional QA choice is resolved (A/B/C flow completed) and user confirmed to proceed.
|
|
55
|
-
- Any unclear/ambiguous state: do not auto-continue; stop and ask.
|
|
56
|
-
- When gates are satisfied, automatically trigger the mapped next skill command.
|
|
57
|
-
|
|
58
48
|
### Handoff-lite template
|
|
59
49
|
|
|
60
50
|
When a stage produces or updates handoff-lite, use this evidence-first structure and keep it concise (target <= 1500 tokens):
|