pi-advisor-flow 0.1.8 → 0.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/src/commands.ts CHANGED
@@ -1,68 +1,197 @@
1
- import { getMarkdownTheme, type ExtensionAPI, type ExtensionContext } from "@earendil-works/pi-coding-agent";
1
+ import {
2
+ type ExtensionAPI,
3
+ type ExtensionContext,
4
+ getMarkdownTheme,
5
+ } from "@earendil-works/pi-coding-agent";
2
6
  import { Box, Markdown, Text } from "@earendil-works/pi-tui";
3
7
  import {
4
- advisorAutoLoopGateRef, advisorMaxCallsPerSessionRef, advisorBlockOnBlockedRef, advisorCollapseResponsesRef, advisorCompletionGateRef, advisorCustomInvocationRef, advisorFailureGateRef, advisorLoopThresholdRef, advisorPlanGateRef, advisorSessionSummaryRef,
5
- advisorRef, advisorEffortRef, executorRef, executorEffortRef,
6
- setAdvisorAutoLoopGateRef, setAdvisorMaxCallsPerSessionRef, setAdvisorBlockOnBlockedRef, setAdvisorCollapseResponsesRef, setAdvisorCompletionGateRef, setAdvisorCustomInvocationRef, setAdvisorFailureGateRef, setAdvisorLoopThresholdRef, setAdvisorPlanGateRef, setAdvisorSessionSummaryRef,
7
- setAdvisorRef, setAdvisorEffortRef, setContextMaxCharsRef, setExecutorRef, setExecutorEffortRef,
8
- contextMaxCharsRef, loadConfig, saveConfig, parseArgs, splitRef,
8
+ advisorAutoLoopGateRef,
9
+ advisorBlockOnBlockedRef,
10
+ advisorCollapseResponsesRef,
11
+ advisorCompletionGateRef,
12
+ advisorCustomInvocationRef,
13
+ advisorEffortRef,
14
+ advisorFailureGateRef,
15
+ advisorFailureModeRef,
16
+ advisorHerdrIntegrationRef,
17
+ advisorLoopThresholdRef,
18
+ advisorMaxCallsPerSessionRef,
19
+ advisorPlanGateRef,
20
+ advisorRef,
21
+ advisorSessionSummaryRef,
22
+ advisorToolResultMaxBytesRef,
23
+ advisorToolResultMaxLinesRef,
24
+ contextMaxCharsRef,
25
+ executorEffortRef,
26
+ executorRef,
27
+ loadConfig,
28
+ parseArgs,
29
+ saveConfig,
30
+ setAdvisorAutoLoopGateRef,
31
+ setAdvisorBlockOnBlockedRef,
32
+ setAdvisorCollapseResponsesRef,
33
+ setAdvisorCompletionGateRef,
34
+ setAdvisorCustomInvocationRef,
35
+ setAdvisorEffortRef,
36
+ setAdvisorFailureGateRef,
37
+ setAdvisorFailureModeRef,
38
+ setAdvisorHerdrIntegrationRef,
39
+ setAdvisorLoopThresholdRef,
40
+ setAdvisorMaxCallsPerSessionRef,
41
+ setAdvisorPlanGateRef,
42
+ setAdvisorRef,
43
+ setAdvisorSessionSummaryRef,
44
+ setAdvisorToolResultMaxBytesRef,
45
+ setAdvisorToolResultMaxLinesRef,
46
+ setContextMaxCharsRef,
47
+ setExecutorEffortRef,
48
+ setExecutorRef,
49
+ splitRef,
9
50
  } from "./config.js";
