akm-cli 0.8.0-rc2 → 0.8.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/{.github/CHANGELOG.md → CHANGELOG.md} +191 -3
- package/README.md +22 -6
- package/SECURITY.md +93 -0
- package/dist/cli/config-migrate.js +144 -0
- package/dist/cli/config-validate.js +39 -0
- package/dist/cli/confirm.js +73 -0
- package/dist/cli/parse-args.js +93 -3
- package/dist/cli/shared.js +129 -0
- package/dist/cli.js +2141 -1268
- package/dist/commands/add-cli.js +279 -0
- package/dist/commands/agent-dispatch.js +20 -12
- package/dist/commands/agent-support.js +11 -5
- package/dist/commands/completions.js +3 -0
- package/dist/commands/config-cli.js +129 -517
- package/dist/commands/consolidate.js +1533 -144
- package/dist/commands/curate.js +44 -3
- package/dist/commands/db-cli.js +23 -0
- package/dist/commands/distill-promotion-policy.js +5 -3
- package/dist/commands/distill.js +906 -100
- package/dist/commands/env.js +213 -0
- package/dist/commands/eval-cases.js +3 -0
- package/dist/commands/events.js +3 -0
- package/dist/commands/extract-cli.js +127 -0
- package/dist/commands/extract-prompt.js +204 -0
- package/dist/commands/extract.js +477 -0
- package/dist/commands/feedback-cli.js +331 -0
- package/dist/commands/graph.js +260 -5
- package/dist/commands/health.js +977 -51
- package/dist/commands/help/help-accept.md +6 -3
- package/dist/commands/help/help-improve.md +36 -8
- package/dist/commands/help/help-proposals.md +7 -4
- package/dist/commands/help/help-reject.md +5 -2
- package/dist/commands/history.js +51 -16
- package/dist/commands/improve-auto-accept.js +97 -0
- package/dist/commands/improve-cli.js +236 -0
- package/dist/commands/improve-profiles.js +184 -0
- package/dist/commands/improve-result-file.js +167 -0
- package/dist/commands/improve.js +1725 -332
- package/dist/commands/info.js +3 -0
- package/dist/commands/init.js +49 -1
- package/dist/commands/installed-stashes.js +6 -23
- package/dist/commands/knowledge.js +3 -0
- package/dist/commands/lint/agent-linter.js +3 -0
- package/dist/commands/lint/base-linter.js +199 -5
- package/dist/commands/lint/command-linter.js +3 -0
- package/dist/commands/lint/default-linter.js +3 -0
- package/dist/commands/lint/env-key-rules.js +154 -0
- package/dist/commands/lint/index.js +92 -3
- package/dist/commands/lint/knowledge-linter.js +3 -0
- package/dist/commands/lint/markdown-insertion.js +343 -0
- package/dist/commands/lint/memory-linter.js +3 -0
- package/dist/commands/lint/registry.js +3 -0
- package/dist/commands/lint/skill-linter.js +3 -0
- package/dist/commands/lint/task-linter.js +15 -12
- package/dist/commands/lint/types.js +3 -0
- package/dist/commands/lint/workflow-linter.js +3 -0
- package/dist/commands/lint.js +3 -0
- package/dist/commands/migration-help.js +5 -2
- package/dist/commands/proposal-drain-policies.js +128 -0
- package/dist/commands/proposal-drain.js +477 -0
- package/dist/commands/proposal.js +60 -6
- package/dist/commands/propose.js +24 -19
- package/dist/commands/reflect.js +1004 -94
- package/dist/commands/registry-cli.js +150 -0
- package/dist/commands/registry-search.js +3 -0
- package/dist/commands/remember-cli.js +257 -0
- package/dist/commands/remember.js +15 -6
- package/dist/commands/schema-repair.js +88 -15
- package/dist/commands/search.js +99 -14
- package/dist/commands/secret.js +173 -0
- package/dist/commands/self-update.js +3 -0
- package/dist/commands/show.js +32 -13
- package/dist/commands/source-add.js +7 -35
- package/dist/commands/source-clone.js +3 -0
- package/dist/commands/source-manage.js +3 -0
- package/dist/commands/tasks.js +161 -95
- package/dist/commands/url-checker.js +3 -0
- package/dist/core/action-contributors.js +3 -0
- package/dist/core/asset-ref.js +13 -2
- package/dist/core/asset-registry.js +9 -2
- package/dist/core/asset-serialize.js +88 -0
- package/dist/core/asset-spec.js +61 -5
- package/dist/core/common.js +93 -5
- package/dist/core/concurrent.js +3 -0
- package/dist/core/config-io.js +347 -0
- package/dist/core/config-migration.js +622 -0
- package/dist/core/config-schema.js +558 -0
- package/dist/core/config-sources.js +108 -0
- package/dist/core/config-types.js +4 -0
- package/dist/core/config-walker.js +337 -0
- package/dist/core/config.js +366 -1077
- package/dist/core/errors.js +42 -20
- package/dist/core/events.js +31 -25
- package/dist/core/file-lock.js +104 -0
- package/dist/core/frontmatter.js +75 -10
- package/dist/core/lesson-lint.js +3 -0
- package/dist/core/markdown.js +3 -0
- package/dist/core/memory-belief.js +62 -0
- package/dist/core/memory-contradiction-detect.js +274 -0
- package/dist/core/memory-improve.js +142 -14
- package/dist/core/parse.js +3 -0
- package/dist/core/paths.js +218 -50
- package/dist/core/proposal-quality-validators.js +380 -0
- package/dist/core/proposal-validators.js +11 -3
- package/dist/core/proposals.js +464 -5
- package/dist/core/state-db.js +349 -56
- package/dist/core/text-truncation.js +107 -0
- package/dist/core/time.js +3 -0
- package/dist/core/tty.js +59 -0
- package/dist/core/warn.js +7 -2
- package/dist/core/write-source.js +12 -0
- package/dist/indexer/db-backup.js +391 -0
- package/dist/indexer/db-search.js +136 -28
- package/dist/indexer/db.js +661 -166
- package/dist/indexer/ensure-index.js +3 -0
- package/dist/indexer/file-context.js +3 -0
- package/dist/indexer/graph-boost.js +162 -40
- package/dist/indexer/graph-db.js +241 -51
- package/dist/indexer/graph-dedup.js +3 -7
- package/dist/indexer/graph-extraction.js +242 -149
- package/dist/indexer/index-context.js +3 -9
- package/dist/indexer/indexer.js +84 -14
- package/dist/indexer/llm-cache.js +24 -19
- package/dist/indexer/manifest.js +3 -0
- package/dist/indexer/matchers.js +184 -11
- package/dist/indexer/memory-inference.js +94 -50
- package/dist/indexer/metadata-contributors.js +3 -0
- package/dist/indexer/metadata.js +110 -50
- package/dist/indexer/path-resolver.js +3 -0
- package/dist/indexer/project-context.js +192 -0
- package/dist/indexer/ranking-contributors.js +134 -7
- package/dist/indexer/ranking.js +8 -1
- package/dist/indexer/search-fields.js +5 -9
- package/dist/indexer/search-hit-enrichers.js +91 -2
- package/dist/indexer/search-source.js +20 -1
- package/dist/indexer/semantic-status.js +4 -1
- package/dist/indexer/staleness-detect.js +447 -0
- package/dist/indexer/usage-events.js +12 -9
- package/dist/indexer/walker.js +3 -0
- package/dist/integrations/agent/builders.js +135 -0
- package/dist/integrations/agent/config.js +121 -401
- package/dist/integrations/agent/detect.js +3 -0
- package/dist/integrations/agent/index.js +6 -14
- package/dist/integrations/agent/model-aliases.js +55 -0
- package/dist/integrations/agent/profiles.js +3 -0
- package/dist/integrations/agent/prompts.js +137 -8
- package/dist/integrations/agent/runner.js +208 -0
- package/dist/integrations/agent/sdk-runner.js +8 -2
- package/dist/integrations/agent/spawn.js +54 -14
- package/dist/integrations/github.js +3 -0
- package/dist/integrations/lockfile.js +22 -51
- package/dist/integrations/session-logs/index.js +4 -0
- package/dist/integrations/session-logs/inline-refs.js +35 -0
- package/dist/integrations/session-logs/pre-filter.js +152 -0
- package/dist/integrations/session-logs/providers/claude-code.js +226 -0
- package/dist/integrations/session-logs/providers/opencode.js +231 -25
- package/dist/integrations/session-logs/types.js +3 -0
- package/dist/llm/call-ai.js +14 -26
- package/dist/llm/client.js +16 -2
- package/dist/llm/embedder.js +20 -29
- package/dist/llm/embedders/cache.js +3 -7
- package/dist/llm/embedders/local.js +42 -1
- package/dist/llm/embedders/remote.js +20 -8
- package/dist/llm/embedders/types.js +3 -7
- package/dist/llm/feature-gate.js +92 -56
- package/dist/llm/graph-extract.js +401 -30
- package/dist/llm/index-passes.js +44 -29
- package/dist/llm/memory-infer.js +30 -2
- package/dist/llm/metadata-enhance.js +3 -7
- package/dist/llm/prompts/extract-session.md +80 -0
- package/dist/llm/prompts/graph-extract-user-prompt.md +24 -1
- package/dist/output/cli-hints-full.md +60 -32
- package/dist/output/cli-hints-short.md +10 -7
- package/dist/output/cli-hints.js +5 -2
- package/dist/output/context.js +60 -8
- package/dist/output/renderers.js +170 -194
- package/dist/output/shapes/curate.js +56 -0
- package/dist/output/shapes/distill.js +10 -0
- package/dist/output/shapes/env-list.js +19 -0
- package/dist/output/shapes/events.js +11 -0
- package/dist/output/shapes/helpers.js +424 -0
- package/dist/output/shapes/history.js +7 -0
- package/dist/output/shapes/passthrough.js +105 -0
- package/dist/output/shapes/proposal-accept.js +7 -0
- package/dist/output/shapes/proposal-diff.js +7 -0
- package/dist/output/shapes/proposal-list.js +7 -0
- package/dist/output/shapes/proposal-producer.js +11 -0
- package/dist/output/shapes/proposal-reject.js +7 -0
- package/dist/output/shapes/proposal-show.js +7 -0
- package/dist/output/shapes/registry-search.js +6 -0
- package/dist/output/shapes/registry.js +30 -0
- package/dist/output/shapes/search.js +6 -0
- package/dist/output/shapes/secret-list.js +19 -0
- package/dist/output/shapes/show.js +6 -0
- package/dist/output/shapes/vault-list.js +19 -0
- package/dist/output/shapes.js +51 -549
- package/dist/output/text/add.js +6 -0
- package/dist/output/text/clone.js +6 -0
- package/dist/output/text/config.js +6 -0
- package/dist/output/text/curate.js +6 -0
- package/dist/output/text/distill.js +7 -0
- package/dist/output/text/enable-disable.js +7 -0
- package/dist/output/text/events.js +10 -0
- package/dist/output/text/feedback.js +6 -0
- package/dist/output/text/helpers.js +1059 -0
- package/dist/output/text/history.js +7 -0
- package/dist/output/text/import.js +6 -0
- package/dist/output/text/index.js +6 -0
- package/dist/output/text/info.js +6 -0
- package/dist/output/text/init.js +6 -0
- package/dist/output/text/list.js +6 -0
- package/dist/output/text/proposal-producer.js +8 -0
- package/dist/output/text/proposal.js +12 -0
- package/dist/output/text/registry-commands.js +11 -0
- package/dist/output/text/registry.js +30 -0
- package/dist/output/text/remember.js +6 -0
- package/dist/output/text/remove.js +6 -0
- package/dist/output/text/save.js +6 -0
- package/dist/output/text/search.js +6 -0
- package/dist/output/text/show.js +6 -0
- package/dist/output/text/update.js +6 -0
- package/dist/output/text/upgrade.js +6 -0
- package/dist/output/text/vault.js +16 -0
- package/dist/output/text/wiki.js +15 -0
- package/dist/output/text/workflow.js +14 -0
- package/dist/output/text.js +44 -1329
- package/dist/registry/build-index.js +3 -0
- package/dist/registry/create-provider-registry.js +3 -0
- package/dist/registry/factory.js +4 -1
- package/dist/registry/origin-resolve.js +3 -0
- package/dist/registry/providers/index.js +3 -0
- package/dist/registry/providers/skills-sh.js +11 -2
- package/dist/registry/providers/static-index.js +10 -1
- package/dist/registry/providers/types.js +3 -24
- package/dist/registry/resolve.js +11 -16
- package/dist/registry/types.js +3 -0
- package/dist/scripts/migrate-storage.js +17767 -0
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +9031 -0
- package/dist/scripts/migrations/v16-to-v17.js +141 -0
- package/dist/setup/detect.js +3 -0
- package/dist/setup/ripgrep-install.js +3 -0
- package/dist/setup/ripgrep-resolve.js +3 -0
- package/dist/setup/setup.js +306 -67
- package/dist/setup/steps.js +3 -15
- package/dist/sources/include.js +3 -0
- package/dist/sources/provider-factory.js +3 -11
- package/dist/sources/provider.js +3 -20
- package/dist/sources/providers/filesystem.js +19 -23
- package/dist/sources/providers/git.js +171 -21
- package/dist/sources/providers/index.js +3 -0
- package/dist/sources/providers/install-types.js +3 -13
- package/dist/sources/providers/npm.js +3 -4
- package/dist/sources/providers/provider-utils.js +3 -0
- package/dist/sources/providers/sync-from-ref.js +3 -11
- package/dist/sources/providers/tar-utils.js +3 -0
- package/dist/sources/providers/website.js +18 -22
- package/dist/sources/resolve.js +3 -0
- package/dist/sources/types.js +3 -0
- package/dist/sources/website-ingest.js +3 -0
- package/dist/tasks/backends/cron.js +3 -0
- package/dist/tasks/backends/exec-utils.js +3 -0
- package/dist/tasks/backends/index.js +3 -11
- package/dist/tasks/backends/launchd.js +3 -0
- package/dist/tasks/backends/schtasks.js +3 -0
- package/dist/tasks/parser.js +51 -38
- package/dist/tasks/resolveAkmBin.js +3 -0
- package/dist/tasks/runner.js +35 -9
- package/dist/tasks/schedule.js +20 -1
- package/dist/tasks/schema.js +5 -3
- package/dist/tasks/validator.js +6 -3
- package/dist/version.js +3 -0
- package/dist/wiki/wiki-templates.js +3 -0
- package/dist/wiki/wiki.js +3 -0
- package/dist/workflows/authoring.js +3 -0
- package/dist/workflows/cli.js +3 -0
- package/dist/workflows/db.js +140 -10
- package/dist/workflows/document-cache.js +3 -10
- package/dist/workflows/parser.js +3 -0
- package/dist/workflows/renderer.js +3 -0
- package/dist/workflows/runs.js +18 -1
- package/dist/workflows/schema.js +3 -0
- package/dist/workflows/scope-key.js +3 -0
- package/dist/workflows/validator.js +5 -9
- package/docs/README.md +7 -2
- package/docs/data-and-telemetry.md +225 -0
- package/docs/migration/release-notes/0.7.5.md +2 -2
- package/docs/migration/release-notes/0.8.0.md +57 -5
- package/docs/migration/v0.7-to-v0.8.md +1378 -0
- package/package.json +28 -11
- package/.github/LICENSE +0 -374
- package/dist/commands/install-audit.js +0 -385
- package/dist/commands/vault.js +0 -310
- package/dist/indexer/match-contributors.js +0 -141
- package/dist/integrations/agent/pipeline.js +0 -39
- package/dist/integrations/agent/runners.js +0 -31
package/dist/cli/parse-args.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
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/.
|
|
1
4
|
/**
|
|
2
5
|
* Shared argument-parsing utilities for the AKM CLI entry point.
|
|
3
6
|
*
|
|
@@ -25,7 +28,7 @@ export function hasSubcommand(args, validSet) {
|
|
|
25
28
|
/**
|
|
26
29
|
* Parse a `--limit`-style flag value into a positive integer.
|
|
27
30
|
*
|
|
28
|
-
* Returns `undefined` when `raw` is `undefined` (flag not supplied).
|
|
31
|
+
* Returns `undefined` when `raw` is `undefined` or empty (flag not supplied).
|
|
29
32
|
* Throws `UsageError` when the raw value is present but not a valid positive
|
|
30
33
|
* integer so the caller gets a structured, machine-readable error response.
|
|
31
34
|
*
|
|
@@ -35,9 +38,96 @@ export function hasSubcommand(args, validSet) {
|
|
|
35
38
|
export function parsePositiveIntFlag(raw, flagName = "--limit") {
|
|
36
39
|
if (raw === undefined)
|
|
37
40
|
return undefined;
|
|
38
|
-
const
|
|
41
|
+
const trimmed = raw.trim();
|
|
42
|
+
if (!trimmed)
|
|
43
|
+
return undefined;
|
|
44
|
+
const parsed = parseInt(trimmed, 10);
|
|
39
45
|
if (Number.isNaN(parsed) || parsed <= 0) {
|
|
40
|
-
throw new UsageError(`Invalid ${flagName} value: "${raw}". Must be a positive integer
|
|
46
|
+
throw new UsageError(`Invalid ${flagName} value: "${raw}". Must be a positive integer.`, "INVALID_FLAG_VALUE");
|
|
41
47
|
}
|
|
42
48
|
return parsed;
|
|
43
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Parse a non-negative integer flag value (0 is allowed, unlike `parsePositiveIntFlag`).
|
|
52
|
+
*
|
|
53
|
+
* Returns `undefined` when `raw` is `undefined` or empty (flag not supplied).
|
|
54
|
+
* Throws `UsageError` when the raw value is present but not a valid non-negative
|
|
55
|
+
* integer (e.g. contains decimals, letters, or is negative).
|
|
56
|
+
*
|
|
57
|
+
* @param raw The raw string value (may be undefined).
|
|
58
|
+
* @param flagName The flag name to include in the error message.
|
|
59
|
+
*/
|
|
60
|
+
export function parseNonNegativeIntFlag(raw, flagName) {
|
|
61
|
+
if (raw === undefined)
|
|
62
|
+
return undefined;
|
|
63
|
+
const trimmed = raw.trim();
|
|
64
|
+
if (!trimmed)
|
|
65
|
+
return undefined;
|
|
66
|
+
if (!/^\d+$/.test(trimmed)) {
|
|
67
|
+
throw new UsageError(`Invalid ${flagName} value: "${raw}". Must be a non-negative integer.`, "INVALID_FLAG_VALUE");
|
|
68
|
+
}
|
|
69
|
+
return parseInt(trimmed, 10);
|
|
70
|
+
}
|
|
71
|
+
// ── Auto-accept flag parsing ─────────────────────────────────────────────────
|
|
72
|
+
/**
|
|
73
|
+
* Parse the value of `akm improve --auto-accept` into a confidence threshold.
|
|
74
|
+
*
|
|
75
|
+
* Semantics (see docs/migration/v0.7-to-v0.8.md):
|
|
76
|
+
* - `undefined` (flag absent) → `undefined` (default-OFF; pre-prod flip)
|
|
77
|
+
* - `""` (bare `--auto-accept`, no value) → `undefined` (treated as flag absent)
|
|
78
|
+
* - `"false"` (case-insensitive) → `undefined` (explicit disable)
|
|
79
|
+
* - `"safe"` (case-insensitive) → `90` (permanent back-compat alias)
|
|
80
|
+
* - integer string `"0".."100"` → that integer
|
|
81
|
+
* - anything else → throws `UsageError("INVALID_FLAG_VALUE")`
|
|
82
|
+
*
|
|
83
|
+
* Citty's `type: "string"` resolves bare flags to `""` and an absent flag to
|
|
84
|
+
* `undefined`. Both forms now disable auto-accept; users must pass an explicit
|
|
85
|
+
* threshold (`--auto-accept=N` or `--auto-accept=safe`) to opt in. This is a
|
|
86
|
+
* deliberate flip from the earlier 0.8.0-RC behaviour, which defaulted to ON
|
|
87
|
+
* at threshold 90 and surprised users who didn't expect Phase B operations to
|
|
88
|
+
* apply without confirmation.
|
|
89
|
+
*
|
|
90
|
+
* Until proposals expose per-operation confidence scores, any non-`undefined`
|
|
91
|
+
* threshold causes the consolidate path to auto-accept the whole batch
|
|
92
|
+
* (legacy "safe" behaviour). The threshold value is preserved for the eventual
|
|
93
|
+
* per-operation comparison; see the TODO in `consolidate.ts`.
|
|
94
|
+
*/
|
|
95
|
+
export function parseAutoAcceptFlag(raw) {
|
|
96
|
+
if (raw === undefined)
|
|
97
|
+
return undefined;
|
|
98
|
+
const trimmed = raw.trim();
|
|
99
|
+
if (trimmed === "")
|
|
100
|
+
return undefined;
|
|
101
|
+
const lower = trimmed.toLowerCase();
|
|
102
|
+
if (lower === "false")
|
|
103
|
+
return undefined;
|
|
104
|
+
if (lower === "safe")
|
|
105
|
+
return 90;
|
|
106
|
+
if (!/^\d+$/.test(trimmed)) {
|
|
107
|
+
throw new UsageError(`Invalid --auto-accept value: "${raw}". Must be an integer 0-100, 'safe', or 'false'.`, "INVALID_FLAG_VALUE");
|
|
108
|
+
}
|
|
109
|
+
const parsed = parseInt(trimmed, 10);
|
|
110
|
+
if (parsed < 0 || parsed > 100) {
|
|
111
|
+
throw new UsageError(`Invalid --auto-accept value: "${raw}". Must be an integer 0-100, 'safe', or 'false'.`, "INVALID_FLAG_VALUE");
|
|
112
|
+
}
|
|
113
|
+
return parsed;
|
|
114
|
+
}
|
|
115
|
+
// ── String flag parsing ──────────────────────────────────────────────────────
|
|
116
|
+
/**
|
|
117
|
+
* Extract a string value from a parsed citty argument object by key.
|
|
118
|
+
*
|
|
119
|
+
* Returns the trimmed string when present and non-empty, or `undefined`
|
|
120
|
+
* otherwise. Eliminates the repeated
|
|
121
|
+
* `typeof args.X === "string" && args.X.trim() ? args.X.trim() : undefined`
|
|
122
|
+
* pattern throughout the CLI command handlers.
|
|
123
|
+
*
|
|
124
|
+
* @param args The citty argument object (typed as unknown for flexibility).
|
|
125
|
+
* @param key The argument key to look up.
|
|
126
|
+
*/
|
|
127
|
+
export function getStringArg(args, key) {
|
|
128
|
+
const val = args[key];
|
|
129
|
+
if (typeof val !== "string")
|
|
130
|
+
return undefined;
|
|
131
|
+
const trimmed = val.trim();
|
|
132
|
+
return trimmed || undefined;
|
|
133
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
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
|
+
* Shared CLI utilities extracted from `src/cli.ts` so that individual
|
|
6
|
+
* command modules can import them without a circular dependency.
|
|
7
|
+
*
|
|
8
|
+
* Exported: output, runWithJsonErrors, parseAllFlagValues, emitJsonError
|
|
9
|
+
*/
|
|
10
|
+
import { stringify as yamlStringify } from "yaml";
|
|
11
|
+
import { ConfigError, NotFoundError, UsageError } from "../core/errors";
|
|
12
|
+
import { getOutputMode } from "../output/context";
|
|
13
|
+
import { shapeForCommand } from "../output/shapes";
|
|
14
|
+
import { formatPlain, outputJsonl } from "../output/text";
|
|
15
|
+
// ── Exit codes ───────────────────────────────────────────────────────────────
|
|
16
|
+
/**
|
|
17
|
+
* Canonical process exit-code table for the akm CLI. Single source of truth —
|
|
18
|
+
* referenced by `classifyExitCode` here and re-imported by `src/cli.ts` so the
|
|
19
|
+
* health-warn / general-failure paths stay in sync.
|
|
20
|
+
*
|
|
21
|
+
* 0 success
|
|
22
|
+
* 1 general / not-found
|
|
23
|
+
* 2 usage error
|
|
24
|
+
* 4 health warn (health command only)
|
|
25
|
+
* 78 config error
|
|
26
|
+
*/
|
|
27
|
+
export const EXIT_CODES = {
|
|
28
|
+
SUCCESS: 0,
|
|
29
|
+
GENERAL: 1,
|
|
30
|
+
USAGE: 2,
|
|
31
|
+
HEALTH_WARN: 4,
|
|
32
|
+
CONFIG: 78,
|
|
33
|
+
};
|
|
34
|
+
// ── Helpers ──────────────────────────────────────────────────────────────────
|
|
35
|
+
function classifyExitCode(error) {
|
|
36
|
+
if (error instanceof UsageError)
|
|
37
|
+
return EXIT_CODES.USAGE;
|
|
38
|
+
if (error instanceof ConfigError)
|
|
39
|
+
return EXIT_CODES.CONFIG;
|
|
40
|
+
if (error instanceof NotFoundError)
|
|
41
|
+
return EXIT_CODES.GENERAL;
|
|
42
|
+
return EXIT_CODES.GENERAL;
|
|
43
|
+
}
|
|
44
|
+
function extractHint(error) {
|
|
45
|
+
if (error instanceof Error && "hint" in error && typeof error.hint === "function") {
|
|
46
|
+
return error.hint();
|
|
47
|
+
}
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Serialize an error to the standard JSON envelope and exit.
|
|
52
|
+
* Used in both the startup try/catch and `runWithJsonErrors`.
|
|
53
|
+
*/
|
|
54
|
+
export function emitJsonError(error) {
|
|
55
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
56
|
+
const hint = extractHint(error);
|
|
57
|
+
const exitCode = classifyExitCode(error);
|
|
58
|
+
const code = error instanceof UsageError || error instanceof ConfigError || error instanceof NotFoundError
|
|
59
|
+
? error.code
|
|
60
|
+
: undefined;
|
|
61
|
+
console.error(JSON.stringify({ ok: false, error: message, ...(code ? { code } : {}), hint }, null, 2));
|
|
62
|
+
process.exit(exitCode);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Run an async function and route any thrown error through the standard JSON
|
|
66
|
+
* error envelope so users never see a raw stack trace.
|
|
67
|
+
*/
|
|
68
|
+
export async function runWithJsonErrors(fn) {
|
|
69
|
+
try {
|
|
70
|
+
await fn();
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
emitJsonError(error);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Render a command result according to the active output mode (json/jsonl/yaml/text).
|
|
78
|
+
*/
|
|
79
|
+
export function output(command, result) {
|
|
80
|
+
const mode = getOutputMode();
|
|
81
|
+
const shaped = shapeForCommand(command, result, mode.detail, mode.shape);
|
|
82
|
+
if (mode.format === "jsonl") {
|
|
83
|
+
outputJsonl(command, shaped);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
switch (mode.format) {
|
|
87
|
+
case "json":
|
|
88
|
+
console.log(JSON.stringify(shaped, null, 2));
|
|
89
|
+
return;
|
|
90
|
+
case "yaml":
|
|
91
|
+
console.log(yamlStringify(shaped));
|
|
92
|
+
return;
|
|
93
|
+
case "text": {
|
|
94
|
+
const plain = formatPlain(command, shaped, mode.detail);
|
|
95
|
+
console.log(plain ?? JSON.stringify(shaped, null, 2));
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
case "md":
|
|
99
|
+
// `--format md` is currently only consumed by `akm health` for the
|
|
100
|
+
// per-run / window-compare table renderings. Commands that don't
|
|
101
|
+
// implement an md renderer fall back to the JSON envelope so
|
|
102
|
+
// pipelines never get an empty stdout.
|
|
103
|
+
console.log(JSON.stringify(shaped, null, 2));
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Collect all occurrences of a repeatable flag from process.argv.
|
|
109
|
+
* Citty's StringArgDef only exposes the last value when a flag is repeated,
|
|
110
|
+
* so for repeatable CLI args (like `--tag foo --tag bar`) we read argv directly.
|
|
111
|
+
* Supports both `--flag value` and `--flag=value` forms.
|
|
112
|
+
*/
|
|
113
|
+
export function parseAllFlagValues(flag) {
|
|
114
|
+
const values = [];
|
|
115
|
+
for (let i = 0; i < process.argv.length; i++) {
|
|
116
|
+
const arg = process.argv[i];
|
|
117
|
+
if (arg === flag && i + 1 < process.argv.length) {
|
|
118
|
+
values.push(process.argv[i + 1]);
|
|
119
|
+
// BUG-M4: skip the value index so `--tag --tag` (literal `--tag`
|
|
120
|
+
// value) does not double-count the second `--tag` as a separate
|
|
121
|
+
// flag occurrence.
|
|
122
|
+
i++;
|
|
123
|
+
}
|
|
124
|
+
else if (arg.startsWith(`${flag}=`)) {
|
|
125
|
+
values.push(arg.slice(flag.length + 1));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return values;
|
|
129
|
+
}
|