akm-cli 0.8.2 → 0.9.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +187 -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/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 +51 -14
- package/dist/cli-node.mjs +26 -0
- package/dist/cli.js +171 -3862
- 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 +240 -3
- package/dist/commands/config-edit.js +344 -0
- 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.js +94 -262
- package/dist/commands/{consolidate.js → improve/consolidate.js} +48 -36
- 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} +185 -26
- package/dist/commands/{improve-auto-accept.js → improve/improve-auto-accept.js} +4 -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} +509 -245
- 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/{reflect.js → improve/reflect.js} +33 -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 +15 -10
- package/dist/commands/proposal/proposal-cli.js +478 -0
- package/dist/commands/{proposal.js → proposal/proposal.js} +5 -5
- 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 +13 -7
- 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 +8 -8
- 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} +45 -1
- 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/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 +88 -46
- 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} +126 -116
- 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} +92 -23
- 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} +16 -1
- 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 +131 -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/output/context.js +6 -44
- 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 +2 -4
- 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 +54 -39
- 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 +1594 -673
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +240 -166
- 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 +28 -15
- 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 +50 -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 +16 -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,55 +8766,58 @@ 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
|
|
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) {
|
|
8812
8821
|
db.exec(`
|
|
8813
8822
|
CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
8814
8823
|
id TEXT PRIMARY KEY,
|
|
@@ -8816,11 +8825,12 @@ function ensureMigrationsTable(db) {
|
|
|
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,99 @@ 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
|
+
readStateEvents: () => readStateEvents,
|
|
8892
|
+
queryTaskHistory: () => queryTaskHistory,
|
|
8893
|
+
queryImproveRuns: () => queryImproveRuns,
|
|
8894
|
+
queryCompletedTaskIntervals: () => queryCompletedTaskIntervals,
|
|
8895
|
+
purgeOldImproveRuns: () => purgeOldImproveRuns,
|
|
8896
|
+
purgeOldEvents: () => purgeOldEvents,
|
|
8897
|
+
proposalToRowValues: () => proposalToRowValues,
|
|
8898
|
+
proposalRowToProposal: () => proposalRowToProposal,
|
|
8899
|
+
openStateDatabase: () => openStateDatabase,
|
|
8900
|
+
listStateProposals: () => listStateProposals,
|
|
8901
|
+
listExistingTableNames: () => listExistingTableNames,
|
|
8902
|
+
insertEvent: () => insertEvent,
|
|
8903
|
+
importEventsJsonl: () => importEventsJsonl,
|
|
8904
|
+
getTaskHistoryRuns: () => getTaskHistoryRuns,
|
|
8905
|
+
getTaskHistory: () => getTaskHistory,
|
|
8906
|
+
getStateProposal: () => getStateProposal,
|
|
8907
|
+
getStateDbPath: () => getStateDbPath,
|
|
8908
|
+
getExtractedSessionsMap: () => getExtractedSessionsMap,
|
|
8909
|
+
getExtractedSession: () => getExtractedSession,
|
|
8910
|
+
eventRowToEnvelope: () => eventRowToEnvelope,
|
|
8911
|
+
computeImproveRunMetrics: () => computeImproveRunMetrics,
|
|
8912
|
+
REGISTRY_INDEX_CACHE_DDL: () => REGISTRY_INDEX_CACHE_DDL
|
|
8913
|
+
});
|
|
8914
|
+
import fs5 from "fs";
|
|
8915
|
+
import path5 from "path";
|
|
8916
|
+
function getStateDbPath() {
|
|
8917
|
+
return path5.join(getDataDir(), "state.db");
|
|
8918
|
+
}
|
|
8919
|
+
function openStateDatabase(dbPath) {
|
|
8920
|
+
const resolvedPath = dbPath ?? getStateDbPath();
|
|
8921
|
+
const dir = path5.dirname(resolvedPath);
|
|
8922
|
+
if (!fs5.existsSync(dir)) {
|
|
8923
|
+
fs5.mkdirSync(dir, { recursive: true });
|
|
8924
|
+
}
|
|
8925
|
+
const db = openDatabase(resolvedPath);
|
|
8926
|
+
db.exec("PRAGMA journal_mode = WAL");
|
|
8927
|
+
db.exec("PRAGMA foreign_keys = ON");
|
|
8928
|
+
db.exec("PRAGMA busy_timeout = 5000");
|
|
8929
|
+
runMigrations2(db);
|
|
8930
|
+
return db;
|
|
8931
|
+
}
|
|
8932
|
+
function runMigrations2(db) {
|
|
8933
|
+
runMigrations(db, MIGRATIONS);
|
|
8934
|
+
}
|
|
8832
8935
|
function eventRowToEnvelope(row) {
|
|
8833
8936
|
let metadata;
|
|
8834
8937
|
try {
|
|
@@ -9026,6 +9129,16 @@ function queryTaskHistory(db, options = {}) {
|
|
|
9026
9129
|
target_kind, target_ref, metadata_json
|
|
9027
9130
|
FROM task_history ${where} ORDER BY started_at DESC`).all(...params);
|
|
9028
9131
|
}
|
|
9132
|
+
function queryCompletedTaskIntervals(db, since, until) {
|
|
9133
|
+
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";
|
|
9134
|
+
return until ? db.prepare(sql).all(since, until) : db.prepare(sql).all(since);
|
|
9135
|
+
}
|
|
9136
|
+
function listExistingTableNames(db, names) {
|
|
9137
|
+
if (names.length === 0)
|
|
9138
|
+
return [];
|
|
9139
|
+
const placeholders = names.map(() => "?").join(", ");
|
|
9140
|
+
return db.prepare(`SELECT name FROM sqlite_master WHERE type = 'table' AND name IN (${placeholders}) ORDER BY name`).all(...names);
|
|
9141
|
+
}
|
|
9029
9142
|
async function importEventsJsonl(db, jsonlPath) {
|
|
9030
9143
|
const { readFileSync, existsSync } = await import("fs");
|
|
9031
9144
|
if (!existsSync(jsonlPath)) {
|
|
@@ -9082,23 +9195,17 @@ function computeImproveRunMetrics(result) {
|
|
|
9082
9195
|
let autoAcceptedCount = 0;
|
|
9083
9196
|
let errorCount = 0;
|
|
9084
9197
|
for (const action of actions) {
|
|
9085
|
-
switch (action.mode) {
|
|
9086
|
-
case "
|
|
9087
|
-
case "distill":
|
|
9088
|
-
case "memory-inference":
|
|
9089
|
-
case "graph-extraction":
|
|
9198
|
+
switch (classifyImproveAction(action.mode)) {
|
|
9199
|
+
case "accepted":
|
|
9090
9200
|
acceptedCount++;
|
|
9091
9201
|
break;
|
|
9092
|
-
case "
|
|
9093
|
-
case "reflect-skipped":
|
|
9094
|
-
case "distill-skipped":
|
|
9202
|
+
case "rejected":
|
|
9095
9203
|
rejectedCount++;
|
|
9096
9204
|
break;
|
|
9097
|
-
case "reflect-failed":
|
|
9098
9205
|
case "error":
|
|
9099
9206
|
errorCount++;
|
|
9100
9207
|
break;
|
|
9101
|
-
case "
|
|
9208
|
+
case "noop":
|
|
9102
9209
|
break;
|
|
9103
9210
|
}
|
|
9104
9211
|
const r = action.result;
|
|
@@ -9117,6 +9224,10 @@ function recordImproveRun(db, input) {
|
|
|
9117
9224
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
9118
9225
|
`).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
9226
|
}
|
|
9227
|
+
function queryImproveRuns(db, since, until) {
|
|
9228
|
+
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";
|
|
9229
|
+
return until ? db.prepare(sql).all(since, until) : db.prepare(sql).all(since);
|
|
9230
|
+
}
|
|
9120
9231
|
function purgeOldImproveRuns(db, retentionDays = 90) {
|
|
9121
9232
|
if (!Number.isFinite(retentionDays) || retentionDays <= 0)
|
|
9122
9233
|
return 0;
|
|
@@ -9177,6 +9288,8 @@ var MIGRATIONS, REGISTRY_INDEX_CACHE_DDL = `
|
|
|
9177
9288
|
ON registry_index_cache(fetched_at);
|
|
9178
9289
|
`;
|
|
9179
9290
|
var init_state_db = __esm(() => {
|
|
9291
|
+
init_database();
|
|
9292
|
+
init_improve_types();
|
|
9180
9293
|
init_paths();
|
|
9181
9294
|
init_warn();
|
|
9182
9295
|
MIGRATIONS = [
|
|
@@ -9441,6 +9554,21 @@ var init_state_db = __esm(() => {
|
|
|
9441
9554
|
];
|
|
9442
9555
|
});
|
|
9443
9556
|
|
|
9557
|
+
// src/core/best-effort.ts
|
|
9558
|
+
function bestEffort(fn, context) {
|
|
9559
|
+
try {
|
|
9560
|
+
return fn();
|
|
9561
|
+
} catch (err) {
|
|
9562
|
+
if (isVerbose()) {
|
|
9563
|
+
warnVerbose(`[akm:best-effort] ${context ? `${context}: ` : ""}swallowed error`, err);
|
|
9564
|
+
}
|
|
9565
|
+
return;
|
|
9566
|
+
}
|
|
9567
|
+
}
|
|
9568
|
+
var init_best_effort = __esm(() => {
|
|
9569
|
+
init_warn();
|
|
9570
|
+
});
|
|
9571
|
+
|
|
9444
9572
|
// src/llm/embedders/types.ts
|
|
9445
9573
|
function cosineSimilarity(a, b) {
|
|
9446
9574
|
if (a.length !== b.length) {
|
|
@@ -9465,7 +9593,98 @@ var init_types = __esm(() => {
|
|
|
9465
9593
|
init_warn();
|
|
9466
9594
|
});
|
|
9467
9595
|
|
|
9468
|
-
// src/
|
|
9596
|
+
// src/runtime.ts
|
|
9597
|
+
import { createHash } from "crypto";
|
|
9598
|
+
import { createRequire as createRequire2 } from "module";
|
|
9599
|
+
function sha256Hex(data) {
|
|
9600
|
+
return createHash("sha256").update(data).digest("hex");
|
|
9601
|
+
}
|
|
9602
|
+
function sleepSync(ms) {
|
|
9603
|
+
if (isBun2) {
|
|
9604
|
+
bunGlobal().sleepSync(ms);
|
|
9605
|
+
return;
|
|
9606
|
+
}
|
|
9607
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
9608
|
+
}
|
|
9609
|
+
function bunGlobal() {
|
|
9610
|
+
return globalThis.Bun;
|
|
9611
|
+
}
|
|
9612
|
+
var isBun2, nodeRequire2, mainPath;
|
|
9613
|
+
var init_runtime = __esm(() => {
|
|
9614
|
+
isBun2 = !!process.versions?.bun;
|
|
9615
|
+
nodeRequire2 = createRequire2(import.meta.url);
|
|
9616
|
+
mainPath = isBun2 ? bunGlobal().main : process.argv[1];
|
|
9617
|
+
});
|
|
9618
|
+
|
|
9619
|
+
// src/indexer/search/search-fields.ts
|
|
9620
|
+
function buildSearchFields(entry) {
|
|
9621
|
+
const name = entry.name.replace(/[-_]/g, " ").toLowerCase();
|
|
9622
|
+
const description = (entry.description ?? "").toLowerCase();
|
|
9623
|
+
const tagParts = [];
|
|
9624
|
+
if (entry.tags)
|
|
9625
|
+
tagParts.push(entry.tags.join(" "));
|
|
9626
|
+
if (entry.aliases)
|
|
9627
|
+
tagParts.push(entry.aliases.join(" "));
|
|
9628
|
+
const tags = tagParts.join(" ").toLowerCase();
|
|
9629
|
+
const hintParts = [];
|
|
9630
|
+
if (entry.searchHints)
|
|
9631
|
+
hintParts.push(entry.searchHints.join(" "));
|
|
9632
|
+
if (entry.examples)
|
|
9633
|
+
hintParts.push(entry.examples.join(" "));
|
|
9634
|
+
if (entry.usage)
|
|
9635
|
+
hintParts.push(entry.usage.join(" "));
|
|
9636
|
+
if (entry.intent) {
|
|
9637
|
+
if (entry.intent.when)
|
|
9638
|
+
hintParts.push(entry.intent.when);
|
|
9639
|
+
if (entry.intent.input)
|
|
9640
|
+
hintParts.push(entry.intent.input);
|
|
9641
|
+
if (entry.intent.output)
|
|
9642
|
+
hintParts.push(entry.intent.output);
|
|
9643
|
+
}
|
|
9644
|
+
if (entry.xrefs)
|
|
9645
|
+
hintParts.push(entry.xrefs.join(" "));
|
|
9646
|
+
if (entry.pageKind)
|
|
9647
|
+
hintParts.push(entry.pageKind);
|
|
9648
|
+
if (entry.whenToUse)
|
|
9649
|
+
hintParts.push(entry.whenToUse);
|
|
9650
|
+
const hints = hintParts.join(" ").toLowerCase();
|
|
9651
|
+
const contentParts = [];
|
|
9652
|
+
if (entry.toc) {
|
|
9653
|
+
contentParts.push(entry.toc.map((h) => h.text).join(" "));
|
|
9654
|
+
}
|
|
9655
|
+
if (entry.parameters) {
|
|
9656
|
+
for (const param of entry.parameters) {
|
|
9657
|
+
contentParts.push(param.name);
|
|
9658
|
+
if (param.description)
|
|
9659
|
+
contentParts.push(param.description);
|
|
9660
|
+
}
|
|
9661
|
+
}
|
|
9662
|
+
const content = contentParts.join(" ").toLowerCase();
|
|
9663
|
+
return { name, description, tags, hints, content };
|
|
9664
|
+
}
|
|
9665
|
+
|
|
9666
|
+
// src/indexer/usage/usage-events.ts
|
|
9667
|
+
function ensureUsageEventsSchema(db) {
|
|
9668
|
+
db.exec(`
|
|
9669
|
+
CREATE TABLE IF NOT EXISTS usage_events (
|
|
9670
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
9671
|
+
event_type TEXT NOT NULL,
|
|
9672
|
+
query TEXT,
|
|
9673
|
+
entry_id INTEGER,
|
|
9674
|
+
entry_ref TEXT,
|
|
9675
|
+
signal TEXT,
|
|
9676
|
+
metadata TEXT,
|
|
9677
|
+
source TEXT NOT NULL DEFAULT 'user',
|
|
9678
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
9679
|
+
);
|
|
9680
|
+
CREATE INDEX IF NOT EXISTS idx_usage_events_entry ON usage_events(entry_id);
|
|
9681
|
+
CREATE INDEX IF NOT EXISTS idx_usage_events_type ON usage_events(event_type);
|
|
9682
|
+
CREATE INDEX IF NOT EXISTS idx_usage_events_ref ON usage_events(entry_ref);
|
|
9683
|
+
CREATE INDEX IF NOT EXISTS idx_usage_events_source ON usage_events(source);
|
|
9684
|
+
`);
|
|
9685
|
+
}
|
|
9686
|
+
|
|
9687
|
+
// src/indexer/db/db-backup.ts
|
|
9469
9688
|
import fs6 from "fs";
|
|
9470
9689
|
import path6 from "path";
|
|
9471
9690
|
function resolveRetention(env = process.env) {
|
|
@@ -9507,9 +9726,9 @@ function measureDataDirSize(dirPath) {
|
|
|
9507
9726
|
if (entry.isDirectory()) {
|
|
9508
9727
|
stack.push(full);
|
|
9509
9728
|
} else if (entry.isFile()) {
|
|
9510
|
-
|
|
9729
|
+
bestEffort(() => {
|
|
9511
9730
|
total += fs6.statSync(full).size;
|
|
9512
|
-
}
|
|
9731
|
+
}, "file vanished between readdir and stat");
|
|
9513
9732
|
}
|
|
9514
9733
|
}
|
|
9515
9734
|
}
|
|
@@ -9545,7 +9764,7 @@ function listBackups(dataDir) {
|
|
|
9545
9764
|
let sizeBytes;
|
|
9546
9765
|
let reason = DEFAULT_BACKUP_REASON;
|
|
9547
9766
|
if (fs6.existsSync(metaPath)) {
|
|
9548
|
-
|
|
9767
|
+
bestEffort(() => {
|
|
9549
9768
|
const raw = fs6.readFileSync(metaPath, "utf8");
|
|
9550
9769
|
const parsed = JSON.parse(raw);
|
|
9551
9770
|
if (typeof parsed.createdAt === "string")
|
|
@@ -9558,7 +9777,7 @@ function listBackups(dataDir) {
|
|
|
9558
9777
|
sizeBytes = parsed.sizeBytes;
|
|
9559
9778
|
if (typeof parsed.reason === "string" && parsed.reason.length > 0)
|
|
9560
9779
|
reason = parsed.reason;
|
|
9561
|
-
}
|
|
9780
|
+
}, "malformed backup metadata \u2014 fall back to filesystem-derived values");
|
|
9562
9781
|
}
|
|
9563
9782
|
if (!createdAt) {
|
|
9564
9783
|
try {
|
|
@@ -9639,9 +9858,7 @@ function backupDataDir(opts) {
|
|
|
9639
9858
|
copyDataDirExcludingBackups(dataDir, finalDest);
|
|
9640
9859
|
} catch (err) {
|
|
9641
9860
|
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 {}
|
|
9861
|
+
bestEffort(() => fs6.rmSync(finalDest, { recursive: true, force: true }), "cleanup partial backup copy");
|
|
9645
9862
|
return null;
|
|
9646
9863
|
}
|
|
9647
9864
|
const createdAt = now.toISOString();
|
|
@@ -9697,9 +9914,7 @@ function copyDataDirExcludingBackups(srcRoot, destRoot) {
|
|
|
9697
9914
|
fs6.copyFileSync(srcPath, destPath);
|
|
9698
9915
|
} else if (entry.isSymbolicLink()) {
|
|
9699
9916
|
const target = fs6.readlinkSync(srcPath);
|
|
9700
|
-
|
|
9701
|
-
fs6.symlinkSync(target, destPath);
|
|
9702
|
-
} catch {}
|
|
9917
|
+
bestEffort(() => fs6.symlinkSync(target, destPath), "symlink creation can fail on Windows without admin");
|
|
9703
9918
|
}
|
|
9704
9919
|
}
|
|
9705
9920
|
}
|
|
@@ -9714,77 +9929,10 @@ function tryHostname() {
|
|
|
9714
9929
|
}
|
|
9715
9930
|
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
9931
|
var init_db_backup = __esm(() => {
|
|
9932
|
+
init_best_effort();
|
|
9717
9933
|
init_warn();
|
|
9718
9934
|
});
|
|
9719
9935
|
|
|
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
9936
|
// src/core/file-lock.ts
|
|
9789
9937
|
import fs7 from "fs";
|
|
9790
9938
|
function tryAcquireLockSync(lockPath, payload) {
|
|
@@ -9850,7 +9998,7 @@ var init_file_lock = __esm(() => {
|
|
|
9850
9998
|
init_common();
|
|
9851
9999
|
});
|
|
9852
10000
|
|
|
9853
|
-
// src/core/config-io.ts
|
|
10001
|
+
// src/core/config/config-io.ts
|
|
9854
10002
|
import fs8 from "fs";
|
|
9855
10003
|
import path7 from "path";
|
|
9856
10004
|
function parseConfigText(text, sourcePath) {
|
|
@@ -9891,9 +10039,12 @@ function backupExistingConfig(configPath) {
|
|
|
9891
10039
|
const backupDir = path7.join(getCacheDir(), "config-backups");
|
|
9892
10040
|
fs8.mkdirSync(backupDir, { recursive: true });
|
|
9893
10041
|
const timestamp = new Date().toISOString().replace(/[.:]/g, "-");
|
|
9894
|
-
|
|
9895
|
-
|
|
10042
|
+
const timestamped = path7.join(backupDir, `config-${timestamp}.json`);
|
|
10043
|
+
const latest = path7.join(backupDir, "config.latest.json");
|
|
10044
|
+
fs8.copyFileSync(configPath, timestamped);
|
|
10045
|
+
fs8.copyFileSync(configPath, latest);
|
|
9896
10046
|
pruneOldBackups2(backupDir);
|
|
10047
|
+
return { timestamped, latest };
|
|
9897
10048
|
}
|
|
9898
10049
|
function pruneOldBackups2(backupDir) {
|
|
9899
10050
|
let entries;
|
|
@@ -9919,6 +10070,9 @@ function pruneOldBackups2(backupDir) {
|
|
|
9919
10070
|
function getConfigLockPath() {
|
|
9920
10071
|
return path7.join(getConfigDir(), "config.json.lck");
|
|
9921
10072
|
}
|
|
10073
|
+
function sleepSyncMs(ms) {
|
|
10074
|
+
sleepSync(ms);
|
|
10075
|
+
}
|
|
9922
10076
|
function acquireConfigLock() {
|
|
9923
10077
|
const lockPath = getConfigLockPath();
|
|
9924
10078
|
try {
|
|
@@ -9937,8 +10091,7 @@ function acquireConfigLock() {
|
|
|
9937
10091
|
continue;
|
|
9938
10092
|
}
|
|
9939
10093
|
if (attempt < CONFIG_LOCK_MAX_RETRIES - 1) {
|
|
9940
|
-
|
|
9941
|
-
while (Date.now() < deadline) {}
|
|
10094
|
+
sleepSyncMs(CONFIG_LOCK_RETRY_DELAY_MS);
|
|
9942
10095
|
}
|
|
9943
10096
|
}
|
|
9944
10097
|
return () => {};
|
|
@@ -9991,17 +10144,801 @@ function stripJsonComments(text) {
|
|
|
9991
10144
|
result += text[i];
|
|
9992
10145
|
i++;
|
|
9993
10146
|
}
|
|
9994
|
-
return result;
|
|
10147
|
+
return result;
|
|
10148
|
+
}
|
|
10149
|
+
var MAX_CONFIG_BACKUPS = 5, CONFIG_LOCK_MAX_RETRIES = 10, CONFIG_LOCK_RETRY_DELAY_MS = 50;
|
|
10150
|
+
var init_config_io = __esm(() => {
|
|
10151
|
+
init_runtime();
|
|
10152
|
+
init_common();
|
|
10153
|
+
init_errors();
|
|
10154
|
+
init_file_lock();
|
|
10155
|
+
init_paths();
|
|
10156
|
+
});
|
|
10157
|
+
|
|
10158
|
+
// src/integrations/harnesses/types.ts
|
|
10159
|
+
class BaseHarness {
|
|
10160
|
+
runtimeId;
|
|
10161
|
+
setupDetectionDir;
|
|
10162
|
+
v1ProfilePrefixes = [];
|
|
10163
|
+
matchesV1ProfileName(name) {
|
|
10164
|
+
if (!this.capabilities.v1Migration)
|
|
10165
|
+
return false;
|
|
10166
|
+
const lower = name.trim().toLowerCase();
|
|
10167
|
+
if (!lower)
|
|
10168
|
+
return false;
|
|
10169
|
+
if (lower === this.id.toLowerCase())
|
|
10170
|
+
return true;
|
|
10171
|
+
for (const alias of this.aliases) {
|
|
10172
|
+
if (lower === alias.toLowerCase())
|
|
10173
|
+
return true;
|
|
10174
|
+
}
|
|
10175
|
+
for (const prefix of this.v1ProfilePrefixes) {
|
|
10176
|
+
if (lower.startsWith(prefix.toLowerCase()))
|
|
10177
|
+
return true;
|
|
10178
|
+
}
|
|
10179
|
+
return false;
|
|
10180
|
+
}
|
|
10181
|
+
}
|
|
10182
|
+
|
|
10183
|
+
// src/integrations/agent/builder-shared.ts
|
|
10184
|
+
var init_builder_shared = __esm(() => {
|
|
10185
|
+
init_errors();
|
|
10186
|
+
});
|
|
10187
|
+
|
|
10188
|
+
// src/integrations/agent/model-aliases.ts
|
|
10189
|
+
var init_model_aliases = () => {};
|
|
10190
|
+
|
|
10191
|
+
// src/integrations/harnesses/claude/agent-builder.ts
|
|
10192
|
+
var init_agent_builder = __esm(() => {
|
|
10193
|
+
init_builder_shared();
|
|
10194
|
+
init_model_aliases();
|
|
10195
|
+
});
|
|
10196
|
+
|
|
10197
|
+
// src/integrations/harnesses/claude/config-import.ts
|
|
10198
|
+
var init_config_import = () => {};
|
|
10199
|
+
|
|
10200
|
+
// src/integrations/session-logs/inline-refs.ts
|
|
10201
|
+
function extractInlineRefMentions(text, ts) {
|
|
10202
|
+
if (!text || text.length < 10)
|
|
10203
|
+
return [];
|
|
10204
|
+
const out = [];
|
|
10205
|
+
REMEMBER_RE.lastIndex = 0;
|
|
10206
|
+
for (const m of text.matchAll(REMEMBER_RE)) {
|
|
10207
|
+
const body = m[1] ?? m[2] ?? "";
|
|
10208
|
+
if (!body.trim())
|
|
10209
|
+
continue;
|
|
10210
|
+
out.push({
|
|
10211
|
+
kind: "remember",
|
|
10212
|
+
text: body,
|
|
10213
|
+
...ts !== undefined ? { ts } : {}
|
|
10214
|
+
});
|
|
10215
|
+
}
|
|
10216
|
+
FEEDBACK_RE.lastIndex = 0;
|
|
10217
|
+
for (const m of text.matchAll(FEEDBACK_RE)) {
|
|
10218
|
+
const ref = m[1] ?? "";
|
|
10219
|
+
const note = m[2] ?? m[3] ?? "";
|
|
10220
|
+
if (!ref)
|
|
10221
|
+
continue;
|
|
10222
|
+
out.push({
|
|
10223
|
+
kind: "feedback",
|
|
10224
|
+
ref,
|
|
10225
|
+
text: note,
|
|
10226
|
+
...ts !== undefined ? { ts } : {}
|
|
10227
|
+
});
|
|
10228
|
+
}
|
|
10229
|
+
return out;
|
|
10230
|
+
}
|
|
10231
|
+
var REMEMBER_RE, FEEDBACK_RE;
|
|
10232
|
+
var init_inline_refs = __esm(() => {
|
|
10233
|
+
REMEMBER_RE = /\bakm\s+remember\s+(?:"((?:[^"\\]|\\.)*)"|'((?:[^'\\]|\\.)*)')/g;
|
|
10234
|
+
FEEDBACK_RE = /\bakm\s+feedback\s+(\S+)(?:\s+--[a-z-]+)*\s+(?:--note|-n)\s+(?:"((?:[^"\\]|\\.)*)"|'((?:[^'\\]|\\.)*)')/g;
|
|
10235
|
+
});
|
|
10236
|
+
|
|
10237
|
+
// src/integrations/harnesses/claude/session-log.ts
|
|
10238
|
+
import fs9 from "fs";
|
|
10239
|
+
import os from "os";
|
|
10240
|
+
import path8 from "path";
|
|
10241
|
+
function parseClaudeEvent(entry, sessionId, filePath, fallbackTsMs) {
|
|
10242
|
+
if (!entry || typeof entry !== "object")
|
|
10243
|
+
return;
|
|
10244
|
+
const e = entry;
|
|
10245
|
+
const tsRaw = e.timestamp;
|
|
10246
|
+
const ts = typeof tsRaw === "number" ? tsRaw : typeof tsRaw === "string" ? Date.parse(tsRaw) || fallbackTsMs : fallbackTsMs;
|
|
10247
|
+
const message = e.message ?? undefined;
|
|
10248
|
+
const role = typeof message?.role === "string" ? message.role : e.type ?? "unknown";
|
|
10249
|
+
const content = message?.content;
|
|
10250
|
+
let text = "";
|
|
10251
|
+
if (typeof content === "string") {
|
|
10252
|
+
text = content;
|
|
10253
|
+
} else if (Array.isArray(content)) {
|
|
10254
|
+
const parts = [];
|
|
10255
|
+
for (const block of content) {
|
|
10256
|
+
if (!block || typeof block !== "object")
|
|
10257
|
+
continue;
|
|
10258
|
+
const b = block;
|
|
10259
|
+
if (b.type === "text" && typeof b.text === "string")
|
|
10260
|
+
parts.push(b.text);
|
|
10261
|
+
else if (b.type === "thinking" && typeof b.thinking === "string")
|
|
10262
|
+
parts.push(b.thinking);
|
|
10263
|
+
else if (b.type === "tool_use") {
|
|
10264
|
+
const toolName = typeof b.name === "string" ? b.name : "tool";
|
|
10265
|
+
const inputObj = b.input;
|
|
10266
|
+
let inputText = "";
|
|
10267
|
+
if (inputObj && typeof inputObj === "object") {
|
|
10268
|
+
const cmd = inputObj.command;
|
|
10269
|
+
inputText = typeof cmd === "string" ? cmd : JSON.stringify(inputObj);
|
|
10270
|
+
} else if (typeof inputObj === "string") {
|
|
10271
|
+
inputText = inputObj;
|
|
10272
|
+
}
|
|
10273
|
+
parts.push(`[tool:${toolName}] ${inputText}`);
|
|
10274
|
+
} else if (b.type === "tool_result") {
|
|
10275
|
+
const out = typeof b.content === "string" ? b.content : JSON.stringify(b.content ?? "");
|
|
10276
|
+
parts.push(`[tool_result] ${out}`);
|
|
10277
|
+
}
|
|
10278
|
+
}
|
|
10279
|
+
text = parts.join(`
|
|
10280
|
+
`);
|
|
10281
|
+
}
|
|
10282
|
+
if (!text || text.length < 1)
|
|
10283
|
+
return;
|
|
10284
|
+
return {
|
|
10285
|
+
harness: "claude-code",
|
|
10286
|
+
text,
|
|
10287
|
+
ts,
|
|
10288
|
+
sessionId,
|
|
10289
|
+
role,
|
|
10290
|
+
filePath
|
|
10291
|
+
};
|
|
10292
|
+
}
|
|
10293
|
+
|
|
10294
|
+
class ClaudeCodeProvider {
|
|
10295
|
+
name = "claude-code";
|
|
10296
|
+
isAvailable() {
|
|
10297
|
+
return fs9.existsSync(CLAUDE_PROJECTS_DIR);
|
|
10298
|
+
}
|
|
10299
|
+
*readEvents(input) {
|
|
10300
|
+
try {
|
|
10301
|
+
for (const jsonlPath of this.#walkJsonl(CLAUDE_PROJECTS_DIR)) {
|
|
10302
|
+
const stat = fs9.statSync(jsonlPath);
|
|
10303
|
+
if (stat.mtimeMs < input.sinceMs)
|
|
10304
|
+
continue;
|
|
10305
|
+
const lines = fs9.readFileSync(jsonlPath, "utf8").split(`
|
|
10306
|
+
`).filter(Boolean);
|
|
10307
|
+
for (const line of lines) {
|
|
10308
|
+
try {
|
|
10309
|
+
const entry = JSON.parse(line);
|
|
10310
|
+
const text = entry?.message?.content ?? entry?.content ?? "";
|
|
10311
|
+
if (typeof text !== "string" || text.length < 10)
|
|
10312
|
+
continue;
|
|
10313
|
+
yield {
|
|
10314
|
+
harness: this.name,
|
|
10315
|
+
text,
|
|
10316
|
+
ts: typeof entry?.timestamp === "number" ? entry.timestamp : stat.mtimeMs,
|
|
10317
|
+
sessionId: typeof entry?.session_id === "string" ? entry.session_id : undefined,
|
|
10318
|
+
role: typeof entry?.role === "string" ? entry.role : "unknown",
|
|
10319
|
+
filePath: jsonlPath
|
|
10320
|
+
};
|
|
10321
|
+
} catch {}
|
|
10322
|
+
}
|
|
10323
|
+
}
|
|
10324
|
+
} catch {
|
|
10325
|
+
return;
|
|
10326
|
+
}
|
|
10327
|
+
}
|
|
10328
|
+
listSessions(input = {}) {
|
|
10329
|
+
const root = input.location ?? CLAUDE_PROJECTS_DIR;
|
|
10330
|
+
const sinceMs = input.sinceMs ?? 0;
|
|
10331
|
+
const summaries = [];
|
|
10332
|
+
try {
|
|
10333
|
+
for (const jsonlPath of this.#walkJsonl(root)) {
|
|
10334
|
+
let stat;
|
|
10335
|
+
try {
|
|
10336
|
+
stat = fs9.statSync(jsonlPath);
|
|
10337
|
+
} catch {
|
|
10338
|
+
continue;
|
|
10339
|
+
}
|
|
10340
|
+
if (stat.mtimeMs < sinceMs)
|
|
10341
|
+
continue;
|
|
10342
|
+
const sessionId = path8.basename(jsonlPath, ".jsonl");
|
|
10343
|
+
const projectHint = path8.basename(path8.dirname(jsonlPath));
|
|
10344
|
+
const peek = this.#peekJsonl(jsonlPath);
|
|
10345
|
+
summaries.push({
|
|
10346
|
+
harness: this.name,
|
|
10347
|
+
sessionId,
|
|
10348
|
+
filePath: jsonlPath,
|
|
10349
|
+
startedAt: peek.firstTsMs ?? stat.ctimeMs,
|
|
10350
|
+
endedAt: peek.lastTsMs ?? stat.mtimeMs,
|
|
10351
|
+
projectHint,
|
|
10352
|
+
...peek.title ? { title: peek.title } : {}
|
|
10353
|
+
});
|
|
10354
|
+
}
|
|
10355
|
+
} catch {}
|
|
10356
|
+
return summaries.sort((a, b) => (b.endedAt ?? 0) - (a.endedAt ?? 0));
|
|
10357
|
+
}
|
|
10358
|
+
readSession(ref) {
|
|
10359
|
+
const stat = fs9.statSync(ref.filePath);
|
|
10360
|
+
const lines = fs9.readFileSync(ref.filePath, "utf8").split(`
|
|
10361
|
+
`).filter(Boolean);
|
|
10362
|
+
const events = [];
|
|
10363
|
+
const inlineRefs = [];
|
|
10364
|
+
let title;
|
|
10365
|
+
let firstTsMs;
|
|
10366
|
+
let lastTsMs;
|
|
10367
|
+
const projectHint = path8.basename(path8.dirname(ref.filePath));
|
|
10368
|
+
for (const line of lines) {
|
|
10369
|
+
let entry;
|
|
10370
|
+
try {
|
|
10371
|
+
entry = JSON.parse(line);
|
|
10372
|
+
} catch {
|
|
10373
|
+
continue;
|
|
10374
|
+
}
|
|
10375
|
+
if (!entry)
|
|
10376
|
+
continue;
|
|
10377
|
+
if (entry.type === "custom-title" && typeof entry.customTitle === "string") {
|
|
10378
|
+
title = entry.customTitle;
|
|
10379
|
+
continue;
|
|
10380
|
+
}
|
|
10381
|
+
const parsed = parseClaudeEvent(entry, ref.sessionId, ref.filePath, stat.mtimeMs);
|
|
10382
|
+
if (!parsed)
|
|
10383
|
+
continue;
|
|
10384
|
+
events.push(parsed);
|
|
10385
|
+
if (firstTsMs === undefined || (parsed.ts ?? 0) < firstTsMs)
|
|
10386
|
+
firstTsMs = parsed.ts;
|
|
10387
|
+
if (lastTsMs === undefined || (parsed.ts ?? 0) > lastTsMs)
|
|
10388
|
+
lastTsMs = parsed.ts;
|
|
10389
|
+
inlineRefs.push(...extractInlineRefMentions(parsed.text, parsed.ts));
|
|
10390
|
+
}
|
|
10391
|
+
return {
|
|
10392
|
+
ref: {
|
|
10393
|
+
harness: this.name,
|
|
10394
|
+
sessionId: ref.sessionId,
|
|
10395
|
+
filePath: ref.filePath,
|
|
10396
|
+
startedAt: firstTsMs ?? stat.ctimeMs,
|
|
10397
|
+
endedAt: lastTsMs ?? stat.mtimeMs,
|
|
10398
|
+
projectHint,
|
|
10399
|
+
...title ? { title } : {}
|
|
10400
|
+
},
|
|
10401
|
+
events,
|
|
10402
|
+
inlineRefs
|
|
10403
|
+
};
|
|
10404
|
+
}
|
|
10405
|
+
#peekJsonl(filePath) {
|
|
10406
|
+
const result = {};
|
|
10407
|
+
try {
|
|
10408
|
+
const fd = fs9.openSync(filePath, "r");
|
|
10409
|
+
try {
|
|
10410
|
+
const stat = fs9.fstatSync(fd);
|
|
10411
|
+
const headSize = Math.min(stat.size, 4096);
|
|
10412
|
+
const head = Buffer.alloc(headSize);
|
|
10413
|
+
fs9.readSync(fd, head, 0, headSize, 0);
|
|
10414
|
+
const headLines = head.toString("utf8").split(`
|
|
10415
|
+
`).filter(Boolean);
|
|
10416
|
+
for (const line of headLines) {
|
|
10417
|
+
try {
|
|
10418
|
+
const e = JSON.parse(line);
|
|
10419
|
+
if (e.type === "custom-title" && typeof e.customTitle === "string") {
|
|
10420
|
+
result.title = e.customTitle;
|
|
10421
|
+
}
|
|
10422
|
+
if (typeof e.timestamp === "string") {
|
|
10423
|
+
const t = Date.parse(e.timestamp);
|
|
10424
|
+
if (!Number.isNaN(t)) {
|
|
10425
|
+
if (result.firstTsMs === undefined)
|
|
10426
|
+
result.firstTsMs = t;
|
|
10427
|
+
result.lastTsMs = t;
|
|
10428
|
+
}
|
|
10429
|
+
}
|
|
10430
|
+
} catch {}
|
|
10431
|
+
}
|
|
10432
|
+
if (stat.size > 4096) {
|
|
10433
|
+
const tailSize = Math.min(stat.size, 4096);
|
|
10434
|
+
const tail = Buffer.alloc(tailSize);
|
|
10435
|
+
fs9.readSync(fd, tail, 0, tailSize, stat.size - tailSize);
|
|
10436
|
+
const tailLines = tail.toString("utf8").split(`
|
|
10437
|
+
`).filter(Boolean);
|
|
10438
|
+
for (let i = tailLines.length - 1;i >= 0; i--) {
|
|
10439
|
+
try {
|
|
10440
|
+
const e = JSON.parse(tailLines[i] ?? "");
|
|
10441
|
+
if (typeof e.timestamp === "string") {
|
|
10442
|
+
const t = Date.parse(e.timestamp);
|
|
10443
|
+
if (!Number.isNaN(t)) {
|
|
10444
|
+
result.lastTsMs = t;
|
|
10445
|
+
break;
|
|
10446
|
+
}
|
|
10447
|
+
}
|
|
10448
|
+
} catch {}
|
|
10449
|
+
}
|
|
10450
|
+
}
|
|
10451
|
+
} finally {
|
|
10452
|
+
fs9.closeSync(fd);
|
|
10453
|
+
}
|
|
10454
|
+
} catch {}
|
|
10455
|
+
return result;
|
|
10456
|
+
}
|
|
10457
|
+
*#walkJsonl(dir) {
|
|
10458
|
+
try {
|
|
10459
|
+
for (const entry of fs9.readdirSync(dir, { withFileTypes: true })) {
|
|
10460
|
+
const full = path8.join(dir, entry.name);
|
|
10461
|
+
if (entry.isDirectory())
|
|
10462
|
+
yield* this.#walkJsonl(full);
|
|
10463
|
+
else if (entry.name.endsWith(".jsonl"))
|
|
10464
|
+
yield full;
|
|
10465
|
+
}
|
|
10466
|
+
} catch {}
|
|
10467
|
+
}
|
|
10468
|
+
}
|
|
10469
|
+
var CLAUDE_PROJECTS_DIR;
|
|
10470
|
+
var init_session_log = __esm(() => {
|
|
10471
|
+
init_inline_refs();
|
|
10472
|
+
CLAUDE_PROJECTS_DIR = path8.join(os.homedir(), ".claude", "projects");
|
|
10473
|
+
});
|
|
10474
|
+
|
|
10475
|
+
// src/integrations/harnesses/claude/index.ts
|
|
10476
|
+
function caps(c) {
|
|
10477
|
+
return {
|
|
10478
|
+
sessionLogs: false,
|
|
10479
|
+
agentDispatch: false,
|
|
10480
|
+
detection: false,
|
|
10481
|
+
configImport: false,
|
|
10482
|
+
runtimeIdentity: false,
|
|
10483
|
+
v1Migration: false,
|
|
10484
|
+
...c
|
|
10485
|
+
};
|
|
10486
|
+
}
|
|
10487
|
+
var ClaudeHarness;
|
|
10488
|
+
var init_claude = __esm(() => {
|
|
10489
|
+
init_agent_builder();
|
|
10490
|
+
init_config_import();
|
|
10491
|
+
init_session_log();
|
|
10492
|
+
ClaudeHarness = class ClaudeHarness extends BaseHarness {
|
|
10493
|
+
id = "claude";
|
|
10494
|
+
displayName = "Claude Code";
|
|
10495
|
+
aliases = ["claude-code"];
|
|
10496
|
+
runtimeId = "claude-code";
|
|
10497
|
+
setupDetectionDir = ".claude";
|
|
10498
|
+
capabilities = caps({
|
|
10499
|
+
sessionLogs: true,
|
|
10500
|
+
agentDispatch: true,
|
|
10501
|
+
detection: true,
|
|
10502
|
+
configImport: true,
|
|
10503
|
+
runtimeIdentity: true,
|
|
10504
|
+
v1Migration: true
|
|
10505
|
+
});
|
|
10506
|
+
};
|
|
10507
|
+
});
|
|
10508
|
+
|
|
10509
|
+
// src/integrations/harnesses/opencode/agent-builder.ts
|
|
10510
|
+
var init_agent_builder2 = __esm(() => {
|
|
10511
|
+
init_builder_shared();
|
|
10512
|
+
init_model_aliases();
|
|
10513
|
+
});
|
|
10514
|
+
|
|
10515
|
+
// src/integrations/harnesses/opencode/config-import.ts
|
|
10516
|
+
var init_config_import2 = () => {};
|
|
10517
|
+
|
|
10518
|
+
// src/integrations/harnesses/opencode/session-log.ts
|
|
10519
|
+
import fs10 from "fs";
|
|
10520
|
+
import os2 from "os";
|
|
10521
|
+
import path9 from "path";
|
|
10522
|
+
function getOpenCodeBaseDir() {
|
|
10523
|
+
if (process.platform === "darwin") {
|
|
10524
|
+
return path9.join(os2.homedir(), "Library", "Application Support", "opencode");
|
|
10525
|
+
}
|
|
10526
|
+
return path9.join(os2.homedir(), ".local", "share", "opencode");
|
|
10527
|
+
}
|
|
10528
|
+
|
|
10529
|
+
class OpenCodeProvider {
|
|
10530
|
+
name = "opencode";
|
|
10531
|
+
#baseDir = getOpenCodeBaseDir();
|
|
10532
|
+
isAvailable() {
|
|
10533
|
+
return fs10.existsSync(this.#baseDir);
|
|
10534
|
+
}
|
|
10535
|
+
*readEvents(input) {
|
|
10536
|
+
const candidates = [this.#baseDir, path9.join(this.#baseDir, "log")];
|
|
10537
|
+
for (const dir of candidates) {
|
|
10538
|
+
if (!fs10.existsSync(dir))
|
|
10539
|
+
continue;
|
|
10540
|
+
try {
|
|
10541
|
+
for (const file of fs10.readdirSync(dir)) {
|
|
10542
|
+
const full = path9.join(dir, file);
|
|
10543
|
+
let stat;
|
|
10544
|
+
try {
|
|
10545
|
+
stat = fs10.statSync(full);
|
|
10546
|
+
} catch {
|
|
10547
|
+
continue;
|
|
10548
|
+
}
|
|
10549
|
+
if (!stat.isFile())
|
|
10550
|
+
continue;
|
|
10551
|
+
if (stat.mtimeMs < input.sinceMs)
|
|
10552
|
+
continue;
|
|
10553
|
+
if (!file.endsWith(".json") && !file.endsWith(".jsonl") && !file.endsWith(".log"))
|
|
10554
|
+
continue;
|
|
10555
|
+
const content = fs10.readFileSync(full, "utf8");
|
|
10556
|
+
const lines = content.includes(`
|
|
10557
|
+
`) ? content.split(`
|
|
10558
|
+
`) : [content];
|
|
10559
|
+
for (const line of lines) {
|
|
10560
|
+
try {
|
|
10561
|
+
const entry = JSON.parse(line);
|
|
10562
|
+
const text = entry?.content ?? entry?.message ?? entry?.text ?? "";
|
|
10563
|
+
if (typeof text !== "string" || text.length < 10)
|
|
10564
|
+
continue;
|
|
10565
|
+
yield {
|
|
10566
|
+
harness: this.name,
|
|
10567
|
+
text,
|
|
10568
|
+
ts: typeof entry?.timestamp === "number" ? entry.timestamp : stat.mtimeMs,
|
|
10569
|
+
sessionId: typeof entry?.sessionId === "string" ? entry.sessionId : undefined,
|
|
10570
|
+
role: typeof entry?.role === "string" ? entry.role : "unknown",
|
|
10571
|
+
filePath: full
|
|
10572
|
+
};
|
|
10573
|
+
} catch {}
|
|
10574
|
+
}
|
|
10575
|
+
}
|
|
10576
|
+
} catch {}
|
|
10577
|
+
}
|
|
10578
|
+
}
|
|
10579
|
+
listSessions(input = {}) {
|
|
10580
|
+
const base = input.location ?? this.#baseDir;
|
|
10581
|
+
const sinceMs = input.sinceMs ?? 0;
|
|
10582
|
+
const sessionRoot = path9.join(base, "storage", "session");
|
|
10583
|
+
if (!fs10.existsSync(sessionRoot))
|
|
10584
|
+
return [];
|
|
10585
|
+
const summaries = [];
|
|
10586
|
+
try {
|
|
10587
|
+
for (const projectId of fs10.readdirSync(sessionRoot)) {
|
|
10588
|
+
const projectDir = path9.join(sessionRoot, projectId);
|
|
10589
|
+
let pstat;
|
|
10590
|
+
try {
|
|
10591
|
+
pstat = fs10.statSync(projectDir);
|
|
10592
|
+
} catch {
|
|
10593
|
+
continue;
|
|
10594
|
+
}
|
|
10595
|
+
if (!pstat.isDirectory())
|
|
10596
|
+
continue;
|
|
10597
|
+
for (const file of fs10.readdirSync(projectDir)) {
|
|
10598
|
+
if (!file.endsWith(".json"))
|
|
10599
|
+
continue;
|
|
10600
|
+
const filePath = path9.join(projectDir, file);
|
|
10601
|
+
let stat;
|
|
10602
|
+
try {
|
|
10603
|
+
stat = fs10.statSync(filePath);
|
|
10604
|
+
} catch {
|
|
10605
|
+
continue;
|
|
10606
|
+
}
|
|
10607
|
+
if (stat.mtimeMs < sinceMs)
|
|
10608
|
+
continue;
|
|
10609
|
+
let meta;
|
|
10610
|
+
try {
|
|
10611
|
+
meta = JSON.parse(fs10.readFileSync(filePath, "utf8"));
|
|
10612
|
+
} catch {
|
|
10613
|
+
continue;
|
|
10614
|
+
}
|
|
10615
|
+
const sessionId = typeof meta?.id === "string" ? meta.id : path9.basename(file, ".json");
|
|
10616
|
+
const time = meta?.time ?? undefined;
|
|
10617
|
+
const startedAt = typeof time?.created === "number" ? time.created : stat.ctimeMs;
|
|
10618
|
+
const endedAt = typeof time?.updated === "number" ? time.updated : stat.mtimeMs;
|
|
10619
|
+
const title = typeof meta?.title === "string" ? meta.title : undefined;
|
|
10620
|
+
const projectHint = typeof meta?.directory === "string" ? meta.directory : projectId;
|
|
10621
|
+
summaries.push({
|
|
10622
|
+
harness: this.name,
|
|
10623
|
+
sessionId,
|
|
10624
|
+
filePath,
|
|
10625
|
+
startedAt,
|
|
10626
|
+
endedAt,
|
|
10627
|
+
projectHint,
|
|
10628
|
+
...title ? { title } : {}
|
|
10629
|
+
});
|
|
10630
|
+
}
|
|
10631
|
+
}
|
|
10632
|
+
} catch {}
|
|
10633
|
+
return summaries.sort((a, b) => (b.endedAt ?? 0) - (a.endedAt ?? 0));
|
|
10634
|
+
}
|
|
10635
|
+
readSession(ref) {
|
|
10636
|
+
let meta = {};
|
|
10637
|
+
try {
|
|
10638
|
+
meta = JSON.parse(fs10.readFileSync(ref.filePath, "utf8"));
|
|
10639
|
+
} catch {}
|
|
10640
|
+
const time = meta.time ?? undefined;
|
|
10641
|
+
const startedAt = typeof time?.created === "number" ? time.created : undefined;
|
|
10642
|
+
const endedAt = typeof time?.updated === "number" ? time.updated : undefined;
|
|
10643
|
+
const title = typeof meta.title === "string" ? meta.title : undefined;
|
|
10644
|
+
const projectHint = typeof meta.directory === "string" ? meta.directory : undefined;
|
|
10645
|
+
const events = [];
|
|
10646
|
+
const inlineRefs = [];
|
|
10647
|
+
const inferredBase = this.#inferBaseFromSessionPath(ref.filePath) ?? this.#baseDir;
|
|
10648
|
+
const msgDir = path9.join(inferredBase, "storage", "message", ref.sessionId);
|
|
10649
|
+
if (fs10.existsSync(msgDir)) {
|
|
10650
|
+
try {
|
|
10651
|
+
const files = fs10.readdirSync(msgDir).filter((f) => f.endsWith(".json"));
|
|
10652
|
+
for (const file of files) {
|
|
10653
|
+
const full = path9.join(msgDir, file);
|
|
10654
|
+
let msg;
|
|
10655
|
+
try {
|
|
10656
|
+
msg = JSON.parse(fs10.readFileSync(full, "utf8"));
|
|
10657
|
+
} catch {
|
|
10658
|
+
continue;
|
|
10659
|
+
}
|
|
10660
|
+
if (!msg)
|
|
10661
|
+
continue;
|
|
10662
|
+
const evt = this.#messageToEvent(msg, ref.sessionId, full);
|
|
10663
|
+
if (evt) {
|
|
10664
|
+
events.push(evt);
|
|
10665
|
+
inlineRefs.push(...extractInlineRefMentions(evt.text, evt.ts));
|
|
10666
|
+
}
|
|
10667
|
+
}
|
|
10668
|
+
} catch {}
|
|
10669
|
+
}
|
|
10670
|
+
events.sort((a, b) => (a.ts ?? 0) - (b.ts ?? 0));
|
|
10671
|
+
return {
|
|
10672
|
+
ref: {
|
|
10673
|
+
harness: this.name,
|
|
10674
|
+
sessionId: ref.sessionId,
|
|
10675
|
+
filePath: ref.filePath,
|
|
10676
|
+
...startedAt !== undefined ? { startedAt } : {},
|
|
10677
|
+
...endedAt !== undefined ? { endedAt } : {},
|
|
10678
|
+
...projectHint ? { projectHint } : {},
|
|
10679
|
+
...title ? { title } : {}
|
|
10680
|
+
},
|
|
10681
|
+
events,
|
|
10682
|
+
inlineRefs
|
|
10683
|
+
};
|
|
10684
|
+
}
|
|
10685
|
+
#inferBaseFromSessionPath(filePath) {
|
|
10686
|
+
const dir = path9.dirname(filePath);
|
|
10687
|
+
const parts = dir.split(path9.sep);
|
|
10688
|
+
if (parts.length < 3)
|
|
10689
|
+
return;
|
|
10690
|
+
const last = parts[parts.length - 1];
|
|
10691
|
+
const sndLast = parts[parts.length - 2];
|
|
10692
|
+
const thirdLast = parts[parts.length - 3];
|
|
10693
|
+
if (sndLast !== "session" || thirdLast !== "storage" || !last)
|
|
10694
|
+
return;
|
|
10695
|
+
return parts.slice(0, parts.length - 3).join(path9.sep);
|
|
10696
|
+
}
|
|
10697
|
+
#messageToEvent(msg, sessionId, filePath) {
|
|
10698
|
+
const time = msg.time ?? undefined;
|
|
10699
|
+
const ts = typeof time?.created === "number" ? time.created : typeof msg.timestamp === "number" ? msg.timestamp : 0;
|
|
10700
|
+
const role = typeof msg.role === "string" ? msg.role : "unknown";
|
|
10701
|
+
const summary = msg.summary;
|
|
10702
|
+
const parts = [];
|
|
10703
|
+
if (typeof summary?.title === "string")
|
|
10704
|
+
parts.push(summary.title);
|
|
10705
|
+
if (Array.isArray(summary?.parts)) {
|
|
10706
|
+
for (const p of summary.parts) {
|
|
10707
|
+
if (typeof p === "string")
|
|
10708
|
+
parts.push(p);
|
|
10709
|
+
else if (p && typeof p === "object") {
|
|
10710
|
+
const text2 = p.text;
|
|
10711
|
+
if (typeof text2 === "string")
|
|
10712
|
+
parts.push(text2);
|
|
10713
|
+
}
|
|
10714
|
+
}
|
|
10715
|
+
}
|
|
10716
|
+
if (typeof msg.content === "string")
|
|
10717
|
+
parts.push(msg.content);
|
|
10718
|
+
const text = parts.join(`
|
|
10719
|
+
`).trim();
|
|
10720
|
+
if (text.length < 1)
|
|
10721
|
+
return;
|
|
10722
|
+
return {
|
|
10723
|
+
harness: this.name,
|
|
10724
|
+
text,
|
|
10725
|
+
ts: ts || undefined,
|
|
10726
|
+
sessionId,
|
|
10727
|
+
role,
|
|
10728
|
+
filePath
|
|
10729
|
+
};
|
|
10730
|
+
}
|
|
10731
|
+
}
|
|
10732
|
+
var init_session_log2 = __esm(() => {
|
|
10733
|
+
init_inline_refs();
|
|
10734
|
+
});
|
|
10735
|
+
|
|
10736
|
+
// src/integrations/harnesses/opencode/index.ts
|
|
10737
|
+
function caps2(c) {
|
|
10738
|
+
return {
|
|
10739
|
+
sessionLogs: false,
|
|
10740
|
+
agentDispatch: false,
|
|
10741
|
+
detection: false,
|
|
10742
|
+
configImport: false,
|
|
10743
|
+
runtimeIdentity: false,
|
|
10744
|
+
v1Migration: false,
|
|
10745
|
+
...c
|
|
10746
|
+
};
|
|
10747
|
+
}
|
|
10748
|
+
var OpencodeHarness;
|
|
10749
|
+
var init_opencode = __esm(() => {
|
|
10750
|
+
init_agent_builder2();
|
|
10751
|
+
init_config_import2();
|
|
10752
|
+
init_session_log2();
|
|
10753
|
+
OpencodeHarness = class OpencodeHarness extends BaseHarness {
|
|
10754
|
+
id = "opencode";
|
|
10755
|
+
displayName = "OpenCode";
|
|
10756
|
+
aliases = [];
|
|
10757
|
+
setupDetectionDir = ".config/opencode";
|
|
10758
|
+
v1ProfilePrefixes = ["opencode"];
|
|
10759
|
+
capabilities = caps2({
|
|
10760
|
+
sessionLogs: true,
|
|
10761
|
+
agentDispatch: true,
|
|
10762
|
+
detection: true,
|
|
10763
|
+
configImport: true,
|
|
10764
|
+
runtimeIdentity: true,
|
|
10765
|
+
v1Migration: true
|
|
10766
|
+
});
|
|
10767
|
+
};
|
|
10768
|
+
});
|
|
10769
|
+
|
|
10770
|
+
// src/integrations/agent/profiles.ts
|
|
10771
|
+
var COMMON_PASSTHROUGH, BUILTINS, HEADLESS_BUILTINS, BUILTIN_AGENT_PROFILE_NAMES;
|
|
10772
|
+
var init_profiles = __esm(() => {
|
|
10773
|
+
COMMON_PASSTHROUGH = ["HOME", "PATH", "USER", "LANG", "LC_ALL", "TERM", "TMPDIR"];
|
|
10774
|
+
BUILTINS = {
|
|
10775
|
+
opencode: {
|
|
10776
|
+
name: "opencode",
|
|
10777
|
+
bin: "opencode",
|
|
10778
|
+
args: ["run"],
|
|
10779
|
+
stdio: "interactive",
|
|
10780
|
+
envPassthrough: [...COMMON_PASSTHROUGH, "OPENCODE_API_KEY", "OPENCODE_CONFIG"],
|
|
10781
|
+
parseOutput: "text"
|
|
10782
|
+
},
|
|
10783
|
+
claude: {
|
|
10784
|
+
name: "claude",
|
|
10785
|
+
bin: "claude",
|
|
10786
|
+
args: [],
|
|
10787
|
+
stdio: "interactive",
|
|
10788
|
+
envPassthrough: [...COMMON_PASSTHROUGH, "ANTHROPIC_API_KEY", "CLAUDE_CONFIG"],
|
|
10789
|
+
parseOutput: "text"
|
|
10790
|
+
},
|
|
10791
|
+
codex: {
|
|
10792
|
+
name: "codex",
|
|
10793
|
+
bin: "codex",
|
|
10794
|
+
args: [],
|
|
10795
|
+
stdio: "interactive",
|
|
10796
|
+
envPassthrough: [...COMMON_PASSTHROUGH, "OPENAI_API_KEY", "CODEX_CONFIG"],
|
|
10797
|
+
parseOutput: "text"
|
|
10798
|
+
},
|
|
10799
|
+
gemini: {
|
|
10800
|
+
name: "gemini",
|
|
10801
|
+
bin: "gemini",
|
|
10802
|
+
args: [],
|
|
10803
|
+
stdio: "interactive",
|
|
10804
|
+
envPassthrough: [...COMMON_PASSTHROUGH, "GEMINI_API_KEY", "GOOGLE_API_KEY"],
|
|
10805
|
+
parseOutput: "text"
|
|
10806
|
+
},
|
|
10807
|
+
aider: {
|
|
10808
|
+
name: "aider",
|
|
10809
|
+
bin: "aider",
|
|
10810
|
+
args: ["--no-auto-commits"],
|
|
10811
|
+
stdio: "interactive",
|
|
10812
|
+
envPassthrough: [...COMMON_PASSTHROUGH, "OPENAI_API_KEY", "ANTHROPIC_API_KEY"],
|
|
10813
|
+
parseOutput: "text"
|
|
10814
|
+
}
|
|
10815
|
+
};
|
|
10816
|
+
HEADLESS_BUILTINS = {
|
|
10817
|
+
"opencode-headless": {
|
|
10818
|
+
name: "opencode-headless",
|
|
10819
|
+
bin: "opencode",
|
|
10820
|
+
args: ["run"],
|
|
10821
|
+
stdio: "captured",
|
|
10822
|
+
envPassthrough: [...COMMON_PASSTHROUGH, "OPENCODE_API_KEY", "OPENCODE_CONFIG"],
|
|
10823
|
+
parseOutput: "json"
|
|
10824
|
+
},
|
|
10825
|
+
"claude-headless": {
|
|
10826
|
+
name: "claude-headless",
|
|
10827
|
+
bin: "claude",
|
|
10828
|
+
args: [],
|
|
10829
|
+
stdio: "captured",
|
|
10830
|
+
envPassthrough: [...COMMON_PASSTHROUGH, "ANTHROPIC_API_KEY", "CLAUDE_CONFIG"],
|
|
10831
|
+
parseOutput: "json"
|
|
10832
|
+
},
|
|
10833
|
+
"codex-headless": {
|
|
10834
|
+
name: "codex-headless",
|
|
10835
|
+
bin: "codex",
|
|
10836
|
+
args: [],
|
|
10837
|
+
stdio: "captured",
|
|
10838
|
+
envPassthrough: [...COMMON_PASSTHROUGH, "OPENAI_API_KEY", "CODEX_CONFIG"],
|
|
10839
|
+
parseOutput: "json"
|
|
10840
|
+
},
|
|
10841
|
+
"gemini-headless": {
|
|
10842
|
+
name: "gemini-headless",
|
|
10843
|
+
bin: "gemini",
|
|
10844
|
+
args: [],
|
|
10845
|
+
stdio: "captured",
|
|
10846
|
+
envPassthrough: [...COMMON_PASSTHROUGH, "GEMINI_API_KEY", "GOOGLE_API_KEY"],
|
|
10847
|
+
parseOutput: "json"
|
|
10848
|
+
},
|
|
10849
|
+
"aider-headless": {
|
|
10850
|
+
name: "aider-headless",
|
|
10851
|
+
bin: "aider",
|
|
10852
|
+
args: ["--no-auto-commits"],
|
|
10853
|
+
stdio: "captured",
|
|
10854
|
+
envPassthrough: [...COMMON_PASSTHROUGH, "OPENAI_API_KEY", "ANTHROPIC_API_KEY"],
|
|
10855
|
+
parseOutput: "json"
|
|
10856
|
+
}
|
|
10857
|
+
};
|
|
10858
|
+
BUILTIN_AGENT_PROFILE_NAMES = Object.freeze(Object.keys(BUILTINS).sort());
|
|
10859
|
+
});
|
|
10860
|
+
|
|
10861
|
+
// src/integrations/agent/config.ts
|
|
10862
|
+
var init_config = __esm(() => {
|
|
10863
|
+
init_config2();
|
|
10864
|
+
init_errors();
|
|
10865
|
+
init_warn();
|
|
10866
|
+
init_profiles();
|
|
10867
|
+
});
|
|
10868
|
+
|
|
10869
|
+
// src/integrations/harnesses/opencode-sdk/sdk-runner.ts
|
|
10870
|
+
var init_sdk_runner = __esm(() => {
|
|
10871
|
+
init_config2();
|
|
10872
|
+
init_config();
|
|
10873
|
+
});
|
|
10874
|
+
|
|
10875
|
+
// src/integrations/harnesses/opencode-sdk/index.ts
|
|
10876
|
+
function caps3(c) {
|
|
10877
|
+
return {
|
|
10878
|
+
sessionLogs: false,
|
|
10879
|
+
agentDispatch: false,
|
|
10880
|
+
detection: false,
|
|
10881
|
+
configImport: false,
|
|
10882
|
+
runtimeIdentity: false,
|
|
10883
|
+
v1Migration: false,
|
|
10884
|
+
...c
|
|
10885
|
+
};
|
|
10886
|
+
}
|
|
10887
|
+
var OpencodeSdkHarness;
|
|
10888
|
+
var init_opencode_sdk = __esm(() => {
|
|
10889
|
+
init_sdk_runner();
|
|
10890
|
+
OpencodeSdkHarness = class OpencodeSdkHarness extends BaseHarness {
|
|
10891
|
+
id = "opencode-sdk";
|
|
10892
|
+
displayName = "OpenCode SDK";
|
|
10893
|
+
aliases = [];
|
|
10894
|
+
v1ProfilePrefixes = ["opencode-sdk"];
|
|
10895
|
+
capabilities = caps3({
|
|
10896
|
+
agentDispatch: true,
|
|
10897
|
+
detection: true,
|
|
10898
|
+
v1Migration: true
|
|
10899
|
+
});
|
|
10900
|
+
};
|
|
10901
|
+
});
|
|
10902
|
+
|
|
10903
|
+
// src/integrations/harnesses/index.ts
|
|
10904
|
+
function v1ProfilePlatform(name) {
|
|
10905
|
+
for (const h of V1_RESOLUTION_ORDER) {
|
|
10906
|
+
if (h.matchesV1ProfileName(name))
|
|
10907
|
+
return h.id;
|
|
10908
|
+
}
|
|
10909
|
+
return;
|
|
9995
10910
|
}
|
|
9996
|
-
var
|
|
9997
|
-
var
|
|
9998
|
-
|
|
9999
|
-
|
|
10000
|
-
|
|
10001
|
-
|
|
10911
|
+
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;
|
|
10912
|
+
var init_harnesses = __esm(() => {
|
|
10913
|
+
init_claude();
|
|
10914
|
+
init_opencode();
|
|
10915
|
+
init_opencode_sdk();
|
|
10916
|
+
HARNESS_REGISTRY = Object.freeze([
|
|
10917
|
+
new OpencodeHarness,
|
|
10918
|
+
new ClaudeHarness,
|
|
10919
|
+
new OpencodeSdkHarness
|
|
10920
|
+
]);
|
|
10921
|
+
HARNESS_BY_ID = new Map(HARNESS_REGISTRY.map((h) => [h.id, h]));
|
|
10922
|
+
HARNESS_BY_ANY_ID = (() => {
|
|
10923
|
+
const m = new Map;
|
|
10924
|
+
for (const h of HARNESS_REGISTRY) {
|
|
10925
|
+
m.set(h.id, h);
|
|
10926
|
+
if (h.runtimeId)
|
|
10927
|
+
m.set(h.runtimeId, h);
|
|
10928
|
+
for (const a of h.aliases)
|
|
10929
|
+
m.set(a, h);
|
|
10930
|
+
}
|
|
10931
|
+
return m;
|
|
10932
|
+
})();
|
|
10933
|
+
VALID_HARNESS_IDS = Object.freeze(HARNESS_REGISTRY.map((h) => h.id));
|
|
10934
|
+
SESSION_LOG_HARNESSES = HARNESS_REGISTRY.filter((h) => h.capabilities.sessionLogs);
|
|
10935
|
+
AGENT_DISPATCH_HARNESSES = HARNESS_REGISTRY.filter((h) => h.capabilities.agentDispatch);
|
|
10936
|
+
CONFIG_IMPORTER_HARNESSES = HARNESS_REGISTRY.filter((h) => h.capabilities.configImport);
|
|
10937
|
+
DETECTION_HARNESSES = HARNESS_REGISTRY.filter((h) => h.capabilities.detection);
|
|
10938
|
+
V1_RESOLUTION_ORDER = [...HARNESS_REGISTRY].sort((a, b) => b.id.length - a.id.length);
|
|
10002
10939
|
});
|
|
10003
10940
|
|
|
10004
|
-
// src/core/config-migration.ts
|
|
10941
|
+
// src/core/config/config-migration.ts
|
|
10005
10942
|
function compareConfigVersion(a, b) {
|
|
10006
10943
|
const partsA = normalizeVersion(a);
|
|
10007
10944
|
const partsB = normalizeVersion(b);
|
|
@@ -10450,14 +11387,7 @@ function migrateConfigShape(raw) {
|
|
|
10450
11387
|
return { changed, result };
|
|
10451
11388
|
}
|
|
10452
11389
|
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;
|
|
11390
|
+
return v1ProfilePlatform(name);
|
|
10461
11391
|
}
|
|
10462
11392
|
function mapV1ProcessName(name) {
|
|
10463
11393
|
switch (name) {
|
|
@@ -10486,6 +11416,7 @@ function mapV1ProcessName(name) {
|
|
|
10486
11416
|
}
|
|
10487
11417
|
var CURRENT_CONFIG_VERSION = "0.8.0";
|
|
10488
11418
|
var init_config_migration = __esm(() => {
|
|
11419
|
+
init_harnesses();
|
|
10489
11420
|
init_warn();
|
|
10490
11421
|
});
|
|
10491
11422
|
|
|
@@ -10536,10 +11467,10 @@ var init_util = __esm(() => {
|
|
|
10536
11467
|
util2.assertEqual = (_) => {};
|
|
10537
11468
|
function assertIs(_arg) {}
|
|
10538
11469
|
util2.assertIs = assertIs;
|
|
10539
|
-
function
|
|
11470
|
+
function assertNever2(_x) {
|
|
10540
11471
|
throw new Error;
|
|
10541
11472
|
}
|
|
10542
|
-
util2.assertNever =
|
|
11473
|
+
util2.assertNever = assertNever2;
|
|
10543
11474
|
util2.arrayToEnum = (items) => {
|
|
10544
11475
|
const obj = {};
|
|
10545
11476
|
for (const item of items) {
|
|
@@ -10933,8 +11864,8 @@ class ParseStatus {
|
|
|
10933
11864
|
}
|
|
10934
11865
|
}
|
|
10935
11866
|
var makeIssue = (params) => {
|
|
10936
|
-
const { data, path:
|
|
10937
|
-
const fullPath = [...
|
|
11867
|
+
const { data, path: path10, errorMaps, issueData } = params;
|
|
11868
|
+
const fullPath = [...path10, ...issueData.path || []];
|
|
10938
11869
|
const fullIssue = {
|
|
10939
11870
|
...issueData,
|
|
10940
11871
|
path: fullPath
|
|
@@ -10980,11 +11911,11 @@ var init_errorUtil = __esm(() => {
|
|
|
10980
11911
|
|
|
10981
11912
|
// node_modules/zod/v3/types.js
|
|
10982
11913
|
class ParseInputLazyPath {
|
|
10983
|
-
constructor(parent, value,
|
|
11914
|
+
constructor(parent, value, path10, key) {
|
|
10984
11915
|
this._cachedPath = [];
|
|
10985
11916
|
this.parent = parent;
|
|
10986
11917
|
this.data = value;
|
|
10987
|
-
this._path =
|
|
11918
|
+
this._path = path10;
|
|
10988
11919
|
this._key = key;
|
|
10989
11920
|
}
|
|
10990
11921
|
get path() {
|
|
@@ -14455,10 +15386,16 @@ var init_zod = __esm(() => {
|
|
|
14455
15386
|
init_external();
|
|
14456
15387
|
});
|
|
14457
15388
|
|
|
14458
|
-
// src/core/config-
|
|
14459
|
-
var
|
|
15389
|
+
// src/core/config/config-types.ts
|
|
15390
|
+
var init_config_types = __esm(() => {
|
|
15391
|
+
init_harnesses();
|
|
15392
|
+
});
|
|
15393
|
+
|
|
15394
|
+
// src/core/config/config-schema.ts
|
|
15395
|
+
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
15396
|
var init_config_schema = __esm(() => {
|
|
14461
15397
|
init_zod();
|
|
15398
|
+
init_config_types();
|
|
14462
15399
|
positiveInt = exports_external.number().int().positive();
|
|
14463
15400
|
nonNegativeNumber = exports_external.number().finite().min(0);
|
|
14464
15401
|
nonEmptyString = exports_external.string().min(1).refine((v) => v.trim().length > 0, { message: "expected a non-empty string" });
|
|
@@ -14502,7 +15439,7 @@ var init_config_schema = __esm(() => {
|
|
|
14502
15439
|
contextLength: positiveInt.optional(),
|
|
14503
15440
|
ollamaOptions: EmbeddingOllamaOptionsSchema.optional()
|
|
14504
15441
|
}).strict();
|
|
14505
|
-
AgentPlatformSchema = exports_external.enum(
|
|
15442
|
+
AgentPlatformSchema = exports_external.enum(VALID_HARNESS_IDS);
|
|
14506
15443
|
AgentProfileConfigSchema = exports_external.object({
|
|
14507
15444
|
platform: AgentPlatformSchema,
|
|
14508
15445
|
bin: exports_external.string().min(1).optional(),
|
|
@@ -14516,11 +15453,15 @@ var init_config_schema = __esm(() => {
|
|
|
14516
15453
|
profile: exports_external.string().min(1).optional(),
|
|
14517
15454
|
timeoutMs: exports_external.union([positiveInt, exports_external.null()]).optional(),
|
|
14518
15455
|
allowedTypes: exports_external.array(exports_external.string().min(1)).optional(),
|
|
15456
|
+
minPoolSize: exports_external.number().int().min(0).optional(),
|
|
14519
15457
|
qualityGate: exports_external.object({ enabled: exports_external.boolean().optional() }).strict().optional(),
|
|
14520
15458
|
contradictionDetection: exports_external.object({ enabled: exports_external.boolean().optional() }).strict().optional(),
|
|
14521
15459
|
defaultSince: exports_external.string().min(1).optional(),
|
|
14522
15460
|
maxTotalChars: positiveInt.optional(),
|
|
14523
15461
|
maxChunkSize: exports_external.number().int().min(1).max(50).optional(),
|
|
15462
|
+
minNewSessions: exports_external.number().int().min(0).optional(),
|
|
15463
|
+
indexSessions: exports_external.boolean().optional(),
|
|
15464
|
+
minSessionDuration: exports_external.number().min(0).optional(),
|
|
14524
15465
|
applyMode: exports_external.enum(["queue", "promote"]).optional(),
|
|
14525
15466
|
policy: exports_external.string().min(1).optional(),
|
|
14526
15467
|
maxAcceptsPerRun: positiveInt.optional(),
|
|
@@ -14778,6 +15719,13 @@ var init_config_schema = __esm(() => {
|
|
|
14778
15719
|
metadataEnhance: MetadataEnhanceSchema.optional(),
|
|
14779
15720
|
stalenessDetection: StalenessDetectionSchema.optional()
|
|
14780
15721
|
}).catchall(IndexPassConfigSchema));
|
|
15722
|
+
SetupTaskSchedulesSchema = exports_external.object({
|
|
15723
|
+
improve: exports_external.string().min(1).optional(),
|
|
15724
|
+
index: exports_external.string().min(1).optional()
|
|
15725
|
+
}).strict();
|
|
15726
|
+
SetupConfigSchema = exports_external.object({
|
|
15727
|
+
taskSchedules: SetupTaskSchedulesSchema.optional()
|
|
15728
|
+
}).strict();
|
|
14781
15729
|
AkmConfigShape = {
|
|
14782
15730
|
configVersion: exports_external.union([exports_external.string().min(1), exports_external.number()]).optional(),
|
|
14783
15731
|
profiles: ProfilesSchema.optional(),
|
|
@@ -14795,7 +15743,8 @@ var init_config_schema = __esm(() => {
|
|
|
14795
15743
|
search: SearchConfigSchema.optional(),
|
|
14796
15744
|
feedback: FeedbackConfigSchema.optional(),
|
|
14797
15745
|
archiveRetentionDays: nonNegativeNumber.optional(),
|
|
14798
|
-
improve: ImproveConfigSchema.optional()
|
|
15746
|
+
improve: ImproveConfigSchema.optional(),
|
|
15747
|
+
setup: SetupConfigSchema.optional()
|
|
14799
15748
|
};
|
|
14800
15749
|
AkmConfigBaseSchema = exports_external.object(AkmConfigShape).strict();
|
|
14801
15750
|
AkmConfigSchema = AkmConfigBaseSchema.superRefine((config, ctx) => {
|
|
@@ -14818,8 +15767,8 @@ var init_config_schema = __esm(() => {
|
|
|
14818
15767
|
});
|
|
14819
15768
|
});
|
|
14820
15769
|
|
|
14821
|
-
// src/core/config-sources.ts
|
|
14822
|
-
import { createHash } from "crypto";
|
|
15770
|
+
// src/core/config/config-sources.ts
|
|
15771
|
+
import { createHash as createHash2 } from "crypto";
|
|
14823
15772
|
function deriveStashEntryName(entry) {
|
|
14824
15773
|
if (entry.name)
|
|
14825
15774
|
return entry.name;
|
|
@@ -14828,7 +15777,7 @@ function deriveStashEntryName(entry) {
|
|
|
14828
15777
|
path: entry.path ?? null,
|
|
14829
15778
|
url: entry.url ?? null
|
|
14830
15779
|
});
|
|
14831
|
-
const hash =
|
|
15780
|
+
const hash = createHash2("sha256").update(seed).digest("hex").slice(0, 8);
|
|
14832
15781
|
return `${entry.type}-${hash}`;
|
|
14833
15782
|
}
|
|
14834
15783
|
function parseSourceSpec(entry) {
|
|
@@ -14897,7 +15846,7 @@ function toConfiguredSource(persisted, isPrimary) {
|
|
|
14897
15846
|
}
|
|
14898
15847
|
var init_config_sources = () => {};
|
|
14899
15848
|
|
|
14900
|
-
// src/core/config.ts
|
|
15849
|
+
// src/core/config/config.ts
|
|
14901
15850
|
var exports_config = {};
|
|
14902
15851
|
__export(exports_config, {
|
|
14903
15852
|
updateConfig: () => updateConfig,
|
|
@@ -14915,12 +15864,13 @@ __export(exports_config, {
|
|
|
14915
15864
|
getIndexPassConfig: () => getIndexPassConfig,
|
|
14916
15865
|
getEffectiveRegistries: () => getEffectiveRegistries,
|
|
14917
15866
|
getDefaultLlmConfig: () => getDefaultLlmConfig,
|
|
15867
|
+
VALID_HARNESS_IDS: () => VALID_HARNESS_IDS,
|
|
14918
15868
|
FEEDBACK_FAILURE_MODES: () => FEEDBACK_FAILURE_MODES,
|
|
14919
15869
|
DEFAULT_GRAPH_EXTRACTION_BATCH_SIZE: () => DEFAULT_GRAPH_EXTRACTION_BATCH_SIZE,
|
|
14920
15870
|
DEFAULT_CONFIG: () => DEFAULT_CONFIG
|
|
14921
15871
|
});
|
|
14922
|
-
import
|
|
14923
|
-
import
|
|
15872
|
+
import fs11 from "fs";
|
|
15873
|
+
import path10 from "path";
|
|
14924
15874
|
function resolveBatchSize(configured, contextLength) {
|
|
14925
15875
|
const base = configured && configured > 0 ? configured : DEFAULT_GRAPH_EXTRACTION_BATCH_SIZE;
|
|
14926
15876
|
if (!contextLength || contextLength <= 0)
|
|
@@ -14935,7 +15885,7 @@ function loadUserConfig() {
|
|
|
14935
15885
|
const configPath = getConfigPath();
|
|
14936
15886
|
let stat;
|
|
14937
15887
|
try {
|
|
14938
|
-
stat =
|
|
15888
|
+
stat = fs11.statSync(configPath);
|
|
14939
15889
|
} catch {
|
|
14940
15890
|
cachedConfig = undefined;
|
|
14941
15891
|
return applyRuntimeEnvApiKeys({ ...DEFAULT_CONFIG });
|
|
@@ -14945,7 +15895,7 @@ function loadUserConfig() {
|
|
|
14945
15895
|
}
|
|
14946
15896
|
let text;
|
|
14947
15897
|
try {
|
|
14948
|
-
text =
|
|
15898
|
+
text = fs11.readFileSync(configPath, "utf8");
|
|
14949
15899
|
} catch {
|
|
14950
15900
|
cachedConfig = undefined;
|
|
14951
15901
|
return applyRuntimeEnvApiKeys({ ...DEFAULT_CONFIG });
|
|
@@ -14954,7 +15904,7 @@ function loadUserConfig() {
|
|
|
14954
15904
|
const finalConfig = applyRuntimeEnvApiKeys(parseAndValidate(text, configPath));
|
|
14955
15905
|
let finalStat = stat;
|
|
14956
15906
|
try {
|
|
14957
|
-
finalStat =
|
|
15907
|
+
finalStat = fs11.statSync(configPath);
|
|
14958
15908
|
} catch {}
|
|
14959
15909
|
cachedConfig = {
|
|
14960
15910
|
config: finalConfig,
|
|
@@ -15057,8 +16007,8 @@ function loadConfig() {
|
|
|
15057
16007
|
function saveConfig(config) {
|
|
15058
16008
|
cachedConfig = undefined;
|
|
15059
16009
|
const configPath = getConfigPath();
|
|
15060
|
-
const dir =
|
|
15061
|
-
|
|
16010
|
+
const dir = path10.dirname(configPath);
|
|
16011
|
+
fs11.mkdirSync(dir, { recursive: true });
|
|
15062
16012
|
const sanitized = sanitizeConfigForWrite(config);
|
|
15063
16013
|
const parseResult = AkmConfigSchema.safeParse(sanitized);
|
|
15064
16014
|
if (!parseResult.success) {
|
|
@@ -15203,14 +16153,14 @@ function applyRuntimeEnvApiKeys(config) {
|
|
|
15203
16153
|
return next;
|
|
15204
16154
|
}
|
|
15205
16155
|
function warnIfProjectConfigPresent(startDir) {
|
|
15206
|
-
let currentDir =
|
|
16156
|
+
let currentDir = path10.resolve(startDir);
|
|
15207
16157
|
while (true) {
|
|
15208
|
-
const configPath =
|
|
16158
|
+
const configPath = path10.join(currentDir, PROJECT_CONFIG_RELATIVE_PATH);
|
|
15209
16159
|
if (isFile(configPath) && !PROJECT_CONFIG_DEPRECATION_WARNED.has(configPath)) {
|
|
15210
16160
|
PROJECT_CONFIG_DEPRECATION_WARNED.add(configPath);
|
|
15211
16161
|
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.");
|
|
15212
16162
|
}
|
|
15213
|
-
const parentDir =
|
|
16163
|
+
const parentDir = path10.dirname(currentDir);
|
|
15214
16164
|
if (parentDir === currentDir)
|
|
15215
16165
|
break;
|
|
15216
16166
|
currentDir = parentDir;
|
|
@@ -15218,20 +16168,21 @@ function warnIfProjectConfigPresent(startDir) {
|
|
|
15218
16168
|
}
|
|
15219
16169
|
function isFile(filePath) {
|
|
15220
16170
|
try {
|
|
15221
|
-
return
|
|
16171
|
+
return fs11.statSync(filePath).isFile();
|
|
15222
16172
|
} catch {
|
|
15223
16173
|
return false;
|
|
15224
16174
|
}
|
|
15225
16175
|
}
|
|
15226
16176
|
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;
|
|
15227
|
-
var
|
|
16177
|
+
var init_config2 = __esm(() => {
|
|
16178
|
+
init_errors();
|
|
15228
16179
|
init_config_io();
|
|
15229
16180
|
init_config_migration();
|
|
15230
16181
|
init_config_schema();
|
|
15231
|
-
init_errors();
|
|
15232
16182
|
init_config_io();
|
|
15233
16183
|
init_paths();
|
|
15234
16184
|
init_warn();
|
|
16185
|
+
init_config_types();
|
|
15235
16186
|
init_config_sources();
|
|
15236
16187
|
FEEDBACK_FAILURE_MODES = [
|
|
15237
16188
|
"incorrect",
|
|
@@ -15251,12 +16202,12 @@ var init_config = __esm(() => {
|
|
|
15251
16202
|
detail: "brief"
|
|
15252
16203
|
}
|
|
15253
16204
|
};
|
|
15254
|
-
PROJECT_CONFIG_RELATIVE_PATH =
|
|
16205
|
+
PROJECT_CONFIG_RELATIVE_PATH = path10.join(".akm", "config.json");
|
|
15255
16206
|
INDEX_RESERVED_KEYS = new Set(["metadataEnhance", "stalenessDetection"]);
|
|
15256
16207
|
PROJECT_CONFIG_DEPRECATION_WARNED = new Set;
|
|
15257
16208
|
});
|
|
15258
16209
|
|
|
15259
|
-
// src/indexer/db.ts
|
|
16210
|
+
// src/indexer/db/db.ts
|
|
15260
16211
|
var exports_db = {};
|
|
15261
16212
|
__export(exports_db, {
|
|
15262
16213
|
warnIfVecMissing: () => warnIfVecMissing,
|
|
@@ -15274,7 +16225,7 @@ __export(exports_db, {
|
|
|
15274
16225
|
relinkUsageEvents: () => relinkUsageEvents,
|
|
15275
16226
|
rebuildFts: () => rebuildFts,
|
|
15276
16227
|
openExistingDatabase: () => openExistingDatabase,
|
|
15277
|
-
openDatabase: () =>
|
|
16228
|
+
openDatabase: () => openDatabase2,
|
|
15278
16229
|
isVecAvailable: () => isVecAvailable,
|
|
15279
16230
|
getZeroResultSearches: () => getZeroResultSearches,
|
|
15280
16231
|
getUtilityScoresByIds: () => getUtilityScoresByIds,
|
|
@@ -15287,11 +16238,15 @@ __export(exports_db, {
|
|
|
15287
16238
|
getLlmCacheEntry: () => getLlmCacheEntry,
|
|
15288
16239
|
getLlmCacheEntriesByRefs: () => getLlmCacheEntriesByRefs,
|
|
15289
16240
|
getIndexDirState: () => getIndexDirState,
|
|
16241
|
+
getEntryRefRowsForStashRoot: () => getEntryRefRowsForStashRoot,
|
|
16242
|
+
getEntryIdByFilePath: () => getEntryIdByFilePath,
|
|
16243
|
+
getEntryFilePathById: () => getEntryFilePathById,
|
|
15290
16244
|
getEntryCount: () => getEntryCount,
|
|
15291
16245
|
getEntryByRef: () => getEntryByRef,
|
|
15292
16246
|
getEntryById: () => getEntryById,
|
|
15293
16247
|
getEntriesByDir: () => getEntriesByDir,
|
|
15294
16248
|
getEmbeddingCount: () => getEmbeddingCount,
|
|
16249
|
+
getEmbeddableEntryCount: () => getEmbeddableEntryCount,
|
|
15295
16250
|
getDerivedForParent: () => getDerivedForParent,
|
|
15296
16251
|
getAllEntriesForEmbedding: () => getAllEntriesForEmbedding,
|
|
15297
16252
|
getAllEntries: () => getAllEntries,
|
|
@@ -15303,6 +16258,7 @@ __export(exports_db, {
|
|
|
15303
16258
|
deleteEntriesByDir: () => deleteEntriesByDir,
|
|
15304
16259
|
computeSourceHash: () => computeSourceHash,
|
|
15305
16260
|
computeBodyHash: () => computeBodyHash,
|
|
16261
|
+
collectTagSetFromEntries: () => collectTagSetFromEntries,
|
|
15306
16262
|
closeDatabase: () => closeDatabase,
|
|
15307
16263
|
clearStaleCacheEntries: () => clearStaleCacheEntries,
|
|
15308
16264
|
bumpUtilityScoresBatch: () => bumpUtilityScoresBatch,
|
|
@@ -15313,17 +16269,16 @@ __export(exports_db, {
|
|
|
15313
16269
|
EMBEDDING_DIM: () => EMBEDDING_DIM,
|
|
15314
16270
|
DB_VERSION: () => DB_VERSION
|
|
15315
16271
|
});
|
|
15316
|
-
import
|
|
15317
|
-
import
|
|
15318
|
-
import
|
|
15319
|
-
|
|
15320
|
-
function openDatabase(dbPath, options) {
|
|
16272
|
+
import fs12 from "fs";
|
|
16273
|
+
import { createRequire as createRequire3 } from "module";
|
|
16274
|
+
import path11 from "path";
|
|
16275
|
+
function openDatabase2(dbPath, options) {
|
|
15321
16276
|
const resolvedPath = dbPath ?? getDbPath();
|
|
15322
|
-
const dir =
|
|
15323
|
-
if (!
|
|
15324
|
-
|
|
16277
|
+
const dir = path11.dirname(resolvedPath);
|
|
16278
|
+
if (!fs12.existsSync(dir)) {
|
|
16279
|
+
fs12.mkdirSync(dir, { recursive: true });
|
|
15325
16280
|
}
|
|
15326
|
-
const db =
|
|
16281
|
+
const db = openDatabase(resolvedPath);
|
|
15327
16282
|
db.exec("PRAGMA journal_mode = WAL");
|
|
15328
16283
|
db.exec("PRAGMA busy_timeout = 5000");
|
|
15329
16284
|
db.exec("PRAGMA foreign_keys = ON");
|
|
@@ -15335,7 +16290,7 @@ function openDatabase(dbPath, options) {
|
|
|
15335
16290
|
}
|
|
15336
16291
|
function resolveConfiguredEmbeddingDim() {
|
|
15337
16292
|
try {
|
|
15338
|
-
const { loadConfig: loadConfig2 } = (
|
|
16293
|
+
const { loadConfig: loadConfig2 } = (init_config2(), __toCommonJS(exports_config));
|
|
15339
16294
|
const dim = loadConfig2().embedding?.dimension;
|
|
15340
16295
|
if (typeof dim === "number" && Number.isInteger(dim) && dim > 0 && dim <= 4096) {
|
|
15341
16296
|
return dim;
|
|
@@ -15347,7 +16302,7 @@ function resolveConfiguredEmbeddingDim() {
|
|
|
15347
16302
|
}
|
|
15348
16303
|
function openExistingDatabase(dbPath) {
|
|
15349
16304
|
const resolvedPath = dbPath ?? getDbPath();
|
|
15350
|
-
const db =
|
|
16305
|
+
const db = openDatabase(resolvedPath);
|
|
15351
16306
|
db.exec("PRAGMA journal_mode = WAL");
|
|
15352
16307
|
db.exec("PRAGMA busy_timeout = 5000");
|
|
15353
16308
|
db.exec("PRAGMA foreign_keys = ON");
|
|
@@ -15359,7 +16314,7 @@ function closeDatabase(db) {
|
|
|
15359
16314
|
}
|
|
15360
16315
|
function loadVecExtension(db) {
|
|
15361
16316
|
try {
|
|
15362
|
-
const esmRequire =
|
|
16317
|
+
const esmRequire = createRequire3(import.meta.url);
|
|
15363
16318
|
const sqliteVec = esmRequire("sqlite-vec");
|
|
15364
16319
|
sqliteVec.load(db);
|
|
15365
16320
|
vecStatus.set(db, true);
|
|
@@ -15375,7 +16330,7 @@ function warnIfVecMissing(db, { once } = { once: false }) {
|
|
|
15375
16330
|
return;
|
|
15376
16331
|
if (once && vecInitWarnedDbs.has(db))
|
|
15377
16332
|
return;
|
|
15378
|
-
|
|
16333
|
+
bestEffort(() => {
|
|
15379
16334
|
const row = db.prepare("SELECT COUNT(*) AS cnt FROM embeddings").get();
|
|
15380
16335
|
const count = row?.cnt ?? 0;
|
|
15381
16336
|
if (count >= VEC_FALLBACK_THRESHOLD) {
|
|
@@ -15384,7 +16339,7 @@ function warnIfVecMissing(db, { once } = { once: false }) {
|
|
|
15384
16339
|
if (once)
|
|
15385
16340
|
vecInitWarnedDbs.add(db);
|
|
15386
16341
|
}
|
|
15387
|
-
}
|
|
16342
|
+
}, "embeddings table may not exist yet during init");
|
|
15388
16343
|
}
|
|
15389
16344
|
function ensureSchema(db, embeddingDim, options) {
|
|
15390
16345
|
db.exec(`
|
|
@@ -15590,12 +16545,8 @@ function ensureSchema(db, embeddingDim, options) {
|
|
|
15590
16545
|
const storedDim = getMeta(db, "embeddingDim");
|
|
15591
16546
|
if (storedDim && storedDim !== String(embeddingDim)) {
|
|
15592
16547
|
backupBeforeEmbeddingDimChange(options?.dataDir, storedDim, String(embeddingDim));
|
|
15593
|
-
|
|
15594
|
-
|
|
15595
|
-
} catch {}
|
|
15596
|
-
try {
|
|
15597
|
-
db.exec("DELETE FROM embeddings");
|
|
15598
|
-
} catch {}
|
|
16548
|
+
bestEffort(() => db.exec("DROP TABLE IF EXISTS entries_vec"), "drop entries_vec on dim change");
|
|
16549
|
+
bestEffort(() => db.exec("DELETE FROM embeddings"), "delete stale embeddings on dim change");
|
|
15599
16550
|
setMeta(db, "hasEmbeddings", "0");
|
|
15600
16551
|
}
|
|
15601
16552
|
}
|
|
@@ -15619,9 +16570,7 @@ function ensureSchema(db, embeddingDim, options) {
|
|
|
15619
16570
|
const storedDim = getMeta(db, "embeddingDim");
|
|
15620
16571
|
if (storedDim && storedDim !== String(embeddingDim)) {
|
|
15621
16572
|
backupBeforeEmbeddingDimChange(options?.dataDir, storedDim, String(embeddingDim));
|
|
15622
|
-
|
|
15623
|
-
db.exec("DELETE FROM embeddings");
|
|
15624
|
-
} catch {}
|
|
16573
|
+
bestEffort(() => db.exec("DELETE FROM embeddings"), "delete embeddings on explicit dim change");
|
|
15625
16574
|
setMeta(db, "hasEmbeddings", "0");
|
|
15626
16575
|
}
|
|
15627
16576
|
setMeta(db, "embeddingDim", String(embeddingDim));
|
|
@@ -15636,9 +16585,9 @@ function handleVersionUpgrade(db) {
|
|
|
15636
16585
|
if (storedVersion === undefined || storedVersion === "" || storedVersion === String(DB_VERSION))
|
|
15637
16586
|
return [];
|
|
15638
16587
|
let usageBackup = [];
|
|
15639
|
-
|
|
16588
|
+
bestEffort(() => {
|
|
15640
16589
|
usageBackup = db.prepare("SELECT * FROM usage_events").all();
|
|
15641
|
-
}
|
|
16590
|
+
}, "usage_events table may not exist in older versions");
|
|
15642
16591
|
db.exec("DROP TABLE IF EXISTS utility_scores");
|
|
15643
16592
|
db.exec("DROP TABLE IF EXISTS utility_scores_scoped");
|
|
15644
16593
|
db.exec("DROP INDEX IF EXISTS idx_utility_scores_scoped_entry_id");
|
|
@@ -15755,7 +16704,7 @@ function deleteIndexDirState(db, dirPath) {
|
|
|
15755
16704
|
db.prepare("DELETE FROM index_dir_state WHERE dir_path = ?").run(dirPath);
|
|
15756
16705
|
}
|
|
15757
16706
|
function deleteIndexDirStatesByStashDir(db, stashDir) {
|
|
15758
|
-
db.prepare("DELETE FROM index_dir_state WHERE dir_path = ? OR dir_path LIKE ?").run(stashDir, `${stashDir}${
|
|
16707
|
+
db.prepare("DELETE FROM index_dir_state WHERE dir_path = ? OR dir_path LIKE ?").run(stashDir, `${stashDir}${path11.sep}%`);
|
|
15759
16708
|
}
|
|
15760
16709
|
function upsertEntry(db, entryKey, dirPath, filePath, stashDir, entry, searchText) {
|
|
15761
16710
|
const stmts = getUpsertStmts(db);
|
|
@@ -15790,14 +16739,14 @@ function getUpsertStmts(db) {
|
|
|
15790
16739
|
return stmts;
|
|
15791
16740
|
}
|
|
15792
16741
|
function ensureDerivedFromColumn(db) {
|
|
15793
|
-
|
|
16742
|
+
bestEffort(() => {
|
|
15794
16743
|
const cols = db.prepare("PRAGMA table_info(entries)").all();
|
|
15795
16744
|
const hasColumn = cols.some((c) => c.name === "derived_from");
|
|
15796
16745
|
if (!hasColumn) {
|
|
15797
16746
|
db.exec("ALTER TABLE entries ADD COLUMN derived_from TEXT");
|
|
15798
16747
|
}
|
|
15799
16748
|
db.exec("CREATE INDEX IF NOT EXISTS idx_entries_derived_from ON entries(derived_from)");
|
|
15800
|
-
}
|
|
16749
|
+
}, "entries table may not exist on a brand-new DB before CREATE \u2014 caller is responsible");
|
|
15801
16750
|
}
|
|
15802
16751
|
function getDerivedForParent(db, parentRef) {
|
|
15803
16752
|
if (!parentRef)
|
|
@@ -15837,7 +16786,7 @@ function getPositiveFeedbackCountsByIds(db, ids) {
|
|
|
15837
16786
|
for (let i = 0;i < ids.length; i += SQLITE_CHUNK_SIZE) {
|
|
15838
16787
|
const chunk = ids.slice(i, i + SQLITE_CHUNK_SIZE);
|
|
15839
16788
|
const placeholders = chunk.map(() => "?").join(",");
|
|
15840
|
-
|
|
16789
|
+
bestEffort(() => {
|
|
15841
16790
|
const rows = db.prepare(`SELECT entry_id, COUNT(*) AS cnt
|
|
15842
16791
|
FROM usage_events
|
|
15843
16792
|
WHERE event_type = 'feedback'
|
|
@@ -15849,7 +16798,7 @@ function getPositiveFeedbackCountsByIds(db, ids) {
|
|
|
15849
16798
|
result.set(row.entry_id, row.cnt);
|
|
15850
16799
|
}
|
|
15851
16800
|
}
|
|
15852
|
-
}
|
|
16801
|
+
}, "usage_events table may be missing on legacy DBs \u2014 treat as zero counts");
|
|
15853
16802
|
}
|
|
15854
16803
|
return result;
|
|
15855
16804
|
}
|
|
@@ -15874,33 +16823,19 @@ function deleteRelatedRows(db, ids) {
|
|
|
15874
16823
|
for (let i = 0;i < numericIds.length; i += SQLITE_CHUNK_SIZE) {
|
|
15875
16824
|
const chunk = numericIds.slice(i, i + SQLITE_CHUNK_SIZE);
|
|
15876
16825
|
const placeholders = chunk.map(() => "?").join(",");
|
|
15877
|
-
|
|
15878
|
-
|
|
15879
|
-
} catch {}
|
|
15880
|
-
try {
|
|
15881
|
-
db.prepare(`DELETE FROM entries_fts_dirty WHERE entry_id IN (${placeholders})`).run(...chunk);
|
|
15882
|
-
} catch {}
|
|
16826
|
+
bestEffort(() => db.prepare(`DELETE FROM entries_fts WHERE entry_id IN (${placeholders})`).run(...chunk), "fts table may not exist on a brand-new db");
|
|
16827
|
+
bestEffort(() => db.prepare(`DELETE FROM entries_fts_dirty WHERE entry_id IN (${placeholders})`).run(...chunk), "fts dirty table is created lazily by upsertEntry");
|
|
15883
16828
|
}
|
|
15884
16829
|
for (let i = 0;i < numericIds.length; i += SQLITE_CHUNK_SIZE) {
|
|
15885
16830
|
const chunk = numericIds.slice(i, i + SQLITE_CHUNK_SIZE);
|
|
15886
16831
|
const placeholders = chunk.map(() => "?").join(",");
|
|
15887
|
-
|
|
15888
|
-
db.prepare(`DELETE FROM embeddings WHERE id IN (${placeholders})`).run(...chunk);
|
|
15889
|
-
} catch {}
|
|
16832
|
+
bestEffort(() => db.prepare(`DELETE FROM embeddings WHERE id IN (${placeholders})`).run(...chunk), "delete embeddings for entries");
|
|
15890
16833
|
if (vecAvail) {
|
|
15891
|
-
|
|
15892
|
-
db.prepare(`DELETE FROM entries_vec WHERE id IN (${placeholders})`).run(...chunk);
|
|
15893
|
-
} catch {}
|
|
16834
|
+
bestEffort(() => db.prepare(`DELETE FROM entries_vec WHERE id IN (${placeholders})`).run(...chunk), "delete entries_vec for entries");
|
|
15894
16835
|
}
|
|
15895
|
-
|
|
15896
|
-
|
|
15897
|
-
|
|
15898
|
-
try {
|
|
15899
|
-
db.prepare(`DELETE FROM utility_scores_scoped WHERE entry_id IN (${placeholders})`).run(...chunk);
|
|
15900
|
-
} catch {}
|
|
15901
|
-
try {
|
|
15902
|
-
db.prepare(`DELETE FROM usage_events WHERE entry_id IN (${placeholders})`).run(...chunk);
|
|
15903
|
-
} catch {}
|
|
16836
|
+
bestEffort(() => db.prepare(`DELETE FROM utility_scores WHERE entry_id IN (${placeholders})`).run(...chunk), "delete utility_scores for entries");
|
|
16837
|
+
bestEffort(() => db.prepare(`DELETE FROM utility_scores_scoped WHERE entry_id IN (${placeholders})`).run(...chunk), "delete utility_scores_scoped for entries");
|
|
16838
|
+
bestEffort(() => db.prepare(`DELETE FROM usage_events WHERE entry_id IN (${placeholders})`).run(...chunk), "delete usage_events for entries");
|
|
15904
16839
|
}
|
|
15905
16840
|
}
|
|
15906
16841
|
function deleteEntriesByIds(db, ids) {
|
|
@@ -15963,12 +16898,12 @@ function upsertEmbedding(db, entryId, embedding) {
|
|
|
15963
16898
|
const buf = float32Buffer(embedding);
|
|
15964
16899
|
db.prepare("INSERT OR REPLACE INTO embeddings (id, embedding) VALUES (?, ?)").run(entryId, buf);
|
|
15965
16900
|
if (isVecAvailable(db)) {
|
|
15966
|
-
|
|
16901
|
+
bestEffort(() => {
|
|
15967
16902
|
db.transaction(() => {
|
|
15968
16903
|
db.prepare("DELETE FROM entries_vec WHERE id = ?").run(entryId);
|
|
15969
16904
|
db.prepare("INSERT INTO entries_vec (id, embedding) VALUES (?, ?)").run(entryId, buf);
|
|
15970
16905
|
})();
|
|
15971
|
-
}
|
|
16906
|
+
}, "vec table unavailable or constraint failure");
|
|
15972
16907
|
}
|
|
15973
16908
|
return true;
|
|
15974
16909
|
}
|
|
@@ -16172,6 +17107,10 @@ function getEntryCount(db) {
|
|
|
16172
17107
|
const row = db.prepare("SELECT COUNT(*) AS cnt FROM entries").get();
|
|
16173
17108
|
return row.cnt;
|
|
16174
17109
|
}
|
|
17110
|
+
function getEmbeddableEntryCount(db) {
|
|
17111
|
+
const row = db.prepare("SELECT COUNT(*) AS cnt FROM entries").get();
|
|
17112
|
+
return row.cnt;
|
|
17113
|
+
}
|
|
16175
17114
|
function getEmbeddingCount(db) {
|
|
16176
17115
|
const row = db.prepare("SELECT COUNT(*) AS cnt FROM embeddings").get();
|
|
16177
17116
|
return row.cnt;
|
|
@@ -16193,6 +17132,17 @@ function getEntriesByDir(db, dirPath) {
|
|
|
16193
17132
|
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);
|
|
16194
17133
|
return parseEntryRows(rows, "getEntriesByDir");
|
|
16195
17134
|
}
|
|
17135
|
+
function getEntryIdByFilePath(db, filePath) {
|
|
17136
|
+
const row = db.prepare("SELECT id FROM entries WHERE file_path = ? LIMIT 1").get(filePath);
|
|
17137
|
+
return row?.id;
|
|
17138
|
+
}
|
|
17139
|
+
function getEntryFilePathById(db, id) {
|
|
17140
|
+
const row = db.prepare("SELECT file_path FROM entries WHERE id = ?").get(id);
|
|
17141
|
+
return row?.file_path;
|
|
17142
|
+
}
|
|
17143
|
+
function getEntryRefRowsForStashRoot(db, stashRoot) {
|
|
17144
|
+
return db.prepare("SELECT file_path, entry_json FROM entries WHERE stash_dir = ? OR file_path LIKE ?").all(stashRoot, `${stashRoot}%`);
|
|
17145
|
+
}
|
|
16196
17146
|
function getUtilityScore(db, entryId) {
|
|
16197
17147
|
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);
|
|
16198
17148
|
if (!row)
|
|
@@ -16302,18 +17252,16 @@ function upsertLlmCacheEntry(db, assetRef, bodyHash, resultJson, cacheVariant =
|
|
|
16302
17252
|
updated_at = excluded.updated_at`).run(assetRef, cacheVariant, bodyHash, resultJson, Date.now());
|
|
16303
17253
|
}
|
|
16304
17254
|
function clearStaleCacheEntries(db) {
|
|
16305
|
-
|
|
17255
|
+
bestEffort(() => {
|
|
16306
17256
|
db.exec(`
|
|
16307
17257
|
DELETE FROM llm_enrichment_cache
|
|
16308
17258
|
WHERE asset_ref NOT IN (SELECT file_path FROM entries)
|
|
16309
17259
|
AND asset_ref NOT IN (SELECT entry_key FROM entries)
|
|
16310
17260
|
`);
|
|
16311
|
-
}
|
|
17261
|
+
}, "llm_enrichment_cache may not exist in very old DBs opened without ensureSchema");
|
|
16312
17262
|
}
|
|
16313
17263
|
function computeBodyHash(body) {
|
|
16314
|
-
|
|
16315
|
-
hasher.update(body);
|
|
16316
|
-
return hasher.digest("hex");
|
|
17264
|
+
return sha256Hex(body);
|
|
16317
17265
|
}
|
|
16318
17266
|
function getRetrievalCounts(db, refs) {
|
|
16319
17267
|
if (refs.length === 0)
|
|
@@ -16368,7 +17316,6 @@ function getAllEntriesForEmbedding(db) {
|
|
|
16368
17316
|
return db.prepare(`
|
|
16369
17317
|
SELECT e.id, e.search_text AS searchText, e.entry_key AS entryKey, e.file_path AS filePath FROM entries e
|
|
16370
17318
|
WHERE NOT EXISTS (SELECT 1 FROM embeddings b WHERE b.id = e.id)
|
|
16371
|
-
AND e.entry_type != 'vault'
|
|
16372
17319
|
`).all();
|
|
16373
17320
|
}
|
|
16374
17321
|
function upsertWorkflowDocument(db, entryId, doc, content) {
|
|
@@ -16432,7 +17379,7 @@ function applyFeedbackToUtilityScore(db, entryId, positiveCount, negativeCount)
|
|
|
16432
17379
|
return { previousUtility, nextUtility, crossedReviewThreshold };
|
|
16433
17380
|
}
|
|
16434
17381
|
function relinkUsageEvents(db) {
|
|
16435
|
-
|
|
17382
|
+
bestEffort(() => {
|
|
16436
17383
|
db.exec(`
|
|
16437
17384
|
UPDATE usage_events
|
|
16438
17385
|
SET entry_id = NULL
|
|
@@ -16447,7 +17394,7 @@ function relinkUsageEvents(db) {
|
|
|
16447
17394
|
)
|
|
16448
17395
|
WHERE entry_id IS NULL AND entry_ref IS NOT NULL
|
|
16449
17396
|
`);
|
|
16450
|
-
}
|
|
17397
|
+
}, "usage_events table may not exist yet during entry_id re-resolution");
|
|
16451
17398
|
}
|
|
16452
17399
|
function upsertRegistryIndexCache(db, registryUrl, indexJson, opts) {
|
|
16453
17400
|
db.prepare(`
|
|
@@ -16470,20 +17417,44 @@ function getRegistryIndexCache(db, registryUrl, maxAgeMs = 3600000) {
|
|
|
16470
17417
|
return;
|
|
16471
17418
|
return { indexJson: row.index_json, etag: row.etag, lastModified: row.last_modified };
|
|
16472
17419
|
}
|
|
17420
|
+
function collectTagSetFromEntries(db, entryType) {
|
|
17421
|
+
const tags = new Set;
|
|
17422
|
+
const stmt = entryType ? db.prepare("SELECT entry_json FROM entries WHERE entry_type = ?") : db.prepare("SELECT entry_json FROM entries");
|
|
17423
|
+
const rows = entryType ? stmt.all(entryType) : stmt.all();
|
|
17424
|
+
for (const row of rows) {
|
|
17425
|
+
let parsed;
|
|
17426
|
+
try {
|
|
17427
|
+
parsed = JSON.parse(row.entry_json);
|
|
17428
|
+
} catch {
|
|
17429
|
+
continue;
|
|
17430
|
+
}
|
|
17431
|
+
if (!Array.isArray(parsed.tags))
|
|
17432
|
+
continue;
|
|
17433
|
+
for (const tag of parsed.tags) {
|
|
17434
|
+
if (typeof tag === "string" && tag.trim().length > 0) {
|
|
17435
|
+
tags.add(tag.trim().toLowerCase());
|
|
17436
|
+
}
|
|
17437
|
+
}
|
|
17438
|
+
}
|
|
17439
|
+
return tags;
|
|
17440
|
+
}
|
|
16473
17441
|
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;
|
|
16474
17442
|
var init_db = __esm(() => {
|
|
16475
17443
|
init_asset_ref();
|
|
17444
|
+
init_best_effort();
|
|
16476
17445
|
init_paths();
|
|
16477
17446
|
init_state_db();
|
|
16478
17447
|
init_warn();
|
|
16479
17448
|
init_types();
|
|
17449
|
+
init_runtime();
|
|
17450
|
+
init_database();
|
|
16480
17451
|
init_db_backup();
|
|
16481
17452
|
vecStatus = new WeakMap;
|
|
16482
17453
|
vecInitWarnedDbs = new WeakSet;
|
|
16483
17454
|
upsertStmtsByDb = new WeakMap;
|
|
16484
17455
|
});
|
|
16485
17456
|
|
|
16486
|
-
// src/indexer/graph-db.ts
|
|
17457
|
+
// src/indexer/db/graph-db.ts
|
|
16487
17458
|
var exports_graph_db = {};
|
|
16488
17459
|
__export(exports_graph_db, {
|
|
16489
17460
|
resolveEntryIdForPath: () => resolveEntryIdForPath,
|
|
@@ -16495,12 +17466,12 @@ __export(exports_graph_db, {
|
|
|
16495
17466
|
loadGraphEntitiesByEntry: () => loadGraphEntitiesByEntry,
|
|
16496
17467
|
deleteStoredGraph: () => deleteStoredGraph
|
|
16497
17468
|
});
|
|
16498
|
-
import
|
|
17469
|
+
import fs13 from "fs";
|
|
16499
17470
|
function withReadableGraphDb(db, fn) {
|
|
16500
17471
|
if (db)
|
|
16501
17472
|
return fn(db);
|
|
16502
17473
|
const dbPath = getDbPath();
|
|
16503
|
-
if (!
|
|
17474
|
+
if (!fs13.existsSync(dbPath))
|
|
16504
17475
|
throw new Error("GRAPH_DB_MISSING");
|
|
16505
17476
|
const opened = openExistingDatabase(dbPath);
|
|
16506
17477
|
try {
|
|
@@ -16720,7 +17691,8 @@ function loadStoredGraphMeta(stashPath, db) {
|
|
|
16720
17691
|
cacheHits: row.cache_hits,
|
|
16721
17692
|
cacheMisses: row.cache_misses,
|
|
16722
17693
|
truncationCount: row.truncation_count,
|
|
16723
|
-
failureCount: row.failure_count
|
|
17694
|
+
failureCount: row.failure_count,
|
|
17695
|
+
retryAttempts: 0
|
|
16724
17696
|
}
|
|
16725
17697
|
};
|
|
16726
17698
|
} catch {
|
|
@@ -16820,10 +17792,17 @@ var init_graph_db = __esm(() => {
|
|
|
16820
17792
|
|
|
16821
17793
|
// scripts/migrate-storage.ts
|
|
16822
17794
|
init_paths();
|
|
16823
|
-
import
|
|
16824
|
-
import
|
|
16825
|
-
import
|
|
17795
|
+
import fs14 from "fs";
|
|
17796
|
+
import os3 from "os";
|
|
17797
|
+
import path12 from "path";
|
|
16826
17798
|
import readline from "readline";
|
|
17799
|
+
|
|
17800
|
+
// src/indexer/usage/unmigrated-vaults-guard.ts
|
|
17801
|
+
init_warn();
|
|
17802
|
+
var MIGRATED_MARKER = ".migrated";
|
|
17803
|
+
var warnedStashDirs = new Set;
|
|
17804
|
+
|
|
17805
|
+
// scripts/migrate-storage.ts
|
|
16827
17806
|
var args = process.argv.slice(2);
|
|
16828
17807
|
var DRY_RUN = args.includes("--dry-run");
|
|
16829
17808
|
var YES = args.includes("--yes");
|
|
@@ -16840,12 +17819,12 @@ function parseFromArg() {
|
|
|
16840
17819
|
return val;
|
|
16841
17820
|
}
|
|
16842
17821
|
var FROM_VERSION = parseFromArg();
|
|
16843
|
-
var dataDir = process.env.AKM_DATA_DIR?.trim() ?? (process.env.XDG_DATA_HOME?.trim() ?
|
|
16844
|
-
var stateDir = process.env.AKM_STATE_DIR?.trim() ?? (process.env.XDG_STATE_HOME?.trim() ?
|
|
17822
|
+
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"));
|
|
17823
|
+
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"));
|
|
16845
17824
|
var cacheDir = getCacheDir();
|
|
16846
17825
|
var configDir = getConfigDir();
|
|
16847
|
-
var stateDbPath =
|
|
16848
|
-
var indexDbPath =
|
|
17826
|
+
var stateDbPath = path12.join(dataDir, "state.db");
|
|
17827
|
+
var indexDbPath = path12.join(dataDir, "index.db");
|
|
16849
17828
|
var PATHS = {
|
|
16850
17829
|
cacheDir,
|
|
16851
17830
|
configDir,
|
|
@@ -16856,92 +17835,97 @@ var PATHS = {
|
|
|
16856
17835
|
};
|
|
16857
17836
|
var versionReports = [];
|
|
16858
17837
|
function ensureDir(dir) {
|
|
16859
|
-
if (!
|
|
16860
|
-
|
|
17838
|
+
if (!fs14.existsSync(dir)) {
|
|
17839
|
+
fs14.mkdirSync(dir, { recursive: true });
|
|
16861
17840
|
}
|
|
16862
17841
|
}
|
|
16863
17842
|
function copyAndVerify(src, dest) {
|
|
16864
|
-
|
|
16865
|
-
const srcStat =
|
|
16866
|
-
const destStat =
|
|
17843
|
+
fs14.copyFileSync(src, dest);
|
|
17844
|
+
const srcStat = fs14.statSync(src);
|
|
17845
|
+
const destStat = fs14.statSync(dest);
|
|
16867
17846
|
return destStat.size === srcStat.size;
|
|
16868
17847
|
}
|
|
16869
|
-
function
|
|
17848
|
+
function copyTree(src, dest, opts) {
|
|
16870
17849
|
let copied = 0;
|
|
17850
|
+
let skipped = 0;
|
|
16871
17851
|
let failed = 0;
|
|
16872
17852
|
ensureDir(dest);
|
|
16873
|
-
for (const entry of
|
|
16874
|
-
const srcEntry =
|
|
16875
|
-
const destEntry =
|
|
17853
|
+
for (const entry of fs14.readdirSync(src, { withFileTypes: true })) {
|
|
17854
|
+
const srcEntry = path12.join(src, entry.name);
|
|
17855
|
+
const destEntry = path12.join(dest, entry.name);
|
|
16876
17856
|
if (entry.isDirectory()) {
|
|
16877
|
-
const sub =
|
|
17857
|
+
const sub = copyTree(srcEntry, destEntry, opts);
|
|
16878
17858
|
copied += sub.copied;
|
|
17859
|
+
skipped += sub.skipped;
|
|
16879
17860
|
failed += sub.failed;
|
|
16880
|
-
|
|
16881
|
-
|
|
16882
|
-
|
|
16883
|
-
|
|
16884
|
-
|
|
16885
|
-
|
|
16886
|
-
|
|
16887
|
-
|
|
17861
|
+
continue;
|
|
17862
|
+
}
|
|
17863
|
+
if (!opts.clobber && fs14.existsSync(destEntry)) {
|
|
17864
|
+
skipped++;
|
|
17865
|
+
continue;
|
|
17866
|
+
}
|
|
17867
|
+
try {
|
|
17868
|
+
if (copyAndVerify(srcEntry, destEntry)) {
|
|
17869
|
+
copied++;
|
|
17870
|
+
} else {
|
|
16888
17871
|
failed++;
|
|
16889
17872
|
}
|
|
17873
|
+
} catch {
|
|
17874
|
+
failed++;
|
|
16890
17875
|
}
|
|
16891
17876
|
}
|
|
16892
|
-
return { copied, failed };
|
|
17877
|
+
return { copied, skipped, failed };
|
|
16893
17878
|
}
|
|
16894
17879
|
function countFilesRecursive(dir) {
|
|
16895
17880
|
let count = 0;
|
|
16896
|
-
for (const entry of
|
|
17881
|
+
for (const entry of fs14.readdirSync(dir, { withFileTypes: true })) {
|
|
16897
17882
|
if (entry.isDirectory()) {
|
|
16898
|
-
count += countFilesRecursive(
|
|
17883
|
+
count += countFilesRecursive(path12.join(dir, entry.name));
|
|
16899
17884
|
} else {
|
|
16900
17885
|
count++;
|
|
16901
17886
|
}
|
|
16902
17887
|
}
|
|
16903
17888
|
return count;
|
|
16904
17889
|
}
|
|
17890
|
+
async function runSteps(steps, ctx) {
|
|
17891
|
+
for (const step of steps) {
|
|
17892
|
+
ctx.recordStep(await step.run(ctx));
|
|
17893
|
+
}
|
|
17894
|
+
}
|
|
16905
17895
|
function migrateDb(ctx, filename) {
|
|
16906
|
-
const src =
|
|
16907
|
-
const dest =
|
|
16908
|
-
if (!
|
|
16909
|
-
|
|
16910
|
-
return;
|
|
17896
|
+
const src = path12.join(ctx.paths.cacheDir, filename);
|
|
17897
|
+
const dest = path12.join(ctx.paths.dataDir, filename);
|
|
17898
|
+
if (!fs14.existsSync(src)) {
|
|
17899
|
+
return { name: filename, status: "skipped", detail: "source not found" };
|
|
16911
17900
|
}
|
|
16912
|
-
if (
|
|
16913
|
-
|
|
16914
|
-
return;
|
|
17901
|
+
if (fs14.existsSync(dest)) {
|
|
17902
|
+
return { name: filename, status: "skipped", detail: "destination already exists" };
|
|
16915
17903
|
}
|
|
16916
17904
|
if (ctx.dryRun) {
|
|
16917
|
-
|
|
16918
|
-
return;
|
|
17905
|
+
return { name: filename, status: "success", detail: `[dry-run] would copy ${src} \u2192 ${dest}` };
|
|
16919
17906
|
}
|
|
16920
17907
|
ensureDir(ctx.paths.dataDir);
|
|
16921
17908
|
const ok = copyAndVerify(src, dest);
|
|
16922
17909
|
if (ok) {
|
|
16923
|
-
|
|
17910
|
+
return {
|
|
16924
17911
|
name: filename,
|
|
16925
17912
|
status: "success",
|
|
16926
17913
|
detail: `copied to ${dest} \u2014 source left at ${src} (delete manually when ready)`
|
|
16927
|
-
}
|
|
16928
|
-
} else {
|
|
16929
|
-
ctx.recordStep({ name: filename, status: "failed", detail: `size mismatch after copy: ${src} \u2192 ${dest}` });
|
|
17914
|
+
};
|
|
16930
17915
|
}
|
|
17916
|
+
return { name: filename, status: "failed", detail: `size mismatch after copy: ${src} \u2192 ${dest}` };
|
|
16931
17917
|
}
|
|
16932
17918
|
async function migrateEventsJsonl(ctx) {
|
|
16933
|
-
const src =
|
|
16934
|
-
if (!
|
|
16935
|
-
|
|
16936
|
-
return;
|
|
17919
|
+
const src = path12.join(ctx.paths.cacheDir, "events.jsonl");
|
|
17920
|
+
if (!fs14.existsSync(src)) {
|
|
17921
|
+
return { name: "events.jsonl \u2192 state.db", status: "skipped", detail: "source not found" };
|
|
16937
17922
|
}
|
|
16938
17923
|
if (ctx.dryRun) {
|
|
16939
|
-
|
|
17924
|
+
return {
|
|
16940
17925
|
name: "events.jsonl \u2192 state.db",
|
|
16941
17926
|
status: "success",
|
|
16942
17927
|
detail: `[dry-run] would import ${src} into ${ctx.paths.stateDbPath}`
|
|
16943
|
-
}
|
|
16944
|
-
return;
|
|
17928
|
+
};
|
|
16945
17929
|
}
|
|
16946
17930
|
try {
|
|
16947
17931
|
ensureDir(ctx.paths.dataDir);
|
|
@@ -16963,46 +17947,43 @@ async function migrateEventsJsonl(ctx) {
|
|
|
16963
17947
|
throw err;
|
|
16964
17948
|
}
|
|
16965
17949
|
const dedupNote = skipped > 0 ? ` (${skipped} duplicate(s) skipped \u2014 re-run idempotency)` : "";
|
|
16966
|
-
|
|
17950
|
+
return {
|
|
16967
17951
|
name: "events.jsonl \u2192 state.db",
|
|
16968
17952
|
status: "success",
|
|
16969
17953
|
detail: `imported ${imported} events (max id: ${maxId})${dedupNote} \u2014 source left at ${src} (delete manually when ready)`
|
|
16970
|
-
}
|
|
17954
|
+
};
|
|
16971
17955
|
} finally {
|
|
16972
17956
|
db.close();
|
|
16973
17957
|
}
|
|
16974
17958
|
} catch (err) {
|
|
16975
17959
|
const msg = err instanceof Error ? err.message : String(err);
|
|
16976
|
-
|
|
17960
|
+
return { name: "events.jsonl \u2192 state.db", status: "failed", detail: msg };
|
|
16977
17961
|
}
|
|
16978
17962
|
}
|
|
16979
17963
|
function migrateTaskHistory(ctx) {
|
|
16980
|
-
const src =
|
|
16981
|
-
const dest =
|
|
16982
|
-
if (!
|
|
16983
|
-
|
|
16984
|
-
return;
|
|
17964
|
+
const src = path12.join(ctx.paths.cacheDir, "tasks", "history");
|
|
17965
|
+
const dest = path12.join(ctx.paths.stateDir, "tasks", "history");
|
|
17966
|
+
if (!fs14.existsSync(src)) {
|
|
17967
|
+
return { name: "tasks/history/", status: "skipped", detail: "source directory not found" };
|
|
16985
17968
|
}
|
|
16986
17969
|
try {
|
|
16987
|
-
const files =
|
|
17970
|
+
const files = fs14.readdirSync(src).filter((f) => f.endsWith(".jsonl"));
|
|
16988
17971
|
if (files.length === 0) {
|
|
16989
|
-
|
|
16990
|
-
return;
|
|
17972
|
+
return { name: "tasks/history/", status: "skipped", detail: "no *.jsonl files found in source directory" };
|
|
16991
17973
|
}
|
|
16992
17974
|
if (ctx.dryRun) {
|
|
16993
|
-
|
|
17975
|
+
return {
|
|
16994
17976
|
name: "tasks/history/",
|
|
16995
17977
|
status: "success",
|
|
16996
17978
|
detail: `[dry-run] would copy ${files.length} *.jsonl file(s) from ${src} \u2192 ${dest}`
|
|
16997
|
-
}
|
|
16998
|
-
return;
|
|
17979
|
+
};
|
|
16999
17980
|
}
|
|
17000
17981
|
ensureDir(dest);
|
|
17001
17982
|
let copied = 0;
|
|
17002
17983
|
let failed = 0;
|
|
17003
17984
|
for (const file of files) {
|
|
17004
|
-
const srcFile =
|
|
17005
|
-
const destFile =
|
|
17985
|
+
const srcFile = path12.join(src, file);
|
|
17986
|
+
const destFile = path12.join(dest, file);
|
|
17006
17987
|
try {
|
|
17007
17988
|
if (copyAndVerify(srcFile, destFile)) {
|
|
17008
17989
|
copied++;
|
|
@@ -17014,119 +17995,107 @@ function migrateTaskHistory(ctx) {
|
|
|
17014
17995
|
}
|
|
17015
17996
|
}
|
|
17016
17997
|
if (failed === 0) {
|
|
17017
|
-
|
|
17998
|
+
return {
|
|
17018
17999
|
name: "tasks/history/",
|
|
17019
18000
|
status: "success",
|
|
17020
18001
|
detail: `copied ${copied} files to ${dest} \u2014 sources left in place (delete manually when ready)`
|
|
17021
|
-
}
|
|
17022
|
-
} else {
|
|
17023
|
-
ctx.recordStep({
|
|
17024
|
-
name: "tasks/history/",
|
|
17025
|
-
status: "failed",
|
|
17026
|
-
detail: `copied ${copied}/${files.length} files; ${failed} failed`
|
|
17027
|
-
});
|
|
18002
|
+
};
|
|
17028
18003
|
}
|
|
18004
|
+
return {
|
|
18005
|
+
name: "tasks/history/",
|
|
18006
|
+
status: "failed",
|
|
18007
|
+
detail: `copied ${copied}/${files.length} files; ${failed} failed`
|
|
18008
|
+
};
|
|
17029
18009
|
} catch (err) {
|
|
17030
18010
|
const msg = err instanceof Error ? err.message : String(err);
|
|
17031
|
-
|
|
18011
|
+
return { name: "tasks/history/", status: "failed", detail: msg };
|
|
17032
18012
|
}
|
|
17033
18013
|
}
|
|
17034
18014
|
function migrateLockfile(ctx) {
|
|
17035
|
-
const src =
|
|
17036
|
-
const dest =
|
|
17037
|
-
if (!
|
|
17038
|
-
|
|
17039
|
-
return;
|
|
18015
|
+
const src = path12.join(ctx.paths.configDir, "akm.lock");
|
|
18016
|
+
const dest = path12.join(ctx.paths.dataDir, "akm.lock");
|
|
18017
|
+
if (!fs14.existsSync(src)) {
|
|
18018
|
+
return { name: "akm.lock", status: "skipped", detail: "source not found" };
|
|
17040
18019
|
}
|
|
17041
|
-
if (
|
|
17042
|
-
|
|
17043
|
-
return;
|
|
18020
|
+
if (fs14.existsSync(dest)) {
|
|
18021
|
+
return { name: "akm.lock", status: "skipped", detail: "destination already exists" };
|
|
17044
18022
|
}
|
|
17045
18023
|
if (ctx.dryRun) {
|
|
17046
|
-
|
|
17047
|
-
return;
|
|
18024
|
+
return { name: "akm.lock", status: "success", detail: `[dry-run] would copy ${src} \u2192 ${dest}` };
|
|
17048
18025
|
}
|
|
17049
18026
|
ensureDir(ctx.paths.dataDir);
|
|
17050
18027
|
const ok = copyAndVerify(src, dest);
|
|
17051
18028
|
if (ok) {
|
|
17052
|
-
|
|
18029
|
+
return {
|
|
17053
18030
|
name: "akm.lock",
|
|
17054
18031
|
status: "success",
|
|
17055
18032
|
detail: `copied to ${dest} \u2014 source left at ${src}.
|
|
17056
18033
|
IMPORTANT: akm now reads ONLY from $DATA/akm.lock. If this step is skipped,
|
|
17057
18034
|
akm will start with an empty lockfile and 'akm add' will rebuild it from scratch.`
|
|
17058
|
-
}
|
|
17059
|
-
} else {
|
|
17060
|
-
ctx.recordStep({ name: "akm.lock", status: "failed", detail: `size mismatch after copy: ${src} \u2192 ${dest}` });
|
|
18035
|
+
};
|
|
17061
18036
|
}
|
|
18037
|
+
return { name: "akm.lock", status: "failed", detail: `size mismatch after copy: ${src} \u2192 ${dest}` };
|
|
17062
18038
|
}
|
|
17063
18039
|
function migrateConfigBackups(ctx) {
|
|
17064
|
-
const src =
|
|
17065
|
-
const dest =
|
|
17066
|
-
if (!
|
|
17067
|
-
|
|
17068
|
-
return;
|
|
18040
|
+
const src = path12.join(ctx.paths.cacheDir, "config-backups");
|
|
18041
|
+
const dest = path12.join(ctx.paths.dataDir, "config-backups");
|
|
18042
|
+
if (!fs14.existsSync(src)) {
|
|
18043
|
+
return { name: "config-backups/", status: "skipped", detail: "source directory not found" };
|
|
17069
18044
|
}
|
|
17070
|
-
if (
|
|
17071
|
-
|
|
17072
|
-
return;
|
|
18045
|
+
if (fs14.existsSync(dest)) {
|
|
18046
|
+
return { name: "config-backups/", status: "skipped", detail: "destination already exists" };
|
|
17073
18047
|
}
|
|
17074
18048
|
if (ctx.dryRun) {
|
|
17075
18049
|
let srcCount = 0;
|
|
17076
18050
|
try {
|
|
17077
18051
|
srcCount = countFilesRecursive(src);
|
|
17078
18052
|
} catch {}
|
|
17079
|
-
|
|
18053
|
+
return {
|
|
17080
18054
|
name: "config-backups/",
|
|
17081
18055
|
status: "success",
|
|
17082
18056
|
detail: `[dry-run] would recursively copy ${srcCount} file(s) from ${src} \u2192 ${dest}`
|
|
17083
|
-
}
|
|
17084
|
-
return;
|
|
18057
|
+
};
|
|
17085
18058
|
}
|
|
17086
18059
|
try {
|
|
17087
18060
|
const srcCount = countFilesRecursive(src);
|
|
17088
|
-
const { copied, failed } =
|
|
17089
|
-
const destCount =
|
|
18061
|
+
const { copied, failed } = copyTree(src, dest, { clobber: true });
|
|
18062
|
+
const destCount = fs14.existsSync(dest) ? countFilesRecursive(dest) : 0;
|
|
17090
18063
|
if (failed === 0 && destCount === srcCount) {
|
|
17091
|
-
|
|
18064
|
+
return {
|
|
17092
18065
|
name: "config-backups/",
|
|
17093
18066
|
status: "success",
|
|
17094
18067
|
detail: `copied ${copied} files to ${dest} \u2014 sources left in place (delete manually when ready)`
|
|
17095
|
-
}
|
|
17096
|
-
} else {
|
|
17097
|
-
ctx.recordStep({
|
|
17098
|
-
name: "config-backups/",
|
|
17099
|
-
status: "failed",
|
|
17100
|
-
detail: `file count mismatch: source ${srcCount}, destination ${destCount}; ${failed} copy errors`
|
|
17101
|
-
});
|
|
18068
|
+
};
|
|
17102
18069
|
}
|
|
18070
|
+
return {
|
|
18071
|
+
name: "config-backups/",
|
|
18072
|
+
status: "failed",
|
|
18073
|
+
detail: `file count mismatch: source ${srcCount}, destination ${destCount}; ${failed} copy errors`
|
|
18074
|
+
};
|
|
17103
18075
|
} catch (err) {
|
|
17104
18076
|
const msg = err instanceof Error ? err.message : String(err);
|
|
17105
|
-
|
|
18077
|
+
return { name: "config-backups/", status: "failed", detail: msg };
|
|
17106
18078
|
}
|
|
17107
18079
|
}
|
|
17108
18080
|
async function migrateTaskHistoryToDb(ctx) {
|
|
17109
|
-
const src =
|
|
17110
|
-
if (!
|
|
17111
|
-
|
|
17112
|
-
return;
|
|
18081
|
+
const src = path12.join(ctx.paths.cacheDir, "tasks", "history");
|
|
18082
|
+
if (!fs14.existsSync(src)) {
|
|
18083
|
+
return { name: "tasks/history/ \u2192 state.db", status: "skipped", detail: "source directory not found" };
|
|
17113
18084
|
}
|
|
17114
|
-
const files =
|
|
18085
|
+
const files = fs14.readdirSync(src).filter((f) => f.endsWith(".jsonl"));
|
|
17115
18086
|
if (files.length === 0) {
|
|
17116
|
-
|
|
18087
|
+
return {
|
|
17117
18088
|
name: "tasks/history/ \u2192 state.db",
|
|
17118
18089
|
status: "skipped",
|
|
17119
18090
|
detail: "no *.jsonl files found in source directory"
|
|
17120
|
-
}
|
|
17121
|
-
return;
|
|
18091
|
+
};
|
|
17122
18092
|
}
|
|
17123
18093
|
if (ctx.dryRun) {
|
|
17124
|
-
|
|
18094
|
+
return {
|
|
17125
18095
|
name: "tasks/history/ \u2192 state.db",
|
|
17126
18096
|
status: "success",
|
|
17127
18097
|
detail: `[dry-run] would parse ${files.length} *.jsonl file(s) and import rows into ${ctx.paths.stateDbPath}`
|
|
17128
|
-
}
|
|
17129
|
-
return;
|
|
18098
|
+
};
|
|
17130
18099
|
}
|
|
17131
18100
|
try {
|
|
17132
18101
|
ensureDir(ctx.paths.dataDir);
|
|
@@ -17136,8 +18105,8 @@ async function migrateTaskHistoryToDb(ctx) {
|
|
|
17136
18105
|
let failed = 0;
|
|
17137
18106
|
try {
|
|
17138
18107
|
for (const file of files) {
|
|
17139
|
-
const filePath =
|
|
17140
|
-
const text =
|
|
18108
|
+
const filePath = path12.join(src, file);
|
|
18109
|
+
const text = fs14.readFileSync(filePath, "utf8");
|
|
17141
18110
|
const lines = text.split(`
|
|
17142
18111
|
`).filter((l) => l.trim().length > 0);
|
|
17143
18112
|
db.exec("BEGIN");
|
|
@@ -17179,33 +18148,30 @@ async function migrateTaskHistoryToDb(ctx) {
|
|
|
17179
18148
|
db.close();
|
|
17180
18149
|
}
|
|
17181
18150
|
if (failed === 0) {
|
|
17182
|
-
|
|
18151
|
+
return {
|
|
17183
18152
|
name: "tasks/history/ \u2192 state.db",
|
|
17184
18153
|
status: "success",
|
|
17185
18154
|
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)`
|
|
17186
|
-
}
|
|
17187
|
-
} else {
|
|
17188
|
-
ctx.recordStep({
|
|
17189
|
-
name: "tasks/history/ \u2192 state.db",
|
|
17190
|
-
status: "failed",
|
|
17191
|
-
detail: `imported ${imported} row(s); ${failed} line(s) could not be parsed`
|
|
17192
|
-
});
|
|
18155
|
+
};
|
|
17193
18156
|
}
|
|
18157
|
+
return {
|
|
18158
|
+
name: "tasks/history/ \u2192 state.db",
|
|
18159
|
+
status: "failed",
|
|
18160
|
+
detail: `imported ${imported} row(s); ${failed} line(s) could not be parsed`
|
|
18161
|
+
};
|
|
17194
18162
|
} catch (err) {
|
|
17195
18163
|
const msg = err instanceof Error ? err.message : String(err);
|
|
17196
|
-
|
|
18164
|
+
return { name: "tasks/history/ \u2192 state.db", status: "failed", detail: msg };
|
|
17197
18165
|
}
|
|
17198
18166
|
}
|
|
17199
18167
|
function noteRegistryIndexCache(ctx) {
|
|
17200
|
-
const src =
|
|
17201
|
-
if (!
|
|
17202
|
-
|
|
17203
|
-
return;
|
|
18168
|
+
const src = path12.join(ctx.paths.cacheDir, "registry-index");
|
|
18169
|
+
if (!fs14.existsSync(src)) {
|
|
18170
|
+
return { name: "registry-index/ (note)", status: "skipped", detail: "no old $CACHE/registry-index/ directory found" };
|
|
17204
18171
|
}
|
|
17205
|
-
const legacyFiles =
|
|
18172
|
+
const legacyFiles = fs14.readdirSync(src).filter((f) => f.endsWith(".json") && !f.startsWith("website-"));
|
|
17206
18173
|
if (legacyFiles.length === 0) {
|
|
17207
|
-
|
|
17208
|
-
return;
|
|
18174
|
+
return { name: "registry-index/ (note)", status: "skipped", detail: "no old *.json cache files found" };
|
|
17209
18175
|
}
|
|
17210
18176
|
if (!ctx.dryRun) {
|
|
17211
18177
|
console.log(`
|
|
@@ -17213,57 +18179,57 @@ function noteRegistryIndexCache(ctx) {
|
|
|
17213
18179
|
These are ignored in v0.9 \u2014 data is now stored in the registry_index_cache` + `
|
|
17214
18180
|
table in $DATA/index.db and will be rebuilt on next 'akm registry search'.
|
|
17215
18181
|
You may safely delete these files after migration:
|
|
17216
|
-
` + legacyFiles.map((f) => ` ${
|
|
18182
|
+
` + legacyFiles.map((f) => ` ${path12.join(src, f)}`).join(`
|
|
17217
18183
|
`));
|
|
17218
18184
|
}
|
|
17219
|
-
|
|
18185
|
+
return {
|
|
17220
18186
|
name: "registry-index/ (note)",
|
|
17221
18187
|
status: "success",
|
|
17222
18188
|
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`
|
|
17223
|
-
}
|
|
18189
|
+
};
|
|
17224
18190
|
}
|
|
17225
18191
|
var v07To08Migration = {
|
|
17226
18192
|
label: "0.7 \u2192 0.8",
|
|
17227
18193
|
sourceVersion: "0.7",
|
|
17228
18194
|
isNeeded: (paths) => {
|
|
17229
18195
|
const candidates = [
|
|
17230
|
-
|
|
17231
|
-
|
|
17232
|
-
|
|
17233
|
-
|
|
17234
|
-
|
|
17235
|
-
|
|
17236
|
-
|
|
18196
|
+
path12.join(paths.cacheDir, "index.db"),
|
|
18197
|
+
path12.join(paths.cacheDir, "workflow.db"),
|
|
18198
|
+
path12.join(paths.cacheDir, "events.jsonl"),
|
|
18199
|
+
path12.join(paths.cacheDir, "tasks", "history"),
|
|
18200
|
+
path12.join(paths.configDir, "akm.lock"),
|
|
18201
|
+
path12.join(paths.cacheDir, "config-backups"),
|
|
18202
|
+
path12.join(paths.cacheDir, "registry-index")
|
|
17237
18203
|
];
|
|
17238
|
-
return candidates.some((p) =>
|
|
18204
|
+
return candidates.some((p) => fs14.existsSync(p));
|
|
17239
18205
|
},
|
|
17240
|
-
|
|
17241
|
-
migrateDb(ctx, "index.db")
|
|
17242
|
-
migrateDb(ctx, "workflow.db")
|
|
17243
|
-
|
|
17244
|
-
migrateTaskHistory
|
|
17245
|
-
migrateLockfile
|
|
17246
|
-
migrateConfigBackups
|
|
17247
|
-
|
|
17248
|
-
|
|
17249
|
-
|
|
18206
|
+
steps: [
|
|
18207
|
+
{ id: "index-db", title: "index.db", run: (ctx) => migrateDb(ctx, "index.db") },
|
|
18208
|
+
{ id: "workflow-db", title: "workflow.db", run: (ctx) => migrateDb(ctx, "workflow.db") },
|
|
18209
|
+
{ id: "events-jsonl", title: "events.jsonl \u2192 state.db", run: migrateEventsJsonl },
|
|
18210
|
+
{ id: "tasks-history-files", title: "tasks/history/", run: migrateTaskHistory },
|
|
18211
|
+
{ id: "lockfile", title: "akm.lock", run: migrateLockfile },
|
|
18212
|
+
{ id: "config-backups", title: "config-backups/", run: migrateConfigBackups },
|
|
18213
|
+
{ id: "tasks-history-db", title: "tasks/history/ \u2192 state.db", run: migrateTaskHistoryToDb },
|
|
18214
|
+
{ id: "registry-index-note", title: "registry-index/ (note)", run: noteRegistryIndexCache }
|
|
18215
|
+
]
|
|
17250
18216
|
};
|
|
17251
18217
|
function legacyGraphCandidatePaths(ctx) {
|
|
17252
18218
|
return [
|
|
17253
|
-
|
|
17254
|
-
|
|
17255
|
-
|
|
18219
|
+
path12.join(ctx.paths.cacheDir, "graph-snapshot.json"),
|
|
18220
|
+
path12.join(ctx.paths.dataDir, "graph-snapshot.json"),
|
|
18221
|
+
path12.join(ctx.paths.dataDir, "graph-export.json")
|
|
17256
18222
|
];
|
|
17257
18223
|
}
|
|
17258
18224
|
function findLegacyGraphFile(ctx) {
|
|
17259
18225
|
for (const candidate of legacyGraphCandidatePaths(ctx)) {
|
|
17260
|
-
if (
|
|
18226
|
+
if (fs14.existsSync(candidate) && fs14.statSync(candidate).isFile())
|
|
17261
18227
|
return candidate;
|
|
17262
18228
|
}
|
|
17263
|
-
const graphDir =
|
|
17264
|
-
if (
|
|
18229
|
+
const graphDir = path12.join(ctx.paths.cacheDir, "graph");
|
|
18230
|
+
if (fs14.existsSync(graphDir) && fs14.statSync(graphDir).isDirectory()) {
|
|
17265
18231
|
try {
|
|
17266
|
-
const json =
|
|
18232
|
+
const json = fs14.readdirSync(graphDir).filter((f) => f.endsWith(".json")).map((f) => path12.join(graphDir, f));
|
|
17267
18233
|
if (json.length > 0)
|
|
17268
18234
|
return json[0];
|
|
17269
18235
|
} catch {}
|
|
@@ -17297,43 +18263,38 @@ async function migrateGraphFileToDb(ctx) {
|
|
|
17297
18263
|
const name = "Graph snapshot import";
|
|
17298
18264
|
const legacyFile = findLegacyGraphFile(ctx);
|
|
17299
18265
|
if (!legacyFile) {
|
|
17300
|
-
|
|
17301
|
-
return;
|
|
18266
|
+
return { name, status: "skipped", detail: "no legacy graph file found" };
|
|
17302
18267
|
}
|
|
17303
|
-
if (!
|
|
17304
|
-
|
|
18268
|
+
if (!fs14.existsSync(ctx.paths.indexDbPath)) {
|
|
18269
|
+
return {
|
|
17305
18270
|
name,
|
|
17306
18271
|
status: "skipped",
|
|
17307
18272
|
detail: `index.db not found at ${ctx.paths.indexDbPath}; run akm to initialize, then re-run this migration`
|
|
17308
|
-
}
|
|
17309
|
-
return;
|
|
18273
|
+
};
|
|
17310
18274
|
}
|
|
17311
18275
|
if (ctx.dryRun) {
|
|
17312
|
-
|
|
18276
|
+
return {
|
|
17313
18277
|
name,
|
|
17314
18278
|
status: "success",
|
|
17315
18279
|
detail: `[dry-run] would parse ${legacyFile} and import into ${ctx.paths.indexDbPath} graph tables`
|
|
17316
|
-
}
|
|
17317
|
-
return;
|
|
18280
|
+
};
|
|
17318
18281
|
}
|
|
17319
18282
|
try {
|
|
17320
|
-
const raw =
|
|
18283
|
+
const raw = fs14.readFileSync(legacyFile, "utf8");
|
|
17321
18284
|
let parsed;
|
|
17322
18285
|
try {
|
|
17323
18286
|
parsed = JSON.parse(raw);
|
|
17324
18287
|
} catch (err) {
|
|
17325
18288
|
const msg = err instanceof Error ? err.message : String(err);
|
|
17326
|
-
|
|
17327
|
-
return;
|
|
18289
|
+
return { name, status: "failed", detail: `${legacyFile} is not valid JSON: ${msg}` };
|
|
17328
18290
|
}
|
|
17329
18291
|
const validation = validateGraphSnapshot(parsed);
|
|
17330
18292
|
if (!validation.ok) {
|
|
17331
|
-
|
|
18293
|
+
return {
|
|
17332
18294
|
name,
|
|
17333
18295
|
status: "failed",
|
|
17334
18296
|
detail: `${legacyFile} does not match expected GraphSnapshot shape: ${validation.reason}`
|
|
17335
|
-
}
|
|
17336
|
-
return;
|
|
18297
|
+
};
|
|
17337
18298
|
}
|
|
17338
18299
|
const snapshot = validation.data;
|
|
17339
18300
|
const { openExistingDatabase: openExistingDatabase2, closeDatabase: closeDatabase2 } = await Promise.resolve().then(() => (init_db(), exports_db));
|
|
@@ -17381,51 +18342,48 @@ async function migrateGraphFileToDb(ctx) {
|
|
|
17381
18342
|
const importedCount = db.prepare("SELECT COUNT(*) AS cnt FROM graph_files WHERE stash_root = ?").get(snapshot.stashRoot).cnt;
|
|
17382
18343
|
const meta = loadStoredGraphMeta2(snapshot.stashRoot, db);
|
|
17383
18344
|
if (!meta) {
|
|
17384
|
-
|
|
18345
|
+
return {
|
|
17385
18346
|
name,
|
|
17386
18347
|
status: "failed",
|
|
17387
18348
|
detail: `import did not produce a graph_meta row for stash ${snapshot.stashRoot}`
|
|
17388
|
-
}
|
|
17389
|
-
return;
|
|
18349
|
+
};
|
|
17390
18350
|
}
|
|
17391
18351
|
if (importedCount === 0) {
|
|
17392
|
-
|
|
18352
|
+
return {
|
|
17393
18353
|
name,
|
|
17394
18354
|
status: "failed",
|
|
17395
18355
|
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.`
|
|
17396
|
-
}
|
|
17397
|
-
return;
|
|
18356
|
+
};
|
|
17398
18357
|
}
|
|
17399
18358
|
const renamed = `${legacyFile}.migrated`;
|
|
17400
18359
|
try {
|
|
17401
|
-
|
|
18360
|
+
fs14.renameSync(legacyFile, renamed);
|
|
17402
18361
|
} catch (err) {
|
|
17403
18362
|
const msg = err instanceof Error ? err.message : String(err);
|
|
17404
|
-
|
|
18363
|
+
return {
|
|
17405
18364
|
name,
|
|
17406
18365
|
status: "success",
|
|
17407
18366
|
detail: `imported graph for ${snapshot.stashRoot} into ${ctx.paths.indexDbPath} but could not rename ${legacyFile}: ${msg}`
|
|
17408
|
-
}
|
|
17409
|
-
return;
|
|
18367
|
+
};
|
|
17410
18368
|
}
|
|
17411
|
-
|
|
18369
|
+
return {
|
|
17412
18370
|
name,
|
|
17413
18371
|
status: "success",
|
|
17414
18372
|
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.`
|
|
17415
|
-
}
|
|
18373
|
+
};
|
|
17416
18374
|
} finally {
|
|
17417
18375
|
closeDatabase2(db);
|
|
17418
18376
|
}
|
|
17419
18377
|
} catch (err) {
|
|
17420
18378
|
const msg = err instanceof Error ? err.message : String(err);
|
|
17421
|
-
|
|
18379
|
+
return { name, status: "failed", detail: msg };
|
|
17422
18380
|
}
|
|
17423
18381
|
}
|
|
17424
18382
|
function resolvePrimaryStashDir(configDirPath) {
|
|
17425
18383
|
try {
|
|
17426
|
-
const cfgPath =
|
|
17427
|
-
if (
|
|
17428
|
-
const cfg = JSON.parse(
|
|
18384
|
+
const cfgPath = path12.join(configDirPath, "config.json");
|
|
18385
|
+
if (fs14.existsSync(cfgPath)) {
|
|
18386
|
+
const cfg = JSON.parse(fs14.readFileSync(cfgPath, "utf8"));
|
|
17429
18387
|
if (typeof cfg.stashDir === "string" && cfg.stashDir.length > 0)
|
|
17430
18388
|
return cfg.stashDir;
|
|
17431
18389
|
}
|
|
@@ -17434,8 +18392,8 @@ function resolvePrimaryStashDir(configDirPath) {
|
|
|
17434
18392
|
}
|
|
17435
18393
|
function countEnvFilesRecursive(dir) {
|
|
17436
18394
|
let count = 0;
|
|
17437
|
-
for (const entry of
|
|
17438
|
-
const full =
|
|
18395
|
+
for (const entry of fs14.readdirSync(dir, { withFileTypes: true })) {
|
|
18396
|
+
const full = path12.join(dir, entry.name);
|
|
17439
18397
|
if (entry.isDirectory()) {
|
|
17440
18398
|
count += countEnvFilesRecursive(full);
|
|
17441
18399
|
} else if (entry.name === ".env" || entry.name.endsWith(".env")) {
|
|
@@ -17444,46 +18402,16 @@ function countEnvFilesRecursive(dir) {
|
|
|
17444
18402
|
}
|
|
17445
18403
|
return count;
|
|
17446
18404
|
}
|
|
17447
|
-
function copyDirNoClobber(src, dest) {
|
|
17448
|
-
let copied = 0;
|
|
17449
|
-
let skipped = 0;
|
|
17450
|
-
let failed = 0;
|
|
17451
|
-
ensureDir(dest);
|
|
17452
|
-
for (const entry of fs12.readdirSync(src, { withFileTypes: true })) {
|
|
17453
|
-
const srcEntry = path10.join(src, entry.name);
|
|
17454
|
-
const destEntry = path10.join(dest, entry.name);
|
|
17455
|
-
if (entry.isDirectory()) {
|
|
17456
|
-
const sub = copyDirNoClobber(srcEntry, destEntry);
|
|
17457
|
-
copied += sub.copied;
|
|
17458
|
-
skipped += sub.skipped;
|
|
17459
|
-
failed += sub.failed;
|
|
17460
|
-
continue;
|
|
17461
|
-
}
|
|
17462
|
-
if (fs12.existsSync(destEntry)) {
|
|
17463
|
-
skipped++;
|
|
17464
|
-
continue;
|
|
17465
|
-
}
|
|
17466
|
-
try {
|
|
17467
|
-
if (copyAndVerify(srcEntry, destEntry))
|
|
17468
|
-
copied++;
|
|
17469
|
-
else
|
|
17470
|
-
failed++;
|
|
17471
|
-
} catch {
|
|
17472
|
-
failed++;
|
|
17473
|
-
}
|
|
17474
|
-
}
|
|
17475
|
-
return { copied, skipped, failed };
|
|
17476
|
-
}
|
|
17477
18405
|
function chmodTreeSecure(dir) {
|
|
17478
18406
|
const isWin = process.platform === "win32";
|
|
17479
18407
|
try {
|
|
17480
|
-
|
|
18408
|
+
fs14.chmodSync(dir, 448);
|
|
17481
18409
|
} catch (err) {
|
|
17482
18410
|
if (!isWin)
|
|
17483
18411
|
return { ok: false, detail: `chmod 0700 ${dir} failed: ${err instanceof Error ? err.message : err}` };
|
|
17484
18412
|
}
|
|
17485
|
-
for (const entry of
|
|
17486
|
-
const full =
|
|
18413
|
+
for (const entry of fs14.readdirSync(dir, { withFileTypes: true })) {
|
|
18414
|
+
const full = path12.join(dir, entry.name);
|
|
17487
18415
|
if (entry.isDirectory()) {
|
|
17488
18416
|
const sub = chmodTreeSecure(full);
|
|
17489
18417
|
if (!sub.ok)
|
|
@@ -17491,8 +18419,8 @@ function chmodTreeSecure(dir) {
|
|
|
17491
18419
|
continue;
|
|
17492
18420
|
}
|
|
17493
18421
|
try {
|
|
17494
|
-
|
|
17495
|
-
if (!isWin && (
|
|
18422
|
+
fs14.chmodSync(full, 384);
|
|
18423
|
+
if (!isWin && (fs14.statSync(full).mode & 511) !== 384) {
|
|
17496
18424
|
return { ok: false, detail: `mode verification failed for ${full}` };
|
|
17497
18425
|
}
|
|
17498
18426
|
} catch (err) {
|
|
@@ -17505,59 +18433,52 @@ function chmodTreeSecure(dir) {
|
|
|
17505
18433
|
async function migrateVaultsToEnv(ctx) {
|
|
17506
18434
|
const name = "vaults/ \u2192 env/";
|
|
17507
18435
|
const stashDir = resolvePrimaryStashDir(ctx.paths.configDir);
|
|
17508
|
-
const vaultsDir =
|
|
17509
|
-
const envDir =
|
|
17510
|
-
const marker =
|
|
17511
|
-
if (!
|
|
17512
|
-
|
|
17513
|
-
return;
|
|
18436
|
+
const vaultsDir = path12.join(stashDir, "vaults");
|
|
18437
|
+
const envDir = path12.join(stashDir, "env");
|
|
18438
|
+
const marker = path12.join(vaultsDir, MIGRATED_MARKER);
|
|
18439
|
+
if (!fs14.existsSync(vaultsDir)) {
|
|
18440
|
+
return { name, status: "skipped", detail: `no vaults/ directory under ${stashDir}` };
|
|
17514
18441
|
}
|
|
17515
|
-
if (
|
|
17516
|
-
|
|
17517
|
-
return;
|
|
18442
|
+
if (fs14.existsSync(marker)) {
|
|
18443
|
+
return { name, status: "skipped", detail: "already migrated (.migrated marker present)" };
|
|
17518
18444
|
}
|
|
17519
18445
|
const vaultEnvCount = countEnvFilesRecursive(vaultsDir);
|
|
17520
18446
|
if (vaultEnvCount === 0) {
|
|
17521
|
-
|
|
17522
|
-
return;
|
|
18447
|
+
return { name, status: "skipped", detail: "vaults/ has no .env files to migrate" };
|
|
17523
18448
|
}
|
|
17524
18449
|
if (ctx.dryRun) {
|
|
17525
|
-
|
|
18450
|
+
return {
|
|
17526
18451
|
name,
|
|
17527
18452
|
status: "success",
|
|
17528
18453
|
detail: `[dry-run] would copy ${vaultEnvCount} .env file(s) ${vaultsDir} \u2192 ${envDir}, chmod 0600/0700, and write ${marker}`
|
|
17529
|
-
}
|
|
17530
|
-
return;
|
|
18454
|
+
};
|
|
17531
18455
|
}
|
|
17532
18456
|
try {
|
|
17533
|
-
const { copied, skipped, failed } =
|
|
18457
|
+
const { copied, skipped, failed } = copyTree(vaultsDir, envDir, { clobber: false });
|
|
17534
18458
|
if (failed > 0) {
|
|
17535
|
-
|
|
17536
|
-
return;
|
|
18459
|
+
return { name, status: "failed", detail: `${failed} file(s) failed to copy; env/ left as-is, no marker written` };
|
|
17537
18460
|
}
|
|
17538
18461
|
const chmodRes = chmodTreeSecure(envDir);
|
|
17539
18462
|
if (!chmodRes.ok) {
|
|
17540
|
-
|
|
17541
|
-
return;
|
|
18463
|
+
return { name, status: "failed", detail: chmodRes.detail ?? "permission tightening failed" };
|
|
17542
18464
|
}
|
|
17543
18465
|
const envEnvCount = countEnvFilesRecursive(envDir);
|
|
17544
18466
|
if (envEnvCount < vaultEnvCount) {
|
|
17545
|
-
|
|
18467
|
+
return {
|
|
17546
18468
|
name,
|
|
17547
18469
|
status: "failed",
|
|
17548
18470
|
detail: `post-copy count ${envEnvCount} < source ${vaultEnvCount}; no marker written`
|
|
17549
|
-
}
|
|
17550
|
-
return;
|
|
18471
|
+
};
|
|
17551
18472
|
}
|
|
17552
|
-
|
|
18473
|
+
fs14.writeFileSync(marker, `migrated vaults/ -> env/ at ${new Date().toISOString()}
|
|
17553
18474
|
`, { mode: 384 });
|
|
17554
|
-
|
|
18475
|
+
return {
|
|
17555
18476
|
name,
|
|
17556
18477
|
status: "success",
|
|
17557
18478
|
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.`
|
|
17558
|
-
}
|
|
18479
|
+
};
|
|
17559
18480
|
} catch (err) {
|
|
17560
|
-
|
|
18481
|
+
return { name, status: "failed", detail: err instanceof Error ? err.message : String(err) };
|
|
17561
18482
|
}
|
|
17562
18483
|
}
|
|
17563
18484
|
var v08To09Migration = {
|
|
@@ -17566,10 +18487,10 @@ var v08To09Migration = {
|
|
|
17566
18487
|
isNeeded: (_paths) => {
|
|
17567
18488
|
return true;
|
|
17568
18489
|
},
|
|
17569
|
-
|
|
17570
|
-
|
|
17571
|
-
|
|
17572
|
-
|
|
18490
|
+
steps: [
|
|
18491
|
+
{ id: "graph-snapshot-import", title: "Graph snapshot import", run: migrateGraphFileToDb },
|
|
18492
|
+
{ id: "vaults-to-env", title: "vaults/ \u2192 env/", run: migrateVaultsToEnv }
|
|
18493
|
+
]
|
|
17573
18494
|
};
|
|
17574
18495
|
var MIGRATIONS2 = [v07To08Migration, v08To09Migration];
|
|
17575
18496
|
async function confirm() {
|
|
@@ -17655,12 +18576,12 @@ task_history: task_id PK).
|
|
|
17655
18576
|
Migration complete. No errors.`);
|
|
17656
18577
|
console.log(`
|
|
17657
18578
|
Old files at the original locations are safe to delete manually after verifying akm works:
|
|
17658
|
-
${
|
|
17659
|
-
${
|
|
17660
|
-
${
|
|
17661
|
-
${
|
|
17662
|
-
${
|
|
17663
|
-
${
|
|
18579
|
+
${path12.join(cacheDir, "index.db")}
|
|
18580
|
+
${path12.join(cacheDir, "workflow.db")}
|
|
18581
|
+
${path12.join(cacheDir, "events.jsonl")}
|
|
18582
|
+
${path12.join(cacheDir, "tasks", "history")}
|
|
18583
|
+
${path12.join(cacheDir, "config-backups")}
|
|
18584
|
+
${path12.join(configDir, "akm.lock")}
|
|
17664
18585
|
|
|
17665
18586
|
Next step \u2014 repopulate graph data (if migrating from 0.7):
|
|
17666
18587
|
The 0.8.0 graph schema redesign (DB_VERSION 12 \u2192 13) rebuilds the graph
|
|
@@ -17672,7 +18593,7 @@ Next step \u2014 repopulate graph data (if migrating from 0.7):
|
|
|
17672
18593
|
docs/migration/v0.7-to-v0.8.md#graph-extraction-will-re-run-after-upgrade.
|
|
17673
18594
|
`);
|
|
17674
18595
|
}
|
|
17675
|
-
async function
|
|
18596
|
+
async function runMigrations3(opts = { dryRun: DRY_RUN }) {
|
|
17676
18597
|
const paths = opts.paths ?? PATHS;
|
|
17677
18598
|
const reports = [];
|
|
17678
18599
|
const migrations = filteredMigrations();
|
|
@@ -17701,7 +18622,7 @@ async function runMigrations2(opts = { dryRun: DRY_RUN }) {
|
|
|
17701
18622
|
continue;
|
|
17702
18623
|
}
|
|
17703
18624
|
try {
|
|
17704
|
-
await migration.
|
|
18625
|
+
await runSteps(migration.steps, ctx);
|
|
17705
18626
|
reports.push({ label: migration.label, ran: true, results: stepResults });
|
|
17706
18627
|
} catch (err) {
|
|
17707
18628
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -17740,7 +18661,7 @@ async function main() {
|
|
|
17740
18661
|
console.log(`[dry-run] No changes will be written.
|
|
17741
18662
|
`);
|
|
17742
18663
|
}
|
|
17743
|
-
const reports = await
|
|
18664
|
+
const reports = await runMigrations3({ dryRun: DRY_RUN, paths: PATHS });
|
|
17744
18665
|
versionReports.push(...reports);
|
|
17745
18666
|
printGroupedSummary();
|
|
17746
18667
|
if (DRY_RUN) {
|
|
@@ -17753,7 +18674,7 @@ var invokedDirectly = (() => {
|
|
|
17753
18674
|
if (!entry)
|
|
17754
18675
|
return false;
|
|
17755
18676
|
const here = new URL(import.meta.url).pathname;
|
|
17756
|
-
return
|
|
18677
|
+
return path12.resolve(entry) === here;
|
|
17757
18678
|
} catch {
|
|
17758
18679
|
return false;
|
|
17759
18680
|
}
|
|
@@ -17762,6 +18683,6 @@ if (invokedDirectly) {
|
|
|
17762
18683
|
await main();
|
|
17763
18684
|
}
|
|
17764
18685
|
export {
|
|
17765
|
-
|
|
18686
|
+
runMigrations3 as runMigrations,
|
|
17766
18687
|
MIGRATIONS2 as MIGRATIONS
|
|
17767
18688
|
};
|