@fiale-plus/pi-rogue-advisor 0.1.3 → 0.1.4
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 +1 -1
- package/src/completions.test.ts +31 -0
- package/src/completions.ts +83 -0
- package/src/extension.ts +41 -1
package/package.json
CHANGED
|
@@ -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,
|
|
@@ -666,10 +667,48 @@ export function registerAdvisor(pi: ExtensionAPI): void {
|
|
|
666
667
|
// ── /pi-rogue cockpit ──────────────────────────────────────────────────
|
|
667
668
|
pi.registerCommand("pi-rogue", {
|
|
668
669
|
description: "Show PiRogue cockpit: advisor, check-ins, and orchestration command pointers",
|
|
669
|
-
|
|
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+/);
|