akm-cli 0.9.0-beta.9 → 0.9.0-rc.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/CHANGELOG.md +715 -0
- package/README.md +12 -4
- package/dist/akm +38 -0
- package/dist/akm-migrate-storage +38 -0
- package/dist/assets/help/help-improve.md +9 -6
- package/dist/assets/hints/cli-hints-full.md +6 -5
- package/dist/assets/profiles/default.json +9 -4
- package/dist/assets/profiles/frequent.json +1 -1
- package/dist/assets/profiles/memory-focus.json +1 -1
- package/dist/assets/profiles/proactive-maintenance.json +25 -0
- package/dist/assets/profiles/quick.json +1 -1
- package/dist/assets/profiles/recombine-only.json +21 -0
- package/dist/assets/profiles/reflect-distill.json +30 -0
- package/dist/assets/profiles/synthesize.json +15 -0
- package/dist/assets/profiles/thorough.json +1 -1
- package/dist/assets/prompts/consolidate-system.md +23 -0
- package/dist/assets/prompts/contradiction-judge.md +33 -0
- package/dist/assets/prompts/distill-knowledge-system.md +22 -0
- package/dist/assets/prompts/distill-lesson-system.md +36 -0
- package/dist/assets/prompts/extract-session.md +11 -3
- package/dist/assets/prompts/graph-extract-system.md +1 -0
- package/dist/assets/prompts/graph-extract-user-prompt.md +1 -1
- package/dist/assets/prompts/memory-infer-system.md +1 -0
- package/dist/assets/prompts/memory-infer-user.md +5 -0
- package/dist/assets/prompts/metadata-enhance-system.md +1 -0
- package/dist/assets/prompts/procedural-system.md +44 -0
- package/dist/assets/prompts/recombine-system.md +40 -0
- package/dist/assets/prompts/staleness-detect-system.md +6 -0
- package/dist/assets/prompts/validate-summary-judge.md +1 -0
- package/dist/assets/prompts/workflow-unit-preamble.md +26 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +38 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +38 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +39 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +40 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +43 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +38 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +43 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +40 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +43 -0
- package/dist/assets/templates/html/health.html +281 -111
- package/dist/assets/wiki/ingest-workflow-template.md +45 -16
- package/dist/assets/wiki/schema-template.md +4 -4
- package/dist/cli/clack.js +56 -0
- package/dist/cli/config-migrate.js +7 -1
- package/dist/cli/confirm.js +1 -1
- package/dist/cli/parse-args.js +46 -1
- package/dist/cli/shared.js +28 -0
- package/dist/cli.js +25 -21
- package/dist/commands/agent/agent-dispatch.js +3 -2
- package/dist/commands/agent/agent-support.js +0 -7
- package/dist/commands/agent/contribute-cli.js +26 -7
- package/dist/commands/config-cli.js +26 -13
- package/dist/commands/env/child-env.js +47 -0
- package/dist/commands/env/env-binding.js +95 -0
- package/dist/commands/env/env-cli.js +228 -292
- package/dist/commands/env/env.js +14 -67
- package/dist/commands/env/secret-cli.js +140 -138
- package/dist/commands/feedback-cli.js +156 -155
- package/dist/commands/graph/graph-cli.js +5 -13
- package/dist/commands/graph/graph.js +3 -3
- package/dist/commands/health/advisories.js +151 -0
- package/dist/commands/health/checks.js +103 -16
- package/dist/commands/health/html-report.js +447 -81
- package/dist/commands/health/improve-metrics.js +771 -0
- package/dist/commands/health/llm-usage.js +65 -0
- package/dist/commands/health/md-report.js +103 -0
- package/dist/commands/health/metrics.js +278 -0
- package/dist/commands/health/stash-exposure.js +46 -0
- package/dist/commands/health/surfaces.js +216 -0
- package/dist/commands/health/task-runs.js +135 -0
- package/dist/commands/health/types.js +26 -0
- package/dist/commands/health/windows.js +195 -0
- package/dist/commands/health.js +91 -1091
- package/dist/commands/improve/anti-collapse.js +170 -0
- package/dist/commands/improve/calibration.js +161 -0
- package/dist/commands/improve/collapse-detector.js +421 -0
- package/dist/commands/improve/consolidate/chunking.js +141 -0
- package/dist/commands/improve/consolidate/eligibility.js +64 -0
- package/dist/commands/improve/consolidate/merge.js +145 -0
- package/dist/commands/improve/consolidate/sanitize.js +231 -0
- package/dist/commands/{lint.js → improve/consolidate/types.js} +1 -1
- package/dist/commands/improve/consolidate.js +1295 -1277
- package/dist/commands/improve/dedup.js +482 -0
- package/dist/commands/improve/distill/content-repair.js +202 -0
- package/dist/commands/improve/distill/promote-memory.js +229 -0
- package/dist/commands/improve/distill/quality-gate.js +236 -0
- package/dist/commands/improve/distill-guards.js +127 -0
- package/dist/commands/improve/distill-promotion-policy.js +826 -167
- package/dist/commands/improve/distill.js +228 -605
- package/dist/commands/improve/eligibility.js +434 -0
- package/dist/commands/improve/encoding-salience.js +205 -0
- package/dist/commands/improve/extract-cli.js +179 -59
- package/dist/commands/improve/extract-prompt.js +54 -3
- package/dist/commands/improve/extract-watch.js +140 -0
- package/dist/commands/improve/extract.js +409 -43
- package/dist/commands/improve/feedback-valence.js +54 -0
- package/dist/commands/improve/hot-probation.js +45 -0
- package/dist/commands/improve/improve-auto-accept.js +157 -10
- package/dist/commands/improve/improve-cli.js +115 -73
- package/dist/commands/improve/improve-profiles.js +28 -8
- package/dist/commands/improve/improve-result-file.js +15 -25
- package/dist/commands/improve/improve-session.js +58 -0
- package/dist/commands/improve/improve.js +485 -2764
- package/dist/commands/improve/locks.js +154 -0
- package/dist/commands/improve/loop-stages.js +1100 -0
- package/dist/commands/improve/memory/memory-belief.js +14 -15
- package/dist/commands/improve/memory/memory-contradiction-detect.js +83 -60
- package/dist/commands/improve/memory/memory-improve.js +27 -27
- package/dist/commands/improve/outcome-loop.js +270 -0
- package/dist/commands/improve/preparation.js +2002 -0
- package/dist/commands/improve/proactive-maintenance.js +37 -35
- package/dist/commands/improve/procedural.js +398 -0
- package/dist/commands/improve/recombine.js +818 -0
- package/dist/commands/improve/reflect-noise.js +0 -0
- package/dist/commands/improve/reflect.js +206 -45
- package/dist/commands/improve/salience.js +455 -0
- package/dist/commands/improve/schema-similarity-gate.js +168 -0
- package/dist/commands/improve/shared.js +51 -0
- package/dist/commands/improve/triage.js +93 -0
- package/dist/commands/lint/agent-linter.js +19 -24
- package/dist/commands/lint/base-linter.js +173 -60
- package/dist/commands/lint/command-linter.js +19 -24
- package/dist/commands/lint/env-key-rules.js +38 -1
- package/dist/commands/lint/fact-linter.js +39 -0
- package/dist/commands/lint/index.js +31 -13
- package/dist/commands/lint/memory-linter.js +1 -1
- package/dist/commands/lint/registry.js +7 -2
- package/dist/commands/lint/task-linter.js +3 -3
- package/dist/commands/lint/workflow-linter.js +26 -1
- package/dist/commands/observability-cli.js +4 -4
- package/dist/commands/proposal/drain-policies.js +13 -4
- package/dist/commands/proposal/drain.js +45 -51
- package/dist/commands/proposal/legacy-import.js +115 -0
- package/dist/commands/proposal/proposal-cli.js +24 -34
- package/dist/commands/proposal/proposal.js +2 -1
- package/dist/commands/proposal/propose.js +8 -3
- package/dist/commands/proposal/repository.js +829 -0
- package/dist/commands/proposal/validators/proposal-quality-validators.js +9 -8
- package/dist/commands/proposal/validators/proposals.js +93 -895
- package/dist/commands/read/curate.js +410 -111
- package/dist/commands/read/knowledge.js +10 -3
- package/dist/commands/read/remember-cli.js +133 -138
- package/dist/commands/read/search-cli.js +15 -8
- package/dist/commands/read/search.js +22 -11
- package/dist/commands/read/show.js +106 -14
- package/dist/commands/registry-cli.js +76 -87
- package/dist/commands/remember.js +11 -12
- package/dist/commands/sources/add-cli.js +91 -95
- package/dist/commands/sources/history.js +1 -1
- package/dist/commands/sources/init.js +66 -18
- package/dist/commands/sources/installed-stashes.js +11 -3
- package/dist/commands/sources/migration-help.js +7 -4
- package/dist/commands/sources/schema-repair.js +44 -46
- package/dist/commands/sources/self-update.js +2 -2
- package/dist/commands/sources/source-add.js +7 -3
- package/dist/commands/sources/sources-cli.js +3 -3
- package/dist/commands/sources/stash-cli.js +19 -39
- package/dist/commands/sources/stash-skeleton.js +57 -8
- package/dist/commands/tasks/default-tasks.js +15 -2
- package/dist/commands/tasks/tasks-cli.js +20 -29
- package/dist/commands/tasks/tasks.js +39 -11
- package/dist/commands/wiki-cli.js +23 -38
- package/dist/commands/workflow-cli.js +291 -13
- package/dist/core/asset/asset-registry.js +3 -1
- package/dist/core/asset/asset-spec.js +79 -5
- package/dist/core/asset/frontmatter.js +188 -167
- package/dist/core/asset/markdown.js +8 -0
- package/dist/core/authoring-rules.js +92 -0
- package/dist/core/common.js +4 -23
- package/dist/core/concurrent.js +10 -1
- package/dist/core/config/config-io.js +10 -1
- package/dist/core/config/config-migration.js +18 -40
- package/dist/core/config/config-schema.js +403 -62
- package/dist/core/config/config-types.js +3 -3
- package/dist/core/config/config.js +67 -22
- package/dist/core/deep-merge.js +38 -0
- package/dist/core/errors.js +1 -0
- package/dist/core/eval/rank-metrics.js +113 -0
- package/dist/core/events.js +4 -7
- package/dist/core/improve-types.js +47 -8
- package/dist/core/json-schema.js +142 -0
- package/dist/core/logs-db.js +14 -75
- package/dist/core/parse.js +36 -16
- package/dist/core/paths.js +18 -18
- package/dist/core/standards/resolve-standards-context.js +87 -0
- package/dist/core/standards/resolve-stash-standards.js +99 -0
- package/dist/core/standards/resolve-type-conventions.js +66 -0
- package/dist/core/state/migrations.js +770 -0
- package/dist/core/state-db.js +132 -1126
- package/dist/core/structured.js +69 -0
- package/dist/core/time.js +53 -0
- package/dist/core/warn.js +21 -0
- package/dist/core/write-source.js +37 -0
- package/dist/indexer/db/db.js +261 -770
- package/dist/indexer/db/entry-mapper.js +41 -0
- package/dist/indexer/db/graph-db.js +129 -86
- package/dist/indexer/db/llm-cache.js +2 -2
- package/dist/indexer/db/schema.js +516 -0
- package/dist/indexer/ensure-index.js +36 -92
- package/dist/indexer/feedback/utility-policy.js +75 -0
- package/dist/indexer/graph/graph-boost.js +51 -41
- package/dist/indexer/graph/graph-extraction.js +207 -4
- package/dist/indexer/index-writer-lock.js +18 -11
- package/dist/indexer/index-written-assets.js +105 -0
- package/dist/indexer/indexer.js +182 -204
- package/dist/indexer/passes/dir-staleness.js +114 -0
- package/dist/indexer/passes/memory-inference.js +13 -5
- package/dist/indexer/passes/metadata.js +20 -0
- package/dist/indexer/read-preflight.js +23 -0
- package/dist/indexer/search/db-search.js +89 -13
- package/dist/indexer/search/fts-query.js +51 -0
- package/dist/indexer/search/ranking-contributors.js +95 -9
- package/dist/indexer/search/ranking.js +79 -3
- package/dist/indexer/search/search-fields.js +6 -0
- package/dist/indexer/search/search-source.js +32 -21
- package/dist/indexer/search/semantic-status.js +4 -0
- package/dist/indexer/walk/matchers.js +48 -0
- package/dist/indexer/walk/walker.js +21 -13
- package/dist/integrations/agent/builders.js +41 -13
- package/dist/integrations/agent/config.js +20 -59
- package/dist/integrations/agent/detect.js +9 -0
- package/dist/integrations/agent/index.js +3 -19
- package/dist/integrations/agent/model-aliases.js +16 -2
- package/dist/integrations/agent/profiles.js +79 -6
- package/dist/integrations/agent/prompts.js +75 -9
- package/dist/integrations/agent/runner-dispatch.js +83 -0
- package/dist/integrations/agent/runner.js +13 -9
- package/dist/integrations/agent/spawn.js +206 -81
- package/dist/integrations/harnesses/aider/agent-builder.js +113 -0
- package/dist/integrations/harnesses/aider/index.js +58 -0
- package/dist/integrations/harnesses/aider/result-extractor.js +53 -0
- package/dist/integrations/harnesses/amazonq/agent-builder.js +153 -0
- package/dist/integrations/harnesses/amazonq/index.js +59 -0
- package/dist/integrations/harnesses/amazonq/result-extractor.js +48 -0
- package/dist/integrations/harnesses/claude/agent-builder.js +46 -7
- package/dist/integrations/harnesses/claude/index.js +27 -23
- package/dist/integrations/harnesses/claude/result-extractor.js +52 -0
- package/dist/integrations/harnesses/claude/session-log.js +10 -0
- package/dist/integrations/harnesses/codex/agent-builder.js +137 -0
- package/dist/integrations/harnesses/codex/index.js +63 -0
- package/dist/integrations/harnesses/codex/result-extractor.js +73 -0
- package/dist/integrations/harnesses/copilot/agent-builder.js +122 -0
- package/dist/integrations/harnesses/copilot/index.js +60 -0
- package/dist/integrations/harnesses/copilot/result-extractor.js +151 -0
- package/dist/integrations/harnesses/gemini/agent-builder.js +121 -0
- package/dist/integrations/harnesses/gemini/index.js +60 -0
- package/dist/integrations/harnesses/gemini/result-extractor.js +121 -0
- package/dist/integrations/harnesses/index.js +28 -7
- package/dist/integrations/harnesses/opencode/agent-builder.js +1 -1
- package/dist/integrations/harnesses/opencode/index.js +17 -16
- package/dist/integrations/harnesses/opencode/session-log.js +173 -3
- package/dist/integrations/harnesses/opencode-sdk/harness.js +65 -0
- package/dist/integrations/harnesses/opencode-sdk/index.js +10 -34
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +642 -71
- package/dist/integrations/harnesses/openhands/agent-builder.js +126 -0
- package/dist/integrations/harnesses/openhands/index.js +58 -0
- package/dist/integrations/harnesses/openhands/result-extractor.js +103 -0
- package/dist/integrations/harnesses/pi/agent-builder.js +104 -0
- package/dist/integrations/harnesses/pi/index.js +58 -0
- package/dist/integrations/harnesses/pi/result-extractor.js +135 -0
- package/dist/integrations/harnesses/types.js +8 -0
- package/dist/integrations/session-logs/index.js +40 -11
- package/dist/llm/call-ai.js +2 -2
- package/dist/llm/client.js +34 -11
- package/dist/llm/embedder.js +67 -4
- package/dist/llm/embedders/cache.js +3 -1
- package/dist/llm/embedders/deterministic.js +66 -0
- package/dist/llm/embedders/local.js +73 -3
- package/dist/llm/feature-gate.js +16 -15
- package/dist/llm/graph-extract.js +67 -44
- package/dist/llm/memory-infer-impl.js +138 -0
- package/dist/llm/memory-infer.js +1 -127
- package/dist/llm/metadata-enhance.js +44 -31
- package/dist/llm/structured-call.js +49 -0
- package/dist/migrate-storage-node.mjs +8 -0
- package/dist/output/context.js +5 -5
- package/dist/output/renderers.js +87 -15
- package/dist/output/shapes/curate.js +14 -2
- package/dist/output/shapes/helpers.js +0 -3
- package/dist/output/shapes/passthrough.js +6 -1
- package/dist/output/text/helpers.js +241 -2
- package/dist/output/text/workflow.js +4 -1
- package/dist/registry/providers/skills-sh.js +21 -147
- package/dist/registry/providers/static-index.js +15 -157
- package/dist/registry/resolve.js +27 -9
- package/dist/runtime.js +25 -1
- package/dist/schemas/akm-config.json +14225 -0
- package/dist/schemas/akm-workflow.json +328 -0
- package/dist/scripts/migrate-storage.js +2743 -8390
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +1652 -607
- package/dist/setup/detect.js +9 -0
- package/dist/setup/legacy-config.js +106 -0
- package/dist/setup/prompt.js +57 -0
- package/dist/setup/providers.js +14 -0
- package/dist/setup/registry-stash-loader.js +12 -0
- package/dist/setup/semantic-assets.js +124 -0
- package/dist/setup/setup.js +52 -1614
- package/dist/setup/steps/connection.js +734 -0
- package/dist/setup/steps/output.js +31 -0
- package/dist/setup/steps/platforms.js +124 -0
- package/dist/setup/steps/semantic.js +27 -0
- package/dist/setup/steps/sources.js +222 -0
- package/dist/setup/steps/stashdir.js +42 -0
- package/dist/setup/steps/tasks.js +152 -0
- package/dist/sources/include.js +6 -2
- package/dist/sources/providers/filesystem.js +0 -1
- package/dist/sources/providers/git-install.js +210 -0
- package/dist/sources/providers/git-provider.js +234 -0
- package/dist/sources/providers/git-stash.js +248 -0
- package/dist/sources/providers/git.js +10 -661
- package/dist/sources/providers/npm.js +2 -6
- package/dist/sources/providers/provider-utils.js +13 -7
- package/dist/sources/providers/sync-from-ref.js +9 -1
- package/dist/sources/providers/website.js +9 -5
- package/dist/sources/website-ingest.js +187 -29
- package/dist/sources/wiki-fetchers/registry.js +53 -0
- package/dist/sources/wiki-fetchers/youtube.js +239 -0
- package/dist/storage/database.js +45 -10
- package/dist/storage/managed-db.js +82 -0
- package/dist/storage/repositories/canaries-repository.js +107 -0
- package/dist/storage/repositories/consolidation-repository.js +38 -0
- package/dist/storage/repositories/embeddings-repository.js +72 -0
- package/dist/storage/repositories/events-repository.js +187 -0
- package/dist/storage/repositories/extract-sessions-repository.js +96 -0
- package/dist/storage/repositories/improve-runs-repository.js +146 -0
- package/dist/storage/repositories/index-db.js +14 -8
- package/dist/storage/repositories/proposals-repository.js +220 -0
- package/dist/storage/repositories/recombine-repository.js +213 -0
- package/dist/storage/repositories/registry-cache.js +93 -0
- package/dist/storage/repositories/registry-index-cache-repository.js +46 -0
- package/dist/storage/repositories/task-history-repository.js +93 -0
- package/dist/storage/repositories/workflow-runs-repository.js +189 -1
- package/dist/storage/sqlite-pragmas.js +146 -0
- package/dist/tasks/backends/cron.js +1 -1
- package/dist/tasks/backends/index.js +9 -0
- package/dist/tasks/backends/launchd.js +1 -1
- package/dist/tasks/backends/schtasks.js +1 -1
- package/dist/tasks/{resolveAkmBin.js → resolve-akm-bin.js} +2 -2
- package/dist/tasks/runner.js +15 -13
- package/dist/text-import-hook.mjs +1 -1
- package/dist/wiki/wiki.js +52 -11
- package/dist/workflows/authoring/authoring.js +123 -10
- package/dist/workflows/authoring/workflow-program-template.yaml +31 -0
- package/dist/workflows/cli.js +5 -0
- package/dist/workflows/db.js +138 -4
- package/dist/workflows/exec/brief.js +484 -0
- package/dist/workflows/exec/native-executor.js +975 -0
- package/dist/workflows/exec/param-secrets.js +115 -0
- package/dist/workflows/exec/report.js +1295 -0
- package/dist/workflows/exec/run-workflow.js +596 -0
- package/dist/workflows/exec/scheduler.js +100 -0
- package/dist/workflows/exec/step-work.js +1156 -0
- package/dist/workflows/exec/unit-writer.js +23 -0
- package/dist/workflows/exec/watch.js +116 -0
- package/dist/workflows/exec/worktree.js +171 -0
- package/dist/workflows/ir/compile.js +388 -0
- package/dist/workflows/ir/params.js +54 -0
- package/dist/workflows/ir/plan-hash.js +33 -0
- package/dist/workflows/ir/schema.js +4 -0
- package/dist/workflows/parser.js +3 -1
- package/dist/workflows/program/expressions.js +369 -0
- package/dist/workflows/program/parser.js +760 -0
- package/dist/workflows/program/project.js +105 -0
- package/dist/workflows/program/schema.js +54 -0
- package/dist/workflows/renderer.js +82 -5
- package/dist/workflows/runtime/agent-identity.js +59 -14
- package/dist/workflows/runtime/runs.js +248 -153
- package/dist/workflows/runtime/unit-checkin.js +45 -0
- package/dist/workflows/runtime/workflow-asset-loader.js +188 -0
- package/dist/workflows/validate-summary.js +26 -10
- package/dist/workflows/validator.js +1 -1
- package/docs/README.md +69 -18
- package/docs/data-and-telemetry.md +7 -5
- package/docs/migration/release-notes/0.7.0.md +1 -1
- package/docs/migration/release-notes/0.9.0-beta.60.md +19 -0
- package/docs/migration/release-notes/0.9.0.md +39 -0
- package/package.json +10 -10
- package/dist/assets/tasks/core/update-stashes.yml +0 -4
- package/dist/commands/db-cli.js +0 -23
- package/dist/indexer/db/db-backup.js +0 -376
- package/dist/indexer/passes/staleness-detect.js +0 -488
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
+
import { createRequire } from "node:module";
|
|
3
4
|
var __create = Object.create;
|
|
4
5
|
var __getProtoOf = Object.getPrototypeOf;
|
|
5
6
|
var __defProp = Object.defineProperty;
|
|
@@ -32,23 +33,53 @@ var __toESM = (mod, isNodeMode, target) => {
|
|
|
32
33
|
};
|
|
33
34
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
34
35
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
35
|
-
var __require = import.meta.
|
|
36
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
37
|
+
|
|
38
|
+
// src/core/warn.ts
|
|
39
|
+
import fs from "node:fs";
|
|
40
|
+
function appendToLogFile(level, args) {
|
|
41
|
+
if (!logFilePath)
|
|
42
|
+
return;
|
|
43
|
+
const ts = new Date().toISOString();
|
|
44
|
+
const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
|
|
45
|
+
try {
|
|
46
|
+
fs.appendFileSync(logFilePath, `[${ts}] [${level}] ${msg}
|
|
47
|
+
`);
|
|
48
|
+
} catch (e) {
|
|
49
|
+
process.stderr.write(`[akm:warn] log-file write failed (${logFilePath}): ${e}
|
|
50
|
+
`);
|
|
51
|
+
process.stderr.write(`[${ts}] [${level}] ${msg}
|
|
52
|
+
`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function warn(...args) {
|
|
56
|
+
if (sinkOverride) {
|
|
57
|
+
sinkOverride("warn", args);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
appendToLogFile("WARN", args);
|
|
61
|
+
if (!quiet) {
|
|
62
|
+
console.warn(...args);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
var quiet = false, logFilePath, sinkOverride;
|
|
66
|
+
var init_warn = () => {};
|
|
36
67
|
|
|
37
68
|
// node_modules/dotenv/lib/main.js
|
|
38
69
|
var require_main = __commonJS((exports, module) => {
|
|
39
|
-
var
|
|
40
|
-
var
|
|
70
|
+
var fs3 = __require("fs");
|
|
71
|
+
var path2 = __require("path");
|
|
41
72
|
var os = __require("os");
|
|
42
73
|
var crypto = __require("crypto");
|
|
43
74
|
var TIPS = [
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
75
|
+
"◈ encrypted .env [www.dotenvx.com]",
|
|
76
|
+
"◈ secrets for agents [www.dotenvx.com]",
|
|
77
|
+
"⌁ auth for agents [www.vestauth.com]",
|
|
78
|
+
"⌘ custom filepath { path: '/custom/path/.env' }",
|
|
79
|
+
"⌘ enable debugging { debug: true }",
|
|
80
|
+
"⌘ override existing { override: true }",
|
|
81
|
+
"⌘ suppress logs { quiet: true }",
|
|
82
|
+
"⌘ multiple files { path: ['.env.local', '.env'] }"
|
|
52
83
|
];
|
|
53
84
|
function _getRandomTip() {
|
|
54
85
|
return TIPS[Math.floor(Math.random() * TIPS.length)];
|
|
@@ -115,13 +146,13 @@ var require_main = __commonJS((exports, module) => {
|
|
|
115
146
|
return DotenvModule.parse(decrypted);
|
|
116
147
|
}
|
|
117
148
|
function _warn(message) {
|
|
118
|
-
console.error(
|
|
149
|
+
console.error(`⚠ ${message}`);
|
|
119
150
|
}
|
|
120
151
|
function _debug(message) {
|
|
121
|
-
console.log(
|
|
152
|
+
console.log(`┆ ${message}`);
|
|
122
153
|
}
|
|
123
154
|
function _log(message) {
|
|
124
|
-
console.log(
|
|
155
|
+
console.log(`◇ ${message}`);
|
|
125
156
|
}
|
|
126
157
|
function _dotenvKey(options) {
|
|
127
158
|
if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) {
|
|
@@ -170,7 +201,7 @@ var require_main = __commonJS((exports, module) => {
|
|
|
170
201
|
if (options && options.path && options.path.length > 0) {
|
|
171
202
|
if (Array.isArray(options.path)) {
|
|
172
203
|
for (const filepath of options.path) {
|
|
173
|
-
if (
|
|
204
|
+
if (fs3.existsSync(filepath)) {
|
|
174
205
|
possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
|
|
175
206
|
}
|
|
176
207
|
}
|
|
@@ -178,20 +209,20 @@ var require_main = __commonJS((exports, module) => {
|
|
|
178
209
|
possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
|
|
179
210
|
}
|
|
180
211
|
} else {
|
|
181
|
-
possibleVaultPath =
|
|
212
|
+
possibleVaultPath = path2.resolve(process.cwd(), ".env.vault");
|
|
182
213
|
}
|
|
183
|
-
if (
|
|
214
|
+
if (fs3.existsSync(possibleVaultPath)) {
|
|
184
215
|
return possibleVaultPath;
|
|
185
216
|
}
|
|
186
217
|
return null;
|
|
187
218
|
}
|
|
188
219
|
function _resolveHome(envPath) {
|
|
189
|
-
return envPath[0] === "~" ?
|
|
220
|
+
return envPath[0] === "~" ? path2.join(os.homedir(), envPath.slice(1)) : envPath;
|
|
190
221
|
}
|
|
191
222
|
function _configVault(options) {
|
|
192
223
|
const debug = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || options && options.debug);
|
|
193
|
-
const
|
|
194
|
-
if (debug || !
|
|
224
|
+
const quiet2 = parseBoolean(process.env.DOTENV_CONFIG_QUIET || options && options.quiet);
|
|
225
|
+
if (debug || !quiet2) {
|
|
195
226
|
_log("loading env from encrypted .env.vault");
|
|
196
227
|
}
|
|
197
228
|
const parsed = DotenvModule._parseVault(options);
|
|
@@ -203,14 +234,14 @@ var require_main = __commonJS((exports, module) => {
|
|
|
203
234
|
return { parsed };
|
|
204
235
|
}
|
|
205
236
|
function configDotenv(options) {
|
|
206
|
-
const dotenvPath =
|
|
237
|
+
const dotenvPath = path2.resolve(process.cwd(), ".env");
|
|
207
238
|
let encoding = "utf8";
|
|
208
239
|
let processEnv = process.env;
|
|
209
240
|
if (options && options.processEnv != null) {
|
|
210
241
|
processEnv = options.processEnv;
|
|
211
242
|
}
|
|
212
243
|
let debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || options && options.debug);
|
|
213
|
-
let
|
|
244
|
+
let quiet2 = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || options && options.quiet);
|
|
214
245
|
if (options && options.encoding) {
|
|
215
246
|
encoding = options.encoding;
|
|
216
247
|
} else {
|
|
@@ -231,26 +262,26 @@ var require_main = __commonJS((exports, module) => {
|
|
|
231
262
|
}
|
|
232
263
|
let lastError;
|
|
233
264
|
const parsedAll = {};
|
|
234
|
-
for (const
|
|
265
|
+
for (const path3 of optionPaths) {
|
|
235
266
|
try {
|
|
236
|
-
const parsed = DotenvModule.parse(
|
|
267
|
+
const parsed = DotenvModule.parse(fs3.readFileSync(path3, { encoding }));
|
|
237
268
|
DotenvModule.populate(parsedAll, parsed, options);
|
|
238
269
|
} catch (e) {
|
|
239
270
|
if (debug) {
|
|
240
|
-
_debug(`failed to load ${
|
|
271
|
+
_debug(`failed to load ${path3} ${e.message}`);
|
|
241
272
|
}
|
|
242
273
|
lastError = e;
|
|
243
274
|
}
|
|
244
275
|
}
|
|
245
276
|
const populated = DotenvModule.populate(processEnv, parsedAll, options);
|
|
246
277
|
debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || debug);
|
|
247
|
-
|
|
248
|
-
if (debug || !
|
|
278
|
+
quiet2 = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || quiet2);
|
|
279
|
+
if (debug || !quiet2) {
|
|
249
280
|
const keysCount = Object.keys(populated).length;
|
|
250
281
|
const shortPaths = [];
|
|
251
282
|
for (const filePath of optionPaths) {
|
|
252
283
|
try {
|
|
253
|
-
const relative =
|
|
284
|
+
const relative = path2.relative(process.cwd(), filePath);
|
|
254
285
|
shortPaths.push(relative);
|
|
255
286
|
} catch (e) {
|
|
256
287
|
if (debug) {
|
|
@@ -363,8 +394,9 @@ var init_errors = __esm(() => {
|
|
|
363
394
|
EMBEDDING_NOT_CONFIGURED: 'Run `akm config set embedding \'{"endpoint":"...","model":"..."}\'` to enable embeddings.',
|
|
364
395
|
LLM_NOT_CONFIGURED: 'Run `akm setup` or `akm config set profiles.llm.default \'{"endpoint":"...","model":"..."}\' to configure an LLM profile.',
|
|
365
396
|
TEST_ISOLATION_MISSING: "Under bun test, when AKM_STASH_DIR is set you MUST also set XDG_DATA_HOME (or AKM_DATA_DIR) and XDG_STATE_HOME (or AKM_STATE_DIR) to temp directories so the test does not touch the developer's real ~/.local/share/akm or ~/.local/state/akm.",
|
|
366
|
-
SETUP_TMP_STASH_REFUSED: "Use a persistent directory, or set AKM_FORCE_SETUP_TMP_STASH=1 to opt in to a sandboxed setup (setup also pre-sets AKM_STASH_DIR so config and cache writes auto-isolate into $stashDir/.akm/
|
|
367
|
-
UNSAFE_STASH_DIR: "Choose a path inside your home directory (e.g. ~/akm) or another empty workspace. The stash directory cannot be the filesystem root, your home directory itself, or a sensitive system path like /etc, /var, ~/.config, or ~/.ssh."
|
|
397
|
+
SETUP_TMP_STASH_REFUSED: "Use a persistent directory, or set AKM_FORCE_SETUP_TMP_STASH=1 to opt in to a sandboxed setup (setup also pre-sets AKM_STASH_DIR so config and cache writes auto-isolate into $stashDir/.akm/ — host config is preserved).",
|
|
398
|
+
UNSAFE_STASH_DIR: "Choose a path inside your home directory (e.g. ~/akm) or another empty workspace. The stash directory cannot be the filesystem root, your home directory itself, or a sensitive system path like /etc, /var, ~/.config, or ~/.ssh.",
|
|
399
|
+
UNKNOWN_IMPROVE_PROFILE: "Pass one of the listed profile names to `--profile`, or define it under `profiles.improve` in your config. Names are case-sensitive."
|
|
368
400
|
};
|
|
369
401
|
USAGE_HINTS = {
|
|
370
402
|
INVALID_FLAG_VALUE: "Run `akm <command> --help` to see accepted values.",
|
|
@@ -412,7 +444,7 @@ var init_errors = __esm(() => {
|
|
|
412
444
|
});
|
|
413
445
|
|
|
414
446
|
// src/commands/env/env.ts
|
|
415
|
-
import
|
|
447
|
+
import fs3 from "node:fs";
|
|
416
448
|
function scanKeys(text) {
|
|
417
449
|
const keys = [];
|
|
418
450
|
const seen = new Set;
|
|
@@ -428,21 +460,11 @@ function scanKeys(text) {
|
|
|
428
460
|
}
|
|
429
461
|
return keys;
|
|
430
462
|
}
|
|
431
|
-
function scanComments(text) {
|
|
432
|
-
const comments = [];
|
|
433
|
-
for (const line of text.split(/\r?\n/)) {
|
|
434
|
-
const trimmed = line.trimStart();
|
|
435
|
-
if (trimmed.startsWith("#")) {
|
|
436
|
-
comments.push(trimmed.slice(1).trimStart());
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
return comments;
|
|
440
|
-
}
|
|
441
463
|
function listKeys(envPath) {
|
|
442
|
-
if (!
|
|
443
|
-
return { keys: []
|
|
444
|
-
const text =
|
|
445
|
-
return { keys: scanKeys(text)
|
|
464
|
+
if (!fs3.existsSync(envPath))
|
|
465
|
+
return { keys: [] };
|
|
466
|
+
const text = fs3.readFileSync(envPath, "utf8");
|
|
467
|
+
return { keys: scanKeys(text) };
|
|
446
468
|
}
|
|
447
469
|
var import_dotenv, ASSIGN_RE;
|
|
448
470
|
var init_env = __esm(() => {
|
|
@@ -452,251 +474,6 @@ var init_env = __esm(() => {
|
|
|
452
474
|
ASSIGN_RE = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/;
|
|
453
475
|
});
|
|
454
476
|
|
|
455
|
-
// src/core/asset/frontmatter.ts
|
|
456
|
-
function parseFrontmatter(raw) {
|
|
457
|
-
const parsedBlock = parseFrontmatterBlock(raw);
|
|
458
|
-
if (!parsedBlock) {
|
|
459
|
-
return { data: {}, content: raw, frontmatter: null, bodyStartLine: 1 };
|
|
460
|
-
}
|
|
461
|
-
const data = {};
|
|
462
|
-
let currentKey = null;
|
|
463
|
-
let mode = "scalar";
|
|
464
|
-
let nested = null;
|
|
465
|
-
let currentList = null;
|
|
466
|
-
let blockLines = null;
|
|
467
|
-
let blockChomping = "clip";
|
|
468
|
-
const flushPending = () => {
|
|
469
|
-
if (mode === "pending" && currentKey !== null) {
|
|
470
|
-
data[currentKey] = "";
|
|
471
|
-
}
|
|
472
|
-
};
|
|
473
|
-
const flushBlock = () => {
|
|
474
|
-
if (mode !== "block" || currentKey === null || blockLines === null)
|
|
475
|
-
return;
|
|
476
|
-
const deindented = blockLines.map((l) => l.startsWith(" ") ? l.slice(2) : l);
|
|
477
|
-
if (blockChomping === "keep") {
|
|
478
|
-
data[currentKey] = deindented.join(`
|
|
479
|
-
`);
|
|
480
|
-
} else if (blockChomping === "strip") {
|
|
481
|
-
data[currentKey] = deindented.join(`
|
|
482
|
-
`).replace(/\n+$/, "");
|
|
483
|
-
} else {
|
|
484
|
-
data[currentKey] = `${deindented.join(`
|
|
485
|
-
`).replace(/\n+$/, "")}
|
|
486
|
-
`;
|
|
487
|
-
}
|
|
488
|
-
};
|
|
489
|
-
for (const line of parsedBlock.frontmatter.split(/\r?\n/)) {
|
|
490
|
-
if (mode === "block") {
|
|
491
|
-
if (line.startsWith(" ") || line === "") {
|
|
492
|
-
blockLines.push(line);
|
|
493
|
-
continue;
|
|
494
|
-
}
|
|
495
|
-
flushBlock();
|
|
496
|
-
mode = "scalar";
|
|
497
|
-
blockLines = null;
|
|
498
|
-
}
|
|
499
|
-
const seqItem = line.match(/^(?: {2})?- (.*)$/);
|
|
500
|
-
if (seqItem && currentKey !== null && (mode === "list" || mode === "pending")) {
|
|
501
|
-
if (mode === "pending") {
|
|
502
|
-
currentList = [];
|
|
503
|
-
data[currentKey] = currentList;
|
|
504
|
-
mode = "list";
|
|
505
|
-
}
|
|
506
|
-
currentList.push(parseYamlScalar(seqItem[1].trim()));
|
|
507
|
-
continue;
|
|
508
|
-
}
|
|
509
|
-
if (mode === "scalar" && currentKey !== null && /^ {2}\S/.test(line)) {
|
|
510
|
-
data[currentKey] = `${String(data[currentKey])} ${line.trim()}`;
|
|
511
|
-
continue;
|
|
512
|
-
}
|
|
513
|
-
const indented = line.match(/^ {2}(\w[\w-]*):\s*(.+)$/);
|
|
514
|
-
if (indented && currentKey !== null && (mode === "object" || mode === "pending")) {
|
|
515
|
-
if (mode === "pending") {
|
|
516
|
-
nested = {};
|
|
517
|
-
data[currentKey] = nested;
|
|
518
|
-
mode = "object";
|
|
519
|
-
}
|
|
520
|
-
nested[indented[1]] = parseYamlScalar(indented[2].trim());
|
|
521
|
-
continue;
|
|
522
|
-
}
|
|
523
|
-
const top = line.match(/^(\w[\w-]*):\s*(.*)$/);
|
|
524
|
-
if (!top) {
|
|
525
|
-
continue;
|
|
526
|
-
}
|
|
527
|
-
flushPending();
|
|
528
|
-
currentKey = top[1];
|
|
529
|
-
const value = top[2].trim();
|
|
530
|
-
if (value === "|" || value === "|-" || value === "|+") {
|
|
531
|
-
mode = "block";
|
|
532
|
-
blockLines = [];
|
|
533
|
-
blockChomping = value === "|-" ? "strip" : value === "|+" ? "keep" : "clip";
|
|
534
|
-
nested = null;
|
|
535
|
-
currentList = null;
|
|
536
|
-
} else if (value === "") {
|
|
537
|
-
mode = "pending";
|
|
538
|
-
nested = null;
|
|
539
|
-
currentList = null;
|
|
540
|
-
} else if (value.startsWith("[") && value.endsWith("]")) {
|
|
541
|
-
mode = "list";
|
|
542
|
-
nested = null;
|
|
543
|
-
currentList = null;
|
|
544
|
-
currentList = parseFlowArray(value);
|
|
545
|
-
data[currentKey] = currentList;
|
|
546
|
-
} else {
|
|
547
|
-
mode = "scalar";
|
|
548
|
-
nested = null;
|
|
549
|
-
currentList = null;
|
|
550
|
-
data[currentKey] = parseYamlScalar(value);
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
if (mode === "block") {
|
|
554
|
-
flushBlock();
|
|
555
|
-
}
|
|
556
|
-
flushPending();
|
|
557
|
-
return {
|
|
558
|
-
data,
|
|
559
|
-
content: parsedBlock.content,
|
|
560
|
-
frontmatter: parsedBlock.frontmatter,
|
|
561
|
-
bodyStartLine: parsedBlock.bodyStartLine
|
|
562
|
-
};
|
|
563
|
-
}
|
|
564
|
-
function parseFlowArray(value) {
|
|
565
|
-
const inner = value.slice(1, -1).trim();
|
|
566
|
-
if (!inner)
|
|
567
|
-
return [];
|
|
568
|
-
return inner.split(",").map((item) => parseYamlScalar(item.trim()));
|
|
569
|
-
}
|
|
570
|
-
function parseFrontmatterBlock(raw) {
|
|
571
|
-
const match = raw.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r\n|\r|\n|$)([\s\S]*)$/);
|
|
572
|
-
if (!match)
|
|
573
|
-
return null;
|
|
574
|
-
const frontmatter = match[1].replace(/\r/g, "");
|
|
575
|
-
const content = match[2];
|
|
576
|
-
return {
|
|
577
|
-
frontmatter,
|
|
578
|
-
content,
|
|
579
|
-
bodyStartLine: countLines(raw.slice(0, match[0].length - match[2].length)) + 1
|
|
580
|
-
};
|
|
581
|
-
}
|
|
582
|
-
function countLines(text) {
|
|
583
|
-
if (text.length === 0)
|
|
584
|
-
return 0;
|
|
585
|
-
return text.split(/\r?\n/).length - 1;
|
|
586
|
-
}
|
|
587
|
-
function parseYamlScalar(value) {
|
|
588
|
-
if (value === "")
|
|
589
|
-
return "";
|
|
590
|
-
if (value === "true")
|
|
591
|
-
return true;
|
|
592
|
-
if (value === "false")
|
|
593
|
-
return false;
|
|
594
|
-
const asNumber = Number(value);
|
|
595
|
-
if (!Number.isNaN(asNumber))
|
|
596
|
-
return asNumber;
|
|
597
|
-
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
598
|
-
return value.slice(1, -1);
|
|
599
|
-
}
|
|
600
|
-
return value;
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
// src/core/asset/markdown.ts
|
|
604
|
-
function parseMarkdownToc(content) {
|
|
605
|
-
const lines = content.split(/\r?\n/);
|
|
606
|
-
const headings = [];
|
|
607
|
-
const parsed = parseFrontmatter(content);
|
|
608
|
-
const start = parsed.frontmatter ? parsed.bodyStartLine - 1 : 0;
|
|
609
|
-
for (let i = start;i < lines.length; i++) {
|
|
610
|
-
const match = lines[i].match(/^(#{1,6})\s+(.+)$/);
|
|
611
|
-
if (match) {
|
|
612
|
-
headings.push({
|
|
613
|
-
level: match[1].length,
|
|
614
|
-
text: match[2].replace(/\s+#+\s*$/, "").trim(),
|
|
615
|
-
line: i + 1
|
|
616
|
-
});
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
return { headings, totalLines: lines.length };
|
|
620
|
-
}
|
|
621
|
-
var init_markdown = () => {};
|
|
622
|
-
|
|
623
|
-
// src/core/warn.ts
|
|
624
|
-
var init_warn = () => {};
|
|
625
|
-
|
|
626
|
-
// src/indexer/walk/file-context.ts
|
|
627
|
-
var renderers;
|
|
628
|
-
var init_file_context = __esm(() => {
|
|
629
|
-
init_common();
|
|
630
|
-
renderers = new Map;
|
|
631
|
-
});
|
|
632
|
-
|
|
633
|
-
// src/indexer/passes/metadata-contributors.ts
|
|
634
|
-
function registerMetadataContributor(contributor) {
|
|
635
|
-
contributors.push(contributor);
|
|
636
|
-
}
|
|
637
|
-
var contributors;
|
|
638
|
-
var init_metadata_contributors = __esm(() => {
|
|
639
|
-
contributors = [];
|
|
640
|
-
});
|
|
641
|
-
|
|
642
|
-
// src/indexer/passes/metadata.ts
|
|
643
|
-
import fs2 from "fs";
|
|
644
|
-
function extractDescriptionFromComments(filePath) {
|
|
645
|
-
let content;
|
|
646
|
-
try {
|
|
647
|
-
content = fs2.readFileSync(filePath, "utf8");
|
|
648
|
-
} catch {
|
|
649
|
-
return null;
|
|
650
|
-
}
|
|
651
|
-
const lines = content.split(/\r?\n/).slice(0, 50);
|
|
652
|
-
const blockStart = lines.findIndex((l) => /^\s*\/\*\*/.test(l));
|
|
653
|
-
if (blockStart >= 0) {
|
|
654
|
-
const desc = [];
|
|
655
|
-
for (let i = blockStart;i < lines.length; i++) {
|
|
656
|
-
const line = lines[i];
|
|
657
|
-
if (i > blockStart && /\*\//.test(line))
|
|
658
|
-
break;
|
|
659
|
-
const cleaned = line.replace(/^\s*\/?\*\*?\s?/, "").replace(/\*\/\s*$/, "").trim();
|
|
660
|
-
if (cleaned)
|
|
661
|
-
desc.push(cleaned);
|
|
662
|
-
}
|
|
663
|
-
if (desc.length > 0)
|
|
664
|
-
return desc.join(" ");
|
|
665
|
-
}
|
|
666
|
-
let start = 0;
|
|
667
|
-
if (lines[0]?.startsWith("#!"))
|
|
668
|
-
start = 1;
|
|
669
|
-
const hashLines = [];
|
|
670
|
-
for (let i = start;i < lines.length; i++) {
|
|
671
|
-
const line = lines[i].trim();
|
|
672
|
-
if (line.startsWith("#") && !line.startsWith("#!")) {
|
|
673
|
-
hashLines.push(line.replace(/^#+\s*/, "").trim());
|
|
674
|
-
} else if (line === "") {} else {
|
|
675
|
-
break;
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
if (hashLines.length > 0)
|
|
679
|
-
return hashLines.join(" ");
|
|
680
|
-
return null;
|
|
681
|
-
}
|
|
682
|
-
var KNOWN_QUALITY_VALUES, warnedUnknownQualityValues, WIKI_INFRA_FILES;
|
|
683
|
-
var init_metadata = __esm(() => {
|
|
684
|
-
init_asset_spec();
|
|
685
|
-
init_common();
|
|
686
|
-
init_warn();
|
|
687
|
-
init_file_context();
|
|
688
|
-
init_metadata_contributors();
|
|
689
|
-
KNOWN_QUALITY_VALUES = new Set(["generated", "curated", "enriched", "proposed"]);
|
|
690
|
-
warnedUnknownQualityValues = new Set;
|
|
691
|
-
WIKI_INFRA_FILES = new Set(["schema.md", "index.md", "log.md"]);
|
|
692
|
-
});
|
|
693
|
-
|
|
694
|
-
// src/core/asset/asset-ref.ts
|
|
695
|
-
var init_asset_ref = __esm(() => {
|
|
696
|
-
init_common();
|
|
697
|
-
init_errors();
|
|
698
|
-
});
|
|
699
|
-
|
|
700
477
|
// node_modules/yaml/dist/nodes/identity.js
|
|
701
478
|
var require_identity = __commonJS((exports) => {
|
|
702
479
|
var ALIAS = Symbol.for("yaml.alias");
|
|
@@ -769,17 +546,17 @@ var require_visit = __commonJS((exports) => {
|
|
|
769
546
|
visit.BREAK = BREAK;
|
|
770
547
|
visit.SKIP = SKIP;
|
|
771
548
|
visit.REMOVE = REMOVE;
|
|
772
|
-
function visit_(key, node, visitor,
|
|
773
|
-
const ctrl = callVisitor(key, node, visitor,
|
|
549
|
+
function visit_(key, node, visitor, path2) {
|
|
550
|
+
const ctrl = callVisitor(key, node, visitor, path2);
|
|
774
551
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
775
|
-
replaceNode(key,
|
|
776
|
-
return visit_(key, ctrl, visitor,
|
|
552
|
+
replaceNode(key, path2, ctrl);
|
|
553
|
+
return visit_(key, ctrl, visitor, path2);
|
|
777
554
|
}
|
|
778
555
|
if (typeof ctrl !== "symbol") {
|
|
779
556
|
if (identity.isCollection(node)) {
|
|
780
|
-
|
|
557
|
+
path2 = Object.freeze(path2.concat(node));
|
|
781
558
|
for (let i = 0;i < node.items.length; ++i) {
|
|
782
|
-
const ci = visit_(i, node.items[i], visitor,
|
|
559
|
+
const ci = visit_(i, node.items[i], visitor, path2);
|
|
783
560
|
if (typeof ci === "number")
|
|
784
561
|
i = ci - 1;
|
|
785
562
|
else if (ci === BREAK)
|
|
@@ -790,13 +567,13 @@ var require_visit = __commonJS((exports) => {
|
|
|
790
567
|
}
|
|
791
568
|
}
|
|
792
569
|
} else if (identity.isPair(node)) {
|
|
793
|
-
|
|
794
|
-
const ck = visit_("key", node.key, visitor,
|
|
570
|
+
path2 = Object.freeze(path2.concat(node));
|
|
571
|
+
const ck = visit_("key", node.key, visitor, path2);
|
|
795
572
|
if (ck === BREAK)
|
|
796
573
|
return BREAK;
|
|
797
574
|
else if (ck === REMOVE)
|
|
798
575
|
node.key = null;
|
|
799
|
-
const cv = visit_("value", node.value, visitor,
|
|
576
|
+
const cv = visit_("value", node.value, visitor, path2);
|
|
800
577
|
if (cv === BREAK)
|
|
801
578
|
return BREAK;
|
|
802
579
|
else if (cv === REMOVE)
|
|
@@ -817,17 +594,17 @@ var require_visit = __commonJS((exports) => {
|
|
|
817
594
|
visitAsync.BREAK = BREAK;
|
|
818
595
|
visitAsync.SKIP = SKIP;
|
|
819
596
|
visitAsync.REMOVE = REMOVE;
|
|
820
|
-
async function visitAsync_(key, node, visitor,
|
|
821
|
-
const ctrl = await callVisitor(key, node, visitor,
|
|
597
|
+
async function visitAsync_(key, node, visitor, path2) {
|
|
598
|
+
const ctrl = await callVisitor(key, node, visitor, path2);
|
|
822
599
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
823
|
-
replaceNode(key,
|
|
824
|
-
return visitAsync_(key, ctrl, visitor,
|
|
600
|
+
replaceNode(key, path2, ctrl);
|
|
601
|
+
return visitAsync_(key, ctrl, visitor, path2);
|
|
825
602
|
}
|
|
826
603
|
if (typeof ctrl !== "symbol") {
|
|
827
604
|
if (identity.isCollection(node)) {
|
|
828
|
-
|
|
605
|
+
path2 = Object.freeze(path2.concat(node));
|
|
829
606
|
for (let i = 0;i < node.items.length; ++i) {
|
|
830
|
-
const ci = await visitAsync_(i, node.items[i], visitor,
|
|
607
|
+
const ci = await visitAsync_(i, node.items[i], visitor, path2);
|
|
831
608
|
if (typeof ci === "number")
|
|
832
609
|
i = ci - 1;
|
|
833
610
|
else if (ci === BREAK)
|
|
@@ -838,13 +615,13 @@ var require_visit = __commonJS((exports) => {
|
|
|
838
615
|
}
|
|
839
616
|
}
|
|
840
617
|
} else if (identity.isPair(node)) {
|
|
841
|
-
|
|
842
|
-
const ck = await visitAsync_("key", node.key, visitor,
|
|
618
|
+
path2 = Object.freeze(path2.concat(node));
|
|
619
|
+
const ck = await visitAsync_("key", node.key, visitor, path2);
|
|
843
620
|
if (ck === BREAK)
|
|
844
621
|
return BREAK;
|
|
845
622
|
else if (ck === REMOVE)
|
|
846
623
|
node.key = null;
|
|
847
|
-
const cv = await visitAsync_("value", node.value, visitor,
|
|
624
|
+
const cv = await visitAsync_("value", node.value, visitor, path2);
|
|
848
625
|
if (cv === BREAK)
|
|
849
626
|
return BREAK;
|
|
850
627
|
else if (cv === REMOVE)
|
|
@@ -871,23 +648,23 @@ var require_visit = __commonJS((exports) => {
|
|
|
871
648
|
}
|
|
872
649
|
return visitor;
|
|
873
650
|
}
|
|
874
|
-
function callVisitor(key, node, visitor,
|
|
651
|
+
function callVisitor(key, node, visitor, path2) {
|
|
875
652
|
if (typeof visitor === "function")
|
|
876
|
-
return visitor(key, node,
|
|
653
|
+
return visitor(key, node, path2);
|
|
877
654
|
if (identity.isMap(node))
|
|
878
|
-
return visitor.Map?.(key, node,
|
|
655
|
+
return visitor.Map?.(key, node, path2);
|
|
879
656
|
if (identity.isSeq(node))
|
|
880
|
-
return visitor.Seq?.(key, node,
|
|
657
|
+
return visitor.Seq?.(key, node, path2);
|
|
881
658
|
if (identity.isPair(node))
|
|
882
|
-
return visitor.Pair?.(key, node,
|
|
659
|
+
return visitor.Pair?.(key, node, path2);
|
|
883
660
|
if (identity.isScalar(node))
|
|
884
|
-
return visitor.Scalar?.(key, node,
|
|
661
|
+
return visitor.Scalar?.(key, node, path2);
|
|
885
662
|
if (identity.isAlias(node))
|
|
886
|
-
return visitor.Alias?.(key, node,
|
|
663
|
+
return visitor.Alias?.(key, node, path2);
|
|
887
664
|
return;
|
|
888
665
|
}
|
|
889
|
-
function replaceNode(key,
|
|
890
|
-
const parent =
|
|
666
|
+
function replaceNode(key, path2, node) {
|
|
667
|
+
const parent = path2[path2.length - 1];
|
|
891
668
|
if (identity.isCollection(parent)) {
|
|
892
669
|
parent.items[key] = node;
|
|
893
670
|
} else if (identity.isPair(parent)) {
|
|
@@ -1446,10 +1223,10 @@ var require_Collection = __commonJS((exports) => {
|
|
|
1446
1223
|
var createNode = require_createNode();
|
|
1447
1224
|
var identity = require_identity();
|
|
1448
1225
|
var Node = require_Node();
|
|
1449
|
-
function collectionFromPath(schema,
|
|
1226
|
+
function collectionFromPath(schema, path2, value) {
|
|
1450
1227
|
let v = value;
|
|
1451
|
-
for (let i =
|
|
1452
|
-
const k =
|
|
1228
|
+
for (let i = path2.length - 1;i >= 0; --i) {
|
|
1229
|
+
const k = path2[i];
|
|
1453
1230
|
if (typeof k === "number" && Number.isInteger(k) && k >= 0) {
|
|
1454
1231
|
const a = [];
|
|
1455
1232
|
a[k] = v;
|
|
@@ -1468,7 +1245,7 @@ var require_Collection = __commonJS((exports) => {
|
|
|
1468
1245
|
sourceObjects: new Map
|
|
1469
1246
|
});
|
|
1470
1247
|
}
|
|
1471
|
-
var isEmptyPath = (
|
|
1248
|
+
var isEmptyPath = (path2) => path2 == null || typeof path2 === "object" && !!path2[Symbol.iterator]().next().done;
|
|
1472
1249
|
|
|
1473
1250
|
class Collection extends Node.NodeBase {
|
|
1474
1251
|
constructor(type, schema) {
|
|
@@ -1489,11 +1266,11 @@ var require_Collection = __commonJS((exports) => {
|
|
|
1489
1266
|
copy.range = this.range.slice();
|
|
1490
1267
|
return copy;
|
|
1491
1268
|
}
|
|
1492
|
-
addIn(
|
|
1493
|
-
if (isEmptyPath(
|
|
1269
|
+
addIn(path2, value) {
|
|
1270
|
+
if (isEmptyPath(path2))
|
|
1494
1271
|
this.add(value);
|
|
1495
1272
|
else {
|
|
1496
|
-
const [key, ...rest] =
|
|
1273
|
+
const [key, ...rest] = path2;
|
|
1497
1274
|
const node = this.get(key, true);
|
|
1498
1275
|
if (identity.isCollection(node))
|
|
1499
1276
|
node.addIn(rest, value);
|
|
@@ -1503,8 +1280,8 @@ var require_Collection = __commonJS((exports) => {
|
|
|
1503
1280
|
throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
|
|
1504
1281
|
}
|
|
1505
1282
|
}
|
|
1506
|
-
deleteIn(
|
|
1507
|
-
const [key, ...rest] =
|
|
1283
|
+
deleteIn(path2) {
|
|
1284
|
+
const [key, ...rest] = path2;
|
|
1508
1285
|
if (rest.length === 0)
|
|
1509
1286
|
return this.delete(key);
|
|
1510
1287
|
const node = this.get(key, true);
|
|
@@ -1513,8 +1290,8 @@ var require_Collection = __commonJS((exports) => {
|
|
|
1513
1290
|
else
|
|
1514
1291
|
throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
|
|
1515
1292
|
}
|
|
1516
|
-
getIn(
|
|
1517
|
-
const [key, ...rest] =
|
|
1293
|
+
getIn(path2, keepScalar) {
|
|
1294
|
+
const [key, ...rest] = path2;
|
|
1518
1295
|
const node = this.get(key, true);
|
|
1519
1296
|
if (rest.length === 0)
|
|
1520
1297
|
return !keepScalar && identity.isScalar(node) ? node.value : node;
|
|
@@ -1529,15 +1306,15 @@ var require_Collection = __commonJS((exports) => {
|
|
|
1529
1306
|
return n == null || allowScalar && identity.isScalar(n) && n.value == null && !n.commentBefore && !n.comment && !n.tag;
|
|
1530
1307
|
});
|
|
1531
1308
|
}
|
|
1532
|
-
hasIn(
|
|
1533
|
-
const [key, ...rest] =
|
|
1309
|
+
hasIn(path2) {
|
|
1310
|
+
const [key, ...rest] = path2;
|
|
1534
1311
|
if (rest.length === 0)
|
|
1535
1312
|
return this.has(key);
|
|
1536
1313
|
const node = this.get(key, true);
|
|
1537
1314
|
return identity.isCollection(node) ? node.hasIn(rest) : false;
|
|
1538
1315
|
}
|
|
1539
|
-
setIn(
|
|
1540
|
-
const [key, ...rest] =
|
|
1316
|
+
setIn(path2, value) {
|
|
1317
|
+
const [key, ...rest] = path2;
|
|
1541
1318
|
if (rest.length === 0) {
|
|
1542
1319
|
this.set(key, value);
|
|
1543
1320
|
} else {
|
|
@@ -3930,9 +3707,9 @@ var require_Document = __commonJS((exports) => {
|
|
|
3930
3707
|
if (assertCollection(this.contents))
|
|
3931
3708
|
this.contents.add(value);
|
|
3932
3709
|
}
|
|
3933
|
-
addIn(
|
|
3710
|
+
addIn(path2, value) {
|
|
3934
3711
|
if (assertCollection(this.contents))
|
|
3935
|
-
this.contents.addIn(
|
|
3712
|
+
this.contents.addIn(path2, value);
|
|
3936
3713
|
}
|
|
3937
3714
|
createAlias(node, name) {
|
|
3938
3715
|
if (!node.anchor) {
|
|
@@ -3981,30 +3758,30 @@ var require_Document = __commonJS((exports) => {
|
|
|
3981
3758
|
delete(key) {
|
|
3982
3759
|
return assertCollection(this.contents) ? this.contents.delete(key) : false;
|
|
3983
3760
|
}
|
|
3984
|
-
deleteIn(
|
|
3985
|
-
if (Collection.isEmptyPath(
|
|
3761
|
+
deleteIn(path2) {
|
|
3762
|
+
if (Collection.isEmptyPath(path2)) {
|
|
3986
3763
|
if (this.contents == null)
|
|
3987
3764
|
return false;
|
|
3988
3765
|
this.contents = null;
|
|
3989
3766
|
return true;
|
|
3990
3767
|
}
|
|
3991
|
-
return assertCollection(this.contents) ? this.contents.deleteIn(
|
|
3768
|
+
return assertCollection(this.contents) ? this.contents.deleteIn(path2) : false;
|
|
3992
3769
|
}
|
|
3993
3770
|
get(key, keepScalar) {
|
|
3994
3771
|
return identity.isCollection(this.contents) ? this.contents.get(key, keepScalar) : undefined;
|
|
3995
3772
|
}
|
|
3996
|
-
getIn(
|
|
3997
|
-
if (Collection.isEmptyPath(
|
|
3773
|
+
getIn(path2, keepScalar) {
|
|
3774
|
+
if (Collection.isEmptyPath(path2))
|
|
3998
3775
|
return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
|
|
3999
|
-
return identity.isCollection(this.contents) ? this.contents.getIn(
|
|
3776
|
+
return identity.isCollection(this.contents) ? this.contents.getIn(path2, keepScalar) : undefined;
|
|
4000
3777
|
}
|
|
4001
3778
|
has(key) {
|
|
4002
3779
|
return identity.isCollection(this.contents) ? this.contents.has(key) : false;
|
|
4003
3780
|
}
|
|
4004
|
-
hasIn(
|
|
4005
|
-
if (Collection.isEmptyPath(
|
|
3781
|
+
hasIn(path2) {
|
|
3782
|
+
if (Collection.isEmptyPath(path2))
|
|
4006
3783
|
return this.contents !== undefined;
|
|
4007
|
-
return identity.isCollection(this.contents) ? this.contents.hasIn(
|
|
3784
|
+
return identity.isCollection(this.contents) ? this.contents.hasIn(path2) : false;
|
|
4008
3785
|
}
|
|
4009
3786
|
set(key, value) {
|
|
4010
3787
|
if (this.contents == null) {
|
|
@@ -4013,13 +3790,13 @@ var require_Document = __commonJS((exports) => {
|
|
|
4013
3790
|
this.contents.set(key, value);
|
|
4014
3791
|
}
|
|
4015
3792
|
}
|
|
4016
|
-
setIn(
|
|
4017
|
-
if (Collection.isEmptyPath(
|
|
3793
|
+
setIn(path2, value) {
|
|
3794
|
+
if (Collection.isEmptyPath(path2)) {
|
|
4018
3795
|
this.contents = value;
|
|
4019
3796
|
} else if (this.contents == null) {
|
|
4020
|
-
this.contents = Collection.collectionFromPath(this.schema, Array.from(
|
|
3797
|
+
this.contents = Collection.collectionFromPath(this.schema, Array.from(path2), value);
|
|
4021
3798
|
} else if (assertCollection(this.contents)) {
|
|
4022
|
-
this.contents.setIn(
|
|
3799
|
+
this.contents.setIn(path2, value);
|
|
4023
3800
|
}
|
|
4024
3801
|
}
|
|
4025
3802
|
setSchema(version, options = {}) {
|
|
@@ -4128,15 +3905,15 @@ var require_errors = __commonJS((exports) => {
|
|
|
4128
3905
|
let lineStr = src.substring(lc.lineStarts[line - 1], lc.lineStarts[line]).replace(/[\n\r]+$/, "");
|
|
4129
3906
|
if (ci >= 60 && lineStr.length > 80) {
|
|
4130
3907
|
const trimStart = Math.min(ci - 39, lineStr.length - 79);
|
|
4131
|
-
lineStr = "
|
|
3908
|
+
lineStr = "…" + lineStr.substring(trimStart);
|
|
4132
3909
|
ci -= trimStart - 1;
|
|
4133
3910
|
}
|
|
4134
3911
|
if (lineStr.length > 80)
|
|
4135
|
-
lineStr = lineStr.substring(0, 79) + "
|
|
3912
|
+
lineStr = lineStr.substring(0, 79) + "…";
|
|
4136
3913
|
if (line > 1 && /^ *$/.test(lineStr.substring(0, ci))) {
|
|
4137
3914
|
let prev = src.substring(lc.lineStarts[line - 2], lc.lineStarts[line - 1]);
|
|
4138
3915
|
if (prev.length > 80)
|
|
4139
|
-
prev = prev.substring(0, 79) +
|
|
3916
|
+
prev = prev.substring(0, 79) + `…
|
|
4140
3917
|
`;
|
|
4141
3918
|
lineStr = prev + lineStr;
|
|
4142
3919
|
}
|
|
@@ -5191,8 +4968,8 @@ var require_resolve_flow_scalar = __commonJS((exports) => {
|
|
|
5191
4968
|
r: "\r",
|
|
5192
4969
|
t: "\t",
|
|
5193
4970
|
v: "\v",
|
|
5194
|
-
N: "
|
|
5195
|
-
_: "
|
|
4971
|
+
N: "
",
|
|
4972
|
+
_: " ",
|
|
5196
4973
|
L: "\u2028",
|
|
5197
4974
|
P: "\u2029",
|
|
5198
4975
|
" ": " ",
|
|
@@ -5914,9 +5691,9 @@ var require_cst_visit = __commonJS((exports) => {
|
|
|
5914
5691
|
visit.BREAK = BREAK;
|
|
5915
5692
|
visit.SKIP = SKIP;
|
|
5916
5693
|
visit.REMOVE = REMOVE;
|
|
5917
|
-
visit.itemAtPath = (cst,
|
|
5694
|
+
visit.itemAtPath = (cst, path2) => {
|
|
5918
5695
|
let item = cst;
|
|
5919
|
-
for (const [field, index] of
|
|
5696
|
+
for (const [field, index] of path2) {
|
|
5920
5697
|
const tok = item?.[field];
|
|
5921
5698
|
if (tok && "items" in tok) {
|
|
5922
5699
|
item = tok.items[index];
|
|
@@ -5925,23 +5702,23 @@ var require_cst_visit = __commonJS((exports) => {
|
|
|
5925
5702
|
}
|
|
5926
5703
|
return item;
|
|
5927
5704
|
};
|
|
5928
|
-
visit.parentCollection = (cst,
|
|
5929
|
-
const parent = visit.itemAtPath(cst,
|
|
5930
|
-
const field =
|
|
5705
|
+
visit.parentCollection = (cst, path2) => {
|
|
5706
|
+
const parent = visit.itemAtPath(cst, path2.slice(0, -1));
|
|
5707
|
+
const field = path2[path2.length - 1][0];
|
|
5931
5708
|
const coll = parent?.[field];
|
|
5932
5709
|
if (coll && "items" in coll)
|
|
5933
5710
|
return coll;
|
|
5934
5711
|
throw new Error("Parent collection not found");
|
|
5935
5712
|
};
|
|
5936
|
-
function _visit(
|
|
5937
|
-
let ctrl = visitor(item,
|
|
5713
|
+
function _visit(path2, item, visitor) {
|
|
5714
|
+
let ctrl = visitor(item, path2);
|
|
5938
5715
|
if (typeof ctrl === "symbol")
|
|
5939
5716
|
return ctrl;
|
|
5940
5717
|
for (const field of ["key", "value"]) {
|
|
5941
5718
|
const token = item[field];
|
|
5942
5719
|
if (token && "items" in token) {
|
|
5943
5720
|
for (let i = 0;i < token.items.length; ++i) {
|
|
5944
|
-
const ci = _visit(Object.freeze(
|
|
5721
|
+
const ci = _visit(Object.freeze(path2.concat([[field, i]])), token.items[i], visitor);
|
|
5945
5722
|
if (typeof ci === "number")
|
|
5946
5723
|
i = ci - 1;
|
|
5947
5724
|
else if (ci === BREAK)
|
|
@@ -5952,10 +5729,10 @@ var require_cst_visit = __commonJS((exports) => {
|
|
|
5952
5729
|
}
|
|
5953
5730
|
}
|
|
5954
5731
|
if (typeof ctrl === "function" && field === "key")
|
|
5955
|
-
ctrl = ctrl(item,
|
|
5732
|
+
ctrl = ctrl(item, path2);
|
|
5956
5733
|
}
|
|
5957
5734
|
}
|
|
5958
|
-
return typeof ctrl === "function" ? ctrl(item,
|
|
5735
|
+
return typeof ctrl === "function" ? ctrl(item, path2) : ctrl;
|
|
5959
5736
|
}
|
|
5960
5737
|
exports.visit = visit;
|
|
5961
5738
|
});
|
|
@@ -7224,14 +7001,14 @@ var require_parser = __commonJS((exports) => {
|
|
|
7224
7001
|
case "scalar":
|
|
7225
7002
|
case "single-quoted-scalar":
|
|
7226
7003
|
case "double-quoted-scalar": {
|
|
7227
|
-
const
|
|
7004
|
+
const fs4 = this.flowScalar(this.type);
|
|
7228
7005
|
if (atNextItem || it.value) {
|
|
7229
|
-
map.items.push({ start, key:
|
|
7006
|
+
map.items.push({ start, key: fs4, sep: [] });
|
|
7230
7007
|
this.onKeyLine = true;
|
|
7231
7008
|
} else if (it.sep) {
|
|
7232
|
-
this.stack.push(
|
|
7009
|
+
this.stack.push(fs4);
|
|
7233
7010
|
} else {
|
|
7234
|
-
Object.assign(it, { key:
|
|
7011
|
+
Object.assign(it, { key: fs4, sep: [] });
|
|
7235
7012
|
this.onKeyLine = true;
|
|
7236
7013
|
}
|
|
7237
7014
|
return;
|
|
@@ -7359,13 +7136,13 @@ var require_parser = __commonJS((exports) => {
|
|
|
7359
7136
|
case "scalar":
|
|
7360
7137
|
case "single-quoted-scalar":
|
|
7361
7138
|
case "double-quoted-scalar": {
|
|
7362
|
-
const
|
|
7139
|
+
const fs4 = this.flowScalar(this.type);
|
|
7363
7140
|
if (!it || it.value)
|
|
7364
|
-
fc.items.push({ start: [], key:
|
|
7141
|
+
fc.items.push({ start: [], key: fs4, sep: [] });
|
|
7365
7142
|
else if (it.sep)
|
|
7366
|
-
this.stack.push(
|
|
7143
|
+
this.stack.push(fs4);
|
|
7367
7144
|
else
|
|
7368
|
-
Object.assign(it, { key:
|
|
7145
|
+
Object.assign(it, { key: fs4, sep: [] });
|
|
7369
7146
|
return;
|
|
7370
7147
|
}
|
|
7371
7148
|
case "flow-map-end":
|
|
@@ -7667,67 +7444,266 @@ var init_dist = __esm(() => {
|
|
|
7667
7444
|
$visitAsync = visit.visitAsync;
|
|
7668
7445
|
});
|
|
7669
7446
|
|
|
7670
|
-
// src/
|
|
7671
|
-
var
|
|
7447
|
+
// src/core/asset/asset-serialize.ts
|
|
7448
|
+
var init_asset_serialize = __esm(() => {
|
|
7449
|
+
init_dist();
|
|
7450
|
+
});
|
|
7672
7451
|
|
|
7673
|
-
// src/
|
|
7674
|
-
function
|
|
7675
|
-
|
|
7676
|
-
|
|
7677
|
-
|
|
7678
|
-
}
|
|
7679
|
-
|
|
7680
|
-
|
|
7681
|
-
|
|
7682
|
-
|
|
7683
|
-
|
|
7684
|
-
|
|
7685
|
-
|
|
7686
|
-
}
|
|
7452
|
+
// src/core/asset/frontmatter.ts
|
|
7453
|
+
function parseFrontmatter(raw) {
|
|
7454
|
+
const parsedBlock = parseFrontmatterBlock(raw);
|
|
7455
|
+
if (!parsedBlock) {
|
|
7456
|
+
return { data: {}, content: raw, frontmatter: null, bodyStartLine: 1 };
|
|
7457
|
+
}
|
|
7458
|
+
let data = {};
|
|
7459
|
+
if (parsedBlock.frontmatter.trim()) {
|
|
7460
|
+
try {
|
|
7461
|
+
const parsed = $parse(parsedBlock.frontmatter);
|
|
7462
|
+
if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
7463
|
+
data = normalizeYamlValues(parsed);
|
|
7464
|
+
}
|
|
7465
|
+
} catch {
|
|
7466
|
+
data = parseFrontmatterLenient(parsedBlock.frontmatter);
|
|
7467
|
+
}
|
|
7687
7468
|
}
|
|
7469
|
+
return {
|
|
7470
|
+
data,
|
|
7471
|
+
content: parsedBlock.content,
|
|
7472
|
+
frontmatter: parsedBlock.frontmatter,
|
|
7473
|
+
bodyStartLine: parsedBlock.bodyStartLine
|
|
7474
|
+
};
|
|
7688
7475
|
}
|
|
7689
|
-
function
|
|
7690
|
-
|
|
7691
|
-
|
|
7692
|
-
|
|
7693
|
-
|
|
7694
|
-
|
|
7695
|
-
|
|
7696
|
-
|
|
7476
|
+
function normalizeYamlValues(value) {
|
|
7477
|
+
if (value instanceof Date) {
|
|
7478
|
+
const y = value.getUTCFullYear();
|
|
7479
|
+
const m = String(value.getUTCMonth() + 1).padStart(2, "0");
|
|
7480
|
+
const d = String(value.getUTCDate()).padStart(2, "0");
|
|
7481
|
+
return `${y}-${m}-${d}`;
|
|
7482
|
+
}
|
|
7483
|
+
if (value === null)
|
|
7484
|
+
return "";
|
|
7485
|
+
if (Array.isArray(value))
|
|
7486
|
+
return value.map(normalizeYamlValues);
|
|
7487
|
+
if (typeof value === "object") {
|
|
7488
|
+
return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, normalizeYamlValues(v)]));
|
|
7697
7489
|
}
|
|
7490
|
+
return value;
|
|
7698
7491
|
}
|
|
7699
|
-
function
|
|
7700
|
-
const
|
|
7701
|
-
for (const
|
|
7702
|
-
const
|
|
7703
|
-
if (
|
|
7704
|
-
errors2.push({
|
|
7705
|
-
line: step.source.start,
|
|
7706
|
-
message: `Step ID "${step.id}" is already used on line ${previous}. Step IDs must be unique within a workflow.`
|
|
7707
|
-
});
|
|
7492
|
+
function parseFrontmatterLenient(frontmatter) {
|
|
7493
|
+
const data = {};
|
|
7494
|
+
for (const line of frontmatter.split(/\r?\n/)) {
|
|
7495
|
+
const m = line.match(/^([\w][\w-]*):\s*(.*)$/);
|
|
7496
|
+
if (!m)
|
|
7708
7497
|
continue;
|
|
7498
|
+
const key = m[1];
|
|
7499
|
+
const rawValue = (m[2] ?? "").trim();
|
|
7500
|
+
try {
|
|
7501
|
+
const singleEntry = $parse(`k: ${rawValue}`);
|
|
7502
|
+
if (singleEntry !== null && typeof singleEntry === "object" && !Array.isArray(singleEntry)) {
|
|
7503
|
+
const v = singleEntry.k;
|
|
7504
|
+
data[key] = v === null || v === undefined ? "" : v;
|
|
7505
|
+
} else {
|
|
7506
|
+
data[key] = rawValue;
|
|
7507
|
+
}
|
|
7508
|
+
} catch {
|
|
7509
|
+
data[key] = rawValue;
|
|
7709
7510
|
}
|
|
7710
|
-
firstSeenLine.set(step.id, step.source.start);
|
|
7711
7511
|
}
|
|
7512
|
+
return data;
|
|
7712
7513
|
}
|
|
7713
|
-
|
|
7714
|
-
|
|
7715
|
-
|
|
7716
|
-
|
|
7514
|
+
function parseFrontmatterBlock(raw) {
|
|
7515
|
+
const match = raw.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r\n|\r|\n|$)([\s\S]*)$/);
|
|
7516
|
+
if (match) {
|
|
7517
|
+
const frontmatter = match[1].replace(/\r/g, "");
|
|
7518
|
+
const content = match[2];
|
|
7519
|
+
return {
|
|
7520
|
+
frontmatter,
|
|
7521
|
+
content,
|
|
7522
|
+
bodyStartLine: countLines(raw.slice(0, match[0].length - match[2].length)) + 1
|
|
7523
|
+
};
|
|
7524
|
+
}
|
|
7525
|
+
const emptyMatch = raw.match(/^---\r?\n---(?:\r\n|\r|\n)([\s\S]*)$/);
|
|
7526
|
+
if (emptyMatch) {
|
|
7527
|
+
return { frontmatter: "", content: emptyMatch[1], bodyStartLine: 3 };
|
|
7528
|
+
}
|
|
7529
|
+
return null;
|
|
7530
|
+
}
|
|
7531
|
+
function countLines(text) {
|
|
7532
|
+
if (text.length === 0)
|
|
7533
|
+
return 0;
|
|
7534
|
+
return text.split(/\r?\n/).length - 1;
|
|
7535
|
+
}
|
|
7536
|
+
var init_frontmatter = __esm(() => {
|
|
7537
|
+
init_dist();
|
|
7538
|
+
init_asset_serialize();
|
|
7717
7539
|
});
|
|
7718
7540
|
|
|
7719
|
-
// src/
|
|
7720
|
-
function
|
|
7721
|
-
const
|
|
7722
|
-
const
|
|
7723
|
-
const
|
|
7724
|
-
const
|
|
7725
|
-
|
|
7726
|
-
|
|
7541
|
+
// src/core/asset/markdown.ts
|
|
7542
|
+
function parseMarkdownToc(content) {
|
|
7543
|
+
const lines = content.split(/\r?\n/);
|
|
7544
|
+
const headings = [];
|
|
7545
|
+
const parsed = parseFrontmatter(content);
|
|
7546
|
+
const start = parsed.frontmatter ? parsed.bodyStartLine - 1 : 0;
|
|
7547
|
+
let inFence = false;
|
|
7548
|
+
for (let i = start;i < lines.length; i++) {
|
|
7549
|
+
if (/^\s*(`{3,}|~{3,})/.test(lines[i])) {
|
|
7550
|
+
inFence = !inFence;
|
|
7551
|
+
continue;
|
|
7552
|
+
}
|
|
7553
|
+
if (inFence)
|
|
7554
|
+
continue;
|
|
7555
|
+
const match = lines[i].match(/^(#{1,6})\s+(.+)$/);
|
|
7556
|
+
if (match) {
|
|
7557
|
+
headings.push({
|
|
7558
|
+
level: match[1].length,
|
|
7559
|
+
text: match[2].replace(/\s+#+\s*$/, "").trim(),
|
|
7560
|
+
line: i + 1
|
|
7561
|
+
});
|
|
7562
|
+
}
|
|
7563
|
+
}
|
|
7564
|
+
return { headings, totalLines: lines.length };
|
|
7565
|
+
}
|
|
7566
|
+
var init_markdown = __esm(() => {
|
|
7567
|
+
init_frontmatter();
|
|
7568
|
+
});
|
|
7569
|
+
|
|
7570
|
+
// src/indexer/walk/file-context.ts
|
|
7571
|
+
var renderers;
|
|
7572
|
+
var init_file_context = __esm(() => {
|
|
7573
|
+
init_frontmatter();
|
|
7574
|
+
init_common();
|
|
7575
|
+
renderers = new Map;
|
|
7576
|
+
});
|
|
7577
|
+
|
|
7578
|
+
// src/indexer/passes/metadata-contributors.ts
|
|
7579
|
+
function registerMetadataContributor(contributor) {
|
|
7580
|
+
contributors.push(contributor);
|
|
7581
|
+
}
|
|
7582
|
+
var contributors;
|
|
7583
|
+
var init_metadata_contributors = __esm(() => {
|
|
7584
|
+
contributors = [];
|
|
7585
|
+
});
|
|
7586
|
+
|
|
7587
|
+
// src/indexer/passes/metadata.ts
|
|
7588
|
+
import fs4 from "node:fs";
|
|
7589
|
+
function extractDescriptionFromComments(filePath) {
|
|
7590
|
+
let content;
|
|
7591
|
+
try {
|
|
7592
|
+
content = fs4.readFileSync(filePath, "utf8");
|
|
7593
|
+
} catch {
|
|
7594
|
+
return null;
|
|
7595
|
+
}
|
|
7596
|
+
const lines = content.split(/\r?\n/).slice(0, 50);
|
|
7597
|
+
const blockStart = lines.findIndex((l) => /^\s*\/\*\*/.test(l));
|
|
7598
|
+
if (blockStart >= 0) {
|
|
7599
|
+
const desc = [];
|
|
7600
|
+
for (let i = blockStart;i < lines.length; i++) {
|
|
7601
|
+
const line = lines[i];
|
|
7602
|
+
if (i > blockStart && /\*\//.test(line))
|
|
7603
|
+
break;
|
|
7604
|
+
const cleaned = line.replace(/^\s*\/?\*\*?\s?/, "").replace(/\*\/\s*$/, "").trim();
|
|
7605
|
+
if (cleaned)
|
|
7606
|
+
desc.push(cleaned);
|
|
7607
|
+
}
|
|
7608
|
+
if (desc.length > 0)
|
|
7609
|
+
return desc.join(" ");
|
|
7610
|
+
}
|
|
7611
|
+
let start = 0;
|
|
7612
|
+
if (lines[0]?.startsWith("#!"))
|
|
7613
|
+
start = 1;
|
|
7614
|
+
const hashLines = [];
|
|
7615
|
+
for (let i = start;i < lines.length; i++) {
|
|
7616
|
+
const line = lines[i].trim();
|
|
7617
|
+
if (line.startsWith("#") && !line.startsWith("#!")) {
|
|
7618
|
+
hashLines.push(line.replace(/^#+\s*/, "").trim());
|
|
7619
|
+
} else if (line === "") {} else {
|
|
7620
|
+
break;
|
|
7621
|
+
}
|
|
7622
|
+
}
|
|
7623
|
+
if (hashLines.length > 0)
|
|
7624
|
+
return hashLines.join(" ");
|
|
7625
|
+
return null;
|
|
7626
|
+
}
|
|
7627
|
+
var KNOWN_QUALITY_VALUES, warnedUnknownQualityValues, WIKI_INFRA_FILES;
|
|
7628
|
+
var init_metadata = __esm(() => {
|
|
7629
|
+
init_asset_spec();
|
|
7630
|
+
init_frontmatter();
|
|
7631
|
+
init_common();
|
|
7632
|
+
init_warn();
|
|
7633
|
+
init_file_context();
|
|
7634
|
+
init_metadata_contributors();
|
|
7635
|
+
KNOWN_QUALITY_VALUES = new Set(["generated", "curated", "enriched", "proposed"]);
|
|
7636
|
+
warnedUnknownQualityValues = new Set;
|
|
7637
|
+
WIKI_INFRA_FILES = new Set(["schema.md", "index.md", "log.md"]);
|
|
7638
|
+
});
|
|
7639
|
+
|
|
7640
|
+
// src/core/asset/asset-ref.ts
|
|
7641
|
+
var init_asset_ref = __esm(() => {
|
|
7642
|
+
init_common();
|
|
7643
|
+
init_errors();
|
|
7644
|
+
});
|
|
7645
|
+
|
|
7646
|
+
// src/workflows/schema.ts
|
|
7647
|
+
var WORKFLOW_SCHEMA_VERSION = 1;
|
|
7648
|
+
|
|
7649
|
+
// src/workflows/validator.ts
|
|
7650
|
+
function runSemanticChecks(draft, frontmatterData, frontmatterEndLine, errors2) {
|
|
7651
|
+
checkFrontmatterKeys(frontmatterData, frontmatterEndLine, errors2);
|
|
7652
|
+
checkStepIdFormat(draft, errors2);
|
|
7653
|
+
checkDuplicateStepIds(draft, errors2);
|
|
7654
|
+
}
|
|
7655
|
+
function checkFrontmatterKeys(data, fmEndLine, errors2) {
|
|
7656
|
+
for (const key of Object.keys(data)) {
|
|
7657
|
+
if (ALLOWED_FRONTMATTER_KEYS.has(key))
|
|
7658
|
+
continue;
|
|
7659
|
+
errors2.push({
|
|
7660
|
+
line: fmEndLine,
|
|
7661
|
+
message: `Workflow frontmatter "${key}" is not supported. Use only: description, tags, params, name, updated, when_to_use.`
|
|
7662
|
+
});
|
|
7663
|
+
}
|
|
7664
|
+
}
|
|
7665
|
+
function checkStepIdFormat(draft, errors2) {
|
|
7666
|
+
for (const step of draft.steps) {
|
|
7667
|
+
if (STEP_ID_REGEX.test(step.id))
|
|
7668
|
+
continue;
|
|
7669
|
+
errors2.push({
|
|
7670
|
+
line: step.source.start,
|
|
7671
|
+
message: `Step ID "${step.id}" is invalid. Use letters, numbers, ".", "_" or "-" (e.g. "deploy-job").`
|
|
7672
|
+
});
|
|
7673
|
+
}
|
|
7674
|
+
}
|
|
7675
|
+
function checkDuplicateStepIds(draft, errors2) {
|
|
7676
|
+
const firstSeenLine = new Map;
|
|
7677
|
+
for (const step of draft.steps) {
|
|
7678
|
+
const previous = firstSeenLine.get(step.id);
|
|
7679
|
+
if (previous !== undefined) {
|
|
7680
|
+
errors2.push({
|
|
7681
|
+
line: step.source.start,
|
|
7682
|
+
message: `Step ID "${step.id}" is already used on line ${previous}. Step IDs must be unique within a workflow.`
|
|
7683
|
+
});
|
|
7684
|
+
continue;
|
|
7685
|
+
}
|
|
7686
|
+
firstSeenLine.set(step.id, step.source.start);
|
|
7687
|
+
}
|
|
7688
|
+
}
|
|
7689
|
+
var STEP_ID_REGEX, ALLOWED_FRONTMATTER_KEYS;
|
|
7690
|
+
var init_validator = __esm(() => {
|
|
7691
|
+
STEP_ID_REGEX = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
7692
|
+
ALLOWED_FRONTMATTER_KEYS = new Set(["description", "tags", "params", "name", "updated", "when_to_use"]);
|
|
7693
|
+
});
|
|
7694
|
+
|
|
7695
|
+
// src/workflows/parser.ts
|
|
7696
|
+
function parseWorkflow(markdown, source) {
|
|
7697
|
+
const errors2 = [];
|
|
7698
|
+
const path2 = source.path;
|
|
7699
|
+
const lines = markdown.split(/\r?\n/);
|
|
7700
|
+
const totalLines = lines.length;
|
|
7701
|
+
const fmBlock = parseFrontmatterBlock(markdown);
|
|
7702
|
+
const frontmatterEndLine = fmBlock ? Math.max(1, fmBlock.bodyStartLine - 1) : 1;
|
|
7727
7703
|
const fmData = readFrontmatter(fmBlock?.frontmatter, errors2);
|
|
7728
7704
|
const description = readDescription(fmData);
|
|
7729
7705
|
const tags = readTags(fmData, errors2, frontmatterEndLine);
|
|
7730
|
-
const parameters = readParameters(fmData, errors2, frontmatterEndLine,
|
|
7706
|
+
const parameters = readParameters(fmData, errors2, frontmatterEndLine, path2);
|
|
7731
7707
|
const toc = parseMarkdownToc(markdown);
|
|
7732
7708
|
const { title, titleLine } = extractTitle(toc.headings, errors2);
|
|
7733
7709
|
for (const h of toc.headings) {
|
|
@@ -7744,7 +7720,7 @@ function parseWorkflow(markdown, source) {
|
|
|
7744
7720
|
});
|
|
7745
7721
|
}
|
|
7746
7722
|
}
|
|
7747
|
-
const steps = extractSteps(toc.headings, lines, totalLines,
|
|
7723
|
+
const steps = extractSteps(toc.headings, lines, totalLines, path2, errors2);
|
|
7748
7724
|
if (steps.length === 0 && titleLine > 0) {
|
|
7749
7725
|
errors2.push({
|
|
7750
7726
|
line: titleLine,
|
|
@@ -7758,7 +7734,7 @@ function parseWorkflow(markdown, source) {
|
|
|
7758
7734
|
...tags ? { tags } : {},
|
|
7759
7735
|
...parameters ? { parameters } : {},
|
|
7760
7736
|
steps,
|
|
7761
|
-
source: { path, lineCount: totalLines }
|
|
7737
|
+
source: { path: path2, lineCount: totalLines }
|
|
7762
7738
|
};
|
|
7763
7739
|
runSemanticChecks(draft, fmData, frontmatterEndLine, errors2);
|
|
7764
7740
|
if (errors2.length > 0) {
|
|
@@ -7793,7 +7769,7 @@ function extractTitle(headings, errors2) {
|
|
|
7793
7769
|
}
|
|
7794
7770
|
return { title, titleLine: first.line };
|
|
7795
7771
|
}
|
|
7796
|
-
function extractSteps(headings, lines, totalLines,
|
|
7772
|
+
function extractSteps(headings, lines, totalLines, path2, errors2) {
|
|
7797
7773
|
const steps = [];
|
|
7798
7774
|
let sequenceIndex = 0;
|
|
7799
7775
|
for (let i = 0;i < headings.length; i++) {
|
|
@@ -7809,11 +7785,11 @@ function extractSteps(headings, lines, totalLines, path, errors2) {
|
|
|
7809
7785
|
continue;
|
|
7810
7786
|
}
|
|
7811
7787
|
const stepEnd = Math.min(findNextSiblingOrParentLine(headings, i, 2) - 1, totalLines);
|
|
7812
|
-
const stepSource = { path, start: h.line, end: stepEnd };
|
|
7788
|
+
const stepSource = { path: path2, start: h.line, end: stepEnd };
|
|
7813
7789
|
const subsections = collectSubsections(headings, i, stepEnd);
|
|
7814
7790
|
const stepIdSearchEnd = subsections.length > 0 ? subsections[0].headingLine - 1 : stepEnd;
|
|
7815
7791
|
const stepId = scanStepId(lines, h.line + 1, stepIdSearchEnd, stepTitle, errors2);
|
|
7816
|
-
const { instructions, completionCriteria } = collectStepBody(subsections, lines,
|
|
7792
|
+
const { instructions, completionCriteria } = collectStepBody(subsections, lines, path2, stepTitle, errors2);
|
|
7817
7793
|
if (!stepId)
|
|
7818
7794
|
continue;
|
|
7819
7795
|
if (!instructions) {
|
|
@@ -7853,7 +7829,7 @@ function collectSubsections(headings, stepIndex, stepEnd) {
|
|
|
7853
7829
|
}
|
|
7854
7830
|
return subs;
|
|
7855
7831
|
}
|
|
7856
|
-
function collectStepBody(subsections, lines,
|
|
7832
|
+
function collectStepBody(subsections, lines, path2, stepTitle, errors2) {
|
|
7857
7833
|
let instructions;
|
|
7858
7834
|
let completionCriteria;
|
|
7859
7835
|
for (const sub of subsections) {
|
|
@@ -7875,7 +7851,7 @@ function collectStepBody(subsections, lines, path, stepTitle, errors2) {
|
|
|
7875
7851
|
}
|
|
7876
7852
|
instructions = {
|
|
7877
7853
|
text,
|
|
7878
|
-
source: { path, start: sub.bodyStart, end: sub.bodyEnd }
|
|
7854
|
+
source: { path: path2, start: sub.bodyStart, end: sub.bodyEnd }
|
|
7879
7855
|
};
|
|
7880
7856
|
continue;
|
|
7881
7857
|
}
|
|
@@ -7887,7 +7863,7 @@ function collectStepBody(subsections, lines, path, stepTitle, errors2) {
|
|
|
7887
7863
|
});
|
|
7888
7864
|
continue;
|
|
7889
7865
|
}
|
|
7890
|
-
const items = collectBullets(lines, sub.bodyStart, sub.bodyEnd,
|
|
7866
|
+
const items = collectBullets(lines, sub.bodyStart, sub.bodyEnd, path2);
|
|
7891
7867
|
if (items.length === 0) {
|
|
7892
7868
|
errors2.push({
|
|
7893
7869
|
line: sub.headingLine,
|
|
@@ -7900,7 +7876,7 @@ function collectStepBody(subsections, lines, path, stepTitle, errors2) {
|
|
|
7900
7876
|
}
|
|
7901
7877
|
errors2.push({
|
|
7902
7878
|
line: sub.headingLine,
|
|
7903
|
-
message: `Step "${stepTitle}" has an unknown "### ${sub.name}" section.
|
|
7879
|
+
message: `Step "${stepTitle}" has an unknown "### ${sub.name}" section. Supported sections: ` + `"### Instructions", "### Completion Criteria". For orchestrated workflows (runners, ` + `fan-out, routing), author a YAML workflow program instead — see \`akm workflow template --yaml\`.`
|
|
7904
7880
|
});
|
|
7905
7881
|
}
|
|
7906
7882
|
return {
|
|
@@ -7936,7 +7912,7 @@ function scanStepId(lines, startLineInclusive, endLineInclusive, stepTitle, erro
|
|
|
7936
7912
|
}
|
|
7937
7913
|
return foundId;
|
|
7938
7914
|
}
|
|
7939
|
-
function collectBullets(lines, startLineInclusive, endLineInclusive,
|
|
7915
|
+
function collectBullets(lines, startLineInclusive, endLineInclusive, path2) {
|
|
7940
7916
|
const items = [];
|
|
7941
7917
|
for (let lineNum = startLineInclusive;lineNum <= endLineInclusive; lineNum++) {
|
|
7942
7918
|
const trimmed = (lines[lineNum - 1] ?? "").trim();
|
|
@@ -7947,7 +7923,7 @@ function collectBullets(lines, startLineInclusive, endLineInclusive, path) {
|
|
|
7947
7923
|
continue;
|
|
7948
7924
|
items.push({
|
|
7949
7925
|
text: match[1].trim(),
|
|
7950
|
-
source: { path, start: lineNum, end: lineNum }
|
|
7926
|
+
source: { path: path2, start: lineNum, end: lineNum }
|
|
7951
7927
|
});
|
|
7952
7928
|
}
|
|
7953
7929
|
return items;
|
|
@@ -8016,7 +7992,7 @@ function readTags(data, errors2, fmEndLine) {
|
|
|
8016
7992
|
}
|
|
8017
7993
|
return v.map((tag) => tag.trim());
|
|
8018
7994
|
}
|
|
8019
|
-
function readParameters(data, errors2, fmEndLine,
|
|
7995
|
+
function readParameters(data, errors2, fmEndLine, path2) {
|
|
8020
7996
|
const v = data.params;
|
|
8021
7997
|
if (v === undefined || v === null)
|
|
8022
7998
|
return;
|
|
@@ -8050,23 +8026,719 @@ function readParameters(data, errors2, fmEndLine, path) {
|
|
|
8050
8026
|
out.push({
|
|
8051
8027
|
name: trimmedName,
|
|
8052
8028
|
description: desc.trim(),
|
|
8053
|
-
source: { path, start: 1, end: fmEndLine }
|
|
8029
|
+
source: { path: path2, start: 1, end: fmEndLine }
|
|
8054
8030
|
});
|
|
8055
8031
|
}
|
|
8056
8032
|
return out.length > 0 ? out : undefined;
|
|
8057
8033
|
}
|
|
8058
|
-
function sortErrors(errors2) {
|
|
8059
|
-
return [...errors2].sort((a, b) => a.line - b.line);
|
|
8034
|
+
function sortErrors(errors2) {
|
|
8035
|
+
return [...errors2].sort((a, b) => a.line - b.line);
|
|
8036
|
+
}
|
|
8037
|
+
var WORKFLOW_TITLE_PREFIX = "Workflow:", STEP_PREFIX = "Step:", STEP_ID_LINE, BULLET_LINE, SUBSECTION_INSTRUCTIONS = "Instructions", SUBSECTION_COMPLETION_CRITERIA = "Completion Criteria";
|
|
8038
|
+
var init_parser = __esm(() => {
|
|
8039
|
+
init_dist();
|
|
8040
|
+
init_frontmatter();
|
|
8041
|
+
init_markdown();
|
|
8042
|
+
init_validator();
|
|
8043
|
+
STEP_ID_LINE = /^Step ID:\s+(.+?)\s*$/;
|
|
8044
|
+
BULLET_LINE = /^[-*]\s+(.+)$/;
|
|
8045
|
+
});
|
|
8046
|
+
|
|
8047
|
+
// src/workflows/program/schema.ts
|
|
8048
|
+
var PROGRAM_RUNNER_KINDS, PROGRAM_REDUCERS, PROGRAM_ON_ERROR, PROGRAM_ISOLATION_KINDS, RETRY_REASON_SET, PROGRAM_RETRY_REASONS, PROGRAM_STEP_ID_PATTERN, PROGRAM_PARAM_NAME_PATTERN;
|
|
8049
|
+
var init_schema = __esm(() => {
|
|
8050
|
+
PROGRAM_RUNNER_KINDS = ["llm", "agent", "sdk", "inherit"];
|
|
8051
|
+
PROGRAM_REDUCERS = ["collect", "vote"];
|
|
8052
|
+
PROGRAM_ON_ERROR = ["fail", "continue"];
|
|
8053
|
+
PROGRAM_ISOLATION_KINDS = ["none", "worktree"];
|
|
8054
|
+
RETRY_REASON_SET = {
|
|
8055
|
+
timeout: true,
|
|
8056
|
+
spawn_failed: true,
|
|
8057
|
+
non_zero_exit: true,
|
|
8058
|
+
parse_error: true,
|
|
8059
|
+
cooldown: true,
|
|
8060
|
+
llm_rate_limit: true,
|
|
8061
|
+
llm_content_filter: true,
|
|
8062
|
+
llm_invalid_json: true,
|
|
8063
|
+
content_policy_reject: true,
|
|
8064
|
+
unsupported_type: true,
|
|
8065
|
+
no_change: true,
|
|
8066
|
+
aborted: true
|
|
8067
|
+
};
|
|
8068
|
+
PROGRAM_RETRY_REASONS = Object.keys(RETRY_REASON_SET);
|
|
8069
|
+
PROGRAM_STEP_ID_PATTERN = /^[A-Za-z_][A-Za-z0-9_-]*$/;
|
|
8070
|
+
PROGRAM_PARAM_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
8071
|
+
});
|
|
8072
|
+
|
|
8073
|
+
// src/workflows/program/parser.ts
|
|
8074
|
+
import { createRequire as createRequire4 } from "node:module";
|
|
8075
|
+
function parseWorkflowProgram(yamlText, source) {
|
|
8076
|
+
const errors2 = [];
|
|
8077
|
+
const lineCounter2 = new $LineCounter;
|
|
8078
|
+
let doc;
|
|
8079
|
+
try {
|
|
8080
|
+
doc = $parseDocument(yamlText, { lineCounter: lineCounter2 });
|
|
8081
|
+
} catch (cause) {
|
|
8082
|
+
return { ok: false, errors: [{ line: 1, message: `YAML parse failed: ${describeError(cause)}` }] };
|
|
8083
|
+
}
|
|
8084
|
+
for (const problem of doc.errors) {
|
|
8085
|
+
const offset = Array.isArray(problem.pos) ? problem.pos[0] : 0;
|
|
8086
|
+
errors2.push({ line: Math.max(1, lineCounter2.linePos(offset).line), message: yamlErrorMessage(problem.message) });
|
|
8087
|
+
}
|
|
8088
|
+
if (errors2.length > 0)
|
|
8089
|
+
return { ok: false, errors: errors2 };
|
|
8090
|
+
let root;
|
|
8091
|
+
try {
|
|
8092
|
+
root = doc.toJS();
|
|
8093
|
+
} catch (cause) {
|
|
8094
|
+
return { ok: false, errors: [{ line: 1, message: `YAML expansion failed: ${describeError(cause)}` }] };
|
|
8095
|
+
}
|
|
8096
|
+
const lineAt = (path2) => {
|
|
8097
|
+
for (let depth = path2.length;depth >= 0; depth--) {
|
|
8098
|
+
const node = depth === 0 ? doc.contents : doc.getIn(path2.slice(0, depth), true);
|
|
8099
|
+
const range = node?.range;
|
|
8100
|
+
if (range)
|
|
8101
|
+
return Math.max(1, lineCounter2.linePos(range[0]).line);
|
|
8102
|
+
}
|
|
8103
|
+
return 1;
|
|
8104
|
+
};
|
|
8105
|
+
const ctx = {
|
|
8106
|
+
filePath: source.path,
|
|
8107
|
+
errors: errors2,
|
|
8108
|
+
lineAt,
|
|
8109
|
+
lineAtOffset: (offset) => Math.max(1, lineCounter2.linePos(offset).line),
|
|
8110
|
+
nodeAt: (path2) => path2.length === 0 ? doc.contents : doc.getIn(path2, true),
|
|
8111
|
+
refAt: (path2) => {
|
|
8112
|
+
for (let depth = path2.length;depth >= 0; depth--) {
|
|
8113
|
+
const node = depth === 0 ? doc.contents : doc.getIn(path2.slice(0, depth), true);
|
|
8114
|
+
const range = node?.range;
|
|
8115
|
+
if (range) {
|
|
8116
|
+
const start = Math.max(1, lineCounter2.linePos(range[0]).line);
|
|
8117
|
+
const end = Math.max(start, lineCounter2.linePos(Math.max(range[0], range[1] - 1)).line);
|
|
8118
|
+
return { path: source.path, start, end };
|
|
8119
|
+
}
|
|
8120
|
+
}
|
|
8121
|
+
return { path: source.path, start: 1, end: 1 };
|
|
8122
|
+
},
|
|
8123
|
+
err: (path2, message) => errors2.push({ line: lineAt(path2), message }),
|
|
8124
|
+
errAtLine: (line, message) => errors2.push({ line, message }),
|
|
8125
|
+
checkTemplates: (text, path2, label) => checkTemplates(ctx, text, path2, label)
|
|
8126
|
+
};
|
|
8127
|
+
if (!isPlainRecord(root)) {
|
|
8128
|
+
return {
|
|
8129
|
+
ok: false,
|
|
8130
|
+
errors: [
|
|
8131
|
+
{ line: 1, message: `A workflow program must be a YAML mapping with "version: 1", "name", and "steps".` }
|
|
8132
|
+
]
|
|
8133
|
+
};
|
|
8134
|
+
}
|
|
8135
|
+
checkUnknownKeys(ctx, root, [], TOP_LEVEL_KEYS, "top-level");
|
|
8136
|
+
if (root.version !== 1) {
|
|
8137
|
+
const got = root.version === undefined ? "it is missing" : `got ${JSON.stringify(root.version)}`;
|
|
8138
|
+
ctx.err(["version"], `"version: 1" is required at the top level (${got}). Only the number 1 is a valid version.`);
|
|
8139
|
+
}
|
|
8140
|
+
let name = "";
|
|
8141
|
+
if (typeof root.name === "string" && root.name.trim() !== "") {
|
|
8142
|
+
name = root.name.trim();
|
|
8143
|
+
ctx.checkTemplates(root.name, ["name"], `"name"`);
|
|
8144
|
+
} else {
|
|
8145
|
+
ctx.err(["name"], `"name" is required and must be a non-empty string.`);
|
|
8146
|
+
}
|
|
8147
|
+
let description;
|
|
8148
|
+
if (root.description !== undefined) {
|
|
8149
|
+
if (typeof root.description === "string") {
|
|
8150
|
+
description = root.description;
|
|
8151
|
+
ctx.checkTemplates(root.description, ["description"], `"description"`);
|
|
8152
|
+
} else {
|
|
8153
|
+
ctx.err(["description"], `"description" must be a string.`);
|
|
8154
|
+
}
|
|
8155
|
+
}
|
|
8156
|
+
const params = parseParams(ctx, root.params);
|
|
8157
|
+
const defaults = parseDefaults(ctx, root.defaults);
|
|
8158
|
+
const budget = parseBudget(ctx, root.budget);
|
|
8159
|
+
const steps = parseSteps(ctx, root.steps);
|
|
8160
|
+
if (errors2.length > 0)
|
|
8161
|
+
return { ok: false, errors: errors2 };
|
|
8162
|
+
const program = {
|
|
8163
|
+
version: 1,
|
|
8164
|
+
name,
|
|
8165
|
+
...description !== undefined ? { description } : {},
|
|
8166
|
+
...params !== undefined ? { params } : {},
|
|
8167
|
+
...defaults !== undefined ? { defaults } : {},
|
|
8168
|
+
...budget !== undefined ? { budget } : {},
|
|
8169
|
+
steps,
|
|
8170
|
+
source: { path: source.path }
|
|
8171
|
+
};
|
|
8172
|
+
return { ok: true, program };
|
|
8173
|
+
}
|
|
8174
|
+
function parseParams(ctx, raw) {
|
|
8175
|
+
if (raw === undefined)
|
|
8176
|
+
return;
|
|
8177
|
+
if (!isPlainRecord(raw)) {
|
|
8178
|
+
ctx.err(["params"], `"params" must be a mapping of param name to a JSON Schema object (e.g. changed_files: { type: array }).`);
|
|
8179
|
+
return;
|
|
8180
|
+
}
|
|
8181
|
+
const params = {};
|
|
8182
|
+
for (const [paramName, value] of Object.entries(raw)) {
|
|
8183
|
+
if (!PROGRAM_PARAM_NAME_PATTERN.test(paramName)) {
|
|
8184
|
+
ctx.err(["params", paramName], `Param name "${paramName}" is invalid. Use letters, digits, and underscores, starting with a letter or underscore, so "\${{ params.${paramName} }}" can address it.`);
|
|
8185
|
+
continue;
|
|
8186
|
+
}
|
|
8187
|
+
if (!isPlainRecord(value)) {
|
|
8188
|
+
ctx.err(["params", paramName], `Param "${paramName}" must be a JSON Schema object (e.g. { type: string }).`);
|
|
8189
|
+
continue;
|
|
8190
|
+
}
|
|
8191
|
+
params[paramName] = value;
|
|
8192
|
+
}
|
|
8193
|
+
return Object.keys(params).length > 0 ? params : undefined;
|
|
8194
|
+
}
|
|
8195
|
+
function parseDefaults(ctx, raw) {
|
|
8196
|
+
if (raw === undefined)
|
|
8197
|
+
return;
|
|
8198
|
+
const path2 = ["defaults"];
|
|
8199
|
+
if (!isPlainRecord(raw)) {
|
|
8200
|
+
ctx.err(path2, `"defaults" must be a mapping with any of: ${DEFAULTS_KEYS.join(", ")}.`);
|
|
8201
|
+
return;
|
|
8202
|
+
}
|
|
8203
|
+
checkUnknownKeys(ctx, raw, path2, DEFAULTS_KEYS, `"defaults"`);
|
|
8204
|
+
const defaults = {};
|
|
8205
|
+
const runner = parseEnumField(ctx, raw.runner, [...path2, "runner"], `"defaults.runner"`, PROGRAM_RUNNER_KINDS);
|
|
8206
|
+
if (runner !== undefined)
|
|
8207
|
+
defaults.runner = runner;
|
|
8208
|
+
if (raw.model !== undefined) {
|
|
8209
|
+
if (typeof raw.model === "string" && raw.model.trim() !== "")
|
|
8210
|
+
defaults.model = raw.model.trim();
|
|
8211
|
+
else
|
|
8212
|
+
ctx.err([...path2, "model"], `"defaults.model" must be a non-empty string (a model alias or exact id).`);
|
|
8213
|
+
}
|
|
8214
|
+
const timeoutMs = parseTimeoutField(ctx, raw.timeout, [...path2, "timeout"], `"defaults.timeout"`);
|
|
8215
|
+
if (timeoutMs !== undefined)
|
|
8216
|
+
defaults.timeoutMs = timeoutMs;
|
|
8217
|
+
const onError = parseEnumField(ctx, raw.on_error, [...path2, "on_error"], `"defaults.on_error"`, PROGRAM_ON_ERROR);
|
|
8218
|
+
if (onError !== undefined)
|
|
8219
|
+
defaults.onError = onError;
|
|
8220
|
+
return Object.keys(defaults).length > 0 ? defaults : undefined;
|
|
8221
|
+
}
|
|
8222
|
+
function parseBudget(ctx, raw) {
|
|
8223
|
+
if (raw === undefined)
|
|
8224
|
+
return;
|
|
8225
|
+
const path2 = ["budget"];
|
|
8226
|
+
if (!isPlainRecord(raw)) {
|
|
8227
|
+
ctx.err(path2, `"budget" must be a mapping with any of: ${BUDGET_KEYS.join(", ")}.`);
|
|
8228
|
+
return;
|
|
8229
|
+
}
|
|
8230
|
+
checkUnknownKeys(ctx, raw, path2, BUDGET_KEYS, `"budget"`);
|
|
8231
|
+
const budget = {};
|
|
8232
|
+
if (raw.max_tokens !== undefined) {
|
|
8233
|
+
if (typeof raw.max_tokens === "number" && Number.isInteger(raw.max_tokens) && raw.max_tokens >= 1) {
|
|
8234
|
+
budget.maxTokens = raw.max_tokens;
|
|
8235
|
+
} else {
|
|
8236
|
+
ctx.err([...path2, "max_tokens"], `"budget.max_tokens" must be an integer >= 1.`);
|
|
8237
|
+
}
|
|
8238
|
+
}
|
|
8239
|
+
if (raw.max_units !== undefined) {
|
|
8240
|
+
if (typeof raw.max_units === "number" && Number.isInteger(raw.max_units) && raw.max_units >= 1) {
|
|
8241
|
+
budget.maxUnits = raw.max_units;
|
|
8242
|
+
} else {
|
|
8243
|
+
ctx.err([...path2, "max_units"], `"budget.max_units" must be an integer >= 1.`);
|
|
8244
|
+
}
|
|
8245
|
+
}
|
|
8246
|
+
return Object.keys(budget).length > 0 ? budget : undefined;
|
|
8247
|
+
}
|
|
8248
|
+
function parseSteps(ctx, raw) {
|
|
8249
|
+
if (!Array.isArray(raw) || raw.length === 0) {
|
|
8250
|
+
ctx.err(["steps"], `"steps" is required and must be a list with at least one step.`);
|
|
8251
|
+
return [];
|
|
8252
|
+
}
|
|
8253
|
+
const idIndex = new Map;
|
|
8254
|
+
raw.forEach((rawStep, index) => {
|
|
8255
|
+
if (isPlainRecord(rawStep) && typeof rawStep.id === "string" && !idIndex.has(rawStep.id)) {
|
|
8256
|
+
idIndex.set(rawStep.id, index);
|
|
8257
|
+
}
|
|
8258
|
+
});
|
|
8259
|
+
const steps = [];
|
|
8260
|
+
const seenIds = new Map;
|
|
8261
|
+
const routeChecks = [];
|
|
8262
|
+
raw.forEach((rawStep, index) => {
|
|
8263
|
+
const path2 = ["steps", index];
|
|
8264
|
+
if (!isPlainRecord(rawStep)) {
|
|
8265
|
+
ctx.err(path2, `Step ${index + 1} must be a mapping with an "id" and exactly one of "unit", "map", or "route".`);
|
|
8266
|
+
return;
|
|
8267
|
+
}
|
|
8268
|
+
const label = typeof rawStep.id === "string" && rawStep.id !== "" ? `Step "${rawStep.id}"` : `Step ${index + 1}`;
|
|
8269
|
+
checkUnknownKeys(ctx, rawStep, path2, STEP_KEYS, label);
|
|
8270
|
+
let id = "";
|
|
8271
|
+
if (typeof rawStep.id !== "string" || rawStep.id === "") {
|
|
8272
|
+
ctx.err([...path2, "id"], `${label} requires a non-empty string "id".`);
|
|
8273
|
+
} else if (!PROGRAM_STEP_ID_PATTERN.test(rawStep.id)) {
|
|
8274
|
+
ctx.err([...path2, "id"], `${label} has an invalid id "${rawStep.id}". A step id cannot be referenced from \${{ }} expressions ` + `unless it matches [A-Za-z_][A-Za-z0-9_-]* (a letter or underscore first, then letters, digits, ` + `underscores, or dashes; no dots, no leading digit) — otherwise \${{ steps.${rawStep.id}.output }} ` + `cannot be written.`);
|
|
8275
|
+
} else {
|
|
8276
|
+
id = rawStep.id;
|
|
8277
|
+
const firstIndex = seenIds.get(id);
|
|
8278
|
+
if (firstIndex !== undefined) {
|
|
8279
|
+
ctx.err([...path2, "id"], `Duplicate step id "${id}" (first used by step ${firstIndex + 1}). Step ids must be unique.`);
|
|
8280
|
+
} else {
|
|
8281
|
+
seenIds.set(id, index);
|
|
8282
|
+
}
|
|
8283
|
+
}
|
|
8284
|
+
let title;
|
|
8285
|
+
if (rawStep.title !== undefined) {
|
|
8286
|
+
if (typeof rawStep.title === "string" && rawStep.title.trim() !== "") {
|
|
8287
|
+
title = rawStep.title.trim();
|
|
8288
|
+
ctx.checkTemplates(rawStep.title, [...path2, "title"], `${label} "title"`);
|
|
8289
|
+
} else {
|
|
8290
|
+
ctx.err([...path2, "title"], `${label} "title" must be a non-empty string.`);
|
|
8291
|
+
}
|
|
8292
|
+
}
|
|
8293
|
+
const declaredKinds = STEP_KINDS.filter((kind) => rawStep[kind] !== undefined);
|
|
8294
|
+
if (declaredKinds.length !== 1) {
|
|
8295
|
+
const found = declaredKinds.length === 0 ? "found none" : `found ${declaredKinds.join(" + ")}`;
|
|
8296
|
+
ctx.err(path2, `${label} must declare exactly one of "unit", "map", or "route" (${found}).`);
|
|
8297
|
+
}
|
|
8298
|
+
const unit = rawStep.unit !== undefined ? parseUnit(ctx, rawStep.unit, [...path2, "unit"], label) : undefined;
|
|
8299
|
+
const map = rawStep.map !== undefined ? parseMap(ctx, rawStep.map, [...path2, "map"], label) : undefined;
|
|
8300
|
+
const route = rawStep.route !== undefined ? parseRoute(ctx, rawStep.route, [...path2, "route"], label, index, routeChecks) : undefined;
|
|
8301
|
+
const output = parseSchemaObject(ctx, rawStep.output, [...path2, "output"], `${label} "output"`);
|
|
8302
|
+
const gate = rawStep.gate !== undefined ? parseGate(ctx, rawStep.gate, [...path2, "gate"], label) : undefined;
|
|
8303
|
+
const step = { id, source: ctx.refAt(path2) };
|
|
8304
|
+
if (title !== undefined)
|
|
8305
|
+
step.title = title;
|
|
8306
|
+
if (declaredKinds.length === 1) {
|
|
8307
|
+
if (unit)
|
|
8308
|
+
step.unit = unit;
|
|
8309
|
+
if (map)
|
|
8310
|
+
step.map = map;
|
|
8311
|
+
if (route)
|
|
8312
|
+
step.route = route;
|
|
8313
|
+
}
|
|
8314
|
+
if (output !== undefined)
|
|
8315
|
+
step.output = output;
|
|
8316
|
+
if (gate !== undefined)
|
|
8317
|
+
step.gate = gate;
|
|
8318
|
+
steps.push(step);
|
|
8319
|
+
});
|
|
8320
|
+
for (const check of routeChecks) {
|
|
8321
|
+
const targets = [...check.branches.map((b) => ({ stepId: b.stepId, line: b.line }))];
|
|
8322
|
+
if (check.defaultTarget)
|
|
8323
|
+
targets.push(check.defaultTarget);
|
|
8324
|
+
for (const target of targets) {
|
|
8325
|
+
const targetIndex = idIndex.get(target.stepId);
|
|
8326
|
+
if (targetIndex === undefined) {
|
|
8327
|
+
ctx.errAtLine(target.line, `${check.stepLabel} routes to unknown step "${target.stepId}". Route targets must name a step id in this workflow.`);
|
|
8328
|
+
} else if (targetIndex === check.stepIndex) {
|
|
8329
|
+
ctx.errAtLine(target.line, `${check.stepLabel} must not route to itself.`);
|
|
8330
|
+
} else if (targetIndex < check.stepIndex) {
|
|
8331
|
+
ctx.errAtLine(target.line, `${check.stepLabel} routes backward to "${target.stepId}" (step ${targetIndex + 1}). Route targets must come after the routing step.`);
|
|
8332
|
+
}
|
|
8333
|
+
}
|
|
8334
|
+
}
|
|
8335
|
+
return steps;
|
|
8336
|
+
}
|
|
8337
|
+
function parseUnit(ctx, raw, path2, stepLabel) {
|
|
8338
|
+
if (!isPlainRecord(raw)) {
|
|
8339
|
+
ctx.err(path2, `${stepLabel} "unit" must be a mapping with an "instructions" key.`);
|
|
8340
|
+
return;
|
|
8341
|
+
}
|
|
8342
|
+
checkUnknownKeys(ctx, raw, path2, UNIT_KEYS, `${stepLabel} "unit"`);
|
|
8343
|
+
const unit = { instructions: "", source: ctx.refAt(path2) };
|
|
8344
|
+
if (typeof raw.instructions === "string" && raw.instructions.trim() !== "") {
|
|
8345
|
+
unit.instructions = raw.instructions;
|
|
8346
|
+
ctx.checkTemplates(raw.instructions, [...path2, "instructions"], `${stepLabel} "instructions"`);
|
|
8347
|
+
} else {
|
|
8348
|
+
ctx.err([...path2, "instructions"], `${stepLabel} "unit" requires non-empty string "instructions".`);
|
|
8349
|
+
}
|
|
8350
|
+
const runner = parseEnumField(ctx, raw.runner, [...path2, "runner"], `${stepLabel} "runner"`, PROGRAM_RUNNER_KINDS);
|
|
8351
|
+
if (runner !== undefined)
|
|
8352
|
+
unit.runner = runner;
|
|
8353
|
+
if (raw.profile !== undefined) {
|
|
8354
|
+
if (typeof raw.profile === "string" && raw.profile.trim() !== "")
|
|
8355
|
+
unit.profile = raw.profile.trim();
|
|
8356
|
+
else
|
|
8357
|
+
ctx.err([...path2, "profile"], `${stepLabel} "profile" must be a non-empty string.`);
|
|
8358
|
+
}
|
|
8359
|
+
if (raw.model !== undefined) {
|
|
8360
|
+
if (typeof raw.model === "string" && raw.model.trim() !== "")
|
|
8361
|
+
unit.model = raw.model.trim();
|
|
8362
|
+
else
|
|
8363
|
+
ctx.err([...path2, "model"], `${stepLabel} "model" must be a non-empty string (a model alias or exact id).`);
|
|
8364
|
+
}
|
|
8365
|
+
const timeoutMs = parseTimeoutField(ctx, raw.timeout, [...path2, "timeout"], `${stepLabel} "timeout"`);
|
|
8366
|
+
if (timeoutMs !== undefined)
|
|
8367
|
+
unit.timeoutMs = timeoutMs;
|
|
8368
|
+
const retry = parseRetry(ctx, raw.retry, [...path2, "retry"], stepLabel);
|
|
8369
|
+
if (retry !== undefined)
|
|
8370
|
+
unit.retry = retry;
|
|
8371
|
+
const onError = parseEnumField(ctx, raw.on_error, [...path2, "on_error"], `${stepLabel} "on_error"`, PROGRAM_ON_ERROR);
|
|
8372
|
+
if (onError !== undefined)
|
|
8373
|
+
unit.onError = onError;
|
|
8374
|
+
const output = parseSchemaObject(ctx, raw.output, [...path2, "output"], `${stepLabel} unit "output"`);
|
|
8375
|
+
if (output !== undefined)
|
|
8376
|
+
unit.output = output;
|
|
8377
|
+
if (raw.env !== undefined) {
|
|
8378
|
+
if (Array.isArray(raw.env) && raw.env.every((entry) => typeof entry === "string" && entry.trim() !== "")) {
|
|
8379
|
+
unit.env = raw.env.map((entry) => entry.trim());
|
|
8380
|
+
} else {
|
|
8381
|
+
ctx.err([...path2, "env"], `${stepLabel} "env" must be a list of non-empty env asset refs.`);
|
|
8382
|
+
}
|
|
8383
|
+
}
|
|
8384
|
+
const isolation = parseEnumField(ctx, raw.isolation, [...path2, "isolation"], `${stepLabel} "isolation"`, PROGRAM_ISOLATION_KINDS);
|
|
8385
|
+
if (isolation !== undefined)
|
|
8386
|
+
unit.isolation = isolation;
|
|
8387
|
+
return unit;
|
|
8388
|
+
}
|
|
8389
|
+
function parseMap(ctx, raw, path2, stepLabel) {
|
|
8390
|
+
if (!isPlainRecord(raw)) {
|
|
8391
|
+
ctx.err(path2, `${stepLabel} "map" must be a mapping with "over" and "unit" keys.`);
|
|
8392
|
+
return;
|
|
8393
|
+
}
|
|
8394
|
+
checkUnknownKeys(ctx, raw, path2, MAP_KEYS, `${stepLabel} "map"`);
|
|
8395
|
+
let over = "";
|
|
8396
|
+
if (typeof raw.over === "string" && raw.over.trim() !== "") {
|
|
8397
|
+
over = raw.over.trim();
|
|
8398
|
+
ctx.checkTemplates(raw.over, [...path2, "over"], `${stepLabel} "over"`);
|
|
8399
|
+
} else {
|
|
8400
|
+
ctx.err([...path2, "over"], `${stepLabel} "map" requires "over": a \${{ … }} expression naming the item list (e.g. \${{ steps.discover.output.files }}).`);
|
|
8401
|
+
}
|
|
8402
|
+
let concurrency;
|
|
8403
|
+
if (raw.concurrency !== undefined) {
|
|
8404
|
+
if (typeof raw.concurrency === "number" && Number.isInteger(raw.concurrency) && raw.concurrency > 0) {
|
|
8405
|
+
concurrency = raw.concurrency;
|
|
8406
|
+
} else {
|
|
8407
|
+
ctx.err([...path2, "concurrency"], `${stepLabel} "concurrency" must be a positive integer.`);
|
|
8408
|
+
}
|
|
8409
|
+
}
|
|
8410
|
+
const reducer = parseEnumField(ctx, raw.reducer, [...path2, "reducer"], `${stepLabel} "reducer"`, PROGRAM_REDUCERS);
|
|
8411
|
+
const unit = raw.unit !== undefined ? parseUnit(ctx, raw.unit, [...path2, "unit"], stepLabel) : undefined;
|
|
8412
|
+
if (raw.unit === undefined) {
|
|
8413
|
+
ctx.err(path2, `${stepLabel} "map" requires a nested "unit" to fan out.`);
|
|
8414
|
+
}
|
|
8415
|
+
if (unit === undefined)
|
|
8416
|
+
return;
|
|
8417
|
+
const map = { over, unit };
|
|
8418
|
+
if (concurrency !== undefined)
|
|
8419
|
+
map.concurrency = concurrency;
|
|
8420
|
+
if (reducer !== undefined)
|
|
8421
|
+
map.reducer = reducer;
|
|
8422
|
+
return map;
|
|
8423
|
+
}
|
|
8424
|
+
function parseRoute(ctx, raw, path2, stepLabel, stepIndex, routeChecks) {
|
|
8425
|
+
if (!isPlainRecord(raw)) {
|
|
8426
|
+
ctx.err(path2, `${stepLabel} "route" must be a mapping with "input" and "when" keys.`);
|
|
8427
|
+
return;
|
|
8428
|
+
}
|
|
8429
|
+
checkUnknownKeys(ctx, raw, path2, ROUTE_KEYS, `${stepLabel} "route"`);
|
|
8430
|
+
let input = "";
|
|
8431
|
+
if (typeof raw.input === "string" && raw.input.trim() !== "") {
|
|
8432
|
+
input = raw.input.trim();
|
|
8433
|
+
ctx.checkTemplates(raw.input, [...path2, "input"], `${stepLabel} "route.input"`);
|
|
8434
|
+
} else {
|
|
8435
|
+
ctx.err([...path2, "input"], `${stepLabel} "route" requires "input": a \${{ … }} expression naming the value to route on.`);
|
|
8436
|
+
}
|
|
8437
|
+
const check = { stepIndex, stepLabel, branches: [] };
|
|
8438
|
+
const whenPath = [...path2, "when"];
|
|
8439
|
+
const whenNode = ctx.nodeAt(whenPath);
|
|
8440
|
+
if (raw.when === undefined || !isPlainRecord(raw.when)) {
|
|
8441
|
+
ctx.err(whenPath, `${stepLabel} "route" requires "when": a mapping of match value to target step id (e.g. when: { pass: ship }).`);
|
|
8442
|
+
} else if ($isMap(whenNode)) {
|
|
8443
|
+
const seenMatches = new Map;
|
|
8444
|
+
for (const pair of whenNode.items) {
|
|
8445
|
+
const keyLine = rangedLine(ctx, pair.key, whenPath);
|
|
8446
|
+
if (!$isScalar(pair.key)) {
|
|
8447
|
+
ctx.errAtLine(keyLine, `${stepLabel} "when" match keys must be scalar values.`);
|
|
8448
|
+
continue;
|
|
8449
|
+
}
|
|
8450
|
+
const match = String(pair.key.value);
|
|
8451
|
+
const valueNode = pair.value;
|
|
8452
|
+
const valueLine = rangedLine(ctx, valueNode, whenPath);
|
|
8453
|
+
const target = $isScalar(valueNode) && typeof valueNode.value === "string" ? valueNode.value.trim() : "";
|
|
8454
|
+
if (target === "") {
|
|
8455
|
+
ctx.errAtLine(valueLine, `${stepLabel} "when: ${match}" must map to a step id string.`);
|
|
8456
|
+
continue;
|
|
8457
|
+
}
|
|
8458
|
+
const firstLine = seenMatches.get(match);
|
|
8459
|
+
if (firstLine !== undefined) {
|
|
8460
|
+
ctx.errAtLine(keyLine, `${stepLabel} has a duplicate "when" match "${match}" (first declared on line ${firstLine}). Matches must be unique.`);
|
|
8461
|
+
continue;
|
|
8462
|
+
}
|
|
8463
|
+
seenMatches.set(match, keyLine);
|
|
8464
|
+
check.branches.push({ match, stepId: target, line: valueLine });
|
|
8465
|
+
}
|
|
8466
|
+
if (check.branches.length === 0 && whenNode.items.length === 0) {
|
|
8467
|
+
ctx.err(whenPath, `${stepLabel} "when" must contain at least one match → step-id entry.`);
|
|
8468
|
+
}
|
|
8469
|
+
} else {
|
|
8470
|
+
for (const [match, target] of Object.entries(raw.when)) {
|
|
8471
|
+
if (typeof target === "string" && target.trim() !== "") {
|
|
8472
|
+
check.branches.push({ match, stepId: target.trim(), line: ctx.lineAt(whenPath) });
|
|
8473
|
+
} else {
|
|
8474
|
+
ctx.err(whenPath, `${stepLabel} "when: ${match}" must map to a step id string.`);
|
|
8475
|
+
}
|
|
8476
|
+
}
|
|
8477
|
+
if (Object.keys(raw.when).length === 0) {
|
|
8478
|
+
ctx.err(whenPath, `${stepLabel} "when" must contain at least one match → step-id entry.`);
|
|
8479
|
+
}
|
|
8480
|
+
}
|
|
8481
|
+
let defaultStepId;
|
|
8482
|
+
if (raw.default !== undefined) {
|
|
8483
|
+
if (typeof raw.default === "string" && raw.default.trim() !== "") {
|
|
8484
|
+
defaultStepId = raw.default.trim();
|
|
8485
|
+
check.defaultTarget = { stepId: defaultStepId, line: ctx.lineAt([...path2, "default"]) };
|
|
8486
|
+
} else {
|
|
8487
|
+
ctx.err([...path2, "default"], `${stepLabel} "route.default" must be a step id string.`);
|
|
8488
|
+
}
|
|
8489
|
+
}
|
|
8490
|
+
routeChecks.push(check);
|
|
8491
|
+
const route = { input, branches: check.branches.map(({ match, stepId }) => ({ match, stepId })) };
|
|
8492
|
+
if (defaultStepId !== undefined)
|
|
8493
|
+
route.defaultStepId = defaultStepId;
|
|
8494
|
+
return route;
|
|
8495
|
+
}
|
|
8496
|
+
function parseGate(ctx, raw, path2, stepLabel) {
|
|
8497
|
+
if (!isPlainRecord(raw)) {
|
|
8498
|
+
ctx.err(path2, `${stepLabel} "gate" must be a mapping with a "criteria" list.`);
|
|
8499
|
+
return;
|
|
8500
|
+
}
|
|
8501
|
+
checkUnknownKeys(ctx, raw, path2, GATE_KEYS, `${stepLabel} "gate"`);
|
|
8502
|
+
const gate = { criteria: [] };
|
|
8503
|
+
if (Array.isArray(raw.criteria) && raw.criteria.length > 0 && raw.criteria.every((c) => typeof c === "string" && c.trim() !== "")) {
|
|
8504
|
+
gate.criteria = raw.criteria.map((c) => c.trim());
|
|
8505
|
+
for (const [i, c] of raw.criteria.entries()) {
|
|
8506
|
+
ctx.checkTemplates(c, [...path2, "criteria", i], `${stepLabel} gate criterion ${i + 1}`);
|
|
8507
|
+
}
|
|
8508
|
+
} else {
|
|
8509
|
+
ctx.err([...path2, "criteria"], `${stepLabel} "gate" requires "criteria": a non-empty list of criterion strings.`);
|
|
8510
|
+
}
|
|
8511
|
+
if (raw.max_loops !== undefined) {
|
|
8512
|
+
if (typeof raw.max_loops === "number" && Number.isInteger(raw.max_loops) && raw.max_loops >= 1) {
|
|
8513
|
+
gate.maxLoops = raw.max_loops;
|
|
8514
|
+
} else {
|
|
8515
|
+
ctx.err([...path2, "max_loops"], `${stepLabel} "gate.max_loops" must be an integer >= 1.`);
|
|
8516
|
+
}
|
|
8517
|
+
}
|
|
8518
|
+
if (raw.required !== undefined) {
|
|
8519
|
+
if (typeof raw.required === "boolean") {
|
|
8520
|
+
gate.required = raw.required;
|
|
8521
|
+
} else {
|
|
8522
|
+
ctx.err([...path2, "required"], `${stepLabel} "gate.required" must be a boolean (true or false).`);
|
|
8523
|
+
}
|
|
8524
|
+
}
|
|
8525
|
+
return gate;
|
|
8526
|
+
}
|
|
8527
|
+
function parseRetry(ctx, raw, path2, stepLabel) {
|
|
8528
|
+
if (raw === undefined)
|
|
8529
|
+
return;
|
|
8530
|
+
if (!isPlainRecord(raw)) {
|
|
8531
|
+
ctx.err(path2, `${stepLabel} "retry" must be a mapping: { max: <n>, on: [<failure_reason>, …] }.`);
|
|
8532
|
+
return;
|
|
8533
|
+
}
|
|
8534
|
+
checkUnknownKeys(ctx, raw, path2, RETRY_KEYS, `${stepLabel} "retry"`);
|
|
8535
|
+
let ok = true;
|
|
8536
|
+
if (!(typeof raw.max === "number" && Number.isInteger(raw.max) && raw.max >= 0)) {
|
|
8537
|
+
ctx.err([...path2, "max"], `${stepLabel} "retry.max" is required and must be a non-negative integer.`);
|
|
8538
|
+
ok = false;
|
|
8539
|
+
}
|
|
8540
|
+
const on = [];
|
|
8541
|
+
if (Array.isArray(raw.on) && raw.on.length > 0) {
|
|
8542
|
+
raw.on.forEach((reason, i) => {
|
|
8543
|
+
if (typeof reason === "string" && PROGRAM_RETRY_REASONS.includes(reason)) {
|
|
8544
|
+
on.push(reason);
|
|
8545
|
+
} else {
|
|
8546
|
+
ctx.err([...path2, "on", i], `${stepLabel} "retry.on" has unknown failure reason ${JSON.stringify(reason)}. Valid reasons: ${PROGRAM_RETRY_REASONS.join(", ")}.`);
|
|
8547
|
+
ok = false;
|
|
8548
|
+
}
|
|
8549
|
+
});
|
|
8550
|
+
} else {
|
|
8551
|
+
ctx.err([...path2, "on"], `${stepLabel} "retry.on" is required and must be a non-empty list of failure reasons (${PROGRAM_RETRY_REASONS.join(", ")}).`);
|
|
8552
|
+
ok = false;
|
|
8553
|
+
}
|
|
8554
|
+
return ok ? { max: raw.max, on } : undefined;
|
|
8555
|
+
}
|
|
8556
|
+
function parseTimeoutField(ctx, raw, path2, label) {
|
|
8557
|
+
if (raw === undefined)
|
|
8558
|
+
return;
|
|
8559
|
+
if (typeof raw === "number") {
|
|
8560
|
+
if (Number.isInteger(raw) && raw > 0)
|
|
8561
|
+
return raw;
|
|
8562
|
+
ctx.err(path2, `${label} has a non-positive timeout ${JSON.stringify(raw)}. ${TIMEOUT_HINT}.`);
|
|
8563
|
+
return;
|
|
8564
|
+
}
|
|
8565
|
+
if (typeof raw !== "string") {
|
|
8566
|
+
ctx.err(path2, `${label} must be a duration string. ${TIMEOUT_HINT}.`);
|
|
8567
|
+
return;
|
|
8568
|
+
}
|
|
8569
|
+
const value = raw.trim().toLowerCase();
|
|
8570
|
+
if (value === "none")
|
|
8571
|
+
return null;
|
|
8572
|
+
const match = value.match(TIMEOUT_VALUE);
|
|
8573
|
+
if (!match) {
|
|
8574
|
+
ctx.err(path2, `${label} has an invalid timeout "${raw}". ${TIMEOUT_HINT}.`);
|
|
8575
|
+
return;
|
|
8576
|
+
}
|
|
8577
|
+
const n = Number.parseInt(match[1], 10);
|
|
8578
|
+
const unit = match[2] ?? "ms";
|
|
8579
|
+
const timeoutMs = unit === "m" ? n * 60000 : unit === "s" ? n * 1000 : n;
|
|
8580
|
+
if (timeoutMs <= 0) {
|
|
8581
|
+
ctx.err(path2, `${label} has a non-positive timeout "${raw}". Use a positive duration or "none".`);
|
|
8582
|
+
return;
|
|
8583
|
+
}
|
|
8584
|
+
return timeoutMs;
|
|
8585
|
+
}
|
|
8586
|
+
function parseEnumField(ctx, raw, path2, label, allowed) {
|
|
8587
|
+
if (raw === undefined)
|
|
8588
|
+
return;
|
|
8589
|
+
if (typeof raw === "string" && allowed.includes(raw))
|
|
8590
|
+
return raw;
|
|
8591
|
+
ctx.err(path2, `${label} must be one of: ${allowed.join(" | ")} (got ${JSON.stringify(raw)}).`);
|
|
8592
|
+
return;
|
|
8593
|
+
}
|
|
8594
|
+
function parseSchemaObject(ctx, raw, path2, label) {
|
|
8595
|
+
if (raw === undefined)
|
|
8596
|
+
return;
|
|
8597
|
+
if (!isPlainRecord(raw)) {
|
|
8598
|
+
ctx.err(path2, `${label} must be a JSON Schema object (e.g. { type: object, properties: { … } }).`);
|
|
8599
|
+
return;
|
|
8600
|
+
}
|
|
8601
|
+
return raw;
|
|
8602
|
+
}
|
|
8603
|
+
function checkUnknownKeys(ctx, obj, path2, allowed, label) {
|
|
8604
|
+
for (const key of Object.keys(obj)) {
|
|
8605
|
+
if (!allowed.includes(key)) {
|
|
8606
|
+
ctx.err([...path2, key], `Unknown ${label} key "${key}". Allowed keys: ${allowed.join(", ")}.`);
|
|
8607
|
+
}
|
|
8608
|
+
}
|
|
8609
|
+
}
|
|
8610
|
+
function rangedLine(ctx, node, fallbackPath) {
|
|
8611
|
+
const range = node?.range;
|
|
8612
|
+
return range ? ctx.lineAtOffset(range[0]) : ctx.lineAt(fallbackPath);
|
|
8613
|
+
}
|
|
8614
|
+
function checkTemplates(ctx, text, path2, label) {
|
|
8615
|
+
let idx = 0;
|
|
8616
|
+
while (true) {
|
|
8617
|
+
const open = text.indexOf("${{", idx);
|
|
8618
|
+
if (open === -1)
|
|
8619
|
+
break;
|
|
8620
|
+
const close = text.indexOf("}}", open + 3);
|
|
8621
|
+
const nextOpen = text.indexOf("${{", open + 3);
|
|
8622
|
+
if (close === -1 || nextOpen !== -1 && nextOpen < close) {
|
|
8623
|
+
ctx.err(path2, `${label} contains an unterminated "\${{" expression. Close it with "}}".`);
|
|
8624
|
+
return;
|
|
8625
|
+
}
|
|
8626
|
+
idx = close + 2;
|
|
8627
|
+
}
|
|
8628
|
+
const checker = loadExpressionChecker();
|
|
8629
|
+
if (checker) {
|
|
8630
|
+
const message = checker(text);
|
|
8631
|
+
if (message !== null)
|
|
8632
|
+
ctx.err(path2, `${label}: ${message}`);
|
|
8633
|
+
}
|
|
8634
|
+
}
|
|
8635
|
+
function loadExpressionChecker() {
|
|
8636
|
+
if (cachedExpressionChecker !== undefined)
|
|
8637
|
+
return cachedExpressionChecker;
|
|
8638
|
+
cachedExpressionChecker = null;
|
|
8639
|
+
let candidate;
|
|
8640
|
+
try {
|
|
8641
|
+
const requireModule = createRequire4(import.meta.url);
|
|
8642
|
+
const specifier = "./expressions";
|
|
8643
|
+
const mod = requireModule(specifier);
|
|
8644
|
+
candidate = [mod.parseTemplate, mod.compileTemplate, mod.parseTemplateString, mod.tokenizeTemplate].find((fn) => typeof fn === "function");
|
|
8645
|
+
} catch {
|
|
8646
|
+
return cachedExpressionChecker;
|
|
8647
|
+
}
|
|
8648
|
+
if (!candidate)
|
|
8649
|
+
return cachedExpressionChecker;
|
|
8650
|
+
const parseTemplate = candidate;
|
|
8651
|
+
cachedExpressionChecker = (text) => {
|
|
8652
|
+
try {
|
|
8653
|
+
const result = parseTemplate(text);
|
|
8654
|
+
if (isPlainRecord(result) && result.ok === false) {
|
|
8655
|
+
const errs = result.errors;
|
|
8656
|
+
if (Array.isArray(errs) && errs.length > 0) {
|
|
8657
|
+
const first = errs[0];
|
|
8658
|
+
if (typeof first === "string")
|
|
8659
|
+
return first;
|
|
8660
|
+
if (isPlainRecord(first) && typeof first.message === "string")
|
|
8661
|
+
return first.message;
|
|
8662
|
+
}
|
|
8663
|
+
if (typeof result.error === "string")
|
|
8664
|
+
return result.error;
|
|
8665
|
+
return `malformed \${{ … }} expression`;
|
|
8666
|
+
}
|
|
8667
|
+
return null;
|
|
8668
|
+
} catch {
|
|
8669
|
+
return null;
|
|
8670
|
+
}
|
|
8671
|
+
};
|
|
8672
|
+
return cachedExpressionChecker;
|
|
8673
|
+
}
|
|
8674
|
+
function isPlainRecord(value) {
|
|
8675
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8060
8676
|
}
|
|
8061
|
-
|
|
8062
|
-
|
|
8677
|
+
function describeError(cause) {
|
|
8678
|
+
return cause instanceof Error ? cause.message : String(cause);
|
|
8679
|
+
}
|
|
8680
|
+
function yamlErrorMessage(message) {
|
|
8681
|
+
const first = message.split(`
|
|
8682
|
+
`, 1)[0] ?? message;
|
|
8683
|
+
return first.replace(/ at line \d+, column \d+:?\s*$/, "").trim();
|
|
8684
|
+
}
|
|
8685
|
+
var TOP_LEVEL_KEYS, DEFAULTS_KEYS, BUDGET_KEYS, STEP_KEYS, UNIT_KEYS, MAP_KEYS, ROUTE_KEYS, RETRY_KEYS, GATE_KEYS, STEP_KINDS, TIMEOUT_VALUE, TIMEOUT_HINT = `Use "<n>ms", "<n>s", "<n>m" (e.g. "10m"), or "none"`, cachedExpressionChecker;
|
|
8686
|
+
var init_parser2 = __esm(() => {
|
|
8063
8687
|
init_dist();
|
|
8064
|
-
|
|
8065
|
-
|
|
8066
|
-
|
|
8067
|
-
|
|
8688
|
+
init_schema();
|
|
8689
|
+
TOP_LEVEL_KEYS = ["version", "name", "description", "params", "defaults", "budget", "steps"];
|
|
8690
|
+
DEFAULTS_KEYS = ["runner", "model", "timeout", "on_error"];
|
|
8691
|
+
BUDGET_KEYS = ["max_tokens", "max_units"];
|
|
8692
|
+
STEP_KEYS = ["id", "title", "unit", "map", "route", "output", "gate"];
|
|
8693
|
+
UNIT_KEYS = [
|
|
8694
|
+
"runner",
|
|
8695
|
+
"profile",
|
|
8696
|
+
"model",
|
|
8697
|
+
"timeout",
|
|
8698
|
+
"retry",
|
|
8699
|
+
"on_error",
|
|
8700
|
+
"instructions",
|
|
8701
|
+
"output",
|
|
8702
|
+
"env",
|
|
8703
|
+
"isolation"
|
|
8704
|
+
];
|
|
8705
|
+
MAP_KEYS = ["over", "concurrency", "reducer", "unit"];
|
|
8706
|
+
ROUTE_KEYS = ["input", "when", "default"];
|
|
8707
|
+
RETRY_KEYS = ["max", "on"];
|
|
8708
|
+
GATE_KEYS = ["criteria", "max_loops", "required"];
|
|
8709
|
+
STEP_KINDS = ["unit", "map", "route"];
|
|
8710
|
+
TIMEOUT_VALUE = /^(\d+)(ms|s|m)?$/;
|
|
8068
8711
|
});
|
|
8069
8712
|
|
|
8713
|
+
// src/workflows/program/project.ts
|
|
8714
|
+
function programStepInstructions(step) {
|
|
8715
|
+
if (step.unit)
|
|
8716
|
+
return step.unit.instructions;
|
|
8717
|
+
if (step.map)
|
|
8718
|
+
return step.map.unit.instructions;
|
|
8719
|
+
if (step.route) {
|
|
8720
|
+
const branches = step.route.branches.map((b) => `"${b.match}" -> ${b.stepId}`);
|
|
8721
|
+
if (step.route.defaultStepId !== undefined)
|
|
8722
|
+
branches.push(`default -> ${step.route.defaultStepId}`);
|
|
8723
|
+
return `Route on ${step.route.input}: ${branches.join(", ")}.`;
|
|
8724
|
+
}
|
|
8725
|
+
return "";
|
|
8726
|
+
}
|
|
8727
|
+
function projectProgramParameters(program) {
|
|
8728
|
+
if (!program.params)
|
|
8729
|
+
return;
|
|
8730
|
+
const parameters = Object.entries(program.params).map(([name, schema]) => {
|
|
8731
|
+
const description = schema.description;
|
|
8732
|
+
return {
|
|
8733
|
+
name,
|
|
8734
|
+
...typeof description === "string" && description !== "" ? { description } : {}
|
|
8735
|
+
};
|
|
8736
|
+
});
|
|
8737
|
+
return parameters.length > 0 ? parameters : undefined;
|
|
8738
|
+
}
|
|
8739
|
+
var WORKFLOW_PROGRAM_RENDERER_NAME = "workflow-program-yaml";
|
|
8740
|
+
var init_project = () => {};
|
|
8741
|
+
|
|
8070
8742
|
// src/workflows/runtime/document-cache.ts
|
|
8071
8743
|
function cacheWorkflowDocument(entry, doc) {
|
|
8072
8744
|
cache.set(entry, doc);
|
|
@@ -8087,7 +8759,16 @@ function loadDocument(ctx) {
|
|
|
8087
8759
|
const result = parseWorkflow(ctx.content(), { path: ctx.relPath });
|
|
8088
8760
|
if (result.ok)
|
|
8089
8761
|
return result.document;
|
|
8090
|
-
const summary = result.errors.map((e) => `${ctx.relPath}:${e.line}
|
|
8762
|
+
const summary = result.errors.map((e) => `${ctx.relPath}:${e.line} — ${e.message}`).join(`
|
|
8763
|
+
`);
|
|
8764
|
+
throw new UsageError(`Workflow has errors:
|
|
8765
|
+
${summary}`);
|
|
8766
|
+
}
|
|
8767
|
+
function loadProgram(ctx) {
|
|
8768
|
+
const result = parseWorkflowProgram(ctx.content(), { path: ctx.relPath });
|
|
8769
|
+
if (result.ok)
|
|
8770
|
+
return result.program;
|
|
8771
|
+
const summary = result.errors.map((e) => `${ctx.relPath}:${e.line} — ${e.message}`).join(`
|
|
8091
8772
|
`);
|
|
8092
8773
|
throw new UsageError(`Workflow has errors:
|
|
8093
8774
|
${summary}`);
|
|
@@ -8097,6 +8778,8 @@ var init_renderer = __esm(() => {
|
|
|
8097
8778
|
init_errors();
|
|
8098
8779
|
init_metadata_contributors();
|
|
8099
8780
|
init_parser();
|
|
8781
|
+
init_parser2();
|
|
8782
|
+
init_project();
|
|
8100
8783
|
init_document_cache();
|
|
8101
8784
|
registerMetadataContributor({
|
|
8102
8785
|
name: "workflow-document-metadata",
|
|
@@ -8123,6 +8806,32 @@ var init_renderer = __esm(() => {
|
|
|
8123
8806
|
cacheWorkflowDocument(entry, doc);
|
|
8124
8807
|
}
|
|
8125
8808
|
});
|
|
8809
|
+
registerMetadataContributor({
|
|
8810
|
+
name: "workflow-program-metadata",
|
|
8811
|
+
appliesTo: ({ rendererName }) => rendererName === WORKFLOW_PROGRAM_RENDERER_NAME,
|
|
8812
|
+
contribute(entry, { renderContext }) {
|
|
8813
|
+
const program = loadProgram(renderContext);
|
|
8814
|
+
const hints = new Set(entry.searchHints ?? []);
|
|
8815
|
+
hints.add(program.name);
|
|
8816
|
+
for (const step of program.steps) {
|
|
8817
|
+
hints.add(step.id);
|
|
8818
|
+
if (step.title)
|
|
8819
|
+
hints.add(step.title);
|
|
8820
|
+
hints.add(programStepInstructions(step));
|
|
8821
|
+
for (const criterion of step.gate?.criteria ?? []) {
|
|
8822
|
+
hints.add(criterion);
|
|
8823
|
+
}
|
|
8824
|
+
}
|
|
8825
|
+
entry.searchHints = Array.from(hints).filter(Boolean);
|
|
8826
|
+
if (!entry.description && program.description) {
|
|
8827
|
+
entry.description = program.description;
|
|
8828
|
+
}
|
|
8829
|
+
const parameters = projectProgramParameters(program);
|
|
8830
|
+
if (parameters?.length) {
|
|
8831
|
+
entry.parameters = parameters;
|
|
8832
|
+
}
|
|
8833
|
+
}
|
|
8834
|
+
});
|
|
8126
8835
|
});
|
|
8127
8836
|
|
|
8128
8837
|
// src/output/renderers.ts
|
|
@@ -8151,6 +8860,25 @@ function applyTocMetadata(entry, ctx) {
|
|
|
8151
8860
|
entry.toc = toc.headings;
|
|
8152
8861
|
} catch {}
|
|
8153
8862
|
}
|
|
8863
|
+
function applyFactMetadata(entry, ctx) {
|
|
8864
|
+
try {
|
|
8865
|
+
const fm = applyFrontmatterDescriptionAndTags(entry, ctx);
|
|
8866
|
+
const tags = new Set([...entry.tags ?? [], "fact"]);
|
|
8867
|
+
const hints = new Set(entry.searchHints ?? []);
|
|
8868
|
+
const category = asNonEmptyString(fm.category);
|
|
8869
|
+
if (category) {
|
|
8870
|
+
tags.add(category);
|
|
8871
|
+
hints.add(`category:${category}`);
|
|
8872
|
+
}
|
|
8873
|
+
if (fm.pinned === true) {
|
|
8874
|
+
tags.add("pinned");
|
|
8875
|
+
hints.add("pinned");
|
|
8876
|
+
}
|
|
8877
|
+
entry.tags = Array.from(tags).filter(Boolean);
|
|
8878
|
+
if (hints.size > 0)
|
|
8879
|
+
entry.searchHints = Array.from(hints).filter(Boolean);
|
|
8880
|
+
} catch {}
|
|
8881
|
+
}
|
|
8154
8882
|
function applyFrontmatterDescriptionAndTags(entry, ctx) {
|
|
8155
8883
|
const parsed = parseFrontmatter(ctx.content());
|
|
8156
8884
|
const fm = parsed.data;
|
|
@@ -8216,12 +8944,7 @@ function applyScriptMetadata(entry, ctx) {
|
|
|
8216
8944
|
}
|
|
8217
8945
|
}
|
|
8218
8946
|
function applyEnvMetadata(entry, ctx) {
|
|
8219
|
-
const { keys
|
|
8220
|
-
if (comments.length > 0 && !entry.description) {
|
|
8221
|
-
entry.description = comments.join(" ").slice(0, 500);
|
|
8222
|
-
entry.source = "comments";
|
|
8223
|
-
entry.confidence = 0.7;
|
|
8224
|
-
}
|
|
8947
|
+
const { keys } = listKeys(ctx.absPath);
|
|
8225
8948
|
if (keys.length > 0) {
|
|
8226
8949
|
entry.searchHints = keys;
|
|
8227
8950
|
}
|
|
@@ -8250,6 +8973,7 @@ function applyTaskMetadata(entry, ctx) {
|
|
|
8250
8973
|
}
|
|
8251
8974
|
var init_renderers = __esm(() => {
|
|
8252
8975
|
init_env();
|
|
8976
|
+
init_frontmatter();
|
|
8253
8977
|
init_markdown();
|
|
8254
8978
|
init_common();
|
|
8255
8979
|
init_metadata();
|
|
@@ -8296,6 +9020,11 @@ var init_renderers = __esm(() => {
|
|
|
8296
9020
|
appliesTo: ({ rendererName }) => rendererName === "session-md",
|
|
8297
9021
|
contribute: (entry, ctx) => applySessionMetadata(entry, ctx.renderContext)
|
|
8298
9022
|
});
|
|
9023
|
+
registerMetadataContributor({
|
|
9024
|
+
name: "fact-md-metadata",
|
|
9025
|
+
appliesTo: ({ rendererName }) => rendererName === "fact-md",
|
|
9026
|
+
contribute: (entry, ctx) => applyFactMetadata(entry, ctx.renderContext)
|
|
9027
|
+
});
|
|
8299
9028
|
});
|
|
8300
9029
|
|
|
8301
9030
|
// src/core/asset/asset-registry.ts
|
|
@@ -8304,24 +9033,52 @@ var init_asset_registry = __esm(() => {
|
|
|
8304
9033
|
});
|
|
8305
9034
|
|
|
8306
9035
|
// src/core/asset/asset-spec.ts
|
|
8307
|
-
import
|
|
9036
|
+
import fs5 from "node:fs";
|
|
9037
|
+
import path2 from "node:path";
|
|
9038
|
+
function toPosix2(input) {
|
|
9039
|
+
return input.replace(/\\/g, "/");
|
|
9040
|
+
}
|
|
8308
9041
|
function getAssetTypes() {
|
|
8309
9042
|
return Object.keys(ASSET_SPECS_INTERNAL);
|
|
8310
9043
|
}
|
|
8311
|
-
var buildTaskAction = (ref) => `akm tasks show ${ref.replace(/^task:/, "")} -> inspect; akm tasks run <id> -> run now; akm tasks remove <id> -> unschedule`, markdownSpec, SCRIPT_EXTENSIONS, scriptSpec, ASSET_SPECS_INTERNAL, TYPE_DIRS;
|
|
9044
|
+
var buildTaskAction = (ref) => `akm tasks show ${ref.replace(/^task:/, "")} -> inspect; akm tasks run <id> -> run now; akm tasks remove <id> -> unschedule`, WORKFLOW_EXTENSIONS, workflowSpec, markdownSpec, SCRIPT_EXTENSIONS, scriptSpec, ASSET_SPECS_INTERNAL, TYPE_DIRS;
|
|
8312
9045
|
var init_asset_spec = __esm(() => {
|
|
8313
9046
|
init_renderers();
|
|
8314
|
-
init_common();
|
|
8315
9047
|
init_asset_registry();
|
|
9048
|
+
WORKFLOW_EXTENSIONS = [".md", ".yaml", ".yml"];
|
|
9049
|
+
workflowSpec = {
|
|
9050
|
+
isRelevantFile: (fileName) => WORKFLOW_EXTENSIONS.includes(path2.extname(fileName).toLowerCase()),
|
|
9051
|
+
toCanonicalName: (typeRoot, filePath) => {
|
|
9052
|
+
const rel = toPosix2(path2.relative(typeRoot, filePath));
|
|
9053
|
+
for (const ext of WORKFLOW_EXTENSIONS) {
|
|
9054
|
+
if (rel.toLowerCase().endsWith(ext))
|
|
9055
|
+
return rel.slice(0, -ext.length);
|
|
9056
|
+
}
|
|
9057
|
+
return rel;
|
|
9058
|
+
},
|
|
9059
|
+
toAssetPath: (typeRoot, name) => {
|
|
9060
|
+
const lower = name.toLowerCase();
|
|
9061
|
+
for (const ext of WORKFLOW_EXTENSIONS) {
|
|
9062
|
+
if (lower.endsWith(ext))
|
|
9063
|
+
return path2.join(typeRoot, name);
|
|
9064
|
+
}
|
|
9065
|
+
for (const ext of WORKFLOW_EXTENSIONS) {
|
|
9066
|
+
const candidate = path2.join(typeRoot, `${name}${ext}`);
|
|
9067
|
+
if (fs5.existsSync(candidate))
|
|
9068
|
+
return candidate;
|
|
9069
|
+
}
|
|
9070
|
+
return path2.join(typeRoot, `${name}.md`);
|
|
9071
|
+
}
|
|
9072
|
+
};
|
|
8316
9073
|
markdownSpec = {
|
|
8317
|
-
isRelevantFile: (fileName) =>
|
|
9074
|
+
isRelevantFile: (fileName) => path2.extname(fileName).toLowerCase() === ".md",
|
|
8318
9075
|
toCanonicalName: (typeRoot, filePath) => {
|
|
8319
|
-
const rel =
|
|
9076
|
+
const rel = toPosix2(path2.relative(typeRoot, filePath));
|
|
8320
9077
|
return rel.endsWith(".md") ? rel.slice(0, -3) : rel;
|
|
8321
9078
|
},
|
|
8322
9079
|
toAssetPath: (typeRoot, name) => {
|
|
8323
9080
|
const withExt = name.endsWith(".md") ? name : `${name}.md`;
|
|
8324
|
-
return
|
|
9081
|
+
return path2.join(typeRoot, withExt);
|
|
8325
9082
|
}
|
|
8326
9083
|
};
|
|
8327
9084
|
SCRIPT_EXTENSIONS = new Set([
|
|
@@ -8343,28 +9100,28 @@ var init_asset_spec = __esm(() => {
|
|
|
8343
9100
|
".kts"
|
|
8344
9101
|
]);
|
|
8345
9102
|
scriptSpec = {
|
|
8346
|
-
isRelevantFile: (fileName) => SCRIPT_EXTENSIONS.has(
|
|
8347
|
-
toCanonicalName: (typeRoot, filePath) =>
|
|
8348
|
-
toAssetPath: (typeRoot, name) =>
|
|
9103
|
+
isRelevantFile: (fileName) => SCRIPT_EXTENSIONS.has(path2.extname(fileName).toLowerCase()),
|
|
9104
|
+
toCanonicalName: (typeRoot, filePath) => toPosix2(path2.relative(typeRoot, filePath)),
|
|
9105
|
+
toAssetPath: (typeRoot, name) => path2.join(typeRoot, name)
|
|
8349
9106
|
};
|
|
8350
9107
|
ASSET_SPECS_INTERNAL = {
|
|
8351
9108
|
skill: {
|
|
8352
9109
|
stashDir: "skills",
|
|
8353
9110
|
isRelevantFile: (fileName) => fileName === "SKILL.md",
|
|
8354
9111
|
toCanonicalName: (typeRoot, filePath) => {
|
|
8355
|
-
const relDir =
|
|
9112
|
+
const relDir = toPosix2(path2.dirname(path2.relative(typeRoot, filePath)));
|
|
8356
9113
|
if (!relDir || relDir === ".")
|
|
8357
9114
|
return;
|
|
8358
9115
|
return relDir;
|
|
8359
9116
|
},
|
|
8360
|
-
toAssetPath: (typeRoot, name) =>
|
|
9117
|
+
toAssetPath: (typeRoot, name) => path2.join(typeRoot, name, "SKILL.md")
|
|
8361
9118
|
},
|
|
8362
9119
|
command: { stashDir: "commands", ...markdownSpec },
|
|
8363
9120
|
agent: { stashDir: "agents", ...markdownSpec },
|
|
8364
9121
|
knowledge: { stashDir: "knowledge", ...markdownSpec },
|
|
8365
9122
|
workflow: {
|
|
8366
9123
|
stashDir: "workflows",
|
|
8367
|
-
...
|
|
9124
|
+
...workflowSpec,
|
|
8368
9125
|
rendererName: "workflow-md",
|
|
8369
9126
|
actionBuilder: (ref) => buildWorkflowAction(ref)
|
|
8370
9127
|
},
|
|
@@ -8374,10 +9131,10 @@ var init_asset_spec = __esm(() => {
|
|
|
8374
9131
|
stashDir: "env",
|
|
8375
9132
|
isRelevantFile: (fileName) => fileName === ".env" || fileName.endsWith(".env"),
|
|
8376
9133
|
toCanonicalName: (typeRoot, filePath) => {
|
|
8377
|
-
const rel =
|
|
8378
|
-
const fileName =
|
|
9134
|
+
const rel = toPosix2(path2.relative(typeRoot, filePath));
|
|
9135
|
+
const fileName = path2.basename(rel);
|
|
8379
9136
|
if (fileName === ".env") {
|
|
8380
|
-
const dir =
|
|
9137
|
+
const dir = path2.dirname(rel);
|
|
8381
9138
|
return dir === "." || dir === "" ? "default" : `${dir}/default`;
|
|
8382
9139
|
}
|
|
8383
9140
|
const stripped = rel.endsWith(".env") ? rel.slice(0, -4) : rel;
|
|
@@ -8385,17 +9142,17 @@ var init_asset_spec = __esm(() => {
|
|
|
8385
9142
|
},
|
|
8386
9143
|
toAssetPath: (typeRoot, name) => {
|
|
8387
9144
|
if (name === "default")
|
|
8388
|
-
return
|
|
8389
|
-
return
|
|
9145
|
+
return path2.join(typeRoot, ".env");
|
|
9146
|
+
return path2.join(typeRoot, name.endsWith(".env") ? name : `${name}.env`);
|
|
8390
9147
|
},
|
|
8391
9148
|
rendererName: "env-file",
|
|
8392
|
-
actionBuilder: (ref) => `akm show ${ref} -> inspect key names; akm env run ${ref} -- <command> -> run with the whole .env injected (
|
|
9149
|
+
actionBuilder: (ref) => `akm show ${ref} -> inspect key names; akm env run ${ref} -- <command> -> run with the whole .env injected (prefer --clean to minimize inherited parent env; child stdout is not redacted); akm env export ${ref} --out <file> -> write a sourceable script to a file`
|
|
8393
9150
|
},
|
|
8394
9151
|
secret: {
|
|
8395
9152
|
stashDir: "secrets",
|
|
8396
9153
|
isRelevantFile: (fileName) => !fileName.endsWith(".lock") && !fileName.endsWith(".sensitive"),
|
|
8397
|
-
toCanonicalName: (typeRoot, filePath) =>
|
|
8398
|
-
toAssetPath: (typeRoot, name) =>
|
|
9154
|
+
toCanonicalName: (typeRoot, filePath) => toPosix2(path2.relative(typeRoot, filePath)),
|
|
9155
|
+
toAssetPath: (typeRoot, name) => path2.join(typeRoot, name),
|
|
8399
9156
|
rendererName: "secret-file",
|
|
8400
9157
|
actionBuilder: (ref) => `akm show ${ref} -> name only (value never shown); akm secret path ${ref} -> file path; akm secret run ${ref} <VAR> -- <command> -> run with value injected into $VAR`
|
|
8401
9158
|
},
|
|
@@ -8413,14 +9170,14 @@ var init_asset_spec = __esm(() => {
|
|
|
8413
9170
|
},
|
|
8414
9171
|
task: {
|
|
8415
9172
|
stashDir: "tasks",
|
|
8416
|
-
isRelevantFile: (fileName) =>
|
|
9173
|
+
isRelevantFile: (fileName) => path2.extname(fileName).toLowerCase() === ".yml",
|
|
8417
9174
|
toCanonicalName: (typeRoot, filePath) => {
|
|
8418
|
-
const rel =
|
|
9175
|
+
const rel = toPosix2(path2.relative(typeRoot, filePath));
|
|
8419
9176
|
return rel.endsWith(".yml") ? rel.slice(0, -4) : rel;
|
|
8420
9177
|
},
|
|
8421
9178
|
toAssetPath: (typeRoot, name) => {
|
|
8422
9179
|
const withExt = name.endsWith(".yml") ? name : `${name}.yml`;
|
|
8423
|
-
return
|
|
9180
|
+
return path2.join(typeRoot, withExt);
|
|
8424
9181
|
},
|
|
8425
9182
|
rendererName: "task-yaml",
|
|
8426
9183
|
actionBuilder: buildTaskAction
|
|
@@ -8430,15 +9187,18 @@ var init_asset_spec = __esm(() => {
|
|
|
8430
9187
|
...markdownSpec,
|
|
8431
9188
|
rendererName: "session-md",
|
|
8432
9189
|
actionBuilder: (ref) => `akm show ${ref} -> read the session summary; follow the \`access\` frontmatter to open the raw log at \`log_path\``
|
|
9190
|
+
},
|
|
9191
|
+
fact: {
|
|
9192
|
+
stashDir: "facts",
|
|
9193
|
+
...markdownSpec,
|
|
9194
|
+
rendererName: "fact-md",
|
|
9195
|
+
actionBuilder: (ref) => `akm show ${ref} -> read the stash fact and apply it as durable context`
|
|
8433
9196
|
}
|
|
8434
9197
|
};
|
|
8435
9198
|
TYPE_DIRS = Object.fromEntries(Object.entries(ASSET_SPECS_INTERNAL).map(([type, spec]) => [type, spec.stashDir]));
|
|
8436
9199
|
});
|
|
8437
9200
|
|
|
8438
9201
|
// src/core/common.ts
|
|
8439
|
-
function toPosix(input) {
|
|
8440
|
-
return input.replace(/\\/g, "/");
|
|
8441
|
-
}
|
|
8442
9202
|
function asNonEmptyString(value) {
|
|
8443
9203
|
if (typeof value !== "string")
|
|
8444
9204
|
return;
|
|
@@ -8457,7 +9217,7 @@ var init_common = __esm(() => {
|
|
|
8457
9217
|
});
|
|
8458
9218
|
|
|
8459
9219
|
// src/core/paths.ts
|
|
8460
|
-
import
|
|
9220
|
+
import path3 from "node:path";
|
|
8461
9221
|
function isUnderBunTest(env) {
|
|
8462
9222
|
return env.BUN_TEST === "1" || env.NODE_ENV === "test";
|
|
8463
9223
|
}
|
|
@@ -8474,23 +9234,23 @@ function getDataDir(env = process.env, platform = process.platform) {
|
|
|
8474
9234
|
if (platform === "win32") {
|
|
8475
9235
|
const localAppData = env.LOCALAPPDATA?.trim();
|
|
8476
9236
|
if (localAppData)
|
|
8477
|
-
return
|
|
9237
|
+
return path3.join(localAppData, "akm", "data");
|
|
8478
9238
|
const userProfile = env.USERPROFILE?.trim();
|
|
8479
9239
|
if (userProfile)
|
|
8480
|
-
return
|
|
9240
|
+
return path3.join(userProfile, "AppData", "Local", "akm", "data");
|
|
8481
9241
|
const appData = env.APPDATA?.trim();
|
|
8482
9242
|
if (!appData) {
|
|
8483
9243
|
throw new ConfigError("Unable to determine data directory. Set LOCALAPPDATA, USERPROFILE, or APPDATA.", "CONFIG_DIR_UNRESOLVABLE");
|
|
8484
9244
|
}
|
|
8485
|
-
return
|
|
9245
|
+
return path3.join(appData, "..", "Local", "akm", "data");
|
|
8486
9246
|
}
|
|
8487
9247
|
const xdgDataHome = env.XDG_DATA_HOME?.trim();
|
|
8488
9248
|
if (xdgDataHome)
|
|
8489
|
-
return
|
|
9249
|
+
return path3.join(xdgDataHome, "akm");
|
|
8490
9250
|
const home = env.HOME?.trim();
|
|
8491
9251
|
if (!home)
|
|
8492
|
-
return
|
|
8493
|
-
return
|
|
9252
|
+
return path3.join("/tmp", "akm-data");
|
|
9253
|
+
return path3.join(home, ".local", "share", "akm");
|
|
8494
9254
|
}
|
|
8495
9255
|
var init_paths = __esm(() => {
|
|
8496
9256
|
init_common();
|
|
@@ -8498,22 +9258,40 @@ var init_paths = __esm(() => {
|
|
|
8498
9258
|
});
|
|
8499
9259
|
|
|
8500
9260
|
// scripts/migrations/import-fs-improve-runs-to-db.ts
|
|
8501
|
-
import
|
|
8502
|
-
import
|
|
9261
|
+
import fs6 from "fs";
|
|
9262
|
+
import path5 from "path";
|
|
8503
9263
|
|
|
8504
9264
|
// src/core/state-db.ts
|
|
8505
|
-
import
|
|
8506
|
-
|
|
9265
|
+
import path4 from "node:path";
|
|
9266
|
+
|
|
9267
|
+
// src/storage/managed-db.ts
|
|
9268
|
+
import fs2 from "node:fs";
|
|
9269
|
+
import path from "node:path";
|
|
8507
9270
|
|
|
8508
9271
|
// src/storage/database.ts
|
|
8509
|
-
import { createRequire } from "module";
|
|
9272
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
8510
9273
|
var isBun = !!process.versions?.bun;
|
|
8511
|
-
var nodeRequire =
|
|
8512
|
-
|
|
8513
|
-
|
|
8514
|
-
|
|
9274
|
+
var nodeRequire = createRequire2(import.meta.url);
|
|
9275
|
+
var bunSqliteProvider = {
|
|
9276
|
+
name: "bun:sqlite",
|
|
9277
|
+
supported: () => isBun,
|
|
9278
|
+
open: openBunDatabase
|
|
9279
|
+
};
|
|
9280
|
+
var nodeSqliteProvider = {
|
|
9281
|
+
name: "better-sqlite3",
|
|
9282
|
+
supported: () => !isBun,
|
|
9283
|
+
open: openNodeDatabase
|
|
9284
|
+
};
|
|
9285
|
+
var PROVIDERS = [bunSqliteProvider, nodeSqliteProvider];
|
|
9286
|
+
function selectProvider() {
|
|
9287
|
+
const provider = PROVIDERS.find((p) => p.supported());
|
|
9288
|
+
if (!provider) {
|
|
9289
|
+
throw new Error(`No storage provider supports the current runtime (${isBun ? "Bun" : "Node"}).`);
|
|
8515
9290
|
}
|
|
8516
|
-
return
|
|
9291
|
+
return provider;
|
|
9292
|
+
}
|
|
9293
|
+
function openDatabase(path, opts) {
|
|
9294
|
+
return selectProvider().open(path, opts);
|
|
8517
9295
|
}
|
|
8518
9296
|
function openBunDatabase(path, opts) {
|
|
8519
9297
|
const { Database: BunDatabase } = loadBunSqlite();
|
|
@@ -8538,7 +9316,16 @@ function loadBunSqlite() {
|
|
|
8538
9316
|
var betterSqlite3Ctor;
|
|
8539
9317
|
function loadBetterSqlite3() {
|
|
8540
9318
|
if (!betterSqlite3Ctor) {
|
|
8541
|
-
|
|
9319
|
+
let mod;
|
|
9320
|
+
try {
|
|
9321
|
+
mod = nodeRequire("better-sqlite3");
|
|
9322
|
+
} catch (err) {
|
|
9323
|
+
throw new Error(`akm could not load 'better-sqlite3', the SQLite driver it needs on Node.js.
|
|
9324
|
+
` + ` • Reinstall akm with a working C/C++ build toolchain so its optional
|
|
9325
|
+
` + " 'better-sqlite3' native binding rebuilds (a global `npm i -g better-sqlite3`\n" + ` will NOT be resolved — Node loads it from akm's own node_modules).
|
|
9326
|
+
` + ` • Or run akm under Bun, which has a built-in SQLite driver and needs no native build.
|
|
9327
|
+
` + ` Underlying load error: ${err instanceof Error ? err.message : String(err)}`);
|
|
9328
|
+
}
|
|
8542
9329
|
betterSqlite3Ctor = mod.default ?? mod;
|
|
8543
9330
|
}
|
|
8544
9331
|
return betterSqlite3Ctor;
|
|
@@ -8554,6 +9341,109 @@ function openNodeDatabase(path, opts) {
|
|
|
8554
9341
|
return db;
|
|
8555
9342
|
}
|
|
8556
9343
|
|
|
9344
|
+
// src/storage/sqlite-pragmas.ts
|
|
9345
|
+
init_warn();
|
|
9346
|
+
|
|
9347
|
+
// src/runtime.ts
|
|
9348
|
+
import { createWriteStream, statfsSync } from "node:fs";
|
|
9349
|
+
import { createRequire as createRequire3 } from "node:module";
|
|
9350
|
+
var isBun2 = !!process.versions?.bun;
|
|
9351
|
+
var nodeRequire2 = createRequire3(import.meta.url);
|
|
9352
|
+
function statfsType(path) {
|
|
9353
|
+
try {
|
|
9354
|
+
return statfsSync(path).type;
|
|
9355
|
+
} catch {
|
|
9356
|
+
return;
|
|
9357
|
+
}
|
|
9358
|
+
}
|
|
9359
|
+
var mainPath = isBun2 ? bunGlobal().main : process.argv[1];
|
|
9360
|
+
function bunGlobal() {
|
|
9361
|
+
return globalThis.Bun;
|
|
9362
|
+
}
|
|
9363
|
+
|
|
9364
|
+
// src/storage/sqlite-pragmas.ts
|
|
9365
|
+
var VALID_MODES = new Set(["WAL", "DELETE", "TRUNCATE"]);
|
|
9366
|
+
var warnedInvalid = false;
|
|
9367
|
+
var warnedNetworkFallback = false;
|
|
9368
|
+
function resolveJournalMode(raw) {
|
|
9369
|
+
if (raw === undefined)
|
|
9370
|
+
return "WAL";
|
|
9371
|
+
const normalized = raw.trim().toUpperCase();
|
|
9372
|
+
if (normalized === "")
|
|
9373
|
+
return "WAL";
|
|
9374
|
+
if (VALID_MODES.has(normalized)) {
|
|
9375
|
+
return normalized;
|
|
9376
|
+
}
|
|
9377
|
+
warnInvalidJournalModeOnce(raw);
|
|
9378
|
+
return "WAL";
|
|
9379
|
+
}
|
|
9380
|
+
function resolveConfiguredJournalMode(env = process.env) {
|
|
9381
|
+
return resolveJournalMode(env.AKM_SQLITE_JOURNAL_MODE);
|
|
9382
|
+
}
|
|
9383
|
+
function warnInvalidJournalModeOnce(raw) {
|
|
9384
|
+
if (warnedInvalid)
|
|
9385
|
+
return;
|
|
9386
|
+
warnedInvalid = true;
|
|
9387
|
+
warn(`[akm] invalid AKM_SQLITE_JOURNAL_MODE=${JSON.stringify(raw)} — using WAL (valid: WAL, DELETE, TRUNCATE)`);
|
|
9388
|
+
}
|
|
9389
|
+
var FS_MAGIC_NFS = 26985;
|
|
9390
|
+
var FS_MAGIC_SMB = 20859;
|
|
9391
|
+
var FS_MAGIC_CIFS = 4283649346;
|
|
9392
|
+
var FS_MAGIC_SMB2 = 4266872130;
|
|
9393
|
+
var FS_MAGIC_FUSE = 1702057286;
|
|
9394
|
+
var NETWORK_FS_MAGICS = new Set([
|
|
9395
|
+
FS_MAGIC_NFS,
|
|
9396
|
+
FS_MAGIC_SMB,
|
|
9397
|
+
FS_MAGIC_CIFS,
|
|
9398
|
+
FS_MAGIC_SMB2,
|
|
9399
|
+
FS_MAGIC_FUSE
|
|
9400
|
+
]);
|
|
9401
|
+
function isNetworkFilesystem(fsType) {
|
|
9402
|
+
if (fsType === undefined)
|
|
9403
|
+
return false;
|
|
9404
|
+
return NETWORK_FS_MAGICS.has(fsType);
|
|
9405
|
+
}
|
|
9406
|
+
function applyStandardPragmas(db, opts = {}) {
|
|
9407
|
+
let mode = resolveConfiguredJournalMode(opts.env);
|
|
9408
|
+
if (mode === "WAL" && opts.dataDir) {
|
|
9409
|
+
const probe = opts.fsTypeProbe ?? statfsType;
|
|
9410
|
+
if (isNetworkFilesystem(probe(opts.dataDir))) {
|
|
9411
|
+
mode = "DELETE";
|
|
9412
|
+
warnNetworkFallbackOnce(opts.dataDir);
|
|
9413
|
+
}
|
|
9414
|
+
}
|
|
9415
|
+
db.exec("PRAGMA busy_timeout = 30000");
|
|
9416
|
+
db.exec(`PRAGMA journal_mode = ${mode}`);
|
|
9417
|
+
if (opts.foreignKeys !== false) {
|
|
9418
|
+
db.exec("PRAGMA foreign_keys = ON");
|
|
9419
|
+
}
|
|
9420
|
+
if (mode !== "WAL") {
|
|
9421
|
+
db.exec("PRAGMA synchronous = FULL");
|
|
9422
|
+
}
|
|
9423
|
+
return mode;
|
|
9424
|
+
}
|
|
9425
|
+
function warnNetworkFallbackOnce(dataDir) {
|
|
9426
|
+
if (warnedNetworkFallback)
|
|
9427
|
+
return;
|
|
9428
|
+
warnedNetworkFallback = true;
|
|
9429
|
+
warn(`[akm] network filesystem detected at ${dataDir} — WAL unsupported, using DELETE journal mode`);
|
|
9430
|
+
}
|
|
9431
|
+
|
|
9432
|
+
// src/storage/managed-db.ts
|
|
9433
|
+
function openManagedDatabase(spec) {
|
|
9434
|
+
const dir = path.dirname(spec.path);
|
|
9435
|
+
if (!fs2.existsSync(dir)) {
|
|
9436
|
+
fs2.mkdirSync(dir, { recursive: true });
|
|
9437
|
+
}
|
|
9438
|
+
const db = openDatabase(spec.path);
|
|
9439
|
+
applyStandardPragmas(db, spec.pragmas ?? { dataDir: dir });
|
|
9440
|
+
spec.init?.(db);
|
|
9441
|
+
return db;
|
|
9442
|
+
}
|
|
9443
|
+
|
|
9444
|
+
// src/core/state-db.ts
|
|
9445
|
+
init_paths();
|
|
9446
|
+
|
|
8557
9447
|
// src/storage/engines/sqlite-migrations.ts
|
|
8558
9448
|
function ensureMigrationsTable(db) {
|
|
8559
9449
|
db.exec(`
|
|
@@ -8578,87 +9468,31 @@ function runMigrations(db, migrations, opts) {
|
|
|
8578
9468
|
}
|
|
8579
9469
|
}
|
|
8580
9470
|
|
|
8581
|
-
// src/core/
|
|
8582
|
-
function assertNever(x, context) {
|
|
8583
|
-
let serialized;
|
|
8584
|
-
try {
|
|
8585
|
-
serialized = JSON.stringify(x);
|
|
8586
|
-
} catch {
|
|
8587
|
-
serialized = String(x);
|
|
8588
|
-
}
|
|
8589
|
-
if (serialized === undefined) {
|
|
8590
|
-
serialized = String(x);
|
|
8591
|
-
}
|
|
8592
|
-
const where = context ? ` (${context})` : "";
|
|
8593
|
-
throw new Error(`Unexpected value reached assertNever${where}: ${serialized}`);
|
|
8594
|
-
}
|
|
8595
|
-
|
|
8596
|
-
// src/core/improve-types.ts
|
|
8597
|
-
function classifyImproveAction(mode) {
|
|
8598
|
-
switch (mode) {
|
|
8599
|
-
case "reflect":
|
|
8600
|
-
case "distill":
|
|
8601
|
-
case "memory-inference":
|
|
8602
|
-
case "graph-extraction":
|
|
8603
|
-
return "accepted";
|
|
8604
|
-
case "reflect-cooldown":
|
|
8605
|
-
case "reflect-skipped":
|
|
8606
|
-
case "distill-skipped":
|
|
8607
|
-
case "reflect-guard-rejected":
|
|
8608
|
-
return "rejected";
|
|
8609
|
-
case "reflect-failed":
|
|
8610
|
-
case "error":
|
|
8611
|
-
return "error";
|
|
8612
|
-
case "memory-prune":
|
|
8613
|
-
return "noop";
|
|
8614
|
-
default:
|
|
8615
|
-
return assertNever(mode);
|
|
8616
|
-
}
|
|
8617
|
-
}
|
|
8618
|
-
|
|
8619
|
-
// src/core/state-db.ts
|
|
8620
|
-
init_paths();
|
|
8621
|
-
init_warn();
|
|
8622
|
-
function getStateDbPath() {
|
|
8623
|
-
return path3.join(getDataDir(), "state.db");
|
|
8624
|
-
}
|
|
8625
|
-
function openStateDatabase(dbPath) {
|
|
8626
|
-
const resolvedPath = dbPath ?? getStateDbPath();
|
|
8627
|
-
const dir = path3.dirname(resolvedPath);
|
|
8628
|
-
if (!fs3.existsSync(dir)) {
|
|
8629
|
-
fs3.mkdirSync(dir, { recursive: true });
|
|
8630
|
-
}
|
|
8631
|
-
const db = openDatabase(resolvedPath);
|
|
8632
|
-
db.exec("PRAGMA journal_mode = WAL");
|
|
8633
|
-
db.exec("PRAGMA foreign_keys = ON");
|
|
8634
|
-
db.exec("PRAGMA busy_timeout = 30000");
|
|
8635
|
-
runMigrations2(db);
|
|
8636
|
-
return db;
|
|
8637
|
-
}
|
|
9471
|
+
// src/core/state/migrations.ts
|
|
8638
9472
|
var MIGRATIONS = [
|
|
8639
9473
|
{
|
|
8640
9474
|
id: "001-initial-schema",
|
|
8641
9475
|
up: `
|
|
8642
|
-
--
|
|
9476
|
+
-- ── events ──────────────────────────────────────────────────────────────
|
|
8643
9477
|
--
|
|
8644
9478
|
-- Replaces events.jsonl. Indexed (query) columns:
|
|
8645
|
-
-- id INTEGER PK
|
|
9479
|
+
-- id INTEGER PK — monotonic rowid; replaces byte-offset cursor.
|
|
8646
9480
|
-- Callers store this as "sinceId" for resume.
|
|
8647
|
-
-- event_type TEXT
|
|
8648
|
-
-- ts TEXT
|
|
8649
|
-
-- ref TEXT
|
|
9481
|
+
-- event_type TEXT — indexed; replaces the type filter in readEvents().
|
|
9482
|
+
-- ts TEXT — ISO-8601 UTC ms; indexed for range queries.
|
|
9483
|
+
-- ref TEXT — nullable asset ref; indexed for ref-scoped queries.
|
|
8650
9484
|
--
|
|
8651
9485
|
-- Extensible (metadata_json) columns:
|
|
8652
|
-
-- metadata_json TEXT
|
|
9486
|
+
-- metadata_json TEXT — JSON object storing all non-indexed payload
|
|
8653
9487
|
-- fields (tags, any future structured fields).
|
|
8654
9488
|
-- Maps directly to EventEnvelope.metadata.
|
|
8655
9489
|
--
|
|
8656
|
-
-- schema_version mirrors EventEnvelope.schemaVersion
|
|
9490
|
+
-- schema_version mirrors EventEnvelope.schemaVersion — always 1 for v1
|
|
8657
9491
|
-- rows. Stored as a column (not in the JSON blob) so future schema
|
|
8658
9492
|
-- changes can be detected and migrated row-by-row if ever needed.
|
|
8659
9493
|
--
|
|
8660
9494
|
-- TTL: rows where ts < NOW() - 90 days can be deleted by a maintenance job.
|
|
8661
|
-
-- No automatic deletion occurs here
|
|
9495
|
+
-- No automatic deletion occurs here — callers call purgeOldEvents().
|
|
8662
9496
|
--
|
|
8663
9497
|
-- ADD COLUMN extension points (future migrations):
|
|
8664
9498
|
-- ALTER TABLE events ADD COLUMN stash_dir TEXT DEFAULT NULL;
|
|
@@ -8674,38 +9508,38 @@ var MIGRATIONS = [
|
|
|
8674
9508
|
);
|
|
8675
9509
|
|
|
8676
9510
|
-- Query patterns supported by these indexes:
|
|
8677
|
-
-- SELECT
|
|
8678
|
-
-- SELECT
|
|
8679
|
-
-- SELECT
|
|
8680
|
-
-- SELECT
|
|
8681
|
-
-- SELECT
|
|
9511
|
+
-- SELECT … WHERE event_type = ? → idx_events_type
|
|
9512
|
+
-- SELECT … WHERE ref = ? → idx_events_ref
|
|
9513
|
+
-- SELECT … WHERE ts >= ? AND ts <= ? → idx_events_ts
|
|
9514
|
+
-- SELECT … WHERE event_type = ? AND ref = ? → idx_events_type (prefix scan) + filter
|
|
9515
|
+
-- SELECT … WHERE id > ? → PK (rowid) — no extra index needed
|
|
8682
9516
|
CREATE INDEX IF NOT EXISTS idx_events_type ON events(event_type);
|
|
8683
9517
|
CREATE INDEX IF NOT EXISTS idx_events_ref ON events(ref);
|
|
8684
9518
|
CREATE INDEX IF NOT EXISTS idx_events_ts ON events(ts);
|
|
8685
9519
|
|
|
8686
|
-
--
|
|
9520
|
+
-- ── proposals ────────────────────────────────────────────────────────────
|
|
8687
9521
|
--
|
|
8688
9522
|
-- Replaces per-uuid JSON directories under <stashDir>/.akm/proposals/.
|
|
8689
9523
|
--
|
|
8690
9524
|
-- Indexed (query) columns:
|
|
8691
|
-
-- id TEXT PK
|
|
8692
|
-
-- stash_dir TEXT
|
|
9525
|
+
-- id TEXT PK — UUID (crypto.randomUUID()); stable directory name.
|
|
9526
|
+
-- stash_dir TEXT — absolute stash root; multi-stash installs need
|
|
8693
9527
|
-- this to partition proposal lists per stash.
|
|
8694
|
-
-- ref TEXT
|
|
9528
|
+
-- ref TEXT — target asset ref (e.g. "lesson:alpha");
|
|
8695
9529
|
-- indexed for ref-scoped queue views.
|
|
8696
|
-
-- status TEXT
|
|
9530
|
+
-- status TEXT — "pending" | "accepted" | "rejected"; indexed
|
|
8697
9531
|
-- so pending-queue queries are fast.
|
|
8698
|
-
-- source TEXT
|
|
8699
|
-
-- created_at TEXT
|
|
8700
|
-
-- updated_at TEXT
|
|
9532
|
+
-- source TEXT — human-readable origin tag (e.g. "reflect").
|
|
9533
|
+
-- created_at TEXT — ISO-8601; used for ORDER BY created_at ASC.
|
|
9534
|
+
-- updated_at TEXT — ISO-8601; updated on accept/reject.
|
|
8701
9535
|
--
|
|
8702
9536
|
-- Large payload columns (NOT indexed):
|
|
8703
|
-
-- content TEXT
|
|
8704
|
-
-- frontmatter_json TEXT
|
|
9537
|
+
-- content TEXT — full markdown text; the proposal payload body.
|
|
9538
|
+
-- frontmatter_json TEXT — JSON of parsed frontmatter (may be NULL when
|
|
8705
9539
|
-- the content has no frontmatter block).
|
|
8706
9540
|
--
|
|
8707
9541
|
-- Extensible (metadata_json) columns:
|
|
8708
|
-
-- metadata_json TEXT
|
|
9542
|
+
-- metadata_json TEXT — JSON object for future proposal fields.
|
|
8709
9543
|
-- Current fields stored here: sourceRun,
|
|
8710
9544
|
-- review, confidence, gateDecision (#577),
|
|
8711
9545
|
-- backupContent, eligibilitySource.
|
|
@@ -8731,38 +9565,38 @@ var MIGRATIONS = [
|
|
|
8731
9565
|
);
|
|
8732
9566
|
|
|
8733
9567
|
-- Query patterns:
|
|
8734
|
-
-- SELECT
|
|
8735
|
-
-- SELECT
|
|
8736
|
-
-- SELECT
|
|
9568
|
+
-- SELECT … WHERE stash_dir = ? AND status = ? → idx_proposals_stash_status
|
|
9569
|
+
-- SELECT … WHERE ref = ? AND status = ? → idx_proposals_ref_status
|
|
9570
|
+
-- SELECT … WHERE id = ? → PK
|
|
8737
9571
|
CREATE INDEX IF NOT EXISTS idx_proposals_stash_status
|
|
8738
9572
|
ON proposals(stash_dir, status);
|
|
8739
9573
|
CREATE INDEX IF NOT EXISTS idx_proposals_ref_status
|
|
8740
9574
|
ON proposals(ref, status);
|
|
8741
9575
|
|
|
8742
|
-
--
|
|
9576
|
+
-- ── task_history ─────────────────────────────────────────────────────────
|
|
8743
9577
|
--
|
|
8744
9578
|
-- Replaces per-task JSONL files under <cacheDir>/tasks/history/.
|
|
8745
9579
|
--
|
|
8746
9580
|
-- Indexed (query) columns:
|
|
8747
|
-
-- task_id TEXT PK
|
|
8748
|
-
-- status TEXT
|
|
9581
|
+
-- task_id TEXT PK — stable task identifier string.
|
|
9582
|
+
-- status TEXT — terminal status (e.g. "completed", "failed",
|
|
8749
9583
|
-- "cancelled"); indexed for status-scoped queries.
|
|
8750
|
-
-- started_at TEXT
|
|
8751
|
-
-- target_kind TEXT
|
|
9584
|
+
-- started_at TEXT — ISO-8601; indexed for time-range queries.
|
|
9585
|
+
-- target_kind TEXT — kind of the target entity (e.g. "issue",
|
|
8752
9586
|
-- "workflow", "agent"); indexed for kind-scoped queries.
|
|
8753
|
-
-- target_ref TEXT
|
|
9587
|
+
-- target_ref TEXT — stable ref of the target entity; indexed for
|
|
8754
9588
|
-- per-target history lookups.
|
|
8755
9589
|
--
|
|
8756
9590
|
-- Non-indexed time columns:
|
|
8757
|
-
-- completed_at TEXT
|
|
8758
|
-
-- failed_at TEXT
|
|
9591
|
+
-- completed_at TEXT — ISO-8601 or NULL if still running.
|
|
9592
|
+
-- failed_at TEXT — ISO-8601 or NULL.
|
|
8759
9593
|
--
|
|
8760
9594
|
-- Non-indexed diagnostic columns:
|
|
8761
|
-
-- log_path TEXT
|
|
9595
|
+
-- log_path TEXT — absolute path to the task log file, if any.
|
|
8762
9596
|
--
|
|
8763
9597
|
-- Extensible (metadata_json) columns:
|
|
8764
|
-
-- metadata_json TEXT
|
|
8765
|
-
-- runner, priority, parent_task_id,
|
|
9598
|
+
-- metadata_json TEXT — JSON object for future task fields (exit_code,
|
|
9599
|
+
-- runner, priority, parent_task_id, …).
|
|
8766
9600
|
--
|
|
8767
9601
|
-- ADD COLUMN extension points (future migrations):
|
|
8768
9602
|
-- ALTER TABLE task_history ADD COLUMN exit_code INTEGER DEFAULT NULL;
|
|
@@ -8783,10 +9617,10 @@ var MIGRATIONS = [
|
|
|
8783
9617
|
);
|
|
8784
9618
|
|
|
8785
9619
|
-- Query patterns:
|
|
8786
|
-
-- SELECT
|
|
8787
|
-
-- SELECT
|
|
8788
|
-
-- SELECT
|
|
8789
|
-
-- SELECT
|
|
9620
|
+
-- SELECT … WHERE task_id = ? → PK
|
|
9621
|
+
-- SELECT … WHERE started_at >= ? AND started_at <= ? → idx_task_history_started
|
|
9622
|
+
-- SELECT … WHERE target_kind = ? AND target_ref = ? → idx_task_history_target
|
|
9623
|
+
-- SELECT … WHERE status = ? → idx_task_history_status
|
|
8790
9624
|
CREATE INDEX IF NOT EXISTS idx_task_history_started
|
|
8791
9625
|
ON task_history(started_at);
|
|
8792
9626
|
CREATE INDEX IF NOT EXISTS idx_task_history_target
|
|
@@ -8855,12 +9689,12 @@ var MIGRATIONS = [
|
|
|
8855
9689
|
);
|
|
8856
9690
|
|
|
8857
9691
|
-- Query patterns supported:
|
|
8858
|
-
-- SELECT
|
|
8859
|
-
--
|
|
8860
|
-
-- SELECT
|
|
8861
|
-
--
|
|
8862
|
-
-- SELECT
|
|
8863
|
-
--
|
|
9692
|
+
-- SELECT … WHERE started_at >= ? AND started_at <= ?
|
|
9693
|
+
-- → idx_improve_runs_started
|
|
9694
|
+
-- SELECT … WHERE dry_run = 0
|
|
9695
|
+
-- → idx_improve_runs_dry_run (productivity audits filter trap)
|
|
9696
|
+
-- SELECT … WHERE stash_dir = ? AND scope_mode = ?
|
|
9697
|
+
-- → idx_improve_runs_stash_scope
|
|
8864
9698
|
CREATE INDEX IF NOT EXISTS idx_improve_runs_started
|
|
8865
9699
|
ON improve_runs(started_at);
|
|
8866
9700
|
CREATE INDEX IF NOT EXISTS idx_improve_runs_dry_run
|
|
@@ -8887,9 +9721,9 @@ var MIGRATIONS = [
|
|
|
8887
9721
|
);
|
|
8888
9722
|
|
|
8889
9723
|
-- Query patterns:
|
|
8890
|
-
-- SELECT
|
|
8891
|
-
-- SELECT
|
|
8892
|
-
-- SELECT
|
|
9724
|
+
-- SELECT … WHERE harness = ? → idx_extract_sessions_harness
|
|
9725
|
+
-- SELECT … WHERE processed_at >= ? → idx_extract_sessions_processed
|
|
9726
|
+
-- SELECT … WHERE harness = ? AND session_id = ? → PK
|
|
8893
9727
|
CREATE INDEX IF NOT EXISTS idx_extract_sessions_harness
|
|
8894
9728
|
ON extract_sessions_seen(harness);
|
|
8895
9729
|
CREATE INDEX IF NOT EXISTS idx_extract_sessions_processed
|
|
@@ -8912,17 +9746,215 @@ var MIGRATIONS = [
|
|
|
8912
9746
|
CREATE INDEX IF NOT EXISTS idx_proposals_stash_status_ref_source
|
|
8913
9747
|
ON proposals(stash_dir, status, ref, source);
|
|
8914
9748
|
`
|
|
9749
|
+
},
|
|
9750
|
+
{
|
|
9751
|
+
id: "007-consolidation-judged",
|
|
9752
|
+
up: `
|
|
9753
|
+
CREATE TABLE IF NOT EXISTS consolidation_judged (
|
|
9754
|
+
entry_key TEXT PRIMARY KEY,
|
|
9755
|
+
content_hash TEXT NOT NULL,
|
|
9756
|
+
judged_at TEXT NOT NULL,
|
|
9757
|
+
outcome TEXT NOT NULL
|
|
9758
|
+
);
|
|
9759
|
+
`
|
|
9760
|
+
},
|
|
9761
|
+
{
|
|
9762
|
+
id: "008-body-embeddings",
|
|
9763
|
+
up: `
|
|
9764
|
+
CREATE TABLE IF NOT EXISTS body_embeddings (
|
|
9765
|
+
content_hash TEXT PRIMARY KEY,
|
|
9766
|
+
embedding BLOB NOT NULL,
|
|
9767
|
+
model_id TEXT NOT NULL,
|
|
9768
|
+
created_at INTEGER NOT NULL
|
|
9769
|
+
);
|
|
9770
|
+
`
|
|
9771
|
+
},
|
|
9772
|
+
{
|
|
9773
|
+
id: "009-asset-salience",
|
|
9774
|
+
up: `
|
|
9775
|
+
CREATE TABLE IF NOT EXISTS asset_salience (
|
|
9776
|
+
asset_ref TEXT PRIMARY KEY,
|
|
9777
|
+
encoding_salience REAL NOT NULL DEFAULT 0.5,
|
|
9778
|
+
outcome_salience REAL NOT NULL DEFAULT 0.0,
|
|
9779
|
+
retrieval_salience REAL NOT NULL DEFAULT 0.0,
|
|
9780
|
+
rank_score REAL NOT NULL DEFAULT 0.0,
|
|
9781
|
+
consecutive_no_ops INTEGER NOT NULL DEFAULT 0,
|
|
9782
|
+
updated_at INTEGER NOT NULL DEFAULT 0
|
|
9783
|
+
);
|
|
9784
|
+
|
|
9785
|
+
-- Hot path: sort / filter by rank_score for selector queries.
|
|
9786
|
+
CREATE INDEX IF NOT EXISTS idx_asset_salience_rank
|
|
9787
|
+
ON asset_salience(rank_score DESC);
|
|
9788
|
+
`
|
|
9789
|
+
},
|
|
9790
|
+
{
|
|
9791
|
+
id: "010-asset-outcome",
|
|
9792
|
+
up: `
|
|
9793
|
+
CREATE TABLE IF NOT EXISTS asset_outcome (
|
|
9794
|
+
asset_ref TEXT PRIMARY KEY,
|
|
9795
|
+
last_retrieved_at INTEGER NOT NULL DEFAULT 0,
|
|
9796
|
+
retrieval_count INTEGER NOT NULL DEFAULT 0,
|
|
9797
|
+
expected_retrieval_rate REAL NOT NULL DEFAULT 0.0,
|
|
9798
|
+
negative_feedback_count INTEGER NOT NULL DEFAULT 0,
|
|
9799
|
+
accepted_change_count INTEGER NOT NULL DEFAULT 0,
|
|
9800
|
+
review_pressure INTEGER NOT NULL DEFAULT 0,
|
|
9801
|
+
outcome_score REAL NOT NULL DEFAULT 0.0,
|
|
9802
|
+
updated_at INTEGER NOT NULL DEFAULT 0
|
|
9803
|
+
);
|
|
9804
|
+
|
|
9805
|
+
-- Hot path: sort assets by review_pressure DESC for #613 admission.
|
|
9806
|
+
CREATE INDEX IF NOT EXISTS idx_asset_outcome_review_pressure
|
|
9807
|
+
ON asset_outcome(review_pressure DESC);
|
|
9808
|
+
|
|
9809
|
+
-- Secondary: sort by outcome_score DESC for outcomeSalience reads.
|
|
9810
|
+
CREATE INDEX IF NOT EXISTS idx_asset_outcome_score
|
|
9811
|
+
ON asset_outcome(outcome_score DESC);
|
|
9812
|
+
`
|
|
9813
|
+
},
|
|
9814
|
+
{
|
|
9815
|
+
id: "011-asset-salience-homeostatic-demoted-at",
|
|
9816
|
+
up: `
|
|
9817
|
+
ALTER TABLE asset_salience ADD COLUMN homeostatic_demoted_at INTEGER DEFAULT NULL;
|
|
9818
|
+
`
|
|
9819
|
+
},
|
|
9820
|
+
{
|
|
9821
|
+
id: "012-improve-gate-thresholds",
|
|
9822
|
+
up: `
|
|
9823
|
+
CREATE TABLE IF NOT EXISTS improve_gate_thresholds (
|
|
9824
|
+
phase TEXT NOT NULL PRIMARY KEY,
|
|
9825
|
+
threshold INTEGER NOT NULL,
|
|
9826
|
+
updated_at INTEGER NOT NULL
|
|
9827
|
+
);
|
|
9828
|
+
`
|
|
9829
|
+
},
|
|
9830
|
+
{
|
|
9831
|
+
id: "013-extract-sessions-content-hash",
|
|
9832
|
+
up: `
|
|
9833
|
+
ALTER TABLE extract_sessions_seen ADD COLUMN content_hash TEXT DEFAULT NULL;
|
|
9834
|
+
`
|
|
9835
|
+
},
|
|
9836
|
+
{
|
|
9837
|
+
id: "014-recombine-hypotheses",
|
|
9838
|
+
up: `
|
|
9839
|
+
CREATE TABLE IF NOT EXISTS recombine_hypotheses (
|
|
9840
|
+
hypothesis_ref TEXT PRIMARY KEY,
|
|
9841
|
+
signature TEXT NOT NULL,
|
|
9842
|
+
member_key TEXT NOT NULL,
|
|
9843
|
+
consecutive_count INTEGER NOT NULL DEFAULT 0,
|
|
9844
|
+
first_seen_at TEXT NOT NULL,
|
|
9845
|
+
last_seen_at TEXT NOT NULL,
|
|
9846
|
+
last_run TEXT,
|
|
9847
|
+
promoted_at TEXT,
|
|
9848
|
+
metadata_json TEXT NOT NULL DEFAULT '{}'
|
|
9849
|
+
);
|
|
9850
|
+
CREATE INDEX IF NOT EXISTS idx_recombine_hypotheses_last_seen
|
|
9851
|
+
ON recombine_hypotheses(last_seen_at);
|
|
9852
|
+
`
|
|
9853
|
+
},
|
|
9854
|
+
{
|
|
9855
|
+
id: "015-asset-salience-encoding-source",
|
|
9856
|
+
up: `
|
|
9857
|
+
ALTER TABLE asset_salience ADD COLUMN encoding_source TEXT DEFAULT NULL;
|
|
9858
|
+
`
|
|
9859
|
+
},
|
|
9860
|
+
{
|
|
9861
|
+
id: "016-collapse-churn-detector",
|
|
9862
|
+
up: `
|
|
9863
|
+
CREATE TABLE IF NOT EXISTS canary_queries (
|
|
9864
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
9865
|
+
canary_set_id TEXT NOT NULL,
|
|
9866
|
+
anchor_ref TEXT NOT NULL,
|
|
9867
|
+
query TEXT NOT NULL,
|
|
9868
|
+
source TEXT NOT NULL DEFAULT 'auto',
|
|
9869
|
+
active INTEGER NOT NULL DEFAULT 1,
|
|
9870
|
+
created_at TEXT NOT NULL
|
|
9871
|
+
);
|
|
9872
|
+
CREATE INDEX IF NOT EXISTS idx_canary_queries_active
|
|
9873
|
+
ON canary_queries(active, canary_set_id);
|
|
9874
|
+
|
|
9875
|
+
CREATE TABLE IF NOT EXISTS improve_cycle_metrics (
|
|
9876
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
9877
|
+
run_id TEXT NOT NULL,
|
|
9878
|
+
ts TEXT NOT NULL,
|
|
9879
|
+
pass TEXT NOT NULL,
|
|
9880
|
+
canary_set_id TEXT NOT NULL,
|
|
9881
|
+
mean_recall REAL NOT NULL,
|
|
9882
|
+
mean_ndcg REAL NOT NULL,
|
|
9883
|
+
mean_mrr REAL NOT NULL,
|
|
9884
|
+
canary_ranks_json TEXT NOT NULL,
|
|
9885
|
+
store_total INTEGER NOT NULL,
|
|
9886
|
+
store_by_type_json TEXT NOT NULL,
|
|
9887
|
+
distinct_content_ratio REAL NOT NULL,
|
|
9888
|
+
mean_bigram_diversity REAL NOT NULL,
|
|
9889
|
+
over_generation_count INTEGER NOT NULL,
|
|
9890
|
+
accepted_actions INTEGER NOT NULL,
|
|
9891
|
+
merge_floor_violations INTEGER NOT NULL DEFAULT 0,
|
|
9892
|
+
alerts_json TEXT NOT NULL DEFAULT '[]'
|
|
9893
|
+
);
|
|
9894
|
+
CREATE INDEX IF NOT EXISTS idx_improve_cycle_metrics_ts
|
|
9895
|
+
ON improve_cycle_metrics(ts);
|
|
9896
|
+
`
|
|
8915
9897
|
}
|
|
8916
9898
|
];
|
|
8917
9899
|
function runMigrations2(db) {
|
|
8918
9900
|
runMigrations(db, MIGRATIONS);
|
|
8919
9901
|
}
|
|
9902
|
+
|
|
9903
|
+
// src/core/state-db.ts
|
|
9904
|
+
function getStateDbPath() {
|
|
9905
|
+
return path4.join(getDataDir(), "state.db");
|
|
9906
|
+
}
|
|
9907
|
+
function openStateDatabase(dbPath) {
|
|
9908
|
+
return openManagedDatabase({ path: dbPath ?? getStateDbPath(), init: runMigrations2 });
|
|
9909
|
+
}
|
|
9910
|
+
|
|
9911
|
+
// src/core/assert.ts
|
|
9912
|
+
function assertNever(x, context) {
|
|
9913
|
+
let serialized;
|
|
9914
|
+
try {
|
|
9915
|
+
serialized = JSON.stringify(x);
|
|
9916
|
+
} catch {
|
|
9917
|
+
serialized = String(x);
|
|
9918
|
+
}
|
|
9919
|
+
if (serialized === undefined) {
|
|
9920
|
+
serialized = String(x);
|
|
9921
|
+
}
|
|
9922
|
+
const where = context ? ` (${context})` : "";
|
|
9923
|
+
throw new Error(`Unexpected value reached assertNever${where}: ${serialized}`);
|
|
9924
|
+
}
|
|
9925
|
+
|
|
9926
|
+
// src/core/improve-types.ts
|
|
9927
|
+
function classifyImproveAction(mode) {
|
|
9928
|
+
switch (mode) {
|
|
9929
|
+
case "reflect":
|
|
9930
|
+
case "distill":
|
|
9931
|
+
case "memory-inference":
|
|
9932
|
+
case "graph-extraction":
|
|
9933
|
+
return "accepted";
|
|
9934
|
+
case "reflect-cooldown":
|
|
9935
|
+
case "reflect-skipped":
|
|
9936
|
+
case "distill-skipped":
|
|
9937
|
+
return "skipped";
|
|
9938
|
+
case "reflect-guard-rejected":
|
|
9939
|
+
return "rejected";
|
|
9940
|
+
case "reflect-failed":
|
|
9941
|
+
case "error":
|
|
9942
|
+
return "error";
|
|
9943
|
+
case "memory-prune":
|
|
9944
|
+
return "noop";
|
|
9945
|
+
default:
|
|
9946
|
+
return assertNever(mode);
|
|
9947
|
+
}
|
|
9948
|
+
}
|
|
9949
|
+
|
|
9950
|
+
// src/storage/repositories/improve-runs-repository.ts
|
|
8920
9951
|
function computeImproveRunMetrics(result) {
|
|
8921
9952
|
const plannedCount = Array.isArray(result.plannedRefs) ? result.plannedRefs.length : 0;
|
|
8922
9953
|
const actions = Array.isArray(result.actions) ? result.actions : [];
|
|
8923
9954
|
const actionsCount = actions.length;
|
|
8924
9955
|
let acceptedCount = 0;
|
|
8925
9956
|
let rejectedCount = 0;
|
|
9957
|
+
let skippedCount = 0;
|
|
8926
9958
|
let autoAcceptedCount = 0;
|
|
8927
9959
|
let errorCount = 0;
|
|
8928
9960
|
for (const action of actions) {
|
|
@@ -8933,6 +9965,9 @@ function computeImproveRunMetrics(result) {
|
|
|
8933
9965
|
case "rejected":
|
|
8934
9966
|
rejectedCount++;
|
|
8935
9967
|
break;
|
|
9968
|
+
case "skipped":
|
|
9969
|
+
skippedCount++;
|
|
9970
|
+
break;
|
|
8936
9971
|
case "error":
|
|
8937
9972
|
errorCount++;
|
|
8938
9973
|
break;
|
|
@@ -8944,7 +9979,17 @@ function computeImproveRunMetrics(result) {
|
|
|
8944
9979
|
autoAcceptedCount++;
|
|
8945
9980
|
}
|
|
8946
9981
|
autoAcceptedCount += result.gateAutoAcceptedCount ?? 0;
|
|
8947
|
-
|
|
9982
|
+
const distillSkippedTotal = result.distillSkipped?.total ?? 0;
|
|
9983
|
+
skippedCount += distillSkippedTotal;
|
|
9984
|
+
return {
|
|
9985
|
+
plannedCount,
|
|
9986
|
+
actionsCount: actionsCount + distillSkippedTotal,
|
|
9987
|
+
acceptedCount,
|
|
9988
|
+
rejectedCount,
|
|
9989
|
+
skippedCount,
|
|
9990
|
+
autoAcceptedCount,
|
|
9991
|
+
errorCount
|
|
9992
|
+
};
|
|
8948
9993
|
}
|
|
8949
9994
|
function recordImproveRun(db, input) {
|
|
8950
9995
|
const metricsObj = input.metrics ?? computeImproveRunMetrics(input.result);
|
|
@@ -8960,7 +10005,7 @@ function recordImproveRun(db, input) {
|
|
|
8960
10005
|
function parseArgs(argv) {
|
|
8961
10006
|
const stashFromEnv = process.env.AKM_STASH_DIR;
|
|
8962
10007
|
const out = {
|
|
8963
|
-
stashDir: stashFromEnv ??
|
|
10008
|
+
stashDir: stashFromEnv ?? path5.join(process.env.HOME ?? "", "akm"),
|
|
8964
10009
|
dryRun: false,
|
|
8965
10010
|
archive: true
|
|
8966
10011
|
};
|
|
@@ -9019,12 +10064,12 @@ function inferScope(envelope) {
|
|
|
9019
10064
|
}
|
|
9020
10065
|
async function main() {
|
|
9021
10066
|
const args = parseArgs(process.argv.slice(2));
|
|
9022
|
-
const runsRoot =
|
|
9023
|
-
if (!
|
|
10067
|
+
const runsRoot = path5.join(args.stashDir, ".akm", "runs");
|
|
10068
|
+
if (!fs6.existsSync(runsRoot)) {
|
|
9024
10069
|
console.log(`[import] no legacy runs directory at ${runsRoot}; nothing to do`);
|
|
9025
10070
|
return;
|
|
9026
10071
|
}
|
|
9027
|
-
const entries =
|
|
10072
|
+
const entries = fs6.readdirSync(runsRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort();
|
|
9028
10073
|
if (entries.length === 0) {
|
|
9029
10074
|
console.log(`[import] ${runsRoot} is empty; nothing to do`);
|
|
9030
10075
|
return;
|
|
@@ -9038,8 +10083,8 @@ async function main() {
|
|
|
9038
10083
|
let skippedParseFailed = 0;
|
|
9039
10084
|
let skippedNoTimestamp = 0;
|
|
9040
10085
|
for (const id of entries) {
|
|
9041
|
-
const resultPath =
|
|
9042
|
-
if (!
|
|
10086
|
+
const resultPath = path5.join(runsRoot, id, "improve-result.json");
|
|
10087
|
+
if (!fs6.existsSync(resultPath)) {
|
|
9043
10088
|
skippedNoResult++;
|
|
9044
10089
|
continue;
|
|
9045
10090
|
}
|
|
@@ -9049,7 +10094,7 @@ async function main() {
|
|
|
9049
10094
|
}
|
|
9050
10095
|
let envelope;
|
|
9051
10096
|
try {
|
|
9052
|
-
envelope = JSON.parse(
|
|
10097
|
+
envelope = JSON.parse(fs6.readFileSync(resultPath, "utf8"));
|
|
9053
10098
|
} catch (err) {
|
|
9054
10099
|
console.warn(`[import] skipping ${id}: parse failed (${err instanceof Error ? err.message : String(err)})`);
|
|
9055
10100
|
skippedParseFailed++;
|
|
@@ -9114,8 +10159,8 @@ async function main() {
|
|
|
9114
10159
|
return;
|
|
9115
10160
|
}
|
|
9116
10161
|
const ts = new Date().toISOString().replace(/[:.]/g, "-");
|
|
9117
|
-
const archiveTarget =
|
|
9118
|
-
|
|
10162
|
+
const archiveTarget = path5.join(args.stashDir, ".akm", `runs.archived-${ts}`);
|
|
10163
|
+
fs6.renameSync(runsRoot, archiveTarget);
|
|
9119
10164
|
console.log(`[import] archived ${runsRoot} \u2192 ${archiveTarget}`);
|
|
9120
10165
|
}
|
|
9121
10166
|
main().catch((err) => {
|