pi-advisor-flow 0.1.9 → 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/README.md +15 -11
- package/extensions/index.ts +17 -1
- package/package.json +25 -21
- package/src/commands.ts +346 -99
- package/src/config.ts +345 -94
- package/src/conversation.ts +199 -48
- package/src/herdr.ts +145 -30
- package/src/session-state.ts +182 -41
- package/src/tools.ts +687 -179
- package/src/ui.ts +317 -81
package/src/config.ts
CHANGED
|
@@ -1,48 +1,124 @@
|
|
|
1
1
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
CONFIG_DIR_NAME,
|
|
5
|
+
DEFAULT_MAX_BYTES,
|
|
6
|
+
DEFAULT_MAX_LINES,
|
|
7
|
+
type ExtensionContext,
|
|
8
|
+
getAgentDir,
|
|
9
|
+
} from "@earendil-works/pi-coding-agent";
|
|
4
10
|
|
|
5
11
|
export const FALLBACK_EXECUTOR = "aikeys/claude-sonnet-5";
|
|
6
12
|
export const FALLBACK_ADVISOR = "aikeys/claude-fable-5";
|
|
7
13
|
export const DEFAULT_CONTEXT_MAX_CHARS = 15_000;
|
|
8
|
-
// MAX_SAFE_INTEGER represents the complete reconstructed branch (the ALL preset).
|
|
9
14
|
export const MAX_CONTEXT_MAX_CHARS = Number.MAX_SAFE_INTEGER;
|
|
15
|
+
export const DEFAULT_ADVISOR_TOOL_RESULT_MAX_LINES = DEFAULT_MAX_LINES;
|
|
16
|
+
export const DEFAULT_ADVISOR_TOOL_RESULT_MAX_BYTES = DEFAULT_MAX_BYTES;
|
|
17
|
+
export type GateFailureMode =
|
|
18
|
+
| "block-session"
|
|
19
|
+
| "block-tool"
|
|
20
|
+
| "warn-and-continue";
|
|
21
|
+
export const GATE_FAILURE_MODES: GateFailureMode[] = [
|
|
22
|
+
"block-session",
|
|
23
|
+
"block-tool",
|
|
24
|
+
"warn-and-continue",
|
|
25
|
+
];
|
|
10
26
|
|
|
11
27
|
export let executorRef = FALLBACK_EXECUTOR;
|
|
12
28
|
export let advisorRef = FALLBACK_ADVISOR;
|
|
13
|
-
export let executorEffortRef: string | undefined
|
|
14
|
-
export let advisorEffortRef: string | undefined
|
|
29
|
+
export let executorEffortRef: string | undefined;
|
|
30
|
+
export let advisorEffortRef: string | undefined;
|
|
15
31
|
export let contextMaxCharsRef = DEFAULT_CONTEXT_MAX_CHARS;
|
|
16
32
|
export let advisorPlanGateRef = true;
|
|
17
33
|
export let advisorFailureGateRef = true;
|
|
18
34
|
export let advisorCompletionGateRef = true;
|
|
19
|
-
export let advisorCustomInvocationRef: string | undefined
|
|
35
|
+
export let advisorCustomInvocationRef: string | undefined;
|
|
20
36
|
export let advisorCollapseResponsesRef = false;
|
|
21
37
|
export let advisorBlockOnBlockedRef = true;
|
|
22
38
|
export let advisorAutoLoopGateRef = true;
|
|
23
39
|
export let advisorLoopThresholdRef = 3;
|
|
24
|
-
export let advisorMaxCallsPerSessionRef: number | undefined
|
|
40
|
+
export let advisorMaxCallsPerSessionRef: number | undefined;
|
|
25
41
|
export let advisorSessionSummaryRef = true;
|
|
42
|
+
export let advisorFailureModeRef: GateFailureMode = "block-session";
|
|
43
|
+
export let advisorHerdrIntegrationRef = true;
|
|
44
|
+
export let advisorToolResultMaxLinesRef = DEFAULT_ADVISOR_TOOL_RESULT_MAX_LINES;
|
|
45
|
+
export let advisorToolResultMaxBytesRef = DEFAULT_ADVISOR_TOOL_RESULT_MAX_BYTES;
|
|
26
46
|
|
|
27
|
-
export const setExecutorRef = (ref: string) => {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
export const
|
|
47
|
+
export const setExecutorRef = (ref: string) => {
|
|
48
|
+
executorRef = ref;
|
|
49
|
+
};
|
|
50
|
+
export const setAdvisorRef = (ref: string) => {
|
|
51
|
+
advisorRef = ref;
|
|
52
|
+
};
|
|
53
|
+
export const setExecutorEffortRef = (effort: string | undefined) => {
|
|
54
|
+
executorEffortRef = effort;
|
|
55
|
+
};
|
|
56
|
+
export const setAdvisorEffortRef = (effort: string | undefined) => {
|
|
57
|
+
advisorEffortRef = effort;
|
|
58
|
+
};
|
|
31
59
|
export const isValidContextMaxChars = (value: unknown): value is number =>
|
|
32
|
-
typeof value === "number" &&
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
export const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
export const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
export const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
export const
|
|
60
|
+
typeof value === "number" &&
|
|
61
|
+
Number.isSafeInteger(value) &&
|
|
62
|
+
value >= 0 &&
|
|
63
|
+
value <= MAX_CONTEXT_MAX_CHARS;
|
|
64
|
+
export const setContextMaxCharsRef = (value: number) => {
|
|
65
|
+
contextMaxCharsRef = value;
|
|
66
|
+
};
|
|
67
|
+
export const setAdvisorPlanGateRef = (enabled: boolean) => {
|
|
68
|
+
advisorPlanGateRef = enabled;
|
|
69
|
+
};
|
|
70
|
+
export const setAdvisorFailureGateRef = (enabled: boolean) => {
|
|
71
|
+
advisorFailureGateRef = enabled;
|
|
72
|
+
};
|
|
73
|
+
export const setAdvisorCompletionGateRef = (enabled: boolean) => {
|
|
74
|
+
advisorCompletionGateRef = enabled;
|
|
75
|
+
};
|
|
76
|
+
export const setAdvisorCustomInvocationRef = (rule: string | undefined) => {
|
|
77
|
+
advisorCustomInvocationRef = rule?.trim() || undefined;
|
|
78
|
+
};
|
|
79
|
+
export const setAdvisorCollapseResponsesRef = (enabled: boolean) => {
|
|
80
|
+
advisorCollapseResponsesRef = enabled;
|
|
81
|
+
};
|
|
82
|
+
export const setAdvisorBlockOnBlockedRef = (enabled: boolean) => {
|
|
83
|
+
advisorBlockOnBlockedRef = enabled;
|
|
84
|
+
};
|
|
85
|
+
export const setAdvisorAutoLoopGateRef = (enabled: boolean) => {
|
|
86
|
+
advisorAutoLoopGateRef = enabled;
|
|
87
|
+
};
|
|
88
|
+
export const isValidLoopThreshold = (value: unknown): value is number =>
|
|
89
|
+
typeof value === "number" && Number.isSafeInteger(value) && value >= 2;
|
|
90
|
+
export const setAdvisorLoopThresholdRef = (value: number) => {
|
|
91
|
+
advisorLoopThresholdRef = value;
|
|
92
|
+
};
|
|
93
|
+
export const isValidMaxCallsPerSession = (value: unknown): value is number =>
|
|
94
|
+
typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
95
|
+
export const setAdvisorMaxCallsPerSessionRef = (value: number | undefined) => {
|
|
96
|
+
advisorMaxCallsPerSessionRef = value;
|
|
97
|
+
};
|
|
98
|
+
export const setAdvisorSessionSummaryRef = (enabled: boolean) => {
|
|
99
|
+
advisorSessionSummaryRef = enabled;
|
|
100
|
+
};
|
|
101
|
+
export const isValidGateFailureMode = (
|
|
102
|
+
value: unknown
|
|
103
|
+
): value is GateFailureMode =>
|
|
104
|
+
typeof value === "string" &&
|
|
105
|
+
GATE_FAILURE_MODES.includes(value as GateFailureMode);
|
|
106
|
+
export const setAdvisorFailureModeRef = (value: GateFailureMode) => {
|
|
107
|
+
advisorFailureModeRef = value;
|
|
108
|
+
};
|
|
109
|
+
export const setAdvisorHerdrIntegrationRef = (enabled: boolean) => {
|
|
110
|
+
advisorHerdrIntegrationRef = enabled;
|
|
111
|
+
};
|
|
112
|
+
export const isValidToolResultMaxLines = (value: unknown): value is number =>
|
|
113
|
+
typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
114
|
+
export const isValidToolResultMaxBytes = (value: unknown): value is number =>
|
|
115
|
+
typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
116
|
+
export const setAdvisorToolResultMaxLinesRef = (value: number) => {
|
|
117
|
+
advisorToolResultMaxLinesRef = value;
|
|
118
|
+
};
|
|
119
|
+
export const setAdvisorToolResultMaxBytesRef = (value: number) => {
|
|
120
|
+
advisorToolResultMaxBytesRef = value;
|
|
121
|
+
};
|
|
46
122
|
|
|
47
123
|
export const splitRef = (ref: string): [string, string] => {
|
|
48
124
|
const i = ref.indexOf("/");
|
|
@@ -50,49 +126,160 @@ export const splitRef = (ref: string): [string, string] => {
|
|
|
50
126
|
};
|
|
51
127
|
|
|
52
128
|
export const configPaths = (ctx: ExtensionContext) => [
|
|
53
|
-
ctx.isProjectTrusted()
|
|
129
|
+
ctx.isProjectTrusted()
|
|
130
|
+
? join(ctx.cwd, CONFIG_DIR_NAME, "advisor.json")
|
|
131
|
+
: null,
|
|
54
132
|
join(getAgentDir(), "advisor.json"),
|
|
55
133
|
];
|
|
56
134
|
|
|
57
|
-
|
|
58
|
-
executor?: string;
|
|
135
|
+
export interface AdvisorConfig {
|
|
59
136
|
advisor?: string;
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
advisorPlanGate?: boolean;
|
|
64
|
-
advisorFailureGate?: boolean;
|
|
137
|
+
advisorAutoLoopGate?: boolean;
|
|
138
|
+
advisorBlockOnBlocked?: boolean;
|
|
139
|
+
advisorCollapseResponses?: boolean;
|
|
65
140
|
advisorCompletionGate?: boolean;
|
|
66
141
|
advisorCustomInvocation?: string;
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
142
|
+
advisorEffort?: string;
|
|
143
|
+
advisorFailureGate?: boolean;
|
|
144
|
+
advisorHerdrIntegration?: boolean;
|
|
70
145
|
advisorLoopThreshold?: number;
|
|
71
146
|
advisorMaxCallsPerSession?: number;
|
|
147
|
+
advisorPlanGate?: boolean;
|
|
72
148
|
advisorSessionSummary?: boolean;
|
|
73
|
-
|
|
149
|
+
advisorToolResultMaxBytes?: number;
|
|
150
|
+
advisorToolResultMaxLines?: number;
|
|
151
|
+
contextMaxChars?: number;
|
|
152
|
+
executor?: string;
|
|
153
|
+
executorEffort?: string;
|
|
154
|
+
gateFailureMode?: GateFailureMode;
|
|
155
|
+
}
|
|
74
156
|
|
|
75
|
-
const
|
|
76
|
-
|
|
157
|
+
const CONFIG_KEYS = new Set(
|
|
158
|
+
Object.keys({
|
|
159
|
+
advisor: true,
|
|
160
|
+
advisorAutoLoopGate: true,
|
|
161
|
+
advisorBlockOnBlocked: true,
|
|
162
|
+
advisorCollapseResponses: true,
|
|
163
|
+
advisorCompletionGate: true,
|
|
164
|
+
advisorCustomInvocation: true,
|
|
165
|
+
advisorEffort: true,
|
|
166
|
+
advisorFailureGate: true,
|
|
167
|
+
advisorHerdrIntegration: true,
|
|
168
|
+
advisorLoopThreshold: true,
|
|
169
|
+
advisorMaxCallsPerSession: true,
|
|
170
|
+
advisorPlanGate: true,
|
|
171
|
+
advisorSessionSummary: true,
|
|
172
|
+
advisorToolResultMaxBytes: true,
|
|
173
|
+
advisorToolResultMaxLines: true,
|
|
174
|
+
contextMaxChars: true,
|
|
175
|
+
executor: true,
|
|
176
|
+
executorEffort: true,
|
|
177
|
+
gateFailureMode: true,
|
|
178
|
+
})
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
export const validateConfig = (
|
|
182
|
+
value: unknown,
|
|
183
|
+
path = "advisor.json"
|
|
184
|
+
): value is AdvisorConfig => {
|
|
185
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
186
|
+
throw new TypeError(
|
|
187
|
+
`Invalid advisor configuration at ${path}: expected a JSON object.`
|
|
188
|
+
);
|
|
189
|
+
}
|
|
77
190
|
const config = value as Record<string, unknown>;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
191
|
+
const unknown = Object.keys(config).filter((key) => !CONFIG_KEYS.has(key));
|
|
192
|
+
if (unknown.length) {
|
|
193
|
+
throw new TypeError(
|
|
194
|
+
`Invalid advisor configuration at ${path}: unknown key(s) ${unknown.map((key) => JSON.stringify(key)).join(", ")}. Remove them or upgrade pi-advisor.`
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
const invalid = (key: string, accepted: string) => {
|
|
198
|
+
throw new TypeError(
|
|
199
|
+
`Invalid advisor configuration at ${path}, key ${JSON.stringify(key)}: expected ${accepted}.`
|
|
200
|
+
);
|
|
201
|
+
};
|
|
202
|
+
if (config.executor !== undefined && typeof config.executor !== "string") {
|
|
203
|
+
invalid("executor", "a provider/model string");
|
|
204
|
+
}
|
|
205
|
+
if (config.advisor !== undefined && typeof config.advisor !== "string") {
|
|
206
|
+
invalid("advisor", "a provider/model string");
|
|
207
|
+
}
|
|
208
|
+
if (
|
|
209
|
+
config.executorEffort !== undefined &&
|
|
210
|
+
typeof config.executorEffort !== "string"
|
|
211
|
+
) {
|
|
212
|
+
invalid("executorEffort", "a string");
|
|
213
|
+
}
|
|
214
|
+
if (
|
|
215
|
+
config.advisorEffort !== undefined &&
|
|
216
|
+
typeof config.advisorEffort !== "string"
|
|
217
|
+
) {
|
|
218
|
+
invalid("advisorEffort", "a string");
|
|
219
|
+
}
|
|
220
|
+
if (
|
|
221
|
+
config.contextMaxChars !== undefined &&
|
|
222
|
+
!isValidContextMaxChars(config.contextMaxChars)
|
|
223
|
+
) {
|
|
224
|
+
invalid(
|
|
225
|
+
"contextMaxChars",
|
|
226
|
+
`a safe integer from 0 through ${MAX_CONTEXT_MAX_CHARS}`
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
for (const key of [
|
|
230
|
+
"advisorPlanGate",
|
|
231
|
+
"advisorFailureGate",
|
|
232
|
+
"advisorCompletionGate",
|
|
233
|
+
"advisorCollapseResponses",
|
|
234
|
+
"advisorBlockOnBlocked",
|
|
235
|
+
"advisorAutoLoopGate",
|
|
236
|
+
"advisorSessionSummary",
|
|
237
|
+
"advisorHerdrIntegration",
|
|
238
|
+
]) {
|
|
239
|
+
if (config[key] !== undefined && typeof config[key] !== "boolean") {
|
|
240
|
+
invalid(key, "true or false");
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (
|
|
244
|
+
config.advisorCustomInvocation !== undefined &&
|
|
245
|
+
typeof config.advisorCustomInvocation !== "string"
|
|
246
|
+
) {
|
|
247
|
+
invalid("advisorCustomInvocation", "a string");
|
|
248
|
+
}
|
|
249
|
+
if (
|
|
250
|
+
config.advisorLoopThreshold !== undefined &&
|
|
251
|
+
!isValidLoopThreshold(config.advisorLoopThreshold)
|
|
252
|
+
) {
|
|
253
|
+
invalid("advisorLoopThreshold", "a safe integer of at least 2");
|
|
254
|
+
}
|
|
255
|
+
if (
|
|
256
|
+
config.advisorMaxCallsPerSession !== undefined &&
|
|
257
|
+
!isValidMaxCallsPerSession(config.advisorMaxCallsPerSession)
|
|
258
|
+
) {
|
|
259
|
+
invalid("advisorMaxCallsPerSession", "a non-negative safe integer");
|
|
260
|
+
}
|
|
261
|
+
if (
|
|
262
|
+
config.gateFailureMode !== undefined &&
|
|
263
|
+
!isValidGateFailureMode(config.gateFailureMode)
|
|
264
|
+
) {
|
|
265
|
+
invalid("gateFailureMode", GATE_FAILURE_MODES.join(", "));
|
|
266
|
+
}
|
|
267
|
+
if (
|
|
268
|
+
config.advisorToolResultMaxLines !== undefined &&
|
|
269
|
+
!isValidToolResultMaxLines(config.advisorToolResultMaxLines)
|
|
270
|
+
) {
|
|
271
|
+
invalid("advisorToolResultMaxLines", "a non-negative safe integer");
|
|
272
|
+
}
|
|
273
|
+
if (
|
|
274
|
+
config.advisorToolResultMaxBytes !== undefined &&
|
|
275
|
+
!isValidToolResultMaxBytes(config.advisorToolResultMaxBytes)
|
|
276
|
+
) {
|
|
277
|
+
invalid("advisorToolResultMaxBytes", "a non-negative safe integer");
|
|
278
|
+
}
|
|
279
|
+
return true;
|
|
93
280
|
};
|
|
94
281
|
|
|
95
|
-
|
|
282
|
+
const resetDefaults = () => {
|
|
96
283
|
executorRef = FALLBACK_EXECUTOR;
|
|
97
284
|
advisorRef = FALLBACK_ADVISOR;
|
|
98
285
|
executorEffortRef = undefined;
|
|
@@ -108,62 +295,125 @@ export const loadConfig = (ctx: ExtensionContext) => {
|
|
|
108
295
|
advisorLoopThresholdRef = 3;
|
|
109
296
|
advisorMaxCallsPerSessionRef = undefined;
|
|
110
297
|
advisorSessionSummaryRef = true;
|
|
298
|
+
advisorFailureModeRef = "block-session";
|
|
299
|
+
advisorHerdrIntegrationRef = true;
|
|
300
|
+
advisorToolResultMaxLinesRef = DEFAULT_ADVISOR_TOOL_RESULT_MAX_LINES;
|
|
301
|
+
advisorToolResultMaxBytesRef = DEFAULT_ADVISOR_TOOL_RESULT_MAX_BYTES;
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
export const loadConfig = (ctx: ExtensionContext) => {
|
|
305
|
+
resetDefaults();
|
|
111
306
|
for (const path of configPaths(ctx)) {
|
|
112
|
-
if (!path
|
|
307
|
+
if (!(path && existsSync(path))) {
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
let config: AdvisorConfig;
|
|
113
311
|
try {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
312
|
+
config = JSON.parse(readFileSync(path, "utf8")) as AdvisorConfig;
|
|
313
|
+
validateConfig(config, path);
|
|
314
|
+
} catch (error) {
|
|
315
|
+
throw error instanceof Error ? error : new Error(String(error));
|
|
316
|
+
}
|
|
317
|
+
if (config.executor) {
|
|
318
|
+
executorRef = config.executor;
|
|
319
|
+
}
|
|
320
|
+
if (config.advisor) {
|
|
321
|
+
advisorRef = config.advisor;
|
|
322
|
+
}
|
|
323
|
+
if (config.executorEffort) {
|
|
324
|
+
executorEffortRef = config.executorEffort;
|
|
325
|
+
}
|
|
326
|
+
if (config.advisorEffort) {
|
|
327
|
+
advisorEffortRef = config.advisorEffort;
|
|
328
|
+
}
|
|
329
|
+
if (config.contextMaxChars !== undefined) {
|
|
330
|
+
contextMaxCharsRef = config.contextMaxChars;
|
|
331
|
+
}
|
|
332
|
+
if (config.advisorPlanGate !== undefined) {
|
|
333
|
+
advisorPlanGateRef = config.advisorPlanGate;
|
|
334
|
+
}
|
|
335
|
+
if (config.advisorFailureGate !== undefined) {
|
|
336
|
+
advisorFailureGateRef = config.advisorFailureGate;
|
|
337
|
+
}
|
|
338
|
+
if (config.advisorCompletionGate !== undefined) {
|
|
339
|
+
advisorCompletionGateRef = config.advisorCompletionGate;
|
|
340
|
+
}
|
|
341
|
+
if (config.advisorCustomInvocation !== undefined) {
|
|
342
|
+
advisorCustomInvocationRef = config.advisorCustomInvocation || undefined;
|
|
343
|
+
}
|
|
344
|
+
if (config.advisorCollapseResponses !== undefined) {
|
|
345
|
+
advisorCollapseResponsesRef = config.advisorCollapseResponses;
|
|
346
|
+
}
|
|
347
|
+
if (config.advisorBlockOnBlocked !== undefined) {
|
|
348
|
+
advisorBlockOnBlockedRef = config.advisorBlockOnBlocked;
|
|
349
|
+
}
|
|
350
|
+
if (config.advisorAutoLoopGate !== undefined) {
|
|
351
|
+
advisorAutoLoopGateRef = config.advisorAutoLoopGate;
|
|
352
|
+
}
|
|
353
|
+
if (config.advisorLoopThreshold !== undefined) {
|
|
354
|
+
advisorLoopThresholdRef = config.advisorLoopThreshold;
|
|
355
|
+
}
|
|
356
|
+
if (config.advisorMaxCallsPerSession !== undefined) {
|
|
357
|
+
advisorMaxCallsPerSessionRef = config.advisorMaxCallsPerSession;
|
|
358
|
+
}
|
|
359
|
+
if (config.advisorSessionSummary !== undefined) {
|
|
360
|
+
advisorSessionSummaryRef = config.advisorSessionSummary;
|
|
361
|
+
}
|
|
362
|
+
if (config.gateFailureMode !== undefined) {
|
|
363
|
+
advisorFailureModeRef = config.gateFailureMode;
|
|
364
|
+
}
|
|
365
|
+
if (config.advisorHerdrIntegration !== undefined) {
|
|
366
|
+
advisorHerdrIntegrationRef = config.advisorHerdrIntegration;
|
|
134
367
|
}
|
|
368
|
+
if (config.advisorToolResultMaxLines !== undefined) {
|
|
369
|
+
advisorToolResultMaxLinesRef = config.advisorToolResultMaxLines;
|
|
370
|
+
}
|
|
371
|
+
if (config.advisorToolResultMaxBytes !== undefined) {
|
|
372
|
+
advisorToolResultMaxBytesRef = config.advisorToolResultMaxBytes;
|
|
373
|
+
}
|
|
374
|
+
return path;
|
|
135
375
|
}
|
|
136
376
|
return null;
|
|
137
377
|
};
|
|
138
378
|
|
|
139
379
|
export const saveConfig = (ctx: ExtensionContext) => {
|
|
140
380
|
const project = join(ctx.cwd, CONFIG_DIR_NAME, "advisor.json");
|
|
141
|
-
const path =
|
|
142
|
-
|
|
381
|
+
const path =
|
|
382
|
+
ctx.isProjectTrusted() && existsSync(project)
|
|
383
|
+
? project
|
|
384
|
+
: join(getAgentDir(), "advisor.json");
|
|
143
385
|
let existing: Record<string, unknown> = {};
|
|
144
386
|
try {
|
|
145
387
|
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
146
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed))
|
|
388
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
389
|
+
existing = parsed as Record<string, unknown>;
|
|
390
|
+
}
|
|
147
391
|
} catch {
|
|
148
|
-
|
|
392
|
+
/* replace a missing or malformed file */
|
|
149
393
|
}
|
|
150
394
|
const data = {
|
|
151
395
|
...existing,
|
|
152
|
-
executor: executorRef,
|
|
153
396
|
advisor: advisorRef,
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
advisorPlanGate: advisorPlanGateRef,
|
|
158
|
-
advisorFailureGate: advisorFailureGateRef,
|
|
397
|
+
advisorAutoLoopGate: advisorAutoLoopGateRef,
|
|
398
|
+
advisorBlockOnBlocked: advisorBlockOnBlockedRef,
|
|
399
|
+
advisorCollapseResponses: advisorCollapseResponsesRef,
|
|
159
400
|
advisorCompletionGate: advisorCompletionGateRef,
|
|
160
401
|
advisorCustomInvocation: advisorCustomInvocationRef,
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
advisorAutoLoopGate: advisorAutoLoopGateRef,
|
|
402
|
+
advisorEffort: advisorEffortRef,
|
|
403
|
+
advisorFailureGate: advisorFailureGateRef,
|
|
164
404
|
advisorLoopThreshold: advisorLoopThresholdRef,
|
|
165
|
-
|
|
405
|
+
advisorPlanGate: advisorPlanGateRef,
|
|
406
|
+
contextMaxChars: contextMaxCharsRef,
|
|
407
|
+
executor: executorRef,
|
|
408
|
+
executorEffort: executorEffortRef,
|
|
409
|
+
...(advisorMaxCallsPerSessionRef === undefined
|
|
410
|
+
? {}
|
|
411
|
+
: { advisorMaxCallsPerSession: advisorMaxCallsPerSessionRef }),
|
|
412
|
+
advisorHerdrIntegration: advisorHerdrIntegrationRef,
|
|
166
413
|
advisorSessionSummary: advisorSessionSummaryRef,
|
|
414
|
+
advisorToolResultMaxBytes: advisorToolResultMaxBytesRef,
|
|
415
|
+
advisorToolResultMaxLines: advisorToolResultMaxLinesRef,
|
|
416
|
+
gateFailureMode: advisorFailureModeRef,
|
|
167
417
|
};
|
|
168
418
|
writeFileSync(path, `${JSON.stringify(data, null, 2)}\n`);
|
|
169
419
|
return path;
|
|
@@ -173,11 +423,14 @@ export const parseArgs = (args: string): string | undefined => {
|
|
|
173
423
|
let nextExecutor = executorRef;
|
|
174
424
|
let nextAdvisor = advisorRef;
|
|
175
425
|
let nextContextMaxChars = contextMaxCharsRef;
|
|
176
|
-
|
|
177
426
|
for (const token of args.trim().split(/\s+/).filter(Boolean)) {
|
|
178
427
|
const [key, value] = token.split("=");
|
|
179
|
-
if (key === "executor" && value)
|
|
180
|
-
|
|
428
|
+
if (key === "executor" && value) {
|
|
429
|
+
nextExecutor = value;
|
|
430
|
+
}
|
|
431
|
+
if (key === "advisor" && value) {
|
|
432
|
+
nextAdvisor = value;
|
|
433
|
+
}
|
|
181
434
|
if (key === "contextMaxChars") {
|
|
182
435
|
const parsed = Number(value);
|
|
183
436
|
if (!isValidContextMaxChars(parsed)) {
|
|
@@ -186,9 +439,7 @@ export const parseArgs = (args: string): string | undefined => {
|
|
|
186
439
|
nextContextMaxChars = parsed;
|
|
187
440
|
}
|
|
188
441
|
}
|
|
189
|
-
|
|
190
442
|
executorRef = nextExecutor;
|
|
191
443
|
advisorRef = nextAdvisor;
|
|
192
444
|
contextMaxCharsRef = nextContextMaxChars;
|
|
193
|
-
return undefined;
|
|
194
445
|
};
|