@ebowwa/coder 0.7.63 → 0.7.65
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/core/__tests__/permissions.test.d.ts +12 -0
- package/dist/core/__tests__/permissions.test.d.ts.map +1 -0
- package/dist/core/__tests__/permissions.test.js +851 -0
- package/dist/core/agent-loop/__tests__/compaction.test.d.ts +5 -0
- package/dist/core/agent-loop/__tests__/compaction.test.d.ts.map +1 -0
- package/dist/core/agent-loop/__tests__/compaction.test.js +209 -0
- package/dist/core/agent-loop/__tests__/formatters.test.d.ts +5 -0
- package/dist/core/agent-loop/__tests__/formatters.test.d.ts.map +1 -0
- package/dist/core/agent-loop/__tests__/formatters.test.js +195 -0
- package/dist/core/agent-loop/__tests__/index.test.d.ts +5 -0
- package/dist/core/agent-loop/__tests__/index.test.d.ts.map +1 -0
- package/dist/core/agent-loop/__tests__/index.test.js +121 -0
- package/dist/core/agent-loop/__tests__/loop-state.test.d.ts +5 -0
- package/dist/core/agent-loop/__tests__/loop-state.test.d.ts.map +1 -0
- package/dist/core/agent-loop/__tests__/loop-state.test.js +340 -0
- package/dist/core/agent-loop/__tests__/message-builder.test.d.ts +5 -0
- package/dist/core/agent-loop/__tests__/message-builder.test.d.ts.map +1 -0
- package/dist/core/agent-loop/__tests__/message-builder.test.js +178 -0
- package/dist/core/agent-loop/__tests__/tool-executor.test.d.ts +5 -0
- package/dist/core/agent-loop/__tests__/tool-executor.test.d.ts.map +1 -0
- package/dist/core/agent-loop/__tests__/tool-executor.test.js +331 -0
- package/dist/core/agent-loop/compaction.d.ts +39 -0
- package/dist/core/agent-loop/compaction.d.ts.map +1 -0
- package/dist/core/agent-loop/compaction.js +51 -0
- package/dist/core/agent-loop/formatters.d.ts +21 -0
- package/dist/core/agent-loop/formatters.d.ts.map +1 -0
- package/dist/core/agent-loop/formatters.js +42 -0
- package/dist/core/agent-loop/index.d.ts +25 -0
- package/dist/core/agent-loop/index.d.ts.map +1 -0
- package/dist/core/agent-loop/index.js +83 -0
- package/dist/core/agent-loop/loop-state.d.ts +74 -0
- package/dist/core/agent-loop/loop-state.d.ts.map +1 -0
- package/dist/core/agent-loop/loop-state.js +147 -0
- package/dist/core/agent-loop/message-builder.d.ts +13 -0
- package/dist/core/agent-loop/message-builder.d.ts.map +1 -0
- package/dist/core/agent-loop/message-builder.js +49 -0
- package/dist/core/agent-loop/tool-executor.d.ts +23 -0
- package/dist/core/agent-loop/tool-executor.d.ts.map +1 -0
- package/dist/core/agent-loop/tool-executor.js +152 -0
- package/dist/core/agent-loop/turn-executor.d.ts +57 -0
- package/dist/core/agent-loop/turn-executor.d.ts.map +1 -0
- package/dist/core/agent-loop/turn-executor.js +124 -0
- package/dist/core/agent-loop/types.d.ts +141 -0
- package/dist/core/agent-loop/types.d.ts.map +1 -0
- package/dist/core/agent-loop/types.js +4 -0
- package/dist/core/agent-loop.d.ts +17 -0
- package/dist/core/agent-loop.d.ts.map +1 -0
- package/dist/core/agent-loop.js +16 -0
- package/dist/core/api-client-impl.d.ts +62 -0
- package/dist/core/api-client-impl.d.ts.map +1 -0
- package/dist/core/api-client-impl.js +479 -0
- package/dist/core/api-client.d.ts +6 -0
- package/dist/core/api-client.d.ts.map +1 -0
- package/dist/core/api-client.js +5 -0
- package/dist/core/checkpoints.d.ts +128 -0
- package/dist/core/checkpoints.d.ts.map +1 -0
- package/dist/core/checkpoints.js +438 -0
- package/dist/core/claude-md.d.ts +71 -0
- package/dist/core/claude-md.d.ts.map +1 -0
- package/dist/core/claude-md.js +198 -0
- package/dist/core/cognitive-security/hooks.d.ts +138 -0
- package/dist/core/cognitive-security/hooks.d.ts.map +1 -0
- package/dist/core/cognitive-security/hooks.js +389 -0
- package/dist/core/cognitive-security/index.d.ts +751 -0
- package/dist/core/cognitive-security/index.d.ts.map +1 -0
- package/dist/core/cognitive-security/index.js +1123 -0
- package/dist/core/cognitive-security/middleware.d.ts +136 -0
- package/dist/core/cognitive-security/middleware.d.ts.map +1 -0
- package/dist/core/cognitive-security/middleware.js +376 -0
- package/dist/core/config-loader.d.ts +127 -0
- package/dist/core/config-loader.d.ts.map +1 -0
- package/dist/core/config-loader.js +219 -0
- package/dist/core/context-compaction.d.ts +87 -0
- package/dist/core/context-compaction.d.ts.map +1 -0
- package/dist/core/context-compaction.js +428 -0
- package/dist/core/git-status.d.ts +25 -0
- package/dist/core/git-status.d.ts.map +1 -0
- package/dist/core/git-status.js +204 -0
- package/dist/core/image.d.ts +69 -0
- package/dist/core/image.d.ts.map +1 -0
- package/dist/core/image.js +290 -0
- package/dist/core/image.test.d.ts +2 -0
- package/dist/core/image.test.d.ts.map +1 -0
- package/dist/core/image.test.js +149 -0
- package/dist/core/models.d.ts +123 -0
- package/dist/core/models.d.ts.map +1 -0
- package/dist/core/models.js +325 -0
- package/dist/core/permissions.d.ts +81 -0
- package/dist/core/permissions.d.ts.map +1 -0
- package/dist/core/permissions.js +327 -0
- package/dist/core/retry.d.ts +25 -0
- package/dist/core/retry.d.ts.map +1 -0
- package/dist/core/retry.js +121 -0
- package/dist/core/session-store.d.ts +9 -0
- package/dist/core/session-store.d.ts.map +1 -0
- package/dist/core/session-store.js +10 -0
- package/dist/core/sessions/export.d.ts +47 -0
- package/dist/core/sessions/export.d.ts.map +1 -0
- package/dist/core/sessions/export.js +256 -0
- package/dist/core/sessions/index.d.ts +132 -0
- package/dist/core/sessions/index.d.ts.map +1 -0
- package/dist/core/sessions/index.js +442 -0
- package/dist/core/sessions/metadata.d.ts +77 -0
- package/dist/core/sessions/metadata.d.ts.map +1 -0
- package/dist/core/sessions/metadata.js +233 -0
- package/dist/core/sessions/persistence.d.ts +72 -0
- package/dist/core/sessions/persistence.d.ts.map +1 -0
- package/dist/core/sessions/persistence.js +201 -0
- package/dist/core/sessions/types.d.ts +110 -0
- package/dist/core/sessions/types.d.ts.map +1 -0
- package/dist/core/sessions/types.js +4 -0
- package/dist/core/stream-highlighter.d.ts +18 -0
- package/dist/core/stream-highlighter.d.ts.map +1 -0
- package/dist/core/stream-highlighter.js +916 -0
- package/dist/core/system-reminders.d.ts +89 -0
- package/dist/core/system-reminders.d.ts.map +1 -0
- package/dist/core/system-reminders.js +285 -0
- package/dist/ecosystem/hooks/__tests__/index.test.d.ts +5 -0
- package/dist/ecosystem/hooks/__tests__/index.test.d.ts.map +1 -0
- package/dist/ecosystem/hooks/__tests__/index.test.js +458 -0
- package/dist/ecosystem/hooks/index.d.ts +59 -0
- package/dist/ecosystem/hooks/index.d.ts.map +1 -0
- package/dist/ecosystem/hooks/index.js +294 -0
- package/dist/ecosystem/hooks/prompt-evaluator.d.ts +32 -0
- package/dist/ecosystem/hooks/prompt-evaluator.d.ts.map +1 -0
- package/dist/ecosystem/hooks/prompt-evaluator.js +229 -0
- package/dist/ecosystem/skills/index.d.ts +55 -0
- package/dist/ecosystem/skills/index.d.ts.map +1 -0
- package/dist/ecosystem/skills/index.js +258 -0
- package/dist/ecosystem/tools/__tests__/index.test.d.ts +7 -0
- package/dist/ecosystem/tools/__tests__/index.test.d.ts.map +1 -0
- package/dist/ecosystem/tools/__tests__/index.test.js +856 -0
- package/dist/ecosystem/tools/index.d.ts +24 -0
- package/dist/ecosystem/tools/index.d.ts.map +1 -0
- package/dist/ecosystem/tools/index.js +1709 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33688 -49712
- package/dist/interfaces/mcp/client.d.ts +40 -0
- package/dist/interfaces/mcp/client.d.ts.map +1 -0
- package/dist/interfaces/mcp/client.js +309 -0
- package/dist/interfaces/ui/index.d.ts +36 -0
- package/dist/interfaces/ui/index.d.ts.map +1 -0
- package/dist/interfaces/ui/index.js +61 -0
- package/dist/interfaces/ui/spinner.d.ts +140 -0
- package/dist/interfaces/ui/spinner.d.ts.map +1 -0
- package/dist/interfaces/ui/spinner.js +342 -0
- package/dist/interfaces/ui/terminal/cli/index.d.ts +12 -0
- package/dist/interfaces/ui/terminal/cli/index.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/cli/index.js +32012 -50526
- package/dist/interfaces/ui/terminal/native/README.md +53 -0
- package/dist/interfaces/ui/terminal/native/claude_code_native.darwin-x64.node +0 -0
- package/dist/interfaces/ui/terminal/native/claude_code_native.dylib +0 -0
- package/dist/interfaces/ui/terminal/native/index.d.ts +0 -0
- package/dist/interfaces/ui/terminal/native/index.darwin-arm64.node +0 -0
- package/dist/interfaces/ui/terminal/native/index.js +43 -0
- package/dist/interfaces/ui/terminal/native/index.node +0 -0
- package/dist/interfaces/ui/terminal/native/package.json +34 -0
- package/dist/interfaces/ui/terminal/shared/args.d.ts +39 -0
- package/dist/interfaces/ui/terminal/shared/args.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/shared/args.js +176 -0
- package/dist/interfaces/ui/terminal/shared/index.d.ts +11 -0
- package/dist/interfaces/ui/terminal/shared/index.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/shared/index.js +16 -0
- package/dist/interfaces/ui/terminal/shared/loading-state.d.ts +124 -0
- package/dist/interfaces/ui/terminal/shared/loading-state.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/shared/loading-state.js +246 -0
- package/dist/interfaces/ui/terminal/shared/query.d.ts +22 -0
- package/dist/interfaces/ui/terminal/shared/query.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/shared/query.js +100 -0
- package/dist/interfaces/ui/terminal/shared/setup.d.ts +33 -0
- package/dist/interfaces/ui/terminal/shared/setup.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/shared/setup.js +226 -0
- package/dist/interfaces/ui/terminal/shared/status-line.d.ts +117 -0
- package/dist/interfaces/ui/terminal/shared/status-line.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/shared/status-line.js +267 -0
- package/dist/interfaces/ui/terminal/shared/system-prompt.d.ts +38 -0
- package/dist/interfaces/ui/terminal/shared/system-prompt.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/shared/system-prompt.js +102 -0
- package/dist/interfaces/ui/terminal/tui/HelpPanel.d.ts +39 -0
- package/dist/interfaces/ui/terminal/tui/HelpPanel.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/HelpPanel.js +215 -0
- package/dist/interfaces/ui/terminal/tui/InputContext.d.ts +91 -0
- package/dist/interfaces/ui/terminal/tui/InputContext.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/InputContext.js +154 -0
- package/dist/interfaces/ui/terminal/tui/InputField.d.ts +18 -0
- package/dist/interfaces/ui/terminal/tui/InputField.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/InputField.js +41 -0
- package/dist/interfaces/ui/terminal/tui/InteractiveTUI.d.ts +16 -0
- package/dist/interfaces/ui/terminal/tui/InteractiveTUI.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/InteractiveTUI.js +451 -0
- package/dist/interfaces/ui/terminal/tui/MessageArea.d.ts +10 -0
- package/dist/interfaces/ui/terminal/tui/MessageArea.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/MessageArea.js +91 -0
- package/dist/interfaces/ui/terminal/tui/MessageStore.d.ts +48 -0
- package/dist/interfaces/ui/terminal/tui/MessageStore.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/MessageStore.js +151 -0
- package/dist/interfaces/ui/terminal/tui/StatusBar.d.ts +9 -0
- package/dist/interfaces/ui/terminal/tui/StatusBar.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/StatusBar.js +36 -0
- package/dist/interfaces/ui/terminal/tui/commands.d.ts +21 -0
- package/dist/interfaces/ui/terminal/tui/commands.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/commands.js +359 -0
- package/dist/interfaces/ui/terminal/tui/components/InteractiveElements.d.ts +115 -0
- package/dist/interfaces/ui/terminal/tui/components/InteractiveElements.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/components/InteractiveElements.js +306 -0
- package/dist/interfaces/ui/terminal/tui/components/MultilineInput.d.ts +92 -0
- package/dist/interfaces/ui/terminal/tui/components/MultilineInput.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/components/MultilineInput.js +399 -0
- package/dist/interfaces/ui/terminal/tui/components/PaneManager.d.ts +59 -0
- package/dist/interfaces/ui/terminal/tui/components/PaneManager.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/components/PaneManager.js +139 -0
- package/dist/interfaces/ui/terminal/tui/components/Sidebar.d.ts +68 -0
- package/dist/interfaces/ui/terminal/tui/components/Sidebar.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/components/Sidebar.js +340 -0
- package/dist/interfaces/ui/terminal/tui/components/index.d.ts +23 -0
- package/dist/interfaces/ui/terminal/tui/components/index.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/components/index.js +51 -0
- package/dist/interfaces/ui/terminal/tui/console.d.ts +20 -0
- package/dist/interfaces/ui/terminal/tui/console.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/console.js +46 -0
- package/dist/interfaces/ui/terminal/tui/index.d.ts +20 -0
- package/dist/interfaces/ui/terminal/tui/index.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/index.js +28 -0
- package/dist/interfaces/ui/terminal/tui/run.d.ts +13 -0
- package/dist/interfaces/ui/terminal/tui/run.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/run.js +31 -0
- package/dist/interfaces/ui/terminal/tui/spinner.d.ts +44 -0
- package/dist/interfaces/ui/terminal/tui/spinner.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/spinner.js +59 -0
- package/dist/interfaces/ui/terminal/tui/tui-app.d.ts +39 -0
- package/dist/interfaces/ui/terminal/tui/tui-app.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/tui-app.js +198 -0
- package/dist/interfaces/ui/terminal/tui/tui-footer.d.ts +167 -0
- package/dist/interfaces/ui/terminal/tui/tui-footer.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/tui-footer.js +330 -0
- package/dist/interfaces/ui/terminal/tui/types.d.ts +165 -0
- package/dist/interfaces/ui/terminal/tui/types.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/types.js +5 -0
- package/dist/interfaces/ui/terminal/tui/useInputHandler.d.ts +23 -0
- package/dist/interfaces/ui/terminal/tui/useInputHandler.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/useInputHandler.js +72 -0
- package/dist/interfaces/ui/terminal/tui/useNativeInput.d.ts +90 -0
- package/dist/interfaces/ui/terminal/tui/useNativeInput.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/useNativeInput.js +188 -0
- package/dist/native/README.md +53 -0
- package/dist/native/claude_code_native.darwin-x64.node +0 -0
- package/dist/native/claude_code_native.dylib +0 -0
- package/dist/native/index.d.ts +0 -0
- package/dist/native/index.d.ts.map +1 -0
- package/dist/native/index.darwin-arm64.node +0 -0
- package/dist/native/index.js +43 -0
- package/dist/native/index.node +0 -0
- package/dist/native/package.json +34 -0
- package/dist/teammates/index.d.ts +161 -0
- package/dist/teammates/index.d.ts.map +1 -0
- package/dist/teammates/index.js +827 -0
- package/dist/types/index.d.ts +482 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +52 -0
- package/native/index.darwin-arm64.node +0 -0
- package/native/index.js +33 -19
- package/package.json +6 -3
- package/packages/src/core/__tests__/permissions.test.ts +1091 -0
- package/packages/src/core/agent-loop/__tests__/compaction.test.ts +283 -0
- package/packages/src/core/agent-loop/__tests__/formatters.test.ts +234 -0
- package/packages/src/core/agent-loop/__tests__/index.test.ts +162 -0
- package/packages/src/core/agent-loop/__tests__/loop-state.test.ts +413 -0
- package/packages/src/core/agent-loop/__tests__/message-builder.test.ts +229 -0
- package/packages/src/core/agent-loop/__tests__/tool-executor.test.ts +457 -0
- package/packages/src/core/agent-loop/compaction.ts +92 -0
- package/packages/src/core/agent-loop/formatters.ts +50 -0
- package/packages/src/core/agent-loop/index.ts +137 -0
- package/packages/src/core/agent-loop/loop-state.ts +187 -0
- package/packages/src/core/agent-loop/message-builder.ts +62 -0
- package/packages/src/core/agent-loop/tool-executor.ts +211 -0
- package/packages/src/core/agent-loop/turn-executor.ts +226 -0
- package/packages/src/core/agent-loop/types.ts +152 -0
- package/packages/src/core/agent-loop.ts +18 -0
- package/packages/src/core/api-client-impl.ts +729 -0
- package/packages/src/core/api-client.ts +6 -0
- package/packages/src/core/checkpoints.ts +606 -0
- package/packages/src/core/claude-md.ts +272 -0
- package/packages/src/core/cognitive-security/hooks.ts +591 -0
- package/packages/src/core/cognitive-security/index.ts +2041 -0
- package/packages/src/core/cognitive-security/middleware.ts +536 -0
- package/packages/src/core/config/todo +7 -0
- package/packages/src/core/config-loader.ts +324 -0
- package/packages/src/core/context/__tests__/integration.test.ts +334 -0
- package/packages/src/core/context/compaction.ts +170 -0
- package/packages/src/core/context/constants.ts +58 -0
- package/packages/src/core/context/extraction.ts +85 -0
- package/packages/src/core/context/index.ts +66 -0
- package/packages/src/core/context/summarization.ts +251 -0
- package/packages/src/core/context/token-estimation.ts +98 -0
- package/packages/src/core/context/types.ts +59 -0
- package/packages/src/core/git-status.ts +262 -0
- package/packages/src/core/image.test.ts +180 -0
- package/packages/src/core/image.ts +350 -0
- package/packages/src/core/lmdb.db +0 -0
- package/packages/src/core/lmdb.db-lock +0 -0
- package/packages/src/core/models.ts +507 -0
- package/packages/src/core/normalizers/todo +8 -0
- package/packages/src/core/permissions.ts +431 -0
- package/packages/src/core/providers/README.md +230 -0
- package/packages/src/core/providers/__tests__/providers.test.ts +135 -0
- package/packages/src/core/providers/index.ts +419 -0
- package/packages/src/core/providers/types.ts +132 -0
- package/packages/src/core/retry.ts +180 -0
- package/packages/src/core/session-store.ts +36 -0
- package/packages/src/core/sessions/export.ts +329 -0
- package/packages/src/core/sessions/index.ts +587 -0
- package/packages/src/core/sessions/metadata.ts +309 -0
- package/packages/src/core/sessions/persistence.ts +244 -0
- package/packages/src/core/sessions/types.ts +169 -0
- package/packages/src/core/stream-highlighter.ts +1123 -0
- package/packages/src/core/system-reminders.ts +402 -0
- package/packages/src/core/todo +8 -0
- package/packages/src/ecosystem/hooks/__tests__/index.test.ts +561 -0
- package/packages/src/ecosystem/hooks/index.ts +341 -0
- package/packages/src/ecosystem/hooks/prompt-evaluator.ts +300 -0
- package/packages/src/ecosystem/skills/index.ts +295 -0
- package/packages/src/ecosystem/tools/__tests__/index.test.ts +1335 -0
- package/packages/src/ecosystem/tools/index.ts +2051 -0
- package/packages/src/index.ts +141 -0
- package/packages/src/interfaces/mcp/client.ts +389 -0
- package/packages/src/interfaces/ui/index.ts +158 -0
- package/packages/src/interfaces/ui/lmdb.db +0 -0
- package/packages/src/interfaces/ui/lmdb.db-lock +0 -0
- package/packages/src/interfaces/ui/spinner.ts +451 -0
- package/packages/src/interfaces/ui/terminal/bridge/index.ts +370 -0
- package/packages/src/interfaces/ui/terminal/bridge/ipc.ts +829 -0
- package/packages/src/interfaces/ui/terminal/bridge/screen-export.ts +968 -0
- package/packages/src/interfaces/ui/terminal/bridge/types.ts +226 -0
- package/packages/src/interfaces/ui/terminal/bridge/useBridge.ts +210 -0
- package/packages/src/interfaces/ui/terminal/cli/bootstrap.ts +132 -0
- package/packages/src/interfaces/ui/terminal/cli/index.ts +415 -0
- package/packages/src/interfaces/ui/terminal/cli/interactive/index.ts +110 -0
- package/packages/src/interfaces/ui/terminal/cli/interactive/input-handler.ts +393 -0
- package/packages/src/interfaces/ui/terminal/cli/interactive/interactive-runner.ts +820 -0
- package/packages/src/interfaces/ui/terminal/cli/interactive/message-store.ts +299 -0
- package/packages/src/interfaces/ui/terminal/cli/interactive/types.ts +274 -0
- package/packages/src/interfaces/ui/terminal/lmdb.db +0 -0
- package/packages/src/interfaces/ui/terminal/lmdb.db-lock +0 -0
- package/packages/src/interfaces/ui/terminal/shared/args.ts +222 -0
- package/packages/src/interfaces/ui/terminal/shared/index.ts +84 -0
- package/packages/src/interfaces/ui/terminal/shared/loading-state.ts +322 -0
- package/packages/src/interfaces/ui/terminal/shared/query.ts +152 -0
- package/packages/src/interfaces/ui/terminal/shared/setup.ts +299 -0
- package/packages/src/interfaces/ui/terminal/shared/spinner-frames.ts +73 -0
- package/packages/src/interfaces/ui/terminal/shared/status-line.ts +366 -0
- package/packages/src/interfaces/ui/terminal/shared/system-prompt.ts +146 -0
- package/packages/src/lmdb.db +0 -0
- package/packages/src/lmdb.db-lock +0 -0
- package/packages/src/native/index.ts +2722 -0
- package/packages/src/native/tui_v2_types.ts +39 -0
- package/packages/src/teammates/coordination.test.ts +279 -0
- package/packages/src/teammates/coordination.ts +646 -0
- package/packages/src/teammates/index.ts +1052 -0
- package/packages/src/teammates/integration.test.ts +272 -0
- package/packages/src/teammates/runner.test.ts +235 -0
- package/packages/src/teammates/runner.ts +750 -0
- package/packages/src/teammates/schemas.ts +673 -0
- package/packages/src/types/index.ts +723 -0
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config Loader - Load Coder configuration files
|
|
3
|
+
*
|
|
4
|
+
* Loads from:
|
|
5
|
+
* 1. ~/.claude.json (MCP servers, project settings)
|
|
6
|
+
* 2. ~/.claude/settings.json (hooks, permissions)
|
|
7
|
+
* 3. ~/.claude/keybindings.json (keybindings)
|
|
8
|
+
* 4. .claude/settings.json (project-level overrides)
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { readFile, access } from "fs/promises";
|
|
12
|
+
import { join } from "path";
|
|
13
|
+
import type { MCPServerConfig, PermissionMode, HookDefinition, HookEvent } from "../types/index.js";
|
|
14
|
+
|
|
15
|
+
// ============================================
|
|
16
|
+
// TYPES
|
|
17
|
+
// ============================================
|
|
18
|
+
|
|
19
|
+
export interface ClaudeMainConfig {
|
|
20
|
+
numStartups?: number;
|
|
21
|
+
verbose?: boolean;
|
|
22
|
+
preferredNotifChannel?: "terminal_bell" | "notification";
|
|
23
|
+
projects?: Record<string, ProjectConfig>;
|
|
24
|
+
mcpServers?: Record<string, MCPServerConfig>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface ProjectConfig {
|
|
28
|
+
allowedTools?: string[];
|
|
29
|
+
mcpServers?: Record<string, MCPServerConfig>;
|
|
30
|
+
enabledMcpjsonServers?: string[];
|
|
31
|
+
disabledMcpjsonServers?: string[];
|
|
32
|
+
hasTrustDialogAccepted?: boolean;
|
|
33
|
+
lastSessionId?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface SettingsConfig {
|
|
37
|
+
hooks?: Partial<Record<HookEvent, HookMatcherConfig[]>>;
|
|
38
|
+
permissions?: {
|
|
39
|
+
defaultMode?: PermissionMode;
|
|
40
|
+
allowedTools?: string[];
|
|
41
|
+
disallowedTools?: string[];
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface HookMatcherConfig {
|
|
46
|
+
matcher?: string;
|
|
47
|
+
hooks: Array<{
|
|
48
|
+
type: "command" | "prompt";
|
|
49
|
+
command?: string;
|
|
50
|
+
prompt?: string;
|
|
51
|
+
timeout?: number;
|
|
52
|
+
}>;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface KeybindingConfig {
|
|
56
|
+
bindings: Array<{
|
|
57
|
+
key: string;
|
|
58
|
+
command: string;
|
|
59
|
+
when?: string;
|
|
60
|
+
}>;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface LoadedConfig {
|
|
64
|
+
main: ClaudeMainConfig;
|
|
65
|
+
settings: SettingsConfig;
|
|
66
|
+
keybindings: KeybindingConfig;
|
|
67
|
+
projectSettings: SettingsConfig;
|
|
68
|
+
sources: string[];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// ============================================
|
|
72
|
+
// PATHS
|
|
73
|
+
// ============================================
|
|
74
|
+
|
|
75
|
+
const HOME = process.env.HOME || "";
|
|
76
|
+
const CLAUDE_DIR = join(HOME, ".claude");
|
|
77
|
+
|
|
78
|
+
export const CONFIG_PATHS = {
|
|
79
|
+
main: join(HOME, ".claude.json"),
|
|
80
|
+
settings: join(CLAUDE_DIR, "settings.json"),
|
|
81
|
+
keybindings: join(CLAUDE_DIR, "keybindings.json"),
|
|
82
|
+
projectSettings: (projectDir: string) => join(projectDir, ".claude", "settings.json"),
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// ============================================
|
|
86
|
+
// HELPERS
|
|
87
|
+
// ============================================
|
|
88
|
+
|
|
89
|
+
async function fileExists(path: string): Promise<boolean> {
|
|
90
|
+
try {
|
|
91
|
+
await access(path);
|
|
92
|
+
return true;
|
|
93
|
+
} catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async function loadJsonFile<T>(path: string, defaultValue: T): Promise<{ config: T; loaded: boolean }> {
|
|
99
|
+
try {
|
|
100
|
+
if (await fileExists(path)) {
|
|
101
|
+
const content = await readFile(path, "utf-8");
|
|
102
|
+
return { config: JSON.parse(content) as T, loaded: true };
|
|
103
|
+
}
|
|
104
|
+
} catch (error) {
|
|
105
|
+
// File not readable or invalid JSON
|
|
106
|
+
}
|
|
107
|
+
return { config: defaultValue, loaded: false };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ============================================
|
|
111
|
+
// LOADERS
|
|
112
|
+
// ============================================
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Load main ~/.claude.json config
|
|
116
|
+
*/
|
|
117
|
+
export async function loadMainConfig(): Promise<{ config: ClaudeMainConfig; loaded: boolean }> {
|
|
118
|
+
return loadJsonFile<ClaudeMainConfig>(CONFIG_PATHS.main, {});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Load settings from ~/.claude/settings.json
|
|
123
|
+
*/
|
|
124
|
+
export async function loadSettings(): Promise<{ config: SettingsConfig; loaded: boolean }> {
|
|
125
|
+
return loadJsonFile<SettingsConfig>(CONFIG_PATHS.settings, {});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Load keybindings from ~/.claude/keybindings.json
|
|
130
|
+
*/
|
|
131
|
+
export async function loadKeybindings(): Promise<{ config: KeybindingConfig; loaded: boolean }> {
|
|
132
|
+
return loadJsonFile<KeybindingConfig>(CONFIG_PATHS.keybindings, { bindings: [] });
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Load project-level settings
|
|
137
|
+
*/
|
|
138
|
+
export async function loadProjectSettings(
|
|
139
|
+
projectDir: string
|
|
140
|
+
): Promise<{ config: SettingsConfig; loaded: boolean }> {
|
|
141
|
+
return loadJsonFile<SettingsConfig>(CONFIG_PATHS.projectSettings(projectDir), {});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Get project-specific config from main config
|
|
146
|
+
*/
|
|
147
|
+
export function getProjectConfig(
|
|
148
|
+
mainConfig: ClaudeMainConfig,
|
|
149
|
+
projectDir: string
|
|
150
|
+
): ProjectConfig | undefined {
|
|
151
|
+
return mainConfig.projects?.[projectDir];
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Load all configs at once
|
|
156
|
+
*/
|
|
157
|
+
export async function loadAllConfigs(projectDir: string = process.cwd()): Promise<LoadedConfig> {
|
|
158
|
+
const sources: string[] = [];
|
|
159
|
+
|
|
160
|
+
const { config: main, loaded: mainLoaded } = await loadMainConfig();
|
|
161
|
+
if (mainLoaded) sources.push(CONFIG_PATHS.main);
|
|
162
|
+
|
|
163
|
+
const { config: settings, loaded: settingsLoaded } = await loadSettings();
|
|
164
|
+
if (settingsLoaded) sources.push(CONFIG_PATHS.settings);
|
|
165
|
+
|
|
166
|
+
const { config: keybindings, loaded: kbLoaded } = await loadKeybindings();
|
|
167
|
+
if (kbLoaded) sources.push(CONFIG_PATHS.keybindings);
|
|
168
|
+
|
|
169
|
+
const { config: projectSettings, loaded: projLoaded } = await loadProjectSettings(projectDir);
|
|
170
|
+
if (projLoaded) sources.push(CONFIG_PATHS.projectSettings(projectDir));
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
main,
|
|
174
|
+
settings,
|
|
175
|
+
keybindings,
|
|
176
|
+
projectSettings,
|
|
177
|
+
sources,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// ============================================
|
|
182
|
+
// MERGED CONFIG
|
|
183
|
+
// ============================================
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Get merged settings (global + project overrides)
|
|
187
|
+
*/
|
|
188
|
+
export function getMergedSettings(
|
|
189
|
+
global: SettingsConfig,
|
|
190
|
+
project: SettingsConfig
|
|
191
|
+
): SettingsConfig {
|
|
192
|
+
return {
|
|
193
|
+
hooks: { ...global.hooks, ...project.hooks },
|
|
194
|
+
permissions: {
|
|
195
|
+
...global.permissions,
|
|
196
|
+
...project.permissions,
|
|
197
|
+
},
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Get all MCP servers (global + project-specific)
|
|
203
|
+
*/
|
|
204
|
+
export function getAllMCPServers(
|
|
205
|
+
mainConfig: ClaudeMainConfig,
|
|
206
|
+
projectDir: string
|
|
207
|
+
): Record<string, MCPServerConfig> {
|
|
208
|
+
const servers: Record<string, MCPServerConfig> = {};
|
|
209
|
+
|
|
210
|
+
// Global MCP servers
|
|
211
|
+
if (mainConfig.mcpServers) {
|
|
212
|
+
Object.assign(servers, mainConfig.mcpServers);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Project-specific MCP servers
|
|
216
|
+
const projectConfig = getProjectConfig(mainConfig, projectDir);
|
|
217
|
+
if (projectConfig?.mcpServers) {
|
|
218
|
+
// Project servers can override global
|
|
219
|
+
Object.assign(servers, projectConfig.mcpServers);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return servers;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Note: HookDefinition is imported at the top of the file
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Get hooks for a specific event and tool
|
|
229
|
+
*/
|
|
230
|
+
export function getHooksForEvent(
|
|
231
|
+
settings: SettingsConfig,
|
|
232
|
+
event: HookEvent,
|
|
233
|
+
toolName?: string
|
|
234
|
+
): HookMatcherConfig["hooks"] {
|
|
235
|
+
const eventHooks = settings.hooks?.[event];
|
|
236
|
+
if (!eventHooks) return [];
|
|
237
|
+
|
|
238
|
+
// Find matching hooks
|
|
239
|
+
for (const hookConfig of eventHooks) {
|
|
240
|
+
if (!hookConfig.matcher) {
|
|
241
|
+
// No matcher = matches all
|
|
242
|
+
return hookConfig.hooks;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Check if tool name matches
|
|
246
|
+
if (toolName) {
|
|
247
|
+
const regex = new RegExp(hookConfig.matcher);
|
|
248
|
+
if (regex.test(toolName)) {
|
|
249
|
+
return hookConfig.hooks;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return [];
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Convert settings hooks to HookDefinitions for HookManager
|
|
259
|
+
*/
|
|
260
|
+
export function settingsToHookDefinitions(
|
|
261
|
+
settings: SettingsConfig
|
|
262
|
+
): Partial<Record<HookEvent, HookDefinition[]>> {
|
|
263
|
+
const result: Partial<Record<HookEvent, HookDefinition[]>> = {};
|
|
264
|
+
|
|
265
|
+
if (!settings.hooks) return result;
|
|
266
|
+
|
|
267
|
+
for (const [event, matcherConfigs] of Object.entries(settings.hooks)) {
|
|
268
|
+
const definitions: HookDefinition[] = [];
|
|
269
|
+
const hookEvent = event as HookEvent;
|
|
270
|
+
|
|
271
|
+
for (const matcherConfig of matcherConfigs) {
|
|
272
|
+
for (const hook of matcherConfig.hooks) {
|
|
273
|
+
// Handle prompt-type hooks - they will be evaluated by LLM
|
|
274
|
+
if (hook.type === "prompt") {
|
|
275
|
+
definitions.push({
|
|
276
|
+
event: hookEvent,
|
|
277
|
+
command: "", // Not used for prompt hooks
|
|
278
|
+
prompt: hook.prompt || "",
|
|
279
|
+
timeout: hook.timeout || 30000,
|
|
280
|
+
enabled: true,
|
|
281
|
+
// Store matcher for runtime filtering
|
|
282
|
+
_matcher: matcherConfig.matcher,
|
|
283
|
+
} as HookDefinition & { _matcher?: string });
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
definitions.push({
|
|
287
|
+
event: hookEvent,
|
|
288
|
+
command: hook.type === "command" ? hook.command || "" : "",
|
|
289
|
+
timeout: hook.timeout || 60000,
|
|
290
|
+
enabled: true,
|
|
291
|
+
// Store matcher for runtime filtering
|
|
292
|
+
_matcher: matcherConfig.matcher,
|
|
293
|
+
} as HookDefinition & { _matcher?: string });
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (definitions.length > 0) {
|
|
298
|
+
result[hookEvent] = definitions;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
return result;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Get permission mode from settings
|
|
307
|
+
*/
|
|
308
|
+
export function getPermissionMode(settings: SettingsConfig): PermissionMode {
|
|
309
|
+
return settings.permissions?.defaultMode || "default";
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Get allowed tools from settings
|
|
314
|
+
*/
|
|
315
|
+
export function getAllowedTools(settings: SettingsConfig): Set<string> {
|
|
316
|
+
return new Set(settings.permissions?.allowedTools || []);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Get disallowed tools from settings
|
|
321
|
+
*/
|
|
322
|
+
export function getDisallowedTools(settings: SettingsConfig): Set<string> {
|
|
323
|
+
return new Set(settings.permissions?.disallowedTools || []);
|
|
324
|
+
}
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import { describe, it, expect } from "bun:test";
|
|
2
|
+
import { compactMessages, needsCompaction, getCompactionStats } from "../compaction.js";
|
|
3
|
+
import { LoopState } from "../../agent-loop/loop-state.js";
|
|
4
|
+
import type { Message, ContentBlock } from "../../../types/index.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Integration tests for context compaction module
|
|
8
|
+
* Tests compaction, token estimation, and LoopState integration
|
|
9
|
+
*/
|
|
10
|
+
describe("Context Compaction Integration", () => {
|
|
11
|
+
// Helper to create text content blocks
|
|
12
|
+
const textBlock = (text: string): ContentBlock => ({ type: "text", text });
|
|
13
|
+
|
|
14
|
+
// Helper to create messages
|
|
15
|
+
const userMessage = (content: string | ContentBlock[]): Message => ({
|
|
16
|
+
role: "user",
|
|
17
|
+
content: Array.isArray(content) ? content : [textBlock(content)]
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const assistantMessage = (content: string | ContentBlock[]): Message => ({
|
|
21
|
+
role: "assistant",
|
|
22
|
+
content: Array.isArray(content) ? content : [textBlock(content)]
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe("needsCompaction", () => {
|
|
26
|
+
it("returns false for empty messages", () => {
|
|
27
|
+
const messages: Message[] = [];
|
|
28
|
+
const result = needsCompaction(messages, 1000);
|
|
29
|
+
expect(result).toBe(false);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("returns false for small messages", () => {
|
|
33
|
+
const messages = [
|
|
34
|
+
userMessage("Hello"),
|
|
35
|
+
assistantMessage("Hi there!")
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
const result = needsCompaction(messages, 100000);
|
|
39
|
+
expect(result).toBe(false);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("returns true when exceeding threshold", () => {
|
|
43
|
+
// Add many large messages to exceed threshold
|
|
44
|
+
const messages: Message[] = [];
|
|
45
|
+
for (let i = 0; i < 100; i++) {
|
|
46
|
+
messages.push(userMessage("This is a test message ".repeat(100)));
|
|
47
|
+
messages.push(assistantMessage("This is a response message ".repeat(100)));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const result = needsCompaction(messages, 1000);
|
|
51
|
+
expect(result).toBe(true);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
describe("compactMessages", () => {
|
|
56
|
+
it("compacts messages while preserving first and last", async () => {
|
|
57
|
+
const messages: Message[] = [];
|
|
58
|
+
|
|
59
|
+
// First messages (to preserve)
|
|
60
|
+
messages.push(userMessage("Initial question"));
|
|
61
|
+
messages.push(assistantMessage("Initial response"));
|
|
62
|
+
|
|
63
|
+
// Middle messages (to summarize)
|
|
64
|
+
for (let i = 0; i < 20; i++) {
|
|
65
|
+
messages.push(userMessage(`User question ${i}: ` + "test ".repeat(50)));
|
|
66
|
+
messages.push(assistantMessage(`Assistant answer ${i}: ` + "response ".repeat(50)));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Last messages (to preserve)
|
|
70
|
+
messages.push(userMessage("Final question"));
|
|
71
|
+
messages.push(assistantMessage("Final response"));
|
|
72
|
+
|
|
73
|
+
// Use lower maxTokens to ensure compaction triggers
|
|
74
|
+
const result = await compactMessages(messages, 500, {
|
|
75
|
+
keepFirst: 2,
|
|
76
|
+
keepLast: 2,
|
|
77
|
+
useLLMSummarization: false
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Verify compaction occurred
|
|
81
|
+
expect(result.didCompact).toBe(true);
|
|
82
|
+
expect(result.messages.length).toBeLessThan(messages.length);
|
|
83
|
+
expect(result.messages.length).toBeGreaterThan(0);
|
|
84
|
+
expect(result.tokensAfter).toBeLessThan(result.tokensBefore);
|
|
85
|
+
|
|
86
|
+
// Verify first messages preserved
|
|
87
|
+
expect(result.messages[0]).toEqual(messages[0]);
|
|
88
|
+
expect(result.messages[1]).toEqual(messages[1]);
|
|
89
|
+
|
|
90
|
+
// Verify last messages preserved
|
|
91
|
+
const lastIdx = result.messages.length - 1;
|
|
92
|
+
expect(result.messages[lastIdx - 1]).toEqual(messages[messages.length - 2]);
|
|
93
|
+
expect(result.messages[lastIdx]).toEqual(messages[messages.length - 1]);
|
|
94
|
+
|
|
95
|
+
// Verify summary inserted
|
|
96
|
+
const hasSummary = result.messages.some(m =>
|
|
97
|
+
m.content.some(block =>
|
|
98
|
+
block.type === "text" &&
|
|
99
|
+
(block as any).text?.includes("compacted")
|
|
100
|
+
)
|
|
101
|
+
);
|
|
102
|
+
expect(hasSummary).toBe(true);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it("handles empty messages gracefully", async () => {
|
|
106
|
+
const messages: Message[] = [];
|
|
107
|
+
|
|
108
|
+
const result = await compactMessages(messages, 1000);
|
|
109
|
+
|
|
110
|
+
expect(result.messages).toEqual([]);
|
|
111
|
+
expect(result.didCompact).toBe(false);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("returns unchanged if under token limit", async () => {
|
|
115
|
+
const messages = [
|
|
116
|
+
userMessage("Hello"),
|
|
117
|
+
assistantMessage("Hi!")
|
|
118
|
+
];
|
|
119
|
+
|
|
120
|
+
const result = await compactMessages(messages, 100000);
|
|
121
|
+
|
|
122
|
+
expect(result.didCompact).toBe(false);
|
|
123
|
+
expect(result.messages).toEqual(messages);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it("preserves tool use and tool result pairs", async () => {
|
|
127
|
+
const messages: Message[] = [
|
|
128
|
+
userMessage("Read the file"),
|
|
129
|
+
{
|
|
130
|
+
role: "assistant",
|
|
131
|
+
content: [
|
|
132
|
+
textBlock("I'll read the file."),
|
|
133
|
+
{ type: "tool_use", id: "tool-1", name: "Read", input: { file_path: "/test.txt" } }
|
|
134
|
+
]
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
role: "user",
|
|
138
|
+
content: [
|
|
139
|
+
{ type: "tool_result", tool_use_id: "tool-1", content: "File contents here" }
|
|
140
|
+
]
|
|
141
|
+
},
|
|
142
|
+
assistantMessage("The file contains test data.")
|
|
143
|
+
];
|
|
144
|
+
|
|
145
|
+
const result = await compactMessages(messages, 500, {
|
|
146
|
+
keepFirst: 1,
|
|
147
|
+
keepLast: 1,
|
|
148
|
+
preserveToolPairs: true,
|
|
149
|
+
useLLMSummarization: false
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// Should have compacted with tool pairs preserved
|
|
153
|
+
expect(result.messages.length).toBeGreaterThan(0);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
describe("getCompactionStats", () => {
|
|
158
|
+
it("returns zero stats for no compaction", () => {
|
|
159
|
+
const result = {
|
|
160
|
+
messages: [],
|
|
161
|
+
messagesRemoved: 0,
|
|
162
|
+
tokensBefore: 100,
|
|
163
|
+
tokensAfter: 100,
|
|
164
|
+
didCompact: false
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const stats = getCompactionStats(result);
|
|
168
|
+
|
|
169
|
+
expect(stats.reductionPercent).toBe(0);
|
|
170
|
+
expect(stats.tokensSaved).toBe(0);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it("calculates correct stats after compaction", () => {
|
|
174
|
+
const result = {
|
|
175
|
+
messages: [],
|
|
176
|
+
messagesRemoved: 50,
|
|
177
|
+
tokensBefore: 1000,
|
|
178
|
+
tokensAfter: 300,
|
|
179
|
+
didCompact: true
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
const stats = getCompactionStats(result);
|
|
183
|
+
|
|
184
|
+
expect(stats.tokensSaved).toBe(700);
|
|
185
|
+
expect(stats.reductionPercent).toBeCloseTo(70, 0);
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
describe("LoopState integration", () => {
|
|
190
|
+
it("LoopState.applyCompaction works with compactMessages result", async () => {
|
|
191
|
+
const initialMessages: Message[] = [];
|
|
192
|
+
for (let i = 0; i < 30; i++) {
|
|
193
|
+
initialMessages.push(userMessage(`Message ${i}: ` + "x".repeat(100)));
|
|
194
|
+
initialMessages.push(assistantMessage(`Response ${i}: ` + "y".repeat(100)));
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const loopState = new LoopState(initialMessages);
|
|
198
|
+
|
|
199
|
+
// Compact
|
|
200
|
+
const compactionResult = await compactMessages(loopState.messages, 5000, {
|
|
201
|
+
keepFirst: 2,
|
|
202
|
+
keepLast: 4,
|
|
203
|
+
useLLMSummarization: false
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// Apply to state
|
|
207
|
+
const applied = loopState.applyCompaction(compactionResult, getCompactionStats);
|
|
208
|
+
|
|
209
|
+
if (compactionResult.didCompact) {
|
|
210
|
+
expect(applied).toBe(true);
|
|
211
|
+
expect(loopState.messages.length).toBeLessThan(initialMessages.length);
|
|
212
|
+
expect(loopState.compactionCount).toBe(1);
|
|
213
|
+
expect(loopState.totalTokensCompacted).toBeGreaterThan(0);
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
describe("extraction and summarization integration", () => {
|
|
219
|
+
it("extracts text correctly from mixed content blocks", async () => {
|
|
220
|
+
const messages: Message[] = [
|
|
221
|
+
{
|
|
222
|
+
role: "user",
|
|
223
|
+
content: [
|
|
224
|
+
textBlock("Here's my question:"),
|
|
225
|
+
{ type: "image", source: { type: "base64", media_type: "image/png", data: "abc123" } } as ContentBlock,
|
|
226
|
+
textBlock("Please help with this.")
|
|
227
|
+
]
|
|
228
|
+
},
|
|
229
|
+
assistantMessage("I'll help you with that.")
|
|
230
|
+
];
|
|
231
|
+
|
|
232
|
+
const result = await compactMessages(messages, 500, {
|
|
233
|
+
useLLMSummarization: false
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// Text should be handled, image preserved or summarized
|
|
237
|
+
expect(result.messages.length).toBeGreaterThan(0);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it("summarizes long conversations effectively", async () => {
|
|
241
|
+
const messages: Message[] = [
|
|
242
|
+
userMessage("I need to build a REST API"),
|
|
243
|
+
assistantMessage("I'll help you build a REST API. What framework?"),
|
|
244
|
+
userMessage("Express.js"),
|
|
245
|
+
assistantMessage("Great choice. Let's set up routes.")
|
|
246
|
+
];
|
|
247
|
+
|
|
248
|
+
// Add more conversation to ensure we exceeds token limit
|
|
249
|
+
for (let i = 0; i < 30; i++) {
|
|
250
|
+
messages.push(userMessage(`Question about route ${i}: ` + "test ".repeat(100)));
|
|
251
|
+
messages.push(assistantMessage(`Answer about route ${i}: ` + "response ".repeat(100)));
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Use a very low token limit to force compaction
|
|
255
|
+
const result = await compactMessages(messages, 100, {
|
|
256
|
+
keepFirst: 2,
|
|
257
|
+
keepLast: 4,
|
|
258
|
+
useLLMSummarization: false
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
// Should have summary of earlier conversation
|
|
262
|
+
expect(result.didCompact).toBe(true);
|
|
263
|
+
expect(result.messages.length).toBeLessThan(messages.length);
|
|
264
|
+
expect(result.messagesRemoved).toBeGreaterThan(0);
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
describe("performance with large contexts", () => {
|
|
269
|
+
it("handles 100+ messages efficiently", async () => {
|
|
270
|
+
const messages: Message[] = [];
|
|
271
|
+
|
|
272
|
+
// Add 100 messages
|
|
273
|
+
for (let i = 0; i < 100; i++) {
|
|
274
|
+
messages.push(userMessage(`User ${i}: ` + "test ".repeat(20)));
|
|
275
|
+
messages.push(assistantMessage(`Assistant ${i}: ` + "response ".repeat(20)));
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const startTime = Date.now();
|
|
279
|
+
|
|
280
|
+
const result = await compactMessages(messages, 5000, {
|
|
281
|
+
keepFirst: 2,
|
|
282
|
+
keepLast: 4,
|
|
283
|
+
useLLMSummarization: false
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
const duration = Date.now() - startTime;
|
|
287
|
+
|
|
288
|
+
// Should complete in reasonable time (< 5s for integration test)
|
|
289
|
+
expect(duration).toBeLessThan(5000);
|
|
290
|
+
expect(result.didCompact).toBe(true);
|
|
291
|
+
expect(result.messages.length).toBeLessThan(200);
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
describe("error handling and edge cases", () => {
|
|
296
|
+
it("handles messages with empty content", async () => {
|
|
297
|
+
const messages: Message[] = [
|
|
298
|
+
{ role: "user", content: [] },
|
|
299
|
+
{ role: "assistant", content: [] }
|
|
300
|
+
];
|
|
301
|
+
|
|
302
|
+
const result = await compactMessages(messages, 1000);
|
|
303
|
+
|
|
304
|
+
expect(result.messages).toBeDefined();
|
|
305
|
+
expect(result.didCompact).toBe(false);
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
it("handles malformed content blocks gracefully", async () => {
|
|
309
|
+
const messages: Message[] = [
|
|
310
|
+
{
|
|
311
|
+
role: "user",
|
|
312
|
+
content: [
|
|
313
|
+
{ type: "unknown" } as unknown as ContentBlock,
|
|
314
|
+
textBlock("Valid text")
|
|
315
|
+
]
|
|
316
|
+
}
|
|
317
|
+
];
|
|
318
|
+
|
|
319
|
+
const result = await compactMessages(messages, 1000);
|
|
320
|
+
|
|
321
|
+
expect(result.messages.length).toBeGreaterThan(0);
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
it("handles very large single messages", async () => {
|
|
325
|
+
const hugeText = "x".repeat(100000);
|
|
326
|
+
const messages = [userMessage(hugeText)];
|
|
327
|
+
|
|
328
|
+
const result = await compactMessages(messages, 1000);
|
|
329
|
+
|
|
330
|
+
// Should return as-is (not enough messages to compact)
|
|
331
|
+
expect(result.messages.length).toBe(1);
|
|
332
|
+
});
|
|
333
|
+
});
|
|
334
|
+
});
|