10
- import { AdvisorSettingsSelector, SearchableModelSelector, type AdvisorSettings, type ContextPreset } from "./ui.js";
11
- import { herdrAdvisorActivity } from "./herdr.js";
12
- import { adviceForDisplay, advisorSessionState, consult, renderAdvisorCallBox, resolveAdvisorRequest } from "./tools.js";
51
+ import { herdrAdvisorActivity, notifyHerdrAdvisorFailure } from "./herdr.js";
52
+ import {
53
+ adviceForDisplay,
54
+ advisorSessionState,
55
+ consultAdvisor,
56
+ renderAdvisorCallBox,
57
+ resolveAdvisorRequest,
58
+ } from "./tools.js";
59
+ import {
60
+ type AdvisorSettings,
61
+ AdvisorSettingsSelector,
62
+ type ContextPreset,
63
+ SearchableModelSelector,
64
+ } from "./ui.js";
13
65
 
14
- const EFFORT_LEVELS = ["Default (Model Default)", "off", "minimal", "low", "medium", "high", "xhigh", "max"];
66
+ const EFFORT_LEVELS = [
67
+ "Default (Model Default)",
68
+ "off",
69
+ "minimal",
70
+ "low",
71
+ "medium",
72
+ "high",
73
+ "xhigh",
74
+ "max",
75
+ ];
15
76
 
16
77
  const CONTEXT_PRESETS: ContextPreset[] = [
17
- { label: "0", value: 0, description: "No conversation history. The Advisor receives only its standing instructions." },
18
- { label: "10k", value: 10_000, description: "The most recent 10,000 characters of the current branch." },
19
- { label: "25k", value: 25_000, description: "The most recent 25,000 characters of the current branch." },
20
- { label: "100k", value: 100_000, description: "The most recent 100,000 characters of the current branch." },
21
- { label: "200k", value: 200_000, description: "The most recent 200,000 characters of the current branch." },
22
- { label: "ALL", value: Number.MAX_SAFE_INTEGER, description: "The complete reconstructed conversation branch. Cost and model context limits apply." },
78
+ {
79
+ description:
80
+ "No conversation history. The Advisor receives only its standing instructions.",
81
+ label: "0",
82
+ value: 0,
83
+ },
84
+ {
85
+ description: "The most recent 10,000 characters of the current branch.",
86
+ label: "10k",
87
+ value: 10_000,
88
+ },
89
+ {
90
+ description: "The most recent 25,000 characters of the current branch.",
91
+ label: "25k",
92
+ value: 25_000,
93
+ },
94
+ {
95
+ description: "The most recent 100,000 characters of the current branch.",
96
+ label: "100k",
97
+ value: 100_000,
98
+ },
99
+ {
100
+ description: "The most recent 200,000 characters of the current branch.",
101
+ label: "200k",
102
+ value: 200_000,
103
+ },
104
+ {
105
+ description:
106
+ "The complete reconstructed conversation branch. Cost and model context limits apply.",
107
+ label: "ALL",
108
+ value: Number.MAX_SAFE_INTEGER,
109
+ },
23
110
  ];
24
111
 
25
- type ManualConsult = (ctx: ExtensionContext, question?: string, signal?: AbortSignal) => Promise<{ advice: string; thinkingText: string }>;
112
+ type ManualConsult = (
113
+ ctx: ExtensionContext,
114
+ question?: string,
115
+ signal?: AbortSignal
116
+ ) => Promise<{ markdown: string; thinkingText: string }>;
26
117
 
