@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/cli.js
ADDED
|
@@ -0,0 +1,912 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* The nectar CLI.
|
|
4
|
+
*
|
|
5
|
+
* `nectar daemon` is the runnable process (PRD-002c): it invokes the
|
|
6
|
+
* composition root, acquires the single-instance lock before binding
|
|
7
|
+
* 127.0.0.1:3854, serves `/health`, and installs SIGINT/SIGTERM handlers.
|
|
8
|
+
*
|
|
9
|
+
* The operational verbs exit non-zero with a clear notice rather than a silent
|
|
10
|
+
* stub, in these shapes:
|
|
11
|
+
* - `brood` (PRD-007d): `--dry-run` runs a real local cost preview; a mutating
|
|
12
|
+
* brood dispatches daemon-side (PRD-008 build endpoint, a later wave).
|
|
13
|
+
* - `search` (PRD-012b): a thin loopback client of the daemon search endpoint
|
|
14
|
+
* (PRD-008b, a later wave); left unwired rather than importing the engine.
|
|
15
|
+
* - `prune` / `review-matches`: mechanics implemented and tested here
|
|
16
|
+
* (`runPrune` / `runReviewMatches`), but not yet wired to a durable,
|
|
17
|
+
* sync-capable hive-graph store (the NOT_WIRED map). They refuse to run
|
|
18
|
+
* against a throwaway empty store so a destructive verb never silently
|
|
19
|
+
* no-ops; the wiring lands with the daemon's registration-pipeline integration.
|
|
20
|
+
*
|
|
21
|
+
* `rebuild-projection` (and `project --rebuild-projection`) is wired REAL
|
|
22
|
+
* (PRD-011c): it scans the durable Deep Lake store for the latest described
|
|
23
|
+
* version per nectar scoped to the project and writes `.honeycomb/nectars.json`
|
|
24
|
+
* atomically. It resolves org/workspace from the shared `~/.deeplake`
|
|
25
|
+
* credentials the Deep Lake store already consumes and the project id + project
|
|
26
|
+
* root from `NECTAR_PROJECT_ID` / `NECTAR_PROJECT_ROOT` (see USAGE).
|
|
27
|
+
*/
|
|
28
|
+
import { realpathSync } from "node:fs";
|
|
29
|
+
import { join } from "node:path";
|
|
30
|
+
import { fileURLToPath } from "node:url";
|
|
31
|
+
import { createInterface } from "node:readline/promises";
|
|
32
|
+
import { assembleDaemon } from "./daemon.js";
|
|
33
|
+
import { resolveConfig } from "./config.js";
|
|
34
|
+
import { mountHiveGraphApi } from "./api/hive-graph-api.js";
|
|
35
|
+
import { buildHiveGraphApiOptions } from "./api/daemon-api-wiring.js";
|
|
36
|
+
import { searchViaDaemon, DaemonUnreachableError, DaemonSearchError } from "./api/loopback-client.js";
|
|
37
|
+
import { createServiceModule, serviceStatus } from "./service/index.js";
|
|
38
|
+
import { registerWithDoctor } from "./doctor-registry.js";
|
|
39
|
+
import { emitInstalled, emitUninstalled, recordDaemonStart } from "./telemetry-usage/emit.js";
|
|
40
|
+
import { DeepLakeHiveGraphStore } from "./hive-graph/deeplake-store.js";
|
|
41
|
+
import { InMemoryHiveGraphStore } from "./hive-graph/memory-store.js";
|
|
42
|
+
import { loadDeepLakeCredentials, credentialsPath } from "./hive-graph/deeplake-credentials.js";
|
|
43
|
+
import { broodPrereqsFromEnv, formatFirstRunGuidance } from "./brood-prereqs.js";
|
|
44
|
+
import { resolveNectarTunables } from "./config-file.js";
|
|
45
|
+
import { resolveProjectScope } from "./hive-graph/project-scope.js";
|
|
46
|
+
import { createDiskRegistrationFs } from "./registration/disk-fs.js";
|
|
47
|
+
import { StoreBridge } from "./registration/store-bridge.js";
|
|
48
|
+
import { runPrune } from "./registration/prune-cli.js";
|
|
49
|
+
import { runReviewMatches } from "./registration/review-cli.js";
|
|
50
|
+
import { FilePendingReviewStore, } from "./registration/review-store.js";
|
|
51
|
+
import { rebuildProjectionAsync, projectionFinalPath, ProjectionWriter } from "./projection/write.js";
|
|
52
|
+
import { DEFAULT_PROJECTION_REL_PATH } from "./projection/format.js";
|
|
53
|
+
import { resolvePortkeyConfig } from "./portkey/config.js";
|
|
54
|
+
import { activeEmbedModelId, resolveEmbeddingsConfig, validateEmbedDimension } from "./embeddings/config.js";
|
|
55
|
+
import { resolveEmbedProvider } from "./embeddings/provider.js";
|
|
56
|
+
import { stderrDimRejectionSink } from "./embeddings/guard.js";
|
|
57
|
+
import { DeepLakeEnricherStore } from "./enricher/store-adapter.js";
|
|
58
|
+
import { createPriorContentCache } from "./enricher/content-cache.js";
|
|
59
|
+
import { parseBroodArgs, planBrood, formatDryRunReport, discoverFiles, prepareFiles, runBroodAsync, } from "./brooding/index.js";
|
|
60
|
+
const USAGE = `nectar - semantic memory layer over a source tree
|
|
61
|
+
|
|
62
|
+
Usage:
|
|
63
|
+
nectar daemon Start the hiveantennae daemon (127.0.0.1:3854, /health)
|
|
64
|
+
nectar install Register the OS service unit + the doctor registry entry (PRD-003)
|
|
65
|
+
nectar uninstall Deregister the OS service unit (PRD-003b)
|
|
66
|
+
nectar service-status Report the OS service unit's running state (PRD-003b)
|
|
67
|
+
nectar brood [flags] Full-codebase brood (PRD-007). --dry-run previews cost locally;
|
|
68
|
+
a mutating brood runs against the durable Deep Lake store (needs
|
|
69
|
+
Portkey configured). Flags: --force, --limit N, --dry-run, --model <id>
|
|
70
|
+
nectar search <query> [flags] Manual hive-graph search (PRD-012). Thin loopback client of the
|
|
71
|
+
daemon search endpoint (POST /api/hive-graph/search). Requires a
|
|
72
|
+
running 'nectar daemon'. Flags: --limit N, --json
|
|
73
|
+
nectar prune [--confirm] Prune long-missing nectars from the durable store (PRD-006d)
|
|
74
|
+
nectar review-matches Review low-confidence step-4 matches against the durable store (PRD-006d)
|
|
75
|
+
nectar rebuild-projection Regenerate .honeycomb/nectars.json from Deep Lake (PRD-011)
|
|
76
|
+
nectar project --rebuild-projection Project-scoped regeneration of .honeycomb/nectars.json (PRD-011)
|
|
77
|
+
nectar --help Show this help
|
|
78
|
+
|
|
79
|
+
rebuild-projection reads org_id/workspace_id from ~/.deeplake/credentials.json (the
|
|
80
|
+
shared file the Deep Lake store already uses). The project id resolves through the
|
|
81
|
+
per-project scope ladder (mirrors honeycomb's resolver, never requires honeycomb):
|
|
82
|
+
NECTAR_PROJECT_ID > detected HONEYCOMB_PROJECT_ID > ~/.deeplake/projects.json folder
|
|
83
|
+
binding (longest prefix) > git remote signal > the workspace __unsorted__ inbox.
|
|
84
|
+
The project root comes from NECTAR_PROJECT_ROOT (defaults to the current working
|
|
85
|
+
directory).
|
|
86
|
+
`;
|
|
87
|
+
/** The exec path the OS service unit will run (mirrors doctor's own CLI resolution). */
|
|
88
|
+
function resolveServiceExecPath() {
|
|
89
|
+
return process.argv[1] ?? "nectar";
|
|
90
|
+
}
|
|
91
|
+
/** Opt into a system-scoped unit via env (mirrors doctor's DOCTOR_SERVICE_SYSTEM). */
|
|
92
|
+
function preferSystemScope() {
|
|
93
|
+
return (process.env["NECTAR_SERVICE_SYSTEM"] ?? "") === "1";
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* `nectar install` (PRD-003): lays down the OS service unit (003b) AND appends
|
|
97
|
+
* nectar's entry to doctor's registry (003c) - the same installer performs
|
|
98
|
+
* both, per PRD-003c's "no two-phase hazard" note. Does not restart doctor;
|
|
99
|
+
* the registry entry takes effect at doctor's next natural boot.
|
|
100
|
+
*/
|
|
101
|
+
async function runInstall() {
|
|
102
|
+
const config = resolveConfig();
|
|
103
|
+
const serviceModule = createServiceModule({
|
|
104
|
+
execPath: resolveServiceExecPath(),
|
|
105
|
+
preferSystemScope: preferSystemScope(),
|
|
106
|
+
});
|
|
107
|
+
const serviceResult = await serviceModule.install();
|
|
108
|
+
process.stdout.write(`${serviceResult.message}\n`);
|
|
109
|
+
try {
|
|
110
|
+
const registration = registerWithDoctor({ config });
|
|
111
|
+
const verb = registration.created ? "created" : registration.replaced ? "updated" : "appended to";
|
|
112
|
+
process.stdout.write(`doctor registry ${verb} at ${registration.registryPath} (healthUrl ${registration.entry.healthUrl}). ` +
|
|
113
|
+
"doctor will supervise nectar starting at its next boot.\n");
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
process.stderr.write(`nectar install: could not update the doctor registry: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
117
|
+
return 1;
|
|
118
|
+
}
|
|
119
|
+
// Usage telemetry: fired only on full success, after the user-facing output.
|
|
120
|
+
// emitInstalled never throws and is bounded, so it cannot alter the exit code.
|
|
121
|
+
if (serviceResult.ok) {
|
|
122
|
+
await emitInstalled();
|
|
123
|
+
}
|
|
124
|
+
return serviceResult.ok ? 0 : 1;
|
|
125
|
+
}
|
|
126
|
+
/** `nectar uninstall` (PRD-003b): deregisters the OS service unit so it does not resurrect. */
|
|
127
|
+
async function runUninstall() {
|
|
128
|
+
const serviceModule = createServiceModule({
|
|
129
|
+
execPath: resolveServiceExecPath(),
|
|
130
|
+
preferSystemScope: preferSystemScope(),
|
|
131
|
+
});
|
|
132
|
+
const result = await serviceModule.uninstall();
|
|
133
|
+
process.stdout.write(`${result.message}\n`);
|
|
134
|
+
// Usage telemetry (NEC-042 item 4 / AC-018l.11): fire only AFTER the uninstall
|
|
135
|
+
// outcome is known, and only on success - a failed/aborted uninstall must not
|
|
136
|
+
// emit a `nectar_uninstalled` event. emitUninstalled never throws and is
|
|
137
|
+
// bounded, so it cannot alter the exit code.
|
|
138
|
+
if (result.ok)
|
|
139
|
+
await emitUninstalled();
|
|
140
|
+
return result.ok ? 0 : 1;
|
|
141
|
+
}
|
|
142
|
+
/** `nectar service-status` (PRD-003b): reports the OS service manager's coarse state. */
|
|
143
|
+
async function runServiceStatus() {
|
|
144
|
+
const status = await serviceStatus({
|
|
145
|
+
execPath: resolveServiceExecPath(),
|
|
146
|
+
preferSystemScope: preferSystemScope(),
|
|
147
|
+
});
|
|
148
|
+
process.stdout.write(`${status}\n`);
|
|
149
|
+
return status === "unknown" ? 1 : 0;
|
|
150
|
+
}
|
|
151
|
+
/** Read an env var, treating unset OR blank/whitespace-only as absent (mirrors config.ts). */
|
|
152
|
+
function cliEnvStr(name) {
|
|
153
|
+
const raw = process.env[name];
|
|
154
|
+
if (raw === undefined || raw.trim() === "")
|
|
155
|
+
return undefined;
|
|
156
|
+
return raw;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Resolve the tenancy triple + project root for the projection CLI verbs. org
|
|
160
|
+
* and workspace come from the SAME `~/.deeplake/credentials.json` the Deep Lake
|
|
161
|
+
* store consumes (`deeplake-credentials.ts`); the project id resolves through
|
|
162
|
+
* the per-project scope ladder (`hive-graph/project-scope.ts`, mirroring
|
|
163
|
+
* honeycomb's resolver across the process boundary): NECTAR_PROJECT_ID, then
|
|
164
|
+
* the detected HONEYCOMB_PROJECT_ID, then the `~/.deeplake/projects.json`
|
|
165
|
+
* folder binding (longest prefix), then the git-remote signal, then the
|
|
166
|
+
* workspace `__unsorted__` inbox; the project root defaults to the current
|
|
167
|
+
* working directory. Returns a typed error string instead of throwing so the
|
|
168
|
+
* caller can print a clear notice and exit non-zero.
|
|
169
|
+
*/
|
|
170
|
+
function resolveProjectionContext() {
|
|
171
|
+
let credentials;
|
|
172
|
+
try {
|
|
173
|
+
credentials = loadDeepLakeCredentials();
|
|
174
|
+
}
|
|
175
|
+
catch (err) {
|
|
176
|
+
return { ok: false, message: err instanceof Error ? err.message : String(err) };
|
|
177
|
+
}
|
|
178
|
+
const projectRoot = cliEnvStr("NECTAR_PROJECT_ROOT") ?? process.cwd();
|
|
179
|
+
const scope = resolveProjectScope({
|
|
180
|
+
cwd: projectRoot,
|
|
181
|
+
expect: { org: credentials.orgId, workspace: credentials.workspaceId },
|
|
182
|
+
});
|
|
183
|
+
const tenancy = {
|
|
184
|
+
orgId: credentials.orgId,
|
|
185
|
+
workspaceId: credentials.workspaceId,
|
|
186
|
+
projectId: scope.projectId,
|
|
187
|
+
};
|
|
188
|
+
const store = new DeepLakeHiveGraphStore({ credentials });
|
|
189
|
+
return { ok: true, tenancy, projectRoot, store, scopeSource: scope.source, credentials };
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* `nectar rebuild-projection` / `nectar project --rebuild-projection`
|
|
193
|
+
* (PRD-011c, trigger #3): a full regeneration of `.honeycomb/nectars.json` from
|
|
194
|
+
* a single Deep Lake scan (latest described version per nectar, scoped to the
|
|
195
|
+
* project), written atomically. Both verbs share this one routine.
|
|
196
|
+
*/
|
|
197
|
+
async function runRebuildProjection() {
|
|
198
|
+
const ctx = resolveProjectionContext();
|
|
199
|
+
if (!ctx.ok) {
|
|
200
|
+
process.stderr.write(`nectar rebuild-projection: ${ctx.message}.\n` +
|
|
201
|
+
"org_id/workspace_id come from ~/.deeplake/credentials.json; the project id resolves via " +
|
|
202
|
+
"NECTAR_PROJECT_ID > detected HONEYCOMB_PROJECT_ID > ~/.deeplake/projects.json binding > git remote signal > __unsorted__.\n");
|
|
203
|
+
return 1;
|
|
204
|
+
}
|
|
205
|
+
const { doc, path } = await rebuildProjectionAsync(ctx.store, ctx.tenancy, { projectRoot: ctx.projectRoot });
|
|
206
|
+
const fileCount = Object.keys(doc.files).length;
|
|
207
|
+
process.stdout.write(`nectar rebuild-projection: regenerated ${path} (${fileCount} nectar${fileCount === 1 ? "" : "s"}, ` +
|
|
208
|
+
`project ${ctx.tenancy.orgId}/${ctx.tenancy.workspaceId}/${ctx.tenancy.projectId}, scope via ${ctx.scopeSource}).\n`);
|
|
209
|
+
return 0;
|
|
210
|
+
}
|
|
211
|
+
export function classifyBroodInvocation(broodArgs) {
|
|
212
|
+
const parsed = parseBroodArgs(broodArgs);
|
|
213
|
+
if (parsed.errors.length > 0)
|
|
214
|
+
return { kind: "errors", errors: parsed.errors };
|
|
215
|
+
if (parsed.options.dryRun === true)
|
|
216
|
+
return { kind: "dry-run", options: parsed.options };
|
|
217
|
+
return { kind: "run", options: parsed.options };
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* `nectar brood --dry-run` (PRD-007d): a real, read-only cost preview run
|
|
221
|
+
* locally via `planBrood` (discover -> pre-check -> bucket -> estimate), which
|
|
222
|
+
* makes NO LLM call and writes NOTHING. Runs against a throwaway in-memory store
|
|
223
|
+
* because the preview is `brooding-pipeline.md`'s "recommended first step on a
|
|
224
|
+
* new project" where the durable store is empty; the projection-inherited count
|
|
225
|
+
* still reads the on-disk `.honeycomb/nectars.json` faithfully. A daemon-side
|
|
226
|
+
* dry-run reflecting live store state lands with the PRD-008 build endpoint.
|
|
227
|
+
*/
|
|
228
|
+
function runBroodDryRun() {
|
|
229
|
+
const ctx = resolveProjectionContext();
|
|
230
|
+
if (!ctx.ok) {
|
|
231
|
+
process.stderr.write(`nectar brood --dry-run: ${ctx.message}.\n` +
|
|
232
|
+
"org_id/workspace_id come from ~/.deeplake/credentials.json; the project id resolves via " +
|
|
233
|
+
"NECTAR_PROJECT_ID > detected HONEYCOMB_PROJECT_ID > ~/.deeplake/projects.json binding > git remote signal > __unsorted__.\n");
|
|
234
|
+
return 1;
|
|
235
|
+
}
|
|
236
|
+
const config = {
|
|
237
|
+
store: new InMemoryHiveGraphStore(),
|
|
238
|
+
tenancy: ctx.tenancy,
|
|
239
|
+
root: ctx.projectRoot,
|
|
240
|
+
fs: createDiskRegistrationFs(ctx.projectRoot),
|
|
241
|
+
};
|
|
242
|
+
const plan = planBrood(config);
|
|
243
|
+
process.stdout.write(`${formatDryRunReport({
|
|
244
|
+
discoveredCount: plan.discoveredCount,
|
|
245
|
+
inheritedCount: plan.inheritedCount,
|
|
246
|
+
skipBinaryCount: plan.skipBinaryCount,
|
|
247
|
+
skipTooLargeCount: plan.skipTooLargeCount,
|
|
248
|
+
batchFileCount: plan.batchFileCount,
|
|
249
|
+
soloFileCount: plan.soloFileCount,
|
|
250
|
+
batchCalls: plan.batchCalls,
|
|
251
|
+
soloCalls: plan.soloCalls,
|
|
252
|
+
estimate: plan.estimate,
|
|
253
|
+
// PRD-018c AC-018c.11: report the discovery source and, when git errored
|
|
254
|
+
// (not simply absent), the degradation reason.
|
|
255
|
+
source: plan.source,
|
|
256
|
+
...(plan.degraded !== undefined ? { degraded: plan.degraded } : {}),
|
|
257
|
+
})}\n`);
|
|
258
|
+
return 0;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* `nectar brood [flags]` (PRD-007d). `--dry-run` runs the local cost preview; a
|
|
262
|
+
* mutating brood executes daemon-side (PRD-007d "the brood mechanic executes
|
|
263
|
+
* daemon-side; the CLI dispatches to it") through the PRD-008
|
|
264
|
+
* `POST /api/hive-graph/build` endpoint, which lands in a later wave. A CLI-side
|
|
265
|
+
* durable brood is additionally blocked by the sync/async store split
|
|
266
|
+
* (`runBrood` needs the synchronous `HiveGraphStore`; the durable substrate is
|
|
267
|
+
* async — the deferral documented on `AsyncHiveGraphStore`), so it is not
|
|
268
|
+
* simulated against a throwaway store.
|
|
269
|
+
*/
|
|
270
|
+
async function runBroodCommand(broodArgs) {
|
|
271
|
+
const invocation = classifyBroodInvocation(broodArgs);
|
|
272
|
+
switch (invocation.kind) {
|
|
273
|
+
case "errors":
|
|
274
|
+
for (const err of invocation.errors)
|
|
275
|
+
process.stderr.write(`nectar brood: ${err}\n`);
|
|
276
|
+
return 2;
|
|
277
|
+
case "dry-run":
|
|
278
|
+
return runBroodDryRun();
|
|
279
|
+
case "run":
|
|
280
|
+
return runBroodMutating(invocation.options);
|
|
281
|
+
default: {
|
|
282
|
+
const unreachable = invocation;
|
|
283
|
+
return unreachable;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Run a mutating brood against the durable async store (AC-018b.8): `runBroodAsync`
|
|
289
|
+
* discovers, mints, describes, and persists to Deep Lake directly (it consumes the
|
|
290
|
+
* async store, so no sync/async bridge is needed here). Returns 0 on success.
|
|
291
|
+
*/
|
|
292
|
+
export async function runBroodMutatingVerb(d) {
|
|
293
|
+
const result = await runBroodAsync(d.config, d.deps, d.options ?? {});
|
|
294
|
+
d.out(`nectar brood: discovered ${result.discoveredCount} file(s); ` +
|
|
295
|
+
`${result.describedCount} described, ${result.failedCount} failed` +
|
|
296
|
+
`${result.projectionPath !== null ? `; projection ${result.projectionPath}` : ""}.`);
|
|
297
|
+
return 0;
|
|
298
|
+
}
|
|
299
|
+
/** Run `prune` (preview or `--confirm` delete) against the injected store (AC-018b.8). Returns 0. */
|
|
300
|
+
export function runPruneVerb(deps) {
|
|
301
|
+
runPrune({
|
|
302
|
+
store: deps.store,
|
|
303
|
+
tenancy: deps.tenancy,
|
|
304
|
+
existsOnDisk: (p) => deps.existsOnDisk(p),
|
|
305
|
+
now: deps.now ?? (() => new Date().toISOString()),
|
|
306
|
+
confirm: deps.confirm,
|
|
307
|
+
out: deps.out,
|
|
308
|
+
});
|
|
309
|
+
return 0;
|
|
310
|
+
}
|
|
311
|
+
/** Run `review-matches` against the injected store (AC-018b.8). Returns 0. */
|
|
312
|
+
export async function runReviewMatchesVerb(deps) {
|
|
313
|
+
await runReviewMatches({
|
|
314
|
+
store: deps.store,
|
|
315
|
+
tenancy: deps.tenancy,
|
|
316
|
+
pendingReviews: deps.pendingReviews,
|
|
317
|
+
decide: deps.decide,
|
|
318
|
+
out: deps.out,
|
|
319
|
+
now: deps.now ?? (() => new Date().toISOString()),
|
|
320
|
+
});
|
|
321
|
+
return 0;
|
|
322
|
+
}
|
|
323
|
+
/** The real stdin/stdout-backed {@link InteractiveReviewIo}. */
|
|
324
|
+
function realInteractiveReviewIo() {
|
|
325
|
+
const isTTY = process.stdin.isTTY === true;
|
|
326
|
+
if (!isTTY) {
|
|
327
|
+
return { isTTY, question: async () => "", write: () => { }, close: () => { } };
|
|
328
|
+
}
|
|
329
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
330
|
+
return {
|
|
331
|
+
isTTY,
|
|
332
|
+
question: (prompt) => rl.question(prompt),
|
|
333
|
+
write: (line) => process.stdout.write(`${line}\n`),
|
|
334
|
+
close: () => rl.close(),
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* A stdin-driven per-candidate decider for the interactive `review-matches`
|
|
339
|
+
* prompt. On a non-TTY stdin (a script, CI) it defaults every candidate to
|
|
340
|
+
* `skip` (the safe, non-destructive choice) rather than blocking on input; a
|
|
341
|
+
* real TTY gets the preview printed, then an accept/reject/skip prompt.
|
|
342
|
+
* Returns a `close` so the caller releases stdin (otherwise the readline
|
|
343
|
+
* interface would keep the process alive).
|
|
344
|
+
*
|
|
345
|
+
* CodeRabbit PR-18 finding #6: the prior implementation's `decide` ignored its
|
|
346
|
+
* `candidate`/`preview` parameters entirely, so on its own it asked
|
|
347
|
+
* accept/reject/skip with zero printed context. `runReviewMatches`
|
|
348
|
+
* (`review-cli.ts`) happens to print the same preview via `out()` immediately
|
|
349
|
+
* before calling `decide` today, but `decide` should not depend on that
|
|
350
|
+
* caller-side ordering to be usable - it prints the preview itself now.
|
|
351
|
+
*/
|
|
352
|
+
export function interactiveReviewDecider(io = realInteractiveReviewIo()) {
|
|
353
|
+
if (!io.isTTY) {
|
|
354
|
+
return { decide: async () => "skip", close: io.close };
|
|
355
|
+
}
|
|
356
|
+
return {
|
|
357
|
+
decide: async (_candidate, preview) => {
|
|
358
|
+
io.write(preview);
|
|
359
|
+
const answer = (await io.question(" [a]ccept / [r]eject / [s]kip? ")).trim().toLowerCase();
|
|
360
|
+
if (answer === "a" || answer === "accept")
|
|
361
|
+
return "accept";
|
|
362
|
+
if (answer === "r" || answer === "reject")
|
|
363
|
+
return "reject";
|
|
364
|
+
return "skip";
|
|
365
|
+
},
|
|
366
|
+
close: io.close,
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Resolve the embed provider + its active embed model id for the CLI's
|
|
371
|
+
* mutating brood deps, the same way the daemon wiring does
|
|
372
|
+
* (`api/daemon-api-wiring.ts`'s `activeEmbedModel`) - CodeRabbit PR-18 finding
|
|
373
|
+
* #7. Exported so the resolution itself (independent of the live Deep Lake
|
|
374
|
+
* context `runBroodMutating` also needs) is unit-testable without network
|
|
375
|
+
* credentials: without threading `embedModelId` through, CLI-brooded rows
|
|
376
|
+
* stamped `embed_model = null` and were never requeued on a provider switch
|
|
377
|
+
* (AC-018i.3).
|
|
378
|
+
*/
|
|
379
|
+
export function resolveCliBroodEmbedDeps() {
|
|
380
|
+
const embeddingsConfig = resolveEmbeddingsConfig({});
|
|
381
|
+
return {
|
|
382
|
+
embedProvider: resolveEmbedProvider(embeddingsConfig),
|
|
383
|
+
embedModelId: activeEmbedModelId(embeddingsConfig),
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* `nectar brood` (mutating, PRD-018b AC-018b.8): resolve the Deep Lake context,
|
|
388
|
+
* require a Portkey describe transport (an LLM-less brood cannot describe), and
|
|
389
|
+
* run the real `runBroodAsync` against the durable store. Exits 1 (a real error,
|
|
390
|
+
* not a wiring stub) when credentials or Portkey are absent.
|
|
391
|
+
*/
|
|
392
|
+
async function runBroodMutating(options) {
|
|
393
|
+
const ctx = resolveProjectionContext();
|
|
394
|
+
if (!ctx.ok) {
|
|
395
|
+
process.stderr.write(`nectar brood: ${ctx.message}.\n` +
|
|
396
|
+
"org_id/workspace_id come from ~/.deeplake/credentials.json; the project id resolves via " +
|
|
397
|
+
"NECTAR_PROJECT_ID > detected HONEYCOMB_PROJECT_ID > ~/.deeplake/projects.json binding > git remote signal > __unsorted__.\n");
|
|
398
|
+
return 1;
|
|
399
|
+
}
|
|
400
|
+
const portkey = resolvePortkeyConfig();
|
|
401
|
+
if (!portkey.enabled) {
|
|
402
|
+
process.stderr.write("nectar brood: a mutating brood needs a describe transport. Configure Portkey " +
|
|
403
|
+
"(PORTKEY_API_KEY + PORTKEY_CONFIG) and retry, or use 'nectar brood --dry-run' for a local cost preview.\n");
|
|
404
|
+
return 1;
|
|
405
|
+
}
|
|
406
|
+
const { embedProvider, embedModelId } = resolveCliBroodEmbedDeps();
|
|
407
|
+
return runBroodMutatingVerb({
|
|
408
|
+
config: {
|
|
409
|
+
store: ctx.store,
|
|
410
|
+
tenancy: ctx.tenancy,
|
|
411
|
+
root: ctx.projectRoot,
|
|
412
|
+
fs: createDiskRegistrationFs(ctx.projectRoot),
|
|
413
|
+
},
|
|
414
|
+
deps: { portkey, embedProvider, embedModelId },
|
|
415
|
+
options,
|
|
416
|
+
out: (line) => process.stdout.write(`${line}\n`),
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Build a {@link StoreBridge} over the resolved durable store, hydrate it, run
|
|
421
|
+
* `body` against the SYNC bridge (so the tested `runPrune`/`runReviewMatches`
|
|
422
|
+
* mechanics run unchanged), then flush the durable writes. Returns the body's
|
|
423
|
+
* exit code, or 1 with a printed notice when no Deep Lake context resolves.
|
|
424
|
+
*/
|
|
425
|
+
async function withDurableBridge(purpose, body) {
|
|
426
|
+
const ctx = resolveProjectionContext();
|
|
427
|
+
if (!ctx.ok) {
|
|
428
|
+
process.stderr.write(`nectar ${purpose}: ${ctx.message}.\n` +
|
|
429
|
+
"org_id/workspace_id come from ~/.deeplake/credentials.json; the project id resolves via " +
|
|
430
|
+
"NECTAR_PROJECT_ID > detected HONEYCOMB_PROJECT_ID > ~/.deeplake/projects.json binding > git remote signal > __unsorted__.\n");
|
|
431
|
+
return 1;
|
|
432
|
+
}
|
|
433
|
+
const bridge = new StoreBridge({
|
|
434
|
+
durable: ctx.store,
|
|
435
|
+
onFlushError: (err, op) => process.stderr.write(`nectar ${purpose}: durable ${op} failed (non-fatal): ${err instanceof Error ? err.message : String(err)}\n`),
|
|
436
|
+
});
|
|
437
|
+
await bridge.hydrate(ctx.tenancy);
|
|
438
|
+
const code = await body(bridge, ctx);
|
|
439
|
+
await bridge.whenFlushed();
|
|
440
|
+
if (bridge.durableFlushFailures > 0) {
|
|
441
|
+
process.stderr.write(`nectar ${purpose}: ${bridge.durableFlushFailures} durable write(s) failed to flush; ` +
|
|
442
|
+
"the local result above is applied but Deep Lake may be behind. Re-run once connectivity is restored.\n");
|
|
443
|
+
return 1;
|
|
444
|
+
}
|
|
445
|
+
return code;
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* `nectar prune [--confirm]` (PRD-018b AC-018b.8): the real `runPrune` mechanic
|
|
449
|
+
* against the durable store through the sync/async bridge.
|
|
450
|
+
*/
|
|
451
|
+
async function runPruneCommand(args) {
|
|
452
|
+
const confirm = args.includes("--confirm");
|
|
453
|
+
return withDurableBridge("prune", async (bridge, ctx) => {
|
|
454
|
+
const fs = createDiskRegistrationFs(ctx.projectRoot);
|
|
455
|
+
return runPruneVerb({
|
|
456
|
+
store: bridge,
|
|
457
|
+
tenancy: ctx.tenancy,
|
|
458
|
+
existsOnDisk: (p) => fs.existsOnDisk(p),
|
|
459
|
+
confirm,
|
|
460
|
+
out: (line) => process.stdout.write(`${line}\n`),
|
|
461
|
+
});
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* `nectar review-matches` (PRD-018b AC-018b.8): the real `runReviewMatches`
|
|
466
|
+
* mechanic against the durable store through the sync/async bridge, reading the
|
|
467
|
+
* same file-backed pending-review queue the daemon writes.
|
|
468
|
+
*/
|
|
469
|
+
async function runReviewMatchesCommand() {
|
|
470
|
+
const config = resolveConfig();
|
|
471
|
+
const reviews = new FilePendingReviewStore(join(config.runtimeDir, "pending-reviews.json"));
|
|
472
|
+
const decider = interactiveReviewDecider();
|
|
473
|
+
try {
|
|
474
|
+
return await withDurableBridge("review-matches", (bridge, ctx) => runReviewMatchesVerb({
|
|
475
|
+
store: bridge,
|
|
476
|
+
tenancy: ctx.tenancy,
|
|
477
|
+
pendingReviews: reviews,
|
|
478
|
+
decide: decider.decide,
|
|
479
|
+
out: (line) => process.stdout.write(`${line}\n`),
|
|
480
|
+
}));
|
|
481
|
+
}
|
|
482
|
+
finally {
|
|
483
|
+
decider.close();
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Parse `nectar search <query> [--limit N] [--json]`. The positional
|
|
488
|
+
* (non-flag) tokens join into the query; `--limit N`/`--limit=N` sets the cap
|
|
489
|
+
* (a non-positive-integer value is an error); `--json` emits raw JSON. A
|
|
490
|
+
* missing query or an unknown flag is an error.
|
|
491
|
+
*/
|
|
492
|
+
export function parseSearchArgs(args) {
|
|
493
|
+
const errors = [];
|
|
494
|
+
const queryParts = [];
|
|
495
|
+
let limit;
|
|
496
|
+
let json = false;
|
|
497
|
+
for (let i = 0; i < args.length; i++) {
|
|
498
|
+
const arg = args[i] ?? "";
|
|
499
|
+
if (arg === "--json") {
|
|
500
|
+
json = true;
|
|
501
|
+
}
|
|
502
|
+
else if (arg === "--limit") {
|
|
503
|
+
const raw = args[i + 1];
|
|
504
|
+
if (raw === undefined) {
|
|
505
|
+
errors.push("--limit requires a value");
|
|
506
|
+
}
|
|
507
|
+
else {
|
|
508
|
+
const n = Number.parseInt(raw, 10);
|
|
509
|
+
if (!Number.isFinite(n) || n < 1 || String(n) !== raw)
|
|
510
|
+
errors.push(`--limit expects a positive integer, got '${raw}'`);
|
|
511
|
+
else
|
|
512
|
+
limit = n;
|
|
513
|
+
i++;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
else if (arg.startsWith("--limit=")) {
|
|
517
|
+
const raw = arg.slice("--limit=".length);
|
|
518
|
+
const n = Number.parseInt(raw, 10);
|
|
519
|
+
if (!Number.isFinite(n) || n < 1 || String(n) !== raw)
|
|
520
|
+
errors.push(`--limit expects a positive integer, got '${raw}'`);
|
|
521
|
+
else
|
|
522
|
+
limit = n;
|
|
523
|
+
}
|
|
524
|
+
else if (arg.startsWith("--")) {
|
|
525
|
+
errors.push(`unknown flag '${arg}'`);
|
|
526
|
+
}
|
|
527
|
+
else {
|
|
528
|
+
queryParts.push(arg);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
const query = queryParts.join(" ").trim();
|
|
532
|
+
if (query === "")
|
|
533
|
+
errors.push("a query is required: nectar search <query> [--limit N] [--json]");
|
|
534
|
+
if (errors.length > 0)
|
|
535
|
+
return { kind: "errors", errors };
|
|
536
|
+
return { kind: "run", query, limit, json };
|
|
537
|
+
}
|
|
538
|
+
/** Truncate a one-line preview of a description for the human table. */
|
|
539
|
+
function truncateCell(value, max = 72) {
|
|
540
|
+
const oneLine = value.replace(/\s+/g, " ").trim();
|
|
541
|
+
return oneLine.length <= max ? oneLine : `${oneLine.slice(0, max - 1)}\u2026`;
|
|
542
|
+
}
|
|
543
|
+
/** Render the engine result as a human-readable ranked table (default, non-`--json`). */
|
|
544
|
+
export function renderSearchTable(result) {
|
|
545
|
+
const lines = [];
|
|
546
|
+
if (result.hits.length === 0) {
|
|
547
|
+
lines.push("No matching files.");
|
|
548
|
+
}
|
|
549
|
+
else {
|
|
550
|
+
lines.push(`${result.hits.length} result${result.hits.length === 1 ? "" : "s"}:`);
|
|
551
|
+
result.hits.forEach((hit, index) => {
|
|
552
|
+
lines.push(` ${index + 1}. ${hit.path}`);
|
|
553
|
+
if (hit.title.trim() !== "")
|
|
554
|
+
lines.push(` ${truncateCell(hit.title)}`);
|
|
555
|
+
if (hit.body.trim() !== "")
|
|
556
|
+
lines.push(` ${truncateCell(hit.body)}`);
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
if (result.degraded) {
|
|
560
|
+
lines.push("");
|
|
561
|
+
if (result.reason === "backend-error") {
|
|
562
|
+
lines.push("(degraded: one or more search backends failed; use --json for arm status)");
|
|
563
|
+
}
|
|
564
|
+
else {
|
|
565
|
+
lines.push("(degraded: semantic search did not run; results are lexical-only)");
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
return `${lines.join("\n")}\n`;
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* `nectar search <query> [--limit N] [--json]` (PRD-012b): a THIN loopback
|
|
572
|
+
* client of the daemon's `POST /api/hive-graph/search` endpoint (PRD-008b). It
|
|
573
|
+
* never imports the search engine or any Deep Lake path (AC-012b.3.1) — it only
|
|
574
|
+
* reaches the running daemon over loopback. When the daemon is not running the
|
|
575
|
+
* connection failure is reported clearly and the verb exits non-zero with NO
|
|
576
|
+
* local fallback (AC-012b.3.2).
|
|
577
|
+
*/
|
|
578
|
+
async function runSearchCommand(args) {
|
|
579
|
+
const invocation = parseSearchArgs(args);
|
|
580
|
+
if (invocation.kind === "errors") {
|
|
581
|
+
for (const err of invocation.errors)
|
|
582
|
+
process.stderr.write(`nectar search: ${err}\n`);
|
|
583
|
+
return 2;
|
|
584
|
+
}
|
|
585
|
+
const config = resolveConfig();
|
|
586
|
+
try {
|
|
587
|
+
const result = await searchViaDaemon({
|
|
588
|
+
host: config.host,
|
|
589
|
+
port: config.port,
|
|
590
|
+
query: invocation.query,
|
|
591
|
+
limit: invocation.limit,
|
|
592
|
+
});
|
|
593
|
+
if (invocation.json)
|
|
594
|
+
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
595
|
+
else
|
|
596
|
+
process.stdout.write(renderSearchTable(result));
|
|
597
|
+
return 0;
|
|
598
|
+
}
|
|
599
|
+
catch (err) {
|
|
600
|
+
if (err instanceof DaemonUnreachableError) {
|
|
601
|
+
process.stderr.write(`nectar search: the nectar daemon is not reachable on ${config.host}:${config.port} (${err.message}).\n` +
|
|
602
|
+
"Start it with 'nectar daemon'. Search reaches the running daemon over loopback and does not fall back to a local index.\n");
|
|
603
|
+
return 2;
|
|
604
|
+
}
|
|
605
|
+
if (err instanceof DaemonSearchError) {
|
|
606
|
+
process.stderr.write(`nectar search: the daemon rejected the search: ${err.message}\n`);
|
|
607
|
+
return 1;
|
|
608
|
+
}
|
|
609
|
+
process.stderr.write(`nectar search: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
610
|
+
return 1;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* Build the boot projection load seam for the live daemon (PRD-011b AC-6): if a
|
|
615
|
+
* project context resolves, the daemon validates `.honeycomb/nectars.json` on
|
|
616
|
+
* boot and inherits hash-matched files into the durable Deep Lake store. All
|
|
617
|
+
* work is deferred to lazy providers so nothing scans disk or hits the network
|
|
618
|
+
* until AFTER the daemon is accepting requests; fail-soft throughout (a missing
|
|
619
|
+
* credentials file just skips the pre-warm). Returns undefined when no context
|
|
620
|
+
* resolves, so `nectar daemon` still starts on a bare machine.
|
|
621
|
+
*/
|
|
622
|
+
function resolveBootProjection() {
|
|
623
|
+
const ctx = resolveProjectionContext();
|
|
624
|
+
if (!ctx.ok)
|
|
625
|
+
return undefined;
|
|
626
|
+
const { store, tenancy, projectRoot } = ctx;
|
|
627
|
+
return {
|
|
628
|
+
tenancy,
|
|
629
|
+
filePath: projectionFinalPath(projectRoot, DEFAULT_PROJECTION_REL_PATH),
|
|
630
|
+
diskHashes: () => {
|
|
631
|
+
const discovery = discoverFiles({ root: projectRoot, fs: createDiskRegistrationFs(projectRoot) });
|
|
632
|
+
const prepared = prepareFiles(createDiskRegistrationFs(projectRoot), discovery.files);
|
|
633
|
+
return new Map(prepared.map((p) => [p.file.relPath, p.contentHash]));
|
|
634
|
+
},
|
|
635
|
+
existingNectars: async () => {
|
|
636
|
+
const latest = await store.listLatestVersions(tenancy);
|
|
637
|
+
return new Set(latest.map((lv) => lv.identity.nectar));
|
|
638
|
+
},
|
|
639
|
+
write: async (rows) => {
|
|
640
|
+
for (const row of rows) {
|
|
641
|
+
if ((await store.getIdentity(row.identity.nectar)) === undefined) {
|
|
642
|
+
await store.insertIdentity(row.identity);
|
|
643
|
+
}
|
|
644
|
+
await store.appendVersion(row.version);
|
|
645
|
+
}
|
|
646
|
+
},
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
/** Resolve the Deep Lake project context, swallowing a missing-creds error into `undefined`. */
|
|
650
|
+
function safeResolveContext() {
|
|
651
|
+
try {
|
|
652
|
+
const result = resolveProjectionContext();
|
|
653
|
+
return result.ok ? result : undefined;
|
|
654
|
+
}
|
|
655
|
+
catch {
|
|
656
|
+
return undefined;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
/** A metrics sink that delegates to the daemon's CURRENT telemetry (fresh per start()), for the live build brood path. */
|
|
660
|
+
function daemonMetricsProxy(daemon) {
|
|
661
|
+
return {
|
|
662
|
+
incrementFilesRegistered: () => daemon.telemetry().metrics.incrementFilesRegistered(),
|
|
663
|
+
incrementNectarsMinted: () => daemon.telemetry().metrics.incrementNectarsMinted(),
|
|
664
|
+
incrementDescriptionsGenerated: () => daemon.telemetry().metrics.incrementDescriptionsGenerated(),
|
|
665
|
+
incrementHiveGraphVersions: () => daemon.telemetry().metrics.incrementHiveGraphVersions(),
|
|
666
|
+
incrementEmbeddingsComputed: () => daemon.telemetry().metrics.incrementEmbeddingsComputed(),
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
/**
|
|
670
|
+
* Build the durable enricher store (hydrated per-nectar-latest from the async
|
|
671
|
+
* store, write-through UPDATEs over the daemon's transport) and a disk content
|
|
672
|
+
* reader for the live enricher cycle. `AsyncHiveGraphStore` exposes only
|
|
673
|
+
* latest-per-nectar reads, so hydration seeds the enricher's pending-selection
|
|
674
|
+
* working set from `listLatestVersions`; per-nectar history (cosmetic-inherit's
|
|
675
|
+
* `priorDescribedVersion`) is not carried across a cold boot, so that step
|
|
676
|
+
* degrades to a fresh describe rather than an inherit (documented, honest).
|
|
677
|
+
*/
|
|
678
|
+
function buildLiveDurableWiring(ctx, portkey) {
|
|
679
|
+
const fs = createDiskRegistrationFs(ctx.projectRoot);
|
|
680
|
+
const readContent = {
|
|
681
|
+
read: (path) => {
|
|
682
|
+
const stat = fs.statPath(path);
|
|
683
|
+
if (stat === null)
|
|
684
|
+
return null;
|
|
685
|
+
try {
|
|
686
|
+
return Buffer.from(stat.readContent()).toString("utf8");
|
|
687
|
+
}
|
|
688
|
+
catch {
|
|
689
|
+
return null;
|
|
690
|
+
}
|
|
691
|
+
},
|
|
692
|
+
};
|
|
693
|
+
// PRD-018g / NEC-017: the durable write-back is a collision-safe VERSION-BUMP
|
|
694
|
+
// APPEND (`appendVersionAtNextSeq`), not the retired fire-and-forget in-place
|
|
695
|
+
// UPDATE. The cycle awaits it and only counts a file described on a confirmed
|
|
696
|
+
// durable write.
|
|
697
|
+
const enricher = new DeepLakeEnricherStore({
|
|
698
|
+
loadVersions: async (tenancy) => (await ctx.store.listLatestVersions(tenancy)).map((lv) => lv.version),
|
|
699
|
+
appendVersion: (row) => ctx.store.appendVersionAtNextSeq(row),
|
|
700
|
+
onWriteBackError: (err) => {
|
|
701
|
+
process.stderr.write(`nectar enricher: durable write-back failed (non-fatal): ${err instanceof Error ? err.message : String(err)}\n`);
|
|
702
|
+
},
|
|
703
|
+
});
|
|
704
|
+
return { portkey, enricher, readContent };
|
|
705
|
+
}
|
|
706
|
+
async function runDaemon() {
|
|
707
|
+
const ctx = safeResolveContext();
|
|
708
|
+
const portkey = resolvePortkeyConfig();
|
|
709
|
+
const embeddingsConfig = resolveEmbeddingsConfig({});
|
|
710
|
+
// AC-018i.7: catch a wrong NECTAR_EMBEDDINGS_OUTPUT_DIMENSION at config
|
|
711
|
+
// resolution and warn loudly rather than silently nulling every hosted vector.
|
|
712
|
+
const dimCheck = validateEmbedDimension(embeddingsConfig);
|
|
713
|
+
if (!dimCheck.ok)
|
|
714
|
+
process.stderr.write(`nectar daemon: ${dimCheck.message ?? "invalid embedding output dimension"}\n`);
|
|
715
|
+
// AC-018i.8: wire the dim-rejection sink at the daemon-path resolveEmbedProvider
|
|
716
|
+
// call site (the API path wires it separately in daemon-api-wiring).
|
|
717
|
+
const embedProvider = resolveEmbedProvider(embeddingsConfig, {
|
|
718
|
+
onDimRejected: stderrDimRejectionSink,
|
|
719
|
+
});
|
|
720
|
+
const embedModel = activeEmbedModelId(embeddingsConfig);
|
|
721
|
+
let bootProjection;
|
|
722
|
+
try {
|
|
723
|
+
bootProjection = resolveBootProjection();
|
|
724
|
+
}
|
|
725
|
+
catch {
|
|
726
|
+
// fail-soft: a boot pre-warm is best-effort and never blocks the daemon start.
|
|
727
|
+
bootProjection = undefined;
|
|
728
|
+
}
|
|
729
|
+
// Durable brood + enrich run live only when Deep Lake creds resolve AND a
|
|
730
|
+
// Portkey describe transport is configured: an LLM-less daemon genuinely
|
|
731
|
+
// cannot brood or enrich, so it stays dormant (honest, and no false-fail
|
|
732
|
+
// marking of pending rows). This is the bridge that closes the Wave D dormancy.
|
|
733
|
+
const live = ctx !== undefined && portkey.enabled ? buildLiveDurableWiring(ctx, portkey) : undefined;
|
|
734
|
+
// PRD-018k / NEC-023: resolve the brood prerequisites so a dormant daemon
|
|
735
|
+
// surfaces WHY on /health and in the startup log (and, on a TTY, prints the
|
|
736
|
+
// guided first-run steps below). PRD-018k / NEC-041: resolve the per-repo
|
|
737
|
+
// tunables (`~/.honeycomb/nectar.json`, env-over-file) once at boot.
|
|
738
|
+
const broodPrereqs = broodPrereqsFromEnv({ credentialsPresent: ctx !== undefined, credentialsPath: credentialsPath() });
|
|
739
|
+
const tunables = resolveNectarTunables();
|
|
740
|
+
const options = {
|
|
741
|
+
broodPrereqs,
|
|
742
|
+
...(bootProjection !== undefined ? { bootProjection } : {}),
|
|
743
|
+
// PRD-018b: when Deep Lake creds resolve, start the update-on-change watch
|
|
744
|
+
// pipeline against the durable store (the watch leg needs no LLM - it appends
|
|
745
|
+
// pending version rows the enricher describes later). Absent creds -> the
|
|
746
|
+
// watch leg stays dormant and /health says so (AC-018b.7).
|
|
747
|
+
...(ctx !== undefined
|
|
748
|
+
? { tenancy: ctx.tenancy, projectRoot: ctx.projectRoot, registrationStore: ctx.store }
|
|
749
|
+
: {}),
|
|
750
|
+
...(live !== undefined && ctx !== undefined
|
|
751
|
+
? {
|
|
752
|
+
asyncBroodStore: ctx.store,
|
|
753
|
+
// AC-018i.1: stamp embed_model on auto-brood-embedded rows.
|
|
754
|
+
broodDepsAsync: { portkey: live.portkey, embedProvider, embedModelId: embedModel },
|
|
755
|
+
enricherStore: live.enricher,
|
|
756
|
+
enricherCycle: {
|
|
757
|
+
readContent: live.readContent,
|
|
758
|
+
portkey: live.portkey,
|
|
759
|
+
embedProvider,
|
|
760
|
+
// PRD-018k / NEC-041 AC-018k.6: source the redescribe threshold from
|
|
761
|
+
// ~/.honeycomb/nectar.json (env-over-file), falling back to the code
|
|
762
|
+
// default when neither the env var nor the file supplies one.
|
|
763
|
+
...(tunables.redescribeThreshold !== undefined
|
|
764
|
+
? { config: { redescribeThreshold: tunables.redescribeThreshold } }
|
|
765
|
+
: {}),
|
|
766
|
+
// AC-018i.1: stamp embed_model on enricher-embedded rows.
|
|
767
|
+
embedModel,
|
|
768
|
+
// AC-018g.6: re-seed the working set each cycle from the durable store.
|
|
769
|
+
refreshWorkingSet: () => live.enricher.refresh(ctx.tenancy),
|
|
770
|
+
// AC-018g.9: prior-content cache backs the cosmetic-change gate.
|
|
771
|
+
priorContentCache: createPriorContentCache(),
|
|
772
|
+
// AC-018g.11/.12: trigger #2 - a debounced projection write after a
|
|
773
|
+
// cycle that wrote descriptions, sourced from the enricher mirror.
|
|
774
|
+
projectionWriter: new ProjectionWriter({ projectRoot: ctx.projectRoot }),
|
|
775
|
+
projectionDoc: () => live.enricher.buildProjectionDoc(ctx.tenancy),
|
|
776
|
+
// Surface the underlying describe-batch error; without this the
|
|
777
|
+
// persistent-failure alert can trip with nothing in the logs to
|
|
778
|
+
// diagnose (2026-07-03 production soak stall).
|
|
779
|
+
onDescribeError: (err, paths) => {
|
|
780
|
+
process.stderr.write(`nectar enricher: describe batch failed (${paths.length} file(s), first: ${paths[0] ?? "?"}): ` +
|
|
781
|
+
`${err instanceof Error ? err.message : String(err)}\n`);
|
|
782
|
+
},
|
|
783
|
+
},
|
|
784
|
+
}
|
|
785
|
+
: {}),
|
|
786
|
+
};
|
|
787
|
+
const daemon = assembleDaemon(options);
|
|
788
|
+
// PRD-008: attach the /api/hive-graph handlers once, after assembleDaemon,
|
|
789
|
+
// mirroring mountGraphApi. When Deep Lake creds resolve the group is filled,
|
|
790
|
+
// and the LIVE build endpoint broods (when Portkey is configured); otherwise
|
|
791
|
+
// the group stays scaffolded + protected but unfilled (an honest 501 scaffold).
|
|
792
|
+
try {
|
|
793
|
+
if (ctx !== undefined) {
|
|
794
|
+
mountHiveGraphApi(daemon, buildHiveGraphApiOptions({
|
|
795
|
+
credentials: ctx.credentials,
|
|
796
|
+
tenancy: ctx.tenancy,
|
|
797
|
+
projectRoot: ctx.projectRoot,
|
|
798
|
+
store: ctx.store,
|
|
799
|
+
costSpentUsd: () => daemon.health.snapshot().cost.broodTotalUsd,
|
|
800
|
+
// PRD-018k / NEC-041 AC-018k.7: thread the loaded recall multiplier into
|
|
801
|
+
// the live search deps (the config surface reaches the recall path).
|
|
802
|
+
...(tunables.recallMultiplier !== undefined ? { recallMultiplier: tunables.recallMultiplier } : {}),
|
|
803
|
+
brood: { portkey, embedProvider, metrics: daemonMetricsProxy(daemon) },
|
|
804
|
+
// AC-018g.2: share the daemon's brood guard with the API /build handler.
|
|
805
|
+
broodGuard: daemon.broodGuard,
|
|
806
|
+
}));
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
catch {
|
|
810
|
+
// fail-soft: a wiring failure never blocks the daemon from serving /health.
|
|
811
|
+
}
|
|
812
|
+
daemon.installSignalHandlers();
|
|
813
|
+
const port = await daemon.start();
|
|
814
|
+
process.stdout.write(`nectar daemon listening on http://${daemon.config.host}:${port}/health\n`);
|
|
815
|
+
// PRD-018k / NEC-023 (AC-018k.5, option B): a guided first-run experience.
|
|
816
|
+
// When brooding is dormant AND this is an interactive terminal, print the
|
|
817
|
+
// exact steps to configure the prerequisites. Never block or prompt; in a
|
|
818
|
+
// non-interactive context (a service unit, CI) nothing is printed - the loud
|
|
819
|
+
// startup log line already carried the machine-readable dormancy reason.
|
|
820
|
+
if (!broodPrereqs.ready && process.stdout.isTTY === true) {
|
|
821
|
+
process.stdout.write(formatFirstRunGuidance(broodPrereqs));
|
|
822
|
+
}
|
|
823
|
+
// Hydrate the durable enricher's working set from Deep Lake in the BACKGROUND
|
|
824
|
+
// (never blocks readiness; fail-soft). The enricher loop sees an empty working
|
|
825
|
+
// set until this settles, then picks up the seeded pending rows on its next cycle.
|
|
826
|
+
if (live !== undefined && ctx !== undefined) {
|
|
827
|
+
void live.enricher.hydrate(ctx.tenancy).catch((err) => {
|
|
828
|
+
process.stderr.write(`nectar daemon: enricher hydrate failed (non-fatal): ${err instanceof Error ? err.message : String(err)}\n`);
|
|
829
|
+
});
|
|
830
|
+
}
|
|
831
|
+
// Usage telemetry: first_run (once per machine) + updated (on a version
|
|
832
|
+
// change) fire AFTER a successful bind. Fire-and-forget: recordDaemonStart
|
|
833
|
+
// never throws and the daemon does not wait on it.
|
|
834
|
+
void recordDaemonStart();
|
|
835
|
+
// Keep the process alive; shutdown is driven by SIGINT/SIGTERM.
|
|
836
|
+
}
|
|
837
|
+
async function main(argv) {
|
|
838
|
+
const command = argv[0];
|
|
839
|
+
if (command === undefined || command === "--help" || command === "-h" || command === "help") {
|
|
840
|
+
process.stdout.write(USAGE);
|
|
841
|
+
return 0;
|
|
842
|
+
}
|
|
843
|
+
if (command === "daemon") {
|
|
844
|
+
await runDaemon();
|
|
845
|
+
return 0;
|
|
846
|
+
}
|
|
847
|
+
if (command === "install") {
|
|
848
|
+
return runInstall();
|
|
849
|
+
}
|
|
850
|
+
if (command === "uninstall") {
|
|
851
|
+
return runUninstall();
|
|
852
|
+
}
|
|
853
|
+
if (command === "service-status") {
|
|
854
|
+
return runServiceStatus();
|
|
855
|
+
}
|
|
856
|
+
if (command === "rebuild-projection") {
|
|
857
|
+
return runRebuildProjection();
|
|
858
|
+
}
|
|
859
|
+
if (command === "brood") {
|
|
860
|
+
return runBroodCommand(argv.slice(1));
|
|
861
|
+
}
|
|
862
|
+
if (command === "prune") {
|
|
863
|
+
return runPruneCommand(argv.slice(1));
|
|
864
|
+
}
|
|
865
|
+
if (command === "review-matches") {
|
|
866
|
+
return runReviewMatchesCommand();
|
|
867
|
+
}
|
|
868
|
+
if (command === "search") {
|
|
869
|
+
return runSearchCommand(argv.slice(1));
|
|
870
|
+
}
|
|
871
|
+
// `project` currently exposes only its `--rebuild-projection` flag (PRD-011c);
|
|
872
|
+
// the broader project verb surface lands with a later PRD.
|
|
873
|
+
if (command === "project") {
|
|
874
|
+
const flags = argv.slice(1);
|
|
875
|
+
if (flags.includes("--rebuild-projection")) {
|
|
876
|
+
return runRebuildProjection();
|
|
877
|
+
}
|
|
878
|
+
process.stderr.write("nectar project: only 'project --rebuild-projection' is implemented (PRD-011c).\n" +
|
|
879
|
+
"The broader project verb surface lands with a later PRD.\n");
|
|
880
|
+
return 2;
|
|
881
|
+
}
|
|
882
|
+
process.stderr.write(`nectar: unknown command '${command}'\n\n${USAGE}`);
|
|
883
|
+
return 1;
|
|
884
|
+
}
|
|
885
|
+
export { main };
|
|
886
|
+
/** True when this module is the process entry point (`node dist/cli.js ...`), not an import. */
|
|
887
|
+
function isDirectRun() {
|
|
888
|
+
const entry = process.argv[1];
|
|
889
|
+
if (entry === undefined)
|
|
890
|
+
return false;
|
|
891
|
+
try {
|
|
892
|
+
return realpathSync(entry) === realpathSync(fileURLToPath(import.meta.url));
|
|
893
|
+
}
|
|
894
|
+
catch {
|
|
895
|
+
return false;
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
// Only drive the CLI when executed directly. Importing this module (e.g. from a
|
|
899
|
+
// test that exercises `classifyBroodInvocation`) must not run `main`.
|
|
900
|
+
if (isDirectRun()) {
|
|
901
|
+
main(process.argv.slice(2))
|
|
902
|
+
.then((code) => {
|
|
903
|
+
if (code !== 0)
|
|
904
|
+
process.exit(code);
|
|
905
|
+
// code 0 for `daemon` keeps the event loop alive via the open socket.
|
|
906
|
+
})
|
|
907
|
+
.catch((err) => {
|
|
908
|
+
process.stderr.write(`nectar: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
909
|
+
process.exit(1);
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
//# sourceMappingURL=cli.js.map
|