profclaw 0.0.1-beta.1
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/.env.example +215 -0
- package/CHANGELOG.md +49 -0
- package/CONTRIBUTING.md +119 -0
- package/Dockerfile +107 -0
- package/LICENSE +661 -0
- package/README.md +196 -0
- package/config/agents.yml +55 -0
- package/config/budget.yml +15 -0
- package/config/pricing.yml +46 -0
- package/config/settings.yml +168 -0
- package/dist/adapters/claude-code.d.ts +46 -0
- package/dist/adapters/claude-code.js +215 -0
- package/dist/adapters/index.d.ts +4 -0
- package/dist/adapters/index.js +4 -0
- package/dist/adapters/ollama.d.ts +45 -0
- package/dist/adapters/ollama.js +277 -0
- package/dist/adapters/openclaw.d.ts +60 -0
- package/dist/adapters/openclaw.js +289 -0
- package/dist/adapters/registry.d.ts +56 -0
- package/dist/adapters/registry.js +163 -0
- package/dist/agents/executor.d.ts +78 -0
- package/dist/agents/executor.js +657 -0
- package/dist/agents/index.d.ts +10 -0
- package/dist/agents/index.js +27 -0
- package/dist/agents/stop-conditions.d.ts +108 -0
- package/dist/agents/stop-conditions.js +299 -0
- package/dist/agents/types.d.ts +185 -0
- package/dist/agents/types.js +14 -0
- package/dist/ai/embedding-service.d.ts +96 -0
- package/dist/ai/embedding-service.js +333 -0
- package/dist/auth/api-tokens.d.ts +71 -0
- package/dist/auth/api-tokens.js +235 -0
- package/dist/auth/auth-service.d.ts +75 -0
- package/dist/auth/auth-service.js +557 -0
- package/dist/auth/device-identity.d.ts +96 -0
- package/dist/auth/device-identity.js +250 -0
- package/dist/auth/github-oauth.d.ts +20 -0
- package/dist/auth/github-oauth.js +59 -0
- package/dist/auth/jira-oauth.d.ts +25 -0
- package/dist/auth/jira-oauth.js +75 -0
- package/dist/auth/linear-oauth.d.ts +21 -0
- package/dist/auth/linear-oauth.js +59 -0
- package/dist/auth/middleware.d.ts +44 -0
- package/dist/auth/middleware.js +190 -0
- package/dist/auth/pairing-codes.d.ts +109 -0
- package/dist/auth/pairing-codes.js +274 -0
- package/dist/auth/password.d.ts +53 -0
- package/dist/auth/password.js +126 -0
- package/dist/auth/qr-pairing.d.ts +36 -0
- package/dist/auth/qr-pairing.js +138 -0
- package/dist/auth/slack-oauth.d.ts +31 -0
- package/dist/auth/slack-oauth.js +80 -0
- package/dist/backup/index.d.ts +50 -0
- package/dist/backup/index.js +184 -0
- package/dist/browser/adapters.d.ts +25 -0
- package/dist/browser/adapters.js +32 -0
- package/dist/browser/cli.d.ts +19 -0
- package/dist/browser/cli.js +277 -0
- package/dist/browser/compression.d.ts +32 -0
- package/dist/browser/compression.js +269 -0
- package/dist/browser/extensions.d.ts +144 -0
- package/dist/browser/extensions.js +251 -0
- package/dist/browser/index.d.ts +37 -0
- package/dist/browser/index.js +43 -0
- package/dist/browser/refs.d.ts +46 -0
- package/dist/browser/refs.js +120 -0
- package/dist/browser/search.d.ts +36 -0
- package/dist/browser/search.js +193 -0
- package/dist/browser/service.d.ts +94 -0
- package/dist/browser/service.js +358 -0
- package/dist/browser/snapshot.d.ts +19 -0
- package/dist/browser/snapshot.js +250 -0
- package/dist/browser/tools.d.ts +259 -0
- package/dist/browser/tools.js +463 -0
- package/dist/browser/types.d.ts +134 -0
- package/dist/browser/types.js +17 -0
- package/dist/chat/agentic-executor.d.ts +108 -0
- package/dist/chat/agentic-executor.js +739 -0
- package/dist/chat/api-key-detector.d.ts +41 -0
- package/dist/chat/api-key-detector.js +290 -0
- package/dist/chat/auto-reply.d.ts +90 -0
- package/dist/chat/auto-reply.js +272 -0
- package/dist/chat/conversations.d.ts +91 -0
- package/dist/chat/conversations.js +297 -0
- package/dist/chat/execution/audit.d.ts +192 -0
- package/dist/chat/execution/audit.js +323 -0
- package/dist/chat/execution/executor.d.ts +56 -0
- package/dist/chat/execution/executor.js +654 -0
- package/dist/chat/execution/guardrails.d.ts +98 -0
- package/dist/chat/execution/guardrails.js +571 -0
- package/dist/chat/execution/index.d.ts +61 -0
- package/dist/chat/execution/index.js +129 -0
- package/dist/chat/execution/model-capability.d.ts +34 -0
- package/dist/chat/execution/model-capability.js +96 -0
- package/dist/chat/execution/process-pool.d.ts +110 -0
- package/dist/chat/execution/process-pool.js +290 -0
- package/dist/chat/execution/pty.d.ts +92 -0
- package/dist/chat/execution/pty.js +285 -0
- package/dist/chat/execution/rate-limiter.d.ts +87 -0
- package/dist/chat/execution/rate-limiter.js +305 -0
- package/dist/chat/execution/registry.d.ts +54 -0
- package/dist/chat/execution/registry.js +220 -0
- package/dist/chat/execution/sandbox.d.ts +109 -0
- package/dist/chat/execution/sandbox.js +684 -0
- package/dist/chat/execution/secrets.d.ts +45 -0
- package/dist/chat/execution/secrets.js +338 -0
- package/dist/chat/execution/security.d.ts +179 -0
- package/dist/chat/execution/security.js +739 -0
- package/dist/chat/execution/self-correction.d.ts +162 -0
- package/dist/chat/execution/self-correction.js +557 -0
- package/dist/chat/execution/session-manager.d.ts +79 -0
- package/dist/chat/execution/session-manager.js +356 -0
- package/dist/chat/execution/session-spawn/config.d.ts +37 -0
- package/dist/chat/execution/session-spawn/config.js +83 -0
- package/dist/chat/execution/session-spawn/index.d.ts +10 -0
- package/dist/chat/execution/session-spawn/index.js +10 -0
- package/dist/chat/execution/session-spawn/manager.d.ts +35 -0
- package/dist/chat/execution/session-spawn/manager.js +418 -0
- package/dist/chat/execution/session-spawn/types.d.ts +117 -0
- package/dist/chat/execution/session-spawn/types.js +16 -0
- package/dist/chat/execution/smart-prompts.d.ts +34 -0
- package/dist/chat/execution/smart-prompts.js +151 -0
- package/dist/chat/execution/stream-results.d.ts +65 -0
- package/dist/chat/execution/stream-results.js +156 -0
- package/dist/chat/execution/tool-router.d.ts +76 -0
- package/dist/chat/execution/tool-router.js +296 -0
- package/dist/chat/execution/tools/agents-list.d.ts +49 -0
- package/dist/chat/execution/tools/agents-list.js +165 -0
- package/dist/chat/execution/tools/browser.d.ts +12 -0
- package/dist/chat/execution/tools/browser.js +14 -0
- package/dist/chat/execution/tools/canvas.d.ts +61 -0
- package/dist/chat/execution/tools/canvas.js +150 -0
- package/dist/chat/execution/tools/complete-task.d.ts +72 -0
- package/dist/chat/execution/tools/complete-task.js +104 -0
- package/dist/chat/execution/tools/cron-tool.d.ts +204 -0
- package/dist/chat/execution/tools/cron-tool.js +680 -0
- package/dist/chat/execution/tools/discord-actions.d.ts +120 -0
- package/dist/chat/execution/tools/discord-actions.js +361 -0
- package/dist/chat/execution/tools/exec.d.ts +43 -0
- package/dist/chat/execution/tools/exec.js +223 -0
- package/dist/chat/execution/tools/file-ops.d.ts +175 -0
- package/dist/chat/execution/tools/file-ops.js +723 -0
- package/dist/chat/execution/tools/git.d.ts +143 -0
- package/dist/chat/execution/tools/git.js +395 -0
- package/dist/chat/execution/tools/github.d.ts +42 -0
- package/dist/chat/execution/tools/github.js +184 -0
- package/dist/chat/execution/tools/glinr-ops.d.ts +202 -0
- package/dist/chat/execution/tools/glinr-ops.js +694 -0
- package/dist/chat/execution/tools/image-analyze.d.ts +29 -0
- package/dist/chat/execution/tools/image-analyze.js +127 -0
- package/dist/chat/execution/tools/index.d.ts +64 -0
- package/dist/chat/execution/tools/index.js +245 -0
- package/dist/chat/execution/tools/integrations.d.ts +109 -0
- package/dist/chat/execution/tools/integrations.js +237 -0
- package/dist/chat/execution/tools/link-understand.d.ts +34 -0
- package/dist/chat/execution/tools/link-understand.js +307 -0
- package/dist/chat/execution/tools/maintenance.d.ts +29 -0
- package/dist/chat/execution/tools/maintenance.js +105 -0
- package/dist/chat/execution/tools/memory-tools.d.ts +76 -0
- package/dist/chat/execution/tools/memory-tools.js +278 -0
- package/dist/chat/execution/tools/openai-image-gen.d.ts +51 -0
- package/dist/chat/execution/tools/openai-image-gen.js +212 -0
- package/dist/chat/execution/tools/profclaw-ops.d.ts +204 -0
- package/dist/chat/execution/tools/profclaw-ops.js +665 -0
- package/dist/chat/execution/tools/session-spawn.d.ts +146 -0
- package/dist/chat/execution/tools/session-spawn.js +544 -0
- package/dist/chat/execution/tools/session-status.d.ts +38 -0
- package/dist/chat/execution/tools/session-status.js +185 -0
- package/dist/chat/execution/tools/sessions-list.d.ts +49 -0
- package/dist/chat/execution/tools/sessions-list.js +153 -0
- package/dist/chat/execution/tools/sessions-send.d.ts +48 -0
- package/dist/chat/execution/tools/sessions-send.js +207 -0
- package/dist/chat/execution/tools/sessions-spawn.d.ts +51 -0
- package/dist/chat/execution/tools/sessions-spawn.js +137 -0
- package/dist/chat/execution/tools/slack-actions.d.ts +90 -0
- package/dist/chat/execution/tools/slack-actions.js +272 -0
- package/dist/chat/execution/tools/subagent-orchestrate.d.ts +66 -0
- package/dist/chat/execution/tools/subagent-orchestrate.js +313 -0
- package/dist/chat/execution/tools/system.d.ts +121 -0
- package/dist/chat/execution/tools/system.js +415 -0
- package/dist/chat/execution/tools/telegram-actions.d.ts +126 -0
- package/dist/chat/execution/tools/telegram-actions.js +339 -0
- package/dist/chat/execution/tools/test-run.d.ts +43 -0
- package/dist/chat/execution/tools/test-run.js +391 -0
- package/dist/chat/execution/tools/tts-speak.d.ts +39 -0
- package/dist/chat/execution/tools/tts-speak.js +199 -0
- package/dist/chat/execution/tools/web-fetch.d.ts +42 -0
- package/dist/chat/execution/tools/web-fetch.js +247 -0
- package/dist/chat/execution/tools/web-search.d.ts +53 -0
- package/dist/chat/execution/tools/web-search.js +130 -0
- package/dist/chat/execution/types.d.ts +337 -0
- package/dist/chat/execution/types.js +8 -0
- package/dist/chat/execution/workflows/built-in.d.ts +10 -0
- package/dist/chat/execution/workflows/built-in.js +249 -0
- package/dist/chat/execution/workflows/executor.d.ts +13 -0
- package/dist/chat/execution/workflows/executor.js +259 -0
- package/dist/chat/execution/workflows/index.d.ts +5 -0
- package/dist/chat/execution/workflows/index.js +5 -0
- package/dist/chat/execution/workflows/trigger.d.ts +15 -0
- package/dist/chat/execution/workflows/trigger.js +111 -0
- package/dist/chat/execution/workflows/types.d.ts +80 -0
- package/dist/chat/execution/workflows/types.js +2 -0
- package/dist/chat/failover/error.d.ts +73 -0
- package/dist/chat/failover/error.js +412 -0
- package/dist/chat/failover/index.d.ts +10 -0
- package/dist/chat/failover/index.js +11 -0
- package/dist/chat/failover/model-fallback.d.ts +97 -0
- package/dist/chat/failover/model-fallback.js +328 -0
- package/dist/chat/failover/types.d.ts +47 -0
- package/dist/chat/failover/types.js +8 -0
- package/dist/chat/format/chunk.d.ts +59 -0
- package/dist/chat/format/chunk.js +253 -0
- package/dist/chat/format/index.d.ts +7 -0
- package/dist/chat/format/index.js +7 -0
- package/dist/chat/format/tool-result-formatter.d.ts +30 -0
- package/dist/chat/format/tool-result-formatter.js +177 -0
- package/dist/chat/group.d.ts +232 -0
- package/dist/chat/group.js +311 -0
- package/dist/chat/index.d.ts +21 -0
- package/dist/chat/index.js +30 -0
- package/dist/chat/memory.d.ts +108 -0
- package/dist/chat/memory.js +343 -0
- package/dist/chat/message-handler.d.ts +38 -0
- package/dist/chat/message-handler.js +274 -0
- package/dist/chat/proactive/index.d.ts +167 -0
- package/dist/chat/proactive/index.js +721 -0
- package/dist/chat/prompt-adapter.d.ts +52 -0
- package/dist/chat/prompt-adapter.js +245 -0
- package/dist/chat/providers/dingtalk/index.d.ts +69 -0
- package/dist/chat/providers/dingtalk/index.js +225 -0
- package/dist/chat/providers/discord/index.d.ts +264 -0
- package/dist/chat/providers/discord/index.js +657 -0
- package/dist/chat/providers/feishu/index.d.ts +97 -0
- package/dist/chat/providers/feishu/index.js +362 -0
- package/dist/chat/providers/googlechat/index.d.ts +269 -0
- package/dist/chat/providers/googlechat/index.js +634 -0
- package/dist/chat/providers/imessage/index.d.ts +61 -0
- package/dist/chat/providers/imessage/index.js +166 -0
- package/dist/chat/providers/index.d.ts +76 -0
- package/dist/chat/providers/index.js +430 -0
- package/dist/chat/providers/irc/index.d.ts +101 -0
- package/dist/chat/providers/irc/index.js +557 -0
- package/dist/chat/providers/line/index.d.ts +113 -0
- package/dist/chat/providers/line/index.js +434 -0
- package/dist/chat/providers/matrix/index.d.ts +161 -0
- package/dist/chat/providers/matrix/index.js +559 -0
- package/dist/chat/providers/mattermost/index.d.ts +106 -0
- package/dist/chat/providers/mattermost/index.js +425 -0
- package/dist/chat/providers/msteams/index.d.ts +198 -0
- package/dist/chat/providers/msteams/index.js +694 -0
- package/dist/chat/providers/nextcloud/index.d.ts +52 -0
- package/dist/chat/providers/nextcloud/index.js +156 -0
- package/dist/chat/providers/nostr/index.d.ts +60 -0
- package/dist/chat/providers/nostr/index.js +200 -0
- package/dist/chat/providers/qq/index.d.ts +57 -0
- package/dist/chat/providers/qq/index.js +260 -0
- package/dist/chat/providers/registry.d.ts +89 -0
- package/dist/chat/providers/registry.js +213 -0
- package/dist/chat/providers/signal/index.d.ts +88 -0
- package/dist/chat/providers/signal/index.js +357 -0
- package/dist/chat/providers/slack/index.d.ts +52 -0
- package/dist/chat/providers/slack/index.js +477 -0
- package/dist/chat/providers/synology/index.d.ts +50 -0
- package/dist/chat/providers/synology/index.js +138 -0
- package/dist/chat/providers/telegram/index.d.ts +148 -0
- package/dist/chat/providers/telegram/index.js +492 -0
- package/dist/chat/providers/tlon/index.d.ts +44 -0
- package/dist/chat/providers/tlon/index.js +243 -0
- package/dist/chat/providers/twitch/index.d.ts +79 -0
- package/dist/chat/providers/twitch/index.js +349 -0
- package/dist/chat/providers/types.d.ts +437 -0
- package/dist/chat/providers/types.js +14 -0
- package/dist/chat/providers/webchat/index.d.ts +38 -0
- package/dist/chat/providers/webchat/index.js +214 -0
- package/dist/chat/providers/wecom/index.d.ts +62 -0
- package/dist/chat/providers/wecom/index.js +228 -0
- package/dist/chat/providers/whatsapp/index.d.ts +147 -0
- package/dist/chat/providers/whatsapp/index.js +396 -0
- package/dist/chat/providers/zalo/index.d.ts +54 -0
- package/dist/chat/providers/zalo/index.js +158 -0
- package/dist/chat/providers/zalo-personal/index.d.ts +53 -0
- package/dist/chat/providers/zalo-personal/index.js +212 -0
- package/dist/chat/skills.d.ts +82 -0
- package/dist/chat/skills.js +410 -0
- package/dist/chat/system-prompts.d.ts +76 -0
- package/dist/chat/system-prompts.js +407 -0
- package/dist/chat/tool-handler.d.ts +57 -0
- package/dist/chat/tool-handler.js +336 -0
- package/dist/chat/tools.d.ts +373 -0
- package/dist/chat/tools.js +512 -0
- package/dist/cli/commands/agent.d.ts +3 -0
- package/dist/cli/commands/agent.js +108 -0
- package/dist/cli/commands/auth.d.ts +12 -0
- package/dist/cli/commands/auth.js +301 -0
- package/dist/cli/commands/browser.d.ts +3 -0
- package/dist/cli/commands/browser.js +138 -0
- package/dist/cli/commands/canvas.d.ts +3 -0
- package/dist/cli/commands/canvas.js +155 -0
- package/dist/cli/commands/channels.d.ts +3 -0
- package/dist/cli/commands/channels.js +167 -0
- package/dist/cli/commands/chat.d.ts +9 -0
- package/dist/cli/commands/chat.js +360 -0
- package/dist/cli/commands/completion.d.ts +3 -0
- package/dist/cli/commands/completion.js +170 -0
- package/dist/cli/commands/config.d.ts +3 -0
- package/dist/cli/commands/config.js +193 -0
- package/dist/cli/commands/cost.d.ts +3 -0
- package/dist/cli/commands/cost.js +134 -0
- package/dist/cli/commands/daemon.d.ts +3 -0
- package/dist/cli/commands/daemon.js +381 -0
- package/dist/cli/commands/devices.d.ts +3 -0
- package/dist/cli/commands/devices.js +150 -0
- package/dist/cli/commands/doctor.d.ts +3 -0
- package/dist/cli/commands/doctor.js +295 -0
- package/dist/cli/commands/logs.d.ts +3 -0
- package/dist/cli/commands/logs.js +139 -0
- package/dist/cli/commands/mcp.d.ts +15 -0
- package/dist/cli/commands/mcp.js +157 -0
- package/dist/cli/commands/memory.d.ts +3 -0
- package/dist/cli/commands/memory.js +170 -0
- package/dist/cli/commands/models.d.ts +3 -0
- package/dist/cli/commands/models.js +197 -0
- package/dist/cli/commands/nodes.d.ts +3 -0
- package/dist/cli/commands/nodes.js +193 -0
- package/dist/cli/commands/onboard.d.ts +13 -0
- package/dist/cli/commands/onboard.js +360 -0
- package/dist/cli/commands/plugin.d.ts +15 -0
- package/dist/cli/commands/plugin.js +226 -0
- package/dist/cli/commands/provider.d.ts +16 -0
- package/dist/cli/commands/provider.js +320 -0
- package/dist/cli/commands/security.d.ts +3 -0
- package/dist/cli/commands/security.js +180 -0
- package/dist/cli/commands/serve.d.ts +3 -0
- package/dist/cli/commands/serve.js +179 -0
- package/dist/cli/commands/session.d.ts +3 -0
- package/dist/cli/commands/session.js +172 -0
- package/dist/cli/commands/setup.d.ts +13 -0
- package/dist/cli/commands/setup.js +636 -0
- package/dist/cli/commands/skill.d.ts +15 -0
- package/dist/cli/commands/skill.js +191 -0
- package/dist/cli/commands/status.d.ts +3 -0
- package/dist/cli/commands/status.js +71 -0
- package/dist/cli/commands/summary.d.ts +3 -0
- package/dist/cli/commands/summary.js +160 -0
- package/dist/cli/commands/task.d.ts +3 -0
- package/dist/cli/commands/task.js +170 -0
- package/dist/cli/commands/ticket.d.ts +3 -0
- package/dist/cli/commands/ticket.js +421 -0
- package/dist/cli/commands/tools.d.ts +9 -0
- package/dist/cli/commands/tools.js +508 -0
- package/dist/cli/commands/tui.d.ts +3 -0
- package/dist/cli/commands/tui.js +158 -0
- package/dist/cli/commands/tunnel.d.ts +3 -0
- package/dist/cli/commands/tunnel.js +135 -0
- package/dist/cli/commands/webhooks.d.ts +3 -0
- package/dist/cli/commands/webhooks.js +191 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.js +127 -0
- package/dist/cli/utils/api.d.ts +17 -0
- package/dist/cli/utils/api.js +63 -0
- package/dist/cli/utils/config.d.ts +31 -0
- package/dist/cli/utils/config.js +81 -0
- package/dist/cli/utils/output.d.ts +58 -0
- package/dist/cli/utils/output.js +148 -0
- package/dist/core/deployment.d.ts +30 -0
- package/dist/core/deployment.js +114 -0
- package/dist/core/sandbox-config.d.ts +63 -0
- package/dist/core/sandbox-config.js +148 -0
- package/dist/costs/budget.d.ts +28 -0
- package/dist/costs/budget.js +57 -0
- package/dist/costs/persistence.d.ts +77 -0
- package/dist/costs/persistence.js +210 -0
- package/dist/costs/pricing.d.ts +16 -0
- package/dist/costs/pricing.js +39 -0
- package/dist/costs/token-tracker.d.ts +34 -0
- package/dist/costs/token-tracker.js +141 -0
- package/dist/cron/heartbeat.d.ts +23 -0
- package/dist/cron/heartbeat.js +109 -0
- package/dist/cron/index.d.ts +22 -0
- package/dist/cron/index.js +37 -0
- package/dist/cron/issue-poller.d.ts +15 -0
- package/dist/cron/issue-poller.js +174 -0
- package/dist/cron/scheduler.d.ts +315 -0
- package/dist/cron/scheduler.js +1008 -0
- package/dist/cron/stale-checker.d.ts +16 -0
- package/dist/cron/stale-checker.js +61 -0
- package/dist/cron/templates.d.ts +107 -0
- package/dist/cron/templates.js +395 -0
- package/dist/diagnostics/exporters.d.ts +21 -0
- package/dist/diagnostics/exporters.js +138 -0
- package/dist/diagnostics/index.d.ts +10 -0
- package/dist/diagnostics/index.js +9 -0
- package/dist/diagnostics/middleware.d.ts +12 -0
- package/dist/diagnostics/middleware.js +58 -0
- package/dist/diagnostics/tracer.d.ts +133 -0
- package/dist/diagnostics/tracer.js +257 -0
- package/dist/discovery/index.d.ts +8 -0
- package/dist/discovery/index.js +7 -0
- package/dist/discovery/mdns.d.ts +40 -0
- package/dist/discovery/mdns.js +249 -0
- package/dist/gateway/index.d.ts +35 -0
- package/dist/gateway/index.js +36 -0
- package/dist/gateway/router.d.ts +110 -0
- package/dist/gateway/router.js +649 -0
- package/dist/gateway/types.d.ts +275 -0
- package/dist/gateway/types.js +2 -0
- package/dist/gateway/workflows.d.ts +37 -0
- package/dist/gateway/workflows.js +748 -0
- package/dist/hooks/agent-webhook.d.ts +277 -0
- package/dist/hooks/agent-webhook.js +197 -0
- package/dist/hooks/index.d.ts +13 -0
- package/dist/hooks/index.js +15 -0
- package/dist/hooks/prompt-submit.d.ts +45 -0
- package/dist/hooks/prompt-submit.js +111 -0
- package/dist/hooks/schemas.d.ts +563 -0
- package/dist/hooks/schemas.js +108 -0
- package/dist/hooks/session-end.d.ts +25 -0
- package/dist/hooks/session-end.js +153 -0
- package/dist/hooks/tool-use.d.ts +41 -0
- package/dist/hooks/tool-use.js +201 -0
- package/dist/hooks/types.d.ts +76 -0
- package/dist/hooks/types.js +7 -0
- package/dist/integrations/cloudflare-tunnel.d.ts +78 -0
- package/dist/integrations/cloudflare-tunnel.js +268 -0
- package/dist/integrations/github-client.d.ts +27 -0
- package/dist/integrations/github-client.js +79 -0
- package/dist/integrations/github-projects.d.ts +97 -0
- package/dist/integrations/github-projects.js +433 -0
- package/dist/integrations/github-ticket-sync.d.ts +82 -0
- package/dist/integrations/github-ticket-sync.js +352 -0
- package/dist/integrations/github.d.ts +11 -0
- package/dist/integrations/github.js +241 -0
- package/dist/integrations/jira-client.d.ts +30 -0
- package/dist/integrations/jira-client.js +67 -0
- package/dist/integrations/jira.d.ts +13 -0
- package/dist/integrations/jira.js +108 -0
- package/dist/integrations/linear-client.d.ts +23 -0
- package/dist/integrations/linear-client.js +52 -0
- package/dist/integrations/linear.d.ts +15 -0
- package/dist/integrations/linear.js +312 -0
- package/dist/integrations/tailscale.d.ts +68 -0
- package/dist/integrations/tailscale.js +173 -0
- package/dist/integrations/web-search.d.ts +112 -0
- package/dist/integrations/web-search.js +287 -0
- package/dist/intelligence/index.d.ts +8 -0
- package/dist/intelligence/index.js +8 -0
- package/dist/intelligence/ollama.d.ts +50 -0
- package/dist/intelligence/ollama.js +213 -0
- package/dist/intelligence/rules.d.ts +39 -0
- package/dist/intelligence/rules.js +308 -0
- package/dist/labels/index.d.ts +93 -0
- package/dist/labels/index.js +248 -0
- package/dist/mcp/browser-tools.d.ts +10 -0
- package/dist/mcp/browser-tools.js +16 -0
- package/dist/mcp/client.d.ts +54 -0
- package/dist/mcp/client.js +153 -0
- package/dist/mcp/index.d.ts +12 -0
- package/dist/mcp/index.js +13 -0
- package/dist/mcp/server.d.ts +40 -0
- package/dist/mcp/server.js +826 -0
- package/dist/mcp/tool-adapter.d.ts +49 -0
- package/dist/mcp/tool-adapter.js +193 -0
- package/dist/memory/experience-store.d.ts +121 -0
- package/dist/memory/experience-store.js +439 -0
- package/dist/memory/index.d.ts +8 -0
- package/dist/memory/index.js +25 -0
- package/dist/memory/memory-service.d.ts +312 -0
- package/dist/memory/memory-service.js +1172 -0
- package/dist/memory/memory-watcher.d.ts +116 -0
- package/dist/memory/memory-watcher.js +239 -0
- package/dist/middleware/logging.d.ts +34 -0
- package/dist/middleware/logging.js +184 -0
- package/dist/middleware/rate-limit.d.ts +29 -0
- package/dist/middleware/rate-limit.js +91 -0
- package/dist/notifications/in-app.d.ts +28 -0
- package/dist/notifications/in-app.js +53 -0
- package/dist/notifications/index.d.ts +3 -0
- package/dist/notifications/index.js +3 -0
- package/dist/notifications/push.d.ts +74 -0
- package/dist/notifications/push.js +175 -0
- package/dist/notifications/slack.d.ts +32 -0
- package/dist/notifications/slack.js +157 -0
- package/dist/plugins/clawhub.d.ts +70 -0
- package/dist/plugins/clawhub.js +260 -0
- package/dist/plugins/loader.d.ts +23 -0
- package/dist/plugins/loader.js +140 -0
- package/dist/plugins/marketplace.d.ts +77 -0
- package/dist/plugins/marketplace.js +275 -0
- package/dist/plugins/registry.d.ts +122 -0
- package/dist/plugins/registry.js +352 -0
- package/dist/plugins/sandbox.d.ts +77 -0
- package/dist/plugins/sandbox.js +287 -0
- package/dist/plugins/scaffolder.d.ts +28 -0
- package/dist/plugins/scaffolder.js +409 -0
- package/dist/plugins/sdk.d.ts +35 -0
- package/dist/plugins/sdk.js +8 -0
- package/dist/plugins/search/brave.d.ts +9 -0
- package/dist/plugins/search/brave.js +157 -0
- package/dist/plugins/search/duckduckgo.d.ts +9 -0
- package/dist/plugins/search/duckduckgo.js +171 -0
- package/dist/plugins/search/index.d.ts +13 -0
- package/dist/plugins/search/index.js +23 -0
- package/dist/plugins/search/searxng.d.ts +9 -0
- package/dist/plugins/search/searxng.js +170 -0
- package/dist/plugins/search/serper.d.ts +9 -0
- package/dist/plugins/search/serper.js +135 -0
- package/dist/plugins/search/tavily.d.ts +9 -0
- package/dist/plugins/search/tavily.js +146 -0
- package/dist/plugins/types.d.ts +174 -0
- package/dist/plugins/types.js +8 -0
- package/dist/projects/index.d.ts +133 -0
- package/dist/projects/index.js +897 -0
- package/dist/projects/types.d.ts +444 -0
- package/dist/projects/types.js +207 -0
- package/dist/providers/adapters/anthropic.d.ts +26 -0
- package/dist/providers/adapters/anthropic.js +306 -0
- package/dist/providers/adapters/base.d.ts +53 -0
- package/dist/providers/adapters/base.js +99 -0
- package/dist/providers/adapters/ollama.d.ts +30 -0
- package/dist/providers/adapters/ollama.js +292 -0
- package/dist/providers/ai-sdk.d.ts +178 -0
- package/dist/providers/ai-sdk.js +1552 -0
- package/dist/providers/core/index.d.ts +8 -0
- package/dist/providers/core/index.js +10 -0
- package/dist/providers/core/models.d.ts +31 -0
- package/dist/providers/core/models.js +949 -0
- package/dist/providers/core/types.d.ts +117 -0
- package/dist/providers/core/types.js +83 -0
- package/dist/providers/index.d.ts +7 -0
- package/dist/providers/index.js +7 -0
- package/dist/providers/registry.d.ts +93 -0
- package/dist/providers/registry.js +228 -0
- package/dist/providers/schema-utils.d.ts +23 -0
- package/dist/providers/schema-utils.js +545 -0
- package/dist/providers/types.d.ts +609 -0
- package/dist/providers/types.js +279 -0
- package/dist/queue/failure-handler.d.ts +93 -0
- package/dist/queue/failure-handler.js +379 -0
- package/dist/queue/index.d.ts +23 -0
- package/dist/queue/index.js +86 -0
- package/dist/queue/memory-queue.d.ts +30 -0
- package/dist/queue/memory-queue.js +429 -0
- package/dist/queue/notifications.d.ts +6 -0
- package/dist/queue/notifications.js +128 -0
- package/dist/queue/task-queue.d.ts +55 -0
- package/dist/queue/task-queue.js +518 -0
- package/dist/queue/webhook-queue.d.ts +47 -0
- package/dist/queue/webhook-queue.js +158 -0
- package/dist/routes/agents.d.ts +4 -0
- package/dist/routes/agents.js +45 -0
- package/dist/routes/auth.d.ts +19 -0
- package/dist/routes/auth.js +492 -0
- package/dist/routes/backup.d.ts +6 -0
- package/dist/routes/backup.js +71 -0
- package/dist/routes/chat.d.ts +10 -0
- package/dist/routes/chat.js +1678 -0
- package/dist/routes/clawhub.d.ts +8 -0
- package/dist/routes/clawhub.js +89 -0
- package/dist/routes/costs.d.ts +4 -0
- package/dist/routes/costs.js +78 -0
- package/dist/routes/cron.d.ts +11 -0
- package/dist/routes/cron.js +708 -0
- package/dist/routes/devices.d.ts +9 -0
- package/dist/routes/devices.js +490 -0
- package/dist/routes/discord.d.ts +15 -0
- package/dist/routes/discord.js +524 -0
- package/dist/routes/dlq.d.ts +4 -0
- package/dist/routes/dlq.js +64 -0
- package/dist/routes/gateway.d.ts +4 -0
- package/dist/routes/gateway.js +253 -0
- package/dist/routes/health.d.ts +29 -0
- package/dist/routes/health.js +296 -0
- package/dist/routes/hooks.d.ts +4 -0
- package/dist/routes/hooks.js +170 -0
- package/dist/routes/import.d.ts +9 -0
- package/dist/routes/import.js +540 -0
- package/dist/routes/index.d.ts +38 -0
- package/dist/routes/index.js +39 -0
- package/dist/routes/integrations.d.ts +10 -0
- package/dist/routes/integrations.js +200 -0
- package/dist/routes/labels.d.ts +8 -0
- package/dist/routes/labels.js +240 -0
- package/dist/routes/mcp.d.ts +14 -0
- package/dist/routes/mcp.js +125 -0
- package/dist/routes/memory.d.ts +10 -0
- package/dist/routes/memory.js +622 -0
- package/dist/routes/notifications.d.ts +9 -0
- package/dist/routes/notifications.js +154 -0
- package/dist/routes/oobe.d.ts +10 -0
- package/dist/routes/oobe.js +405 -0
- package/dist/routes/openapi.d.ts +9 -0
- package/dist/routes/openapi.js +537 -0
- package/dist/routes/plugins.d.ts +8 -0
- package/dist/routes/plugins.js +108 -0
- package/dist/routes/projects.d.ts +8 -0
- package/dist/routes/projects.js +592 -0
- package/dist/routes/push.d.ts +8 -0
- package/dist/routes/push.js +75 -0
- package/dist/routes/search.d.ts +4 -0
- package/dist/routes/search.js +189 -0
- package/dist/routes/security.d.ts +10 -0
- package/dist/routes/security.js +189 -0
- package/dist/routes/settings.d.ts +4 -0
- package/dist/routes/settings.js +119 -0
- package/dist/routes/setup.d.ts +11 -0
- package/dist/routes/setup.js +525 -0
- package/dist/routes/skills.d.ts +13 -0
- package/dist/routes/skills.js +152 -0
- package/dist/routes/slack.d.ts +12 -0
- package/dist/routes/slack.js +999 -0
- package/dist/routes/states.d.ts +8 -0
- package/dist/routes/states.js +123 -0
- package/dist/routes/stats.d.ts +6 -0
- package/dist/routes/stats.js +369 -0
- package/dist/routes/summaries.d.ts +4 -0
- package/dist/routes/summaries.js +344 -0
- package/dist/routes/sync.d.ts +13 -0
- package/dist/routes/sync.js +268 -0
- package/dist/routes/tasks.d.ts +4 -0
- package/dist/routes/tasks.js +473 -0
- package/dist/routes/telegram.d.ts +14 -0
- package/dist/routes/telegram.js +420 -0
- package/dist/routes/tickets.d.ts +4 -0
- package/dist/routes/tickets.js +1090 -0
- package/dist/routes/tokens.d.ts +4 -0
- package/dist/routes/tokens.js +83 -0
- package/dist/routes/tools.d.ts +14 -0
- package/dist/routes/tools.js +790 -0
- package/dist/routes/tunnels.d.ts +8 -0
- package/dist/routes/tunnels.js +145 -0
- package/dist/routes/users.d.ts +15 -0
- package/dist/routes/users.js +998 -0
- package/dist/routes/voice.d.ts +8 -0
- package/dist/routes/voice.js +127 -0
- package/dist/routes/webchat.d.ts +11 -0
- package/dist/routes/webchat.js +173 -0
- package/dist/routes/webhook-dedup.d.ts +11 -0
- package/dist/routes/webhook-dedup.js +49 -0
- package/dist/routes/webhooks.d.ts +4 -0
- package/dist/routes/webhooks.js +71 -0
- package/dist/routes/whatsapp.d.ts +14 -0
- package/dist/routes/whatsapp.js +391 -0
- package/dist/security/audit-scanner.d.ts +32 -0
- package/dist/security/audit-scanner.js +217 -0
- package/dist/security/fs-guard.d.ts +41 -0
- package/dist/security/fs-guard.js +206 -0
- package/dist/security/prompt-guard.d.ts +47 -0
- package/dist/security/prompt-guard.js +198 -0
- package/dist/security/ssrf-guard.d.ts +38 -0
- package/dist/security/ssrf-guard.js +266 -0
- package/dist/security/types.d.ts +92 -0
- package/dist/security/types.js +8 -0
- package/dist/server/route-loader.d.ts +15 -0
- package/dist/server/route-loader.js +135 -0
- package/dist/server.d.ts +5 -0
- package/dist/server.js +835 -0
- package/dist/settings/index.d.ts +841 -0
- package/dist/settings/index.js +451 -0
- package/dist/skills/compiler.d.ts +83 -0
- package/dist/skills/compiler.js +358 -0
- package/dist/skills/frontmatter.d.ts +33 -0
- package/dist/skills/frontmatter.js +175 -0
- package/dist/skills/index.d.ts +19 -0
- package/dist/skills/index.js +24 -0
- package/dist/skills/installer.d.ts +22 -0
- package/dist/skills/installer.js +220 -0
- package/dist/skills/loader.d.ts +72 -0
- package/dist/skills/loader.js +484 -0
- package/dist/skills/prompt-builder.d.ts +48 -0
- package/dist/skills/prompt-builder.js +135 -0
- package/dist/skills/registry.d.ts +115 -0
- package/dist/skills/registry.js +225 -0
- package/dist/skills/types.d.ts +202 -0
- package/dist/skills/types.js +24 -0
- package/dist/states/index.d.ts +64 -0
- package/dist/states/index.js +142 -0
- package/dist/storage/adapter.d.ts +146 -0
- package/dist/storage/adapter.js +2 -0
- package/dist/storage/index.d.ts +48 -0
- package/dist/storage/index.js +135 -0
- package/dist/storage/libsql.d.ts +99 -0
- package/dist/storage/libsql.js +1873 -0
- package/dist/storage/migrations.d.ts +65 -0
- package/dist/storage/migrations.js +289 -0
- package/dist/storage/schema.d.ts +10185 -0
- package/dist/storage/schema.js +1113 -0
- package/dist/summaries/extractor.d.ts +56 -0
- package/dist/summaries/extractor.js +377 -0
- package/dist/summaries/index.d.ts +13 -0
- package/dist/summaries/index.js +14 -0
- package/dist/summaries/storage.d.ts +51 -0
- package/dist/summaries/storage.js +101 -0
- package/dist/summaries/templates.d.ts +68 -0
- package/dist/summaries/templates.js +245 -0
- package/dist/sync/adapters/base.d.ts +42 -0
- package/dist/sync/adapters/base.js +142 -0
- package/dist/sync/adapters/github.d.ts +45 -0
- package/dist/sync/adapters/github.js +445 -0
- package/dist/sync/adapters/linear.d.ts +40 -0
- package/dist/sync/adapters/linear.js +434 -0
- package/dist/sync/config.d.ts +388 -0
- package/dist/sync/config.js +281 -0
- package/dist/sync/engine.d.ts +112 -0
- package/dist/sync/engine.js +623 -0
- package/dist/sync/index.d.ts +31 -0
- package/dist/sync/index.js +34 -0
- package/dist/sync/integration.d.ts +53 -0
- package/dist/sync/integration.js +231 -0
- package/dist/sync/types.d.ts +249 -0
- package/dist/sync/types.js +30 -0
- package/dist/tickets/index.d.ts +139 -0
- package/dist/tickets/index.js +1406 -0
- package/dist/tickets/types.d.ts +817 -0
- package/dist/tickets/types.js +310 -0
- package/dist/tools/adapters.d.ts +56 -0
- package/dist/tools/adapters.js +183 -0
- package/dist/tools/index.d.ts +66 -0
- package/dist/tools/index.js +105 -0
- package/dist/tools/types.d.ts +117 -0
- package/dist/tools/types.js +20 -0
- package/dist/types/agent.d.ts +101 -0
- package/dist/types/agent.js +2 -0
- package/dist/types/errors.d.ts +150 -0
- package/dist/types/errors.js +338 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.js +3 -0
- package/dist/types/summary.d.ts +638 -0
- package/dist/types/summary.js +137 -0
- package/dist/types/task.d.ts +123 -0
- package/dist/types/task.js +46 -0
- package/dist/utils/ai-cache.d.ts +72 -0
- package/dist/utils/ai-cache.js +204 -0
- package/dist/utils/ai-inference.d.ts +57 -0
- package/dist/utils/ai-inference.js +190 -0
- package/dist/utils/ai-responder.d.ts +44 -0
- package/dist/utils/ai-responder.js +272 -0
- package/dist/utils/circuit-breaker.d.ts +139 -0
- package/dist/utils/circuit-breaker.js +281 -0
- package/dist/utils/config-loader.d.ts +12 -0
- package/dist/utils/config-loader.js +44 -0
- package/dist/utils/crypto.d.ts +10 -0
- package/dist/utils/crypto.js +59 -0
- package/dist/utils/env-validator.d.ts +44 -0
- package/dist/utils/env-validator.js +236 -0
- package/dist/utils/file-lock.d.ts +85 -0
- package/dist/utils/file-lock.js +204 -0
- package/dist/utils/logger.d.ts +153 -0
- package/dist/utils/logger.js +282 -0
- package/dist/utils/metrics.d.ts +183 -0
- package/dist/utils/metrics.js +345 -0
- package/dist/utils/security.d.ts +90 -0
- package/dist/utils/security.js +347 -0
- package/dist/voice/index.d.ts +79 -0
- package/dist/voice/index.js +144 -0
- package/dist/voice/stt/whisper.d.ts +13 -0
- package/dist/voice/stt/whisper.js +116 -0
- package/dist/voice/tts/elevenlabs.d.ts +18 -0
- package/dist/voice/tts/elevenlabs.js +178 -0
- package/dist/voice/tts/openai-tts.d.ts +19 -0
- package/dist/voice/tts/openai-tts.js +127 -0
- package/dist/voice/tts/system.d.ts +26 -0
- package/dist/voice/tts/system.js +146 -0
- package/dist/voice/wake-word.d.ts +44 -0
- package/dist/voice/wake-word.js +145 -0
- package/docker-compose.yml +222 -0
- package/package.json +154 -0
- package/profclaw.mjs +24 -0
- package/skills/1password/SKILL.md +155 -0
- package/skills/api-tester/SKILL.md +177 -0
- package/skills/apple-notes/SKILL.md +167 -0
- package/skills/apple-reminders/SKILL.md +178 -0
- package/skills/bear-notes/SKILL.md +166 -0
- package/skills/blogwatcher/SKILL.md +177 -0
- package/skills/camsnap/SKILL.md +130 -0
- package/skills/code-generation/SKILL.md +139 -0
- package/skills/code-review/SKILL.md +116 -0
- package/skills/coding-agent/SKILL.md +184 -0
- package/skills/cron-manager/SKILL.md +141 -0
- package/skills/debug-helper/SKILL.md +134 -0
- package/skills/docker-ops/SKILL.md +246 -0
- package/skills/file-manager/SKILL.md +160 -0
- package/skills/git-workflow/SKILL.md +171 -0
- package/skills/github-issues/SKILL.md +244 -0
- package/skills/gog/SKILL.md +191 -0
- package/skills/goplaces/SKILL.md +156 -0
- package/skills/healthcheck/SKILL.md +270 -0
- package/skills/himalaya/SKILL.md +165 -0
- package/skills/mcp-discovery/SKILL.md +109 -0
- package/skills/memory-manager/SKILL.md +151 -0
- package/skills/model-usage/SKILL.md +177 -0
- package/skills/nano-banana-pro/SKILL.md +214 -0
- package/skills/nano-pdf/SKILL.md +165 -0
- package/skills/notion/SKILL.md +147 -0
- package/skills/obsidian/SKILL.md +163 -0
- package/skills/openai-image-gen/SKILL.md +194 -0
- package/skills/openai-whisper/SKILL.md +98 -0
- package/skills/openai-whisper-api/SKILL.md +130 -0
- package/skills/openhue/SKILL.md +203 -0
- package/skills/oracle/SKILL.md +236 -0
- package/skills/phone-control/SKILL.md +201 -0
- package/skills/profclaw-assistant/SKILL.md +81 -0
- package/skills/profclaw-projects/SKILL.md +68 -0
- package/skills/profclaw-tickets/SKILL.md +91 -0
- package/skills/session-logs/SKILL.md +216 -0
- package/skills/sherpa-onnx-tts/SKILL.md +134 -0
- package/skills/skill-creator/SKILL.md +183 -0
- package/skills/songsee/SKILL.md +170 -0
- package/skills/spotify-player/SKILL.md +254 -0
- package/skills/summarize/SKILL.md +155 -0
- package/skills/system-admin/SKILL.md +179 -0
- package/skills/things-mac/SKILL.md +179 -0
- package/skills/tmux/SKILL.md +170 -0
- package/skills/trello/SKILL.md +154 -0
- package/skills/video-frames/SKILL.md +127 -0
- package/skills/weather/SKILL.md +186 -0
- package/skills/web-research/SKILL.md +128 -0
- package/skills/xurl/SKILL.md +198 -0
- package/ui/README.md +73 -0
- package/ui/dist/assets/ActivityView-CkPgKhwm.js +1 -0
- package/ui/dist/assets/AgentList-C3SVdeEz.js +1 -0
- package/ui/dist/assets/AnalyticsDashboard-DVU--vlP.js +1 -0
- package/ui/dist/assets/AreaChart-B5qMEGWj.js +1 -0
- package/ui/dist/assets/CartesianChart-B50bcUJi.js +36 -0
- package/ui/dist/assets/ChatView-BZFJs7w_.js +10 -0
- package/ui/dist/assets/CostsDashboard-ChfH8BlG.js +1 -0
- package/ui/dist/assets/EstimateSelect-CLpB4NQO.js +1 -0
- package/ui/dist/assets/FloatingChatbot-CBzBY9a0.js +2 -0
- package/ui/dist/assets/InviteCodeManagement-DsbdPa6W.js +2 -0
- package/ui/dist/assets/ProjectDetail-BEM3tFXg.js +2 -0
- package/ui/dist/assets/ProjectDetail-D1-0B2xV.css +1 -0
- package/ui/dist/assets/ProjectIcon-CN1FmFAk.js +1 -0
- package/ui/dist/assets/ProjectList-DSDaNhxQ.js +4 -0
- package/ui/dist/assets/Settings-dPVcqC_d.js +6 -0
- package/ui/dist/assets/StatusIndicator-DA3NAo_b.js +1 -0
- package/ui/dist/assets/SummaryDetail-Bjnf9lT8.js +27 -0
- package/ui/dist/assets/SummaryList-ENwKDBKW.js +1 -0
- package/ui/dist/assets/TaskDetail-DnwG6MzB.js +1 -0
- package/ui/dist/assets/TaskList-D9Ug_HiV.js +1 -0
- package/ui/dist/assets/TicketBoard-CviH1571.js +1 -0
- package/ui/dist/assets/TicketDetail-8Jk8O-33.js +1 -0
- package/ui/dist/assets/TicketList-B-iV4rRA.js +1 -0
- package/ui/dist/assets/UserManagement-CPZ8s7s2.js +2 -0
- package/ui/dist/assets/ViewSwitcher-BUyOOWDI.js +1 -0
- package/ui/dist/assets/alert-dialog-BOmnTkN-.js +7 -0
- package/ui/dist/assets/archive-D5my9zOG.js +1 -0
- package/ui/dist/assets/badge-B4ov81_m.js +1 -0
- package/ui/dist/assets/brain-C53ElFLD.js +1 -0
- package/ui/dist/assets/bug-D0TJoCYn.js +1 -0
- package/ui/dist/assets/calendar-BkWIhKa1.js +1 -0
- package/ui/dist/assets/chevron-up-BRTtndUZ.js +1 -0
- package/ui/dist/assets/circle-x-BN89YhbS.js +1 -0
- package/ui/dist/assets/constants-fc7TFI7u.js +1 -0
- package/ui/dist/assets/cpu-B41x1-vV.js +1 -0
- package/ui/dist/assets/database-D9Cnfmzj.js +1 -0
- package/ui/dist/assets/defineProperty-CoXUr7_6.js +2 -0
- package/ui/dist/assets/dialog-DrWB4EYD.js +1 -0
- package/ui/dist/assets/element-adapter-DL0DQilL.js +4 -0
- package/ui/dist/assets/ellipsis-NuUWekvu.js +1 -0
- package/ui/dist/assets/ellipsis-vertical-BueMfuCw.js +1 -0
- package/ui/dist/assets/file-code-HR9829Jc.js +1 -0
- package/ui/dist/assets/folder-open-C_7oYEqe.js +1 -0
- package/ui/dist/assets/funnel-B5gmNXGf.js +1 -0
- package/ui/dist/assets/git-branch-BRMiJmV3.js +1 -0
- package/ui/dist/assets/git-commit-horizontal-CXOUQeJI.js +1 -0
- package/ui/dist/assets/globe-CCspjvus.js +1 -0
- package/ui/dist/assets/hash-g3102kPC.js +1 -0
- package/ui/dist/assets/history-CNqcBBrV.js +1 -0
- package/ui/dist/assets/index-27mTPKuh.js +1 -0
- package/ui/dist/assets/index-BMx3fH-e.js +1 -0
- package/ui/dist/assets/index-C9jNQXzL.js +1 -0
- package/ui/dist/assets/index-CEZ6R2Uw.js +7 -0
- package/ui/dist/assets/index-DURTouJI.js +1 -0
- package/ui/dist/assets/index-WclMPci1.css +1 -0
- package/ui/dist/assets/index-kb4AJXUB.js +67 -0
- package/ui/dist/assets/layers-CLXiHN6o.js +1 -0
- package/ui/dist/assets/layout-dashboard-B07MFhBs.js +1 -0
- package/ui/dist/assets/lightbulb-B2dgG5ks.js +1 -0
- package/ui/dist/assets/link-2-BxNmr9hL.js +1 -0
- package/ui/dist/assets/markdown-renderer-CjU6hBcW.js +36 -0
- package/ui/dist/assets/message-square-Bf2-CVbt.js +1 -0
- package/ui/dist/assets/pencil-D096Ey62.js +1 -0
- package/ui/dist/assets/play-DfdcSI3x.js +1 -0
- package/ui/dist/assets/popover-BV0QJDQq.js +1 -0
- package/ui/dist/assets/progress-DjPEDJfI.js +1 -0
- package/ui/dist/assets/rocket-CPsTc-5G.js +1 -0
- package/ui/dist/assets/select-LsO16slr.js +1 -0
- package/ui/dist/assets/send-BDYBZDUZ.js +1 -0
- package/ui/dist/assets/server-B3k6noce.js +1 -0
- package/ui/dist/assets/settings-2-Cu4xTjhG.js +1 -0
- package/ui/dist/assets/sheet-BScLnPKX.js +1 -0
- package/ui/dist/assets/shield-check-CQqkwufI.js +1 -0
- package/ui/dist/assets/shield-off-ZFruH9KO.js +1 -0
- package/ui/dist/assets/skeleton-CtkIA_MU.js +1 -0
- package/ui/dist/assets/smartphone-DnoksVkc.js +1 -0
- package/ui/dist/assets/square-uD9ZHMfW.js +1 -0
- package/ui/dist/assets/switch-MQPnwGJK.js +1 -0
- package/ui/dist/assets/table-B8cqlywA.js +1 -0
- package/ui/dist/assets/tag-wEJQRWlV.js +1 -0
- package/ui/dist/assets/textarea-D5LJCOGl.js +1 -0
- package/ui/dist/assets/timer-mbGHegmr.js +1 -0
- package/ui/dist/assets/tooltip-Df1CunSp.js +1 -0
- package/ui/dist/assets/trash-2-B4oAXsX-.js +1 -0
- package/ui/dist/assets/trending-up-BGWxvlmZ.js +1 -0
- package/ui/dist/assets/wand-sparkles-CZy4xvL3.js +1 -0
- package/ui/dist/assets/wrench-ByZkjO6m.js +1 -0
- package/ui/dist/audio-worklets/vad-processor.js +132 -0
- package/ui/dist/brand/profclaw-appicon-192.png +0 -0
- package/ui/dist/brand/profclaw-appicon-512.png +0 -0
- package/ui/dist/brand/profclaw-appicon-shadow.svg +51 -0
- package/ui/dist/brand/profclaw-appicon.svg +50 -0
- package/ui/dist/brand/profclaw-favicon-coral-bg-128.png +0 -0
- package/ui/dist/brand/profclaw-favicon-coral-bg-64.png +0 -0
- package/ui/dist/brand/profclaw-favicon-coral-bg.svg +52 -0
- package/ui/dist/brand/profclaw-favicon-coral-body-128.png +0 -0
- package/ui/dist/brand/profclaw-favicon-coral-body.svg +41 -0
- package/ui/dist/brand/profclaw-favicon-shadow-128.png +0 -0
- package/ui/dist/brand/profclaw-favicon-shadow-64.png +0 -0
- package/ui/dist/brand/profclaw-favicon-shadow.svg +51 -0
- package/ui/dist/brand/profclaw-mark-coral-256.png +0 -0
- package/ui/dist/brand/profclaw-mark-coral-64.png +0 -0
- package/ui/dist/brand/profclaw-mark-coral.svg +31 -0
- package/ui/dist/brand/profclaw-mono-white.svg +18 -0
- package/ui/dist/brand/profclaw-text-dark.svg +18 -0
- package/ui/dist/brand/profclaw-text-light.svg +18 -0
- package/ui/dist/brand/profclaw-wordmark-dark.svg +48 -0
- package/ui/dist/brand/profclaw-wordmark-light.svg +48 -0
- package/ui/dist/brand/safari-pinned-tab.svg +15 -0
- package/ui/dist/favicon/android-chrome-192x192.png +0 -0
- package/ui/dist/favicon/android-chrome-384x384.png +0 -0
- package/ui/dist/favicon/android-chrome-512x512.png +0 -0
- package/ui/dist/favicon/apple-touch-icon.png +0 -0
- package/ui/dist/favicon/browserconfig.xml +9 -0
- package/ui/dist/favicon/favicon-16x16.png +0 -0
- package/ui/dist/favicon/favicon-32x32.png +0 -0
- package/ui/dist/favicon/favicon.ico +0 -0
- package/ui/dist/favicon/mstile-150x150.png +0 -0
- package/ui/dist/favicon/safari-pinned-tab.svg +46 -0
- package/ui/dist/favicon/site.webmanifest +22 -0
- package/ui/dist/index.html +32 -0
- package/ui/dist/manifest.json +49 -0
- package/ui/dist/sw.js +124 -0
- package/ui/dist/vite.svg +1 -0
|
@@ -0,0 +1,1172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Service
|
|
3
|
+
*
|
|
4
|
+
* Semantic memory system with embeddings and hybrid search.
|
|
5
|
+
* Based on OpenClaw's memory architecture.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Token-based chunking with overlap
|
|
9
|
+
* - Multiple embedding providers (OpenAI, Ollama)
|
|
10
|
+
* - Hybrid search (vector + FTS5)
|
|
11
|
+
* - File change detection with hash
|
|
12
|
+
* - Embedding cache for efficiency
|
|
13
|
+
*/
|
|
14
|
+
import { randomUUID } from 'node:crypto';
|
|
15
|
+
import { createHash } from 'node:crypto';
|
|
16
|
+
import { readFile, stat, readdir } from 'node:fs/promises';
|
|
17
|
+
import { join, relative, extname } from 'node:path';
|
|
18
|
+
import { getClient } from '../storage/index.js';
|
|
19
|
+
import { getEmbeddingService } from '../ai/embedding-service.js';
|
|
20
|
+
import { logger } from '../utils/logger.js';
|
|
21
|
+
export const DEFAULT_MEMORY_CONFIG = {
|
|
22
|
+
sources: ['memory'],
|
|
23
|
+
provider: 'auto',
|
|
24
|
+
fallback: 'none',
|
|
25
|
+
model: 'text-embedding-3-small',
|
|
26
|
+
chunking: {
|
|
27
|
+
tokens: 400,
|
|
28
|
+
overlap: 80,
|
|
29
|
+
},
|
|
30
|
+
query: {
|
|
31
|
+
maxResults: 6,
|
|
32
|
+
minScore: 0.35,
|
|
33
|
+
hybrid: {
|
|
34
|
+
enabled: true,
|
|
35
|
+
vectorWeight: 0.7,
|
|
36
|
+
textWeight: 0.3,
|
|
37
|
+
candidateMultiplier: 4,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
sync: {
|
|
41
|
+
onSessionStart: true,
|
|
42
|
+
onSearch: true,
|
|
43
|
+
watch: true,
|
|
44
|
+
watchDebounceMs: 1500,
|
|
45
|
+
intervalMinutes: 0,
|
|
46
|
+
},
|
|
47
|
+
paths: {
|
|
48
|
+
memoryDir: 'memory',
|
|
49
|
+
memoryFile: 'MEMORY.md',
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
// Database Initialization
|
|
53
|
+
/**
|
|
54
|
+
* Initialize memory tables including FTS5 virtual table
|
|
55
|
+
*/
|
|
56
|
+
export async function initMemoryTables() {
|
|
57
|
+
const client = getClient();
|
|
58
|
+
// Memory files table
|
|
59
|
+
await client.execute(`
|
|
60
|
+
CREATE TABLE IF NOT EXISTS memory_files (
|
|
61
|
+
path TEXT PRIMARY KEY,
|
|
62
|
+
source TEXT NOT NULL DEFAULT 'memory',
|
|
63
|
+
hash TEXT NOT NULL,
|
|
64
|
+
mtime INTEGER NOT NULL,
|
|
65
|
+
size INTEGER NOT NULL,
|
|
66
|
+
user_id TEXT,
|
|
67
|
+
project_id TEXT,
|
|
68
|
+
updated_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
69
|
+
)
|
|
70
|
+
`);
|
|
71
|
+
// Memory chunks table
|
|
72
|
+
await client.execute(`
|
|
73
|
+
CREATE TABLE IF NOT EXISTS memory_chunks (
|
|
74
|
+
id TEXT PRIMARY KEY,
|
|
75
|
+
path TEXT NOT NULL,
|
|
76
|
+
source TEXT NOT NULL DEFAULT 'memory',
|
|
77
|
+
start_line INTEGER NOT NULL,
|
|
78
|
+
end_line INTEGER NOT NULL,
|
|
79
|
+
hash TEXT NOT NULL,
|
|
80
|
+
text TEXT NOT NULL,
|
|
81
|
+
model TEXT NOT NULL,
|
|
82
|
+
embedding BLOB,
|
|
83
|
+
embedding_dims INTEGER,
|
|
84
|
+
user_id TEXT,
|
|
85
|
+
project_id TEXT,
|
|
86
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
87
|
+
updated_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
88
|
+
)
|
|
89
|
+
`);
|
|
90
|
+
// Embedding cache table
|
|
91
|
+
await client.execute(`
|
|
92
|
+
CREATE TABLE IF NOT EXISTS embedding_cache (
|
|
93
|
+
id TEXT PRIMARY KEY,
|
|
94
|
+
provider TEXT NOT NULL,
|
|
95
|
+
model TEXT NOT NULL,
|
|
96
|
+
provider_key TEXT NOT NULL,
|
|
97
|
+
hash TEXT NOT NULL,
|
|
98
|
+
embedding BLOB NOT NULL,
|
|
99
|
+
dims INTEGER,
|
|
100
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
101
|
+
updated_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
102
|
+
)
|
|
103
|
+
`);
|
|
104
|
+
// Memory meta table
|
|
105
|
+
await client.execute(`
|
|
106
|
+
CREATE TABLE IF NOT EXISTS memory_meta (
|
|
107
|
+
key TEXT PRIMARY KEY,
|
|
108
|
+
value TEXT NOT NULL,
|
|
109
|
+
updated_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
110
|
+
)
|
|
111
|
+
`);
|
|
112
|
+
// Memory sessions table
|
|
113
|
+
await client.execute(`
|
|
114
|
+
CREATE TABLE IF NOT EXISTS memory_sessions (
|
|
115
|
+
id TEXT PRIMARY KEY,
|
|
116
|
+
name TEXT,
|
|
117
|
+
conversation_id TEXT,
|
|
118
|
+
user_id TEXT,
|
|
119
|
+
project_id TEXT,
|
|
120
|
+
memory_enabled INTEGER NOT NULL DEFAULT 1,
|
|
121
|
+
memory_last_sync_at INTEGER,
|
|
122
|
+
total_tokens INTEGER NOT NULL DEFAULT 0,
|
|
123
|
+
total_messages INTEGER NOT NULL DEFAULT 0,
|
|
124
|
+
total_cost INTEGER NOT NULL DEFAULT 0,
|
|
125
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
126
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
127
|
+
updated_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
128
|
+
last_active_at INTEGER DEFAULT (unixepoch())
|
|
129
|
+
)
|
|
130
|
+
`);
|
|
131
|
+
// FTS5 virtual table for text search
|
|
132
|
+
try {
|
|
133
|
+
await client.execute(`
|
|
134
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS memory_fts USING fts5(
|
|
135
|
+
text,
|
|
136
|
+
id UNINDEXED,
|
|
137
|
+
path UNINDEXED,
|
|
138
|
+
source UNINDEXED,
|
|
139
|
+
model UNINDEXED,
|
|
140
|
+
start_line UNINDEXED,
|
|
141
|
+
end_line UNINDEXED
|
|
142
|
+
)
|
|
143
|
+
`);
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
// FTS5 might not be available in all SQLite builds
|
|
147
|
+
logger.warn('[Memory] FTS5 not available, text search will be slower');
|
|
148
|
+
}
|
|
149
|
+
// Indexes
|
|
150
|
+
await client.execute(`
|
|
151
|
+
CREATE INDEX IF NOT EXISTS idx_memory_chunks_path ON memory_chunks(path)
|
|
152
|
+
`);
|
|
153
|
+
await client.execute(`
|
|
154
|
+
CREATE INDEX IF NOT EXISTS idx_memory_chunks_hash ON memory_chunks(hash)
|
|
155
|
+
`);
|
|
156
|
+
await client.execute(`
|
|
157
|
+
CREATE INDEX IF NOT EXISTS idx_embedding_cache_hash ON embedding_cache(provider, model, hash)
|
|
158
|
+
`);
|
|
159
|
+
logger.info('[Memory] Tables initialized');
|
|
160
|
+
}
|
|
161
|
+
// Chunking
|
|
162
|
+
/**
|
|
163
|
+
* Estimate token count for a string (rough approximation: 4 chars = 1 token)
|
|
164
|
+
*/
|
|
165
|
+
export function estimateTokens(text) {
|
|
166
|
+
return Math.ceil(text.length / 4);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Split text into chunks with token-based boundaries and overlap
|
|
170
|
+
*/
|
|
171
|
+
export function chunkText(text, config = DEFAULT_MEMORY_CONFIG) {
|
|
172
|
+
const { tokens: maxTokens, overlap } = config.chunking;
|
|
173
|
+
const lines = text.split('\n');
|
|
174
|
+
const chunks = [];
|
|
175
|
+
let currentChunk = [];
|
|
176
|
+
let currentTokens = 0;
|
|
177
|
+
let startLine = 1;
|
|
178
|
+
for (let i = 0; i < lines.length; i++) {
|
|
179
|
+
const line = lines[i];
|
|
180
|
+
const lineTokens = estimateTokens(line);
|
|
181
|
+
// If adding this line would exceed max tokens, save current chunk
|
|
182
|
+
if (currentTokens + lineTokens > maxTokens && currentChunk.length > 0) {
|
|
183
|
+
chunks.push({
|
|
184
|
+
text: currentChunk.join('\n'),
|
|
185
|
+
startLine,
|
|
186
|
+
endLine: startLine + currentChunk.length - 1,
|
|
187
|
+
});
|
|
188
|
+
// Calculate overlap: keep last N tokens worth of lines
|
|
189
|
+
let overlapTokens = 0;
|
|
190
|
+
const overlapLines = [];
|
|
191
|
+
for (let j = currentChunk.length - 1; j >= 0 && overlapTokens < overlap; j--) {
|
|
192
|
+
overlapLines.unshift(currentChunk[j]);
|
|
193
|
+
overlapTokens += estimateTokens(currentChunk[j]);
|
|
194
|
+
}
|
|
195
|
+
currentChunk = overlapLines;
|
|
196
|
+
currentTokens = overlapTokens;
|
|
197
|
+
startLine = startLine + currentChunk.length - overlapLines.length;
|
|
198
|
+
}
|
|
199
|
+
currentChunk.push(line);
|
|
200
|
+
currentTokens += lineTokens;
|
|
201
|
+
}
|
|
202
|
+
// Don't forget the last chunk
|
|
203
|
+
if (currentChunk.length > 0) {
|
|
204
|
+
chunks.push({
|
|
205
|
+
text: currentChunk.join('\n'),
|
|
206
|
+
startLine,
|
|
207
|
+
endLine: startLine + currentChunk.length - 1,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
return chunks;
|
|
211
|
+
}
|
|
212
|
+
// Hashing
|
|
213
|
+
/**
|
|
214
|
+
* Generate SHA256 hash of content
|
|
215
|
+
*/
|
|
216
|
+
export function hashContent(content) {
|
|
217
|
+
return createHash('sha256').update(content).digest('hex');
|
|
218
|
+
}
|
|
219
|
+
// File Sync
|
|
220
|
+
/**
|
|
221
|
+
* Sync memory files from disk to database
|
|
222
|
+
*/
|
|
223
|
+
export async function syncMemoryFiles(basePath, config = DEFAULT_MEMORY_CONFIG) {
|
|
224
|
+
const client = getClient();
|
|
225
|
+
const embeddingService = getEmbeddingService();
|
|
226
|
+
const stats = { synced: 0, added: 0, updated: 0, removed: 0 };
|
|
227
|
+
// Get all markdown files in memory directory
|
|
228
|
+
const files = await findMemoryFiles(basePath, config);
|
|
229
|
+
// Get existing files from DB
|
|
230
|
+
const existingResult = await client.execute({
|
|
231
|
+
sql: `SELECT path, hash FROM memory_files WHERE source = 'memory'`,
|
|
232
|
+
args: [],
|
|
233
|
+
});
|
|
234
|
+
const existingFiles = new Map(existingResult.rows.map((row) => [String(row.path), String(row.hash)]));
|
|
235
|
+
// Process each file
|
|
236
|
+
for (const filePath of files) {
|
|
237
|
+
try {
|
|
238
|
+
const content = await readFile(filePath, 'utf-8');
|
|
239
|
+
const fileStat = await stat(filePath);
|
|
240
|
+
const hash = hashContent(content);
|
|
241
|
+
const relativePath = relative(basePath, filePath);
|
|
242
|
+
const existingHash = existingFiles.get(relativePath);
|
|
243
|
+
if (!existingHash) {
|
|
244
|
+
// New file
|
|
245
|
+
await indexFile(relativePath, content, fileStat, 'memory', config, embeddingService);
|
|
246
|
+
stats.added++;
|
|
247
|
+
}
|
|
248
|
+
else if (existingHash !== hash) {
|
|
249
|
+
// Updated file
|
|
250
|
+
await reindexFile(relativePath, content, fileStat, 'memory', config, embeddingService);
|
|
251
|
+
stats.updated++;
|
|
252
|
+
}
|
|
253
|
+
existingFiles.delete(relativePath);
|
|
254
|
+
stats.synced++;
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
logger.error(`[Memory] Error syncing file ${filePath}:`, error);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
// Remove files that no longer exist
|
|
261
|
+
for (const [removedPath] of existingFiles.entries()) {
|
|
262
|
+
await removeFile(removedPath);
|
|
263
|
+
stats.removed++;
|
|
264
|
+
}
|
|
265
|
+
// Update last sync time
|
|
266
|
+
await client.execute({
|
|
267
|
+
sql: `INSERT OR REPLACE INTO memory_meta (key, value, updated_at) VALUES ('last_sync_at', ?, unixepoch())`,
|
|
268
|
+
args: [Date.now().toString()],
|
|
269
|
+
});
|
|
270
|
+
logger.info(`[Memory] Sync complete: ${stats.added} added, ${stats.updated} updated, ${stats.removed} removed`);
|
|
271
|
+
return stats;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Find all memory files in a directory
|
|
275
|
+
*/
|
|
276
|
+
async function findMemoryFiles(basePath, config) {
|
|
277
|
+
const files = [];
|
|
278
|
+
const validExtensions = ['.md', '.txt', '.markdown'];
|
|
279
|
+
try {
|
|
280
|
+
// Check for MEMORY.md in base path
|
|
281
|
+
const memoryFile = join(basePath, config.paths.memoryFile);
|
|
282
|
+
try {
|
|
283
|
+
await stat(memoryFile);
|
|
284
|
+
files.push(memoryFile);
|
|
285
|
+
}
|
|
286
|
+
catch {
|
|
287
|
+
// MEMORY.md doesn't exist, that's okay
|
|
288
|
+
}
|
|
289
|
+
// Check for memory directory
|
|
290
|
+
const memoryDir = join(basePath, config.paths.memoryDir);
|
|
291
|
+
try {
|
|
292
|
+
const entries = await readdir(memoryDir, { withFileTypes: true });
|
|
293
|
+
for (const entry of entries) {
|
|
294
|
+
if (entry.isFile() && validExtensions.includes(extname(entry.name).toLowerCase())) {
|
|
295
|
+
files.push(join(memoryDir, entry.name));
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
catch {
|
|
300
|
+
// Memory directory doesn't exist, that's okay
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
catch (error) {
|
|
304
|
+
logger.error('[Memory] Error finding memory files:', error);
|
|
305
|
+
}
|
|
306
|
+
return files;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Index a new file
|
|
310
|
+
*/
|
|
311
|
+
async function indexFile(path, content, fileStat, source, config, embeddingService) {
|
|
312
|
+
const client = getClient();
|
|
313
|
+
const hash = hashContent(content);
|
|
314
|
+
// Insert file record
|
|
315
|
+
await client.execute({
|
|
316
|
+
sql: `INSERT INTO memory_files (path, source, hash, mtime, size) VALUES (?, ?, ?, ?, ?)`,
|
|
317
|
+
args: [path, source, hash, Math.floor(fileStat.mtimeMs), fileStat.size],
|
|
318
|
+
});
|
|
319
|
+
// Chunk and index content
|
|
320
|
+
const chunks = chunkText(content, config);
|
|
321
|
+
for (const chunk of chunks) {
|
|
322
|
+
const chunkId = randomUUID();
|
|
323
|
+
const chunkHash = hashContent(chunk.text);
|
|
324
|
+
// Generate embedding
|
|
325
|
+
let embedding = null;
|
|
326
|
+
try {
|
|
327
|
+
embedding = await embeddingService.generateEmbedding(chunk.text);
|
|
328
|
+
}
|
|
329
|
+
catch {
|
|
330
|
+
logger.warn(`[Memory] Failed to generate embedding for chunk ${chunkId}`);
|
|
331
|
+
}
|
|
332
|
+
// Insert chunk
|
|
333
|
+
await client.execute({
|
|
334
|
+
sql: `INSERT INTO memory_chunks (id, path, source, start_line, end_line, hash, text, model, embedding, embedding_dims)
|
|
335
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
336
|
+
args: [
|
|
337
|
+
chunkId,
|
|
338
|
+
path,
|
|
339
|
+
source,
|
|
340
|
+
chunk.startLine,
|
|
341
|
+
chunk.endLine,
|
|
342
|
+
chunkHash,
|
|
343
|
+
chunk.text,
|
|
344
|
+
config.model,
|
|
345
|
+
embedding ? new Float32Array(embedding).buffer : null,
|
|
346
|
+
embedding?.length || null,
|
|
347
|
+
],
|
|
348
|
+
});
|
|
349
|
+
// Insert into FTS
|
|
350
|
+
try {
|
|
351
|
+
await client.execute({
|
|
352
|
+
sql: `INSERT INTO memory_fts (text, id, path, source, model, start_line, end_line)
|
|
353
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
354
|
+
args: [chunk.text, chunkId, path, source, config.model, chunk.startLine, chunk.endLine],
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
catch {
|
|
358
|
+
// FTS5 might not be available
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Reindex an updated file
|
|
364
|
+
*/
|
|
365
|
+
async function reindexFile(path, content, fileStat, source, config, embeddingService) {
|
|
366
|
+
// Remove old chunks
|
|
367
|
+
await removeFileChunks(path);
|
|
368
|
+
// Reindex
|
|
369
|
+
const client = getClient();
|
|
370
|
+
const hash = hashContent(content);
|
|
371
|
+
// Update file record
|
|
372
|
+
await client.execute({
|
|
373
|
+
sql: `UPDATE memory_files SET hash = ?, mtime = ?, size = ?, updated_at = unixepoch() WHERE path = ?`,
|
|
374
|
+
args: [hash, Math.floor(fileStat.mtimeMs), fileStat.size, path],
|
|
375
|
+
});
|
|
376
|
+
// Re-chunk and index
|
|
377
|
+
const chunks = chunkText(content, config);
|
|
378
|
+
for (const chunk of chunks) {
|
|
379
|
+
const chunkId = randomUUID();
|
|
380
|
+
const chunkHash = hashContent(chunk.text);
|
|
381
|
+
let embedding = null;
|
|
382
|
+
try {
|
|
383
|
+
embedding = await embeddingService.generateEmbedding(chunk.text);
|
|
384
|
+
}
|
|
385
|
+
catch {
|
|
386
|
+
logger.warn(`[Memory] Failed to generate embedding for chunk ${chunkId}`);
|
|
387
|
+
}
|
|
388
|
+
await client.execute({
|
|
389
|
+
sql: `INSERT INTO memory_chunks (id, path, source, start_line, end_line, hash, text, model, embedding, embedding_dims)
|
|
390
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
391
|
+
args: [
|
|
392
|
+
chunkId,
|
|
393
|
+
path,
|
|
394
|
+
source,
|
|
395
|
+
chunk.startLine,
|
|
396
|
+
chunk.endLine,
|
|
397
|
+
chunkHash,
|
|
398
|
+
chunk.text,
|
|
399
|
+
config.model,
|
|
400
|
+
embedding ? new Float32Array(embedding).buffer : null,
|
|
401
|
+
embedding?.length || null,
|
|
402
|
+
],
|
|
403
|
+
});
|
|
404
|
+
try {
|
|
405
|
+
await client.execute({
|
|
406
|
+
sql: `INSERT INTO memory_fts (text, id, path, source, model, start_line, end_line)
|
|
407
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
408
|
+
args: [chunk.text, chunkId, path, source, config.model, chunk.startLine, chunk.endLine],
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
catch {
|
|
412
|
+
// FTS5 might not be available
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Remove file chunks from database
|
|
418
|
+
*/
|
|
419
|
+
async function removeFileChunks(path) {
|
|
420
|
+
const client = getClient();
|
|
421
|
+
// Get chunk IDs for FTS deletion
|
|
422
|
+
const chunks = await client.execute({
|
|
423
|
+
sql: `SELECT id FROM memory_chunks WHERE path = ?`,
|
|
424
|
+
args: [path],
|
|
425
|
+
});
|
|
426
|
+
// Delete from FTS
|
|
427
|
+
for (const chunk of chunks.rows) {
|
|
428
|
+
try {
|
|
429
|
+
await client.execute({
|
|
430
|
+
sql: `DELETE FROM memory_fts WHERE id = ?`,
|
|
431
|
+
args: [chunk.id],
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
catch {
|
|
435
|
+
// FTS might not be available
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
// Delete chunks
|
|
439
|
+
await client.execute({
|
|
440
|
+
sql: `DELETE FROM memory_chunks WHERE path = ?`,
|
|
441
|
+
args: [path],
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Remove a file and its chunks
|
|
446
|
+
*/
|
|
447
|
+
async function removeFile(path) {
|
|
448
|
+
const client = getClient();
|
|
449
|
+
await removeFileChunks(path);
|
|
450
|
+
await client.execute({
|
|
451
|
+
sql: `DELETE FROM memory_files WHERE path = ?`,
|
|
452
|
+
args: [path],
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
// Search
|
|
456
|
+
/**
|
|
457
|
+
* Search memory using hybrid (vector + FTS5) search
|
|
458
|
+
*/
|
|
459
|
+
export async function searchMemory(query, config = DEFAULT_MEMORY_CONFIG) {
|
|
460
|
+
const embeddingService = getEmbeddingService();
|
|
461
|
+
const { maxResults, minScore, hybrid } = config.query;
|
|
462
|
+
let chunks = [];
|
|
463
|
+
let method = 'hybrid';
|
|
464
|
+
let totalCandidates = 0;
|
|
465
|
+
if (hybrid.enabled) {
|
|
466
|
+
// Hybrid search: combine vector and FTS results
|
|
467
|
+
const candidateLimit = maxResults * hybrid.candidateMultiplier;
|
|
468
|
+
// Vector search
|
|
469
|
+
const queryEmbedding = await embeddingService.generateEmbedding(query);
|
|
470
|
+
const vectorResults = await vectorSearch(queryEmbedding, candidateLimit);
|
|
471
|
+
// FTS search
|
|
472
|
+
const ftsResults = await ftsSearch(query, candidateLimit);
|
|
473
|
+
// Combine and re-rank
|
|
474
|
+
const scoreMap = new Map();
|
|
475
|
+
for (const result of vectorResults) {
|
|
476
|
+
scoreMap.set(result.id, {
|
|
477
|
+
chunk: result,
|
|
478
|
+
vectorScore: result.score || 0,
|
|
479
|
+
ftsScore: 0,
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
for (const result of ftsResults) {
|
|
483
|
+
const existing = scoreMap.get(result.id);
|
|
484
|
+
if (existing) {
|
|
485
|
+
existing.ftsScore = result.score || 0;
|
|
486
|
+
}
|
|
487
|
+
else {
|
|
488
|
+
scoreMap.set(result.id, {
|
|
489
|
+
chunk: result,
|
|
490
|
+
vectorScore: 0,
|
|
491
|
+
ftsScore: result.score || 0,
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
// Calculate hybrid scores
|
|
496
|
+
const scoredChunks = Array.from(scoreMap.values())
|
|
497
|
+
.map(({ chunk, vectorScore, ftsScore }) => ({
|
|
498
|
+
...chunk,
|
|
499
|
+
score: vectorScore * hybrid.vectorWeight + ftsScore * hybrid.textWeight,
|
|
500
|
+
}))
|
|
501
|
+
.filter((c) => c.score >= minScore)
|
|
502
|
+
.sort((a, b) => (b.score || 0) - (a.score || 0))
|
|
503
|
+
.slice(0, maxResults);
|
|
504
|
+
chunks = scoredChunks;
|
|
505
|
+
totalCandidates = scoreMap.size;
|
|
506
|
+
}
|
|
507
|
+
else {
|
|
508
|
+
// Vector-only search
|
|
509
|
+
const queryEmbedding = await embeddingService.generateEmbedding(query);
|
|
510
|
+
chunks = await vectorSearch(queryEmbedding, maxResults);
|
|
511
|
+
chunks = chunks.filter((c) => (c.score || 0) >= minScore);
|
|
512
|
+
method = 'vector';
|
|
513
|
+
totalCandidates = chunks.length;
|
|
514
|
+
}
|
|
515
|
+
return {
|
|
516
|
+
chunks,
|
|
517
|
+
query,
|
|
518
|
+
method,
|
|
519
|
+
totalCandidates,
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Vector similarity search using cosine similarity
|
|
524
|
+
*/
|
|
525
|
+
async function vectorSearch(queryEmbedding, limit) {
|
|
526
|
+
const client = getClient();
|
|
527
|
+
// Get all chunks with embeddings
|
|
528
|
+
const result = await client.execute({
|
|
529
|
+
sql: `SELECT id, path, source, start_line, end_line, hash, text, model, embedding
|
|
530
|
+
FROM memory_chunks WHERE embedding IS NOT NULL LIMIT 1000`,
|
|
531
|
+
args: [],
|
|
532
|
+
});
|
|
533
|
+
// Calculate cosine similarity
|
|
534
|
+
const scored = [];
|
|
535
|
+
for (const row of result.rows) {
|
|
536
|
+
const embedding = row.embedding;
|
|
537
|
+
if (!embedding)
|
|
538
|
+
continue;
|
|
539
|
+
const chunkEmbedding = Array.from(new Float32Array(embedding));
|
|
540
|
+
const similarity = cosineSimilarity(queryEmbedding, chunkEmbedding);
|
|
541
|
+
scored.push({
|
|
542
|
+
id: row.id,
|
|
543
|
+
path: row.path,
|
|
544
|
+
source: row.source,
|
|
545
|
+
startLine: row.start_line,
|
|
546
|
+
endLine: row.end_line,
|
|
547
|
+
hash: row.hash,
|
|
548
|
+
text: row.text,
|
|
549
|
+
model: row.model,
|
|
550
|
+
score: similarity,
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
return scored.sort((a, b) => (b.score || 0) - (a.score || 0)).slice(0, limit);
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* Full-text search using FTS5
|
|
557
|
+
*/
|
|
558
|
+
async function ftsSearch(query, limit) {
|
|
559
|
+
const client = getClient();
|
|
560
|
+
try {
|
|
561
|
+
// FTS5 query with ranking
|
|
562
|
+
const result = await client.execute({
|
|
563
|
+
sql: `SELECT id, path, source, start_line, end_line, bm25(memory_fts) as score
|
|
564
|
+
FROM memory_fts WHERE memory_fts MATCH ? ORDER BY score LIMIT ?`,
|
|
565
|
+
args: [query, limit],
|
|
566
|
+
});
|
|
567
|
+
// Fetch full chunk data
|
|
568
|
+
const chunks = [];
|
|
569
|
+
for (const row of result.rows) {
|
|
570
|
+
const chunkResult = await client.execute({
|
|
571
|
+
sql: `SELECT id, path, source, start_line, end_line, hash, text, model
|
|
572
|
+
FROM memory_chunks WHERE id = ?`,
|
|
573
|
+
args: [row.id],
|
|
574
|
+
});
|
|
575
|
+
if (chunkResult.rows.length > 0) {
|
|
576
|
+
const chunk = chunkResult.rows[0];
|
|
577
|
+
// Normalize BM25 score (BM25 returns negative values, lower = better)
|
|
578
|
+
const normalizedScore = 1 / (1 + Math.abs(row.score));
|
|
579
|
+
chunks.push({
|
|
580
|
+
id: chunk.id,
|
|
581
|
+
path: chunk.path,
|
|
582
|
+
source: chunk.source,
|
|
583
|
+
startLine: chunk.start_line,
|
|
584
|
+
endLine: chunk.end_line,
|
|
585
|
+
hash: chunk.hash,
|
|
586
|
+
text: chunk.text,
|
|
587
|
+
model: chunk.model,
|
|
588
|
+
score: normalizedScore,
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
return chunks;
|
|
593
|
+
}
|
|
594
|
+
catch {
|
|
595
|
+
// FTS5 not available, fall back to LIKE search
|
|
596
|
+
const result = await client.execute({
|
|
597
|
+
sql: `SELECT id, path, source, start_line, end_line, hash, text, model
|
|
598
|
+
FROM memory_chunks WHERE text LIKE ? LIMIT ?`,
|
|
599
|
+
args: [`%${query}%`, limit],
|
|
600
|
+
});
|
|
601
|
+
return result.rows.map((row) => rowToMemoryChunk(row, 0.5));
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
/**
|
|
605
|
+
* Calculate cosine similarity between two vectors
|
|
606
|
+
*/
|
|
607
|
+
function cosineSimilarity(a, b) {
|
|
608
|
+
if (a.length !== b.length)
|
|
609
|
+
return 0;
|
|
610
|
+
let dotProduct = 0;
|
|
611
|
+
let normA = 0;
|
|
612
|
+
let normB = 0;
|
|
613
|
+
for (let i = 0; i < a.length; i++) {
|
|
614
|
+
dotProduct += a[i] * b[i];
|
|
615
|
+
normA += a[i] * a[i];
|
|
616
|
+
normB += b[i] * b[i];
|
|
617
|
+
}
|
|
618
|
+
const magnitude = Math.sqrt(normA) * Math.sqrt(normB);
|
|
619
|
+
return magnitude === 0 ? 0 : dotProduct / magnitude;
|
|
620
|
+
}
|
|
621
|
+
// Memory Get (Read specific lines)
|
|
622
|
+
/**
|
|
623
|
+
* Get specific content from a memory file
|
|
624
|
+
*/
|
|
625
|
+
export async function getMemoryContent(path, options) {
|
|
626
|
+
const client = getClient();
|
|
627
|
+
// Get file info
|
|
628
|
+
const fileResult = await client.execute({
|
|
629
|
+
sql: `SELECT path, hash FROM memory_files WHERE path = ?`,
|
|
630
|
+
args: [path],
|
|
631
|
+
});
|
|
632
|
+
if (fileResult.rows.length === 0) {
|
|
633
|
+
return null;
|
|
634
|
+
}
|
|
635
|
+
// Get relevant chunks
|
|
636
|
+
let sql = `SELECT text, start_line, end_line FROM memory_chunks WHERE path = ?`;
|
|
637
|
+
const args = [path];
|
|
638
|
+
if (options?.fromLine) {
|
|
639
|
+
sql += ` AND end_line >= ?`;
|
|
640
|
+
args.push(options.fromLine);
|
|
641
|
+
}
|
|
642
|
+
if (options?.toLine) {
|
|
643
|
+
sql += ` AND start_line <= ?`;
|
|
644
|
+
args.push(options.toLine);
|
|
645
|
+
}
|
|
646
|
+
sql += ` ORDER BY start_line`;
|
|
647
|
+
if (options?.lines) {
|
|
648
|
+
sql += ` LIMIT ?`;
|
|
649
|
+
args.push(Math.ceil(options.lines / 10) + 1); // Approximate chunks needed
|
|
650
|
+
}
|
|
651
|
+
const chunksResult = await client.execute({ sql, args });
|
|
652
|
+
if (chunksResult.rows.length === 0) {
|
|
653
|
+
return null;
|
|
654
|
+
}
|
|
655
|
+
// Combine chunks and extract requested lines
|
|
656
|
+
const allText = chunksResult.rows.map((row) => String(row.text)).join('\n');
|
|
657
|
+
const allLines = allText.split('\n');
|
|
658
|
+
const fromLine = options?.fromLine || 1;
|
|
659
|
+
const toLine = options?.toLine || (options?.lines ? fromLine + options.lines - 1 : allLines.length);
|
|
660
|
+
const selectedLines = allLines.slice(fromLine - 1, toLine);
|
|
661
|
+
return {
|
|
662
|
+
content: selectedLines.join('\n'),
|
|
663
|
+
fromLine,
|
|
664
|
+
toLine: Math.min(toLine, fromLine + selectedLines.length - 1),
|
|
665
|
+
path,
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
// Memory Stats
|
|
669
|
+
/**
|
|
670
|
+
* Get memory system statistics
|
|
671
|
+
*/
|
|
672
|
+
export async function getMemoryStats() {
|
|
673
|
+
const client = getClient();
|
|
674
|
+
const filesResult = await client.execute({
|
|
675
|
+
sql: `SELECT COUNT(*) as count FROM memory_files`,
|
|
676
|
+
args: [],
|
|
677
|
+
});
|
|
678
|
+
const chunksResult = await client.execute({
|
|
679
|
+
sql: `SELECT COUNT(*) as count, SUM(LENGTH(text)) as total_chars FROM memory_chunks`,
|
|
680
|
+
args: [],
|
|
681
|
+
});
|
|
682
|
+
const cacheResult = await client.execute({
|
|
683
|
+
sql: `SELECT COUNT(*) as count FROM embedding_cache`,
|
|
684
|
+
args: [],
|
|
685
|
+
});
|
|
686
|
+
const lastSyncResult = await client.execute({
|
|
687
|
+
sql: `SELECT value FROM memory_meta WHERE key = 'last_sync_at'`,
|
|
688
|
+
args: [],
|
|
689
|
+
});
|
|
690
|
+
return {
|
|
691
|
+
totalFiles: Number(filesResult.rows[0]?.count || 0),
|
|
692
|
+
totalChunks: Number(chunksResult.rows[0]?.count || 0),
|
|
693
|
+
totalTokensEstimate: Math.ceil(Number(chunksResult.rows[0]?.total_chars || 0) / 4),
|
|
694
|
+
lastSyncAt: lastSyncResult.rows[0]?.value ? Number(lastSyncResult.rows[0].value) : null,
|
|
695
|
+
embeddingModel: DEFAULT_MEMORY_CONFIG.model,
|
|
696
|
+
cachedEmbeddings: Number(cacheResult.rows[0]?.count || 0),
|
|
697
|
+
};
|
|
698
|
+
}
|
|
699
|
+
// Memory Management (CRUD)
|
|
700
|
+
/**
|
|
701
|
+
* List all memory files
|
|
702
|
+
*/
|
|
703
|
+
export async function listMemoryFiles() {
|
|
704
|
+
const client = getClient();
|
|
705
|
+
const result = await client.execute({
|
|
706
|
+
sql: `SELECT path, source, hash, mtime, size FROM memory_files ORDER BY path`,
|
|
707
|
+
args: [],
|
|
708
|
+
});
|
|
709
|
+
return result.rows.map((row) => rowToMemoryFile(row));
|
|
710
|
+
}
|
|
711
|
+
/**
|
|
712
|
+
* List chunks for a specific file
|
|
713
|
+
*/
|
|
714
|
+
export async function listFileChunks(path) {
|
|
715
|
+
const client = getClient();
|
|
716
|
+
const result = await client.execute({
|
|
717
|
+
sql: `SELECT id, path, source, start_line, end_line, hash, text, model
|
|
718
|
+
FROM memory_chunks WHERE path = ? ORDER BY start_line`,
|
|
719
|
+
args: [path],
|
|
720
|
+
});
|
|
721
|
+
return result.rows.map((row) => rowToMemoryChunk(row));
|
|
722
|
+
}
|
|
723
|
+
/**
|
|
724
|
+
* Delete a memory chunk
|
|
725
|
+
*/
|
|
726
|
+
export async function deleteMemoryChunk(chunkId) {
|
|
727
|
+
const client = getClient();
|
|
728
|
+
// Delete from FTS
|
|
729
|
+
try {
|
|
730
|
+
await client.execute({
|
|
731
|
+
sql: `DELETE FROM memory_fts WHERE id = ?`,
|
|
732
|
+
args: [chunkId],
|
|
733
|
+
});
|
|
734
|
+
}
|
|
735
|
+
catch {
|
|
736
|
+
// FTS might not be available
|
|
737
|
+
}
|
|
738
|
+
// Delete from chunks
|
|
739
|
+
const result = await client.execute({
|
|
740
|
+
sql: `DELETE FROM memory_chunks WHERE id = ?`,
|
|
741
|
+
args: [chunkId],
|
|
742
|
+
});
|
|
743
|
+
return (result.rowsAffected || 0) > 0;
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* Delete all memories for a file
|
|
747
|
+
*/
|
|
748
|
+
export async function deleteMemoryFile(path) {
|
|
749
|
+
const client = getClient();
|
|
750
|
+
await removeFileChunks(path);
|
|
751
|
+
const result = await client.execute({
|
|
752
|
+
sql: `DELETE FROM memory_files WHERE path = ?`,
|
|
753
|
+
args: [path],
|
|
754
|
+
});
|
|
755
|
+
return (result.rowsAffected || 0) > 0;
|
|
756
|
+
}
|
|
757
|
+
/**
|
|
758
|
+
* Clear all memories
|
|
759
|
+
*/
|
|
760
|
+
export async function clearAllMemories() {
|
|
761
|
+
const client = getClient();
|
|
762
|
+
try {
|
|
763
|
+
await client.execute(`DELETE FROM memory_fts`);
|
|
764
|
+
}
|
|
765
|
+
catch {
|
|
766
|
+
// FTS might not be available
|
|
767
|
+
}
|
|
768
|
+
await client.execute(`DELETE FROM memory_chunks`);
|
|
769
|
+
await client.execute(`DELETE FROM memory_files`);
|
|
770
|
+
await client.execute(`DELETE FROM embedding_cache`);
|
|
771
|
+
logger.info('[Memory] All memories cleared');
|
|
772
|
+
}
|
|
773
|
+
function rowToMemoryChunk(row, score) {
|
|
774
|
+
return {
|
|
775
|
+
id: String(row.id),
|
|
776
|
+
path: String(row.path),
|
|
777
|
+
source: String(row.source),
|
|
778
|
+
startLine: Number(row.start_line),
|
|
779
|
+
endLine: Number(row.end_line),
|
|
780
|
+
hash: String(row.hash),
|
|
781
|
+
text: String(row.text),
|
|
782
|
+
model: String(row.model),
|
|
783
|
+
score,
|
|
784
|
+
};
|
|
785
|
+
}
|
|
786
|
+
function rowToMemoryFile(row) {
|
|
787
|
+
return {
|
|
788
|
+
path: String(row.path),
|
|
789
|
+
source: String(row.source),
|
|
790
|
+
hash: String(row.hash),
|
|
791
|
+
mtime: Number(row.mtime),
|
|
792
|
+
size: Number(row.size),
|
|
793
|
+
};
|
|
794
|
+
}
|
|
795
|
+
function rowToMemorySession(row) {
|
|
796
|
+
return {
|
|
797
|
+
id: String(row.id),
|
|
798
|
+
name: row.name ? String(row.name) : undefined,
|
|
799
|
+
conversationId: row.conversation_id ? String(row.conversation_id) : undefined,
|
|
800
|
+
userId: row.user_id ? String(row.user_id) : undefined,
|
|
801
|
+
projectId: row.project_id ? String(row.project_id) : undefined,
|
|
802
|
+
memoryEnabled: Boolean(row.memory_enabled),
|
|
803
|
+
memoryLastSyncAt: row.memory_last_sync_at ? Number(row.memory_last_sync_at) : undefined,
|
|
804
|
+
totalTokens: Number(row.total_tokens),
|
|
805
|
+
totalMessages: Number(row.total_messages),
|
|
806
|
+
totalCost: Number(row.total_cost),
|
|
807
|
+
status: String(row.status),
|
|
808
|
+
createdAt: Number(row.created_at),
|
|
809
|
+
updatedAt: Number(row.updated_at),
|
|
810
|
+
lastActiveAt: Number(row.last_active_at),
|
|
811
|
+
};
|
|
812
|
+
}
|
|
813
|
+
/**
|
|
814
|
+
* Create a new memory session
|
|
815
|
+
*/
|
|
816
|
+
export async function createMemorySession(params) {
|
|
817
|
+
const client = getClient();
|
|
818
|
+
const id = randomUUID();
|
|
819
|
+
const now = Math.floor(Date.now() / 1000);
|
|
820
|
+
await client.execute({
|
|
821
|
+
sql: `INSERT INTO memory_sessions (id, name, conversation_id, user_id, project_id, created_at, updated_at, last_active_at)
|
|
822
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
823
|
+
args: [id, params.name || null, params.conversationId || null, params.userId || null, params.projectId || null, now, now, now],
|
|
824
|
+
});
|
|
825
|
+
return {
|
|
826
|
+
id,
|
|
827
|
+
name: params.name,
|
|
828
|
+
conversationId: params.conversationId,
|
|
829
|
+
userId: params.userId,
|
|
830
|
+
projectId: params.projectId,
|
|
831
|
+
memoryEnabled: true,
|
|
832
|
+
totalTokens: 0,
|
|
833
|
+
totalMessages: 0,
|
|
834
|
+
totalCost: 0,
|
|
835
|
+
status: 'active',
|
|
836
|
+
createdAt: now,
|
|
837
|
+
updatedAt: now,
|
|
838
|
+
lastActiveAt: now,
|
|
839
|
+
};
|
|
840
|
+
}
|
|
841
|
+
/**
|
|
842
|
+
* List memory sessions
|
|
843
|
+
*/
|
|
844
|
+
export async function listMemorySessions(params) {
|
|
845
|
+
const client = getClient();
|
|
846
|
+
const limit = params?.limit || 20;
|
|
847
|
+
const offset = params?.offset || 0;
|
|
848
|
+
let whereClause = '1=1';
|
|
849
|
+
const args = [];
|
|
850
|
+
if (params?.status) {
|
|
851
|
+
whereClause += ' AND status = ?';
|
|
852
|
+
args.push(params.status);
|
|
853
|
+
}
|
|
854
|
+
const countResult = await client.execute({
|
|
855
|
+
sql: `SELECT COUNT(*) as total FROM memory_sessions WHERE ${whereClause}`,
|
|
856
|
+
args,
|
|
857
|
+
});
|
|
858
|
+
const result = await client.execute({
|
|
859
|
+
sql: `SELECT * FROM memory_sessions WHERE ${whereClause} ORDER BY last_active_at DESC LIMIT ? OFFSET ?`,
|
|
860
|
+
args: [...args, limit, offset],
|
|
861
|
+
});
|
|
862
|
+
return {
|
|
863
|
+
sessions: result.rows.map((row) => rowToMemorySession(row)),
|
|
864
|
+
total: Number(countResult.rows[0]?.total || 0),
|
|
865
|
+
};
|
|
866
|
+
}
|
|
867
|
+
/**
|
|
868
|
+
* Update session stats
|
|
869
|
+
*/
|
|
870
|
+
export async function updateSessionStats(sessionId, stats) {
|
|
871
|
+
const client = getClient();
|
|
872
|
+
const now = Math.floor(Date.now() / 1000);
|
|
873
|
+
const updates = ['updated_at = ?', 'last_active_at = ?'];
|
|
874
|
+
const args = [now, now];
|
|
875
|
+
if (stats.tokens !== undefined) {
|
|
876
|
+
updates.push('total_tokens = total_tokens + ?');
|
|
877
|
+
args.push(stats.tokens);
|
|
878
|
+
}
|
|
879
|
+
if (stats.messages !== undefined) {
|
|
880
|
+
updates.push('total_messages = total_messages + ?');
|
|
881
|
+
args.push(stats.messages);
|
|
882
|
+
}
|
|
883
|
+
if (stats.cost !== undefined) {
|
|
884
|
+
updates.push('total_cost = total_cost + ?');
|
|
885
|
+
args.push(stats.cost);
|
|
886
|
+
}
|
|
887
|
+
args.push(sessionId);
|
|
888
|
+
await client.execute({
|
|
889
|
+
sql: `UPDATE memory_sessions SET ${updates.join(', ')} WHERE id = ?`,
|
|
890
|
+
args,
|
|
891
|
+
});
|
|
892
|
+
}
|
|
893
|
+
/**
|
|
894
|
+
* Archive a session
|
|
895
|
+
*/
|
|
896
|
+
export async function archiveSession(sessionId) {
|
|
897
|
+
const client = getClient();
|
|
898
|
+
await client.execute({
|
|
899
|
+
sql: `UPDATE memory_sessions SET status = 'archived', updated_at = unixepoch() WHERE id = ?`,
|
|
900
|
+
args: [sessionId],
|
|
901
|
+
});
|
|
902
|
+
}
|
|
903
|
+
/**
|
|
904
|
+
* Index a chat conversation into semantic memory
|
|
905
|
+
* Creates a virtual "file" from conversation messages for searchability
|
|
906
|
+
*/
|
|
907
|
+
export async function indexConversation(input, config = DEFAULT_MEMORY_CONFIG) {
|
|
908
|
+
const client = getClient();
|
|
909
|
+
const embeddingService = getEmbeddingService();
|
|
910
|
+
// Create virtual path for the conversation
|
|
911
|
+
const path = `chat://${input.conversationId}`;
|
|
912
|
+
const source = 'chat';
|
|
913
|
+
// Format messages into indexable content
|
|
914
|
+
const contentParts = [];
|
|
915
|
+
// Add metadata header
|
|
916
|
+
contentParts.push(`# Chat: ${input.title}`);
|
|
917
|
+
if (input.projectName) {
|
|
918
|
+
contentParts.push(`Project: ${input.projectName}`);
|
|
919
|
+
}
|
|
920
|
+
if (input.presetId) {
|
|
921
|
+
contentParts.push(`Preset: ${input.presetId}`);
|
|
922
|
+
}
|
|
923
|
+
contentParts.push('');
|
|
924
|
+
// Add messages
|
|
925
|
+
for (const msg of input.messages) {
|
|
926
|
+
const roleLabel = msg.role === 'user' ? 'User' : msg.role === 'assistant' ? 'Assistant' : 'System';
|
|
927
|
+
const timestamp = msg.createdAt ? new Date(msg.createdAt).toLocaleString() : '';
|
|
928
|
+
contentParts.push(`## ${roleLabel}${timestamp ? ` (${timestamp})` : ''}`);
|
|
929
|
+
contentParts.push(msg.content);
|
|
930
|
+
contentParts.push('');
|
|
931
|
+
}
|
|
932
|
+
const content = contentParts.join('\n');
|
|
933
|
+
const hash = hashContent(content);
|
|
934
|
+
const now = Date.now();
|
|
935
|
+
// Check if conversation already exists in memory
|
|
936
|
+
const existing = await client.execute({
|
|
937
|
+
sql: `SELECT hash FROM memory_files WHERE path = ?`,
|
|
938
|
+
args: [path],
|
|
939
|
+
});
|
|
940
|
+
if (existing.rows.length > 0) {
|
|
941
|
+
// Check if content changed
|
|
942
|
+
if (existing.rows[0].hash === hash) {
|
|
943
|
+
// No changes, skip indexing
|
|
944
|
+
return { chunksIndexed: 0, tokensEstimate: 0 };
|
|
945
|
+
}
|
|
946
|
+
// Remove old chunks before reindexing
|
|
947
|
+
await removeFileChunks(path);
|
|
948
|
+
// Update file record
|
|
949
|
+
await client.execute({
|
|
950
|
+
sql: `UPDATE memory_files SET hash = ?, mtime = ?, size = ?, updated_at = unixepoch() WHERE path = ?`,
|
|
951
|
+
args: [hash, now, content.length, path],
|
|
952
|
+
});
|
|
953
|
+
}
|
|
954
|
+
else {
|
|
955
|
+
// Insert new file record
|
|
956
|
+
await client.execute({
|
|
957
|
+
sql: `INSERT INTO memory_files (path, source, hash, mtime, size, project_id) VALUES (?, ?, ?, ?, ?, ?)`,
|
|
958
|
+
args: [path, source, hash, now, content.length, input.projectId || null],
|
|
959
|
+
});
|
|
960
|
+
}
|
|
961
|
+
// Chunk and index content
|
|
962
|
+
const chunks = chunkText(content, config);
|
|
963
|
+
let tokensEstimate = 0;
|
|
964
|
+
for (const chunk of chunks) {
|
|
965
|
+
const chunkId = randomUUID();
|
|
966
|
+
const chunkHash = hashContent(chunk.text);
|
|
967
|
+
tokensEstimate += estimateTokens(chunk.text);
|
|
968
|
+
// Generate embedding
|
|
969
|
+
let embedding = null;
|
|
970
|
+
try {
|
|
971
|
+
embedding = await embeddingService.generateEmbedding(chunk.text);
|
|
972
|
+
}
|
|
973
|
+
catch {
|
|
974
|
+
logger.warn(`[Memory] Failed to generate embedding for chat chunk ${chunkId}`);
|
|
975
|
+
}
|
|
976
|
+
// Insert chunk
|
|
977
|
+
await client.execute({
|
|
978
|
+
sql: `INSERT INTO memory_chunks (id, path, source, start_line, end_line, hash, text, model, embedding, embedding_dims)
|
|
979
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
980
|
+
args: [
|
|
981
|
+
chunkId,
|
|
982
|
+
path,
|
|
983
|
+
source,
|
|
984
|
+
chunk.startLine,
|
|
985
|
+
chunk.endLine,
|
|
986
|
+
chunkHash,
|
|
987
|
+
chunk.text,
|
|
988
|
+
config.model,
|
|
989
|
+
embedding ? new Float32Array(embedding).buffer : null,
|
|
990
|
+
embedding?.length || null,
|
|
991
|
+
],
|
|
992
|
+
});
|
|
993
|
+
// Insert into FTS
|
|
994
|
+
try {
|
|
995
|
+
await client.execute({
|
|
996
|
+
sql: `INSERT INTO memory_fts (text, id, path, source, model, start_line, end_line)
|
|
997
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
998
|
+
args: [chunk.text, chunkId, path, source, config.model, chunk.startLine, chunk.endLine],
|
|
999
|
+
});
|
|
1000
|
+
}
|
|
1001
|
+
catch {
|
|
1002
|
+
// FTS5 might not be available
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
logger.info(`[Memory] Indexed conversation ${input.conversationId}: ${chunks.length} chunks, ~${tokensEstimate} tokens`);
|
|
1006
|
+
return { chunksIndexed: chunks.length, tokensEstimate };
|
|
1007
|
+
}
|
|
1008
|
+
/**
|
|
1009
|
+
* Remove a conversation from memory index
|
|
1010
|
+
*/
|
|
1011
|
+
export async function removeConversationFromMemory(conversationId) {
|
|
1012
|
+
const path = `chat://${conversationId}`;
|
|
1013
|
+
await removeFileChunks(path);
|
|
1014
|
+
const client = getClient();
|
|
1015
|
+
await client.execute({
|
|
1016
|
+
sql: `DELETE FROM memory_files WHERE path = ?`,
|
|
1017
|
+
args: [path],
|
|
1018
|
+
});
|
|
1019
|
+
logger.info(`[Memory] Removed conversation ${conversationId} from memory`);
|
|
1020
|
+
}
|
|
1021
|
+
/**
|
|
1022
|
+
* Initialize citation tracking table
|
|
1023
|
+
*/
|
|
1024
|
+
export async function initCitationTable() {
|
|
1025
|
+
const client = getClient();
|
|
1026
|
+
await client.execute({
|
|
1027
|
+
sql: `CREATE TABLE IF NOT EXISTS memory_citations (
|
|
1028
|
+
id TEXT PRIMARY KEY,
|
|
1029
|
+
memory_id TEXT NOT NULL,
|
|
1030
|
+
chunk_id TEXT,
|
|
1031
|
+
source_type TEXT NOT NULL,
|
|
1032
|
+
source_id TEXT NOT NULL,
|
|
1033
|
+
timestamp TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1034
|
+
excerpt TEXT,
|
|
1035
|
+
FOREIGN KEY (memory_id) REFERENCES memory_files(path) ON DELETE CASCADE
|
|
1036
|
+
)`,
|
|
1037
|
+
args: [],
|
|
1038
|
+
});
|
|
1039
|
+
await client.execute({
|
|
1040
|
+
sql: `CREATE INDEX IF NOT EXISTS idx_citations_memory ON memory_citations(memory_id)`,
|
|
1041
|
+
args: [],
|
|
1042
|
+
});
|
|
1043
|
+
await client.execute({
|
|
1044
|
+
sql: `CREATE INDEX IF NOT EXISTS idx_citations_source ON memory_citations(source_type, source_id)`,
|
|
1045
|
+
args: [],
|
|
1046
|
+
});
|
|
1047
|
+
}
|
|
1048
|
+
/**
|
|
1049
|
+
* Add a citation to a memory entry
|
|
1050
|
+
*/
|
|
1051
|
+
export async function addCitation(citation) {
|
|
1052
|
+
const id = randomUUID();
|
|
1053
|
+
const client = getClient();
|
|
1054
|
+
await client.execute({
|
|
1055
|
+
sql: `INSERT INTO memory_citations (id, memory_id, chunk_id, source_type, source_id, timestamp, excerpt)
|
|
1056
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
1057
|
+
args: [id, citation.memoryId, citation.chunkId ?? null, citation.sourceType, citation.sourceId, citation.timestamp ?? new Date().toISOString(), citation.excerpt ?? null],
|
|
1058
|
+
});
|
|
1059
|
+
return { id, ...citation };
|
|
1060
|
+
}
|
|
1061
|
+
/**
|
|
1062
|
+
* Get citations for a memory entry
|
|
1063
|
+
*/
|
|
1064
|
+
export async function getCitations(memoryId) {
|
|
1065
|
+
const client = getClient();
|
|
1066
|
+
const result = await client.execute({
|
|
1067
|
+
sql: `SELECT id, memory_id as memoryId, chunk_id as chunkId, source_type as sourceType,
|
|
1068
|
+
source_id as sourceId, timestamp, excerpt
|
|
1069
|
+
FROM memory_citations WHERE memory_id = ? ORDER BY timestamp DESC`,
|
|
1070
|
+
args: [memoryId],
|
|
1071
|
+
});
|
|
1072
|
+
return result.rows.map((row) => ({
|
|
1073
|
+
id: String(row.id),
|
|
1074
|
+
memoryId: String(row.memoryId),
|
|
1075
|
+
chunkId: row.chunkId ? String(row.chunkId) : undefined,
|
|
1076
|
+
sourceType: String(row.sourceType),
|
|
1077
|
+
sourceId: String(row.sourceId),
|
|
1078
|
+
timestamp: String(row.timestamp),
|
|
1079
|
+
excerpt: row.excerpt ? String(row.excerpt) : undefined,
|
|
1080
|
+
}));
|
|
1081
|
+
}
|
|
1082
|
+
/**
|
|
1083
|
+
* Get citations by source (e.g., all citations from a conversation)
|
|
1084
|
+
*/
|
|
1085
|
+
export async function getCitationsBySource(sourceType, sourceId) {
|
|
1086
|
+
const client = getClient();
|
|
1087
|
+
const result = await client.execute({
|
|
1088
|
+
sql: `SELECT id, memory_id as memoryId, chunk_id as chunkId, source_type as sourceType,
|
|
1089
|
+
source_id as sourceId, timestamp, excerpt
|
|
1090
|
+
FROM memory_citations WHERE source_type = ? AND source_id = ? ORDER BY timestamp DESC`,
|
|
1091
|
+
args: [sourceType, sourceId],
|
|
1092
|
+
});
|
|
1093
|
+
return result.rows.map((row) => ({
|
|
1094
|
+
id: String(row.id),
|
|
1095
|
+
memoryId: String(row.memoryId),
|
|
1096
|
+
chunkId: row.chunkId ? String(row.chunkId) : undefined,
|
|
1097
|
+
sourceType: String(row.sourceType),
|
|
1098
|
+
sourceId: String(row.sourceId),
|
|
1099
|
+
timestamp: String(row.timestamp),
|
|
1100
|
+
excerpt: row.excerpt ? String(row.excerpt) : undefined,
|
|
1101
|
+
}));
|
|
1102
|
+
}
|
|
1103
|
+
/**
|
|
1104
|
+
* Delete a citation
|
|
1105
|
+
*/
|
|
1106
|
+
export async function deleteCitation(citationId) {
|
|
1107
|
+
const client = getClient();
|
|
1108
|
+
const result = await client.execute({
|
|
1109
|
+
sql: `DELETE FROM memory_citations WHERE id = ?`,
|
|
1110
|
+
args: [citationId],
|
|
1111
|
+
});
|
|
1112
|
+
return (result.rowsAffected ?? 0) > 0;
|
|
1113
|
+
}
|
|
1114
|
+
// Backend registry
|
|
1115
|
+
const memoryBackends = new Map();
|
|
1116
|
+
/**
|
|
1117
|
+
* Register a memory backend plugin
|
|
1118
|
+
*/
|
|
1119
|
+
export function registerMemoryBackend(backend) {
|
|
1120
|
+
memoryBackends.set(backend.name, backend);
|
|
1121
|
+
logger.info(`[Memory] Backend registered: ${backend.name} (${backend.type})`);
|
|
1122
|
+
}
|
|
1123
|
+
/**
|
|
1124
|
+
* Get a registered memory backend
|
|
1125
|
+
*/
|
|
1126
|
+
export function getMemoryBackend(name) {
|
|
1127
|
+
return memoryBackends.get(name);
|
|
1128
|
+
}
|
|
1129
|
+
/**
|
|
1130
|
+
* List registered memory backends
|
|
1131
|
+
*/
|
|
1132
|
+
export function listMemoryBackends() {
|
|
1133
|
+
return Array.from(memoryBackends.keys());
|
|
1134
|
+
}
|
|
1135
|
+
export default {
|
|
1136
|
+
// Init
|
|
1137
|
+
initMemoryTables,
|
|
1138
|
+
initCitationTable,
|
|
1139
|
+
// Sync
|
|
1140
|
+
syncMemoryFiles,
|
|
1141
|
+
// Search
|
|
1142
|
+
searchMemory,
|
|
1143
|
+
getMemoryContent,
|
|
1144
|
+
// Stats
|
|
1145
|
+
getMemoryStats,
|
|
1146
|
+
// Management
|
|
1147
|
+
listMemoryFiles,
|
|
1148
|
+
listFileChunks,
|
|
1149
|
+
deleteMemoryChunk,
|
|
1150
|
+
deleteMemoryFile,
|
|
1151
|
+
clearAllMemories,
|
|
1152
|
+
// Sessions
|
|
1153
|
+
createMemorySession,
|
|
1154
|
+
listMemorySessions,
|
|
1155
|
+
updateSessionStats,
|
|
1156
|
+
archiveSession,
|
|
1157
|
+
// Chat indexing
|
|
1158
|
+
indexConversation,
|
|
1159
|
+
removeConversationFromMemory,
|
|
1160
|
+
// Citations
|
|
1161
|
+
addCitation,
|
|
1162
|
+
getCitations,
|
|
1163
|
+
getCitationsBySource,
|
|
1164
|
+
deleteCitation,
|
|
1165
|
+
// Multi-backend
|
|
1166
|
+
registerMemoryBackend,
|
|
1167
|
+
getMemoryBackend,
|
|
1168
|
+
listMemoryBackends,
|
|
1169
|
+
// Config
|
|
1170
|
+
DEFAULT_MEMORY_CONFIG,
|
|
1171
|
+
};
|
|
1172
|
+
//# sourceMappingURL=memory-service.js.map
|