@bubblebrain-ai/bubble 0.0.63 → 0.0.64
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 +437 -11
- package/dist/agent/abort-errors.d.ts +18 -0
- package/dist/agent/abort-errors.js +51 -0
- package/dist/agent/budget-ledger.d.ts +20 -0
- package/dist/agent/budget-ledger.js +45 -0
- package/dist/agent/categories.d.ts +100 -0
- package/dist/agent/categories.js +203 -0
- package/dist/agent/change-tracker.d.ts +40 -0
- package/dist/agent/change-tracker.js +89 -0
- package/dist/agent/child-runner.d.ts +64 -0
- package/dist/agent/child-runner.js +405 -0
- package/dist/agent/input-controller.d.ts +14 -0
- package/dist/agent/input-controller.js +43 -0
- package/dist/agent/internal-reminder-sanitizer.d.ts +25 -0
- package/dist/agent/internal-reminder-sanitizer.js +297 -0
- package/dist/agent/profiles.d.ts +76 -0
- package/dist/agent/profiles.js +526 -0
- package/dist/agent/provider-fingerprint.d.ts +6 -0
- package/dist/agent/provider-fingerprint.js +89 -0
- package/dist/agent/resident-history.d.ts +7 -0
- package/dist/agent/resident-history.js +61 -0
- package/dist/agent/result-integrator.d.ts +22 -0
- package/dist/agent/result-integrator.js +50 -0
- package/dist/agent/routing-catalog.d.ts +131 -0
- package/dist/agent/routing-catalog.js +260 -0
- package/dist/agent/structured-output.d.ts +37 -0
- package/dist/agent/structured-output.js +193 -0
- package/dist/agent/subagent/router.d.ts +65 -0
- package/dist/agent/subagent/router.js +203 -0
- package/dist/agent/subagent/runtime.d.ts +235 -0
- package/dist/agent/subagent/runtime.js +835 -0
- package/dist/agent/subagent-control.d.ts +100 -0
- package/dist/agent/subagent-control.js +70 -0
- package/dist/agent/subagent-lifecycle-reminder.d.ts +3 -0
- package/dist/agent/subagent-lifecycle-reminder.js +112 -0
- package/dist/agent/subagent-route-format.d.ts +8 -0
- package/dist/agent/subagent-route-format.js +18 -0
- package/dist/agent/subagent-scheduler.d.ts +105 -0
- package/dist/agent/subagent-scheduler.js +287 -0
- package/dist/agent/subagent-store.d.ts +57 -0
- package/dist/agent/subagent-store.js +180 -0
- package/dist/agent/subagent-summary.d.ts +30 -0
- package/dist/agent/subagent-summary.js +74 -0
- package/dist/agent/subagent-wait-guidance.d.ts +2 -0
- package/dist/agent/subagent-wait-guidance.js +8 -0
- package/dist/agent/subtask-policy.d.ts +13 -0
- package/dist/agent/subtask-policy.js +56 -0
- package/dist/agent/task-lifecycle-reminder.d.ts +26 -0
- package/dist/agent/task-lifecycle-reminder.js +59 -0
- package/dist/agent/tool-intent.d.ts +45 -0
- package/dist/agent/tool-intent.js +318 -0
- package/dist/agent/tool-visibility.d.ts +10 -0
- package/dist/agent/tool-visibility.js +6 -0
- package/dist/agent/transcript-helpers.d.ts +20 -0
- package/dist/agent/transcript-helpers.js +63 -0
- package/dist/agent/update-queue.d.ts +13 -0
- package/dist/agent/update-queue.js +69 -0
- package/dist/agent/workflow/control.d.ts +60 -0
- package/dist/agent/workflow/control.js +62 -0
- package/dist/agent/workflow/errors.d.ts +16 -0
- package/dist/agent/workflow/errors.js +24 -0
- package/dist/agent/workflow/runs.d.ts +73 -0
- package/dist/agent/workflow/runs.js +160 -0
- package/dist/agent/workflow/runtime.d.ts +88 -0
- package/dist/agent/workflow/runtime.js +319 -0
- package/dist/agent/worktree.d.ts +29 -0
- package/dist/agent/worktree.js +73 -0
- package/dist/agent.d.ts +460 -0
- package/dist/agent.js +2210 -0
- package/dist/anthropic-thinking.d.ts +4 -0
- package/dist/anthropic-thinking.js +11 -0
- package/dist/approval/controller.d.ts +71 -0
- package/dist/approval/controller.js +286 -0
- package/dist/approval/danger.d.ts +13 -0
- package/dist/approval/danger.js +55 -0
- package/dist/approval/diff-hunks.d.ts +12 -0
- package/dist/approval/diff-hunks.js +32 -0
- package/dist/approval/protected-paths.d.ts +1 -0
- package/dist/approval/protected-paths.js +35 -0
- package/dist/approval/session-cache.d.ts +21 -0
- package/dist/approval/session-cache.js +38 -0
- package/dist/approval/tool-helper.d.ts +14 -0
- package/dist/approval/tool-helper.js +47 -0
- package/dist/approval/types.d.ts +146 -0
- package/dist/approval/types.js +8 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +3 -0
- package/dist/bubble-home.d.ts +8 -0
- package/dist/bubble-home.js +19 -0
- package/dist/checkpoints.d.ts +57 -0
- package/dist/checkpoints.js +0 -0
- package/dist/cli.d.ts +37 -0
- package/dist/cli.js +175 -0
- package/dist/clipboard.d.ts +14 -0
- package/dist/clipboard.js +132 -0
- package/dist/config.d.ts +96 -0
- package/dist/config.js +287 -0
- package/dist/context/budget.d.ts +28 -0
- package/dist/context/budget.js +130 -0
- package/dist/context/checkpoint.d.ts +18 -0
- package/dist/context/checkpoint.js +117 -0
- package/dist/context/compact-llm.d.ts +25 -0
- package/dist/context/compact-llm.js +175 -0
- package/dist/context/compact.d.ts +124 -0
- package/dist/context/compact.js +635 -0
- package/dist/context/compaction-files.d.ts +44 -0
- package/dist/context/compaction-files.js +148 -0
- package/dist/context/llm-compactor.d.ts +53 -0
- package/dist/context/llm-compactor.js +424 -0
- package/dist/context/overflow.d.ts +9 -0
- package/dist/context/overflow.js +50 -0
- package/dist/context/projector.d.ts +34 -0
- package/dist/context/projector.js +251 -0
- package/dist/context/prune.d.ts +26 -0
- package/dist/context/prune.js +171 -0
- package/dist/context/session-write-lock.d.ts +20 -0
- package/dist/context/session-write-lock.js +162 -0
- package/dist/context/token-estimator.d.ts +14 -0
- package/dist/context/token-estimator.js +106 -0
- package/dist/context/tool-images.d.ts +3 -0
- package/dist/context/tool-images.js +35 -0
- package/dist/context/tool-output-truncate.d.ts +24 -0
- package/dist/context/tool-output-truncate.js +181 -0
- package/dist/context/usage.d.ts +34 -0
- package/dist/context/usage.js +230 -0
- package/dist/debug-trace.d.ts +27 -0
- package/dist/debug-trace.js +401 -0
- package/dist/diff-stats.d.ts +5 -0
- package/dist/diff-stats.js +21 -0
- package/dist/external-runtime/grok-acp.d.ts +56 -0
- package/dist/external-runtime/grok-acp.js +386 -0
- package/dist/external-runtime/grok-binary.d.ts +25 -0
- package/dist/external-runtime/grok-binary.js +108 -0
- package/dist/external-runtime/grok-errors.d.ts +7 -0
- package/dist/external-runtime/grok-errors.js +15 -0
- package/dist/external-runtime/grok-input-policy.d.ts +58 -0
- package/dist/external-runtime/grok-input-policy.js +52 -0
- package/dist/external-runtime/grok-ndjson.d.ts +14 -0
- package/dist/external-runtime/grok-ndjson.js +193 -0
- package/dist/external-runtime/grok-network.d.ts +15 -0
- package/dist/external-runtime/grok-network.js +81 -0
- package/dist/external-runtime/grok-preflight.d.ts +28 -0
- package/dist/external-runtime/grok-preflight.js +194 -0
- package/dist/external-runtime/grok-process.d.ts +26 -0
- package/dist/external-runtime/grok-process.js +184 -0
- package/dist/external-runtime/grok-profile.d.ts +32 -0
- package/dist/external-runtime/grok-profile.js +419 -0
- package/dist/external-runtime/grok-provider.d.ts +31 -0
- package/dist/external-runtime/grok-provider.js +41 -0
- package/dist/external-runtime/grok-runtime.d.ts +91 -0
- package/dist/external-runtime/grok-runtime.js +882 -0
- package/dist/external-runtime/index.d.ts +13 -0
- package/dist/external-runtime/index.js +13 -0
- package/dist/external-runtime/session-policy.d.ts +11 -0
- package/dist/external-runtime/session-policy.js +30 -0
- package/dist/external-runtime/types.d.ts +65 -0
- package/dist/external-runtime/types.js +1 -0
- package/dist/feedback/collect.d.ts +7 -0
- package/dist/feedback/collect.js +119 -0
- package/dist/feedback/config.d.ts +14 -0
- package/dist/feedback/config.js +16 -0
- package/dist/feedback/redact.d.ts +1 -0
- package/dist/feedback/redact.js +25 -0
- package/dist/feedback/submit.d.ts +6 -0
- package/dist/feedback/submit.js +43 -0
- package/dist/feedback/types.d.ts +22 -0
- package/dist/feedback/types.js +1 -0
- package/dist/feishu/agent-host/approval-card.d.ts +11 -0
- package/dist/feishu/agent-host/approval-card.js +85 -0
- package/dist/feishu/agent-host/approval-ui.d.ts +59 -0
- package/dist/feishu/agent-host/approval-ui.js +214 -0
- package/dist/feishu/agent-host/run-driver.d.ts +51 -0
- package/dist/feishu/agent-host/run-driver.js +397 -0
- package/dist/feishu/agent-host/runtime-deps.d.ts +33 -0
- package/dist/feishu/agent-host/runtime-deps.js +8 -0
- package/dist/feishu/card/budget.d.ts +40 -0
- package/dist/feishu/card/budget.js +134 -0
- package/dist/feishu/card/renderer.d.ts +29 -0
- package/dist/feishu/card/renderer.js +245 -0
- package/dist/feishu/card/run-state-types.d.ts +49 -0
- package/dist/feishu/card/run-state-types.js +15 -0
- package/dist/feishu/card/run-state.d.ts +21 -0
- package/dist/feishu/card/run-state.js +223 -0
- package/dist/feishu/channel/channel.d.ts +52 -0
- package/dist/feishu/channel/channel.js +74 -0
- package/dist/feishu/config.d.ts +24 -0
- package/dist/feishu/config.js +97 -0
- package/dist/feishu/format.d.ts +6 -0
- package/dist/feishu/format.js +14 -0
- package/dist/feishu/index.d.ts +4 -0
- package/dist/feishu/index.js +4 -0
- package/dist/feishu/logger.d.ts +31 -0
- package/dist/feishu/logger.js +62 -0
- package/dist/feishu/paths.d.ts +12 -0
- package/dist/feishu/paths.js +38 -0
- package/dist/feishu/process-registry.d.ts +29 -0
- package/dist/feishu/process-registry.js +90 -0
- package/dist/feishu/router/commands.d.ts +38 -0
- package/dist/feishu/router/commands.js +286 -0
- package/dist/feishu/router/event-router.d.ts +40 -0
- package/dist/feishu/router/event-router.js +208 -0
- package/dist/feishu/router/whitelist.d.ts +23 -0
- package/dist/feishu/router/whitelist.js +20 -0
- package/dist/feishu/runtime/active-runs.d.ts +32 -0
- package/dist/feishu/runtime/active-runs.js +84 -0
- package/dist/feishu/runtime/pending-queue.d.ts +36 -0
- package/dist/feishu/runtime/pending-queue.js +98 -0
- package/dist/feishu/runtime/process-pool.d.ts +29 -0
- package/dist/feishu/runtime/process-pool.js +49 -0
- package/dist/feishu/schema.d.ts +17 -0
- package/dist/feishu/schema.js +252 -0
- package/dist/feishu/scope/scope-registry.d.ts +39 -0
- package/dist/feishu/scope/scope-registry.js +148 -0
- package/dist/feishu/scope/session-binder.d.ts +44 -0
- package/dist/feishu/scope/session-binder.js +100 -0
- package/dist/feishu/scope/session-store.d.ts +24 -0
- package/dist/feishu/scope/session-store.js +73 -0
- package/dist/feishu/secrets.d.ts +37 -0
- package/dist/feishu/secrets.js +129 -0
- package/dist/feishu/serve.d.ts +12 -0
- package/dist/feishu/serve.js +302 -0
- package/dist/feishu/types.d.ts +75 -0
- package/dist/feishu/types.js +23 -0
- package/dist/feishu/wizard.d.ts +24 -0
- package/dist/feishu/wizard.js +121 -0
- package/dist/goal/command.d.ts +20 -0
- package/dist/goal/command.js +76 -0
- package/dist/goal/engine.d.ts +33 -0
- package/dist/goal/engine.js +65 -0
- package/dist/goal/format.d.ts +18 -0
- package/dist/goal/format.js +112 -0
- package/dist/goal/prompts.d.ts +13 -0
- package/dist/goal/prompts.js +84 -0
- package/dist/goal/store.d.ts +64 -0
- package/dist/goal/store.js +174 -0
- package/dist/goal/tools.d.ts +13 -0
- package/dist/goal/tools.js +67 -0
- package/dist/goal/usage.d.ts +2 -0
- package/dist/goal/usage.js +3 -0
- package/dist/hooks/config.d.ts +9 -0
- package/dist/hooks/config.js +278 -0
- package/dist/hooks/controller.d.ts +24 -0
- package/dist/hooks/controller.js +254 -0
- package/dist/hooks/index.d.ts +6 -0
- package/dist/hooks/index.js +4 -0
- package/dist/hooks/log.d.ts +14 -0
- package/dist/hooks/log.js +54 -0
- package/dist/hooks/runner.d.ts +5 -0
- package/dist/hooks/runner.js +225 -0
- package/dist/hooks/trust.d.ts +37 -0
- package/dist/hooks/trust.js +143 -0
- package/dist/hooks/types.d.ts +173 -0
- package/dist/hooks/types.js +46 -0
- package/dist/loop/engine.d.ts +29 -0
- package/dist/loop/engine.js +63 -0
- package/dist/lsp/config.d.ts +18 -0
- package/dist/lsp/config.js +58 -0
- package/dist/lsp/diagnostics.d.ts +24 -0
- package/dist/lsp/diagnostics.js +103 -0
- package/dist/lsp/index.d.ts +3 -0
- package/dist/lsp/index.js +3 -0
- package/dist/lsp/service.d.ts +97 -0
- package/dist/lsp/service.js +815 -0
- package/dist/main.d.ts +5 -0
- package/dist/main.js +984 -0
- package/dist/mcp/client.d.ts +68 -0
- package/dist/mcp/client.js +177 -0
- package/dist/mcp/config.d.ts +30 -0
- package/dist/mcp/config.js +144 -0
- package/dist/mcp/manager.d.ts +67 -0
- package/dist/mcp/manager.js +328 -0
- package/dist/mcp/name.d.ts +26 -0
- package/dist/mcp/name.js +40 -0
- package/dist/mcp/transports.d.ts +54 -0
- package/dist/mcp/transports.js +267 -0
- package/dist/mcp/types.d.ts +111 -0
- package/dist/mcp/types.js +14 -0
- package/dist/memory/db.d.ts +65 -0
- package/dist/memory/db.js +332 -0
- package/dist/memory/index.d.ts +10 -0
- package/dist/memory/index.js +10 -0
- package/dist/memory/paths.d.ts +18 -0
- package/dist/memory/paths.js +38 -0
- package/dist/memory/phase1.d.ts +23 -0
- package/dist/memory/phase1.js +292 -0
- package/dist/memory/phase2.d.ts +19 -0
- package/dist/memory/phase2.js +119 -0
- package/dist/memory/prompts.d.ts +19 -0
- package/dist/memory/prompts.js +104 -0
- package/dist/memory/reset.d.ts +1 -0
- package/dist/memory/reset.js +13 -0
- package/dist/memory/session-policy.d.ts +25 -0
- package/dist/memory/session-policy.js +55 -0
- package/dist/memory/start.d.ts +24 -0
- package/dist/memory/start.js +50 -0
- package/dist/memory/storage.d.ts +11 -0
- package/dist/memory/storage.js +95 -0
- package/dist/memory/store.d.ts +43 -0
- package/dist/memory/store.js +193 -0
- package/dist/memory/usage.d.ts +1 -0
- package/dist/memory/usage.js +38 -0
- package/dist/model-catalog.d.ts +65 -0
- package/dist/model-catalog.js +387 -0
- package/dist/model-config.d.ts +40 -0
- package/dist/model-config.js +74 -0
- package/dist/model-data.generated.d.ts +16 -0
- package/dist/model-data.generated.js +275 -0
- package/dist/model-pricing.d.ts +54 -0
- package/dist/model-pricing.js +244 -0
- package/dist/model-selection.d.ts +7 -0
- package/dist/model-selection.js +18 -0
- package/dist/network/chatgpt-transport.d.ts +16 -0
- package/dist/network/chatgpt-transport.js +232 -0
- package/dist/network/errors.d.ts +47 -0
- package/dist/network/errors.js +48 -0
- package/dist/network/provider-transport-log.d.ts +12 -0
- package/dist/network/provider-transport-log.js +32 -0
- package/dist/network/provider-transport.d.ts +37 -0
- package/dist/network/provider-transport.js +256 -0
- package/dist/network/retry.d.ts +34 -0
- package/dist/network/retry.js +97 -0
- package/dist/network/system-proxy.d.ts +18 -0
- package/dist/network/system-proxy.js +175 -0
- package/dist/oauth/grok.d.ts +26 -0
- package/dist/oauth/grok.js +251 -0
- package/dist/oauth/index.d.ts +4 -0
- package/dist/oauth/index.js +3 -0
- package/dist/oauth/openai-codex.d.ts +15 -0
- package/dist/oauth/openai-codex.js +193 -0
- package/dist/oauth/refresh-control.d.ts +12 -0
- package/dist/oauth/refresh-control.js +42 -0
- package/dist/oauth/storage.d.ts +88 -0
- package/dist/oauth/storage.js +357 -0
- package/dist/oauth/types.d.ts +15 -0
- package/dist/oauth/types.js +1 -0
- package/dist/orchestrator/default-hooks.d.ts +22 -0
- package/dist/orchestrator/default-hooks.js +127 -0
- package/dist/orchestrator/hooks.d.ts +69 -0
- package/dist/orchestrator/hooks.js +52 -0
- package/dist/permission/mode.d.ts +19 -0
- package/dist/permission/mode.js +16 -0
- package/dist/permissions/rule.d.ts +42 -0
- package/dist/permissions/rule.js +293 -0
- package/dist/permissions/settings.d.ts +97 -0
- package/dist/permissions/settings.js +289 -0
- package/dist/permissions/shell-command.d.ts +36 -0
- package/dist/permissions/shell-command.js +226 -0
- package/dist/permissions/trust-prompt.d.ts +10 -0
- package/dist/permissions/trust-prompt.js +34 -0
- package/dist/permissions/trust.d.ts +26 -0
- package/dist/permissions/trust.js +113 -0
- package/dist/permissions/types.d.ts +61 -0
- package/dist/permissions/types.js +14 -0
- package/dist/print-output.d.ts +98 -0
- package/dist/print-output.js +117 -0
- package/dist/prompt/compose.d.ts +19 -0
- package/dist/prompt/compose.js +110 -0
- package/dist/prompt/delegation.d.ts +14 -0
- package/dist/prompt/delegation.js +100 -0
- package/dist/prompt/environment.d.ts +12 -0
- package/dist/prompt/environment.js +55 -0
- package/dist/prompt/provider-prompts/anthropic.d.ts +1 -0
- package/dist/prompt/provider-prompts/anthropic.js +5 -0
- package/dist/prompt/provider-prompts/codex.d.ts +1 -0
- package/dist/prompt/provider-prompts/codex.js +5 -0
- package/dist/prompt/provider-prompts/deepseek.d.ts +1 -0
- package/dist/prompt/provider-prompts/deepseek.js +7 -0
- package/dist/prompt/provider-prompts/default.d.ts +1 -0
- package/dist/prompt/provider-prompts/default.js +6 -0
- package/dist/prompt/provider-prompts/gemini.d.ts +1 -0
- package/dist/prompt/provider-prompts/gemini.js +5 -0
- package/dist/prompt/provider-prompts/glm.d.ts +1 -0
- package/dist/prompt/provider-prompts/glm.js +7 -0
- package/dist/prompt/provider-prompts/gpt.d.ts +1 -0
- package/dist/prompt/provider-prompts/gpt.js +5 -0
- package/dist/prompt/provider-prompts/kimi.d.ts +1 -0
- package/dist/prompt/provider-prompts/kimi.js +8 -0
- package/dist/prompt/reminders.d.ts +33 -0
- package/dist/prompt/reminders.js +135 -0
- package/dist/prompt/routing.d.ts +14 -0
- package/dist/prompt/routing.js +71 -0
- package/dist/prompt/runtime.d.ts +12 -0
- package/dist/prompt/runtime.js +40 -0
- package/dist/prompt/task-reminders.d.ts +12 -0
- package/dist/prompt/task-reminders.js +64 -0
- package/dist/provider-ai-sdk.d.ts +59 -0
- package/dist/provider-ai-sdk.js +541 -0
- package/dist/provider-anthropic.d.ts +126 -0
- package/dist/provider-anthropic.js +940 -0
- package/dist/provider-ark-responses.d.ts +29 -0
- package/dist/provider-ark-responses.js +518 -0
- package/dist/provider-artifacts.d.ts +7 -0
- package/dist/provider-artifacts.js +60 -0
- package/dist/provider-error-record.d.ts +43 -0
- package/dist/provider-error-record.js +213 -0
- package/dist/provider-grok.d.ts +50 -0
- package/dist/provider-grok.js +110 -0
- package/dist/provider-model-policy.d.ts +16 -0
- package/dist/provider-model-policy.js +33 -0
- package/dist/provider-openai-codex.d.ts +66 -0
- package/dist/provider-openai-codex.js +781 -0
- package/dist/provider-registry.d.ts +197 -0
- package/dist/provider-registry.js +1194 -0
- package/dist/provider-transform.d.ts +12 -0
- package/dist/provider-transform.js +293 -0
- package/dist/provider-zen-errors.d.ts +9 -0
- package/dist/provider-zen-errors.js +36 -0
- package/dist/provider.d.ts +85 -0
- package/dist/provider.js +925 -0
- package/dist/question/controller.d.ts +22 -0
- package/dist/question/controller.js +98 -0
- package/dist/question/index.d.ts +2 -0
- package/dist/question/index.js +2 -0
- package/dist/question/normalize.d.ts +6 -0
- package/dist/question/normalize.js +11 -0
- package/dist/question/types.d.ts +42 -0
- package/dist/question/types.js +6 -0
- package/dist/reasoning-debug.d.ts +7 -0
- package/dist/reasoning-debug.js +33 -0
- package/dist/rewind.d.ts +20 -0
- package/dist/rewind.js +29 -0
- package/dist/sdk/index.d.ts +319 -0
- package/dist/sdk/index.js +1068 -0
- package/dist/sdk/replay-event-log.d.ts +26 -0
- package/dist/sdk/replay-event-log.js +122 -0
- package/dist/sdk/session-turn-coordinator.d.ts +45 -0
- package/dist/sdk/session-turn-coordinator.js +227 -0
- package/dist/session-context-fence.d.ts +16 -0
- package/dist/session-context-fence.js +26 -0
- package/dist/session-log.d.ts +25 -0
- package/dist/session-log.js +444 -0
- package/dist/session-title.d.ts +16 -0
- package/dist/session-title.js +131 -0
- package/dist/session-types.d.ts +86 -0
- package/dist/session-types.js +1 -0
- package/dist/session.d.ts +135 -0
- package/dist/session.js +664 -0
- package/dist/skills/discovery.d.ts +12 -0
- package/dist/skills/discovery.js +166 -0
- package/dist/skills/format.d.ts +32 -0
- package/dist/skills/format.js +68 -0
- package/dist/skills/frontmatter.d.ts +5 -0
- package/dist/skills/frontmatter.js +60 -0
- package/dist/skills/invocation.d.ts +8 -0
- package/dist/skills/invocation.js +33 -0
- package/dist/skills/registry.d.ts +28 -0
- package/dist/skills/registry.js +79 -0
- package/dist/skills/types.d.ts +34 -0
- package/dist/skills/types.js +1 -0
- package/dist/slash-commands/commands.d.ts +10 -0
- package/dist/slash-commands/commands.js +1251 -0
- package/dist/slash-commands/feishu.d.ts +17 -0
- package/dist/slash-commands/feishu.js +400 -0
- package/dist/slash-commands/index.d.ts +4 -0
- package/dist/slash-commands/index.js +8 -0
- package/dist/slash-commands/registry.d.ts +32 -0
- package/dist/slash-commands/registry.js +73 -0
- package/dist/slash-commands/types.d.ts +109 -0
- package/dist/slash-commands/types.js +1 -0
- package/dist/slash-commands/unified.d.ts +38 -0
- package/dist/slash-commands/unified.js +38 -0
- package/dist/stats/usage.d.ts +59 -0
- package/dist/stats/usage.js +485 -0
- package/dist/stream-json.d.ts +13 -0
- package/dist/stream-json.js +74 -0
- package/dist/system-prompt.d.ts +40 -0
- package/dist/system-prompt.js +7 -0
- package/dist/tasks/manager.d.ts +145 -0
- package/dist/tasks/manager.js +634 -0
- package/dist/tasks/process-utils.d.ts +10 -0
- package/dist/tasks/process-utils.js +49 -0
- package/dist/tasks/promotion.d.ts +17 -0
- package/dist/tasks/promotion.js +30 -0
- package/dist/tasks/wake.d.ts +53 -0
- package/dist/tasks/wake.js +125 -0
- package/dist/text-display.d.ts +3 -0
- package/dist/text-display.js +25 -0
- package/dist/tools/agent-lifecycle.d.ts +30 -0
- package/dist/tools/agent-lifecycle.js +790 -0
- package/dist/tools/bash.d.ts +23 -0
- package/dist/tools/bash.js +443 -0
- package/dist/tools/child-tools.d.ts +41 -0
- package/dist/tools/child-tools.js +122 -0
- package/dist/tools/edit-apply.d.ts +25 -0
- package/dist/tools/edit-apply.js +274 -0
- package/dist/tools/edit.d.ts +18 -0
- package/dist/tools/edit.js +200 -0
- package/dist/tools/exa-mcp.d.ts +3 -0
- package/dist/tools/exa-mcp.js +74 -0
- package/dist/tools/exit-plan-mode.d.ts +22 -0
- package/dist/tools/exit-plan-mode.js +79 -0
- package/dist/tools/file-mutation-queue.d.ts +2 -0
- package/dist/tools/file-mutation-queue.js +43 -0
- package/dist/tools/file-state.d.ts +48 -0
- package/dist/tools/file-state.js +76 -0
- package/dist/tools/grep.d.ts +9 -0
- package/dist/tools/grep.js +387 -0
- package/dist/tools/index.d.ts +63 -0
- package/dist/tools/index.js +76 -0
- package/dist/tools/ls.d.ts +3 -0
- package/dist/tools/ls.js +85 -0
- package/dist/tools/lsp.d.ts +4 -0
- package/dist/tools/lsp.js +95 -0
- package/dist/tools/memory.d.ts +8 -0
- package/dist/tools/memory.js +77 -0
- package/dist/tools/path-utils.d.ts +8 -0
- package/dist/tools/path-utils.js +53 -0
- package/dist/tools/prompt-metadata.d.ts +3 -0
- package/dist/tools/prompt-metadata.js +17 -0
- package/dist/tools/question.d.ts +3 -0
- package/dist/tools/question.js +177 -0
- package/dist/tools/read.d.ts +8 -0
- package/dist/tools/read.js +309 -0
- package/dist/tools/sensitive-paths.d.ts +11 -0
- package/dist/tools/sensitive-paths.js +106 -0
- package/dist/tools/server-manager.d.ts +6 -0
- package/dist/tools/server-manager.js +6 -0
- package/dist/tools/server.d.ts +6 -0
- package/dist/tools/server.js +249 -0
- package/dist/tools/skill-search.d.ts +10 -0
- package/dist/tools/skill-search.js +134 -0
- package/dist/tools/skill.d.ts +7 -0
- package/dist/tools/skill.js +81 -0
- package/dist/tools/task-tools.d.ts +10 -0
- package/dist/tools/task-tools.js +133 -0
- package/dist/tools/tool-search.d.ts +23 -0
- package/dist/tools/tool-search.js +145 -0
- package/dist/tools/web-fetch.d.ts +6 -0
- package/dist/tools/web-fetch.js +76 -0
- package/dist/tools/web-search.d.ts +5 -0
- package/dist/tools/web-search.js +50 -0
- package/dist/tools/write.d.ts +10 -0
- package/dist/tools/write.js +155 -0
- package/dist/tui/animation-clock.d.ts +14 -0
- package/dist/tui/animation-clock.js +34 -0
- package/dist/tui/app.d.ts +176 -0
- package/dist/tui/app.js +1659 -0
- package/dist/tui/components/approval-dialog.d.ts +43 -0
- package/dist/tui/components/approval-dialog.js +212 -0
- package/dist/tui/components/bottom-sheet.d.ts +9 -0
- package/dist/tui/components/bottom-sheet.js +32 -0
- package/dist/tui/components/context-info.d.ts +54 -0
- package/dist/tui/components/context-info.js +388 -0
- package/dist/tui/components/feedback-dialog.d.ts +56 -0
- package/dist/tui/components/feedback-dialog.js +262 -0
- package/dist/tui/components/feishu-setup-dialog.d.ts +65 -0
- package/dist/tui/components/feishu-setup-dialog.js +332 -0
- package/dist/tui/components/image-preview.d.ts +32 -0
- package/dist/tui/components/image-preview.js +130 -0
- package/dist/tui/components/plan-dialog.d.ts +34 -0
- package/dist/tui/components/plan-dialog.js +196 -0
- package/dist/tui/components/provider-key-input.d.ts +18 -0
- package/dist/tui/components/provider-key-input.js +49 -0
- package/dist/tui/components/question-dialog.d.ts +25 -0
- package/dist/tui/components/question-dialog.js +263 -0
- package/dist/tui/components/responsive-transcript.d.ts +31 -0
- package/dist/tui/components/responsive-transcript.js +77 -0
- package/dist/tui/components/rewind-picker.d.ts +62 -0
- package/dist/tui/components/rewind-picker.js +317 -0
- package/dist/tui/components/session-picker.d.ts +49 -0
- package/dist/tui/components/session-picker.js +303 -0
- package/dist/tui/components/skills-panel.d.ts +63 -0
- package/dist/tui/components/skills-panel.js +582 -0
- package/dist/tui/components/stats-panel.d.ts +40 -0
- package/dist/tui/components/stats-panel.js +301 -0
- package/dist/tui/components/streaming-message.d.ts +69 -0
- package/dist/tui/components/streaming-message.js +398 -0
- package/dist/tui/components/subagent-inspector.d.ts +28 -0
- package/dist/tui/components/subagent-inspector.js +127 -0
- package/dist/tui/components/task-inspector.d.ts +26 -0
- package/dist/tui/components/task-inspector.js +70 -0
- package/dist/tui/components/tasks-pane.d.ts +126 -0
- package/dist/tui/components/tasks-pane.js +566 -0
- package/dist/tui/components/transcript.d.ts +103 -0
- package/dist/tui/components/transcript.js +858 -0
- package/dist/tui/components/welcome.d.ts +20 -0
- package/dist/tui/components/welcome.js +133 -0
- package/dist/tui/components/workflow-inspector.d.ts +30 -0
- package/dist/tui/components/workflow-inspector.js +136 -0
- package/dist/tui/composer-autocomplete.d.ts +76 -0
- package/dist/tui/composer-autocomplete.js +465 -0
- package/dist/tui/composer-style.d.ts +7 -0
- package/dist/tui/composer-style.js +29 -0
- package/dist/tui/controller/agent-event-reducer.d.ts +75 -0
- package/dist/tui/controller/agent-event-reducer.js +239 -0
- package/dist/tui/controller/composer-controller.d.ts +95 -0
- package/dist/tui/controller/composer-controller.js +502 -0
- package/dist/tui/controller/controller.d.ts +199 -0
- package/dist/tui/controller/controller.js +1034 -0
- package/dist/tui/controller/effects.d.ts +71 -0
- package/dist/tui/controller/effects.js +1 -0
- package/dist/tui/controller/goal-runtime-controller.d.ts +47 -0
- package/dist/tui/controller/goal-runtime-controller.js +202 -0
- package/dist/tui/controller/input-queue-machine.d.ts +71 -0
- package/dist/tui/controller/input-queue-machine.js +121 -0
- package/dist/tui/controller/intents.d.ts +56 -0
- package/dist/tui/controller/intents.js +6 -0
- package/dist/tui/controller/overlay-controller.d.ts +64 -0
- package/dist/tui/controller/overlay-controller.js +129 -0
- package/dist/tui/controller/ports.d.ts +57 -0
- package/dist/tui/controller/ports.js +9 -0
- package/dist/tui/controller/session-transition.d.ts +54 -0
- package/dist/tui/controller/session-transition.js +68 -0
- package/dist/tui/controller/state.d.ts +14 -0
- package/dist/tui/controller/state.js +36 -0
- package/dist/tui/controller/task-runtime-controller.d.ts +66 -0
- package/dist/tui/controller/task-runtime-controller.js +158 -0
- package/dist/tui/detect-theme.d.ts +4 -0
- package/dist/tui/detect-theme.js +116 -0
- package/dist/tui/display-history.d.ts +64 -0
- package/dist/tui/display-history.js +283 -0
- package/dist/tui/display-sanitizer.d.ts +3 -0
- package/dist/tui/display-sanitizer.js +38 -0
- package/dist/tui/edit-diff.d.ts +11 -0
- package/dist/tui/edit-diff.js +57 -0
- package/dist/tui/file-mentions.d.ts +29 -0
- package/dist/tui/file-mentions.js +174 -0
- package/dist/tui/footer.d.ts +37 -0
- package/dist/tui/footer.js +80 -0
- package/dist/tui/formatting/edit-diff.d.ts +11 -0
- package/dist/tui/formatting/edit-diff.js +52 -0
- package/dist/tui/formatting/summary.d.ts +43 -0
- package/dist/tui/formatting/summary.js +150 -0
- package/dist/tui/fullscreen.d.ts +48 -0
- package/dist/tui/fullscreen.js +256 -0
- package/dist/tui/image-display.d.ts +23 -0
- package/dist/tui/image-display.js +92 -0
- package/dist/tui/image-paste.d.ts +113 -0
- package/dist/tui/image-paste.js +565 -0
- package/dist/tui/input-history.d.ts +47 -0
- package/dist/tui/input-history.js +250 -0
- package/dist/tui/markdown-style.d.ts +5 -0
- package/dist/tui/markdown-style.js +23 -0
- package/dist/tui/model/composer-buffer.d.ts +55 -0
- package/dist/tui/model/composer-buffer.js +317 -0
- package/dist/tui/model/composer-types.d.ts +17 -0
- package/dist/tui/model/composer-types.js +1 -0
- package/dist/tui/model/display-history.d.ts +78 -0
- package/dist/tui/model/display-history.js +124 -0
- package/dist/tui/model/display-reconstruct.d.ts +3 -0
- package/dist/tui/model/display-reconstruct.js +130 -0
- package/dist/tui/model/file-mentions.d.ts +31 -0
- package/dist/tui/model/file-mentions.js +178 -0
- package/dist/tui/model/image-attachment.d.ts +15 -0
- package/dist/tui/model/image-attachment.js +1 -0
- package/dist/tui/model/image-paste.d.ts +119 -0
- package/dist/tui/model/image-paste.js +610 -0
- package/dist/tui/model/input-history.d.ts +1 -0
- package/dist/tui/model/input-history.js +1 -0
- package/dist/tui/model/input-queue.d.ts +12 -0
- package/dist/tui/model/input-queue.js +17 -0
- package/dist/tui/model/key-events.d.ts +9 -0
- package/dist/tui/model/key-events.js +8 -0
- package/dist/tui/model/paste-operation-tracker.d.ts +13 -0
- package/dist/tui/model/paste-operation-tracker.js +25 -0
- package/dist/tui/model/recent-activity.d.ts +8 -0
- package/dist/tui/model/recent-activity.js +71 -0
- package/dist/tui/model/subagent-view.d.ts +87 -0
- package/dist/tui/model/subagent-view.js +336 -0
- package/dist/tui/model/submit-dedupe.d.ts +5 -0
- package/dist/tui/model/submit-dedupe.js +25 -0
- package/dist/tui/model/sync-output.d.ts +17 -0
- package/dist/tui/model/sync-output.js +35 -0
- package/dist/tui/model/task-lifecycle.d.ts +57 -0
- package/dist/tui/model/task-lifecycle.js +124 -0
- package/dist/tui/model/terminal-env.d.ts +15 -0
- package/dist/tui/model/terminal-env.js +22 -0
- package/dist/tui/model/terminal-mouse.d.ts +28 -0
- package/dist/tui/model/terminal-mouse.js +82 -0
- package/dist/tui/model/theme-style.d.ts +10 -0
- package/dist/tui/model/theme-style.js +79 -0
- package/dist/tui/model/theme.d.ts +72 -0
- package/dist/tui/model/theme.js +121 -0
- package/dist/tui/model/trace-groups.d.ts +45 -0
- package/dist/tui/model/trace-groups.js +558 -0
- package/dist/tui/model/trace-interaction.d.ts +63 -0
- package/dist/tui/model/trace-interaction.js +87 -0
- package/dist/tui/model/width.d.ts +18 -0
- package/dist/tui/model/width.js +130 -0
- package/dist/tui/model-picker-data.d.ts +9 -0
- package/dist/tui/model-picker-data.js +39 -0
- package/dist/tui/model-switch.d.ts +49 -0
- package/dist/tui/model-switch.js +67 -0
- package/dist/tui/paste-placeholder.d.ts +11 -0
- package/dist/tui/paste-placeholder.js +52 -0
- package/dist/tui/recent-activity.d.ts +8 -0
- package/dist/tui/recent-activity.js +71 -0
- package/dist/tui/run-session-picker.d.ts +9 -0
- package/dist/tui/run-session-picker.js +64 -0
- package/dist/tui/run.d.ts +72 -0
- package/dist/tui/run.js +139 -0
- package/dist/tui/session-display.d.ts +6 -0
- package/dist/tui/session-display.js +12 -0
- package/dist/tui/session-picker-data.d.ts +18 -0
- package/dist/tui/session-picker-data.js +21 -0
- package/dist/tui/terminal/multiplexer.d.ts +5 -0
- package/dist/tui/terminal/multiplexer.js +14 -0
- package/dist/tui/testing/fake-agent.d.ts +24 -0
- package/dist/tui/testing/fake-agent.js +22 -0
- package/dist/tui/testing/spy-host.d.ts +21 -0
- package/dist/tui/testing/spy-host.js +55 -0
- package/dist/tui/trace-groups.d.ts +43 -0
- package/dist/tui/trace-groups.js +554 -0
- package/dist/tui/wordmark.d.ts +18 -0
- package/dist/tui/wordmark.js +208 -0
- package/dist/types.d.ts +503 -0
- package/dist/types.js +4 -0
- package/dist/update/index.d.ts +61 -0
- package/dist/update/index.js +267 -0
- package/dist/variant/thinking-level.d.ts +5 -0
- package/dist/variant/thinking-level.js +26 -0
- package/dist/variant/variant-resolver.d.ts +28 -0
- package/dist/variant/variant-resolver.js +62 -0
- package/node_modules/@bubblebrain-ai/pi-tui/LICENSE +21 -0
- package/node_modules/@bubblebrain-ai/pi-tui/README.md +854 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/alt-screen-search.d.ts +26 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/alt-screen-search.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/alt-screen-search.js +121 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/alt-screen-search.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/autocomplete.d.ts +86 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/autocomplete.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/autocomplete.js +649 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/autocomplete.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/alt-screen-flash.d.ts +13 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/alt-screen-flash.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/alt-screen-flash.js +36 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/alt-screen-flash.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/box.d.ts +22 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/box.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/box.js +99 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/box.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/cancellable-loader.d.ts +22 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/cancellable-loader.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/cancellable-loader.js +36 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/cancellable-loader.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/editor.d.ts +330 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/editor.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/editor.js +2344 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/editor.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/h-stack.d.ts +7 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/h-stack.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/h-stack.js +43 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/h-stack.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/image.d.ts +28 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/image.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/image.js +82 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/image.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/input.d.ts +48 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/input.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/input.js +390 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/input.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/loader.d.ts +31 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/loader.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/loader.js +67 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/loader.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/markdown.d.ts +103 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/markdown.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/markdown.js +797 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/markdown.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/scroll-view.d.ts +56 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/scroll-view.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/scroll-view.js +179 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/scroll-view.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/select-list.d.ts +53 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/select-list.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/select-list.js +175 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/select-list.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/settings-list.d.ts +50 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/settings-list.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/settings-list.js +174 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/settings-list.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/spacer.d.ts +12 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/spacer.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/spacer.js +22 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/spacer.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/stack.d.ts +32 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/stack.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/stack.js +109 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/stack.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/text.d.ts +19 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/text.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/text.js +81 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/text.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/truncated-text.d.ts +13 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/truncated-text.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/truncated-text.js +48 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/truncated-text.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/v-stack.d.ts +8 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/v-stack.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/v-stack.js +26 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/v-stack.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/editor-component.d.ts +39 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/editor-component.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/editor-component.js +2 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/editor-component.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/fuzzy.d.ts +16 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/fuzzy.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/fuzzy.js +110 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/fuzzy.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/index.d.ts +31 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/index.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/index.js +42 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/index.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keybindings.d.ts +273 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keybindings.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keybindings.js +231 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keybindings.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keys.d.ts +184 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keys.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keys.js +1174 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keys.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/kill-ring.d.ts +28 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/kill-ring.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/kill-ring.js +46 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/kill-ring.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/latex.d.ts +10 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/latex.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/latex.js +1268 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/latex.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout-node.d.ts +40 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout-node.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout-node.js +6 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout-node.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout.d.ts +42 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout.js +335 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/native-modifiers.d.ts +3 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/native-modifiers.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/native-modifiers.js +60 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/native-modifiers.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/stdin-buffer.d.ts +56 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/stdin-buffer.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/stdin-buffer.js +363 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/stdin-buffer.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-colors.d.ts +10 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-colors.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-colors.js +59 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-colors.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-image.d.ts +116 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-image.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-image.js +518 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-image.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal.d.ts +142 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal.js +544 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/testing.d.ts +11 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/testing.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/testing.js +11 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/testing.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-alt-screen.d.ts +141 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-alt-screen.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-alt-screen.js +1340 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-alt-screen.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-main-screen.d.ts +39 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-main-screen.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-main-screen.js +536 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-main-screen.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui.d.ts +340 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui.js +1020 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/undo-stack.d.ts +17 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/undo-stack.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/undo-stack.js +27 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/undo-stack.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/utils.d.ts +96 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/utils.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/utils.js +1193 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/utils.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/word-navigation.d.ts +25 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/word-navigation.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/word-navigation.js +96 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/word-navigation.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/test/virtual-terminal.d.ts +73 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/test/virtual-terminal.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/test/virtual-terminal.js +188 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/test/virtual-terminal.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/native/darwin/README.md +20 -0
- package/node_modules/@bubblebrain-ai/pi-tui/native/darwin/build.sh +62 -0
- package/node_modules/@bubblebrain-ai/pi-tui/native/darwin/prebuilds/darwin-arm64/darwin-modifiers.node +0 -0
- package/node_modules/@bubblebrain-ai/pi-tui/native/darwin/prebuilds/darwin-x64/darwin-modifiers.node +0 -0
- package/node_modules/@bubblebrain-ai/pi-tui/native/darwin/src/darwin-modifiers.c +70 -0
- package/node_modules/@bubblebrain-ai/pi-tui/native/win32/README.md +22 -0
- package/node_modules/@bubblebrain-ai/pi-tui/native/win32/build.mjs +229 -0
- package/node_modules/@bubblebrain-ai/pi-tui/native/win32/prebuilds/win32-arm64/win32-console-mode.node +0 -0
- package/node_modules/@bubblebrain-ai/pi-tui/native/win32/prebuilds/win32-x64/win32-console-mode.node +0 -0
- package/node_modules/@bubblebrain-ai/pi-tui/native/win32/src/win32-console-mode.c +119 -0
- package/node_modules/@bubblebrain-ai/pi-tui/package.json +66 -0
- package/node_modules/get-east-asian-width/index.d.ts +60 -0
- package/node_modules/get-east-asian-width/index.js +30 -0
- package/node_modules/get-east-asian-width/license +9 -0
- package/node_modules/get-east-asian-width/lookup-data.js +21 -0
- package/node_modules/get-east-asian-width/lookup.js +138 -0
- package/node_modules/get-east-asian-width/package.json +71 -0
- package/node_modules/get-east-asian-width/readme.md +65 -0
- package/node_modules/get-east-asian-width/utilities.js +24 -0
- package/node_modules/marked/LICENSE +44 -0
- package/node_modules/marked/README.md +115 -0
- package/node_modules/marked/bin/main.js +284 -0
- package/node_modules/marked/bin/marked.js +16 -0
- package/node_modules/marked/lib/marked.d.ts +760 -0
- package/node_modules/marked/lib/marked.esm.js +77 -0
- package/node_modules/marked/lib/marked.esm.js.map +7 -0
- package/node_modules/marked/lib/marked.umd.js +79 -0
- package/node_modules/marked/lib/marked.umd.js.map +7 -0
- package/node_modules/marked/man/marked.1 +113 -0
- package/node_modules/marked/man/marked.1.md +93 -0
- package/node_modules/marked/package.json +103 -0
- package/package.json +96 -17
- package/bin/bubble.js +0 -39
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cumulative file-operation tracking across compactions.
|
|
3
|
+
*
|
|
4
|
+
* The LLM summary handles semantics (progress, decisions, next steps); which
|
|
5
|
+
* files were touched is an enumerable fact the model reliably drops after a
|
|
6
|
+
* couple of rolling summaries. So it never goes through the model: at each
|
|
7
|
+
* compaction, deterministic code extracts file ops from the evicted messages,
|
|
8
|
+
* unions them with the lists the previous summary carried, and appends the
|
|
9
|
+
* result as structured blocks after the summary text.
|
|
10
|
+
*
|
|
11
|
+
* Robustness rules (each earned by a review finding):
|
|
12
|
+
* - appendFileBlocks sanitizes its input first, so a summary can never carry
|
|
13
|
+
* two generations of blocks — or model-echoed tags — at once.
|
|
14
|
+
* - Only tool calls with a successful result count: a rejected or failed edit
|
|
15
|
+
* must not report the file as modified.
|
|
16
|
+
* - Lists are capped; modified entries are the ones worth keeping complete.
|
|
17
|
+
* - Serialization is sorted and deduped so identical sets are identical bytes.
|
|
18
|
+
*/
|
|
19
|
+
const READ_TOOLS = new Set(["read"]);
|
|
20
|
+
const MODIFY_TOOLS = new Set(["edit", "write"]);
|
|
21
|
+
/** Cap per list. Modified is the higher-value list; both stay bounded. */
|
|
22
|
+
const MAX_FILES_PER_LIST = 200;
|
|
23
|
+
const MORE_MARKER = /^\(\+\d+ more\)$/;
|
|
24
|
+
const READ_BLOCKS = /<read-files>[\s\S]*?<\/read-files>/g;
|
|
25
|
+
const MODIFIED_BLOCKS = /<modified-files>[\s\S]*?<\/modified-files>/g;
|
|
26
|
+
/** Stray (unpaired / model-echoed) tags left after full blocks are removed. */
|
|
27
|
+
const STRAY_TAGS = /<\/?(?:read|modified)-files>/g;
|
|
28
|
+
/**
|
|
29
|
+
* File ops mentioned by tool calls in the given (about-to-be-evicted)
|
|
30
|
+
* messages. A call only counts when its tool result is present and not an
|
|
31
|
+
* error — a rejected edit or failed read must not enter the record.
|
|
32
|
+
*/
|
|
33
|
+
export function extractFileOps(messages) {
|
|
34
|
+
const succeeded = new Set();
|
|
35
|
+
for (const message of messages) {
|
|
36
|
+
if (message.role === "tool" && !message.isError)
|
|
37
|
+
succeeded.add(message.toolCallId);
|
|
38
|
+
}
|
|
39
|
+
const read = new Set();
|
|
40
|
+
const modified = new Set();
|
|
41
|
+
for (const message of messages) {
|
|
42
|
+
if (message.role !== "assistant" || !message.toolCalls)
|
|
43
|
+
continue;
|
|
44
|
+
for (const toolCall of message.toolCalls) {
|
|
45
|
+
if (!succeeded.has(toolCall.id))
|
|
46
|
+
continue;
|
|
47
|
+
const target = READ_TOOLS.has(toolCall.name)
|
|
48
|
+
? read
|
|
49
|
+
: MODIFY_TOOLS.has(toolCall.name)
|
|
50
|
+
? modified
|
|
51
|
+
: undefined;
|
|
52
|
+
if (!target)
|
|
53
|
+
continue;
|
|
54
|
+
const path = pathFromArguments(toolCall.arguments);
|
|
55
|
+
if (path)
|
|
56
|
+
target.add(path);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return { read: [...read], modified: [...modified] };
|
|
60
|
+
}
|
|
61
|
+
/** Parse every block a previous compaction summary carried (empty when absent). */
|
|
62
|
+
export function parseFileBlocks(text) {
|
|
63
|
+
return {
|
|
64
|
+
read: parseBlocks(text, READ_BLOCKS, "<read-files>", "</read-files>"),
|
|
65
|
+
modified: parseBlocks(text, MODIFIED_BLOCKS, "<modified-files>", "</modified-files>"),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Remove all blocks AND stray tags, e.g. before feeding a prior summary back
|
|
70
|
+
* to the model. Whitespace is only reflowed when something was removed.
|
|
71
|
+
*/
|
|
72
|
+
export function stripFileBlocks(text) {
|
|
73
|
+
const without = text.replace(READ_BLOCKS, "").replace(MODIFIED_BLOCKS, "").replace(STRAY_TAGS, "");
|
|
74
|
+
if (without === text)
|
|
75
|
+
return text;
|
|
76
|
+
return without.replace(/\n{3,}/g, "\n\n").trim();
|
|
77
|
+
}
|
|
78
|
+
/** Union, deduped and sorted; a file that was ever modified never lists as read-only. */
|
|
79
|
+
export function mergeFileOps(...ops) {
|
|
80
|
+
const read = new Set();
|
|
81
|
+
const modified = new Set();
|
|
82
|
+
for (const op of ops) {
|
|
83
|
+
for (const path of op.modified)
|
|
84
|
+
modified.add(normalizePath(path));
|
|
85
|
+
for (const path of op.read)
|
|
86
|
+
read.add(normalizePath(path));
|
|
87
|
+
}
|
|
88
|
+
for (const path of modified)
|
|
89
|
+
read.delete(path);
|
|
90
|
+
return { read: [...read].sort(), modified: [...modified].sort() };
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Append the blocks to a summary text. Sanitizes the summary first so the
|
|
94
|
+
* output always contains exactly one generation of blocks, even when the
|
|
95
|
+
* model echoed tags into its own prose. No-op when both lists are empty.
|
|
96
|
+
*/
|
|
97
|
+
export function appendFileBlocks(summary, ops) {
|
|
98
|
+
const clean = stripFileBlocks(summary);
|
|
99
|
+
const blocks = [];
|
|
100
|
+
if (ops.read.length > 0)
|
|
101
|
+
blocks.push(`<read-files>\n${capped(ops.read)}\n</read-files>`);
|
|
102
|
+
if (ops.modified.length > 0)
|
|
103
|
+
blocks.push(`<modified-files>\n${capped(ops.modified)}\n</modified-files>`);
|
|
104
|
+
if (blocks.length === 0)
|
|
105
|
+
return clean;
|
|
106
|
+
return `${clean.trimEnd()}\n\n${blocks.join("\n")}`;
|
|
107
|
+
}
|
|
108
|
+
function capped(paths) {
|
|
109
|
+
if (paths.length <= MAX_FILES_PER_LIST)
|
|
110
|
+
return paths.join("\n");
|
|
111
|
+
const kept = paths.slice(0, MAX_FILES_PER_LIST);
|
|
112
|
+
return `${kept.join("\n")}\n(+${paths.length - MAX_FILES_PER_LIST} more)`;
|
|
113
|
+
}
|
|
114
|
+
function parseBlocks(text, pattern, open, close) {
|
|
115
|
+
const out = new Set();
|
|
116
|
+
for (const match of text.match(pattern) ?? []) {
|
|
117
|
+
const inner = match.slice(open.length, match.length - close.length);
|
|
118
|
+
for (const line of inner.split("\n")) {
|
|
119
|
+
const trimmed = line.trim();
|
|
120
|
+
if (trimmed && !MORE_MARKER.test(trimmed))
|
|
121
|
+
out.add(trimmed);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return [...out];
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Best-effort normalization so "./src/a.ts" and "src/a.ts" dedupe. Relative vs
|
|
128
|
+
* absolute spellings of the same file can still coexist — resolving that needs
|
|
129
|
+
* a cwd this layer doesn't have; models are consistent enough within a session
|
|
130
|
+
* that the union stays useful.
|
|
131
|
+
*/
|
|
132
|
+
function normalizePath(path) {
|
|
133
|
+
let out = path.trim().replace(/\/{2,}/g, "/");
|
|
134
|
+
while (out.startsWith("./"))
|
|
135
|
+
out = out.slice(2);
|
|
136
|
+
return out;
|
|
137
|
+
}
|
|
138
|
+
function pathFromArguments(rawArguments) {
|
|
139
|
+
if (!rawArguments)
|
|
140
|
+
return undefined;
|
|
141
|
+
try {
|
|
142
|
+
const parsed = JSON.parse(rawArguments);
|
|
143
|
+
return typeof parsed.path === "string" && parsed.path.trim() ? parsed.path.trim() : undefined;
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
return undefined;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { Message, Provider } from "../types.js";
|
|
2
|
+
export declare const LLM_COMPACTION_PROMPT = "You are performing a CONTEXT CHECKPOINT COMPACTION. The conversation below is about to be removed from the model's context and replaced by your summary. Another LLM will resume the task seeing only your summary, the user's original instruction, and the most recent messages. Anything you leave out is gone.\n\nWrite a handoff summary that lets it continue without repeating the investigation. Cover:\n- Goal and constraints: what the user wants, in their terms. Explicit requirements, preferences, and anything they ruled out. Quote exact wording where precision matters.\n- Decisions made and why, including approaches that were tried and rejected, so they are not retried.\n- Current state: what is done and verified, what is in progress, what is broken or still unverified. Keep verified facts distinct from assumptions.\n- Specifics needed to continue: file paths, identifiers, commands, error messages, config values, ids, URLs. Exact, never paraphrased.\n- Next steps in order, starting with the immediate one.\n\nLength follows content: as long as needed to preserve the above, and no longer. Spend words on what cannot be cheaply re-derived (decisions, constraints, findings). Do not reproduce file contents or tool output that can simply be read again, and do not narrate the conversation turn by turn. The lists of files read and modified are recorded separately; name only the files that matter for the next steps.\n\nCarry forward every fact from prior summaries and the original user constraints. If the input says parts of the history were omitted, say so explicitly.";
|
|
3
|
+
export declare const LLM_SUMMARY_PREFIX = "Another language model previously worked on this task and produced this handoff summary. Build on what's already done; avoid re-running the same investigation. Summary:";
|
|
4
|
+
export interface LLMCompactOptions {
|
|
5
|
+
provider: Provider;
|
|
6
|
+
modelId: string;
|
|
7
|
+
/** Total estimated request ceiling, including the compaction prompt. */
|
|
8
|
+
maxInputTokens?: number;
|
|
9
|
+
providerId?: string;
|
|
10
|
+
contextWindow?: number;
|
|
11
|
+
/** Number of trailing (assistant + tool-results) groups in the current turn to keep verbatim. */
|
|
12
|
+
keepRecentGroups?: number;
|
|
13
|
+
abortSignal?: AbortSignal;
|
|
14
|
+
}
|
|
15
|
+
export interface LLMCompactResult {
|
|
16
|
+
compacted: boolean;
|
|
17
|
+
summary?: string;
|
|
18
|
+
messages?: Message[];
|
|
19
|
+
reason?: string;
|
|
20
|
+
/** Explicit lossy-input diagnostics; also persisted in a successful summary. */
|
|
21
|
+
degradation?: string;
|
|
22
|
+
}
|
|
23
|
+
export declare function compactWithLLM(messages: Message[], options: LLMCompactOptions): Promise<LLMCompactResult>;
|
|
24
|
+
/** Fit the summarization input under the model's window, degrading breadth-first:
|
|
25
|
+
* 1. everything verbatim;
|
|
26
|
+
* 2. cap tool payloads (results and tool-call arguments alike) at the LARGEST
|
|
27
|
+
* common length that fits — short payloads such as paths and commands stay
|
|
28
|
+
* whole, only long ones lose their middle, and every group still informs
|
|
29
|
+
* the summary;
|
|
30
|
+
* 3. only when even empty payloads do not fit, drop the oldest assistant/tool
|
|
31
|
+
* group and search again, so what survives is as complete as the room allows.
|
|
32
|
+
* The cap is derived from the budget, never a fixed size. Prior summaries, user
|
|
33
|
+
* constraints and runtime context are never trimmed; if they alone exceed the
|
|
34
|
+
* budget this fails explicitly and the caller chooses a fallback.
|
|
35
|
+
* `degradation` is the durable part: whole steps the summary never saw. Trimmed
|
|
36
|
+
* middles are stated in the input only — that loss is inherent to summarizing.
|
|
37
|
+
* Exported for regression tests only — callers use compactWithLLM. */
|
|
38
|
+
export declare function fitSummaryInput(messages: Message[], prompt: string, maxTokens: number, providerId: string): {
|
|
39
|
+
historyText: string;
|
|
40
|
+
degradation?: string;
|
|
41
|
+
} | undefined;
|
|
42
|
+
/** One trimming pass: the cap, how to price text, and whether anything was cut. */
|
|
43
|
+
interface PayloadTrim {
|
|
44
|
+
cap: number;
|
|
45
|
+
estimate: (text: string) => number;
|
|
46
|
+
trimmed: boolean;
|
|
47
|
+
}
|
|
48
|
+
/** Keep the head and tail of a payload longer than `cap`; the marker states
|
|
49
|
+
* exactly how much is missing so the summarizer never mistakes it for the whole.
|
|
50
|
+
* Returns the text unchanged (and leaves `trim.trimmed` alone) when cutting would
|
|
51
|
+
* not make it cheaper. Exported for regression tests only. */
|
|
52
|
+
export declare function capPayload(text: string, trim: PayloadTrim | undefined): string;
|
|
53
|
+
export {};
|
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
// LLM-driven context compaction.
|
|
2
|
+
//
|
|
3
|
+
// When the budget says we're approaching the context window, ask the model to
|
|
4
|
+
// produce a handoff summary of the conversation so far. Replace the bulky middle
|
|
5
|
+
// of history with that summary while keeping the initial system context and the
|
|
6
|
+
// user's latest ask intact. Architecturally this mirrors Codex CLI's approach
|
|
7
|
+
// (codex-rs/core/src/compact.rs + templates/compact/prompt.md): trust the model
|
|
8
|
+
// to pick what matters instead of writing a template.
|
|
9
|
+
//
|
|
10
|
+
// Failure modes are explicit: returns { compacted: false, reason } so the
|
|
11
|
+
// caller can fall back to algorithmic compaction without an exception.
|
|
12
|
+
import { sanitizeInternalReminderBlocks } from "../agent/internal-reminder-sanitizer.js";
|
|
13
|
+
import { estimateTextTokens, getMaxInputTokens } from "./budget.js";
|
|
14
|
+
import { getTokenEstimator } from "./token-estimator.js";
|
|
15
|
+
import { getModelContextWindow } from "../model-catalog.js";
|
|
16
|
+
import { appendFileBlocks, stripFileBlocks } from "./compaction-files.js";
|
|
17
|
+
import { collectCompactionFileOps, messageText, buildCompactionSummaryMessage, clonePinnedUserMessage, findFirstRealUserIndex, isCompactionSummaryMessage, isRealUserMessage, splitLeadingContext, PINNED_INSTRUCTION_MAX_CHARS, } from "./compact.js";
|
|
18
|
+
export const LLM_COMPACTION_PROMPT = `You are performing a CONTEXT CHECKPOINT COMPACTION. The conversation below is about to be removed from the model's context and replaced by your summary. Another LLM will resume the task seeing only your summary, the user's original instruction, and the most recent messages. Anything you leave out is gone.
|
|
19
|
+
|
|
20
|
+
Write a handoff summary that lets it continue without repeating the investigation. Cover:
|
|
21
|
+
- Goal and constraints: what the user wants, in their terms. Explicit requirements, preferences, and anything they ruled out. Quote exact wording where precision matters.
|
|
22
|
+
- Decisions made and why, including approaches that were tried and rejected, so they are not retried.
|
|
23
|
+
- Current state: what is done and verified, what is in progress, what is broken or still unverified. Keep verified facts distinct from assumptions.
|
|
24
|
+
- Specifics needed to continue: file paths, identifiers, commands, error messages, config values, ids, URLs. Exact, never paraphrased.
|
|
25
|
+
- Next steps in order, starting with the immediate one.
|
|
26
|
+
|
|
27
|
+
Length follows content: as long as needed to preserve the above, and no longer. Spend words on what cannot be cheaply re-derived (decisions, constraints, findings). Do not reproduce file contents or tool output that can simply be read again, and do not narrate the conversation turn by turn. The lists of files read and modified are recorded separately; name only the files that matter for the next steps.
|
|
28
|
+
|
|
29
|
+
Carry forward every fact from prior summaries and the original user constraints. If the input says parts of the history were omitted, say so explicitly.`;
|
|
30
|
+
export const LLM_SUMMARY_PREFIX = `Another language model previously worked on this task and produced this handoff summary. Build on what's already done; avoid re-running the same investigation. Summary:`;
|
|
31
|
+
export async function compactWithLLM(messages, options) {
|
|
32
|
+
const { provider, modelId, abortSignal } = options;
|
|
33
|
+
if (abortSignal?.aborted)
|
|
34
|
+
return { compacted: false, reason: "compactor cancelled" };
|
|
35
|
+
const providerId = options.providerId ?? modelId.split(":")[0];
|
|
36
|
+
const catalogModelId = modelId.startsWith(`${providerId}:`) ? modelId.slice(providerId.length + 1) : modelId;
|
|
37
|
+
// Unknown models use a conservative window rather than an unbounded 100k call.
|
|
38
|
+
const contextWindow = options.contextWindow ?? getModelContextWindow(providerId, catalogModelId) ?? 8192;
|
|
39
|
+
// getMaxInputTokens already reserves the window's answer space, which is what
|
|
40
|
+
// the summary is written into. No fixed output ceiling: summary length is
|
|
41
|
+
// judged against what it replaces, below, and by the caller's before/after
|
|
42
|
+
// budget comparison.
|
|
43
|
+
const maxInputTokens = Math.min(options.maxInputTokens ?? Infinity, getMaxInputTokens(contextWindow) ?? 0);
|
|
44
|
+
if (![contextWindow, maxInputTokens].every((n) => Number.isFinite(n) && n > 0)) {
|
|
45
|
+
return { compacted: false, reason: "invalid compactor token budget" };
|
|
46
|
+
}
|
|
47
|
+
const keepRecentGroups = Math.max(0, Math.floor(options.keepRecentGroups ?? 2));
|
|
48
|
+
// Positional leading prefix, not role-global filtering: filtering by role
|
|
49
|
+
// used to relocate mid-history system messages (including prior summaries)
|
|
50
|
+
// to the head, where the projector then fused them into the system prompt.
|
|
51
|
+
const { leading, body: rawBody } = splitLeadingContext(messages);
|
|
52
|
+
// Replace semantics: prior summaries become summarization INPUT (semantic
|
|
53
|
+
// rolling — the compactor model merges them), never preserved copies.
|
|
54
|
+
const priorSummaries = rawBody.filter(isCompactionSummaryMessage);
|
|
55
|
+
const body = rawBody.filter((m) => !isCompactionSummaryMessage(m));
|
|
56
|
+
let lastUserIndex = -1;
|
|
57
|
+
for (let i = body.length - 1; i >= 0; i--) {
|
|
58
|
+
if (isRealUserMessage(body[i])) {
|
|
59
|
+
lastUserIndex = i;
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (lastUserIndex < 0) {
|
|
64
|
+
return { compacted: false, reason: "no user message in history" };
|
|
65
|
+
}
|
|
66
|
+
// Pivot the body around the last user message:
|
|
67
|
+
// priorTurns: everything from earlier user turns (multi-turn case)
|
|
68
|
+
// lastUser: the user's current ask (always kept verbatim)
|
|
69
|
+
// currentTurn: the assistant + tool groups produced in response so far
|
|
70
|
+
//
|
|
71
|
+
// The FIRST real user message (the original instruction) is pinned verbatim
|
|
72
|
+
// too: after meta reminders get re-rolled into user role by the projector,
|
|
73
|
+
// "last user message" often points at a reminder, not the instruction — and
|
|
74
|
+
// late requirements in a long instruction must survive compaction.
|
|
75
|
+
const priorTurns = body.slice(0, lastUserIndex);
|
|
76
|
+
const lastUser = body[lastUserIndex];
|
|
77
|
+
const currentTurn = body.slice(lastUserIndex + 1);
|
|
78
|
+
const firstRealUserIndex = findFirstRealUserIndex(body);
|
|
79
|
+
const pinnedFirstUser = firstRealUserIndex >= 0 && firstRealUserIndex < lastUserIndex
|
|
80
|
+
? body[firstRealUserIndex]
|
|
81
|
+
: undefined;
|
|
82
|
+
const summarizablePriorTurns = pinnedFirstUser
|
|
83
|
+
? priorTurns.filter((message) => message !== pinnedFirstUser)
|
|
84
|
+
: priorTurns;
|
|
85
|
+
const groups = [];
|
|
86
|
+
let active = null;
|
|
87
|
+
for (const msg of currentTurn) {
|
|
88
|
+
if (msg.role === "assistant") {
|
|
89
|
+
if (active)
|
|
90
|
+
groups.push(active);
|
|
91
|
+
active = { assistant: msg, toolResults: [] };
|
|
92
|
+
}
|
|
93
|
+
else if (active) {
|
|
94
|
+
active.toolResults.push(msg);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
// Preserve interleaved reminders and other context, not just tool results.
|
|
98
|
+
active = { assistant: msg, toolResults: [] };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (active)
|
|
102
|
+
groups.push(active);
|
|
103
|
+
const keptGroupCount = Math.min(keepRecentGroups, groups.length);
|
|
104
|
+
const evictedGroups = groups.slice(0, groups.length - keptGroupCount);
|
|
105
|
+
const keptGroups = groups.slice(groups.length - keptGroupCount);
|
|
106
|
+
// What we'll send to the model to summarize: prior summaries (semantic
|
|
107
|
+
// rolling), prior turns, and the older groups in the current turn. The
|
|
108
|
+
// pinned first instruction is excluded — it survives verbatim. File blocks
|
|
109
|
+
// are stripped from prior summaries here: the deterministic merge below owns
|
|
110
|
+
// the file lists, and feeding them to the model only invites a lossy echo.
|
|
111
|
+
const toSummarize = [
|
|
112
|
+
...priorSummaries.map((m) => ({
|
|
113
|
+
role: "user",
|
|
114
|
+
content: `[Prior compaction summary]\n${stripFileBlocks(messageText(m))}`,
|
|
115
|
+
})),
|
|
116
|
+
// The pin is capped; its tail is protected summary input, never silently lost.
|
|
117
|
+
...(pinnedFirstUser && messageText(pinnedFirstUser).length > PINNED_INSTRUCTION_MAX_CHARS
|
|
118
|
+
? [{ role: "user", content: `[Original instruction beyond retained pin]\n${messageText(pinnedFirstUser).slice(PINNED_INSTRUCTION_MAX_CHARS)}` }]
|
|
119
|
+
: []),
|
|
120
|
+
...summarizablePriorTurns,
|
|
121
|
+
...evictedGroups.flatMap((g) => [g.assistant, ...g.toolResults]),
|
|
122
|
+
];
|
|
123
|
+
// Cumulative file tracking (deterministic, never via the model): union the
|
|
124
|
+
// lists the prior summaries carried with the ops in what we're evicting now.
|
|
125
|
+
// Tool results ride along so failed/rejected calls don't count as touches.
|
|
126
|
+
const fileOps = collectCompactionFileOps([...summarizablePriorTurns, ...evictedGroups.flatMap((g) => [g.assistant, ...g.toolResults])], priorSummaries);
|
|
127
|
+
if (toSummarize.length === 0) {
|
|
128
|
+
return { compacted: false, reason: "nothing to evict" };
|
|
129
|
+
}
|
|
130
|
+
const prompt = LLM_COMPACTION_PROMPT;
|
|
131
|
+
const fitted = fitSummaryInput(toSummarize, prompt, maxInputTokens, providerId);
|
|
132
|
+
if (!fitted) {
|
|
133
|
+
return { compacted: false, reason: "compactor input budget cannot retain prior summaries and user constraints" };
|
|
134
|
+
}
|
|
135
|
+
const { historyText, degradation } = fitted;
|
|
136
|
+
const summaryInput = [
|
|
137
|
+
{ role: "system", content: prompt },
|
|
138
|
+
{ role: "user", content: historyText },
|
|
139
|
+
];
|
|
140
|
+
if (abortSignal?.aborted)
|
|
141
|
+
return { compacted: false, reason: "compactor cancelled" };
|
|
142
|
+
let summaryText;
|
|
143
|
+
try {
|
|
144
|
+
summaryText = await provider.complete(summaryInput, {
|
|
145
|
+
model: modelId,
|
|
146
|
+
temperature: 0.2,
|
|
147
|
+
abortSignal,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
return { compacted: false, reason: `compactor call failed: ${err.message}` };
|
|
152
|
+
}
|
|
153
|
+
// Some providers resolve even after abort; never apply that late result.
|
|
154
|
+
if (abortSignal?.aborted)
|
|
155
|
+
return { compacted: false, reason: "compactor cancelled" };
|
|
156
|
+
if (!summaryText || summaryText.trim().length === 0) {
|
|
157
|
+
return { compacted: false, reason: "compactor returned empty summary" };
|
|
158
|
+
}
|
|
159
|
+
// The summarizer's input transcript can contain projected reminder blocks
|
|
160
|
+
// (resident history holds them after pruned-mode projection), and models
|
|
161
|
+
// quote their input. This summary is persisted via onCompactionApplied, so
|
|
162
|
+
// scrub markup before it can reach the session file.
|
|
163
|
+
summaryText = stripFileBlocks(sanitizeInternalReminderBlocks(summaryText)).trim();
|
|
164
|
+
if (!summaryText) {
|
|
165
|
+
return { compacted: false, reason: "compactor returned only internal markup" };
|
|
166
|
+
}
|
|
167
|
+
// The only meaningful length bound is relative: a summary that is not shorter
|
|
168
|
+
// than the history it replaces (a model echoing its input) compacts nothing.
|
|
169
|
+
// Judge the model's prose alone — the deterministic file lists are not its
|
|
170
|
+
// output — and reject rather than clip decisions/constraints out of it.
|
|
171
|
+
if (estimateTextTokens(summaryText, providerId) >= estimateTextTokens(serializeHistoryAsText(toSummarize), providerId)) {
|
|
172
|
+
return { compacted: false, reason: "compactor summary is not shorter than the history it replaces", degradation };
|
|
173
|
+
}
|
|
174
|
+
if (degradation)
|
|
175
|
+
summaryText = `${degradation}\n\n${summaryText}`;
|
|
176
|
+
const summaryWithFiles = appendFileBlocks(summaryText, fileOps);
|
|
177
|
+
// New history shape (prefix-cache-friendly: preserved system+meta stay at the
|
|
178
|
+
// absolute prefix unchanged; summary is injected after as a user-role envelope
|
|
179
|
+
// so it can't pollute the cacheable system-prompt prefix):
|
|
180
|
+
//
|
|
181
|
+
// [...preserved system+meta] ← stable prefix
|
|
182
|
+
// user: "<SUMMARY_PREFIX>\n<summary>" ← evicted history compressed
|
|
183
|
+
// user: <original last user message> ← the current ask
|
|
184
|
+
// [...kept current-turn (assistant + tool) groups] ← recent tool work
|
|
185
|
+
const flatKept = [];
|
|
186
|
+
for (const g of keptGroups) {
|
|
187
|
+
flatKept.push(cloneMessage(g.assistant));
|
|
188
|
+
for (const t of g.toolResults)
|
|
189
|
+
flatKept.push(cloneMessage(t));
|
|
190
|
+
}
|
|
191
|
+
const compacted = [
|
|
192
|
+
...leading.map(cloneMessage),
|
|
193
|
+
...(pinnedFirstUser ? [clonePinnedUserMessage(pinnedFirstUser)] : []),
|
|
194
|
+
buildCompactionSummaryMessage(appendFileBlocks(`${LLM_SUMMARY_PREFIX}\n${summaryText}`, fileOps)),
|
|
195
|
+
cloneMessage(lastUser),
|
|
196
|
+
...flatKept,
|
|
197
|
+
];
|
|
198
|
+
return {
|
|
199
|
+
compacted: true,
|
|
200
|
+
degradation,
|
|
201
|
+
// Same payload the resident message carries (minus the envelope prefix —
|
|
202
|
+
// session replay adds its own "Previous conversation summary:" header), so
|
|
203
|
+
// the persisted checkpoint matches the in-memory state, file blocks included.
|
|
204
|
+
summary: summaryWithFiles,
|
|
205
|
+
messages: compacted,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
/** Fit the summarization input under the model's window, degrading breadth-first:
|
|
209
|
+
* 1. everything verbatim;
|
|
210
|
+
* 2. cap tool payloads (results and tool-call arguments alike) at the LARGEST
|
|
211
|
+
* common length that fits — short payloads such as paths and commands stay
|
|
212
|
+
* whole, only long ones lose their middle, and every group still informs
|
|
213
|
+
* the summary;
|
|
214
|
+
* 3. only when even empty payloads do not fit, drop the oldest assistant/tool
|
|
215
|
+
* group and search again, so what survives is as complete as the room allows.
|
|
216
|
+
* The cap is derived from the budget, never a fixed size. Prior summaries, user
|
|
217
|
+
* constraints and runtime context are never trimmed; if they alone exceed the
|
|
218
|
+
* budget this fails explicitly and the caller chooses a fallback.
|
|
219
|
+
* `degradation` is the durable part: whole steps the summary never saw. Trimmed
|
|
220
|
+
* middles are stated in the input only — that loss is inherent to summarizing.
|
|
221
|
+
* Exported for regression tests only — callers use compactWithLLM. */
|
|
222
|
+
export function fitSummaryInput(messages, prompt, maxTokens, providerId) {
|
|
223
|
+
// Group by pending tool-call ids, not adjacency: an interleaved meta reminder
|
|
224
|
+
// between a call and its result must not split the pair — otherwise dropping
|
|
225
|
+
// can remove the call while keeping an orphan `TOOL_RESULT[tool]` line that
|
|
226
|
+
// has lost its name and provenance.
|
|
227
|
+
const groups = [];
|
|
228
|
+
const groupByCallId = new Map();
|
|
229
|
+
for (const message of messages) {
|
|
230
|
+
if (message.role === "tool") {
|
|
231
|
+
const group = groupByCallId.get(message.toolCallId);
|
|
232
|
+
if (group) {
|
|
233
|
+
group.push(message);
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
const group = [message];
|
|
238
|
+
groups.push(group);
|
|
239
|
+
if (message.role === "assistant" && message.toolCalls) {
|
|
240
|
+
for (const toolCall of message.toolCalls)
|
|
241
|
+
groupByCallId.set(toolCall.id, group);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
const promptTokens = estimateTextTokens(prompt, providerId);
|
|
245
|
+
const render = (cap, dropped, estimate = (text) => estimateTextTokens(text, providerId)) => {
|
|
246
|
+
const degradation = dropped
|
|
247
|
+
? `[Compaction input degraded: omitted ${dropped} older assistant/tool groups to fit the model window.]`
|
|
248
|
+
: undefined;
|
|
249
|
+
const trim = cap === undefined ? undefined : { cap, estimate, trimmed: false };
|
|
250
|
+
const body = serializeHistoryAsText(groups.flat(), trim);
|
|
251
|
+
// The note is part of the cost, so it appears only when something was cut:
|
|
252
|
+
// an input with nothing to trim must measure exactly like the verbatim one.
|
|
253
|
+
const trimNote = trim?.trimmed
|
|
254
|
+
? `[Tool results and tool-call arguments longer than ${cap} characters show only their head and tail.]`
|
|
255
|
+
: undefined;
|
|
256
|
+
const historyText = [degradation, trimNote, body].filter(Boolean).join("\n\n");
|
|
257
|
+
// Measure the actual serialized payload (including labels and prompt), with
|
|
258
|
+
// the same conservative first-turn safety margin as the context budget.
|
|
259
|
+
const tokens = Math.ceil((promptTokens + estimate(historyText) + 32) * 1.25);
|
|
260
|
+
// What the note itself costs: trimming that saves less than this makes the
|
|
261
|
+
// input LARGER than the verbatim one.
|
|
262
|
+
const noteTokens = trimNote ? Math.ceil((estimate(trimNote) + 2) * 1.25) + 1 : 0;
|
|
263
|
+
return { fits: tokens <= maxTokens, overBy: tokens - maxTokens, noteTokens, trimmed: !!trim?.trimmed, fitted: { historyText, degradation } };
|
|
264
|
+
};
|
|
265
|
+
/** Largest cap the predicate accepts, assuming it is monotone; the returned
|
|
266
|
+
* cap is always one that was actually probed and accepted. */
|
|
267
|
+
const searchCap = (longest, accepts) => {
|
|
268
|
+
let low = 0;
|
|
269
|
+
let high = longest;
|
|
270
|
+
while (low < high) {
|
|
271
|
+
const middle = Math.ceil((low + high) / 2);
|
|
272
|
+
if (accepts(middle))
|
|
273
|
+
low = middle;
|
|
274
|
+
else
|
|
275
|
+
high = middle - 1;
|
|
276
|
+
}
|
|
277
|
+
return low;
|
|
278
|
+
};
|
|
279
|
+
// A provider tokenizer is not monotone in the cap: the tiktoken estimator
|
|
280
|
+
// switches to the heuristic above a length limit and BPE counts wobble at cut
|
|
281
|
+
// points, so a failing midpoint can hide a fitting interval above it. The
|
|
282
|
+
// character-class heuristic IS monotone (every character only adds), so it
|
|
283
|
+
// also proposes a cap; whichever real-estimator-verified cap is larger wins.
|
|
284
|
+
const heuristicOnly = getTokenEstimator(providerId) === getTokenEstimator();
|
|
285
|
+
for (let dropped = 0; groups.length > 0; dropped++) {
|
|
286
|
+
// Empty payloads are the cheapest probe and the floor of what trimming can reach.
|
|
287
|
+
const floor = render(0, dropped);
|
|
288
|
+
if (floor.fits) {
|
|
289
|
+
if (!floor.trimmed)
|
|
290
|
+
return floor.fitted; // Nothing to trim: this IS the verbatim input.
|
|
291
|
+
const whole = render(undefined, dropped);
|
|
292
|
+
if (whole.fits)
|
|
293
|
+
return whole.fitted;
|
|
294
|
+
const longest = longestPayload(groups);
|
|
295
|
+
let bestCap = searchCap(longest, (cap) => render(cap, dropped).fits);
|
|
296
|
+
if (!heuristicOnly) {
|
|
297
|
+
const proposed = searchCap(longest, (cap) => render(cap, dropped, (text) => estimateTextTokens(text)).fits);
|
|
298
|
+
if (proposed > bestCap && render(proposed, dropped).fits)
|
|
299
|
+
bestCap = proposed;
|
|
300
|
+
}
|
|
301
|
+
return render(bestCap, dropped).fitted;
|
|
302
|
+
}
|
|
303
|
+
// Emptying the payloads is not always the smallest rendering. With the
|
|
304
|
+
// additive heuristic the verbatim input can only be smaller when trimming
|
|
305
|
+
// saves less than its note costs, i.e. within that cost of the budget, so it
|
|
306
|
+
// is probed just then. A provider tokenizer gives no such bound: past its
|
|
307
|
+
// length limit it switches to the (cheaper) heuristic, so a longer verbatim
|
|
308
|
+
// input can measure far below a shorter trimmed one — always probe there.
|
|
309
|
+
if (floor.trimmed && (!heuristicOnly || floor.overBy <= floor.noteTokens)) {
|
|
310
|
+
const whole = render(undefined, dropped);
|
|
311
|
+
if (whole.fits)
|
|
312
|
+
return whole.fitted;
|
|
313
|
+
}
|
|
314
|
+
const removable = groups.findIndex((group) => group.every((m) => m.role === "assistant" || m.role === "tool"));
|
|
315
|
+
if (removable < 0)
|
|
316
|
+
return undefined;
|
|
317
|
+
groups.splice(removable, 1);
|
|
318
|
+
}
|
|
319
|
+
return undefined;
|
|
320
|
+
}
|
|
321
|
+
function longestPayload(groups) {
|
|
322
|
+
let longest = 0;
|
|
323
|
+
for (const group of groups) {
|
|
324
|
+
for (const message of group) {
|
|
325
|
+
if (message.role === "tool")
|
|
326
|
+
longest = Math.max(longest, message.content.length);
|
|
327
|
+
else if (message.role === "assistant") {
|
|
328
|
+
for (const toolCall of message.toolCalls ?? [])
|
|
329
|
+
longest = Math.max(longest, (toolCall.arguments || "").length);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return longest;
|
|
334
|
+
}
|
|
335
|
+
/** Keep the head and tail of a payload longer than `cap`; the marker states
|
|
336
|
+
* exactly how much is missing so the summarizer never mistakes it for the whole.
|
|
337
|
+
* Returns the text unchanged (and leaves `trim.trimmed` alone) when cutting would
|
|
338
|
+
* not make it cheaper. Exported for regression tests only. */
|
|
339
|
+
export function capPayload(text, trim) {
|
|
340
|
+
if (!trim || text.length <= trim.cap)
|
|
341
|
+
return text;
|
|
342
|
+
let headEnd = Math.ceil(trim.cap / 2);
|
|
343
|
+
let tailStart = text.length - (trim.cap - headEnd);
|
|
344
|
+
// Never cut a surrogate pair in half: a lone surrogate is invalid Unicode that
|
|
345
|
+
// some provider endpoints reject outright.
|
|
346
|
+
if (headEnd > 0 && isHighSurrogate(text.charCodeAt(headEnd - 1)))
|
|
347
|
+
headEnd--;
|
|
348
|
+
if (tailStart < text.length && isLowSurrogate(text.charCodeAt(tailStart)))
|
|
349
|
+
tailStart++;
|
|
350
|
+
const capped = `${text.slice(0, headEnd)}[... ${tailStart - headEnd} of ${text.length} characters omitted ...]${text.slice(tailStart)}`;
|
|
351
|
+
// Worth it only if it is cheaper in TOKENS. Fewer characters is taken as
|
|
352
|
+
// cheaper without pricing (large payloads, every probe); a marker longer than
|
|
353
|
+
// what it replaces can still be cheaper for token-dense text such as CJK, and
|
|
354
|
+
// that case is always short enough to price exactly.
|
|
355
|
+
if (capped.length >= text.length && trim.estimate(capped) >= trim.estimate(text))
|
|
356
|
+
return text;
|
|
357
|
+
trim.trimmed = true;
|
|
358
|
+
return capped;
|
|
359
|
+
}
|
|
360
|
+
const isHighSurrogate = (code) => code >= 0xd800 && code <= 0xdbff;
|
|
361
|
+
const isLowSurrogate = (code) => code >= 0xdc00 && code <= 0xdfff;
|
|
362
|
+
function serializeHistoryAsText(messages, trim) {
|
|
363
|
+
const lines = [];
|
|
364
|
+
const toolNameByCallId = new Map();
|
|
365
|
+
for (const msg of messages) {
|
|
366
|
+
switch (msg.role) {
|
|
367
|
+
case "user": {
|
|
368
|
+
const text = typeof msg.content === "string"
|
|
369
|
+
? msg.content
|
|
370
|
+
: msg.content.filter((p) => p.type === "text").map((p) => p.text).join(" ");
|
|
371
|
+
lines.push(`USER: ${text}`);
|
|
372
|
+
break;
|
|
373
|
+
}
|
|
374
|
+
case "assistant": {
|
|
375
|
+
if (msg.content.trim()) {
|
|
376
|
+
lines.push(`ASSISTANT: ${msg.content}`);
|
|
377
|
+
}
|
|
378
|
+
if (msg.toolCalls && msg.toolCalls.length > 0) {
|
|
379
|
+
for (const tc of msg.toolCalls) {
|
|
380
|
+
toolNameByCallId.set(tc.id, tc.name);
|
|
381
|
+
lines.push(`TOOL_CALL[${tc.name}]: ${capPayload(summarizeToolCallArgs(tc), trim)}`);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
break;
|
|
385
|
+
}
|
|
386
|
+
case "tool": {
|
|
387
|
+
const name = toolNameByCallId.get(msg.toolCallId) ?? "tool";
|
|
388
|
+
lines.push(`TOOL_RESULT[${name}]: ${capPayload(msg.content, trim)}`);
|
|
389
|
+
break;
|
|
390
|
+
}
|
|
391
|
+
case "meta":
|
|
392
|
+
// Expired runtime reminders remain in history but are no longer model
|
|
393
|
+
// context. Prior summaries have already been folded into user input.
|
|
394
|
+
if (msg.includeInLlm !== false)
|
|
395
|
+
lines.push(`CONTEXT: ${msg.content}`);
|
|
396
|
+
break;
|
|
397
|
+
default:
|
|
398
|
+
lines.push(`CONTEXT: ${messageText(msg)}`);
|
|
399
|
+
break;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
return lines.join("\n\n");
|
|
403
|
+
}
|
|
404
|
+
function summarizeToolCallArgs(tc) {
|
|
405
|
+
return tc.arguments || "{}";
|
|
406
|
+
}
|
|
407
|
+
function cloneMessage(message) {
|
|
408
|
+
if (message.role === "assistant") {
|
|
409
|
+
return {
|
|
410
|
+
...message,
|
|
411
|
+
toolCalls: message.toolCalls?.map((toolCall) => ({ ...toolCall })),
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
if (message.role === "user" && Array.isArray(message.content)) {
|
|
415
|
+
return {
|
|
416
|
+
...message,
|
|
417
|
+
content: message.content.map((part) => ({
|
|
418
|
+
...part,
|
|
419
|
+
...(part.type === "image_url" ? { image_url: { ...part.image_url } } : {}),
|
|
420
|
+
})),
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
return { ...message };
|
|
424
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context-overflow detection.
|
|
3
|
+
*
|
|
4
|
+
* When the upstream provider rejects a request because the prompt exceeds
|
|
5
|
+
* the effective context window, we catch the error here so the agent can
|
|
6
|
+
* compact history and retry automatically.
|
|
7
|
+
*/
|
|
8
|
+
export declare function isContextOverflowError(error: unknown): boolean;
|
|
9
|
+
export declare function isContextOverflowByUsage(inputTokens: number | undefined, contextWindow: number | undefined): boolean;
|