@stigmer/cli 3.15.3-dev.20260916211208 → 3.16.1-dev.20260917224426
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/commands/agent-exec-flags.d.ts +2 -5
- package/commands/agent-exec-flags.d.ts.map +1 -1
- package/commands/agent-exec-flags.js +6 -13
- package/commands/agent-exec-flags.js.map +1 -1
- package/commands/connect.js +1 -1
- package/commands/connect.js.map +1 -1
- package/commands/install.d.ts +3 -0
- package/commands/install.d.ts.map +1 -0
- package/commands/install.js +68 -0
- package/commands/install.js.map +1 -0
- package/commands/marketplace.d.ts +3 -0
- package/commands/marketplace.d.ts.map +1 -0
- package/commands/marketplace.js +94 -0
- package/commands/marketplace.js.map +1 -0
- package/commands/push.js +2 -7
- package/commands/push.js.map +1 -1
- package/commands/run.js +0 -3
- package/commands/run.js.map +1 -1
- package/config/config.d.ts +19 -0
- package/config/config.d.ts.map +1 -1
- package/config/config.js +15 -0
- package/config/config.js.map +1 -1
- package/config/index.d.ts +1 -1
- package/config/index.d.ts.map +1 -1
- package/config/index.js.map +1 -1
- package/local/bootstrap.d.ts +21 -0
- package/local/bootstrap.d.ts.map +1 -0
- package/local/bootstrap.js +88 -0
- package/local/bootstrap.js.map +1 -0
- package/local/daemon/launch.d.ts +2 -2
- package/local/daemon/launch.d.ts.map +1 -1
- package/local/daemon/launch.js +4 -34
- package/local/daemon/launch.js.map +1 -1
- package/local/daemon/process.d.ts +1 -1
- package/local/plugins/defaults.d.ts +35 -0
- package/local/plugins/defaults.d.ts.map +1 -0
- package/local/plugins/defaults.js +83 -0
- package/local/plugins/defaults.js.map +1 -0
- package/local/seedpack/content.d.ts +2 -1
- package/local/seedpack/content.d.ts.map +1 -1
- package/local/seedpack/content.js +5 -34
- package/local/seedpack/content.js.map +1 -1
- package/marketplace/config.d.ts +59 -0
- package/marketplace/config.d.ts.map +1 -0
- package/marketplace/config.js +162 -0
- package/marketplace/config.js.map +1 -0
- package/marketplace/github.d.ts +31 -0
- package/marketplace/github.d.ts.map +1 -0
- package/marketplace/github.js +203 -0
- package/marketplace/github.js.map +1 -0
- package/marketplace/index.d.ts +8 -0
- package/marketplace/index.d.ts.map +1 -0
- package/marketplace/index.js +12 -0
- package/marketplace/index.js.map +1 -0
- package/marketplace/install.d.ts +28 -0
- package/marketplace/install.d.ts.map +1 -0
- package/marketplace/install.js +109 -0
- package/marketplace/install.js.map +1 -0
- package/marketplace/materialize.d.ts +19 -0
- package/marketplace/materialize.d.ts.map +1 -0
- package/marketplace/materialize.js +53 -0
- package/marketplace/materialize.js.map +1 -0
- package/marketplace/official.d.ts +28 -0
- package/marketplace/official.d.ts.map +1 -0
- package/marketplace/official.js +86 -0
- package/marketplace/official.js.map +1 -0
- package/marketplace/read.d.ts +17 -0
- package/marketplace/read.d.ts.map +1 -0
- package/marketplace/read.js +44 -0
- package/marketplace/read.js.map +1 -0
- package/marketplace/ref.d.ts +13 -0
- package/marketplace/ref.d.ts.map +1 -0
- package/marketplace/ref.js +54 -0
- package/marketplace/ref.js.map +1 -0
- package/marketplace/render.d.ts +22 -0
- package/marketplace/render.d.ts.map +1 -0
- package/marketplace/render.js +118 -0
- package/marketplace/render.js.map +1 -0
- package/output/ndjson.js +1 -1
- package/output/ndjson.js.map +1 -1
- package/package.json +7 -6
- package/program.d.ts.map +1 -1
- package/program.js +4 -2
- package/program.js.map +1 -1
- package/resources/ignore/index.d.ts +2 -4
- package/resources/ignore/index.d.ts.map +1 -1
- package/resources/ignore/index.js +5 -5
- package/resources/ignore/index.js.map +1 -1
- package/resources/ignore/matcher.d.ts +2 -35
- package/resources/ignore/matcher.d.ts.map +1 -1
- package/resources/ignore/matcher.js +25 -109
- package/resources/ignore/matcher.js.map +1 -1
- package/resources/plugin.d.ts +50 -18
- package/resources/plugin.d.ts.map +1 -1
- package/resources/plugin.js +73 -74
- package/resources/plugin.js.map +1 -1
- package/resources/run/agent-exec.js +1 -1
- package/resources/run/agent-exec.js.map +1 -1
- package/resources/run/prepare.d.ts +8 -19
- package/resources/run/prepare.d.ts.map +1 -1
- package/resources/run/prepare.js +4 -4
- package/resources/run/prepare.js.map +1 -1
- package/resources/skill.d.ts +2 -2
- package/resources/skill.d.ts.map +1 -1
- package/resources/skill.js +6 -10
- package/resources/skill.js.map +1 -1
- package/src/commands/agent-exec-flags.ts +6 -12
- package/src/commands/connect.ts +1 -1
- package/src/commands/install.test.ts +289 -0
- package/src/commands/install.ts +108 -0
- package/src/commands/marketplace.test.ts +200 -0
- package/src/commands/marketplace.ts +131 -0
- package/src/commands/push.ts +5 -10
- package/src/commands/run.ts +0 -3
- package/src/config/config.ts +37 -0
- package/src/config/index.ts +1 -0
- package/src/local/bootstrap.test.ts +71 -0
- package/src/local/bootstrap.ts +133 -0
- package/src/local/daemon/launch.ts +5 -40
- package/src/local/daemon/process.ts +1 -1
- package/src/local/plugins/defaults.test.ts +238 -0
- package/src/local/plugins/defaults.ts +135 -0
- package/src/local/seedpack/content.ts +11 -42
- package/src/marketplace/__fixtures__/cursor-marketplace.ts +62 -0
- package/src/marketplace/config.test.ts +245 -0
- package/src/marketplace/config.ts +236 -0
- package/src/marketplace/github.test.ts +318 -0
- package/src/marketplace/github.ts +296 -0
- package/src/marketplace/index.ts +54 -0
- package/src/marketplace/install.test.ts +194 -0
- package/src/marketplace/install.ts +159 -0
- package/src/marketplace/materialize.ts +80 -0
- package/src/marketplace/official.test.ts +107 -0
- package/src/marketplace/official.ts +125 -0
- package/src/marketplace/read.test.ts +94 -0
- package/src/marketplace/read.ts +76 -0
- package/src/marketplace/ref.test.ts +179 -0
- package/src/marketplace/ref.ts +74 -0
- package/src/marketplace/render.ts +154 -0
- package/src/output/ndjson.ts +1 -1
- package/src/program.test.ts +4 -13
- package/src/program.ts +4 -2
- package/src/resources/ignore/ignore.test.ts +23 -100
- package/src/resources/ignore/index.ts +11 -8
- package/src/resources/ignore/matcher.ts +33 -136
- package/src/resources/plugin.test.ts +35 -6
- package/src/resources/plugin.ts +132 -85
- package/src/resources/run/agent-exec.ts +1 -1
- package/src/resources/run/prepare.test.ts +4 -18
- package/src/resources/run/prepare.ts +12 -24
- package/src/resources/skill.ts +6 -10
- package/commands/draft.d.ts +0 -3
- package/commands/draft.d.ts.map +0 -1
- package/commands/draft.js +0 -115
- package/commands/draft.js.map +0 -1
- package/resources/ignore/defaults.d.ts +0 -2
- package/resources/ignore/defaults.d.ts.map +0 -1
- package/resources/ignore/defaults.js +0 -140
- package/resources/ignore/defaults.js.map +0 -1
- package/resources/ignore/match.d.ts +0 -3
- package/resources/ignore/match.d.ts.map +0 -1
- package/resources/ignore/match.js +0 -166
- package/resources/ignore/match.js.map +0 -1
- package/resources/ignore/pattern.d.ts +0 -13
- package/resources/ignore/pattern.d.ts.map +0 -1
- package/resources/ignore/pattern.js +0 -118
- package/resources/ignore/pattern.js.map +0 -1
- package/src/commands/draft.ts +0 -189
- package/src/resources/ignore/defaults.ts +0 -155
- package/src/resources/ignore/match.ts +0 -158
- package/src/resources/ignore/pattern.ts +0 -131
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
// Public surface of the
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export {
|
|
5
|
-
export {
|
|
1
|
+
// Public surface of the CLI's ignore edge. The engine is
|
|
2
|
+
// `@stigmer/plugin-package/client`; re-exported here so the CLI's callers keep
|
|
3
|
+
// one import path and the shared engine stays the only implementation.
|
|
4
|
+
export { DEFAULT_PATTERNS, MatchResult, Matcher, REASON_TEXT, Reason, SOURCE_CLI, SOURCE_DEFAULTS, SOURCE_GITIGNORE, SOURCE_STIGMERIGNORE, matchName, parsePattern, } from "@stigmer/plugin-package/client";
|
|
5
|
+
export { createMatcher } from "./matcher.js";
|
|
6
6
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/resources/ignore/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/resources/ignore/index.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,+EAA+E;AAC/E,uEAAuE;AAEvE,OAAO,EACL,gBAAgB,EAEhB,WAAW,EACX,OAAO,EAEP,WAAW,EACX,MAAM,EACN,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,SAAS,EACT,YAAY,GACb,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,aAAa,EAAuB,MAAM,cAAc,CAAC"}
|
|
@@ -1,26 +1,4 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
export declare const SOURCE_DEFAULTS = "defaults";
|
|
3
|
-
export declare const SOURCE_GITIGNORE = ".gitignore";
|
|
4
|
-
export declare const SOURCE_STIGMERIGNORE = ".stigmerignore";
|
|
5
|
-
export declare const SOURCE_CLI = "cli";
|
|
6
|
-
export declare enum Reason {
|
|
7
|
-
NoMatch = 0,
|
|
8
|
-
Excluded = 1,
|
|
9
|
-
Included = 2,
|
|
10
|
-
DefaultDeny = 3
|
|
11
|
-
}
|
|
12
|
-
export declare const REASON_TEXT: Readonly<Record<Reason, string>>;
|
|
13
|
-
export interface MatchReason {
|
|
14
|
-
readonly ignored: boolean;
|
|
15
|
-
readonly reason: Reason;
|
|
16
|
-
readonly source: string;
|
|
17
|
-
readonly pattern: string;
|
|
18
|
-
}
|
|
19
|
-
interface PatternEntry {
|
|
20
|
-
readonly pattern: Pattern;
|
|
21
|
-
readonly source: string;
|
|
22
|
-
readonly raw: string;
|
|
23
|
-
}
|
|
1
|
+
import { type Matcher } from "@stigmer/plugin-package/client";
|
|
24
2
|
export interface MatcherOptions {
|
|
25
3
|
readonly rootDir: string;
|
|
26
4
|
readonly respectGitignore: boolean;
|
|
@@ -28,17 +6,6 @@ export interface MatcherOptions {
|
|
|
28
6
|
readonly extraIgnore?: readonly string[];
|
|
29
7
|
readonly extraInclude?: readonly string[];
|
|
30
8
|
}
|
|
31
|
-
|
|
32
|
-
private readonly entries;
|
|
33
|
-
constructor(entries: readonly PatternEntry[]);
|
|
34
|
-
/** Decide whether a path (relative, forward-slash) is ignored, with reason. */
|
|
35
|
-
matchWithReason(path: string, isDir: boolean): MatchReason;
|
|
36
|
-
/** Whether the path should be excluded from the artifact. */
|
|
37
|
-
match(path: string, isDir: boolean): boolean;
|
|
38
|
-
/** All loaded patterns as "[source] pattern" (for dry-run diagnostics). */
|
|
39
|
-
patterns(): string[];
|
|
40
|
-
}
|
|
41
|
-
/** Build a Matcher for `rootDir`, loading the configured pattern sources. */
|
|
9
|
+
/** Build a Matcher for `rootDir`, loading the configured pattern sources from disk. */
|
|
42
10
|
export declare function createMatcher(options: MatcherOptions): Matcher;
|
|
43
|
-
export {};
|
|
44
11
|
//# sourceMappingURL=matcher.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matcher.d.ts","sourceRoot":"","sources":["../../../src/resources/ignore/matcher.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"matcher.d.ts","sourceRoot":"","sources":["../../../src/resources/ignore/matcher.ts"],"names":[],"mappings":"AAWA,OAAO,EAEL,KAAK,OAAO,EAIb,MAAM,gCAAgC,CAAC;AAExC,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;IACnC,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3C;AAED,uFAAuF;AACvF,wBAAgB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAiB9D"}
|
|
@@ -1,125 +1,41 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
1
|
+
// The CLI's edge for the shared ignore engine: read the ignore files from the
|
|
2
|
+
// directory about to be packaged and build the matcher from their text.
|
|
3
|
+
//
|
|
4
|
+
// The engine itself (patterns, precedence, last-match-wins, the security
|
|
5
|
+
// defaults) lives in `@stigmer/plugin-package/client`, where the console
|
|
6
|
+
// builds the same matcher from a marketplace tree's file list. What is left
|
|
7
|
+
// here is what only a filesystem client needs: which files to read and that
|
|
8
|
+
// an absent or unreadable ignore file is normal and contributes nothing.
|
|
4
9
|
import { readFileSync, statSync } from "node:fs";
|
|
5
10
|
import { join } from "node:path";
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
export const SOURCE_DEFAULTS = "defaults";
|
|
9
|
-
export const SOURCE_GITIGNORE = ".gitignore";
|
|
10
|
-
export const SOURCE_STIGMERIGNORE = ".stigmerignore";
|
|
11
|
-
export const SOURCE_CLI = "cli";
|
|
12
|
-
export var Reason;
|
|
13
|
-
(function (Reason) {
|
|
14
|
-
Reason[Reason["NoMatch"] = 0] = "NoMatch";
|
|
15
|
-
Reason[Reason["Excluded"] = 1] = "Excluded";
|
|
16
|
-
Reason[Reason["Included"] = 2] = "Included";
|
|
17
|
-
Reason[Reason["DefaultDeny"] = 3] = "DefaultDeny";
|
|
18
|
-
})(Reason || (Reason = {}));
|
|
19
|
-
export const REASON_TEXT = {
|
|
20
|
-
[Reason.NoMatch]: "no pattern matched",
|
|
21
|
-
[Reason.Excluded]: "excluded by pattern",
|
|
22
|
-
[Reason.Included]: "included by negation pattern",
|
|
23
|
-
[Reason.DefaultDeny]: "excluded by security default",
|
|
24
|
-
};
|
|
25
|
-
export class Matcher {
|
|
26
|
-
entries;
|
|
27
|
-
constructor(entries) {
|
|
28
|
-
this.entries = entries;
|
|
29
|
-
}
|
|
30
|
-
/** Decide whether a path (relative, forward-slash) is ignored, with reason. */
|
|
31
|
-
matchWithReason(path, isDir) {
|
|
32
|
-
const components = pathToComponents(path);
|
|
33
|
-
if (components.length === 0) {
|
|
34
|
-
return { ignored: false, reason: Reason.NoMatch, source: "", pattern: "" };
|
|
35
|
-
}
|
|
36
|
-
let lastMatch;
|
|
37
|
-
let lastResult = MatchResult.NoMatch;
|
|
38
|
-
for (const entry of this.entries) {
|
|
39
|
-
const result = entry.pattern.match(components, isDir);
|
|
40
|
-
if (result !== MatchResult.NoMatch) {
|
|
41
|
-
lastMatch = entry;
|
|
42
|
-
lastResult = result;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
if (lastMatch === undefined) {
|
|
46
|
-
return { ignored: false, reason: Reason.NoMatch, source: "", pattern: "" };
|
|
47
|
-
}
|
|
48
|
-
if (lastResult === MatchResult.Exclude) {
|
|
49
|
-
const reason = lastMatch.source === SOURCE_DEFAULTS ? Reason.DefaultDeny : Reason.Excluded;
|
|
50
|
-
return { ignored: true, reason, source: lastMatch.source, pattern: lastMatch.raw };
|
|
51
|
-
}
|
|
52
|
-
// Include (negation): explicitly un-ignored.
|
|
53
|
-
return { ignored: false, reason: Reason.Included, source: lastMatch.source, pattern: lastMatch.raw };
|
|
54
|
-
}
|
|
55
|
-
/** Whether the path should be excluded from the artifact. */
|
|
56
|
-
match(path, isDir) {
|
|
57
|
-
return this.matchWithReason(path, isDir).ignored;
|
|
58
|
-
}
|
|
59
|
-
/** All loaded patterns as "[source] pattern" (for dry-run diagnostics). */
|
|
60
|
-
patterns() {
|
|
61
|
-
return this.entries.map((entry) => `[${entry.source}] ${entry.raw}`);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
/** Build a Matcher for `rootDir`, loading the configured pattern sources. */
|
|
11
|
+
import { SOURCE_GITIGNORE, SOURCE_STIGMERIGNORE, buildMatcher, } from "@stigmer/plugin-package/client";
|
|
12
|
+
/** Build a Matcher for `rootDir`, loading the configured pattern sources from disk. */
|
|
65
13
|
export function createMatcher(options) {
|
|
66
14
|
if (options.rootDir === "")
|
|
67
15
|
throw new Error("rootDir is required");
|
|
68
16
|
const stat = statSync(options.rootDir);
|
|
69
17
|
if (!stat.isDirectory())
|
|
70
18
|
throw new Error(`rootDir is not a directory: ${options.rootDir}`);
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
return new Matcher(entries);
|
|
85
|
-
}
|
|
86
|
-
function parseEntries(patterns, source) {
|
|
87
|
-
const entries = [];
|
|
88
|
-
for (const raw of patterns) {
|
|
89
|
-
const trimmed = raw.trim();
|
|
90
|
-
if (trimmed === "" || trimmed.startsWith("#"))
|
|
91
|
-
continue;
|
|
92
|
-
entries.push({ pattern: parsePattern(trimmed, []), source, raw: trimmed });
|
|
93
|
-
}
|
|
94
|
-
return entries;
|
|
19
|
+
const gitignore = options.respectGitignore
|
|
20
|
+
? readIgnoreFile(join(options.rootDir, SOURCE_GITIGNORE))
|
|
21
|
+
: undefined;
|
|
22
|
+
const stigmerignore = readIgnoreFile(join(options.rootDir, SOURCE_STIGMERIGNORE));
|
|
23
|
+
const sources = {
|
|
24
|
+
includeDefaults: options.includeDefaults,
|
|
25
|
+
...(gitignore !== undefined && { gitignore }),
|
|
26
|
+
...(stigmerignore !== undefined && { stigmerignore }),
|
|
27
|
+
...(options.extraIgnore !== undefined && { extraIgnore: options.extraIgnore }),
|
|
28
|
+
...(options.extraInclude !== undefined && { extraInclude: options.extraInclude }),
|
|
29
|
+
};
|
|
30
|
+
return buildMatcher(sources);
|
|
95
31
|
}
|
|
96
|
-
function
|
|
97
|
-
let text;
|
|
32
|
+
function readIgnoreFile(path) {
|
|
98
33
|
try {
|
|
99
|
-
|
|
34
|
+
return readFileSync(path, "utf8");
|
|
100
35
|
}
|
|
101
36
|
catch {
|
|
102
37
|
// Absent or unreadable ignore files are normal — no patterns.
|
|
103
|
-
return
|
|
38
|
+
return undefined;
|
|
104
39
|
}
|
|
105
|
-
return parseEntries(text.split(/\r?\n/), source);
|
|
106
|
-
}
|
|
107
|
-
function loadCliPatterns(ignore, include) {
|
|
108
|
-
const entries = parseEntries(ignore, SOURCE_CLI);
|
|
109
|
-
const negations = [];
|
|
110
|
-
for (const pattern of include) {
|
|
111
|
-
const trimmed = pattern.trim();
|
|
112
|
-
if (trimmed === "")
|
|
113
|
-
continue;
|
|
114
|
-
negations.push(trimmed.startsWith("!") ? trimmed : `!${trimmed}`);
|
|
115
|
-
}
|
|
116
|
-
entries.push(...parseEntries(negations, SOURCE_CLI));
|
|
117
|
-
return entries;
|
|
118
|
-
}
|
|
119
|
-
function pathToComponents(path) {
|
|
120
|
-
const normalized = path.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
121
|
-
if (normalized === "" || normalized === ".")
|
|
122
|
-
return [];
|
|
123
|
-
return normalized.split("/");
|
|
124
40
|
}
|
|
125
41
|
//# sourceMappingURL=matcher.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matcher.js","sourceRoot":"","sources":["../../../src/resources/ignore/matcher.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"matcher.js","sourceRoot":"","sources":["../../../src/resources/ignore/matcher.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,wEAAwE;AACxE,EAAE;AACF,yEAAyE;AACzE,yEAAyE;AACzE,4EAA4E;AAC5E,4EAA4E;AAC5E,yEAAyE;AAEzE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAGL,gBAAgB,EAChB,oBAAoB,EACpB,YAAY,GACb,MAAM,gCAAgC,CAAC;AAUxC,uFAAuF;AACvF,MAAM,UAAU,aAAa,CAAC,OAAuB;IACnD,IAAI,OAAO,CAAC,OAAO,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACnE,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAE3F,MAAM,SAAS,GAAG,OAAO,CAAC,gBAAgB;QACxC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;QACzD,CAAC,CAAC,SAAS,CAAC;IACd,MAAM,aAAa,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC,CAAC;IAClF,MAAM,OAAO,GAAkB;QAC7B,eAAe,EAAE,OAAO,CAAC,eAAe;QACxC,GAAG,CAAC,SAAS,KAAK,SAAS,IAAI,EAAE,SAAS,EAAE,CAAC;QAC7C,GAAG,CAAC,aAAa,KAAK,SAAS,IAAI,EAAE,aAAa,EAAE,CAAC;QACrD,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC;QAC9E,GAAG,CAAC,OAAO,CAAC,YAAY,KAAK,SAAS,IAAI,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC;KAClF,CAAC;IACF,OAAO,YAAY,CAAC,OAAO,CAAC,CAAC;AAC/B,CAAC;AAED,SAAS,cAAc,CAAC,IAAY;IAClC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,8DAA8D;QAC9D,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
|
package/resources/plugin.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type PluginFiles, type PluginFinding, type PluginPackage } from "@stigmer/plugin-package";
|
|
2
|
+
import { DIALECT_LABELS } from "@stigmer/plugin-package/client";
|
|
2
3
|
import { type Plugin } from "@stigmer/protos/ai/stigmer/agentic/plugin/v1/api_pb";
|
|
3
4
|
import { type PluginMember } from "@stigmer/protos/ai/stigmer/agentic/plugin/v1/io_pb";
|
|
4
5
|
import type { ApiResourceVisibility } from "@stigmer/protos/ai/stigmer/commons/apiresource/enum_pb";
|
|
@@ -6,6 +7,7 @@ import type { Stigmer } from "@stigmer/sdk";
|
|
|
6
7
|
import { UsageError } from "../errors/index.js";
|
|
7
8
|
import { CommandResult } from "../output/index.js";
|
|
8
9
|
import { type IgnoreOptions, type ZipStats } from "./skill.js";
|
|
10
|
+
export { DIALECT_LABELS };
|
|
9
11
|
/** The four manifest locations; a directory holding any of them is a plugin. */
|
|
10
12
|
export declare const PLUGIN_MANIFEST_PATHS: readonly string[];
|
|
11
13
|
/** True when `path` is a directory holding one of the four plugin manifests. */
|
|
@@ -17,7 +19,14 @@ export interface PluginDirectory {
|
|
|
17
19
|
}
|
|
18
20
|
/** Validate's ignore posture: the defaults and the directory's own ignore files, no flags. */
|
|
19
21
|
export declare const DEFAULT_IGNORE_OPTIONS: IgnoreOptions;
|
|
20
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* List the files under `dir` and select through the shared rule. The walk
|
|
24
|
+
* prunes a directory the matcher ignores before descending (a
|
|
25
|
+
* `node_modules/` is never stat'ed), and the selection applies the same
|
|
26
|
+
* matcher to what remains, so the CLI and the console agree on every
|
|
27
|
+
* decision and only the CLI pays the filesystem. Symlinks are neither
|
|
28
|
+
* files nor directories to `readdirSync` and are never followed.
|
|
29
|
+
*/
|
|
21
30
|
export declare function readPluginDirectory(dir: string, options?: IgnoreOptions): PluginDirectory;
|
|
22
31
|
/** The `--json` payload: the package with overlay documents as paths, plus the findings. */
|
|
23
32
|
export interface PluginDescription {
|
|
@@ -38,8 +47,6 @@ export interface PluginDescription {
|
|
|
38
47
|
readonly excludedFiles: number;
|
|
39
48
|
}
|
|
40
49
|
export declare function describePlugin(plugin: PluginPackage, warnings: readonly PluginFinding[], stats: ZipStats): PluginDescription;
|
|
41
|
-
/** Human labels for the four dialects, in the vocabulary the docs use. */
|
|
42
|
-
export declare const DIALECT_LABELS: Readonly<Record<PluginDialect, string>>;
|
|
43
50
|
/** The library's refusal as the CLI's one UsageError: every problem, then every warning. */
|
|
44
51
|
export declare function pluginRefusal(dir: string, errors: readonly PluginFinding[], warnings: readonly PluginFinding[]): UsageError;
|
|
45
52
|
/**
|
|
@@ -50,17 +57,41 @@ export declare function pluginRefusal(dir: string, errors: readonly PluginFindin
|
|
|
50
57
|
export declare function describePackageOn(result: CommandResult, plugin: PluginPackage, warnings: readonly PluginFinding[], stats: ZipStats): CommandResult;
|
|
51
58
|
export declare function count(n: number, noun: string): string;
|
|
52
59
|
/**
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
60
|
+
* A plugin directory read, validated and zipped, but not yet pushed. The
|
|
61
|
+
* step between "a folder" and "a push" is its own value because two callers
|
|
62
|
+
* need to look at it first: `push plugin --dry-run` prints it, and `stigmer
|
|
63
|
+
* up` compares `digest` with what the server already holds before deciding
|
|
64
|
+
* whether a push is needed at all.
|
|
65
|
+
*/
|
|
66
|
+
export interface PreparedPluginPush {
|
|
67
|
+
/** The directory that was read, for sentences. */
|
|
68
|
+
readonly dir: string;
|
|
69
|
+
readonly files: PluginFiles;
|
|
70
|
+
readonly stats: ZipStats;
|
|
71
|
+
readonly plugin: PluginPackage;
|
|
72
|
+
readonly warnings: readonly PluginFinding[];
|
|
73
|
+
/** The exact bytes a push sends. */
|
|
74
|
+
readonly archive: Uint8Array;
|
|
75
|
+
/**
|
|
76
|
+
* SHA-256 of `archive`, lowercase hex: the identity the server records as
|
|
77
|
+
* `status.digest` (its digest is over the bytes it receives, and these are
|
|
78
|
+
* those bytes), so a client can know "already installed" without pushing.
|
|
79
|
+
*/
|
|
80
|
+
readonly digest: string;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Read and validate offline (the same refusal `validate` prints, before a
|
|
84
|
+
* byte moves), then zip. The server re-validates with the same library; the
|
|
85
|
+
* offline pass exists so an author never waits on the network to hear a
|
|
86
|
+
* sentence the CLI could say.
|
|
58
87
|
*/
|
|
59
|
-
export declare function
|
|
60
|
-
export interface
|
|
88
|
+
export declare function preparePluginPush(dir: string, ignoreOptions?: IgnoreOptions): Promise<PreparedPluginPush>;
|
|
89
|
+
export interface PushPreparedOptions {
|
|
61
90
|
readonly org: string;
|
|
62
91
|
readonly visibility: ApiResourceVisibility | undefined;
|
|
63
92
|
readonly message: string;
|
|
93
|
+
}
|
|
94
|
+
export interface PushPluginOptions extends PushPreparedOptions {
|
|
64
95
|
readonly ignoreOptions: IgnoreOptions;
|
|
65
96
|
}
|
|
66
97
|
export interface PushPluginOutcome {
|
|
@@ -68,13 +99,14 @@ export interface PushPluginOutcome {
|
|
|
68
99
|
readonly members: readonly PluginMember[];
|
|
69
100
|
readonly archiveBytes: number;
|
|
70
101
|
}
|
|
71
|
-
/**
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
* with the same library; the offline pass exists so an author never waits
|
|
75
|
-
* on the network to hear a sentence the CLI could say.
|
|
76
|
-
*/
|
|
102
|
+
/** Push a prepared archive, then read the members back for the install summary. */
|
|
103
|
+
export declare function pushPrepared(client: Stigmer, prepared: PreparedPluginPush, options: PushPreparedOptions): Promise<PushPluginOutcome>;
|
|
104
|
+
/** `push plugin <dir>` in one call: prepare, then push. */
|
|
77
105
|
export declare function pushPlugin(client: Stigmer, dir: string, options: PushPluginOptions): Promise<PushPluginOutcome>;
|
|
106
|
+
export interface RenderPushOptions {
|
|
107
|
+
/** Where the archive came from when it was not a folder: the marketplace's name and source. */
|
|
108
|
+
readonly installedFrom?: string;
|
|
109
|
+
}
|
|
78
110
|
/** The install as the user reads it: what landed, what was skipped, what to know. */
|
|
79
|
-
export declare function renderPushOutcome(outcome: PushPluginOutcome): CommandResult;
|
|
111
|
+
export declare function renderPushOutcome(outcome: PushPluginOutcome, options?: RenderPushOptions): CommandResult;
|
|
80
112
|
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/resources/plugin.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/resources/plugin.ts"],"names":[],"mappings":"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"}
|
package/resources/plugin.js
CHANGED
|
@@ -2,28 +2,32 @@
|
|
|
2
2
|
// something the CLI can print.
|
|
3
3
|
//
|
|
4
4
|
// `@stigmer/plugin-package` is pure over a `PluginFiles` list; this module is
|
|
5
|
-
// the CLI's edge for it. The walk
|
|
6
|
-
// (
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
5
|
+
// the CLI's edge for it. The walk lists every file under the directory
|
|
6
|
+
// (symlinks never followed, sizes from `stat` so the library can refuse an
|
|
7
|
+
// over-cap document before reading it) and hands the list to the shared
|
|
8
|
+
// selection rule in `@stigmer/plugin-package/client`, which decides
|
|
9
|
+
// inclusion and order the same way for every client: what `validate` reads
|
|
10
|
+
// here is exactly what a push of the same directory packages, and exactly
|
|
11
|
+
// what the console packages from the same tree on a marketplace host.
|
|
11
12
|
//
|
|
12
13
|
// `describePlugin` is the JSON projection for `--json`: the normalised
|
|
13
14
|
// package with overlay documents reduced to their paths (the bytes are the
|
|
14
15
|
// user's own files, and a byte array serialises badly).
|
|
15
16
|
//
|
|
16
|
-
// The push half
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
17
|
+
// The push half is two steps with a value between them: `preparePluginPush`
|
|
18
|
+
// (the same selected file list, archived and digested by the shared module,
|
|
19
|
+
// so the bytes and their SHA-256 are a function of content alone and equal
|
|
20
|
+
// what the console computes for the same tree) and `pushPrepared` (the SDK's
|
|
21
|
+
// routed plugin client, then the members read back for the install summary). The value in between is what `push plugin
|
|
22
|
+
// --dry-run` prints, what `stigmer install` pushes from a marketplace entry,
|
|
23
|
+
// and what `stigmer up` compares with the server's digest before deciding
|
|
24
|
+
// to push. `validate -f`, `push plugin --dry-run` and `push plugin` share one
|
|
25
|
+
// description renderer so the author reads one vocabulary at every step.
|
|
22
26
|
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
23
27
|
import { join } from "node:path";
|
|
24
28
|
import { create, toJson } from "@bufbuild/protobuf";
|
|
25
|
-
import { zipSync } from "fflate";
|
|
26
29
|
import { MANIFEST_LOCATIONS, readPluginPackage, } from "@stigmer/plugin-package";
|
|
30
|
+
import { DIALECT_LABELS, archivePlugin, digestArchive, selectPluginFiles, } from "@stigmer/plugin-package/client";
|
|
27
31
|
import { PluginSchema, } from "@stigmer/protos/ai/stigmer/agentic/plugin/v1/api_pb";
|
|
28
32
|
import { PluginMemberSchema, PushPluginRequestSchema, } from "@stigmer/protos/ai/stigmer/agentic/plugin/v1/io_pb";
|
|
29
33
|
import { PluginDialect as PluginDialectProto } from "@stigmer/protos/ai/stigmer/agentic/plugin/v1/spec_pb";
|
|
@@ -31,7 +35,8 @@ import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/
|
|
|
31
35
|
import { UsageError } from "../errors/index.js";
|
|
32
36
|
import { CommandResult } from "../output/index.js";
|
|
33
37
|
import { createMatcher } from "./ignore/index.js";
|
|
34
|
-
import {
|
|
38
|
+
import { formatBytes, shortHash, } from "./skill.js";
|
|
39
|
+
export { DIALECT_LABELS };
|
|
35
40
|
/** The four manifest locations; a directory holding any of them is a plugin. */
|
|
36
41
|
export const PLUGIN_MANIFEST_PATHS = Object.values(MANIFEST_LOCATIONS);
|
|
37
42
|
/** True when `path` is a directory holding one of the four plugin manifests. */
|
|
@@ -58,7 +63,14 @@ export const DEFAULT_IGNORE_OPTIONS = {
|
|
|
58
63
|
extraIgnore: [],
|
|
59
64
|
extraInclude: [],
|
|
60
65
|
};
|
|
61
|
-
/**
|
|
66
|
+
/**
|
|
67
|
+
* List the files under `dir` and select through the shared rule. The walk
|
|
68
|
+
* prunes a directory the matcher ignores before descending (a
|
|
69
|
+
* `node_modules/` is never stat'ed), and the selection applies the same
|
|
70
|
+
* matcher to what remains, so the CLI and the console agree on every
|
|
71
|
+
* decision and only the CLI pays the filesystem. Symlinks are neither
|
|
72
|
+
* files nor directories to `readdirSync` and are never followed.
|
|
73
|
+
*/
|
|
62
74
|
export function readPluginDirectory(dir, options = DEFAULT_IGNORE_OPTIONS) {
|
|
63
75
|
const matcher = createMatcher({
|
|
64
76
|
rootDir: dir,
|
|
@@ -67,46 +79,37 @@ export function readPluginDirectory(dir, options = DEFAULT_IGNORE_OPTIONS) {
|
|
|
67
79
|
extraIgnore: options.extraIgnore,
|
|
68
80
|
extraInclude: options.extraInclude,
|
|
69
81
|
});
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
filesIgnored: 0,
|
|
73
|
-
dirsSkipped: 0,
|
|
74
|
-
totalSize: 0,
|
|
75
|
-
};
|
|
76
|
-
const entries = [];
|
|
82
|
+
let dirsSkipped = 0;
|
|
83
|
+
const candidates = [];
|
|
77
84
|
const walk = (currentDir, prefix) => {
|
|
78
|
-
const
|
|
79
|
-
for (const dirent of dirents) {
|
|
85
|
+
for (const dirent of readdirSync(currentDir, { withFileTypes: true })) {
|
|
80
86
|
const relPath = prefix === "" ? dirent.name : `${prefix}/${dirent.name}`;
|
|
81
|
-
const full = join(currentDir, dirent.name);
|
|
82
87
|
if (dirent.isDirectory()) {
|
|
83
|
-
if (matcher.
|
|
84
|
-
|
|
88
|
+
if (matcher.match(relPath, true)) {
|
|
89
|
+
dirsSkipped++;
|
|
85
90
|
continue;
|
|
86
91
|
}
|
|
87
|
-
walk(
|
|
92
|
+
walk(join(currentDir, dirent.name), relPath);
|
|
88
93
|
continue;
|
|
89
94
|
}
|
|
90
|
-
// Symlinks are neither files nor directories here and are never followed.
|
|
91
95
|
if (!dirent.isFile())
|
|
92
96
|
continue;
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
const size = statSync(full).size;
|
|
98
|
-
entries.push({ path: relPath, size });
|
|
99
|
-
stats.filesIncluded++;
|
|
100
|
-
stats.totalSize += size;
|
|
97
|
+
candidates.push({
|
|
98
|
+
path: relPath,
|
|
99
|
+
size: statSync(join(currentDir, dirent.name)).size,
|
|
100
|
+
});
|
|
101
101
|
}
|
|
102
102
|
};
|
|
103
103
|
walk(dir, "");
|
|
104
|
+
const read = (path) => new Uint8Array(readFileSync(join(dir, ...path.split("/"))));
|
|
105
|
+
const selection = selectPluginFiles(candidates, read, {
|
|
106
|
+
respectGitignore: options.respectGitignore,
|
|
107
|
+
extraIgnore: options.extraIgnore,
|
|
108
|
+
extraInclude: options.extraInclude,
|
|
109
|
+
});
|
|
104
110
|
return {
|
|
105
|
-
files:
|
|
106
|
-
|
|
107
|
-
read: (path) => new Uint8Array(readFileSync(join(dir, ...path.split("/")))),
|
|
108
|
-
},
|
|
109
|
-
stats,
|
|
111
|
+
files: selection.files,
|
|
112
|
+
stats: { ...selection.stats, dirsSkipped },
|
|
110
113
|
};
|
|
111
114
|
}
|
|
112
115
|
export function describePlugin(plugin, warnings, stats) {
|
|
@@ -131,13 +134,6 @@ export function describePlugin(plugin, warnings, stats) {
|
|
|
131
134
|
};
|
|
132
135
|
}
|
|
133
136
|
// ─── Rendering, shared by `validate -f <dir>` and `push plugin --dry-run` ────
|
|
134
|
-
/** Human labels for the four dialects, in the vocabulary the docs use. */
|
|
135
|
-
export const DIALECT_LABELS = {
|
|
136
|
-
"agent-plugins": "Agent Plugins 1.0",
|
|
137
|
-
claude: "Claude Code plugin",
|
|
138
|
-
cursor: "Cursor plugin",
|
|
139
|
-
codex: "Codex plugin",
|
|
140
|
-
};
|
|
141
137
|
/** The library's refusal as the CLI's one UsageError: every problem, then every warning. */
|
|
142
138
|
export function pluginRefusal(dir, errors, warnings) {
|
|
143
139
|
const lines = [
|
|
@@ -192,37 +188,34 @@ export function count(n, noun) {
|
|
|
192
188
|
function named(items) {
|
|
193
189
|
return items.length === 0 ? "none" : `${items.length}: ${items.join(", ")}`;
|
|
194
190
|
}
|
|
195
|
-
// ─── Push ────────────────────────────────────────────────────────────────
|
|
196
191
|
/**
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
* the server's no-op.
|
|
192
|
+
* Read and validate offline (the same refusal `validate` prints, before a
|
|
193
|
+
* byte moves), then zip. The server re-validates with the same library; the
|
|
194
|
+
* offline pass exists so an author never waits on the network to hear a
|
|
195
|
+
* sentence the CLI could say.
|
|
202
196
|
*/
|
|
203
|
-
export function
|
|
204
|
-
const
|
|
205
|
-
for (const entry of files.entries) {
|
|
206
|
-
tree[entry.path] = files.read(entry.path);
|
|
207
|
-
}
|
|
208
|
-
return zipSync(tree, { level: 6, mtime: DETERMINISTIC_ZIP_MTIME });
|
|
209
|
-
}
|
|
210
|
-
/**
|
|
211
|
-
* Read, validate offline (the same refusal `validate` prints, before a byte
|
|
212
|
-
* moves), zip, push, then read the members back. The server re-validates
|
|
213
|
-
* with the same library; the offline pass exists so an author never waits
|
|
214
|
-
* on the network to hear a sentence the CLI could say.
|
|
215
|
-
*/
|
|
216
|
-
export async function pushPlugin(client, dir, options) {
|
|
217
|
-
const directory = readPluginDirectory(dir, options.ignoreOptions);
|
|
197
|
+
export async function preparePluginPush(dir, ignoreOptions = DEFAULT_IGNORE_OPTIONS) {
|
|
198
|
+
const directory = readPluginDirectory(dir, ignoreOptions);
|
|
218
199
|
const outcome = readPluginPackage(directory.files);
|
|
219
200
|
if (!outcome.ok) {
|
|
220
201
|
throw pluginRefusal(dir, outcome.errors, outcome.warnings);
|
|
221
202
|
}
|
|
222
|
-
const archive =
|
|
203
|
+
const archive = archivePlugin(directory.files);
|
|
204
|
+
return {
|
|
205
|
+
dir,
|
|
206
|
+
files: directory.files,
|
|
207
|
+
stats: directory.stats,
|
|
208
|
+
plugin: outcome.plugin,
|
|
209
|
+
warnings: outcome.warnings,
|
|
210
|
+
archive,
|
|
211
|
+
digest: await digestArchive(archive),
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
/** Push a prepared archive, then read the members back for the install summary. */
|
|
215
|
+
export async function pushPrepared(client, prepared, options) {
|
|
223
216
|
const plugin = await client.plugin.push(create(PushPluginRequestSchema, {
|
|
224
217
|
org: options.org,
|
|
225
|
-
artifact: archive,
|
|
218
|
+
artifact: prepared.archive,
|
|
226
219
|
message: options.message,
|
|
227
220
|
...(options.visibility !== undefined && {
|
|
228
221
|
visibility: options.visibility,
|
|
@@ -230,10 +223,14 @@ export async function pushPlugin(client, dir, options) {
|
|
|
230
223
|
}));
|
|
231
224
|
const members = (await client.plugin.listMembers(plugin.metadata?.id ?? ""))
|
|
232
225
|
.members;
|
|
233
|
-
return { plugin, members, archiveBytes: archive.length };
|
|
226
|
+
return { plugin, members, archiveBytes: prepared.archive.length };
|
|
227
|
+
}
|
|
228
|
+
/** `push plugin <dir>` in one call: prepare, then push. */
|
|
229
|
+
export async function pushPlugin(client, dir, options) {
|
|
230
|
+
return pushPrepared(client, await preparePluginPush(dir, options.ignoreOptions), options);
|
|
234
231
|
}
|
|
235
232
|
/** The install as the user reads it: what landed, what was skipped, what to know. */
|
|
236
|
-
export function renderPushOutcome(outcome) {
|
|
233
|
+
export function renderPushOutcome(outcome, options = {}) {
|
|
237
234
|
const { plugin, members } = outcome;
|
|
238
235
|
const warnings = plugin.status?.warnings ?? [];
|
|
239
236
|
const counts = plugin.status?.materialized;
|
|
@@ -257,6 +254,8 @@ export function renderPushOutcome(outcome) {
|
|
|
257
254
|
about.field("Digest", shortHash(plugin.status?.digest ?? ""));
|
|
258
255
|
about.field("Format", plugin.spec === undefined ? "" : dialectLabel(plugin.spec.dialect));
|
|
259
256
|
about.field("Size", formatBytes(outcome.archiveBytes));
|
|
257
|
+
if (options.installedFrom !== undefined)
|
|
258
|
+
about.field("Marketplace", options.installedFrom);
|
|
260
259
|
const installed = result.addSection("Installed");
|
|
261
260
|
for (const kind of [
|
|
262
261
|
ApiResourceKind.skill,
|