pi-advisor-flow 0.8.1-dev.2 → 0.8.2-dev.1
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 +16 -0
- package/dist/index.js +70 -17
- package/package.json +1 -1
- package/src/child-session.ts +15 -0
- package/src/commands/activation.ts +10 -3
- package/src/commands/lifecycle.ts +6 -1
- package/src/commands/settings-persistence.ts +5 -0
- package/src/config/defaults.ts +8 -0
- package/src/config/schema.ts +15 -0
- package/src/config/state.ts +6 -0
- package/src/config/types.ts +3 -0
- package/src/scout.ts +18 -10
- package/src/tools/scout-status.ts +11 -6
- package/src/ui/settings-items.ts +17 -0
- package/src/ui/settings-mutations.ts +4 -0
- package/src/ui/types.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,22 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
|
|
|
8
8
|
|
|
9
9
|
### Added
|
|
10
10
|
|
|
11
|
+
- Added a configurable Advisor Scout response-stream timeout in `/advisor-settings` and `advisor.json`, defaulting to 30 seconds. Model and auth resolution remain outside the timeout window.
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- Scout timeout fallbacks now report that the original conversation was retained instead of showing a misleading zero-kept/all-omitted selection count.
|
|
16
|
+
|
|
17
|
+
## 0.8.1 - 2026-09-23
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- Preserve a native subagent's host-selected model and thinking level when `alwaysOn` or explicit `/advisor` activation runs in a process marked with `PI_SUBAGENT_CHILD=1`.
|
|
22
|
+
- Keep marked child model selections out of the persisted parent Executor configuration.
|
|
23
|
+
- Run Advisor Scout with the marked child's active model and thinking level instead of replacing them with the configured parent Executor.
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
11
27
|
- Published validated npm development previews for package changes on `main` under the `dev` dist-tag; stable installs continue to use `latest`.
|
|
12
28
|
|
|
13
29
|
## 0.8.0 - 2026-09-22
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,8 @@ var DEFAULT_ADVISOR_TOOL_RESULT_MAX_BYTES = PI_DEFAULT_MAX_BYTES;
|
|
|
14
14
|
var DEFAULT_ADVISOR_GIT_CONTEXT_MAX_CHARS = 20000;
|
|
15
15
|
var DEFAULT_JEV_MODEL = "jev-latest";
|
|
16
16
|
var DEFAULT_JEV_TIMEOUT_MS = 8000;
|
|
17
|
+
var DEFAULT_SCOUT_TIMEOUT_MS = 30000;
|
|
18
|
+
var MAX_SCOUT_TIMEOUT_MS = 2147483647;
|
|
17
19
|
var DEFAULT_JEV_DIGEST_MAX_CHARS = 4000;
|
|
18
20
|
var DEFAULT_JEV_PRICE_PER_MTOK = 0.042;
|
|
19
21
|
var DEFAULT_JEV_FILTER_SKIP_CONFIDENCE = 0.85;
|
|
@@ -82,6 +84,7 @@ var advisorOutcomeLoggingRef = false;
|
|
|
82
84
|
var advisorUntrackedContentRef = false;
|
|
83
85
|
var advisorTrackedFileContentRef = false;
|
|
84
86
|
var advisorScoutEnabledRef = false;
|
|
87
|
+
var advisorScoutTimeoutMsRef = DEFAULT_SCOUT_TIMEOUT_MS;
|
|
85
88
|
var showUsageDetailsRef = true;
|
|
86
89
|
var showUsageFooterRef = false;
|
|
87
90
|
var setExecutorRef = (ref) => {
|
|
@@ -218,6 +221,9 @@ var setAdvisorTrackedFileContentRef = (enabled) => {
|
|
|
218
221
|
var setAdvisorScoutEnabledRef = (enabled) => {
|
|
219
222
|
advisorScoutEnabledRef = enabled;
|
|
220
223
|
};
|
|
224
|
+
var setAdvisorScoutTimeoutMsRef = (value) => {
|
|
225
|
+
advisorScoutTimeoutMsRef = value;
|
|
226
|
+
};
|
|
221
227
|
var setShowUsageDetailsRef = (enabled) => {
|
|
222
228
|
showUsageDetailsRef = enabled;
|
|
223
229
|
};
|
|
@@ -256,6 +262,7 @@ var getAdvisorSettings = () => ({
|
|
|
256
262
|
planGate: advisorPlanGateRef,
|
|
257
263
|
redactSecrets: advisorRedactSecretsRef,
|
|
258
264
|
scoutEnabled: advisorScoutEnabledRef,
|
|
265
|
+
scoutTimeoutMs: advisorScoutTimeoutMsRef,
|
|
259
266
|
sessionSummary: advisorSessionSummaryRef,
|
|
260
267
|
showUsageDetails: showUsageDetailsRef,
|
|
261
268
|
showUsageFooter: showUsageFooterRef,
|
|
@@ -272,6 +279,16 @@ var splitRef = (ref) => {
|
|
|
272
279
|
return i === -1 ? ["openai-codex", ref] : [ref.slice(0, i), ref.slice(i + 1)];
|
|
273
280
|
};
|
|
274
281
|
|
|
282
|
+
// src/child-session.ts
|
|
283
|
+
var isMarkedSubagent = () => process.env.PI_SUBAGENT_CHILD === "1";
|
|
284
|
+
var effectiveExecutorRef = (ctx) => {
|
|
285
|
+
if (isMarkedSubagent() && ctx.model) {
|
|
286
|
+
return `${ctx.model.provider}/${ctx.model.id}`;
|
|
287
|
+
}
|
|
288
|
+
return executorRef;
|
|
289
|
+
};
|
|
290
|
+
var effectiveExecutorEffort = (ctx) => isMarkedSubagent() ? ctx.thinkingLevel : executorEffortRef;
|
|
291
|
+
|
|
275
292
|
// src/content-utils.ts
|
|
276
293
|
var isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
277
294
|
var isRecordOf = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
@@ -426,6 +443,7 @@ var isValidGateFailureMode = (value) => isString(value) && GATE_FAILURE_MODE_NAM
|
|
|
426
443
|
var isValidToolResultMaxLines = (value) => nonNegativeSafeInteger(value);
|
|
427
444
|
var isValidToolResultMaxBytes = (value) => nonNegativeSafeInteger(value);
|
|
428
445
|
var isValidJevTimeoutMs = (value) => typeof value === "number" && Number.isSafeInteger(value) && value >= 1;
|
|
446
|
+
var isValidScoutTimeoutMs = (value) => typeof value === "number" && Number.isSafeInteger(value) && value >= 1 && value <= MAX_SCOUT_TIMEOUT_MS;
|
|
429
447
|
var isValidJevDigestMaxChars = (value) => nonNegativeSafeInteger(value);
|
|
430
448
|
var isValidJevPricePerMtok = (value) => typeof value === "number" && Number.isFinite(value) && value > 0;
|
|
431
449
|
var isValidJevSkipConfidence = (value) => typeof value === "number" && Number.isFinite(value) && value >= 0.5 && value <= 1;
|
|
@@ -621,6 +639,13 @@ var CONFIG_SCHEMA = {
|
|
|
621
639
|
persisted: true,
|
|
622
640
|
type: "boolean"
|
|
623
641
|
},
|
|
642
|
+
advisorScoutTimeoutMs: {
|
|
643
|
+
accepted: `a positive safe integer no greater than ${MAX_SCOUT_TIMEOUT_MS} milliseconds`,
|
|
644
|
+
current: () => advisorScoutTimeoutMsRef,
|
|
645
|
+
persisted: true,
|
|
646
|
+
type: "number",
|
|
647
|
+
validate: isValidScoutTimeoutMs
|
|
648
|
+
},
|
|
624
649
|
advisorSessionSummary: {
|
|
625
650
|
accepted: "true or false",
|
|
626
651
|
current: () => advisorSessionSummaryRef,
|
|
@@ -859,6 +884,7 @@ var resetDefaults = () => {
|
|
|
859
884
|
setAdvisorUntrackedContentRef(false);
|
|
860
885
|
setAdvisorTrackedFileContentRef(false);
|
|
861
886
|
setAdvisorScoutEnabledRef(false);
|
|
887
|
+
setAdvisorScoutTimeoutMsRef(DEFAULT_SCOUT_TIMEOUT_MS);
|
|
862
888
|
setShowUsageDetailsRef(true);
|
|
863
889
|
setShowUsageFooterRef(false);
|
|
864
890
|
};
|
|
@@ -891,6 +917,7 @@ var applyConfig = (config) => {
|
|
|
891
917
|
applyOptionalConfig(config, "advisorModelWhitelist", setAdvisorModelWhitelistRef);
|
|
892
918
|
applyOptionalConfig(config, "advisorSessionSummary", setAdvisorSessionSummaryRef);
|
|
893
919
|
applyOptionalConfig(config, "advisorScoutEnabled", setAdvisorScoutEnabledRef);
|
|
920
|
+
applyOptionalConfig(config, "advisorScoutTimeoutMs", setAdvisorScoutTimeoutMsRef);
|
|
894
921
|
applyOptionalConfig(config, "showUsageDetails", setShowUsageDetailsRef);
|
|
895
922
|
applyOptionalConfig(config, "showUsageFooter", setShowUsageFooterRef);
|
|
896
923
|
applyOptionalConfig(config, "simpleMode", setSimpleModeRef);
|
|
@@ -2691,7 +2718,6 @@ var formatAdvisorUsageStatus = (totals) => {
|
|
|
2691
2718
|
};
|
|
2692
2719
|
|
|
2693
2720
|
// src/scout.ts
|
|
2694
|
-
var SCOUT_TIMEOUT_MS = 30000;
|
|
2695
2721
|
var SCOUT_SYSTEM = [
|
|
2696
2722
|
"You are Scout, a context curator serving a separate engineering Advisor.",
|
|
2697
2723
|
"Select only conversation groups materially relevant to the current request, unresolved decisions, attempted work, diagnostics, and validation.",
|
|
@@ -2814,17 +2840,17 @@ var setupAbortWatch = (parentSignal, timeoutMs) => {
|
|
|
2814
2840
|
wasTimedOut: () => timedOut
|
|
2815
2841
|
};
|
|
2816
2842
|
};
|
|
2817
|
-
var streamScoutResponse = async (dependencies, resolved, manifest, parentSignal, timeoutMs, publish) => {
|
|
2843
|
+
var streamScoutResponse = async (dependencies, resolved, executorModel, executorEffort, manifest, parentSignal, timeoutMs, publish) => {
|
|
2818
2844
|
const { abortPromise, controller, teardown, wasTimedOut } = setupAbortWatch(parentSignal, timeoutMs);
|
|
2819
2845
|
try {
|
|
2820
2846
|
const collection = dependencies.collect(resolved, {
|
|
2821
2847
|
messages: [manifestMessage(manifest)],
|
|
2822
2848
|
onChunk: (thinking, text) => {
|
|
2823
2849
|
if (!controller.signal.aborted) {
|
|
2824
|
-
publish({ model:
|
|
2850
|
+
publish({ model: executorModel, text, thinking, type: "chunk" });
|
|
2825
2851
|
}
|
|
2826
2852
|
},
|
|
2827
|
-
reasoning:
|
|
2853
|
+
reasoning: executorEffort,
|
|
2828
2854
|
signal: controller.signal,
|
|
2829
2855
|
systemPrompt: SCOUT_SYSTEM
|
|
2830
2856
|
});
|
|
@@ -2843,7 +2869,7 @@ var streamScoutResponse = async (dependencies, resolved, manifest, parentSignal,
|
|
|
2843
2869
|
teardown();
|
|
2844
2870
|
}
|
|
2845
2871
|
};
|
|
2846
|
-
var runAdvisorScout = async (ctx, manifest, parentSignal, onEvent, timeoutMs =
|
|
2872
|
+
var runAdvisorScout = async (ctx, manifest, parentSignal, onEvent, timeoutMs = advisorScoutTimeoutMsRef, dependencies = defaultDependencies) => {
|
|
2847
2873
|
const startedAt = Date.now();
|
|
2848
2874
|
const publish = (event) => {
|
|
2849
2875
|
onEvent?.(event);
|
|
@@ -2857,7 +2883,7 @@ var runAdvisorScout = async (ctx, manifest, parentSignal, onEvent, timeoutMs = S
|
|
|
2857
2883
|
category,
|
|
2858
2884
|
message,
|
|
2859
2885
|
metrics: usage === undefined ? baseMetrics(manifest, startedAt) : { ...baseMetrics(manifest, startedAt), usage },
|
|
2860
|
-
model:
|
|
2886
|
+
model: effectiveExecutorRef(ctx),
|
|
2861
2887
|
ok: false
|
|
2862
2888
|
};
|
|
2863
2889
|
publish({ outcome, type: "fallback" });
|
|
@@ -2866,9 +2892,11 @@ var runAdvisorScout = async (ctx, manifest, parentSignal, onEvent, timeoutMs = S
|
|
|
2866
2892
|
if (parentSignal?.aborted) {
|
|
2867
2893
|
return cancelled();
|
|
2868
2894
|
}
|
|
2895
|
+
const executorModel = effectiveExecutorRef(ctx);
|
|
2896
|
+
const executorEffort = effectiveExecutorEffort(ctx);
|
|
2869
2897
|
let resolved;
|
|
2870
2898
|
try {
|
|
2871
|
-
resolved = await dependencies.resolve(ctx,
|
|
2899
|
+
resolved = await dependencies.resolve(ctx, executorModel, "Scout");
|
|
2872
2900
|
} catch (error) {
|
|
2873
2901
|
if (parentSignal?.aborted) {
|
|
2874
2902
|
return cancelled();
|
|
@@ -2879,8 +2907,8 @@ var runAdvisorScout = async (ctx, manifest, parentSignal, onEvent, timeoutMs = S
|
|
|
2879
2907
|
if (parentSignal?.aborted) {
|
|
2880
2908
|
return cancelled();
|
|
2881
2909
|
}
|
|
2882
|
-
publish({ model:
|
|
2883
|
-
const streamed = await streamScoutResponse(dependencies, resolved, manifest, parentSignal, timeoutMs, publish);
|
|
2910
|
+
publish({ model: executorModel, type: "call" });
|
|
2911
|
+
const streamed = await streamScoutResponse(dependencies, resolved, executorModel, executorEffort, manifest, parentSignal, timeoutMs, publish);
|
|
2884
2912
|
if (!streamed.ok) {
|
|
2885
2913
|
if (parentSignal?.aborted) {
|
|
2886
2914
|
return cancelled();
|
|
@@ -2907,7 +2935,7 @@ var runAdvisorScout = async (ctx, manifest, parentSignal, onEvent, timeoutMs = S
|
|
|
2907
2935
|
]).size,
|
|
2908
2936
|
usage: snapshotAdvisorUsage(streamed.streamed.usage)
|
|
2909
2937
|
},
|
|
2910
|
-
model:
|
|
2938
|
+
model: executorModel,
|
|
2911
2939
|
ok: true,
|
|
2912
2940
|
selectedLabels: manifest.groups.filter((group) => group.required || selection.selectedIds.includes(group.id)).map((group) => group.label),
|
|
2913
2941
|
selection
|
|
@@ -3488,7 +3516,6 @@ var scoutDetailsFromEvent = (event, previous) => {
|
|
|
3488
3516
|
latencyMs: outcome.metrics.latencyMs,
|
|
3489
3517
|
model: outcome.model,
|
|
3490
3518
|
omittedBeforeScout: outcome.metrics.omittedBeforeScout,
|
|
3491
|
-
selectedCount: 0,
|
|
3492
3519
|
status: "fallback",
|
|
3493
3520
|
usage: snapshotAdvisorUsage(outcome.metrics.usage)
|
|
3494
3521
|
};
|
|
@@ -3560,7 +3587,16 @@ var scoutTitle = (scout, frame) => {
|
|
|
3560
3587
|
}
|
|
3561
3588
|
return "◆ SCOUT · FALLBACK";
|
|
3562
3589
|
};
|
|
3563
|
-
var
|
|
3590
|
+
var scoutSelectionSummary = (scout) => {
|
|
3591
|
+
if (scout.status === "fallback") {
|
|
3592
|
+
return " · original conversation retained";
|
|
3593
|
+
}
|
|
3594
|
+
if (scout.status !== "curated" || scout.selectedCount === undefined) {
|
|
3595
|
+
return "";
|
|
3596
|
+
}
|
|
3597
|
+
return ` · ${scout.selectedCount} kept / ${Math.max(0, (scout.availableCount ?? 0) - scout.selectedCount)} omitted`;
|
|
3598
|
+
};
|
|
3599
|
+
var scoutSummaryLine = (scout) => ` ${scout.model}${scoutSelectionSummary(scout)}${scout.latencyMs === undefined ? "" : ` · ${(scout.latencyMs / 1000).toFixed(1)}s`}`;
|
|
3564
3600
|
var scoutExpandedLines = (scout, expanded, theme) => {
|
|
3565
3601
|
const lines = [];
|
|
3566
3602
|
if (expanded && scout.selectedLabels?.length) {
|
|
@@ -4173,7 +4209,7 @@ var resolveActivationModels = async (runtime, ctx) => {
|
|
|
4173
4209
|
if (!(advisorAuth.ok && advisorAuth.apiKey)) {
|
|
4174
4210
|
return { error: `No API key for Advisor ${advisorRef}` };
|
|
4175
4211
|
}
|
|
4176
|
-
if (!await runtime.setExecutorModel(executor)) {
|
|
4212
|
+
if (!isMarkedSubagent() && !await runtime.setExecutorModel(executor)) {
|
|
4177
4213
|
return { error: `No API key for Executor ${executorRef}` };
|
|
4178
4214
|
}
|
|
4179
4215
|
return {};
|
|
@@ -4219,7 +4255,7 @@ var activateAdvisor = async (runtime, args, ctx, announce = true) => {
|
|
|
4219
4255
|
saveConfig(ctx, { persistAdvisor: true, persistExecutor: true });
|
|
4220
4256
|
}
|
|
4221
4257
|
runtime.pendingExecutorModelRef = undefined;
|
|
4222
|
-
if (executorEffortRef) {
|
|
4258
|
+
if (executorEffortRef && !isMarkedSubagent()) {
|
|
4223
4259
|
runtime.pi.setThinkingLevel(executorEffortRef);
|
|
4224
4260
|
}
|
|
4225
4261
|
if (!runtime.flowEnabled()) {
|
|
@@ -4230,9 +4266,11 @@ var activateAdvisor = async (runtime, args, ctx, announce = true) => {
|
|
|
4230
4266
|
]);
|
|
4231
4267
|
}
|
|
4232
4268
|
if (announce) {
|
|
4269
|
+
const activeExecutorRef = effectiveExecutorRef(ctx);
|
|
4270
|
+
const activeExecutorEffort = effectiveExecutorEffort(ctx);
|
|
4233
4271
|
notify(ctx, `${ADVISOR_ACTIVATION_EXPLANATION}
|
|
4234
4272
|
|
|
4235
|
-
Advisor flow ready — Executor: ${
|
|
4273
|
+
Advisor flow ready — Executor: ${activeExecutorRef} (thinking: ${activeExecutorEffort || "default"}) · Advisor: ${advisorRef} (thinking: ${advisorEffortRef || "default"})`, "info");
|
|
4236
4274
|
}
|
|
4237
4275
|
};
|
|
4238
4276
|
|
|
@@ -4251,7 +4289,7 @@ var registerCommandLifecycle = (runtime, activateAdvisor) => {
|
|
|
4251
4289
|
}
|
|
4252
4290
|
});
|
|
4253
4291
|
runtime.pi.on("model_select", (event, ctx) => {
|
|
4254
|
-
if (event.source !== "set" || runtime.suppressModelSelectionSync) {
|
|
4292
|
+
if (event.source !== "set" || runtime.suppressModelSelectionSync || isMarkedSubagent()) {
|
|
4255
4293
|
return;
|
|
4256
4294
|
}
|
|
4257
4295
|
const selected = `${event.model.provider}/${event.model.id}`;
|
|
@@ -6041,6 +6079,16 @@ var toggle = (id, label, description, value, defaultValue) => ({
|
|
|
6041
6079
|
label,
|
|
6042
6080
|
values: TOGGLE_VALUES
|
|
6043
6081
|
});
|
|
6082
|
+
var scoutTimeoutItem = (settings) => {
|
|
6083
|
+
const timeoutMs = settings.scoutTimeoutMs ?? DEFAULT_SCOUT_TIMEOUT_MS;
|
|
6084
|
+
return {
|
|
6085
|
+
currentValue: String(timeoutMs),
|
|
6086
|
+
description: "Maximum time for Scout's response stream; model and auth resolution happen before this timeout starts.",
|
|
6087
|
+
id: "scoutTimeoutMs",
|
|
6088
|
+
label: "Scout timeout ms",
|
|
6089
|
+
values: numericValues(timeoutMs, [5000, 1e4, 15000, 30000, 45000, 60000, 90000, 120000])
|
|
6090
|
+
};
|
|
6091
|
+
};
|
|
6044
6092
|
var jevItems = (settings, theme, tui) => [
|
|
6045
6093
|
{
|
|
6046
6094
|
currentValue: settingValue(settings.jevFilterEnabled, false),
|
|
@@ -6198,7 +6246,7 @@ var createSettingsItems = ({
|
|
|
6198
6246
|
id: "effort",
|
|
6199
6247
|
label: "Advisor reasoning",
|
|
6200
6248
|
values: withCurrentValue(currentEffort(settings.effort), effortLevels)
|
|
6201
|
-
}, modelWhitelist, toggle("scoutEnabled", "Experimental Advisor Scout", "Enable the experimental Scout before Advisor calls.", settings.scoutEnabled, false), toggle("showUsageDetails", "Show usage and cost details", "Show token usage and cost details in Advisor responses.", settings.showUsageDetails, true), toggle("showUsageFooter", "Show usage in footer", "Show the current Advisor usage summary in the footer.", settings.showUsageFooter, false), toggle("planGate", "Plan gate", "Ask the Advisor to review implementation plans.", settings.planGate, true), toggle("failureGate", "Failure gate", "Ask the Advisor to review repeated failures.", settings.failureGate, true), toggle("completionGate", "Completion gate", "Ask the Advisor to review work before declaring success.", settings.completionGate, true), toggle("collapseResponses", "Collapse long responses", "Collapse long Advisor responses in the transcript.", settings.collapseResponses, false), {
|
|
6249
|
+
}, modelWhitelist, toggle("scoutEnabled", "Experimental Advisor Scout", "Enable the experimental Scout before Advisor calls.", settings.scoutEnabled, false), scoutTimeoutItem(settings), toggle("showUsageDetails", "Show usage and cost details", "Show token usage and cost details in Advisor responses.", settings.showUsageDetails, true), toggle("showUsageFooter", "Show usage in footer", "Show the current Advisor usage summary in the footer.", settings.showUsageFooter, false), toggle("planGate", "Plan gate", "Ask the Advisor to review implementation plans.", settings.planGate, true), toggle("failureGate", "Failure gate", "Ask the Advisor to review repeated failures.", settings.failureGate, true), toggle("completionGate", "Completion gate", "Ask the Advisor to review work before declaring success.", settings.completionGate, true), toggle("collapseResponses", "Collapse long responses", "Collapse long Advisor responses in the transcript.", settings.collapseResponses, false), {
|
|
6202
6250
|
currentValue: settings.customRule || "None",
|
|
6203
6251
|
description: "Add a rule that triggers Advisor involvement.",
|
|
6204
6252
|
id: "customRule",
|
|
@@ -6496,6 +6544,10 @@ var applyJevMutation = (settings, id, value) => {
|
|
|
6496
6544
|
settings.jevTimeoutMs = Number(value);
|
|
6497
6545
|
return true;
|
|
6498
6546
|
}
|
|
6547
|
+
case "scoutTimeoutMs": {
|
|
6548
|
+
settings.scoutTimeoutMs = Number(value);
|
|
6549
|
+
return true;
|
|
6550
|
+
}
|
|
6499
6551
|
case "jevDigestMaxChars": {
|
|
6500
6552
|
settings.jevDigestMaxChars = Number(value);
|
|
6501
6553
|
return true;
|
|
@@ -6653,6 +6705,7 @@ var applySessionSettings = (settings) => {
|
|
|
6653
6705
|
setAdvisorModelWhitelistRef(settings.modelWhitelist ?? []);
|
|
6654
6706
|
setAdvisorSessionSummaryRef(settings.sessionSummary ?? false);
|
|
6655
6707
|
setAdvisorScoutEnabledRef(settings.scoutEnabled ?? false);
|
|
6708
|
+
setAdvisorScoutTimeoutMsRef(settings.scoutTimeoutMs ?? DEFAULT_SCOUT_TIMEOUT_MS);
|
|
6656
6709
|
setShowUsageDetailsRef(settings.showUsageDetails ?? true);
|
|
6657
6710
|
setShowUsageFooterRef(settings.showUsageFooter ?? false);
|
|
6658
6711
|
setSimpleModeRef(settings.simpleMode ?? false);
|
package/package.json
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
|
|
3
|
+
import { executorEffortRef, executorRef } from "./config/state.ts";
|
|
4
|
+
|
|
5
|
+
export const isMarkedSubagent = () => process.env.PI_SUBAGENT_CHILD === "1";
|
|
6
|
+
|
|
7
|
+
export const effectiveExecutorRef = (ctx: ExtensionContext) => {
|
|
8
|
+
if (isMarkedSubagent() && ctx.model) {
|
|
9
|
+
return `${ctx.model.provider}/${ctx.model.id}`;
|
|
10
|
+
}
|
|
11
|
+
return executorRef;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const effectiveExecutorEffort = (ctx: ExtensionContext) =>
|
|
15
|
+
isMarkedSubagent() ? ctx.thinkingLevel : executorEffortRef;
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
|
|
3
|
+
import {
|
|
4
|
+
effectiveExecutorEffort,
|
|
5
|
+
effectiveExecutorRef,
|
|
6
|
+
isMarkedSubagent,
|
|
7
|
+
} from "../child-session.ts";
|
|
3
8
|
import { parseArgs } from "../config/args.ts";
|
|
4
9
|
import {
|
|
5
10
|
advisorEffortRef,
|
|
@@ -51,7 +56,7 @@ const resolveActivationModels = async (
|
|
|
51
56
|
if (!(advisorAuth.ok && advisorAuth.apiKey)) {
|
|
52
57
|
return { error: `No API key for Advisor ${advisorRef}` };
|
|
53
58
|
}
|
|
54
|
-
if (!(await runtime.setExecutorModel(executor))) {
|
|
59
|
+
if (!isMarkedSubagent() && !(await runtime.setExecutorModel(executor))) {
|
|
55
60
|
return { error: `No API key for Executor ${executorRef}` };
|
|
56
61
|
}
|
|
57
62
|
return {};
|
|
@@ -116,7 +121,7 @@ export const activateAdvisor = async (
|
|
|
116
121
|
// an older inactive selection override an explicit activation argument on a
|
|
117
122
|
// later attempt.
|
|
118
123
|
runtime.pendingExecutorModelRef = undefined;
|
|
119
|
-
if (executorEffortRef) {
|
|
124
|
+
if (executorEffortRef && !isMarkedSubagent()) {
|
|
120
125
|
// SAFETY: executorEffortRef is operator-configured and trusted to name a ThinkingLevel.
|
|
121
126
|
runtime.pi.setThinkingLevel(executorEffortRef as ThinkingLevel);
|
|
122
127
|
}
|
|
@@ -128,9 +133,11 @@ export const activateAdvisor = async (
|
|
|
128
133
|
]);
|
|
129
134
|
}
|
|
130
135
|
if (announce) {
|
|
136
|
+
const activeExecutorRef = effectiveExecutorRef(ctx);
|
|
137
|
+
const activeExecutorEffort = effectiveExecutorEffort(ctx);
|
|
131
138
|
notify(
|
|
132
139
|
ctx,
|
|
133
|
-
`${ADVISOR_ACTIVATION_EXPLANATION}\n\nAdvisor flow ready — Executor: ${
|
|
140
|
+
`${ADVISOR_ACTIVATION_EXPLANATION}\n\nAdvisor flow ready — Executor: ${activeExecutorRef} (thinking: ${activeExecutorEffort || "default"}) · Advisor: ${advisorRef} (thinking: ${advisorEffortRef || "default"})`,
|
|
134
141
|
"info"
|
|
135
142
|
);
|
|
136
143
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
|
|
3
|
+
import { isMarkedSubagent } from "../child-session.ts";
|
|
3
4
|
import {
|
|
4
5
|
alwaysOnRef,
|
|
5
6
|
executorRef,
|
|
@@ -40,7 +41,11 @@ export const registerCommandLifecycle = (
|
|
|
40
41
|
// "restore" replays a stored session model and "cycle" changes the active
|
|
41
42
|
// model without an explicit `/model` choice. Neither should redefine the
|
|
42
43
|
// configured Executor.
|
|
43
|
-
if (
|
|
44
|
+
if (
|
|
45
|
+
event.source !== "set" ||
|
|
46
|
+
runtime.suppressModelSelectionSync ||
|
|
47
|
+
isMarkedSubagent()
|
|
48
|
+
) {
|
|
44
49
|
return;
|
|
45
50
|
}
|
|
46
51
|
const selected = `${event.model.provider}/${event.model.id}`;
|
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
setAdvisorPlanGateRef,
|
|
32
32
|
setAdvisorRedactSecretsRef,
|
|
33
33
|
setAdvisorScoutEnabledRef,
|
|
34
|
+
setAdvisorScoutTimeoutMsRef,
|
|
34
35
|
setAdvisorSessionSummaryRef,
|
|
35
36
|
setAdvisorToolPoliciesRef,
|
|
36
37
|
setAdvisorToolResultMaxBytesRef,
|
|
@@ -55,6 +56,7 @@ import {
|
|
|
55
56
|
DEFAULT_JEV_TRANSPORT,
|
|
56
57
|
DEFAULT_JEV_TURN_GATE_EVERY_TURNS,
|
|
57
58
|
DEFAULT_JEV_TURN_GATE_NOUL_THRESHOLD,
|
|
59
|
+
DEFAULT_SCOUT_TIMEOUT_MS,
|
|
58
60
|
} from "../config/types.ts";
|
|
59
61
|
import type { AdvisorSettings } from "../ui/types.ts";
|
|
60
62
|
|
|
@@ -75,6 +77,9 @@ const applySessionSettings = (settings: AdvisorSettings) => {
|
|
|
75
77
|
setAdvisorModelWhitelistRef(settings.modelWhitelist ?? []);
|
|
76
78
|
setAdvisorSessionSummaryRef(settings.sessionSummary ?? false);
|
|
77
79
|
setAdvisorScoutEnabledRef(settings.scoutEnabled ?? false);
|
|
80
|
+
setAdvisorScoutTimeoutMsRef(
|
|
81
|
+
settings.scoutTimeoutMs ?? DEFAULT_SCOUT_TIMEOUT_MS
|
|
82
|
+
);
|
|
78
83
|
setShowUsageDetailsRef(settings.showUsageDetails ?? true);
|
|
79
84
|
setShowUsageFooterRef(settings.showUsageFooter ?? false);
|
|
80
85
|
setSimpleModeRef(settings.simpleMode ?? false);
|
package/src/config/defaults.ts
CHANGED
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
setAdvisorRedactSecretsRef,
|
|
30
30
|
setAdvisorRef,
|
|
31
31
|
setAdvisorScoutEnabledRef,
|
|
32
|
+
setAdvisorScoutTimeoutMsRef,
|
|
32
33
|
setAdvisorSessionSummaryRef,
|
|
33
34
|
setAdvisorToolPoliciesRef,
|
|
34
35
|
setAdvisorToolResultMaxBytesRef,
|
|
@@ -60,6 +61,7 @@ import {
|
|
|
60
61
|
DEFAULT_JEV_TRANSPORT,
|
|
61
62
|
DEFAULT_JEV_TURN_GATE_EVERY_TURNS,
|
|
62
63
|
DEFAULT_JEV_TURN_GATE_NOUL_THRESHOLD,
|
|
64
|
+
DEFAULT_SCOUT_TIMEOUT_MS,
|
|
63
65
|
} from "./types.ts";
|
|
64
66
|
|
|
65
67
|
export const resetDefaults = () => {
|
|
@@ -105,6 +107,7 @@ export const resetDefaults = () => {
|
|
|
105
107
|
setAdvisorUntrackedContentRef(false);
|
|
106
108
|
setAdvisorTrackedFileContentRef(false);
|
|
107
109
|
setAdvisorScoutEnabledRef(false);
|
|
110
|
+
setAdvisorScoutTimeoutMsRef(DEFAULT_SCOUT_TIMEOUT_MS);
|
|
108
111
|
setShowUsageDetailsRef(true);
|
|
109
112
|
setShowUsageFooterRef(false);
|
|
110
113
|
};
|
|
@@ -179,6 +182,11 @@ export const applyConfig = (config: AdvisorConfig) => {
|
|
|
179
182
|
setAdvisorSessionSummaryRef
|
|
180
183
|
);
|
|
181
184
|
applyOptionalConfig(config, "advisorScoutEnabled", setAdvisorScoutEnabledRef);
|
|
185
|
+
applyOptionalConfig(
|
|
186
|
+
config,
|
|
187
|
+
"advisorScoutTimeoutMs",
|
|
188
|
+
setAdvisorScoutTimeoutMsRef
|
|
189
|
+
);
|
|
182
190
|
applyOptionalConfig(config, "showUsageDetails", setShowUsageDetailsRef);
|
|
183
191
|
applyOptionalConfig(config, "showUsageFooter", setShowUsageFooterRef);
|
|
184
192
|
applyOptionalConfig(config, "simpleMode", setSimpleModeRef);
|
package/src/config/schema.ts
CHANGED
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
advisorRedactSecretsRef,
|
|
33
33
|
advisorRef,
|
|
34
34
|
advisorScoutEnabledRef,
|
|
35
|
+
advisorScoutTimeoutMsRef,
|
|
35
36
|
advisorSessionSummaryRef,
|
|
36
37
|
advisorToolPoliciesRef,
|
|
37
38
|
advisorToolResultMaxBytesRef,
|
|
@@ -56,6 +57,7 @@ import {
|
|
|
56
57
|
GATE_FAILURE_MODES,
|
|
57
58
|
JEV_TRANSPORTS,
|
|
58
59
|
MAX_CONTEXT_MAX_CHARS,
|
|
60
|
+
MAX_SCOUT_TIMEOUT_MS,
|
|
59
61
|
} from "./types.ts";
|
|
60
62
|
|
|
61
63
|
/** An empty ref means no model has been selected yet. */
|
|
@@ -116,6 +118,12 @@ export const isValidToolResultMaxBytes = (value: unknown): value is number =>
|
|
|
116
118
|
export const isValidJevTimeoutMs = (value: unknown): value is number =>
|
|
117
119
|
typeof value === "number" && Number.isSafeInteger(value) && value >= 1;
|
|
118
120
|
|
|
121
|
+
const isValidScoutTimeoutMs = (value: unknown): value is number =>
|
|
122
|
+
typeof value === "number" &&
|
|
123
|
+
Number.isSafeInteger(value) &&
|
|
124
|
+
value >= 1 &&
|
|
125
|
+
value <= MAX_SCOUT_TIMEOUT_MS;
|
|
126
|
+
|
|
119
127
|
export const isValidJevDigestMaxChars = (value: unknown): value is number =>
|
|
120
128
|
nonNegativeSafeInteger(value);
|
|
121
129
|
|
|
@@ -344,6 +352,13 @@ export const CONFIG_SCHEMA = {
|
|
|
344
352
|
persisted: true,
|
|
345
353
|
type: "boolean",
|
|
346
354
|
},
|
|
355
|
+
advisorScoutTimeoutMs: {
|
|
356
|
+
accepted: `a positive safe integer no greater than ${MAX_SCOUT_TIMEOUT_MS} milliseconds`,
|
|
357
|
+
current: () => advisorScoutTimeoutMsRef,
|
|
358
|
+
persisted: true,
|
|
359
|
+
type: "number",
|
|
360
|
+
validate: isValidScoutTimeoutMs,
|
|
361
|
+
},
|
|
347
362
|
advisorSessionSummary: {
|
|
348
363
|
accepted: "true or false",
|
|
349
364
|
current: () => advisorSessionSummaryRef,
|
package/src/config/state.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
DEFAULT_JEV_TRANSPORT,
|
|
15
15
|
DEFAULT_JEV_TURN_GATE_EVERY_TURNS,
|
|
16
16
|
DEFAULT_JEV_TURN_GATE_NOUL_THRESHOLD,
|
|
17
|
+
DEFAULT_SCOUT_TIMEOUT_MS,
|
|
17
18
|
} from "./types.ts";
|
|
18
19
|
import type {
|
|
19
20
|
AdvisorToolPolicies,
|
|
@@ -68,6 +69,7 @@ export let advisorOutcomeLoggingRef = false;
|
|
|
68
69
|
export let advisorUntrackedContentRef = false;
|
|
69
70
|
export let advisorTrackedFileContentRef = false;
|
|
70
71
|
export let advisorScoutEnabledRef = false;
|
|
72
|
+
export let advisorScoutTimeoutMsRef = DEFAULT_SCOUT_TIMEOUT_MS;
|
|
71
73
|
export let showUsageDetailsRef = true;
|
|
72
74
|
export let showUsageFooterRef = false;
|
|
73
75
|
|
|
@@ -213,6 +215,9 @@ export const setAdvisorTrackedFileContentRef = (enabled: boolean) => {
|
|
|
213
215
|
export const setAdvisorScoutEnabledRef = (enabled: boolean) => {
|
|
214
216
|
advisorScoutEnabledRef = enabled;
|
|
215
217
|
};
|
|
218
|
+
export const setAdvisorScoutTimeoutMsRef = (value: number) => {
|
|
219
|
+
advisorScoutTimeoutMsRef = value;
|
|
220
|
+
};
|
|
216
221
|
export const setShowUsageDetailsRef = (enabled: boolean) => {
|
|
217
222
|
showUsageDetailsRef = enabled;
|
|
218
223
|
};
|
|
@@ -256,6 +261,7 @@ export const getAdvisorSettings = () => ({
|
|
|
256
261
|
planGate: advisorPlanGateRef,
|
|
257
262
|
redactSecrets: advisorRedactSecretsRef,
|
|
258
263
|
scoutEnabled: advisorScoutEnabledRef,
|
|
264
|
+
scoutTimeoutMs: advisorScoutTimeoutMsRef,
|
|
259
265
|
sessionSummary: advisorSessionSummaryRef,
|
|
260
266
|
showUsageDetails: showUsageDetailsRef,
|
|
261
267
|
showUsageFooter: showUsageFooterRef,
|
package/src/config/types.ts
CHANGED
|
@@ -23,6 +23,8 @@ export const DEFAULT_JEV_MODEL = "jev-latest";
|
|
|
23
23
|
// Provisional: the latency benchmark was dropped from scope; revisit if live
|
|
24
24
|
// measurements suggest a different bound.
|
|
25
25
|
export const DEFAULT_JEV_TIMEOUT_MS = 8000;
|
|
26
|
+
export const DEFAULT_SCOUT_TIMEOUT_MS = 30_000;
|
|
27
|
+
export const MAX_SCOUT_TIMEOUT_MS = 2_147_483_647;
|
|
26
28
|
export const DEFAULT_JEV_DIGEST_MAX_CHARS = 4000;
|
|
27
29
|
export const DEFAULT_JEV_PRICE_PER_MTOK = 0.042;
|
|
28
30
|
export const DEFAULT_JEV_FILTER_SKIP_CONFIDENCE = 0.85;
|
|
@@ -86,6 +88,7 @@ export interface AdvisorConfig {
|
|
|
86
88
|
advisorPlanGate?: boolean;
|
|
87
89
|
advisorRedactSecrets?: boolean;
|
|
88
90
|
advisorScoutEnabled?: boolean;
|
|
91
|
+
advisorScoutTimeoutMs?: number;
|
|
89
92
|
advisorSessionSummary?: boolean;
|
|
90
93
|
advisorToolPolicies?: AdvisorToolPolicies;
|
|
91
94
|
advisorToolResultMaxBytes?: number;
|
package/src/scout.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import type { Message } from "@earendil-works/pi-ai/compat";
|
|
2
2
|
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
effectiveExecutorEffort,
|
|
6
|
+
effectiveExecutorRef,
|
|
7
|
+
} from "./child-session.ts";
|
|
8
|
+
import { advisorScoutTimeoutMsRef } from "./config/state.ts";
|
|
5
9
|
import { isRecord, isString } from "./content-utils.ts";
|
|
6
10
|
import { collectTextStream, resolveConfiguredModel } from "./model-stream.ts";
|
|
7
11
|
import type {
|
|
@@ -18,8 +22,6 @@ import type { ScoutManifest } from "./scout-types.ts";
|
|
|
18
22
|
import { snapshotAdvisorUsage } from "./usage.ts";
|
|
19
23
|
import type { AdvisorUsageSnapshot } from "./usage.ts";
|
|
20
24
|
|
|
21
|
-
const SCOUT_TIMEOUT_MS = 30_000;
|
|
22
|
-
|
|
23
25
|
export const SCOUT_SYSTEM = [
|
|
24
26
|
"You are Scout, a context curator serving a separate engineering Advisor.",
|
|
25
27
|
"Select only conversation groups materially relevant to the current request, unresolved decisions, attempted work, diagnostics, and validation.",
|
|
@@ -250,6 +252,8 @@ type ScoutStreamResult =
|
|
|
250
252
|
const streamScoutResponse = async (
|
|
251
253
|
dependencies: ScoutDependencies,
|
|
252
254
|
resolved: ResolvedConfiguredModel,
|
|
255
|
+
executorModel: string,
|
|
256
|
+
executorEffort: string | undefined,
|
|
253
257
|
manifest: ScoutManifest,
|
|
254
258
|
parentSignal: AbortSignal | undefined,
|
|
255
259
|
timeoutMs: number,
|
|
@@ -264,10 +268,10 @@ const streamScoutResponse = async (
|
|
|
264
268
|
messages: [manifestMessage(manifest)],
|
|
265
269
|
onChunk: (thinking, text) => {
|
|
266
270
|
if (!controller.signal.aborted) {
|
|
267
|
-
publish({ model:
|
|
271
|
+
publish({ model: executorModel, text, thinking, type: "chunk" });
|
|
268
272
|
}
|
|
269
273
|
},
|
|
270
|
-
reasoning:
|
|
274
|
+
reasoning: executorEffort,
|
|
271
275
|
signal: controller.signal,
|
|
272
276
|
systemPrompt: SCOUT_SYSTEM,
|
|
273
277
|
});
|
|
@@ -294,7 +298,7 @@ export const runAdvisorScout = async (
|
|
|
294
298
|
manifest: ScoutManifest,
|
|
295
299
|
parentSignal?: AbortSignal,
|
|
296
300
|
onEvent?: (event: ScoutLifecycleEvent) => void,
|
|
297
|
-
timeoutMs =
|
|
301
|
+
timeoutMs = advisorScoutTimeoutMsRef,
|
|
298
302
|
dependencies: ScoutDependencies = defaultDependencies
|
|
299
303
|
): Promise<ScoutOutcome> => {
|
|
300
304
|
const startedAt = Date.now();
|
|
@@ -317,7 +321,7 @@ export const runAdvisorScout = async (
|
|
|
317
321
|
usage === undefined
|
|
318
322
|
? baseMetrics(manifest, startedAt)
|
|
319
323
|
: { ...baseMetrics(manifest, startedAt), usage },
|
|
320
|
-
model:
|
|
324
|
+
model: effectiveExecutorRef(ctx),
|
|
321
325
|
ok: false as const,
|
|
322
326
|
};
|
|
323
327
|
publish({ outcome, type: "fallback" });
|
|
@@ -328,9 +332,11 @@ export const runAdvisorScout = async (
|
|
|
328
332
|
return cancelled();
|
|
329
333
|
}
|
|
330
334
|
|
|
335
|
+
const executorModel = effectiveExecutorRef(ctx);
|
|
336
|
+
const executorEffort = effectiveExecutorEffort(ctx);
|
|
331
337
|
let resolved: ResolvedConfiguredModel;
|
|
332
338
|
try {
|
|
333
|
-
resolved = await dependencies.resolve(ctx,
|
|
339
|
+
resolved = await dependencies.resolve(ctx, executorModel, "Scout");
|
|
334
340
|
} catch (error) {
|
|
335
341
|
if (parentSignal?.aborted) {
|
|
336
342
|
return cancelled();
|
|
@@ -342,11 +348,13 @@ export const runAdvisorScout = async (
|
|
|
342
348
|
if (parentSignal?.aborted) {
|
|
343
349
|
return cancelled();
|
|
344
350
|
}
|
|
345
|
-
publish({ model:
|
|
351
|
+
publish({ model: executorModel, type: "call" });
|
|
346
352
|
|
|
347
353
|
const streamed = await streamScoutResponse(
|
|
348
354
|
dependencies,
|
|
349
355
|
resolved,
|
|
356
|
+
executorModel,
|
|
357
|
+
executorEffort,
|
|
350
358
|
manifest,
|
|
351
359
|
parentSignal,
|
|
352
360
|
timeoutMs,
|
|
@@ -390,7 +398,7 @@ export const runAdvisorScout = async (
|
|
|
390
398
|
]).size,
|
|
391
399
|
usage: snapshotAdvisorUsage(streamed.streamed.usage),
|
|
392
400
|
},
|
|
393
|
-
model:
|
|
401
|
+
model: executorModel,
|
|
394
402
|
ok: true as const,
|
|
395
403
|
selectedLabels: manifest.groups
|
|
396
404
|
.filter(
|
|
@@ -53,7 +53,6 @@ export const scoutDetailsFromEvent = (
|
|
|
53
53
|
latencyMs: outcome.metrics.latencyMs,
|
|
54
54
|
model: outcome.model,
|
|
55
55
|
omittedBeforeScout: outcome.metrics.omittedBeforeScout,
|
|
56
|
-
selectedCount: 0,
|
|
57
56
|
status: "fallback",
|
|
58
57
|
usage: snapshotAdvisorUsage(outcome.metrics.usage),
|
|
59
58
|
};
|
|
@@ -144,12 +143,18 @@ const scoutTitle = (scout: ScoutToolDetails, frame: string) => {
|
|
|
144
143
|
return "◆ SCOUT · FALLBACK";
|
|
145
144
|
};
|
|
146
145
|
|
|
146
|
+
const scoutSelectionSummary = (scout: ScoutToolDetails) => {
|
|
147
|
+
if (scout.status === "fallback") {
|
|
148
|
+
return " · original conversation retained";
|
|
149
|
+
}
|
|
150
|
+
if (scout.status !== "curated" || scout.selectedCount === undefined) {
|
|
151
|
+
return "";
|
|
152
|
+
}
|
|
153
|
+
return ` · ${scout.selectedCount} kept / ${Math.max(0, (scout.availableCount ?? 0) - scout.selectedCount)} omitted`;
|
|
154
|
+
};
|
|
155
|
+
|
|
147
156
|
const scoutSummaryLine = (scout: ScoutToolDetails) =>
|
|
148
|
-
` ${scout.model}${
|
|
149
|
-
scout.selectedCount === undefined
|
|
150
|
-
? ""
|
|
151
|
-
: ` · ${scout.selectedCount} kept / ${Math.max(0, (scout.availableCount ?? 0) - scout.selectedCount)} omitted`
|
|
152
|
-
}${scout.latencyMs === undefined ? "" : ` · ${(scout.latencyMs / 1000).toFixed(1)}s`}`;
|
|
157
|
+
` ${scout.model}${scoutSelectionSummary(scout)}${scout.latencyMs === undefined ? "" : ` · ${(scout.latencyMs / 1000).toFixed(1)}s`}`;
|
|
153
158
|
|
|
154
159
|
const scoutExpandedLines = (
|
|
155
160
|
scout: ScoutToolDetails,
|
package/src/ui/settings-items.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
DEFAULT_JEV_TIMEOUT_MS,
|
|
13
13
|
DEFAULT_JEV_TRANSPORT,
|
|
14
14
|
DEFAULT_JEV_TURN_GATE_NOUL_THRESHOLD,
|
|
15
|
+
DEFAULT_SCOUT_TIMEOUT_MS,
|
|
15
16
|
} from "../config/types.ts";
|
|
16
17
|
import { isValidAdvisorToolPolicies } from "../config/validation.ts";
|
|
17
18
|
import { JevSetupSubmenu } from "./jev-setup-submenu.ts";
|
|
@@ -56,6 +57,21 @@ const toggle = (
|
|
|
56
57
|
values: TOGGLE_VALUES,
|
|
57
58
|
});
|
|
58
59
|
|
|
60
|
+
const scoutTimeoutItem = (settings: AdvisorSettings): SettingItem => {
|
|
61
|
+
const timeoutMs = settings.scoutTimeoutMs ?? DEFAULT_SCOUT_TIMEOUT_MS;
|
|
62
|
+
return {
|
|
63
|
+
currentValue: String(timeoutMs),
|
|
64
|
+
description:
|
|
65
|
+
"Maximum time for Scout's response stream; model and auth resolution happen before this timeout starts.",
|
|
66
|
+
id: "scoutTimeoutMs",
|
|
67
|
+
label: "Scout timeout ms",
|
|
68
|
+
values: numericValues(
|
|
69
|
+
timeoutMs,
|
|
70
|
+
[5000, 10_000, 15_000, 30_000, 45_000, 60_000, 90_000, 120_000]
|
|
71
|
+
),
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
|
|
59
75
|
const jevItems = (
|
|
60
76
|
settings: AdvisorSettings,
|
|
61
77
|
theme: Theme,
|
|
@@ -288,6 +304,7 @@ export const createSettingsItems = ({
|
|
|
288
304
|
settings.scoutEnabled,
|
|
289
305
|
false
|
|
290
306
|
),
|
|
307
|
+
scoutTimeoutItem(settings),
|
|
291
308
|
toggle(
|
|
292
309
|
"showUsageDetails",
|
|
293
310
|
"Show usage and cost details",
|
|
@@ -161,6 +161,10 @@ const applyJevMutation = (
|
|
|
161
161
|
settings.jevTimeoutMs = Number(value);
|
|
162
162
|
return true;
|
|
163
163
|
}
|
|
164
|
+
case "scoutTimeoutMs": {
|
|
165
|
+
settings.scoutTimeoutMs = Number(value);
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
164
168
|
case "jevDigestMaxChars": {
|
|
165
169
|
settings.jevDigestMaxChars = Number(value);
|
|
166
170
|
return true;
|
package/src/ui/types.ts
CHANGED