@remnic/core 9.3.732 → 9.3.734
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-boundary.d.ts +10 -10
- package/dist/access-boundary.js +9 -9
- package/dist/access-cli.js +25 -23
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +10 -10
- package/dist/access-http.js +14 -14
- package/dist/access-mcp.d.ts +10 -10
- package/dist/access-mcp.js +13 -13
- package/dist/access-operations-batch.js +11 -11
- package/dist/access-operations.d.ts +10 -10
- package/dist/access-operations.js +12 -12
- package/dist/{access-service-Byoe3HsT.d.ts → access-service-rjFfmfKB.d.ts} +4 -4
- package/dist/access-service.d.ts +10 -10
- package/dist/access-service.js +8 -8
- package/dist/access-surface-catalog.d.ts +10 -10
- package/dist/action-confidence.d.ts +1 -1
- package/dist/active-memory-bridge.d.ts +1 -1
- package/dist/active-memory-bridge.js +3 -2
- package/dist/active-recall.d.ts +1 -1
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +9 -9
- package/dist/briefing.d.ts +1 -1
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer.d.ts +1 -1
- package/dist/calibration.d.ts +1 -1
- package/dist/capabilities.d.ts +97 -2
- package/dist/capabilities.js +11 -3
- package/dist/{catalog-DM1nk7cM.d.ts → catalog-DHYXzM4-.d.ts} +2 -2
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-24D66MMN.js → chunk-2L5RTVMO.js} +7 -4
- package/dist/chunk-2L5RTVMO.js.map +1 -0
- package/dist/{chunk-KQYGNGON.js → chunk-3QETM5NG.js} +6 -3
- package/dist/chunk-3QETM5NG.js.map +1 -0
- package/dist/{chunk-ZQUAVZNG.js → chunk-54RCE5Z3.js} +7 -4
- package/dist/chunk-54RCE5Z3.js.map +1 -0
- package/dist/{chunk-NOU77OHX.js → chunk-5DIKZKOD.js} +2 -2
- package/dist/{chunk-CGPHMNL4.js → chunk-5OYHJIJN.js} +10 -6
- package/dist/chunk-5OYHJIJN.js.map +1 -0
- package/dist/{chunk-LUCARK4W.js → chunk-6U7TES2M.js} +29 -28
- package/dist/chunk-6U7TES2M.js.map +1 -0
- package/dist/{chunk-FFUCCKPN.js → chunk-7FPJFCXL.js} +10 -7
- package/dist/chunk-7FPJFCXL.js.map +1 -0
- package/dist/{chunk-PMAQRUN4.js → chunk-CILX2XW7.js} +5 -2
- package/dist/chunk-CILX2XW7.js.map +1 -0
- package/dist/{chunk-ZVHRSR2R.js → chunk-ET5HXSQL.js} +6 -3
- package/dist/chunk-ET5HXSQL.js.map +1 -0
- package/dist/{chunk-KSJCXXOU.js → chunk-FAGERSH2.js} +6 -3
- package/dist/chunk-FAGERSH2.js.map +1 -0
- package/dist/{chunk-FYWUNVFZ.js → chunk-IDIXGGDN.js} +6 -6
- package/dist/{chunk-CX77GNMB.js → chunk-IWMGBNXY.js} +6 -3
- package/dist/chunk-IWMGBNXY.js.map +1 -0
- package/dist/{chunk-GGL34GCW.js → chunk-IZLTOS5L.js} +7 -4
- package/dist/chunk-IZLTOS5L.js.map +1 -0
- package/dist/{chunk-HHNSLPX7.js → chunk-K7PAILHO.js} +10 -9
- package/dist/chunk-K7PAILHO.js.map +1 -0
- package/dist/{chunk-UZYLX7M6.js → chunk-LV32K4OP.js} +9 -6
- package/dist/chunk-LV32K4OP.js.map +1 -0
- package/dist/{chunk-HJWQJUKQ.js → chunk-NDYQIN6C.js} +3 -3
- package/dist/{chunk-DKT3X5C3.js → chunk-PEF2XOIV.js} +7 -4
- package/dist/chunk-PEF2XOIV.js.map +1 -0
- package/dist/{chunk-646B5ERJ.js → chunk-PKO5NJ65.js} +51 -48
- package/dist/chunk-PKO5NJ65.js.map +1 -0
- package/dist/{chunk-QZHF4BWN.js → chunk-Q5LGXWNG.js} +6 -6
- package/dist/{chunk-ESF7TRYJ.js → chunk-SHJGBAIW.js} +37 -2
- package/dist/{chunk-ESF7TRYJ.js.map → chunk-SHJGBAIW.js.map} +1 -1
- package/dist/{chunk-O4ZIBPIW.js → chunk-T7CGPTFU.js} +3 -3
- package/dist/{chunk-PLBIPT6I.js → chunk-TJSQHO4Q.js} +7 -4
- package/dist/chunk-TJSQHO4Q.js.map +1 -0
- package/dist/{chunk-6TUWSUUD.js → chunk-UF3N7IRP.js} +26 -24
- package/dist/chunk-UF3N7IRP.js.map +1 -0
- package/dist/{chunk-P3VJCTVE.js → chunk-UH3NYOHN.js} +4 -3
- package/dist/chunk-UH3NYOHN.js.map +1 -0
- package/dist/{chunk-J6BH2OBA.js → chunk-UK6U5C3N.js} +8 -5
- package/dist/chunk-UK6U5C3N.js.map +1 -0
- package/dist/{chunk-OTQE66IX.js → chunk-V5OVSGB6.js} +6 -3
- package/dist/chunk-V5OVSGB6.js.map +1 -0
- package/dist/{chunk-H3MB3F62.js → chunk-WHQ2JB35.js} +4 -3
- package/dist/chunk-WHQ2JB35.js.map +1 -0
- package/dist/{chunk-NIZQH6AU.js → chunk-WTTVFSCO.js} +8 -7
- package/dist/chunk-WTTVFSCO.js.map +1 -0
- package/dist/{chunk-OUITHS6V.js → chunk-Z7J3OAPR.js} +357 -325
- package/dist/chunk-Z7J3OAPR.js.map +1 -0
- package/dist/{cli-Dt-tuiYH.d.ts → cli-XVpmSoQs.d.ts} +3 -3
- package/dist/cli.d.ts +11 -11
- package/dist/cli.js +20 -20
- package/dist/compounding/engine.d.ts +3 -2
- package/dist/compounding/engine.js +2 -1
- package/dist/compounding/preference-consolidator.d.ts +1 -1
- package/dist/compression-optimizer.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/consolidation-provenance-check.d.ts +1 -1
- package/dist/consolidation-undo.d.ts +1 -1
- package/dist/contradiction/index.d.ts +2 -2
- package/dist/contradiction/index.js +2 -1
- package/dist/{contradiction-scan-HWGEOUDS.js → contradiction-scan-OUHMCUBT.js} +3 -2
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/day-summary.d.ts +1 -1
- package/dist/delinearize.d.ts +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -1
- package/dist/direct-answer.d.ts +1 -1
- package/dist/embedding-fallback.d.ts +1 -1
- package/dist/embedding-fallback.js +2 -2
- package/dist/enrichment/index.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +1 -1
- package/dist/entity-retrieval.js +2 -1
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +9 -9
- package/dist/explicit-capture.js +2 -1
- package/dist/extraction-faithfulness.d.ts +1 -1
- package/dist/extraction-judge-telemetry.d.ts +1 -1
- package/dist/extraction-judge-training.d.ts +1 -1
- package/dist/extraction-judge.d.ts +1 -1
- package/dist/extraction.d.ts +1 -1
- package/dist/extraction.js +3 -3
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/{first-start-migration-OOR57AYR.js → first-start-migration-W4U6XDKI.js} +7 -6
- package/dist/first-start-migration-W4U6XDKI.js.map +1 -0
- package/dist/graph-dashboard-diff.d.ts +1 -1
- package/dist/graph-dashboard-key.d.ts +1 -1
- package/dist/graph-dashboard-parser.d.ts +1 -1
- package/dist/graph-edge-reinforcement.d.ts +1 -1
- package/dist/graph-snapshot.d.ts +1 -1
- package/dist/graph.d.ts +1 -1
- package/dist/identity-continuity.d.ts +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/index.d.ts +12 -12
- package/dist/index.js +43 -43
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/tools.d.ts +1 -1
- package/dist/lifecycle.d.ts +1 -1
- package/dist/live-connectors-runner.d.ts +1 -1
- package/dist/local-llm.d.ts +1 -1
- package/dist/local-llm.js +2 -1
- package/dist/local-model-endpoint.d.ts +1 -1
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/mcp-memory-inspector-app.d.ts +10 -10
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-provenance.d.ts +1 -1
- package/dist/memory-worth-outcomes.d.ts +1 -1
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +2 -2
- package/dist/namespaces/migrate.js +6 -6
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/principal.js +2 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/search.js +4 -4
- package/dist/namespaces/storage.d.ts +2 -2
- package/dist/namespaces/storage.js +2 -1
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +1 -1
- package/dist/operator-toolkit.js +11 -11
- package/dist/orchestration/compression-guideline-coordinator.d.ts +1 -1
- package/dist/orchestration/maintenance.d.ts +2 -2
- package/dist/orchestration/maintenance.js +6 -5
- package/dist/{orchestrator-B4KjaOtY.d.ts → orchestrator-BXi-gadS.d.ts} +66 -5
- package/dist/orchestrator.d.ts +5 -5
- package/dist/orchestrator.js +20 -18
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/provenance.d.ts +1 -1
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +1 -1
- package/dist/recall-disclosure-escalation.d.ts +1 -1
- package/dist/recall-explain-renderer.d.ts +1 -1
- package/dist/recall-planner-llm.d.ts +1 -1
- package/dist/recall-state.d.ts +1 -1
- package/dist/recall-tag-filter.d.ts +1 -1
- package/dist/recall-xray-cli.d.ts +1 -1
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray.d.ts +1 -1
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/retrieval-agents.d.ts +1 -1
- package/dist/retrieval-tiers.d.ts +1 -1
- package/dist/routing/engine.d.ts +1 -1
- package/dist/routing/store.d.ts +1 -1
- package/dist/schemas.d.ts +22 -22
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/embed-helper.js +2 -2
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/factory.js +3 -3
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.js +3 -3
- package/dist/search/lancedb-backend.d.ts +1 -1
- package/dist/search/meilisearch-backend.d.ts +1 -1
- package/dist/search/noop-backend.d.ts +1 -1
- package/dist/search/orama-backend.d.ts +1 -1
- package/dist/search/port.d.ts +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/{semantic-SLAa_prH.d.ts → semantic-DJR8_DMQ.d.ts} +1 -1
- package/dist/{semantic-consolidation-CstTvHPo.d.ts → semantic-consolidation-DeL5grLx.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/shared-context/manager.d.ts +1 -1
- package/dist/signal.d.ts +1 -1
- package/dist/storage.d.ts +1 -1
- package/dist/summarizer.d.ts +1 -1
- package/dist/summarizer.js +3 -2
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/temporal-supersession.d.ts +1 -1
- package/dist/temporal-validity.d.ts +1 -1
- package/dist/threading.d.ts +1 -1
- package/dist/tier-migration.d.ts +1 -1
- package/dist/tier-routing.d.ts +1 -1
- package/dist/{tier-stats-3LYQ3VV5.js → tier-stats-LSM35HZY.js} +5 -2
- package/dist/tier-stats-LSM35HZY.js.map +1 -0
- package/dist/topics.d.ts +1 -1
- package/dist/transcript.d.ts +1 -1
- package/dist/transfer/types.d.ts +12 -12
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-VkxElCHR.d.ts → types-CpFz51Pv.d.ts} +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/package.json +2 -2
- package/src/access-service.ts +42 -37
- package/src/active-memory-bridge.ts +2 -1
- package/src/admin/admin-surfaces.ts +2 -1
- package/src/capabilities.test.ts +178 -0
- package/src/capabilities.ts +197 -0
- package/src/cli.ts +13 -9
- package/src/compounding/engine.ts +4 -3
- package/src/contradiction/contradiction-scan.ts +4 -3
- package/src/embedding-fallback.ts +5 -2
- package/src/entity-retrieval.ts +3 -2
- package/src/explicit-capture.ts +2 -1
- package/src/extraction.ts +6 -3
- package/src/local-llm.ts +4 -3
- package/src/maintenance/first-start-migration.ts +6 -3
- package/src/maintenance/namespace-maintenance-fanout.ts +2 -1
- package/src/maintenance/namespace-planner.ts +4 -3
- package/src/maintenance/tier-stats.ts +2 -1
- package/src/namespaces/catalog.ts +2 -1
- package/src/namespaces/migrate.ts +2 -1
- package/src/namespaces/principal.ts +6 -5
- package/src/namespaces/scope-profiles.ts +2 -1
- package/src/namespaces/search.ts +2 -1
- package/src/namespaces/storage.ts +4 -3
- package/src/operator-toolkit.ts +19 -18
- package/src/orchestration/maintenance.ts +8 -4
- package/src/orchestration/semantic-consolidation-coordinator.ts +454 -0
- package/src/orchestration/tier-migration-coordinator.ts +5 -4
- package/src/orchestrator.ts +78 -417
- package/src/scopes/scope-plan.ts +3 -2
- package/src/search/embed-helper.ts +5 -2
- package/src/search/factory.ts +9 -6
- package/src/summarizer.ts +3 -2
- package/dist/chunk-24D66MMN.js.map +0 -1
- package/dist/chunk-646B5ERJ.js.map +0 -1
- package/dist/chunk-6TUWSUUD.js.map +0 -1
- package/dist/chunk-CGPHMNL4.js.map +0 -1
- package/dist/chunk-CX77GNMB.js.map +0 -1
- package/dist/chunk-DKT3X5C3.js.map +0 -1
- package/dist/chunk-FFUCCKPN.js.map +0 -1
- package/dist/chunk-GGL34GCW.js.map +0 -1
- package/dist/chunk-H3MB3F62.js.map +0 -1
- package/dist/chunk-HHNSLPX7.js.map +0 -1
- package/dist/chunk-J6BH2OBA.js.map +0 -1
- package/dist/chunk-KQYGNGON.js.map +0 -1
- package/dist/chunk-KSJCXXOU.js.map +0 -1
- package/dist/chunk-LUCARK4W.js.map +0 -1
- package/dist/chunk-NIZQH6AU.js.map +0 -1
- package/dist/chunk-OTQE66IX.js.map +0 -1
- package/dist/chunk-OUITHS6V.js.map +0 -1
- package/dist/chunk-P3VJCTVE.js.map +0 -1
- package/dist/chunk-PLBIPT6I.js.map +0 -1
- package/dist/chunk-PMAQRUN4.js.map +0 -1
- package/dist/chunk-UZYLX7M6.js.map +0 -1
- package/dist/chunk-ZQUAVZNG.js.map +0 -1
- package/dist/chunk-ZVHRSR2R.js.map +0 -1
- package/dist/first-start-migration-OOR57AYR.js.map +0 -1
- package/dist/tier-stats-3LYQ3VV5.js.map +0 -1
- /package/dist/{chunk-NOU77OHX.js.map → chunk-5DIKZKOD.js.map} +0 -0
- /package/dist/{chunk-FYWUNVFZ.js.map → chunk-IDIXGGDN.js.map} +0 -0
- /package/dist/{chunk-HJWQJUKQ.js.map → chunk-NDYQIN6C.js.map} +0 -0
- /package/dist/{chunk-QZHF4BWN.js.map → chunk-Q5LGXWNG.js.map} +0 -0
- /package/dist/{chunk-O4ZIBPIW.js.map → chunk-T7CGPTFU.js.map} +0 -0
- /package/dist/{contradiction-scan-HWGEOUDS.js.map → contradiction-scan-OUHMCUBT.js.map} +0 -0
package/dist/capabilities.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as PluginConfig } from './types-
|
|
1
|
+
import { P as PluginConfig } from './types-CpFz51Pv.js';
|
|
2
2
|
import './types-gb_SNtjR.js';
|
|
3
3
|
import './message-parts/index.js';
|
|
4
4
|
|
|
@@ -220,5 +220,100 @@ type CreationMemoryConfigProjection = Pick<PluginConfig, "creationMemoryEnabled"
|
|
|
220
220
|
* recall.
|
|
221
221
|
*/
|
|
222
222
|
declare function resolveCreationMemoryCapabilities(config: CreationMemoryConfigProjection): CreationMemoryCapabilitySet;
|
|
223
|
+
/**
|
|
224
|
+
* Frozen projection of namespace feature gates (issue #1523 batch 5).
|
|
225
|
+
*
|
|
226
|
+
* Every field is `readonly boolean`. Composition lives ONLY in
|
|
227
|
+
* {@link resolveNamespaceCapabilities}.
|
|
228
|
+
*/
|
|
229
|
+
interface NamespaceCapabilitySet {
|
|
230
|
+
/** `namespacesEnabled` — multi-namespace system master switch. */
|
|
231
|
+
readonly namespaces: boolean;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Config projection consumed by {@link resolveNamespaceCapabilities}.
|
|
235
|
+
*/
|
|
236
|
+
type NamespaceConfigProjection = Pick<PluginConfig, "namespacesEnabled">;
|
|
237
|
+
/**
|
|
238
|
+
* Resolve the {@link NamespaceCapabilitySet} from parsed config.
|
|
239
|
+
*
|
|
240
|
+
* Call this ONCE at operation entry and thread the result down. The flag is a
|
|
241
|
+
* non-optional boolean so the projection is a pure pass-through.
|
|
242
|
+
*/
|
|
243
|
+
declare function resolveNamespaceCapabilities(config: NamespaceConfigProjection): NamespaceCapabilitySet;
|
|
244
|
+
/**
|
|
245
|
+
* Frozen projection of QMD feature gates (issue #1523 batch 6).
|
|
246
|
+
*
|
|
247
|
+
* Every field is `readonly boolean`. Composition lives ONLY in
|
|
248
|
+
* {@link resolveQmdCapabilities}.
|
|
249
|
+
*/
|
|
250
|
+
interface QmdCapabilitySet {
|
|
251
|
+
/** `qmdEnabled` — QMD tiered-memory master switch. */
|
|
252
|
+
readonly qmd: boolean;
|
|
253
|
+
/** `qmdTierMigrationEnabled` — automatic tier promotion/demotion. */
|
|
254
|
+
readonly qmdTierMigration: boolean;
|
|
255
|
+
/** `qmdTierAutoBackfillEnabled` — backfill stale tier entries. */
|
|
256
|
+
readonly qmdTierAutoBackfill: boolean;
|
|
257
|
+
/** `qmdAutoEmbedEnabled` — auto-embed documents on write. */
|
|
258
|
+
readonly qmdAutoEmbed: boolean;
|
|
259
|
+
/** `qmdMaintenanceEnabled` — QMD maintenance pass runner. */
|
|
260
|
+
readonly qmdMaintenance: boolean;
|
|
261
|
+
/** `qmdColdTierEnabled` — cold-tier storage. */
|
|
262
|
+
readonly qmdColdTier: boolean;
|
|
263
|
+
/** `qmdDaemonEnabled` — background QMD daemon. */
|
|
264
|
+
readonly qmdDaemon: boolean;
|
|
265
|
+
/** `qmdTierParityGraphEnabled` — tier parity graph. */
|
|
266
|
+
readonly qmdTierParityGraph: boolean;
|
|
267
|
+
/** `qmdQueryRerankEnabled` — QMD query reranking. */
|
|
268
|
+
readonly qmdQueryRerank: boolean;
|
|
269
|
+
/** `qmdIntentHintsEnabled` — QMD intent hint extraction. */
|
|
270
|
+
readonly qmdIntentHints: boolean;
|
|
271
|
+
/** `qmdExplainEnabled` — QMD explain output. */
|
|
272
|
+
readonly qmdExplain: boolean;
|
|
273
|
+
/** `qmdAutoUpgradeEnabled` — QMD auto-upgrade tiers. */
|
|
274
|
+
readonly qmdAutoUpgrade: boolean;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Config projection consumed by {@link resolveQmdCapabilities}.
|
|
278
|
+
*/
|
|
279
|
+
type QmdConfigProjection = Pick<PluginConfig, "qmdEnabled" | "qmdTierMigrationEnabled" | "qmdTierAutoBackfillEnabled" | "qmdAutoEmbedEnabled" | "qmdMaintenanceEnabled" | "qmdColdTierEnabled" | "qmdDaemonEnabled" | "qmdTierParityGraphEnabled" | "qmdQueryRerankEnabled" | "qmdIntentHintsEnabled" | "qmdExplainEnabled" | "qmdAutoUpgradeEnabled">;
|
|
280
|
+
/**
|
|
281
|
+
* Resolve the {@link QmdCapabilitySet} from parsed config.
|
|
282
|
+
*
|
|
283
|
+
* Call this ONCE at operation entry and thread the result down. Eleven flags
|
|
284
|
+
* are non-optional booleans (pure pass-through); `qmdColdTierEnabled` is
|
|
285
|
+
* optional and coerced with `=== true` (matching the pre-migration call sites).
|
|
286
|
+
*/
|
|
287
|
+
declare function resolveQmdCapabilities(config: QmdConfigProjection): QmdCapabilitySet;
|
|
288
|
+
/**
|
|
289
|
+
* Frozen projection of identity-continuity feature gates (issue #1523 batch 6).
|
|
290
|
+
*/
|
|
291
|
+
interface IdentityContinuityCapabilitySet {
|
|
292
|
+
/** `identityContinuityEnabled` — identity-continuity master switch. */
|
|
293
|
+
readonly identityContinuity: boolean;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Config projection consumed by {@link resolveIdentityContinuityCapabilities}.
|
|
297
|
+
*/
|
|
298
|
+
type IdentityContinuityConfigProjection = Pick<PluginConfig, "identityContinuityEnabled">;
|
|
299
|
+
/**
|
|
300
|
+
* Resolve the {@link IdentityContinuityCapabilitySet} from parsed config.
|
|
301
|
+
*/
|
|
302
|
+
declare function resolveIdentityContinuityCapabilities(config: IdentityContinuityConfigProjection): IdentityContinuityCapabilitySet;
|
|
303
|
+
/**
|
|
304
|
+
* Frozen projection of local-LLM feature gates (issue #1523 batch 6).
|
|
305
|
+
*/
|
|
306
|
+
interface LocalLlmCapabilitySet {
|
|
307
|
+
/** `localLlmEnabled` — local (on-device) LLM master switch. */
|
|
308
|
+
readonly localLlm: boolean;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Config projection consumed by {@link resolveLocalLlmCapabilities}.
|
|
312
|
+
*/
|
|
313
|
+
type LocalLlmConfigProjection = Pick<PluginConfig, "localLlmEnabled">;
|
|
314
|
+
/**
|
|
315
|
+
* Resolve the {@link LocalLlmCapabilitySet} from parsed config.
|
|
316
|
+
*/
|
|
317
|
+
declare function resolveLocalLlmCapabilities(config: LocalLlmConfigProjection): LocalLlmCapabilitySet;
|
|
223
318
|
|
|
224
|
-
export { type AccessSetupCapabilitySet, type AccessSetupConfigProjection, type CapabilitySet, type CreationMemoryCapabilitySet, type CreationMemoryConfigProjection, type GraphConstructionCapabilitySet, type GraphConstructionConfigProjection, type IndexingCapabilitySet, type IndexingConfigProjection, type MemoryLifecycleCapabilitySet, type MemoryLifecycleConfigProjection, resolveAccessSetupCapabilities, resolveCapabilities, resolveCreationMemoryCapabilities, resolveGraphConstructionCapabilities, resolveIndexingCapabilities, resolveMemoryLifecycleCapabilities };
|
|
319
|
+
export { type AccessSetupCapabilitySet, type AccessSetupConfigProjection, type CapabilitySet, type CreationMemoryCapabilitySet, type CreationMemoryConfigProjection, type GraphConstructionCapabilitySet, type GraphConstructionConfigProjection, type IdentityContinuityCapabilitySet, type IdentityContinuityConfigProjection, type IndexingCapabilitySet, type IndexingConfigProjection, type LocalLlmCapabilitySet, type LocalLlmConfigProjection, type MemoryLifecycleCapabilitySet, type MemoryLifecycleConfigProjection, type NamespaceCapabilitySet, type NamespaceConfigProjection, type QmdCapabilitySet, type QmdConfigProjection, resolveAccessSetupCapabilities, resolveCapabilities, resolveCreationMemoryCapabilities, resolveGraphConstructionCapabilities, resolveIdentityContinuityCapabilities, resolveIndexingCapabilities, resolveLocalLlmCapabilities, resolveMemoryLifecycleCapabilities, resolveNamespaceCapabilities, resolveQmdCapabilities };
|
package/dist/capabilities.js
CHANGED
|
@@ -3,16 +3,24 @@ import {
|
|
|
3
3
|
resolveCapabilities,
|
|
4
4
|
resolveCreationMemoryCapabilities,
|
|
5
5
|
resolveGraphConstructionCapabilities,
|
|
6
|
+
resolveIdentityContinuityCapabilities,
|
|
6
7
|
resolveIndexingCapabilities,
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
resolveLocalLlmCapabilities,
|
|
9
|
+
resolveMemoryLifecycleCapabilities,
|
|
10
|
+
resolveNamespaceCapabilities,
|
|
11
|
+
resolveQmdCapabilities
|
|
12
|
+
} from "./chunk-SHJGBAIW.js";
|
|
9
13
|
import "./chunk-PZ5AY32C.js";
|
|
10
14
|
export {
|
|
11
15
|
resolveAccessSetupCapabilities,
|
|
12
16
|
resolveCapabilities,
|
|
13
17
|
resolveCreationMemoryCapabilities,
|
|
14
18
|
resolveGraphConstructionCapabilities,
|
|
19
|
+
resolveIdentityContinuityCapabilities,
|
|
15
20
|
resolveIndexingCapabilities,
|
|
16
|
-
|
|
21
|
+
resolveLocalLlmCapabilities,
|
|
22
|
+
resolveMemoryLifecycleCapabilities,
|
|
23
|
+
resolveNamespaceCapabilities,
|
|
24
|
+
resolveQmdCapabilities
|
|
17
25
|
};
|
|
18
26
|
//# sourceMappingURL=capabilities.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as PluginConfig } from './types-
|
|
1
|
+
import { P as PluginConfig } from './types-CpFz51Pv.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Rebuildable namespace catalog (issue #1499).
|
|
@@ -427,4 +427,4 @@ declare class NamespaceCatalog {
|
|
|
427
427
|
private rewriteUnchained;
|
|
428
428
|
}
|
|
429
429
|
|
|
430
|
-
export { NamespaceCatalog as N, type
|
|
430
|
+
export { NamespaceCatalog as N, type NamespaceRecord as a, type NamespaceKind as b, type NamespaceCatalogFilter as c, type NamespaceCatalogRebuildResult as d, type NamespaceCatalogSkippedRoot as e, type NamespaceDiscoverySource as f, type NamespaceTouchMetadata as g };
|
|
@@ -2,7 +2,7 @@ import { CausalChainIndex } from './causal-chain.js';
|
|
|
2
2
|
import { ConsolidatedPreference } from './compounding/preference-consolidator.js';
|
|
3
3
|
import './causal-trajectory.js';
|
|
4
4
|
import './objective-state.js';
|
|
5
|
-
import './types-
|
|
5
|
+
import './types-CpFz51Pv.js';
|
|
6
6
|
import './types-gb_SNtjR.js';
|
|
7
7
|
import './message-parts/index.js';
|
|
8
8
|
import './lcm/engine.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { G as GatewayConfig, j as AgentPersonaModelConfig, P as PluginConfig, g as MemoryFile } from './types-
|
|
1
|
+
import { G as GatewayConfig, j as AgentPersonaModelConfig, P as PluginConfig, g as MemoryFile } from './types-CpFz51Pv.js';
|
|
2
2
|
import { RolloutSummaryInput, MaterializeResult } from './connectors/codex-materialize.js';
|
|
3
3
|
import './types-gb_SNtjR.js';
|
|
4
4
|
import './message-parts/index.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { GraphEdge } from './graph.js';
|
|
2
2
|
import { CausalTrajectoryRecord } from './causal-trajectory.js';
|
|
3
3
|
import './capabilities.js';
|
|
4
|
-
import './types-
|
|
4
|
+
import './types-CpFz51Pv.js';
|
|
5
5
|
import './types-gb_SNtjR.js';
|
|
6
6
|
import './message-parts/index.js';
|
|
7
7
|
import './objective-state.js';
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
launchProcessSync
|
|
3
3
|
} from "./chunk-O75CRYGF.js";
|
|
4
|
+
import {
|
|
5
|
+
resolveLocalLlmCapabilities
|
|
6
|
+
} from "./chunk-SHJGBAIW.js";
|
|
4
7
|
import {
|
|
5
8
|
mergeEnv,
|
|
6
9
|
readEnvVar
|
|
@@ -697,7 +700,7 @@ var LocalLlmClient = class _LocalLlmClient {
|
|
|
697
700
|
}
|
|
698
701
|
async runChatCompletionRequest(messages, options, queueMeta) {
|
|
699
702
|
log.debug(
|
|
700
|
-
`local LLM chatCompletion: localLlmEnabled=${this.config.
|
|
703
|
+
`local LLM chatCompletion: localLlmEnabled=${resolveLocalLlmCapabilities(this.config).localLlm}, model=${this.config.localLlmModel}`
|
|
701
704
|
);
|
|
702
705
|
const operation = options.operation ?? "unspecified";
|
|
703
706
|
const startedAtMs = Date.now();
|
|
@@ -1012,7 +1015,7 @@ var LocalLlmClient = class _LocalLlmClient {
|
|
|
1012
1015
|
* Make a chat completion request to local LLM
|
|
1013
1016
|
*/
|
|
1014
1017
|
async chatCompletion(messages, options = {}) {
|
|
1015
|
-
if (!this.config.
|
|
1018
|
+
if (!resolveLocalLlmCapabilities(this.config).localLlm) {
|
|
1016
1019
|
log.debug("local LLM: disabled, returning null");
|
|
1017
1020
|
return null;
|
|
1018
1021
|
}
|
|
@@ -1054,7 +1057,7 @@ var LocalLlmClient = class _LocalLlmClient {
|
|
|
1054
1057
|
* Try local LLM first, fallback to cloud provider if configured
|
|
1055
1058
|
*/
|
|
1056
1059
|
async withFallback(localOperation, fallbackOperation, operationName) {
|
|
1057
|
-
if (this.config.
|
|
1060
|
+
if (resolveLocalLlmCapabilities(this.config).localLlm) {
|
|
1058
1061
|
const localResult = await localOperation();
|
|
1059
1062
|
if (localResult !== null) {
|
|
1060
1063
|
log.debug(`${operationName}: used local LLM`);
|
|
@@ -1073,4 +1076,4 @@ var LocalLlmClient = class _LocalLlmClient {
|
|
|
1073
1076
|
export {
|
|
1074
1077
|
LocalLlmClient
|
|
1075
1078
|
};
|
|
1076
|
-
//# sourceMappingURL=chunk-
|
|
1079
|
+
//# sourceMappingURL=chunk-2L5RTVMO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/local-llm.ts"],"sourcesContent":["import { log } from \"./logger.js\";\nimport type { PluginConfig } from \"./types.js\";\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport type { ModelRegistry } from \"./model-registry.js\";\nimport { launchProcessSync } from \"./runtime/child-process.js\";\nimport { mergeEnv, readEnvVar } from \"./runtime/env.js\";\nimport { resolveLocalLlmCapabilities } from \"./capabilities.js\";\n\n/** Trim trailing slash characters without backtracking regex. */\nfunction trimTrailingSlashes(s: string): string {\n let end = s.length;\n while (end > 0 && s[end - 1] === \"/\") end--;\n return s.substring(0, end);\n}\n\nfunction stripTrailingV1Path(s: string): string {\n return s.endsWith(\"/v1\") ? s.slice(0, -3) : s;\n}\n\nfunction explicitPortFromUrl(s: string): number | null {\n try {\n const parsed = new URL(s);\n if (!parsed.port) return null;\n const port = Number(parsed.port);\n return Number.isInteger(port) ? port : null;\n } catch {\n return null;\n }\n}\n\nfunction isObjectRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction isLlamaCppPropsResponse(value: unknown): boolean {\n return (\n isObjectRecord(value) &&\n isObjectRecord(value.default_generation_settings) &&\n typeof value.total_slots === \"number\" &&\n (\n typeof value.model_path === \"string\" ||\n typeof value.chat_template === \"string\" ||\n typeof value.build_info === \"string\"\n )\n );\n}\n\nfunction isLlamaCppModelsResponse(value: unknown): boolean {\n if (!isObjectRecord(value) || !Array.isArray(value.data)) {\n return false;\n }\n return value.data.some((entry) => {\n if (!isObjectRecord(entry)) return false;\n if (entry.owned_by === \"llamacpp\") return true;\n if (typeof entry.id === \"string\" && entry.id.endsWith(\".gguf\")) return true;\n const meta = entry.meta;\n return (\n isObjectRecord(meta) &&\n (\"n_ctx_train\" in meta || \"n_params\" in meta || \"vocab_type\" in meta)\n );\n });\n}\n\nfunction isLmStudioApiV1ModelsResponse(value: unknown): boolean {\n if (!isObjectRecord(value) || !Array.isArray(value.models)) {\n return false;\n }\n return value.models.some((entry) => {\n if (!isObjectRecord(entry)) return false;\n return (\n typeof entry.key === \"string\" &&\n typeof entry.display_name === \"string\" &&\n (\n typeof entry.format === \"string\" ||\n typeof entry.max_context_length === \"number\" ||\n Array.isArray(entry.loaded_instances)\n )\n );\n });\n}\n\nfunction isLmStudioApiV0ModelsResponse(value: unknown): boolean {\n if (!isObjectRecord(value) || !Array.isArray(value.data)) {\n return false;\n }\n return value.data.some((entry) => {\n if (!isObjectRecord(entry)) return false;\n return (\n typeof entry.id === \"string\" &&\n typeof entry.publisher === \"string\" &&\n (\n typeof entry.compatibility_type === \"string\" ||\n typeof entry.max_context_length === \"number\" ||\n typeof entry.state === \"string\"\n )\n );\n });\n}\n\nfunction isLmStudioNativeModelsResponse(value: unknown): boolean {\n return isLmStudioApiV1ModelsResponse(value) || isLmStudioApiV0ModelsResponse(value);\n}\n\n/**\n * Local LLM client for OpenAI-compatible endpoints (LM Studio, Ollama, MLX, etc.)\n *\n * Based on openclaw-tactician's provider detection patterns for consistency.\n * Provides privacy-preserving, cost-effective LLM operations with\n * graceful fallback to cloud providers when local LLM is unavailable.\n */\nexport type LocalLlmType = \"lmstudio\" | \"ollama\" | \"mlx\" | \"vllm\" | \"llamacpp\" | \"generic\";\n\n/**\n * Backends known to honor `chat_template_kwargs: { enable_thinking: false }`\n * on OpenAI-compatible `/v1/chat/completions`. LM Studio, vLLM, and\n * llama.cpp forward this field to the jinja chat template, where thinking-capable\n * models (Qwen 3.5, Gemma 4, DeepSeek) suppress reasoning tokens.\n *\n * Strict OpenAI-compatible backends (standard OpenAI, Azure OpenAI, some\n * proxies) reject unknown request fields with 400 — which trips the\n * `localLlm400*` cooldown path. `LocalLlmClient` therefore only injects\n * the kwarg when the detected backend is in this set; unknown / `generic`\n * / `ollama` / `mlx` fail open (no injection, no 400 risk). Issue #548.\n */\nconst THINKING_COMPATIBLE_BACKENDS: ReadonlySet<LocalLlmType> = new Set([\n \"lmstudio\",\n \"vllm\",\n \"llamacpp\",\n]);\n\nconst THINKING_SUPPRESSED_OPERATIONS: ReadonlySet<string> = new Set([\n \"extraction\",\n \"extraction-judge\",\n \"extraction-faithfulness\",\n \"contradiction-judge\",\n \"contradiction_verification\",\n \"link_suggestion\",\n \"memory_summarization\",\n \"proactive_extraction\",\n \"lcm-summarize\",\n \"day_summary\",\n \"hourly_summary\",\n \"hourly_summary_extended\",\n]);\n\ninterface LocalServerConfig {\n type: LocalLlmType;\n defaultPort: number;\n healthEndpoint: string;\n modelsEndpoint: string;\n detectFn: (response: unknown) => boolean;\n}\n\nconst LOCAL_SERVERS: LocalServerConfig[] = [\n {\n type: \"ollama\",\n defaultPort: 11434,\n healthEndpoint: \"/\",\n modelsEndpoint: \"/api/tags\",\n detectFn: (resp) => typeof resp === \"string\" && resp.includes(\"Ollama\"),\n },\n {\n type: \"llamacpp\",\n defaultPort: 8080,\n healthEndpoint: \"/health\",\n modelsEndpoint: \"/v1/models\",\n detectFn: (resp) => isObjectRecord(resp) && resp.status === \"ok\",\n },\n {\n type: \"mlx\",\n defaultPort: 8080,\n healthEndpoint: \"/v1/models\",\n modelsEndpoint: \"/v1/models\",\n detectFn: (resp) => isObjectRecord(resp) && Array.isArray(resp.data),\n },\n {\n type: \"lmstudio\",\n defaultPort: 1234,\n healthEndpoint: \"/v1/models\",\n modelsEndpoint: \"/v1/models\",\n detectFn: (resp) => isObjectRecord(resp) && Array.isArray(resp.data),\n },\n {\n type: \"vllm\",\n defaultPort: 8000,\n healthEndpoint: \"/health\",\n modelsEndpoint: \"/v1/models\",\n detectFn: (resp) => resp === \"\" || (isObjectRecord(resp) && !(\"status\" in resp)),\n },\n];\n\nfunction orderedLocalServers(configuredBaseUrl: string): LocalServerConfig[] {\n const configuredPort = explicitPortFromUrl(configuredBaseUrl);\n if (configuredPort === null) return LOCAL_SERVERS;\n const matching = LOCAL_SERVERS.filter(\n (serverConfig) => serverConfig.defaultPort === configuredPort,\n );\n if (matching.length === 0) return LOCAL_SERVERS;\n const matchingTypes = new Set(matching.map((serverConfig) => serverConfig.type));\n return [\n ...matching,\n ...LOCAL_SERVERS.filter((serverConfig) => !matchingTypes.has(serverConfig.type)),\n ];\n}\n\nexport interface LocalModelInfo {\n id: string;\n contextWindow?: number;\n maxTokens?: number;\n}\n\nexport type LocalLlmRequestPriority = \"recall-critical\" | \"background\";\n\ninterface LocalLlmChatCompletionOptions {\n temperature?: number;\n maxTokens?: number;\n responseFormat?: { type: string };\n timeoutMs?: number;\n operation?: string;\n forceDisableThinking?: boolean;\n priority?: LocalLlmRequestPriority;\n}\n\ninterface LocalLlmQueuedRequest {\n messages: Array<{ role: string; content: string }>;\n options: LocalLlmChatCompletionOptions;\n priority: LocalLlmRequestPriority;\n enqueuedAtMs: number;\n resolve: (value: LocalLlmChatCompletionResult | null) => void;\n}\n\ninterface LocalLlmChatCompletionResult {\n content: string;\n usage?: { promptTokens: number; completionTokens: number; totalTokens: number };\n}\n\nconst LOCAL_LLM_GLOBAL_BACKEND_STATE = \"__openclawEngramLocalLlmBackendState\";\n\ntype LocalLlmBackendState = {\n untilMs: number;\n reason: string;\n};\nexport class LocalLlmClient {\n private config: PluginConfig;\n private isAvailable: boolean | null = null;\n private lastHealthCheck: number = 0;\n private detectedType: LocalLlmType | null = null;\n private cachedModelInfo: LocalModelInfo | null = null;\n private cachedLmsContext: number | null = null;\n private lastLmsCheck: number = 0;\n private consecutive400s: number = 0;\n private cooldownUntilMs: number = 0;\n private modelRegistry?: ModelRegistry;\n private _disableThinking: boolean = false;\n private readonly requestQueues: Record<LocalLlmRequestPriority, LocalLlmQueuedRequest[]> = {\n \"recall-critical\": [],\n background: [],\n };\n private readonly queueProcessing = new Set<LocalLlmRequestPriority>();\n private queueDrainScheduled: boolean = false;\n private static readonly HEALTH_CHECK_INTERVAL_MS = 60000; // 1 minute\n private static readonly LMS_CACHE_INTERVAL_MS = 30000; // 30 seconds\n\n constructor(config: PluginConfig, modelRegistry?: ModelRegistry) {\n this.config = config;\n this.modelRegistry = modelRegistry;\n }\n\n /**\n * Request thinking/reasoning suppression on the next chat completion.\n *\n * When `true`, the client will inject\n * `chat_template_kwargs: { enable_thinking: false }` into the request\n * body — **but only when the detected backend is known to support it**\n * (LM Studio, vLLM; see `THINKING_COMPATIBLE_BACKENDS`). Strict\n * OpenAI-compat backends reject unknown fields with 400; on those the\n * client fails open (thinking runs normally). This is the safe\n * default for Remnic extraction-style operations: measurable latency\n * win on thinking-capable backends, zero risk on others. Consolidation\n * operations keep thinking enabled unless explicitly added to\n * `THINKING_SUPPRESSED_OPERATIONS`. Issues #548 and #979.\n */\n set disableThinking(value: boolean) {\n this._disableThinking = value;\n }\n\n private resolveHomeDir(): string {\n return this.config.localLlmHomeDir || readEnvVar(\"HOME\") || os.homedir();\n }\n\n private buildRequestHeaders(base: Record<string, string> = {}): Record<string, string> {\n const headers: Record<string, string> = {\n ...base,\n ...(this.config.localLlmHeaders ?? {}),\n };\n if (this.config.localLlmApiKey && this.config.localLlmAuthHeader !== false) {\n headers.Authorization = `Bearer ${this.config.localLlmApiKey}`;\n }\n return headers;\n }\n\n private isAbortError(err: unknown): boolean {\n if (!err || typeof err !== \"object\") return false;\n const maybe = err as { name?: string; message?: string };\n return (\n maybe.name === \"AbortError\" ||\n maybe.message === \"This operation was aborted\" ||\n maybe.message === \"The operation was aborted\"\n );\n }\n\n /**\n * Set the ModelRegistry for caching detected capabilities\n */\n setModelRegistry(registry: ModelRegistry): void {\n this.modelRegistry = registry;\n }\n\n /**\n * Get the detected server type (null if not detected)\n */\n getDetectedType(): LocalLlmType | null {\n return this.detectedType;\n }\n\n private getBackendKey(): string {\n return trimTrailingSlashes(\n this.config.localLlmUrl.replace(\"localhost\", \"127.0.0.1\"),\n ).replace(/\\/v1$/, \"\");\n }\n\n private getGlobalBackendState(): Map<string, LocalLlmBackendState> {\n const globalAny = globalThis as typeof globalThis & {\n [LOCAL_LLM_GLOBAL_BACKEND_STATE]?: Map<string, LocalLlmBackendState>;\n };\n if (!globalAny[LOCAL_LLM_GLOBAL_BACKEND_STATE]) {\n globalAny[LOCAL_LLM_GLOBAL_BACKEND_STATE] = new Map();\n }\n return globalAny[LOCAL_LLM_GLOBAL_BACKEND_STATE];\n }\n\n private getTrippedBackendState(now: number): LocalLlmBackendState | null {\n const state = this.getGlobalBackendState().get(this.getBackendKey()) ?? null;\n if (!state) return null;\n if (state.untilMs <= now) {\n this.getGlobalBackendState().delete(this.getBackendKey());\n this.lastHealthCheck = 0;\n return null;\n }\n return state;\n }\n\n private markBackendUnavailable(reason: string, durationMs: number): void {\n const normalizedReason = this.normalizeBackendTripReason(reason);\n if (durationMs > 0) {\n const untilMs = Date.now() + durationMs;\n this.getGlobalBackendState().set(this.getBackendKey(), { untilMs, reason: normalizedReason });\n } else {\n this.getGlobalBackendState().delete(this.getBackendKey());\n }\n this.isAvailable = false;\n this.lastHealthCheck = 0;\n log.warn(\n `local LLM backend unavailable for ${durationMs}ms: model=${this.config.localLlmModel} reason=${normalizedReason}`,\n );\n }\n\n private extractNonRecoverableBackendReason(reason: string): string | null {\n const match = reason.match(\n /Failed to load model|Library not loaded|different Team IDs|code signature|llm_engine_mlx_amphibian/i,\n );\n return match?.[0] ?? null;\n }\n\n private extractNonRecoverableBackendReasonFromErrorText(errorText: string): string | null {\n const directReason = this.extractNonRecoverableBackendReason(errorText);\n if (directReason) return directReason;\n try {\n const parsed = JSON.parse(errorText) as { error?: { message?: string } };\n return this.extractNonRecoverableBackendReason(parsed?.error?.message ?? \"\");\n } catch {\n return null;\n }\n }\n\n private normalizeBackendTripReason(reason: string): string {\n const cleaned = reason.replace(/\\s+/g, \" \").replace(/^[-:–—\\s]+/, \"\").trim();\n if (!cleaned) return \"unknown local backend failure\";\n return cleaned.length > 160 ? `${cleaned.slice(0, 157)}...` : cleaned;\n }\n\n /**\n * Fetch with timeout for health checks\n */\n private async fetchWithTimeout(\n url: string,\n timeoutMs: number = 2000,\n headers?: Record<string, string>,\n ): Promise<{ ok: boolean; data: unknown; status: number | null }> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const response = await fetch(url, {\n signal: controller.signal,\n headers: this.buildRequestHeaders({ Accept: \"application/json\", ...(headers ?? {}) }),\n });\n clearTimeout(timeout);\n\n if (!response.ok) {\n return { ok: false, data: null, status: response.status };\n }\n\n const contentType = response.headers.get(\"content-type\");\n if (contentType?.includes(\"application/json\")) {\n return { ok: true, data: await response.json(), status: response.status };\n } else {\n return { ok: true, data: await response.text(), status: response.status };\n }\n } catch (err) {\n clearTimeout(timeout);\n return { ok: false, data: null, status: null };\n }\n }\n\n private async probeLmStudioNativeModels(\n probeBaseUrl: string,\n ): Promise<{ matched: boolean; unauthorized: boolean }> {\n let unauthorized = false;\n for (const endpoint of [\"/api/v1/models\", \"/api/v0/models\"]) {\n const probe = await this.fetchWithTimeout(`${probeBaseUrl}${endpoint}`);\n if (probe.ok && isLmStudioNativeModelsResponse(probe.data)) {\n return { matched: true, unauthorized };\n }\n if (probe.status === 401 || probe.status === 403) {\n unauthorized = true;\n }\n }\n return { matched: false, unauthorized };\n }\n\n /**\n * Check if local LLM is available\n * Uses 127.0.0.1 instead of localhost to avoid DNS issues (consistent with tactician)\n */\n async checkAvailability(): Promise<boolean> {\n // Cache health check results for 1 minute\n const now = Date.now();\n const trippedState = this.getTrippedBackendState(now);\n if (trippedState) {\n this.isAvailable = false;\n this.lastHealthCheck = 0;\n log.info(\n `local LLM availability: backend circuit open for ${Math.max(0, trippedState.untilMs - now)}ms (${trippedState.reason})`,\n );\n return false;\n }\n if (this.isAvailable !== null && now - this.lastHealthCheck < LocalLlmClient.HEALTH_CHECK_INTERVAL_MS) {\n return this.isAvailable;\n }\n\n // Normalize URL - replace localhost with 127.0.0.1, remove trailing slashes.\n // Probe server-native endpoints from the server root even when users configure\n // the OpenAI-compatible `/v1` base URL for chat completions.\n const configuredBaseUrl = trimTrailingSlashes(\n this.config.localLlmUrl.replace(\"localhost\", \"127.0.0.1\"),\n );\n const probeBaseUrl = stripTrailingV1Path(configuredBaseUrl);\n let sawUnauthorizedProbe = false;\n\n // Try to detect which server type is running\n for (const serverConfig of orderedLocalServers(configuredBaseUrl)) {\n const healthUrl = `${probeBaseUrl}${serverConfig.healthEndpoint}`;\n log.debug(`checking ${serverConfig.type} at ${healthUrl}`);\n\n const result = await this.fetchWithTimeout(healthUrl);\n if (result.ok && serverConfig.detectFn(result.data)) {\n if (serverConfig.type === \"mlx\") {\n const lmStudioProbe = await this.probeLmStudioNativeModels(probeBaseUrl);\n if (lmStudioProbe.unauthorized) {\n sawUnauthorizedProbe = true;\n }\n if (lmStudioProbe.matched) {\n this.isAvailable = true;\n this.detectedType = \"lmstudio\";\n this.lastHealthCheck = now;\n log.info(`detected lmstudio at ${configuredBaseUrl}`);\n return true;\n }\n }\n if (serverConfig.type === \"llamacpp\") {\n let sawLlamaCppSignal = false;\n const propsProbe = await this.fetchWithTimeout(`${probeBaseUrl}/props`);\n if (propsProbe.ok && isLlamaCppPropsResponse(propsProbe.data)) {\n sawLlamaCppSignal = true;\n }\n if (propsProbe.status === 401 || propsProbe.status === 403) {\n sawUnauthorizedProbe = true;\n }\n\n const modelsUrl = `${probeBaseUrl}${serverConfig.modelsEndpoint}`;\n const modelsProbe = await this.fetchWithTimeout(modelsUrl);\n if (modelsProbe.ok && isLlamaCppModelsResponse(modelsProbe.data)) {\n sawLlamaCppSignal = true;\n }\n if (modelsProbe.status === 401 || modelsProbe.status === 403) {\n sawUnauthorizedProbe = true;\n continue;\n }\n\n const authConfigured =\n Boolean(this.config.localLlmApiKey) &&\n this.config.localLlmAuthHeader !== false;\n if (!sawLlamaCppSignal || (authConfigured && !modelsProbe.ok)) {\n continue;\n }\n }\n this.isAvailable = true;\n this.detectedType = serverConfig.type;\n this.lastHealthCheck = now;\n log.info(`detected ${serverConfig.type} at ${configuredBaseUrl}`);\n return true;\n }\n if (result.status === 401 || result.status === 403) {\n sawUnauthorizedProbe = true;\n }\n }\n\n // Generic check if specific detection failed\n try {\n const modelsUrl = `${probeBaseUrl}/v1/models`;\n const result = await this.fetchWithTimeout(modelsUrl);\n if (result.ok) {\n this.isAvailable = true;\n this.detectedType = \"generic\";\n this.lastHealthCheck = now;\n log.info(`detected generic OpenAI-compatible server at ${configuredBaseUrl}`);\n return true;\n }\n if (result.status === 401 || result.status === 403) {\n sawUnauthorizedProbe = true;\n }\n } catch {\n // Fall through to unavailable\n }\n\n this.isAvailable = false;\n this.detectedType = null;\n this.lastHealthCheck = now;\n if (sawUnauthorizedProbe) {\n log.warn(\n `local LLM availability probe was unauthorized at ${configuredBaseUrl}; verify localLlmApiKey and localLlmAuthHeader settings`,\n );\n }\n log.debug(\"local LLM not available at\", configuredBaseUrl);\n return false;\n }\n\n /**\n * Try to get context window from LM Studio settings.json as fallback.\n * This reads the defaultContextLength setting which is what LM Studio uses\n * when loading models without explicit context configuration.\n */\n private getContextFromLmStudioSettings(): number | null {\n try {\n const homeDir = this.resolveHomeDir();\n const settingsPath = `${homeDir}/.cache/lm-studio/settings.json`;\n\n if (!fs.existsSync(settingsPath)) {\n log.debug(`LM Studio settings: file not found at ${settingsPath}`);\n return null;\n }\n\n const content = fs.readFileSync(settingsPath, \"utf-8\");\n const settings = JSON.parse(content) as {\n defaultContextLength?: {\n type?: string;\n value?: number;\n };\n };\n\n if (settings.defaultContextLength?.value) {\n const contextWindow = settings.defaultContextLength.value;\n log.debug(`LM Studio settings: found default context length: ${contextWindow}`);\n return contextWindow;\n }\n\n return null;\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n log.debug(`LM Studio settings: failed to read - ${errorMsg}`);\n return null;\n }\n }\n\n /**\n * Try to get context window from LMS CLI (LM Studio specific).\n * Uses --json flag for reliable parsing.\n * Returns null if LMS CLI is not available or model not found.\n */\n private getContextFromLmsCli(modelId: string): number | null {\n try {\n // Check if lms CLI exists in common locations.\n // HOME may be absent in launchd environments, so prefer the resolved helper.\n const homeDir = this.resolveHomeDir();\n const lmsPaths = [\n this.config.localLmsCliPath || \"\",\n `${homeDir}/.cache/lm-studio/bin/lms`,\n \"/usr/local/bin/lms\",\n \"/opt/homebrew/bin/lms\",\n ];\n\n const lmsPath = lmsPaths.find((p) => p.length > 0 && fs.existsSync(p));\n if (!lmsPath) {\n log.debug(`LMS CLI: not found in standard locations (checked: ${lmsPaths.join(\", \")})`);\n return null;\n }\n\n // Run lms ps --json to get loaded models with context\n // Use spawnSync with shell and explicit PATH to ensure lms can find its dependencies\n log.debug(`LMS CLI: running: ${lmsPath} ps --json`);\n const existingPath = readEnvVar(\"PATH\") || \"\";\n const result = launchProcessSync(lmsPath, [\"ps\", \"--json\"], {\n encoding: \"utf-8\",\n timeout: 5000,\n shell: false, // Don't use shell for JSON output - more reliable\n env: mergeEnv({\n PATH: `${this.config.localLmsBinDir || `${homeDir}/.cache/lm-studio/bin`}:/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin:${existingPath}`,\n HOME: homeDir,\n }),\n });\n\n if (result.error) {\n log.debug(`LMS CLI: spawn error - ${result.error.message}`);\n return null;\n }\n\n if (result.stderr && result.stderr.trim()) {\n log.debug(`LMS CLI: stderr - ${result.stderr.slice(0, 200)}`);\n }\n\n const output = result.stdout || \"\";\n if (!output.trim()) {\n log.debug(\"LMS CLI: empty output - LM Studio may not be running or no models loaded\");\n return null;\n }\n\n // Parse JSON output\n let models: Array<{\n identifier?: string;\n modelKey?: string;\n contextLength?: number;\n maxContextLength?: number;\n }>;\n\n try {\n models = JSON.parse(output) as typeof models;\n } catch (parseErr) {\n log.debug(`LMS CLI: JSON parse error - ${parseErr}`);\n return null;\n }\n\n if (!Array.isArray(models) || models.length === 0) {\n log.debug(\"LMS CLI: no models loaded\");\n return null;\n }\n\n // Find the model matching our configured model ID\n const model = models.find((m) =>\n m.identifier === modelId ||\n m.modelKey === modelId ||\n (m.identifier?.includes(modelId.replace(/@\\d+bit$/, \"\")))\n );\n\n if (!model) {\n log.debug(`LMS CLI: model \"${modelId}\" not found in loaded models: ${models.map(m => m.identifier).join(\", \")}`);\n return null;\n }\n\n // Use contextLength (actual configured) or fall back to maxContextLength (model max)\n const contextWindow = model.contextLength || model.maxContextLength;\n\n if (contextWindow) {\n log.info(`LMS CLI detected context window: ${contextWindow} for ${modelId} (max: ${model.maxContextLength})`);\n return contextWindow;\n }\n\n return null;\n } catch (err) {\n // LMS CLI not available or failed\n const errorMsg = err instanceof Error ? err.message : String(err);\n log.debug(`LMS CLI: failed - ${errorMsg}`);\n return null;\n }\n }\n\n /**\n * Get full model info from LMS CLI including context length and max context length.\n * Returns null if LMS CLI is unavailable or model not found.\n */\n private getLmsModelInfo(modelId: string): { contextLength: number; maxContextLength: number; identifier: string } | null {\n try {\n const result = launchProcessSync(\"lms\", [\"ps\", \"--json\"], {\n encoding: \"utf-8\",\n timeout: 5000,\n shell: false,\n });\n\n if (result.error) {\n return null;\n }\n\n const output = result.stdout || \"\";\n if (!output.trim()) {\n return null;\n }\n\n let models: Array<{\n identifier?: string;\n modelKey?: string;\n contextLength?: number;\n maxContextLength?: number;\n }>;\n\n try {\n models = JSON.parse(output) as typeof models;\n } catch {\n return null;\n }\n\n if (!Array.isArray(models) || models.length === 0) {\n return null;\n }\n\n const model = models.find((m) =>\n m.identifier === modelId ||\n m.modelKey === modelId ||\n (m.identifier?.includes(modelId.replace(/@\\d+bit$/, \"\")))\n );\n\n if (!model || !model.contextLength) {\n return null;\n }\n\n return {\n contextLength: model.contextLength,\n maxContextLength: model.maxContextLength || model.contextLength,\n identifier: model.identifier || modelId,\n };\n } catch {\n return null;\n }\n }\n\n /**\n * Get context window for the configured model, using cache if available.\n * This method caches the result to avoid repeated LMS CLI calls.\n * Order: ModelRegistry (persistent) -> memory cache -> LMS CLI -> settings.json\n */\n getCachedContextWindow(modelId: string): number | null {\n const now = Date.now();\n\n // 1. Check ModelRegistry for persisted context window\n if (this.modelRegistry) {\n const caps = this.modelRegistry.getCapabilities(modelId);\n if (caps.source === \"lmstudio\" && caps.contextWindow) {\n log.debug(`ModelRegistry: using persisted LM Studio context: ${caps.contextWindow}`);\n // Also update memory cache\n this.cachedLmsContext = caps.contextWindow;\n this.lastLmsCheck = now;\n return caps.contextWindow;\n }\n }\n\n // 2. Return in-memory cached value if still valid\n if (this.cachedLmsContext && now - this.lastLmsCheck < LocalLlmClient.LMS_CACHE_INTERVAL_MS) {\n log.debug(`LMS CLI: returning in-memory cached context: ${this.cachedLmsContext}`);\n return this.cachedLmsContext;\n }\n\n // 3. Try LMS CLI (authoritative source)\n const lmsInfo = this.getLmsModelInfo(modelId);\n if (lmsInfo?.contextLength) {\n this.cachedLmsContext = lmsInfo.contextLength;\n this.lastLmsCheck = now;\n // Calculate appropriate output tokens based on context size\n // Use 12.5% of context window, capped at 16K (generous but safe)\n const calculatedOutputTokens = Math.min(Math.floor(lmsInfo.contextLength / 8), 16384);\n const outputTokens = Math.max(calculatedOutputTokens, 4096); // Minimum 4K\n // Persist to ModelRegistry with detected capabilities\n if (this.modelRegistry) {\n this.modelRegistry.setCapabilities(modelId, {\n maxPositionEmbeddings: lmsInfo.maxContextLength || lmsInfo.contextLength,\n contextWindow: lmsInfo.contextLength,\n supportsExtendedContext: (lmsInfo.maxContextLength || lmsInfo.contextLength) > 65536,\n typicalOutputTokens: outputTokens,\n source: \"lmstudio\",\n });\n log.info(`LMS CLI: Stored capabilities for ${modelId}: ${lmsInfo.contextLength} context, ${outputTokens} output tokens`);\n }\n return lmsInfo.contextLength;\n }\n\n // Legacy: Try LMS CLI context only (fallback)\n const legacyContext = this.getContextFromLmsCli(modelId);\n if (legacyContext) {\n this.cachedLmsContext = legacyContext;\n this.lastLmsCheck = now;\n // Persist to ModelRegistry with calculated output tokens\n if (this.modelRegistry) {\n const calculatedOutputTokens = Math.min(Math.floor(legacyContext / 8), 16384);\n const outputTokens = Math.max(calculatedOutputTokens, 4096);\n this.modelRegistry.setCapabilities(modelId, {\n maxPositionEmbeddings: legacyContext,\n contextWindow: legacyContext,\n supportsExtendedContext: false,\n typicalOutputTokens: outputTokens,\n source: \"lmstudio\",\n });\n }\n return legacyContext;\n }\n\n // 4. Fall back to LM Studio settings.json\n const settingsContext = this.getContextFromLmStudioSettings();\n if (settingsContext) {\n log.info(`LM Studio settings: using default context: ${settingsContext}`);\n this.cachedLmsContext = settingsContext;\n this.lastLmsCheck = now;\n return settingsContext;\n }\n\n return null;\n }\n\n /**\n * Clear the LMS context cache. Call this when the model changes.\n */\n clearContextCache(): void {\n this.cachedLmsContext = null;\n this.lastLmsCheck = 0;\n log.debug(\"LMS CLI: context cache cleared\");\n }\n\n private remainingCooldownMs(now: number = Date.now()): number {\n return Math.max(0, this.cooldownUntilMs - now);\n }\n\n private scheduleQueueDrain(): void {\n if (this.queueDrainScheduled) return;\n this.queueDrainScheduled = true;\n\n queueMicrotask(() => {\n this.queueDrainScheduled = false;\n this.startAvailableQueuedRequests();\n });\n }\n\n private hasQueuedRequests(): boolean {\n return (\n this.requestQueues[\"recall-critical\"].length > 0 ||\n this.requestQueues.background.length > 0\n );\n }\n\n private dequeueQueuedRequest(priority: LocalLlmRequestPriority): LocalLlmQueuedRequest | null {\n const next = this.requestQueues[priority].shift();\n return next ?? null;\n }\n\n private failOpenQueuedRequestsForCooldown(): number {\n let dropped = 0;\n for (const priority of [\"recall-critical\", \"background\"] as const) {\n while (this.requestQueues[priority].length > 0) {\n const queued = this.requestQueues[priority].shift();\n queued?.resolve(null);\n dropped += 1;\n }\n }\n return dropped;\n }\n\n private startAvailableQueuedRequests(): void {\n if (!this.queueProcessing.has(\"recall-critical\")) {\n const nextCritical = this.dequeueQueuedRequest(\"recall-critical\");\n if (nextCritical) {\n this.queueProcessing.add(\"recall-critical\");\n void this.runQueuedRequest(nextCritical);\n }\n }\n\n if (!this.queueProcessing.has(\"background\")) {\n const nextBackground = this.dequeueQueuedRequest(\"background\");\n if (nextBackground) {\n this.queueProcessing.add(\"background\");\n void this.runQueuedRequest(nextBackground);\n }\n }\n }\n\n private async runQueuedRequest(next: LocalLlmQueuedRequest): Promise<void> {\n try {\n const remainingCooldownMs = this.remainingCooldownMs();\n if (remainingCooldownMs > 0) {\n const additionalDropped = this.failOpenQueuedRequestsForCooldown();\n log.warn(\n `local LLM: cooldown active (${remainingCooldownMs}ms remaining), dropping ${additionalDropped + 1} queued request(s) fail-open`,\n );\n next.resolve(null);\n return;\n }\n\n let result: LocalLlmChatCompletionResult | null = null;\n try {\n result = await this.runChatCompletionRequest(next.messages, next.options, {\n priority: next.priority,\n enqueuedAtMs: next.enqueuedAtMs,\n });\n } catch (err) {\n log.warn(`local LLM queue drain failed open: ${err instanceof Error ? err.message : String(err)}`);\n }\n next.resolve(result);\n } finally {\n this.queueProcessing.delete(next.priority);\n if (this.hasQueuedRequests()) {\n this.scheduleQueueDrain();\n }\n }\n }\n\n private async runChatCompletionRequest(\n messages: Array<{ role: string; content: string }>,\n options: LocalLlmChatCompletionOptions,\n queueMeta?: { priority: LocalLlmRequestPriority; enqueuedAtMs: number },\n ): Promise<LocalLlmChatCompletionResult | null> {\n log.debug(\n `local LLM chatCompletion: localLlmEnabled=${resolveLocalLlmCapabilities(this.config).localLlm}, model=${this.config.localLlmModel}`,\n );\n\n const operation = options.operation ?? \"unspecified\";\n const startedAtMs = Date.now();\n if (queueMeta) {\n log.debug(\n `local LLM queue start: priority=${queueMeta.priority} waitMs=${startedAtMs - queueMeta.enqueuedAtMs} op=${operation}`,\n );\n }\n\n try {\n const isAvailable = await this.checkAvailability();\n if (!isAvailable) {\n log.debug(\n `local LLM: checkAvailability returned false for ${this.config.localLlmUrl}`,\n );\n return null;\n }\n\n const promptChars = messages.reduce((sum, m) => sum + (m.content?.length ?? 0), 0);\n const requestBody: Record<string, unknown> = {\n model: this.config.localLlmModel,\n messages,\n temperature: options.temperature ?? 0.7,\n // Use max_tokens consistent with cloud models\n max_tokens: options.maxTokens ?? 4096,\n };\n\n // Skip response_format for local LLMs - they don't support json_object type\n // The prompts already instruct the model to output JSON\n // Only send if it's json_schema type which some local LLMs support\n if (options.responseFormat?.type === \"json_schema\") {\n requestBody.response_format = options.responseFormat;\n }\n\n // Suppress thinking/reasoning for operations that benefit from terse,\n // structured output. Thinking-capable models (Qwen 3.5, Gemma 4,\n // DeepSeek) default to thinking-on via their chat template; sending\n // `chat_template_kwargs: { enable_thinking: false }` tells the template\n // to skip reasoning tokens. Consolidation operations on the main client\n // intentionally keep thinking enabled so entity resolution and\n // deduplication can use the model's reasoning path. Fast-tier callers can\n // still force suppression per request to preserve their low-latency\n // contract.\n //\n // Gate the injection on detected backend support (issue #548,\n // Codex P1 on PR #550): `chat_template_kwargs` is an LM Studio /\n // vLLM / llama.cpp extension, not part of standard OpenAI chat\n // completions. Strict OpenAI-compatible backends reject\n // unknown fields with 400, which trips the 400-cooldown path and\n // can effectively disable local extraction. Fail open when the\n // backend hasn't been positively identified as thinking-capable.\n const shouldSuppressThinking =\n options.forceDisableThinking === true ||\n (this._disableThinking &&\n THINKING_SUPPRESSED_OPERATIONS.has(operation));\n if (\n shouldSuppressThinking &&\n this.detectedType !== null &&\n THINKING_COMPATIBLE_BACKENDS.has(this.detectedType)\n ) {\n requestBody.chat_template_kwargs = { enable_thinking: false };\n }\n\n // Normalize URL (use 127.0.0.1 instead of localhost)\n const baseUrl = trimTrailingSlashes(\n this.config.localLlmUrl.replace(\"localhost\", \"127.0.0.1\"),\n );\n const chatUrl = baseUrl.endsWith(\"/v1\")\n ? `${baseUrl}/chat/completions`\n : `${baseUrl}/v1/chat/completions`;\n\n const requestBodyJson = JSON.stringify(requestBody);\n log.debug(\n `local LLM: sending request to ${chatUrl} with model ${this.config.localLlmModel}`,\n );\n // Avoid logging request bodies by default (can contain sensitive user content).\n log.debug(`local LLM: request body length=${requestBodyJson.length}`);\n\n // Write request body to file for debugging\n if (this.config.debug) {\n try {\n const { writeFileSync } = await import(\"node:fs\");\n writeFileSync(\"/tmp/engram-last-request.json\", requestBodyJson);\n } catch {\n /* ignore */\n }\n }\n\n const effectiveTimeoutMs =\n typeof options.timeoutMs === \"number\"\n ? Math.min(this.config.localLlmTimeoutMs, options.timeoutMs)\n : this.config.localLlmTimeoutMs;\n const maxAttempts = 1 + Math.max(0, this.config.localLlmRetry5xxCount);\n let response: Response | null = null;\n let lastAbortError: Error | null = null;\n for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {\n const attemptAbort = new AbortController();\n const attemptTimeout = setTimeout(() => attemptAbort.abort(), effectiveTimeoutMs);\n try {\n response = await fetch(chatUrl, {\n method: \"POST\",\n headers: this.buildRequestHeaders({\n \"Content-Type\": \"application/json\",\n }),\n body: JSON.stringify(requestBody),\n signal: attemptAbort.signal,\n });\n } catch (err) {\n if (!this.isAbortError(err)) throw err;\n lastAbortError = err instanceof Error ? err : new Error(String(err));\n if (attempt < maxAttempts) {\n const backoffMs = this.config.localLlmRetryBackoffMs * attempt;\n log.warn(\n `local LLM request aborted: op=${operation} attempt=${attempt}/${maxAttempts} timeoutMs=${effectiveTimeoutMs} model=${this.config.localLlmModel}; retrying after ${backoffMs}ms`,\n );\n await new Promise((resolve) => setTimeout(resolve, backoffMs));\n continue;\n }\n break;\n } finally {\n clearTimeout(attemptTimeout);\n }\n\n if (response.ok) break;\n if (response.status >= 500 && attempt < maxAttempts) {\n try {\n const errorText = await response.clone().text();\n const nonRecoverableReason =\n this.extractNonRecoverableBackendReasonFromErrorText(errorText);\n if (nonRecoverableReason) {\n this.markBackendUnavailable(\n nonRecoverableReason,\n this.config.localLlm400CooldownMs,\n );\n this.consecutive400s = 0;\n return null;\n }\n } catch (e) {\n log.debug(`local LLM failed to inspect retryable error body: ${e}`);\n }\n }\n if (response.status < 500 || attempt >= maxAttempts) break;\n\n const backoffMs = this.config.localLlmRetryBackoffMs * attempt;\n log.warn(\n `local LLM request got ${response.status}; retrying (attempt ${attempt + 1}/${maxAttempts}) after ${backoffMs}ms`,\n );\n await new Promise((resolve) => setTimeout(resolve, backoffMs));\n }\n log.debug(\n `local LLM: received response, status=${response?.status}, ok=${response?.ok}`,\n );\n\n if (!response) {\n if (lastAbortError) {\n log.warn(\n `local LLM request aborted after ${maxAttempts} attempt(s): op=${operation} timeoutMs=${effectiveTimeoutMs} model=${this.config.localLlmModel} promptChars=${promptChars} durationMs=${Date.now() - startedAtMs}`,\n );\n } else {\n log.warn(\n `local LLM request failed: no response object (op=${operation} model=${this.config.localLlmModel} durationMs=${Date.now() - startedAtMs})`,\n );\n }\n return null;\n }\n\n if (!response.ok) {\n let reason = \"\";\n let errorText = \"\";\n try {\n errorText = await response.text();\n // Try to extract a stable error message without logging content.\n try {\n const parsed = JSON.parse(errorText) as { error?: { message?: string } };\n reason = parsed?.error?.message ? ` — ${parsed.error.message}` : \"\";\n } catch {\n // Keep a short preview in debug only.\n log.debug(`local LLM error body: ${errorText.slice(0, 500)}`);\n }\n } catch (e) {\n log.debug(`local LLM failed to read error body: ${e}`);\n }\n log.warn(\n `local LLM request failed: ${response.status} ${response.statusText}${reason} ` +\n `(op=${operation}, model=${this.config.localLlmModel}, url=${chatUrl}, promptChars=${promptChars}, maxTokens=${requestBody.max_tokens as number})`,\n );\n const nonRecoverableReason =\n this.extractNonRecoverableBackendReason(reason) ??\n this.extractNonRecoverableBackendReasonFromErrorText(errorText);\n if (nonRecoverableReason) {\n this.markBackendUnavailable(\n nonRecoverableReason,\n this.config.localLlm400CooldownMs,\n );\n this.consecutive400s = 0;\n return null;\n }\n if (response.status === 400) {\n this.consecutive400s += 1;\n if (this.consecutive400s >= this.config.localLlm400TripThreshold) {\n this.cooldownUntilMs = Date.now() + this.config.localLlm400CooldownMs;\n log.warn(\n `local LLM: entering cooldown for ${this.config.localLlm400CooldownMs}ms ` +\n `after ${this.consecutive400s} consecutive 400 responses`,\n );\n this.consecutive400s = 0;\n }\n } else {\n this.consecutive400s = 0;\n }\n return null;\n }\n this.consecutive400s = 0;\n\n const data = (await response.json()) as {\n choices?: Array<{\n message?: { content?: string; reasoning_content?: string };\n }>;\n usage?: {\n prompt_tokens?: number;\n completion_tokens?: number;\n total_tokens?: number;\n };\n };\n\n log.debug(\n `local LLM response: choices=${data.choices?.length}, usage=${JSON.stringify(data.usage)}`,\n );\n\n // Thinking models (e.g. Qwen 3.5) may put their response in\n // `reasoning_content` and leave `content` empty. Fall back to\n // reasoning_content so engram still gets a usable result.\n const msg = data.choices?.[0]?.message;\n const content = msg?.content || msg?.reasoning_content || \"\";\n if (!content) {\n log.warn(`local LLM returned empty content. choices=${JSON.stringify(data.choices)?.slice(0, 200)}`);\n return null;\n }\n\n // Estimate tokens if not provided by local LLM\n const usage = data.usage\n ? {\n promptTokens: data.usage.prompt_tokens ?? 0,\n completionTokens: data.usage.completion_tokens ?? 0,\n totalTokens: data.usage.total_tokens ?? 0,\n }\n : this.estimateTokens(messages, content);\n\n const durationMs = Date.now() - startedAtMs;\n if (this.config.slowLogEnabled && durationMs >= this.config.slowLogThresholdMs) {\n const promptChars = messages.reduce((sum, m) => sum + (m.content?.length ?? 0), 0);\n const op = options.operation ? ` op=${options.operation}` : \"\";\n log.warn(\n `SLOW local LLM:${op} durationMs=${durationMs} model=${this.config.localLlmModel} url=${chatUrl} promptChars=${promptChars} outputTokens=${usage.completionTokens} totalTokens=${usage.totalTokens}`,\n );\n }\n\n log.debug(\"local LLM: request succeeded, tokens:\", usage.totalTokens);\n return { content, usage };\n } catch (err) {\n const errMsg = err instanceof Error ? err.message : String(err);\n const durationMs = Date.now() - startedAtMs;\n if (this.isAbortError(err)) {\n log.warn(\n `local LLM request aborted: op=${operation} timeoutMs=${options.timeoutMs ?? this.config.localLlmTimeoutMs} model=${this.config.localLlmModel} durationMs=${durationMs} error=${errMsg}`,\n );\n return null;\n }\n log.warn(`local LLM request error: op=${operation} error=${errMsg}`);\n this.isAvailable = false; // Mark as unavailable on non-abort errors\n const nonRecoverableReason = this.extractNonRecoverableBackendReason(errMsg);\n if (nonRecoverableReason) {\n this.markBackendUnavailable(\n nonRecoverableReason,\n this.config.localLlm400CooldownMs,\n );\n }\n return null;\n } finally {\n if (queueMeta) {\n const finishedAtMs = Date.now();\n const waitMs = startedAtMs - queueMeta.enqueuedAtMs;\n log.debug(\n `local LLM queue finish: priority=${queueMeta.priority} waitMs=${waitMs} runMs=${finishedAtMs - startedAtMs} totalMs=${finishedAtMs - queueMeta.enqueuedAtMs} op=${operation}`,\n );\n }\n }\n }\n\n /**\n * Query the local LLM server for loaded model information.\n * Returns null if unavailable or if the model is not found.\n */\n async getLoadedModelInfo(): Promise<LocalModelInfo | null> {\n const baseUrl = trimTrailingSlashes(\n this.config.localLlmUrl.replace(\"localhost\", \"127.0.0.1\"),\n );\n\n // Handle URL construction - localLlmUrl may already include /v1\n const modelsUrl = baseUrl.endsWith(\"/v1\")\n ? `${baseUrl}/models`\n : `${baseUrl}/v1/models`;\n log.debug(`Fetching model info from ${modelsUrl}`);\n\n try {\n const result = await this.fetchWithTimeout(modelsUrl, 3000);\n if (!result.ok) {\n if (result.status === 401 || result.status === 403) {\n log.warn(\n `Local LLM: unauthorized while fetching models from ${modelsUrl}; verify localLlmApiKey and localLlmAuthHeader settings`,\n );\n }\n log.warn(`Local LLM: Failed to fetch models from ${modelsUrl} - server returned error`);\n return null;\n }\n if (!result.data) {\n log.warn(`Local LLM: No data returned from ${modelsUrl}`);\n return null;\n }\n\n const data = result.data as {\n data?: Array<{\n id?: string;\n object?: string;\n owned_by?: string;\n // LM Studio specific fields\n max_context_length?: number;\n max_tokens?: number;\n // Ollama specific\n name?: string;\n details?: {\n parameter_size?: string;\n family?: string;\n };\n }>;\n };\n\n if (!Array.isArray(data.data) || data.data.length === 0) {\n log.warn(\"Local LLM returned no models\");\n return null;\n }\n\n // Verbose model listings are noisy on every gateway restart. Keep it debug-only.\n const modelIds = data.data.map((m) => m.id).filter(Boolean);\n log.debug(\n `Local LLM: Found ${modelIds.length} model(s). First 10: ${modelIds.slice(0, 10).join(\", \")}`,\n );\n\n // Find the model matching our configured model ID\n const configuredModel = this.config.localLlmModel;\n let model = data.data.find((m) => m.id === configuredModel);\n\n // If not found by exact match, try partial match (handle suffixes like @4bit)\n if (!model) {\n model = data.data.find((m) =>\n configuredModel.includes(m.id || \"\") ||\n (m.id || \"\").includes(configuredModel.replace(/@\\d+bit$/, \"\"))\n );\n }\n\n // If still not found, use the first loaded model and warn\n if (!model) {\n model = data.data[0];\n const availablePreview = data.data\n .map((m) => m.id)\n .filter(Boolean)\n .slice(0, 10)\n .join(\", \");\n log.warn(\n `Configured model \"${configuredModel}\" not found in local LLM. ` +\n `Using \"${model.id}\" instead. Available (first 10): ${availablePreview}`\n );\n }\n\n // Extract context window - try multiple field names\n let contextWindow = model.max_context_length || model.max_tokens;\n\n // If API doesn't report context window, try LMS CLI (LM Studio specific)\n if (!contextWindow) {\n log.info(\"Local LLM: API did not report context window, trying LMS CLI...\");\n const lmsContext = this.getCachedContextWindow(model.id || \"\");\n if (lmsContext) {\n contextWindow = lmsContext;\n }\n }\n\n this.cachedModelInfo = {\n id: model.id || \"unknown\",\n contextWindow: contextWindow,\n maxTokens: model.max_tokens,\n };\n\n log.info(\n `Local LLM model detected: ${this.cachedModelInfo.id}, ` +\n `context window: ${contextWindow?.toLocaleString() || \"unknown (may use default)\"}`\n );\n\n return this.cachedModelInfo;\n } catch (err) {\n log.warn(`Failed to fetch model info: ${err}`);\n return null;\n }\n }\n\n /**\n * Check if the configured model is available and get its actual context window.\n * Warns if there's a mismatch between expected and actual context.\n */\n async validateModelConfig(expectedContextWindow?: number): Promise<{\n available: boolean;\n actualContextWindow?: number;\n warnings: string[];\n }> {\n const warnings: string[] = [];\n\n const modelInfo = await this.getLoadedModelInfo();\n if (!modelInfo) {\n return { available: false, warnings: [\"Could not query local LLM for model info\"] };\n }\n\n // If we have expected context and the server reports one, check for mismatch\n if (expectedContextWindow && modelInfo.contextWindow) {\n if (modelInfo.contextWindow < expectedContextWindow) {\n warnings.push(\n `Context window mismatch: Model ${modelInfo.id} supports ${modelInfo.contextWindow.toLocaleString()} tokens, ` +\n `but engram is configured for ${expectedContextWindow.toLocaleString()}. ` +\n `Set localLlmMaxContext: ${modelInfo.contextWindow} in config to avoid errors.`\n );\n }\n }\n\n // Warn if server doesn't report context window (common with some local LLM setups)\n if (!modelInfo.contextWindow) {\n warnings.push(\n `Local LLM server did not report context window for ${modelInfo.id}. ` +\n `If you get \"context length exceeded\" errors, set localLlmMaxContext in config.`\n );\n }\n\n return {\n available: true,\n actualContextWindow: modelInfo.contextWindow,\n warnings,\n };\n }\n\n /**\n * Make a chat completion request to local LLM\n */\n async chatCompletion(\n messages: Array<{ role: string; content: string }>,\n options: LocalLlmChatCompletionOptions = {},\n ): Promise<LocalLlmChatCompletionResult | null> {\n if (!resolveLocalLlmCapabilities(this.config).localLlm) {\n log.debug(\"local LLM: disabled, returning null\");\n return null;\n }\n\n const remainingMs = this.remainingCooldownMs();\n if (remainingMs > 0) {\n log.debug(`local LLM: cooldown active (${remainingMs}ms remaining), skipping request`);\n return null;\n }\n if (options.priority) {\n const priority = options.priority;\n return await new Promise<LocalLlmChatCompletionResult | null>((resolve) => {\n this.requestQueues[priority].push({\n messages,\n options,\n priority,\n enqueuedAtMs: Date.now(),\n resolve,\n });\n this.scheduleQueueDrain();\n });\n }\n\n return await this.runChatCompletionRequest(messages, options);\n }\n\n /**\n * Estimate tokens when local LLM doesn't return usage stats\n * Rough estimate: 1 token ≈ 4 characters\n */\n private estimateTokens(\n messages: Array<{ role: string; content: string }>,\n response: string\n ): { promptTokens: number; completionTokens: number; totalTokens: number } {\n const promptChars = messages.reduce((sum, m) => sum + m.content.length, 0);\n const promptTokens = Math.ceil(promptChars / 4);\n const completionTokens = Math.ceil(response.length / 4);\n\n return {\n promptTokens,\n completionTokens,\n totalTokens: promptTokens + completionTokens,\n };\n }\n\n /**\n * Try local LLM first, fallback to cloud provider if configured\n */\n async withFallback<T>(\n localOperation: () => Promise<T | null>,\n fallbackOperation: () => Promise<T>,\n operationName: string\n ): Promise<T> {\n // Try local LLM first if enabled\n if (resolveLocalLlmCapabilities(this.config).localLlm) {\n const localResult = await localOperation();\n if (localResult !== null) {\n log.debug(`${operationName}: used local LLM`);\n return localResult;\n }\n\n // Local failed or unavailable\n if (this.config.localLlmFallback) {\n log.info(`${operationName}: local LLM unavailable, falling back to cloud`);\n } else {\n throw new Error(`${operationName}: local LLM unavailable and fallback disabled`);\n }\n }\n\n // Use fallback (cloud provider)\n return fallbackOperation();\n }\n}\n"],"mappings":"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","names":["backoffMs","promptChars"]}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createSearchBackend
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-K7PAILHO.js";
|
|
4
4
|
import {
|
|
5
5
|
namespaceIdentityToken,
|
|
6
6
|
normalizeNamespaceIdentity
|
|
7
7
|
} from "./chunk-ZFXCQPNO.js";
|
|
8
|
+
import {
|
|
9
|
+
resolveNamespaceCapabilities
|
|
10
|
+
} from "./chunk-SHJGBAIW.js";
|
|
8
11
|
|
|
9
12
|
// src/namespaces/search.ts
|
|
10
13
|
import path from "path";
|
|
@@ -219,7 +222,7 @@ var NamespaceSearchRouter = class {
|
|
|
219
222
|
const key = namespace.trim() || this.config.defaultNamespace;
|
|
220
223
|
const storage = await this.storageRouter.storageFor(key);
|
|
221
224
|
const useLegacyDefaultCollection = key === this.config.defaultNamespace && storage.dir === this.config.memoryDir;
|
|
222
|
-
const filtersNestedNamespaces = this.config.
|
|
225
|
+
const filtersNestedNamespaces = resolveNamespaceCapabilities(this.config).namespaces === true && useLegacyDefaultCollection;
|
|
223
226
|
const rootHostEmbeddingScope = this.config.hostEmbeddingProviderScope ?? this.config.memoryDir;
|
|
224
227
|
const scopedConfig = {
|
|
225
228
|
...this.config,
|
|
@@ -401,4 +404,4 @@ export {
|
|
|
401
404
|
namespaceCollectionName,
|
|
402
405
|
NamespaceSearchRouter
|
|
403
406
|
};
|
|
404
|
-
//# sourceMappingURL=chunk-
|
|
407
|
+
//# sourceMappingURL=chunk-3QETM5NG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/namespaces/search.ts"],"sourcesContent":["import { resolveNamespaceCapabilities } from \"../capabilities.js\";\nimport path from \"node:path\";\nimport type { PluginConfig, QmdSearchResult } from \"../types.js\";\nimport type {\n SearchBackend,\n SearchExecutionOptions,\n SearchQueryOptions,\n} from \"../search/port.js\";\nimport { createSearchBackend } from \"../search/factory.js\";\nimport { namespaceIdentityToken, normalizeNamespaceIdentity } from \"./identity.js\";\n\nconst NESTED_NAMESPACE_FILTER_OVERFETCH_FACTOR = 4;\nconst NESTED_NAMESPACE_FILTER_OVERFETCH_MIN = 50;\n\nexport function namespaceCollectionName(\n baseCollection: string,\n namespace: string,\n options?: {\n defaultNamespace?: string;\n useLegacyDefaultCollection?: boolean;\n },\n): string {\n const trimmed = normalizeNamespaceIdentity(namespace);\n const defaultNamespace = normalizeNamespaceIdentity(options?.defaultNamespace ?? \"\") || \"default\";\n if (\n options?.useLegacyDefaultCollection === true &&\n trimmed === defaultNamespace\n ) {\n return baseCollection;\n }\n\n return `${baseCollection}--${namespaceIdentityToken(trimmed || defaultNamespace)}`;\n}\n\ntype StorageRouterLike = {\n storageFor(namespace: string): Promise<{ dir: string }>;\n};\n\ntype NamespaceBackendRecord = {\n backend: SearchBackend;\n collection: string;\n memoryDir: string;\n available: boolean;\n collectionState: CollectionState;\n filtersNestedNamespaces: boolean;\n};\n\nexport interface NamespaceUpdateResult {\n backendCount: number;\n eligibleNamespaces: string[];\n}\n\nexport type CollectionState = \"present\" | \"missing\" | \"unknown\" | \"skipped\";\n\nexport interface NamespaceSearchHealth {\n collection: string;\n memoryDir: string;\n available: boolean;\n collectionState: CollectionState;\n debugStatus: string;\n installedVersion: string | null;\n supportedVersion: string | null;\n supported: boolean | null;\n upgradeAvailable: boolean | null;\n doctorAvailable: boolean | null;\n daemonMode: boolean | null;\n}\n\ntype NamespaceScopedSearchConfig = PluginConfig & {\n hostEmbeddingProviderScope?: string;\n};\n\ntype BackendRecordOptions = {\n autoCreateCollection: boolean;\n abortAsUnavailable: boolean;\n failOpenMissingGuardedCollection: boolean;\n};\n\nexport class NamespaceSearchRouter {\n private readonly cache = new Map<string, Promise<NamespaceBackendRecord>>();\n\n constructor(\n private readonly config: PluginConfig,\n private readonly storageRouter: StorageRouterLike,\n private readonly createBackend: (config: PluginConfig) => SearchBackend = createSearchBackend,\n ) {}\n\n async collectionForNamespace(namespace: string): Promise<string> {\n return (await this.backendRecordFor(namespace)).collection;\n }\n\n async searchAcrossNamespaces(options: {\n query: string;\n namespaces: string[];\n maxResults?: number;\n mode?: \"search\" | \"hybrid\" | \"bm25\" | \"vector\";\n searchOptions?: SearchQueryOptions;\n execution?: SearchExecutionOptions;\n }): Promise<QmdSearchResult[]> {\n const query = options.query.trim();\n if (!query) return [];\n const maxResults = Math.max(0, Math.floor(options.maxResults ?? this.config.qmdMaxResults));\n if (maxResults === 0) return [];\n\n const method = options.mode ?? \"search\";\n const namespaces = Array.from(new Set(options.namespaces.map((value) => value.trim()).filter(Boolean)));\n if (namespaces.length === 0) return [];\n\n const resultsByNamespace = await Promise.all(\n namespaces.map(async (namespace) => {\n const record = await this.backendRecordFor(namespace);\n if (!record.available || record.collectionState === \"missing\") {\n // A per-namespace backend that is unavailable (or missing its\n // collection) must report like any other QMD skip (#1536): its\n // empty contribution is otherwise indistinguishable from a true\n // no-matches for that namespace (codex round-5 review on #1544).\n try {\n options.execution?.onDegradation?.({\n backend: \"qmd\",\n code: \"backend_unavailable\",\n detail:\n record.collectionState === \"missing\"\n ? `namespace collection missing: ${namespace}`\n : `namespace backend unavailable: ${namespace}`,\n });\n } catch {\n // Observers must never break search.\n }\n return { namespace, results: [] as QmdSearchResult[] };\n }\n const backendLimit = backendSearchLimit(record, maxResults);\n let results: QmdSearchResult[];\n switch (method) {\n case \"hybrid\":\n results = await record.backend.hybridSearch(\n query,\n record.collection,\n backendLimit,\n options.execution,\n );\n break;\n case \"bm25\":\n results = await record.backend.bm25Search(\n query,\n record.collection,\n backendLimit,\n options.execution,\n );\n break;\n case \"vector\":\n results = await record.backend.vectorSearch(\n query,\n record.collection,\n backendLimit,\n options.execution,\n );\n break;\n default:\n results = await record.backend.search(\n query,\n record.collection,\n backendLimit,\n options.searchOptions,\n options.execution,\n );\n break;\n }\n results = filterNamespaceSubtreeResults(record, results);\n return { namespace, results };\n }),\n );\n\n return mergeNamespaceSearchResults(resultsByNamespace, maxResults);\n }\n\n /**\n * Update all namespace backends.\n * Returns the number of backends for which an update was attempted\n * (i.e., available and collection present). Callers can treat 0 as a\n * signal that no backend was eligible — useful for success-verification in\n * startup-sync when namespacesEnabled is true.\n */\n async updateNamespaces(\n namespaces: string[],\n execution?: SearchExecutionOptions,\n options?: { strict?: boolean },\n ): Promise<number> {\n return (await this.updateNamespacesDetailed(namespaces, execution, options)).backendCount;\n }\n\n async updateNamespacesDetailed(\n namespaces: string[],\n execution?: SearchExecutionOptions,\n options?: { strict?: boolean },\n ): Promise<NamespaceUpdateResult> {\n const unique = Array.from(new Set(namespaces.map((value) => value.trim()).filter(Boolean)));\n const eligible = (await Promise.all(\n unique.map(async (namespace) => {\n const record = await this.backendRecordFor(namespace);\n return record.available && record.collectionState !== \"missing\"\n ? { namespace, record }\n : null;\n }),\n )).filter((entry): entry is { namespace: string; record: NamespaceBackendRecord } => entry !== null);\n\n const globalEntry = eligible.find(({ record }) => record.backend.updatesAllCollections?.() === true);\n const scopedEntries = globalEntry\n ? eligible.filter(({ record }) => record.backend.updatesAllCollections?.() !== true)\n : eligible;\n\n await Promise.all([\n globalEntry\n ? updateBackendRecord(globalEntry.record, execution, options)\n : Promise.resolve(),\n ...scopedEntries.map(({ record }) => updateBackendRecord(record, execution, options)),\n ]);\n\n return {\n backendCount: (globalEntry ? 1 : 0) + scopedEntries.length,\n eligibleNamespaces: eligible.map(({ namespace }) => namespace),\n };\n }\n\n async embedNamespaces(namespaces: string[], options?: { strict?: boolean }): Promise<void> {\n const unique = Array.from(new Set(namespaces.map((value) => value.trim()).filter(Boolean)));\n await Promise.all(\n unique.map(async (namespace) => {\n const record = await this.backendRecordFor(namespace);\n if (!record.available || record.collectionState === \"missing\") return;\n await embedBackendRecord(record, options);\n }),\n );\n }\n\n async ensureNamespaceCollection(\n namespace: string,\n execution?: SearchExecutionOptions,\n ): Promise<\"present\" | \"missing\" | \"unknown\" | \"skipped\"> {\n const record = await this.backendRecordFor(namespace, execution);\n return record.collectionState;\n }\n\n async healthForNamespace(\n namespace: string,\n execution?: SearchExecutionOptions,\n ): Promise<NamespaceSearchHealth> {\n const key = namespace.trim() || this.config.defaultNamespace;\n const record = await this.createBackendRecordFor(\n key,\n execution,\n {\n autoCreateCollection: false,\n abortAsUnavailable: true,\n failOpenMissingGuardedCollection: false,\n },\n );\n try {\n const liveRecord = await this.liveCachedRecordForHealth(key, record, execution);\n const diagnosticBackend = liveRecord?.backend ?? record.backend;\n const versionStatus =\n \"getVersionStatus\" in diagnosticBackend &&\n typeof diagnosticBackend.getVersionStatus === \"function\"\n ? diagnosticBackend.getVersionStatus()\n : null;\n const daemonMode = daemonModeForBackend(diagnosticBackend);\n const collectionState =\n liveRecord?.collectionState === \"missing\"\n ? \"missing\"\n : record.collectionState;\n\n return {\n collection: record.collection,\n memoryDir: record.memoryDir,\n available: liveRecord?.available ?? record.available,\n collectionState,\n debugStatus: diagnosticBackend.debugStatus(),\n installedVersion: versionStatus?.installedVersion ?? null,\n supportedVersion: versionStatus?.supportedVersion ?? null,\n supported: versionStatus?.supported ?? null,\n upgradeAvailable: versionStatus?.upgradeAvailable ?? null,\n doctorAvailable: versionStatus?.capabilities?.doctor ?? null,\n daemonMode,\n };\n } finally {\n const dispose = (record.backend as { dispose?: () => void | Promise<void> }).dispose;\n await dispose?.call(record.backend);\n }\n }\n\n private async liveCachedRecordForHealth(\n key: string,\n disposableRecord: NamespaceBackendRecord,\n execution?: SearchExecutionOptions,\n ): Promise<NamespaceBackendRecord | null> {\n const pending = this.cache.get(key);\n if (!pending) return null;\n const cachedRecord = await awaitWithAbort(pending, execution?.signal).catch(() => null);\n if (!cachedRecord) return null;\n if (cachedRecord.collection !== disposableRecord.collection) return null;\n if (cachedRecord.memoryDir !== disposableRecord.memoryDir) return null;\n return cachedRecord;\n }\n\n /** Clear cached backend records so the next access re-probes availability. */\n clearCache(): void {\n this.cache.clear();\n }\n\n /** Release any per-namespace backend handles held by cached records. */\n async dispose(): Promise<void> {\n const pendingRecords = Array.from(this.cache.values());\n this.cache.clear();\n const settled = await Promise.allSettled(pendingRecords);\n await Promise.allSettled(\n settled.flatMap((entry) => {\n if (entry.status !== \"fulfilled\") return [];\n const dispose = (entry.value.backend as { dispose?: () => void | Promise<void> }).dispose;\n return dispose ? [dispose.call(entry.value.backend)] : [];\n }),\n );\n }\n\n private async backendRecordFor(\n namespace: string,\n execution?: SearchExecutionOptions,\n ): Promise<NamespaceBackendRecord> {\n const key = namespace.trim() || this.config.defaultNamespace;\n const existing = this.cache.get(key);\n if (existing) return await existing;\n\n const pending = this.createBackendRecordFor(key, execution, {\n autoCreateCollection: true,\n abortAsUnavailable: false,\n failOpenMissingGuardedCollection: true,\n }).catch((error) => {\n this.cache.delete(key);\n throw error;\n });\n\n this.cache.set(key, pending);\n return await pending;\n }\n\n private async createBackendRecordFor(\n namespace: string,\n execution: SearchExecutionOptions | undefined,\n options: BackendRecordOptions,\n ): Promise<NamespaceBackendRecord> {\n const key = namespace.trim() || this.config.defaultNamespace;\n const storage = await this.storageRouter.storageFor(key);\n const useLegacyDefaultCollection =\n key === this.config.defaultNamespace && storage.dir === this.config.memoryDir;\n const filtersNestedNamespaces =\n resolveNamespaceCapabilities(this.config).namespaces === true && useLegacyDefaultCollection;\n const rootHostEmbeddingScope =\n (this.config as NamespaceScopedSearchConfig).hostEmbeddingProviderScope ??\n this.config.memoryDir;\n const scopedConfig: NamespaceScopedSearchConfig = {\n ...this.config,\n memoryDir: storage.dir,\n hostEmbeddingProviderScope: rootHostEmbeddingScope,\n qmdCollection: namespaceCollectionName(this.config.qmdCollection, key, {\n defaultNamespace: this.config.defaultNamespace,\n useLegacyDefaultCollection,\n }),\n };\n\n const backend = this.createBackend(scopedConfig);\n try {\n const availabilityProbe =\n options.autoCreateCollection || typeof backend.checkAvailability !== \"function\"\n ? backend.probe()\n : backend.checkAvailability({ signal: execution?.signal });\n const available = await awaitWithAbort(availabilityProbe, execution?.signal).catch((error) => {\n if (error instanceof NamespaceSearchAbortError && !options.abortAsUnavailable) {\n throw error;\n }\n return false;\n });\n const collectionState = available\n ? await awaitWithAbort(\n this.collectionStateForBackend(backend, storage.dir, scopedConfig.qmdCollection, {\n autoCreate: options.autoCreateCollection,\n failOpenMissingGuardedCollection: options.failOpenMissingGuardedCollection,\n skipAutoCreate: filtersNestedNamespaces,\n execution,\n }),\n execution?.signal,\n ).catch((error) => {\n if (error instanceof NamespaceSearchAbortError && !options.abortAsUnavailable) {\n throw error;\n }\n return \"unknown\" as const;\n })\n : \"unknown\";\n return {\n backend,\n collection: scopedConfig.qmdCollection,\n memoryDir: storage.dir,\n available,\n collectionState,\n filtersNestedNamespaces,\n };\n } catch (error) {\n const dispose = (backend as { dispose?: () => void | Promise<void> }).dispose;\n if (dispose) {\n await Promise.resolve(dispose.call(backend)).catch(() => {});\n }\n throw error;\n }\n }\n\n private async collectionStateForBackend(\n backend: SearchBackend,\n memoryDir: string,\n collection: string,\n options: {\n autoCreate: boolean;\n failOpenMissingGuardedCollection: boolean;\n skipAutoCreate: boolean;\n execution?: SearchExecutionOptions;\n },\n ): Promise<CollectionState> {\n if (!options.autoCreate || options.skipAutoCreate) {\n if (!backend.checkCollection) return \"unknown\";\n const collectionState = await backend\n .checkCollection(collection, options.execution)\n .catch(() => \"unknown\" as const);\n return options.failOpenMissingGuardedCollection && collectionState === \"missing\"\n ? \"unknown\"\n : collectionState;\n }\n return await backend.ensureCollection(memoryDir, collection, options.execution).catch(() => \"unknown\" as const);\n }\n}\n\nclass NamespaceSearchAbortError extends Error {\n constructor() {\n super(\"operation aborted\");\n }\n}\n\nfunction awaitWithAbort<T>(operation: Promise<T>, signal?: AbortSignal): Promise<T> {\n if (!signal) return operation;\n if (signal.aborted) return Promise.reject(new NamespaceSearchAbortError());\n\n return new Promise<T>((resolve, reject) => {\n const onAbort = () => {\n signal.removeEventListener(\"abort\", onAbort);\n reject(new NamespaceSearchAbortError());\n };\n signal.addEventListener(\"abort\", onAbort, { once: true });\n operation.then(resolve, reject).finally(() => {\n signal.removeEventListener(\"abort\", onAbort);\n });\n });\n}\n\nfunction filterNamespaceSubtreeResults(\n record: NamespaceBackendRecord,\n results: QmdSearchResult[],\n): QmdSearchResult[] {\n if (!record.filtersNestedNamespaces) return results;\n return results.filter((result) =>\n !pathIsInsideNamespaceSubtree(record.memoryDir, record.collection, result.path)\n );\n}\n\nfunction backendSearchLimit(\n record: NamespaceBackendRecord,\n maxResults: number,\n): number {\n if (!record.filtersNestedNamespaces) return maxResults;\n return Math.max(\n maxResults,\n maxResults * NESTED_NAMESPACE_FILTER_OVERFETCH_FACTOR,\n NESTED_NAMESPACE_FILTER_OVERFETCH_MIN,\n );\n}\n\nasync function updateBackendRecord(\n record: NamespaceBackendRecord,\n execution?: SearchExecutionOptions,\n options?: { strict?: boolean },\n): Promise<void> {\n if (options?.strict === true) {\n if (\n record.backend.updatesAllCollections?.() === true &&\n typeof record.backend.updateStrict === \"function\"\n ) {\n await record.backend.updateStrict(execution);\n return;\n }\n if (typeof record.backend.updateCollectionStrict === \"function\") {\n await record.backend.updateCollectionStrict(record.collection, execution);\n return;\n }\n }\n await record.backend.update(execution);\n}\n\nasync function embedBackendRecord(\n record: NamespaceBackendRecord,\n options?: { strict?: boolean },\n): Promise<void> {\n if (options?.strict === true) {\n if (typeof record.backend.embedCollectionStrict === \"function\") {\n await record.backend.embedCollectionStrict(record.collection);\n return;\n }\n if (typeof record.backend.embedStrict === \"function\") {\n await record.backend.embedStrict();\n return;\n }\n }\n if (typeof record.backend.embedCollection === \"function\") {\n await record.backend.embedCollection(record.collection);\n return;\n }\n await record.backend.embed();\n}\n\nfunction daemonModeForBackend(backend: SearchBackend): boolean | null {\n return \"isDaemonMode\" in backend && typeof backend.isDaemonMode === \"function\"\n ? backend.isDaemonMode() === true\n : null;\n}\n\nfunction pathIsInsideNamespaceSubtree(\n memoryDir: string,\n collection: string,\n resultPath: string | undefined,\n): boolean {\n if (!resultPath) return false;\n const normalizedResultPath = normalizeQmdResultPath(resultPath, collection);\n const memoryRoot = path.resolve(memoryDir);\n const namespacesRoot = path.join(memoryRoot, \"namespaces\");\n const candidate = path.isAbsolute(normalizedResultPath)\n ? path.normalize(normalizedResultPath)\n : path.resolve(memoryRoot, normalizedResultPath);\n const relative = path.relative(namespacesRoot, candidate);\n return relative === \"\" || (!relative.startsWith(\"..\") && !path.isAbsolute(relative));\n}\n\nfunction normalizeQmdResultPath(resultPath: string, collection: string): string {\n let value = resultPath.trim();\n if (value.startsWith(\"qmd://\")) {\n try {\n const parsed = new URL(value);\n if (parsed.protocol === \"qmd:\" && parsed.hostname === collection) {\n value = decodeURIComponent(parsed.pathname.replace(/^\\/+/, \"\"));\n }\n } catch {\n const remainder = value.slice(\"qmd://\".length);\n const slashIndex = remainder.indexOf(\"/\");\n if (slashIndex !== -1) {\n value = remainder.slice(slashIndex + 1);\n }\n }\n }\n\n const collectionPrefix = `${collection}/`;\n if (value.startsWith(collectionPrefix)) {\n value = value.slice(collectionPrefix.length);\n }\n return value;\n}\n\nfunction mergeNamespaceSearchResults(\n lists: Array<{ namespace: string; results: QmdSearchResult[] }>,\n maxResults: number,\n): QmdSearchResult[] {\n const merged = new Map<string, QmdSearchResult>();\n\n for (const { namespace, results } of lists) {\n for (const result of results) {\n const key = `${namespace}\\0${result.path || result.docid}`;\n const existing = merged.get(key);\n if (!existing) {\n merged.set(key, result);\n continue;\n }\n if (result.score > existing.score) {\n merged.set(key, {\n ...result,\n snippet: existing.snippet || result.snippet || \"\",\n });\n }\n }\n }\n\n return [...merged.values()]\n .sort((a, b) => b.score - a.score)\n .slice(0, maxResults);\n}\n"],"mappings":";;;;;;;;;;;;AACA,OAAO,UAAU;AAUjB,IAAM,2CAA2C;AACjD,IAAM,wCAAwC;AAEvC,SAAS,wBACd,gBACA,WACA,SAIQ;AACR,QAAM,UAAU,2BAA2B,SAAS;AACpD,QAAM,mBAAmB,2BAA2B,SAAS,oBAAoB,EAAE,KAAK;AACxF,MACE,SAAS,+BAA+B,QACxC,YAAY,kBACZ;AACA,WAAO;AAAA,EACT;AAEA,SAAO,GAAG,cAAc,KAAK,uBAAuB,WAAW,gBAAgB,CAAC;AAClF;AA8CO,IAAM,wBAAN,MAA4B;AAAA,EAGjC,YACmB,QACA,eACA,gBAAyD,qBAC1E;AAHiB;AACA;AACA;AAAA,EAChB;AAAA,EAHgB;AAAA,EACA;AAAA,EACA;AAAA,EALF,QAAQ,oBAAI,IAA6C;AAAA,EAQ1E,MAAM,uBAAuB,WAAoC;AAC/D,YAAQ,MAAM,KAAK,iBAAiB,SAAS,GAAG;AAAA,EAClD;AAAA,EAEA,MAAM,uBAAuB,SAOE;AAC7B,UAAM,QAAQ,QAAQ,MAAM,KAAK;AACjC,QAAI,CAAC,MAAO,QAAO,CAAC;AACpB,UAAM,aAAa,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,cAAc,KAAK,OAAO,aAAa,CAAC;AAC1F,QAAI,eAAe,EAAG,QAAO,CAAC;AAE9B,UAAM,SAAS,QAAQ,QAAQ;AAC/B,UAAM,aAAa,MAAM,KAAK,IAAI,IAAI,QAAQ,WAAW,IAAI,CAAC,UAAU,MAAM,KAAK,CAAC,EAAE,OAAO,OAAO,CAAC,CAAC;AACtG,QAAI,WAAW,WAAW,EAAG,QAAO,CAAC;AAErC,UAAM,qBAAqB,MAAM,QAAQ;AAAA,MACvC,WAAW,IAAI,OAAO,cAAc;AAClC,cAAM,SAAS,MAAM,KAAK,iBAAiB,SAAS;AACpD,YAAI,CAAC,OAAO,aAAa,OAAO,oBAAoB,WAAW;AAK7D,cAAI;AACF,oBAAQ,WAAW,gBAAgB;AAAA,cACjC,SAAS;AAAA,cACT,MAAM;AAAA,cACN,QACE,OAAO,oBAAoB,YACvB,iCAAiC,SAAS,KAC1C,kCAAkC,SAAS;AAAA,YACnD,CAAC;AAAA,UACH,QAAQ;AAAA,UAER;AACA,iBAAO,EAAE,WAAW,SAAS,CAAC,EAAuB;AAAA,QACvD;AACA,cAAM,eAAe,mBAAmB,QAAQ,UAAU;AAC1D,YAAI;AACJ,gBAAQ,QAAQ;AAAA,UACd,KAAK;AACH,sBAAU,MAAM,OAAO,QAAQ;AAAA,cAC7B;AAAA,cACA,OAAO;AAAA,cACP;AAAA,cACA,QAAQ;AAAA,YACV;AACA;AAAA,UACF,KAAK;AACH,sBAAU,MAAM,OAAO,QAAQ;AAAA,cAC7B;AAAA,cACA,OAAO;AAAA,cACP;AAAA,cACA,QAAQ;AAAA,YACV;AACA;AAAA,UACF,KAAK;AACH,sBAAU,MAAM,OAAO,QAAQ;AAAA,cAC7B;AAAA,cACA,OAAO;AAAA,cACP;AAAA,cACA,QAAQ;AAAA,YACV;AACA;AAAA,UACF;AACE,sBAAU,MAAM,OAAO,QAAQ;AAAA,cAC7B;AAAA,cACA,OAAO;AAAA,cACP;AAAA,cACA,QAAQ;AAAA,cACR,QAAQ;AAAA,YACV;AACA;AAAA,QACJ;AACA,kBAAU,8BAA8B,QAAQ,OAAO;AACvD,eAAO,EAAE,WAAW,QAAQ;AAAA,MAC9B,CAAC;AAAA,IACH;AAEA,WAAO,4BAA4B,oBAAoB,UAAU;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,iBACJ,YACA,WACA,SACiB;AACjB,YAAQ,MAAM,KAAK,yBAAyB,YAAY,WAAW,OAAO,GAAG;AAAA,EAC/E;AAAA,EAEA,MAAM,yBACJ,YACA,WACA,SACgC;AAChC,UAAM,SAAS,MAAM,KAAK,IAAI,IAAI,WAAW,IAAI,CAAC,UAAU,MAAM,KAAK,CAAC,EAAE,OAAO,OAAO,CAAC,CAAC;AAC1F,UAAM,YAAY,MAAM,QAAQ;AAAA,MAC9B,OAAO,IAAI,OAAO,cAAc;AAC9B,cAAM,SAAS,MAAM,KAAK,iBAAiB,SAAS;AACpD,eAAO,OAAO,aAAa,OAAO,oBAAoB,YAClD,EAAE,WAAW,OAAO,IACpB;AAAA,MACN,CAAC;AAAA,IACH,GAAG,OAAO,CAAC,UAA0E,UAAU,IAAI;AAEnG,UAAM,cAAc,SAAS,KAAK,CAAC,EAAE,OAAO,MAAM,OAAO,QAAQ,wBAAwB,MAAM,IAAI;AACnG,UAAM,gBAAgB,cAClB,SAAS,OAAO,CAAC,EAAE,OAAO,MAAM,OAAO,QAAQ,wBAAwB,MAAM,IAAI,IACjF;AAEJ,UAAM,QAAQ,IAAI;AAAA,MAChB,cACI,oBAAoB,YAAY,QAAQ,WAAW,OAAO,IAC1D,QAAQ,QAAQ;AAAA,MACpB,GAAG,cAAc,IAAI,CAAC,EAAE,OAAO,MAAM,oBAAoB,QAAQ,WAAW,OAAO,CAAC;AAAA,IACtF,CAAC;AAED,WAAO;AAAA,MACL,eAAe,cAAc,IAAI,KAAK,cAAc;AAAA,MACpD,oBAAoB,SAAS,IAAI,CAAC,EAAE,UAAU,MAAM,SAAS;AAAA,IAC/D;AAAA,EACF;AAAA,EAEA,MAAM,gBAAgB,YAAsB,SAA+C;AACzF,UAAM,SAAS,MAAM,KAAK,IAAI,IAAI,WAAW,IAAI,CAAC,UAAU,MAAM,KAAK,CAAC,EAAE,OAAO,OAAO,CAAC,CAAC;AAC1F,UAAM,QAAQ;AAAA,MACZ,OAAO,IAAI,OAAO,cAAc;AAC9B,cAAM,SAAS,MAAM,KAAK,iBAAiB,SAAS;AACpD,YAAI,CAAC,OAAO,aAAa,OAAO,oBAAoB,UAAW;AAC/D,cAAM,mBAAmB,QAAQ,OAAO;AAAA,MAC1C,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAM,0BACJ,WACA,WACwD;AACxD,UAAM,SAAS,MAAM,KAAK,iBAAiB,WAAW,SAAS;AAC/D,WAAO,OAAO;AAAA,EAChB;AAAA,EAEA,MAAM,mBACJ,WACA,WACgC;AAChC,UAAM,MAAM,UAAU,KAAK,KAAK,KAAK,OAAO;AAC5C,UAAM,SAAS,MAAM,KAAK;AAAA,MACxB;AAAA,MACA;AAAA,MACA;AAAA,QACE,sBAAsB;AAAA,QACtB,oBAAoB;AAAA,QACpB,kCAAkC;AAAA,MACpC;AAAA,IACF;AACA,QAAI;AACF,YAAM,aAAa,MAAM,KAAK,0BAA0B,KAAK,QAAQ,SAAS;AAC9E,YAAM,oBAAoB,YAAY,WAAW,OAAO;AACxD,YAAM,gBACJ,sBAAsB,qBACtB,OAAO,kBAAkB,qBAAqB,aAC1C,kBAAkB,iBAAiB,IACnC;AACN,YAAM,aAAa,qBAAqB,iBAAiB;AACzD,YAAM,kBACJ,YAAY,oBAAoB,YAC5B,YACA,OAAO;AAEb,aAAO;AAAA,QACL,YAAY,OAAO;AAAA,QACnB,WAAW,OAAO;AAAA,QAClB,WAAW,YAAY,aAAa,OAAO;AAAA,QAC3C;AAAA,QACA,aAAa,kBAAkB,YAAY;AAAA,QAC3C,kBAAkB,eAAe,oBAAoB;AAAA,QACrD,kBAAkB,eAAe,oBAAoB;AAAA,QACrD,WAAW,eAAe,aAAa;AAAA,QACvC,kBAAkB,eAAe,oBAAoB;AAAA,QACrD,iBAAiB,eAAe,cAAc,UAAU;AAAA,QACxD;AAAA,MACF;AAAA,IACF,UAAE;AACA,YAAM,UAAW,OAAO,QAAqD;AAC7E,YAAM,SAAS,KAAK,OAAO,OAAO;AAAA,IACpC;AAAA,EACF;AAAA,EAEA,MAAc,0BACZ,KACA,kBACA,WACwC;AACxC,UAAM,UAAU,KAAK,MAAM,IAAI,GAAG;AAClC,QAAI,CAAC,QAAS,QAAO;AACrB,UAAM,eAAe,MAAM,eAAe,SAAS,WAAW,MAAM,EAAE,MAAM,MAAM,IAAI;AACtF,QAAI,CAAC,aAAc,QAAO;AAC1B,QAAI,aAAa,eAAe,iBAAiB,WAAY,QAAO;AACpE,QAAI,aAAa,cAAc,iBAAiB,UAAW,QAAO;AAClE,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,aAAmB;AACjB,SAAK,MAAM,MAAM;AAAA,EACnB;AAAA;AAAA,EAGA,MAAM,UAAyB;AAC7B,UAAM,iBAAiB,MAAM,KAAK,KAAK,MAAM,OAAO,CAAC;AACrD,SAAK,MAAM,MAAM;AACjB,UAAM,UAAU,MAAM,QAAQ,WAAW,cAAc;AACvD,UAAM,QAAQ;AAAA,MACZ,QAAQ,QAAQ,CAAC,UAAU;AACzB,YAAI,MAAM,WAAW,YAAa,QAAO,CAAC;AAC1C,cAAM,UAAW,MAAM,MAAM,QAAqD;AAClF,eAAO,UAAU,CAAC,QAAQ,KAAK,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC;AAAA,MAC1D,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAc,iBACZ,WACA,WACiC;AACjC,UAAM,MAAM,UAAU,KAAK,KAAK,KAAK,OAAO;AAC5C,UAAM,WAAW,KAAK,MAAM,IAAI,GAAG;AACnC,QAAI,SAAU,QAAO,MAAM;AAE3B,UAAM,UAAU,KAAK,uBAAuB,KAAK,WAAW;AAAA,MAC1D,sBAAsB;AAAA,MACtB,oBAAoB;AAAA,MACpB,kCAAkC;AAAA,IACpC,CAAC,EAAE,MAAM,CAAC,UAAU;AAClB,WAAK,MAAM,OAAO,GAAG;AACrB,YAAM;AAAA,IACR,CAAC;AAED,SAAK,MAAM,IAAI,KAAK,OAAO;AAC3B,WAAO,MAAM;AAAA,EACf;AAAA,EAEA,MAAc,uBACZ,WACA,WACA,SACiC;AACjC,UAAM,MAAM,UAAU,KAAK,KAAK,KAAK,OAAO;AAC5C,UAAM,UAAU,MAAM,KAAK,cAAc,WAAW,GAAG;AACvD,UAAM,6BACJ,QAAQ,KAAK,OAAO,oBAAoB,QAAQ,QAAQ,KAAK,OAAO;AACtE,UAAM,0BACJ,6BAA6B,KAAK,MAAM,EAAE,eAAe,QAAQ;AACnE,UAAM,yBACH,KAAK,OAAuC,8BAC7C,KAAK,OAAO;AACd,UAAM,eAA4C;AAAA,MAChD,GAAG,KAAK;AAAA,MACR,WAAW,QAAQ;AAAA,MACnB,4BAA4B;AAAA,MAC5B,eAAe,wBAAwB,KAAK,OAAO,eAAe,KAAK;AAAA,QACrE,kBAAkB,KAAK,OAAO;AAAA,QAC9B;AAAA,MACF,CAAC;AAAA,IACH;AAEA,UAAM,UAAU,KAAK,cAAc,YAAY;AAC/C,QAAI;AACF,YAAM,oBACJ,QAAQ,wBAAwB,OAAO,QAAQ,sBAAsB,aACjE,QAAQ,MAAM,IACd,QAAQ,kBAAkB,EAAE,QAAQ,WAAW,OAAO,CAAC;AAC7D,YAAM,YAAY,MAAM,eAAe,mBAAmB,WAAW,MAAM,EAAE,MAAM,CAAC,UAAU;AAC5F,YAAI,iBAAiB,6BAA6B,CAAC,QAAQ,oBAAoB;AAC7E,gBAAM;AAAA,QACR;AACA,eAAO;AAAA,MACT,CAAC;AACD,YAAM,kBAAkB,YACpB,MAAM;AAAA,QACN,KAAK,0BAA0B,SAAS,QAAQ,KAAK,aAAa,eAAe;AAAA,UAC/E,YAAY,QAAQ;AAAA,UACpB,kCAAkC,QAAQ;AAAA,UAC1C,gBAAgB;AAAA,UAChB;AAAA,QACF,CAAC;AAAA,QACD,WAAW;AAAA,MACb,EAAE,MAAM,CAAC,UAAU;AACjB,YAAI,iBAAiB,6BAA6B,CAAC,QAAQ,oBAAoB;AAC7E,gBAAM;AAAA,QACR;AACA,eAAO;AAAA,MACT,CAAC,IACC;AACJ,aAAO;AAAA,QACL;AAAA,QACA,YAAY,aAAa;AAAA,QACzB,WAAW,QAAQ;AAAA,QACnB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,YAAM,UAAW,QAAqD;AACtE,UAAI,SAAS;AACX,cAAM,QAAQ,QAAQ,QAAQ,KAAK,OAAO,CAAC,EAAE,MAAM,MAAM;AAAA,QAAC,CAAC;AAAA,MAC7D;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAc,0BACZ,SACA,WACA,YACA,SAM0B;AAC1B,QAAI,CAAC,QAAQ,cAAc,QAAQ,gBAAgB;AACjD,UAAI,CAAC,QAAQ,gBAAiB,QAAO;AACrC,YAAM,kBAAkB,MAAM,QAC3B,gBAAgB,YAAY,QAAQ,SAAS,EAC7C,MAAM,MAAM,SAAkB;AACjC,aAAO,QAAQ,oCAAoC,oBAAoB,YACnE,YACA;AAAA,IACN;AACA,WAAO,MAAM,QAAQ,iBAAiB,WAAW,YAAY,QAAQ,SAAS,EAAE,MAAM,MAAM,SAAkB;AAAA,EAChH;AACF;AAEA,IAAM,4BAAN,cAAwC,MAAM;AAAA,EAC5C,cAAc;AACZ,UAAM,mBAAmB;AAAA,EAC3B;AACF;AAEA,SAAS,eAAkB,WAAuB,QAAkC;AAClF,MAAI,CAAC,OAAQ,QAAO;AACpB,MAAI,OAAO,QAAS,QAAO,QAAQ,OAAO,IAAI,0BAA0B,CAAC;AAEzE,SAAO,IAAI,QAAW,CAAC,SAAS,WAAW;AACzC,UAAM,UAAU,MAAM;AACpB,aAAO,oBAAoB,SAAS,OAAO;AAC3C,aAAO,IAAI,0BAA0B,CAAC;AAAA,IACxC;AACA,WAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AACxD,cAAU,KAAK,SAAS,MAAM,EAAE,QAAQ,MAAM;AAC5C,aAAO,oBAAoB,SAAS,OAAO;AAAA,IAC7C,CAAC;AAAA,EACH,CAAC;AACH;AAEA,SAAS,8BACP,QACA,SACmB;AACnB,MAAI,CAAC,OAAO,wBAAyB,QAAO;AAC5C,SAAO,QAAQ;AAAA,IAAO,CAAC,WACrB,CAAC,6BAA6B,OAAO,WAAW,OAAO,YAAY,OAAO,IAAI;AAAA,EAChF;AACF;AAEA,SAAS,mBACP,QACA,YACQ;AACR,MAAI,CAAC,OAAO,wBAAyB,QAAO;AAC5C,SAAO,KAAK;AAAA,IACV;AAAA,IACA,aAAa;AAAA,IACb;AAAA,EACF;AACF;AAEA,eAAe,oBACb,QACA,WACA,SACe;AACf,MAAI,SAAS,WAAW,MAAM;AAC5B,QACE,OAAO,QAAQ,wBAAwB,MAAM,QAC7C,OAAO,OAAO,QAAQ,iBAAiB,YACvC;AACA,YAAM,OAAO,QAAQ,aAAa,SAAS;AAC3C;AAAA,IACF;AACA,QAAI,OAAO,OAAO,QAAQ,2BAA2B,YAAY;AAC/D,YAAM,OAAO,QAAQ,uBAAuB,OAAO,YAAY,SAAS;AACxE;AAAA,IACF;AAAA,EACF;AACA,QAAM,OAAO,QAAQ,OAAO,SAAS;AACvC;AAEA,eAAe,mBACb,QACA,SACe;AACf,MAAI,SAAS,WAAW,MAAM;AAC5B,QAAI,OAAO,OAAO,QAAQ,0BAA0B,YAAY;AAC9D,YAAM,OAAO,QAAQ,sBAAsB,OAAO,UAAU;AAC5D;AAAA,IACF;AACA,QAAI,OAAO,OAAO,QAAQ,gBAAgB,YAAY;AACpD,YAAM,OAAO,QAAQ,YAAY;AACjC;AAAA,IACF;AAAA,EACF;AACA,MAAI,OAAO,OAAO,QAAQ,oBAAoB,YAAY;AACxD,UAAM,OAAO,QAAQ,gBAAgB,OAAO,UAAU;AACtD;AAAA,EACF;AACA,QAAM,OAAO,QAAQ,MAAM;AAC7B;AAEA,SAAS,qBAAqB,SAAwC;AACpE,SAAO,kBAAkB,WAAW,OAAO,QAAQ,iBAAiB,aAChE,QAAQ,aAAa,MAAM,OAC3B;AACN;AAEA,SAAS,6BACP,WACA,YACA,YACS;AACT,MAAI,CAAC,WAAY,QAAO;AACxB,QAAM,uBAAuB,uBAAuB,YAAY,UAAU;AAC1E,QAAM,aAAa,KAAK,QAAQ,SAAS;AACzC,QAAM,iBAAiB,KAAK,KAAK,YAAY,YAAY;AACzD,QAAM,YAAY,KAAK,WAAW,oBAAoB,IAClD,KAAK,UAAU,oBAAoB,IACnC,KAAK,QAAQ,YAAY,oBAAoB;AACjD,QAAM,WAAW,KAAK,SAAS,gBAAgB,SAAS;AACxD,SAAO,aAAa,MAAO,CAAC,SAAS,WAAW,IAAI,KAAK,CAAC,KAAK,WAAW,QAAQ;AACpF;AAEA,SAAS,uBAAuB,YAAoB,YAA4B;AAC9E,MAAI,QAAQ,WAAW,KAAK;AAC5B,MAAI,MAAM,WAAW,QAAQ,GAAG;AAC9B,QAAI;AACF,YAAM,SAAS,IAAI,IAAI,KAAK;AAC5B,UAAI,OAAO,aAAa,UAAU,OAAO,aAAa,YAAY;AAChE,gBAAQ,mBAAmB,OAAO,SAAS,QAAQ,QAAQ,EAAE,CAAC;AAAA,MAChE;AAAA,IACF,QAAQ;AACN,YAAM,YAAY,MAAM,MAAM,SAAS,MAAM;AAC7C,YAAM,aAAa,UAAU,QAAQ,GAAG;AACxC,UAAI,eAAe,IAAI;AACrB,gBAAQ,UAAU,MAAM,aAAa,CAAC;AAAA,MACxC;AAAA,IACF;AAAA,EACF;AAEA,QAAM,mBAAmB,GAAG,UAAU;AACtC,MAAI,MAAM,WAAW,gBAAgB,GAAG;AACtC,YAAQ,MAAM,MAAM,iBAAiB,MAAM;AAAA,EAC7C;AACA,SAAO;AACT;AAEA,SAAS,4BACP,OACA,YACmB;AACnB,QAAM,SAAS,oBAAI,IAA6B;AAEhD,aAAW,EAAE,WAAW,QAAQ,KAAK,OAAO;AAC1C,eAAW,UAAU,SAAS;AAC5B,YAAM,MAAM,GAAG,SAAS,KAAK,OAAO,QAAQ,OAAO,KAAK;AACxD,YAAM,WAAW,OAAO,IAAI,GAAG;AAC/B,UAAI,CAAC,UAAU;AACb,eAAO,IAAI,KAAK,MAAM;AACtB;AAAA,MACF;AACA,UAAI,OAAO,QAAQ,SAAS,OAAO;AACjC,eAAO,IAAI,KAAK;AAAA,UACd,GAAG;AAAA,UACH,SAAS,SAAS,WAAW,OAAO,WAAW;AAAA,QACjD,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,SAAO,CAAC,GAAG,OAAO,OAAO,CAAC,EACvB,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,EAChC,MAAM,GAAG,UAAU;AACxB;","names":[]}
|
|
@@ -11,6 +11,9 @@ import {
|
|
|
11
11
|
import {
|
|
12
12
|
ALL_CATEGORY_DIRS
|
|
13
13
|
} from "./chunk-VS2IYZRU.js";
|
|
14
|
+
import {
|
|
15
|
+
resolveNamespaceCapabilities
|
|
16
|
+
} from "./chunk-SHJGBAIW.js";
|
|
14
17
|
import {
|
|
15
18
|
isSafeRouteNamespace
|
|
16
19
|
} from "./chunk-U3PN77QT.js";
|
|
@@ -73,7 +76,7 @@ async function hasAnyNamespaceStorageMarker(rootDir, options = {}) {
|
|
|
73
76
|
return false;
|
|
74
77
|
}
|
|
75
78
|
async function resolveDefaultNamespaceRoot(config) {
|
|
76
|
-
if (!config.
|
|
79
|
+
if (!resolveNamespaceCapabilities(config).namespaces) {
|
|
77
80
|
return config.memoryDir;
|
|
78
81
|
}
|
|
79
82
|
const defaultIdentity = normalizeNamespaceIdentity(config.defaultNamespace);
|
|
@@ -87,7 +90,7 @@ async function resolveDefaultNamespaceRoot(config) {
|
|
|
87
90
|
return await exists(nsDir) && !await hasAnyLegacyData(config.memoryDir) ? nsDir : config.memoryDir;
|
|
88
91
|
}
|
|
89
92
|
async function resolveNamespaceStorageRoot(config, namespace) {
|
|
90
|
-
if (!config.
|
|
93
|
+
if (!resolveNamespaceCapabilities(config).namespaces) return config.memoryDir;
|
|
91
94
|
if (normalizeNamespaceIdentity(namespace) === normalizeNamespaceIdentity(config.defaultNamespace)) {
|
|
92
95
|
return resolveDefaultNamespaceRoot(config);
|
|
93
96
|
}
|
|
@@ -150,7 +153,7 @@ var NamespaceStorageRouter = class {
|
|
|
150
153
|
return this.defaultNsRootResolved;
|
|
151
154
|
}
|
|
152
155
|
async namespaceRoot(namespace) {
|
|
153
|
-
if (!this.config.
|
|
156
|
+
if (!resolveNamespaceCapabilities(this.config).namespaces) return this.config.memoryDir;
|
|
154
157
|
if (normalizeNamespaceIdentity(namespace) === this.defaultNamespaceIdentity) {
|
|
155
158
|
return this.defaultNsRootResolved ?? this.config.memoryDir;
|
|
156
159
|
}
|
|
@@ -336,4 +339,4 @@ export {
|
|
|
336
339
|
resolveNamespaceStorageRoot,
|
|
337
340
|
NamespaceStorageRouter
|
|
338
341
|
};
|
|
339
|
-
//# sourceMappingURL=chunk-
|
|
342
|
+
//# sourceMappingURL=chunk-54RCE5Z3.js.map
|