openclaw-hybrid-memory 2026.5.310 → 2026.6.10

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.
Files changed (535) hide show
  1. package/api/plugin-runtime.ts +2 -0
  2. package/backends/facts-db/contradictions.ts +1 -1
  3. package/cli/cmd-extract-directives.ts +225 -11
  4. package/cli/cmd-extract-proposals.ts +5 -6
  5. package/cli/cmd-extract-reinforcement.ts +71 -0
  6. package/cli/cmd-feedback.ts +15 -9
  7. package/cli/commands/manage/register-reflection-pipeline.ts +247 -13
  8. package/cli/commands/manage/register-storage-maintenance.ts +224 -15
  9. package/cli/commands/manage/storage-stats-helpers.ts +13 -2
  10. package/cli/context.ts +9 -19
  11. package/cli/distill.ts +31 -1
  12. package/cli/register.ts +28 -38
  13. package/dist/api/plugin-runtime.js.map +1 -1
  14. package/dist/backends/agent-health-store.js.map +1 -1
  15. package/dist/backends/apitap-store.js.map +1 -1
  16. package/dist/backends/audit-store.js.map +1 -1
  17. package/dist/backends/base-sqlite-store.js.map +1 -1
  18. package/dist/backends/cost-tracker.js.map +1 -1
  19. package/dist/backends/credentials-db.js +2 -3
  20. package/dist/backends/credentials-db.js.map +1 -1
  21. package/dist/backends/crystallization-store.js.map +1 -1
  22. package/dist/backends/edict-store.js.map +1 -1
  23. package/dist/backends/event-bus.js.map +1 -1
  24. package/dist/backends/event-log.js.map +1 -1
  25. package/dist/backends/facts-db/cache-manager.js.map +1 -1
  26. package/dist/backends/facts-db/clusters.js.map +1 -1
  27. package/dist/backends/facts-db/contradictions.js +1 -1
  28. package/dist/backends/facts-db/contradictions.js.map +1 -1
  29. package/dist/backends/facts-db/crud.js.map +1 -1
  30. package/dist/backends/facts-db/db-connection.js.map +1 -1
  31. package/dist/backends/facts-db/entity-autolink.js.map +1 -1
  32. package/dist/backends/facts-db/entity-layer.js.map +1 -1
  33. package/dist/backends/facts-db/episodes.js.map +1 -1
  34. package/dist/backends/facts-db/fact-queries.js.map +1 -1
  35. package/dist/backends/facts-db/fact-read-queries.js.map +1 -1
  36. package/dist/backends/facts-db/facts-db-layer1.js.map +1 -1
  37. package/dist/backends/facts-db/facts-db-layer2.js.map +1 -1
  38. package/dist/backends/facts-db/facts-db-layer3.js.map +1 -1
  39. package/dist/backends/facts-db/fts-text.js.map +1 -1
  40. package/dist/backends/facts-db/generated-skills/policy.js.map +1 -1
  41. package/dist/backends/facts-db/generated-skills.js.map +1 -1
  42. package/dist/backends/facts-db/housekeeping.js.map +1 -1
  43. package/dist/backends/facts-db/links.js.map +1 -1
  44. package/dist/backends/facts-db/maintenance.js.map +1 -1
  45. package/dist/backends/facts-db/procedures/crud.js.map +1 -1
  46. package/dist/backends/facts-db/procedures/internal.js.map +1 -1
  47. package/dist/backends/facts-db/procedures/promotion.js.map +1 -1
  48. package/dist/backends/facts-db/procedures/search.js.map +1 -1
  49. package/dist/backends/facts-db/procedures/stats.js.map +1 -1
  50. package/dist/backends/facts-db/reinforcement.js.map +1 -1
  51. package/dist/backends/facts-db/row-mapper.js.map +1 -1
  52. package/dist/backends/facts-db/scan-cursors.js.map +1 -1
  53. package/dist/backends/facts-db/schema-bootstrap.js.map +1 -1
  54. package/dist/backends/facts-db/scope-sql.js.map +1 -1
  55. package/dist/backends/facts-db/search.js.map +1 -1
  56. package/dist/backends/facts-db/stats.js.map +1 -1
  57. package/dist/backends/facts-db/types.js.map +1 -1
  58. package/dist/backends/facts-db/variants.js.map +1 -1
  59. package/dist/backends/identity-reflection-store.js.map +1 -1
  60. package/dist/backends/issue-store.js.map +1 -1
  61. package/dist/backends/learnings-db.js.map +1 -1
  62. package/dist/backends/migrations/facts-migrations.js.map +1 -1
  63. package/dist/backends/migrations/procedures.js.map +1 -1
  64. package/dist/backends/narratives-db.js.map +1 -1
  65. package/dist/backends/persona-state-store.js.map +1 -1
  66. package/dist/backends/proposals-db.js.map +1 -1
  67. package/dist/backends/scope-filter-sql.js.map +1 -1
  68. package/dist/backends/sqlite-schema-meta.js.map +1 -1
  69. package/dist/backends/tool-proposal-store.js.map +1 -1
  70. package/dist/backends/vector-db/constants.js.map +1 -1
  71. package/dist/backends/vector-db/path-utils.js.map +1 -1
  72. package/dist/backends/vector-db/runtime-locks.js.map +1 -1
  73. package/dist/backends/vector-db/vector-db-class.js.map +1 -1
  74. package/dist/backends/wal.js.map +1 -1
  75. package/dist/backends/workflow-store.js.map +1 -1
  76. package/dist/benchmark/shadow-eval.js.map +1 -1
  77. package/dist/cli/active-tasks.js.map +1 -1
  78. package/dist/cli/backup.js.map +1 -1
  79. package/dist/cli/benchmark.js.map +1 -1
  80. package/dist/cli/cmd-backfill.js.map +1 -1
  81. package/dist/cli/cmd-config.js.map +1 -1
  82. package/dist/cli/cmd-credentials.js.map +1 -1
  83. package/dist/cli/cmd-demo.js.map +1 -1
  84. package/dist/cli/cmd-distill.js.map +1 -1
  85. package/dist/cli/cmd-doctor.js.map +1 -1
  86. package/dist/cli/cmd-examples.js.map +1 -1
  87. package/dist/cli/cmd-extract-daily.js.map +1 -1
  88. package/dist/cli/cmd-extract-directives.js +141 -10
  89. package/dist/cli/cmd-extract-directives.js.map +1 -1
  90. package/dist/cli/cmd-extract-procedures.js.map +1 -1
  91. package/dist/cli/cmd-extract-proposals.js +3 -2
  92. package/dist/cli/cmd-extract-proposals.js.map +1 -1
  93. package/dist/cli/cmd-extract-reinforcement.js +39 -0
  94. package/dist/cli/cmd-extract-reinforcement.js.map +1 -1
  95. package/dist/cli/cmd-extract-sessions.js.map +1 -1
  96. package/dist/cli/cmd-feedback.js +9 -4
  97. package/dist/cli/cmd-feedback.js.map +1 -1
  98. package/dist/cli/cmd-health.js.map +1 -1
  99. package/dist/cli/cmd-providers.js.map +1 -1
  100. package/dist/cli/cmd-selfcorrection.js.map +1 -1
  101. package/dist/cli/cmd-setup.js.map +1 -1
  102. package/dist/cli/cmd-status.js.map +1 -1
  103. package/dist/cli/cmd-store.js.map +1 -1
  104. package/dist/cli/cmd-user-friendly.js.map +1 -1
  105. package/dist/cli/cmd-verify.js.map +1 -1
  106. package/dist/cli/commands/manage/bindings.js.map +1 -1
  107. package/dist/cli/commands/manage/dream-cycle-followup.js.map +1 -1
  108. package/dist/cli/commands/manage/maintenance-heartbeat.js.map +1 -1
  109. package/dist/cli/commands/manage/register-agents-audit-runall.js.map +1 -1
  110. package/dist/cli/commands/manage/register-analyze-maintenance-logs.js.map +1 -1
  111. package/dist/cli/commands/manage/register-budget-proposals.js.map +1 -1
  112. package/dist/cli/commands/manage/register-config-cli.js.map +1 -1
  113. package/dist/cli/commands/manage/register-corrections-and-pipeline.js.map +1 -1
  114. package/dist/cli/commands/manage/register-corrections.js.map +1 -1
  115. package/dist/cli/commands/manage/register-council.js.map +1 -1
  116. package/dist/cli/commands/manage/register-credentials-scope.js.map +1 -1
  117. package/dist/cli/commands/manage/register-digest.js.map +1 -1
  118. package/dist/cli/commands/manage/register-lifecycle.js.map +1 -1
  119. package/dist/cli/commands/manage/register-procedure-lifecycle.js.map +1 -1
  120. package/dist/cli/commands/manage/register-reconcile-cron-ledgers.js.map +1 -1
  121. package/dist/cli/commands/manage/register-reflection-pipeline.js +144 -7
  122. package/dist/cli/commands/manage/register-reflection-pipeline.js.map +1 -1
  123. package/dist/cli/commands/manage/register-self-correction-feedback.js.map +1 -1
  124. package/dist/cli/commands/manage/register-storage-and-stats.js.map +1 -1
  125. package/dist/cli/commands/manage/register-storage-entities-decay.js.map +1 -1
  126. package/dist/cli/commands/manage/register-storage-graph-audit.js.map +1 -1
  127. package/dist/cli/commands/manage/register-storage-maintenance.js +152 -9
  128. package/dist/cli/commands/manage/register-storage-maintenance.js.map +1 -1
  129. package/dist/cli/commands/manage/register-validate-cron-exit.js.map +1 -1
  130. package/dist/cli/commands/manage/storage-stats-helpers.js +10 -3
  131. package/dist/cli/commands/manage/storage-stats-helpers.js.map +1 -1
  132. package/dist/cli/commands/register-manage-commands.js.map +1 -1
  133. package/dist/cli/config-feature-summaries.js.map +1 -1
  134. package/dist/cli/config-output-sink.js.map +1 -1
  135. package/dist/cli/distill-session-jsonl.js.map +1 -1
  136. package/dist/cli/distill.js +10 -1
  137. package/dist/cli/distill.js.map +1 -1
  138. package/dist/cli/global-verbose.js.map +1 -1
  139. package/dist/cli/goals.js.map +1 -1
  140. package/dist/cli/hybrid-mem-commander-utils.js.map +1 -1
  141. package/dist/cli/install/config-merge.js.map +1 -1
  142. package/dist/cli/install/cron-jobs.js.map +1 -1
  143. package/dist/cli/install/embedding-detect.js.map +1 -1
  144. package/dist/cli/install/run-install.js.map +1 -1
  145. package/dist/cli/install/workspace.js.map +1 -1
  146. package/dist/cli/proposals.js.map +1 -1
  147. package/dist/cli/register.js.map +1 -1
  148. package/dist/cli/shared.js.map +1 -1
  149. package/dist/cli/skills.js.map +1 -1
  150. package/dist/cli/task-queue-status.js.map +1 -1
  151. package/dist/cli/verified.js.map +1 -1
  152. package/dist/cli/verify/fact-count.js.map +1 -1
  153. package/dist/cli/verify/openclaw-config.js.map +1 -1
  154. package/dist/cli/verify/plugin-config-credentials.js.map +1 -1
  155. package/dist/cli/verify/sections/config-cron.js.map +1 -1
  156. package/dist/cli/verify/sections/embeddings.js.map +1 -1
  157. package/dist/cli/verify/sections/infrastructure.js.map +1 -1
  158. package/dist/cli/verify/sections/llm-models.js.map +1 -1
  159. package/dist/cli/verify/sections/reconcile.js.map +1 -1
  160. package/dist/cli/verify/verify-run-state.js.map +1 -1
  161. package/dist/cli/verify-llm-azure-auth.js.map +1 -1
  162. package/dist/cli/verify.js.map +1 -1
  163. package/dist/config/hybrid-schema.js.map +1 -1
  164. package/dist/config/index.js.map +1 -1
  165. package/dist/config/maintenance-fallback-policy.js.map +1 -1
  166. package/dist/config/parsers/capture.js.map +1 -1
  167. package/dist/config/parsers/core.js.map +1 -1
  168. package/dist/config/parsers/features.js.map +1 -1
  169. package/dist/config/parsers/index.js.map +1 -1
  170. package/dist/config/parsers/maintenance.js.map +1 -1
  171. package/dist/config/parsers/retrieval.js.map +1 -1
  172. package/dist/config/parsers/sensors.js.map +1 -1
  173. package/dist/config/skill-sections.js.map +1 -1
  174. package/dist/config/skill-size-limits.js.map +1 -1
  175. package/dist/config/types/agents.js.map +1 -1
  176. package/dist/config/types/bootstrap.js.map +1 -1
  177. package/dist/config/types/core.js.map +1 -1
  178. package/dist/config/types/index.js.map +1 -1
  179. package/dist/config/utils.js.map +1 -1
  180. package/dist/index-help.js.map +1 -1
  181. package/dist/index-testing-exports.js.map +1 -1
  182. package/dist/index.d.ts +1 -1
  183. package/dist/index.js +2 -2
  184. package/dist/index.js.map +1 -1
  185. package/dist/lifecycle/hook-resolution-api.js.map +1 -1
  186. package/dist/lifecycle/hooks.js +0 -1
  187. package/dist/lifecycle/hooks.js.map +1 -1
  188. package/dist/lifecycle/resolve-agent-id.js.map +1 -1
  189. package/dist/lifecycle/session-state.js.map +1 -1
  190. package/dist/lifecycle/stage-active-task.js.map +1 -1
  191. package/dist/lifecycle/stage-auth-failure.js.map +1 -1
  192. package/dist/lifecycle/stage-capture/run-capture.js.map +1 -1
  193. package/dist/lifecycle/stage-capture.js.map +1 -1
  194. package/dist/lifecycle/stage-cleanup.js.map +1 -1
  195. package/dist/lifecycle/stage-credential-hint.js.map +1 -1
  196. package/dist/lifecycle/stage-frustration.js.map +1 -1
  197. package/dist/lifecycle/stage-goal-stewardship.js.map +1 -1
  198. package/dist/lifecycle/stage-goal-subagent.js.map +1 -1
  199. package/dist/lifecycle/stage-injection.js +1 -1
  200. package/dist/lifecycle/stage-injection.js.map +1 -1
  201. package/dist/lifecycle/stage-recall/run-recall.js.map +1 -1
  202. package/dist/lifecycle/stage-recall.js.map +1 -1
  203. package/dist/lifecycle/stage-setup.js.map +1 -1
  204. package/dist/routes/dashboard/collectors.js.map +1 -1
  205. package/dist/routes/dashboard/html.js.map +1 -1
  206. package/dist/routes/dashboard/server.js.map +1 -1
  207. package/dist/routes/dashboard-graph.js.map +1 -1
  208. package/dist/routes/graphql-resolvers.js.map +1 -1
  209. package/dist/routes/graphql-server.js.map +1 -1
  210. package/dist/services/active-task-checkpoint.js.map +1 -1
  211. package/dist/services/active-task-injection.js.map +1 -1
  212. package/dist/services/active-task.js.map +1 -1
  213. package/dist/services/adaptive-catch-up-pacing.js +25 -0
  214. package/dist/services/adaptive-catch-up-pacing.js.map +1 -0
  215. package/dist/services/adaptive-maintenance-llm.js.map +1 -1
  216. package/dist/services/adaptive-model-limits.js.map +1 -1
  217. package/dist/services/ambient-retrieval.js.map +1 -1
  218. package/dist/services/apitap-service.js.map +1 -1
  219. package/dist/services/audit-health-exit-info.js.map +1 -1
  220. package/dist/services/audit-health-json.js.map +1 -1
  221. package/dist/services/auth-failure-detect.js.map +1 -1
  222. package/dist/services/auto-capture.js.map +1 -1
  223. package/dist/services/auto-classifier.js.map +1 -1
  224. package/dist/services/auto-skills-audit.js.map +1 -1
  225. package/dist/services/bootstrap-optional.js.map +1 -1
  226. package/dist/services/bootstrap-priority.js.map +1 -1
  227. package/dist/services/bootstrap.js.map +1 -1
  228. package/dist/services/capture-provenance.js.map +1 -1
  229. package/dist/services/capture-utils.js.map +1 -1
  230. package/dist/services/chat.js +22 -3
  231. package/dist/services/chat.js.map +1 -1
  232. package/dist/services/classification-scope.js.map +1 -1
  233. package/dist/services/classification.js.map +1 -1
  234. package/dist/services/cli-sql-dump.js.map +1 -1
  235. package/dist/services/consolidation.js.map +1 -1
  236. package/dist/services/context-audit.js +1 -1
  237. package/dist/services/context-audit.js.map +1 -1
  238. package/dist/services/context-budget.js.map +1 -1
  239. package/dist/services/context-engine.js.map +1 -1
  240. package/dist/services/contextual-variants.js.map +1 -1
  241. package/dist/services/continuous-verifier.js.map +1 -1
  242. package/dist/services/contradiction-adjudicator.js.map +1 -1
  243. package/dist/services/cost-context.js.map +1 -1
  244. package/dist/services/cost-feature-labels.js.map +1 -1
  245. package/dist/services/credential-migration.js.map +1 -1
  246. package/dist/services/credential-scanner.js.map +1 -1
  247. package/dist/services/credential-validation.js.map +1 -1
  248. package/dist/services/cron-exit-validator.js.map +1 -1
  249. package/dist/services/cron-guard.js.map +1 -1
  250. package/dist/services/cron-job-bash-harness.js +52 -5
  251. package/dist/services/cron-job-bash-harness.js.map +1 -1
  252. package/dist/services/cron-maintenance-reconciler.js +1 -3
  253. package/dist/services/cron-maintenance-reconciler.js.map +1 -1
  254. package/dist/services/cross-agent-learning.js.map +1 -1
  255. package/dist/services/crystallization-proposer.js.map +1 -1
  256. package/dist/services/dedupe-policy.js.map +1 -1
  257. package/dist/services/deprecated-cron-commands.js.map +1 -1
  258. package/dist/services/directive-extract.js.map +1 -1
  259. package/dist/services/document-chunker.js.map +1 -1
  260. package/dist/services/document-grader.js.map +1 -1
  261. package/dist/services/dream-cycle.js.map +1 -1
  262. package/dist/services/embedding-migration.js.map +1 -1
  263. package/dist/services/embedding-registry.js.map +1 -1
  264. package/dist/services/embeddings/chain-provider.js.map +1 -1
  265. package/dist/services/embeddings/factory.js.map +1 -1
  266. package/dist/services/embeddings/fallback-provider.js.map +1 -1
  267. package/dist/services/embeddings/ollama-provider.js.map +1 -1
  268. package/dist/services/embeddings/onnx-provider.js.map +1 -1
  269. package/dist/services/embeddings/openai-provider.js.map +1 -1
  270. package/dist/services/embeddings/shared.js +3 -3
  271. package/dist/services/embeddings/shared.js.map +1 -1
  272. package/dist/services/embeddings/types.js.map +1 -1
  273. package/dist/services/entity-enrichment-adaptive.js +128 -0
  274. package/dist/services/entity-enrichment-adaptive.js.map +1 -0
  275. package/dist/services/entity-enrichment-cli.js +389 -42
  276. package/dist/services/entity-enrichment-cli.js.map +1 -1
  277. package/dist/services/entity-enrichment.js +31 -5
  278. package/dist/services/entity-enrichment.js.map +1 -1
  279. package/dist/services/error-reporter/noisy-errors.js.map +1 -1
  280. package/dist/services/error-reporter/sanitize.js.map +1 -1
  281. package/dist/services/error-reporter.js.map +1 -1
  282. package/dist/services/event-hub-repair.js.map +1 -1
  283. package/dist/services/export-memory.js.map +1 -1
  284. package/dist/services/fact-extraction.js.map +1 -1
  285. package/dist/services/feedback-effectiveness.js.map +1 -1
  286. package/dist/services/find-duplicates.js.map +1 -1
  287. package/dist/services/frustration-detector.js.map +1 -1
  288. package/dist/services/fts-search.js.map +1 -1
  289. package/dist/services/gap-detector.js.map +1 -1
  290. package/dist/services/generated-skill-lifecycle.js.map +1 -1
  291. package/dist/services/generated-skill-validation.js.map +1 -1
  292. package/dist/services/goal-active-task-mirror.js.map +1 -1
  293. package/dist/services/goal-circuit-breaker.js.map +1 -1
  294. package/dist/services/goal-health.js.map +1 -1
  295. package/dist/services/goal-registry.js.map +1 -1
  296. package/dist/services/goal-stewardship-heartbeat.js.map +1 -1
  297. package/dist/services/goal-stewardship-llm-triage.js.map +1 -1
  298. package/dist/services/goal-stewardship-verify-cron.js.map +1 -1
  299. package/dist/services/goal-stewardship.js.map +1 -1
  300. package/dist/services/goal-subagent.js.map +1 -1
  301. package/dist/services/graph-retrieval.js.map +1 -1
  302. package/dist/services/humanizer-score.js.map +1 -1
  303. package/dist/services/hybrid-mem-cron-default-job-steps.js.map +1 -1
  304. package/dist/services/hyde-helper.js.map +1 -1
  305. package/dist/services/identity-reflection.js.map +1 -1
  306. package/dist/services/implicit-feedback-extract.js.map +1 -1
  307. package/dist/services/index.js.map +1 -1
  308. package/dist/services/ingest-utils.js.map +1 -1
  309. package/dist/services/intent-template.js.map +1 -1
  310. package/dist/services/json-array-parser.js.map +1 -1
  311. package/dist/services/knowledge-gaps.js.map +1 -1
  312. package/dist/services/language-keywords-build.js.map +1 -1
  313. package/dist/services/lifecycle/github-adapter.js.map +1 -1
  314. package/dist/services/llm-rate-limit-headers.js +1 -2
  315. package/dist/services/llm-rate-limit-headers.js.map +1 -1
  316. package/dist/services/maintenance-auto-fix.js.map +1 -1
  317. package/dist/services/maintenance-log-analyzer.js +7 -1
  318. package/dist/services/maintenance-log-analyzer.js.map +1 -1
  319. package/dist/services/maintenance-timestamp.js.map +1 -1
  320. package/dist/services/memory-diagnostics.js.map +1 -1
  321. package/dist/services/memory-index.js.map +1 -1
  322. package/dist/services/merge-results.js.map +1 -1
  323. package/dist/services/model-capabilities.js.map +1 -1
  324. package/dist/services/model-pricing.js.map +1 -1
  325. package/dist/services/narrative-recall.js.map +1 -1
  326. package/dist/services/openclaw-session-artifact.js.map +1 -1
  327. package/dist/services/passive-observer.js.map +1 -1
  328. package/dist/services/pattern-detector-hash.js.map +1 -1
  329. package/dist/services/pattern-detector.js.map +1 -1
  330. package/dist/services/pending-autopilot/foundation.js.map +1 -1
  331. package/dist/services/pending-autopilot/redaction.js.map +1 -1
  332. package/dist/services/pending-autopilot/store.js.map +1 -1
  333. package/dist/services/pending-autopilot/types.js.map +1 -1
  334. package/dist/services/pending-digest-autopilot-cron.js.map +1 -1
  335. package/dist/services/pending-digest-autopilot.js.map +1 -1
  336. package/dist/services/pending-review-digest.js.map +1 -1
  337. package/dist/services/persona-proposal-triage.js.map +1 -1
  338. package/dist/services/persona-state-promotion.js.map +1 -1
  339. package/dist/services/post-compaction-recall.js.map +1 -1
  340. package/dist/services/pre-consolidation-flush.js.map +1 -1
  341. package/dist/services/pre-finalization-guard.js.map +1 -1
  342. package/dist/services/procedure-cluster.js.map +1 -1
  343. package/dist/services/procedure-extractor.js.map +1 -1
  344. package/dist/services/procedure-promotion/duplicate-skill-cache.js.map +1 -1
  345. package/dist/services/procedure-promotion-policy.js.map +1 -1
  346. package/dist/services/procedure-selection-metrics.js.map +1 -1
  347. package/dist/services/procedure-skill-eval.js.map +1 -1
  348. package/dist/services/procedure-skill-generator.js.map +1 -1
  349. package/dist/services/procedure-skill-recipe.js.map +1 -1
  350. package/dist/services/procedure-skill-shrink.js.map +1 -1
  351. package/dist/services/procedure-skill-workflow.js.map +1 -1
  352. package/dist/services/provenance.js.map +1 -1
  353. package/dist/services/public-export-bundle.js.map +1 -1
  354. package/dist/services/python-bridge.js.map +1 -1
  355. package/dist/services/query-expander.js.map +1 -1
  356. package/dist/services/query-validator.js.map +1 -1
  357. package/dist/services/recall-pipeline.js.map +1 -1
  358. package/dist/services/recall-timing.js.map +1 -1
  359. package/dist/services/recent-http-attempts.js.map +1 -1
  360. package/dist/services/reflection/shared.js.map +1 -1
  361. package/dist/services/reflection.js.map +1 -1
  362. package/dist/services/reinforcement-extract.js.map +1 -1
  363. package/dist/services/reranker.js.map +1 -1
  364. package/dist/services/responses-adapter.js.map +1 -1
  365. package/dist/services/retrieval-aliases.js.map +1 -1
  366. package/dist/services/retrieval-mode-policy.js.map +1 -1
  367. package/dist/services/retrieval-orchestrator/packing.js.map +1 -1
  368. package/dist/services/retrieval-orchestrator.d.ts +2 -3
  369. package/dist/services/retrieval-orchestrator.js.map +1 -1
  370. package/dist/services/rrf-fusion.js.map +1 -1
  371. package/dist/services/self-correction-extract.js.map +1 -1
  372. package/dist/services/session-observability.js.map +1 -1
  373. package/dist/services/session-pre-filter.js.map +1 -1
  374. package/dist/services/shortest-path.js.map +1 -1
  375. package/dist/services/skill-allowed-tools.js.map +1 -1
  376. package/dist/services/skill-creator-validator.js.map +1 -1
  377. package/dist/services/skill-crystallizer-helpers.js.map +1 -1
  378. package/dist/services/skill-crystallizer.js.map +1 -1
  379. package/dist/services/skill-description-builder.js.map +1 -1
  380. package/dist/services/skill-eval-synthesizer.js.map +1 -1
  381. package/dist/services/skill-examples-builder.js.map +1 -1
  382. package/dist/services/skill-frontmatter.js.map +1 -1
  383. package/dist/services/skill-name-validator.js.map +1 -1
  384. package/dist/services/skill-prompt-injection.js.map +1 -1
  385. package/dist/services/skill-reference-sidecar.js.map +1 -1
  386. package/dist/services/skill-script-bundler.js.map +1 -1
  387. package/dist/services/skill-validator.js.map +1 -1
  388. package/dist/services/startup-memory-attribution.js.map +1 -1
  389. package/dist/services/task-hygiene.js.map +1 -1
  390. package/dist/services/task-ledger/canonical.js.map +1 -1
  391. package/dist/services/task-ledger-facts.js.map +1 -1
  392. package/dist/services/task-queue-leases.js.map +1 -1
  393. package/dist/services/task-queue-watchdog.js.map +1 -1
  394. package/dist/services/tool-effectiveness.js.map +1 -1
  395. package/dist/services/tool-proposer.js.map +1 -1
  396. package/dist/services/tools-md-section.js.map +1 -1
  397. package/dist/services/topic-clusters.js.map +1 -1
  398. package/dist/services/trajectory-tracker.js.map +1 -1
  399. package/dist/services/vector-backend-observability.js.map +1 -1
  400. package/dist/services/vector-lifecycle-audit.js.map +1 -1
  401. package/dist/services/vector-maintenance.js.map +1 -1
  402. package/dist/services/vector-search.js.map +1 -1
  403. package/dist/services/verification-store.js.map +1 -1
  404. package/dist/services/verified-fact-triage.js.map +1 -1
  405. package/dist/services/wal-helpers.js.map +1 -1
  406. package/dist/services/workflow-tracker.js.map +1 -1
  407. package/dist/setup/bootstrap-databases.js.map +1 -1
  408. package/dist/setup/cli-context/cli-services.js.map +1 -1
  409. package/dist/setup/cli-context/help-text.js.map +1 -1
  410. package/dist/setup/cli-context/metadata.js.map +1 -1
  411. package/dist/setup/cli-context/register-cli-with-help.js.map +1 -1
  412. package/dist/setup/cli-context/register-full.js.map +1 -1
  413. package/dist/setup/cli-context/register-help.js.map +1 -1
  414. package/dist/setup/cost-instrumentation.js.map +1 -1
  415. package/dist/setup/hybrid-memory-generation-state.js.map +1 -1
  416. package/dist/setup/hybrid-memory-reload-coordinator.js +13 -13
  417. package/dist/setup/hybrid-memory-reload-coordinator.js.map +1 -1
  418. package/dist/setup/plugin-service.js.map +1 -1
  419. package/dist/setup/provider-router.js.map +1 -1
  420. package/dist/setup/register-context-engine.js.map +1 -1
  421. package/dist/setup/register-hooks.js.map +1 -1
  422. package/dist/setup/register-plugin.js +25 -21
  423. package/dist/setup/register-plugin.js.map +1 -1
  424. package/dist/setup/register-tools.js.map +1 -1
  425. package/dist/setup/reregister-policy.js +2 -2
  426. package/dist/setup/reregister-policy.js.map +1 -1
  427. package/dist/setup/tool-installers.js.map +1 -1
  428. package/dist/setup/workspace-bootstrap.js.map +1 -1
  429. package/dist/src/worker/narratives.js.map +1 -1
  430. package/dist/tools/apitap-tools.js.map +1 -1
  431. package/dist/tools/credential-tools.js.map +1 -1
  432. package/dist/tools/crystallization-tools.js.map +1 -1
  433. package/dist/tools/dashboard-routes.js.map +1 -1
  434. package/dist/tools/document-tools.js.map +1 -1
  435. package/dist/tools/goal-tools.js.map +1 -1
  436. package/dist/tools/graph-tools.js.map +1 -1
  437. package/dist/tools/issue-tools.js.map +1 -1
  438. package/dist/tools/memory/build-runtime.js.map +1 -1
  439. package/dist/tools/memory/helpers.js.map +1 -1
  440. package/dist/tools/memory/register-checkpoint-tools.js.map +1 -1
  441. package/dist/tools/memory/register-directory-tools.js.map +1 -1
  442. package/dist/tools/memory/register-edict-tools.js.map +1 -1
  443. package/dist/tools/memory/register-episode-tools.js.map +1 -1
  444. package/dist/tools/memory/register-recall-tools.js.map +1 -1
  445. package/dist/tools/memory/register-store-tools.js.map +1 -1
  446. package/dist/tools/memory-tools.js.map +1 -1
  447. package/dist/tools/persona-tools.js.map +1 -1
  448. package/dist/tools/provenance-tools.js.map +1 -1
  449. package/dist/tools/public-api-routes.js.map +1 -1
  450. package/dist/tools/safe-register-http-route.js.map +1 -1
  451. package/dist/tools/self-extension-tools.js.map +1 -1
  452. package/dist/tools/task-hygiene-tools.js.map +1 -1
  453. package/dist/tools/utility-tools.js.map +1 -1
  454. package/dist/tools/verification-tools.js.map +1 -1
  455. package/dist/tools/workflow-tools.js.map +1 -1
  456. package/dist/types/issue-types.js.map +1 -1
  457. package/dist/types/learnings-types.js.map +1 -1
  458. package/dist/types/memory.js.map +1 -1
  459. package/dist/utils/apim-gateway-fetch.js.map +1 -1
  460. package/dist/utils/atomic-write.js.map +1 -1
  461. package/dist/utils/auth-failover.js.map +1 -1
  462. package/dist/utils/auth.js.map +1 -1
  463. package/dist/utils/compaction-model-watchdog.js.map +1 -1
  464. package/dist/utils/consolidation-controls.js.map +1 -1
  465. package/dist/utils/constants.js.map +1 -1
  466. package/dist/utils/date-detector.js.map +1 -1
  467. package/dist/utils/dates.js.map +1 -1
  468. package/dist/utils/decay.js.map +1 -1
  469. package/dist/utils/duration.js.map +1 -1
  470. package/dist/utils/embed-call.js.map +1 -1
  471. package/dist/utils/entity-lookup-resolve.js.map +1 -1
  472. package/dist/utils/entity-mention-quality.js.map +1 -1
  473. package/dist/utils/entity-stopwords.js.map +1 -1
  474. package/dist/utils/env-manager.js.map +1 -1
  475. package/dist/utils/error-tracking.js.map +1 -1
  476. package/dist/utils/event-loop-yield.js.map +1 -1
  477. package/dist/utils/extract-last-user-message.js.map +1 -1
  478. package/dist/utils/extraction-from-template.js.map +1 -1
  479. package/dist/utils/fact-embeddings.js.map +1 -1
  480. package/dist/utils/file-snapshot.js.map +1 -1
  481. package/dist/utils/format.js.map +1 -1
  482. package/dist/utils/fs.js.map +1 -1
  483. package/dist/utils/gh-repo-arg.js.map +1 -1
  484. package/dist/utils/hybrid-mem-json-cli.js.map +1 -1
  485. package/dist/utils/language-keywords.js.map +1 -1
  486. package/dist/utils/lifecycle-generation.js.map +1 -1
  487. package/dist/utils/llm-json-array.js.map +1 -1
  488. package/dist/utils/llm-selection.js.map +1 -1
  489. package/dist/utils/logger.js.map +1 -1
  490. package/dist/utils/model-provider-family.js.map +1 -1
  491. package/dist/utils/model-tier.js.map +1 -1
  492. package/dist/utils/openclaw-agent-defaults.js.map +1 -1
  493. package/dist/utils/path.js.map +1 -1
  494. package/dist/utils/plugin-root.js.map +1 -1
  495. package/dist/utils/plugin-update-check.js.map +1 -1
  496. package/dist/utils/procedure-risk.js.map +1 -1
  497. package/dist/utils/progress-indicators.js.map +1 -1
  498. package/dist/utils/prompt-loader.js.map +1 -1
  499. package/dist/utils/provenance.js.map +1 -1
  500. package/dist/utils/provider-detection.js.map +1 -1
  501. package/dist/utils/registration-superseded.js.map +1 -1
  502. package/dist/utils/salience.js.map +1 -1
  503. package/dist/utils/sanitize-messages.js.map +1 -1
  504. package/dist/utils/scope-filter.js.map +1 -1
  505. package/dist/utils/skill-discovery.js.map +1 -1
  506. package/dist/utils/sqlite-file-perms.js.map +1 -1
  507. package/dist/utils/sqlite-outcome-compat.js.map +1 -1
  508. package/dist/utils/sqlite-transaction.js.map +1 -1
  509. package/dist/utils/stable-stringify.js.map +1 -1
  510. package/dist/utils/subagent-ended-utils.js.map +1 -1
  511. package/dist/utils/tags.js.map +1 -1
  512. package/dist/utils/text.js.map +1 -1
  513. package/dist/utils/timeout.js.map +1 -1
  514. package/dist/utils/typebox.js.map +1 -1
  515. package/dist/utils/version-check.js.map +1 -1
  516. package/dist/utils/wal-replay.js.map +1 -1
  517. package/dist/versionInfo.js.map +1 -1
  518. package/index.ts +2 -2
  519. package/lifecycle/hooks.ts +0 -1
  520. package/npm-shrinkwrap.json +487 -186
  521. package/openclaw.plugin.json +1 -1
  522. package/package.json +2 -2
  523. package/services/adaptive-catch-up-pacing.ts +28 -0
  524. package/services/chat.ts +34 -1
  525. package/services/cron-job-bash-harness.ts +52 -5
  526. package/services/embeddings/shared.ts +5 -2
  527. package/services/entity-enrichment-adaptive.ts +245 -0
  528. package/services/entity-enrichment-cli.ts +553 -47
  529. package/services/entity-enrichment.ts +43 -2
  530. package/services/llm-rate-limit-headers.ts +1 -4
  531. package/services/maintenance-log-analyzer.ts +13 -9
  532. package/services/reinforcement-extract.ts +19 -0
  533. package/setup/hybrid-memory-reload-coordinator.ts +26 -0
  534. package/setup/register-plugin.ts +62 -32
  535. package/setup/reregister-policy.ts +10 -5
