@oh-my-pi/pi-coding-agent 16.2.12 → 16.3.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/CHANGELOG.md +115 -7
- package/dist/cli.js +5996 -5945
- package/dist/types/advisor/config.d.ts +4 -2
- package/dist/types/collab/host.d.ts +16 -0
- package/dist/types/collab/protocol.d.ts +9 -3
- package/dist/types/commit/model-selection.d.ts +5 -0
- package/dist/types/config/model-resolver.d.ts +12 -10
- package/dist/types/config/models-config-schema.d.ts +12 -0
- package/dist/types/config/models-config.d.ts +9 -0
- package/dist/types/config/settings-schema.d.ts +28 -5
- package/dist/types/edit/modes/patch.d.ts +11 -0
- package/dist/types/eval/agent-bridge.d.ts +5 -1
- package/dist/types/exec/bash-executor.d.ts +1 -0
- package/dist/types/extensibility/legacy-pi-coding-agent-shim.d.ts +86 -2
- package/dist/types/extensibility/skills.d.ts +2 -1
- package/dist/types/mnemopi/state.d.ts +12 -0
- package/dist/types/modes/components/agent-hub.d.ts +9 -5
- package/dist/types/modes/components/status-line/component.test.d.ts +1 -0
- package/dist/types/modes/components/usage-row.d.ts +1 -1
- package/dist/types/modes/controllers/command-controller.d.ts +0 -1
- package/dist/types/modes/controllers/extension-ui-controller.d.ts +6 -0
- package/dist/types/modes/controllers/streaming-reveal.d.ts +17 -1
- package/dist/types/modes/controllers/tool-args-reveal.d.ts +30 -3
- package/dist/types/modes/interactive-mode.d.ts +12 -7
- package/dist/types/modes/rpc/rpc-client.d.ts +5 -0
- package/dist/types/modes/rpc/rpc-mode.d.ts +64 -1
- package/dist/types/modes/session-teardown.d.ts +63 -0
- package/dist/types/modes/session-teardown.test.d.ts +1 -0
- package/dist/types/modes/theme/theme.d.ts +9 -4
- package/dist/types/modes/types.d.ts +2 -3
- package/dist/types/modes/utils/copy-targets.d.ts +2 -0
- package/dist/types/plan-mode/approved-plan-prompt.test.d.ts +1 -0
- package/dist/types/sdk.d.ts +9 -0
- package/dist/types/session/agent-session.d.ts +46 -13
- package/dist/types/session/exit-diagnostics.d.ts +48 -0
- package/dist/types/session/session-loader.d.ts +5 -0
- package/dist/types/task/executor.d.ts +12 -5
- package/dist/types/task/parallel.d.ts +1 -0
- package/dist/types/task/render.test.d.ts +1 -0
- package/dist/types/thinking.d.ts +2 -0
- package/dist/types/tools/checkpoint.d.ts +8 -0
- package/dist/types/tools/eval-render.d.ts +1 -0
- package/dist/types/tools/fetch.d.ts +11 -1
- package/dist/types/tools/index.d.ts +3 -1
- package/dist/types/tools/irc.d.ts +1 -0
- package/dist/types/tools/output-meta.d.ts +7 -0
- package/dist/types/tools/output-schema-validator.d.ts +7 -4
- package/dist/types/tools/path-utils.d.ts +16 -0
- package/dist/types/tools/render-utils.d.ts +4 -1
- package/dist/types/utils/git.d.ts +47 -2
- package/dist/types/web/search/provider.d.ts +7 -0
- package/dist/types/web/search/types.d.ts +1 -1
- package/package.json +12 -12
- package/src/advisor/config.ts +4 -2
- package/src/cli/bench-cli.ts +7 -2
- package/src/collab/guest.ts +94 -5
- package/src/collab/host.ts +80 -3
- package/src/collab/protocol.ts +9 -2
- package/src/commit/model-selection.ts +8 -2
- package/src/config/keybindings.ts +3 -1
- package/src/config/model-discovery.ts +66 -2
- package/src/config/model-registry.ts +7 -3
- package/src/config/model-resolver.ts +51 -23
- package/src/config/models-config-schema.ts +13 -0
- package/src/config/settings-schema.ts +44 -14
- package/src/edit/hashline/diff.ts +13 -2
- package/src/edit/index.ts +58 -8
- package/src/edit/modes/patch.ts +53 -18
- package/src/edit/streaming.ts +7 -6
- package/src/eval/__tests__/agent-bridge.test.ts +57 -1
- package/src/eval/agent-bridge.ts +15 -5
- package/src/exec/bash-executor.ts +7 -12
- package/src/extensibility/legacy-pi-coding-agent-shim.ts +534 -16
- package/src/extensibility/skills.ts +29 -6
- package/src/goals/guided-setup.ts +4 -3
- package/src/internal-urls/docs-index.generated.txt +1 -1
- package/src/lsp/client.ts +11 -14
- package/src/main.ts +38 -10
- package/src/mnemopi/state.ts +43 -7
- package/src/modes/acp/acp-agent.ts +1 -1
- package/src/modes/components/agent-hub.ts +10 -2
- package/src/modes/components/agent-transcript-viewer.ts +39 -7
- package/src/modes/components/assistant-message.ts +16 -10
- package/src/modes/components/chat-transcript-builder.ts +11 -1
- package/src/modes/components/custom-editor.test.ts +20 -0
- package/src/modes/components/hook-selector.ts +44 -25
- package/src/modes/components/model-selector.ts +1 -1
- package/src/modes/components/status-line/component.test.ts +44 -0
- package/src/modes/components/status-line/component.ts +9 -1
- package/src/modes/components/status-line/segments.ts +3 -3
- package/src/modes/components/usage-row.ts +16 -2
- package/src/modes/controllers/command-controller.ts +6 -21
- package/src/modes/controllers/event-controller.ts +11 -9
- package/src/modes/controllers/extension-ui-controller.ts +84 -3
- package/src/modes/controllers/input-controller.ts +16 -13
- package/src/modes/controllers/selector-controller.ts +3 -8
- package/src/modes/controllers/streaming-reveal.ts +75 -53
- package/src/modes/controllers/tool-args-reveal.ts +340 -10
- package/src/modes/interactive-mode.ts +122 -79
- package/src/modes/rpc/rpc-client.ts +21 -0
- package/src/modes/rpc/rpc-mode.ts +197 -46
- package/src/modes/session-teardown.test.ts +219 -0
- package/src/modes/session-teardown.ts +82 -0
- package/src/modes/setup-wizard/scenes/theme.ts +2 -2
- package/src/modes/skill-command.ts +7 -20
- package/src/modes/theme/theme.ts +29 -15
- package/src/modes/types.ts +2 -3
- package/src/modes/utils/copy-targets.ts +12 -0
- package/src/modes/utils/ui-helpers.ts +19 -2
- package/src/plan-mode/approved-plan-prompt.test.ts +36 -0
- package/src/prompts/advisor/system.md +1 -1
- package/src/prompts/agents/tester.md +6 -2
- package/src/prompts/skills/autoload.md +8 -0
- package/src/prompts/skills/user-invocation.md +11 -0
- package/src/prompts/steering/parent-irc.md +5 -0
- package/src/prompts/system/irc-incoming.md +2 -0
- package/src/prompts/system/mid-run-todo-nudge.md +3 -0
- package/src/prompts/system/plan-mode-approved.md +7 -10
- package/src/prompts/system/plan-mode-compact-instructions.md +2 -1
- package/src/prompts/system/plan-mode-reference.md +3 -4
- package/src/prompts/system/rewind-report.md +6 -0
- package/src/prompts/system/subagent-system-prompt.md +3 -0
- package/src/prompts/tools/irc.md +2 -1
- package/src/prompts/tools/job.md +2 -2
- package/src/prompts/tools/rewind.md +3 -2
- package/src/prompts/tools/ssh.md +1 -0
- package/src/prompts/tools/task.md +4 -0
- package/src/sdk.ts +18 -4
- package/src/session/agent-session.ts +660 -114
- package/src/session/exit-diagnostics.ts +202 -0
- package/src/session/session-context.ts +25 -13
- package/src/session/session-loader.ts +58 -25
- package/src/session/session-manager.ts +0 -1
- package/src/session/session-persistence.ts +30 -4
- package/src/session/settings-stream-fn.ts +14 -0
- package/src/slash-commands/builtin-registry.ts +35 -3
- package/src/system-prompt.ts +15 -1
- package/src/task/executor.ts +31 -8
- package/src/task/index.ts +31 -9
- package/src/task/isolation-runner.ts +18 -2
- package/src/task/parallel.ts +7 -2
- package/src/task/render.test.ts +121 -0
- package/src/task/render.ts +48 -2
- package/src/task/worktree.ts +12 -13
- package/src/task/yield-assembly.ts +8 -5
- package/src/thinking.ts +5 -0
- package/src/tools/ask.ts +188 -9
- package/src/tools/ast-edit.ts +7 -0
- package/src/tools/ast-grep.ts +11 -0
- package/src/tools/bash.ts +6 -30
- package/src/tools/checkpoint.ts +15 -1
- package/src/tools/eval-render.ts +15 -0
- package/src/tools/fetch.ts +82 -18
- package/src/tools/gh.ts +1 -1
- package/src/tools/grep.ts +45 -27
- package/src/tools/index.ts +3 -1
- package/src/tools/irc.ts +24 -9
- package/src/tools/output-meta.ts +50 -0
- package/src/tools/output-schema-validator.ts +152 -15
- package/src/tools/path-utils.ts +55 -10
- package/src/tools/read.ts +1 -1
- package/src/tools/render-utils.ts +5 -3
- package/src/tools/ssh.ts +8 -1
- package/src/tools/yield.ts +41 -1
- package/src/utils/commit-message-generator.ts +2 -2
- package/src/utils/git.ts +271 -29
- package/src/utils/thinking-display.ts +13 -0
- package/src/web/search/index.ts +9 -28
- package/src/web/search/provider.ts +26 -1
- package/src/web/search/providers/duckduckgo.ts +1 -1
- package/src/web/search/types.ts +5 -1
package/src/modes/theme/theme.ts
CHANGED
|
@@ -115,6 +115,7 @@ export type SymbolKey =
|
|
|
115
115
|
| "icon.cacheMiss"
|
|
116
116
|
| "icon.input"
|
|
117
117
|
| "icon.output"
|
|
118
|
+
| "icon.throughput"
|
|
118
119
|
| "icon.host"
|
|
119
120
|
| "icon.session"
|
|
120
121
|
| "icon.package"
|
|
@@ -319,6 +320,7 @@ const UNICODE_SYMBOLS: SymbolMap = {
|
|
|
319
320
|
"icon.cacheMiss": "⊘",
|
|
320
321
|
"icon.input": "⤵",
|
|
321
322
|
"icon.output": "⤴",
|
|
323
|
+
"icon.throughput": "⚡",
|
|
322
324
|
"icon.host": "🖥",
|
|
323
325
|
"icon.session": "🆔",
|
|
324
326
|
"icon.package": "📦",
|
|
@@ -597,6 +599,8 @@ const NERD_SYMBOLS: SymbolMap = {
|
|
|
597
599
|
"icon.input": "\uf090",
|
|
598
600
|
// pick: | alt: →
|
|
599
601
|
"icon.output": "\uf08b",
|
|
602
|
+
// pick: (nf-fa-tachometer) | alt: ⚡ ↬
|
|
603
|
+
"icon.throughput": "\uf0e4",
|
|
600
604
|
// pick: | alt:
|
|
601
605
|
"icon.host": "\uf109",
|
|
602
606
|
// pick: | alt:
|
|
@@ -827,10 +831,11 @@ const ASCII_SYMBOLS: SymbolMap = {
|
|
|
827
831
|
"icon.ghost": "@",
|
|
828
832
|
"icon.agents": "AG",
|
|
829
833
|
"icon.job": "bg",
|
|
834
|
+
"icon.output": "out:",
|
|
835
|
+
"icon.throughput": "tok/s:",
|
|
830
836
|
"icon.cache": "cache",
|
|
831
837
|
"icon.cacheMiss": "!",
|
|
832
838
|
"icon.input": "in:",
|
|
833
|
-
"icon.output": "out:",
|
|
834
839
|
"icon.host": "host",
|
|
835
840
|
"icon.session": "id",
|
|
836
841
|
"icon.package": "[P]",
|
|
@@ -1820,6 +1825,7 @@ export class Theme {
|
|
|
1820
1825
|
cacheMiss: this.#symbols["icon.cacheMiss"],
|
|
1821
1826
|
input: this.#symbols["icon.input"],
|
|
1822
1827
|
output: this.#symbols["icon.output"],
|
|
1828
|
+
throughput: this.#symbols["icon.throughput"],
|
|
1823
1829
|
host: this.#symbols["icon.host"],
|
|
1824
1830
|
session: this.#symbols["icon.session"],
|
|
1825
1831
|
package: this.#symbols["icon.package"],
|
|
@@ -2151,6 +2157,11 @@ export function getCurrentThemeName(): string | undefined {
|
|
|
2151
2157
|
export function fgOrPlain(color: ThemeColor, text: string, styledText: string = text): string {
|
|
2152
2158
|
return typeof theme === "undefined" ? text : theme.fg(color, styledText);
|
|
2153
2159
|
}
|
|
2160
|
+
export interface ThemeChangeEvent {
|
|
2161
|
+
/** Preview/presentation-only changes should repaint live UI without replacing native scrollback. */
|
|
2162
|
+
ephemeral?: boolean;
|
|
2163
|
+
}
|
|
2164
|
+
|
|
2154
2165
|
var currentSymbolPresetOverride: SymbolPreset | undefined;
|
|
2155
2166
|
var currentColorBlindMode: boolean = false;
|
|
2156
2167
|
var themeWatcher: fs.FSWatcher | undefined;
|
|
@@ -2159,7 +2170,7 @@ var sigwinchHandler: (() => void) | undefined;
|
|
|
2159
2170
|
var autoDetectedTheme: boolean = false;
|
|
2160
2171
|
var autoDarkTheme: string = "dark";
|
|
2161
2172
|
var autoLightTheme: string = "light";
|
|
2162
|
-
var onThemeChangeCallback: (() => void) | undefined;
|
|
2173
|
+
var onThemeChangeCallback: ((event: ThemeChangeEvent) => void) | undefined;
|
|
2163
2174
|
var themeLoadRequestId: number = 0;
|
|
2164
2175
|
let themeEpoch = 0;
|
|
2165
2176
|
|
|
@@ -2235,7 +2246,10 @@ export async function setTheme(
|
|
|
2235
2246
|
}
|
|
2236
2247
|
}
|
|
2237
2248
|
|
|
2238
|
-
export async function previewTheme(
|
|
2249
|
+
export async function previewTheme(
|
|
2250
|
+
name: string,
|
|
2251
|
+
event: ThemeChangeEvent = { ephemeral: true },
|
|
2252
|
+
): Promise<{ success: boolean; error?: string }> {
|
|
2239
2253
|
const requestId = ++themeLoadRequestId;
|
|
2240
2254
|
try {
|
|
2241
2255
|
const loadedTheme = await loadTheme(name, getCurrentThemeOptions());
|
|
@@ -2243,7 +2257,7 @@ export async function previewTheme(name: string): Promise<{ success: boolean; er
|
|
|
2243
2257
|
return { success: false, error: "Theme preview superseded by a newer request" };
|
|
2244
2258
|
}
|
|
2245
2259
|
theme = loadedTheme;
|
|
2246
|
-
notifyThemeChange();
|
|
2260
|
+
notifyThemeChange(event);
|
|
2247
2261
|
return { success: true };
|
|
2248
2262
|
} catch (error) {
|
|
2249
2263
|
if (requestId !== themeLoadRequestId) {
|
|
@@ -2259,9 +2273,9 @@ export async function previewTheme(name: string): Promise<{ success: boolean; er
|
|
|
2259
2273
|
/**
|
|
2260
2274
|
* Enable auto-detection mode, switching to the appropriate dark/light theme.
|
|
2261
2275
|
*/
|
|
2262
|
-
export function enableAutoTheme(): void {
|
|
2276
|
+
export function enableAutoTheme(event: ThemeChangeEvent = {}): void {
|
|
2263
2277
|
autoDetectedTheme = true;
|
|
2264
|
-
reevaluateAutoTheme("enableAutoTheme");
|
|
2278
|
+
reevaluateAutoTheme("enableAutoTheme", event);
|
|
2265
2279
|
}
|
|
2266
2280
|
|
|
2267
2281
|
/**
|
|
@@ -2290,7 +2304,7 @@ export function setThemeInstance(themeInstance: Theme): void {
|
|
|
2290
2304
|
theme = themeInstance;
|
|
2291
2305
|
currentThemeName = "<in-memory>";
|
|
2292
2306
|
stopThemeWatcher();
|
|
2293
|
-
notifyThemeChange();
|
|
2307
|
+
notifyThemeChange({ ephemeral: true });
|
|
2294
2308
|
}
|
|
2295
2309
|
|
|
2296
2310
|
/**
|
|
@@ -2311,7 +2325,7 @@ export async function setSymbolPreset(preset: SymbolPreset): Promise<void> {
|
|
|
2311
2325
|
theme = await loadTheme("dark", getCurrentThemeOptions());
|
|
2312
2326
|
if (requestId !== themeLoadRequestId) return;
|
|
2313
2327
|
}
|
|
2314
|
-
notifyThemeChange();
|
|
2328
|
+
notifyThemeChange({ ephemeral: true });
|
|
2315
2329
|
}
|
|
2316
2330
|
|
|
2317
2331
|
/**
|
|
@@ -2340,7 +2354,7 @@ export async function setColorBlindMode(enabled: boolean): Promise<void> {
|
|
|
2340
2354
|
theme = await loadTheme("dark", getCurrentThemeOptions());
|
|
2341
2355
|
if (requestId !== themeLoadRequestId) return;
|
|
2342
2356
|
}
|
|
2343
|
-
notifyThemeChange();
|
|
2357
|
+
notifyThemeChange({ ephemeral: true });
|
|
2344
2358
|
}
|
|
2345
2359
|
|
|
2346
2360
|
/**
|
|
@@ -2350,7 +2364,7 @@ export function getColorBlindMode(): boolean {
|
|
|
2350
2364
|
return currentColorBlindMode;
|
|
2351
2365
|
}
|
|
2352
2366
|
|
|
2353
|
-
export function onThemeChange(callback: () => void): () => void {
|
|
2367
|
+
export function onThemeChange(callback: (event: ThemeChangeEvent) => void): () => void {
|
|
2354
2368
|
onThemeChangeCallback = callback;
|
|
2355
2369
|
return () => {
|
|
2356
2370
|
if (onThemeChangeCallback === callback) {
|
|
@@ -2371,9 +2385,9 @@ export function getThemeEpoch(): number {
|
|
|
2371
2385
|
}
|
|
2372
2386
|
|
|
2373
2387
|
/** Bump the theme epoch and notify the registered theme-change listener. */
|
|
2374
|
-
function notifyThemeChange(): void {
|
|
2388
|
+
function notifyThemeChange(event: ThemeChangeEvent = {}): void {
|
|
2375
2389
|
themeEpoch++;
|
|
2376
|
-
onThemeChangeCallback?.();
|
|
2390
|
+
onThemeChangeCallback?.(event);
|
|
2377
2391
|
}
|
|
2378
2392
|
|
|
2379
2393
|
/**
|
|
@@ -2428,7 +2442,7 @@ async function startThemeWatcher(): Promise<void> {
|
|
|
2428
2442
|
loadTheme(watchedThemeName, getCurrentThemeOptions())
|
|
2429
2443
|
.then(loadedTheme => {
|
|
2430
2444
|
theme = loadedTheme;
|
|
2431
|
-
notifyThemeChange();
|
|
2445
|
+
notifyThemeChange({ ephemeral: true });
|
|
2432
2446
|
})
|
|
2433
2447
|
.catch(() => {
|
|
2434
2448
|
// Ignore errors (file might be in invalid state while being edited)
|
|
@@ -2460,7 +2474,7 @@ async function startThemeWatcher(): Promise<void> {
|
|
|
2460
2474
|
* Shared logic for re-evaluating the auto-detected theme.
|
|
2461
2475
|
* Called from SIGWINCH, terminal appearance change handler, and macOS fallback observer.
|
|
2462
2476
|
*/
|
|
2463
|
-
function reevaluateAutoTheme(debugLabel: string): void {
|
|
2477
|
+
function reevaluateAutoTheme(debugLabel: string, event: ThemeChangeEvent = {}): void {
|
|
2464
2478
|
if (!autoDetectedTheme) return;
|
|
2465
2479
|
const resolved = getDefaultTheme();
|
|
2466
2480
|
if (resolved === currentThemeName) return;
|
|
@@ -2468,7 +2482,7 @@ function reevaluateAutoTheme(debugLabel: string): void {
|
|
|
2468
2482
|
loadTheme(resolved, getCurrentThemeOptions())
|
|
2469
2483
|
.then(loadedTheme => {
|
|
2470
2484
|
theme = loadedTheme;
|
|
2471
|
-
notifyThemeChange();
|
|
2485
|
+
notifyThemeChange(event);
|
|
2472
2486
|
})
|
|
2473
2487
|
.catch(err => {
|
|
2474
2488
|
logger.debug(`Theme switch on ${debugLabel} failed`, { error: String(err) });
|
package/src/modes/types.ts
CHANGED
|
@@ -14,6 +14,7 @@ import type {
|
|
|
14
14
|
ExtensionWidgetOptions,
|
|
15
15
|
} from "../extensibility/extensions";
|
|
16
16
|
import type { CompactOptions } from "../extensibility/extensions/types";
|
|
17
|
+
import type { Skill } from "../extensibility/skills";
|
|
17
18
|
import type { MCPManager } from "../mcp";
|
|
18
19
|
import type { PlanApprovalDetails } from "../plan-mode/approved-plan";
|
|
19
20
|
import type { AgentSession } from "../session/agent-session";
|
|
@@ -129,7 +130,6 @@ export interface InteractiveModeContext {
|
|
|
129
130
|
historyStorage?: HistoryStorage;
|
|
130
131
|
mcpManager?: MCPManager;
|
|
131
132
|
lspServers?: LspStartupServerInfo[];
|
|
132
|
-
titleSystemPrompt?: string;
|
|
133
133
|
collabHost?: CollabHost;
|
|
134
134
|
collabGuest?: CollabGuestLink;
|
|
135
135
|
eventController: EventController;
|
|
@@ -205,7 +205,7 @@ export interface InteractiveModeContext {
|
|
|
205
205
|
lastStatusSpacer: Spacer | undefined;
|
|
206
206
|
lastStatusText: Text | undefined;
|
|
207
207
|
fileSlashCommands: Set<string>;
|
|
208
|
-
skillCommands: Map<string,
|
|
208
|
+
skillCommands: Map<string, Skill>;
|
|
209
209
|
oauthManualInput: OAuthManualInputManager;
|
|
210
210
|
todoPhases: TodoPhase[];
|
|
211
211
|
|
|
@@ -297,7 +297,6 @@ export interface InteractiveModeContext {
|
|
|
297
297
|
getUserMessageText(message: Message): string;
|
|
298
298
|
findLastAssistantMessage(): AssistantMessage | undefined;
|
|
299
299
|
extractAssistantText(message: AssistantMessage): string;
|
|
300
|
-
updateEditorTopBorder(): void;
|
|
301
300
|
/** Refresh the running-subagents status badge from the active local or collab registry. */
|
|
302
301
|
syncRunningSubagentBadge(): void;
|
|
303
302
|
updateEditorBorderColor(): void;
|
|
@@ -118,6 +118,18 @@ export function extractCodeBlocks(text: string): CodeBlock[] {
|
|
|
118
118
|
.map(b => ({ lang: b.lang, code: b.code }));
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
+
/** Walk the transcript backwards for the most recent fenced assistant code block. */
|
|
122
|
+
export function extractLastCodeBlock(messages: readonly AgentMessage[]): CodeBlock | undefined {
|
|
123
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
124
|
+
const msg = messages[i];
|
|
125
|
+
const text = assistantText(msg);
|
|
126
|
+
if (!text) continue;
|
|
127
|
+
const blocks = extractCodeBlocks(text);
|
|
128
|
+
if (blocks.length > 0) return blocks[blocks.length - 1];
|
|
129
|
+
}
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
|
|
121
133
|
/** Extract `>`-quoted blocks from assistant markdown, in document order. */
|
|
122
134
|
export function extractQuoteBlocks(text: string): QuoteBlock[] {
|
|
123
135
|
return extractBlocks(text)
|
|
@@ -34,6 +34,7 @@ import { ToolExecutionComponent } from "../../modes/components/tool-execution";
|
|
|
34
34
|
import { TranscriptBlock } from "../../modes/components/transcript-container";
|
|
35
35
|
import { createUsageRowBlock } from "../../modes/components/usage-row";
|
|
36
36
|
import { UserMessageComponent } from "../../modes/components/user-message";
|
|
37
|
+
import { decodeStreamedToolArgs, streamingStringKeysForTool } from "../../modes/controllers/tool-args-reveal";
|
|
37
38
|
import { materializeImageReferenceLinksSync } from "../../modes/image-references";
|
|
38
39
|
import { theme } from "../../modes/theme/theme";
|
|
39
40
|
import type { CompactionQueuedMessage, InteractiveModeContext } from "../../modes/types";
|
|
@@ -296,12 +297,16 @@ export class UiHelpers {
|
|
|
296
297
|
// read run so the row sits under it. Mirrors the live path, where the read
|
|
297
298
|
// group is created during streaming and the row is appended below it.
|
|
298
299
|
let pendingUsage: Usage | undefined;
|
|
300
|
+
let pendingUsageDuration: number | undefined;
|
|
301
|
+
let pendingUsageTtft: number | undefined;
|
|
299
302
|
const flushPendingUsage = () => {
|
|
300
303
|
if (!pendingUsage) return;
|
|
301
304
|
readGroup?.seal();
|
|
302
305
|
readGroup = null;
|
|
303
|
-
this.ctx.chatContainer.addChild(createUsageRowBlock(pendingUsage));
|
|
306
|
+
this.ctx.chatContainer.addChild(createUsageRowBlock(pendingUsage, pendingUsageDuration, pendingUsageTtft));
|
|
304
307
|
pendingUsage = undefined;
|
|
308
|
+
pendingUsageDuration = undefined;
|
|
309
|
+
pendingUsageTtft = undefined;
|
|
305
310
|
};
|
|
306
311
|
// Rebuild-time mirror of the event controller's displaceable-poll
|
|
307
312
|
// bookkeeping: a `job` poll that found every watched job still running is
|
|
@@ -412,8 +417,18 @@ export class UiHelpers {
|
|
|
412
417
|
readGroup = null;
|
|
413
418
|
const tool = this.ctx.viewSession.getToolByName(content.name);
|
|
414
419
|
const partialJson = getStreamingPartialJson(content);
|
|
420
|
+
// Mid-stream rebuild (theme change, settings, focus replay): decode
|
|
421
|
+
// display args from the raw stream exactly like the live reveal path.
|
|
422
|
+
// The provider-parsed `arguments` lag the stream by up to a throttled
|
|
423
|
+
// parse window, so spreading them alone would freeze a long write/edit
|
|
424
|
+
// preview at its last full parse.
|
|
425
|
+
const rawInput = content.customWireName !== undefined;
|
|
415
426
|
const renderArgs = partialJson
|
|
416
|
-
?
|
|
427
|
+
? decodeStreamedToolArgs(partialJson, {
|
|
428
|
+
rawInput,
|
|
429
|
+
fullArgs: content.arguments,
|
|
430
|
+
streamingStringKeys: streamingStringKeysForTool(content.name, rawInput),
|
|
431
|
+
})
|
|
417
432
|
: content.arguments;
|
|
418
433
|
const component = new ToolExecutionComponent(
|
|
419
434
|
content.name,
|
|
@@ -444,6 +459,8 @@ export class UiHelpers {
|
|
|
444
459
|
}
|
|
445
460
|
}
|
|
446
461
|
pendingUsage = this.ctx.settings.get("display.showTokenUsage") ? message.usage : undefined;
|
|
462
|
+
pendingUsageDuration = message.duration;
|
|
463
|
+
pendingUsageTtft = message.ttft;
|
|
447
464
|
} else if (message.role === "toolResult") {
|
|
448
465
|
const pendingReadComponent = this.ctx.pendingTools.get(message.toolCallId);
|
|
449
466
|
const isReadGroupResult =
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { describe, expect, it } from "bun:test";
|
|
2
|
+
import { prompt } from "@oh-my-pi/pi-utils";
|
|
3
|
+
import planModeApprovedPrompt from "../prompts/system/plan-mode-approved.md" with { type: "text" };
|
|
4
|
+
import planModeCompactInstructionsPrompt from "../prompts/system/plan-mode-compact-instructions.md" with {
|
|
5
|
+
type: "text",
|
|
6
|
+
};
|
|
7
|
+
import planModeReferencePrompt from "../prompts/system/plan-mode-reference.md" with { type: "text" };
|
|
8
|
+
|
|
9
|
+
const PLAN_FILE_PATH = "local://durable-plan.md";
|
|
10
|
+
const PLAN_SENTINEL = "SENTINEL_HEADROOM_COMPRESSED_PLAN_CONTENT";
|
|
11
|
+
|
|
12
|
+
describe("approved plan execution prompts", () => {
|
|
13
|
+
it("requires reading the durable plan file without inlining plan content", () => {
|
|
14
|
+
const approved = prompt.render(planModeApprovedPrompt, {
|
|
15
|
+
planContent: PLAN_SENTINEL,
|
|
16
|
+
planFilePath: PLAN_FILE_PATH,
|
|
17
|
+
contextPreserved: false,
|
|
18
|
+
});
|
|
19
|
+
const reference = prompt.render(planModeReferencePrompt, {
|
|
20
|
+
planContent: PLAN_SENTINEL,
|
|
21
|
+
planFilePath: PLAN_FILE_PATH,
|
|
22
|
+
});
|
|
23
|
+
const compact = prompt.render(planModeCompactInstructionsPrompt, {
|
|
24
|
+
planFilePath: PLAN_FILE_PATH,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
for (const rendered of [approved, reference, compact]) {
|
|
28
|
+
expect(rendered).toContain(PLAN_FILE_PATH);
|
|
29
|
+
}
|
|
30
|
+
for (const rendered of [approved, reference, compact]) {
|
|
31
|
+
expect(rendered).not.toContain(PLAN_SENTINEL);
|
|
32
|
+
}
|
|
33
|
+
expect(approved).toContain("MUST read `local://durable-plan.md`");
|
|
34
|
+
expect(reference).toContain("MUST read `local://durable-plan.md`");
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -14,7 +14,7 @@ Offer that view before they sink work into the wrong direction.
|
|
|
14
14
|
|
|
15
15
|
<workflow>
|
|
16
16
|
You receive the agent's transcript incrementally, including their thoughts.
|
|
17
|
-
|
|
17
|
+
Use the tools this session grants you to verify suspicions — by default read-only lookup (`read`, `grep`, `glob`); operators may extend the grant via `WATCHDOG.yml`. Advising is your primary channel; touch mutating tools (when granted) only when a verify step genuinely needs them.
|
|
18
18
|
Keep exploration lean:
|
|
19
19
|
- 2–3 tool calls per advise.
|
|
20
20
|
- Exception: critical bugs may need deeper verification before raising a blocker.
|
|
@@ -22,6 +22,8 @@ A test suite is a liability until it pays for itself. Every worthless test is ne
|
|
|
22
22
|
- Mutation test in your head: if a plausible bug — a flipped condition, an off-by-one, a wrong return value, a dropped case — would still let the test PASS, the test is worthless. Discard it.
|
|
23
23
|
- You NEVER write tests that assert plumbing or restate the implementation. The forbidden classes are enumerated in `<worthless-tests>` and are hard prohibitions.
|
|
24
24
|
- You MUST match the repo's existing test conventions — framework, file layout, naming, assertion style. A second convention beside an existing one is PROHIBITED.
|
|
25
|
+
- NEVER test defaults (configurations, fallback values, or default environment values). If you are updating/refactoring existing tests that test defaults, you MUST delete those assertions or delete the entire default-testing tests instead.
|
|
26
|
+
- You are explicitly ALLOWED to write **no tests at all** if you were spawned for a stupid reason (meaning: the change is trivial—such as docs, comments, types, exports, or simple config; the behavior is already fully covered; or any tests you would write would be worthless, restate plumbing, or test defaults). If so, state this clearly and exit.
|
|
25
27
|
</critical>
|
|
26
28
|
|
|
27
29
|
<anti-patterns name="worthless-tests">
|
|
@@ -33,7 +35,7 @@ NEVER write any of these. Each is a green check that survives real bugs:
|
|
|
33
35
|
- **Construction smoke.** "Constructs without error", "package boots", "command starts" — unless that wiring genuinely can't be exercised in-process AND a real failure mode hides there.
|
|
34
36
|
- **Mock round-trips.** Asserting a mock was called with the args you just passed it. You tested the mock, not the system.
|
|
35
37
|
- **Existence/shape-only.** Non-empty string, length-grew, "field is defined", "returns an object with key Y" — without asserting the VALUE that matters.
|
|
36
|
-
- **Default
|
|
38
|
+
- **Default values.** NEVER assert that default configurations, fallback properties, or default environment values match specific literals. A harmless change to a default setting must never break the tests. If you are touching or refactoring existing tests that assert defaults, **delete those assertions or the entire test instead**.
|
|
37
39
|
- **Field-wiring.** Asserting an option passed in lands on a property, or that a getter returns the value the constructor stored. Test the downstream BEHAVIOR that depends on it, not the assignment.
|
|
38
40
|
- **Duplicate-layer coverage.** Re-proving through mocks what an integration test already proves. Drop the narrower restatement.
|
|
39
41
|
|
|
@@ -103,5 +105,7 @@ Tests MUST be full-suite safe and order-independent, not merely file-local safe.
|
|
|
103
105
|
- A test exists to FAIL on a real bug. No nameable contract, or no plausible bug would redden it → NEVER write it.
|
|
104
106
|
- NEVER assert plumbing, restate the implementation, or grep the source. Test observable behavior through the public surface.
|
|
105
107
|
- No timing races, no environment pollution, deterministic and order-independent — full-suite safe.
|
|
106
|
-
-
|
|
108
|
+
- NEVER test defaults. If updating tests that do, delete them instead.
|
|
109
|
+
- You are explicitly ALLOWED to write **no tests at all** if you were spawned for a stupid reason (trivial changes, already covered, or if any possible test would be worthless/test defaults).
|
|
110
|
+
- You MUST keep going until the tests are written, passing, and proven to have teeth (unless skipped per above).
|
|
107
111
|
</critical>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
[IMPORTANT: The user has invoked the "{{name}}" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]
|
|
2
|
+
|
|
3
|
+
{{body}}
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
[Skill directory: {{baseDir}}]
|
|
8
|
+
Resolve any relative paths in this skill (e.g. `scripts/foo.js`, `templates/config.yaml`) against that directory using its absolute path: read referenced assets and templates, and run scripts with the terminal tool when the skill's instructions call for it.
|
|
9
|
+
{{#if userArgs}}
|
|
10
|
+
User: {{userArgs}}
|
|
11
|
+
{{/if}}
|
|
@@ -3,5 +3,7 @@ Incoming IRC message from agent `{{from}}`{{#if replyTo}} (replying to {{replyTo
|
|
|
3
3
|
|
|
4
4
|
{{message}}
|
|
5
5
|
|
|
6
|
+
{{#if interrupting}}An agent sent this while you were waiting or working. Any active interruptible wait was stopped early so you can read it now.{{/if}}
|
|
7
|
+
|
|
6
8
|
{{#if autoReplied}}You are mid-task, so a side-channel auto-reply was generated from your context and delivered to `{{from}}` on your behalf (recorded after this message). Follow up with the `irc` tool (`op: "send"`, `to: "{{from}}"`) only if that auto-reply needs correcting.{{else}}If a response is expected, reply with the `irc` tool (`op: "send"`, `to: "{{from}}"`) — you may finish your current step first. Nobody replies on your behalf.{{/if}}
|
|
7
9
|
</irc>
|
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
Plan approved.
|
|
2
2
|
{{#if contextPreserved}}
|
|
3
|
-
- Context preserved. Use conversation history when useful;
|
|
3
|
+
- Context preserved. Use conversation history when useful; the plan file is the source of truth if it conflicts with earlier exploration.
|
|
4
4
|
{{/if}}
|
|
5
5
|
|
|
6
6
|
<instruction>
|
|
7
|
-
You MUST
|
|
7
|
+
You MUST read `{{planFilePath}}` before executing.
|
|
8
|
+
The file content is the authoritative plan; visible/compressed context is secondary.
|
|
9
|
+
Read failure? Report the exact path and error instead of guessing.
|
|
10
|
+
After reading, you MUST execute the plan step by step with full tool access.
|
|
8
11
|
You MUST verify each step before proceeding to the next.
|
|
9
12
|
{{#has tools "todo"}}
|
|
10
|
-
|
|
13
|
+
After reading the plan, initialize todo tracking with `todo`.
|
|
11
14
|
After each completed step, immediately update `todo`.
|
|
12
15
|
If `todo` fails, fix the payload and retry before continuing.
|
|
13
16
|
{{/has}}
|
|
14
|
-
The plan path is for subagent handoff only. You already have the plan; NEVER read it.
|
|
15
17
|
</instruction>
|
|
16
18
|
|
|
17
|
-
The full plan is injected below. You MUST execute it now:
|
|
18
|
-
|
|
19
|
-
<plan path="{{planFilePath}}">
|
|
20
|
-
{{planContent}}
|
|
21
|
-
</plan>
|
|
22
|
-
|
|
23
19
|
<critical>
|
|
20
|
+
NEVER stop because inline plan content is compressed, expired, or unrecoverable. Read `{{planFilePath}}`.
|
|
24
21
|
You MUST keep going until complete. This matters.
|
|
25
22
|
</critical>
|
|
@@ -12,5 +12,6 @@ You MUST drop:
|
|
|
12
12
|
- Restated context already present in the plan file.
|
|
13
13
|
|
|
14
14
|
{{#if planFilePath}}
|
|
15
|
-
The approved plan file is at `{{planFilePath}}`; it is the authoritative source of truth
|
|
15
|
+
The approved plan file is at `{{planFilePath}}`; it is the authoritative source of truth.
|
|
16
|
+
You MUST preserve this durable path and the fact that the executor must read it directly after compaction.
|
|
16
17
|
{{/if}}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
## Existing Plan
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
{{planContent}}
|
|
5
|
-
</plan>
|
|
3
|
+
The approved plan file is at `{{planFilePath}}`.
|
|
6
4
|
|
|
7
5
|
<instruction>
|
|
8
6
|
If this plan is relevant to current work and not complete, you MUST continue executing it.
|
|
7
|
+
If you do not have the current plan content in visible context, you MUST read `{{planFilePath}}`.
|
|
9
8
|
If the plan is stale or unrelated, you MUST ignore it.
|
|
10
|
-
|
|
9
|
+
NEVER stop because inline plan content is compressed, expired, or unrecoverable. Read the file.
|
|
11
10
|
</instruction>
|
|
@@ -61,6 +61,9 @@ Yield protocol:
|
|
|
61
61
|
|
|
62
62
|
This is your only way to return a final result. For structured results, you NEVER put JSON in plain text or substitute a text summary for `result.data`.
|
|
63
63
|
|
|
64
|
+
{{#if outputSchemaOverridesAgent}}
|
|
65
|
+
Caller schema overrides agent-native output instructions. Ignore ROLE-provided output/yield labels, field names, examples, and procedures that conflict with the interface below. Use ONLY labels/fields from the caller schema; safest path: omit `type` and terminal-yield the full `result.data` object.
|
|
66
|
+
{{/if}}
|
|
64
67
|
{{#if outputSchema}}
|
|
65
68
|
Your terminal `yield` MUST use exactly this shape — the schema fields go inside `result.data`, NEVER at the top level and NEVER as a stringified summary:
|
|
66
69
|
```ts
|
package/src/prompts/tools/irc.md
CHANGED
|
@@ -12,7 +12,8 @@ Use `op: "send"` to deliver a message to a specific peer or broadcast to `"all"`
|
|
|
12
12
|
|
|
13
13
|
# Waiting and Inboxes
|
|
14
14
|
Messages only arrive when the peer actively sends one—do not interrogate a peer for status.
|
|
15
|
-
- If you are completely blocked and MUST wait for an answer, use `op: "wait"` (or `await: true` on a send).
|
|
15
|
+
- If you are completely blocked and MUST wait for an answer, use `op: "wait"` (or `await: true` on a send). The wait returns when a matching message arrives, the timeout elapses, or any IRC / steering message interrupts the wait. Parent-agent IRC interrupts with steering-level priority.
|
|
16
|
+
- No need to alternate `irc wait`, `irc inbox`, and `job poll`: waits surface cross-channel interrupts promptly. The next turn includes the interrupt reason and message.
|
|
16
17
|
- To check for messages without blocking, use `op: "inbox"` to drain your queue.
|
|
17
18
|
|
|
18
19
|
# When to Coordinate
|
package/src/prompts/tools/job.md
CHANGED
|
@@ -4,8 +4,8 @@ Background tasks deliver their results automatically the moment they finish. You
|
|
|
4
4
|
|
|
5
5
|
# Interventions
|
|
6
6
|
|
|
7
|
-
- **Block and wait:** Pass `poll` with specific job IDs when you are completely blocked and cannot do any other work. The call returns as soon as one watched job finishes
|
|
7
|
+
- **Block and wait:** Pass `poll` with specific job IDs when you are completely blocked and cannot do any other work. The call returns as soon as one watched job finishes, the wait window elapses, or an IRC / steering message interrupts the wait — NOT when all jobs finish; re-issue to keep waiting.
|
|
8
8
|
- To watch EVERY running job, issue a call with NO fields at all (no `poll`, no `cancel`, no `list`). NEVER pass an array of every running ID.
|
|
9
|
-
- A finished job's output is included in the
|
|
9
|
+
- A finished job's output, or the interrupting message and reason, is included in the next turn.
|
|
10
10
|
- **Stop execution:** Pass `cancel` with job IDs to kill jobs that have hung, stalled, or are no longer needed. A cancel-only call returns immediately.
|
|
11
11
|
- **Snapshot:** Pass `list: true` to get the current status of all jobs without waiting.
|
|
@@ -9,5 +9,6 @@ Requirements:
|
|
|
9
9
|
- You MUST call this before yielding if a checkpoint is active.
|
|
10
10
|
|
|
11
11
|
Behavior:
|
|
12
|
-
- If no checkpoint is active, this tool errors.
|
|
13
|
-
- On success, the session rewinds
|
|
12
|
+
- If no checkpoint is active, this tool errors. If the checkpoint already rewound, continue from the retained report instead of retrying.
|
|
13
|
+
- On success, the session rewinds, keeps your report as retained context, and closes the checkpoint.
|
|
14
|
+
- A successful rewind is final for that checkpoint; repeat calls error.
|
package/src/prompts/tools/ssh.md
CHANGED
|
@@ -4,7 +4,11 @@ Execution blocks your turn: the call only returns once the work is completely fi
|
|
|
4
4
|
|
|
5
5
|
# Delegation Strategy
|
|
6
6
|
- **Maximize parallelism:** Break work into the widest possible {{#if batchEnabled}}array of `tasks[]`{{else}}set of parallel `task` calls{{/if}}. NEVER serialize work that can run concurrently. Tasks touching different files or independent refactors should run in parallel; agents resolve their own file collisions live.
|
|
7
|
+
{{#when MAX_CONCURRENCY ">" 0}}
|
|
8
|
+
- **Concurrency cap:** At most {{pluralize MAX_CONCURRENCY "subagent" "subagents"}} run at once in this session — anything beyond that just queues, so a {{#if batchEnabled}}`tasks[]` batch{{else}}set of parallel `task` calls{{/if}} larger than {{MAX_CONCURRENCY}} only delays results. Keep the fan-out at or under the cap.
|
|
9
|
+
{{/when}}
|
|
7
10
|
- **Sequence only when necessary:** The only reason to run A before B is if B strictly requires A's output to function (e.g., a core API contract or schema migration). {{#if ircEnabled}}If the missing piece is small, run them in parallel and have B ask A via `irc`!{{/if}}
|
|
11
|
+
{{#if ircEnabled}}- **Steering delivery:** Parent-to-subagent IRC is delivered immediately as steering; subagents blocked in `job poll` / `irc wait` do not need to poll separately for it.{{/if}}
|
|
8
12
|
- **Role matching:** Assign each subagent a specific `role` (e.g. "Security Reviewer", "DB Migrator"). Do not spawn generic workers.
|
|
9
13
|
- **No overhead:** Each assignment MUST instruct its agent to skip formatters, linters, and project-wide test suites. You will run those once at the end.
|
|
10
14
|
- **One-pass agents:** Prefer agents that investigate **and** edit in a single pass; only spin a read-only discovery step (e.g. `explore`) when the affected files are genuinely unknown.
|
package/src/sdk.ts
CHANGED
|
@@ -135,6 +135,7 @@ import { wrapStreamFnWithProviderConcurrency } from "./task/provider-concurrency
|
|
|
135
135
|
import {
|
|
136
136
|
AUTO_THINKING,
|
|
137
137
|
type ConfiguredThinkingLevel,
|
|
138
|
+
concreteThinkingLevel,
|
|
138
139
|
parseConfiguredThinkingLevel,
|
|
139
140
|
parseThinkingLevel,
|
|
140
141
|
resolveProvisionalAutoLevel,
|
|
@@ -404,6 +405,15 @@ export interface CreateAgentSessionOptions {
|
|
|
404
405
|
customSystemPrompt?: string;
|
|
405
406
|
/** Already-loaded text appended through the bundled system prompt templates. */
|
|
406
407
|
appendSystemPrompt?: string;
|
|
408
|
+
/**
|
|
409
|
+
* Already-loaded title-generation system prompt override (typically
|
|
410
|
+
* {@link discoverTitleSystemPromptFile} → {@link resolvePromptInput}). When
|
|
411
|
+
* set, every automatic session-title generation path on this session — the
|
|
412
|
+
* first-input title and the replan-driven refresh — uses this prompt
|
|
413
|
+
* instead of the bundled default. Refresh on cwd change via
|
|
414
|
+
* {@link AgentSession.setTitleSystemPrompt}.
|
|
415
|
+
*/
|
|
416
|
+
titleSystemPrompt?: string;
|
|
407
417
|
/** Optional provider-facing session identifier for prompt caches and sticky auth selection.
|
|
408
418
|
* Keeps persisted session files isolated while reusing provider-side caches. */
|
|
409
419
|
providerSessionId?: string;
|
|
@@ -1258,7 +1268,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1258
1268
|
? getRestorableSessionModels(existingSession.models, sessionManager.getLastModelChangeRole())
|
|
1259
1269
|
: [];
|
|
1260
1270
|
let restoredSessionModelIndex = -1;
|
|
1261
|
-
let restoredSessionThinkingLevel:
|
|
1271
|
+
let restoredSessionThinkingLevel: ConfiguredThinkingLevel | undefined;
|
|
1262
1272
|
if (!hasExplicitModel && !model && sessionModelStrings.length > 0) {
|
|
1263
1273
|
logger.time("restoreSessionModel", () => {
|
|
1264
1274
|
let failedSessionModel: string | undefined;
|
|
@@ -1266,6 +1276,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1266
1276
|
const sessionModelStr = sessionModelStrings[i];
|
|
1267
1277
|
const parsedModel = parseModelString(sessionModelStr, {
|
|
1268
1278
|
allowMaxAlias: true,
|
|
1279
|
+
allowAutoAlias: true,
|
|
1269
1280
|
isLiteralModelId: (provider, id) => modelRegistry.find(provider, id) !== undefined,
|
|
1270
1281
|
});
|
|
1271
1282
|
if (!parsedModel) {
|
|
@@ -1333,7 +1344,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1333
1344
|
// Concrete level the agent/session start with. With `auto` this is the
|
|
1334
1345
|
// provisional level shown until the first per-turn classification resolves;
|
|
1335
1346
|
// `auto` itself stays a session-only concept handled by AgentSession.
|
|
1336
|
-
let effectiveThinkingLevel: ThinkingLevel | undefined = thinkingLevel
|
|
1347
|
+
let effectiveThinkingLevel: ThinkingLevel | undefined = concreteThinkingLevel(thinkingLevel);
|
|
1337
1348
|
if (model) {
|
|
1338
1349
|
const resolvedModel = model;
|
|
1339
1350
|
effectiveThinkingLevel = logger.time("resolveThinkingLevelForModel", () =>
|
|
@@ -1567,6 +1578,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1567
1578
|
activateDiscoveredTools: toolNames => session.activateDiscoveredTools(toolNames),
|
|
1568
1579
|
getCheckpointState: () => session.getCheckpointState(),
|
|
1569
1580
|
setCheckpointState: state => session.setCheckpointState(state ?? undefined),
|
|
1581
|
+
getLastCompletedRewind: () => session.getLastCompletedRewind(),
|
|
1570
1582
|
getToolChoiceQueue: () => session.toolChoiceQueue,
|
|
1571
1583
|
buildToolChoice: name => {
|
|
1572
1584
|
const m = session.model;
|
|
@@ -1916,6 +1928,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1916
1928
|
const sessionModelStr = sessionModelStrings[i];
|
|
1917
1929
|
const parsedModel = parseModelString(sessionModelStr, {
|
|
1918
1930
|
allowMaxAlias: true,
|
|
1931
|
+
allowAutoAlias: true,
|
|
1919
1932
|
isLiteralModelId: (provider, id) => modelRegistry.find(provider, id) !== undefined,
|
|
1920
1933
|
});
|
|
1921
1934
|
if (!parsedModel) continue;
|
|
@@ -1930,7 +1943,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1930
1943
|
// `thinking.defaultLevel` must not become sticky.
|
|
1931
1944
|
thinkingLevel = pickInitialThinkingLevel(restoredModel);
|
|
1932
1945
|
autoThinking = thinkingLevel === AUTO_THINKING;
|
|
1933
|
-
effectiveThinkingLevel = thinkingLevel
|
|
1946
|
+
effectiveThinkingLevel = concreteThinkingLevel(thinkingLevel);
|
|
1934
1947
|
effectiveThinkingLevel = logger.time("resolveThinkingLevelForModel", () =>
|
|
1935
1948
|
autoThinking
|
|
1936
1949
|
? resolveProvisionalAutoLevel(restoredModel)
|
|
@@ -1986,7 +1999,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1986
1999
|
// so the role's explicit selector (e.g. `:max`) now applies.
|
|
1987
2000
|
thinkingLevel = pickInitialThinkingLevel(resolvedDefaultModel);
|
|
1988
2001
|
autoThinking = thinkingLevel === AUTO_THINKING;
|
|
1989
|
-
effectiveThinkingLevel = thinkingLevel
|
|
2002
|
+
effectiveThinkingLevel = concreteThinkingLevel(thinkingLevel);
|
|
1990
2003
|
effectiveThinkingLevel = logger.time("resolveThinkingLevelForModel", () =>
|
|
1991
2004
|
autoThinking
|
|
1992
2005
|
? resolveProvisionalAutoLevel(resolvedDefaultModel)
|
|
@@ -2744,6 +2757,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2744
2757
|
providerSessionId: options.providerSessionId,
|
|
2745
2758
|
parentEvalSessionId: options.parentEvalSessionId,
|
|
2746
2759
|
advisorTools,
|
|
2760
|
+
titleSystemPrompt: options.titleSystemPrompt,
|
|
2747
2761
|
});
|
|
2748
2762
|
hasSession = true;
|
|
2749
2763
|
if (asyncJobManager) {
|