pi-advisor-flow 0.9.2-dev.5 → 0.10.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.
@@ -95,6 +95,16 @@ export const registerToolLifecycle = ({
95
95
  : undefined;
96
96
  });
97
97
 
98
+ pi.on("input", () => {
99
+ session.clearFollowUps();
100
+ });
101
+
102
+ pi.on("tool_result", (event) => {
103
+ if (event.toolName !== "ask_advisor") {
104
+ session.advanceFollowUpToolCall();
105
+ }
106
+ });
107
+
98
108
  pi.on("tool_call", (event, ctx) => {
99
109
  if (session.blocked) {
100
110
  return {
@@ -149,6 +159,7 @@ export const registerToolLifecycle = ({
149
159
 
150
160
  pi.on("session_shutdown", (_event, ctx) => {
151
161
  reservedCalls.clear();
162
+ session.clearFollowUps();
152
163
  session.clearCallReservations();
153
164
  scoutStatus.clear(ctx);
154
165
  herdrBlock.clear();
@@ -162,6 +162,9 @@ const finalResultLines = (
162
162
  theme: Theme
163
163
  ): string[] => {
164
164
  const lines = [renderAdvisorResponseHeader(hasSoundVerdict(advice), theme)];
165
+ if (details?.followUp) {
166
+ lines.push(theme.fg("dim", " Follow-up consultation"));
167
+ }
165
168
  if (details?.advisor) {
166
169
  lines.push(theme.fg("dim", ` ${details.advisor}`));
167
170
  }
@@ -85,11 +85,15 @@ export const resolveAdvisorRequest = (question?: string) =>
85
85
 
86
86
  export const renderAdvisorCallBox = (
87
87
  question: string | undefined,
88
- theme: Theme
88
+ theme: Theme,
89
+ followUp = false
89
90
  ) => {
90
91
  const box = new Box(1, 1, (text) => theme.bg("customMessageBg", text));
91
92
  const label = theme.fg("customMessageLabel", theme.bold("[advisor]"));
92
- const title = theme.fg("customMessageText", "Executor → Advisor");
93
+ const title = theme.fg(
94
+ "customMessageText",
95
+ followUp ? "Executor → Advisor · Follow-up" : "Executor → Advisor"
96
+ );
93
97
  box.addChild(
94
98
  new Text(
95
99
  question
@@ -48,6 +48,7 @@ export interface AdvisorConsultationResult {
48
48
  adviceId: string;
49
49
  agentRulesBytes?: number;
50
50
  draftBytes?: number;
51
+ followUp?: boolean;
51
52
  imageBytes?: number;
52
53
  imageCount?: number;
53
54
  imageOmissions?: number;
@@ -89,6 +90,7 @@ export interface AdvisorToolDetails {
89
90
  adviceId?: string;
90
91
  advisor?: string;
91
92
  agentRulesBytes?: number;
93
+ followUp?: boolean;
92
94
  draftBytes?: number;
93
95
  imageBytes?: number;
94
96
  imageCount?: number;
@@ -17,6 +17,7 @@ import {
17
17
  import { isValidAdvisorToolPolicies } from "../config/validation.ts";
18
18
  import { JevSetupSubmenu } from "./jev-setup-submenu.ts";
19
19
  import { SearchableModelMultiSelector } from "./model-multi-selector.ts";
20
+ import { SearchableModelSelector } from "./model-selector.ts";
20
21
  import {
21
22
  contextDescription,
22
23
  currentContextLabel,
@@ -28,6 +29,7 @@ import {
28
29
  withCurrentValue,
29
30
  } from "./settings-formatting.ts";
30
31
  import { TextSettingSubmenu } from "./text-setting-submenu.ts";
32
+ import { FALLBACK_ADVISOR_MODEL_DISABLED } from "./types.ts";
31
33
  import type {
32
34
  AdvisorSettings,
33
35
  ContextPreset,
@@ -36,6 +38,7 @@ import type {
36
38
 
37
39
  export interface SettingsItemsOptions {
38
40
  effortLevels: string[];
41
+ fallbackModel: SettingItem;
39
42
  modelWhitelist: SettingItem;
40
43
  presets: ContextPreset[];
41
44
  settings: AdvisorSettings;
@@ -220,6 +223,37 @@ const jevItems = (
220
223
  },
221
224
  ];
222
225
 
226
+ export const advisorFallbackModelItem = (
227
+ settings: AdvisorSettings,
228
+ modelRefs: string[] | undefined,
229
+ keybindings: KeybindingsManager | undefined,
230
+ theme: Theme,
231
+ tui: RenderRequester
232
+ ): SettingItem => ({
233
+ currentValue: settings.fallbackModel ?? FALLBACK_ADVISOR_MODEL_DISABLED,
234
+ description:
235
+ "Retry a failed Advisor request once with this optional model; the primary model remains unchanged.",
236
+ id: "fallbackModel",
237
+ label: "Fallback Advisor model",
238
+ submenu: (_currentValue, done) =>
239
+ new SearchableModelSelector({
240
+ allOptions: [
241
+ FALLBACK_ADVISOR_MODEL_DISABLED,
242
+ ...new Set(
243
+ modelRefs ?? (settings.fallbackModel ? [settings.fallbackModel] : [])
244
+ ),
245
+ ],
246
+ currentOption: settings.fallbackModel ?? FALLBACK_ADVISOR_MODEL_DISABLED,
247
+ keybindings: keybindings ?? getKeybindings(),
248
+ onCancel: done,
249
+ onSelect: (value) =>
250
+ done(value === FALLBACK_ADVISOR_MODEL_DISABLED ? "" : value),
251
+ theme,
252
+ title: "Fallback Advisor model",
253
+ tui,
254
+ }),
255
+ });
256
+
223
257
  export const advisorModelWhitelistItem = (
224
258
  settings: AdvisorSettings,
225
259
  modelRefs: string[] | undefined,
@@ -252,6 +286,7 @@ export const advisorModelWhitelistItem = (
252
286
 
253
287
  export const createSettingsItems = ({
254
288
  effortLevels,
289
+ fallbackModel,
255
290
  modelWhitelist,
256
291
  presets,
257
292
  settings,
@@ -282,6 +317,7 @@ export const createSettingsItems = ({
282
317
  label: "Always on",
283
318
  values: TOGGLE_VALUES,
284
319
  },
320
+ fallbackModel,
285
321
  ];
286
322
  if (settings.simpleMode) {
287
323
  items.push(
@@ -1,4 +1,5 @@
1
1
  import { DEFAULT_JEV_MODEL } from "../config/types.ts";
2
+ import { FALLBACK_ADVISOR_MODEL_DISABLED } from "./types.ts";
2
3
  import type { AdvisorSettings, ContextPreset } from "./types.ts";
3
4
 
4
5
  const BOOLEAN_SETTING_FIELDS = [
@@ -55,6 +56,13 @@ const applyCoreMutation = (
55
56
  settings.alwaysOn = value === "On";
56
57
  return true;
57
58
  }
59
+ case "fallbackModel": {
60
+ settings.fallbackModel =
61
+ value === FALLBACK_ADVISOR_MODEL_DISABLED
62
+ ? undefined
63
+ : value.trim() || undefined;
64
+ return true;
65
+ }
58
66
  case "effort": {
59
67
  settings.effort = value;
60
68
  return true;
@@ -7,6 +7,7 @@ import {
7
7
  SIMPLE_MODE_GRADIENT_INTERVAL_MS,
8
8
  } from "./settings-formatting.ts";
9
9
  import {
10
+ advisorFallbackModelItem,
10
11
  advisorModelWhitelistItem,
11
12
  createSettingsItems,
12
13
  } from "./settings-items.ts";
@@ -96,6 +97,13 @@ export class AdvisorSettingsSelector implements Component, Focusable {
96
97
  }
97
98
  return defaultLabel(text, selected);
98
99
  };
100
+ const fallbackModel = advisorFallbackModelItem(
101
+ this.settings,
102
+ this.options.modelRefs,
103
+ this.options.keybindings,
104
+ this.options.theme,
105
+ this.options.tui
106
+ );
99
107
  const modelWhitelist = advisorModelWhitelistItem(
100
108
  this.settings,
101
109
  this.options.modelRefs,
@@ -105,6 +113,7 @@ export class AdvisorSettingsSelector implements Component, Focusable {
105
113
  );
106
114
  const items = createSettingsItems({
107
115
  effortLevels: this.options.effortLevels,
116
+ fallbackModel,
108
117
  modelWhitelist,
109
118
  presets: this.presets,
110
119
  settings: this.settings,
package/src/ui/types.ts CHANGED
@@ -66,8 +66,11 @@ export interface ContextPreset {
66
66
  value: number;
67
67
  }
68
68
 
69
+ export const FALLBACK_ADVISOR_MODEL_DISABLED = "Disabled (no fallback)";
70
+
69
71
  export interface AdvisorSettings {
70
72
  agentsMdContext?: boolean;
73
+ fallbackModel?: string;
71
74
  alwaysOn?: boolean;
72
75
  autoLoopGate?: boolean;
73
76
  blockOnBlocked?: boolean;