@@ -1 +1 @@
1
- {"version":3,"file":"wal-helpers.js","names":[],"sources":["../../services/wal-helpers.ts"],"sourcesContent":["/**\n * WAL helpers — wrap the write-before-commit / remove-after-commit pattern.\n * Each call site was 8–12 lines of identical boilerplate; these reduce it to 1–2 lines.\n *\n * Circuit breaker: After 10 consecutive failures, WAL is disabled to prevent degradation.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport { existsSync, mkdirSync, rmSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { type WALEntry, WAL_ENTRY_SCHEMA_VERSION, type WriteAheadLog } from \"../backends/wal.js\";\nimport { capturePluginError } from \"./error-reporter.js\";\n\nconst WAL_FAILURE_THRESHOLD = 10;\nconst WAL_DISABLED_SENTINEL = \".wal.disabled\";\nlet walFailureCount = 0;\nlet walDisabled = false;\nlet walPersistentDisableWarned = false;\n\nexport type WalCircuitBreakerState = {\n failureCount: number;\n inMemoryDisabled: boolean;\n persistentDisabled: boolean;\n walPath: string | null;\n sentinelPath: string | null;\n};\n\n/** JSON.stringify drops Float32Array as `{}`; normalize before WAL persistence (#896). */\nfunction normalizeWalPayload(data: Record<string, unknown>): WALEntry[\"data\"] {\n const d = { ...data } as Record<string, unknown>;\n const v = d.vector;\n if (v instanceof Float32Array) {\n d.vector = Array.from(v);\n }\n return d as WALEntry[\"data\"];\n}\n\nexport function getWalDisabledSentinelPath(walPath: string): string {\n return join(dirname(walPath), WAL_DISABLED_SENTINEL);\n}\n\nfunction resolveWalPath(wal: WriteAheadLog | null): string | null {\n if (!wal) return null;\n const maybeGetPath = (wal as { getPath?: () => string }).getPath;\n if (typeof maybeGetPath !== \"function\") return null;\n try {\n const walPath = maybeGetPath.call(wal);\n if (typeof walPath !== \"string\") return null;\n const trimmed = walPath.trim();\n return trimmed.length > 0 ? trimmed : null;\n } catch {\n return null;\n }\n}\n\nexport function isWalPersistentlyDisabledAtPath(walPath: string): boolean {\n try {\n return existsSync(getWalDisabledSentinelPath(walPath));\n } catch {\n return false;\n }\n}\n\nfunction resetWalCircuitBreakerState(): void {\n walFailureCount = 0;\n walDisabled = false;\n walPersistentDisableWarned = false;\n}\n\nfunction persistWalDisabledSentinel(walPath: string, err: unknown): string {\n const sentinelPath = getWalDisabledSentinelPath(walPath);\n mkdirSync(dirname(sentinelPath), { recursive: true });\n const payload = {\n reason: \"wal-circuit-breaker-threshold\",\n threshold: WAL_FAILURE_THRESHOLD,\n failureCount: walFailureCount,\n trippedAt: new Date().toISOString(),\n error: err instanceof Error ? err.message : String(err),\n };\n writeFileSync(sentinelPath, `${JSON.stringify(payload, null, 2)}\\n`, \"utf-8\");\n return sentinelPath;\n}\n\nexport function getWalCircuitBreakerState(wal: WriteAheadLog | null): WalCircuitBreakerState {\n const walPath = resolveWalPath(wal);\n const sentinelPath = walPath ? getWalDisabledSentinelPath(walPath) : null;\n return {\n failureCount: walFailureCount,\n inMemoryDisabled: walDisabled,\n persistentDisabled: walPath ? isWalPersistentlyDisabledAtPath(walPath) : false,\n walPath,\n sentinelPath,\n };\n}\n\nexport async function walWrite(\n wal: WriteAheadLog | null,\n operation: \"store\" | \"update\",\n data: Record<string, unknown>,\n logger: { warn: (msg: string) => void },\n supersedeTargetId?: string,\n): Promise<string> {\n const id = randomUUID();\n if (!wal) return id;\n if (walDisabled) return id;\n const walPath = resolveWalPath(wal);\n if (walPath && isWalPersistentlyDisabledAtPath(walPath)) {\n walDisabled = true;\n if (!walPersistentDisableWarned) {\n logger.warn(\n `memory-hybrid: WAL persistently disabled via ${getWalDisabledSentinelPath(walPath)} (remove sentinel to retry after fixing durability errors)`,\n );\n walPersistentDisableWarned = true;\n }\n return id;\n }\n try {\n const entry: WALEntry = {\n id,\n timestamp: Date.now(),\n schemaVersion: WAL_ENTRY_SCHEMA_VERSION,\n operation,\n data: normalizeWalPayload(data),\n };\n if (operation === \"update\" && supersedeTargetId) {\n entry.targetId = supersedeTargetId;\n }\n await wal.write(entry);\n walFailureCount = 0; // Reset on success\n walPersistentDisableWarned = false;\n } catch (err) {\n walFailureCount++;\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"wal\",\n operation: \"wal-write\",\n });\n logger.warn(`memory-hybrid: WAL write failed: ${err}`);\n if (walFailureCount >= WAL_FAILURE_THRESHOLD) {\n walDisabled = true;\n logger.warn(`memory-hybrid: WAL disabled after ${WAL_FAILURE_THRESHOLD} consecutive failures`);\n if (walPath) {\n try {\n const sentinelPath = persistWalDisabledSentinel(walPath, err);\n logger.warn(`memory-hybrid: WAL persistent disable sentinel written: ${sentinelPath}`);\n } catch (persistErr) {\n logger.warn(`memory-hybrid: failed to persist WAL disable sentinel: ${persistErr}`);\n }\n }\n }\n }\n return id;\n}\n\nexport async function walRemove(\n wal: WriteAheadLog | null,\n id: string,\n logger: { warn: (msg: string) => void },\n): Promise<void> {\n if (wal) {\n try {\n await wal.remove(id);\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"wal\",\n operation: \"wal-remove\",\n });\n logger.warn(`memory-hybrid: WAL cleanup failed: ${err}`);\n }\n }\n}\n\n/**\n * Reset the WAL circuit breaker state to its initial values.\n * Intended for use in tests only — do not call in production code.\n */\nexport function _resetWalCircuitBreakerForTesting(): void {\n resetWalCircuitBreakerState();\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"wal-helpers.js","names":[],"sources":["../../services/wal-helpers.ts"],"sourcesContent":["/**\n * WAL helpers — wrap the write-before-commit / remove-after-commit pattern.\n * Each call site was 8–12 lines of identical boilerplate; these reduce it to 1–2 lines.\n *\n * Circuit breaker: After 10 consecutive failures, WAL is disabled to prevent degradation.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport { existsSync, mkdirSync, rmSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { type WALEntry, WAL_ENTRY_SCHEMA_VERSION, type WriteAheadLog } from \"../backends/wal.js\";\nimport { capturePluginError } from \"./error-reporter.js\";\n\nconst WAL_FAILURE_THRESHOLD = 10;\nconst WAL_DISABLED_SENTINEL = \".wal.disabled\";\nlet walFailureCount = 0;\nlet walDisabled = false;\nlet walPersistentDisableWarned = false;\n\nexport type WalCircuitBreakerState = {\n failureCount: number;\n inMemoryDisabled: boolean;\n persistentDisabled: boolean;\n walPath: string | null;\n sentinelPath: string | null;\n};\n\n/** JSON.stringify drops Float32Array as `{}`; normalize before WAL persistence (#896). */\nfunction normalizeWalPayload(data: Record<string, unknown>): WALEntry[\"data\"] {\n const d = { ...data } as Record<string, unknown>;\n const v = d.vector;\n if (v instanceof Float32Array) {\n d.vector = Array.from(v);\n }\n return d as WALEntry[\"data\"];\n}\n\nexport function getWalDisabledSentinelPath(walPath: string): string {\n return join(dirname(walPath), WAL_DISABLED_SENTINEL);\n}\n\nfunction resolveWalPath(wal: WriteAheadLog | null): string | null {\n if (!wal) return null;\n const maybeGetPath = (wal as { getPath?: () => string }).getPath;\n if (typeof maybeGetPath !== \"function\") return null;\n try {\n const walPath = maybeGetPath.call(wal);\n if (typeof walPath !== \"string\") return null;\n const trimmed = walPath.trim();\n return trimmed.length > 0 ? trimmed : null;\n } catch {\n return null;\n }\n}\n\nexport function isWalPersistentlyDisabledAtPath(walPath: string): boolean {\n try {\n return existsSync(getWalDisabledSentinelPath(walPath));\n } catch {\n return false;\n }\n}\n\nfunction resetWalCircuitBreakerState(): void {\n walFailureCount = 0;\n walDisabled = false;\n walPersistentDisableWarned = false;\n}\n\nfunction persistWalDisabledSentinel(walPath: string, err: unknown): string {\n const sentinelPath = getWalDisabledSentinelPath(walPath);\n mkdirSync(dirname(sentinelPath), { recursive: true });\n const payload = {\n reason: \"wal-circuit-breaker-threshold\",\n threshold: WAL_FAILURE_THRESHOLD,\n failureCount: walFailureCount,\n trippedAt: new Date().toISOString(),\n error: err instanceof Error ? err.message : String(err),\n };\n writeFileSync(sentinelPath, `${JSON.stringify(payload, null, 2)}\\n`, \"utf-8\");\n return sentinelPath;\n}\n\nexport function getWalCircuitBreakerState(wal: WriteAheadLog | null): WalCircuitBreakerState {\n const walPath = resolveWalPath(wal);\n const sentinelPath = walPath ? getWalDisabledSentinelPath(walPath) : null;\n return {\n failureCount: walFailureCount,\n inMemoryDisabled: walDisabled,\n persistentDisabled: walPath ? isWalPersistentlyDisabledAtPath(walPath) : false,\n walPath,\n sentinelPath,\n };\n}\n\nexport async function walWrite(\n wal: WriteAheadLog | null,\n operation: \"store\" | \"update\",\n data: Record<string, unknown>,\n logger: { warn: (msg: string) => void },\n supersedeTargetId?: string,\n): Promise<string> {\n const id = randomUUID();\n if (!wal) return id;\n if (walDisabled) return id;\n const walPath = resolveWalPath(wal);\n if (walPath && isWalPersistentlyDisabledAtPath(walPath)) {\n walDisabled = true;\n if (!walPersistentDisableWarned) {\n logger.warn(\n `memory-hybrid: WAL persistently disabled via ${getWalDisabledSentinelPath(walPath)} (remove sentinel to retry after fixing durability errors)`,\n );\n walPersistentDisableWarned = true;\n }\n return id;\n }\n try {\n const entry: WALEntry = {\n id,\n timestamp: Date.now(),\n schemaVersion: WAL_ENTRY_SCHEMA_VERSION,\n operation,\n data: normalizeWalPayload(data),\n };\n if (operation === \"update\" && supersedeTargetId) {\n entry.targetId = supersedeTargetId;\n }\n await wal.write(entry);\n walFailureCount = 0; // Reset on success\n walPersistentDisableWarned = false;\n } catch (err) {\n walFailureCount++;\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"wal\",\n operation: \"wal-write\",\n });\n logger.warn(`memory-hybrid: WAL write failed: ${err}`);\n if (walFailureCount >= WAL_FAILURE_THRESHOLD) {\n walDisabled = true;\n logger.warn(`memory-hybrid: WAL disabled after ${WAL_FAILURE_THRESHOLD} consecutive failures`);\n if (walPath) {\n try {\n const sentinelPath = persistWalDisabledSentinel(walPath, err);\n logger.warn(`memory-hybrid: WAL persistent disable sentinel written: ${sentinelPath}`);\n } catch (persistErr) {\n logger.warn(`memory-hybrid: failed to persist WAL disable sentinel: ${persistErr}`);\n }\n }\n }\n }\n return id;\n}\n\nexport async function walRemove(\n wal: WriteAheadLog | null,\n id: string,\n logger: { warn: (msg: string) => void },\n): Promise<void> {\n if (wal) {\n try {\n await wal.remove(id);\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"wal\",\n operation: \"wal-remove\",\n });\n logger.warn(`memory-hybrid: WAL cleanup failed: ${err}`);\n }\n }\n}\n\n/**\n * Reset the WAL circuit breaker state to its initial values.\n * Intended for use in tests only — do not call in production code.\n */\nexport function _resetWalCircuitBreakerForTesting(): void {\n resetWalCircuitBreakerState();\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-tracker.js","names":[],"sources":["../../services/workflow-tracker.ts"],"sourcesContent":["/**\n * Workflow Tracker — session-level tool-sequence buffer and flush logic (Issue #209).\n *\n * Usage:\n * 1. Create: `const tracker = new WorkflowTracker(store, config)`\n * 2. Buffer: `tracker.push(toolName)` after each tool call\n * 3. Persist: `tracker.flush(goal, outcome, sessionId)` at session end\n * 4. Discard: `tracker.discard()` to clear without persisting\n * 5. Inspect: `tracker.getBuffer()` to see buffered tool names\n *\n * Privacy: only tool *names* are stored; argument values are never persisted.\n * Rate limiting: enforced per UTC calendar day, scoped to the instance.\n */\n\nimport type { WorkflowStore } from \"../backends/workflow-store.js\";\nimport { extractGoalKeywords } from \"../backends/workflow-store.js\";\nimport type { WorkflowTrackingConfig } from \"../config/types/features.js\";\nimport { capturePluginError } from \"./error-reporter.js\";\n\ninterface SessionBuffer {\n sessionId: string;\n toolCalls: string[];\n startedAt: number;\n}\n\n// ---------------------------------------------------------------------------\n// WorkflowTracker\n// ---------------------------------------------------------------------------\n\nexport class WorkflowTracker {\n private sessions = new Map<string, SessionBuffer>();\n\n // Instance-level rate-limit state (not module-global)\n private rateLimitDay: string;\n private rateLimitCount = 0;\n\n constructor(\n private readonly store: WorkflowStore,\n private readonly cfg: WorkflowTrackingConfig,\n private readonly clock: () => Date = () => new Date(),\n ) {\n this.rateLimitDay = this.clock().toISOString().slice(0, 10);\n }\n\n private checkAndIncrementRateLimit(): boolean {\n const today = this.clock().toISOString().slice(0, 10);\n if (today !== this.rateLimitDay) {\n this.rateLimitDay = today;\n this.rateLimitCount = 0;\n }\n if (this.rateLimitCount >= this.cfg.maxTracesPerDay) return false;\n this.rateLimitCount++;\n return true;\n }\n\n /**\n * Push a tool name onto the given session's buffer.\n * No-op when tracking is disabled.\n * @param sessionId - The session identifier\n * @param toolName - The tool name to record\n * @param startTime - Optional start time in milliseconds; if provided on first push, used as startedAt\n */\n push(sessionId: string, toolName: string, startTime?: number): void {\n if (!this.cfg.enabled) return;\n let buf = this.sessions.get(sessionId);\n if (!buf) {\n buf = { sessionId, toolCalls: [], startedAt: startTime ?? this.clock().getTime() };\n this.sessions.set(sessionId, buf);\n }\n buf.toolCalls.push(toolName);\n }\n\n /**\n * Flush the session buffer to persistent storage.\n * Returns the recorded trace id or null if nothing was recorded.\n */\n flush(sessionId: string, goal: string, outcome: \"success\" | \"failure\" | \"unknown\" = \"unknown\"): string | null {\n if (!this.cfg.enabled) return null;\n const buf = this.sessions.get(sessionId);\n if (!buf || buf.toolCalls.length === 0) {\n this.sessions.delete(sessionId);\n return null;\n }\n\n // Rate limit\n if (!this.checkAndIncrementRateLimit()) {\n this.sessions.delete(sessionId);\n return null;\n }\n\n const durationMs = this.clock().getTime() - buf.startedAt;\n const goalKeywords = extractGoalKeywords(goal);\n\n try {\n const trace = this.store.record({\n goal,\n goalKeywords,\n toolSequence: buf.toolCalls,\n outcome,\n durationMs,\n sessionId,\n });\n this.sessions.delete(sessionId);\n return trace.id;\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"workflow-flush\",\n subsystem: \"workflow-tracker\",\n });\n this.sessions.delete(sessionId);\n return null;\n }\n }\n\n /**\n * Discard (without saving) the session buffer.\n */\n discard(sessionId: string): void {\n this.sessions.delete(sessionId);\n }\n\n /**\n * Snapshot of the current tool sequence for a session (for tests / inspection).\n */\n getBuffer(sessionId: string): string[] {\n return this.sessions.get(sessionId)?.toolCalls ?? [];\n }\n\n /**\n * Run auto-prune based on retentionDays config. Call this during nightly cycle.\n */\n prune(): number {\n if (!this.cfg.enabled || this.cfg.retentionDays <= 0) return 0;\n try {\n return this.store.prune(this.cfg.retentionDays);\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"workflow-prune\",\n subsystem: \"workflow-tracker\",\n });\n return 0;\n }\n }\n}\n"],"mappings":";;;AA6BA,IAAa,kBAAb,MAA6B;CAQR;CACA;CACA;CATnB,2BAAmB,IAAI,KAA4B;CAGnD;CACA,iBAAyB;CAEzB,YACE,OACA,KACA,8BAA2C,IAAI,MAAM,EACrD;EAHiB,KAAA,QAAA;EACA,KAAA,MAAA;EACA,KAAA,QAAA;EAEjB,KAAK,eAAe,KAAK,OAAO,CAAC,aAAa,CAAC,MAAM,GAAG,GAAG;;CAG7D,6BAA8C;EAC5C,MAAM,QAAQ,KAAK,OAAO,CAAC,aAAa,CAAC,MAAM,GAAG,GAAG;EACrD,IAAI,UAAU,KAAK,cAAc;GAC/B,KAAK,eAAe;GACpB,KAAK,iBAAiB;;EAExB,IAAI,KAAK,kBAAkB,KAAK,IAAI,iBAAiB,OAAO;EAC5D,KAAK;EACL,OAAO;;;;;;;;;CAUT,KAAK,WAAmB,UAAkB,WAA0B;EAClE,IAAI,CAAC,KAAK,IAAI,SAAS;EACvB,IAAI,MAAM,KAAK,SAAS,IAAI,UAAU;EACtC,IAAI,CAAC,KAAK;GACR,MAAM;IAAE;IAAW,WAAW,EAAE;IAAE,WAAW,aAAa,KAAK,OAAO,CAAC,SAAS;IAAE;GAClF,KAAK,SAAS,IAAI,WAAW,IAAI;;EAEnC,IAAI,UAAU,KAAK,SAAS;;;;;;CAO9B,MAAM,WAAmB,MAAc,UAA6C,WAA0B;EAC5G,IAAI,CAAC,KAAK,IAAI,SAAS,OAAO;EAC9B,MAAM,MAAM,KAAK,SAAS,IAAI,UAAU;EACxC,IAAI,CAAC,OAAO,IAAI,UAAU,WAAW,GAAG;GACtC,KAAK,SAAS,OAAO,UAAU;GAC/B,OAAO;;EAIT,IAAI,CAAC,KAAK,4BAA4B,EAAE;GACtC,KAAK,SAAS,OAAO,UAAU;GAC/B,OAAO;;EAGT,MAAM,aAAa,KAAK,OAAO,CAAC,SAAS,GAAG,IAAI;EAChD,MAAM,eAAe,oBAAoB,KAAK;EAE9C,IAAI;GACF,MAAM,QAAQ,KAAK,MAAM,OAAO;IAC9B;IACA;IACA,cAAc,IAAI;IAClB;IACA;IACA;IACD,CAAC;GACF,KAAK,SAAS,OAAO,UAAU;GAC/B,OAAO,MAAM;WACN,KAAK;GACZ,mBAAmB,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,IAAI,CAAC,EAAE;IACtE,WAAW;IACX,WAAW;IACZ,CAAC;GACF,KAAK,SAAS,OAAO,UAAU;GAC/B,OAAO;;;;;;CAOX,QAAQ,WAAyB;EAC/B,KAAK,SAAS,OAAO,UAAU;;;;;CAMjC,UAAU,WAA6B;EACrC,OAAO,KAAK,SAAS,IAAI,UAAU,EAAE,aAAa,EAAE;;;;;CAMtD,QAAgB;EACd,IAAI,CAAC,KAAK,IAAI,WAAW,KAAK,IAAI,iBAAiB,GAAG,OAAO;EAC7D,IAAI;GACF,OAAO,KAAK,MAAM,MAAM,KAAK,IAAI,cAAc;WACxC,KAAK;GACZ,mBAAmB,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,IAAI,CAAC,EAAE;IACtE,WAAW;IACX,WAAW;IACZ,CAAC;GACF,OAAO"}
1
+ {"version":3,"file":"workflow-tracker.js","names":[],"sources":["../../services/workflow-tracker.ts"],"sourcesContent":["/**\n * Workflow Tracker — session-level tool-sequence buffer and flush logic (Issue #209).\n *\n * Usage:\n * 1. Create: `const tracker = new WorkflowTracker(store, config)`\n * 2. Buffer: `tracker.push(toolName)` after each tool call\n * 3. Persist: `tracker.flush(goal, outcome, sessionId)` at session end\n * 4. Discard: `tracker.discard()` to clear without persisting\n * 5. Inspect: `tracker.getBuffer()` to see buffered tool names\n *\n * Privacy: only tool *names* are stored; argument values are never persisted.\n * Rate limiting: enforced per UTC calendar day, scoped to the instance.\n */\n\nimport type { WorkflowStore } from \"../backends/workflow-store.js\";\nimport { extractGoalKeywords } from \"../backends/workflow-store.js\";\nimport type { WorkflowTrackingConfig } from \"../config/types/features.js\";\nimport { capturePluginError } from \"./error-reporter.js\";\n\ninterface SessionBuffer {\n sessionId: string;\n toolCalls: string[];\n startedAt: number;\n}\n\n// ---------------------------------------------------------------------------\n// WorkflowTracker\n// ---------------------------------------------------------------------------\n\nexport class WorkflowTracker {\n private sessions = new Map<string, SessionBuffer>();\n\n // Instance-level rate-limit state (not module-global)\n private rateLimitDay: string;\n private rateLimitCount = 0;\n\n constructor(\n private readonly store: WorkflowStore,\n private readonly cfg: WorkflowTrackingConfig,\n private readonly clock: () => Date = () => new Date(),\n ) {\n this.rateLimitDay = this.clock().toISOString().slice(0, 10);\n }\n\n private checkAndIncrementRateLimit(): boolean {\n const today = this.clock().toISOString().slice(0, 10);\n if (today !== this.rateLimitDay) {\n this.rateLimitDay = today;\n this.rateLimitCount = 0;\n }\n if (this.rateLimitCount >= this.cfg.maxTracesPerDay) return false;\n this.rateLimitCount++;\n return true;\n }\n\n /**\n * Push a tool name onto the given session's buffer.\n * No-op when tracking is disabled.\n * @param sessionId - The session identifier\n * @param toolName - The tool name to record\n * @param startTime - Optional start time in milliseconds; if provided on first push, used as startedAt\n */\n push(sessionId: string, toolName: string, startTime?: number): void {\n if (!this.cfg.enabled) return;\n let buf = this.sessions.get(sessionId);\n if (!buf) {\n buf = { sessionId, toolCalls: [], startedAt: startTime ?? this.clock().getTime() };\n this.sessions.set(sessionId, buf);\n }\n buf.toolCalls.push(toolName);\n }\n\n /**\n * Flush the session buffer to persistent storage.\n * Returns the recorded trace id or null if nothing was recorded.\n */\n flush(sessionId: string, goal: string, outcome: \"success\" | \"failure\" | \"unknown\" = \"unknown\"): string | null {\n if (!this.cfg.enabled) return null;\n const buf = this.sessions.get(sessionId);\n if (!buf || buf.toolCalls.length === 0) {\n this.sessions.delete(sessionId);\n return null;\n }\n\n // Rate limit\n if (!this.checkAndIncrementRateLimit()) {\n this.sessions.delete(sessionId);\n return null;\n }\n\n const durationMs = this.clock().getTime() - buf.startedAt;\n const goalKeywords = extractGoalKeywords(goal);\n\n try {\n const trace = this.store.record({\n goal,\n goalKeywords,\n toolSequence: buf.toolCalls,\n outcome,\n durationMs,\n sessionId,\n });\n this.sessions.delete(sessionId);\n return trace.id;\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"workflow-flush\",\n subsystem: \"workflow-tracker\",\n });\n this.sessions.delete(sessionId);\n return null;\n }\n }\n\n /**\n * Discard (without saving) the session buffer.\n */\n discard(sessionId: string): void {\n this.sessions.delete(sessionId);\n }\n\n /**\n * Snapshot of the current tool sequence for a session (for tests / inspection).\n */\n getBuffer(sessionId: string): string[] {\n return this.sessions.get(sessionId)?.toolCalls ?? [];\n }\n\n /**\n * Run auto-prune based on retentionDays config. Call this during nightly cycle.\n */\n prune(): number {\n if (!this.cfg.enabled || this.cfg.retentionDays <= 0) return 0;\n try {\n return this.store.prune(this.cfg.retentionDays);\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"workflow-prune\",\n subsystem: \"workflow-tracker\",\n });\n return 0;\n }\n }\n}\n"],"mappings":";;;AA6BA,IAAa,kBAAb,MAA6B;CAQR;CACA;CACA;CATnB,2BAAmB,IAAI,IAA2B;CAGlD;CACA,iBAAyB;CAEzB,YACE,OACA,KACA,8BAA2C,IAAI,KAAK,GACpD;EAHiB,KAAA,QAAA;EACA,KAAA,MAAA;EACA,KAAA,QAAA;EAEjB,KAAK,eAAe,KAAK,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE;CAC5D;CAEA,6BAA8C;EAC5C,MAAM,QAAQ,KAAK,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE;EACpD,IAAI,UAAU,KAAK,cAAc;GAC/B,KAAK,eAAe;GACpB,KAAK,iBAAiB;EACxB;EACA,IAAI,KAAK,kBAAkB,KAAK,IAAI,iBAAiB,OAAO;EAC5D,KAAK;EACL,OAAO;CACT;;;;;;;;CASA,KAAK,WAAmB,UAAkB,WAA0B;EAClE,IAAI,CAAC,KAAK,IAAI,SAAS;EACvB,IAAI,MAAM,KAAK,SAAS,IAAI,SAAS;EACrC,IAAI,CAAC,KAAK;GACR,MAAM;IAAE;IAAW,WAAW,CAAC;IAAG,WAAW,aAAa,KAAK,MAAM,EAAE,QAAQ;GAAE;GACjF,KAAK,SAAS,IAAI,WAAW,GAAG;EAClC;EACA,IAAI,UAAU,KAAK,QAAQ;CAC7B;;;;;CAMA,MAAM,WAAmB,MAAc,UAA6C,WAA0B;EAC5G,IAAI,CAAC,KAAK,IAAI,SAAS,OAAO;EAC9B,MAAM,MAAM,KAAK,SAAS,IAAI,SAAS;EACvC,IAAI,CAAC,OAAO,IAAI,UAAU,WAAW,GAAG;GACtC,KAAK,SAAS,OAAO,SAAS;GAC9B,OAAO;EACT;EAGA,IAAI,CAAC,KAAK,2BAA2B,GAAG;GACtC,KAAK,SAAS,OAAO,SAAS;GAC9B,OAAO;EACT;EAEA,MAAM,aAAa,KAAK,MAAM,EAAE,QAAQ,IAAI,IAAI;EAChD,MAAM,eAAe,oBAAoB,IAAI;EAE7C,IAAI;GACF,MAAM,QAAQ,KAAK,MAAM,OAAO;IAC9B;IACA;IACA,cAAc,IAAI;IAClB;IACA;IACA;GACF,CAAC;GACD,KAAK,SAAS,OAAO,SAAS;GAC9B,OAAO,MAAM;EACf,SAAS,KAAK;GACZ,mBAAmB,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC,GAAG;IACtE,WAAW;IACX,WAAW;GACb,CAAC;GACD,KAAK,SAAS,OAAO,SAAS;GAC9B,OAAO;EACT;CACF;;;;CAKA,QAAQ,WAAyB;EAC/B,KAAK,SAAS,OAAO,SAAS;CAChC;;;;CAKA,UAAU,WAA6B;EACrC,OAAO,KAAK,SAAS,IAAI,SAAS,GAAG,aAAa,CAAC;CACrD;;;;CAKA,QAAgB;EACd,IAAI,CAAC,KAAK,IAAI,WAAW,KAAK,IAAI,iBAAiB,GAAG,OAAO;EAC7D,IAAI;GACF,OAAO,KAAK,MAAM,MAAM,KAAK,IAAI,aAAa;EAChD,SAAS,KAAK;GACZ,mBAAmB,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC,GAAG;IACtE,WAAW;IACX,WAAW;GACb,CAAC;GACD,OAAO;EACT;CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap-databases.js","names":[],"sources":["../../setup/bootstrap-databases.ts"],"sourcesContent":["import { constants, existsSync, readFileSync } from \"node:fs\";\nimport { open, unlink } from \"node:fs/promises\";\n/** @module bootstrap-databases — Database bootstrap, optional stores, and lifecycle teardown. */\nimport { dirname, join } from \"node:path\";\nimport type OpenAI from \"openai\";\nimport type { ClawdbotPluginApi } from \"openclaw/plugin-sdk/core\";\nimport type { ApitapStore } from \"../backends/apitap-store.js\";\nimport { CostTracker } from \"../backends/cost-tracker.js\";\nimport type { CredentialsDB } from \"../backends/credentials-db.js\";\nimport type { CrystallizationStore } from \"../backends/crystallization-store.js\";\nimport type { EdictStore } from \"../backends/edict-store.js\";\nimport type { EventLog } from \"../backends/event-log.js\";\nimport type { FactsDB } from \"../backends/facts-db.js\";\nimport type { IssueStore } from \"../backends/issue-store.js\";\nimport { NarrativesDB } from \"../backends/narratives-db.js\";\nimport type { ProposalsDB } from \"../backends/proposals-db.js\";\nimport type { ToolProposalStore } from \"../backends/tool-proposal-store.js\";\nimport type { VectorDB } from \"../backends/vector-db.js\";\nimport type { WriteAheadLog } from \"../backends/wal.js\";\nimport type { WorkflowStore } from \"../backends/workflow-store.js\";\nimport type { CredentialType, HybridMemoryConfig } from \"../config.js\";\nimport { normalizeResolvedSecretValue } from \"../config/parsers/core.js\";\nimport { is403QuotaOrRateLimitLike, is429OrWrapped } from \"../services/chat.js\";\nimport { CREDENTIAL_REDACTION_MIGRATION_FLAG, migrateCredentialsToVault } from \"../services/credential-migration.js\";\nimport { runEmbeddingMaintenance } from \"../services/embedding-migration.js\";\nimport type { EmbeddingRegistry } from \"../services/embedding-registry.js\";\nimport type { EmbeddingProvider } from \"../services/embeddings.js\";\nimport { formatOpenAiEmbeddingDisplayLabel, shouldSuppressEmbeddingError } from \"../services/embeddings/shared.js\";\nimport { capturePluginError } from \"../services/error-reporter.js\";\nimport { installCoreBootstrapServices, installOptionalBootstrapServices } from \"../services/index.js\";\nimport type { ProvenanceService } from \"../services/provenance.js\";\nimport type { AliasDB } from \"../services/retrieval-aliases.js\";\nimport { recordStartupMemoryCheckpoint } from \"../services/startup-memory-attribution.js\";\nimport { invalidateClusterCache } from \"../services/retrieval-orchestrator.js\";\nimport type { VerificationStore } from \"../services/verification-store.js\";\nimport { hasOAuthProfiles } from \"../utils/auth.js\";\nimport { getEnv } from \"../utils/env-manager.js\";\nimport { setKeywordsPath } from \"../utils/language-keywords.js\";\nimport { spawn } from \"../utils/process-runner.js\";\nimport { isDbClosedError, isRegistrationSuperseded } from \"../utils/registration-superseded.js\";\nimport { isHeavyModel, isLightModel, isNanoModel } from \"../utils/model-tier.js\";\nimport {\n OLLAMA_DEFAULT_BASE_URL,\n ROUTABLE_BUILTIN_PROVIDERS,\n buildMultiProviderOpenAI,\n clearOllamaHealthCacheEntry,\n extractGatewayConfig,\n gatewayLogInfoOnce,\n getGatewayModelsProviders,\n mergeGatewayProviderCredentialsIntoLlmProvidersMap,\n patchEmbeddingEndpointFromGatewayProviders,\n probeOllamaEndpoint,\n} from \"./provider-router.js\";\ninterface HealthStatus {\n embeddingsOk: boolean;\n credentialsVaultOk: boolean;\n lastCheckTime: number;\n}\n\ninterface DatabaseContext {\n factsDb: FactsDB;\n edictStore: EdictStore;\n vectorDb: VectorDB;\n embeddings: EmbeddingProvider;\n embeddingRegistry: EmbeddingRegistry;\n openai: OpenAI;\n credentialsDb: CredentialsDB | null;\n wal: WriteAheadLog | null;\n proposalsDb: ProposalsDB | null;\n identityReflectionStore: import(\"../backends/identity-reflection-store.js\").IdentityReflectionStore | null;\n personaStateStore: import(\"../backends/persona-state-store.js\").PersonaStateStore | null;\n eventLog: EventLog | null;\n narrativesDb: NarrativesDB;\n aliasDb: AliasDB | null;\n issueStore: IssueStore;\n workflowStore: WorkflowStore;\n crystallizationStore: CrystallizationStore;\n toolProposalStore: ToolProposalStore;\n verificationStore: VerificationStore | null;\n provenanceService: ProvenanceService | null;\n costTracker: CostTracker | null;\n resolvedLancePath: string;\n resolvedSqlitePath: string;\n health: HealthStatus;\n initialized: Promise<void>;\n apitapStore: ApitapStore;\n}\n\n// Module-level guard: tracks an in-progress Ollama auto-start promise so concurrent calls to\n// initializeDatabases (e.g. rapid plugin reload on SIGUSR1) cannot spawn multiple `ollama serve`\n// processes at the same time. Cleared in the `finally` block so a future startup can retry.\nlet _ollamaAutoStartPromise: Promise<void> | null = null;\n\n/** @internal Reset the Ollama auto-start deduplication guard between tests. */\nexport function _resetOllamaAutoStartForTesting(): void {\n _ollamaAutoStartPromise = null;\n}\n\n/**\n * Attempt to start the Ollama server in the background when `localAutoStart` is enabled and at\n * least one `ollama/*` model is configured. Concurrent calls while a spawn attempt is already\n * in progress are silently skipped — only one `ollama serve` process is ever launched at a time.\n * The guard is automatically cleared after the attempt completes (success or failure) so a later\n * non-overlapping call can retry.\n *\n * Errors are captured via `capturePluginError` and logged as warnings so they never crash the\n * plugin startup path.\n *\n * @internal Exported for focused unit testing only.\n */\nexport function startOllamaIfNeeded(cfg: HybridMemoryConfig, api: ClawdbotPluginApi): void {\n if (!cfg.llm?.localAutoStart) return;\n const allModels = [...(cfg.llm.nano ?? []), ...(cfg.llm.default ?? []), ...(cfg.llm.heavy ?? [])];\n const hasOllamaModels = allModels.some((m) => m.split(\"/\")[0]?.toLowerCase() === \"ollama\");\n if (!hasOllamaModels) return;\n\n // Already in-progress — skip to prevent a second concurrent spawn.\n if (_ollamaAutoStartPromise) return;\n\n _ollamaAutoStartPromise = (async () => {\n try {\n const ollamaBase =\n (cfg.llm?.providers as Record<string, { baseURL?: string } | undefined> | undefined)?.ollama?.baseURL?.replace(\n /\\/v1\\/?$/,\n \"\",\n ) ?? OLLAMA_DEFAULT_BASE_URL;\n const running = await probeOllamaEndpoint(ollamaBase);\n if (!running) {\n api.logger.info(\"memory-hybrid: Ollama is not running — attempting auto-start (llm.localAutoStart: true)\");\n const child = spawn(\"ollama\", [\"serve\"], {\n detached: true,\n stdio: \"ignore\",\n });\n child.on(\"error\", (err) => {\n api.logger.warn(`memory-hybrid: Ollama spawn error: ${err.message}`);\n });\n child.unref();\n // Allow Ollama ~2 s to bind its port before re-probing\n await new Promise<void>((r) => setTimeout(r, 2000));\n // Invalidate any cached \"down\" entry so the next probe goes to the network\n clearOllamaHealthCacheEntry(ollamaBase);\n const nowRunning = await probeOllamaEndpoint(ollamaBase);\n if (nowRunning) {\n api.logger.info(\"memory-hybrid: Ollama started successfully\");\n } else {\n api.logger.warn(\n \"memory-hybrid: Ollama auto-start attempted but server still not available — local model calls will fall back to cloud\",\n );\n }\n }\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"ollama-auto-start\",\n subsystem: \"llm\",\n });\n api.logger.warn(`memory-hybrid: Ollama auto-start failed: ${err}`);\n } finally {\n _ollamaAutoStartPromise = null;\n }\n })();\n}\n\n/**\n * Ollama auto-start: if any tier includes ollama/* models and localAutoStart is enabled,\n * attempt to launch `ollama serve` in the background when the server is not already running.\n * Delegates to `startOllamaIfNeeded`; retained for backwards-compatibility with external callers.\n */\nexport function maybeAutoStartOllama(cfg: HybridMemoryConfig, api: ClawdbotPluginApi): void {\n startOllamaIfNeeded(cfg, api);\n}\n\n/**\n * Run bootstrap checks (WAL init, embedding verify, vault check, credential migration)\n * for a new registration generation when reusing database handles.\n * @internal Exported for reregister-policy; not part of public API.\n */\nexport function createReusedDatabaseBootstrap(\n cfg: HybridMemoryConfig,\n api: ClawdbotPluginApi,\n ctx: Pick<\n DatabaseContext,\n \"embeddings\" | \"wal\" | \"credentialsDb\" | \"factsDb\" | \"vectorDb\" | \"aliasDb\" | \"resolvedSqlitePath\" | \"health\"\n >,\n opts: { bootRegistrationGeneration: number },\n): Promise<void> {\n const { embeddings, wal, credentialsDb, factsDb, vectorDb, aliasDb, resolvedSqlitePath, health } = ctx;\n const bootRegistrationGeneration = opts.bootRegistrationGeneration;\n const isBootstrapSuperseded = (): boolean => isRegistrationSuperseded(bootRegistrationGeneration);\n\n return (async () => {\n if (isBootstrapSuperseded()) return;\n if (wal) {\n try {\n await wal.init();\n } catch (e) {\n if (isBootstrapSuperseded()) {\n api.logger.debug?.(\"memory-hybrid: WAL initialization skipped (registration superseded)\");\n return;\n }\n capturePluginError(e instanceof Error ? e : new Error(String(e)), {\n subsystem: \"wal\",\n operation: \"init\",\n phase: \"initialization\",\n });\n api.logger.warn(`memory-hybrid: WAL initialization failed: ${e}`);\n }\n }\n if (isBootstrapSuperseded()) return;\n try {\n await embeddings.embed(\"verify\");\n if (isBootstrapSuperseded()) return;\n health.embeddingsOk = true;\n const effectiveProvider = embeddings.activeProvider ?? cfg.embedding.provider;\n const modelForLog =\n effectiveProvider === \"openai\"\n ? formatOpenAiEmbeddingDisplayLabel(embeddings.modelName, cfg.embedding.endpoint)\n : embeddings.modelName;\n api.logger.info(\n effectiveProvider !== cfg.embedding.provider\n ? `memory-hybrid: embedding check OK (provider=${effectiveProvider}, model=${modelForLog} — using fallback; ${cfg.embedding.provider} unavailable)`\n : `memory-hybrid: embedding check OK (provider=${effectiveProvider}, model=${modelForLog})`,\n );\n } catch (e) {\n if (isBootstrapSuperseded()) {\n api.logger.debug?.(\"memory-hybrid: embedding check skipped (registration superseded)\");\n return;\n }\n const asErr = e instanceof Error ? e : new Error(String(e));\n if (!shouldSuppressEmbeddingError(asErr)) {\n capturePluginError(asErr, {\n subsystem: \"embeddings\",\n operation: \"init-verify\",\n phase: \"initialization\",\n backend: cfg.embedding.provider,\n });\n }\n const errText = String(e);\n const quota403 = is403QuotaOrRateLimitLike(e);\n const azure404 =\n typeof cfg.embedding.endpoint === \"string\" &&\n /\\.openai\\.azure\\.com/i.test(cfg.embedding.endpoint) &&\n (/404|not found/i.test(errText) || /Model not found/i.test(errText));\n const hint = quota403\n ? \"The provider returned 403 with quota/rate-limit signals (e.g. remaining-tokens=0, Retry-After). Wait for the window to reset or raise quota; your key may still be valid. Run 'openclaw hybrid-mem verify' for details.\"\n : cfg.embedding.provider === \"ollama\"\n ? `Ensure Ollama is running at ${cfg.embedding.endpoint ?? \"http://localhost:11434\"} and model '${cfg.embedding.model}' is pulled. Run 'openclaw hybrid-mem verify' for details.`\n : azure404\n ? 'Azure OpenAI embeddings use the deployment name as the API model id. In plugins.entries[\"openclaw-hybrid-memory\"].config.embedding set \"deployment\" to the exact embedding deployment name from Azure Portal (Resource → Model deployments), or rename the deployment to match embedding.model. Ensure embedding.endpoint is the resource URL (e.g. …/openai/v1). Run \\'openclaw hybrid-mem verify\\' for details.'\n : \"Set a valid embedding.apiKey in plugin config and ensure the model is accessible. Run 'openclaw hybrid-mem verify' for details.\";\n const logEmbFailure = quota403 || is429OrWrapped(asErr) ? api.logger.warn : api.logger.error;\n const embTag = quota403 || is429OrWrapped(asErr) ? \"[embedding-quota]\" : \"[embedding-init]\";\n logEmbFailure(\n `${embTag} memory-hybrid: ⚠️ EMBEDDING CHECK FAILED (provider=${cfg.embedding.provider}) — ${String(e)}. ` +\n `Plugin will continue but semantic search will not work. ${hint}`,\n );\n }\n if (cfg.credentials.enabled && credentialsDb) {\n if (isBootstrapSuperseded()) return;\n try {\n const verifyVault = (): void => {\n const items = credentialsDb.list();\n if (items.length > 0) {\n const first = items[0];\n credentialsDb.get(first.service, first.type as CredentialType);\n }\n };\n verifyVault();\n if (isBootstrapSuperseded()) return;\n health.credentialsVaultOk = true;\n api.logger.info(\"memory-hybrid: credentials vault check OK\");\n } catch (e) {\n if (isBootstrapSuperseded()) {\n api.logger.debug?.(\"memory-hybrid: credentials vault check skipped (registration superseded)\");\n return;\n }\n capturePluginError(e instanceof Error ? e : new Error(String(e)), {\n subsystem: \"credentials\",\n operation: \"vault-verify\",\n phase: \"initialization\",\n backend: \"sqlite\",\n });\n api.logger.error(\n `memory-hybrid: ⚠️ CREDENTIALS VAULT CHECK FAILED — ${String(e)}. Plugin will continue but credential storage will not work. Check OPENCLAW_CRED_KEY (or credentials.encryptionKey). Wrong key or corrupted DB. Run 'openclaw hybrid-mem verify' for details.`,\n );\n }\n if (isBootstrapSuperseded()) return;\n const migrationFlagPath = join(dirname(resolvedSqlitePath), CREDENTIAL_REDACTION_MIGRATION_FLAG);\n const clearMigrationFlagForRetry = async (reason: string): Promise<void> => {\n try {\n await unlink(migrationFlagPath);\n api.logger.debug?.(`memory-hybrid: cleared credential migration flag (${reason})`);\n } catch (err: unknown) {\n const errCode =\n typeof err === \"object\" && err !== null && \"code\" in err ? (err as { code?: unknown }).code : undefined;\n if (errCode === \"ENOENT\") return;\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"credentials\",\n operation: \"migration-flag-clear\",\n phase: \"initialization\",\n backend: \"sqlite\",\n });\n api.logger.warn(`memory-hybrid: failed to clear migration flag for retry: ${err}`);\n }\n };\n let shouldMigrate = false;\n try {\n const handle = await open(migrationFlagPath, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY);\n try {\n await handle.writeFile(\"1\", \"utf8\");\n shouldMigrate = true;\n } finally {\n await handle.close().catch(() => {});\n }\n } catch (err: unknown) {\n const errCode =\n typeof err === \"object\" && err !== null && \"code\" in err ? (err as { code?: unknown }).code : undefined;\n if (isBootstrapSuperseded()) return;\n if (errCode === \"EEXIST\") {\n shouldMigrate = false;\n } else {\n shouldMigrate = false;\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"credentials\",\n operation: \"migration-flag-create\",\n phase: \"initialization\",\n backend: \"sqlite\",\n });\n api.logger.warn(`memory-hybrid: failed to create migration flag (skipping migration): ${err}`);\n }\n }\n if (shouldMigrate) {\n if (isBootstrapSuperseded()) {\n await clearMigrationFlagForRetry(\"registration superseded before migration\");\n return;\n }\n try {\n const result = await migrateCredentialsToVault({\n factsDb,\n vectorDb,\n embeddings,\n credentialsDb,\n aliasDb,\n migrationFlagPath,\n markDone: false,\n });\n if (isBootstrapSuperseded()) {\n await clearMigrationFlagForRetry(\"registration superseded after migration\");\n api.logger.debug?.(\n \"memory-hybrid: credential migration finished after supersession; suppressing stale logs\",\n );\n return;\n }\n if (result.migrated > 0) {\n api.logger.info(`memory-hybrid: migrated ${result.migrated} credential(s) from memory into vault`);\n }\n if (result.errors.length > 0) {\n api.logger.warn(\n `memory-hybrid: credential migration had ${result.errors.length} error(s): ${result.errors.join(\"; \")}`,\n );\n await clearMigrationFlagForRetry(\"credential migration completed with errors\");\n }\n } catch (e) {\n if (isBootstrapSuperseded()) {\n await clearMigrationFlagForRetry(\"registration superseded during migration\");\n const isDbClosed = isDbClosedError(e);\n if (!isDbClosed) {\n api.logger.debug?.(\n \"memory-hybrid: credential migration error during superseded bootstrap cleared for retry\",\n );\n } else {\n api.logger.debug?.(\"memory-hybrid: credential migration skipped (registration superseded)\");\n }\n return;\n }\n capturePluginError(e instanceof Error ? e : new Error(String(e)), {\n subsystem: \"credentials\",\n operation: \"migration-to-vault\",\n phase: \"initialization\",\n backend: \"sqlite\",\n });\n api.logger.warn(`memory-hybrid: credential migration failed: ${e}`);\n }\n }\n }\n })().catch((err: unknown) => {\n if (isBootstrapSuperseded()) return;\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"init\",\n operation: \"async-initialization\",\n phase: \"initialization\",\n });\n api.logger.warn(`memory-hybrid: async initialization encountered an error: ${err}`);\n });\n}\n\n/**\n * Initializes all databases and services for the plugin.\n *\n * This includes:\n * - FactsDB (SQLite)\n * - VectorDB (LanceDB)\n * - Embeddings service\n * - OpenAI client\n * - CredentialsDB (optional)\n * - WriteAheadLog (optional)\n * - ProposalsDB (optional)\n * - Discovered categories loading\n * - Async verification checks\n */\nexport function initializeDatabases(\n cfg: HybridMemoryConfig,\n api: ClawdbotPluginApi,\n opts?: { bootRegistrationGeneration?: number },\n): DatabaseContext {\n const bootRegistrationGeneration = opts?.bootRegistrationGeneration ?? -1;\n const isBootstrapSuperseded = (): boolean => isRegistrationSuperseded(bootRegistrationGeneration);\n const resolvedLancePath = api.resolvePath(cfg.lanceDbPath);\n const resolvedSqlitePath = api.resolvePath(cfg.sqlitePath);\n setKeywordsPath(dirname(resolvedSqlitePath));\n\n recordStartupMemoryCheckpoint({\n logger: api.logger,\n subsystem: \"bootstrap\",\n operation: \"plugin-registration\",\n phase: \"startup.plugin-registration.begin\",\n onceKey: \"startup.plugin-registration.begin\",\n tags: {\n sqlitePath: resolvedSqlitePath,\n lancedbPath: resolvedLancePath,\n },\n });\n\n patchEmbeddingEndpointFromGatewayProviders(cfg, api);\n\n const { factsDb, edictStore, vectorDb, embeddings, embeddingRegistry } = installCoreBootstrapServices({\n cfg,\n api,\n resolvedSqlitePath,\n resolvedLancePath,\n });\n\n recordStartupMemoryCheckpoint({\n logger: api.logger,\n subsystem: \"bootstrap\",\n operation: \"plugin-registration\",\n phase: \"startup.plugin-registration.after-bootstrap\",\n onceKey: \"startup.plugin-registration.after-bootstrap\",\n tags: {\n sqlitePath: resolvedSqlitePath,\n lancedbPath: resolvedLancePath,\n lancedbInitialized: typeof vectorDb.isInitialized === \"function\" ? vectorDb.isInitialized() : undefined,\n lancedbOpenReaders: typeof vectorDb.getOpenReaderCount === \"function\" ? vectorDb.getOpenReaderCount() : undefined,\n },\n });\n\n // Merge gateway provider keys into plugin llm.providers BEFORE auto-derivation so canRoute\n // can see all available providers (issue #487 fix).\n // Check three paths: models.providers (standard), llm.providers (legacy), providers (top-level).\n const gwConfig = api.config as Record<string, unknown> | undefined;\n const gwProviders = getGatewayModelsProviders(gwConfig);\n const mergedProviderNames: string[] = [];\n const mergedProviderOriginalNames = new Map<string, string>();\n if (!cfg.llm)\n (cfg as Record<string, unknown>).llm = {\n providers: {},\n default: [],\n heavy: [],\n nano: [],\n };\n const plm = cfg.llm as Record<string, unknown>;\n if (!plm.providers || typeof plm.providers !== \"object\") plm.providers = {};\n const prov = plm.providers as Record<string, Record<string, unknown>>;\n\n mergeGatewayProviderCredentialsIntoLlmProvidersMap(\n prov,\n gwProviders,\n api,\n mergedProviderNames,\n mergedProviderOriginalNames,\n );\n\n // When llm.default/heavy are not explicitly configured, auto-derive from agents.defaults.model\n // (the same model list shown by `openclaw models list`). This makes the plugin zero-config for\n // model selection when the user has already set up their models in openclaw.json.\n // If the gateway list is heavy-only (e.g. only Opus), we prepend a cheap fallback so default/nano\n // tasks don't all use the expensive model (see cost issue: hundreds of tasks running as Opus).\n const RECOMMENDED_CHEAP_FALLBACK = [\n \"openai/gpt-4.1-nano\",\n \"google/gemini-2.5-flash-lite\",\n \"anthropic/claude-3-5-haiku\",\n ];\n if (\n (cfg.llm?.default ?? []).length === 0 &&\n (cfg.llm?.heavy ?? []).length === 0 &&\n (cfg.llm?.nano ?? []).length === 0\n ) {\n const agentModel = (api.config as Record<string, unknown>)?.agents as Record<string, unknown> | undefined;\n const agentDefaults = agentModel?.defaults as Record<string, unknown> | undefined;\n const modelCfg = agentDefaults?.model as Record<string, unknown> | undefined;\n const primary = typeof modelCfg?.primary === \"string\" ? modelCfg.primary : undefined;\n const fallbacks = Array.isArray(modelCfg?.fallbacks)\n ? (modelCfg.fallbacks as unknown[]).filter((m): m is string => typeof m === \"string\" && m.trim().length > 0)\n : [];\n // Models from agents.defaults.model with an unknown provider prefix (e.g. \"Local/S\", \"custom/X\")\n // would throw UnconfiguredProviderError when used, so filter them out here (issue #487).\n // Normalize provider keys to lowercase to match the lowercased prefix check at line 831 (issue #487 fix).\n const pluginProviders = Object.fromEntries(\n Object.entries((cfg.llm?.providers ?? {}) as Record<string, unknown>).map(([k, v]) => [k.toLowerCase(), v]),\n );\n // Extract gateway config for OAuth routing check (matches buildMultiProviderOpenAI logic)\n const { gatewayBaseUrl, gatewayToken } = extractGatewayConfig(cfg);\n // Normalize auth.order keys to lowercase so lookups match the lowercased prefix.\n const authOrder = cfg.auth?.order\n ? Object.fromEntries(Object.entries(cfg.auth.order).map(([k, v]) => [k.toLowerCase(), v]))\n : undefined;\n const canRoute = (m: string): boolean => {\n if (!m.includes(\"/\")) return true; // bare name — normalizeModelId() may rewrite to a prefixed form (e.g. gemini-*, claude-*, MiniMax-*)\n const prefix = m.trim().split(\"/\")[0].toLowerCase();\n // Check OAuth routing first (matches resolveClient logic at line 378)\n if (hasOAuthProfiles(authOrder?.[prefix], prefix) && gatewayBaseUrl && gatewayToken) return true;\n if (ROUTABLE_BUILTIN_PROVIDERS.has(prefix) || Object.hasOwn(pluginProviders, prefix)) return true;\n // Read-only env var check: safe even with user-supplied prefix since we only read env vars.\n // Mirrors resolveClient()'s <PREFIX>_API_KEY fallback (see resolveClient in setup/provider-router.ts).\n const envKey = process.env[`${prefix.toUpperCase()}_API_KEY`];\n return Boolean(envKey?.trim());\n };\n const gatewayModels = [primary, ...fallbacks]\n .filter((m): m is string => Boolean(m))\n .filter((m) => {\n if (canRoute(m)) return true;\n const prefix = m.trim().split(\"/\")[0];\n api.logger.warn?.(\n `memory-hybrid: skipping gateway model \"${m}\" from agents.defaults.model — ` +\n `provider \"${prefix}\" is not a known built-in and is not configured in llm.providers. ` +\n `To use this model configure llm.providers.${prefix.toLowerCase()} (apiKey and/or baseURL) in plugin config.`,\n );\n return false;\n });\n\n if (gatewayModels.length === 0 && [primary, ...fallbacks].some(Boolean)) {\n api.logger.warn?.(\n \"memory-hybrid: all models from agents.defaults.model were filtered out (unknown provider prefixes). \" +\n \"No LLM tiers auto-configured. Set llm.default explicitly or add provider entries to llm.providers.\",\n );\n }\n\n if (gatewayModels.length > 0) {\n // Deduplicate while preserving order\n const seen = new Set<string>();\n const uniqueModels = gatewayModels.filter((m) => {\n if (seen.has(m)) return false;\n seen.add(m);\n return true;\n });\n\n // Heuristic tier split based on model name keywords.\n // Nano: nano, mini, haiku, lite, turbo-mini — ultra-cheap for classify/HyDE/summarize\n // Heavy: pro, opus, o3, o1, large, ultra, gpt-5 — capable/expensive models (incl. GPT-5.4, Codex)\n // Light: flash, small — fast/cheap (but not nano-cheap)\n // Medium: everything else (sonnet, gpt-4o, etc.)\n // All ollama/* models are nano-tier (local = free, no API cost)\n const nano = uniqueModels.filter((m) => isNanoModel(m) && !isHeavyModel(m));\n const heavy = uniqueModels.filter((m) => isHeavyModel(m) && !isNanoModel(m));\n const light = uniqueModels.filter((m) => isLightModel(m) && !isNanoModel(m) && !isHeavyModel(m));\n const medium = uniqueModels.filter((m) => !isNanoModel(m) && !isLightModel(m) && !isHeavyModel(m));\n\n // default tier: agent order (primary then fallbacks) so reflection/general match what you set in openclaw.json\n const defaultIsHeavyOnly = uniqueModels.length > 0 && uniqueModels.every((m) => isHeavyModel(m));\n let defaultTier = [...uniqueModels];\n if (defaultIsHeavyOnly) {\n defaultTier = [...RECOMMENDED_CHEAP_FALLBACK, ...defaultTier];\n api.logger.info?.(\n \"memory-hybrid: agents.defaults.model is heavy-only; prepending cheap fallback for default tier so maintenance tasks use a cheaper model first. Set llm.default / llm.nano explicitly in plugin config to override.\",\n );\n }\n // heavy tier: capable first (heavy → medium → light) for distill/self-correction\n const heavyTier = [...heavy, ...medium, ...light];\n\n // nano: cheap first — never use Opus/heavy for classify/summarize. Use nano models if present; else when heavy-only use cheap fallback; else use light then medium from agent list.\n const nanoList =\n nano.length > 0\n ? [...nano, ...light, ...medium]\n : defaultIsHeavyOnly\n ? RECOMMENDED_CHEAP_FALLBACK\n : light.length > 0 || medium.length > 0\n ? [...light, ...medium]\n : [];\n\n cfg.llm = {\n ...(cfg.llm?.localAutoStart !== undefined ? { localAutoStart: cfg.llm.localAutoStart } : {}),\n ...(cfg.llm?.providers !== undefined ? { providers: cfg.llm.providers } : {}),\n ...(cfg.llm?.fallbackToDefault !== undefined ? { fallbackToDefault: cfg.llm.fallbackToDefault } : {}),\n ...(cfg.llm?.fallbackModel !== undefined ? { fallbackModel: cfg.llm.fallbackModel } : {}),\n default: defaultTier.length > 0 ? defaultTier : uniqueModels,\n heavy: heavyTier.length > 0 ? heavyTier : uniqueModels,\n ...(nanoList.length > 0 ? { nano: nanoList } : {}),\n _source: \"gateway\",\n };\n api.logger.info?.(\n `memory-hybrid: llm model tiers auto-derived from agents.defaults.model (default: ${(cfg.llm.default ?? []).slice(0, 3).join(\", \")}${(cfg.llm.default ?? []).length > 3 ? \"…\" : \"\"}${nanoList.length > 0 ? `; nano: ${(cfg.llm.nano ?? []).slice(0, 2).join(\", \")}` : \"\"})`,\n );\n }\n }\n // CostTracker — created early so proxy can instrument every chat.completions.create call (Issue #270).\n // Shares FactsDB's SQLite connection (same memory.db, avoids a second DB handle).\n // Gated on cfg.costTracking.enabled (default: true).\n const costTracker: CostTracker | null = cfg.costTracking?.enabled !== false ? new CostTracker(factsDb) : null;\n if (costTracker) {\n api.logger.info(\"memory-hybrid: LLM cost tracker initialized\");\n }\n\n // If Anthropic is in tier lists (e.g. from agents.defaults.model) but not yet in providers, use ANTHROPIC_API_KEY so verify --test-llm can test it.\n const defaultList = Array.isArray(cfg.llm?.default) ? cfg.llm.default : [];\n const heavyList = Array.isArray(cfg.llm?.heavy) ? cfg.llm.heavy : [];\n const hasAnthropicModel = (list: string[]) => list.some((m) => m.startsWith(\"anthropic/\") || m.startsWith(\"claude-\"));\n if (!prov.anthropic && (hasAnthropicModel(defaultList) || hasAnthropicModel(heavyList))) {\n const envKey = normalizeResolvedSecretValue(getEnv(\"ANTHROPIC_API_KEY\")) ?? \"\";\n if (envKey.length >= 10) {\n prov.anthropic = { apiKey: envKey };\n mergedProviderNames.push(\"anthropic\");\n api.logger.info?.(\n \"memory-hybrid: using ANTHROPIC_API_KEY for llm.providers.anthropic (verify --test-llm will test Anthropic models)\",\n );\n }\n }\n\n // If we merged providers, ensure at least one model from each is in the tier lists so they get tested and used as fallbacks.\n const hasModelFrom = (list: string[], prefix: string) =>\n list.some(\n (m) =>\n m.toLowerCase().startsWith(`${prefix}/`) ||\n (m.startsWith(\"claude-\") && prefix === \"anthropic\") ||\n (m.startsWith(\"gemini-\") && prefix === \"google\") ||\n (m.toLowerCase().startsWith(\"minimax-\") && prefix === \"minimax\"),\n );\n if (cfg.llm && mergedProviderNames.length > 0) {\n const defaultList = Array.isArray(cfg.llm.default) ? [...cfg.llm.default] : [];\n const heavyList = Array.isArray(cfg.llm.heavy) ? [...cfg.llm.heavy] : [];\n const knownDefault: Record<string, string> = {\n anthropic: \"anthropic/claude-sonnet-4-6\",\n openai: \"openai/gpt-4.1-mini\",\n google: \"google/gemini-2.5-flash\",\n minimax: \"minimax/MiniMax-Text-01\",\n };\n let appended = false;\n for (const name of mergedProviderNames) {\n if (hasModelFrom(defaultList, name) && hasModelFrom(heavyList, name)) continue;\n // Prefer the actual model IDs from gateway config over the hardcoded knownDefault fallback.\n // This ensures that if the gateway has e.g. minimax.models: [\"MiniMax-M2.5\"], we use that\n // instead of the hardcoded \"MiniMax-Text-01\".\n let defaultModel: string | null = null;\n const originalName = mergedProviderOriginalNames.get(name) ?? name;\n if (gwProviders && typeof (gwProviders as Record<string, unknown>)[originalName] === \"object\") {\n const gw = (gwProviders as Record<string, unknown>)[originalName] as Record<string, unknown>;\n // Define chat-compatibility filter (used for both models[] and defaultModel/model fields).\n // Skip non-chat entries (embeddings, transcription, TTS, image generation) so that\n // chatCompleteWithRetry is never routed through an incompatible model.\n const NON_CHAT_TYPES = new Set([\n \"embed\",\n \"embedding\",\n \"embeddings\",\n \"transcription\",\n \"speech-to-text\",\n \"text-to-speech\",\n \"tts\",\n \"image\",\n \"image-generation\",\n ]);\n const NON_CHAT_ID_RE = /\\bembed|whisper|\\btts\\b|dall-e|transcri|gpt-image|image-gen/i;\n const isChatEntry = (entry: unknown): boolean => {\n if (typeof entry === \"object\" && entry !== null) {\n const type = String((entry as Record<string, unknown>).type ?? \"\")\n .toLowerCase()\n .trim();\n if (type && NON_CHAT_TYPES.has(type)) return false;\n // If type is explicit and non-empty, trust it (unknown types → assume chat)\n if (type) return true;\n const id = String(\n (entry as Record<string, unknown>).id ?? (entry as Record<string, unknown>).name ?? \"\",\n ).toLowerCase();\n return !NON_CHAT_ID_RE.test(id);\n }\n if (typeof entry === \"string\") return !NON_CHAT_ID_RE.test(entry.toLowerCase());\n return false;\n };\n // Check models[] array first: iterate to find the first chat-compatible entry that\n // yields a non-empty trimmed model ID (skips entries with missing/empty id/name).\n if (Array.isArray(gw.models) && gw.models.length > 0) {\n for (const entry of gw.models) {\n if (!isChatEntry(entry)) continue;\n const modelId =\n typeof entry === \"string\"\n ? entry.trim()\n : String((entry as Record<string, unknown>).id ?? (entry as Record<string, unknown>).name ?? \"\").trim();\n if (modelId) {\n // Gateway may already use \"provider/model\" ids; avoid double prefix (e.g. azure-foundry/azure-foundry/model-router).\n defaultModel = modelId.includes(\"/\") ? modelId : `${name}/${modelId}`;\n break;\n }\n }\n }\n // Fall back to singular defaultModel or model field (also filter non-chat models)\n if (!defaultModel) {\n const gwModel =\n typeof gw.defaultModel === \"string\" ? gw.defaultModel : typeof gw.model === \"string\" ? gw.model : null;\n const trimmed = gwModel?.trim();\n if (trimmed && isChatEntry(gwModel)) {\n defaultModel = trimmed.includes(\"/\") ? trimmed : `${name}/${trimmed}`;\n }\n }\n }\n // Final fallback: use hardcoded knownDefault for well-known providers\n if (!defaultModel) defaultModel = knownDefault[name] ?? null;\n if (!defaultModel) continue;\n if (!hasModelFrom(defaultList, name)) {\n defaultList.push(defaultModel);\n appended = true;\n }\n const heavyModel = name === \"anthropic\" ? \"anthropic/claude-opus-4-6\" : defaultModel;\n if (!hasModelFrom(heavyList, name)) {\n heavyList.push(heavyModel);\n appended = true;\n }\n }\n if (appended) {\n (cfg.llm as Record<string, unknown>).default = defaultList;\n (cfg.llm as Record<string, unknown>).heavy = heavyList;\n gatewayLogInfoOnce(\n \"appended-gateway-models\",\n \"memory-hybrid: appended gateway provider models to llm.default/heavy so they are tested and used as fallbacks.\",\n api,\n );\n }\n }\n\n // Ollama auto-start: if any tier includes ollama/* models and localAutoStart is enabled,\n // attempt to launch `ollama serve` in the background when the server is not already running.\n // startOllamaIfNeeded deduplicates concurrent calls so only one spawn attempt runs at a time.\n startOllamaIfNeeded(cfg, api);\n\n // Chat/LLM client: multi-provider proxy that routes each model to the correct API.\n // google/* → Google Gemini OpenAI-compat API (uses distill.apiKey or llm.providers.google.apiKey)\n // openai/* or bare names → OpenAI API (uses embedding.apiKey or llm.providers.openai.apiKey)\n // ollama/* → local Ollama server (http://127.0.0.1:11434/v1 by default)\n // Other providers → require llm.providers.<provider>.apiKey + optionally baseURL\n const authBackoffStatePath = join(dirname(resolvedSqlitePath), \".auth-backoff.json\");\n const openai = buildMultiProviderOpenAI(cfg, api, costTracker, authBackoffStatePath);\n\n const {\n credentialsDb,\n wal,\n proposalsDb,\n identityReflectionStore,\n personaStateStore,\n eventLog,\n aliasDb,\n issueStore,\n workflowStore,\n crystallizationStore,\n toolProposalStore,\n verificationStore,\n provenanceService,\n apitapStore,\n } = installOptionalBootstrapServices({\n cfg,\n api,\n factsDb,\n resolvedSqlitePath,\n });\n\n const narrativesPath = join(dirname(resolvedSqlitePath), \"narratives.db\");\n const narrativesDb = new NarrativesDB(narrativesPath);\n api.logger.info(`memory-hybrid: narratives store initialized (${narrativesPath})`);\n\n // Report previously proposed categories, but do not load them as valid runtime categories.\n // Auto-classifier discovery is advisory only; operators must promote categories through config\n // before facts can be written under those labels.\n const discoveredPath = join(dirname(resolvedSqlitePath), \".discovered-categories.json\");\n if (existsSync(discoveredPath)) {\n try {\n const loaded = JSON.parse(readFileSync(discoveredPath, \"utf-8\")) as string[];\n if (Array.isArray(loaded) && loaded.length > 0) {\n api.logger.info(\n `memory-hybrid: ${loaded.length} proposed categories pending operator review (${discoveredPath})`,\n );\n }\n } catch (err) {\n api.logger.warn(`memory-hybrid: failed to inspect proposed categories: ${err}`);\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"inspect-proposed-categories\",\n subsystem: \"config\",\n });\n }\n }\n\n // Track embedding provider+model changes to trigger re-embedding (Issue #153).\n const currentEmbeddingMeta = {\n provider: cfg.embedding.provider,\n model: cfg.embedding.model,\n };\n let embeddingConfigChanged = false;\n try {\n const previousEmbeddingMeta = factsDb.getEmbeddingMeta();\n embeddingConfigChanged = Boolean(\n previousEmbeddingMeta &&\n (previousEmbeddingMeta.provider !== currentEmbeddingMeta.provider ||\n previousEmbeddingMeta.model !== currentEmbeddingMeta.model),\n );\n // When autoMigrate is enabled, still record the initial baseline on first run so future\n // changes can be detected. For subsequent runs with a config change, let runEmbeddingMaintenance\n // handle the meta update to avoid pre-updating before the migration service can detect the change.\n if (!cfg.embedding.autoMigrate && (!previousEmbeddingMeta || embeddingConfigChanged)) {\n factsDb.setEmbeddingMeta(currentEmbeddingMeta.provider, currentEmbeddingMeta.model);\n } else if (cfg.embedding.autoMigrate && !previousEmbeddingMeta && !embeddingConfigChanged) {\n factsDb.setEmbeddingMeta(currentEmbeddingMeta.provider, currentEmbeddingMeta.model);\n }\n } catch (err) {\n api.logger.warn(`memory-hybrid: failed to read embedding metadata (non-fatal): ${err}`);\n }\n\n // Health status tracking for verification checks\n const health: HealthStatus = {\n embeddingsOk: false,\n credentialsVaultOk: false,\n lastCheckTime: Date.now(),\n };\n\n // Prerequisite checks (async, don't block plugin start): verify keys and model access\n // Health status can be queried by tools to fail gracefully instead of throwing at runtime.\n const initialized = (async () => {\n if (isBootstrapSuperseded()) return;\n if (wal) {\n try {\n await wal.init();\n } catch (e) {\n if (isBootstrapSuperseded()) {\n api.logger.debug?.(\"memory-hybrid: WAL initialization skipped (registration superseded)\");\n return;\n }\n capturePluginError(e instanceof Error ? e : new Error(String(e)), {\n subsystem: \"wal\",\n operation: \"init\",\n phase: \"initialization\",\n });\n api.logger.warn(`memory-hybrid: WAL initialization failed: ${e}`);\n }\n }\n if (isBootstrapSuperseded()) return;\n try {\n await embeddings.embed(\"verify\");\n if (isBootstrapSuperseded()) return;\n health.embeddingsOk = true;\n const effectiveProvider = embeddings.activeProvider ?? cfg.embedding.provider;\n const modelForLog =\n effectiveProvider === \"openai\"\n ? formatOpenAiEmbeddingDisplayLabel(embeddings.modelName, cfg.embedding.endpoint)\n : embeddings.modelName;\n api.logger.info(\n effectiveProvider !== cfg.embedding.provider\n ? `memory-hybrid: embedding check OK (provider=${effectiveProvider}, model=${modelForLog} — using fallback; ${cfg.embedding.provider} unavailable)`\n : `memory-hybrid: embedding check OK (provider=${effectiveProvider}, model=${modelForLog})`,\n );\n } catch (e) {\n if (isBootstrapSuperseded()) {\n api.logger.debug?.(\"memory-hybrid: embedding check skipped (registration superseded)\");\n return;\n }\n const asErr = e instanceof Error ? e : new Error(String(e));\n if (!shouldSuppressEmbeddingError(asErr)) {\n capturePluginError(asErr, {\n subsystem: \"embeddings\",\n operation: \"init-verify\",\n phase: \"initialization\",\n backend: cfg.embedding.provider,\n });\n }\n const errText = String(e);\n const quota403 = is403QuotaOrRateLimitLike(e);\n const azure404 =\n typeof cfg.embedding.endpoint === \"string\" &&\n /\\.openai\\.azure\\.com/i.test(cfg.embedding.endpoint) &&\n (/404|not found/i.test(errText) || /Model not found/i.test(errText));\n const hint = quota403\n ? \"The provider returned 403 with quota/rate-limit signals (e.g. remaining-tokens=0, Retry-After). Wait for the window to reset or raise quota; your key may still be valid. Run 'openclaw hybrid-mem verify' for details.\"\n : cfg.embedding.provider === \"ollama\"\n ? `Ensure Ollama is running at ${cfg.embedding.endpoint ?? \"http://localhost:11434\"} and model '${cfg.embedding.model}' is pulled. Run 'openclaw hybrid-mem verify' for details.`\n : azure404\n ? 'Azure OpenAI embeddings use the deployment name as the API model id. In plugins.entries[\"openclaw-hybrid-memory\"].config.embedding set \"deployment\" to the exact embedding deployment name from Azure Portal (Resource → Model deployments), or rename the deployment to match embedding.model. Ensure embedding.endpoint is the resource URL (e.g. …/openai/v1). Run \\'openclaw hybrid-mem verify\\' for details.'\n : \"Set a valid embedding.apiKey in plugin config and ensure the model is accessible. Run 'openclaw hybrid-mem verify' for details.\";\n // Warn only for transient quota/rate-limit; keep error for bad keys, wrong model, geo 403, etc. (#941 review).\n const logEmbFailure = quota403 || is429OrWrapped(asErr) ? api.logger.warn : api.logger.error;\n const embTag = quota403 || is429OrWrapped(asErr) ? \"[embedding-quota]\" : \"[embedding-init]\";\n logEmbFailure(\n `${embTag} memory-hybrid: ⚠️ EMBEDDING CHECK FAILED (provider=${cfg.embedding.provider}) — ${String(e)}. ` +\n `Plugin will continue but semantic search will not work. ${hint}`,\n );\n }\n if (cfg.credentials.enabled && credentialsDb) {\n if (isBootstrapSuperseded()) return;\n try {\n const verifyVault = (): void => {\n const items = credentialsDb.list();\n if (items.length > 0) {\n const first = items[0];\n credentialsDb.get(first.service, first.type as CredentialType);\n }\n };\n verifyVault();\n if (isBootstrapSuperseded()) return;\n health.credentialsVaultOk = true;\n api.logger.info(\"memory-hybrid: credentials vault check OK\");\n } catch (e) {\n if (isBootstrapSuperseded()) {\n api.logger.debug?.(\"memory-hybrid: credentials vault check skipped (registration superseded)\");\n return;\n }\n capturePluginError(e instanceof Error ? e : new Error(String(e)), {\n subsystem: \"credentials\",\n operation: \"vault-verify\",\n phase: \"initialization\",\n backend: \"sqlite\",\n });\n api.logger.error(\n `memory-hybrid: ⚠️ CREDENTIALS VAULT CHECK FAILED — ${String(e)}. Plugin will continue but credential storage will not work. Check OPENCLAW_CRED_KEY (or credentials.encryptionKey). Wrong key or corrupted DB. Run 'openclaw hybrid-mem verify' for details.`,\n );\n }\n if (isBootstrapSuperseded()) return;\n // When vault is enabled: once per install, move existing credential facts into vault and redact from memory\n const migrationFlagPath = join(dirname(resolvedSqlitePath), CREDENTIAL_REDACTION_MIGRATION_FLAG);\n const clearMigrationFlagForRetry = async (reason: string): Promise<void> => {\n try {\n await unlink(migrationFlagPath);\n api.logger.debug?.(`memory-hybrid: cleared credential migration flag (${reason})`);\n } catch (err: unknown) {\n const errCode =\n typeof err === \"object\" && err !== null && \"code\" in err ? (err as { code?: unknown }).code : undefined;\n if (errCode === \"ENOENT\") return;\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"credentials\",\n operation: \"migration-flag-clear\",\n phase: \"initialization\",\n backend: \"sqlite\",\n });\n api.logger.warn(`memory-hybrid: failed to clear migration flag for retry: ${err}`);\n }\n };\n // Atomic flag creation to prevent race condition with multiple processes\n let shouldMigrate = false;\n try {\n const handle = await open(migrationFlagPath, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY);\n try {\n await handle.writeFile(\"1\", \"utf8\");\n shouldMigrate = true; // We won the race, proceed with migration\n } finally {\n await handle.close().catch(() => {\n /* ignore close errors */\n });\n }\n } catch (err: unknown) {\n const errCode =\n typeof err === \"object\" && err !== null && \"code\" in err ? (err as { code?: unknown }).code : undefined;\n if (isBootstrapSuperseded()) return;\n if (errCode === \"EEXIST\") {\n // Another process already created the flag - skip migration\n shouldMigrate = false;\n } else {\n shouldMigrate = false;\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"credentials\",\n operation: \"migration-flag-create\",\n phase: \"initialization\",\n backend: \"sqlite\",\n });\n api.logger.warn(`memory-hybrid: failed to create migration flag (skipping migration): ${err}`);\n }\n }\n if (shouldMigrate) {\n if (isBootstrapSuperseded()) {\n await clearMigrationFlagForRetry(\"registration superseded before migration\");\n return;\n }\n try {\n const result = await migrateCredentialsToVault({\n factsDb,\n vectorDb,\n embeddings,\n credentialsDb,\n aliasDb,\n migrationFlagPath,\n markDone: false, // Flag already created atomically above\n });\n if (isBootstrapSuperseded()) {\n await clearMigrationFlagForRetry(\"registration superseded after migration\");\n api.logger.debug?.(\n \"memory-hybrid: credential migration finished after supersession; suppressing stale logs\",\n );\n return;\n }\n if (result.migrated > 0) {\n api.logger.info(`memory-hybrid: migrated ${result.migrated} credential(s) from memory into vault`);\n }\n if (result.errors.length > 0) {\n api.logger.warn(\n `memory-hybrid: credential migration had ${result.errors.length} error(s): ${result.errors.join(\"; \")}`,\n );\n await clearMigrationFlagForRetry(\"credential migration completed with errors\");\n }\n } catch (e) {\n if (isBootstrapSuperseded()) {\n await clearMigrationFlagForRetry(\"registration superseded during migration\");\n const isDbClosed = isDbClosedError(e);\n if (!isDbClosed) {\n // Non-DB-closed error during superseded bootstrap: flag was set but bootstrap\n // was superseded before or during migration. Clear flag so retry can run fresh.\n api.logger.debug?.(\n \"memory-hybrid: credential migration error during superseded bootstrap cleared for retry\",\n );\n } else {\n api.logger.debug?.(\"memory-hybrid: credential migration skipped (registration superseded)\");\n }\n return;\n }\n capturePluginError(e instanceof Error ? e : new Error(String(e)), {\n subsystem: \"credentials\",\n operation: \"migration-to-vault\",\n phase: \"initialization\",\n backend: \"sqlite\",\n });\n api.logger.warn(`memory-hybrid: credential migration failed: ${e}`);\n }\n }\n }\n })().catch((err: unknown) => {\n if (isBootstrapSuperseded()) return;\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"init\",\n operation: \"async-initialization\",\n phase: \"initialization\",\n });\n api.logger.warn(`memory-hybrid: async initialization encountered an error: ${err}`);\n });\n\n // autoMigrate path: use the embedding-migration service when autoMigrate=true (Issue #153).\n // Runs asynchronously so it does not block plugin start.\n if (cfg.embedding.autoMigrate && embeddingConfigChanged) {\n void (async () => {\n try {\n await runEmbeddingMaintenance({\n factsDb,\n vectorDb,\n embeddings,\n currentProvider: cfg.embedding.provider,\n currentModel: cfg.embedding.model,\n autoMigrate: true,\n batchSize: cfg.embedding.batchSize,\n logger: {\n info: (msg) => api.logger.info(msg),\n warn: (msg) => api.logger.warn(msg),\n },\n });\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"autoMigrate-embedding\",\n subsystem: \"embeddings\",\n });\n api.logger.warn(`memory-hybrid: autoMigrate embedding run failed: ${err}`);\n }\n })();\n }\n\n // Schema validation + re-embedding (Issue #128 + #153).\n // Runs asynchronously so it does not block plugin start.\n // vectorDb.count() triggers lazy initialization, after which wasRepaired is set.\n // Skip this block when autoMigrate is enabled and config changed — runEmbeddingMaintenance handles it.\n if ((cfg.vector.autoRepair || embeddingConfigChanged) && !(cfg.embedding.autoMigrate && embeddingConfigChanged)) {\n void (async () => {\n const reembedProgressPath = join(dirname(resolvedSqlitePath), \".reembed-progress.json\");\n try {\n if (cfg.vector.autoRepair || embeddingConfigChanged) {\n await vectorDb.count(); // triggers doInitialize() → validateOrRepairSchema()\n }\n\n // Check if there's an incomplete re-embedding from a previous run\n let needsReembedding = embeddingConfigChanged || (cfg.vector.autoRepair && vectorDb.wasRepaired);\n let completedIds = new Set<string>();\n\n if (!needsReembedding && existsSync(reembedProgressPath)) {\n try {\n const progress = JSON.parse(readFileSync(reembedProgressPath, \"utf-8\")) as {\n completedIds: string[];\n total: number;\n };\n if (progress.completedIds.length < progress.total) {\n needsReembedding = true;\n completedIds = new Set(progress.completedIds);\n api.logger.info(\n `memory-hybrid: resuming incomplete re-embedding from previous run (${progress.completedIds.length}/${progress.total} completed)`,\n );\n }\n } catch {\n // Ignore invalid progress file\n }\n }\n\n if (needsReembedding) {\n const initialGeneration = vectorDb.getCloseGeneration();\n api.logger.info(\n embeddingConfigChanged\n ? `memory-hybrid: embedding config changed (${currentEmbeddingMeta.provider}/${currentEmbeddingMeta.model}) — re-embedding existing facts...`\n : vectorDb.wasRepaired\n ? \"memory-hybrid: VectorDB was auto-repaired — re-embedding existing facts from SQLite...\"\n : \"memory-hybrid: resuming re-embedding after hot reload...\",\n );\n const facts = factsDb.getAll({ includeSuperseded: false });\n let reembedded = completedIds.size;\n\n for (const fact of facts) {\n if (completedIds.has(fact.id)) {\n continue;\n }\n if (vectorDb.getCloseGeneration() !== initialGeneration) {\n // Save progress before aborting\n try {\n const progress = {\n completedIds: Array.from(completedIds),\n total: facts.length,\n };\n const { writeFileSync } = await import(\"node:fs\");\n writeFileSync(reembedProgressPath, JSON.stringify(progress), \"utf-8\");\n } catch {\n // Ignore write errors\n }\n api.logger.info(\n `memory-hybrid: re-embedding aborted (VectorDB closed during hot reload) — ${reembedded}/${facts.length} facts re-embedded`,\n );\n return;\n }\n try {\n const vec = await embeddings.embed(fact.text);\n const isDuplicate = await vectorDb.hasDuplicate(vec);\n if (!isDuplicate) {\n await vectorDb.store({\n id: fact.id,\n text: fact.text,\n vector: vec,\n importance: fact.importance ?? 0.5,\n category: fact.category,\n });\n factsDb.setEmbeddingModel(fact.id, embeddings.modelName);\n }\n completedIds.add(fact.id);\n reembedded++;\n } catch {\n // Skip individual failures — best-effort re-embedding\n }\n }\n\n // Clean up progress file on successful completion\n try {\n const { unlinkSync } = await import(\"node:fs\");\n if (existsSync(reembedProgressPath)) {\n unlinkSync(reembedProgressPath);\n }\n } catch {\n // Ignore cleanup errors\n }\n\n api.logger.info(`memory-hybrid: re-embedded ${reembedded}/${facts.length} facts during re-embedding pass`);\n }\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"vector-reembed\",\n subsystem: \"vector\",\n });\n api.logger.warn(`memory-hybrid: re-embedding failed: ${err}`);\n }\n })();\n }\n\n // Mark the VectorDB as a persistent long-lived singleton connection (#581).\n // This prevents fragile session refcounting from accidentally closing the shared\n // connection via removeSession() — the connection is only closed by close() (gateway shutdown).\n vectorDb.setPersistent();\n\n return {\n factsDb,\n edictStore,\n vectorDb,\n embeddings,\n embeddingRegistry,\n openai,\n credentialsDb,\n wal,\n proposalsDb,\n identityReflectionStore,\n personaStateStore,\n eventLog,\n narrativesDb,\n aliasDb,\n issueStore,\n workflowStore,\n crystallizationStore,\n toolProposalStore,\n verificationStore,\n provenanceService,\n costTracker,\n resolvedLancePath,\n resolvedSqlitePath,\n health,\n initialized,\n apitapStore,\n };\n}\n\n/**\n * Closes old database instances before reinitializing.\n * Used when the plugin is reloaded (e.g., on SIGUSR1 signal).\n */\nexport function closeOldDatabases(context: {\n factsDb?: FactsDB | null;\n edictStore?: EdictStore | null;\n narrativesDb?: NarrativesDB | null;\n vectorDb?: VectorDB | null;\n credentialsDb?: CredentialsDB | null;\n proposalsDb?: ProposalsDB | null;\n identityReflectionStore?: import(\"../backends/identity-reflection-store.js\").IdentityReflectionStore | null;\n personaStateStore?: import(\"../backends/persona-state-store.js\").PersonaStateStore | null;\n eventLog?: EventLog | null;\n aliasDb?: AliasDB | null;\n eventBus?: import(\"../backends/event-bus.js\").EventBus | null;\n issueStore?: IssueStore | null;\n workflowStore?: WorkflowStore | null;\n crystallizationStore?: CrystallizationStore | null;\n toolProposalStore?: ToolProposalStore | null;\n verificationStore?: VerificationStore | null;\n provenanceService?: ProvenanceService | null;\n learningsDb?: import(\"../backends/learnings-db.js\").LearningsDB | null;\n apitapStore?: ApitapStore | null;\n auditStore?: import(\"../backends/audit-store.js\").AuditStore | null;\n agentHealthStore?: import(\"../backends/agent-health-store.js\").AgentHealthStore | null;\n}): void {\n const {\n factsDb,\n edictStore,\n narrativesDb,\n vectorDb,\n credentialsDb,\n proposalsDb,\n identityReflectionStore,\n personaStateStore,\n eventLog,\n aliasDb,\n eventBus,\n issueStore,\n workflowStore,\n crystallizationStore,\n toolProposalStore,\n verificationStore,\n provenanceService,\n learningsDb,\n apitapStore,\n auditStore,\n agentHealthStore,\n } = context;\n\n invalidateClusterCache();\n\n // BaseSqliteStore-derived stores: call permanentClose() so liveDb throws on any\n // subsequent access rather than silently reopening the old SQLite handle.\n // This is the primary fix for issue #1550 (duplicate handles after re-registration).\n if (typeof factsDb?.permanentClose === \"function\") {\n try {\n factsDb.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"factsDb\",\n });\n }\n }\n if (typeof edictStore?.permanentClose === \"function\") {\n try {\n edictStore.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"edictStore\",\n });\n }\n }\n // VectorDB is LanceDB-based (not a BaseSqliteStore); its close() is already terminal.\n if (typeof vectorDb?.close === \"function\") {\n try {\n vectorDb.close();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"vectorDb\",\n });\n }\n }\n if (credentialsDb) {\n try {\n credentialsDb.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"credentialsDb\",\n });\n }\n }\n if (narrativesDb) {\n try {\n narrativesDb.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"narrativesDb\",\n });\n }\n }\n if (proposalsDb) {\n try {\n proposalsDb.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"proposalsDb\",\n });\n }\n }\n if (identityReflectionStore) {\n try {\n identityReflectionStore.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"identityReflectionStore\",\n });\n }\n }\n if (personaStateStore) {\n try {\n personaStateStore.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"personaStateStore\",\n });\n }\n }\n if (eventLog) {\n try {\n eventLog.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"eventLog\",\n });\n }\n }\n // AliasDB has its own reference-counted close logic (not a BaseSqliteStore).\n if (aliasDb) {\n try {\n aliasDb.close();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"aliasDb\",\n });\n }\n }\n // EventBus.close() is already terminal (sets _terminallyClosed = true).\n if (eventBus) {\n try {\n eventBus.close();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"eventBus\",\n });\n }\n }\n if (issueStore) {\n try {\n issueStore.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"issueStore\",\n });\n }\n }\n if (workflowStore) {\n try {\n workflowStore.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"workflowStore\",\n });\n }\n }\n if (crystallizationStore) {\n try {\n crystallizationStore.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"crystallizationStore\",\n });\n }\n }\n if (toolProposalStore) {\n try {\n toolProposalStore.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"toolProposalStore\",\n });\n }\n }\n // VerificationStore has its own connection-sharing logic (not a BaseSqliteStore).\n if (verificationStore) {\n try {\n verificationStore.close();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"verificationStore\",\n });\n }\n }\n if (provenanceService) {\n try {\n provenanceService.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"provenanceService\",\n });\n }\n }\n if (learningsDb) {\n try {\n learningsDb.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"learningsDb\",\n });\n }\n }\n if (apitapStore) {\n try {\n apitapStore.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"apitapStore\",\n });\n }\n }\n if (auditStore) {\n try {\n auditStore.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"auditStore\",\n });\n }\n }\n if (agentHealthStore) {\n try {\n agentHealthStore.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"agentHealthStore\",\n });\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"bootstrap-databases.js","names":[],"sources":["../../setup/bootstrap-databases.ts"],"sourcesContent":["import { constants, existsSync, readFileSync } from \"node:fs\";\nimport { open, unlink } from \"node:fs/promises\";\n/** @module bootstrap-databases — Database bootstrap, optional stores, and lifecycle teardown. */\nimport { dirname, join } from \"node:path\";\nimport type OpenAI from \"openai\";\nimport type { ClawdbotPluginApi } from \"openclaw/plugin-sdk/core\";\nimport type { ApitapStore } from \"../backends/apitap-store.js\";\nimport { CostTracker } from \"../backends/cost-tracker.js\";\nimport type { CredentialsDB } from \"../backends/credentials-db.js\";\nimport type { CrystallizationStore } from \"../backends/crystallization-store.js\";\nimport type { EdictStore } from \"../backends/edict-store.js\";\nimport type { EventLog } from \"../backends/event-log.js\";\nimport type { FactsDB } from \"../backends/facts-db.js\";\nimport type { IssueStore } from \"../backends/issue-store.js\";\nimport { NarrativesDB } from \"../backends/narratives-db.js\";\nimport type { ProposalsDB } from \"../backends/proposals-db.js\";\nimport type { ToolProposalStore } from \"../backends/tool-proposal-store.js\";\nimport type { VectorDB } from \"../backends/vector-db.js\";\nimport type { WriteAheadLog } from \"../backends/wal.js\";\nimport type { WorkflowStore } from \"../backends/workflow-store.js\";\nimport type { CredentialType, HybridMemoryConfig } from \"../config.js\";\nimport { normalizeResolvedSecretValue } from \"../config/parsers/core.js\";\nimport { is403QuotaOrRateLimitLike, is429OrWrapped } from \"../services/chat.js\";\nimport { CREDENTIAL_REDACTION_MIGRATION_FLAG, migrateCredentialsToVault } from \"../services/credential-migration.js\";\nimport { runEmbeddingMaintenance } from \"../services/embedding-migration.js\";\nimport type { EmbeddingRegistry } from \"../services/embedding-registry.js\";\nimport type { EmbeddingProvider } from \"../services/embeddings.js\";\nimport { formatOpenAiEmbeddingDisplayLabel, shouldSuppressEmbeddingError } from \"../services/embeddings/shared.js\";\nimport { capturePluginError } from \"../services/error-reporter.js\";\nimport { installCoreBootstrapServices, installOptionalBootstrapServices } from \"../services/index.js\";\nimport type { ProvenanceService } from \"../services/provenance.js\";\nimport type { AliasDB } from \"../services/retrieval-aliases.js\";\nimport { recordStartupMemoryCheckpoint } from \"../services/startup-memory-attribution.js\";\nimport { invalidateClusterCache } from \"../services/retrieval-orchestrator.js\";\nimport type { VerificationStore } from \"../services/verification-store.js\";\nimport { hasOAuthProfiles } from \"../utils/auth.js\";\nimport { getEnv } from \"../utils/env-manager.js\";\nimport { setKeywordsPath } from \"../utils/language-keywords.js\";\nimport { spawn } from \"../utils/process-runner.js\";\nimport { isDbClosedError, isRegistrationSuperseded } from \"../utils/registration-superseded.js\";\nimport { isHeavyModel, isLightModel, isNanoModel } from \"../utils/model-tier.js\";\nimport {\n OLLAMA_DEFAULT_BASE_URL,\n ROUTABLE_BUILTIN_PROVIDERS,\n buildMultiProviderOpenAI,\n clearOllamaHealthCacheEntry,\n extractGatewayConfig,\n gatewayLogInfoOnce,\n getGatewayModelsProviders,\n mergeGatewayProviderCredentialsIntoLlmProvidersMap,\n patchEmbeddingEndpointFromGatewayProviders,\n probeOllamaEndpoint,\n} from \"./provider-router.js\";\ninterface HealthStatus {\n embeddingsOk: boolean;\n credentialsVaultOk: boolean;\n lastCheckTime: number;\n}\n\ninterface DatabaseContext {\n factsDb: FactsDB;\n edictStore: EdictStore;\n vectorDb: VectorDB;\n embeddings: EmbeddingProvider;\n embeddingRegistry: EmbeddingRegistry;\n openai: OpenAI;\n credentialsDb: CredentialsDB | null;\n wal: WriteAheadLog | null;\n proposalsDb: ProposalsDB | null;\n identityReflectionStore: import(\"../backends/identity-reflection-store.js\").IdentityReflectionStore | null;\n personaStateStore: import(\"../backends/persona-state-store.js\").PersonaStateStore | null;\n eventLog: EventLog | null;\n narrativesDb: NarrativesDB;\n aliasDb: AliasDB | null;\n issueStore: IssueStore;\n workflowStore: WorkflowStore;\n crystallizationStore: CrystallizationStore;\n toolProposalStore: ToolProposalStore;\n verificationStore: VerificationStore | null;\n provenanceService: ProvenanceService | null;\n costTracker: CostTracker | null;\n resolvedLancePath: string;\n resolvedSqlitePath: string;\n health: HealthStatus;\n initialized: Promise<void>;\n apitapStore: ApitapStore;\n}\n\n// Module-level guard: tracks an in-progress Ollama auto-start promise so concurrent calls to\n// initializeDatabases (e.g. rapid plugin reload on SIGUSR1) cannot spawn multiple `ollama serve`\n// processes at the same time. Cleared in the `finally` block so a future startup can retry.\nlet _ollamaAutoStartPromise: Promise<void> | null = null;\n\n/** @internal Reset the Ollama auto-start deduplication guard between tests. */\nexport function _resetOllamaAutoStartForTesting(): void {\n _ollamaAutoStartPromise = null;\n}\n\n/**\n * Attempt to start the Ollama server in the background when `localAutoStart` is enabled and at\n * least one `ollama/*` model is configured. Concurrent calls while a spawn attempt is already\n * in progress are silently skipped — only one `ollama serve` process is ever launched at a time.\n * The guard is automatically cleared after the attempt completes (success or failure) so a later\n * non-overlapping call can retry.\n *\n * Errors are captured via `capturePluginError` and logged as warnings so they never crash the\n * plugin startup path.\n *\n * @internal Exported for focused unit testing only.\n */\nexport function startOllamaIfNeeded(cfg: HybridMemoryConfig, api: ClawdbotPluginApi): void {\n if (!cfg.llm?.localAutoStart) return;\n const allModels = [...(cfg.llm.nano ?? []), ...(cfg.llm.default ?? []), ...(cfg.llm.heavy ?? [])];\n const hasOllamaModels = allModels.some((m) => m.split(\"/\")[0]?.toLowerCase() === \"ollama\");\n if (!hasOllamaModels) return;\n\n // Already in-progress — skip to prevent a second concurrent spawn.\n if (_ollamaAutoStartPromise) return;\n\n _ollamaAutoStartPromise = (async () => {\n try {\n const ollamaBase =\n (cfg.llm?.providers as Record<string, { baseURL?: string } | undefined> | undefined)?.ollama?.baseURL?.replace(\n /\\/v1\\/?$/,\n \"\",\n ) ?? OLLAMA_DEFAULT_BASE_URL;\n const running = await probeOllamaEndpoint(ollamaBase);\n if (!running) {\n api.logger.info(\"memory-hybrid: Ollama is not running — attempting auto-start (llm.localAutoStart: true)\");\n const child = spawn(\"ollama\", [\"serve\"], {\n detached: true,\n stdio: \"ignore\",\n });\n child.on(\"error\", (err) => {\n api.logger.warn(`memory-hybrid: Ollama spawn error: ${err.message}`);\n });\n child.unref();\n // Allow Ollama ~2 s to bind its port before re-probing\n await new Promise<void>((r) => setTimeout(r, 2000));\n // Invalidate any cached \"down\" entry so the next probe goes to the network\n clearOllamaHealthCacheEntry(ollamaBase);\n const nowRunning = await probeOllamaEndpoint(ollamaBase);\n if (nowRunning) {\n api.logger.info(\"memory-hybrid: Ollama started successfully\");\n } else {\n api.logger.warn(\n \"memory-hybrid: Ollama auto-start attempted but server still not available — local model calls will fall back to cloud\",\n );\n }\n }\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"ollama-auto-start\",\n subsystem: \"llm\",\n });\n api.logger.warn(`memory-hybrid: Ollama auto-start failed: ${err}`);\n } finally {\n _ollamaAutoStartPromise = null;\n }\n })();\n}\n\n/**\n * Ollama auto-start: if any tier includes ollama/* models and localAutoStart is enabled,\n * attempt to launch `ollama serve` in the background when the server is not already running.\n * Delegates to `startOllamaIfNeeded`; retained for backwards-compatibility with external callers.\n */\nexport function maybeAutoStartOllama(cfg: HybridMemoryConfig, api: ClawdbotPluginApi): void {\n startOllamaIfNeeded(cfg, api);\n}\n\n/**\n * Run bootstrap checks (WAL init, embedding verify, vault check, credential migration)\n * for a new registration generation when reusing database handles.\n * @internal Exported for reregister-policy; not part of public API.\n */\nexport function createReusedDatabaseBootstrap(\n cfg: HybridMemoryConfig,\n api: ClawdbotPluginApi,\n ctx: Pick<\n DatabaseContext,\n \"embeddings\" | \"wal\" | \"credentialsDb\" | \"factsDb\" | \"vectorDb\" | \"aliasDb\" | \"resolvedSqlitePath\" | \"health\"\n >,\n opts: { bootRegistrationGeneration: number },\n): Promise<void> {\n const { embeddings, wal, credentialsDb, factsDb, vectorDb, aliasDb, resolvedSqlitePath, health } = ctx;\n const bootRegistrationGeneration = opts.bootRegistrationGeneration;\n const isBootstrapSuperseded = (): boolean => isRegistrationSuperseded(bootRegistrationGeneration);\n\n return (async () => {\n if (isBootstrapSuperseded()) return;\n if (wal) {\n try {\n await wal.init();\n } catch (e) {\n if (isBootstrapSuperseded()) {\n api.logger.debug?.(\"memory-hybrid: WAL initialization skipped (registration superseded)\");\n return;\n }\n capturePluginError(e instanceof Error ? e : new Error(String(e)), {\n subsystem: \"wal\",\n operation: \"init\",\n phase: \"initialization\",\n });\n api.logger.warn(`memory-hybrid: WAL initialization failed: ${e}`);\n }\n }\n if (isBootstrapSuperseded()) return;\n try {\n await embeddings.embed(\"verify\");\n if (isBootstrapSuperseded()) return;\n health.embeddingsOk = true;\n const effectiveProvider = embeddings.activeProvider ?? cfg.embedding.provider;\n const modelForLog =\n effectiveProvider === \"openai\"\n ? formatOpenAiEmbeddingDisplayLabel(embeddings.modelName, cfg.embedding.endpoint)\n : embeddings.modelName;\n api.logger.info(\n effectiveProvider !== cfg.embedding.provider\n ? `memory-hybrid: embedding check OK (provider=${effectiveProvider}, model=${modelForLog} — using fallback; ${cfg.embedding.provider} unavailable)`\n : `memory-hybrid: embedding check OK (provider=${effectiveProvider}, model=${modelForLog})`,\n );\n } catch (e) {\n if (isBootstrapSuperseded()) {\n api.logger.debug?.(\"memory-hybrid: embedding check skipped (registration superseded)\");\n return;\n }\n const asErr = e instanceof Error ? e : new Error(String(e));\n if (!shouldSuppressEmbeddingError(asErr)) {\n capturePluginError(asErr, {\n subsystem: \"embeddings\",\n operation: \"init-verify\",\n phase: \"initialization\",\n backend: cfg.embedding.provider,\n });\n }\n const errText = String(e);\n const quota403 = is403QuotaOrRateLimitLike(e);\n const azure404 =\n typeof cfg.embedding.endpoint === \"string\" &&\n /\\.openai\\.azure\\.com/i.test(cfg.embedding.endpoint) &&\n (/404|not found/i.test(errText) || /Model not found/i.test(errText));\n const hint = quota403\n ? \"The provider returned 403 with quota/rate-limit signals (e.g. remaining-tokens=0, Retry-After). Wait for the window to reset or raise quota; your key may still be valid. Run 'openclaw hybrid-mem verify' for details.\"\n : cfg.embedding.provider === \"ollama\"\n ? `Ensure Ollama is running at ${cfg.embedding.endpoint ?? \"http://localhost:11434\"} and model '${cfg.embedding.model}' is pulled. Run 'openclaw hybrid-mem verify' for details.`\n : azure404\n ? 'Azure OpenAI embeddings use the deployment name as the API model id. In plugins.entries[\"openclaw-hybrid-memory\"].config.embedding set \"deployment\" to the exact embedding deployment name from Azure Portal (Resource → Model deployments), or rename the deployment to match embedding.model. Ensure embedding.endpoint is the resource URL (e.g. …/openai/v1). Run \\'openclaw hybrid-mem verify\\' for details.'\n : \"Set a valid embedding.apiKey in plugin config and ensure the model is accessible. Run 'openclaw hybrid-mem verify' for details.\";\n const logEmbFailure = quota403 || is429OrWrapped(asErr) ? api.logger.warn : api.logger.error;\n const embTag = quota403 || is429OrWrapped(asErr) ? \"[embedding-quota]\" : \"[embedding-init]\";\n logEmbFailure(\n `${embTag} memory-hybrid: ⚠️ EMBEDDING CHECK FAILED (provider=${cfg.embedding.provider}) — ${String(e)}. ` +\n `Plugin will continue but semantic search will not work. ${hint}`,\n );\n }\n if (cfg.credentials.enabled && credentialsDb) {\n if (isBootstrapSuperseded()) return;\n try {\n const verifyVault = (): void => {\n const items = credentialsDb.list();\n if (items.length > 0) {\n const first = items[0];\n credentialsDb.get(first.service, first.type as CredentialType);\n }\n };\n verifyVault();\n if (isBootstrapSuperseded()) return;\n health.credentialsVaultOk = true;\n api.logger.info(\"memory-hybrid: credentials vault check OK\");\n } catch (e) {\n if (isBootstrapSuperseded()) {\n api.logger.debug?.(\"memory-hybrid: credentials vault check skipped (registration superseded)\");\n return;\n }\n capturePluginError(e instanceof Error ? e : new Error(String(e)), {\n subsystem: \"credentials\",\n operation: \"vault-verify\",\n phase: \"initialization\",\n backend: \"sqlite\",\n });\n api.logger.error(\n `memory-hybrid: ⚠️ CREDENTIALS VAULT CHECK FAILED — ${String(e)}. Plugin will continue but credential storage will not work. Check OPENCLAW_CRED_KEY (or credentials.encryptionKey). Wrong key or corrupted DB. Run 'openclaw hybrid-mem verify' for details.`,\n );\n }\n if (isBootstrapSuperseded()) return;\n const migrationFlagPath = join(dirname(resolvedSqlitePath), CREDENTIAL_REDACTION_MIGRATION_FLAG);\n const clearMigrationFlagForRetry = async (reason: string): Promise<void> => {\n try {\n await unlink(migrationFlagPath);\n api.logger.debug?.(`memory-hybrid: cleared credential migration flag (${reason})`);\n } catch (err: unknown) {\n const errCode =\n typeof err === \"object\" && err !== null && \"code\" in err ? (err as { code?: unknown }).code : undefined;\n if (errCode === \"ENOENT\") return;\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"credentials\",\n operation: \"migration-flag-clear\",\n phase: \"initialization\",\n backend: \"sqlite\",\n });\n api.logger.warn(`memory-hybrid: failed to clear migration flag for retry: ${err}`);\n }\n };\n let shouldMigrate = false;\n try {\n const handle = await open(migrationFlagPath, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY);\n try {\n await handle.writeFile(\"1\", \"utf8\");\n shouldMigrate = true;\n } finally {\n await handle.close().catch(() => {});\n }\n } catch (err: unknown) {\n const errCode =\n typeof err === \"object\" && err !== null && \"code\" in err ? (err as { code?: unknown }).code : undefined;\n if (isBootstrapSuperseded()) return;\n if (errCode === \"EEXIST\") {\n shouldMigrate = false;\n } else {\n shouldMigrate = false;\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"credentials\",\n operation: \"migration-flag-create\",\n phase: \"initialization\",\n backend: \"sqlite\",\n });\n api.logger.warn(`memory-hybrid: failed to create migration flag (skipping migration): ${err}`);\n }\n }\n if (shouldMigrate) {\n if (isBootstrapSuperseded()) {\n await clearMigrationFlagForRetry(\"registration superseded before migration\");\n return;\n }\n try {\n const result = await migrateCredentialsToVault({\n factsDb,\n vectorDb,\n embeddings,\n credentialsDb,\n aliasDb,\n migrationFlagPath,\n markDone: false,\n });\n if (isBootstrapSuperseded()) {\n await clearMigrationFlagForRetry(\"registration superseded after migration\");\n api.logger.debug?.(\n \"memory-hybrid: credential migration finished after supersession; suppressing stale logs\",\n );\n return;\n }\n if (result.migrated > 0) {\n api.logger.info(`memory-hybrid: migrated ${result.migrated} credential(s) from memory into vault`);\n }\n if (result.errors.length > 0) {\n api.logger.warn(\n `memory-hybrid: credential migration had ${result.errors.length} error(s): ${result.errors.join(\"; \")}`,\n );\n await clearMigrationFlagForRetry(\"credential migration completed with errors\");\n }\n } catch (e) {\n if (isBootstrapSuperseded()) {\n await clearMigrationFlagForRetry(\"registration superseded during migration\");\n const isDbClosed = isDbClosedError(e);\n if (!isDbClosed) {\n api.logger.debug?.(\n \"memory-hybrid: credential migration error during superseded bootstrap cleared for retry\",\n );\n } else {\n api.logger.debug?.(\"memory-hybrid: credential migration skipped (registration superseded)\");\n }\n return;\n }\n capturePluginError(e instanceof Error ? e : new Error(String(e)), {\n subsystem: \"credentials\",\n operation: \"migration-to-vault\",\n phase: \"initialization\",\n backend: \"sqlite\",\n });\n api.logger.warn(`memory-hybrid: credential migration failed: ${e}`);\n }\n }\n }\n })().catch((err: unknown) => {\n if (isBootstrapSuperseded()) return;\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"init\",\n operation: \"async-initialization\",\n phase: \"initialization\",\n });\n api.logger.warn(`memory-hybrid: async initialization encountered an error: ${err}`);\n });\n}\n\n/**\n * Initializes all databases and services for the plugin.\n *\n * This includes:\n * - FactsDB (SQLite)\n * - VectorDB (LanceDB)\n * - Embeddings service\n * - OpenAI client\n * - CredentialsDB (optional)\n * - WriteAheadLog (optional)\n * - ProposalsDB (optional)\n * - Discovered categories loading\n * - Async verification checks\n */\nexport function initializeDatabases(\n cfg: HybridMemoryConfig,\n api: ClawdbotPluginApi,\n opts?: { bootRegistrationGeneration?: number },\n): DatabaseContext {\n const bootRegistrationGeneration = opts?.bootRegistrationGeneration ?? -1;\n const isBootstrapSuperseded = (): boolean => isRegistrationSuperseded(bootRegistrationGeneration);\n const resolvedLancePath = api.resolvePath(cfg.lanceDbPath);\n const resolvedSqlitePath = api.resolvePath(cfg.sqlitePath);\n setKeywordsPath(dirname(resolvedSqlitePath));\n\n recordStartupMemoryCheckpoint({\n logger: api.logger,\n subsystem: \"bootstrap\",\n operation: \"plugin-registration\",\n phase: \"startup.plugin-registration.begin\",\n onceKey: \"startup.plugin-registration.begin\",\n tags: {\n sqlitePath: resolvedSqlitePath,\n lancedbPath: resolvedLancePath,\n },\n });\n\n patchEmbeddingEndpointFromGatewayProviders(cfg, api);\n\n const { factsDb, edictStore, vectorDb, embeddings, embeddingRegistry } = installCoreBootstrapServices({\n cfg,\n api,\n resolvedSqlitePath,\n resolvedLancePath,\n });\n\n recordStartupMemoryCheckpoint({\n logger: api.logger,\n subsystem: \"bootstrap\",\n operation: \"plugin-registration\",\n phase: \"startup.plugin-registration.after-bootstrap\",\n onceKey: \"startup.plugin-registration.after-bootstrap\",\n tags: {\n sqlitePath: resolvedSqlitePath,\n lancedbPath: resolvedLancePath,\n lancedbInitialized: typeof vectorDb.isInitialized === \"function\" ? vectorDb.isInitialized() : undefined,\n lancedbOpenReaders: typeof vectorDb.getOpenReaderCount === \"function\" ? vectorDb.getOpenReaderCount() : undefined,\n },\n });\n\n // Merge gateway provider keys into plugin llm.providers BEFORE auto-derivation so canRoute\n // can see all available providers (issue #487 fix).\n // Check three paths: models.providers (standard), llm.providers (legacy), providers (top-level).\n const gwConfig = api.config as Record<string, unknown> | undefined;\n const gwProviders = getGatewayModelsProviders(gwConfig);\n const mergedProviderNames: string[] = [];\n const mergedProviderOriginalNames = new Map<string, string>();\n if (!cfg.llm)\n (cfg as Record<string, unknown>).llm = {\n providers: {},\n default: [],\n heavy: [],\n nano: [],\n };\n const plm = cfg.llm as Record<string, unknown>;\n if (!plm.providers || typeof plm.providers !== \"object\") plm.providers = {};\n const prov = plm.providers as Record<string, Record<string, unknown>>;\n\n mergeGatewayProviderCredentialsIntoLlmProvidersMap(\n prov,\n gwProviders,\n api,\n mergedProviderNames,\n mergedProviderOriginalNames,\n );\n\n // When llm.default/heavy are not explicitly configured, auto-derive from agents.defaults.model\n // (the same model list shown by `openclaw models list`). This makes the plugin zero-config for\n // model selection when the user has already set up their models in openclaw.json.\n // If the gateway list is heavy-only (e.g. only Opus), we prepend a cheap fallback so default/nano\n // tasks don't all use the expensive model (see cost issue: hundreds of tasks running as Opus).\n const RECOMMENDED_CHEAP_FALLBACK = [\n \"openai/gpt-4.1-nano\",\n \"google/gemini-2.5-flash-lite\",\n \"anthropic/claude-3-5-haiku\",\n ];\n if (\n (cfg.llm?.default ?? []).length === 0 &&\n (cfg.llm?.heavy ?? []).length === 0 &&\n (cfg.llm?.nano ?? []).length === 0\n ) {\n const agentModel = (api.config as Record<string, unknown>)?.agents as Record<string, unknown> | undefined;\n const agentDefaults = agentModel?.defaults as Record<string, unknown> | undefined;\n const modelCfg = agentDefaults?.model as Record<string, unknown> | undefined;\n const primary = typeof modelCfg?.primary === \"string\" ? modelCfg.primary : undefined;\n const fallbacks = Array.isArray(modelCfg?.fallbacks)\n ? (modelCfg.fallbacks as unknown[]).filter((m): m is string => typeof m === \"string\" && m.trim().length > 0)\n : [];\n // Models from agents.defaults.model with an unknown provider prefix (e.g. \"Local/S\", \"custom/X\")\n // would throw UnconfiguredProviderError when used, so filter them out here (issue #487).\n // Normalize provider keys to lowercase to match the lowercased prefix check at line 831 (issue #487 fix).\n const pluginProviders = Object.fromEntries(\n Object.entries((cfg.llm?.providers ?? {}) as Record<string, unknown>).map(([k, v]) => [k.toLowerCase(), v]),\n );\n // Extract gateway config for OAuth routing check (matches buildMultiProviderOpenAI logic)\n const { gatewayBaseUrl, gatewayToken } = extractGatewayConfig(cfg);\n // Normalize auth.order keys to lowercase so lookups match the lowercased prefix.\n const authOrder = cfg.auth?.order\n ? Object.fromEntries(Object.entries(cfg.auth.order).map(([k, v]) => [k.toLowerCase(), v]))\n : undefined;\n const canRoute = (m: string): boolean => {\n if (!m.includes(\"/\")) return true; // bare name — normalizeModelId() may rewrite to a prefixed form (e.g. gemini-*, claude-*, MiniMax-*)\n const prefix = m.trim().split(\"/\")[0].toLowerCase();\n // Check OAuth routing first (matches resolveClient logic at line 378)\n if (hasOAuthProfiles(authOrder?.[prefix], prefix) && gatewayBaseUrl && gatewayToken) return true;\n if (ROUTABLE_BUILTIN_PROVIDERS.has(prefix) || Object.hasOwn(pluginProviders, prefix)) return true;\n // Read-only env var check: safe even with user-supplied prefix since we only read env vars.\n // Mirrors resolveClient()'s <PREFIX>_API_KEY fallback (see resolveClient in setup/provider-router.ts).\n const envKey = process.env[`${prefix.toUpperCase()}_API_KEY`];\n return Boolean(envKey?.trim());\n };\n const gatewayModels = [primary, ...fallbacks]\n .filter((m): m is string => Boolean(m))\n .filter((m) => {\n if (canRoute(m)) return true;\n const prefix = m.trim().split(\"/\")[0];\n api.logger.warn?.(\n `memory-hybrid: skipping gateway model \"${m}\" from agents.defaults.model — ` +\n `provider \"${prefix}\" is not a known built-in and is not configured in llm.providers. ` +\n `To use this model configure llm.providers.${prefix.toLowerCase()} (apiKey and/or baseURL) in plugin config.`,\n );\n return false;\n });\n\n if (gatewayModels.length === 0 && [primary, ...fallbacks].some(Boolean)) {\n api.logger.warn?.(\n \"memory-hybrid: all models from agents.defaults.model were filtered out (unknown provider prefixes). \" +\n \"No LLM tiers auto-configured. Set llm.default explicitly or add provider entries to llm.providers.\",\n );\n }\n\n if (gatewayModels.length > 0) {\n // Deduplicate while preserving order\n const seen = new Set<string>();\n const uniqueModels = gatewayModels.filter((m) => {\n if (seen.has(m)) return false;\n seen.add(m);\n return true;\n });\n\n // Heuristic tier split based on model name keywords.\n // Nano: nano, mini, haiku, lite, turbo-mini — ultra-cheap for classify/HyDE/summarize\n // Heavy: pro, opus, o3, o1, large, ultra, gpt-5 — capable/expensive models (incl. GPT-5.4, Codex)\n // Light: flash, small — fast/cheap (but not nano-cheap)\n // Medium: everything else (sonnet, gpt-4o, etc.)\n // All ollama/* models are nano-tier (local = free, no API cost)\n const nano = uniqueModels.filter((m) => isNanoModel(m) && !isHeavyModel(m));\n const heavy = uniqueModels.filter((m) => isHeavyModel(m) && !isNanoModel(m));\n const light = uniqueModels.filter((m) => isLightModel(m) && !isNanoModel(m) && !isHeavyModel(m));\n const medium = uniqueModels.filter((m) => !isNanoModel(m) && !isLightModel(m) && !isHeavyModel(m));\n\n // default tier: agent order (primary then fallbacks) so reflection/general match what you set in openclaw.json\n const defaultIsHeavyOnly = uniqueModels.length > 0 && uniqueModels.every((m) => isHeavyModel(m));\n let defaultTier = [...uniqueModels];\n if (defaultIsHeavyOnly) {\n defaultTier = [...RECOMMENDED_CHEAP_FALLBACK, ...defaultTier];\n api.logger.info?.(\n \"memory-hybrid: agents.defaults.model is heavy-only; prepending cheap fallback for default tier so maintenance tasks use a cheaper model first. Set llm.default / llm.nano explicitly in plugin config to override.\",\n );\n }\n // heavy tier: capable first (heavy → medium → light) for distill/self-correction\n const heavyTier = [...heavy, ...medium, ...light];\n\n // nano: cheap first — never use Opus/heavy for classify/summarize. Use nano models if present; else when heavy-only use cheap fallback; else use light then medium from agent list.\n const nanoList =\n nano.length > 0\n ? [...nano, ...light, ...medium]\n : defaultIsHeavyOnly\n ? RECOMMENDED_CHEAP_FALLBACK\n : light.length > 0 || medium.length > 0\n ? [...light, ...medium]\n : [];\n\n cfg.llm = {\n ...(cfg.llm?.localAutoStart !== undefined ? { localAutoStart: cfg.llm.localAutoStart } : {}),\n ...(cfg.llm?.providers !== undefined ? { providers: cfg.llm.providers } : {}),\n ...(cfg.llm?.fallbackToDefault !== undefined ? { fallbackToDefault: cfg.llm.fallbackToDefault } : {}),\n ...(cfg.llm?.fallbackModel !== undefined ? { fallbackModel: cfg.llm.fallbackModel } : {}),\n default: defaultTier.length > 0 ? defaultTier : uniqueModels,\n heavy: heavyTier.length > 0 ? heavyTier : uniqueModels,\n ...(nanoList.length > 0 ? { nano: nanoList } : {}),\n _source: \"gateway\",\n };\n api.logger.info?.(\n `memory-hybrid: llm model tiers auto-derived from agents.defaults.model (default: ${(cfg.llm.default ?? []).slice(0, 3).join(\", \")}${(cfg.llm.default ?? []).length > 3 ? \"…\" : \"\"}${nanoList.length > 0 ? `; nano: ${(cfg.llm.nano ?? []).slice(0, 2).join(\", \")}` : \"\"})`,\n );\n }\n }\n // CostTracker — created early so proxy can instrument every chat.completions.create call (Issue #270).\n // Shares FactsDB's SQLite connection (same memory.db, avoids a second DB handle).\n // Gated on cfg.costTracking.enabled (default: true).\n const costTracker: CostTracker | null = cfg.costTracking?.enabled !== false ? new CostTracker(factsDb) : null;\n if (costTracker) {\n api.logger.info(\"memory-hybrid: LLM cost tracker initialized\");\n }\n\n // If Anthropic is in tier lists (e.g. from agents.defaults.model) but not yet in providers, use ANTHROPIC_API_KEY so verify --test-llm can test it.\n const defaultList = Array.isArray(cfg.llm?.default) ? cfg.llm.default : [];\n const heavyList = Array.isArray(cfg.llm?.heavy) ? cfg.llm.heavy : [];\n const hasAnthropicModel = (list: string[]) => list.some((m) => m.startsWith(\"anthropic/\") || m.startsWith(\"claude-\"));\n if (!prov.anthropic && (hasAnthropicModel(defaultList) || hasAnthropicModel(heavyList))) {\n const envKey = normalizeResolvedSecretValue(getEnv(\"ANTHROPIC_API_KEY\")) ?? \"\";\n if (envKey.length >= 10) {\n prov.anthropic = { apiKey: envKey };\n mergedProviderNames.push(\"anthropic\");\n api.logger.info?.(\n \"memory-hybrid: using ANTHROPIC_API_KEY for llm.providers.anthropic (verify --test-llm will test Anthropic models)\",\n );\n }\n }\n\n // If we merged providers, ensure at least one model from each is in the tier lists so they get tested and used as fallbacks.\n const hasModelFrom = (list: string[], prefix: string) =>\n list.some(\n (m) =>\n m.toLowerCase().startsWith(`${prefix}/`) ||\n (m.startsWith(\"claude-\") && prefix === \"anthropic\") ||\n (m.startsWith(\"gemini-\") && prefix === \"google\") ||\n (m.toLowerCase().startsWith(\"minimax-\") && prefix === \"minimax\"),\n );\n if (cfg.llm && mergedProviderNames.length > 0) {\n const defaultList = Array.isArray(cfg.llm.default) ? [...cfg.llm.default] : [];\n const heavyList = Array.isArray(cfg.llm.heavy) ? [...cfg.llm.heavy] : [];\n const knownDefault: Record<string, string> = {\n anthropic: \"anthropic/claude-sonnet-4-6\",\n openai: \"openai/gpt-4.1-mini\",\n google: \"google/gemini-2.5-flash\",\n minimax: \"minimax/MiniMax-Text-01\",\n };\n let appended = false;\n for (const name of mergedProviderNames) {\n if (hasModelFrom(defaultList, name) && hasModelFrom(heavyList, name)) continue;\n // Prefer the actual model IDs from gateway config over the hardcoded knownDefault fallback.\n // This ensures that if the gateway has e.g. minimax.models: [\"MiniMax-M2.5\"], we use that\n // instead of the hardcoded \"MiniMax-Text-01\".\n let defaultModel: string | null = null;\n const originalName = mergedProviderOriginalNames.get(name) ?? name;\n if (gwProviders && typeof (gwProviders as Record<string, unknown>)[originalName] === \"object\") {\n const gw = (gwProviders as Record<string, unknown>)[originalName] as Record<string, unknown>;\n // Define chat-compatibility filter (used for both models[] and defaultModel/model fields).\n // Skip non-chat entries (embeddings, transcription, TTS, image generation) so that\n // chatCompleteWithRetry is never routed through an incompatible model.\n const NON_CHAT_TYPES = new Set([\n \"embed\",\n \"embedding\",\n \"embeddings\",\n \"transcription\",\n \"speech-to-text\",\n \"text-to-speech\",\n \"tts\",\n \"image\",\n \"image-generation\",\n ]);\n const NON_CHAT_ID_RE = /\\bembed|whisper|\\btts\\b|dall-e|transcri|gpt-image|image-gen/i;\n const isChatEntry = (entry: unknown): boolean => {\n if (typeof entry === \"object\" && entry !== null) {\n const type = String((entry as Record<string, unknown>).type ?? \"\")\n .toLowerCase()\n .trim();\n if (type && NON_CHAT_TYPES.has(type)) return false;\n // If type is explicit and non-empty, trust it (unknown types → assume chat)\n if (type) return true;\n const id = String(\n (entry as Record<string, unknown>).id ?? (entry as Record<string, unknown>).name ?? \"\",\n ).toLowerCase();\n return !NON_CHAT_ID_RE.test(id);\n }\n if (typeof entry === \"string\") return !NON_CHAT_ID_RE.test(entry.toLowerCase());\n return false;\n };\n // Check models[] array first: iterate to find the first chat-compatible entry that\n // yields a non-empty trimmed model ID (skips entries with missing/empty id/name).\n if (Array.isArray(gw.models) && gw.models.length > 0) {\n for (const entry of gw.models) {\n if (!isChatEntry(entry)) continue;\n const modelId =\n typeof entry === \"string\"\n ? entry.trim()\n : String((entry as Record<string, unknown>).id ?? (entry as Record<string, unknown>).name ?? \"\").trim();\n if (modelId) {\n // Gateway may already use \"provider/model\" ids; avoid double prefix (e.g. azure-foundry/azure-foundry/model-router).\n defaultModel = modelId.includes(\"/\") ? modelId : `${name}/${modelId}`;\n break;\n }\n }\n }\n // Fall back to singular defaultModel or model field (also filter non-chat models)\n if (!defaultModel) {\n const gwModel =\n typeof gw.defaultModel === \"string\" ? gw.defaultModel : typeof gw.model === \"string\" ? gw.model : null;\n const trimmed = gwModel?.trim();\n if (trimmed && isChatEntry(gwModel)) {\n defaultModel = trimmed.includes(\"/\") ? trimmed : `${name}/${trimmed}`;\n }\n }\n }\n // Final fallback: use hardcoded knownDefault for well-known providers\n if (!defaultModel) defaultModel = knownDefault[name] ?? null;\n if (!defaultModel) continue;\n if (!hasModelFrom(defaultList, name)) {\n defaultList.push(defaultModel);\n appended = true;\n }\n const heavyModel = name === \"anthropic\" ? \"anthropic/claude-opus-4-6\" : defaultModel;\n if (!hasModelFrom(heavyList, name)) {\n heavyList.push(heavyModel);\n appended = true;\n }\n }\n if (appended) {\n (cfg.llm as Record<string, unknown>).default = defaultList;\n (cfg.llm as Record<string, unknown>).heavy = heavyList;\n gatewayLogInfoOnce(\n \"appended-gateway-models\",\n \"memory-hybrid: appended gateway provider models to llm.default/heavy so they are tested and used as fallbacks.\",\n api,\n );\n }\n }\n\n // Ollama auto-start: if any tier includes ollama/* models and localAutoStart is enabled,\n // attempt to launch `ollama serve` in the background when the server is not already running.\n // startOllamaIfNeeded deduplicates concurrent calls so only one spawn attempt runs at a time.\n startOllamaIfNeeded(cfg, api);\n\n // Chat/LLM client: multi-provider proxy that routes each model to the correct API.\n // google/* → Google Gemini OpenAI-compat API (uses distill.apiKey or llm.providers.google.apiKey)\n // openai/* or bare names → OpenAI API (uses embedding.apiKey or llm.providers.openai.apiKey)\n // ollama/* → local Ollama server (http://127.0.0.1:11434/v1 by default)\n // Other providers → require llm.providers.<provider>.apiKey + optionally baseURL\n const authBackoffStatePath = join(dirname(resolvedSqlitePath), \".auth-backoff.json\");\n const openai = buildMultiProviderOpenAI(cfg, api, costTracker, authBackoffStatePath);\n\n const {\n credentialsDb,\n wal,\n proposalsDb,\n identityReflectionStore,\n personaStateStore,\n eventLog,\n aliasDb,\n issueStore,\n workflowStore,\n crystallizationStore,\n toolProposalStore,\n verificationStore,\n provenanceService,\n apitapStore,\n } = installOptionalBootstrapServices({\n cfg,\n api,\n factsDb,\n resolvedSqlitePath,\n });\n\n const narrativesPath = join(dirname(resolvedSqlitePath), \"narratives.db\");\n const narrativesDb = new NarrativesDB(narrativesPath);\n api.logger.info(`memory-hybrid: narratives store initialized (${narrativesPath})`);\n\n // Report previously proposed categories, but do not load them as valid runtime categories.\n // Auto-classifier discovery is advisory only; operators must promote categories through config\n // before facts can be written under those labels.\n const discoveredPath = join(dirname(resolvedSqlitePath), \".discovered-categories.json\");\n if (existsSync(discoveredPath)) {\n try {\n const loaded = JSON.parse(readFileSync(discoveredPath, \"utf-8\")) as string[];\n if (Array.isArray(loaded) && loaded.length > 0) {\n api.logger.info(\n `memory-hybrid: ${loaded.length} proposed categories pending operator review (${discoveredPath})`,\n );\n }\n } catch (err) {\n api.logger.warn(`memory-hybrid: failed to inspect proposed categories: ${err}`);\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"inspect-proposed-categories\",\n subsystem: \"config\",\n });\n }\n }\n\n // Track embedding provider+model changes to trigger re-embedding (Issue #153).\n const currentEmbeddingMeta = {\n provider: cfg.embedding.provider,\n model: cfg.embedding.model,\n };\n let embeddingConfigChanged = false;\n try {\n const previousEmbeddingMeta = factsDb.getEmbeddingMeta();\n embeddingConfigChanged = Boolean(\n previousEmbeddingMeta &&\n (previousEmbeddingMeta.provider !== currentEmbeddingMeta.provider ||\n previousEmbeddingMeta.model !== currentEmbeddingMeta.model),\n );\n // When autoMigrate is enabled, still record the initial baseline on first run so future\n // changes can be detected. For subsequent runs with a config change, let runEmbeddingMaintenance\n // handle the meta update to avoid pre-updating before the migration service can detect the change.\n if (!cfg.embedding.autoMigrate && (!previousEmbeddingMeta || embeddingConfigChanged)) {\n factsDb.setEmbeddingMeta(currentEmbeddingMeta.provider, currentEmbeddingMeta.model);\n } else if (cfg.embedding.autoMigrate && !previousEmbeddingMeta && !embeddingConfigChanged) {\n factsDb.setEmbeddingMeta(currentEmbeddingMeta.provider, currentEmbeddingMeta.model);\n }\n } catch (err) {\n api.logger.warn(`memory-hybrid: failed to read embedding metadata (non-fatal): ${err}`);\n }\n\n // Health status tracking for verification checks\n const health: HealthStatus = {\n embeddingsOk: false,\n credentialsVaultOk: false,\n lastCheckTime: Date.now(),\n };\n\n // Prerequisite checks (async, don't block plugin start): verify keys and model access\n // Health status can be queried by tools to fail gracefully instead of throwing at runtime.\n const initialized = (async () => {\n if (isBootstrapSuperseded()) return;\n if (wal) {\n try {\n await wal.init();\n } catch (e) {\n if (isBootstrapSuperseded()) {\n api.logger.debug?.(\"memory-hybrid: WAL initialization skipped (registration superseded)\");\n return;\n }\n capturePluginError(e instanceof Error ? e : new Error(String(e)), {\n subsystem: \"wal\",\n operation: \"init\",\n phase: \"initialization\",\n });\n api.logger.warn(`memory-hybrid: WAL initialization failed: ${e}`);\n }\n }\n if (isBootstrapSuperseded()) return;\n try {\n await embeddings.embed(\"verify\");\n if (isBootstrapSuperseded()) return;\n health.embeddingsOk = true;\n const effectiveProvider = embeddings.activeProvider ?? cfg.embedding.provider;\n const modelForLog =\n effectiveProvider === \"openai\"\n ? formatOpenAiEmbeddingDisplayLabel(embeddings.modelName, cfg.embedding.endpoint)\n : embeddings.modelName;\n api.logger.info(\n effectiveProvider !== cfg.embedding.provider\n ? `memory-hybrid: embedding check OK (provider=${effectiveProvider}, model=${modelForLog} — using fallback; ${cfg.embedding.provider} unavailable)`\n : `memory-hybrid: embedding check OK (provider=${effectiveProvider}, model=${modelForLog})`,\n );\n } catch (e) {\n if (isBootstrapSuperseded()) {\n api.logger.debug?.(\"memory-hybrid: embedding check skipped (registration superseded)\");\n return;\n }\n const asErr = e instanceof Error ? e : new Error(String(e));\n if (!shouldSuppressEmbeddingError(asErr)) {\n capturePluginError(asErr, {\n subsystem: \"embeddings\",\n operation: \"init-verify\",\n phase: \"initialization\",\n backend: cfg.embedding.provider,\n });\n }\n const errText = String(e);\n const quota403 = is403QuotaOrRateLimitLike(e);\n const azure404 =\n typeof cfg.embedding.endpoint === \"string\" &&\n /\\.openai\\.azure\\.com/i.test(cfg.embedding.endpoint) &&\n (/404|not found/i.test(errText) || /Model not found/i.test(errText));\n const hint = quota403\n ? \"The provider returned 403 with quota/rate-limit signals (e.g. remaining-tokens=0, Retry-After). Wait for the window to reset or raise quota; your key may still be valid. Run 'openclaw hybrid-mem verify' for details.\"\n : cfg.embedding.provider === \"ollama\"\n ? `Ensure Ollama is running at ${cfg.embedding.endpoint ?? \"http://localhost:11434\"} and model '${cfg.embedding.model}' is pulled. Run 'openclaw hybrid-mem verify' for details.`\n : azure404\n ? 'Azure OpenAI embeddings use the deployment name as the API model id. In plugins.entries[\"openclaw-hybrid-memory\"].config.embedding set \"deployment\" to the exact embedding deployment name from Azure Portal (Resource → Model deployments), or rename the deployment to match embedding.model. Ensure embedding.endpoint is the resource URL (e.g. …/openai/v1). Run \\'openclaw hybrid-mem verify\\' for details.'\n : \"Set a valid embedding.apiKey in plugin config and ensure the model is accessible. Run 'openclaw hybrid-mem verify' for details.\";\n // Warn only for transient quota/rate-limit; keep error for bad keys, wrong model, geo 403, etc. (#941 review).\n const logEmbFailure = quota403 || is429OrWrapped(asErr) ? api.logger.warn : api.logger.error;\n const embTag = quota403 || is429OrWrapped(asErr) ? \"[embedding-quota]\" : \"[embedding-init]\";\n logEmbFailure(\n `${embTag} memory-hybrid: ⚠️ EMBEDDING CHECK FAILED (provider=${cfg.embedding.provider}) — ${String(e)}. ` +\n `Plugin will continue but semantic search will not work. ${hint}`,\n );\n }\n if (cfg.credentials.enabled && credentialsDb) {\n if (isBootstrapSuperseded()) return;\n try {\n const verifyVault = (): void => {\n const items = credentialsDb.list();\n if (items.length > 0) {\n const first = items[0];\n credentialsDb.get(first.service, first.type as CredentialType);\n }\n };\n verifyVault();\n if (isBootstrapSuperseded()) return;\n health.credentialsVaultOk = true;\n api.logger.info(\"memory-hybrid: credentials vault check OK\");\n } catch (e) {\n if (isBootstrapSuperseded()) {\n api.logger.debug?.(\"memory-hybrid: credentials vault check skipped (registration superseded)\");\n return;\n }\n capturePluginError(e instanceof Error ? e : new Error(String(e)), {\n subsystem: \"credentials\",\n operation: \"vault-verify\",\n phase: \"initialization\",\n backend: \"sqlite\",\n });\n api.logger.error(\n `memory-hybrid: ⚠️ CREDENTIALS VAULT CHECK FAILED — ${String(e)}. Plugin will continue but credential storage will not work. Check OPENCLAW_CRED_KEY (or credentials.encryptionKey). Wrong key or corrupted DB. Run 'openclaw hybrid-mem verify' for details.`,\n );\n }\n if (isBootstrapSuperseded()) return;\n // When vault is enabled: once per install, move existing credential facts into vault and redact from memory\n const migrationFlagPath = join(dirname(resolvedSqlitePath), CREDENTIAL_REDACTION_MIGRATION_FLAG);\n const clearMigrationFlagForRetry = async (reason: string): Promise<void> => {\n try {\n await unlink(migrationFlagPath);\n api.logger.debug?.(`memory-hybrid: cleared credential migration flag (${reason})`);\n } catch (err: unknown) {\n const errCode =\n typeof err === \"object\" && err !== null && \"code\" in err ? (err as { code?: unknown }).code : undefined;\n if (errCode === \"ENOENT\") return;\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"credentials\",\n operation: \"migration-flag-clear\",\n phase: \"initialization\",\n backend: \"sqlite\",\n });\n api.logger.warn(`memory-hybrid: failed to clear migration flag for retry: ${err}`);\n }\n };\n // Atomic flag creation to prevent race condition with multiple processes\n let shouldMigrate = false;\n try {\n const handle = await open(migrationFlagPath, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY);\n try {\n await handle.writeFile(\"1\", \"utf8\");\n shouldMigrate = true; // We won the race, proceed with migration\n } finally {\n await handle.close().catch(() => {\n /* ignore close errors */\n });\n }\n } catch (err: unknown) {\n const errCode =\n typeof err === \"object\" && err !== null && \"code\" in err ? (err as { code?: unknown }).code : undefined;\n if (isBootstrapSuperseded()) return;\n if (errCode === \"EEXIST\") {\n // Another process already created the flag - skip migration\n shouldMigrate = false;\n } else {\n shouldMigrate = false;\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"credentials\",\n operation: \"migration-flag-create\",\n phase: \"initialization\",\n backend: \"sqlite\",\n });\n api.logger.warn(`memory-hybrid: failed to create migration flag (skipping migration): ${err}`);\n }\n }\n if (shouldMigrate) {\n if (isBootstrapSuperseded()) {\n await clearMigrationFlagForRetry(\"registration superseded before migration\");\n return;\n }\n try {\n const result = await migrateCredentialsToVault({\n factsDb,\n vectorDb,\n embeddings,\n credentialsDb,\n aliasDb,\n migrationFlagPath,\n markDone: false, // Flag already created atomically above\n });\n if (isBootstrapSuperseded()) {\n await clearMigrationFlagForRetry(\"registration superseded after migration\");\n api.logger.debug?.(\n \"memory-hybrid: credential migration finished after supersession; suppressing stale logs\",\n );\n return;\n }\n if (result.migrated > 0) {\n api.logger.info(`memory-hybrid: migrated ${result.migrated} credential(s) from memory into vault`);\n }\n if (result.errors.length > 0) {\n api.logger.warn(\n `memory-hybrid: credential migration had ${result.errors.length} error(s): ${result.errors.join(\"; \")}`,\n );\n await clearMigrationFlagForRetry(\"credential migration completed with errors\");\n }\n } catch (e) {\n if (isBootstrapSuperseded()) {\n await clearMigrationFlagForRetry(\"registration superseded during migration\");\n const isDbClosed = isDbClosedError(e);\n if (!isDbClosed) {\n // Non-DB-closed error during superseded bootstrap: flag was set but bootstrap\n // was superseded before or during migration. Clear flag so retry can run fresh.\n api.logger.debug?.(\n \"memory-hybrid: credential migration error during superseded bootstrap cleared for retry\",\n );\n } else {\n api.logger.debug?.(\"memory-hybrid: credential migration skipped (registration superseded)\");\n }\n return;\n }\n capturePluginError(e instanceof Error ? e : new Error(String(e)), {\n subsystem: \"credentials\",\n operation: \"migration-to-vault\",\n phase: \"initialization\",\n backend: \"sqlite\",\n });\n api.logger.warn(`memory-hybrid: credential migration failed: ${e}`);\n }\n }\n }\n })().catch((err: unknown) => {\n if (isBootstrapSuperseded()) return;\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"init\",\n operation: \"async-initialization\",\n phase: \"initialization\",\n });\n api.logger.warn(`memory-hybrid: async initialization encountered an error: ${err}`);\n });\n\n // autoMigrate path: use the embedding-migration service when autoMigrate=true (Issue #153).\n // Runs asynchronously so it does not block plugin start.\n if (cfg.embedding.autoMigrate && embeddingConfigChanged) {\n void (async () => {\n try {\n await runEmbeddingMaintenance({\n factsDb,\n vectorDb,\n embeddings,\n currentProvider: cfg.embedding.provider,\n currentModel: cfg.embedding.model,\n autoMigrate: true,\n batchSize: cfg.embedding.batchSize,\n logger: {\n info: (msg) => api.logger.info(msg),\n warn: (msg) => api.logger.warn(msg),\n },\n });\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"autoMigrate-embedding\",\n subsystem: \"embeddings\",\n });\n api.logger.warn(`memory-hybrid: autoMigrate embedding run failed: ${err}`);\n }\n })();\n }\n\n // Schema validation + re-embedding (Issue #128 + #153).\n // Runs asynchronously so it does not block plugin start.\n // vectorDb.count() triggers lazy initialization, after which wasRepaired is set.\n // Skip this block when autoMigrate is enabled and config changed — runEmbeddingMaintenance handles it.\n if ((cfg.vector.autoRepair || embeddingConfigChanged) && !(cfg.embedding.autoMigrate && embeddingConfigChanged)) {\n void (async () => {\n const reembedProgressPath = join(dirname(resolvedSqlitePath), \".reembed-progress.json\");\n try {\n if (cfg.vector.autoRepair || embeddingConfigChanged) {\n await vectorDb.count(); // triggers doInitialize() → validateOrRepairSchema()\n }\n\n // Check if there's an incomplete re-embedding from a previous run\n let needsReembedding = embeddingConfigChanged || (cfg.vector.autoRepair && vectorDb.wasRepaired);\n let completedIds = new Set<string>();\n\n if (!needsReembedding && existsSync(reembedProgressPath)) {\n try {\n const progress = JSON.parse(readFileSync(reembedProgressPath, \"utf-8\")) as {\n completedIds: string[];\n total: number;\n };\n if (progress.completedIds.length < progress.total) {\n needsReembedding = true;\n completedIds = new Set(progress.completedIds);\n api.logger.info(\n `memory-hybrid: resuming incomplete re-embedding from previous run (${progress.completedIds.length}/${progress.total} completed)`,\n );\n }\n } catch {\n // Ignore invalid progress file\n }\n }\n\n if (needsReembedding) {\n const initialGeneration = vectorDb.getCloseGeneration();\n api.logger.info(\n embeddingConfigChanged\n ? `memory-hybrid: embedding config changed (${currentEmbeddingMeta.provider}/${currentEmbeddingMeta.model}) — re-embedding existing facts...`\n : vectorDb.wasRepaired\n ? \"memory-hybrid: VectorDB was auto-repaired — re-embedding existing facts from SQLite...\"\n : \"memory-hybrid: resuming re-embedding after hot reload...\",\n );\n const facts = factsDb.getAll({ includeSuperseded: false });\n let reembedded = completedIds.size;\n\n for (const fact of facts) {\n if (completedIds.has(fact.id)) {\n continue;\n }\n if (vectorDb.getCloseGeneration() !== initialGeneration) {\n // Save progress before aborting\n try {\n const progress = {\n completedIds: Array.from(completedIds),\n total: facts.length,\n };\n const { writeFileSync } = await import(\"node:fs\");\n writeFileSync(reembedProgressPath, JSON.stringify(progress), \"utf-8\");\n } catch {\n // Ignore write errors\n }\n api.logger.info(\n `memory-hybrid: re-embedding aborted (VectorDB closed during hot reload) — ${reembedded}/${facts.length} facts re-embedded`,\n );\n return;\n }\n try {\n const vec = await embeddings.embed(fact.text);\n const isDuplicate = await vectorDb.hasDuplicate(vec);\n if (!isDuplicate) {\n await vectorDb.store({\n id: fact.id,\n text: fact.text,\n vector: vec,\n importance: fact.importance ?? 0.5,\n category: fact.category,\n });\n factsDb.setEmbeddingModel(fact.id, embeddings.modelName);\n }\n completedIds.add(fact.id);\n reembedded++;\n } catch {\n // Skip individual failures — best-effort re-embedding\n }\n }\n\n // Clean up progress file on successful completion\n try {\n const { unlinkSync } = await import(\"node:fs\");\n if (existsSync(reembedProgressPath)) {\n unlinkSync(reembedProgressPath);\n }\n } catch {\n // Ignore cleanup errors\n }\n\n api.logger.info(`memory-hybrid: re-embedded ${reembedded}/${facts.length} facts during re-embedding pass`);\n }\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"vector-reembed\",\n subsystem: \"vector\",\n });\n api.logger.warn(`memory-hybrid: re-embedding failed: ${err}`);\n }\n })();\n }\n\n // Mark the VectorDB as a persistent long-lived singleton connection (#581).\n // This prevents fragile session refcounting from accidentally closing the shared\n // connection via removeSession() — the connection is only closed by close() (gateway shutdown).\n vectorDb.setPersistent();\n\n return {\n factsDb,\n edictStore,\n vectorDb,\n embeddings,\n embeddingRegistry,\n openai,\n credentialsDb,\n wal,\n proposalsDb,\n identityReflectionStore,\n personaStateStore,\n eventLog,\n narrativesDb,\n aliasDb,\n issueStore,\n workflowStore,\n crystallizationStore,\n toolProposalStore,\n verificationStore,\n provenanceService,\n costTracker,\n resolvedLancePath,\n resolvedSqlitePath,\n health,\n initialized,\n apitapStore,\n };\n}\n\n/**\n * Closes old database instances before reinitializing.\n * Used when the plugin is reloaded (e.g., on SIGUSR1 signal).\n */\nexport function closeOldDatabases(context: {\n factsDb?: FactsDB | null;\n edictStore?: EdictStore | null;\n narrativesDb?: NarrativesDB | null;\n vectorDb?: VectorDB | null;\n credentialsDb?: CredentialsDB | null;\n proposalsDb?: ProposalsDB | null;\n identityReflectionStore?: import(\"../backends/identity-reflection-store.js\").IdentityReflectionStore | null;\n personaStateStore?: import(\"../backends/persona-state-store.js\").PersonaStateStore | null;\n eventLog?: EventLog | null;\n aliasDb?: AliasDB | null;\n eventBus?: import(\"../backends/event-bus.js\").EventBus | null;\n issueStore?: IssueStore | null;\n workflowStore?: WorkflowStore | null;\n crystallizationStore?: CrystallizationStore | null;\n toolProposalStore?: ToolProposalStore | null;\n verificationStore?: VerificationStore | null;\n provenanceService?: ProvenanceService | null;\n learningsDb?: import(\"../backends/learnings-db.js\").LearningsDB | null;\n apitapStore?: ApitapStore | null;\n auditStore?: import(\"../backends/audit-store.js\").AuditStore | null;\n agentHealthStore?: import(\"../backends/agent-health-store.js\").AgentHealthStore | null;\n}): void {\n const {\n factsDb,\n edictStore,\n narrativesDb,\n vectorDb,\n credentialsDb,\n proposalsDb,\n identityReflectionStore,\n personaStateStore,\n eventLog,\n aliasDb,\n eventBus,\n issueStore,\n workflowStore,\n crystallizationStore,\n toolProposalStore,\n verificationStore,\n provenanceService,\n learningsDb,\n apitapStore,\n auditStore,\n agentHealthStore,\n } = context;\n\n invalidateClusterCache();\n\n // BaseSqliteStore-derived stores: call permanentClose() so liveDb throws on any\n // subsequent access rather than silently reopening the old SQLite handle.\n // This is the primary fix for issue #1550 (duplicate handles after re-registration).\n if (typeof factsDb?.permanentClose === \"function\") {\n try {\n factsDb.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"factsDb\",\n });\n }\n }\n if (typeof edictStore?.permanentClose === \"function\") {\n try {\n edictStore.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"edictStore\",\n });\n }\n }\n // VectorDB is LanceDB-based (not a BaseSqliteStore); its close() is already terminal.\n if (typeof vectorDb?.close === \"function\") {\n try {\n vectorDb.close();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"vectorDb\",\n });\n }\n }\n if (credentialsDb) {\n try {\n credentialsDb.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"credentialsDb\",\n });\n }\n }\n if (narrativesDb) {\n try {\n narrativesDb.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"narrativesDb\",\n });\n }\n }\n if (proposalsDb) {\n try {\n proposalsDb.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"proposalsDb\",\n });\n }\n }\n if (identityReflectionStore) {\n try {\n identityReflectionStore.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"identityReflectionStore\",\n });\n }\n }\n if (personaStateStore) {\n try {\n personaStateStore.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"personaStateStore\",\n });\n }\n }\n if (eventLog) {\n try {\n eventLog.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"eventLog\",\n });\n }\n }\n // AliasDB has its own reference-counted close logic (not a BaseSqliteStore).\n if (aliasDb) {\n try {\n aliasDb.close();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"aliasDb\",\n });\n }\n }\n // EventBus.close() is already terminal (sets _terminallyClosed = true).\n if (eventBus) {\n try {\n eventBus.close();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"eventBus\",\n });\n }\n }\n if (issueStore) {\n try {\n issueStore.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"issueStore\",\n });\n }\n }\n if (workflowStore) {\n try {\n workflowStore.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"workflowStore\",\n });\n }\n }\n if (crystallizationStore) {\n try {\n crystallizationStore.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"crystallizationStore\",\n });\n }\n }\n if (toolProposalStore) {\n try {\n toolProposalStore.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"toolProposalStore\",\n });\n }\n }\n // VerificationStore has its own connection-sharing logic (not a BaseSqliteStore).\n if (verificationStore) {\n try {\n verificationStore.close();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"verificationStore\",\n });\n }\n }\n if (provenanceService) {\n try {\n provenanceService.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"provenanceService\",\n });\n }\n }\n if (learningsDb) {\n try {\n learningsDb.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"learningsDb\",\n });\n }\n }\n if (apitapStore) {\n try {\n apitapStore.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"apitapStore\",\n });\n }\n }\n if (auditStore) {\n try {\n auditStore.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"auditStore\",\n });\n }\n }\n if (agentHealthStore) {\n try {\n agentHealthStore.permanentClose();\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"close-databases\",\n subsystem: \"agentHealthStore\",\n });\n }\n }\n}\n"],"mappings":"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"}