@kolisachint/hoocode-agent 0.4.162 → 0.4.164
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 +29 -0
- package/dist/cli/args.d.ts +0 -6
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +0 -31
- package/dist/cli/args.js.map +1 -1
- package/dist/config.d.ts +0 -40
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +4 -50
- package/dist/config.js.map +1 -1
- package/dist/core/agent-frontmatter.d.ts +0 -28
- package/dist/core/agent-frontmatter.d.ts.map +1 -1
- package/dist/core/agent-frontmatter.js +0 -6
- package/dist/core/agent-frontmatter.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +0 -2
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +0 -2
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +0 -2
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-guidance.d.ts +0 -1
- package/dist/core/auth-guidance.d.ts.map +1 -1
- package/dist/core/auth-guidance.js +1 -1
- package/dist/core/auth-guidance.js.map +1 -1
- package/dist/core/embsearch/chunker.d.ts +0 -2
- package/dist/core/embsearch/chunker.d.ts.map +1 -1
- package/dist/core/embsearch/chunker.js +1 -1
- package/dist/core/embsearch/chunker.js.map +1 -1
- package/dist/core/embsearch/index-meta.d.ts +0 -2
- package/dist/core/embsearch/index-meta.d.ts.map +1 -1
- package/dist/core/embsearch/index-meta.js +0 -6
- package/dist/core/embsearch/index-meta.js.map +1 -1
- package/dist/core/export-html/ansi-to-html.d.ts +0 -4
- package/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
- package/dist/core/export-html/ansi-to-html.js +1 -1
- package/dist/core/export-html/ansi-to-html.js.map +1 -1
- package/dist/core/extensions/index.d.ts +3 -3
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/plugins/authoring.d.ts +2 -2
- package/dist/core/extensions/plugins/authoring.d.ts.map +1 -1
- package/dist/core/extensions/plugins/authoring.js +0 -0
- package/dist/core/extensions/plugins/authoring.js.map +1 -1
- package/dist/core/extensions/plugins/formats/index.d.ts +2 -6
- package/dist/core/extensions/plugins/formats/index.d.ts.map +1 -1
- package/dist/core/extensions/plugins/formats/index.js +2 -3
- package/dist/core/extensions/plugins/formats/index.js.map +1 -1
- package/dist/core/extensions/plugins/formats/shared.d.ts +0 -2
- package/dist/core/extensions/plugins/formats/shared.d.ts.map +1 -1
- package/dist/core/extensions/plugins/formats/shared.js +1 -1
- package/dist/core/extensions/plugins/formats/shared.js.map +1 -1
- package/dist/core/extensions/plugins/formats/types.d.ts +4 -3
- package/dist/core/extensions/plugins/formats/types.d.ts.map +1 -1
- package/dist/core/extensions/plugins/formats/types.js.map +1 -1
- package/dist/core/extensions/plugins/install.d.ts +0 -2
- package/dist/core/extensions/plugins/install.d.ts.map +1 -1
- package/dist/core/extensions/plugins/install.js +1 -1
- package/dist/core/extensions/plugins/install.js.map +1 -1
- package/dist/core/extensions/plugins/manifest.d.ts +0 -6
- package/dist/core/extensions/plugins/manifest.d.ts.map +1 -1
- package/dist/core/extensions/plugins/manifest.js +0 -6
- package/dist/core/extensions/plugins/manifest.js.map +1 -1
- package/dist/core/extensions/plugins/marketplace.d.ts +3 -3
- package/dist/core/extensions/plugins/marketplace.d.ts.map +1 -1
- package/dist/core/extensions/plugins/marketplace.js.map +1 -1
- package/dist/core/extensions/types.d.ts +28 -28
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/keybindings.d.ts +3 -3
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/model-resolver.d.ts +0 -7
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +0 -56
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/package-resource-discovery.d.ts +0 -10
- package/dist/core/package-resource-discovery.d.ts.map +1 -1
- package/dist/core/package-resource-discovery.js +7 -7
- package/dist/core/package-resource-discovery.js.map +1 -1
- package/dist/core/provider-health.d.ts +0 -2
- package/dist/core/provider-health.d.ts.map +1 -1
- package/dist/core/provider-health.js +1 -1
- package/dist/core/provider-health.js.map +1 -1
- package/dist/core/resolve-config-value.d.ts +0 -4
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js +0 -15
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/sdk.d.ts +3 -23
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +3 -5
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/search/eval.d.ts +0 -3
- package/dist/core/search/eval.d.ts.map +1 -1
- package/dist/core/search/eval.js +1 -1
- package/dist/core/search/eval.js.map +1 -1
- package/dist/core/search/types.d.ts +2 -1
- package/dist/core/search/types.d.ts.map +1 -1
- package/dist/core/search/types.js.map +1 -1
- package/dist/core/session-cwd.d.ts +0 -1
- package/dist/core/session-cwd.d.ts.map +1 -1
- package/dist/core/session-cwd.js +1 -1
- package/dist/core/session-cwd.js.map +1 -1
- package/dist/core/settings-defaults.d.ts +0 -3
- package/dist/core/settings-defaults.d.ts.map +1 -1
- package/dist/core/settings-defaults.js +0 -3
- package/dist/core/settings-defaults.js.map +1 -1
- package/dist/core/settings-manager.d.ts +2 -9
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +0 -25
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/settings-types.d.ts +9 -11
- package/dist/core/settings-types.d.ts.map +1 -1
- package/dist/core/settings-types.js.map +1 -1
- package/dist/core/subagent-inbox.d.ts +1 -3
- package/dist/core/subagent-inbox.d.ts.map +1 -1
- package/dist/core/subagent-inbox.js +1 -1
- package/dist/core/subagent-inbox.js.map +1 -1
- package/dist/core/subagent-pool.d.ts +0 -13
- package/dist/core/subagent-pool.d.ts.map +1 -1
- package/dist/core/subagent-pool.js +2 -2
- package/dist/core/subagent-pool.js.map +1 -1
- package/dist/core/task-store.d.ts +3 -3
- package/dist/core/task-store.d.ts.map +1 -1
- package/dist/core/task-store.js.map +1 -1
- package/dist/core/team-auto.d.ts +0 -2
- package/dist/core/team-auto.d.ts.map +1 -1
- package/dist/core/team-auto.js +1 -1
- package/dist/core/team-auto.js.map +1 -1
- package/dist/core/token-budget.d.ts +0 -13
- package/dist/core/token-budget.d.ts.map +1 -1
- package/dist/core/token-budget.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +3 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts +0 -38
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js +2 -9
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +5 -5
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +8 -10
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +4 -4
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/index.d.ts +0 -24
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +0 -20
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +2 -2
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/native-search.d.ts +3 -2
- package/dist/core/tools/native-search.d.ts.map +1 -1
- package/dist/core/tools/native-search.js.map +1 -1
- package/dist/core/tools/path-utils.d.ts +0 -10
- package/dist/core/tools/path-utils.d.ts.map +1 -1
- package/dist/core/tools/path-utils.js +2 -2
- package/dist/core/tools/path-utils.js.map +1 -1
- package/dist/core/tools/plugins.d.ts +1 -20
- package/dist/core/tools/plugins.d.ts.map +1 -1
- package/dist/core/tools/plugins.js +2 -2
- package/dist/core/tools/plugins.js.map +1 -1
- package/dist/core/tools/propose-plugin.d.ts +0 -12
- package/dist/core/tools/propose-plugin.d.ts.map +1 -1
- package/dist/core/tools/propose-plugin.js +0 -1
- package/dist/core/tools/propose-plugin.js.map +1 -1
- package/dist/core/tools/read-dedup.d.ts +0 -2
- package/dist/core/tools/read-dedup.d.ts.map +1 -1
- package/dist/core/tools/read-dedup.js +1 -1
- package/dist/core/tools/read-dedup.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +10 -8
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts +0 -5
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/core/tools/search.d.ts +1 -4
- package/dist/core/tools/search.d.ts.map +1 -1
- package/dist/core/tools/search.js +6 -6
- package/dist/core/tools/search.js.map +1 -1
- package/dist/core/tools/webfetch.d.ts +1 -2
- package/dist/core/tools/webfetch.d.ts.map +1 -1
- package/dist/core/tools/webfetch.js.map +1 -1
- package/dist/core/tools/websearch.d.ts +1 -2
- package/dist/core/tools/websearch.d.ts.map +1 -1
- package/dist/core/tools/websearch.js.map +1 -1
- package/dist/core/tools/webtools-shared.d.ts +3 -5
- package/dist/core/tools/webtools-shared.d.ts.map +1 -1
- package/dist/core/tools/webtools-shared.js +1 -1
- package/dist/core/tools/webtools-shared.js.map +1 -1
- package/dist/core/warm-subagent-pool-instance.d.ts +0 -4
- package/dist/core/warm-subagent-pool-instance.d.ts.map +1 -1
- package/dist/core/warm-subagent-pool-instance.js +0 -10
- package/dist/core/warm-subagent-pool-instance.js.map +1 -1
- package/dist/core/wordmark.d.ts +1 -9
- package/dist/core/wordmark.d.ts.map +1 -1
- package/dist/core/wordmark.js +2 -26
- package/dist/core/wordmark.js.map +1 -1
- package/dist/extensions/core/config.d.ts +4 -3
- package/dist/extensions/core/config.d.ts.map +1 -1
- package/dist/extensions/core/config.js.map +1 -1
- package/dist/extensions/core/mcp-loader.d.ts +0 -18
- package/dist/extensions/core/mcp-loader.d.ts.map +1 -1
- package/dist/extensions/core/mcp-loader.js.map +1 -1
- package/dist/extensions/core/prompt-reactive/policy.d.ts +0 -8
- package/dist/extensions/core/prompt-reactive/policy.d.ts.map +1 -1
- package/dist/extensions/core/prompt-reactive/policy.js +1 -1
- package/dist/extensions/core/prompt-reactive/policy.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +0 -30
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts +0 -16
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +2 -2
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/brand.d.ts +0 -4
- package/dist/modes/interactive/brand.d.ts.map +1 -1
- package/dist/modes/interactive/brand.js +0 -4
- package/dist/modes/interactive/brand.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +0 -4
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +0 -5
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/read-output.d.ts +0 -9
- package/dist/modes/interactive/components/read-output.d.ts.map +1 -1
- package/dist/modes/interactive/components/read-output.js +0 -20
- package/dist/modes/interactive/components/read-output.js.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.d.ts +0 -17
- package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.js +2 -2
- package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +5 -14
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +2 -2
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +0 -18
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/login-controller.d.ts +1 -1
- package/dist/modes/interactive/login-controller.d.ts.map +1 -1
- package/dist/modes/interactive/login-controller.js +1 -1
- package/dist/modes/interactive/login-controller.js.map +1 -1
- package/dist/modes/interactive/resource-display.d.ts +0 -20
- package/dist/modes/interactive/resource-display.d.ts.map +1 -1
- package/dist/modes/interactive/resource-display.js +7 -7
- package/dist/modes/interactive/resource-display.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts +0 -4
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +0 -7
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts +0 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +0 -1
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js +3 -0
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/package-manager-cli.d.ts +0 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/utils/changelog.d.ts +0 -4
- package/dist/utils/changelog.d.ts.map +1 -1
- package/dist/utils/changelog.js +1 -1
- package/dist/utils/changelog.js.map +1 -1
- package/dist/utils/clipboard-native.d.ts +1 -1
- package/dist/utils/clipboard-native.d.ts.map +1 -1
- package/dist/utils/clipboard-native.js.map +1 -1
- package/dist/utils/paths.d.ts +0 -2
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +1 -1
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/plan/parser.d.ts +5 -4
- package/dist/utils/plan/parser.d.ts.map +1 -1
- package/dist/utils/plan/parser.js.map +1 -1
- package/dist/utils/tools-manager.d.ts +1 -2
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +2 -50
- package/dist/utils/tools-manager.js.map +1 -1
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package.json +1 -1
- package/package.json +4 -7
- package/dist/core/index.d.ts +0 -12
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/index.js +0 -12
- package/dist/core/index.js.map +0 -1
- package/dist/core/tools/browser/browser-continue.d.ts +0 -25
- package/dist/core/tools/browser/browser-continue.d.ts.map +0 -1
- package/dist/core/tools/browser/browser-continue.js +0 -84
- package/dist/core/tools/browser/browser-continue.js.map +0 -1
- package/dist/core/tools/browser/browser-run.d.ts +0 -48
- package/dist/core/tools/browser/browser-run.d.ts.map +0 -1
- package/dist/core/tools/browser/browser-run.js +0 -377
- package/dist/core/tools/browser/browser-run.js.map +0 -1
- package/dist/core/tools/browser/browsertools-shared.d.ts +0 -190
- package/dist/core/tools/browser/browsertools-shared.d.ts.map +0 -1
- package/dist/core/tools/browser/browsertools-shared.js +0 -335
- package/dist/core/tools/browser/browsertools-shared.js.map +0 -1
- package/dist/core/tools/browser/index.d.ts +0 -8
- package/dist/core/tools/browser/index.d.ts.map +0 -1
- package/dist/core/tools/browser/index.js +0 -8
- package/dist/core/tools/browser/index.js.map +0 -1
- package/dist/core/tools/doc/docedit.d.ts +0 -44
- package/dist/core/tools/doc/docedit.d.ts.map +0 -1
- package/dist/core/tools/doc/docedit.js +0 -133
- package/dist/core/tools/doc/docedit.js.map +0 -1
- package/dist/core/tools/doc/docgrep.d.ts +0 -28
- package/dist/core/tools/doc/docgrep.d.ts.map +0 -1
- package/dist/core/tools/doc/docgrep.js +0 -106
- package/dist/core/tools/doc/docgrep.js.map +0 -1
- package/dist/core/tools/doc/docpeek.d.ts +0 -25
- package/dist/core/tools/doc/docpeek.d.ts.map +0 -1
- package/dist/core/tools/doc/docpeek.js +0 -112
- package/dist/core/tools/doc/docpeek.js.map +0 -1
- package/dist/core/tools/doc/docread.d.ts +0 -32
- package/dist/core/tools/doc/docread.d.ts.map +0 -1
- package/dist/core/tools/doc/docread.js +0 -113
- package/dist/core/tools/doc/docread.js.map +0 -1
- package/dist/core/tools/doc/docscan.d.ts +0 -29
- package/dist/core/tools/doc/docscan.d.ts.map +0 -1
- package/dist/core/tools/doc/docscan.js +0 -110
- package/dist/core/tools/doc/docscan.js.map +0 -1
- package/dist/core/tools/doc/docwrite.d.ts +0 -44
- package/dist/core/tools/doc/docwrite.d.ts.map +0 -1
- package/dist/core/tools/doc/docwrite.js +0 -102
- package/dist/core/tools/doc/docwrite.js.map +0 -1
- package/dist/core/tools/doc/index.d.ts +0 -11
- package/dist/core/tools/doc/index.d.ts.map +0 -1
- package/dist/core/tools/doc/index.js +0 -11
- package/dist/core/tools/doc/index.js.map +0 -1
- package/dist/core/tools/filetools-shared.d.ts +0 -271
- package/dist/core/tools/filetools-shared.d.ts.map +0 -1
- package/dist/core/tools/filetools-shared.js +0 -403
- package/dist/core/tools/filetools-shared.js.map +0 -1
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Browser automation tools (browser_run + browser_continue), driving the
|
|
3
|
-
* `browsertools` deterministic browser engine. Off by default; enabled per
|
|
4
|
-
* session via `--enable-browsertools` or settings.
|
|
5
|
-
*/
|
|
6
|
-
export { type BrowserContinueInput, type BrowserContinueToolOptions, createBrowserContinueTool, createBrowserContinueToolDefinition, } from "./browser-continue.js";
|
|
7
|
-
export { advanceFlow, type BrowserRunDetails, type BrowserRunInput, type BrowserRunToolOptions, createBrowserRunTool, createBrowserRunToolDefinition, } from "./browser-run.js";
|
|
8
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/tools/browser/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACN,KAAK,oBAAoB,EACzB,KAAK,0BAA0B,EAC/B,yBAAyB,EACzB,mCAAmC,GACnC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,WAAW,EACX,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,oBAAoB,EACpB,8BAA8B,GAC9B,MAAM,kBAAkB,CAAC","sourcesContent":["/**\n * Browser automation tools (browser_run + browser_continue), driving the\n * `browsertools` deterministic browser engine. Off by default; enabled per\n * session via `--enable-browsertools` or settings.\n */\n\nexport {\n\ttype BrowserContinueInput,\n\ttype BrowserContinueToolOptions,\n\tcreateBrowserContinueTool,\n\tcreateBrowserContinueToolDefinition,\n} from \"./browser-continue.js\";\nexport {\n\tadvanceFlow,\n\ttype BrowserRunDetails,\n\ttype BrowserRunInput,\n\ttype BrowserRunToolOptions,\n\tcreateBrowserRunTool,\n\tcreateBrowserRunToolDefinition,\n} from \"./browser-run.js\";\n"]}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Browser automation tools (browser_run + browser_continue), driving the
|
|
3
|
-
* `browsertools` deterministic browser engine. Off by default; enabled per
|
|
4
|
-
* session via `--enable-browsertools` or settings.
|
|
5
|
-
*/
|
|
6
|
-
export { createBrowserContinueTool, createBrowserContinueToolDefinition, } from "./browser-continue.js";
|
|
7
|
-
export { advanceFlow, createBrowserRunTool, createBrowserRunToolDefinition, } from "./browser-run.js";
|
|
8
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/tools/browser/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAGN,yBAAyB,EACzB,mCAAmC,GACnC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,WAAW,EAIX,oBAAoB,EACpB,8BAA8B,GAC9B,MAAM,kBAAkB,CAAC","sourcesContent":["/**\n * Browser automation tools (browser_run + browser_continue), driving the\n * `browsertools` deterministic browser engine. Off by default; enabled per\n * session via `--enable-browsertools` or settings.\n */\n\nexport {\n\ttype BrowserContinueInput,\n\ttype BrowserContinueToolOptions,\n\tcreateBrowserContinueTool,\n\tcreateBrowserContinueToolDefinition,\n} from \"./browser-continue.js\";\nexport {\n\tadvanceFlow,\n\ttype BrowserRunDetails,\n\ttype BrowserRunInput,\n\ttype BrowserRunToolOptions,\n\tcreateBrowserRunTool,\n\tcreateBrowserRunToolDefinition,\n} from \"./browser-run.js\";\n"]}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import type { AgentTool } from "@kolisachint/hoocode-agent-core";
|
|
2
|
-
import { type Static, Type } from "typebox";
|
|
3
|
-
import type { ToolDefinition } from "../../extensions/types.js";
|
|
4
|
-
import { type DocNode } from "../filetools-shared.js";
|
|
5
|
-
declare const docEditSchema: Type.TObject<{
|
|
6
|
-
path: Type.TString;
|
|
7
|
-
patch: Type.TArray<Type.TUnion<[Type.TObject<{
|
|
8
|
-
op: Type.TLiteral<"test">;
|
|
9
|
-
path: Type.TString;
|
|
10
|
-
hash: Type.TString;
|
|
11
|
-
}>, Type.TObject<{
|
|
12
|
-
op: Type.TLiteral<"replace">;
|
|
13
|
-
path: Type.TString;
|
|
14
|
-
value: Type.TString;
|
|
15
|
-
}>, Type.TObject<{
|
|
16
|
-
op: Type.TLiteral<"add">;
|
|
17
|
-
after: Type.TOptional<Type.TString>;
|
|
18
|
-
before: Type.TOptional<Type.TString>;
|
|
19
|
-
value: Type.TObject<{
|
|
20
|
-
tag: Type.TString;
|
|
21
|
-
attrs: Type.TOptional<Type.TArray<Type.TObject<{
|
|
22
|
-
name: Type.TString;
|
|
23
|
-
value: Type.TString;
|
|
24
|
-
}>>>;
|
|
25
|
-
text: Type.TOptional<Type.TString>;
|
|
26
|
-
}>;
|
|
27
|
-
}>, Type.TObject<{
|
|
28
|
-
op: Type.TLiteral<"remove">;
|
|
29
|
-
path: Type.TString;
|
|
30
|
-
}>]>>;
|
|
31
|
-
}>;
|
|
32
|
-
export type DocEditToolInput = Static<typeof docEditSchema>;
|
|
33
|
-
export interface DocEditToolDetails {
|
|
34
|
-
ops?: number;
|
|
35
|
-
affected?: DocNode[];
|
|
36
|
-
}
|
|
37
|
-
export interface DocEditToolOptions {
|
|
38
|
-
/** Timeout (seconds) for the filetools invocations. */
|
|
39
|
-
timeoutSecs?: number;
|
|
40
|
-
}
|
|
41
|
-
export declare function createDocEditToolDefinition(cwd: string, options?: DocEditToolOptions): ToolDefinition<typeof docEditSchema, DocEditToolDetails | undefined>;
|
|
42
|
-
export declare function createDocEditTool(cwd: string, options?: DocEditToolOptions): AgentTool<typeof docEditSchema>;
|
|
43
|
-
export {};
|
|
44
|
-
//# sourceMappingURL=docedit.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"docedit.d.ts","sourceRoot":"","sources":["../../../../src/core/tools/doc/docedit.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAEjE,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAG5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAEhE,OAAO,EACN,KAAK,OAAO,EAUZ,MAAM,wBAAwB,CAAC;AAMhC,QAAA,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;EAKjB,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,OAAO,aAAa,CAAC,CAAC;AAE5D,MAAM,WAAW,kBAAkB;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IAClC,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAYD,wBAAgB,2BAA2B,CAC1C,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,kBAAkB,GAC1B,cAAc,CAAC,OAAO,aAAa,EAAE,kBAAkB,GAAG,SAAS,CAAC,CAmGtE;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC,OAAO,aAAa,CAAC,CAE5G","sourcesContent":["import { mkdtempSync, renameSync, rmSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { basename, join } from \"node:path\";\nimport type { AgentTool } from \"@kolisachint/hoocode-agent-core\";\nimport { Container, Text } from \"@kolisachint/hoocode-tui\";\nimport { type Static, Type } from \"typebox\";\nimport { APP_NAME } from \"../../../config.js\";\nimport { theme as appTheme } from \"../../../modes/interactive/theme/theme.js\";\nimport type { ToolDefinition } from \"../../extensions/types.js\";\nimport { withFileMutationQueue } from \"../file-mutation-queue.js\";\nimport {\n\ttype DocNode,\n\tensureExtractRecord,\n\textractDocument,\n\tfindNodeById,\n\tinvalidateExtractRecord,\n\tpatchOpNodeId,\n\tpatchOpsSchema,\n\treconstructDocument,\n\tStalePatchError,\n\ttoPatch,\n} from \"../filetools-shared.js\";\nimport { resolveReadPath } from \"../path-utils.js\";\nimport { invalidArgText, shortenPath, str } from \"../render-utils.js\";\nimport { wrapToolDefinition } from \"../tool-definition-wrapper.js\";\nimport { renderEnvelopeText } from \"./docread.js\";\n\nconst docEditSchema = Type.Object({\n\tpath: Type.String({\n\t\tdescription: \"Path to the document to edit in place. Must have been opened with DocRead first.\",\n\t}),\n\tpatch: patchOpsSchema,\n});\n\nexport type DocEditToolInput = Static<typeof docEditSchema>;\n\nexport interface DocEditToolDetails {\n\tops?: number;\n\taffected?: DocNode[];\n}\n\nexport interface DocEditToolOptions {\n\t/** Timeout (seconds) for the filetools invocations. */\n\ttimeoutSecs?: number;\n}\n\nfunction formatDocEditCall(args: { path?: string; patch?: unknown[] } | undefined): string {\n\tconst path = str(args?.path);\n\tconst pathDisplay =\n\t\tpath === null ? invalidArgText(appTheme) : path ? shortenPath(path) : appTheme.fg(\"toolOutput\", \"...\");\n\tlet text = appTheme.fg(\"toolTitle\", appTheme.bold(\"DocEdit \")) + appTheme.fg(\"accent\", pathDisplay);\n\tconst ops = Array.isArray(args?.patch) ? args.patch.length : undefined;\n\tif (ops !== undefined) text += appTheme.fg(\"muted\", ` (${ops} op${ops === 1 ? \"\" : \"s\"})`);\n\treturn text;\n}\n\nexport function createDocEditToolDefinition(\n\tcwd: string,\n\toptions?: DocEditToolOptions,\n): ToolDefinition<typeof docEditSchema, DocEditToolDetails | undefined> {\n\treturn {\n\t\tname: \"DocEdit\",\n\t\tlabel: \"DocEdit\",\n\t\tdescription:\n\t\t\t\"Apply an id-based patch to a structured/binary document IN PLACE, losslessly. Targets node ids from a DocRead extract; if the cache is missing or the file changed on disk (e.g. an external script rewrote it) the document is re-extracted automatically, so a separate DocRead is not required. If the patch references ids that no longer exist, the call fails and returns the current structure with fresh ids so you can re-issue. Untouched bytes are preserved exactly; the file is re-extracted after the write so ids stay current for further edits. This is the canonical way to edit these formats: never fall back to ad-hoc scripts (python/openpyxl, docx, PyPDF2, unzip, sed) to rewrite them — that bypasses the lossless id-map and corrupts the file. Off by default; enabled with --enable-filetools.\",\n\t\tpromptSnippet: \"Patch a structured/binary document in place by node id\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use DocEdit to modify a document opened with DocRead; pass a patch of id-based ops (replace/add/remove) targeting the #ids from the extract. It edits in place and re-extracts.\",\n\t\t\t\"Keep patches minimal — only the ops you actually need. DocEdit re-extracts after writing and refreshes ids, so do not DocRead again between edits; the full extract is token-heavy. Reach for a fresh writable DocRead only when ids have gone stale and the failure output isn't enough to continue.\",\n\t\t],\n\t\tparameters: docEditSchema,\n\t\tasync execute(_toolCallId, { path, patch }: DocEditToolInput, signal?: AbortSignal) {\n\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\tconst absolutePath = resolveReadPath(path, cwd);\n\n\t\t\treturn withFileMutationQueue(absolutePath, async () => {\n\t\t\t\t// Resolve affected nodes from the pre-reconstruct extract: the patch's\n\t\t\t\t// ids are valid against THIS extract, and a later re-extract\n\t\t\t\t// regenerates ids that would not match the patch. reconstructDocument\n\t\t\t\t// auto-extracts when the cache is missing/stale, so capture the record\n\t\t\t\t// the same way to stay in sync with what the patch is applied against.\n\t\t\t\tconst preRecord = await ensureExtractRecord(absolutePath, cwd, signal, {\n\t\t\t\t\ttimeoutSecs: options?.timeoutSecs,\n\t\t\t\t});\n\t\t\t\tconst affectedIds = new Set<string>();\n\t\t\t\tfor (const op of toPatch(patch).patch) {\n\t\t\t\t\tconst id = patchOpNodeId(op);\n\t\t\t\t\tif (id) affectedIds.add(id);\n\t\t\t\t}\n\t\t\t\tconst affectedNodes: DocNode[] = [];\n\t\t\t\tfor (const id of affectedIds) {\n\t\t\t\t\tconst node = findNodeById(preRecord.envelope.structure, id);\n\t\t\t\t\tif (node) affectedNodes.push(node);\n\t\t\t\t}\n\n\t\t\t\t// Reconstruct to a temp file, then atomically swap it into place so a\n\t\t\t\t// failed reconstruct never leaves a half-written document behind.\n\t\t\t\tconst stageDir = mkdtempSync(join(tmpdir(), `${APP_NAME}-docedit-`));\n\t\t\t\tconst stagePath = join(stageDir, basename(absolutePath));\n\t\t\t\ttry {\n\t\t\t\t\tawait reconstructDocument(absolutePath, toPatch(patch), stagePath, cwd, signal, {\n\t\t\t\t\t\ttimeoutSecs: options?.timeoutSecs,\n\t\t\t\t\t});\n\t\t\t\t\trenameSync(stagePath, absolutePath);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tif (err instanceof StalePatchError) {\n\t\t\t\t\t\t// The document was rewritten out-of-band: the cache auto-refreshed\n\t\t\t\t\t\t// but the patch targets ids that no longer exist. Surface the\n\t\t\t\t\t\t// current structure so the agent can re-issue without a DocRead.\n\t\t\t\t\t\tthrow new Error(`${err.message}\\n\\n${renderEnvelopeText(err.envelope, false)}`);\n\t\t\t\t\t}\n\t\t\t\t\tthrow err;\n\t\t\t\t} finally {\n\t\t\t\t\trmSync(stageDir, { recursive: true, force: true });\n\t\t\t\t}\n\n\t\t\t\t// The source changed, so the cached id-map is stale. Re-extract to\n\t\t\t\t// refresh ids for subsequent edits (best-effort; a failure here does\n\t\t\t\t// not undo the successful write).\n\t\t\t\tinvalidateExtractRecord(absolutePath);\n\t\t\t\ttry {\n\t\t\t\t\tawait extractDocument(absolutePath, cwd, signal, { timeoutSecs: options?.timeoutSecs });\n\t\t\t\t} catch {\n\t\t\t\t\t// Re-extract failure leaves no cached record; the next DocEdit will\n\t\t\t\t\t// auto-extract (or fall back to DocRead), which is the correct path.\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\ttext: `Applied ${patch.length} op${patch.length === 1 ? \"\" : \"s\"} to ${path} (re-extracted; ids refreshed).`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: { ops: patch.length, affected: affectedNodes.length > 0 ? affectedNodes : undefined },\n\t\t\t\t};\n\t\t\t});\n\t\t},\n\t\trenderCall(args, _theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatDocEditCall(args));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, _options, _theme, context) {\n\t\t\tif (!context.isError) {\n\t\t\t\tconst component = (context.lastComponent as Container | undefined) ?? new Container();\n\t\t\t\tcomponent.clear();\n\t\t\t\treturn component;\n\t\t\t}\n\t\t\tconst output = (result.content as Array<{ type: string; text?: string }>)\n\t\t\t\t.filter((c) => c.type === \"text\")\n\t\t\t\t.map((c) => c.text || \"\")\n\t\t\t\t.join(\"\\n\");\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(output ? `\\n${appTheme.fg(\"error\", output)}` : \"\");\n\t\t\treturn text;\n\t\t},\n\t};\n}\n\nexport function createDocEditTool(cwd: string, options?: DocEditToolOptions): AgentTool<typeof docEditSchema> {\n\treturn wrapToolDefinition(createDocEditToolDefinition(cwd, options));\n}\n"]}
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import { mkdtempSync, renameSync, rmSync } from "node:fs";
|
|
2
|
-
import { tmpdir } from "node:os";
|
|
3
|
-
import { basename, join } from "node:path";
|
|
4
|
-
import { Container, Text } from "@kolisachint/hoocode-tui";
|
|
5
|
-
import { Type } from "typebox";
|
|
6
|
-
import { APP_NAME } from "../../../config.js";
|
|
7
|
-
import { theme as appTheme } from "../../../modes/interactive/theme/theme.js";
|
|
8
|
-
import { withFileMutationQueue } from "../file-mutation-queue.js";
|
|
9
|
-
import { ensureExtractRecord, extractDocument, findNodeById, invalidateExtractRecord, patchOpNodeId, patchOpsSchema, reconstructDocument, StalePatchError, toPatch, } from "../filetools-shared.js";
|
|
10
|
-
import { resolveReadPath } from "../path-utils.js";
|
|
11
|
-
import { invalidArgText, shortenPath, str } from "../render-utils.js";
|
|
12
|
-
import { wrapToolDefinition } from "../tool-definition-wrapper.js";
|
|
13
|
-
import { renderEnvelopeText } from "./docread.js";
|
|
14
|
-
const docEditSchema = Type.Object({
|
|
15
|
-
path: Type.String({
|
|
16
|
-
description: "Path to the document to edit in place. Must have been opened with DocRead first.",
|
|
17
|
-
}),
|
|
18
|
-
patch: patchOpsSchema,
|
|
19
|
-
});
|
|
20
|
-
function formatDocEditCall(args) {
|
|
21
|
-
const path = str(args?.path);
|
|
22
|
-
const pathDisplay = path === null ? invalidArgText(appTheme) : path ? shortenPath(path) : appTheme.fg("toolOutput", "...");
|
|
23
|
-
let text = appTheme.fg("toolTitle", appTheme.bold("DocEdit ")) + appTheme.fg("accent", pathDisplay);
|
|
24
|
-
const ops = Array.isArray(args?.patch) ? args.patch.length : undefined;
|
|
25
|
-
if (ops !== undefined)
|
|
26
|
-
text += appTheme.fg("muted", ` (${ops} op${ops === 1 ? "" : "s"})`);
|
|
27
|
-
return text;
|
|
28
|
-
}
|
|
29
|
-
export function createDocEditToolDefinition(cwd, options) {
|
|
30
|
-
return {
|
|
31
|
-
name: "DocEdit",
|
|
32
|
-
label: "DocEdit",
|
|
33
|
-
description: "Apply an id-based patch to a structured/binary document IN PLACE, losslessly. Targets node ids from a DocRead extract; if the cache is missing or the file changed on disk (e.g. an external script rewrote it) the document is re-extracted automatically, so a separate DocRead is not required. If the patch references ids that no longer exist, the call fails and returns the current structure with fresh ids so you can re-issue. Untouched bytes are preserved exactly; the file is re-extracted after the write so ids stay current for further edits. This is the canonical way to edit these formats: never fall back to ad-hoc scripts (python/openpyxl, docx, PyPDF2, unzip, sed) to rewrite them — that bypasses the lossless id-map and corrupts the file. Off by default; enabled with --enable-filetools.",
|
|
34
|
-
promptSnippet: "Patch a structured/binary document in place by node id",
|
|
35
|
-
promptGuidelines: [
|
|
36
|
-
"Use DocEdit to modify a document opened with DocRead; pass a patch of id-based ops (replace/add/remove) targeting the #ids from the extract. It edits in place and re-extracts.",
|
|
37
|
-
"Keep patches minimal — only the ops you actually need. DocEdit re-extracts after writing and refreshes ids, so do not DocRead again between edits; the full extract is token-heavy. Reach for a fresh writable DocRead only when ids have gone stale and the failure output isn't enough to continue.",
|
|
38
|
-
],
|
|
39
|
-
parameters: docEditSchema,
|
|
40
|
-
async execute(_toolCallId, { path, patch }, signal) {
|
|
41
|
-
if (signal?.aborted)
|
|
42
|
-
throw new Error("Operation aborted");
|
|
43
|
-
const absolutePath = resolveReadPath(path, cwd);
|
|
44
|
-
return withFileMutationQueue(absolutePath, async () => {
|
|
45
|
-
// Resolve affected nodes from the pre-reconstruct extract: the patch's
|
|
46
|
-
// ids are valid against THIS extract, and a later re-extract
|
|
47
|
-
// regenerates ids that would not match the patch. reconstructDocument
|
|
48
|
-
// auto-extracts when the cache is missing/stale, so capture the record
|
|
49
|
-
// the same way to stay in sync with what the patch is applied against.
|
|
50
|
-
const preRecord = await ensureExtractRecord(absolutePath, cwd, signal, {
|
|
51
|
-
timeoutSecs: options?.timeoutSecs,
|
|
52
|
-
});
|
|
53
|
-
const affectedIds = new Set();
|
|
54
|
-
for (const op of toPatch(patch).patch) {
|
|
55
|
-
const id = patchOpNodeId(op);
|
|
56
|
-
if (id)
|
|
57
|
-
affectedIds.add(id);
|
|
58
|
-
}
|
|
59
|
-
const affectedNodes = [];
|
|
60
|
-
for (const id of affectedIds) {
|
|
61
|
-
const node = findNodeById(preRecord.envelope.structure, id);
|
|
62
|
-
if (node)
|
|
63
|
-
affectedNodes.push(node);
|
|
64
|
-
}
|
|
65
|
-
// Reconstruct to a temp file, then atomically swap it into place so a
|
|
66
|
-
// failed reconstruct never leaves a half-written document behind.
|
|
67
|
-
const stageDir = mkdtempSync(join(tmpdir(), `${APP_NAME}-docedit-`));
|
|
68
|
-
const stagePath = join(stageDir, basename(absolutePath));
|
|
69
|
-
try {
|
|
70
|
-
await reconstructDocument(absolutePath, toPatch(patch), stagePath, cwd, signal, {
|
|
71
|
-
timeoutSecs: options?.timeoutSecs,
|
|
72
|
-
});
|
|
73
|
-
renameSync(stagePath, absolutePath);
|
|
74
|
-
}
|
|
75
|
-
catch (err) {
|
|
76
|
-
if (err instanceof StalePatchError) {
|
|
77
|
-
// The document was rewritten out-of-band: the cache auto-refreshed
|
|
78
|
-
// but the patch targets ids that no longer exist. Surface the
|
|
79
|
-
// current structure so the agent can re-issue without a DocRead.
|
|
80
|
-
throw new Error(`${err.message}\n\n${renderEnvelopeText(err.envelope, false)}`);
|
|
81
|
-
}
|
|
82
|
-
throw err;
|
|
83
|
-
}
|
|
84
|
-
finally {
|
|
85
|
-
rmSync(stageDir, { recursive: true, force: true });
|
|
86
|
-
}
|
|
87
|
-
// The source changed, so the cached id-map is stale. Re-extract to
|
|
88
|
-
// refresh ids for subsequent edits (best-effort; a failure here does
|
|
89
|
-
// not undo the successful write).
|
|
90
|
-
invalidateExtractRecord(absolutePath);
|
|
91
|
-
try {
|
|
92
|
-
await extractDocument(absolutePath, cwd, signal, { timeoutSecs: options?.timeoutSecs });
|
|
93
|
-
}
|
|
94
|
-
catch {
|
|
95
|
-
// Re-extract failure leaves no cached record; the next DocEdit will
|
|
96
|
-
// auto-extract (or fall back to DocRead), which is the correct path.
|
|
97
|
-
}
|
|
98
|
-
return {
|
|
99
|
-
content: [
|
|
100
|
-
{
|
|
101
|
-
type: "text",
|
|
102
|
-
text: `Applied ${patch.length} op${patch.length === 1 ? "" : "s"} to ${path} (re-extracted; ids refreshed).`,
|
|
103
|
-
},
|
|
104
|
-
],
|
|
105
|
-
details: { ops: patch.length, affected: affectedNodes.length > 0 ? affectedNodes : undefined },
|
|
106
|
-
};
|
|
107
|
-
});
|
|
108
|
-
},
|
|
109
|
-
renderCall(args, _theme, context) {
|
|
110
|
-
const text = context.lastComponent ?? new Text("", 0, 0);
|
|
111
|
-
text.setText(formatDocEditCall(args));
|
|
112
|
-
return text;
|
|
113
|
-
},
|
|
114
|
-
renderResult(result, _options, _theme, context) {
|
|
115
|
-
if (!context.isError) {
|
|
116
|
-
const component = context.lastComponent ?? new Container();
|
|
117
|
-
component.clear();
|
|
118
|
-
return component;
|
|
119
|
-
}
|
|
120
|
-
const output = result.content
|
|
121
|
-
.filter((c) => c.type === "text")
|
|
122
|
-
.map((c) => c.text || "")
|
|
123
|
-
.join("\n");
|
|
124
|
-
const text = context.lastComponent ?? new Text("", 0, 0);
|
|
125
|
-
text.setText(output ? `\n${appTheme.fg("error", output)}` : "");
|
|
126
|
-
return text;
|
|
127
|
-
},
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
export function createDocEditTool(cwd, options) {
|
|
131
|
-
return wrapToolDefinition(createDocEditToolDefinition(cwd, options));
|
|
132
|
-
}
|
|
133
|
-
//# sourceMappingURL=docedit.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"docedit.js","sourceRoot":"","sources":["../../../../src/core/tools/doc/docedit.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdtempSync, renameSync, rmSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { basename, join } from \"node:path\";\nimport type { AgentTool } from \"@kolisachint/hoocode-agent-core\";\nimport { Container, Text } from \"@kolisachint/hoocode-tui\";\nimport { type Static, Type } from \"typebox\";\nimport { APP_NAME } from \"../../../config.js\";\nimport { theme as appTheme } from \"../../../modes/interactive/theme/theme.js\";\nimport type { ToolDefinition } from \"../../extensions/types.js\";\nimport { withFileMutationQueue } from \"../file-mutation-queue.js\";\nimport {\n\ttype DocNode,\n\tensureExtractRecord,\n\textractDocument,\n\tfindNodeById,\n\tinvalidateExtractRecord,\n\tpatchOpNodeId,\n\tpatchOpsSchema,\n\treconstructDocument,\n\tStalePatchError,\n\ttoPatch,\n} from \"../filetools-shared.js\";\nimport { resolveReadPath } from \"../path-utils.js\";\nimport { invalidArgText, shortenPath, str } from \"../render-utils.js\";\nimport { wrapToolDefinition } from \"../tool-definition-wrapper.js\";\nimport { renderEnvelopeText } from \"./docread.js\";\n\nconst docEditSchema = Type.Object({\n\tpath: Type.String({\n\t\tdescription: \"Path to the document to edit in place. Must have been opened with DocRead first.\",\n\t}),\n\tpatch: patchOpsSchema,\n});\n\nexport type DocEditToolInput = Static<typeof docEditSchema>;\n\nexport interface DocEditToolDetails {\n\tops?: number;\n\taffected?: DocNode[];\n}\n\nexport interface DocEditToolOptions {\n\t/** Timeout (seconds) for the filetools invocations. */\n\ttimeoutSecs?: number;\n}\n\nfunction formatDocEditCall(args: { path?: string; patch?: unknown[] } | undefined): string {\n\tconst path = str(args?.path);\n\tconst pathDisplay =\n\t\tpath === null ? invalidArgText(appTheme) : path ? shortenPath(path) : appTheme.fg(\"toolOutput\", \"...\");\n\tlet text = appTheme.fg(\"toolTitle\", appTheme.bold(\"DocEdit \")) + appTheme.fg(\"accent\", pathDisplay);\n\tconst ops = Array.isArray(args?.patch) ? args.patch.length : undefined;\n\tif (ops !== undefined) text += appTheme.fg(\"muted\", ` (${ops} op${ops === 1 ? \"\" : \"s\"})`);\n\treturn text;\n}\n\nexport function createDocEditToolDefinition(\n\tcwd: string,\n\toptions?: DocEditToolOptions,\n): ToolDefinition<typeof docEditSchema, DocEditToolDetails | undefined> {\n\treturn {\n\t\tname: \"DocEdit\",\n\t\tlabel: \"DocEdit\",\n\t\tdescription:\n\t\t\t\"Apply an id-based patch to a structured/binary document IN PLACE, losslessly. Targets node ids from a DocRead extract; if the cache is missing or the file changed on disk (e.g. an external script rewrote it) the document is re-extracted automatically, so a separate DocRead is not required. If the patch references ids that no longer exist, the call fails and returns the current structure with fresh ids so you can re-issue. Untouched bytes are preserved exactly; the file is re-extracted after the write so ids stay current for further edits. This is the canonical way to edit these formats: never fall back to ad-hoc scripts (python/openpyxl, docx, PyPDF2, unzip, sed) to rewrite them — that bypasses the lossless id-map and corrupts the file. Off by default; enabled with --enable-filetools.\",\n\t\tpromptSnippet: \"Patch a structured/binary document in place by node id\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use DocEdit to modify a document opened with DocRead; pass a patch of id-based ops (replace/add/remove) targeting the #ids from the extract. It edits in place and re-extracts.\",\n\t\t\t\"Keep patches minimal — only the ops you actually need. DocEdit re-extracts after writing and refreshes ids, so do not DocRead again between edits; the full extract is token-heavy. Reach for a fresh writable DocRead only when ids have gone stale and the failure output isn't enough to continue.\",\n\t\t],\n\t\tparameters: docEditSchema,\n\t\tasync execute(_toolCallId, { path, patch }: DocEditToolInput, signal?: AbortSignal) {\n\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\tconst absolutePath = resolveReadPath(path, cwd);\n\n\t\t\treturn withFileMutationQueue(absolutePath, async () => {\n\t\t\t\t// Resolve affected nodes from the pre-reconstruct extract: the patch's\n\t\t\t\t// ids are valid against THIS extract, and a later re-extract\n\t\t\t\t// regenerates ids that would not match the patch. reconstructDocument\n\t\t\t\t// auto-extracts when the cache is missing/stale, so capture the record\n\t\t\t\t// the same way to stay in sync with what the patch is applied against.\n\t\t\t\tconst preRecord = await ensureExtractRecord(absolutePath, cwd, signal, {\n\t\t\t\t\ttimeoutSecs: options?.timeoutSecs,\n\t\t\t\t});\n\t\t\t\tconst affectedIds = new Set<string>();\n\t\t\t\tfor (const op of toPatch(patch).patch) {\n\t\t\t\t\tconst id = patchOpNodeId(op);\n\t\t\t\t\tif (id) affectedIds.add(id);\n\t\t\t\t}\n\t\t\t\tconst affectedNodes: DocNode[] = [];\n\t\t\t\tfor (const id of affectedIds) {\n\t\t\t\t\tconst node = findNodeById(preRecord.envelope.structure, id);\n\t\t\t\t\tif (node) affectedNodes.push(node);\n\t\t\t\t}\n\n\t\t\t\t// Reconstruct to a temp file, then atomically swap it into place so a\n\t\t\t\t// failed reconstruct never leaves a half-written document behind.\n\t\t\t\tconst stageDir = mkdtempSync(join(tmpdir(), `${APP_NAME}-docedit-`));\n\t\t\t\tconst stagePath = join(stageDir, basename(absolutePath));\n\t\t\t\ttry {\n\t\t\t\t\tawait reconstructDocument(absolutePath, toPatch(patch), stagePath, cwd, signal, {\n\t\t\t\t\t\ttimeoutSecs: options?.timeoutSecs,\n\t\t\t\t\t});\n\t\t\t\t\trenameSync(stagePath, absolutePath);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tif (err instanceof StalePatchError) {\n\t\t\t\t\t\t// The document was rewritten out-of-band: the cache auto-refreshed\n\t\t\t\t\t\t// but the patch targets ids that no longer exist. Surface the\n\t\t\t\t\t\t// current structure so the agent can re-issue without a DocRead.\n\t\t\t\t\t\tthrow new Error(`${err.message}\\n\\n${renderEnvelopeText(err.envelope, false)}`);\n\t\t\t\t\t}\n\t\t\t\t\tthrow err;\n\t\t\t\t} finally {\n\t\t\t\t\trmSync(stageDir, { recursive: true, force: true });\n\t\t\t\t}\n\n\t\t\t\t// The source changed, so the cached id-map is stale. Re-extract to\n\t\t\t\t// refresh ids for subsequent edits (best-effort; a failure here does\n\t\t\t\t// not undo the successful write).\n\t\t\t\tinvalidateExtractRecord(absolutePath);\n\t\t\t\ttry {\n\t\t\t\t\tawait extractDocument(absolutePath, cwd, signal, { timeoutSecs: options?.timeoutSecs });\n\t\t\t\t} catch {\n\t\t\t\t\t// Re-extract failure leaves no cached record; the next DocEdit will\n\t\t\t\t\t// auto-extract (or fall back to DocRead), which is the correct path.\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\ttext: `Applied ${patch.length} op${patch.length === 1 ? \"\" : \"s\"} to ${path} (re-extracted; ids refreshed).`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: { ops: patch.length, affected: affectedNodes.length > 0 ? affectedNodes : undefined },\n\t\t\t\t};\n\t\t\t});\n\t\t},\n\t\trenderCall(args, _theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatDocEditCall(args));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, _options, _theme, context) {\n\t\t\tif (!context.isError) {\n\t\t\t\tconst component = (context.lastComponent as Container | undefined) ?? new Container();\n\t\t\t\tcomponent.clear();\n\t\t\t\treturn component;\n\t\t\t}\n\t\t\tconst output = (result.content as Array<{ type: string; text?: string }>)\n\t\t\t\t.filter((c) => c.type === \"text\")\n\t\t\t\t.map((c) => c.text || \"\")\n\t\t\t\t.join(\"\\n\");\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(output ? `\\n${appTheme.fg(\"error\", output)}` : \"\");\n\t\t\treturn text;\n\t\t},\n\t};\n}\n\nexport function createDocEditTool(cwd: string, options?: DocEditToolOptions): AgentTool<typeof docEditSchema> {\n\treturn wrapToolDefinition(createDocEditToolDefinition(cwd, options));\n}\n"]}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import type { AgentTool } from "@kolisachint/hoocode-agent-core";
|
|
2
|
-
import { type Static, Type } from "typebox";
|
|
3
|
-
import type { ToolDefinition } from "../../extensions/types.js";
|
|
4
|
-
import { type GrepView } from "../filetools-shared.js";
|
|
5
|
-
declare const docGrepSchema: Type.TObject<{
|
|
6
|
-
path: Type.TString;
|
|
7
|
-
pattern: Type.TString;
|
|
8
|
-
ignoreCase: Type.TOptional<Type.TBoolean>;
|
|
9
|
-
limit: Type.TOptional<Type.TNumber>;
|
|
10
|
-
}>;
|
|
11
|
-
export type DocGrepToolInput = Static<typeof docGrepSchema>;
|
|
12
|
-
export interface DocGrepToolDetails {
|
|
13
|
-
pattern?: string;
|
|
14
|
-
matches?: number;
|
|
15
|
-
}
|
|
16
|
-
export interface DocGrepToolOptions {
|
|
17
|
-
/** Timeout (seconds) for the filetools invocation. */
|
|
18
|
-
timeoutSecs?: number;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Render grep matches as `#block_id:line :: "snippet"` lines. Each block id
|
|
22
|
-
* feeds straight back into DocPeek (to hydrate) or a DocEdit patch.
|
|
23
|
-
*/
|
|
24
|
-
export declare function renderGrepView(view: GrepView): string;
|
|
25
|
-
export declare function createDocGrepToolDefinition(cwd: string, options?: DocGrepToolOptions): ToolDefinition<typeof docGrepSchema, DocGrepToolDetails | undefined>;
|
|
26
|
-
export declare function createDocGrepTool(cwd: string, options?: DocGrepToolOptions): AgentTool<typeof docGrepSchema>;
|
|
27
|
-
export {};
|
|
28
|
-
//# sourceMappingURL=docgrep.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"docgrep.d.ts","sourceRoot":"","sources":["../../../../src/core/tools/doc/docgrep.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAEjE,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAG5C,OAAO,KAAK,EAAE,cAAc,EAA2B,MAAM,2BAA2B,CAAC;AACzF,OAAO,EAAE,KAAK,QAAQ,EAA6C,MAAM,wBAAwB,CAAC;AAKlG,QAAA,MAAM,aAAa;;;;;EAUjB,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,OAAO,aAAa,CAAC,CAAC;AAE5D,MAAM,WAAW,kBAAkB;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IAClC,sDAAsD;IACtD,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAcrD;AAgCD,wBAAgB,2BAA2B,CAC1C,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,kBAAkB,GAC1B,cAAc,CAAC,OAAO,aAAa,EAAE,kBAAkB,GAAG,SAAS,CAAC,CAsCtE;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC,OAAO,aAAa,CAAC,CAE5G","sourcesContent":["import type { AgentTool } from \"@kolisachint/hoocode-agent-core\";\nimport { Text } from \"@kolisachint/hoocode-tui\";\nimport { type Static, Type } from \"typebox\";\nimport { keyHint } from \"../../../modes/interactive/components/keybinding-hints.js\";\nimport { theme as appTheme } from \"../../../modes/interactive/theme/theme.js\";\nimport type { ToolDefinition, ToolRenderResultOptions } from \"../../extensions/types.js\";\nimport { type GrepView, grepDocument, truncateRenderToTokenBudget } from \"../filetools-shared.js\";\nimport { resolveReadPath } from \"../path-utils.js\";\nimport { getTextOutput, invalidArgText, shortenPath, str } from \"../render-utils.js\";\nimport { wrapToolDefinition } from \"../tool-definition-wrapper.js\";\n\nconst docGrepSchema = Type.Object({\n\tpath: Type.String({\n\t\tdescription:\n\t\t\t\"Path to the document to search (relative or absolute). XML, drawio, OOXML (docx/xlsx/pptx), or PDF.\",\n\t}),\n\tpattern: Type.String({\n\t\tdescription: \"Literal substring to match per line (NOT a regex).\",\n\t}),\n\tignoreCase: Type.Optional(Type.Boolean({ description: \"Case-insensitive matching. Default false.\" })),\n\tlimit: Type.Optional(Type.Number({ description: \"Stop after N matches. Default: all matches.\" })),\n});\n\nexport type DocGrepToolInput = Static<typeof docGrepSchema>;\n\nexport interface DocGrepToolDetails {\n\tpattern?: string;\n\tmatches?: number;\n}\n\nexport interface DocGrepToolOptions {\n\t/** Timeout (seconds) for the filetools invocation. */\n\ttimeoutSecs?: number;\n}\n\n/**\n * Render grep matches as `#block_id:line :: \"snippet\"` lines. Each block id\n * feeds straight back into DocPeek (to hydrate) or a DocEdit patch.\n */\nexport function renderGrepView(view: GrepView): string {\n\tconst header = `grep ${JSON.stringify(view.pattern)} — ${view.returned} match${view.returned === 1 ? \"\" : \"es\"}`;\n\tif (view.matches.length === 0) return header;\n\tconst lines: string[] = [header, \"\"];\n\tfor (const m of view.matches) {\n\t\tconst flag = m.writable ? \"\" : \" (read-only)\";\n\t\tlines.push(`#${m.block_id}:${m.line}${flag} :: ${JSON.stringify(m.snippet)}`);\n\t}\n\tconst { text, droppedLines } = truncateRenderToTokenBudget(lines);\n\tif (droppedLines === 0) return text;\n\treturn (\n\t\t`${text}\\n\\n[Truncated: ${droppedLines} more match line${droppedLines === 1 ? \"\" : \"s\"} omitted; ` +\n\t\t`re-run with a smaller limit or a more specific pattern.]`\n\t);\n}\n\nfunction formatDocGrepCall(args: { path?: string; pattern?: string; ignoreCase?: boolean } | undefined): string {\n\tconst path = str(args?.path);\n\tconst pathDisplay =\n\t\tpath === null ? invalidArgText(appTheme) : path ? shortenPath(path) : appTheme.fg(\"toolOutput\", \"...\");\n\tlet text = appTheme.fg(\"toolTitle\", appTheme.bold(\"DocGrep \"));\n\tconst pattern = str(args?.pattern);\n\tif (pattern) text += `${appTheme.fg(\"accent\", JSON.stringify(pattern))} ${appTheme.fg(\"muted\", \"in\")} `;\n\ttext += appTheme.fg(\"accent\", pathDisplay);\n\tif (args?.ignoreCase) text += appTheme.fg(\"muted\", \" (i)\");\n\treturn text;\n}\n\nfunction formatDocGrepResult(\n\tresult: { content: Array<{ type: string; text?: string }> },\n\toptions: ToolRenderResultOptions,\n\tshowImages: boolean,\n): string {\n\tconst output = getTextOutput(result as any, showImages).trim();\n\tif (!output) return \"\";\n\tconst lines = output.split(\"\\n\");\n\tconst maxLines = options.expanded ? lines.length : 15;\n\tconst displayLines = lines.slice(0, maxLines);\n\tconst remaining = lines.length - maxLines;\n\tlet text = `\\n${displayLines.map((line) => appTheme.fg(\"toolOutput\", line)).join(\"\\n\")}`;\n\tif (remaining > 0) {\n\t\ttext += `${appTheme.fg(\"muted\", `\\n... (${remaining} more lines,`)} ${keyHint(\"app.tools.expand\", \"to expand\")})`;\n\t}\n\treturn text;\n}\n\nexport function createDocGrepToolDefinition(\n\tcwd: string,\n\toptions?: DocGrepToolOptions,\n): ToolDefinition<typeof docGrepSchema, DocGrepToolDetails | undefined> {\n\treturn {\n\t\tname: \"DocGrep\",\n\t\tlabel: \"DocGrep\",\n\t\tdescription:\n\t\t\t\"Locate blocks in a structured/binary document (XML, drawio, docx/xlsx/pptx, PDF) by literal text, WITHOUT hydrating the whole document. Returns each match as an editable el_ node #id, line number, and snippet. Those el_ #ids target a DocEdit/DocWrite patch directly — DocGrep is the fast path from 'find text' to 'edit it' (far cheaper than a full DocRead). Off by default; enabled with --enable-filetools.\",\n\t\tpromptSnippet: \"Find blocks in a structured/binary document by literal text, without hydrating it\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use DocGrep to find where something is in a large structured/binary document instead of reading it all: it returns editable el_ node #ids + snippets for a literal substring match. Patch those el_ #ids straight with DocEdit/DocWrite.\",\n\t\t\t\"DocGrep's el_ #ids are the edit id-space; they are NOT DocPeek's structural-path ids. To read more context around a match, DocScan/DocPeek by structural path instead.\",\n\t\t\t\"pattern is a literal substring (not a regex); pass ignoreCase for case-insensitive matching.\",\n\t\t\t\"Works across all supported formats including spreadsheet cell values (xlsx) and slide text (pptx); patch a matched el_ #id with DocEdit, or read more context with DocPeek.\",\n\t\t],\n\t\tparameters: docGrepSchema,\n\t\tasync execute(_toolCallId, { path, pattern, ignoreCase, limit }: DocGrepToolInput, signal?: AbortSignal) {\n\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\tconst absolutePath = resolveReadPath(path, cwd);\n\t\t\tconst view = await grepDocument(absolutePath, pattern, cwd, signal, {\n\t\t\t\tignoreCase,\n\t\t\t\tlimit,\n\t\t\t\ttimeoutSecs: options?.timeoutSecs,\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\" as const, text: renderGrepView(view) }],\n\t\t\t\tdetails: { pattern: view.pattern, matches: view.returned },\n\t\t\t};\n\t\t},\n\t\trenderCall(args, _theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatDocGrepCall(args));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, _theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatDocGrepResult(result as any, options, context.showImages));\n\t\t\treturn text;\n\t\t},\n\t};\n}\n\nexport function createDocGrepTool(cwd: string, options?: DocGrepToolOptions): AgentTool<typeof docGrepSchema> {\n\treturn wrapToolDefinition(createDocGrepToolDefinition(cwd, options));\n}\n"]}
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { Text } from "@kolisachint/hoocode-tui";
|
|
2
|
-
import { Type } from "typebox";
|
|
3
|
-
import { keyHint } from "../../../modes/interactive/components/keybinding-hints.js";
|
|
4
|
-
import { theme as appTheme } from "../../../modes/interactive/theme/theme.js";
|
|
5
|
-
import { grepDocument, truncateRenderToTokenBudget } from "../filetools-shared.js";
|
|
6
|
-
import { resolveReadPath } from "../path-utils.js";
|
|
7
|
-
import { getTextOutput, invalidArgText, shortenPath, str } from "../render-utils.js";
|
|
8
|
-
import { wrapToolDefinition } from "../tool-definition-wrapper.js";
|
|
9
|
-
const docGrepSchema = Type.Object({
|
|
10
|
-
path: Type.String({
|
|
11
|
-
description: "Path to the document to search (relative or absolute). XML, drawio, OOXML (docx/xlsx/pptx), or PDF.",
|
|
12
|
-
}),
|
|
13
|
-
pattern: Type.String({
|
|
14
|
-
description: "Literal substring to match per line (NOT a regex).",
|
|
15
|
-
}),
|
|
16
|
-
ignoreCase: Type.Optional(Type.Boolean({ description: "Case-insensitive matching. Default false." })),
|
|
17
|
-
limit: Type.Optional(Type.Number({ description: "Stop after N matches. Default: all matches." })),
|
|
18
|
-
});
|
|
19
|
-
/**
|
|
20
|
-
* Render grep matches as `#block_id:line :: "snippet"` lines. Each block id
|
|
21
|
-
* feeds straight back into DocPeek (to hydrate) or a DocEdit patch.
|
|
22
|
-
*/
|
|
23
|
-
export function renderGrepView(view) {
|
|
24
|
-
const header = `grep ${JSON.stringify(view.pattern)} — ${view.returned} match${view.returned === 1 ? "" : "es"}`;
|
|
25
|
-
if (view.matches.length === 0)
|
|
26
|
-
return header;
|
|
27
|
-
const lines = [header, ""];
|
|
28
|
-
for (const m of view.matches) {
|
|
29
|
-
const flag = m.writable ? "" : " (read-only)";
|
|
30
|
-
lines.push(`#${m.block_id}:${m.line}${flag} :: ${JSON.stringify(m.snippet)}`);
|
|
31
|
-
}
|
|
32
|
-
const { text, droppedLines } = truncateRenderToTokenBudget(lines);
|
|
33
|
-
if (droppedLines === 0)
|
|
34
|
-
return text;
|
|
35
|
-
return (`${text}\n\n[Truncated: ${droppedLines} more match line${droppedLines === 1 ? "" : "s"} omitted; ` +
|
|
36
|
-
`re-run with a smaller limit or a more specific pattern.]`);
|
|
37
|
-
}
|
|
38
|
-
function formatDocGrepCall(args) {
|
|
39
|
-
const path = str(args?.path);
|
|
40
|
-
const pathDisplay = path === null ? invalidArgText(appTheme) : path ? shortenPath(path) : appTheme.fg("toolOutput", "...");
|
|
41
|
-
let text = appTheme.fg("toolTitle", appTheme.bold("DocGrep "));
|
|
42
|
-
const pattern = str(args?.pattern);
|
|
43
|
-
if (pattern)
|
|
44
|
-
text += `${appTheme.fg("accent", JSON.stringify(pattern))} ${appTheme.fg("muted", "in")} `;
|
|
45
|
-
text += appTheme.fg("accent", pathDisplay);
|
|
46
|
-
if (args?.ignoreCase)
|
|
47
|
-
text += appTheme.fg("muted", " (i)");
|
|
48
|
-
return text;
|
|
49
|
-
}
|
|
50
|
-
function formatDocGrepResult(result, options, showImages) {
|
|
51
|
-
const output = getTextOutput(result, showImages).trim();
|
|
52
|
-
if (!output)
|
|
53
|
-
return "";
|
|
54
|
-
const lines = output.split("\n");
|
|
55
|
-
const maxLines = options.expanded ? lines.length : 15;
|
|
56
|
-
const displayLines = lines.slice(0, maxLines);
|
|
57
|
-
const remaining = lines.length - maxLines;
|
|
58
|
-
let text = `\n${displayLines.map((line) => appTheme.fg("toolOutput", line)).join("\n")}`;
|
|
59
|
-
if (remaining > 0) {
|
|
60
|
-
text += `${appTheme.fg("muted", `\n... (${remaining} more lines,`)} ${keyHint("app.tools.expand", "to expand")})`;
|
|
61
|
-
}
|
|
62
|
-
return text;
|
|
63
|
-
}
|
|
64
|
-
export function createDocGrepToolDefinition(cwd, options) {
|
|
65
|
-
return {
|
|
66
|
-
name: "DocGrep",
|
|
67
|
-
label: "DocGrep",
|
|
68
|
-
description: "Locate blocks in a structured/binary document (XML, drawio, docx/xlsx/pptx, PDF) by literal text, WITHOUT hydrating the whole document. Returns each match as an editable el_ node #id, line number, and snippet. Those el_ #ids target a DocEdit/DocWrite patch directly — DocGrep is the fast path from 'find text' to 'edit it' (far cheaper than a full DocRead). Off by default; enabled with --enable-filetools.",
|
|
69
|
-
promptSnippet: "Find blocks in a structured/binary document by literal text, without hydrating it",
|
|
70
|
-
promptGuidelines: [
|
|
71
|
-
"Use DocGrep to find where something is in a large structured/binary document instead of reading it all: it returns editable el_ node #ids + snippets for a literal substring match. Patch those el_ #ids straight with DocEdit/DocWrite.",
|
|
72
|
-
"DocGrep's el_ #ids are the edit id-space; they are NOT DocPeek's structural-path ids. To read more context around a match, DocScan/DocPeek by structural path instead.",
|
|
73
|
-
"pattern is a literal substring (not a regex); pass ignoreCase for case-insensitive matching.",
|
|
74
|
-
"Works across all supported formats including spreadsheet cell values (xlsx) and slide text (pptx); patch a matched el_ #id with DocEdit, or read more context with DocPeek.",
|
|
75
|
-
],
|
|
76
|
-
parameters: docGrepSchema,
|
|
77
|
-
async execute(_toolCallId, { path, pattern, ignoreCase, limit }, signal) {
|
|
78
|
-
if (signal?.aborted)
|
|
79
|
-
throw new Error("Operation aborted");
|
|
80
|
-
const absolutePath = resolveReadPath(path, cwd);
|
|
81
|
-
const view = await grepDocument(absolutePath, pattern, cwd, signal, {
|
|
82
|
-
ignoreCase,
|
|
83
|
-
limit,
|
|
84
|
-
timeoutSecs: options?.timeoutSecs,
|
|
85
|
-
});
|
|
86
|
-
return {
|
|
87
|
-
content: [{ type: "text", text: renderGrepView(view) }],
|
|
88
|
-
details: { pattern: view.pattern, matches: view.returned },
|
|
89
|
-
};
|
|
90
|
-
},
|
|
91
|
-
renderCall(args, _theme, context) {
|
|
92
|
-
const text = context.lastComponent ?? new Text("", 0, 0);
|
|
93
|
-
text.setText(formatDocGrepCall(args));
|
|
94
|
-
return text;
|
|
95
|
-
},
|
|
96
|
-
renderResult(result, options, _theme, context) {
|
|
97
|
-
const text = context.lastComponent ?? new Text("", 0, 0);
|
|
98
|
-
text.setText(formatDocGrepResult(result, options, context.showImages));
|
|
99
|
-
return text;
|
|
100
|
-
},
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
export function createDocGrepTool(cwd, options) {
|
|
104
|
-
return wrapToolDefinition(createDocGrepToolDefinition(cwd, options));
|
|
105
|
-
}
|
|
106
|
-
//# sourceMappingURL=docgrep.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"docgrep.js","sourceRoot":"","sources":["../../../../src/core/tools/doc/docgrep.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool } from \"@kolisachint/hoocode-agent-core\";\nimport { Text } from \"@kolisachint/hoocode-tui\";\nimport { type Static, Type } from \"typebox\";\nimport { keyHint } from \"../../../modes/interactive/components/keybinding-hints.js\";\nimport { theme as appTheme } from \"../../../modes/interactive/theme/theme.js\";\nimport type { ToolDefinition, ToolRenderResultOptions } from \"../../extensions/types.js\";\nimport { type GrepView, grepDocument, truncateRenderToTokenBudget } from \"../filetools-shared.js\";\nimport { resolveReadPath } from \"../path-utils.js\";\nimport { getTextOutput, invalidArgText, shortenPath, str } from \"../render-utils.js\";\nimport { wrapToolDefinition } from \"../tool-definition-wrapper.js\";\n\nconst docGrepSchema = Type.Object({\n\tpath: Type.String({\n\t\tdescription:\n\t\t\t\"Path to the document to search (relative or absolute). XML, drawio, OOXML (docx/xlsx/pptx), or PDF.\",\n\t}),\n\tpattern: Type.String({\n\t\tdescription: \"Literal substring to match per line (NOT a regex).\",\n\t}),\n\tignoreCase: Type.Optional(Type.Boolean({ description: \"Case-insensitive matching. Default false.\" })),\n\tlimit: Type.Optional(Type.Number({ description: \"Stop after N matches. Default: all matches.\" })),\n});\n\nexport type DocGrepToolInput = Static<typeof docGrepSchema>;\n\nexport interface DocGrepToolDetails {\n\tpattern?: string;\n\tmatches?: number;\n}\n\nexport interface DocGrepToolOptions {\n\t/** Timeout (seconds) for the filetools invocation. */\n\ttimeoutSecs?: number;\n}\n\n/**\n * Render grep matches as `#block_id:line :: \"snippet\"` lines. Each block id\n * feeds straight back into DocPeek (to hydrate) or a DocEdit patch.\n */\nexport function renderGrepView(view: GrepView): string {\n\tconst header = `grep ${JSON.stringify(view.pattern)} — ${view.returned} match${view.returned === 1 ? \"\" : \"es\"}`;\n\tif (view.matches.length === 0) return header;\n\tconst lines: string[] = [header, \"\"];\n\tfor (const m of view.matches) {\n\t\tconst flag = m.writable ? \"\" : \" (read-only)\";\n\t\tlines.push(`#${m.block_id}:${m.line}${flag} :: ${JSON.stringify(m.snippet)}`);\n\t}\n\tconst { text, droppedLines } = truncateRenderToTokenBudget(lines);\n\tif (droppedLines === 0) return text;\n\treturn (\n\t\t`${text}\\n\\n[Truncated: ${droppedLines} more match line${droppedLines === 1 ? \"\" : \"s\"} omitted; ` +\n\t\t`re-run with a smaller limit or a more specific pattern.]`\n\t);\n}\n\nfunction formatDocGrepCall(args: { path?: string; pattern?: string; ignoreCase?: boolean } | undefined): string {\n\tconst path = str(args?.path);\n\tconst pathDisplay =\n\t\tpath === null ? invalidArgText(appTheme) : path ? shortenPath(path) : appTheme.fg(\"toolOutput\", \"...\");\n\tlet text = appTheme.fg(\"toolTitle\", appTheme.bold(\"DocGrep \"));\n\tconst pattern = str(args?.pattern);\n\tif (pattern) text += `${appTheme.fg(\"accent\", JSON.stringify(pattern))} ${appTheme.fg(\"muted\", \"in\")} `;\n\ttext += appTheme.fg(\"accent\", pathDisplay);\n\tif (args?.ignoreCase) text += appTheme.fg(\"muted\", \" (i)\");\n\treturn text;\n}\n\nfunction formatDocGrepResult(\n\tresult: { content: Array<{ type: string; text?: string }> },\n\toptions: ToolRenderResultOptions,\n\tshowImages: boolean,\n): string {\n\tconst output = getTextOutput(result as any, showImages).trim();\n\tif (!output) return \"\";\n\tconst lines = output.split(\"\\n\");\n\tconst maxLines = options.expanded ? lines.length : 15;\n\tconst displayLines = lines.slice(0, maxLines);\n\tconst remaining = lines.length - maxLines;\n\tlet text = `\\n${displayLines.map((line) => appTheme.fg(\"toolOutput\", line)).join(\"\\n\")}`;\n\tif (remaining > 0) {\n\t\ttext += `${appTheme.fg(\"muted\", `\\n... (${remaining} more lines,`)} ${keyHint(\"app.tools.expand\", \"to expand\")})`;\n\t}\n\treturn text;\n}\n\nexport function createDocGrepToolDefinition(\n\tcwd: string,\n\toptions?: DocGrepToolOptions,\n): ToolDefinition<typeof docGrepSchema, DocGrepToolDetails | undefined> {\n\treturn {\n\t\tname: \"DocGrep\",\n\t\tlabel: \"DocGrep\",\n\t\tdescription:\n\t\t\t\"Locate blocks in a structured/binary document (XML, drawio, docx/xlsx/pptx, PDF) by literal text, WITHOUT hydrating the whole document. Returns each match as an editable el_ node #id, line number, and snippet. Those el_ #ids target a DocEdit/DocWrite patch directly — DocGrep is the fast path from 'find text' to 'edit it' (far cheaper than a full DocRead). Off by default; enabled with --enable-filetools.\",\n\t\tpromptSnippet: \"Find blocks in a structured/binary document by literal text, without hydrating it\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use DocGrep to find where something is in a large structured/binary document instead of reading it all: it returns editable el_ node #ids + snippets for a literal substring match. Patch those el_ #ids straight with DocEdit/DocWrite.\",\n\t\t\t\"DocGrep's el_ #ids are the edit id-space; they are NOT DocPeek's structural-path ids. To read more context around a match, DocScan/DocPeek by structural path instead.\",\n\t\t\t\"pattern is a literal substring (not a regex); pass ignoreCase for case-insensitive matching.\",\n\t\t\t\"Works across all supported formats including spreadsheet cell values (xlsx) and slide text (pptx); patch a matched el_ #id with DocEdit, or read more context with DocPeek.\",\n\t\t],\n\t\tparameters: docGrepSchema,\n\t\tasync execute(_toolCallId, { path, pattern, ignoreCase, limit }: DocGrepToolInput, signal?: AbortSignal) {\n\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\tconst absolutePath = resolveReadPath(path, cwd);\n\t\t\tconst view = await grepDocument(absolutePath, pattern, cwd, signal, {\n\t\t\t\tignoreCase,\n\t\t\t\tlimit,\n\t\t\t\ttimeoutSecs: options?.timeoutSecs,\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\" as const, text: renderGrepView(view) }],\n\t\t\t\tdetails: { pattern: view.pattern, matches: view.returned },\n\t\t\t};\n\t\t},\n\t\trenderCall(args, _theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatDocGrepCall(args));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, _theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatDocGrepResult(result as any, options, context.showImages));\n\t\t\treturn text;\n\t\t},\n\t};\n}\n\nexport function createDocGrepTool(cwd: string, options?: DocGrepToolOptions): AgentTool<typeof docGrepSchema> {\n\treturn wrapToolDefinition(createDocGrepToolDefinition(cwd, options));\n}\n"]}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { AgentTool } from "@kolisachint/hoocode-agent-core";
|
|
2
|
-
import { type Static, Type } from "typebox";
|
|
3
|
-
import type { ToolDefinition } from "../../extensions/types.js";
|
|
4
|
-
import { type ReadView } from "../filetools-shared.js";
|
|
5
|
-
declare const docPeekSchema: Type.TObject<{
|
|
6
|
-
path: Type.TString;
|
|
7
|
-
id: Type.TOptional<Type.TArray<Type.TString>>;
|
|
8
|
-
offset: Type.TOptional<Type.TNumber>;
|
|
9
|
-
limit: Type.TOptional<Type.TNumber>;
|
|
10
|
-
}>;
|
|
11
|
-
export type DocPeekToolInput = Static<typeof docPeekSchema>;
|
|
12
|
-
export interface DocPeekToolDetails {
|
|
13
|
-
returned?: number;
|
|
14
|
-
total?: number;
|
|
15
|
-
}
|
|
16
|
-
export interface DocPeekToolOptions {
|
|
17
|
-
/** Timeout (seconds) for the filetools invocation. */
|
|
18
|
-
timeoutSecs?: number;
|
|
19
|
-
}
|
|
20
|
-
/** Render hydrated read blocks using the same id-addressed node dialect as DocRead. */
|
|
21
|
-
export declare function renderReadView(view: ReadView): string;
|
|
22
|
-
export declare function createDocPeekToolDefinition(cwd: string, options?: DocPeekToolOptions): ToolDefinition<typeof docPeekSchema, DocPeekToolDetails | undefined>;
|
|
23
|
-
export declare function createDocPeekTool(cwd: string, options?: DocPeekToolOptions): AgentTool<typeof docPeekSchema>;
|
|
24
|
-
export {};
|
|
25
|
-
//# sourceMappingURL=docpeek.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"docpeek.d.ts","sourceRoot":"","sources":["../../../../src/core/tools/doc/docpeek.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAEjE,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAG5C,OAAO,KAAK,EAAE,cAAc,EAA2B,MAAM,2BAA2B,CAAC;AACzF,OAAO,EACN,KAAK,QAAQ,EAIb,MAAM,wBAAwB,CAAC;AAKhC,QAAA,MAAM,aAAa;;;;;EAYjB,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,OAAO,aAAa,CAAC,CAAC;AAE5D,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IAClC,sDAAsD;IACtD,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,uFAAuF;AACvF,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAmBrD;AAuCD,wBAAgB,2BAA2B,CAC1C,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,kBAAkB,GAC1B,cAAc,CAAC,OAAO,aAAa,EAAE,kBAAkB,GAAG,SAAS,CAAC,CAuCtE;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC,OAAO,aAAa,CAAC,CAE5G","sourcesContent":["import type { AgentTool } from \"@kolisachint/hoocode-agent-core\";\nimport { Text } from \"@kolisachint/hoocode-tui\";\nimport { type Static, Type } from \"typebox\";\nimport { keyHint } from \"../../../modes/interactive/components/keybinding-hints.js\";\nimport { theme as appTheme } from \"../../../modes/interactive/theme/theme.js\";\nimport type { ToolDefinition, ToolRenderResultOptions } from \"../../extensions/types.js\";\nimport {\n\ttype ReadView,\n\treadDocumentBlocks,\n\trenderDocNodeLines,\n\ttruncateRenderToTokenBudget,\n} from \"../filetools-shared.js\";\nimport { resolveReadPath } from \"../path-utils.js\";\nimport { getTextOutput, invalidArgText, shortenPath, str } from \"../render-utils.js\";\nimport { wrapToolDefinition } from \"../tool-definition-wrapper.js\";\n\nconst docPeekSchema = Type.Object({\n\tpath: Type.String({\n\t\tdescription: \"Path to the document to read (relative or absolute). XML, drawio, OOXML (docx/xlsx/pptx), or PDF.\",\n\t}),\n\tid: Type.Optional(\n\t\tType.Array(Type.String(), {\n\t\t\tdescription:\n\t\t\t\t\"Block id(s) to hydrate — use the EXACT ids returned by a prior DocScan (e.g. 'node[title:0]', 'paragraph[3]', 'page[1]'); do NOT hand-construct sub-ranges (an invented 'rows[0-2]' returns nothing — pass the exact 'rows[0-99]' DocScan emitted). These are DocScan's path ids, not DocGrep's el_ node ids. Omit to read a paginated slice of all blocks.\",\n\t\t}),\n\t),\n\toffset: Type.Optional(Type.Number({ description: \"Pagination start when no ids are given. Default 0.\" })),\n\tlimit: Type.Optional(Type.Number({ description: \"Pagination size when no ids are given. Default: all remaining.\" })),\n});\n\nexport type DocPeekToolInput = Static<typeof docPeekSchema>;\n\nexport interface DocPeekToolDetails {\n\treturned?: number;\n\ttotal?: number;\n}\n\nexport interface DocPeekToolOptions {\n\t/** Timeout (seconds) for the filetools invocation. */\n\ttimeoutSecs?: number;\n}\n\n/** Render hydrated read blocks using the same id-addressed node dialect as DocRead. */\nexport function renderReadView(view: ReadView): string {\n\tconst header = `document — ${view.returned}/${view.total} blocks (offset ${view.offset})`;\n\tconst lines: string[] = [header, \"\", ...renderDocNodeLines(view.nodes)];\n\tconst { text, droppedLines } = truncateRenderToTokenBudget(lines);\n\tconst seen = view.offset + view.returned;\n\tconst remaining = view.total - seen;\n\tconst parts = [text];\n\tif (droppedLines > 0) {\n\t\tparts.push(\n\t\t\t`\\n[Truncated: ${droppedLines} more node line${droppedLines === 1 ? \"\" : \"s\"} omitted; ` +\n\t\t\t\t`request fewer ids or a smaller limit.]`,\n\t\t);\n\t}\n\tif (remaining > 0) {\n\t\tparts.push(\n\t\t\t`\\n[${remaining} more block${remaining === 1 ? \"\" : \"s\"} not shown — re-run with offset:${seen} to continue.]`,\n\t\t);\n\t}\n\treturn parts.join(\"\\n\");\n}\n\nfunction formatDocPeekCall(\n\targs: { path?: string; id?: string[]; offset?: number; limit?: number } | undefined,\n): string {\n\tconst path = str(args?.path);\n\tconst pathDisplay =\n\t\tpath === null ? invalidArgText(appTheme) : path ? shortenPath(path) : appTheme.fg(\"toolOutput\", \"...\");\n\tlet text = appTheme.fg(\"toolTitle\", appTheme.bold(\"DocPeek \")) + appTheme.fg(\"accent\", pathDisplay);\n\tconst ids = Array.isArray(args?.id) ? args.id.length : 0;\n\tif (ids > 0) {\n\t\ttext += appTheme.fg(\"muted\", ` (${ids} id${ids === 1 ? \"\" : \"s\"})`);\n\t} else {\n\t\tconst range: string[] = [];\n\t\tif (args?.offset !== undefined) range.push(`offset ${args.offset}`);\n\t\tif (args?.limit !== undefined) range.push(`limit ${args.limit}`);\n\t\tif (range.length > 0) text += appTheme.fg(\"muted\", ` (${range.join(\", \")})`);\n\t}\n\treturn text;\n}\n\nfunction formatDocPeekResult(\n\tresult: { content: Array<{ type: string; text?: string }> },\n\toptions: ToolRenderResultOptions,\n\tshowImages: boolean,\n): string {\n\tconst output = getTextOutput(result as any, showImages).trim();\n\tif (!output) return \"\";\n\tconst lines = output.split(\"\\n\");\n\tconst maxLines = options.expanded ? lines.length : 15;\n\tconst displayLines = lines.slice(0, maxLines);\n\tconst remaining = lines.length - maxLines;\n\tlet text = `\\n${displayLines.map((line) => appTheme.fg(\"toolOutput\", line)).join(\"\\n\")}`;\n\tif (remaining > 0) {\n\t\ttext += `${appTheme.fg(\"muted\", `\\n... (${remaining} more lines,`)} ${keyHint(\"app.tools.expand\", \"to expand\")})`;\n\t}\n\treturn text;\n}\n\nexport function createDocPeekToolDefinition(\n\tcwd: string,\n\toptions?: DocPeekToolOptions,\n): ToolDefinition<typeof docPeekSchema, DocPeekToolDetails | undefined> {\n\treturn {\n\t\tname: \"DocPeek\",\n\t\tlabel: \"DocPeek\",\n\t\tdescription:\n\t\t\t\"Hydrate specific blocks of a structured/binary document (XML, drawio, docx/xlsx/pptx, PDF) by structural-path id — the read half of the token-sensitive loop. Pass the path ids from a prior DocScan (e.g. node[title:0]) to read only those blocks (or omit ids to page through all with offset/limit), instead of dumping the whole document with DocRead. The hydrated nodes carry the editable el_ #ids, which you then patch with DocEdit/DocWrite. Read-only. Off by default; enabled with --enable-filetools.\",\n\t\tpromptSnippet: \"Read only specific blocks of a structured/binary document by id\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use DocPeek to read just the blocks you need (by structural-path id from DocScan, e.g. node[title:0]) instead of a full DocRead — it is much cheaper in tokens. Omit ids and use offset/limit to page through a large document.\",\n\t\t\t\"Pass the EXACT ids DocScan returned; DocPeek does not accept invented sub-ranges (e.g. rows[0-2] when DocScan emitted rows[0-99]).\",\n\t\t\t\"DocPeek takes DocScan's path ids, NOT DocGrep's el_ node ids. The nodes it returns carry the editable el_ #ids — patch those with DocEdit/DocWrite (which auto-extract). If you already have an el_ id from DocGrep, go straight to DocEdit; you do not need DocPeek.\",\n\t\t\t\"Works across all supported formats including spreadsheet cells (hydrating a sheet's rows[a-b] block returns the cell values) and slide text (pptx).\",\n\t\t],\n\t\tparameters: docPeekSchema,\n\t\tasync execute(_toolCallId, { path, id, offset, limit }: DocPeekToolInput, signal?: AbortSignal) {\n\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\tconst absolutePath = resolveReadPath(path, cwd);\n\t\t\tconst view = await readDocumentBlocks(absolutePath, cwd, signal, {\n\t\t\t\tids: id,\n\t\t\t\toffset,\n\t\t\t\tlimit,\n\t\t\t\ttimeoutSecs: options?.timeoutSecs,\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\" as const, text: renderReadView(view) }],\n\t\t\t\tdetails: { returned: view.returned, total: view.total },\n\t\t\t};\n\t\t},\n\t\trenderCall(args, _theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatDocPeekCall(args));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, _theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatDocPeekResult(result as any, options, context.showImages));\n\t\t\treturn text;\n\t\t},\n\t};\n}\n\nexport function createDocPeekTool(cwd: string, options?: DocPeekToolOptions): AgentTool<typeof docPeekSchema> {\n\treturn wrapToolDefinition(createDocPeekToolDefinition(cwd, options));\n}\n"]}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { Text } from "@kolisachint/hoocode-tui";
|
|
2
|
-
import { Type } from "typebox";
|
|
3
|
-
import { keyHint } from "../../../modes/interactive/components/keybinding-hints.js";
|
|
4
|
-
import { theme as appTheme } from "../../../modes/interactive/theme/theme.js";
|
|
5
|
-
import { readDocumentBlocks, renderDocNodeLines, truncateRenderToTokenBudget, } from "../filetools-shared.js";
|
|
6
|
-
import { resolveReadPath } from "../path-utils.js";
|
|
7
|
-
import { getTextOutput, invalidArgText, shortenPath, str } from "../render-utils.js";
|
|
8
|
-
import { wrapToolDefinition } from "../tool-definition-wrapper.js";
|
|
9
|
-
const docPeekSchema = Type.Object({
|
|
10
|
-
path: Type.String({
|
|
11
|
-
description: "Path to the document to read (relative or absolute). XML, drawio, OOXML (docx/xlsx/pptx), or PDF.",
|
|
12
|
-
}),
|
|
13
|
-
id: Type.Optional(Type.Array(Type.String(), {
|
|
14
|
-
description: "Block id(s) to hydrate — use the EXACT ids returned by a prior DocScan (e.g. 'node[title:0]', 'paragraph[3]', 'page[1]'); do NOT hand-construct sub-ranges (an invented 'rows[0-2]' returns nothing — pass the exact 'rows[0-99]' DocScan emitted). These are DocScan's path ids, not DocGrep's el_ node ids. Omit to read a paginated slice of all blocks.",
|
|
15
|
-
})),
|
|
16
|
-
offset: Type.Optional(Type.Number({ description: "Pagination start when no ids are given. Default 0." })),
|
|
17
|
-
limit: Type.Optional(Type.Number({ description: "Pagination size when no ids are given. Default: all remaining." })),
|
|
18
|
-
});
|
|
19
|
-
/** Render hydrated read blocks using the same id-addressed node dialect as DocRead. */
|
|
20
|
-
export function renderReadView(view) {
|
|
21
|
-
const header = `document — ${view.returned}/${view.total} blocks (offset ${view.offset})`;
|
|
22
|
-
const lines = [header, "", ...renderDocNodeLines(view.nodes)];
|
|
23
|
-
const { text, droppedLines } = truncateRenderToTokenBudget(lines);
|
|
24
|
-
const seen = view.offset + view.returned;
|
|
25
|
-
const remaining = view.total - seen;
|
|
26
|
-
const parts = [text];
|
|
27
|
-
if (droppedLines > 0) {
|
|
28
|
-
parts.push(`\n[Truncated: ${droppedLines} more node line${droppedLines === 1 ? "" : "s"} omitted; ` +
|
|
29
|
-
`request fewer ids or a smaller limit.]`);
|
|
30
|
-
}
|
|
31
|
-
if (remaining > 0) {
|
|
32
|
-
parts.push(`\n[${remaining} more block${remaining === 1 ? "" : "s"} not shown — re-run with offset:${seen} to continue.]`);
|
|
33
|
-
}
|
|
34
|
-
return parts.join("\n");
|
|
35
|
-
}
|
|
36
|
-
function formatDocPeekCall(args) {
|
|
37
|
-
const path = str(args?.path);
|
|
38
|
-
const pathDisplay = path === null ? invalidArgText(appTheme) : path ? shortenPath(path) : appTheme.fg("toolOutput", "...");
|
|
39
|
-
let text = appTheme.fg("toolTitle", appTheme.bold("DocPeek ")) + appTheme.fg("accent", pathDisplay);
|
|
40
|
-
const ids = Array.isArray(args?.id) ? args.id.length : 0;
|
|
41
|
-
if (ids > 0) {
|
|
42
|
-
text += appTheme.fg("muted", ` (${ids} id${ids === 1 ? "" : "s"})`);
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
const range = [];
|
|
46
|
-
if (args?.offset !== undefined)
|
|
47
|
-
range.push(`offset ${args.offset}`);
|
|
48
|
-
if (args?.limit !== undefined)
|
|
49
|
-
range.push(`limit ${args.limit}`);
|
|
50
|
-
if (range.length > 0)
|
|
51
|
-
text += appTheme.fg("muted", ` (${range.join(", ")})`);
|
|
52
|
-
}
|
|
53
|
-
return text;
|
|
54
|
-
}
|
|
55
|
-
function formatDocPeekResult(result, options, showImages) {
|
|
56
|
-
const output = getTextOutput(result, showImages).trim();
|
|
57
|
-
if (!output)
|
|
58
|
-
return "";
|
|
59
|
-
const lines = output.split("\n");
|
|
60
|
-
const maxLines = options.expanded ? lines.length : 15;
|
|
61
|
-
const displayLines = lines.slice(0, maxLines);
|
|
62
|
-
const remaining = lines.length - maxLines;
|
|
63
|
-
let text = `\n${displayLines.map((line) => appTheme.fg("toolOutput", line)).join("\n")}`;
|
|
64
|
-
if (remaining > 0) {
|
|
65
|
-
text += `${appTheme.fg("muted", `\n... (${remaining} more lines,`)} ${keyHint("app.tools.expand", "to expand")})`;
|
|
66
|
-
}
|
|
67
|
-
return text;
|
|
68
|
-
}
|
|
69
|
-
export function createDocPeekToolDefinition(cwd, options) {
|
|
70
|
-
return {
|
|
71
|
-
name: "DocPeek",
|
|
72
|
-
label: "DocPeek",
|
|
73
|
-
description: "Hydrate specific blocks of a structured/binary document (XML, drawio, docx/xlsx/pptx, PDF) by structural-path id — the read half of the token-sensitive loop. Pass the path ids from a prior DocScan (e.g. node[title:0]) to read only those blocks (or omit ids to page through all with offset/limit), instead of dumping the whole document with DocRead. The hydrated nodes carry the editable el_ #ids, which you then patch with DocEdit/DocWrite. Read-only. Off by default; enabled with --enable-filetools.",
|
|
74
|
-
promptSnippet: "Read only specific blocks of a structured/binary document by id",
|
|
75
|
-
promptGuidelines: [
|
|
76
|
-
"Use DocPeek to read just the blocks you need (by structural-path id from DocScan, e.g. node[title:0]) instead of a full DocRead — it is much cheaper in tokens. Omit ids and use offset/limit to page through a large document.",
|
|
77
|
-
"Pass the EXACT ids DocScan returned; DocPeek does not accept invented sub-ranges (e.g. rows[0-2] when DocScan emitted rows[0-99]).",
|
|
78
|
-
"DocPeek takes DocScan's path ids, NOT DocGrep's el_ node ids. The nodes it returns carry the editable el_ #ids — patch those with DocEdit/DocWrite (which auto-extract). If you already have an el_ id from DocGrep, go straight to DocEdit; you do not need DocPeek.",
|
|
79
|
-
"Works across all supported formats including spreadsheet cells (hydrating a sheet's rows[a-b] block returns the cell values) and slide text (pptx).",
|
|
80
|
-
],
|
|
81
|
-
parameters: docPeekSchema,
|
|
82
|
-
async execute(_toolCallId, { path, id, offset, limit }, signal) {
|
|
83
|
-
if (signal?.aborted)
|
|
84
|
-
throw new Error("Operation aborted");
|
|
85
|
-
const absolutePath = resolveReadPath(path, cwd);
|
|
86
|
-
const view = await readDocumentBlocks(absolutePath, cwd, signal, {
|
|
87
|
-
ids: id,
|
|
88
|
-
offset,
|
|
89
|
-
limit,
|
|
90
|
-
timeoutSecs: options?.timeoutSecs,
|
|
91
|
-
});
|
|
92
|
-
return {
|
|
93
|
-
content: [{ type: "text", text: renderReadView(view) }],
|
|
94
|
-
details: { returned: view.returned, total: view.total },
|
|
95
|
-
};
|
|
96
|
-
},
|
|
97
|
-
renderCall(args, _theme, context) {
|
|
98
|
-
const text = context.lastComponent ?? new Text("", 0, 0);
|
|
99
|
-
text.setText(formatDocPeekCall(args));
|
|
100
|
-
return text;
|
|
101
|
-
},
|
|
102
|
-
renderResult(result, options, _theme, context) {
|
|
103
|
-
const text = context.lastComponent ?? new Text("", 0, 0);
|
|
104
|
-
text.setText(formatDocPeekResult(result, options, context.showImages));
|
|
105
|
-
return text;
|
|
106
|
-
},
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
export function createDocPeekTool(cwd, options) {
|
|
110
|
-
return wrapToolDefinition(createDocPeekToolDefinition(cwd, options));
|
|
111
|
-
}
|
|
112
|
-
//# sourceMappingURL=docpeek.js.map
|