@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,1625 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native module loader
|
|
3
|
+
* Loads Rust-compiled native modules for performance-critical operations
|
|
4
|
+
*/
|
|
5
|
+
import { dlopen, suffix } from "bun:ffi";
|
|
6
|
+
import { join, dirname } from "path";
|
|
7
|
+
import { fileURLToPath } from "url";
|
|
8
|
+
let nativeModule = null;
|
|
9
|
+
/**
|
|
10
|
+
* Load the native module
|
|
11
|
+
*/
|
|
12
|
+
export function loadNative() {
|
|
13
|
+
if (nativeModule) {
|
|
14
|
+
return nativeModule;
|
|
15
|
+
}
|
|
16
|
+
// Try multiple possible locations for the native module
|
|
17
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
18
|
+
const basePaths = [
|
|
19
|
+
join(__dirname, "..", "native"), // dist/../native (library entry)
|
|
20
|
+
join(__dirname, "..", "..", "native"), // dist/foo/../native
|
|
21
|
+
join(__dirname, "..", "..", "..", "native"), // dist/foo/bar/../native
|
|
22
|
+
join(__dirname, "..", "..", "..", "..", "native"), // dist/interfaces/ui/../native
|
|
23
|
+
join(__dirname, "..", "..", "..", "..", "..", "native"), // dist/interfaces/ui/terminal/../native
|
|
24
|
+
join(__dirname, "..", "..", "..", "..", "..", "..", "native"), // CLI entry: dist/interfaces/ui/terminal/cli/../native
|
|
25
|
+
join(__dirname, "native"), // native/ (if running from project root)
|
|
26
|
+
];
|
|
27
|
+
// Try .node files first (NAPI modules)
|
|
28
|
+
const nodeFiles = ["index.darwin-arm64.node", "index.darwin-x64.node", "index.node"];
|
|
29
|
+
for (const basePath of basePaths) {
|
|
30
|
+
for (const file of nodeFiles) {
|
|
31
|
+
const nativePath = join(basePath, file);
|
|
32
|
+
try {
|
|
33
|
+
// Try to load NAPI module directly
|
|
34
|
+
const native = require(nativePath);
|
|
35
|
+
if (native && (native.highlightCode || native.highlight_code)) {
|
|
36
|
+
// Map camelCase to snake_case if needed
|
|
37
|
+
nativeModule = {
|
|
38
|
+
highlight_code: native.highlightCode || native.highlight_code,
|
|
39
|
+
highlight_markdown: native.highlightMarkdown || native.highlight_markdown,
|
|
40
|
+
highlight_diff: native.highlightDiff || native.highlight_diff,
|
|
41
|
+
search_files: native.searchFiles || native.search_files,
|
|
42
|
+
count_tokens: native.countTokens || native.count_tokens,
|
|
43
|
+
calculate_diff: native.calculateDiff || native.calculate_diff,
|
|
44
|
+
compact_content: native.compactContent || native.compact_content,
|
|
45
|
+
count_tool_use: native.countToolUse || native.count_tool_use,
|
|
46
|
+
find_tool_pairs: native.findToolPairs || native.find_tool_pairs,
|
|
47
|
+
find_common_patterns: native.findCommonPatterns || native.find_common_patterns,
|
|
48
|
+
validate_multi_edits: native.validateMultiEdits || native.validate_multi_edits,
|
|
49
|
+
preview_multi_edits: native.previewMultiEdits || native.preview_multi_edits,
|
|
50
|
+
apply_multi_edits: native.applyMultiEdits || native.apply_multi_edits,
|
|
51
|
+
// Cognitive Security - Action Module (NAPI exports camelCase)
|
|
52
|
+
classify_operation: native.classifyOperation,
|
|
53
|
+
get_action_types: native.getActionTypes,
|
|
54
|
+
get_action_risk_levels: native.getActionRiskLevels,
|
|
55
|
+
create_deny_all_policy: native.createDenyAllPolicy,
|
|
56
|
+
create_observe_only_policy: native.createObserveOnlyPolicy,
|
|
57
|
+
create_transfer_approval_policy: native.createTransferApprovalPolicy,
|
|
58
|
+
// Cognitive Security - Intent Module (NAPI exports camelCase)
|
|
59
|
+
cs_generate_keypair: native.generateIntentKeypair,
|
|
60
|
+
cs_sign_intent: native.signIntent,
|
|
61
|
+
cs_verify_intent: native.verifyIntentSignature,
|
|
62
|
+
cs_hash_intent: native.hashIntent,
|
|
63
|
+
cs_intents_equivalent: native.intentsEquivalent,
|
|
64
|
+
cs_score_alignment: native.scoreAlignment,
|
|
65
|
+
cs_batch_score_alignment: native.batchScoreAlignment,
|
|
66
|
+
cs_check_sequence_violations: native.checkSequenceViolations,
|
|
67
|
+
cs_load_intent: native.loadIntentFromFile,
|
|
68
|
+
cs_save_intent: native.saveIntentToFile,
|
|
69
|
+
cs_parse_intent: native.parseIntent,
|
|
70
|
+
cs_serialize_intent: native.serializeIntent,
|
|
71
|
+
cs_validate_intent: native.validateIntentStructure,
|
|
72
|
+
cs_create_data_collector_intent: native.createDataCollectorIntent,
|
|
73
|
+
cs_merge_intents: native.mergeIntents,
|
|
74
|
+
cs_analyze_corruption: native.analyzeCorruption,
|
|
75
|
+
cs_detect_drift: native.detectBehavioralDrift,
|
|
76
|
+
cs_create_empty_snapshot: native.createEmptySnapshot,
|
|
77
|
+
cs_update_snapshot: native.updateSnapshot,
|
|
78
|
+
// Cognitive Security - Flow Module (NAPI exports camelCase)
|
|
79
|
+
classify_data: native.classifyData,
|
|
80
|
+
contains_sensitive_data: native.containsSensitiveData,
|
|
81
|
+
redact_sensitive: native.redactSensitive,
|
|
82
|
+
get_sensitivity_levels: native.getSensitivityLevels,
|
|
83
|
+
get_data_categories: native.getDataCategories,
|
|
84
|
+
create_flow_policy_engine: native.createFlowPolicyEngine,
|
|
85
|
+
create_allow_all_flow_policy: native.createAllowAllFlowPolicy,
|
|
86
|
+
create_deny_all_flow_policy: native.createDenyAllFlowPolicy,
|
|
87
|
+
create_strict_flow_policy: native.createStrictFlowPolicy,
|
|
88
|
+
create_flow_tracker: native.createFlowTracker,
|
|
89
|
+
create_leak_prevention: native.createLeakPrevention,
|
|
90
|
+
check_for_leaks: native.checkForLeaks,
|
|
91
|
+
sanitize_content: native.sanitizeContent,
|
|
92
|
+
create_taint_tracker: native.createTaintTracker,
|
|
93
|
+
// Quant Functions
|
|
94
|
+
quant_version: native.quantVersion || native.quant_version,
|
|
95
|
+
quant_ohlcv_new: native.quantOhlcvNew || native.quant_ohlcv_new,
|
|
96
|
+
quant_amm_new: native.quantAmmNew || native.quant_amm_new,
|
|
97
|
+
quant_amm_calculate_cost: native.quantAmmCalculateCost || native.quant_amm_calculate_cost,
|
|
98
|
+
quant_amm_price_impact: native.quantAmmPriceImpact || native.quant_amm_price_impact,
|
|
99
|
+
quant_lmsr_price: native.quantLmsrPrice || native.quant_lmsr_price,
|
|
100
|
+
quant_lmsr_cost: native.quantLmsrCost || native.quant_lmsr_cost,
|
|
101
|
+
quant_detect_arbitrage: native.quantDetectArbitrage || native.quant_detect_arbitrage,
|
|
102
|
+
quant_convert_odds: native.quantConvertOdds || native.quant_convert_odds,
|
|
103
|
+
quant_mean: native.quantMean || native.quant_mean,
|
|
104
|
+
quant_std_dev: native.quantStdDev || native.quant_std_dev,
|
|
105
|
+
quant_variance: native.quantVariance || native.quant_variance,
|
|
106
|
+
quant_correlation: native.quantCorrelation || native.quant_correlation,
|
|
107
|
+
// Terminal Input
|
|
108
|
+
create_terminal: native.createTerminal || native.create_terminal,
|
|
109
|
+
// Native TUI
|
|
110
|
+
create_tui: native.createTui || native.create_tui,
|
|
111
|
+
is_native_tui_available: () => typeof (native.createTui || native.create_tui) === 'function',
|
|
112
|
+
};
|
|
113
|
+
return nativeModule;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
// Try next path
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Try FFI with dylib
|
|
123
|
+
const dylibPaths = basePaths.map(p => join(p, `claude_code_native.${suffix}`));
|
|
124
|
+
for (const nativePath of dylibPaths) {
|
|
125
|
+
try {
|
|
126
|
+
const lib = dlopen(nativePath, {
|
|
127
|
+
highlight_code: {
|
|
128
|
+
args: ["cstring", "cstring"],
|
|
129
|
+
returns: "pointer",
|
|
130
|
+
},
|
|
131
|
+
highlight_markdown: {
|
|
132
|
+
args: ["cstring"],
|
|
133
|
+
returns: "pointer",
|
|
134
|
+
},
|
|
135
|
+
highlight_diff: {
|
|
136
|
+
args: ["cstring", "cstring", "pointer"],
|
|
137
|
+
returns: "pointer",
|
|
138
|
+
},
|
|
139
|
+
search_files: {
|
|
140
|
+
args: ["cstring", "cstring", "pointer"],
|
|
141
|
+
returns: "pointer",
|
|
142
|
+
},
|
|
143
|
+
count_tokens: {
|
|
144
|
+
args: ["cstring"],
|
|
145
|
+
returns: "u32",
|
|
146
|
+
},
|
|
147
|
+
calculate_diff: {
|
|
148
|
+
args: ["cstring", "cstring"],
|
|
149
|
+
returns: "pointer",
|
|
150
|
+
},
|
|
151
|
+
compact_content: {
|
|
152
|
+
args: ["cstring", "u32", "cstring"],
|
|
153
|
+
returns: "pointer",
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
nativeModule = lib.symbols;
|
|
157
|
+
return nativeModule;
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// No native module found, use fallback
|
|
164
|
+
console.warn("Native module not available, using JS fallback");
|
|
165
|
+
return getFallbackModule();
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Check if native module is available
|
|
169
|
+
*/
|
|
170
|
+
export function isNativeAvailable() {
|
|
171
|
+
try {
|
|
172
|
+
loadNative();
|
|
173
|
+
return nativeModule !== null;
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Fallback implementations in pure JavaScript
|
|
181
|
+
*/
|
|
182
|
+
function getFallbackModule() {
|
|
183
|
+
return {
|
|
184
|
+
highlight_code: (code, language) => {
|
|
185
|
+
// ANSI color codes
|
|
186
|
+
const colors = {
|
|
187
|
+
reset: "\x1b[0m",
|
|
188
|
+
keyword: "\x1b[38;2;180;142;173m", // purple
|
|
189
|
+
string: "\x1b[38;2;163;190;140m", // green
|
|
190
|
+
number: "\x1b[38;2;208;135;112m", // orange
|
|
191
|
+
type: "\x1b[38;2;191;97;106m", // red
|
|
192
|
+
function: "\x1b[38;2;143;161;179m", // blue
|
|
193
|
+
comment: "\x1b[38;2;108;153;139m", // gray-green
|
|
194
|
+
default: "\x1b[38;2;192;197;206m", // gray
|
|
195
|
+
special: "\x1b[38;2;150;180;210m", // light blue
|
|
196
|
+
arrow: "\x1b[38;2;200;160;120m", // gold/tan
|
|
197
|
+
};
|
|
198
|
+
// Mermaid-specific highlighting
|
|
199
|
+
if (language.toLowerCase() === "mermaid" || language.toLowerCase() === "mmd") {
|
|
200
|
+
const MERMAID_KEYWORDS = new Set([
|
|
201
|
+
// Diagram types
|
|
202
|
+
"graph", "flowchart", "sequenceDiagram", "classDiagram", "stateDiagram",
|
|
203
|
+
"erDiagram", "journey", "gantt", "pie", "gitGraph", "mindmap", "timeline",
|
|
204
|
+
"quadrantChart", "requirementDiagram", "C4Context", "C4Container",
|
|
205
|
+
"C4Component", "C4Dynamic", "C4Deployment",
|
|
206
|
+
// Directions
|
|
207
|
+
"TB", "TD", "BT", "RL", "LR", "left", "right", "top", "bottom",
|
|
208
|
+
// Subgraphs/participants
|
|
209
|
+
"subgraph", "end", "participant", "actor", "as",
|
|
210
|
+
// Flowchart
|
|
211
|
+
"node", "click", "link", "href", "callback",
|
|
212
|
+
// Sequence
|
|
213
|
+
"Note", "over", "loop", "alt", "else", "opt", "par", "rect", "autonumber",
|
|
214
|
+
"activate", "deactivate",
|
|
215
|
+
// Class
|
|
216
|
+
"class", "namespace", "interface", "annotation", "service", "enum",
|
|
217
|
+
// State
|
|
218
|
+
"state", "note", "fork", "join", "choice",
|
|
219
|
+
// ER
|
|
220
|
+
"entity",
|
|
221
|
+
// Gantt
|
|
222
|
+
"dateFormat", "title", "section", "excludes", "includes", "todayMarker",
|
|
223
|
+
// Common
|
|
224
|
+
"title", "accTitle", "accDescr",
|
|
225
|
+
]);
|
|
226
|
+
const MERMAID_ARROWS = new Set([
|
|
227
|
+
"-->", "---", "->", "->>", "-.", "-.-", "==>", "==", "--x", "--o",
|
|
228
|
+
"<--", "<-", "<<-", "<-->", "<->", "o--o", "x--x", "-x", "-o",
|
|
229
|
+
]);
|
|
230
|
+
const MERMAID_SHAPES = [
|
|
231
|
+
["[", "]"], // rect
|
|
232
|
+
["(", ")"], // rounded
|
|
233
|
+
["([", "])"], // stadium
|
|
234
|
+
["[[", "]]"], // subroutine
|
|
235
|
+
["[((", ")]"], // cylinder
|
|
236
|
+
[">", "]"], // asymmetric
|
|
237
|
+
["{", "}"], // rhombus
|
|
238
|
+
["{{", "}}"], // hexagon
|
|
239
|
+
["[/", "/]"], // parallelogram
|
|
240
|
+
["[\\", "\\]"], // parallelogram alt
|
|
241
|
+
["[(", ")]"], // circle
|
|
242
|
+
["(((", ")))"], // double circle
|
|
243
|
+
];
|
|
244
|
+
const lines = code.split("\n");
|
|
245
|
+
const highlighted = lines.map(line => {
|
|
246
|
+
let result = line;
|
|
247
|
+
// Comments (%%)
|
|
248
|
+
if (line.trim().startsWith("%%")) {
|
|
249
|
+
return `${colors.comment}${line}${colors.reset}`;
|
|
250
|
+
}
|
|
251
|
+
// Arrows and connections (handle first to preserve them)
|
|
252
|
+
for (const arrow of MERMAID_ARROWS) {
|
|
253
|
+
const escaped = arrow.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
254
|
+
result = result.replace(new RegExp(escaped, 'g'), `${colors.arrow}${arrow}${colors.default}`);
|
|
255
|
+
}
|
|
256
|
+
// Strings (quoted)
|
|
257
|
+
result = result.replace(/"([^"\\]|\\.)*"/g, match => {
|
|
258
|
+
return `${colors.string}${match}${colors.default}`;
|
|
259
|
+
});
|
|
260
|
+
// Numbers
|
|
261
|
+
result = result.replace(/\b(\d+\.?\d*)\b/g, `${colors.number}$1${colors.default}`);
|
|
262
|
+
// Keywords
|
|
263
|
+
result = result.replace(/\b([A-Za-z_][A-Za-z0-9_]*)\b/g, (match) => {
|
|
264
|
+
if (MERMAID_KEYWORDS.has(match)) {
|
|
265
|
+
return `${colors.keyword}${match}${colors.default}`;
|
|
266
|
+
}
|
|
267
|
+
return match;
|
|
268
|
+
});
|
|
269
|
+
// Special characters for shapes
|
|
270
|
+
for (const [open, close] of MERMAID_SHAPES) {
|
|
271
|
+
if (!open || !close)
|
|
272
|
+
continue;
|
|
273
|
+
const openEsc = open.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
274
|
+
const closeEsc = close.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
275
|
+
result = result.replace(new RegExp(`${openEsc}([^${closeEsc}]+)${closeEsc}`, 'g'), (_, content) => {
|
|
276
|
+
return `${colors.special}${open}${content}${close}${colors.default}`;
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
// Arrow labels
|
|
280
|
+
result = result.replace(/\|([^|]+)\|/g, (_, content) => {
|
|
281
|
+
return `${colors.special}|${content}|${colors.default}`;
|
|
282
|
+
});
|
|
283
|
+
return result;
|
|
284
|
+
}).join("\n");
|
|
285
|
+
return {
|
|
286
|
+
html: highlighted + colors.reset,
|
|
287
|
+
theme: "mermaid",
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
// Standard code highlighting
|
|
291
|
+
const KEYWORDS = new Set([
|
|
292
|
+
"function", "const", "let", "var", "return", "if", "else", "for", "while",
|
|
293
|
+
"class", "interface", "type", "import", "export", "from", "async", "await",
|
|
294
|
+
"try", "catch", "throw", "new", "this", "extends", "implements", "static",
|
|
295
|
+
"public", "private", "protected", "readonly", "abstract", "enum", "namespace",
|
|
296
|
+
]);
|
|
297
|
+
const TYPES = new Set([
|
|
298
|
+
"string", "number", "boolean", "void", "null", "undefined", "any", "never",
|
|
299
|
+
"object", "symbol", "bigint", "true", "false",
|
|
300
|
+
]);
|
|
301
|
+
// Simple tokenization
|
|
302
|
+
const lines = code.split("\n");
|
|
303
|
+
const highlighted = lines.map(line => {
|
|
304
|
+
// Comments
|
|
305
|
+
if (line.trim().startsWith("//") || line.trim().startsWith("#")) {
|
|
306
|
+
return `${colors.comment}${line}${colors.reset}`;
|
|
307
|
+
}
|
|
308
|
+
// Replace strings
|
|
309
|
+
let result = line.replace(/(["'`])(?:(?!\1)[^\\]|\\.)*?\1/g, match => {
|
|
310
|
+
return `${colors.string}${match}${colors.default}`;
|
|
311
|
+
});
|
|
312
|
+
// Replace numbers
|
|
313
|
+
result = result.replace(/\b(\d+\.?\d*)\b/g, `${colors.number}$1${colors.default}`);
|
|
314
|
+
// Replace keywords
|
|
315
|
+
result = result.replace(/\b([a-z]+)\b/gi, (match) => {
|
|
316
|
+
if (KEYWORDS.has(match)) {
|
|
317
|
+
return `${colors.keyword}${match}${colors.default}`;
|
|
318
|
+
}
|
|
319
|
+
if (TYPES.has(match)) {
|
|
320
|
+
return `${colors.type}${match}${colors.default}`;
|
|
321
|
+
}
|
|
322
|
+
return match;
|
|
323
|
+
});
|
|
324
|
+
// Function names (before parentheses)
|
|
325
|
+
result = result.replace(/\b([a-zA-Z_][a-zA-Z0-9_]*)\s*\(/g, (_, name) => {
|
|
326
|
+
return `${colors.function}${name}${colors.default}(`;
|
|
327
|
+
});
|
|
328
|
+
return result;
|
|
329
|
+
}).join("\n");
|
|
330
|
+
return {
|
|
331
|
+
html: highlighted + colors.reset,
|
|
332
|
+
theme: "fallback",
|
|
333
|
+
};
|
|
334
|
+
},
|
|
335
|
+
highlight_markdown: (markdown) => {
|
|
336
|
+
// Simple markdown highlighting - just return as-is with reset
|
|
337
|
+
// Full nested code block highlighting requires native module
|
|
338
|
+
return {
|
|
339
|
+
html: markdown + "\x1b[0m",
|
|
340
|
+
theme: "fallback",
|
|
341
|
+
};
|
|
342
|
+
},
|
|
343
|
+
highlight_diff: (oldText, newText, options) => {
|
|
344
|
+
// Simple line-based diff with ANSI colors
|
|
345
|
+
const GREEN = "\x1b[38;2;163;190;140m";
|
|
346
|
+
const RED = "\x1b[38;2;191;97;106m";
|
|
347
|
+
const DIM = "\x1b[38;2;108;153;139m";
|
|
348
|
+
const CYAN = "\x1b[38;2;143;161;179m";
|
|
349
|
+
const RESET = "\x1b[0m";
|
|
350
|
+
const oldLines = oldText.split("\n");
|
|
351
|
+
const newLines = newText.split("\n");
|
|
352
|
+
let output = "";
|
|
353
|
+
let additions = 0;
|
|
354
|
+
let deletions = 0;
|
|
355
|
+
let hunks = 0;
|
|
356
|
+
// File header
|
|
357
|
+
if (options?.file_path) {
|
|
358
|
+
output += `${CYAN}${options.file_path}${RESET}\n`;
|
|
359
|
+
}
|
|
360
|
+
// Simple LCS-based diff
|
|
361
|
+
const lcs = [];
|
|
362
|
+
const dp = Array.from({ length: oldLines.length + 1 }, () => Array.from({ length: newLines.length + 1 }, () => 0));
|
|
363
|
+
for (let i = 0; i <= oldLines.length; i++) {
|
|
364
|
+
for (let j = 0; j <= newLines.length; j++) {
|
|
365
|
+
if (i === 0 || j === 0) {
|
|
366
|
+
dp[i][j] = 0;
|
|
367
|
+
}
|
|
368
|
+
else if (oldLines[i - 1] === newLines[j - 1]) {
|
|
369
|
+
dp[i][j] = dp[i - 1][j - 1] + 1;
|
|
370
|
+
}
|
|
371
|
+
else {
|
|
372
|
+
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
// Backtrack for LCS
|
|
377
|
+
let i = oldLines.length;
|
|
378
|
+
let j = newLines.length;
|
|
379
|
+
const lcsSet = new Set();
|
|
380
|
+
while (i > 0 && j > 0) {
|
|
381
|
+
if (oldLines[i - 1] === newLines[j - 1]) {
|
|
382
|
+
lcsSet.add(`${i - 1}:${j - 1}`);
|
|
383
|
+
lcs.unshift(oldLines[i - 1]);
|
|
384
|
+
i--;
|
|
385
|
+
j--;
|
|
386
|
+
}
|
|
387
|
+
else if (dp[i - 1][j] > dp[i][j - 1]) {
|
|
388
|
+
i--;
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
j--;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
// Build diff output
|
|
395
|
+
let oldIdx = 0;
|
|
396
|
+
let newIdx = 0;
|
|
397
|
+
let lcsIdx = 0;
|
|
398
|
+
while (oldIdx < oldLines.length || newIdx < newLines.length) {
|
|
399
|
+
// Skip matching lines
|
|
400
|
+
while (lcsIdx < lcs.length &&
|
|
401
|
+
oldIdx < oldLines.length &&
|
|
402
|
+
newIdx < newLines.length &&
|
|
403
|
+
oldLines[oldIdx] === lcs[lcsIdx] &&
|
|
404
|
+
newLines[newIdx] === lcs[lcsIdx]) {
|
|
405
|
+
oldIdx++;
|
|
406
|
+
newIdx++;
|
|
407
|
+
lcsIdx++;
|
|
408
|
+
}
|
|
409
|
+
const oldStart = oldIdx + 1;
|
|
410
|
+
const newStart = newIdx + 1;
|
|
411
|
+
let oldCount = 0;
|
|
412
|
+
let newCount = 0;
|
|
413
|
+
const hunkLines = [];
|
|
414
|
+
// Collect removed lines
|
|
415
|
+
while (oldIdx < oldLines.length &&
|
|
416
|
+
(lcsIdx >= lcs.length || oldLines[oldIdx] !== lcs[lcsIdx])) {
|
|
417
|
+
hunkLines.push(`${RED}-${oldLines[oldIdx]}${RESET}`);
|
|
418
|
+
oldIdx++;
|
|
419
|
+
oldCount++;
|
|
420
|
+
deletions++;
|
|
421
|
+
}
|
|
422
|
+
// Collect added lines
|
|
423
|
+
while (newIdx < newLines.length &&
|
|
424
|
+
(lcsIdx >= lcs.length || newLines[newIdx] !== lcs[lcsIdx])) {
|
|
425
|
+
hunkLines.push(`${GREEN}+${newLines[newIdx]}${RESET}`);
|
|
426
|
+
newIdx++;
|
|
427
|
+
newCount++;
|
|
428
|
+
additions++;
|
|
429
|
+
}
|
|
430
|
+
if (oldCount > 0 || newCount > 0) {
|
|
431
|
+
hunks++;
|
|
432
|
+
output += `${DIM}@@ -${oldStart},${oldCount} +${newStart},${newCount} @@${RESET}\n`;
|
|
433
|
+
output += hunkLines.join("\n") + "\n";
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
return { output, additions, deletions, hunks };
|
|
437
|
+
},
|
|
438
|
+
search_files: (pattern, path, options) => {
|
|
439
|
+
// Simple grep fallback
|
|
440
|
+
return {
|
|
441
|
+
matches: [],
|
|
442
|
+
total_count: 0,
|
|
443
|
+
files_searched: 0,
|
|
444
|
+
};
|
|
445
|
+
},
|
|
446
|
+
count_tokens: (text) => {
|
|
447
|
+
// Approximate token count: ~4 chars per token
|
|
448
|
+
return Math.ceil(text.length / 4);
|
|
449
|
+
},
|
|
450
|
+
calculate_diff: (oldText, newText) => {
|
|
451
|
+
// Simple line-based diff
|
|
452
|
+
const oldLines = oldText.split("\n");
|
|
453
|
+
const newLines = newText.split("\n");
|
|
454
|
+
const hunks = [];
|
|
455
|
+
// Very simple diff - just show all changes as one hunk
|
|
456
|
+
if (oldText !== newText) {
|
|
457
|
+
hunks.push({
|
|
458
|
+
oldStart: 1,
|
|
459
|
+
oldLines: oldLines.length,
|
|
460
|
+
newStart: 1,
|
|
461
|
+
newLines: newLines.length,
|
|
462
|
+
content: `- ${oldLines.join("\n- ")}\n+ ${newLines.join("\n+ ")}`,
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
return hunks;
|
|
466
|
+
},
|
|
467
|
+
compact_content: (content, maxTokens, strategy = "truncate") => {
|
|
468
|
+
const charsPerToken = 4;
|
|
469
|
+
const maxChars = maxTokens * charsPerToken;
|
|
470
|
+
if (content.length <= maxChars) {
|
|
471
|
+
return content;
|
|
472
|
+
}
|
|
473
|
+
switch (strategy) {
|
|
474
|
+
case "truncate":
|
|
475
|
+
return (content.slice(0, maxChars / 2) +
|
|
476
|
+
"\n\n... [truncated] ...\n\n" +
|
|
477
|
+
content.slice(-maxChars / 2));
|
|
478
|
+
case "summarize":
|
|
479
|
+
// Return first and last sections
|
|
480
|
+
const quarter = Math.floor(maxChars / 4);
|
|
481
|
+
return ("=== BEGINNING ===\n" +
|
|
482
|
+
content.slice(0, quarter) +
|
|
483
|
+
"\n\n=== END ===\n" +
|
|
484
|
+
content.slice(-quarter));
|
|
485
|
+
case "extract":
|
|
486
|
+
// Return important lines only
|
|
487
|
+
const lines = content.split("\n");
|
|
488
|
+
const important = lines.filter((line) => line.trim().startsWith("#") ||
|
|
489
|
+
line.trim().startsWith("function") ||
|
|
490
|
+
line.trim().startsWith("const") ||
|
|
491
|
+
line.trim().startsWith("class") ||
|
|
492
|
+
line.trim().startsWith("export") ||
|
|
493
|
+
line.trim().startsWith("import"));
|
|
494
|
+
return important.slice(0, maxChars / 50).join("\n");
|
|
495
|
+
default:
|
|
496
|
+
return content.slice(0, maxChars);
|
|
497
|
+
}
|
|
498
|
+
},
|
|
499
|
+
// Multi-file editing fallback implementation
|
|
500
|
+
validate_multi_edits: (edits) => {
|
|
501
|
+
const errors = [];
|
|
502
|
+
const fileContents = new Map();
|
|
503
|
+
const fs = require('fs');
|
|
504
|
+
for (const edit of edits) {
|
|
505
|
+
// Check file exists
|
|
506
|
+
try {
|
|
507
|
+
if (!fs.existsSync(edit.filePath)) {
|
|
508
|
+
errors.push(`File not found: ${edit.filePath}`);
|
|
509
|
+
continue;
|
|
510
|
+
}
|
|
511
|
+
// Load file content if not already loaded
|
|
512
|
+
if (!fileContents.has(edit.filePath)) {
|
|
513
|
+
const content = fs.readFileSync(edit.filePath, 'utf-8');
|
|
514
|
+
fileContents.set(edit.filePath, content);
|
|
515
|
+
}
|
|
516
|
+
const content = fileContents.get(edit.filePath);
|
|
517
|
+
// Check oldString exists
|
|
518
|
+
if (!content.includes(edit.oldString)) {
|
|
519
|
+
errors.push(`String not found in ${edit.filePath}: "${truncateString(edit.oldString, 50)}"`);
|
|
520
|
+
continue;
|
|
521
|
+
}
|
|
522
|
+
// Check uniqueness if not replaceAll
|
|
523
|
+
if (!edit.replaceAll) {
|
|
524
|
+
const count = (content.match(new RegExp(escapeRegex(edit.oldString), "g")) || []).length;
|
|
525
|
+
if (count > 1) {
|
|
526
|
+
errors.push(`String appears ${count} times in ${edit.filePath}. Use replaceAll or provide more context.`);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
catch (err) {
|
|
531
|
+
errors.push(`Error reading ${edit.filePath}: ${err}`);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
return errors;
|
|
535
|
+
},
|
|
536
|
+
preview_multi_edits: (edits) => {
|
|
537
|
+
const results = [];
|
|
538
|
+
const fileReplacements = new Map();
|
|
539
|
+
const fs = require('fs');
|
|
540
|
+
for (const edit of edits) {
|
|
541
|
+
try {
|
|
542
|
+
if (!fs.existsSync(edit.filePath))
|
|
543
|
+
continue;
|
|
544
|
+
const content = fs.readFileSync(edit.filePath, 'utf-8');
|
|
545
|
+
const count = edit.replaceAll
|
|
546
|
+
? (content.match(new RegExp(escapeRegex(edit.oldString), "g")) || []).length
|
|
547
|
+
: 1;
|
|
548
|
+
fileReplacements.set(edit.filePath, (fileReplacements.get(edit.filePath) || 0) + count);
|
|
549
|
+
}
|
|
550
|
+
catch {
|
|
551
|
+
// Skip files that can't be read
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
for (const [filePath, replacementCount] of fileReplacements) {
|
|
555
|
+
results.push({ filePath, replacementCount });
|
|
556
|
+
}
|
|
557
|
+
return results;
|
|
558
|
+
},
|
|
559
|
+
apply_multi_edits: (edits) => {
|
|
560
|
+
// First validate all edits
|
|
561
|
+
const errors = getFallbackModule().validate_multi_edits(edits);
|
|
562
|
+
if (errors.length > 0) {
|
|
563
|
+
return {
|
|
564
|
+
success: false,
|
|
565
|
+
filesModified: [],
|
|
566
|
+
totalReplacements: 0,
|
|
567
|
+
error: errors.join("\n"),
|
|
568
|
+
rolledBack: false,
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
// Create backups
|
|
572
|
+
const backups = new Map();
|
|
573
|
+
const uniqueFiles = new Set(edits.map(e => e.filePath));
|
|
574
|
+
const fs = require('fs');
|
|
575
|
+
for (const filePath of uniqueFiles) {
|
|
576
|
+
try {
|
|
577
|
+
backups.set(filePath, fs.readFileSync(filePath, 'utf-8'));
|
|
578
|
+
}
|
|
579
|
+
catch (err) {
|
|
580
|
+
return {
|
|
581
|
+
success: false,
|
|
582
|
+
filesModified: [],
|
|
583
|
+
totalReplacements: 0,
|
|
584
|
+
error: `Failed to backup ${filePath}: ${err}`,
|
|
585
|
+
rolledBack: false,
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
// Apply edits
|
|
590
|
+
const currentContents = new Map();
|
|
591
|
+
for (const [path, content] of backups) {
|
|
592
|
+
currentContents.set(path, content);
|
|
593
|
+
}
|
|
594
|
+
let totalReplacements = 0;
|
|
595
|
+
for (const edit of edits) {
|
|
596
|
+
const content = currentContents.get(edit.filePath);
|
|
597
|
+
if (!content)
|
|
598
|
+
continue;
|
|
599
|
+
if (edit.replaceAll) {
|
|
600
|
+
const count = (content.match(new RegExp(escapeRegex(edit.oldString), "g")) || []).length;
|
|
601
|
+
currentContents.set(edit.filePath, content.split(edit.oldString).join(edit.newString));
|
|
602
|
+
totalReplacements += count;
|
|
603
|
+
}
|
|
604
|
+
else {
|
|
605
|
+
currentContents.set(edit.filePath, content.replace(edit.oldString, edit.newString));
|
|
606
|
+
totalReplacements += 1;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
// Write all files
|
|
610
|
+
const filesModified = [];
|
|
611
|
+
for (const [path, newContent] of currentContents) {
|
|
612
|
+
const originalContent = backups.get(path);
|
|
613
|
+
if (newContent !== originalContent) {
|
|
614
|
+
try {
|
|
615
|
+
Bun.write(path, newContent);
|
|
616
|
+
filesModified.push(path);
|
|
617
|
+
}
|
|
618
|
+
catch (err) {
|
|
619
|
+
// Rollback on failure
|
|
620
|
+
for (const [rollbackPath, rollbackContent] of backups) {
|
|
621
|
+
try {
|
|
622
|
+
Bun.write(rollbackPath, rollbackContent);
|
|
623
|
+
}
|
|
624
|
+
catch {
|
|
625
|
+
// Ignore rollback errors
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
return {
|
|
629
|
+
success: false,
|
|
630
|
+
filesModified: [],
|
|
631
|
+
totalReplacements: 0,
|
|
632
|
+
error: `Failed to write ${path}: ${err}. All changes rolled back.`,
|
|
633
|
+
rolledBack: true,
|
|
634
|
+
};
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
return {
|
|
639
|
+
success: true,
|
|
640
|
+
filesModified: filesModified,
|
|
641
|
+
totalReplacements: totalReplacements,
|
|
642
|
+
error: undefined,
|
|
643
|
+
rolledBack: false,
|
|
644
|
+
};
|
|
645
|
+
},
|
|
646
|
+
// Tool analysis fallback implementations
|
|
647
|
+
count_tool_use: (messages) => {
|
|
648
|
+
const counts = {};
|
|
649
|
+
for (const msg of messages) {
|
|
650
|
+
if (msg.tool_use) {
|
|
651
|
+
for (const tool of msg.tool_use) {
|
|
652
|
+
counts[tool.name] = (counts[tool.name] || 0) + 1;
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
return counts;
|
|
657
|
+
},
|
|
658
|
+
find_tool_pairs: (messages, _windowSize) => {
|
|
659
|
+
const pairs = {};
|
|
660
|
+
for (const msg of messages) {
|
|
661
|
+
if (msg.tool_use && msg.tool_use.length >= 2) {
|
|
662
|
+
for (let i = 0; i < msg.tool_use.length - 1; i++) {
|
|
663
|
+
const tool1 = msg.tool_use[i]?.name;
|
|
664
|
+
const tool2 = msg.tool_use[i + 1]?.name;
|
|
665
|
+
if (tool1 && tool2) {
|
|
666
|
+
if (!pairs[tool1])
|
|
667
|
+
pairs[tool1] = {};
|
|
668
|
+
pairs[tool1][tool2] = (pairs[tool1][tool2] || 0) + 1;
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
return pairs;
|
|
674
|
+
},
|
|
675
|
+
find_common_patterns: (messages) => {
|
|
676
|
+
const patterns = [];
|
|
677
|
+
const toolPairs = new Map();
|
|
678
|
+
let totalPairs = 0;
|
|
679
|
+
for (const msg of messages) {
|
|
680
|
+
if (msg.tool_use && msg.tool_use.length >= 2) {
|
|
681
|
+
for (let i = 0; i < msg.tool_use.length - 1; i++) {
|
|
682
|
+
const name1 = msg.tool_use[i]?.name;
|
|
683
|
+
const name2 = msg.tool_use[i + 1]?.name;
|
|
684
|
+
if (name1 && name2) {
|
|
685
|
+
const key = `${name1}|${name2}`;
|
|
686
|
+
toolPairs.set(key, (toolPairs.get(key) || 0) + 1);
|
|
687
|
+
totalPairs++;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
for (const [key, count] of toolPairs) {
|
|
693
|
+
const [tool1, tool2] = key.split("|");
|
|
694
|
+
patterns.push({
|
|
695
|
+
tools: [tool1, tool2],
|
|
696
|
+
count,
|
|
697
|
+
percentage: totalPairs > 0 ? (count / totalPairs) * 100 : 0,
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
return patterns.sort((a, b) => b.count - a.count).slice(0, 10);
|
|
701
|
+
},
|
|
702
|
+
// ===== Cognitive Security Fallbacks =====
|
|
703
|
+
// Action Module
|
|
704
|
+
classify_operation: (operation, domain, target, reasoning) => {
|
|
705
|
+
const id = `action_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
706
|
+
let actionType = "observe";
|
|
707
|
+
let riskLevel = 1;
|
|
708
|
+
let hasSideEffects = false;
|
|
709
|
+
let requiresApproval = false;
|
|
710
|
+
const op = operation.toLowerCase();
|
|
711
|
+
if (op.includes("write") || op.includes("edit") || op.includes("create") || op.includes("delete")) {
|
|
712
|
+
actionType = "modify";
|
|
713
|
+
riskLevel = 3;
|
|
714
|
+
hasSideEffects = true;
|
|
715
|
+
requiresApproval = true;
|
|
716
|
+
}
|
|
717
|
+
else if (op.includes("execute") || op.includes("run") || op.includes("bash")) {
|
|
718
|
+
actionType = "execute";
|
|
719
|
+
riskLevel = 4;
|
|
720
|
+
hasSideEffects = true;
|
|
721
|
+
requiresApproval = true;
|
|
722
|
+
}
|
|
723
|
+
else if (op.includes("send") || op.includes("post") || op.includes("transmit")) {
|
|
724
|
+
actionType = "communicate";
|
|
725
|
+
riskLevel = 2;
|
|
726
|
+
hasSideEffects = true;
|
|
727
|
+
requiresApproval = domain === "external";
|
|
728
|
+
}
|
|
729
|
+
else if (op.includes("read") || op.includes("get") || op.includes("list") || op.includes("search")) {
|
|
730
|
+
actionType = "observe";
|
|
731
|
+
riskLevel = 1;
|
|
732
|
+
hasSideEffects = false;
|
|
733
|
+
requiresApproval = false;
|
|
734
|
+
}
|
|
735
|
+
return {
|
|
736
|
+
id,
|
|
737
|
+
actionType,
|
|
738
|
+
domain,
|
|
739
|
+
operation,
|
|
740
|
+
target: target || null,
|
|
741
|
+
flowDirection: "outbound",
|
|
742
|
+
riskLevel,
|
|
743
|
+
hasSideEffects,
|
|
744
|
+
requiresApproval,
|
|
745
|
+
reasoning: reasoning || `Classified as ${actionType} based on operation name`,
|
|
746
|
+
timestamp: Date.now(),
|
|
747
|
+
metadata: null,
|
|
748
|
+
};
|
|
749
|
+
},
|
|
750
|
+
get_action_types: () => ["modify", "execute", "communicate", "transfer", "observe", "create", "delete"],
|
|
751
|
+
get_action_risk_levels: () => [
|
|
752
|
+
{ actionType: "observe", riskLevel: 1 },
|
|
753
|
+
{ actionType: "communicate", riskLevel: 2 },
|
|
754
|
+
{ actionType: "create", riskLevel: 3 },
|
|
755
|
+
{ actionType: "modify", riskLevel: 3 },
|
|
756
|
+
{ actionType: "transfer", riskLevel: 4 },
|
|
757
|
+
{ actionType: "execute", riskLevel: 4 },
|
|
758
|
+
{ actionType: "delete", riskLevel: 5 },
|
|
759
|
+
],
|
|
760
|
+
create_deny_all_policy: () => ({
|
|
761
|
+
id: "deny_all",
|
|
762
|
+
description: "Deny all actions",
|
|
763
|
+
actionTypes: [],
|
|
764
|
+
domains: [],
|
|
765
|
+
operations: [],
|
|
766
|
+
effect: "deny",
|
|
767
|
+
priority: 1000,
|
|
768
|
+
enabled: true,
|
|
769
|
+
}),
|
|
770
|
+
create_observe_only_policy: () => ({
|
|
771
|
+
id: "observe_only",
|
|
772
|
+
description: "Allow observe actions only",
|
|
773
|
+
actionTypes: ["observe"],
|
|
774
|
+
domains: [],
|
|
775
|
+
operations: [],
|
|
776
|
+
effect: "allow",
|
|
777
|
+
priority: 100,
|
|
778
|
+
enabled: true,
|
|
779
|
+
}),
|
|
780
|
+
create_transfer_approval_policy: () => ({
|
|
781
|
+
id: "transfer_approval",
|
|
782
|
+
description: "Require approval for transfer actions",
|
|
783
|
+
actionTypes: ["transfer"],
|
|
784
|
+
domains: [],
|
|
785
|
+
operations: [],
|
|
786
|
+
effect: "require_approval",
|
|
787
|
+
priority: 200,
|
|
788
|
+
enabled: true,
|
|
789
|
+
}),
|
|
790
|
+
// Intent Module
|
|
791
|
+
cs_generate_keypair: () => ({
|
|
792
|
+
privateKey: `private_${Math.random().toString(36).slice(2)}_${Date.now()}`,
|
|
793
|
+
publicKey: `public_${Math.random().toString(36).slice(2)}_${Date.now()}`,
|
|
794
|
+
}),
|
|
795
|
+
cs_sign_intent: (intent, _privateKey) => {
|
|
796
|
+
return { ...intent, signature: `sig_${Date.now()}`, signedBy: "fallback" };
|
|
797
|
+
},
|
|
798
|
+
cs_verify_intent: (_intent) => ({
|
|
799
|
+
valid: true,
|
|
800
|
+
error: null,
|
|
801
|
+
signatureValid: true,
|
|
802
|
+
contentIntact: true,
|
|
803
|
+
expired: false,
|
|
804
|
+
}),
|
|
805
|
+
cs_hash_intent: (intent) => {
|
|
806
|
+
const str = JSON.stringify(intent);
|
|
807
|
+
let hash = 0;
|
|
808
|
+
for (let i = 0; i < str.length; i++) {
|
|
809
|
+
const char = str.charCodeAt(i);
|
|
810
|
+
hash = ((hash << 5) - hash) + char;
|
|
811
|
+
hash = hash & hash;
|
|
812
|
+
}
|
|
813
|
+
return Math.abs(hash).toString(16).padStart(16, '0');
|
|
814
|
+
},
|
|
815
|
+
cs_intents_equivalent: (intent1, intent2) => {
|
|
816
|
+
const stripSignature = (i) => {
|
|
817
|
+
const { signature, signedBy, ...rest } = i;
|
|
818
|
+
return rest;
|
|
819
|
+
};
|
|
820
|
+
return JSON.stringify(stripSignature(intent1)) === JSON.stringify(stripSignature(intent2));
|
|
821
|
+
},
|
|
822
|
+
cs_score_alignment: (_action, _intent) => ({
|
|
823
|
+
score: 0.8,
|
|
824
|
+
reasoning: "Fallback alignment score - native module not available",
|
|
825
|
+
servesGoals: [],
|
|
826
|
+
hindersGoals: [],
|
|
827
|
+
boundaryConcerns: [],
|
|
828
|
+
confidence: 0.5,
|
|
829
|
+
shouldBlock: false,
|
|
830
|
+
requiresReview: false,
|
|
831
|
+
}),
|
|
832
|
+
cs_batch_score_alignment: (actions, intent) => {
|
|
833
|
+
return actions.map(() => ({
|
|
834
|
+
score: 0.8,
|
|
835
|
+
reasoning: "Fallback alignment score",
|
|
836
|
+
servesGoals: [],
|
|
837
|
+
hindersGoals: [],
|
|
838
|
+
boundaryConcerns: [],
|
|
839
|
+
confidence: 0.5,
|
|
840
|
+
shouldBlock: false,
|
|
841
|
+
requiresReview: false,
|
|
842
|
+
}));
|
|
843
|
+
},
|
|
844
|
+
cs_check_sequence_violations: (_actions, _intent) => [],
|
|
845
|
+
cs_load_intent: (_path) => {
|
|
846
|
+
throw new Error("Native module required for cs_load_intent");
|
|
847
|
+
},
|
|
848
|
+
cs_save_intent: (_intent, _path) => {
|
|
849
|
+
throw new Error("Native module required for cs_save_intent");
|
|
850
|
+
},
|
|
851
|
+
cs_parse_intent: (json) => JSON.parse(json),
|
|
852
|
+
cs_serialize_intent: (intent) => JSON.stringify(intent, null, 2),
|
|
853
|
+
cs_validate_intent: (intent) => {
|
|
854
|
+
const errors = [];
|
|
855
|
+
const warnings = [];
|
|
856
|
+
if (!intent.id)
|
|
857
|
+
errors.push("Missing intent id");
|
|
858
|
+
if (!intent.version)
|
|
859
|
+
warnings.push("Missing version");
|
|
860
|
+
if (!intent.identity)
|
|
861
|
+
errors.push("Missing identity");
|
|
862
|
+
if (!intent.purpose)
|
|
863
|
+
errors.push("Missing purpose");
|
|
864
|
+
return {
|
|
865
|
+
valid: errors.length === 0,
|
|
866
|
+
errors,
|
|
867
|
+
warnings,
|
|
868
|
+
};
|
|
869
|
+
},
|
|
870
|
+
cs_create_data_collector_intent: (name, description) => ({
|
|
871
|
+
id: `intent_${Date.now()}`,
|
|
872
|
+
version: 1,
|
|
873
|
+
identity: {
|
|
874
|
+
name,
|
|
875
|
+
description,
|
|
876
|
+
capabilities: ["read", "list", "search"],
|
|
877
|
+
constraints: ["no_write", "no_execute", "no_network"],
|
|
878
|
+
},
|
|
879
|
+
purpose: {
|
|
880
|
+
goals: [],
|
|
881
|
+
nonGoals: ["modify_data", "execute_commands", "send_data"],
|
|
882
|
+
boundaries: [],
|
|
883
|
+
},
|
|
884
|
+
principles: {
|
|
885
|
+
values: ["transparency", "privacy"],
|
|
886
|
+
priorities: ["safety_first"],
|
|
887
|
+
forbidden: ["exfiltration", "modification"],
|
|
888
|
+
},
|
|
889
|
+
createdAt: Date.now(),
|
|
890
|
+
}),
|
|
891
|
+
cs_merge_intents: (base, override) => ({ ...base, ...override }),
|
|
892
|
+
cs_analyze_corruption: (_snapshot, _intent) => ({
|
|
893
|
+
riskScore: 0,
|
|
894
|
+
indicators: [],
|
|
895
|
+
recommendation: "continue",
|
|
896
|
+
explanation: "Fallback analysis - native module not available",
|
|
897
|
+
}),
|
|
898
|
+
cs_detect_drift: (_baseline, _current) => ({
|
|
899
|
+
overallDrift: 0,
|
|
900
|
+
driftFactors: [],
|
|
901
|
+
concernLevel: "none",
|
|
902
|
+
}),
|
|
903
|
+
cs_create_empty_snapshot: () => ({
|
|
904
|
+
timestamp: Date.now(),
|
|
905
|
+
actionCount: 0,
|
|
906
|
+
alignmentDistribution: { mean: 1, variance: 0, min: 1, max: 1, belowThresholdCount: 0 },
|
|
907
|
+
actionsByDomain: [],
|
|
908
|
+
actionsByType: [],
|
|
909
|
+
boundaryViolations: 0,
|
|
910
|
+
actionsBlocked: 0,
|
|
911
|
+
}),
|
|
912
|
+
cs_update_snapshot: (snapshot, _action, alignment) => {
|
|
913
|
+
const newScore = alignment?.score ?? 1;
|
|
914
|
+
const oldMean = snapshot.alignmentDistribution?.mean ?? 1;
|
|
915
|
+
const newMean = (oldMean * snapshot.actionCount + newScore) / (snapshot.actionCount + 1);
|
|
916
|
+
return {
|
|
917
|
+
...snapshot,
|
|
918
|
+
timestamp: Date.now(),
|
|
919
|
+
actionCount: snapshot.actionCount + 1,
|
|
920
|
+
alignmentDistribution: {
|
|
921
|
+
...snapshot.alignmentDistribution,
|
|
922
|
+
mean: newMean,
|
|
923
|
+
},
|
|
924
|
+
};
|
|
925
|
+
},
|
|
926
|
+
// Flow Module
|
|
927
|
+
classify_data: (content, source, tags) => {
|
|
928
|
+
let sensitivity = "internal";
|
|
929
|
+
let category = "generic";
|
|
930
|
+
if (content.includes("password") || content.includes("secret") || content.includes("key")) {
|
|
931
|
+
sensitivity = "secret";
|
|
932
|
+
category = "credentials";
|
|
933
|
+
}
|
|
934
|
+
else if (content.includes("@") && content.includes(".")) {
|
|
935
|
+
sensitivity = "confidential";
|
|
936
|
+
category = "pii";
|
|
937
|
+
}
|
|
938
|
+
return {
|
|
939
|
+
id: `data_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,
|
|
940
|
+
sensitivity,
|
|
941
|
+
category,
|
|
942
|
+
source,
|
|
943
|
+
tags,
|
|
944
|
+
can_log: sensitivity !== "secret",
|
|
945
|
+
can_transmit: sensitivity === "public" || sensitivity === "internal",
|
|
946
|
+
can_store: true,
|
|
947
|
+
expires_at: null,
|
|
948
|
+
created_at: Date.now(),
|
|
949
|
+
};
|
|
950
|
+
},
|
|
951
|
+
contains_sensitive_data: (content) => {
|
|
952
|
+
const patterns = ["password", "secret", "api_key", "token", "credential"];
|
|
953
|
+
return patterns.some(p => content.toLowerCase().includes(p));
|
|
954
|
+
},
|
|
955
|
+
redact_sensitive: (content, replacement) => {
|
|
956
|
+
const repl = replacement || "[REDACTED]";
|
|
957
|
+
return content
|
|
958
|
+
.replace(/password[=:]\s*\S+/gi, `password=${repl}`)
|
|
959
|
+
.replace(/api[_-]?key[=:]\s*\S+/gi, `api_key=${repl}`)
|
|
960
|
+
.replace(/token[=:]\s*\S+/gi, `token=${repl}`)
|
|
961
|
+
.replace(/secret[=:]\s*\S+/gi, `secret=${repl}`);
|
|
962
|
+
},
|
|
963
|
+
get_sensitivity_levels: () => [
|
|
964
|
+
{ name: "public", value: 1, description: "Publicly shareable" },
|
|
965
|
+
{ name: "internal", value: 2, description: "Internal use only" },
|
|
966
|
+
{ name: "confidential", value: 3, description: "Confidential" },
|
|
967
|
+
{ name: "secret", value: 4, description: "Highly sensitive" },
|
|
968
|
+
{ name: "top_secret", value: 5, description: "Maximum sensitivity" },
|
|
969
|
+
],
|
|
970
|
+
get_data_categories: () => [
|
|
971
|
+
{ name: "generic", description: "Generic data" },
|
|
972
|
+
{ name: "pii", description: "Personally identifiable information" },
|
|
973
|
+
{ name: "credentials", description: "Authentication credentials" },
|
|
974
|
+
{ name: "financial", description: "Financial data" },
|
|
975
|
+
{ name: "source_code", description: "Source code" },
|
|
976
|
+
{ name: "configuration", description: "Configuration data" },
|
|
977
|
+
],
|
|
978
|
+
// Flow Policy Engine
|
|
979
|
+
create_flow_policy_engine: () => ({
|
|
980
|
+
addPolicy: (_policy) => { },
|
|
981
|
+
removePolicy: (_id) => true,
|
|
982
|
+
evaluate: (_data, _source, _target) => ({
|
|
983
|
+
allowed: true,
|
|
984
|
+
reason: "Fallback: allowed by default",
|
|
985
|
+
applied_policy: null,
|
|
986
|
+
can_log: true,
|
|
987
|
+
can_transmit: true,
|
|
988
|
+
can_store: true,
|
|
989
|
+
transformations: [],
|
|
990
|
+
confidence: 0.5,
|
|
991
|
+
warnings: ["Fallback implementation - native module not available"],
|
|
992
|
+
}),
|
|
993
|
+
listPolicies: () => [],
|
|
994
|
+
setDefaultAction: (_action) => { },
|
|
995
|
+
setBlpMode: (_mode) => { },
|
|
996
|
+
}),
|
|
997
|
+
// Flow Policies
|
|
998
|
+
create_allow_all_flow_policy: () => ({
|
|
999
|
+
id: "allow_all",
|
|
1000
|
+
description: "Allow all flows",
|
|
1001
|
+
source_pattern: "*",
|
|
1002
|
+
target_pattern: "*",
|
|
1003
|
+
min_source_sensitivity: null,
|
|
1004
|
+
max_target_sensitivity: null,
|
|
1005
|
+
categories: [],
|
|
1006
|
+
effect: "allow",
|
|
1007
|
+
priority: 0,
|
|
1008
|
+
required_transforms: [],
|
|
1009
|
+
log_flow: false,
|
|
1010
|
+
require_approval: false,
|
|
1011
|
+
conditions: null,
|
|
1012
|
+
enabled: true,
|
|
1013
|
+
}),
|
|
1014
|
+
create_deny_all_flow_policy: () => ({
|
|
1015
|
+
id: "deny_all",
|
|
1016
|
+
description: "Deny all flows",
|
|
1017
|
+
source_pattern: "*",
|
|
1018
|
+
target_pattern: "*",
|
|
1019
|
+
min_source_sensitivity: null,
|
|
1020
|
+
max_target_sensitivity: null,
|
|
1021
|
+
categories: [],
|
|
1022
|
+
effect: "deny",
|
|
1023
|
+
priority: 1000,
|
|
1024
|
+
required_transforms: [],
|
|
1025
|
+
log_flow: false,
|
|
1026
|
+
require_approval: false,
|
|
1027
|
+
conditions: null,
|
|
1028
|
+
enabled: true,
|
|
1029
|
+
}),
|
|
1030
|
+
create_strict_flow_policy: () => ({
|
|
1031
|
+
id: "strict",
|
|
1032
|
+
description: "Strict flow policy",
|
|
1033
|
+
source_pattern: "*",
|
|
1034
|
+
target_pattern: "*",
|
|
1035
|
+
min_source_sensitivity: "internal",
|
|
1036
|
+
max_target_sensitivity: null,
|
|
1037
|
+
categories: [],
|
|
1038
|
+
effect: "transform",
|
|
1039
|
+
priority: 500,
|
|
1040
|
+
required_transforms: ["redact_sensitive"],
|
|
1041
|
+
log_flow: true,
|
|
1042
|
+
require_approval: true,
|
|
1043
|
+
conditions: null,
|
|
1044
|
+
enabled: true,
|
|
1045
|
+
}),
|
|
1046
|
+
// Flow Tracker
|
|
1047
|
+
create_flow_tracker: () => ({
|
|
1048
|
+
record: (_data, _source, _target, _direction, _validation, _sessionId, _actionId) => ({
|
|
1049
|
+
id: `flow_${Date.now()}`,
|
|
1050
|
+
data_id: _data.id,
|
|
1051
|
+
source_domain: _source,
|
|
1052
|
+
target_domain: _target,
|
|
1053
|
+
direction: _direction,
|
|
1054
|
+
allowed: _validation.allowed,
|
|
1055
|
+
reason: _validation.reason,
|
|
1056
|
+
policy_id: _validation.applied_policy || null,
|
|
1057
|
+
session_id: _sessionId,
|
|
1058
|
+
action_id: _actionId,
|
|
1059
|
+
timestamp: Date.now(),
|
|
1060
|
+
data_hash: "",
|
|
1061
|
+
}),
|
|
1062
|
+
getFlow: (_id) => null,
|
|
1063
|
+
getLineage: (_dataId) => [],
|
|
1064
|
+
bySource: (_domain) => [],
|
|
1065
|
+
byTarget: (_domain) => [],
|
|
1066
|
+
bySession: (_sessionId) => [],
|
|
1067
|
+
blocked: () => [],
|
|
1068
|
+
allowed: () => [],
|
|
1069
|
+
recent: (_limit) => [],
|
|
1070
|
+
stats: () => ({
|
|
1071
|
+
total_flows: 0,
|
|
1072
|
+
allowed_count: 0,
|
|
1073
|
+
blocked_count: 0,
|
|
1074
|
+
by_direction: [],
|
|
1075
|
+
by_source_domain: [],
|
|
1076
|
+
by_target_domain: [],
|
|
1077
|
+
first_timestamp: Date.now(),
|
|
1078
|
+
last_timestamp: Date.now(),
|
|
1079
|
+
}),
|
|
1080
|
+
domainStats: (_domain) => null,
|
|
1081
|
+
count: () => 0,
|
|
1082
|
+
clear: () => { },
|
|
1083
|
+
setMaxFlows: (_max) => { },
|
|
1084
|
+
exportJsonl: () => "",
|
|
1085
|
+
}),
|
|
1086
|
+
// Leak Prevention
|
|
1087
|
+
create_leak_prevention: () => ({
|
|
1088
|
+
check: (_content, _channel) => ({
|
|
1089
|
+
action: "allow",
|
|
1090
|
+
detections: [],
|
|
1091
|
+
channel_allowed: true,
|
|
1092
|
+
checked_at: Date.now(),
|
|
1093
|
+
}),
|
|
1094
|
+
sanitize: (content) => content
|
|
1095
|
+
.replace(/password[=:]\s*\S+/gi, "password=[REDACTED]")
|
|
1096
|
+
.replace(/api[_-]?key[=:]\s*\S+/gi, "api_key=[REDACTED]")
|
|
1097
|
+
.replace(/token[=:]\s*\S+/gi, "token=[REDACTED]")
|
|
1098
|
+
.replace(/secret[=:]\s*\S+/gi, "secret=[REDACTED]"),
|
|
1099
|
+
registerSensitive: (_data) => { },
|
|
1100
|
+
addChannel: (_channel) => { },
|
|
1101
|
+
removeChannel: (_channel) => { },
|
|
1102
|
+
setMode: (_mode) => { },
|
|
1103
|
+
stats: () => ({
|
|
1104
|
+
total_checks: 0,
|
|
1105
|
+
blocked_count: 0,
|
|
1106
|
+
alert_count: 0,
|
|
1107
|
+
by_leak_type: {},
|
|
1108
|
+
}),
|
|
1109
|
+
clearSensitive: () => { },
|
|
1110
|
+
}),
|
|
1111
|
+
// Leak Prevention helpers
|
|
1112
|
+
check_for_leaks: (content, channel) => ({
|
|
1113
|
+
action: "allow",
|
|
1114
|
+
detections: [],
|
|
1115
|
+
channel_allowed: true,
|
|
1116
|
+
checked_at: Date.now(),
|
|
1117
|
+
}),
|
|
1118
|
+
sanitize_content: (content) => content
|
|
1119
|
+
.replace(/password[=:]\s*\S+/gi, "password=[REDACTED]")
|
|
1120
|
+
.replace(/api[_-]?key[=:]\s*\S+/gi, "api_key=[REDACTED]")
|
|
1121
|
+
.replace(/token[=:]\s*\S+/gi, "token=[REDACTED]")
|
|
1122
|
+
.replace(/secret[=:]\s*\S+/gi, "secret=[REDACTED]"),
|
|
1123
|
+
// Taint Tracker
|
|
1124
|
+
create_taint_tracker: () => ({
|
|
1125
|
+
registerSource: (_type, _sensitivity, _tags) => `source_${Date.now()}`,
|
|
1126
|
+
taint: (_sourceId, _data, _locationType, _identifier) => `taint_${Date.now()}`,
|
|
1127
|
+
propagate: (_sourceTaintId, _newData, _locationType, _identifier, _propagationType, _operation) => `prop_${Date.now()}`,
|
|
1128
|
+
canFlow: (_taintId, _sink) => ({ allowed: true, reason: "Fallback", requires_sanitization: false }),
|
|
1129
|
+
isTainted: (_data) => false,
|
|
1130
|
+
getTaint: (_taintId) => null,
|
|
1131
|
+
stats: () => ({
|
|
1132
|
+
total_sources: 0,
|
|
1133
|
+
total_tainted: 0,
|
|
1134
|
+
total_propagations: 0,
|
|
1135
|
+
by_source_type: {},
|
|
1136
|
+
by_sensitivity: {},
|
|
1137
|
+
}),
|
|
1138
|
+
clear: (_taintId) => false,
|
|
1139
|
+
clearAll: () => { },
|
|
1140
|
+
}),
|
|
1141
|
+
// Quant Functions (stubs)
|
|
1142
|
+
quant_version: () => "0.1.0-fallback",
|
|
1143
|
+
quant_ohlcv_new: (_ts, _o, _h, _l, _c, _v) => JSON.stringify({ open: _o, high: _h, low: _l, close: _c, volume: _v }),
|
|
1144
|
+
quant_amm_new: (_poolYes, _poolNo, _fee) => JSON.stringify({ poolYes: _poolYes, poolNo: _poolNo, fee: _fee }),
|
|
1145
|
+
quant_amm_calculate_cost: (_poolYes, _poolNo, _buyYes, _shares) => JSON.stringify({ cost: 0 }),
|
|
1146
|
+
quant_amm_price_impact: (_poolYes, _poolNo, _buyYes, _shares) => JSON.stringify({ impact: 0 }),
|
|
1147
|
+
quant_lmsr_price: (_yesShares, _noShares, _b) => JSON.stringify({ price: 0.5 }),
|
|
1148
|
+
quant_lmsr_cost: (_yesShares, _noShares, _b, _buyYes, _shares) => JSON.stringify({ cost: 0 }),
|
|
1149
|
+
quant_detect_arbitrage: (_yesPrice, _noPrice) => JSON.stringify({ hasArbitrage: false }),
|
|
1150
|
+
quant_convert_odds: (_value, _fromType) => JSON.stringify({ decimal: 0 }),
|
|
1151
|
+
quant_mean: (_data) => 0,
|
|
1152
|
+
quant_std_dev: (_data) => 0,
|
|
1153
|
+
quant_variance: (_data) => 0,
|
|
1154
|
+
quant_correlation: (_x, _y) => 0,
|
|
1155
|
+
// Terminal Input (fallback - uses Node.js stdin directly)
|
|
1156
|
+
create_terminal: () => {
|
|
1157
|
+
let inRawMode = false;
|
|
1158
|
+
return {
|
|
1159
|
+
get isRawMode() { return inRawMode; },
|
|
1160
|
+
enterRawMode() {
|
|
1161
|
+
if (process.stdin.isTTY && !inRawMode) {
|
|
1162
|
+
process.stdin.setRawMode(true);
|
|
1163
|
+
process.stdin.resume();
|
|
1164
|
+
inRawMode = true;
|
|
1165
|
+
}
|
|
1166
|
+
},
|
|
1167
|
+
exitRawMode() {
|
|
1168
|
+
if (process.stdin.isTTY && inRawMode) {
|
|
1169
|
+
process.stdin.setRawMode(false);
|
|
1170
|
+
inRawMode = false;
|
|
1171
|
+
}
|
|
1172
|
+
},
|
|
1173
|
+
pollEvent(_timeoutMs) {
|
|
1174
|
+
// Fallback can't poll synchronously - return null
|
|
1175
|
+
// Use readEvent() instead for async operation
|
|
1176
|
+
return null;
|
|
1177
|
+
},
|
|
1178
|
+
async readEvent() {
|
|
1179
|
+
return new Promise((resolve) => {
|
|
1180
|
+
const handler = (buffer) => {
|
|
1181
|
+
process.stdin.off("data", handler);
|
|
1182
|
+
const str = buffer.toString("utf8");
|
|
1183
|
+
// Parse simple keypresses
|
|
1184
|
+
if (str === "\r" || str === "\n") {
|
|
1185
|
+
resolve({ code: "enter", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1186
|
+
}
|
|
1187
|
+
else if (str === "\x03") {
|
|
1188
|
+
// Ctrl+C
|
|
1189
|
+
resolve({ code: "c", is_special: false, ctrl: true, alt: false, shift: false, kind: "press" });
|
|
1190
|
+
}
|
|
1191
|
+
else if (str === "\x7f" || str === "\x08") {
|
|
1192
|
+
resolve({ code: "backspace", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1193
|
+
}
|
|
1194
|
+
else if (str === "\x1b") {
|
|
1195
|
+
resolve({ code: "escape", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1196
|
+
}
|
|
1197
|
+
else if (str === "\t") {
|
|
1198
|
+
resolve({ code: "tab", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1199
|
+
}
|
|
1200
|
+
else if (str.length === 1 && str >= " ") {
|
|
1201
|
+
// Regular printable character
|
|
1202
|
+
const ctrl = str.charCodeAt(0) < 32;
|
|
1203
|
+
const char = ctrl ? String.fromCharCode(str.charCodeAt(0) + 96) : str;
|
|
1204
|
+
resolve({ code: char, is_special: false, ctrl, alt: false, shift: false, kind: "press" });
|
|
1205
|
+
}
|
|
1206
|
+
else {
|
|
1207
|
+
// Handle escape sequences for arrows and special keys
|
|
1208
|
+
if (str === "\x1b[A") {
|
|
1209
|
+
resolve({ code: "up", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1210
|
+
}
|
|
1211
|
+
else if (str === "\x1b[B") {
|
|
1212
|
+
resolve({ code: "down", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1213
|
+
}
|
|
1214
|
+
else if (str === "\x1b[C") {
|
|
1215
|
+
resolve({ code: "right", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1216
|
+
}
|
|
1217
|
+
else if (str === "\x1b[D") {
|
|
1218
|
+
resolve({ code: "left", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1219
|
+
}
|
|
1220
|
+
else if (str === "\x1b[5~") {
|
|
1221
|
+
resolve({ code: "pageup", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1222
|
+
}
|
|
1223
|
+
else if (str === "\x1b[6~") {
|
|
1224
|
+
resolve({ code: "pagedown", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1225
|
+
}
|
|
1226
|
+
else if (str === "\x1b[H" || str === "\x1b[1~") {
|
|
1227
|
+
resolve({ code: "home", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1228
|
+
}
|
|
1229
|
+
else if (str === "\x1b[F" || str === "\x1b[4~") {
|
|
1230
|
+
resolve({ code: "end", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1231
|
+
}
|
|
1232
|
+
else if (str === "\x1b[3~") {
|
|
1233
|
+
resolve({ code: "delete", is_special: true, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1234
|
+
}
|
|
1235
|
+
else if (str === "\x1b[Z") {
|
|
1236
|
+
resolve({ code: "backtab", is_special: true, ctrl: false, alt: false, shift: true, kind: "press" });
|
|
1237
|
+
}
|
|
1238
|
+
else {
|
|
1239
|
+
// Unknown escape sequence - treat as-is
|
|
1240
|
+
resolve({ code: str, is_special: false, ctrl: false, alt: false, shift: false, kind: "press" });
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
};
|
|
1244
|
+
process.stdin.once("data", handler);
|
|
1245
|
+
});
|
|
1246
|
+
},
|
|
1247
|
+
};
|
|
1248
|
+
},
|
|
1249
|
+
// Native TUI (fallback - not available in pure JS)
|
|
1250
|
+
create_tui: () => {
|
|
1251
|
+
throw new Error("Native TUI not available in fallback mode. Build the Rust native module.");
|
|
1252
|
+
},
|
|
1253
|
+
is_native_tui_available: () => false,
|
|
1254
|
+
};
|
|
1255
|
+
}
|
|
1256
|
+
// Export a singleton instance
|
|
1257
|
+
export const native = loadNative();
|
|
1258
|
+
/**
|
|
1259
|
+
* Syntax highlight code with ANSI escape codes for terminal display
|
|
1260
|
+
* Uses native Rust module if available, falls back to JS implementation
|
|
1261
|
+
*/
|
|
1262
|
+
export function highlight_code(code, language) {
|
|
1263
|
+
return native.highlight_code(code, language);
|
|
1264
|
+
}
|
|
1265
|
+
/**
|
|
1266
|
+
* Highlight markdown with nested code block syntax highlighting
|
|
1267
|
+
* Parses markdown for code fences and highlights code blocks with their language
|
|
1268
|
+
*/
|
|
1269
|
+
export function highlight_markdown(markdown) {
|
|
1270
|
+
return native.highlight_markdown(markdown);
|
|
1271
|
+
}
|
|
1272
|
+
/**
|
|
1273
|
+
* List all supported languages for syntax highlighting
|
|
1274
|
+
*/
|
|
1275
|
+
export function list_highlight_languages() {
|
|
1276
|
+
return [
|
|
1277
|
+
// Core languages
|
|
1278
|
+
"typescript", "ts", "javascript", "js",
|
|
1279
|
+
"python", "py",
|
|
1280
|
+
"rust", "rs",
|
|
1281
|
+
"go", "golang",
|
|
1282
|
+
"ruby", "rb",
|
|
1283
|
+
"java",
|
|
1284
|
+
"c", "cpp", "c++", "csharp", "cs", "c#",
|
|
1285
|
+
"php",
|
|
1286
|
+
"swift",
|
|
1287
|
+
"kotlin", "kt",
|
|
1288
|
+
"scala",
|
|
1289
|
+
// Shell & config
|
|
1290
|
+
"shell", "sh", "bash", "zsh",
|
|
1291
|
+
"json",
|
|
1292
|
+
"yaml", "yml",
|
|
1293
|
+
"toml",
|
|
1294
|
+
// Markup
|
|
1295
|
+
"markdown", "md",
|
|
1296
|
+
"html", "htm",
|
|
1297
|
+
"css", "scss", "less",
|
|
1298
|
+
"xml",
|
|
1299
|
+
// Database
|
|
1300
|
+
"sql",
|
|
1301
|
+
// Diagrams
|
|
1302
|
+
"mermaid", "mmd",
|
|
1303
|
+
];
|
|
1304
|
+
}
|
|
1305
|
+
/**
|
|
1306
|
+
* Highlight a diff with ANSI colors
|
|
1307
|
+
* Uses native Rust module if available, falls back to JS implementation
|
|
1308
|
+
*/
|
|
1309
|
+
export function highlight_diff(oldText, newText, options) {
|
|
1310
|
+
return native.highlight_diff(oldText, newText, options);
|
|
1311
|
+
}
|
|
1312
|
+
/**
|
|
1313
|
+
* Calculate diff hunks with hunk headers for LLM context
|
|
1314
|
+
* Returns structured diff with @@ headers included in content
|
|
1315
|
+
*/
|
|
1316
|
+
export function calculate_diff(oldText, newText) {
|
|
1317
|
+
return native.calculate_diff(oldText, newText);
|
|
1318
|
+
}
|
|
1319
|
+
// ===== Multi-File Edit Functions =====
|
|
1320
|
+
/**
|
|
1321
|
+
* Validate multi-file edits without applying them
|
|
1322
|
+
* Returns an array of error messages (empty if valid)
|
|
1323
|
+
*/
|
|
1324
|
+
export function validate_multi_edits(edits) {
|
|
1325
|
+
return native.validate_multi_edits(edits);
|
|
1326
|
+
}
|
|
1327
|
+
/**
|
|
1328
|
+
* Preview what edits would be applied without making changes
|
|
1329
|
+
* Returns an array of { file_path, replacement_count } for each file
|
|
1330
|
+
*/
|
|
1331
|
+
export function preview_multi_edits(edits) {
|
|
1332
|
+
return native.preview_multi_edits(edits);
|
|
1333
|
+
}
|
|
1334
|
+
/**
|
|
1335
|
+
* Apply multiple file edits atomically with rollback on failure
|
|
1336
|
+
*
|
|
1337
|
+
* This function:
|
|
1338
|
+
* 1. Validates all edits can be applied (files exist, strings found)
|
|
1339
|
+
* 2. Creates backups of all affected files
|
|
1340
|
+
* 3. Applies all edits
|
|
1341
|
+
* 4. Rolls back on any failure
|
|
1342
|
+
*
|
|
1343
|
+
* @param edits Array of edit operations
|
|
1344
|
+
* @returns Result with success status and list of modified files
|
|
1345
|
+
*/
|
|
1346
|
+
export function apply_multi_edits(edits) {
|
|
1347
|
+
return native.apply_multi_edits(edits);
|
|
1348
|
+
}
|
|
1349
|
+
// ===== Helper Functions =====
|
|
1350
|
+
function truncateString(s, maxLen) {
|
|
1351
|
+
if (s.length <= maxLen)
|
|
1352
|
+
return s;
|
|
1353
|
+
return s.slice(0, maxLen) + "...";
|
|
1354
|
+
}
|
|
1355
|
+
function escapeRegex(string) {
|
|
1356
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1357
|
+
}
|
|
1358
|
+
let quantModule = null;
|
|
1359
|
+
/**
|
|
1360
|
+
* Load the quant native module from @ebowwa/quant-rust
|
|
1361
|
+
*/
|
|
1362
|
+
function loadQuant() {
|
|
1363
|
+
if (quantModule)
|
|
1364
|
+
return quantModule;
|
|
1365
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
1366
|
+
// Try multiple paths for the quant library
|
|
1367
|
+
const libName = process.platform === "darwin"
|
|
1368
|
+
? "libquant_rust.dylib"
|
|
1369
|
+
: process.platform === "linux"
|
|
1370
|
+
? "libquant_rust.so"
|
|
1371
|
+
: "quant_rust.dll";
|
|
1372
|
+
const possiblePaths = [
|
|
1373
|
+
// From npm package
|
|
1374
|
+
join(__dirname, "..", "..", "node_modules", "@ebowwa", "quant-rust", "native", `${process.platform}-${process.arch}`, libName),
|
|
1375
|
+
// From npm package (alternate)
|
|
1376
|
+
join(__dirname, "..", "..", "..", "@ebowwa", "quant-rust", "native", `${process.platform}-${process.arch}`, libName),
|
|
1377
|
+
// Development build
|
|
1378
|
+
join(__dirname, "..", "..", "node_modules", "@ebowwa", "quant-rust", "target", "release", libName),
|
|
1379
|
+
];
|
|
1380
|
+
for (const libPath of possiblePaths) {
|
|
1381
|
+
try {
|
|
1382
|
+
const { existsSync } = require("fs");
|
|
1383
|
+
if (!existsSync(libPath))
|
|
1384
|
+
continue;
|
|
1385
|
+
const { dlopen, FFIType, ptr } = require("bun:ffi");
|
|
1386
|
+
const lib = dlopen(libPath, {
|
|
1387
|
+
quant_version: { returns: FFIType.cstring, args: [] },
|
|
1388
|
+
quant_last_error: { returns: FFIType.cstring, args: [] },
|
|
1389
|
+
quant_clear_error: { returns: FFIType.void, args: [] },
|
|
1390
|
+
quant_ohlcv_new: { returns: FFIType.cstring, args: [FFIType.u64, FFIType.f64, FFIType.f64, FFIType.f64, FFIType.f64, FFIType.f64] },
|
|
1391
|
+
quant_amm_new: { returns: FFIType.cstring, args: [FFIType.f64, FFIType.f64, FFIType.f64] },
|
|
1392
|
+
quant_amm_calculate_cost: { returns: FFIType.cstring, args: [FFIType.f64, FFIType.f64, FFIType.bool, FFIType.f64] },
|
|
1393
|
+
quant_amm_price_impact: { returns: FFIType.cstring, args: [FFIType.f64, FFIType.f64, FFIType.bool, FFIType.f64] },
|
|
1394
|
+
quant_lmsr_price: { returns: FFIType.cstring, args: [FFIType.f64, FFIType.f64, FFIType.f64] },
|
|
1395
|
+
quant_lmsr_cost: { returns: FFIType.cstring, args: [FFIType.f64, FFIType.f64, FFIType.f64, FFIType.bool, FFIType.f64] },
|
|
1396
|
+
quant_detect_arbitrage: { returns: FFIType.cstring, args: [FFIType.f64, FFIType.f64] },
|
|
1397
|
+
quant_convert_odds: { returns: FFIType.cstring, args: [FFIType.f64, FFIType.i32] },
|
|
1398
|
+
quant_mean: { returns: FFIType.f64, args: [FFIType.ptr, FFIType.usize] },
|
|
1399
|
+
quant_std_dev: { returns: FFIType.f64, args: [FFIType.ptr, FFIType.usize] },
|
|
1400
|
+
quant_variance: { returns: FFIType.f64, args: [FFIType.ptr, FFIType.usize] },
|
|
1401
|
+
quant_correlation: { returns: FFIType.f64, args: [FFIType.ptr, FFIType.ptr, FFIType.usize] },
|
|
1402
|
+
quant_free_string: { returns: FFIType.void, args: [FFIType.ptr] },
|
|
1403
|
+
});
|
|
1404
|
+
quantModule = lib.symbols;
|
|
1405
|
+
return quantModule;
|
|
1406
|
+
}
|
|
1407
|
+
catch {
|
|
1408
|
+
continue;
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
return null;
|
|
1412
|
+
}
|
|
1413
|
+
// Load quant module
|
|
1414
|
+
export const quant = loadQuant();
|
|
1415
|
+
// ===== Quant Helper Functions =====
|
|
1416
|
+
function parseQuantJson(response) {
|
|
1417
|
+
if (!response) {
|
|
1418
|
+
throw new Error(quant?.quant_last_error() || "Unknown quant error");
|
|
1419
|
+
}
|
|
1420
|
+
return JSON.parse(response);
|
|
1421
|
+
}
|
|
1422
|
+
function toFloat64Ptr(data) {
|
|
1423
|
+
const { ptr } = require("bun:ffi");
|
|
1424
|
+
const buffer = new Float64Array(data);
|
|
1425
|
+
return { buffer, ptr: ptr(buffer) };
|
|
1426
|
+
}
|
|
1427
|
+
// ===== Quant Export Functions =====
|
|
1428
|
+
/** Warn once when using JS fallback */
|
|
1429
|
+
let quantFallbackWarned = false;
|
|
1430
|
+
function warnQuantFallback() {
|
|
1431
|
+
if (!quantFallbackWarned) {
|
|
1432
|
+
console.warn("\x1b[33m[quant] WARNING: Rust native module not loaded, using JS fallback\x1b[0m");
|
|
1433
|
+
quantFallbackWarned = true;
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
export function quantVersion() {
|
|
1437
|
+
if (!quant) {
|
|
1438
|
+
warnQuantFallback();
|
|
1439
|
+
return "JS_FALLBACK (rust failed)";
|
|
1440
|
+
}
|
|
1441
|
+
return quant.quant_version();
|
|
1442
|
+
}
|
|
1443
|
+
export function isQuantAvailable() {
|
|
1444
|
+
return quant !== null;
|
|
1445
|
+
}
|
|
1446
|
+
// ----- OHLCV -----
|
|
1447
|
+
export function createOHLCV(timestamp, open, high, low, close, volume) {
|
|
1448
|
+
if (!quant) {
|
|
1449
|
+
warnQuantFallback();
|
|
1450
|
+
return { timestamp, open, high, low, close, volume };
|
|
1451
|
+
}
|
|
1452
|
+
const response = quant.quant_ohlcv_new(BigInt(timestamp), open, high, low, close, volume);
|
|
1453
|
+
return parseQuantJson(response);
|
|
1454
|
+
}
|
|
1455
|
+
// ----- AMM -----
|
|
1456
|
+
export function createAMM(poolYes, poolNo, fee) {
|
|
1457
|
+
if (!quant) {
|
|
1458
|
+
warnQuantFallback();
|
|
1459
|
+
const k = poolYes * poolNo;
|
|
1460
|
+
return {
|
|
1461
|
+
pool_yes: poolYes,
|
|
1462
|
+
pool_no: poolNo,
|
|
1463
|
+
k,
|
|
1464
|
+
fee,
|
|
1465
|
+
price_yes: poolNo / k,
|
|
1466
|
+
price_no: poolYes / k,
|
|
1467
|
+
};
|
|
1468
|
+
}
|
|
1469
|
+
const response = quant.quant_amm_new(poolYes, poolNo, fee);
|
|
1470
|
+
return parseQuantJson(response);
|
|
1471
|
+
}
|
|
1472
|
+
export function ammCalculateCost(poolYes, poolNo, outcome, shares) {
|
|
1473
|
+
if (!quant) {
|
|
1474
|
+
warnQuantFallback();
|
|
1475
|
+
const buyYes = typeof outcome === "string" ? outcome === "yes" : outcome;
|
|
1476
|
+
const k = poolYes * poolNo;
|
|
1477
|
+
if (buyYes) {
|
|
1478
|
+
return (k / (poolYes + shares)) - poolNo;
|
|
1479
|
+
}
|
|
1480
|
+
return (k / (poolNo + shares)) - poolYes;
|
|
1481
|
+
}
|
|
1482
|
+
const buyYes = typeof outcome === "string" ? outcome === "yes" : outcome;
|
|
1483
|
+
const response = quant.quant_amm_calculate_cost(poolYes, poolNo, buyYes, shares);
|
|
1484
|
+
const result = parseQuantJson(response);
|
|
1485
|
+
return Math.abs(result.cost);
|
|
1486
|
+
}
|
|
1487
|
+
export function ammPriceImpact(poolYes, poolNo, outcome, shares) {
|
|
1488
|
+
if (!quant) {
|
|
1489
|
+
warnQuantFallback();
|
|
1490
|
+
const buyYes = typeof outcome === "string" ? outcome === "yes" : outcome;
|
|
1491
|
+
const k = poolYes * poolNo;
|
|
1492
|
+
const priceBefore = buyYes ? poolNo / k : poolYes / k;
|
|
1493
|
+
const newPoolYes = buyYes ? poolYes + shares : poolYes;
|
|
1494
|
+
const newPoolNo = buyYes ? poolNo : poolNo + shares;
|
|
1495
|
+
const priceAfter = buyYes ? newPoolNo / k : newPoolYes / k;
|
|
1496
|
+
return {
|
|
1497
|
+
price_before: priceBefore,
|
|
1498
|
+
price_after: priceAfter,
|
|
1499
|
+
price_impact: Math.abs(priceAfter - priceBefore) / priceBefore,
|
|
1500
|
+
slippage: Math.abs(priceAfter - priceBefore),
|
|
1501
|
+
};
|
|
1502
|
+
}
|
|
1503
|
+
const buyYes = typeof outcome === "string" ? outcome === "yes" : outcome;
|
|
1504
|
+
const response = quant.quant_amm_price_impact(poolYes, poolNo, buyYes, shares);
|
|
1505
|
+
return parseQuantJson(response);
|
|
1506
|
+
}
|
|
1507
|
+
// ----- LMSR -----
|
|
1508
|
+
export function lmsrPrice(yesShares, noShares, b) {
|
|
1509
|
+
if (!quant) {
|
|
1510
|
+
warnQuantFallback();
|
|
1511
|
+
const expYes = Math.exp(yesShares / b);
|
|
1512
|
+
const expNo = Math.exp(noShares / b);
|
|
1513
|
+
const sum = expYes + expNo;
|
|
1514
|
+
return { yes_price: expYes / sum, no_price: expNo / sum, spread: Math.abs(expYes - expNo) / sum };
|
|
1515
|
+
}
|
|
1516
|
+
const response = quant.quant_lmsr_price(yesShares, noShares, b);
|
|
1517
|
+
return parseQuantJson(response);
|
|
1518
|
+
}
|
|
1519
|
+
export function lmsrCost(yesShares, noShares, b, outcome, shares) {
|
|
1520
|
+
if (!quant) {
|
|
1521
|
+
warnQuantFallback();
|
|
1522
|
+
const buyYes = typeof outcome === "string" ? outcome === "yes" : outcome;
|
|
1523
|
+
const costBefore = b * Math.log(Math.exp(yesShares / b) + Math.exp(noShares / b));
|
|
1524
|
+
const newYes = buyYes ? yesShares + shares : yesShares;
|
|
1525
|
+
const newNo = buyYes ? noShares : noShares + shares;
|
|
1526
|
+
const costAfter = b * Math.log(Math.exp(newYes / b) + Math.exp(newNo / b));
|
|
1527
|
+
return { cost: costAfter - costBefore, avg_price: (costAfter - costBefore) / shares };
|
|
1528
|
+
}
|
|
1529
|
+
const buyYes = typeof outcome === "string" ? outcome === "yes" : outcome;
|
|
1530
|
+
const response = quant.quant_lmsr_cost(yesShares, noShares, b, buyYes, shares);
|
|
1531
|
+
return parseQuantJson(response);
|
|
1532
|
+
}
|
|
1533
|
+
// ----- Arbitrage -----
|
|
1534
|
+
export function detectArbitrage(yesPrice, noPrice) {
|
|
1535
|
+
if (!quant) {
|
|
1536
|
+
warnQuantFallback();
|
|
1537
|
+
const total = yesPrice + noPrice;
|
|
1538
|
+
return {
|
|
1539
|
+
has_arbitrage: total < 1,
|
|
1540
|
+
yes_price: yesPrice,
|
|
1541
|
+
no_price: noPrice,
|
|
1542
|
+
total,
|
|
1543
|
+
profit_per_share: total < 1 ? 1 - total : 0,
|
|
1544
|
+
};
|
|
1545
|
+
}
|
|
1546
|
+
const response = quant.quant_detect_arbitrage(yesPrice, noPrice);
|
|
1547
|
+
return parseQuantJson(response);
|
|
1548
|
+
}
|
|
1549
|
+
// ----- Odds Conversion -----
|
|
1550
|
+
const ODDS_TYPE_MAP = {
|
|
1551
|
+
probability: 0,
|
|
1552
|
+
decimal: 1,
|
|
1553
|
+
american: 2,
|
|
1554
|
+
};
|
|
1555
|
+
export function convertOdds(value, fromType) {
|
|
1556
|
+
if (!quant) {
|
|
1557
|
+
warnQuantFallback();
|
|
1558
|
+
let prob;
|
|
1559
|
+
switch (fromType) {
|
|
1560
|
+
case "probability":
|
|
1561
|
+
prob = value;
|
|
1562
|
+
break;
|
|
1563
|
+
case "decimal":
|
|
1564
|
+
prob = 1 / value;
|
|
1565
|
+
break;
|
|
1566
|
+
case "american":
|
|
1567
|
+
prob = value > 0 ? 100 / (value + 100) : -value / (-value + 100);
|
|
1568
|
+
break;
|
|
1569
|
+
}
|
|
1570
|
+
const americanOdds = prob >= 0.5 ? Math.round(-100 / (prob - 1)) : Math.round((1 - prob) / prob * 100);
|
|
1571
|
+
return { probability: prob, decimal_odds: 1 / prob, american_odds: americanOdds };
|
|
1572
|
+
}
|
|
1573
|
+
const response = quant.quant_convert_odds(value, ODDS_TYPE_MAP[fromType] ?? 0);
|
|
1574
|
+
return parseQuantJson(response);
|
|
1575
|
+
}
|
|
1576
|
+
// ----- Statistics -----
|
|
1577
|
+
export function quantMean(data) {
|
|
1578
|
+
if (data.length === 0)
|
|
1579
|
+
return NaN;
|
|
1580
|
+
if (!quant) {
|
|
1581
|
+
warnQuantFallback();
|
|
1582
|
+
return data.reduce((a, b) => a + b, 0) / data.length;
|
|
1583
|
+
}
|
|
1584
|
+
const { ptr } = toFloat64Ptr(data);
|
|
1585
|
+
return quant.quant_mean(ptr, data.length);
|
|
1586
|
+
}
|
|
1587
|
+
export function quantStdDev(data) {
|
|
1588
|
+
if (data.length === 0)
|
|
1589
|
+
return NaN;
|
|
1590
|
+
if (!quant) {
|
|
1591
|
+
warnQuantFallback();
|
|
1592
|
+
const m = data.reduce((a, b) => a + b, 0) / data.length;
|
|
1593
|
+
return Math.sqrt(data.reduce((sum, x) => sum + (x - m) ** 2, 0) / data.length);
|
|
1594
|
+
}
|
|
1595
|
+
const { ptr } = toFloat64Ptr(data);
|
|
1596
|
+
return quant.quant_std_dev(ptr, data.length);
|
|
1597
|
+
}
|
|
1598
|
+
export function quantVariance(data) {
|
|
1599
|
+
if (data.length === 0)
|
|
1600
|
+
return NaN;
|
|
1601
|
+
if (!quant) {
|
|
1602
|
+
warnQuantFallback();
|
|
1603
|
+
const m = data.reduce((a, b) => a + b, 0) / data.length;
|
|
1604
|
+
return data.reduce((sum, x) => sum + (x - m) ** 2, 0) / data.length;
|
|
1605
|
+
}
|
|
1606
|
+
const { ptr } = toFloat64Ptr(data);
|
|
1607
|
+
return quant.quant_variance(ptr, data.length);
|
|
1608
|
+
}
|
|
1609
|
+
export function quantCorrelation(x, y) {
|
|
1610
|
+
if (x.length === 0 || y.length === 0 || x.length !== y.length)
|
|
1611
|
+
return NaN;
|
|
1612
|
+
if (!quant) {
|
|
1613
|
+
warnQuantFallback();
|
|
1614
|
+
const n = x.length;
|
|
1615
|
+
const mx = x.reduce((a, b) => a + b, 0) / n;
|
|
1616
|
+
const my = y.reduce((a, b) => a + b, 0) / n;
|
|
1617
|
+
const cov = x.reduce((s, xi, i) => s + (xi - mx) * (y[i] - my), 0) / n;
|
|
1618
|
+
const vx = x.reduce((s, xi) => s + (xi - mx) ** 2, 0) / n;
|
|
1619
|
+
const vy = y.reduce((s, yi) => s + (yi - my) ** 2, 0) / n;
|
|
1620
|
+
return cov / Math.sqrt(vx * vy);
|
|
1621
|
+
}
|
|
1622
|
+
const { ptr: ptrX } = toFloat64Ptr(x);
|
|
1623
|
+
const { ptr: ptrY } = toFloat64Ptr(y);
|
|
1624
|
+
return quant.quant_correlation(ptrX, ptrY, x.length);
|
|
1625
|
+
}
|