pi-advisor-flow 0.5.0 → 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.
- package/CHANGELOG.md +54 -0
- package/README.md +37 -71
- package/extensions/index.ts +7 -7
- package/package.json +19 -6
- package/src/commands/activation-preparation.ts +117 -0
- package/src/commands/activation.ts +135 -0
- package/src/commands/lifecycle.ts +83 -0
- package/src/commands/manual-command.ts +107 -0
- package/src/commands/manual-consultation.ts +144 -0
- package/src/commands/manual-progress.ts +93 -0
- package/src/commands/model-commands.ts +66 -0
- package/src/commands/model-options.ts +181 -0
- package/src/commands/model-picker.ts +110 -0
- package/src/commands/registration.ts +27 -0
- package/src/commands/renderers.ts +76 -0
- package/src/commands/runtime.ts +114 -0
- package/src/commands/settings-commands.ts +80 -0
- package/src/commands/settings-persistence.ts +81 -0
- package/src/commands/types.ts +78 -0
- package/src/commands.ts +9 -946
- package/src/config/args.ts +37 -0
- package/src/config/defaults.ts +190 -0
- package/src/config/state.ts +199 -0
- package/src/config/storage.ts +224 -0
- package/src/config/types.ts +63 -0
- package/src/config/validation.ts +234 -0
- package/src/config.ts +104 -791
- package/src/conversation.ts +4 -2
- package/src/herdr.ts +1 -1
- package/src/model-stream.ts +25 -2
- package/src/scout-context.ts +2 -2
- package/src/scout.ts +1 -1
- package/src/tools/consultation.ts +337 -0
- package/src/tools/gate-policy.ts +132 -0
- package/src/tools/gate-protocol.ts +127 -0
- package/src/tools/loop-gate.ts +210 -0
- package/src/tools/prompts.ts +159 -0
- package/src/tools/register-ask-advisor.ts +225 -0
- package/src/tools/register-lifecycle.ts +89 -0
- package/src/tools/register-outcome.ts +75 -0
- package/src/tools/register-renderers.ts +88 -0
- package/src/tools/registration.ts +35 -0
- package/src/tools/render-advisor-result.ts +168 -0
- package/src/tools/render-common.ts +120 -0
- package/src/tools/scout-status.ts +206 -0
- package/src/tools/session.ts +3 -0
- package/src/tools/types.ts +119 -0
- package/src/tools.ts +42 -1811
- package/src/ui/manual-dialog-render.ts +150 -0
- package/src/ui/manual-dialog.ts +305 -0
- package/src/ui/model-selector.ts +166 -0
- package/src/ui/settings-formatting.ts +133 -0
- package/src/ui/settings-items.ts +323 -0
- package/src/ui/settings-list-adapter.ts +103 -0
- package/src/ui/settings-mutations.ts +80 -0
- package/src/ui/settings-selector.ts +161 -0
- package/src/ui/text-setting-submenu.ts +66 -0
- package/src/ui/types.ts +111 -0
- package/src/ui.ts +9 -1418
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ExtensionAPI,
|
|
3
|
+
ExtensionContext,
|
|
4
|
+
} from "@earendil-works/pi-coding-agent";
|
|
5
|
+
import { activateAdvisor } from "./activation.js";
|
|
6
|
+
import { registerCommandLifecycle } from "./lifecycle.js";
|
|
7
|
+
import { registerManualCommand } from "./manual-command.js";
|
|
8
|
+
import { registerModelCommands } from "./model-commands.js";
|
|
9
|
+
import { registerCommandRenderers } from "./renderers.js";
|
|
10
|
+
import { createCommandRuntime } from "./runtime.js";
|
|
11
|
+
import { registerSettingsCommands } from "./settings-commands.js";
|
|
12
|
+
import type { CommandDependencies } from "./types.js";
|
|
13
|
+
|
|
14
|
+
export const registerCommands = (
|
|
15
|
+
pi: ExtensionAPI,
|
|
16
|
+
dependencies: CommandDependencies = {}
|
|
17
|
+
) => {
|
|
18
|
+
const runtime = createCommandRuntime(pi, dependencies);
|
|
19
|
+
const activate = (args: string, ctx: ExtensionContext, announce = true) =>
|
|
20
|
+
activateAdvisor(runtime, args, ctx, announce);
|
|
21
|
+
|
|
22
|
+
registerCommandRenderers(runtime);
|
|
23
|
+
registerCommandLifecycle(runtime, activate);
|
|
24
|
+
registerManualCommand(runtime);
|
|
25
|
+
registerModelCommands(runtime);
|
|
26
|
+
registerSettingsCommands(runtime);
|
|
27
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { getMarkdownTheme } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { Box, Markdown, Text } from "@earendil-works/pi-tui";
|
|
3
|
+
import { getAdvisorSettings } from "../config/state.js";
|
|
4
|
+
import {
|
|
5
|
+
adviceForDisplay,
|
|
6
|
+
hasSoundVerdict,
|
|
7
|
+
renderAdvisorCallBox,
|
|
8
|
+
renderAdvisorResponseHeader,
|
|
9
|
+
} from "../tools/render-common.js";
|
|
10
|
+
import { formatAdvisorUsage } from "../usage.js";
|
|
11
|
+
import { ManualAdvisorProgressComponent } from "./manual-progress.js";
|
|
12
|
+
import type { CommandRuntime } from "./types.js";
|
|
13
|
+
|
|
14
|
+
export const registerCommandRenderers = (runtime: CommandRuntime) => {
|
|
15
|
+
runtime.pi.registerEntryRenderer?.(
|
|
16
|
+
"advisor-manual-call",
|
|
17
|
+
(entry, { expanded }, theme) => {
|
|
18
|
+
const { progressId, question } = (entry.data ?? {}) as {
|
|
19
|
+
progressId?: string;
|
|
20
|
+
question?: string;
|
|
21
|
+
};
|
|
22
|
+
const progress = progressId
|
|
23
|
+
? runtime.manualProgress.get(progressId)
|
|
24
|
+
: undefined;
|
|
25
|
+
return progress
|
|
26
|
+
? new ManualAdvisorProgressComponent(
|
|
27
|
+
question,
|
|
28
|
+
progress,
|
|
29
|
+
Boolean(expanded),
|
|
30
|
+
theme
|
|
31
|
+
)
|
|
32
|
+
: renderAdvisorCallBox(question, theme);
|
|
33
|
+
}
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
runtime.pi.registerMessageRenderer?.(
|
|
37
|
+
"advisor-manual-result",
|
|
38
|
+
(message, { expanded }, theme) => {
|
|
39
|
+
const details = message.details as
|
|
40
|
+
| { advisor?: string; text?: string; usage?: unknown }
|
|
41
|
+
| undefined;
|
|
42
|
+
const box = new Box(1, 1, (text) => theme.bg("customMessageBg", text));
|
|
43
|
+
const advice =
|
|
44
|
+
details?.text ??
|
|
45
|
+
(typeof message.content === "string"
|
|
46
|
+
? message.content
|
|
47
|
+
: "(Advisor returned no advice.)");
|
|
48
|
+
// Manual consultations must render exactly like an Executor ask_advisor call.
|
|
49
|
+
box.addChild(
|
|
50
|
+
new Text(
|
|
51
|
+
renderAdvisorResponseHeader(hasSoundVerdict(advice), theme),
|
|
52
|
+
0,
|
|
53
|
+
0
|
|
54
|
+
)
|
|
55
|
+
);
|
|
56
|
+
if (details?.advisor) {
|
|
57
|
+
box.addChild(new Text(theme.fg("dim", ` ${details.advisor}`), 0, 0));
|
|
58
|
+
}
|
|
59
|
+
if (getAdvisorSettings().showUsageDetails) {
|
|
60
|
+
const usage = formatAdvisorUsage(details?.usage);
|
|
61
|
+
if (usage) {
|
|
62
|
+
box.addChild(new Text(theme.fg("dim", ` Usage: ${usage}`), 0, 0));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
box.addChild(
|
|
66
|
+
new Markdown(
|
|
67
|
+
adviceForDisplay(advice, expanded),
|
|
68
|
+
0,
|
|
69
|
+
0,
|
|
70
|
+
getMarkdownTheme()
|
|
71
|
+
)
|
|
72
|
+
);
|
|
73
|
+
return box;
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ExtensionAPI,
|
|
3
|
+
ExtensionContext,
|
|
4
|
+
} from "@earendil-works/pi-coding-agent";
|
|
5
|
+
import { getAdvisorSettings } from "../config/state.js";
|
|
6
|
+
import { notifyHerdrAdvisorFailure } from "../herdr.js";
|
|
7
|
+
import type { AdvisorSessionState } from "../session-state.js";
|
|
8
|
+
import { consultAdvisor } from "../tools/consultation.js";
|
|
9
|
+
import { ScoutStatusManager } from "../tools/scout-status.js";
|
|
10
|
+
import { advisorSessionState as defaultAdvisorSessionState } from "../tools/session.js";
|
|
11
|
+
import type {
|
|
12
|
+
CommandDependencies,
|
|
13
|
+
CommandRuntime as CommandRuntimeContract,
|
|
14
|
+
ManualAdvisorProgressState,
|
|
15
|
+
ManualConsult,
|
|
16
|
+
} from "./types.js";
|
|
17
|
+
|
|
18
|
+
export const notify = (
|
|
19
|
+
ctx: ExtensionContext,
|
|
20
|
+
message: string,
|
|
21
|
+
level: "error" | "info" | "warning"
|
|
22
|
+
) => {
|
|
23
|
+
if (ctx.hasUI) {
|
|
24
|
+
ctx.ui.notify(message, level);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export class CommandRuntime implements CommandRuntimeContract {
|
|
29
|
+
readonly advisorSessionState: AdvisorSessionState;
|
|
30
|
+
readonly manualConsultations = new Map<AbortController, symbol>();
|
|
31
|
+
readonly manualProgress = new Map<string, ManualAdvisorProgressState>();
|
|
32
|
+
readonly manualProgressTimers = new Map<
|
|
33
|
+
AbortController,
|
|
34
|
+
ReturnType<typeof setInterval>
|
|
35
|
+
>();
|
|
36
|
+
readonly pi: ExtensionAPI;
|
|
37
|
+
readonly requestAdvisor: ManualConsult;
|
|
38
|
+
readonly scoutStatus: ScoutStatusManager;
|
|
39
|
+
manualProgressSequence = 0;
|
|
40
|
+
pendingExecutorModelRef: string | undefined;
|
|
41
|
+
suppressModelSelectionSync = false;
|
|
42
|
+
|
|
43
|
+
constructor(pi: ExtensionAPI, dependencies: CommandDependencies = {}) {
|
|
44
|
+
this.pi = pi;
|
|
45
|
+
this.advisorSessionState =
|
|
46
|
+
dependencies.sessionState ?? defaultAdvisorSessionState;
|
|
47
|
+
this.scoutStatus =
|
|
48
|
+
dependencies.statusManager ?? new ScoutStatusManager(false);
|
|
49
|
+
this.requestAdvisor =
|
|
50
|
+
dependencies.consult ??
|
|
51
|
+
((ctx, question, signal, onChunk, onScout, gitContext) =>
|
|
52
|
+
consultAdvisor(
|
|
53
|
+
ctx,
|
|
54
|
+
question,
|
|
55
|
+
signal,
|
|
56
|
+
onChunk,
|
|
57
|
+
"manual",
|
|
58
|
+
gitContext,
|
|
59
|
+
undefined,
|
|
60
|
+
undefined,
|
|
61
|
+
undefined,
|
|
62
|
+
onScout,
|
|
63
|
+
undefined
|
|
64
|
+
));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
flowEnabled() {
|
|
68
|
+
return this.pi.getActiveTools().includes("ask_advisor");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
nextManualProgressId() {
|
|
72
|
+
this.manualProgressSequence += 1;
|
|
73
|
+
return `manual-${this.manualProgressSequence}`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async setExecutorModel(
|
|
77
|
+
model: Parameters<ExtensionAPI["setModel"]>[0]
|
|
78
|
+
): Promise<boolean> {
|
|
79
|
+
this.suppressModelSelectionSync = true;
|
|
80
|
+
try {
|
|
81
|
+
return await this.pi.setModel(model);
|
|
82
|
+
} finally {
|
|
83
|
+
this.suppressModelSelectionSync = false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
updateAdvisorUsageStatus(ctx: ExtensionContext) {
|
|
88
|
+
if (ctx.hasUI) {
|
|
89
|
+
ctx.ui.setStatus(
|
|
90
|
+
"advisor-usage",
|
|
91
|
+
getAdvisorSettings().showUsageFooter
|
|
92
|
+
? this.advisorSessionState.usageStatus()
|
|
93
|
+
: undefined
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
reportManualBudgetExhausted(ctx: ExtensionContext) {
|
|
99
|
+
const message = "Advisor call budget exhausted for this session.";
|
|
100
|
+
notify(ctx, message, "warning");
|
|
101
|
+
notifyHerdrAdvisorFailure("Advisor budget exhausted", message);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
requestManualRender(ctx: ExtensionContext) {
|
|
105
|
+
if (ctx.hasUI) {
|
|
106
|
+
ctx.ui.setStatus("advisor-manual", undefined);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export const createCommandRuntime = (
|
|
112
|
+
pi: ExtensionAPI,
|
|
113
|
+
dependencies: CommandDependencies = {}
|
|
114
|
+
) => new CommandRuntime(pi, dependencies);
|
|
@@ -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
|
+
}
|