akm-cli 0.10.261019 → 0.10.261021
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 +46 -0
- package/STABILITY.md +0 -8
- package/dist/assets/templates/html/metrics.html +14 -8
- package/dist/assets/ui/overview.js +2 -2
- package/dist/commands/health/llm-usage.js +16 -2
- package/dist/commands/health/plugin-staleness.js +126 -112
- package/dist/commands/health/stash-exposure.js +23 -5
- package/dist/commands/health/type-directory-check.js +17 -49
- package/dist/commands/health.js +45 -15
- package/dist/commands/metrics/collect.js +9 -1
- package/dist/commands/metrics/metrics-cli.js +1 -1
- package/dist/commands/metrics/report-view.js +20 -9
- package/dist/commands/sources/plugin-channels.js +147 -0
- package/dist/commands/sources/plugin-upgrade.js +341 -59
- package/dist/commands/sources/self-update.js +6 -3
- package/dist/commands/sources/source-add.js +7 -3
- package/dist/commands/sources/sources-cli.js +15 -2
- package/dist/core/common.js +4 -1
- package/dist/indexer/passes/metadata.js +8 -6
- package/dist/indexer/walk/matchers.js +10 -0
- package/dist/output/text/command-format.js +10 -3
- package/dist/scripts/akm-migrate-node.js +69 -40
- package/dist/scripts/akm-migrate.js +69 -40
- package/dist/workflows/exec/param-secrets.js +29 -1
- package/docs/architecture/internals/health-advisories.md +3 -3
- package/docs/architecture/testing/testing-workflow.md +13 -7
- package/docs/reference/cli.md +39 -11
- package/package.json +3 -1
package/dist/core/common.js
CHANGED
|
@@ -495,7 +495,10 @@ export async function fetchWithTimeout(url, opts, timeoutMs = 30_000, signal) {
|
|
|
495
495
|
try {
|
|
496
496
|
if (controller.signal.aborted)
|
|
497
497
|
throw controller.signal.reason ?? new Error(`Request aborted: ${url}`);
|
|
498
|
-
|
|
498
|
+
// `timeout: false` turns off Bun's independent five-minute socket-idle timer,
|
|
499
|
+
// which would otherwise cut a longer AKM deadline short. The AbortController
|
|
500
|
+
// signal (deadline + caller cancel) remains the only bound on the request.
|
|
501
|
+
return await fetch(url, { ...opts, signal: controller.signal, timeout: false });
|
|
499
502
|
}
|
|
500
503
|
catch (err) {
|
|
501
504
|
if (err instanceof DOMException && err.name === "AbortError") {
|
|
@@ -875,9 +875,9 @@ function isMarkdownFenceClosing(line, fence) {
|
|
|
875
875
|
* Version of what {@link projectMarkdownContent} indexes. It is part of every
|
|
876
876
|
* directory's index fingerprint, so bumping it makes the next `akm index`
|
|
877
877
|
* re-project every directory once instead of keeping the old text for
|
|
878
|
-
* unchanged files.
|
|
878
|
+
* unchanged files. 3: count each fenced identifier once per document (akm#1284).
|
|
879
879
|
*/
|
|
880
|
-
export const CONTENT_PROJECTION_VERSION =
|
|
880
|
+
export const CONTENT_PROJECTION_VERSION = 3;
|
|
881
881
|
/** At or above this length a token with a digit reads as a key or hash, not a name. */
|
|
882
882
|
const TOKEN_LIKE_MIN_LENGTH = 20;
|
|
883
883
|
/**
|
|
@@ -1114,7 +1114,7 @@ export function projectMarkdownContent(body, truncationInfo) {
|
|
|
1114
1114
|
const innerBlock = findInnerFrontmatterBlock(lines);
|
|
1115
1115
|
const start = innerBlock && isFrontmatterShaped(lines, innerBlock) ? innerBlock.close + 1 : 0;
|
|
1116
1116
|
const projected = [];
|
|
1117
|
-
const fenced =
|
|
1117
|
+
const fenced = new Map();
|
|
1118
1118
|
forEachVisibleMarkdownLine(lines, start, (_index, visible) => {
|
|
1119
1119
|
let trimmed = visible.trim();
|
|
1120
1120
|
if (!trimmed || /^(-{3,}|\*{3,}|_{3,}|=+)$/.test(trimmed))
|
|
@@ -1135,11 +1135,13 @@ export function projectMarkdownContent(body, truncationInfo) {
|
|
|
1135
1135
|
projected.push(trimmed);
|
|
1136
1136
|
}, (_index, fencedLine) => {
|
|
1137
1137
|
const identifiers = fencedCodeIdentifiers(fencedLine);
|
|
1138
|
-
|
|
1139
|
-
|
|
1138
|
+
for (const identifier of identifiers.split(/\s+/)) {
|
|
1139
|
+
if (identifier)
|
|
1140
|
+
fenced.set(identifier.toLowerCase(), identifier);
|
|
1141
|
+
}
|
|
1140
1142
|
});
|
|
1141
1143
|
// Fenced identifiers follow the prose, so a head-truncated embedding input keeps the prose first.
|
|
1142
|
-
const text = [...projected, ...fenced].join(" ").replace(/\s+/g, " ").trim();
|
|
1144
|
+
const text = [...projected, ...fenced.values()].join(" ").replace(/\s+/g, " ").trim();
|
|
1143
1145
|
if (!text)
|
|
1144
1146
|
return undefined;
|
|
1145
1147
|
if (truncationInfo)
|
|
@@ -194,6 +194,16 @@ function classifyByParentDirHint(ctx) {
|
|
|
194
194
|
}
|
|
195
195
|
return matchDirectoryHint(parentDir, ctx, 15);
|
|
196
196
|
}
|
|
197
|
+
/**
|
|
198
|
+
* The type a file's location declares, from the same directory rules the
|
|
199
|
+
* indexer applies: parent-directory hint (specificity 15) over the outermost
|
|
200
|
+
* typed ancestor (10), each honouring the rule's extension predicate, the
|
|
201
|
+
* `README.md` documentation exception and nested skill resources. `undefined`
|
|
202
|
+
* when no directory rule claims the file. Path fields only; no bytes are read.
|
|
203
|
+
*/
|
|
204
|
+
export function declaredTypeForPath(ctx) {
|
|
205
|
+
return (classifyByParentDirHint(ctx) ?? classifyByDirectory(ctx))?.type;
|
|
206
|
+
}
|
|
197
207
|
function classifyBySmartMd(ctx) {
|
|
198
208
|
if (ctx.ext !== ".md")
|
|
199
209
|
return null;
|
|
@@ -680,11 +680,15 @@ function formatUpgradePluginLines(r) {
|
|
|
680
680
|
}
|
|
681
681
|
const plugins = Array.isArray(r.plugins) ? r.plugins : [];
|
|
682
682
|
for (const p of plugins) {
|
|
683
|
-
if (p.outcome === "current" || p.outcome === "skipped")
|
|
683
|
+
if ((p.outcome === "current" || p.outcome === "skipped") &&
|
|
684
|
+
(r.updateAvailable === undefined || !p.channel) &&
|
|
685
|
+
!p.channelMismatch &&
|
|
686
|
+
!p.targetChannel)
|
|
684
687
|
continue;
|
|
685
688
|
const versions = p.from && p.to && p.from !== p.to ? ` v${p.from} → v${p.to}` : "";
|
|
689
|
+
const channel = p.channel ? ` [channel ${p.channel}${p.channelMismatch ? "; differs from CLI" : ""}]` : "";
|
|
686
690
|
const note = p.message ? ` (${p.message})` : "";
|
|
687
|
-
lines.push(`${HARNESS_LABELS[String(p.harness)] ?? p.harness} plugin ${p.outcome}${versions}${note}`);
|
|
691
|
+
lines.push(`${HARNESS_LABELS[String(p.harness)] ?? p.harness} plugin ${p.outcome}${versions}${channel}${note}`);
|
|
688
692
|
}
|
|
689
693
|
return lines;
|
|
690
694
|
}
|
|
@@ -698,8 +702,11 @@ function formatUpgradeHead(r) {
|
|
|
698
702
|
if (r.upgraded === true) {
|
|
699
703
|
return `akm upgraded: v${r.currentVersion} → v${r.newVersion}`;
|
|
700
704
|
}
|
|
705
|
+
if (r.targetChannel && r.latestVersion && r.latestVersion !== r.currentVersion && r.updateAvailable === false) {
|
|
706
|
+
return `akm v${r.currentVersion} → v${r.latestVersion} requires --allow-downgrade (run 'akm upgrade --channel ${r.targetChannel} --allow-downgrade' to install)`;
|
|
707
|
+
}
|
|
701
708
|
if (r.updateAvailable === true) {
|
|
702
|
-
return `akm v${r.currentVersion} → v${r.latestVersion} available (run 'akm upgrade${r.channel === "next" ? " --next" : ""}' to install)`;
|
|
709
|
+
return `akm v${r.currentVersion} → v${r.latestVersion} available (run 'akm upgrade${r.targetChannel ? ` --channel ${r.targetChannel}` : r.channel === "next" ? " --next" : ""}' to install)`;
|
|
703
710
|
}
|
|
704
711
|
if (r.updateAvailable === false && r.latestVersion) {
|
|
705
712
|
return `akm v${r.currentVersion} is already the latest version`;
|
|
@@ -34812,7 +34812,7 @@ function projectMarkdownContent(body, truncationInfo) {
|
|
|
34812
34812
|
const innerBlock = findInnerFrontmatterBlock(lines);
|
|
34813
34813
|
const start = innerBlock && isFrontmatterShaped(lines, innerBlock) ? innerBlock.close + 1 : 0;
|
|
34814
34814
|
const projected = [];
|
|
34815
|
-
const fenced =
|
|
34815
|
+
const fenced = new Map;
|
|
34816
34816
|
forEachVisibleMarkdownLine(lines, start, (_index, visible) => {
|
|
34817
34817
|
let trimmed = visible.trim();
|
|
34818
34818
|
if (!trimmed || /^(-{3,}|\*{3,}|_{3,}|=+)$/.test(trimmed))
|
|
@@ -34832,10 +34832,12 @@ function projectMarkdownContent(body, truncationInfo) {
|
|
|
34832
34832
|
projected.push(trimmed);
|
|
34833
34833
|
}, (_index, fencedLine) => {
|
|
34834
34834
|
const identifiers = fencedCodeIdentifiers(fencedLine);
|
|
34835
|
-
|
|
34836
|
-
|
|
34835
|
+
for (const identifier of identifiers.split(/\s+/)) {
|
|
34836
|
+
if (identifier)
|
|
34837
|
+
fenced.set(identifier.toLowerCase(), identifier);
|
|
34838
|
+
}
|
|
34837
34839
|
});
|
|
34838
|
-
const text2 = [...projected, ...fenced].join(" ").replace(/\s+/g, " ").trim();
|
|
34840
|
+
const text2 = [...projected, ...fenced.values()].join(" ").replace(/\s+/g, " ").trim();
|
|
34839
34841
|
if (!text2)
|
|
34840
34842
|
return;
|
|
34841
34843
|
if (truncationInfo)
|
|
@@ -37169,12 +37171,24 @@ function keyLooksSecret(key) {
|
|
|
37169
37171
|
const lower = key.toLowerCase();
|
|
37170
37172
|
return SECRET_KEY_HINTS.some((hint) => lower.includes(hint));
|
|
37171
37173
|
}
|
|
37174
|
+
function segmentLooksSecret(seg) {
|
|
37175
|
+
if (SECRET_VALUE_PREFIX.test(seg))
|
|
37176
|
+
return true;
|
|
37177
|
+
const eq = seg.indexOf("=");
|
|
37178
|
+
if (eq > 0 && keyLooksSecret(seg.slice(0, eq)) && seg.length - eq > 8)
|
|
37179
|
+
return true;
|
|
37180
|
+
if (seg.length >= 32 && !UUID.test(seg) && /^[A-Za-z0-9+_=-]+$/.test(seg) && /\d/.test(seg) && /[a-zA-Z]/.test(seg))
|
|
37181
|
+
return true;
|
|
37182
|
+
return seg.length >= 20 && /^[A-Za-z0-9]+$/.test(seg) && /[a-z]/.test(seg) && /[A-Z]/.test(seg) && /\d/.test(seg);
|
|
37183
|
+
}
|
|
37172
37184
|
function valueLooksSecret(value) {
|
|
37173
37185
|
const s = value.trim();
|
|
37174
37186
|
if (s.length < 20 || /\s/.test(s))
|
|
37175
37187
|
return false;
|
|
37176
37188
|
if (SECRET_VALUE_PREFIX.test(s))
|
|
37177
37189
|
return true;
|
|
37190
|
+
if (PATH_LIKE.test(s))
|
|
37191
|
+
return s.split(/[/\\?&#]/).some(segmentLooksSecret);
|
|
37178
37192
|
const classes = [/[a-z]/, /[A-Z]/, /[0-9]/, /[^A-Za-z0-9]/].filter((re) => re.test(s)).length;
|
|
37179
37193
|
if (s.length >= 24 && classes >= 3)
|
|
37180
37194
|
return true;
|
|
@@ -37216,7 +37230,7 @@ function walkSecretShaped(params, hit) {
|
|
|
37216
37230
|
for (const [k, v] of Object.entries(params))
|
|
37217
37231
|
walk(v, k, k);
|
|
37218
37232
|
}
|
|
37219
|
-
var SECRET_KEY_HINTS, SECRET_VALUE_PREFIX, MOVE_TO_ENV;
|
|
37233
|
+
var SECRET_KEY_HINTS, SECRET_VALUE_PREFIX, PATH_LIKE, UUID, MOVE_TO_ENV;
|
|
37220
37234
|
var init_param_secrets = __esm(() => {
|
|
37221
37235
|
SECRET_KEY_HINTS = [
|
|
37222
37236
|
"secret",
|
|
@@ -37237,6 +37251,8 @@ var init_param_secrets = __esm(() => {
|
|
|
37237
37251
|
"client_secret"
|
|
37238
37252
|
];
|
|
37239
37253
|
SECRET_VALUE_PREFIX = /^(sk-|rk-|ghp_|gho_|ghu_|ghs_|ghr_|github_pat_|xox[baprs]-|AKIA|ASIA|AIza|ya29\.|-----BEGIN)/;
|
|
37254
|
+
PATH_LIKE = /^(\/|\.{1,2}[\\/]|~[\\/]|[A-Za-z]:[\\/]|\\\\)|^[\w.-]+[\\/][^?#]*\.[A-Za-z0-9]{1,8}$/;
|
|
37255
|
+
UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
37240
37256
|
MOVE_TO_ENV = "Workflow params are copied verbatim into every native unit execution context and returned in `akm workflow run` and " + "`akm workflow status` output — move secrets to an env binding (`env:` ref), whose value native execution resolves " + "only at dispatch instead of storing it as a run param.";
|
|
37241
37257
|
});
|
|
37242
37258
|
|
|
@@ -41922,10 +41938,10 @@ var init_marked_esm = __esm(() => {
|
|
|
41922
41938
|
|
|
41923
41939
|
// src/core/asset/markdown-link-targets.ts
|
|
41924
41940
|
function markdownLinkTargets(body, references) {
|
|
41925
|
-
const
|
|
41941
|
+
const tokens2 = markdown.lexer(body);
|
|
41926
41942
|
const definitions = new Map;
|
|
41927
41943
|
if (references) {
|
|
41928
|
-
markdown.walkTokens(
|
|
41944
|
+
markdown.walkTokens(tokens2, (token) => {
|
|
41929
41945
|
if (token.type !== "def")
|
|
41930
41946
|
return;
|
|
41931
41947
|
const definition = /^\s*\[([^\]]+)\]:\s*(\S+)/.exec(token.raw);
|
|
@@ -41934,7 +41950,7 @@ function markdownLinkTargets(body, references) {
|
|
|
41934
41950
|
});
|
|
41935
41951
|
}
|
|
41936
41952
|
const targets = [];
|
|
41937
|
-
markdown.walkTokens(
|
|
41953
|
+
markdown.walkTokens(tokens2, (token) => {
|
|
41938
41954
|
if (token.type !== "link" && token.type !== "image")
|
|
41939
41955
|
return;
|
|
41940
41956
|
const inline = /^!?\[[\s\S]*\]\(/.test(token.raw);
|
|
@@ -62448,7 +62464,7 @@ var require_HTMLParser = __commonJS((exports, module) => {
|
|
|
62448
62464
|
}
|
|
62449
62465
|
}
|
|
62450
62466
|
htmlparser.testTokenizer = function(input2, initialState, lastStartTag, charbychar) {
|
|
62451
|
-
var
|
|
62467
|
+
var tokens2 = [];
|
|
62452
62468
|
switch (initialState) {
|
|
62453
62469
|
case "PCDATA state":
|
|
62454
62470
|
tokenizer = data_state;
|
|
@@ -62470,16 +62486,16 @@ var require_HTMLParser = __commonJS((exports, module) => {
|
|
|
62470
62486
|
flushText();
|
|
62471
62487
|
switch (t) {
|
|
62472
62488
|
case 1:
|
|
62473
|
-
if (
|
|
62474
|
-
|
|
62489
|
+
if (tokens2.length > 0 && tokens2[tokens2.length - 1][0] === "Character") {
|
|
62490
|
+
tokens2[tokens2.length - 1][1] += value;
|
|
62475
62491
|
} else
|
|
62476
|
-
|
|
62492
|
+
tokens2.push(["Character", value]);
|
|
62477
62493
|
break;
|
|
62478
62494
|
case 4:
|
|
62479
|
-
|
|
62495
|
+
tokens2.push(["Comment", value]);
|
|
62480
62496
|
break;
|
|
62481
62497
|
case 5:
|
|
62482
|
-
|
|
62498
|
+
tokens2.push([
|
|
62483
62499
|
"DOCTYPE",
|
|
62484
62500
|
value,
|
|
62485
62501
|
arg3 === undefined ? null : arg3,
|
|
@@ -62500,10 +62516,10 @@ var require_HTMLParser = __commonJS((exports, module) => {
|
|
|
62500
62516
|
var token = ["StartTag", value, attrs];
|
|
62501
62517
|
if (arg4)
|
|
62502
62518
|
token.push(true);
|
|
62503
|
-
|
|
62519
|
+
tokens2.push(token);
|
|
62504
62520
|
break;
|
|
62505
62521
|
case 3:
|
|
62506
|
-
|
|
62522
|
+
tokens2.push(["EndTag", value]);
|
|
62507
62523
|
break;
|
|
62508
62524
|
case -1:
|
|
62509
62525
|
break;
|
|
@@ -62517,7 +62533,7 @@ var require_HTMLParser = __commonJS((exports, module) => {
|
|
|
62517
62533
|
}
|
|
62518
62534
|
this.parse("", true);
|
|
62519
62535
|
}
|
|
62520
|
-
return
|
|
62536
|
+
return tokens2;
|
|
62521
62537
|
};
|
|
62522
62538
|
return htmlparser;
|
|
62523
62539
|
}
|
|
@@ -68891,18 +68907,25 @@ function sourceFacts(counts) {
|
|
|
68891
68907
|
const entries = Object.entries(counts);
|
|
68892
68908
|
return entries.length === 0 ? "-" : entries.map(([k, v]) => `${k}=${v}`).join(" ");
|
|
68893
68909
|
}
|
|
68910
|
+
function tokens(n, a) {
|
|
68911
|
+
return a.calls > 0 && a.usageCalls === 0 ? "unknown" : int(n);
|
|
68912
|
+
}
|
|
68913
|
+
function usageCoverage(a) {
|
|
68914
|
+
return a.usageCalls === undefined ? "-" : `${a.usageCalls}/${a.calls}`;
|
|
68915
|
+
}
|
|
68894
68916
|
function llmRows(group) {
|
|
68895
68917
|
return Object.entries(group).map(([name, a]) => [
|
|
68896
68918
|
name,
|
|
68897
68919
|
int(a.calls),
|
|
68898
68920
|
int(a.failures),
|
|
68899
|
-
|
|
68900
|
-
|
|
68901
|
-
|
|
68921
|
+
tokens(a.promptTokens, a),
|
|
68922
|
+
tokens(a.completionTokens, a),
|
|
68923
|
+
tokens(a.totalTokens, a),
|
|
68924
|
+
usageCoverage(a),
|
|
68902
68925
|
ms(a.totalDurationMs)
|
|
68903
68926
|
]);
|
|
68904
68927
|
}
|
|
68905
|
-
var LLM_HEADERS = ["name", "calls", "failed", "prompt", "completion", "total", "time"];
|
|
68928
|
+
var LLM_HEADERS = ["name", "calls", "failed", "prompt", "completion", "total", "calls with usage", "time"];
|
|
68906
68929
|
function buildMetricsView(r, detail) {
|
|
68907
68930
|
const brief = detail === "brief";
|
|
68908
68931
|
const cut = (items) => brief ? items.slice(0, BRIEF_LIST_LIMIT) : items;
|
|
@@ -68916,7 +68939,8 @@ function buildMetricsView(r, detail) {
|
|
|
68916
68939
|
["shows", int(usage.totals.shows)],
|
|
68917
68940
|
["curates", int(usage.totals.curates)],
|
|
68918
68941
|
["selects", int(usage.totals.selects)],
|
|
68919
|
-
["
|
|
68942
|
+
["searches with hits", int(usage.totals.searchesWithHits)],
|
|
68943
|
+
["selects per search with hits", fixed(usage.selectsPerSearch, 2)],
|
|
68920
68944
|
[
|
|
68921
68945
|
"zero-result searches",
|
|
68922
68946
|
`${usage.totals.zeroResultSearches} (${pct(searches === 0 ? null : usage.totals.zeroResultSearches / searches)})`
|
|
@@ -69023,10 +69047,11 @@ function buildMetricsView(r, detail) {
|
|
|
69023
69047
|
facts: [
|
|
69024
69048
|
["calls", int(llm.calls)],
|
|
69025
69049
|
["failed", int(llm.failures)],
|
|
69026
|
-
["
|
|
69027
|
-
["
|
|
69028
|
-
["
|
|
69029
|
-
["
|
|
69050
|
+
["calls with token usage", usageCoverage(llm)],
|
|
69051
|
+
["prompt tokens", tokens(llm.promptTokens, llm)],
|
|
69052
|
+
["completion tokens", tokens(llm.completionTokens, llm)],
|
|
69053
|
+
["reasoning tokens", llm.calls > 0 && llm.reasoningCalls === 0 ? "unknown" : tokens(llm.reasoningTokens, llm)],
|
|
69054
|
+
["total tokens", tokens(llm.totalTokens, llm)],
|
|
69030
69055
|
["time", ms(llm.totalDurationMs)]
|
|
69031
69056
|
],
|
|
69032
69057
|
tables: [
|
|
@@ -70528,11 +70553,12 @@ function formatUpgradePluginLines(r) {
|
|
|
70528
70553
|
}
|
|
70529
70554
|
const plugins = Array.isArray(r.plugins) ? r.plugins : [];
|
|
70530
70555
|
for (const p of plugins) {
|
|
70531
|
-
if (p.outcome === "current" || p.outcome === "skipped")
|
|
70556
|
+
if ((p.outcome === "current" || p.outcome === "skipped") && (r.updateAvailable === undefined || !p.channel) && !p.channelMismatch && !p.targetChannel)
|
|
70532
70557
|
continue;
|
|
70533
70558
|
const versions = p.from && p.to && p.from !== p.to ? ` v${p.from} → v${p.to}` : "";
|
|
70559
|
+
const channel = p.channel ? ` [channel ${p.channel}${p.channelMismatch ? "; differs from CLI" : ""}]` : "";
|
|
70534
70560
|
const note = p.message ? ` (${p.message})` : "";
|
|
70535
|
-
lines.push(`${HARNESS_LABELS[String(p.harness)] ?? p.harness} plugin ${p.outcome}${versions}${note}`);
|
|
70561
|
+
lines.push(`${HARNESS_LABELS[String(p.harness)] ?? p.harness} plugin ${p.outcome}${versions}${channel}${note}`);
|
|
70536
70562
|
}
|
|
70537
70563
|
return lines;
|
|
70538
70564
|
}
|
|
@@ -70547,8 +70573,11 @@ function formatUpgradeHead(r) {
|
|
|
70547
70573
|
if (r.upgraded === true) {
|
|
70548
70574
|
return `akm upgraded: v${r.currentVersion} → v${r.newVersion}`;
|
|
70549
70575
|
}
|
|
70576
|
+
if (r.targetChannel && r.latestVersion && r.latestVersion !== r.currentVersion && r.updateAvailable === false) {
|
|
70577
|
+
return `akm v${r.currentVersion} → v${r.latestVersion} requires --allow-downgrade (run 'akm upgrade --channel ${r.targetChannel} --allow-downgrade' to install)`;
|
|
70578
|
+
}
|
|
70550
70579
|
if (r.updateAvailable === true) {
|
|
70551
|
-
return `akm v${r.currentVersion} → v${r.latestVersion} available (run 'akm upgrade${r.channel === "next" ? " --next" : ""}' to install)`;
|
|
70580
|
+
return `akm v${r.currentVersion} → v${r.latestVersion} available (run 'akm upgrade${r.targetChannel ? ` --channel ${r.targetChannel}` : r.channel === "next" ? " --next" : ""}' to install)`;
|
|
70552
70581
|
}
|
|
70553
70582
|
if (r.updateAvailable === false && r.latestVersion) {
|
|
70554
70583
|
return `akm v${r.currentVersion} is already the latest version`;
|
|
@@ -72913,15 +72942,15 @@ var SHELL_ASSIGNMENT_WORD = /^[A-Za-z_][A-Za-z0-9_]*=/;
|
|
|
72913
72942
|
function shellStableV2Executable(executable) {
|
|
72914
72943
|
return executable === "akm" || executable.includes("/");
|
|
72915
72944
|
}
|
|
72916
|
-
function skipEnvAssignmentPrefix(
|
|
72917
|
-
if (
|
|
72918
|
-
return { tokens, envWrapped: false };
|
|
72945
|
+
function skipEnvAssignmentPrefix(tokens2) {
|
|
72946
|
+
if (tokens2[0] !== "env")
|
|
72947
|
+
return { tokens: tokens2, envWrapped: false };
|
|
72919
72948
|
let index = 1;
|
|
72920
|
-
while (index <
|
|
72949
|
+
while (index < tokens2.length && SHELL_ASSIGNMENT_WORD.test(tokens2[index]))
|
|
72921
72950
|
index += 1;
|
|
72922
|
-
if (index >=
|
|
72923
|
-
return { tokens, envWrapped: false };
|
|
72924
|
-
return { tokens:
|
|
72951
|
+
if (index >= tokens2.length)
|
|
72952
|
+
return { tokens: tokens2, envWrapped: false };
|
|
72953
|
+
return { tokens: tokens2.slice(index), envWrapped: true };
|
|
72925
72954
|
}
|
|
72926
72955
|
var KNOWN_PROMPT_REF_FAMILIES = new Set([
|
|
72927
72956
|
"agents",
|
|
@@ -73353,16 +73382,16 @@ function migratedObject(data) {
|
|
|
73353
73382
|
const command = exactString(data.command, "command", true).trim();
|
|
73354
73383
|
if (/['"\\]/.test(command))
|
|
73355
73384
|
return "shell-quoting-changes-v2-whitespace-split-semantics";
|
|
73356
|
-
const
|
|
73357
|
-
if (
|
|
73385
|
+
const tokens2 = command.split(/\s+/).filter(Boolean);
|
|
73386
|
+
if (tokens2.length === 0 || tokens2.some((token) => !SAFE_V2_COMMAND_TOKEN.test(token))) {
|
|
73358
73387
|
return "shell-operators-change-v2-literal-argv-semantics";
|
|
73359
73388
|
}
|
|
73360
|
-
const { tokens: targetTokens, envWrapped } = skipEnvAssignmentPrefix(
|
|
73389
|
+
const { tokens: targetTokens, envWrapped } = skipEnvAssignmentPrefix(tokens2);
|
|
73361
73390
|
const executable = targetTokens[0];
|
|
73362
73391
|
if (SHELL_ASSIGNMENT_WORD.test(executable) || !envWrapped && !shellStableV2Executable(executable)) {
|
|
73363
73392
|
return "shell-command-resolution-changes-v2-literal-argv-semantics";
|
|
73364
73393
|
}
|
|
73365
|
-
output2.run =
|
|
73394
|
+
output2.run = tokens2.join(" ");
|
|
73366
73395
|
addSharedNonPromptOverrides(data, akm);
|
|
73367
73396
|
}
|
|
73368
73397
|
output2.akm = akm;
|
|
@@ -34811,7 +34811,7 @@ function projectMarkdownContent(body, truncationInfo) {
|
|
|
34811
34811
|
const innerBlock = findInnerFrontmatterBlock(lines);
|
|
34812
34812
|
const start = innerBlock && isFrontmatterShaped(lines, innerBlock) ? innerBlock.close + 1 : 0;
|
|
34813
34813
|
const projected = [];
|
|
34814
|
-
const fenced =
|
|
34814
|
+
const fenced = new Map;
|
|
34815
34815
|
forEachVisibleMarkdownLine(lines, start, (_index, visible) => {
|
|
34816
34816
|
let trimmed = visible.trim();
|
|
34817
34817
|
if (!trimmed || /^(-{3,}|\*{3,}|_{3,}|=+)$/.test(trimmed))
|
|
@@ -34831,10 +34831,12 @@ function projectMarkdownContent(body, truncationInfo) {
|
|
|
34831
34831
|
projected.push(trimmed);
|
|
34832
34832
|
}, (_index, fencedLine) => {
|
|
34833
34833
|
const identifiers = fencedCodeIdentifiers(fencedLine);
|
|
34834
|
-
|
|
34835
|
-
|
|
34834
|
+
for (const identifier of identifiers.split(/\s+/)) {
|
|
34835
|
+
if (identifier)
|
|
34836
|
+
fenced.set(identifier.toLowerCase(), identifier);
|
|
34837
|
+
}
|
|
34836
34838
|
});
|
|
34837
|
-
const text2 = [...projected, ...fenced].join(" ").replace(/\s+/g, " ").trim();
|
|
34839
|
+
const text2 = [...projected, ...fenced.values()].join(" ").replace(/\s+/g, " ").trim();
|
|
34838
34840
|
if (!text2)
|
|
34839
34841
|
return;
|
|
34840
34842
|
if (truncationInfo)
|
|
@@ -37168,12 +37170,24 @@ function keyLooksSecret(key) {
|
|
|
37168
37170
|
const lower = key.toLowerCase();
|
|
37169
37171
|
return SECRET_KEY_HINTS.some((hint) => lower.includes(hint));
|
|
37170
37172
|
}
|
|
37173
|
+
function segmentLooksSecret(seg) {
|
|
37174
|
+
if (SECRET_VALUE_PREFIX.test(seg))
|
|
37175
|
+
return true;
|
|
37176
|
+
const eq = seg.indexOf("=");
|
|
37177
|
+
if (eq > 0 && keyLooksSecret(seg.slice(0, eq)) && seg.length - eq > 8)
|
|
37178
|
+
return true;
|
|
37179
|
+
if (seg.length >= 32 && !UUID.test(seg) && /^[A-Za-z0-9+_=-]+$/.test(seg) && /\d/.test(seg) && /[a-zA-Z]/.test(seg))
|
|
37180
|
+
return true;
|
|
37181
|
+
return seg.length >= 20 && /^[A-Za-z0-9]+$/.test(seg) && /[a-z]/.test(seg) && /[A-Z]/.test(seg) && /\d/.test(seg);
|
|
37182
|
+
}
|
|
37171
37183
|
function valueLooksSecret(value) {
|
|
37172
37184
|
const s = value.trim();
|
|
37173
37185
|
if (s.length < 20 || /\s/.test(s))
|
|
37174
37186
|
return false;
|
|
37175
37187
|
if (SECRET_VALUE_PREFIX.test(s))
|
|
37176
37188
|
return true;
|
|
37189
|
+
if (PATH_LIKE.test(s))
|
|
37190
|
+
return s.split(/[/\\?&#]/).some(segmentLooksSecret);
|
|
37177
37191
|
const classes = [/[a-z]/, /[A-Z]/, /[0-9]/, /[^A-Za-z0-9]/].filter((re) => re.test(s)).length;
|
|
37178
37192
|
if (s.length >= 24 && classes >= 3)
|
|
37179
37193
|
return true;
|
|
@@ -37215,7 +37229,7 @@ function walkSecretShaped(params, hit) {
|
|
|
37215
37229
|
for (const [k, v] of Object.entries(params))
|
|
37216
37230
|
walk(v, k, k);
|
|
37217
37231
|
}
|
|
37218
|
-
var SECRET_KEY_HINTS, SECRET_VALUE_PREFIX, MOVE_TO_ENV;
|
|
37232
|
+
var SECRET_KEY_HINTS, SECRET_VALUE_PREFIX, PATH_LIKE, UUID, MOVE_TO_ENV;
|
|
37219
37233
|
var init_param_secrets = __esm(() => {
|
|
37220
37234
|
SECRET_KEY_HINTS = [
|
|
37221
37235
|
"secret",
|
|
@@ -37236,6 +37250,8 @@ var init_param_secrets = __esm(() => {
|
|
|
37236
37250
|
"client_secret"
|
|
37237
37251
|
];
|
|
37238
37252
|
SECRET_VALUE_PREFIX = /^(sk-|rk-|ghp_|gho_|ghu_|ghs_|ghr_|github_pat_|xox[baprs]-|AKIA|ASIA|AIza|ya29\.|-----BEGIN)/;
|
|
37253
|
+
PATH_LIKE = /^(\/|\.{1,2}[\\/]|~[\\/]|[A-Za-z]:[\\/]|\\\\)|^[\w.-]+[\\/][^?#]*\.[A-Za-z0-9]{1,8}$/;
|
|
37254
|
+
UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
37239
37255
|
MOVE_TO_ENV = "Workflow params are copied verbatim into every native unit execution context and returned in `akm workflow run` and " + "`akm workflow status` output \u2014 move secrets to an env binding (`env:` ref), whose value native execution resolves " + "only at dispatch instead of storing it as a run param.";
|
|
37240
37256
|
});
|
|
37241
37257
|
|
|
@@ -41921,10 +41937,10 @@ var init_marked_esm = __esm(() => {
|
|
|
41921
41937
|
|
|
41922
41938
|
// src/core/asset/markdown-link-targets.ts
|
|
41923
41939
|
function markdownLinkTargets(body, references) {
|
|
41924
|
-
const
|
|
41940
|
+
const tokens2 = markdown.lexer(body);
|
|
41925
41941
|
const definitions = new Map;
|
|
41926
41942
|
if (references) {
|
|
41927
|
-
markdown.walkTokens(
|
|
41943
|
+
markdown.walkTokens(tokens2, (token) => {
|
|
41928
41944
|
if (token.type !== "def")
|
|
41929
41945
|
return;
|
|
41930
41946
|
const definition = /^\s*\[([^\]]+)\]:\s*(\S+)/.exec(token.raw);
|
|
@@ -41933,7 +41949,7 @@ function markdownLinkTargets(body, references) {
|
|
|
41933
41949
|
});
|
|
41934
41950
|
}
|
|
41935
41951
|
const targets = [];
|
|
41936
|
-
markdown.walkTokens(
|
|
41952
|
+
markdown.walkTokens(tokens2, (token) => {
|
|
41937
41953
|
if (token.type !== "link" && token.type !== "image")
|
|
41938
41954
|
return;
|
|
41939
41955
|
const inline = /^!?\[[\s\S]*\]\(/.test(token.raw);
|
|
@@ -62447,7 +62463,7 @@ var require_HTMLParser = __commonJS((exports, module) => {
|
|
|
62447
62463
|
}
|
|
62448
62464
|
}
|
|
62449
62465
|
htmlparser.testTokenizer = function(input2, initialState, lastStartTag, charbychar) {
|
|
62450
|
-
var
|
|
62466
|
+
var tokens2 = [];
|
|
62451
62467
|
switch (initialState) {
|
|
62452
62468
|
case "PCDATA state":
|
|
62453
62469
|
tokenizer = data_state;
|
|
@@ -62469,16 +62485,16 @@ var require_HTMLParser = __commonJS((exports, module) => {
|
|
|
62469
62485
|
flushText();
|
|
62470
62486
|
switch (t) {
|
|
62471
62487
|
case 1:
|
|
62472
|
-
if (
|
|
62473
|
-
|
|
62488
|
+
if (tokens2.length > 0 && tokens2[tokens2.length - 1][0] === "Character") {
|
|
62489
|
+
tokens2[tokens2.length - 1][1] += value;
|
|
62474
62490
|
} else
|
|
62475
|
-
|
|
62491
|
+
tokens2.push(["Character", value]);
|
|
62476
62492
|
break;
|
|
62477
62493
|
case 4:
|
|
62478
|
-
|
|
62494
|
+
tokens2.push(["Comment", value]);
|
|
62479
62495
|
break;
|
|
62480
62496
|
case 5:
|
|
62481
|
-
|
|
62497
|
+
tokens2.push([
|
|
62482
62498
|
"DOCTYPE",
|
|
62483
62499
|
value,
|
|
62484
62500
|
arg3 === undefined ? null : arg3,
|
|
@@ -62499,10 +62515,10 @@ var require_HTMLParser = __commonJS((exports, module) => {
|
|
|
62499
62515
|
var token = ["StartTag", value, attrs];
|
|
62500
62516
|
if (arg4)
|
|
62501
62517
|
token.push(true);
|
|
62502
|
-
|
|
62518
|
+
tokens2.push(token);
|
|
62503
62519
|
break;
|
|
62504
62520
|
case 3:
|
|
62505
|
-
|
|
62521
|
+
tokens2.push(["EndTag", value]);
|
|
62506
62522
|
break;
|
|
62507
62523
|
case -1:
|
|
62508
62524
|
break;
|
|
@@ -62516,7 +62532,7 @@ var require_HTMLParser = __commonJS((exports, module) => {
|
|
|
62516
62532
|
}
|
|
62517
62533
|
this.parse("", true);
|
|
62518
62534
|
}
|
|
62519
|
-
return
|
|
62535
|
+
return tokens2;
|
|
62520
62536
|
};
|
|
62521
62537
|
return htmlparser;
|
|
62522
62538
|
}
|
|
@@ -68889,18 +68905,25 @@ function sourceFacts(counts) {
|
|
|
68889
68905
|
const entries = Object.entries(counts);
|
|
68890
68906
|
return entries.length === 0 ? "-" : entries.map(([k, v]) => `${k}=${v}`).join(" ");
|
|
68891
68907
|
}
|
|
68908
|
+
function tokens(n, a) {
|
|
68909
|
+
return a.calls > 0 && a.usageCalls === 0 ? "unknown" : int(n);
|
|
68910
|
+
}
|
|
68911
|
+
function usageCoverage(a) {
|
|
68912
|
+
return a.usageCalls === undefined ? "-" : `${a.usageCalls}/${a.calls}`;
|
|
68913
|
+
}
|
|
68892
68914
|
function llmRows(group) {
|
|
68893
68915
|
return Object.entries(group).map(([name, a]) => [
|
|
68894
68916
|
name,
|
|
68895
68917
|
int(a.calls),
|
|
68896
68918
|
int(a.failures),
|
|
68897
|
-
|
|
68898
|
-
|
|
68899
|
-
|
|
68919
|
+
tokens(a.promptTokens, a),
|
|
68920
|
+
tokens(a.completionTokens, a),
|
|
68921
|
+
tokens(a.totalTokens, a),
|
|
68922
|
+
usageCoverage(a),
|
|
68900
68923
|
ms(a.totalDurationMs)
|
|
68901
68924
|
]);
|
|
68902
68925
|
}
|
|
68903
|
-
var LLM_HEADERS = ["name", "calls", "failed", "prompt", "completion", "total", "time"];
|
|
68926
|
+
var LLM_HEADERS = ["name", "calls", "failed", "prompt", "completion", "total", "calls with usage", "time"];
|
|
68904
68927
|
function buildMetricsView(r, detail) {
|
|
68905
68928
|
const brief = detail === "brief";
|
|
68906
68929
|
const cut = (items) => brief ? items.slice(0, BRIEF_LIST_LIMIT) : items;
|
|
@@ -68914,7 +68937,8 @@ function buildMetricsView(r, detail) {
|
|
|
68914
68937
|
["shows", int(usage.totals.shows)],
|
|
68915
68938
|
["curates", int(usage.totals.curates)],
|
|
68916
68939
|
["selects", int(usage.totals.selects)],
|
|
68917
|
-
["
|
|
68940
|
+
["searches with hits", int(usage.totals.searchesWithHits)],
|
|
68941
|
+
["selects per search with hits", fixed(usage.selectsPerSearch, 2)],
|
|
68918
68942
|
[
|
|
68919
68943
|
"zero-result searches",
|
|
68920
68944
|
`${usage.totals.zeroResultSearches} (${pct(searches === 0 ? null : usage.totals.zeroResultSearches / searches)})`
|
|
@@ -69021,10 +69045,11 @@ function buildMetricsView(r, detail) {
|
|
|
69021
69045
|
facts: [
|
|
69022
69046
|
["calls", int(llm.calls)],
|
|
69023
69047
|
["failed", int(llm.failures)],
|
|
69024
|
-
["
|
|
69025
|
-
["
|
|
69026
|
-
["
|
|
69027
|
-
["
|
|
69048
|
+
["calls with token usage", usageCoverage(llm)],
|
|
69049
|
+
["prompt tokens", tokens(llm.promptTokens, llm)],
|
|
69050
|
+
["completion tokens", tokens(llm.completionTokens, llm)],
|
|
69051
|
+
["reasoning tokens", llm.calls > 0 && llm.reasoningCalls === 0 ? "unknown" : tokens(llm.reasoningTokens, llm)],
|
|
69052
|
+
["total tokens", tokens(llm.totalTokens, llm)],
|
|
69028
69053
|
["time", ms(llm.totalDurationMs)]
|
|
69029
69054
|
],
|
|
69030
69055
|
tables: [
|
|
@@ -70526,11 +70551,12 @@ function formatUpgradePluginLines(r) {
|
|
|
70526
70551
|
}
|
|
70527
70552
|
const plugins = Array.isArray(r.plugins) ? r.plugins : [];
|
|
70528
70553
|
for (const p of plugins) {
|
|
70529
|
-
if (p.outcome === "current" || p.outcome === "skipped")
|
|
70554
|
+
if ((p.outcome === "current" || p.outcome === "skipped") && (r.updateAvailable === undefined || !p.channel) && !p.channelMismatch && !p.targetChannel)
|
|
70530
70555
|
continue;
|
|
70531
70556
|
const versions = p.from && p.to && p.from !== p.to ? ` v${p.from} \u2192 v${p.to}` : "";
|
|
70557
|
+
const channel = p.channel ? ` [channel ${p.channel}${p.channelMismatch ? "; differs from CLI" : ""}]` : "";
|
|
70532
70558
|
const note = p.message ? ` (${p.message})` : "";
|
|
70533
|
-
lines.push(`${HARNESS_LABELS[String(p.harness)] ?? p.harness} plugin ${p.outcome}${versions}${note}`);
|
|
70559
|
+
lines.push(`${HARNESS_LABELS[String(p.harness)] ?? p.harness} plugin ${p.outcome}${versions}${channel}${note}`);
|
|
70534
70560
|
}
|
|
70535
70561
|
return lines;
|
|
70536
70562
|
}
|
|
@@ -70545,8 +70571,11 @@ function formatUpgradeHead(r) {
|
|
|
70545
70571
|
if (r.upgraded === true) {
|
|
70546
70572
|
return `akm upgraded: v${r.currentVersion} \u2192 v${r.newVersion}`;
|
|
70547
70573
|
}
|
|
70574
|
+
if (r.targetChannel && r.latestVersion && r.latestVersion !== r.currentVersion && r.updateAvailable === false) {
|
|
70575
|
+
return `akm v${r.currentVersion} \u2192 v${r.latestVersion} requires --allow-downgrade (run 'akm upgrade --channel ${r.targetChannel} --allow-downgrade' to install)`;
|
|
70576
|
+
}
|
|
70548
70577
|
if (r.updateAvailable === true) {
|
|
70549
|
-
return `akm v${r.currentVersion} \u2192 v${r.latestVersion} available (run 'akm upgrade${r.channel === "next" ? " --next" : ""}' to install)`;
|
|
70578
|
+
return `akm v${r.currentVersion} \u2192 v${r.latestVersion} available (run 'akm upgrade${r.targetChannel ? ` --channel ${r.targetChannel}` : r.channel === "next" ? " --next" : ""}' to install)`;
|
|
70550
70579
|
}
|
|
70551
70580
|
if (r.updateAvailable === false && r.latestVersion) {
|
|
70552
70581
|
return `akm v${r.currentVersion} is already the latest version`;
|
|
@@ -72876,15 +72905,15 @@ var SHELL_ASSIGNMENT_WORD = /^[A-Za-z_][A-Za-z0-9_]*=/;
|
|
|
72876
72905
|
function shellStableV2Executable(executable) {
|
|
72877
72906
|
return executable === "akm" || executable.includes("/");
|
|
72878
72907
|
}
|
|
72879
|
-
function skipEnvAssignmentPrefix(
|
|
72880
|
-
if (
|
|
72881
|
-
return { tokens, envWrapped: false };
|
|
72908
|
+
function skipEnvAssignmentPrefix(tokens2) {
|
|
72909
|
+
if (tokens2[0] !== "env")
|
|
72910
|
+
return { tokens: tokens2, envWrapped: false };
|
|
72882
72911
|
let index = 1;
|
|
72883
|
-
while (index <
|
|
72912
|
+
while (index < tokens2.length && SHELL_ASSIGNMENT_WORD.test(tokens2[index]))
|
|
72884
72913
|
index += 1;
|
|
72885
|
-
if (index >=
|
|
72886
|
-
return { tokens, envWrapped: false };
|
|
72887
|
-
return { tokens:
|
|
72914
|
+
if (index >= tokens2.length)
|
|
72915
|
+
return { tokens: tokens2, envWrapped: false };
|
|
72916
|
+
return { tokens: tokens2.slice(index), envWrapped: true };
|
|
72888
72917
|
}
|
|
72889
72918
|
var KNOWN_PROMPT_REF_FAMILIES = new Set([
|
|
72890
72919
|
"agents",
|
|
@@ -73316,16 +73345,16 @@ function migratedObject(data) {
|
|
|
73316
73345
|
const command = exactString(data.command, "command", true).trim();
|
|
73317
73346
|
if (/['"\\]/.test(command))
|
|
73318
73347
|
return "shell-quoting-changes-v2-whitespace-split-semantics";
|
|
73319
|
-
const
|
|
73320
|
-
if (
|
|
73348
|
+
const tokens2 = command.split(/\s+/).filter(Boolean);
|
|
73349
|
+
if (tokens2.length === 0 || tokens2.some((token) => !SAFE_V2_COMMAND_TOKEN.test(token))) {
|
|
73321
73350
|
return "shell-operators-change-v2-literal-argv-semantics";
|
|
73322
73351
|
}
|
|
73323
|
-
const { tokens: targetTokens, envWrapped } = skipEnvAssignmentPrefix(
|
|
73352
|
+
const { tokens: targetTokens, envWrapped } = skipEnvAssignmentPrefix(tokens2);
|
|
73324
73353
|
const executable = targetTokens[0];
|
|
73325
73354
|
if (SHELL_ASSIGNMENT_WORD.test(executable) || !envWrapped && !shellStableV2Executable(executable)) {
|
|
73326
73355
|
return "shell-command-resolution-changes-v2-literal-argv-semantics";
|
|
73327
73356
|
}
|
|
73328
|
-
output2.run =
|
|
73357
|
+
output2.run = tokens2.join(" ");
|
|
73329
73358
|
addSharedNonPromptOverrides(data, akm);
|
|
73330
73359
|
}
|
|
73331
73360
|
output2.akm = akm;
|