advisor-pi 1.0.3 → 1.2.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/README.md CHANGED
@@ -18,21 +18,38 @@ advice to the executor.
18
18
  - Lets the executor decide when a consultation is useful.
19
19
  - Calls a configured advisor model through Pi's model registry and auth.
20
20
  - Tracks advisor uses per session branch and stops after the configured limit.
21
+ - Caps the conversation transcript sent per call at a configurable character
22
+ limit (default 20000): longer transcripts keep the most recent context and
23
+ are marked as truncated, so per-call cost stays bounded as sessions grow.
21
24
  - Passes a prompt-cache preference (`none`, `short`, or `long`) where the
22
25
  selected provider supports it.
23
26
  - Defaults to `openai-codex/gpt-5.6-sol` with `high` thinking.
27
+ - Validates the configured model against the registry at load: when the
28
+ default (or a stored/flag-provided model) does not resolve, it falls back
29
+ to a working model with a warning notice instead of failing every call.
30
+ Stored legacy defaults are only migrated when the migration target resolves.
24
31
  - Shows a compact `advisor:<provider>/<model> <thinking> <remaining>` status in Pi's
25
32
  footer when UI is available.
33
+ - In the terminal TUI, bare `/advisor-pi` opens an interactive settings menu. It
34
+ edits enabled state, model, thinking, use limit, transcript cap, and cache
35
+ retention; it also shows the current branch use count and offers a confirmed
36
+ reset. Each accepted edit is validated and persisted immediately. Enter a
37
+ `provider/model` ID to select a model; Pi's registry validates it. The menu
38
+ does not list arbitrary configured model IDs, which could contain private data.
39
+ Use arrow keys and Enter to select, and Escape to cancel a prompt or exit the
40
+ menu; **Close** exits without further changes.
26
41
 
27
42
  ## Commands
28
43
 
29
44
  ```text
45
+ /advisor-pi
30
46
  /advisor-pi status
31
47
  /advisor-pi enable
32
48
  /advisor-pi disable
33
49
  /advisor-pi model <provider>/<model>
34
50
  /advisor-pi thinking <minimal|low|medium|high|xhigh|max>
35
51
  /advisor-pi max-uses <number>
52
+ /advisor-pi max-transcript-chars <number>
36
53
  /advisor-pi cache <none|short|long>
37
54
  /advisor-pi reset
38
55
  ```
@@ -43,15 +60,21 @@ Examples:
43
60
  /advisor-pi model openai-codex/gpt-5.6-sol
44
61
  /advisor-pi thinking high
45
62
  /advisor-pi max-uses 5
63
+ /advisor-pi max-transcript-chars 20000
46
64
  /advisor-pi cache long
47
65
  ```
48
66
 
67
+ Bare `/advisor-pi` keeps the text status response in print, JSON, and other
68
+ non-TUI modes. `/advisor-pi reset` remains available as the explicit command
69
+ for resetting this session branch's use count.
70
+
49
71
  ## CLI flags
50
72
 
51
73
  ```bash
52
74
  pi --advisor-model openai-codex/gpt-5.6-sol \
53
75
  --advisor-thinking high \
54
76
  --advisor-max-uses 5 \
77
+ --advisor-max-transcript-chars 20000 \
55
78
  --advisor-cache short
56
79
  ```
57
80
 
@@ -61,6 +84,18 @@ Disable on startup:
61
84
  pi --advisor-enabled=false
62
85
  ```
63
86
 
87
+ ## Settings persistence
88
+
89
+ Deliberate `/advisor-pi` edits are stored as private, validated per-setting
90
+ JSON files in `~/.pi/agent/advisor-pi-preferences/` (under Pi's
91
+ `getAgentDir()`): `enabled.json`, `model.json` (provider and model ID are one
92
+ logical setting), `thinkingLevel.json`, `maxUses.json`, `cacheRetention.json`,
93
+ and `maxTranscriptChars.json`. The stored settings are enabled state,
94
+ model, thinking level, max uses, cache preference, and transcript cap. Advisor
95
+ `useCount`, branch replay state, and runtime-only request settings remain
96
+ session-only. Explicit startup flags override the stored settings for that
97
+ session and are not written back.
98
+
64
99
  ## Install
65
100
 
