@fiale-plus/pi-rogue-advisor 0.1.7 → 0.1.9
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 +3 -4
- package/assets/binary-gate-model.json +23262 -23262
- package/package.json +1 -1
- package/skills/advisor/SKILL.md +3 -4
- package/src/completions.test.ts +2 -5
- package/src/completions.ts +2 -8
- package/src/extension.test.ts +85 -2
- package/src/extension.ts +254 -117
- package/src/index.ts +1 -0
package/package.json
CHANGED
package/skills/advisor/SKILL.md
CHANGED
|
@@ -12,7 +12,7 @@ Use this skill for non-trivial decisions before/after significant edits.
|
|
|
12
12
|
- `/pi-rogue` — open cockpit and command pointers
|
|
13
13
|
- `/advisor status` — show current advisor settings and model route
|
|
14
14
|
- `/advisor <question>` — ask immediate advice
|
|
15
|
-
- `/
|
|
15
|
+
- Check-ins are lifecycle-managed by `/loop`, not by the advisor command surface
|
|
16
16
|
|
|
17
17
|
## Command surface
|
|
18
18
|
|
|
@@ -24,7 +24,6 @@ Use this skill for non-trivial decisions before/after significant edits.
|
|
|
24
24
|
| `/advisor off` | Disable advisor |
|
|
25
25
|
| `/advisor mode auto\|manual\|off` | Control when advisor auto-runs |
|
|
26
26
|
| `/advisor review light\|strict\|off` | Set review threshold |
|
|
27
|
-
| `/advisor checkins on\|off\|<minutes>` | Configure interval check-ins |
|
|
28
27
|
| `/advisor config` | Dump full config |
|
|
29
28
|
| `/advisor model <provider/model>` | Pin model explicitly |
|
|
30
29
|
| `/advisor <question>` | Run one advisory response |
|
|
@@ -33,7 +32,7 @@ Use this skill for non-trivial decisions before/after significant edits.
|
|
|
33
32
|
|
|
34
33
|
- Preflight is heuristics + quick local gate first.
|
|
35
34
|
- Review runs after edits and/or at completion points by policy.
|
|
36
|
-
- No
|
|
35
|
+
- No standalone check-in command: check-ins are triggered from loop cadence (not from advisor internals), using higher/advanced advisor models first with regular model fallback enabled by default.
|
|
37
36
|
|
|
38
37
|
## Keep scope clear
|
|
39
38
|
|
|
@@ -43,6 +42,6 @@ The advisor surface is separate from orchestration (`goal`/`loop`/`autoresearch`
|
|
|
43
42
|
|
|
44
43
|
- `mode: auto`
|
|
45
44
|
- `review: light`
|
|
46
|
-
- `checkins: off` by default; orchestration
|
|
45
|
+
- `checkins: off` by default; loop orchestration owns cadence and enables them when active
|
|
47
46
|
- `checkinIntervalMinutes: 30`
|
|
48
47
|
- `model: auto`
|
package/src/completions.test.ts
CHANGED
|
@@ -4,7 +4,8 @@ import { advisorArgumentCompletions, piRogueArgumentCompletions } from "./comple
|
|
|
4
4
|
describe("advisor completions", () => {
|
|
5
5
|
it("offers top-level advisor continuations", () => {
|
|
6
6
|
const values = advisorArgumentCompletions("")?.map((i) => i.value);
|
|
7
|
-
expect(values).toEqual(expect.arrayContaining(["status", "config", "
|
|
7
|
+
expect(values).toEqual(expect.arrayContaining(["status", "config", "model", "review"]));
|
|
8
|
+
expect(values).not.toContain("checkins");
|
|
8
9
|
});
|
|
9
10
|
|
|
10
11
|
it("offers nested review choices", () => {
|
|
@@ -12,10 +13,6 @@ describe("advisor completions", () => {
|
|
|
12
13
|
expect(values).toEqual(["light", "strict", "off"]);
|
|
13
14
|
});
|
|
14
15
|
|
|
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
16
|
});
|
|
20
17
|
|
|
21
18
|
describe("pi-rogue cockpit completions", () => {
|
package/src/completions.ts
CHANGED
|
@@ -40,24 +40,19 @@ const advisorTopLevel: Array<[string, string?]> = [
|
|
|
40
40
|
["off", "disable advisor"],
|
|
41
41
|
["mode", "set auto/manual/off"],
|
|
42
42
|
["review", "set light/strict/off"],
|
|
43
|
-
["checkins", "configure mid-hour check-ins"],
|
|
44
|
-
["checkin", "alias for checkins"],
|
|
45
43
|
["model", "set or inspect model override"],
|
|
46
44
|
];
|
|
47
45
|
|
|
48
46
|
const advisorNested: Record<string, Array<[string, string?]>> = {
|
|
49
47
|
mode: [["auto"], ["manual"], ["off"]],
|
|
50
48
|
review: [["light"], ["strict"], ["off"]],
|
|
51
|
-
checkins: [["on"], ["off"], ["10"], ["15"], ["30"], ["60"]],
|
|
52
|
-
checkin: [["on"], ["off"], ["10"], ["15"], ["30"], ["60"]],
|
|
53
49
|
model: [["auto"], ["openai-codex/gpt-5.5"], ["anthropic/claude-opus-4-6"]],
|
|
54
50
|
};
|
|
55
51
|
|
|
56
52
|
const piRogueTopLevel: Array<[string, string?]> = [
|
|
57
53
|
["status", "show cockpit"],
|
|
58
|
-
["advisor", "advisor status
|
|
54
|
+
["advisor", "advisor status"],
|
|
59
55
|
["orchestration", "goal/loop/autoresearch shortcuts"],
|
|
60
|
-
["checkins", "advisor check-ins"],
|
|
61
56
|
["help", "show cockpit help"],
|
|
62
57
|
];
|
|
63
58
|
|
|
@@ -70,8 +65,7 @@ const piRogueNested: Record<string, Array<[string, string?]>> = {
|
|
|
70
65
|
["autoresearch-lab", "parallel research flow"],
|
|
71
66
|
["status", "show all surfaces"],
|
|
72
67
|
],
|
|
73
|
-
|
|
74
|
-
help: [["advisor"], ["orchestration"], ["checkins"], ["status"]],
|
|
68
|
+
help: [["advisor"], ["orchestration"], ["status"]],
|
|
75
69
|
};
|
|
76
70
|
|
|
77
71
|
export function advisorArgumentCompletions(prefix: string): CompletionItem[] | null {
|
package/src/extension.test.ts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
|
-
import { describe, it,
|
|
2
|
-
import {
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { completeSimple } from "@earendil-works/pi-ai";
|
|
3
|
+
import { normalizeAdvisorConfig, shouldRunCheckin, type AdvisorConfig, completeWithHigherAdvisorModel, completeWithModelFallback } from "./extension.js";
|
|
4
|
+
|
|
5
|
+
vi.mock("@earendil-works/pi-ai", async () => {
|
|
6
|
+
const actual = await vi.importActual<typeof import("@earendil-works/pi-ai")>("@earendil-works/pi-ai");
|
|
7
|
+
return {
|
|
8
|
+
...actual,
|
|
9
|
+
completeSimple: vi.fn(),
|
|
10
|
+
};
|
|
11
|
+
});
|
|
3
12
|
|
|
4
13
|
function state(overrides: Record<string, unknown> = {}) {
|
|
5
14
|
return {
|
|
@@ -89,6 +98,80 @@ describe("mid-hour check-ins", () => {
|
|
|
89
98
|
const cfg = normalizeAdvisorConfig({ checkins: "off" });
|
|
90
99
|
expect(shouldRunCheckin(cfg, state(), 999999, 1)).toBeNull();
|
|
91
100
|
});
|
|
101
|
+
|
|
102
|
+
it("flushes queued check-in regardless of turn delta", () => {
|
|
103
|
+
const cfg = normalizeAdvisorConfig({ checkins: "mid-hour", checkinIntervalMinutes: 30 });
|
|
104
|
+
expect(
|
|
105
|
+
shouldRunCheckin(cfg, state({
|
|
106
|
+
checkin: {
|
|
107
|
+
queued: true,
|
|
108
|
+
queuedReason: "queued mid-session check-in",
|
|
109
|
+
},
|
|
110
|
+
})),
|
|
111
|
+
).toBe("queued mid-session check-in");
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
describe("advisor completion fallback behavior", () => {
|
|
117
|
+
function mkCtx(allowHighTier: boolean, includeRegular = true) {
|
|
118
|
+
const high = { id: "openai-codex/gpt-5.5", provider: "openai-codex", input: ["text"] };
|
|
119
|
+
const regular = { id: "provider/text-light", provider: "provider", input: ["text"] };
|
|
120
|
+
return {
|
|
121
|
+
modelRegistry: {
|
|
122
|
+
find: (_provider: string, model: string) => {
|
|
123
|
+
if (!allowHighTier) return null;
|
|
124
|
+
if (_provider === "openai-codex" && model === "gpt-5.5") return high;
|
|
125
|
+
if (_provider === "anthropic" && model === "claude-opus-4-6") return { ...high, id: "anthropic/claude-opus-4-6" };
|
|
126
|
+
if (_provider === "anthropic" && model === "claude-sonnet-4-6") return { ...high, id: "anthropic/claude-sonnet-4-6" };
|
|
127
|
+
if (_provider === "openai-codex" && model === "gpt-5.4-mini") return { ...high, id: "openai-codex/gpt-5.4-mini" };
|
|
128
|
+
return null;
|
|
129
|
+
},
|
|
130
|
+
getAvailable: () => (includeRegular ? [regular] : []),
|
|
131
|
+
getApiKeyAndHeaders: async (_model: unknown) => ({ ok: true, apiKey: "k", headers: {} }),
|
|
132
|
+
},
|
|
133
|
+
} as any;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
it("uses high/advanced models first for check-in completion", async () => {
|
|
137
|
+
const completeSimpleMock = vi.mocked(completeSimple as any);
|
|
138
|
+
completeSimpleMock.mockReset();
|
|
139
|
+
completeSimpleMock.mockResolvedValue({ content: [{ type: "text", text: "ok" }] });
|
|
140
|
+
|
|
141
|
+
const cfg = normalizeAdvisorConfig({ mode: "auto", review: "light" });
|
|
142
|
+
const result = await completeWithHigherAdvisorModel(mkCtx(true, true), cfg, "system", [{ role: "user", content: "x" }], { maxTokens: 128, reasoning: "low" as const });
|
|
143
|
+
|
|
144
|
+
expect(result).not.toBeNull();
|
|
145
|
+
expect(completeSimpleMock).toHaveBeenCalledTimes(1);
|
|
146
|
+
expect(completeSimpleMock.mock.calls[0]?.[0]?.id).toBe("openai-codex/gpt-5.5");
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it("falls back to regular models for check-in completion when high/advanced are unavailable", async () => {
|
|
150
|
+
const completeSimpleMock = vi.mocked(completeSimple as any);
|
|
151
|
+
completeSimpleMock.mockReset();
|
|
152
|
+
completeSimpleMock.mockResolvedValue({ content: [{ type: "text", text: "ok" }] });
|
|
153
|
+
|
|
154
|
+
const cfg = normalizeAdvisorConfig({ mode: "auto", review: "light" });
|
|
155
|
+
const result = await completeWithHigherAdvisorModel(mkCtx(false, true), cfg, "system", [{ role: "user", content: "x" }], { maxTokens: 128, reasoning: "low" as const });
|
|
156
|
+
|
|
157
|
+
expect(result).not.toBeNull();
|
|
158
|
+
expect(completeSimpleMock).toHaveBeenCalledTimes(1);
|
|
159
|
+
expect(completeSimpleMock.mock.calls[0]?.[0]?.id).toBe("provider/text-light");
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it("uses regular fallback for non-checkin completion", async () => {
|
|
163
|
+
const completeSimpleMock = vi.mocked(completeSimple as any);
|
|
164
|
+
completeSimpleMock.mockReset();
|
|
165
|
+
completeSimpleMock.mockResolvedValue({ content: [{ type: "text", text: "ok" }] });
|
|
166
|
+
|
|
167
|
+
const cfg = normalizeAdvisorConfig({ mode: "auto", review: "light" });
|
|
168
|
+
const result = await completeWithModelFallback(mkCtx(false), cfg, "system", [{ role: "user", content: "x" }], { maxTokens: 128, reasoning: "low" as const });
|
|
169
|
+
|
|
170
|
+
expect(result).not.toBeNull();
|
|
171
|
+
expect(result?.fallback).toBe(true);
|
|
172
|
+
expect(completeSimpleMock).toHaveBeenCalledTimes(1);
|
|
173
|
+
expect(completeSimpleMock.mock.calls[0]?.[0]?.id).toBe("provider/text-light");
|
|
174
|
+
});
|
|
92
175
|
});
|
|
93
176
|
|
|
94
177
|
|