@oh-my-pi/pi-coding-agent 15.9.5 → 15.10.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 +98 -1
- package/dist/types/cli/args.d.ts +1 -1
- package/dist/types/cli/gallery-cli.d.ts +43 -0
- package/dist/types/cli/gallery-fixtures/agentic.d.ts +2 -0
- package/dist/types/cli/gallery-fixtures/codeintel.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/edit.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/fs.d.ts +2 -0
- package/dist/types/cli/gallery-fixtures/index.d.ts +4 -0
- package/dist/types/cli/gallery-fixtures/interaction.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/memory.d.ts +2 -0
- package/dist/types/cli/gallery-fixtures/misc.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/search.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/shell.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/types.d.ts +44 -0
- package/dist/types/cli/gallery-fixtures/web.d.ts +2 -0
- package/dist/types/cli/gallery-screenshot.d.ts +35 -0
- package/dist/types/commands/gallery.d.ts +47 -0
- package/dist/types/config/keybindings.d.ts +10 -2
- package/dist/types/config/model-id-affixes.d.ts +2 -0
- package/dist/types/config/model-registry.d.ts +8 -1
- package/dist/types/config/settings-schema.d.ts +43 -7
- package/dist/types/edit/file-snapshot-store.d.ts +1 -1
- package/dist/types/eval/backend.d.ts +6 -6
- package/dist/types/eval/bridge-timeout.d.ts +27 -0
- package/dist/types/eval/idle-timeout.d.ts +16 -14
- package/dist/types/eval/js/executor.d.ts +3 -3
- package/dist/types/eval/py/executor.d.ts +2 -2
- package/dist/types/eval/py/spawn-options.d.ts +58 -0
- package/dist/types/extensibility/plugins/marketplace-auto-update.d.ts +8 -0
- package/dist/types/lsp/types.d.ts +10 -0
- package/dist/types/main.d.ts +3 -2
- package/dist/types/memory-backend/index.d.ts +2 -1
- package/dist/types/memory-backend/resolve.d.ts +1 -1
- package/dist/types/memory-backend/types.d.ts +1 -1
- package/dist/types/modes/components/assistant-message.d.ts +5 -0
- package/dist/types/modes/components/copy-selector.d.ts +22 -0
- package/dist/types/modes/components/custom-editor.d.ts +2 -1
- package/dist/types/modes/components/model-selector.d.ts +1 -0
- package/dist/types/modes/components/tool-execution.d.ts +18 -0
- package/dist/types/modes/controllers/command-controller.d.ts +0 -1
- package/dist/types/modes/controllers/selector-controller.d.ts +2 -1
- package/dist/types/modes/index.d.ts +5 -4
- package/dist/types/modes/interactive-mode.d.ts +2 -2
- package/dist/types/modes/setup-version.d.ts +11 -0
- package/dist/types/modes/setup-wizard/index.d.ts +2 -1
- package/dist/types/modes/setup-wizard/scenes/web-search.d.ts +2 -1
- package/dist/types/modes/types.d.ts +2 -2
- package/dist/types/modes/utils/copy-targets.d.ts +53 -0
- package/dist/types/sdk.d.ts +1 -1
- package/dist/types/task/executor.d.ts +7 -0
- package/dist/types/telemetry-export.d.ts +1 -1
- package/dist/types/tools/eval-render.d.ts +1 -0
- package/dist/types/tools/fetch.d.ts +15 -7
- package/dist/types/tools/render-utils.d.ts +33 -0
- package/dist/types/tools/renderers.d.ts +16 -2
- package/dist/types/tools/search.d.ts +1 -1
- package/dist/types/tools/write.d.ts +2 -0
- package/dist/types/tui/code-cell.d.ts +6 -0
- package/dist/types/tui/output-block.d.ts +11 -0
- package/dist/types/web/scrapers/github.d.ts +22 -0
- package/dist/types/web/search/providers/perplexity.d.ts +8 -1
- package/dist/types/web/search/types.d.ts +1 -1
- package/package.json +9 -9
- package/scripts/dev-launch +42 -0
- package/scripts/dev-launch-preload.ts +19 -0
- package/src/autoresearch/dashboard.ts +11 -21
- package/src/cli/args.ts +2 -2
- package/src/cli/claude-trace-cli.ts +13 -1
- package/src/cli/gallery-cli.ts +223 -0
- package/src/cli/gallery-fixtures/agentic.ts +292 -0
- package/src/cli/gallery-fixtures/codeintel.ts +188 -0
- package/src/cli/gallery-fixtures/edit.ts +194 -0
- package/src/cli/gallery-fixtures/fs.ts +153 -0
- package/src/cli/gallery-fixtures/index.ts +40 -0
- package/src/cli/gallery-fixtures/interaction.ts +49 -0
- package/src/cli/gallery-fixtures/memory.ts +81 -0
- package/src/cli/gallery-fixtures/misc.ts +221 -0
- package/src/cli/gallery-fixtures/search.ts +213 -0
- package/src/cli/gallery-fixtures/shell.ts +167 -0
- package/src/cli/gallery-fixtures/types.ts +41 -0
- package/src/cli/gallery-fixtures/web.ts +158 -0
- package/src/cli/gallery-screenshot.ts +279 -0
- package/src/cli-commands.ts +1 -0
- package/src/commands/gallery.ts +52 -0
- package/src/commands/launch.ts +1 -1
- package/src/config/keybindings.ts +68 -2
- package/src/config/model-equivalence.ts +35 -12
- package/src/config/model-id-affixes.ts +39 -22
- package/src/config/model-registry.ts +16 -16
- package/src/config/settings-schema.ts +29 -6
- package/src/config/settings.ts +11 -0
- package/src/dap/client.ts +14 -16
- package/src/debug/raw-sse.ts +18 -4
- package/src/edit/file-snapshot-store.ts +1 -1
- package/src/edit/index.ts +1 -1
- package/src/edit/renderer.ts +43 -55
- package/src/edit/streaming.ts +1 -1
- package/src/eval/__tests__/agent-bridge.test.ts +102 -58
- package/src/eval/__tests__/bridge-timeout.test.ts +64 -0
- package/src/eval/__tests__/idle-timeout.test.ts +26 -12
- package/src/eval/__tests__/kernel-spawn.test.ts +103 -0
- package/src/eval/__tests__/llm-bridge.test.ts +10 -10
- package/src/eval/agent-bridge.ts +38 -12
- package/src/eval/backend.ts +6 -6
- package/src/eval/bridge-timeout.ts +44 -0
- package/src/eval/idle-timeout.ts +33 -15
- package/src/eval/js/executor.ts +10 -10
- package/src/eval/llm-bridge.ts +4 -5
- package/src/eval/py/executor.ts +6 -6
- package/src/eval/py/kernel.ts +11 -1
- package/src/eval/py/spawn-options.ts +126 -0
- package/src/export/ttsr.ts +9 -0
- package/src/extensibility/extensions/runner.ts +3 -0
- package/src/extensibility/plugins/doctor.ts +0 -1
- package/src/extensibility/plugins/marketplace-auto-update.ts +49 -0
- package/src/goals/tools/goal-tool.ts +2 -2
- package/src/internal-urls/docs-index.generated.ts +7 -6
- package/src/lsp/client.ts +179 -52
- package/src/lsp/index.ts +38 -4
- package/src/lsp/render.ts +3 -3
- package/src/lsp/types.ts +10 -0
- package/src/main.ts +47 -52
- package/src/memory-backend/index.ts +13 -1
- package/src/memory-backend/resolve.ts +3 -5
- package/src/memory-backend/types.ts +1 -1
- package/src/modes/components/agent-dashboard.ts +13 -4
- package/src/modes/components/assistant-message.ts +22 -1
- package/src/modes/components/copy-selector.ts +249 -0
- package/src/modes/components/custom-editor.ts +10 -1
- package/src/modes/components/extensions/extension-list.ts +17 -8
- package/src/modes/components/history-search.ts +19 -11
- package/src/modes/components/model-selector.ts +125 -29
- package/src/modes/components/oauth-selector.ts +28 -12
- package/src/modes/components/session-observer-overlay.ts +13 -15
- package/src/modes/components/session-selector.ts +24 -13
- package/src/modes/components/status-line.ts +3 -5
- package/src/modes/components/tool-execution.ts +83 -24
- package/src/modes/components/tree-selector.ts +19 -7
- package/src/modes/components/user-message-selector.ts +25 -14
- package/src/modes/controllers/command-controller.ts +13 -118
- package/src/modes/controllers/event-controller.ts +26 -10
- package/src/modes/controllers/input-controller.ts +11 -3
- package/src/modes/controllers/selector-controller.ts +40 -3
- package/src/modes/index.ts +5 -4
- package/src/modes/interactive-mode.ts +21 -7
- package/src/modes/setup-version.ts +11 -0
- package/src/modes/setup-wizard/index.ts +3 -2
- package/src/modes/setup-wizard/scenes/web-search.ts +3 -2
- package/src/modes/theme/theme.ts +46 -10
- package/src/modes/types.ts +2 -2
- package/src/modes/utils/context-usage.ts +10 -6
- package/src/modes/utils/copy-targets.ts +254 -0
- package/src/modes/utils/hotkeys-markdown.ts +1 -0
- package/src/prompts/tools/ast-edit.md +1 -1
- package/src/prompts/tools/ast-grep.md +1 -1
- package/src/prompts/tools/read.md +1 -1
- package/src/prompts/tools/search.md +1 -1
- package/src/sdk.ts +21 -23
- package/src/session/agent-session.ts +13 -9
- package/src/slash-commands/builtin-registry.ts +4 -12
- package/src/slash-commands/helpers/usage-report.ts +2 -0
- package/src/task/executor.ts +20 -2
- package/src/task/render.ts +37 -11
- package/src/telemetry-export.ts +25 -7
- package/src/tools/bash.ts +18 -8
- package/src/tools/browser/render.ts +5 -4
- package/src/tools/debug.ts +3 -3
- package/src/tools/eval-backends.ts +6 -17
- package/src/tools/eval-render.ts +28 -10
- package/src/tools/eval.ts +19 -23
- package/src/tools/fetch.ts +99 -89
- package/src/tools/read.ts +7 -7
- package/src/tools/render-utils.ts +63 -3
- package/src/tools/renderers.ts +16 -1
- package/src/tools/report-tool-issue.ts +1 -1
- package/src/tools/search.ts +173 -81
- package/src/tools/ssh.ts +21 -8
- package/src/tools/todo.ts +20 -7
- package/src/tools/write.ts +39 -9
- package/src/tui/code-cell.ts +19 -4
- package/src/tui/output-block.ts +14 -0
- package/src/web/scrapers/github.ts +255 -3
- package/src/web/scrapers/youtube.ts +3 -2
- package/src/web/search/providers/perplexity.ts +199 -51
- package/src/web/search/render.ts +42 -57
- package/src/web/search/types.ts +5 -1
- package/dist/types/eval/heartbeat.d.ts +0 -45
- package/src/eval/__tests__/heartbeat.test.ts +0 -84
- package/src/eval/__tests__/shared-executors.test.ts +0 -609
- package/src/eval/heartbeat.ts +0 -74
- /package/dist/types/eval/__tests__/{heartbeat.test.d.ts → bridge-timeout.test.d.ts} +0 -0
- /package/dist/types/eval/__tests__/{shared-executors.test.d.ts → kernel-spawn.test.d.ts} +0 -0
|
@@ -9,7 +9,7 @@ Searches files using powerful regex matching.
|
|
|
9
9
|
|
|
10
10
|
<output>
|
|
11
11
|
{{#if IS_HL_MODE}}
|
|
12
|
-
- Text output emits a file snapshot tag header per matched file plus numbered lines:
|
|
12
|
+
- Text output emits a file snapshot tag header per matched file plus numbered lines: `[src/login.ts#1A2B]`, `*42:if (user.id) {` (match), ` 43:return user;` (context). Copy the header for anchored edits; ops use bare line numbers.
|
|
13
13
|
{{else}}
|
|
14
14
|
{{#if IS_LINE_NUMBER_MODE}}
|
|
15
15
|
- Text output is line-number-prefixed
|
package/src/sdk.ts
CHANGED
|
@@ -36,7 +36,6 @@ import {
|
|
|
36
36
|
} from "@oh-my-pi/pi-utils";
|
|
37
37
|
import chalk from "chalk";
|
|
38
38
|
import { type AsyncJob, AsyncJobManager, isBackgroundJobSupportEnabled } from "./async";
|
|
39
|
-
import { createAutoresearchExtension } from "./autoresearch";
|
|
40
39
|
import { loadCapability } from "./capability";
|
|
41
40
|
import { type Rule, ruleCapability, setActiveRules } from "./capability/rule";
|
|
42
41
|
import { bucketRules } from "./capability/rule-buckets";
|
|
@@ -57,7 +56,6 @@ import { resolveConfigValue } from "./config/resolve-config-value";
|
|
|
57
56
|
import { initializeWithSettings } from "./discovery";
|
|
58
57
|
import { disposeAllKernelSessions, disposeKernelSessionsByOwner } from "./eval/py/executor";
|
|
59
58
|
import { defaultEvalSessionId } from "./eval/session-id";
|
|
60
|
-
import { TtsrManager } from "./export/ttsr";
|
|
61
59
|
import {
|
|
62
60
|
type CustomCommandsLoadResult,
|
|
63
61
|
type LoadedCustomCommand,
|
|
@@ -90,7 +88,7 @@ import { LocalProtocolHandler, type LocalProtocolOptions } from "./internal-urls
|
|
|
90
88
|
import { LSP_STARTUP_EVENT_CHANNEL, type LspStartupEvent } from "./lsp/startup-events";
|
|
91
89
|
import { discoverAndLoadMCPTools, MCPManager, type MCPToolsLoadResult } from "./mcp";
|
|
92
90
|
import { resolveMemoryBackend } from "./memory-backend";
|
|
93
|
-
import {
|
|
91
|
+
import type { MnemopiSessionState } from "./mnemopi/state";
|
|
94
92
|
import asyncResultTemplate from "./prompts/tools/async-result.md" with { type: "text" };
|
|
95
93
|
import { AgentRegistry, MAIN_AGENT_ID } from "./registry/agent-registry";
|
|
96
94
|
import {
|
|
@@ -1150,6 +1148,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1150
1148
|
|
|
1151
1149
|
// Discover rules and bucket them in one pass to avoid repeated scans over large rule sets.
|
|
1152
1150
|
const { ttsrManager, rulebookRules, alwaysApplyRules } = await logger.time("discoverTtsrRules", async () => {
|
|
1151
|
+
const { TtsrManager } = await import("./export/ttsr");
|
|
1153
1152
|
const ttsrSettings = settings.getGroup("ttsr");
|
|
1154
1153
|
const ttsrManager = new TtsrManager(ttsrSettings);
|
|
1155
1154
|
const rulesResult =
|
|
@@ -1295,7 +1294,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1295
1294
|
session ? session.trackEvalExecution(execution, abortController) : execution,
|
|
1296
1295
|
getSessionId: () => sessionManager.getSessionId?.() ?? null,
|
|
1297
1296
|
getHindsightSessionState: () => session?.getHindsightSessionState(),
|
|
1298
|
-
getMnemopiSessionState: () => getMnemopiSessionState(
|
|
1297
|
+
getMnemopiSessionState: () => session?.getMnemopiSessionState(),
|
|
1299
1298
|
getAgentId: () => resolvedAgentId,
|
|
1300
1299
|
getToolByName: name => session?.getToolByName(name),
|
|
1301
1300
|
agentRegistry,
|
|
@@ -1472,7 +1471,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1472
1471
|
}
|
|
1473
1472
|
|
|
1474
1473
|
const inlineExtensions: ExtensionFactory[] = options.extensions ? [...options.extensions] : [];
|
|
1475
|
-
inlineExtensions.push(createAutoresearchExtension);
|
|
1474
|
+
inlineExtensions.push((await import("./autoresearch")).createAutoresearchExtension);
|
|
1476
1475
|
if (customTools.length > 0) {
|
|
1477
1476
|
inlineExtensions.push(createCustomToolsExtension(customTools));
|
|
1478
1477
|
}
|
|
@@ -1607,9 +1606,9 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1607
1606
|
// `ExtensionToolWrapper` installed below is the only place the per-tool approval gate runs.
|
|
1608
1607
|
// A conditional runner means the approval system silently disappears for users with no
|
|
1609
1608
|
// extensions, contradicting non-yolo `tools.approvalMode` settings without feedback.
|
|
1610
|
-
// (
|
|
1611
|
-
// is unreachable;
|
|
1612
|
-
//
|
|
1609
|
+
// (The builtin autoresearch extension is unconditionally loaded above, so this scenario
|
|
1610
|
+
// is unreachable; unconditional runner construction keeps that invariant explicit and
|
|
1611
|
+
// prevents future optional extensions from silently re-opening the hole.)
|
|
1613
1612
|
const extensionRunner: ExtensionRunner = new ExtensionRunner(
|
|
1614
1613
|
extensionsResult.extensions,
|
|
1615
1614
|
extensionsResult.runtime,
|
|
@@ -1723,7 +1722,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1723
1722
|
|
|
1724
1723
|
const repeatToolDescriptions = settings.get("repeatToolDescriptions");
|
|
1725
1724
|
const eagerTasks = settings.get("task.eager");
|
|
1726
|
-
const intentField = settings.get("tools.intentTracing")
|
|
1725
|
+
const intentField = $flag("PI_INTENT_TRACING", settings.get("tools.intentTracing")) ? INTENT_FIELD : undefined;
|
|
1727
1726
|
const rebuildSystemPrompt = async (
|
|
1728
1727
|
toolNames: string[],
|
|
1729
1728
|
tools: Map<string, AgentTool>,
|
|
@@ -1749,7 +1748,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1749
1748
|
const promptTools = buildSystemPromptToolMetadata(tools, {
|
|
1750
1749
|
search_tool_bm25: { description: renderSearchToolBm25Description(discoverableToolsForDesc) },
|
|
1751
1750
|
});
|
|
1752
|
-
const memoryBackend = resolveMemoryBackend(settings);
|
|
1751
|
+
const memoryBackend = await resolveMemoryBackend(settings);
|
|
1753
1752
|
const memoryInstructions = await memoryBackend.buildDeveloperInstructions(agentDir, settings, session);
|
|
1754
1753
|
|
|
1755
1754
|
// Build combined append prompt: memory instructions + MCP server instructions
|
|
@@ -2267,19 +2266,18 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2267
2266
|
}
|
|
2268
2267
|
}
|
|
2269
2268
|
|
|
2270
|
-
logger.time("startMemoryStartupTask", () =>
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
);
|
|
2269
|
+
logger.time("startMemoryStartupTask", async () => {
|
|
2270
|
+
const memoryBackend = await resolveMemoryBackend(settings);
|
|
2271
|
+
await memoryBackend.start({
|
|
2272
|
+
session,
|
|
2273
|
+
settings,
|
|
2274
|
+
modelRegistry,
|
|
2275
|
+
agentDir,
|
|
2276
|
+
taskDepth,
|
|
2277
|
+
parentHindsightSessionState: options.parentHindsightSessionState,
|
|
2278
|
+
parentMnemopiSessionState: options.parentMnemopiSessionState,
|
|
2279
|
+
});
|
|
2280
|
+
});
|
|
2283
2281
|
|
|
2284
2282
|
// Wire MCP manager callbacks to session for reactive tool updates.
|
|
2285
2283
|
// Skip when reusing a parent's manager — the parent owns the callbacks.
|
|
@@ -91,6 +91,7 @@ import {
|
|
|
91
91
|
extractRetryHint,
|
|
92
92
|
getAgentDbPath,
|
|
93
93
|
getInstallId,
|
|
94
|
+
isBunTestRuntime,
|
|
94
95
|
isEnoent,
|
|
95
96
|
isUnexpectedSocketCloseMessage,
|
|
96
97
|
logger,
|
|
@@ -127,7 +128,6 @@ import {
|
|
|
127
128
|
} from "../eval/py/executor";
|
|
128
129
|
import { defaultEvalSessionId } from "../eval/session-id";
|
|
129
130
|
import { type BashResult, executeBash as executeBashCommand } from "../exec/bash-executor";
|
|
130
|
-
import { exportSessionToHtml } from "../export/html";
|
|
131
131
|
import type { TtsrManager, TtsrMatchContext } from "../export/ttsr";
|
|
132
132
|
import type { LoadedCustomCommand } from "../extensibility/custom-commands";
|
|
133
133
|
import type { CustomTool, CustomToolContext } from "../extensibility/custom-tools/types";
|
|
@@ -1036,6 +1036,7 @@ export class AgentSession {
|
|
|
1036
1036
|
|
|
1037
1037
|
#acquirePowerAssertion(): void {
|
|
1038
1038
|
if (process.platform !== "darwin") return;
|
|
1039
|
+
if (isBunTestRuntime()) return;
|
|
1039
1040
|
if (this.#powerAssertion) return;
|
|
1040
1041
|
const idle = this.settings.get("power.preventIdleSleep");
|
|
1041
1042
|
const system = this.settings.get("power.preventSystemSleep");
|
|
@@ -2965,14 +2966,14 @@ export class AgentSession {
|
|
|
2965
2966
|
}
|
|
2966
2967
|
|
|
2967
2968
|
#rekeyHindsightMemoryForCurrentSessionId(): void {
|
|
2968
|
-
if (
|
|
2969
|
+
if (this.settings.get("memory.backend") !== "hindsight") return;
|
|
2969
2970
|
const sid = this.agent.sessionId;
|
|
2970
2971
|
if (!sid) return;
|
|
2971
2972
|
this.getHindsightSessionState()?.setSessionId(sid);
|
|
2972
2973
|
}
|
|
2973
2974
|
|
|
2974
2975
|
#rekeyMnemopiMemoryForCurrentSessionId(): void {
|
|
2975
|
-
if (
|
|
2976
|
+
if (this.settings.get("memory.backend") !== "mnemopi") return;
|
|
2976
2977
|
const sid = this.agent.sessionId;
|
|
2977
2978
|
if (!sid) return;
|
|
2978
2979
|
this.getMnemopiSessionState()?.setSessionId(sid);
|
|
@@ -2980,14 +2981,14 @@ export class AgentSession {
|
|
|
2980
2981
|
|
|
2981
2982
|
/** New session file: reset auto-recall / retain-threshold counters for the new transcript. */
|
|
2982
2983
|
#resetHindsightConversationTrackingIfHindsight(): void {
|
|
2983
|
-
if (
|
|
2984
|
+
if (this.settings.get("memory.backend") !== "hindsight") return;
|
|
2984
2985
|
const state = this.getHindsightSessionState();
|
|
2985
2986
|
if (!state || state.aliasOf) return;
|
|
2986
2987
|
state.resetConversationTracking();
|
|
2987
2988
|
}
|
|
2988
2989
|
|
|
2989
2990
|
#resetMnemopiConversationTrackingIfMnemopi(): void {
|
|
2990
|
-
if (
|
|
2991
|
+
if (this.settings.get("memory.backend") !== "mnemopi") return;
|
|
2991
2992
|
const state = this.getMnemopiSessionState();
|
|
2992
2993
|
if (!state || state.aliasOf) return;
|
|
2993
2994
|
state.resetConversationTracking();
|
|
@@ -3668,7 +3669,7 @@ export class AgentSession {
|
|
|
3668
3669
|
}
|
|
3669
3670
|
|
|
3670
3671
|
async #buildSystemPromptForAgentStart(promptText: string): Promise<string[]> {
|
|
3671
|
-
const backend = resolveMemoryBackend(this.settings);
|
|
3672
|
+
const backend = await resolveMemoryBackend(this.settings);
|
|
3672
3673
|
if (!backend.beforeAgentStartPrompt) return this.#baseSystemPrompt;
|
|
3673
3674
|
|
|
3674
3675
|
try {
|
|
@@ -6094,7 +6095,7 @@ export class AgentSession {
|
|
|
6094
6095
|
messagesToSummarize: AgentMessage[];
|
|
6095
6096
|
turnPrefixMessages: AgentMessage[];
|
|
6096
6097
|
}): Promise<string | undefined> {
|
|
6097
|
-
const backend = resolveMemoryBackend(this.settings);
|
|
6098
|
+
const backend = await resolveMemoryBackend(this.settings);
|
|
6098
6099
|
if (!backend.preCompactionContext) return undefined;
|
|
6099
6100
|
const messages = preparation.messagesToSummarize.concat(preparation.turnPrefixMessages);
|
|
6100
6101
|
try {
|
|
@@ -8136,8 +8137,10 @@ export class AgentSession {
|
|
|
8136
8137
|
|
|
8137
8138
|
const currentSelector = this.model ? formatRetryFallbackSelector(this.model, this.thinkingLevel) : undefined;
|
|
8138
8139
|
if (!switchedCredential && currentSelector) {
|
|
8139
|
-
|
|
8140
|
-
|
|
8140
|
+
if (retrySettings.modelFallback) {
|
|
8141
|
+
this.#noteRetryFallbackCooldown(currentSelector, parsedRetryAfterMs, errorMessage);
|
|
8142
|
+
switchedModel = await this.#tryRetryModelFallback(currentSelector);
|
|
8143
|
+
}
|
|
8141
8144
|
if (switchedModel) {
|
|
8142
8145
|
delayMs = 0;
|
|
8143
8146
|
} else if (parsedRetryAfterMs && parsedRetryAfterMs > delayMs) {
|
|
@@ -9584,6 +9587,7 @@ export class AgentSession {
|
|
|
9584
9587
|
*/
|
|
9585
9588
|
async exportToHtml(outputPath?: string): Promise<string> {
|
|
9586
9589
|
const themeName = getCurrentThemeName();
|
|
9590
|
+
const { exportSessionToHtml } = await import("../export/html");
|
|
9587
9591
|
return exportSessionToHtml(this.sessionManager, this.state, { outputPath, themeName });
|
|
9588
9592
|
}
|
|
9589
9593
|
|
|
@@ -392,17 +392,9 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
392
392
|
},
|
|
393
393
|
{
|
|
394
394
|
name: "copy",
|
|
395
|
-
description: "
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
{ name: "code", description: "Copy last code block" },
|
|
399
|
-
{ name: "all", description: "Copy all code blocks from last message" },
|
|
400
|
-
{ name: "cmd", description: "Copy last bash/python command" },
|
|
401
|
-
],
|
|
402
|
-
allowArgs: true,
|
|
403
|
-
handleTui: async (command, runtime) => {
|
|
404
|
-
const sub = command.args.trim().toLowerCase() || undefined;
|
|
405
|
-
await runtime.ctx.handleCopyCommand(sub);
|
|
395
|
+
description: "Pick text or code from the conversation to copy",
|
|
396
|
+
handleTui: (_command, runtime) => {
|
|
397
|
+
runtime.ctx.showCopySelector();
|
|
406
398
|
runtime.ctx.editor.setText("");
|
|
407
399
|
},
|
|
408
400
|
},
|
|
@@ -942,7 +934,7 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
942
934
|
allowArgs: true,
|
|
943
935
|
handle: async (command, runtime) => {
|
|
944
936
|
const verb = (command.args.trim().split(/\s+/)[0] ?? "").toLowerCase() || "view";
|
|
945
|
-
const backend = resolveMemoryBackend(runtime.settings);
|
|
937
|
+
const backend = await resolveMemoryBackend(runtime.settings);
|
|
946
938
|
switch (verb) {
|
|
947
939
|
case "view": {
|
|
948
940
|
const payload = await backend.buildDeveloperInstructions(
|
|
@@ -26,6 +26,8 @@ function formatUsageReportAccount(report: UsageReport, limit: UsageLimit, index:
|
|
|
26
26
|
if (typeof email === "string" && email) return email;
|
|
27
27
|
const accountId = report.metadata?.accountId ?? limit.scope.accountId;
|
|
28
28
|
if (typeof accountId === "string" && accountId) return accountId;
|
|
29
|
+
const projectId = report.metadata?.projectId ?? limit.scope.projectId;
|
|
30
|
+
if (typeof projectId === "string" && projectId) return projectId;
|
|
29
31
|
return `account ${index + 1}`;
|
|
30
32
|
}
|
|
31
33
|
|
package/src/task/executor.ts
CHANGED
|
@@ -166,6 +166,13 @@ export interface ExecutorOptions {
|
|
|
166
166
|
outputSchema?: unknown;
|
|
167
167
|
/** Parent task recursion depth (0 = top-level, 1 = first child, etc.) */
|
|
168
168
|
taskDepth?: number;
|
|
169
|
+
/**
|
|
170
|
+
* Override the `task.maxRuntimeMs` wall-clock cap for this run. When provided
|
|
171
|
+
* it wins over the settings value; `0` disables the per-subagent wall-clock
|
|
172
|
+
* limit entirely. Used by the eval `agent()` bridge, whose parent cell
|
|
173
|
+
* watchdog is already suspended for the call's duration.
|
|
174
|
+
*/
|
|
175
|
+
maxRuntimeMs?: number;
|
|
169
176
|
enableLsp?: boolean;
|
|
170
177
|
signal?: AbortSignal;
|
|
171
178
|
onProgress?: (progress: AgentProgress) => void;
|
|
@@ -625,7 +632,10 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
625
632
|
agent.readSummarize === false ? { "read.summarize.enabled": false } : undefined,
|
|
626
633
|
);
|
|
627
634
|
const maxRecursionDepth = settings.get("task.maxRecursionDepth") ?? 2;
|
|
628
|
-
const maxRuntimeMs = Math.max(
|
|
635
|
+
const maxRuntimeMs = Math.max(
|
|
636
|
+
0,
|
|
637
|
+
Math.trunc(Number(options.maxRuntimeMs ?? settings.get("task.maxRuntimeMs") ?? 0) || 0),
|
|
638
|
+
);
|
|
629
639
|
const parentDepth = options.taskDepth ?? 0;
|
|
630
640
|
const childDepth = parentDepth + 1;
|
|
631
641
|
const atMaxDepth = maxRecursionDepth >= 0 && childDepth >= maxRecursionDepth;
|
|
@@ -1484,7 +1494,15 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1484
1494
|
if (lastAssistant.stopReason === "aborted") {
|
|
1485
1495
|
aborted = abortReason === "signal" || runtimeLimitExceeded || abortReason === undefined;
|
|
1486
1496
|
if (aborted) {
|
|
1487
|
-
|
|
1497
|
+
// A real caller signal or the wall-clock timer carries a precise
|
|
1498
|
+
// reason (signal.reason / "runtime limit exceeded"). An internal
|
|
1499
|
+
// turn abort (abortReason === undefined) does NOT — prefer the
|
|
1500
|
+
// assistant message's own errorMessage ("Request was aborted" or a
|
|
1501
|
+
// specific stream error) over the misleading "Cancelled by caller".
|
|
1502
|
+
abortReasonText ??=
|
|
1503
|
+
abortReason === "signal" || runtimeLimitExceeded
|
|
1504
|
+
? resolveAbortReasonText()
|
|
1505
|
+
: lastAssistant.errorMessage?.trim() || resolveAbortReasonText();
|
|
1488
1506
|
}
|
|
1489
1507
|
exitCode = 1;
|
|
1490
1508
|
} else if (lastAssistant.stopReason === "error") {
|
package/src/task/render.ts
CHANGED
|
@@ -117,6 +117,26 @@ function normalizeReportFindings(value: unknown): ReportFindingDetails[] {
|
|
|
117
117
|
return findings;
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Normalize the `yield` slot of `extractedToolData` into an array of
|
|
122
|
+
* yield-detail records. The subprocess executor always populates this slot as
|
|
123
|
+
* `unknown[]` (see `executor.ts` `extractData` handler), but the renderer
|
|
124
|
+
* MUST also tolerate a stray single object — optional chaining short-circuits
|
|
125
|
+
* on `null`/`undefined` only, so calling `.map` on a plain object would throw
|
|
126
|
+
* `TypeError: completeData?.map is not a function` and crash the TUI.
|
|
127
|
+
* A single object is wrapped as a 1-element array so the review verdict still
|
|
128
|
+
* renders; non-object primitives drop out.
|
|
129
|
+
*/
|
|
130
|
+
function normalizeYieldData(value: unknown): Array<{ data: unknown }> {
|
|
131
|
+
if (Array.isArray(value)) {
|
|
132
|
+
return value.filter((item): item is { data: unknown } => item !== null && typeof item === "object");
|
|
133
|
+
}
|
|
134
|
+
if (value !== null && typeof value === "object") {
|
|
135
|
+
return [value as { data: unknown }];
|
|
136
|
+
}
|
|
137
|
+
return [];
|
|
138
|
+
}
|
|
139
|
+
|
|
120
140
|
function formatJsonScalar(value: unknown, _theme: Theme): string {
|
|
121
141
|
if (value === null) return "null";
|
|
122
142
|
if (typeof value === "string") {
|
|
@@ -541,10 +561,11 @@ export function renderCall(
|
|
|
541
561
|
|
|
542
562
|
if (hasContext) {
|
|
543
563
|
lines.push(` ${branch} ${theme.fg("dim", "Context")}`);
|
|
544
|
-
|
|
564
|
+
const contextLines = context.split("\n").map(line => {
|
|
545
565
|
const content = line ? theme.fg("muted", replaceTabs(line)) : "";
|
|
546
|
-
|
|
547
|
-
}
|
|
566
|
+
return ` ${vertical} ${content}`;
|
|
567
|
+
});
|
|
568
|
+
lines.push(...contextLines);
|
|
548
569
|
}
|
|
549
570
|
|
|
550
571
|
// `Tasks` is the last child unless the isolation flag follows it.
|
|
@@ -671,12 +692,12 @@ function renderAgentProgress(
|
|
|
671
692
|
if (progress.extractedToolData) {
|
|
672
693
|
// For completed tasks, check for review verdict from yield tool
|
|
673
694
|
if (progress.status === "completed") {
|
|
674
|
-
const completeData = progress.extractedToolData.yield
|
|
695
|
+
const completeData = normalizeYieldData(progress.extractedToolData.yield);
|
|
675
696
|
const reportFindingData = normalizeReportFindings(progress.extractedToolData.report_finding);
|
|
676
697
|
const reviewData = completeData
|
|
677
|
-
|
|
698
|
+
.map(c => c.data as SubmitReviewDetails)
|
|
678
699
|
.filter(d => d && typeof d === "object" && "overall_correctness" in d);
|
|
679
|
-
if (reviewData
|
|
700
|
+
if (reviewData.length > 0) {
|
|
680
701
|
const summary = reviewData[reviewData.length - 1];
|
|
681
702
|
const findings = reportFindingData;
|
|
682
703
|
lines.push(...renderReviewResult(summary, findings, continuePrefix, expanded, theme));
|
|
@@ -912,16 +933,21 @@ function renderAgentResult(result: SingleResult, isLast: boolean, expanded: bool
|
|
|
912
933
|
);
|
|
913
934
|
}
|
|
914
935
|
// Check for review result (yield with review schema + report_finding)
|
|
915
|
-
|
|
936
|
+
// Check for review result (yield with review schema + report_finding).
|
|
937
|
+
// `normalizeYieldData` guards against a stray non-array `yield` slot —
|
|
938
|
+
// optional chaining on `.map` only short-circuits on null/undefined and
|
|
939
|
+
// would otherwise crash the renderer with `TypeError: completeData?.map
|
|
940
|
+
// is not a function` when the slot is a plain object (see issue #1987).
|
|
941
|
+
const completeData = normalizeYieldData(result.extractedToolData?.yield);
|
|
916
942
|
const reportFindingData = normalizeReportFindings(result.extractedToolData?.report_finding);
|
|
917
943
|
|
|
918
944
|
// Extract review verdict from yield tool's data field if it matches SubmitReviewDetails
|
|
919
945
|
const reviewData = completeData
|
|
920
|
-
|
|
946
|
+
.map(c => c.data as SubmitReviewDetails)
|
|
921
947
|
.filter(d => d && typeof d === "object" && "overall_correctness" in d);
|
|
922
|
-
const submitReviewData = reviewData
|
|
948
|
+
const submitReviewData = reviewData.length > 0 ? reviewData : undefined;
|
|
923
949
|
|
|
924
|
-
if (submitReviewData
|
|
950
|
+
if (submitReviewData) {
|
|
925
951
|
// Use combined review renderer
|
|
926
952
|
const summary = submitReviewData[submitReviewData.length - 1];
|
|
927
953
|
const findings = reportFindingData;
|
|
@@ -929,7 +955,7 @@ function renderAgentResult(result: SingleResult, isLast: boolean, expanded: bool
|
|
|
929
955
|
return lines;
|
|
930
956
|
}
|
|
931
957
|
if (reportFindingData.length > 0) {
|
|
932
|
-
const hasCompleteData = completeData
|
|
958
|
+
const hasCompleteData = completeData.length > 0;
|
|
933
959
|
const message = hasCompleteData
|
|
934
960
|
? "Review verdict missing expected fields"
|
|
935
961
|
: "Review incomplete (yield not called)";
|
package/src/telemetry-export.ts
CHANGED
|
@@ -23,11 +23,7 @@
|
|
|
23
23
|
* `sdk-trace-base@2.7` exports cleanly on Bun.
|
|
24
24
|
*/
|
|
25
25
|
import { logger, postmortem } from "@oh-my-pi/pi-utils";
|
|
26
|
-
import
|
|
27
|
-
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
|
|
28
|
-
import { resourceFromAttributes } from "@opentelemetry/resources";
|
|
29
|
-
import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
|
|
30
|
-
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
|
|
26
|
+
import type * as TraceNode from "@opentelemetry/sdk-trace-node";
|
|
31
27
|
|
|
32
28
|
/**
|
|
33
29
|
* Periodic flush interval. A long-lived `omp` process (the ACP server is
|
|
@@ -36,7 +32,8 @@ import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
|
|
|
36
32
|
*/
|
|
37
33
|
const FLUSH_INTERVAL_MS = 30_000;
|
|
38
34
|
|
|
39
|
-
let provider: NodeTracerProvider | undefined;
|
|
35
|
+
let provider: TraceNode.NodeTracerProvider | undefined;
|
|
36
|
+
let initPromise: Promise<void> | undefined;
|
|
40
37
|
|
|
41
38
|
/**
|
|
42
39
|
* Whether {@link initTelemetryExport} registered a real provider. The CLI uses
|
|
@@ -53,8 +50,10 @@ export function isTelemetryExportEnabled(): boolean {
|
|
|
53
50
|
* the OTEL kill-switches are engaged), so it is safe to call unconditionally at
|
|
54
51
|
* startup.
|
|
55
52
|
*/
|
|
56
|
-
export function initTelemetryExport(): void {
|
|
53
|
+
export async function initTelemetryExport(): Promise<void> {
|
|
57
54
|
if (provider) return;
|
|
55
|
+
if (initPromise) return initPromise;
|
|
56
|
+
|
|
58
57
|
// The OTEL env contract parses booleans and enum lists case-insensitively, so
|
|
59
58
|
// OTEL_SDK_DISABLED=TRUE and OTEL_TRACES_EXPORTER=None must also disable export.
|
|
60
59
|
if (process.env.OTEL_SDK_DISABLED?.trim().toLowerCase() === "true") return;
|
|
@@ -77,6 +76,25 @@ export function initTelemetryExport(): void {
|
|
|
77
76
|
return;
|
|
78
77
|
}
|
|
79
78
|
|
|
79
|
+
initPromise = registerProvider();
|
|
80
|
+
return initPromise;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function registerProvider(): Promise<void> {
|
|
84
|
+
const [
|
|
85
|
+
{ AsyncLocalStorageContextManager },
|
|
86
|
+
{ OTLPTraceExporter },
|
|
87
|
+
{ resourceFromAttributes },
|
|
88
|
+
{ BatchSpanProcessor },
|
|
89
|
+
{ NodeTracerProvider },
|
|
90
|
+
] = await Promise.all([
|
|
91
|
+
import("@opentelemetry/context-async-hooks"),
|
|
92
|
+
import("@opentelemetry/exporter-trace-otlp-proto"),
|
|
93
|
+
import("@opentelemetry/resources"),
|
|
94
|
+
import("@opentelemetry/sdk-trace-base"),
|
|
95
|
+
import("@opentelemetry/sdk-trace-node"),
|
|
96
|
+
]);
|
|
97
|
+
|
|
80
98
|
// The exporter reads endpoint/headers/timeout from OTEL_EXPORTER_OTLP_* itself,
|
|
81
99
|
// so there is nothing to thread through here.
|
|
82
100
|
const exporter = new OTLPTraceExporter();
|
package/src/tools/bash.ts
CHANGED
|
@@ -20,7 +20,7 @@ import bashDescription from "../prompts/tools/bash.md" with { type: "text" };
|
|
|
20
20
|
import type { ClientBridgeTerminalExitStatus, ClientBridgeTerminalOutput } from "../session/client-bridge";
|
|
21
21
|
import { DEFAULT_MAX_BYTES, streamTailUpdates, TailBuffer } from "../session/streaming-output";
|
|
22
22
|
import { renderStatusLine } from "../tui";
|
|
23
|
-
import { CachedOutputBlock } from "../tui/output-block";
|
|
23
|
+
import { CachedOutputBlock, markFramedBlockComponent } from "../tui/output-block";
|
|
24
24
|
import { getSixelLineMask } from "../utils/sixel";
|
|
25
25
|
import type { ToolSession } from ".";
|
|
26
26
|
import { truncateForPrompt } from "./approval";
|
|
@@ -31,7 +31,7 @@ import { canUseInteractiveBashPty } from "./bash-pty-selection";
|
|
|
31
31
|
import { expandInternalUrls, type InternalUrlExpansionOptions } from "./bash-skill-urls";
|
|
32
32
|
import { formatStyledTruncationWarning, type OutputMeta, stripOutputNotice } from "./output-meta";
|
|
33
33
|
import { resolveToCwd } from "./path-utils";
|
|
34
|
-
import { formatToolWorkingDirectory, replaceTabs } from "./render-utils";
|
|
34
|
+
import { capPreviewLines, formatToolWorkingDirectory, replaceTabs } from "./render-utils";
|
|
35
35
|
import { ToolAbortError, ToolError } from "./tool-errors";
|
|
36
36
|
import { toolResult } from "./tool-result";
|
|
37
37
|
import { clampTimeout, TOOL_TIMEOUTS } from "./tool-timeouts";
|
|
@@ -1083,16 +1083,22 @@ export function createShellRenderer<TArgs>(config: ShellRendererConfig<TArgs>) {
|
|
|
1083
1083
|
const cmdLines = formatBashCommandLines(renderArgs, uiTheme);
|
|
1084
1084
|
const header = renderStatusLine({ icon: "pending", title }, uiTheme);
|
|
1085
1085
|
const outputBlock = new CachedOutputBlock();
|
|
1086
|
-
return {
|
|
1086
|
+
return markFramedBlockComponent({
|
|
1087
1087
|
render: (width: number): string[] =>
|
|
1088
1088
|
outputBlock.render(
|
|
1089
|
-
{
|
|
1089
|
+
{
|
|
1090
|
+
header,
|
|
1091
|
+
state: "pending",
|
|
1092
|
+
sections: [{ lines: capPreviewLines(cmdLines, uiTheme, { expanded: options.expanded }) }],
|
|
1093
|
+
width,
|
|
1094
|
+
animate: true,
|
|
1095
|
+
},
|
|
1090
1096
|
uiTheme,
|
|
1091
1097
|
),
|
|
1092
1098
|
invalidate: () => {
|
|
1093
1099
|
outputBlock.invalidate();
|
|
1094
1100
|
},
|
|
1095
|
-
};
|
|
1101
|
+
});
|
|
1096
1102
|
},
|
|
1097
1103
|
|
|
1098
1104
|
renderResult(
|
|
@@ -1114,7 +1120,7 @@ export function createShellRenderer<TArgs>(config: ShellRendererConfig<TArgs>) {
|
|
|
1114
1120
|
const details = result.details;
|
|
1115
1121
|
const outputBlock = new CachedOutputBlock();
|
|
1116
1122
|
|
|
1117
|
-
return {
|
|
1123
|
+
return markFramedBlockComponent({
|
|
1118
1124
|
render: (width: number): string[] => {
|
|
1119
1125
|
// REACTIVE: read mutable options at render time
|
|
1120
1126
|
const { renderContext } = options;
|
|
@@ -1201,7 +1207,11 @@ export function createShellRenderer<TArgs>(config: ShellRendererConfig<TArgs>) {
|
|
|
1201
1207
|
header,
|
|
1202
1208
|
state: options.isPartial ? "pending" : isError ? "error" : "success",
|
|
1203
1209
|
sections: [
|
|
1204
|
-
{
|
|
1210
|
+
{
|
|
1211
|
+
lines: options.isPartial
|
|
1212
|
+
? capPreviewLines(cmdLines ?? [], uiTheme, { expanded })
|
|
1213
|
+
: (cmdLines ?? []),
|
|
1214
|
+
},
|
|
1205
1215
|
{ label: uiTheme.fg("toolTitle", "Output"), lines: outputLines },
|
|
1206
1216
|
],
|
|
1207
1217
|
width,
|
|
@@ -1213,7 +1223,7 @@ export function createShellRenderer<TArgs>(config: ShellRendererConfig<TArgs>) {
|
|
|
1213
1223
|
invalidate: () => {
|
|
1214
1224
|
outputBlock.invalidate();
|
|
1215
1225
|
},
|
|
1216
|
-
};
|
|
1226
|
+
});
|
|
1217
1227
|
},
|
|
1218
1228
|
mergeCallAndResult: true,
|
|
1219
1229
|
inline: true,
|
|
@@ -9,7 +9,7 @@ import type { Component } from "@oh-my-pi/pi-tui";
|
|
|
9
9
|
import { Text } from "@oh-my-pi/pi-tui";
|
|
10
10
|
import type { RenderResultOptions } from "../../extensibility/custom-tools/types";
|
|
11
11
|
import type { Theme } from "../../modes/theme/theme";
|
|
12
|
-
import { Hasher, renderCodeCell, renderStatusLine } from "../../tui";
|
|
12
|
+
import { Hasher, isFramedBlockComponent, markFramedBlockComponent, renderCodeCell, renderStatusLine } from "../../tui";
|
|
13
13
|
import type { BrowserToolDetails } from "../browser";
|
|
14
14
|
import { formatStyledTruncationWarning, stripOutputNotice } from "../output-meta";
|
|
15
15
|
import { replaceTabs, shortenPath } from "../render-utils";
|
|
@@ -65,13 +65,14 @@ function dropTrailingBlankLines(text: string): string {
|
|
|
65
65
|
|
|
66
66
|
function appendLine(component: Component, line: string | undefined): Component {
|
|
67
67
|
if (!line) return component;
|
|
68
|
-
|
|
68
|
+
const wrapped = {
|
|
69
69
|
render: (width: number): string[] => {
|
|
70
70
|
const base = component.render(width);
|
|
71
71
|
return [...base, line];
|
|
72
72
|
},
|
|
73
73
|
invalidate: () => component.invalidate?.(),
|
|
74
74
|
};
|
|
75
|
+
return isFramedBlockComponent(component) ? markFramedBlockComponent(wrapped) : wrapped;
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
function renderRunCell(
|
|
@@ -93,7 +94,7 @@ function renderRunCell(
|
|
|
93
94
|
const title = titleParts.join(" · ");
|
|
94
95
|
|
|
95
96
|
let cached: { key: bigint; width: number; lines: string[] } | undefined;
|
|
96
|
-
return {
|
|
97
|
+
return markFramedBlockComponent({
|
|
97
98
|
render: (width: number): string[] => {
|
|
98
99
|
const expanded = options.renderContext?.expanded ?? options.expanded;
|
|
99
100
|
const previewLines = options.renderContext?.previewLines ?? BROWSER_DEFAULT_PREVIEW_LINES;
|
|
@@ -131,7 +132,7 @@ function renderRunCell(
|
|
|
131
132
|
invalidate: () => {
|
|
132
133
|
cached = undefined;
|
|
133
134
|
},
|
|
134
|
-
};
|
|
135
|
+
});
|
|
135
136
|
}
|
|
136
137
|
|
|
137
138
|
function renderOpenOrCloseLine(
|
package/src/tools/debug.ts
CHANGED
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
import type { Theme } from "../modes/theme/theme";
|
|
37
37
|
import debugDescription from "../prompts/tools/debug.md" with { type: "text" };
|
|
38
38
|
import { renderStatusLine } from "../tui";
|
|
39
|
-
import { CachedOutputBlock } from "../tui/output-block";
|
|
39
|
+
import { CachedOutputBlock, markFramedBlockComponent } from "../tui/output-block";
|
|
40
40
|
import type { ToolSession } from ".";
|
|
41
41
|
import { truncateForPrompt } from "./approval";
|
|
42
42
|
import type { OutputMeta } from "./output-meta";
|
|
@@ -581,7 +581,7 @@ export const debugToolRenderer = {
|
|
|
581
581
|
args?: DebugRenderArgs,
|
|
582
582
|
): Component {
|
|
583
583
|
const outputBlock = new CachedOutputBlock();
|
|
584
|
-
return {
|
|
584
|
+
return markFramedBlockComponent({
|
|
585
585
|
render(width: number): string[] {
|
|
586
586
|
const action = (args?.action ?? result.details?.action ?? "debug").replaceAll("_", " ");
|
|
587
587
|
const status = options.isPartial ? "running" : result.isError ? "error" : "success";
|
|
@@ -620,7 +620,7 @@ export const debugToolRenderer = {
|
|
|
620
620
|
invalidate() {
|
|
621
621
|
outputBlock.invalidate();
|
|
622
622
|
},
|
|
623
|
-
};
|
|
623
|
+
});
|
|
624
624
|
},
|
|
625
625
|
mergeCallAndResult: true,
|
|
626
626
|
inline: true,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $
|
|
1
|
+
import { $flag } from "@oh-my-pi/pi-utils";
|
|
2
2
|
import type { ToolSession } from ".";
|
|
3
3
|
|
|
4
4
|
export interface EvalBackendsAllowance {
|
|
@@ -6,21 +6,6 @@ export interface EvalBackendsAllowance {
|
|
|
6
6
|
js: boolean;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
/**
|
|
10
|
-
* Parse PI_PY / PI_JS environment variables. Each is a boolean flag; unset
|
|
11
|
-
* means "not specified, defer to settings". Returns null when neither is set
|
|
12
|
-
* so the caller can fall through to `readEvalBackendsAllowance` per key.
|
|
13
|
-
*/
|
|
14
|
-
function getEvalBackendsFromEnv(): EvalBackendsAllowance | null {
|
|
15
|
-
const pyEnv = $env.PI_PY;
|
|
16
|
-
const jsEnv = $env.PI_JS;
|
|
17
|
-
if (pyEnv === undefined && jsEnv === undefined) return null;
|
|
18
|
-
return {
|
|
19
|
-
python: pyEnv === undefined ? true : $flag("PI_PY"),
|
|
20
|
-
js: jsEnv === undefined ? true : $flag("PI_JS"),
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
|
|
24
9
|
/** Read per-backend allowance from settings (defaults true). */
|
|
25
10
|
export function readEvalBackendsAllowance(session: ToolSession): EvalBackendsAllowance {
|
|
26
11
|
return {
|
|
@@ -34,5 +19,9 @@ export function readEvalBackendsAllowance(session: ToolSession): EvalBackendsAll
|
|
|
34
19
|
* override the per-key settings; otherwise settings (defaults true) win.
|
|
35
20
|
*/
|
|
36
21
|
export function resolveEvalBackends(session: ToolSession): EvalBackendsAllowance {
|
|
37
|
-
|
|
22
|
+
const settings = readEvalBackendsAllowance(session);
|
|
23
|
+
return {
|
|
24
|
+
python: $flag("PI_PY", settings.python),
|
|
25
|
+
js: $flag("PI_JS", settings.js),
|
|
26
|
+
};
|
|
38
27
|
}
|