@poolzin/pool-bot 2026.2.11 → 2026.2.18
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/CHANGELOG.md +34 -0
- package/dist/agents/agent-scope.js +4 -0
- package/dist/agents/announce-idempotency.js +14 -0
- package/dist/agents/auth-profiles/usage.js +22 -0
- package/dist/agents/auth-profiles.js +1 -1
- package/dist/agents/auth-profiles.resolve-auth-profile-order.fixtures.js +23 -0
- package/dist/agents/bash-tools.exec-runtime.js +438 -0
- package/dist/agents/bash-tools.shared.js +6 -0
- package/dist/agents/cli-runner/reliability.js +61 -0
- package/dist/agents/cli-watchdog-defaults.js +11 -0
- package/dist/agents/command-poll-backoff.js +63 -0
- package/dist/agents/current-time.js +16 -0
- package/dist/agents/glob-pattern.js +42 -0
- package/dist/agents/memory-search.js +33 -0
- package/dist/agents/model-alias-lines.js +18 -0
- package/dist/agents/model-auth-label.js +61 -0
- package/dist/agents/model-fallback.js +59 -8
- package/dist/agents/models-config.e2e-harness.js +115 -0
- package/dist/agents/ollama-stream.js +11 -3
- package/dist/agents/openclaw-tools.js +135 -0
- package/dist/agents/pi-auth-json.js +118 -0
- package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +147 -0
- package/dist/agents/pi-embedded-subscribe.e2e-harness.js +90 -0
- package/dist/agents/pi-embedded-subscribe.handlers.compaction.js +63 -0
- package/dist/agents/pi-embedded-subscribe.handlers.tools.media.test-helpers.js +30 -0
- package/dist/agents/pi-extensions/session-manager-runtime-registry.js +23 -0
- package/dist/agents/pi-tools.before-tool-call.js +145 -4
- package/dist/agents/pi-tools.js +29 -9
- package/dist/agents/pi-tools.policy.js +85 -92
- package/dist/agents/pi-tools.schema.js +54 -27
- package/dist/agents/queued-file-writer.js +22 -0
- package/dist/agents/sandbox/docker.js +133 -40
- package/dist/agents/sandbox/fs-bridge.js +146 -0
- package/dist/agents/sandbox/fs-paths.js +205 -0
- package/dist/agents/sandbox/hash.js +4 -0
- package/dist/agents/sandbox/validate-sandbox-security.js +157 -0
- package/dist/agents/sandbox-paths.js +3 -0
- package/dist/agents/sandbox-tool-policy.js +26 -0
- package/dist/agents/sanitize-for-prompt.js +18 -0
- package/dist/agents/session-dirs.js +20 -0
- package/dist/agents/session-write-lock.js +203 -39
- package/dist/agents/skills/filter.js +24 -0
- package/dist/agents/skills/tools-dir.js +9 -0
- package/dist/agents/skills-install-download.js +290 -0
- package/dist/agents/skills-install-output.js +30 -0
- package/dist/agents/skills-install.download-test-utils.js +36 -0
- package/dist/agents/skills.e2e-test-helpers.js +13 -0
- package/dist/agents/subagent-announce-queue.js +59 -15
- package/dist/agents/subagent-depth.js +137 -0
- package/dist/agents/subagent-registry.js +448 -96
- package/dist/agents/subagent-spawn.js +262 -0
- package/dist/agents/system-prompt.js +52 -10
- package/dist/agents/test-helpers/fast-tool-stubs.js +18 -0
- package/dist/agents/test-helpers/host-sandbox-fs-bridge.js +74 -0
- package/dist/agents/tool-display-common.js +782 -0
- package/dist/agents/tool-loop-detection.js +466 -0
- package/dist/agents/tool-policy.js +6 -0
- package/dist/agents/tools/image-tool.js +1 -1
- package/dist/agents/tools/sessions-access.js +178 -0
- package/dist/agents/tools/sessions-resolution.js +206 -0
- package/dist/agents/tools/subagents-tool.js +616 -0
- package/dist/agents/workspace-dir.js +18 -0
- package/dist/agents/workspace-dirs.js +14 -0
- package/dist/agents/workspace.js +70 -0
- package/dist/auto-reply/heartbeat-reply-payload.js +18 -0
- package/dist/auto-reply/reply/commands-export-session.js +163 -0
- package/dist/auto-reply/reply/commands-mesh.js +245 -0
- package/dist/auto-reply/reply/commands-setunset.js +28 -0
- package/dist/auto-reply/reply/commands-slash-parse.js +31 -0
- package/dist/auto-reply/reply/commands-system-prompt.js +117 -0
- package/dist/auto-reply/reply/directive-handling.levels.js +17 -0
- package/dist/auto-reply/reply/directive-handling.params.js +1 -0
- package/dist/auto-reply/reply/directive-parsing.js +36 -0
- package/dist/auto-reply/reply/dispatcher-registry.js +43 -0
- package/dist/auto-reply/reply/elevated-unavailable.js +20 -0
- package/dist/auto-reply/reply/post-compaction-audit.js +96 -0
- package/dist/auto-reply/reply/post-compaction-context.js +98 -0
- package/dist/auto-reply/reply/reply-delivery.js +92 -0
- package/dist/auto-reply/reply/session-reset-prompt.js +1 -0
- package/dist/auto-reply/reply/session-run-accounting.js +33 -0
- package/dist/auto-reply/reply.directive.directive-behavior.e2e-harness.js +115 -0
- package/dist/auto-reply/reply.directive.directive-behavior.e2e-mocks.js +12 -0
- package/dist/browser/bridge-auth-registry.js +26 -0
- package/dist/browser/client-actions-url.js +10 -0
- package/dist/browser/control-auth.js +73 -0
- package/dist/browser/csrf.js +64 -0
- package/dist/browser/http-auth.js +52 -0
- package/dist/browser/paths.js +37 -0
- package/dist/browser/proxy-files.js +32 -0
- package/dist/browser/pw-ai-state.js +7 -0
- package/dist/browser/resolved-config-refresh.js +42 -0
- package/dist/browser/routes/path-output.js +1 -0
- package/dist/browser/server-context.chrome-test-harness.js +20 -0
- package/dist/browser/server-middleware.js +31 -0
- package/dist/browser/test-port.js +16 -0
- package/dist/build-info.json +3 -3
- package/dist/canvas-host/file-resolver.js +43 -0
- package/dist/channels/account-summary.js +19 -0
- package/dist/channels/draft-stream-loop.js +77 -0
- package/dist/channels/plugins/account-helpers.js +26 -0
- package/dist/channels/telegram/allow-from.js +10 -0
- package/dist/cli/browser-cli-resize.js +22 -0
- package/dist/cli/browser-cli-shared.js +8 -0
- package/dist/cli/clawbot-cli.js +5 -0
- package/dist/cli/completion-cli.js +566 -0
- package/dist/cli/config-cli.js +63 -5
- package/dist/cli/daemon-cli/lifecycle-core.js +256 -0
- package/dist/cli/daemon-cli/register-service-commands.js +60 -0
- package/dist/cli/daemon-cli-compat.js +80 -0
- package/dist/cli/nodes-cli/pairing-render.js +26 -0
- package/dist/cli/program/action-reparse.js +17 -0
- package/dist/cli/program/command-registry.js +17 -0
- package/dist/cli/program/program-context.js +8 -0
- package/dist/cli/program/register.subclis.js +7 -0
- package/dist/cli/program/routes.js +233 -0
- package/dist/cli/qr-cli.js +132 -0
- package/dist/cli/requirements-test-fixtures.js +17 -0
- package/dist/cli/respawn-policy.js +4 -0
- package/dist/cli/shared/parse-port.js +18 -0
- package/dist/cli/skills-cli.format.js +241 -0
- package/dist/cli/update-cli/progress.js +121 -0
- package/dist/cli/update-cli/restart-helper.js +108 -0
- package/dist/cli/update-cli/shared.js +196 -0
- package/dist/cli/update-cli/status.js +97 -0
- package/dist/cli/update-cli/suppress-deprecations.js +17 -0
- package/dist/cli/update-cli/update-command.js +506 -0
- package/dist/cli/update-cli/wizard.js +130 -0
- package/dist/cli/update-cli.js +3 -9
- package/dist/cli/windows-argv.js +69 -0
- package/dist/commands/auth-choice-legacy.js +20 -0
- package/dist/commands/auth-choice.apply-helpers.js +8 -0
- package/dist/commands/channel-test-helpers.js +19 -0
- package/dist/commands/cleanup-plan.js +10 -0
- package/dist/commands/cleanup-utils.js +7 -0
- package/dist/commands/config-validation.js +15 -0
- package/dist/commands/doctor-completion.js +112 -0
- package/dist/commands/doctor-memory-search.js +119 -0
- package/dist/commands/doctor-session-locks.js +73 -0
- package/dist/commands/doctor.e2e-harness.js +364 -0
- package/dist/commands/gateway-presence.js +19 -0
- package/dist/commands/model-default.js +35 -0
- package/dist/commands/models/fallbacks-shared.js +102 -0
- package/dist/commands/models/shared.js +24 -0
- package/dist/commands/onboard-auth.config-gateways.js +64 -0
- package/dist/commands/onboard-auth.config-litellm.js +45 -0
- package/dist/commands/onboard-auth.config-shared.js +116 -0
- package/dist/commands/onboard-config.js +16 -0
- package/dist/commands/onboard-non-interactive.test-helpers.js +31 -0
- package/dist/commands/onboard-provider-auth-flags.js +136 -0
- package/dist/commands/openai-codex-oauth.js +40 -0
- package/dist/commands/test-runtime-config-helpers.js +21 -0
- package/dist/commands/test-wizard-helpers.js +68 -0
- package/dist/commands/vllm-setup.js +66 -0
- package/dist/compat/legacy-names.js +2 -0
- package/dist/config/backup-rotation.js +19 -0
- package/dist/config/env-preserve.js +122 -0
- package/dist/config/includes-scan.js +78 -0
- package/dist/config/plugins-allowlist.js +13 -0
- package/dist/config/schema.help.js +256 -0
- package/dist/config/schema.hints.js +189 -0
- package/dist/config/schema.irc.js +20 -0
- package/dist/config/schema.labels.js +317 -0
- package/dist/config/sessions/delivery-info.js +40 -0
- package/dist/config/types.irc.js +1 -0
- package/dist/config/zod-schema.agent-defaults.js +14 -0
- package/dist/config/zod-schema.agent-model.js +10 -0
- package/dist/config/zod-schema.agent-runtime.js +14 -0
- package/dist/config/zod-schema.allowdeny.js +35 -0
- package/dist/config/zod-schema.sensitive.js +4 -0
- package/dist/control-ui/assets/index-HRr1grwl.js.map +1 -1
- package/dist/cron/isolated-agent/skills-snapshot.js +26 -0
- package/dist/cron/isolated-agent/subagent-followup.js +127 -0
- package/dist/cron/isolated-agent.mocks.js +12 -0
- package/dist/cron/isolated-agent.test-setup.js +22 -0
- package/dist/cron/legacy-delivery.js +43 -0
- package/dist/cron/webhook-url.js +22 -0
- package/dist/daemon/arg-split.js +40 -0
- package/dist/daemon/exec-file.js +23 -0
- package/dist/daemon/output.js +6 -0
- package/dist/daemon/runtime-format.js +31 -0
- package/dist/daemon/schtasks-exec.js +4 -0
- package/dist/daemon/service-audit.js +22 -0
- package/dist/discord/client.js +41 -0
- package/dist/discord/components-registry.js +57 -0
- package/dist/discord/components.js +816 -0
- package/dist/discord/guilds.js +12 -0
- package/dist/discord/monitor/gateway-plugin.js +48 -0
- package/dist/discord/monitor/presence.js +30 -0
- package/dist/discord/send.components.js +115 -0
- package/dist/discord/send.shared.js +4 -0
- package/dist/discord/ui.js +26 -0
- package/dist/discord/voice-message.js +254 -0
- package/dist/gateway/agent-event-assistant-text.js +5 -0
- package/dist/gateway/agent-prompt.js +33 -0
- package/dist/gateway/auth-rate-limit.js +136 -0
- package/dist/gateway/channel-health-monitor.js +114 -0
- package/dist/gateway/control-ui-contract.js +1 -0
- package/dist/gateway/control-ui-csp.js +15 -0
- package/dist/gateway/gateway-config-prompts.shared.js +25 -0
- package/dist/gateway/http-auth-helpers.js +18 -0
- package/dist/gateway/http-common.js +18 -0
- package/dist/gateway/http-endpoint-helpers.js +27 -0
- package/dist/gateway/node-invoke-sanitize.js +11 -0
- package/dist/gateway/node-invoke-system-run-approval.js +205 -0
- package/dist/gateway/probe-auth.js +21 -0
- package/dist/gateway/protocol/index.js +7 -2
- package/dist/gateway/protocol/schema/mesh.js +54 -0
- package/dist/gateway/protocol/schema/protocol-schemas.js +7 -0
- package/dist/gateway/protocol/schema.js +1 -0
- package/dist/gateway/server/ws-connection/auth-messages.js +54 -0
- package/dist/gateway/server-channels.js +11 -0
- package/dist/gateway/server-methods/attachment-normalize.js +16 -0
- package/dist/gateway/server-methods/base-hash.js +8 -0
- package/dist/gateway/server-methods/mesh.js +700 -0
- package/dist/gateway/server-methods/nodes.handlers.invoke-result.js +55 -0
- package/dist/gateway/server-methods/restart-request.js +13 -0
- package/dist/gateway/server-methods/validation.js +8 -0
- package/dist/gateway/server.agent.gateway-server-agent.mocks.js +35 -0
- package/dist/gateway/server.e2e-registry-helpers.js +1 -0
- package/dist/gateway/server.e2e-ws-harness.js +20 -0
- package/dist/gateway/test-helpers.js +2 -0
- package/dist/gateway/test-helpers.server.js +3 -1
- package/dist/gateway/test-http-response.js +12 -0
- package/dist/gateway/test-openai-responses-model.js +20 -0
- package/dist/gateway/test-temp-config.js +30 -0
- package/dist/gateway/test-with-server.js +32 -0
- package/dist/hooks/bundled/bootstrap-extra-files/handler.js +46 -0
- package/dist/imessage/monitor/abort-handler.js +23 -0
- package/dist/imessage/monitor/inbound-processing.js +346 -0
- package/dist/imessage/monitor/parse-notification.js +64 -0
- package/dist/imessage/target-parsing-helpers.js +92 -0
- package/dist/infra/archive.js +244 -20
- package/dist/infra/detect-package-manager.js +26 -0
- package/dist/infra/exec-approvals-allowlist.js +257 -0
- package/dist/infra/exec-approvals-analysis.js +770 -0
- package/dist/infra/exec-approvals.js +13 -0
- package/dist/infra/file-lock.js +1 -0
- package/dist/infra/gemini-auth.js +39 -0
- package/dist/infra/heartbeat-active-hours.js +85 -0
- package/dist/infra/heartbeat-events-filter.js +50 -0
- package/dist/infra/heartbeat-runner.test-utils.js +39 -0
- package/dist/infra/http-body.js +265 -0
- package/dist/infra/install-package-dir.js +50 -0
- package/dist/infra/install-safe-path.js +49 -0
- package/dist/infra/json-files.js +49 -0
- package/dist/infra/jsonl-socket.js +52 -0
- package/dist/infra/map-size.js +14 -0
- package/dist/infra/net/hostname.js +7 -0
- package/dist/infra/npm-registry-spec.js +39 -0
- package/dist/infra/openclaw-root.js +109 -0
- package/dist/infra/outbound/delivery-queue.js +214 -0
- package/dist/infra/outbound/identity.js +23 -0
- package/dist/infra/outbound/message-action-params.js +307 -0
- package/dist/infra/outbound/tool-payload.js +21 -0
- package/dist/infra/package-json.js +23 -0
- package/dist/infra/pairing-files.js +19 -0
- package/dist/infra/pairing-token.js +9 -0
- package/dist/infra/path-prepend.js +51 -0
- package/dist/infra/path-safety.js +16 -0
- package/dist/infra/process-respawn.js +49 -0
- package/dist/infra/runtime-status.js +16 -0
- package/dist/infra/session-cost-usage.types.js +1 -0
- package/dist/infra/session-maintenance-warning.js +89 -0
- package/dist/infra/system-run-command.js +78 -0
- package/dist/infra/tmp-openclaw-dir.js +81 -0
- package/dist/infra/tmp-poolbot-dir.js +2 -0
- package/dist/infra/update-channels.js +19 -0
- package/dist/line/actions.js +45 -0
- package/dist/line/channel-access-token.js +9 -0
- package/dist/line/flex-templates/basic-cards.js +332 -0
- package/dist/line/flex-templates/common.js +18 -0
- package/dist/line/flex-templates/media-control-cards.js +453 -0
- package/dist/line/flex-templates/message.js +10 -0
- package/dist/line/flex-templates/schedule-cards.js +399 -0
- package/dist/line/flex-templates/types.js +1 -0
- package/dist/line/webhook-node.js +100 -0
- package/dist/line/webhook-utils.js +11 -0
- package/dist/logging/diagnostic-session-state.js +73 -0
- package/dist/logging/diagnostic.js +22 -0
- package/dist/logging/timestamps.js +14 -0
- package/dist/markdown/whatsapp.js +62 -0
- package/dist/media/base64.js +34 -0
- package/dist/media/local-roots.js +32 -0
- package/dist/media/outbound-attachment.js +10 -0
- package/dist/media/read-response-with-limit.js +41 -0
- package/dist/media/sniff-mime-from-base64.js +19 -0
- package/dist/media-understanding/audio-preflight.js +67 -0
- package/dist/media-understanding/fs.js +13 -0
- package/dist/media-understanding/output-extract.js +26 -0
- package/dist/media-understanding/providers/audio.test-helpers.js +34 -0
- package/dist/media-understanding/providers/google/inline-data.js +64 -0
- package/dist/media-understanding/providers/shared.js +7 -0
- package/dist/media-understanding/runner.entries.js +459 -0
- package/dist/memory/batch-error-utils.js +11 -0
- package/dist/memory/batch-http.js +27 -0
- package/dist/memory/batch-output.js +29 -0
- package/dist/memory/batch-runner.js +22 -0
- package/dist/memory/batch-upload.js +23 -0
- package/dist/memory/batch-utils.js +26 -0
- package/dist/memory/embeddings-debug.js +11 -0
- package/dist/memory/embeddings-remote-client.js +22 -0
- package/dist/memory/embeddings-remote-fetch.js +14 -0
- package/dist/memory/embeddings.js +36 -9
- package/dist/memory/hybrid.js +24 -5
- package/dist/memory/manager-embedding-ops.js +616 -0
- package/dist/memory/manager-sync-ops.js +953 -0
- package/dist/memory/manager.js +76 -28
- package/dist/memory/mmr.js +164 -0
- package/dist/memory/qmd-manager.js +1061 -0
- package/dist/memory/qmd-query-parser.js +107 -0
- package/dist/memory/qmd-scope.js +93 -0
- package/dist/memory/query-expansion.js +331 -0
- package/dist/memory/search-manager.js +0 -1
- package/dist/memory/sync-index.js +21 -0
- package/dist/memory/sync-progress.js +22 -0
- package/dist/memory/sync-stale.js +30 -0
- package/dist/memory/temporal-decay.js +119 -0
- package/dist/memory/test-embeddings-mock.js +16 -0
- package/dist/memory/test-manager-helpers.js +14 -0
- package/dist/memory/test-runtime-mocks.js +11 -0
- package/dist/node-host/invoke-browser.js +177 -0
- package/dist/node-host/invoke.js +685 -0
- package/dist/pairing/setup-code.js +285 -0
- package/dist/plugin-sdk/account-id.js +1 -0
- package/dist/plugin-sdk/agent-media-payload.js +13 -0
- package/dist/plugin-sdk/allow-from.js +47 -0
- package/dist/plugin-sdk/command-auth.js +23 -0
- package/dist/plugin-sdk/config-paths.js +9 -0
- package/dist/plugin-sdk/file-lock.js +116 -0
- package/dist/plugin-sdk/json-store.js +31 -0
- package/dist/plugin-sdk/onboarding.js +28 -0
- package/dist/plugin-sdk/provider-auth-result.js +29 -0
- package/dist/plugin-sdk/slack-message-actions.js +133 -0
- package/dist/plugin-sdk/status-helpers.js +35 -0
- package/dist/plugin-sdk/text-chunking.js +31 -0
- package/dist/plugin-sdk/tool-send.js +12 -0
- package/dist/plugin-sdk/webhook-path.js +27 -0
- package/dist/plugin-sdk/webhook-targets.js +34 -0
- package/dist/plugins/hooks.test-helpers.js +21 -0
- package/dist/plugins/uninstall.js +171 -0
- package/dist/process/kill-tree.js +98 -0
- package/dist/process/supervisor/adapters/child.js +143 -0
- package/dist/process/supervisor/adapters/env.js +13 -0
- package/dist/process/supervisor/adapters/pty.js +148 -0
- package/dist/process/supervisor/index.js +10 -0
- package/dist/process/supervisor/registry.js +117 -0
- package/dist/process/supervisor/supervisor.js +244 -0
- package/dist/process/supervisor/types.js +1 -0
- package/dist/providers/google-shared.test-helpers.js +75 -0
- package/dist/security/audit-channel.js +419 -0
- package/dist/security/audit-tool-policy.js +1 -0
- package/dist/security/scan-paths.js +12 -0
- package/dist/sessions/input-provenance.js +55 -0
- package/dist/sessions/session-key-utils.js +7 -0
- package/dist/shared/chat-content.js +31 -0
- package/dist/shared/chat-envelope.js +45 -0
- package/dist/shared/config-eval.js +117 -0
- package/dist/shared/device-auth.js +16 -0
- package/dist/shared/entry-metadata.js +9 -0
- package/dist/shared/entry-status.js +25 -0
- package/dist/shared/frontmatter.js +98 -0
- package/dist/shared/model-param-b.js +19 -0
- package/dist/shared/net/ipv4.js +17 -0
- package/dist/shared/node-match.js +53 -0
- package/dist/shared/pid-alive.js +12 -0
- package/dist/shared/process-scoped-map.js +10 -0
- package/dist/shared/requirements.js +128 -0
- package/dist/shared/subagents-format.js +84 -0
- package/dist/shared/usage-aggregates.js +28 -0
- package/dist/signal/monitor/mentions.js +45 -0
- package/dist/signal/rpc-context.js +19 -0
- package/dist/slack/blocks-fallback.js +76 -0
- package/dist/slack/blocks-input.js +40 -0
- package/dist/slack/draft-stream.js +106 -0
- package/dist/slack/message-actions.js +51 -0
- package/dist/slack/modal-metadata.js +32 -0
- package/dist/slack/monitor/events/interactions.js +462 -0
- package/dist/slack/monitor/room-context.js +17 -0
- package/dist/slack/stream-mode.js +41 -0
- package/dist/telegram/bot-native-command-menu.js +64 -0
- package/dist/telegram/bot.media.e2e-harness.js +81 -0
- package/dist/telegram/button-types.js +1 -0
- package/dist/telegram/group-access.js +65 -0
- package/dist/telegram/outbound-params.js +21 -0
- package/dist/telegram/poll-vote-cache.js +21 -0
- package/dist/terminal/health-style.js +36 -0
- package/dist/test-utils/chunk-test-helpers.js +21 -0
- package/dist/test-utils/env.js +72 -0
- package/dist/test-utils/exec-assertions.js +12 -0
- package/dist/test-utils/imessage-test-plugin.js +54 -0
- package/dist/test-utils/mock-http-response.js +17 -0
- package/dist/test-utils/vitest-mock-fn.js +1 -0
- package/dist/tts/tts-core.js +550 -0
- package/dist/utils/chunk-items.js +10 -0
- package/dist/utils/reaction-level.js +52 -0
- package/dist/utils/safe-json.js +22 -0
- package/dist/utils/with-timeout.js +14 -0
- package/dist/web/media.js +17 -5
- package/dist/whatsapp/resolve-outbound-target.js +42 -0
- package/dist/wizard/onboarding.completion.js +74 -0
- package/extensions/bluebubbles/package.json +1 -1
- package/extensions/bluebubbles/src/account-resolve.ts +29 -0
- package/extensions/bluebubbles/src/monitor-normalize.ts +796 -0
- package/extensions/bluebubbles/src/monitor-processing.ts +1007 -0
- package/extensions/bluebubbles/src/monitor-reply-cache.ts +185 -0
- package/extensions/bluebubbles/src/monitor-shared.ts +51 -0
- package/extensions/bluebubbles/src/multipart.ts +32 -0
- package/extensions/bluebubbles/src/send-helpers.ts +53 -0
- package/extensions/bluebubbles/src/test-harness.ts +50 -0
- package/extensions/bluebubbles/src/test-mocks.ts +11 -0
- package/extensions/copilot-proxy/package.json +1 -1
- package/extensions/device-pair/index.ts +554 -0
- package/extensions/diagnostics-otel/package.json +1 -1
- package/extensions/discord/package.json +1 -1
- package/extensions/discord/src/channel.js +366 -0
- package/extensions/discord/src/runtime.js +10 -0
- package/extensions/feishu/index.ts +63 -0
- package/extensions/feishu/src/accounts.ts +114 -0
- package/extensions/feishu/src/bitable.ts +739 -0
- package/extensions/feishu/src/bot.ts +965 -0
- package/extensions/feishu/src/channel.ts +351 -0
- package/extensions/feishu/src/client.ts +118 -0
- package/extensions/feishu/src/config-schema.ts +206 -0
- package/extensions/feishu/src/dedup.ts +33 -0
- package/extensions/feishu/src/directory.ts +177 -0
- package/extensions/feishu/src/doc-schema.ts +47 -0
- package/extensions/feishu/src/docx.ts +536 -0
- package/extensions/feishu/src/drive-schema.ts +46 -0
- package/extensions/feishu/src/drive.ts +227 -0
- package/extensions/feishu/src/dynamic-agent.ts +131 -0
- package/extensions/feishu/src/media.ts +449 -0
- package/extensions/feishu/src/mention.ts +126 -0
- package/extensions/feishu/src/monitor.ts +330 -0
- package/extensions/feishu/src/onboarding.ts +359 -0
- package/extensions/feishu/src/outbound.ts +55 -0
- package/extensions/feishu/src/perm-schema.ts +52 -0
- package/extensions/feishu/src/perm.ts +173 -0
- package/extensions/feishu/src/policy.ts +84 -0
- package/extensions/feishu/src/probe.ts +44 -0
- package/extensions/feishu/src/reactions.ts +160 -0
- package/extensions/feishu/src/reply-dispatcher.ts +239 -0
- package/extensions/feishu/src/runtime.ts +14 -0
- package/extensions/feishu/src/send-result.ts +29 -0
- package/extensions/feishu/src/send.ts +335 -0
- package/extensions/feishu/src/streaming-card.ts +223 -0
- package/extensions/feishu/src/targets.ts +78 -0
- package/extensions/feishu/src/tools-config.ts +21 -0
- package/extensions/feishu/src/types.ts +81 -0
- package/extensions/feishu/src/typing.ts +80 -0
- package/extensions/feishu/src/wiki-schema.ts +55 -0
- package/extensions/feishu/src/wiki.ts +232 -0
- package/extensions/google-antigravity-auth/package.json +1 -1
- package/extensions/google-gemini-cli-auth/package.json +1 -1
- package/extensions/googlechat/package.json +1 -1
- package/extensions/imessage/package.json +1 -1
- package/extensions/imessage/src/channel.js +253 -0
- package/extensions/imessage/src/runtime.js +10 -0
- package/extensions/irc/index.ts +17 -0
- package/extensions/irc/src/accounts.ts +268 -0
- package/extensions/irc/src/channel.ts +367 -0
- package/extensions/irc/src/client.ts +439 -0
- package/extensions/irc/src/config-schema.ts +97 -0
- package/extensions/irc/src/connect-options.ts +30 -0
- package/extensions/irc/src/control-chars.ts +22 -0
- package/extensions/irc/src/inbound.ts +334 -0
- package/extensions/irc/src/monitor.ts +147 -0
- package/extensions/irc/src/normalize.ts +117 -0
- package/extensions/irc/src/onboarding.ts +479 -0
- package/extensions/irc/src/policy.ts +157 -0
- package/extensions/irc/src/probe.ts +53 -0
- package/extensions/irc/src/protocol.ts +169 -0
- package/extensions/irc/src/runtime.ts +14 -0
- package/extensions/irc/src/send.ts +88 -0
- package/extensions/irc/src/types.ts +93 -0
- package/extensions/line/package.json +1 -1
- package/extensions/llm-task/package.json +1 -1
- package/extensions/lobster/package.json +1 -1
- package/extensions/matrix/CHANGELOG.md +5 -0
- package/extensions/matrix/package.json +1 -1
- package/extensions/matrix/src/matrix/client-bootstrap.ts +39 -0
- package/extensions/mattermost/package.json +1 -1
- package/extensions/mattermost/src/mattermost/monitor-onchar.ts +25 -0
- package/extensions/mattermost/src/mattermost/monitor-websocket.ts +221 -0
- package/extensions/mattermost/src/mattermost/reactions.ts +130 -0
- package/extensions/mattermost/src/mattermost/reconnect.ts +103 -0
- package/extensions/memory-core/package.json +1 -1
- package/extensions/memory-lancedb/package.json +1 -1
- package/extensions/minimax-portal-auth/index.ts +161 -0
- package/extensions/minimax-portal-auth/oauth.ts +247 -0
- package/extensions/msteams/CHANGELOG.md +5 -0
- package/extensions/msteams/package.json +1 -1
- package/extensions/msteams/src/file-lock.ts +1 -0
- package/extensions/msteams/src/graph.ts +92 -0
- package/extensions/msteams/src/mentions.ts +114 -0
- package/extensions/msteams/src/test-runtime.ts +16 -0
- package/extensions/nextcloud-talk/package.json +1 -1
- package/extensions/nostr/CHANGELOG.md +5 -0
- package/extensions/nostr/package.json +1 -1
- package/extensions/open-prose/package.json +1 -1
- package/extensions/openai-codex-auth/index.ts +177 -0
- package/extensions/phone-control/index.ts +421 -0
- package/extensions/shared/resolve-target-test-helpers.ts +66 -0
- package/extensions/signal/package.json +1 -1
- package/extensions/signal/src/channel.js +273 -0
- package/extensions/signal/src/runtime.js +10 -0
- package/extensions/slack/package.json +1 -1
- package/extensions/slack/src/channel.js +489 -0
- package/extensions/slack/src/runtime.js +10 -0
- package/extensions/talk-voice/index.ts +150 -0
- package/extensions/telegram/package.json +1 -1
- package/extensions/telegram/src/channel.js +424 -0
- package/extensions/telegram/src/runtime.js +10 -0
- package/extensions/thread-ownership/index.ts +133 -0
- package/extensions/tlon/package.json +1 -1
- package/extensions/tlon/src/account-fields.ts +25 -0
- package/extensions/tlon/src/urbit/base-url.ts +57 -0
- package/extensions/tlon/src/urbit/channel-client.ts +157 -0
- package/extensions/tlon/src/urbit/channel-ops.ts +164 -0
- package/extensions/tlon/src/urbit/context.ts +47 -0
- package/extensions/tlon/src/urbit/errors.ts +51 -0
- package/extensions/tlon/src/urbit/fetch.ts +39 -0
- package/extensions/twitch/CHANGELOG.md +5 -0
- package/extensions/twitch/package.json +1 -1
- package/extensions/twitch/src/test-fixtures.ts +30 -0
- package/extensions/voice-call/CHANGELOG.md +5 -0
- package/extensions/voice-call/package.json +1 -1
- package/extensions/voice-call/src/allowlist.ts +19 -0
- package/extensions/whatsapp/package.json +1 -1
- package/extensions/whatsapp/src/channel.js +429 -0
- package/extensions/whatsapp/src/runtime.js +10 -0
- package/extensions/zalo/CHANGELOG.md +5 -0
- package/extensions/zalo/package.json +1 -1
- package/extensions/zalouser/CHANGELOG.md +5 -0
- package/extensions/zalouser/package.json +1 -1
- package/package.json +1 -1
package/dist/memory/manager.js
CHANGED
|
@@ -20,6 +20,7 @@ import { buildFileEntry, chunkMarkdown, ensureDir, hashText, isMemoryPath, listM
|
|
|
20
20
|
import { bm25RankToScore, buildFtsQuery, mergeHybridResults } from "./hybrid.js";
|
|
21
21
|
import { searchKeyword, searchVector } from "./manager-search.js";
|
|
22
22
|
import { ensureMemoryIndexSchema } from "./memory-schema.js";
|
|
23
|
+
import { extractKeywords } from "./query-expansion.js";
|
|
23
24
|
import { requireNodeSqlite } from "./sqlite.js";
|
|
24
25
|
import { loadSqliteVecExtension } from "./sqlite-vec.js";
|
|
25
26
|
const META_KEY = "memory_index_meta_v1";
|
|
@@ -54,6 +55,7 @@ export class MemoryIndexManager {
|
|
|
54
55
|
requestedProvider;
|
|
55
56
|
fallbackFrom;
|
|
56
57
|
fallbackReason;
|
|
58
|
+
providerUnavailableReason;
|
|
57
59
|
openAi;
|
|
58
60
|
gemini;
|
|
59
61
|
voyage;
|
|
@@ -108,6 +110,7 @@ export class MemoryIndexManager {
|
|
|
108
110
|
workspaceDir,
|
|
109
111
|
settings,
|
|
110
112
|
providerResult,
|
|
113
|
+
purpose: params.purpose,
|
|
111
114
|
});
|
|
112
115
|
INDEX_CACHE.set(key, manager);
|
|
113
116
|
return manager;
|
|
@@ -122,6 +125,7 @@ export class MemoryIndexManager {
|
|
|
122
125
|
this.requestedProvider = params.providerResult.requestedProvider;
|
|
123
126
|
this.fallbackFrom = params.providerResult.fallbackFrom;
|
|
124
127
|
this.fallbackReason = params.providerResult.fallbackReason;
|
|
128
|
+
this.providerUnavailableReason = params.providerResult.providerUnavailableReason;
|
|
125
129
|
this.openAi = params.providerResult.openAi;
|
|
126
130
|
this.gemini = params.providerResult.gemini;
|
|
127
131
|
this.voyage = params.providerResult.voyage;
|
|
@@ -146,7 +150,8 @@ export class MemoryIndexManager {
|
|
|
146
150
|
this.ensureWatcher();
|
|
147
151
|
this.ensureSessionListener();
|
|
148
152
|
this.ensureIntervalSync();
|
|
149
|
-
|
|
153
|
+
const statusOnly = params.purpose === "status";
|
|
154
|
+
this.dirty = this.sources.has("memory") && (statusOnly ? !meta : true);
|
|
150
155
|
this.batch = this.resolveBatchConfig();
|
|
151
156
|
}
|
|
152
157
|
async warmSession(sessionKey) {
|
|
@@ -175,6 +180,30 @@ export class MemoryIndexManager {
|
|
|
175
180
|
const maxResults = opts?.maxResults ?? this.settings.query.maxResults;
|
|
176
181
|
const hybrid = this.settings.query.hybrid;
|
|
177
182
|
const candidates = Math.min(200, Math.max(1, Math.floor(maxResults * hybrid.candidateMultiplier)));
|
|
183
|
+
// FTS-only mode: no embedding provider available
|
|
184
|
+
if (!this.provider) {
|
|
185
|
+
if (!this.fts.enabled || !this.fts.available) {
|
|
186
|
+
log.warn("memory search: no provider and FTS unavailable");
|
|
187
|
+
return [];
|
|
188
|
+
}
|
|
189
|
+
const keywords = extractKeywords(cleaned);
|
|
190
|
+
const searchTerms = keywords.length > 0 ? keywords : [cleaned];
|
|
191
|
+
const resultSets = await Promise.all(searchTerms.map((term) => this.searchKeyword(term, candidates).catch(() => [])));
|
|
192
|
+
const seenIds = new Map();
|
|
193
|
+
for (const results of resultSets) {
|
|
194
|
+
for (const result of results) {
|
|
195
|
+
const existing = seenIds.get(result.id);
|
|
196
|
+
if (!existing || result.score > existing.score) {
|
|
197
|
+
seenIds.set(result.id, result);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
const merged = [...seenIds.values()]
|
|
202
|
+
.toSorted((a, b) => b.score - a.score)
|
|
203
|
+
.filter((entry) => entry.score >= minScore)
|
|
204
|
+
.slice(0, maxResults);
|
|
205
|
+
return merged;
|
|
206
|
+
}
|
|
178
207
|
const keywordResults = hybrid.enabled
|
|
179
208
|
? await this.searchKeyword(cleaned, candidates).catch(() => [])
|
|
180
209
|
: [];
|
|
@@ -186,15 +215,19 @@ export class MemoryIndexManager {
|
|
|
186
215
|
if (!hybrid.enabled) {
|
|
187
216
|
return vectorResults.filter((entry) => entry.score >= minScore).slice(0, maxResults);
|
|
188
217
|
}
|
|
189
|
-
const merged = this.mergeHybridResults({
|
|
218
|
+
const merged = await this.mergeHybridResults({
|
|
190
219
|
vector: vectorResults,
|
|
191
220
|
keyword: keywordResults,
|
|
192
221
|
vectorWeight: hybrid.vectorWeight,
|
|
193
222
|
textWeight: hybrid.textWeight,
|
|
223
|
+
mmr: hybrid.mmr,
|
|
224
|
+
temporalDecay: hybrid.temporalDecay,
|
|
194
225
|
});
|
|
195
226
|
return merged.filter((entry) => entry.score >= minScore).slice(0, maxResults);
|
|
196
227
|
}
|
|
197
228
|
async searchVector(queryVec, limit) {
|
|
229
|
+
if (!this.provider)
|
|
230
|
+
return [];
|
|
198
231
|
const results = await searchVector({
|
|
199
232
|
db: this.db,
|
|
200
233
|
vectorTable: VECTOR_TABLE,
|
|
@@ -218,7 +251,7 @@ export class MemoryIndexManager {
|
|
|
218
251
|
const results = await searchKeyword({
|
|
219
252
|
db: this.db,
|
|
220
253
|
ftsTable: FTS_TABLE,
|
|
221
|
-
providerModel: this.provider
|
|
254
|
+
providerModel: this.provider?.model ?? "fts-only",
|
|
222
255
|
query,
|
|
223
256
|
limit,
|
|
224
257
|
snippetMaxChars: SNIPPET_MAX_CHARS,
|
|
@@ -228,8 +261,8 @@ export class MemoryIndexManager {
|
|
|
228
261
|
});
|
|
229
262
|
return results.map((entry) => entry);
|
|
230
263
|
}
|
|
231
|
-
mergeHybridResults(params) {
|
|
232
|
-
const merged = mergeHybridResults({
|
|
264
|
+
async mergeHybridResults(params) {
|
|
265
|
+
const merged = await mergeHybridResults({
|
|
233
266
|
vector: params.vector.map((r) => ({
|
|
234
267
|
id: r.id,
|
|
235
268
|
path: r.path,
|
|
@@ -250,6 +283,9 @@ export class MemoryIndexManager {
|
|
|
250
283
|
})),
|
|
251
284
|
vectorWeight: params.vectorWeight,
|
|
252
285
|
textWeight: params.textWeight,
|
|
286
|
+
workspaceDir: this.workspaceDir,
|
|
287
|
+
mmr: params.mmr,
|
|
288
|
+
temporalDecay: params.temporalDecay,
|
|
253
289
|
});
|
|
254
290
|
return merged.map((entry) => entry);
|
|
255
291
|
}
|
|
@@ -359,8 +395,8 @@ export class MemoryIndexManager {
|
|
|
359
395
|
dirty: this.dirty || this.sessionsDirty,
|
|
360
396
|
workspaceDir: this.workspaceDir,
|
|
361
397
|
dbPath: this.settings.store.path,
|
|
362
|
-
provider: this.provider
|
|
363
|
-
model: this.provider
|
|
398
|
+
provider: this.provider?.id ?? "none",
|
|
399
|
+
model: this.provider?.model,
|
|
364
400
|
requestedProvider: this.requestedProvider,
|
|
365
401
|
sources: Array.from(this.sources),
|
|
366
402
|
extraPaths: this.settings.extraPaths,
|
|
@@ -882,7 +918,7 @@ export class MemoryIndexManager {
|
|
|
882
918
|
try {
|
|
883
919
|
this.db
|
|
884
920
|
.prepare(`DELETE FROM ${FTS_TABLE} WHERE path = ? AND source = ? AND model = ?`)
|
|
885
|
-
.run(stale.path, "memory", this.provider
|
|
921
|
+
.run(stale.path, "memory", this.provider?.model ?? "fts-only");
|
|
886
922
|
}
|
|
887
923
|
catch { }
|
|
888
924
|
}
|
|
@@ -976,7 +1012,7 @@ export class MemoryIndexManager {
|
|
|
976
1012
|
try {
|
|
977
1013
|
this.db
|
|
978
1014
|
.prepare(`DELETE FROM ${FTS_TABLE} WHERE path = ? AND source = ? AND model = ?`)
|
|
979
|
-
.run(stale.path, "sessions", this.provider
|
|
1015
|
+
.run(stale.path, "sessions", this.provider?.model ?? "fts-only");
|
|
980
1016
|
}
|
|
981
1017
|
catch { }
|
|
982
1018
|
}
|
|
@@ -1015,8 +1051,8 @@ export class MemoryIndexManager {
|
|
|
1015
1051
|
const meta = this.readMeta();
|
|
1016
1052
|
const needsFullReindex = params?.force ||
|
|
1017
1053
|
!meta ||
|
|
1018
|
-
meta.model !== this.provider
|
|
1019
|
-
meta.provider !== this.provider
|
|
1054
|
+
meta.model !== this.provider?.model ||
|
|
1055
|
+
meta.provider !== this.provider?.id ||
|
|
1020
1056
|
meta.providerKey !== this.providerKey ||
|
|
1021
1057
|
meta.chunkTokens !== this.settings.chunking.tokens ||
|
|
1022
1058
|
meta.chunkOverlap !== this.settings.chunking.overlap ||
|
|
@@ -1068,9 +1104,9 @@ export class MemoryIndexManager {
|
|
|
1068
1104
|
resolveBatchConfig() {
|
|
1069
1105
|
const batch = this.settings.remote?.batch;
|
|
1070
1106
|
const enabled = Boolean(batch?.enabled &&
|
|
1071
|
-
((this.openAi && this.provider
|
|
1072
|
-
(this.gemini && this.provider
|
|
1073
|
-
(this.voyage && this.provider
|
|
1107
|
+
((this.openAi && this.provider?.id === "openai") ||
|
|
1108
|
+
(this.gemini && this.provider?.id === "gemini") ||
|
|
1109
|
+
(this.voyage && this.provider?.id === "voyage")));
|
|
1074
1110
|
return {
|
|
1075
1111
|
enabled,
|
|
1076
1112
|
wait: batch?.wait ?? true,
|
|
@@ -1081,7 +1117,7 @@ export class MemoryIndexManager {
|
|
|
1081
1117
|
}
|
|
1082
1118
|
async activateFallbackProvider(reason) {
|
|
1083
1119
|
const fallback = this.settings.fallback;
|
|
1084
|
-
if (!fallback || fallback === "none" || fallback === this.provider.id)
|
|
1120
|
+
if (!fallback || fallback === "none" || !this.provider || fallback === this.provider.id)
|
|
1085
1121
|
return false;
|
|
1086
1122
|
if (this.fallbackFrom)
|
|
1087
1123
|
return false;
|
|
@@ -1170,8 +1206,8 @@ export class MemoryIndexManager {
|
|
|
1170
1206
|
this.sessionsDirty = false;
|
|
1171
1207
|
}
|
|
1172
1208
|
nextMeta = {
|
|
1173
|
-
model: this.provider
|
|
1174
|
-
provider: this.provider
|
|
1209
|
+
model: this.provider?.model ?? "fts-only",
|
|
1210
|
+
provider: this.provider?.id ?? "none",
|
|
1175
1211
|
providerKey: this.providerKey,
|
|
1176
1212
|
chunkTokens: this.settings.chunking.tokens,
|
|
1177
1213
|
chunkOverlap: this.settings.chunking.overlap,
|
|
@@ -1371,7 +1407,11 @@ export class MemoryIndexManager {
|
|
|
1371
1407
|
if (unique.length === 0)
|
|
1372
1408
|
return new Map();
|
|
1373
1409
|
const out = new Map();
|
|
1374
|
-
const baseParams = [
|
|
1410
|
+
const baseParams = [
|
|
1411
|
+
this.provider?.id ?? "none",
|
|
1412
|
+
this.provider?.model ?? "fts-only",
|
|
1413
|
+
this.providerKey,
|
|
1414
|
+
];
|
|
1375
1415
|
const batchSize = 400;
|
|
1376
1416
|
for (let start = 0; start < unique.length; start += batchSize) {
|
|
1377
1417
|
const batch = unique.slice(start, start + batchSize);
|
|
@@ -1387,7 +1427,7 @@ export class MemoryIndexManager {
|
|
|
1387
1427
|
return out;
|
|
1388
1428
|
}
|
|
1389
1429
|
upsertEmbeddingCache(entries) {
|
|
1390
|
-
if (!this.cache.enabled)
|
|
1430
|
+
if (!this.cache.enabled || !this.provider)
|
|
1391
1431
|
return;
|
|
1392
1432
|
if (entries.length === 0)
|
|
1393
1433
|
return;
|
|
@@ -1461,6 +1501,9 @@ export class MemoryIndexManager {
|
|
|
1461
1501
|
return embeddings;
|
|
1462
1502
|
}
|
|
1463
1503
|
computeProviderKey() {
|
|
1504
|
+
if (!this.provider) {
|
|
1505
|
+
return hashText(JSON.stringify({ provider: "none", model: "fts-only" }));
|
|
1506
|
+
}
|
|
1464
1507
|
if (this.provider.id === "openai" && this.openAi) {
|
|
1465
1508
|
const entries = Object.entries(this.openAi.headers)
|
|
1466
1509
|
.filter(([key]) => key.toLowerCase() !== "authorization")
|
|
@@ -1491,13 +1534,13 @@ export class MemoryIndexManager {
|
|
|
1491
1534
|
return hashText(JSON.stringify({ provider: this.provider.id, model: this.provider.model }));
|
|
1492
1535
|
}
|
|
1493
1536
|
async embedChunksWithBatch(chunks, entry, source) {
|
|
1494
|
-
if (this.provider
|
|
1537
|
+
if (this.provider?.id === "openai" && this.openAi) {
|
|
1495
1538
|
return this.embedChunksWithOpenAiBatch(chunks, entry, source);
|
|
1496
1539
|
}
|
|
1497
|
-
if (this.provider
|
|
1540
|
+
if (this.provider?.id === "gemini" && this.gemini) {
|
|
1498
1541
|
return this.embedChunksWithGeminiBatch(chunks, entry, source);
|
|
1499
1542
|
}
|
|
1500
|
-
if (this.provider
|
|
1543
|
+
if (this.provider?.id === "voyage" && this.voyage) {
|
|
1501
1544
|
return this.embedChunksWithVoyageBatch(chunks, entry, source);
|
|
1502
1545
|
}
|
|
1503
1546
|
return this.embedChunksInBatches(chunks);
|
|
@@ -1602,7 +1645,7 @@ export class MemoryIndexManager {
|
|
|
1602
1645
|
method: "POST",
|
|
1603
1646
|
url: OPENAI_BATCH_ENDPOINT,
|
|
1604
1647
|
body: {
|
|
1605
|
-
model: this.openAi?.model ?? this.provider
|
|
1648
|
+
model: this.openAi?.model ?? this.provider?.model ?? "fts-only",
|
|
1606
1649
|
input: chunk.text,
|
|
1607
1650
|
},
|
|
1608
1651
|
});
|
|
@@ -1700,6 +1743,8 @@ export class MemoryIndexManager {
|
|
|
1700
1743
|
async embedBatchWithRetry(texts) {
|
|
1701
1744
|
if (texts.length === 0)
|
|
1702
1745
|
return [];
|
|
1746
|
+
if (!this.provider)
|
|
1747
|
+
throw new Error("embedding provider unavailable");
|
|
1703
1748
|
let attempt = 0;
|
|
1704
1749
|
let delayMs = EMBEDDING_RETRY_BASE_DELAY_MS;
|
|
1705
1750
|
while (true) {
|
|
@@ -1729,13 +1774,15 @@ export class MemoryIndexManager {
|
|
|
1729
1774
|
return /(rate[_ ]limit|too many requests|429|resource has been exhausted|5\d\d|cloudflare)/i.test(message);
|
|
1730
1775
|
}
|
|
1731
1776
|
resolveEmbeddingTimeout(kind) {
|
|
1732
|
-
const isLocal = this.provider
|
|
1777
|
+
const isLocal = this.provider?.id === "local";
|
|
1733
1778
|
if (kind === "query") {
|
|
1734
1779
|
return isLocal ? EMBEDDING_QUERY_TIMEOUT_LOCAL_MS : EMBEDDING_QUERY_TIMEOUT_REMOTE_MS;
|
|
1735
1780
|
}
|
|
1736
1781
|
return isLocal ? EMBEDDING_BATCH_TIMEOUT_LOCAL_MS : EMBEDDING_BATCH_TIMEOUT_REMOTE_MS;
|
|
1737
1782
|
}
|
|
1738
1783
|
async embedQueryWithTimeout(text) {
|
|
1784
|
+
if (!this.provider)
|
|
1785
|
+
throw new Error("embedding provider unavailable");
|
|
1739
1786
|
const timeoutMs = this.resolveEmbeddingTimeout("query");
|
|
1740
1787
|
log.debug("memory embeddings: query start", { provider: this.provider.id, timeoutMs });
|
|
1741
1788
|
return await this.withTimeout(this.provider.embedQuery(text), timeoutMs, `memory embeddings query timed out after ${Math.round(timeoutMs / 1000)}s`);
|
|
@@ -1873,7 +1920,7 @@ export class MemoryIndexManager {
|
|
|
1873
1920
|
try {
|
|
1874
1921
|
this.db
|
|
1875
1922
|
.prepare(`DELETE FROM ${FTS_TABLE} WHERE path = ? AND source = ? AND model = ?`)
|
|
1876
|
-
.run(entry.path, options.source, this.provider
|
|
1923
|
+
.run(entry.path, options.source, this.provider?.model ?? "fts-only");
|
|
1877
1924
|
}
|
|
1878
1925
|
catch { }
|
|
1879
1926
|
}
|
|
@@ -1883,7 +1930,8 @@ export class MemoryIndexManager {
|
|
|
1883
1930
|
for (let i = 0; i < chunks.length; i++) {
|
|
1884
1931
|
const chunk = chunks[i];
|
|
1885
1932
|
const embedding = embeddings[i] ?? [];
|
|
1886
|
-
const
|
|
1933
|
+
const providerModel = this.provider?.model ?? "fts-only";
|
|
1934
|
+
const id = hashText(`${options.source}:${entry.path}:${chunk.startLine}:${chunk.endLine}:${chunk.hash}:${providerModel}`);
|
|
1887
1935
|
this.db
|
|
1888
1936
|
.prepare(`INSERT INTO chunks (id, path, source, start_line, end_line, hash, model, text, embedding, updated_at)
|
|
1889
1937
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
@@ -1893,7 +1941,7 @@ export class MemoryIndexManager {
|
|
|
1893
1941
|
text=excluded.text,
|
|
1894
1942
|
embedding=excluded.embedding,
|
|
1895
1943
|
updated_at=excluded.updated_at`)
|
|
1896
|
-
.run(id, entry.path, options.source, chunk.startLine, chunk.endLine, chunk.hash,
|
|
1944
|
+
.run(id, entry.path, options.source, chunk.startLine, chunk.endLine, chunk.hash, providerModel, chunk.text, JSON.stringify(embedding), now);
|
|
1897
1945
|
if (vectorReady && embedding.length > 0) {
|
|
1898
1946
|
try {
|
|
1899
1947
|
this.db.prepare(`DELETE FROM ${VECTOR_TABLE} WHERE id = ?`).run(id);
|
|
@@ -1907,7 +1955,7 @@ export class MemoryIndexManager {
|
|
|
1907
1955
|
this.db
|
|
1908
1956
|
.prepare(`INSERT INTO ${FTS_TABLE} (text, id, path, source, model, start_line, end_line)\n` +
|
|
1909
1957
|
` VALUES (?, ?, ?, ?, ?, ?, ?)`)
|
|
1910
|
-
.run(chunk.text, id, entry.path, options.source,
|
|
1958
|
+
.run(chunk.text, id, entry.path, options.source, providerModel, chunk.startLine, chunk.endLine);
|
|
1911
1959
|
}
|
|
1912
1960
|
}
|
|
1913
1961
|
this.db
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maximal Marginal Relevance (MMR) re-ranking algorithm.
|
|
3
|
+
*
|
|
4
|
+
* MMR balances relevance with diversity by iteratively selecting results
|
|
5
|
+
* that maximize: λ * relevance - (1-λ) * max_similarity_to_selected
|
|
6
|
+
*
|
|
7
|
+
* @see Carbonell & Goldstein, "The Use of MMR, Diversity-Based Reranking" (1998)
|
|
8
|
+
*/
|
|
9
|
+
export const DEFAULT_MMR_CONFIG = {
|
|
10
|
+
enabled: false,
|
|
11
|
+
lambda: 0.7,
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Tokenize text for Jaccard similarity computation.
|
|
15
|
+
* Extracts alphanumeric tokens and normalizes to lowercase.
|
|
16
|
+
*/
|
|
17
|
+
export function tokenize(text) {
|
|
18
|
+
const tokens = text.toLowerCase().match(/[a-z0-9_]+/g) ?? [];
|
|
19
|
+
return new Set(tokens);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Compute Jaccard similarity between two token sets.
|
|
23
|
+
* Returns a value in [0, 1] where 1 means identical sets.
|
|
24
|
+
*/
|
|
25
|
+
export function jaccardSimilarity(setA, setB) {
|
|
26
|
+
if (setA.size === 0 && setB.size === 0) {
|
|
27
|
+
return 1;
|
|
28
|
+
}
|
|
29
|
+
if (setA.size === 0 || setB.size === 0) {
|
|
30
|
+
return 0;
|
|
31
|
+
}
|
|
32
|
+
let intersectionSize = 0;
|
|
33
|
+
const smaller = setA.size <= setB.size ? setA : setB;
|
|
34
|
+
const larger = setA.size <= setB.size ? setB : setA;
|
|
35
|
+
for (const token of smaller) {
|
|
36
|
+
if (larger.has(token)) {
|
|
37
|
+
intersectionSize++;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const unionSize = setA.size + setB.size - intersectionSize;
|
|
41
|
+
return unionSize === 0 ? 0 : intersectionSize / unionSize;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Compute text similarity between two content strings using Jaccard on tokens.
|
|
45
|
+
*/
|
|
46
|
+
export function textSimilarity(contentA, contentB) {
|
|
47
|
+
return jaccardSimilarity(tokenize(contentA), tokenize(contentB));
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Compute the maximum similarity between an item and all selected items.
|
|
51
|
+
*/
|
|
52
|
+
function maxSimilarityToSelected(item, selectedItems, tokenCache) {
|
|
53
|
+
if (selectedItems.length === 0) {
|
|
54
|
+
return 0;
|
|
55
|
+
}
|
|
56
|
+
let maxSim = 0;
|
|
57
|
+
const itemTokens = tokenCache.get(item.id) ?? tokenize(item.content);
|
|
58
|
+
for (const selected of selectedItems) {
|
|
59
|
+
const selectedTokens = tokenCache.get(selected.id) ?? tokenize(selected.content);
|
|
60
|
+
const sim = jaccardSimilarity(itemTokens, selectedTokens);
|
|
61
|
+
if (sim > maxSim) {
|
|
62
|
+
maxSim = sim;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return maxSim;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Compute MMR score for a candidate item.
|
|
69
|
+
* MMR = λ * relevance - (1-λ) * max_similarity_to_selected
|
|
70
|
+
*/
|
|
71
|
+
export function computeMMRScore(relevance, maxSimilarity, lambda) {
|
|
72
|
+
return lambda * relevance - (1 - lambda) * maxSimilarity;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Re-rank items using Maximal Marginal Relevance (MMR).
|
|
76
|
+
*
|
|
77
|
+
* The algorithm iteratively selects items that balance relevance with diversity:
|
|
78
|
+
* 1. Start with the highest-scoring item
|
|
79
|
+
* 2. For each remaining slot, select the item that maximizes the MMR score
|
|
80
|
+
* 3. MMR score = λ * relevance - (1-λ) * max_similarity_to_already_selected
|
|
81
|
+
*
|
|
82
|
+
* @param items - Items to re-rank, must have score and content
|
|
83
|
+
* @param config - MMR configuration (lambda, enabled)
|
|
84
|
+
* @returns Re-ranked items in MMR order
|
|
85
|
+
*/
|
|
86
|
+
export function mmrRerank(items, config = {}) {
|
|
87
|
+
const { enabled = DEFAULT_MMR_CONFIG.enabled, lambda = DEFAULT_MMR_CONFIG.lambda } = config;
|
|
88
|
+
// Early exits
|
|
89
|
+
if (!enabled || items.length <= 1) {
|
|
90
|
+
return [...items];
|
|
91
|
+
}
|
|
92
|
+
// Clamp lambda to valid range
|
|
93
|
+
const clampedLambda = Math.max(0, Math.min(1, lambda));
|
|
94
|
+
// If lambda is 1, just return sorted by relevance (no diversity penalty)
|
|
95
|
+
if (clampedLambda === 1) {
|
|
96
|
+
return [...items].toSorted((a, b) => b.score - a.score);
|
|
97
|
+
}
|
|
98
|
+
// Pre-tokenize all items for efficiency
|
|
99
|
+
const tokenCache = new Map();
|
|
100
|
+
for (const item of items) {
|
|
101
|
+
tokenCache.set(item.id, tokenize(item.content));
|
|
102
|
+
}
|
|
103
|
+
// Normalize scores to [0, 1] for fair comparison with similarity
|
|
104
|
+
const maxScore = Math.max(...items.map((i) => i.score));
|
|
105
|
+
const minScore = Math.min(...items.map((i) => i.score));
|
|
106
|
+
const scoreRange = maxScore - minScore;
|
|
107
|
+
const normalizeScore = (score) => {
|
|
108
|
+
if (scoreRange === 0) {
|
|
109
|
+
return 1; // All scores equal
|
|
110
|
+
}
|
|
111
|
+
return (score - minScore) / scoreRange;
|
|
112
|
+
};
|
|
113
|
+
const selected = [];
|
|
114
|
+
const remaining = new Set(items);
|
|
115
|
+
// Select items iteratively
|
|
116
|
+
while (remaining.size > 0) {
|
|
117
|
+
let bestItem = null;
|
|
118
|
+
let bestMMRScore = -Infinity;
|
|
119
|
+
for (const candidate of remaining) {
|
|
120
|
+
const normalizedRelevance = normalizeScore(candidate.score);
|
|
121
|
+
const maxSim = maxSimilarityToSelected(candidate, selected, tokenCache);
|
|
122
|
+
const mmrScore = computeMMRScore(normalizedRelevance, maxSim, clampedLambda);
|
|
123
|
+
// Use original score as tiebreaker (higher is better)
|
|
124
|
+
if (mmrScore > bestMMRScore ||
|
|
125
|
+
(mmrScore === bestMMRScore && candidate.score > (bestItem?.score ?? -Infinity))) {
|
|
126
|
+
bestMMRScore = mmrScore;
|
|
127
|
+
bestItem = candidate;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (bestItem) {
|
|
131
|
+
selected.push(bestItem);
|
|
132
|
+
remaining.delete(bestItem);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
// Should never happen, but safety exit
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return selected;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Apply MMR re-ranking to hybrid search results.
|
|
143
|
+
* Adapts the generic MMR function to work with the hybrid search result format.
|
|
144
|
+
*/
|
|
145
|
+
export function applyMMRToHybridResults(results, config = {}) {
|
|
146
|
+
if (results.length === 0) {
|
|
147
|
+
return results;
|
|
148
|
+
}
|
|
149
|
+
// Create a map from ID to original item for type-safe retrieval
|
|
150
|
+
const itemById = new Map();
|
|
151
|
+
// Create MMR items with unique IDs
|
|
152
|
+
const mmrItems = results.map((r, index) => {
|
|
153
|
+
const id = `${r.path}:${r.startLine}:${index}`;
|
|
154
|
+
itemById.set(id, r);
|
|
155
|
+
return {
|
|
156
|
+
id,
|
|
157
|
+
score: r.score,
|
|
158
|
+
content: r.snippet,
|
|
159
|
+
};
|
|
160
|
+
});
|
|
161
|
+
const reranked = mmrRerank(mmrItems, config);
|
|
162
|
+
// Map back to original items using the ID
|
|
163
|
+
return reranked.map((item) => itemById.get(item.id));
|
|
164
|
+
}
|