@juicesharp/rpiv-advisor 1.6.1 → 1.7.0
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/advisor.ts +84 -5
- package/index.ts +5 -3
- package/package.json +1 -1
package/advisor.ts
CHANGED
|
@@ -84,6 +84,10 @@ const msgAdvisorEnabled = (label: string, effort: ThinkingLevel | undefined) =>
|
|
|
84
84
|
`Advisor: ${label}${effort ? `, ${effort}` : ""}`;
|
|
85
85
|
const msgAdvisorRestored = (label: string, effort: ThinkingLevel | undefined) =>
|
|
86
86
|
`Advisor restored: ${label}${effort ? `, ${effort}` : ""}`;
|
|
87
|
+
const msgAdvisorRestoredInactive = (label: string, effort: ThinkingLevel | undefined) =>
|
|
88
|
+
`Advisor restored: ${label}${effort ? `, ${effort}` : ""} (inactive for current executor)`;
|
|
89
|
+
const msgAdvisorEnabledInactive = (label: string, effort: ThinkingLevel | undefined) =>
|
|
90
|
+
`Advisor: ${label}${effort ? `, ${effort}` : ""} (inactive for current executor)`;
|
|
87
91
|
const msgConsulting = (label: string, effort: ThinkingLevel | undefined) =>
|
|
88
92
|
`Consulting advisor (${label}${effort ? `, ${effort}` : ""})…`;
|
|
89
93
|
|
|
@@ -100,6 +104,7 @@ interface AdvisorConfig {
|
|
|
100
104
|
modelKey?: string;
|
|
101
105
|
effort?: ThinkingLevel;
|
|
102
106
|
guidance?: GuidanceFields;
|
|
107
|
+
disabledForModels?: string[];
|
|
103
108
|
}
|
|
104
109
|
|
|
105
110
|
export function loadAdvisorConfig(): AdvisorConfig {
|
|
@@ -128,6 +133,11 @@ function validateGuidanceFields(fields: unknown): GuidanceFields {
|
|
|
128
133
|
return result;
|
|
129
134
|
}
|
|
130
135
|
|
|
136
|
+
function validateDisabledForModels(value: unknown): string[] {
|
|
137
|
+
if (!Array.isArray(value)) return [];
|
|
138
|
+
return value.filter((entry): entry is string => typeof entry === "string" && entry.length > 0);
|
|
139
|
+
}
|
|
140
|
+
|
|
131
141
|
export function saveAdvisorConfig(key: string | undefined, effort: ThinkingLevel | undefined): void {
|
|
132
142
|
const existing = loadAdvisorConfig();
|
|
133
143
|
const config: AdvisorConfig = { ...existing };
|
|
@@ -297,12 +307,21 @@ export function setAdvisorEffort(effort: ThinkingLevel | undefined): void {
|
|
|
297
307
|
selectedAdvisorEffort = effort;
|
|
298
308
|
}
|
|
299
309
|
|
|
310
|
+
let disabledForModelsCache: string[] = [];
|
|
311
|
+
|
|
312
|
+
export function setDisabledForModels(models: string[]): void {
|
|
313
|
+
disabledForModelsCache = models;
|
|
314
|
+
}
|
|
315
|
+
|
|
300
316
|
// ---------------------------------------------------------------------------
|
|
301
317
|
// Session restoration — called from index.ts session_start handler
|
|
302
318
|
// ---------------------------------------------------------------------------
|
|
303
319
|
|
|
304
320
|
export function restoreAdvisorState(ctx: ExtensionContext, pi: ExtensionAPI): void {
|
|
305
321
|
const config = loadAdvisorConfig();
|
|
322
|
+
|
|
323
|
+
setDisabledForModels(validateDisabledForModels(config.disabledForModels));
|
|
324
|
+
|
|
306
325
|
if (!config.modelKey) return;
|
|
307
326
|
|
|
308
327
|
const parsed = parseModelKey(config.modelKey);
|
|
@@ -321,6 +340,14 @@ export function restoreAdvisorState(ctx: ExtensionContext, pi: ExtensionAPI): vo
|
|
|
321
340
|
setAdvisorEffort(config.effort);
|
|
322
341
|
}
|
|
323
342
|
|
|
343
|
+
if (isExecutorBlocked(ctx)) {
|
|
344
|
+
if (ctx.hasUI) {
|
|
345
|
+
const advisorLabel = `${model.provider}:${model.id}`;
|
|
346
|
+
ctx.ui.notify(msgAdvisorRestoredInactive(advisorLabel, config.effort), "info");
|
|
347
|
+
}
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
|
|
324
351
|
const active = pi.getActiveTools();
|
|
325
352
|
if (!active.includes(ADVISOR_TOOL_NAME)) {
|
|
326
353
|
pi.setActiveTools([...active, ADVISOR_TOOL_NAME]);
|
|
@@ -511,8 +538,9 @@ export function registerAdvisorTool(pi: ExtensionAPI): void {
|
|
|
511
538
|
// ---------------------------------------------------------------------------
|
|
512
539
|
|
|
513
540
|
export function registerAdvisorBeforeAgentStart(pi: ExtensionAPI): void {
|
|
514
|
-
pi.on("before_agent_start", async () => {
|
|
515
|
-
|
|
541
|
+
pi.on("before_agent_start", async (_event, ctx) => {
|
|
542
|
+
const shouldStrip = !getAdvisorModel() || isExecutorBlocked(ctx);
|
|
543
|
+
if (shouldStrip) {
|
|
516
544
|
const active = pi.getActiveTools();
|
|
517
545
|
if (active.includes(ADVISOR_TOOL_NAME)) {
|
|
518
546
|
pi.setActiveTools(active.filter((n) => n !== ADVISOR_TOOL_NAME));
|
|
@@ -521,6 +549,38 @@ export function registerAdvisorBeforeAgentStart(pi: ExtensionAPI): void {
|
|
|
521
549
|
});
|
|
522
550
|
}
|
|
523
551
|
|
|
552
|
+
// ---------------------------------------------------------------------------
|
|
553
|
+
// model_select handler — mid-session model switches strip/re-add advisor
|
|
554
|
+
// ---------------------------------------------------------------------------
|
|
555
|
+
|
|
556
|
+
export function registerModelSelectHandler(pi: ExtensionAPI): void {
|
|
557
|
+
pi.on("model_select", async (event, ctx) => {
|
|
558
|
+
// session_start restore path is owned by restoreAdvisorState — it already
|
|
559
|
+
// activates the tool and notifies. Skipping "restore" here prevents a
|
|
560
|
+
// duplicate notification on initial model load.
|
|
561
|
+
if (event.source === "restore") return;
|
|
562
|
+
|
|
563
|
+
const advisor = getAdvisorModel();
|
|
564
|
+
if (!advisor) return;
|
|
565
|
+
|
|
566
|
+
const blocked = isModelBlocked(event.model);
|
|
567
|
+
const active = pi.getActiveTools();
|
|
568
|
+
const hasTool = active.includes(ADVISOR_TOOL_NAME);
|
|
569
|
+
|
|
570
|
+
if (blocked && hasTool) {
|
|
571
|
+
pi.setActiveTools(active.filter((n) => n !== ADVISOR_TOOL_NAME));
|
|
572
|
+
if (ctx.hasUI) {
|
|
573
|
+
ctx.ui.notify(`Advisor disabled for ${modelKey(event.model)}`, "info");
|
|
574
|
+
}
|
|
575
|
+
} else if (!blocked && !hasTool) {
|
|
576
|
+
pi.setActiveTools([...active, ADVISOR_TOOL_NAME]);
|
|
577
|
+
if (ctx.hasUI) {
|
|
578
|
+
ctx.ui.notify(msgAdvisorRestored(modelKey(advisor), getAdvisorEffort()), "info");
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
|
|
524
584
|
// ---------------------------------------------------------------------------
|
|
525
585
|
// /advisor slash command — opens selector panel for picking the advisor model
|
|
526
586
|
// ---------------------------------------------------------------------------
|
|
@@ -529,6 +589,15 @@ function modelKey(m: { provider: string; id: string }): string {
|
|
|
529
589
|
return `${m.provider}:${m.id}`;
|
|
530
590
|
}
|
|
531
591
|
|
|
592
|
+
function isModelBlocked(model: Model<Api> | undefined): boolean {
|
|
593
|
+
if (!model) return false;
|
|
594
|
+
return disabledForModelsCache.includes(modelKey(model));
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
function isExecutorBlocked(ctx: ExtensionContext): boolean {
|
|
598
|
+
return isModelBlocked(ctx?.model);
|
|
599
|
+
}
|
|
600
|
+
|
|
532
601
|
export function registerAdvisorCommand(pi: ExtensionAPI): void {
|
|
533
602
|
pi.registerCommand("advisor", {
|
|
534
603
|
description: "Configure the advisor model for the advisor-strategy pattern",
|
|
@@ -602,10 +671,20 @@ export function registerAdvisorCommand(pi: ExtensionAPI): void {
|
|
|
602
671
|
setAdvisorEffort(effortChoice);
|
|
603
672
|
setAdvisorModel(picked);
|
|
604
673
|
saveAdvisorConfig(modelKey(picked), effortChoice);
|
|
605
|
-
|
|
606
|
-
|
|
674
|
+
|
|
675
|
+
// Re-read after the effort-picker await — the snapshot taken before
|
|
676
|
+
// `showEffortPicker` is stale once execution yields.
|
|
677
|
+
const activeToolsNow = pi.getActiveTools();
|
|
678
|
+
const activeHasNow = activeToolsNow.includes(ADVISOR_TOOL_NAME);
|
|
679
|
+
const blocked = isExecutorBlocked(ctx);
|
|
680
|
+
if (!activeHasNow && !blocked) {
|
|
681
|
+
pi.setActiveTools([...activeToolsNow, ADVISOR_TOOL_NAME]);
|
|
682
|
+
}
|
|
683
|
+
if (blocked) {
|
|
684
|
+
ctx.ui.notify(msgAdvisorEnabledInactive(modelKey(picked), effortChoice), "info");
|
|
685
|
+
} else {
|
|
686
|
+
ctx.ui.notify(msgAdvisorEnabled(modelKey(picked), effortChoice), "info");
|
|
607
687
|
}
|
|
608
|
-
ctx.ui.notify(msgAdvisorEnabled(modelKey(picked), effortChoice), "info");
|
|
609
688
|
},
|
|
610
689
|
});
|
|
611
690
|
}
|
package/index.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* rpiv-advisor — Pi extension
|
|
3
3
|
*
|
|
4
|
-
* Registers the `advisor` tool, `/advisor` command, and the
|
|
5
|
-
* hooks (session_start restore, before_agent_start strip
|
|
6
|
-
* implement the advisor-strategy pattern.
|
|
4
|
+
* Registers the `advisor` tool, `/advisor` command, and the three lifecycle
|
|
5
|
+
* hooks (session_start restore, before_agent_start strip, model_select
|
|
6
|
+
* re-evaluation) that together implement the advisor-strategy pattern.
|
|
7
7
|
*
|
|
8
8
|
* Config persists at ~/.config/rpiv-advisor/advisor.json. Tool name
|
|
9
9
|
* preserved verbatim from rpiv-pi@7525a5d.
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
registerAdvisorBeforeAgentStart,
|
|
15
15
|
registerAdvisorCommand,
|
|
16
16
|
registerAdvisorTool,
|
|
17
|
+
registerModelSelectHandler,
|
|
17
18
|
restoreAdvisorState,
|
|
18
19
|
} from "./advisor.js";
|
|
19
20
|
|
|
@@ -21,6 +22,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
21
22
|
registerAdvisorTool(pi);
|
|
22
23
|
registerAdvisorCommand(pi);
|
|
23
24
|
registerAdvisorBeforeAgentStart(pi);
|
|
25
|
+
registerModelSelectHandler(pi);
|
|
24
26
|
|
|
25
27
|
pi.on("session_start", async (_event, ctx) => {
|
|
26
28
|
restoreAdvisorState(ctx, pi);
|