pi-advisor-flow 0.5.1 → 0.5.2

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.
Files changed (59) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +3 -2
  3. package/extensions/index.ts +7 -7
  4. package/package.json +2 -1
  5. package/src/commands/activation-preparation.ts +117 -0
  6. package/src/commands/activation.ts +135 -0
  7. package/src/commands/lifecycle.ts +83 -0
  8. package/src/commands/manual-command.ts +107 -0
  9. package/src/commands/manual-consultation.ts +144 -0
  10. package/src/commands/manual-progress.ts +93 -0
  11. package/src/commands/model-commands.ts +66 -0
  12. package/src/commands/model-options.ts +181 -0
  13. package/src/commands/model-picker.ts +110 -0
  14. package/src/commands/registration.ts +27 -0
  15. package/src/commands/renderers.ts +76 -0
  16. package/src/commands/runtime.ts +114 -0
  17. package/src/commands/settings-commands.ts +80 -0
  18. package/src/commands/settings-persistence.ts +81 -0
  19. package/src/commands/types.ts +78 -0
  20. package/src/commands.ts +9 -1259
  21. package/src/config/args.ts +37 -0
  22. package/src/config/defaults.ts +190 -0
  23. package/src/config/state.ts +199 -0
  24. package/src/config/storage.ts +224 -0
  25. package/src/config/types.ts +63 -0
  26. package/src/config/validation.ts +234 -0
  27. package/src/config.ts +104 -814
  28. package/src/conversation.ts +4 -2
  29. package/src/herdr.ts +1 -1
  30. package/src/model-stream.ts +15 -1
  31. package/src/scout-context.ts +2 -2
  32. package/src/scout.ts +1 -1
  33. package/src/tools/consultation.ts +337 -0
  34. package/src/tools/gate-policy.ts +132 -0
  35. package/src/tools/gate-protocol.ts +127 -0
  36. package/src/tools/loop-gate.ts +210 -0
  37. package/src/tools/prompts.ts +159 -0
  38. package/src/tools/register-ask-advisor.ts +225 -0
  39. package/src/tools/register-lifecycle.ts +89 -0
  40. package/src/tools/register-outcome.ts +75 -0
  41. package/src/tools/register-renderers.ts +88 -0
  42. package/src/tools/registration.ts +35 -0
  43. package/src/tools/render-advisor-result.ts +168 -0
  44. package/src/tools/render-common.ts +120 -0
  45. package/src/tools/scout-status.ts +206 -0
  46. package/src/tools/session.ts +3 -0
  47. package/src/tools/types.ts +119 -0
  48. package/src/tools.ts +42 -1865
  49. package/src/ui/manual-dialog-render.ts +150 -0
  50. package/src/ui/manual-dialog.ts +305 -0
  51. package/src/ui/model-selector.ts +166 -0
  52. package/src/ui/settings-formatting.ts +133 -0
  53. package/src/ui/settings-items.ts +323 -0
  54. package/src/ui/settings-list-adapter.ts +103 -0
  55. package/src/ui/settings-mutations.ts +80 -0
  56. package/src/ui/settings-selector.ts +161 -0
  57. package/src/ui/text-setting-submenu.ts +66 -0
  58. package/src/ui/types.ts +111 -0
  59. package/src/ui.ts +9 -1418
