@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,428 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Compaction - Reduces context size while preserving important information
|
|
3
|
+
*
|
|
4
|
+
* When the context window fills up, we need to compact messages to continue.
|
|
5
|
+
* This module provides token estimation, summarization, and compaction utilities.
|
|
6
|
+
*/
|
|
7
|
+
import { SUMMARIZATION_MODEL } from "./models.js";
|
|
8
|
+
// ============================================
|
|
9
|
+
// CONSTANTS
|
|
10
|
+
// ============================================
|
|
11
|
+
/** Approximate characters per token (rough estimate for Claude models) */
|
|
12
|
+
const CHARS_PER_TOKEN = 4;
|
|
13
|
+
/** Default number of recent messages to keep during compaction */
|
|
14
|
+
const DEFAULT_KEEP_LAST = 5;
|
|
15
|
+
/** Default number of initial messages to keep (usually just the first user query) */
|
|
16
|
+
const DEFAULT_KEEP_FIRST = 1;
|
|
17
|
+
/** Minimum messages required before compaction is possible */
|
|
18
|
+
const MIN_MESSAGES_FOR_COMPACTION = 8;
|
|
19
|
+
/** Default threshold for proactive compaction (90% of max tokens) */
|
|
20
|
+
const DEFAULT_COMPACTION_THRESHOLD = 0.9;
|
|
21
|
+
/** Maximum length for summary text before truncation */
|
|
22
|
+
const MAX_SUMMARY_LENGTH = 8000;
|
|
23
|
+
/** Maximum tokens for summary output */
|
|
24
|
+
const SUMMARY_MAX_TOKENS = 2000;
|
|
25
|
+
/** System prompt for summarization */
|
|
26
|
+
const SUMMARIZATION_SYSTEM_PROMPT = `You are a context summarizer. Your job is to create concise, information-dense summaries of conversation history.
|
|
27
|
+
|
|
28
|
+
Guidelines:
|
|
29
|
+
- Preserve all important decisions, file changes, and key information
|
|
30
|
+
- Keep track of what tools were used and their outcomes
|
|
31
|
+
- Note any errors encountered and how they were resolved
|
|
32
|
+
- Maintain chronological flow
|
|
33
|
+
- Be extremely concise - use bullet points and short sentences
|
|
34
|
+
- Focus on information that would be needed to continue the conversation
|
|
35
|
+
- Do not include pleasantries or filler text
|
|
36
|
+
|
|
37
|
+
Format your summary as:
|
|
38
|
+
## Summary
|
|
39
|
+
[Brief overview of what was discussed]
|
|
40
|
+
|
|
41
|
+
## Key Actions
|
|
42
|
+
- [Action 1]
|
|
43
|
+
- [Action 2]
|
|
44
|
+
|
|
45
|
+
## Files Modified
|
|
46
|
+
- [file]: [what changed]
|
|
47
|
+
|
|
48
|
+
## Important Context
|
|
49
|
+
[Any critical information needed going forward]`;
|
|
50
|
+
/** User prompt template for summarization */
|
|
51
|
+
const SUMMARIZATION_PROMPT = `Summarize the following conversation messages for context compaction. Preserve all important information in a concise format.
|
|
52
|
+
|
|
53
|
+
Messages to summarize:
|
|
54
|
+
{{MESSAGES}}
|
|
55
|
+
|
|
56
|
+
Provide a dense, information-rich summary that captures everything needed to continue this conversation.`;
|
|
57
|
+
// ============================================
|
|
58
|
+
// TOKEN ESTIMATION
|
|
59
|
+
// ============================================
|
|
60
|
+
/**
|
|
61
|
+
* Estimate the number of tokens in a text string.
|
|
62
|
+
* Uses a simple heuristic of ~4 characters per token.
|
|
63
|
+
* This is a rough estimate; actual tokenization varies by model.
|
|
64
|
+
*/
|
|
65
|
+
export function estimateTokens(text) {
|
|
66
|
+
if (!text || text.length === 0)
|
|
67
|
+
return 0;
|
|
68
|
+
return Math.ceil(text.length / CHARS_PER_TOKEN);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Estimate tokens for a single content block
|
|
72
|
+
*/
|
|
73
|
+
function estimateBlockTokens(block) {
|
|
74
|
+
switch (block.type) {
|
|
75
|
+
case "text":
|
|
76
|
+
return estimateTokens(block.text);
|
|
77
|
+
case "image":
|
|
78
|
+
// Images are roughly 85-110 tokens for standard sizes
|
|
79
|
+
// Use 100 as an average estimate
|
|
80
|
+
return 100;
|
|
81
|
+
case "tool_use":
|
|
82
|
+
// Tool use: name + JSON input
|
|
83
|
+
const toolInput = JSON.stringify(block.input);
|
|
84
|
+
return estimateTokens(block.name) + estimateTokens(toolInput) + 10; // overhead
|
|
85
|
+
case "tool_result":
|
|
86
|
+
// Tool result: content + metadata
|
|
87
|
+
if (typeof block.content === "string") {
|
|
88
|
+
return estimateTokens(block.content) + 10;
|
|
89
|
+
}
|
|
90
|
+
return block.content.reduce((sum, b) => sum + estimateBlockTokens(b), 0) + 10;
|
|
91
|
+
case "thinking":
|
|
92
|
+
return estimateTokens(block.thinking);
|
|
93
|
+
default:
|
|
94
|
+
return 0;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Estimate the total number of tokens in a message
|
|
99
|
+
*/
|
|
100
|
+
function estimateMessageTokens(message) {
|
|
101
|
+
// Role overhead (~4 tokens)
|
|
102
|
+
const roleOverhead = 4;
|
|
103
|
+
// Sum all content blocks
|
|
104
|
+
const contentTokens = message.content.reduce((sum, block) => sum + estimateBlockTokens(block), 0);
|
|
105
|
+
return roleOverhead + contentTokens;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Get total estimated tokens across all messages
|
|
109
|
+
*/
|
|
110
|
+
export function estimateMessagesTokens(messages) {
|
|
111
|
+
if (!messages || messages.length === 0)
|
|
112
|
+
return 0;
|
|
113
|
+
return messages.reduce((sum, msg) => sum + estimateMessageTokens(msg), 0);
|
|
114
|
+
}
|
|
115
|
+
// ============================================
|
|
116
|
+
// CONTENT EXTRACTION
|
|
117
|
+
// ============================================
|
|
118
|
+
/**
|
|
119
|
+
* Extract text content from a message for summarization
|
|
120
|
+
*/
|
|
121
|
+
function extractTextFromMessage(message) {
|
|
122
|
+
const parts = [];
|
|
123
|
+
for (const block of message.content) {
|
|
124
|
+
switch (block.type) {
|
|
125
|
+
case "text":
|
|
126
|
+
parts.push(block.text);
|
|
127
|
+
break;
|
|
128
|
+
case "tool_use":
|
|
129
|
+
parts.push(`[Tool: ${block.name}(${JSON.stringify(block.input)})]`);
|
|
130
|
+
break;
|
|
131
|
+
case "tool_result":
|
|
132
|
+
const content = typeof block.content === "string"
|
|
133
|
+
? block.content
|
|
134
|
+
: block.content.map(b => b.type === "text" ? b.text : "[content]").join("");
|
|
135
|
+
parts.push(`[Result: ${content.slice(0, 500)}${content.length > 500 ? "..." : ""}]`);
|
|
136
|
+
break;
|
|
137
|
+
case "thinking":
|
|
138
|
+
parts.push(`[Thinking: ${block.thinking.slice(0, 200)}...]`);
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return parts.join("\n");
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Extract tool use/result pairs from messages for preservation
|
|
146
|
+
*/
|
|
147
|
+
function extractToolPairs(messages) {
|
|
148
|
+
const toolPairs = new Map();
|
|
149
|
+
// First pass: collect all tool uses
|
|
150
|
+
for (const message of messages) {
|
|
151
|
+
for (const block of message.content) {
|
|
152
|
+
if (block.type === "tool_use") {
|
|
153
|
+
toolPairs.set(block.id, { use: block });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Second pass: match results to uses
|
|
158
|
+
for (const message of messages) {
|
|
159
|
+
for (const block of message.content) {
|
|
160
|
+
if (block.type === "tool_result") {
|
|
161
|
+
const pair = toolPairs.get(block.tool_use_id);
|
|
162
|
+
if (pair) {
|
|
163
|
+
pair.result = block;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return toolPairs;
|
|
169
|
+
}
|
|
170
|
+
// ============================================
|
|
171
|
+
// SUMMARIZATION
|
|
172
|
+
// ============================================
|
|
173
|
+
/**
|
|
174
|
+
* Summarize a range of messages into a single text.
|
|
175
|
+
* This is a simple implementation that concatenates and truncates.
|
|
176
|
+
* Can be enhanced later with LLM-based summarization.
|
|
177
|
+
*/
|
|
178
|
+
export async function summarizeMessages(messages) {
|
|
179
|
+
if (!messages || messages.length === 0) {
|
|
180
|
+
return "";
|
|
181
|
+
}
|
|
182
|
+
const summaryParts = [];
|
|
183
|
+
summaryParts.push(`[Context Summary: ${messages.length} messages compacted]\n`);
|
|
184
|
+
// Track tool operations for a cleaner summary
|
|
185
|
+
const toolOperations = [];
|
|
186
|
+
for (let i = 0; i < messages.length; i++) {
|
|
187
|
+
const message = messages[i];
|
|
188
|
+
if (!message)
|
|
189
|
+
continue;
|
|
190
|
+
const role = message.role.toUpperCase();
|
|
191
|
+
const text = extractTextFromMessage(message);
|
|
192
|
+
// Track tool operations
|
|
193
|
+
for (const block of message.content) {
|
|
194
|
+
if (block.type === "tool_use") {
|
|
195
|
+
toolOperations.push(`${block.name}`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// Add truncated message content
|
|
199
|
+
const truncated = text.length > 300 ? `${text.slice(0, 300)}...` : text;
|
|
200
|
+
summaryParts.push(`${role}: ${truncated}\n`);
|
|
201
|
+
}
|
|
202
|
+
// Add tool summary
|
|
203
|
+
if (toolOperations.length > 0) {
|
|
204
|
+
const toolCounts = toolOperations.reduce((acc, tool) => {
|
|
205
|
+
acc[tool] = (acc[tool] || 0) + 1;
|
|
206
|
+
return acc;
|
|
207
|
+
}, {});
|
|
208
|
+
const toolSummary = Object.entries(toolCounts)
|
|
209
|
+
.map(([name, count]) => `${name}(${count})`)
|
|
210
|
+
.join(", ");
|
|
211
|
+
summaryParts.push(`\nTools used: ${toolSummary}\n`);
|
|
212
|
+
}
|
|
213
|
+
let summary = summaryParts.join("");
|
|
214
|
+
// Truncate if too long
|
|
215
|
+
if (summary.length > MAX_SUMMARY_LENGTH) {
|
|
216
|
+
summary = summary.slice(0, MAX_SUMMARY_LENGTH) + "\n...[truncated]";
|
|
217
|
+
}
|
|
218
|
+
return summary;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Summarize messages using an LLM for better context preservation.
|
|
222
|
+
* Falls back to simple truncation if LLM fails or no API key provided.
|
|
223
|
+
*/
|
|
224
|
+
export async function summarizeWithLLM(messages, options = {}) {
|
|
225
|
+
const { apiKey = process.env.ANTHROPIC_AUTH_TOKEN || process.env.ANTHROPIC_API_KEY || process.env.CLAUDE_API_KEY, model = SUMMARIZATION_MODEL, baseUrl = process.env.ANTHROPIC_BASE_URL || "https://api.anthropic.com", timeout = 30000, } = options;
|
|
226
|
+
// No API key - fall back to simple summarization
|
|
227
|
+
if (!apiKey) {
|
|
228
|
+
return summarizeMessages(messages);
|
|
229
|
+
}
|
|
230
|
+
try {
|
|
231
|
+
// Build the conversation text for summarization
|
|
232
|
+
const conversationText = messages.map((msg) => {
|
|
233
|
+
const role = msg.role.toUpperCase();
|
|
234
|
+
const text = extractTextFromMessage(msg);
|
|
235
|
+
// Extract tool info
|
|
236
|
+
const tools = [];
|
|
237
|
+
for (const block of msg.content) {
|
|
238
|
+
if (block.type === "tool_use") {
|
|
239
|
+
tools.push(`[TOOL_USE: ${block.name}]`);
|
|
240
|
+
}
|
|
241
|
+
else if (block.type === "tool_result") {
|
|
242
|
+
const resultBlock = block;
|
|
243
|
+
const preview = typeof resultBlock.content === "string"
|
|
244
|
+
? resultBlock.content.slice(0, 200)
|
|
245
|
+
: "[complex result]";
|
|
246
|
+
tools.push(`[TOOL_RESULT: ${resultBlock.is_error ? "ERROR" : "OK"}] ${preview}`);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
const toolsStr = tools.length > 0 ? `\n${tools.join("\n")}` : "";
|
|
250
|
+
return `${role}:\n${text.slice(0, 2000)}${toolsStr}`;
|
|
251
|
+
}).join("\n\n---\n\n");
|
|
252
|
+
// Build request
|
|
253
|
+
const requestBody = {
|
|
254
|
+
model,
|
|
255
|
+
max_tokens: SUMMARY_MAX_TOKENS,
|
|
256
|
+
system: SUMMARIZATION_SYSTEM_PROMPT,
|
|
257
|
+
messages: [{
|
|
258
|
+
role: "user",
|
|
259
|
+
content: SUMMARIZATION_PROMPT.replace("{{MESSAGES}}", conversationText),
|
|
260
|
+
}],
|
|
261
|
+
};
|
|
262
|
+
// Make API call with timeout
|
|
263
|
+
const controller = new AbortController();
|
|
264
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
265
|
+
try {
|
|
266
|
+
const response = await fetch(`${baseUrl}/v1/messages`, {
|
|
267
|
+
method: "POST",
|
|
268
|
+
headers: {
|
|
269
|
+
"Content-Type": "application/json",
|
|
270
|
+
"x-api-key": apiKey,
|
|
271
|
+
"anthropic-version": "2023-06-01",
|
|
272
|
+
},
|
|
273
|
+
body: JSON.stringify(requestBody),
|
|
274
|
+
signal: controller.signal,
|
|
275
|
+
});
|
|
276
|
+
clearTimeout(timeoutId);
|
|
277
|
+
if (!response.ok) {
|
|
278
|
+
const errorText = await response.text();
|
|
279
|
+
console.error(`\x1b[33m[Compaction] LLM summarization failed: ${response.status} - ${errorText}\x1b[0m`);
|
|
280
|
+
return summarizeMessages(messages);
|
|
281
|
+
}
|
|
282
|
+
const data = await response.json();
|
|
283
|
+
// Extract text from response
|
|
284
|
+
const summaryText = data.content
|
|
285
|
+
?.filter((block) => block.type === "text")
|
|
286
|
+
.map((block) => block.text || "")
|
|
287
|
+
.join("\n") || "";
|
|
288
|
+
if (!summaryText) {
|
|
289
|
+
console.error("\x1b[33m[Compaction] LLM returned empty summary\x1b[0m");
|
|
290
|
+
return summarizeMessages(messages);
|
|
291
|
+
}
|
|
292
|
+
// Log usage for debugging
|
|
293
|
+
if (data.usage) {
|
|
294
|
+
console.log(`\x1b[90m[Compaction] LLM summary: ${data.usage.input_tokens} in, ${data.usage.output_tokens} out\x1b[0m`);
|
|
295
|
+
}
|
|
296
|
+
return `[LLM Summary of ${messages.length} messages]\n\n${summaryText}`;
|
|
297
|
+
}
|
|
298
|
+
finally {
|
|
299
|
+
clearTimeout(timeoutId);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
catch (error) {
|
|
303
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
304
|
+
console.error(`\x1b[33m[Compaction] LLM summarization error: ${errorMsg}\x1b[0m`);
|
|
305
|
+
// Fall back to simple summarization
|
|
306
|
+
return summarizeMessages(messages);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Compact messages to fit within a token limit.
|
|
311
|
+
*
|
|
312
|
+
* Strategy:
|
|
313
|
+
* 1. Always keep the first N messages (original query)
|
|
314
|
+
* 2. Always keep the last M messages (recent context)
|
|
315
|
+
* 3. Summarize middle messages into a single "context summary" user message
|
|
316
|
+
* 4. Preserve tool_use/tool_result pairs when possible
|
|
317
|
+
*/
|
|
318
|
+
export async function compactMessages(messages, maxTokens, options = {}) {
|
|
319
|
+
const { keepFirst = DEFAULT_KEEP_FIRST, keepLast = DEFAULT_KEEP_LAST, preserveToolPairs = true, useLLMSummarization = true, // Default to LLM summarization
|
|
320
|
+
apiKey, baseUrl, } = options;
|
|
321
|
+
const tokensBefore = estimateMessagesTokens(messages);
|
|
322
|
+
// If already under limit, no compaction needed
|
|
323
|
+
if (tokensBefore <= maxTokens) {
|
|
324
|
+
return {
|
|
325
|
+
messages,
|
|
326
|
+
messagesRemoved: 0,
|
|
327
|
+
tokensBefore,
|
|
328
|
+
tokensAfter: tokensBefore,
|
|
329
|
+
didCompact: false,
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
// Not enough messages to compact - silent return
|
|
333
|
+
if (messages.length <= keepFirst + keepLast) {
|
|
334
|
+
return {
|
|
335
|
+
messages,
|
|
336
|
+
messagesRemoved: 0,
|
|
337
|
+
tokensBefore,
|
|
338
|
+
tokensAfter: tokensBefore,
|
|
339
|
+
didCompact: false,
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
// Extract segments
|
|
343
|
+
const firstMessages = messages.slice(0, keepFirst);
|
|
344
|
+
const middleMessages = messages.slice(keepFirst, -keepLast);
|
|
345
|
+
const lastMessages = messages.slice(-keepLast);
|
|
346
|
+
// Create summary of middle messages (use LLM if available, fallback to simple)
|
|
347
|
+
const summary = useLLMSummarization
|
|
348
|
+
? await summarizeWithLLM(middleMessages, { apiKey, baseUrl })
|
|
349
|
+
: await summarizeMessages(middleMessages);
|
|
350
|
+
// Build summary message
|
|
351
|
+
const summaryMessage = {
|
|
352
|
+
role: "user",
|
|
353
|
+
content: [{
|
|
354
|
+
type: "text",
|
|
355
|
+
text: `[Previous context has been compacted for continuity]\n\n${summary}`,
|
|
356
|
+
}],
|
|
357
|
+
};
|
|
358
|
+
// Optionally preserve important tool pairs
|
|
359
|
+
let preservedBlocks = [];
|
|
360
|
+
if (preserveToolPairs && middleMessages.length > 0) {
|
|
361
|
+
const toolPairs = extractToolPairs(middleMessages);
|
|
362
|
+
// Keep the most recent tool use/result pairs (up to 3)
|
|
363
|
+
const recentPairs = Array.from(toolPairs.values())
|
|
364
|
+
.slice(-3)
|
|
365
|
+
.filter(pair => pair.result && !pair.result.is_error);
|
|
366
|
+
for (const pair of recentPairs) {
|
|
367
|
+
preservedBlocks.push(pair.use);
|
|
368
|
+
if (pair.result) {
|
|
369
|
+
preservedBlocks.push(pair.result);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
// Build compacted message list
|
|
374
|
+
const compacted = [
|
|
375
|
+
...firstMessages,
|
|
376
|
+
summaryMessage,
|
|
377
|
+
];
|
|
378
|
+
// Add preserved tool results if any
|
|
379
|
+
if (preservedBlocks.length > 0) {
|
|
380
|
+
compacted.push({
|
|
381
|
+
role: "assistant",
|
|
382
|
+
content: preservedBlocks.filter(b => b.type === "tool_use"),
|
|
383
|
+
});
|
|
384
|
+
compacted.push({
|
|
385
|
+
role: "user",
|
|
386
|
+
content: preservedBlocks.filter(b => b.type === "tool_result"),
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
// Add recent messages
|
|
390
|
+
compacted.push(...lastMessages);
|
|
391
|
+
const tokensAfter = estimateMessagesTokens(compacted);
|
|
392
|
+
const messagesRemoved = messages.length - compacted.length;
|
|
393
|
+
console.log(`Context compaction: ${messages.length} -> ${compacted.length} messages, ${tokensBefore} -> ${tokensAfter} tokens`);
|
|
394
|
+
return {
|
|
395
|
+
messages: compacted,
|
|
396
|
+
messagesRemoved,
|
|
397
|
+
tokensBefore,
|
|
398
|
+
tokensAfter,
|
|
399
|
+
didCompact: true,
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Check if compaction is needed proactively.
|
|
404
|
+
* Returns true if current token usage exceeds the threshold AND there are enough messages to compact.
|
|
405
|
+
*/
|
|
406
|
+
export function needsCompaction(messages, maxTokens, threshold = DEFAULT_COMPACTION_THRESHOLD) {
|
|
407
|
+
// Not enough messages to meaningfully compact
|
|
408
|
+
if (messages.length < MIN_MESSAGES_FOR_COMPACTION) {
|
|
409
|
+
return false;
|
|
410
|
+
}
|
|
411
|
+
const currentTokens = estimateMessagesTokens(messages);
|
|
412
|
+
const thresholdTokens = Math.floor(maxTokens * threshold);
|
|
413
|
+
return currentTokens >= thresholdTokens;
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Get compaction statistics for logging/metrics
|
|
417
|
+
*/
|
|
418
|
+
export function getCompactionStats(result) {
|
|
419
|
+
if (!result.didCompact) {
|
|
420
|
+
return { reductionPercent: 0, tokensSaved: 0 };
|
|
421
|
+
}
|
|
422
|
+
const tokensSaved = result.tokensBefore - result.tokensAfter;
|
|
423
|
+
const reductionPercent = (tokensSaved / result.tokensBefore) * 100;
|
|
424
|
+
return {
|
|
425
|
+
reductionPercent: Math.round(reductionPercent * 100) / 100,
|
|
426
|
+
tokensSaved,
|
|
427
|
+
};
|
|
428
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Status - Retrieve repository status information
|
|
3
|
+
* Uses Bun subprocess to run git commands
|
|
4
|
+
*/
|
|
5
|
+
import type { GitStatus } from "../types/index.js";
|
|
6
|
+
/**
|
|
7
|
+
* Get comprehensive git status for a working directory
|
|
8
|
+
*
|
|
9
|
+
* @param workingDirectory - The directory to check git status for
|
|
10
|
+
* @returns GitStatus object if in a git repository, null otherwise
|
|
11
|
+
*/
|
|
12
|
+
export declare function getGitStatus(workingDirectory: string): Promise<GitStatus | null>;
|
|
13
|
+
/**
|
|
14
|
+
* Check if there are any uncommitted changes
|
|
15
|
+
*/
|
|
16
|
+
export declare function hasUncommittedChanges(status: GitStatus): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Check if the repository is clean (no changes and synced with upstream)
|
|
19
|
+
*/
|
|
20
|
+
export declare function isRepositoryClean(status: GitStatus): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Get a human-readable summary of the git status
|
|
23
|
+
*/
|
|
24
|
+
export declare function getGitStatusSummary(status: GitStatus): string;
|
|
25
|
+
//# sourceMappingURL=git-status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-status.d.ts","sourceRoot":"","sources":["../../packages/src/core/git-status.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AA4KnD;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CA6B3B;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAOhE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAE5D;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAuB7D"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Status - Retrieve repository status information
|
|
3
|
+
* Uses Bun subprocess to run git commands
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Run a git command and return its output
|
|
7
|
+
*/
|
|
8
|
+
async function runGitCommand(args, cwd) {
|
|
9
|
+
const proc = Bun.spawn(["git", ...args], {
|
|
10
|
+
cwd,
|
|
11
|
+
stdout: "pipe",
|
|
12
|
+
stderr: "pipe",
|
|
13
|
+
});
|
|
14
|
+
const stdout = await new Response(proc.stdout).text();
|
|
15
|
+
const stderr = await new Response(proc.stderr).text();
|
|
16
|
+
const exitCode = await proc.exited;
|
|
17
|
+
return { stdout: stdout.trim(), stderr: stderr.trim(), exitCode };
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Check if the directory is a git repository
|
|
21
|
+
*/
|
|
22
|
+
async function isGitRepository(workingDirectory) {
|
|
23
|
+
const { exitCode } = await runGitCommand(["rev-parse", "--git-dir"], workingDirectory);
|
|
24
|
+
return exitCode === 0;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get the current branch name
|
|
28
|
+
*/
|
|
29
|
+
async function getBranch(workingDirectory) {
|
|
30
|
+
const { stdout, exitCode } = await runGitCommand(["rev-parse", "--abbrev-ref", "HEAD"], workingDirectory);
|
|
31
|
+
if (exitCode !== 0) {
|
|
32
|
+
return "HEAD";
|
|
33
|
+
}
|
|
34
|
+
return stdout || "HEAD";
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Get ahead/behind counts compared to upstream
|
|
38
|
+
*/
|
|
39
|
+
async function getAheadBehind(workingDirectory) {
|
|
40
|
+
const { stdout, exitCode } = await runGitCommand(["rev-list", "--left-right", "--count", "@{upstream}...HEAD"], workingDirectory);
|
|
41
|
+
if (exitCode !== 0 || !stdout) {
|
|
42
|
+
return { ahead: 0, behind: 0 };
|
|
43
|
+
}
|
|
44
|
+
const parts = stdout.split(/\s+/);
|
|
45
|
+
if (parts.length >= 2 && parts[0] !== undefined && parts[1] !== undefined) {
|
|
46
|
+
return {
|
|
47
|
+
ahead: parseInt(parts[0], 10) || 0,
|
|
48
|
+
behind: parseInt(parts[1], 10) || 0,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
return { ahead: 0, behind: 0 };
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Parse git status porcelain output
|
|
55
|
+
* Format: XY PATH where X is staged status, Y is unstaged status
|
|
56
|
+
*
|
|
57
|
+
* Status codes:
|
|
58
|
+
* - ' ' (space): unmodified
|
|
59
|
+
* - 'M': modified
|
|
60
|
+
* - 'A': added (staged)
|
|
61
|
+
* - 'D': deleted
|
|
62
|
+
* - 'R': renamed
|
|
63
|
+
* - 'C': copied
|
|
64
|
+
* - 'U': unmerged (conflict)
|
|
65
|
+
* - '?': untracked
|
|
66
|
+
* - '!': ignored
|
|
67
|
+
*/
|
|
68
|
+
async function getFileStatus(workingDirectory) {
|
|
69
|
+
const { stdout, exitCode } = await runGitCommand(["status", "--porcelain"], workingDirectory);
|
|
70
|
+
if (exitCode !== 0 || !stdout) {
|
|
71
|
+
return {
|
|
72
|
+
staged: [],
|
|
73
|
+
unstaged: [],
|
|
74
|
+
untracked: [],
|
|
75
|
+
conflicted: [],
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
const staged = [];
|
|
79
|
+
const unstaged = [];
|
|
80
|
+
const untracked = [];
|
|
81
|
+
const conflicted = [];
|
|
82
|
+
const lines = stdout.split("\n");
|
|
83
|
+
for (const line of lines) {
|
|
84
|
+
if (!line)
|
|
85
|
+
continue;
|
|
86
|
+
// Porcelain format: XY PATH or XY ORIG_PATH -> PATH
|
|
87
|
+
const x = line[0]; // Staged status
|
|
88
|
+
const y = line[1]; // Unstaged status
|
|
89
|
+
let path = line.substring(3);
|
|
90
|
+
// Handle renamed files (format: "R old -> new")
|
|
91
|
+
if (path.includes(" -> ")) {
|
|
92
|
+
const splitPath = path.split(" -> ");
|
|
93
|
+
path = splitPath[1] ?? splitPath[0] ?? path;
|
|
94
|
+
}
|
|
95
|
+
// Check for conflicts (U or both A/A, D/D, etc.)
|
|
96
|
+
const isConflicted = x === "U" ||
|
|
97
|
+
y === "U" ||
|
|
98
|
+
(x === "A" && y === "A") ||
|
|
99
|
+
(x === "D" && y === "D") ||
|
|
100
|
+
x === "A" && y === "U" ||
|
|
101
|
+
x === "U" && y === "A" ||
|
|
102
|
+
x === "D" && y === "U" ||
|
|
103
|
+
x === "U" && y === "D";
|
|
104
|
+
if (isConflicted) {
|
|
105
|
+
conflicted.push(path);
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
// Untracked files
|
|
109
|
+
if (x === "?" && y === "?") {
|
|
110
|
+
untracked.push(path);
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
// Staged changes (X is not space or ?)
|
|
114
|
+
if (x !== " " && x !== "?" && x !== "!") {
|
|
115
|
+
staged.push(path);
|
|
116
|
+
}
|
|
117
|
+
// Unstaged changes (Y is not space or ?)
|
|
118
|
+
if (y !== " " && y !== "?" && y !== "!") {
|
|
119
|
+
// Don't double-add if already in staged
|
|
120
|
+
if (!staged.includes(path)) {
|
|
121
|
+
unstaged.push(path);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return { staged, unstaged, untracked, conflicted };
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Get comprehensive git status for a working directory
|
|
129
|
+
*
|
|
130
|
+
* @param workingDirectory - The directory to check git status for
|
|
131
|
+
* @returns GitStatus object if in a git repository, null otherwise
|
|
132
|
+
*/
|
|
133
|
+
export async function getGitStatus(workingDirectory) {
|
|
134
|
+
try {
|
|
135
|
+
// First check if this is a git repository
|
|
136
|
+
const isRepo = await isGitRepository(workingDirectory);
|
|
137
|
+
if (!isRepo) {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
// Run all status queries in parallel for better performance
|
|
141
|
+
const [branch, aheadBehind, fileStatus] = await Promise.all([
|
|
142
|
+
getBranch(workingDirectory),
|
|
143
|
+
getAheadBehind(workingDirectory),
|
|
144
|
+
getFileStatus(workingDirectory),
|
|
145
|
+
]);
|
|
146
|
+
return {
|
|
147
|
+
branch,
|
|
148
|
+
ahead: aheadBehind.ahead,
|
|
149
|
+
behind: aheadBehind.behind,
|
|
150
|
+
staged: fileStatus.staged,
|
|
151
|
+
unstaged: fileStatus.unstaged,
|
|
152
|
+
untracked: fileStatus.untracked,
|
|
153
|
+
conflicted: fileStatus.conflicted,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
// Log error for debugging but return null gracefully
|
|
158
|
+
console.error("Error getting git status:", error);
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Check if there are any uncommitted changes
|
|
164
|
+
*/
|
|
165
|
+
export function hasUncommittedChanges(status) {
|
|
166
|
+
return (status.staged.length > 0 ||
|
|
167
|
+
status.unstaged.length > 0 ||
|
|
168
|
+
status.untracked.length > 0 ||
|
|
169
|
+
status.conflicted.length > 0);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Check if the repository is clean (no changes and synced with upstream)
|
|
173
|
+
*/
|
|
174
|
+
export function isRepositoryClean(status) {
|
|
175
|
+
return !hasUncommittedChanges(status) && status.ahead === 0 && status.behind === 0;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Get a human-readable summary of the git status
|
|
179
|
+
*/
|
|
180
|
+
export function getGitStatusSummary(status) {
|
|
181
|
+
const parts = [];
|
|
182
|
+
parts.push(`branch: ${status.branch}`);
|
|
183
|
+
if (status.ahead > 0 || status.behind > 0) {
|
|
184
|
+
const sync = [];
|
|
185
|
+
if (status.ahead > 0)
|
|
186
|
+
sync.push(`ahead ${status.ahead}`);
|
|
187
|
+
if (status.behind > 0)
|
|
188
|
+
sync.push(`behind ${status.behind}`);
|
|
189
|
+
parts.push(`(${sync.join(", ")})`);
|
|
190
|
+
}
|
|
191
|
+
const changes = [];
|
|
192
|
+
if (status.staged.length > 0)
|
|
193
|
+
changes.push(`${status.staged.length} staged`);
|
|
194
|
+
if (status.unstaged.length > 0)
|
|
195
|
+
changes.push(`${status.unstaged.length} unstaged`);
|
|
196
|
+
if (status.untracked.length > 0)
|
|
197
|
+
changes.push(`${status.untracked.length} untracked`);
|
|
198
|
+
if (status.conflicted.length > 0)
|
|
199
|
+
changes.push(`${status.conflicted.length} conflicted`);
|
|
200
|
+
if (changes.length > 0) {
|
|
201
|
+
parts.push(`[${changes.join(", ")}]`);
|
|
202
|
+
}
|
|
203
|
+
return parts.join(" ");
|
|
204
|
+
}
|