aws-runtime-bridge 1.9.78 → 1.9.80
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/dist/adapter/AcodeSdkAdapter.d.ts +0 -1
- package/dist/adapter/AcodeSdkAdapter.js +11 -1986
- package/dist/adapter/AdapterRegistry.d.ts +0 -1
- package/dist/adapter/AdapterRegistry.js +2 -100
- package/dist/adapter/ClaudeSdkAdapter.d.ts +0 -1
- package/dist/adapter/ClaudeSdkAdapter.js +4 -1300
- package/dist/adapter/CodexSdkAdapter.d.ts +0 -1
- package/dist/adapter/CodexSdkAdapter.js +4 -836
- package/dist/adapter/OpencodeSdkAdapter.d.ts +0 -1
- package/dist/adapter/OpencodeSdkAdapter.js +4 -879
- package/dist/adapter/SdkProviderSpi.d.ts +0 -1
- package/dist/adapter/SdkProviderSpi.js +2 -55
- package/dist/adapter/acode-tool-names.d.ts +0 -1
- package/dist/adapter/acode-tool-names.js +2 -37
- package/dist/adapter/idle-poll-loop.d.ts +0 -1
- package/dist/adapter/idle-poll-loop.js +2 -59
- package/dist/adapter/index.d.ts +0 -1
- package/dist/adapter/index.js +2 -11
- package/dist/adapter/instance-ai-config-resolver.d.ts +0 -1
- package/dist/adapter/instance-ai-config-resolver.js +2 -46
- package/dist/adapter/types.d.ts +0 -1
- package/dist/adapter/types.js +2 -443
- package/dist/adapters/cc-switch/common.d.ts +0 -1
- package/dist/adapters/cc-switch/common.js +2 -61
- package/dist/adapters/cc-switch/index.d.ts +0 -1
- package/dist/adapters/cc-switch/index.js +2 -57
- package/dist/adapters/cc-switch/mcp-acode.d.ts +0 -1
- package/dist/adapters/cc-switch/mcp-acode.js +2 -71
- package/dist/adapters/cc-switch/mcp-claude.d.ts +0 -1
- package/dist/adapters/cc-switch/mcp-claude.js +2 -89
- package/dist/adapters/cc-switch/mcp-claudecode.d.ts +0 -1
- package/dist/adapters/cc-switch/mcp-claudecode.js +2 -77
- package/dist/adapters/cc-switch/mcp-codex.d.ts +0 -1
- package/dist/adapters/cc-switch/mcp-codex.js +11 -249
- package/dist/adapters/cc-switch/mcp-opencode.d.ts +0 -1
- package/dist/adapters/cc-switch/mcp-opencode.js +2 -97
- package/dist/adapters/cc-switch/mcp-placeholder.d.ts +0 -1
- package/dist/adapters/cc-switch/mcp-placeholder.js +2 -19
- package/dist/adapters/cc-switch/skill-acode.d.ts +0 -1
- package/dist/adapters/cc-switch/skill-acode.js +2 -12
- package/dist/adapters/cc-switch/skill-claude.d.ts +0 -1
- package/dist/adapters/cc-switch/skill-claude.js +2 -11
- package/dist/adapters/cc-switch/skill-claudecode.d.ts +0 -1
- package/dist/adapters/cc-switch/skill-claudecode.js +2 -11
- package/dist/adapters/cc-switch/skill-codex.d.ts +0 -1
- package/dist/adapters/cc-switch/skill-codex.js +2 -6
- package/dist/adapters/cc-switch/skill-directory.d.ts +0 -1
- package/dist/adapters/cc-switch/skill-directory.js +3 -137
- package/dist/adapters/cc-switch/skill-opencode.d.ts +0 -1
- package/dist/adapters/cc-switch/skill-opencode.js +2 -11
- package/dist/adapters/cc-switch/skill-placeholder.d.ts +0 -1
- package/dist/adapters/cc-switch/skill-placeholder.js +2 -19
- package/dist/config.d.ts +0 -1
- package/dist/config.js +2 -290
- package/dist/index.d.ts +0 -1
- package/dist/index.js +2 -573
- package/dist/middleware/auth.d.ts +0 -1
- package/dist/middleware/auth.js +2 -98
- package/dist/routes/acode-todos.d.ts +0 -1
- package/dist/routes/acode-todos.js +2 -75
- package/dist/routes/ai-sources.d.ts +0 -1
- package/dist/routes/ai-sources.js +2 -132
- package/dist/routes/dashboard.d.ts +0 -1
- package/dist/routes/dashboard.js +182 -649
- package/dist/routes/events.d.ts +0 -1
- package/dist/routes/events.js +2 -22
- package/dist/routes/file-browser.d.ts +0 -1
- package/dist/routes/file-browser.js +2 -781
- package/dist/routes/file-diff-rollback.d.ts +0 -1
- package/dist/routes/file-diff-rollback.js +2 -301
- package/dist/routes/file-snapshot.d.ts +0 -1
- package/dist/routes/file-snapshot.js +2 -156
- package/dist/routes/git.d.ts +0 -1
- package/dist/routes/git.js +28 -1900
- package/dist/routes/instance.d.ts +0 -1
- package/dist/routes/instance.js +3 -748
- package/dist/routes/mcp.d.ts +0 -1
- package/dist/routes/mcp.js +2 -196
- package/dist/routes/processes.d.ts +0 -1
- package/dist/routes/processes.js +2 -252
- package/dist/routes/properties.d.ts +0 -1
- package/dist/routes/properties.js +2 -72
- package/dist/routes/pty.d.ts +0 -1
- package/dist/routes/pty.js +6 -560
- package/dist/routes/runtime-binding.d.ts +0 -1
- package/dist/routes/runtime-binding.js +2 -263
- package/dist/routes/sessions.d.ts +0 -1
- package/dist/routes/sessions.js +2 -758
- package/dist/routes/skills.d.ts +0 -1
- package/dist/routes/skills.js +2 -187
- package/dist/routes/sub-agents.d.ts +0 -1
- package/dist/routes/sub-agents.js +20 -279
- package/dist/routes/system-metrics.d.ts +0 -1
- package/dist/routes/system-metrics.js +2 -20
- package/dist/routes/task-context.d.ts +0 -1
- package/dist/routes/task-context.js +2 -78
- package/dist/routes/terminal.d.ts +0 -1
- package/dist/routes/terminal.js +54 -2882
- package/dist/routes/yml.d.ts +0 -1
- package/dist/routes/yml.js +2 -223
- package/dist/services/acode-package.d.ts +0 -1
- package/dist/services/acode-package.js +2 -111
- package/dist/services/agent-event-store.d.ts +0 -1
- package/dist/services/agent-event-store.js +2 -81
- package/dist/services/agent-process-manager.d.ts +0 -1
- package/dist/services/agent-process-manager.js +2 -796
- package/dist/services/ai-source-apply.d.ts +0 -1
- package/dist/services/ai-source-apply.js +2 -83
- package/dist/services/auto-register.d.ts +0 -1
- package/dist/services/auto-register.js +2 -1053
- package/dist/services/aws-client-agent-mcp.d.ts +0 -1
- package/dist/services/aws-client-agent-mcp.js +3 -337
- package/dist/services/bridge-package-publish-hooks.d.ts +0 -1
- package/dist/services/bridge-package-publish-hooks.js +2 -115
- package/dist/services/cc-switch-sdk.d.ts +0 -1
- package/dist/services/cc-switch-sdk.js +2 -135
- package/dist/services/cli-commands.d.ts +6 -1
- package/dist/services/cli-commands.js +6 -645
- package/dist/services/event-delta-pusher.d.ts +0 -1
- package/dist/services/event-delta-pusher.js +2 -95
- package/dist/services/fileSnapshotStore.d.ts +0 -1
- package/dist/services/fileSnapshotStore.js +2 -500
- package/dist/services/instance-ai-config-service.d.ts +0 -1
- package/dist/services/instance-ai-config-service.js +2 -174
- package/dist/services/instance-init-service.d.ts +0 -1
- package/dist/services/instance-init-service.js +2 -193
- package/dist/services/instance-service.d.ts +0 -1
- package/dist/services/instance-service.js +2 -237
- package/dist/services/instance-state.d.ts +0 -1
- package/dist/services/instance-state.js +2 -94
- package/dist/services/legacy-path-migration.d.ts +0 -1
- package/dist/services/legacy-path-migration.js +2 -66
- package/dist/services/lifecycle-state.d.ts +0 -1
- package/dist/services/lifecycle-state.js +3 -110
- package/dist/services/mcp-launch-binding-queue.d.ts +0 -1
- package/dist/services/mcp-launch-binding-queue.js +2 -175
- package/dist/services/orphan-monitor.d.ts +0 -1
- package/dist/services/orphan-monitor.js +2 -382
- package/dist/services/panel-auth.d.ts +0 -1
- package/dist/services/panel-auth.js +2 -168
- package/dist/services/process-detector.d.ts +0 -1
- package/dist/services/process-detector.js +18 -1019
- package/dist/services/process-registry.d.ts +0 -1
- package/dist/services/process-registry.js +2 -375
- package/dist/services/ring-buffer.d.ts +0 -1
- package/dist/services/ring-buffer.js +2 -103
- package/dist/services/runtime-binding.d.ts +0 -1
- package/dist/services/runtime-binding.js +6 -363
- package/dist/services/runtime-lifecycle-policy.d.ts +0 -1
- package/dist/services/runtime-lifecycle-policy.js +2 -35
- package/dist/services/session-output.d.ts +0 -1
- package/dist/services/session-output.js +5 -539
- package/dist/services/startup-config-wizard.d.ts +0 -1
- package/dist/services/startup-config-wizard.js +14 -258
- package/dist/services/sub-agent-manager-instance.d.ts +0 -1
- package/dist/services/sub-agent-manager-instance.js +2 -12
- package/dist/services/system-metrics.d.ts +0 -1
- package/dist/services/system-metrics.js +2 -252
- package/dist/services/terminal-persistence.d.ts +0 -1
- package/dist/services/terminal-persistence.js +2 -176
- package/dist/services/tool-installer.d.ts +0 -1
- package/dist/services/tool-installer.js +5 -751
- package/dist/services/tunnel-client.d.ts +0 -1
- package/dist/services/tunnel-client.js +2 -402
- package/dist/services/windows-service-manager.d.ts +3 -2
- package/dist/services/windows-service-manager.js +2 -54
- package/dist/services/workspace-files.d.ts +0 -1
- package/dist/services/workspace-files.js +2 -1275
- package/dist/services/workspace-watch.d.ts +0 -1
- package/dist/services/workspace-watch.js +2 -123
- package/dist/services/workspaceTaskChangeWatcher.d.ts +0 -1
- package/dist/services/workspaceTaskChangeWatcher.js +2 -483
- package/dist/types.d.ts +0 -1
- package/dist/types.js +1 -1
- package/dist/utils/file-utils.d.ts +0 -1
- package/dist/utils/file-utils.js +3 -208
- package/dist/utils/instance-ai-config-debug-logger.d.ts +0 -1
- package/dist/utils/instance-ai-config-debug-logger.js +4 -63
- package/dist/utils/logger.d.ts +0 -1
- package/dist/utils/logger.js +2 -154
- package/dist/utils/mcp-utils.d.ts +0 -1
- package/dist/utils/mcp-utils.js +2 -187
- package/dist/utils/path-utils.d.ts +0 -1
- package/dist/utils/path-utils.js +2 -44
- package/dist/utils/sdk-package-loader.d.ts +0 -1
- package/dist/utils/sdk-package-loader.js +2 -78
- package/dist/utils/validation.d.ts +0 -1
- package/dist/utils/validation.js +2 -53
- package/dist/utils/yaml-utils.d.ts +0 -1
- package/dist/utils/yaml-utils.js +2 -312
- package/node_modules/@cc-switch/sdk/dist/constants.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/constants.js +2 -63
- package/node_modules/@cc-switch/sdk/dist/errors.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/errors.js +2 -8
- package/node_modules/@cc-switch/sdk/dist/index.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/index.js +2 -9
- package/node_modules/@cc-switch/sdk/dist/schemas.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/schemas.js +2 -38
- package/node_modules/@cc-switch/sdk/dist/sdk.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/sdk.js +2 -470
- package/node_modules/@cc-switch/sdk/dist/services/ai-config-service.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/services/ai-config-service.js +4 -307
- package/node_modules/@cc-switch/sdk/dist/services/mcp-model.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/services/mcp-model.js +2 -37
- package/node_modules/@cc-switch/sdk/dist/services/mcp-service.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/services/mcp-service.js +2 -9
- package/node_modules/@cc-switch/sdk/dist/services/skill-model.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/services/skill-model.js +2 -41
- package/node_modules/@cc-switch/sdk/dist/services/skill-service.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/services/skill-service.js +2 -9
- package/node_modules/@cc-switch/sdk/dist/state.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/state.js +2 -19
- package/node_modules/@cc-switch/sdk/dist/types.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/types.js +1 -1
- package/node_modules/@cc-switch/sdk/dist/utils/fs.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/utils/fs.js +3 -114
- package/node_modules/@cc-switch/sdk/dist/utils/id.d.ts +0 -1
- package/node_modules/@cc-switch/sdk/dist/utils/id.js +2 -12
- package/node_modules/@cc-switch/sdk/package.json +1 -1
- package/package/acode/dist/ask-user-question-tool.d.ts +0 -1
- package/package/acode/dist/ask-user-question-tool.js +4 -233
- package/package/acode/dist/built-in-file-tools.d.ts +0 -1
- package/package/acode/dist/built-in-file-tools.js +4 -966
- package/package/acode/dist/built-in-symbols-tool.d.ts +0 -1
- package/package/acode/dist/built-in-symbols-tool.js +2 -117
- package/package/acode/dist/builtins/commandArtifacts.d.ts +0 -1
- package/package/acode/dist/builtins/commandArtifacts.js +9 -97
- package/package/acode/dist/builtins/commandOutputEvents.d.ts +0 -1
- package/package/acode/dist/builtins/commandOutputEvents.js +2 -56
- package/package/acode/dist/builtins/shellCommandPreparation.d.ts +0 -1
- package/package/acode/dist/builtins/shellCommandPreparation.js +5 -44
- package/package/acode/dist/builtins/shellCommandResult.d.ts +0 -1
- package/package/acode/dist/builtins/shellCommandResult.js +2 -71
- package/package/acode/dist/builtins/shellCommandRunner.d.ts +0 -1
- package/package/acode/dist/builtins/shellCommandRunner.js +2 -115
- package/package/acode/dist/builtins/shellOutputDecoder.d.ts +0 -1
- package/package/acode/dist/builtins/shellOutputDecoder.js +2 -94
- package/package/acode/dist/cli.d.ts +0 -1
- package/package/acode/dist/cli.js +4 -38
- package/package/acode/dist/commands/commandLoader.d.ts +0 -1
- package/package/acode/dist/commands/commandLoader.js +2 -33
- package/package/acode/dist/commands/commandParser.d.ts +0 -1
- package/package/acode/dist/commands/commandParser.js +3 -77
- package/package/acode/dist/commands/commandRegistry.d.ts +0 -1
- package/package/acode/dist/commands/commandRegistry.js +2 -30
- package/package/acode/dist/compaction.d.ts +0 -1
- package/package/acode/dist/compaction.js +7 -919
- package/package/acode/dist/config.d.ts +0 -1
- package/package/acode/dist/config.js +5 -105
- package/package/acode/dist/fs-utils.d.ts +0 -1
- package/package/acode/dist/fs-utils.js +2 -79
- package/package/acode/dist/hooks/hookBus.d.ts +0 -1
- package/package/acode/dist/hooks/hookBus.js +2 -40
- package/package/acode/dist/index.d.ts +0 -1
- package/package/acode/dist/index.js +2 -19
- package/package/acode/dist/mcpToolNames.d.ts +0 -1
- package/package/acode/dist/mcpToolNames.js +2 -17
- package/package/acode/dist/parsers/ast-cache.d.ts +0 -1
- package/package/acode/dist/parsers/ast-cache.js +2 -76
- package/package/acode/dist/parsers/language-detector.d.ts +0 -1
- package/package/acode/dist/parsers/language-detector.js +2 -44
- package/package/acode/dist/parsers/language-queries.d.ts +0 -1
- package/package/acode/dist/parsers/language-queries.js +12 -602
- package/package/acode/dist/parsers/symbol-extractor.d.ts +0 -1
- package/package/acode/dist/parsers/symbol-extractor.js +3 -164
- package/package/acode/dist/parsers/tree-sitter-loader.d.ts +0 -1
- package/package/acode/dist/parsers/tree-sitter-loader.js +2 -64
- package/package/acode/dist/parsers/types.d.ts +0 -1
- package/package/acode/dist/parsers/types.js +1 -7
- package/package/acode/dist/runtime.d.ts +0 -1
- package/package/acode/dist/runtime.js +86 -3771
- package/package/acode/dist/skill-tool.d.ts +0 -1
- package/package/acode/dist/skill-tool.js +5 -174
- package/package/acode/dist/sub-agent-manager.d.ts +0 -1
- package/package/acode/dist/sub-agent-manager.js +2 -1159
- package/package/acode/dist/sub-agent-store.d.ts +0 -1
- package/package/acode/dist/sub-agent-store.js +4 -236
- package/package/acode/dist/sub-agent-tools.d.ts +0 -1
- package/package/acode/dist/sub-agent-tools.js +15 -369
- package/package/acode/dist/sub-agent-types.d.ts +0 -1
- package/package/acode/dist/sub-agent-types.js +1 -8
- package/package/acode/dist/todo-store.d.ts +0 -1
- package/package/acode/dist/todo-store.js +2 -73
- package/package/acode/dist/todo-tool.d.ts +0 -1
- package/package/acode/dist/todo-tool.js +5 -121
- package/package/acode/dist/types.d.ts +0 -1
- package/package/acode/dist/types.js +1 -1
- package/package/acode/package.json +2 -2
- package/package/aws-client-agent-mcp/dist/agent-client.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/agent-client.js +2 -890
- package/package/aws-client-agent-mcp/dist/agent-client.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/agent-client.test.js +0 -1
- package/package/aws-client-agent-mcp/dist/config.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/config.js +2 -243
- package/package/aws-client-agent-mcp/dist/config.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/config.test.js +0 -1
- package/package/aws-client-agent-mcp/dist/constants.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/constants.js +2 -24
- package/package/aws-client-agent-mcp/dist/context-manager.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/context-manager.js +2 -477
- package/package/aws-client-agent-mcp/dist/context-manager.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/context-manager.test.js +0 -1
- package/package/aws-client-agent-mcp/dist/http-client.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/http-client.js +2 -446
- package/package/aws-client-agent-mcp/dist/http-client.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/http-client.test.js +0 -1
- package/package/aws-client-agent-mcp/dist/index.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/index.js +2 -34
- package/package/aws-client-agent-mcp/dist/logger.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/logger.js +3 -178
- package/package/aws-client-agent-mcp/dist/logger.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/logger.test.js +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.js +38 -2709
- package/package/aws-client-agent-mcp/dist/mcp-server.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.test.js +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-tools.js +22 -562
- package/package/aws-client-agent-mcp/dist/mcp-tools.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-tools.test.js +0 -1
- package/package/aws-client-agent-mcp/dist/memory-store.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/memory-store.js +4 -826
- package/package/aws-client-agent-mcp/dist/memory-store.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/memory-store.test.js +0 -1
- package/package/aws-client-agent-mcp/dist/memory-tools.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/memory-tools.js +31 -294
- package/package/aws-client-agent-mcp/dist/message-buffer.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/message-buffer.js +2 -288
- package/package/aws-client-agent-mcp/dist/message-buffer.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/message-buffer.test.js +0 -1
- package/package/aws-client-agent-mcp/dist/messageContent.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/messageContent.js +2 -125
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.js +2 -103
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.js +0 -1
- package/package/aws-client-agent-mcp/dist/server-memory-store.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/server-memory-store.js +2 -96
- package/package/aws-client-agent-mcp/dist/status-reporter.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/status-reporter.js +3 -327
- package/package/aws-client-agent-mcp/dist/status-reporter.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/status-reporter.test.js +0 -1
- package/package/aws-client-agent-mcp/dist/types.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/types.js +2 -9
- package/package/aws-client-agent-mcp/dist/websocket-client.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/websocket-client.js +2 -677
- package/package/aws-client-agent-mcp/dist/websocket-client.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/websocket-client.test.js +0 -1
- package/package/aws-client-agent-mcp/package.json +1 -1
- package/package/cc-switch-sdk/dist/constants.d.ts +0 -1
- package/package/cc-switch-sdk/dist/constants.js +2 -63
- package/package/cc-switch-sdk/dist/errors.d.ts +0 -1
- package/package/cc-switch-sdk/dist/errors.js +2 -8
- package/package/cc-switch-sdk/dist/index.d.ts +0 -1
- package/package/cc-switch-sdk/dist/index.js +2 -9
- package/package/cc-switch-sdk/dist/schemas.d.ts +0 -1
- package/package/cc-switch-sdk/dist/schemas.js +2 -38
- package/package/cc-switch-sdk/dist/sdk.d.ts +0 -1
- package/package/cc-switch-sdk/dist/sdk.js +2 -470
- package/package/cc-switch-sdk/dist/services/ai-config-service.d.ts +0 -1
- package/package/cc-switch-sdk/dist/services/ai-config-service.js +4 -307
- package/package/cc-switch-sdk/dist/services/mcp-model.d.ts +0 -1
- package/package/cc-switch-sdk/dist/services/mcp-model.js +2 -37
- package/package/cc-switch-sdk/dist/services/mcp-service.d.ts +0 -1
- package/package/cc-switch-sdk/dist/services/mcp-service.js +2 -9
- package/package/cc-switch-sdk/dist/services/skill-model.d.ts +0 -1
- package/package/cc-switch-sdk/dist/services/skill-model.js +2 -41
- package/package/cc-switch-sdk/dist/services/skill-service.d.ts +0 -1
- package/package/cc-switch-sdk/dist/services/skill-service.js +2 -9
- package/package/cc-switch-sdk/dist/state.d.ts +0 -1
- package/package/cc-switch-sdk/dist/state.js +2 -19
- package/package/cc-switch-sdk/dist/types.d.ts +0 -1
- package/package/cc-switch-sdk/dist/types.js +1 -1
- package/package/cc-switch-sdk/dist/utils/fs.d.ts +0 -1
- package/package/cc-switch-sdk/dist/utils/fs.js +3 -114
- package/package/cc-switch-sdk/dist/utils/id.d.ts +0 -1
- package/package/cc-switch-sdk/dist/utils/id.js +2 -12
- package/package/cc-switch-sdk/package.json +1 -1
- package/package.json +4 -2
- package/dist/adapter/AcodeSdkAdapter.d.ts.map +0 -1
- package/dist/adapter/AdapterRegistry.d.ts.map +0 -1
- package/dist/adapter/ClaudeSdkAdapter.d.ts.map +0 -1
- package/dist/adapter/CodexSdkAdapter.d.ts.map +0 -1
- package/dist/adapter/OpencodeSdkAdapter.d.ts.map +0 -1
- package/dist/adapter/SdkProviderSpi.d.ts.map +0 -1
- package/dist/adapter/acode-tool-names.d.ts.map +0 -1
- package/dist/adapter/idle-poll-loop.d.ts.map +0 -1
- package/dist/adapter/index.d.ts.map +0 -1
- package/dist/adapter/instance-ai-config-resolver.d.ts.map +0 -1
- package/dist/adapter/types.d.ts.map +0 -1
- package/dist/adapters/cc-switch/common.d.ts.map +0 -1
- package/dist/adapters/cc-switch/index.d.ts.map +0 -1
- package/dist/adapters/cc-switch/mcp-acode.d.ts.map +0 -1
- package/dist/adapters/cc-switch/mcp-claude.d.ts.map +0 -1
- package/dist/adapters/cc-switch/mcp-claudecode.d.ts.map +0 -1
- package/dist/adapters/cc-switch/mcp-codex.d.ts.map +0 -1
- package/dist/adapters/cc-switch/mcp-opencode.d.ts.map +0 -1
- package/dist/adapters/cc-switch/mcp-placeholder.d.ts.map +0 -1
- package/dist/adapters/cc-switch/skill-acode.d.ts.map +0 -1
- package/dist/adapters/cc-switch/skill-claude.d.ts.map +0 -1
- package/dist/adapters/cc-switch/skill-claudecode.d.ts.map +0 -1
- package/dist/adapters/cc-switch/skill-codex.d.ts.map +0 -1
- package/dist/adapters/cc-switch/skill-directory.d.ts.map +0 -1
- package/dist/adapters/cc-switch/skill-opencode.d.ts.map +0 -1
- package/dist/adapters/cc-switch/skill-placeholder.d.ts.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/middleware/auth.d.ts.map +0 -1
- package/dist/routes/acode-todos.d.ts.map +0 -1
- package/dist/routes/ai-sources.d.ts.map +0 -1
- package/dist/routes/dashboard.d.ts.map +0 -1
- package/dist/routes/events.d.ts.map +0 -1
- package/dist/routes/file-browser.d.ts.map +0 -1
- package/dist/routes/file-diff-rollback.d.ts.map +0 -1
- package/dist/routes/file-snapshot.d.ts.map +0 -1
- package/dist/routes/git.d.ts.map +0 -1
- package/dist/routes/instance.d.ts.map +0 -1
- package/dist/routes/mcp.d.ts.map +0 -1
- package/dist/routes/processes.d.ts.map +0 -1
- package/dist/routes/properties.d.ts.map +0 -1
- package/dist/routes/pty.d.ts.map +0 -1
- package/dist/routes/runtime-binding.d.ts.map +0 -1
- package/dist/routes/sessions.d.ts.map +0 -1
- package/dist/routes/skills.d.ts.map +0 -1
- package/dist/routes/sub-agents.d.ts.map +0 -1
- package/dist/routes/system-metrics.d.ts.map +0 -1
- package/dist/routes/task-context.d.ts.map +0 -1
- package/dist/routes/terminal.d.ts.map +0 -1
- package/dist/routes/yml.d.ts.map +0 -1
- package/dist/services/acode-package.d.ts.map +0 -1
- package/dist/services/agent-event-store.d.ts.map +0 -1
- package/dist/services/agent-process-manager.d.ts.map +0 -1
- package/dist/services/ai-source-apply.d.ts.map +0 -1
- package/dist/services/auto-register.d.ts.map +0 -1
- package/dist/services/aws-client-agent-mcp.d.ts.map +0 -1
- package/dist/services/bridge-package-publish-hooks.d.ts.map +0 -1
- package/dist/services/cc-switch-sdk.d.ts.map +0 -1
- package/dist/services/cli-commands.d.ts.map +0 -1
- package/dist/services/event-delta-pusher.d.ts.map +0 -1
- package/dist/services/fileSnapshotStore.d.ts.map +0 -1
- package/dist/services/instance-ai-config-service.d.ts.map +0 -1
- package/dist/services/instance-init-service.d.ts.map +0 -1
- package/dist/services/instance-service.d.ts.map +0 -1
- package/dist/services/instance-state.d.ts.map +0 -1
- package/dist/services/legacy-path-migration.d.ts.map +0 -1
- package/dist/services/lifecycle-state.d.ts.map +0 -1
- package/dist/services/mcp-launch-binding-queue.d.ts.map +0 -1
- package/dist/services/orphan-monitor.d.ts.map +0 -1
- package/dist/services/panel-auth.d.ts.map +0 -1
- package/dist/services/process-detector.d.ts.map +0 -1
- package/dist/services/process-registry.d.ts.map +0 -1
- package/dist/services/ring-buffer.d.ts.map +0 -1
- package/dist/services/runtime-binding.d.ts.map +0 -1
- package/dist/services/runtime-lifecycle-policy.d.ts.map +0 -1
- package/dist/services/session-output.d.ts.map +0 -1
- package/dist/services/startup-config-wizard.d.ts.map +0 -1
- package/dist/services/sub-agent-manager-instance.d.ts.map +0 -1
- package/dist/services/system-metrics.d.ts.map +0 -1
- package/dist/services/terminal-persistence.d.ts.map +0 -1
- package/dist/services/tool-installer.d.ts.map +0 -1
- package/dist/services/tunnel-client.d.ts.map +0 -1
- package/dist/services/windows-service-manager.d.ts.map +0 -1
- package/dist/services/workspace-files.d.ts.map +0 -1
- package/dist/services/workspace-watch.d.ts.map +0 -1
- package/dist/services/workspaceTaskChangeWatcher.d.ts.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/utils/file-utils.d.ts.map +0 -1
- package/dist/utils/instance-ai-config-debug-logger.d.ts.map +0 -1
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/mcp-utils.d.ts.map +0 -1
- package/dist/utils/path-utils.d.ts.map +0 -1
- package/dist/utils/sdk-package-loader.d.ts.map +0 -1
- package/dist/utils/validation.d.ts.map +0 -1
- package/dist/utils/yaml-utils.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/constants.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/errors.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/index.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/schemas.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/sdk.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/services/ai-config-service.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/services/mcp-model.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/services/mcp-service.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/services/skill-model.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/services/skill-service.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/state.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/types.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/utils/fs.d.ts.map +0 -1
- package/node_modules/@cc-switch/sdk/dist/utils/id.d.ts.map +0 -1
- package/package/acode/dist/ask-user-question-tool.d.ts.map +0 -1
- package/package/acode/dist/built-in-file-tools.d.ts.map +0 -1
- package/package/acode/dist/built-in-symbols-tool.d.ts.map +0 -1
- package/package/acode/dist/builtins/commandArtifacts.d.ts.map +0 -1
- package/package/acode/dist/builtins/commandOutputEvents.d.ts.map +0 -1
- package/package/acode/dist/builtins/shellCommandPreparation.d.ts.map +0 -1
- package/package/acode/dist/builtins/shellCommandResult.d.ts.map +0 -1
- package/package/acode/dist/builtins/shellCommandRunner.d.ts.map +0 -1
- package/package/acode/dist/builtins/shellOutputDecoder.d.ts.map +0 -1
- package/package/acode/dist/cli.d.ts.map +0 -1
- package/package/acode/dist/commands/commandLoader.d.ts.map +0 -1
- package/package/acode/dist/commands/commandParser.d.ts.map +0 -1
- package/package/acode/dist/commands/commandRegistry.d.ts.map +0 -1
- package/package/acode/dist/compaction.d.ts.map +0 -1
- package/package/acode/dist/config.d.ts.map +0 -1
- package/package/acode/dist/fs-utils.d.ts.map +0 -1
- package/package/acode/dist/hooks/hookBus.d.ts.map +0 -1
- package/package/acode/dist/index.d.ts.map +0 -1
- package/package/acode/dist/mcpToolNames.d.ts.map +0 -1
- package/package/acode/dist/parsers/ast-cache.d.ts.map +0 -1
- package/package/acode/dist/parsers/language-detector.d.ts.map +0 -1
- package/package/acode/dist/parsers/language-queries.d.ts.map +0 -1
- package/package/acode/dist/parsers/symbol-extractor.d.ts.map +0 -1
- package/package/acode/dist/parsers/tree-sitter-loader.d.ts.map +0 -1
- package/package/acode/dist/parsers/types.d.ts.map +0 -1
- package/package/acode/dist/runtime.d.ts.map +0 -1
- package/package/acode/dist/skill-tool.d.ts.map +0 -1
- package/package/acode/dist/sub-agent-manager.d.ts.map +0 -1
- package/package/acode/dist/sub-agent-store.d.ts.map +0 -1
- package/package/acode/dist/sub-agent-tools.d.ts.map +0 -1
- package/package/acode/dist/sub-agent-types.d.ts.map +0 -1
- package/package/acode/dist/todo-store.d.ts.map +0 -1
- package/package/acode/dist/todo-tool.d.ts.map +0 -1
- package/package/acode/dist/types.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/agent-client.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/agent-client.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/agent-client.test.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/agent-client.test.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/config.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/config.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/config.test.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/config.test.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/constants.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/constants.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/context-manager.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/context-manager.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/context-manager.test.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/context-manager.test.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/http-client.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/http-client.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/http-client.test.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/http-client.test.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/index.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/index.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/logger.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/logger.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/logger.test.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/logger.test.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.test.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.test.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-tools.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-tools.test.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-tools.test.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/memory-store.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/memory-store.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/memory-store.test.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/memory-store.test.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/memory-tools.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/memory-tools.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/message-buffer.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/message-buffer.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/message-buffer.test.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/message-buffer.test.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/messageContent.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/messageContent.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/server-memory-store.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/server-memory-store.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/status-reporter.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/status-reporter.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/status-reporter.test.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/status-reporter.test.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/types.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/types.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/websocket-client.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/websocket-client.js.map +0 -1
- package/package/aws-client-agent-mcp/dist/websocket-client.test.d.ts.map +0 -1
- package/package/aws-client-agent-mcp/dist/websocket-client.test.js.map +0 -1
- package/package/cc-switch-sdk/dist/constants.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/errors.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/index.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/schemas.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/sdk.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/services/ai-config-service.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/services/mcp-model.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/services/mcp-service.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/services/skill-model.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/services/skill-service.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/state.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/types.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/utils/fs.d.ts.map +0 -1
- package/package/cc-switch-sdk/dist/utils/id.d.ts.map +0 -1
|
@@ -1,919 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
*
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
*
|
|
7
|
-
|
|
8
|
-
* 触发时机:在每次 AI 请求前检测 token 是否溢出,溢出则执行压缩
|
|
9
|
-
*
|
|
10
|
-
* 与 OpenCode 的对应关系:
|
|
11
|
-
* - isOverflow ↔ SessionCompaction.isOverflow
|
|
12
|
-
* - prune ↔ SessionCompaction.prune
|
|
13
|
-
* - summarize ↔ SessionCompaction.process (LLM 摘要的简化版)
|
|
14
|
-
*/
|
|
15
|
-
// ============ 常量(与 OpenCode compaction.ts 对齐) ============
|
|
16
|
-
/** 压缩缓冲区:保留这么多 token 的空闲空间,避免压缩过程中溢出 */
|
|
17
|
-
export const COMPACTION_BUFFER = 20_000;
|
|
18
|
-
/**
|
|
19
|
-
* 基础压缩触发比例(兜底默认值,仅用于 contextLimit <= 0 的异常场景)。
|
|
20
|
-
* 正常情况下通过 {@link getCompactionTriggerRatio} 按窗口大小动态分级。
|
|
21
|
-
*/
|
|
22
|
-
export const COMPACTION_TRIGGER_RATIO = 0.55;
|
|
23
|
-
/**
|
|
24
|
-
* 压缩触发比例的窗口分级表。
|
|
25
|
-
* 大窗口下压缩成本高(LLM 摘要调用 + 上下文丢失风险),应提高比例充分利用窗口;
|
|
26
|
-
* 小窗口下压缩成本低,可适当降低比例以及时释放空间。
|
|
27
|
-
*
|
|
28
|
-
* | 窗口大小 | 比例 |
|
|
29
|
-
* |---------------|-------|
|
|
30
|
-
* | < 32K | 0.70 |
|
|
31
|
-
* | 32K - 128K | 0.75 |
|
|
32
|
-
* | 128K - 512K | 0.80 |
|
|
33
|
-
* | ≥ 512K | 0.85 |
|
|
34
|
-
*/
|
|
35
|
-
const COMPACTION_TRIGGER_RATIO_TIERS = [
|
|
36
|
-
[32_000, 0.70],
|
|
37
|
-
[128_000, 0.75],
|
|
38
|
-
[512_000, 0.80],
|
|
39
|
-
[Number.POSITIVE_INFINITY, 0.85],
|
|
40
|
-
];
|
|
41
|
-
/** 按上下文窗口大小返回压缩触发比例(大窗口更高,充分利用空间)。 */
|
|
42
|
-
export function getCompactionTriggerRatio(contextLimit) {
|
|
43
|
-
if (contextLimit <= 0)
|
|
44
|
-
return COMPACTION_TRIGGER_RATIO;
|
|
45
|
-
for (const [limit, ratio] of COMPACTION_TRIGGER_RATIO_TIERS) {
|
|
46
|
-
if (contextLimit < limit)
|
|
47
|
-
return ratio;
|
|
48
|
-
}
|
|
49
|
-
return 0.85;
|
|
50
|
-
}
|
|
51
|
-
/** Prune 保护线默认值:保留最近 PRUNE_PROTECT token 的工具输出完整。
|
|
52
|
-
* 注意:实际使用时会按 contextLimit 比例调整(见 pruneToolOutputs),
|
|
53
|
-
* 避免在小上下文窗口(如 60k)下保护线过高导致 prune 永不触发。
|
|
54
|
-
*/
|
|
55
|
-
export const PRUNE_PROTECT = 40_000;
|
|
56
|
-
/** Prune 最小收益默认值:累计可释放 token 不足此数时跳过修剪。
|
|
57
|
-
* 注意:实际使用时会按 contextLimit 比例调整。
|
|
58
|
-
*/
|
|
59
|
-
export const PRUNE_MINIMUM = 20_000;
|
|
60
|
-
/** Prune 保护线占 contextLimit 的比例(取较小者:固定值或比例值) */
|
|
61
|
-
const PRUNE_PROTECT_RATIO = 0.5;
|
|
62
|
-
/** Prune 最小收益占 contextLimit 的比例 */
|
|
63
|
-
const PRUNE_MINIMUM_RATIO = 0.1;
|
|
64
|
-
/** Prune 白名单:这些工具的输出永远不会被裁剪 */
|
|
65
|
-
const PRUNE_PROTECTED_TOOLS = new Set(["skill", "todo_write", "todo_read"]);
|
|
66
|
-
/**
|
|
67
|
-
* 工具重要性等级(数字越小越重要,越优先保护)。
|
|
68
|
-
* 用于 prune 时按重要性排序:裁剪时优先移除低重要性的工具输出。
|
|
69
|
-
*/
|
|
70
|
-
const TOOL_IMPORTANCE = {
|
|
71
|
-
// 最高保护:文件读取和搜索类(结果包含关键上下文)
|
|
72
|
-
"read_file": 0,
|
|
73
|
-
"Read": 0,
|
|
74
|
-
"grep": 0,
|
|
75
|
-
"Grep": 0,
|
|
76
|
-
"glob": 0,
|
|
77
|
-
"Glob": 0,
|
|
78
|
-
"contextweaver_codebase-retrieval": 0,
|
|
79
|
-
// 高保护:文件写入和编辑(确认信息)
|
|
80
|
-
"Edit": 1,
|
|
81
|
-
"edit": 1,
|
|
82
|
-
"Write": 1,
|
|
83
|
-
"write": 1,
|
|
84
|
-
"write_file": 1,
|
|
85
|
-
// 中保护:网络请求
|
|
86
|
-
"webfetch": 2,
|
|
87
|
-
"WebFetch": 2,
|
|
88
|
-
"WebSearch": 2,
|
|
89
|
-
"websearch_web_search_exa": 2,
|
|
90
|
-
// 低保护:命令行执行(输出通常可丢弃)
|
|
91
|
-
"bash": 3,
|
|
92
|
-
"Bash": 3,
|
|
93
|
-
"run_terminal_command": 3,
|
|
94
|
-
// 最低保护:UI 操作
|
|
95
|
-
"playwright_browser_": 4,
|
|
96
|
-
};
|
|
97
|
-
/** 默认重要性(不在 TOOL_IMPORTANCE 中的工具) */
|
|
98
|
-
const DEFAULT_TOOL_IMPORTANCE = 2;
|
|
99
|
-
/**
|
|
100
|
-
* 获取工具的重要性等级。
|
|
101
|
-
* 支持前缀匹配(如 "playwright_browser_navigate" 匹配 "playwright_browser_")。
|
|
102
|
-
*/
|
|
103
|
-
function getToolImportance(toolName) {
|
|
104
|
-
if (!toolName)
|
|
105
|
-
return DEFAULT_TOOL_IMPORTANCE;
|
|
106
|
-
if (TOOL_IMPORTANCE[toolName] !== undefined)
|
|
107
|
-
return TOOL_IMPORTANCE[toolName];
|
|
108
|
-
// 前缀匹配(按长度降序)
|
|
109
|
-
const matches = Object.keys(TOOL_IMPORTANCE)
|
|
110
|
-
.filter((key) => toolName.startsWith(key))
|
|
111
|
-
.sort((a, b) => b.length - a.length);
|
|
112
|
-
if (matches.length > 0) {
|
|
113
|
-
return TOOL_IMPORTANCE[matches[0]];
|
|
114
|
-
}
|
|
115
|
-
return DEFAULT_TOOL_IMPORTANCE;
|
|
116
|
-
}
|
|
117
|
-
/** 默认上下文窗口上限(查找不到模型时使用) */
|
|
118
|
-
const DEFAULT_CONTEXT_LIMIT = 128_000;
|
|
119
|
-
/** 默认最大输出 token */
|
|
120
|
-
const DEFAULT_MAX_OUTPUT = 8_192;
|
|
121
|
-
/** 压缩后保留的最近消息条数。
|
|
122
|
-
* 注意:此值针对 compactable 消息(user/assistant/tool,不含 system)。
|
|
123
|
-
* 设为 8 而非 12,避免在常见场景(4 条 system + 12 条非 system = 16 条总消息)下
|
|
124
|
-
* removableCount = max(0, 12 - 12) = 0 导致 summarize 完全不生效。
|
|
125
|
-
*/
|
|
126
|
-
const COMPACTION_RECENT_MESSAGE_COUNT = 8;
|
|
127
|
-
/** 摘要最大字符数 */
|
|
128
|
-
const COMPACTION_MAX_SUMMARY_CHARS = 6000;
|
|
129
|
-
/** 单条消息预览最大字符数 */
|
|
130
|
-
const COMPACTION_MAX_PREVIEW_CHARS = 500;
|
|
131
|
-
/** 摘要前缀标识 */
|
|
132
|
-
const COMPACTION_SUMMARY_PREFIX = "ACode context compaction summary:";
|
|
133
|
-
/**
|
|
134
|
-
* LLM 摘要 prompt 模板(OpenCode 风格结构化摘要)。
|
|
135
|
-
*
|
|
136
|
-
* 用于 summarizeConversationWithLLM:追加到 user 消息末尾,指导 LLM 按结构化
|
|
137
|
-
* 段落(Goal/Instructions/Discoveries/Accomplished/Files)输出摘要,便于后续
|
|
138
|
-
* 轮次快速恢复上下文。LLM 摘要失败时降级到 rule-based summarizeConversation。
|
|
139
|
-
*/
|
|
140
|
-
export const COMPACTION_LLM_PROMPT_TEMPLATE = [
|
|
141
|
-
"Please summarize the conversation above using the following structured format.",
|
|
142
|
-
"Keep each section concise but preserve all actionable details.",
|
|
143
|
-
"",
|
|
144
|
-
"## Goal",
|
|
145
|
-
"The user's primary objective in this conversation.",
|
|
146
|
-
"",
|
|
147
|
-
"## Instructions",
|
|
148
|
-
"Standing instructions, constraints, or preferences the user has stated.",
|
|
149
|
-
"",
|
|
150
|
-
"## Discoveries",
|
|
151
|
-
"Key findings, decisions, tool results, file paths, and errors encountered.",
|
|
152
|
-
"",
|
|
153
|
-
"## Accomplished",
|
|
154
|
-
"Tasks that have been completed (do not redo these).",
|
|
155
|
-
"",
|
|
156
|
-
"## Files",
|
|
157
|
-
"Files read, modified, or created with brief context.",
|
|
158
|
-
"",
|
|
159
|
-
"Output only the summary, no preamble.",
|
|
160
|
-
].join("\n");
|
|
161
|
-
/** 中文字符 token 估算系数:约 1.5 字符/token */
|
|
162
|
-
const ESTIMATION_CJK_CHARS_PER_TOKEN = 1.5;
|
|
163
|
-
/** ASCII 字符 token 估算系数:约 4 字符/token */
|
|
164
|
-
const ESTIMATION_ASCII_CHARS_PER_TOKEN = 4;
|
|
165
|
-
/**
|
|
166
|
-
* Token 估算安全填充系数。
|
|
167
|
-
* 参考 Claude Code 的 ×4/3 策略:本地估算始终比实际 token 数偏小,
|
|
168
|
-
* 乘以安全系数确保估算值 >= 实际值,避免在溢出前来不及压缩。
|
|
169
|
-
*/
|
|
170
|
-
const ESTIMATION_SAFE_PADDING = 1.15;
|
|
171
|
-
/** 图片/文档块固定 token 估算值(参考 Claude Code 的 2000 tokens/image) */
|
|
172
|
-
const ESTIMATION_IMAGE_TOKENS = 2000;
|
|
173
|
-
/** 工具调用 JSON 结构附加开销(tool_call_id + role 等) */
|
|
174
|
-
const ESTIMATION_TOOL_OVERHEAD = 8;
|
|
175
|
-
/**
|
|
176
|
-
* 计算压缩触发阈值:取 min(contextLimit × 动态比例, hardLimit - reserved)。
|
|
177
|
-
*
|
|
178
|
-
* - ratioBased = contextLimit × getCompactionTriggerRatio(contextLimit)(按窗口大小动态分级)
|
|
179
|
-
* - hardLimit = inputLimit ?? contextLimit(provider 显式 inputLimit 优先)
|
|
180
|
-
* - reserved = min(COMPACTION_BUFFER, maxOutput)(buffer 不超过输出上限)
|
|
181
|
-
*
|
|
182
|
-
* 取两者较小者,既避免小窗口下过早触发,又避免接近硬上限时来不及压缩。
|
|
183
|
-
*/
|
|
184
|
-
export function calculateCompactionThreshold(contextLimit, maxOutput, inputLimit) {
|
|
185
|
-
const ratioBased = Math.floor(contextLimit * getCompactionTriggerRatio(contextLimit));
|
|
186
|
-
const hardLimit = inputLimit ?? contextLimit;
|
|
187
|
-
const reserved = Math.min(COMPACTION_BUFFER, maxOutput);
|
|
188
|
-
const hardLimitBased = hardLimit - reserved;
|
|
189
|
-
return Math.min(ratioBased, hardLimitBased);
|
|
190
|
-
}
|
|
191
|
-
// ============ 模型上下文窗口查找 ============
|
|
192
|
-
/**
|
|
193
|
-
* 知名模型的上下文窗口大小查找表。
|
|
194
|
-
* 数据来源:各模型官方文档。
|
|
195
|
-
*/
|
|
196
|
-
const MODEL_CONTEXT_LIMITS = {
|
|
197
|
-
// Anthropic Claude
|
|
198
|
-
"claude-4": { contextLimit: 200_000, maxOutput: 8_192 },
|
|
199
|
-
"claude-sonnet-4": { contextLimit: 200_000, maxOutput: 8_192 },
|
|
200
|
-
"claude-3-5-sonnet": { contextLimit: 200_000, maxOutput: 8_192 },
|
|
201
|
-
"claude-3-opus": { contextLimit: 200_000, maxOutput: 8_192 },
|
|
202
|
-
"claude-3-haiku": { contextLimit: 200_000, maxOutput: 8_192 },
|
|
203
|
-
"claude-2": { contextLimit: 100_000, maxOutput: 4_096 },
|
|
204
|
-
// OpenAI GPT
|
|
205
|
-
"gpt-4o": { contextLimit: 128_000, maxOutput: 16_384 },
|
|
206
|
-
"gpt-4-turbo": { contextLimit: 128_000, maxOutput: 4_096 },
|
|
207
|
-
"gpt-4": { contextLimit: 8_192, maxOutput: 4_096 },
|
|
208
|
-
"gpt-3.5-turbo": { contextLimit: 16_384, maxOutput: 4_096 },
|
|
209
|
-
"o1": { contextLimit: 200_000, maxOutput: 100_000 },
|
|
210
|
-
"o3-mini": { contextLimit: 200_000, maxOutput: 100_000 },
|
|
211
|
-
// Google Gemini
|
|
212
|
-
"gemini-2.0-flash": { contextLimit: 1_048_576, maxOutput: 8_192 },
|
|
213
|
-
"gemini-2.5-pro": { contextLimit: 1_048_576, maxOutput: 8_192 },
|
|
214
|
-
"gemini-1.5-pro": { contextLimit: 2_097_152, maxOutput: 8_192 },
|
|
215
|
-
"gemini-1.5-flash": { contextLimit: 1_048_576, maxOutput: 8_192 },
|
|
216
|
-
// DeepSeek
|
|
217
|
-
"deepseek": { contextLimit: 64_000, maxOutput: 8_192 },
|
|
218
|
-
"deepseek-chat": { contextLimit: 64_000, maxOutput: 8_192 },
|
|
219
|
-
"deepseek-reasoner": { contextLimit: 64_000, maxOutput: 8_192 },
|
|
220
|
-
// Qwen
|
|
221
|
-
"qwen-max": { contextLimit: 32_000, maxOutput: 8_192 },
|
|
222
|
-
"qwen-plus": { contextLimit: 128_000, maxOutput: 8_192 },
|
|
223
|
-
"qwen-turbo": { contextLimit: 1_000_000, maxOutput: 8_192 },
|
|
224
|
-
// GLM
|
|
225
|
-
"glm-4": { contextLimit: 128_000, maxOutput: 4_096 },
|
|
226
|
-
// Yi
|
|
227
|
-
"yi-": { contextLimit: 200_000, maxOutput: 4_096 },
|
|
228
|
-
// Meta Llama
|
|
229
|
-
"llama-3": { contextLimit: 8_192, maxOutput: 4_096 },
|
|
230
|
-
"llama-2": { contextLimit: 4_096, maxOutput: 4_096 },
|
|
231
|
-
// Mistral
|
|
232
|
-
"mistral": { contextLimit: 32_000, maxOutput: 4_096 },
|
|
233
|
-
"mixtral": { contextLimit: 32_000, maxOutput: 4_096 },
|
|
234
|
-
"codestral": { contextLimit: 256_000, maxOutput: 8_192 },
|
|
235
|
-
// Grok
|
|
236
|
-
"grok": { contextLimit: 131_072, maxOutput: 4_096 },
|
|
237
|
-
// Amazon Nova
|
|
238
|
-
"nova-": { contextLimit: 200_000, maxOutput: 8_192 },
|
|
239
|
-
};
|
|
240
|
-
/**
|
|
241
|
-
* 根据模型名查找上下文窗口大小。
|
|
242
|
-
* 主流程:优先使用传入的 configOverrides → 精确匹配 → 前缀匹配(按长度降序)→ 默认值。
|
|
243
|
-
*
|
|
244
|
-
* @param modelName 模型名
|
|
245
|
-
* @param configOverrides 可选的配置覆盖值(来自 acode.json 的 contextLimit/maxOutput)
|
|
246
|
-
*/
|
|
247
|
-
export function lookupModelLimits(modelName, configOverrides) {
|
|
248
|
-
// 配置覆盖优先(来自 acode.json 等模板配置)
|
|
249
|
-
if (configOverrides?.contextLimit && configOverrides.contextLimit > 0) {
|
|
250
|
-
return {
|
|
251
|
-
contextLimit: configOverrides.contextLimit,
|
|
252
|
-
maxOutput: configOverrides.maxOutput ?? DEFAULT_MAX_OUTPUT,
|
|
253
|
-
};
|
|
254
|
-
}
|
|
255
|
-
if (!modelName)
|
|
256
|
-
return { contextLimit: DEFAULT_CONTEXT_LIMIT, maxOutput: DEFAULT_MAX_OUTPUT };
|
|
257
|
-
const key = modelName.toLowerCase().trim();
|
|
258
|
-
if (MODEL_CONTEXT_LIMITS[key])
|
|
259
|
-
return MODEL_CONTEXT_LIMITS[key];
|
|
260
|
-
const matches = Object.keys(MODEL_CONTEXT_LIMITS)
|
|
261
|
-
.filter((prefix) => key.startsWith(prefix))
|
|
262
|
-
.sort((a, b) => b.length - a.length);
|
|
263
|
-
if (matches.length > 0)
|
|
264
|
-
return MODEL_CONTEXT_LIMITS[matches[0]];
|
|
265
|
-
return { contextLimit: DEFAULT_CONTEXT_LIMIT, maxOutput: DEFAULT_MAX_OUTPUT };
|
|
266
|
-
}
|
|
267
|
-
// ============ Token 估算 ============
|
|
268
|
-
/**
|
|
269
|
-
* 中英文分离的文本 token 估算。
|
|
270
|
-
* 对纯 ASCII 约 4 字符/token,对中文约 1.5 字符/token。
|
|
271
|
-
* 参考:context-manager.ts 的同名方法。
|
|
272
|
-
*/
|
|
273
|
-
export function estimateTextTokens(text) {
|
|
274
|
-
if (!text)
|
|
275
|
-
return 0;
|
|
276
|
-
let cjkCount = 0;
|
|
277
|
-
let asciiCount = 0;
|
|
278
|
-
for (const ch of text) {
|
|
279
|
-
if (ch > "\u00ff") {
|
|
280
|
-
cjkCount++;
|
|
281
|
-
}
|
|
282
|
-
else {
|
|
283
|
-
asciiCount++;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
return Math.ceil(cjkCount / ESTIMATION_CJK_CHARS_PER_TOKEN + asciiCount / ESTIMATION_ASCII_CHARS_PER_TOKEN);
|
|
287
|
-
}
|
|
288
|
-
/**
|
|
289
|
-
* 粗略估算文本的 token 数(保留向后兼容)。
|
|
290
|
-
* 使用 estimateTextTokens 的中英文分离 + 安全填充。
|
|
291
|
-
*/
|
|
292
|
-
export function estimateTokens(text) {
|
|
293
|
-
if (!text)
|
|
294
|
-
return 0;
|
|
295
|
-
// × ESTIMATION_SAFE_PADDING 确保估算始终偏大(安全侧)
|
|
296
|
-
// 参考 Claude Code 的 estimateMessageTokens 的 ×4/3 策略
|
|
297
|
-
return Math.ceil(estimateTextTokens(text) * ESTIMATION_SAFE_PADDING);
|
|
298
|
-
}
|
|
299
|
-
/**
|
|
300
|
-
* 块级内容 token 估算:识别 text/image_url 等不同块类型分别定价。
|
|
301
|
-
*/
|
|
302
|
-
function estimateContentBlock(block) {
|
|
303
|
-
if (typeof block === "object" && block !== null) {
|
|
304
|
-
const record = block;
|
|
305
|
-
if (record.type === "text" && typeof record.text === "string") {
|
|
306
|
-
return estimateTokens(record.text);
|
|
307
|
-
}
|
|
308
|
-
if (record.type === "image_url" || record.type === "document") {
|
|
309
|
-
return ESTIMATION_IMAGE_TOKENS;
|
|
310
|
-
}
|
|
311
|
-
// 其他类型(tool_result 嵌套等):JSON 估算
|
|
312
|
-
return Math.ceil(JSON.stringify(block).length / ESTIMATION_ASCII_CHARS_PER_TOKEN);
|
|
313
|
-
}
|
|
314
|
-
if (typeof block === "string") {
|
|
315
|
-
return estimateTokens(block);
|
|
316
|
-
}
|
|
317
|
-
return 0;
|
|
318
|
-
}
|
|
319
|
-
/**
|
|
320
|
-
* 估算单条消息的字节大小。
|
|
321
|
-
*/
|
|
322
|
-
function estimateMessageBytes(message) {
|
|
323
|
-
let size = 16;
|
|
324
|
-
if (typeof message.content === "string") {
|
|
325
|
-
size += message.content.length * 2;
|
|
326
|
-
}
|
|
327
|
-
else if (Array.isArray(message.content)) {
|
|
328
|
-
for (const part of message.content) {
|
|
329
|
-
if (typeof part === "object" && part !== null) {
|
|
330
|
-
size += JSON.stringify(part).length;
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
if (message.tool_calls) {
|
|
335
|
-
size += JSON.stringify(message.tool_calls).length;
|
|
336
|
-
}
|
|
337
|
-
if (message.tool_call_id) {
|
|
338
|
-
size += message.tool_call_id.length;
|
|
339
|
-
}
|
|
340
|
-
return size;
|
|
341
|
-
}
|
|
342
|
-
/**
|
|
343
|
-
* 估算整个对话的 token 数。
|
|
344
|
-
* 使用块级识别 + 中英文分离 + 安全填充。
|
|
345
|
-
*/
|
|
346
|
-
export function estimateConversationTokens(messages) {
|
|
347
|
-
let total = 0;
|
|
348
|
-
for (const msg of messages) {
|
|
349
|
-
if (typeof msg.content === "string") {
|
|
350
|
-
total += estimateTokens(msg.content);
|
|
351
|
-
}
|
|
352
|
-
else if (Array.isArray(msg.content)) {
|
|
353
|
-
for (const part of msg.content) {
|
|
354
|
-
total += estimateContentBlock(part);
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
// tool_calls 结构开销
|
|
358
|
-
if (msg.tool_calls) {
|
|
359
|
-
total += ESTIMATION_TOOL_OVERHEAD + Math.ceil(JSON.stringify(msg.tool_calls).length / ESTIMATION_ASCII_CHARS_PER_TOKEN);
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
return total;
|
|
363
|
-
}
|
|
364
|
-
/**
|
|
365
|
-
* 计算对话的 KB 大小。
|
|
366
|
-
*/
|
|
367
|
-
export function conversationSizeKB(messages) {
|
|
368
|
-
let totalBytes = 0;
|
|
369
|
-
for (const msg of messages) {
|
|
370
|
-
totalBytes += estimateMessageBytes(msg);
|
|
371
|
-
}
|
|
372
|
-
return Math.round((totalBytes / 1024) * 10) / 10;
|
|
373
|
-
}
|
|
374
|
-
/**
|
|
375
|
-
* 判断对话是否上下文溢出(基于文本估算)。
|
|
376
|
-
* 使用显式传入的 contextLimit 和比例触发,不依赖模型名查找表。
|
|
377
|
-
*
|
|
378
|
-
* @param messages 对话消息数组
|
|
379
|
-
* @param contextLimit 上下文窗口上限
|
|
380
|
-
* @param maxOutput 模型最大输出 token(未使用,保留参数兼容)
|
|
381
|
-
*/
|
|
382
|
-
export function isOverflow(messages, contextLimit, _maxOutput) {
|
|
383
|
-
if (contextLimit <= 0)
|
|
384
|
-
return false;
|
|
385
|
-
const totalUsed = estimateConversationTokens(messages);
|
|
386
|
-
const ratioThreshold = Math.floor(contextLimit * getCompactionTriggerRatio(contextLimit));
|
|
387
|
-
return totalUsed >= ratioThreshold;
|
|
388
|
-
}
|
|
389
|
-
/**
|
|
390
|
-
* 基于 provider 实际返回的累积 token 使用量判断是否应触发压缩。
|
|
391
|
-
*
|
|
392
|
-
* provider 每次请求都会返回实际 token 计数(input + output),
|
|
393
|
-
* 这个计数比基于文本的估算(estimateConversationTokens)要准确得多。
|
|
394
|
-
*
|
|
395
|
-
* 触发条件:累积 tokens >= contextLimit * getCompactionTriggerRatio(contextLimit)
|
|
396
|
-
* 使用显式传入的 contextLimit,不依赖模型名查找表。
|
|
397
|
-
*
|
|
398
|
-
* @param accumulatedInput provider 实际累积的 input tokens
|
|
399
|
-
* @param accumulatedOutput provider 实际累积的 output tokens
|
|
400
|
-
* @param contextLimit 上下文窗口上限(来自模板配置,未配置时使用默认值)
|
|
401
|
-
*/
|
|
402
|
-
export function isOverflowByActualUsage(accumulatedInput, accumulatedOutput, contextLimit) {
|
|
403
|
-
if (contextLimit <= 0)
|
|
404
|
-
return false;
|
|
405
|
-
const totalUsed = accumulatedInput + accumulatedOutput;
|
|
406
|
-
const ratioThreshold = Math.floor(contextLimit * getCompactionTriggerRatio(contextLimit));
|
|
407
|
-
return totalUsed >= ratioThreshold;
|
|
408
|
-
}
|
|
409
|
-
// ============ Prune 策略 ============
|
|
410
|
-
/**
|
|
411
|
-
* 判断消息是否为工具消息(可裁剪)。
|
|
412
|
-
*/
|
|
413
|
-
function isToolMessage(message) {
|
|
414
|
-
return message.role === "tool";
|
|
415
|
-
}
|
|
416
|
-
/**
|
|
417
|
-
* 从工具消息中提取工具名(用于白名单检查)。
|
|
418
|
-
* 通过 tool_call_id 在对话历史中查找对应的 assistant 消息的 tool_calls,
|
|
419
|
-
* 匹配后返回 function name。
|
|
420
|
-
*/
|
|
421
|
-
function getToolNameFromMessage(message, allMessages, messageIndex) {
|
|
422
|
-
if (message.role !== "tool" || !message.tool_call_id) {
|
|
423
|
-
return undefined;
|
|
424
|
-
}
|
|
425
|
-
for (let i = messageIndex - 1; i >= 0; i--) {
|
|
426
|
-
const m = allMessages[i];
|
|
427
|
-
if (!m)
|
|
428
|
-
continue;
|
|
429
|
-
if (m.role === "assistant" && Array.isArray(m.tool_calls)) {
|
|
430
|
-
for (const tc of m.tool_calls) {
|
|
431
|
-
if (typeof tc === "object" &&
|
|
432
|
-
tc !== null &&
|
|
433
|
-
"id" in tc &&
|
|
434
|
-
tc.id === message.tool_call_id) {
|
|
435
|
-
const fn = tc.function;
|
|
436
|
-
return fn ? String(fn.name ?? "") : undefined;
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
return undefined;
|
|
442
|
-
}
|
|
443
|
-
/**
|
|
444
|
-
* Prune:从消息列表中裁剪旧工具消息的输出内容。
|
|
445
|
-
*
|
|
446
|
-
* 算法(参考 OpenCode compaction.ts:58-99):
|
|
447
|
-
* 1. 从最新消息往旧遍历
|
|
448
|
-
* 2. 跳过前 2 轮对话(保护最近上下文)
|
|
449
|
-
* 3. 累计工具消息的 token
|
|
450
|
-
* 4. 超过保护线后,将工具输出替换为占位符
|
|
451
|
-
* 5. 只有收益超过最小阈值才真正执行
|
|
452
|
-
*
|
|
453
|
-
* 保护线和最小阈值会按 contextLimit 比例调整:
|
|
454
|
-
* - protectLine = min(PRUNE_PROTECT, contextLimit * PRUNE_PROTECT_RATIO)
|
|
455
|
-
* - minimumGain = min(PRUNE_MINIMUM, contextLimit * PRUNE_MINIMUM_RATIO)
|
|
456
|
-
* 这样在小上下文窗口(如 60k)下也能正常触发 prune,
|
|
457
|
-
* 而不是固定 40k/20k 导致 60k 上下文永远无法 prune。
|
|
458
|
-
*
|
|
459
|
-
* @param messages 对话消息数组(会被原地修改)
|
|
460
|
-
* @param contextLimit 上下文窗口大小,用于按比例调整阈值(默认使用 DEFAULT_CONTEXT_LIMIT)
|
|
461
|
-
* @returns 裁剪结果
|
|
462
|
-
*/
|
|
463
|
-
export function pruneToolOutputs(messages, contextLimit = DEFAULT_CONTEXT_LIMIT) {
|
|
464
|
-
if (messages.length === 0) {
|
|
465
|
-
return { prunedCount: 0, freedTokens: 0 };
|
|
466
|
-
}
|
|
467
|
-
// 按比例调整保护线和最小收益阈值
|
|
468
|
-
const protectLine = Math.min(PRUNE_PROTECT, Math.floor(contextLimit * PRUNE_PROTECT_RATIO));
|
|
469
|
-
const minimumGain = Math.min(PRUNE_MINIMUM, Math.floor(contextLimit * PRUNE_MINIMUM_RATIO));
|
|
470
|
-
// 阶段 1:收集所有候选(按重要性分组)
|
|
471
|
-
// 在保护线内的工具输出(最近 N 轮),无论重要性如何都保留。
|
|
472
|
-
// 超过保护线的输出,按重要性排序,优先裁剪低重要性的。
|
|
473
|
-
let accumulatedTokens = 0;
|
|
474
|
-
const lowImportanceCandidates = [];
|
|
475
|
-
const highImportanceCandidates = [];
|
|
476
|
-
let turns = 0;
|
|
477
|
-
// 从最新往旧遍历
|
|
478
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
479
|
-
const msg = messages[i];
|
|
480
|
-
if (msg.role === "user")
|
|
481
|
-
turns++;
|
|
482
|
-
if (turns < 2)
|
|
483
|
-
continue;
|
|
484
|
-
if (!isToolMessage(msg))
|
|
485
|
-
continue;
|
|
486
|
-
const toolName = getToolNameFromMessage(msg, messages, i);
|
|
487
|
-
if (toolName && PRUNE_PROTECTED_TOOLS.has(toolName))
|
|
488
|
-
continue;
|
|
489
|
-
const contentStr = typeof msg.content === "string" ? msg.content : "";
|
|
490
|
-
const estimate = estimateTokens(contentStr);
|
|
491
|
-
accumulatedTokens += estimate;
|
|
492
|
-
if (accumulatedTokens > protectLine) {
|
|
493
|
-
// 超过保护线,按重要性分组
|
|
494
|
-
const importance = toolName ? getToolImportance(toolName) : DEFAULT_TOOL_IMPORTANCE;
|
|
495
|
-
const candidate = { msg, tokens: estimate, name: toolName ?? "" };
|
|
496
|
-
if (importance <= 1) {
|
|
497
|
-
// 高重要性(Read/Grep/Edit 等):暂不优先裁剪
|
|
498
|
-
highImportanceCandidates.push(candidate);
|
|
499
|
-
}
|
|
500
|
-
else {
|
|
501
|
-
// 低重要性(Bash/WebSearch 等):优先裁剪
|
|
502
|
-
lowImportanceCandidates.push(candidate);
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
// 阶段 2:按重要性排序,低重要性优先裁剪
|
|
507
|
-
// 低重要性按 token 数降序(先裁大的),高重要性按 token 数升序(尽量保留)
|
|
508
|
-
lowImportanceCandidates.sort((a, b) => b.tokens - a.tokens);
|
|
509
|
-
highImportanceCandidates.sort((a, b) => a.tokens - b.tokens);
|
|
510
|
-
const toPrune = [];
|
|
511
|
-
let freedTokens = 0;
|
|
512
|
-
// 先裁低重要性
|
|
513
|
-
for (const c of lowImportanceCandidates) {
|
|
514
|
-
if (freedTokens >= minimumGain)
|
|
515
|
-
break;
|
|
516
|
-
freedTokens += c.tokens;
|
|
517
|
-
toPrune.push(c.msg);
|
|
518
|
-
}
|
|
519
|
-
// 如果低重要性不够,再裁高重要性(从最小的开始)
|
|
520
|
-
if (freedTokens < minimumGain) {
|
|
521
|
-
for (const c of highImportanceCandidates) {
|
|
522
|
-
freedTokens += c.tokens;
|
|
523
|
-
toPrune.push(c.msg);
|
|
524
|
-
if (freedTokens >= minimumGain)
|
|
525
|
-
break;
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
if (freedTokens < minimumGain) {
|
|
529
|
-
return { prunedCount: 0, freedTokens: 0 };
|
|
530
|
-
}
|
|
531
|
-
// 执行裁剪:将工具输出替换为占位符
|
|
532
|
-
for (const msg of toPrune) {
|
|
533
|
-
msg.content = "[Old tool result content cleared]";
|
|
534
|
-
}
|
|
535
|
-
return { prunedCount: toPrune.length, freedTokens };
|
|
536
|
-
}
|
|
537
|
-
// ============ Summarize 策略 ============
|
|
538
|
-
/**
|
|
539
|
-
* 判断消息是否为压缩摘要消息。
|
|
540
|
-
*/
|
|
541
|
-
function isCompactionSummaryMessage(message) {
|
|
542
|
-
return (message.role === "system" &&
|
|
543
|
-
typeof message.content === "string" &&
|
|
544
|
-
message.content.startsWith(COMPACTION_SUMMARY_PREFIX));
|
|
545
|
-
}
|
|
546
|
-
/**
|
|
547
|
-
* 生成单条消息的摘要预览。
|
|
548
|
-
*/
|
|
549
|
-
function summarizeMessage(message, index) {
|
|
550
|
-
const contentStr = typeof message.content === "string"
|
|
551
|
-
? message.content
|
|
552
|
-
: Array.isArray(message.content)
|
|
553
|
-
? message.content.map((p) => (typeof p === "object" && p !== null ? JSON.stringify(p) : String(p))).join(" ")
|
|
554
|
-
: "";
|
|
555
|
-
const preview = contentStr.length > COMPACTION_MAX_PREVIEW_CHARS
|
|
556
|
-
? `${contentStr.slice(0, COMPACTION_MAX_PREVIEW_CHARS)}…`
|
|
557
|
-
: contentStr;
|
|
558
|
-
const parts = [`${index + 1}. ${message.role}`];
|
|
559
|
-
if (message.tool_calls && Array.isArray(message.tool_calls) && message.tool_calls.length > 0) {
|
|
560
|
-
const toolCallSummary = message.tool_calls
|
|
561
|
-
.map((tc) => {
|
|
562
|
-
if (typeof tc === "object" && tc !== null) {
|
|
563
|
-
const fn = tc.function;
|
|
564
|
-
return fn ? String(fn.name ?? "") : "";
|
|
565
|
-
}
|
|
566
|
-
return "";
|
|
567
|
-
})
|
|
568
|
-
.filter(Boolean)
|
|
569
|
-
.join(", ");
|
|
570
|
-
if (toolCallSummary)
|
|
571
|
-
parts.push(`tool_calls=${toolCallSummary}`);
|
|
572
|
-
}
|
|
573
|
-
if (message.tool_call_id)
|
|
574
|
-
parts.push(`tool_call_id=${message.tool_call_id}`);
|
|
575
|
-
if (preview)
|
|
576
|
-
parts.push(`content=${preview}`);
|
|
577
|
-
return parts.join(" | ");
|
|
578
|
-
}
|
|
579
|
-
/**
|
|
580
|
-
* Summarize:将早期对话消息替换为结构化摘要。
|
|
581
|
-
*
|
|
582
|
-
* 算法(参考 OpenCode compaction.ts:101-229 的 process 函数):
|
|
583
|
-
* 1. 分离 base system 消息和可压缩消息
|
|
584
|
-
* 2. 保留最近 COMPACTION_RECENT_MESSAGE_COUNT 条消息
|
|
585
|
-
* 3. 将早期消息生成结构化摘要
|
|
586
|
-
* 4. 用摘要消息替换早期消息
|
|
587
|
-
*
|
|
588
|
-
* @param messages 对话消息数组(会被原地修改)
|
|
589
|
-
* @returns 摘要化的消息数
|
|
590
|
-
*/
|
|
591
|
-
export async function summarizeConversation(messages, options) {
|
|
592
|
-
const baseSystemMessages = messages.filter((m) => m.role === "system" && !isCompactionSummaryMessage(m));
|
|
593
|
-
const compactableMessages = messages.filter((m) => m.role !== "system" || isCompactionSummaryMessage(m));
|
|
594
|
-
const removableCount = Math.max(0, compactableMessages.length - COMPACTION_RECENT_MESSAGE_COUNT);
|
|
595
|
-
if (removableCount === 0)
|
|
596
|
-
return 0;
|
|
597
|
-
// ★ 切片 + 后清理(取代之前的边界推进):
|
|
598
|
-
// 边界推进在找不到"干净边界"时会一路推进到末尾,返回 0,导致 summarize 完全不生效。
|
|
599
|
-
// 新策略:先按 removableCount 切片,再清理 kept 部分中的 orphan tool 消息和
|
|
600
|
-
// orphan assistant(tool_calls),保证消息序列对 OpenAI 兼容 API 有效。
|
|
601
|
-
const removedMessages = compactableMessages.slice(0, removableCount);
|
|
602
|
-
let keptMessages = compactableMessages.slice(removableCount);
|
|
603
|
-
// 收集 kept 部分所有 assistant(tool_calls) 的 tool_call_id
|
|
604
|
-
const keptToolCallIds = new Set();
|
|
605
|
-
for (const m of keptMessages) {
|
|
606
|
-
if (m.role === "assistant" && m.tool_calls?.length) {
|
|
607
|
-
for (const tc of m.tool_calls) {
|
|
608
|
-
if (typeof tc === "object" &&
|
|
609
|
-
tc !== null &&
|
|
610
|
-
typeof tc.id === "string") {
|
|
611
|
-
keptToolCallIds.add(tc.id);
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
// 第一轮过滤:移除 orphan tool 消息(其父 assistant 已被摘要化)
|
|
617
|
-
keptMessages = keptMessages.filter((m) => {
|
|
618
|
-
if (m.role === "tool" && m.tool_call_id) {
|
|
619
|
-
return keptToolCallIds.has(m.tool_call_id);
|
|
620
|
-
}
|
|
621
|
-
return true;
|
|
622
|
-
});
|
|
623
|
-
// 第二轮过滤:移除 orphan assistant(tool_calls)(其部分 tool 结果已在第一轮被移除)
|
|
624
|
-
// 反复迭代直到稳定(一次过滤可能产生新的 orphan)
|
|
625
|
-
let changed = true;
|
|
626
|
-
while (changed) {
|
|
627
|
-
changed = false;
|
|
628
|
-
// 重新收集 kept 中的 tool_call_id
|
|
629
|
-
const currentToolCallIds = new Set();
|
|
630
|
-
for (const m of keptMessages) {
|
|
631
|
-
if (m.role === "assistant" && m.tool_calls?.length) {
|
|
632
|
-
for (const tc of m.tool_calls) {
|
|
633
|
-
if (typeof tc === "object" &&
|
|
634
|
-
tc !== null &&
|
|
635
|
-
typeof tc.id === "string") {
|
|
636
|
-
currentToolCallIds.add(tc.id);
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
// 重新收集 kept 中的 tool_result id
|
|
642
|
-
const currentToolResultIds = new Set();
|
|
643
|
-
for (const m of keptMessages) {
|
|
644
|
-
if (m.role === "tool" && m.tool_call_id) {
|
|
645
|
-
currentToolResultIds.add(m.tool_call_id);
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
const nextKept = keptMessages.filter((m) => {
|
|
649
|
-
if (m.role === "tool" && m.tool_call_id) {
|
|
650
|
-
return currentToolCallIds.has(m.tool_call_id);
|
|
651
|
-
}
|
|
652
|
-
if (m.role === "assistant" && m.tool_calls?.length) {
|
|
653
|
-
const expectedIds = new Set();
|
|
654
|
-
for (const tc of m.tool_calls) {
|
|
655
|
-
if (typeof tc === "object" &&
|
|
656
|
-
tc !== null &&
|
|
657
|
-
typeof tc.id === "string") {
|
|
658
|
-
expectedIds.add(tc.id);
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
if (expectedIds.size === 0)
|
|
662
|
-
return true;
|
|
663
|
-
let allFound = true;
|
|
664
|
-
for (const id of expectedIds) {
|
|
665
|
-
if (!currentToolResultIds.has(id)) {
|
|
666
|
-
allFound = false;
|
|
667
|
-
break;
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
return allFound;
|
|
671
|
-
}
|
|
672
|
-
return true;
|
|
673
|
-
});
|
|
674
|
-
if (nextKept.length !== keptMessages.length) {
|
|
675
|
-
changed = true;
|
|
676
|
-
keptMessages = nextKept;
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
// 如果清理后 kept 为空,放弃本次摘要(避免清空整个对话)
|
|
680
|
-
if (keptMessages.length === 0) {
|
|
681
|
-
return 0;
|
|
682
|
-
}
|
|
683
|
-
// ★ 尝试 LLM 摘要(若注入了 llmSummarizer),失败则降级到规则摘要。
|
|
684
|
-
// LLM 摘要失败时静默降级,不抛异常,保证压缩流程继续。
|
|
685
|
-
let llmSummary = null;
|
|
686
|
-
if (options?.llmSummarizer) {
|
|
687
|
-
try {
|
|
688
|
-
const conversationText = removedMessages
|
|
689
|
-
.map((message, index) => summarizeMessage(message, index))
|
|
690
|
-
.join("\n");
|
|
691
|
-
llmSummary = await options.llmSummarizer({
|
|
692
|
-
conversationText,
|
|
693
|
-
messageCount: removableCount,
|
|
694
|
-
contextLimit: options.contextLimit ?? DEFAULT_CONTEXT_LIMIT,
|
|
695
|
-
});
|
|
696
|
-
}
|
|
697
|
-
catch {
|
|
698
|
-
// 降级到规则摘要
|
|
699
|
-
llmSummary = null;
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
// 原地修改 messages 数组
|
|
703
|
-
messages.length = 0;
|
|
704
|
-
messages.push(...baseSystemMessages);
|
|
705
|
-
if (llmSummary !== null) {
|
|
706
|
-
// LLM 摘要路径:标记 "summarized by LLM" 以便 performCompaction 识别
|
|
707
|
-
messages.push({
|
|
708
|
-
role: "system",
|
|
709
|
-
content: [
|
|
710
|
-
COMPACTION_SUMMARY_PREFIX,
|
|
711
|
-
`${removableCount} earlier conversation messages were summarized by LLM to free context space.`,
|
|
712
|
-
"Preserve the user's goal, decisions, tool results, file paths, errors, and unresolved tasks from this summary.",
|
|
713
|
-
"Recent messages below remain authoritative.",
|
|
714
|
-
"",
|
|
715
|
-
llmSummary,
|
|
716
|
-
].join("\n"),
|
|
717
|
-
});
|
|
718
|
-
}
|
|
719
|
-
else {
|
|
720
|
-
// 规则摘要路径(降级或未注入 llmSummarizer)
|
|
721
|
-
const summaryLines = removedMessages.map((message, index) => summarizeMessage(message, index));
|
|
722
|
-
const summary = summaryLines.join("\n").slice(0, COMPACTION_MAX_SUMMARY_CHARS);
|
|
723
|
-
messages.push({
|
|
724
|
-
role: "system",
|
|
725
|
-
content: [
|
|
726
|
-
COMPACTION_SUMMARY_PREFIX,
|
|
727
|
-
`${removableCount} earlier conversation messages were summarized to free context space.`,
|
|
728
|
-
"Preserve the user's goal, decisions, tool results, file paths, errors, and unresolved tasks from this summary.",
|
|
729
|
-
"Recent messages below remain authoritative.",
|
|
730
|
-
"",
|
|
731
|
-
summary,
|
|
732
|
-
].join("\n"),
|
|
733
|
-
});
|
|
734
|
-
}
|
|
735
|
-
messages.push(...keptMessages);
|
|
736
|
-
return removableCount;
|
|
737
|
-
}
|
|
738
|
-
// ============ 配对不变量保护 ============
|
|
739
|
-
/**
|
|
740
|
-
* Snip:删除最旧的一组消息(从第一个非 system 消息到下一个 user 消息之前)。
|
|
741
|
-
*
|
|
742
|
-
* 作为压缩的最终手段——当 prune 和 summarize 都无法释放足够空间时使用。
|
|
743
|
-
* 能确保:
|
|
744
|
-
* 1. 不删除 system 消息
|
|
745
|
-
* 2. 删除的组不跨 user 边界(保证一个完整轮次)
|
|
746
|
-
* 3. 删除后至少保留 1 组非 system 消息
|
|
747
|
-
*
|
|
748
|
-
* @param messages 对话消息数组(会被原地修改,通过 splice 删除)
|
|
749
|
-
* @returns 删除的消息数
|
|
750
|
-
*/
|
|
751
|
-
export function snipOldestMessageGroup(messages) {
|
|
752
|
-
if (messages.length <= 1)
|
|
753
|
-
return 0;
|
|
754
|
-
// 找到第一个非 system 消息的索引
|
|
755
|
-
let startIdx = 0;
|
|
756
|
-
while (startIdx < messages.length && messages[startIdx].role === "system") {
|
|
757
|
-
startIdx++;
|
|
758
|
-
}
|
|
759
|
-
if (startIdx >= messages.length)
|
|
760
|
-
return 0;
|
|
761
|
-
// 找到下一个 user 消息的索引(作为删除组的结束边界)
|
|
762
|
-
let groupEnd = messages.length;
|
|
763
|
-
for (let i = startIdx + 1; i < messages.length; i++) {
|
|
764
|
-
if (messages[i].role === "user") {
|
|
765
|
-
groupEnd = i;
|
|
766
|
-
break;
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
// 不能删除全部非 system 消息(至少保留一组)
|
|
770
|
-
if (groupEnd >= messages.length)
|
|
771
|
-
return 0;
|
|
772
|
-
// 收集删除范围内 assistant 发起的 tool_call_id
|
|
773
|
-
const removedToolCallIds = new Set();
|
|
774
|
-
for (let i = startIdx; i < groupEnd; i++) {
|
|
775
|
-
const msg = messages[i];
|
|
776
|
-
if (msg.role === "assistant" && Array.isArray(msg.tool_calls)) {
|
|
777
|
-
for (const tc of msg.tool_calls) {
|
|
778
|
-
if (typeof tc === "object" && tc !== null && typeof tc.id === "string") {
|
|
779
|
-
removedToolCallIds.add(tc.id);
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
// 删除主组 [startIdx, groupEnd)
|
|
785
|
-
const removedCount = groupEnd - startIdx;
|
|
786
|
-
messages.splice(startIdx, removedCount);
|
|
787
|
-
// 清理孤儿 tool_result:其对应的 tool_call 已在上一步删除,但 tool_result 可能落在下一轮(groupEnd 之后)。
|
|
788
|
-
// 不能用连续 splice 扩展范围(会误删中间的 user 消息),故采用逆向遍历逐个删除孤儿 tool_result。
|
|
789
|
-
let orphanRemoved = 0;
|
|
790
|
-
if (removedToolCallIds.size > 0) {
|
|
791
|
-
for (let i = messages.length - 1; i >= startIdx; i--) {
|
|
792
|
-
const msg = messages[i];
|
|
793
|
-
if (msg.role === "tool" && msg.tool_call_id && removedToolCallIds.has(msg.tool_call_id)) {
|
|
794
|
-
messages.splice(i, 1);
|
|
795
|
-
orphanRemoved++;
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
return removedCount + orphanRemoved;
|
|
800
|
-
}
|
|
801
|
-
// ============ 完整压缩流程 ============
|
|
802
|
-
/**
|
|
803
|
-
* 执行完整压缩流程:Prune → 若仍溢出则 Summarize。
|
|
804
|
-
*
|
|
805
|
-
* 参考 OpenCode 的两阶段策略:
|
|
806
|
-
* 1. 先尝试 prune(低成本,只清除旧工具输出)
|
|
807
|
-
* 2. 若 prune 后仍溢出,执行 summarize(高成本,摘要化早期对话)
|
|
808
|
-
*
|
|
809
|
-
* @param messages 对话消息数组(会被原地修改)
|
|
810
|
-
* @param contextLimit 上下文窗口上限(来自模板配置,未配置时使用默认值)
|
|
811
|
-
* @param maxOutput 模型最大输出 token
|
|
812
|
-
* @param options 可选:llmSummarizer(LLM 摘要器,失败降级到规则摘要)、onPhase(阶段事件回调)
|
|
813
|
-
* @returns 压缩结果
|
|
814
|
-
*/
|
|
815
|
-
export async function performCompaction(messages, contextLimit, maxOutput = DEFAULT_MAX_OUTPUT, options) {
|
|
816
|
-
const sizeBeforeKB = conversationSizeKB(messages);
|
|
817
|
-
const messageCountBefore = messages.length;
|
|
818
|
-
const tokensBefore = estimateConversationTokens(messages);
|
|
819
|
-
let strategy = "none";
|
|
820
|
-
let prunedToolMessages = 0;
|
|
821
|
-
let summarizedMessages = 0;
|
|
822
|
-
let freedTokens = 0;
|
|
823
|
-
let usedLLM = false;
|
|
824
|
-
// 阶段 1: Prune(传入 contextLimit 以按比例调整保护线和最小收益阈值)
|
|
825
|
-
if (options?.onPhase) {
|
|
826
|
-
options.onPhase({ phase: "prune_start", messageCount: messages.length });
|
|
827
|
-
}
|
|
828
|
-
const pruneResult = pruneToolOutputs(messages, contextLimit);
|
|
829
|
-
if (pruneResult.prunedCount > 0) {
|
|
830
|
-
strategy = "prune";
|
|
831
|
-
prunedToolMessages = pruneResult.prunedCount;
|
|
832
|
-
freedTokens += pruneResult.freedTokens;
|
|
833
|
-
}
|
|
834
|
-
if (options?.onPhase) {
|
|
835
|
-
options.onPhase({
|
|
836
|
-
phase: "prune_end",
|
|
837
|
-
prunedCount: pruneResult.prunedCount,
|
|
838
|
-
freedTokens: pruneResult.freedTokens,
|
|
839
|
-
});
|
|
840
|
-
}
|
|
841
|
-
// 阶段 2: 若仍溢出,执行 Summarize
|
|
842
|
-
//
|
|
843
|
-
// ★ 使用 effectiveUsed(文本估算与 actual 的较大值)而非仅文本估算:
|
|
844
|
-
// provider 实际 token 计数往往高于基于字符的估算,若仅依赖文本估算,
|
|
845
|
-
// 可能因估算值低于阈值而导致"假阴性"——实际已溢出但 isOverflow 返回 false,
|
|
846
|
-
// summarize 被直接跳过,最终策略为 "none"。
|
|
847
|
-
const tokensAfterPrune = estimateConversationTokens(messages);
|
|
848
|
-
const postPruneEffective = options?.actualUsedTokens
|
|
849
|
-
? Math.max(tokensAfterPrune, Math.max(options.actualUsedTokens, tokensBefore) - freedTokens)
|
|
850
|
-
: tokensAfterPrune;
|
|
851
|
-
if (postPruneEffective >= Math.floor(contextLimit * getCompactionTriggerRatio(contextLimit))) {
|
|
852
|
-
if (options?.onPhase) {
|
|
853
|
-
options.onPhase({ phase: "summarize_start", messageCount: messages.length });
|
|
854
|
-
}
|
|
855
|
-
const summarized = await summarizeConversation(messages, {
|
|
856
|
-
llmSummarizer: options?.llmSummarizer,
|
|
857
|
-
contextLimit,
|
|
858
|
-
});
|
|
859
|
-
if (summarized > 0) {
|
|
860
|
-
strategy = strategy === "prune" ? "prune+summarize" : "summarize";
|
|
861
|
-
summarizedMessages = summarized;
|
|
862
|
-
const tokensAfter = estimateConversationTokens(messages);
|
|
863
|
-
freedTokens = Math.max(freedTokens, tokensBefore - tokensAfter);
|
|
864
|
-
// 检测是否使用了 LLM 摘要(通过摘要消息内容识别)
|
|
865
|
-
const summaryMsg = messages.find((m) => m.role === "system" &&
|
|
866
|
-
typeof m.content === "string" &&
|
|
867
|
-
m.content.includes("summarized by LLM"));
|
|
868
|
-
usedLLM = Boolean(summaryMsg);
|
|
869
|
-
}
|
|
870
|
-
else {
|
|
871
|
-
// ★ 阶段 2b: Summarize 失败降级 → Snip 最旧消息组(最终手段)
|
|
872
|
-
// 当 summarize 返回 0(无法找到干净边界或清理后 kept 为空),
|
|
873
|
-
// 尝试直接删除最旧的一组非 system 消息。
|
|
874
|
-
const sniped = snipOldestMessageGroup(messages);
|
|
875
|
-
if (sniped > 0) {
|
|
876
|
-
strategy = strategy === "prune" ? "prune+summarize" : "summarize";
|
|
877
|
-
summarizedMessages = sniped;
|
|
878
|
-
const tokensAfter = estimateConversationTokens(messages);
|
|
879
|
-
freedTokens = Math.max(freedTokens, tokensBefore - tokensAfter);
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
|
-
if (options?.onPhase) {
|
|
883
|
-
options.onPhase({
|
|
884
|
-
phase: "summarize_end",
|
|
885
|
-
summarizedCount: summarizedMessages,
|
|
886
|
-
usedLLM,
|
|
887
|
-
});
|
|
888
|
-
}
|
|
889
|
-
}
|
|
890
|
-
const sizeAfterKB = conversationSizeKB(messages);
|
|
891
|
-
const messageCountAfter = messages.length;
|
|
892
|
-
const tokensAfter = estimateConversationTokens(messages);
|
|
893
|
-
if (strategy === "none") {
|
|
894
|
-
return {
|
|
895
|
-
strategy: "none",
|
|
896
|
-
freedTokens: 0,
|
|
897
|
-
sizeBeforeKB,
|
|
898
|
-
sizeAfterKB: sizeBeforeKB,
|
|
899
|
-
tokensBefore,
|
|
900
|
-
tokensAfter,
|
|
901
|
-
messageCountBefore,
|
|
902
|
-
messageCountAfter,
|
|
903
|
-
prunedToolMessages: 0,
|
|
904
|
-
summarizedMessages: 0,
|
|
905
|
-
};
|
|
906
|
-
}
|
|
907
|
-
return {
|
|
908
|
-
strategy,
|
|
909
|
-
freedTokens,
|
|
910
|
-
sizeBeforeKB,
|
|
911
|
-
sizeAfterKB,
|
|
912
|
-
tokensBefore,
|
|
913
|
-
tokensAfter,
|
|
914
|
-
messageCountBefore,
|
|
915
|
-
messageCountAfter,
|
|
916
|
-
prunedToolMessages,
|
|
917
|
-
summarizedMessages,
|
|
918
|
-
};
|
|
919
|
-
}
|
|
1
|
+
const nt=2e4,rt=.55,z=[[32e3,.7],[128e3,.75],[512e3,.8],[Number.POSITIVE_INFINITY,.85]];function T(t){if(t<=0)return .55;for(const[e,o]of z)if(t<e)return o;return .85}const U=4e4,j=2e4,B=.5,F=.1,G=new Set(["skill","todo_write","todo_read"]),y={read_file:0,Read:0,grep:0,Grep:0,glob:0,Glob:0,"contextweaver_codebase-retrieval":0,Edit:1,edit:1,Write:1,write:1,write_file:1,webfetch:2,WebFetch:2,WebSearch:2,websearch_web_search_exa:2,bash:3,Bash:3,run_terminal_command:3,playwright_browser_:4},L=2;function K(t){if(!t)return L;if(y[t]!==void 0)return y[t];const e=Object.keys(y).filter(o=>t.startsWith(o)).sort((o,n)=>n.length-o.length);return e.length>0?y[e[0]]:L}const M=128e3,C=8192,D=8,$=6e3,b=500,E="ACode context compaction summary:",it=["Please summarize the conversation above using the following structured format.","Keep each section concise but preserve all actionable details.","","## Goal","The user's primary objective in this conversation.","","## Instructions","Standing instructions, constraints, or preferences the user has stated.","","## Discoveries","Key findings, decisions, tool results, file paths, and errors encountered.","","## Accomplished","Tasks that have been completed (do not redo these).","","## Files","Files read, modified, or created with brief context.","","Output only the summary, no preamble."].join(`
|
|
2
|
+
`),W=1.5,S=4,J=1.15,X=2e3,H=8;function lt(t,e,o){const n=Math.floor(t*T(t)),l=o??t,s=Math.min(2e4,e),i=l-s;return Math.min(n,i)}const A={"claude-4":{contextLimit:2e5,maxOutput:8192},"claude-sonnet-4":{contextLimit:2e5,maxOutput:8192},"claude-3-5-sonnet":{contextLimit:2e5,maxOutput:8192},"claude-3-opus":{contextLimit:2e5,maxOutput:8192},"claude-3-haiku":{contextLimit:2e5,maxOutput:8192},"claude-2":{contextLimit:1e5,maxOutput:4096},"gpt-4o":{contextLimit:128e3,maxOutput:16384},"gpt-4-turbo":{contextLimit:128e3,maxOutput:4096},"gpt-4":{contextLimit:8192,maxOutput:4096},"gpt-3.5-turbo":{contextLimit:16384,maxOutput:4096},o1:{contextLimit:2e5,maxOutput:1e5},"o3-mini":{contextLimit:2e5,maxOutput:1e5},"gemini-2.0-flash":{contextLimit:1048576,maxOutput:8192},"gemini-2.5-pro":{contextLimit:1048576,maxOutput:8192},"gemini-1.5-pro":{contextLimit:2097152,maxOutput:8192},"gemini-1.5-flash":{contextLimit:1048576,maxOutput:8192},deepseek:{contextLimit:64e3,maxOutput:8192},"deepseek-chat":{contextLimit:64e3,maxOutput:8192},"deepseek-reasoner":{contextLimit:64e3,maxOutput:8192},"qwen-max":{contextLimit:32e3,maxOutput:8192},"qwen-plus":{contextLimit:128e3,maxOutput:8192},"qwen-turbo":{contextLimit:1e6,maxOutput:8192},"glm-4":{contextLimit:128e3,maxOutput:4096},"yi-":{contextLimit:2e5,maxOutput:4096},"llama-3":{contextLimit:8192,maxOutput:4096},"llama-2":{contextLimit:4096,maxOutput:4096},mistral:{contextLimit:32e3,maxOutput:4096},mixtral:{contextLimit:32e3,maxOutput:4096},codestral:{contextLimit:256e3,maxOutput:8192},grok:{contextLimit:131072,maxOutput:4096},"nova-":{contextLimit:2e5,maxOutput:8192}};function st(t,e){if(e?.contextLimit&&e.contextLimit>0)return{contextLimit:e.contextLimit,maxOutput:e.maxOutput??C};if(!t)return{contextLimit:M,maxOutput:C};const o=t.toLowerCase().trim();if(A[o])return A[o];const n=Object.keys(A).filter(l=>o.startsWith(l)).sort((l,s)=>s.length-l.length);return n.length>0?A[n[0]]:{contextLimit:M,maxOutput:C}}function q(t){if(!t)return 0;let e=0,o=0;for(const n of t)n>"\xFF"?e++:o++;return Math.ceil(e/W+o/S)}function g(t){return t?Math.ceil(q(t)*J):0}function V(t){if(typeof t=="object"&&t!==null){const e=t;return e.type==="text"&&typeof e.text=="string"?g(e.text):e.type==="image_url"||e.type==="document"?X:Math.ceil(JSON.stringify(t).length/S)}return typeof t=="string"?g(t):0}function Y(t){let e=16;if(typeof t.content=="string")e+=t.content.length*2;else if(Array.isArray(t.content))for(const o of t.content)typeof o=="object"&&o!==null&&(e+=JSON.stringify(o).length);return t.tool_calls&&(e+=JSON.stringify(t.tool_calls).length),t.tool_call_id&&(e+=t.tool_call_id.length),e}function x(t){let e=0;for(const o of t){if(typeof o.content=="string")e+=g(o.content);else if(Array.isArray(o.content))for(const n of o.content)e+=V(n);o.tool_calls&&(e+=H+Math.ceil(JSON.stringify(o.tool_calls).length/S))}return e}function N(t){let e=0;for(const o of t)e+=Y(o);return Math.round(e/1024*10)/10}function ct(t,e,o){if(e<=0)return!1;const n=x(t),l=Math.floor(e*T(e));return n>=l}function ut(t,e,o){if(o<=0)return!1;const n=t+e,l=Math.floor(o*T(o));return n>=l}function Q(t){return t.role==="tool"}function Z(t,e,o){if(!(t.role!=="tool"||!t.tool_call_id))for(let n=o-1;n>=0;n--){const l=e[n];if(l&&l.role==="assistant"&&Array.isArray(l.tool_calls)){for(const s of l.tool_calls)if(typeof s=="object"&&s!==null&&"id"in s&&s.id===t.tool_call_id){const i=s.function;return i?String(i.name??""):void 0}}}}function tt(t,e=M){if(t.length===0)return{prunedCount:0,freedTokens:0};const o=Math.min(U,Math.floor(e*B)),n=Math.min(j,Math.floor(e*F));let l=0;const s=[],i=[];let u=0;for(let r=t.length-1;r>=0;r--){const c=t[r];if(c.role==="user"&&u++,u<2||!Q(c))continue;const f=Z(c,t,r);if(f&&G.has(f))continue;const a=typeof c.content=="string"?c.content:"",p=g(a);if(l+=p,l>o){const h=f?K(f):L,d={msg:c,tokens:p,name:f??""};h<=1?i.push(d):s.push(d)}}s.sort((r,c)=>c.tokens-r.tokens),i.sort((r,c)=>r.tokens-c.tokens);const m=[];let _=0;for(const r of s){if(_>=n)break;_+=r.tokens,m.push(r.msg)}if(_<n){for(const r of i)if(_+=r.tokens,m.push(r.msg),_>=n)break}if(_<n)return{prunedCount:0,freedTokens:0};for(const r of m)r.content="[Old tool result content cleared]";return{prunedCount:m.length,freedTokens:_}}function w(t){return t.role==="system"&&typeof t.content=="string"&&t.content.startsWith(E)}function v(t,e){const o=typeof t.content=="string"?t.content:Array.isArray(t.content)?t.content.map(s=>typeof s=="object"&&s!==null?JSON.stringify(s):String(s)).join(" "):"",n=o.length>b?`${o.slice(0,b)}\u2026`:o,l=[`${e+1}. ${t.role}`];if(t.tool_calls&&Array.isArray(t.tool_calls)&&t.tool_calls.length>0){const s=t.tool_calls.map(i=>{if(typeof i=="object"&&i!==null){const u=i.function;return u?String(u.name??""):""}return""}).filter(Boolean).join(", ");s&&l.push(`tool_calls=${s}`)}return t.tool_call_id&&l.push(`tool_call_id=${t.tool_call_id}`),n&&l.push(`content=${n}`),l.join(" | ")}async function et(t,e){const o=t.filter(r=>r.role==="system"&&!w(r)),n=t.filter(r=>r.role!=="system"||w(r)),l=Math.max(0,n.length-D);if(l===0)return 0;const s=n.slice(0,l);let i=n.slice(l);const u=new Set;for(const r of i)if(r.role==="assistant"&&r.tool_calls?.length)for(const c of r.tool_calls)typeof c=="object"&&c!==null&&typeof c.id=="string"&&u.add(c.id);i=i.filter(r=>r.role==="tool"&&r.tool_call_id?u.has(r.tool_call_id):!0);let m=!0;for(;m;){m=!1;const r=new Set;for(const a of i)if(a.role==="assistant"&&a.tool_calls?.length)for(const p of a.tool_calls)typeof p=="object"&&p!==null&&typeof p.id=="string"&&r.add(p.id);const c=new Set;for(const a of i)a.role==="tool"&&a.tool_call_id&&c.add(a.tool_call_id);const f=i.filter(a=>{if(a.role==="tool"&&a.tool_call_id)return r.has(a.tool_call_id);if(a.role==="assistant"&&a.tool_calls?.length){const p=new Set;for(const d of a.tool_calls)typeof d=="object"&&d!==null&&typeof d.id=="string"&&p.add(d.id);if(p.size===0)return!0;let h=!0;for(const d of p)if(!c.has(d)){h=!1;break}return h}return!0});f.length!==i.length&&(m=!0,i=f)}if(i.length===0)return 0;let _=null;if(e?.llmSummarizer)try{const r=s.map((c,f)=>v(c,f)).join(`
|
|
3
|
+
`);_=await e.llmSummarizer({conversationText:r,messageCount:l,contextLimit:e.contextLimit??M})}catch{_=null}if(t.length=0,t.push(...o),_!==null)t.push({role:"system",content:[E,`${l} earlier conversation messages were summarized by LLM to free context space.`,"Preserve the user's goal, decisions, tool results, file paths, errors, and unresolved tasks from this summary.","Recent messages below remain authoritative.","",_].join(`
|
|
4
|
+
`)});else{const c=s.map((f,a)=>v(f,a)).join(`
|
|
5
|
+
`).slice(0,$);t.push({role:"system",content:[E,`${l} earlier conversation messages were summarized to free context space.`,"Preserve the user's goal, decisions, tool results, file paths, errors, and unresolved tasks from this summary.","Recent messages below remain authoritative.","",c].join(`
|
|
6
|
+
`)})}return t.push(...i),l}function ot(t){if(t.length<=1)return 0;let e=0;for(;e<t.length&&t[e].role==="system";)e++;if(e>=t.length)return 0;let o=t.length;for(let i=e+1;i<t.length;i++)if(t[i].role==="user"){o=i;break}if(o>=t.length)return 0;const n=new Set;for(let i=e;i<o;i++){const u=t[i];if(u.role==="assistant"&&Array.isArray(u.tool_calls))for(const m of u.tool_calls)typeof m=="object"&&m!==null&&typeof m.id=="string"&&n.add(m.id)}const l=o-e;t.splice(e,l);let s=0;if(n.size>0)for(let i=t.length-1;i>=e;i--){const u=t[i];u.role==="tool"&&u.tool_call_id&&n.has(u.tool_call_id)&&(t.splice(i,1),s++)}return l+s}async function at(t,e,o=C,n){const l=N(t),s=t.length,i=x(t);let u="none",m=0,_=0,r=0,c=!1;n?.onPhase&&n.onPhase({phase:"prune_start",messageCount:t.length});const f=tt(t,e);f.prunedCount>0&&(u="prune",m=f.prunedCount,r+=f.freedTokens),n?.onPhase&&n.onPhase({phase:"prune_end",prunedCount:f.prunedCount,freedTokens:f.freedTokens});const a=x(t);if((n?.actualUsedTokens?Math.max(a,Math.max(n.actualUsedTokens,i)-r):a)>=Math.floor(e*T(e))){n?.onPhase&&n.onPhase({phase:"summarize_start",messageCount:t.length});const R=await et(t,{llmSummarizer:n?.llmSummarizer,contextLimit:e});if(R>0){u=u==="prune"?"prune+summarize":"summarize",_=R;const O=x(t);r=Math.max(r,i-O),c=!!t.find(I=>I.role==="system"&&typeof I.content=="string"&&I.content.includes("summarized by LLM"))}else{const O=ot(t);if(O>0){u=u==="prune"?"prune+summarize":"summarize",_=O;const k=x(t);r=Math.max(r,i-k)}}n?.onPhase&&n.onPhase({phase:"summarize_end",summarizedCount:_,usedLLM:c})}const h=N(t),d=t.length,P=x(t);return u==="none"?{strategy:"none",freedTokens:0,sizeBeforeKB:l,sizeAfterKB:l,tokensBefore:i,tokensAfter:P,messageCountBefore:s,messageCountAfter:d,prunedToolMessages:0,summarizedMessages:0}:{strategy:u,freedTokens:r,sizeBeforeKB:l,sizeAfterKB:h,tokensBefore:i,tokensAfter:P,messageCountBefore:s,messageCountAfter:d,prunedToolMessages:m,summarizedMessages:_}}export{nt as COMPACTION_BUFFER,it as COMPACTION_LLM_PROMPT_TEMPLATE,rt as COMPACTION_TRIGGER_RATIO,j as PRUNE_MINIMUM,U as PRUNE_PROTECT,lt as calculateCompactionThreshold,N as conversationSizeKB,x as estimateConversationTokens,q as estimateTextTokens,g as estimateTokens,T as getCompactionTriggerRatio,ct as isOverflow,ut as isOverflowByActualUsage,st as lookupModelLimits,at as performCompaction,tt as pruneToolOutputs,ot as snipOldestMessageGroup,et as summarizeConversation};
|
|
7
|
+
|