@ebowwa/coder 0.2.1 → 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/README.md +31 -32
- 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 -2
- 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 +167 -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/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/native/README.md +5 -5
- package/native/index.darwin-arm64.node +0 -0
- package/native/index.node +0 -0
- package/native/package.json +4 -4
- package/package.json +33 -16
- 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
- package/dist/cli.js +0 -148
- package/dist/index-0pkak453.js +0 -136
- package/dist/index-0qd0x8b4.js +0 -110
- package/dist/index-0x3kprq6.js +0 -240
- package/dist/index-1eawy937.js +0 -308
- package/dist/index-24m2aygy.js +0 -240
- package/dist/index-29xcjnne.js +0 -280
- package/dist/index-2avyytn5.js +0 -349
- package/dist/index-4ms367ey.js +0 -136
- package/dist/index-4w2t3b0m.js +0 -240
- package/dist/index-4xfgd8nz.js +0 -261
- package/dist/index-5acjp9gc.js +0 -157
- package/dist/index-5s15hr56.js +0 -136
- package/dist/index-6e4wf341.js +0 -349
- package/dist/index-6fvnkedw.js +0 -240
- package/dist/index-6rqpmd4g.js +0 -128
- package/dist/index-77ckwnbm.js +0 -280
- package/dist/index-9knxy49k.js +0 -128
- package/dist/index-9zrnw4zx.js +0 -128
- package/dist/index-bk21w99v.js +0 -280
- package/dist/index-c41n76fv.js +0 -240
- package/dist/index-cb4ppjdt.js +0 -255
- package/dist/index-cfb2edt6.js +0 -240
- package/dist/index-cmfa38hh.js +0 -308
- package/dist/index-datjz8q1.js +0 -257
- package/dist/index-eadf4wvn.js +0 -240
- package/dist/index-em5k0m3z.js +0 -345
- package/dist/index-gh8r333a.js +0 -110
- package/dist/index-gkx6k2tr.js +0 -261
- package/dist/index-h5cabfks.js +0 -155
- package/dist/index-hcrpwyy3.js +0 -261
- package/dist/index-hk7fwwa8.js +0 -257
- package/dist/index-jb8cw7f8.js +0 -136
- package/dist/index-kbyw4th1.js +0 -347
- package/dist/index-kgj5gqnm.js +0 -345
- package/dist/index-mdf6xp1z.js +0 -255
- package/dist/index-mrhv8kvc.js +0 -280
- package/dist/index-mt4743dd.js +0 -161
- package/dist/index-qnwsg97q.js +0 -240
- package/dist/index-qwdy6x44.js +0 -261
- package/dist/index-rmj77261.js +0 -157
- package/dist/index-sbbw1a61.js +0 -349
- package/dist/index-svy5bcpn.js +0 -345
- package/dist/index-tvmy7tm9.js +0 -261
- package/dist/index-tzz4vzkj.js +0 -312
- package/dist/index-vz80zmhe.js +0 -110
- package/dist/index-wed2fk67.js +0 -240
- package/dist/index-wksgzz8e.js +0 -280
- package/dist/index-wn2m4wma.js +0 -240
- package/dist/index-xha05vjc.js +0 -257
- package/dist/index-yc6eh8p8.js +0 -136
- package/dist/index-ycjxx9ft.js +0 -240
- package/dist/index-z0gzd0fc.js +0 -110
- package/dist/index-z8cwtf8j.js +0 -240
- package/dist/index-zy5mtt00.js +0 -128
|
@@ -0,0 +1,2345 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native module loader
|
|
3
|
+
* Loads Rust-compiled native modules for performance-critical operations
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { dlopen, suffix } from "bun:ffi";
|
|
7
|
+
import { join, dirname } from "path";
|
|
8
|
+
import { fileURLToPath } from "url";
|
|
9
|
+
|
|
10
|
+
// Type definitions for native module exports
|
|
11
|
+
|
|
12
|
+
export interface HighlightResult {
|
|
13
|
+
/** ANSI-colored text (for terminal display) */
|
|
14
|
+
html: string;
|
|
15
|
+
/** Theme used for highlighting */
|
|
16
|
+
theme: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface HighlightDiffResult {
|
|
20
|
+
/** ANSI-colored diff output */
|
|
21
|
+
output: string;
|
|
22
|
+
/** Number of added lines */
|
|
23
|
+
additions: number;
|
|
24
|
+
/** Number of deleted lines */
|
|
25
|
+
deletions: number;
|
|
26
|
+
/** Number of hunks */
|
|
27
|
+
hunks: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface DiffOptions {
|
|
31
|
+
/** File path to display in header */
|
|
32
|
+
file_path?: string;
|
|
33
|
+
/** Number of context lines around changes (default: 3) */
|
|
34
|
+
context_lines?: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ===== Multi-File Edit Types =====
|
|
38
|
+
|
|
39
|
+
/** A single edit operation for multi-file editing */
|
|
40
|
+
export interface MultiEditEntry {
|
|
41
|
+
/** File path to edit (absolute path) */
|
|
42
|
+
filePath: string;
|
|
43
|
+
/** String to find and replace */
|
|
44
|
+
oldString: string;
|
|
45
|
+
/** Replacement string */
|
|
46
|
+
newString: string;
|
|
47
|
+
/** Replace all occurrences (default: false) */
|
|
48
|
+
replaceAll?: boolean;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Result of an atomic multi-file edit operation */
|
|
52
|
+
export interface MultiEditResult {
|
|
53
|
+
/** Whether all edits succeeded */
|
|
54
|
+
success: boolean;
|
|
55
|
+
/** List of files that were modified */
|
|
56
|
+
filesModified: string[];
|
|
57
|
+
/** Total number of string replacements made */
|
|
58
|
+
totalReplacements: number;
|
|
59
|
+
/** Error message if operation failed */
|
|
60
|
+
error?: string;
|
|
61
|
+
/** Whether changes were rolled back due to failure */
|
|
62
|
+
rolledBack: boolean;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Preview result for a single file */
|
|
66
|
+
export interface MultiEditPreviewEntry {
|
|
67
|
+
/** File path */
|
|
68
|
+
filePath: string;
|
|
69
|
+
/** Number of replacements that would be made */
|
|
70
|
+
replacementCount: number;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ===== Quant Types =====
|
|
74
|
+
|
|
75
|
+
/** OHLCV candlestick data */
|
|
76
|
+
export interface OHLCV {
|
|
77
|
+
timestamp: number;
|
|
78
|
+
open: number;
|
|
79
|
+
high: number;
|
|
80
|
+
low: number;
|
|
81
|
+
close: number;
|
|
82
|
+
volume: number;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** AMM state for constant-product AMMs */
|
|
86
|
+
export interface AMMState {
|
|
87
|
+
pool_yes: number;
|
|
88
|
+
pool_no: number;
|
|
89
|
+
k: number;
|
|
90
|
+
fee: number;
|
|
91
|
+
price_yes: number;
|
|
92
|
+
price_no: number;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** AMM cost calculation result */
|
|
96
|
+
export interface AMMCostResult {
|
|
97
|
+
cost: number;
|
|
98
|
+
avg_price: number;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** AMM price impact result */
|
|
102
|
+
export interface AMMPriceImpactResult {
|
|
103
|
+
price_before: number;
|
|
104
|
+
price_after: number;
|
|
105
|
+
price_impact: number;
|
|
106
|
+
slippage: number;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** LMSR price result */
|
|
110
|
+
export interface LMSRPriceResult {
|
|
111
|
+
yes_price: number;
|
|
112
|
+
no_price: number;
|
|
113
|
+
spread: number;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** Arbitrage detection result */
|
|
117
|
+
export interface ArbitrageResult {
|
|
118
|
+
has_arbitrage: boolean;
|
|
119
|
+
yes_price: number;
|
|
120
|
+
no_price: number;
|
|
121
|
+
total: number;
|
|
122
|
+
profit_per_share: number;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** Odds conversion result */
|
|
126
|
+
export interface OddsConversion {
|
|
127
|
+
probability: number;
|
|
128
|
+
decimal_odds: number;
|
|
129
|
+
american_odds: number;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** Value at Risk result */
|
|
133
|
+
export interface VaRResult {
|
|
134
|
+
var: number;
|
|
135
|
+
cvar: number;
|
|
136
|
+
confidence_level: number;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** Drawdown analysis result */
|
|
140
|
+
export interface DrawdownResult {
|
|
141
|
+
max_drawdown: number;
|
|
142
|
+
max_duration: number;
|
|
143
|
+
current_drawdown: number;
|
|
144
|
+
recovery_factor: number;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** Sharpe ratio result */
|
|
148
|
+
export interface SharpeResult {
|
|
149
|
+
sharpe_ratio: number;
|
|
150
|
+
annualized_sharpe: number;
|
|
151
|
+
risk_free_rate: number;
|
|
152
|
+
avg_return: number;
|
|
153
|
+
std_dev: number;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// ===== Terminal Input Types =====
|
|
157
|
+
|
|
158
|
+
/** Native key event from terminal */
|
|
159
|
+
export interface NativeKeyEvent {
|
|
160
|
+
/** The key code (character or special key name) */
|
|
161
|
+
code: string;
|
|
162
|
+
/** Whether this is a special key (arrow, function, etc.) */
|
|
163
|
+
is_special: boolean;
|
|
164
|
+
/** Ctrl modifier */
|
|
165
|
+
ctrl: boolean;
|
|
166
|
+
/** Alt/Meta modifier */
|
|
167
|
+
alt: boolean;
|
|
168
|
+
/** Shift modifier */
|
|
169
|
+
shift: boolean;
|
|
170
|
+
/** Event kind: "press", "release", "repeat" */
|
|
171
|
+
kind: "press" | "release" | "repeat";
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** Terminal handle for raw mode input */
|
|
175
|
+
export interface TerminalHandle {
|
|
176
|
+
/** Enter raw terminal mode */
|
|
177
|
+
enterRawMode(): void;
|
|
178
|
+
/** Exit raw terminal mode */
|
|
179
|
+
exitRawMode(): void;
|
|
180
|
+
/** Check if in raw mode (getter) */
|
|
181
|
+
readonly isRawMode: boolean;
|
|
182
|
+
/** Poll for a key event (non-blocking), returns null if no event */
|
|
183
|
+
pollEvent(timeoutMs?: number): NativeKeyEvent | null;
|
|
184
|
+
/** Read next key event (blocking, async) */
|
|
185
|
+
readEvent(): Promise<NativeKeyEvent>;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ===== Native TUI Types =====
|
|
189
|
+
|
|
190
|
+
/** Message for display in the native TUI */
|
|
191
|
+
export interface TuiMessage {
|
|
192
|
+
id: string;
|
|
193
|
+
role: "user" | "assistant" | "system";
|
|
194
|
+
content: string;
|
|
195
|
+
timestamp?: number;
|
|
196
|
+
subType?: string;
|
|
197
|
+
toolName?: string;
|
|
198
|
+
isError?: boolean;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/** TUI state for rendering */
|
|
202
|
+
export interface TuiState {
|
|
203
|
+
messages: TuiMessage[];
|
|
204
|
+
inputValue: string;
|
|
205
|
+
cursorPos: number;
|
|
206
|
+
isLoading: boolean;
|
|
207
|
+
spinnerFrame: number;
|
|
208
|
+
model: string;
|
|
209
|
+
tokensUsed: number;
|
|
210
|
+
permissionMode: string;
|
|
211
|
+
streamingText: string;
|
|
212
|
+
scrollOffset: number;
|
|
213
|
+
contextWarning?: string;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/** Result of handling input in native TUI */
|
|
217
|
+
export interface InputResult {
|
|
218
|
+
submitted: boolean;
|
|
219
|
+
text?: string;
|
|
220
|
+
exitRequested: boolean;
|
|
221
|
+
command?: string;
|
|
222
|
+
scrollUp: boolean;
|
|
223
|
+
scrollDown: boolean;
|
|
224
|
+
inputValue: string;
|
|
225
|
+
cursorPos: number;
|
|
226
|
+
historyNavigated: boolean;
|
|
227
|
+
historyDirection: number;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/** Native TUI handle from Rust */
|
|
231
|
+
export interface NativeTuiHandle {
|
|
232
|
+
init(): void;
|
|
233
|
+
cleanup(): void;
|
|
234
|
+
render(state: TuiState): void;
|
|
235
|
+
pollInput(state: TuiState, timeoutMs?: number): InputResult;
|
|
236
|
+
addToHistory(input: string): void;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export interface NativeModule {
|
|
240
|
+
/** Syntax highlight code with ANSI escape codes */
|
|
241
|
+
highlight_code: (code: string, language: string) => HighlightResult;
|
|
242
|
+
|
|
243
|
+
/** Highlight markdown with nested code block syntax highlighting */
|
|
244
|
+
highlight_markdown: (markdown: string) => HighlightResult;
|
|
245
|
+
|
|
246
|
+
/** Highlight a diff with ANSI colors */
|
|
247
|
+
highlight_diff: (oldText: string, newText: string, options?: DiffOptions) => HighlightDiffResult;
|
|
248
|
+
|
|
249
|
+
search_files: (
|
|
250
|
+
pattern: string,
|
|
251
|
+
path: string,
|
|
252
|
+
options: {
|
|
253
|
+
case_insensitive?: boolean;
|
|
254
|
+
hidden?: boolean;
|
|
255
|
+
glob?: string;
|
|
256
|
+
max_results?: number;
|
|
257
|
+
}
|
|
258
|
+
) => {
|
|
259
|
+
matches: Array<{
|
|
260
|
+
file_path: string;
|
|
261
|
+
line_number: number;
|
|
262
|
+
column: number;
|
|
263
|
+
line_content: string;
|
|
264
|
+
match_text: string;
|
|
265
|
+
}>;
|
|
266
|
+
total_count: number;
|
|
267
|
+
files_searched: number;
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
count_tokens: (text: string) => number;
|
|
271
|
+
|
|
272
|
+
calculate_diff: (
|
|
273
|
+
oldText: string,
|
|
274
|
+
newText: string
|
|
275
|
+
) => Array<{
|
|
276
|
+
oldStart: number;
|
|
277
|
+
oldLines: number;
|
|
278
|
+
newStart: number;
|
|
279
|
+
newLines: number;
|
|
280
|
+
content: string;
|
|
281
|
+
}>;
|
|
282
|
+
|
|
283
|
+
compact_content: (
|
|
284
|
+
content: string,
|
|
285
|
+
maxTokens: number,
|
|
286
|
+
strategy?: "truncate" | "summarize" | "extract"
|
|
287
|
+
) => string;
|
|
288
|
+
|
|
289
|
+
count_tool_use: (
|
|
290
|
+
messages: Array<{
|
|
291
|
+
role: string;
|
|
292
|
+
tool_use?: Array<{ name: string; input?: any }>;
|
|
293
|
+
tool_result?: Array<any>;
|
|
294
|
+
}>
|
|
295
|
+
) => Record<string, number>;
|
|
296
|
+
|
|
297
|
+
find_tool_pairs: (
|
|
298
|
+
messages: Array<{
|
|
299
|
+
role: string;
|
|
300
|
+
tool_use?: Array<{ name: string; input?: any }>;
|
|
301
|
+
tool_result?: Array<any>;
|
|
302
|
+
}>,
|
|
303
|
+
window_size: number
|
|
304
|
+
) => Record<string, Record<string, number>>;
|
|
305
|
+
|
|
306
|
+
find_common_patterns: (
|
|
307
|
+
messages: Array<{
|
|
308
|
+
role: string;
|
|
309
|
+
tool_use?: Array<{ name: string; input?: any }>;
|
|
310
|
+
tool_result?: Array<any>;
|
|
311
|
+
}>
|
|
312
|
+
) => Array<{
|
|
313
|
+
tools: [string, string];
|
|
314
|
+
count: number;
|
|
315
|
+
percentage: number;
|
|
316
|
+
}>;
|
|
317
|
+
|
|
318
|
+
// Multi-file editing
|
|
319
|
+
/** Validate multi-file edits without applying them */
|
|
320
|
+
validate_multi_edits: (edits: MultiEditEntry[]) => string[];
|
|
321
|
+
|
|
322
|
+
/** Preview what edits would be applied without making changes */
|
|
323
|
+
preview_multi_edits: (edits: MultiEditEntry[]) => MultiEditPreviewEntry[];
|
|
324
|
+
|
|
325
|
+
/** Apply multiple file edits atomically with rollback on failure */
|
|
326
|
+
apply_multi_edits: (edits: MultiEditEntry[]) => MultiEditResult;
|
|
327
|
+
|
|
328
|
+
// ===== Quant Functions =====
|
|
329
|
+
|
|
330
|
+
/** Get library version */
|
|
331
|
+
quant_version: () => string;
|
|
332
|
+
|
|
333
|
+
// OHLCV
|
|
334
|
+
quant_ohlcv_new: (timestamp: bigint, open: number, high: number, low: number, close: number, volume: number) => string;
|
|
335
|
+
|
|
336
|
+
// AMM (Automated Market Maker)
|
|
337
|
+
quant_amm_new: (poolYes: number, poolNo: number, fee: number) => string;
|
|
338
|
+
quant_amm_calculate_cost: (poolYes: number, poolNo: number, buyYes: boolean, shares: number) => string;
|
|
339
|
+
quant_amm_price_impact: (poolYes: number, poolNo: number, buyYes: boolean, shares: number) => string;
|
|
340
|
+
|
|
341
|
+
// LMSR (Logarithmic Market Scoring Rule)
|
|
342
|
+
quant_lmsr_price: (yesShares: number, noShares: number, b: number) => string;
|
|
343
|
+
quant_lmsr_cost: (yesShares: number, noShares: number, b: number, buyYes: boolean, shares: number) => string;
|
|
344
|
+
|
|
345
|
+
// Arbitrage
|
|
346
|
+
quant_detect_arbitrage: (yesPrice: number, noPrice: number) => string;
|
|
347
|
+
|
|
348
|
+
// Odds Conversion
|
|
349
|
+
quant_convert_odds: (value: number, fromType: number) => string;
|
|
350
|
+
|
|
351
|
+
// Statistics
|
|
352
|
+
quant_mean: (data: Float64Array) => number;
|
|
353
|
+
quant_std_dev: (data: Float64Array) => number;
|
|
354
|
+
quant_variance: (data: Float64Array) => number;
|
|
355
|
+
quant_correlation: (x: Float64Array, y: Float64Array) => number;
|
|
356
|
+
|
|
357
|
+
// ===== Cognitive Security - Action Module =====
|
|
358
|
+
|
|
359
|
+
/** Classify an operation into an action type */
|
|
360
|
+
classify_operation: (operation: string, domain: string, target?: string | null, reasoning?: string | null) => any;
|
|
361
|
+
|
|
362
|
+
/** Get all supported action types */
|
|
363
|
+
get_action_types: () => string[];
|
|
364
|
+
|
|
365
|
+
/** Get risk levels for all action types */
|
|
366
|
+
get_action_risk_levels: () => Array<{ actionType: string; riskLevel: number }>;
|
|
367
|
+
|
|
368
|
+
/** Create a deny-all policy */
|
|
369
|
+
create_deny_all_policy: () => any;
|
|
370
|
+
|
|
371
|
+
/** Create an observe-only policy */
|
|
372
|
+
create_observe_only_policy: () => any;
|
|
373
|
+
|
|
374
|
+
/** Create a transfer approval policy */
|
|
375
|
+
create_transfer_approval_policy: () => any;
|
|
376
|
+
|
|
377
|
+
// ===== Cognitive Security - Intent Module =====
|
|
378
|
+
|
|
379
|
+
/** Generate a new Ed25519 keypair for signing intents */
|
|
380
|
+
cs_generate_keypair: () => { privateKey: string; publicKey: string };
|
|
381
|
+
|
|
382
|
+
/** Sign an agent intent with a private key */
|
|
383
|
+
cs_sign_intent: (intent: any, privateKey: string) => any;
|
|
384
|
+
|
|
385
|
+
/** Verify an intent's signature */
|
|
386
|
+
cs_verify_intent: (intent: any) => any;
|
|
387
|
+
|
|
388
|
+
/** Hash an intent for comparison */
|
|
389
|
+
cs_hash_intent: (intent: any) => string;
|
|
390
|
+
|
|
391
|
+
/** Check if two intents are equivalent */
|
|
392
|
+
cs_intents_equivalent: (intent1: any, intent2: any) => boolean;
|
|
393
|
+
|
|
394
|
+
/** Score how well an action aligns with an intent */
|
|
395
|
+
cs_score_alignment: (action: any, intent: any) => any;
|
|
396
|
+
|
|
397
|
+
/** Batch score multiple actions against an intent */
|
|
398
|
+
cs_batch_score_alignment: (actions: any[], intent: any) => any[];
|
|
399
|
+
|
|
400
|
+
/** Check if any action in a sequence would violate intent */
|
|
401
|
+
cs_check_sequence_violations: (actions: any[], intent: any) => number[];
|
|
402
|
+
|
|
403
|
+
/** Load intent from a JSON file */
|
|
404
|
+
cs_load_intent: (path: string) => any;
|
|
405
|
+
|
|
406
|
+
/** Save intent to a JSON file */
|
|
407
|
+
cs_save_intent: (intent: any, path: string) => void;
|
|
408
|
+
|
|
409
|
+
/** Parse intent from JSON string */
|
|
410
|
+
cs_parse_intent: (json: string) => any;
|
|
411
|
+
|
|
412
|
+
/** Serialize intent to JSON string */
|
|
413
|
+
cs_serialize_intent: (intent: any) => string;
|
|
414
|
+
|
|
415
|
+
/** Validate intent structure */
|
|
416
|
+
cs_validate_intent: (intent: any) => any;
|
|
417
|
+
|
|
418
|
+
/** Create a default data collector intent */
|
|
419
|
+
cs_create_data_collector_intent: (name: string, description: string) => any;
|
|
420
|
+
|
|
421
|
+
/** Merge two intents (child overrides parent) */
|
|
422
|
+
cs_merge_intents: (base: any, override: any) => any;
|
|
423
|
+
|
|
424
|
+
/** Analyze behavior for signs of intent corruption */
|
|
425
|
+
cs_analyze_corruption: (snapshot: any, intent: any) => any;
|
|
426
|
+
|
|
427
|
+
/** Detect behavioral drift between two snapshots */
|
|
428
|
+
cs_detect_drift: (baseline: any, current: any) => any;
|
|
429
|
+
|
|
430
|
+
/** Create an empty behavior snapshot */
|
|
431
|
+
cs_create_empty_snapshot: () => any;
|
|
432
|
+
|
|
433
|
+
/** Update a snapshot with a new action result */
|
|
434
|
+
cs_update_snapshot: (snapshot: any, action: any, alignment: any) => any;
|
|
435
|
+
|
|
436
|
+
// ===== Cognitive Security - Flow Module =====
|
|
437
|
+
|
|
438
|
+
/** Classify data based on content and source */
|
|
439
|
+
classify_data: (content: string, source: string, tags: string[]) => any;
|
|
440
|
+
|
|
441
|
+
/** Check if content contains sensitive data */
|
|
442
|
+
contains_sensitive_data: (content: string) => boolean;
|
|
443
|
+
|
|
444
|
+
/** Redact sensitive content */
|
|
445
|
+
redact_sensitive: (content: string, replacement?: string | null) => string;
|
|
446
|
+
|
|
447
|
+
/** Get sensitivity levels */
|
|
448
|
+
get_sensitivity_levels: () => Array<{ name: string; value: number; description: string }>;
|
|
449
|
+
|
|
450
|
+
/** Get data categories */
|
|
451
|
+
get_data_categories: () => Array<{ name: string; description: string }>;
|
|
452
|
+
|
|
453
|
+
/** Create a flow policy engine */
|
|
454
|
+
create_flow_policy_engine: () => any;
|
|
455
|
+
|
|
456
|
+
/** Create an allow-all flow policy */
|
|
457
|
+
create_allow_all_flow_policy: () => any;
|
|
458
|
+
|
|
459
|
+
/** Create a deny-all flow policy */
|
|
460
|
+
create_deny_all_flow_policy: () => any;
|
|
461
|
+
|
|
462
|
+
/** Create a strict flow policy */
|
|
463
|
+
create_strict_flow_policy: () => any;
|
|
464
|
+
|
|
465
|
+
/** Create a flow tracker */
|
|
466
|
+
create_flow_tracker: () => any;
|
|
467
|
+
|
|
468
|
+
/** Create a leak prevention engine */
|
|
469
|
+
create_leak_prevention: () => any;
|
|
470
|
+
|
|
471
|
+
/** Check content for leaks */
|
|
472
|
+
check_for_leaks: (content: string, channel: string) => any;
|
|
473
|
+
|
|
474
|
+
/** Sanitize content */
|
|
475
|
+
sanitize_content: (content: string) => string;
|
|
476
|
+
|
|
477
|
+
/** Create a taint tracker */
|
|
478
|
+
create_taint_tracker: () => any;
|
|
479
|
+
|
|
480
|
+
// ===== Terminal Input =====
|
|
481
|
+
|
|
482
|
+
/** Create a terminal handle for raw mode input */
|
|
483
|
+
create_terminal: () => TerminalHandle;
|
|
484
|
+
|
|
485
|
+
// ===== Native TUI =====
|
|
486
|
+
|
|
487
|
+
/** Create a native TUI handle */
|
|
488
|
+
create_tui: () => NativeTuiHandle;
|
|
489
|
+
|
|
490
|
+
/** Check if native TUI is available */
|
|
491
|
+
is_native_tui_available: () => boolean;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
let nativeModule: NativeModule | null = null;
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Load the native module
|
|
498
|
+
*/
|
|
499
|
+
export function loadNative(): NativeModule {
|
|
500
|
+
if (nativeModule) {
|
|
501
|
+
return nativeModule;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// Try multiple possible locations for the native module
|
|
505
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
506
|
+
const basePaths = [
|
|
507
|
+
join(__dirname, "..", "native"), // dist/../native (library entry)
|
|
508
|
+
join(__dirname, "..", "..", "native"), // dist/foo/../native
|
|
509
|
+
join(__dirname, "..", "..", "..", "native"), // dist/foo/bar/../native
|
|
510
|
+
join(__dirname, "..", "..", "..", "..", "native"), // dist/interfaces/ui/../native
|
|
511
|
+
join(__dirname, "..", "..", "..", "..", "..", "native"), // dist/interfaces/ui/terminal/../native
|
|
512
|
+
join(__dirname, "..", "..", "..", "..", "..", "..", "native"), // CLI entry: dist/interfaces/ui/terminal/cli/../native
|
|
513
|
+
join(__dirname, "native"), // native/ (if running from project root)
|
|
514
|
+
];
|
|
515
|
+
|
|
516
|
+
// Try .node files first (NAPI modules)
|
|
517
|
+
const nodeFiles = ["index.darwin-arm64.node", "index.darwin-x64.node", "index.node"];
|
|
518
|
+
|
|
519
|
+
for (const basePath of basePaths) {
|
|
520
|
+
for (const file of nodeFiles) {
|
|
521
|
+
const nativePath = join(basePath, file);
|
|
522
|
+
try {
|
|
523
|
+
// Try to load NAPI module directly
|
|
524
|
+
const native = require(nativePath);
|
|
525
|
+
if (native && (native.highlightCode || native.highlight_code)) {
|
|
526
|
+
// Map camelCase to snake_case if needed
|
|
527
|
+
nativeModule = {
|
|
528
|
+
highlight_code: native.highlightCode || native.highlight_code,
|
|
529
|
+
highlight_markdown: native.highlightMarkdown || native.highlight_markdown,
|
|
530
|
+
highlight_diff: native.highlightDiff || native.highlight_diff,
|
|
531
|
+
search_files: native.searchFiles || native.search_files,
|
|
532
|
+
count_tokens: native.countTokens || native.count_tokens,
|
|
533
|
+
calculate_diff: native.calculateDiff || native.calculate_diff,
|
|
534
|
+
compact_content: native.compactContent || native.compact_content,
|
|
535
|
+
count_tool_use: native.countToolUse || native.count_tool_use,
|
|
536
|
+
find_tool_pairs: native.findToolPairs || native.find_tool_pairs,
|
|
537
|
+
find_common_patterns: native.findCommonPatterns || native.find_common_patterns,
|
|
538
|
+
validate_multi_edits: native.validateMultiEdits || native.validate_multi_edits,
|
|
539
|
+
preview_multi_edits: native.previewMultiEdits || native.preview_multi_edits,
|
|
540
|
+
apply_multi_edits: native.applyMultiEdits || native.apply_multi_edits,
|
|
541
|
+
|
|
542
|
+
// Cognitive Security - Action Module (NAPI exports camelCase)
|
|
543
|
+
classify_operation: native.classifyOperation,
|
|
544
|
+
get_action_types: native.getActionTypes,
|
|
545
|
+
get_action_risk_levels: native.getActionRiskLevels,
|
|
546
|
+
create_deny_all_policy: native.createDenyAllPolicy,
|
|
547
|
+
create_observe_only_policy: native.createObserveOnlyPolicy,
|
|
548
|
+
create_transfer_approval_policy: native.createTransferApprovalPolicy,
|
|
549
|
+
|
|
550
|
+
// Cognitive Security - Intent Module (NAPI exports camelCase)
|
|
551
|
+
cs_generate_keypair: native.generateIntentKeypair,
|
|
552
|
+
cs_sign_intent: native.signIntent,
|
|
553
|
+
cs_verify_intent: native.verifyIntentSignature,
|
|
554
|
+
cs_hash_intent: native.hashIntent,
|
|
555
|
+
cs_intents_equivalent: native.intentsEquivalent,
|
|
556
|
+
cs_score_alignment: native.scoreAlignment,
|
|
557
|
+
cs_batch_score_alignment: native.batchScoreAlignment,
|
|
558
|
+
cs_check_sequence_violations: native.checkSequenceViolations,
|
|
559
|
+
cs_load_intent: native.loadIntentFromFile,
|
|
560
|
+
cs_save_intent: native.saveIntentToFile,
|
|
561
|
+
cs_parse_intent: native.parseIntent,
|
|
562
|
+
cs_serialize_intent: native.serializeIntent,
|
|
563
|
+
cs_validate_intent: native.validateIntentStructure,
|
|
564
|
+
cs_create_data_collector_intent: native.createDataCollectorIntent,
|
|
565
|
+
cs_merge_intents: native.mergeIntents,
|
|
566
|
+
cs_analyze_corruption: native.analyzeCorruption,
|
|
567
|
+
cs_detect_drift: native.detectBehavioralDrift,
|
|
568
|
+
cs_create_empty_snapshot: native.createEmptySnapshot,
|
|
569
|
+
cs_update_snapshot: native.updateSnapshot,
|
|
570
|
+
|
|
571
|
+
// Cognitive Security - Flow Module (NAPI exports camelCase)
|
|
572
|
+
classify_data: native.classifyData,
|
|
573
|
+
contains_sensitive_data: native.containsSensitiveData,
|
|
574
|
+
redact_sensitive: native.redactSensitive,
|
|
575
|
+
get_sensitivity_levels: native.getSensitivityLevels,
|
|
576
|
+
get_data_categories: native.getDataCategories,
|
|
577
|
+
create_flow_policy_engine: native.createFlowPolicyEngine,
|
|
578
|
+
create_allow_all_flow_policy: native.createAllowAllFlowPolicy,
|
|
579
|
+
create_deny_all_flow_policy: native.createDenyAllFlowPolicy,
|
|
580
|
+
create_strict_flow_policy: native.createStrictFlowPolicy,
|
|
581
|
+
create_flow_tracker: native.createFlowTracker,
|
|
582
|
+
create_leak_prevention: native.createLeakPrevention,
|
|
583
|
+
check_for_leaks: native.checkForLeaks,
|
|
584
|
+
sanitize_content: native.sanitizeContent,
|
|
585
|
+
create_taint_tracker: native.createTaintTracker,
|
|
586
|
+
|
|
587
|
+
// Quant Functions
|
|
588
|
+
quant_version: native.quantVersion || native.quant_version,
|
|
589
|
+
quant_ohlcv_new: native.quantOhlcvNew || native.quant_ohlcv_new,
|
|
590
|
+
quant_amm_new: native.quantAmmNew || native.quant_amm_new,
|
|
591
|
+
quant_amm_calculate_cost: native.quantAmmCalculateCost || native.quant_amm_calculate_cost,
|
|
592
|
+
quant_amm_price_impact: native.quantAmmPriceImpact || native.quant_amm_price_impact,
|
|
593
|
+
quant_lmsr_price: native.quantLmsrPrice || native.quant_lmsr_price,
|
|
594
|
+
quant_lmsr_cost: native.quantLmsrCost || native.quant_lmsr_cost,
|
|
595
|
+
quant_detect_arbitrage: native.quantDetectArbitrage || native.quant_detect_arbitrage,
|
|
596
|
+
quant_convert_odds: native.quantConvertOdds || native.quant_convert_odds,
|
|
597
|
+
quant_mean: native.quantMean || native.quant_mean,
|
|
598
|
+
quant_std_dev: native.quantStdDev || native.quant_std_dev,
|
|
599
|
+
quant_variance: native.quantVariance || native.quant_variance,
|
|
600
|
+
quant_correlation: native.quantCorrelation || native.quant_correlation,
|
|
601
|
+
|
|
602
|
+
// Terminal Input
|
|
603
|
+
create_terminal: native.createTerminal || native.create_terminal,
|
|
604
|
+
|
|
605
|
+
// Native TUI
|
|
606
|
+
create_tui: native.createTui || native.create_tui,
|
|
607
|
+
is_native_tui_available: () => typeof (native.createTui || native.create_tui) === 'function',
|
|
608
|
+
};
|
|
609
|
+
return nativeModule;
|
|
610
|
+
}
|
|
611
|
+
} catch {
|
|
612
|
+
// Try next path
|
|
613
|
+
continue;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
// Try FFI with dylib
|
|
619
|
+
const dylibPaths = basePaths.map(p => join(p, `claude_code_native.${suffix}`));
|
|
620
|
+
|
|
621
|
+
for (const nativePath of dylibPaths) {
|
|
622
|
+
try {
|
|
623
|
+
const lib = dlopen(nativePath, {
|
|
624
|
+
highlight_code: {
|
|
625
|
+
args: ["cstring", "cstring"],
|
|
626
|
+
returns: "pointer",
|
|
627
|
+
},
|
|
628
|
+
highlight_markdown: {
|
|
629
|
+
args: ["cstring"],
|
|
630
|
+
returns: "pointer",
|
|
631
|
+
},
|
|
632
|
+
highlight_diff: {
|
|
633
|
+
args: ["cstring", "cstring", "pointer"],
|
|
634
|
+
returns: "pointer",
|
|
635
|
+
},
|
|
636
|
+
search_files: {
|
|
637
|
+
args: ["cstring", "cstring", "pointer"],
|
|
638
|
+
returns: "pointer",
|
|
639
|
+
},
|
|
640
|
+
count_tokens: {
|
|
641
|
+
args: ["cstring"],
|
|
642
|
+
returns: "u32",
|
|
643
|
+
},
|
|
644
|
+
calculate_diff: {
|
|
645
|
+
args: ["cstring", "cstring"],
|
|
646
|
+
returns: "pointer",
|
|
647
|
+
},
|
|
648
|
+
compact_content: {
|
|
649
|
+
args: ["cstring", "u32", "cstring"],
|
|
650
|
+
returns: "pointer",
|
|
651
|
+
},
|
|
652
|
+
},
|
|
653
|
+
);
|
|
654
|
+
|
|
655
|
+
nativeModule = lib.symbols as unknown as NativeModule;
|
|
656
|
+
return nativeModule;
|
|
657
|
+
} catch {
|
|
658
|
+
continue;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
// No native module found, use fallback
|
|
663
|
+
console.warn("Native module not available, using JS fallback");
|
|
664
|
+
return getFallbackModule();
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
/**
|
|
668
|
+
* Check if native module is available
|
|
669
|
+
*/
|
|
670
|
+
export function isNativeAvailable(): boolean {
|
|
671
|
+
try {
|
|
672
|
+
loadNative();
|
|
673
|
+
return nativeModule !== null;
|
|
674
|
+
} catch {
|
|
675
|
+
return false;
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
/**
|
|
680
|
+
* Fallback implementations in pure JavaScript
|
|
681
|
+
*/
|
|
682
|
+
function getFallbackModule(): NativeModule {
|
|
683
|
+
return {
|
|
684
|
+
highlight_code: (code: string, language: string): HighlightResult => {
|
|
685
|
+
// ANSI color codes
|
|
686
|
+
const colors = {
|
|
687
|
+
reset: "\x1b[0m",
|
|
688
|
+
keyword: "\x1b[38;2;180;142;173m", // purple
|
|
689
|
+
string: "\x1b[38;2;163;190;140m", // green
|
|
690
|
+
number: "\x1b[38;2;208;135;112m", // orange
|
|
691
|
+
type: "\x1b[38;2;191;97;106m", // red
|
|
692
|
+
function: "\x1b[38;2;143;161;179m", // blue
|
|
693
|
+
comment: "\x1b[38;2;108;153;139m", // gray-green
|
|
694
|
+
default: "\x1b[38;2;192;197;206m", // gray
|
|
695
|
+
special: "\x1b[38;2;150;180;210m", // light blue
|
|
696
|
+
arrow: "\x1b[38;2;200;160;120m", // gold/tan
|
|
697
|
+
};
|
|
698
|
+
|
|
699
|
+
// Mermaid-specific highlighting
|
|
700
|
+
if (language.toLowerCase() === "mermaid" || language.toLowerCase() === "mmd") {
|
|
701
|
+
const MERMAID_KEYWORDS = new Set([
|
|
702
|
+
// Diagram types
|
|
703
|
+
"graph", "flowchart", "sequenceDiagram", "classDiagram", "stateDiagram",
|
|
704
|
+
"erDiagram", "journey", "gantt", "pie", "gitGraph", "mindmap", "timeline",
|
|
705
|
+
"quadrantChart", "requirementDiagram", "C4Context", "C4Container",
|
|
706
|
+
"C4Component", "C4Dynamic", "C4Deployment",
|
|
707
|
+
// Directions
|
|
708
|
+
"TB", "TD", "BT", "RL", "LR", "left", "right", "top", "bottom",
|
|
709
|
+
// Subgraphs/participants
|
|
710
|
+
"subgraph", "end", "participant", "actor", "as",
|
|
711
|
+
// Flowchart
|
|
712
|
+
"node", "click", "link", "href", "callback",
|
|
713
|
+
// Sequence
|
|
714
|
+
"Note", "over", "loop", "alt", "else", "opt", "par", "rect", "autonumber",
|
|
715
|
+
"activate", "deactivate",
|
|
716
|
+
// Class
|
|
717
|
+
"class", "namespace", "interface", "annotation", "service", "enum",
|
|
718
|
+
// State
|
|
719
|
+
"state", "note", "fork", "join", "choice",
|
|
720
|
+
// ER
|
|
721
|
+
"entity",
|
|
722
|
+
// Gantt
|
|
723
|
+
"dateFormat", "title", "section", "excludes", "includes", "todayMarker",
|
|
724
|
+
// Common
|
|
725
|
+
"title", "accTitle", "accDescr",
|
|
726
|
+
]);
|
|
727
|
+
|
|
728
|
+
const MERMAID_ARROWS = new Set([
|
|
729
|
+
"-->", "---", "->", "->>", "-.", "-.-", "==>", "==", "--x", "--o",
|
|
730
|
+
"<--", "<-", "<<-", "<-->", "<->", "o--o", "x--x", "-x", "-o",
|
|
731
|
+
]);
|
|
732
|
+
|
|
733
|
+
const MERMAID_SHAPES = [
|
|
734
|
+
["[", "]"], // rect
|
|
735
|
+
["(", ")"], // rounded
|
|
736
|
+
["([", "])"], // stadium
|
|
737
|
+
["[[", "]]"], // subroutine
|
|
738
|
+
["[((", ")]"], // cylinder
|
|
739
|
+
[">", "]"], // asymmetric
|
|
740
|
+
["{", "}"], // rhombus
|
|
741
|
+
["{{", "}}"], // hexagon
|
|
742
|
+
["[/", "/]"], // parallelogram
|
|
743
|
+
["[\\", "\\]"], // parallelogram alt
|
|
744
|
+
["[(", ")]"], // circle
|
|
745
|
+
["(((", ")))"], // double circle
|
|
746
|
+
];
|
|
747
|
+
|
|
748
|
+
const lines = code.split("\n");
|
|
749
|
+
const highlighted = lines.map(line => {
|
|
750
|
+
let result = line;
|
|
751
|
+
|
|
752
|
+
// Comments (%%)
|
|
753
|
+
if (line.trim().startsWith("%%")) {
|
|
754
|
+
return `${colors.comment}${line}${colors.reset}`;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
// Arrows and connections (handle first to preserve them)
|
|
758
|
+
for (const arrow of MERMAID_ARROWS) {
|
|
759
|
+
const escaped = arrow.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
760
|
+
result = result.replace(new RegExp(escaped, 'g'), `${colors.arrow}${arrow}${colors.default}`);
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
// Strings (quoted)
|
|
764
|
+
result = result.replace(/"([^"\\]|\\.)*"/g, match => {
|
|
765
|
+
return `${colors.string}${match}${colors.default}`;
|
|
766
|
+
});
|
|
767
|
+
|
|
768
|
+
// Numbers
|
|
769
|
+
result = result.replace(/\b(\d+\.?\d*)\b/g, `${colors.number}$1${colors.default}`);
|
|
770
|
+
|
|
771
|
+
// Keywords
|
|
772
|
+
result = result.replace(/\b([A-Za-z_][A-Za-z0-9_]*)\b/g, (match) => {
|
|
773
|
+
if (MERMAID_KEYWORDS.has(match)) {
|
|
774
|
+
return `${colors.keyword}${match}${colors.default}`;
|
|
775
|
+
}
|
|
776
|
+
return match;
|
|
777
|
+
});
|
|
778
|
+
|
|
779
|
+
// Special characters for shapes
|
|
780
|
+
for (const [open, close] of MERMAID_SHAPES) {
|
|
781
|
+
if (!open || !close) continue;
|
|
782
|
+
const openEsc = open.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
783
|
+
const closeEsc = close.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
784
|
+
result = result.replace(new RegExp(`${openEsc}([^${closeEsc}]+)${closeEsc}`, 'g'), (_, content) => {
|
|
785
|
+
return `${colors.special}${open}${content}${close}${colors.default}`;
|
|
786
|
+
});
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
// Arrow labels
|
|
790
|
+
result = result.replace(/\|([^|]+)\|/g, (_, content) => {
|
|
791
|
+
return `${colors.special}|${content}|${colors.default}`;
|
|
792
|
+
});
|
|
793
|
+
|
|
794
|
+
return result;
|
|
795
|
+
}).join("\n");
|
|
796
|
+
|
|
797
|
+
return {
|
|
798
|
+
html: highlighted + colors.reset,
|
|
799
|
+
theme: "mermaid",
|
|
800
|
+
};
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
// Standard code highlighting
|
|
804
|
+
const KEYWORDS = new Set([
|
|
805
|
+
"function", "const", "let", "var", "return", "if", "else", "for", "while",
|
|
806
|
+
"class", "interface", "type", "import", "export", "from", "async", "await",
|
|
807
|
+
"try", "catch", "throw", "new", "this", "extends", "implements", "static",
|
|
808
|
+
"public", "private", "protected", "readonly", "abstract", "enum", "namespace",
|
|
809
|
+
]);
|
|
810
|
+
|
|
811
|
+
const TYPES = new Set([
|
|
812
|
+
"string", "number", "boolean", "void", "null", "undefined", "any", "never",
|
|
813
|
+
"object", "symbol", "bigint", "true", "false",
|
|
814
|
+
]);
|
|
815
|
+
|
|
816
|
+
// Simple tokenization
|
|
817
|
+
const lines = code.split("\n");
|
|
818
|
+
const highlighted = lines.map(line => {
|
|
819
|
+
// Comments
|
|
820
|
+
if (line.trim().startsWith("//") || line.trim().startsWith("#")) {
|
|
821
|
+
return `${colors.comment}${line}${colors.reset}`;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
// Replace strings
|
|
825
|
+
let result = line.replace(/(["'`])(?:(?!\1)[^\\]|\\.)*?\1/g, match => {
|
|
826
|
+
return `${colors.string}${match}${colors.default}`;
|
|
827
|
+
});
|
|
828
|
+
|
|
829
|
+
// Replace numbers
|
|
830
|
+
result = result.replace(/\b(\d+\.?\d*)\b/g, `${colors.number}$1${colors.default}`);
|
|
831
|
+
|
|
832
|
+
// Replace keywords
|
|
833
|
+
result = result.replace(/\b([a-z]+)\b/gi, (match) => {
|
|
834
|
+
if (KEYWORDS.has(match)) {
|
|
835
|
+
return `${colors.keyword}${match}${colors.default}`;
|
|
836
|
+
}
|
|
837
|
+
if (TYPES.has(match)) {
|
|
838
|
+
return `${colors.type}${match}${colors.default}`;
|
|
839
|
+
}
|
|
840
|
+
return match;
|
|
841
|
+
});
|
|
842
|
+
|
|
843
|
+
// Function names (before parentheses)
|
|
844
|
+
result = result.replace(/\b([a-zA-Z_][a-zA-Z0-9_]*)\s*\(/g, (_, name) => {
|
|
845
|
+
return `${colors.function}${name}${colors.default}(`;
|
|
846
|
+
});
|
|
847
|
+
|
|
848
|
+
return result;
|
|
849
|
+
}).join("\n");
|
|
850
|
+
|
|
851
|
+
return {
|
|
852
|
+
html: highlighted + colors.reset,
|
|
853
|
+
theme: "fallback",
|
|
854
|
+
};
|
|
855
|
+
},
|
|
856
|
+
|
|
857
|
+
highlight_markdown: (markdown: string): HighlightResult => {
|
|
858
|
+
// Simple markdown highlighting - just return as-is with reset
|
|
859
|
+
// Full nested code block highlighting requires native module
|
|
860
|
+
return {
|
|
861
|
+
html: markdown + "\x1b[0m",
|
|
862
|
+
theme: "fallback",
|
|
863
|
+
};
|
|
864
|
+
},
|
|
865
|
+
|
|
866
|
+
highlight_diff: (oldText: string, newText: string, options?: DiffOptions): HighlightDiffResult => {
|
|
867
|
+
// Simple line-based diff with ANSI colors
|
|
868
|
+
const GREEN = "\x1b[38;2;163;190;140m";
|
|
869
|
+
const RED = "\x1b[38;2;191;97;106m";
|
|
870
|
+
const DIM = "\x1b[38;2;108;153;139m";
|
|
871
|
+
const CYAN = "\x1b[38;2;143;161;179m";
|
|
872
|
+
const RESET = "\x1b[0m";
|
|
873
|
+
|
|
874
|
+
const oldLines = oldText.split("\n");
|
|
875
|
+
const newLines = newText.split("\n");
|
|
876
|
+
|
|
877
|
+
let output = "";
|
|
878
|
+
let additions = 0;
|
|
879
|
+
let deletions = 0;
|
|
880
|
+
let hunks = 0;
|
|
881
|
+
|
|
882
|
+
// File header
|
|
883
|
+
if (options?.file_path) {
|
|
884
|
+
output += `${CYAN}${options.file_path}${RESET}\n`;
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
// Simple LCS-based diff
|
|
888
|
+
const lcs: string[] = [];
|
|
889
|
+
const dp: number[][] = Array.from({ length: oldLines.length + 1 }, () =>
|
|
890
|
+
Array.from({ length: newLines.length + 1 }, () => 0)
|
|
891
|
+
);
|
|
892
|
+
|
|
893
|
+
for (let i = 0; i <= oldLines.length; i++) {
|
|
894
|
+
for (let j = 0; j <= newLines.length; j++) {
|
|
895
|
+
if (i === 0 || j === 0) {
|
|
896
|
+
dp[i]![j] = 0;
|
|
897
|
+
} else if (oldLines[i - 1] === newLines[j - 1]) {
|
|
898
|
+
dp[i]![j] = dp[i - 1]![j - 1]! + 1;
|
|
899
|
+
} else {
|
|
900
|
+
dp[i]![j] = Math.max(dp[i - 1]![j]!, dp[i]![j - 1]!);
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
// Backtrack for LCS
|
|
906
|
+
let i = oldLines.length;
|
|
907
|
+
let j = newLines.length;
|
|
908
|
+
const lcsSet = new Set<string>();
|
|
909
|
+
while (i > 0 && j > 0) {
|
|
910
|
+
if (oldLines[i - 1] === newLines[j - 1]) {
|
|
911
|
+
lcsSet.add(`${i - 1}:${j - 1}`);
|
|
912
|
+
lcs.unshift(oldLines[i - 1]!);
|
|
913
|
+
i--;
|
|
914
|
+
j--;
|
|
915
|
+
} else if (dp[i - 1]![j]! > dp[i]![j - 1]!) {
|
|
916
|
+
i--;
|
|
917
|
+
} else {
|
|
918
|
+
j--;
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
// Build diff output
|
|
923
|
+
let oldIdx = 0;
|
|
924
|
+
let newIdx = 0;
|
|
925
|
+
let lcsIdx = 0;
|
|
926
|
+
|
|
927
|
+
while (oldIdx < oldLines.length || newIdx < newLines.length) {
|
|
928
|
+
// Skip matching lines
|
|
929
|
+
while (
|
|
930
|
+
lcsIdx < lcs.length &&
|
|
931
|
+
oldIdx < oldLines.length &&
|
|
932
|
+
newIdx < newLines.length &&
|
|
933
|
+
oldLines[oldIdx] === lcs[lcsIdx] &&
|
|
934
|
+
newLines[newIdx] === lcs[lcsIdx]
|
|
935
|
+
) {
|
|
936
|
+
oldIdx++;
|
|
937
|
+
newIdx++;
|
|
938
|
+
lcsIdx++;
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
const oldStart = oldIdx + 1;
|
|
942
|
+
const newStart = newIdx + 1;
|
|
943
|
+
let oldCount = 0;
|
|
944
|
+
let newCount = 0;
|
|
945
|
+
const hunkLines: string[] = [];
|
|
946
|
+
|
|
947
|
+
// Collect removed lines
|
|
948
|
+
while (
|
|
949
|
+
oldIdx < oldLines.length &&
|
|
950
|
+
(lcsIdx >= lcs.length || oldLines[oldIdx] !== lcs[lcsIdx])
|
|
951
|
+
) {
|
|
952
|
+
hunkLines.push(`${RED}-${oldLines[oldIdx]}${RESET}`);
|
|
953
|
+
oldIdx++;
|
|
954
|
+
oldCount++;
|
|
955
|
+
deletions++;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
// Collect added lines
|
|
959
|
+
while (
|
|
960
|
+
newIdx < newLines.length &&
|
|
961
|
+
(lcsIdx >= lcs.length || newLines[newIdx] !== lcs[lcsIdx])
|
|
962
|
+
) {
|
|
963
|
+
hunkLines.push(`${GREEN}+${newLines[newIdx]}${RESET}`);
|
|
964
|
+
newIdx++;
|
|
965
|
+
newCount++;
|
|
966
|
+
additions++;
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
if (oldCount > 0 || newCount > 0) {
|
|
970
|
+
hunks++;
|
|
971
|
+
output += `${DIM}@@ -${oldStart},${oldCount} +${newStart},${newCount} @@${RESET}\n`;
|
|
972
|
+
output += hunkLines.join("\n") + "\n";
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
return { output, additions, deletions, hunks };
|
|
977
|
+
},
|
|
978
|
+
|
|
979
|
+
search_files: (pattern, path, options) => {
|
|
980
|
+
// Simple grep fallback
|
|
981
|
+
return {
|
|
982
|
+
matches: [],
|
|
983
|
+
total_count: 0,
|
|
984
|
+
files_searched: 0,
|
|
985
|
+
};
|
|
986
|
+
},
|
|
987
|
+
|
|
988
|
+
count_tokens: (text) => {
|
|
989
|
+
// Approximate token count: ~4 chars per token
|
|
990
|
+
return Math.ceil(text.length / 4);
|
|
991
|
+
},
|
|
992
|
+
|
|
993
|
+
calculate_diff: (oldText, newText) => {
|
|
994
|
+
// Simple line-based diff
|
|
995
|
+
const oldLines = oldText.split("\n");
|
|
996
|
+
const newLines = newText.split("\n");
|
|
997
|
+
const hunks: Array<{
|
|
998
|
+
oldStart: number;
|
|
999
|
+
oldLines: number;
|
|
1000
|
+
newStart: number;
|
|
1001
|
+
newLines: number;
|
|
1002
|
+
content: string;
|
|
1003
|
+
}> = [];
|
|
1004
|
+
|
|
1005
|
+
// Very simple diff - just show all changes as one hunk
|
|
1006
|
+
if (oldText !== newText) {
|
|
1007
|
+
hunks.push({
|
|
1008
|
+
oldStart: 1,
|
|
1009
|
+
oldLines: oldLines.length,
|
|
1010
|
+
newStart: 1,
|
|
1011
|
+
newLines: newLines.length,
|
|
1012
|
+
content: `- ${oldLines.join("\n- ")}\n+ ${newLines.join("\n+ ")}`,
|
|
1013
|
+
});
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
return hunks;
|
|
1017
|
+
},
|
|
1018
|
+
|
|
1019
|
+
compact_content: (content, maxTokens, strategy = "truncate") => {
|
|
1020
|
+
const charsPerToken = 4;
|
|
1021
|
+
const maxChars = maxTokens * charsPerToken;
|
|
1022
|
+
|
|
1023
|
+
if (content.length <= maxChars) {
|
|
1024
|
+
return content;
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
switch (strategy) {
|
|
1028
|
+
case "truncate":
|
|
1029
|
+
return (
|
|
1030
|
+
content.slice(0, maxChars / 2) +
|
|
1031
|
+
"\n\n... [truncated] ...\n\n" +
|
|
1032
|
+
content.slice(-maxChars / 2)
|
|
1033
|
+
);
|
|
1034
|
+
case "summarize":
|
|
1035
|
+
// Return first and last sections
|
|
1036
|
+
const quarter = Math.floor(maxChars / 4);
|
|
1037
|
+
return (
|
|
1038
|
+
"=== BEGINNING ===\n" +
|
|
1039
|
+
content.slice(0, quarter) +
|
|
1040
|
+
"\n\n=== END ===\n" +
|
|
1041
|
+
content.slice(-quarter)
|
|
1042
|
+
);
|
|
1043
|
+
case "extract":
|
|
1044
|
+
// Return important lines only
|
|
1045
|
+
const lines = content.split("\n");
|
|
1046
|
+
const important = lines.filter(
|
|
1047
|
+
(line) =>
|
|
1048
|
+
line.trim().startsWith("#") ||
|
|
1049
|
+
line.trim().startsWith("function") ||
|
|
1050
|
+
line.trim().startsWith("const") ||
|
|
1051
|
+
line.trim().startsWith("class") ||
|
|
1052
|
+
line.trim().startsWith("export") ||
|
|
1053
|
+
line.trim().startsWith("import")
|
|
1054
|
+
);
|
|
1055
|
+
return important.slice(0, maxChars / 50).join("\n");
|
|
1056
|
+
default:
|
|
1057
|
+
return content.slice(0, maxChars);
|
|
1058
|
+
}
|
|
1059
|
+
},
|
|
1060
|
+
|
|
1061
|
+
// Multi-file editing fallback implementation
|
|
1062
|
+
validate_multi_edits: (edits: MultiEditEntry[]): string[] => {
|
|
1063
|
+
const errors: string[] = [];
|
|
1064
|
+
const fileContents = new Map<string, string>();
|
|
1065
|
+
const fs = require('fs');
|
|
1066
|
+
|
|
1067
|
+
for (const edit of edits) {
|
|
1068
|
+
// Check file exists
|
|
1069
|
+
try {
|
|
1070
|
+
if (!fs.existsSync(edit.filePath)) {
|
|
1071
|
+
errors.push(`File not found: ${edit.filePath}`);
|
|
1072
|
+
continue;
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
// Load file content if not already loaded
|
|
1076
|
+
if (!fileContents.has(edit.filePath)) {
|
|
1077
|
+
const content = fs.readFileSync(edit.filePath, 'utf-8');
|
|
1078
|
+
fileContents.set(edit.filePath, content);
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
const content = fileContents.get(edit.filePath)!;
|
|
1082
|
+
|
|
1083
|
+
// Check oldString exists
|
|
1084
|
+
if (!content.includes(edit.oldString)) {
|
|
1085
|
+
errors.push(`String not found in ${edit.filePath}: "${truncateString(edit.oldString, 50)}"`);
|
|
1086
|
+
continue;
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
// Check uniqueness if not replaceAll
|
|
1090
|
+
if (!edit.replaceAll) {
|
|
1091
|
+
const count = (content.match(new RegExp(escapeRegex(edit.oldString), "g")) || []).length;
|
|
1092
|
+
if (count > 1) {
|
|
1093
|
+
errors.push(`String appears ${count} times in ${edit.filePath}. Use replaceAll or provide more context.`);
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
} catch (err) {
|
|
1097
|
+
errors.push(`Error reading ${edit.filePath}: ${err}`);
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
return errors;
|
|
1102
|
+
},
|
|
1103
|
+
|
|
1104
|
+
preview_multi_edits: (edits: MultiEditEntry[]): MultiEditPreviewEntry[] => {
|
|
1105
|
+
const results: MultiEditPreviewEntry[] = [];
|
|
1106
|
+
const fileReplacements = new Map<string, number>();
|
|
1107
|
+
const fs = require('fs');
|
|
1108
|
+
|
|
1109
|
+
for (const edit of edits) {
|
|
1110
|
+
try {
|
|
1111
|
+
if (!fs.existsSync(edit.filePath)) continue;
|
|
1112
|
+
|
|
1113
|
+
const content = fs.readFileSync(edit.filePath, 'utf-8');
|
|
1114
|
+
const count = edit.replaceAll
|
|
1115
|
+
? (content.match(new RegExp(escapeRegex(edit.oldString), "g")) || []).length
|
|
1116
|
+
: 1;
|
|
1117
|
+
|
|
1118
|
+
fileReplacements.set(
|
|
1119
|
+
edit.filePath,
|
|
1120
|
+
(fileReplacements.get(edit.filePath) || 0) + count
|
|
1121
|
+
);
|
|
1122
|
+
} catch {
|
|
1123
|
+
// Skip files that can't be read
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
for (const [filePath, replacementCount] of fileReplacements) {
|
|
1128
|
+
results.push({ filePath, replacementCount });
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
return results;
|
|
1132
|
+
},
|
|
1133
|
+
|
|
1134
|
+
apply_multi_edits: (edits: MultiEditEntry[]): MultiEditResult => {
|
|
1135
|
+
// First validate all edits
|
|
1136
|
+
const errors = getFallbackModule().validate_multi_edits(edits);
|
|
1137
|
+
if (errors.length > 0) {
|
|
1138
|
+
return {
|
|
1139
|
+
success: false,
|
|
1140
|
+
filesModified: [],
|
|
1141
|
+
totalReplacements: 0,
|
|
1142
|
+
error: errors.join("\n"),
|
|
1143
|
+
rolledBack: false,
|
|
1144
|
+
};
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
// Create backups
|
|
1148
|
+
const backups = new Map<string, string>();
|
|
1149
|
+
const uniqueFiles = new Set(edits.map(e => e.filePath));
|
|
1150
|
+
const fs = require('fs');
|
|
1151
|
+
|
|
1152
|
+
for (const filePath of uniqueFiles) {
|
|
1153
|
+
try {
|
|
1154
|
+
backups.set(filePath, fs.readFileSync(filePath, 'utf-8'));
|
|
1155
|
+
} catch (err) {
|
|
1156
|
+
return {
|
|
1157
|
+
success: false,
|
|
1158
|
+
filesModified: [],
|
|
1159
|
+
totalReplacements: 0,
|
|
1160
|
+
error: `Failed to backup ${filePath}: ${err}`,
|
|
1161
|
+
rolledBack: false,
|
|
1162
|
+
};
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
// Apply edits
|
|
1167
|
+
const currentContents = new Map<string, string>();
|
|
1168
|
+
for (const [path, content] of backups) {
|
|
1169
|
+
currentContents.set(path, content);
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
let totalReplacements = 0;
|
|
1173
|
+
|
|
1174
|
+
for (const edit of edits) {
|
|
1175
|
+
const content = currentContents.get(edit.filePath);
|
|
1176
|
+
if (!content) continue;
|
|
1177
|
+
|
|
1178
|
+
if (edit.replaceAll) {
|
|
1179
|
+
const count = (content.match(new RegExp(escapeRegex(edit.oldString), "g")) || []).length;
|
|
1180
|
+
currentContents.set(edit.filePath, content.split(edit.oldString).join(edit.newString));
|
|
1181
|
+
totalReplacements += count;
|
|
1182
|
+
} else {
|
|
1183
|
+
currentContents.set(edit.filePath, content.replace(edit.oldString, edit.newString));
|
|
1184
|
+
totalReplacements += 1;
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
// Write all files
|
|
1189
|
+
const filesModified: string[] = [];
|
|
1190
|
+
for (const [path, newContent] of currentContents) {
|
|
1191
|
+
const originalContent = backups.get(path);
|
|
1192
|
+
if (newContent !== originalContent) {
|
|
1193
|
+
try {
|
|
1194
|
+
Bun.write(path, newContent);
|
|
1195
|
+
filesModified.push(path);
|
|
1196
|
+
} catch (err) {
|
|
1197
|
+
// Rollback on failure
|
|
1198
|
+
for (const [rollbackPath, rollbackContent] of backups) {
|
|
1199
|
+
try {
|
|
1200
|
+
Bun.write(rollbackPath, rollbackContent);
|
|
1201
|
+
} catch {
|
|
1202
|
+
// Ignore rollback errors
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
return {
|
|
1206
|
+
success: false,
|
|
1207
|
+
filesModified: [],
|
|
1208
|
+
totalReplacements: 0,
|
|
1209
|
+
error: `Failed to write ${path}: ${err}. All changes rolled back.`,
|
|
1210
|
+
rolledBack: true,
|
|
1211
|
+
};
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
return {
|
|
1217
|
+
success: true,
|
|
1218
|
+
filesModified: filesModified,
|
|
1219
|
+
totalReplacements: totalReplacements,
|
|
1220
|
+
error: undefined,
|
|
1221
|
+
rolledBack: false,
|
|
1222
|
+
};
|
|
1223
|
+
},
|
|
1224
|
+
|
|
1225
|
+
// Tool analysis fallback implementations
|
|
1226
|
+
count_tool_use: (messages) => {
|
|
1227
|
+
const counts: Record<string, number> = {};
|
|
1228
|
+
for (const msg of messages) {
|
|
1229
|
+
if (msg.tool_use) {
|
|
1230
|
+
for (const tool of msg.tool_use) {
|
|
1231
|
+
counts[tool.name] = (counts[tool.name] || 0) + 1;
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
return counts;
|
|
1236
|
+
},
|
|
1237
|
+
|
|
1238
|
+
find_tool_pairs: (messages, _windowSize) => {
|
|
1239
|
+
const pairs: Record<string, Record<string, number>> = {};
|
|
1240
|
+
for (const msg of messages) {
|
|
1241
|
+
if (msg.tool_use && msg.tool_use.length >= 2) {
|
|
1242
|
+
for (let i = 0; i < msg.tool_use.length - 1; i++) {
|
|
1243
|
+
const tool1 = msg.tool_use[i]?.name;
|
|
1244
|
+
const tool2 = msg.tool_use[i + 1]?.name;
|
|
1245
|
+
if (tool1 && tool2) {
|
|
1246
|
+
if (!pairs[tool1]) pairs[tool1] = {};
|
|
1247
|
+
pairs[tool1][tool2] = (pairs[tool1][tool2] || 0) + 1;
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
return pairs;
|
|
1253
|
+
},
|
|
1254
|
+
|
|
1255
|
+
find_common_patterns: (messages) => {
|
|
1256
|
+
const patterns: Array<{ tools: [string, string]; count: number; percentage: number }> = [];
|
|
1257
|
+
const toolPairs: Map<string, number> = new Map();
|
|
1258
|
+
let totalPairs = 0;
|
|
1259
|
+
|
|
1260
|
+
for (const msg of messages) {
|
|
1261
|
+
if (msg.tool_use && msg.tool_use.length >= 2) {
|
|
1262
|
+
for (let i = 0; i < msg.tool_use.length - 1; i++) {
|
|
1263
|
+
const name1 = msg.tool_use[i]?.name;
|
|
1264
|
+
const name2 = msg.tool_use[i + 1]?.name;
|
|
1265
|
+
if (name1 && name2) {
|
|
1266
|
+
const key = `${name1}|${name2}`;
|
|
1267
|
+
toolPairs.set(key, (toolPairs.get(key) || 0) + 1);
|
|
1268
|
+
totalPairs++;
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
for (const [key, count] of toolPairs) {
|
|
1275
|
+
const [tool1, tool2] = key.split("|") as [string, string];
|
|
1276
|
+
patterns.push({
|
|
1277
|
+
tools: [tool1, tool2],
|
|
1278
|
+
count,
|
|
1279
|
+
percentage: totalPairs > 0 ? (count / totalPairs) * 100 : 0,
|
|
1280
|
+
});
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
return patterns.sort((a, b) => b.count - a.count).slice(0, 10);
|
|
1284
|
+
},
|
|
1285
|
+
|
|
1286
|
+
// ===== Cognitive Security Fallbacks =====
|
|
1287
|
+
|
|
1288
|
+
// Action Module
|
|
1289
|
+
classify_operation: (operation: string, domain: string, target?: string | null, reasoning?: string | null) => {
|
|
1290
|
+
const id = `action_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
1291
|
+
let actionType = "observe";
|
|
1292
|
+
let riskLevel = 1;
|
|
1293
|
+
let hasSideEffects = false;
|
|
1294
|
+
let requiresApproval = false;
|
|
1295
|
+
|
|
1296
|
+
const op = operation.toLowerCase();
|
|
1297
|
+
if (op.includes("write") || op.includes("edit") || op.includes("create") || op.includes("delete")) {
|
|
1298
|
+
actionType = "modify";
|
|
1299
|
+
riskLevel = 3;
|
|
1300
|
+
hasSideEffects = true;
|
|
1301
|
+
requiresApproval = true;
|
|
1302
|
+
} else if (op.includes("execute") || op.includes("run") || op.includes("bash")) {
|
|
1303
|
+
actionType = "execute";
|
|
1304
|
+
riskLevel = 4;
|
|
1305
|
+
hasSideEffects = true;
|
|
1306
|
+
requiresApproval = true;
|
|
1307
|
+
} else if (op.includes("send") || op.includes("post") || op.includes("transmit")) {
|
|
1308
|
+
actionType = "communicate";
|
|
1309
|
+
riskLevel = 2;
|
|
1310
|
+
hasSideEffects = true;
|
|
1311
|
+
requiresApproval = domain === "external";
|
|
1312
|
+
} else if (op.includes("read") || op.includes("get") || op.includes("list") || op.includes("search")) {
|
|
1313
|
+
actionType = "observe";
|
|
1314
|
+
riskLevel = 1;
|
|
1315
|
+
hasSideEffects = false;
|
|
1316
|
+
requiresApproval = false;
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
return {
|
|
1320
|
+
id,
|
|
1321
|
+
actionType,
|
|
1322
|
+
domain,
|
|
1323
|
+
operation,
|
|
1324
|
+
target: target || null,
|
|
1325
|
+
flowDirection: "outbound",
|
|
1326
|
+
riskLevel,
|
|
1327
|
+
hasSideEffects,
|
|
1328
|
+
requiresApproval,
|
|
1329
|
+
reasoning: reasoning || `Classified as ${actionType} based on operation name`,
|
|
1330
|
+
timestamp: Date.now(),
|
|
1331
|
+
metadata: null,
|
|
1332
|
+
};
|
|
1333
|
+
},
|
|
1334
|
+
|
|
1335
|
+
get_action_types: () => ["modify", "execute", "communicate", "transfer", "observe", "create", "delete"],
|
|
1336
|
+
|
|
1337
|
+
get_action_risk_levels: () => [
|
|
1338
|
+
{ actionType: "observe", riskLevel: 1 },
|
|
1339
|
+
{ actionType: "communicate", riskLevel: 2 },
|
|
1340
|
+
{ actionType: "create", riskLevel: 3 },
|
|
1341
|
+
{ actionType: "modify", riskLevel: 3 },
|
|
1342
|
+
{ actionType: "transfer", riskLevel: 4 },
|
|
1343
|
+
{ actionType: "execute", riskLevel: 4 },
|
|
1344
|
+
{ actionType: "delete", riskLevel: 5 },
|
|
1345
|
+
],
|
|
1346
|
+
|
|
1347
|
+
create_deny_all_policy: () => ({
|
|
1348
|
+
id: "deny_all",
|
|
1349
|
+
description: "Deny all actions",
|
|
1350
|
+
actionTypes: [],
|
|
1351
|
+
domains: [],
|
|
1352
|
+
operations: [],
|
|
1353
|
+
effect: "deny",
|
|
1354
|
+
priority: 1000,
|
|
1355
|
+
enabled: true,
|
|
1356
|
+
}),
|
|
1357
|
+
|
|
1358
|
+
create_observe_only_policy: () => ({
|
|
1359
|
+
id: "observe_only",
|
|
1360
|
+
description: "Allow observe actions only",
|
|
1361
|
+
actionTypes: ["observe"],
|
|
1362
|
+
domains: [],
|
|
1363
|
+
operations: [],
|
|
1364
|
+
effect: "allow",
|
|
1365
|
+
priority: 100,
|
|
1366
|
+
enabled: true,
|
|
1367
|
+
}),
|
|
1368
|
+
|
|
1369
|
+
create_transfer_approval_policy: () => ({
|
|
1370
|
+
id: "transfer_approval",
|
|
1371
|
+
description: "Require approval for transfer actions",
|
|
1372
|
+
actionTypes: ["transfer"],
|
|
1373
|
+
domains: [],
|
|
1374
|
+
operations: [],
|
|
1375
|
+
effect: "require_approval",
|
|
1376
|
+
priority: 200,
|
|
1377
|
+
enabled: true,
|
|
1378
|
+
}),
|
|
1379
|
+
|
|
1380
|
+
// Intent Module
|
|
1381
|
+
cs_generate_keypair: () => ({
|
|
1382
|
+
privateKey: `private_${Math.random().toString(36).slice(2)}_${Date.now()}`,
|
|
1383
|
+
publicKey: `public_${Math.random().toString(36).slice(2)}_${Date.now()}`,
|
|
1384
|
+
}),
|
|
1385
|
+
|
|
1386
|
+
cs_sign_intent: (intent: any, _privateKey: string) => {
|
|
1387
|
+
return { ...intent, signature: `sig_${Date.now()}`, signedBy: "fallback" };
|
|
1388
|
+
},
|
|
1389
|
+
|
|
1390
|
+
cs_verify_intent: (_intent: any) => ({
|
|
1391
|
+
valid: true,
|
|
1392
|
+
error: null,
|
|
1393
|
+
signatureValid: true,
|
|
1394
|
+
contentIntact: true,
|
|
1395
|
+
expired: false,
|
|
1396
|
+
}),
|
|
1397
|
+
|
|
1398
|
+
cs_hash_intent: (intent: any) => {
|
|
1399
|
+
const str = JSON.stringify(intent);
|
|
1400
|
+
let hash = 0;
|
|
1401
|
+
for (let i = 0; i < str.length; i++) {
|
|
1402
|
+
const char = str.charCodeAt(i);
|
|
1403
|
+
hash = ((hash << 5) - hash) + char;
|
|
1404
|
+
hash = hash & hash;
|
|
1405
|
+
}
|
|
1406
|
+
return Math.abs(hash).toString(16).padStart(16, '0');
|
|
1407
|
+
},
|
|
1408
|
+
|
|
1409
|
+
cs_intents_equivalent: (intent1: any, intent2: any) => {
|
|
1410
|
+
const stripSignature = (i: any) => {
|
|
1411
|
+
const { signature, signedBy, ...rest } = i;
|
|
1412
|
+
return rest;
|
|
1413
|
+
};
|
|
1414
|
+
return JSON.stringify(stripSignature(intent1)) === JSON.stringify(stripSignature(intent2));
|
|
1415
|
+
},
|
|
1416
|
+
|
|
1417
|
+
cs_score_alignment: (_action: any, _intent: any) => ({
|
|
1418
|
+
score: 0.8,
|
|
1419
|
+
reasoning: "Fallback alignment score - native module not available",
|
|
1420
|
+
servesGoals: [],
|
|
1421
|
+
hindersGoals: [],
|
|
1422
|
+
boundaryConcerns: [],
|
|
1423
|
+
confidence: 0.5,
|
|
1424
|
+
shouldBlock: false,
|
|
1425
|
+
requiresReview: false,
|
|
1426
|
+
}),
|
|
1427
|
+
|
|
1428
|
+
cs_batch_score_alignment: (actions: any[], intent: any) => {
|
|
1429
|
+
return actions.map(() => ({
|
|
1430
|
+
score: 0.8,
|
|
1431
|
+
reasoning: "Fallback alignment score",
|
|
1432
|
+
servesGoals: [],
|
|
1433
|
+
hindersGoals: [],
|
|
1434
|
+
boundaryConcerns: [],
|
|
1435
|
+
confidence: 0.5,
|
|
1436
|
+
shouldBlock: false,
|
|
1437
|
+
requiresReview: false,
|
|
1438
|
+
}));
|
|
1439
|
+
},
|
|
1440
|
+
|
|
1441
|
+
cs_check_sequence_violations: (_actions: any[], _intent: any) => [],
|
|
1442
|
+
|
|
1443
|
+
cs_load_intent: (_path: string) => {
|
|
1444
|
+
throw new Error("Native module required for cs_load_intent");
|
|
1445
|
+
},
|
|
1446
|
+
|
|
1447
|
+
cs_save_intent: (_intent: any, _path: string) => {
|
|
1448
|
+
throw new Error("Native module required for cs_save_intent");
|
|
1449
|
+
},
|
|
1450
|
+
|
|
1451
|
+
cs_parse_intent: (json: string) => JSON.parse(json),
|
|
1452
|
+
|
|
1453
|
+
cs_serialize_intent: (intent: any) => JSON.stringify(intent, null, 2),
|
|
1454
|
+
|
|
1455
|
+
cs_validate_intent: (intent: any) => {
|
|
1456
|
+
const errors: string[] = [];
|
|
1457
|
+
const warnings: string[] = [];
|
|
1458
|
+
|
|
1459
|
+
if (!intent.id) errors.push("Missing intent id");
|
|
1460
|
+
if (!intent.version) warnings.push("Missing version");
|
|
1461
|
+
if (!intent.identity) errors.push("Missing identity");
|
|
1462
|
+
if (!intent.purpose) errors.push("Missing purpose");
|
|
1463
|
+
|
|
1464
|
+
return {
|
|
1465
|
+
valid: errors.length === 0,
|
|
1466
|
+
errors,
|
|
1467
|
+
warnings,
|
|
1468
|
+
};
|
|
1469
|
+
},
|
|
1470
|
+
|
|
1471
|
+
cs_create_data_collector_intent: (name: string, description: string) => ({
|
|
1472
|
+
id: `intent_${Date.now()}`,
|
|
1473
|
+
version: 1,
|
|
1474
|
+
identity: {
|
|
1475
|
+
name,
|
|
1476
|
+
description,
|
|
1477
|
+
capabilities: ["read", "list", "search"],
|
|
1478
|
+
constraints: ["no_write", "no_execute", "no_network"],
|
|
1479
|
+
},
|
|
1480
|
+
purpose: {
|
|
1481
|
+
goals: [],
|
|
1482
|
+
nonGoals: ["modify_data", "execute_commands", "send_data"],
|
|
1483
|
+
boundaries: [],
|
|
1484
|
+
},
|
|
1485
|
+
principles: {
|
|
1486
|
+
values: ["transparency", "privacy"],
|
|
1487
|
+
priorities: ["safety_first"],
|
|
1488
|
+
forbidden: ["exfiltration", "modification"],
|
|
1489
|
+
},
|
|
1490
|
+
createdAt: Date.now(),
|
|
1491
|
+
}),
|
|
1492
|
+
|
|
1493
|
+
cs_merge_intents: (base: any, override: any) => ({ ...base, ...override }),
|
|
1494
|
+
|
|
1495
|
+
cs_analyze_corruption: (_snapshot: any, _intent: any) => ({
|
|
1496
|
+
riskScore: 0,
|
|
1497
|
+
indicators: [],
|
|
1498
|
+
recommendation: "continue",
|
|
1499
|
+
explanation: "Fallback analysis - native module not available",
|
|
1500
|
+
}),
|
|
1501
|
+
|
|
1502
|
+
cs_detect_drift: (_baseline: any, _current: any) => ({
|
|
1503
|
+
overallDrift: 0,
|
|
1504
|
+
driftFactors: [],
|
|
1505
|
+
concernLevel: "none",
|
|
1506
|
+
}),
|
|
1507
|
+
|
|
1508
|
+
cs_create_empty_snapshot: () => ({
|
|
1509
|
+
timestamp: Date.now(),
|
|
1510
|
+
actionCount: 0,
|
|
1511
|
+
alignmentDistribution: { mean: 1, variance: 0, min: 1, max: 1, belowThresholdCount: 0 },
|
|
1512
|
+
actionsByDomain: [],
|
|
1513
|
+
actionsByType: [],
|
|
1514
|
+
boundaryViolations: 0,
|
|
1515
|
+
actionsBlocked: 0,
|
|
1516
|
+
}),
|
|
1517
|
+
|
|
1518
|
+
cs_update_snapshot: (snapshot: any, _action: any, alignment: any) => {
|
|
1519
|
+
const newScore = alignment?.score ?? 1;
|
|
1520
|
+
const oldMean = snapshot.alignmentDistribution?.mean ?? 1;
|
|
1521
|
+
const newMean = (oldMean * snapshot.actionCount + newScore) / (snapshot.actionCount + 1);
|
|
1522
|
+
|
|
1523
|
+
return {
|
|
1524
|
+
...snapshot,
|
|
1525
|
+
timestamp: Date.now(),
|
|
1526
|
+
actionCount: snapshot.actionCount + 1,
|
|
1527
|
+
alignmentDistribution: {
|
|
1528
|
+
...snapshot.alignmentDistribution,
|
|
1529
|
+
mean: newMean,
|
|
1530
|
+
},
|
|
1531
|
+
};
|
|
1532
|
+
},
|
|
1533
|
+
|
|
1534
|
+
// Flow Module
|
|
1535
|
+
classify_data: (content: string, source: string, tags: string[]) => {
|
|
1536
|
+
let sensitivity = "internal";
|
|
1537
|
+
let category = "generic";
|
|
1538
|
+
|
|
1539
|
+
if (content.includes("password") || content.includes("secret") || content.includes("key")) {
|
|
1540
|
+
sensitivity = "secret";
|
|
1541
|
+
category = "credentials";
|
|
1542
|
+
} else if (content.includes("@") && content.includes(".")) {
|
|
1543
|
+
sensitivity = "confidential";
|
|
1544
|
+
category = "pii";
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1547
|
+
return {
|
|
1548
|
+
id: `data_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,
|
|
1549
|
+
sensitivity,
|
|
1550
|
+
category,
|
|
1551
|
+
source,
|
|
1552
|
+
tags,
|
|
1553
|
+
can_log: sensitivity !== "secret",
|
|
1554
|
+
can_transmit: sensitivity === "public" || sensitivity === "internal",
|
|
1555
|
+
can_store: true,
|
|
1556
|
+
expires_at: null,
|
|
1557
|
+
created_at: Date.now(),
|
|
1558
|
+
};
|
|
1559
|
+
},
|
|
1560
|
+
|
|
1561
|
+
contains_sensitive_data: (content: string) => {
|
|
1562
|
+
const patterns = ["password", "secret", "api_key", "token", "credential"];
|
|
1563
|
+
return patterns.some(p => content.toLowerCase().includes(p));
|
|
1564
|
+
},
|
|
1565
|
+
|
|
1566
|
+
redact_sensitive: (content: string, replacement?: string | null) => {
|
|
1567
|
+
const repl = replacement || "[REDACTED]";
|
|
1568
|
+
return content
|
|
1569
|
+
.replace(/password[=:]\s*\S+/gi, `password=${repl}`)
|
|
1570
|
+
.replace(/api[_-]?key[=:]\s*\S+/gi, `api_key=${repl}`)
|
|
1571
|
+
.replace(/token[=:]\s*\S+/gi, `token=${repl}`)
|
|
1572
|
+
.replace(/secret[=:]\s*\S+/gi, `secret=${repl}`);
|
|
1573
|
+
},
|
|
1574
|
+
|
|
1575
|
+
get_sensitivity_levels: () => [
|
|
1576
|
+
{ name: "public", value: 1, description: "Publicly shareable" },
|
|
1577
|
+
{ name: "internal", value: 2, description: "Internal use only" },
|
|
1578
|
+
{ name: "confidential", value: 3, description: "Confidential" },
|
|
1579
|
+
{ name: "secret", value: 4, description: "Highly sensitive" },
|
|
1580
|
+
{ name: "top_secret", value: 5, description: "Maximum sensitivity" },
|
|
1581
|
+
],
|
|
1582
|
+
|
|
1583
|
+
get_data_categories: () => [
|
|
1584
|
+
{ name: "generic", description: "Generic data" },
|
|
1585
|
+
{ name: "pii", description: "Personally identifiable information" },
|
|
1586
|
+
{ name: "credentials", description: "Authentication credentials" },
|
|
1587
|
+
{ name: "financial", description: "Financial data" },
|
|
1588
|
+
{ name: "source_code", description: "Source code" },
|
|
1589
|
+
{ name: "configuration", description: "Configuration data" },
|
|
1590
|
+
],
|
|
1591
|
+
|
|
1592
|
+
// Flow Policy Engine
|
|
1593
|
+
create_flow_policy_engine: () => ({
|
|
1594
|
+
addPolicy: (_policy: any) => {},
|
|
1595
|
+
removePolicy: (_id: string) => true,
|
|
1596
|
+
evaluate: (_data: any, _source: string, _target: string) => ({
|
|
1597
|
+
allowed: true,
|
|
1598
|
+
reason: "Fallback: allowed by default",
|
|
1599
|
+
applied_policy: null,
|
|
1600
|
+
can_log: true,
|
|
1601
|
+
can_transmit: true,
|
|
1602
|
+
can_store: true,
|
|
1603
|
+
transformations: [],
|
|
1604
|
+
confidence: 0.5,
|
|
1605
|
+
warnings: ["Fallback implementation - native module not available"],
|
|
1606
|
+
}),
|
|
1607
|
+
listPolicies: () => [],
|
|
1608
|
+
setDefaultAction: (_action: string) => {},
|
|
1609
|
+
setBlpMode: (_mode: string) => {},
|
|
1610
|
+
}),
|
|
1611
|
+
|
|
1612
|
+
// Flow Policies
|
|
1613
|
+
create_allow_all_flow_policy: () => ({
|
|
1614
|
+
id: "allow_all",
|
|
1615
|
+
description: "Allow all flows",
|
|
1616
|
+
source_pattern: "*",
|
|
1617
|
+
target_pattern: "*",
|
|
1618
|
+
min_source_sensitivity: null,
|
|
1619
|
+
max_target_sensitivity: null,
|
|
1620
|
+
categories: [],
|
|
1621
|
+
effect: "allow",
|
|
1622
|
+
priority: 0,
|
|
1623
|
+
required_transforms: [],
|
|
1624
|
+
log_flow: false,
|
|
1625
|
+
require_approval: false,
|
|
1626
|
+
conditions: null,
|
|
1627
|
+
enabled: true,
|
|
1628
|
+
}),
|
|
1629
|
+
|
|
1630
|
+
create_deny_all_flow_policy: () => ({
|
|
1631
|
+
id: "deny_all",
|
|
1632
|
+
description: "Deny all flows",
|
|
1633
|
+
source_pattern: "*",
|
|
1634
|
+
target_pattern: "*",
|
|
1635
|
+
min_source_sensitivity: null,
|
|
1636
|
+
max_target_sensitivity: null,
|
|
1637
|
+
categories: [],
|
|
1638
|
+
effect: "deny",
|
|
1639
|
+
priority: 1000,
|
|
1640
|
+
required_transforms: [],
|
|
1641
|
+
log_flow: false,
|
|
1642
|
+
require_approval: false,
|
|
1643
|
+
conditions: null,
|
|
1644
|
+
enabled: true,
|
|
1645
|
+
}),
|
|
1646
|
+
|
|
1647
|
+
create_strict_flow_policy: () => ({
|
|
1648
|
+
id: "strict",
|
|
1649
|
+
description: "Strict flow policy",
|
|
1650
|
+
source_pattern: "*",
|
|
1651
|
+
target_pattern: "*",
|
|
1652
|
+
min_source_sensitivity: "internal",
|
|
1653
|
+
max_target_sensitivity: null,
|
|
1654
|
+
categories: [],
|
|
1655
|
+
effect: "transform",
|
|
1656
|
+
priority: 500,
|
|
1657
|
+
required_transforms: ["redact_sensitive"],
|
|
1658
|
+
log_flow: true,
|
|
1659
|
+
require_approval: true,
|
|
1660
|
+
conditions: null,
|
|
1661
|
+
enabled: true,
|
|
1662
|
+
}),
|
|
1663
|
+
|
|
1664
|
+
// Flow Tracker
|
|
1665
|
+
create_flow_tracker: () => ({
|
|
1666
|
+
record: (_data: any, _source: string, _target: string, _direction: string, _validation: any, _sessionId: string | null, _actionId: string | null) => ({
|
|
1667
|
+
id: `flow_${Date.now()}`,
|
|
1668
|
+
data_id: _data.id,
|
|
1669
|
+
source_domain: _source,
|
|
1670
|
+
target_domain: _target,
|
|
1671
|
+
direction: _direction,
|
|
1672
|
+
allowed: _validation.allowed,
|
|
1673
|
+
reason: _validation.reason,
|
|
1674
|
+
policy_id: _validation.applied_policy || null,
|
|
1675
|
+
session_id: _sessionId,
|
|
1676
|
+
action_id: _actionId,
|
|
1677
|
+
timestamp: Date.now(),
|
|
1678
|
+
data_hash: "",
|
|
1679
|
+
}),
|
|
1680
|
+
getFlow: (_id: string) => null,
|
|
1681
|
+
getLineage: (_dataId: string) => [],
|
|
1682
|
+
bySource: (_domain: string) => [],
|
|
1683
|
+
byTarget: (_domain: string) => [],
|
|
1684
|
+
bySession: (_sessionId: string) => [],
|
|
1685
|
+
blocked: () => [],
|
|
1686
|
+
allowed: () => [],
|
|
1687
|
+
recent: (_limit: number) => [],
|
|
1688
|
+
stats: () => ({
|
|
1689
|
+
total_flows: 0,
|
|
1690
|
+
allowed_count: 0,
|
|
1691
|
+
blocked_count: 0,
|
|
1692
|
+
by_direction: [],
|
|
1693
|
+
by_source_domain: [],
|
|
1694
|
+
by_target_domain: [],
|
|
1695
|
+
first_timestamp: Date.now(),
|
|
1696
|
+
last_timestamp: Date.now(),
|
|
1697
|
+
}),
|
|
1698
|
+
domainStats: (_domain: string) => null,
|
|
1699
|
+
count: () => 0,
|
|
1700
|
+
clear: () => {},
|
|
1701
|
+
setMaxFlows: (_max: number) => {},
|
|
1702
|
+
exportJsonl: () => "",
|
|
1703
|
+
}),
|
|
1704
|
+
|
|
1705
|
+
// Leak Prevention
|
|
1706
|
+
create_leak_prevention: () => ({
|
|
1707
|
+
check: (_content: string, _channel: string) => ({
|
|
1708
|
+
action: "allow",
|
|
1709
|
+
detections: [],
|
|
1710
|
+
channel_allowed: true,
|
|
1711
|
+
checked_at: Date.now(),
|
|
1712
|
+
}),
|
|
1713
|
+
sanitize: (content: string) => content
|
|
1714
|
+
.replace(/password[=:]\s*\S+/gi, "password=[REDACTED]")
|
|
1715
|
+
.replace(/api[_-]?key[=:]\s*\S+/gi, "api_key=[REDACTED]")
|
|
1716
|
+
.replace(/token[=:]\s*\S+/gi, "token=[REDACTED]")
|
|
1717
|
+
.replace(/secret[=:]\s*\S+/gi, "secret=[REDACTED]"),
|
|
1718
|
+
registerSensitive: (_data: string) => {},
|
|
1719
|
+
addChannel: (_channel: string) => {},
|
|
1720
|
+
removeChannel: (_channel: string) => {},
|
|
1721
|
+
setMode: (_mode: string) => {},
|
|
1722
|
+
stats: () => ({
|
|
1723
|
+
total_checks: 0,
|
|
1724
|
+
blocked_count: 0,
|
|
1725
|
+
alert_count: 0,
|
|
1726
|
+
by_leak_type: {},
|
|
1727
|
+
}),
|
|
1728
|
+
clearSensitive: () => {},
|
|
1729
|
+
}),
|
|
1730
|
+
|
|
1731
|
+
// Leak Prevention helpers
|
|
1732
|
+
check_for_leaks: (content: string, channel: string) => ({
|
|
1733
|
+
action: "allow",
|
|
1734
|
+
detections: [],
|
|
1735
|
+
channel_allowed: true,
|
|
1736
|
+
checked_at: Date.now(),
|
|
1737
|
+
}),
|
|
1738
|
+
|
|
1739
|
+
sanitize_content: (content: string) => content
|
|
1740
|
+
.replace(/password[=:]\s*\S+/gi, "password=[REDACTED]")
|
|
1741
|
+
.replace(/api[_-]?key[=:]\s*\S+/gi, "api_key=[REDACTED]")
|
|
1742
|
+
.replace(/token[=:]\s*\S+/gi, "token=[REDACTED]")
|
|
1743
|
+
.replace(/secret[=:]\s*\S+/gi, "secret=[REDACTED]"),
|
|
1744
|
+
|
|
1745
|
+
// Taint Tracker
|
|
1746
|
+
create_taint_tracker: () => ({
|
|
1747
|
+
registerSource: (_type: string, _sensitivity: string, _tags: string[]) => `source_${Date.now()}`,
|
|
1748
|
+
taint: (_sourceId: string, _data: string, _locationType: string, _identifier: string) => `taint_${Date.now()}`,
|
|
1749
|
+
propagate: (_sourceTaintId: string, _newData: string, _locationType: string, _identifier: string, _propagationType: string, _operation: string) => `prop_${Date.now()}`,
|
|
1750
|
+
canFlow: (_taintId: string, _sink: string) => ({ allowed: true, reason: "Fallback", requires_sanitization: false }),
|
|
1751
|
+
isTainted: (_data: string) => false,
|
|
1752
|
+
getTaint: (_taintId: string) => null,
|
|
1753
|
+
stats: () => ({
|
|
1754
|
+
total_sources: 0,
|
|
1755
|
+
total_tainted: 0,
|
|
1756
|
+
total_propagations: 0,
|
|
1757
|
+
by_source_type: {},
|
|
1758
|
+
by_sensitivity: {},
|
|
1759
|
+
}),
|
|
1760
|
+
clear: (_taintId: string) => false,
|
|
1761
|
+
clearAll: () => {},
|
|
1762
|
+
}),
|
|
1763
|
+
|
|
1764
|
+
// Quant Functions (stubs)
|
|
1765
|
+
quant_version: () => "0.1.0-fallback",
|
|
1766
|
+
quant_ohlcv_new: (_ts: bigint, _o: number, _h: number, _l: number, _c: number, _v: number) => JSON.stringify({ open: _o, high: _h, low: _l, close: _c, volume: _v }),
|
|
1767
|
+
quant_amm_new: (_poolYes: number, _poolNo: number, _fee: number) => JSON.stringify({ poolYes: _poolYes, poolNo: _poolNo, fee: _fee }),
|
|
1768
|
+
quant_amm_calculate_cost: (_poolYes: number, _poolNo: number, _buyYes: boolean, _shares: number) => JSON.stringify({ cost: 0 }),
|
|
1769
|
+
quant_amm_price_impact: (_poolYes: number, _poolNo: number, _buyYes: boolean, _shares: number) => JSON.stringify({ impact: 0 }),
|
|
1770
|
+
quant_lmsr_price: (_yesShares: number, _noShares: number, _b: number) => JSON.stringify({ price: 0.5 }),
|
|
1771
|
+
quant_lmsr_cost: (_yesShares: number, _noShares: number, _b: number, _buyYes: boolean, _shares: number) => JSON.stringify({ cost: 0 }),
|
|
1772
|
+
quant_detect_arbitrage: (_yesPrice: number, _noPrice: number) => JSON.stringify({ hasArbitrage: false }),
|
|
1773
|
+
quant_convert_odds: (_value: number, _fromType: number) => JSON.stringify({ decimal: 0 }),
|
|
1774
|
+
quant_mean: (_data: Float64Array) => 0,
|
|
1775
|
+
quant_std_dev: (_data: Float64Array) => 0,
|
|
1776
|
+
quant_variance: (_data: Float64Array) => 0,
|
|
1777
|
+
quant_correlation: (_x: Float64Array, _y: Float64Array) => 0,
|
|
1778
|
+
|
|
1779
|
+
// Terminal Input (fallback - uses Node.js stdin directly)
|
|
1780
|
+
create_terminal: (): TerminalHandle => {
|
|
1781
|
+
let inRawMode = false;
|
|
1782
|
+
|
|
1783
|
+
return {
|
|
1784
|
+
get isRawMode() { return inRawMode; },
|
|
1785
|
+
enterRawMode(): void {
|
|
1786
|
+
if (process.stdin.isTTY && !inRawMode) {
|
|
1787
|
+
process.stdin.setRawMode(true);
|
|
1788
|
+
process.stdin.resume();
|
|
1789
|
+
inRawMode = true;
|
|
1790
|
+
}
|
|
1791
|
+
},
|
|
1792
|
+
exitRawMode(): void {
|
|
1793
|
+
if (process.stdin.isTTY && inRawMode) {
|
|
1794
|
+
process.stdin.setRawMode(false);
|
|
1795
|
+
inRawMode = false;
|
|
1796
|
+
}
|
|
1797
|
+
},
|
|
1798
|
+
pollEvent(_timeoutMs?: number): NativeKeyEvent | null {
|
|
1799
|
+
// Fallback can't poll synchronously - return null
|
|
1800
|
+
// Use readEvent() instead for async operation
|
|
1801
|
+
return null;
|
|
1802
|
+
},
|
|
1803
|
+
async readEvent(): Promise<NativeKeyEvent> {
|
|
1804
|
+
return new Promise((resolve) => {
|
|
1805
|
+
const handler = (buffer: Buffer) => {
|
|
1806
|
+
process.stdin.off("data", handler);
|
|
1807
|
+
const str = buffer.toString("utf8");
|
|
1808
|
+
|
|
1809
|
+
// Parse simple keypresses
|
|
1810
|
+
if (str === "\r" || str === "\n") {
|
|
1811
|
+
resolve({ code: "enter", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1812
|
+
} else if (str === "\x03") {
|
|
1813
|
+
// Ctrl+C
|
|
1814
|
+
resolve({ code: "c", is_special: false, ctrl: true, alt: false, shift: false, kind: "press" });
|
|
1815
|
+
} else if (str === "\x7f" || str === "\x08") {
|
|
1816
|
+
resolve({ code: "backspace", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1817
|
+
} else if (str === "\x1b") {
|
|
1818
|
+
resolve({ code: "escape", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1819
|
+
} else if (str === "\t") {
|
|
1820
|
+
resolve({ code: "tab", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1821
|
+
} else if (str.length === 1 && str >= " ") {
|
|
1822
|
+
// Regular printable character
|
|
1823
|
+
const ctrl = str.charCodeAt(0) < 32;
|
|
1824
|
+
const char = ctrl ? String.fromCharCode(str.charCodeAt(0) + 96) : str;
|
|
1825
|
+
resolve({ code: char, is_special: false, ctrl, alt: false, shift: false, kind: "press" });
|
|
1826
|
+
} else {
|
|
1827
|
+
// Handle escape sequences for arrows and special keys
|
|
1828
|
+
if (str === "\x1b[A") {
|
|
1829
|
+
resolve({ code: "up", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1830
|
+
} else if (str === "\x1b[B") {
|
|
1831
|
+
resolve({ code: "down", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1832
|
+
} else if (str === "\x1b[C") {
|
|
1833
|
+
resolve({ code: "right", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1834
|
+
} else if (str === "\x1b[D") {
|
|
1835
|
+
resolve({ code: "left", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1836
|
+
} else if (str === "\x1b[5~") {
|
|
1837
|
+
resolve({ code: "pageup", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1838
|
+
} else if (str === "\x1b[6~") {
|
|
1839
|
+
resolve({ code: "pagedown", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1840
|
+
} else if (str === "\x1b[H" || str === "\x1b[1~") {
|
|
1841
|
+
resolve({ code: "home", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1842
|
+
} else if (str === "\x1b[F" || str === "\x1b[4~") {
|
|
1843
|
+
resolve({ code: "end", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1844
|
+
} else if (str === "\x1b[3~") {
|
|
1845
|
+
resolve({ code: "delete", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1846
|
+
} else if (str === "\x1b[Z") {
|
|
1847
|
+
resolve({ code: "backtab", is_special: true, ctrl: false, alt: false, shift: true, kind: "press" });
|
|
1848
|
+
} else {
|
|
1849
|
+
// Unknown escape sequence - treat as-is
|
|
1850
|
+
resolve({ code: str, is_special: false, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
};
|
|
1854
|
+
process.stdin.once("data", handler);
|
|
1855
|
+
});
|
|
1856
|
+
},
|
|
1857
|
+
};
|
|
1858
|
+
},
|
|
1859
|
+
|
|
1860
|
+
// Native TUI (fallback - not available in pure JS)
|
|
1861
|
+
create_tui: (): NativeTuiHandle => {
|
|
1862
|
+
throw new Error("Native TUI not available in fallback mode. Build the Rust native module.");
|
|
1863
|
+
},
|
|
1864
|
+
is_native_tui_available: () => false,
|
|
1865
|
+
};
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
// Export a singleton instance
|
|
1869
|
+
export const native = loadNative();
|
|
1870
|
+
|
|
1871
|
+
/**
|
|
1872
|
+
* Syntax highlight code with ANSI escape codes for terminal display
|
|
1873
|
+
* Uses native Rust module if available, falls back to JS implementation
|
|
1874
|
+
*/
|
|
1875
|
+
export function highlight_code(code: string, language: string): HighlightResult {
|
|
1876
|
+
return native.highlight_code(code, language);
|
|
1877
|
+
}
|
|
1878
|
+
|
|
1879
|
+
/**
|
|
1880
|
+
* Highlight markdown with nested code block syntax highlighting
|
|
1881
|
+
* Parses markdown for code fences and highlights code blocks with their language
|
|
1882
|
+
*/
|
|
1883
|
+
export function highlight_markdown(markdown: string): HighlightResult {
|
|
1884
|
+
return native.highlight_markdown(markdown);
|
|
1885
|
+
}
|
|
1886
|
+
|
|
1887
|
+
/**
|
|
1888
|
+
* List all supported languages for syntax highlighting
|
|
1889
|
+
*/
|
|
1890
|
+
export function list_highlight_languages(): string[] {
|
|
1891
|
+
return [
|
|
1892
|
+
// Core languages
|
|
1893
|
+
"typescript", "ts", "javascript", "js",
|
|
1894
|
+
"python", "py",
|
|
1895
|
+
"rust", "rs",
|
|
1896
|
+
"go", "golang",
|
|
1897
|
+
"ruby", "rb",
|
|
1898
|
+
"java",
|
|
1899
|
+
"c", "cpp", "c++", "csharp", "cs", "c#",
|
|
1900
|
+
"php",
|
|
1901
|
+
"swift",
|
|
1902
|
+
"kotlin", "kt",
|
|
1903
|
+
"scala",
|
|
1904
|
+
// Shell & config
|
|
1905
|
+
"shell", "sh", "bash", "zsh",
|
|
1906
|
+
"json",
|
|
1907
|
+
"yaml", "yml",
|
|
1908
|
+
"toml",
|
|
1909
|
+
// Markup
|
|
1910
|
+
"markdown", "md",
|
|
1911
|
+
"html", "htm",
|
|
1912
|
+
"css", "scss", "less",
|
|
1913
|
+
"xml",
|
|
1914
|
+
// Database
|
|
1915
|
+
"sql",
|
|
1916
|
+
// Diagrams
|
|
1917
|
+
"mermaid", "mmd",
|
|
1918
|
+
];
|
|
1919
|
+
}
|
|
1920
|
+
|
|
1921
|
+
/**
|
|
1922
|
+
* Highlight a diff with ANSI colors
|
|
1923
|
+
* Uses native Rust module if available, falls back to JS implementation
|
|
1924
|
+
*/
|
|
1925
|
+
export function highlight_diff(
|
|
1926
|
+
oldText: string,
|
|
1927
|
+
newText: string,
|
|
1928
|
+
options?: DiffOptions
|
|
1929
|
+
): HighlightDiffResult {
|
|
1930
|
+
return native.highlight_diff(oldText, newText, options);
|
|
1931
|
+
}
|
|
1932
|
+
|
|
1933
|
+
/**
|
|
1934
|
+
* Calculate diff hunks with hunk headers for LLM context
|
|
1935
|
+
* Returns structured diff with @@ headers included in content
|
|
1936
|
+
*/
|
|
1937
|
+
export function calculate_diff(oldText: string, newText: string): Array<{
|
|
1938
|
+
oldStart: number;
|
|
1939
|
+
oldLines: number;
|
|
1940
|
+
newStart: number;
|
|
1941
|
+
newLines: number;
|
|
1942
|
+
content: string;
|
|
1943
|
+
}> {
|
|
1944
|
+
return native.calculate_diff(oldText, newText);
|
|
1945
|
+
}
|
|
1946
|
+
|
|
1947
|
+
// ===== Multi-File Edit Functions =====
|
|
1948
|
+
|
|
1949
|
+
/**
|
|
1950
|
+
* Validate multi-file edits without applying them
|
|
1951
|
+
* Returns an array of error messages (empty if valid)
|
|
1952
|
+
*/
|
|
1953
|
+
export function validate_multi_edits(edits: MultiEditEntry[]): string[] {
|
|
1954
|
+
return native.validate_multi_edits(edits);
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1957
|
+
/**
|
|
1958
|
+
* Preview what edits would be applied without making changes
|
|
1959
|
+
* Returns an array of { file_path, replacement_count } for each file
|
|
1960
|
+
*/
|
|
1961
|
+
export function preview_multi_edits(edits: MultiEditEntry[]): MultiEditPreviewEntry[] {
|
|
1962
|
+
return native.preview_multi_edits(edits);
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1965
|
+
/**
|
|
1966
|
+
* Apply multiple file edits atomically with rollback on failure
|
|
1967
|
+
*
|
|
1968
|
+
* This function:
|
|
1969
|
+
* 1. Validates all edits can be applied (files exist, strings found)
|
|
1970
|
+
* 2. Creates backups of all affected files
|
|
1971
|
+
* 3. Applies all edits
|
|
1972
|
+
* 4. Rolls back on any failure
|
|
1973
|
+
*
|
|
1974
|
+
* @param edits Array of edit operations
|
|
1975
|
+
* @returns Result with success status and list of modified files
|
|
1976
|
+
*/
|
|
1977
|
+
export function apply_multi_edits(edits: MultiEditEntry[]): MultiEditResult {
|
|
1978
|
+
return native.apply_multi_edits(edits);
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1981
|
+
// ===== Helper Functions =====
|
|
1982
|
+
|
|
1983
|
+
function truncateString(s: string, maxLen: number): string {
|
|
1984
|
+
if (s.length <= maxLen) return s;
|
|
1985
|
+
return s.slice(0, maxLen) + "...";
|
|
1986
|
+
}
|
|
1987
|
+
|
|
1988
|
+
function escapeRegex(string: string): string {
|
|
1989
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1990
|
+
}
|
|
1991
|
+
|
|
1992
|
+
// ===== Quant Module =====
|
|
1993
|
+
|
|
1994
|
+
/**
|
|
1995
|
+
* Quant module interface for financial calculations
|
|
1996
|
+
* Loads from @ebowwa/quant-rust native library
|
|
1997
|
+
*/
|
|
1998
|
+
interface QuantModule {
|
|
1999
|
+
quant_version: () => string;
|
|
2000
|
+
quant_last_error: () => string;
|
|
2001
|
+
quant_clear_error: () => void;
|
|
2002
|
+
|
|
2003
|
+
// OHLCV
|
|
2004
|
+
quant_ohlcv_new: (timestamp: bigint, open: number, high: number, low: number, close: number, volume: number) => string;
|
|
2005
|
+
|
|
2006
|
+
// AMM
|
|
2007
|
+
quant_amm_new: (poolYes: number, poolNo: number, fee: number) => string;
|
|
2008
|
+
quant_amm_calculate_cost: (poolYes: number, poolNo: number, buyYes: boolean, shares: number) => string;
|
|
2009
|
+
quant_amm_price_impact: (poolYes: number, poolNo: number, buyYes: boolean, shares: number) => string;
|
|
2010
|
+
|
|
2011
|
+
// LMSR
|
|
2012
|
+
quant_lmsr_price: (yesShares: number, noShares: number, b: number) => string;
|
|
2013
|
+
quant_lmsr_cost: (yesShares: number, noShares: number, b: number, buyYes: boolean, shares: number) => string;
|
|
2014
|
+
|
|
2015
|
+
// Arbitrage
|
|
2016
|
+
quant_detect_arbitrage: (yesPrice: number, noPrice: number) => string;
|
|
2017
|
+
|
|
2018
|
+
// Odds
|
|
2019
|
+
quant_convert_odds: (value: number, fromType: number) => string;
|
|
2020
|
+
|
|
2021
|
+
// Statistics
|
|
2022
|
+
quant_mean: (ptr: number, len: number) => number;
|
|
2023
|
+
quant_std_dev: (ptr: number, len: number) => number;
|
|
2024
|
+
quant_variance: (ptr: number, len: number) => number;
|
|
2025
|
+
quant_correlation: (ptrX: number, ptrY: number, len: number) => number;
|
|
2026
|
+
|
|
2027
|
+
// Memory
|
|
2028
|
+
quant_free_string: (ptr: number) => void;
|
|
2029
|
+
}
|
|
2030
|
+
|
|
2031
|
+
let quantModule: QuantModule | null = null;
|
|
2032
|
+
|
|
2033
|
+
/**
|
|
2034
|
+
* Load the quant native module from @ebowwa/quant-rust
|
|
2035
|
+
*/
|
|
2036
|
+
function loadQuant(): QuantModule | null {
|
|
2037
|
+
if (quantModule) return quantModule;
|
|
2038
|
+
|
|
2039
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
2040
|
+
|
|
2041
|
+
// Try multiple paths for the quant library
|
|
2042
|
+
const libName = process.platform === "darwin"
|
|
2043
|
+
? "libquant_rust.dylib"
|
|
2044
|
+
: process.platform === "linux"
|
|
2045
|
+
? "libquant_rust.so"
|
|
2046
|
+
: "quant_rust.dll";
|
|
2047
|
+
|
|
2048
|
+
const possiblePaths = [
|
|
2049
|
+
// From npm package
|
|
2050
|
+
join(__dirname, "..", "..", "node_modules", "@ebowwa", "quant-rust", "native", `${process.platform}-${process.arch}`, libName),
|
|
2051
|
+
// From npm package (alternate)
|
|
2052
|
+
join(__dirname, "..", "..", "..", "@ebowwa", "quant-rust", "native", `${process.platform}-${process.arch}`, libName),
|
|
2053
|
+
// Development build
|
|
2054
|
+
join(__dirname, "..", "..", "node_modules", "@ebowwa", "quant-rust", "target", "release", libName),
|
|
2055
|
+
];
|
|
2056
|
+
|
|
2057
|
+
for (const libPath of possiblePaths) {
|
|
2058
|
+
try {
|
|
2059
|
+
const { existsSync } = require("fs");
|
|
2060
|
+
if (!existsSync(libPath)) continue;
|
|
2061
|
+
|
|
2062
|
+
const { dlopen, FFIType, ptr } = require("bun:ffi");
|
|
2063
|
+
|
|
2064
|
+
const lib = dlopen(libPath, {
|
|
2065
|
+
quant_version: { returns: FFIType.cstring, args: [] },
|
|
2066
|
+
quant_last_error: { returns: FFIType.cstring, args: [] },
|
|
2067
|
+
quant_clear_error: { returns: FFIType.void, args: [] },
|
|
2068
|
+
quant_ohlcv_new: { returns: FFIType.cstring, args: [FFIType.u64, FFIType.f64, FFIType.f64, FFIType.f64, FFIType.f64, FFIType.f64] },
|
|
2069
|
+
quant_amm_new: { returns: FFIType.cstring, args: [FFIType.f64, FFIType.f64, FFIType.f64] },
|
|
2070
|
+
quant_amm_calculate_cost: { returns: FFIType.cstring, args: [FFIType.f64, FFIType.f64, FFIType.bool, FFIType.f64] },
|
|
2071
|
+
quant_amm_price_impact: { returns: FFIType.cstring, args: [FFIType.f64, FFIType.f64, FFIType.bool, FFIType.f64] },
|
|
2072
|
+
quant_lmsr_price: { returns: FFIType.cstring, args: [FFIType.f64, FFIType.f64, FFIType.f64] },
|
|
2073
|
+
quant_lmsr_cost: { returns: FFIType.cstring, args: [FFIType.f64, FFIType.f64, FFIType.f64, FFIType.bool, FFIType.f64] },
|
|
2074
|
+
quant_detect_arbitrage: { returns: FFIType.cstring, args: [FFIType.f64, FFIType.f64] },
|
|
2075
|
+
quant_convert_odds: { returns: FFIType.cstring, args: [FFIType.f64, FFIType.i32] },
|
|
2076
|
+
quant_mean: { returns: FFIType.f64, args: [FFIType.ptr, FFIType.usize] },
|
|
2077
|
+
quant_std_dev: { returns: FFIType.f64, args: [FFIType.ptr, FFIType.usize] },
|
|
2078
|
+
quant_variance: { returns: FFIType.f64, args: [FFIType.ptr, FFIType.usize] },
|
|
2079
|
+
quant_correlation: { returns: FFIType.f64, args: [FFIType.ptr, FFIType.ptr, FFIType.usize] },
|
|
2080
|
+
quant_free_string: { returns: FFIType.void, args: [FFIType.ptr] },
|
|
2081
|
+
});
|
|
2082
|
+
|
|
2083
|
+
quantModule = lib.symbols as unknown as QuantModule;
|
|
2084
|
+
return quantModule;
|
|
2085
|
+
} catch {
|
|
2086
|
+
continue;
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
2089
|
+
|
|
2090
|
+
return null;
|
|
2091
|
+
}
|
|
2092
|
+
|
|
2093
|
+
// Load quant module
|
|
2094
|
+
export const quant = loadQuant();
|
|
2095
|
+
|
|
2096
|
+
// ===== Quant Helper Functions =====
|
|
2097
|
+
|
|
2098
|
+
function parseQuantJson<T>(response: string | null): T {
|
|
2099
|
+
if (!response) {
|
|
2100
|
+
throw new Error(quant?.quant_last_error() || "Unknown quant error");
|
|
2101
|
+
}
|
|
2102
|
+
return JSON.parse(response) as T;
|
|
2103
|
+
}
|
|
2104
|
+
|
|
2105
|
+
function toFloat64Ptr(data: number[]): { buffer: Float64Array; ptr: number } {
|
|
2106
|
+
const { ptr } = require("bun:ffi");
|
|
2107
|
+
const buffer = new Float64Array(data);
|
|
2108
|
+
return { buffer, ptr: ptr(buffer) };
|
|
2109
|
+
}
|
|
2110
|
+
|
|
2111
|
+
// ===== Quant Export Functions =====
|
|
2112
|
+
|
|
2113
|
+
/** Warn once when using JS fallback */
|
|
2114
|
+
let quantFallbackWarned = false;
|
|
2115
|
+
function warnQuantFallback(): void {
|
|
2116
|
+
if (!quantFallbackWarned) {
|
|
2117
|
+
console.warn("\x1b[33m[quant] WARNING: Rust native module not loaded, using JS fallback\x1b[0m");
|
|
2118
|
+
quantFallbackWarned = true;
|
|
2119
|
+
}
|
|
2120
|
+
}
|
|
2121
|
+
|
|
2122
|
+
export function quantVersion(): string {
|
|
2123
|
+
if (!quant) {
|
|
2124
|
+
warnQuantFallback();
|
|
2125
|
+
return "JS_FALLBACK (rust failed)";
|
|
2126
|
+
}
|
|
2127
|
+
return quant.quant_version();
|
|
2128
|
+
}
|
|
2129
|
+
|
|
2130
|
+
export function isQuantAvailable(): boolean {
|
|
2131
|
+
return quant !== null;
|
|
2132
|
+
}
|
|
2133
|
+
|
|
2134
|
+
// ----- OHLCV -----
|
|
2135
|
+
|
|
2136
|
+
export function createOHLCV(
|
|
2137
|
+
timestamp: number,
|
|
2138
|
+
open: number,
|
|
2139
|
+
high: number,
|
|
2140
|
+
low: number,
|
|
2141
|
+
close: number,
|
|
2142
|
+
volume: number
|
|
2143
|
+
): OHLCV {
|
|
2144
|
+
if (!quant) {
|
|
2145
|
+
warnQuantFallback();
|
|
2146
|
+
return { timestamp, open, high, low, close, volume };
|
|
2147
|
+
}
|
|
2148
|
+
const response = quant.quant_ohlcv_new(BigInt(timestamp), open, high, low, close, volume);
|
|
2149
|
+
return parseQuantJson(response);
|
|
2150
|
+
}
|
|
2151
|
+
|
|
2152
|
+
// ----- AMM -----
|
|
2153
|
+
|
|
2154
|
+
export function createAMM(poolYes: number, poolNo: number, fee: number): AMMState {
|
|
2155
|
+
if (!quant) {
|
|
2156
|
+
warnQuantFallback();
|
|
2157
|
+
const k = poolYes * poolNo;
|
|
2158
|
+
return {
|
|
2159
|
+
pool_yes: poolYes,
|
|
2160
|
+
pool_no: poolNo,
|
|
2161
|
+
k,
|
|
2162
|
+
fee,
|
|
2163
|
+
price_yes: poolNo / k,
|
|
2164
|
+
price_no: poolYes / k,
|
|
2165
|
+
};
|
|
2166
|
+
}
|
|
2167
|
+
const response = quant.quant_amm_new(poolYes, poolNo, fee);
|
|
2168
|
+
return parseQuantJson(response);
|
|
2169
|
+
}
|
|
2170
|
+
|
|
2171
|
+
export function ammCalculateCost(
|
|
2172
|
+
poolYes: number,
|
|
2173
|
+
poolNo: number,
|
|
2174
|
+
outcome: "yes" | "no" | boolean,
|
|
2175
|
+
shares: number
|
|
2176
|
+
): number {
|
|
2177
|
+
if (!quant) {
|
|
2178
|
+
warnQuantFallback();
|
|
2179
|
+
const buyYes = typeof outcome === "string" ? outcome === "yes" : outcome;
|
|
2180
|
+
const k = poolYes * poolNo;
|
|
2181
|
+
if (buyYes) {
|
|
2182
|
+
return (k / (poolYes + shares)) - poolNo;
|
|
2183
|
+
}
|
|
2184
|
+
return (k / (poolNo + shares)) - poolYes;
|
|
2185
|
+
}
|
|
2186
|
+
const buyYes = typeof outcome === "string" ? outcome === "yes" : outcome;
|
|
2187
|
+
const response = quant.quant_amm_calculate_cost(poolYes, poolNo, buyYes, shares);
|
|
2188
|
+
const result = parseQuantJson<AMMCostResult>(response);
|
|
2189
|
+
return Math.abs(result.cost);
|
|
2190
|
+
}
|
|
2191
|
+
|
|
2192
|
+
export function ammPriceImpact(
|
|
2193
|
+
poolYes: number,
|
|
2194
|
+
poolNo: number,
|
|
2195
|
+
outcome: "yes" | "no" | boolean,
|
|
2196
|
+
shares: number
|
|
2197
|
+
): AMMPriceImpactResult {
|
|
2198
|
+
if (!quant) {
|
|
2199
|
+
warnQuantFallback();
|
|
2200
|
+
const buyYes = typeof outcome === "string" ? outcome === "yes" : outcome;
|
|
2201
|
+
const k = poolYes * poolNo;
|
|
2202
|
+
const priceBefore = buyYes ? poolNo / k : poolYes / k;
|
|
2203
|
+
const newPoolYes = buyYes ? poolYes + shares : poolYes;
|
|
2204
|
+
const newPoolNo = buyYes ? poolNo : poolNo + shares;
|
|
2205
|
+
const priceAfter = buyYes ? newPoolNo / k : newPoolYes / k;
|
|
2206
|
+
return {
|
|
2207
|
+
price_before: priceBefore,
|
|
2208
|
+
price_after: priceAfter,
|
|
2209
|
+
price_impact: Math.abs(priceAfter - priceBefore) / priceBefore,
|
|
2210
|
+
slippage: Math.abs(priceAfter - priceBefore),
|
|
2211
|
+
};
|
|
2212
|
+
}
|
|
2213
|
+
const buyYes = typeof outcome === "string" ? outcome === "yes" : outcome;
|
|
2214
|
+
const response = quant.quant_amm_price_impact(poolYes, poolNo, buyYes, shares);
|
|
2215
|
+
return parseQuantJson(response);
|
|
2216
|
+
}
|
|
2217
|
+
|
|
2218
|
+
// ----- LMSR -----
|
|
2219
|
+
|
|
2220
|
+
export function lmsrPrice(yesShares: number, noShares: number, b: number): LMSRPriceResult {
|
|
2221
|
+
if (!quant) {
|
|
2222
|
+
warnQuantFallback();
|
|
2223
|
+
const expYes = Math.exp(yesShares / b);
|
|
2224
|
+
const expNo = Math.exp(noShares / b);
|
|
2225
|
+
const sum = expYes + expNo;
|
|
2226
|
+
return { yes_price: expYes / sum, no_price: expNo / sum, spread: Math.abs(expYes - expNo) / sum };
|
|
2227
|
+
}
|
|
2228
|
+
const response = quant.quant_lmsr_price(yesShares, noShares, b);
|
|
2229
|
+
return parseQuantJson(response);
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2232
|
+
export function lmsrCost(
|
|
2233
|
+
yesShares: number,
|
|
2234
|
+
noShares: number,
|
|
2235
|
+
b: number,
|
|
2236
|
+
outcome: "yes" | "no" | boolean,
|
|
2237
|
+
shares: number
|
|
2238
|
+
): AMMCostResult {
|
|
2239
|
+
if (!quant) {
|
|
2240
|
+
warnQuantFallback();
|
|
2241
|
+
const buyYes = typeof outcome === "string" ? outcome === "yes" : outcome;
|
|
2242
|
+
const costBefore = b * Math.log(Math.exp(yesShares / b) + Math.exp(noShares / b));
|
|
2243
|
+
const newYes = buyYes ? yesShares + shares : yesShares;
|
|
2244
|
+
const newNo = buyYes ? noShares : noShares + shares;
|
|
2245
|
+
const costAfter = b * Math.log(Math.exp(newYes / b) + Math.exp(newNo / b));
|
|
2246
|
+
return { cost: costAfter - costBefore, avg_price: (costAfter - costBefore) / shares };
|
|
2247
|
+
}
|
|
2248
|
+
const buyYes = typeof outcome === "string" ? outcome === "yes" : outcome;
|
|
2249
|
+
const response = quant.quant_lmsr_cost(yesShares, noShares, b, buyYes, shares);
|
|
2250
|
+
return parseQuantJson(response);
|
|
2251
|
+
}
|
|
2252
|
+
|
|
2253
|
+
// ----- Arbitrage -----
|
|
2254
|
+
|
|
2255
|
+
export function detectArbitrage(yesPrice: number, noPrice: number): ArbitrageResult {
|
|
2256
|
+
if (!quant) {
|
|
2257
|
+
warnQuantFallback();
|
|
2258
|
+
const total = yesPrice + noPrice;
|
|
2259
|
+
return {
|
|
2260
|
+
has_arbitrage: total < 1,
|
|
2261
|
+
yes_price: yesPrice,
|
|
2262
|
+
no_price: noPrice,
|
|
2263
|
+
total,
|
|
2264
|
+
profit_per_share: total < 1 ? 1 - total : 0,
|
|
2265
|
+
};
|
|
2266
|
+
}
|
|
2267
|
+
const response = quant.quant_detect_arbitrage(yesPrice, noPrice);
|
|
2268
|
+
return parseQuantJson(response);
|
|
2269
|
+
}
|
|
2270
|
+
|
|
2271
|
+
// ----- Odds Conversion -----
|
|
2272
|
+
|
|
2273
|
+
const ODDS_TYPE_MAP: Record<string, number> = {
|
|
2274
|
+
probability: 0,
|
|
2275
|
+
decimal: 1,
|
|
2276
|
+
american: 2,
|
|
2277
|
+
};
|
|
2278
|
+
|
|
2279
|
+
export function convertOdds(value: number, fromType: "probability" | "decimal" | "american"): OddsConversion {
|
|
2280
|
+
if (!quant) {
|
|
2281
|
+
warnQuantFallback();
|
|
2282
|
+
let prob: number;
|
|
2283
|
+
switch (fromType) {
|
|
2284
|
+
case "probability": prob = value; break;
|
|
2285
|
+
case "decimal": prob = 1 / value; break;
|
|
2286
|
+
case "american": prob = value > 0 ? 100 / (value + 100) : -value / (-value + 100); break;
|
|
2287
|
+
}
|
|
2288
|
+
const americanOdds = prob >= 0.5 ? Math.round(-100 / (prob - 1)) : Math.round((1 - prob) / prob * 100);
|
|
2289
|
+
return { probability: prob, decimal_odds: 1 / prob, american_odds: americanOdds };
|
|
2290
|
+
}
|
|
2291
|
+
const response = quant.quant_convert_odds(value, ODDS_TYPE_MAP[fromType] ?? 0);
|
|
2292
|
+
return parseQuantJson(response);
|
|
2293
|
+
}
|
|
2294
|
+
|
|
2295
|
+
// ----- Statistics -----
|
|
2296
|
+
|
|
2297
|
+
export function quantMean(data: number[]): number {
|
|
2298
|
+
if (data.length === 0) return NaN;
|
|
2299
|
+
if (!quant) {
|
|
2300
|
+
warnQuantFallback();
|
|
2301
|
+
return data.reduce((a, b) => a + b, 0) / data.length;
|
|
2302
|
+
}
|
|
2303
|
+
const { ptr } = toFloat64Ptr(data);
|
|
2304
|
+
return quant.quant_mean(ptr, data.length);
|
|
2305
|
+
}
|
|
2306
|
+
|
|
2307
|
+
export function quantStdDev(data: number[]): number {
|
|
2308
|
+
if (data.length === 0) return NaN;
|
|
2309
|
+
if (!quant) {
|
|
2310
|
+
warnQuantFallback();
|
|
2311
|
+
const m = data.reduce((a, b) => a + b, 0) / data.length;
|
|
2312
|
+
return Math.sqrt(data.reduce((sum, x) => sum + (x - m) ** 2, 0) / data.length);
|
|
2313
|
+
}
|
|
2314
|
+
const { ptr } = toFloat64Ptr(data);
|
|
2315
|
+
return quant.quant_std_dev(ptr, data.length);
|
|
2316
|
+
}
|
|
2317
|
+
|
|
2318
|
+
export function quantVariance(data: number[]): number {
|
|
2319
|
+
if (data.length === 0) return NaN;
|
|
2320
|
+
if (!quant) {
|
|
2321
|
+
warnQuantFallback();
|
|
2322
|
+
const m = data.reduce((a, b) => a + b, 0) / data.length;
|
|
2323
|
+
return data.reduce((sum, x) => sum + (x - m) ** 2, 0) / data.length;
|
|
2324
|
+
}
|
|
2325
|
+
const { ptr } = toFloat64Ptr(data);
|
|
2326
|
+
return quant.quant_variance(ptr, data.length);
|
|
2327
|
+
}
|
|
2328
|
+
|
|
2329
|
+
export function quantCorrelation(x: number[], y: number[]): number {
|
|
2330
|
+
if (x.length === 0 || y.length === 0 || x.length !== y.length) return NaN;
|
|
2331
|
+
if (!quant) {
|
|
2332
|
+
warnQuantFallback();
|
|
2333
|
+
const n = x.length;
|
|
2334
|
+
const mx = x.reduce((a, b) => a + b, 0) / n;
|
|
2335
|
+
const my = y.reduce((a, b) => a + b, 0) / n;
|
|
2336
|
+
const cov = x.reduce((s, xi, i) => s + (xi - mx) * (y[i]! - my), 0) / n;
|
|
2337
|
+
const vx = x.reduce((s, xi) => s + (xi - mx) ** 2, 0) / n;
|
|
2338
|
+
const vy = y.reduce((s, yi) => s + (yi - my) ** 2, 0) / n;
|
|
2339
|
+
return cov / Math.sqrt(vx * vy);
|
|
2340
|
+
}
|
|
2341
|
+
const { ptr: ptrX } = toFloat64Ptr(x);
|
|
2342
|
+
const { ptr: ptrY } = toFloat64Ptr(y);
|
|
2343
|
+
return quant.quant_correlation(ptrX, ptrY, x.length);
|
|
2344
|
+
}
|
|
2345
|
+
|