@sayknow-cli/coding-agent 0.4.7 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +97 -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/output-meta.ts
CHANGED
|
@@ -16,7 +16,15 @@ import { getDefault, type Settings } from "../config/settings";
|
|
|
16
16
|
import { formatGroupedDiagnosticMessages } from "../lsp/utils";
|
|
17
17
|
import type { Theme } from "../modes/theme/theme";
|
|
18
18
|
import { sessionArtifactCapability } from "../session/session-manager";
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
formatMiddleElisionMarker,
|
|
21
|
+
type OutputSummary,
|
|
22
|
+
type ReadWindow,
|
|
23
|
+
type TruncationResult,
|
|
24
|
+
truncateMiddle,
|
|
25
|
+
truncateTail,
|
|
26
|
+
} from "../session/streaming-output";
|
|
27
|
+
|
|
20
28
|
import { formatBytes, wrapBrackets } from "./render-utils";
|
|
21
29
|
import { renderError } from "./tool-errors";
|
|
22
30
|
|
|
@@ -25,6 +33,9 @@ import { renderError } from "./tool-errors";
|
|
|
25
33
|
*/
|
|
26
34
|
export interface TruncationMeta {
|
|
27
35
|
direction: "head" | "tail" | "middle";
|
|
36
|
+
/** Coordinate basis for shown/head/tail ranges. Omitted means file coordinates; "window" is the selected-range coordinate system. */
|
|
37
|
+
rangeBase?: "file" | "window";
|
|
38
|
+
noticeOwner?: "body";
|
|
28
39
|
truncatedBy: "lines" | "bytes" | "middle";
|
|
29
40
|
totalLines: number;
|
|
30
41
|
totalBytes: number;
|
|
@@ -36,6 +47,8 @@ export interface TruncationMeta {
|
|
|
36
47
|
/** Head/tail line ranges shown when direction === "middle". */
|
|
37
48
|
headRange?: { start: number; end: number };
|
|
38
49
|
tailRange?: { start: number; end: number };
|
|
50
|
+
/** Partial source-line preview retained by a directional window. */
|
|
51
|
+
partialLine?: { line: number; bytes: number; sourceBytes: number };
|
|
39
52
|
/** Bytes elided from the middle. */
|
|
40
53
|
elidedBytes?: number;
|
|
41
54
|
/** Lines elided from the middle. */
|
|
@@ -91,12 +104,15 @@ export interface TruncationOptions {
|
|
|
91
104
|
startLine?: number;
|
|
92
105
|
totalFileLines?: number;
|
|
93
106
|
artifactId?: string;
|
|
107
|
+
maxBytes?: number;
|
|
108
|
+
noticeOwner?: "body";
|
|
94
109
|
}
|
|
95
110
|
|
|
96
111
|
export interface TruncationSummaryOptions {
|
|
97
112
|
direction: "head" | "tail" | "middle";
|
|
98
113
|
startLine?: number;
|
|
99
114
|
totalFileLines?: number;
|
|
115
|
+
noticeOwner?: "body";
|
|
100
116
|
}
|
|
101
117
|
|
|
102
118
|
export interface TruncationTextOptions {
|
|
@@ -105,6 +121,7 @@ export interface TruncationTextOptions {
|
|
|
105
121
|
totalBytes?: number;
|
|
106
122
|
maxBytes?: number;
|
|
107
123
|
artifactId?: string;
|
|
124
|
+
noticeOwner?: "body";
|
|
108
125
|
}
|
|
109
126
|
|
|
110
127
|
/**
|
|
@@ -126,7 +143,7 @@ export class OutputMetaBuilder {
|
|
|
126
143
|
truncation(result: TruncationResult, options: TruncationOptions): this {
|
|
127
144
|
if (!result.truncated) return this;
|
|
128
145
|
|
|
129
|
-
const { direction, startLine = 1, totalFileLines, artifactId } = options;
|
|
146
|
+
const { direction, startLine = 1, totalFileLines, artifactId, noticeOwner, maxBytes } = options;
|
|
130
147
|
const outputLines = result.outputLines ?? result.totalLines;
|
|
131
148
|
const outputBytes = result.outputBytes ?? result.totalBytes;
|
|
132
149
|
const isMiddle = direction === "middle" || result.truncatedBy === "middle";
|
|
@@ -137,6 +154,7 @@ export class OutputMetaBuilder {
|
|
|
137
154
|
: "bytes";
|
|
138
155
|
|
|
139
156
|
const effectiveTotalLines = totalFileLines ?? result.totalLines;
|
|
157
|
+
const owner = noticeOwner !== undefined ? { noticeOwner } : {};
|
|
140
158
|
|
|
141
159
|
if (isMiddle) {
|
|
142
160
|
const elidedLines = result.elidedLines ?? Math.max(0, effectiveTotalLines - outputLines);
|
|
@@ -150,10 +168,12 @@ export class OutputMetaBuilder {
|
|
|
150
168
|
this.#meta.truncation = {
|
|
151
169
|
direction: "middle",
|
|
152
170
|
truncatedBy: "middle",
|
|
171
|
+
...owner,
|
|
153
172
|
totalLines: effectiveTotalLines,
|
|
154
173
|
totalBytes: result.totalBytes,
|
|
155
174
|
outputLines,
|
|
156
175
|
outputBytes,
|
|
176
|
+
...(maxBytes !== undefined ? { maxBytes } : {}),
|
|
157
177
|
headRange: headLines > 0 ? { start: 1, end: headLines } : undefined,
|
|
158
178
|
tailRange:
|
|
159
179
|
tailLines > 0 ? { start: effectiveTotalLines - tailLines + 1, end: effectiveTotalLines } : undefined,
|
|
@@ -178,10 +198,12 @@ export class OutputMetaBuilder {
|
|
|
178
198
|
this.#meta.truncation = {
|
|
179
199
|
direction,
|
|
180
200
|
truncatedBy,
|
|
201
|
+
...owner,
|
|
181
202
|
totalLines: effectiveTotalLines,
|
|
182
203
|
totalBytes: result.totalBytes,
|
|
183
204
|
outputLines,
|
|
184
205
|
outputBytes,
|
|
206
|
+
...(maxBytes !== undefined ? { maxBytes } : {}),
|
|
185
207
|
shownRange: { start: shownStart, end: shownEnd },
|
|
186
208
|
artifactId,
|
|
187
209
|
nextOffset: direction === "head" ? shownEnd + 1 : undefined,
|
|
@@ -190,12 +212,124 @@ export class OutputMetaBuilder {
|
|
|
190
212
|
return this;
|
|
191
213
|
}
|
|
192
214
|
|
|
215
|
+
/** Add metadata from the actual head/tail windows retained by middle truncation. */
|
|
216
|
+
truncationWindows(
|
|
217
|
+
windows: ReadWindow,
|
|
218
|
+
options: {
|
|
219
|
+
artifactId?: string;
|
|
220
|
+
noticeOwner?: "body";
|
|
221
|
+
maxBytes?: number;
|
|
222
|
+
rangeBase?: "file" | "window";
|
|
223
|
+
} = {},
|
|
224
|
+
): this {
|
|
225
|
+
if (windows.kind === "full") return this;
|
|
226
|
+
|
|
227
|
+
const { artifactId, noticeOwner, rangeBase } = options;
|
|
228
|
+
const maxBytes = options.maxBytes ?? (windows as ReadWindow & { maxBytes?: number }).maxBytes;
|
|
229
|
+
const outputLinesOverride = (windows as ReadWindow & { outputLinesOverride?: number }).outputLinesOverride;
|
|
230
|
+
const outputBytesOverride = (windows as ReadWindow & { outputBytesOverride?: number }).outputBytesOverride;
|
|
231
|
+
const owner = noticeOwner !== undefined ? { noticeOwner } : {};
|
|
232
|
+
const rangeBaseMeta = rangeBase !== undefined ? { rangeBase } : {};
|
|
233
|
+
const hiddenReason = (windows as ReadWindow & { truncatedBy?: "lines" | "bytes" | "middle" }).truncatedBy;
|
|
234
|
+
const fallbackTruncatedBy: "lines" | "bytes" = hiddenReason === "bytes" ? "bytes" : "lines";
|
|
235
|
+
const partialTail = windows.tail?.kind === "partial-line" ? windows.tail : undefined;
|
|
236
|
+
if (partialTail) {
|
|
237
|
+
const headBytes = windows.head?.bytes ?? 0;
|
|
238
|
+
const separatorBytes = windows.head ? 1 : 0;
|
|
239
|
+
const markerBytes =
|
|
240
|
+
windows.elidedLines > 0
|
|
241
|
+
? Buffer.byteLength(formatMiddleElisionMarker(windows.elidedLines, windows.elidedBytes), "utf-8") + 1
|
|
242
|
+
: 0;
|
|
243
|
+
this.#meta.truncation = {
|
|
244
|
+
direction: windows.kind === "tail-only" ? "tail" : "middle",
|
|
245
|
+
truncatedBy: "bytes",
|
|
246
|
+
...owner,
|
|
247
|
+
...rangeBaseMeta,
|
|
248
|
+
totalLines: windows.totalLines,
|
|
249
|
+
totalBytes: windows.totalBytes,
|
|
250
|
+
outputLines:
|
|
251
|
+
outputLinesOverride ??
|
|
252
|
+
(windows.head
|
|
253
|
+
? windows.head.lines + partialTail.lines + (windows.elidedLines > 0 ? 1 : 0)
|
|
254
|
+
: partialTail.lines),
|
|
255
|
+
outputBytes: outputBytesOverride ?? headBytes + partialTail.bytes + separatorBytes + markerBytes,
|
|
256
|
+
...(maxBytes !== undefined ? { maxBytes } : {}),
|
|
257
|
+
partialLine: {
|
|
258
|
+
line: partialTail.origin.startLine,
|
|
259
|
+
bytes: partialTail.bytes,
|
|
260
|
+
sourceBytes: partialTail.sourceLineBytes,
|
|
261
|
+
},
|
|
262
|
+
artifactId,
|
|
263
|
+
};
|
|
264
|
+
return this;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (windows.kind === "head-only" && windows.head) {
|
|
268
|
+
const { head } = windows;
|
|
269
|
+
this.#meta.truncation = {
|
|
270
|
+
direction: "head",
|
|
271
|
+
truncatedBy: fallbackTruncatedBy,
|
|
272
|
+
...owner,
|
|
273
|
+
...rangeBaseMeta,
|
|
274
|
+
totalLines: windows.totalLines,
|
|
275
|
+
totalBytes: windows.totalBytes,
|
|
276
|
+
outputLines: outputLinesOverride ?? head.lines,
|
|
277
|
+
outputBytes: outputBytesOverride ?? head.bytes,
|
|
278
|
+
...(maxBytes !== undefined ? { maxBytes } : {}),
|
|
279
|
+
shownRange: { start: head.origin.startLine, end: head.origin.endLine },
|
|
280
|
+
artifactId,
|
|
281
|
+
nextOffset: head.origin.endLine + 1,
|
|
282
|
+
};
|
|
283
|
+
return this;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (windows.kind === "tail-only" && windows.tail) {
|
|
287
|
+
const { tail } = windows;
|
|
288
|
+
this.#meta.truncation = {
|
|
289
|
+
direction: "tail",
|
|
290
|
+
truncatedBy: fallbackTruncatedBy,
|
|
291
|
+
...owner,
|
|
292
|
+
...rangeBaseMeta,
|
|
293
|
+
totalLines: windows.totalLines,
|
|
294
|
+
totalBytes: windows.totalBytes,
|
|
295
|
+
outputLines: outputLinesOverride ?? tail.lines,
|
|
296
|
+
outputBytes: outputBytesOverride ?? tail.bytes,
|
|
297
|
+
...(maxBytes !== undefined ? { maxBytes } : {}),
|
|
298
|
+
shownRange: { start: tail.origin.startLine, end: tail.origin.endLine },
|
|
299
|
+
artifactId,
|
|
300
|
+
};
|
|
301
|
+
return this;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const { head, tail } = windows;
|
|
305
|
+
if (!head || !tail) return this;
|
|
306
|
+
const marker = formatMiddleElisionMarker(windows.elidedLines, windows.elidedBytes);
|
|
307
|
+
this.#meta.truncation = {
|
|
308
|
+
direction: "middle",
|
|
309
|
+
truncatedBy: "middle",
|
|
310
|
+
...owner,
|
|
311
|
+
...rangeBaseMeta,
|
|
312
|
+
totalLines: windows.totalLines,
|
|
313
|
+
totalBytes: windows.totalBytes,
|
|
314
|
+
outputLines: head.lines + tail.lines + 1,
|
|
315
|
+
outputBytes: head.bytes + tail.bytes + Buffer.byteLength(marker, "utf-8") + 2,
|
|
316
|
+
...(maxBytes !== undefined ? { maxBytes } : {}),
|
|
317
|
+
headRange: { start: head.origin.startLine, end: head.origin.endLine },
|
|
318
|
+
tailRange: { start: tail.origin.startLine, end: tail.origin.endLine },
|
|
319
|
+
elidedLines: windows.elidedLines,
|
|
320
|
+
elidedBytes: windows.elidedBytes,
|
|
321
|
+
artifactId,
|
|
322
|
+
};
|
|
323
|
+
return this;
|
|
324
|
+
}
|
|
325
|
+
|
|
193
326
|
/** Add truncation info from OutputSummary. No-op if not truncated. */
|
|
194
327
|
truncationFromSummary(summary: OutputSummary, options: TruncationSummaryOptions): this {
|
|
195
328
|
if (!summary.truncated) return this;
|
|
196
329
|
|
|
197
|
-
const { direction, startLine = 1, totalFileLines } = options;
|
|
330
|
+
const { direction, startLine = 1, totalFileLines, noticeOwner } = options;
|
|
198
331
|
const totalLines = totalFileLines ?? summary.totalLines;
|
|
332
|
+
const owner = noticeOwner !== undefined ? { noticeOwner } : {};
|
|
199
333
|
|
|
200
334
|
// Middle elision: the sink retained head + tail with an elision marker.
|
|
201
335
|
if (summary.elidedBytes != null && summary.elidedBytes > 0) {
|
|
@@ -206,6 +340,7 @@ export class OutputMetaBuilder {
|
|
|
206
340
|
this.#meta.truncation = {
|
|
207
341
|
direction: "middle",
|
|
208
342
|
truncatedBy: "middle",
|
|
343
|
+
...owner,
|
|
209
344
|
totalLines,
|
|
210
345
|
totalBytes: summary.totalBytes,
|
|
211
346
|
outputLines: summary.outputLines,
|
|
@@ -240,6 +375,7 @@ export class OutputMetaBuilder {
|
|
|
240
375
|
this.#meta.truncation = {
|
|
241
376
|
direction,
|
|
242
377
|
truncatedBy,
|
|
378
|
+
...owner,
|
|
243
379
|
totalLines,
|
|
244
380
|
totalBytes: summary.totalBytes,
|
|
245
381
|
outputLines: summary.outputLines,
|
|
@@ -285,6 +421,7 @@ export class OutputMetaBuilder {
|
|
|
285
421
|
this.#meta.truncation = {
|
|
286
422
|
direction: options.direction,
|
|
287
423
|
truncatedBy,
|
|
424
|
+
...(options.noticeOwner !== undefined ? { noticeOwner: options.noticeOwner } : {}),
|
|
288
425
|
totalLines,
|
|
289
426
|
totalBytes,
|
|
290
427
|
outputLines,
|
|
@@ -387,7 +524,25 @@ export function formatFullOutputReference(artifactId: string): string {
|
|
|
387
524
|
return `Read artifact://${artifactId} for full output`;
|
|
388
525
|
}
|
|
389
526
|
|
|
527
|
+
function formatTruncationRangeTotal(truncation: TruncationMeta): string {
|
|
528
|
+
return truncation.rangeBase === "window"
|
|
529
|
+
? `the selected ${truncation.totalLines}-line range`
|
|
530
|
+
: `${truncation.totalLines}`;
|
|
531
|
+
}
|
|
532
|
+
|
|
390
533
|
export function formatTruncationMetaNotice(truncation: TruncationMeta): string {
|
|
534
|
+
const rangeTotal = formatTruncationRangeTotal(truncation);
|
|
535
|
+
if (truncation.partialLine) {
|
|
536
|
+
let notice = `Showing last ${formatBytes(truncation.partialLine.bytes)} of line ${truncation.partialLine.line} of ${rangeTotal}`;
|
|
537
|
+
if (truncation.partialLine.sourceBytes > truncation.partialLine.bytes) {
|
|
538
|
+
notice += ` (line is ${formatBytes(truncation.partialLine.sourceBytes)})`;
|
|
539
|
+
}
|
|
540
|
+
if (truncation.artifactId != null) {
|
|
541
|
+
notice += `. ${formatFullOutputReference(truncation.artifactId)}`;
|
|
542
|
+
}
|
|
543
|
+
return notice;
|
|
544
|
+
}
|
|
545
|
+
|
|
391
546
|
let notice: string;
|
|
392
547
|
|
|
393
548
|
if (truncation.direction === "middle") {
|
|
@@ -399,9 +554,9 @@ export function formatTruncationMetaNotice(truncation: TruncationMeta): string {
|
|
|
399
554
|
const headPart = head ? `lines ${head.start}-${head.end}` : "";
|
|
400
555
|
const tailPart = tail ? `${tail.start}-${tail.end}` : "";
|
|
401
556
|
if (headPart && tailPart) {
|
|
402
|
-
notice = `Showing ${headPart} and ${tailPart} of ${
|
|
557
|
+
notice = `Showing ${headPart} and ${tailPart} of ${rangeTotal}; ${elidedLines.toLocaleString()} middle line${elidedLines === 1 ? "" : "s"} (${formatBytes(elidedBytes)}) elided`;
|
|
403
558
|
} else {
|
|
404
|
-
notice = `Showing ${truncation.outputLines} of ${
|
|
559
|
+
notice = `Showing ${truncation.outputLines} of ${rangeTotal}${truncation.rangeBase === "window" ? "" : " lines"}; middle elided`;
|
|
405
560
|
}
|
|
406
561
|
if (truncation.artifactId != null) {
|
|
407
562
|
notice += `. ${formatFullOutputReference(truncation.artifactId)}`;
|
|
@@ -411,9 +566,9 @@ export function formatTruncationMetaNotice(truncation: TruncationMeta): string {
|
|
|
411
566
|
|
|
412
567
|
const range = truncation.shownRange;
|
|
413
568
|
if (range && range.end >= range.start) {
|
|
414
|
-
notice = `Showing lines ${range.start}-${range.end} of ${
|
|
569
|
+
notice = `Showing lines ${range.start}-${range.end} of ${rangeTotal}`;
|
|
415
570
|
} else {
|
|
416
|
-
notice = `Showing ${truncation.outputLines} of ${truncation.
|
|
571
|
+
notice = `Showing ${truncation.outputLines} of ${rangeTotal}${truncation.rangeBase === "window" ? "" : " lines"}`;
|
|
417
572
|
}
|
|
418
573
|
|
|
419
574
|
if (truncation.truncatedBy === "bytes") {
|
|
@@ -450,7 +605,7 @@ export function formatOutputNotice(meta: OutputMeta | undefined): string {
|
|
|
450
605
|
const parts: string[] = [];
|
|
451
606
|
|
|
452
607
|
// Truncation notice
|
|
453
|
-
if (meta.truncation) {
|
|
608
|
+
if (meta.truncation && meta.truncation.noticeOwner !== "body") {
|
|
454
609
|
parts.push(formatTruncationMetaNotice(meta.truncation));
|
|
455
610
|
}
|
|
456
611
|
|
|
@@ -710,6 +865,17 @@ async function spillLargeResultToArtifact(
|
|
|
710
865
|
return { ...result, content: newContent, details: newDetails };
|
|
711
866
|
}
|
|
712
867
|
|
|
868
|
+
const BODY_TRUNCATION_FOOTER_KEY = "__bodyTruncationFooter";
|
|
869
|
+
|
|
870
|
+
function stripBodyOwnedTruncationFooter(text: string, details: unknown): string {
|
|
871
|
+
const footer = (details as { [BODY_TRUNCATION_FOOTER_KEY]?: unknown } | undefined)?.[BODY_TRUNCATION_FOOTER_KEY];
|
|
872
|
+
if (typeof footer !== "string" || footer.length === 0) return text;
|
|
873
|
+
const trimmedText = text.trimEnd();
|
|
874
|
+
const trimmedFooter = footer.trim();
|
|
875
|
+
if (!trimmedText.endsWith(trimmedFooter)) return text;
|
|
876
|
+
return trimmedText.slice(0, -trimmedFooter.length).trimEnd();
|
|
877
|
+
}
|
|
878
|
+
|
|
713
879
|
/**
|
|
714
880
|
* Absolute inline-size backstop enforced after {@link spillLargeResultToArtifact}.
|
|
715
881
|
*
|
|
@@ -738,7 +904,8 @@ async function enforceInlineResultBackstop(
|
|
|
738
904
|
}
|
|
739
905
|
if (textParts.length === 0) return result;
|
|
740
906
|
|
|
741
|
-
const
|
|
907
|
+
const renderedText = textParts.length === 1 ? textParts[0] : textParts.join("\n");
|
|
908
|
+
const fullText = stripBodyOwnedTruncationFooter(renderedText, result.details);
|
|
742
909
|
const totalBytes = Buffer.byteLength(fullText, "utf-8");
|
|
743
910
|
if (totalBytes <= maxInlineBytes) return result;
|
|
744
911
|
|
package/src/tools/path-utils.ts
CHANGED
|
@@ -33,7 +33,11 @@ function normalizeUnicodeSpaces(str: string): string {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
function tryMacOSScreenshotPath(filePath: string): string {
|
|
36
|
-
|
|
36
|
+
// macOS writes a narrow no-break space before AM/PM, but the model normalizes it
|
|
37
|
+
// to a plain space. The original name is not always `…PM.png`: attachment paths
|
|
38
|
+
// append a timestamp (`…PM-1785075812409.png`), so match any non-alphanumeric
|
|
39
|
+
// separator or end of segment rather than a literal dot.
|
|
40
|
+
return filePath.replace(/ (AM|PM)(?=[^A-Za-z0-9/]|$)/g, `${NARROW_NO_BREAK_SPACE}$1`);
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
function tryNFDVariant(filePath: string): string {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Settings } from "../config/settings";
|
|
2
|
+
import type { TruncationDirection } from "../session/streaming-output";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Read execution routes that have distinct truncation-default contracts.
|
|
6
|
+
* Routes that share the same default are grouped only when their truncation
|
|
7
|
+
* policy is identical; selection and rendering remain owned by read.ts.
|
|
8
|
+
*/
|
|
9
|
+
export type ReadRoute =
|
|
10
|
+
| "local-bare-stream"
|
|
11
|
+
| "local-bare-acp"
|
|
12
|
+
| "archive-member-bare"
|
|
13
|
+
| "local-range"
|
|
14
|
+
| "local-multi-range"
|
|
15
|
+
| "local-raw"
|
|
16
|
+
| "local-summary"
|
|
17
|
+
| "url-reader"
|
|
18
|
+
| "url-cache-page"
|
|
19
|
+
| "dir-local"
|
|
20
|
+
| "dir-archive"
|
|
21
|
+
| "sqlite-list"
|
|
22
|
+
| "sqlite-rows"
|
|
23
|
+
| "converted";
|
|
24
|
+
|
|
25
|
+
/** Resolve the configured default for a route; explicit parameters bypass it. */
|
|
26
|
+
export function pathDefault(route: ReadRoute, settings: Settings): TruncationDirection {
|
|
27
|
+
switch (route) {
|
|
28
|
+
case "local-bare-stream":
|
|
29
|
+
case "local-bare-acp":
|
|
30
|
+
case "archive-member-bare":
|
|
31
|
+
return settings.get("read.truncation") ?? "last";
|
|
32
|
+
default:
|
|
33
|
+
return "head";
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Resolve the effective caller-facing direction with explicit precedence. */
|
|
38
|
+
export function resolveEffectiveDirection(
|
|
39
|
+
explicitParam: TruncationDirection | undefined,
|
|
40
|
+
route: ReadRoute,
|
|
41
|
+
settings: Settings,
|
|
42
|
+
): TruncationDirection {
|
|
43
|
+
return explicitParam !== undefined ? explicitParam : pathDefault(route, settings);
|
|
44
|
+
}
|