@jagilber-org/index-server 1.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1354 -0
- package/CODE_OF_CONDUCT.md +49 -0
- package/CONTRIBUTING.md +99 -0
- package/LICENSE +21 -0
- package/README.md +228 -0
- package/SECURITY.md +50 -0
- package/dist/config/configUtils.d.ts +11 -0
- package/dist/config/configUtils.js +87 -0
- package/dist/config/dashboardConfig.d.ts +46 -0
- package/dist/config/dashboardConfig.js +67 -0
- package/dist/config/defaultValues.d.ts +63 -0
- package/dist/config/defaultValues.js +72 -0
- package/dist/config/dirConstants.d.ts +18 -0
- package/dist/config/dirConstants.js +29 -0
- package/dist/config/featureConfig.d.ts +61 -0
- package/dist/config/featureConfig.js +121 -0
- package/dist/config/runtimeConfig.d.ts +151 -0
- package/dist/config/runtimeConfig.js +380 -0
- package/dist/config/serverConfig.d.ts +90 -0
- package/dist/config/serverConfig.js +167 -0
- package/dist/dashboard/analytics/AnalyticsEngine.d.ts +142 -0
- package/dist/dashboard/analytics/AnalyticsEngine.js +373 -0
- package/dist/dashboard/analytics/BusinessIntelligence.d.ts +187 -0
- package/dist/dashboard/analytics/BusinessIntelligence.js +594 -0
- package/dist/dashboard/client/admin.html +2175 -0
- package/dist/dashboard/client/chunks/mermaid-layout-elk.esm.min/chunk-SP2CHFBE.mjs +1 -0
- package/dist/dashboard/client/chunks/mermaid-layout-elk.esm.min/render-T6MDALS3.mjs +27 -0
- package/dist/dashboard/client/css/admin.css +1587 -0
- package/dist/dashboard/client/js/admin.auth.js +179 -0
- package/dist/dashboard/client/js/admin.boot.js +359 -0
- package/dist/dashboard/client/js/admin.config.js +196 -0
- package/dist/dashboard/client/js/admin.embeddings.js +426 -0
- package/dist/dashboard/client/js/admin.graph.js +615 -0
- package/dist/dashboard/client/js/admin.instances.js +120 -0
- package/dist/dashboard/client/js/admin.instructions.js +579 -0
- package/dist/dashboard/client/js/admin.logs.js +113 -0
- package/dist/dashboard/client/js/admin.maintenance.js +393 -0
- package/dist/dashboard/client/js/admin.messaging.js +636 -0
- package/dist/dashboard/client/js/admin.monitor.js +184 -0
- package/dist/dashboard/client/js/admin.overview.js +221 -0
- package/dist/dashboard/client/js/admin.performance.js +61 -0
- package/dist/dashboard/client/js/admin.sessions.js +292 -0
- package/dist/dashboard/client/js/admin.sqlite.js +373 -0
- package/dist/dashboard/client/js/admin.utils.js +49 -0
- package/dist/dashboard/client/js/chart.umd.js +14 -0
- package/dist/dashboard/client/js/elk.bundled.js +6696 -0
- package/dist/dashboard/client/js/marked.umd.js +74 -0
- package/dist/dashboard/client/js/mermaid.min.js +3022 -0
- package/dist/dashboard/client/mermaid-layout-elk.esm.min.mjs +1 -0
- package/dist/dashboard/export/DataExporter.d.ts +169 -0
- package/dist/dashboard/export/DataExporter.js +737 -0
- package/dist/dashboard/export/exporters/csvExporter.d.ts +11 -0
- package/dist/dashboard/export/exporters/csvExporter.js +47 -0
- package/dist/dashboard/export/exporters/exportTypes.d.ts +89 -0
- package/dist/dashboard/export/exporters/exportTypes.js +5 -0
- package/dist/dashboard/export/exporters/jsonExporter.d.ts +7 -0
- package/dist/dashboard/export/exporters/jsonExporter.js +23 -0
- package/dist/dashboard/export/exporters/xmlExporter.d.ts +17 -0
- package/dist/dashboard/export/exporters/xmlExporter.js +176 -0
- package/dist/dashboard/integration/APIIntegration.d.ts +41 -0
- package/dist/dashboard/integration/APIIntegration.js +95 -0
- package/dist/dashboard/security/SecurityMonitor.d.ts +167 -0
- package/dist/dashboard/security/SecurityMonitor.js +560 -0
- package/dist/dashboard/server/AdminPanel.d.ts +195 -0
- package/dist/dashboard/server/AdminPanel.js +861 -0
- package/dist/dashboard/server/AdminPanelConfig.d.ts +42 -0
- package/dist/dashboard/server/AdminPanelConfig.js +80 -0
- package/dist/dashboard/server/AdminPanelState.d.ts +47 -0
- package/dist/dashboard/server/AdminPanelState.js +215 -0
- package/dist/dashboard/server/ApiRoutes.d.ts +17 -0
- package/dist/dashboard/server/ApiRoutes.js +184 -0
- package/dist/dashboard/server/DashboardServer.d.ts +49 -0
- package/dist/dashboard/server/DashboardServer.js +160 -0
- package/dist/dashboard/server/FileMetricsStorage.d.ts +49 -0
- package/dist/dashboard/server/FileMetricsStorage.js +196 -0
- package/dist/dashboard/server/HttpTransport.d.ts +23 -0
- package/dist/dashboard/server/HttpTransport.js +116 -0
- package/dist/dashboard/server/InstanceManager.d.ts +53 -0
- package/dist/dashboard/server/InstanceManager.js +295 -0
- package/dist/dashboard/server/KnowledgeStore.d.ts +35 -0
- package/dist/dashboard/server/KnowledgeStore.js +105 -0
- package/dist/dashboard/server/LeaderElection.d.ts +81 -0
- package/dist/dashboard/server/LeaderElection.js +268 -0
- package/dist/dashboard/server/MetricsCollector.d.ts +200 -0
- package/dist/dashboard/server/MetricsCollector.js +810 -0
- package/dist/dashboard/server/SessionPersistenceManager.d.ts +88 -0
- package/dist/dashboard/server/SessionPersistenceManager.js +458 -0
- package/dist/dashboard/server/ThinClient.d.ts +64 -0
- package/dist/dashboard/server/ThinClient.js +237 -0
- package/dist/dashboard/server/WebSocketManager.d.ts +161 -0
- package/dist/dashboard/server/WebSocketManager.js +448 -0
- package/dist/dashboard/server/httpLifecycle.d.ts +17 -0
- package/dist/dashboard/server/httpLifecycle.js +35 -0
- package/dist/dashboard/server/legacyDashboardHtml.d.ts +9 -0
- package/dist/dashboard/server/legacyDashboardHtml.js +618 -0
- package/dist/dashboard/server/legacyDashboardStyles.d.ts +5 -0
- package/dist/dashboard/server/legacyDashboardStyles.js +490 -0
- package/dist/dashboard/server/metricsAggregation.d.ts +252 -0
- package/dist/dashboard/server/metricsAggregation.js +210 -0
- package/dist/dashboard/server/metricsSerializer.d.ts +25 -0
- package/dist/dashboard/server/metricsSerializer.js +195 -0
- package/dist/dashboard/server/middleware/ensureLoadedMiddleware.d.ts +25 -0
- package/dist/dashboard/server/middleware/ensureLoadedMiddleware.js +24 -0
- package/dist/dashboard/server/routes/admin.routes.d.ts +16 -0
- package/dist/dashboard/server/routes/admin.routes.js +574 -0
- package/dist/dashboard/server/routes/adminAuth.d.ts +4 -0
- package/dist/dashboard/server/routes/adminAuth.js +46 -0
- package/dist/dashboard/server/routes/alerts.routes.d.ts +7 -0
- package/dist/dashboard/server/routes/alerts.routes.js +91 -0
- package/dist/dashboard/server/routes/api.feedback.routes.d.ts +73 -0
- package/dist/dashboard/server/routes/api.feedback.routes.js +171 -0
- package/dist/dashboard/server/routes/api.instructions.routes.d.ts +101 -0
- package/dist/dashboard/server/routes/api.instructions.routes.js +213 -0
- package/dist/dashboard/server/routes/api.usage.routes.d.ts +57 -0
- package/dist/dashboard/server/routes/api.usage.routes.js +374 -0
- package/dist/dashboard/server/routes/embeddings.routes.d.ts +6 -0
- package/dist/dashboard/server/routes/embeddings.routes.js +246 -0
- package/dist/dashboard/server/routes/graph.routes.d.ts +6 -0
- package/dist/dashboard/server/routes/graph.routes.js +279 -0
- package/dist/dashboard/server/routes/index.d.ts +39 -0
- package/dist/dashboard/server/routes/index.js +229 -0
- package/dist/dashboard/server/routes/instances.routes.d.ts +6 -0
- package/dist/dashboard/server/routes/instances.routes.js +35 -0
- package/dist/dashboard/server/routes/instructions.routes.d.ts +8 -0
- package/dist/dashboard/server/routes/instructions.routes.js +268 -0
- package/dist/dashboard/server/routes/knowledge.routes.d.ts +6 -0
- package/dist/dashboard/server/routes/knowledge.routes.js +80 -0
- package/dist/dashboard/server/routes/logs.routes.d.ts +6 -0
- package/dist/dashboard/server/routes/logs.routes.js +166 -0
- package/dist/dashboard/server/routes/messaging.routes.d.ts +16 -0
- package/dist/dashboard/server/routes/messaging.routes.js +307 -0
- package/dist/dashboard/server/routes/metrics.routes.d.ts +10 -0
- package/dist/dashboard/server/routes/metrics.routes.js +335 -0
- package/dist/dashboard/server/routes/scripts.routes.d.ts +9 -0
- package/dist/dashboard/server/routes/scripts.routes.js +84 -0
- package/dist/dashboard/server/routes/sqlite.routes.d.ts +9 -0
- package/dist/dashboard/server/routes/sqlite.routes.js +570 -0
- package/dist/dashboard/server/routes/status.routes.d.ts +7 -0
- package/dist/dashboard/server/routes/status.routes.js +179 -0
- package/dist/dashboard/server/routes/synthetic.routes.d.ts +7 -0
- package/dist/dashboard/server/routes/synthetic.routes.js +197 -0
- package/dist/dashboard/server/routes/tools.routes.d.ts +6 -0
- package/dist/dashboard/server/routes/tools.routes.js +47 -0
- package/dist/dashboard/server/routes/usage.routes.d.ts +6 -0
- package/dist/dashboard/server/routes/usage.routes.js +26 -0
- package/dist/dashboard/server/wsInit.d.ts +16 -0
- package/dist/dashboard/server/wsInit.js +35 -0
- package/dist/externalClientLib.d.ts +1 -0
- package/dist/externalClientLib.js +2 -0
- package/dist/minimal/index.d.ts +1 -0
- package/dist/minimal/index.js +140 -0
- package/dist/models/SessionPersistence.d.ts +115 -0
- package/dist/models/SessionPersistence.js +66 -0
- package/dist/models/instruction.d.ts +46 -0
- package/dist/models/instruction.js +2 -0
- package/dist/perf/benchmark.d.ts +1 -0
- package/dist/perf/benchmark.js +50 -0
- package/dist/portableClientWrapper.d.ts +1 -0
- package/dist/portableClientWrapper.js +2 -0
- package/dist/schemas/index.d.ts +132 -0
- package/dist/schemas/index.js +372 -0
- package/dist/scripts/runPerformanceBaseline.d.ts +1 -0
- package/dist/scripts/runPerformanceBaseline.js +17 -0
- package/dist/server/backgroundServicesStartup.d.ts +3 -0
- package/dist/server/backgroundServicesStartup.js +51 -0
- package/dist/server/handshakeManager.d.ts +25 -0
- package/dist/server/handshakeManager.js +470 -0
- package/dist/server/index-server.d.ts +38 -0
- package/dist/server/index-server.js +620 -0
- package/dist/server/multiInstanceStartup.d.ts +6 -0
- package/dist/server/multiInstanceStartup.js +132 -0
- package/dist/server/registry.d.ts +44 -0
- package/dist/server/registry.js +236 -0
- package/dist/server/sdkServer.d.ts +8 -0
- package/dist/server/sdkServer.js +299 -0
- package/dist/server/shutdownGuard.d.ts +41 -0
- package/dist/server/shutdownGuard.js +52 -0
- package/dist/server/startupDiagnostics.d.ts +2 -0
- package/dist/server/startupDiagnostics.js +33 -0
- package/dist/server/thin-client.d.ts +22 -0
- package/dist/server/thin-client.js +111 -0
- package/dist/server/transport.d.ts +41 -0
- package/dist/server/transport.js +312 -0
- package/dist/server/transportFactory.d.ts +21 -0
- package/dist/server/transportFactory.js +429 -0
- package/dist/services/atomicFs.d.ts +22 -0
- package/dist/services/atomicFs.js +103 -0
- package/dist/services/auditLog.d.ts +38 -0
- package/dist/services/auditLog.js +142 -0
- package/dist/services/autoBackup.d.ts +14 -0
- package/dist/services/autoBackup.js +171 -0
- package/dist/services/autoSplit.d.ts +32 -0
- package/dist/services/autoSplit.js +113 -0
- package/dist/services/backupZip.d.ts +25 -0
- package/dist/services/backupZip.js +112 -0
- package/dist/services/bootstrapGating.d.ts +123 -0
- package/dist/services/bootstrapGating.js +221 -0
- package/dist/services/canonical.d.ts +23 -0
- package/dist/services/canonical.js +65 -0
- package/dist/services/categoryRules.d.ts +7 -0
- package/dist/services/categoryRules.js +37 -0
- package/dist/services/classificationService.d.ts +42 -0
- package/dist/services/classificationService.js +168 -0
- package/dist/services/embeddingService.d.ts +62 -0
- package/dist/services/embeddingService.js +264 -0
- package/dist/services/errors.d.ts +22 -0
- package/dist/services/errors.js +31 -0
- package/dist/services/featureFlags.d.ts +25 -0
- package/dist/services/featureFlags.js +89 -0
- package/dist/services/features.d.ts +13 -0
- package/dist/services/features.js +35 -0
- package/dist/services/handlers/instructions.add.d.ts +1 -0
- package/dist/services/handlers/instructions.add.js +510 -0
- package/dist/services/handlers/instructions.groom.d.ts +1 -0
- package/dist/services/handlers/instructions.groom.js +575 -0
- package/dist/services/handlers/instructions.import.d.ts +1 -0
- package/dist/services/handlers/instructions.import.js +205 -0
- package/dist/services/handlers/instructions.patch.d.ts +1 -0
- package/dist/services/handlers/instructions.patch.js +121 -0
- package/dist/services/handlers/instructions.query.d.ts +159 -0
- package/dist/services/handlers/instructions.query.js +469 -0
- package/dist/services/handlers/instructions.reload.d.ts +1 -0
- package/dist/services/handlers/instructions.reload.js +13 -0
- package/dist/services/handlers/instructions.remove.d.ts +1 -0
- package/dist/services/handlers/instructions.remove.js +122 -0
- package/dist/services/handlers/instructions.shared.d.ts +32 -0
- package/dist/services/handlers/instructions.shared.js +91 -0
- package/dist/services/handlers.activation.d.ts +1 -0
- package/dist/services/handlers.activation.js +203 -0
- package/dist/services/handlers.bootstrap.d.ts +1 -0
- package/dist/services/handlers.bootstrap.js +38 -0
- package/dist/services/handlers.dashboardConfig.d.ts +34 -0
- package/dist/services/handlers.dashboardConfig.js +110 -0
- package/dist/services/handlers.diagnostics.d.ts +1 -0
- package/dist/services/handlers.diagnostics.js +64 -0
- package/dist/services/handlers.feedback.d.ts +15 -0
- package/dist/services/handlers.feedback.js +389 -0
- package/dist/services/handlers.gates.d.ts +1 -0
- package/dist/services/handlers.gates.js +47 -0
- package/dist/services/handlers.graph.d.ts +53 -0
- package/dist/services/handlers.graph.js +231 -0
- package/dist/services/handlers.help.d.ts +1 -0
- package/dist/services/handlers.help.js +119 -0
- package/dist/services/handlers.instructionSchema.d.ts +1 -0
- package/dist/services/handlers.instructionSchema.js +227 -0
- package/dist/services/handlers.instructions.d.ts +8 -0
- package/dist/services/handlers.instructions.js +14 -0
- package/dist/services/handlers.instructionsDiagnostics.d.ts +1 -0
- package/dist/services/handlers.instructionsDiagnostics.js +14 -0
- package/dist/services/handlers.integrity.d.ts +1 -0
- package/dist/services/handlers.integrity.js +35 -0
- package/dist/services/handlers.manifest.d.ts +1 -0
- package/dist/services/handlers.manifest.js +24 -0
- package/dist/services/handlers.messaging.d.ts +12 -0
- package/dist/services/handlers.messaging.js +203 -0
- package/dist/services/handlers.metrics.d.ts +1 -0
- package/dist/services/handlers.metrics.js +43 -0
- package/dist/services/handlers.promote.d.ts +1 -0
- package/dist/services/handlers.promote.js +326 -0
- package/dist/services/handlers.prompt.d.ts +1 -0
- package/dist/services/handlers.prompt.js +7 -0
- package/dist/services/handlers.search.d.ts +69 -0
- package/dist/services/handlers.search.js +669 -0
- package/dist/services/handlers.testPrimitive.d.ts +1 -0
- package/dist/services/handlers.testPrimitive.js +5 -0
- package/dist/services/handlers.trace.d.ts +1 -0
- package/dist/services/handlers.trace.js +35 -0
- package/dist/services/handlers.usage.d.ts +1 -0
- package/dist/services/handlers.usage.js +11 -0
- package/dist/services/hotScore.d.ts +137 -0
- package/dist/services/hotScore.js +244 -0
- package/dist/services/indexContext.d.ts +117 -0
- package/dist/services/indexContext.js +989 -0
- package/dist/services/indexLoader.d.ts +44 -0
- package/dist/services/indexLoader.js +920 -0
- package/dist/services/indexRepository.d.ts +32 -0
- package/dist/services/indexRepository.js +71 -0
- package/dist/services/indexingService.d.ts +1 -0
- package/dist/services/indexingService.js +2 -0
- package/dist/services/instructions.dispatcher.d.ts +1 -0
- package/dist/services/instructions.dispatcher.js +231 -0
- package/dist/services/logPrefix.d.ts +1 -0
- package/dist/services/logPrefix.js +30 -0
- package/dist/services/logger.d.ts +52 -0
- package/dist/services/logger.js +268 -0
- package/dist/services/manifestManager.d.ts +82 -0
- package/dist/services/manifestManager.js +200 -0
- package/dist/services/messaging/agentMailbox.d.ts +60 -0
- package/dist/services/messaging/agentMailbox.js +353 -0
- package/dist/services/messaging/messagingPersistence.d.ts +20 -0
- package/dist/services/messaging/messagingPersistence.js +111 -0
- package/dist/services/messaging/messagingTypes.d.ts +150 -0
- package/dist/services/messaging/messagingTypes.js +66 -0
- package/dist/services/ownershipService.d.ts +1 -0
- package/dist/services/ownershipService.js +36 -0
- package/dist/services/performanceBaseline.d.ts +19 -0
- package/dist/services/performanceBaseline.js +210 -0
- package/dist/services/preflight.d.ts +12 -0
- package/dist/services/preflight.js +79 -0
- package/dist/services/promptReviewService.d.ts +44 -0
- package/dist/services/promptReviewService.js +101 -0
- package/dist/services/responseEnvelope.d.ts +6 -0
- package/dist/services/responseEnvelope.js +25 -0
- package/dist/services/seedBootstrap.d.ts +34 -0
- package/dist/services/seedBootstrap.js +259 -0
- package/dist/services/storage/factory.d.ts +17 -0
- package/dist/services/storage/factory.js +35 -0
- package/dist/services/storage/hashUtils.d.ts +11 -0
- package/dist/services/storage/hashUtils.js +35 -0
- package/dist/services/storage/index.d.ts +12 -0
- package/dist/services/storage/index.js +18 -0
- package/dist/services/storage/jsonFileStore.d.ts +32 -0
- package/dist/services/storage/jsonFileStore.js +241 -0
- package/dist/services/storage/migrationEngine.d.ts +35 -0
- package/dist/services/storage/migrationEngine.js +93 -0
- package/dist/services/storage/sqliteMessageStore.d.ts +53 -0
- package/dist/services/storage/sqliteMessageStore.js +146 -0
- package/dist/services/storage/sqliteSchema.d.ts +12 -0
- package/dist/services/storage/sqliteSchema.js +123 -0
- package/dist/services/storage/sqliteStore.d.ts +42 -0
- package/dist/services/storage/sqliteStore.js +361 -0
- package/dist/services/storage/sqliteUsageStore.d.ts +35 -0
- package/dist/services/storage/sqliteUsageStore.js +94 -0
- package/dist/services/storage/types.d.ts +171 -0
- package/dist/services/storage/types.js +12 -0
- package/dist/services/toolHandlers.d.ts +23 -0
- package/dist/services/toolHandlers.js +50 -0
- package/dist/services/toolRegistry.d.ts +20 -0
- package/dist/services/toolRegistry.js +490 -0
- package/dist/services/toolRegistry.zod.d.ts +10 -0
- package/dist/services/toolRegistry.zod.js +325 -0
- package/dist/services/tracing.d.ts +26 -0
- package/dist/services/tracing.js +260 -0
- package/dist/services/usageBuckets.d.ts +161 -0
- package/dist/services/usageBuckets.js +364 -0
- package/dist/services/validationService.d.ts +38 -0
- package/dist/services/validationService.js +125 -0
- package/dist/utils/BufferRing.d.ts +203 -0
- package/dist/utils/BufferRing.js +551 -0
- package/dist/utils/BufferRingExamples.d.ts +55 -0
- package/dist/utils/BufferRingExamples.js +188 -0
- package/dist/utils/envUtils.d.ts +42 -0
- package/dist/utils/envUtils.js +80 -0
- package/dist/utils/memoryMonitor.d.ts +83 -0
- package/dist/utils/memoryMonitor.js +275 -0
- package/dist/versioning/schemaVersion.d.ts +6 -0
- package/dist/versioning/schemaVersion.js +94 -0
- package/package.json +139 -0
- package/schemas/README.md +13 -0
- package/schemas/feedback-entry.schema.json +27 -0
- package/schemas/graph-export-v2.schema.json +60 -0
- package/schemas/index-server.code-schema.json +40670 -0
- package/schemas/instruction.schema.json +262 -0
- package/schemas/json-schema/SessionPersistence-persisted-admin-session.schema.json +54 -0
- package/schemas/json-schema/SessionPersistence-persisted-session-history-entry.schema.json +51 -0
- package/schemas/json-schema/SessionPersistence-persisted-web-socket-connection.schema.json +54 -0
- package/schemas/json-schema/SessionPersistence-session-persistence-config.schema.json +110 -0
- package/schemas/json-schema/SessionPersistence-session-persistence-data.schema.json +229 -0
- package/schemas/json-schema/SessionPersistence-session-persistence-manifest.schema.json +109 -0
- package/schemas/json-schema/SessionPersistence-session-persistence-metadata.schema.json +55 -0
- package/schemas/json-schema/instruction-audience-scope.schema.json +14 -0
- package/schemas/json-schema/instruction-content-type.schema.json +17 -0
- package/schemas/json-schema/instruction-instruction-entry.schema.json +210 -0
- package/schemas/json-schema/instruction-requirement-level.schema.json +16 -0
- package/schemas/manifest.json +78 -0
- package/schemas/manifest.schema.json +33 -0
- package/schemas/usage-batch.schema.json +16 -0
- package/schemas/usage-buckets.schema.json +30 -0
- package/schemas/usage-event.schema.json +17 -0
- package/scripts/copy-dashboard-assets.mjs +170 -0
- package/scripts/dist/README.md +15 -0
- package/scripts/setup-hooks.cjs +28 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SqliteStore — SQLite storage backend using Node.js built-in node:sqlite.
|
|
4
|
+
*
|
|
5
|
+
* ⚠️ EXPERIMENTAL — LIMITED TESTING PERFORMED.
|
|
6
|
+
* This backend is behind the INDEX_SERVER_STORAGE_BACKEND=sqlite feature flag
|
|
7
|
+
* and should NOT be used in production without thorough validation.
|
|
8
|
+
* Data loss, migration issues, or compatibility problems may occur.
|
|
9
|
+
*
|
|
10
|
+
* Uses DatabaseSync (synchronous API) — zero third-party dependencies.
|
|
11
|
+
* Requires Node.js >= 22.5.0.
|
|
12
|
+
*
|
|
13
|
+
* Implements IInstructionStore for the storage abstraction layer.
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.SqliteStore = void 0;
|
|
17
|
+
const node_sqlite_1 = require("node:sqlite");
|
|
18
|
+
const hashUtils_js_1 = require("./hashUtils.js");
|
|
19
|
+
const sqliteSchema_js_1 = require("./sqliteSchema.js");
|
|
20
|
+
// ── Column Mapping ───────────────────────────────────────────────────────────
|
|
21
|
+
/** Map DB row (snake_case) to InstructionEntry (camelCase). */
|
|
22
|
+
function rowToEntry(row) {
|
|
23
|
+
return {
|
|
24
|
+
id: row.id,
|
|
25
|
+
title: row.title,
|
|
26
|
+
body: row.body,
|
|
27
|
+
rationale: row.rationale,
|
|
28
|
+
priority: row.priority,
|
|
29
|
+
audience: row.audience,
|
|
30
|
+
requirement: row.requirement,
|
|
31
|
+
categories: safeJsonParse(row.categories, []),
|
|
32
|
+
contentType: row.content_type ?? 'instruction',
|
|
33
|
+
primaryCategory: row.primary_category,
|
|
34
|
+
sourceHash: row.source_hash,
|
|
35
|
+
schemaVersion: row.schema_version,
|
|
36
|
+
deprecatedBy: row.deprecated_by,
|
|
37
|
+
createdAt: row.created_at,
|
|
38
|
+
updatedAt: row.updated_at,
|
|
39
|
+
version: row.version,
|
|
40
|
+
status: row.status,
|
|
41
|
+
owner: row.owner,
|
|
42
|
+
priorityTier: row.priority_tier,
|
|
43
|
+
classification: row.classification,
|
|
44
|
+
lastReviewedAt: row.last_reviewed_at,
|
|
45
|
+
nextReviewDue: row.next_review_due,
|
|
46
|
+
reviewIntervalDays: row.review_interval_days,
|
|
47
|
+
changeLog: safeJsonParse(row.change_log, undefined),
|
|
48
|
+
supersedes: row.supersedes,
|
|
49
|
+
archivedAt: row.archived_at,
|
|
50
|
+
workspaceId: row.workspace_id,
|
|
51
|
+
userId: row.user_id,
|
|
52
|
+
teamIds: safeJsonParse(row.team_ids, undefined),
|
|
53
|
+
semanticSummary: row.semantic_summary,
|
|
54
|
+
createdByAgent: row.created_by_agent,
|
|
55
|
+
sourceWorkspace: row.source_workspace,
|
|
56
|
+
extensions: safeJsonParse(row.extensions, undefined),
|
|
57
|
+
riskScore: row.risk_score,
|
|
58
|
+
usageCount: row.usage_count,
|
|
59
|
+
firstSeenTs: row.first_seen_ts,
|
|
60
|
+
lastUsedAt: row.last_used_at,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/** Safely parse a JSON string, returning fallback on failure. */
|
|
64
|
+
function safeJsonParse(raw, fallback) {
|
|
65
|
+
if (raw == null)
|
|
66
|
+
return fallback;
|
|
67
|
+
try {
|
|
68
|
+
return JSON.parse(raw);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return fallback;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/** Strip undefined values from entry to avoid SQLite binding issues. */
|
|
75
|
+
function val(v) {
|
|
76
|
+
return v === undefined ? null : v;
|
|
77
|
+
}
|
|
78
|
+
function isDuplicateColumnError(error, column) {
|
|
79
|
+
if (!(error instanceof Error))
|
|
80
|
+
return false;
|
|
81
|
+
const message = error.message.toLowerCase();
|
|
82
|
+
const columnName = column.toLowerCase();
|
|
83
|
+
return (message.includes('duplicate column') || message.includes('duplicate column name')) && message.includes(columnName);
|
|
84
|
+
}
|
|
85
|
+
// ── SqliteStore ──────────────────────────────────────────────────────────────
|
|
86
|
+
class SqliteStore {
|
|
87
|
+
db;
|
|
88
|
+
loaded = false;
|
|
89
|
+
cache = new Map();
|
|
90
|
+
constructor(dbPath) {
|
|
91
|
+
this.db = new node_sqlite_1.DatabaseSync(dbPath);
|
|
92
|
+
this.initSchema();
|
|
93
|
+
}
|
|
94
|
+
initSchema() {
|
|
95
|
+
this.db.exec(sqliteSchema_js_1.PRAGMAS);
|
|
96
|
+
this.db.exec(sqliteSchema_js_1.INSTRUCTIONS_DDL);
|
|
97
|
+
this.ensureColumn('instructions', 'extensions', 'TEXT');
|
|
98
|
+
// FTS5 for full-text search (with content sync triggers)
|
|
99
|
+
try {
|
|
100
|
+
this.db.exec(sqliteSchema_js_1.FTS5_DDL);
|
|
101
|
+
}
|
|
102
|
+
catch { /* FTS5 may already exist */ }
|
|
103
|
+
// Stamp schema version if not present
|
|
104
|
+
const meta = this.db.prepare('SELECT value FROM metadata WHERE key = ?').get('schema_version');
|
|
105
|
+
if (!meta) {
|
|
106
|
+
this.db.prepare('INSERT INTO metadata (key, value) VALUES (?, ?)').run('schema_version', sqliteSchema_js_1.SCHEMA_VERSION);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
ensureColumn(table, column, ddl) {
|
|
110
|
+
const rows = this.db.prepare(`PRAGMA table_info(${table})`).all();
|
|
111
|
+
if (rows.some(row => row.name === column))
|
|
112
|
+
return;
|
|
113
|
+
try {
|
|
114
|
+
this.db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${ddl}`);
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
if (!isDuplicateColumnError(error, column))
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// ── Lifecycle ──────────────────────────────────────────────────────
|
|
122
|
+
load() {
|
|
123
|
+
const rows = this.db.prepare('SELECT * FROM instructions').all();
|
|
124
|
+
const entries = [];
|
|
125
|
+
const errors = [];
|
|
126
|
+
for (const row of rows) {
|
|
127
|
+
try {
|
|
128
|
+
entries.push(rowToEntry(row));
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
errors.push({
|
|
132
|
+
file: row.id ?? 'unknown',
|
|
133
|
+
error: err instanceof Error ? err.message : 'Row parse error',
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
this.cache.clear();
|
|
138
|
+
for (const e of entries) {
|
|
139
|
+
this.cache.set(e.id, e);
|
|
140
|
+
}
|
|
141
|
+
this.loaded = true;
|
|
142
|
+
return {
|
|
143
|
+
entries,
|
|
144
|
+
hash: (0, hashUtils_js_1.computeGovernanceHashFromEntries)(entries),
|
|
145
|
+
errors,
|
|
146
|
+
debug: { scanned: rows.length, accepted: entries.length, skipped: errors.length },
|
|
147
|
+
summary: {
|
|
148
|
+
scanned: rows.length,
|
|
149
|
+
accepted: entries.length,
|
|
150
|
+
skipped: errors.length,
|
|
151
|
+
reasons: errors.length > 0 ? { 'row-parse-error': errors.length } : {},
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
close() {
|
|
156
|
+
this.cache.clear();
|
|
157
|
+
this.loaded = false;
|
|
158
|
+
this.db.close();
|
|
159
|
+
}
|
|
160
|
+
// ── CRUD ───────────────────────────────────────────────────────────
|
|
161
|
+
get(id) {
|
|
162
|
+
this.ensureLoaded();
|
|
163
|
+
return this.cache.get(id) ?? null;
|
|
164
|
+
}
|
|
165
|
+
write(entry) {
|
|
166
|
+
const sql = `INSERT OR REPLACE INTO instructions (
|
|
167
|
+
id, title, body, rationale, priority, audience, requirement,
|
|
168
|
+
categories, content_type, primary_category, source_hash,
|
|
169
|
+
schema_version, deprecated_by, created_at, updated_at,
|
|
170
|
+
version, status, owner, priority_tier, classification,
|
|
171
|
+
last_reviewed_at, next_review_due, review_interval_days,
|
|
172
|
+
change_log, supersedes, archived_at, workspace_id, user_id,
|
|
173
|
+
team_ids, semantic_summary, created_by_agent, source_workspace,
|
|
174
|
+
extensions,
|
|
175
|
+
risk_score, usage_count, first_seen_ts, last_used_at
|
|
176
|
+
) VALUES (
|
|
177
|
+
?, ?, ?, ?, ?, ?, ?,
|
|
178
|
+
?, ?, ?, ?,
|
|
179
|
+
?, ?, ?, ?,
|
|
180
|
+
?, ?, ?, ?, ?,
|
|
181
|
+
?, ?, ?,
|
|
182
|
+
?, ?, ?, ?, ?,
|
|
183
|
+
?, ?, ?, ?, ?,
|
|
184
|
+
?, ?, ?, ?
|
|
185
|
+
)`;
|
|
186
|
+
this.db.prepare(sql).run(entry.id, entry.title, entry.body, val(entry.rationale), val(entry.priority) ?? 0, val(entry.audience) ?? 'all', val(entry.requirement) ?? 'may', JSON.stringify(entry.categories ?? []), val(entry.contentType) ?? 'instruction', val(entry.primaryCategory), entry.sourceHash ?? '', entry.schemaVersion ?? '4', val(entry.deprecatedBy), val(entry.createdAt) ?? new Date().toISOString(), val(entry.updatedAt) ?? new Date().toISOString(), val(entry.version), val(entry.status), val(entry.owner), val(entry.priorityTier), val(entry.classification), val(entry.lastReviewedAt), val(entry.nextReviewDue), val(entry.reviewIntervalDays), JSON.stringify(entry.changeLog ?? []), val(entry.supersedes), val(entry.archivedAt), val(entry.workspaceId), val(entry.userId), JSON.stringify(entry.teamIds ?? []), val(entry.semanticSummary), val(entry.createdByAgent), val(entry.sourceWorkspace), entry.extensions === undefined ? null : JSON.stringify(entry.extensions), val(entry.riskScore), val(entry.usageCount) ?? 0, val(entry.firstSeenTs), val(entry.lastUsedAt));
|
|
187
|
+
// Update in-memory cache
|
|
188
|
+
this.cache.set(entry.id, entry);
|
|
189
|
+
this.loaded = true;
|
|
190
|
+
}
|
|
191
|
+
remove(id) {
|
|
192
|
+
this.db.prepare('DELETE FROM instructions WHERE id = ?').run(id);
|
|
193
|
+
this.cache.delete(id);
|
|
194
|
+
}
|
|
195
|
+
// ── Queries ────────────────────────────────────────────────────────
|
|
196
|
+
list(opts) {
|
|
197
|
+
this.ensureLoaded();
|
|
198
|
+
let result = Array.from(this.cache.values());
|
|
199
|
+
if (opts?.category) {
|
|
200
|
+
result = result.filter(e => e.categories?.includes(opts.category));
|
|
201
|
+
}
|
|
202
|
+
if (opts?.contentType) {
|
|
203
|
+
result = result.filter(e => e.contentType === opts.contentType);
|
|
204
|
+
}
|
|
205
|
+
return result;
|
|
206
|
+
}
|
|
207
|
+
query(opts) {
|
|
208
|
+
this.ensureLoaded();
|
|
209
|
+
let result = Array.from(this.cache.values());
|
|
210
|
+
if (opts.text) {
|
|
211
|
+
const lower = opts.text.toLowerCase();
|
|
212
|
+
result = result.filter(e => e.title.toLowerCase().includes(lower) ||
|
|
213
|
+
e.body.toLowerCase().includes(lower) ||
|
|
214
|
+
(e.semanticSummary && e.semanticSummary.toLowerCase().includes(lower)));
|
|
215
|
+
}
|
|
216
|
+
if (opts.categoriesAny?.length) {
|
|
217
|
+
const set = new Set(opts.categoriesAny);
|
|
218
|
+
result = result.filter(e => e.categories?.some(c => set.has(c)));
|
|
219
|
+
}
|
|
220
|
+
if (opts.categoriesAll?.length) {
|
|
221
|
+
result = result.filter(e => opts.categoriesAll.every(c => e.categories?.includes(c)));
|
|
222
|
+
}
|
|
223
|
+
if (opts.excludeCategories?.length) {
|
|
224
|
+
const excl = new Set(opts.excludeCategories);
|
|
225
|
+
result = result.filter(e => !e.categories?.some(c => excl.has(c)));
|
|
226
|
+
}
|
|
227
|
+
if (opts.contentType) {
|
|
228
|
+
result = result.filter(e => e.contentType === opts.contentType);
|
|
229
|
+
}
|
|
230
|
+
if (opts.priorityMin !== undefined) {
|
|
231
|
+
result = result.filter(e => e.priority >= opts.priorityMin);
|
|
232
|
+
}
|
|
233
|
+
if (opts.priorityMax !== undefined) {
|
|
234
|
+
result = result.filter(e => e.priority <= opts.priorityMax);
|
|
235
|
+
}
|
|
236
|
+
if (opts.priorityTiers?.length) {
|
|
237
|
+
const tiers = new Set(opts.priorityTiers);
|
|
238
|
+
result = result.filter(e => e.priorityTier && tiers.has(e.priorityTier));
|
|
239
|
+
}
|
|
240
|
+
if (opts.requirements?.length) {
|
|
241
|
+
const reqs = new Set(opts.requirements);
|
|
242
|
+
result = result.filter(e => reqs.has(e.requirement));
|
|
243
|
+
}
|
|
244
|
+
if (opts.offset) {
|
|
245
|
+
result = result.slice(opts.offset);
|
|
246
|
+
}
|
|
247
|
+
if (opts.limit) {
|
|
248
|
+
result = result.slice(0, opts.limit);
|
|
249
|
+
}
|
|
250
|
+
return result;
|
|
251
|
+
}
|
|
252
|
+
listScoped(opts) {
|
|
253
|
+
this.ensureLoaded();
|
|
254
|
+
let result = Array.from(this.cache.values());
|
|
255
|
+
if (opts.userId) {
|
|
256
|
+
result = result.filter(e => e.userId === opts.userId || e.audience === 'all');
|
|
257
|
+
}
|
|
258
|
+
if (opts.workspaceId) {
|
|
259
|
+
result = result.filter(e => e.workspaceId === opts.workspaceId || e.audience === 'all');
|
|
260
|
+
}
|
|
261
|
+
if (opts.teamIds?.length) {
|
|
262
|
+
const teams = new Set(opts.teamIds);
|
|
263
|
+
result = result.filter(e => e.audience === 'all' ||
|
|
264
|
+
e.teamIds?.some(t => teams.has(t)));
|
|
265
|
+
}
|
|
266
|
+
return result;
|
|
267
|
+
}
|
|
268
|
+
search(opts) {
|
|
269
|
+
this.ensureLoaded();
|
|
270
|
+
const results = [];
|
|
271
|
+
for (const entry of this.cache.values()) {
|
|
272
|
+
let score = 0;
|
|
273
|
+
const titleLower = entry.title.toLowerCase();
|
|
274
|
+
const bodyLower = entry.body.toLowerCase();
|
|
275
|
+
const catStr = (entry.categories ?? []).join(' ').toLowerCase();
|
|
276
|
+
for (const kw of opts.keywords) {
|
|
277
|
+
const kwLower = opts.caseSensitive ? kw : kw.toLowerCase();
|
|
278
|
+
const title = opts.caseSensitive ? entry.title : titleLower;
|
|
279
|
+
const body = opts.caseSensitive ? entry.body : bodyLower;
|
|
280
|
+
if (title.includes(kwLower))
|
|
281
|
+
score += 3;
|
|
282
|
+
if (body.includes(kwLower))
|
|
283
|
+
score += 1;
|
|
284
|
+
if (opts.includeCategories && catStr.includes(kwLower))
|
|
285
|
+
score += 2;
|
|
286
|
+
}
|
|
287
|
+
if (score > 0) {
|
|
288
|
+
results.push({ id: entry.id, score });
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
results.sort((a, b) => b.score - a.score);
|
|
292
|
+
if (opts.limit) {
|
|
293
|
+
return results.slice(0, opts.limit);
|
|
294
|
+
}
|
|
295
|
+
return results;
|
|
296
|
+
}
|
|
297
|
+
categories() {
|
|
298
|
+
this.ensureLoaded();
|
|
299
|
+
const counts = new Map();
|
|
300
|
+
for (const entry of this.cache.values()) {
|
|
301
|
+
for (const cat of entry.categories ?? []) {
|
|
302
|
+
counts.set(cat, (counts.get(cat) ?? 0) + 1);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return counts;
|
|
306
|
+
}
|
|
307
|
+
// ── FTS5 Search ────────────────────────────────────────────────────
|
|
308
|
+
/**
|
|
309
|
+
* Full-text search using FTS5 with BM25 ranking.
|
|
310
|
+
* More efficient than in-memory scan for large instruction sets.
|
|
311
|
+
* Falls back to in-memory search if FTS5 is unavailable.
|
|
312
|
+
*/
|
|
313
|
+
searchFts(opts) {
|
|
314
|
+
this.ensureLoaded();
|
|
315
|
+
try {
|
|
316
|
+
// Build FTS5 MATCH query: OR all keywords
|
|
317
|
+
const matchTerms = opts.keywords
|
|
318
|
+
.map(kw => `"${kw.replace(/"/g, '""')}"`)
|
|
319
|
+
.join(' OR ');
|
|
320
|
+
const sql = `
|
|
321
|
+
SELECT id, bm25(instructions_fts, 0, 10.0, 5.0, 1.0) as rank
|
|
322
|
+
FROM instructions_fts
|
|
323
|
+
WHERE instructions_fts MATCH ?
|
|
324
|
+
ORDER BY rank
|
|
325
|
+
${opts.limit ? 'LIMIT ?' : ''}
|
|
326
|
+
`;
|
|
327
|
+
const params = [matchTerms];
|
|
328
|
+
if (opts.limit)
|
|
329
|
+
params.push(opts.limit);
|
|
330
|
+
const rows = this.db.prepare(sql).all(...params);
|
|
331
|
+
return rows.map(row => {
|
|
332
|
+
const r = row;
|
|
333
|
+
return {
|
|
334
|
+
id: r.id,
|
|
335
|
+
// BM25 returns negative scores (lower = better), negate for positive ranking
|
|
336
|
+
score: -r.rank,
|
|
337
|
+
};
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
catch {
|
|
341
|
+
// FTS5 unavailable — fall back to in-memory search
|
|
342
|
+
return this.search(opts);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
// ── Integrity ──────────────────────────────────────────────────────
|
|
346
|
+
computeHash() {
|
|
347
|
+
this.ensureLoaded();
|
|
348
|
+
return (0, hashUtils_js_1.computeGovernanceHashFromEntries)(Array.from(this.cache.values()));
|
|
349
|
+
}
|
|
350
|
+
count() {
|
|
351
|
+
this.ensureLoaded();
|
|
352
|
+
return this.cache.size;
|
|
353
|
+
}
|
|
354
|
+
// ── Internal ───────────────────────────────────────────────────────
|
|
355
|
+
ensureLoaded() {
|
|
356
|
+
if (!this.loaded) {
|
|
357
|
+
this.load();
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
exports.SqliteStore = SqliteStore;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SqliteUsageStore — Usage tracking backed by node:sqlite.
|
|
3
|
+
*
|
|
4
|
+
* Stores instruction usage counts, timestamps, and signals in the
|
|
5
|
+
* usage table. Provides atomic increment and bulk snapshot operations.
|
|
6
|
+
*/
|
|
7
|
+
export interface UsageRecord {
|
|
8
|
+
instructionId: string;
|
|
9
|
+
usageCount: number;
|
|
10
|
+
firstSeenTs: string | null;
|
|
11
|
+
lastUsedAt: string | null;
|
|
12
|
+
lastAction: string | null;
|
|
13
|
+
lastSignal: string | null;
|
|
14
|
+
lastComment: string | null;
|
|
15
|
+
}
|
|
16
|
+
export interface TrackOptions {
|
|
17
|
+
action?: string;
|
|
18
|
+
signal?: string;
|
|
19
|
+
comment?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare class SqliteUsageStore {
|
|
22
|
+
private db;
|
|
23
|
+
constructor(dbPath: string);
|
|
24
|
+
/** Get usage record for an instruction. */
|
|
25
|
+
get(instructionId: string): UsageRecord | null;
|
|
26
|
+
/** Increment usage count and update timestamps/signals. */
|
|
27
|
+
increment(instructionId: string, opts?: TrackOptions): UsageRecord;
|
|
28
|
+
/** Get all usage records as a snapshot. */
|
|
29
|
+
snapshot(): Record<string, UsageRecord>;
|
|
30
|
+
/** Reset usage for a specific instruction or all. */
|
|
31
|
+
flush(instructionId?: string): void;
|
|
32
|
+
/** Count of tracked instructions. */
|
|
33
|
+
count(): number;
|
|
34
|
+
close(): void;
|
|
35
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SqliteUsageStore — Usage tracking backed by node:sqlite.
|
|
4
|
+
*
|
|
5
|
+
* Stores instruction usage counts, timestamps, and signals in the
|
|
6
|
+
* usage table. Provides atomic increment and bulk snapshot operations.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.SqliteUsageStore = void 0;
|
|
10
|
+
const node_sqlite_1 = require("node:sqlite");
|
|
11
|
+
const sqliteSchema_js_1 = require("./sqliteSchema.js");
|
|
12
|
+
class SqliteUsageStore {
|
|
13
|
+
db;
|
|
14
|
+
constructor(dbPath) {
|
|
15
|
+
this.db = new node_sqlite_1.DatabaseSync(dbPath);
|
|
16
|
+
this.db.exec(sqliteSchema_js_1.PRAGMAS);
|
|
17
|
+
this.db.exec(sqliteSchema_js_1.INSTRUCTIONS_DDL);
|
|
18
|
+
}
|
|
19
|
+
/** Get usage record for an instruction. */
|
|
20
|
+
get(instructionId) {
|
|
21
|
+
const row = this.db.prepare('SELECT * FROM usage WHERE instruction_id = ?').get(instructionId);
|
|
22
|
+
if (!row)
|
|
23
|
+
return null;
|
|
24
|
+
return {
|
|
25
|
+
instructionId: row.instruction_id,
|
|
26
|
+
usageCount: row.usage_count ?? 0,
|
|
27
|
+
firstSeenTs: row.first_seen_ts,
|
|
28
|
+
lastUsedAt: row.last_used_at,
|
|
29
|
+
lastAction: row.last_action,
|
|
30
|
+
lastSignal: row.last_signal,
|
|
31
|
+
lastComment: row.last_comment,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/** Increment usage count and update timestamps/signals. */
|
|
35
|
+
increment(instructionId, opts) {
|
|
36
|
+
const now = new Date().toISOString();
|
|
37
|
+
const existing = this.get(instructionId);
|
|
38
|
+
if (existing) {
|
|
39
|
+
this.db.prepare(`
|
|
40
|
+
UPDATE usage SET
|
|
41
|
+
usage_count = usage_count + 1,
|
|
42
|
+
last_used_at = ?,
|
|
43
|
+
last_action = COALESCE(?, last_action),
|
|
44
|
+
last_signal = COALESCE(?, last_signal),
|
|
45
|
+
last_comment = COALESCE(?, last_comment)
|
|
46
|
+
WHERE instruction_id = ?
|
|
47
|
+
`).run(now, opts?.action ?? null, opts?.signal ?? null, opts?.comment ?? null, instructionId);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
this.db.prepare(`
|
|
51
|
+
INSERT INTO usage (instruction_id, usage_count, first_seen_ts, last_used_at, last_action, last_signal, last_comment)
|
|
52
|
+
VALUES (?, 1, ?, ?, ?, ?, ?)
|
|
53
|
+
`).run(instructionId, now, now, opts?.action ?? null, opts?.signal ?? null, opts?.comment ?? null);
|
|
54
|
+
}
|
|
55
|
+
return this.get(instructionId);
|
|
56
|
+
}
|
|
57
|
+
/** Get all usage records as a snapshot. */
|
|
58
|
+
snapshot() {
|
|
59
|
+
const rows = this.db.prepare('SELECT * FROM usage').all();
|
|
60
|
+
const result = {};
|
|
61
|
+
for (const row of rows) {
|
|
62
|
+
const r = row;
|
|
63
|
+
const id = r.instruction_id;
|
|
64
|
+
result[id] = {
|
|
65
|
+
instructionId: id,
|
|
66
|
+
usageCount: r.usage_count ?? 0,
|
|
67
|
+
firstSeenTs: r.first_seen_ts,
|
|
68
|
+
lastUsedAt: r.last_used_at,
|
|
69
|
+
lastAction: r.last_action,
|
|
70
|
+
lastSignal: r.last_signal,
|
|
71
|
+
lastComment: r.last_comment,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
/** Reset usage for a specific instruction or all. */
|
|
77
|
+
flush(instructionId) {
|
|
78
|
+
if (instructionId) {
|
|
79
|
+
this.db.prepare('DELETE FROM usage WHERE instruction_id = ?').run(instructionId);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
this.db.exec('DELETE FROM usage');
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/** Count of tracked instructions. */
|
|
86
|
+
count() {
|
|
87
|
+
const row = this.db.prepare('SELECT COUNT(*) as cnt FROM usage').get();
|
|
88
|
+
return row?.cnt ?? 0;
|
|
89
|
+
}
|
|
90
|
+
close() {
|
|
91
|
+
this.db.close();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
exports.SqliteUsageStore = SqliteUsageStore;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IInstructionStore — Storage abstraction for instruction persistence.
|
|
3
|
+
*
|
|
4
|
+
* Implementations:
|
|
5
|
+
* - JsonFileStore: JSON-file-per-instruction (default, current behavior)
|
|
6
|
+
* - SqliteStore: SQLite database (experimental, behind feature flag)
|
|
7
|
+
*
|
|
8
|
+
* IndexContext delegates all storage I/O through this interface.
|
|
9
|
+
* Queries, search, and usage tracking are backend-agnostic.
|
|
10
|
+
*/
|
|
11
|
+
import { InstructionEntry } from '../../models/instruction.js';
|
|
12
|
+
/** Options for listing instructions with filters. */
|
|
13
|
+
export interface ListOptions {
|
|
14
|
+
category?: string;
|
|
15
|
+
contentType?: string;
|
|
16
|
+
}
|
|
17
|
+
/** Options for complex multi-filter queries. */
|
|
18
|
+
export interface QueryOptions {
|
|
19
|
+
text?: string;
|
|
20
|
+
categoriesAny?: string[];
|
|
21
|
+
categoriesAll?: string[];
|
|
22
|
+
excludeCategories?: string[];
|
|
23
|
+
contentType?: string;
|
|
24
|
+
priorityMin?: number;
|
|
25
|
+
priorityMax?: number;
|
|
26
|
+
priorityTiers?: string[];
|
|
27
|
+
requirements?: string[];
|
|
28
|
+
offset?: number;
|
|
29
|
+
limit?: number;
|
|
30
|
+
}
|
|
31
|
+
/** Options for scoped listing (workspace/user/team). */
|
|
32
|
+
export interface ScopedListOptions {
|
|
33
|
+
userId?: string;
|
|
34
|
+
workspaceId?: string;
|
|
35
|
+
teamIds?: string[];
|
|
36
|
+
}
|
|
37
|
+
/** Options for keyword search. */
|
|
38
|
+
export interface SearchOptions {
|
|
39
|
+
keywords: string[];
|
|
40
|
+
includeCategories?: boolean;
|
|
41
|
+
caseSensitive?: boolean;
|
|
42
|
+
limit?: number;
|
|
43
|
+
}
|
|
44
|
+
/** A single search result with relevance score. */
|
|
45
|
+
export interface SearchResult {
|
|
46
|
+
id: string;
|
|
47
|
+
score: number;
|
|
48
|
+
}
|
|
49
|
+
/** Persisted usage record for an instruction. */
|
|
50
|
+
export interface UsagePersistRecord {
|
|
51
|
+
usageCount?: number;
|
|
52
|
+
firstSeenTs?: string;
|
|
53
|
+
lastUsedAt?: string;
|
|
54
|
+
lastAction?: string;
|
|
55
|
+
lastSignal?: string;
|
|
56
|
+
lastComment?: string;
|
|
57
|
+
}
|
|
58
|
+
/** Options for tracking a usage event. */
|
|
59
|
+
export interface UsageTrackOptions {
|
|
60
|
+
action?: string;
|
|
61
|
+
signal?: string;
|
|
62
|
+
comment?: string;
|
|
63
|
+
}
|
|
64
|
+
/** Result of loading the full instruction set. */
|
|
65
|
+
export interface LoadResult {
|
|
66
|
+
entries: InstructionEntry[];
|
|
67
|
+
hash: string;
|
|
68
|
+
errors: {
|
|
69
|
+
file: string;
|
|
70
|
+
error: string;
|
|
71
|
+
}[];
|
|
72
|
+
debug?: {
|
|
73
|
+
scanned: number;
|
|
74
|
+
accepted: number;
|
|
75
|
+
skipped: number;
|
|
76
|
+
trace?: {
|
|
77
|
+
file: string;
|
|
78
|
+
accepted: boolean;
|
|
79
|
+
reason?: string;
|
|
80
|
+
}[];
|
|
81
|
+
};
|
|
82
|
+
summary?: {
|
|
83
|
+
scanned: number;
|
|
84
|
+
accepted: number;
|
|
85
|
+
skipped: number;
|
|
86
|
+
reasons: Record<string, number>;
|
|
87
|
+
cacheHits?: number;
|
|
88
|
+
hashHits?: number;
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Storage backend interface for the instruction index.
|
|
93
|
+
*
|
|
94
|
+
* All methods are synchronous unless otherwise noted (matching current
|
|
95
|
+
* IndexContext behavior). Async methods are marked with Promise return types.
|
|
96
|
+
*
|
|
97
|
+
* @remarks
|
|
98
|
+
* Implementations must ensure:
|
|
99
|
+
* - `load()` is idempotent and safe to call multiple times
|
|
100
|
+
* - `write()` is atomic (entry is fully written or not at all)
|
|
101
|
+
* - `remove()` tolerates missing IDs (no-op, no throw)
|
|
102
|
+
* - `computeHash()` returns identical hashes for identical entry sets
|
|
103
|
+
* - `get()` returns null for missing IDs (no throw)
|
|
104
|
+
*/
|
|
105
|
+
export interface IInstructionStore {
|
|
106
|
+
/**
|
|
107
|
+
* Load all instructions from the backing store.
|
|
108
|
+
* @returns Load result with entries, hash, and diagnostics.
|
|
109
|
+
*/
|
|
110
|
+
load(): LoadResult;
|
|
111
|
+
/**
|
|
112
|
+
* Close the store and release resources (e.g., DB connections).
|
|
113
|
+
* No-op for file-based stores.
|
|
114
|
+
*/
|
|
115
|
+
close(): void;
|
|
116
|
+
/**
|
|
117
|
+
* Get a single instruction by ID.
|
|
118
|
+
* @param id - Instruction ID.
|
|
119
|
+
* @returns The entry, or null if not found.
|
|
120
|
+
*/
|
|
121
|
+
get(id: string): InstructionEntry | null;
|
|
122
|
+
/**
|
|
123
|
+
* Write (create or update) an instruction.
|
|
124
|
+
* @param entry - The instruction to persist.
|
|
125
|
+
*/
|
|
126
|
+
write(entry: InstructionEntry): void;
|
|
127
|
+
/**
|
|
128
|
+
* Remove an instruction by ID. No-op if not found.
|
|
129
|
+
* @param id - Instruction ID to remove.
|
|
130
|
+
*/
|
|
131
|
+
remove(id: string): void;
|
|
132
|
+
/**
|
|
133
|
+
* List instructions with optional category/contentType filter.
|
|
134
|
+
* @param opts - Filter options.
|
|
135
|
+
* @returns Array of matching entries.
|
|
136
|
+
*/
|
|
137
|
+
list(opts?: ListOptions): InstructionEntry[];
|
|
138
|
+
/**
|
|
139
|
+
* Complex multi-filter query with pagination.
|
|
140
|
+
* @param opts - Query options.
|
|
141
|
+
* @returns Array of matching entries (paginated).
|
|
142
|
+
*/
|
|
143
|
+
query(opts: QueryOptions): InstructionEntry[];
|
|
144
|
+
/**
|
|
145
|
+
* List instructions scoped to a user, workspace, or team.
|
|
146
|
+
* @param opts - Scoping options.
|
|
147
|
+
* @returns Array of matching entries.
|
|
148
|
+
*/
|
|
149
|
+
listScoped(opts: ScopedListOptions): InstructionEntry[];
|
|
150
|
+
/**
|
|
151
|
+
* Search instructions by keywords with relevance scoring.
|
|
152
|
+
* @param opts - Search options with keywords.
|
|
153
|
+
* @returns Array of { id, score } sorted by relevance descending.
|
|
154
|
+
*/
|
|
155
|
+
search(opts: SearchOptions): SearchResult[];
|
|
156
|
+
/**
|
|
157
|
+
* Get all unique categories with occurrence counts.
|
|
158
|
+
* @returns Map of category name → count.
|
|
159
|
+
*/
|
|
160
|
+
categories(): Map<string, number>;
|
|
161
|
+
/**
|
|
162
|
+
* Compute deterministic governance hash over all entries.
|
|
163
|
+
* Must return identical hash for identical entry sets regardless of backend.
|
|
164
|
+
* @returns SHA256 hex string.
|
|
165
|
+
*/
|
|
166
|
+
computeHash(): string;
|
|
167
|
+
/**
|
|
168
|
+
* Get the count of loaded instructions.
|
|
169
|
+
*/
|
|
170
|
+
count(): number;
|
|
171
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* IInstructionStore — Storage abstraction for instruction persistence.
|
|
4
|
+
*
|
|
5
|
+
* Implementations:
|
|
6
|
+
* - JsonFileStore: JSON-file-per-instruction (default, current behavior)
|
|
7
|
+
* - SqliteStore: SQLite database (experimental, behind feature flag)
|
|
8
|
+
*
|
|
9
|
+
* IndexContext delegates all storage I/O through this interface.
|
|
10
|
+
* Queries, search, and usage tracking are backend-agnostic.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { computeGovernanceHash, projectGovernance, getIndexState } from './indexContext';
|
|
2
|
+
import './handlers.instructions';
|
|
3
|
+
import './handlers.search';
|
|
4
|
+
import './instructions.dispatcher';
|
|
5
|
+
import './handlers.integrity';
|
|
6
|
+
import './handlers.usage';
|
|
7
|
+
import './handlers.prompt';
|
|
8
|
+
import './handlers.metrics';
|
|
9
|
+
import './handlers.gates';
|
|
10
|
+
import './handlers.testPrimitive';
|
|
11
|
+
import './handlers.diagnostics';
|
|
12
|
+
import './handlers.feedback';
|
|
13
|
+
import './handlers.help';
|
|
14
|
+
import './handlers.instructionSchema';
|
|
15
|
+
import './handlers.bootstrap';
|
|
16
|
+
import './handlers.manifest';
|
|
17
|
+
import './handlers.instructionsDiagnostics';
|
|
18
|
+
import './handlers.graph';
|
|
19
|
+
import './handlers.activation';
|
|
20
|
+
import './handlers.promote';
|
|
21
|
+
import './handlers.messaging';
|
|
22
|
+
import './handlers.trace';
|
|
23
|
+
export { computeGovernanceHash, projectGovernance, getIndexState };
|