@juicesharp/rpiv-advisor 2.5.2 → 2.6.1
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 +1 -1
- package/advisor/command.ts +36 -14
- package/advisor/config.ts +15 -8
- package/advisor/execute.ts +12 -7
- package/advisor/messages.ts +9 -5
- package/advisor/policy.ts +13 -3
- package/advisor/restore.ts +23 -5
- package/advisor/state.ts +5 -4
- package/docs/configuration.md +13 -7
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -78,7 +78,7 @@ write leaves your previous selection untouched and tells you so.
|
|
|
78
78
|
| Key | What it does | Default |
|
|
79
79
|
| --- | --- | --- |
|
|
80
80
|
| `modelKey` | The reviewer model, as `"provider/modelId"`. Written by `/advisor`. | absent — advisor off |
|
|
81
|
-
| `effort` | Reasoning effort for the reviewer: `minimal`, `low`, `medium`, `high`, `xhigh`. Written by `/advisor
|
|
81
|
+
| `effort` | Reasoning effort for the reviewer: `minimal`, `low`, `medium`, `high`, `xhigh`, `max`. Written by `/advisor`; only levels supported by the selected model are offered. | absent — no reasoning sent |
|
|
82
82
|
| `disabledForModels` | Executor models the advisor is stripped for. Plain strings block at any effort; `{ "model": "…", "minEffort": "…" }` blocks only at or above that effort. | `[]` |
|
|
83
83
|
|
|
84
84
|
```json
|
package/advisor/command.ts
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
* command — the /advisor slash command. Reads top-down: interactive guard →
|
|
3
3
|
* model picker (buildModelItems) → no-advisor branch (applyDisable) → model
|
|
4
4
|
* lookup → effort picker (buildEffortItems) → enable (applyEnable). The apply
|
|
5
|
-
* helpers persist before mutating in-memory state
|
|
5
|
+
* helpers persist before mutating in-memory state — a save failure must never
|
|
6
|
+
* leave memory ahead of disk.
|
|
6
7
|
*/
|
|
7
8
|
|
|
8
9
|
import type { Api, Model } from "@earendil-works/pi-ai";
|
|
9
|
-
import { getSupportedThinkingLevels
|
|
10
|
+
import { getSupportedThinkingLevels } from "@earendil-works/pi-ai";
|
|
10
11
|
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
11
12
|
import type { SelectItem } from "@earendil-works/pi-tui";
|
|
12
13
|
import { modelKey } from "@juicesharp/rpiv-config";
|
|
@@ -15,11 +16,13 @@ import { saveAdvisorConfig } from "./config.js";
|
|
|
15
16
|
import { reconcileAdvisorTool } from "./handlers.js";
|
|
16
17
|
import {
|
|
17
18
|
ADVISOR_TOOL_NAME,
|
|
18
|
-
BASE_EFFORT_LEVELS,
|
|
19
19
|
CHECKMARK,
|
|
20
20
|
DEFAULT_EFFORT,
|
|
21
|
+
EFFORT_ORDINAL,
|
|
21
22
|
errSelectionNotFound,
|
|
23
|
+
type GradedEffort,
|
|
22
24
|
MSG_ADVISOR_DISABLED,
|
|
25
|
+
MSG_EFFORT_NOT_SET,
|
|
23
26
|
MSG_PERSIST_FAILED,
|
|
24
27
|
MSG_REQUIRES_INTERACTIVE,
|
|
25
28
|
msgAdvisorEnabled,
|
|
@@ -27,11 +30,13 @@ import {
|
|
|
27
30
|
NO_ADVISOR_VALUE,
|
|
28
31
|
OFF_VALUE,
|
|
29
32
|
RECOMMENDED_EFFORT_SUFFIX,
|
|
30
|
-
XHIGH_EFFORT_LEVEL,
|
|
31
33
|
} from "./messages.js";
|
|
32
34
|
import { isExecutorBlocked } from "./policy.js";
|
|
33
35
|
import { getAdvisorEffort, getAdvisorModel, setAdvisorEffort, setAdvisorModel } from "./state.js";
|
|
34
36
|
|
|
37
|
+
// Mirror: packages/rpiv-pi/extensions/rpiv-core/rpiv-models/items.ts
|
|
38
|
+
// buildModelItems — structural twin kept in a separate package by the
|
|
39
|
+
// zero-cross-imports contract; evolve model-picker semantics together.
|
|
35
40
|
function buildModelItems(availableModels: Model<Api>[], currentKey: string | undefined): SelectItem[] {
|
|
36
41
|
const items: SelectItem[] = availableModels.map((m) => {
|
|
37
42
|
const key = modelKey(m);
|
|
@@ -45,12 +50,20 @@ function buildModelItems(availableModels: Model<Api>[], currentKey: string | und
|
|
|
45
50
|
return items;
|
|
46
51
|
}
|
|
47
52
|
|
|
53
|
+
// Mirror: packages/rpiv-pi/extensions/rpiv-core/rpiv-models/items.ts
|
|
54
|
+
// buildEffortItems — same filter-in/map-out shape, different sentinels and
|
|
55
|
+
// persist target; evolve level-picker semantics together.
|
|
48
56
|
function buildEffortItems(picked: Model<Api>): SelectItem[] {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
57
|
+
// Intersect with EFFORT_ORDINAL (which excludes "off") so the picker can
|
|
58
|
+
// never offer — hence saveAdvisorConfig can never persist — a level that
|
|
59
|
+
// minEffort blocklist comparisons don't rank.
|
|
60
|
+
const levels = getSupportedThinkingLevels(picked).filter((level): level is GradedEffort =>
|
|
61
|
+
EFFORT_ORDINAL.includes(level as GradedEffort),
|
|
62
|
+
);
|
|
52
63
|
return [
|
|
53
|
-
|
|
64
|
+
// "off (no reasoning sent)" ≠ /rpiv-models' "off (disable reasoning)":
|
|
65
|
+
// this row sends NO reasoning option; /rpiv-models persists thinking:"off".
|
|
66
|
+
{ value: OFF_VALUE, label: "off (no reasoning sent)" },
|
|
54
67
|
...levels.map((level) => ({
|
|
55
68
|
value: level,
|
|
56
69
|
label: level === DEFAULT_EFFORT ? `${level}${RECOMMENDED_EFFORT_SUFFIX}` : level,
|
|
@@ -59,7 +72,7 @@ function buildEffortItems(picked: Model<Api>): SelectItem[] {
|
|
|
59
72
|
}
|
|
60
73
|
|
|
61
74
|
// Disable path — persist BEFORE mutating in-memory state so a save failure
|
|
62
|
-
// can't strand "model=undefined + tool still registered"
|
|
75
|
+
// can't strand "model=undefined + tool still registered". The strip
|
|
63
76
|
// is unconditional-on-presence (no advisor at all), so it stays inline rather
|
|
64
77
|
// than routing through reconcileAdvisorTool's blocked-conditional path.
|
|
65
78
|
function applyDisable(pi: ExtensionAPI, ctx: ExtensionContext): void {
|
|
@@ -76,7 +89,7 @@ function applyDisable(pi: ExtensionAPI, ctx: ExtensionContext): void {
|
|
|
76
89
|
ctx.ui.notify(MSG_ADVISOR_DISABLED, "info");
|
|
77
90
|
}
|
|
78
91
|
|
|
79
|
-
// Enable path — persist first
|
|
92
|
+
// Enable path — persist first, set in-memory state, activate via
|
|
80
93
|
// reconcileAdvisorTool (which re-reads the active-tool list post-effort-picker-
|
|
81
94
|
// await), and notify. Silent reconcile — the enable/inactive notify is the
|
|
82
95
|
// single trailing notify call here.
|
|
@@ -84,7 +97,7 @@ function applyEnable(
|
|
|
84
97
|
pi: ExtensionAPI,
|
|
85
98
|
ctx: ExtensionContext,
|
|
86
99
|
picked: Model<Api>,
|
|
87
|
-
effort:
|
|
100
|
+
effort: GradedEffort | undefined,
|
|
88
101
|
): void {
|
|
89
102
|
if (!saveAdvisorConfig(modelKey(picked), effort)) {
|
|
90
103
|
ctx.ui.notify(MSG_PERSIST_FAILED, "error");
|
|
@@ -129,7 +142,7 @@ export function registerAdvisorCommand(pi: ExtensionAPI): void {
|
|
|
129
142
|
}
|
|
130
143
|
|
|
131
144
|
// Effort picker — only for reasoning-capable models
|
|
132
|
-
let effortChoice:
|
|
145
|
+
let effortChoice: GradedEffort | undefined;
|
|
133
146
|
if (picked.reasoning) {
|
|
134
147
|
const effortResult = await showEffortPicker(
|
|
135
148
|
ctx,
|
|
@@ -137,8 +150,17 @@ export function registerAdvisorCommand(pi: ExtensionAPI): void {
|
|
|
137
150
|
getAdvisorEffort(),
|
|
138
151
|
DEFAULT_EFFORT,
|
|
139
152
|
);
|
|
140
|
-
if (!effortResult)
|
|
141
|
-
|
|
153
|
+
if (!effortResult) {
|
|
154
|
+
// Esc at the effort step keeps the model selection — cancelling
|
|
155
|
+
// one step never discards prior choices (the invariant shared
|
|
156
|
+
// with the /rpiv-models stepper). The divergence is deliberate:
|
|
157
|
+
// that twin backs up without writing, while here the enable
|
|
158
|
+
// proceeds and PERSISTS with no explicit effort (model default),
|
|
159
|
+
// announced by this notify before the write.
|
|
160
|
+
ctx.ui.notify(MSG_EFFORT_NOT_SET, "info");
|
|
161
|
+
} else {
|
|
162
|
+
effortChoice = effortResult === OFF_VALUE ? undefined : (effortResult as GradedEffort);
|
|
163
|
+
}
|
|
142
164
|
}
|
|
143
165
|
|
|
144
166
|
applyEnable(pi, ctx, picked, effortChoice);
|
package/advisor/config.ts
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* config — persisted advisor config (~/.config/rpiv-advisor/advisor.json) and
|
|
3
|
-
* the provider:id key codec. Owns the AdvisorConfig shape
|
|
4
|
-
*
|
|
3
|
+
* the provider:id key codec. Owns the AdvisorConfig shape and load/validate/save.
|
|
4
|
+
* The modelKey (join) / parseModelKey (split) inverse pair the codec relies on
|
|
5
|
+
* lives in @juicesharp/rpiv-config.
|
|
5
6
|
*/
|
|
6
7
|
|
|
7
|
-
import type { ThinkingLevel } from "@earendil-works/pi-ai";
|
|
8
8
|
import type { GuidanceFields } from "@juicesharp/rpiv-config";
|
|
9
9
|
import { configPath, loadJsonConfigWithLegacyFallback, saveJsonConfig } from "@juicesharp/rpiv-config";
|
|
10
|
-
import { EFFORT_ORDINAL } from "./messages.js";
|
|
10
|
+
import { EFFORT_ORDINAL, type GradedEffort } from "./messages.js";
|
|
11
11
|
|
|
12
12
|
const ADVISOR_CONFIG_PATH = configPath("rpiv-advisor", "advisor.json");
|
|
13
13
|
|
|
14
|
-
export type DisabledForModelsEntry = string | { model: string; minEffort?:
|
|
14
|
+
export type DisabledForModelsEntry = string | { model: string; minEffort?: GradedEffort };
|
|
15
15
|
|
|
16
16
|
interface AdvisorConfig {
|
|
17
17
|
modelKey?: string;
|
|
18
|
-
effort?:
|
|
18
|
+
effort?: GradedEffort;
|
|
19
19
|
guidance?: GuidanceFields;
|
|
20
20
|
disabledForModels?: DisabledForModelsEntry[];
|
|
21
21
|
}
|
|
@@ -31,12 +31,19 @@ export function validateDisabledForModels(value: unknown): DisabledForModelsEntr
|
|
|
31
31
|
if (typeof entry !== "object" || entry === null) return false;
|
|
32
32
|
const obj = entry as Record<string, unknown>;
|
|
33
33
|
if (typeof obj.model !== "string" || obj.model.length === 0) return false;
|
|
34
|
-
if (obj.minEffort !== undefined && !EFFORT_ORDINAL.includes(obj.minEffort as
|
|
34
|
+
if (obj.minEffort !== undefined && !EFFORT_ORDINAL.includes(obj.minEffort as GradedEffort)) {
|
|
35
|
+
// Warn before dropping — the entry's model identity is discarded along
|
|
36
|
+
// with the bad threshold (mirrors models-config's warn-on-miss posture).
|
|
37
|
+
console.warn(
|
|
38
|
+
`[rpiv-advisor] advisor.json: unknown minEffort "${String(obj.minEffort)}" — dropping disabledForModels entry for "${obj.model}"`,
|
|
39
|
+
);
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
35
42
|
return true;
|
|
36
43
|
});
|
|
37
44
|
}
|
|
38
45
|
|
|
39
|
-
export function saveAdvisorConfig(key: string | undefined, effort:
|
|
46
|
+
export function saveAdvisorConfig(key: string | undefined, effort: GradedEffort | undefined): boolean {
|
|
40
47
|
const existing = loadAdvisorConfig();
|
|
41
48
|
const config: AdvisorConfig = { ...existing };
|
|
42
49
|
// Delete (rather than omit) to clear fields that may exist in the spread
|
package/advisor/execute.ts
CHANGED
|
@@ -105,7 +105,12 @@ export async function executeAdvisor(
|
|
|
105
105
|
if (!auth.ok) {
|
|
106
106
|
return buildErrorResult(advisorLabel, effort, errMisconfigured(advisorLabel, auth.error), auth.error);
|
|
107
107
|
}
|
|
108
|
-
|
|
108
|
+
// OAuth-backed providers resolve `{ ok: true }` with no literal apiKey — their
|
|
109
|
+
// credentials are applied inside Pi's runtime facade. A missing key is only
|
|
110
|
+
// fatal on legacy hosts without that facade, where the global completion
|
|
111
|
+
// fallback needs the key passed explicitly.
|
|
112
|
+
const runtimeCompleteSimple = getRuntimeCompleteSimple(ctx.modelRegistry);
|
|
113
|
+
if (!auth.apiKey && !runtimeCompleteSimple) {
|
|
109
114
|
return buildErrorResult(advisorLabel, effort, errNoApiKey(advisorLabel), errNoApiKeyDetail(advisor.provider));
|
|
110
115
|
}
|
|
111
116
|
|
|
@@ -129,12 +134,12 @@ export async function executeAdvisor(
|
|
|
129
134
|
});
|
|
130
135
|
|
|
131
136
|
try {
|
|
132
|
-
// Prefer Pi's auth-aware runtime facade
|
|
133
|
-
//
|
|
134
|
-
//
|
|
135
|
-
//
|
|
136
|
-
//
|
|
137
|
-
|
|
137
|
+
// Prefer Pi's auth-aware runtime facade (resolved once above, before the
|
|
138
|
+
// missing-key guard). Unlike the global compatibility function, it runs
|
|
139
|
+
// request preparation and applies credential-derived fields such as GitHub
|
|
140
|
+
// Copilot's OAuth-specific baseUrl. Do not pass the preflight key/headers
|
|
141
|
+
// to this path: explicit overrides would bypass that resolution and
|
|
142
|
+
// reintroduce the endpoint mismatch.
|
|
138
143
|
const completeSimple = runtimeCompleteSimple ?? (await loadCompleteSimple());
|
|
139
144
|
const requestOptions = runtimeCompleteSimple
|
|
140
145
|
? { signal, reasoning: effort }
|
package/advisor/messages.ts
CHANGED
|
@@ -14,11 +14,14 @@ export const TOOL_LABEL = "Advisor";
|
|
|
14
14
|
export const NO_ADVISOR_VALUE = "__no_advisor__";
|
|
15
15
|
export const OFF_VALUE = "__off__";
|
|
16
16
|
|
|
17
|
-
// Effort levels
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
// Effort levels. GradedEffort is the ordinal's domain: the graded levels only,
|
|
18
|
+
// never "off" — an "off" element would corrupt the indexOf ranking that
|
|
19
|
+
// minEffort thresholds compare against. Today pi-ai's ThinkingLevel already
|
|
20
|
+
// excludes "off" (the Exclude is a defensive no-op); the alias keeps that
|
|
21
|
+
// exclusion structural if the upstream universe ever re-widens.
|
|
22
|
+
export type GradedEffort = Exclude<ThinkingLevel, "off">;
|
|
23
|
+
export const EFFORT_ORDINAL: readonly GradedEffort[] = ["minimal", "low", "medium", "high", "xhigh", "max"];
|
|
24
|
+
export const DEFAULT_EFFORT: GradedEffort = "high";
|
|
22
25
|
export const RECOMMENDED_EFFORT_SUFFIX = " (recommended)";
|
|
23
26
|
|
|
24
27
|
// UI — labels used by command flow; panel prose/titles live in advisor-ui.ts
|
|
@@ -28,6 +31,7 @@ export const CHECKMARK = " ✓";
|
|
|
28
31
|
export const MSG_ADVISOR_DISABLED = "Advisor disabled";
|
|
29
32
|
export const MSG_REQUIRES_INTERACTIVE = "/advisor requires interactive mode";
|
|
30
33
|
export const MSG_ADVISOR_NUDGE = "Please advise on the executor's situation above.";
|
|
34
|
+
export const MSG_EFFORT_NOT_SET = "Effort not set — advisor uses the model default";
|
|
31
35
|
export const MSG_PERSIST_FAILED = "Failed to save advisor selection — selection not persisted";
|
|
32
36
|
|
|
33
37
|
// Errors (static)
|
package/advisor/policy.ts
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
* that decide whether the advisor tool is blocked for a given model/effort.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type { Api, Model
|
|
6
|
+
import type { Api, Model } from "@earendil-works/pi-ai";
|
|
7
7
|
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
8
8
|
import { modelKey, parseModelKey } from "@juicesharp/rpiv-config";
|
|
9
9
|
import type { DisabledForModelsEntry } from "./config.js";
|
|
10
|
-
import { EFFORT_ORDINAL } from "./messages.js";
|
|
10
|
+
import { EFFORT_ORDINAL, type GradedEffort } from "./messages.js";
|
|
11
11
|
|
|
12
12
|
let disabledForModelsCache: DisabledForModelsEntry[] = [];
|
|
13
13
|
|
|
@@ -27,6 +27,12 @@ function canonicalKey(entry: string): string {
|
|
|
27
27
|
return parsed ? `${parsed.provider}/${parsed.modelId}` : entry;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
/**
|
|
31
|
+
* True when `model` is on the disabledForModels blocklist at the executor's
|
|
32
|
+
* current thinking level. Fail-soft ranking contract: an executor level that
|
|
33
|
+
* is unset, "off", or unknown to EFFORT_ORDINAL yields indexOf −1, ranking
|
|
34
|
+
* below every minEffort threshold — such levels never block.
|
|
35
|
+
*/
|
|
30
36
|
export function isModelBlocked(model: Model<Api> | undefined, thinkingLevel?: string): boolean {
|
|
31
37
|
if (!model) return false;
|
|
32
38
|
const key = modelKey(model);
|
|
@@ -37,7 +43,11 @@ export function isModelBlocked(model: Model<Api> | undefined, thinkingLevel?: st
|
|
|
37
43
|
if (canonicalKey(entry.model) !== key) continue;
|
|
38
44
|
if (entry.minEffort === undefined) return true;
|
|
39
45
|
const thresholdOrdinal = EFFORT_ORDINAL.indexOf(entry.minEffort);
|
|
40
|
-
|
|
46
|
+
// A threshold unknown to the ordinal cannot rank; skip the entry —
|
|
47
|
+
// otherwise its indexOf -1 would equal an unknown executor's -1 and
|
|
48
|
+
// block, breaking the "unknown never blocks" contract above.
|
|
49
|
+
if (thresholdOrdinal === -1) continue;
|
|
50
|
+
const executorOrdinal = EFFORT_ORDINAL.indexOf(thinkingLevel as GradedEffort);
|
|
41
51
|
if (executorOrdinal >= thresholdOrdinal) return true;
|
|
42
52
|
}
|
|
43
53
|
}
|
package/advisor/restore.ts
CHANGED
|
@@ -8,7 +8,13 @@ import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-a
|
|
|
8
8
|
import { modelKey, parseModelKey } from "@juicesharp/rpiv-config";
|
|
9
9
|
import { loadAdvisorConfig, validateDisabledForModels } from "./config.js";
|
|
10
10
|
import { reconcileAdvisorTool } from "./handlers.js";
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
ADVISOR_TOOL_NAME,
|
|
13
|
+
EFFORT_ORDINAL,
|
|
14
|
+
errModelUnavailable,
|
|
15
|
+
msgAdvisorRestored,
|
|
16
|
+
msgAdvisorRestoredInactive,
|
|
17
|
+
} from "./messages.js";
|
|
12
18
|
import { isExecutorBlocked, setDisabledForModels } from "./policy.js";
|
|
13
19
|
import { setAdvisorEffort, setAdvisorModel } from "./state.js";
|
|
14
20
|
|
|
@@ -74,14 +80,26 @@ export function restoreAdvisorState(ctx: ExtensionContext, pi: ExtensionAPI): vo
|
|
|
74
80
|
}
|
|
75
81
|
|
|
76
82
|
setAdvisorModel(model);
|
|
77
|
-
|
|
78
|
-
|
|
83
|
+
// Overwrite — never merge — the in-memory effort with the persisted value.
|
|
84
|
+
// "Model present, effort absent" is a first-class persisted state (the
|
|
85
|
+
// /advisor Esc and off choices both save it), and another process can
|
|
86
|
+
// remove the field from the shared advisor.json mid-session; a guarded set
|
|
87
|
+
// here would leave a stale module-level effort feeding `reasoning` on every
|
|
88
|
+
// advisor call. A hand-edited value unknown to EFFORT_ORDINAL is dropped
|
|
89
|
+
// with a warning rather than restored and sent as `reasoning`.
|
|
90
|
+
let effort = config.effort;
|
|
91
|
+
if (effort !== undefined && !EFFORT_ORDINAL.includes(effort)) {
|
|
92
|
+
console.warn(
|
|
93
|
+
`[rpiv-advisor] advisor.json: unknown effort "${effort}" — ignoring (valid values: ${EFFORT_ORDINAL.join(", ")})`,
|
|
94
|
+
);
|
|
95
|
+
effort = undefined;
|
|
79
96
|
}
|
|
97
|
+
setAdvisorEffort(effort);
|
|
80
98
|
|
|
81
99
|
if (isExecutorBlocked(ctx, pi.getThinkingLevel())) {
|
|
82
100
|
reconcileAdvisorTool(pi, ctx, { blocked: true });
|
|
83
101
|
const advisorLabel = modelKey(model);
|
|
84
|
-
notifyOnce(msgAdvisorRestoredInactive(advisorLabel,
|
|
102
|
+
notifyOnce(msgAdvisorRestoredInactive(advisorLabel, effort), "info");
|
|
85
103
|
return;
|
|
86
104
|
}
|
|
87
105
|
|
|
@@ -90,7 +108,7 @@ export function restoreAdvisorState(ctx: ExtensionContext, pi: ExtensionAPI): vo
|
|
|
90
108
|
pi.setActiveTools([...active, ADVISOR_TOOL_NAME]);
|
|
91
109
|
}
|
|
92
110
|
|
|
93
|
-
notifyOnce(msgAdvisorRestored(modelKey(model),
|
|
111
|
+
notifyOnce(msgAdvisorRestored(modelKey(model), effort), "info");
|
|
94
112
|
}
|
|
95
113
|
|
|
96
114
|
export function registerAdvisorSessionStart(pi: ExtensionAPI): void {
|
package/advisor/state.ts
CHANGED
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
* the persisted form lives in config.ts, the blocklist cache in policy.ts.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type { Api, Model
|
|
6
|
+
import type { Api, Model } from "@earendil-works/pi-ai";
|
|
7
|
+
import type { GradedEffort } from "./messages.js";
|
|
7
8
|
|
|
8
9
|
let selectedAdvisor: Model<Api> | undefined;
|
|
9
|
-
let selectedAdvisorEffort:
|
|
10
|
+
let selectedAdvisorEffort: GradedEffort | undefined;
|
|
10
11
|
|
|
11
12
|
export function getAdvisorModel(): Model<Api> | undefined {
|
|
12
13
|
return selectedAdvisor;
|
|
@@ -16,10 +17,10 @@ export function setAdvisorModel(model: Model<Api> | undefined): void {
|
|
|
16
17
|
selectedAdvisor = model;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
export function getAdvisorEffort():
|
|
20
|
+
export function getAdvisorEffort(): GradedEffort | undefined {
|
|
20
21
|
return selectedAdvisorEffort;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
export function setAdvisorEffort(effort:
|
|
24
|
+
export function setAdvisorEffort(effort: GradedEffort | undefined): void {
|
|
24
25
|
selectedAdvisorEffort = effort;
|
|
25
26
|
}
|
package/docs/configuration.md
CHANGED
|
@@ -41,7 +41,7 @@ previous selection and the active tool list are left untouched.
|
|
|
41
41
|
| Key | Type | Default | Written by |
|
|
42
42
|
| --- | --- | --- | --- |
|
|
43
43
|
| `modelKey` | `string` — `"provider/modelId"` | absent (advisor off) | `/advisor` |
|
|
44
|
-
| `effort` |
|
|
44
|
+
| `effort` | graded thinking level (`minimal` → `max`) | absent (no `reasoning` sent) | `/advisor` effort picker |
|
|
45
45
|
| `disabledForModels` | `(string \| { model, minEffort? })[]` | `[]` | hand-edited |
|
|
46
46
|
| `guidance.promptSnippet` | `string` | built-in snippet | hand-edited |
|
|
47
47
|
| `guidance.promptGuidelines` | `string[]` | six built-in guidelines | hand-edited |
|
|
@@ -59,12 +59,18 @@ form the next time you save through `/advisor`.
|
|
|
59
59
|
### `effort`
|
|
60
60
|
|
|
61
61
|
Offered only for models whose registry entry reports reasoning support. The
|
|
62
|
-
picker lists `off
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
`
|
|
67
|
-
|
|
62
|
+
picker lists `off (no reasoning sent)` plus the graded levels Pi reports for the
|
|
63
|
+
selected model. `high` is marked `(recommended)`. Choosing `off` deletes the
|
|
64
|
+
key, and no `reasoning` parameter is sent with the advisor call — distinct from
|
|
65
|
+
`/rpiv-models`' `off (disable reasoning)`, which persists an explicit
|
|
66
|
+
`thinking: "off"`.
|
|
67
|
+
|
|
68
|
+
`EFFORT_ORDINAL` orders the graded levels lowest → highest; this ordering is what
|
|
69
|
+
`minEffort` compares against.
|
|
70
|
+
|
|
71
|
+
> **Naming note.** Advisor "effort", Pi's "thinking level", and pi-ai's `reasoning`
|
|
72
|
+
> parameter are the same graded-level concept — the name differs per layer (fixed by
|
|
73
|
+
> on-disk config keys and upstream APIs), but there is no semantic distinction.
|
|
68
74
|
|
|
69
75
|
### `disabledForModels`
|
|
70
76
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juicesharp/rpiv-advisor",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.1",
|
|
4
4
|
"description": "Pi extension. A second opinion the model can request from a stronger reviewer model before it acts.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -40,12 +40,13 @@
|
|
|
40
40
|
"LICENSE"
|
|
41
41
|
],
|
|
42
42
|
"pi": {
|
|
43
|
+
"image": "https://raw.githubusercontent.com/juicesharp/rpiv-mono/main/packages/rpiv-advisor/docs/cover.png",
|
|
43
44
|
"extensions": [
|
|
44
45
|
"./index.ts"
|
|
45
46
|
]
|
|
46
47
|
},
|
|
47
48
|
"dependencies": {
|
|
48
|
-
"@juicesharp/rpiv-config": "^2.
|
|
49
|
+
"@juicesharp/rpiv-config": "^2.6.1",
|
|
49
50
|
"typebox": "^1.1.24"
|
|
50
51
|
},
|
|
51
52
|
"peerDependencies": {
|