akm-cli 0.8.6 → 0.8.14
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 +442 -0
- package/dist/assets/help/help-proposals.md +1 -2
- package/dist/assets/hints/cli-hints-full.md +34 -19
- package/dist/assets/hints/cli-hints-short.md +1 -1
- package/dist/assets/profiles/catchup.json +13 -0
- package/dist/assets/profiles/consolidate.json +13 -0
- package/dist/assets/profiles/frequent.json +13 -0
- package/dist/assets/tasks/core/backup.yml +4 -0
- package/dist/assets/tasks/core/extract.yml +4 -0
- package/dist/assets/tasks/core/improve.yml +4 -0
- package/dist/assets/tasks/core/index-refresh.yml +4 -0
- package/dist/assets/tasks/core/sync.yml +4 -0
- package/dist/assets/tasks/core/update-stashes.yml +4 -0
- package/dist/assets/tasks/core/version-check.yml +4 -0
- package/dist/assets/templates/html/default.html +78 -0
- package/dist/assets/templates/html/health.html +560 -0
- package/dist/assets/templates/html/vendor/echarts.min.js +45 -0
- package/dist/cli/config-migrate.js +6 -6
- package/dist/cli/config-validate.js +4 -4
- package/dist/cli/confirm.js +3 -3
- package/dist/cli/parse-args.js +1 -1
- package/dist/cli/shared.js +72 -19
- package/dist/cli-node.mjs +26 -0
- package/dist/cli.js +206 -3866
- package/dist/commands/{agent-dispatch.js → agent/agent-dispatch.js} +6 -6
- package/dist/commands/{agent-support.js → agent/agent-support.js} +2 -2
- package/dist/commands/agent/contribute-cli.js +200 -0
- package/dist/commands/completions.js +1 -1
- package/dist/commands/config-cli.js +230 -3
- package/dist/commands/db-cli.js +2 -2
- package/dist/commands/env/env-cli.js +529 -0
- package/dist/commands/env/env.js +410 -0
- package/dist/commands/env/secret-cli.js +259 -0
- package/dist/commands/{secret.js → env/secret.js} +6 -47
- package/dist/commands/events.js +4 -4
- package/dist/commands/feedback-cli.js +18 -34
- package/dist/commands/graph/graph-cli.js +132 -0
- package/dist/commands/{graph.js → graph/graph.js} +22 -16
- package/dist/commands/health/checks.js +279 -0
- package/dist/commands/health/html-report.js +448 -0
- package/dist/commands/health.js +189 -266
- package/dist/commands/{consolidate.js → improve/consolidate.js} +63 -38
- package/dist/commands/{distill-promotion-policy.js → improve/distill-promotion-policy.js} +3 -3
- package/dist/commands/{distill.js → improve/distill.js} +39 -18
- package/dist/commands/{eval-cases.js → improve/eval-cases.js} +1 -1
- package/dist/commands/{extract-cli.js → improve/extract-cli.js} +4 -4
- package/dist/commands/{extract-prompt.js → improve/extract-prompt.js} +2 -2
- package/dist/commands/{extract.js → improve/extract.js} +221 -26
- package/dist/commands/{improve-auto-accept.js → improve/improve-auto-accept.js} +30 -4
- package/dist/commands/{improve-cli.js → improve/improve-cli.js} +44 -22
- package/dist/commands/{improve-profiles.js → improve/improve-profiles.js} +13 -7
- package/dist/commands/{improve-result-file.js → improve/improve-result-file.js} +1 -1
- package/dist/commands/{improve.js → improve/improve.js} +672 -292
- package/dist/{core → commands/improve/memory}/memory-belief.js +2 -2
- package/dist/{core → commands/improve/memory}/memory-contradiction-detect.js +5 -5
- package/dist/{core → commands/improve/memory}/memory-improve.js +4 -4
- package/dist/commands/improve/reflect-noise.js +0 -0
- package/dist/commands/{reflect.js → improve/reflect.js} +58 -28
- package/dist/commands/improve/session-asset.js +248 -0
- package/dist/commands/lint/agent-linter.js +1 -1
- package/dist/commands/lint/base-linter.js +55 -37
- package/dist/commands/lint/command-linter.js +1 -1
- package/dist/commands/lint/default-linter.js +1 -1
- package/dist/commands/lint/env-key-rules.js +1 -1
- package/dist/commands/lint/index.js +19 -25
- package/dist/commands/lint/knowledge-linter.js +1 -1
- package/dist/commands/lint/memory-linter.js +1 -1
- package/dist/commands/lint/registry.js +8 -8
- package/dist/commands/lint/skill-linter.js +1 -1
- package/dist/commands/lint/task-linter.js +1 -1
- package/dist/commands/lint/workflow-linter.js +1 -1
- package/dist/commands/lint.js +1 -1
- package/dist/commands/observability-cli.js +244 -0
- package/dist/commands/proposal/drain-policies.js +3 -3
- package/dist/commands/proposal/drain.js +87 -15
- package/dist/commands/proposal/proposal-cli.js +490 -0
- package/dist/commands/{proposal.js → proposal/proposal.js} +17 -6
- package/dist/commands/{propose.js → proposal/propose.js} +11 -11
- package/dist/{core → commands/proposal/validators}/proposal-quality-validators.js +8 -3
- package/dist/{core → commands/proposal/validators}/proposal-validators.js +5 -5
- package/dist/{core → commands/proposal/validators}/proposals.js +374 -345
- package/dist/commands/{curate.js → read/curate.js} +7 -7
- package/dist/commands/{knowledge.js → read/knowledge.js} +22 -9
- package/dist/commands/{registry-search.js → read/registry-search.js} +5 -5
- package/dist/commands/{remember-cli.js → read/remember-cli.js} +15 -7
- package/dist/commands/read/search-cli.js +207 -0
- package/dist/commands/{search.js → read/search.js} +22 -27
- package/dist/commands/{show.js → read/show.js} +31 -45
- package/dist/commands/registry-cli.js +8 -8
- package/dist/commands/remember.js +14 -10
- package/dist/commands/sources/add-cli.js +293 -0
- package/dist/commands/{history.js → sources/history.js} +27 -25
- package/dist/commands/{info.js → sources/info.js} +6 -6
- package/dist/commands/{init.js → sources/init.js} +6 -6
- package/dist/commands/{installed-stashes.js → sources/installed-stashes.js} +12 -12
- package/dist/commands/{migration-help.js → sources/migration-help.js} +3 -2
- package/dist/commands/{schema-repair.js → sources/schema-repair.js} +8 -8
- package/dist/commands/{self-update.js → sources/self-update.js} +10 -9
- package/dist/commands/{source-add.js → sources/source-add.js} +10 -10
- package/dist/commands/{source-clone.js → sources/source-clone.js} +7 -7
- package/dist/commands/{source-manage.js → sources/source-manage.js} +4 -4
- package/dist/commands/sources/sources-cli.js +305 -0
- package/dist/commands/sources/stash-cli.js +219 -0
- package/dist/commands/{stash-skeleton.js → sources/stash-skeleton.js} +2 -1
- package/dist/commands/tasks/default-tasks.js +173 -0
- package/dist/commands/tasks/tasks-cli.js +210 -0
- package/dist/commands/{tasks.js → tasks/tasks.js} +14 -14
- package/dist/commands/wiki-cli.js +307 -0
- package/dist/commands/workflow-cli.js +329 -0
- package/dist/core/action-contributors.js +1 -1
- package/dist/core/assert.js +40 -0
- package/dist/core/asset/asset-create.js +54 -0
- package/dist/core/{asset-ref.js → asset/asset-ref.js} +21 -4
- package/dist/core/{asset-registry.js → asset/asset-registry.js} +3 -3
- package/dist/core/{asset-spec.js → asset/asset-spec.js} +17 -31
- package/dist/core/{markdown.js → asset/markdown.js} +1 -1
- package/dist/core/{stash-meta.js → asset/stash-meta.js} +1 -1
- package/dist/core/best-effort.js +64 -0
- package/dist/core/common.js +32 -18
- package/dist/core/{config-io.js → config/config-io.js} +29 -19
- package/dist/core/{config-migration.js → config/config-migration.js} +11 -9
- package/dist/core/{config-schema.js → config/config-schema.js} +50 -7
- package/dist/core/config/config-types.js +16 -0
- package/dist/core/{config-walker.js → config/config-walker.js} +2 -2
- package/dist/core/{config.js → config/config.js} +10 -8
- package/dist/core/env-secret-ref.js +90 -0
- package/dist/core/errors.js +13 -3
- package/dist/core/events.js +27 -4
- package/dist/core/file-lock.js +1 -1
- package/dist/core/improve-types.js +48 -0
- package/dist/core/lesson-lint.js +2 -2
- package/dist/core/logs-db.js +304 -0
- package/dist/core/paths.js +2 -2
- package/dist/core/ripgrep/install.js +2 -2
- package/dist/core/ripgrep/resolve.js +2 -2
- package/dist/core/state-db.js +195 -60
- package/dist/core/text-truncation.js +148 -0
- package/dist/core/time.js +1 -1
- package/dist/core/write-source.js +98 -85
- package/dist/indexer/{db-backup.js → db/db-backup.js} +9 -24
- package/dist/indexer/{db.js → db/db.js} +128 -118
- package/dist/indexer/{graph-db.js → db/graph-db.js} +9 -4
- package/dist/indexer/{llm-cache.js → db/llm-cache.js} +15 -12
- package/dist/indexer/ensure-index.js +4 -4
- package/dist/indexer/{graph-boost.js → graph/graph-boost.js} +1 -1
- package/dist/indexer/{graph-extraction.js → graph/graph-extraction.js} +55 -13
- package/dist/indexer/indexer.js +37 -30
- package/dist/indexer/init.js +54 -0
- package/dist/indexer/manifest.js +10 -10
- package/dist/indexer/{memory-inference.js → passes/memory-inference.js} +141 -33
- package/dist/indexer/{metadata-contributors.js → passes/metadata-contributors.js} +10 -8
- package/dist/indexer/{metadata.js → passes/metadata.js} +15 -19
- package/dist/indexer/{staleness-detect.js → passes/staleness-detect.js} +53 -12
- package/dist/indexer/{db-search.js → search/db-search.js} +28 -16
- package/dist/indexer/{ranking-contributors.js → search/ranking-contributors.js} +1 -1
- package/dist/indexer/{ranking.js → search/ranking.js} +2 -2
- package/dist/indexer/{search-hit-enrichers.js → search/search-hit-enrichers.js} +3 -3
- package/dist/indexer/{search-source.js → search/search-source.js} +8 -8
- package/dist/indexer/{semantic-status.js → search/semantic-status.js} +3 -3
- package/dist/indexer/usage/unmigrated-vaults-guard.js +94 -0
- package/dist/indexer/{usage-events.js → usage/usage-events.js} +32 -0
- package/dist/indexer/{file-context.js → walk/file-context.js} +10 -15
- package/dist/indexer/{matchers.js → walk/matchers.js} +13 -9
- package/dist/indexer/{path-resolver.js → walk/path-resolver.js} +6 -6
- package/dist/indexer/{project-context.js → walk/project-context.js} +1 -1
- package/dist/indexer/{walker.js → walk/walker.js} +4 -3
- package/dist/integrations/agent/builder-shared.js +39 -0
- package/dist/integrations/agent/builders.js +14 -81
- package/dist/integrations/agent/config.js +6 -4
- package/dist/integrations/agent/detect.js +1 -1
- package/dist/integrations/agent/index.js +23 -8
- package/dist/integrations/agent/prompts.js +2 -3
- package/dist/integrations/agent/runner.js +22 -3
- package/dist/integrations/agent/spawn.js +9 -10
- package/dist/integrations/harnesses/claude/agent-builder.js +48 -0
- package/dist/integrations/harnesses/claude/config-import.js +70 -0
- package/dist/integrations/harnesses/claude/index.js +64 -0
- package/dist/integrations/{session-logs/providers/claude-code.js → harnesses/claude/session-log.js} +32 -5
- package/dist/integrations/harnesses/index.js +144 -0
- package/dist/integrations/harnesses/opencode/agent-builder.js +43 -0
- package/dist/integrations/harnesses/opencode/config-import.js +82 -0
- package/dist/integrations/harnesses/opencode/index.js +59 -0
- package/dist/integrations/{session-logs/providers/opencode.js → harnesses/opencode/session-log.js} +1 -1
- package/dist/integrations/harnesses/opencode-sdk/index.js +49 -0
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +234 -0
- package/dist/integrations/harnesses/types.js +43 -0
- package/dist/integrations/lockfile.js +7 -16
- package/dist/integrations/session-logs/index.js +82 -9
- package/dist/llm/call-ai.js +4 -4
- package/dist/llm/client.js +146 -6
- package/dist/llm/embedder.js +6 -6
- package/dist/llm/embedders/local.js +9 -22
- package/dist/llm/embedders/remote.js +2 -2
- package/dist/llm/embedders/types.js +1 -1
- package/dist/llm/graph-extract.js +31 -12
- package/dist/llm/index-passes.js +1 -1
- package/dist/llm/memory-infer.js +12 -5
- package/dist/llm/metadata-enhance.js +2 -2
- package/dist/llm/usage-persist.js +77 -0
- package/dist/llm/usage-telemetry.js +103 -0
- package/dist/output/context.js +9 -46
- package/dist/output/html-render.js +73 -0
- package/dist/output/renderers.js +88 -58
- package/dist/output/shapes/curate.js +7 -3
- package/dist/output/shapes/distill.js +7 -3
- package/dist/output/shapes/env-list.js +18 -16
- package/dist/output/shapes/events.js +5 -4
- package/dist/output/shapes/helpers.js +19 -5
- package/dist/output/shapes/history.js +7 -3
- package/dist/output/shapes/passthrough.js +8 -11
- package/dist/output/shapes/{proposal-accept.js → proposal/accept.js} +7 -3
- package/dist/output/shapes/{proposal-diff.js → proposal/diff.js} +7 -3
- package/dist/output/shapes/{proposal-list.js → proposal/list.js} +7 -3
- package/dist/output/shapes/{proposal-producer.js → proposal/producer.js} +5 -4
- package/dist/output/shapes/{proposal-reject.js → proposal/reject.js} +7 -3
- package/dist/output/shapes/{proposal-show.js → proposal/show.js} +7 -3
- package/dist/output/shapes/registry-search.js +7 -3
- package/dist/output/shapes/registry.js +12 -0
- package/dist/output/shapes/search.js +7 -3
- package/dist/output/shapes/secret-list.js +18 -16
- package/dist/output/shapes/show.js +7 -3
- package/dist/output/shapes.js +55 -30
- package/dist/output/text/add.js +2 -3
- package/dist/output/text/clone.js +2 -3
- package/dist/output/text/config.js +2 -3
- package/dist/output/text/curate.js +4 -3
- package/dist/output/text/distill.js +2 -3
- package/dist/output/text/enable-disable.js +5 -4
- package/dist/output/text/env.js +13 -0
- package/dist/output/text/events.js +5 -4
- package/dist/output/text/feedback.js +4 -3
- package/dist/output/text/helpers.js +123 -40
- package/dist/output/text/history.js +2 -3
- package/dist/output/text/import.js +2 -3
- package/dist/output/text/index.js +2 -3
- package/dist/output/text/info.js +2 -3
- package/dist/output/text/init.js +2 -3
- package/dist/output/text/list.js +2 -3
- package/dist/output/text/proposal/producer.js +9 -0
- package/dist/output/text/proposal/proposal.js +13 -0
- package/dist/output/text/registry-commands.js +8 -7
- package/dist/output/text/registry.js +12 -0
- package/dist/output/text/remember.js +4 -3
- package/dist/output/text/remove.js +2 -3
- package/dist/output/text/save.js +2 -3
- package/dist/output/text/search.js +4 -3
- package/dist/output/text/show.js +4 -3
- package/dist/output/text/update.js +2 -3
- package/dist/output/text/upgrade.js +2 -3
- package/dist/output/text/wiki.js +12 -11
- package/dist/output/text/workflow.js +12 -10
- package/dist/output/text.js +66 -32
- package/dist/registry/build-index.js +11 -10
- package/dist/registry/factory.js +1 -1
- package/dist/registry/origin-resolve.js +1 -1
- package/dist/registry/providers/index.js +2 -2
- package/dist/registry/providers/skills-sh.js +91 -72
- package/dist/registry/providers/static-index.js +75 -52
- package/dist/registry/resolve.js +3 -3
- package/dist/runtime.js +242 -0
- package/dist/scripts/migrate-storage.js +1654 -683
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +254 -168
- package/dist/setup/detect.js +311 -9
- package/dist/setup/harness-config-import.js +6 -120
- package/dist/setup/setup.js +454 -43
- package/dist/sources/include.js +1 -1
- package/dist/sources/provider-factory.js +2 -2
- package/dist/sources/providers/filesystem.js +3 -3
- package/dist/sources/providers/git.js +9 -9
- package/dist/sources/providers/index.js +4 -4
- package/dist/sources/providers/npm.js +6 -6
- package/dist/sources/providers/provider-utils.js +13 -20
- package/dist/sources/providers/sync-from-ref.js +5 -5
- package/dist/sources/providers/tar-utils.js +2 -2
- package/dist/sources/providers/website.js +2 -2
- package/dist/sources/resolve.js +5 -5
- package/dist/sources/website-ingest.js +5 -5
- package/dist/storage/database.js +102 -0
- package/dist/storage/engines/sqlite-migrations.js +42 -0
- package/dist/storage/locations.js +25 -0
- package/dist/storage/repositories/index-db.js +43 -0
- package/dist/storage/repositories/workflow-runs-repository.js +141 -0
- package/dist/tasks/backends/cron.js +4 -4
- package/dist/tasks/backends/exec-utils.js +32 -0
- package/dist/tasks/backends/index.js +3 -3
- package/dist/tasks/backends/launchd.js +7 -14
- package/dist/tasks/backends/schtasks.js +7 -16
- package/dist/tasks/embedded.js +71 -0
- package/dist/tasks/parser.js +2 -2
- package/dist/tasks/resolveAkmBin.js +1 -1
- package/dist/tasks/runner.js +127 -31
- package/dist/tasks/schedule.js +1 -1
- package/dist/tasks/validator.js +7 -7
- package/dist/text-import-hook.mjs +51 -0
- package/dist/version.js +2 -1
- package/dist/wiki/wiki.js +7 -7
- package/dist/workflows/{authoring.js → authoring/authoring.js} +6 -6
- package/dist/workflows/{scope-key.js → authoring/scope-key.js} +1 -1
- package/dist/workflows/cli.js +1 -1
- package/dist/workflows/db.js +54 -32
- package/dist/workflows/parser.js +4 -4
- package/dist/workflows/renderer.js +5 -5
- package/dist/workflows/runtime/agent-identity.js +56 -0
- package/dist/workflows/runtime/checkin.js +57 -0
- package/dist/workflows/{runs.js → runtime/runs.js} +197 -101
- package/dist/workflows/validate-summary.js +82 -0
- package/docs/README.md +1 -1
- package/docs/data-and-telemetry.md +6 -6
- package/package.json +17 -8
- package/dist/commands/add-cli.js +0 -279
- package/dist/commands/env.js +0 -213
- package/dist/integrations/agent/sdk-runner.js +0 -126
- package/dist/output/shapes/vault-list.js +0 -19
- package/dist/output/text/proposal-producer.js +0 -8
- package/dist/output/text/proposal.js +0 -12
- package/dist/output/text/vault.js +0 -16
- /package/dist/core/{asset-serialize.js → asset/asset-serialize.js} +0 -0
- /package/dist/core/{frontmatter.js → asset/frontmatter.js} +0 -0
- /package/dist/core/{config-sources.js → config/config-sources.js} +0 -0
- /package/dist/indexer/{graph-dedup.js → graph/graph-dedup.js} +0 -0
- /package/dist/{core/config-types.js → indexer/passes/pass-context.js} +0 -0
- /package/dist/indexer/{search-fields.js → search/search-fields.js} +0 -0
- /package/dist/indexer/{index-context.js → walk/index-context.js} +0 -0
- /package/dist/workflows/{document-cache.js → runtime/document-cache.js} +0 -0
|
@@ -384,7 +384,73 @@ var require_main = __commonJS((exports, module) => {
|
|
|
384
384
|
module.exports = DotenvModule;
|
|
385
385
|
});
|
|
386
386
|
|
|
387
|
-
// src/
|
|
387
|
+
// src/core/errors.ts
|
|
388
|
+
function isTestIsolationError(err) {
|
|
389
|
+
return err instanceof ConfigError && err.code === "TEST_ISOLATION_MISSING";
|
|
390
|
+
}
|
|
391
|
+
function rethrowIfTestIsolationError(err) {
|
|
392
|
+
if (isTestIsolationError(err)) {
|
|
393
|
+
throw err;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
var CONFIG_HINTS, USAGE_HINTS, AkmError, ConfigError, UsageError;
|
|
397
|
+
var init_errors = __esm(() => {
|
|
398
|
+
CONFIG_HINTS = {
|
|
399
|
+
STASH_DIR_NOT_FOUND: "Run `akm setup` to create and configure your stash, or set stashDir in your config.",
|
|
400
|
+
STASH_DIR_NOT_A_DIRECTORY: "The configured stashDir exists but isn't a directory. Update stashDir to point at a folder.",
|
|
401
|
+
STASH_DIR_UNREADABLE: "Check the path exists and your user has read permission, or update stashDir.",
|
|
402
|
+
EMBEDDING_NOT_CONFIGURED: 'Run `akm config set embedding \'{"endpoint":"...","model":"..."}\'` to enable embeddings.',
|
|
403
|
+
LLM_NOT_CONFIGURED: 'Run `akm setup` or `akm config set profiles.llm.default \'{"endpoint":"...","model":"..."}\' to configure an LLM profile.',
|
|
404
|
+
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.",
|
|
405
|
+
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/ \u2014 host config is preserved).",
|
|
406
|
+
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."
|
|
407
|
+
};
|
|
408
|
+
USAGE_HINTS = {
|
|
409
|
+
INVALID_FLAG_VALUE: "Run `akm <command> --help` to see accepted values.",
|
|
410
|
+
INVALID_SOURCE_VALUE: "Pick one of: stash, registry, both.",
|
|
411
|
+
INVALID_FORMAT_VALUE: "Pick one of: json, jsonl, text, yaml.",
|
|
412
|
+
INVALID_DETAIL_VALUE: "Pick one of: brief, normal, full. For agent/summary projections use --shape.",
|
|
413
|
+
INVALID_SHAPE_VALUE: "Pick one of: human, agent, summary (summary is only valid on `akm show`).",
|
|
414
|
+
INVALID_JSON_CONFIG_VALUE: `Quote JSON values in your shell, for example: akm config set embedding '{"endpoint":"http://localhost:11434/v1/embeddings","model":"nomic-embed-text"}'.`,
|
|
415
|
+
MISSING_OR_AMBIGUOUS_TARGET: "Use `akm update --all` or pass a target like `akm update npm:@scope/pkg` (not both).",
|
|
416
|
+
TARGET_NOT_UPDATABLE: "Run `akm list` to view your sources, then retry with one of those values.",
|
|
417
|
+
MISSING_REQUIRED_ARGUMENT: "Refs use the form type:name, e.g. `akm show skill:deploy` or `akm show knowledge:guide.md`."
|
|
418
|
+
};
|
|
419
|
+
AkmError = class AkmError extends Error {
|
|
420
|
+
};
|
|
421
|
+
ConfigError = class ConfigError extends AkmError {
|
|
422
|
+
kind = "config";
|
|
423
|
+
code;
|
|
424
|
+
_hint;
|
|
425
|
+
constructor(msg, code = "INVALID_CONFIG_FILE", hint) {
|
|
426
|
+
super(msg);
|
|
427
|
+
this.name = "ConfigError";
|
|
428
|
+
this.code = code;
|
|
429
|
+
this._hint = hint;
|
|
430
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
431
|
+
}
|
|
432
|
+
hint() {
|
|
433
|
+
return this._hint ?? CONFIG_HINTS[this.code];
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
UsageError = class UsageError extends AkmError {
|
|
437
|
+
kind = "usage";
|
|
438
|
+
code;
|
|
439
|
+
_hint;
|
|
440
|
+
constructor(msg, code = "INVALID_FLAG_VALUE", hint) {
|
|
441
|
+
super(msg);
|
|
442
|
+
this.name = "UsageError";
|
|
443
|
+
this.code = code;
|
|
444
|
+
this._hint = hint;
|
|
445
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
446
|
+
}
|
|
447
|
+
hint() {
|
|
448
|
+
return this._hint ?? USAGE_HINTS[this.code];
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
// src/commands/env/env.ts
|
|
388
454
|
import fs from "fs";
|
|
389
455
|
function scanKeys(text) {
|
|
390
456
|
const keys = [];
|
|
@@ -420,11 +486,12 @@ function listKeys(envPath) {
|
|
|
420
486
|
var import_dotenv, ASSIGN_RE;
|
|
421
487
|
var init_env = __esm(() => {
|
|
422
488
|
init_common();
|
|
489
|
+
init_errors();
|
|
423
490
|
import_dotenv = __toESM(require_main(), 1);
|
|
424
491
|
ASSIGN_RE = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/;
|
|
425
492
|
});
|
|
426
493
|
|
|
427
|
-
// src/core/frontmatter.ts
|
|
494
|
+
// src/core/asset/frontmatter.ts
|
|
428
495
|
function parseFrontmatter(raw) {
|
|
429
496
|
const parsedBlock = parseFrontmatterBlock(raw);
|
|
430
497
|
if (!parsedBlock) {
|
|
@@ -572,7 +639,7 @@ function parseYamlScalar(value) {
|
|
|
572
639
|
return value;
|
|
573
640
|
}
|
|
574
641
|
|
|
575
|
-
// src/core/markdown.ts
|
|
642
|
+
// src/core/asset/markdown.ts
|
|
576
643
|
function parseMarkdownToc(content) {
|
|
577
644
|
const lines = content.split(/\r?\n/);
|
|
578
645
|
const headings = [];
|
|
@@ -592,15 +659,16 @@ function parseMarkdownToc(content) {
|
|
|
592
659
|
}
|
|
593
660
|
var init_markdown = () => {};
|
|
594
661
|
|
|
595
|
-
// src/indexer/file-context.ts
|
|
596
|
-
var renderers;
|
|
597
|
-
var init_file_context = __esm(() => {
|
|
598
|
-
init_common();
|
|
599
|
-
renderers = new Map;
|
|
600
|
-
});
|
|
601
|
-
|
|
602
662
|
// src/core/warn.ts
|
|
603
663
|
import fs2 from "fs";
|
|
664
|
+
function isVerbose() {
|
|
665
|
+
const env = process.env.AKM_VERBOSE?.trim().toLowerCase();
|
|
666
|
+
if (env === "1" || env === "true" || env === "yes" || env === "on")
|
|
667
|
+
return true;
|
|
668
|
+
if (env === "0" || env === "false" || env === "no" || env === "off")
|
|
669
|
+
return false;
|
|
670
|
+
return verbose;
|
|
671
|
+
}
|
|
604
672
|
function appendToLogFile(level, args) {
|
|
605
673
|
if (!logFilePath)
|
|
606
674
|
return;
|
|
@@ -628,10 +696,22 @@ function error(...args) {
|
|
|
628
696
|
console.error(...args);
|
|
629
697
|
}
|
|
630
698
|
}
|
|
631
|
-
|
|
699
|
+
function warnVerbose(...args) {
|
|
700
|
+
if (isVerbose()) {
|
|
701
|
+
warn(...args);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
var quiet = false, verbose = false, logFilePath;
|
|
632
705
|
var init_warn = () => {};
|
|
633
706
|
|
|
634
|
-
// src/indexer/
|
|
707
|
+
// src/indexer/walk/file-context.ts
|
|
708
|
+
var renderers;
|
|
709
|
+
var init_file_context = __esm(() => {
|
|
710
|
+
init_common();
|
|
711
|
+
renderers = new Map;
|
|
712
|
+
});
|
|
713
|
+
|
|
714
|
+
// src/indexer/passes/metadata-contributors.ts
|
|
635
715
|
function registerMetadataContributor(contributor) {
|
|
636
716
|
contributors.push(contributor);
|
|
637
717
|
}
|
|
@@ -640,7 +720,7 @@ var init_metadata_contributors = __esm(() => {
|
|
|
640
720
|
contributors = [];
|
|
641
721
|
});
|
|
642
722
|
|
|
643
|
-
// src/indexer/metadata.ts
|
|
723
|
+
// src/indexer/passes/metadata.ts
|
|
644
724
|
import fs3 from "fs";
|
|
645
725
|
function extractDescriptionFromComments(filePath) {
|
|
646
726
|
let content;
|
|
@@ -692,69 +772,7 @@ var init_metadata = __esm(() => {
|
|
|
692
772
|
WIKI_INFRA_FILES = new Set(["schema.md", "index.md", "log.md"]);
|
|
693
773
|
});
|
|
694
774
|
|
|
695
|
-
// src/core/
|
|
696
|
-
function isTestIsolationError(err) {
|
|
697
|
-
return err instanceof ConfigError && err.code === "TEST_ISOLATION_MISSING";
|
|
698
|
-
}
|
|
699
|
-
function rethrowIfTestIsolationError(err) {
|
|
700
|
-
if (isTestIsolationError(err)) {
|
|
701
|
-
throw err;
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
var CONFIG_HINTS, USAGE_HINTS, ConfigError, UsageError;
|
|
705
|
-
var init_errors = __esm(() => {
|
|
706
|
-
CONFIG_HINTS = {
|
|
707
|
-
STASH_DIR_NOT_FOUND: "Run `akm setup` to create and configure your stash, or set stashDir in your config.",
|
|
708
|
-
STASH_DIR_NOT_A_DIRECTORY: "The configured stashDir exists but isn't a directory. Update stashDir to point at a folder.",
|
|
709
|
-
STASH_DIR_UNREADABLE: "Check the path exists and your user has read permission, or update stashDir.",
|
|
710
|
-
EMBEDDING_NOT_CONFIGURED: 'Run `akm config set embedding \'{"endpoint":"...","model":"..."}\'` to enable embeddings.',
|
|
711
|
-
LLM_NOT_CONFIGURED: 'Run `akm setup` or `akm config set profiles.llm.default \'{"endpoint":"...","model":"..."}\' to configure an LLM profile.',
|
|
712
|
-
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.",
|
|
713
|
-
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/ \u2014 host config is preserved).",
|
|
714
|
-
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."
|
|
715
|
-
};
|
|
716
|
-
USAGE_HINTS = {
|
|
717
|
-
INVALID_FLAG_VALUE: "Run `akm <command> --help` to see accepted values.",
|
|
718
|
-
INVALID_SOURCE_VALUE: "Pick one of: stash, registry, both.",
|
|
719
|
-
INVALID_FORMAT_VALUE: "Pick one of: json, jsonl, text, yaml.",
|
|
720
|
-
INVALID_DETAIL_VALUE: "Pick one of: brief, normal, full. For agent/summary projections use --shape.",
|
|
721
|
-
INVALID_SHAPE_VALUE: "Pick one of: human, agent, summary (summary is only valid on `akm show`).",
|
|
722
|
-
INVALID_JSON_CONFIG_VALUE: `Quote JSON values in your shell, for example: akm config set embedding '{"endpoint":"http://localhost:11434/v1/embeddings","model":"nomic-embed-text"}'.`,
|
|
723
|
-
MISSING_OR_AMBIGUOUS_TARGET: "Use `akm update --all` or pass a target like `akm update npm:@scope/pkg` (not both).",
|
|
724
|
-
TARGET_NOT_UPDATABLE: "Run `akm list` to view your sources, then retry with one of those values.",
|
|
725
|
-
MISSING_REQUIRED_ARGUMENT: "Refs use the form type:name, e.g. `akm show skill:deploy` or `akm show knowledge:guide.md`."
|
|
726
|
-
};
|
|
727
|
-
ConfigError = class ConfigError extends Error {
|
|
728
|
-
code;
|
|
729
|
-
_hint;
|
|
730
|
-
constructor(msg, code = "INVALID_CONFIG_FILE", hint) {
|
|
731
|
-
super(msg);
|
|
732
|
-
this.name = "ConfigError";
|
|
733
|
-
this.code = code;
|
|
734
|
-
this._hint = hint;
|
|
735
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
736
|
-
}
|
|
737
|
-
hint() {
|
|
738
|
-
return this._hint ?? CONFIG_HINTS[this.code];
|
|
739
|
-
}
|
|
740
|
-
};
|
|
741
|
-
UsageError = class UsageError extends Error {
|
|
742
|
-
code;
|
|
743
|
-
_hint;
|
|
744
|
-
constructor(msg, code = "INVALID_FLAG_VALUE", hint) {
|
|
745
|
-
super(msg);
|
|
746
|
-
this.name = "UsageError";
|
|
747
|
-
this.code = code;
|
|
748
|
-
this._hint = hint;
|
|
749
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
750
|
-
}
|
|
751
|
-
hint() {
|
|
752
|
-
return this._hint ?? USAGE_HINTS[this.code];
|
|
753
|
-
}
|
|
754
|
-
};
|
|
755
|
-
});
|
|
756
|
-
|
|
757
|
-
// src/core/asset-ref.ts
|
|
775
|
+
// src/core/asset/asset-ref.ts
|
|
758
776
|
import path from "path";
|
|
759
777
|
function parseAssetRef(ref) {
|
|
760
778
|
const trimmed = ref.trim();
|
|
@@ -775,6 +793,9 @@ function parseAssetRef(ref) {
|
|
|
775
793
|
}
|
|
776
794
|
const rawType = body.slice(0, colon);
|
|
777
795
|
const rawName = body.slice(colon + 1);
|
|
796
|
+
if (rawType === "vault") {
|
|
797
|
+
throw new UsageError("The `vault` asset type was removed in 0.9.0 \u2014 use `env:` (whole .env config) or `secret:` (a single value).", "MISSING_REQUIRED_ARGUMENT");
|
|
798
|
+
}
|
|
778
799
|
const resolvedType = TYPE_ALIASES[rawType] ?? rawType;
|
|
779
800
|
if (!isAssetType(resolvedType)) {
|
|
780
801
|
throw new UsageError(`Invalid asset type: "${rawType}".`, "MISSING_REQUIRED_ARGUMENT");
|
|
@@ -813,15 +834,6 @@ var init_asset_ref = __esm(() => {
|
|
|
813
834
|
};
|
|
814
835
|
});
|
|
815
836
|
|
|
816
|
-
// src/workflows/document-cache.ts
|
|
817
|
-
function cacheWorkflowDocument(entry, doc) {
|
|
818
|
-
cache.set(entry, doc);
|
|
819
|
-
}
|
|
820
|
-
var cache;
|
|
821
|
-
var init_document_cache = __esm(() => {
|
|
822
|
-
cache = new WeakMap;
|
|
823
|
-
});
|
|
824
|
-
|
|
825
837
|
// node_modules/yaml/dist/nodes/identity.js
|
|
826
838
|
var require_identity = __commonJS((exports) => {
|
|
827
839
|
var ALIAS = Symbol.for("yaml.alias");
|
|
@@ -8192,6 +8204,15 @@ var init_parser = __esm(() => {
|
|
|
8192
8204
|
BULLET_LINE = /^[-*]\s+(.+)$/;
|
|
8193
8205
|
});
|
|
8194
8206
|
|
|
8207
|
+
// src/workflows/runtime/document-cache.ts
|
|
8208
|
+
function cacheWorkflowDocument(entry, doc) {
|
|
8209
|
+
cache.set(entry, doc);
|
|
8210
|
+
}
|
|
8211
|
+
var cache;
|
|
8212
|
+
var init_document_cache = __esm(() => {
|
|
8213
|
+
cache = new WeakMap;
|
|
8214
|
+
});
|
|
8215
|
+
|
|
8195
8216
|
// src/workflows/renderer.ts
|
|
8196
8217
|
function shellQuote(value) {
|
|
8197
8218
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
@@ -8212,8 +8233,8 @@ var init_renderer = __esm(() => {
|
|
|
8212
8233
|
init_asset_ref();
|
|
8213
8234
|
init_errors();
|
|
8214
8235
|
init_metadata_contributors();
|
|
8215
|
-
init_document_cache();
|
|
8216
8236
|
init_parser();
|
|
8237
|
+
init_document_cache();
|
|
8217
8238
|
registerMetadataContributor({
|
|
8218
8239
|
name: "workflow-document-metadata",
|
|
8219
8240
|
appliesTo: ({ rendererName }) => rendererName === "workflow-md",
|
|
@@ -8242,6 +8263,24 @@ var init_renderer = __esm(() => {
|
|
|
8242
8263
|
});
|
|
8243
8264
|
|
|
8244
8265
|
// src/output/renderers.ts
|
|
8266
|
+
function applySessionMetadata(entry, ctx) {
|
|
8267
|
+
try {
|
|
8268
|
+
const fm = applyFrontmatterDescriptionAndTags(entry, ctx);
|
|
8269
|
+
entry.tags = Array.from(new Set([...entry.tags ?? [], "session"]));
|
|
8270
|
+
const hints = new Set(entry.searchHints ?? []);
|
|
8271
|
+
const harness = asNonEmptyString(fm.harness);
|
|
8272
|
+
if (harness)
|
|
8273
|
+
hints.add(`harness:${harness}`);
|
|
8274
|
+
const project = asNonEmptyString(fm.project);
|
|
8275
|
+
if (project)
|
|
8276
|
+
hints.add(`project:${project}`);
|
|
8277
|
+
const logPath = asNonEmptyString(fm.log_path);
|
|
8278
|
+
if (logPath)
|
|
8279
|
+
hints.add(`log_path:${logPath}`);
|
|
8280
|
+
if (hints.size > 0)
|
|
8281
|
+
entry.searchHints = Array.from(hints).filter(Boolean);
|
|
8282
|
+
} catch {}
|
|
8283
|
+
}
|
|
8245
8284
|
function applyTocMetadata(entry, ctx) {
|
|
8246
8285
|
try {
|
|
8247
8286
|
const toc = parseMarkdownToc(ctx.content());
|
|
@@ -8313,18 +8352,6 @@ function applyScriptMetadata(entry, ctx) {
|
|
|
8313
8352
|
entry.confidence = 0.7;
|
|
8314
8353
|
}
|
|
8315
8354
|
}
|
|
8316
|
-
function applyVaultMetadata(entry, ctx) {
|
|
8317
|
-
const { keys, comments } = listKeys(ctx.absPath);
|
|
8318
|
-
if (comments.length > 0 && !entry.description) {
|
|
8319
|
-
entry.description = comments.join(" ").slice(0, 500);
|
|
8320
|
-
entry.source = "comments";
|
|
8321
|
-
entry.confidence = 0.7;
|
|
8322
|
-
}
|
|
8323
|
-
if (keys.length > 0) {
|
|
8324
|
-
entry.searchHints = keys;
|
|
8325
|
-
}
|
|
8326
|
-
entry.tags = Array.from(new Set([...entry.tags ?? [], "vault", "secrets"]));
|
|
8327
|
-
}
|
|
8328
8355
|
function applyEnvMetadata(entry, ctx) {
|
|
8329
8356
|
const { keys, comments } = listKeys(ctx.absPath);
|
|
8330
8357
|
if (comments.length > 0 && !entry.description) {
|
|
@@ -8360,11 +8387,11 @@ function applyTaskMetadata(entry, ctx) {
|
|
|
8360
8387
|
}
|
|
8361
8388
|
var init_renderers = __esm(() => {
|
|
8362
8389
|
init_env();
|
|
8363
|
-
init_common();
|
|
8364
8390
|
init_markdown();
|
|
8365
|
-
|
|
8391
|
+
init_common();
|
|
8366
8392
|
init_metadata();
|
|
8367
8393
|
init_metadata_contributors();
|
|
8394
|
+
init_file_context();
|
|
8368
8395
|
init_renderer();
|
|
8369
8396
|
registerMetadataContributor({
|
|
8370
8397
|
name: "toc-metadata",
|
|
@@ -8386,11 +8413,6 @@ var init_renderers = __esm(() => {
|
|
|
8386
8413
|
appliesTo: ({ rendererName }) => rendererName === "script-source",
|
|
8387
8414
|
contribute: (entry, ctx) => applyScriptMetadata(entry, ctx.renderContext)
|
|
8388
8415
|
});
|
|
8389
|
-
registerMetadataContributor({
|
|
8390
|
-
name: "vault-secret-metadata",
|
|
8391
|
-
appliesTo: ({ rendererName }) => rendererName === "vault-env",
|
|
8392
|
-
contribute: (entry, ctx) => applyVaultMetadata(entry, ctx.renderContext)
|
|
8393
|
-
});
|
|
8394
8416
|
registerMetadataContributor({
|
|
8395
8417
|
name: "env-file-metadata",
|
|
8396
8418
|
appliesTo: ({ rendererName }) => rendererName === "env-file",
|
|
@@ -8406,20 +8428,28 @@ var init_renderers = __esm(() => {
|
|
|
8406
8428
|
appliesTo: ({ rendererName }) => rendererName === "task-yaml",
|
|
8407
8429
|
contribute: (entry, ctx) => applyTaskMetadata(entry, ctx.renderContext)
|
|
8408
8430
|
});
|
|
8431
|
+
registerMetadataContributor({
|
|
8432
|
+
name: "session-md-metadata",
|
|
8433
|
+
appliesTo: ({ rendererName }) => rendererName === "session-md",
|
|
8434
|
+
contribute: (entry, ctx) => applySessionMetadata(entry, ctx.renderContext)
|
|
8435
|
+
});
|
|
8409
8436
|
});
|
|
8410
8437
|
|
|
8411
|
-
// src/core/asset-registry.ts
|
|
8438
|
+
// src/core/asset/asset-registry.ts
|
|
8412
8439
|
var init_asset_registry = __esm(() => {
|
|
8413
8440
|
init_renderers();
|
|
8414
8441
|
});
|
|
8415
8442
|
|
|
8416
|
-
// src/core/asset-spec.ts
|
|
8443
|
+
// src/core/asset/asset-spec.ts
|
|
8417
8444
|
import path2 from "path";
|
|
8445
|
+
function getAssetTypes() {
|
|
8446
|
+
return Object.keys(ASSET_SPECS_INTERNAL);
|
|
8447
|
+
}
|
|
8418
8448
|
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;
|
|
8419
8449
|
var init_asset_spec = __esm(() => {
|
|
8420
8450
|
init_renderers();
|
|
8421
|
-
init_asset_registry();
|
|
8422
8451
|
init_common();
|
|
8452
|
+
init_asset_registry();
|
|
8423
8453
|
markdownSpec = {
|
|
8424
8454
|
isRelevantFile: (fileName) => path2.extname(fileName).toLowerCase() === ".md",
|
|
8425
8455
|
toCanonicalName: (typeRoot, filePath) => {
|
|
@@ -8498,27 +8528,6 @@ var init_asset_spec = __esm(() => {
|
|
|
8498
8528
|
rendererName: "env-file",
|
|
8499
8529
|
actionBuilder: (ref) => `akm show ${ref} -> inspect key names; akm env run ${ref} -- <command> -> run with the whole .env injected (values never reach stdout); akm env export ${ref} --out <file> -> write a sourceable script to a file`
|
|
8500
8530
|
},
|
|
8501
|
-
vault: {
|
|
8502
|
-
stashDir: "vaults",
|
|
8503
|
-
isRelevantFile: (fileName) => fileName === ".env" || fileName.endsWith(".env"),
|
|
8504
|
-
toCanonicalName: (typeRoot, filePath) => {
|
|
8505
|
-
const rel = toPosix(path2.relative(typeRoot, filePath));
|
|
8506
|
-
const fileName = path2.basename(rel);
|
|
8507
|
-
if (fileName === ".env") {
|
|
8508
|
-
const dir = path2.dirname(rel);
|
|
8509
|
-
return dir === "." || dir === "" ? "default" : `${dir}/default`;
|
|
8510
|
-
}
|
|
8511
|
-
const stripped = rel.endsWith(".env") ? rel.slice(0, -4) : rel;
|
|
8512
|
-
return stripped;
|
|
8513
|
-
},
|
|
8514
|
-
toAssetPath: (typeRoot, name) => {
|
|
8515
|
-
if (name === "default")
|
|
8516
|
-
return path2.join(typeRoot, ".env");
|
|
8517
|
-
return path2.join(typeRoot, name.endsWith(".env") ? name : `${name}.env`);
|
|
8518
|
-
},
|
|
8519
|
-
rendererName: "vault-env",
|
|
8520
|
-
actionBuilder: (ref) => `DEPRECATED (use env): akm show ${ref} -> inspect key names; akm env run ${ref} -- <command> -> run with injected env`
|
|
8521
|
-
},
|
|
8522
8531
|
secret: {
|
|
8523
8532
|
stashDir: "secrets",
|
|
8524
8533
|
isRelevantFile: (fileName) => !fileName.endsWith(".lock") && !fileName.endsWith(".sensitive"),
|
|
@@ -8552,6 +8561,12 @@ var init_asset_spec = __esm(() => {
|
|
|
8552
8561
|
},
|
|
8553
8562
|
rendererName: "task-yaml",
|
|
8554
8563
|
actionBuilder: buildTaskAction
|
|
8564
|
+
},
|
|
8565
|
+
session: {
|
|
8566
|
+
stashDir: "sessions",
|
|
8567
|
+
...markdownSpec,
|
|
8568
|
+
rendererName: "session-md",
|
|
8569
|
+
actionBuilder: (ref) => `akm show ${ref} -> read the session summary; follow the \`access\` frontmatter to open the raw log at \`log_path\``
|
|
8555
8570
|
}
|
|
8556
8571
|
};
|
|
8557
8572
|
TYPE_DIRS = Object.fromEntries(Object.entries(ASSET_SPECS_INTERNAL).map(([type, spec]) => [type, spec.stashDir]));
|
|
@@ -8568,7 +8583,11 @@ function writeFileAtomic(target, content, mode) {
|
|
|
8568
8583
|
const tmp = `${target}.tmp.${process.pid}.${crypto.randomBytes(8).toString("hex")}`;
|
|
8569
8584
|
const fd = fs4.openSync(tmp, "w", mode ?? 384);
|
|
8570
8585
|
try {
|
|
8571
|
-
|
|
8586
|
+
if (typeof content === "string") {
|
|
8587
|
+
fs4.writeSync(fd, content);
|
|
8588
|
+
} else {
|
|
8589
|
+
fs4.writeSync(fd, content);
|
|
8590
|
+
}
|
|
8572
8591
|
try {
|
|
8573
8592
|
fs4.fdatasyncSync(fd);
|
|
8574
8593
|
} catch {}
|
|
@@ -8607,20 +8626,7 @@ var init_common = __esm(() => {
|
|
|
8607
8626
|
init_asset_spec();
|
|
8608
8627
|
init_errors();
|
|
8609
8628
|
init_paths();
|
|
8610
|
-
ASSET_TYPES = [
|
|
8611
|
-
"skill",
|
|
8612
|
-
"command",
|
|
8613
|
-
"agent",
|
|
8614
|
-
"knowledge",
|
|
8615
|
-
"workflow",
|
|
8616
|
-
"script",
|
|
8617
|
-
"memory",
|
|
8618
|
-
"env",
|
|
8619
|
-
"vault",
|
|
8620
|
-
"secret",
|
|
8621
|
-
"wiki",
|
|
8622
|
-
"lesson"
|
|
8623
|
-
];
|
|
8629
|
+
ASSET_TYPES = Object.freeze([...getAssetTypes()]);
|
|
8624
8630
|
ASSET_TYPE_SET = new Set(ASSET_TYPES);
|
|
8625
8631
|
IS_WINDOWS = process.platform === "win32";
|
|
8626
8632
|
DEFAULT_RESPONSE_BYTE_CAP = 10 * 1024 * 1024;
|
|
@@ -8760,67 +8766,71 @@ var init_paths = __esm(() => {
|
|
|
8760
8766
|
init_errors();
|
|
8761
8767
|
});
|
|
8762
8768
|
|
|
8763
|
-
// src/
|
|
8764
|
-
|
|
8765
|
-
|
|
8766
|
-
|
|
8767
|
-
|
|
8768
|
-
upsertExtractedSession: () => upsertExtractedSession,
|
|
8769
|
-
shouldSkipAlreadyExtractedSession: () => shouldSkipAlreadyExtractedSession,
|
|
8770
|
-
runMigrations: () => runMigrations,
|
|
8771
|
-
recordImproveRun: () => recordImproveRun,
|
|
8772
|
-
readStateEvents: () => readStateEvents,
|
|
8773
|
-
queryTaskHistory: () => queryTaskHistory,
|
|
8774
|
-
purgeOldImproveRuns: () => purgeOldImproveRuns,
|
|
8775
|
-
purgeOldEvents: () => purgeOldEvents,
|
|
8776
|
-
proposalToRowValues: () => proposalToRowValues,
|
|
8777
|
-
proposalRowToProposal: () => proposalRowToProposal,
|
|
8778
|
-
openStateDatabase: () => openStateDatabase,
|
|
8779
|
-
listStateProposals: () => listStateProposals,
|
|
8780
|
-
insertEvent: () => insertEvent,
|
|
8781
|
-
importEventsJsonl: () => importEventsJsonl,
|
|
8782
|
-
getTaskHistoryRuns: () => getTaskHistoryRuns,
|
|
8783
|
-
getTaskHistory: () => getTaskHistory,
|
|
8784
|
-
getStateProposal: () => getStateProposal,
|
|
8785
|
-
getStateDbPath: () => getStateDbPath,
|
|
8786
|
-
getExtractedSessionsMap: () => getExtractedSessionsMap,
|
|
8787
|
-
getExtractedSession: () => getExtractedSession,
|
|
8788
|
-
eventRowToEnvelope: () => eventRowToEnvelope,
|
|
8789
|
-
computeImproveRunMetrics: () => computeImproveRunMetrics,
|
|
8790
|
-
REGISTRY_INDEX_CACHE_DDL: () => REGISTRY_INDEX_CACHE_DDL
|
|
8791
|
-
});
|
|
8792
|
-
import { Database } from "bun:sqlite";
|
|
8793
|
-
import fs5 from "fs";
|
|
8794
|
-
import path5 from "path";
|
|
8795
|
-
function getStateDbPath() {
|
|
8796
|
-
return path5.join(getDataDir(), "state.db");
|
|
8797
|
-
}
|
|
8798
|
-
function openStateDatabase(dbPath) {
|
|
8799
|
-
const resolvedPath = dbPath ?? getStateDbPath();
|
|
8800
|
-
const dir = path5.dirname(resolvedPath);
|
|
8801
|
-
if (!fs5.existsSync(dir)) {
|
|
8802
|
-
fs5.mkdirSync(dir, { recursive: true });
|
|
8769
|
+
// src/storage/database.ts
|
|
8770
|
+
import { createRequire } from "module";
|
|
8771
|
+
function openDatabase(path5, opts) {
|
|
8772
|
+
if (isBun) {
|
|
8773
|
+
return openBunDatabase(path5, opts);
|
|
8803
8774
|
}
|
|
8804
|
-
|
|
8805
|
-
|
|
8806
|
-
|
|
8807
|
-
|
|
8808
|
-
|
|
8775
|
+
return openNodeDatabase(path5, opts);
|
|
8776
|
+
}
|
|
8777
|
+
function openBunDatabase(path5, opts) {
|
|
8778
|
+
const { Database: BunDatabase } = loadBunSqlite();
|
|
8779
|
+
const db = opts ? new BunDatabase(path5, bunOptions(opts)) : new BunDatabase(path5);
|
|
8809
8780
|
return db;
|
|
8810
8781
|
}
|
|
8811
|
-
function
|
|
8812
|
-
|
|
8782
|
+
function bunOptions(opts) {
|
|
8783
|
+
const out = {};
|
|
8784
|
+
if (opts.readonly !== undefined)
|
|
8785
|
+
out.readonly = opts.readonly;
|
|
8786
|
+
if (opts.create !== undefined)
|
|
8787
|
+
out.create = opts.create;
|
|
8788
|
+
return out;
|
|
8789
|
+
}
|
|
8790
|
+
function loadBunSqlite() {
|
|
8791
|
+
if (!bunSqliteModule) {
|
|
8792
|
+
bunSqliteModule = nodeRequire("bun:sqlite");
|
|
8793
|
+
}
|
|
8794
|
+
return bunSqliteModule;
|
|
8795
|
+
}
|
|
8796
|
+
function loadBetterSqlite3() {
|
|
8797
|
+
if (!betterSqlite3Ctor) {
|
|
8798
|
+
const mod = nodeRequire("better-sqlite3");
|
|
8799
|
+
betterSqlite3Ctor = mod.default ?? mod;
|
|
8800
|
+
}
|
|
8801
|
+
return betterSqlite3Ctor;
|
|
8802
|
+
}
|
|
8803
|
+
function openNodeDatabase(path5, opts) {
|
|
8804
|
+
const BetterSqlite3 = loadBetterSqlite3();
|
|
8805
|
+
const options = {};
|
|
8806
|
+
if (opts?.readonly !== undefined)
|
|
8807
|
+
options.readonly = opts.readonly;
|
|
8808
|
+
if (opts?.create === false)
|
|
8809
|
+
options.fileMustExist = true;
|
|
8810
|
+
const db = opts ? new BetterSqlite3(path5, options) : new BetterSqlite3(path5);
|
|
8811
|
+
return db;
|
|
8812
|
+
}
|
|
8813
|
+
var isBun, nodeRequire, bunSqliteModule, betterSqlite3Ctor;
|
|
8814
|
+
var init_database = __esm(() => {
|
|
8815
|
+
isBun = !!process.versions?.bun;
|
|
8816
|
+
nodeRequire = createRequire(import.meta.url);
|
|
8817
|
+
});
|
|
8818
|
+
|
|
8819
|
+
// src/storage/engines/sqlite-migrations.ts
|
|
8820
|
+
function ensureMigrationsTable(db) {
|
|
8821
|
+
db.exec(`
|
|
8813
8822
|
CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
8814
8823
|
id TEXT PRIMARY KEY,
|
|
8815
8824
|
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
8816
8825
|
);
|
|
8817
8826
|
`);
|
|
8818
8827
|
}
|
|
8819
|
-
function runMigrations(db) {
|
|
8828
|
+
function runMigrations(db, migrations, opts) {
|
|
8820
8829
|
ensureMigrationsTable(db);
|
|
8830
|
+
opts?.bootstrap?.(db);
|
|
8821
8831
|
const appliedRows = db.prepare("SELECT id FROM schema_migrations").all();
|
|
8822
8832
|
const applied = new Set(appliedRows.map((r) => r.id));
|
|
8823
|
-
for (const migration of
|
|
8833
|
+
for (const migration of migrations) {
|
|
8824
8834
|
if (applied.has(migration.id))
|
|
8825
8835
|
continue;
|
|
8826
8836
|
db.transaction(() => {
|
|
@@ -8829,6 +8839,103 @@ function runMigrations(db) {
|
|
|
8829
8839
|
})();
|
|
8830
8840
|
}
|
|
8831
8841
|
}
|
|
8842
|
+
|
|
8843
|
+
// src/core/assert.ts
|
|
8844
|
+
function assertNever(x, context) {
|
|
8845
|
+
let serialized;
|
|
8846
|
+
try {
|
|
8847
|
+
serialized = JSON.stringify(x);
|
|
8848
|
+
} catch {
|
|
8849
|
+
serialized = String(x);
|
|
8850
|
+
}
|
|
8851
|
+
if (serialized === undefined) {
|
|
8852
|
+
serialized = String(x);
|
|
8853
|
+
}
|
|
8854
|
+
const where = context ? ` (${context})` : "";
|
|
8855
|
+
throw new Error(`Unexpected value reached assertNever${where}: ${serialized}`);
|
|
8856
|
+
}
|
|
8857
|
+
|
|
8858
|
+
// src/core/improve-types.ts
|
|
8859
|
+
function classifyImproveAction(mode) {
|
|
8860
|
+
switch (mode) {
|
|
8861
|
+
case "reflect":
|
|
8862
|
+
case "distill":
|
|
8863
|
+
case "memory-inference":
|
|
8864
|
+
case "graph-extraction":
|
|
8865
|
+
return "accepted";
|
|
8866
|
+
case "reflect-cooldown":
|
|
8867
|
+
case "reflect-skipped":
|
|
8868
|
+
case "distill-skipped":
|
|
8869
|
+
case "reflect-guard-rejected":
|
|
8870
|
+
return "rejected";
|
|
8871
|
+
case "reflect-failed":
|
|
8872
|
+
case "error":
|
|
8873
|
+
return "error";
|
|
8874
|
+
case "memory-prune":
|
|
8875
|
+
return "noop";
|
|
8876
|
+
default:
|
|
8877
|
+
return assertNever(mode);
|
|
8878
|
+
}
|
|
8879
|
+
}
|
|
8880
|
+
var init_improve_types = () => {};
|
|
8881
|
+
|
|
8882
|
+
// src/core/state-db.ts
|
|
8883
|
+
var exports_state_db = {};
|
|
8884
|
+
__export(exports_state_db, {
|
|
8885
|
+
upsertTaskHistory: () => upsertTaskHistory,
|
|
8886
|
+
upsertProposal: () => upsertProposal,
|
|
8887
|
+
upsertExtractedSession: () => upsertExtractedSession,
|
|
8888
|
+
shouldSkipAlreadyExtractedSession: () => shouldSkipAlreadyExtractedSession,
|
|
8889
|
+
runMigrations: () => runMigrations2,
|
|
8890
|
+
recordImproveRun: () => recordImproveRun,
|
|
8891
|
+
recordFsProposalsImport: () => recordFsProposalsImport,
|
|
8892
|
+
readStateEvents: () => readStateEvents,
|
|
8893
|
+
queryTaskHistory: () => queryTaskHistory,
|
|
8894
|
+
queryImproveRuns: () => queryImproveRuns,
|
|
8895
|
+
queryCompletedTaskIntervals: () => queryCompletedTaskIntervals,
|
|
8896
|
+
purgeOldImproveRuns: () => purgeOldImproveRuns,
|
|
8897
|
+
purgeOldEvents: () => purgeOldEvents,
|
|
8898
|
+
proposalToRowValues: () => proposalToRowValues,
|
|
8899
|
+
proposalRowToProposal: () => proposalRowToProposal,
|
|
8900
|
+
openStateDatabase: () => openStateDatabase,
|
|
8901
|
+
listStateProposals: () => listStateProposals,
|
|
8902
|
+
listStateProposalIdsByPrefix: () => listStateProposalIdsByPrefix,
|
|
8903
|
+
listExistingTableNames: () => listExistingTableNames,
|
|
8904
|
+
insertProposalIfAbsent: () => insertProposalIfAbsent,
|
|
8905
|
+
insertEvent: () => insertEvent,
|
|
8906
|
+
importEventsJsonl: () => importEventsJsonl,
|
|
8907
|
+
hasImportedFsProposals: () => hasImportedFsProposals,
|
|
8908
|
+
getTaskHistoryRuns: () => getTaskHistoryRuns,
|
|
8909
|
+
getTaskHistory: () => getTaskHistory,
|
|
8910
|
+
getStateProposal: () => getStateProposal,
|
|
8911
|
+
getStateDbPath: () => getStateDbPath,
|
|
8912
|
+
getExtractedSessionsMap: () => getExtractedSessionsMap,
|
|
8913
|
+
getExtractedSession: () => getExtractedSession,
|
|
8914
|
+
eventRowToEnvelope: () => eventRowToEnvelope,
|
|
8915
|
+
computeImproveRunMetrics: () => computeImproveRunMetrics,
|
|
8916
|
+
REGISTRY_INDEX_CACHE_DDL: () => REGISTRY_INDEX_CACHE_DDL
|
|
8917
|
+
});
|
|
8918
|
+
import fs5 from "fs";
|
|
8919
|
+
import path5 from "path";
|
|
8920
|
+
function getStateDbPath() {
|
|
8921
|
+
return path5.join(getDataDir(), "state.db");
|
|
8922
|
+
}
|
|
8923
|
+
function openStateDatabase(dbPath) {
|
|
8924
|
+
const resolvedPath = dbPath ?? getStateDbPath();
|
|
8925
|
+
const dir = path5.dirname(resolvedPath);
|
|
8926
|
+
if (!fs5.existsSync(dir)) {
|
|
8927
|
+
fs5.mkdirSync(dir, { recursive: true });
|
|
8928
|
+
}
|
|
8929
|
+
const db = openDatabase(resolvedPath);
|
|
8930
|
+
db.exec("PRAGMA journal_mode = WAL");
|
|
8931
|
+
db.exec("PRAGMA foreign_keys = ON");
|
|
8932
|
+
db.exec("PRAGMA busy_timeout = 30000");
|
|
8933
|
+
runMigrations2(db);
|
|
8934
|
+
return db;
|
|
8935
|
+
}
|
|
8936
|
+
function runMigrations2(db) {
|
|
8937
|
+
runMigrations(db, MIGRATIONS);
|
|
8938
|
+
}
|
|
8832
8939
|
function eventRowToEnvelope(row) {
|
|
8833
8940
|
let metadata;
|
|
8834
8941
|
try {
|
|
@@ -8869,7 +8976,10 @@ function proposalRowToProposal(row) {
|
|
|
8869
8976
|
content: row.content,
|
|
8870
8977
|
...frontmatter !== undefined ? { frontmatter } : {}
|
|
8871
8978
|
},
|
|
8872
|
-
...meta.review !== undefined ? { review: meta.review } : {}
|
|
8979
|
+
...meta.review !== undefined ? { review: meta.review } : {},
|
|
8980
|
+
...typeof meta.confidence === "number" ? { confidence: meta.confidence } : {},
|
|
8981
|
+
...meta.gateDecision !== undefined ? { gateDecision: meta.gateDecision } : {},
|
|
8982
|
+
...typeof meta.backupContent === "string" ? { backupContent: meta.backupContent } : {}
|
|
8873
8983
|
};
|
|
8874
8984
|
}
|
|
8875
8985
|
function proposalToRowValues(proposal, stashDir) {
|
|
@@ -8878,6 +8988,12 @@ function proposalToRowValues(proposal, stashDir) {
|
|
|
8878
8988
|
metaObj.sourceRun = proposal.sourceRun;
|
|
8879
8989
|
if (proposal.review !== undefined)
|
|
8880
8990
|
metaObj.review = proposal.review;
|
|
8991
|
+
if (proposal.confidence !== undefined)
|
|
8992
|
+
metaObj.confidence = proposal.confidence;
|
|
8993
|
+
if (proposal.gateDecision !== undefined)
|
|
8994
|
+
metaObj.gateDecision = proposal.gateDecision;
|
|
8995
|
+
if (proposal.backupContent !== undefined)
|
|
8996
|
+
metaObj.backupContent = proposal.backupContent;
|
|
8881
8997
|
return {
|
|
8882
8998
|
id: proposal.id,
|
|
8883
8999
|
stash_dir: stashDir,
|
|
@@ -8971,15 +9087,39 @@ function listStateProposals(db, options = {}) {
|
|
|
8971
9087
|
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
8972
9088
|
const rows = db.prepare(`SELECT id, stash_dir, ref, status, source, created_at, updated_at,
|
|
8973
9089
|
content, frontmatter_json, metadata_json
|
|
8974
|
-
FROM proposals ${where} ORDER BY created_at ASC`).all(...params);
|
|
9090
|
+
FROM proposals ${where} ORDER BY created_at ASC, rowid ASC`).all(...params);
|
|
8975
9091
|
return rows.map(proposalRowToProposal);
|
|
8976
9092
|
}
|
|
8977
|
-
function getStateProposal(db, id) {
|
|
8978
|
-
const
|
|
9093
|
+
function getStateProposal(db, id, stashDir) {
|
|
9094
|
+
const sql = `SELECT id, stash_dir, ref, status, source, created_at, updated_at,
|
|
8979
9095
|
content, frontmatter_json, metadata_json
|
|
8980
|
-
FROM proposals WHERE id =
|
|
9096
|
+
FROM proposals WHERE id = ?${stashDir ? " AND stash_dir = ?" : ""}`;
|
|
9097
|
+
const row = stashDir ? db.prepare(sql).get(id, stashDir) : db.prepare(sql).get(id);
|
|
8981
9098
|
return row ? proposalRowToProposal(row) : undefined;
|
|
8982
9099
|
}
|
|
9100
|
+
function listStateProposalIdsByPrefix(db, stashDir, idPrefix) {
|
|
9101
|
+
const escaped = idPrefix.replace(/[\\%_]/g, (ch) => `\\${ch}`);
|
|
9102
|
+
const rows = db.prepare(`SELECT id FROM proposals
|
|
9103
|
+
WHERE stash_dir = ? AND status = 'pending' AND id LIKE ? ESCAPE '\\'
|
|
9104
|
+
ORDER BY id ASC`).all(stashDir, `${escaped}%`);
|
|
9105
|
+
return rows.map((r) => r.id);
|
|
9106
|
+
}
|
|
9107
|
+
function hasImportedFsProposals(db, stashDir) {
|
|
9108
|
+
return Boolean(db.prepare("SELECT 1 FROM proposal_fs_imports WHERE stash_dir = ?").get(stashDir));
|
|
9109
|
+
}
|
|
9110
|
+
function recordFsProposalsImport(db, stashDir, importedCount) {
|
|
9111
|
+
db.prepare("INSERT OR REPLACE INTO proposal_fs_imports (stash_dir, imported_at, imported_count) VALUES (?, ?, ?)").run(stashDir, new Date().toISOString(), importedCount);
|
|
9112
|
+
}
|
|
9113
|
+
function insertProposalIfAbsent(db, proposal, stashDir) {
|
|
9114
|
+
const v = proposalToRowValues(proposal, stashDir);
|
|
9115
|
+
const result = db.prepare(`
|
|
9116
|
+
INSERT OR IGNORE INTO proposals
|
|
9117
|
+
(id, stash_dir, ref, status, source, created_at, updated_at, content, frontmatter_json, metadata_json)
|
|
9118
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
9119
|
+
`).run(v.id, v.stash_dir, v.ref, v.status, v.source, v.created_at, v.updated_at, v.content, v.frontmatter_json, v.metadata_json);
|
|
9120
|
+
const changes = result.changes ?? 0;
|
|
9121
|
+
return Number(changes) > 0;
|
|
9122
|
+
}
|
|
8983
9123
|
function upsertTaskHistory(db, row) {
|
|
8984
9124
|
db.prepare(`
|
|
8985
9125
|
INSERT OR IGNORE INTO task_history
|
|
@@ -9026,6 +9166,16 @@ function queryTaskHistory(db, options = {}) {
|
|
|
9026
9166
|
target_kind, target_ref, metadata_json
|
|
9027
9167
|
FROM task_history ${where} ORDER BY started_at DESC`).all(...params);
|
|
9028
9168
|
}
|
|
9169
|
+
function queryCompletedTaskIntervals(db, since, until) {
|
|
9170
|
+
const sql = until ? "SELECT started_at, completed_at FROM task_history WHERE task_id = 'akm-improve' AND started_at >= ? AND started_at < ? AND completed_at IS NOT NULL ORDER BY started_at" : "SELECT started_at, completed_at FROM task_history WHERE task_id = 'akm-improve' AND started_at >= ? AND completed_at IS NOT NULL ORDER BY started_at";
|
|
9171
|
+
return until ? db.prepare(sql).all(since, until) : db.prepare(sql).all(since);
|
|
9172
|
+
}
|
|
9173
|
+
function listExistingTableNames(db, names) {
|
|
9174
|
+
if (names.length === 0)
|
|
9175
|
+
return [];
|
|
9176
|
+
const placeholders = names.map(() => "?").join(", ");
|
|
9177
|
+
return db.prepare(`SELECT name FROM sqlite_master WHERE type = 'table' AND name IN (${placeholders}) ORDER BY name`).all(...names);
|
|
9178
|
+
}
|
|
9029
9179
|
async function importEventsJsonl(db, jsonlPath) {
|
|
9030
9180
|
const { readFileSync, existsSync } = await import("fs");
|
|
9031
9181
|
if (!existsSync(jsonlPath)) {
|
|
@@ -9082,23 +9232,17 @@ function computeImproveRunMetrics(result) {
|
|
|
9082
9232
|
let autoAcceptedCount = 0;
|
|
9083
9233
|
let errorCount = 0;
|
|
9084
9234
|
for (const action of actions) {
|
|
9085
|
-
switch (action.mode) {
|
|
9086
|
-
case "
|
|
9087
|
-
case "distill":
|
|
9088
|
-
case "memory-inference":
|
|
9089
|
-
case "graph-extraction":
|
|
9235
|
+
switch (classifyImproveAction(action.mode)) {
|
|
9236
|
+
case "accepted":
|
|
9090
9237
|
acceptedCount++;
|
|
9091
9238
|
break;
|
|
9092
|
-
case "
|
|
9093
|
-
case "reflect-skipped":
|
|
9094
|
-
case "distill-skipped":
|
|
9239
|
+
case "rejected":
|
|
9095
9240
|
rejectedCount++;
|
|
9096
9241
|
break;
|
|
9097
|
-
case "reflect-failed":
|
|
9098
9242
|
case "error":
|
|
9099
9243
|
errorCount++;
|
|
9100
9244
|
break;
|
|
9101
|
-
case "
|
|
9245
|
+
case "noop":
|
|
9102
9246
|
break;
|
|
9103
9247
|
}
|
|
9104
9248
|
const r = action.result;
|
|
@@ -9117,6 +9261,10 @@ function recordImproveRun(db, input) {
|
|
|
9117
9261
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
9118
9262
|
`).run(input.id, input.startedAt, input.completedAt, input.stashDir, input.dryRun ? 1 : 0, input.profile, input.scopeMode, input.scopeValue, input.guidance, input.ok ? 1 : 0, JSON.stringify(input.result), JSON.stringify(metricsObj), JSON.stringify(input.metadata ?? {}));
|
|
9119
9263
|
}
|
|
9264
|
+
function queryImproveRuns(db, since, until) {
|
|
9265
|
+
const sql = until ? "SELECT id, started_at, completed_at, ok, scope_mode, scope_value, result_json FROM improve_runs WHERE started_at >= ? AND started_at < ? AND dry_run = 0 ORDER BY started_at DESC" : "SELECT id, started_at, completed_at, ok, scope_mode, scope_value, result_json FROM improve_runs WHERE started_at >= ? AND dry_run = 0 ORDER BY started_at DESC";
|
|
9266
|
+
return until ? db.prepare(sql).all(since, until) : db.prepare(sql).all(since);
|
|
9267
|
+
}
|
|
9120
9268
|
function purgeOldImproveRuns(db, retentionDays = 90) {
|
|
9121
9269
|
if (!Number.isFinite(retentionDays) || retentionDays <= 0)
|
|
9122
9270
|
return 0;
|
|
@@ -9177,6 +9325,8 @@ var MIGRATIONS, REGISTRY_INDEX_CACHE_DDL = `
|
|
|
9177
9325
|
ON registry_index_cache(fetched_at);
|
|
9178
9326
|
`;
|
|
9179
9327
|
var init_state_db = __esm(() => {
|
|
9328
|
+
init_database();
|
|
9329
|
+
init_improve_types();
|
|
9180
9330
|
init_paths();
|
|
9181
9331
|
init_warn();
|
|
9182
9332
|
MIGRATIONS = [
|
|
@@ -9250,7 +9400,9 @@ var init_state_db = __esm(() => {
|
|
|
9250
9400
|
--
|
|
9251
9401
|
-- Extensible (metadata_json) columns:
|
|
9252
9402
|
-- metadata_json TEXT \u2014 JSON object for future proposal fields.
|
|
9253
|
-
-- Current fields stored here: sourceRun,
|
|
9403
|
+
-- Current fields stored here: sourceRun,
|
|
9404
|
+
-- review, confidence, gateDecision (#577),
|
|
9405
|
+
-- backupContent.
|
|
9254
9406
|
--
|
|
9255
9407
|
-- ADD COLUMN extension points (future migrations):
|
|
9256
9408
|
-- ALTER TABLE proposals ADD COLUMN source_run TEXT DEFAULT NULL;
|
|
@@ -9437,10 +9589,35 @@ var init_state_db = __esm(() => {
|
|
|
9437
9589
|
CREATE INDEX IF NOT EXISTS idx_extract_sessions_processed
|
|
9438
9590
|
ON extract_sessions_seen(processed_at);
|
|
9439
9591
|
`
|
|
9592
|
+
},
|
|
9593
|
+
{
|
|
9594
|
+
id: "005-proposal-fs-imports",
|
|
9595
|
+
up: `
|
|
9596
|
+
CREATE TABLE IF NOT EXISTS proposal_fs_imports (
|
|
9597
|
+
stash_dir TEXT PRIMARY KEY,
|
|
9598
|
+
imported_at TEXT NOT NULL,
|
|
9599
|
+
imported_count INTEGER NOT NULL DEFAULT 0
|
|
9600
|
+
);
|
|
9601
|
+
`
|
|
9440
9602
|
}
|
|
9441
9603
|
];
|
|
9442
9604
|
});
|
|
9443
9605
|
|
|
9606
|
+
// src/core/best-effort.ts
|
|
9607
|
+
function bestEffort(fn, context) {
|
|
9608
|
+
try {
|
|
9609
|
+
return fn();
|
|
9610
|
+
} catch (err) {
|
|
9611
|
+
if (isVerbose()) {
|
|
9612
|
+
warnVerbose(`[akm:best-effort] ${context ? `${context}: ` : ""}swallowed error`, err);
|
|
9613
|
+
}
|
|
9614
|
+
return;
|
|
9615
|
+
}
|
|
9616
|
+
}
|
|
9617
|
+
var init_best_effort = __esm(() => {
|
|
9618
|
+
init_warn();
|
|
9619
|
+
});
|
|
9620
|
+
|
|
9444
9621
|
// src/llm/embedders/types.ts
|
|
9445
9622
|
function cosineSimilarity(a, b) {
|
|
9446
9623
|
if (a.length !== b.length) {
|
|
@@ -9465,7 +9642,98 @@ var init_types = __esm(() => {
|
|
|
9465
9642
|
init_warn();
|
|
9466
9643
|
});
|
|
9467
9644
|
|
|
9468
|
-
// src/
|
|
9645
|
+
// src/runtime.ts
|
|
9646
|
+
import { createHash } from "crypto";
|
|
9647
|
+
import { createRequire as createRequire2 } from "module";
|
|
9648
|
+
function sha256Hex(data) {
|
|
9649
|
+
return createHash("sha256").update(data).digest("hex");
|
|
9650
|
+
}
|
|
9651
|
+
function sleepSync(ms) {
|
|
9652
|
+
if (isBun2) {
|
|
9653
|
+
bunGlobal().sleepSync(ms);
|
|
9654
|
+
return;
|
|
9655
|
+
}
|
|
9656
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
9657
|
+
}
|
|
9658
|
+
function bunGlobal() {
|
|
9659
|
+
return globalThis.Bun;
|
|
9660
|
+
}
|
|
9661
|
+
var isBun2, nodeRequire2, mainPath;
|
|
9662
|
+
var init_runtime = __esm(() => {
|
|
9663
|
+
isBun2 = !!process.versions?.bun;
|
|
9664
|
+
nodeRequire2 = createRequire2(import.meta.url);
|
|
9665
|
+
mainPath = isBun2 ? bunGlobal().main : process.argv[1];
|
|
9666
|
+
});
|
|
9667
|
+
|
|
9668
|
+
// src/indexer/search/search-fields.ts
|
|
9669
|
+
function buildSearchFields(entry) {
|
|
9670
|
+
const name = entry.name.replace(/[-_]/g, " ").toLowerCase();
|
|
9671
|
+
const description = (entry.description ?? "").toLowerCase();
|
|
9672
|
+
const tagParts = [];
|
|
9673
|
+
if (entry.tags)
|
|
9674
|
+
tagParts.push(entry.tags.join(" "));
|
|
9675
|
+
if (entry.aliases)
|
|
9676
|
+
tagParts.push(entry.aliases.join(" "));
|
|
9677
|
+
const tags = tagParts.join(" ").toLowerCase();
|
|
9678
|
+
const hintParts = [];
|
|
9679
|
+
if (entry.searchHints)
|
|
9680
|
+
hintParts.push(entry.searchHints.join(" "));
|
|
9681
|
+
if (entry.examples)
|
|
9682
|
+
hintParts.push(entry.examples.join(" "));
|
|
9683
|
+
if (entry.usage)
|
|
9684
|
+
hintParts.push(entry.usage.join(" "));
|
|
9685
|
+
if (entry.intent) {
|
|
9686
|
+
if (entry.intent.when)
|
|
9687
|
+
hintParts.push(entry.intent.when);
|
|
9688
|
+
if (entry.intent.input)
|
|
9689
|
+
hintParts.push(entry.intent.input);
|
|
9690
|
+
if (entry.intent.output)
|
|
9691
|
+
hintParts.push(entry.intent.output);
|
|
9692
|
+
}
|
|
9693
|
+
if (entry.xrefs)
|
|
9694
|
+
hintParts.push(entry.xrefs.join(" "));
|
|
9695
|
+
if (entry.pageKind)
|
|
9696
|
+
hintParts.push(entry.pageKind);
|
|
9697
|
+
if (entry.whenToUse)
|
|
9698
|
+
hintParts.push(entry.whenToUse);
|
|
9699
|
+
const hints = hintParts.join(" ").toLowerCase();
|
|
9700
|
+
const contentParts = [];
|
|
9701
|
+
if (entry.toc) {
|
|
9702
|
+
contentParts.push(entry.toc.map((h) => h.text).join(" "));
|
|
9703
|
+
}
|
|
9704
|
+
if (entry.parameters) {
|
|
9705
|
+
for (const param of entry.parameters) {
|
|
9706
|
+
contentParts.push(param.name);
|
|
9707
|
+
if (param.description)
|
|
9708
|
+
contentParts.push(param.description);
|
|
9709
|
+
}
|
|
9710
|
+
}
|
|
9711
|
+
const content = contentParts.join(" ").toLowerCase();
|
|
9712
|
+
return { name, description, tags, hints, content };
|
|
9713
|
+
}
|
|
9714
|
+
|
|
9715
|
+
// src/indexer/usage/usage-events.ts
|
|
9716
|
+
function ensureUsageEventsSchema(db) {
|
|
9717
|
+
db.exec(`
|
|
9718
|
+
CREATE TABLE IF NOT EXISTS usage_events (
|
|
9719
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
9720
|
+
event_type TEXT NOT NULL,
|
|
9721
|
+
query TEXT,
|
|
9722
|
+
entry_id INTEGER,
|
|
9723
|
+
entry_ref TEXT,
|
|
9724
|
+
signal TEXT,
|
|
9725
|
+
metadata TEXT,
|
|
9726
|
+
source TEXT NOT NULL DEFAULT 'user',
|
|
9727
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
9728
|
+
);
|
|
9729
|
+
CREATE INDEX IF NOT EXISTS idx_usage_events_entry ON usage_events(entry_id);
|
|
9730
|
+
CREATE INDEX IF NOT EXISTS idx_usage_events_type ON usage_events(event_type);
|
|
9731
|
+
CREATE INDEX IF NOT EXISTS idx_usage_events_ref ON usage_events(entry_ref);
|
|
9732
|
+
CREATE INDEX IF NOT EXISTS idx_usage_events_source ON usage_events(source);
|
|
9733
|
+
`);
|
|
9734
|
+
}
|
|
9735
|
+
|
|
9736
|
+
// src/indexer/db/db-backup.ts
|
|
9469
9737
|
import fs6 from "fs";
|
|
9470
9738
|
import path6 from "path";
|
|
9471
9739
|
function resolveRetention(env = process.env) {
|
|
@@ -9507,9 +9775,9 @@ function measureDataDirSize(dirPath) {
|
|
|
9507
9775
|
if (entry.isDirectory()) {
|
|
9508
9776
|
stack.push(full);
|
|
9509
9777
|
} else if (entry.isFile()) {
|
|
9510
|
-
|
|
9778
|
+
bestEffort(() => {
|
|
9511
9779
|
total += fs6.statSync(full).size;
|
|
9512
|
-
}
|
|
9780
|
+
}, "file vanished between readdir and stat");
|
|
9513
9781
|
}
|
|
9514
9782
|
}
|
|
9515
9783
|
}
|
|
@@ -9545,7 +9813,7 @@ function listBackups(dataDir) {
|
|
|
9545
9813
|
let sizeBytes;
|
|
9546
9814
|
let reason = DEFAULT_BACKUP_REASON;
|
|
9547
9815
|
if (fs6.existsSync(metaPath)) {
|
|
9548
|
-
|
|
9816
|
+
bestEffort(() => {
|
|
9549
9817
|
const raw = fs6.readFileSync(metaPath, "utf8");
|
|
9550
9818
|
const parsed = JSON.parse(raw);
|
|
9551
9819
|
if (typeof parsed.createdAt === "string")
|
|
@@ -9558,7 +9826,7 @@ function listBackups(dataDir) {
|
|
|
9558
9826
|
sizeBytes = parsed.sizeBytes;
|
|
9559
9827
|
if (typeof parsed.reason === "string" && parsed.reason.length > 0)
|
|
9560
9828
|
reason = parsed.reason;
|
|
9561
|
-
}
|
|
9829
|
+
}, "malformed backup metadata \u2014 fall back to filesystem-derived values");
|
|
9562
9830
|
}
|
|
9563
9831
|
if (!createdAt) {
|
|
9564
9832
|
try {
|
|
@@ -9639,9 +9907,7 @@ function backupDataDir(opts) {
|
|
|
9639
9907
|
copyDataDirExcludingBackups(dataDir, finalDest);
|
|
9640
9908
|
} catch (err) {
|
|
9641
9909
|
warn("[akm] data dir backup failed \u2014 %s; upgrade will proceed without a snapshot", err instanceof Error ? err.message : String(err));
|
|
9642
|
-
|
|
9643
|
-
fs6.rmSync(finalDest, { recursive: true, force: true });
|
|
9644
|
-
} catch {}
|
|
9910
|
+
bestEffort(() => fs6.rmSync(finalDest, { recursive: true, force: true }), "cleanup partial backup copy");
|
|
9645
9911
|
return null;
|
|
9646
9912
|
}
|
|
9647
9913
|
const createdAt = now.toISOString();
|
|
@@ -9697,9 +9963,7 @@ function copyDataDirExcludingBackups(srcRoot, destRoot) {
|
|
|
9697
9963
|
fs6.copyFileSync(srcPath, destPath);
|
|
9698
9964
|
} else if (entry.isSymbolicLink()) {
|
|
9699
9965
|
const target = fs6.readlinkSync(srcPath);
|
|
9700
|
-
|
|
9701
|
-
fs6.symlinkSync(target, destPath);
|
|
9702
|
-
} catch {}
|
|
9966
|
+
bestEffort(() => fs6.symlinkSync(target, destPath), "symlink creation can fail on Windows without admin");
|
|
9703
9967
|
}
|
|
9704
9968
|
}
|
|
9705
9969
|
}
|
|
@@ -9714,77 +9978,10 @@ function tryHostname() {
|
|
|
9714
9978
|
}
|
|
9715
9979
|
var DEFAULT_BACKUP_REASON = "version-upgrade", EMBEDDING_DIM_CHANGE_REASON = "embedding-dim-change", BACKUPS_DIR_NAME = "backups", BACKUP_METADATA_FILE = "backup.meta.json", DEFAULT_RETAIN = 5, FREE_SPACE_MULTIPLIER = 1.1;
|
|
9716
9980
|
var init_db_backup = __esm(() => {
|
|
9981
|
+
init_best_effort();
|
|
9717
9982
|
init_warn();
|
|
9718
9983
|
});
|
|
9719
9984
|
|
|
9720
|
-
// src/indexer/search-fields.ts
|
|
9721
|
-
function buildSearchFields(entry) {
|
|
9722
|
-
const name = entry.name.replace(/[-_]/g, " ").toLowerCase();
|
|
9723
|
-
const description = (entry.description ?? "").toLowerCase();
|
|
9724
|
-
const tagParts = [];
|
|
9725
|
-
if (entry.tags)
|
|
9726
|
-
tagParts.push(entry.tags.join(" "));
|
|
9727
|
-
if (entry.aliases)
|
|
9728
|
-
tagParts.push(entry.aliases.join(" "));
|
|
9729
|
-
const tags = tagParts.join(" ").toLowerCase();
|
|
9730
|
-
const hintParts = [];
|
|
9731
|
-
if (entry.searchHints)
|
|
9732
|
-
hintParts.push(entry.searchHints.join(" "));
|
|
9733
|
-
if (entry.examples)
|
|
9734
|
-
hintParts.push(entry.examples.join(" "));
|
|
9735
|
-
if (entry.usage)
|
|
9736
|
-
hintParts.push(entry.usage.join(" "));
|
|
9737
|
-
if (entry.intent) {
|
|
9738
|
-
if (entry.intent.when)
|
|
9739
|
-
hintParts.push(entry.intent.when);
|
|
9740
|
-
if (entry.intent.input)
|
|
9741
|
-
hintParts.push(entry.intent.input);
|
|
9742
|
-
if (entry.intent.output)
|
|
9743
|
-
hintParts.push(entry.intent.output);
|
|
9744
|
-
}
|
|
9745
|
-
if (entry.xrefs)
|
|
9746
|
-
hintParts.push(entry.xrefs.join(" "));
|
|
9747
|
-
if (entry.pageKind)
|
|
9748
|
-
hintParts.push(entry.pageKind);
|
|
9749
|
-
if (entry.whenToUse)
|
|
9750
|
-
hintParts.push(entry.whenToUse);
|
|
9751
|
-
const hints = hintParts.join(" ").toLowerCase();
|
|
9752
|
-
const contentParts = [];
|
|
9753
|
-
if (entry.toc) {
|
|
9754
|
-
contentParts.push(entry.toc.map((h) => h.text).join(" "));
|
|
9755
|
-
}
|
|
9756
|
-
if (entry.parameters) {
|
|
9757
|
-
for (const param of entry.parameters) {
|
|
9758
|
-
contentParts.push(param.name);
|
|
9759
|
-
if (param.description)
|
|
9760
|
-
contentParts.push(param.description);
|
|
9761
|
-
}
|
|
9762
|
-
}
|
|
9763
|
-
const content = contentParts.join(" ").toLowerCase();
|
|
9764
|
-
return { name, description, tags, hints, content };
|
|
9765
|
-
}
|
|
9766
|
-
|
|
9767
|
-
// src/indexer/usage-events.ts
|
|
9768
|
-
function ensureUsageEventsSchema(db) {
|
|
9769
|
-
db.exec(`
|
|
9770
|
-
CREATE TABLE IF NOT EXISTS usage_events (
|
|
9771
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
9772
|
-
event_type TEXT NOT NULL,
|
|
9773
|
-
query TEXT,
|
|
9774
|
-
entry_id INTEGER,
|
|
9775
|
-
entry_ref TEXT,
|
|
9776
|
-
signal TEXT,
|
|
9777
|
-
metadata TEXT,
|
|
9778
|
-
source TEXT NOT NULL DEFAULT 'user',
|
|
9779
|
-
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
9780
|
-
);
|
|
9781
|
-
CREATE INDEX IF NOT EXISTS idx_usage_events_entry ON usage_events(entry_id);
|
|
9782
|
-
CREATE INDEX IF NOT EXISTS idx_usage_events_type ON usage_events(event_type);
|
|
9783
|
-
CREATE INDEX IF NOT EXISTS idx_usage_events_ref ON usage_events(entry_ref);
|
|
9784
|
-
CREATE INDEX IF NOT EXISTS idx_usage_events_source ON usage_events(source);
|
|
9785
|
-
`);
|
|
9786
|
-
}
|
|
9787
|
-
|
|
9788
9985
|
// src/core/file-lock.ts
|
|
9789
9986
|
import fs7 from "fs";
|
|
9790
9987
|
function tryAcquireLockSync(lockPath, payload) {
|
|
@@ -9850,7 +10047,7 @@ var init_file_lock = __esm(() => {
|
|
|
9850
10047
|
init_common();
|
|
9851
10048
|
});
|
|
9852
10049
|
|
|
9853
|
-
// src/core/config-io.ts
|
|
10050
|
+
// src/core/config/config-io.ts
|
|
9854
10051
|
import fs8 from "fs";
|
|
9855
10052
|
import path7 from "path";
|
|
9856
10053
|
function parseConfigText(text, sourcePath) {
|
|
@@ -9891,9 +10088,12 @@ function backupExistingConfig(configPath) {
|
|
|
9891
10088
|
const backupDir = path7.join(getCacheDir(), "config-backups");
|
|
9892
10089
|
fs8.mkdirSync(backupDir, { recursive: true });
|
|
9893
10090
|
const timestamp = new Date().toISOString().replace(/[.:]/g, "-");
|
|
9894
|
-
|
|
9895
|
-
|
|
10091
|
+
const timestamped = path7.join(backupDir, `config-${timestamp}.json`);
|
|
10092
|
+
const latest = path7.join(backupDir, "config.latest.json");
|
|
10093
|
+
fs8.copyFileSync(configPath, timestamped);
|
|
10094
|
+
fs8.copyFileSync(configPath, latest);
|
|
9896
10095
|
pruneOldBackups2(backupDir);
|
|
10096
|
+
return { timestamped, latest };
|
|
9897
10097
|
}
|
|
9898
10098
|
function pruneOldBackups2(backupDir) {
|
|
9899
10099
|
let entries;
|
|
@@ -9919,6 +10119,9 @@ function pruneOldBackups2(backupDir) {
|
|
|
9919
10119
|
function getConfigLockPath() {
|
|
9920
10120
|
return path7.join(getConfigDir(), "config.json.lck");
|
|
9921
10121
|
}
|
|
10122
|
+
function sleepSyncMs(ms) {
|
|
10123
|
+
sleepSync(ms);
|
|
10124
|
+
}
|
|
9922
10125
|
function acquireConfigLock() {
|
|
9923
10126
|
const lockPath = getConfigLockPath();
|
|
9924
10127
|
try {
|
|
@@ -9937,8 +10140,7 @@ function acquireConfigLock() {
|
|
|
9937
10140
|
continue;
|
|
9938
10141
|
}
|
|
9939
10142
|
if (attempt < CONFIG_LOCK_MAX_RETRIES - 1) {
|
|
9940
|
-
|
|
9941
|
-
while (Date.now() < deadline) {}
|
|
10143
|
+
sleepSyncMs(CONFIG_LOCK_RETRY_DELAY_MS);
|
|
9942
10144
|
}
|
|
9943
10145
|
}
|
|
9944
10146
|
return () => {};
|
|
@@ -9991,17 +10193,802 @@ function stripJsonComments(text) {
|
|
|
9991
10193
|
result += text[i];
|
|
9992
10194
|
i++;
|
|
9993
10195
|
}
|
|
9994
|
-
return result;
|
|
10196
|
+
return result;
|
|
10197
|
+
}
|
|
10198
|
+
var MAX_CONFIG_BACKUPS = 5, CONFIG_LOCK_MAX_RETRIES = 10, CONFIG_LOCK_RETRY_DELAY_MS = 50;
|
|
10199
|
+
var init_config_io = __esm(() => {
|
|
10200
|
+
init_runtime();
|
|
10201
|
+
init_common();
|
|
10202
|
+
init_errors();
|
|
10203
|
+
init_file_lock();
|
|
10204
|
+
init_paths();
|
|
10205
|
+
});
|
|
10206
|
+
|
|
10207
|
+
// src/integrations/harnesses/types.ts
|
|
10208
|
+
class BaseHarness {
|
|
10209
|
+
runtimeId;
|
|
10210
|
+
setupDetectionDir;
|
|
10211
|
+
v1ProfilePrefixes = [];
|
|
10212
|
+
matchesV1ProfileName(name) {
|
|
10213
|
+
if (!this.capabilities.v1Migration)
|
|
10214
|
+
return false;
|
|
10215
|
+
const lower = name.trim().toLowerCase();
|
|
10216
|
+
if (!lower)
|
|
10217
|
+
return false;
|
|
10218
|
+
if (lower === this.id.toLowerCase())
|
|
10219
|
+
return true;
|
|
10220
|
+
for (const alias of this.aliases) {
|
|
10221
|
+
if (lower === alias.toLowerCase())
|
|
10222
|
+
return true;
|
|
10223
|
+
}
|
|
10224
|
+
for (const prefix of this.v1ProfilePrefixes) {
|
|
10225
|
+
if (lower.startsWith(prefix.toLowerCase()))
|
|
10226
|
+
return true;
|
|
10227
|
+
}
|
|
10228
|
+
return false;
|
|
10229
|
+
}
|
|
10230
|
+
}
|
|
10231
|
+
|
|
10232
|
+
// src/integrations/agent/builder-shared.ts
|
|
10233
|
+
var init_builder_shared = __esm(() => {
|
|
10234
|
+
init_errors();
|
|
10235
|
+
});
|
|
10236
|
+
|
|
10237
|
+
// src/integrations/agent/model-aliases.ts
|
|
10238
|
+
var init_model_aliases = () => {};
|
|
10239
|
+
|
|
10240
|
+
// src/integrations/harnesses/claude/agent-builder.ts
|
|
10241
|
+
var init_agent_builder = __esm(() => {
|
|
10242
|
+
init_builder_shared();
|
|
10243
|
+
init_model_aliases();
|
|
10244
|
+
});
|
|
10245
|
+
|
|
10246
|
+
// src/integrations/harnesses/claude/config-import.ts
|
|
10247
|
+
var init_config_import = () => {};
|
|
10248
|
+
|
|
10249
|
+
// src/integrations/session-logs/inline-refs.ts
|
|
10250
|
+
function extractInlineRefMentions(text, ts) {
|
|
10251
|
+
if (!text || text.length < 10)
|
|
10252
|
+
return [];
|
|
10253
|
+
const out = [];
|
|
10254
|
+
REMEMBER_RE.lastIndex = 0;
|
|
10255
|
+
for (const m of text.matchAll(REMEMBER_RE)) {
|
|
10256
|
+
const body = m[1] ?? m[2] ?? "";
|
|
10257
|
+
if (!body.trim())
|
|
10258
|
+
continue;
|
|
10259
|
+
out.push({
|
|
10260
|
+
kind: "remember",
|
|
10261
|
+
text: body,
|
|
10262
|
+
...ts !== undefined ? { ts } : {}
|
|
10263
|
+
});
|
|
10264
|
+
}
|
|
10265
|
+
FEEDBACK_RE.lastIndex = 0;
|
|
10266
|
+
for (const m of text.matchAll(FEEDBACK_RE)) {
|
|
10267
|
+
const ref = m[1] ?? "";
|
|
10268
|
+
const note = m[2] ?? m[3] ?? "";
|
|
10269
|
+
if (!ref)
|
|
10270
|
+
continue;
|
|
10271
|
+
out.push({
|
|
10272
|
+
kind: "feedback",
|
|
10273
|
+
ref,
|
|
10274
|
+
text: note,
|
|
10275
|
+
...ts !== undefined ? { ts } : {}
|
|
10276
|
+
});
|
|
10277
|
+
}
|
|
10278
|
+
return out;
|
|
10279
|
+
}
|
|
10280
|
+
var REMEMBER_RE, FEEDBACK_RE;
|
|
10281
|
+
var init_inline_refs = __esm(() => {
|
|
10282
|
+
REMEMBER_RE = /\bakm\s+remember\s+(?:"((?:[^"\\]|\\.)*)"|'((?:[^'\\]|\\.)*)')/g;
|
|
10283
|
+
FEEDBACK_RE = /\bakm\s+feedback\s+(\S+)(?:\s+--[a-z-]+)*\s+(?:--note|-n)\s+(?:"((?:[^"\\]|\\.)*)"|'((?:[^'\\]|\\.)*)')/g;
|
|
10284
|
+
});
|
|
10285
|
+
|
|
10286
|
+
// src/integrations/harnesses/claude/session-log.ts
|
|
10287
|
+
import fs9 from "fs";
|
|
10288
|
+
import os from "os";
|
|
10289
|
+
import path8 from "path";
|
|
10290
|
+
function claudeProjectsDir() {
|
|
10291
|
+
return process.env.AKM_CLAUDE_PROJECTS_DIR ?? path8.join(os.homedir(), ".claude", "projects");
|
|
10292
|
+
}
|
|
10293
|
+
function parseClaudeEvent(entry, sessionId, filePath, fallbackTsMs) {
|
|
10294
|
+
if (!entry || typeof entry !== "object")
|
|
10295
|
+
return;
|
|
10296
|
+
const e = entry;
|
|
10297
|
+
const tsRaw = e.timestamp;
|
|
10298
|
+
const ts = typeof tsRaw === "number" ? tsRaw : typeof tsRaw === "string" ? Date.parse(tsRaw) || fallbackTsMs : fallbackTsMs;
|
|
10299
|
+
const message = e.message ?? undefined;
|
|
10300
|
+
const role = typeof message?.role === "string" ? message.role : e.type ?? "unknown";
|
|
10301
|
+
const content = message?.content;
|
|
10302
|
+
let text = "";
|
|
10303
|
+
if (typeof content === "string") {
|
|
10304
|
+
text = content;
|
|
10305
|
+
} else if (Array.isArray(content)) {
|
|
10306
|
+
const parts = [];
|
|
10307
|
+
for (const block of content) {
|
|
10308
|
+
if (!block || typeof block !== "object")
|
|
10309
|
+
continue;
|
|
10310
|
+
const b = block;
|
|
10311
|
+
if (b.type === "text" && typeof b.text === "string")
|
|
10312
|
+
parts.push(b.text);
|
|
10313
|
+
else if (b.type === "thinking" && typeof b.thinking === "string")
|
|
10314
|
+
parts.push(b.thinking);
|
|
10315
|
+
else if (b.type === "tool_use") {
|
|
10316
|
+
const toolName = typeof b.name === "string" ? b.name : "tool";
|
|
10317
|
+
const inputObj = b.input;
|
|
10318
|
+
let inputText = "";
|
|
10319
|
+
if (inputObj && typeof inputObj === "object") {
|
|
10320
|
+
const cmd = inputObj.command;
|
|
10321
|
+
inputText = typeof cmd === "string" ? cmd : JSON.stringify(inputObj);
|
|
10322
|
+
} else if (typeof inputObj === "string") {
|
|
10323
|
+
inputText = inputObj;
|
|
10324
|
+
}
|
|
10325
|
+
parts.push(`[tool:${toolName}] ${inputText}`);
|
|
10326
|
+
} else if (b.type === "tool_result") {
|
|
10327
|
+
const out = typeof b.content === "string" ? b.content : JSON.stringify(b.content ?? "");
|
|
10328
|
+
parts.push(`[tool_result] ${out}`);
|
|
10329
|
+
}
|
|
10330
|
+
}
|
|
10331
|
+
text = parts.join(`
|
|
10332
|
+
`);
|
|
10333
|
+
}
|
|
10334
|
+
if (!text || text.length < 1)
|
|
10335
|
+
return;
|
|
10336
|
+
return {
|
|
10337
|
+
harness: "claude-code",
|
|
10338
|
+
text,
|
|
10339
|
+
ts,
|
|
10340
|
+
sessionId,
|
|
10341
|
+
role,
|
|
10342
|
+
filePath
|
|
10343
|
+
};
|
|
10344
|
+
}
|
|
10345
|
+
|
|
10346
|
+
class ClaudeCodeProvider {
|
|
10347
|
+
name = "claude-code";
|
|
10348
|
+
isAvailable() {
|
|
10349
|
+
return fs9.existsSync(claudeProjectsDir());
|
|
10350
|
+
}
|
|
10351
|
+
*readEvents(input) {
|
|
10352
|
+
try {
|
|
10353
|
+
for (const jsonlPath of this.#walkJsonl(claudeProjectsDir())) {
|
|
10354
|
+
const stat = fs9.statSync(jsonlPath);
|
|
10355
|
+
if (stat.mtimeMs < input.sinceMs)
|
|
10356
|
+
continue;
|
|
10357
|
+
const lines = fs9.readFileSync(jsonlPath, "utf8").split(`
|
|
10358
|
+
`).filter(Boolean);
|
|
10359
|
+
for (const line of lines) {
|
|
10360
|
+
try {
|
|
10361
|
+
const entry = JSON.parse(line);
|
|
10362
|
+
const text = entry?.message?.content ?? entry?.content ?? "";
|
|
10363
|
+
if (typeof text !== "string" || text.length < 10)
|
|
10364
|
+
continue;
|
|
10365
|
+
yield {
|
|
10366
|
+
harness: this.name,
|
|
10367
|
+
text,
|
|
10368
|
+
ts: typeof entry?.timestamp === "number" ? entry.timestamp : stat.mtimeMs,
|
|
10369
|
+
sessionId: typeof entry?.session_id === "string" ? entry.session_id : undefined,
|
|
10370
|
+
role: typeof entry?.role === "string" ? entry.role : "unknown",
|
|
10371
|
+
filePath: jsonlPath
|
|
10372
|
+
};
|
|
10373
|
+
} catch {}
|
|
10374
|
+
}
|
|
10375
|
+
}
|
|
10376
|
+
} catch {
|
|
10377
|
+
return;
|
|
10378
|
+
}
|
|
10379
|
+
}
|
|
10380
|
+
listSessions(input = {}) {
|
|
10381
|
+
const root = input.location ?? claudeProjectsDir();
|
|
10382
|
+
const sinceMs = input.sinceMs ?? 0;
|
|
10383
|
+
const summaries = [];
|
|
10384
|
+
try {
|
|
10385
|
+
for (const jsonlPath of this.#walkJsonl(root)) {
|
|
10386
|
+
let stat;
|
|
10387
|
+
try {
|
|
10388
|
+
stat = fs9.statSync(jsonlPath);
|
|
10389
|
+
} catch {
|
|
10390
|
+
continue;
|
|
10391
|
+
}
|
|
10392
|
+
if (stat.mtimeMs < sinceMs)
|
|
10393
|
+
continue;
|
|
10394
|
+
const sessionId = path8.basename(jsonlPath, ".jsonl");
|
|
10395
|
+
const projectHint = path8.basename(path8.dirname(jsonlPath));
|
|
10396
|
+
const peek = this.#peekJsonl(jsonlPath);
|
|
10397
|
+
summaries.push({
|
|
10398
|
+
harness: this.name,
|
|
10399
|
+
sessionId,
|
|
10400
|
+
filePath: jsonlPath,
|
|
10401
|
+
startedAt: peek.firstTsMs ?? stat.ctimeMs,
|
|
10402
|
+
endedAt: peek.lastTsMs ?? stat.mtimeMs,
|
|
10403
|
+
projectHint,
|
|
10404
|
+
...peek.title ? { title: peek.title } : {}
|
|
10405
|
+
});
|
|
10406
|
+
}
|
|
10407
|
+
} catch {}
|
|
10408
|
+
return summaries.sort((a, b) => (b.endedAt ?? 0) - (a.endedAt ?? 0));
|
|
10409
|
+
}
|
|
10410
|
+
readSession(ref) {
|
|
10411
|
+
const stat = fs9.statSync(ref.filePath);
|
|
10412
|
+
const lines = fs9.readFileSync(ref.filePath, "utf8").split(`
|
|
10413
|
+
`).filter(Boolean);
|
|
10414
|
+
const events = [];
|
|
10415
|
+
const inlineRefs = [];
|
|
10416
|
+
let title;
|
|
10417
|
+
let firstTsMs;
|
|
10418
|
+
let lastTsMs;
|
|
10419
|
+
const projectHint = path8.basename(path8.dirname(ref.filePath));
|
|
10420
|
+
for (const line of lines) {
|
|
10421
|
+
let entry;
|
|
10422
|
+
try {
|
|
10423
|
+
entry = JSON.parse(line);
|
|
10424
|
+
} catch {
|
|
10425
|
+
continue;
|
|
10426
|
+
}
|
|
10427
|
+
if (!entry)
|
|
10428
|
+
continue;
|
|
10429
|
+
if (entry.type === "custom-title" && typeof entry.customTitle === "string") {
|
|
10430
|
+
title = entry.customTitle;
|
|
10431
|
+
continue;
|
|
10432
|
+
}
|
|
10433
|
+
const parsed = parseClaudeEvent(entry, ref.sessionId, ref.filePath, stat.mtimeMs);
|
|
10434
|
+
if (!parsed)
|
|
10435
|
+
continue;
|
|
10436
|
+
events.push(parsed);
|
|
10437
|
+
if (firstTsMs === undefined || (parsed.ts ?? 0) < firstTsMs)
|
|
10438
|
+
firstTsMs = parsed.ts;
|
|
10439
|
+
if (lastTsMs === undefined || (parsed.ts ?? 0) > lastTsMs)
|
|
10440
|
+
lastTsMs = parsed.ts;
|
|
10441
|
+
inlineRefs.push(...extractInlineRefMentions(parsed.text, parsed.ts));
|
|
10442
|
+
}
|
|
10443
|
+
return {
|
|
10444
|
+
ref: {
|
|
10445
|
+
harness: this.name,
|
|
10446
|
+
sessionId: ref.sessionId,
|
|
10447
|
+
filePath: ref.filePath,
|
|
10448
|
+
startedAt: firstTsMs ?? stat.ctimeMs,
|
|
10449
|
+
endedAt: lastTsMs ?? stat.mtimeMs,
|
|
10450
|
+
projectHint,
|
|
10451
|
+
...title ? { title } : {}
|
|
10452
|
+
},
|
|
10453
|
+
events,
|
|
10454
|
+
inlineRefs
|
|
10455
|
+
};
|
|
10456
|
+
}
|
|
10457
|
+
#peekJsonl(filePath) {
|
|
10458
|
+
const result = {};
|
|
10459
|
+
try {
|
|
10460
|
+
const fd = fs9.openSync(filePath, "r");
|
|
10461
|
+
try {
|
|
10462
|
+
const stat = fs9.fstatSync(fd);
|
|
10463
|
+
const headSize = Math.min(stat.size, 4096);
|
|
10464
|
+
const head = Buffer.alloc(headSize);
|
|
10465
|
+
fs9.readSync(fd, head, 0, headSize, 0);
|
|
10466
|
+
const headLines = head.toString("utf8").split(`
|
|
10467
|
+
`).filter(Boolean);
|
|
10468
|
+
for (const line of headLines) {
|
|
10469
|
+
try {
|
|
10470
|
+
const e = JSON.parse(line);
|
|
10471
|
+
if (e.type === "custom-title" && typeof e.customTitle === "string") {
|
|
10472
|
+
result.title = e.customTitle;
|
|
10473
|
+
}
|
|
10474
|
+
if (typeof e.timestamp === "string") {
|
|
10475
|
+
const t = Date.parse(e.timestamp);
|
|
10476
|
+
if (!Number.isNaN(t)) {
|
|
10477
|
+
if (result.firstTsMs === undefined)
|
|
10478
|
+
result.firstTsMs = t;
|
|
10479
|
+
result.lastTsMs = t;
|
|
10480
|
+
}
|
|
10481
|
+
}
|
|
10482
|
+
} catch {}
|
|
10483
|
+
}
|
|
10484
|
+
if (stat.size > 4096) {
|
|
10485
|
+
const tailSize = Math.min(stat.size, 4096);
|
|
10486
|
+
const tail = Buffer.alloc(tailSize);
|
|
10487
|
+
fs9.readSync(fd, tail, 0, tailSize, stat.size - tailSize);
|
|
10488
|
+
const tailLines = tail.toString("utf8").split(`
|
|
10489
|
+
`).filter(Boolean);
|
|
10490
|
+
for (let i = tailLines.length - 1;i >= 0; i--) {
|
|
10491
|
+
try {
|
|
10492
|
+
const e = JSON.parse(tailLines[i] ?? "");
|
|
10493
|
+
if (typeof e.timestamp === "string") {
|
|
10494
|
+
const t = Date.parse(e.timestamp);
|
|
10495
|
+
if (!Number.isNaN(t)) {
|
|
10496
|
+
result.lastTsMs = t;
|
|
10497
|
+
break;
|
|
10498
|
+
}
|
|
10499
|
+
}
|
|
10500
|
+
} catch {}
|
|
10501
|
+
}
|
|
10502
|
+
}
|
|
10503
|
+
} finally {
|
|
10504
|
+
fs9.closeSync(fd);
|
|
10505
|
+
}
|
|
10506
|
+
} catch {}
|
|
10507
|
+
return result;
|
|
10508
|
+
}
|
|
10509
|
+
*#walkJsonl(dir) {
|
|
10510
|
+
try {
|
|
10511
|
+
for (const entry of fs9.readdirSync(dir, { withFileTypes: true })) {
|
|
10512
|
+
const full = path8.join(dir, entry.name);
|
|
10513
|
+
if (entry.isDirectory())
|
|
10514
|
+
yield* this.#walkJsonl(full);
|
|
10515
|
+
else if (entry.name.endsWith(".jsonl"))
|
|
10516
|
+
yield full;
|
|
10517
|
+
}
|
|
10518
|
+
} catch {}
|
|
10519
|
+
}
|
|
10520
|
+
}
|
|
10521
|
+
var init_session_log = __esm(() => {
|
|
10522
|
+
init_inline_refs();
|
|
10523
|
+
});
|
|
10524
|
+
|
|
10525
|
+
// src/integrations/harnesses/claude/index.ts
|
|
10526
|
+
function caps(c) {
|
|
10527
|
+
return {
|
|
10528
|
+
sessionLogs: false,
|
|
10529
|
+
agentDispatch: false,
|
|
10530
|
+
detection: false,
|
|
10531
|
+
configImport: false,
|
|
10532
|
+
runtimeIdentity: false,
|
|
10533
|
+
v1Migration: false,
|
|
10534
|
+
...c
|
|
10535
|
+
};
|
|
10536
|
+
}
|
|
10537
|
+
var ClaudeHarness;
|
|
10538
|
+
var init_claude = __esm(() => {
|
|
10539
|
+
init_agent_builder();
|
|
10540
|
+
init_config_import();
|
|
10541
|
+
init_session_log();
|
|
10542
|
+
ClaudeHarness = class ClaudeHarness extends BaseHarness {
|
|
10543
|
+
id = "claude";
|
|
10544
|
+
displayName = "Claude Code";
|
|
10545
|
+
aliases = ["claude-code"];
|
|
10546
|
+
runtimeId = "claude-code";
|
|
10547
|
+
setupDetectionDir = ".claude";
|
|
10548
|
+
capabilities = caps({
|
|
10549
|
+
sessionLogs: true,
|
|
10550
|
+
agentDispatch: true,
|
|
10551
|
+
detection: true,
|
|
10552
|
+
configImport: true,
|
|
10553
|
+
runtimeIdentity: true,
|
|
10554
|
+
v1Migration: true
|
|
10555
|
+
});
|
|
10556
|
+
};
|
|
10557
|
+
});
|
|
10558
|
+
|
|
10559
|
+
// src/integrations/harnesses/opencode/agent-builder.ts
|
|
10560
|
+
var init_agent_builder2 = __esm(() => {
|
|
10561
|
+
init_builder_shared();
|
|
10562
|
+
init_model_aliases();
|
|
10563
|
+
});
|
|
10564
|
+
|
|
10565
|
+
// src/integrations/harnesses/opencode/config-import.ts
|
|
10566
|
+
var init_config_import2 = () => {};
|
|
10567
|
+
|
|
10568
|
+
// src/integrations/harnesses/opencode/session-log.ts
|
|
10569
|
+
import fs10 from "fs";
|
|
10570
|
+
import os2 from "os";
|
|
10571
|
+
import path9 from "path";
|
|
10572
|
+
function getOpenCodeBaseDir() {
|
|
10573
|
+
if (process.platform === "darwin") {
|
|
10574
|
+
return path9.join(os2.homedir(), "Library", "Application Support", "opencode");
|
|
10575
|
+
}
|
|
10576
|
+
return path9.join(os2.homedir(), ".local", "share", "opencode");
|
|
10577
|
+
}
|
|
10578
|
+
|
|
10579
|
+
class OpenCodeProvider {
|
|
10580
|
+
name = "opencode";
|
|
10581
|
+
#baseDir = getOpenCodeBaseDir();
|
|
10582
|
+
isAvailable() {
|
|
10583
|
+
return fs10.existsSync(this.#baseDir);
|
|
10584
|
+
}
|
|
10585
|
+
*readEvents(input) {
|
|
10586
|
+
const candidates = [this.#baseDir, path9.join(this.#baseDir, "log")];
|
|
10587
|
+
for (const dir of candidates) {
|
|
10588
|
+
if (!fs10.existsSync(dir))
|
|
10589
|
+
continue;
|
|
10590
|
+
try {
|
|
10591
|
+
for (const file of fs10.readdirSync(dir)) {
|
|
10592
|
+
const full = path9.join(dir, file);
|
|
10593
|
+
let stat;
|
|
10594
|
+
try {
|
|
10595
|
+
stat = fs10.statSync(full);
|
|
10596
|
+
} catch {
|
|
10597
|
+
continue;
|
|
10598
|
+
}
|
|
10599
|
+
if (!stat.isFile())
|
|
10600
|
+
continue;
|
|
10601
|
+
if (stat.mtimeMs < input.sinceMs)
|
|
10602
|
+
continue;
|
|
10603
|
+
if (!file.endsWith(".json") && !file.endsWith(".jsonl") && !file.endsWith(".log"))
|
|
10604
|
+
continue;
|
|
10605
|
+
const content = fs10.readFileSync(full, "utf8");
|
|
10606
|
+
const lines = content.includes(`
|
|
10607
|
+
`) ? content.split(`
|
|
10608
|
+
`) : [content];
|
|
10609
|
+
for (const line of lines) {
|
|
10610
|
+
try {
|
|
10611
|
+
const entry = JSON.parse(line);
|
|
10612
|
+
const text = entry?.content ?? entry?.message ?? entry?.text ?? "";
|
|
10613
|
+
if (typeof text !== "string" || text.length < 10)
|
|
10614
|
+
continue;
|
|
10615
|
+
yield {
|
|
10616
|
+
harness: this.name,
|
|
10617
|
+
text,
|
|
10618
|
+
ts: typeof entry?.timestamp === "number" ? entry.timestamp : stat.mtimeMs,
|
|
10619
|
+
sessionId: typeof entry?.sessionId === "string" ? entry.sessionId : undefined,
|
|
10620
|
+
role: typeof entry?.role === "string" ? entry.role : "unknown",
|
|
10621
|
+
filePath: full
|
|
10622
|
+
};
|
|
10623
|
+
} catch {}
|
|
10624
|
+
}
|
|
10625
|
+
}
|
|
10626
|
+
} catch {}
|
|
10627
|
+
}
|
|
10628
|
+
}
|
|
10629
|
+
listSessions(input = {}) {
|
|
10630
|
+
const base = input.location ?? this.#baseDir;
|
|
10631
|
+
const sinceMs = input.sinceMs ?? 0;
|
|
10632
|
+
const sessionRoot = path9.join(base, "storage", "session");
|
|
10633
|
+
if (!fs10.existsSync(sessionRoot))
|
|
10634
|
+
return [];
|
|
10635
|
+
const summaries = [];
|
|
10636
|
+
try {
|
|
10637
|
+
for (const projectId of fs10.readdirSync(sessionRoot)) {
|
|
10638
|
+
const projectDir = path9.join(sessionRoot, projectId);
|
|
10639
|
+
let pstat;
|
|
10640
|
+
try {
|
|
10641
|
+
pstat = fs10.statSync(projectDir);
|
|
10642
|
+
} catch {
|
|
10643
|
+
continue;
|
|
10644
|
+
}
|
|
10645
|
+
if (!pstat.isDirectory())
|
|
10646
|
+
continue;
|
|
10647
|
+
for (const file of fs10.readdirSync(projectDir)) {
|
|
10648
|
+
if (!file.endsWith(".json"))
|
|
10649
|
+
continue;
|
|
10650
|
+
const filePath = path9.join(projectDir, file);
|
|
10651
|
+
let stat;
|
|
10652
|
+
try {
|
|
10653
|
+
stat = fs10.statSync(filePath);
|
|
10654
|
+
} catch {
|
|
10655
|
+
continue;
|
|
10656
|
+
}
|
|
10657
|
+
if (stat.mtimeMs < sinceMs)
|
|
10658
|
+
continue;
|
|
10659
|
+
let meta;
|
|
10660
|
+
try {
|
|
10661
|
+
meta = JSON.parse(fs10.readFileSync(filePath, "utf8"));
|
|
10662
|
+
} catch {
|
|
10663
|
+
continue;
|
|
10664
|
+
}
|
|
10665
|
+
const sessionId = typeof meta?.id === "string" ? meta.id : path9.basename(file, ".json");
|
|
10666
|
+
const time = meta?.time ?? undefined;
|
|
10667
|
+
const startedAt = typeof time?.created === "number" ? time.created : stat.ctimeMs;
|
|
10668
|
+
const endedAt = typeof time?.updated === "number" ? time.updated : stat.mtimeMs;
|
|
10669
|
+
const title = typeof meta?.title === "string" ? meta.title : undefined;
|
|
10670
|
+
const projectHint = typeof meta?.directory === "string" ? meta.directory : projectId;
|
|
10671
|
+
summaries.push({
|
|
10672
|
+
harness: this.name,
|
|
10673
|
+
sessionId,
|
|
10674
|
+
filePath,
|
|
10675
|
+
startedAt,
|
|
10676
|
+
endedAt,
|
|
10677
|
+
projectHint,
|
|
10678
|
+
...title ? { title } : {}
|
|
10679
|
+
});
|
|
10680
|
+
}
|
|
10681
|
+
}
|
|
10682
|
+
} catch {}
|
|
10683
|
+
return summaries.sort((a, b) => (b.endedAt ?? 0) - (a.endedAt ?? 0));
|
|
10684
|
+
}
|
|
10685
|
+
readSession(ref) {
|
|
10686
|
+
let meta = {};
|
|
10687
|
+
try {
|
|
10688
|
+
meta = JSON.parse(fs10.readFileSync(ref.filePath, "utf8"));
|
|
10689
|
+
} catch {}
|
|
10690
|
+
const time = meta.time ?? undefined;
|
|
10691
|
+
const startedAt = typeof time?.created === "number" ? time.created : undefined;
|
|
10692
|
+
const endedAt = typeof time?.updated === "number" ? time.updated : undefined;
|
|
10693
|
+
const title = typeof meta.title === "string" ? meta.title : undefined;
|
|
10694
|
+
const projectHint = typeof meta.directory === "string" ? meta.directory : undefined;
|
|
10695
|
+
const events = [];
|
|
10696
|
+
const inlineRefs = [];
|
|
10697
|
+
const inferredBase = this.#inferBaseFromSessionPath(ref.filePath) ?? this.#baseDir;
|
|
10698
|
+
const msgDir = path9.join(inferredBase, "storage", "message", ref.sessionId);
|
|
10699
|
+
if (fs10.existsSync(msgDir)) {
|
|
10700
|
+
try {
|
|
10701
|
+
const files = fs10.readdirSync(msgDir).filter((f) => f.endsWith(".json"));
|
|
10702
|
+
for (const file of files) {
|
|
10703
|
+
const full = path9.join(msgDir, file);
|
|
10704
|
+
let msg;
|
|
10705
|
+
try {
|
|
10706
|
+
msg = JSON.parse(fs10.readFileSync(full, "utf8"));
|
|
10707
|
+
} catch {
|
|
10708
|
+
continue;
|
|
10709
|
+
}
|
|
10710
|
+
if (!msg)
|
|
10711
|
+
continue;
|
|
10712
|
+
const evt = this.#messageToEvent(msg, ref.sessionId, full);
|
|
10713
|
+
if (evt) {
|
|
10714
|
+
events.push(evt);
|
|
10715
|
+
inlineRefs.push(...extractInlineRefMentions(evt.text, evt.ts));
|
|
10716
|
+
}
|
|
10717
|
+
}
|
|
10718
|
+
} catch {}
|
|
10719
|
+
}
|
|
10720
|
+
events.sort((a, b) => (a.ts ?? 0) - (b.ts ?? 0));
|
|
10721
|
+
return {
|
|
10722
|
+
ref: {
|
|
10723
|
+
harness: this.name,
|
|
10724
|
+
sessionId: ref.sessionId,
|
|
10725
|
+
filePath: ref.filePath,
|
|
10726
|
+
...startedAt !== undefined ? { startedAt } : {},
|
|
10727
|
+
...endedAt !== undefined ? { endedAt } : {},
|
|
10728
|
+
...projectHint ? { projectHint } : {},
|
|
10729
|
+
...title ? { title } : {}
|
|
10730
|
+
},
|
|
10731
|
+
events,
|
|
10732
|
+
inlineRefs
|
|
10733
|
+
};
|
|
10734
|
+
}
|
|
10735
|
+
#inferBaseFromSessionPath(filePath) {
|
|
10736
|
+
const dir = path9.dirname(filePath);
|
|
10737
|
+
const parts = dir.split(path9.sep);
|
|
10738
|
+
if (parts.length < 3)
|
|
10739
|
+
return;
|
|
10740
|
+
const last = parts[parts.length - 1];
|
|
10741
|
+
const sndLast = parts[parts.length - 2];
|
|
10742
|
+
const thirdLast = parts[parts.length - 3];
|
|
10743
|
+
if (sndLast !== "session" || thirdLast !== "storage" || !last)
|
|
10744
|
+
return;
|
|
10745
|
+
return parts.slice(0, parts.length - 3).join(path9.sep);
|
|
10746
|
+
}
|
|
10747
|
+
#messageToEvent(msg, sessionId, filePath) {
|
|
10748
|
+
const time = msg.time ?? undefined;
|
|
10749
|
+
const ts = typeof time?.created === "number" ? time.created : typeof msg.timestamp === "number" ? msg.timestamp : 0;
|
|
10750
|
+
const role = typeof msg.role === "string" ? msg.role : "unknown";
|
|
10751
|
+
const summary = msg.summary;
|
|
10752
|
+
const parts = [];
|
|
10753
|
+
if (typeof summary?.title === "string")
|
|
10754
|
+
parts.push(summary.title);
|
|
10755
|
+
if (Array.isArray(summary?.parts)) {
|
|
10756
|
+
for (const p of summary.parts) {
|
|
10757
|
+
if (typeof p === "string")
|
|
10758
|
+
parts.push(p);
|
|
10759
|
+
else if (p && typeof p === "object") {
|
|
10760
|
+
const text2 = p.text;
|
|
10761
|
+
if (typeof text2 === "string")
|
|
10762
|
+
parts.push(text2);
|
|
10763
|
+
}
|
|
10764
|
+
}
|
|
10765
|
+
}
|
|
10766
|
+
if (typeof msg.content === "string")
|
|
10767
|
+
parts.push(msg.content);
|
|
10768
|
+
const text = parts.join(`
|
|
10769
|
+
`).trim();
|
|
10770
|
+
if (text.length < 1)
|
|
10771
|
+
return;
|
|
10772
|
+
return {
|
|
10773
|
+
harness: this.name,
|
|
10774
|
+
text,
|
|
10775
|
+
ts: ts || undefined,
|
|
10776
|
+
sessionId,
|
|
10777
|
+
role,
|
|
10778
|
+
filePath
|
|
10779
|
+
};
|
|
10780
|
+
}
|
|
10781
|
+
}
|
|
10782
|
+
var init_session_log2 = __esm(() => {
|
|
10783
|
+
init_inline_refs();
|
|
10784
|
+
});
|
|
10785
|
+
|
|
10786
|
+
// src/integrations/harnesses/opencode/index.ts
|
|
10787
|
+
function caps2(c) {
|
|
10788
|
+
return {
|
|
10789
|
+
sessionLogs: false,
|
|
10790
|
+
agentDispatch: false,
|
|
10791
|
+
detection: false,
|
|
10792
|
+
configImport: false,
|
|
10793
|
+
runtimeIdentity: false,
|
|
10794
|
+
v1Migration: false,
|
|
10795
|
+
...c
|
|
10796
|
+
};
|
|
10797
|
+
}
|
|
10798
|
+
var OpencodeHarness;
|
|
10799
|
+
var init_opencode = __esm(() => {
|
|
10800
|
+
init_agent_builder2();
|
|
10801
|
+
init_config_import2();
|
|
10802
|
+
init_session_log2();
|
|
10803
|
+
OpencodeHarness = class OpencodeHarness extends BaseHarness {
|
|
10804
|
+
id = "opencode";
|
|
10805
|
+
displayName = "OpenCode";
|
|
10806
|
+
aliases = [];
|
|
10807
|
+
setupDetectionDir = ".config/opencode";
|
|
10808
|
+
v1ProfilePrefixes = ["opencode"];
|
|
10809
|
+
capabilities = caps2({
|
|
10810
|
+
sessionLogs: true,
|
|
10811
|
+
agentDispatch: true,
|
|
10812
|
+
detection: true,
|
|
10813
|
+
configImport: true,
|
|
10814
|
+
runtimeIdentity: true,
|
|
10815
|
+
v1Migration: true
|
|
10816
|
+
});
|
|
10817
|
+
};
|
|
10818
|
+
});
|
|
10819
|
+
|
|
10820
|
+
// src/integrations/agent/profiles.ts
|
|
10821
|
+
var COMMON_PASSTHROUGH, BUILTINS, HEADLESS_BUILTINS, BUILTIN_AGENT_PROFILE_NAMES;
|
|
10822
|
+
var init_profiles = __esm(() => {
|
|
10823
|
+
COMMON_PASSTHROUGH = ["HOME", "PATH", "USER", "LANG", "LC_ALL", "TERM", "TMPDIR"];
|
|
10824
|
+
BUILTINS = {
|
|
10825
|
+
opencode: {
|
|
10826
|
+
name: "opencode",
|
|
10827
|
+
bin: "opencode",
|
|
10828
|
+
args: ["run"],
|
|
10829
|
+
stdio: "interactive",
|
|
10830
|
+
envPassthrough: [...COMMON_PASSTHROUGH, "OPENCODE_API_KEY", "OPENCODE_CONFIG"],
|
|
10831
|
+
parseOutput: "text"
|
|
10832
|
+
},
|
|
10833
|
+
claude: {
|
|
10834
|
+
name: "claude",
|
|
10835
|
+
bin: "claude",
|
|
10836
|
+
args: [],
|
|
10837
|
+
stdio: "interactive",
|
|
10838
|
+
envPassthrough: [...COMMON_PASSTHROUGH, "ANTHROPIC_API_KEY", "CLAUDE_CONFIG"],
|
|
10839
|
+
parseOutput: "text"
|
|
10840
|
+
},
|
|
10841
|
+
codex: {
|
|
10842
|
+
name: "codex",
|
|
10843
|
+
bin: "codex",
|
|
10844
|
+
args: [],
|
|
10845
|
+
stdio: "interactive",
|
|
10846
|
+
envPassthrough: [...COMMON_PASSTHROUGH, "OPENAI_API_KEY", "CODEX_CONFIG"],
|
|
10847
|
+
parseOutput: "text"
|
|
10848
|
+
},
|
|
10849
|
+
gemini: {
|
|
10850
|
+
name: "gemini",
|
|
10851
|
+
bin: "gemini",
|
|
10852
|
+
args: [],
|
|
10853
|
+
stdio: "interactive",
|
|
10854
|
+
envPassthrough: [...COMMON_PASSTHROUGH, "GEMINI_API_KEY", "GOOGLE_API_KEY"],
|
|
10855
|
+
parseOutput: "text"
|
|
10856
|
+
},
|
|
10857
|
+
aider: {
|
|
10858
|
+
name: "aider",
|
|
10859
|
+
bin: "aider",
|
|
10860
|
+
args: ["--no-auto-commits"],
|
|
10861
|
+
stdio: "interactive",
|
|
10862
|
+
envPassthrough: [...COMMON_PASSTHROUGH, "OPENAI_API_KEY", "ANTHROPIC_API_KEY"],
|
|
10863
|
+
parseOutput: "text"
|
|
10864
|
+
}
|
|
10865
|
+
};
|
|
10866
|
+
HEADLESS_BUILTINS = {
|
|
10867
|
+
"opencode-headless": {
|
|
10868
|
+
name: "opencode-headless",
|
|
10869
|
+
bin: "opencode",
|
|
10870
|
+
args: ["run"],
|
|
10871
|
+
stdio: "captured",
|
|
10872
|
+
envPassthrough: [...COMMON_PASSTHROUGH, "OPENCODE_API_KEY", "OPENCODE_CONFIG"],
|
|
10873
|
+
parseOutput: "json"
|
|
10874
|
+
},
|
|
10875
|
+
"claude-headless": {
|
|
10876
|
+
name: "claude-headless",
|
|
10877
|
+
bin: "claude",
|
|
10878
|
+
args: [],
|
|
10879
|
+
stdio: "captured",
|
|
10880
|
+
envPassthrough: [...COMMON_PASSTHROUGH, "ANTHROPIC_API_KEY", "CLAUDE_CONFIG"],
|
|
10881
|
+
parseOutput: "json"
|
|
10882
|
+
},
|
|
10883
|
+
"codex-headless": {
|
|
10884
|
+
name: "codex-headless",
|
|
10885
|
+
bin: "codex",
|
|
10886
|
+
args: [],
|
|
10887
|
+
stdio: "captured",
|
|
10888
|
+
envPassthrough: [...COMMON_PASSTHROUGH, "OPENAI_API_KEY", "CODEX_CONFIG"],
|
|
10889
|
+
parseOutput: "json"
|
|
10890
|
+
},
|
|
10891
|
+
"gemini-headless": {
|
|
10892
|
+
name: "gemini-headless",
|
|
10893
|
+
bin: "gemini",
|
|
10894
|
+
args: [],
|
|
10895
|
+
stdio: "captured",
|
|
10896
|
+
envPassthrough: [...COMMON_PASSTHROUGH, "GEMINI_API_KEY", "GOOGLE_API_KEY"],
|
|
10897
|
+
parseOutput: "json"
|
|
10898
|
+
},
|
|
10899
|
+
"aider-headless": {
|
|
10900
|
+
name: "aider-headless",
|
|
10901
|
+
bin: "aider",
|
|
10902
|
+
args: ["--no-auto-commits"],
|
|
10903
|
+
stdio: "captured",
|
|
10904
|
+
envPassthrough: [...COMMON_PASSTHROUGH, "OPENAI_API_KEY", "ANTHROPIC_API_KEY"],
|
|
10905
|
+
parseOutput: "json"
|
|
10906
|
+
}
|
|
10907
|
+
};
|
|
10908
|
+
BUILTIN_AGENT_PROFILE_NAMES = Object.freeze(Object.keys(BUILTINS).sort());
|
|
10909
|
+
});
|
|
10910
|
+
|
|
10911
|
+
// src/integrations/agent/config.ts
|
|
10912
|
+
var init_config = __esm(() => {
|
|
10913
|
+
init_config2();
|
|
10914
|
+
init_errors();
|
|
10915
|
+
init_warn();
|
|
10916
|
+
init_profiles();
|
|
10917
|
+
});
|
|
10918
|
+
|
|
10919
|
+
// src/integrations/harnesses/opencode-sdk/sdk-runner.ts
|
|
10920
|
+
var init_sdk_runner = __esm(() => {
|
|
10921
|
+
init_config2();
|
|
10922
|
+
init_config();
|
|
10923
|
+
});
|
|
10924
|
+
|
|
10925
|
+
// src/integrations/harnesses/opencode-sdk/index.ts
|
|
10926
|
+
function caps3(c) {
|
|
10927
|
+
return {
|
|
10928
|
+
sessionLogs: false,
|
|
10929
|
+
agentDispatch: false,
|
|
10930
|
+
detection: false,
|
|
10931
|
+
configImport: false,
|
|
10932
|
+
runtimeIdentity: false,
|
|
10933
|
+
v1Migration: false,
|
|
10934
|
+
...c
|
|
10935
|
+
};
|
|
10936
|
+
}
|
|
10937
|
+
var OpencodeSdkHarness;
|
|
10938
|
+
var init_opencode_sdk = __esm(() => {
|
|
10939
|
+
init_sdk_runner();
|
|
10940
|
+
OpencodeSdkHarness = class OpencodeSdkHarness extends BaseHarness {
|
|
10941
|
+
id = "opencode-sdk";
|
|
10942
|
+
displayName = "OpenCode SDK";
|
|
10943
|
+
aliases = [];
|
|
10944
|
+
v1ProfilePrefixes = ["opencode-sdk"];
|
|
10945
|
+
capabilities = caps3({
|
|
10946
|
+
agentDispatch: true,
|
|
10947
|
+
detection: true,
|
|
10948
|
+
v1Migration: true
|
|
10949
|
+
});
|
|
10950
|
+
};
|
|
10951
|
+
});
|
|
10952
|
+
|
|
10953
|
+
// src/integrations/harnesses/index.ts
|
|
10954
|
+
function v1ProfilePlatform(name) {
|
|
10955
|
+
for (const h of V1_RESOLUTION_ORDER) {
|
|
10956
|
+
if (h.matchesV1ProfileName(name))
|
|
10957
|
+
return h.id;
|
|
10958
|
+
}
|
|
10959
|
+
return;
|
|
9995
10960
|
}
|
|
9996
|
-
var
|
|
9997
|
-
var
|
|
9998
|
-
|
|
9999
|
-
|
|
10000
|
-
|
|
10001
|
-
|
|
10961
|
+
var HARNESS_REGISTRY, HARNESS_BY_ID, HARNESS_BY_ANY_ID, VALID_HARNESS_IDS, SESSION_LOG_HARNESSES, AGENT_DISPATCH_HARNESSES, CONFIG_IMPORTER_HARNESSES, DETECTION_HARNESSES, V1_RESOLUTION_ORDER;
|
|
10962
|
+
var init_harnesses = __esm(() => {
|
|
10963
|
+
init_claude();
|
|
10964
|
+
init_opencode();
|
|
10965
|
+
init_opencode_sdk();
|
|
10966
|
+
HARNESS_REGISTRY = Object.freeze([
|
|
10967
|
+
new OpencodeHarness,
|
|
10968
|
+
new ClaudeHarness,
|
|
10969
|
+
new OpencodeSdkHarness
|
|
10970
|
+
]);
|
|
10971
|
+
HARNESS_BY_ID = new Map(HARNESS_REGISTRY.map((h) => [h.id, h]));
|
|
10972
|
+
HARNESS_BY_ANY_ID = (() => {
|
|
10973
|
+
const m = new Map;
|
|
10974
|
+
for (const h of HARNESS_REGISTRY) {
|
|
10975
|
+
m.set(h.id, h);
|
|
10976
|
+
if (h.runtimeId)
|
|
10977
|
+
m.set(h.runtimeId, h);
|
|
10978
|
+
for (const a of h.aliases)
|
|
10979
|
+
m.set(a, h);
|
|
10980
|
+
}
|
|
10981
|
+
return m;
|
|
10982
|
+
})();
|
|
10983
|
+
VALID_HARNESS_IDS = Object.freeze(HARNESS_REGISTRY.map((h) => h.id));
|
|
10984
|
+
SESSION_LOG_HARNESSES = HARNESS_REGISTRY.filter((h) => h.capabilities.sessionLogs);
|
|
10985
|
+
AGENT_DISPATCH_HARNESSES = HARNESS_REGISTRY.filter((h) => h.capabilities.agentDispatch);
|
|
10986
|
+
CONFIG_IMPORTER_HARNESSES = HARNESS_REGISTRY.filter((h) => h.capabilities.configImport);
|
|
10987
|
+
DETECTION_HARNESSES = HARNESS_REGISTRY.filter((h) => h.capabilities.detection);
|
|
10988
|
+
V1_RESOLUTION_ORDER = [...HARNESS_REGISTRY].sort((a, b) => b.id.length - a.id.length);
|
|
10002
10989
|
});
|
|
10003
10990
|
|
|
10004
|
-
// src/core/config-migration.ts
|
|
10991
|
+
// src/core/config/config-migration.ts
|
|
10005
10992
|
function compareConfigVersion(a, b) {
|
|
10006
10993
|
const partsA = normalizeVersion(a);
|
|
10007
10994
|
const partsB = normalizeVersion(b);
|
|
@@ -10450,14 +11437,7 @@ function migrateConfigShape(raw) {
|
|
|
10450
11437
|
return { changed, result };
|
|
10451
11438
|
}
|
|
10452
11439
|
function guessAgentPlatform(name) {
|
|
10453
|
-
|
|
10454
|
-
if (lower === "claude" || lower === "claude-code")
|
|
10455
|
-
return "claude";
|
|
10456
|
-
if (lower.startsWith("opencode-sdk"))
|
|
10457
|
-
return "opencode-sdk";
|
|
10458
|
-
if (lower.startsWith("opencode"))
|
|
10459
|
-
return "opencode";
|
|
10460
|
-
return;
|
|
11440
|
+
return v1ProfilePlatform(name);
|
|
10461
11441
|
}
|
|
10462
11442
|
function mapV1ProcessName(name) {
|
|
10463
11443
|
switch (name) {
|
|
@@ -10486,6 +11466,7 @@ function mapV1ProcessName(name) {
|
|
|
10486
11466
|
}
|
|
10487
11467
|
var CURRENT_CONFIG_VERSION = "0.8.0";
|
|
10488
11468
|
var init_config_migration = __esm(() => {
|
|
11469
|
+
init_harnesses();
|
|
10489
11470
|
init_warn();
|
|
10490
11471
|
});
|
|
10491
11472
|
|
|
@@ -10536,10 +11517,10 @@ var init_util = __esm(() => {
|
|
|
10536
11517
|
util2.assertEqual = (_) => {};
|
|
10537
11518
|
function assertIs(_arg) {}
|
|
10538
11519
|
util2.assertIs = assertIs;
|
|
10539
|
-
function
|
|
11520
|
+
function assertNever2(_x) {
|
|
10540
11521
|
throw new Error;
|
|
10541
11522
|
}
|
|
10542
|
-
util2.assertNever =
|
|
11523
|
+
util2.assertNever = assertNever2;
|
|
10543
11524
|
util2.arrayToEnum = (items) => {
|
|
10544
11525
|
const obj = {};
|
|
10545
11526
|
for (const item of items) {
|
|
@@ -10933,8 +11914,8 @@ class ParseStatus {
|
|
|
10933
11914
|
}
|
|
10934
11915
|
}
|
|
10935
11916
|
var makeIssue = (params) => {
|
|
10936
|
-
const { data, path:
|
|
10937
|
-
const fullPath = [...
|
|
11917
|
+
const { data, path: path10, errorMaps, issueData } = params;
|
|
11918
|
+
const fullPath = [...path10, ...issueData.path || []];
|
|
10938
11919
|
const fullIssue = {
|
|
10939
11920
|
...issueData,
|
|
10940
11921
|
path: fullPath
|
|
@@ -10980,11 +11961,11 @@ var init_errorUtil = __esm(() => {
|
|
|
10980
11961
|
|
|
10981
11962
|
// node_modules/zod/v3/types.js
|
|
10982
11963
|
class ParseInputLazyPath {
|
|
10983
|
-
constructor(parent, value,
|
|
11964
|
+
constructor(parent, value, path10, key) {
|
|
10984
11965
|
this._cachedPath = [];
|
|
10985
11966
|
this.parent = parent;
|
|
10986
11967
|
this.data = value;
|
|
10987
|
-
this._path =
|
|
11968
|
+
this._path = path10;
|
|
10988
11969
|
this._key = key;
|
|
10989
11970
|
}
|
|
10990
11971
|
get path() {
|
|
@@ -14455,10 +15436,16 @@ var init_zod = __esm(() => {
|
|
|
14455
15436
|
init_external();
|
|
14456
15437
|
});
|
|
14457
15438
|
|
|
14458
|
-
// src/core/config-
|
|
14459
|
-
var
|
|
15439
|
+
// src/core/config/config-types.ts
|
|
15440
|
+
var init_config_types = __esm(() => {
|
|
15441
|
+
init_harnesses();
|
|
15442
|
+
});
|
|
15443
|
+
|
|
15444
|
+
// src/core/config/config-schema.ts
|
|
15445
|
+
var positiveInt, nonNegativeNumber, nonEmptyString, httpUrl, LlmCapabilitiesSchema, LlmConnectionConfigSchema, LlmProfileConfigSchema, EmbeddingOllamaOptionsSchema, EmbeddingConnectionConfigSchema, AgentPlatformSchema, AgentProfileConfigSchema, ImproveProcessConfigSchema, ImproveProfileProcessesSchema, ImproveProfileConfigSchema, ProfilesSchema, DefaultsSchema, SourceConfigEntryOptionsSchema, SourceConfigEntrySchema, RegistryConfigEntrySchema, KitSourceSchema, InstalledStashEntrySchema, OutputConfigSchema, SearchGraphBoostSchema, SearchConfigSchema, FeedbackConfigSchema, ImproveUtilityDecaySchema, ImproveConfigSchema, GRAPH_EXTRACTION_INCLUDE_TYPES_ALLOWED, INDEX_PASS_PROVIDER_KEYS, INDEX_PASS_KNOWN_KEYS, IndexPassConfigSchema, MetadataEnhanceSchema, StalenessDetectionSchema, IndexConfigSchema, SetupTaskSchedulesSchema, SetupConfigSchema, AkmConfigShape, AkmConfigBaseSchema, AkmConfigSchema;
|
|
14460
15446
|
var init_config_schema = __esm(() => {
|
|
14461
15447
|
init_zod();
|
|
15448
|
+
init_config_types();
|
|
14462
15449
|
positiveInt = exports_external.number().int().positive();
|
|
14463
15450
|
nonNegativeNumber = exports_external.number().finite().min(0);
|
|
14464
15451
|
nonEmptyString = exports_external.string().min(1).refine((v) => v.trim().length > 0, { message: "expected a non-empty string" });
|
|
@@ -14502,7 +15489,7 @@ var init_config_schema = __esm(() => {
|
|
|
14502
15489
|
contextLength: positiveInt.optional(),
|
|
14503
15490
|
ollamaOptions: EmbeddingOllamaOptionsSchema.optional()
|
|
14504
15491
|
}).strict();
|
|
14505
|
-
AgentPlatformSchema = exports_external.enum(
|
|
15492
|
+
AgentPlatformSchema = exports_external.enum(VALID_HARNESS_IDS);
|
|
14506
15493
|
AgentProfileConfigSchema = exports_external.object({
|
|
14507
15494
|
platform: AgentPlatformSchema,
|
|
14508
15495
|
bin: exports_external.string().min(1).optional(),
|
|
@@ -14516,12 +15503,16 @@ var init_config_schema = __esm(() => {
|
|
|
14516
15503
|
profile: exports_external.string().min(1).optional(),
|
|
14517
15504
|
timeoutMs: exports_external.union([positiveInt, exports_external.null()]).optional(),
|
|
14518
15505
|
allowedTypes: exports_external.array(exports_external.string().min(1)).optional(),
|
|
15506
|
+
minPoolSize: exports_external.number().int().min(0).optional(),
|
|
14519
15507
|
qualityGate: exports_external.object({ enabled: exports_external.boolean().optional() }).strict().optional(),
|
|
14520
15508
|
contradictionDetection: exports_external.object({ enabled: exports_external.boolean().optional() }).strict().optional(),
|
|
14521
15509
|
defaultSince: exports_external.string().min(1).optional(),
|
|
14522
15510
|
maxTotalChars: positiveInt.optional(),
|
|
15511
|
+
minContentChars: exports_external.number().int().min(0).optional(),
|
|
14523
15512
|
maxChunkSize: exports_external.number().int().min(1).max(50).optional(),
|
|
14524
|
-
|
|
15513
|
+
minNewSessions: exports_external.number().int().min(0).optional(),
|
|
15514
|
+
indexSessions: exports_external.boolean().optional(),
|
|
15515
|
+
minSessionDuration: exports_external.number().min(0).optional(),
|
|
14525
15516
|
applyMode: exports_external.enum(["queue", "promote"]).optional(),
|
|
14526
15517
|
policy: exports_external.string().min(1).optional(),
|
|
14527
15518
|
maxAcceptsPerRun: positiveInt.optional(),
|
|
@@ -14779,6 +15770,13 @@ var init_config_schema = __esm(() => {
|
|
|
14779
15770
|
metadataEnhance: MetadataEnhanceSchema.optional(),
|
|
14780
15771
|
stalenessDetection: StalenessDetectionSchema.optional()
|
|
14781
15772
|
}).catchall(IndexPassConfigSchema));
|
|
15773
|
+
SetupTaskSchedulesSchema = exports_external.object({
|
|
15774
|
+
improve: exports_external.string().min(1).optional(),
|
|
15775
|
+
index: exports_external.string().min(1).optional()
|
|
15776
|
+
}).strict();
|
|
15777
|
+
SetupConfigSchema = exports_external.object({
|
|
15778
|
+
taskSchedules: SetupTaskSchedulesSchema.optional()
|
|
15779
|
+
}).strict();
|
|
14782
15780
|
AkmConfigShape = {
|
|
14783
15781
|
configVersion: exports_external.union([exports_external.string().min(1), exports_external.number()]).optional(),
|
|
14784
15782
|
profiles: ProfilesSchema.optional(),
|
|
@@ -14796,7 +15794,8 @@ var init_config_schema = __esm(() => {
|
|
|
14796
15794
|
search: SearchConfigSchema.optional(),
|
|
14797
15795
|
feedback: FeedbackConfigSchema.optional(),
|
|
14798
15796
|
archiveRetentionDays: nonNegativeNumber.optional(),
|
|
14799
|
-
improve: ImproveConfigSchema.optional()
|
|
15797
|
+
improve: ImproveConfigSchema.optional(),
|
|
15798
|
+
setup: SetupConfigSchema.optional()
|
|
14800
15799
|
};
|
|
14801
15800
|
AkmConfigBaseSchema = exports_external.object(AkmConfigShape).strict();
|
|
14802
15801
|
AkmConfigSchema = AkmConfigBaseSchema.superRefine((config, ctx) => {
|
|
@@ -14819,8 +15818,8 @@ var init_config_schema = __esm(() => {
|
|
|
14819
15818
|
});
|
|
14820
15819
|
});
|
|
14821
15820
|
|
|
14822
|
-
// src/core/config-sources.ts
|
|
14823
|
-
import { createHash } from "crypto";
|
|
15821
|
+
// src/core/config/config-sources.ts
|
|
15822
|
+
import { createHash as createHash2 } from "crypto";
|
|
14824
15823
|
function deriveStashEntryName(entry) {
|
|
14825
15824
|
if (entry.name)
|
|
14826
15825
|
return entry.name;
|
|
@@ -14829,7 +15828,7 @@ function deriveStashEntryName(entry) {
|
|
|
14829
15828
|
path: entry.path ?? null,
|
|
14830
15829
|
url: entry.url ?? null
|
|
14831
15830
|
});
|
|
14832
|
-
const hash =
|
|
15831
|
+
const hash = createHash2("sha256").update(seed).digest("hex").slice(0, 8);
|
|
14833
15832
|
return `${entry.type}-${hash}`;
|
|
14834
15833
|
}
|
|
14835
15834
|
function parseSourceSpec(entry) {
|
|
@@ -14898,7 +15897,7 @@ function toConfiguredSource(persisted, isPrimary) {
|
|
|
14898
15897
|
}
|
|
14899
15898
|
var init_config_sources = () => {};
|
|
14900
15899
|
|
|
14901
|
-
// src/core/config.ts
|
|
15900
|
+
// src/core/config/config.ts
|
|
14902
15901
|
var exports_config = {};
|
|
14903
15902
|
__export(exports_config, {
|
|
14904
15903
|
updateConfig: () => updateConfig,
|
|
@@ -14916,12 +15915,13 @@ __export(exports_config, {
|
|
|
14916
15915
|
getIndexPassConfig: () => getIndexPassConfig,
|
|
14917
15916
|
getEffectiveRegistries: () => getEffectiveRegistries,
|
|
14918
15917
|
getDefaultLlmConfig: () => getDefaultLlmConfig,
|
|
15918
|
+
VALID_HARNESS_IDS: () => VALID_HARNESS_IDS,
|
|
14919
15919
|
FEEDBACK_FAILURE_MODES: () => FEEDBACK_FAILURE_MODES,
|
|
14920
15920
|
DEFAULT_GRAPH_EXTRACTION_BATCH_SIZE: () => DEFAULT_GRAPH_EXTRACTION_BATCH_SIZE,
|
|
14921
15921
|
DEFAULT_CONFIG: () => DEFAULT_CONFIG
|
|
14922
15922
|
});
|
|
14923
|
-
import
|
|
14924
|
-
import
|
|
15923
|
+
import fs11 from "fs";
|
|
15924
|
+
import path10 from "path";
|
|
14925
15925
|
function resolveBatchSize(configured, contextLength) {
|
|
14926
15926
|
const base = configured && configured > 0 ? configured : DEFAULT_GRAPH_EXTRACTION_BATCH_SIZE;
|
|
14927
15927
|
if (!contextLength || contextLength <= 0)
|
|
@@ -14936,7 +15936,7 @@ function loadUserConfig() {
|
|
|
14936
15936
|
const configPath = getConfigPath();
|
|
14937
15937
|
let stat;
|
|
14938
15938
|
try {
|
|
14939
|
-
stat =
|
|
15939
|
+
stat = fs11.statSync(configPath);
|
|
14940
15940
|
} catch {
|
|
14941
15941
|
cachedConfig = undefined;
|
|
14942
15942
|
return applyRuntimeEnvApiKeys({ ...DEFAULT_CONFIG });
|
|
@@ -14946,7 +15946,7 @@ function loadUserConfig() {
|
|
|
14946
15946
|
}
|
|
14947
15947
|
let text;
|
|
14948
15948
|
try {
|
|
14949
|
-
text =
|
|
15949
|
+
text = fs11.readFileSync(configPath, "utf8");
|
|
14950
15950
|
} catch {
|
|
14951
15951
|
cachedConfig = undefined;
|
|
14952
15952
|
return applyRuntimeEnvApiKeys({ ...DEFAULT_CONFIG });
|
|
@@ -14955,7 +15955,7 @@ function loadUserConfig() {
|
|
|
14955
15955
|
const finalConfig = applyRuntimeEnvApiKeys(parseAndValidate(text, configPath));
|
|
14956
15956
|
let finalStat = stat;
|
|
14957
15957
|
try {
|
|
14958
|
-
finalStat =
|
|
15958
|
+
finalStat = fs11.statSync(configPath);
|
|
14959
15959
|
} catch {}
|
|
14960
15960
|
cachedConfig = {
|
|
14961
15961
|
config: finalConfig,
|
|
@@ -15058,8 +16058,8 @@ function loadConfig() {
|
|
|
15058
16058
|
function saveConfig(config) {
|
|
15059
16059
|
cachedConfig = undefined;
|
|
15060
16060
|
const configPath = getConfigPath();
|
|
15061
|
-
const dir =
|
|
15062
|
-
|
|
16061
|
+
const dir = path10.dirname(configPath);
|
|
16062
|
+
fs11.mkdirSync(dir, { recursive: true });
|
|
15063
16063
|
const sanitized = sanitizeConfigForWrite(config);
|
|
15064
16064
|
const parseResult = AkmConfigSchema.safeParse(sanitized);
|
|
15065
16065
|
if (!parseResult.success) {
|
|
@@ -15204,14 +16204,14 @@ function applyRuntimeEnvApiKeys(config) {
|
|
|
15204
16204
|
return next;
|
|
15205
16205
|
}
|
|
15206
16206
|
function warnIfProjectConfigPresent(startDir) {
|
|
15207
|
-
let currentDir =
|
|
16207
|
+
let currentDir = path10.resolve(startDir);
|
|
15208
16208
|
while (true) {
|
|
15209
|
-
const configPath =
|
|
16209
|
+
const configPath = path10.join(currentDir, PROJECT_CONFIG_RELATIVE_PATH);
|
|
15210
16210
|
if (isFile(configPath) && !PROJECT_CONFIG_DEPRECATION_WARNED.has(configPath)) {
|
|
15211
16211
|
PROJECT_CONFIG_DEPRECATION_WARNED.add(configPath);
|
|
15212
16212
|
warn(`[akm] DEPRECATED: project-level config file found at ${configPath}. ` + "Project-level config files are no longer merged (removed after 0.8.x deprecation). " + "Move any needed settings to ~/.config/akm/config.json; this file is ignored.");
|
|
15213
16213
|
}
|
|
15214
|
-
const parentDir =
|
|
16214
|
+
const parentDir = path10.dirname(currentDir);
|
|
15215
16215
|
if (parentDir === currentDir)
|
|
15216
16216
|
break;
|
|
15217
16217
|
currentDir = parentDir;
|
|
@@ -15219,20 +16219,21 @@ function warnIfProjectConfigPresent(startDir) {
|
|
|
15219
16219
|
}
|
|
15220
16220
|
function isFile(filePath) {
|
|
15221
16221
|
try {
|
|
15222
|
-
return
|
|
16222
|
+
return fs11.statSync(filePath).isFile();
|
|
15223
16223
|
} catch {
|
|
15224
16224
|
return false;
|
|
15225
16225
|
}
|
|
15226
16226
|
}
|
|
15227
16227
|
var FEEDBACK_FAILURE_MODES, DEFAULT_GRAPH_EXTRACTION_BATCH_SIZE = 4, GRAPH_EXTRACTION_CHARS_PER_BODY = 1500, DEFAULT_CONFIG, PROJECT_CONFIG_RELATIVE_PATH, cachedConfig, INDEX_RESERVED_KEYS, PROJECT_CONFIG_DEPRECATION_WARNED;
|
|
15228
|
-
var
|
|
16228
|
+
var init_config2 = __esm(() => {
|
|
16229
|
+
init_errors();
|
|
15229
16230
|
init_config_io();
|
|
15230
16231
|
init_config_migration();
|
|
15231
16232
|
init_config_schema();
|
|
15232
|
-
init_errors();
|
|
15233
16233
|
init_config_io();
|
|
15234
16234
|
init_paths();
|
|
15235
16235
|
init_warn();
|
|
16236
|
+
init_config_types();
|
|
15236
16237
|
init_config_sources();
|
|
15237
16238
|
FEEDBACK_FAILURE_MODES = [
|
|
15238
16239
|
"incorrect",
|
|
@@ -15252,12 +16253,12 @@ var init_config = __esm(() => {
|
|
|
15252
16253
|
detail: "brief"
|
|
15253
16254
|
}
|
|
15254
16255
|
};
|
|
15255
|
-
PROJECT_CONFIG_RELATIVE_PATH =
|
|
16256
|
+
PROJECT_CONFIG_RELATIVE_PATH = path10.join(".akm", "config.json");
|
|
15256
16257
|
INDEX_RESERVED_KEYS = new Set(["metadataEnhance", "stalenessDetection"]);
|
|
15257
16258
|
PROJECT_CONFIG_DEPRECATION_WARNED = new Set;
|
|
15258
16259
|
});
|
|
15259
16260
|
|
|
15260
|
-
// src/indexer/db.ts
|
|
16261
|
+
// src/indexer/db/db.ts
|
|
15261
16262
|
var exports_db = {};
|
|
15262
16263
|
__export(exports_db, {
|
|
15263
16264
|
warnIfVecMissing: () => warnIfVecMissing,
|
|
@@ -15275,7 +16276,7 @@ __export(exports_db, {
|
|
|
15275
16276
|
relinkUsageEvents: () => relinkUsageEvents,
|
|
15276
16277
|
rebuildFts: () => rebuildFts,
|
|
15277
16278
|
openExistingDatabase: () => openExistingDatabase,
|
|
15278
|
-
openDatabase: () =>
|
|
16279
|
+
openDatabase: () => openDatabase2,
|
|
15279
16280
|
isVecAvailable: () => isVecAvailable,
|
|
15280
16281
|
getZeroResultSearches: () => getZeroResultSearches,
|
|
15281
16282
|
getUtilityScoresByIds: () => getUtilityScoresByIds,
|
|
@@ -15288,11 +16289,15 @@ __export(exports_db, {
|
|
|
15288
16289
|
getLlmCacheEntry: () => getLlmCacheEntry,
|
|
15289
16290
|
getLlmCacheEntriesByRefs: () => getLlmCacheEntriesByRefs,
|
|
15290
16291
|
getIndexDirState: () => getIndexDirState,
|
|
16292
|
+
getEntryRefRowsForStashRoot: () => getEntryRefRowsForStashRoot,
|
|
16293
|
+
getEntryIdByFilePath: () => getEntryIdByFilePath,
|
|
16294
|
+
getEntryFilePathById: () => getEntryFilePathById,
|
|
15291
16295
|
getEntryCount: () => getEntryCount,
|
|
15292
16296
|
getEntryByRef: () => getEntryByRef,
|
|
15293
16297
|
getEntryById: () => getEntryById,
|
|
15294
16298
|
getEntriesByDir: () => getEntriesByDir,
|
|
15295
16299
|
getEmbeddingCount: () => getEmbeddingCount,
|
|
16300
|
+
getEmbeddableEntryCount: () => getEmbeddableEntryCount,
|
|
15296
16301
|
getDerivedForParent: () => getDerivedForParent,
|
|
15297
16302
|
getAllEntriesForEmbedding: () => getAllEntriesForEmbedding,
|
|
15298
16303
|
getAllEntries: () => getAllEntries,
|
|
@@ -15304,6 +16309,7 @@ __export(exports_db, {
|
|
|
15304
16309
|
deleteEntriesByDir: () => deleteEntriesByDir,
|
|
15305
16310
|
computeSourceHash: () => computeSourceHash,
|
|
15306
16311
|
computeBodyHash: () => computeBodyHash,
|
|
16312
|
+
collectTagSetFromEntries: () => collectTagSetFromEntries,
|
|
15307
16313
|
closeDatabase: () => closeDatabase,
|
|
15308
16314
|
clearStaleCacheEntries: () => clearStaleCacheEntries,
|
|
15309
16315
|
bumpUtilityScoresBatch: () => bumpUtilityScoresBatch,
|
|
@@ -15314,19 +16320,18 @@ __export(exports_db, {
|
|
|
15314
16320
|
EMBEDDING_DIM: () => EMBEDDING_DIM,
|
|
15315
16321
|
DB_VERSION: () => DB_VERSION
|
|
15316
16322
|
});
|
|
15317
|
-
import
|
|
15318
|
-
import
|
|
15319
|
-
import
|
|
15320
|
-
|
|
15321
|
-
function openDatabase(dbPath, options) {
|
|
16323
|
+
import fs12 from "fs";
|
|
16324
|
+
import { createRequire as createRequire3 } from "module";
|
|
16325
|
+
import path11 from "path";
|
|
16326
|
+
function openDatabase2(dbPath, options) {
|
|
15322
16327
|
const resolvedPath = dbPath ?? getDbPath();
|
|
15323
|
-
const dir =
|
|
15324
|
-
if (!
|
|
15325
|
-
|
|
16328
|
+
const dir = path11.dirname(resolvedPath);
|
|
16329
|
+
if (!fs12.existsSync(dir)) {
|
|
16330
|
+
fs12.mkdirSync(dir, { recursive: true });
|
|
15326
16331
|
}
|
|
15327
|
-
const db =
|
|
16332
|
+
const db = openDatabase(resolvedPath);
|
|
15328
16333
|
db.exec("PRAGMA journal_mode = WAL");
|
|
15329
|
-
db.exec("PRAGMA busy_timeout =
|
|
16334
|
+
db.exec("PRAGMA busy_timeout = 30000");
|
|
15330
16335
|
db.exec("PRAGMA foreign_keys = ON");
|
|
15331
16336
|
loadVecExtension(db);
|
|
15332
16337
|
const resolvedDim = options?.embeddingDim ?? resolveConfiguredEmbeddingDim();
|
|
@@ -15336,7 +16341,7 @@ function openDatabase(dbPath, options) {
|
|
|
15336
16341
|
}
|
|
15337
16342
|
function resolveConfiguredEmbeddingDim() {
|
|
15338
16343
|
try {
|
|
15339
|
-
const { loadConfig: loadConfig2 } = (
|
|
16344
|
+
const { loadConfig: loadConfig2 } = (init_config2(), __toCommonJS(exports_config));
|
|
15340
16345
|
const dim = loadConfig2().embedding?.dimension;
|
|
15341
16346
|
if (typeof dim === "number" && Number.isInteger(dim) && dim > 0 && dim <= 4096) {
|
|
15342
16347
|
return dim;
|
|
@@ -15348,9 +16353,9 @@ function resolveConfiguredEmbeddingDim() {
|
|
|
15348
16353
|
}
|
|
15349
16354
|
function openExistingDatabase(dbPath) {
|
|
15350
16355
|
const resolvedPath = dbPath ?? getDbPath();
|
|
15351
|
-
const db =
|
|
16356
|
+
const db = openDatabase(resolvedPath);
|
|
15352
16357
|
db.exec("PRAGMA journal_mode = WAL");
|
|
15353
|
-
db.exec("PRAGMA busy_timeout =
|
|
16358
|
+
db.exec("PRAGMA busy_timeout = 30000");
|
|
15354
16359
|
db.exec("PRAGMA foreign_keys = ON");
|
|
15355
16360
|
loadVecExtension(db);
|
|
15356
16361
|
return db;
|
|
@@ -15360,7 +16365,7 @@ function closeDatabase(db) {
|
|
|
15360
16365
|
}
|
|
15361
16366
|
function loadVecExtension(db) {
|
|
15362
16367
|
try {
|
|
15363
|
-
const esmRequire =
|
|
16368
|
+
const esmRequire = createRequire3(import.meta.url);
|
|
15364
16369
|
const sqliteVec = esmRequire("sqlite-vec");
|
|
15365
16370
|
sqliteVec.load(db);
|
|
15366
16371
|
vecStatus.set(db, true);
|
|
@@ -15376,7 +16381,7 @@ function warnIfVecMissing(db, { once } = { once: false }) {
|
|
|
15376
16381
|
return;
|
|
15377
16382
|
if (once && vecInitWarnedDbs.has(db))
|
|
15378
16383
|
return;
|
|
15379
|
-
|
|
16384
|
+
bestEffort(() => {
|
|
15380
16385
|
const row = db.prepare("SELECT COUNT(*) AS cnt FROM embeddings").get();
|
|
15381
16386
|
const count = row?.cnt ?? 0;
|
|
15382
16387
|
if (count >= VEC_FALLBACK_THRESHOLD) {
|
|
@@ -15385,7 +16390,7 @@ function warnIfVecMissing(db, { once } = { once: false }) {
|
|
|
15385
16390
|
if (once)
|
|
15386
16391
|
vecInitWarnedDbs.add(db);
|
|
15387
16392
|
}
|
|
15388
|
-
}
|
|
16393
|
+
}, "embeddings table may not exist yet during init");
|
|
15389
16394
|
}
|
|
15390
16395
|
function ensureSchema(db, embeddingDim, options) {
|
|
15391
16396
|
db.exec(`
|
|
@@ -15591,12 +16596,8 @@ function ensureSchema(db, embeddingDim, options) {
|
|
|
15591
16596
|
const storedDim = getMeta(db, "embeddingDim");
|
|
15592
16597
|
if (storedDim && storedDim !== String(embeddingDim)) {
|
|
15593
16598
|
backupBeforeEmbeddingDimChange(options?.dataDir, storedDim, String(embeddingDim));
|
|
15594
|
-
|
|
15595
|
-
|
|
15596
|
-
} catch {}
|
|
15597
|
-
try {
|
|
15598
|
-
db.exec("DELETE FROM embeddings");
|
|
15599
|
-
} catch {}
|
|
16599
|
+
bestEffort(() => db.exec("DROP TABLE IF EXISTS entries_vec"), "drop entries_vec on dim change");
|
|
16600
|
+
bestEffort(() => db.exec("DELETE FROM embeddings"), "delete stale embeddings on dim change");
|
|
15600
16601
|
setMeta(db, "hasEmbeddings", "0");
|
|
15601
16602
|
}
|
|
15602
16603
|
}
|
|
@@ -15620,9 +16621,7 @@ function ensureSchema(db, embeddingDim, options) {
|
|
|
15620
16621
|
const storedDim = getMeta(db, "embeddingDim");
|
|
15621
16622
|
if (storedDim && storedDim !== String(embeddingDim)) {
|
|
15622
16623
|
backupBeforeEmbeddingDimChange(options?.dataDir, storedDim, String(embeddingDim));
|
|
15623
|
-
|
|
15624
|
-
db.exec("DELETE FROM embeddings");
|
|
15625
|
-
} catch {}
|
|
16624
|
+
bestEffort(() => db.exec("DELETE FROM embeddings"), "delete embeddings on explicit dim change");
|
|
15626
16625
|
setMeta(db, "hasEmbeddings", "0");
|
|
15627
16626
|
}
|
|
15628
16627
|
setMeta(db, "embeddingDim", String(embeddingDim));
|
|
@@ -15637,9 +16636,9 @@ function handleVersionUpgrade(db) {
|
|
|
15637
16636
|
if (storedVersion === undefined || storedVersion === "" || storedVersion === String(DB_VERSION))
|
|
15638
16637
|
return [];
|
|
15639
16638
|
let usageBackup = [];
|
|
15640
|
-
|
|
16639
|
+
bestEffort(() => {
|
|
15641
16640
|
usageBackup = db.prepare("SELECT * FROM usage_events").all();
|
|
15642
|
-
}
|
|
16641
|
+
}, "usage_events table may not exist in older versions");
|
|
15643
16642
|
db.exec("DROP TABLE IF EXISTS utility_scores");
|
|
15644
16643
|
db.exec("DROP TABLE IF EXISTS utility_scores_scoped");
|
|
15645
16644
|
db.exec("DROP INDEX IF EXISTS idx_utility_scores_scoped_entry_id");
|
|
@@ -15756,7 +16755,7 @@ function deleteIndexDirState(db, dirPath) {
|
|
|
15756
16755
|
db.prepare("DELETE FROM index_dir_state WHERE dir_path = ?").run(dirPath);
|
|
15757
16756
|
}
|
|
15758
16757
|
function deleteIndexDirStatesByStashDir(db, stashDir) {
|
|
15759
|
-
db.prepare("DELETE FROM index_dir_state WHERE dir_path = ? OR dir_path LIKE ?").run(stashDir, `${stashDir}${
|
|
16758
|
+
db.prepare("DELETE FROM index_dir_state WHERE dir_path = ? OR dir_path LIKE ?").run(stashDir, `${stashDir}${path11.sep}%`);
|
|
15760
16759
|
}
|
|
15761
16760
|
function upsertEntry(db, entryKey, dirPath, filePath, stashDir, entry, searchText) {
|
|
15762
16761
|
const stmts = getUpsertStmts(db);
|
|
@@ -15791,14 +16790,14 @@ function getUpsertStmts(db) {
|
|
|
15791
16790
|
return stmts;
|
|
15792
16791
|
}
|
|
15793
16792
|
function ensureDerivedFromColumn(db) {
|
|
15794
|
-
|
|
16793
|
+
bestEffort(() => {
|
|
15795
16794
|
const cols = db.prepare("PRAGMA table_info(entries)").all();
|
|
15796
16795
|
const hasColumn = cols.some((c) => c.name === "derived_from");
|
|
15797
16796
|
if (!hasColumn) {
|
|
15798
16797
|
db.exec("ALTER TABLE entries ADD COLUMN derived_from TEXT");
|
|
15799
16798
|
}
|
|
15800
16799
|
db.exec("CREATE INDEX IF NOT EXISTS idx_entries_derived_from ON entries(derived_from)");
|
|
15801
|
-
}
|
|
16800
|
+
}, "entries table may not exist on a brand-new DB before CREATE \u2014 caller is responsible");
|
|
15802
16801
|
}
|
|
15803
16802
|
function getDerivedForParent(db, parentRef) {
|
|
15804
16803
|
if (!parentRef)
|
|
@@ -15838,7 +16837,7 @@ function getPositiveFeedbackCountsByIds(db, ids) {
|
|
|
15838
16837
|
for (let i = 0;i < ids.length; i += SQLITE_CHUNK_SIZE) {
|
|
15839
16838
|
const chunk = ids.slice(i, i + SQLITE_CHUNK_SIZE);
|
|
15840
16839
|
const placeholders = chunk.map(() => "?").join(",");
|
|
15841
|
-
|
|
16840
|
+
bestEffort(() => {
|
|
15842
16841
|
const rows = db.prepare(`SELECT entry_id, COUNT(*) AS cnt
|
|
15843
16842
|
FROM usage_events
|
|
15844
16843
|
WHERE event_type = 'feedback'
|
|
@@ -15850,7 +16849,7 @@ function getPositiveFeedbackCountsByIds(db, ids) {
|
|
|
15850
16849
|
result.set(row.entry_id, row.cnt);
|
|
15851
16850
|
}
|
|
15852
16851
|
}
|
|
15853
|
-
}
|
|
16852
|
+
}, "usage_events table may be missing on legacy DBs \u2014 treat as zero counts");
|
|
15854
16853
|
}
|
|
15855
16854
|
return result;
|
|
15856
16855
|
}
|
|
@@ -15875,33 +16874,19 @@ function deleteRelatedRows(db, ids) {
|
|
|
15875
16874
|
for (let i = 0;i < numericIds.length; i += SQLITE_CHUNK_SIZE) {
|
|
15876
16875
|
const chunk = numericIds.slice(i, i + SQLITE_CHUNK_SIZE);
|
|
15877
16876
|
const placeholders = chunk.map(() => "?").join(",");
|
|
15878
|
-
|
|
15879
|
-
|
|
15880
|
-
} catch {}
|
|
15881
|
-
try {
|
|
15882
|
-
db.prepare(`DELETE FROM entries_fts_dirty WHERE entry_id IN (${placeholders})`).run(...chunk);
|
|
15883
|
-
} catch {}
|
|
16877
|
+
bestEffort(() => db.prepare(`DELETE FROM entries_fts WHERE entry_id IN (${placeholders})`).run(...chunk), "fts table may not exist on a brand-new db");
|
|
16878
|
+
bestEffort(() => db.prepare(`DELETE FROM entries_fts_dirty WHERE entry_id IN (${placeholders})`).run(...chunk), "fts dirty table is created lazily by upsertEntry");
|
|
15884
16879
|
}
|
|
15885
16880
|
for (let i = 0;i < numericIds.length; i += SQLITE_CHUNK_SIZE) {
|
|
15886
16881
|
const chunk = numericIds.slice(i, i + SQLITE_CHUNK_SIZE);
|
|
15887
16882
|
const placeholders = chunk.map(() => "?").join(",");
|
|
15888
|
-
|
|
15889
|
-
db.prepare(`DELETE FROM embeddings WHERE id IN (${placeholders})`).run(...chunk);
|
|
15890
|
-
} catch {}
|
|
16883
|
+
bestEffort(() => db.prepare(`DELETE FROM embeddings WHERE id IN (${placeholders})`).run(...chunk), "delete embeddings for entries");
|
|
15891
16884
|
if (vecAvail) {
|
|
15892
|
-
|
|
15893
|
-
db.prepare(`DELETE FROM entries_vec WHERE id IN (${placeholders})`).run(...chunk);
|
|
15894
|
-
} catch {}
|
|
16885
|
+
bestEffort(() => db.prepare(`DELETE FROM entries_vec WHERE id IN (${placeholders})`).run(...chunk), "delete entries_vec for entries");
|
|
15895
16886
|
}
|
|
15896
|
-
|
|
15897
|
-
|
|
15898
|
-
|
|
15899
|
-
try {
|
|
15900
|
-
db.prepare(`DELETE FROM utility_scores_scoped WHERE entry_id IN (${placeholders})`).run(...chunk);
|
|
15901
|
-
} catch {}
|
|
15902
|
-
try {
|
|
15903
|
-
db.prepare(`DELETE FROM usage_events WHERE entry_id IN (${placeholders})`).run(...chunk);
|
|
15904
|
-
} catch {}
|
|
16887
|
+
bestEffort(() => db.prepare(`DELETE FROM utility_scores WHERE entry_id IN (${placeholders})`).run(...chunk), "delete utility_scores for entries");
|
|
16888
|
+
bestEffort(() => db.prepare(`DELETE FROM utility_scores_scoped WHERE entry_id IN (${placeholders})`).run(...chunk), "delete utility_scores_scoped for entries");
|
|
16889
|
+
bestEffort(() => db.prepare(`DELETE FROM usage_events WHERE entry_id IN (${placeholders})`).run(...chunk), "delete usage_events for entries");
|
|
15905
16890
|
}
|
|
15906
16891
|
}
|
|
15907
16892
|
function deleteEntriesByIds(db, ids) {
|
|
@@ -15964,12 +16949,12 @@ function upsertEmbedding(db, entryId, embedding) {
|
|
|
15964
16949
|
const buf = float32Buffer(embedding);
|
|
15965
16950
|
db.prepare("INSERT OR REPLACE INTO embeddings (id, embedding) VALUES (?, ?)").run(entryId, buf);
|
|
15966
16951
|
if (isVecAvailable(db)) {
|
|
15967
|
-
|
|
16952
|
+
bestEffort(() => {
|
|
15968
16953
|
db.transaction(() => {
|
|
15969
16954
|
db.prepare("DELETE FROM entries_vec WHERE id = ?").run(entryId);
|
|
15970
16955
|
db.prepare("INSERT INTO entries_vec (id, embedding) VALUES (?, ?)").run(entryId, buf);
|
|
15971
16956
|
})();
|
|
15972
|
-
}
|
|
16957
|
+
}, "vec table unavailable or constraint failure");
|
|
15973
16958
|
}
|
|
15974
16959
|
return true;
|
|
15975
16960
|
}
|
|
@@ -16173,6 +17158,10 @@ function getEntryCount(db) {
|
|
|
16173
17158
|
const row = db.prepare("SELECT COUNT(*) AS cnt FROM entries").get();
|
|
16174
17159
|
return row.cnt;
|
|
16175
17160
|
}
|
|
17161
|
+
function getEmbeddableEntryCount(db) {
|
|
17162
|
+
const row = db.prepare("SELECT COUNT(*) AS cnt FROM entries").get();
|
|
17163
|
+
return row.cnt;
|
|
17164
|
+
}
|
|
16176
17165
|
function getEmbeddingCount(db) {
|
|
16177
17166
|
const row = db.prepare("SELECT COUNT(*) AS cnt FROM embeddings").get();
|
|
16178
17167
|
return row.cnt;
|
|
@@ -16194,6 +17183,17 @@ function getEntriesByDir(db, dirPath) {
|
|
|
16194
17183
|
const rows = db.prepare("SELECT id, entry_key, dir_path, file_path, stash_dir, entry_json, search_text FROM entries WHERE dir_path = ?").all(dirPath);
|
|
16195
17184
|
return parseEntryRows(rows, "getEntriesByDir");
|
|
16196
17185
|
}
|
|
17186
|
+
function getEntryIdByFilePath(db, filePath) {
|
|
17187
|
+
const row = db.prepare("SELECT id FROM entries WHERE file_path = ? LIMIT 1").get(filePath);
|
|
17188
|
+
return row?.id;
|
|
17189
|
+
}
|
|
17190
|
+
function getEntryFilePathById(db, id) {
|
|
17191
|
+
const row = db.prepare("SELECT file_path FROM entries WHERE id = ?").get(id);
|
|
17192
|
+
return row?.file_path;
|
|
17193
|
+
}
|
|
17194
|
+
function getEntryRefRowsForStashRoot(db, stashRoot) {
|
|
17195
|
+
return db.prepare("SELECT file_path, entry_json FROM entries WHERE stash_dir = ? OR file_path LIKE ?").all(stashRoot, `${stashRoot}%`);
|
|
17196
|
+
}
|
|
16197
17197
|
function getUtilityScore(db, entryId) {
|
|
16198
17198
|
const row = db.prepare("SELECT entry_id, utility, show_count, search_count, select_rate, last_used_at, updated_at FROM utility_scores WHERE entry_id = ?").get(entryId);
|
|
16199
17199
|
if (!row)
|
|
@@ -16303,18 +17303,16 @@ function upsertLlmCacheEntry(db, assetRef, bodyHash, resultJson, cacheVariant =
|
|
|
16303
17303
|
updated_at = excluded.updated_at`).run(assetRef, cacheVariant, bodyHash, resultJson, Date.now());
|
|
16304
17304
|
}
|
|
16305
17305
|
function clearStaleCacheEntries(db) {
|
|
16306
|
-
|
|
17306
|
+
bestEffort(() => {
|
|
16307
17307
|
db.exec(`
|
|
16308
17308
|
DELETE FROM llm_enrichment_cache
|
|
16309
17309
|
WHERE asset_ref NOT IN (SELECT file_path FROM entries)
|
|
16310
17310
|
AND asset_ref NOT IN (SELECT entry_key FROM entries)
|
|
16311
17311
|
`);
|
|
16312
|
-
}
|
|
17312
|
+
}, "llm_enrichment_cache may not exist in very old DBs opened without ensureSchema");
|
|
16313
17313
|
}
|
|
16314
17314
|
function computeBodyHash(body) {
|
|
16315
|
-
|
|
16316
|
-
hasher.update(body);
|
|
16317
|
-
return hasher.digest("hex");
|
|
17315
|
+
return sha256Hex(body);
|
|
16318
17316
|
}
|
|
16319
17317
|
function getRetrievalCounts(db, refs) {
|
|
16320
17318
|
if (refs.length === 0)
|
|
@@ -16369,7 +17367,6 @@ function getAllEntriesForEmbedding(db) {
|
|
|
16369
17367
|
return db.prepare(`
|
|
16370
17368
|
SELECT e.id, e.search_text AS searchText, e.entry_key AS entryKey, e.file_path AS filePath FROM entries e
|
|
16371
17369
|
WHERE NOT EXISTS (SELECT 1 FROM embeddings b WHERE b.id = e.id)
|
|
16372
|
-
AND e.entry_type != 'vault'
|
|
16373
17370
|
`).all();
|
|
16374
17371
|
}
|
|
16375
17372
|
function upsertWorkflowDocument(db, entryId, doc, content) {
|
|
@@ -16433,7 +17430,7 @@ function applyFeedbackToUtilityScore(db, entryId, positiveCount, negativeCount)
|
|
|
16433
17430
|
return { previousUtility, nextUtility, crossedReviewThreshold };
|
|
16434
17431
|
}
|
|
16435
17432
|
function relinkUsageEvents(db) {
|
|
16436
|
-
|
|
17433
|
+
bestEffort(() => {
|
|
16437
17434
|
db.exec(`
|
|
16438
17435
|
UPDATE usage_events
|
|
16439
17436
|
SET entry_id = NULL
|
|
@@ -16448,7 +17445,7 @@ function relinkUsageEvents(db) {
|
|
|
16448
17445
|
)
|
|
16449
17446
|
WHERE entry_id IS NULL AND entry_ref IS NOT NULL
|
|
16450
17447
|
`);
|
|
16451
|
-
}
|
|
17448
|
+
}, "usage_events table may not exist yet during entry_id re-resolution");
|
|
16452
17449
|
}
|
|
16453
17450
|
function upsertRegistryIndexCache(db, registryUrl, indexJson, opts) {
|
|
16454
17451
|
db.prepare(`
|
|
@@ -16471,20 +17468,44 @@ function getRegistryIndexCache(db, registryUrl, maxAgeMs = 3600000) {
|
|
|
16471
17468
|
return;
|
|
16472
17469
|
return { indexJson: row.index_json, etag: row.etag, lastModified: row.last_modified };
|
|
16473
17470
|
}
|
|
17471
|
+
function collectTagSetFromEntries(db, entryType) {
|
|
17472
|
+
const tags = new Set;
|
|
17473
|
+
const stmt = entryType ? db.prepare("SELECT entry_json FROM entries WHERE entry_type = ?") : db.prepare("SELECT entry_json FROM entries");
|
|
17474
|
+
const rows = entryType ? stmt.all(entryType) : stmt.all();
|
|
17475
|
+
for (const row of rows) {
|
|
17476
|
+
let parsed;
|
|
17477
|
+
try {
|
|
17478
|
+
parsed = JSON.parse(row.entry_json);
|
|
17479
|
+
} catch {
|
|
17480
|
+
continue;
|
|
17481
|
+
}
|
|
17482
|
+
if (!Array.isArray(parsed.tags))
|
|
17483
|
+
continue;
|
|
17484
|
+
for (const tag of parsed.tags) {
|
|
17485
|
+
if (typeof tag === "string" && tag.trim().length > 0) {
|
|
17486
|
+
tags.add(tag.trim().toLowerCase());
|
|
17487
|
+
}
|
|
17488
|
+
}
|
|
17489
|
+
}
|
|
17490
|
+
return tags;
|
|
17491
|
+
}
|
|
16474
17492
|
var DB_VERSION = 17, EMBEDDING_DIM = 384, GRAPH_SCHEMA_VERSION = 3, vecStatus, VEC_DOCS_URL = "https://github.com/itlackey/akm/blob/main/docs/configuration.md#sqlite-vec-extension", VEC_FALLBACK_THRESHOLD = 1e4, vecInitWarnedDbs, SQLITE_CHUNK_SIZE = 500, upsertStmtsByDb, FEEDBACK_LR = 0.1, FEEDBACK_REWARD_POSITIVE = 1, FEEDBACK_REWARD_NEGATIVE = 0, MAX_NEG_DELTA_PER_CALL = 0.15, UTILITY_REVIEW_THRESHOLD = 0.5, HIGH_UTILITY_THRESHOLD = 0.5;
|
|
16475
17493
|
var init_db = __esm(() => {
|
|
16476
17494
|
init_asset_ref();
|
|
17495
|
+
init_best_effort();
|
|
16477
17496
|
init_paths();
|
|
16478
17497
|
init_state_db();
|
|
16479
17498
|
init_warn();
|
|
16480
17499
|
init_types();
|
|
17500
|
+
init_runtime();
|
|
17501
|
+
init_database();
|
|
16481
17502
|
init_db_backup();
|
|
16482
17503
|
vecStatus = new WeakMap;
|
|
16483
17504
|
vecInitWarnedDbs = new WeakSet;
|
|
16484
17505
|
upsertStmtsByDb = new WeakMap;
|
|
16485
17506
|
});
|
|
16486
17507
|
|
|
16487
|
-
// src/indexer/graph-db.ts
|
|
17508
|
+
// src/indexer/db/graph-db.ts
|
|
16488
17509
|
var exports_graph_db = {};
|
|
16489
17510
|
__export(exports_graph_db, {
|
|
16490
17511
|
resolveEntryIdForPath: () => resolveEntryIdForPath,
|
|
@@ -16496,12 +17517,12 @@ __export(exports_graph_db, {
|
|
|
16496
17517
|
loadGraphEntitiesByEntry: () => loadGraphEntitiesByEntry,
|
|
16497
17518
|
deleteStoredGraph: () => deleteStoredGraph
|
|
16498
17519
|
});
|
|
16499
|
-
import
|
|
17520
|
+
import fs13 from "fs";
|
|
16500
17521
|
function withReadableGraphDb(db, fn) {
|
|
16501
17522
|
if (db)
|
|
16502
17523
|
return fn(db);
|
|
16503
17524
|
const dbPath = getDbPath();
|
|
16504
|
-
if (!
|
|
17525
|
+
if (!fs13.existsSync(dbPath))
|
|
16505
17526
|
throw new Error("GRAPH_DB_MISSING");
|
|
16506
17527
|
const opened = openExistingDatabase(dbPath);
|
|
16507
17528
|
try {
|
|
@@ -16721,7 +17742,8 @@ function loadStoredGraphMeta(stashPath, db) {
|
|
|
16721
17742
|
cacheHits: row.cache_hits,
|
|
16722
17743
|
cacheMisses: row.cache_misses,
|
|
16723
17744
|
truncationCount: row.truncation_count,
|
|
16724
|
-
failureCount: row.failure_count
|
|
17745
|
+
failureCount: row.failure_count,
|
|
17746
|
+
retryAttempts: 0
|
|
16725
17747
|
}
|
|
16726
17748
|
};
|
|
16727
17749
|
} catch {
|
|
@@ -16821,10 +17843,17 @@ var init_graph_db = __esm(() => {
|
|
|
16821
17843
|
|
|
16822
17844
|
// scripts/migrate-storage.ts
|
|
16823
17845
|
init_paths();
|
|
16824
|
-
import
|
|
16825
|
-
import
|
|
16826
|
-
import
|
|
17846
|
+
import fs14 from "fs";
|
|
17847
|
+
import os3 from "os";
|
|
17848
|
+
import path12 from "path";
|
|
16827
17849
|
import readline from "readline";
|
|
17850
|
+
|
|
17851
|
+
// src/indexer/usage/unmigrated-vaults-guard.ts
|
|
17852
|
+
init_warn();
|
|
17853
|
+
var MIGRATED_MARKER = ".migrated";
|
|
17854
|
+
var warnedStashDirs = new Set;
|
|
17855
|
+
|
|
17856
|
+
// scripts/migrate-storage.ts
|
|
16828
17857
|
var args = process.argv.slice(2);
|
|
16829
17858
|
var DRY_RUN = args.includes("--dry-run");
|
|
16830
17859
|
var YES = args.includes("--yes");
|
|
@@ -16841,12 +17870,12 @@ function parseFromArg() {
|
|
|
16841
17870
|
return val;
|
|
16842
17871
|
}
|
|
16843
17872
|
var FROM_VERSION = parseFromArg();
|
|
16844
|
-
var dataDir = process.env.AKM_DATA_DIR?.trim() ?? (process.env.XDG_DATA_HOME?.trim() ?
|
|
16845
|
-
var stateDir = process.env.AKM_STATE_DIR?.trim() ?? (process.env.XDG_STATE_HOME?.trim() ?
|
|
17873
|
+
var dataDir = process.env.AKM_DATA_DIR?.trim() ?? (process.env.XDG_DATA_HOME?.trim() ? path12.join(process.env.XDG_DATA_HOME.trim(), "akm") : path12.join(os3.homedir(), ".local", "share", "akm"));
|
|
17874
|
+
var stateDir = process.env.AKM_STATE_DIR?.trim() ?? (process.env.XDG_STATE_HOME?.trim() ? path12.join(process.env.XDG_STATE_HOME.trim(), "akm") : path12.join(os3.homedir(), ".local", "state", "akm"));
|
|
16846
17875
|
var cacheDir = getCacheDir();
|
|
16847
17876
|
var configDir = getConfigDir();
|
|
16848
|
-
var stateDbPath =
|
|
16849
|
-
var indexDbPath =
|
|
17877
|
+
var stateDbPath = path12.join(dataDir, "state.db");
|
|
17878
|
+
var indexDbPath = path12.join(dataDir, "index.db");
|
|
16850
17879
|
var PATHS = {
|
|
16851
17880
|
cacheDir,
|
|
16852
17881
|
configDir,
|
|
@@ -16857,92 +17886,97 @@ var PATHS = {
|
|
|
16857
17886
|
};
|
|
16858
17887
|
var versionReports = [];
|
|
16859
17888
|
function ensureDir(dir) {
|
|
16860
|
-
if (!
|
|
16861
|
-
|
|
17889
|
+
if (!fs14.existsSync(dir)) {
|
|
17890
|
+
fs14.mkdirSync(dir, { recursive: true });
|
|
16862
17891
|
}
|
|
16863
17892
|
}
|
|
16864
17893
|
function copyAndVerify(src, dest) {
|
|
16865
|
-
|
|
16866
|
-
const srcStat =
|
|
16867
|
-
const destStat =
|
|
17894
|
+
fs14.copyFileSync(src, dest);
|
|
17895
|
+
const srcStat = fs14.statSync(src);
|
|
17896
|
+
const destStat = fs14.statSync(dest);
|
|
16868
17897
|
return destStat.size === srcStat.size;
|
|
16869
17898
|
}
|
|
16870
|
-
function
|
|
17899
|
+
function copyTree(src, dest, opts) {
|
|
16871
17900
|
let copied = 0;
|
|
17901
|
+
let skipped = 0;
|
|
16872
17902
|
let failed = 0;
|
|
16873
17903
|
ensureDir(dest);
|
|
16874
|
-
for (const entry of
|
|
16875
|
-
const srcEntry =
|
|
16876
|
-
const destEntry =
|
|
17904
|
+
for (const entry of fs14.readdirSync(src, { withFileTypes: true })) {
|
|
17905
|
+
const srcEntry = path12.join(src, entry.name);
|
|
17906
|
+
const destEntry = path12.join(dest, entry.name);
|
|
16877
17907
|
if (entry.isDirectory()) {
|
|
16878
|
-
const sub =
|
|
17908
|
+
const sub = copyTree(srcEntry, destEntry, opts);
|
|
16879
17909
|
copied += sub.copied;
|
|
17910
|
+
skipped += sub.skipped;
|
|
16880
17911
|
failed += sub.failed;
|
|
16881
|
-
|
|
16882
|
-
|
|
16883
|
-
|
|
16884
|
-
|
|
16885
|
-
|
|
16886
|
-
|
|
16887
|
-
|
|
16888
|
-
|
|
17912
|
+
continue;
|
|
17913
|
+
}
|
|
17914
|
+
if (!opts.clobber && fs14.existsSync(destEntry)) {
|
|
17915
|
+
skipped++;
|
|
17916
|
+
continue;
|
|
17917
|
+
}
|
|
17918
|
+
try {
|
|
17919
|
+
if (copyAndVerify(srcEntry, destEntry)) {
|
|
17920
|
+
copied++;
|
|
17921
|
+
} else {
|
|
16889
17922
|
failed++;
|
|
16890
17923
|
}
|
|
17924
|
+
} catch {
|
|
17925
|
+
failed++;
|
|
16891
17926
|
}
|
|
16892
17927
|
}
|
|
16893
|
-
return { copied, failed };
|
|
17928
|
+
return { copied, skipped, failed };
|
|
16894
17929
|
}
|
|
16895
17930
|
function countFilesRecursive(dir) {
|
|
16896
17931
|
let count = 0;
|
|
16897
|
-
for (const entry of
|
|
17932
|
+
for (const entry of fs14.readdirSync(dir, { withFileTypes: true })) {
|
|
16898
17933
|
if (entry.isDirectory()) {
|
|
16899
|
-
count += countFilesRecursive(
|
|
17934
|
+
count += countFilesRecursive(path12.join(dir, entry.name));
|
|
16900
17935
|
} else {
|
|
16901
17936
|
count++;
|
|
16902
17937
|
}
|
|
16903
17938
|
}
|
|
16904
17939
|
return count;
|
|
16905
17940
|
}
|
|
17941
|
+
async function runSteps(steps, ctx) {
|
|
17942
|
+
for (const step of steps) {
|
|
17943
|
+
ctx.recordStep(await step.run(ctx));
|
|
17944
|
+
}
|
|
17945
|
+
}
|
|
16906
17946
|
function migrateDb(ctx, filename) {
|
|
16907
|
-
const src =
|
|
16908
|
-
const dest =
|
|
16909
|
-
if (!
|
|
16910
|
-
|
|
16911
|
-
return;
|
|
17947
|
+
const src = path12.join(ctx.paths.cacheDir, filename);
|
|
17948
|
+
const dest = path12.join(ctx.paths.dataDir, filename);
|
|
17949
|
+
if (!fs14.existsSync(src)) {
|
|
17950
|
+
return { name: filename, status: "skipped", detail: "source not found" };
|
|
16912
17951
|
}
|
|
16913
|
-
if (
|
|
16914
|
-
|
|
16915
|
-
return;
|
|
17952
|
+
if (fs14.existsSync(dest)) {
|
|
17953
|
+
return { name: filename, status: "skipped", detail: "destination already exists" };
|
|
16916
17954
|
}
|
|
16917
17955
|
if (ctx.dryRun) {
|
|
16918
|
-
|
|
16919
|
-
return;
|
|
17956
|
+
return { name: filename, status: "success", detail: `[dry-run] would copy ${src} \u2192 ${dest}` };
|
|
16920
17957
|
}
|
|
16921
17958
|
ensureDir(ctx.paths.dataDir);
|
|
16922
17959
|
const ok = copyAndVerify(src, dest);
|
|
16923
17960
|
if (ok) {
|
|
16924
|
-
|
|
17961
|
+
return {
|
|
16925
17962
|
name: filename,
|
|
16926
17963
|
status: "success",
|
|
16927
17964
|
detail: `copied to ${dest} \u2014 source left at ${src} (delete manually when ready)`
|
|
16928
|
-
}
|
|
16929
|
-
} else {
|
|
16930
|
-
ctx.recordStep({ name: filename, status: "failed", detail: `size mismatch after copy: ${src} \u2192 ${dest}` });
|
|
17965
|
+
};
|
|
16931
17966
|
}
|
|
17967
|
+
return { name: filename, status: "failed", detail: `size mismatch after copy: ${src} \u2192 ${dest}` };
|
|
16932
17968
|
}
|
|
16933
17969
|
async function migrateEventsJsonl(ctx) {
|
|
16934
|
-
const src =
|
|
16935
|
-
if (!
|
|
16936
|
-
|
|
16937
|
-
return;
|
|
17970
|
+
const src = path12.join(ctx.paths.cacheDir, "events.jsonl");
|
|
17971
|
+
if (!fs14.existsSync(src)) {
|
|
17972
|
+
return { name: "events.jsonl \u2192 state.db", status: "skipped", detail: "source not found" };
|
|
16938
17973
|
}
|
|
16939
17974
|
if (ctx.dryRun) {
|
|
16940
|
-
|
|
17975
|
+
return {
|
|
16941
17976
|
name: "events.jsonl \u2192 state.db",
|
|
16942
17977
|
status: "success",
|
|
16943
17978
|
detail: `[dry-run] would import ${src} into ${ctx.paths.stateDbPath}`
|
|
16944
|
-
}
|
|
16945
|
-
return;
|
|
17979
|
+
};
|
|
16946
17980
|
}
|
|
16947
17981
|
try {
|
|
16948
17982
|
ensureDir(ctx.paths.dataDir);
|
|
@@ -16964,46 +17998,43 @@ async function migrateEventsJsonl(ctx) {
|
|
|
16964
17998
|
throw err;
|
|
16965
17999
|
}
|
|
16966
18000
|
const dedupNote = skipped > 0 ? ` (${skipped} duplicate(s) skipped \u2014 re-run idempotency)` : "";
|
|
16967
|
-
|
|
18001
|
+
return {
|
|
16968
18002
|
name: "events.jsonl \u2192 state.db",
|
|
16969
18003
|
status: "success",
|
|
16970
18004
|
detail: `imported ${imported} events (max id: ${maxId})${dedupNote} \u2014 source left at ${src} (delete manually when ready)`
|
|
16971
|
-
}
|
|
18005
|
+
};
|
|
16972
18006
|
} finally {
|
|
16973
18007
|
db.close();
|
|
16974
18008
|
}
|
|
16975
18009
|
} catch (err) {
|
|
16976
18010
|
const msg = err instanceof Error ? err.message : String(err);
|
|
16977
|
-
|
|
18011
|
+
return { name: "events.jsonl \u2192 state.db", status: "failed", detail: msg };
|
|
16978
18012
|
}
|
|
16979
18013
|
}
|
|
16980
18014
|
function migrateTaskHistory(ctx) {
|
|
16981
|
-
const src =
|
|
16982
|
-
const dest =
|
|
16983
|
-
if (!
|
|
16984
|
-
|
|
16985
|
-
return;
|
|
18015
|
+
const src = path12.join(ctx.paths.cacheDir, "tasks", "history");
|
|
18016
|
+
const dest = path12.join(ctx.paths.stateDir, "tasks", "history");
|
|
18017
|
+
if (!fs14.existsSync(src)) {
|
|
18018
|
+
return { name: "tasks/history/", status: "skipped", detail: "source directory not found" };
|
|
16986
18019
|
}
|
|
16987
18020
|
try {
|
|
16988
|
-
const files =
|
|
18021
|
+
const files = fs14.readdirSync(src).filter((f) => f.endsWith(".jsonl"));
|
|
16989
18022
|
if (files.length === 0) {
|
|
16990
|
-
|
|
16991
|
-
return;
|
|
18023
|
+
return { name: "tasks/history/", status: "skipped", detail: "no *.jsonl files found in source directory" };
|
|
16992
18024
|
}
|
|
16993
18025
|
if (ctx.dryRun) {
|
|
16994
|
-
|
|
18026
|
+
return {
|
|
16995
18027
|
name: "tasks/history/",
|
|
16996
18028
|
status: "success",
|
|
16997
18029
|
detail: `[dry-run] would copy ${files.length} *.jsonl file(s) from ${src} \u2192 ${dest}`
|
|
16998
|
-
}
|
|
16999
|
-
return;
|
|
18030
|
+
};
|
|
17000
18031
|
}
|
|
17001
18032
|
ensureDir(dest);
|
|
17002
18033
|
let copied = 0;
|
|
17003
18034
|
let failed = 0;
|
|
17004
18035
|
for (const file of files) {
|
|
17005
|
-
const srcFile =
|
|
17006
|
-
const destFile =
|
|
18036
|
+
const srcFile = path12.join(src, file);
|
|
18037
|
+
const destFile = path12.join(dest, file);
|
|
17007
18038
|
try {
|
|
17008
18039
|
if (copyAndVerify(srcFile, destFile)) {
|
|
17009
18040
|
copied++;
|
|
@@ -17015,119 +18046,107 @@ function migrateTaskHistory(ctx) {
|
|
|
17015
18046
|
}
|
|
17016
18047
|
}
|
|
17017
18048
|
if (failed === 0) {
|
|
17018
|
-
|
|
18049
|
+
return {
|
|
17019
18050
|
name: "tasks/history/",
|
|
17020
18051
|
status: "success",
|
|
17021
18052
|
detail: `copied ${copied} files to ${dest} \u2014 sources left in place (delete manually when ready)`
|
|
17022
|
-
}
|
|
17023
|
-
} else {
|
|
17024
|
-
ctx.recordStep({
|
|
17025
|
-
name: "tasks/history/",
|
|
17026
|
-
status: "failed",
|
|
17027
|
-
detail: `copied ${copied}/${files.length} files; ${failed} failed`
|
|
17028
|
-
});
|
|
18053
|
+
};
|
|
17029
18054
|
}
|
|
18055
|
+
return {
|
|
18056
|
+
name: "tasks/history/",
|
|
18057
|
+
status: "failed",
|
|
18058
|
+
detail: `copied ${copied}/${files.length} files; ${failed} failed`
|
|
18059
|
+
};
|
|
17030
18060
|
} catch (err) {
|
|
17031
18061
|
const msg = err instanceof Error ? err.message : String(err);
|
|
17032
|
-
|
|
18062
|
+
return { name: "tasks/history/", status: "failed", detail: msg };
|
|
17033
18063
|
}
|
|
17034
18064
|
}
|
|
17035
18065
|
function migrateLockfile(ctx) {
|
|
17036
|
-
const src =
|
|
17037
|
-
const dest =
|
|
17038
|
-
if (!
|
|
17039
|
-
|
|
17040
|
-
return;
|
|
18066
|
+
const src = path12.join(ctx.paths.configDir, "akm.lock");
|
|
18067
|
+
const dest = path12.join(ctx.paths.dataDir, "akm.lock");
|
|
18068
|
+
if (!fs14.existsSync(src)) {
|
|
18069
|
+
return { name: "akm.lock", status: "skipped", detail: "source not found" };
|
|
17041
18070
|
}
|
|
17042
|
-
if (
|
|
17043
|
-
|
|
17044
|
-
return;
|
|
18071
|
+
if (fs14.existsSync(dest)) {
|
|
18072
|
+
return { name: "akm.lock", status: "skipped", detail: "destination already exists" };
|
|
17045
18073
|
}
|
|
17046
18074
|
if (ctx.dryRun) {
|
|
17047
|
-
|
|
17048
|
-
return;
|
|
18075
|
+
return { name: "akm.lock", status: "success", detail: `[dry-run] would copy ${src} \u2192 ${dest}` };
|
|
17049
18076
|
}
|
|
17050
18077
|
ensureDir(ctx.paths.dataDir);
|
|
17051
18078
|
const ok = copyAndVerify(src, dest);
|
|
17052
18079
|
if (ok) {
|
|
17053
|
-
|
|
18080
|
+
return {
|
|
17054
18081
|
name: "akm.lock",
|
|
17055
18082
|
status: "success",
|
|
17056
18083
|
detail: `copied to ${dest} \u2014 source left at ${src}.
|
|
17057
18084
|
IMPORTANT: akm now reads ONLY from $DATA/akm.lock. If this step is skipped,
|
|
17058
18085
|
akm will start with an empty lockfile and 'akm add' will rebuild it from scratch.`
|
|
17059
|
-
}
|
|
17060
|
-
} else {
|
|
17061
|
-
ctx.recordStep({ name: "akm.lock", status: "failed", detail: `size mismatch after copy: ${src} \u2192 ${dest}` });
|
|
18086
|
+
};
|
|
17062
18087
|
}
|
|
18088
|
+
return { name: "akm.lock", status: "failed", detail: `size mismatch after copy: ${src} \u2192 ${dest}` };
|
|
17063
18089
|
}
|
|
17064
18090
|
function migrateConfigBackups(ctx) {
|
|
17065
|
-
const src =
|
|
17066
|
-
const dest =
|
|
17067
|
-
if (!
|
|
17068
|
-
|
|
17069
|
-
return;
|
|
18091
|
+
const src = path12.join(ctx.paths.cacheDir, "config-backups");
|
|
18092
|
+
const dest = path12.join(ctx.paths.dataDir, "config-backups");
|
|
18093
|
+
if (!fs14.existsSync(src)) {
|
|
18094
|
+
return { name: "config-backups/", status: "skipped", detail: "source directory not found" };
|
|
17070
18095
|
}
|
|
17071
|
-
if (
|
|
17072
|
-
|
|
17073
|
-
return;
|
|
18096
|
+
if (fs14.existsSync(dest)) {
|
|
18097
|
+
return { name: "config-backups/", status: "skipped", detail: "destination already exists" };
|
|
17074
18098
|
}
|
|
17075
18099
|
if (ctx.dryRun) {
|
|
17076
18100
|
let srcCount = 0;
|
|
17077
18101
|
try {
|
|
17078
18102
|
srcCount = countFilesRecursive(src);
|
|
17079
18103
|
} catch {}
|
|
17080
|
-
|
|
18104
|
+
return {
|
|
17081
18105
|
name: "config-backups/",
|
|
17082
18106
|
status: "success",
|
|
17083
18107
|
detail: `[dry-run] would recursively copy ${srcCount} file(s) from ${src} \u2192 ${dest}`
|
|
17084
|
-
}
|
|
17085
|
-
return;
|
|
18108
|
+
};
|
|
17086
18109
|
}
|
|
17087
18110
|
try {
|
|
17088
18111
|
const srcCount = countFilesRecursive(src);
|
|
17089
|
-
const { copied, failed } =
|
|
17090
|
-
const destCount =
|
|
18112
|
+
const { copied, failed } = copyTree(src, dest, { clobber: true });
|
|
18113
|
+
const destCount = fs14.existsSync(dest) ? countFilesRecursive(dest) : 0;
|
|
17091
18114
|
if (failed === 0 && destCount === srcCount) {
|
|
17092
|
-
|
|
18115
|
+
return {
|
|
17093
18116
|
name: "config-backups/",
|
|
17094
18117
|
status: "success",
|
|
17095
18118
|
detail: `copied ${copied} files to ${dest} \u2014 sources left in place (delete manually when ready)`
|
|
17096
|
-
}
|
|
17097
|
-
} else {
|
|
17098
|
-
ctx.recordStep({
|
|
17099
|
-
name: "config-backups/",
|
|
17100
|
-
status: "failed",
|
|
17101
|
-
detail: `file count mismatch: source ${srcCount}, destination ${destCount}; ${failed} copy errors`
|
|
17102
|
-
});
|
|
18119
|
+
};
|
|
17103
18120
|
}
|
|
18121
|
+
return {
|
|
18122
|
+
name: "config-backups/",
|
|
18123
|
+
status: "failed",
|
|
18124
|
+
detail: `file count mismatch: source ${srcCount}, destination ${destCount}; ${failed} copy errors`
|
|
18125
|
+
};
|
|
17104
18126
|
} catch (err) {
|
|
17105
18127
|
const msg = err instanceof Error ? err.message : String(err);
|
|
17106
|
-
|
|
18128
|
+
return { name: "config-backups/", status: "failed", detail: msg };
|
|
17107
18129
|
}
|
|
17108
18130
|
}
|
|
17109
18131
|
async function migrateTaskHistoryToDb(ctx) {
|
|
17110
|
-
const src =
|
|
17111
|
-
if (!
|
|
17112
|
-
|
|
17113
|
-
return;
|
|
18132
|
+
const src = path12.join(ctx.paths.cacheDir, "tasks", "history");
|
|
18133
|
+
if (!fs14.existsSync(src)) {
|
|
18134
|
+
return { name: "tasks/history/ \u2192 state.db", status: "skipped", detail: "source directory not found" };
|
|
17114
18135
|
}
|
|
17115
|
-
const files =
|
|
18136
|
+
const files = fs14.readdirSync(src).filter((f) => f.endsWith(".jsonl"));
|
|
17116
18137
|
if (files.length === 0) {
|
|
17117
|
-
|
|
18138
|
+
return {
|
|
17118
18139
|
name: "tasks/history/ \u2192 state.db",
|
|
17119
18140
|
status: "skipped",
|
|
17120
18141
|
detail: "no *.jsonl files found in source directory"
|
|
17121
|
-
}
|
|
17122
|
-
return;
|
|
18142
|
+
};
|
|
17123
18143
|
}
|
|
17124
18144
|
if (ctx.dryRun) {
|
|
17125
|
-
|
|
18145
|
+
return {
|
|
17126
18146
|
name: "tasks/history/ \u2192 state.db",
|
|
17127
18147
|
status: "success",
|
|
17128
18148
|
detail: `[dry-run] would parse ${files.length} *.jsonl file(s) and import rows into ${ctx.paths.stateDbPath}`
|
|
17129
|
-
}
|
|
17130
|
-
return;
|
|
18149
|
+
};
|
|
17131
18150
|
}
|
|
17132
18151
|
try {
|
|
17133
18152
|
ensureDir(ctx.paths.dataDir);
|
|
@@ -17137,8 +18156,8 @@ async function migrateTaskHistoryToDb(ctx) {
|
|
|
17137
18156
|
let failed = 0;
|
|
17138
18157
|
try {
|
|
17139
18158
|
for (const file of files) {
|
|
17140
|
-
const filePath =
|
|
17141
|
-
const text =
|
|
18159
|
+
const filePath = path12.join(src, file);
|
|
18160
|
+
const text = fs14.readFileSync(filePath, "utf8");
|
|
17142
18161
|
const lines = text.split(`
|
|
17143
18162
|
`).filter((l) => l.trim().length > 0);
|
|
17144
18163
|
db.exec("BEGIN");
|
|
@@ -17180,33 +18199,30 @@ async function migrateTaskHistoryToDb(ctx) {
|
|
|
17180
18199
|
db.close();
|
|
17181
18200
|
}
|
|
17182
18201
|
if (failed === 0) {
|
|
17183
|
-
|
|
18202
|
+
return {
|
|
17184
18203
|
name: "tasks/history/ \u2192 state.db",
|
|
17185
18204
|
status: "success",
|
|
17186
18205
|
detail: `imported ${imported} task history row(s) from ${files.length} JSONL file(s) into state.db \u2014 sources left in place (delete manually when ready)`
|
|
17187
|
-
}
|
|
17188
|
-
} else {
|
|
17189
|
-
ctx.recordStep({
|
|
17190
|
-
name: "tasks/history/ \u2192 state.db",
|
|
17191
|
-
status: "failed",
|
|
17192
|
-
detail: `imported ${imported} row(s); ${failed} line(s) could not be parsed`
|
|
17193
|
-
});
|
|
18206
|
+
};
|
|
17194
18207
|
}
|
|
18208
|
+
return {
|
|
18209
|
+
name: "tasks/history/ \u2192 state.db",
|
|
18210
|
+
status: "failed",
|
|
18211
|
+
detail: `imported ${imported} row(s); ${failed} line(s) could not be parsed`
|
|
18212
|
+
};
|
|
17195
18213
|
} catch (err) {
|
|
17196
18214
|
const msg = err instanceof Error ? err.message : String(err);
|
|
17197
|
-
|
|
18215
|
+
return { name: "tasks/history/ \u2192 state.db", status: "failed", detail: msg };
|
|
17198
18216
|
}
|
|
17199
18217
|
}
|
|
17200
18218
|
function noteRegistryIndexCache(ctx) {
|
|
17201
|
-
const src =
|
|
17202
|
-
if (!
|
|
17203
|
-
|
|
17204
|
-
return;
|
|
18219
|
+
const src = path12.join(ctx.paths.cacheDir, "registry-index");
|
|
18220
|
+
if (!fs14.existsSync(src)) {
|
|
18221
|
+
return { name: "registry-index/ (note)", status: "skipped", detail: "no old $CACHE/registry-index/ directory found" };
|
|
17205
18222
|
}
|
|
17206
|
-
const legacyFiles =
|
|
18223
|
+
const legacyFiles = fs14.readdirSync(src).filter((f) => f.endsWith(".json") && !f.startsWith("website-"));
|
|
17207
18224
|
if (legacyFiles.length === 0) {
|
|
17208
|
-
|
|
17209
|
-
return;
|
|
18225
|
+
return { name: "registry-index/ (note)", status: "skipped", detail: "no old *.json cache files found" };
|
|
17210
18226
|
}
|
|
17211
18227
|
if (!ctx.dryRun) {
|
|
17212
18228
|
console.log(`
|
|
@@ -17214,57 +18230,57 @@ function noteRegistryIndexCache(ctx) {
|
|
|
17214
18230
|
These are ignored in v0.9 \u2014 data is now stored in the registry_index_cache` + `
|
|
17215
18231
|
table in $DATA/index.db and will be rebuilt on next 'akm registry search'.
|
|
17216
18232
|
You may safely delete these files after migration:
|
|
17217
|
-
` + legacyFiles.map((f) => ` ${
|
|
18233
|
+
` + legacyFiles.map((f) => ` ${path12.join(src, f)}`).join(`
|
|
17218
18234
|
`));
|
|
17219
18235
|
}
|
|
17220
|
-
|
|
18236
|
+
return {
|
|
17221
18237
|
name: "registry-index/ (note)",
|
|
17222
18238
|
status: "success",
|
|
17223
18239
|
detail: `${legacyFiles.length} old file(s) noted at ${src} \u2014 registry index cache will be rebuilt on next ` + `'akm registry search'. Safe to delete: ${src}/*.json`
|
|
17224
|
-
}
|
|
18240
|
+
};
|
|
17225
18241
|
}
|
|
17226
18242
|
var v07To08Migration = {
|
|
17227
18243
|
label: "0.7 \u2192 0.8",
|
|
17228
18244
|
sourceVersion: "0.7",
|
|
17229
18245
|
isNeeded: (paths) => {
|
|
17230
18246
|
const candidates = [
|
|
17231
|
-
|
|
17232
|
-
|
|
17233
|
-
|
|
17234
|
-
|
|
17235
|
-
|
|
17236
|
-
|
|
17237
|
-
|
|
18247
|
+
path12.join(paths.cacheDir, "index.db"),
|
|
18248
|
+
path12.join(paths.cacheDir, "workflow.db"),
|
|
18249
|
+
path12.join(paths.cacheDir, "events.jsonl"),
|
|
18250
|
+
path12.join(paths.cacheDir, "tasks", "history"),
|
|
18251
|
+
path12.join(paths.configDir, "akm.lock"),
|
|
18252
|
+
path12.join(paths.cacheDir, "config-backups"),
|
|
18253
|
+
path12.join(paths.cacheDir, "registry-index")
|
|
17238
18254
|
];
|
|
17239
|
-
return candidates.some((p) =>
|
|
18255
|
+
return candidates.some((p) => fs14.existsSync(p));
|
|
17240
18256
|
},
|
|
17241
|
-
|
|
17242
|
-
migrateDb(ctx, "index.db")
|
|
17243
|
-
migrateDb(ctx, "workflow.db")
|
|
17244
|
-
|
|
17245
|
-
migrateTaskHistory
|
|
17246
|
-
migrateLockfile
|
|
17247
|
-
migrateConfigBackups
|
|
17248
|
-
|
|
17249
|
-
|
|
17250
|
-
|
|
18257
|
+
steps: [
|
|
18258
|
+
{ id: "index-db", title: "index.db", run: (ctx) => migrateDb(ctx, "index.db") },
|
|
18259
|
+
{ id: "workflow-db", title: "workflow.db", run: (ctx) => migrateDb(ctx, "workflow.db") },
|
|
18260
|
+
{ id: "events-jsonl", title: "events.jsonl \u2192 state.db", run: migrateEventsJsonl },
|
|
18261
|
+
{ id: "tasks-history-files", title: "tasks/history/", run: migrateTaskHistory },
|
|
18262
|
+
{ id: "lockfile", title: "akm.lock", run: migrateLockfile },
|
|
18263
|
+
{ id: "config-backups", title: "config-backups/", run: migrateConfigBackups },
|
|
18264
|
+
{ id: "tasks-history-db", title: "tasks/history/ \u2192 state.db", run: migrateTaskHistoryToDb },
|
|
18265
|
+
{ id: "registry-index-note", title: "registry-index/ (note)", run: noteRegistryIndexCache }
|
|
18266
|
+
]
|
|
17251
18267
|
};
|
|
17252
18268
|
function legacyGraphCandidatePaths(ctx) {
|
|
17253
18269
|
return [
|
|
17254
|
-
|
|
17255
|
-
|
|
17256
|
-
|
|
18270
|
+
path12.join(ctx.paths.cacheDir, "graph-snapshot.json"),
|
|
18271
|
+
path12.join(ctx.paths.dataDir, "graph-snapshot.json"),
|
|
18272
|
+
path12.join(ctx.paths.dataDir, "graph-export.json")
|
|
17257
18273
|
];
|
|
17258
18274
|
}
|
|
17259
18275
|
function findLegacyGraphFile(ctx) {
|
|
17260
18276
|
for (const candidate of legacyGraphCandidatePaths(ctx)) {
|
|
17261
|
-
if (
|
|
18277
|
+
if (fs14.existsSync(candidate) && fs14.statSync(candidate).isFile())
|
|
17262
18278
|
return candidate;
|
|
17263
18279
|
}
|
|
17264
|
-
const graphDir =
|
|
17265
|
-
if (
|
|
18280
|
+
const graphDir = path12.join(ctx.paths.cacheDir, "graph");
|
|
18281
|
+
if (fs14.existsSync(graphDir) && fs14.statSync(graphDir).isDirectory()) {
|
|
17266
18282
|
try {
|
|
17267
|
-
const json =
|
|
18283
|
+
const json = fs14.readdirSync(graphDir).filter((f) => f.endsWith(".json")).map((f) => path12.join(graphDir, f));
|
|
17268
18284
|
if (json.length > 0)
|
|
17269
18285
|
return json[0];
|
|
17270
18286
|
} catch {}
|
|
@@ -17298,43 +18314,38 @@ async function migrateGraphFileToDb(ctx) {
|
|
|
17298
18314
|
const name = "Graph snapshot import";
|
|
17299
18315
|
const legacyFile = findLegacyGraphFile(ctx);
|
|
17300
18316
|
if (!legacyFile) {
|
|
17301
|
-
|
|
17302
|
-
return;
|
|
18317
|
+
return { name, status: "skipped", detail: "no legacy graph file found" };
|
|
17303
18318
|
}
|
|
17304
|
-
if (!
|
|
17305
|
-
|
|
18319
|
+
if (!fs14.existsSync(ctx.paths.indexDbPath)) {
|
|
18320
|
+
return {
|
|
17306
18321
|
name,
|
|
17307
18322
|
status: "skipped",
|
|
17308
18323
|
detail: `index.db not found at ${ctx.paths.indexDbPath}; run akm to initialize, then re-run this migration`
|
|
17309
|
-
}
|
|
17310
|
-
return;
|
|
18324
|
+
};
|
|
17311
18325
|
}
|
|
17312
18326
|
if (ctx.dryRun) {
|
|
17313
|
-
|
|
18327
|
+
return {
|
|
17314
18328
|
name,
|
|
17315
18329
|
status: "success",
|
|
17316
18330
|
detail: `[dry-run] would parse ${legacyFile} and import into ${ctx.paths.indexDbPath} graph tables`
|
|
17317
|
-
}
|
|
17318
|
-
return;
|
|
18331
|
+
};
|
|
17319
18332
|
}
|
|
17320
18333
|
try {
|
|
17321
|
-
const raw =
|
|
18334
|
+
const raw = fs14.readFileSync(legacyFile, "utf8");
|
|
17322
18335
|
let parsed;
|
|
17323
18336
|
try {
|
|
17324
18337
|
parsed = JSON.parse(raw);
|
|
17325
18338
|
} catch (err) {
|
|
17326
18339
|
const msg = err instanceof Error ? err.message : String(err);
|
|
17327
|
-
|
|
17328
|
-
return;
|
|
18340
|
+
return { name, status: "failed", detail: `${legacyFile} is not valid JSON: ${msg}` };
|
|
17329
18341
|
}
|
|
17330
18342
|
const validation = validateGraphSnapshot(parsed);
|
|
17331
18343
|
if (!validation.ok) {
|
|
17332
|
-
|
|
18344
|
+
return {
|
|
17333
18345
|
name,
|
|
17334
18346
|
status: "failed",
|
|
17335
18347
|
detail: `${legacyFile} does not match expected GraphSnapshot shape: ${validation.reason}`
|
|
17336
|
-
}
|
|
17337
|
-
return;
|
|
18348
|
+
};
|
|
17338
18349
|
}
|
|
17339
18350
|
const snapshot = validation.data;
|
|
17340
18351
|
const { openExistingDatabase: openExistingDatabase2, closeDatabase: closeDatabase2 } = await Promise.resolve().then(() => (init_db(), exports_db));
|
|
@@ -17382,51 +18393,48 @@ async function migrateGraphFileToDb(ctx) {
|
|
|
17382
18393
|
const importedCount = db.prepare("SELECT COUNT(*) AS cnt FROM graph_files WHERE stash_root = ?").get(snapshot.stashRoot).cnt;
|
|
17383
18394
|
const meta = loadStoredGraphMeta2(snapshot.stashRoot, db);
|
|
17384
18395
|
if (!meta) {
|
|
17385
|
-
|
|
18396
|
+
return {
|
|
17386
18397
|
name,
|
|
17387
18398
|
status: "failed",
|
|
17388
18399
|
detail: `import did not produce a graph_meta row for stash ${snapshot.stashRoot}`
|
|
17389
|
-
}
|
|
17390
|
-
return;
|
|
18400
|
+
};
|
|
17391
18401
|
}
|
|
17392
18402
|
if (importedCount === 0) {
|
|
17393
|
-
|
|
18403
|
+
return {
|
|
17394
18404
|
name,
|
|
17395
18405
|
status: "failed",
|
|
17396
18406
|
detail: `import produced zero graph_files rows for stash ${snapshot.stashRoot} \u2014 ` + `the entries table has no matching paths. Run "akm index" first, then retry the migration. Source file ${legacyFile} was NOT renamed.`
|
|
17397
|
-
}
|
|
17398
|
-
return;
|
|
18407
|
+
};
|
|
17399
18408
|
}
|
|
17400
18409
|
const renamed = `${legacyFile}.migrated`;
|
|
17401
18410
|
try {
|
|
17402
|
-
|
|
18411
|
+
fs14.renameSync(legacyFile, renamed);
|
|
17403
18412
|
} catch (err) {
|
|
17404
18413
|
const msg = err instanceof Error ? err.message : String(err);
|
|
17405
|
-
|
|
18414
|
+
return {
|
|
17406
18415
|
name,
|
|
17407
18416
|
status: "success",
|
|
17408
18417
|
detail: `imported graph for ${snapshot.stashRoot} into ${ctx.paths.indexDbPath} but could not rename ${legacyFile}: ${msg}`
|
|
17409
|
-
}
|
|
17410
|
-
return;
|
|
18418
|
+
};
|
|
17411
18419
|
}
|
|
17412
|
-
|
|
18420
|
+
return {
|
|
17413
18421
|
name,
|
|
17414
18422
|
status: "success",
|
|
17415
18423
|
detail: `imported graph snapshot from ${legacyFile} into ${ctx.paths.indexDbPath} (stash ${snapshot.stashRoot}; ${importedCount} file(s) imported of ${graph.files.length} in source). Source renamed to ${renamed} \u2014 delete manually when ready.`
|
|
17416
|
-
}
|
|
18424
|
+
};
|
|
17417
18425
|
} finally {
|
|
17418
18426
|
closeDatabase2(db);
|
|
17419
18427
|
}
|
|
17420
18428
|
} catch (err) {
|
|
17421
18429
|
const msg = err instanceof Error ? err.message : String(err);
|
|
17422
|
-
|
|
18430
|
+
return { name, status: "failed", detail: msg };
|
|
17423
18431
|
}
|
|
17424
18432
|
}
|
|
17425
18433
|
function resolvePrimaryStashDir(configDirPath) {
|
|
17426
18434
|
try {
|
|
17427
|
-
const cfgPath =
|
|
17428
|
-
if (
|
|
17429
|
-
const cfg = JSON.parse(
|
|
18435
|
+
const cfgPath = path12.join(configDirPath, "config.json");
|
|
18436
|
+
if (fs14.existsSync(cfgPath)) {
|
|
18437
|
+
const cfg = JSON.parse(fs14.readFileSync(cfgPath, "utf8"));
|
|
17430
18438
|
if (typeof cfg.stashDir === "string" && cfg.stashDir.length > 0)
|
|
17431
18439
|
return cfg.stashDir;
|
|
17432
18440
|
}
|
|
@@ -17435,8 +18443,8 @@ function resolvePrimaryStashDir(configDirPath) {
|
|
|
17435
18443
|
}
|
|
17436
18444
|
function countEnvFilesRecursive(dir) {
|
|
17437
18445
|
let count = 0;
|
|
17438
|
-
for (const entry of
|
|
17439
|
-
const full =
|
|
18446
|
+
for (const entry of fs14.readdirSync(dir, { withFileTypes: true })) {
|
|
18447
|
+
const full = path12.join(dir, entry.name);
|
|
17440
18448
|
if (entry.isDirectory()) {
|
|
17441
18449
|
count += countEnvFilesRecursive(full);
|
|
17442
18450
|
} else if (entry.name === ".env" || entry.name.endsWith(".env")) {
|
|
@@ -17445,46 +18453,16 @@ function countEnvFilesRecursive(dir) {
|
|
|
17445
18453
|
}
|
|
17446
18454
|
return count;
|
|
17447
18455
|
}
|
|
17448
|
-
function copyDirNoClobber(src, dest) {
|
|
17449
|
-
let copied = 0;
|
|
17450
|
-
let skipped = 0;
|
|
17451
|
-
let failed = 0;
|
|
17452
|
-
ensureDir(dest);
|
|
17453
|
-
for (const entry of fs12.readdirSync(src, { withFileTypes: true })) {
|
|
17454
|
-
const srcEntry = path10.join(src, entry.name);
|
|
17455
|
-
const destEntry = path10.join(dest, entry.name);
|
|
17456
|
-
if (entry.isDirectory()) {
|
|
17457
|
-
const sub = copyDirNoClobber(srcEntry, destEntry);
|
|
17458
|
-
copied += sub.copied;
|
|
17459
|
-
skipped += sub.skipped;
|
|
17460
|
-
failed += sub.failed;
|
|
17461
|
-
continue;
|
|
17462
|
-
}
|
|
17463
|
-
if (fs12.existsSync(destEntry)) {
|
|
17464
|
-
skipped++;
|
|
17465
|
-
continue;
|
|
17466
|
-
}
|
|
17467
|
-
try {
|
|
17468
|
-
if (copyAndVerify(srcEntry, destEntry))
|
|
17469
|
-
copied++;
|
|
17470
|
-
else
|
|
17471
|
-
failed++;
|
|
17472
|
-
} catch {
|
|
17473
|
-
failed++;
|
|
17474
|
-
}
|
|
17475
|
-
}
|
|
17476
|
-
return { copied, skipped, failed };
|
|
17477
|
-
}
|
|
17478
18456
|
function chmodTreeSecure(dir) {
|
|
17479
18457
|
const isWin = process.platform === "win32";
|
|
17480
18458
|
try {
|
|
17481
|
-
|
|
18459
|
+
fs14.chmodSync(dir, 448);
|
|
17482
18460
|
} catch (err) {
|
|
17483
18461
|
if (!isWin)
|
|
17484
18462
|
return { ok: false, detail: `chmod 0700 ${dir} failed: ${err instanceof Error ? err.message : err}` };
|
|
17485
18463
|
}
|
|
17486
|
-
for (const entry of
|
|
17487
|
-
const full =
|
|
18464
|
+
for (const entry of fs14.readdirSync(dir, { withFileTypes: true })) {
|
|
18465
|
+
const full = path12.join(dir, entry.name);
|
|
17488
18466
|
if (entry.isDirectory()) {
|
|
17489
18467
|
const sub = chmodTreeSecure(full);
|
|
17490
18468
|
if (!sub.ok)
|
|
@@ -17492,8 +18470,8 @@ function chmodTreeSecure(dir) {
|
|
|
17492
18470
|
continue;
|
|
17493
18471
|
}
|
|
17494
18472
|
try {
|
|
17495
|
-
|
|
17496
|
-
if (!isWin && (
|
|
18473
|
+
fs14.chmodSync(full, 384);
|
|
18474
|
+
if (!isWin && (fs14.statSync(full).mode & 511) !== 384) {
|
|
17497
18475
|
return { ok: false, detail: `mode verification failed for ${full}` };
|
|
17498
18476
|
}
|
|
17499
18477
|
} catch (err) {
|
|
@@ -17506,59 +18484,52 @@ function chmodTreeSecure(dir) {
|
|
|
17506
18484
|
async function migrateVaultsToEnv(ctx) {
|
|
17507
18485
|
const name = "vaults/ \u2192 env/";
|
|
17508
18486
|
const stashDir = resolvePrimaryStashDir(ctx.paths.configDir);
|
|
17509
|
-
const vaultsDir =
|
|
17510
|
-
const envDir =
|
|
17511
|
-
const marker =
|
|
17512
|
-
if (!
|
|
17513
|
-
|
|
17514
|
-
return;
|
|
18487
|
+
const vaultsDir = path12.join(stashDir, "vaults");
|
|
18488
|
+
const envDir = path12.join(stashDir, "env");
|
|
18489
|
+
const marker = path12.join(vaultsDir, MIGRATED_MARKER);
|
|
18490
|
+
if (!fs14.existsSync(vaultsDir)) {
|
|
18491
|
+
return { name, status: "skipped", detail: `no vaults/ directory under ${stashDir}` };
|
|
17515
18492
|
}
|
|
17516
|
-
if (
|
|
17517
|
-
|
|
17518
|
-
return;
|
|
18493
|
+
if (fs14.existsSync(marker)) {
|
|
18494
|
+
return { name, status: "skipped", detail: "already migrated (.migrated marker present)" };
|
|
17519
18495
|
}
|
|
17520
18496
|
const vaultEnvCount = countEnvFilesRecursive(vaultsDir);
|
|
17521
18497
|
if (vaultEnvCount === 0) {
|
|
17522
|
-
|
|
17523
|
-
return;
|
|
18498
|
+
return { name, status: "skipped", detail: "vaults/ has no .env files to migrate" };
|
|
17524
18499
|
}
|
|
17525
18500
|
if (ctx.dryRun) {
|
|
17526
|
-
|
|
18501
|
+
return {
|
|
17527
18502
|
name,
|
|
17528
18503
|
status: "success",
|
|
17529
18504
|
detail: `[dry-run] would copy ${vaultEnvCount} .env file(s) ${vaultsDir} \u2192 ${envDir}, chmod 0600/0700, and write ${marker}`
|
|
17530
|
-
}
|
|
17531
|
-
return;
|
|
18505
|
+
};
|
|
17532
18506
|
}
|
|
17533
18507
|
try {
|
|
17534
|
-
const { copied, skipped, failed } =
|
|
18508
|
+
const { copied, skipped, failed } = copyTree(vaultsDir, envDir, { clobber: false });
|
|
17535
18509
|
if (failed > 0) {
|
|
17536
|
-
|
|
17537
|
-
return;
|
|
18510
|
+
return { name, status: "failed", detail: `${failed} file(s) failed to copy; env/ left as-is, no marker written` };
|
|
17538
18511
|
}
|
|
17539
18512
|
const chmodRes = chmodTreeSecure(envDir);
|
|
17540
18513
|
if (!chmodRes.ok) {
|
|
17541
|
-
|
|
17542
|
-
return;
|
|
18514
|
+
return { name, status: "failed", detail: chmodRes.detail ?? "permission tightening failed" };
|
|
17543
18515
|
}
|
|
17544
18516
|
const envEnvCount = countEnvFilesRecursive(envDir);
|
|
17545
18517
|
if (envEnvCount < vaultEnvCount) {
|
|
17546
|
-
|
|
18518
|
+
return {
|
|
17547
18519
|
name,
|
|
17548
18520
|
status: "failed",
|
|
17549
18521
|
detail: `post-copy count ${envEnvCount} < source ${vaultEnvCount}; no marker written`
|
|
17550
|
-
}
|
|
17551
|
-
return;
|
|
18522
|
+
};
|
|
17552
18523
|
}
|
|
17553
|
-
|
|
18524
|
+
fs14.writeFileSync(marker, `migrated vaults/ -> env/ at ${new Date().toISOString()}
|
|
17554
18525
|
`, { mode: 384 });
|
|
17555
|
-
|
|
18526
|
+
return {
|
|
17556
18527
|
name,
|
|
17557
18528
|
status: "success",
|
|
17558
18529
|
detail: `copied ${copied} file(s) (${skipped} already present in env/, preserved) ${vaultsDir} \u2192 ${envDir}; vaults/ left intact as a frozen copy. Run \`akm index\` to refresh search.`
|
|
17559
|
-
}
|
|
18530
|
+
};
|
|
17560
18531
|
} catch (err) {
|
|
17561
|
-
|
|
18532
|
+
return { name, status: "failed", detail: err instanceof Error ? err.message : String(err) };
|
|
17562
18533
|
}
|
|
17563
18534
|
}
|
|
17564
18535
|
var v08To09Migration = {
|
|
@@ -17567,10 +18538,10 @@ var v08To09Migration = {
|
|
|
17567
18538
|
isNeeded: (_paths) => {
|
|
17568
18539
|
return true;
|
|
17569
18540
|
},
|
|
17570
|
-
|
|
17571
|
-
|
|
17572
|
-
|
|
17573
|
-
|
|
18541
|
+
steps: [
|
|
18542
|
+
{ id: "graph-snapshot-import", title: "Graph snapshot import", run: migrateGraphFileToDb },
|
|
18543
|
+
{ id: "vaults-to-env", title: "vaults/ \u2192 env/", run: migrateVaultsToEnv }
|
|
18544
|
+
]
|
|
17574
18545
|
};
|
|
17575
18546
|
var MIGRATIONS2 = [v07To08Migration, v08To09Migration];
|
|
17576
18547
|
async function confirm() {
|
|
@@ -17656,12 +18627,12 @@ task_history: task_id PK).
|
|
|
17656
18627
|
Migration complete. No errors.`);
|
|
17657
18628
|
console.log(`
|
|
17658
18629
|
Old files at the original locations are safe to delete manually after verifying akm works:
|
|
17659
|
-
${
|
|
17660
|
-
${
|
|
17661
|
-
${
|
|
17662
|
-
${
|
|
17663
|
-
${
|
|
17664
|
-
${
|
|
18630
|
+
${path12.join(cacheDir, "index.db")}
|
|
18631
|
+
${path12.join(cacheDir, "workflow.db")}
|
|
18632
|
+
${path12.join(cacheDir, "events.jsonl")}
|
|
18633
|
+
${path12.join(cacheDir, "tasks", "history")}
|
|
18634
|
+
${path12.join(cacheDir, "config-backups")}
|
|
18635
|
+
${path12.join(configDir, "akm.lock")}
|
|
17665
18636
|
|
|
17666
18637
|
Next step \u2014 repopulate graph data (if migrating from 0.7):
|
|
17667
18638
|
The 0.8.0 graph schema redesign (DB_VERSION 12 \u2192 13) rebuilds the graph
|
|
@@ -17673,7 +18644,7 @@ Next step \u2014 repopulate graph data (if migrating from 0.7):
|
|
|
17673
18644
|
docs/migration/v0.7-to-v0.8.md#graph-extraction-will-re-run-after-upgrade.
|
|
17674
18645
|
`);
|
|
17675
18646
|
}
|
|
17676
|
-
async function
|
|
18647
|
+
async function runMigrations3(opts = { dryRun: DRY_RUN }) {
|
|
17677
18648
|
const paths = opts.paths ?? PATHS;
|
|
17678
18649
|
const reports = [];
|
|
17679
18650
|
const migrations = filteredMigrations();
|
|
@@ -17702,7 +18673,7 @@ async function runMigrations2(opts = { dryRun: DRY_RUN }) {
|
|
|
17702
18673
|
continue;
|
|
17703
18674
|
}
|
|
17704
18675
|
try {
|
|
17705
|
-
await migration.
|
|
18676
|
+
await runSteps(migration.steps, ctx);
|
|
17706
18677
|
reports.push({ label: migration.label, ran: true, results: stepResults });
|
|
17707
18678
|
} catch (err) {
|
|
17708
18679
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -17741,7 +18712,7 @@ async function main() {
|
|
|
17741
18712
|
console.log(`[dry-run] No changes will be written.
|
|
17742
18713
|
`);
|
|
17743
18714
|
}
|
|
17744
|
-
const reports = await
|
|
18715
|
+
const reports = await runMigrations3({ dryRun: DRY_RUN, paths: PATHS });
|
|
17745
18716
|
versionReports.push(...reports);
|
|
17746
18717
|
printGroupedSummary();
|
|
17747
18718
|
if (DRY_RUN) {
|
|
@@ -17754,7 +18725,7 @@ var invokedDirectly = (() => {
|
|
|
17754
18725
|
if (!entry)
|
|
17755
18726
|
return false;
|
|
17756
18727
|
const here = new URL(import.meta.url).pathname;
|
|
17757
|
-
return
|
|
18728
|
+
return path12.resolve(entry) === here;
|
|
17758
18729
|
} catch {
|
|
17759
18730
|
return false;
|
|
17760
18731
|
}
|
|
@@ -17763,6 +18734,6 @@ if (invokedDirectly) {
|
|
|
17763
18734
|
await main();
|
|
17764
18735
|
}
|
|
17765
18736
|
export {
|
|
17766
|
-
|
|
18737
|
+
runMigrations3 as runMigrations,
|
|
17767
18738
|
MIGRATIONS2 as MIGRATIONS
|
|
17768
18739
|
};
|