66
101
  Published on npm: [`advisor-pi`](https://www.npmjs.com/package/advisor-pi). Register the package with **Pi** (`pi install`) — plain `npm install` does not add it to Pi's `settings.json`.
@@ -94,7 +129,8 @@ Each advisor consultation is a separate model call. That means:
94
129
  - Advisor input and output are billed separately by the selected provider.
95
130
  - Streaming from the executor pauses while the advisor call runs.
96
131
  - Longer transcripts cost more because the advisor reads the conversation
97
- context.
132
+ context. Each call sends at most `max-transcript-chars` characters
133
+ (default 20000), keeping the most recent context and marking truncation.
98
134
  - The `max-uses` setting is a safety budget; raise it only when deeper review is
99
135
  worth the extra cost.
100
136
 
@@ -117,6 +153,7 @@ specific model compatibility, and cache reads/writes may still be billed.
117
153
  reports.
118
154
  - The advisor has no tools and cannot inspect files beyond what appears in the
119
155
  transcript.
120
- - Very long conversations can make advisor calls slower and more expensive.
156
+ - Very long conversations are truncated to the transcript cap before sending,
157
+ so older context may be omitted on advisor calls.
121
158
  - `max-uses` is tracked per Pi session branch from extension state and tool
122
159
  result details; manual session editing can affect reconstruction.
@@ -0,0 +1,12 @@
1
+ import type { AdvisorConfig } from "./index.js";
2
+ /** Rows used by the interactive advisor-pi settings menu. */
3
+ export type MenuRow<TKey extends string = string> = {
4
+ key: TKey;
5
+ label: string;
6
+ };
7
+ export type MenuKey = "enabled" | "model" | "thinking" | "max-uses" | "max-transcript-chars" | "cache" | "reset" | "close";
8
+ /** Build the top-level settings rows, including the current value for each setting. */
9
+ export declare function buildMenuRows(config: AdvisorConfig, useCount?: number): MenuRow<MenuKey>[];
10
+ /** Maps a selected label back to its row; cancelled dialogs return undefined. */
11
+ export declare function rowForLabel<TKey extends string>(rows: MenuRow<TKey>[], label: string | undefined): MenuRow<TKey> | undefined;
12
+ //# sourceMappingURL=config-ui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-ui.d.ts","sourceRoot":"","sources":["../src/config-ui.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,6DAA6D;AAC7D,MAAM,MAAM,OAAO,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM,IAAI;IAAE,GAAG,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjF,MAAM,MAAM,OAAO,GAChB,SAAS,GACT,OAAO,GACP,UAAU,GACV,UAAU,GACV,sBAAsB,GACtB,OAAO,GACP,OAAO,GACP,OAAO,CAAC;AAEX,uFAAuF;AACvF,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,SAAI,GAAG,OAAO,CAAC,OAAO,CAAC,EAAE,CAiBrF;AAED,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,IAAI,SAAS,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,SAAS,CAG5H"}
@@ -0,0 +1,26 @@
1
+ /** Build the top-level settings rows, including the current value for each setting. */
2
+ export function buildMenuRows(config, useCount = 0) {
3
+ const entries = [
4
+ ["enabled", "Advisor enabled", config.enabled ? "enabled" : "disabled"],
5
+ ["model", "Advisor model", "configured (use /advisor-pi status for ID)"],
6
+ ["thinking", "Advisor thinking", config.thinkingLevel],
7
+ ["max-uses", "Max advisor uses", String(config.maxUses)],
8
+ ["max-transcript-chars", "Max transcript chars", String(config.maxTranscriptChars)],
9
+ ["cache", "Cache retention", config.cacheRetention],
10
+ ];
11
+ const width = Math.max(...entries.map(([, label]) => label.length));
12
+ const rows = entries.map(([key, label, value]) => ({
13
+ key,
14
+ label: `${label.padEnd(width)} ${value}`,
15
+ }));
16
+ rows.push({ key: "reset", label: `Reset use count (${useCount} used)` });
17
+ rows.push({ key: "close", label: "Close" });
18
+ return rows;
19
+ }
20
+ /** Maps a selected label back to its row; cancelled dialogs return undefined. */
21
+ export function rowForLabel(rows, label) {
22
+ if (label === undefined)
23
+ return undefined;
24
+ return rows.find((row) => row.label === label);
25
+ }
26
+ //# sourceMappingURL=config-ui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-ui.js","sourceRoot":"","sources":["../src/config-ui.ts"],"names":[],"mappings":"AAeA,uFAAuF;AACvF,MAAM,UAAU,aAAa,CAAC,MAAqB,EAAE,QAAQ,GAAG,CAAC;IAChE,MAAM,OAAO,GAAqC;QACjD,CAAC,SAAS,EAAE,iBAAiB,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC;QACvE,CAAC,OAAO,EAAE,eAAe,EAAE,4CAA4C,CAAC;QACxE,CAAC,UAAU,EAAE,kBAAkB,EAAE,MAAM,CAAC,aAAa,CAAC;QACtD,CAAC,UAAU,EAAE,kBAAkB,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACxD,CAAC,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QACnF,CAAC,OAAO,EAAE,iBAAiB,EAAE,MAAM,CAAC,cAAc,CAAC;KACnD,CAAC;IACF,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACpE,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;QAClD,GAAG;QACH,KAAK,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,EAAE;KACzC,CAAC,CAAC,CAAC;IACJ,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,qBAAqB,QAAQ,QAAQ,EAAE,CAAC,CAAC;IAC1E,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;IAC5C,OAAO,IAAI,CAAC;AACb,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,WAAW,CAAsB,IAAqB,EAAE,KAAyB;IAChG,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1C,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;AAChD,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,55 @@
1
+ import { type CacheRetention, type ThinkingLevel } from "@earendil-works/pi-ai";
1
2
  import { type ExtensionAPI } from "@earendil-works/pi-coding-agent";
3
+ export { loadPreferences, preferencesPath, savePreferences, savePreferencesPatch } from "./preferences.js";
4
+ export type { AdvisorPreferences, AdvisorPreferencesConfig, AdvisorPreferencesPatch } from "./preferences.js";
5
+ export declare const STATE_ENTRY = "advisor-pi-state";
6
+ export declare const DEFAULT_ADVISOR_MODEL = "openai-codex/gpt-5.6-sol";
7
+ export declare const LEGACY_DEFAULT_ADVISOR_MODEL = "openai-codex/gpt-5.5";
8
+ export declare const DEFAULT_MAX_TRANSCRIPT_CHARS = 20000;
9
+ type AdvisorThinkingLevel = ThinkingLevel | "max";
10
+ export type AdvisorConfig = {
11
+ enabled: boolean;
12
+ provider: string;
13
+ modelId: string;
14
+ thinkingLevel: AdvisorThinkingLevel;
15
+ maxUses: number;
16
+ cacheRetention: CacheRetention;
17
+ maxTokens: number;
18
+ timeoutMs: number;
19
+ maxTranscriptChars: number;
20
+ };
21
+ type AdvisorStateEntry = {
22
+ version: 1;
23
+ config: AdvisorConfig;
24
+ useCount: number;
25
+ updatedAt: string;
26
+ };
27
+ export type ModelRegistryLike = {
28
+ find: (provider: string, modelId: string) => unknown;
29
+ getAvailable?: () => Array<{
30
+ provider?: unknown;
31
+ id?: unknown;
32
+ }>;
33
+ };
34
+ export type NormalizeConfigOptions = {
35
+ migrateLegacyDefault?: boolean;
36
+ };
2
37
  export default function advisorPiExtension(pi: ExtensionAPI): void;
38
+ export declare function defaultConfig(): AdvisorConfig;
39
+ export declare function truncateTranscript(text: string, maxChars: number): string;
40
+ export declare function makeStateEntry(config: AdvisorConfig, useCount: number): AdvisorStateEntry;
41
+ export declare function persistState(pi: ExtensionAPI, config: AdvisorConfig, useCount: number): void;
42
+ export declare function normalizeConfig(input: Partial<AdvisorConfig>, fallback: AdvisorConfig, registry?: ModelRegistryLike, options?: NormalizeConfigOptions): AdvisorConfig;
43
+ export declare function modelResolves(registry: ModelRegistryLike | undefined, provider: string, modelId: string): boolean;
44
+ export declare function resolveAdvisorModel(registry: ModelRegistryLike | undefined, candidates: Array<{
45
+ provider: string;
46
+ modelId: string;
47
+ }>): {
48
+ provider: string;
49
+ modelId: string;
50
+ } | undefined;
51
+ export declare function parseModelSpec(value: string): {
52
+ provider: string;
53
+ modelId: string;
54
+ } | undefined;
3
55
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAIN,KAAK,YAAY,EAEjB,MAAM,iCAAiC,CAAC;AAqEzC,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,EAAE,EAAE,YAAY,QAqY1D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}