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,63 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_MAX_BYTES,
|
|
3
|
+
DEFAULT_MAX_LINES,
|
|
4
|
+
} from "@earendil-works/pi-coding-agent";
|
|
5
|
+
import type { GitContextLevel } from "../git.js";
|
|
6
|
+
|
|
7
|
+
export const DEFAULT_CONTEXT_MAX_CHARS = 15_000;
|
|
8
|
+
export const MAX_CONTEXT_MAX_CHARS = Number.MAX_SAFE_INTEGER;
|
|
9
|
+
export const DEFAULT_ADVISOR_TOOL_RESULT_MAX_LINES = DEFAULT_MAX_LINES;
|
|
10
|
+
export const DEFAULT_ADVISOR_TOOL_RESULT_MAX_BYTES = DEFAULT_MAX_BYTES;
|
|
11
|
+
export const DEFAULT_ADVISOR_GIT_CONTEXT_MAX_CHARS = 20_000;
|
|
12
|
+
|
|
13
|
+
export type AdvisorToolPolicy = "full" | "summary" | "exclude";
|
|
14
|
+
export type AdvisorToolPolicies = Record<string, AdvisorToolPolicy>;
|
|
15
|
+
export const ADVISOR_TOOL_POLICIES: AdvisorToolPolicy[] = [
|
|
16
|
+
"full",
|
|
17
|
+
"summary",
|
|
18
|
+
"exclude",
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
export type GateFailureMode =
|
|
22
|
+
| "block-session"
|
|
23
|
+
| "block-tool"
|
|
24
|
+
| "warn-and-continue";
|
|
25
|
+
export const GATE_FAILURE_MODES: GateFailureMode[] = [
|
|
26
|
+
"block-session",
|
|
27
|
+
"block-tool",
|
|
28
|
+
"warn-and-continue",
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
export interface AdvisorConfig {
|
|
32
|
+
advisor?: string;
|
|
33
|
+
advisorAutoLoopGate?: boolean;
|
|
34
|
+
advisorBlockOnBlocked?: boolean;
|
|
35
|
+
advisorCollapseResponses?: boolean;
|
|
36
|
+
advisorCompletionGate?: boolean;
|
|
37
|
+
advisorCustomInvocation?: string;
|
|
38
|
+
advisorEffort?: string;
|
|
39
|
+
advisorFailureGate?: boolean;
|
|
40
|
+
advisorGitContext?: GitContextLevel;
|
|
41
|
+
advisorGitContextMaxChars?: number;
|
|
42
|
+
advisorHerdrIntegration?: boolean;
|
|
43
|
+
advisorLoopThreshold?: number;
|
|
44
|
+
advisorMaxCallsPerSession?: number;
|
|
45
|
+
advisorOutcomeLogging?: boolean;
|
|
46
|
+
advisorPlanGate?: boolean;
|
|
47
|
+
advisorRedactSecrets?: boolean;
|
|
48
|
+
advisorScoutEnabled?: boolean;
|
|
49
|
+
advisorSessionSummary?: boolean;
|
|
50
|
+
advisorToolPolicies?: AdvisorToolPolicies;
|
|
51
|
+
advisorToolResultMaxBytes?: number;
|
|
52
|
+
advisorToolResultMaxLines?: number;
|
|
53
|
+
advisorTrackedFileContent?: boolean;
|
|
54
|
+
advisorUntrackedContent?: boolean;
|
|
55
|
+
alwaysOn?: boolean;
|
|
56
|
+
contextMaxChars?: number;
|
|
57
|
+
executor?: string;
|
|
58
|
+
executorEffort?: string;
|
|
59
|
+
gateFailureMode?: GateFailureMode;
|
|
60
|
+
showUsageDetails?: boolean;
|
|
61
|
+
showUsageFooter?: boolean;
|
|
62
|
+
simpleMode?: boolean;
|
|
63
|
+
}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { GIT_CONTEXT_LEVELS, isValidGitContextLevel } from "../git.js";
|
|
2
|
+
import {
|
|
3
|
+
ADVISOR_TOOL_POLICIES,
|
|
4
|
+
type AdvisorConfig,
|
|
5
|
+
GATE_FAILURE_MODES,
|
|
6
|
+
MAX_CONTEXT_MAX_CHARS,
|
|
7
|
+
} from "./types.js";
|
|
8
|
+
|
|
9
|
+
const CONFIG_KEYS = new Set<keyof AdvisorConfig>([
|
|
10
|
+
"advisor",
|
|
11
|
+
"advisorAutoLoopGate",
|
|
12
|
+
"advisorBlockOnBlocked",
|
|
13
|
+
"advisorCollapseResponses",
|
|
14
|
+
"advisorCompletionGate",
|
|
15
|
+
"advisorCustomInvocation",
|
|
16
|
+
"advisorEffort",
|
|
17
|
+
"advisorFailureGate",
|
|
18
|
+
"advisorGitContext",
|
|
19
|
+
"advisorGitContextMaxChars",
|
|
20
|
+
"advisorHerdrIntegration",
|
|
21
|
+
"advisorLoopThreshold",
|
|
22
|
+
"advisorMaxCallsPerSession",
|
|
23
|
+
"advisorPlanGate",
|
|
24
|
+
"advisorSessionSummary",
|
|
25
|
+
"advisorScoutEnabled",
|
|
26
|
+
"showUsageDetails",
|
|
27
|
+
"showUsageFooter",
|
|
28
|
+
"simpleMode",
|
|
29
|
+
"alwaysOn",
|
|
30
|
+
"advisorToolResultMaxBytes",
|
|
31
|
+
"advisorToolResultMaxLines",
|
|
32
|
+
"advisorTrackedFileContent",
|
|
33
|
+
"advisorRedactSecrets",
|
|
34
|
+
"advisorUntrackedContent",
|
|
35
|
+
"advisorOutcomeLogging",
|
|
36
|
+
"advisorToolPolicies",
|
|
37
|
+
"contextMaxChars",
|
|
38
|
+
"executor",
|
|
39
|
+
"executorEffort",
|
|
40
|
+
"gateFailureMode",
|
|
41
|
+
]);
|
|
42
|
+
|
|
43
|
+
const BOOLEAN_CONFIG_KEYS = [
|
|
44
|
+
"advisorPlanGate",
|
|
45
|
+
"advisorFailureGate",
|
|
46
|
+
"advisorCompletionGate",
|
|
47
|
+
"advisorCollapseResponses",
|
|
48
|
+
"advisorBlockOnBlocked",
|
|
49
|
+
"advisorAutoLoopGate",
|
|
50
|
+
"advisorSessionSummary",
|
|
51
|
+
"advisorScoutEnabled",
|
|
52
|
+
"showUsageDetails",
|
|
53
|
+
"showUsageFooter",
|
|
54
|
+
"simpleMode",
|
|
55
|
+
"alwaysOn",
|
|
56
|
+
"advisorHerdrIntegration",
|
|
57
|
+
"advisorTrackedFileContent",
|
|
58
|
+
"advisorRedactSecrets",
|
|
59
|
+
"advisorUntrackedContent",
|
|
60
|
+
"advisorOutcomeLogging",
|
|
61
|
+
] as const;
|
|
62
|
+
|
|
63
|
+
const STRING_CONFIG_KEYS = [
|
|
64
|
+
"executor",
|
|
65
|
+
"advisor",
|
|
66
|
+
"executorEffort",
|
|
67
|
+
"advisorEffort",
|
|
68
|
+
"advisorCustomInvocation",
|
|
69
|
+
] as const;
|
|
70
|
+
|
|
71
|
+
type ConfigRecord = Record<string, unknown>;
|
|
72
|
+
|
|
73
|
+
const invalidConfigValue = (
|
|
74
|
+
path: string,
|
|
75
|
+
key: string,
|
|
76
|
+
accepted: string
|
|
77
|
+
): never => {
|
|
78
|
+
throw new TypeError(
|
|
79
|
+
`Invalid advisor configuration at ${path}, key ${JSON.stringify(key)}: expected ${accepted}.`
|
|
80
|
+
);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export const unknownConfigKeys = (config: ConfigRecord) =>
|
|
84
|
+
Object.keys(config).filter(
|
|
85
|
+
(key) => !CONFIG_KEYS.has(key as keyof AdvisorConfig)
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const validateStringValues = (config: ConfigRecord, path: string) => {
|
|
89
|
+
for (const key of STRING_CONFIG_KEYS) {
|
|
90
|
+
if (config[key] !== undefined && typeof config[key] !== "string") {
|
|
91
|
+
invalidConfigValue(
|
|
92
|
+
path,
|
|
93
|
+
key,
|
|
94
|
+
key === "executor" || key === "advisor"
|
|
95
|
+
? "a provider/model string"
|
|
96
|
+
: "a string"
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const validateBooleanValues = (config: ConfigRecord, path: string) => {
|
|
103
|
+
for (const key of BOOLEAN_CONFIG_KEYS) {
|
|
104
|
+
if (config[key] !== undefined && typeof config[key] !== "boolean") {
|
|
105
|
+
invalidConfigValue(path, key, "true or false");
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export const isValidAdvisorToolPolicies = (
|
|
111
|
+
value: unknown
|
|
112
|
+
): value is Record<string, (typeof ADVISOR_TOOL_POLICIES)[number]> => {
|
|
113
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
return Object.entries(value).every(
|
|
117
|
+
([toolName, policy]) =>
|
|
118
|
+
toolName.trim().length > 0 &&
|
|
119
|
+
typeof policy === "string" &&
|
|
120
|
+
ADVISOR_TOOL_POLICIES.includes(
|
|
121
|
+
policy as (typeof ADVISOR_TOOL_POLICIES)[number]
|
|
122
|
+
)
|
|
123
|
+
);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export const isValidContextMaxChars = (value: unknown): value is number =>
|
|
127
|
+
typeof value === "number" &&
|
|
128
|
+
Number.isSafeInteger(value) &&
|
|
129
|
+
value >= 0 &&
|
|
130
|
+
value <= MAX_CONTEXT_MAX_CHARS;
|
|
131
|
+
|
|
132
|
+
export const isValidLoopThreshold = (value: unknown): value is number =>
|
|
133
|
+
typeof value === "number" && Number.isSafeInteger(value) && value >= 2;
|
|
134
|
+
|
|
135
|
+
export const isValidMaxCallsPerSession = (value: unknown): value is number =>
|
|
136
|
+
typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
137
|
+
|
|
138
|
+
export const isValidGateFailureMode = (
|
|
139
|
+
value: unknown
|
|
140
|
+
): value is (typeof GATE_FAILURE_MODES)[number] =>
|
|
141
|
+
typeof value === "string" &&
|
|
142
|
+
GATE_FAILURE_MODES.includes(value as (typeof GATE_FAILURE_MODES)[number]);
|
|
143
|
+
|
|
144
|
+
export const isValidToolResultMaxLines = (value: unknown): value is number =>
|
|
145
|
+
typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
146
|
+
|
|
147
|
+
export const isValidToolResultMaxBytes = (value: unknown): value is number =>
|
|
148
|
+
typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
149
|
+
|
|
150
|
+
const validateNumericValues = (config: ConfigRecord, path: string) => {
|
|
151
|
+
const numericRules: [
|
|
152
|
+
keyof AdvisorConfig,
|
|
153
|
+
(value: unknown) => boolean,
|
|
154
|
+
string,
|
|
155
|
+
][] = [
|
|
156
|
+
[
|
|
157
|
+
"contextMaxChars",
|
|
158
|
+
isValidContextMaxChars,
|
|
159
|
+
`a safe integer from 0 through ${MAX_CONTEXT_MAX_CHARS}`,
|
|
160
|
+
],
|
|
161
|
+
[
|
|
162
|
+
"advisorLoopThreshold",
|
|
163
|
+
isValidLoopThreshold,
|
|
164
|
+
"a safe integer of at least 2",
|
|
165
|
+
],
|
|
166
|
+
[
|
|
167
|
+
"advisorMaxCallsPerSession",
|
|
168
|
+
isValidMaxCallsPerSession,
|
|
169
|
+
"a non-negative safe integer",
|
|
170
|
+
],
|
|
171
|
+
[
|
|
172
|
+
"advisorToolResultMaxLines",
|
|
173
|
+
isValidToolResultMaxLines,
|
|
174
|
+
"a non-negative safe integer",
|
|
175
|
+
],
|
|
176
|
+
[
|
|
177
|
+
"advisorToolResultMaxBytes",
|
|
178
|
+
isValidToolResultMaxBytes,
|
|
179
|
+
"a non-negative safe integer",
|
|
180
|
+
],
|
|
181
|
+
[
|
|
182
|
+
"advisorGitContextMaxChars",
|
|
183
|
+
isValidToolResultMaxBytes,
|
|
184
|
+
"a non-negative safe integer",
|
|
185
|
+
],
|
|
186
|
+
];
|
|
187
|
+
for (const [key, isValid, description] of numericRules) {
|
|
188
|
+
if (config[key] !== undefined && !isValid(config[key])) {
|
|
189
|
+
invalidConfigValue(path, key, description);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
export const validateConfig = (
|
|
195
|
+
value: unknown,
|
|
196
|
+
path = "advisor.json"
|
|
197
|
+
): value is AdvisorConfig => {
|
|
198
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
199
|
+
throw new TypeError(
|
|
200
|
+
`Invalid advisor configuration at ${path}: expected a JSON object.`
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
const config = value as ConfigRecord;
|
|
204
|
+
validateStringValues(config, path);
|
|
205
|
+
validateBooleanValues(config, path);
|
|
206
|
+
validateNumericValues(config, path);
|
|
207
|
+
if (
|
|
208
|
+
config.advisorToolPolicies !== undefined &&
|
|
209
|
+
!isValidAdvisorToolPolicies(config.advisorToolPolicies)
|
|
210
|
+
) {
|
|
211
|
+
invalidConfigValue(
|
|
212
|
+
path,
|
|
213
|
+
"advisorToolPolicies",
|
|
214
|
+
"a JSON object with non-empty tool names and full, summary, or exclude values"
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
if (
|
|
218
|
+
config.gateFailureMode !== undefined &&
|
|
219
|
+
!isValidGateFailureMode(config.gateFailureMode)
|
|
220
|
+
) {
|
|
221
|
+
invalidConfigValue(path, "gateFailureMode", GATE_FAILURE_MODES.join(", "));
|
|
222
|
+
}
|
|
223
|
+
if (
|
|
224
|
+
config.advisorGitContext !== undefined &&
|
|
225
|
+
!isValidGitContextLevel(config.advisorGitContext)
|
|
226
|
+
) {
|
|
227
|
+
invalidConfigValue(
|
|
228
|
+
path,
|
|
229
|
+
"advisorGitContext",
|
|
230
|
+
GIT_CONTEXT_LEVELS.join(", ")
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
return true;
|
|
234
|
+
};
|