@oh-my-pi/pi-coding-agent 13.8.0 → 13.9.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 +52 -0
- package/package.json +7 -7
- package/src/capability/rule.ts +0 -4
- package/src/cli/agents-cli.ts +1 -1
- package/src/cli/args.ts +7 -12
- package/src/commands/launch.ts +3 -2
- package/src/config/model-resolver.ts +106 -33
- package/src/config/settings-schema.ts +14 -2
- package/src/config/settings.ts +1 -17
- package/src/discovery/helpers.ts +10 -17
- package/src/export/html/template.generated.ts +1 -1
- package/src/export/html/template.js +37 -15
- package/src/extensibility/extensions/loader.ts +1 -2
- package/src/extensibility/extensions/types.ts +2 -1
- package/src/main.ts +20 -13
- package/src/modes/components/agent-dashboard.ts +12 -13
- package/src/modes/components/model-selector.ts +157 -59
- package/src/modes/components/read-tool-group.ts +36 -2
- package/src/modes/components/settings-defs.ts +11 -8
- package/src/modes/components/settings-selector.ts +1 -1
- package/src/modes/components/thinking-selector.ts +3 -15
- package/src/modes/controllers/selector-controller.ts +21 -7
- package/src/modes/rpc/rpc-client.ts +2 -2
- package/src/modes/rpc/rpc-types.ts +2 -2
- package/src/modes/theme/theme.ts +2 -1
- package/src/patch/hashline.ts +26 -3
- package/src/patch/index.ts +14 -16
- package/src/prompts/tools/read.md +2 -2
- package/src/sdk.ts +21 -29
- package/src/session/agent-session.ts +44 -37
- package/src/task/executor.ts +10 -8
- package/src/task/types.ts +1 -2
- package/src/tools/read.ts +88 -264
- package/src/utils/frontmatter.ts +25 -4
- package/src/web/scrapers/choosealicense.ts +1 -1
package/src/modes/theme/theme.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
+
import type { ThinkingLevel } from "@oh-my-pi/pi-ai";
|
|
3
4
|
import {
|
|
4
5
|
detectMacOSAppearance,
|
|
5
6
|
type HighlightColors as NativeHighlightColors,
|
|
@@ -1219,7 +1220,7 @@ export class Theme {
|
|
|
1219
1220
|
return this.mode;
|
|
1220
1221
|
}
|
|
1221
1222
|
|
|
1222
|
-
getThinkingBorderColor(level:
|
|
1223
|
+
getThinkingBorderColor(level: ThinkingLevel): (str: string) => string {
|
|
1223
1224
|
// Map thinking levels to dedicated theme colors
|
|
1224
1225
|
switch (level) {
|
|
1225
1226
|
case "off":
|
package/src/patch/hashline.ts
CHANGED
|
@@ -458,6 +458,18 @@ function maybeWarnSuspiciousUnicodeEscapePlaceholder(edits: HashlineEdit[], warn
|
|
|
458
458
|
// Edit Application
|
|
459
459
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
460
460
|
|
|
461
|
+
const MIN_AUTOCORRECT_LENGTH = 2;
|
|
462
|
+
|
|
463
|
+
function shouldAutocorrect(line: string, otherLine: string): boolean {
|
|
464
|
+
if (!line || line !== otherLine) return false;
|
|
465
|
+
line = line.trim();
|
|
466
|
+
if (line.length < MIN_AUTOCORRECT_LENGTH) {
|
|
467
|
+
// if brace, we allow
|
|
468
|
+
return line.endsWith("}") || line.endsWith(")");
|
|
469
|
+
}
|
|
470
|
+
return true;
|
|
471
|
+
}
|
|
472
|
+
|
|
461
473
|
/**
|
|
462
474
|
* Apply an array of hashline edits to file content.
|
|
463
475
|
*
|
|
@@ -630,9 +642,7 @@ export function applyHashlineEdits(
|
|
|
630
642
|
const trailingReplacementLine = newLines[newLines.length - 1]?.trimEnd();
|
|
631
643
|
const nextSurvivingLine = fileLines[edit.end.line]?.trimEnd();
|
|
632
644
|
if (
|
|
633
|
-
trailingReplacementLine &&
|
|
634
|
-
nextSurvivingLine &&
|
|
635
|
-
trailingReplacementLine === nextSurvivingLine &&
|
|
645
|
+
shouldAutocorrect(trailingReplacementLine, nextSurvivingLine) &&
|
|
636
646
|
// Safety: only correct when end-line content differs from the duplicate.
|
|
637
647
|
// If end already points to the boundary, matching next line is coincidence.
|
|
638
648
|
fileLines[edit.end.line - 1]?.trimEnd() !== trailingReplacementLine
|
|
@@ -642,6 +652,19 @@ export function applyHashlineEdits(
|
|
|
642
652
|
`Auto-corrected range replace ${edit.pos.line}#${edit.pos.hash}-${edit.end.line}#${edit.end.hash}: removed trailing replacement line "${trailingReplacementLine}" that duplicated next surviving line`,
|
|
643
653
|
);
|
|
644
654
|
}
|
|
655
|
+
const leadingReplacementLine = newLines[0]?.trimEnd();
|
|
656
|
+
const prevSurvivingLine = fileLines[edit.pos.line - 2]?.trimEnd();
|
|
657
|
+
if (
|
|
658
|
+
shouldAutocorrect(leadingReplacementLine, prevSurvivingLine) &&
|
|
659
|
+
// Safety: only correct when pos-line content differs from the duplicate.
|
|
660
|
+
// If pos already points to the boundary, matching prev line is coincidence.
|
|
661
|
+
fileLines[edit.pos.line - 1]?.trimEnd() !== leadingReplacementLine
|
|
662
|
+
) {
|
|
663
|
+
newLines.shift();
|
|
664
|
+
warnings.push(
|
|
665
|
+
`Auto-corrected range replace ${edit.pos.line}#${edit.pos.hash}-${edit.end.line}#${edit.end.hash}: removed leading replacement line "${leadingReplacementLine}" that duplicated preceding surviving line`,
|
|
666
|
+
);
|
|
667
|
+
}
|
|
645
668
|
fileLines.splice(edit.pos.line - 1, count, ...newLines);
|
|
646
669
|
trackFirstChanged(edit.pos.line);
|
|
647
670
|
}
|
package/src/patch/index.ts
CHANGED
|
@@ -322,18 +322,10 @@ export type EditMode = "replace" | "patch" | "hashline";
|
|
|
322
322
|
|
|
323
323
|
export const DEFAULT_EDIT_MODE: EditMode = "hashline";
|
|
324
324
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
case "patch":
|
|
330
|
-
return "patch";
|
|
331
|
-
case "hashline":
|
|
332
|
-
return "hashline";
|
|
333
|
-
default:
|
|
334
|
-
return null;
|
|
335
|
-
}
|
|
336
|
-
}
|
|
325
|
+
const EDIT_ID: Record<string, EditMode> = Object.fromEntries(
|
|
326
|
+
["replace", "patch", "hashline"].map(mode => [mode, mode as EditMode]),
|
|
327
|
+
);
|
|
328
|
+
export const normalizeEditMode = (mode?: string | null): EditMode | undefined => EDIT_ID[mode ?? ""];
|
|
337
329
|
|
|
338
330
|
/**
|
|
339
331
|
* Edit tool implementation.
|
|
@@ -408,11 +400,17 @@ export class EditTool implements AgentTool<TInput> {
|
|
|
408
400
|
*/
|
|
409
401
|
get mode(): EditMode {
|
|
410
402
|
if (this.#editMode) return this.#editMode;
|
|
403
|
+
// 1. Check if edit mode is explicitly set for this model
|
|
411
404
|
const activeModel = this.session.getActiveModelString?.();
|
|
412
|
-
const
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
405
|
+
const modelVariant = this.session.settings.getEditVariantForModel(activeModel);
|
|
406
|
+
if (modelVariant) return modelVariant;
|
|
407
|
+
// 2. Check if model contains "-spark" substring (default to replace mode)
|
|
408
|
+
if (activeModel?.includes("-spark")) return "replace";
|
|
409
|
+
// 3. Check if edit mode is explicitly set in session settings
|
|
410
|
+
const settingsMode = normalizeEditMode(this.session.settings.get("edit.mode"));
|
|
411
|
+
if (settingsMode) return settingsMode;
|
|
412
|
+
// 4. Default to DEFAULT_EDIT_MODE
|
|
413
|
+
return DEFAULT_EDIT_MODE;
|
|
416
414
|
}
|
|
417
415
|
|
|
418
416
|
/**
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Reads files from local filesystem or internal URLs.
|
|
2
2
|
|
|
3
3
|
<instruction>
|
|
4
|
-
- Reads up to {{
|
|
5
|
-
- Use `offset` and `limit` for large files
|
|
4
|
+
- Reads up to {{DEFAULT_LIMIT}} lines default
|
|
5
|
+
- Use `offset` and `limit` for large files; max {{DEFAULT_MAX_LINES}} lines per call
|
|
6
6
|
{{#if IS_HASHLINE_MODE}}
|
|
7
7
|
- Text output is CID prefixed: `LINE#ID:content`
|
|
8
8
|
{{else}}
|
package/src/sdk.ts
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
type AgentMessage,
|
|
5
|
-
type AgentTool,
|
|
6
|
-
INTENT_FIELD,
|
|
7
|
-
type ThinkingLevel,
|
|
8
|
-
} from "@oh-my-pi/pi-agent-core";
|
|
9
|
-
import { type Message, type Model, supportsXhigh } from "@oh-my-pi/pi-ai";
|
|
1
|
+
import { Agent, type AgentEvent, type AgentMessage, type AgentTool, INTENT_FIELD } from "@oh-my-pi/pi-agent-core";
|
|
2
|
+
import { type Message, type Model, supportsXhigh, type ThinkingLevel } from "@oh-my-pi/pi-ai";
|
|
3
|
+
|
|
10
4
|
import { prewarmOpenAICodexResponses } from "@oh-my-pi/pi-ai/providers/openai-codex-responses";
|
|
11
5
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
12
6
|
import { $env, getAgentDbPath, getAgentDir, getProjectDir, logger, postmortem } from "@oh-my-pi/pi-utils";
|
|
@@ -15,7 +9,7 @@ import { AsyncJobManager } from "./async";
|
|
|
15
9
|
import { loadCapability } from "./capability";
|
|
16
10
|
import { type Rule, ruleCapability } from "./capability/rule";
|
|
17
11
|
import { ModelRegistry } from "./config/model-registry";
|
|
18
|
-
import { formatModelString, parseModelPattern, parseModelString } from "./config/model-resolver";
|
|
12
|
+
import { formatModelString, parseModelPattern, parseModelString, resolveModelRoleValue } from "./config/model-resolver";
|
|
19
13
|
import {
|
|
20
14
|
loadPromptTemplates as loadPromptTemplatesInternal,
|
|
21
15
|
type PromptTemplate,
|
|
@@ -651,6 +645,13 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
651
645
|
const hasThinkingEntry = sessionManager.getBranch().some(entry => entry.type === "thinking_level_change");
|
|
652
646
|
|
|
653
647
|
const hasExplicitModel = options.model !== undefined || options.modelPattern !== undefined;
|
|
648
|
+
const modelMatchPreferences = {
|
|
649
|
+
usageOrder: settings.getStorage()?.getModelUsageOrder(),
|
|
650
|
+
};
|
|
651
|
+
const defaultRoleSpec = resolveModelRoleValue(settings.getModelRole("default"), modelRegistry.getAvailable(), {
|
|
652
|
+
settings,
|
|
653
|
+
matchPreferences: modelMatchPreferences,
|
|
654
|
+
});
|
|
654
655
|
let model = options.model;
|
|
655
656
|
let modelFallbackMessage: string | undefined;
|
|
656
657
|
// If session has data, try to restore model from it.
|
|
@@ -671,20 +672,9 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
671
672
|
|
|
672
673
|
// If still no model, try settings default.
|
|
673
674
|
// Skip settings fallback when an explicit model was requested.
|
|
674
|
-
if (!hasExplicitModel && !model) {
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
const parsedModel = parseModelString(settingsDefaultModel);
|
|
678
|
-
if (parsedModel) {
|
|
679
|
-
const settingsModel = modelRegistry.find(parsedModel.provider, parsedModel.id);
|
|
680
|
-
if (settingsModel && (await hasModelApiKey(settingsModel))) {
|
|
681
|
-
model = settingsModel;
|
|
682
|
-
// Apply thinking level from config role suffix if not already set
|
|
683
|
-
if (options.thinkingLevel === undefined && parsedModel.thinkingLevel) {
|
|
684
|
-
options.thinkingLevel = parsedModel.thinkingLevel;
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
}
|
|
675
|
+
if (!hasExplicitModel && !model && defaultRoleSpec.model) {
|
|
676
|
+
if (await hasModelApiKey(defaultRoleSpec.model)) {
|
|
677
|
+
model = defaultRoleSpec.model;
|
|
688
678
|
}
|
|
689
679
|
}
|
|
690
680
|
|
|
@@ -704,11 +694,13 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
704
694
|
|
|
705
695
|
let thinkingLevel = options.thinkingLevel;
|
|
706
696
|
|
|
707
|
-
// If session has data
|
|
708
|
-
if (thinkingLevel === undefined && hasExistingSession) {
|
|
709
|
-
thinkingLevel =
|
|
710
|
-
|
|
711
|
-
|
|
697
|
+
// If session has data and includes a thinking entry, restore it
|
|
698
|
+
if (thinkingLevel === undefined && hasExistingSession && hasThinkingEntry) {
|
|
699
|
+
thinkingLevel = existingSession.thinkingLevel as ThinkingLevel;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
if (thinkingLevel === undefined && !hasExplicitModel && !hasThinkingEntry && defaultRoleSpec.explicitThinkingLevel) {
|
|
703
|
+
thinkingLevel = defaultRoleSpec.thinkingLevel;
|
|
712
704
|
}
|
|
713
705
|
|
|
714
706
|
// Fall back to settings default
|
|
@@ -24,7 +24,6 @@ import {
|
|
|
24
24
|
type AgentState,
|
|
25
25
|
type AgentTool,
|
|
26
26
|
INTENT_FIELD,
|
|
27
|
-
type ThinkingLevel,
|
|
28
27
|
} from "@oh-my-pi/pi-agent-core";
|
|
29
28
|
import type {
|
|
30
29
|
AssistantMessage,
|
|
@@ -33,6 +32,7 @@ import type {
|
|
|
33
32
|
Model,
|
|
34
33
|
ProviderSessionState,
|
|
35
34
|
TextContent,
|
|
35
|
+
ThinkingLevel,
|
|
36
36
|
ToolCall,
|
|
37
37
|
ToolChoice,
|
|
38
38
|
Usage,
|
|
@@ -40,6 +40,7 @@ import type {
|
|
|
40
40
|
} from "@oh-my-pi/pi-ai";
|
|
41
41
|
import {
|
|
42
42
|
calculateRateLimitBackoffMs,
|
|
43
|
+
getAvailableThinkingLevels,
|
|
43
44
|
isContextOverflow,
|
|
44
45
|
modelsAreEqual,
|
|
45
46
|
parseRateLimitReason,
|
|
@@ -49,7 +50,7 @@ import { abortableSleep, getAgentDbPath, isEnoent, logger } from "@oh-my-pi/pi-u
|
|
|
49
50
|
import type { AsyncJob, AsyncJobManager } from "../async";
|
|
50
51
|
import type { Rule } from "../capability/rule";
|
|
51
52
|
import { MODEL_ROLE_IDS, type ModelRegistry, type ModelRole } from "../config/model-registry";
|
|
52
|
-
import {
|
|
53
|
+
import { extractExplicitThinkingSelector, parseModelString, resolveModelRoleValue } from "../config/model-resolver";
|
|
53
54
|
import { expandPromptTemplate, type PromptTemplate, renderPromptTemplate } from "../config/prompt-templates";
|
|
54
55
|
import type { Settings, SkillsSettings } from "../config/settings";
|
|
55
56
|
import { type BashResult, executeBash as executeBashCommand } from "../exec/bash-executor";
|
|
@@ -252,10 +253,6 @@ export interface HandoffResult {
|
|
|
252
253
|
// ============================================================================
|
|
253
254
|
|
|
254
255
|
/** Standard thinking levels */
|
|
255
|
-
const THINKING_LEVELS: ThinkingLevel[] = ["off", "minimal", "low", "medium", "high"];
|
|
256
|
-
|
|
257
|
-
/** Thinking levels including xhigh (for supported models) */
|
|
258
|
-
const THINKING_LEVELS_WITH_XHIGH: ThinkingLevel[] = ["off", "minimal", "low", "medium", "high", "xhigh"];
|
|
259
256
|
|
|
260
257
|
const noOpUIContext: ExtensionUIContext = {
|
|
261
258
|
select: async (_title, _options, _dialogOptions) => undefined,
|
|
@@ -295,7 +292,6 @@ export class AgentSession {
|
|
|
295
292
|
readonly settings: Settings;
|
|
296
293
|
|
|
297
294
|
#asyncJobManager: AsyncJobManager | undefined = undefined;
|
|
298
|
-
|
|
299
295
|
#scopedModels: Array<{ model: Model; thinkingLevel: ThinkingLevel }>;
|
|
300
296
|
#promptTemplates: PromptTemplate[];
|
|
301
297
|
#slashCommands: FileSlashCommand[];
|
|
@@ -2630,7 +2626,7 @@ export class AgentSession {
|
|
|
2630
2626
|
|
|
2631
2627
|
this.#setModelWithProviderSessionReset(model);
|
|
2632
2628
|
this.sessionManager.appendModelChange(`${model.provider}/${model.id}`, role);
|
|
2633
|
-
this.settings.setModelRole(role,
|
|
2629
|
+
this.settings.setModelRole(role, this.#formatRoleModelValue(role, model));
|
|
2634
2630
|
this.settings.getStorage()?.recordModelUsage(`${model.provider}/${model.id}`);
|
|
2635
2631
|
|
|
2636
2632
|
// Re-clamp thinking level for new model's capabilities without persisting settings
|
|
@@ -2684,7 +2680,13 @@ export class AgentSession {
|
|
|
2684
2680
|
|
|
2685
2681
|
const currentModel = this.model;
|
|
2686
2682
|
if (!currentModel) return undefined;
|
|
2687
|
-
const
|
|
2683
|
+
const matchPreferences = { usageOrder: this.settings.getStorage()?.getModelUsageOrder() };
|
|
2684
|
+
const roleModels: Array<{
|
|
2685
|
+
role: ModelRole;
|
|
2686
|
+
model: Model;
|
|
2687
|
+
thinkingLevel?: ThinkingLevel;
|
|
2688
|
+
explicitThinkingLevel: boolean;
|
|
2689
|
+
}> = [];
|
|
2688
2690
|
|
|
2689
2691
|
for (const role of roleOrder) {
|
|
2690
2692
|
const roleModelStr =
|
|
@@ -2693,18 +2695,18 @@ export class AgentSession {
|
|
|
2693
2695
|
: this.settings.getModelRole(role);
|
|
2694
2696
|
if (!roleModelStr) continue;
|
|
2695
2697
|
|
|
2696
|
-
const
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
}
|
|
2702
|
-
if (!match) {
|
|
2703
|
-
match = availableModels.find(m => m.id.toLowerCase() === expandedRoleModelStr.toLowerCase());
|
|
2704
|
-
}
|
|
2705
|
-
if (!match) continue;
|
|
2698
|
+
const resolved = resolveModelRoleValue(roleModelStr, availableModels, {
|
|
2699
|
+
settings: this.settings,
|
|
2700
|
+
matchPreferences,
|
|
2701
|
+
});
|
|
2702
|
+
if (!resolved.model) continue;
|
|
2706
2703
|
|
|
2707
|
-
roleModels.push({
|
|
2704
|
+
roleModels.push({
|
|
2705
|
+
role,
|
|
2706
|
+
model: resolved.model,
|
|
2707
|
+
thinkingLevel: resolved.thinkingLevel,
|
|
2708
|
+
explicitThinkingLevel: resolved.explicitThinkingLevel,
|
|
2709
|
+
});
|
|
2708
2710
|
}
|
|
2709
2711
|
|
|
2710
2712
|
if (roleModels.length <= 1) return undefined;
|
|
@@ -2724,12 +2726,8 @@ export class AgentSession {
|
|
|
2724
2726
|
await this.setModel(next.model, next.role);
|
|
2725
2727
|
}
|
|
2726
2728
|
|
|
2727
|
-
|
|
2728
|
-
if (next.thinkingLevel) {
|
|
2729
|
+
if (next.explicitThinkingLevel && next.thinkingLevel !== undefined) {
|
|
2729
2730
|
this.setThinkingLevel(next.thinkingLevel);
|
|
2730
|
-
if (!options?.temporary) {
|
|
2731
|
-
this.settings.setModelRole(next.role, `${next.model.provider}/${next.model.id}:${next.thinkingLevel}`);
|
|
2732
|
-
}
|
|
2733
2731
|
}
|
|
2734
2732
|
|
|
2735
2733
|
return { model: next.model, thinkingLevel: this.thinkingLevel, role: next.role };
|
|
@@ -2772,7 +2770,7 @@ export class AgentSession {
|
|
|
2772
2770
|
// Apply model
|
|
2773
2771
|
this.#setModelWithProviderSessionReset(next.model);
|
|
2774
2772
|
this.sessionManager.appendModelChange(`${next.model.provider}/${next.model.id}`);
|
|
2775
|
-
this.settings.setModelRole("default",
|
|
2773
|
+
this.settings.setModelRole("default", this.#formatRoleModelValue("default", next.model));
|
|
2776
2774
|
this.settings.getStorage()?.recordModelUsage(`${next.model.provider}/${next.model.id}`);
|
|
2777
2775
|
|
|
2778
2776
|
// Apply thinking level (setThinkingLevel clamps to model capabilities)
|
|
@@ -2800,7 +2798,7 @@ export class AgentSession {
|
|
|
2800
2798
|
|
|
2801
2799
|
this.#setModelWithProviderSessionReset(nextModel);
|
|
2802
2800
|
this.sessionManager.appendModelChange(`${nextModel.provider}/${nextModel.id}`);
|
|
2803
|
-
this.settings.setModelRole("default",
|
|
2801
|
+
this.settings.setModelRole("default", this.#formatRoleModelValue("default", nextModel));
|
|
2804
2802
|
this.settings.getStorage()?.recordModelUsage(`${nextModel.provider}/${nextModel.id}`);
|
|
2805
2803
|
|
|
2806
2804
|
// Re-clamp thinking level for new model's capabilities without persisting settings
|
|
@@ -2862,9 +2860,9 @@ export class AgentSession {
|
|
|
2862
2860
|
* Get available thinking levels for current model.
|
|
2863
2861
|
* The provider will clamp to what the specific model supports internally.
|
|
2864
2862
|
*/
|
|
2865
|
-
getAvailableThinkingLevels(): ThinkingLevel
|
|
2863
|
+
getAvailableThinkingLevels(): ReadonlyArray<ThinkingLevel> {
|
|
2866
2864
|
if (!this.supportsThinking()) return ["off"];
|
|
2867
|
-
return this.supportsXhighThinking()
|
|
2865
|
+
return getAvailableThinkingLevels(this.supportsXhighThinking());
|
|
2868
2866
|
}
|
|
2869
2867
|
|
|
2870
2868
|
/**
|
|
@@ -2881,8 +2879,8 @@ export class AgentSession {
|
|
|
2881
2879
|
return !!this.model?.reasoning;
|
|
2882
2880
|
}
|
|
2883
2881
|
|
|
2884
|
-
#clampThinkingLevel(level: ThinkingLevel, availableLevels: ThinkingLevel
|
|
2885
|
-
const ordered =
|
|
2882
|
+
#clampThinkingLevel(level: ThinkingLevel, availableLevels: ReadonlyArray<ThinkingLevel>): ThinkingLevel {
|
|
2883
|
+
const ordered = getAvailableThinkingLevels(true);
|
|
2886
2884
|
const available = new Set(availableLevels);
|
|
2887
2885
|
const requestedIndex = ordered.indexOf(level);
|
|
2888
2886
|
if (requestedIndex === -1) {
|
|
@@ -3585,6 +3583,15 @@ Be thorough - include exact file paths, function names, error messages, and tech
|
|
|
3585
3583
|
return `${model.provider}/${model.id}`;
|
|
3586
3584
|
}
|
|
3587
3585
|
|
|
3586
|
+
#formatRoleModelValue(role: ModelRole, model: Model): string {
|
|
3587
|
+
const modelKey = `${model.provider}/${model.id}`;
|
|
3588
|
+
const existingRoleValue = this.settings.getModelRole(role);
|
|
3589
|
+
if (!existingRoleValue) return modelKey;
|
|
3590
|
+
|
|
3591
|
+
const thinkingLevel = extractExplicitThinkingSelector(existingRoleValue, this.settings);
|
|
3592
|
+
if (thinkingLevel === undefined) return modelKey;
|
|
3593
|
+
return `${modelKey}:${thinkingLevel}`;
|
|
3594
|
+
}
|
|
3588
3595
|
#resolveContextPromotionConfiguredTarget(currentModel: Model, availableModels: Model[]): Model | undefined {
|
|
3589
3596
|
const configuredTarget = currentModel.contextPromotionTarget?.trim();
|
|
3590
3597
|
if (!configuredTarget) return undefined;
|
|
@@ -3607,12 +3614,10 @@ Be thorough - include exact file paths, function names, error messages, and tech
|
|
|
3607
3614
|
|
|
3608
3615
|
if (!roleModelStr) return undefined;
|
|
3609
3616
|
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
}
|
|
3614
|
-
const roleLower = roleModelStr.toLowerCase();
|
|
3615
|
-
return availableModels.find(m => m.id.toLowerCase() === roleLower);
|
|
3617
|
+
return resolveModelRoleValue(roleModelStr, availableModels, {
|
|
3618
|
+
settings: this.settings,
|
|
3619
|
+
matchPreferences: { usageOrder: this.settings.getStorage()?.getModelUsageOrder() },
|
|
3620
|
+
}).model;
|
|
3616
3621
|
}
|
|
3617
3622
|
|
|
3618
3623
|
#getCompactionModelCandidates(availableModels: Model[]): Model[] {
|
|
@@ -4563,6 +4568,7 @@ Be thorough - include exact file paths, function names, error messages, and tech
|
|
|
4563
4568
|
|
|
4564
4569
|
if (!skipConversationRestore) {
|
|
4565
4570
|
this.agent.replaceMessages(sessionContext.messages);
|
|
4571
|
+
this.#closeCodexProviderSessionsForHistoryRewrite();
|
|
4566
4572
|
}
|
|
4567
4573
|
|
|
4568
4574
|
return { selectedText, cancelled: false };
|
|
@@ -4717,6 +4723,7 @@ Be thorough - include exact file paths, function names, error messages, and tech
|
|
|
4717
4723
|
const sessionContext = this.sessionManager.buildSessionContext();
|
|
4718
4724
|
this.agent.replaceMessages(sessionContext.messages);
|
|
4719
4725
|
this.#syncTodoPhasesFromBranch();
|
|
4726
|
+
this.#closeCodexProviderSessionsForHistoryRewrite();
|
|
4720
4727
|
|
|
4721
4728
|
// Emit session_tree event
|
|
4722
4729
|
if (this.#extensionRunner) {
|
package/src/task/executor.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Runs each subagent on the main thread and forwards AgentEvents for progress tracking.
|
|
5
5
|
*/
|
|
6
6
|
import path from "node:path";
|
|
7
|
-
import type { AgentEvent
|
|
8
|
-
import type { Api, Model, ToolChoice } from "@oh-my-pi/pi-ai";
|
|
7
|
+
import type { AgentEvent } from "@oh-my-pi/pi-agent-core";
|
|
8
|
+
import type { Api, Model, ThinkingLevel, ToolChoice } from "@oh-my-pi/pi-ai";
|
|
9
9
|
import { logger, untilAborted } from "@oh-my-pi/pi-utils";
|
|
10
10
|
import type { TSchema } from "@sinclair/typebox";
|
|
11
11
|
import Ajv, { type ValidateFunction } from "ajv";
|
|
@@ -938,12 +938,14 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
938
938
|
await modelRegistry.refresh();
|
|
939
939
|
checkAbort();
|
|
940
940
|
|
|
941
|
-
const {
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
);
|
|
946
|
-
const effectiveThinkingLevel =
|
|
941
|
+
const {
|
|
942
|
+
model,
|
|
943
|
+
thinkingLevel: resolvedThinkingLevel,
|
|
944
|
+
explicitThinkingLevel,
|
|
945
|
+
} = resolveModelOverride(modelPatterns, modelRegistry, settings);
|
|
946
|
+
const effectiveThinkingLevel = explicitThinkingLevel
|
|
947
|
+
? resolvedThinkingLevel
|
|
948
|
+
: (thinkingLevel ?? resolvedThinkingLevel);
|
|
947
949
|
|
|
948
950
|
const sessionManager = sessionFile
|
|
949
951
|
? await SessionManager.open(sessionFile)
|
package/src/task/types.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { ThinkingLevel } from "@oh-my-pi/pi-
|
|
2
|
-
import type { Usage } from "@oh-my-pi/pi-ai";
|
|
1
|
+
import type { ThinkingLevel, Usage } from "@oh-my-pi/pi-ai";
|
|
3
2
|
import { $env } from "@oh-my-pi/pi-utils";
|
|
4
3
|
import { type Static, Type } from "@sinclair/typebox";
|
|
5
4
|
import type { NestedRepoPatch } from "./worktree";
|