@@ -0,0 +1,80 @@
1
+ import {
2
+ alwaysOnRef,
3
+ getAdvisorSettings,
4
+ getPersistedModelRefs,
5
+ setAlwaysOnRef,
6
+ } from "../config/state.js";
7
+ import { saveConfig } from "../config/storage.js";
8
+ import { AdvisorSettingsSelector } from "../ui/settings-selector.js";
9
+ import { loadCommandConfig } from "./activation-preparation.js";
10
+ import { CONTEXT_PRESETS, EFFORT_LEVELS } from "./model-options.js";
11
+ import { notify } from "./runtime.js";
12
+ import { saveAdvisorSettings } from "./settings-persistence.js";
13
+ import type { CommandRuntime } from "./types.js";
14
+
15
+ export const registerSettingsCommands = (runtime: CommandRuntime) => {
16
+ runtime.pi.registerCommand("advisor-settings", {
17
+ description: "Configure Advisor settings",
18
+ handler: async (_args, ctx) => {
19
+ if (!(loadCommandConfig(ctx) && ctx.hasUI)) {
20
+ return;
21
+ }
22
+
23
+ const initial = getAdvisorSettings();
24
+ await ctx.ui.custom<void>(
25
+ (tui, theme, _keybindings, done) =>
26
+ new AdvisorSettingsSelector({
27
+ effortLevels: EFFORT_LEVELS,
28
+ initial,
29
+ onCancel: () => done(),
30
+ onChange: (settings) => {
31
+ try {
32
+ saveAdvisorSettings(ctx, settings);
33
+ runtime.updateAdvisorUsageStatus(ctx);
34
+ } catch (error) {
35
+ const message =
36
+ error instanceof Error ? error.message : String(error);
37
+ ctx.ui.notify(
38
+ `Could not save Advisor settings: ${message}`,
39
+ "error"
40
+ );
41
+ }
42
+ },
43
+ presets: CONTEXT_PRESETS,
44
+ theme,
45
+ tui,
46
+ })
47
+ );
48
+ },
49
+ });
50
+
51
+ runtime.pi.registerCommand("advisor-off", {
52
+ description: "Disable on-demand Advisor calls; keep the current model",
53
+ handler: (_args, ctx) => {
54
+ runtime.pi.setActiveTools(
55
+ runtime.pi
56
+ .getActiveTools()
57
+ .filter(
58
+ (name) =>
59
+ name !== "ask_advisor" && name !== "record_advisor_outcome"
60
+ )
61
+ );
62
+ // Leaving alwaysOn set would silently reactivate the flow next session.
63
+ const wasAlwaysOn = alwaysOnRef;
64
+ if (wasAlwaysOn) {
65
+ const persisted = getPersistedModelRefs();
66
+ setAlwaysOnRef(false);
67
+ saveConfig(ctx, {
68
+ persistAdvisor: Boolean(persisted.advisor),
69
+ persistExecutor: Boolean(persisted.executor),
70
+ });
71
+ }
72
+ notify(
73
+ ctx,
74
+ `Advisor flow disabled. Current model unchanged.${wasAlwaysOn ? " Always on turned off." : ""}`,
75
+ "info"
76
+ );
77
+ return Promise.resolve();
78
+ },
79
+ });
80
+ };
@@ -0,0 +1,81 @@
1
+ import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
2
+ import {
3
+ getPersistedModelRefs,
4
+ setAdvisorAutoLoopGateRef,
5
+ setAdvisorBlockOnBlockedRef,
6
+ setAdvisorCollapseResponsesRef,
7
+ setAdvisorCompletionGateRef,
8
+ setAdvisorCustomInvocationRef,
9
+ setAdvisorEffortRef,
10
+ setAdvisorFailureGateRef,
11
+ setAdvisorFailureModeRef,
12
+ setAdvisorGitContextMaxCharsRef,
13
+ setAdvisorGitContextRef,
14
+ setAdvisorHerdrIntegrationRef,
15
+ setAdvisorLoopThresholdRef,
16
+ setAdvisorMaxCallsPerSessionRef,
17
+ setAdvisorOutcomeLoggingRef,
18
+ setAdvisorPlanGateRef,
19
+ setAdvisorRedactSecretsRef,
20
+ setAdvisorScoutEnabledRef,
21
+ setAdvisorSessionSummaryRef,
22
+ setAdvisorToolPoliciesRef,
23
+ setAdvisorToolResultMaxBytesRef,
24
+ setAdvisorToolResultMaxLinesRef,
25
+ setAdvisorTrackedFileContentRef,
26
+ setAdvisorUntrackedContentRef,
27
+ setAlwaysOnRef,
28
+ setContextMaxCharsRef,
29
+ setShowUsageDetailsRef,
30
+ setShowUsageFooterRef,
31
+ setSimpleModeRef,
32
+ } from "../config/state.js";
33
+ import { saveConfig, saveGlobalOutcomeLogging } from "../config/storage.js";
34
+ import type { AdvisorSettings } from "../ui/types.js";
35
+
36
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: one settings form maps every persisted control.
37
+ export const applyAdvisorSettings = (settings: AdvisorSettings) => {
38
+ setAdvisorEffortRef(
39
+ settings.effort === "Default (Model Default)" ? undefined : settings.effort
40
+ );
41
+ setContextMaxCharsRef(settings.contextMaxChars);
42
+ setAdvisorPlanGateRef(settings.planGate);
43
+ setAdvisorFailureGateRef(settings.failureGate);
44
+ setAdvisorCompletionGateRef(settings.completionGate);
45
+ setAdvisorCollapseResponsesRef(settings.collapseResponses);
46
+ setAdvisorCustomInvocationRef(settings.customRule);
47
+ setAdvisorBlockOnBlockedRef(settings.blockOnBlocked ?? true);
48
+ setAdvisorAutoLoopGateRef(settings.autoLoopGate ?? true);
49
+ setAdvisorLoopThresholdRef(settings.loopThreshold ?? 3);
50
+ setAdvisorMaxCallsPerSessionRef(settings.maxCallsPerSession);
51
+ setAdvisorSessionSummaryRef(settings.sessionSummary ?? false);
52
+ setAdvisorScoutEnabledRef(settings.scoutEnabled ?? false);
53
+ setShowUsageDetailsRef(settings.showUsageDetails ?? true);
54
+ setShowUsageFooterRef(settings.showUsageFooter ?? false);
55
+ setSimpleModeRef(settings.simpleMode ?? false);
56
+ setAlwaysOnRef(settings.alwaysOn ?? false);
57
+ setAdvisorFailureModeRef(settings.failureMode ?? "block-session");
58
+ setAdvisorHerdrIntegrationRef(settings.herdrIntegration ?? true);
59
+ setAdvisorToolResultMaxLinesRef(settings.toolResultMaxLines ?? 2000);
60
+ setAdvisorToolResultMaxBytesRef(settings.toolResultMaxBytes ?? 50 * 1024);
61
+ setAdvisorRedactSecretsRef(settings.redactSecrets ?? false);
62
+ setAdvisorGitContextRef(settings.gitContext ?? "summary");
63
+ setAdvisorGitContextMaxCharsRef(settings.gitContextMaxChars ?? 20_000);
64
+ setAdvisorToolPoliciesRef(settings.toolPolicies ?? {});
65
+ setAdvisorTrackedFileContentRef(settings.trackedFileContent ?? false);
66
+ setAdvisorUntrackedContentRef(settings.untrackedContent ?? false);
67
+ setAdvisorOutcomeLoggingRef(settings.outcomeLogging ?? false);
68
+ };
69
+
70
+ export const saveAdvisorSettings = (
71
+ ctx: ExtensionContext,
72
+ settings: AdvisorSettings
73
+ ) => {
74
+ applyAdvisorSettings(settings);
75
+ const persisted = getPersistedModelRefs();
76
+ saveConfig(ctx, {
77
+ persistAdvisor: Boolean(persisted.advisor),
78
+ persistExecutor: Boolean(persisted.executor),
79
+ });
80
+ saveGlobalOutcomeLogging(settings.outcomeLogging ?? false);
81
+ };
@@ -0,0 +1,78 @@
1
+ import type {
2
+ ExtensionAPI,
3
+ ExtensionContext,
4
+ Theme,
5
+ } from "@earendil-works/pi-coding-agent";
6
+ import type { GitContextLevel } from "../git.js";
7
+ import type { ScoutLifecycleEvent } from "../scout.js";
8
+ import type { AdvisorSessionState } from "../session-state.js";
9
+ import type { ScoutStatusManager } from "../tools/scout-status.js";
10
+ import type { ScoutToolDetails } from "../tools/types.js";
11
+
12
+ export type ManualConsult = (
13
+ ctx: ExtensionContext,
14
+ question?: string,
15
+ signal?: AbortSignal,
16
+ onChunk?: (thinking: string, text: string) => void,
17
+ onScout?: (event: ScoutLifecycleEvent) => void,
18
+ gitContext?: GitContextLevel
19
+ ) => Promise<{
20
+ markdown: string;
21
+ thinkingText: string;
22
+ draftBytes?: number;
23
+ preferenceBytes?: number;
24
+ usage?: unknown;
25
+ }>;
26
+
27
+ export type ThinkingLevel = Parameters<ExtensionAPI["setThinkingLevel"]>[0];
28
+
29
+ export type ManualAdvisorProgressPhase =
30
+ | "preparing"
31
+ | "active"
32
+ | "complete"
33
+ | "cancelled"
34
+ | "error";
35
+
36
+ export interface ManualAdvisorProgressState {
37
+ phase: ManualAdvisorProgressPhase;
38
+ scout?: ScoutToolDetails;
39
+ text?: string;
40
+ thinking?: string;
41
+ }
42
+
43
+ export interface CommandDependencies {
44
+ consult?: ManualConsult;
45
+ sessionState?: AdvisorSessionState;
46
+ statusManager?: ScoutStatusManager;
47
+ }
48
+
49
+ export interface CommandRuntime {
50
+ readonly advisorSessionState: AdvisorSessionState;
51
+ flowEnabled: () => boolean;
52
+ readonly manualConsultations: Map<AbortController, symbol>;
53
+ readonly manualProgress: Map<string, ManualAdvisorProgressState>;
54
+ manualProgressSequence: number;
55
+ readonly manualProgressTimers: Map<
56
+ AbortController,
57
+ ReturnType<typeof setInterval>
58
+ >;
59
+ nextManualProgressId: () => string;
60
+ pendingExecutorModelRef: string | undefined;
61
+ readonly pi: ExtensionAPI;
62
+ reportManualBudgetExhausted: (ctx: ExtensionContext) => void;
63
+ readonly requestAdvisor: ManualConsult;
64
+ requestManualRender: (ctx: ExtensionContext) => void;
65
+ readonly scoutStatus: ScoutStatusManager;
66
+ setExecutorModel: (
67
+ model: Parameters<ExtensionAPI["setModel"]>[0]
68
+ ) => ReturnType<ExtensionAPI["setModel"]>;
69
+ suppressModelSelectionSync: boolean;
70
+ updateAdvisorUsageStatus: (ctx: ExtensionContext) => void;
71
+ }
72
+
73
+ export interface ManualAdvisorProgressView {
74
+ expanded: boolean;
75
+ question: string | undefined;
76
+ state: ManualAdvisorProgressState;
77
+ theme: Theme;
78
+ }