@oh-my-pi/pi-coding-agent 16.0.8 → 16.0.10
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 +33 -0
- package/dist/cli.js +3004 -2976
- package/dist/types/cli/args.d.ts +1 -0
- package/dist/types/collab/host.d.ts +2 -2
- package/dist/types/collab/protocol.d.ts +4 -5
- package/dist/types/commands/launch.d.ts +3 -0
- package/dist/types/config/model-resolver.d.ts +11 -2
- package/dist/types/config/settings-schema.d.ts +12 -2
- package/dist/types/goals/runtime.d.ts +4 -1
- package/dist/types/modes/print-mode.d.ts +2 -0
- package/dist/types/session/agent-session.d.ts +13 -0
- package/dist/types/slash-commands/builtin-registry.d.ts +1 -1
- package/dist/types/slash-commands/helpers/collab-qrcode.d.ts +13 -0
- package/dist/types/tools/index.d.ts +9 -1
- package/dist/types/utils/image-loading.d.ts +12 -0
- package/dist/types/utils/qrcode.d.ts +48 -0
- package/package.json +12 -12
- package/src/cli/args.ts +10 -1
- package/src/cli/flag-tables.ts +1 -0
- package/src/collab/host.ts +4 -4
- package/src/collab/protocol.ts +48 -15
- package/src/commands/launch.ts +3 -0
- package/src/config/config-file.ts +1 -1
- package/src/config/keybindings.ts +2 -2
- package/src/config/model-registry.ts +16 -4
- package/src/config/model-resolver.ts +193 -35
- package/src/config/settings-schema.ts +14 -2
- package/src/config/settings.ts +3 -3
- package/src/goals/runtime.ts +19 -7
- package/src/internal-urls/docs-index.generated.txt +1 -1
- package/src/main.ts +10 -2
- package/src/modes/components/oauth-selector.ts +31 -2
- package/src/modes/interactive-mode.ts +7 -3
- package/src/modes/print-mode.ts +5 -1
- package/src/prompts/advisor/advise-tool.md +3 -1
- package/src/prompts/advisor/system.md +55 -12
- package/src/prompts/tools/inspect-image.md +1 -1
- package/src/sdk.ts +26 -7
- package/src/session/agent-session.ts +103 -16
- package/src/slash-commands/builtin-registry.ts +29 -11
- package/src/slash-commands/helpers/collab-qrcode.ts +28 -0
- package/src/thinking.ts +25 -5
- package/src/tools/index.ts +10 -1
- package/src/tools/inspect-image.ts +72 -9
- package/src/utils/file-mentions.ts +5 -2
- package/src/utils/image-loading.ts +58 -0
- package/src/utils/qrcode.ts +535 -0
package/src/main.ts
CHANGED
|
@@ -72,7 +72,7 @@ import { shouldShowStartupSplash } from "./startup-splash";
|
|
|
72
72
|
import { discoverTitleSystemPromptFile, resolvePromptInput } from "./system-prompt";
|
|
73
73
|
import { createPersistedSubagentReviverFactory } from "./task/persisted-revive";
|
|
74
74
|
import { initTelemetryExport, isTelemetryExportEnabled } from "./telemetry-export";
|
|
75
|
-
import { AUTO_THINKING } from "./thinking";
|
|
75
|
+
import { AUTO_THINKING, parseConfiguredThinkingLevel } from "./thinking";
|
|
76
76
|
import type { LspStartupServerInfo } from "./tools";
|
|
77
77
|
import {
|
|
78
78
|
getChangelogPath,
|
|
@@ -857,7 +857,7 @@ async function buildSessionOptions(
|
|
|
857
857
|
if (scopedModels.length > 0) {
|
|
858
858
|
// `auto` is a session-level concept only; per-scoped-model (Ctrl+P) thinking
|
|
859
859
|
// overrides stay concrete, so coerce the auto default to "unset" here.
|
|
860
|
-
const defaultThinkingLevelSetting = activeSettings.get("defaultThinkingLevel");
|
|
860
|
+
const defaultThinkingLevelSetting = parseConfiguredThinkingLevel(activeSettings.get("defaultThinkingLevel"));
|
|
861
861
|
const defaultThinkingLevel =
|
|
862
862
|
defaultThinkingLevelSetting === AUTO_THINKING ? undefined : defaultThinkingLevelSetting;
|
|
863
863
|
options.scopedModels = scopedModels.map(scopedModel => ({
|
|
@@ -1039,6 +1039,13 @@ export async function runRootCommand(
|
|
|
1039
1039
|
});
|
|
1040
1040
|
}
|
|
1041
1041
|
|
|
1042
|
+
// --print-thoughts (single-shot print mode) must surface reasoning, so un-hide
|
|
1043
|
+
// thinking before the session is built — otherwise a passive hideThinkingBlock
|
|
1044
|
+
// setting makes the provider omit summaries and the flag prints nothing. An
|
|
1045
|
+
// explicit --hide-thinking below still wins.
|
|
1046
|
+
if (parsedArgs.printThoughts && !isProtocolMode && !isInteractive) {
|
|
1047
|
+
settingsInstance.override("hideThinkingBlock", false);
|
|
1048
|
+
}
|
|
1042
1049
|
// Apply --hide-thinking CLI flag (ephemeral, not persisted)
|
|
1043
1050
|
if (parsedArgs.hideThinking) {
|
|
1044
1051
|
settingsInstance.override("hideThinkingBlock", true);
|
|
@@ -1373,6 +1380,7 @@ export async function runRootCommand(
|
|
|
1373
1380
|
messages: initialArgs.messages,
|
|
1374
1381
|
initialMessage,
|
|
1375
1382
|
initialImages,
|
|
1383
|
+
printThoughts: initialArgs.printThoughts,
|
|
1376
1384
|
});
|
|
1377
1385
|
if ($env.PI_TIMING) {
|
|
1378
1386
|
logger.printTimings();
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
Spacer,
|
|
11
11
|
TruncatedText,
|
|
12
12
|
} from "@oh-my-pi/pi-tui";
|
|
13
|
+
import { settings } from "../../config/settings";
|
|
13
14
|
import { theme } from "../../modes/theme/theme";
|
|
14
15
|
import { matchesSelectCancel, matchesSelectDown, matchesSelectUp } from "../../modes/utils/keybinding-matchers";
|
|
15
16
|
import type { AuthStorage, CredentialOriginKind } from "../../session/auth-storage";
|
|
@@ -17,6 +18,20 @@ import { DynamicBorder } from "./dynamic-border";
|
|
|
17
18
|
|
|
18
19
|
const OAUTH_SELECTOR_MAX_VISIBLE = 10;
|
|
19
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Provider ids the user has disabled via settings. `/login` (login mode) hides
|
|
23
|
+
* these so a disabled provider's models stay out of reach end-to-end, mirroring
|
|
24
|
+
* the model picker's `disabledProviders` filtering. Reads the settings singleton
|
|
25
|
+
* defensively: it throws before `Settings.init()`, in which case nothing is disabled.
|
|
26
|
+
*/
|
|
27
|
+
function getDisabledProviderIds(): ReadonlySet<string> {
|
|
28
|
+
try {
|
|
29
|
+
return new Set(settings.get("disabledProviders"));
|
|
30
|
+
} catch {
|
|
31
|
+
return new Set();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
20
35
|
/**
|
|
21
36
|
* Rendered lines before the provider rows: top border, spacer, title, spacer
|
|
22
37
|
* (must mirror the constructor's addChild order).
|
|
@@ -102,8 +117,22 @@ export class OAuthSelectorComponent extends Container {
|
|
|
102
117
|
|
|
103
118
|
#loadProviders(): void {
|
|
104
119
|
const providers = getOAuthProviders();
|
|
105
|
-
this.#
|
|
106
|
-
|
|
120
|
+
if (this.#mode === "logout") {
|
|
121
|
+
// Logout stays unfiltered by `disabledProviders`: a now-disabled
|
|
122
|
+
// provider may still hold stored credentials worth removing.
|
|
123
|
+
this.#allProviders = providers.filter(provider => this.#hasSelectableAuth(provider.id));
|
|
124
|
+
} else {
|
|
125
|
+
const disabled = getDisabledProviderIds();
|
|
126
|
+
// Hide a login entry when either its own id or the provider id it
|
|
127
|
+
// stores credentials under is disabled, so alias logins (e.g.
|
|
128
|
+
// `openai-codex-device` ⇒ `openai-codex`) disappear alongside the
|
|
129
|
+
// model provider they authenticate.
|
|
130
|
+
this.#allProviders = providers.filter(
|
|
131
|
+
provider =>
|
|
132
|
+
!disabled.has(provider.id) &&
|
|
133
|
+
!(provider.storeCredentialsAs && disabled.has(provider.storeCredentialsAs)),
|
|
134
|
+
);
|
|
135
|
+
}
|
|
107
136
|
this.#filteredProviders = this.#allProviders;
|
|
108
137
|
}
|
|
109
138
|
|
|
@@ -797,7 +797,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
797
797
|
await this.initHooksAndCustomTools();
|
|
798
798
|
|
|
799
799
|
// Restore mode from session (e.g. plan mode on resume)
|
|
800
|
-
this.session.setSessionSwitchReconciler?.(() => this.#reconcileModeFromSession());
|
|
800
|
+
this.session.setSessionSwitchReconciler?.(() => this.#reconcileModeFromSession({ preserveActiveGoal: true }));
|
|
801
801
|
await this.#reconcileModeFromSession();
|
|
802
802
|
|
|
803
803
|
// Brand-new sessions optionally start in plan mode when the user has made it
|
|
@@ -1783,11 +1783,12 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
1783
1783
|
}
|
|
1784
1784
|
|
|
1785
1785
|
/** Reconcile mode state from session entries on resume/switch. */
|
|
1786
|
-
async #reconcileModeFromSession(): Promise<void> {
|
|
1786
|
+
async #reconcileModeFromSession(options?: { preserveActiveGoal?: boolean }): Promise<void> {
|
|
1787
1787
|
await this.#clearTransientModeState();
|
|
1788
1788
|
const sessionContext = this.sessionManager.buildSessionContext();
|
|
1789
1789
|
const goalEnabled = this.session.settings.get("goal.enabled");
|
|
1790
1790
|
if (!goalEnabled && (sessionContext.mode === "goal" || sessionContext.mode === "goal_paused")) {
|
|
1791
|
+
this.session.goalRuntime.clearAccounting();
|
|
1791
1792
|
this.sessionManager.appendModeChange("none");
|
|
1792
1793
|
return;
|
|
1793
1794
|
}
|
|
@@ -1802,7 +1803,9 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
1802
1803
|
mode: "active",
|
|
1803
1804
|
goal,
|
|
1804
1805
|
});
|
|
1805
|
-
const restored = await this.session.goalRuntime.onThreadResumed(
|
|
1806
|
+
const restored = await this.session.goalRuntime.onThreadResumed({
|
|
1807
|
+
preserveActiveGoal: options?.preserveActiveGoal,
|
|
1808
|
+
});
|
|
1806
1809
|
this.goalModeEnabled = restored?.enabled === true;
|
|
1807
1810
|
this.goalModePaused = restored?.enabled !== true && restored?.goal.status === "paused";
|
|
1808
1811
|
// sdk.ts excludes "goal" from the initial active tool set unconditionally.
|
|
@@ -1815,6 +1818,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
1815
1818
|
this.#updateGoalModeStatus();
|
|
1816
1819
|
return;
|
|
1817
1820
|
}
|
|
1821
|
+
this.session.goalRuntime.clearAccounting();
|
|
1818
1822
|
if (!this.session.settings.get("plan.enabled")) {
|
|
1819
1823
|
// Clear stale plan/plan_paused mode so re-enabling the setting
|
|
1820
1824
|
// later doesn't unexpectedly restore an old plan session.
|
package/src/modes/print-mode.ts
CHANGED
|
@@ -24,6 +24,8 @@ export interface PrintModeOptions {
|
|
|
24
24
|
initialMessage?: string;
|
|
25
25
|
/** Images to attach to the initial message */
|
|
26
26
|
initialImages?: ImageContent[];
|
|
27
|
+
/** If true, include thinking blocks in text output */
|
|
28
|
+
printThoughts?: boolean;
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
/**
|
|
@@ -31,7 +33,7 @@ export interface PrintModeOptions {
|
|
|
31
33
|
* Sends prompts to the agent and outputs the result.
|
|
32
34
|
*/
|
|
33
35
|
export async function runPrintMode(session: AgentSession, options: PrintModeOptions): Promise<void> {
|
|
34
|
-
const { mode, messages = [], initialMessage, initialImages } = options;
|
|
36
|
+
const { mode, messages = [], initialMessage, initialImages, printThoughts } = options;
|
|
35
37
|
|
|
36
38
|
// Emit session header for JSON mode
|
|
37
39
|
if (mode === "json") {
|
|
@@ -108,6 +110,8 @@ export async function runPrintMode(session: AgentSession, options: PrintModeOpti
|
|
|
108
110
|
for (const content of assistantMsg.content) {
|
|
109
111
|
if (content.type === "text") {
|
|
110
112
|
process.stdout.write(`${sanitizeText(content.text)}\n`);
|
|
113
|
+
} else if (printThoughts && content.type === "thinking" && content.thinking.trim().length > 0) {
|
|
114
|
+
process.stdout.write(`${sanitizeText(content.thinking)}\n`);
|
|
111
115
|
}
|
|
112
116
|
}
|
|
113
117
|
}
|
|
@@ -1 +1,3 @@
|
|
|
1
|
-
Send one concrete, terse piece of advice to the agent you are watching.
|
|
1
|
+
Send one concrete, terse piece of advice to the agent you are watching.
|
|
2
|
+
- Use sparingly; stay silent when nothing matters.
|
|
3
|
+
- Call it to head off likely-wrong or materially wasteful work.
|
|
@@ -1,32 +1,75 @@
|
|
|
1
1
|
<system-conventions>
|
|
2
2
|
RFC 2119 applies to MUST, REQUIRED, SHOULD, RECOMMENDED, MAY, OPTIONAL. `NEVER` and `AVOID` are aliases for `MUST NOT` and `SHOULD NOT`.
|
|
3
|
-
You can explore the workspace; budget is 2–3 tool calls per advise (exception: critical bugs warrant deeper verification before raising a blocker).
|
|
4
3
|
</system-conventions>
|
|
5
4
|
|
|
6
|
-
You bring a different angle.
|
|
7
|
-
|
|
5
|
+
You bring a different angle, and advocate for the user and the code-quality & robustness.
|
|
6
|
+
You're watching over the main agent as a peer-programmer:
|
|
7
|
+
- They might not have thought about an edge case, or realized a more elegant approach exists.
|
|
8
|
+
- They might be sinking deeper into a hole that will not get the user's request accomplished.
|
|
9
|
+
|
|
8
10
|
Your job is to offer that view before they sink work into the wrong direction.
|
|
9
11
|
|
|
10
12
|
<workflow>
|
|
11
|
-
You receive the agent's transcript incrementally, including
|
|
13
|
+
You receive the agent's transcript incrementally, including their thoughts.
|
|
12
14
|
You have read-only access through `read`, `search`, `find` to verify your suspicions.
|
|
13
|
-
Keep exploration lean
|
|
15
|
+
Keep exploration lean:
|
|
16
|
+
- 2–3 tool calls per advise.
|
|
17
|
+
- Exception: critical bugs may need deeper verification before raising a blocker.
|
|
14
18
|
</workflow>
|
|
15
19
|
|
|
16
20
|
<communication>
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
- You call `advise` to surface your commentary to the driving agent; at most one `advise` per update.
|
|
22
|
+
- Prefer silence when the agent is on track.
|
|
23
|
+
- Address the agent directly.
|
|
24
|
+
- Offer alternatives, not lectures.
|
|
25
|
+
- NEVER restate information the agent already has, including errors they have seen.
|
|
26
|
+
- Examples: type errors, LSP diagnostics, failed builds, failing tests, lint.
|
|
27
|
+
- NEVER repeat advice you already gave.
|
|
28
|
+
- NEVER nitpick about things user stated they are okay with. You are the advocate for the user.
|
|
19
29
|
</communication>
|
|
20
30
|
|
|
21
31
|
<critical>
|
|
22
|
-
|
|
32
|
+
A low-confidence bar applies ONLY to concrete technical risk:
|
|
33
|
+
- Generic uncertainty, vague unease, or user-intent ambiguity → stay SILENT.
|
|
34
|
+
|
|
23
35
|
NEVER advise just to second-guess decisions the agent understands and is committed to, if you are not certain.
|
|
36
|
+
|
|
37
|
+
NEVER advise on intent or process:
|
|
38
|
+
- Do not push the agent to ask for clarification, confirm scope, or summarize input before acting.
|
|
39
|
+
- Do not question whether the user's ask is clear enough.
|
|
40
|
+
- Intent is the agent's domain; it defaults to informed action.
|
|
41
|
+
- Your lane: correctness, edge cases, design, process.
|
|
42
|
+
|
|
43
|
+
Cite the exact instruction or risk.
|
|
24
44
|
</critical>
|
|
25
45
|
|
|
26
46
|
<completeness>
|
|
27
|
-
**`nit`**
|
|
28
|
-
|
|
29
|
-
|
|
47
|
+
**`nit`**
|
|
48
|
+
- Non-urgent cleanup, refactor, style, missed opportunity.
|
|
49
|
+
- Folded at next step boundary; agent keeps working.
|
|
50
|
+
- Examples:
|
|
51
|
+
- Edge cases that don't break correctness.
|
|
52
|
+
- Simplifications.
|
|
53
|
+
- Better approach the agent can consider.
|
|
54
|
+
|
|
55
|
+
**`concern`**
|
|
56
|
+
- Agent might be heading wrong or missed something material.
|
|
57
|
+
- Offers your view; agent decides.
|
|
58
|
+
- Use when:
|
|
59
|
+
- Exploring wrong code path.
|
|
60
|
+
- Picking fragile approach when better exists.
|
|
61
|
+
- Not parallelizing when user request is obviously parallelizable.
|
|
62
|
+
- Missing constraint.
|
|
63
|
+
- Edge case about to be baked in.
|
|
64
|
+
|
|
65
|
+
**`blocker`**
|
|
66
|
+
- Stop and reconsider.
|
|
67
|
+
- Use ONLY when the agent making progress will clearly:
|
|
68
|
+
- Waste the users time with a larger refactor.
|
|
69
|
+
- Will require the user to interrupt the agent later on, due to them going in circles without a solution.
|
|
70
|
+
- Be fundamentally unsound.
|
|
71
|
+
- Verify thoroughly before raising.
|
|
30
72
|
</completeness>
|
|
31
73
|
|
|
32
|
-
You MAY suggest an approach or fix if you've explored enough to be confident.
|
|
74
|
+
You MAY suggest an approach or fix if you've explored enough to be confident.
|
|
75
|
+
Offer the better designs, not just the warning.
|
|
@@ -2,7 +2,7 @@ Inspects an image file with a vision-capable model and returns compact text anal
|
|
|
2
2
|
|
|
3
3
|
<instruction>
|
|
4
4
|
- Use this for image understanding tasks (OCR, UI/screenshot debugging, scene/object questions)
|
|
5
|
-
- Provide `path`
|
|
5
|
+
- Provide `path` as a local image file path, `Image #N` attachment label, or `attachment://N` URI
|
|
6
6
|
- Write a specific `question`:
|
|
7
7
|
- what to inspect
|
|
8
8
|
- constraints (for example: "quote visible text verbatim", "only report confirmed findings")
|
package/src/sdk.ts
CHANGED
|
@@ -144,6 +144,7 @@ import { AgentOutputManager } from "./task/output-manager";
|
|
|
144
144
|
import {
|
|
145
145
|
AUTO_THINKING,
|
|
146
146
|
type ConfiguredThinkingLevel,
|
|
147
|
+
parseConfiguredThinkingLevel,
|
|
147
148
|
parseThinkingLevel,
|
|
148
149
|
resolveProvisionalAutoLevel,
|
|
149
150
|
resolveThinkingLevelForModel,
|
|
@@ -1266,12 +1267,16 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1266
1267
|
? getRestorableSessionModels(existingSession.models, sessionManager.getLastModelChangeRole())
|
|
1267
1268
|
: [];
|
|
1268
1269
|
let restoredSessionModelIndex = -1;
|
|
1270
|
+
let restoredSessionThinkingLevel: ThinkingLevel | undefined;
|
|
1269
1271
|
if (!hasExplicitModel && !model && sessionModelStrings.length > 0) {
|
|
1270
1272
|
logger.time("restoreSessionModel", () => {
|
|
1271
1273
|
let failedSessionModel: string | undefined;
|
|
1272
1274
|
for (let i = 0; i < sessionModelStrings.length; i++) {
|
|
1273
1275
|
const sessionModelStr = sessionModelStrings[i];
|
|
1274
|
-
const parsedModel = parseModelString(sessionModelStr
|
|
1276
|
+
const parsedModel = parseModelString(sessionModelStr, {
|
|
1277
|
+
allowMaxAlias: true,
|
|
1278
|
+
isLiteralModelId: (provider, id) => modelRegistry.find(provider, id) !== undefined,
|
|
1279
|
+
});
|
|
1275
1280
|
if (!parsedModel) {
|
|
1276
1281
|
failedSessionModel ??= sessionModelStr;
|
|
1277
1282
|
continue;
|
|
@@ -1281,6 +1286,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1281
1286
|
if (restoredModel && hasModelAuth(restoredModel)) {
|
|
1282
1287
|
model = restoredModel;
|
|
1283
1288
|
restoredSessionModelIndex = i;
|
|
1289
|
+
restoredSessionThinkingLevel = parsedModel.thinkingLevel;
|
|
1284
1290
|
break;
|
|
1285
1291
|
}
|
|
1286
1292
|
failedSessionModel ??= sessionModelStr;
|
|
@@ -1305,15 +1311,19 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1305
1311
|
const taskDepth = options.taskDepth ?? 0;
|
|
1306
1312
|
|
|
1307
1313
|
// Resolves the session/agent thinking level using the same precedence we
|
|
1308
|
-
// apply at startup: explicit option → persisted session entry →
|
|
1309
|
-
//
|
|
1310
|
-
// settings default. Run again after extension
|
|
1311
|
-
// model's own defaults aren't masked by an earlier
|
|
1314
|
+
// apply at startup: explicit option → persisted session entry → restored
|
|
1315
|
+
// model selector suffix → default role's explicit selector → selected
|
|
1316
|
+
// model's defaultLevel → global settings default. Run again after extension
|
|
1317
|
+
// role reclaim so the final model's own defaults aren't masked by an earlier
|
|
1318
|
+
// fallback model's.
|
|
1312
1319
|
const pickInitialThinkingLevel = (selectedModel: Model | undefined): ConfiguredThinkingLevel | undefined => {
|
|
1313
1320
|
let level = options.thinkingLevel;
|
|
1314
1321
|
if (level === undefined && hasExistingSession && hasThinkingEntry) {
|
|
1315
1322
|
level = parseThinkingLevel(existingSession.thinkingLevel);
|
|
1316
1323
|
}
|
|
1324
|
+
if (level === undefined && !hasThinkingEntry && restoredSessionThinkingLevel !== undefined) {
|
|
1325
|
+
level = restoredSessionThinkingLevel;
|
|
1326
|
+
}
|
|
1317
1327
|
if (level === undefined && !hasExplicitModel && !hasThinkingEntry && defaultRoleSpec.explicitThinkingLevel) {
|
|
1318
1328
|
level = defaultRoleSpec.thinkingLevel;
|
|
1319
1329
|
}
|
|
@@ -1321,7 +1331,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1321
1331
|
level = selectedModel.thinking.defaultLevel;
|
|
1322
1332
|
}
|
|
1323
1333
|
if (level === undefined) {
|
|
1324
|
-
level = settings.get("defaultThinkingLevel");
|
|
1334
|
+
level = parseConfiguredThinkingLevel(settings.get("defaultThinkingLevel"));
|
|
1325
1335
|
}
|
|
1326
1336
|
return level;
|
|
1327
1337
|
};
|
|
@@ -1533,6 +1543,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1533
1543
|
getModelString: () => (hasExplicitModel && model ? formatModelString(model) : undefined),
|
|
1534
1544
|
getActiveModelString,
|
|
1535
1545
|
getActiveModel: () => agent?.state.model ?? model,
|
|
1546
|
+
getImageAttachments: () => session?.getImageAttachments() ?? [],
|
|
1536
1547
|
getPlanModeState: () => session?.getPlanModeState(),
|
|
1537
1548
|
getPlanReferencePath: () => session?.getPlanReferencePath() ?? "local://PLAN.md",
|
|
1538
1549
|
getGoalModeState: () => session?.getGoalModeState(),
|
|
@@ -1905,13 +1916,17 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1905
1916
|
if (!hasExplicitModel && sessionRetryLimit > 0) {
|
|
1906
1917
|
for (let i = 0; i < sessionRetryLimit; i++) {
|
|
1907
1918
|
const sessionModelStr = sessionModelStrings[i];
|
|
1908
|
-
const parsedModel = parseModelString(sessionModelStr
|
|
1919
|
+
const parsedModel = parseModelString(sessionModelStr, {
|
|
1920
|
+
allowMaxAlias: true,
|
|
1921
|
+
isLiteralModelId: (provider, id) => modelRegistry.find(provider, id) !== undefined,
|
|
1922
|
+
});
|
|
1909
1923
|
if (!parsedModel) continue;
|
|
1910
1924
|
const restoredModel = modelRegistry.find(parsedModel.provider, parsedModel.id);
|
|
1911
1925
|
if (restoredModel && hasModelAuth(restoredModel)) {
|
|
1912
1926
|
model = restoredModel;
|
|
1913
1927
|
modelFallbackMessage = undefined;
|
|
1914
1928
|
restoredSessionModelIndex = i;
|
|
1929
|
+
restoredSessionThinkingLevel = parsedModel.thinkingLevel;
|
|
1915
1930
|
// Recompute thinking-level from scratch against the reclaimed
|
|
1916
1931
|
// model: any value derived from the earlier fallback model's
|
|
1917
1932
|
// `thinking.defaultLevel` must not become sticky.
|
|
@@ -2585,6 +2600,9 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2585
2600
|
if (watchdogFiles && watchdogFiles.length > 0) {
|
|
2586
2601
|
advisorWatchdogPrompt = watchdogFiles.join("\n\n");
|
|
2587
2602
|
}
|
|
2603
|
+
// Owned only when this session created the manager; subagents receive a
|
|
2604
|
+
// parent's manager via `options.mcpManager` and MUST NOT disconnect it.
|
|
2605
|
+
const ownedMcpManager = options.mcpManager ? undefined : mcpManager;
|
|
2588
2606
|
session = new AgentSession({
|
|
2589
2607
|
advisorWatchdogPrompt,
|
|
2590
2608
|
agent,
|
|
@@ -2630,6 +2648,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2630
2648
|
return out;
|
|
2631
2649
|
}
|
|
2632
2650
|
: undefined,
|
|
2651
|
+
disconnectOwnedMcpManager: ownedMcpManager ? () => ownedMcpManager.disconnectAll() : undefined,
|
|
2633
2652
|
mcpDiscoveryEnabled,
|
|
2634
2653
|
initialSelectedMCPToolNames,
|
|
2635
2654
|
defaultSelectedMCPToolNames,
|