@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.
Files changed (171) hide show
  1. package/commands/agent-exec-flags.d.ts +2 -5
  2. package/commands/agent-exec-flags.d.ts.map +1 -1
  3. package/commands/agent-exec-flags.js +6 -13
  4. package/commands/agent-exec-flags.js.map +1 -1
  5. package/commands/connect.js +1 -1
  6. package/commands/connect.js.map +1 -1
  7. package/commands/install.d.ts +3 -0
  8. package/commands/install.d.ts.map +1 -0
  9. package/commands/install.js +68 -0
  10. package/commands/install.js.map +1 -0
  11. package/commands/marketplace.d.ts +3 -0
  12. package/commands/marketplace.d.ts.map +1 -0
  13. package/commands/marketplace.js +94 -0
  14. package/commands/marketplace.js.map +1 -0
  15. package/commands/push.js +2 -7
  16. package/commands/push.js.map +1 -1
  17. package/commands/run.js +0 -3
  18. package/commands/run.js.map +1 -1
  19. package/config/config.d.ts +19 -0
  20. package/config/config.d.ts.map +1 -1
  21. package/config/config.js +15 -0
  22. package/config/config.js.map +1 -1
  23. package/config/index.d.ts +1 -1
  24. package/config/index.d.ts.map +1 -1
  25. package/config/index.js.map +1 -1
  26. package/local/bootstrap.d.ts +21 -0
  27. package/local/bootstrap.d.ts.map +1 -0
  28. package/local/bootstrap.js +88 -0
  29. package/local/bootstrap.js.map +1 -0
  30. package/local/daemon/launch.d.ts +2 -2
  31. package/local/daemon/launch.d.ts.map +1 -1
  32. package/local/daemon/launch.js +4 -34
  33. package/local/daemon/launch.js.map +1 -1
  34. package/local/daemon/process.d.ts +1 -1
  35. package/local/plugins/defaults.d.ts +35 -0
  36. package/local/plugins/defaults.d.ts.map +1 -0
  37. package/local/plugins/defaults.js +83 -0
  38. package/local/plugins/defaults.js.map +1 -0
  39. package/local/seedpack/content.d.ts +2 -1
  40. package/local/seedpack/content.d.ts.map +1 -1
  41. package/local/seedpack/content.js +5 -34
  42. package/local/seedpack/content.js.map +1 -1
  43. package/marketplace/config.d.ts +59 -0
  44. package/marketplace/config.d.ts.map +1 -0
  45. package/marketplace/config.js +162 -0
  46. package/marketplace/config.js.map +1 -0
  47. package/marketplace/github.d.ts +31 -0
  48. package/marketplace/github.d.ts.map +1 -0
  49. package/marketplace/github.js +203 -0
  50. package/marketplace/github.js.map +1 -0
  51. package/marketplace/index.d.ts +8 -0
  52. package/marketplace/index.d.ts.map +1 -0
  53. package/marketplace/index.js +12 -0
  54. package/marketplace/index.js.map +1 -0
  55. package/marketplace/install.d.ts +28 -0
  56. package/marketplace/install.d.ts.map +1 -0
  57. package/marketplace/install.js +109 -0
  58. package/marketplace/install.js.map +1 -0
  59. package/marketplace/materialize.d.ts +19 -0
  60. package/marketplace/materialize.d.ts.map +1 -0
  61. package/marketplace/materialize.js +53 -0
  62. package/marketplace/materialize.js.map +1 -0
  63. package/marketplace/official.d.ts +28 -0
  64. package/marketplace/official.d.ts.map +1 -0
  65. package/marketplace/official.js +86 -0
  66. package/marketplace/official.js.map +1 -0
  67. package/marketplace/read.d.ts +17 -0
  68. package/marketplace/read.d.ts.map +1 -0
  69. package/marketplace/read.js +44 -0
  70. package/marketplace/read.js.map +1 -0
  71. package/marketplace/ref.d.ts +13 -0
  72. package/marketplace/ref.d.ts.map +1 -0
  73. package/marketplace/ref.js +54 -0
  74. package/marketplace/ref.js.map +1 -0
  75. package/marketplace/render.d.ts +22 -0
  76. package/marketplace/render.d.ts.map +1 -0
  77. package/marketplace/render.js +118 -0
  78. package/marketplace/render.js.map +1 -0
  79. package/output/ndjson.js +1 -1
  80. package/output/ndjson.js.map +1 -1
  81. package/package.json +7 -6
  82. package/program.d.ts.map +1 -1
  83. package/program.js +4 -2
  84. package/program.js.map +1 -1
  85. package/resources/ignore/index.d.ts +2 -4
  86. package/resources/ignore/index.d.ts.map +1 -1
  87. package/resources/ignore/index.js +5 -5
  88. package/resources/ignore/index.js.map +1 -1
  89. package/resources/ignore/matcher.d.ts +2 -35
  90. package/resources/ignore/matcher.d.ts.map +1 -1
  91. package/resources/ignore/matcher.js +25 -109
  92. package/resources/ignore/matcher.js.map +1 -1
  93. package/resources/plugin.d.ts +50 -18
  94. package/resources/plugin.d.ts.map +1 -1
  95. package/resources/plugin.js +73 -74
  96. package/resources/plugin.js.map +1 -1
  97. package/resources/run/agent-exec.js +1 -1
  98. package/resources/run/agent-exec.js.map +1 -1
  99. package/resources/run/prepare.d.ts +8 -19
  100. package/resources/run/prepare.d.ts.map +1 -1
  101. package/resources/run/prepare.js +4 -4
  102. package/resources/run/prepare.js.map +1 -1
  103. package/resources/skill.d.ts +2 -2
  104. package/resources/skill.d.ts.map +1 -1
  105. package/resources/skill.js +6 -10
  106. package/resources/skill.js.map +1 -1
  107. package/src/commands/agent-exec-flags.ts +6 -12
  108. package/src/commands/connect.ts +1 -1
  109. package/src/commands/install.test.ts +289 -0
  110. package/src/commands/install.ts +108 -0
  111. package/src/commands/marketplace.test.ts +200 -0
  112. package/src/commands/marketplace.ts +131 -0
  113. package/src/commands/push.ts +5 -10
  114. package/src/commands/run.ts +0 -3
  115. package/src/config/config.ts +37 -0
  116. package/src/config/index.ts +1 -0
  117. package/src/local/bootstrap.test.ts +71 -0
  118. package/src/local/bootstrap.ts +133 -0
  119. package/src/local/daemon/launch.ts +5 -40
  120. package/src/local/daemon/process.ts +1 -1
  121. package/src/local/plugins/defaults.test.ts +238 -0
  122. package/src/local/plugins/defaults.ts +135 -0
  123. package/src/local/seedpack/content.ts +11 -42
  124. package/src/marketplace/__fixtures__/cursor-marketplace.ts +62 -0
  125. package/src/marketplace/config.test.ts +245 -0
  126. package/src/marketplace/config.ts +236 -0
  127. package/src/marketplace/github.test.ts +318 -0
  128. package/src/marketplace/github.ts +296 -0
  129. package/src/marketplace/index.ts +54 -0
  130. package/src/marketplace/install.test.ts +194 -0
  131. package/src/marketplace/install.ts +159 -0
  132. package/src/marketplace/materialize.ts +80 -0
  133. package/src/marketplace/official.test.ts +107 -0
  134. package/src/marketplace/official.ts +125 -0
  135. package/src/marketplace/read.test.ts +94 -0
  136. package/src/marketplace/read.ts +76 -0
  137. package/src/marketplace/ref.test.ts +179 -0
  138. package/src/marketplace/ref.ts +74 -0
  139. package/src/marketplace/render.ts +154 -0
  140. package/src/output/ndjson.ts +1 -1
  141. package/src/program.test.ts +4 -13
  142. package/src/program.ts +4 -2
  143. package/src/resources/ignore/ignore.test.ts +23 -100
  144. package/src/resources/ignore/index.ts +11 -8
  145. package/src/resources/ignore/matcher.ts +33 -136
  146. package/src/resources/plugin.test.ts +35 -6
  147. package/src/resources/plugin.ts +132 -85
  148. package/src/resources/run/agent-exec.ts +1 -1
  149. package/src/resources/run/prepare.test.ts +4 -18
  150. package/src/resources/run/prepare.ts +12 -24
  151. package/src/resources/skill.ts +6 -10
  152. package/commands/draft.d.ts +0 -3
  153. package/commands/draft.d.ts.map +0 -1
  154. package/commands/draft.js +0 -115
  155. package/commands/draft.js.map +0 -1
  156. package/resources/ignore/defaults.d.ts +0 -2
  157. package/resources/ignore/defaults.d.ts.map +0 -1
  158. package/resources/ignore/defaults.js +0 -140
  159. package/resources/ignore/defaults.js.map +0 -1
  160. package/resources/ignore/match.d.ts +0 -3
  161. package/resources/ignore/match.d.ts.map +0 -1
  162. package/resources/ignore/match.js +0 -166
  163. package/resources/ignore/match.js.map +0 -1
  164. package/resources/ignore/pattern.d.ts +0 -13
  165. package/resources/ignore/pattern.d.ts.map +0 -1
  166. package/resources/ignore/pattern.js +0 -118
  167. package/resources/ignore/pattern.js.map +0 -1
  168. package/src/commands/draft.ts +0 -189
  169. package/src/resources/ignore/defaults.ts +0 -155
  170. package/src/resources/ignore/match.ts +0 -158
  171. package/src/resources/ignore/pattern.ts +0 -131
