@sayknow-cli/coding-agent 0.4.7 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +122 -0
- package/dist/types/capability/index.d.ts +10 -20
- package/dist/types/capability/types.d.ts +3 -0
- package/dist/types/cli/args.d.ts +0 -2
- package/dist/types/cli/read-cli.d.ts +1 -0
- package/dist/types/cli.d.ts +9 -1
- package/dist/types/commands/daemon.d.ts +2 -2
- package/dist/types/commands/deep-interview.d.ts +9 -0
- package/dist/types/commands/harness.d.ts +22 -0
- package/dist/types/commands/read.d.ts +6 -0
- package/dist/types/commands/sdk.d.ts +20 -2
- package/dist/types/config/keybindings.d.ts +34 -4
- package/dist/types/config/model-profile-contract.d.ts +40 -0
- package/dist/types/config/model-profiles.d.ts +2 -3
- package/dist/types/config/model-registry.d.ts +5 -0
- package/dist/types/config/provider-auth-health.d.ts +14 -0
- package/dist/types/config/provider-ranking.d.ts +59 -0
- package/dist/types/config/settings-schema.d.ts +156 -10
- package/dist/types/config/settings.d.ts +3 -0
- package/dist/types/edit/modes/patch.d.ts +13 -0
- package/dist/types/edit/path-mutation-lock.d.ts +15 -0
- package/dist/types/eval/py/executor.d.ts +1 -1
- package/dist/types/eval/py/runner-artifact.d.ts +8 -0
- package/dist/types/eval/py/tool-bridge.d.ts +1 -2
- package/dist/types/extensibility/extensions/types.d.ts +43 -2
- package/dist/types/extensibility/shared-events.d.ts +6 -0
- package/dist/types/internal-urls/local-root-gc.d.ts +2 -0
- package/dist/types/main.d.ts +33 -2
- package/dist/types/memories/index.d.ts +2 -0
- package/dist/types/modes/acp/acp-agent.d.ts +22 -9
- package/dist/types/modes/components/assistant-message.d.ts +3 -1
- package/dist/types/modes/components/btw-panel.d.ts +1 -0
- package/dist/types/modes/components/irc-sidebar.d.ts +41 -0
- package/dist/types/modes/components/queue-pane.d.ts +8 -0
- package/dist/types/modes/components/queued-message-selector.d.ts +6 -0
- package/dist/types/modes/components/read-tool-group.d.ts +4 -4
- package/dist/types/modes/components/runtime-mcp-add-wizard.d.ts +2 -1
- package/dist/types/modes/components/session-observer-overlay.d.ts +4 -0
- package/dist/types/modes/components/settings-selector.d.ts +2 -0
- package/dist/types/modes/components/tool-execution.d.ts +8 -0
- package/dist/types/modes/components/tool-status-header.d.ts +4 -2
- package/dist/types/modes/components/welcome.d.ts +5 -0
- package/dist/types/modes/controllers/btw-controller.d.ts +5 -0
- package/dist/types/modes/controllers/command-controller.d.ts +2 -0
- package/dist/types/modes/controllers/event-controller.d.ts +3 -0
- package/dist/types/modes/interactive-mode.d.ts +13 -2
- package/dist/types/modes/irc-observation-ledger.d.ts +17 -1
- package/dist/types/modes/prompt-action-autocomplete.d.ts +6 -1
- package/dist/types/modes/prompt-suggestion-controller.d.ts +35 -0
- package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +2 -2
- package/dist/types/modes/types.d.ts +6 -0
- package/dist/types/modes/utils/hotkeys-markdown.d.ts +2 -1
- package/dist/types/modes/utils/ui-helpers.d.ts +16 -0
- package/dist/types/runtime/memory-domain.d.ts +9 -0
- package/dist/types/runtime/memory-guard-contract.d.ts +71 -0
- package/dist/types/runtime/memory-guard.d.ts +39 -0
- package/dist/types/runtime/memory-limit.d.ts +11 -0
- package/dist/types/runtime-mcp/content-limits.d.ts +7 -0
- package/dist/types/runtime-mcp/discoverable-tool-metadata.d.ts +1 -1
- package/dist/types/runtime-mcp/manager.d.ts +9 -1
- package/dist/types/runtime-mcp/oauth-flow.d.ts +0 -5
- package/dist/types/runtime-mcp/plugin-network-boundary.d.ts +14 -0
- package/dist/types/runtime-mcp/redaction.d.ts +2 -0
- package/dist/types/runtime-mcp/smithery-auth.d.ts +5 -0
- package/dist/types/sdk/acp/final-text.d.ts +19 -0
- package/dist/types/sdk/acp/mcp.d.ts +23 -0
- package/dist/types/sdk/broker/broker.d.ts +2 -0
- package/dist/types/sdk/broker/lifecycle.d.ts +13 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +9 -1
- package/dist/types/sdk/bus/config-commands.d.ts +2 -2
- package/dist/types/sdk/bus/config.d.ts +2 -0
- package/dist/types/sdk/bus/control-drain-lease.d.ts +52 -0
- package/dist/types/sdk/bus/conversation-store.d.ts +1 -0
- package/dist/types/sdk/bus/daemon-paths.d.ts +1 -0
- package/dist/types/sdk/bus/index.d.ts +52 -4
- package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +37 -0
- package/dist/types/sdk/bus/lifecycle-commands.d.ts +5 -4
- package/dist/types/sdk/bus/notification-orchestration.d.ts +1 -0
- package/dist/types/sdk/bus/notification-service.d.ts +34 -0
- package/dist/types/sdk/bus/operator-runtime.d.ts +1 -0
- package/dist/types/sdk/bus/prompt-reconciliation.d.ts +106 -0
- package/dist/types/sdk/bus/rate-limit-pool.d.ts +2 -0
- package/dist/types/sdk/bus/reconciliation-store.d.ts +65 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +33 -9
- package/dist/types/sdk/bus/telegram-daemon-control.d.ts +5 -1
- package/dist/types/sdk/bus/telegram-daemon.d.ts +286 -12
- package/dist/types/sdk/bus/telegram-reference.d.ts +2 -0
- package/dist/types/sdk/bus/topic-registry.d.ts +88 -2
- package/dist/types/sdk/client/discovery.d.ts +2 -0
- package/dist/types/sdk/client/liveness.d.ts +7 -0
- package/dist/types/sdk/host/control/operations.d.ts +3 -2
- package/dist/types/sdk/host/host.d.ts +3 -1
- package/dist/types/sdk/host/query/handlers.d.ts +14 -0
- package/dist/types/sdk/index.d.ts +2 -0
- package/dist/types/sdk/lifecycle-session.d.ts +10 -1
- package/dist/types/sdk/prompt-status.d.ts +88 -0
- package/dist/types/sdk/session-directory.d.ts +1 -1
- package/dist/types/sdk/session.d.ts +7 -0
- package/dist/types/sdk/startup-capability.d.ts +9 -0
- package/dist/types/sdk/transport/auth-preface.d.ts +9 -0
- package/dist/types/sdk/transport/index.d.ts +12 -0
- package/dist/types/sdk/transport/relay.d.ts +43 -0
- package/dist/types/sdk/transport/serve-cli.d.ts +4 -0
- package/dist/types/sdk/transport/socket.d.ts +7 -0
- package/dist/types/sdk/transport/stdio.d.ts +3 -0
- package/dist/types/session/agent-session.d.ts +83 -24
- package/dist/types/session/btw-contract.d.ts +16 -0
- package/dist/types/session/fallback-chain-controller.d.ts +18 -2
- package/dist/types/session/internal/managed-session-scope.d.ts +70 -10
- package/dist/types/session/internal/managed-session-storage.d.ts +34 -12
- package/dist/types/session/internal/native-publish-outcome.d.ts +48 -0
- package/dist/types/session/memory-guard-checkpoint-participant.d.ts +69 -0
- package/dist/types/session/session-manager.d.ts +89 -18
- package/dist/types/session/session-storage.d.ts +31 -0
- package/dist/types/session/streaming-output.d.ts +60 -5
- package/dist/types/setup/credential-import.d.ts +5 -1
- package/dist/types/setup/provider-onboarding.d.ts +2 -0
- package/dist/types/skc-runtime/deep-interview-runtime.d.ts +1 -1
- package/dist/types/skc-runtime/deep-interview-stage.d.ts +37 -0
- package/dist/types/skc-runtime/gc-runtime.d.ts +1 -1
- package/dist/types/skc-runtime/linux-proc.d.ts +22 -14
- package/dist/types/skc-runtime/memory-guard-owner-claims.d.ts +47 -0
- package/dist/types/skc-runtime/ralplan-runtime.d.ts +112 -1
- package/dist/types/skc-runtime/repository-binding.d.ts +63 -0
- package/dist/types/skc-runtime/state-runtime.d.ts +3 -1
- package/dist/types/skc-runtime/state-writer.d.ts +5 -1
- package/dist/types/skc-runtime/team-launch.d.ts +1 -1
- package/dist/types/skc-runtime/team-runtime.d.ts +9 -2
- package/dist/types/skc-runtime/team-store.d.ts +12 -0
- package/dist/types/skc-runtime/team-worker-memory-guard.d.ts +92 -0
- package/dist/types/skc-runtime/tmux-owner-isolation.d.ts +7 -0
- package/dist/types/skc-runtime/ultragoal-guard.d.ts +6 -5
- package/dist/types/skc-runtime/ultragoal-receipt-freshness.d.ts +28 -0
- package/dist/types/skc-runtime/ultragoal-runtime.d.ts +43 -5
- package/dist/types/skill-state/workflow-hud.d.ts +3 -0
- package/dist/types/ssh/utils.d.ts +1 -0
- package/dist/types/task/discovery.d.ts +3 -1
- package/dist/types/task/executor.d.ts +6 -0
- package/dist/types/task/index.d.ts +3 -1
- package/dist/types/task/provider-retry-status.d.ts +13 -0
- package/dist/types/task/receipt.d.ts +2 -0
- package/dist/types/task/types.d.ts +133 -0
- package/dist/types/task/ultragoal-redteam-activation.d.ts +33 -0
- package/dist/types/tools/browser/launch.d.ts +7 -0
- package/dist/types/tools/fetch.d.ts +22 -9
- package/dist/types/tools/image-gen.d.ts +63 -1
- package/dist/types/tools/index.d.ts +7 -1
- package/dist/types/tools/output-meta.d.ts +21 -1
- package/dist/types/tools/read-internals.d.ts +12 -0
- package/dist/types/tools/read.d.ts +45 -1
- package/dist/types/tools/resource-gc.d.ts +23 -0
- package/dist/types/tools/skill-discovery.d.ts +7 -0
- package/dist/types/tools/sqlite-reader.d.ts +7 -0
- package/dist/types/tools/tool-result.d.ts +7 -1
- package/dist/types/utils/prompt-suggestion.d.ts +33 -0
- package/dist/types/utils/shell-snapshot.d.ts +12 -0
- package/dist/types/web/insane/bridge.d.ts +1 -0
- package/dist/types/web/insane/url-guard.d.ts +17 -0
- package/package.json +8 -12
- package/scripts/benchmark-sticky-viewport-pr1.ts +239 -0
- package/scripts/capture-platform-shortcut-labels-showcase.ts +342 -0
- package/scripts/capture-sticky-viewport-showcase.ts +292 -0
- package/scripts/compile-args.ts +0 -1
- package/scripts/dogfood-repository-binding.ts +209 -0
- package/scripts/generate-docs-index.ts +4 -1
- package/scripts/generate-sdk-operation-inventory.ts +9 -0
- package/scripts/run-test-manifest.ts +6 -4
- package/scripts/verify-skc-sdk-canonicalization.ts +122 -18
- package/scripts/verify-sticky-viewport-showcase.ts +611 -0
- package/src/capability/index.ts +58 -42
- package/src/capability/types.ts +3 -0
- package/src/cli/args.ts +16 -100
- package/src/cli/fast-help.ts +1 -1
- package/src/cli/mcp-cli.ts +4 -21
- package/src/cli/notify-cli.ts +6 -38
- package/src/cli/read-cli.ts +2 -1
- package/src/cli/setup-cli.ts +10 -4
- package/src/cli.ts +133 -11
- package/src/commands/daemon.ts +22 -5
- package/src/commands/deep-interview.ts +26 -1
- package/src/commands/harness.ts +35 -12
- package/src/commands/read.ts +11 -2
- package/src/commands/sdk.ts +134 -17
- package/src/commands/team.ts +1 -1
- package/src/commit/agentic/index.ts +3 -3
- package/src/commit/map-reduce/index.ts +2 -2
- package/src/config/keybindings.ts +158 -25
- package/src/config/model-profile-contract.ts +174 -0
- package/src/config/model-profiles.ts +51 -10
- package/src/config/model-registry.ts +24 -4
- package/src/config/model-resolver.ts +2 -2
- package/src/config/provider-auth-health.ts +42 -0
- package/src/config/provider-ranking.ts +119 -0
- package/src/config/settings-schema.ts +157 -10
- package/src/config/settings.ts +254 -108
- package/src/coordinator-mcp/model-preset.ts +21 -74
- package/src/defaults/skc/skills/deep-interview/SKILL.md +147 -24
- package/src/defaults/skc/skills/ralplan/SKILL.md +91 -34
- package/src/defaults/skc/skills/team/SKILL.md +1 -1
- package/src/defaults/skc/skills/ultragoal/SKILL.md +68 -17
- package/src/discovery/ssh.ts +12 -1
- package/src/edit/index.ts +3 -6
- package/src/edit/modes/patch.ts +38 -1
- package/src/edit/modes/replace.ts +42 -0
- package/src/edit/path-mutation-lock.ts +112 -0
- package/src/eval/js/tool-bridge.ts +1 -1
- package/src/eval/py/executor.ts +37 -13
- package/src/eval/py/kernel.ts +1 -21
- package/src/eval/py/prelude.py +2 -2
- package/src/eval/py/runner-artifact.ts +84 -0
- package/src/eval/py/tool-bridge.ts +34 -18
- package/src/extensibility/extensions/runner.ts +4 -0
- package/src/extensibility/extensions/types.ts +42 -4
- package/src/extensibility/plugins/marketplace/fetcher.ts +191 -7
- package/src/extensibility/shared-events.ts +5 -0
- package/src/extensibility/skc-plugins/runtime-adapters.ts +2 -1
- package/src/hooks/native-skill-hook.ts +17 -4
- package/src/internal-urls/docs-index.generated.ts +17 -16
- package/src/internal-urls/local-protocol.ts +87 -25
- package/src/internal-urls/local-root-gc.ts +127 -0
- package/src/internal-urls/mcp-protocol.ts +73 -11
- package/src/main.ts +120 -42
- package/src/memories/index.ts +10 -0
- package/src/modes/DESIGN.md +52 -0
- package/src/modes/acp/acp-agent.ts +647 -83
- package/src/modes/acp/acp-event-mapper.ts +106 -12
- package/src/modes/acp/acp-mode.ts +39 -3
- package/src/modes/action-registry.ts +1 -1
- package/src/modes/components/assistant-message.ts +123 -22
- package/src/modes/components/btw-panel.ts +82 -16
- package/src/modes/components/irc-sidebar.ts +176 -62
- package/src/modes/components/model-selector.ts +61 -4
- package/src/modes/components/notifications-settings-editor.ts +1 -1
- package/src/modes/components/oauth-selector.ts +42 -12
- package/src/modes/components/plan-preview-overlay.ts +1 -1
- package/src/modes/components/queue-pane.ts +55 -9
- package/src/modes/components/queued-message-selector.ts +53 -10
- package/src/modes/components/read-tool-group.ts +82 -14
- package/src/modes/components/runtime-mcp-add-wizard.ts +5 -0
- package/src/modes/components/sayknow-pet-widget.ts +20 -8
- package/src/modes/components/session-observer-overlay.ts +187 -32
- package/src/modes/components/settings-selector.ts +60 -18
- package/src/modes/components/tool-execution.ts +138 -27
- package/src/modes/components/tool-status-header.ts +26 -8
- package/src/modes/components/welcome.ts +50 -23
- package/src/modes/controllers/btw-controller.ts +119 -36
- package/src/modes/controllers/command-controller.ts +101 -54
- package/src/modes/controllers/event-controller.ts +119 -27
- package/src/modes/controllers/extension-ui-controller.ts +23 -12
- package/src/modes/controllers/input-controller.ts +100 -8
- package/src/modes/controllers/runtime-mcp-command-controller.ts +29 -6
- package/src/modes/controllers/selector-controller.ts +4 -1
- package/src/modes/interactive-mode.ts +201 -60
- package/src/modes/irc-observation-ledger.ts +71 -15
- package/src/modes/prompt-action-autocomplete.ts +32 -13
- package/src/modes/prompt-suggestion-controller.ts +96 -0
- package/src/modes/runtime-init.ts +20 -2
- package/src/modes/shared/agent-wire/command-dispatch.ts +3 -3
- package/src/modes/shared/agent-wire/workflow-gate-broker.ts +2 -2
- package/src/modes/types.ts +6 -0
- package/src/modes/utils/hotkeys-markdown.ts +64 -36
- package/src/modes/utils/ui-helpers.ts +99 -4
- package/src/prompts/agent-fragments/restricted-bash.md +1 -1
- package/src/prompts/agents/architect.md +17 -3
- package/src/prompts/agents/critic.md +17 -2
- package/src/prompts/agents/executor.md +1 -1
- package/src/prompts/agents/planner.md +8 -1
- package/src/prompts/system/btw-user.md +3 -8
- package/src/prompts/system/prompt-suggestion-system.md +32 -0
- package/src/prompts/system/system-prompt.md +6 -3
- package/src/prompts/tools/cron.md +3 -1
- package/src/prompts/tools/read.md +4 -2
- package/src/prompts/tools/skill-discovery.md +1 -0
- package/src/runtime/memory-domain.ts +66 -0
- package/src/runtime/memory-guard-contract.ts +73 -0
- package/src/runtime/memory-guard.ts +292 -0
- package/src/runtime/memory-limit.ts +50 -0
- package/src/runtime-mcp/client.ts +41 -55
- package/src/runtime-mcp/content-limits.ts +71 -0
- package/src/runtime-mcp/discoverable-tool-metadata.ts +1 -1
- package/src/runtime-mcp/json-rpc.ts +28 -11
- package/src/runtime-mcp/manager.ts +77 -59
- package/src/runtime-mcp/oauth-flow.ts +0 -72
- package/src/runtime-mcp/plugin-network-boundary.ts +101 -0
- package/src/runtime-mcp/redaction.ts +30 -0
- package/src/runtime-mcp/smithery-auth.ts +17 -2
- package/src/runtime-mcp/smithery-connect.ts +11 -1
- package/src/runtime-mcp/transports/http.ts +63 -22
- package/src/sdk/acp/adapter.ts +8 -1
- package/src/sdk/acp/final-text.ts +40 -0
- package/src/sdk/acp/mcp.ts +26 -0
- package/src/sdk/broker/broker.ts +34 -20
- package/src/sdk/broker/identity.ts +22 -12
- package/src/sdk/broker/lifecycle.ts +293 -43
- package/src/sdk/broker/session-index.ts +11 -1
- package/src/sdk/bus/chat-daemon-cli.ts +2 -2
- package/src/sdk/bus/chat-daemon-control.ts +22 -5
- package/src/sdk/bus/config-commands.ts +2 -2
- package/src/sdk/bus/config.ts +10 -2
- package/src/sdk/bus/control-drain-lease.ts +104 -0
- package/src/sdk/bus/conversation-store.ts +40 -6
- package/src/sdk/bus/daemon-paths.ts +2 -0
- package/src/sdk/bus/index.ts +793 -121
- package/src/sdk/bus/kind-aware-reconciliation.ts +242 -0
- package/src/sdk/bus/lifecycle-commands.ts +63 -10
- package/src/sdk/bus/lifecycle-control-runtime.ts +11 -2
- package/src/sdk/bus/lifecycle-orchestrator.ts +32 -1
- package/src/sdk/bus/notification-orchestration.ts +12 -0
- package/src/sdk/bus/notification-service.ts +87 -25
- package/src/sdk/bus/operator-runtime.ts +31 -5
- package/src/sdk/bus/prompt-reconciliation.ts +240 -0
- package/src/sdk/bus/rate-limit-pool.ts +8 -0
- package/src/sdk/bus/recent-activity.ts +90 -26
- package/src/sdk/bus/reconciliation-store.ts +224 -0
- package/src/sdk/bus/telegram-cli.ts +6 -13
- package/src/sdk/bus/telegram-daemon-cli.ts +8 -3
- package/src/sdk/bus/telegram-daemon-contract.ts +34 -9
- package/src/sdk/bus/telegram-daemon-control.ts +161 -40
- package/src/sdk/bus/telegram-daemon.ts +3649 -593
- package/src/sdk/bus/telegram-reference.ts +20 -2
- package/src/sdk/bus/topic-registry.ts +451 -12
- package/src/sdk/cli/session-cli.ts +15 -2
- package/src/sdk/client/discovery.ts +19 -3
- package/src/sdk/client/liveness.ts +49 -0
- package/src/sdk/host/control/dispatch.ts +8 -2
- package/src/sdk/host/control/operations.ts +3 -2
- package/src/sdk/host/host.ts +27 -9
- package/src/sdk/host/query/handlers.ts +125 -5
- package/src/sdk/index.ts +12 -0
- package/src/sdk/lifecycle-session.ts +19 -3
- package/src/sdk/mcp/server.ts +46 -18
- package/src/sdk/prompt-status.ts +97 -0
- package/src/sdk/protocol/operation-inventory.generated.json +145 -0
- package/src/sdk/protocol/operation-registry.ts +24 -4
- package/src/sdk/session-directory.ts +5 -1
- package/src/sdk/session.ts +69 -8
- package/src/sdk/startup-capability.ts +15 -1
- package/src/sdk/transport/auth-preface.ts +82 -0
- package/src/sdk/transport/index.ts +18 -0
- package/src/sdk/transport/relay.ts +252 -0
- package/src/sdk/transport/serve-cli.ts +105 -0
- package/src/sdk/transport/socket.ts +197 -0
- package/src/sdk/transport/stdio.ts +17 -0
- package/src/session/agent-session.ts +1112 -314
- package/src/session/blob-store.ts +25 -7
- package/src/session/btw-contract.ts +59 -0
- package/src/session/fallback-chain-controller.ts +47 -8
- package/src/session/internal/managed-session-scope.ts +1426 -259
- package/src/session/internal/managed-session-storage.ts +414 -238
- package/src/session/internal/native-publish-outcome.ts +271 -0
- package/src/session/memory-guard-checkpoint-participant.ts +131 -0
- package/src/session/session-manager.ts +2079 -469
- package/src/session/session-storage.ts +151 -11
- package/src/session/streaming-output.ts +262 -43
- package/src/setup/credential-import.ts +28 -3
- package/src/setup/provider-onboarding.ts +49 -5
- package/src/setup/provider-presets.json +2 -1
- package/src/skc-runtime/deep-interview-runtime.ts +303 -36
- package/src/skc-runtime/deep-interview-stage.ts +1016 -0
- package/src/skc-runtime/deep-interview-state.ts +8 -5
- package/src/skc-runtime/gc-render.ts +1 -0
- package/src/skc-runtime/gc-runtime.ts +11 -1
- package/src/skc-runtime/linux-proc.ts +70 -36
- package/src/skc-runtime/managed-owner-supervisor.ts +83 -4
- package/src/skc-runtime/memory-guard-owner-claims.ts +389 -0
- package/src/skc-runtime/ralplan-runtime.ts +1057 -75
- package/src/skc-runtime/repository-binding.ts +267 -0
- package/src/skc-runtime/session-state-sidecar.ts +25 -9
- package/src/skc-runtime/state-runtime.ts +50 -12
- package/src/skc-runtime/state-writer.ts +68 -56
- package/src/skc-runtime/team-launch.ts +34 -5
- package/src/skc-runtime/team-runtime.ts +41 -1
- package/src/skc-runtime/team-store.ts +32 -0
- package/src/skc-runtime/team-worker-memory-guard.ts +363 -0
- package/src/skc-runtime/team-workers.ts +1 -0
- package/src/skc-runtime/tmux-common.ts +13 -2
- package/src/skc-runtime/tmux-owner-isolation.ts +20 -1
- package/src/skc-runtime/tmux-sessions.ts +45 -6
- package/src/skc-runtime/ultragoal-guard.ts +93 -15
- package/src/skc-runtime/ultragoal-receipt-freshness.ts +123 -0
- package/src/skc-runtime/ultragoal-runtime.ts +469 -38
- package/src/skc-runtime/workflow-manifest.generated.json +195 -5
- package/src/skc-runtime/workflow-manifest.ts +67 -3
- package/src/skill-state/workflow-hud.ts +25 -2
- package/src/skill-state/workflow-mutation-guard.ts +104 -12
- package/src/slash-commands/builtin-registry.ts +1 -1
- package/src/ssh/utils.ts +14 -0
- package/src/task/discovery.ts +8 -2
- package/src/task/executor.ts +165 -47
- package/src/task/index.ts +123 -15
- package/src/task/provider-retry-status.ts +88 -0
- package/src/task/receipt.ts +3 -0
- package/src/task/render.ts +45 -26
- package/src/task/skc-command.ts +2 -2
- package/src/task/types.ts +55 -10
- package/src/task/ultragoal-redteam-activation.ts +75 -0
- package/src/tools/ask.ts +1 -1
- package/src/tools/ast-edit.ts +2 -2
- package/src/tools/bash-allowed-prefixes.ts +45 -1
- package/src/tools/bash-pty-selection.ts +2 -2
- package/src/tools/browser/launch.ts +41 -6
- package/src/tools/browser/screenshot-format.ts +6 -1
- package/src/tools/cron.ts +1 -1
- package/src/tools/fetch.ts +127 -154
- package/src/tools/image-gen.ts +476 -23
- package/src/tools/index.ts +7 -1
- package/src/tools/output-meta.ts +176 -9
- package/src/tools/path-utils.ts +5 -1
- package/src/tools/read-internals.ts +44 -0
- package/src/tools/read.ts +1544 -310
- package/src/tools/resource-gc.ts +665 -125
- package/src/tools/skill-discovery.ts +39 -3
- package/src/tools/sqlite-reader.ts +63 -5
- package/src/tools/subagent-render.ts +74 -16
- package/src/tools/subagent.ts +2 -0
- package/src/tools/tool-result.ts +14 -1
- package/src/utils/edit-mode.ts +2 -2
- package/src/utils/pasted-image-path.ts +15 -6
- package/src/utils/prompt-suggestion.ts +265 -0
- package/src/utils/shell-snapshot.ts +173 -63
- package/src/utils/sixel.ts +3 -3
- package/src/web/insane/bridge.ts +5 -1
- package/src/web/insane/url-guard.ts +140 -27
- package/src/web/scrapers/docs-rs.ts +30 -5
- package/src/web/scrapers/types.ts +19 -49
- package/src/web/scrapers/utils.ts +12 -26
- package/src/web/search/providers/codex.ts +1 -1
- package/src/workflow/workflow-intent-diff.ts +4 -1
package/src/tools/fetch.ts
CHANGED
|
@@ -4,21 +4,19 @@ import type { AgentToolResult } from "@sayknow-cli/agent-core";
|
|
|
4
4
|
import type { ImageContent, TextContent } from "@sayknow-cli/ai";
|
|
5
5
|
import { htmlToMarkdown } from "@sayknow-cli/natives";
|
|
6
6
|
import { type Component, Text } from "@sayknow-cli/tui";
|
|
7
|
-
import {
|
|
7
|
+
import { ptree, truncate } from "@sayknow-cli/utils";
|
|
8
8
|
import type { Settings } from "../config/settings";
|
|
9
9
|
import type { RenderResultOptions } from "../extensibility/custom-tools/types";
|
|
10
10
|
import { type Theme, theme } from "../modes/theme/theme";
|
|
11
11
|
import type { ToolSession } from "../sdk";
|
|
12
12
|
import type { AgentStorage } from "../session/agent-storage";
|
|
13
|
-
import { DEFAULT_MAX_BYTES,
|
|
13
|
+
import { DEFAULT_MAX_BYTES, type TruncationDirection, truncateContent } from "../session/streaming-output";
|
|
14
14
|
import { renderStatusLine } from "../tui";
|
|
15
15
|
import { CachedOutputBlock } from "../tui/output-block";
|
|
16
16
|
import { formatDimensionNote, resizeImage } from "../utils/image-resize";
|
|
17
17
|
import { parseHtmlLazy } from "../utils/linkedom";
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import { validatePublicHttpUrl, validatePublicHttpUrlForInsane } from "../web/insane/url-guard";
|
|
21
|
-
import { extractWithParallel, findParallelApiKey, getParallelExtractContent } from "../web/parallel";
|
|
18
|
+
import { INSANE_NOTES } from "../web/insane/bridge";
|
|
19
|
+
import { validatePublicHttpUrl } from "../web/insane/url-guard";
|
|
22
20
|
import { specialHandlers } from "../web/scrapers";
|
|
23
21
|
import type { RenderResult } from "../web/scrapers/types";
|
|
24
22
|
import { finalizeOutput, loadPage, looksLikeHtml, MAX_OUTPUT_CHARS } from "../web/scrapers/types";
|
|
@@ -93,13 +91,6 @@ const MAX_INLINE_IMAGE_OUTPUT_BYTES = 300 * 1024;
|
|
|
93
91
|
// Utilities
|
|
94
92
|
// =============================================================================
|
|
95
93
|
|
|
96
|
-
/**
|
|
97
|
-
* Check if a command exists (cross-platform)
|
|
98
|
-
*/
|
|
99
|
-
function hasCommand(cmd: string): boolean {
|
|
100
|
-
return Boolean($which(cmd));
|
|
101
|
-
}
|
|
102
|
-
|
|
103
94
|
/**
|
|
104
95
|
* Build llms.txt candidates scoped to the requested URL
|
|
105
96
|
*/
|
|
@@ -537,96 +528,18 @@ async function parseFeedToMarkdown(content: string, maxItems = 10): Promise<stri
|
|
|
537
528
|
return content; // Fall back to raw content
|
|
538
529
|
}
|
|
539
530
|
|
|
540
|
-
|
|
541
|
-
* Render HTML to markdown using Parallel, jina, trafilatura, lynx (in order of preference)
|
|
542
|
-
*/
|
|
543
|
-
async function renderHtmlToText(
|
|
544
|
-
url: string,
|
|
531
|
+
export async function renderHtmlToText(
|
|
545
532
|
html: string,
|
|
546
|
-
|
|
547
|
-
settings: Settings,
|
|
548
|
-
userSignal: AbortSignal | undefined,
|
|
549
|
-
storage: AgentStorage | null,
|
|
533
|
+
signal?: AbortSignal,
|
|
550
534
|
): Promise<{ content: string; ok: boolean; method: string }> {
|
|
551
|
-
const signal = ptree.combineSignals(userSignal, timeout * 1000);
|
|
552
|
-
const execOptions = {
|
|
553
|
-
mode: "group" as const,
|
|
554
|
-
allowNonZero: true,
|
|
555
|
-
allowAbort: true,
|
|
556
|
-
stderr: "full" as const,
|
|
557
|
-
signal,
|
|
558
|
-
};
|
|
559
|
-
|
|
560
|
-
// Try Parallel extract first when credentials are configured
|
|
561
|
-
if (settings.get("providers.parallelFetch") && findParallelApiKey(storage)) {
|
|
562
|
-
try {
|
|
563
|
-
const parallelResult = await extractWithParallel(
|
|
564
|
-
[url],
|
|
565
|
-
{
|
|
566
|
-
objective: "Extract the main content",
|
|
567
|
-
excerpts: true,
|
|
568
|
-
fullContent: false,
|
|
569
|
-
signal,
|
|
570
|
-
},
|
|
571
|
-
storage,
|
|
572
|
-
);
|
|
573
|
-
const firstDocument = parallelResult.results[0];
|
|
574
|
-
if (firstDocument) {
|
|
575
|
-
const content = getParallelExtractContent(firstDocument);
|
|
576
|
-
if (content.trim().length > 100 && !isLowQualityOutput(content)) {
|
|
577
|
-
return { content, ok: true, method: "parallel" };
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
} catch {
|
|
581
|
-
// Parallel extract failed, continue to next method
|
|
582
|
-
signal?.throwIfAborted();
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
// Try jina first (reader API)
|
|
587
535
|
try {
|
|
588
|
-
const jinaUrl = `https://r.jina.ai/${url}`;
|
|
589
|
-
const response = await fetch(jinaUrl, {
|
|
590
|
-
headers: { Accept: "text/markdown" },
|
|
591
|
-
signal,
|
|
592
|
-
});
|
|
593
|
-
if (response.ok) {
|
|
594
|
-
const content = await response.text();
|
|
595
|
-
if (content.trim().length > 100 && !isLowQualityOutput(content)) {
|
|
596
|
-
return { content, ok: true, method: "jina" };
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
} catch {
|
|
600
|
-
// Jina failed, continue to next method
|
|
601
536
|
signal?.throwIfAborted();
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
// Try trafilatura (auto-install via uv/pip)
|
|
605
|
-
const trafilatura = await ensureTool("trafilatura", { signal, silent: true });
|
|
606
|
-
if (trafilatura) {
|
|
607
|
-
const result = await ptree.exec([trafilatura, "-u", url, "--output-format", "markdown"], execOptions);
|
|
608
|
-
if (result.ok && result.stdout.trim().length > 100) {
|
|
609
|
-
return { content: result.stdout, ok: true, method: "trafilatura" };
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
// Try lynx (can't auto-install, system package)
|
|
614
|
-
const lynx = hasCommand("lynx");
|
|
615
|
-
if (lynx) {
|
|
616
|
-
const result = await ptree.exec(["lynx", "-dump", "-nolist", "-width", "250", url], execOptions);
|
|
617
|
-
if (result.ok) {
|
|
618
|
-
return { content: result.stdout, ok: true, method: "lynx" };
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
// Fall back to native converter (fastest, no network/subprocess)
|
|
623
|
-
try {
|
|
624
537
|
const content = await htmlToMarkdown(html, { cleanContent: true });
|
|
625
538
|
if (content.trim().length > 100 && !isLowQualityOutput(content)) {
|
|
626
539
|
return { content, ok: true, method: "native" };
|
|
627
540
|
}
|
|
628
541
|
} catch {
|
|
629
|
-
// Native
|
|
542
|
+
// Native conversion failed; the caller returns its bounded raw HTML.
|
|
630
543
|
signal?.throwIfAborted();
|
|
631
544
|
}
|
|
632
545
|
return { content: "", ok: false, method: "none" };
|
|
@@ -707,14 +620,6 @@ async function handleSpecialUrls(
|
|
|
707
620
|
// Main Render Function
|
|
708
621
|
// =============================================================================
|
|
709
622
|
|
|
710
|
-
/**
|
|
711
|
-
* Opt-in insane-search fallback for blocked / degraded public URL reads.
|
|
712
|
-
*
|
|
713
|
-
* Returns a finalized `method: "insane"` result on success, or null (so the
|
|
714
|
-
* caller continues with its normal degraded behavior). Fail-closed: no note,
|
|
715
|
-
* guard DNS, dependency probe, or subprocess when raw mode or the opt-in
|
|
716
|
-
* setting is off. The public-URL guard runs BEFORE any probe/spawn.
|
|
717
|
-
*/
|
|
718
623
|
export async function tryInsaneFallback(args: {
|
|
719
624
|
url: string;
|
|
720
625
|
finalUrl: string;
|
|
@@ -727,32 +632,7 @@ export async function tryInsaneFallback(args: {
|
|
|
727
632
|
}): Promise<FetchRenderResult | null> {
|
|
728
633
|
if (args.raw) return null;
|
|
729
634
|
if (args.settings.get("web.insaneFallback") !== true) return null;
|
|
730
|
-
|
|
731
|
-
const target = args.finalUrl || args.url;
|
|
732
|
-
const guard = await validatePublicHttpUrlForInsane(target);
|
|
733
|
-
if (!guard.ok) {
|
|
734
|
-
args.notes.push(INSANE_NOTES.guardBlocked(guard.reason));
|
|
735
|
-
return null;
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
const result = await tryInsaneFetch(guard.url.toString(), {
|
|
739
|
-
timeoutMs: args.timeout * 1000,
|
|
740
|
-
signal: args.signal,
|
|
741
|
-
});
|
|
742
|
-
if (result.ok) {
|
|
743
|
-
const output = finalizeOutput(result.content);
|
|
744
|
-
return {
|
|
745
|
-
url: args.url,
|
|
746
|
-
finalUrl: target,
|
|
747
|
-
contentType: "text/markdown",
|
|
748
|
-
method: "insane",
|
|
749
|
-
content: output.content,
|
|
750
|
-
fetchedAt: args.fetchedAt,
|
|
751
|
-
truncated: output.truncated,
|
|
752
|
-
notes: [...args.notes, ...result.notes],
|
|
753
|
-
};
|
|
754
|
-
}
|
|
755
|
-
for (const note of result.notes) args.notes.push(note);
|
|
635
|
+
args.notes.push(INSANE_NOTES.securityDisabled);
|
|
756
636
|
return null;
|
|
757
637
|
}
|
|
758
638
|
|
|
@@ -772,6 +652,7 @@ async function renderUrl(
|
|
|
772
652
|
if (signal?.aborted) {
|
|
773
653
|
throw new ToolAbortError();
|
|
774
654
|
}
|
|
655
|
+
const preflightSignal = ptree.combineSignals(signal, timeout * 1000);
|
|
775
656
|
|
|
776
657
|
// Handle internal protocol URLs (e.g., pi-internal://) - return empty
|
|
777
658
|
if (url.startsWith("pi-internal://")) {
|
|
@@ -789,7 +670,8 @@ async function renderUrl(
|
|
|
789
670
|
|
|
790
671
|
// Step 0: Normalize URL (ensure scheme for special handlers)
|
|
791
672
|
url = normalizeUrl(url);
|
|
792
|
-
const publicUrl = await validatePublicHttpUrl(url);
|
|
673
|
+
const publicUrl = await validatePublicHttpUrl(url, { signal: preflightSignal });
|
|
674
|
+
if (signal?.aborted) throw new ToolAbortError();
|
|
793
675
|
if (!publicUrl.ok) {
|
|
794
676
|
notes.push(`Blocked URL fetch: target URL is not public HTTP(S): ${publicUrl.reason}`);
|
|
795
677
|
return {
|
|
@@ -1138,10 +1020,10 @@ async function renderUrl(
|
|
|
1138
1020
|
throw new ToolAbortError();
|
|
1139
1021
|
}
|
|
1140
1022
|
|
|
1141
|
-
// 5E: Render
|
|
1142
|
-
const htmlResult = await renderHtmlToText(
|
|
1023
|
+
// 5E: Render only the bytes already fetched above.
|
|
1024
|
+
const htmlResult = await renderHtmlToText(rawContent, signal);
|
|
1143
1025
|
if (!htmlResult.ok) {
|
|
1144
|
-
notes.push("
|
|
1026
|
+
notes.push("native HTML rendering failed");
|
|
1145
1027
|
const insane = await tryInsaneFallback({ url, finalUrl, timeout, raw, settings, signal, fetchedAt, notes });
|
|
1146
1028
|
if (insane) return insane;
|
|
1147
1029
|
const output = finalizeOutput(rawContent);
|
|
@@ -1264,7 +1146,12 @@ interface ReadUrlCacheEntry {
|
|
|
1264
1146
|
artifactId?: string;
|
|
1265
1147
|
details: ReadUrlToolDetails;
|
|
1266
1148
|
image?: FetchImagePayload;
|
|
1149
|
+
/** Complete URL output, including its preamble and body. */
|
|
1267
1150
|
output: string;
|
|
1151
|
+
/** UTF-16 code-unit offset of the preamble in `output`. */
|
|
1152
|
+
preambleChars: number;
|
|
1153
|
+
/** Offset of the preamble after `wrapUntrustedContent(output)` is persisted. */
|
|
1154
|
+
wrappedPreambleChars?: number;
|
|
1268
1155
|
}
|
|
1269
1156
|
|
|
1270
1157
|
const readUrlCache = new Map<string, ReadUrlCacheEntry>();
|
|
@@ -1296,7 +1183,13 @@ async function materializeReadUrlCacheEntry(
|
|
|
1296
1183
|
if (entry.artifactId) {
|
|
1297
1184
|
const artifactOutput = await readArtifactOutput(session, entry.artifactId);
|
|
1298
1185
|
if (artifactOutput !== null) {
|
|
1299
|
-
|
|
1186
|
+
// Artifacts retain their trust-boundary wrapper. Keep the raw preamble
|
|
1187
|
+
// coordinate alongside the escaped coordinate for live/rehydrated parity.
|
|
1188
|
+
return {
|
|
1189
|
+
...entry,
|
|
1190
|
+
output: artifactOutput,
|
|
1191
|
+
...(entry.wrappedPreambleChars !== undefined ? { wrappedPreambleChars: entry.wrappedPreambleChars } : {}),
|
|
1192
|
+
};
|
|
1300
1193
|
}
|
|
1301
1194
|
}
|
|
1302
1195
|
return null;
|
|
@@ -1336,8 +1229,8 @@ async function buildReadUrlCacheEntry(
|
|
|
1336
1229
|
|
|
1337
1230
|
const storage = session.settings.getStorage();
|
|
1338
1231
|
const result = await renderUrl(url, effectiveTimeout, raw, session.settings, signal, storage);
|
|
1339
|
-
const
|
|
1340
|
-
const artifactId = options?.ensureArtifact ? await persistReadUrlArtifact(session, output) : undefined;
|
|
1232
|
+
const built = buildUrlReadOutput(result, result.content);
|
|
1233
|
+
const artifactId = options?.ensureArtifact ? await persistReadUrlArtifact(session, built.output) : undefined;
|
|
1341
1234
|
|
|
1342
1235
|
return {
|
|
1343
1236
|
artifactId,
|
|
@@ -1351,7 +1244,9 @@ async function buildReadUrlCacheEntry(
|
|
|
1351
1244
|
notes: result.notes,
|
|
1352
1245
|
},
|
|
1353
1246
|
image: result.image,
|
|
1354
|
-
output,
|
|
1247
|
+
output: built.output,
|
|
1248
|
+
preambleChars: built.preambleChars,
|
|
1249
|
+
wrappedPreambleChars: built.wrappedPreambleChars,
|
|
1355
1250
|
};
|
|
1356
1251
|
}
|
|
1357
1252
|
|
|
@@ -1381,60 +1276,138 @@ export async function loadReadUrlCacheEntry(
|
|
|
1381
1276
|
|
|
1382
1277
|
const UNTRUSTED_CONTENT_OPEN = "<untrusted-content>";
|
|
1383
1278
|
const UNTRUSTED_CONTENT_CLOSE = "</untrusted-content>";
|
|
1279
|
+
export const WRAP_PREFIX_CHARS = `${UNTRUSTED_CONTENT_OPEN}\n`.length;
|
|
1280
|
+
const WRAP_SUFFIX = `\n${UNTRUSTED_CONTENT_CLOSE}`;
|
|
1281
|
+
|
|
1282
|
+
export function escapeUntrustedContent(content: string): string {
|
|
1283
|
+
return content.replace(/<\/untrusted-content>/gi, "</untrusted-content>");
|
|
1284
|
+
}
|
|
1384
1285
|
|
|
1385
1286
|
export function wrapUntrustedContent(content: string): string {
|
|
1386
|
-
return `${UNTRUSTED_CONTENT_OPEN}\n${
|
|
1287
|
+
return `${UNTRUSTED_CONTENT_OPEN}\n${escapeUntrustedContent(content)}${WRAP_SUFFIX}`;
|
|
1387
1288
|
}
|
|
1388
1289
|
|
|
1389
|
-
function
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1290
|
+
function isWrappedReadUrlOutput(output: string): boolean {
|
|
1291
|
+
return output.startsWith(`${UNTRUSTED_CONTENT_OPEN}\n`) && output.endsWith(WRAP_SUFFIX);
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
/**
|
|
1295
|
+
* Remove only the outer URL-output wrapper before line pagination. The content
|
|
1296
|
+
* remains escaped exactly as persisted; it is deliberately never unescaped.
|
|
1297
|
+
*/
|
|
1298
|
+
export function prepareReadUrlSelectorInput(
|
|
1299
|
+
output: string,
|
|
1300
|
+
preambleChars: number,
|
|
1301
|
+
wrappedPreambleChars?: number,
|
|
1302
|
+
): { text: string; preambleChars: number } {
|
|
1303
|
+
if (!isWrappedReadUrlOutput(output)) return { text: output, preambleChars };
|
|
1304
|
+
const bodyEnd = output.length - WRAP_SUFFIX.length;
|
|
1305
|
+
return {
|
|
1306
|
+
text: output.slice(WRAP_PREFIX_CHARS, Math.max(WRAP_PREFIX_CHARS, bodyEnd)),
|
|
1307
|
+
preambleChars: Math.max(0, (wrappedPreambleChars ?? preambleChars) - WRAP_PREFIX_CHARS),
|
|
1308
|
+
};
|
|
1309
|
+
}
|
|
1310
|
+
interface BuiltUrlReadOutput {
|
|
1311
|
+
output: string;
|
|
1312
|
+
preambleChars: number;
|
|
1313
|
+
wrappedPreambleChars: number;
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
function buildReadUrlPreamble(
|
|
1317
|
+
result: Pick<FetchRenderResult, "finalUrl" | "contentType" | "method" | "notes">,
|
|
1318
|
+
): string {
|
|
1319
|
+
let preamble = "";
|
|
1320
|
+
preamble += `URL: ${result.finalUrl}\n`;
|
|
1321
|
+
preamble += `Content-Type: ${result.contentType}\n`;
|
|
1322
|
+
preamble += `Method: ${result.method}\n`;
|
|
1394
1323
|
if (result.notes.length > 0) {
|
|
1395
|
-
|
|
1324
|
+
preamble += `Notes: ${result.notes.join("; ")}\n`;
|
|
1396
1325
|
}
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1326
|
+
preamble += "\n---\n\n";
|
|
1327
|
+
return preamble;
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
function buildUrlReadOutput(result: FetchRenderResult, content: string): BuiltUrlReadOutput {
|
|
1331
|
+
const preamble = buildReadUrlPreamble(result);
|
|
1332
|
+
const preambleChars = preamble.length;
|
|
1333
|
+
const output = `${preamble}${content}`;
|
|
1334
|
+
return {
|
|
1335
|
+
output,
|
|
1336
|
+
preambleChars,
|
|
1337
|
+
wrappedPreambleChars: WRAP_PREFIX_CHARS + escapeUntrustedContent(preamble).length,
|
|
1338
|
+
};
|
|
1400
1339
|
}
|
|
1401
1340
|
|
|
1402
1341
|
export async function executeReadUrl(
|
|
1403
1342
|
session: ToolSession,
|
|
1404
1343
|
params: { path: string; raw?: boolean },
|
|
1405
1344
|
signal?: AbortSignal,
|
|
1345
|
+
direction: TruncationDirection = "head",
|
|
1406
1346
|
): Promise<AgentToolResult<ReadUrlToolDetails>> {
|
|
1407
1347
|
let cacheEntry = await loadReadUrlCacheEntry(session, params, signal, { preferCached: true });
|
|
1408
|
-
|
|
1348
|
+
// `head` intentionally retains the historical whole-output accounting so the
|
|
1349
|
+
// existing URL golden remains byte-identical. Non-head directions account for
|
|
1350
|
+
// and truncate only the body; preamble bytes/chars are never part of that cap.
|
|
1351
|
+
const effectiveDirection =
|
|
1352
|
+
direction !== "head" && cacheEntry.wrappedPreambleChars === undefined ? "head" : direction;
|
|
1353
|
+
const isWrappedOutput = isWrappedReadUrlOutput(cacheEntry.output);
|
|
1354
|
+
const preambleChars = isWrappedOutput
|
|
1355
|
+
? (cacheEntry.wrappedPreambleChars ??
|
|
1356
|
+
WRAP_PREFIX_CHARS + escapeUntrustedContent(buildReadUrlPreamble(cacheEntry.details)).length)
|
|
1357
|
+
: cacheEntry.preambleChars;
|
|
1358
|
+
const wrappedPrefix = isWrappedOutput ? WRAP_PREFIX_CHARS : 0;
|
|
1359
|
+
const wrappedSuffix = isWrappedOutput ? `\n${UNTRUSTED_CONTENT_CLOSE}` : "";
|
|
1360
|
+
const bodyEnd = cacheEntry.output.length - wrappedSuffix.length;
|
|
1361
|
+
const unwrappedOutput = isWrappedOutput
|
|
1362
|
+
? cacheEntry.output.slice(wrappedPrefix, Math.max(wrappedPrefix, bodyEnd))
|
|
1363
|
+
: cacheEntry.output;
|
|
1364
|
+
const truncationInput =
|
|
1365
|
+
effectiveDirection === "head"
|
|
1366
|
+
? unwrappedOutput
|
|
1367
|
+
: cacheEntry.output.slice(preambleChars, Math.max(preambleChars, bodyEnd));
|
|
1368
|
+
const truncation = truncateContent(truncationInput, {
|
|
1409
1369
|
maxBytes: DEFAULT_MAX_BYTES,
|
|
1410
1370
|
maxLines: FETCH_DEFAULT_MAX_LINES,
|
|
1371
|
+
direction: effectiveDirection,
|
|
1411
1372
|
});
|
|
1412
1373
|
const needsArtifact = truncation.truncated;
|
|
1413
1374
|
if (needsArtifact && !cacheEntry.artifactId) {
|
|
1414
1375
|
cacheEntry = await ensureReadUrlCacheArtifact(session, cacheEntry);
|
|
1415
1376
|
cacheReadUrlEntry(session, params.path, params.raw ?? false, cacheEntry);
|
|
1416
1377
|
}
|
|
1417
|
-
const output =
|
|
1378
|
+
const output =
|
|
1379
|
+
effectiveDirection !== "head"
|
|
1380
|
+
? needsArtifact
|
|
1381
|
+
? `${cacheEntry.output.slice(0, preambleChars)}${truncation.content}${wrappedSuffix}`
|
|
1382
|
+
: cacheEntry.output
|
|
1383
|
+
: truncation.content;
|
|
1418
1384
|
const details: ReadUrlToolDetails = {
|
|
1419
1385
|
...cacheEntry.details,
|
|
1420
1386
|
truncated: Boolean(cacheEntry.details.truncated || needsArtifact),
|
|
1421
1387
|
};
|
|
1422
1388
|
|
|
1423
|
-
const contentBlocks: Array<TextContent | ImageContent> = [
|
|
1389
|
+
const contentBlocks: Array<TextContent | ImageContent> = [
|
|
1390
|
+
{ type: "text", text: isWrappedOutput && effectiveDirection !== "head" ? output : wrapUntrustedContent(output) },
|
|
1391
|
+
];
|
|
1424
1392
|
if (cacheEntry.image) {
|
|
1425
1393
|
contentBlocks.push({ type: "image", data: cacheEntry.image.data, mimeType: cacheEntry.image.mimeType });
|
|
1426
1394
|
}
|
|
1427
1395
|
|
|
1428
1396
|
const resultBuilder = toolResult(details).content(contentBlocks).sourceUrl(details.finalUrl);
|
|
1429
1397
|
if (needsArtifact) {
|
|
1430
|
-
resultBuilder.truncation(truncation, {
|
|
1398
|
+
resultBuilder.truncation(truncation, {
|
|
1399
|
+
direction: effectiveDirection === "both" ? "middle" : effectiveDirection === "last" ? "tail" : "head",
|
|
1400
|
+
artifactId: cacheEntry.artifactId,
|
|
1401
|
+
...(effectiveDirection !== "head" ? { maxBytes: DEFAULT_MAX_BYTES } : {}),
|
|
1402
|
+
});
|
|
1431
1403
|
} else if (cacheEntry.details.truncated) {
|
|
1432
|
-
const
|
|
1433
|
-
const
|
|
1404
|
+
const reportedText = effectiveDirection === "head" ? cacheEntry.output : truncationInput;
|
|
1405
|
+
const outputLines = reportedText.split("\n").length;
|
|
1406
|
+
const outputBytes = Buffer.byteLength(reportedText, "utf-8");
|
|
1434
1407
|
const totalBytes = Math.max(outputBytes + 1, MAX_OUTPUT_CHARS + 1);
|
|
1435
1408
|
const totalLines = outputLines + 1;
|
|
1436
|
-
resultBuilder.truncationFromText(
|
|
1437
|
-
direction: "tail",
|
|
1409
|
+
resultBuilder.truncationFromText(reportedText, {
|
|
1410
|
+
direction: effectiveDirection === "both" ? "middle" : effectiveDirection === "last" ? "tail" : "head",
|
|
1438
1411
|
totalLines,
|
|
1439
1412
|
totalBytes,
|
|
1440
1413
|
maxBytes: MAX_OUTPUT_CHARS,
|