@oh-my-pi/pi-coding-agent 15.9.67 → 15.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +136 -0
- package/dist/types/cli/args.d.ts +1 -1
- package/dist/types/cli/dry-balance-cli.d.ts +15 -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/commit/analysis/conventional.d.ts +2 -2
- package/dist/types/commit/analysis/summary.d.ts +2 -2
- package/dist/types/commit/changelog/generate.d.ts +2 -2
- package/dist/types/commit/changelog/index.d.ts +2 -2
- package/dist/types/commit/map-reduce/index.d.ts +3 -3
- package/dist/types/commit/map-reduce/map-phase.d.ts +2 -2
- package/dist/types/commit/map-reduce/reduce-phase.d.ts +2 -2
- package/dist/types/commit/model-selection.d.ts +10 -4
- package/dist/types/config/api-key-resolver.d.ts +34 -0
- package/dist/types/config/keybindings.d.ts +6 -1
- package/dist/types/config/model-id-affixes.d.ts +2 -0
- package/dist/types/config/model-registry.d.ts +25 -2
- package/dist/types/config/settings-schema.d.ts +41 -6
- package/dist/types/dap/config.d.ts +14 -1
- package/dist/types/dap/types.d.ts +10 -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/lsp/utils.d.ts +3 -2
- 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/chat-block.d.ts +64 -0
- package/dist/types/modes/components/custom-editor.d.ts +5 -1
- package/dist/types/modes/components/overlay-box.d.ts +17 -0
- package/dist/types/modes/components/plan-review-overlay.d.ts +59 -0
- package/dist/types/modes/components/plan-toc.d.ts +41 -0
- package/dist/types/modes/components/read-tool-group.d.ts +2 -0
- package/dist/types/modes/components/tool-execution.d.ts +18 -0
- package/dist/types/modes/components/transcript-container.d.ts +11 -0
- package/dist/types/modes/controllers/command-controller.d.ts +1 -0
- package/dist/types/modes/controllers/event-controller.d.ts +0 -1
- package/dist/types/modes/controllers/extension-ui-controller.d.ts +0 -1
- package/dist/types/modes/controllers/input-controller.d.ts +1 -1
- package/dist/types/modes/controllers/selector-controller.d.ts +1 -1
- package/dist/types/modes/controllers/streaming-reveal.d.ts +22 -0
- package/dist/types/modes/controllers/tan-command-controller.d.ts +6 -0
- package/dist/types/modes/index.d.ts +5 -4
- package/dist/types/modes/interactive-mode.d.ts +16 -6
- 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/theme/theme.d.ts +1 -1
- package/dist/types/modes/types.d.ts +19 -6
- package/dist/types/modes/utils/copy-targets.d.ts +21 -1
- package/dist/types/plan-mode/approved-plan.d.ts +27 -8
- package/dist/types/plan-mode/plan-protection.d.ts +4 -4
- package/dist/types/sdk.d.ts +3 -1
- package/dist/types/session/agent-session.d.ts +21 -0
- package/dist/types/session/messages.d.ts +12 -0
- package/dist/types/session/session-manager.d.ts +3 -1
- package/dist/types/slash-commands/types.d.ts +4 -6
- package/dist/types/task/executor.d.ts +14 -0
- package/dist/types/task/index.d.ts +1 -0
- package/dist/types/task/render.d.ts +3 -2
- package/dist/types/telemetry-export.d.ts +1 -1
- package/dist/types/tools/archive-reader.d.ts +5 -0
- package/dist/types/tools/ast-edit.d.ts +3 -0
- package/dist/types/tools/ast-grep.d.ts +3 -0
- package/dist/types/tools/bash.d.ts +1 -0
- package/dist/types/tools/eval-render.d.ts +1 -8
- package/dist/types/tools/fetch.d.ts +15 -7
- package/dist/types/tools/find.d.ts +8 -4
- package/dist/types/tools/grouped-file-output.d.ts +95 -12
- package/dist/types/tools/memory-render.d.ts +4 -1
- package/dist/types/tools/plan-mode-guard.d.ts +8 -9
- package/dist/types/tools/render-utils.d.ts +13 -9
- package/dist/types/tools/renderers.d.ts +16 -2
- package/dist/types/tools/search.d.ts +5 -1
- package/dist/types/tools/sqlite-reader.d.ts +1 -0
- package/dist/types/tools/todo.d.ts +3 -2
- package/dist/types/tools/write.d.ts +5 -0
- package/dist/types/tui/output-block.d.ts +16 -4
- package/dist/types/tui/status-line.d.ts +3 -0
- package/dist/types/utils/enhanced-paste.d.ts +20 -0
- package/dist/types/web/scrapers/github.d.ts +22 -0
- package/dist/types/web/search/providers/kimi.d.ts +1 -1
- 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/auto-thinking/classifier.ts +5 -1
- package/src/cli/args.ts +2 -2
- package/src/cli/dry-balance-cli.ts +52 -17
- package/src/cli/gallery-cli.ts +226 -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 +250 -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/commit/analysis/conventional.ts +2 -2
- package/src/commit/analysis/summary.ts +2 -2
- package/src/commit/changelog/generate.ts +2 -2
- package/src/commit/changelog/index.ts +2 -2
- package/src/commit/map-reduce/index.ts +3 -3
- package/src/commit/map-reduce/map-phase.ts +2 -2
- package/src/commit/map-reduce/reduce-phase.ts +2 -2
- package/src/commit/model-selection.ts +33 -9
- package/src/commit/pipeline.ts +4 -4
- package/src/config/api-key-resolver.ts +58 -0
- package/src/config/keybindings.ts +15 -6
- package/src/config/model-equivalence.ts +35 -12
- package/src/config/model-id-affixes.ts +39 -22
- package/src/config/model-registry.ts +41 -18
- package/src/config/settings-schema.ts +28 -5
- package/src/config/settings.ts +31 -2
- package/src/dap/client.ts +14 -16
- package/src/dap/config.ts +41 -2
- package/src/dap/defaults.json +1 -0
- package/src/dap/session.ts +1 -0
- package/src/dap/types.ts +10 -0
- package/src/debug/index.ts +40 -54
- package/src/edit/renderer.ts +111 -119
- package/src/eval/__tests__/agent-bridge.test.ts +75 -32
- package/src/eval/__tests__/llm-bridge.test.ts +90 -31
- package/src/eval/agent-bridge.ts +34 -7
- package/src/eval/llm-bridge.ts +8 -3
- package/src/extensibility/extensions/runner.ts +1 -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 +37 -27
- package/src/internal-urls/docs-index.generated.ts +10 -10
- package/src/lsp/client.ts +104 -55
- package/src/lsp/types.ts +10 -0
- package/src/lsp/utils.ts +3 -2
- package/src/main.ts +53 -56
- package/src/memories/index.ts +12 -5
- 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/mnemopi/backend.ts +5 -1
- package/src/modes/acp/acp-agent.ts +33 -26
- package/src/modes/components/assistant-message.ts +2 -9
- package/src/modes/components/chat-block.ts +111 -0
- package/src/modes/components/copy-selector.ts +1 -44
- package/src/modes/components/custom-editor.ts +33 -1
- package/src/modes/components/custom-message.ts +1 -3
- package/src/modes/components/execution-shared.ts +1 -2
- package/src/modes/components/hook-message.ts +1 -3
- package/src/modes/components/overlay-box.ts +108 -0
- package/src/modes/components/plan-review-overlay.ts +799 -0
- package/src/modes/components/plan-toc.ts +138 -0
- package/src/modes/components/read-tool-group.ts +20 -4
- package/src/modes/components/skill-message.ts +0 -1
- package/src/modes/components/status-line.ts +3 -5
- package/src/modes/components/tips.txt +1 -0
- package/src/modes/components/todo-reminder.ts +0 -2
- package/src/modes/components/tool-execution.ts +115 -90
- package/src/modes/components/transcript-container.ts +84 -24
- package/src/modes/components/user-message.ts +1 -2
- package/src/modes/controllers/command-controller-shared.ts +7 -6
- package/src/modes/controllers/command-controller.ts +70 -57
- package/src/modes/controllers/event-controller.ts +41 -40
- package/src/modes/controllers/extension-ui-controller.ts +10 -73
- package/src/modes/controllers/input-controller.ts +135 -122
- package/src/modes/controllers/mcp-command-controller.ts +69 -60
- package/src/modes/controllers/selector-controller.ts +25 -27
- package/src/modes/controllers/streaming-reveal.ts +212 -0
- package/src/modes/controllers/tan-command-controller.ts +173 -0
- package/src/modes/index.ts +5 -4
- package/src/modes/interactive-mode.ts +171 -82
- 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/setup-wizard/wizard-overlay.ts +1 -1
- package/src/modes/theme/theme-schema.json +1 -1
- package/src/modes/theme/theme.ts +8 -4
- package/src/modes/types.ts +19 -8
- package/src/modes/utils/context-usage.ts +10 -6
- package/src/modes/utils/copy-targets.ts +133 -27
- package/src/modes/utils/hotkeys-markdown.ts +1 -0
- package/src/modes/utils/ui-helpers.ts +44 -46
- package/src/plan-mode/approved-plan.ts +66 -43
- package/src/plan-mode/plan-protection.ts +4 -4
- package/src/prompts/system/background-tan-dispatch.md +8 -0
- package/src/prompts/system/plan-mode-active.md +67 -58
- package/src/prompts/system/plan-mode-approved.md +1 -1
- package/src/sdk.ts +32 -60
- package/src/session/agent-session.ts +89 -13
- package/src/session/messages.ts +26 -0
- package/src/session/session-manager.ts +13 -5
- package/src/slash-commands/builtin-registry.ts +37 -10
- package/src/slash-commands/helpers/usage-report.ts +2 -0
- package/src/slash-commands/types.ts +4 -6
- package/src/task/executor.ts +25 -4
- package/src/task/index.ts +4 -0
- package/src/task/render.ts +212 -148
- package/src/telemetry-export.ts +25 -7
- package/src/tools/archive-reader.ts +64 -0
- package/src/tools/ask.ts +119 -164
- package/src/tools/ast-edit.ts +98 -71
- package/src/tools/ast-grep.ts +37 -43
- package/src/tools/bash.ts +50 -6
- package/src/tools/debug.ts +20 -8
- package/src/tools/eval-backends.ts +6 -17
- package/src/tools/eval-render.ts +21 -18
- package/src/tools/eval.ts +5 -4
- package/src/tools/fetch.ts +391 -91
- package/src/tools/find.ts +44 -30
- package/src/tools/gh-renderer.ts +81 -42
- package/src/tools/grouped-file-output.ts +272 -48
- package/src/tools/image-gen.ts +150 -103
- package/src/tools/inspect-image-renderer.ts +63 -41
- package/src/tools/inspect-image.ts +8 -1
- package/src/tools/job.ts +3 -4
- package/src/tools/memory-render.ts +4 -1
- package/src/tools/plan-mode-guard.ts +21 -39
- package/src/tools/read.ts +23 -16
- package/src/tools/render-utils.ts +38 -40
- package/src/tools/renderers.ts +16 -1
- package/src/tools/report-tool-issue.ts +1 -1
- package/src/tools/resolve.ts +14 -0
- package/src/tools/search-tool-bm25.ts +36 -23
- package/src/tools/search.ts +189 -95
- package/src/tools/sqlite-reader.ts +9 -12
- package/src/tools/todo.ts +138 -59
- package/src/tools/write.ts +100 -60
- package/src/tui/output-block.ts +60 -13
- package/src/tui/status-line.ts +5 -1
- package/src/utils/commit-message-generator.ts +9 -1
- package/src/utils/enhanced-paste.ts +202 -0
- package/src/utils/title-generator.ts +2 -1
- package/src/web/scrapers/github.ts +255 -3
- package/src/web/scrapers/youtube.ts +3 -2
- package/src/web/search/providers/anthropic.ts +25 -19
- package/src/web/search/providers/exa.ts +11 -3
- package/src/web/search/providers/kimi.ts +28 -17
- package/src/web/search/providers/parallel.ts +35 -24
- package/src/web/search/providers/perplexity.ts +199 -51
- package/src/web/search/providers/synthetic.ts +8 -6
- package/src/web/search/providers/tavily.ts +9 -8
- package/src/web/search/providers/zai.ts +8 -6
- package/src/web/search/render.ts +39 -54
- package/src/web/search/types.ts +5 -1
- package/dist/types/eval/__tests__/shared-executors.test.d.ts +0 -1
- package/src/eval/__tests__/shared-executors.test.ts +0 -609
package/src/tools/ast-grep.ts
CHANGED
|
@@ -14,7 +14,7 @@ import { Ellipsis, fileHyperlink, renderStatusLine, renderTreeList, truncateToWi
|
|
|
14
14
|
import { resolveFileDisplayMode } from "../utils/file-display-mode";
|
|
15
15
|
import type { ToolSession } from ".";
|
|
16
16
|
import { createFileRecorder, formatResultPath } from "./file-recorder";
|
|
17
|
-
import { formatGroupedFiles } from "./grouped-file-output";
|
|
17
|
+
import { classifyGroupedLines, formatGroupedFiles, groupLineIndicesByBlank } from "./grouped-file-output";
|
|
18
18
|
import { formatMatchLine } from "./match-line-format";
|
|
19
19
|
import type { OutputMeta } from "./output-meta";
|
|
20
20
|
import { resolveToolSearchScope } from "./path-utils";
|
|
@@ -29,7 +29,6 @@ import {
|
|
|
29
29
|
formatParseErrors,
|
|
30
30
|
formatParseErrorsCountLabel,
|
|
31
31
|
PREVIEW_LIMITS,
|
|
32
|
-
splitGroupsByBlankLine,
|
|
33
32
|
} from "./render-utils";
|
|
34
33
|
import { ToolError } from "./tool-errors";
|
|
35
34
|
import { toolResult } from "./tool-result";
|
|
@@ -118,6 +117,9 @@ export interface AstGrepToolDetails {
|
|
|
118
117
|
/** Absolute base directory used during search. Used by the renderer to resolve
|
|
119
118
|
* display-relative paths to absolute paths for OSC 8 hyperlinks. */
|
|
120
119
|
searchPath?: string;
|
|
120
|
+
/** Session cwd at search time. Display header/match paths are cwd-relative, so
|
|
121
|
+
* the renderer resolves them against this; `searchPath` is the scope target. */
|
|
122
|
+
cwd?: string;
|
|
121
123
|
}
|
|
122
124
|
|
|
123
125
|
export class AstGrepTool implements AgentTool<typeof astGrepSchema, AstGrepToolDetails> {
|
|
@@ -207,6 +209,7 @@ export class AstGrepTool implements AgentTool<typeof astGrepSchema, AstGrepToolD
|
|
|
207
209
|
...(cappedParseErrors.length > 0 ? { parseErrors: cappedParseErrors, parseErrorsTotal } : {}),
|
|
208
210
|
scopePath,
|
|
209
211
|
searchPath: resolvedSearchPath,
|
|
212
|
+
cwd: this.session.cwd,
|
|
210
213
|
files: fileList,
|
|
211
214
|
fileMatches: [],
|
|
212
215
|
};
|
|
@@ -381,15 +384,41 @@ export const astGrepToolRenderer = {
|
|
|
381
384
|
if (limitReached) meta.push(uiTheme.fg("warning", "limit reached"));
|
|
382
385
|
const description = args?.pat;
|
|
383
386
|
const header = renderStatusLine(
|
|
384
|
-
{
|
|
387
|
+
{
|
|
388
|
+
...(limitReached
|
|
389
|
+
? { icon: "warning" as const }
|
|
390
|
+
: { iconOverride: uiTheme.fg("accent", uiTheme.symbol("icon.search")) }),
|
|
391
|
+
title: "AST Grep",
|
|
392
|
+
description,
|
|
393
|
+
meta,
|
|
394
|
+
},
|
|
385
395
|
uiTheme,
|
|
386
396
|
);
|
|
387
397
|
|
|
388
398
|
const textContent = result.details?.displayContent ?? result.content?.find(c => c.type === "text")?.text ?? "";
|
|
389
|
-
const
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
);
|
|
399
|
+
const allLines = textContent.split("\n");
|
|
400
|
+
// Resolve hyperlinks over the whole output so nested directory headers
|
|
401
|
+
// reconstruct across the blank-line groups the tree list collapses by.
|
|
402
|
+
const contexts = classifyGroupedLines(allLines, details?.cwd ?? details?.searchPath, details?.searchPath);
|
|
403
|
+
const styledLines = allLines.map((line, index) => {
|
|
404
|
+
const ctx = contexts[index]!;
|
|
405
|
+
if (ctx.kind === "dir") {
|
|
406
|
+
const styled = uiTheme.fg("accent", line);
|
|
407
|
+
return ctx.headerPath ? fileHyperlink(ctx.headerPath, styled) : styled;
|
|
408
|
+
}
|
|
409
|
+
if (ctx.kind === "file") {
|
|
410
|
+
const styled = uiTheme.fg(ctx.depth === 1 ? "accent" : "dim", line);
|
|
411
|
+
return ctx.headerPath ? fileHyperlink(ctx.headerPath, styled) : styled;
|
|
412
|
+
}
|
|
413
|
+
if (line.startsWith(" meta:")) return uiTheme.fg("dim", line);
|
|
414
|
+
return uiTheme.fg("toolOutput", line);
|
|
415
|
+
});
|
|
416
|
+
const matchGroups = groupLineIndicesByBlank(allLines)
|
|
417
|
+
.filter(indices => {
|
|
418
|
+
const first = allLines[indices[0]!]!;
|
|
419
|
+
return !first.startsWith("Result limit reached") && !first.startsWith("Parse issues:");
|
|
420
|
+
})
|
|
421
|
+
.map(indices => indices.map(index => styledLines[index]!));
|
|
393
422
|
|
|
394
423
|
const extraLines: string[] = [];
|
|
395
424
|
if (limitReached) {
|
|
@@ -404,7 +433,6 @@ export const astGrepToolRenderer = {
|
|
|
404
433
|
return createCachedComponent(
|
|
405
434
|
() => options.expanded,
|
|
406
435
|
width => {
|
|
407
|
-
const searchBase = details?.searchPath;
|
|
408
436
|
const matchLines = renderTreeList(
|
|
409
437
|
{
|
|
410
438
|
items: matchGroups,
|
|
@@ -412,41 +440,7 @@ export const astGrepToolRenderer = {
|
|
|
412
440
|
maxCollapsed: matchGroups.length,
|
|
413
441
|
maxCollapsedLines: COLLAPSED_MATCH_LIMIT,
|
|
414
442
|
itemType: "match",
|
|
415
|
-
renderItem: group =>
|
|
416
|
-
let contextDir = searchBase ?? "";
|
|
417
|
-
return group.map(line => {
|
|
418
|
-
if (line.startsWith("## ")) {
|
|
419
|
-
const fileName = line
|
|
420
|
-
.slice(3)
|
|
421
|
-
.trimEnd()
|
|
422
|
-
.replace(/\s+\([^)]*\)\s*$/, "")
|
|
423
|
-
.replace(/#[0-9a-f]+$/, "");
|
|
424
|
-
const absPath = contextDir && fileName ? path.join(contextDir, fileName) : undefined;
|
|
425
|
-
const styled = uiTheme.fg("dim", line);
|
|
426
|
-
return absPath ? fileHyperlink(absPath, styled) : styled;
|
|
427
|
-
}
|
|
428
|
-
if (line.startsWith("# ")) {
|
|
429
|
-
const raw = line
|
|
430
|
-
.slice(2)
|
|
431
|
-
.trimEnd()
|
|
432
|
-
.replace(/\s+\([^)]*\)\s*$/, "");
|
|
433
|
-
const isDirectory = raw.endsWith("/");
|
|
434
|
-
const name = isDirectory ? raw.replace(/\/$/, "") : raw.replace(/#[0-9a-f]+$/, "");
|
|
435
|
-
if (isDirectory) {
|
|
436
|
-
if (searchBase) {
|
|
437
|
-
contextDir = name === "." ? searchBase : path.join(searchBase, name);
|
|
438
|
-
}
|
|
439
|
-
return uiTheme.fg("accent", line);
|
|
440
|
-
}
|
|
441
|
-
// Root-level file (single # without trailing slash) from formatGroupedFiles.
|
|
442
|
-
const absPath = searchBase && name ? path.join(searchBase, name) : undefined;
|
|
443
|
-
const styled = uiTheme.fg("accent", line);
|
|
444
|
-
return absPath ? fileHyperlink(absPath, styled) : styled;
|
|
445
|
-
}
|
|
446
|
-
if (line.startsWith(" meta:")) return uiTheme.fg("dim", line);
|
|
447
|
-
return uiTheme.fg("toolOutput", line);
|
|
448
|
-
});
|
|
449
|
-
},
|
|
443
|
+
renderItem: group => group,
|
|
450
444
|
},
|
|
451
445
|
uiTheme,
|
|
452
446
|
);
|
package/src/tools/bash.ts
CHANGED
|
@@ -287,6 +287,35 @@ function formatExitCodeNotice(exitCode: number): string {
|
|
|
287
287
|
return `Command exited with code ${exitCode}`;
|
|
288
288
|
}
|
|
289
289
|
|
|
290
|
+
const RAW_OUTPUT_ARTIFACT_PREFIX = "[raw output: artifact://";
|
|
291
|
+
const RAW_OUTPUT_ARTIFACT_SUFFIX = "]";
|
|
292
|
+
|
|
293
|
+
function stripRawOutputArtifactNotice(text: string): { text: string; artifactId?: string } {
|
|
294
|
+
const trimmed = text.trimEnd();
|
|
295
|
+
const lineStart = trimmed.lastIndexOf("\n");
|
|
296
|
+
const candidateStart = lineStart === -1 ? 0 : lineStart + 1;
|
|
297
|
+
if (
|
|
298
|
+
!trimmed.startsWith(RAW_OUTPUT_ARTIFACT_PREFIX, candidateStart) ||
|
|
299
|
+
!trimmed.endsWith(RAW_OUTPUT_ARTIFACT_SUFFIX)
|
|
300
|
+
) {
|
|
301
|
+
return { text };
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const idStart = candidateStart + RAW_OUTPUT_ARTIFACT_PREFIX.length;
|
|
305
|
+
const idEnd = trimmed.length - RAW_OUTPUT_ARTIFACT_SUFFIX.length;
|
|
306
|
+
if (idStart === idEnd) return { text };
|
|
307
|
+
for (let i = idStart; i < idEnd; i++) {
|
|
308
|
+
const code = trimmed.charCodeAt(i);
|
|
309
|
+
if (code < 48 || code > 57) return { text };
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const artifactId = trimmed.slice(idStart, idEnd);
|
|
313
|
+
return {
|
|
314
|
+
text: trimmed.slice(0, lineStart === -1 ? 0 : lineStart).trimEnd(),
|
|
315
|
+
artifactId,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
290
319
|
/**
|
|
291
320
|
* Strip the trailing occurrence of `notice` (plus a single surrounding newline
|
|
292
321
|
* on each side) so the TUI can echo the value via a styled footer label
|
|
@@ -1028,6 +1057,7 @@ export interface ShellRendererConfig<TArgs> {
|
|
|
1028
1057
|
resolveCommand?: (args: TArgs | undefined) => string | undefined;
|
|
1029
1058
|
resolveCwd?: (args: TArgs | undefined) => string | undefined;
|
|
1030
1059
|
resolveEnv?: (args: TArgs | undefined) => Record<string, string> | undefined;
|
|
1060
|
+
showHeader?: boolean;
|
|
1031
1061
|
}
|
|
1032
1062
|
|
|
1033
1063
|
function getPartialJson<TArgs>(args: TArgs | undefined): string | undefined {
|
|
@@ -1079,9 +1109,11 @@ export function createShellRenderer<TArgs>(config: ShellRendererConfig<TArgs>) {
|
|
|
1079
1109
|
return {
|
|
1080
1110
|
renderCall(args: TArgs, options: RenderResultOptions, uiTheme: Theme): Component {
|
|
1081
1111
|
const renderArgs = toBashRenderArgs(args, config);
|
|
1082
|
-
const title = config.resolveTitle(args, options);
|
|
1083
1112
|
const cmdLines = formatBashCommandLines(renderArgs, uiTheme);
|
|
1084
|
-
const header =
|
|
1113
|
+
const header =
|
|
1114
|
+
config.showHeader === false
|
|
1115
|
+
? undefined
|
|
1116
|
+
: renderStatusLine({ icon: "pending", title: config.resolveTitle(args, options) }, uiTheme);
|
|
1085
1117
|
const outputBlock = new CachedOutputBlock();
|
|
1086
1118
|
return markFramedBlockComponent({
|
|
1087
1119
|
render: (width: number): string[] =>
|
|
@@ -1115,8 +1147,10 @@ export function createShellRenderer<TArgs>(config: ShellRendererConfig<TArgs>) {
|
|
|
1115
1147
|
const cmdLines = args ? formatBashCommandLines(renderArgs, uiTheme) : undefined;
|
|
1116
1148
|
const isError = result.isError === true;
|
|
1117
1149
|
const icon = options.isPartial ? "pending" : isError ? "error" : "success";
|
|
1118
|
-
const
|
|
1119
|
-
|
|
1150
|
+
const header =
|
|
1151
|
+
config.showHeader === false
|
|
1152
|
+
? undefined
|
|
1153
|
+
: renderStatusLine({ icon, title: config.resolveTitle(args, options) }, uiTheme);
|
|
1120
1154
|
const details = result.details;
|
|
1121
1155
|
const outputBlock = new CachedOutputBlock();
|
|
1122
1156
|
|
|
@@ -1133,7 +1167,9 @@ export function createShellRenderer<TArgs>(config: ShellRendererConfig<TArgs>) {
|
|
|
1133
1167
|
const rawOutput = renderContext?.output ?? result.content?.find(c => c.type === "text")?.text ?? "";
|
|
1134
1168
|
const strippedOutput = stripOutputNotice(rawOutput, details?.meta);
|
|
1135
1169
|
const withoutExit = stripExitCodeNotice(strippedOutput, details?.exitCode);
|
|
1136
|
-
const
|
|
1170
|
+
const withoutWall = stripWallTimeNotice(withoutExit, details?.wallTimeMs);
|
|
1171
|
+
const rawOutputArtifact = stripRawOutputArtifactNotice(withoutWall);
|
|
1172
|
+
const output = rawOutputArtifact.text;
|
|
1137
1173
|
const displayOutput = output.trimEnd();
|
|
1138
1174
|
const showingFullOutput = expanded && renderContext?.isFullOutput === true;
|
|
1139
1175
|
|
|
@@ -1152,6 +1188,9 @@ export function createShellRenderer<TArgs>(config: ShellRendererConfig<TArgs>) {
|
|
|
1152
1188
|
: `Timeout: ${timeoutSeconds}s`,
|
|
1153
1189
|
);
|
|
1154
1190
|
}
|
|
1191
|
+
if (rawOutputArtifact.artifactId) {
|
|
1192
|
+
statsParts.push(`Artifact: ${rawOutputArtifact.artifactId}`);
|
|
1193
|
+
}
|
|
1155
1194
|
if (isError && typeof details?.exitCode === "number") {
|
|
1156
1195
|
statsParts.push(`Exit: ${details.exitCode}`);
|
|
1157
1196
|
}
|
|
@@ -1215,7 +1254,11 @@ export function createShellRenderer<TArgs>(config: ShellRendererConfig<TArgs>) {
|
|
|
1215
1254
|
{ label: uiTheme.fg("toolTitle", "Output"), lines: outputLines },
|
|
1216
1255
|
],
|
|
1217
1256
|
width,
|
|
1218
|
-
animate:
|
|
1257
|
+
// Don't animate once the command has been backgrounded: the block
|
|
1258
|
+
// gets committed to scrollback and finalizes later via the async
|
|
1259
|
+
// update path, so a mid-sweep frame would freeze a stray dark
|
|
1260
|
+
// border segment.
|
|
1261
|
+
animate: options.isPartial && shimmerEnabled() && details?.async?.state !== "running",
|
|
1219
1262
|
},
|
|
1220
1263
|
uiTheme,
|
|
1221
1264
|
);
|
|
@@ -1235,4 +1278,5 @@ export const bashToolRenderer = createShellRenderer<BashRenderArgs>({
|
|
|
1235
1278
|
resolveCommand: args => args?.command,
|
|
1236
1279
|
resolveCwd: args => args?.cwd,
|
|
1237
1280
|
resolveEnv: args => args?.env,
|
|
1281
|
+
showHeader: false,
|
|
1238
1282
|
});
|
package/src/tools/debug.ts
CHANGED
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
type DapFunctionBreakpointRecord,
|
|
23
23
|
type DapInstructionBreakpointRecord,
|
|
24
24
|
type DapModule,
|
|
25
|
+
type DapResolvedAdapter,
|
|
25
26
|
type DapScope,
|
|
26
27
|
type DapSessionSummary,
|
|
27
28
|
type DapSource,
|
|
@@ -30,6 +31,8 @@ import {
|
|
|
30
31
|
type DapVariable,
|
|
31
32
|
dapSessionManager,
|
|
32
33
|
getAvailableAdapters,
|
|
34
|
+
type LaunchProgramKind,
|
|
35
|
+
resolveLaunchOverrides,
|
|
33
36
|
selectAttachAdapter,
|
|
34
37
|
selectLaunchAdapter,
|
|
35
38
|
} from "../dap";
|
|
@@ -489,16 +492,23 @@ function getConfiguredAdapters(cwd: string): string {
|
|
|
489
492
|
const adapters = getAvailableAdapters(cwd).map(adapter => adapter.name);
|
|
490
493
|
return adapters.length > 0 ? adapters.join(", ") : "none";
|
|
491
494
|
}
|
|
492
|
-
|
|
493
|
-
|
|
495
|
+
|
|
496
|
+
async function classifyLaunchProgram(program: string): Promise<LaunchProgramKind> {
|
|
494
497
|
try {
|
|
495
|
-
|
|
498
|
+
return (await fs.stat(program)).isDirectory() ? "directory" : "file";
|
|
496
499
|
} catch (error) {
|
|
497
|
-
if (isEnoent(error)) return;
|
|
500
|
+
if (isEnoent(error)) return "missing";
|
|
498
501
|
throw error;
|
|
499
502
|
}
|
|
500
|
-
|
|
503
|
+
}
|
|
501
504
|
|
|
505
|
+
function validateLaunchProgram(
|
|
506
|
+
program: string,
|
|
507
|
+
cwd: string,
|
|
508
|
+
programKind: LaunchProgramKind,
|
|
509
|
+
adapter: DapResolvedAdapter,
|
|
510
|
+
): void {
|
|
511
|
+
if (programKind !== "directory" || adapter.acceptsDirectoryProgram) return;
|
|
502
512
|
const displayPath = formatPathRelativeToCwd(program, cwd, { trailingSlash: true });
|
|
503
513
|
throw new ToolError(
|
|
504
514
|
`launch program resolves to a directory: ${displayPath}. Pass an executable file path, or for Python use adapter "debugpy" with program set to the .py file.`,
|
|
@@ -676,8 +686,8 @@ export class DebugTool implements AgentTool<typeof debugSchema, DebugToolDetails
|
|
|
676
686
|
}
|
|
677
687
|
const commandCwd = params.cwd ? resolveToCwd(params.cwd, this.session.cwd) : this.session.cwd;
|
|
678
688
|
const program = resolveToCwd(params.program, commandCwd);
|
|
679
|
-
await
|
|
680
|
-
const adapter = selectLaunchAdapter(program, commandCwd, params.adapter);
|
|
689
|
+
const programKind = await classifyLaunchProgram(program);
|
|
690
|
+
const adapter = selectLaunchAdapter(program, commandCwd, params.adapter, programKind);
|
|
681
691
|
if (!adapter) {
|
|
682
692
|
if (params.adapter === "debugpy") {
|
|
683
693
|
throw new ToolError("adapter 'debugpy' is not available: python not found in PATH");
|
|
@@ -686,8 +696,10 @@ export class DebugTool implements AgentTool<typeof debugSchema, DebugToolDetails
|
|
|
686
696
|
`No debugger adapter available. Installed adapters: ${getConfiguredAdapters(commandCwd)}`,
|
|
687
697
|
);
|
|
688
698
|
}
|
|
699
|
+
validateLaunchProgram(program, commandCwd, programKind, adapter);
|
|
700
|
+
const extraLaunchArguments = resolveLaunchOverrides(adapter, program, programKind);
|
|
689
701
|
const snapshot = await dapSessionManager.launch(
|
|
690
|
-
{ adapter, program, args: params.args, cwd: commandCwd },
|
|
702
|
+
{ adapter, program, args: params.args, cwd: commandCwd, extraLaunchArguments },
|
|
691
703
|
combinedSignal,
|
|
692
704
|
timeoutSec * 1000,
|
|
693
705
|
);
|
|
@@ -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
|
}
|
package/src/tools/eval-render.ts
CHANGED
|
@@ -40,14 +40,6 @@ import {
|
|
|
40
40
|
wrapBrackets,
|
|
41
41
|
} from "./render-utils";
|
|
42
42
|
export const EVAL_DEFAULT_PREVIEW_LINES = 10;
|
|
43
|
-
/**
|
|
44
|
-
* Rows of source kept in the *pending* eval preview. The window follows the
|
|
45
|
-
* streaming edge (newest lines pinned to the bottom) so you can watch the code
|
|
46
|
-
* being written, while staying bounded — a volatile tool block taller than the
|
|
47
|
-
* viewport would otherwise strand its scrolled-off head out of native scrollback
|
|
48
|
-
* on ED3-risk terminals. Matches the streaming windows used by edit/write.
|
|
49
|
-
*/
|
|
50
|
-
export const EVAL_STREAMING_PREVIEW_LINES = 12;
|
|
51
43
|
|
|
52
44
|
function languageForHighlighter(language: EvalLanguage | undefined): "python" | "javascript" {
|
|
53
45
|
return language === "js" ? "javascript" : "python";
|
|
@@ -517,15 +509,12 @@ export const evalToolRenderer = {
|
|
|
517
509
|
title: cell.title,
|
|
518
510
|
status: "pending",
|
|
519
511
|
width,
|
|
520
|
-
|
|
521
|
-
//
|
|
522
|
-
//
|
|
523
|
-
//
|
|
524
|
-
//
|
|
525
|
-
|
|
526
|
-
// out of native scrollback, cutting the box top. `Ctrl+O` lifts
|
|
527
|
-
// the window via `expanded` for a deliberate full view.
|
|
528
|
-
codeTail: true,
|
|
512
|
+
// Always render the full source: the code is fixed input, not the
|
|
513
|
+
// streaming part, so it is never compacted. While still pending
|
|
514
|
+
// (args streaming) the block is not yet committed to native
|
|
515
|
+
// scrollback — its head is only committed once a result exists and
|
|
516
|
+
// the code has finalized (see `isStreamingPreviewAppendOnly`).
|
|
517
|
+
codeMaxLines: Number.POSITIVE_INFINITY,
|
|
529
518
|
expanded: options.expanded,
|
|
530
519
|
animate,
|
|
531
520
|
},
|
|
@@ -628,7 +617,9 @@ export const evalToolRenderer = {
|
|
|
628
617
|
duration: cell.durationMs,
|
|
629
618
|
output: outputLines.length > 0 ? outputLines.join("\n") : undefined,
|
|
630
619
|
outputMaxLines: outputLines.length,
|
|
631
|
-
|
|
620
|
+
// Code is fixed input — always shown in full, never compacted.
|
|
621
|
+
// Only `output` honors the collapsed preview cap above.
|
|
622
|
+
codeMaxLines: Number.POSITIVE_INFINITY,
|
|
632
623
|
expanded,
|
|
633
624
|
width,
|
|
634
625
|
animate,
|
|
@@ -760,6 +751,18 @@ export const evalToolRenderer = {
|
|
|
760
751
|
},
|
|
761
752
|
};
|
|
762
753
|
},
|
|
754
|
+
|
|
755
|
+
// Append-only once a result exists (args complete → code finalized). The code
|
|
756
|
+
// is rendered in full as a fixed top-anchored prefix, and the streamed stdout
|
|
757
|
+
// below it only appends rows at the bottom, so the scrolled-off head commits
|
|
758
|
+
// to native scrollback instead of being yanked — collapsed or expanded, since
|
|
759
|
+
// the collapsed output cap keeps its sliding tail in the bottom live region.
|
|
760
|
+
// Returns false while still pending: the code is mid-stream (args incomplete)
|
|
761
|
+
// and its header still reads "pending", so committing it would strand a stale
|
|
762
|
+
// pending preview in history.
|
|
763
|
+
isStreamingPreviewAppendOnly(_args: EvalRenderArgs, _options: RenderResultOptions, result?: unknown): boolean {
|
|
764
|
+
return result != null;
|
|
765
|
+
},
|
|
763
766
|
mergeCallAndResult: true,
|
|
764
767
|
inline: true,
|
|
765
768
|
};
|
package/src/tools/eval.ts
CHANGED
|
@@ -130,11 +130,12 @@ function timeoutSecondsFromMs(timeoutMs: number): number {
|
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
async function resolveBackend(session: ToolSession, language: EvalLanguage): Promise<ResolvedBackend> {
|
|
133
|
-
const
|
|
134
|
-
const
|
|
133
|
+
const backends = resolveEvalBackends(session);
|
|
134
|
+
const allowPy = backends.python;
|
|
135
|
+
const allowJs = backends.js;
|
|
135
136
|
|
|
136
137
|
if (language === "python") {
|
|
137
|
-
if (!allowPy) throw new ToolError("Python backend is disabled (eval.py = false).");
|
|
138
|
+
if (!allowPy) throw new ToolError("Python backend is disabled (PI_PY=0 or eval.py = false).");
|
|
138
139
|
if (!(await pythonBackend.isAvailable(session))) {
|
|
139
140
|
throw new ToolError(
|
|
140
141
|
'Python backend is unavailable in this session. Pass language: "js" or install the python kernel.',
|
|
@@ -142,7 +143,7 @@ async function resolveBackend(session: ToolSession, language: EvalLanguage): Pro
|
|
|
142
143
|
}
|
|
143
144
|
return { backend: pythonBackend };
|
|
144
145
|
}
|
|
145
|
-
if (!allowJs) throw new ToolError("JavaScript backend is disabled (eval.js = false).");
|
|
146
|
+
if (!allowJs) throw new ToolError("JavaScript backend is disabled (PI_JS=0 or eval.js = false).");
|
|
146
147
|
return { backend: jsBackend };
|
|
147
148
|
}
|
|
148
149
|
|