akm-cli 0.8.6 → 0.8.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +442 -0
- package/dist/assets/help/help-proposals.md +1 -2
- package/dist/assets/hints/cli-hints-full.md +34 -19
- package/dist/assets/hints/cli-hints-short.md +1 -1
- package/dist/assets/profiles/catchup.json +13 -0
- package/dist/assets/profiles/consolidate.json +13 -0
- package/dist/assets/profiles/frequent.json +13 -0
- package/dist/assets/tasks/core/backup.yml +4 -0
- package/dist/assets/tasks/core/extract.yml +4 -0
- package/dist/assets/tasks/core/improve.yml +4 -0
- package/dist/assets/tasks/core/index-refresh.yml +4 -0
- package/dist/assets/tasks/core/sync.yml +4 -0
- package/dist/assets/tasks/core/update-stashes.yml +4 -0
- package/dist/assets/tasks/core/version-check.yml +4 -0
- package/dist/assets/templates/html/default.html +78 -0
- package/dist/assets/templates/html/health.html +560 -0
- package/dist/assets/templates/html/vendor/echarts.min.js +45 -0
- package/dist/cli/config-migrate.js +6 -6
- package/dist/cli/config-validate.js +4 -4
- package/dist/cli/confirm.js +3 -3
- package/dist/cli/parse-args.js +1 -1
- package/dist/cli/shared.js +72 -19
- package/dist/cli-node.mjs +26 -0
- package/dist/cli.js +206 -3866
- package/dist/commands/{agent-dispatch.js → agent/agent-dispatch.js} +6 -6
- package/dist/commands/{agent-support.js → agent/agent-support.js} +2 -2
- package/dist/commands/agent/contribute-cli.js +200 -0
- package/dist/commands/completions.js +1 -1
- package/dist/commands/config-cli.js +230 -3
- package/dist/commands/db-cli.js +2 -2
- package/dist/commands/env/env-cli.js +529 -0
- package/dist/commands/env/env.js +410 -0
- package/dist/commands/env/secret-cli.js +259 -0
- package/dist/commands/{secret.js → env/secret.js} +6 -47
- package/dist/commands/events.js +4 -4
- package/dist/commands/feedback-cli.js +18 -34
- package/dist/commands/graph/graph-cli.js +132 -0
- package/dist/commands/{graph.js → graph/graph.js} +22 -16
- package/dist/commands/health/checks.js +279 -0
- package/dist/commands/health/html-report.js +448 -0
- package/dist/commands/health.js +189 -266
- package/dist/commands/{consolidate.js → improve/consolidate.js} +63 -38
- package/dist/commands/{distill-promotion-policy.js → improve/distill-promotion-policy.js} +3 -3
- package/dist/commands/{distill.js → improve/distill.js} +39 -18
- package/dist/commands/{eval-cases.js → improve/eval-cases.js} +1 -1
- package/dist/commands/{extract-cli.js → improve/extract-cli.js} +4 -4
- package/dist/commands/{extract-prompt.js → improve/extract-prompt.js} +2 -2
- package/dist/commands/{extract.js → improve/extract.js} +221 -26
- package/dist/commands/{improve-auto-accept.js → improve/improve-auto-accept.js} +30 -4
- package/dist/commands/{improve-cli.js → improve/improve-cli.js} +44 -22
- package/dist/commands/{improve-profiles.js → improve/improve-profiles.js} +13 -7
- package/dist/commands/{improve-result-file.js → improve/improve-result-file.js} +1 -1
- package/dist/commands/{improve.js → improve/improve.js} +672 -292
- package/dist/{core → commands/improve/memory}/memory-belief.js +2 -2
- package/dist/{core → commands/improve/memory}/memory-contradiction-detect.js +5 -5
- package/dist/{core → commands/improve/memory}/memory-improve.js +4 -4
- package/dist/commands/improve/reflect-noise.js +0 -0
- package/dist/commands/{reflect.js → improve/reflect.js} +58 -28
- package/dist/commands/improve/session-asset.js +248 -0
- package/dist/commands/lint/agent-linter.js +1 -1
- package/dist/commands/lint/base-linter.js +55 -37
- package/dist/commands/lint/command-linter.js +1 -1
- package/dist/commands/lint/default-linter.js +1 -1
- package/dist/commands/lint/env-key-rules.js +1 -1
- package/dist/commands/lint/index.js +19 -25
- package/dist/commands/lint/knowledge-linter.js +1 -1
- package/dist/commands/lint/memory-linter.js +1 -1
- package/dist/commands/lint/registry.js +8 -8
- package/dist/commands/lint/skill-linter.js +1 -1
- package/dist/commands/lint/task-linter.js +1 -1
- package/dist/commands/lint/workflow-linter.js +1 -1
- package/dist/commands/lint.js +1 -1
- package/dist/commands/observability-cli.js +244 -0
- package/dist/commands/proposal/drain-policies.js +3 -3
- package/dist/commands/proposal/drain.js +87 -15
- package/dist/commands/proposal/proposal-cli.js +490 -0
- package/dist/commands/{proposal.js → proposal/proposal.js} +17 -6
- package/dist/commands/{propose.js → proposal/propose.js} +11 -11
- package/dist/{core → commands/proposal/validators}/proposal-quality-validators.js +8 -3
- package/dist/{core → commands/proposal/validators}/proposal-validators.js +5 -5
- package/dist/{core → commands/proposal/validators}/proposals.js +374 -345
- package/dist/commands/{curate.js → read/curate.js} +7 -7
- package/dist/commands/{knowledge.js → read/knowledge.js} +22 -9
- package/dist/commands/{registry-search.js → read/registry-search.js} +5 -5
- package/dist/commands/{remember-cli.js → read/remember-cli.js} +15 -7
- package/dist/commands/read/search-cli.js +207 -0
- package/dist/commands/{search.js → read/search.js} +22 -27
- package/dist/commands/{show.js → read/show.js} +31 -45
- package/dist/commands/registry-cli.js +8 -8
- package/dist/commands/remember.js +14 -10
- package/dist/commands/sources/add-cli.js +293 -0
- package/dist/commands/{history.js → sources/history.js} +27 -25
- package/dist/commands/{info.js → sources/info.js} +6 -6
- package/dist/commands/{init.js → sources/init.js} +6 -6
- package/dist/commands/{installed-stashes.js → sources/installed-stashes.js} +12 -12
- package/dist/commands/{migration-help.js → sources/migration-help.js} +3 -2
- package/dist/commands/{schema-repair.js → sources/schema-repair.js} +8 -8
- package/dist/commands/{self-update.js → sources/self-update.js} +10 -9
- package/dist/commands/{source-add.js → sources/source-add.js} +10 -10
- package/dist/commands/{source-clone.js → sources/source-clone.js} +7 -7
- package/dist/commands/{source-manage.js → sources/source-manage.js} +4 -4
- package/dist/commands/sources/sources-cli.js +305 -0
- package/dist/commands/sources/stash-cli.js +219 -0
- package/dist/commands/{stash-skeleton.js → sources/stash-skeleton.js} +2 -1
- package/dist/commands/tasks/default-tasks.js +173 -0
- package/dist/commands/tasks/tasks-cli.js +210 -0
- package/dist/commands/{tasks.js → tasks/tasks.js} +14 -14
- package/dist/commands/wiki-cli.js +307 -0
- package/dist/commands/workflow-cli.js +329 -0
- package/dist/core/action-contributors.js +1 -1
- package/dist/core/assert.js +40 -0
- package/dist/core/asset/asset-create.js +54 -0
- package/dist/core/{asset-ref.js → asset/asset-ref.js} +21 -4
- package/dist/core/{asset-registry.js → asset/asset-registry.js} +3 -3
- package/dist/core/{asset-spec.js → asset/asset-spec.js} +17 -31
- package/dist/core/{markdown.js → asset/markdown.js} +1 -1
- package/dist/core/{stash-meta.js → asset/stash-meta.js} +1 -1
- package/dist/core/best-effort.js +64 -0
- package/dist/core/common.js +32 -18
- package/dist/core/{config-io.js → config/config-io.js} +29 -19
- package/dist/core/{config-migration.js → config/config-migration.js} +11 -9
- package/dist/core/{config-schema.js → config/config-schema.js} +50 -7
- package/dist/core/config/config-types.js +16 -0
- package/dist/core/{config-walker.js → config/config-walker.js} +2 -2
- package/dist/core/{config.js → config/config.js} +10 -8
- package/dist/core/env-secret-ref.js +90 -0
- package/dist/core/errors.js +13 -3
- package/dist/core/events.js +27 -4
- package/dist/core/file-lock.js +1 -1
- package/dist/core/improve-types.js +48 -0
- package/dist/core/lesson-lint.js +2 -2
- package/dist/core/logs-db.js +304 -0
- package/dist/core/paths.js +2 -2
- package/dist/core/ripgrep/install.js +2 -2
- package/dist/core/ripgrep/resolve.js +2 -2
- package/dist/core/state-db.js +195 -60
- package/dist/core/text-truncation.js +148 -0
- package/dist/core/time.js +1 -1
- package/dist/core/write-source.js +98 -85
- package/dist/indexer/{db-backup.js → db/db-backup.js} +9 -24
- package/dist/indexer/{db.js → db/db.js} +128 -118
- package/dist/indexer/{graph-db.js → db/graph-db.js} +9 -4
- package/dist/indexer/{llm-cache.js → db/llm-cache.js} +15 -12
- package/dist/indexer/ensure-index.js +4 -4
- package/dist/indexer/{graph-boost.js → graph/graph-boost.js} +1 -1
- package/dist/indexer/{graph-extraction.js → graph/graph-extraction.js} +55 -13
- package/dist/indexer/indexer.js +37 -30
- package/dist/indexer/init.js +54 -0
- package/dist/indexer/manifest.js +10 -10
- package/dist/indexer/{memory-inference.js → passes/memory-inference.js} +141 -33
- package/dist/indexer/{metadata-contributors.js → passes/metadata-contributors.js} +10 -8
- package/dist/indexer/{metadata.js → passes/metadata.js} +15 -19
- package/dist/indexer/{staleness-detect.js → passes/staleness-detect.js} +53 -12
- package/dist/indexer/{db-search.js → search/db-search.js} +28 -16
- package/dist/indexer/{ranking-contributors.js → search/ranking-contributors.js} +1 -1
- package/dist/indexer/{ranking.js → search/ranking.js} +2 -2
- package/dist/indexer/{search-hit-enrichers.js → search/search-hit-enrichers.js} +3 -3
- package/dist/indexer/{search-source.js → search/search-source.js} +8 -8
- package/dist/indexer/{semantic-status.js → search/semantic-status.js} +3 -3
- package/dist/indexer/usage/unmigrated-vaults-guard.js +94 -0
- package/dist/indexer/{usage-events.js → usage/usage-events.js} +32 -0
- package/dist/indexer/{file-context.js → walk/file-context.js} +10 -15
- package/dist/indexer/{matchers.js → walk/matchers.js} +13 -9
- package/dist/indexer/{path-resolver.js → walk/path-resolver.js} +6 -6
- package/dist/indexer/{project-context.js → walk/project-context.js} +1 -1
- package/dist/indexer/{walker.js → walk/walker.js} +4 -3
- package/dist/integrations/agent/builder-shared.js +39 -0
- package/dist/integrations/agent/builders.js +14 -81
- package/dist/integrations/agent/config.js +6 -4
- package/dist/integrations/agent/detect.js +1 -1
- package/dist/integrations/agent/index.js +23 -8
- package/dist/integrations/agent/prompts.js +2 -3
- package/dist/integrations/agent/runner.js +22 -3
- package/dist/integrations/agent/spawn.js +9 -10
- package/dist/integrations/harnesses/claude/agent-builder.js +48 -0
- package/dist/integrations/harnesses/claude/config-import.js +70 -0
- package/dist/integrations/harnesses/claude/index.js +64 -0
- package/dist/integrations/{session-logs/providers/claude-code.js → harnesses/claude/session-log.js} +32 -5
- package/dist/integrations/harnesses/index.js +144 -0
- package/dist/integrations/harnesses/opencode/agent-builder.js +43 -0
- package/dist/integrations/harnesses/opencode/config-import.js +82 -0
- package/dist/integrations/harnesses/opencode/index.js +59 -0
- package/dist/integrations/{session-logs/providers/opencode.js → harnesses/opencode/session-log.js} +1 -1
- package/dist/integrations/harnesses/opencode-sdk/index.js +49 -0
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +234 -0
- package/dist/integrations/harnesses/types.js +43 -0
- package/dist/integrations/lockfile.js +7 -16
- package/dist/integrations/session-logs/index.js +82 -9
- package/dist/llm/call-ai.js +4 -4
- package/dist/llm/client.js +146 -6
- package/dist/llm/embedder.js +6 -6
- package/dist/llm/embedders/local.js +9 -22
- package/dist/llm/embedders/remote.js +2 -2
- package/dist/llm/embedders/types.js +1 -1
- package/dist/llm/graph-extract.js +31 -12
- package/dist/llm/index-passes.js +1 -1
- package/dist/llm/memory-infer.js +12 -5
- package/dist/llm/metadata-enhance.js +2 -2
- package/dist/llm/usage-persist.js +77 -0
- package/dist/llm/usage-telemetry.js +103 -0
- package/dist/output/context.js +9 -46
- package/dist/output/html-render.js +73 -0
- package/dist/output/renderers.js +88 -58
- package/dist/output/shapes/curate.js +7 -3
- package/dist/output/shapes/distill.js +7 -3
- package/dist/output/shapes/env-list.js +18 -16
- package/dist/output/shapes/events.js +5 -4
- package/dist/output/shapes/helpers.js +19 -5
- package/dist/output/shapes/history.js +7 -3
- package/dist/output/shapes/passthrough.js +8 -11
- package/dist/output/shapes/{proposal-accept.js → proposal/accept.js} +7 -3
- package/dist/output/shapes/{proposal-diff.js → proposal/diff.js} +7 -3
- package/dist/output/shapes/{proposal-list.js → proposal/list.js} +7 -3
- package/dist/output/shapes/{proposal-producer.js → proposal/producer.js} +5 -4
- package/dist/output/shapes/{proposal-reject.js → proposal/reject.js} +7 -3
- package/dist/output/shapes/{proposal-show.js → proposal/show.js} +7 -3
- package/dist/output/shapes/registry-search.js +7 -3
- package/dist/output/shapes/registry.js +12 -0
- package/dist/output/shapes/search.js +7 -3
- package/dist/output/shapes/secret-list.js +18 -16
- package/dist/output/shapes/show.js +7 -3
- package/dist/output/shapes.js +55 -30
- package/dist/output/text/add.js +2 -3
- package/dist/output/text/clone.js +2 -3
- package/dist/output/text/config.js +2 -3
- package/dist/output/text/curate.js +4 -3
- package/dist/output/text/distill.js +2 -3
- package/dist/output/text/enable-disable.js +5 -4
- package/dist/output/text/env.js +13 -0
- package/dist/output/text/events.js +5 -4
- package/dist/output/text/feedback.js +4 -3
- package/dist/output/text/helpers.js +123 -40
- package/dist/output/text/history.js +2 -3
- package/dist/output/text/import.js +2 -3
- package/dist/output/text/index.js +2 -3
- package/dist/output/text/info.js +2 -3
- package/dist/output/text/init.js +2 -3
- package/dist/output/text/list.js +2 -3
- package/dist/output/text/proposal/producer.js +9 -0
- package/dist/output/text/proposal/proposal.js +13 -0
- package/dist/output/text/registry-commands.js +8 -7
- package/dist/output/text/registry.js +12 -0
- package/dist/output/text/remember.js +4 -3
- package/dist/output/text/remove.js +2 -3
- package/dist/output/text/save.js +2 -3
- package/dist/output/text/search.js +4 -3
- package/dist/output/text/show.js +4 -3
- package/dist/output/text/update.js +2 -3
- package/dist/output/text/upgrade.js +2 -3
- package/dist/output/text/wiki.js +12 -11
- package/dist/output/text/workflow.js +12 -10
- package/dist/output/text.js +66 -32
- package/dist/registry/build-index.js +11 -10
- package/dist/registry/factory.js +1 -1
- package/dist/registry/origin-resolve.js +1 -1
- package/dist/registry/providers/index.js +2 -2
- package/dist/registry/providers/skills-sh.js +91 -72
- package/dist/registry/providers/static-index.js +75 -52
- package/dist/registry/resolve.js +3 -3
- package/dist/runtime.js +242 -0
- package/dist/scripts/migrate-storage.js +1654 -683
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +254 -168
- package/dist/setup/detect.js +311 -9
- package/dist/setup/harness-config-import.js +6 -120
- package/dist/setup/setup.js +454 -43
- package/dist/sources/include.js +1 -1
- package/dist/sources/provider-factory.js +2 -2
- package/dist/sources/providers/filesystem.js +3 -3
- package/dist/sources/providers/git.js +9 -9
- package/dist/sources/providers/index.js +4 -4
- package/dist/sources/providers/npm.js +6 -6
- package/dist/sources/providers/provider-utils.js +13 -20
- package/dist/sources/providers/sync-from-ref.js +5 -5
- package/dist/sources/providers/tar-utils.js +2 -2
- package/dist/sources/providers/website.js +2 -2
- package/dist/sources/resolve.js +5 -5
- package/dist/sources/website-ingest.js +5 -5
- package/dist/storage/database.js +102 -0
- package/dist/storage/engines/sqlite-migrations.js +42 -0
- package/dist/storage/locations.js +25 -0
- package/dist/storage/repositories/index-db.js +43 -0
- package/dist/storage/repositories/workflow-runs-repository.js +141 -0
- package/dist/tasks/backends/cron.js +4 -4
- package/dist/tasks/backends/exec-utils.js +32 -0
- package/dist/tasks/backends/index.js +3 -3
- package/dist/tasks/backends/launchd.js +7 -14
- package/dist/tasks/backends/schtasks.js +7 -16
- package/dist/tasks/embedded.js +71 -0
- package/dist/tasks/parser.js +2 -2
- package/dist/tasks/resolveAkmBin.js +1 -1
- package/dist/tasks/runner.js +127 -31
- package/dist/tasks/schedule.js +1 -1
- package/dist/tasks/validator.js +7 -7
- package/dist/text-import-hook.mjs +51 -0
- package/dist/version.js +2 -1
- package/dist/wiki/wiki.js +7 -7
- package/dist/workflows/{authoring.js → authoring/authoring.js} +6 -6
- package/dist/workflows/{scope-key.js → authoring/scope-key.js} +1 -1
- package/dist/workflows/cli.js +1 -1
- package/dist/workflows/db.js +54 -32
- package/dist/workflows/parser.js +4 -4
- package/dist/workflows/renderer.js +5 -5
- package/dist/workflows/runtime/agent-identity.js +56 -0
- package/dist/workflows/runtime/checkin.js +57 -0
- package/dist/workflows/{runs.js → runtime/runs.js} +197 -101
- package/dist/workflows/validate-summary.js +82 -0
- package/docs/README.md +1 -1
- package/docs/data-and-telemetry.md +6 -6
- package/package.json +17 -8
- package/dist/commands/add-cli.js +0 -279
- package/dist/commands/env.js +0 -213
- package/dist/integrations/agent/sdk-runner.js +0 -126
- package/dist/output/shapes/vault-list.js +0 -19
- package/dist/output/text/proposal-producer.js +0 -8
- package/dist/output/text/proposal.js +0 -12
- package/dist/output/text/vault.js +0 -16
- /package/dist/core/{asset-serialize.js → asset/asset-serialize.js} +0 -0
- /package/dist/core/{frontmatter.js → asset/frontmatter.js} +0 -0
- /package/dist/core/{config-sources.js → config/config-sources.js} +0 -0
- /package/dist/indexer/{graph-dedup.js → graph/graph-dedup.js} +0 -0
- /package/dist/{core/config-types.js → indexer/passes/pass-context.js} +0 -0
- /package/dist/indexer/{search-fields.js → search/search-fields.js} +0 -0
- /package/dist/indexer/{index-context.js → walk/index-context.js} +0 -0
- /package/dist/workflows/{document-cache.js → runtime/document-cache.js} +0 -0
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
* pure helpers (`curateSearchResults`, `orderCuratedTypes`,
|
|
14
14
|
* `deriveCurateFallbackQueries`) by importing them directly.
|
|
15
15
|
*/
|
|
16
|
-
import { rethrowIfTestIsolationError, UsageError } from "
|
|
17
|
-
import { appendEvent } from "
|
|
18
|
-
import { closeDatabase, openExistingDatabase } from "
|
|
19
|
-
import { insertUsageEvent } from "
|
|
20
|
-
import { truncateDescription } from "
|
|
21
|
-
import { akmSearch, parseSearchSource } from "./search";
|
|
22
|
-
import { akmShowUnified } from "./show";
|
|
16
|
+
import { rethrowIfTestIsolationError, UsageError } from "../../core/errors.js";
|
|
17
|
+
import { appendEvent } from "../../core/events.js";
|
|
18
|
+
import { closeDatabase, openExistingDatabase } from "../../indexer/db/db.js";
|
|
19
|
+
import { insertUsageEvent } from "../../indexer/usage/usage-events.js";
|
|
20
|
+
import { truncateDescription } from "../../output/shapes.js";
|
|
21
|
+
import { akmSearch, parseSearchSource } from "./search.js";
|
|
22
|
+
import { akmShowUnified } from "./show.js";
|
|
23
23
|
const CURATE_FALLBACK_FILTER_WORDS = new Set([
|
|
24
24
|
"a",
|
|
25
25
|
"an",
|
|
@@ -10,12 +10,13 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import fs from "node:fs";
|
|
12
12
|
import path from "node:path";
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
13
|
+
import { assertFlatAssetName, combineCreatePath, normalizeCreateSubPath } from "../../core/asset/asset-create.js";
|
|
14
|
+
import { resolveAssetPathFromName } from "../../core/asset/asset-spec.js";
|
|
15
|
+
import { isHttpUrl, isWithin, tryReadStdinText } from "../../core/common.js";
|
|
16
|
+
import { loadConfig } from "../../core/config/config.js";
|
|
17
|
+
import { UsageError } from "../../core/errors.js";
|
|
18
|
+
import { commitWriteTargetBoundary, formatRefForMessage, resolveWriteTarget, writeAssetToSource, } from "../../core/write-source.js";
|
|
19
|
+
import { fetchWebsiteMarkdownSnapshot } from "../../sources/website-ingest.js";
|
|
19
20
|
const MAX_CAPTURED_ASSET_SLUG_LENGTH = 64;
|
|
20
21
|
// ── Asset-name normalisation ─────────────────────────────────────────────────
|
|
21
22
|
/**
|
|
@@ -38,6 +39,9 @@ export function normalizeMarkdownAssetName(name, fallback) {
|
|
|
38
39
|
}
|
|
39
40
|
return trimmed;
|
|
40
41
|
}
|
|
42
|
+
// `--path`/`--name` create semantics are shared across all asset-creating
|
|
43
|
+
// commands; re-exported here so existing `./knowledge` importers keep working.
|
|
44
|
+
export { assertFlatAssetName, combineCreatePath, normalizeCreateSubPath };
|
|
41
45
|
function slugifyAssetName(value, fallbackPrefix) {
|
|
42
46
|
const slug = value
|
|
43
47
|
.toLowerCase()
|
|
@@ -114,9 +118,14 @@ export async function readKnowledgeInput(source) {
|
|
|
114
118
|
*/
|
|
115
119
|
export async function writeMarkdownAsset(options) {
|
|
116
120
|
const cfg = loadConfig();
|
|
117
|
-
const
|
|
121
|
+
const target = resolveWriteTarget(cfg, options.target);
|
|
122
|
+
const { source, config } = target;
|
|
118
123
|
const typeRoot = path.join(source.path, options.type === "knowledge" ? "knowledge" : "memories");
|
|
119
|
-
|
|
124
|
+
// `--name` is the flat asset name; `--path` is the subdirectory under the
|
|
125
|
+
// type root. Combine them into the nested name the path resolver expects.
|
|
126
|
+
const subPath = normalizeCreateSubPath(options.path);
|
|
127
|
+
const baseName = normalizeMarkdownAssetName(options.name, inferAssetName(options.content, options.fallbackPrefix, options.preferredName));
|
|
128
|
+
const normalizedName = combineCreatePath(subPath, baseName);
|
|
120
129
|
// Pre-flight: existence + force semantics. The helper itself overwrites
|
|
121
130
|
// unconditionally; the CLI surfaces a friendlier UsageError before any
|
|
122
131
|
// disk activity when --force is absent.
|
|
@@ -127,7 +136,11 @@ export async function writeMarkdownAsset(options) {
|
|
|
127
136
|
if (fs.existsSync(assetPath) && !options.force) {
|
|
128
137
|
throw new UsageError(`${options.type === "knowledge" ? "Knowledge" : "Memory"} "${normalizedName}" already exists. Re-run with --force to overwrite it.`, "RESOURCE_ALREADY_EXISTS");
|
|
129
138
|
}
|
|
130
|
-
const
|
|
139
|
+
const ref = { type: options.type, name: normalizedName };
|
|
140
|
+
const result = await writeAssetToSource(source, config, ref, options.content);
|
|
141
|
+
// 0.9.0 (issue #507): single batch commit at the write boundary for git
|
|
142
|
+
// targets. No-op for filesystem/primary-stash targets.
|
|
143
|
+
commitWriteTargetBoundary(target, `Update ${formatRefForMessage(ref)}`);
|
|
131
144
|
return {
|
|
132
145
|
ref: result.ref,
|
|
133
146
|
path: result.path,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
-
import { toErrorMessage } from "
|
|
5
|
-
import { DEFAULT_CONFIG } from "
|
|
6
|
-
import { warn } from "
|
|
7
|
-
import { resolveProviderFactory } from "
|
|
4
|
+
import { toErrorMessage } from "../../core/common.js";
|
|
5
|
+
import { DEFAULT_CONFIG } from "../../core/config/config.js";
|
|
6
|
+
import { warn } from "../../core/warn.js";
|
|
7
|
+
import { resolveProviderFactory } from "../../registry/factory.js";
|
|
8
8
|
// ── Eagerly import providers to trigger self-registration ───────────────────
|
|
9
|
-
import "
|
|
9
|
+
import "../../registry/providers/index.js";
|
|
10
10
|
// ── Public API ──────────────────────────────────────────────────────────────
|
|
11
11
|
export async function searchRegistry(query, options) {
|
|
12
12
|
const trimmed = query.trim();
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
|
-
import { output, parseAllFlagValues, runWithJsonErrors } from "
|
|
6
|
-
import { UsageError } from "
|
|
7
|
-
import { appendEvent } from "
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { akmSearch } from "./search";
|
|
5
|
+
import { output, parseAllFlagValues, runWithJsonErrors } from "../../cli/shared.js";
|
|
6
|
+
import { UsageError } from "../../core/errors.js";
|
|
7
|
+
import { appendEvent } from "../../core/events.js";
|
|
8
|
+
import { buildMemoryFrontmatter, parseDuration, readMemoryContent, resolveRememberContentArg, runAutoHeuristics, runLlmEnrich, } from "../remember.js";
|
|
9
|
+
import { assertFlatAssetName, inferAssetName, writeMarkdownAsset } from "./knowledge.js";
|
|
10
|
+
import { akmSearch } from "./search.js";
|
|
11
11
|
// ── Helper: similar memory search ────────────────────────────────────────────
|
|
12
12
|
/**
|
|
13
13
|
* Best-effort top-3 similar memory search for `--show-similar`.
|
|
@@ -39,7 +39,11 @@ export const rememberCommand = defineCommand({
|
|
|
39
39
|
},
|
|
40
40
|
name: {
|
|
41
41
|
type: "string",
|
|
42
|
-
description: "Memory name (defaults to a slug from the content)",
|
|
42
|
+
description: "Memory name (flat, no '/'; defaults to a slug from the content). Use --path for a subdirectory.",
|
|
43
|
+
},
|
|
44
|
+
path: {
|
|
45
|
+
type: "string",
|
|
46
|
+
description: "Relative subdirectory under memories/ to place the memory in (e.g. 'personal/projects'). The filename still comes from --name or the content slug.",
|
|
43
47
|
},
|
|
44
48
|
force: {
|
|
45
49
|
type: "boolean",
|
|
@@ -100,6 +104,8 @@ export const rememberCommand = defineCommand({
|
|
|
100
104
|
async run({ args }) {
|
|
101
105
|
return runWithJsonErrors(async () => {
|
|
102
106
|
const body = readMemoryContent(resolveRememberContentArg(args.content));
|
|
107
|
+
// `--name` is a flat name; subdirectory placement is `--path`'s job.
|
|
108
|
+
assertFlatAssetName(args.name);
|
|
103
109
|
// Determine if the user has requested any structured metadata mode.
|
|
104
110
|
// Collect all --tag occurrences directly from process.argv because citty
|
|
105
111
|
// only exposes the last value for repeated string flags.
|
|
@@ -138,6 +144,7 @@ export const rememberCommand = defineCommand({
|
|
|
138
144
|
preferredName: inferAssetName(body, "memory"),
|
|
139
145
|
force: args.force,
|
|
140
146
|
target: args.target,
|
|
147
|
+
path: args.path,
|
|
141
148
|
});
|
|
142
149
|
appendEvent({
|
|
143
150
|
eventType: "remember",
|
|
@@ -232,6 +239,7 @@ export const rememberCommand = defineCommand({
|
|
|
232
239
|
fallbackPrefix: "memory",
|
|
233
240
|
force: args.force,
|
|
234
241
|
target: args.target,
|
|
242
|
+
path: args.path,
|
|
235
243
|
});
|
|
236
244
|
appendEvent({
|
|
237
245
|
eventType: "remember",
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
/**
|
|
5
|
+
* `akm search`, `akm curate`, and `akm show` command family. Extracted verbatim
|
|
6
|
+
* from src/cli.ts (WS6) so the God Module shrinks; the `main.subCommands.search`,
|
|
7
|
+
* `.curate`, and `.show` keys and every command's args/output shape are
|
|
8
|
+
* byte-identical. The three commands form a clean cluster: they share the
|
|
9
|
+
* private `resolveEventSource()` helper and the `parseScopeFilterFlags`
|
|
10
|
+
* search-source parsers. Handlers whose body is a plain
|
|
11
|
+
* `runWithJsonErrors(async () => { … })` are migrated to `defineJsonCommand`,
|
|
12
|
+
* which emits the same JSON envelope (stdout/stderr/exit-code) as the inline
|
|
13
|
+
* form.
|
|
14
|
+
*/
|
|
15
|
+
import { parsePositiveIntFlag } from "../../cli/parse-args.js";
|
|
16
|
+
import { defineJsonCommand, output, parseAllFlagValues } from "../../cli/shared.js";
|
|
17
|
+
import { parseAssetRef } from "../../core/asset/asset-ref.js";
|
|
18
|
+
import { parseMetaRef } from "../../core/asset/stash-meta.js";
|
|
19
|
+
import { UsageError } from "../../core/errors.js";
|
|
20
|
+
import { getHyphenatedBoolean, getOutputMode, parseFlagValue } from "../../output/context.js";
|
|
21
|
+
import { akmCurate } from "./curate.js";
|
|
22
|
+
import { akmSearch, parseBeliefFilterMode, parseScopeFilterFlags, parseSearchSource } from "./search.js";
|
|
23
|
+
import { akmShowUnified } from "./show.js";
|
|
24
|
+
// AKM_EVENT_SOURCE attributes a query to a `user` invocation or the internal
|
|
25
|
+
// `improve` loop so the event log can distinguish them; any other value is
|
|
26
|
+
// treated as unset.
|
|
27
|
+
function resolveEventSource() {
|
|
28
|
+
const raw = process.env.AKM_EVENT_SOURCE;
|
|
29
|
+
if (raw === "improve")
|
|
30
|
+
return "improve";
|
|
31
|
+
if (raw === "user")
|
|
32
|
+
return "user";
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
export const searchCommand = defineJsonCommand({
|
|
36
|
+
meta: { name: "search", description: "Search the stash" },
|
|
37
|
+
args: {
|
|
38
|
+
query: { type: "positional", description: "Search query (omit to list all assets)", required: false, default: "" },
|
|
39
|
+
type: {
|
|
40
|
+
type: "string",
|
|
41
|
+
description: "Asset type filter (skill, command, agent, knowledge, workflow, script, memory, env, secret, wiki, lesson, or any). Use workflow to find step-by-step task assets.",
|
|
42
|
+
},
|
|
43
|
+
limit: { type: "string", description: "Maximum number of results" },
|
|
44
|
+
source: { type: "string", description: "Search source (stash|registry|both)", default: "stash" },
|
|
45
|
+
filter: {
|
|
46
|
+
type: "string",
|
|
47
|
+
description: "Scope filter (repeatable): --filter user=<id> --filter agent=<id> --filter run=<id> --filter channel=<name>. Narrows results without changing ranking.",
|
|
48
|
+
},
|
|
49
|
+
"include-proposed": {
|
|
50
|
+
type: "boolean",
|
|
51
|
+
description: 'Include entries with quality:"proposed" in the result set. Excluded by default (v1 spec §4.2).',
|
|
52
|
+
default: false,
|
|
53
|
+
},
|
|
54
|
+
belief: {
|
|
55
|
+
type: "string",
|
|
56
|
+
description: "Memory belief filter: all|current|historical. current keeps active memory beliefs; historical keeps contradicted/superseded/archived memory beliefs.",
|
|
57
|
+
default: "all",
|
|
58
|
+
},
|
|
59
|
+
format: { type: "string", description: "Output format (json|jsonl|text|yaml)" },
|
|
60
|
+
detail: { type: "string", description: "Detail level (brief|normal|full)" },
|
|
61
|
+
"no-project-context": {
|
|
62
|
+
type: "boolean",
|
|
63
|
+
description: "Disable the automatic project-context ranking boost (also disabled by AKM_DISABLE_PROJECT_CONTEXT=1).",
|
|
64
|
+
default: false,
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
async run({ args }) {
|
|
68
|
+
const query = (args.query ?? "").trim();
|
|
69
|
+
if (!query) {
|
|
70
|
+
throw new UsageError('A search query is required. Usage: akm search "<query>" [--type <type>] [--limit <n>]', "MISSING_REQUIRED_ARGUMENT", 'Pass a query like `akm search "docker"` or `akm search "code review" --type skill`.');
|
|
71
|
+
}
|
|
72
|
+
const type = args.type;
|
|
73
|
+
const limit = parsePositiveIntFlag(args.limit ?? undefined);
|
|
74
|
+
const source = parseSearchSource(args.source);
|
|
75
|
+
// Repeatable; citty exposes only the last `--filter` value, so read all
|
|
76
|
+
// occurrences directly from argv (same pattern as `--tag`).
|
|
77
|
+
const filterTokens = parseAllFlagValues("--filter");
|
|
78
|
+
const filters = parseScopeFilterFlags(filterTokens, "--filter");
|
|
79
|
+
const includeProposed = args["include-proposed"] === true;
|
|
80
|
+
const belief = parseBeliefFilterMode(typeof args.belief === "string" ? args.belief : undefined);
|
|
81
|
+
const noProjectContext = getHyphenatedBoolean(args, "no-project-context");
|
|
82
|
+
// --no-project-context sets env so searchDatabase picks it up without
|
|
83
|
+
// threading the flag through the entire call stack.
|
|
84
|
+
if (noProjectContext)
|
|
85
|
+
process.env.AKM_DISABLE_PROJECT_CONTEXT = "1";
|
|
86
|
+
const result = await akmSearch({
|
|
87
|
+
query,
|
|
88
|
+
type,
|
|
89
|
+
limit,
|
|
90
|
+
source,
|
|
91
|
+
filters,
|
|
92
|
+
includeProposed,
|
|
93
|
+
belief,
|
|
94
|
+
eventSource: resolveEventSource(),
|
|
95
|
+
});
|
|
96
|
+
output("search", result);
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
export const curateCommand = defineJsonCommand({
|
|
100
|
+
meta: { name: "curate", description: "Curate the best matching assets for a task or prompt" },
|
|
101
|
+
args: {
|
|
102
|
+
// Optional in citty so run() is invoked when omitted; we re-validate
|
|
103
|
+
// below to surface a structured UsageError (exit 2) instead of citty's
|
|
104
|
+
// default help-banner exit-0.
|
|
105
|
+
query: { type: "positional", description: "Task or prompt to curate assets for", required: false },
|
|
106
|
+
type: {
|
|
107
|
+
type: "string",
|
|
108
|
+
description: "Asset type filter (skill, command, agent, knowledge, workflow, script, memory, env, secret, wiki, lesson, or any). Use workflow to curate step-by-step task assets.",
|
|
109
|
+
},
|
|
110
|
+
limit: { type: "string", description: "Maximum number of curated results", default: "4" },
|
|
111
|
+
source: { type: "string", description: "Search source (stash|registry|both)", default: "stash" },
|
|
112
|
+
// Output-contract flags. The active values are read from the process-level
|
|
113
|
+
// singleton (parsed from argv at startup); these declarations make them
|
|
114
|
+
// visible in `akm curate --help` and document the supported axes.
|
|
115
|
+
format: { type: "string", description: "Output format (json|jsonl|text|yaml)" },
|
|
116
|
+
detail: { type: "string", description: "Detail level (brief|normal|full)" },
|
|
117
|
+
shape: { type: "string", description: "Output projection (human|agent)" },
|
|
118
|
+
},
|
|
119
|
+
async run({ args }) {
|
|
120
|
+
if (!args.query || !String(args.query).trim()) {
|
|
121
|
+
throw new UsageError('A curate query is required. Usage: akm curate "<task or prompt>" [--type <type>] [--limit <n>]', "MISSING_REQUIRED_ARGUMENT", 'Describe the task you want assets for, e.g. `akm curate "deploy to prod"`.');
|
|
122
|
+
}
|
|
123
|
+
const type = args.type;
|
|
124
|
+
const limitParsed = parsePositiveIntFlag(args.limit ?? undefined);
|
|
125
|
+
const limit = limitParsed && limitParsed > 0 ? limitParsed : 4;
|
|
126
|
+
const source = parseSearchSource(args.source ?? "stash");
|
|
127
|
+
const curated = await akmCurate({ query: args.query, type, limit, source });
|
|
128
|
+
output("curate", curated);
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
export const showCommand = defineJsonCommand({
|
|
132
|
+
meta: {
|
|
133
|
+
name: "show",
|
|
134
|
+
description: "Show a stash asset by ref (e.g. akm show knowledge:guide.md toc, akm show knowledge:guide.md section 'Auth')",
|
|
135
|
+
},
|
|
136
|
+
args: {
|
|
137
|
+
ref: {
|
|
138
|
+
type: "positional",
|
|
139
|
+
description: 'Asset ref ([origin//]type:name) optionally followed by a view mode. View modes: `toc` (table of contents), `section "Heading"` (extract one section), `lines <start> <end>` (line range), `frontmatter` (YAML metadata only), `full` (raw file). Example: `akm show knowledge:guide.md section "Auth"`.',
|
|
140
|
+
required: true,
|
|
141
|
+
},
|
|
142
|
+
format: { type: "string", description: "Output format (json|jsonl|text|yaml)" },
|
|
143
|
+
detail: { type: "string", description: "Detail level (brief|normal|full)" },
|
|
144
|
+
shape: { type: "string", description: "Output projection (human|agent|summary)" },
|
|
145
|
+
scope: {
|
|
146
|
+
type: "string",
|
|
147
|
+
description: "Scope filter (repeatable): --scope user=<id> --scope agent=<id> --scope run=<id> --scope channel=<name>. Narrows resolution to assets whose frontmatter scope matches.",
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
async run({ args }) {
|
|
151
|
+
// `[origin//]meta[:name]` targets the stash `.meta/` convention, which is
|
|
152
|
+
// not a typed asset ref — skip ref validation and let akmShowUnified
|
|
153
|
+
// direct-read it. (`parseAssetRef` would reject the non-type `meta`.)
|
|
154
|
+
if (!parseMetaRef(args.ref))
|
|
155
|
+
parseAssetRef(args.ref);
|
|
156
|
+
// The knowledge-view positional syntax (`akm show knowledge:foo section "Auth"`)
|
|
157
|
+
// is rewritten to `--akmView` / `--akmHeading` / `--akmStart` / `--akmEnd`
|
|
158
|
+
// by `normalizeShowArgv` before citty parses argv. We read those values
|
|
159
|
+
// directly via `parseFlagValue` so the flags don't surface as user-facing
|
|
160
|
+
// options in `akm show --help`.
|
|
161
|
+
const akmView = parseFlagValue(process.argv, "--akmView");
|
|
162
|
+
const akmHeading = parseFlagValue(process.argv, "--akmHeading");
|
|
163
|
+
const akmStart = parseFlagValue(process.argv, "--akmStart");
|
|
164
|
+
const akmEnd = parseFlagValue(process.argv, "--akmEnd");
|
|
165
|
+
let view;
|
|
166
|
+
if (akmView) {
|
|
167
|
+
switch (akmView) {
|
|
168
|
+
case "section":
|
|
169
|
+
view = { mode: "section", heading: akmHeading ?? "" };
|
|
170
|
+
break;
|
|
171
|
+
case "lines":
|
|
172
|
+
view = {
|
|
173
|
+
mode: "lines",
|
|
174
|
+
start: Number(akmStart ?? "1"),
|
|
175
|
+
end: akmEnd ? parseInt(akmEnd, 10) : Number.MAX_SAFE_INTEGER,
|
|
176
|
+
};
|
|
177
|
+
break;
|
|
178
|
+
case "toc":
|
|
179
|
+
case "frontmatter":
|
|
180
|
+
case "full":
|
|
181
|
+
view = { mode: akmView };
|
|
182
|
+
break;
|
|
183
|
+
default:
|
|
184
|
+
throw new UsageError(`Unknown view mode: ${akmView}. Expected one of: full|toc|frontmatter|section|lines`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
const cliShape = getOutputMode().shape;
|
|
188
|
+
const explicitDetail = parseFlagValue(process.argv, "--detail");
|
|
189
|
+
// `--shape summary` selects the compact metadata projection for show
|
|
190
|
+
// (the legacy `--detail summary` spelling still maps here via the
|
|
191
|
+
// back-compat path in resolveOutputMode). `--detail brief` forces the
|
|
192
|
+
// brief response regardless of shape.
|
|
193
|
+
const showDetail = explicitDetail === "brief" ? "brief" : cliShape === "summary" ? "summary" : undefined;
|
|
194
|
+
// `--scope` is repeatable — citty only exposes the last value, so read
|
|
195
|
+
// every occurrence directly from argv (same pattern as `--filter`).
|
|
196
|
+
const scopeTokens = parseAllFlagValues("--scope");
|
|
197
|
+
const scope = parseScopeFilterFlags(scopeTokens, "--scope");
|
|
198
|
+
const result = await akmShowUnified({
|
|
199
|
+
ref: args.ref,
|
|
200
|
+
view,
|
|
201
|
+
detail: showDetail,
|
|
202
|
+
scope,
|
|
203
|
+
eventSource: resolveEventSource(),
|
|
204
|
+
});
|
|
205
|
+
output("show", result);
|
|
206
|
+
},
|
|
207
|
+
});
|
|
@@ -11,19 +11,20 @@
|
|
|
11
11
|
* a registry search behind `--source registry|both`, and log a usage event.
|
|
12
12
|
* Provider `search()` methods do not exist.
|
|
13
13
|
*/
|
|
14
|
-
import { loadConfig } from "
|
|
15
|
-
import { rethrowIfTestIsolationError, UsageError } from "
|
|
16
|
-
import { appendEvent } from "
|
|
17
|
-
import { isTransientStashPath } from "
|
|
18
|
-
import { bumpUtilityScoresBatch,
|
|
19
|
-
import { searchLocal } from "
|
|
20
|
-
import { resolveSourceEntries } from "
|
|
21
|
-
import { getCurrentWorkflowScopeKey } from "
|
|
14
|
+
import { loadConfig } from "../../core/config/config.js";
|
|
15
|
+
import { rethrowIfTestIsolationError, UsageError } from "../../core/errors.js";
|
|
16
|
+
import { appendEvent } from "../../core/events.js";
|
|
17
|
+
import { isTransientStashPath } from "../../core/paths.js";
|
|
18
|
+
import { bumpUtilityScoresBatch, getEntryIdByFilePath } from "../../indexer/db/db.js";
|
|
19
|
+
import { searchLocal } from "../../indexer/search/db-search.js";
|
|
20
|
+
import { resolveSourceEntries } from "../../indexer/search/search-source.js";
|
|
21
|
+
import { getCurrentWorkflowScopeKey } from "../../workflows/authoring/scope-key.js";
|
|
22
22
|
// Eagerly import source providers to trigger self-registration before the
|
|
23
23
|
// indexer or path-resolution code runs.
|
|
24
|
-
import "
|
|
25
|
-
import { insertUsageEvent } from "
|
|
26
|
-
import {
|
|
24
|
+
import "../../sources/providers/index.js";
|
|
25
|
+
import { insertUsageEvent } from "../../indexer/usage/usage-events.js";
|
|
26
|
+
import { withIndexDb } from "../../storage/repositories/index-db.js";
|
|
27
|
+
import { searchRegistry } from "./registry-search.js";
|
|
27
28
|
const DEFAULT_LIMIT = 20;
|
|
28
29
|
export async function akmSearch(input) {
|
|
29
30
|
const t0 = Date.now();
|
|
@@ -78,7 +79,7 @@ export async function akmSearch(input) {
|
|
|
78
79
|
timing: { totalMs: Date.now() - t0 },
|
|
79
80
|
};
|
|
80
81
|
if (!input.skipLogging)
|
|
81
|
-
logSearchEvent(query, response, undefined,
|
|
82
|
+
logSearchEvent(query, response, undefined, input.eventSource);
|
|
82
83
|
return response;
|
|
83
84
|
}
|
|
84
85
|
// Primary stash directory — used for DB path lookups and as the default
|
|
@@ -122,7 +123,7 @@ export async function akmSearch(input) {
|
|
|
122
123
|
timing: { totalMs: Date.now() - t0, rankMs: localResult?.rankMs, embedMs: localResult?.embedMs },
|
|
123
124
|
};
|
|
124
125
|
if (!input.skipLogging)
|
|
125
|
-
logSearchEvent(query, response,
|
|
126
|
+
logSearchEvent(query, response, localResult?.mode ?? "keyword", input.eventSource);
|
|
126
127
|
return response;
|
|
127
128
|
}
|
|
128
129
|
const registryHits = (registryResult?.hits ?? []).map((hit) => {
|
|
@@ -157,7 +158,7 @@ export async function akmSearch(input) {
|
|
|
157
158
|
timing: { totalMs: Date.now() - t0 },
|
|
158
159
|
};
|
|
159
160
|
if (!input.skipLogging)
|
|
160
|
-
logSearchEvent(query, response, undefined,
|
|
161
|
+
logSearchEvent(query, response, undefined, input.eventSource);
|
|
161
162
|
return response;
|
|
162
163
|
}
|
|
163
164
|
// source === "both"
|
|
@@ -175,7 +176,7 @@ export async function akmSearch(input) {
|
|
|
175
176
|
timing: { totalMs: Date.now() - t0 },
|
|
176
177
|
};
|
|
177
178
|
if (!input.skipLogging)
|
|
178
|
-
logSearchEvent(query, response, undefined,
|
|
179
|
+
logSearchEvent(query, response, undefined, input.eventSource);
|
|
179
180
|
return response;
|
|
180
181
|
}
|
|
181
182
|
/**
|
|
@@ -183,12 +184,11 @@ export async function akmSearch(input) {
|
|
|
183
184
|
*/
|
|
184
185
|
function resolveEntryIds(db, hits) {
|
|
185
186
|
const results = [];
|
|
186
|
-
const stmt = db.prepare("SELECT id FROM entries WHERE file_path = ? LIMIT 1");
|
|
187
187
|
for (const hit of hits) {
|
|
188
188
|
try {
|
|
189
|
-
const
|
|
190
|
-
if (
|
|
191
|
-
results.push({ entryId
|
|
189
|
+
const entryId = getEntryIdByFilePath(db, hit.path);
|
|
190
|
+
if (entryId !== undefined)
|
|
191
|
+
results.push({ entryId, ref: hit.ref });
|
|
192
192
|
}
|
|
193
193
|
catch {
|
|
194
194
|
/* skip unresolvable */
|
|
@@ -211,7 +211,7 @@ function resolveEntryIds(db, hits) {
|
|
|
211
211
|
* Per-entry events are recorded only for stash hits because registry hits
|
|
212
212
|
* have no local entry_id to reference.
|
|
213
213
|
*/
|
|
214
|
-
function logSearchEvent(query, response,
|
|
214
|
+
function logSearchEvent(query, response, mode = "keyword", eventSource = "user") {
|
|
215
215
|
// Emit a structured event to events.jsonl so workflow-trace consumers
|
|
216
216
|
// detect akm search invocations without relying on stdout scraping.
|
|
217
217
|
const stashHits = response.hits.filter((h) => h.type !== "registry");
|
|
@@ -223,8 +223,7 @@ function logSearchEvent(query, response, existingDb, mode = "keyword", eventSour
|
|
|
223
223
|
metadata: { query, hitCount: stashHits.length, resultRefs: allResultRefs, mode },
|
|
224
224
|
});
|
|
225
225
|
try {
|
|
226
|
-
|
|
227
|
-
try {
|
|
226
|
+
withIndexDb((db) => {
|
|
228
227
|
const resolved = resolveEntryIds(db, stashHits.slice(0, 50));
|
|
229
228
|
for (const { entryId, ref } of resolved) {
|
|
230
229
|
insertUsageEvent(db, {
|
|
@@ -266,11 +265,7 @@ function logSearchEvent(query, response, existingDb, mode = "keyword", eventSour
|
|
|
266
265
|
}),
|
|
267
266
|
source: eventSource,
|
|
268
267
|
});
|
|
269
|
-
}
|
|
270
|
-
finally {
|
|
271
|
-
if (!existingDb)
|
|
272
|
-
closeDatabase(db);
|
|
273
|
-
}
|
|
268
|
+
});
|
|
274
269
|
}
|
|
275
270
|
catch (err) {
|
|
276
271
|
rethrowIfTestIsolationError(err);
|
|
@@ -18,32 +18,33 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import fs from "node:fs";
|
|
20
20
|
import path from "node:path";
|
|
21
|
-
import { parseAssetRef } from "
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import { ensureIndex } from "
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import { resolveSourcesForOrigin } from "
|
|
21
|
+
import { parseAssetRef } from "../../core/asset/asset-ref.js";
|
|
22
|
+
import { parseFrontmatter } from "../../core/asset/frontmatter.js";
|
|
23
|
+
import { META_DIR, parseMetaRef, resolveMetaFilePath } from "../../core/asset/stash-meta.js";
|
|
24
|
+
import { asNonEmptyString } from "../../core/common.js";
|
|
25
|
+
import { loadConfig } from "../../core/config/config.js";
|
|
26
|
+
import { NotFoundError, rethrowIfTestIsolationError, UsageError } from "../../core/errors.js";
|
|
27
|
+
import { appendEvent, readEvents } from "../../core/events.js";
|
|
28
|
+
import { findEntryIdByRef } from "../../indexer/db/db.js";
|
|
29
|
+
import { ensureIndex } from "../../indexer/ensure-index.js";
|
|
30
|
+
import { listRelatedPathsForFile } from "../../indexer/graph/graph-boost.js";
|
|
31
|
+
import { lookup } from "../../indexer/indexer.js";
|
|
32
|
+
import { buildEditHint, findSourceForPath, isEditable, resolveSourceEntries } from "../../indexer/search/search-source.js";
|
|
33
|
+
import { insertUsageEvent } from "../../indexer/usage/usage-events.js";
|
|
34
|
+
import { buildFileContext, buildRenderContext, getRenderer, runMatchers } from "../../indexer/walk/file-context.js";
|
|
35
|
+
import { resolveAssetPath } from "../../indexer/walk/path-resolver.js";
|
|
36
|
+
import { resolveSourcesForOrigin } from "../../registry/origin-resolve.js";
|
|
37
|
+
import { withIndexDb } from "../../storage/repositories/index-db.js";
|
|
37
38
|
// Eagerly import source providers to trigger self-registration.
|
|
38
|
-
import "
|
|
39
|
-
import {
|
|
40
|
-
import {
|
|
39
|
+
import "../../sources/providers/index.js";
|
|
40
|
+
import { getCurrentWorkflowScopeKey } from "../../workflows/authoring/scope-key.js";
|
|
41
|
+
import { getActiveWorkflowRun } from "../../workflows/runtime/runs.js";
|
|
41
42
|
/**
|
|
42
43
|
* Show a wiki root (no page path) — returns the same payload as
|
|
43
44
|
* `akm wiki show <name>`.
|
|
44
45
|
*/
|
|
45
46
|
async function showWikiRoot(stashDir, wikiName) {
|
|
46
|
-
const { showWiki } = await import("
|
|
47
|
+
const { showWiki } = await import("../../wiki/wiki.js");
|
|
47
48
|
const result = showWiki(stashDir, wikiName);
|
|
48
49
|
return {
|
|
49
50
|
type: "wiki",
|
|
@@ -59,7 +60,7 @@ async function showWikiRoot(stashDir, wikiName) {
|
|
|
59
60
|
};
|
|
60
61
|
}
|
|
61
62
|
async function showWikiRootForSource(stashDir, source, wikiName) {
|
|
62
|
-
const { showWikiAtPath } = await import("
|
|
63
|
+
const { showWikiAtPath } = await import("../../wiki/wiki.js");
|
|
63
64
|
if (source.wikiName === wikiName) {
|
|
64
65
|
const result = showWikiAtPath(wikiName, source.path);
|
|
65
66
|
return {
|
|
@@ -156,7 +157,7 @@ export async function akmShowUnified(input) {
|
|
|
156
157
|
}
|
|
157
158
|
// Count prior shows of this ref before logging the current one.
|
|
158
159
|
const priorShowCount = recentShowCount(ref);
|
|
159
|
-
logShowEvent(ref,
|
|
160
|
+
logShowEvent(ref, input.eventSource);
|
|
160
161
|
if (priorShowCount >= 2) {
|
|
161
162
|
// Agent has shown this same asset 3+ times — inject a loop-break hint.
|
|
162
163
|
result.showLoopWarning = priorShowCount + 1;
|
|
@@ -253,7 +254,7 @@ function recentShowCount(ref) {
|
|
|
253
254
|
return 0;
|
|
254
255
|
}
|
|
255
256
|
}
|
|
256
|
-
function logShowEvent(ref,
|
|
257
|
+
function logShowEvent(ref, eventSource = "user") {
|
|
257
258
|
// Emit a structured event to events.jsonl so workflow-trace consumers
|
|
258
259
|
// detect akm show invocations without relying on stdout scraping.
|
|
259
260
|
const parsed = parseAssetRef(ref);
|
|
@@ -288,19 +289,14 @@ function logShowEvent(ref, existingDb, eventSource = "user") {
|
|
|
288
289
|
/* fire-and-forget — select is best-effort */
|
|
289
290
|
}
|
|
290
291
|
try {
|
|
291
|
-
|
|
292
|
-
try {
|
|
292
|
+
withIndexDb((db) => {
|
|
293
293
|
insertUsageEvent(db, {
|
|
294
294
|
event_type: "show",
|
|
295
295
|
entry_ref: ref,
|
|
296
296
|
entry_id: findEntryIdByRef(db, ref),
|
|
297
297
|
source: eventSource,
|
|
298
298
|
});
|
|
299
|
-
}
|
|
300
|
-
finally {
|
|
301
|
-
if (!existingDb)
|
|
302
|
-
closeDatabase(db);
|
|
303
|
-
}
|
|
299
|
+
});
|
|
304
300
|
}
|
|
305
301
|
catch (err) {
|
|
306
302
|
rethrowIfTestIsolationError(err);
|
|
@@ -371,20 +367,16 @@ export async function showLocal(input) {
|
|
|
371
367
|
editable,
|
|
372
368
|
...(!editable ? { editHint: buildEditHint(assetPath, parsed.type, parsed.name, source?.registryId) } : {}),
|
|
373
369
|
related: (() => {
|
|
374
|
-
let db;
|
|
375
370
|
try {
|
|
376
|
-
db
|
|
377
|
-
|
|
378
|
-
|
|
371
|
+
return withIndexDb((db) => {
|
|
372
|
+
const related = listRelatedPathsForFile(sourceStashDir, assetPath, 5, db);
|
|
373
|
+
return { total: related.length, hits: related };
|
|
374
|
+
});
|
|
379
375
|
}
|
|
380
376
|
catch (err) {
|
|
381
377
|
rethrowIfTestIsolationError(err);
|
|
382
378
|
return { total: 0, hits: [] };
|
|
383
379
|
}
|
|
384
|
-
finally {
|
|
385
|
-
if (db)
|
|
386
|
-
closeDatabase(db);
|
|
387
|
-
}
|
|
388
380
|
})(),
|
|
389
381
|
};
|
|
390
382
|
const activeRun = await getActiveWorkflowRun(getCurrentWorkflowScopeKey());
|
|
@@ -482,8 +474,6 @@ export function normalizeShowArgv(argv) {
|
|
|
482
474
|
// argv[0]=bun argv[1]=script argv[2]=subcommand argv[3]=ref argv[4..]=rest
|
|
483
475
|
if (argv[2] !== "show")
|
|
484
476
|
return argv;
|
|
485
|
-
if (argv[3] === "proposal")
|
|
486
|
-
return argv;
|
|
487
477
|
if (argv.includes("--view") || argv.includes("--heading") || argv.includes("--start") || argv.includes("--end")) {
|
|
488
478
|
throw new UsageError('Legacy show flags are no longer supported. Use positional syntax like `akm show knowledge:guide toc` or `akm show knowledge:guide section "Auth"`.');
|
|
489
479
|
}
|
|
@@ -494,11 +484,7 @@ export function normalizeShowArgv(argv) {
|
|
|
494
484
|
const showArgs = [];
|
|
495
485
|
for (let i = 0; i < rest.length; i++) {
|
|
496
486
|
const arg = rest[i];
|
|
497
|
-
if (arg === "--quiet" ||
|
|
498
|
-
arg === "-q" ||
|
|
499
|
-
arg === "--verbose" ||
|
|
500
|
-
arg === "--for-agent" ||
|
|
501
|
-
arg === "--for-agent=true") {
|
|
487
|
+
if (arg === "--quiet" || arg === "-q" || arg === "--verbose") {
|
|
502
488
|
globalFlags.push(arg);
|
|
503
489
|
continue;
|
|
504
490
|
}
|