@legioncodeinc/nectar 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +662 -0
- package/README.md +307 -0
- package/dist/api/daemon-api-wiring.d.ts +72 -0
- package/dist/api/daemon-api-wiring.d.ts.map +1 -0
- package/dist/api/daemon-api-wiring.js +150 -0
- package/dist/api/daemon-api-wiring.js.map +1 -0
- package/dist/api/hive-graph-api.d.ts +136 -0
- package/dist/api/hive-graph-api.d.ts.map +1 -0
- package/dist/api/hive-graph-api.js +234 -0
- package/dist/api/hive-graph-api.js.map +1 -0
- package/dist/api/loopback-client.d.ts +27 -0
- package/dist/api/loopback-client.d.ts.map +1 -0
- package/dist/api/loopback-client.js +87 -0
- package/dist/api/loopback-client.js.map +1 -0
- package/dist/api/router.d.ts +172 -0
- package/dist/api/router.d.ts.map +1 -0
- package/dist/api/router.js +212 -0
- package/dist/api/router.js.map +1 -0
- package/dist/api/status-query.d.ts +49 -0
- package/dist/api/status-query.d.ts.map +1 -0
- package/dist/api/status-query.js +103 -0
- package/dist/api/status-query.js.map +1 -0
- package/dist/brood-guard.d.ts +24 -0
- package/dist/brood-guard.d.ts.map +1 -0
- package/dist/brood-guard.js +19 -0
- package/dist/brood-guard.js.map +1 -0
- package/dist/brood-prereqs.d.ts +62 -0
- package/dist/brood-prereqs.d.ts.map +1 -0
- package/dist/brood-prereqs.js +87 -0
- package/dist/brood-prereqs.js.map +1 -0
- package/dist/brooding/bucketing.d.ts +68 -0
- package/dist/brooding/bucketing.d.ts.map +1 -0
- package/dist/brooding/bucketing.js +122 -0
- package/dist/brooding/bucketing.js.map +1 -0
- package/dist/brooding/cli.d.ts +78 -0
- package/dist/brooding/cli.d.ts.map +1 -0
- package/dist/brooding/cli.js +140 -0
- package/dist/brooding/cli.js.map +1 -0
- package/dist/brooding/constants.d.ts +75 -0
- package/dist/brooding/constants.d.ts.map +1 -0
- package/dist/brooding/constants.js +91 -0
- package/dist/brooding/constants.js.map +1 -0
- package/dist/brooding/cost.d.ts +110 -0
- package/dist/brooding/cost.d.ts.map +1 -0
- package/dist/brooding/cost.js +96 -0
- package/dist/brooding/cost.js.map +1 -0
- package/dist/brooding/describe.d.ts +152 -0
- package/dist/brooding/describe.d.ts.map +1 -0
- package/dist/brooding/describe.js +281 -0
- package/dist/brooding/describe.js.map +1 -0
- package/dist/brooding/discovery.d.ts +116 -0
- package/dist/brooding/discovery.d.ts.map +1 -0
- package/dist/brooding/discovery.js +179 -0
- package/dist/brooding/discovery.js.map +1 -0
- package/dist/brooding/index.d.ts +23 -0
- package/dist/brooding/index.d.ts.map +1 -0
- package/dist/brooding/index.js +33 -0
- package/dist/brooding/index.js.map +1 -0
- package/dist/brooding/pipeline-async.d.ts +97 -0
- package/dist/brooding/pipeline-async.d.ts.map +1 -0
- package/dist/brooding/pipeline-async.js +364 -0
- package/dist/brooding/pipeline-async.js.map +1 -0
- package/dist/brooding/pipeline.d.ts +198 -0
- package/dist/brooding/pipeline.d.ts.map +1 -0
- package/dist/brooding/pipeline.js +454 -0
- package/dist/brooding/pipeline.js.map +1 -0
- package/dist/brooding/precheck.d.ts +52 -0
- package/dist/brooding/precheck.d.ts.map +1 -0
- package/dist/brooding/precheck.js +143 -0
- package/dist/brooding/precheck.js.map +1 -0
- package/dist/brooding/resumability.d.ts +57 -0
- package/dist/brooding/resumability.d.ts.map +1 -0
- package/dist/brooding/resumability.js +46 -0
- package/dist/brooding/resumability.js.map +1 -0
- package/dist/cli.d.ts +139 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +912 -0
- package/dist/cli.js.map +1 -0
- package/dist/config-file.d.ts +52 -0
- package/dist/config-file.d.ts.map +1 -0
- package/dist/config-file.js +130 -0
- package/dist/config-file.js.map +1 -0
- package/dist/config.d.ts +49 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +98 -0
- package/dist/config.js.map +1 -0
- package/dist/daemon.d.ts +265 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +664 -0
- package/dist/daemon.js.map +1 -0
- package/dist/doctor-registry.d.ts +134 -0
- package/dist/doctor-registry.d.ts.map +1 -0
- package/dist/doctor-registry.js +173 -0
- package/dist/doctor-registry.js.map +1 -0
- package/dist/embeddings/cohere-portkey.d.ts +67 -0
- package/dist/embeddings/cohere-portkey.d.ts.map +1 -0
- package/dist/embeddings/cohere-portkey.js +171 -0
- package/dist/embeddings/cohere-portkey.js.map +1 -0
- package/dist/embeddings/config.d.ts +74 -0
- package/dist/embeddings/config.d.ts.map +1 -0
- package/dist/embeddings/config.js +131 -0
- package/dist/embeddings/config.js.map +1 -0
- package/dist/embeddings/guard.d.ts +34 -0
- package/dist/embeddings/guard.d.ts.map +1 -0
- package/dist/embeddings/guard.js +67 -0
- package/dist/embeddings/guard.js.map +1 -0
- package/dist/embeddings/hosted-portkey.d.ts +73 -0
- package/dist/embeddings/hosted-portkey.d.ts.map +1 -0
- package/dist/embeddings/hosted-portkey.js +179 -0
- package/dist/embeddings/hosted-portkey.js.map +1 -0
- package/dist/embeddings/http.d.ts +33 -0
- package/dist/embeddings/http.d.ts.map +1 -0
- package/dist/embeddings/http.js +19 -0
- package/dist/embeddings/http.js.map +1 -0
- package/dist/embeddings/index.d.ts +17 -0
- package/dist/embeddings/index.d.ts.map +1 -0
- package/dist/embeddings/index.js +17 -0
- package/dist/embeddings/index.js.map +1 -0
- package/dist/embeddings/local-nomic.d.ts +78 -0
- package/dist/embeddings/local-nomic.d.ts.map +1 -0
- package/dist/embeddings/local-nomic.js +126 -0
- package/dist/embeddings/local-nomic.js.map +1 -0
- package/dist/embeddings/provider.d.ts +79 -0
- package/dist/embeddings/provider.d.ts.map +1 -0
- package/dist/embeddings/provider.js +50 -0
- package/dist/embeddings/provider.js.map +1 -0
- package/dist/enricher/config.d.ts +43 -0
- package/dist/enricher/config.d.ts.map +1 -0
- package/dist/enricher/config.js +34 -0
- package/dist/enricher/config.js.map +1 -0
- package/dist/enricher/content-cache.d.ts +29 -0
- package/dist/enricher/content-cache.d.ts.map +1 -0
- package/dist/enricher/content-cache.js +24 -0
- package/dist/enricher/content-cache.js.map +1 -0
- package/dist/enricher/cycle.d.ts +71 -0
- package/dist/enricher/cycle.d.ts.map +1 -0
- package/dist/enricher/cycle.js +319 -0
- package/dist/enricher/cycle.js.map +1 -0
- package/dist/enricher/describe.d.ts +61 -0
- package/dist/enricher/describe.d.ts.map +1 -0
- package/dist/enricher/describe.js +175 -0
- package/dist/enricher/describe.js.map +1 -0
- package/dist/enricher/failure.d.ts +25 -0
- package/dist/enricher/failure.d.ts.map +1 -0
- package/dist/enricher/failure.js +46 -0
- package/dist/enricher/failure.js.map +1 -0
- package/dist/enricher/index.d.ts +22 -0
- package/dist/enricher/index.d.ts.map +1 -0
- package/dist/enricher/index.js +22 -0
- package/dist/enricher/index.js.map +1 -0
- package/dist/enricher/jaccard.d.ts +11 -0
- package/dist/enricher/jaccard.d.ts.map +1 -0
- package/dist/enricher/jaccard.js +29 -0
- package/dist/enricher/jaccard.js.map +1 -0
- package/dist/enricher/loop.d.ts +22 -0
- package/dist/enricher/loop.d.ts.map +1 -0
- package/dist/enricher/loop.js +34 -0
- package/dist/enricher/loop.js.map +1 -0
- package/dist/enricher/meaningful-change.d.ts +28 -0
- package/dist/enricher/meaningful-change.d.ts.map +1 -0
- package/dist/enricher/meaningful-change.js +41 -0
- package/dist/enricher/meaningful-change.js.map +1 -0
- package/dist/enricher/observability.d.ts +22 -0
- package/dist/enricher/observability.d.ts.map +1 -0
- package/dist/enricher/observability.js +55 -0
- package/dist/enricher/observability.js.map +1 -0
- package/dist/enricher/pending-query.d.ts +35 -0
- package/dist/enricher/pending-query.d.ts.map +1 -0
- package/dist/enricher/pending-query.js +54 -0
- package/dist/enricher/pending-query.js.map +1 -0
- package/dist/enricher/sql-update.d.ts +7 -0
- package/dist/enricher/sql-update.d.ts.map +1 -0
- package/dist/enricher/sql-update.js +22 -0
- package/dist/enricher/sql-update.js.map +1 -0
- package/dist/enricher/store-adapter.d.ts +98 -0
- package/dist/enricher/store-adapter.d.ts.map +1 -0
- package/dist/enricher/store-adapter.js +129 -0
- package/dist/enricher/store-adapter.js.map +1 -0
- package/dist/enricher/store.d.ts +58 -0
- package/dist/enricher/store.d.ts.map +1 -0
- package/dist/enricher/store.js +126 -0
- package/dist/enricher/store.js.map +1 -0
- package/dist/enricher/tokenize.d.ts +10 -0
- package/dist/enricher/tokenize.d.ts.map +1 -0
- package/dist/enricher/tokenize.js +28 -0
- package/dist/enricher/tokenize.js.map +1 -0
- package/dist/errors.d.ts +41 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +56 -0
- package/dist/errors.js.map +1 -0
- package/dist/health.d.ts +147 -0
- package/dist/health.d.ts.map +1 -0
- package/dist/health.js +168 -0
- package/dist/health.js.map +1 -0
- package/dist/hive-graph/deeplake-credentials.d.ts +68 -0
- package/dist/hive-graph/deeplake-credentials.d.ts.map +1 -0
- package/dist/hive-graph/deeplake-credentials.js +135 -0
- package/dist/hive-graph/deeplake-credentials.js.map +1 -0
- package/dist/hive-graph/deeplake-heal.d.ts +63 -0
- package/dist/hive-graph/deeplake-heal.d.ts.map +1 -0
- package/dist/hive-graph/deeplake-heal.js +118 -0
- package/dist/hive-graph/deeplake-heal.js.map +1 -0
- package/dist/hive-graph/deeplake-store.d.ts +199 -0
- package/dist/hive-graph/deeplake-store.d.ts.map +1 -0
- package/dist/hive-graph/deeplake-store.js +541 -0
- package/dist/hive-graph/deeplake-store.js.map +1 -0
- package/dist/hive-graph/deeplake-transport.d.ts +89 -0
- package/dist/hive-graph/deeplake-transport.d.ts.map +1 -0
- package/dist/hive-graph/deeplake-transport.js +145 -0
- package/dist/hive-graph/deeplake-transport.js.map +1 -0
- package/dist/hive-graph/hash.d.ts +3 -0
- package/dist/hive-graph/hash.d.ts.map +1 -0
- package/dist/hive-graph/hash.js +12 -0
- package/dist/hive-graph/hash.js.map +1 -0
- package/dist/hive-graph/memory-store.d.ts +39 -0
- package/dist/hive-graph/memory-store.d.ts.map +1 -0
- package/dist/hive-graph/memory-store.js +125 -0
- package/dist/hive-graph/memory-store.js.map +1 -0
- package/dist/hive-graph/model.d.ts +109 -0
- package/dist/hive-graph/model.d.ts.map +1 -0
- package/dist/hive-graph/model.js +36 -0
- package/dist/hive-graph/model.js.map +1 -0
- package/dist/hive-graph/paths.d.ts +7 -0
- package/dist/hive-graph/paths.d.ts.map +1 -0
- package/dist/hive-graph/paths.js +26 -0
- package/dist/hive-graph/paths.js.map +1 -0
- package/dist/hive-graph/project-scope.d.ts +99 -0
- package/dist/hive-graph/project-scope.d.ts.map +1 -0
- package/dist/hive-graph/project-scope.js +286 -0
- package/dist/hive-graph/project-scope.js.map +1 -0
- package/dist/hive-graph/schema.d.ts +53 -0
- package/dist/hive-graph/schema.d.ts.map +1 -0
- package/dist/hive-graph/schema.js +139 -0
- package/dist/hive-graph/schema.js.map +1 -0
- package/dist/hive-graph/search-types.d.ts +82 -0
- package/dist/hive-graph/search-types.d.ts.map +1 -0
- package/dist/hive-graph/search-types.js +2 -0
- package/dist/hive-graph/search-types.js.map +1 -0
- package/dist/hive-graph/search.d.ts +51 -0
- package/dist/hive-graph/search.d.ts.map +1 -0
- package/dist/hive-graph/search.js +417 -0
- package/dist/hive-graph/search.js.map +1 -0
- package/dist/hive-graph/sql-guards.d.ts +99 -0
- package/dist/hive-graph/sql-guards.d.ts.map +1 -0
- package/dist/hive-graph/sql-guards.js +129 -0
- package/dist/hive-graph/sql-guards.js.map +1 -0
- package/dist/hive-graph/store.d.ts +151 -0
- package/dist/hive-graph/store.d.ts.map +1 -0
- package/dist/hive-graph/store.js +2 -0
- package/dist/hive-graph/store.js.map +1 -0
- package/dist/hive-graph/ulid.d.ts +14 -0
- package/dist/hive-graph/ulid.d.ts.map +1 -0
- package/dist/hive-graph/ulid.js +109 -0
- package/dist/hive-graph/ulid.js.map +1 -0
- package/dist/hivedoctor-registry.d.ts +111 -0
- package/dist/hivedoctor-registry.d.ts.map +1 -0
- package/dist/hivedoctor-registry.js +143 -0
- package/dist/hivedoctor-registry.js.map +1 -0
- package/dist/index.d.ts +106 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +78 -0
- package/dist/index.js.map +1 -0
- package/dist/lock.d.ts +66 -0
- package/dist/lock.d.ts.map +1 -0
- package/dist/lock.js +282 -0
- package/dist/lock.js.map +1 -0
- package/dist/poll-loop.d.ts +71 -0
- package/dist/poll-loop.d.ts.map +1 -0
- package/dist/poll-loop.js +130 -0
- package/dist/poll-loop.js.map +1 -0
- package/dist/portkey/config.d.ts +46 -0
- package/dist/portkey/config.d.ts.map +1 -0
- package/dist/portkey/config.js +68 -0
- package/dist/portkey/config.js.map +1 -0
- package/dist/portkey/describe-model.d.ts +53 -0
- package/dist/portkey/describe-model.d.ts.map +1 -0
- package/dist/portkey/describe-model.js +56 -0
- package/dist/portkey/describe-model.js.map +1 -0
- package/dist/portkey/headers.d.ts +31 -0
- package/dist/portkey/headers.d.ts.map +1 -0
- package/dist/portkey/headers.js +37 -0
- package/dist/portkey/headers.js.map +1 -0
- package/dist/portkey/transport.d.ts +89 -0
- package/dist/portkey/transport.d.ts.map +1 -0
- package/dist/portkey/transport.js +167 -0
- package/dist/portkey/transport.js.map +1 -0
- package/dist/projection/format.d.ts +51 -0
- package/dist/projection/format.d.ts.map +1 -0
- package/dist/projection/format.js +81 -0
- package/dist/projection/format.js.map +1 -0
- package/dist/projection/generate.d.ts +31 -0
- package/dist/projection/generate.d.ts.map +1 -0
- package/dist/projection/generate.js +83 -0
- package/dist/projection/generate.js.map +1 -0
- package/dist/projection/inherit.d.ts +27 -0
- package/dist/projection/inherit.d.ts.map +1 -0
- package/dist/projection/inherit.js +128 -0
- package/dist/projection/inherit.js.map +1 -0
- package/dist/projection/load.d.ts +47 -0
- package/dist/projection/load.d.ts.map +1 -0
- package/dist/projection/load.js +258 -0
- package/dist/projection/load.js.map +1 -0
- package/dist/projection/store-adapter.d.ts +42 -0
- package/dist/projection/store-adapter.d.ts.map +1 -0
- package/dist/projection/store-adapter.js +42 -0
- package/dist/projection/store-adapter.js.map +1 -0
- package/dist/projection/write.d.ts +79 -0
- package/dist/projection/write.d.ts.map +1 -0
- package/dist/projection/write.js +122 -0
- package/dist/projection/write.js.map +1 -0
- package/dist/registration/classify.d.ts +33 -0
- package/dist/registration/classify.d.ts.map +1 -0
- package/dist/registration/classify.js +32 -0
- package/dist/registration/classify.js.map +1 -0
- package/dist/registration/copy-detect.d.ts +22 -0
- package/dist/registration/copy-detect.d.ts.map +1 -0
- package/dist/registration/copy-detect.js +12 -0
- package/dist/registration/copy-detect.js.map +1 -0
- package/dist/registration/disk-fs.d.ts +41 -0
- package/dist/registration/disk-fs.d.ts.map +1 -0
- package/dist/registration/disk-fs.js +175 -0
- package/dist/registration/disk-fs.js.map +1 -0
- package/dist/registration/fs-watch.d.ts +114 -0
- package/dist/registration/fs-watch.d.ts.map +1 -0
- package/dist/registration/fs-watch.js +266 -0
- package/dist/registration/fs-watch.js.map +1 -0
- package/dist/registration/ignore.d.ts +77 -0
- package/dist/registration/ignore.d.ts.map +1 -0
- package/dist/registration/ignore.js +249 -0
- package/dist/registration/ignore.js.map +1 -0
- package/dist/registration/ladder.d.ts +211 -0
- package/dist/registration/ladder.d.ts.map +1 -0
- package/dist/registration/ladder.js +378 -0
- package/dist/registration/ladder.js.map +1 -0
- package/dist/registration/paths-safe.d.ts +21 -0
- package/dist/registration/paths-safe.d.ts.map +1 -0
- package/dist/registration/paths-safe.js +88 -0
- package/dist/registration/paths-safe.js.map +1 -0
- package/dist/registration/prune-cli.d.ts +48 -0
- package/dist/registration/prune-cli.d.ts.map +1 -0
- package/dist/registration/prune-cli.js +57 -0
- package/dist/registration/prune-cli.js.map +1 -0
- package/dist/registration/review-cli.d.ts +42 -0
- package/dist/registration/review-cli.d.ts.map +1 -0
- package/dist/registration/review-cli.js +110 -0
- package/dist/registration/review-cli.js.map +1 -0
- package/dist/registration/review-store.d.ts +73 -0
- package/dist/registration/review-store.d.ts.map +1 -0
- package/dist/registration/review-store.js +243 -0
- package/dist/registration/review-store.js.map +1 -0
- package/dist/registration/service.d.ts +196 -0
- package/dist/registration/service.d.ts.map +1 -0
- package/dist/registration/service.js +384 -0
- package/dist/registration/service.js.map +1 -0
- package/dist/registration/store-bridge.d.ts +133 -0
- package/dist/registration/store-bridge.d.ts.map +1 -0
- package/dist/registration/store-bridge.js +159 -0
- package/dist/registration/store-bridge.js.map +1 -0
- package/dist/registration/tlsh.d.ts +125 -0
- package/dist/registration/tlsh.d.ts.map +1 -0
- package/dist/registration/tlsh.js +274 -0
- package/dist/registration/tlsh.js.map +1 -0
- package/dist/server.d.ts +26 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +156 -0
- package/dist/server.js.map +1 -0
- package/dist/service/argv.d.ts +52 -0
- package/dist/service/argv.d.ts.map +1 -0
- package/dist/service/argv.js +127 -0
- package/dist/service/argv.js.map +1 -0
- package/dist/service/command-runner.d.ts +54 -0
- package/dist/service/command-runner.d.ts.map +1 -0
- package/dist/service/command-runner.js +55 -0
- package/dist/service/command-runner.js.map +1 -0
- package/dist/service/index.d.ts +83 -0
- package/dist/service/index.d.ts.map +1 -0
- package/dist/service/index.js +270 -0
- package/dist/service/index.js.map +1 -0
- package/dist/service/platform.d.ts +110 -0
- package/dist/service/platform.d.ts.map +1 -0
- package/dist/service/platform.js +157 -0
- package/dist/service/platform.js.map +1 -0
- package/dist/service/templates.d.ts +88 -0
- package/dist/service/templates.d.ts.map +1 -0
- package/dist/service/templates.js +212 -0
- package/dist/service/templates.js.map +1 -0
- package/dist/source-graph/deeplake-credentials.d.ts +57 -0
- package/dist/source-graph/deeplake-credentials.d.ts.map +1 -0
- package/dist/source-graph/deeplake-credentials.js +109 -0
- package/dist/source-graph/deeplake-credentials.js.map +1 -0
- package/dist/source-graph/deeplake-heal.d.ts +53 -0
- package/dist/source-graph/deeplake-heal.d.ts.map +1 -0
- package/dist/source-graph/deeplake-heal.js +41 -0
- package/dist/source-graph/deeplake-heal.js.map +1 -0
- package/dist/source-graph/deeplake-store.d.ts +151 -0
- package/dist/source-graph/deeplake-store.d.ts.map +1 -0
- package/dist/source-graph/deeplake-store.js +389 -0
- package/dist/source-graph/deeplake-store.js.map +1 -0
- package/dist/source-graph/deeplake-transport.d.ts +74 -0
- package/dist/source-graph/deeplake-transport.d.ts.map +1 -0
- package/dist/source-graph/deeplake-transport.js +107 -0
- package/dist/source-graph/deeplake-transport.js.map +1 -0
- package/dist/source-graph/hash.d.ts +3 -0
- package/dist/source-graph/hash.d.ts.map +1 -0
- package/dist/source-graph/hash.js +12 -0
- package/dist/source-graph/hash.js.map +1 -0
- package/dist/source-graph/memory-store.d.ts +32 -0
- package/dist/source-graph/memory-store.d.ts.map +1 -0
- package/dist/source-graph/memory-store.js +81 -0
- package/dist/source-graph/memory-store.js.map +1 -0
- package/dist/source-graph/model.d.ts +102 -0
- package/dist/source-graph/model.d.ts.map +1 -0
- package/dist/source-graph/model.js +36 -0
- package/dist/source-graph/model.js.map +1 -0
- package/dist/source-graph/paths.d.ts +7 -0
- package/dist/source-graph/paths.d.ts.map +1 -0
- package/dist/source-graph/paths.js +26 -0
- package/dist/source-graph/paths.js.map +1 -0
- package/dist/source-graph/schema.d.ts +44 -0
- package/dist/source-graph/schema.d.ts.map +1 -0
- package/dist/source-graph/schema.js +123 -0
- package/dist/source-graph/schema.js.map +1 -0
- package/dist/source-graph/sql-guards.d.ts +99 -0
- package/dist/source-graph/sql-guards.d.ts.map +1 -0
- package/dist/source-graph/sql-guards.js +129 -0
- package/dist/source-graph/sql-guards.js.map +1 -0
- package/dist/source-graph/store.d.ts +101 -0
- package/dist/source-graph/store.d.ts.map +1 -0
- package/dist/source-graph/store.js +2 -0
- package/dist/source-graph/store.js.map +1 -0
- package/dist/source-graph/ulid.d.ts +9 -0
- package/dist/source-graph/ulid.d.ts.map +1 -0
- package/dist/source-graph/ulid.js +61 -0
- package/dist/source-graph/ulid.js.map +1 -0
- package/dist/telemetry/checkin.d.ts +66 -0
- package/dist/telemetry/checkin.d.ts.map +1 -0
- package/dist/telemetry/checkin.js +142 -0
- package/dist/telemetry/checkin.js.map +1 -0
- package/dist/telemetry/db.d.ts +34 -0
- package/dist/telemetry/db.d.ts.map +1 -0
- package/dist/telemetry/db.js +122 -0
- package/dist/telemetry/db.js.map +1 -0
- package/dist/telemetry/index.d.ts +76 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +98 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/logs.d.ts +83 -0
- package/dist/telemetry/logs.d.ts.map +1 -0
- package/dist/telemetry/logs.js +110 -0
- package/dist/telemetry/logs.js.map +1 -0
- package/dist/telemetry/metrics.d.ts +82 -0
- package/dist/telemetry/metrics.d.ts.map +1 -0
- package/dist/telemetry/metrics.js +148 -0
- package/dist/telemetry/metrics.js.map +1 -0
- package/dist/telemetry-usage/emit.d.ts +105 -0
- package/dist/telemetry-usage/emit.d.ts.map +1 -0
- package/dist/telemetry-usage/emit.js +267 -0
- package/dist/telemetry-usage/emit.js.map +1 -0
- package/dist/telemetry-usage/posthog-key.d.ts +22 -0
- package/dist/telemetry-usage/posthog-key.d.ts.map +1 -0
- package/dist/telemetry-usage/posthog-key.js +22 -0
- package/dist/telemetry-usage/posthog-key.js.map +1 -0
- package/dist/worker.d.ts +69 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +91 -0
- package/dist/worker.js.map +1 -0
- package/package.json +44 -0
package/dist/daemon.js
ADDED
|
@@ -0,0 +1,664 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The nectar daemon composition root.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors honeycomb's `assembleDaemon` + `runAssembledDaemon`
|
|
5
|
+
* (honeycomb/src/daemon/runtime/assemble.ts, honeycomb/src/daemon/index.ts:150-187)
|
|
6
|
+
* per PRD-002a, scoped to nectar's job surface. The load-bearing ordering is
|
|
7
|
+
* lock BEFORE bind (PRD-002a step 5 before step 7): a double-start fails fast at
|
|
8
|
+
* the lock before the port is bound, and a bind failure rolls the lifecycle back
|
|
9
|
+
* so no stale lock survives.
|
|
10
|
+
*
|
|
11
|
+
* `assembleDaemon()` constructs but never listens (importing the module is
|
|
12
|
+
* side-effect free). `start()` acquires the lock, starts the worker, and binds
|
|
13
|
+
* the socket. `shutdown()` drains the worker, closes the socket, and releases
|
|
14
|
+
* the lock, idempotently.
|
|
15
|
+
*
|
|
16
|
+
* PRD-017a wires nectar's telemetry check-in/heartbeat here: `start()`
|
|
17
|
+
* checks in (a fresh binding_time) right after `health.markStarted()` and arms
|
|
18
|
+
* a heartbeat interval; `shutdown()` disarms it and closes the SQLite handle.
|
|
19
|
+
* A fresh `Telemetry` is opened on every `start()` (not once at
|
|
20
|
+
* `assembleDaemon()` construction time), so a stop/start cycle on the SAME
|
|
21
|
+
* `AssembledDaemon` - not just a brand-new process - also gets a fresh
|
|
22
|
+
* binding_time and zeroed since-restart counters (AC-017a.3.2 / AC-017b.3.1).
|
|
23
|
+
* Opening/writing telemetry is fail-soft throughout (`telemetry/index.ts`):
|
|
24
|
+
* a SQLite failure never blocks the lock, the bind, or the pipeline (AC-7).
|
|
25
|
+
*/
|
|
26
|
+
import { join } from "node:path";
|
|
27
|
+
import { resolveConfig, isLoopbackHost, } from "./config.js";
|
|
28
|
+
import { HealthState } from "./health.js";
|
|
29
|
+
import { resolvePortkeyConfig } from "./portkey/config.js";
|
|
30
|
+
import { resolveEmbeddingsConfig, } from "./embeddings/config.js";
|
|
31
|
+
import { acquireSingleInstanceLock, releaseSingleInstanceLock } from "./lock.js";
|
|
32
|
+
import { DaemonStartAbortedError, NonLoopbackOpenApiError } from "./errors.js";
|
|
33
|
+
import { createHttpServer, DEFAULT_CLOSE_GRACE_MS } from "./server.js";
|
|
34
|
+
import { NectarRouter, ROUTE_GROUPS, allowAllPermission, } from "./api/router.js";
|
|
35
|
+
import { mountHiveGraphApi } from "./api/hive-graph-api.js";
|
|
36
|
+
import { createBroodGuard } from "./brood-guard.js";
|
|
37
|
+
import { createLogTap, createNullTelemetry, createTelemetry, telemetryDbPathForRuntimeDir, } from "./telemetry/index.js";
|
|
38
|
+
import { HiveantennaeWorker, emptyJobSource, } from "./worker.js";
|
|
39
|
+
import { createDiskRegistrationFs } from "./registration/disk-fs.js";
|
|
40
|
+
import { RegistrationService } from "./registration/service.js";
|
|
41
|
+
import { StoreBridge } from "./registration/store-bridge.js";
|
|
42
|
+
import { createSharedIgnore } from "./registration/ignore.js";
|
|
43
|
+
import { createTlshFuzzyStep, DEFAULT_TUNABLE_FUZZY_CONFIG } from "./registration/tlsh.js";
|
|
44
|
+
import { FilePendingReviewStore } from "./registration/review-store.js";
|
|
45
|
+
import { createOffProvider } from "./embeddings/provider.js";
|
|
46
|
+
import { createEnricherLoop, EnricherInMemoryStore, } from "./enricher/index.js";
|
|
47
|
+
import { evaluateAutoBrood, evaluateAutoBroodAsync, runBrood, runBroodAsync, shouldAutoBrood, } from "./brooding/index.js";
|
|
48
|
+
import { loadProjection, loadProjectionFromFile } from "./projection/load.js";
|
|
49
|
+
import { inheritFromProjection } from "./projection/inherit.js";
|
|
50
|
+
/**
|
|
51
|
+
* Bounded drain timeout for `shutdown()` (PRD-018a NEC-033 / AC-018a.11): how
|
|
52
|
+
* long to wait for the in-flight worker tick and background boot tasks to settle
|
|
53
|
+
* before releasing the lock and proceeding. A drain that exceeds this logs and
|
|
54
|
+
* proceeds, so shutdown stays bounded (it must not reintroduce the NEC-021 hang).
|
|
55
|
+
*/
|
|
56
|
+
export const DEFAULT_SHUTDOWN_DRAIN_MS = 5_000;
|
|
57
|
+
/**
|
|
58
|
+
* Await `work` but give up after `ms`. Resolves `true` when the work settled
|
|
59
|
+
* first, `false` on timeout. The timer is unref'd so it never keeps the process
|
|
60
|
+
* alive, and cleared on settle so it never leaks.
|
|
61
|
+
*/
|
|
62
|
+
async function raceWithTimeout(work, ms) {
|
|
63
|
+
let timer;
|
|
64
|
+
const timeout = new Promise((resolve) => {
|
|
65
|
+
timer = setTimeout(() => resolve(false), ms);
|
|
66
|
+
timer.unref?.();
|
|
67
|
+
});
|
|
68
|
+
try {
|
|
69
|
+
return await Promise.race([work.then(() => true), timeout]);
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
if (timer !== undefined)
|
|
73
|
+
clearTimeout(timer);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Load + validate a projection on boot and, when disk hashes are supplied, run
|
|
78
|
+
* the fresh-clone inheritance (PRD-011b AC-6). Never throws: a validation
|
|
79
|
+
* failure returns `{ loaded: false, reason }`, and a `write` rejection is
|
|
80
|
+
* swallowed (recall is simply not pre-warmed). Uses `projection/load.ts` +
|
|
81
|
+
* `projection/inherit.ts` verbatim.
|
|
82
|
+
*/
|
|
83
|
+
export async function runBootProjectionLoad(opts) {
|
|
84
|
+
let loaded;
|
|
85
|
+
try {
|
|
86
|
+
if (opts.doc !== undefined) {
|
|
87
|
+
loaded = loadProjection(opts.doc, opts.tenancy);
|
|
88
|
+
}
|
|
89
|
+
else if (opts.filePath !== undefined) {
|
|
90
|
+
loaded = loadProjectionFromFile(opts.filePath, { tenancy: opts.tenancy });
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
return { loaded: false };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return { loaded: false };
|
|
98
|
+
}
|
|
99
|
+
if (!loaded.ok) {
|
|
100
|
+
const result = { loaded: false, reason: loaded.reason };
|
|
101
|
+
opts.onResult?.(result);
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
let inheritSummary;
|
|
105
|
+
if (opts.diskHashes !== undefined) {
|
|
106
|
+
const diskHashes = typeof opts.diskHashes === "function" ? await opts.diskHashes() : opts.diskHashes;
|
|
107
|
+
const existingNectars = typeof opts.existingNectars === "function" ? await opts.existingNectars() : opts.existingNectars;
|
|
108
|
+
inheritSummary = inheritFromProjection(loaded.doc, diskHashes, {
|
|
109
|
+
tenancy: opts.tenancy,
|
|
110
|
+
...(opts.nowIso !== undefined ? { nowIso: opts.nowIso } : {}),
|
|
111
|
+
...(existingNectars !== undefined ? { existingNectars } : {}),
|
|
112
|
+
});
|
|
113
|
+
if (opts.write !== undefined && inheritSummary.rows.length > 0) {
|
|
114
|
+
try {
|
|
115
|
+
await opts.write(inheritSummary.rows);
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
// fail-soft: recall is not pre-warmed, but the daemon still boots.
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const result = inheritSummary !== undefined ? { loaded: true, inheritSummary } : { loaded: true };
|
|
123
|
+
opts.onResult?.(result);
|
|
124
|
+
return result;
|
|
125
|
+
}
|
|
126
|
+
/** Map the embeddings selector (`off | local | hosted`) to the health body's provider label. */
|
|
127
|
+
function embeddingsHealthProvider(selector) {
|
|
128
|
+
switch (selector) {
|
|
129
|
+
case "off":
|
|
130
|
+
return "off";
|
|
131
|
+
case "local":
|
|
132
|
+
return "local-nomic";
|
|
133
|
+
case "hosted":
|
|
134
|
+
return "hosted";
|
|
135
|
+
default: {
|
|
136
|
+
// Exhaustiveness: a new selector variant fails the build here until mapped.
|
|
137
|
+
const unreachable = selector;
|
|
138
|
+
return unreachable;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function defaultLog(line) {
|
|
143
|
+
process.stderr.write(`${JSON.stringify({ ts: new Date().toISOString(), ...line })}\n`);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Construct the daemon. Does NOT bind a socket or acquire the lock (that is
|
|
147
|
+
* `start()`), so importing/constructing is safe in tests.
|
|
148
|
+
*/
|
|
149
|
+
export function assembleDaemon(options = {}) {
|
|
150
|
+
const config = resolveConfig(options);
|
|
151
|
+
const baseLog = options.log ?? defaultLog;
|
|
152
|
+
const health = new HealthState();
|
|
153
|
+
// Resolve the provider state ONCE here, not per /health request (decision #20).
|
|
154
|
+
// Both resolvers read only `process.env` (or an injected override bag) and never
|
|
155
|
+
// touch disk or the network, so this keeps construction side-effect free.
|
|
156
|
+
const portkeyConfig = resolvePortkeyConfig(options.portkey ?? {});
|
|
157
|
+
const embeddingsConfig = resolveEmbeddingsConfig(options.embeddings ?? {});
|
|
158
|
+
health.setProviderState({
|
|
159
|
+
portkeyEnabled: portkeyConfig.enabled,
|
|
160
|
+
embeddingsProvider: embeddingsHealthProvider(embeddingsConfig.selector),
|
|
161
|
+
});
|
|
162
|
+
// PRD-018k / NEC-023: surface the brooding-dormancy reason on /health as soon
|
|
163
|
+
// as the daemon is constructed, so a dormant daemon is observable before the
|
|
164
|
+
// auto-brood trigger even runs. Ready (or unspecified) leaves reason null.
|
|
165
|
+
const broodPrereqs = options.broodPrereqs;
|
|
166
|
+
if (broodPrereqs !== undefined) {
|
|
167
|
+
health.setBroodingState({ reason: broodPrereqs.ready ? null : broodPrereqs.reason });
|
|
168
|
+
}
|
|
169
|
+
const telemetryDbPath = options.telemetryDbPath ?? telemetryDbPathForRuntimeDir(config.runtimeDir);
|
|
170
|
+
// A no-op placeholder until the first start() actually opens the SQLite store
|
|
171
|
+
// (constructing/importing the daemon must stay side-effect free, unchanged).
|
|
172
|
+
let telemetry = createNullTelemetry(telemetryDbPath);
|
|
173
|
+
// Indirection so `log` (built once, below) always taps whatever `telemetry`
|
|
174
|
+
// CURRENTLY is, across every start()/shutdown() cycle that reassigns it.
|
|
175
|
+
const telemetrySink = { log: (level, message) => telemetry.log(level, message) };
|
|
176
|
+
const log = createLogTap(baseLog, telemetrySink);
|
|
177
|
+
const worker = new HiveantennaeWorker({
|
|
178
|
+
source: options.jobSource ?? emptyJobSource,
|
|
179
|
+
handlers: options.handlers ?? {},
|
|
180
|
+
pollIntervalMs: config.pollIntervalMs,
|
|
181
|
+
onError: (err) => log({ level: "error", scope: "worker", err: String(err) }),
|
|
182
|
+
});
|
|
183
|
+
// ── PRD-008a: the in-repo router seam over node:http ────────────────────────
|
|
184
|
+
// Constructed side-effect free (no socket): it holds the frozen ROUTE_GROUPS,
|
|
185
|
+
// the shared live route table, and the permission gate. `createHttpServer`
|
|
186
|
+
// consumes it at start(); `daemon.group("/api/hive-graph")` exposes the
|
|
187
|
+
// RouteGroup handle so `mountHiveGraphApi` can attach handlers before OR after
|
|
188
|
+
// the socket binds (the route table is consulted per request).
|
|
189
|
+
const router = new NectarRouter(ROUTE_GROUPS, options.apiPermission ?? allowAllPermission);
|
|
190
|
+
const apiPermission = options.apiPermission ?? allowAllPermission;
|
|
191
|
+
// Shared Wave C context: an empty placeholder tenancy means an empty store
|
|
192
|
+
// yields no work, so the default enricher loop is a harmless no-op until a
|
|
193
|
+
// real tenancy + store are wired in.
|
|
194
|
+
const waveCTenancy = options.tenancy ?? { orgId: "", workspaceId: "", projectId: "" };
|
|
195
|
+
const projectRoot = options.projectRoot ?? process.cwd();
|
|
196
|
+
// PRD-018c NEC-007 (AC-018c.1): the ONE shared ignore predicate (segments ∪
|
|
197
|
+
// graph-ignore ∪ gitignore semantics) - the SAME function reference is used
|
|
198
|
+
// by brood discovery (both its git and walk paths), the watch intake, and
|
|
199
|
+
// the resync path, so the three legs of the mission never disagree about
|
|
200
|
+
// what the codebase is again. Memoized and constructed LAZILY on first
|
|
201
|
+
// actual use (registration or brood activating), not at assembly time: a
|
|
202
|
+
// daemon that never wires a store (most unit tests) never spawns `git`.
|
|
203
|
+
let sharedIgnoreInstance;
|
|
204
|
+
function sharedIgnore() {
|
|
205
|
+
if (sharedIgnoreInstance === undefined)
|
|
206
|
+
sharedIgnoreInstance = createSharedIgnore(projectRoot);
|
|
207
|
+
return sharedIgnoreInstance;
|
|
208
|
+
}
|
|
209
|
+
const resolvedIgnore = options.registrationIgnore ?? ((relPath) => sharedIgnore().isIgnored(relPath));
|
|
210
|
+
// PRD-018g / NEC-011: the ONE shared brood guard. The boot auto-brood and the
|
|
211
|
+
// API `/build` handler both go through it, and the enricher pauses while it is
|
|
212
|
+
// active, so at most one brood runs per daemon and the enricher never races it.
|
|
213
|
+
const broodGuard = createBroodGuard();
|
|
214
|
+
// ── PRD-016: the enricher steady-state loop ─────────────────────────────────
|
|
215
|
+
// The loop reads/writes the SYNCHRONOUS EnricherStore seam; its per-cycle stats
|
|
216
|
+
// feed the /health enricher slice through `enricherHealthSink`. Started on
|
|
217
|
+
// start(), stopped on shutdown(). The durable Deep Lake bridge is injected via
|
|
218
|
+
// `enricherStore` (see enricher/store-adapter.ts); the default is an empty
|
|
219
|
+
// in-memory working set.
|
|
220
|
+
let enricherLoop = null;
|
|
221
|
+
if (options.enricherEnabled ?? true) {
|
|
222
|
+
const enricherStore = options.enricherStore ?? new EnricherInMemoryStore();
|
|
223
|
+
const nowIso = options.enricherCycle?.nowIso ?? (() => new Date().toISOString());
|
|
224
|
+
const enricherHealthSink = {
|
|
225
|
+
logCycle: (stats) => {
|
|
226
|
+
try {
|
|
227
|
+
health.setEnricherState({
|
|
228
|
+
queueDepth: stats.queueDepth,
|
|
229
|
+
lastCycleAt: nowIso(),
|
|
230
|
+
consecutiveFailures: enricherLoop?.getFailureState().consecutiveFailures ?? 0,
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
// fail-soft: /health is best-effort and never blocks a cycle.
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
};
|
|
238
|
+
// Default the enricher's metrics sink to the daemon's OWN telemetry (read
|
|
239
|
+
// lazily so it tracks the fresh instance opened on each start()), so a live
|
|
240
|
+
// enricher cycle that describes/embeds moves the PRD-017 counters. A caller
|
|
241
|
+
// may still override it via `enricherCycle.metrics`.
|
|
242
|
+
const enricherMetrics = options.enricherCycle?.metrics ?? {
|
|
243
|
+
incrementFilesRegistered: () => telemetry.metrics.incrementFilesRegistered(),
|
|
244
|
+
incrementNectarsMinted: () => telemetry.metrics.incrementNectarsMinted(),
|
|
245
|
+
incrementDescriptionsGenerated: () => telemetry.metrics.incrementDescriptionsGenerated(),
|
|
246
|
+
incrementHiveGraphVersions: () => telemetry.metrics.incrementHiveGraphVersions(),
|
|
247
|
+
incrementEmbeddingsComputed: () => telemetry.metrics.incrementEmbeddingsComputed(),
|
|
248
|
+
};
|
|
249
|
+
const cycleDeps = {
|
|
250
|
+
readContent: { read: () => null },
|
|
251
|
+
portkey: null,
|
|
252
|
+
embedProvider: createOffProvider(),
|
|
253
|
+
...options.enricherCycle,
|
|
254
|
+
store: enricherStore,
|
|
255
|
+
tenancy: waveCTenancy,
|
|
256
|
+
logSink: enricherHealthSink,
|
|
257
|
+
metrics: enricherMetrics,
|
|
258
|
+
// AC-018g.1: pause the enricher while a brood is in flight (shared guard).
|
|
259
|
+
broodActive: () => broodGuard.active(),
|
|
260
|
+
};
|
|
261
|
+
enricherLoop = createEnricherLoop({
|
|
262
|
+
deps: cycleDeps,
|
|
263
|
+
...(options.enricherPollIntervalMs !== undefined ? { pollIntervalMs: options.enricherPollIntervalMs } : {}),
|
|
264
|
+
...(options.enricherTimer !== undefined ? { timer: options.enricherTimer } : {}),
|
|
265
|
+
onError: (err) => log({ level: "error", scope: "enricher", err: String(err) }),
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
/** Background boot tasks (projection load, auto-brood) from the latest start(); never blocks readiness. */
|
|
269
|
+
let bootSettled = Promise.resolve();
|
|
270
|
+
/** Record a completed brood's file/cost slices on /health (shared by both paths). */
|
|
271
|
+
function finishBrood(result) {
|
|
272
|
+
health.setBroodingState({
|
|
273
|
+
active: false,
|
|
274
|
+
filesDescribed: result.describedCount,
|
|
275
|
+
filesTotal: result.discoveredCount,
|
|
276
|
+
lastEventAt: new Date().toISOString(),
|
|
277
|
+
});
|
|
278
|
+
health.addBroodCost({ tokens: result.actualUsage.inputTokens, usd: result.actualUsage.usd });
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* PRD-007d automatic trigger: after the socket is bound, if the project has no
|
|
282
|
+
* hive_graph rows OR no projection, brood in the BACKGROUND (never blocks
|
|
283
|
+
* readiness). Runs against the durable ASYNC store when {@link asyncBroodStore}
|
|
284
|
+
* is wired (the sync/async bridge, counting via the daemon's telemetry), else
|
|
285
|
+
* against a sync {@link broodStore}; a no-op when neither is configured.
|
|
286
|
+
*/
|
|
287
|
+
async function triggerAutoBrood() {
|
|
288
|
+
if ((options.autoBroodEnabled ?? true) === false)
|
|
289
|
+
return;
|
|
290
|
+
const asyncStore = options.asyncBroodStore;
|
|
291
|
+
const syncStore = options.broodStore;
|
|
292
|
+
if (asyncStore === undefined && syncStore === undefined)
|
|
293
|
+
return;
|
|
294
|
+
// AC-018g.2: route the boot auto-brood through the SAME shared guard the API
|
|
295
|
+
// `/build` handler uses, so a `/build` arriving during the boot brood is
|
|
296
|
+
// refused (409) and no two broods ever run - and no identity is double-minted.
|
|
297
|
+
if (!broodGuard.tryAcquire())
|
|
298
|
+
return;
|
|
299
|
+
try {
|
|
300
|
+
if (asyncStore !== undefined) {
|
|
301
|
+
if (!shouldAutoBrood(await evaluateAutoBroodAsync(asyncStore, waveCTenancy, projectRoot)))
|
|
302
|
+
return;
|
|
303
|
+
health.setBroodingState({ active: true, lastEventAt: new Date().toISOString() });
|
|
304
|
+
const config = {
|
|
305
|
+
isIgnored: resolvedIgnore,
|
|
306
|
+
...options.broodConfigAsync,
|
|
307
|
+
store: telemetry.wrapAsyncStore(asyncStore),
|
|
308
|
+
tenancy: waveCTenancy,
|
|
309
|
+
root: projectRoot,
|
|
310
|
+
fs: options.broodConfigAsync?.fs ?? createDiskRegistrationFs(projectRoot, resolvedIgnore),
|
|
311
|
+
};
|
|
312
|
+
const run = options.broodRunAsync ?? runBroodAsync;
|
|
313
|
+
finishBrood(await run(config, options.broodDepsAsync ?? {}, options.broodOptions ?? {}));
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
if (syncStore !== undefined) {
|
|
317
|
+
if (!shouldAutoBrood(evaluateAutoBrood(syncStore, waveCTenancy, projectRoot)))
|
|
318
|
+
return;
|
|
319
|
+
health.setBroodingState({ active: true, lastEventAt: new Date().toISOString() });
|
|
320
|
+
const config = {
|
|
321
|
+
isIgnored: resolvedIgnore,
|
|
322
|
+
...options.broodConfig,
|
|
323
|
+
store: syncStore,
|
|
324
|
+
tenancy: waveCTenancy,
|
|
325
|
+
root: projectRoot,
|
|
326
|
+
fs: options.broodConfig?.fs ?? createDiskRegistrationFs(projectRoot, resolvedIgnore),
|
|
327
|
+
};
|
|
328
|
+
const run = options.broodRun ?? runBrood;
|
|
329
|
+
finishBrood(await run(config, options.broodDeps ?? {}, options.broodOptions ?? {}));
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
catch (err) {
|
|
334
|
+
health.setBroodingState({ active: false });
|
|
335
|
+
log({ level: "error", scope: "brood", err: String(err) });
|
|
336
|
+
}
|
|
337
|
+
finally {
|
|
338
|
+
broodGuard.release();
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
/** PRD-011b AC-6: load + validate the projection and inherit hash-matched files, in the background. */
|
|
342
|
+
async function loadBootProjection() {
|
|
343
|
+
const boot = options.bootProjection;
|
|
344
|
+
if (boot === undefined)
|
|
345
|
+
return;
|
|
346
|
+
try {
|
|
347
|
+
const result = await runBootProjectionLoad(boot);
|
|
348
|
+
if (result.loaded && result.inheritSummary !== undefined && result.inheritSummary.inherited > 0) {
|
|
349
|
+
health.setProjectionState({ lastWriteAt: new Date().toISOString() });
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
catch (err) {
|
|
353
|
+
log({ level: "error", scope: "projection", err: String(err) });
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
// ── PRD-018b: the update-on-change registration pipeline ────────────────────
|
|
357
|
+
// Constructed at start() (after the bind) when a durable async store resolved,
|
|
358
|
+
// then hydrated + started + resynced in the background AFTER auto-brood settles
|
|
359
|
+
// (so a first boot's brood never races the watcher into a double mint, and an
|
|
360
|
+
// already-brooded boot still gets its cold catch-up). Stopped in shutdown()
|
|
361
|
+
// before the lock is released, with its durable writes drained.
|
|
362
|
+
const registrationStore = options.registrationStore;
|
|
363
|
+
const registrationOn = registrationStore !== undefined && (options.registrationEnabled ?? true);
|
|
364
|
+
let registration = null;
|
|
365
|
+
let bootResyncCount = 0;
|
|
366
|
+
/**
|
|
367
|
+
* Build the registration pipeline: a {@link StoreBridge} over the durable async
|
|
368
|
+
* store and a {@link RegistrationService} wired with the disk fs, ignore
|
|
369
|
+
* predicate, the tunable TLSH fuzzy step, and the file-backed review queue.
|
|
370
|
+
* Constructing the service does NOT start the watcher (that is `service.start()`).
|
|
371
|
+
*/
|
|
372
|
+
function buildRegistration(store) {
|
|
373
|
+
const bridge = new StoreBridge({
|
|
374
|
+
durable: store,
|
|
375
|
+
onFlushError: (err, op) => {
|
|
376
|
+
health.recordWatchFlushFailure(new Date().toISOString());
|
|
377
|
+
log({ level: "error", scope: "registration.bridge", op, err: String(err) });
|
|
378
|
+
},
|
|
379
|
+
});
|
|
380
|
+
const reviews = options.registrationReviews ?? new FilePendingReviewStore(join(config.runtimeDir, "pending-reviews.json"));
|
|
381
|
+
const registrationMetrics = {
|
|
382
|
+
incrementFilesRegistered: () => telemetry.metrics.incrementFilesRegistered(),
|
|
383
|
+
incrementNectarsMinted: () => telemetry.metrics.incrementNectarsMinted(),
|
|
384
|
+
incrementDescriptionsGenerated: () => telemetry.metrics.incrementDescriptionsGenerated(),
|
|
385
|
+
incrementHiveGraphVersions: () => telemetry.metrics.incrementHiveGraphVersions(),
|
|
386
|
+
incrementEmbeddingsComputed: () => telemetry.metrics.incrementEmbeddingsComputed(),
|
|
387
|
+
};
|
|
388
|
+
const service = new RegistrationService({
|
|
389
|
+
store: bridge,
|
|
390
|
+
tenancy: waveCTenancy,
|
|
391
|
+
fs: options.registrationFs ?? createDiskRegistrationFs(projectRoot, resolvedIgnore),
|
|
392
|
+
root: projectRoot,
|
|
393
|
+
fuzzy: createTlshFuzzyStep(options.registrationFuzzyConfig ?? DEFAULT_TUNABLE_FUZZY_CONFIG),
|
|
394
|
+
pendingReviews: reviews,
|
|
395
|
+
isIgnored: resolvedIgnore,
|
|
396
|
+
...(options.registrationTimer !== undefined ? { timer: options.registrationTimer } : {}),
|
|
397
|
+
...(options.registrationDebounceMs !== undefined ? { debounceMs: options.registrationDebounceMs } : {}),
|
|
398
|
+
metrics: registrationMetrics,
|
|
399
|
+
log,
|
|
400
|
+
// PRD-018c NEC-007 point 1: refresh the shared predicate's gitignore
|
|
401
|
+
// snapshot on every resync (boot, directory-event, watcher-restart, and
|
|
402
|
+
// the periodic backstop all funnel through requestResync()), so the
|
|
403
|
+
// cache stays warm without spawning git per watch event. A no-op when
|
|
404
|
+
// `registrationIgnore` overrides the shared predicate (nothing to refresh).
|
|
405
|
+
onResyncRequested: () => sharedIgnoreInstance?.refresh(),
|
|
406
|
+
// PRD-018c AC-018c.6/7: surface watcher liveness on /health.
|
|
407
|
+
onWatcherStateChange: (state) => {
|
|
408
|
+
health.setWatchState({ state, running: state === "running" });
|
|
409
|
+
},
|
|
410
|
+
});
|
|
411
|
+
return { service, bridge };
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Hydrate the mirror, start the watcher, and request the single cold-catch-up
|
|
415
|
+
* resync (AC-018b.5) - the boot sequencing step that runs AFTER auto-brood
|
|
416
|
+
* settles. A shutdown that raced boot sets `closed`; in that case this bails
|
|
417
|
+
* out so the watcher is never started during teardown (AC-018b.3).
|
|
418
|
+
*/
|
|
419
|
+
async function startRegistrationPipeline() {
|
|
420
|
+
if (registration === null || closed)
|
|
421
|
+
return;
|
|
422
|
+
try {
|
|
423
|
+
await registration.bridge.hydrate(waveCTenancy);
|
|
424
|
+
}
|
|
425
|
+
catch (err) {
|
|
426
|
+
log({ level: "error", scope: "registration.hydrate", err: String(err) });
|
|
427
|
+
}
|
|
428
|
+
if (closed)
|
|
429
|
+
return; // a shutdown may have landed while hydrating
|
|
430
|
+
registration.service.start();
|
|
431
|
+
health.setWatchState({ running: true, reason: null });
|
|
432
|
+
registration.service.requestResync();
|
|
433
|
+
bootResyncCount += 1;
|
|
434
|
+
log({ level: "info", scope: "registration", msg: "watch leg started", root: projectRoot });
|
|
435
|
+
}
|
|
436
|
+
const lockPaths = { lockFilePath: config.lockFilePath, pidFilePath: config.pidFilePath };
|
|
437
|
+
const drainTimeoutMs = options.shutdownDrainMs ?? DEFAULT_SHUTDOWN_DRAIN_MS;
|
|
438
|
+
const closeGraceMs = options.shutdownCloseGraceMs ?? DEFAULT_CLOSE_GRACE_MS;
|
|
439
|
+
let server = null;
|
|
440
|
+
let closed = false;
|
|
441
|
+
let signalsInstalled = false;
|
|
442
|
+
/** The identity this instance stamped into the lock, or null when it holds no lock (never acquired, or released). */
|
|
443
|
+
let lockIdentity = null;
|
|
444
|
+
/** The one in-flight (or settled) startup. Concurrent/repeat callers share it, so nobody observes a "started" port before listen() actually succeeds. */
|
|
445
|
+
let startPromise = null;
|
|
446
|
+
/** Stops the check-in heartbeat armed by the current telemetry instance, or null before/after it is running. */
|
|
447
|
+
let stopHeartbeat = null;
|
|
448
|
+
async function start() {
|
|
449
|
+
if (startPromise !== null)
|
|
450
|
+
return startPromise;
|
|
451
|
+
startPromise = (async () => {
|
|
452
|
+
// CodeRabbit PR-18 finding #1: clear `closed` at the very top of the
|
|
453
|
+
// startPromise IIFE, before anything that can throw (the loopback guard,
|
|
454
|
+
// the lock acquire). On a REUSED daemon instance (start -> shutdown ->
|
|
455
|
+
// start again), a second start() that throws before this point used to
|
|
456
|
+
// leave `closed === true` from the prior shutdown; the catch handler's
|
|
457
|
+
// rollback `await shutdown()` then no-op'd on the `if (closed) return;`
|
|
458
|
+
// guard and never cleared `startPromise`, wedging every later start() on
|
|
459
|
+
// the same rejected promise forever. This is a synchronous assignment at
|
|
460
|
+
// the top of a prefix that is itself synchronous up to the awaited
|
|
461
|
+
// `listen()` call, so it does not affect the EX-1 race test's timing.
|
|
462
|
+
closed = false;
|
|
463
|
+
// PRD-018j / NEC-029: refuse to bind off loopback when the default open gate
|
|
464
|
+
// is active, so the API is never network-reachable without authentication.
|
|
465
|
+
if (apiPermission === allowAllPermission && !isLoopbackHost(config.host)) {
|
|
466
|
+
throw new NonLoopbackOpenApiError(config.host);
|
|
467
|
+
}
|
|
468
|
+
// Step 5 (PRD-002a): acquire the single-instance lock BEFORE the bind, and
|
|
469
|
+
// remember the identity we stamped so the rollback path releases only what
|
|
470
|
+
// THIS instance acquired (PRD-018a NEC-002).
|
|
471
|
+
lockIdentity = acquireSingleInstanceLock(lockPaths);
|
|
472
|
+
// Step 6: start services (the worker's adaptive poll loop + the enricher loop).
|
|
473
|
+
worker.start();
|
|
474
|
+
enricherLoop?.start();
|
|
475
|
+
health.markStarted();
|
|
476
|
+
// PRD-017a: open a FRESH telemetry store and check in (a new binding_time)
|
|
477
|
+
// on every start(), so a stop/start cycle on this SAME daemon object also
|
|
478
|
+
// resets since-restart state, not only a brand-new process. Fail-soft
|
|
479
|
+
// throughout (`createTelemetry`): a SQLite failure never blocks the bind.
|
|
480
|
+
telemetry = createTelemetry({
|
|
481
|
+
dbPath: telemetryDbPath,
|
|
482
|
+
onceFailure: (msg) => baseLog({ level: "warn", scope: "telemetry", msg }),
|
|
483
|
+
});
|
|
484
|
+
stopHeartbeat = telemetry.startCheckin(() => health.pipelineStatus, {
|
|
485
|
+
intervalMs: options.telemetryHeartbeatIntervalMs,
|
|
486
|
+
timer: options.telemetryTimer,
|
|
487
|
+
});
|
|
488
|
+
// Step 7: bind the socket. Use a local reference so a concurrent shutdown()
|
|
489
|
+
// that nulls `server` cannot turn the unwind below into a null deref.
|
|
490
|
+
const httpServer = createHttpServer(health, config.host, config.port, router);
|
|
491
|
+
server = httpServer;
|
|
492
|
+
const boundPort = await httpServer.listen();
|
|
493
|
+
// EX-1 / M6: a shutdown() may have raced this start between lock acquisition
|
|
494
|
+
// and the bind completing. If so, unwind: close the socket we just bound and
|
|
495
|
+
// release the lock this instance holds, so we never end up listening without
|
|
496
|
+
// a lock (which would let a second daemon start alongside us).
|
|
497
|
+
if (closed) {
|
|
498
|
+
await httpServer.close(closeGraceMs);
|
|
499
|
+
if (server === httpServer)
|
|
500
|
+
server = null;
|
|
501
|
+
if (lockIdentity !== null) {
|
|
502
|
+
releaseSingleInstanceLock(lockPaths, lockIdentity);
|
|
503
|
+
lockIdentity = null;
|
|
504
|
+
}
|
|
505
|
+
throw new DaemonStartAbortedError();
|
|
506
|
+
}
|
|
507
|
+
log({ level: "info", scope: "daemon", msg: "listening", host: config.host, port: boundPort });
|
|
508
|
+
// PRD-018k / NEC-023 (AC-018k.1 / AC-018k.2): a booted daemon that cannot
|
|
509
|
+
// brood says so loudly, enumerating exactly which prerequisites are unmet
|
|
510
|
+
// (the credentials file, and/or the specific NECTAR_PORTKEY_* variables),
|
|
511
|
+
// instead of silently describing nothing.
|
|
512
|
+
if (broodPrereqs !== undefined && !broodPrereqs.ready) {
|
|
513
|
+
log({
|
|
514
|
+
level: "warn",
|
|
515
|
+
scope: "brood",
|
|
516
|
+
msg: "brooding is dormant; the following prerequisites are missing",
|
|
517
|
+
reason: broodPrereqs.reason,
|
|
518
|
+
missing: broodPrereqs.missing,
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
// PRD-018b: construct the registration pipeline now (side-effect light: no
|
|
522
|
+
// watcher yet), and surface the watch-leg state on /health. Dormant with a
|
|
523
|
+
// reason when no durable store resolved (AC-018b.7); constructed-but-not-yet
|
|
524
|
+
// -started otherwise (the watcher starts in the boot task below).
|
|
525
|
+
if (registrationOn && registrationStore !== undefined) {
|
|
526
|
+
registration = buildRegistration(registrationStore);
|
|
527
|
+
health.setWatchState({ running: false, reason: null });
|
|
528
|
+
}
|
|
529
|
+
else {
|
|
530
|
+
health.setWatchState({
|
|
531
|
+
running: false,
|
|
532
|
+
reason: registrationStore === undefined ? "no-credentials" : "disabled",
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
// Step 8 (Wave C / PRD-018b): kick off the background boot tasks AFTER the
|
|
536
|
+
// daemon is accepting requests, so neither the fresh-clone projection load
|
|
537
|
+
// nor the auto-brood trigger ever blocks readiness (PRD-007d / PRD-011b
|
|
538
|
+
// AC-6). The registration watcher + cold-catch-up resync are sequenced
|
|
539
|
+
// AFTER auto-brood settles (AC-018b.5/6): on a first boot the order is
|
|
540
|
+
// brood, then watch, then resync; on a warm boot auto-brood is a no-op and
|
|
541
|
+
// the resync runs promptly. No lock is needed - the watcher simply is not
|
|
542
|
+
// running while the brood runs, so it cannot race a mint.
|
|
543
|
+
bootSettled = (async () => {
|
|
544
|
+
await Promise.allSettled([loadBootProjection(), triggerAutoBrood()]);
|
|
545
|
+
await startRegistrationPipeline();
|
|
546
|
+
})();
|
|
547
|
+
return boundPort;
|
|
548
|
+
})();
|
|
549
|
+
// Only the caller that created the promise drives rollback; concurrent
|
|
550
|
+
// callers returned the shared promise above and observe the same result.
|
|
551
|
+
try {
|
|
552
|
+
return await startPromise;
|
|
553
|
+
}
|
|
554
|
+
catch (err) {
|
|
555
|
+
log({ level: "error", scope: "daemon", msg: "start failed, rolling back", err: String(err) });
|
|
556
|
+
await shutdown(); // clears startPromise so a later start() can retry cleanly
|
|
557
|
+
throw err;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
async function shutdown() {
|
|
561
|
+
if (closed)
|
|
562
|
+
return; // idempotent: a second signal is ignored
|
|
563
|
+
closed = true;
|
|
564
|
+
// EX-1 / M6: if a start is in flight, let IT observe `closed` and unwind
|
|
565
|
+
// itself (close its own socket, release its own lock) rather than racing to
|
|
566
|
+
// close a mid-bind socket here (which would leave the start's `listen()`
|
|
567
|
+
// unsettled and hang shutdown). Its rejection is expected during this race.
|
|
568
|
+
const inFlightStart = startPromise;
|
|
569
|
+
if (inFlightStart !== null) {
|
|
570
|
+
try {
|
|
571
|
+
await inFlightStart;
|
|
572
|
+
}
|
|
573
|
+
catch {
|
|
574
|
+
// An aborted or failed start during a racing shutdown is expected here.
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
// Disarm the poll loops so no NEW tick starts, then drain the in-flight tick
|
|
578
|
+
// and the background boot tasks (bootSettled) before releasing the lock.
|
|
579
|
+
worker.stop();
|
|
580
|
+
enricherLoop?.stop();
|
|
581
|
+
// PRD-018b AC-018b.3: stop the watcher NOW (before the lock is released) so no
|
|
582
|
+
// new watch event is scheduled; an in-flight cycle is drained below. This also
|
|
583
|
+
// means the boot task's `startRegistrationPipeline` (if it has not run yet)
|
|
584
|
+
// sees `closed` and never starts the watcher during teardown.
|
|
585
|
+
registration?.service.stop();
|
|
586
|
+
if (registration !== null)
|
|
587
|
+
health.setWatchState({ running: false });
|
|
588
|
+
// AC-018a.10/11 (NEC-033): await the in-flight worker tick and bootSettled
|
|
589
|
+
// under a bounded timeout so a shutdown that catches the worker busy drains
|
|
590
|
+
// the write instead of killing it mid-flight. The drain never rejects
|
|
591
|
+
// (errors are logged); a drain that exceeds the timeout logs and proceeds so
|
|
592
|
+
// shutdown stays bounded (it must not reintroduce the NEC-021 hang). PRD-018b:
|
|
593
|
+
// the registration cycle and its durable bridge flush are drained too, so a
|
|
594
|
+
// ladder write in flight lands durably before the lock is released.
|
|
595
|
+
const drainWork = (async () => {
|
|
596
|
+
await worker.whenIdle();
|
|
597
|
+
await bootSettled;
|
|
598
|
+
if (registration !== null) {
|
|
599
|
+
await registration.service._waitForIdle();
|
|
600
|
+
await registration.bridge.whenFlushed();
|
|
601
|
+
}
|
|
602
|
+
})().catch((err) => {
|
|
603
|
+
log({ level: "error", scope: "daemon", msg: "drain error", err: String(err) });
|
|
604
|
+
});
|
|
605
|
+
const drained = await raceWithTimeout(drainWork, drainTimeoutMs);
|
|
606
|
+
if (!drained) {
|
|
607
|
+
log({ level: "warn", scope: "daemon", msg: "drain timed out; proceeding with shutdown", timeoutMs: drainTimeoutMs });
|
|
608
|
+
}
|
|
609
|
+
if (server !== null) {
|
|
610
|
+
await server.close(closeGraceMs);
|
|
611
|
+
server = null;
|
|
612
|
+
}
|
|
613
|
+
stopHeartbeat?.();
|
|
614
|
+
stopHeartbeat = null;
|
|
615
|
+
// Ownership-checked release: only remove the lock this instance holds. A
|
|
616
|
+
// failed second start (which never acquired the lock) has lockIdentity null
|
|
617
|
+
// and touches nothing, so it can never delete the live daemon's lock (NEC-002).
|
|
618
|
+
if (lockIdentity !== null) {
|
|
619
|
+
releaseSingleInstanceLock(lockPaths, lockIdentity);
|
|
620
|
+
lockIdentity = null;
|
|
621
|
+
}
|
|
622
|
+
startPromise = null; // allow a fresh start after a clean shutdown
|
|
623
|
+
log({ level: "info", scope: "daemon", msg: "shutdown complete" });
|
|
624
|
+
telemetry.close();
|
|
625
|
+
telemetry = createNullTelemetry(telemetryDbPath);
|
|
626
|
+
}
|
|
627
|
+
function installSignalHandlers() {
|
|
628
|
+
if (signalsInstalled)
|
|
629
|
+
return;
|
|
630
|
+
signalsInstalled = true;
|
|
631
|
+
const onSignal = (sig) => {
|
|
632
|
+
log({ level: "info", scope: "daemon", msg: `received ${sig}, draining` });
|
|
633
|
+
void shutdown().then(() => process.exit(0));
|
|
634
|
+
};
|
|
635
|
+
process.once("SIGINT", () => onSignal("SIGINT"));
|
|
636
|
+
process.once("SIGTERM", () => onSignal("SIGTERM"));
|
|
637
|
+
}
|
|
638
|
+
const daemon = {
|
|
639
|
+
config,
|
|
640
|
+
health,
|
|
641
|
+
worker,
|
|
642
|
+
broodGuard,
|
|
643
|
+
start,
|
|
644
|
+
shutdown,
|
|
645
|
+
pipelineStatus: () => health.pipelineStatus,
|
|
646
|
+
telemetry: () => telemetry,
|
|
647
|
+
installSignalHandlers,
|
|
648
|
+
acknowledgeAlert: () => enricherLoop?.acknowledgeAlert(),
|
|
649
|
+
awaitBoot: () => bootSettled,
|
|
650
|
+
group: (path) => router.group(path),
|
|
651
|
+
registration: () => registration,
|
|
652
|
+
registrationBootResyncCount: () => bootResyncCount,
|
|
653
|
+
};
|
|
654
|
+
// PRD-008: attach the /api/hive-graph handlers when the caller wired the
|
|
655
|
+
// mechanics. The group is already scaffolded + protected regardless; this
|
|
656
|
+
// fills it. Callers may equivalently call mountHiveGraphApi(daemon, opts).
|
|
657
|
+
if (options.hiveGraphApi !== undefined) {
|
|
658
|
+
// Share the daemon's brood guard with the API `/build` handler (AC-018g.2)
|
|
659
|
+
// unless the caller already supplied one.
|
|
660
|
+
mountHiveGraphApi(daemon, { broodGuard, ...options.hiveGraphApi });
|
|
661
|
+
}
|
|
662
|
+
return daemon;
|
|
663
|
+
}
|
|
664
|
+
//# sourceMappingURL=daemon.js.map
|