pi-ui-extend 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +307 -0
- package/bin/pix.mjs +219 -0
- package/dist/app/app.d.ts +96 -0
- package/dist/app/app.js +871 -0
- package/dist/app/blink-controller.d.ts +23 -0
- package/dist/app/blink-controller.js +82 -0
- package/dist/app/cli.d.ts +8 -0
- package/dist/app/cli.js +83 -0
- package/dist/app/clipboard.d.ts +1 -0
- package/dist/app/clipboard.js +24 -0
- package/dist/app/command-controller.d.ts +18 -0
- package/dist/app/command-controller.js +58 -0
- package/dist/app/command-host.d.ts +44 -0
- package/dist/app/command-host.js +1 -0
- package/dist/app/command-model-actions.d.ts +12 -0
- package/dist/app/command-model-actions.js +176 -0
- package/dist/app/command-navigation-actions.d.ts +19 -0
- package/dist/app/command-navigation-actions.js +267 -0
- package/dist/app/command-registry.d.ts +32 -0
- package/dist/app/command-registry.js +225 -0
- package/dist/app/command-runtime.d.ts +5 -0
- package/dist/app/command-runtime.js +32 -0
- package/dist/app/command-session-actions.d.ts +20 -0
- package/dist/app/command-session-actions.js +295 -0
- package/dist/app/constants.d.ts +52 -0
- package/dist/app/constants.js +103 -0
- package/dist/app/conversation-entry-renderer.d.ts +21 -0
- package/dist/app/conversation-entry-renderer.js +81 -0
- package/dist/app/conversation-shell-renderer.d.ts +5 -0
- package/dist/app/conversation-shell-renderer.js +43 -0
- package/dist/app/conversation-tool-renderer.d.ts +16 -0
- package/dist/app/conversation-tool-renderer.js +216 -0
- package/dist/app/conversation-viewport.d.ts +55 -0
- package/dist/app/conversation-viewport.js +252 -0
- package/dist/app/dcp-stats.d.ts +2 -0
- package/dist/app/dcp-stats.js +116 -0
- package/dist/app/editor-layout-renderer.d.ts +31 -0
- package/dist/app/editor-layout-renderer.js +211 -0
- package/dist/app/editor-panels.d.ts +4 -0
- package/dist/app/editor-panels.js +130 -0
- package/dist/app/extension-actions-controller.d.ts +22 -0
- package/dist/app/extension-actions-controller.js +60 -0
- package/dist/app/extension-event-bus.d.ts +3 -0
- package/dist/app/extension-event-bus.js +23 -0
- package/dist/app/extension-ui-controller.d.ts +57 -0
- package/dist/app/extension-ui-controller.js +532 -0
- package/dist/app/file-link-opener.d.ts +2 -0
- package/dist/app/file-link-opener.js +66 -0
- package/dist/app/file-links.d.ts +10 -0
- package/dist/app/file-links.js +117 -0
- package/dist/app/guards.d.ts +3 -0
- package/dist/app/guards.js +9 -0
- package/dist/app/icons.d.ts +37 -0
- package/dist/app/icons.js +97 -0
- package/dist/app/id.d.ts +1 -0
- package/dist/app/id.js +4 -0
- package/dist/app/image-click-targets.d.ts +5 -0
- package/dist/app/image-click-targets.js +32 -0
- package/dist/app/image-opener.d.ts +2 -0
- package/dist/app/image-opener.js +64 -0
- package/dist/app/input-action-controller.d.ts +47 -0
- package/dist/app/input-action-controller.js +209 -0
- package/dist/app/input-controller.d.ts +60 -0
- package/dist/app/input-controller.js +425 -0
- package/dist/app/input-paste-handler.d.ts +27 -0
- package/dist/app/input-paste-handler.js +146 -0
- package/dist/app/menu-items-controller.d.ts +32 -0
- package/dist/app/menu-items-controller.js +182 -0
- package/dist/app/message-content.d.ts +8 -0
- package/dist/app/message-content.js +115 -0
- package/dist/app/model-ref.d.ts +13 -0
- package/dist/app/model-ref.js +50 -0
- package/dist/app/model-usage-controller.d.ts +35 -0
- package/dist/app/model-usage-controller.js +99 -0
- package/dist/app/model-usage-status.d.ts +125 -0
- package/dist/app/model-usage-status.js +749 -0
- package/dist/app/mouse-controller.d.ts +182 -0
- package/dist/app/mouse-controller.js +968 -0
- package/dist/app/native-modifiers.d.ts +3 -0
- package/dist/app/native-modifiers.js +60 -0
- package/dist/app/nerd-font-controller.d.ts +11 -0
- package/dist/app/nerd-font-controller.js +90 -0
- package/dist/app/popup-action-controller.d.ts +44 -0
- package/dist/app/popup-action-controller.js +278 -0
- package/dist/app/popup-menu-controller.d.ts +183 -0
- package/dist/app/popup-menu-controller.js +1070 -0
- package/dist/app/prompt-enhancer-controller.d.ts +40 -0
- package/dist/app/prompt-enhancer-controller.js +215 -0
- package/dist/app/queued-message-controller.d.ts +62 -0
- package/dist/app/queued-message-controller.js +377 -0
- package/dist/app/render-controller.d.ts +41 -0
- package/dist/app/render-controller.js +378 -0
- package/dist/app/render-text.d.ts +19 -0
- package/dist/app/render-text.js +67 -0
- package/dist/app/request-history.d.ts +23 -0
- package/dist/app/request-history.js +131 -0
- package/dist/app/runtime.d.ts +39 -0
- package/dist/app/runtime.js +195 -0
- package/dist/app/screen-selection.d.ts +6 -0
- package/dist/app/screen-selection.js +9 -0
- package/dist/app/screen-styler.d.ts +34 -0
- package/dist/app/screen-styler.js +168 -0
- package/dist/app/scroll-controller.d.ts +51 -0
- package/dist/app/scroll-controller.js +207 -0
- package/dist/app/session-event-controller.d.ts +69 -0
- package/dist/app/session-event-controller.js +338 -0
- package/dist/app/session-history.d.ts +23 -0
- package/dist/app/session-history.js +164 -0
- package/dist/app/session-lifecycle-controller.d.ts +55 -0
- package/dist/app/session-lifecycle-controller.js +116 -0
- package/dist/app/session-search.d.ts +24 -0
- package/dist/app/session-search.js +215 -0
- package/dist/app/shell-command.d.ts +27 -0
- package/dist/app/shell-command.js +176 -0
- package/dist/app/shell-controller.d.ts +28 -0
- package/dist/app/shell-controller.js +124 -0
- package/dist/app/slash-commands.d.ts +6 -0
- package/dist/app/slash-commands.js +75 -0
- package/dist/app/startup-checks.d.ts +8 -0
- package/dist/app/startup-checks.js +59 -0
- package/dist/app/startup-info.d.ts +3 -0
- package/dist/app/startup-info.js +176 -0
- package/dist/app/status-controller.d.ts +35 -0
- package/dist/app/status-controller.js +105 -0
- package/dist/app/status-line-renderer.d.ts +68 -0
- package/dist/app/status-line-renderer.js +453 -0
- package/dist/app/subagents-files.d.ts +10 -0
- package/dist/app/subagents-files.js +193 -0
- package/dist/app/subagents-model.d.ts +23 -0
- package/dist/app/subagents-model.js +224 -0
- package/dist/app/subagents-widget-controller.d.ts +43 -0
- package/dist/app/subagents-widget-controller.js +311 -0
- package/dist/app/tab-line-renderer.d.ts +26 -0
- package/dist/app/tab-line-renderer.js +222 -0
- package/dist/app/tabs-controller.d.ts +100 -0
- package/dist/app/tabs-controller.js +885 -0
- package/dist/app/terminal-controller.d.ts +40 -0
- package/dist/app/terminal-controller.js +135 -0
- package/dist/app/terminal-edit-shortcuts.d.ts +23 -0
- package/dist/app/terminal-edit-shortcuts.js +138 -0
- package/dist/app/terminal-output-buffer.d.ts +20 -0
- package/dist/app/terminal-output-buffer.js +52 -0
- package/dist/app/toast-controller.d.ts +13 -0
- package/dist/app/toast-controller.js +40 -0
- package/dist/app/toast-renderer.d.ts +9 -0
- package/dist/app/toast-renderer.js +79 -0
- package/dist/app/todo-model.d.ts +22 -0
- package/dist/app/todo-model.js +179 -0
- package/dist/app/todo-widget-controller.d.ts +21 -0
- package/dist/app/todo-widget-controller.js +59 -0
- package/dist/app/tool-block-renderer.d.ts +26 -0
- package/dist/app/tool-block-renderer.js +439 -0
- package/dist/app/types.d.ts +550 -0
- package/dist/app/types.js +1 -0
- package/dist/app/update.d.ts +36 -0
- package/dist/app/update.js +315 -0
- package/dist/app/voice-controller.d.ts +52 -0
- package/dist/app/voice-controller.js +600 -0
- package/dist/app/workspace-actions-controller.d.ts +40 -0
- package/dist/app/workspace-actions-controller.js +215 -0
- package/dist/app/workspace-undo.d.ts +44 -0
- package/dist/app/workspace-undo.js +215 -0
- package/dist/config.d.ts +62 -0
- package/dist/config.js +527 -0
- package/dist/context-progress-bar.d.ts +17 -0
- package/dist/context-progress-bar.js +48 -0
- package/dist/default-pix-config.d.ts +1 -0
- package/dist/default-pix-config.js +375 -0
- package/dist/fuzzy.d.ts +23 -0
- package/dist/fuzzy.js +165 -0
- package/dist/input-editor-files.d.ts +15 -0
- package/dist/input-editor-files.js +62 -0
- package/dist/input-editor.d.ts +186 -0
- package/dist/input-editor.js +835 -0
- package/dist/main.d.ts +1 -0
- package/dist/main.js +12 -0
- package/dist/markdown-format.d.ts +22 -0
- package/dist/markdown-format.js +542 -0
- package/dist/sdk.d.ts +3 -0
- package/dist/sdk.js +1 -0
- package/dist/syntax-highlight.d.ts +22 -0
- package/dist/syntax-highlight.js +528 -0
- package/dist/terminal-width.d.ts +6 -0
- package/dist/terminal-width.js +245 -0
- package/dist/theme.d.ts +56 -0
- package/dist/theme.js +118 -0
- package/dist/tool-renderers/apply-patch.d.ts +2 -0
- package/dist/tool-renderers/apply-patch.js +36 -0
- package/dist/tool-renderers/ast.d.ts +2 -0
- package/dist/tool-renderers/ast.js +5 -0
- package/dist/tool-renderers/compress.d.ts +2 -0
- package/dist/tool-renderers/compress.js +126 -0
- package/dist/tool-renderers/index.d.ts +3 -0
- package/dist/tool-renderers/index.js +44 -0
- package/dist/tool-renderers/question.d.ts +2 -0
- package/dist/tool-renderers/question.js +88 -0
- package/dist/tool-renderers/read.d.ts +2 -0
- package/dist/tool-renderers/read.js +36 -0
- package/dist/tool-renderers/repo.d.ts +2 -0
- package/dist/tool-renderers/repo.js +13 -0
- package/dist/tool-renderers/shell.d.ts +3 -0
- package/dist/tool-renderers/shell.js +27 -0
- package/dist/tool-renderers/skill.d.ts +2 -0
- package/dist/tool-renderers/skill.js +132 -0
- package/dist/tool-renderers/subagents.d.ts +2 -0
- package/dist/tool-renderers/subagents.js +51 -0
- package/dist/tool-renderers/todo.d.ts +2 -0
- package/dist/tool-renderers/todo.js +9 -0
- package/dist/tool-renderers/types.d.ts +42 -0
- package/dist/tool-renderers/types.js +1 -0
- package/dist/tool-renderers/utils.d.ts +31 -0
- package/dist/tool-renderers/utils.js +230 -0
- package/dist/tool-renderers/web.d.ts +3 -0
- package/dist/tool-renderers/web.js +9 -0
- package/dist/tool-renderers/write.d.ts +2 -0
- package/dist/tool-renderers/write.js +42 -0
- package/dist/ui.d.ts +56 -0
- package/dist/ui.js +94 -0
- package/docs/release.md +81 -0
- package/extensions/question/contract.ts +100 -0
- package/extensions/question/index.ts +34 -0
- package/extensions/question/render.ts +28 -0
- package/extensions/question/result.ts +86 -0
- package/extensions/question/tool-description.ts +11 -0
- package/extensions/question/tui.ts +629 -0
- package/extensions/question/types.ts +123 -0
- package/extensions/session-title/config.ts +169 -0
- package/extensions/session-title/index.ts +459 -0
- package/extensions/terminal-bell/index.ts +315 -0
- package/external/pi-tools-suite/README.md +242 -0
- package/external/pi-tools-suite/index.ts +1 -0
- package/external/pi-tools-suite/licenses/ollama-pi-web-search.MIT +21 -0
- package/external/pi-tools-suite/licenses/opencode-mystatus-MIT.txt +21 -0
- package/external/pi-tools-suite/package.json +53 -0
- package/external/pi-tools-suite/src/antigravity-auth/auth-store.ts +194 -0
- package/external/pi-tools-suite/src/antigravity-auth/commands.ts +80 -0
- package/external/pi-tools-suite/src/antigravity-auth/constants.ts +26 -0
- package/external/pi-tools-suite/src/antigravity-auth/headers.ts +20 -0
- package/external/pi-tools-suite/src/antigravity-auth/index.ts +104 -0
- package/external/pi-tools-suite/src/antigravity-auth/models.ts +86 -0
- package/external/pi-tools-suite/src/antigravity-auth/oauth.ts +305 -0
- package/external/pi-tools-suite/src/antigravity-auth/payload.ts +423 -0
- package/external/pi-tools-suite/src/antigravity-auth/status.ts +78 -0
- package/external/pi-tools-suite/src/antigravity-auth/stream.ts +302 -0
- package/external/pi-tools-suite/src/antigravity-auth/types.ts +113 -0
- package/external/pi-tools-suite/src/ast-grep/index.ts +6 -0
- package/external/pi-tools-suite/src/ast-grep/render.ts +70 -0
- package/external/pi-tools-suite/src/ast-grep/schema.ts +109 -0
- package/external/pi-tools-suite/src/ast-grep/tool.ts +345 -0
- package/external/pi-tools-suite/src/ast-grep/types.ts +55 -0
- package/external/pi-tools-suite/src/ast-grep/utils.ts +65 -0
- package/external/pi-tools-suite/src/async-subagents/async-subagents.sample.jsonc +222 -0
- package/external/pi-tools-suite/src/async-subagents/commands.ts +518 -0
- package/external/pi-tools-suite/src/async-subagents/constants.ts +11 -0
- package/external/pi-tools-suite/src/async-subagents/core/agent-strategy.ts +74 -0
- package/external/pi-tools-suite/src/async-subagents/core/attachment-bridge.ts +133 -0
- package/external/pi-tools-suite/src/async-subagents/core/cleanup.ts +66 -0
- package/external/pi-tools-suite/src/async-subagents/core/concurrency.ts +90 -0
- package/external/pi-tools-suite/src/async-subagents/core/config.ts +819 -0
- package/external/pi-tools-suite/src/async-subagents/core/log-limits.ts +166 -0
- package/external/pi-tools-suite/src/async-subagents/core/model-fallback.ts +133 -0
- package/external/pi-tools-suite/src/async-subagents/core/paths.ts +47 -0
- package/external/pi-tools-suite/src/async-subagents/core/pi-invocation.ts +35 -0
- package/external/pi-tools-suite/src/async-subagents/core/presets.ts +67 -0
- package/external/pi-tools-suite/src/async-subagents/core/process.ts +15 -0
- package/external/pi-tools-suite/src/async-subagents/core/prompt.ts +66 -0
- package/external/pi-tools-suite/src/async-subagents/core/registry.ts +224 -0
- package/external/pi-tools-suite/src/async-subagents/core/retry.ts +191 -0
- package/external/pi-tools-suite/src/async-subagents/core/routing.ts +259 -0
- package/external/pi-tools-suite/src/async-subagents/core/sessions.ts +138 -0
- package/external/pi-tools-suite/src/async-subagents/core/spawn.ts +688 -0
- package/external/pi-tools-suite/src/async-subagents/core/state.ts +281 -0
- package/external/pi-tools-suite/src/async-subagents/core/stop.ts +131 -0
- package/external/pi-tools-suite/src/async-subagents/core/structured-result.ts +237 -0
- package/external/pi-tools-suite/src/async-subagents/core/tool-guard.ts +34 -0
- package/external/pi-tools-suite/src/async-subagents/core/types.ts +150 -0
- package/external/pi-tools-suite/src/async-subagents/core/ultrawork-auto.ts +184 -0
- package/external/pi-tools-suite/src/async-subagents/core/utils.ts +11 -0
- package/external/pi-tools-suite/src/async-subagents/format.ts +41 -0
- package/external/pi-tools-suite/src/async-subagents/index.ts +422 -0
- package/external/pi-tools-suite/src/async-subagents/lib.ts +88 -0
- package/external/pi-tools-suite/src/async-subagents/live.ts +10 -0
- package/external/pi-tools-suite/src/async-subagents/polling.ts +83 -0
- package/external/pi-tools-suite/src/async-subagents/render.ts +230 -0
- package/external/pi-tools-suite/src/async-subagents/subagent-overlay.ts +77 -0
- package/external/pi-tools-suite/src/async-subagents/tasks.ts +120 -0
- package/external/pi-tools-suite/src/async-subagents/tools/cleanup.ts +99 -0
- package/external/pi-tools-suite/src/async-subagents/tools/result.ts +179 -0
- package/external/pi-tools-suite/src/async-subagents/tools/spawn.ts +372 -0
- package/external/pi-tools-suite/src/async-subagents/tools/status.ts +60 -0
- package/external/pi-tools-suite/src/async-subagents/tools/stop.ts +79 -0
- package/external/pi-tools-suite/src/async-subagents/tools/subagents.ts +152 -0
- package/external/pi-tools-suite/src/async-subagents/tools/wait.ts +67 -0
- package/external/pi-tools-suite/src/async-subagents/types.ts +45 -0
- package/external/pi-tools-suite/src/async-subagents/ui.ts +5 -0
- package/external/pi-tools-suite/src/compress/commands.ts +440 -0
- package/external/pi-tools-suite/src/compress/compress-tool.ts +368 -0
- package/external/pi-tools-suite/src/compress/compression-blocks.ts +524 -0
- package/external/pi-tools-suite/src/compress/config.ts +310 -0
- package/external/pi-tools-suite/src/compress/dcp-tui-filter.ts +498 -0
- package/external/pi-tools-suite/src/compress/index.ts +397 -0
- package/external/pi-tools-suite/src/compress/prompts.ts +269 -0
- package/external/pi-tools-suite/src/compress/pruner-candidates.ts +176 -0
- package/external/pi-tools-suite/src/compress/pruner-compression-blocks.ts +260 -0
- package/external/pi-tools-suite/src/compress/pruner-message-ids.ts +147 -0
- package/external/pi-tools-suite/src/compress/pruner-metadata.ts +268 -0
- package/external/pi-tools-suite/src/compress/pruner-nudge.ts +315 -0
- package/external/pi-tools-suite/src/compress/pruner-tools.ts +263 -0
- package/external/pi-tools-suite/src/compress/pruner-types.ts +25 -0
- package/external/pi-tools-suite/src/compress/pruner.ts +92 -0
- package/external/pi-tools-suite/src/compress/state.ts +486 -0
- package/external/pi-tools-suite/src/compress/ui.ts +308 -0
- package/external/pi-tools-suite/src/config.ts +176 -0
- package/external/pi-tools-suite/src/context-usage.ts +31 -0
- package/external/pi-tools-suite/src/default-pi-tools-suite-config.ts +355 -0
- package/external/pi-tools-suite/src/index.ts +46 -0
- package/external/pi-tools-suite/src/lib/lsp.ts +62 -0
- package/external/pi-tools-suite/src/lib/project.ts +42 -0
- package/external/pi-tools-suite/src/lib/tool-args.ts +137 -0
- package/external/pi-tools-suite/src/lsp/_shared/config.ts +156 -0
- package/external/pi-tools-suite/src/lsp/_shared/glob.ts +60 -0
- package/external/pi-tools-suite/src/lsp/_shared/output.ts +102 -0
- package/external/pi-tools-suite/src/lsp/_shared/paths.ts +138 -0
- package/external/pi-tools-suite/src/lsp/_shared/runner.ts +64 -0
- package/external/pi-tools-suite/src/lsp/_shared/template.ts +23 -0
- package/external/pi-tools-suite/src/lsp/_shared/trust.ts +116 -0
- package/external/pi-tools-suite/src/lsp/_shared/types.ts +98 -0
- package/external/pi-tools-suite/src/lsp/async.ts +29 -0
- package/external/pi-tools-suite/src/lsp/child-process.ts +81 -0
- package/external/pi-tools-suite/src/lsp/client.ts +340 -0
- package/external/pi-tools-suite/src/lsp/constants.ts +9 -0
- package/external/pi-tools-suite/src/lsp/diagnostics-store.ts +64 -0
- package/external/pi-tools-suite/src/lsp/documents.ts +24 -0
- package/external/pi-tools-suite/src/lsp/index.ts +31 -0
- package/external/pi-tools-suite/src/lsp/lsp-utils.ts +37 -0
- package/external/pi-tools-suite/src/lsp/manager.ts +190 -0
- package/external/pi-tools-suite/src/lsp/mutation-events.ts +78 -0
- package/external/pi-tools-suite/src/lsp/renderer.ts +1 -0
- package/external/pi-tools-suite/src/lsp/tool-result.ts +6 -0
- package/external/pi-tools-suite/src/lsp/tsserver.ts +107 -0
- package/external/pi-tools-suite/src/lsp/types.ts +15 -0
- package/external/pi-tools-suite/src/model-tools/apply-patch.ts +590 -0
- package/external/pi-tools-suite/src/model-tools/index.ts +430 -0
- package/external/pi-tools-suite/src/model-tools/path-utils.ts +6 -0
- package/external/pi-tools-suite/src/model-tools/tool-args.ts +11 -0
- package/external/pi-tools-suite/src/prompt-commands/index.ts +349 -0
- package/external/pi-tools-suite/src/repo-discovery/index.ts +384 -0
- package/external/pi-tools-suite/src/repo-discovery/project.ts +7 -0
- package/external/pi-tools-suite/src/startup-section.ts +13 -0
- package/external/pi-tools-suite/src/terminal-bell/index.ts +309 -0
- package/external/pi-tools-suite/src/todo/index.ts +201 -0
- package/external/pi-tools-suite/src/todo/state/auto-clear.ts +13 -0
- package/external/pi-tools-suite/src/todo/state/invariants.ts +21 -0
- package/external/pi-tools-suite/src/todo/state/persistence.ts +94 -0
- package/external/pi-tools-suite/src/todo/state/replay.ts +38 -0
- package/external/pi-tools-suite/src/todo/state/selectors.ts +49 -0
- package/external/pi-tools-suite/src/todo/state/state-reducer.ts +362 -0
- package/external/pi-tools-suite/src/todo/state/state.ts +18 -0
- package/external/pi-tools-suite/src/todo/state/store.ts +52 -0
- package/external/pi-tools-suite/src/todo/state/task-graph.ts +57 -0
- package/external/pi-tools-suite/src/todo/todo.ts +487 -0
- package/external/pi-tools-suite/src/todo/tool/response-envelope.ts +143 -0
- package/external/pi-tools-suite/src/todo/tool/types.ts +188 -0
- package/external/pi-tools-suite/src/todo/view/format.ts +18 -0
- package/external/pi-tools-suite/src/todo/view/labels.ts +13 -0
- package/external/pi-tools-suite/src/tool-descriptions.ts +369 -0
- package/external/pi-tools-suite/src/usage/index.ts +152 -0
- package/external/pi-tools-suite/src/usage/lib/copilot.ts +535 -0
- package/external/pi-tools-suite/src/usage/lib/google.ts +478 -0
- package/external/pi-tools-suite/src/usage/lib/openai.ts +268 -0
- package/external/pi-tools-suite/src/usage/lib/types.ts +114 -0
- package/external/pi-tools-suite/src/usage/lib/utils.ts +134 -0
- package/external/pi-tools-suite/src/usage/lib/zhipu.ts +228 -0
- package/external/pi-tools-suite/src/web-search/index.ts +397 -0
- package/package.json +89 -0
- package/skills/context7/SKILL.md +69 -0
- package/skills/context7/scripts/context7.sh +73 -0
- package/skills/handoff/SKILL.md +15 -0
- package/skills/pdf/LICENSE.txt +30 -0
- package/skills/pdf/SKILL.md +314 -0
- package/skills/pdf/forms.md +294 -0
- package/skills/pdf/reference.md +612 -0
- package/skills/pdf/scripts/check_bounding_boxes.py +65 -0
- package/skills/pdf/scripts/check_fillable_fields.py +11 -0
- package/skills/pdf/scripts/convert_pdf_to_images.py +33 -0
- package/skills/pdf/scripts/create_validation_image.py +37 -0
- package/skills/pdf/scripts/extract_form_field_info.py +122 -0
- package/skills/pdf/scripts/extract_form_structure.py +115 -0
- package/skills/pdf/scripts/fill_fillable_fields.py +98 -0
- package/skills/pdf/scripts/fill_pdf_form_with_annotations.py +107 -0
- package/skills/playwright-cli/SKILL.md +388 -0
- package/skills/playwright-cli/references/element-attributes.md +23 -0
- package/skills/playwright-cli/references/playwright-tests.md +39 -0
- package/skills/playwright-cli/references/request-mocking.md +87 -0
- package/skills/playwright-cli/references/running-code.md +241 -0
- package/skills/playwright-cli/references/session-management.md +225 -0
- package/skills/playwright-cli/references/spec-driven-testing.md +305 -0
- package/skills/playwright-cli/references/storage-state.md +275 -0
- package/skills/playwright-cli/references/test-generation.md +134 -0
- package/skills/playwright-cli/references/tracing.md +139 -0
- package/skills/playwright-cli/references/video-recording.md +143 -0
- package/skills/simplify/SKILL.md +51 -0
- package/skills/skill-creator/LICENSE.txt +202 -0
- package/skills/skill-creator/SKILL.md +485 -0
- package/skills/skill-creator/agents/analyzer.md +274 -0
- package/skills/skill-creator/agents/comparator.md +202 -0
- package/skills/skill-creator/agents/grader.md +223 -0
- package/skills/skill-creator/assets/eval_review.html +146 -0
- package/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/skills/skill-creator/references/schemas.md +430 -0
- package/skills/skill-creator/scripts/__init__.py +0 -0
- package/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/skills/skill-creator/scripts/generate_report.py +326 -0
- package/skills/skill-creator/scripts/improve_description.py +247 -0
- package/skills/skill-creator/scripts/package_skill.py +136 -0
- package/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/skills/skill-creator/scripts/run_eval.py +310 -0
- package/skills/skill-creator/scripts/run_loop.py +328 -0
- package/skills/skill-creator/scripts/utils.py +47 -0
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
import type { CompressionBlock, DcpState, MessageIdMeta } from "./state.js"
|
|
2
|
+
import type { DcpConfig } from "./config.js"
|
|
3
|
+
import { estimateTokens } from "./pruner-metadata.js"
|
|
4
|
+
import { isToolRecordProtected } from "./pruner-tools.js"
|
|
5
|
+
import * as fs from "node:fs"
|
|
6
|
+
import * as path from "node:path"
|
|
7
|
+
|
|
8
|
+
const MAX_PROTECTED_SUBAGENT_RESULT_CHARS = 50_000
|
|
9
|
+
|
|
10
|
+
export interface CompressionBlockCreationResult {
|
|
11
|
+
block: CompressionBlock
|
|
12
|
+
removedTokenEstimate: number
|
|
13
|
+
summaryTokenEstimate: number
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface CreateRangeCompressionBlockOptions {
|
|
17
|
+
topic: string
|
|
18
|
+
summary: string
|
|
19
|
+
startTimestamp: number
|
|
20
|
+
endTimestamp: number
|
|
21
|
+
startMessageId?: string
|
|
22
|
+
endMessageId?: string
|
|
23
|
+
state: DcpState
|
|
24
|
+
config: DcpConfig
|
|
25
|
+
anchorTimestamp?: number
|
|
26
|
+
anchorMessageId?: string
|
|
27
|
+
createdByToolCallId?: string
|
|
28
|
+
mode?: "range" | "message"
|
|
29
|
+
validatePlaceholders?: boolean
|
|
30
|
+
expandPlaceholders?: boolean
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface ResolvedCompressionBoundary {
|
|
34
|
+
timestamp: number
|
|
35
|
+
stableId?: string
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface ResolvedCompressionAnchor extends ResolvedCompressionBoundary {}
|
|
39
|
+
|
|
40
|
+
const BLOCK_PLACEHOLDER_RE = /\(b(\d+)\)|\{block_(\d+)\}/gi
|
|
41
|
+
const MAX_DIAGNOSTIC_IDS = 24
|
|
42
|
+
|
|
43
|
+
function idSortKey(id: string): [number, string] {
|
|
44
|
+
const match = id.match(/^(\D+)(\d+)$/)
|
|
45
|
+
if (!match) return [Number.MAX_SAFE_INTEGER, id]
|
|
46
|
+
return [Number.parseInt(match[2]!, 10), match[1]!.toLowerCase()]
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function sortIds(ids: string[]): string[] {
|
|
50
|
+
return [...ids].sort((a, b) => {
|
|
51
|
+
const [aNumber, aPrefix] = idSortKey(a)
|
|
52
|
+
const [bNumber, bPrefix] = idSortKey(b)
|
|
53
|
+
return aNumber - bNumber || aPrefix.localeCompare(bPrefix) || a.localeCompare(b)
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function compactList(items: string[], maxItems = MAX_DIAGNOSTIC_IDS): string {
|
|
58
|
+
if (items.length === 0) return "none"
|
|
59
|
+
if (items.length <= maxItems) return items.join(", ")
|
|
60
|
+
|
|
61
|
+
const headCount = Math.max(1, Math.floor(maxItems * 0.65))
|
|
62
|
+
const tailCount = Math.max(1, maxItems - headCount)
|
|
63
|
+
return `${items.slice(0, headCount).join(", ")}, …, ${items.slice(-tailCount).join(", ")} (${items.length} total)`
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function quoteTopic(topic: string): string {
|
|
67
|
+
const singleLine = topic.replace(/\s+/g, " ").trim()
|
|
68
|
+
if (!singleLine) return ""
|
|
69
|
+
const truncated = singleLine.length > 48 ? `${singleLine.slice(0, 47)}…` : singleLine
|
|
70
|
+
return ` "${truncated.replace(/"/g, "'")}"`
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function formatCompressionIdDiagnostics(state: DcpState): string {
|
|
74
|
+
const rawIds = sortIds([
|
|
75
|
+
...new Set([
|
|
76
|
+
...state.messageIdSnapshot.keys(),
|
|
77
|
+
...state.messageMetaSnapshot.keys(),
|
|
78
|
+
]),
|
|
79
|
+
])
|
|
80
|
+
const blockIds = state.compressionBlocks
|
|
81
|
+
.filter((block) => block.active)
|
|
82
|
+
.sort((a, b) => a.id - b.id)
|
|
83
|
+
.map((block) => `b${block.id}${quoteTopic(block.topic)}`)
|
|
84
|
+
|
|
85
|
+
return [
|
|
86
|
+
`Current raw message IDs: ${compactList(rawIds)}.`,
|
|
87
|
+
`Current active block IDs: ${compactList(blockIds)}.`,
|
|
88
|
+
"Use only IDs from the latest visible context. If a raw range was already compressed, use the corresponding bN block ID instead of stale mNNN IDs.",
|
|
89
|
+
].join("\n")
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function unknownCompressionIdError(rawId: string, state: DcpState): Error {
|
|
93
|
+
const id = rawId.trim()
|
|
94
|
+
return new Error(
|
|
95
|
+
`Unknown message ID: ${id}.\n` +
|
|
96
|
+
"The ID is not present in the current DCP snapshot; it may be stale after compression, pruning, reload, or session switching.\n" +
|
|
97
|
+
formatCompressionIdDiagnostics(state),
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function formatRestoredBlock(block: CompressionBlock): string {
|
|
102
|
+
return `[Previously compressed: ${block.topic}]\n${block.summary}`
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Replace `(bN)` / legacy `{block_N}` placeholders in a summary with the
|
|
107
|
+
* stored content of the referenced compression block. Unrecognised
|
|
108
|
+
* placeholders are left as-is for backwards compatibility.
|
|
109
|
+
*/
|
|
110
|
+
export function expandBlockPlaceholders(summary: string, state: DcpState): string {
|
|
111
|
+
return summary.replace(BLOCK_PLACEHOLDER_RE, (match, idStr, legacyIdStr) => {
|
|
112
|
+
const id = parseInt(idStr ?? legacyIdStr, 10)
|
|
113
|
+
const block = state.compressionBlocks.find((b) => b.id === id)
|
|
114
|
+
return block ? formatRestoredBlock(block) : match
|
|
115
|
+
})
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function expandBlockPlaceholdersWithRecovery(
|
|
119
|
+
summary: string,
|
|
120
|
+
coveredBlocks: CompressionBlock[],
|
|
121
|
+
state: DcpState,
|
|
122
|
+
): string {
|
|
123
|
+
const coveredIds = new Set(coveredBlocks.map((block) => block.id))
|
|
124
|
+
const consumed = new Set<number>()
|
|
125
|
+
|
|
126
|
+
const expanded = summary.replace(BLOCK_PLACEHOLDER_RE, (_match, idStr, legacyIdStr) => {
|
|
127
|
+
const id = parseInt(idStr ?? legacyIdStr, 10)
|
|
128
|
+
if (!coveredIds.has(id) || consumed.has(id)) return ""
|
|
129
|
+
|
|
130
|
+
const block = state.compressionBlocks.find((b) => b.id === id)
|
|
131
|
+
if (!block) return ""
|
|
132
|
+
|
|
133
|
+
consumed.add(id)
|
|
134
|
+
return formatRestoredBlock(block)
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
const missing = coveredBlocks.filter((block) => !consumed.has(block.id))
|
|
138
|
+
if (missing.length === 0) return expanded
|
|
139
|
+
|
|
140
|
+
const recoveryHeading =
|
|
141
|
+
"\n\nThe following previously compressed summaries were also part of this conversation section and were preserved automatically:"
|
|
142
|
+
const recovery = missing
|
|
143
|
+
.map((block) => `\n\n### b${block.id}\n${formatRestoredBlock(block)}`)
|
|
144
|
+
.join("")
|
|
145
|
+
|
|
146
|
+
return expanded + recoveryHeading + recovery
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function preparePlaceholderSummary(
|
|
150
|
+
summary: string,
|
|
151
|
+
coveredBlocks: CompressionBlock[],
|
|
152
|
+
state: DcpState,
|
|
153
|
+
options: { validatePlaceholders: boolean; expandPlaceholders: boolean },
|
|
154
|
+
): string {
|
|
155
|
+
if (!options.expandPlaceholders) return summary
|
|
156
|
+
if (options.validatePlaceholders) {
|
|
157
|
+
return expandBlockPlaceholdersWithRecovery(summary, coveredBlocks, state)
|
|
158
|
+
}
|
|
159
|
+
return expandBlockPlaceholders(summary, state)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function findCoveredAndPartialBlocks(
|
|
163
|
+
startTimestamp: number,
|
|
164
|
+
endTimestamp: number,
|
|
165
|
+
state: DcpState,
|
|
166
|
+
): { coveredBlocks: CompressionBlock[]; partialBlocks: CompressionBlock[] } {
|
|
167
|
+
const coveredBlocks: CompressionBlock[] = []
|
|
168
|
+
const partialBlocks: CompressionBlock[] = []
|
|
169
|
+
|
|
170
|
+
for (const existing of state.compressionBlocks) {
|
|
171
|
+
if (!existing.active) continue
|
|
172
|
+
if (!Number.isFinite(existing.startTimestamp) || !Number.isFinite(existing.endTimestamp)) continue
|
|
173
|
+
|
|
174
|
+
const overlaps =
|
|
175
|
+
startTimestamp <= existing.endTimestamp &&
|
|
176
|
+
existing.startTimestamp <= endTimestamp
|
|
177
|
+
if (!overlaps) continue
|
|
178
|
+
|
|
179
|
+
const fullyCovered =
|
|
180
|
+
startTimestamp <= existing.startTimestamp &&
|
|
181
|
+
existing.endTimestamp <= endTimestamp
|
|
182
|
+
|
|
183
|
+
if (fullyCovered) coveredBlocks.push(existing)
|
|
184
|
+
else partialBlocks.push(existing)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return { coveredBlocks, partialBlocks }
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export function getMessageMeta(id: string, state: DcpState): MessageIdMeta | undefined {
|
|
191
|
+
return state.messageMetaSnapshot.get(id.trim())
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function extractProtectTagTexts(text: string): string[] {
|
|
195
|
+
const protectedTexts: string[] = []
|
|
196
|
+
for (const match of text.matchAll(/<protect>([\s\S]*?)<\/protect>/gi)) {
|
|
197
|
+
const protectedText = match[1]?.trim()
|
|
198
|
+
if (protectedText) protectedTexts.push(protectedText)
|
|
199
|
+
}
|
|
200
|
+
return protectedTexts
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export function appendProtectedPromptInfo(
|
|
204
|
+
summary: string,
|
|
205
|
+
startTimestamp: number,
|
|
206
|
+
endTimestamp: number,
|
|
207
|
+
state: DcpState,
|
|
208
|
+
config: DcpConfig,
|
|
209
|
+
): string {
|
|
210
|
+
if (!config.compress.protectTags) return summary
|
|
211
|
+
|
|
212
|
+
const protectedTexts: string[] = []
|
|
213
|
+
const seen = new Set<string>()
|
|
214
|
+
|
|
215
|
+
for (const meta of state.messageMetaSnapshot.values()) {
|
|
216
|
+
if (meta.role !== "user") continue
|
|
217
|
+
if (meta.blockId !== undefined) continue
|
|
218
|
+
if (!Number.isFinite(meta.timestamp)) continue
|
|
219
|
+
if (meta.timestamp < startTimestamp || meta.timestamp > endTimestamp) continue
|
|
220
|
+
|
|
221
|
+
for (const text of extractProtectTagTexts(meta.text ?? "")) {
|
|
222
|
+
if (seen.has(text)) continue
|
|
223
|
+
seen.add(text)
|
|
224
|
+
protectedTexts.push(text)
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (protectedTexts.length === 0) return summary
|
|
229
|
+
|
|
230
|
+
const heading = "\n\nThe following protected prompt information appeared in the selected user message(s) and must be preserved verbatim:"
|
|
231
|
+
return summary + heading + protectedTexts.map((text) => `\n${text}`).join("")
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export function appendProtectedUserMessages(
|
|
235
|
+
summary: string,
|
|
236
|
+
startTimestamp: number,
|
|
237
|
+
endTimestamp: number,
|
|
238
|
+
state: DcpState,
|
|
239
|
+
enabled: boolean,
|
|
240
|
+
): string {
|
|
241
|
+
if (!enabled) return summary
|
|
242
|
+
|
|
243
|
+
const userTexts: string[] = []
|
|
244
|
+
const seen = new Set<string>()
|
|
245
|
+
|
|
246
|
+
for (const meta of state.messageMetaSnapshot.values()) {
|
|
247
|
+
if (meta.role !== "user") continue
|
|
248
|
+
if (meta.blockId !== undefined) continue
|
|
249
|
+
if (!Number.isFinite(meta.timestamp)) continue
|
|
250
|
+
if (meta.timestamp < startTimestamp || meta.timestamp > endTimestamp) continue
|
|
251
|
+
|
|
252
|
+
const text = meta.text?.trim()
|
|
253
|
+
if (!text || seen.has(text)) continue
|
|
254
|
+
seen.add(text)
|
|
255
|
+
userTexts.push(text)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (userTexts.length === 0) return summary
|
|
259
|
+
|
|
260
|
+
const heading = "\n\nThe following user messages from this compressed range were preserved verbatim:"
|
|
261
|
+
return summary + heading + userTexts.map((text) => `\n${text}`).join("")
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function truncateProtectedOutput(text: string, maxChars: number): string {
|
|
265
|
+
if (text.length <= maxChars) return text
|
|
266
|
+
const omitted = text.length - maxChars
|
|
267
|
+
return text.slice(0, maxChars) + `\n[Protected output truncated; ${omitted} characters omitted]`
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function resolveArtifactPath(filePath: string): string {
|
|
271
|
+
return path.isAbsolute(filePath) ? filePath : path.resolve(process.cwd(), filePath)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function readProtectedSubagentResult(details: unknown, fallbackText: string): string | undefined {
|
|
275
|
+
if (!details || typeof details !== "object") return undefined
|
|
276
|
+
const record = details as any
|
|
277
|
+
const artifactPath = record.artifacts?.resultMd
|
|
278
|
+
if (typeof artifactPath !== "string" || artifactPath.trim().length === 0) return undefined
|
|
279
|
+
|
|
280
|
+
const absolutePath = resolveArtifactPath(artifactPath.trim())
|
|
281
|
+
let text: string
|
|
282
|
+
try {
|
|
283
|
+
text = fs.readFileSync(absolutePath, "utf8")
|
|
284
|
+
} catch {
|
|
285
|
+
return undefined
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const trimmed = text.trim()
|
|
289
|
+
if (!trimmed || fallbackText.includes(trimmed)) return undefined
|
|
290
|
+
return `\n### Expanded subagent result: ${artifactPath}\n${truncateProtectedOutput(trimmed, MAX_PROTECTED_SUBAGENT_RESULT_CHARS)}`
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function appendProtectedToolOutputs(
|
|
294
|
+
summary: string,
|
|
295
|
+
startTimestamp: number,
|
|
296
|
+
endTimestamp: number,
|
|
297
|
+
state: DcpState,
|
|
298
|
+
config: DcpConfig,
|
|
299
|
+
): string {
|
|
300
|
+
const protectedOutputs: string[] = []
|
|
301
|
+
const seenToolCallIds = new Set<string>()
|
|
302
|
+
|
|
303
|
+
for (const meta of state.messageMetaSnapshot.values()) {
|
|
304
|
+
if (meta.blockId !== undefined) continue
|
|
305
|
+
if (!Number.isFinite(meta.timestamp)) continue
|
|
306
|
+
if (meta.timestamp < startTimestamp || meta.timestamp > endTimestamp) continue
|
|
307
|
+
if (meta.role !== "toolResult" && meta.role !== "bashExecution") continue
|
|
308
|
+
|
|
309
|
+
const toolCallId = meta.toolCallId
|
|
310
|
+
if (!toolCallId || seenToolCallIds.has(toolCallId)) continue
|
|
311
|
+
const record = state.toolCalls.get(toolCallId)
|
|
312
|
+
if (!record) continue
|
|
313
|
+
|
|
314
|
+
// The compress tool's own JSON accounting output is control-plane data and
|
|
315
|
+
// rarely useful in future summaries; avoid recursively copying it.
|
|
316
|
+
if (record.toolName === "compress") continue
|
|
317
|
+
if (!isToolRecordProtected(record, config)) continue
|
|
318
|
+
|
|
319
|
+
const output = (record.outputText ?? meta.text ?? "").trim()
|
|
320
|
+
if (!output) continue
|
|
321
|
+
|
|
322
|
+
seenToolCallIds.add(toolCallId)
|
|
323
|
+
const expandedSubagentResult =
|
|
324
|
+
record.toolName === "subagents" || record.toolName === "async_subagents_result"
|
|
325
|
+
? readProtectedSubagentResult(record.outputDetails, output)
|
|
326
|
+
: undefined
|
|
327
|
+
protectedOutputs.push(`\n### Tool: ${record.toolName}\n${output}${expandedSubagentResult ?? ""}`)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (protectedOutputs.length === 0) return summary
|
|
331
|
+
const heading = "\n\nThe following protected tool outputs were included in this conversation section:"
|
|
332
|
+
return summary + heading + protectedOutputs.join("")
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export function estimateVisibleRangeTokens(
|
|
336
|
+
startTimestamp: number,
|
|
337
|
+
endTimestamp: number,
|
|
338
|
+
coveredBlocks: CompressionBlock[],
|
|
339
|
+
state: DcpState,
|
|
340
|
+
): number {
|
|
341
|
+
let total = 0
|
|
342
|
+
for (const meta of state.messageMetaSnapshot.values()) {
|
|
343
|
+
if (meta.blockId !== undefined) continue
|
|
344
|
+
if (!Number.isFinite(meta.timestamp)) continue
|
|
345
|
+
if (meta.timestamp < startTimestamp || meta.timestamp > endTimestamp) continue
|
|
346
|
+
total += Math.max(0, Math.round(meta.tokenEstimate ?? 0))
|
|
347
|
+
}
|
|
348
|
+
for (const block of coveredBlocks) {
|
|
349
|
+
total += Math.max(0, Math.round(block.summaryTokenEstimate ?? 0))
|
|
350
|
+
}
|
|
351
|
+
return total
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Resolve a user-supplied ID string (e.g. "m001" or "b3") to an actual
|
|
356
|
+
* message timestamp.
|
|
357
|
+
*/
|
|
358
|
+
export function resolveIdToTimestamp(
|
|
359
|
+
rawId: string,
|
|
360
|
+
field: "startTimestamp" | "endTimestamp",
|
|
361
|
+
state: DcpState,
|
|
362
|
+
): number {
|
|
363
|
+
return resolveIdToBoundary(rawId, field, state).timestamp
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
export function resolveIdToBoundary(
|
|
367
|
+
rawId: string,
|
|
368
|
+
field: "startTimestamp" | "endTimestamp",
|
|
369
|
+
state: DcpState,
|
|
370
|
+
): ResolvedCompressionBoundary {
|
|
371
|
+
const id = rawId.trim()
|
|
372
|
+
|
|
373
|
+
const blockMatch = id.match(/^b(\d+)$/i)
|
|
374
|
+
if (blockMatch) {
|
|
375
|
+
const blockId = parseInt(blockMatch[1]!, 10)
|
|
376
|
+
const block = state.compressionBlocks.find((b) => b.id === blockId && b.active)
|
|
377
|
+
if (!block) throw unknownCompressionIdError(id, state)
|
|
378
|
+
return {
|
|
379
|
+
timestamp: block[field],
|
|
380
|
+
stableId: field === "startTimestamp" ? block.startMessageId : block.endMessageId,
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
const meta = state.messageMetaSnapshot.get(id)
|
|
385
|
+
if (meta) return { timestamp: meta.timestamp, stableId: meta.stableId }
|
|
386
|
+
|
|
387
|
+
const ts = state.messageIdSnapshot.get(id)
|
|
388
|
+
if (ts === undefined) throw unknownCompressionIdError(id, state)
|
|
389
|
+
return { timestamp: ts }
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Determine the anchor timestamp for a compression block — the timestamp of
|
|
394
|
+
* the first raw message that appears strictly after `endTimestamp`.
|
|
395
|
+
*/
|
|
396
|
+
export function resolveAnchorTimestamp(endTimestamp: number, state: DcpState): number {
|
|
397
|
+
return resolveAnchorBoundary(endTimestamp, state).timestamp
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
export function resolveAnchorBoundary(endTimestamp: number, state: DcpState): ResolvedCompressionAnchor {
|
|
401
|
+
let anchor: number | null = null
|
|
402
|
+
let stableId: string | undefined
|
|
403
|
+
for (const meta of state.messageMetaSnapshot.values()) {
|
|
404
|
+
const ts = meta.timestamp
|
|
405
|
+
if (ts > endTimestamp && (anchor === null || ts < anchor)) {
|
|
406
|
+
anchor = ts
|
|
407
|
+
stableId = meta.stableId
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
if (anchor === null) {
|
|
411
|
+
for (const ts of state.messageIdSnapshot.values()) {
|
|
412
|
+
if (ts > endTimestamp && (anchor === null || ts < anchor)) anchor = ts
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
return { timestamp: anchor ?? endTimestamp + 1, stableId }
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
export function createRangeCompressionBlock(
|
|
419
|
+
options: CreateRangeCompressionBlockOptions,
|
|
420
|
+
): CompressionBlockCreationResult {
|
|
421
|
+
const {
|
|
422
|
+
topic,
|
|
423
|
+
summary,
|
|
424
|
+
startTimestamp,
|
|
425
|
+
endTimestamp,
|
|
426
|
+
startMessageId,
|
|
427
|
+
endMessageId,
|
|
428
|
+
state,
|
|
429
|
+
config,
|
|
430
|
+
anchorTimestamp = resolveAnchorBoundary(endTimestamp, state).timestamp,
|
|
431
|
+
anchorMessageId,
|
|
432
|
+
createdByToolCallId,
|
|
433
|
+
mode = "range",
|
|
434
|
+
validatePlaceholders = true,
|
|
435
|
+
expandPlaceholders = true,
|
|
436
|
+
} = options
|
|
437
|
+
|
|
438
|
+
if (startTimestamp > endTimestamp) {
|
|
439
|
+
throw new Error("Compression range start must appear before end in the conversation")
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
if (!Number.isFinite(startTimestamp)) {
|
|
443
|
+
throw new Error(`Compression range start resolved to a non-finite timestamp (${startTimestamp})`)
|
|
444
|
+
}
|
|
445
|
+
if (!Number.isFinite(endTimestamp)) {
|
|
446
|
+
throw new Error(`Compression range end resolved to a non-finite timestamp (${endTimestamp})`)
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
const { coveredBlocks, partialBlocks } = findCoveredAndPartialBlocks(
|
|
450
|
+
startTimestamp,
|
|
451
|
+
endTimestamp,
|
|
452
|
+
state,
|
|
453
|
+
)
|
|
454
|
+
|
|
455
|
+
if (partialBlocks.length > 0) {
|
|
456
|
+
const blockList = partialBlocks.map((block) => `b${block.id} "${block.topic}"`).join(", ")
|
|
457
|
+
throw new Error(
|
|
458
|
+
`Compression range partially overlaps existing block(s): ${blockList}. ` +
|
|
459
|
+
"Select the whole block or choose non-overlapping boundaries.",
|
|
460
|
+
)
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
const placeholderSummary = preparePlaceholderSummary(
|
|
464
|
+
summary,
|
|
465
|
+
coveredBlocks,
|
|
466
|
+
state,
|
|
467
|
+
{ validatePlaceholders, expandPlaceholders },
|
|
468
|
+
)
|
|
469
|
+
|
|
470
|
+
const userPreservedSummary = mode === "range"
|
|
471
|
+
? appendProtectedUserMessages(
|
|
472
|
+
placeholderSummary,
|
|
473
|
+
startTimestamp,
|
|
474
|
+
endTimestamp,
|
|
475
|
+
state,
|
|
476
|
+
config.compress.protectUserMessages,
|
|
477
|
+
)
|
|
478
|
+
: placeholderSummary
|
|
479
|
+
|
|
480
|
+
const promptPreservedSummary = appendProtectedPromptInfo(
|
|
481
|
+
userPreservedSummary,
|
|
482
|
+
startTimestamp,
|
|
483
|
+
endTimestamp,
|
|
484
|
+
state,
|
|
485
|
+
config,
|
|
486
|
+
)
|
|
487
|
+
|
|
488
|
+
const expandedSummary = appendProtectedToolOutputs(
|
|
489
|
+
promptPreservedSummary,
|
|
490
|
+
startTimestamp,
|
|
491
|
+
endTimestamp,
|
|
492
|
+
state,
|
|
493
|
+
config,
|
|
494
|
+
)
|
|
495
|
+
|
|
496
|
+
const block: CompressionBlock = {
|
|
497
|
+
id: state.nextBlockId++,
|
|
498
|
+
topic,
|
|
499
|
+
summary: expandedSummary,
|
|
500
|
+
startTimestamp,
|
|
501
|
+
endTimestamp,
|
|
502
|
+
startMessageId,
|
|
503
|
+
endMessageId,
|
|
504
|
+
anchorTimestamp,
|
|
505
|
+
anchorMessageId,
|
|
506
|
+
createdByToolCallId,
|
|
507
|
+
active: true,
|
|
508
|
+
summaryTokenEstimate: estimateTokens(expandedSummary),
|
|
509
|
+
createdAt: Date.now(),
|
|
510
|
+
coveredBlockIds: coveredBlocks.map((covered) => covered.id),
|
|
511
|
+
mode,
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
state.compressionBlocks.push(block)
|
|
515
|
+
for (const covered of coveredBlocks) {
|
|
516
|
+
covered.active = false
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
return {
|
|
520
|
+
block,
|
|
521
|
+
removedTokenEstimate: estimateVisibleRangeTokens(startTimestamp, endTimestamp, coveredBlocks, state),
|
|
522
|
+
summaryTokenEstimate: Math.max(0, Math.round(block.summaryTokenEstimate ?? 0)),
|
|
523
|
+
}
|
|
524
|
+
}
|