@ebowwa/coder 0.7.63 → 0.7.64
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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 +32 -52192
- 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 +159 -52768
- 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/index.d.ts +480 -0
- package/dist/native/index.d.ts.map +1 -0
- package/dist/native/index.js +1625 -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/package.json +4 -2
- package/packages/src/core/__tests__/permissions.test.ts +1091 -0
- package/packages/src/core/agent-loop/__tests__/compaction.test.ts +280 -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 +88 -0
- package/packages/src/core/agent-loop/formatters.ts +50 -0
- package/packages/src/core/agent-loop/index.ts +135 -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 +222 -0
- package/packages/src/core/agent-loop/types.ts +148 -0
- package/packages/src/core/agent-loop.ts +18 -0
- package/packages/src/core/api-client-impl.ts +619 -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 +590 -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-loader.ts +324 -0
- package/packages/src/core/context-compaction.ts +578 -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 +430 -0
- package/packages/src/core/normalizers/todo +4 -0
- package/packages/src/core/permissions.ts +431 -0
- package/packages/src/core/retry.ts +170 -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 +1877 -0
- package/packages/src/index.ts +120 -0
- package/packages/src/interfaces/mcp/client.ts +389 -0
- package/packages/src/interfaces/ui/Screenshot 2026-03-02 at 9.23.10/342/200/257PM.png +0 -0
- package/packages/src/interfaces/ui/Screenshot 2026-03-03 at 10.55.11/342/200/257AM.png +0 -0
- package/packages/src/interfaces/ui/index.ts +161 -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/cli/index.ts +228 -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 +71 -0
- package/packages/src/interfaces/ui/terminal/shared/loading-state.ts +322 -0
- package/packages/src/interfaces/ui/terminal/shared/query.ts +146 -0
- package/packages/src/interfaces/ui/terminal/shared/setup.ts +295 -0
- package/packages/src/interfaces/ui/terminal/shared/status-line.ts +358 -0
- package/packages/src/interfaces/ui/terminal/shared/system-prompt.ts +146 -0
- package/packages/src/interfaces/ui/terminal/tui/HelpPanel.tsx +262 -0
- package/packages/src/interfaces/ui/terminal/tui/InputContext.tsx +232 -0
- package/packages/src/interfaces/ui/terminal/tui/InputField.tsx +62 -0
- package/packages/src/interfaces/ui/terminal/tui/InteractiveTUI.tsx +537 -0
- package/packages/src/interfaces/ui/terminal/tui/MessageArea.tsx +107 -0
- package/packages/src/interfaces/ui/terminal/tui/MessageStore.tsx +240 -0
- package/packages/src/interfaces/ui/terminal/tui/StatusBar.tsx +54 -0
- package/packages/src/interfaces/ui/terminal/tui/commands.ts +438 -0
- package/packages/src/interfaces/ui/terminal/tui/components/InteractiveElements.tsx +584 -0
- package/packages/src/interfaces/ui/terminal/tui/components/MultilineInput.tsx +614 -0
- package/packages/src/interfaces/ui/terminal/tui/components/PaneManager.tsx +333 -0
- package/packages/src/interfaces/ui/terminal/tui/components/Sidebar.tsx +604 -0
- package/packages/src/interfaces/ui/terminal/tui/components/index.ts +118 -0
- package/packages/src/interfaces/ui/terminal/tui/console.ts +49 -0
- package/packages/src/interfaces/ui/terminal/tui/index.ts +90 -0
- package/packages/src/interfaces/ui/terminal/tui/run.tsx +42 -0
- package/packages/src/interfaces/ui/terminal/tui/spinner.ts +69 -0
- package/packages/src/interfaces/ui/terminal/tui/tui-app.tsx +390 -0
- package/packages/src/interfaces/ui/terminal/tui/tui-footer.ts +422 -0
- package/packages/src/interfaces/ui/terminal/tui/types.ts +186 -0
- package/packages/src/interfaces/ui/terminal/tui/useInputHandler.ts +104 -0
- package/packages/src/interfaces/ui/terminal/tui/useNativeInput.ts +239 -0
- package/packages/src/lmdb.db +0 -0
- package/packages/src/lmdb.db-lock +0 -0
- package/packages/src/native/index.ts +2345 -0
- package/packages/src/teammates/index.ts +982 -0
- package/packages/src/types/index.ts +722 -0
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Executor Tests - Parallel tool execution with hooks and permissions
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, it, expect, beforeEach } from "bun:test";
|
|
6
|
+
import { executeTools, type ToolExecutionOptions } from "../tool-executor.js";
|
|
7
|
+
import type {
|
|
8
|
+
ToolDefinition,
|
|
9
|
+
ToolUseBlock,
|
|
10
|
+
ToolResult,
|
|
11
|
+
PermissionMode,
|
|
12
|
+
} from "../../../types/index.js";
|
|
13
|
+
import { PermissionManager } from "../../permissions.js";
|
|
14
|
+
|
|
15
|
+
// Mock tool definitions
|
|
16
|
+
const createMockTool = (
|
|
17
|
+
name: string,
|
|
18
|
+
handler: (args: Record<string, unknown>) => Promise<ToolResult>
|
|
19
|
+
): ToolDefinition => ({
|
|
20
|
+
name,
|
|
21
|
+
description: `Mock ${name} tool`,
|
|
22
|
+
input_schema: {
|
|
23
|
+
type: "object",
|
|
24
|
+
properties: {},
|
|
25
|
+
},
|
|
26
|
+
handler,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe("executeTools", () => {
|
|
30
|
+
let permissionManager: PermissionManager;
|
|
31
|
+
let toolResults: Array<{ id: string; result: ToolResult }>;
|
|
32
|
+
|
|
33
|
+
beforeEach(() => {
|
|
34
|
+
permissionManager = new PermissionManager("bypassPermissions");
|
|
35
|
+
toolResults = [];
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const createOptions = (
|
|
39
|
+
tools: ToolDefinition[],
|
|
40
|
+
overrides: Partial<ToolExecutionOptions> = {}
|
|
41
|
+
): ToolExecutionOptions => ({
|
|
42
|
+
tools,
|
|
43
|
+
workingDirectory: "/test",
|
|
44
|
+
permissionMode: "bypassPermissions" as PermissionMode,
|
|
45
|
+
permissionManager,
|
|
46
|
+
onToolResult: (result) => toolResults.push(result),
|
|
47
|
+
...overrides,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe("basic execution", () => {
|
|
51
|
+
it("should execute a single tool and return result", async () => {
|
|
52
|
+
const tools = [
|
|
53
|
+
createMockTool("TestTool", async () => ({ content: "Success" })),
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
const toolUseBlocks: ToolUseBlock[] = [
|
|
57
|
+
{ type: "tool_use", id: "tool1", name: "TestTool", input: {} },
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
const results = await executeTools(toolUseBlocks, createOptions(tools));
|
|
61
|
+
|
|
62
|
+
expect(results).toHaveLength(1);
|
|
63
|
+
expect(results[0]?.tool_use_id).toBe("tool1");
|
|
64
|
+
expect(results[0]?.content).toBe("Success");
|
|
65
|
+
expect(results[0]?.is_error).toBeFalsy();
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("should execute multiple tools in parallel", async () => {
|
|
69
|
+
const executionOrder: string[] = [];
|
|
70
|
+
|
|
71
|
+
const tools = [
|
|
72
|
+
createMockTool("Tool1", async () => {
|
|
73
|
+
executionOrder.push("Tool1");
|
|
74
|
+
await new Promise((r) => setTimeout(r, 10));
|
|
75
|
+
return { content: "Result 1" };
|
|
76
|
+
}),
|
|
77
|
+
createMockTool("Tool2", async () => {
|
|
78
|
+
executionOrder.push("Tool2");
|
|
79
|
+
await new Promise((r) => setTimeout(r, 5));
|
|
80
|
+
return { content: "Result 2" };
|
|
81
|
+
}),
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
const toolUseBlocks: ToolUseBlock[] = [
|
|
85
|
+
{ type: "tool_use", id: "tool1", name: "Tool1", input: {} },
|
|
86
|
+
{ type: "tool_use", id: "tool2", name: "Tool2", input: {} },
|
|
87
|
+
];
|
|
88
|
+
|
|
89
|
+
const results = await executeTools(toolUseBlocks, createOptions(tools));
|
|
90
|
+
|
|
91
|
+
expect(results).toHaveLength(2);
|
|
92
|
+
// Both should have been started before either finished (parallel)
|
|
93
|
+
expect(executionOrder).toContain("Tool1");
|
|
94
|
+
expect(executionOrder).toContain("Tool2");
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("should return error for unknown tool", async () => {
|
|
98
|
+
const tools = [
|
|
99
|
+
createMockTool("KnownTool", async () => ({ content: "OK" })),
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
const toolUseBlocks: ToolUseBlock[] = [
|
|
103
|
+
{ type: "tool_use", id: "tool1", name: "UnknownTool", input: {} },
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
const results = await executeTools(toolUseBlocks, createOptions(tools));
|
|
107
|
+
|
|
108
|
+
expect(results).toHaveLength(1);
|
|
109
|
+
expect(results[0]?.is_error).toBe(true);
|
|
110
|
+
expect(results[0]?.content).toContain("Unknown tool");
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("should handle tool handler errors", async () => {
|
|
114
|
+
const tools = [
|
|
115
|
+
createMockTool("FailingTool", async () => {
|
|
116
|
+
throw new Error("Handler error");
|
|
117
|
+
}),
|
|
118
|
+
];
|
|
119
|
+
|
|
120
|
+
const toolUseBlocks: ToolUseBlock[] = [
|
|
121
|
+
{ type: "tool_use", id: "tool1", name: "FailingTool", input: {} },
|
|
122
|
+
];
|
|
123
|
+
|
|
124
|
+
const results = await executeTools(toolUseBlocks, createOptions(tools));
|
|
125
|
+
|
|
126
|
+
expect(results).toHaveLength(1);
|
|
127
|
+
expect(results[0]?.is_error).toBe(true);
|
|
128
|
+
expect(results[0]?.content).toContain("Handler error");
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it("should pass tool input to handler", async () => {
|
|
132
|
+
let receivedInput: Record<string, unknown> | null = null;
|
|
133
|
+
|
|
134
|
+
const tools = [
|
|
135
|
+
createMockTool("InputTool", async (args) => {
|
|
136
|
+
receivedInput = args;
|
|
137
|
+
return { content: "OK" };
|
|
138
|
+
}),
|
|
139
|
+
];
|
|
140
|
+
|
|
141
|
+
const toolUseBlocks: ToolUseBlock[] = [
|
|
142
|
+
{
|
|
143
|
+
type: "tool_use",
|
|
144
|
+
id: "tool1",
|
|
145
|
+
name: "InputTool",
|
|
146
|
+
input: { path: "/test/file.txt", mode: "read" },
|
|
147
|
+
},
|
|
148
|
+
];
|
|
149
|
+
|
|
150
|
+
await executeTools(toolUseBlocks, createOptions(tools));
|
|
151
|
+
|
|
152
|
+
expect(receivedInput).not.toBeNull();
|
|
153
|
+
expect(receivedInput as unknown as Record<string, unknown>).toEqual({ path: "/test/file.txt", mode: "read" });
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
describe("tool result callbacks", () => {
|
|
158
|
+
it("should call onToolResult for successful tools", async () => {
|
|
159
|
+
const tools = [
|
|
160
|
+
createMockTool("SuccessTool", async () => ({ content: "Done" })),
|
|
161
|
+
];
|
|
162
|
+
|
|
163
|
+
const toolUseBlocks: ToolUseBlock[] = [
|
|
164
|
+
{ type: "tool_use", id: "tool1", name: "SuccessTool", input: {} },
|
|
165
|
+
];
|
|
166
|
+
|
|
167
|
+
await executeTools(toolUseBlocks, createOptions(tools));
|
|
168
|
+
|
|
169
|
+
expect(toolResults).toHaveLength(1);
|
|
170
|
+
expect(toolResults[0]?.id).toBe("tool1");
|
|
171
|
+
expect(toolResults[0]?.result.content).toBe("Done");
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it("should not call onToolResult for unknown tools", async () => {
|
|
175
|
+
const tools: ToolDefinition[] = [];
|
|
176
|
+
|
|
177
|
+
const toolUseBlocks: ToolUseBlock[] = [
|
|
178
|
+
{ type: "tool_use", id: "tool1", name: "Unknown", input: {} },
|
|
179
|
+
];
|
|
180
|
+
|
|
181
|
+
await executeTools(toolUseBlocks, createOptions(tools));
|
|
182
|
+
|
|
183
|
+
expect(toolResults).toHaveLength(0);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it("should not call onToolResult for failed tools", async () => {
|
|
187
|
+
const tools = [
|
|
188
|
+
createMockTool("FailingTool", async () => {
|
|
189
|
+
throw new Error("Fail");
|
|
190
|
+
}),
|
|
191
|
+
];
|
|
192
|
+
|
|
193
|
+
const toolUseBlocks: ToolUseBlock[] = [
|
|
194
|
+
{ type: "tool_use", id: "tool1", name: "FailingTool", input: {} },
|
|
195
|
+
];
|
|
196
|
+
|
|
197
|
+
await executeTools(toolUseBlocks, createOptions(tools));
|
|
198
|
+
|
|
199
|
+
expect(toolResults).toHaveLength(0);
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
describe("abort signal", () => {
|
|
204
|
+
it("should return empty array if signal is already aborted", async () => {
|
|
205
|
+
const tools = [
|
|
206
|
+
createMockTool("Tool", async () => ({ content: "OK" })),
|
|
207
|
+
];
|
|
208
|
+
|
|
209
|
+
const controller = new AbortController();
|
|
210
|
+
controller.abort();
|
|
211
|
+
|
|
212
|
+
const toolUseBlocks: ToolUseBlock[] = [
|
|
213
|
+
{ type: "tool_use", id: "tool1", name: "Tool", input: {} },
|
|
214
|
+
];
|
|
215
|
+
|
|
216
|
+
const results = await executeTools(
|
|
217
|
+
toolUseBlocks,
|
|
218
|
+
createOptions(tools, { signal: controller.signal })
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
expect(results).toHaveLength(0);
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
describe("permission checks", () => {
|
|
226
|
+
it("should deny tool when permission is denied", async () => {
|
|
227
|
+
const tools = [
|
|
228
|
+
createMockTool("RestrictedTool", async () => ({ content: "Should not reach" })),
|
|
229
|
+
];
|
|
230
|
+
|
|
231
|
+
const denyManager = new PermissionManager("dontAsk");
|
|
232
|
+
|
|
233
|
+
const toolUseBlocks: ToolUseBlock[] = [
|
|
234
|
+
{ type: "tool_use", id: "tool1", name: "RestrictedTool", input: {} },
|
|
235
|
+
];
|
|
236
|
+
|
|
237
|
+
const results = await executeTools(
|
|
238
|
+
toolUseBlocks,
|
|
239
|
+
createOptions(tools, { permissionManager: denyManager })
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
expect(results).toHaveLength(1);
|
|
243
|
+
expect(results[0]?.is_error).toBe(true);
|
|
244
|
+
expect(results[0]?.content).toContain("Permission denied");
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
it("should allow tool when permission is granted", async () => {
|
|
248
|
+
const tools = [
|
|
249
|
+
createMockTool("AllowedTool", async () => ({ content: "Success" })),
|
|
250
|
+
];
|
|
251
|
+
|
|
252
|
+
const toolUseBlocks: ToolUseBlock[] = [
|
|
253
|
+
{ type: "tool_use", id: "tool1", name: "AllowedTool", input: {} },
|
|
254
|
+
];
|
|
255
|
+
|
|
256
|
+
const results = await executeTools(
|
|
257
|
+
toolUseBlocks,
|
|
258
|
+
createOptions(tools, { permissionManager })
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
expect(results[0]?.is_error).toBeFalsy();
|
|
262
|
+
expect(results[0]?.content).toBe("Success");
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
describe("hook integration", () => {
|
|
267
|
+
it("should execute PreToolUse hooks", async () => {
|
|
268
|
+
let hookCalled = false;
|
|
269
|
+
|
|
270
|
+
const mockHookManager = {
|
|
271
|
+
execute: async (event: string, input: any) => {
|
|
272
|
+
if (event === "PreToolUse") {
|
|
273
|
+
hookCalled = true;
|
|
274
|
+
}
|
|
275
|
+
return { decision: "allow" as const };
|
|
276
|
+
},
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
const tools = [
|
|
280
|
+
createMockTool("HookTool", async () => ({ content: "OK" })),
|
|
281
|
+
];
|
|
282
|
+
|
|
283
|
+
const toolUseBlocks: ToolUseBlock[] = [
|
|
284
|
+
{ type: "tool_use", id: "tool1", name: "HookTool", input: {} },
|
|
285
|
+
];
|
|
286
|
+
|
|
287
|
+
await executeTools(
|
|
288
|
+
toolUseBlocks,
|
|
289
|
+
createOptions(tools, { hookManager: mockHookManager as any })
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
expect(hookCalled).toBe(true);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it("should block tool when PreToolUse hook denies", async () => {
|
|
296
|
+
const mockHookManager = {
|
|
297
|
+
execute: async (event: string, input: any) => {
|
|
298
|
+
if (event === "PreToolUse") {
|
|
299
|
+
return { decision: "deny" as const, reason: "Blocked by hook" };
|
|
300
|
+
}
|
|
301
|
+
return { decision: "allow" as const };
|
|
302
|
+
},
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
const tools = [
|
|
306
|
+
createMockTool("BlockedTool", async () => ({ content: "Should not reach" })),
|
|
307
|
+
];
|
|
308
|
+
|
|
309
|
+
const toolUseBlocks: ToolUseBlock[] = [
|
|
310
|
+
{ type: "tool_use", id: "tool1", name: "BlockedTool", input: {} },
|
|
311
|
+
];
|
|
312
|
+
|
|
313
|
+
const results = await executeTools(
|
|
314
|
+
toolUseBlocks,
|
|
315
|
+
createOptions(tools, { hookManager: mockHookManager as any })
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
expect(results[0]?.is_error).toBe(true);
|
|
319
|
+
expect(results[0]?.content).toContain("Blocked by hook");
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
it("should execute PostToolUse hooks", async () => {
|
|
323
|
+
let postHookCalled = false;
|
|
324
|
+
|
|
325
|
+
const mockHookManager = {
|
|
326
|
+
execute: async (event: string, input: any) => {
|
|
327
|
+
if (event === "PostToolUse") {
|
|
328
|
+
postHookCalled = true;
|
|
329
|
+
}
|
|
330
|
+
return { decision: "allow" as const };
|
|
331
|
+
},
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
const tools = [
|
|
335
|
+
createMockTool("PostHookTool", async () => ({ content: "Result" })),
|
|
336
|
+
];
|
|
337
|
+
|
|
338
|
+
const toolUseBlocks: ToolUseBlock[] = [
|
|
339
|
+
{ type: "tool_use", id: "tool1", name: "PostHookTool", input: {} },
|
|
340
|
+
];
|
|
341
|
+
|
|
342
|
+
await executeTools(
|
|
343
|
+
toolUseBlocks,
|
|
344
|
+
createOptions(tools, { hookManager: mockHookManager as any })
|
|
345
|
+
);
|
|
346
|
+
|
|
347
|
+
expect(postHookCalled).toBe(true);
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
it("should modify tool input via hook", async () => {
|
|
351
|
+
let receivedInput: Record<string, unknown> | null = null;
|
|
352
|
+
|
|
353
|
+
const mockHookManager = {
|
|
354
|
+
execute: async (event: string, input: any) => {
|
|
355
|
+
if (event === "PreToolUse") {
|
|
356
|
+
return {
|
|
357
|
+
decision: "allow" as const,
|
|
358
|
+
modified_input: { modified: true },
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
return { decision: "allow" as const };
|
|
362
|
+
},
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
const tools = [
|
|
366
|
+
createMockTool("ModifiedInputTool", async (args) => {
|
|
367
|
+
receivedInput = args;
|
|
368
|
+
return { content: "OK" };
|
|
369
|
+
}),
|
|
370
|
+
];
|
|
371
|
+
|
|
372
|
+
const toolUseBlocks: ToolUseBlock[] = [
|
|
373
|
+
{
|
|
374
|
+
type: "tool_use",
|
|
375
|
+
id: "tool1",
|
|
376
|
+
name: "ModifiedInputTool",
|
|
377
|
+
input: { original: true },
|
|
378
|
+
},
|
|
379
|
+
];
|
|
380
|
+
|
|
381
|
+
await executeTools(
|
|
382
|
+
toolUseBlocks,
|
|
383
|
+
createOptions(tools, { hookManager: mockHookManager as any })
|
|
384
|
+
);
|
|
385
|
+
|
|
386
|
+
// Object.assign merges properties, so we get both original and modified
|
|
387
|
+
expect(receivedInput).not.toBeNull();
|
|
388
|
+
expect(receivedInput as unknown as Record<string, unknown>).toEqual({ original: true, modified: true });
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
it("should execute PostToolUseFailure hooks on error", async () => {
|
|
392
|
+
let failureHookCalled = false;
|
|
393
|
+
|
|
394
|
+
const mockHookManager = {
|
|
395
|
+
execute: async (event: string, input: any) => {
|
|
396
|
+
if (event === "PostToolUseFailure") {
|
|
397
|
+
failureHookCalled = true;
|
|
398
|
+
expect(input.error).toContain("Handler crashed");
|
|
399
|
+
}
|
|
400
|
+
return { decision: "allow" as const };
|
|
401
|
+
},
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
const tools = [
|
|
405
|
+
createMockTool("CrashTool", async () => {
|
|
406
|
+
throw new Error("Handler crashed");
|
|
407
|
+
}),
|
|
408
|
+
];
|
|
409
|
+
|
|
410
|
+
const toolUseBlocks: ToolUseBlock[] = [
|
|
411
|
+
{ type: "tool_use", id: "tool1", name: "CrashTool", input: {} },
|
|
412
|
+
];
|
|
413
|
+
|
|
414
|
+
await executeTools(
|
|
415
|
+
toolUseBlocks,
|
|
416
|
+
createOptions(tools, { hookManager: mockHookManager as any })
|
|
417
|
+
);
|
|
418
|
+
|
|
419
|
+
expect(failureHookCalled).toBe(true);
|
|
420
|
+
});
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
describe("error handling", () => {
|
|
424
|
+
it("should handle non-Error thrown objects", async () => {
|
|
425
|
+
const tools = [
|
|
426
|
+
createMockTool("StringThrowTool", async () => {
|
|
427
|
+
throw "String error";
|
|
428
|
+
}),
|
|
429
|
+
];
|
|
430
|
+
|
|
431
|
+
const toolUseBlocks: ToolUseBlock[] = [
|
|
432
|
+
{ type: "tool_use", id: "tool1", name: "StringThrowTool", input: {} },
|
|
433
|
+
];
|
|
434
|
+
|
|
435
|
+
const results = await executeTools(toolUseBlocks, createOptions(tools));
|
|
436
|
+
|
|
437
|
+
expect(results[0]?.is_error).toBe(true);
|
|
438
|
+
expect(results[0]?.content).toContain("String error");
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
it("should handle null thrown", async () => {
|
|
442
|
+
const tools = [
|
|
443
|
+
createMockTool("NullThrowTool", async () => {
|
|
444
|
+
throw null;
|
|
445
|
+
}),
|
|
446
|
+
];
|
|
447
|
+
|
|
448
|
+
const toolUseBlocks: ToolUseBlock[] = [
|
|
449
|
+
{ type: "tool_use", id: "tool1", name: "NullThrowTool", input: {} },
|
|
450
|
+
];
|
|
451
|
+
|
|
452
|
+
const results = await executeTools(toolUseBlocks, createOptions(tools));
|
|
453
|
+
|
|
454
|
+
expect(results[0]?.is_error).toBe(true);
|
|
455
|
+
});
|
|
456
|
+
});
|
|
457
|
+
});
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compaction Handler - Context compaction strategies
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { Message } from "../../types/index.js";
|
|
6
|
+
import {
|
|
7
|
+
needsCompaction,
|
|
8
|
+
compactMessages,
|
|
9
|
+
getCompactionStats,
|
|
10
|
+
type CompactionResult,
|
|
11
|
+
} from "../context-compaction.js";
|
|
12
|
+
import type { LoopState } from "./loop-state.js";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Compaction options
|
|
16
|
+
*/
|
|
17
|
+
export interface CompactionOptions {
|
|
18
|
+
/** Number of initial messages to preserve (0 = none) */
|
|
19
|
+
keepFirst?: number;
|
|
20
|
+
/** Number of recent messages to preserve */
|
|
21
|
+
keepLast?: number;
|
|
22
|
+
/** Preserve tool use/result pairs */
|
|
23
|
+
preserveToolPairs?: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Default compaction options for proactive compaction */
|
|
27
|
+
export const DEFAULT_PROACTIVE_OPTIONS: CompactionOptions = {
|
|
28
|
+
keepFirst: 0, // Don't preserve first message - summary covers it
|
|
29
|
+
keepLast: 3, // Only keep last 3 messages for more aggressive compaction
|
|
30
|
+
preserveToolPairs: true,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/** Default compaction options for reactive compaction (on max_tokens) */
|
|
34
|
+
export const DEFAULT_REACTIVE_OPTIONS: CompactionOptions = {
|
|
35
|
+
keepFirst: 0, // Don't preserve first message
|
|
36
|
+
keepLast: 3, // More aggressive - only keep last 3
|
|
37
|
+
preserveToolPairs: true,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Check if compaction is needed and apply it proactively
|
|
42
|
+
* @returns true if compaction was applied
|
|
43
|
+
*/
|
|
44
|
+
export async function handleProactiveCompaction(
|
|
45
|
+
state: LoopState,
|
|
46
|
+
maxTokens: number,
|
|
47
|
+
options: CompactionOptions = DEFAULT_PROACTIVE_OPTIONS
|
|
48
|
+
): Promise<boolean> {
|
|
49
|
+
if (!needsCompaction(state.messages, maxTokens)) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const compactionResult = await compactMessages(state.messages, maxTokens, {
|
|
54
|
+
keepFirst: options.keepFirst ?? 0,
|
|
55
|
+
keepLast: options.keepLast ?? 3,
|
|
56
|
+
preserveToolPairs: options.preserveToolPairs ?? true,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
return state.applyCompaction(compactionResult, getCompactionStats);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Handle reactive compaction when max_tokens is hit
|
|
64
|
+
* @returns true if compaction was applied and loop should continue
|
|
65
|
+
*/
|
|
66
|
+
export async function handleReactiveCompaction(
|
|
67
|
+
state: LoopState,
|
|
68
|
+
maxTokens: number,
|
|
69
|
+
options: CompactionOptions = DEFAULT_REACTIVE_OPTIONS
|
|
70
|
+
): Promise<boolean> {
|
|
71
|
+
const compactionResult = await compactMessages(state.messages, maxTokens, {
|
|
72
|
+
keepFirst: options.keepFirst ?? 0,
|
|
73
|
+
keepLast: options.keepLast ?? 3,
|
|
74
|
+
preserveToolPairs: options.preserveToolPairs ?? true,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
return state.applyCompaction(compactionResult, getCompactionStats);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Check if messages need compaction
|
|
82
|
+
*/
|
|
83
|
+
export { needsCompaction };
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Get token estimate for messages
|
|
87
|
+
*/
|
|
88
|
+
export { estimateMessagesTokens } from "../context-compaction.js";
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formatters - Cost and metrics display utilities
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { QueryMetrics, CacheMetrics } from "../../types/index.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Format cost for display
|
|
9
|
+
*/
|
|
10
|
+
export function formatCost(costUSD: number): string {
|
|
11
|
+
if (costUSD < 0.01) {
|
|
12
|
+
return `$${costUSD.toFixed(4)}`;
|
|
13
|
+
}
|
|
14
|
+
return `$${costUSD.toFixed(2)}`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Format metrics for display
|
|
19
|
+
*/
|
|
20
|
+
export function formatMetrics(metrics: QueryMetrics): string {
|
|
21
|
+
const cost = formatCost(metrics.costUSD);
|
|
22
|
+
const tokens = `${metrics.usage.input_tokens.toLocaleString()} input, ${metrics.usage.output_tokens.toLocaleString()} output`;
|
|
23
|
+
|
|
24
|
+
// Include cache info if available
|
|
25
|
+
if (metrics.usage.cache_read_input_tokens || metrics.usage.cache_creation_input_tokens) {
|
|
26
|
+
const cacheRead = metrics.usage.cache_read_input_tokens?.toLocaleString() ?? "0";
|
|
27
|
+
const cacheWrite = metrics.usage.cache_creation_input_tokens?.toLocaleString() ?? "0";
|
|
28
|
+
return `Cost: ${cost} | Tokens: ${tokens} | Cache: ${cacheRead} read, ${cacheWrite} write`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return `Cost: ${cost} | Tokens: ${tokens}`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Format brief cost for per-turn display (less verbose)
|
|
36
|
+
*/
|
|
37
|
+
export function formatCostBrief(metrics: QueryMetrics): string {
|
|
38
|
+
const cost = formatCost(metrics.costUSD);
|
|
39
|
+
const totalTokens = metrics.usage.input_tokens + metrics.usage.output_tokens;
|
|
40
|
+
return `Cost: ${cost} | Tokens: ${totalTokens.toLocaleString()}`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Format cache metrics for display
|
|
45
|
+
*/
|
|
46
|
+
export function formatCacheMetrics(cacheMetrics: CacheMetrics): string {
|
|
47
|
+
const savings = formatCost(cacheMetrics.estimatedSavingsUSD);
|
|
48
|
+
const hitRate = (cacheMetrics.cacheHitRate * 100).toFixed(1);
|
|
49
|
+
return `Cache: ${hitRate}% hit rate | ${cacheMetrics.totalCacheReadTokens.toLocaleString()} read | ${cacheMetrics.totalCacheWriteTokens.toLocaleString()} written | Saved: ${savings}`;
|
|
50
|
+
}
|