@fiale-plus/pi-rogue-advisor 0.1.3 → 0.1.5
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 +43 -7
- package/package.json +2 -2
- package/skills/advisor/SKILL.md +36 -38
- package/src/completions.test.ts +31 -0
- package/src/completions.ts +83 -0
- package/src/extension.ts +43 -3
package/README.md
CHANGED
|
@@ -1,14 +1,50 @@
|
|
|
1
1
|
# @fiale-plus/pi-rogue-advisor
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## What this package is
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Strategic advisor for Pi sessions with low-overhead preflight/post-review routing, model auto-detection, session memory, and optional mid-session check-ins.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- SOTA-first model fallback: `gpt-5.5`/`claude-opus-4-6`/`claude-sonnet-4-6` where available.
|
|
8
|
+
- Keeps command-level behavior simple and explicit.
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
## Install
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
```bash
|
|
13
|
+
# Published package (recommended)
|
|
14
|
+
pi install npm:@fiale-plus/pi-rogue-advisor
|
|
15
|
+
|
|
16
|
+
# Local package development
|
|
17
|
+
npm install --workspace packages/advisor
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Commands
|
|
21
|
+
|
|
22
|
+
| Command | What it does |
|
|
23
|
+
|---|---|
|
|
24
|
+
| `/pi-rogue` | Show the Pi-Rogue cockpit + command pointers |
|
|
25
|
+
| `/advisor` | Show status (`/advisor status`) and quick hint |
|
|
26
|
+
| `/advisor status` | Show mode, review policy, check-in status, model selection, counters |
|
|
27
|
+
| `/advisor on` | Enable advisor (auto mode) |
|
|
28
|
+
| `/advisor off` | Disable advisor |
|
|
29
|
+
| `/advisor mode auto\|manual\|off` | Change routing behavior |
|
|
30
|
+
| `/advisor review light\|strict\|off` | Change review strictness |
|
|
31
|
+
| `/advisor checkins on\|off\|<minutes>` | Enable/disable low-cost mid-hour check-ins |
|
|
32
|
+
| `/advisor config` | Show current config |
|
|
33
|
+
| `/advisor model <provider>/<model>` | Set explicit model override |
|
|
34
|
+
| `/advisor <question>` | Get one-shot advisory response |
|
|
35
|
+
|
|
36
|
+
## Notes on defaults
|
|
37
|
+
|
|
38
|
+
- `mode`: `auto`
|
|
39
|
+
- `review`: `light`
|
|
40
|
+
- `checkins`: `mid-hour`
|
|
41
|
+
- `checkinIntervalMinutes`: `30`
|
|
42
|
+
- `model`: not set (auto-detected)
|
|
43
|
+
|
|
44
|
+
Check-ins gate on session activity, are bounded, and avoid overlapping calls.
|
|
45
|
+
|
|
46
|
+
## Stability guarantees
|
|
47
|
+
|
|
48
|
+
- No flattening: the advisor remains its own surface and does not hide orchestration commands.
|
|
49
|
+
- Cockpit is simple and explicit: `/pi-rogue` is the top-level status view.
|
|
12
50
|
|
|
13
|
-
- `/pi-rogue` — cockpit/status entry point
|
|
14
|
-
- `/advisor checkins on|off|<minutes>` — configure low-power mid-session check-ins
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fiale-plus/pi-rogue-advisor",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.5",
|
|
4
|
+
"description": "Pi-Rogue advisor extension for Pi — multi-model support, SOTA model suggestion, cache-aware session advisory.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
package/skills/advisor/SKILL.md
CHANGED
|
@@ -3,48 +3,46 @@ name: advisor
|
|
|
3
3
|
description: Zero-config strategic advisor for Pi. Auto-detects best model, phase-aware routing, preflight + post-review + cache. Use for architecture, tradeoffs, planning.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
#
|
|
6
|
+
# Pi-Rogue Advisor
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
> 96 strategic calls saved ~$53 on GPT-5.5 over 3,071 turns — see [`docs/savings.md`](../../docs/savings.md)
|
|
8
|
+
Use this skill for non-trivial decisions before/after significant edits.
|
|
11
9
|
|
|
12
10
|
## Quick start
|
|
13
11
|
|
|
14
|
-
- `/pi-rogue` — cockpit
|
|
15
|
-
- `/advisor` —
|
|
16
|
-
- `/advisor <question>` —
|
|
17
|
-
- `/advisor on|off
|
|
18
|
-
- `/advisor checkins on|off|<minutes>` — configure low-power mid-hour check-ins
|
|
19
|
-
|
|
20
|
-
Zero config needed. Falls back through SOTA models (gpt-5.5 → claude-opus-4-6 → sonnet-4-6) automatically.
|
|
21
|
-
|
|
22
|
-
The router is phase-aware: it keeps tiny edits cheap, escalates complex/high-risk work to SOTA, and writes compact routing logs for future classifier training.
|
|
23
|
-
|
|
24
|
-
## When to call
|
|
25
|
-
|
|
26
|
-
Agent should call `advisor` tool before: new frameworks, refactoring, API design, concurrency, security, tradeoffs.
|
|
27
|
-
Skip: reads, small edits, one-liners.
|
|
12
|
+
- `/pi-rogue` — open cockpit and command pointers
|
|
13
|
+
- `/advisor status` — show current advisor settings and model route
|
|
14
|
+
- `/advisor <question>` — ask immediate advice
|
|
15
|
+
- `/advisor checkins on|off|<minutes>` — control low-power check-ins
|
|
28
16
|
|
|
29
|
-
##
|
|
17
|
+
## Command surface
|
|
30
18
|
|
|
31
19
|
| Command | What it does |
|
|
32
|
-
|
|
33
|
-
| `/advisor` | Show status
|
|
34
|
-
| `/advisor
|
|
35
|
-
| `/advisor on` | Enable auto mode
|
|
36
|
-
| `/advisor off` | Disable |
|
|
37
|
-
| `/advisor mode auto\|manual\|off` |
|
|
38
|
-
| `/advisor
|
|
39
|
-
| `/advisor
|
|
40
|
-
| `/advisor config` |
|
|
41
|
-
| `/advisor
|
|
42
|
-
| `/advisor
|
|
43
|
-
|
|
44
|
-
##
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
20
|
+
|---|---|
|
|
21
|
+
| `/advisor` | Show status + config summary |
|
|
22
|
+
| `/advisor status` | Same as `/advisor` |
|
|
23
|
+
| `/advisor on` | Enable auto mode |
|
|
24
|
+
| `/advisor off` | Disable advisor |
|
|
25
|
+
| `/advisor mode auto\|manual\|off` | Control when advisor auto-runs |
|
|
26
|
+
| `/advisor review light\|strict\|off` | Set review threshold |
|
|
27
|
+
| `/advisor checkins on\|off\|<minutes>` | Configure interval check-ins |
|
|
28
|
+
| `/advisor config` | Dump full config |
|
|
29
|
+
| `/advisor model <provider/model>` | Pin model explicitly |
|
|
30
|
+
| `/advisor <question>` | Run one advisory response |
|
|
31
|
+
|
|
32
|
+
## Routing and safety
|
|
33
|
+
|
|
34
|
+
- Preflight is heuristics + quick local gate first.
|
|
35
|
+
- Review runs after edits and/or at completion points by policy.
|
|
36
|
+
- No hidden long-running background daemon: check-ins are interval-gated and lightweight.
|
|
37
|
+
|
|
38
|
+
## Keep scope clear
|
|
39
|
+
|
|
40
|
+
The advisor surface is separate from orchestration (`goal`/`loop`/`autoresearch`) and intentionally stays a small command set with explicit entries above.
|
|
41
|
+
|
|
42
|
+
## Defaults
|
|
43
|
+
|
|
44
|
+
- `mode: auto`
|
|
45
|
+
- `review: light`
|
|
46
|
+
- `checkins: mid-hour`
|
|
47
|
+
- `checkinIntervalMinutes: 30`
|
|
48
|
+
- `model: auto`
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { advisorArgumentCompletions, piRogueArgumentCompletions } from "./completions.js";
|
|
3
|
+
|
|
4
|
+
describe("advisor completions", () => {
|
|
5
|
+
it("offers top-level advisor continuations", () => {
|
|
6
|
+
const values = advisorArgumentCompletions("")?.map((i) => i.value);
|
|
7
|
+
expect(values).toEqual(expect.arrayContaining(["status", "config", "checkins", "review"]));
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it("offers nested review choices", () => {
|
|
11
|
+
const values = advisorArgumentCompletions("review ")?.map((i) => i.value);
|
|
12
|
+
expect(values).toEqual(["light", "strict", "off"]);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("offers check-in choices", () => {
|
|
16
|
+
const values = advisorArgumentCompletions("checkins ")?.map((i) => i.value);
|
|
17
|
+
expect(values).toEqual(expect.arrayContaining(["on", "off", "30", "60"]));
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe("pi-rogue cockpit completions", () => {
|
|
22
|
+
it("offers umbrella sections", () => {
|
|
23
|
+
const values = piRogueArgumentCompletions("")?.map((i) => i.value);
|
|
24
|
+
expect(values).toEqual(expect.arrayContaining(["status", "advisor", "orchestration", "help"]));
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("fans out to orchestration shortcuts", () => {
|
|
28
|
+
const values = piRogueArgumentCompletions("orchestration ")?.map((i) => i.value);
|
|
29
|
+
expect(values).toEqual(expect.arrayContaining(["goal", "loop", "autoresearch", "autoresearch-lab"]));
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
type CompletionItem = { value: string; label: string; description?: string };
|
|
2
|
+
|
|
3
|
+
function item(value: string, description?: string): CompletionItem {
|
|
4
|
+
return { value, label: value, ...(description ? { description } : {}) };
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function complete(values: Array<[string, string?]>, prefix: string): CompletionItem[] | null {
|
|
8
|
+
const q = prefix.trimStart().toLowerCase();
|
|
9
|
+
const items = values.map(([value, description]) => item(value, description));
|
|
10
|
+
const filtered = q
|
|
11
|
+
? items.filter((i) => i.value.startsWith(q))
|
|
12
|
+
: items;
|
|
13
|
+
return filtered.length > 0 ? filtered : null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function completionsForPrefix(prefix: string, topLevel: Array<[string, string?]>, nested: Record<string, Array<[string, string?]>>): CompletionItem[] | null {
|
|
17
|
+
const q = prefix.trimStart().toLowerCase();
|
|
18
|
+
if (!q) return complete(topLevel, q);
|
|
19
|
+
|
|
20
|
+
const [head, ...rest] = q.split(/\s+/);
|
|
21
|
+
if (!head) return complete(topLevel, q);
|
|
22
|
+
|
|
23
|
+
if (rest.length === 0) {
|
|
24
|
+
const top = complete(topLevel, head);
|
|
25
|
+
if (top) return top;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const next = nested[head];
|
|
29
|
+
if (next) {
|
|
30
|
+
return complete(next, rest.join(" "));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return complete(topLevel, q);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const advisorTopLevel: Array<[string, string?]> = [
|
|
37
|
+
["status", "show status and configuration"],
|
|
38
|
+
["config", "show full config"],
|
|
39
|
+
["on", "enable auto mode"],
|
|
40
|
+
["off", "disable advisor"],
|
|
41
|
+
["mode", "set auto/manual/off"],
|
|
42
|
+
["review", "set light/strict/off"],
|
|
43
|
+
["checkins", "configure mid-hour check-ins"],
|
|
44
|
+
["checkin", "alias for checkins"],
|
|
45
|
+
["model", "set or inspect model override"],
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
const advisorNested: Record<string, Array<[string, string?]>> = {
|
|
49
|
+
mode: [["auto"], ["manual"], ["off"]],
|
|
50
|
+
review: [["light"], ["strict"], ["off"]],
|
|
51
|
+
checkins: [["on"], ["off"], ["10"], ["15"], ["30"], ["60"]],
|
|
52
|
+
checkin: [["on"], ["off"], ["10"], ["15"], ["30"], ["60"]],
|
|
53
|
+
model: [["auto"], ["openai-codex/gpt-5.5"], ["anthropic/claude-opus-4-6"]],
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const piRogueTopLevel: Array<[string, string?]> = [
|
|
57
|
+
["status", "show cockpit"],
|
|
58
|
+
["advisor", "advisor status and check-ins"],
|
|
59
|
+
["orchestration", "goal/loop/autoresearch shortcuts"],
|
|
60
|
+
["checkins", "advisor check-ins"],
|
|
61
|
+
["help", "show cockpit help"],
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
const piRogueNested: Record<string, Array<[string, string?]>> = {
|
|
65
|
+
advisor: advisorTopLevel,
|
|
66
|
+
orchestration: [
|
|
67
|
+
["goal", "goal commands"],
|
|
68
|
+
["loop", "loop commands"],
|
|
69
|
+
["autoresearch", "solo research flow"],
|
|
70
|
+
["autoresearch-lab", "parallel research flow"],
|
|
71
|
+
["status", "show all surfaces"],
|
|
72
|
+
],
|
|
73
|
+
checkins: advisorNested.checkins,
|
|
74
|
+
help: [["advisor"], ["orchestration"], ["checkins"], ["status"]],
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export function advisorArgumentCompletions(prefix: string): CompletionItem[] | null {
|
|
78
|
+
return completionsForPrefix(prefix, advisorTopLevel, advisorNested);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function piRogueArgumentCompletions(prefix: string): CompletionItem[] | null {
|
|
82
|
+
return completionsForPrefix(prefix, piRogueTopLevel, piRogueNested);
|
|
83
|
+
}
|
package/src/extension.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { Box, Text } from "@earendil-works/pi-tui";
|
|
|
5
5
|
import { completeSimple, type ThinkingLevel } from "@earendil-works/pi-ai";
|
|
6
6
|
import { Type } from "typebox";
|
|
7
7
|
import { featureFile, readText, truncate, writeText } from "./internal.js";
|
|
8
|
+
import { advisorArgumentCompletions, piRogueArgumentCompletions } from "./completions.js";
|
|
8
9
|
import {
|
|
9
10
|
appendRouteLog,
|
|
10
11
|
binaryGatePredict,
|
|
@@ -373,7 +374,7 @@ function syncCheckinTimer(pi: ExtensionAPI, ctx: any): void {
|
|
|
373
374
|
function piRogueCockpitText(config: AdvisorConfig, state: SessionState, currentNote: string): string {
|
|
374
375
|
const normalized = normalizeAdvisorConfig(config);
|
|
375
376
|
return [
|
|
376
|
-
"☠︎
|
|
377
|
+
"☠︎ Pi-Rogue cockpit",
|
|
377
378
|
currentNote ? `Advisor: ${truncate(currentNote, 220)}` : "Advisor: no current note",
|
|
378
379
|
`Mode: ${normalized.mode} | Review: ${normalized.review} | Check-ins: ${normalized.checkins === "off" ? "off" : `${normalized.checkinIntervalMinutes}m`}`,
|
|
379
380
|
`Turns: ${state.turns} | Advisor calls: ${state.advisorCalls} | Cache hits: ${state.cacheHits}`,
|
|
@@ -665,11 +666,49 @@ export function registerAdvisor(pi: ExtensionAPI): void {
|
|
|
665
666
|
|
|
666
667
|
// ── /pi-rogue cockpit ──────────────────────────────────────────────────
|
|
667
668
|
pi.registerCommand("pi-rogue", {
|
|
668
|
-
description: "Show
|
|
669
|
-
|
|
669
|
+
description: "Show Pi-Rogue cockpit: advisor, check-ins, and orchestration command pointers",
|
|
670
|
+
getArgumentCompletions: (prefix: string) => piRogueArgumentCompletions(prefix),
|
|
671
|
+
handler: async (args, ctx) => {
|
|
670
672
|
const cfg = loadConfig();
|
|
671
673
|
const state = loadState();
|
|
674
|
+
const arg = String(args ?? "").trim().toLowerCase();
|
|
672
675
|
setPiRogueStatus(ctx, cfg, state);
|
|
676
|
+
|
|
677
|
+
if (!arg || arg === "status" || arg === "help") {
|
|
678
|
+
ctx.ui.notify(piRogueCockpitText(cfg, state, readText(CURRENT_PATH).trim()), "info");
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
if (arg.startsWith("advisor")) {
|
|
683
|
+
ctx.ui.notify([
|
|
684
|
+
"Advisor surface:",
|
|
685
|
+
" /advisor status",
|
|
686
|
+
" /advisor config",
|
|
687
|
+
" /advisor checkins on|off|<minutes>",
|
|
688
|
+
" /advisor <question>",
|
|
689
|
+
].join("\n"), "info");
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
if (arg.startsWith("orchestration")) {
|
|
694
|
+
ctx.ui.notify([
|
|
695
|
+
"Orchestration surface:",
|
|
696
|
+
" /goal show|clear|list|set <text>",
|
|
697
|
+
" /loop status|off|clear|stop|<interval> <instruction>",
|
|
698
|
+
" /autoresearch status|clear|<instruction>",
|
|
699
|
+
" /autoresearch-lab status|clear|<instruction>",
|
|
700
|
+
].join("\n"), "info");
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
if (arg.startsWith("checkins")) {
|
|
705
|
+
ctx.ui.notify([
|
|
706
|
+
`Advisor check-ins: ${cfg.checkins === "off" ? "off" : `${cfg.checkinIntervalMinutes}m`}`,
|
|
707
|
+
"Use /advisor checkins on|off|<minutes> to change it.",
|
|
708
|
+
].join("\n"), "info");
|
|
709
|
+
return;
|
|
710
|
+
}
|
|
711
|
+
|
|
673
712
|
ctx.ui.notify(piRogueCockpitText(cfg, state, readText(CURRENT_PATH).trim()), "info");
|
|
674
713
|
},
|
|
675
714
|
});
|
|
@@ -677,6 +716,7 @@ export function registerAdvisor(pi: ExtensionAPI): void {
|
|
|
677
716
|
// ── /advisor command ───────────────────────────────────────────────────
|
|
678
717
|
pi.registerCommand("advisor", {
|
|
679
718
|
description: "Senior engineering advisor. Usage: /advisor [on|off|status|config|question]",
|
|
719
|
+
getArgumentCompletions: (prefix: string) => advisorArgumentCompletions(prefix),
|
|
680
720
|
handler: async (args, ctx) => {
|
|
681
721
|
const a = String(args ?? "").trim().toLowerCase();
|
|
682
722
|
const [cmd, ...rest] = a.split(/\s+/);
|