akm-cli 0.9.0-rc.8 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1063 -44
- package/README.md +51 -25
- package/SECURITY.md +14 -1
- package/STABILITY.md +497 -0
- package/dist/akm +148 -35
- package/dist/{akm-migrate-storage → akm-migrate} +6 -9
- package/dist/assets/hints/cli-hints-full.md +223 -95
- package/dist/assets/hints/cli-hints-short.md +85 -22
- package/dist/assets/improve-strategies/default.json +1 -1
- package/dist/assets/improve-strategies/reflect-distill.json +1 -1
- package/dist/assets/prompts/memory-infer-user.md +2 -3
- package/dist/assets/stash-skeleton/README.md +6 -5
- package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/backlinks.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/domains.md +2 -0
- package/dist/assets/stash-skeleton/facts/conventions/organization.md +20 -9
- package/dist/assets/tasks/core/extract.yml +1 -1
- package/dist/assets/tasks/core/version-check.yml +1 -1
- package/dist/assets/tasks/improve/akm-graph-refresh-weekly.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-catchup.yml +8 -0
- package/dist/assets/tasks/improve/akm-improve-consolidate.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-frequent.yml +5 -0
- package/dist/assets/tasks/improve/akm-improve-nightly.yml +5 -0
- package/dist/assets/templates/html/health.html +1 -3
- package/dist/assets/workflows/workflow-template.md +32 -15
- package/dist/cli/invocation.js +40 -15
- package/dist/cli/parse-args.js +0 -22
- package/dist/cli/retired-commands.js +121 -0
- package/dist/cli/shared.js +154 -22
- package/dist/cli/unknown-flags.js +236 -0
- package/dist/cli-node.mjs +2 -1
- package/dist/cli.js +696 -258
- package/dist/commands/agent/agent-dispatch.js +14 -3
- package/dist/commands/agent/contribute-cli.js +73 -88
- package/dist/commands/completions.js +79 -22
- package/dist/commands/config-cli.js +17 -150
- package/dist/commands/env/env-cli.js +59 -143
- package/dist/commands/env/env.js +12 -163
- package/dist/commands/env/marker-path.js +6 -0
- package/dist/commands/env/secret-cli.js +36 -66
- package/dist/commands/env/secret.js +24 -57
- package/dist/commands/feedback-cli.js +141 -87
- package/dist/commands/health/accept-rate.js +58 -0
- package/dist/commands/health/advisories.js +3 -4
- package/dist/commands/health/checks.js +85 -23
- package/dist/commands/health/html-report.js +7 -10
- package/dist/commands/health/improve-metrics.js +25 -83
- package/dist/commands/health/md-report.js +5 -9
- package/dist/commands/health/metrics.js +62 -20
- package/dist/commands/health/renderers.js +47 -0
- package/dist/commands/health/report-view-model.js +4 -5
- package/dist/commands/health/stash-exposure.js +1 -1
- package/dist/commands/health/surfaces.js +3 -48
- package/dist/commands/health/task-runs.js +3 -67
- package/dist/commands/health/types-improve.js +7 -0
- package/dist/commands/health.js +99 -28
- package/dist/commands/improve/anti-collapse.js +2 -2
- package/dist/commands/improve/autonomy-gate.js +68 -0
- package/dist/commands/improve/collapse-detector.js +41 -40
- package/dist/commands/improve/consolidate/eligibility.js +1 -23
- package/dist/commands/improve/consolidate/merge.js +4 -0
- package/dist/commands/improve/consolidate.js +140 -1000
- package/dist/commands/improve/distill/promote-memory.js +12 -12
- package/dist/commands/improve/distill/quality-gate.js +6 -6
- package/dist/commands/improve/distill.js +58 -69
- package/dist/commands/improve/eligibility.js +105 -57
- package/dist/commands/improve/extract-cli.js +14 -133
- package/dist/commands/improve/improve-cli.js +98 -114
- package/dist/commands/improve/improve-result-file.js +1 -28
- package/dist/commands/improve/improve-strategies.js +8 -5
- package/dist/commands/improve/improve.js +128 -91
- package/dist/commands/improve/loop-stages.js +182 -20
- package/dist/commands/improve/memory/derived-ref.js +45 -43
- package/dist/commands/improve/memory/memory-belief.js +1 -1
- package/dist/commands/improve/memory/memory-contradiction-detect.js +4 -12
- package/dist/commands/improve/memory/memory-improve.js +6 -5
- package/dist/commands/improve/outcome-loop.js +22 -65
- package/dist/commands/improve/preparation.js +114 -123
- package/dist/commands/improve/proactive-maintenance.js +2 -5
- package/dist/commands/improve/reflect.js +56 -160
- package/dist/commands/improve/salience.js +11 -122
- package/dist/commands/improve/source-identity.js +10 -38
- package/dist/commands/lint/base-linter.js +20 -124
- package/dist/commands/lint/env-key-rules.js +31 -47
- package/dist/commands/lint/index.js +249 -43
- package/dist/commands/{events.js → log.js} +33 -38
- package/dist/commands/migrate-cli.js +92 -12
- package/dist/commands/migration-tool.js +46 -0
- package/dist/commands/observability-cli.js +70 -209
- package/dist/commands/proposal/drain.js +101 -29
- package/dist/commands/proposal/proposal-cli.js +76 -48
- package/dist/commands/proposal/proposal.js +54 -18
- package/dist/commands/proposal/propose-cli.js +88 -0
- package/dist/commands/proposal/propose.js +23 -15
- package/dist/commands/proposal/repository.js +701 -278
- package/dist/commands/proposal/validators/proposal-quality-validators.js +2 -8
- package/dist/commands/proposal/validators/proposal-validators.js +55 -7
- package/dist/commands/proposal/validators/proposals.js +4 -7
- package/dist/commands/read/curate.js +34 -53
- package/dist/commands/read/knowledge.js +150 -95
- package/dist/commands/read/registry-search.js +2 -2
- package/dist/commands/read/remember-cli.js +42 -15
- package/dist/commands/read/search-cli.js +180 -78
- package/dist/commands/read/search.js +58 -43
- package/dist/commands/read/show.js +197 -141
- package/dist/commands/registry-cli.js +12 -51
- package/dist/commands/remember.js +14 -57
- package/dist/commands/sources/add-cli.js +100 -31
- package/dist/commands/sources/bundle-cli.js +166 -0
- package/dist/commands/sources/bundle-config-ops.js +7 -2
- package/dist/commands/sources/info.js +18 -5
- package/dist/commands/sources/init.js +12 -12
- package/dist/commands/sources/installed-stashes.js +382 -98
- package/dist/commands/sources/schema-repair.js +3 -2
- package/dist/commands/sources/self-update.js +131 -38
- package/dist/commands/sources/source-add.js +72 -17
- package/dist/commands/sources/source-clone.js +129 -45
- package/dist/commands/sources/source-manage.js +43 -23
- package/dist/commands/sources/sources-cli.js +57 -208
- package/dist/commands/sources/stash-cli.js +46 -53
- package/dist/commands/tasks/tasks-cli.js +91 -97
- package/dist/commands/tasks/tasks.js +276 -421
- package/dist/commands/workflow-cli.js +175 -450
- package/dist/core/adapter/adapters/akm-adapter.js +47 -28
- package/dist/core/adapter/adapters/akm-lint.js +42 -27
- package/dist/core/adapter/adapters/akm-metadata.js +15 -44
- package/dist/core/adapter/adapters/akm-task-adapter.js +15 -13
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +55 -71
- package/dist/core/adapter/adapters/dotenv-adapter.js +1 -1
- package/dist/core/adapter/adapters/generic-files-adapter.js +2 -0
- package/dist/core/adapter/adapters/index.js +6 -6
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +14 -8
- package/dist/core/adapter/adapters/okf-adapter.js +187 -19
- package/dist/core/adapter/adapters/shared.js +3 -19
- package/dist/core/adapter/adapters/tool-dir-shared.js +8 -3
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +1 -0
- package/dist/core/adapter/detect-adapter.js +17 -0
- package/dist/core/adapter/recognize-match.js +6 -4
- package/dist/core/adapter/validate-context.js +214 -0
- package/dist/core/asset/akm-markdown.js +63 -0
- package/dist/core/asset/asset-placement.js +20 -6
- package/dist/core/asset/asset-ref.js +11 -9
- package/dist/core/asset/frontmatter-lint.js +30 -0
- package/dist/core/asset/frontmatter.js +37 -9
- package/dist/core/asset/markdown.js +40 -51
- package/dist/core/asset/resolve-ref.js +89 -18
- package/dist/core/asset/stash-meta.js +1 -1
- package/dist/core/bundle-id.js +51 -0
- package/dist/core/common.js +152 -38
- package/dist/core/config/config-io.js +12 -1
- package/dist/core/config/config-schema.js +35 -8
- package/dist/core/config/config-sources.js +55 -11
- package/dist/core/config/config-walker.js +25 -9
- package/dist/core/config/config.js +9 -48
- package/dist/core/config/experimental.js +21 -0
- package/dist/core/config/schema/embedding.js +5 -1
- package/dist/core/config/schema/experimental.js +30 -0
- package/dist/core/config/schema/improve-processes.js +0 -6
- package/dist/core/config/schema/improve.js +21 -3
- package/dist/core/config/schema/index-config.js +8 -15
- package/dist/core/config/schema/output.js +4 -1
- package/dist/core/config/schema/setup.js +9 -18
- package/dist/core/config/schema/sources-bundles.js +49 -33
- package/dist/core/config/schema/workflow.js +3 -3
- package/dist/core/env-secret-ref.js +76 -46
- package/dist/core/errors.js +18 -12
- package/dist/core/events.js +46 -128
- package/dist/core/file-change.js +6 -5
- package/dist/core/fs-txn.js +83 -7
- package/dist/core/git-message.js +2 -2
- package/dist/core/improve-result.js +1 -100
- package/dist/core/lesson-lint.js +1 -17
- package/dist/core/logs-db.js +2 -1
- package/dist/core/migration-operation.js +16 -0
- package/dist/core/mutation-target.js +78 -0
- package/dist/core/parse.js +4 -1
- package/dist/core/paths.js +17 -20
- package/dist/core/recognition-util.js +12 -14
- package/dist/core/redaction.js +34 -0
- package/dist/core/standards/resolve-standards-context.js +2 -14
- package/dist/core/standards/resolve-stash-standards.js +2 -2
- package/dist/core/standards/resolve-type-conventions.js +2 -2
- package/dist/core/state/migrations.js +41 -18
- package/dist/core/state-db.js +5 -14
- package/dist/core/structured.js +1 -1
- package/dist/core/subprocess.js +6 -4
- package/dist/core/text-truncation.js +9 -5
- package/dist/core/type-presentation.js +3 -3
- package/dist/core/warn.js +0 -3
- package/dist/core/write-source.js +771 -95
- package/dist/indexer/bundle-identity-guard.js +3 -2
- package/dist/indexer/db/graph-db.js +0 -24
- package/dist/indexer/ensure-index.js +1 -0
- package/dist/indexer/graph/graph-boost.js +9 -34
- package/dist/indexer/graph/graph-extraction.js +8 -5
- package/dist/indexer/index-writer-lock.js +53 -17
- package/dist/indexer/index-written-assets.js +16 -22
- package/dist/indexer/indexer.js +497 -239
- package/dist/indexer/installations.js +14 -96
- package/dist/indexer/passes/dir-staleness.js +16 -9
- package/dist/indexer/passes/memory-inference.js +11 -9
- package/dist/indexer/passes/metadata.js +113 -47
- package/dist/indexer/scan/doc-to-entry.js +38 -1
- package/dist/indexer/scan/drain-dir.js +13 -23
- package/dist/indexer/search/db-search.js +99 -54
- package/dist/indexer/search/fts-query.js +47 -24
- package/dist/indexer/search/ranking-contributors.js +42 -20
- package/dist/indexer/search/ranking.js +18 -99
- package/dist/indexer/search/search-fields.js +7 -2
- package/dist/indexer/search/search-source.js +82 -93
- package/dist/indexer/usage/usage-events.js +0 -89
- package/dist/indexer/walk/file-context.js +2 -1
- package/dist/indexer/walk/matchers.js +30 -43
- package/dist/indexer/walk/path-resolver.js +7 -2
- package/dist/indexer/walk/walker.js +38 -12
- package/dist/integrations/agent/builders.js +0 -6
- package/dist/integrations/agent/config.js +2 -2
- package/dist/integrations/agent/detect.js +49 -19
- package/dist/integrations/agent/engine-fallback.js +76 -0
- package/dist/integrations/agent/profiles.js +14 -0
- package/dist/integrations/agent/prompts.js +12 -8
- package/dist/integrations/agent/runner-dispatch.js +4 -2
- package/dist/integrations/agent/runner.js +0 -1
- package/dist/integrations/agent/spawn.js +5 -6
- package/dist/integrations/github.js +1 -1
- package/dist/integrations/harnesses/aider/agent-builder.js +6 -4
- package/dist/integrations/harnesses/amazonq/agent-builder.js +7 -4
- package/dist/integrations/harnesses/claude/session-log.js +0 -10
- package/dist/integrations/harnesses/codex/agent-builder.js +5 -2
- package/dist/integrations/harnesses/copilot/agent-builder.js +5 -3
- package/dist/integrations/harnesses/gemini/agent-builder.js +5 -3
- package/dist/integrations/harnesses/index.js +3 -7
- package/dist/integrations/harnesses/opencode/agent-builder.js +21 -2
- package/dist/integrations/harnesses/opencode/session-log.js +0 -15
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +13 -4
- package/dist/integrations/harnesses/openhands/agent-builder.js +9 -6
- package/dist/integrations/harnesses/pi/agent-builder.js +6 -4
- package/dist/integrations/lockfile.js +101 -6
- package/dist/integrations/session-logs/index.js +3 -28
- package/dist/llm/client.js +136 -100
- package/dist/llm/embedders/remote.js +13 -5
- package/dist/llm/feature-gate.js +4 -12
- package/dist/llm/graph-extract.js +5 -11
- package/dist/llm/memory-infer.js +144 -1
- package/dist/llm/metadata-enhance.js +5 -7
- package/dist/llm/structured-call.js +1 -1
- package/dist/llm/usage-persist.js +26 -5
- package/dist/llm/usage-telemetry.js +25 -2
- package/dist/output/cli-hints.js +1 -2
- package/dist/output/context.js +22 -7
- package/dist/output/format-exempt.js +80 -0
- package/dist/output/generic-render.js +259 -0
- package/dist/output/render-registry.js +57 -0
- package/dist/output/renderers.js +14 -36
- package/dist/output/shapes/curate.js +10 -1
- package/dist/output/shapes/events.js +12 -7
- package/dist/output/shapes/helpers.js +56 -83
- package/dist/output/shapes/migrate.js +8 -0
- package/dist/output/shapes/passthrough.js +7 -41
- package/dist/output/shapes/proposal/producer.js +15 -7
- package/dist/output/shapes.js +2 -9
- package/dist/output/text/{init.js → bundle-create.js} +3 -1
- package/dist/output/text/bundle-show.js +7 -0
- package/dist/output/text/command-format.js +164 -96
- package/dist/output/text/env.js +1 -3
- package/dist/output/text/events.js +8 -7
- package/dist/output/text/health-format.js +103 -0
- package/dist/output/text/health.js +7 -0
- package/dist/output/text/helpers.js +10 -8
- package/dist/output/text/lint-format.js +43 -0
- package/dist/output/text/{save.js → lint.js} +2 -2
- package/dist/output/text/migrate.js +88 -0
- package/dist/output/text/proposal/producer.js +4 -2
- package/dist/output/text/proposal-format.js +44 -72
- package/dist/output/text/registry-commands.js +1 -2
- package/dist/output/text/show-directives.js +15 -7
- package/dist/output/text/status-list.js +32 -0
- package/dist/output/text/sync.js +5 -0
- package/dist/output/text/workflow-format.js +24 -203
- package/dist/output/text/workflow.js +1 -7
- package/dist/output/text.js +16 -17
- package/dist/registry/factory.js +4 -6
- package/dist/registry/origin-resolve.js +16 -27
- package/dist/registry/providers/skills-sh.js +3 -3
- package/dist/registry/providers/static-index.js +13 -23
- package/dist/registry/resolve.js +42 -7
- package/dist/registry/semver.js +34 -84
- package/dist/runtime.js +2 -23
- package/dist/scripts/akm-migrate-node.js +60290 -0
- package/dist/scripts/akm-migrate.js +59628 -0
- package/dist/setup/detect.js +42 -15
- package/dist/setup/registry-stash-loader.js +2 -2
- package/dist/setup/setup.js +236 -136
- package/dist/setup/steps/connection.js +7 -9
- package/dist/setup/steps/platforms.js +9 -9
- package/dist/setup/steps/semantic.js +15 -3
- package/dist/setup/steps/sources.js +12 -13
- package/dist/setup/steps/stashdir.js +2 -3
- package/dist/setup/steps/tasks.js +237 -120
- package/dist/sources/freshness.js +1 -1
- package/dist/sources/provider-factory.js +11 -17
- package/dist/sources/providers/filesystem.js +2 -3
- package/dist/sources/providers/git-install.js +278 -34
- package/dist/sources/providers/git-provider.js +25 -23
- package/dist/sources/providers/git-stash.js +395 -106
- package/dist/sources/providers/git.js +2 -2
- package/dist/sources/providers/npm.js +16 -19
- package/dist/sources/providers/provider-utils.js +7 -4
- package/dist/sources/providers/sync-from-ref.js +3 -9
- package/dist/sources/providers/website.js +6 -1
- package/dist/sources/resolve.js +6 -5
- package/dist/sources/snapshot-fetchers/bluesky.js +146 -0
- package/dist/sources/snapshot-fetchers/content-extract.js +566 -0
- package/dist/sources/snapshot-fetchers/fetcher-util.js +41 -0
- package/dist/sources/snapshot-fetchers/github.js +100 -0
- package/dist/sources/snapshot-fetchers/host-guard.js +291 -0
- package/dist/sources/snapshot-fetchers/registry.js +17 -1
- package/dist/sources/snapshot-fetchers/robots.js +348 -0
- package/dist/sources/snapshot-fetchers/rss.js +282 -0
- package/dist/sources/snapshot-fetchers/secret-seam.js +42 -0
- package/dist/sources/snapshot-fetchers/website-ingest.js +566 -268
- package/dist/sources/snapshot-fetchers/x.js +910 -0
- package/dist/storage/database.js +7 -0
- package/dist/storage/engines/sqlite-migrations.js +23 -111
- package/dist/storage/managed-db.js +2 -2
- package/dist/storage/repositories/canaries-repository.js +1 -1
- package/dist/storage/repositories/events-repository.js +27 -11
- package/dist/storage/repositories/improve-runs-repository.js +6 -12
- package/dist/storage/repositories/index-connection.js +17 -6
- package/dist/storage/repositories/index-entries-repository.js +151 -240
- package/dist/storage/repositories/index-entry-mapper.js +15 -11
- package/dist/storage/repositories/index-fts-repository.js +5 -2
- package/dist/storage/repositories/index-llm-cache-repository.js +0 -1
- package/dist/storage/repositories/index-meta-repository.js +2 -3
- package/dist/storage/repositories/index-schema.js +10 -25
- package/dist/storage/repositories/index-utility-repository.js +15 -28
- package/dist/storage/repositories/index-vec-repository.js +6 -1
- package/dist/storage/repositories/outcome-repository.js +119 -0
- package/dist/storage/repositories/proposals-repository.js +296 -59
- package/dist/storage/repositories/registry-cache.js +19 -0
- package/dist/storage/repositories/salience-repository.js +172 -0
- package/dist/storage/repositories/task-history-repository.js +15 -13
- package/dist/storage/repositories/workflow-runs-repository.js +52 -40
- package/dist/tasks/backends/cron.js +105 -15
- package/dist/tasks/backends/index.js +1 -1
- package/dist/tasks/backends/launchd.js +85 -38
- package/dist/tasks/backends/schtasks.js +135 -15
- package/dist/tasks/embedded.js +56 -40
- package/dist/tasks/parser.js +7 -157
- package/dist/tasks/resolve-akm-bin.js +137 -59
- package/dist/tasks/runner.js +79 -42
- package/dist/tasks/scheduler-invocation.js +220 -10
- package/dist/tasks/schema.js +24 -1
- package/dist/tasks/task-id.js +1 -3
- package/dist/tasks/validator.js +20 -6
- package/dist/workflows/authoring/authoring.js +94 -143
- package/dist/workflows/authoring/scope-key.js +1 -1
- package/dist/workflows/exec/frozen-judge.js +28 -2
- package/dist/workflows/exec/native-executor.js +77 -57
- package/dist/workflows/exec/param-secrets.js +9 -9
- package/dist/workflows/exec/run-workflow.js +133 -79
- package/dist/workflows/exec/step-work.js +219 -346
- package/dist/{migrate-storage-node.mjs → workflows/exec/unit-dispatch.js} +1 -5
- package/dist/workflows/ir/compile.js +141 -270
- package/dist/workflows/ir/freeze.js +40 -30
- package/dist/workflows/ir/params.js +135 -11
- package/dist/workflows/ir/plan-hash.js +1 -1
- package/dist/workflows/ir/schema.js +25 -26
- package/dist/workflows/parser.js +872 -307
- package/dist/workflows/program/expressions.js +20 -208
- package/dist/workflows/program/schema.js +7 -10
- package/dist/workflows/renderer.js +95 -68
- package/dist/workflows/resource-limits.js +2 -0
- package/dist/workflows/runtime/checkin.js +3 -3
- package/dist/workflows/runtime/plan-classifier.js +16 -75
- package/dist/workflows/runtime/runs.js +186 -127
- package/dist/workflows/runtime/unit-checkin.js +1 -1
- package/dist/workflows/runtime/unit-phases.js +2 -2
- package/dist/workflows/runtime/workflow-asset-loader.js +232 -83
- package/dist/workflows/schema.js +1 -11
- package/dist/workflows/validate-summary.js +30 -36
- package/dist/workflows/validator.js +21 -62
- package/docs/README.md +68 -0
- package/docs/migration/README.md +8 -0
- package/docs/migration/release-notes/0.7.0.md +11 -11
- package/docs/migration/release-notes/0.9.0.md +208 -27
- package/docs/migration/v0.7-to-v0.8.md +46 -47
- package/docs/migration/v0.8-to-v0.9.md +564 -208
- package/docs/migration/v0.9.0-troubleshooting.md +561 -0
- package/docs/reference/README.md +12 -0
- package/docs/reference/cli.md +2253 -0
- package/docs/reference/configuration.md +358 -0
- package/docs/reference/data-and-telemetry.md +105 -42
- package/docs/reference/workflows.md +647 -0
- package/package.json +22 -11
- package/schemas/akm-asset-envelope.json +93 -0
- package/schemas/akm-config.json +81 -128
- package/schemas/akm-workflow.json +74 -73
- package/dist/assets/tasks/core/backup.yml +0 -5
- package/dist/assets/tasks/graph-refresh-weekly.yml +0 -10
- package/dist/cli/config-migrate.js +0 -1806
- package/dist/cli/config-validate.js +0 -41
- package/dist/commands/backup-cli.js +0 -56
- package/dist/commands/bundle/bundle-cli.js +0 -68
- package/dist/commands/bundle/bundle.js +0 -219
- package/dist/commands/graph/graph-cli.js +0 -124
- package/dist/commands/graph/graph.js +0 -489
- package/dist/commands/improve/extract-watch.js +0 -140
- package/dist/commands/mv-cli.js +0 -1221
- package/dist/commands/sources/history.js +0 -201
- package/dist/commands/tasks/default-tasks.js +0 -186
- package/dist/core/migration-backup.js +0 -1234
- package/dist/indexer/usage/unmigrated-vaults-guard.js +0 -95
- package/dist/llm/memory-infer-impl.js +0 -138
- package/dist/migrate/legacy/config-source-migration.js +0 -223
- package/dist/migrate/legacy/content-migration.js +0 -305
- package/dist/migrate/legacy/legacy-layout.js +0 -779
- package/dist/migrate/legacy/legacy-paths.js +0 -25
- package/dist/migrate/legacy/legacy-stash-json.js +0 -72
- package/dist/migrate/legacy/proposal-fs-import.js +0 -168
- package/dist/migrate/legacy/task-target-ref-migration.js +0 -272
- package/dist/migrate/legacy/three-db-cutover.js +0 -841
- package/dist/migrate/legacy/workflow-migrations-bodies.js +0 -52
- package/dist/migrate/legacy/workflow-migrations-frozen.js +0 -21
- package/dist/migrate/legacy-ref-grammar.js +0 -214
- package/dist/output/shapes/distill.js +0 -14
- package/dist/output/shapes/history.js +0 -11
- package/dist/output/text/distill.js +0 -6
- package/dist/output/text/enable-disable.js +0 -8
- package/dist/output/text/history.js +0 -6
- package/dist/registry/build-index.js +0 -382
- package/dist/schemas/akm-config.json +0 -4704
- package/dist/schemas/akm-task.json +0 -87
- package/dist/schemas/akm-workflow.json +0 -372
- package/dist/scripts/migrate-storage.js +0 -3816
- package/dist/workflows/authoring/workflow-program-template.yaml +0 -31
- package/dist/workflows/cli.js +0 -53
- package/dist/workflows/exec/brief.js +0 -481
- package/dist/workflows/exec/report.js +0 -1460
- package/dist/workflows/exec/watch.js +0 -116
- package/dist/workflows/program/parser.js +0 -813
- package/dist/workflows/program/project.js +0 -104
|
@@ -1,382 +0,0 @@
|
|
|
1
|
-
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
-
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
-
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
-
/**
|
|
5
|
-
* Build the v2 JSON registry index consumed by the `static-index` registry
|
|
6
|
-
* provider. This module emits artifacts that conform to the v2 schema; the
|
|
7
|
-
* schema itself is the input contract owned by `src/registry/providers/static-index.ts`
|
|
8
|
-
* (see v1 architecture spec §3.3 — "the v2 JSON index schema belongs to
|
|
9
|
-
* static-index"). When the schema changes, the parser in `static-index.ts`
|
|
10
|
-
* must be updated together with this builder.
|
|
11
|
-
*/
|
|
12
|
-
import fs from "node:fs";
|
|
13
|
-
import path from "node:path";
|
|
14
|
-
import { fetchWithRetry, jsonWithByteCap } from "../core/common.js";
|
|
15
|
-
import { getCacheDir } from "../core/paths.js";
|
|
16
|
-
import { recognizeStashEntries } from "../indexer/scan/drain-dir.js";
|
|
17
|
-
import { walkStashFlat } from "../indexer/walk/walker.js";
|
|
18
|
-
import { asRecord, asString, GITHUB_API_BASE, githubHeaders } from "../integrations/github.js";
|
|
19
|
-
import { writeResponseToFileCapped } from "../runtime.js";
|
|
20
|
-
import { copyIncludedPaths, findNearestIncludeConfig } from "../sources/include.js";
|
|
21
|
-
import { detectStashRoot } from "../sources/providers/provider-utils.js";
|
|
22
|
-
import { extractTarGzSecure } from "../sources/providers/tar-utils.js";
|
|
23
|
-
import { parseRegistryIndex } from "./providers/static-index.js";
|
|
24
|
-
const DEFAULT_NPM_REGISTRY_BASE = "https://registry.npmjs.org";
|
|
25
|
-
const REQUIRED_KEYWORDS = ["akm-stash"];
|
|
26
|
-
const GITHUB_TOPICS = ["akm-stash"];
|
|
27
|
-
const EXCLUDED_REPOS = new Set(["itlackey/akm"]);
|
|
28
|
-
const EXCLUDED_NPM_PACKAGES = new Set(["akm-cli"]);
|
|
29
|
-
const EMPTY_INSPECTION = {};
|
|
30
|
-
function getDefaultRegistryBuildDir() {
|
|
31
|
-
return path.join(getCacheDir(), "registry-build");
|
|
32
|
-
}
|
|
33
|
-
export async function buildRegistryIndex(options) {
|
|
34
|
-
const manualEntriesPath = path.resolve(options?.manualEntriesPath ?? path.join(getDefaultRegistryBuildDir(), "manual-entries.json"));
|
|
35
|
-
const npmRegistryBase = trimTrailingSlash(options?.npmRegistryBase ?? DEFAULT_NPM_REGISTRY_BASE);
|
|
36
|
-
const githubApiBase = trimTrailingSlash(options?.githubApiBase ?? GITHUB_API_BASE);
|
|
37
|
-
const [manualKits, npmKits, githubKits] = await Promise.all([
|
|
38
|
-
loadManualEntries(manualEntriesPath),
|
|
39
|
-
scanNpm(npmRegistryBase),
|
|
40
|
-
scanGithub(githubApiBase),
|
|
41
|
-
]);
|
|
42
|
-
const stashes = deduplicateStashes([...manualKits, ...npmKits, ...githubKits]).sort((a, b) => a.name.localeCompare(b.name));
|
|
43
|
-
const index = {
|
|
44
|
-
version: 3,
|
|
45
|
-
updatedAt: new Date().toISOString(),
|
|
46
|
-
stashes,
|
|
47
|
-
};
|
|
48
|
-
return {
|
|
49
|
-
index,
|
|
50
|
-
counts: {
|
|
51
|
-
manual: manualKits.length,
|
|
52
|
-
npm: npmKits.length,
|
|
53
|
-
github: githubKits.length,
|
|
54
|
-
total: stashes.length,
|
|
55
|
-
},
|
|
56
|
-
paths: {
|
|
57
|
-
manualEntriesPath,
|
|
58
|
-
},
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
export function writeRegistryIndex(index, outPath) {
|
|
62
|
-
const resolved = path.resolve(outPath ?? path.join(getDefaultRegistryBuildDir(), "index.json"));
|
|
63
|
-
fs.mkdirSync(path.dirname(resolved), { recursive: true });
|
|
64
|
-
fs.writeFileSync(resolved, `${JSON.stringify(index, null, 2)}\n`, "utf8");
|
|
65
|
-
return resolved;
|
|
66
|
-
}
|
|
67
|
-
async function scanNpm(npmRegistryBase) {
|
|
68
|
-
const stashes = [];
|
|
69
|
-
const seen = new Set();
|
|
70
|
-
for (const keyword of REQUIRED_KEYWORDS) {
|
|
71
|
-
let offset = 0;
|
|
72
|
-
const size = 250;
|
|
73
|
-
while (true) {
|
|
74
|
-
const url = `${npmRegistryBase}/-/v1/search?text=keywords:${encodeURIComponent(keyword)}&size=${size}&from=${offset}`;
|
|
75
|
-
const data = await fetchJson(url);
|
|
76
|
-
for (const obj of data.objects) {
|
|
77
|
-
const pkg = obj.package;
|
|
78
|
-
if (EXCLUDED_NPM_PACKAGES.has(pkg.name))
|
|
79
|
-
continue;
|
|
80
|
-
const repoUrl = pkg.links?.repository ?? "";
|
|
81
|
-
const normalizedRepo = repoUrl.replace(/^https?:\/\/github\.com\//, "").replace(/\.git$/, "");
|
|
82
|
-
if (EXCLUDED_REPOS.has(normalizedRepo))
|
|
83
|
-
continue;
|
|
84
|
-
const id = `npm:${pkg.name}`;
|
|
85
|
-
if (seen.has(id))
|
|
86
|
-
continue;
|
|
87
|
-
seen.add(id);
|
|
88
|
-
const keywords = (pkg.keywords ?? []).map((value) => value.toLowerCase());
|
|
89
|
-
if (!keywords.some((value) => REQUIRED_KEYWORDS.includes(value)))
|
|
90
|
-
continue;
|
|
91
|
-
let latestMetadata = {};
|
|
92
|
-
try {
|
|
93
|
-
latestMetadata = await fetchJson(`${npmRegistryBase}/${encodeURIComponent(pkg.name)}/latest`);
|
|
94
|
-
}
|
|
95
|
-
catch {
|
|
96
|
-
latestMetadata = {};
|
|
97
|
-
}
|
|
98
|
-
const inspection = await inspectNpmPackage(npmRegistryBase, latestMetadata).catch(() => EMPTY_INSPECTION);
|
|
99
|
-
const tags = mergeStrings((pkg.keywords ?? []).filter((value) => !REQUIRED_KEYWORDS.includes(value.toLowerCase())), inspection.tags);
|
|
100
|
-
stashes.push(normalizeStash({
|
|
101
|
-
id,
|
|
102
|
-
name: pkg.name,
|
|
103
|
-
description: inspection.description ?? pkg.description,
|
|
104
|
-
ref: pkg.name,
|
|
105
|
-
source: "npm",
|
|
106
|
-
homepage: pkg.links?.homepage ?? pkg.links?.npm,
|
|
107
|
-
author: pkg.author?.name ?? pkg.author?.username ?? pkg.publisher?.username,
|
|
108
|
-
latestVersion: inspection.latestVersion ?? pkg.version,
|
|
109
|
-
license: asString(latestMetadata.license) ?? inspection.license,
|
|
110
|
-
tags,
|
|
111
|
-
assetTypes: inspection.assetTypes,
|
|
112
|
-
assets: inspection.assets,
|
|
113
|
-
}));
|
|
114
|
-
}
|
|
115
|
-
if (data.objects.length < size)
|
|
116
|
-
break;
|
|
117
|
-
offset += size;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
return stashes;
|
|
121
|
-
}
|
|
122
|
-
async function inspectNpmPackage(_npmRegistryBase, latestMetadata) {
|
|
123
|
-
const dist = asRecord(latestMetadata.dist);
|
|
124
|
-
const tarballUrl = asString(dist.tarball);
|
|
125
|
-
if (!tarballUrl)
|
|
126
|
-
return {};
|
|
127
|
-
const inspection = await inspectArchive(tarballUrl);
|
|
128
|
-
return {
|
|
129
|
-
description: asString(latestMetadata.description) ?? inspection.description,
|
|
130
|
-
latestVersion: asString(latestMetadata.version) ?? inspection.latestVersion,
|
|
131
|
-
license: asString(latestMetadata.license) ?? inspection.license,
|
|
132
|
-
tags: mergeStrings(extractNonReservedKeywords(latestMetadata.keywords), inspection.tags),
|
|
133
|
-
assetTypes: inspection.assetTypes,
|
|
134
|
-
assets: inspection.assets,
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
async function scanGithub(githubApiBase) {
|
|
138
|
-
const stashes = [];
|
|
139
|
-
const seen = new Set();
|
|
140
|
-
const headers = githubHeaders();
|
|
141
|
-
for (const topic of GITHUB_TOPICS) {
|
|
142
|
-
let page = 1;
|
|
143
|
-
const perPage = 100;
|
|
144
|
-
while (true) {
|
|
145
|
-
const q = encodeURIComponent(`topic:${topic}`);
|
|
146
|
-
const url = `${githubApiBase}/search/repositories?q=${q}&sort=updated&order=desc&per_page=${perPage}&page=${page}`;
|
|
147
|
-
const data = await fetchJson(url, headers);
|
|
148
|
-
for (const repo of data.items) {
|
|
149
|
-
if (EXCLUDED_REPOS.has(repo.full_name))
|
|
150
|
-
continue;
|
|
151
|
-
const id = `github:${repo.full_name}`;
|
|
152
|
-
if (seen.has(id))
|
|
153
|
-
continue;
|
|
154
|
-
seen.add(id);
|
|
155
|
-
const inspection = await inspectArchive(`${githubApiBase}/repos/${repo.full_name}/tarball/${encodeURIComponent(repo.default_branch)}`, headers).catch(() => EMPTY_INSPECTION);
|
|
156
|
-
const topics = repo.topics.filter((value) => !GITHUB_TOPICS.includes(value));
|
|
157
|
-
stashes.push(normalizeStash({
|
|
158
|
-
id,
|
|
159
|
-
name: repo.name,
|
|
160
|
-
description: inspection.description ?? repo.description ?? undefined,
|
|
161
|
-
ref: repo.full_name,
|
|
162
|
-
source: "github",
|
|
163
|
-
homepage: repo.html_url,
|
|
164
|
-
author: repo.owner.login,
|
|
165
|
-
latestVersion: inspection.latestVersion,
|
|
166
|
-
license: repo.license?.spdx_id ?? inspection.license,
|
|
167
|
-
tags: mergeStrings(topics, inspection.tags),
|
|
168
|
-
assetTypes: inspection.assetTypes,
|
|
169
|
-
assets: inspection.assets,
|
|
170
|
-
}));
|
|
171
|
-
}
|
|
172
|
-
if (data.items.length < perPage)
|
|
173
|
-
break;
|
|
174
|
-
page += 1;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
return stashes;
|
|
178
|
-
}
|
|
179
|
-
async function inspectArchive(url, headers) {
|
|
180
|
-
// Route registry-build scratch space under the akm cache dir instead of
|
|
181
|
-
// the system temp directory. Long-running registry builds that crash
|
|
182
|
-
// mid-flight previously left orphan dirs under `/tmp`, which can fill
|
|
183
|
-
// the OS partition. Pinning to `${getCacheDir()}/registry-build/` keeps
|
|
184
|
-
// a single `rm -rf` of that directory sufficient to reclaim the space
|
|
185
|
-
// and leaves the operator's `/tmp` untouched. See #276 for the
|
|
186
|
-
// bench-tmp precedent and #284 for this non-bench rollout.
|
|
187
|
-
const tmpRoot = path.join(getCacheDir(), "registry-build");
|
|
188
|
-
fs.mkdirSync(tmpRoot, { recursive: true });
|
|
189
|
-
const tempDir = fs.mkdtempSync(path.join(tmpRoot, "build-"));
|
|
190
|
-
const archivePath = path.join(tempDir, "archive.tgz");
|
|
191
|
-
const extractDir = path.join(tempDir, "extract");
|
|
192
|
-
try {
|
|
193
|
-
const response = await fetchWithRetry(url, headers ? { headers } : undefined, { timeout: 120_000 });
|
|
194
|
-
if (!response.ok) {
|
|
195
|
-
throw new Error(`Failed to fetch archive (${response.status}) from ${url}`);
|
|
196
|
-
}
|
|
197
|
-
// Byte-capped + body-deadline streaming: the fetch timeout bounds only the
|
|
198
|
-
// header phase, so cap the streamed archive to guard against an unbounded or
|
|
199
|
-
// dribbling body during a registry build.
|
|
200
|
-
await writeResponseToFileCapped(archivePath, response);
|
|
201
|
-
// Reuse the secure extraction from registry-install which validates entries,
|
|
202
|
-
// uses --no-same-owner, strips components, and runs a post-extraction scan.
|
|
203
|
-
extractTarGzSecure(archivePath, extractDir);
|
|
204
|
-
const stashRoot = detectStashRoot(extractDir);
|
|
205
|
-
const inspectionRoot = applyIncludeConfigForInspection(stashRoot, tempDir, extractDir) ?? stashRoot;
|
|
206
|
-
const metadata = await enumerateAssets(inspectionRoot);
|
|
207
|
-
const packageMetadata = readNearestPackageJson(extractDir, inspectionRoot);
|
|
208
|
-
const assets = metadata.map((entry) => ({
|
|
209
|
-
type: entry.type,
|
|
210
|
-
name: entry.name,
|
|
211
|
-
...(entry.description ? { description: entry.description } : {}),
|
|
212
|
-
...(entry.tags && entry.tags.length > 0 ? { tags: entry.tags } : {}),
|
|
213
|
-
...(typeof entry.fileSize === "number" ? { estimatedTokens: Math.round(entry.fileSize / 4) } : {}),
|
|
214
|
-
}));
|
|
215
|
-
return {
|
|
216
|
-
description: asString(packageMetadata.description),
|
|
217
|
-
latestVersion: asString(packageMetadata.version),
|
|
218
|
-
license: asString(packageMetadata.license),
|
|
219
|
-
tags: extractNonReservedKeywords(packageMetadata.keywords),
|
|
220
|
-
assetTypes: deriveAssetTypes(assets),
|
|
221
|
-
assets: assets.length > 0 ? assets : undefined,
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
finally {
|
|
225
|
-
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
function readNearestPackageJson(extractDir, stashRoot) {
|
|
229
|
-
const candidates = [
|
|
230
|
-
path.join(stashRoot, "package.json"),
|
|
231
|
-
path.join(extractDir, "package.json"),
|
|
232
|
-
path.join(extractDir, "package", "package.json"),
|
|
233
|
-
];
|
|
234
|
-
for (const candidate of candidates) {
|
|
235
|
-
try {
|
|
236
|
-
return asRecord(JSON.parse(fs.readFileSync(candidate, "utf8")));
|
|
237
|
-
}
|
|
238
|
-
catch { }
|
|
239
|
-
}
|
|
240
|
-
return {};
|
|
241
|
-
}
|
|
242
|
-
async function enumerateAssets(stashRoot) {
|
|
243
|
-
const fileContexts = walkStashFlat(stashRoot);
|
|
244
|
-
const dirGroups = new Map();
|
|
245
|
-
for (const ctx of fileContexts) {
|
|
246
|
-
const group = dirGroups.get(ctx.parentDirAbs);
|
|
247
|
-
if (group)
|
|
248
|
-
group.push(ctx.absPath);
|
|
249
|
-
else
|
|
250
|
-
dirGroups.set(ctx.parentDirAbs, [ctx.absPath]);
|
|
251
|
-
}
|
|
252
|
-
const entries = [];
|
|
253
|
-
for (const [dirPath, files] of dirGroups) {
|
|
254
|
-
// `.stash.json` sidecar overrides retired (#39): a published stash that
|
|
255
|
-
// still ships sidecars (pre-0.9.0, never migrated) contributes only its
|
|
256
|
-
// frontmatter-recognized entries.
|
|
257
|
-
const stash = recognizeStashEntries(stashRoot, files);
|
|
258
|
-
if (stash.entries.length === 0)
|
|
259
|
-
continue;
|
|
260
|
-
entries.push(...stash.entries.filter((entry) => !!entry.filename).map((entry) => attachFileSize(dirPath, entry)));
|
|
261
|
-
}
|
|
262
|
-
return entries.sort((a, b) => `${a.type}:${a.name}`.localeCompare(`${b.type}:${b.name}`));
|
|
263
|
-
}
|
|
264
|
-
function attachFileSize(dirPath, entry) {
|
|
265
|
-
if (typeof entry.fileSize === "number" || !entry.filename)
|
|
266
|
-
return entry;
|
|
267
|
-
try {
|
|
268
|
-
return { ...entry, fileSize: fs.statSync(path.join(dirPath, entry.filename)).size };
|
|
269
|
-
}
|
|
270
|
-
catch {
|
|
271
|
-
return entry;
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
function applyIncludeConfigForInspection(stashRoot, tempDir, searchRoot) {
|
|
275
|
-
const includeConfig = findNearestIncludeConfig(stashRoot, searchRoot);
|
|
276
|
-
if (!includeConfig)
|
|
277
|
-
return undefined;
|
|
278
|
-
const selectedDir = path.join(tempDir, "selected");
|
|
279
|
-
fs.rmSync(selectedDir, { recursive: true, force: true });
|
|
280
|
-
fs.mkdirSync(selectedDir, { recursive: true });
|
|
281
|
-
copyIncludedPaths(includeConfig.include, includeConfig.baseDir, selectedDir);
|
|
282
|
-
return selectedDir;
|
|
283
|
-
}
|
|
284
|
-
async function loadManualEntries(manualEntriesPath) {
|
|
285
|
-
try {
|
|
286
|
-
const raw = JSON.parse(fs.readFileSync(manualEntriesPath, "utf8"));
|
|
287
|
-
const candidateKits = Array.isArray(raw) ? raw : asRecord(raw).stashes;
|
|
288
|
-
const parsed = parseRegistryIndex({ version: 3, updatedAt: new Date().toISOString(), stashes: candidateKits });
|
|
289
|
-
if (!parsed)
|
|
290
|
-
return [];
|
|
291
|
-
// Legacy `curated` flag on input entries is ignored (v1 spec §4.2). The
|
|
292
|
-
// builder no longer emits it on the resulting index.
|
|
293
|
-
return parsed.stashes.map((stash) => normalizeStash(stash));
|
|
294
|
-
}
|
|
295
|
-
catch {
|
|
296
|
-
return [];
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
// npm / GitHub API JSON pages; 25 MB cap covers the largest realistic
|
|
300
|
-
// search result set while still bounding memory against a malicious or
|
|
301
|
-
// misconfigured upstream that streams unbounded JSON.
|
|
302
|
-
const BUILD_INDEX_JSON_BYTE_CAP = 25 * 1024 * 1024;
|
|
303
|
-
async function fetchJson(url, headers) {
|
|
304
|
-
const response = await fetchWithRetry(url, headers ? { headers } : undefined, { timeout: 30_000 });
|
|
305
|
-
if (!response.ok) {
|
|
306
|
-
// Error-body sampling is intentionally small; 4 KB is plenty to
|
|
307
|
-
// include upstream hints in the thrown error.
|
|
308
|
-
const body = await response.text().catch(() => "");
|
|
309
|
-
throw new Error(`HTTP ${response.status} from ${url}: ${body.slice(0, 200)}`);
|
|
310
|
-
}
|
|
311
|
-
return jsonWithByteCap(response, BUILD_INDEX_JSON_BYTE_CAP);
|
|
312
|
-
}
|
|
313
|
-
function deduplicateStashes(stashes) {
|
|
314
|
-
const byId = new Map();
|
|
315
|
-
for (const stash of stashes) {
|
|
316
|
-
const existing = byId.get(stash.id);
|
|
317
|
-
byId.set(stash.id, existing ? mergeEntries(existing, stash) : stash);
|
|
318
|
-
}
|
|
319
|
-
return [...byId.values()];
|
|
320
|
-
}
|
|
321
|
-
function mergeEntries(a, b) {
|
|
322
|
-
const assets = mergeAssets(a.assets, b.assets);
|
|
323
|
-
const assetTypes = mergeStrings(a.assetTypes, b.assetTypes, assets ? deriveAssetTypes(assets) : undefined);
|
|
324
|
-
return normalizeStash({
|
|
325
|
-
id: a.id,
|
|
326
|
-
name: a.name,
|
|
327
|
-
description: a.description ?? b.description,
|
|
328
|
-
ref: a.ref,
|
|
329
|
-
source: a.source,
|
|
330
|
-
homepage: a.homepage ?? b.homepage,
|
|
331
|
-
tags: mergeStrings(a.tags, b.tags),
|
|
332
|
-
assetTypes,
|
|
333
|
-
assets,
|
|
334
|
-
author: a.author ?? b.author,
|
|
335
|
-
license: a.license ?? b.license,
|
|
336
|
-
latestVersion: a.latestVersion ?? b.latestVersion,
|
|
337
|
-
});
|
|
338
|
-
}
|
|
339
|
-
function mergeAssets(a, b) {
|
|
340
|
-
if (!a && !b)
|
|
341
|
-
return undefined;
|
|
342
|
-
const merged = new Map();
|
|
343
|
-
for (const asset of [...(a ?? []), ...(b ?? [])]) {
|
|
344
|
-
const key = `${asset.type}:${asset.name}`;
|
|
345
|
-
if (!merged.has(key))
|
|
346
|
-
merged.set(key, asset);
|
|
347
|
-
}
|
|
348
|
-
const values = [...merged.values()];
|
|
349
|
-
return values.length > 0 ? sortAssets(values) : undefined;
|
|
350
|
-
}
|
|
351
|
-
function mergeStrings(...values) {
|
|
352
|
-
const merged = [...new Set(values.flatMap((value) => value ?? []).filter((value) => value.trim().length > 0))].sort();
|
|
353
|
-
return merged.length > 0 ? merged : undefined;
|
|
354
|
-
}
|
|
355
|
-
function deriveAssetTypes(assets) {
|
|
356
|
-
return mergeStrings(assets?.map((asset) => asset.type));
|
|
357
|
-
}
|
|
358
|
-
function extractNonReservedKeywords(value) {
|
|
359
|
-
if (!Array.isArray(value))
|
|
360
|
-
return undefined;
|
|
361
|
-
const filtered = value
|
|
362
|
-
.filter((item) => typeof item === "string")
|
|
363
|
-
.map((item) => item.trim())
|
|
364
|
-
.filter((item) => item.length > 0)
|
|
365
|
-
.filter((item) => !REQUIRED_KEYWORDS.includes(item.toLowerCase()));
|
|
366
|
-
return filtered.length > 0 ? filtered : undefined;
|
|
367
|
-
}
|
|
368
|
-
function normalizeStash(stash) {
|
|
369
|
-
const assets = stash.assets ? sortAssets(stash.assets) : undefined;
|
|
370
|
-
return {
|
|
371
|
-
...stash,
|
|
372
|
-
...(stash.tags && stash.tags.length > 0 ? { tags: stash.tags } : {}),
|
|
373
|
-
...(stash.assetTypes && stash.assetTypes.length > 0 ? { assetTypes: stash.assetTypes } : {}),
|
|
374
|
-
...(assets && assets.length > 0 ? { assets } : {}),
|
|
375
|
-
};
|
|
376
|
-
}
|
|
377
|
-
function sortAssets(assets) {
|
|
378
|
-
return [...assets].sort((a, b) => `${a.type}:${a.name}`.localeCompare(`${b.type}:${b.name}`));
|
|
379
|
-
}
|
|
380
|
-
function trimTrailingSlash(value) {
|
|
381
|
-
return value.replace(/\/+$/, "");
|
|
382
|
-
}
|