27
- export const registerCommands = (pi: ExtensionAPI, dependencies: { consult?: ManualConsult } = {}) => {
118
+ export const registerCommands = (
119
+ pi: ExtensionAPI,
120
+ dependencies: { consult?: ManualConsult } = {}
121
+ ) => {
28
122
  const flowEnabled = () => pi.getActiveTools().includes("ask_advisor");
29
- const requestAdvisor = dependencies.consult ?? consult;
123
+ const requestAdvisor =
124
+ dependencies.consult ??
125
+ ((ctx, question, signal) =>
126
+ consultAdvisor(ctx, question, signal, undefined, "manual"));
30
127
  const manualConsultations = new Set<AbortController>();
31
128
 
32
- pi.registerEntryRenderer?.("advisor-manual-call", (entry, _options, theme) => {
33
- const { question } = (entry.data ?? {}) as { question?: string };
34
- return renderAdvisorCallBox(question, theme);
35
- });
129
+ pi.registerEntryRenderer?.(
130
+ "advisor-manual-call",
131
+ (entry, _options, theme) => {
132
+ const { question } = (entry.data ?? {}) as { question?: string };
133
+ return renderAdvisorCallBox(question, theme);
134
+ }
135
+ );
36
136
 
37
- pi.registerMessageRenderer?.("advisor-manual-result", (message, { expanded }, theme) => {
38
- const details = message.details as { advisor?: string; text?: string } | undefined;
39
- const box = new Box(1, 1, (text) => theme.bg("customMessageBg", text));
40
- box.addChild(new Text(theme.fg("warning", theme.bold("◆ ADVISOR RESPONSE")), 0, 0));
41
- if (details?.advisor) box.addChild(new Text(theme.fg("dim", ` ${details.advisor}`), 0, 0));
42
- const advice = details?.text ?? (typeof message.content === "string" ? message.content : "(Advisor returned no advice.)");
43
- box.addChild(new Markdown(adviceForDisplay(advice, expanded), 0, 0, getMarkdownTheme()));
44
- return box;
45
- });
137
+ pi.registerMessageRenderer?.(
138
+ "advisor-manual-result",
139
+ (message, { expanded }, theme) => {
140
+ const details = message.details as
141
+ | { advisor?: string; text?: string }
142
+ | undefined;
143
+ const box = new Box(1, 1, (text) => theme.bg("customMessageBg", text));
144
+ box.addChild(
145
+ new Text(theme.fg("warning", theme.bold("◆ ADVISOR RESPONSE")), 0, 0)
146
+ );
147
+ if (details?.advisor) {
148
+ box.addChild(new Text(theme.fg("dim", ` ${details.advisor}`), 0, 0));
149
+ }
150
+ const advice =
151
+ details?.text ??
152
+ (typeof message.content === "string"
153
+ ? message.content
154
+ : "(Advisor returned no advice.)");
155
+ box.addChild(
156
+ new Markdown(
157
+ adviceForDisplay(advice, expanded),
158
+ 0,
159
+ 0,
160
+ getMarkdownTheme()
161
+ )
162
+ );
163
+ return box;
164
+ }
165
+ );
46
166
 
47
167
  pi.on("session_shutdown", () => {
48
- for (const controller of manualConsultations) controller.abort();
168
+ for (const controller of manualConsultations) {
169
+ controller.abort();
170
+ }
49
171
  manualConsultations.clear();
50
172
  herdrAdvisorActivity.clear();
51
173
  });
52
174
 
53
175
  pi.registerCommand("advisor-manual", {
54
- description: "Consult the Advisor in parallel; accepts an optional focused question and fans its response out to the Executor",
176
+ description:
177
+ "Consult the Advisor in parallel; accepts an optional focused question and fans its response out to the Executor",
55
178
  handler: async (args, ctx) => {
56
179
  loadConfig(ctx);
57
- if (!advisorSessionState.canUseAutomaticCall(advisorMaxCallsPerSessionRef)) {
58
- if (ctx.hasUI) ctx.ui.notify("Advisor call budget exhausted for this session.", "warning");
180
+ if (!advisorSessionState.canConsult(advisorMaxCallsPerSessionRef)) {
181
+ const message = "Advisor call budget exhausted for this session.";
182
+ if (ctx.hasUI) {
183
+ ctx.ui.notify(message, "warning");
184
+ }
185
+ notifyHerdrAdvisorFailure("Advisor budget exhausted", message);
59
186
  return;
60
187
  }
61
- advisorSessionState.consumeAutomaticCall();
188
+ advisorSessionState.consumeCall();
62
189
  const question = resolveAdvisorRequest(args);
63
190
  // A single visible progress surface avoids competing consultations overwriting
64
191
  // each other's streamed state. A newer manual request replaces the previous one.
65
- for (const pending of manualConsultations) pending.abort();
192
+ for (const pending of manualConsultations) {
193
+ pending.abort();
194
+ }
66
195
  manualConsultations.clear();
67
196
  const controller = new AbortController();
68
197
  manualConsultations.add(controller);
@@ -70,25 +199,49 @@ export const registerCommands = (pi: ExtensionAPI, dependencies: { consult?: Man
70
199
 
71
200
  herdrAdvisorActivity.start();
72
201
  void requestAdvisor(ctx, question, controller.signal)
73
- .then(({ advice }) => {
74
- advisorSessionState.recordConsultation("manual");
75
- if (controller.signal.aborted) return;
76
- pi.sendMessage({
77
- customType: "advisor-manual-result",
78
- content: `Manual Advisor consultation${question ? ` (${question})` : ""}:\n\n${advice}`,
79
- display: true,
80
- details: { advisor: advisorRef, question, text: advice },
81
- }, {
82
- // Steer lets the current turn finish its active work; the Executor sees
83
- // the result before its next model call rather than being interrupted.
84
- deliverAs: "steer",
85
- triggerTurn: true,
202
+ .then(({ markdown }) => {
203
+ advisorSessionState.recordInvocation({
204
+ executionEffect: "continued",
205
+ kind: "markdown",
206
+ model: advisorRef,
207
+ trigger: "manual",
86
208
  });
209
+ const advice = markdown;
210
+ if (controller.signal.aborted) {
211
+ return;
212
+ }
213
+ pi.sendMessage(
214
+ {
215
+ content: `Manual Advisor consultation${question ? ` (${question})` : ""}:\n\n${advice}`,
216
+ customType: "advisor-manual-result",
217
+ details: { advisor: advisorRef, question, text: advice },
218
+ display: true,
219
+ },
220
+ {
221
+ // Steer lets the current turn finish its active work; the Executor sees
222
+ // the result before its next model call rather than being interrupted.
223
+ deliverAs: "steer",
224
+ triggerTurn: true,
225
+ }
226
+ );
87
227
  })
88
228
  .catch((error: unknown) => {
89
- if (controller.signal.aborted) return;
90
- const message = error instanceof Error ? error.message : String(error);
91
- if (ctx.hasUI) ctx.ui.notify(`Advisor consultation failed: ${message}`, "error");
229
+ if (controller.signal.aborted) {
230
+ return;
231
+ }
232
+ const message =
233
+ error instanceof Error ? error.message : String(error);
234
+ advisorSessionState.recordInvocation({
235
+ executionEffect: "continued",
236
+ failure: "provider-error",
237
+ kind: "markdown",
238
+ model: advisorRef,
239
+ trigger: "manual",
240
+ });
241
+ if (ctx.hasUI) {
242
+ ctx.ui.notify(`Advisor consultation failed: ${message}`, "error");
243
+ }
244
+ notifyHerdrAdvisorFailure("Advisor consultation failed", message);
92
245
  })
93
246
  .finally(() => {
94
247
  manualConsultations.delete(controller);
@@ -98,55 +251,125 @@ export const registerCommands = (pi: ExtensionAPI, dependencies: { consult?: Man
98
251
  });
99
252
 
100
253
  pi.registerCommand("advisor", {
101
- description: "Enable the Executor/Advisor flow and switch to the configured Executor model; accepts contextMaxChars=N",
254
+ description:
255
+ "Enable the Executor/Advisor flow and switch to the configured Executor model; accepts contextMaxChars=N",
102
256
  handler: async (args, ctx) => {
103
257
  loadConfig(ctx);
104
258
  const argumentError = parseArgs(args);
105
259
  if (argumentError) {
106
- if (ctx.hasUI) ctx.ui.notify(argumentError, "error");
260
+ if (ctx.hasUI) {
261
+ ctx.ui.notify(argumentError, "error");
262
+ }
107
263
  return;
108
264
  }
109
265
  const [provider, modelId] = splitRef(executorRef);
110
266
  const executor = ctx.modelRegistry.find(provider, modelId);
111
- if (!executor) return ctx.hasUI ? ctx.ui.notify(`Executor model not found: ${executorRef}`, "error") : undefined;
267
+ if (!executor) {
268
+ return ctx.hasUI
269
+ ? ctx.ui.notify(`Executor model not found: ${executorRef}`, "error")
270
+ : undefined;
271
+ }
112
272
  const [ap, am] = splitRef(advisorRef);
113
- if (!ctx.modelRegistry.find(ap, am)) return ctx.hasUI ? ctx.ui.notify(`Advisor model not found: ${advisorRef}`, "error") : undefined;
114
- if (!(await pi.setModel(executor))) return ctx.hasUI ? ctx.ui.notify(`No API key for Executor ${executorRef}`, "error") : undefined;
115
- if (executorEffortRef) pi.setThinkingLevel(executorEffortRef as any);
116
- if (!flowEnabled()) pi.setActiveTools([...pi.getActiveTools(), "ask_advisor"]);
117
- if (ctx.hasUI) ctx.ui.notify(`Advisor flow ready — Executor: ${executorRef} (thinking: ${executorEffortRef || "default"}) · Advisor: ${advisorRef} (thinking: ${advisorEffortRef || "default"})`, "info");
273
+ if (!ctx.modelRegistry.find(ap, am)) {
274
+ return ctx.hasUI
275
+ ? ctx.ui.notify(`Advisor model not found: ${advisorRef}`, "error")
276
+ : undefined;
277
+ }
278
+ if (!(await pi.setModel(executor))) {
279
+ return ctx.hasUI
280
+ ? ctx.ui.notify(`No API key for Executor ${executorRef}`, "error")
281
+ : undefined;
282
+ }
283
+ if (executorEffortRef) {
284
+ pi.setThinkingLevel(executorEffortRef as any);
285
+ }
286
+ if (!flowEnabled()) {
287
+ pi.setActiveTools([...pi.getActiveTools(), "ask_advisor"]);
288
+ }
289
+ if (ctx.hasUI) {
290
+ ctx.ui.notify(
291
+ `Advisor flow ready — Executor: ${executorRef} (thinking: ${executorEffortRef || "default"}) · Advisor: ${advisorRef} (thinking: ${advisorEffortRef || "default"})`,
292
+ "info"
293
+ );
294
+ }
118
295
  },
119
296
  });
120
297
 
121
298
  pi.registerCommand("advisor-models", {
122
- description: "Select and persist the Executor and Advisor models with reasoning levels",
299
+ description:
300
+ "Select and persist the Executor and Advisor models with reasoning levels",
123
301
  handler: async (_args, ctx) => {
124
- if (!ctx.hasUI) return;
125
- const refs = ctx.modelRegistry.getAvailable().map((m) => `${m.provider}/${m.id}`);
302
+ if (!ctx.hasUI) {
303
+ return;
304
+ }
305
+ const refs = ctx.modelRegistry
306
+ .getAvailable()
307
+ .map((m) => `${m.provider}/${m.id}`);
126
308
 
127
- const executor = await ctx.ui.custom<string | undefined>((tui, theme, keybindings, done) =>
128
- new SearchableModelSelector({ tui, title: "Select Executor Model", allOptions: refs, theme, keybindings, onSelect: done, onCancel: () => done(undefined) })
309
+ const executor = await ctx.ui.custom<string | undefined>(
310
+ (tui, theme, keybindings, done) =>
311
+ new SearchableModelSelector({
312
+ allOptions: refs,
313
+ keybindings,
314
+ onCancel: () => done(undefined),
315
+ onSelect: done,
316
+ theme,
317
+ title: "Select Executor Model",
318
+ tui,
319
+ })
129
320
  );
130
- if (!executor) return;
321
+ if (!executor) {
322
+ return;
323
+ }
131
324
 
132
- const executorEffort = await ctx.ui.select("Select Executor Reasoning/Thinking Level", EFFORT_LEVELS);
133
- if (!executorEffort) return;
325
+ const executorEffort = await ctx.ui.select(
326
+ "Select Executor Reasoning/Thinking Level",
327
+ EFFORT_LEVELS
328
+ );
329
+ if (!executorEffort) {
330
+ return;
331
+ }
134
332
 
135
- const advisor = await ctx.ui.custom<string | undefined>((tui, theme, keybindings, done) =>
136
- new SearchableModelSelector({ tui, title: "Select Advisor Model", allOptions: refs, theme, keybindings, onSelect: done, onCancel: () => done(undefined) })
333
+ const advisor = await ctx.ui.custom<string | undefined>(
334
+ (tui, theme, keybindings, done) =>
335
+ new SearchableModelSelector({
336
+ allOptions: refs,
337
+ keybindings,
338
+ onCancel: () => done(undefined),
339
+ onSelect: done,
340
+ theme,
341
+ title: "Select Advisor Model",
342
+ tui,
343
+ })
137
344
  );
138
- if (!advisor) return;
345
+ if (!advisor) {
346
+ return;
347
+ }
139
348
 
140
- const advisorEffort = await ctx.ui.select("Select Advisor Reasoning/Thinking Level", EFFORT_LEVELS);
141
- if (!advisorEffort) return;
349
+ const advisorEffort = await ctx.ui.select(
350
+ "Select Advisor Reasoning/Thinking Level",
351
+ EFFORT_LEVELS
352
+ );
353
+ if (!advisorEffort) {
354
+ return;
355
+ }
142
356
 
143
357
  setExecutorRef(executor);
144
358
  setAdvisorRef(advisor);
145
- setExecutorEffortRef(executorEffort === "Default (Model Default)" ? undefined : executorEffort);
146
- setAdvisorEffortRef(advisorEffort === "Default (Model Default)" ? undefined : advisorEffort);
359
+ setExecutorEffortRef(
360
+ executorEffort === "Default (Model Default)"
361
+ ? undefined
362
+ : executorEffort
363
+ );
364
+ setAdvisorEffortRef(
365
+ advisorEffort === "Default (Model Default)" ? undefined : advisorEffort
366
+ );
147
367
 
148
368
  const path = saveConfig(ctx);
149
- ctx.ui.notify(`Saved Executor + Advisor configurations to ${path}`, "info");
369
+ ctx.ui.notify(
370
+ `Saved Executor + Advisor configurations to ${path}`,
371
+ "info"
372
+ );
150
373
  },
151
374
  });
152
375
 
@@ -154,36 +377,49 @@ export const registerCommands = (pi: ExtensionAPI, dependencies: { consult?: Man
154
377
  description: "Configure Advisor context and reasoning effort",
155
378
  handler: async (_args, ctx) => {
156
379
  loadConfig(ctx);
157
- if (!ctx.hasUI) return;
380
+ if (!ctx.hasUI) {
381
+ return;
382
+ }
158
383
 
159
384
  const initial: AdvisorSettings = {
385
+ autoLoopGate: advisorAutoLoopGateRef,
386
+ blockOnBlocked: advisorBlockOnBlockedRef,
387
+ collapseResponses: advisorCollapseResponsesRef,
388
+ completionGate: advisorCompletionGateRef,
160
389
  contextMaxChars: contextMaxCharsRef,
390
+ customRule: advisorCustomInvocationRef,
161
391
  effort: advisorEffortRef,
162
- planGate: advisorPlanGateRef,
163
392
  failureGate: advisorFailureGateRef,
164
- completionGate: advisorCompletionGateRef,
165
- collapseResponses: advisorCollapseResponsesRef,
166
- customRule: advisorCustomInvocationRef,
167
- blockOnBlocked: advisorBlockOnBlockedRef,
168
- autoLoopGate: advisorAutoLoopGateRef,
393
+ failureMode: advisorFailureModeRef,
394
+ herdrIntegration: advisorHerdrIntegrationRef,
169
395
  loopThreshold: advisorLoopThresholdRef,
170
396
  maxCallsPerSession: advisorMaxCallsPerSessionRef,
397
+ planGate: advisorPlanGateRef,
171
398
  sessionSummary: advisorSessionSummaryRef,
399
+ toolResultMaxBytes: advisorToolResultMaxBytesRef,
400
+ toolResultMaxLines: advisorToolResultMaxLinesRef,
172
401
  };
173
- const settings = await ctx.ui.custom<AdvisorSettings | undefined>((tui, theme, _keybindings, done) =>
174
- new AdvisorSettingsSelector({
175
- tui,
176
- theme,
177
- presets: CONTEXT_PRESETS,
178
- effortLevels: EFFORT_LEVELS,
179
- initial,
180
- onSave: done,
181
- onCancel: () => done(undefined),
182
- })
402
+ const settings = await ctx.ui.custom<AdvisorSettings | undefined>(
403
+ (tui, theme, _keybindings, done) =>
404
+ new AdvisorSettingsSelector({
405
+ effortLevels: EFFORT_LEVELS,
406
+ initial,
407
+ onCancel: () => done(undefined),
408
+ onSave: done,
409
+ presets: CONTEXT_PRESETS,
410
+ theme,
411
+ tui,
412
+ })
183
413
  );
184
- if (!settings) return;
414
+ if (!settings) {
415
+ return;
416
+ }
185
417
 
186
- setAdvisorEffortRef(settings.effort === "Default (Model Default)" ? undefined : settings.effort);
418
+ setAdvisorEffortRef(
419
+ settings.effort === "Default (Model Default)"
420
+ ? undefined
421
+ : settings.effort
422
+ );
187
423
  setContextMaxCharsRef(settings.contextMaxChars);
188
424
  setAdvisorPlanGateRef(settings.planGate);
189
425
  setAdvisorFailureGateRef(settings.failureGate);
@@ -195,6 +431,10 @@ export const registerCommands = (pi: ExtensionAPI, dependencies: { consult?: Man
195
431
  setAdvisorLoopThresholdRef(settings.loopThreshold ?? 3);
196
432
  setAdvisorMaxCallsPerSessionRef(settings.maxCallsPerSession);
197
433
  setAdvisorSessionSummaryRef(settings.sessionSummary ?? true);
434
+ setAdvisorFailureModeRef(settings.failureMode ?? "block-session");
435
+ setAdvisorHerdrIntegrationRef(settings.herdrIntegration ?? true);
436
+ setAdvisorToolResultMaxLinesRef(settings.toolResultMaxLines ?? 2000);
437
+ setAdvisorToolResultMaxBytesRef(settings.toolResultMaxBytes ?? 50 * 1024);
198
438
  const path = saveConfig(ctx);
199
439
  ctx.ui.notify(`Saved Advisor settings to ${path}`, "info");
200
440
  },
@@ -203,8 +443,15 @@ export const registerCommands = (pi: ExtensionAPI, dependencies: { consult?: Man
203
443
  pi.registerCommand("advisor-off", {
204
444
  description: "Disable on-demand Advisor calls; keep the current model",
205
445
  handler: async (_args, ctx) => {
206
- pi.setActiveTools(pi.getActiveTools().filter((name) => name !== "ask_advisor"));
207
- if (ctx.hasUI) ctx.ui.notify("Advisor flow disabled. Current model unchanged.", "info");
446
+ pi.setActiveTools(
447
+ pi.getActiveTools().filter((name) => name !== "ask_advisor")
448
+ );
449
+ if (ctx.hasUI) {
450
+ ctx.ui.notify(
451
+ "Advisor flow disabled. Current model unchanged.",
452
+ "info"
453
+ );
454
+ }
208
455
  },
209
456
  });
210
457
  };