@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,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Metadata - Manage session metadata and summaries
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type {
|
|
6
|
+
SessionMetadata,
|
|
7
|
+
SessionSummary,
|
|
8
|
+
SessionEntry,
|
|
9
|
+
SessionMessage,
|
|
10
|
+
SessionMetrics,
|
|
11
|
+
SessionFilter,
|
|
12
|
+
} from "./types.js";
|
|
13
|
+
import type { ContentBlock, Message } from "../../types/index.js";
|
|
14
|
+
import { SessionPersistence } from "./persistence.js";
|
|
15
|
+
|
|
16
|
+
export class SessionMetadataManager {
|
|
17
|
+
private persistence: SessionPersistence;
|
|
18
|
+
|
|
19
|
+
constructor(persistence: SessionPersistence) {
|
|
20
|
+
this.persistence = persistence;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Generate a new session ID
|
|
25
|
+
*/
|
|
26
|
+
generateId(): string {
|
|
27
|
+
const timestamp = Date.now().toString(36);
|
|
28
|
+
const random = Math.random().toString(36).slice(2, 8);
|
|
29
|
+
return `${timestamp}-${random}`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Create metadata for a new session
|
|
34
|
+
*/
|
|
35
|
+
createMetadata(options: {
|
|
36
|
+
id?: string;
|
|
37
|
+
model: string;
|
|
38
|
+
workingDirectory: string;
|
|
39
|
+
agentName?: string;
|
|
40
|
+
agentColor?: string;
|
|
41
|
+
teamName?: string;
|
|
42
|
+
}): SessionMetadata {
|
|
43
|
+
return {
|
|
44
|
+
type: "metadata",
|
|
45
|
+
id: options.id ?? this.generateId(),
|
|
46
|
+
created: Date.now(),
|
|
47
|
+
updated: Date.now(),
|
|
48
|
+
model: options.model,
|
|
49
|
+
workingDirectory: options.workingDirectory,
|
|
50
|
+
agentName: options.agentName,
|
|
51
|
+
agentColor: options.agentColor,
|
|
52
|
+
teamName: options.teamName,
|
|
53
|
+
totalCost: 0,
|
|
54
|
+
totalTokens: { input: 0, output: 0 },
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Update metadata timestamps
|
|
60
|
+
*/
|
|
61
|
+
touch(metadata: SessionMetadata): SessionMetadata {
|
|
62
|
+
return {
|
|
63
|
+
...metadata,
|
|
64
|
+
updated: Date.now(),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Merge updated fields into metadata
|
|
70
|
+
*/
|
|
71
|
+
merge(
|
|
72
|
+
metadata: SessionMetadata,
|
|
73
|
+
updates: Partial<SessionMetadata>
|
|
74
|
+
): SessionMetadata {
|
|
75
|
+
return {
|
|
76
|
+
...metadata,
|
|
77
|
+
...updates,
|
|
78
|
+
updated: Date.now(),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Get summary from session entries
|
|
84
|
+
*/
|
|
85
|
+
async getSummary(sessionId: string): Promise<SessionSummary | null> {
|
|
86
|
+
const entries = await this.persistence.read(sessionId);
|
|
87
|
+
return this.entriesToSummary(sessionId, entries);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Convert entries to summary
|
|
92
|
+
*/
|
|
93
|
+
entriesToSummary(
|
|
94
|
+
sessionId: string,
|
|
95
|
+
entries: SessionEntry[]
|
|
96
|
+
): SessionSummary | null {
|
|
97
|
+
let metadata: SessionMetadata | null = null;
|
|
98
|
+
let messageCount = 0;
|
|
99
|
+
let totalCost = 0;
|
|
100
|
+
let totalInput = 0;
|
|
101
|
+
let totalOutput = 0;
|
|
102
|
+
let firstMessage: string | undefined;
|
|
103
|
+
let lastActivity: number | undefined;
|
|
104
|
+
|
|
105
|
+
for (const entry of entries) {
|
|
106
|
+
// All entries have a type field now
|
|
107
|
+
if ("type" in entry) {
|
|
108
|
+
switch (entry.type) {
|
|
109
|
+
case "metadata":
|
|
110
|
+
metadata = entry as SessionMetadata;
|
|
111
|
+
break;
|
|
112
|
+
case "message":
|
|
113
|
+
messageCount++;
|
|
114
|
+
lastActivity = entry.timestamp;
|
|
115
|
+
const msg = (entry as SessionMessage).data as Message;
|
|
116
|
+
if (!firstMessage && msg.role === "user") {
|
|
117
|
+
const textBlock = msg.content.find(
|
|
118
|
+
(b: ContentBlock) => b.type === "text"
|
|
119
|
+
);
|
|
120
|
+
if (textBlock && "text" in textBlock) {
|
|
121
|
+
firstMessage = textBlock.text.slice(0, 100);
|
|
122
|
+
if (textBlock.text.length > 100) {
|
|
123
|
+
firstMessage += "...";
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
break;
|
|
128
|
+
|
|
129
|
+
case "metrics":
|
|
130
|
+
const metrics = (entry as SessionMetrics).data;
|
|
131
|
+
totalCost += metrics.costUSD;
|
|
132
|
+
totalInput += metrics.usage.input_tokens;
|
|
133
|
+
totalOutput += metrics.usage.output_tokens;
|
|
134
|
+
lastActivity = entry.timestamp;
|
|
135
|
+
break;
|
|
136
|
+
|
|
137
|
+
case "tool_use":
|
|
138
|
+
case "context":
|
|
139
|
+
case "checkpoint":
|
|
140
|
+
lastActivity = entry.timestamp;
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (!metadata) {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
id: sessionId,
|
|
152
|
+
created: metadata.created,
|
|
153
|
+
updated: metadata.updated,
|
|
154
|
+
lastActivity,
|
|
155
|
+
model: metadata.model,
|
|
156
|
+
messageCount,
|
|
157
|
+
totalCost,
|
|
158
|
+
totalTokens: { input: totalInput, output: totalOutput },
|
|
159
|
+
firstMessage,
|
|
160
|
+
workingDirectory: metadata.workingDirectory,
|
|
161
|
+
metadata: {
|
|
162
|
+
agentName: metadata.agentName,
|
|
163
|
+
agentColor: metadata.agentColor,
|
|
164
|
+
teamName: metadata.teamName,
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Filter sessions based on criteria
|
|
171
|
+
*/
|
|
172
|
+
filterSessions(
|
|
173
|
+
sessions: SessionSummary[],
|
|
174
|
+
filter: SessionFilter
|
|
175
|
+
): SessionSummary[] {
|
|
176
|
+
return sessions.filter((session) => {
|
|
177
|
+
// Filter by model
|
|
178
|
+
if (filter.model && session.model !== filter.model) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Filter by working directory
|
|
183
|
+
if (
|
|
184
|
+
filter.workingDirectory &&
|
|
185
|
+
session.workingDirectory !== filter.workingDirectory
|
|
186
|
+
) {
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Filter by minimum messages
|
|
191
|
+
if (filter.minMessages && session.messageCount < filter.minMessages) {
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Filter by age (maxAge = maximum age in ms)
|
|
196
|
+
if (filter.maxAge) {
|
|
197
|
+
const age = Date.now() - session.created;
|
|
198
|
+
if (age > filter.maxAge) {
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Filter by timestamp (since = minimum created timestamp)
|
|
204
|
+
if (filter.since && session.created < filter.since) {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return true;
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Sort sessions by various criteria
|
|
214
|
+
*/
|
|
215
|
+
sortSessions(
|
|
216
|
+
sessions: SessionSummary[],
|
|
217
|
+
sortBy: "created" | "updated" | "lastActivity" | "messageCount" | "cost" = "lastActivity",
|
|
218
|
+
order: "asc" | "desc" = "desc"
|
|
219
|
+
): SessionSummary[] {
|
|
220
|
+
return [...sessions].sort((a, b) => {
|
|
221
|
+
let comparison = 0;
|
|
222
|
+
|
|
223
|
+
switch (sortBy) {
|
|
224
|
+
case "created":
|
|
225
|
+
comparison = a.created - b.created;
|
|
226
|
+
break;
|
|
227
|
+
case "updated":
|
|
228
|
+
comparison = a.updated - b.updated;
|
|
229
|
+
break;
|
|
230
|
+
case "lastActivity":
|
|
231
|
+
comparison = (a.lastActivity ?? a.updated) - (b.lastActivity ?? b.updated);
|
|
232
|
+
break;
|
|
233
|
+
case "messageCount":
|
|
234
|
+
comparison = a.messageCount - b.messageCount;
|
|
235
|
+
break;
|
|
236
|
+
case "cost":
|
|
237
|
+
comparison = a.totalCost - b.totalCost;
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return order === "desc" ? -comparison : comparison;
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Find empty sessions (no messages)
|
|
247
|
+
*/
|
|
248
|
+
findEmptySessions(sessions: SessionSummary[]): SessionSummary[] {
|
|
249
|
+
return sessions.filter((s) => s.messageCount === 0);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Find sessions by partial ID match
|
|
254
|
+
*/
|
|
255
|
+
findById(sessions: SessionSummary[], partialId: string): SessionSummary | undefined {
|
|
256
|
+
return sessions.find((s) => s.id.startsWith(partialId) || s.id.includes(partialId));
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Get unique models from sessions
|
|
261
|
+
*/
|
|
262
|
+
getUniqueModels(sessions: SessionSummary[]): string[] {
|
|
263
|
+
const models = new Set(sessions.map((s) => s.model));
|
|
264
|
+
return [...models].sort();
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Get unique working directories from sessions
|
|
269
|
+
*/
|
|
270
|
+
getUniqueDirectories(sessions: SessionSummary[]): string[] {
|
|
271
|
+
const dirs = new Set(sessions.map((s) => s.workingDirectory));
|
|
272
|
+
return [...dirs].sort();
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Calculate aggregate statistics
|
|
277
|
+
*/
|
|
278
|
+
calculateStats(sessions: SessionSummary[]): {
|
|
279
|
+
totalSessions: number;
|
|
280
|
+
totalMessages: number;
|
|
281
|
+
totalCost: number;
|
|
282
|
+
totalInputTokens: number;
|
|
283
|
+
totalOutputTokens: number;
|
|
284
|
+
averageMessagesPerSession: number;
|
|
285
|
+
averageCostPerSession: number;
|
|
286
|
+
} {
|
|
287
|
+
const totalSessions = sessions.length;
|
|
288
|
+
const totalMessages = sessions.reduce((sum, s) => sum + s.messageCount, 0);
|
|
289
|
+
const totalCost = sessions.reduce((sum, s) => sum + s.totalCost, 0);
|
|
290
|
+
const totalInputTokens = sessions.reduce(
|
|
291
|
+
(sum, s) => sum + s.totalTokens.input,
|
|
292
|
+
0
|
|
293
|
+
);
|
|
294
|
+
const totalOutputTokens = sessions.reduce(
|
|
295
|
+
(sum, s) => sum + s.totalTokens.output,
|
|
296
|
+
0
|
|
297
|
+
);
|
|
298
|
+
|
|
299
|
+
return {
|
|
300
|
+
totalSessions,
|
|
301
|
+
totalMessages,
|
|
302
|
+
totalCost,
|
|
303
|
+
totalInputTokens,
|
|
304
|
+
totalOutputTokens,
|
|
305
|
+
averageMessagesPerSession: totalSessions > 0 ? totalMessages / totalSessions : 0,
|
|
306
|
+
averageCostPerSession: totalSessions > 0 ? totalCost / totalSessions : 0,
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
}
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Persistence - File operations for session storage
|
|
3
|
+
* Handles JSONL file I/O with atomic writes and queue management
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { homedir } from "os";
|
|
7
|
+
import { join } from "path";
|
|
8
|
+
import type {
|
|
9
|
+
SessionEntry,
|
|
10
|
+
SessionMetadata,
|
|
11
|
+
ISessionPersistence,
|
|
12
|
+
} from "./types.js";
|
|
13
|
+
|
|
14
|
+
export class SessionPersistence implements ISessionPersistence {
|
|
15
|
+
private sessionsDir: string;
|
|
16
|
+
private writeQueues: Map<string, Promise<void>> = new Map();
|
|
17
|
+
|
|
18
|
+
constructor(sessionsDir?: string) {
|
|
19
|
+
this.sessionsDir = sessionsDir ?? join(homedir(), ".claude", "sessions");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Get the sessions directory path
|
|
24
|
+
*/
|
|
25
|
+
getSessionsDir(): string {
|
|
26
|
+
return this.sessionsDir;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Get the file path for a session
|
|
31
|
+
*/
|
|
32
|
+
getSessionPath(sessionId: string): string {
|
|
33
|
+
return join(this.sessionsDir, `${sessionId}.jsonl`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Initialize the sessions directory
|
|
38
|
+
*/
|
|
39
|
+
async init(): Promise<void> {
|
|
40
|
+
try {
|
|
41
|
+
await Bun.write(join(this.sessionsDir, ".gitkeep"), "");
|
|
42
|
+
} catch {
|
|
43
|
+
// Directory might already exist
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Check if a session file exists
|
|
49
|
+
*/
|
|
50
|
+
async exists(sessionId: string): Promise<boolean> {
|
|
51
|
+
const file = Bun.file(this.getSessionPath(sessionId));
|
|
52
|
+
return file.exists();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Read all entries from a session file
|
|
57
|
+
*/
|
|
58
|
+
async read(sessionId: string): Promise<SessionEntry[]> {
|
|
59
|
+
const sessionFile = this.getSessionPath(sessionId);
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
const content = await Bun.file(sessionFile).text();
|
|
63
|
+
if (!content) {
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const entries: SessionEntry[] = [];
|
|
68
|
+
const lines = content.trim().split("\n");
|
|
69
|
+
|
|
70
|
+
for (const line of lines) {
|
|
71
|
+
if (!line.trim()) continue;
|
|
72
|
+
try {
|
|
73
|
+
entries.push(JSON.parse(line) as SessionEntry);
|
|
74
|
+
} catch {
|
|
75
|
+
// Skip malformed lines
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return entries;
|
|
80
|
+
} catch {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Append an entry to a session file (queued for atomic writes)
|
|
87
|
+
*/
|
|
88
|
+
async append(
|
|
89
|
+
sessionId: string,
|
|
90
|
+
entry: SessionEntry | SessionMetadata
|
|
91
|
+
): Promise<void> {
|
|
92
|
+
const sessionFile = this.getSessionPath(sessionId);
|
|
93
|
+
|
|
94
|
+
// Queue writes per session to ensure order
|
|
95
|
+
const existingQueue = this.writeQueues.get(sessionId) || Promise.resolve();
|
|
96
|
+
|
|
97
|
+
const newQueue = existingQueue.then(async () => {
|
|
98
|
+
const line = JSON.stringify(entry) + "\n";
|
|
99
|
+
const file = Bun.file(sessionFile);
|
|
100
|
+
const existing = (await file.exists()) ? await file.text() : "";
|
|
101
|
+
await Bun.write(sessionFile, existing + line);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
this.writeQueues.set(sessionId, newQueue);
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
await newQueue;
|
|
108
|
+
} finally {
|
|
109
|
+
// Clean up completed queue
|
|
110
|
+
if (this.writeQueues.get(sessionId) === newQueue) {
|
|
111
|
+
this.writeQueues.delete(sessionId);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Write all entries to a session file (replaces existing)
|
|
118
|
+
*/
|
|
119
|
+
async writeAll(sessionId: string, entries: SessionEntry[]): Promise<void> {
|
|
120
|
+
const sessionFile = this.getSessionPath(sessionId);
|
|
121
|
+
const content = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
122
|
+
await Bun.write(sessionFile, content);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Delete a session file
|
|
127
|
+
*/
|
|
128
|
+
async delete(sessionId: string): Promise<boolean> {
|
|
129
|
+
const sessionFile = this.getSessionPath(sessionId);
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
const file = Bun.file(sessionFile);
|
|
133
|
+
if (await file.exists()) {
|
|
134
|
+
const { unlink } = await import("fs/promises");
|
|
135
|
+
await unlink(sessionFile);
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
return false;
|
|
139
|
+
} catch {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* List all session files in the directory
|
|
146
|
+
*/
|
|
147
|
+
async listFiles(): Promise<string[]> {
|
|
148
|
+
await this.init();
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
const glob = new Bun.Glob("*.jsonl");
|
|
152
|
+
const files = [...glob.scanSync(this.sessionsDir)];
|
|
153
|
+
return files.map((f) => f.replace(".jsonl", ""));
|
|
154
|
+
} catch {
|
|
155
|
+
return [];
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Get file stats for a session
|
|
161
|
+
*/
|
|
162
|
+
async getStats(sessionId: string): Promise<{
|
|
163
|
+
exists: boolean;
|
|
164
|
+
size: number;
|
|
165
|
+
mtime: Date | null;
|
|
166
|
+
}> {
|
|
167
|
+
const sessionFile = this.getSessionPath(sessionId);
|
|
168
|
+
|
|
169
|
+
try {
|
|
170
|
+
const file = Bun.file(sessionFile);
|
|
171
|
+
const stat = await file.stat();
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
exists: true,
|
|
175
|
+
size: stat?.size ?? 0,
|
|
176
|
+
mtime: stat?.mtime ?? null,
|
|
177
|
+
};
|
|
178
|
+
} catch {
|
|
179
|
+
return { exists: false, size: 0, mtime: null };
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Get modification times for multiple sessions
|
|
185
|
+
*/
|
|
186
|
+
async getModificationTimes(sessionIds: string[]): Promise<Map<string, Date>> {
|
|
187
|
+
const times = new Map<string, Date>();
|
|
188
|
+
|
|
189
|
+
await Promise.all(
|
|
190
|
+
sessionIds.map(async (id) => {
|
|
191
|
+
const stats = await this.getStats(id);
|
|
192
|
+
if (stats.exists && stats.mtime) {
|
|
193
|
+
times.set(id, stats.mtime);
|
|
194
|
+
}
|
|
195
|
+
})
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
return times;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Read the first line (metadata) of a session file
|
|
203
|
+
*/
|
|
204
|
+
async readMetadata(sessionId: string): Promise<SessionMetadata | null> {
|
|
205
|
+
const entries = await this.read(sessionId);
|
|
206
|
+
|
|
207
|
+
for (const entry of entries) {
|
|
208
|
+
// Metadata has explicit type field now
|
|
209
|
+
if ("type" in entry && entry.type === "metadata") {
|
|
210
|
+
return entry as SessionMetadata;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Read the last N entries from a session file
|
|
219
|
+
*/
|
|
220
|
+
async readLast(sessionId: string, count: number): Promise<SessionEntry[]> {
|
|
221
|
+
const entries = await this.read(sessionId);
|
|
222
|
+
return entries.slice(-count);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Count entries in a session file
|
|
227
|
+
*/
|
|
228
|
+
async countEntries(sessionId: string): Promise<number> {
|
|
229
|
+
const entries = await this.read(sessionId);
|
|
230
|
+
return entries.length;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Singleton instance for convenience
|
|
235
|
+
let defaultPersistence: SessionPersistence | null = null;
|
|
236
|
+
|
|
237
|
+
export function getSessionPersistence(
|
|
238
|
+
sessionsDir?: string
|
|
239
|
+
): SessionPersistence {
|
|
240
|
+
if (!defaultPersistence) {
|
|
241
|
+
defaultPersistence = new SessionPersistence(sessionsDir);
|
|
242
|
+
}
|
|
243
|
+
return defaultPersistence;
|
|
244
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Types - All type definitions for session handling
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { Message, QueryMetrics } from "../../types/index.js";
|
|
6
|
+
|
|
7
|
+
// ============================================
|
|
8
|
+
// SESSION METADATA
|
|
9
|
+
// ============================================
|
|
10
|
+
|
|
11
|
+
export interface SessionMetadata {
|
|
12
|
+
type: "metadata";
|
|
13
|
+
id: string;
|
|
14
|
+
created: number;
|
|
15
|
+
updated: number;
|
|
16
|
+
model: string;
|
|
17
|
+
workingDirectory: string;
|
|
18
|
+
agentName?: string;
|
|
19
|
+
agentColor?: string;
|
|
20
|
+
teamName?: string;
|
|
21
|
+
totalCost?: number;
|
|
22
|
+
totalTokens?: { input: number; output: number };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// ============================================
|
|
26
|
+
// SESSION ENTRIES (JSONL lines)
|
|
27
|
+
// ============================================
|
|
28
|
+
|
|
29
|
+
export interface SessionMessage {
|
|
30
|
+
type: "message";
|
|
31
|
+
timestamp: number;
|
|
32
|
+
data: Message;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface SessionToolUse {
|
|
36
|
+
type: "tool_use";
|
|
37
|
+
timestamp: number;
|
|
38
|
+
toolId: string;
|
|
39
|
+
toolName: string;
|
|
40
|
+
input: Record<string, unknown>;
|
|
41
|
+
result?: string;
|
|
42
|
+
isError?: boolean;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface SessionMetrics {
|
|
46
|
+
type: "metrics";
|
|
47
|
+
timestamp: number;
|
|
48
|
+
data: QueryMetrics;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface SessionContext {
|
|
52
|
+
type: "context";
|
|
53
|
+
timestamp: number;
|
|
54
|
+
workingDirectory: string;
|
|
55
|
+
gitBranch?: string;
|
|
56
|
+
systemPrompt?: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface SessionCheckpoint {
|
|
60
|
+
type: "checkpoint";
|
|
61
|
+
timestamp: number;
|
|
62
|
+
checkpointId: string;
|
|
63
|
+
label?: string;
|
|
64
|
+
messageCount: number;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export type SessionEntry =
|
|
68
|
+
| SessionMetadata
|
|
69
|
+
| SessionMessage
|
|
70
|
+
| SessionToolUse
|
|
71
|
+
| SessionMetrics
|
|
72
|
+
| SessionContext
|
|
73
|
+
| SessionCheckpoint;
|
|
74
|
+
|
|
75
|
+
// ============================================
|
|
76
|
+
// LOADED SESSION
|
|
77
|
+
// ============================================
|
|
78
|
+
|
|
79
|
+
export interface LoadedSession {
|
|
80
|
+
metadata: SessionMetadata;
|
|
81
|
+
messages: Message[];
|
|
82
|
+
tools: SessionToolUse[];
|
|
83
|
+
metrics: QueryMetrics[];
|
|
84
|
+
context: SessionContext | null;
|
|
85
|
+
checkpoints: SessionCheckpoint[];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// ============================================
|
|
89
|
+
// SESSION SUMMARY (for listing)
|
|
90
|
+
// ============================================
|
|
91
|
+
|
|
92
|
+
export interface SessionSummary {
|
|
93
|
+
id: string;
|
|
94
|
+
created: number;
|
|
95
|
+
updated: number;
|
|
96
|
+
lastActivity?: number;
|
|
97
|
+
model: string;
|
|
98
|
+
messageCount: number;
|
|
99
|
+
totalCost: number;
|
|
100
|
+
totalTokens: { input: number; output: number };
|
|
101
|
+
firstMessage?: string;
|
|
102
|
+
workingDirectory: string;
|
|
103
|
+
metadata?: Record<string, unknown>;
|
|
104
|
+
// Additional fields for TUI compatibility
|
|
105
|
+
agentName?: string;
|
|
106
|
+
agentColor?: string;
|
|
107
|
+
teamName?: string;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ============================================
|
|
111
|
+
// SESSION FILTERS
|
|
112
|
+
// ============================================
|
|
113
|
+
|
|
114
|
+
export interface SessionFilter {
|
|
115
|
+
model?: string;
|
|
116
|
+
workingDirectory?: string;
|
|
117
|
+
minMessages?: number;
|
|
118
|
+
maxAge?: number; // milliseconds
|
|
119
|
+
since?: number; // timestamp
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// ============================================
|
|
123
|
+
// SESSION EVENTS
|
|
124
|
+
// ============================================
|
|
125
|
+
|
|
126
|
+
export type SessionEventType =
|
|
127
|
+
| "created"
|
|
128
|
+
| "resumed"
|
|
129
|
+
| "message_saved"
|
|
130
|
+
| "metrics_saved"
|
|
131
|
+
| "checkpoint_created"
|
|
132
|
+
| "deleted";
|
|
133
|
+
|
|
134
|
+
export interface SessionEvent {
|
|
135
|
+
type: SessionEventType;
|
|
136
|
+
sessionId: string;
|
|
137
|
+
timestamp: number;
|
|
138
|
+
data?: unknown;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export type SessionEventHandler = (event: SessionEvent) => void | Promise<void>;
|
|
142
|
+
|
|
143
|
+
// ============================================
|
|
144
|
+
// PERSISTENCE INTERFACE
|
|
145
|
+
// ============================================
|
|
146
|
+
|
|
147
|
+
export interface ISessionPersistence {
|
|
148
|
+
init(): Promise<void>;
|
|
149
|
+
read(sessionId: string): Promise<SessionEntry[]>;
|
|
150
|
+
append(sessionId: string, entry: SessionEntry | SessionMetadata): Promise<void>;
|
|
151
|
+
delete(sessionId: string): Promise<boolean>;
|
|
152
|
+
exists(sessionId: string): Promise<boolean>;
|
|
153
|
+
listFiles(): Promise<string[]>;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// ============================================
|
|
157
|
+
// EXPORT INTERFACE
|
|
158
|
+
// ============================================
|
|
159
|
+
|
|
160
|
+
export type ExportFormat = "jsonl" | "json" | "markdown";
|
|
161
|
+
|
|
162
|
+
export interface ISessionExporter {
|
|
163
|
+
export(session: LoadedSession, format: ExportFormat): string;
|
|
164
|
+
exportToFile(
|
|
165
|
+
sessionId: string,
|
|
166
|
+
format: ExportFormat,
|
|
167
|
+
outputPath?: string
|
|
168
|
+
): Promise<string>;
|
|
169
|
+
}
|