@tomsun28/pizza 0.1.0 → 0.1.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/README.md +20 -143
- package/README.zh-CN.md +36 -0
- package/dist/bun/cli.d.ts +2 -0
- package/dist/bun/cli.js +6 -0
- package/dist/bun/register-bedrock.d.ts +1 -0
- package/dist/bun/register-bedrock.js +3 -0
- package/dist/cli/args.d.ts +48 -0
- package/dist/cli/args.js +330 -0
- package/dist/cli/config-selector.d.ts +13 -0
- package/dist/cli/config-selector.js +30 -0
- package/dist/cli/file-processor.d.ts +14 -0
- package/dist/cli/file-processor.js +82 -0
- package/dist/cli/initial-message.d.ts +17 -0
- package/dist/cli/initial-message.js +21 -0
- package/dist/cli/list-models.d.ts +8 -0
- package/dist/cli/list-models.js +96 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +68 -0
- package/dist/config.d.ts +79 -0
- package/dist/config.js +223 -0
- package/dist/core/agent/index.d.ts +6 -0
- package/dist/core/agent/index.js +6 -0
- package/dist/core/agent/types.d.ts +202 -0
- package/dist/core/agent/types.js +51 -0
- package/dist/core/auth-storage.d.ts +135 -0
- package/dist/core/auth-storage.js +417 -0
- package/dist/core/bash-executor.d.ts +31 -0
- package/dist/core/bash-executor.js +107 -0
- package/dist/core/compaction/branch-summarization.d.ts +87 -0
- package/dist/core/compaction/branch-summarization.js +242 -0
- package/dist/core/compaction/compaction-engine.d.ts +40 -0
- package/dist/core/compaction/compaction-engine.js +292 -0
- package/dist/core/compaction/compaction.d.ts +106 -0
- package/dist/core/compaction/compaction.js +295 -0
- package/dist/core/compaction/index.d.ts +7 -0
- package/dist/core/compaction/index.js +7 -0
- package/dist/core/compaction/utils.d.ts +37 -0
- package/dist/core/compaction/utils.js +152 -0
- package/dist/core/defaults.d.ts +2 -0
- package/dist/core/defaults.js +1 -0
- package/dist/core/diagnostics.d.ts +14 -0
- package/dist/core/diagnostics.js +1 -0
- package/dist/core/event-bus.d.ts +8 -0
- package/dist/core/event-bus.js +24 -0
- package/dist/core/event-store/events.d.ts +465 -0
- package/dist/core/event-store/events.js +6 -0
- package/dist/core/event-store/index.d.ts +10 -0
- package/dist/core/event-store/index.js +10 -0
- package/dist/core/event-store/sqlite-store.d.ts +27 -0
- package/dist/core/event-store/sqlite-store.js +275 -0
- package/dist/core/event-store/store.d.ts +91 -0
- package/dist/core/event-store/store.js +7 -0
- package/dist/core/event-store/thread-scoped-store.d.ts +29 -0
- package/dist/core/event-store/thread-scoped-store.js +50 -0
- package/dist/core/event-store/types.d.ts +70 -0
- package/dist/core/event-store/types.js +7 -0
- package/dist/core/event-store/workspace.d.ts +37 -0
- package/dist/core/event-store/workspace.js +71 -0
- package/dist/core/exec.d.ts +28 -0
- package/dist/core/exec.js +74 -0
- package/dist/core/export-html/ansi-to-html.d.ts +21 -0
- package/dist/core/export-html/ansi-to-html.js +248 -0
- package/dist/core/export-html/index.d.ts +29 -0
- package/dist/core/export-html/index.js +186 -0
- package/dist/core/export-html/template.css +1017 -0
- package/dist/core/export-html/template.html +55 -0
- package/dist/core/export-html/template.js +1742 -0
- package/dist/core/export-html/tool-renderer.d.ts +39 -0
- package/dist/core/export-html/tool-renderer.js +94 -0
- package/dist/core/export-html/vendor/highlight.min.js +1213 -0
- package/dist/core/export-html/vendor/marked.min.js +6 -0
- package/dist/core/extensions/index.d.ts +12 -0
- package/dist/core/extensions/index.js +9 -0
- package/dist/core/extensions/loader.d.ts +24 -0
- package/dist/core/extensions/loader.js +492 -0
- package/dist/core/extensions/runner.d.ts +167 -0
- package/dist/core/extensions/runner.js +898 -0
- package/dist/core/extensions/session-context.d.ts +67 -0
- package/dist/core/extensions/session-context.js +272 -0
- package/dist/core/extensions/types.d.ts +1147 -0
- package/dist/core/extensions/types.js +44 -0
- package/dist/core/extensions/wrapper.d.ts +19 -0
- package/dist/core/extensions/wrapper.js +21 -0
- package/dist/core/footer-data-provider.d.ts +47 -0
- package/dist/core/footer-data-provider.js +321 -0
- package/dist/core/goal/index.d.ts +3 -0
- package/dist/core/goal/index.js +1 -0
- package/dist/core/goal/scheduler.d.ts +83 -0
- package/dist/core/goal/scheduler.js +154 -0
- package/dist/core/goal/types.d.ts +182 -0
- package/dist/core/goal/types.js +11 -0
- package/dist/core/index.d.ts +8 -0
- package/dist/core/index.js +8 -0
- package/dist/core/intent/classifier.d.ts +53 -0
- package/dist/core/intent/classifier.js +353 -0
- package/dist/core/intent/index.d.ts +8 -0
- package/dist/core/intent/index.js +8 -0
- package/dist/core/intent/tool-adapter.d.ts +31 -0
- package/dist/core/intent/tool-adapter.js +168 -0
- package/dist/core/intent/types.d.ts +71 -0
- package/dist/core/intent/types.js +6 -0
- package/dist/core/keybindings.d.ts +297 -0
- package/dist/core/keybindings.js +250 -0
- package/dist/core/messages.d.ts +30 -0
- package/dist/core/messages.js +134 -0
- package/dist/core/model-registry.d.ts +131 -0
- package/dist/core/model-registry.js +634 -0
- package/dist/core/model-resolver.d.ts +109 -0
- package/dist/core/model-resolver.js +486 -0
- package/dist/core/output-guard.d.ts +5 -0
- package/dist/core/output-guard.js +58 -0
- package/dist/core/package-manager.d.ts +196 -0
- package/dist/core/package-manager.js +1873 -0
- package/dist/core/projection/boundary-inferrer.d.ts +58 -0
- package/dist/core/projection/boundary-inferrer.js +122 -0
- package/dist/core/projection/event-to-message.d.ts +35 -0
- package/dist/core/projection/event-to-message.js +253 -0
- package/dist/core/projection/goal-projection.d.ts +67 -0
- package/dist/core/projection/goal-projection.js +339 -0
- package/dist/core/projection/index.d.ts +13 -0
- package/dist/core/projection/index.js +13 -0
- package/dist/core/projection/session-manager.d.ts +100 -0
- package/dist/core/projection/session-manager.js +331 -0
- package/dist/core/projection/session-projection.d.ts +58 -0
- package/dist/core/projection/session-projection.js +257 -0
- package/dist/core/projection/task-history.d.ts +13 -0
- package/dist/core/projection/task-history.js +61 -0
- package/dist/core/projection/timeline-projection.d.ts +82 -0
- package/dist/core/projection/timeline-projection.js +276 -0
- package/dist/core/projection/types.d.ts +69 -0
- package/dist/core/projection/types.js +6 -0
- package/dist/core/prompt-templates.d.ts +51 -0
- package/dist/core/prompt-templates.js +249 -0
- package/dist/core/resolve-config-value.d.ts +22 -0
- package/dist/core/resolve-config-value.js +125 -0
- package/dist/core/resource-loader.d.ts +193 -0
- package/dist/core/resource-loader.js +685 -0
- package/dist/core/runtime/ai-client.d.ts +12 -0
- package/dist/core/runtime/ai-client.js +153 -0
- package/dist/core/runtime/checkpoint.d.ts +12 -0
- package/dist/core/runtime/checkpoint.js +78 -0
- package/dist/core/runtime/index.d.ts +12 -0
- package/dist/core/runtime/index.js +12 -0
- package/dist/core/runtime/llm-types.d.ts +99 -0
- package/dist/core/runtime/llm-types.js +6 -0
- package/dist/core/runtime/local-runtime.d.ts +23 -0
- package/dist/core/runtime/local-runtime.js +59 -0
- package/dist/core/runtime/policies.d.ts +72 -0
- package/dist/core/runtime/policies.js +37 -0
- package/dist/core/runtime/reactor.d.ts +213 -0
- package/dist/core/runtime/reactor.js +992 -0
- package/dist/core/runtime/runtime.d.ts +191 -0
- package/dist/core/runtime/runtime.js +449 -0
- package/dist/core/runtime/types.d.ts +42 -0
- package/dist/core/runtime/types.js +1 -0
- package/dist/core/sdk.d.ts +12 -0
- package/dist/core/sdk.js +10 -0
- package/dist/core/session-context-builder.d.ts +9 -0
- package/dist/core/session-context-builder.js +87 -0
- package/dist/core/session-cwd.d.ts +18 -0
- package/dist/core/session-cwd.js +36 -0
- package/dist/core/session-facade-factory.d.ts +79 -0
- package/dist/core/session-facade-factory.js +460 -0
- package/dist/core/session-facade.d.ts +57 -0
- package/dist/core/session-facade.js +91 -0
- package/dist/core/session-listing.d.ts +30 -0
- package/dist/core/session-listing.js +168 -0
- package/dist/core/session-reader.d.ts +19 -0
- package/dist/core/session-reader.js +101 -0
- package/dist/core/session-ref.d.ts +7 -0
- package/dist/core/session-ref.js +25 -0
- package/dist/core/session-services.d.ts +51 -0
- package/dist/core/session-services.js +90 -0
- package/dist/core/session-stats.d.ts +43 -0
- package/dist/core/session-stats.js +41 -0
- package/dist/core/settings-manager.d.ts +236 -0
- package/dist/core/settings-manager.js +706 -0
- package/dist/core/skill-block-parser.d.ts +12 -0
- package/dist/core/skill-block-parser.js +15 -0
- package/dist/core/skills.d.ts +59 -0
- package/dist/core/skills.js +408 -0
- package/dist/core/slash-commands.d.ts +13 -0
- package/dist/core/slash-commands.js +17 -0
- package/dist/core/source-info.d.ts +17 -0
- package/dist/core/source-info.js +18 -0
- package/dist/core/system-prompt.d.ts +27 -0
- package/dist/core/system-prompt.js +179 -0
- package/dist/core/timings.d.ts +7 -0
- package/dist/core/timings.js +30 -0
- package/dist/core/tools/bash.d.ts +95 -0
- package/dist/core/tools/bash.js +513 -0
- package/dist/core/tools/builtin-commands.d.ts +75 -0
- package/dist/core/tools/builtin-commands.js +503 -0
- package/dist/core/tools/compat-commands.d.ts +12 -0
- package/dist/core/tools/compat-commands.js +1280 -0
- package/dist/core/tools/edit-diff.d.ts +59 -0
- package/dist/core/tools/edit-diff.js +263 -0
- package/dist/core/tools/edit.d.ts +49 -0
- package/dist/core/tools/edit.js +340 -0
- package/dist/core/tools/file-mutation-queue.d.ts +5 -0
- package/dist/core/tools/file-mutation-queue.js +36 -0
- package/dist/core/tools/find.d.ts +34 -0
- package/dist/core/tools/find.js +459 -0
- package/dist/core/tools/grep.d.ts +36 -0
- package/dist/core/tools/grep.js +422 -0
- package/dist/core/tools/index.d.ts +70 -0
- package/dist/core/tools/index.js +129 -0
- package/dist/core/tools/line-anchors.d.ts +33 -0
- package/dist/core/tools/line-anchors.js +151 -0
- package/dist/core/tools/ls.d.ts +36 -0
- package/dist/core/tools/ls.js +268 -0
- package/dist/core/tools/path-utils.d.ts +7 -0
- package/dist/core/tools/path-utils.js +80 -0
- package/dist/core/tools/read.d.ts +35 -0
- package/dist/core/tools/read.js +244 -0
- package/dist/core/tools/render-utils.d.ts +20 -0
- package/dist/core/tools/render-utils.js +48 -0
- package/dist/core/tools/session-split.d.ts +9 -0
- package/dist/core/tools/session-split.js +77 -0
- package/dist/core/tools/tool-definition-wrapper.d.ts +13 -0
- package/dist/core/tools/tool-definition-wrapper.js +32 -0
- package/dist/core/tools/truncate.d.ts +69 -0
- package/dist/core/tools/truncate.js +204 -0
- package/dist/core/tools/write.d.ts +25 -0
- package/dist/core/tools/write.js +211 -0
- package/dist/core/types/session-types.d.ts +123 -0
- package/dist/core/types/session-types.js +8 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +38 -0
- package/dist/main.d.ts +11 -2
- package/dist/main.js +577 -149
- package/dist/modes/event-mapper.d.ts +115 -0
- package/dist/modes/event-mapper.js +200 -0
- package/dist/modes/gui/server.d.ts +14 -0
- package/dist/modes/gui/server.js +1032 -0
- package/dist/modes/index.d.ts +10 -0
- package/dist/modes/index.js +9 -0
- package/dist/modes/interactive/assets/clankolas.png +0 -0
- package/dist/modes/interactive/components/armin.d.ts +33 -0
- package/dist/modes/interactive/components/armin.js +328 -0
- package/dist/modes/interactive/components/assistant-message.d.ts +19 -0
- package/dist/modes/interactive/components/assistant-message.js +115 -0
- package/dist/modes/interactive/components/bash-execution.d.ts +33 -0
- package/dist/modes/interactive/components/bash-execution.js +169 -0
- package/dist/modes/interactive/components/bordered-loader.d.ts +15 -0
- package/dist/modes/interactive/components/bordered-loader.js +50 -0
- package/dist/modes/interactive/components/branch-summary-message.d.ts +15 -0
- package/dist/modes/interactive/components/branch-summary-message.js +41 -0
- package/dist/modes/interactive/components/brand-header.d.ts +33 -0
- package/dist/modes/interactive/components/brand-header.js +235 -0
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +15 -0
- package/dist/modes/interactive/components/compaction-summary-message.js +42 -0
- package/dist/modes/interactive/components/config-selector.d.ts +70 -0
- package/dist/modes/interactive/components/config-selector.js +469 -0
- package/dist/modes/interactive/components/countdown-timer.d.ts +13 -0
- package/dist/modes/interactive/components/countdown-timer.js +27 -0
- package/dist/modes/interactive/components/custom-editor.d.ts +27 -0
- package/dist/modes/interactive/components/custom-editor.js +94 -0
- package/dist/modes/interactive/components/custom-message.d.ts +19 -0
- package/dist/modes/interactive/components/custom-message.js +73 -0
- package/dist/modes/interactive/components/daxnuts.d.ts +22 -0
- package/dist/modes/interactive/components/daxnuts.js +137 -0
- package/dist/modes/interactive/components/diff.d.ts +11 -0
- package/dist/modes/interactive/components/diff.js +132 -0
- package/dist/modes/interactive/components/dynamic-border.d.ts +14 -0
- package/dist/modes/interactive/components/dynamic-border.js +19 -0
- package/dist/modes/interactive/components/earendil-announcement.d.ts +4 -0
- package/dist/modes/interactive/components/earendil-announcement.js +39 -0
- package/dist/modes/interactive/components/extension-editor.d.ts +19 -0
- package/dist/modes/interactive/components/extension-editor.js +105 -0
- package/dist/modes/interactive/components/extension-input.d.ts +22 -0
- package/dist/modes/interactive/components/extension-input.js +54 -0
- package/dist/modes/interactive/components/extension-selector.d.ts +23 -0
- package/dist/modes/interactive/components/extension-selector.js +70 -0
- package/dist/modes/interactive/components/footer.d.ts +55 -0
- package/dist/modes/interactive/components/footer.js +207 -0
- package/dist/modes/interactive/components/index.d.ts +31 -0
- package/dist/modes/interactive/components/index.js +32 -0
- package/dist/modes/interactive/components/keybinding-hints.d.ts +7 -0
- package/dist/modes/interactive/components/keybinding-hints.js +21 -0
- package/dist/modes/interactive/components/login-dialog.d.ts +41 -0
- package/dist/modes/interactive/components/login-dialog.js +138 -0
- package/dist/modes/interactive/components/model-selector.d.ts +32 -0
- package/dist/modes/interactive/components/model-selector.js +209 -0
- package/dist/modes/interactive/components/oauth-selector.d.ts +18 -0
- package/dist/modes/interactive/components/oauth-selector.js +91 -0
- package/dist/modes/interactive/components/settings-selector.d.ts +57 -0
- package/dist/modes/interactive/components/settings-selector.js +299 -0
- package/dist/modes/interactive/components/show-images-selector.d.ts +9 -0
- package/dist/modes/interactive/components/show-images-selector.js +37 -0
- package/dist/modes/interactive/components/skill-invocation-message.d.ts +16 -0
- package/dist/modes/interactive/components/skill-invocation-message.js +44 -0
- package/dist/modes/interactive/components/theme-selector.d.ts +10 -0
- package/dist/modes/interactive/components/theme-selector.js +47 -0
- package/dist/modes/interactive/components/thinking-selector.d.ts +10 -0
- package/dist/modes/interactive/components/thinking-selector.js +50 -0
- package/dist/modes/interactive/components/timeline-view.d.ts +31 -0
- package/dist/modes/interactive/components/timeline-view.js +81 -0
- package/dist/modes/interactive/components/tool-execution.d.ts +64 -0
- package/dist/modes/interactive/components/tool-execution.js +305 -0
- package/dist/modes/interactive/components/tree-selector.d.ts +88 -0
- package/dist/modes/interactive/components/tree-selector.js +1072 -0
- package/dist/modes/interactive/components/user-message-selector.d.ts +29 -0
- package/dist/modes/interactive/components/user-message-selector.js +110 -0
- package/dist/modes/interactive/components/user-message.d.ts +9 -0
- package/dist/modes/interactive/components/user-message.js +27 -0
- package/dist/modes/interactive/components/visual-truncate.d.ts +23 -0
- package/dist/modes/interactive/components/visual-truncate.js +32 -0
- package/dist/modes/interactive/interactive-mode.d.ts +394 -0
- package/dist/modes/interactive/interactive-mode.js +4116 -0
- package/dist/modes/interactive/theme/dark.json +85 -0
- package/dist/modes/interactive/theme/light.json +84 -0
- package/dist/modes/interactive/theme/theme-schema.json +335 -0
- package/dist/modes/interactive/theme/theme.d.ts +80 -0
- package/dist/modes/interactive/theme/theme.js +973 -0
- package/dist/modes/print-mode.d.ts +27 -0
- package/dist/modes/print-mode.js +102 -0
- package/dist/modes/rpc/jsonl.d.ts +16 -0
- package/dist/modes/rpc/jsonl.js +48 -0
- package/dist/modes/rpc/rpc-client.d.ts +219 -0
- package/dist/modes/rpc/rpc-client.js +405 -0
- package/dist/modes/rpc/rpc-mode.d.ts +19 -0
- package/dist/modes/rpc/rpc-mode.js +381 -0
- package/dist/modes/rpc/rpc-types.d.ts +406 -0
- package/dist/modes/rpc/rpc-types.js +7 -0
- package/dist/package-manager-cli.d.ts +3 -0
- package/dist/package-manager-cli.js +233 -0
- package/dist/utils/changelog.d.ts +20 -0
- package/dist/utils/changelog.js +86 -0
- package/dist/utils/child-process.d.ts +10 -0
- package/dist/utils/child-process.js +77 -0
- package/dist/utils/clipboard-image.d.ts +10 -0
- package/dist/utils/clipboard-image.js +244 -0
- package/dist/utils/clipboard-native.d.ts +7 -0
- package/dist/utils/clipboard-native.js +13 -0
- package/dist/utils/clipboard.d.ts +1 -0
- package/dist/utils/clipboard.js +77 -0
- package/dist/utils/exif-orientation.d.ts +4 -0
- package/dist/utils/exif-orientation.js +157 -0
- package/dist/utils/frontmatter.d.ts +7 -0
- package/dist/utils/frontmatter.js +25 -0
- package/dist/utils/git.d.ts +25 -0
- package/dist/utils/git.js +162 -0
- package/dist/utils/image-convert.d.ts +8 -0
- package/dist/utils/image-convert.js +38 -0
- package/dist/utils/image-resize.d.ts +35 -0
- package/dist/utils/image-resize.js +136 -0
- package/dist/utils/mime.d.ts +1 -0
- package/dist/utils/mime.js +25 -0
- package/dist/utils/path-shims.d.ts +1 -0
- package/dist/utils/path-shims.js +90 -0
- package/dist/utils/paths.d.ts +6 -0
- package/dist/utils/paths.js +18 -0
- package/dist/utils/photon.d.ts +20 -0
- package/dist/utils/photon.js +120 -0
- package/dist/utils/shell.d.ts +29 -0
- package/dist/utils/shell.js +189 -0
- package/dist/utils/sleep.d.ts +4 -0
- package/dist/utils/sleep.js +16 -0
- package/dist/utils/tools-manager.d.ts +3 -0
- package/dist/utils/tools-manager.js +101 -0
- package/dist/vendor/bin/darwin-arm64/fd +0 -0
- package/dist/vendor/bin/darwin-arm64/rg +0 -0
- package/dist/vendor/bin/darwin-x64/fd +0 -0
- package/dist/vendor/bin/darwin-x64/rg +0 -0
- package/dist/vendor/bin/linux-arm64/fd +0 -0
- package/dist/vendor/bin/linux-arm64/rg +0 -0
- package/dist/vendor/bin/linux-x64/fd +0 -0
- package/dist/vendor/bin/linux-x64/rg +0 -0
- package/dist/vendor/bin/win32-arm64/fd.exe +0 -0
- package/dist/vendor/bin/win32-arm64/rg.exe +0 -0
- package/dist/vendor/bin/win32-x64/fd.exe +0 -0
- package/dist/vendor/bin/win32-x64/rg.exe +0 -0
- package/package.json +90 -26
- package/dist/extension/core.d.ts +0 -69
- package/dist/extension/core.js +0 -270
- package/dist/extension/core.js.map +0 -1
- package/dist/extension/index.d.ts +0 -14
- package/dist/extension/index.js +0 -374
- package/dist/extension/index.js.map +0 -1
- package/dist/main.js.map +0 -1
- package/themes/pizza.json +0 -87
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { Text } from "@earendil-works/pi-tui";
|
|
2
|
+
import { Type } from "@sinclair/typebox";
|
|
3
|
+
import { constants } from "fs";
|
|
4
|
+
import { access as fsAccess, readFile as fsReadFile } from "fs/promises";
|
|
5
|
+
import { keyHint } from "../../modes/interactive/components/keybinding-hints.js";
|
|
6
|
+
import { getLanguageFromPath, highlightCode } from "../../modes/interactive/theme/theme.js";
|
|
7
|
+
import { formatDimensionNote, resizeImage } from "../../utils/image-resize.js";
|
|
8
|
+
import { detectSupportedImageMimeTypeFromFile } from "../../utils/mime.js";
|
|
9
|
+
import { annotateTextWithLineAnchors } from "./line-anchors.js";
|
|
10
|
+
import { resolveReadPath } from "./path-utils.js";
|
|
11
|
+
import { getTextOutput, invalidArgText, replaceTabs, shortenPath, str } from "./render-utils.js";
|
|
12
|
+
import { wrapToolDefinition } from "./tool-definition-wrapper.js";
|
|
13
|
+
import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, truncateHead } from "./truncate.js";
|
|
14
|
+
const readSchema = Type.Object({
|
|
15
|
+
path: Type.String({ description: "Path to the file to read (relative or absolute)" }),
|
|
16
|
+
offset: Type.Optional(Type.Number({ description: "Line number to start reading from (1-indexed)" })),
|
|
17
|
+
limit: Type.Optional(Type.Number({ description: "Maximum number of lines to read" })),
|
|
18
|
+
anchors: Type.Optional(Type.Union([Type.Literal("line"), Type.Literal("none")], {
|
|
19
|
+
description: 'Whether to include hashline anchors in text output. "line" prefixes each line with <line>#<2-hex-hash> for use with edit range. Default: "line". Use "none" only when raw file text is required.',
|
|
20
|
+
})),
|
|
21
|
+
});
|
|
22
|
+
const defaultReadOperations = {
|
|
23
|
+
readFile: (path) => fsReadFile(path),
|
|
24
|
+
access: (path) => fsAccess(path, constants.R_OK),
|
|
25
|
+
detectImageMimeType: detectSupportedImageMimeTypeFromFile,
|
|
26
|
+
};
|
|
27
|
+
function formatReadCall(args, theme) {
|
|
28
|
+
const rawPath = str(args?.file_path ?? args?.path);
|
|
29
|
+
const path = rawPath !== null ? shortenPath(rawPath) : null;
|
|
30
|
+
const offset = args?.offset;
|
|
31
|
+
const limit = args?.limit;
|
|
32
|
+
const invalidArg = invalidArgText(theme);
|
|
33
|
+
let pathDisplay = path === null ? invalidArg : path ? theme.fg("accent", path) : theme.fg("toolOutput", "...");
|
|
34
|
+
if (offset !== undefined || limit !== undefined) {
|
|
35
|
+
const startLine = offset ?? 1;
|
|
36
|
+
const endLine = limit !== undefined ? startLine + limit - 1 : "";
|
|
37
|
+
pathDisplay += theme.fg("warning", `:${startLine}${endLine ? `-${endLine}` : ""}`);
|
|
38
|
+
}
|
|
39
|
+
return `${theme.fg("toolTitle", theme.bold("read"))} ${pathDisplay}`;
|
|
40
|
+
}
|
|
41
|
+
function trimTrailingEmptyLines(lines) {
|
|
42
|
+
let end = lines.length;
|
|
43
|
+
while (end > 0 && lines[end - 1] === "") {
|
|
44
|
+
end--;
|
|
45
|
+
}
|
|
46
|
+
return lines.slice(0, end);
|
|
47
|
+
}
|
|
48
|
+
function getNonVisionImageNote(model) {
|
|
49
|
+
if (!model || model.input.includes("image")) {
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
return "[Current model does not support images. The image will be omitted from this request.]";
|
|
53
|
+
}
|
|
54
|
+
function formatTextReadOutput(text, startLine, anchors) {
|
|
55
|
+
return anchors === "line" ? annotateTextWithLineAnchors(text, startLine) : text;
|
|
56
|
+
}
|
|
57
|
+
function normalizeTextForAnchors(text, anchors) {
|
|
58
|
+
return anchors === "line" ? text.replace(/\r\n/g, "\n").replace(/\r/g, "\n") : text;
|
|
59
|
+
}
|
|
60
|
+
function formatReadResult(args, result, options, theme, showImages) {
|
|
61
|
+
const rawPath = str(args?.file_path ?? args?.path);
|
|
62
|
+
const output = getTextOutput(result, showImages);
|
|
63
|
+
const lang = rawPath ? getLanguageFromPath(rawPath) : undefined;
|
|
64
|
+
const renderedLines = lang ? highlightCode(replaceTabs(output), lang) : output.split("\n");
|
|
65
|
+
const lines = trimTrailingEmptyLines(renderedLines);
|
|
66
|
+
const maxLines = options.expanded ? lines.length : 10;
|
|
67
|
+
const displayLines = lines.slice(0, maxLines);
|
|
68
|
+
const remaining = lines.length - maxLines;
|
|
69
|
+
let text = `\n${displayLines.map((line) => (lang ? replaceTabs(line) : theme.fg("toolOutput", replaceTabs(line)))).join("\n")}`;
|
|
70
|
+
if (remaining > 0) {
|
|
71
|
+
text += `${theme.fg("muted", `\n... (${remaining} more lines,`)} ${keyHint("app.tools.expand", "to expand")})`;
|
|
72
|
+
}
|
|
73
|
+
const truncation = result.details?.truncation;
|
|
74
|
+
if (truncation?.truncated) {
|
|
75
|
+
if (truncation.firstLineExceedsLimit) {
|
|
76
|
+
text += `\n${theme.fg("warning", `[First line exceeds ${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit]`)}`;
|
|
77
|
+
}
|
|
78
|
+
else if (truncation.truncatedBy === "lines") {
|
|
79
|
+
text += `\n${theme.fg("warning", `[Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines (${truncation.maxLines ?? DEFAULT_MAX_LINES} line limit)]`)}`;
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
text += `\n${theme.fg("warning", `[Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)]`)}`;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return text;
|
|
86
|
+
}
|
|
87
|
+
export function createReadToolDefinition(cwd, options) {
|
|
88
|
+
const autoResizeImages = options?.autoResizeImages ?? true;
|
|
89
|
+
const ops = options?.operations ?? defaultReadOperations;
|
|
90
|
+
return {
|
|
91
|
+
name: "read",
|
|
92
|
+
label: "read",
|
|
93
|
+
description: `Read the contents of a file. Supports text files and images (jpg, png, gif, webp). Images are sent as attachments. For text files, output is truncated to ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). Text output includes 2-hex hashline anchors by default (<line>#<hash> | content); pass anchors="none" only when raw text is required. Use offset/limit for large files. When you need the full file, continue with offset until complete.`,
|
|
94
|
+
promptSnippet: "Read file contents",
|
|
95
|
+
promptGuidelines: [
|
|
96
|
+
"Use read to examine files instead of cat or sed.",
|
|
97
|
+
"Use read line anchors as edit edits[].range for whole-line edits.",
|
|
98
|
+
],
|
|
99
|
+
parameters: readSchema,
|
|
100
|
+
async execute(_toolCallId, { path, offset, limit, anchors = "line" }, signal, _onUpdate, ctx) {
|
|
101
|
+
const absolutePath = resolveReadPath(path, cwd);
|
|
102
|
+
return new Promise((resolve, reject) => {
|
|
103
|
+
if (signal?.aborted) {
|
|
104
|
+
reject(new Error("Operation aborted"));
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
let aborted = false;
|
|
108
|
+
const onAbort = () => {
|
|
109
|
+
aborted = true;
|
|
110
|
+
reject(new Error("Operation aborted"));
|
|
111
|
+
};
|
|
112
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
113
|
+
(async () => {
|
|
114
|
+
try {
|
|
115
|
+
// Check if file exists and is readable.
|
|
116
|
+
await ops.access(absolutePath);
|
|
117
|
+
if (aborted)
|
|
118
|
+
return;
|
|
119
|
+
const mimeType = ops.detectImageMimeType ? await ops.detectImageMimeType(absolutePath) : undefined;
|
|
120
|
+
let content;
|
|
121
|
+
let details;
|
|
122
|
+
const nonVisionImageNote = getNonVisionImageNote(ctx?.model);
|
|
123
|
+
if (mimeType) {
|
|
124
|
+
// Read image as binary.
|
|
125
|
+
const buffer = await ops.readFile(absolutePath);
|
|
126
|
+
const base64 = buffer.toString("base64");
|
|
127
|
+
if (autoResizeImages) {
|
|
128
|
+
// Resize image if needed before sending it back to the model.
|
|
129
|
+
const resized = await resizeImage({ type: "image", data: base64, mimeType });
|
|
130
|
+
if (!resized) {
|
|
131
|
+
let textNote = `Read image file [${mimeType}]\n[Image omitted: could not be resized below the inline image size limit.]`;
|
|
132
|
+
if (nonVisionImageNote)
|
|
133
|
+
textNote += `\n${nonVisionImageNote}`;
|
|
134
|
+
content = [{ type: "text", text: textNote }];
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
const dimensionNote = formatDimensionNote(resized);
|
|
138
|
+
let textNote = `Read image file [${resized.mimeType}]`;
|
|
139
|
+
if (dimensionNote)
|
|
140
|
+
textNote += `\n${dimensionNote}`;
|
|
141
|
+
if (nonVisionImageNote)
|
|
142
|
+
textNote += `\n${nonVisionImageNote}`;
|
|
143
|
+
content = [
|
|
144
|
+
{ type: "text", text: textNote },
|
|
145
|
+
{ type: "image", data: resized.data, mimeType: resized.mimeType },
|
|
146
|
+
];
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
let textNote = `Read image file [${mimeType}]`;
|
|
151
|
+
if (nonVisionImageNote)
|
|
152
|
+
textNote += `\n${nonVisionImageNote}`;
|
|
153
|
+
content = [
|
|
154
|
+
{ type: "text", text: textNote },
|
|
155
|
+
{ type: "image", data: base64, mimeType },
|
|
156
|
+
];
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
// Read text content.
|
|
161
|
+
const buffer = await ops.readFile(absolutePath);
|
|
162
|
+
const textContent = normalizeTextForAnchors(buffer.toString("utf-8"), anchors);
|
|
163
|
+
const allLines = textContent.split("\n");
|
|
164
|
+
const totalFileLines = allLines.length;
|
|
165
|
+
// Apply offset if specified. Convert from 1-indexed input to 0-indexed array access.
|
|
166
|
+
const startLine = offset ? Math.max(0, offset - 1) : 0;
|
|
167
|
+
const startLineDisplay = startLine + 1;
|
|
168
|
+
// Check if offset is out of bounds.
|
|
169
|
+
if (startLine >= allLines.length) {
|
|
170
|
+
throw new Error(`Offset ${offset} is beyond end of file (${allLines.length} lines total)`);
|
|
171
|
+
}
|
|
172
|
+
let selectedContent;
|
|
173
|
+
let userLimitedLines;
|
|
174
|
+
// If limit is specified by the user, honor it first. Otherwise truncateHead decides.
|
|
175
|
+
if (limit !== undefined) {
|
|
176
|
+
const endLine = Math.min(startLine + limit, allLines.length);
|
|
177
|
+
selectedContent = allLines.slice(startLine, endLine).join("\n");
|
|
178
|
+
userLimitedLines = endLine - startLine;
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
selectedContent = allLines.slice(startLine).join("\n");
|
|
182
|
+
}
|
|
183
|
+
// Apply truncation, respecting both line and byte limits.
|
|
184
|
+
const truncation = truncateHead(selectedContent);
|
|
185
|
+
let outputText;
|
|
186
|
+
if (truncation.firstLineExceedsLimit) {
|
|
187
|
+
// First line alone exceeds the byte limit. Point the model at a bash fallback.
|
|
188
|
+
const firstLineSize = formatSize(Buffer.byteLength(allLines[startLine], "utf-8"));
|
|
189
|
+
outputText = `[Line ${startLineDisplay} is ${firstLineSize}, exceeds ${formatSize(DEFAULT_MAX_BYTES)} limit. Use bash: sed -n '${startLineDisplay}p' ${path} | head -c ${DEFAULT_MAX_BYTES}]`;
|
|
190
|
+
details = { truncation };
|
|
191
|
+
}
|
|
192
|
+
else if (truncation.truncated) {
|
|
193
|
+
// Truncation occurred. Build an actionable continuation notice.
|
|
194
|
+
const endLineDisplay = startLineDisplay + truncation.outputLines - 1;
|
|
195
|
+
const nextOffset = endLineDisplay + 1;
|
|
196
|
+
outputText = formatTextReadOutput(truncation.content, startLineDisplay, anchors);
|
|
197
|
+
if (truncation.truncatedBy === "lines") {
|
|
198
|
+
outputText += `\n\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines}. Use offset=${nextOffset} to continue.]`;
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
outputText += `\n\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Use offset=${nextOffset} to continue.]`;
|
|
202
|
+
}
|
|
203
|
+
details = { truncation };
|
|
204
|
+
}
|
|
205
|
+
else if (userLimitedLines !== undefined && startLine + userLimitedLines < allLines.length) {
|
|
206
|
+
// User-specified limit stopped early, but the file still has more content.
|
|
207
|
+
const remaining = allLines.length - (startLine + userLimitedLines);
|
|
208
|
+
const nextOffset = startLine + userLimitedLines + 1;
|
|
209
|
+
outputText = `${formatTextReadOutput(truncation.content, startLineDisplay, anchors)}\n\n[${remaining} more lines in file. Use offset=${nextOffset} to continue.]`;
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
// No truncation and no remaining user-limited content.
|
|
213
|
+
outputText = formatTextReadOutput(truncation.content, startLineDisplay, anchors);
|
|
214
|
+
}
|
|
215
|
+
content = [{ type: "text", text: outputText }];
|
|
216
|
+
}
|
|
217
|
+
if (aborted)
|
|
218
|
+
return;
|
|
219
|
+
signal?.removeEventListener("abort", onAbort);
|
|
220
|
+
resolve({ content, details });
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
signal?.removeEventListener("abort", onAbort);
|
|
224
|
+
if (!aborted)
|
|
225
|
+
reject(error);
|
|
226
|
+
}
|
|
227
|
+
})();
|
|
228
|
+
});
|
|
229
|
+
},
|
|
230
|
+
renderCall(args, theme, context) {
|
|
231
|
+
const text = context.lastComponent ?? new Text("", 0, 0);
|
|
232
|
+
text.setText(formatReadCall(args, theme));
|
|
233
|
+
return text;
|
|
234
|
+
},
|
|
235
|
+
renderResult(result, options, theme, context) {
|
|
236
|
+
const text = context.lastComponent ?? new Text("", 0, 0);
|
|
237
|
+
text.setText(formatReadResult(context.args, result, options, theme, context.showImages));
|
|
238
|
+
return text;
|
|
239
|
+
},
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
export function createReadTool(cwd, options) {
|
|
243
|
+
return wrapToolDefinition(createReadToolDefinition(cwd, options));
|
|
244
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ImageContent, TextContent } from "@earendil-works/pi-ai/compat";
|
|
2
|
+
export declare function shortenPath(path: unknown): string;
|
|
3
|
+
export declare function str(value: unknown): string | null;
|
|
4
|
+
export declare function replaceTabs(text: string): string;
|
|
5
|
+
export declare function normalizeDisplayText(text: string): string;
|
|
6
|
+
export declare function getTextOutput(result: {
|
|
7
|
+
content: Array<{
|
|
8
|
+
type: string;
|
|
9
|
+
text?: string;
|
|
10
|
+
data?: string;
|
|
11
|
+
mimeType?: string;
|
|
12
|
+
}>;
|
|
13
|
+
} | undefined, showImages: boolean): string;
|
|
14
|
+
export type ToolRenderResultLike<TDetails> = {
|
|
15
|
+
content: (TextContent | ImageContent)[];
|
|
16
|
+
details: TDetails;
|
|
17
|
+
};
|
|
18
|
+
export declare function invalidArgText(theme: {
|
|
19
|
+
fg: (name: any, text: string) => string;
|
|
20
|
+
}): string;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as os from "node:os";
|
|
2
|
+
import { getCapabilities, getImageDimensions, imageFallback } from "@earendil-works/pi-tui";
|
|
3
|
+
import stripAnsi from "strip-ansi";
|
|
4
|
+
import { sanitizeBinaryOutput } from "../../utils/shell.js";
|
|
5
|
+
export function shortenPath(path) {
|
|
6
|
+
if (typeof path !== "string")
|
|
7
|
+
return "";
|
|
8
|
+
const home = os.homedir();
|
|
9
|
+
if (path.startsWith(home)) {
|
|
10
|
+
return `~${path.slice(home.length)}`;
|
|
11
|
+
}
|
|
12
|
+
return path;
|
|
13
|
+
}
|
|
14
|
+
export function str(value) {
|
|
15
|
+
if (typeof value === "string")
|
|
16
|
+
return value;
|
|
17
|
+
if (value == null)
|
|
18
|
+
return "";
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
export function replaceTabs(text) {
|
|
22
|
+
return text.replace(/\t/g, " ");
|
|
23
|
+
}
|
|
24
|
+
export function normalizeDisplayText(text) {
|
|
25
|
+
return text.replace(/\r/g, "");
|
|
26
|
+
}
|
|
27
|
+
export function getTextOutput(result, showImages) {
|
|
28
|
+
if (!result)
|
|
29
|
+
return "";
|
|
30
|
+
const textBlocks = result.content.filter((c) => c.type === "text");
|
|
31
|
+
const imageBlocks = result.content.filter((c) => c.type === "image");
|
|
32
|
+
let output = textBlocks.map((c) => sanitizeBinaryOutput(stripAnsi(c.text || "")).replace(/\r/g, "")).join("\n");
|
|
33
|
+
const caps = getCapabilities();
|
|
34
|
+
if (imageBlocks.length > 0 && (!caps.images || !showImages)) {
|
|
35
|
+
const imageIndicators = imageBlocks
|
|
36
|
+
.map((img) => {
|
|
37
|
+
const mimeType = img.mimeType ?? "image/unknown";
|
|
38
|
+
const dims = img.data && img.mimeType ? (getImageDimensions(img.data, img.mimeType) ?? undefined) : undefined;
|
|
39
|
+
return imageFallback(mimeType, dims);
|
|
40
|
+
})
|
|
41
|
+
.join("\n");
|
|
42
|
+
output = output ? `${output}\n${imageIndicators}` : imageIndicators;
|
|
43
|
+
}
|
|
44
|
+
return output;
|
|
45
|
+
}
|
|
46
|
+
export function invalidArgText(theme) {
|
|
47
|
+
return theme.fg("error", "[invalid arg]");
|
|
48
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type Static } from "@sinclair/typebox";
|
|
2
|
+
import { type ToolDefinition } from "../extensions/types.js";
|
|
3
|
+
declare const sessionSplitSchema: import("@sinclair/typebox").TObject<{
|
|
4
|
+
reason: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
5
|
+
name: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
6
|
+
}>;
|
|
7
|
+
export type SessionSplitToolInput = Static<typeof sessionSplitSchema>;
|
|
8
|
+
export declare function createSessionSplitToolDefinition(): ToolDefinition<typeof sessionSplitSchema>;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { Text } from "@earendil-works/pi-tui";
|
|
3
|
+
import { defineTool } from "../extensions/types.js";
|
|
4
|
+
const sessionSplitSchema = Type.Object({
|
|
5
|
+
reason: Type.Optional(Type.String({
|
|
6
|
+
description: "Short reason for the split (e.g. 'topic_change', 'new_task', 'context_reset'). Helps the user understand why the session was divided.",
|
|
7
|
+
})),
|
|
8
|
+
name: Type.Optional(Type.String({
|
|
9
|
+
description: "Optional name for the new session (e.g. 'Fix authentication bug'). If omitted, a default name is used.",
|
|
10
|
+
})),
|
|
11
|
+
});
|
|
12
|
+
export function createSessionSplitToolDefinition() {
|
|
13
|
+
return defineTool({
|
|
14
|
+
name: "session_split",
|
|
15
|
+
label: "session_split",
|
|
16
|
+
description: "Split the current conversation session, starting a new session from this point forward. " +
|
|
17
|
+
"Previous messages will no longer be included in the LLM context for subsequent turns. " +
|
|
18
|
+
"Call this when the user's intent has clearly shifted to a new, unrelated topic and the previous " +
|
|
19
|
+
"conversation context is no longer needed. Do NOT call this for follow-up questions or clarifications " +
|
|
20
|
+
"about the current topic. You can call this alongside other tools in the same turn. " +
|
|
21
|
+
"IMPORTANT: Call this AT MOST ONCE per turn. After the split, your context will be refreshed " +
|
|
22
|
+
"to the new session — proceed directly with the user's requested task.",
|
|
23
|
+
promptSnippet: "Split the conversation session when the user's topic has clearly changed",
|
|
24
|
+
promptGuidelines: [
|
|
25
|
+
"Only call session_split when the user's request is clearly unrelated to the current conversation topic.",
|
|
26
|
+
"Do not call session_split for follow-up questions, clarifications, or refinements of the current task.",
|
|
27
|
+
"Call session_split at most once per turn. After the split, your context is refreshed — proceed with the task.",
|
|
28
|
+
],
|
|
29
|
+
parameters: sessionSplitSchema,
|
|
30
|
+
renderShell: "self",
|
|
31
|
+
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
32
|
+
const result = ctx?.sessionManager?.splitSession?.(params.reason ?? "intent_shift", params.name);
|
|
33
|
+
if (!result) {
|
|
34
|
+
return {
|
|
35
|
+
content: [
|
|
36
|
+
{
|
|
37
|
+
type: "text",
|
|
38
|
+
text: "Session split is not available in this runtime configuration.",
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (result.already_split) {
|
|
44
|
+
return {
|
|
45
|
+
content: [
|
|
46
|
+
{
|
|
47
|
+
type: "text",
|
|
48
|
+
text: "The session was already split for this turn. Do NOT call session_split again — " +
|
|
49
|
+
"proceed directly with the user's requested task.",
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
content: [
|
|
56
|
+
{
|
|
57
|
+
type: "text",
|
|
58
|
+
text: `Session split successfully. New session: ${result.session_id}. ` +
|
|
59
|
+
"Your context has been refreshed to the new session. " +
|
|
60
|
+
"Proceed with the user's task now — do NOT call session_split again.",
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
};
|
|
64
|
+
},
|
|
65
|
+
renderCall(args, _theme) {
|
|
66
|
+
const reason = args?.reason ?? "intent_shift";
|
|
67
|
+
const name = args?.name ? ` → ${args.name}` : "";
|
|
68
|
+
return new Text(`session_split (${reason})${name}`, 0, 0);
|
|
69
|
+
},
|
|
70
|
+
renderResult(result, _options, _theme) {
|
|
71
|
+
const text = result.content
|
|
72
|
+
.map((c) => ("text" in c ? c.text : ""))
|
|
73
|
+
.join("\n");
|
|
74
|
+
return new Text(`\n${text}`, 0, 0);
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AgentTool } from "../agent/types.js";
|
|
2
|
+
import type { ExtensionContext, ToolDefinition } from "../extensions/types.js";
|
|
3
|
+
/** Wrap a ToolDefinition into an AgentTool for the core runtime. */
|
|
4
|
+
export declare function wrapToolDefinition<TDetails = unknown>(definition: ToolDefinition<any, TDetails>, ctxFactory?: () => ExtensionContext): AgentTool<any, TDetails>;
|
|
5
|
+
/** Wrap multiple ToolDefinitions into AgentTools for the core runtime. */
|
|
6
|
+
export declare function wrapToolDefinitions(definitions: ToolDefinition<any, any>[], ctxFactory?: () => ExtensionContext): AgentTool<any>[];
|
|
7
|
+
/**
|
|
8
|
+
* Synthesize a minimal ToolDefinition from an AgentTool.
|
|
9
|
+
*
|
|
10
|
+
* This keeps the internal registry definition-first even when a caller
|
|
11
|
+
* provides plain AgentTool overrides that do not include prompt metadata or renderers.
|
|
12
|
+
*/
|
|
13
|
+
export declare function createToolDefinitionFromAgentTool(tool: AgentTool<any>): ToolDefinition<any, unknown>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** Wrap a ToolDefinition into an AgentTool for the core runtime. */
|
|
2
|
+
export function wrapToolDefinition(definition, ctxFactory) {
|
|
3
|
+
return {
|
|
4
|
+
name: definition.name,
|
|
5
|
+
description: definition.description,
|
|
6
|
+
parameters: definition.parameters,
|
|
7
|
+
prepareArguments: definition.prepareArguments,
|
|
8
|
+
executionMode: definition.executionMode,
|
|
9
|
+
execute: (toolCallId, params, signal, onUpdate) => definition.execute(toolCallId, params, signal, onUpdate, ctxFactory?.()),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
/** Wrap multiple ToolDefinitions into AgentTools for the core runtime. */
|
|
13
|
+
export function wrapToolDefinitions(definitions, ctxFactory) {
|
|
14
|
+
return definitions.map((definition) => wrapToolDefinition(definition, ctxFactory));
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Synthesize a minimal ToolDefinition from an AgentTool.
|
|
18
|
+
*
|
|
19
|
+
* This keeps the internal registry definition-first even when a caller
|
|
20
|
+
* provides plain AgentTool overrides that do not include prompt metadata or renderers.
|
|
21
|
+
*/
|
|
22
|
+
export function createToolDefinitionFromAgentTool(tool) {
|
|
23
|
+
return {
|
|
24
|
+
name: tool.name,
|
|
25
|
+
label: tool.label, // label is inherited from Tool interface
|
|
26
|
+
description: tool.description,
|
|
27
|
+
parameters: tool.parameters,
|
|
28
|
+
prepareArguments: tool.prepareArguments,
|
|
29
|
+
executionMode: tool.executionMode,
|
|
30
|
+
execute: async (toolCallId, params, signal, onUpdate) => tool.execute(toolCallId, params, signal, onUpdate),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared truncation utilities for tool outputs.
|
|
3
|
+
*
|
|
4
|
+
* Truncation is based on two independent limits - whichever is hit first wins:
|
|
5
|
+
* - Line limit (default: 2000 lines)
|
|
6
|
+
* - Byte limit (default: 50KB)
|
|
7
|
+
*
|
|
8
|
+
* Never returns partial lines (except bash tail truncation edge case).
|
|
9
|
+
*/
|
|
10
|
+
export declare const DEFAULT_MAX_LINES = 2000;
|
|
11
|
+
export declare const DEFAULT_MAX_BYTES: number;
|
|
12
|
+
export declare const GREP_MAX_LINE_LENGTH = 500;
|
|
13
|
+
export interface TruncationResult {
|
|
14
|
+
/** The truncated content */
|
|
15
|
+
content: string;
|
|
16
|
+
/** Whether truncation occurred */
|
|
17
|
+
truncated: boolean;
|
|
18
|
+
/** Which limit was hit: "lines", "bytes", or null if not truncated */
|
|
19
|
+
truncatedBy: "lines" | "bytes" | null;
|
|
20
|
+
/** Total number of lines in the original content */
|
|
21
|
+
totalLines: number;
|
|
22
|
+
/** Total number of bytes in the original content */
|
|
23
|
+
totalBytes: number;
|
|
24
|
+
/** Number of complete lines in the truncated output */
|
|
25
|
+
outputLines: number;
|
|
26
|
+
/** Number of bytes in the truncated output */
|
|
27
|
+
outputBytes: number;
|
|
28
|
+
/** Whether the last line was partially truncated (only for tail truncation edge case) */
|
|
29
|
+
lastLinePartial: boolean;
|
|
30
|
+
/** Whether the first line exceeded the byte limit (for head truncation) */
|
|
31
|
+
firstLineExceedsLimit: boolean;
|
|
32
|
+
/** The max lines limit that was applied */
|
|
33
|
+
maxLines: number;
|
|
34
|
+
/** The max bytes limit that was applied */
|
|
35
|
+
maxBytes: number;
|
|
36
|
+
}
|
|
37
|
+
export interface TruncationOptions {
|
|
38
|
+
/** Maximum number of lines (default: 2000) */
|
|
39
|
+
maxLines?: number;
|
|
40
|
+
/** Maximum number of bytes (default: 50KB) */
|
|
41
|
+
maxBytes?: number;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Format bytes as human-readable size.
|
|
45
|
+
*/
|
|
46
|
+
export declare function formatSize(bytes: number): string;
|
|
47
|
+
/**
|
|
48
|
+
* Truncate content from the head (keep first N lines/bytes).
|
|
49
|
+
* Suitable for file reads where you want to see the beginning.
|
|
50
|
+
*
|
|
51
|
+
* Never returns partial lines. If first line exceeds byte limit,
|
|
52
|
+
* returns empty content with firstLineExceedsLimit=true.
|
|
53
|
+
*/
|
|
54
|
+
export declare function truncateHead(content: string, options?: TruncationOptions): TruncationResult;
|
|
55
|
+
/**
|
|
56
|
+
* Truncate content from the tail (keep last N lines/bytes).
|
|
57
|
+
* Suitable for bash output where you want to see the end (errors, final results).
|
|
58
|
+
*
|
|
59
|
+
* May return partial first line if the last line of original content exceeds byte limit.
|
|
60
|
+
*/
|
|
61
|
+
export declare function truncateTail(content: string, options?: TruncationOptions): TruncationResult;
|
|
62
|
+
/**
|
|
63
|
+
* Truncate a single line to max characters, adding [truncated] suffix.
|
|
64
|
+
* Used for grep match lines.
|
|
65
|
+
*/
|
|
66
|
+
export declare function truncateLine(line: string, maxChars?: number): {
|
|
67
|
+
text: string;
|
|
68
|
+
wasTruncated: boolean;
|
|
69
|
+
};
|