@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/lock.js
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single-instance PID/lock guard for the nectar daemon.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors honeycomb's `acquireSingleInstanceLock` / `releaseSingleInstanceLock`
|
|
5
|
+
* (honeycomb/src/daemon/runtime/assemble.ts:715-756) per PRD-002d, hardened by
|
|
6
|
+
* PRD-018a against the three lock defects the daemon-api review found:
|
|
7
|
+
* - a second start with a LIVE recorded identity throws before the socket bind,
|
|
8
|
+
* - a stale lock (dead owner, or an owner from a prior boot) is reclaimed so a
|
|
9
|
+
* crashed daemon never wedges the next start,
|
|
10
|
+
* - reclaim is ATOMIC: a concurrent reclaimer can never delete the winner's
|
|
11
|
+
* fresh lock (the unconditional `rmSync` at the old `lock.ts:84` is gone),
|
|
12
|
+
* - release is OWNERSHIP-CHECKED: a process only ever removes a lock it holds,
|
|
13
|
+
* - the lock records a stronger identity than a bare pid (pid + machine boot
|
|
14
|
+
* time + a random token), so a REUSED pid after a crash/reboot is recognized
|
|
15
|
+
* as stale instead of masquerading as a live daemon (NEC-020).
|
|
16
|
+
*
|
|
17
|
+
* The lock file is the guard and carries the JSON identity; the pid file stays a
|
|
18
|
+
* bare pid for operator convenience (`cat ~/.honeycomb/nectar.pid`) and doctor
|
|
19
|
+
* supervision (`doctor-registry.ts` `pidPath`).
|
|
20
|
+
*/
|
|
21
|
+
import { closeSync, existsSync, mkdirSync, openSync, readFileSync, rmSync, writeFileSync, writeSync, } from "node:fs";
|
|
22
|
+
import { uptime } from "node:os";
|
|
23
|
+
import { dirname } from "node:path";
|
|
24
|
+
import { randomUUID } from "node:crypto";
|
|
25
|
+
import { DaemonAlreadyRunningError } from "./errors.js";
|
|
26
|
+
/** How many exclusive-create attempts an acquire makes before conceding to a live holder. */
|
|
27
|
+
const MAX_ACQUIRE_ATTEMPTS = 5;
|
|
28
|
+
/**
|
|
29
|
+
* Tolerance (seconds) when comparing a recorded boot time against the current
|
|
30
|
+
* one. `Date.now()` and `os.uptime()` are sampled a few milliseconds apart, so a
|
|
31
|
+
* live lock written this boot can read back a second off; a real reboot moves
|
|
32
|
+
* the boot time by minutes or more, so a small window cleanly separates the two.
|
|
33
|
+
*/
|
|
34
|
+
const BOOT_TOLERANCE_SEC = 5;
|
|
35
|
+
/**
|
|
36
|
+
* Probe whether a PID is alive via signal 0.
|
|
37
|
+
* - `ESRCH` -> no such process (stale),
|
|
38
|
+
* - `EPERM` -> alive but owned by another user (treated as alive),
|
|
39
|
+
* - success -> alive.
|
|
40
|
+
* Mirrors honeycomb's `isPidAlive` (assemble.ts:692-705).
|
|
41
|
+
*/
|
|
42
|
+
export function isPidAlive(pid) {
|
|
43
|
+
if (!Number.isInteger(pid) || pid <= 0)
|
|
44
|
+
return false;
|
|
45
|
+
try {
|
|
46
|
+
process.kill(pid, 0);
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
const code = err.code;
|
|
51
|
+
if (code === "EPERM")
|
|
52
|
+
return true; // alive, different user
|
|
53
|
+
return false; // ESRCH or anything else -> not alive
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** Read the PID from a lock/pid file; absent/unreadable/garbage returns null. */
|
|
57
|
+
export function readPidFile(path) {
|
|
58
|
+
try {
|
|
59
|
+
const raw = readFileSync(path, "utf8").trim();
|
|
60
|
+
if (raw === "")
|
|
61
|
+
return null;
|
|
62
|
+
const pid = Number.parseInt(raw, 10);
|
|
63
|
+
return Number.isInteger(pid) && pid > 0 ? pid : null;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/** The current machine boot time as whole epoch seconds (stable across quick reads). */
|
|
70
|
+
function currentBoot() {
|
|
71
|
+
return Math.floor(Date.now() / 1000 - uptime());
|
|
72
|
+
}
|
|
73
|
+
/** Two boot timestamps refer to the same boot when they are within the sampling tolerance. */
|
|
74
|
+
function sameBoot(a, b) {
|
|
75
|
+
return Math.abs(a - b) <= BOOT_TOLERANCE_SEC;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Read and parse the identity a lock file records. Accepts the current JSON
|
|
79
|
+
* shape and, for backward compatibility, a legacy bare-pid file (interpreted as
|
|
80
|
+
* a pid-only identity). Absent / unreadable / unparseable returns null.
|
|
81
|
+
*/
|
|
82
|
+
export function readLockIdentity(path) {
|
|
83
|
+
let raw;
|
|
84
|
+
try {
|
|
85
|
+
raw = readFileSync(path, "utf8").trim();
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
if (raw === "")
|
|
91
|
+
return null;
|
|
92
|
+
// Legacy bare-pid lock (honeycomb-style): pid is the only identity available.
|
|
93
|
+
if (/^\d+$/.test(raw)) {
|
|
94
|
+
const pid = Number.parseInt(raw, 10);
|
|
95
|
+
return Number.isInteger(pid) && pid > 0 ? { pid } : null;
|
|
96
|
+
}
|
|
97
|
+
let parsed;
|
|
98
|
+
try {
|
|
99
|
+
parsed = JSON.parse(raw);
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
if (parsed === null || typeof parsed !== "object")
|
|
105
|
+
return null;
|
|
106
|
+
const rec = parsed;
|
|
107
|
+
const pid = typeof rec["pid"] === "number" ? rec["pid"] : Number.NaN;
|
|
108
|
+
if (!Number.isInteger(pid) || pid <= 0)
|
|
109
|
+
return null;
|
|
110
|
+
const boot = typeof rec["boot"] === "number" ? rec["boot"] : undefined;
|
|
111
|
+
const token = typeof rec["token"] === "string" ? rec["token"] : undefined;
|
|
112
|
+
return {
|
|
113
|
+
pid,
|
|
114
|
+
...(boot !== undefined ? { boot } : {}),
|
|
115
|
+
...(token !== undefined ? { token } : {}),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* True when the recorded identity plausibly belongs to a LIVE nectar daemon: its
|
|
120
|
+
* pid is alive AND (when the lock records a boot time) it was written this boot.
|
|
121
|
+
* A live-but-foreign pid from a prior boot (PID reuse) fails the boot check and
|
|
122
|
+
* is therefore reclaimable rather than a permanent wedge (NEC-020).
|
|
123
|
+
*/
|
|
124
|
+
function isLockOwnerLive(id) {
|
|
125
|
+
if (!isPidAlive(id.pid))
|
|
126
|
+
return false;
|
|
127
|
+
if (id.boot === undefined)
|
|
128
|
+
return true; // legacy pid-only lock: pid liveness is all we have
|
|
129
|
+
return sameBoot(id.boot, currentBoot());
|
|
130
|
+
}
|
|
131
|
+
/** Two identities are the same lock when their tokens match (or, legacy, their pid+boot). */
|
|
132
|
+
function sameIdentity(a, b) {
|
|
133
|
+
if (a.token !== undefined && b.token !== undefined)
|
|
134
|
+
return a.token === b.token;
|
|
135
|
+
return a.pid === b.pid && a.boot === b.boot;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Reclaim a stale lock atomically. Re-reads the lock immediately before removing
|
|
139
|
+
* it and removes it ONLY if it still holds the same stale content we decided to
|
|
140
|
+
* reclaim. If a concurrent reclaimer already replaced it (content changed, or the
|
|
141
|
+
* file is gone), this is a no-op: the caller's next exclusive-create attempt
|
|
142
|
+
* re-evaluates the fresh content and correctly sees a live owner. This is what
|
|
143
|
+
* makes two racing reclaims yield exactly one winner without the loser deleting
|
|
144
|
+
* the winner's lock (NEC-020 / the old unconditional `rmSync`).
|
|
145
|
+
*/
|
|
146
|
+
function reclaimStaleLock(lockFilePath, expected) {
|
|
147
|
+
const current = readLockIdentity(lockFilePath);
|
|
148
|
+
if (current === null) {
|
|
149
|
+
// `readLockIdentity` returns null for two different situations: the file
|
|
150
|
+
// is now gone (someone else already reclaimed it; the retry loop
|
|
151
|
+
// re-creates it), OR the file is PRESENT but its content is empty/garbage
|
|
152
|
+
// (a corrupt lock). CodeRabbit PR-18 finding #2: the pre-fix code treated
|
|
153
|
+
// both as "already gone" and never removed a present-but-corrupt lock, so
|
|
154
|
+
// every later acquire hit EEXIST forever and the daemon could never start
|
|
155
|
+
// without a manual `rm`. A corrupt lock records no owner at all, so it is
|
|
156
|
+
// unconditionally stale; reclaim it the same way. Re-check immediately
|
|
157
|
+
// before removing (the same re-read-then-conditionally-remove discipline
|
|
158
|
+
// the live-lock branch below uses) so a concurrent racer that has already
|
|
159
|
+
// replaced the corrupt file with a fresh, parseable, live lock is never
|
|
160
|
+
// deleted out from under its new owner (NEC-020 - the atomic-reclaim
|
|
161
|
+
// guarantee this function exists to preserve).
|
|
162
|
+
if (existsSync(lockFilePath) && readLockIdentity(lockFilePath) === null) {
|
|
163
|
+
rmSync(lockFilePath, { force: true });
|
|
164
|
+
}
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (expected !== null && !sameIdentity(current, expected))
|
|
168
|
+
return; // changed under us
|
|
169
|
+
if (isLockOwnerLive(current))
|
|
170
|
+
return; // became live under us; loop re-evaluates
|
|
171
|
+
rmSync(lockFilePath, { force: true });
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Acquire the single-instance lock. Called BEFORE the socket bind (PRD-002a).
|
|
175
|
+
* Throws `DaemonAlreadyRunningError` if a LIVE daemon already holds the lock;
|
|
176
|
+
* atomically reclaims a stale lock otherwise. Returns the identity it stamped so
|
|
177
|
+
* the caller can pass it back to {@link releaseSingleInstanceLock} for an
|
|
178
|
+
* ownership-checked release (PRD-018a NEC-002).
|
|
179
|
+
*/
|
|
180
|
+
export function acquireSingleInstanceLock(paths, options = {}) {
|
|
181
|
+
mkdirSync(dirname(paths.lockFilePath), { recursive: true });
|
|
182
|
+
const identity = {
|
|
183
|
+
pid: options.pid ?? process.pid,
|
|
184
|
+
boot: options.boot ?? currentBoot(),
|
|
185
|
+
token: options.token ?? randomUUID(),
|
|
186
|
+
};
|
|
187
|
+
const serialized = JSON.stringify(identity);
|
|
188
|
+
const writeLockBody = options.writeLockBody ?? writeSync;
|
|
189
|
+
for (let attempt = 0; attempt < MAX_ACQUIRE_ATTEMPTS; attempt++) {
|
|
190
|
+
let fd;
|
|
191
|
+
try {
|
|
192
|
+
// Exclusive create is the atomic winner-picker: only ONE process can create
|
|
193
|
+
// the lock with "wx"; every other concurrent creator gets EEXIST.
|
|
194
|
+
fd = openSync(paths.lockFilePath, "wx");
|
|
195
|
+
}
|
|
196
|
+
catch (err) {
|
|
197
|
+
if (err.code !== "EEXIST")
|
|
198
|
+
throw err;
|
|
199
|
+
const existing = readLockIdentity(paths.lockFilePath);
|
|
200
|
+
if (existing !== null && isLockOwnerLive(existing)) {
|
|
201
|
+
throw new DaemonAlreadyRunningError(existing.pid, paths.lockFilePath);
|
|
202
|
+
}
|
|
203
|
+
// Stale (dead owner / prior boot / unreadable): reclaim and retry.
|
|
204
|
+
reclaimStaleLock(paths.lockFilePath, existing);
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
try {
|
|
208
|
+
writeLockBody(fd, serialized);
|
|
209
|
+
}
|
|
210
|
+
catch (err) {
|
|
211
|
+
closeSync(fd);
|
|
212
|
+
// Roll back: the lock file was just created by us (the "wx" open above
|
|
213
|
+
// succeeded), so a write failure must not leave a half-written/corrupt
|
|
214
|
+
// lock body behind wedging every future acquire (CodeRabbit PR-18
|
|
215
|
+
// finding #2), mirroring the pid-file write path's rollback below.
|
|
216
|
+
rmSync(paths.lockFilePath, { force: true });
|
|
217
|
+
throw err;
|
|
218
|
+
}
|
|
219
|
+
closeSync(fd);
|
|
220
|
+
// Verify-after-create: confirm the lock still records OUR token. A concurrent
|
|
221
|
+
// reclaimer cannot have replaced it (our "wx" create means the file existed
|
|
222
|
+
// for everyone else, who then read our live identity and threw), so this is
|
|
223
|
+
// belt-and-suspenders; on a mismatch we retry rather than proceed unsafely.
|
|
224
|
+
const readback = readLockIdentity(paths.lockFilePath);
|
|
225
|
+
if (readback === null || readback.token !== identity.token)
|
|
226
|
+
continue;
|
|
227
|
+
// Write the operator-facing pid file (bare pid). On failure, roll the lock
|
|
228
|
+
// back so a partial acquisition never leaves a stale lock wedging the next
|
|
229
|
+
// start; the lock was just created by us, so removing it is safe.
|
|
230
|
+
try {
|
|
231
|
+
writeFileSync(paths.pidFilePath, String(identity.pid), "utf8");
|
|
232
|
+
}
|
|
233
|
+
catch (err) {
|
|
234
|
+
rmSync(paths.lockFilePath, { force: true });
|
|
235
|
+
throw err;
|
|
236
|
+
}
|
|
237
|
+
return identity;
|
|
238
|
+
}
|
|
239
|
+
// Every attempt lost to a live lock created between our checks.
|
|
240
|
+
const raced = readLockIdentity(paths.lockFilePath);
|
|
241
|
+
throw new DaemonAlreadyRunningError(raced?.pid ?? -1, paths.lockFilePath);
|
|
242
|
+
}
|
|
243
|
+
/** Does the recorded lock belong to `identity` (or, absent one, to this live process)? */
|
|
244
|
+
function lockOwnedBy(recorded, identity) {
|
|
245
|
+
if (identity !== undefined) {
|
|
246
|
+
if (identity.token !== undefined && recorded.token !== undefined) {
|
|
247
|
+
return recorded.token === identity.token;
|
|
248
|
+
}
|
|
249
|
+
return recorded.pid === identity.pid && bootMatches(recorded.boot, identity.boot);
|
|
250
|
+
}
|
|
251
|
+
// No identity supplied: own it iff this live process wrote it (pid + this boot).
|
|
252
|
+
return recorded.pid === process.pid && (recorded.boot === undefined || sameBoot(recorded.boot, currentBoot()));
|
|
253
|
+
}
|
|
254
|
+
function bootMatches(a, b) {
|
|
255
|
+
if (a === undefined || b === undefined)
|
|
256
|
+
return a === b;
|
|
257
|
+
return sameBoot(a, b);
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Release the lock: remove both files, but ONLY when this process owns the lock
|
|
261
|
+
* (PRD-018a NEC-002). Called by a process that does not own the lock (a failed
|
|
262
|
+
* second start), it is a no-op, so a failed start can never delete the live
|
|
263
|
+
* daemon's lock and pid. Pass the identity returned by
|
|
264
|
+
* {@link acquireSingleInstanceLock} for a precise token-based check; omit it to
|
|
265
|
+
* fall back to a pid+boot check against this live process. Never throws (a
|
|
266
|
+
* missing lock on shutdown is fine; the goal already holds).
|
|
267
|
+
*/
|
|
268
|
+
export function releaseSingleInstanceLock(paths, identity) {
|
|
269
|
+
const recorded = readLockIdentity(paths.lockFilePath);
|
|
270
|
+
// Own the lock, or it is already gone: safe to clear both files. Otherwise the
|
|
271
|
+
// lock belongs to a live, different owner and we touch nothing.
|
|
272
|
+
if (recorded === null || lockOwnedBy(recorded, identity)) {
|
|
273
|
+
rmSync(paths.lockFilePath, { force: true });
|
|
274
|
+
rmSync(paths.pidFilePath, { force: true });
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
/** True if a live daemon currently holds this lock (used by health/status). */
|
|
278
|
+
export function isLockHeldByLiveDaemon(lockFilePath) {
|
|
279
|
+
const id = readLockIdentity(lockFilePath);
|
|
280
|
+
return id !== null && isLockOwnerLive(id);
|
|
281
|
+
}
|
|
282
|
+
//# sourceMappingURL=lock.js.map
|
package/dist/lock.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lock.js","sourceRoot":"","sources":["../src/lock.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adaptive poll loop for the hiveantennae worker.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors honeycomb's poll-loop (honeycomb/src/daemon/runtime/services/poll-loop.ts)
|
|
5
|
+
* per PRD-002b:
|
|
6
|
+
* - tick -> run one pass,
|
|
7
|
+
* - skip a tick if the previous run is still in flight (overlap guard),
|
|
8
|
+
* - reschedule via a backoff state machine: reset to the floor when a tick did
|
|
9
|
+
* work, step toward the ceiling when it was idle.
|
|
10
|
+
* The loop owns no wall clock and no I/O: the timer seam is injected so it is
|
|
11
|
+
* deterministic under a manual clock in tests.
|
|
12
|
+
*/
|
|
13
|
+
/** A single pass. Returns true if it did work (reset backoff), false if idle (step toward ceiling). */
|
|
14
|
+
export type Tick = () => Promise<boolean> | boolean;
|
|
15
|
+
export interface Timer {
|
|
16
|
+
set(fn: () => void, ms: number): unknown;
|
|
17
|
+
clear(handle: unknown): void;
|
|
18
|
+
}
|
|
19
|
+
/** Default timer backed by Node's global timers. */
|
|
20
|
+
export declare const realTimer: Timer;
|
|
21
|
+
export interface PollLoopOptions {
|
|
22
|
+
readonly tick: Tick;
|
|
23
|
+
/** Backoff floor (fast cadence when there is work). */
|
|
24
|
+
readonly floorMs: number;
|
|
25
|
+
/** Backoff ceiling (slow cadence when idle). Defaults to floorMs (no backoff). */
|
|
26
|
+
readonly ceilingMs?: number;
|
|
27
|
+
/** Multiplier applied to the delay on each idle tick. Defaults to 2. */
|
|
28
|
+
readonly backoffFactor?: number;
|
|
29
|
+
readonly timer?: Timer;
|
|
30
|
+
readonly onError?: (err: unknown) => void;
|
|
31
|
+
}
|
|
32
|
+
export declare class PollLoop {
|
|
33
|
+
private readonly tick;
|
|
34
|
+
private readonly floorMs;
|
|
35
|
+
private readonly ceilingMs;
|
|
36
|
+
private readonly backoffFactor;
|
|
37
|
+
private readonly timer;
|
|
38
|
+
private readonly onError;
|
|
39
|
+
private running;
|
|
40
|
+
private inFlight;
|
|
41
|
+
/** The currently-running tick, or null when idle. Exposed via {@link whenIdle} for bounded drain on shutdown. */
|
|
42
|
+
private inFlightPromise;
|
|
43
|
+
private handle;
|
|
44
|
+
private currentDelayMs;
|
|
45
|
+
/** Bumped on every start() and stop(); a pump/schedule from an older generation is ignored. */
|
|
46
|
+
private generation;
|
|
47
|
+
constructor(opts: PollLoopOptions);
|
|
48
|
+
get currentDelay(): number;
|
|
49
|
+
get isRunning(): boolean;
|
|
50
|
+
/** Arm the loop. Idempotent: a second start while running is a no-op. */
|
|
51
|
+
start(): void;
|
|
52
|
+
/** Disarm the loop. Idempotent. An in-flight tick is allowed to finish but cannot reschedule. */
|
|
53
|
+
stop(): void;
|
|
54
|
+
/**
|
|
55
|
+
* Run exactly one lease pass. Skips (returns false) if a previous run is still
|
|
56
|
+
* in flight, so a slow tick never overlaps itself. A skipped tick does NOT
|
|
57
|
+
* feed the backoff state machine. Errors are routed to onError and treated as
|
|
58
|
+
* idle for backoff purposes.
|
|
59
|
+
*/
|
|
60
|
+
runOnce(): Promise<boolean>;
|
|
61
|
+
/**
|
|
62
|
+
* Resolve once any in-flight tick has settled. `shutdown()` awaits this (under
|
|
63
|
+
* a bounded timeout) so a tick is drained rather than killed mid-flight
|
|
64
|
+
* (PRD-018a NEC-033). The tracked promise never rejects (errors are routed to
|
|
65
|
+
* `onError` inside `runOnce`), so awaiting it is safe.
|
|
66
|
+
*/
|
|
67
|
+
whenIdle(): Promise<void>;
|
|
68
|
+
private schedule;
|
|
69
|
+
private pump;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=poll-loop.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poll-loop.d.ts","sourceRoot":"","sources":["../src/poll-loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,uGAAuG;AACvG,MAAM,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;AAEpD,MAAM,WAAW,KAAK;IACpB,GAAG,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IACzC,KAAK,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;CAC9B;AAED,oDAAoD;AACpD,eAAO,MAAM,SAAS,EAAE,KAGvB,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,uDAAuD;IACvD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,kFAAkF;IAClF,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,wEAAwE;IACxE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;CAC3C;AAED,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAO;IAC5B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IAEjD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,iHAAiH;IACjH,OAAO,CAAC,eAAe,CAAiC;IACxD,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,cAAc,CAAS;IAC/B,+FAA+F;IAC/F,OAAO,CAAC,UAAU,CAAK;gBAEX,IAAI,EAAE,eAAe;IAUjC,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,yEAAyE;IACzE,KAAK,IAAI,IAAI;IAQb,iGAAiG;IACjG,IAAI,IAAI,IAAI;IASZ;;;;;OAKG;IACG,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;IAkBjC;;;;;OAKG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAK/B,OAAO,CAAC,QAAQ;YAOF,IAAI;CAoBnB"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adaptive poll loop for the hiveantennae worker.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors honeycomb's poll-loop (honeycomb/src/daemon/runtime/services/poll-loop.ts)
|
|
5
|
+
* per PRD-002b:
|
|
6
|
+
* - tick -> run one pass,
|
|
7
|
+
* - skip a tick if the previous run is still in flight (overlap guard),
|
|
8
|
+
* - reschedule via a backoff state machine: reset to the floor when a tick did
|
|
9
|
+
* work, step toward the ceiling when it was idle.
|
|
10
|
+
* The loop owns no wall clock and no I/O: the timer seam is injected so it is
|
|
11
|
+
* deterministic under a manual clock in tests.
|
|
12
|
+
*/
|
|
13
|
+
/** Default timer backed by Node's global timers. */
|
|
14
|
+
export const realTimer = {
|
|
15
|
+
set: (fn, ms) => setTimeout(fn, ms),
|
|
16
|
+
clear: (handle) => clearTimeout(handle),
|
|
17
|
+
};
|
|
18
|
+
export class PollLoop {
|
|
19
|
+
tick;
|
|
20
|
+
floorMs;
|
|
21
|
+
ceilingMs;
|
|
22
|
+
backoffFactor;
|
|
23
|
+
timer;
|
|
24
|
+
onError;
|
|
25
|
+
running = false;
|
|
26
|
+
inFlight = false;
|
|
27
|
+
/** The currently-running tick, or null when idle. Exposed via {@link whenIdle} for bounded drain on shutdown. */
|
|
28
|
+
inFlightPromise = null;
|
|
29
|
+
handle = null;
|
|
30
|
+
currentDelayMs;
|
|
31
|
+
/** Bumped on every start() and stop(); a pump/schedule from an older generation is ignored. */
|
|
32
|
+
generation = 0;
|
|
33
|
+
constructor(opts) {
|
|
34
|
+
this.tick = opts.tick;
|
|
35
|
+
this.floorMs = Math.max(1, opts.floorMs);
|
|
36
|
+
this.ceilingMs = Math.max(this.floorMs, opts.ceilingMs ?? opts.floorMs);
|
|
37
|
+
this.backoffFactor = Math.max(1, opts.backoffFactor ?? 2);
|
|
38
|
+
this.timer = opts.timer ?? realTimer;
|
|
39
|
+
this.onError = opts.onError ?? (() => { });
|
|
40
|
+
this.currentDelayMs = this.floorMs;
|
|
41
|
+
}
|
|
42
|
+
get currentDelay() {
|
|
43
|
+
return this.currentDelayMs;
|
|
44
|
+
}
|
|
45
|
+
get isRunning() {
|
|
46
|
+
return this.running;
|
|
47
|
+
}
|
|
48
|
+
/** Arm the loop. Idempotent: a second start while running is a no-op. */
|
|
49
|
+
start() {
|
|
50
|
+
if (this.running)
|
|
51
|
+
return;
|
|
52
|
+
this.running = true;
|
|
53
|
+
this.generation += 1;
|
|
54
|
+
this.currentDelayMs = this.floorMs;
|
|
55
|
+
this.schedule(0, this.generation);
|
|
56
|
+
}
|
|
57
|
+
/** Disarm the loop. Idempotent. An in-flight tick is allowed to finish but cannot reschedule. */
|
|
58
|
+
stop() {
|
|
59
|
+
this.running = false;
|
|
60
|
+
this.generation += 1;
|
|
61
|
+
if (this.handle !== null) {
|
|
62
|
+
this.timer.clear(this.handle);
|
|
63
|
+
this.handle = null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Run exactly one lease pass. Skips (returns false) if a previous run is still
|
|
68
|
+
* in flight, so a slow tick never overlaps itself. A skipped tick does NOT
|
|
69
|
+
* feed the backoff state machine. Errors are routed to onError and treated as
|
|
70
|
+
* idle for backoff purposes.
|
|
71
|
+
*/
|
|
72
|
+
async runOnce() {
|
|
73
|
+
if (this.inFlight)
|
|
74
|
+
return false;
|
|
75
|
+
this.inFlight = true;
|
|
76
|
+
const run = (async () => {
|
|
77
|
+
try {
|
|
78
|
+
return await this.tick();
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
this.onError(err);
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
this.inFlight = false;
|
|
86
|
+
this.inFlightPromise = null;
|
|
87
|
+
}
|
|
88
|
+
})();
|
|
89
|
+
this.inFlightPromise = run;
|
|
90
|
+
return run;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Resolve once any in-flight tick has settled. `shutdown()` awaits this (under
|
|
94
|
+
* a bounded timeout) so a tick is drained rather than killed mid-flight
|
|
95
|
+
* (PRD-018a NEC-033). The tracked promise never rejects (errors are routed to
|
|
96
|
+
* `onError` inside `runOnce`), so awaiting it is safe.
|
|
97
|
+
*/
|
|
98
|
+
async whenIdle() {
|
|
99
|
+
const inflight = this.inFlightPromise;
|
|
100
|
+
if (inflight !== null)
|
|
101
|
+
await inflight;
|
|
102
|
+
}
|
|
103
|
+
schedule(delayMs, gen) {
|
|
104
|
+
if (!this.running || gen !== this.generation)
|
|
105
|
+
return;
|
|
106
|
+
this.handle = this.timer.set(() => {
|
|
107
|
+
void this.pump(gen);
|
|
108
|
+
}, delayMs);
|
|
109
|
+
}
|
|
110
|
+
async pump(gen) {
|
|
111
|
+
if (!this.running || gen !== this.generation)
|
|
112
|
+
return;
|
|
113
|
+
const didWork = await this.runOnce();
|
|
114
|
+
// A stop()/start() may have happened while the tick was in flight; if so this
|
|
115
|
+
// is a stale generation and must not reschedule (that would leave two active
|
|
116
|
+
// schedules on one loop).
|
|
117
|
+
if (!this.running || gen !== this.generation)
|
|
118
|
+
return;
|
|
119
|
+
// Backoff: schedule the NEXT tick at the current delay, then advance the
|
|
120
|
+
// delay for the tick after that. A tick that did work resets to the floor;
|
|
121
|
+
// an idle tick steps toward the ceiling. This makes the first idle tick fire
|
|
122
|
+
// at the floor, and only consecutive idles grow the interval.
|
|
123
|
+
const nextDelay = didWork ? this.floorMs : this.currentDelayMs;
|
|
124
|
+
this.currentDelayMs = didWork
|
|
125
|
+
? this.floorMs
|
|
126
|
+
: Math.min(this.ceilingMs, Math.max(this.floorMs, Math.round(this.currentDelayMs * this.backoffFactor)));
|
|
127
|
+
this.schedule(nextDelay, gen);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=poll-loop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poll-loop.js","sourceRoot":"","sources":["../src/poll-loop.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portkey + activeModel resolution for nectar (PRD-010).
|
|
3
|
+
*
|
|
4
|
+
* Disabled or keyless Portkey is an explicit, testable `{ enabled: false }` state;
|
|
5
|
+
* this module never throws at import time. Env names follow the `NECTAR_*`
|
|
6
|
+
* convention used by `src/config.ts`.
|
|
7
|
+
*/
|
|
8
|
+
/** SIGNED OFF 2026-07-02 (decision #29): default description model id. */
|
|
9
|
+
export declare const DEFAULT_ACTIVE_MODEL: "gemini-2.5-flash";
|
|
10
|
+
/** Portkey is off or not configured enough to call the gateway. */
|
|
11
|
+
export interface PortkeyDisabled {
|
|
12
|
+
readonly enabled: false;
|
|
13
|
+
readonly reason: "disabled" | "missing_api_key" | "missing_config_id";
|
|
14
|
+
}
|
|
15
|
+
/** Portkey is enabled with the credentials needed for chat completions. */
|
|
16
|
+
export interface PortkeyEnabled {
|
|
17
|
+
readonly enabled: true;
|
|
18
|
+
readonly apiKey: string;
|
|
19
|
+
readonly configId: string;
|
|
20
|
+
readonly activeModel: string;
|
|
21
|
+
}
|
|
22
|
+
export type PortkeyRuntimeConfig = PortkeyDisabled | PortkeyEnabled;
|
|
23
|
+
export interface PortkeyConfigOverrides {
|
|
24
|
+
readonly enabled?: boolean;
|
|
25
|
+
readonly apiKey?: string;
|
|
26
|
+
readonly configId?: string;
|
|
27
|
+
readonly activeModel?: string;
|
|
28
|
+
/** Injectable env bag for tests; defaults to `process.env`. */
|
|
29
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Resolve Portkey enablement, credentials, and the active description model.
|
|
33
|
+
*
|
|
34
|
+
* Env layer (each flagged [DEFAULT - confirm before implementation] in PRD-010):
|
|
35
|
+
* - `NECTAR_PORTKEY_ENABLED` explicit on/off gate (absent => off)
|
|
36
|
+
* - `NECTAR_PORTKEY_API_KEY` Portkey API key (required when enabled)
|
|
37
|
+
* - `NECTAR_PORTKEY_CONFIG` `portkey.config` / virtual-key id (required when enabled)
|
|
38
|
+
* - `NECTAR_ACTIVE_MODEL` description model id (default `gemini-2.5-flash`, decision #29)
|
|
39
|
+
*/
|
|
40
|
+
export declare function resolvePortkeyConfig(overrides?: PortkeyConfigOverrides): PortkeyRuntimeConfig;
|
|
41
|
+
/**
|
|
42
|
+
* Keys exposed on {@link PortkeyRuntimeConfig} for AC-5 structural checks: no cache or
|
|
43
|
+
* guardrail toggle exists on this surface (DECISION #6).
|
|
44
|
+
*/
|
|
45
|
+
export declare const PORTKEY_CONFIG_SURFACE_KEYS: readonly ["enabled", "apiKey", "configId", "activeModel", "reason"];
|
|
46
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/portkey/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,0EAA0E;AAC1E,eAAO,MAAM,oBAAoB,EAAG,kBAA2B,CAAC;AAEhE,mEAAmE;AACnE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,iBAAiB,GAAG,mBAAmB,CAAC;CACvE;AAED,2EAA2E;AAC3E,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,MAAM,oBAAoB,GAAG,eAAe,GAAG,cAAc,CAAC;AAEpE,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,+DAA+D;IAC/D,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CAClC;AAiBD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,GAAE,sBAA2B,GAAG,oBAAoB,CA4BjG;AAED;;;GAGG;AACH,eAAO,MAAM,2BAA2B,qEAM9B,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portkey + activeModel resolution for nectar (PRD-010).
|
|
3
|
+
*
|
|
4
|
+
* Disabled or keyless Portkey is an explicit, testable `{ enabled: false }` state;
|
|
5
|
+
* this module never throws at import time. Env names follow the `NECTAR_*`
|
|
6
|
+
* convention used by `src/config.ts`.
|
|
7
|
+
*/
|
|
8
|
+
/** SIGNED OFF 2026-07-02 (decision #29): default description model id. */
|
|
9
|
+
export const DEFAULT_ACTIVE_MODEL = "gemini-2.5-flash";
|
|
10
|
+
function envStr(env, name) {
|
|
11
|
+
const raw = env[name];
|
|
12
|
+
if (raw === undefined || raw.trim() === "")
|
|
13
|
+
return undefined;
|
|
14
|
+
return raw;
|
|
15
|
+
}
|
|
16
|
+
function envBool(env, name) {
|
|
17
|
+
const raw = envStr(env, name);
|
|
18
|
+
if (raw === undefined)
|
|
19
|
+
return undefined;
|
|
20
|
+
const normalized = raw.trim().toLowerCase();
|
|
21
|
+
if (normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on")
|
|
22
|
+
return true;
|
|
23
|
+
if (normalized === "0" || normalized === "false" || normalized === "no" || normalized === "off")
|
|
24
|
+
return false;
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Resolve Portkey enablement, credentials, and the active description model.
|
|
29
|
+
*
|
|
30
|
+
* Env layer (each flagged [DEFAULT - confirm before implementation] in PRD-010):
|
|
31
|
+
* - `NECTAR_PORTKEY_ENABLED` explicit on/off gate (absent => off)
|
|
32
|
+
* - `NECTAR_PORTKEY_API_KEY` Portkey API key (required when enabled)
|
|
33
|
+
* - `NECTAR_PORTKEY_CONFIG` `portkey.config` / virtual-key id (required when enabled)
|
|
34
|
+
* - `NECTAR_ACTIVE_MODEL` description model id (default `gemini-2.5-flash`, decision #29)
|
|
35
|
+
*/
|
|
36
|
+
export function resolvePortkeyConfig(overrides = {}) {
|
|
37
|
+
const env = overrides.env ?? process.env;
|
|
38
|
+
const enabled = overrides.enabled ??
|
|
39
|
+
envBool(env, "NECTAR_PORTKEY_ENABLED") ??
|
|
40
|
+
false;
|
|
41
|
+
if (!enabled) {
|
|
42
|
+
return { enabled: false, reason: "disabled" };
|
|
43
|
+
}
|
|
44
|
+
const apiKey = overrides.apiKey ?? envStr(env, "NECTAR_PORTKEY_API_KEY");
|
|
45
|
+
if (apiKey === undefined) {
|
|
46
|
+
return { enabled: false, reason: "missing_api_key" };
|
|
47
|
+
}
|
|
48
|
+
const configId = overrides.configId ?? envStr(env, "NECTAR_PORTKEY_CONFIG");
|
|
49
|
+
if (configId === undefined) {
|
|
50
|
+
return { enabled: false, reason: "missing_config_id" };
|
|
51
|
+
}
|
|
52
|
+
const activeModel = overrides.activeModel ??
|
|
53
|
+
envStr(env, "NECTAR_ACTIVE_MODEL") ??
|
|
54
|
+
DEFAULT_ACTIVE_MODEL;
|
|
55
|
+
return { enabled: true, apiKey, configId, activeModel };
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Keys exposed on {@link PortkeyRuntimeConfig} for AC-5 structural checks: no cache or
|
|
59
|
+
* guardrail toggle exists on this surface (DECISION #6).
|
|
60
|
+
*/
|
|
61
|
+
export const PORTKEY_CONFIG_SURFACE_KEYS = [
|
|
62
|
+
"enabled",
|
|
63
|
+
"apiKey",
|
|
64
|
+
"configId",
|
|
65
|
+
"activeModel",
|
|
66
|
+
"reason",
|
|
67
|
+
];
|
|
68
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/portkey/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,0EAA0E;AAC1E,MAAM,CAAC,MAAM,oBAAoB,GAAG,kBAA2B,CAAC;AA2BhE,SAAS,MAAM,CAAC,GAAsB,EAAE,IAAY;IAClD,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;IACtB,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,SAAS,CAAC;IAC7D,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,OAAO,CAAC,GAAsB,EAAE,IAAY;IACnD,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC9B,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACxC,MAAM,UAAU,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5C,IAAI,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,MAAM,IAAI,UAAU,KAAK,KAAK,IAAI,UAAU,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC5G,IAAI,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,OAAO,IAAI,UAAU,KAAK,IAAI,IAAI,UAAU,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC;IAC9G,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,YAAoC,EAAE;IACzE,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IAEzC,MAAM,OAAO,GACX,SAAS,CAAC,OAAO;QACjB,OAAO,CAAC,GAAG,EAAE,wBAAwB,CAAC;QACtC,KAAK,CAAC;IAER,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAChD,CAAC;IAED,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,IAAI,MAAM,CAAC,GAAG,EAAE,wBAAwB,CAAC,CAAC;IACzE,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;IACvD,CAAC;IAED,MAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ,IAAI,MAAM,CAAC,GAAG,EAAE,uBAAuB,CAAC,CAAC;IAC5E,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IACzD,CAAC;IAED,MAAM,WAAW,GACf,SAAS,CAAC,WAAW;QACrB,MAAM,CAAC,GAAG,EAAE,qBAAqB,CAAC;QAClC,oBAAoB,CAAC;IAEvB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;AAC1D,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,SAAS;IACT,QAAQ;IACR,UAAU;IACV,aAAa;IACb,QAAQ;CACA,CAAC"}
|