@@ -1,6 +1,6 @@
1
- // Public surface of the gitignore-compatible ignore engine.
2
- export { DEFAULT_PATTERNS } from "./defaults.js";
3
- export { matchName } from "./match.js";
4
- export { createMatcher, Matcher, Reason, REASON_TEXT, SOURCE_CLI, SOURCE_DEFAULTS, SOURCE_GITIGNORE, SOURCE_STIGMERIGNORE, } from "./matcher.js";
5
- export { MatchResult, parsePattern } from "./pattern.js";
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,4DAA4D;AAE5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EACL,aAAa,EAGb,OAAO,EACP,MAAM,EACN,WAAW,EACX,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,WAAW,EAAgB,YAAY,EAAE,MAAM,cAAc,CAAC"}
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 Pattern } from "./pattern.js";
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
- export declare class Matcher {
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":"AAOA,OAAO,EAAe,KAAK,OAAO,EAAgB,MAAM,cAAc,CAAC;AAEvE,eAAO,MAAM,eAAe,aAAa,CAAC;AAC1C,eAAO,MAAM,gBAAgB,eAAe,CAAC;AAC7C,eAAO,MAAM,oBAAoB,mBAAmB,CAAC;AACrD,eAAO,MAAM,UAAU,QAAQ,CAAC;AAEhC,oBAAY,MAAM;IAChB,OAAO,IAAI;IACX,QAAQ,IAAI;IACZ,QAAQ,IAAI;IACZ,WAAW,IAAI;CAChB;AAED,eAAO,MAAM,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAKxD,CAAC;AAEF,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,UAAU,YAAY;IACpB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,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,qBAAa,OAAO;IAClB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;gBAEtC,OAAO,EAAE,SAAS,YAAY,EAAE;IAI5C,+EAA+E;IAC/E,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,WAAW;IA4B1D,6DAA6D;IAC7D,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO;IAI5C,2EAA2E;IAC3E,QAAQ,IAAI,MAAM,EAAE;CAGrB;AAED,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAqB9D"}
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
- // Ignore matcher: composes pattern sources with gitignore precedence (defaults
2
- // → .gitignore → .stigmerignore → CLI flags), evaluating "last match wins".
3
- // A faithful port of the Go CLI's pkg/ignore Matcher.
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 { DEFAULT_PATTERNS } from "./defaults.js";
7
- import { MatchResult, parsePattern } from "./pattern.js";
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 entries = [];
72
- if (options.includeDefaults) {
73
- entries.push(...parseEntries(DEFAULT_PATTERNS, SOURCE_DEFAULTS));
74
- }
75
- if (options.respectGitignore) {
76
- entries.push(...loadIgnoreFile(join(options.rootDir, ".gitignore"), SOURCE_GITIGNORE));
77
- }
78
- entries.push(...loadIgnoreFile(join(options.rootDir, ".stigmerignore"), SOURCE_STIGMERIGNORE));
79
- const extraIgnore = options.extraIgnore ?? [];
80
- const extraInclude = options.extraInclude ?? [];
81
- if (extraIgnore.length > 0 || extraInclude.length > 0) {
82
- entries.push(...loadCliPatterns(extraIgnore, extraInclude));
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 loadIgnoreFile(path, source) {
97
- let text;
32
+ function readIgnoreFile(path) {
98
33
  try {
99
- text = readFileSync(path, "utf8");
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":"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"}
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"}
@@ -1,4 +1,5 @@
1
- import { type PluginDialect, type PluginFiles, type PluginFinding, type PluginPackage } from "@stigmer/plugin-package";
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
- /** Walk `dir` through the ignore matcher into a `PluginFiles`. */
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
- * The archive a push sends: the SAME file list `validate` read, zipped
54
- * deterministically (sorted entries, one DOS-epoch mtime, the skill
55
- * packager's level), so the digest the server records is a pure function
56
- * of the plugin's content and a second push of an unchanged directory is
57
- * the server's no-op.
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 zipPluginFiles(files: PluginFiles): Uint8Array;
60
- export interface PushPluginOptions {
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
- * Read, validate offline (the same refusal `validate` prints, before a byte
73
- * moves), zip, push, then read the members back. The server re-validates
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":"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"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/resources/plugin.ts"],"names":[],"mappings":"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"}
@@ -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 is the skill packager's discipline
6
- // (`createSkillZip`): sorted entries, symlinks never followed, the same
7
- // gitignore-compatible matcher deciding inclusion, so what `validate` reads
8
- // is exactly what a push of the same directory would package. Sizes come
9
- // from `stat` so the library can refuse an over-cap document before reading
10
- // it; the library re-checks the bytes it gets back.
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: the same walked file list, zipped the way the skill
17
- // packager zips (deterministic bytes, so the server's digest is a function
18
- // of content), pushed through the SDK's routed plugin client, and the
19
- // members read back for the install summary. `validate -f`, `push plugin
20
- // --dry-run` and `push plugin` share one description renderer so the
21
- // author reads one vocabulary at every step.
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 { DETERMINISTIC_ZIP_MTIME, formatBytes, shortHash, } from "./skill.js";
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
- /** Walk `dir` through the ignore matcher into a `PluginFiles`. */
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
- const stats = {
71
- filesIncluded: 0,
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 dirents = readdirSync(currentDir, { withFileTypes: true }).sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
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.matchWithReason(relPath, true).ignored) {
84
- stats.dirsSkipped++;
88
+ if (matcher.match(relPath, true)) {
89
+ dirsSkipped++;
85
90
  continue;
86
91
  }
87
- walk(full, relPath);
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
- if (matcher.matchWithReason(relPath, false).ignored) {
94
- stats.filesIgnored++;
95
- continue;
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
- entries,
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
- * The archive a push sends: the SAME file list `validate` read, zipped
198
- * deterministically (sorted entries, one DOS-epoch mtime, the skill
199
- * packager's level), so the digest the server records is a pure function
200
- * of the plugin's content and a second push of an unchanged directory is
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 zipPluginFiles(files) {
204
- const tree = {};
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 = zipPluginFiles(directory.files);
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,