@skill-map/cli 0.70.0 → 0.72.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/dist/cli/tutorial/sm-tutorial/SKILL.md +2 -2
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/manifest.json +1 -0
- package/dist/cli/tutorial/sm-tutorial/fixtures-data/sets/portfolio/providers/codex/shared/CLAUDE.md +1 -0
- package/dist/cli/tutorial/sm-tutorial/references/_core.md +27 -20
- package/dist/cli/tutorial/sm-tutorial/references/_manifest.json +1 -1
- package/dist/cli/tutorial/sm-tutorial/references/_manifest.yml +3 -3
- package/dist/cli/tutorial/sm-tutorial/references/fixtures.md +4 -1
- package/dist/cli/tutorial/sm-tutorial/references/part-authoring.md +0 -7
- package/dist/cli/tutorial/sm-tutorial/references/part-basic-daily.md +45 -22
- package/dist/cli/tutorial/sm-tutorial/references/part-basic-fundamentals.md +6 -13
- package/dist/cli/tutorial/sm-tutorial/references/part-basic-kickoff.md +19 -38
- package/dist/cli/tutorial/sm-tutorial/references/part-cli.md +0 -4
- package/dist/cli/tutorial/sm-tutorial/references/part-daily-loop.md +0 -17
- package/dist/cli/tutorial/sm-tutorial/references/part-fundamentals.md +0 -4
- package/dist/cli/tutorial/sm-tutorial/references/part-mcp.md +4 -14
- package/dist/cli/tutorial/sm-tutorial/references/part-plugins.md +0 -8
- package/dist/cli/tutorial/sm-tutorial/references/part-project-kickoff.md +5 -25
- package/dist/cli/tutorial/sm-tutorial/references/part-settings.md +2 -10
- package/dist/cli/tutorial/sm-tutorial/scripts/fixtures.js +6 -3
- package/dist/cli.js +471 -241
- package/dist/index.js +109 -14
- package/dist/kernel/index.js +109 -14
- package/dist/ui/chunk-GKN3HN4R.js +3 -0
- package/dist/ui/index.html +1 -1
- package/dist/ui/{main-K4O6LCIJ.js → main-Z2OYMXNS.js} +1 -1
- package/package.json +2 -2
- package/dist/ui/chunk-RJUHQQOF.js +0 -3
- /package/dist/cli/tutorial/sm-tutorial/fixtures-data/sets/portfolio/providers/agent-skills/shared/{CLAUDE.md → README.md} +0 -0
- /package/dist/cli/tutorial/sm-tutorial/fixtures-data/sets/portfolio/{shared → providers/claude/shared}/CLAUDE.md +0 -0
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// cli/entry.ts
|
|
2
2
|
|
|
3
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
3
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="2c7d4927-4422-59d2-a37a-59fed3a2ec80")}catch(e){}}();
|
|
4
4
|
import { existsSync as existsSync34 } from "fs";
|
|
5
5
|
import { Builtins, Cli as Cli2 } from "clipanion";
|
|
6
6
|
|
|
@@ -250,7 +250,7 @@ function bucketByKind(kind, instance, bag) {
|
|
|
250
250
|
// package.json
|
|
251
251
|
var package_default = {
|
|
252
252
|
name: "@skill-map/cli",
|
|
253
|
-
version: "0.
|
|
253
|
+
version: "0.72.0",
|
|
254
254
|
description: "skill-map reference implementation \u2014 kernel + CLI + adapters.",
|
|
255
255
|
license: "MIT",
|
|
256
256
|
type: "module",
|
|
@@ -581,9 +581,10 @@ var command_schema_default = {
|
|
|
581
581
|
// plugins/ids.ts
|
|
582
582
|
var CORE_PLUGIN_ID = "core";
|
|
583
583
|
var CLAUDE_PLUGIN_ID = "claude";
|
|
584
|
-
var
|
|
584
|
+
var CODEX_PLUGIN_ID = "codex";
|
|
585
585
|
var ANTIGRAVITY_PLUGIN_ID = "antigravity";
|
|
586
586
|
var AGENT_SKILLS_PLUGIN_ID = "agent-skills";
|
|
587
|
+
var OPENCODE_PLUGIN_ID = "opencode";
|
|
587
588
|
|
|
588
589
|
// plugins/claude/providers/claude/index.ts
|
|
589
590
|
var RESERVED_SLASH_NAMES = [
|
|
@@ -808,9 +809,6 @@ var claudeProvider = {
|
|
|
808
809
|
}
|
|
809
810
|
};
|
|
810
811
|
|
|
811
|
-
// plugins/claude/extractors/at-directive/index.ts
|
|
812
|
-
import { posix as pathPosix } from "path";
|
|
813
|
-
|
|
814
812
|
// kernel/util/strip-code-blocks.ts
|
|
815
813
|
var FENCE_RE = /^(?<indent> {0,3})(?<fence>`{3,}|~{3,})/;
|
|
816
814
|
function stripCodeBlocks(input) {
|
|
@@ -818,6 +816,28 @@ function stripCodeBlocks(input) {
|
|
|
818
816
|
const fenceless = stripFences(input);
|
|
819
817
|
return stripInline(fenceless);
|
|
820
818
|
}
|
|
819
|
+
function findBacktickImbalance(body) {
|
|
820
|
+
if (!body) return null;
|
|
821
|
+
const { stripped, openFenceLine } = scanFences(body);
|
|
822
|
+
if (openFenceLine > 0) {
|
|
823
|
+
return { kind: "fence", line: openFenceLine, sourceLine: sourceLineAt(body, openFenceLine) };
|
|
824
|
+
}
|
|
825
|
+
const survivor = stripInline(maskEscapes(stripped)).indexOf("`");
|
|
826
|
+
if (survivor < 0) return null;
|
|
827
|
+
const line = lineOfIndex(stripped, survivor);
|
|
828
|
+
return { kind: "inline", line, sourceLine: sourceLineAt(body, line) };
|
|
829
|
+
}
|
|
830
|
+
function maskEscapes(text) {
|
|
831
|
+
return text.replace(/\\[^\n]/g, " ");
|
|
832
|
+
}
|
|
833
|
+
function lineOfIndex(text, idx) {
|
|
834
|
+
let line = 1;
|
|
835
|
+
for (let i = 0; i < idx; i++) if (text[i] === "\n") line++;
|
|
836
|
+
return line;
|
|
837
|
+
}
|
|
838
|
+
function sourceLineAt(text, line) {
|
|
839
|
+
return text.split("\n")[line - 1]?.trim() ?? "";
|
|
840
|
+
}
|
|
821
841
|
function extractCodeRegions(input) {
|
|
822
842
|
if (!input) return input;
|
|
823
843
|
const stripped = stripCodeBlocks(input);
|
|
@@ -837,30 +857,31 @@ function stripHtml(input) {
|
|
|
837
857
|
function stripCodeAndHtml(input) {
|
|
838
858
|
return stripHtml(stripCodeBlocks(input));
|
|
839
859
|
}
|
|
840
|
-
function
|
|
860
|
+
function scanFences(input) {
|
|
841
861
|
const out = [];
|
|
842
862
|
const lines = input.split("\n");
|
|
843
863
|
let openFence = null;
|
|
844
|
-
|
|
864
|
+
let openFenceLine = 0;
|
|
865
|
+
for (let i = 0; i < lines.length; i++) {
|
|
866
|
+
const line = lines[i];
|
|
845
867
|
if (openFence) {
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
out.push(blank(line));
|
|
849
|
-
openFence = null;
|
|
850
|
-
} else {
|
|
851
|
-
out.push(blank(line));
|
|
852
|
-
}
|
|
868
|
+
if (matchClosingFence(line, openFence)) openFence = null;
|
|
869
|
+
out.push(blank(line));
|
|
853
870
|
continue;
|
|
854
871
|
}
|
|
855
872
|
const open3 = FENCE_RE.exec(line);
|
|
856
873
|
if (open3?.groups) {
|
|
857
874
|
openFence = open3.groups["fence"];
|
|
875
|
+
openFenceLine = i + 1;
|
|
858
876
|
out.push(blank(line));
|
|
859
877
|
continue;
|
|
860
878
|
}
|
|
861
879
|
out.push(line);
|
|
862
880
|
}
|
|
863
|
-
return out.join("\n");
|
|
881
|
+
return { stripped: out.join("\n"), openFenceLine: openFence ? openFenceLine : 0 };
|
|
882
|
+
}
|
|
883
|
+
function stripFences(input) {
|
|
884
|
+
return scanFences(input).stripped;
|
|
864
885
|
}
|
|
865
886
|
function matchClosingFence(line, openFence) {
|
|
866
887
|
const m = FENCE_RE.exec(line);
|
|
@@ -906,82 +927,61 @@ function normalizeTrigger(source) {
|
|
|
906
927
|
return out.trim();
|
|
907
928
|
}
|
|
908
929
|
|
|
930
|
+
// kernel/util/at-token.ts
|
|
931
|
+
import { posix as pathPosix } from "path";
|
|
932
|
+
var AT_TOKEN_RE = /(?:^|[^A-Za-z0-9_@])(@(?:(?:\.{1,2}\/)+|\/)?[a-z0-9](?:[a-z0-9_\-./]*[a-z0-9_])?(?::[a-z0-9][a-z0-9_-]*)?)/gi;
|
|
933
|
+
var FILE_EXT_RE = /\.(md|mdx|js|jsx|ts|tsx|json|yml|yaml|toml|txt|html|css|scss|less|py|rb|go|rs|java|c|cpp|h|hpp|sh|sql|svg|png|jpg|jpeg|gif|webp|pdf)$/i;
|
|
934
|
+
function classifyAtFileToken(bare) {
|
|
935
|
+
if (bare.startsWith("/")) return null;
|
|
936
|
+
if (bare.startsWith("./") || bare.startsWith("../")) return "relative path prefix";
|
|
937
|
+
if (FILE_EXT_RE.test(bare)) return "known file extension";
|
|
938
|
+
return null;
|
|
939
|
+
}
|
|
940
|
+
function resolveAtFileTarget(sourceDir, bare) {
|
|
941
|
+
const joined = sourceDir === "." ? bare : `${sourceDir}/${bare}`;
|
|
942
|
+
return pathPosix.normalize(joined);
|
|
943
|
+
}
|
|
944
|
+
|
|
909
945
|
// plugins/claude/extractors/at-directive/index.ts
|
|
910
946
|
var ID = "at-directive";
|
|
911
|
-
var AT_RE = /(?:^|[^A-Za-z0-9_@])(@(?:\.{1,2}\/|\/)?[a-z0-9](?:[a-z0-9_\-./]*[a-z0-9_])?(?::[a-z0-9][a-z0-9_-]*)?)/gi;
|
|
912
|
-
var FILE_EXT_RE = /\.(md|mdx|js|jsx|ts|tsx|json|yml|yaml|toml|txt|html|css|scss|less|py|rb|go|rs|java|c|cpp|h|hpp|sh|sql|svg|png|jpg|jpeg|gif|webp|pdf)$/i;
|
|
913
947
|
var atDirectiveExtractor = {
|
|
914
948
|
id: ID,
|
|
915
949
|
pluginId: CLAUDE_PLUGIN_ID,
|
|
916
950
|
kind: "extractor",
|
|
917
|
-
description: "Detects `@<
|
|
951
|
+
description: "Detects bare `@<handle>` mentions in a node's body using Claude Code rules and emits a `mentions` link to the named entity. Example: `@team` becomes a `mentions` link. File-shaped tokens like `@docs/api.md` are handled by `core/at-file` instead.",
|
|
918
952
|
scope: "body",
|
|
919
|
-
// Claude-only. This is Claude's `@<
|
|
920
|
-
//
|
|
921
|
-
//
|
|
922
|
-
// extractor
|
|
953
|
+
// Claude-only. This is Claude's bare `@<handle>` MENTION grammar. The
|
|
954
|
+
// file-reference half of `@` (file-shaped tokens) is the shared
|
|
955
|
+
// `core/at-file` extractor, which also serves codex / antigravity; this
|
|
956
|
+
// extractor defers file-shaped tokens to it.
|
|
923
957
|
precondition: { provider: ["claude"] },
|
|
924
|
-
// eslint-disable-next-line complexity
|
|
925
958
|
extract(ctx) {
|
|
926
959
|
const seenMentions = /* @__PURE__ */ new Set();
|
|
927
|
-
const seenReferences = /* @__PURE__ */ new Set();
|
|
928
960
|
const body = stripCodeAndHtml(ctx.body);
|
|
929
961
|
const lineStarts = computeLineStarts(body);
|
|
930
|
-
const
|
|
931
|
-
for (const match of body.matchAll(AT_RE)) {
|
|
962
|
+
for (const match of body.matchAll(AT_TOKEN_RE)) {
|
|
932
963
|
const original = match[1];
|
|
933
964
|
const bare = original.slice(1);
|
|
934
|
-
const captureOffset = (match.index ?? 0) + match[0].indexOf(original);
|
|
935
|
-
const line = lineFor(lineStarts, captureOffset);
|
|
936
|
-
const range = { start: captureOffset, end: captureOffset + original.length, line };
|
|
937
965
|
if (bare.startsWith("/")) continue;
|
|
938
|
-
|
|
939
|
-
if (isReference) {
|
|
940
|
-
const target = resolveSourceRelative(sourceDir, bare);
|
|
941
|
-
const dedupKey = target.toLowerCase();
|
|
942
|
-
if (seenReferences.has(dedupKey)) continue;
|
|
943
|
-
seenReferences.add(dedupKey);
|
|
944
|
-
ctx.emitSignal({
|
|
945
|
-
source: ctx.node.path,
|
|
946
|
-
scope: "body",
|
|
947
|
-
range,
|
|
948
|
-
raw: original,
|
|
949
|
-
candidates: [
|
|
950
|
-
{
|
|
951
|
-
extractorId: ID,
|
|
952
|
-
kind: "references",
|
|
953
|
-
target,
|
|
954
|
-
// 0.85: strong file signal (path prefix `./` / `../` OR
|
|
955
|
-
// a known file extension on the tail). One degree of
|
|
956
|
-
// inference (the runtime still resolves the path).
|
|
957
|
-
confidence: 0.85,
|
|
958
|
-
rationale: bare.startsWith("./") || bare.startsWith("../") ? "relative path prefix" : "known file extension",
|
|
959
|
-
trigger: {
|
|
960
|
-
originalTrigger: original,
|
|
961
|
-
normalizedTrigger: target
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
|
-
]
|
|
965
|
-
});
|
|
966
|
-
continue;
|
|
967
|
-
}
|
|
966
|
+
if (classifyAtFileToken(bare) !== null) continue;
|
|
968
967
|
const normalized = normalizeTrigger(original);
|
|
969
968
|
if (seenMentions.has(normalized)) continue;
|
|
970
969
|
seenMentions.add(normalized);
|
|
970
|
+
const captureOffset = (match.index ?? 0) + match[0].indexOf(original);
|
|
971
|
+
const line = lineFor(lineStarts, captureOffset);
|
|
971
972
|
ctx.emitSignal({
|
|
972
973
|
source: ctx.node.path,
|
|
973
974
|
scope: "body",
|
|
974
|
-
range,
|
|
975
|
+
range: { start: captureOffset, end: captureOffset + original.length, line },
|
|
975
976
|
raw: original,
|
|
976
977
|
candidates: [
|
|
977
978
|
{
|
|
978
979
|
extractorId: ID,
|
|
979
980
|
kind: "mentions",
|
|
980
981
|
target: original,
|
|
981
|
-
// 0.5: genuine ambiguity. A bare `@handle` (no extension, no
|
|
982
|
-
//
|
|
983
|
-
//
|
|
984
|
-
// the question open.
|
|
982
|
+
// 0.5: genuine ambiguity. A bare `@handle` (no extension, no path
|
|
983
|
+
// prefix) could be an agent, a handle, or generic prose. The
|
|
984
|
+
// runtime decides at invocation time; the extractor leaves it open.
|
|
985
985
|
confidence: 0.5,
|
|
986
986
|
rationale: "no extension, no path prefix",
|
|
987
987
|
trigger: {
|
|
@@ -994,72 +994,9 @@ var atDirectiveExtractor = {
|
|
|
994
994
|
}
|
|
995
995
|
}
|
|
996
996
|
};
|
|
997
|
-
function resolveSourceRelative(sourceDir, bare) {
|
|
998
|
-
const joined = sourceDir === "." ? bare : `${sourceDir}/${bare}`;
|
|
999
|
-
return pathPosix.normalize(joined);
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
|
-
// plugins/claude/extractors/slash-command/index.ts
|
|
1003
|
-
var ID2 = "slash-command";
|
|
1004
|
-
var SLASH_RE = /(?<![A-Za-z0-9_/.:?#=&])(\/[a-z0-9][a-z0-9_-]*(?::[a-z0-9][a-z0-9_-]*)?)/gi;
|
|
1005
|
-
var slashCommandExtractor = {
|
|
1006
|
-
id: ID2,
|
|
1007
|
-
pluginId: CLAUDE_PLUGIN_ID,
|
|
1008
|
-
kind: "extractor",
|
|
1009
|
-
description: "Turns `/command` invocations in a node's body into arrows that point at the resolved slash command or skill, using Claude Code routing rules. Example: `/deploy` in the body draws an arrow to the `deploy` command.",
|
|
1010
|
-
scope: "body",
|
|
1011
|
-
// Also authorised under the antigravity lens, which shares the `/command`
|
|
1012
|
-
// grammar: a workflow / skill / AGENTS.md body's `/name` tokens resolve to
|
|
1013
|
-
// BOTH skills and workflows (`invokes: ['skill', 'workflow']`), since
|
|
1014
|
-
// Antigravity invokes either by the same slash. NOT gated under codex:
|
|
1015
|
-
// OpenAI Codex reserves `/` for its OWN built-in commands (`/model`,
|
|
1016
|
-
// `/init`, ...) and invokes user skills with `$` instead (parsed by the
|
|
1017
|
-
// codex `dollar-skill` extractor). A lens that declares no `invokes`
|
|
1018
|
-
// resolution leaves the signals unresolved (no spurious edges).
|
|
1019
|
-
precondition: { provider: ["claude", "antigravity"] },
|
|
1020
|
-
extract(ctx) {
|
|
1021
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1022
|
-
const body = stripCodeAndHtml(ctx.body);
|
|
1023
|
-
const lineStarts = computeLineStarts(body);
|
|
1024
|
-
for (const match of body.matchAll(SLASH_RE)) {
|
|
1025
|
-
const original = match[1];
|
|
1026
|
-
const endIdx = (match.index ?? 0) + match[0].length;
|
|
1027
|
-
const nextChar = body[endIdx];
|
|
1028
|
-
if (nextChar && /[A-Za-z0-9_/-]/.test(nextChar)) continue;
|
|
1029
|
-
const normalized = normalizeTrigger(original);
|
|
1030
|
-
if (seen.has(normalized)) continue;
|
|
1031
|
-
seen.add(normalized);
|
|
1032
|
-
const captureOffset = (match.index ?? 0) + match[0].indexOf(original);
|
|
1033
|
-
const line = lineFor(lineStarts, captureOffset);
|
|
1034
|
-
ctx.emitSignal({
|
|
1035
|
-
source: ctx.node.path,
|
|
1036
|
-
scope: "body",
|
|
1037
|
-
range: { start: captureOffset, end: captureOffset + original.length, line },
|
|
1038
|
-
raw: original,
|
|
1039
|
-
candidates: [
|
|
1040
|
-
{
|
|
1041
|
-
extractorId: ID2,
|
|
1042
|
-
kind: "invokes",
|
|
1043
|
-
target: original,
|
|
1044
|
-
// 0.8: clean `/command` match after code-block strip. The
|
|
1045
|
-
// post-match path guard above filters URL / file-path noise,
|
|
1046
|
-
// so a hit is unambiguous syntax. Resolution against the
|
|
1047
|
-
// live skill / command catalog happens downstream.
|
|
1048
|
-
confidence: 0.8,
|
|
1049
|
-
rationale: "unambiguous slash syntax post code-block strip",
|
|
1050
|
-
trigger: {
|
|
1051
|
-
originalTrigger: original,
|
|
1052
|
-
normalizedTrigger: normalized
|
|
1053
|
-
}
|
|
1054
|
-
}
|
|
1055
|
-
]
|
|
1056
|
-
});
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1059
|
-
};
|
|
1060
997
|
|
|
1061
998
|
// plugins/claude/extractors/tools-counter/index.ts
|
|
1062
|
-
var
|
|
999
|
+
var ID2 = "tools-counter";
|
|
1063
1000
|
var count = {
|
|
1064
1001
|
slot: "card.footer.left",
|
|
1065
1002
|
icon: "pi-wrench",
|
|
@@ -1069,7 +1006,7 @@ var count = {
|
|
|
1069
1006
|
};
|
|
1070
1007
|
var TOOLTIP_MAX = 255;
|
|
1071
1008
|
var toolsCounterExtractor = {
|
|
1072
|
-
id:
|
|
1009
|
+
id: ID2,
|
|
1073
1010
|
pluginId: CLAUDE_PLUGIN_ID,
|
|
1074
1011
|
kind: "extractor",
|
|
1075
1012
|
description: "Counts the tools an agent declares in its frontmatter and shows the count on the agent card. Example: an agent with `tools: [Bash, Read, Grep]` shows a count of 3.",
|
|
@@ -1355,10 +1292,15 @@ var antigravityProvider = {
|
|
|
1355
1292
|
schemaJson: workflow_schema_default,
|
|
1356
1293
|
ui: {
|
|
1357
1294
|
label: "Workflows",
|
|
1358
|
-
//
|
|
1359
|
-
//
|
|
1360
|
-
color
|
|
1361
|
-
|
|
1295
|
+
// A workflow is Antigravity's command-equivalent (its own slash-
|
|
1296
|
+
// invocable procedural kind, the slot Claude fills with `command`),
|
|
1297
|
+
// so it adopts the SAME color as Claude's `command` kind (amber) for a
|
|
1298
|
+
// uniform cross-provider vocabulary, the same way skills normalise to
|
|
1299
|
+
// the cross-provider green of COMMONS_KINDS. The Antigravity violet
|
|
1300
|
+
// stays on the provider-level `presentation` (the lens identity), not
|
|
1301
|
+
// on this kind.
|
|
1302
|
+
color: "#f59e0b",
|
|
1303
|
+
colorDark: "#fbbf24",
|
|
1362
1304
|
icon: { kind: "pi", id: "pi-sitemap" }
|
|
1363
1305
|
},
|
|
1364
1306
|
// The handle is ALWAYS the filename stem (`/<name>`): Antigravity
|
|
@@ -1370,7 +1312,12 @@ var antigravityProvider = {
|
|
|
1370
1312
|
// `/<name>` slash invocations resolve to BOTH skills and workflows: under
|
|
1371
1313
|
// the antigravity lens a `/deploy` links to either `.agents/skills/deploy`
|
|
1372
1314
|
// or `.agent/workflows/deploy.md`. Overrides the open-standard default
|
|
1373
|
-
// (`invokes: ['skill']`) to add the own `workflow` kind.
|
|
1315
|
+
// (`invokes: ['skill']`) to add the own `workflow` kind. Antigravity's OTHER
|
|
1316
|
+
// connector, `@filename` file references (the documented rules / skill /
|
|
1317
|
+
// workflow file pointer, a file-picker grammar like Codex's, distinct from
|
|
1318
|
+
// Claude's `@`-agent-mention), needs no entry here: the shared `core/at-file`
|
|
1319
|
+
// extractor (gated to claude / codex / antigravity) emits them as
|
|
1320
|
+
// `references` resolved by PATH, lens-independent.
|
|
1374
1321
|
resolution: { invokes: ["skill", "workflow"] },
|
|
1375
1322
|
classify(path) {
|
|
1376
1323
|
if (/^\.agent\/workflows\/[^/]+\.md$/.test(path.toLowerCase())) return "workflow";
|
|
@@ -1461,7 +1408,7 @@ var agent_schema_default2 = {
|
|
|
1461
1408
|
// plugins/codex/providers/codex/index.ts
|
|
1462
1409
|
var codexProvider = {
|
|
1463
1410
|
id: "codex",
|
|
1464
|
-
pluginId:
|
|
1411
|
+
pluginId: CODEX_PLUGIN_ID,
|
|
1465
1412
|
kind: "provider",
|
|
1466
1413
|
description: "Classifies `.codex/agents/*.toml` as OpenAI Codex CLI sub-agents and `.agents/skills/*/SKILL.md` as Codex skills (open standard).",
|
|
1467
1414
|
// Provider identity for the active-lens dropdown, the topbar lens chip,
|
|
@@ -1562,78 +1509,12 @@ var codexProvider = {
|
|
|
1562
1509
|
}
|
|
1563
1510
|
};
|
|
1564
1511
|
|
|
1565
|
-
// plugins/codex/extractors/at-file/index.ts
|
|
1566
|
-
import { posix as pathPosix2 } from "path";
|
|
1567
|
-
var ID4 = "at-file";
|
|
1568
|
-
var AT_RE2 = /(?:^|[^A-Za-z0-9_@])(@(?:\.{1,2}\/|\/)?[a-z0-9](?:[a-z0-9_\-./]*[a-z0-9_])?(?::[a-z0-9][a-z0-9_-]*)?)/gi;
|
|
1569
|
-
var FILE_EXT_RE2 = /\.(md|mdx|js|jsx|ts|tsx|json|yml|yaml|toml|txt|html|css|scss|less|py|rb|go|rs|java|c|cpp|h|hpp|sh|sql|svg|png|jpg|jpeg|gif|webp|pdf)$/i;
|
|
1570
|
-
var atFileExtractor = {
|
|
1571
|
-
id: ID4,
|
|
1572
|
-
pluginId: OPENAI_PLUGIN_ID,
|
|
1573
|
-
kind: "extractor",
|
|
1574
|
-
description: "Detects `@<file>` references in a node's body under the OpenAI Codex lens, where `@` is a file picker. A path- or extension-shaped token becomes a `references` link to that file; a bare `@handle` forms no edge. Example: `@builder.toml` in an agent's prompt draws an arrow to the `builder` agent file.",
|
|
1575
|
-
scope: "body",
|
|
1576
|
-
// Codex-only: under the codex lens `@` is a file-path picker, so only
|
|
1577
|
-
// file-shaped tokens form references. The claude `at-directive` (bare
|
|
1578
|
-
// `@handle` → agent mention) is NOT gated under codex.
|
|
1579
|
-
precondition: { provider: ["codex"] },
|
|
1580
|
-
extract(ctx) {
|
|
1581
|
-
const seenReferences = /* @__PURE__ */ new Set();
|
|
1582
|
-
const body = stripCodeAndHtml(ctx.body);
|
|
1583
|
-
const lineStarts = computeLineStarts(body);
|
|
1584
|
-
const sourceDir = pathPosix2.dirname(ctx.node.path);
|
|
1585
|
-
for (const match of body.matchAll(AT_RE2)) {
|
|
1586
|
-
const original = match[1];
|
|
1587
|
-
const bare = original.slice(1);
|
|
1588
|
-
const rationale = classifyAtToken(bare);
|
|
1589
|
-
if (rationale === null) continue;
|
|
1590
|
-
const target = resolveSourceRelative2(sourceDir, bare);
|
|
1591
|
-
const dedupKey = target.toLowerCase();
|
|
1592
|
-
if (seenReferences.has(dedupKey)) continue;
|
|
1593
|
-
seenReferences.add(dedupKey);
|
|
1594
|
-
const captureOffset = (match.index ?? 0) + match[0].indexOf(original);
|
|
1595
|
-
const line = lineFor(lineStarts, captureOffset);
|
|
1596
|
-
ctx.emitSignal({
|
|
1597
|
-
source: ctx.node.path,
|
|
1598
|
-
scope: "body",
|
|
1599
|
-
range: { start: captureOffset, end: captureOffset + original.length, line },
|
|
1600
|
-
raw: original,
|
|
1601
|
-
candidates: [
|
|
1602
|
-
{
|
|
1603
|
-
extractorId: ID4,
|
|
1604
|
-
kind: "references",
|
|
1605
|
-
target,
|
|
1606
|
-
// 0.85: strong file signal (path prefix or known extension),
|
|
1607
|
-
// one degree of inference (the runtime resolves the path).
|
|
1608
|
-
confidence: 0.85,
|
|
1609
|
-
rationale,
|
|
1610
|
-
trigger: {
|
|
1611
|
-
originalTrigger: original,
|
|
1612
|
-
normalizedTrigger: target
|
|
1613
|
-
}
|
|
1614
|
-
}
|
|
1615
|
-
]
|
|
1616
|
-
});
|
|
1617
|
-
}
|
|
1618
|
-
}
|
|
1619
|
-
};
|
|
1620
|
-
function classifyAtToken(bare) {
|
|
1621
|
-
if (bare.startsWith("/")) return null;
|
|
1622
|
-
if (bare.startsWith("./") || bare.startsWith("../")) return "relative path prefix";
|
|
1623
|
-
if (FILE_EXT_RE2.test(bare)) return "known file extension";
|
|
1624
|
-
return null;
|
|
1625
|
-
}
|
|
1626
|
-
function resolveSourceRelative2(sourceDir, bare) {
|
|
1627
|
-
const joined = sourceDir === "." ? bare : `${sourceDir}/${bare}`;
|
|
1628
|
-
return pathPosix2.normalize(joined);
|
|
1629
|
-
}
|
|
1630
|
-
|
|
1631
1512
|
// plugins/codex/extractors/dollar-skill/index.ts
|
|
1632
|
-
var
|
|
1513
|
+
var ID3 = "dollar-skill";
|
|
1633
1514
|
var DOLLAR_RE = /(?<![A-Za-z0-9_$])(\$[a-z][a-z0-9_-]*)/g;
|
|
1634
1515
|
var dollarSkillExtractor = {
|
|
1635
|
-
id:
|
|
1636
|
-
pluginId:
|
|
1516
|
+
id: ID3,
|
|
1517
|
+
pluginId: CODEX_PLUGIN_ID,
|
|
1637
1518
|
kind: "extractor",
|
|
1638
1519
|
description: "Turns `$skill` invocations in a node's body into arrows that point at the resolved Codex skill, using OpenAI Codex routing rules. Example: `$check-links` in the body draws an arrow to the `check-links` skill.",
|
|
1639
1520
|
scope: "body",
|
|
@@ -1659,7 +1540,7 @@ var dollarSkillExtractor = {
|
|
|
1659
1540
|
raw: original,
|
|
1660
1541
|
candidates: [
|
|
1661
1542
|
{
|
|
1662
|
-
extractorId:
|
|
1543
|
+
extractorId: ID3,
|
|
1663
1544
|
kind: "invokes",
|
|
1664
1545
|
target: original,
|
|
1665
1546
|
// 0.8: clean `$skill` match after code-block strip. The
|
|
@@ -1679,6 +1560,186 @@ var dollarSkillExtractor = {
|
|
|
1679
1560
|
}
|
|
1680
1561
|
};
|
|
1681
1562
|
|
|
1563
|
+
// plugins/opencode/providers/opencode/schemas/agent.schema.json
|
|
1564
|
+
var agent_schema_default3 = {
|
|
1565
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
1566
|
+
$id: "https://skill-map.ai/providers/opencode/v1/frontmatter/agent.schema.json",
|
|
1567
|
+
title: "FrontmatterOpenCodeAgent",
|
|
1568
|
+
description: "Frontmatter shape for nodes classified as `agent` by the OpenCode Provider. OpenCode agents live as markdown files under `.opencode/agent/<name>.md` (https://opencode.ai/docs/agents); the markdown body is the agent prompt. There is NO `name` field, the filename stem is the handle. Field set mirrors OpenCode's documented agent frontmatter; `additionalProperties: true` lets any other inherited key flow through unchanged.",
|
|
1569
|
+
allOf: [
|
|
1570
|
+
{ $ref: "https://skill-map.ai/spec/v0/frontmatter/base.schema.json" }
|
|
1571
|
+
],
|
|
1572
|
+
type: "object",
|
|
1573
|
+
additionalProperties: true,
|
|
1574
|
+
required: ["description"],
|
|
1575
|
+
properties: {
|
|
1576
|
+
description: {
|
|
1577
|
+
type: "string",
|
|
1578
|
+
description: "What the agent does and when to use it. OpenCode surfaces this when selecting a subagent; skill-map mirrors it in the card. Required: a description-less agent cannot be meaningfully selected."
|
|
1579
|
+
},
|
|
1580
|
+
mode: {
|
|
1581
|
+
type: "string",
|
|
1582
|
+
enum: ["all", "primary", "subagent"],
|
|
1583
|
+
description: "How the agent runs: `primary` (a top-level agent the user can switch to), `subagent` (invoked by another agent via the `task` tool), or `all`. Inherits OpenCode's default when omitted."
|
|
1584
|
+
},
|
|
1585
|
+
model: {
|
|
1586
|
+
type: "string",
|
|
1587
|
+
description: "Model the agent runs against, in OpenCode's `provider/model` form (e.g. `anthropic/claude-opus-4-8`). Inherits the parent's model when omitted."
|
|
1588
|
+
},
|
|
1589
|
+
permission: {
|
|
1590
|
+
type: "object",
|
|
1591
|
+
additionalProperties: true,
|
|
1592
|
+
description: "Per-tool permission policy. Each documented tool key maps to `allow`, `ask`, or `deny`; `bash` may instead be a map of command globs to policies. Any tool omitted inherits OpenCode's default.",
|
|
1593
|
+
properties: {
|
|
1594
|
+
edit: { type: "string", enum: ["allow", "ask", "deny"] },
|
|
1595
|
+
bash: {
|
|
1596
|
+
description: "Either a blanket policy or a per-command-glob map.",
|
|
1597
|
+
oneOf: [
|
|
1598
|
+
{ type: "string", enum: ["allow", "ask", "deny"] },
|
|
1599
|
+
{
|
|
1600
|
+
type: "object",
|
|
1601
|
+
additionalProperties: { type: "string", enum: ["allow", "ask", "deny"] }
|
|
1602
|
+
}
|
|
1603
|
+
]
|
|
1604
|
+
},
|
|
1605
|
+
webfetch: { type: "string", enum: ["allow", "ask", "deny"] }
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
};
|
|
1610
|
+
|
|
1611
|
+
// plugins/opencode/providers/opencode/schemas/command.schema.json
|
|
1612
|
+
var command_schema_default2 = {
|
|
1613
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
1614
|
+
$id: "https://skill-map.ai/providers/opencode/v1/frontmatter/command.schema.json",
|
|
1615
|
+
title: "FrontmatterOpenCodeCommand",
|
|
1616
|
+
description: "Frontmatter shape for nodes classified as `command` by the OpenCode Provider. OpenCode custom commands live as markdown files under `.opencode/commands/<name>.md` (https://opencode.ai/docs/commands); the markdown body is the command template and the filename stem is the command name (invoked `/<name>`). No required fields beyond the base (OpenCode treats the frontmatter as optional metadata); `additionalProperties: true` lets inherited keys flow through unchanged.",
|
|
1617
|
+
allOf: [
|
|
1618
|
+
{ $ref: "https://skill-map.ai/spec/v0/frontmatter/base.schema.json" }
|
|
1619
|
+
],
|
|
1620
|
+
type: "object",
|
|
1621
|
+
additionalProperties: true,
|
|
1622
|
+
properties: {
|
|
1623
|
+
description: {
|
|
1624
|
+
type: "string",
|
|
1625
|
+
description: "Brief explanation of the command's purpose, shown in OpenCode's slash-command picker."
|
|
1626
|
+
},
|
|
1627
|
+
agent: {
|
|
1628
|
+
type: "string",
|
|
1629
|
+
description: "Optional agent this command runs under (matches an `.opencode/agent/<name>` handle)."
|
|
1630
|
+
},
|
|
1631
|
+
model: {
|
|
1632
|
+
type: "string",
|
|
1633
|
+
description: "Optional model override for this command, in OpenCode's `provider/model` form."
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1636
|
+
};
|
|
1637
|
+
|
|
1638
|
+
// plugins/opencode/providers/opencode/index.ts
|
|
1639
|
+
var OPENCODE_RESERVED_SLASH_VERBS = [
|
|
1640
|
+
// Inherited open-standard base (universal cross-agent slash commands).
|
|
1641
|
+
...COMMONS_RESERVED_NAMES["skill"] ?? [],
|
|
1642
|
+
// OpenCode-specific built-in verbs (`/help` already lives in the base).
|
|
1643
|
+
"init",
|
|
1644
|
+
"redo",
|
|
1645
|
+
"share",
|
|
1646
|
+
"undo"
|
|
1647
|
+
];
|
|
1648
|
+
var opencodeProvider = {
|
|
1649
|
+
id: "opencode",
|
|
1650
|
+
pluginId: OPENCODE_PLUGIN_ID,
|
|
1651
|
+
kind: "provider",
|
|
1652
|
+
description: "Classifies `.opencode/agent/*.md` as OpenCode agents and `.opencode/commands/*.md` as OpenCode commands (its own kinds), and skills under `.opencode/skills/`, `.claude/skills/`, and `.agents/skills/` (the project-level homes OpenCode reads).",
|
|
1653
|
+
// Provider identity for the active-lens dropdown, the topbar lens chip, and
|
|
1654
|
+
// the per-node provider chip. OpenCode has no strong model vendor (it is
|
|
1655
|
+
// model-agnostic), so the label is the bare product name, NOT a possessive
|
|
1656
|
+
// `<Vendor>'s <product>` like the other vendor lenses. Cyan, distinct from
|
|
1657
|
+
// codex green, antigravity violet, and the agent-skills slate.
|
|
1658
|
+
presentation: {
|
|
1659
|
+
label: "OpenCode",
|
|
1660
|
+
color: "#0891b2",
|
|
1661
|
+
colorDark: "#22d3ee",
|
|
1662
|
+
// OpenCode invokes its custom commands with `/<name>`; the palette paints
|
|
1663
|
+
// this as the `invokes` edge glyph under the opencode lens. (Skills are
|
|
1664
|
+
// loaded by OpenCode's native `skill` tool, not a body sigil.)
|
|
1665
|
+
invocationSigil: "/"
|
|
1666
|
+
},
|
|
1667
|
+
// Auto-detect marker: a `.opencode/` directory marks an OpenCode project.
|
|
1668
|
+
detect: { markers: [".opencode"] },
|
|
1669
|
+
// Vendor lens: gated to the active lens. OpenCode only resolves its own
|
|
1670
|
+
// territory (plus the Claude-compat / open-standard skill homes it reads).
|
|
1671
|
+
// Gating keeps the walker from claiming OpenCode territory under another
|
|
1672
|
+
// lens, where the OpenCode runtime would never resolve it anyway, and keeps
|
|
1673
|
+
// the `.claude/skills/` claim here from colliding with the claude lens.
|
|
1674
|
+
gatedByActiveLens: true,
|
|
1675
|
+
// Beta: ships enabled, auto-detects `.opencode/`, selectable as the active
|
|
1676
|
+
// lens, with a maturity badge. Same posture as codex / antigravity, since
|
|
1677
|
+
// the lens is freshly landed. Promote to `stable` (drop the field) once it
|
|
1678
|
+
// has real-world mileage.
|
|
1679
|
+
stability: "beta",
|
|
1680
|
+
// Single read rule: all three families are `.md` + YAML frontmatter, so one
|
|
1681
|
+
// `COMMONS_READ` pass suffices (no multi-rule `read` like codex, which mixes
|
|
1682
|
+
// `.toml`). `classify()` below routes each path to its kind.
|
|
1683
|
+
read: COMMONS_READ,
|
|
1684
|
+
kinds: {
|
|
1685
|
+
agent: {
|
|
1686
|
+
schema: "./schemas/agent.schema.json",
|
|
1687
|
+
schemaJson: agent_schema_default3,
|
|
1688
|
+
ui: {
|
|
1689
|
+
label: "Agents",
|
|
1690
|
+
// Cross-provider agent vocabulary: same blue as Claude's `agent` kind,
|
|
1691
|
+
// so an agent paints the same regardless of which lens sourced it.
|
|
1692
|
+
color: "#3b82f6",
|
|
1693
|
+
colorDark: "#60a5fa",
|
|
1694
|
+
icon: { kind: "pi", id: "pi-user" }
|
|
1695
|
+
},
|
|
1696
|
+
// No `name` frontmatter field: the filename stem
|
|
1697
|
+
// (`.opencode/agent/<name>.md`) is the handle.
|
|
1698
|
+
identifiers: ["filename-basename"]
|
|
1699
|
+
},
|
|
1700
|
+
command: {
|
|
1701
|
+
schema: "./schemas/command.schema.json",
|
|
1702
|
+
schemaJson: command_schema_default2,
|
|
1703
|
+
ui: {
|
|
1704
|
+
label: "Commands",
|
|
1705
|
+
// Cross-provider command vocabulary: same amber (and icon) as Claude's
|
|
1706
|
+
// `command` kind and Antigravity's `workflow` kind.
|
|
1707
|
+
color: "#f59e0b",
|
|
1708
|
+
colorDark: "#fbbf24",
|
|
1709
|
+
icon: { kind: "svg", path: "M4 17 L10 11 L4 5 M12 19 L20 19" }
|
|
1710
|
+
},
|
|
1711
|
+
// The filename stem is the command name (`/<name>`); no `name` field.
|
|
1712
|
+
identifiers: ["filename-basename"]
|
|
1713
|
+
},
|
|
1714
|
+
// Open-standard `skill` kind, inherited from `agent-skills` by manifest
|
|
1715
|
+
// composition (same schema + green visuals every adopter shares).
|
|
1716
|
+
// `classify()` routes the three skill homes OpenCode reads into this kind.
|
|
1717
|
+
...COMMONS_KINDS
|
|
1718
|
+
},
|
|
1719
|
+
// `/<name>` slash invocations resolve to commands ONLY: OpenCode reserves the
|
|
1720
|
+
// slash for its custom commands, and loads skills via its native `skill` tool
|
|
1721
|
+
// (no `/`-invocation), so `invokes` does NOT target `skill` here (unlike
|
|
1722
|
+
// claude). Overrides the open-standard default (`invokes: ['skill']`). The
|
|
1723
|
+
// `core/slash-command` extractor is authorised under the opencode lens (its
|
|
1724
|
+
// precondition lists `opencode`) so `/deploy` in a body emits the link.
|
|
1725
|
+
resolution: { invokes: ["command"] },
|
|
1726
|
+
// Reserved built-in slash commands, applied to the `command` kind (the only
|
|
1727
|
+
// `/`-invocable OpenCode kind: skills are tool-loaded, not slash-invoked, so
|
|
1728
|
+
// a skill named after a built-in cannot be shadowed through the slash
|
|
1729
|
+
// channel and is deliberately NOT reserved).
|
|
1730
|
+
reservedNames: {
|
|
1731
|
+
command: OPENCODE_RESERVED_SLASH_VERBS
|
|
1732
|
+
},
|
|
1733
|
+
classify(path) {
|
|
1734
|
+
const lower = path.toLowerCase();
|
|
1735
|
+
if (/^\.opencode\/agent\/[^/]+\.md$/.test(lower)) return "agent";
|
|
1736
|
+
if (/^\.opencode\/commands\/[^/]+\.md$/.test(lower)) return "command";
|
|
1737
|
+
if (/^\.opencode\/skills\/[^/]+\/skill\.md$/.test(lower)) return "skill";
|
|
1738
|
+
if (/^\.claude\/skills\/[^/]+\/skill\.md$/.test(lower)) return "skill";
|
|
1739
|
+
return classifyCommonsPath(path);
|
|
1740
|
+
}
|
|
1741
|
+
};
|
|
1742
|
+
|
|
1682
1743
|
// plugins/core/providers/core-markdown/schemas/markdown.schema.json
|
|
1683
1744
|
var markdown_schema_default = {
|
|
1684
1745
|
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
@@ -1765,12 +1826,68 @@ var coreMarkdownProvider = {
|
|
|
1765
1826
|
}
|
|
1766
1827
|
};
|
|
1767
1828
|
|
|
1829
|
+
// plugins/core/extractors/at-file/index.ts
|
|
1830
|
+
import { posix as pathPosix2 } from "path";
|
|
1831
|
+
var ID4 = "at-file";
|
|
1832
|
+
var atFileExtractor = {
|
|
1833
|
+
id: ID4,
|
|
1834
|
+
pluginId: CORE_PLUGIN_ID,
|
|
1835
|
+
kind: "extractor",
|
|
1836
|
+
description: "Detects `@<file>` references in a node's body for the `@`-file-picker lenses (Codex, Antigravity, Claude), where `@` points at a workspace file. A path- or extension-shaped token becomes a `references` link to that file; a bare `@handle` forms no edge. Example: `@builder.toml` in a body draws an arrow to the `builder` file.",
|
|
1837
|
+
scope: "body",
|
|
1838
|
+
// The lenses whose runtime reads `@` as a file-path picker. Codex (`@` is a
|
|
1839
|
+
// file picker, `$` invokes skills), Antigravity (documented `@filename` file
|
|
1840
|
+
// refs), and Claude (`@file.md` file ref; its bare-handle MENTION half lives
|
|
1841
|
+
// in `claude/at-directive`). NOT gated under `agent-skills` / `markdown`,
|
|
1842
|
+
// whose runtimes read `@` as nothing (no phantom edges).
|
|
1843
|
+
precondition: { provider: ["claude", "codex", "antigravity"] },
|
|
1844
|
+
extract(ctx) {
|
|
1845
|
+
const seenReferences = /* @__PURE__ */ new Set();
|
|
1846
|
+
const body = stripCodeAndHtml(ctx.body);
|
|
1847
|
+
const lineStarts = computeLineStarts(body);
|
|
1848
|
+
const sourceDir = pathPosix2.dirname(ctx.node.path);
|
|
1849
|
+
for (const match of body.matchAll(AT_TOKEN_RE)) {
|
|
1850
|
+
const original = match[1];
|
|
1851
|
+
const bare = original.slice(1);
|
|
1852
|
+
const rationale = classifyAtFileToken(bare);
|
|
1853
|
+
if (rationale === null) continue;
|
|
1854
|
+
const target = resolveAtFileTarget(sourceDir, bare);
|
|
1855
|
+
const dedupKey = target.toLowerCase();
|
|
1856
|
+
if (seenReferences.has(dedupKey)) continue;
|
|
1857
|
+
seenReferences.add(dedupKey);
|
|
1858
|
+
const captureOffset = (match.index ?? 0) + match[0].indexOf(original);
|
|
1859
|
+
const line = lineFor(lineStarts, captureOffset);
|
|
1860
|
+
ctx.emitSignal({
|
|
1861
|
+
source: ctx.node.path,
|
|
1862
|
+
scope: "body",
|
|
1863
|
+
range: { start: captureOffset, end: captureOffset + original.length, line },
|
|
1864
|
+
raw: original,
|
|
1865
|
+
candidates: [
|
|
1866
|
+
{
|
|
1867
|
+
extractorId: ID4,
|
|
1868
|
+
kind: "references",
|
|
1869
|
+
target,
|
|
1870
|
+
// 0.85: strong file signal (path prefix or known extension),
|
|
1871
|
+
// one degree of inference (the runtime resolves the path).
|
|
1872
|
+
confidence: 0.85,
|
|
1873
|
+
rationale,
|
|
1874
|
+
trigger: {
|
|
1875
|
+
originalTrigger: original,
|
|
1876
|
+
normalizedTrigger: target
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
]
|
|
1880
|
+
});
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
};
|
|
1884
|
+
|
|
1768
1885
|
// plugins/core/extractors/backtick-path/index.ts
|
|
1769
1886
|
import { posix as pathPosix3 } from "path";
|
|
1770
|
-
var
|
|
1887
|
+
var ID5 = "backtick-path";
|
|
1771
1888
|
var PATH_RE = /(?<![\w/:.-])(?:\.{1,2}\/)?[\w][\w.-]*(?:\/[\w.-]+)*\.md\b(?![\w/])/g;
|
|
1772
1889
|
var backtickPathExtractor = {
|
|
1773
|
-
id:
|
|
1890
|
+
id: ID5,
|
|
1774
1891
|
pluginId: CORE_PLUGIN_ID,
|
|
1775
1892
|
kind: "extractor",
|
|
1776
1893
|
description: "Turns relative .md paths written inside code spans and fenced blocks into arrows between nodes in the graph. Example: a backticked `references/rules.md` path draws an arrow to that file.",
|
|
@@ -1795,7 +1912,7 @@ var backtickPathExtractor = {
|
|
|
1795
1912
|
raw: original,
|
|
1796
1913
|
candidates: [
|
|
1797
1914
|
{
|
|
1798
|
-
extractorId:
|
|
1915
|
+
extractorId: ID5,
|
|
1799
1916
|
kind: "points",
|
|
1800
1917
|
target: resolved,
|
|
1801
1918
|
// 0.85: a strong file signal with one degree of inference,
|
|
@@ -1824,7 +1941,7 @@ function resolveTarget(sourceDir, raw) {
|
|
|
1824
1941
|
}
|
|
1825
1942
|
|
|
1826
1943
|
// plugins/core/extractors/external-url-counter/index.ts
|
|
1827
|
-
var
|
|
1944
|
+
var ID6 = "external-url-counter";
|
|
1828
1945
|
var count2 = {
|
|
1829
1946
|
slot: "card.footer.left",
|
|
1830
1947
|
icon: "pi-link",
|
|
@@ -1844,7 +1961,7 @@ var settings = {
|
|
|
1844
1961
|
var URL_RE = /https?:\/\/[^\s<>"'`)\]]+/g;
|
|
1845
1962
|
var TRAILING_PUNCT = /[.,;:!?]+$/;
|
|
1846
1963
|
var externalUrlCounterExtractor = {
|
|
1847
|
-
id:
|
|
1964
|
+
id: ID6,
|
|
1848
1965
|
pluginId: CORE_PLUGIN_ID,
|
|
1849
1966
|
kind: "extractor",
|
|
1850
1967
|
description: "Counts the distinct external URLs in a node's body and shows the count on the card. Example: a body linking `https://example.com` and `https://docs.rs` shows a count of 2.",
|
|
@@ -1896,7 +2013,7 @@ var externalUrlCounterExtractor = {
|
|
|
1896
2013
|
raw: original,
|
|
1897
2014
|
candidates: [
|
|
1898
2015
|
{
|
|
1899
|
-
extractorId:
|
|
2016
|
+
extractorId: ID6,
|
|
1900
2017
|
kind: "references",
|
|
1901
2018
|
target: normalized.href,
|
|
1902
2019
|
confidence: 0.3,
|
|
@@ -1938,11 +2055,11 @@ function normalizeUrl(raw) {
|
|
|
1938
2055
|
|
|
1939
2056
|
// plugins/core/extractors/markdown-link/index.ts
|
|
1940
2057
|
import { posix as pathPosix4 } from "path";
|
|
1941
|
-
var
|
|
2058
|
+
var ID7 = "markdown-link";
|
|
1942
2059
|
var LINK_RE = /(?<!!)\[([^\]]*)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g;
|
|
1943
2060
|
var URL_SCHEME_RE = /^[a-z][a-z0-9+.-]*:/i;
|
|
1944
2061
|
var markdownLinkExtractor = {
|
|
1945
|
-
id:
|
|
2062
|
+
id: ID7,
|
|
1946
2063
|
pluginId: CORE_PLUGIN_ID,
|
|
1947
2064
|
kind: "extractor",
|
|
1948
2065
|
description: "Turns markdown links (`[text](path)`) in a node's body into arrows between nodes in the graph. Example: `[the guide](docs/guide.md)` draws an arrow to `docs/guide.md`.",
|
|
@@ -1967,7 +2084,7 @@ var markdownLinkExtractor = {
|
|
|
1967
2084
|
raw: match[0],
|
|
1968
2085
|
candidates: [
|
|
1969
2086
|
{
|
|
1970
|
-
extractorId:
|
|
2087
|
+
extractorId: ID7,
|
|
1971
2088
|
kind: "references",
|
|
1972
2089
|
target: resolved,
|
|
1973
2090
|
// 0.95: the `[text](path)` syntax is unambiguous (the spec's
|
|
@@ -2002,10 +2119,10 @@ function resolveTarget2(sourceDir, raw) {
|
|
|
2002
2119
|
}
|
|
2003
2120
|
|
|
2004
2121
|
// plugins/core/extractors/mcp-tools/index.ts
|
|
2005
|
-
var
|
|
2122
|
+
var ID8 = "mcp-tools";
|
|
2006
2123
|
var MCP_PATTERN = /^mcp__([a-z0-9][a-z0-9_-]*)__[a-z0-9_-]+$/i;
|
|
2007
2124
|
var mcpToolsExtractor = {
|
|
2008
|
-
id:
|
|
2125
|
+
id: ID8,
|
|
2009
2126
|
pluginId: CORE_PLUGIN_ID,
|
|
2010
2127
|
kind: "extractor",
|
|
2011
2128
|
description: "Turns `tools: [mcp__<server>__<tool>]` entries in a node's frontmatter into an MCP node per unique server and an arrow from the source to each one. Example: `tools: [mcp__github__create_pr]` adds an `mcp://github` node and an arrow to it.",
|
|
@@ -2036,7 +2153,7 @@ var mcpToolsExtractor = {
|
|
|
2036
2153
|
raw: `mcp__${server}__*`,
|
|
2037
2154
|
candidates: [
|
|
2038
2155
|
{
|
|
2039
|
-
extractorId:
|
|
2156
|
+
extractorId: ID8,
|
|
2040
2157
|
kind: "references",
|
|
2041
2158
|
target: mcpPath,
|
|
2042
2159
|
confidence: 0.85,
|
|
@@ -2066,6 +2183,71 @@ function collectMcpServers(tools) {
|
|
|
2066
2183
|
return out;
|
|
2067
2184
|
}
|
|
2068
2185
|
|
|
2186
|
+
// plugins/core/extractors/slash-command/index.ts
|
|
2187
|
+
var ID9 = "slash-command";
|
|
2188
|
+
var SLASH_RE = /(?<![A-Za-z0-9_/.:?#=&])(\/[a-z0-9][a-z0-9_-]*(?::[a-z0-9][a-z0-9_-]*)?)/gi;
|
|
2189
|
+
var slashCommandExtractor = {
|
|
2190
|
+
id: ID9,
|
|
2191
|
+
pluginId: CORE_PLUGIN_ID,
|
|
2192
|
+
kind: "extractor",
|
|
2193
|
+
description: "Turns `/command` invocations in a node's body into arrows that point at the resolved slash command, skill, or workflow, using the `/`-grammar shared by Claude, Antigravity, and OpenCode. Example: `/deploy` in the body draws an arrow to the `deploy` command.",
|
|
2194
|
+
scope: "body",
|
|
2195
|
+
// Also authorised under the antigravity lens, which shares the `/command`
|
|
2196
|
+
// grammar: a workflow / skill / AGENTS.md body's `/name` tokens resolve to
|
|
2197
|
+
// BOTH skills and workflows (`invokes: ['skill', 'workflow']`), since
|
|
2198
|
+
// Antigravity invokes either by the same slash. NOT gated under codex:
|
|
2199
|
+
// OpenAI Codex reserves `/` for its OWN built-in commands (`/model`,
|
|
2200
|
+
// `/init`, ...) and invokes user skills with `$` instead (parsed by the
|
|
2201
|
+
// codex `dollar-skill` extractor). A lens that declares no `invokes`
|
|
2202
|
+
// resolution leaves the signals unresolved (no spurious edges).
|
|
2203
|
+
//
|
|
2204
|
+
// Also authorised under the opencode lens: OpenCode invokes its custom
|
|
2205
|
+
// `.opencode/commands/<name>.md` with `/<name>` (the opencode provider maps
|
|
2206
|
+
// `invokes: ['command']`, since OpenCode loads skills via its native `skill`
|
|
2207
|
+
// tool rather than the slash channel). Additive: claude / antigravity runs
|
|
2208
|
+
// are unchanged.
|
|
2209
|
+
precondition: { provider: ["claude", "antigravity", "opencode"] },
|
|
2210
|
+
extract(ctx) {
|
|
2211
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2212
|
+
const body = stripCodeAndHtml(ctx.body);
|
|
2213
|
+
const lineStarts = computeLineStarts(body);
|
|
2214
|
+
for (const match of body.matchAll(SLASH_RE)) {
|
|
2215
|
+
const original = match[1];
|
|
2216
|
+
const endIdx = (match.index ?? 0) + match[0].length;
|
|
2217
|
+
const nextChar = body[endIdx];
|
|
2218
|
+
if (nextChar && /[A-Za-z0-9_/-]/.test(nextChar)) continue;
|
|
2219
|
+
const normalized = normalizeTrigger(original);
|
|
2220
|
+
if (seen.has(normalized)) continue;
|
|
2221
|
+
seen.add(normalized);
|
|
2222
|
+
const captureOffset = (match.index ?? 0) + match[0].indexOf(original);
|
|
2223
|
+
const line = lineFor(lineStarts, captureOffset);
|
|
2224
|
+
ctx.emitSignal({
|
|
2225
|
+
source: ctx.node.path,
|
|
2226
|
+
scope: "body",
|
|
2227
|
+
range: { start: captureOffset, end: captureOffset + original.length, line },
|
|
2228
|
+
raw: original,
|
|
2229
|
+
candidates: [
|
|
2230
|
+
{
|
|
2231
|
+
extractorId: ID9,
|
|
2232
|
+
kind: "invokes",
|
|
2233
|
+
target: original,
|
|
2234
|
+
// 0.8: clean `/command` match after code-block strip. The
|
|
2235
|
+
// post-match path guard above filters URL / file-path noise,
|
|
2236
|
+
// so a hit is unambiguous syntax. Resolution against the
|
|
2237
|
+
// live skill / command catalog happens downstream.
|
|
2238
|
+
confidence: 0.8,
|
|
2239
|
+
rationale: "unambiguous slash syntax post code-block strip",
|
|
2240
|
+
trigger: {
|
|
2241
|
+
originalTrigger: original,
|
|
2242
|
+
normalizedTrigger: normalized
|
|
2243
|
+
}
|
|
2244
|
+
}
|
|
2245
|
+
]
|
|
2246
|
+
});
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2249
|
+
};
|
|
2250
|
+
|
|
2069
2251
|
// plugins/core/analyzers/annotation-field-unknown/index.ts
|
|
2070
2252
|
import { readFileSync } from "fs";
|
|
2071
2253
|
import { dirname, resolve } from "path";
|
|
@@ -4651,18 +4833,19 @@ var updateCheckHook = {
|
|
|
4651
4833
|
// plugins/built-ins.ts
|
|
4652
4834
|
var claudeProvider2 = { ...claudeProvider, pluginId: "claude", version: VERSION };
|
|
4653
4835
|
var atDirectiveExtractor2 = { ...atDirectiveExtractor, pluginId: "claude", version: VERSION };
|
|
4654
|
-
var slashCommandExtractor2 = { ...slashCommandExtractor, pluginId: "claude", version: VERSION };
|
|
4655
4836
|
var toolsCounterExtractor2 = { ...toolsCounterExtractor, pluginId: "claude", version: VERSION };
|
|
4656
4837
|
var antigravityProvider2 = { ...antigravityProvider, pluginId: "antigravity", version: VERSION };
|
|
4657
4838
|
var codexProvider2 = { ...codexProvider, pluginId: "codex", version: VERSION };
|
|
4658
|
-
var atFileExtractor2 = { ...atFileExtractor, pluginId: "codex", version: VERSION };
|
|
4659
4839
|
var dollarSkillExtractor2 = { ...dollarSkillExtractor, pluginId: "codex", version: VERSION };
|
|
4840
|
+
var opencodeProvider2 = { ...opencodeProvider, pluginId: "opencode", version: VERSION };
|
|
4660
4841
|
var agentSkillsProvider2 = { ...agentSkillsProvider, pluginId: "agent-skills", version: VERSION };
|
|
4661
4842
|
var coreMarkdownProvider2 = { ...coreMarkdownProvider, pluginId: "core", version: VERSION };
|
|
4843
|
+
var atFileExtractor2 = { ...atFileExtractor, pluginId: "core", version: VERSION };
|
|
4662
4844
|
var backtickPathExtractor2 = { ...backtickPathExtractor, pluginId: "core", version: VERSION };
|
|
4663
4845
|
var externalUrlCounterExtractor2 = { ...externalUrlCounterExtractor, pluginId: "core", version: VERSION };
|
|
4664
4846
|
var markdownLinkExtractor2 = { ...markdownLinkExtractor, pluginId: "core", version: VERSION };
|
|
4665
4847
|
var mcpToolsExtractor2 = { ...mcpToolsExtractor, pluginId: "core", version: VERSION };
|
|
4848
|
+
var slashCommandExtractor2 = { ...slashCommandExtractor, pluginId: "core", version: VERSION };
|
|
4666
4849
|
var annotationFieldUnknownAnalyzer2 = { ...annotationFieldUnknownAnalyzer, pluginId: "core", version: VERSION };
|
|
4667
4850
|
var annotationOrphanAnalyzer2 = { ...annotationOrphanAnalyzer, pluginId: "core", version: VERSION };
|
|
4668
4851
|
var annotationStaleAnalyzer2 = { ...annotationStaleAnalyzer, pluginId: "core", version: VERSION };
|
|
@@ -4691,7 +4874,6 @@ var builtInPlugins = [
|
|
|
4691
4874
|
extensions: [
|
|
4692
4875
|
claudeProvider2,
|
|
4693
4876
|
atDirectiveExtractor2,
|
|
4694
|
-
slashCommandExtractor2,
|
|
4695
4877
|
toolsCounterExtractor2
|
|
4696
4878
|
]
|
|
4697
4879
|
},
|
|
@@ -4707,10 +4889,16 @@ var builtInPlugins = [
|
|
|
4707
4889
|
description: "OpenAI Codex CLI platform integration. Classifies TOML sub-agent definitions under `.codex/agents/*.toml`.",
|
|
4708
4890
|
extensions: [
|
|
4709
4891
|
codexProvider2,
|
|
4710
|
-
atFileExtractor2,
|
|
4711
4892
|
dollarSkillExtractor2
|
|
4712
4893
|
]
|
|
4713
4894
|
},
|
|
4895
|
+
{
|
|
4896
|
+
id: "opencode",
|
|
4897
|
+
description: "OpenCode CLI platform integration (open-source, model-agnostic terminal coding agent). Classifies OpenCode agents under `.opencode/agent/*.md` and commands under `.opencode/commands/*.md` (its own kinds), and adopts the skill homes OpenCode reads (`.opencode/skills/`, `.claude/skills/`, `.agents/skills/`); contributes the OpenCode runtime identity and reserved built-in names.",
|
|
4898
|
+
extensions: [
|
|
4899
|
+
opencodeProvider2
|
|
4900
|
+
]
|
|
4901
|
+
},
|
|
4714
4902
|
{
|
|
4715
4903
|
id: "agent-skills",
|
|
4716
4904
|
description: "Open-standard Agent Skills layout. Classifies skills under the vendor-neutral path `.agents/skills/<name>/SKILL.md` (adopted by Anthropic, OpenAI, Google). See agentskills.io.",
|
|
@@ -4723,10 +4911,12 @@ var builtInPlugins = [
|
|
|
4723
4911
|
description: "Core extensions shared across providers: parsers, extractors, analyzers, actions, hooks, formatters, and the universal `.md` fallback provider.",
|
|
4724
4912
|
extensions: [
|
|
4725
4913
|
coreMarkdownProvider2,
|
|
4914
|
+
atFileExtractor2,
|
|
4726
4915
|
backtickPathExtractor2,
|
|
4727
4916
|
externalUrlCounterExtractor2,
|
|
4728
4917
|
markdownLinkExtractor2,
|
|
4729
4918
|
mcpToolsExtractor2,
|
|
4919
|
+
slashCommandExtractor2,
|
|
4730
4920
|
annotationFieldUnknownAnalyzer2,
|
|
4731
4921
|
annotationOrphanAnalyzer2,
|
|
4732
4922
|
annotationStaleAnalyzer2,
|
|
@@ -5447,6 +5637,7 @@ var BUILT_IN_PLUGIN_IDS = /* @__PURE__ */ new Set([
|
|
|
5447
5637
|
"claude",
|
|
5448
5638
|
"antigravity",
|
|
5449
5639
|
"codex",
|
|
5640
|
+
"opencode",
|
|
5450
5641
|
"agent-skills",
|
|
5451
5642
|
"core"
|
|
5452
5643
|
]);
|
|
@@ -16538,6 +16729,8 @@ var ORCHESTRATOR_TEXTS = {
|
|
|
16538
16729
|
frontmatterMalformedPasteWithIndent: "Frontmatter fence in {{path}} appears indented; YAML frontmatter MUST start with `---` at column 0. The file was scanned as body-only; the metadata block was silently lost. Move the `---` lines to the start of the line.",
|
|
16539
16730
|
frontmatterMalformedByteOrderMark: "Frontmatter fence in {{path}} is preceded by a UTF-8 byte-order mark (BOM); the file was scanned as body-only. Re-save the file as UTF-8 without BOM. The metadata block was silently lost.",
|
|
16540
16731
|
frontmatterMalformedMissingClose: "Frontmatter in {{path}} opens with `---` but never closes (no matching `---` line at column 0 was found). The file was scanned as body-only and every metadata field was silently lost. Add a closing `---` line below the metadata block.",
|
|
16732
|
+
bodyBacktickUnclosedFence: "Body of {{path}} has an unclosed fenced code block opened at body line {{line}} (no matching closing ``` or ~~~). The code-strip policy then reads the rest of the file as code, so prose extractors stop emitting edges past it. Close the fence.",
|
|
16733
|
+
bodyBacktickUnclosedInline: "Body of {{path}} has an unclosed inline backtick at body line {{line}} (the backtick run has no equal-length closer). Close the inline span with a matching backtick run, or escape a literal backtick with a backslash.",
|
|
16541
16734
|
extensionErrorLinkKindNotDeclared: 'Extractor "{{extractorId}}" emitted a link of kind "{{linkKind}}" outside its declared `emitsLinkKinds` set [{{declaredKinds}}]. Link dropped.',
|
|
16542
16735
|
extensionErrorIssueInvalidSeverity: `Rule "{{analyzerId}}" emitted an issue with invalid severity {{severity}} (allowed: 'error' | 'warn' | 'info'). Issue dropped.`,
|
|
16543
16736
|
extensionErrorContributionUndeclaredRef: 'Extension "{{extractorId}}" emitted a view contribution on {{nodePath}} whose object is not one declared in its `ui` map (pass the declared const by reference, do not spread or inline it). Contribution dropped.',
|
|
@@ -17223,6 +17416,11 @@ var FRONTMATTER_ISSUE_ANALYZERS = /* @__PURE__ */ new Set([
|
|
|
17223
17416
|
"frontmatter-malformed",
|
|
17224
17417
|
"frontmatter-parse-error"
|
|
17225
17418
|
]);
|
|
17419
|
+
var BACKTICK_ISSUE_ID = "backtick-unbalanced";
|
|
17420
|
+
var CACHED_KERNEL_ISSUE_ANALYZERS = /* @__PURE__ */ new Set([
|
|
17421
|
+
...FRONTMATTER_ISSUE_ANALYZERS,
|
|
17422
|
+
BACKTICK_ISSUE_ID
|
|
17423
|
+
]);
|
|
17226
17424
|
|
|
17227
17425
|
// kernel/orchestrator/cache.ts
|
|
17228
17426
|
function indexPriorSnapshot(prior) {
|
|
@@ -17252,7 +17450,7 @@ function indexPriorLinks(links, byOriginating) {
|
|
|
17252
17450
|
}
|
|
17253
17451
|
function indexPriorFrontmatterIssues(issues, byNode) {
|
|
17254
17452
|
for (const issue of issues) {
|
|
17255
|
-
if (!
|
|
17453
|
+
if (!CACHED_KERNEL_ISSUE_ANALYZERS.has(issue.analyzerId)) continue;
|
|
17256
17454
|
if (issue.nodeIds.length !== 1) continue;
|
|
17257
17455
|
const path = issue.nodeIds[0];
|
|
17258
17456
|
const list = byNode.get(path);
|
|
@@ -17996,6 +18194,21 @@ function malformedMessage(hint, path) {
|
|
|
17996
18194
|
}
|
|
17997
18195
|
}
|
|
17998
18196
|
|
|
18197
|
+
// kernel/orchestrator/body-syntax.ts
|
|
18198
|
+
function detectUnclosedBacktick(body, path, strict) {
|
|
18199
|
+
const imbalance = findBacktickImbalance(body);
|
|
18200
|
+
if (!imbalance) return null;
|
|
18201
|
+
const template = imbalance.kind === "fence" ? ORCHESTRATOR_TEXTS.bodyBacktickUnclosedFence : ORCHESTRATOR_TEXTS.bodyBacktickUnclosedInline;
|
|
18202
|
+
return {
|
|
18203
|
+
analyzerId: BACKTICK_ISSUE_ID,
|
|
18204
|
+
severity: strict ? "error" : "warn",
|
|
18205
|
+
nodeIds: [path],
|
|
18206
|
+
message: tx(template, { path, line: imbalance.line }),
|
|
18207
|
+
detail: imbalance.sourceLine,
|
|
18208
|
+
data: { kind: imbalance.kind, line: imbalance.line }
|
|
18209
|
+
};
|
|
18210
|
+
}
|
|
18211
|
+
|
|
17999
18212
|
// kernel/orchestrator/node-build.ts
|
|
18000
18213
|
function buildNode(args2) {
|
|
18001
18214
|
const bytesFrontmatter = Buffer.byteLength(args2.frontmatterRaw, "utf8");
|
|
@@ -18122,6 +18335,9 @@ function relativePathFromRoots(absolutePath, roots) {
|
|
|
18122
18335
|
}
|
|
18123
18336
|
return absolutePath;
|
|
18124
18337
|
}
|
|
18338
|
+
function pushIssue(list, issue) {
|
|
18339
|
+
if (issue) list.push(issue);
|
|
18340
|
+
}
|
|
18125
18341
|
function buildFreshNodeAndValidateFrontmatter(opts) {
|
|
18126
18342
|
const node = buildNode({
|
|
18127
18343
|
path: opts.raw.path,
|
|
@@ -18149,19 +18365,27 @@ function buildFreshNodeAndValidateFrontmatter(opts) {
|
|
|
18149
18365
|
}
|
|
18150
18366
|
}
|
|
18151
18367
|
if (opts.raw.frontmatterRaw.length > 0) {
|
|
18152
|
-
|
|
18153
|
-
|
|
18154
|
-
|
|
18155
|
-
|
|
18156
|
-
|
|
18157
|
-
|
|
18158
|
-
|
|
18368
|
+
pushIssue(
|
|
18369
|
+
frontmatterIssues,
|
|
18370
|
+
validateFrontmatter(
|
|
18371
|
+
opts.providerFrontmatter,
|
|
18372
|
+
opts.provider,
|
|
18373
|
+
opts.kind,
|
|
18374
|
+
opts.raw.frontmatter,
|
|
18375
|
+
opts.raw.path,
|
|
18376
|
+
opts.strict
|
|
18377
|
+
)
|
|
18159
18378
|
);
|
|
18160
|
-
if (fmIssue) frontmatterIssues.push(fmIssue);
|
|
18161
18379
|
} else {
|
|
18162
|
-
|
|
18163
|
-
|
|
18380
|
+
pushIssue(
|
|
18381
|
+
frontmatterIssues,
|
|
18382
|
+
detectMalformedFrontmatter(opts.raw.body, opts.raw.path, opts.strict)
|
|
18383
|
+
);
|
|
18164
18384
|
}
|
|
18385
|
+
pushIssue(
|
|
18386
|
+
frontmatterIssues,
|
|
18387
|
+
detectUnclosedBacktick(opts.raw.body, opts.raw.path, opts.strict)
|
|
18388
|
+
);
|
|
18165
18389
|
return { node, frontmatterIssues };
|
|
18166
18390
|
}
|
|
18167
18391
|
|
|
@@ -22153,6 +22377,7 @@ var BUILT_IN_PLUGIN_PRESENTATION_ORDER = [
|
|
|
22153
22377
|
"claude",
|
|
22154
22378
|
"antigravity",
|
|
22155
22379
|
"codex",
|
|
22380
|
+
"opencode",
|
|
22156
22381
|
"agent-skills"
|
|
22157
22382
|
];
|
|
22158
22383
|
function sortPluginsForPresentation(plugins) {
|
|
@@ -32575,15 +32800,20 @@ var TUTORIAL_TEXTS = {
|
|
|
32575
32800
|
writtenLabelEs: "Espa\xF1ol",
|
|
32576
32801
|
// Destination-provider prompt (interactive stdin, no `--for`). Header
|
|
32577
32802
|
// uses a yellow `?` glyph; options are a numbered list of the provider's
|
|
32578
|
-
//
|
|
32579
|
-
//
|
|
32580
|
-
// the
|
|
32581
|
-
//
|
|
32582
|
-
// identify the lens. The input line
|
|
32583
|
-
// an empty answer (which takes the
|
|
32803
|
+
// label (for a provider with an `aka`, the standard label leads and the
|
|
32804
|
+
// supporting vendors follow in parentheses, closed by `akaOthers` to mark
|
|
32805
|
+
// the set as open), with a `(default)` marker on the first option (Claude).
|
|
32806
|
+
// The destination folder is deliberately NOT shown: several providers share
|
|
32807
|
+
// `.agents/skills`, so the folder does not identify the lens. The input line
|
|
32808
|
+
// accepts a number, a provider id, or an empty answer (which takes the
|
|
32809
|
+
// default).
|
|
32584
32810
|
promptHeader: "{{glyph}} Which agent should host the tutorial skill?",
|
|
32585
32811
|
promptOption: " {{index}}) {{label}}{{marker}}",
|
|
32586
32812
|
promptDefaultMarker: " (default)",
|
|
32813
|
+
// Trailing token appended to the `aka` vendor list in the open-lens label
|
|
32814
|
+
// ("... (Google's Antigravity, others)"), signalling the open standard is
|
|
32815
|
+
// not tied to a single vendor and more will support it.
|
|
32816
|
+
akaOthers: "others",
|
|
32587
32817
|
promptInput: " Enter the number or provider id [default {{index}}]: ",
|
|
32588
32818
|
// Prompt answer matched neither an index nor an id. Goes to stderr,
|
|
32589
32819
|
// exit code 2. Mirrors the error shape: glyph + headline + dim hint.
|
|
@@ -32833,7 +33063,7 @@ function listScaffoldTargets(includeExperimental = false) {
|
|
|
32833
33063
|
return out;
|
|
32834
33064
|
}
|
|
32835
33065
|
function labelWithAka(target) {
|
|
32836
|
-
return target.aka.length > 0 ? `${target.aka.join(", ")}
|
|
33066
|
+
return target.aka.length > 0 ? `${target.label} (${[...target.aka, TUTORIAL_TEXTS.akaOthers].join(", ")})` : target.label;
|
|
32837
33067
|
}
|
|
32838
33068
|
function renderTargetLines(targets, def, glyph) {
|
|
32839
33069
|
const lines = [tx(TUTORIAL_TEXTS.promptHeader, { glyph })];
|
|
@@ -33128,4 +33358,4 @@ function resolveBareDefault() {
|
|
|
33128
33358
|
process.exit(ExitCode.Error);
|
|
33129
33359
|
}
|
|
33130
33360
|
//# sourceMappingURL=cli.js.map
|
|
33131
|
-
//# debugId=
|
|
33361
|
+
//# debugId=2c7d4927-4422-59d2-a37a-59fed3a2ec80
|