@tanstack/intent 0.0.5 → 0.0.7

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/index.mjs CHANGED
@@ -1,8 +1,249 @@
1
- import { n as parseFrontmatter, t as findSkillFiles } from "./utils-DjkEPBxu.mjs";
2
- import { t as scanForIntents } from "./scanner-CpsJAHXT.mjs";
3
- import { t as checkStaleness } from "./staleness-CnomT9Hm.mjs";
4
- import { c as toMarkdown, i as resolveFrequency, l as validateMetaPayload, n as hasGhCli, o as submitFeedback, r as metaToMarkdown, s as submitMetaFeedback, t as containsSecrets, u as validatePayload } from "./feedback-DKreHfB1.mjs";
5
- import { a as runInit, i as readProjectConfig, n as hasIntentBlock, o as writeProjectConfig, r as injectIntentBlock, t as detectAgentConfigs } from "./init-DNxmjQfU.mjs";
6
- import { t as runSetup } from "./setup-CNGz26qL.mjs";
1
+ import { n as parseFrontmatter, t as findSkillFiles } from "./utils-DH3jY3CI.mjs";
2
+ import { t as scanForIntents } from "./scanner-OmHt14bs.mjs";
3
+ import { t as checkStaleness } from "./staleness-lP6B0O4z.mjs";
4
+ import { t as runSetup } from "./setup-DGvdyKEq.mjs";
5
+ import { readFileSync, writeFileSync } from "node:fs";
6
+ import { join } from "node:path";
7
+ import { execFileSync, execSync } from "node:child_process";
7
8
 
8
- export { checkStaleness, containsSecrets, detectAgentConfigs, findSkillFiles, hasGhCli, hasIntentBlock, injectIntentBlock, metaToMarkdown, parseFrontmatter, readProjectConfig, resolveFrequency, runInit, runSetup, scanForIntents, submitFeedback, submitMetaFeedback, toMarkdown, validateMetaPayload, validatePayload, writeProjectConfig };
9
+ //#region src/feedback.ts
10
+ const META_FEEDBACK_REPO = "TanStack/intent";
11
+ const SECRET_PATTERNS = [
12
+ /(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{36,}/,
13
+ /(?:sk|pk)[-_](?:live|test)[-_][A-Za-z0-9]{24,}/,
14
+ /AKIA[0-9A-Z]{16}/,
15
+ /-----BEGIN (?:RSA |EC )?PRIVATE KEY-----/,
16
+ /eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/,
17
+ /(?:Bearer|token)\s+[A-Za-z0-9_\-.~+/]{20,}/i,
18
+ /[A-Za-z0-9]{32,}(?=.*(?:key|secret|token|password))/i
19
+ ];
20
+ function containsSecrets(text) {
21
+ return SECRET_PATTERNS.some((pattern) => pattern.test(text));
22
+ }
23
+ function hasGhCli() {
24
+ try {
25
+ execSync("gh --version", { stdio: "ignore" });
26
+ return true;
27
+ } catch {
28
+ return false;
29
+ }
30
+ }
31
+ function getHomeConfigDir() {
32
+ return process.env.XDG_CONFIG_HOME ?? join(process.env.HOME ?? process.env.USERPROFILE ?? "", ".config");
33
+ }
34
+ function resolveFrequency(root) {
35
+ const userConfigPath = join(getHomeConfigDir(), "intent", "config.json");
36
+ try {
37
+ const userCfg = JSON.parse(readFileSync(userConfigPath, "utf8"));
38
+ if (userCfg.feedback?.frequency) return userCfg.feedback.frequency;
39
+ } catch {}
40
+ const projectConfigPath = join(root, "intent.config.json");
41
+ try {
42
+ const projCfg = JSON.parse(readFileSync(projectConfigPath, "utf8"));
43
+ if (projCfg.feedback?.frequency) return projCfg.feedback.frequency;
44
+ } catch {}
45
+ return "every-5";
46
+ }
47
+ const REQUIRED_FIELDS = [
48
+ "skill",
49
+ "package",
50
+ "skillVersion",
51
+ "task",
52
+ "whatWorked",
53
+ "whatFailed",
54
+ "missing",
55
+ "selfCorrections",
56
+ "userRating"
57
+ ];
58
+ function validatePayload(payload) {
59
+ const errors = [];
60
+ if (!payload || typeof payload !== "object") return {
61
+ valid: false,
62
+ errors: ["Payload must be a JSON object"]
63
+ };
64
+ const obj = payload;
65
+ for (const field of REQUIRED_FIELDS) if (typeof obj[field] !== "string" || obj[field].trim() === "") errors.push(`Missing or empty required field: ${field}`);
66
+ if (obj.userRating && ![
67
+ "good",
68
+ "mixed",
69
+ "bad"
70
+ ].includes(obj.userRating)) errors.push("userRating must be one of: good, mixed, bad");
71
+ if (containsSecrets(Object.values(obj).filter((v) => typeof v === "string").join("\n"))) errors.push("Payload appears to contain secrets or tokens — submission rejected");
72
+ return {
73
+ valid: errors.length === 0,
74
+ errors
75
+ };
76
+ }
77
+ const META_REQUIRED_FIELDS = [
78
+ "metaSkill",
79
+ "library",
80
+ "agentUsed",
81
+ "artifactQuality",
82
+ "whatWorked",
83
+ "whatFailed",
84
+ "suggestions",
85
+ "userRating"
86
+ ];
87
+ const VALID_META_SKILLS = [
88
+ "domain-discovery",
89
+ "tree-generator",
90
+ "generate-skill",
91
+ "skill-staleness-check"
92
+ ];
93
+ const VALID_AGENTS = [
94
+ "claude-code",
95
+ "cursor",
96
+ "copilot",
97
+ "codex",
98
+ "other"
99
+ ];
100
+ const VALID_QUALITY_RATINGS = [
101
+ "good",
102
+ "mixed",
103
+ "bad"
104
+ ];
105
+ function validateMetaPayload(payload) {
106
+ const errors = [];
107
+ if (!payload || typeof payload !== "object") return {
108
+ valid: false,
109
+ errors: ["Payload must be a JSON object"]
110
+ };
111
+ const obj = payload;
112
+ for (const field of META_REQUIRED_FIELDS) if (typeof obj[field] !== "string" || obj[field].trim() === "") errors.push(`Missing or empty required field: ${field}`);
113
+ if (obj.metaSkill && !VALID_META_SKILLS.includes(obj.metaSkill)) errors.push(`metaSkill must be one of: ${VALID_META_SKILLS.join(", ")}`);
114
+ if (obj.agentUsed && !VALID_AGENTS.includes(obj.agentUsed)) errors.push(`agentUsed must be one of: ${VALID_AGENTS.join(", ")}`);
115
+ if (obj.artifactQuality && !VALID_QUALITY_RATINGS.includes(obj.artifactQuality)) errors.push("artifactQuality must be one of: good, mixed, bad");
116
+ if (obj.userRating && !VALID_QUALITY_RATINGS.includes(obj.userRating)) errors.push("userRating must be one of: good, mixed, bad");
117
+ if (containsSecrets(Object.values(obj).filter((v) => typeof v === "string").join("\n"))) errors.push("Payload appears to contain secrets or tokens — submission rejected");
118
+ return {
119
+ valid: errors.length === 0,
120
+ errors
121
+ };
122
+ }
123
+ function metaToMarkdown(payload) {
124
+ const lines = [
125
+ `# Meta-Skill Feedback: ${payload.metaSkill}`,
126
+ "",
127
+ `**Library:** ${payload.library}`,
128
+ `**Agent:** ${payload.agentUsed}`,
129
+ `**Artifact quality:** ${payload.artifactQuality}`,
130
+ `**Rating:** ${payload.userRating}`
131
+ ];
132
+ if (payload.interviewQuality) lines.push(`**Interview quality:** ${payload.interviewQuality}`);
133
+ if (payload.failureModeQuality) lines.push(`**Failure mode quality:** ${payload.failureModeQuality}`);
134
+ lines.push("", "## What Worked", payload.whatWorked, "", "## What Failed", payload.whatFailed, "", "## Suggestions", payload.suggestions);
135
+ return lines.join("\n") + "\n";
136
+ }
137
+ function toMarkdown(payload) {
138
+ const lines = [
139
+ `# Skill Feedback: ${payload.skill}`,
140
+ "",
141
+ `**Package:** ${payload.package}`,
142
+ `**Skill version:** ${payload.skillVersion}`,
143
+ `**Rating:** ${payload.userRating}`,
144
+ "",
145
+ "## Task",
146
+ payload.task,
147
+ "",
148
+ "## What Worked",
149
+ payload.whatWorked,
150
+ "",
151
+ "## What Failed",
152
+ payload.whatFailed,
153
+ "",
154
+ "## Missing",
155
+ payload.missing,
156
+ "",
157
+ "## Self-Corrections",
158
+ payload.selfCorrections
159
+ ];
160
+ if (payload.userComments) lines.push("", "## User Comments", payload.userComments);
161
+ return lines.join("\n") + "\n";
162
+ }
163
+ function submitFeedback(payload, repo, opts) {
164
+ const md = toMarkdown(payload);
165
+ if (opts.ghAvailable) try {
166
+ execFileSync("gh", [
167
+ "issue",
168
+ "create",
169
+ "--repo",
170
+ repo,
171
+ "--title",
172
+ `Skill Feedback: ${payload.skill} (${payload.userRating})`,
173
+ "--body",
174
+ "-"
175
+ ], {
176
+ input: md,
177
+ stdio: [
178
+ "pipe",
179
+ "pipe",
180
+ "pipe"
181
+ ]
182
+ });
183
+ return {
184
+ method: "gh",
185
+ detail: `Submitted issue to ${repo}`
186
+ };
187
+ } catch (err) {
188
+ const msg = err instanceof Error ? err.message : String(err);
189
+ console.error(`GitHub submission failed: ${msg}`);
190
+ console.error("Falling back to file output.");
191
+ }
192
+ if (opts.outputPath) {
193
+ writeFileSync(opts.outputPath, md, "utf8");
194
+ return {
195
+ method: "file",
196
+ detail: `Saved to ${opts.outputPath}`
197
+ };
198
+ }
199
+ return {
200
+ method: "stdout",
201
+ detail: md
202
+ };
203
+ }
204
+ function submitMetaFeedback(payload, opts) {
205
+ const md = metaToMarkdown(payload);
206
+ if (opts.ghAvailable) try {
207
+ execFileSync("gh", [
208
+ "issue",
209
+ "create",
210
+ "--repo",
211
+ META_FEEDBACK_REPO,
212
+ "--title",
213
+ `Meta-Skill Feedback: ${payload.metaSkill} (${payload.userRating})`,
214
+ "--label",
215
+ `feedback:${payload.metaSkill}`,
216
+ "--body",
217
+ "-"
218
+ ], {
219
+ input: md,
220
+ stdio: [
221
+ "pipe",
222
+ "pipe",
223
+ "pipe"
224
+ ]
225
+ });
226
+ return {
227
+ method: "gh",
228
+ detail: `Submitted issue to ${META_FEEDBACK_REPO}`
229
+ };
230
+ } catch (err) {
231
+ const msg = err instanceof Error ? err.message : String(err);
232
+ console.error(`GitHub submission failed: ${msg}`);
233
+ console.error("Falling back to file output.");
234
+ }
235
+ if (opts.outputPath) {
236
+ writeFileSync(opts.outputPath, md, "utf8");
237
+ return {
238
+ method: "file",
239
+ detail: `Saved to ${opts.outputPath}`
240
+ };
241
+ }
242
+ return {
243
+ method: "stdout",
244
+ detail: md
245
+ };
246
+ }
247
+
248
+ //#endregion
249
+ export { checkStaleness, containsSecrets, findSkillFiles, hasGhCli, metaToMarkdown, parseFrontmatter, resolveFrequency, runSetup, scanForIntents, submitFeedback, submitMetaFeedback, toMarkdown, validateMetaPayload, validatePayload };
@@ -1,57 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import "./utils-DjkEPBxu.mjs";
3
- import { t as scanLibrary } from "./library-scanner-BrznE00j.mjs";
2
+ import "./utils-DH3jY3CI.mjs";
3
+ import { n as printSkillTree, r as printTable, t as computeSkillNameWidth } from "./display-D_XzuGnu.mjs";
4
+ import { t as scanLibrary } from "./library-scanner-V9sTOhrb.mjs";
4
5
 
5
6
  //#region src/intent-library.ts
6
- function padColumn(text, width) {
7
- return text.length >= width ? text + " " : text.padEnd(width);
8
- }
9
- function printTable(headers, rows) {
10
- const widths = headers.map((h, i) => Math.max(h.length, ...rows.map((r) => (r[i] ?? "").length)) + 2);
11
- const headerLine = headers.map((h, i) => padColumn(h, widths[i])).join("");
12
- const separator = widths.map((w) => "─".repeat(w)).join("");
13
- console.log(headerLine);
14
- console.log(separator);
15
- for (const row of rows) console.log(row.map((cell, i) => padColumn(cell, widths[i])).join(""));
16
- }
17
- function printSkillTree(skills, opts) {
18
- const roots = [];
19
- const children = /* @__PURE__ */ new Map();
20
- for (const skill of skills) {
21
- const slashIdx = skill.name.indexOf("/");
22
- if (slashIdx === -1) roots.push(skill.name);
23
- else {
24
- const parent = skill.name.slice(0, slashIdx);
25
- if (!children.has(parent)) children.set(parent, []);
26
- children.get(parent).push(skill);
27
- }
28
- }
29
- if (roots.length === 0) {
30
- for (const skill of skills) if (!roots.includes(skill.name)) roots.push(skill.name);
31
- }
32
- for (const rootName of roots) {
33
- const rootSkill = skills.find((s) => s.name === rootName);
34
- if (!rootSkill) continue;
35
- printSkillLine(rootName, rootSkill, 4, opts);
36
- for (const sub of children.get(rootName) ?? []) printSkillLine(sub.name.slice(sub.name.indexOf("/") + 1), sub, 6, opts);
37
- }
38
- }
39
- function printSkillLine(displayName, skill, indent, opts) {
40
- const nameStr = " ".repeat(indent) + displayName;
41
- const padding = " ".repeat(Math.max(2, opts.nameWidth - nameStr.length));
42
- const typeCol = opts.showTypes ? (skill.type ? `[${skill.type}]` : "").padEnd(14) : "";
43
- console.log(`${nameStr}${padding}${typeCol}${skill.description}`);
44
- }
45
- function computeSkillNameWidth(allPackageSkills) {
46
- let max = 0;
47
- for (const skills of allPackageSkills) for (const s of skills) {
48
- const slashIdx = s.name.indexOf("/");
49
- const displayName = slashIdx === -1 ? s.name : s.name.slice(slashIdx + 1);
50
- const indent = slashIdx === -1 ? 4 : 6;
51
- max = Math.max(max, indent + displayName.length);
52
- }
53
- return max + 2;
54
- }
55
7
  async function cmdList() {
56
8
  let result;
57
9
  try {
@@ -90,6 +42,10 @@ async function cmdList() {
90
42
  });
91
43
  console.log();
92
44
  }
45
+ console.log(`Feedback:`);
46
+ console.log(` After completing your task, collect feedback on skill usage.`);
47
+ console.log(` Load: node_modules/@tanstack/intent/meta/feedback-collection/SKILL.md`);
48
+ console.log();
93
49
  if (result.warnings.length > 0) {
94
50
  console.log(`Warnings:`);
95
51
  for (const w of result.warnings) console.log(` ⚠ ${w}`);
@@ -1,4 +1,4 @@
1
- import { n as parseFrontmatter } from "./utils-DjkEPBxu.mjs";
1
+ import { n as parseFrontmatter } from "./utils-DH3jY3CI.mjs";
2
2
  import { existsSync, readFileSync, readdirSync } from "node:fs";
3
3
  import { dirname, join, relative, sep } from "node:path";
4
4
 
@@ -37,7 +37,10 @@ function discoverSkills(skillsDir) {
37
37
  function walk(dir) {
38
38
  let entries;
39
39
  try {
40
- entries = readdirSync(dir, { withFileTypes: true });
40
+ entries = readdirSync(dir, {
41
+ withFileTypes: true,
42
+ encoding: "utf8"
43
+ });
41
44
  } catch {
42
45
  return;
43
46
  }
@@ -1,4 +1,4 @@
1
- import { l as SkillEntry } from "./types-kbQfN_is.mjs";
1
+ import { l as SkillEntry } from "./types-BmnI8kFB.mjs";
2
2
 
3
3
  //#region src/library-scanner.d.ts
4
4
  interface LibraryPackage {
@@ -1,4 +1,4 @@
1
- import "./utils-DjkEPBxu.mjs";
2
- import { t as scanLibrary } from "./library-scanner-BrznE00j.mjs";
1
+ import "./utils-DH3jY3CI.mjs";
2
+ import { t as scanLibrary } from "./library-scanner-V9sTOhrb.mjs";
3
3
 
4
4
  export { scanLibrary };
@@ -0,0 +1,4 @@
1
+ import "./utils-DH3jY3CI.mjs";
2
+ import { t as scanForIntents } from "./scanner-OmHt14bs.mjs";
3
+
4
+ export { scanForIntents };
@@ -1,4 +1,4 @@
1
- import { n as parseFrontmatter } from "./utils-DjkEPBxu.mjs";
1
+ import { n as parseFrontmatter } from "./utils-DH3jY3CI.mjs";
2
2
  import { existsSync, readFileSync, readdirSync } from "node:fs";
3
3
  import { join, relative, sep } from "node:path";
4
4
 
@@ -12,7 +12,7 @@ function detectPackageManager(root) {
12
12
  if (existsSync(join(root, "package-lock.json"))) return "npm";
13
13
  return "unknown";
14
14
  }
15
- function validateIntentField(pkgName, intent) {
15
+ function validateIntentField(_pkgName, intent) {
16
16
  if (!intent || typeof intent !== "object") return null;
17
17
  const pb = intent;
18
18
  if (pb.version !== 1) return null;
@@ -26,12 +26,39 @@ function validateIntentField(pkgName, intent) {
26
26
  requires
27
27
  };
28
28
  }
29
- function discoverSkills(skillsDir, baseName) {
29
+ /**
30
+ * Derive an IntentConfig from standard package.json fields when no explicit
31
+ * `intent` field is present. A package with a `skills/` directory signals
32
+ * intent support; `repo` and `docs` are derived from `repository` and
33
+ * `homepage`.
34
+ */
35
+ function deriveIntentConfig(pkgJson) {
36
+ let repo = null;
37
+ if (typeof pkgJson.repository === "string") repo = pkgJson.repository;
38
+ else if (pkgJson.repository && typeof pkgJson.repository === "object" && typeof pkgJson.repository.url === "string") {
39
+ repo = pkgJson.repository.url;
40
+ repo = repo.replace(/^git\+/, "").replace(/\.git$/, "").replace(/^https?:\/\/github\.com\//, "");
41
+ }
42
+ const docs = typeof pkgJson.homepage === "string" ? pkgJson.homepage : void 0;
43
+ if (!repo) return null;
44
+ const intentPartial = pkgJson.intent;
45
+ const requires = intentPartial && Array.isArray(intentPartial.requires) ? intentPartial.requires.filter((r) => typeof r === "string") : void 0;
46
+ return {
47
+ version: 1,
48
+ repo,
49
+ docs: docs ?? "",
50
+ requires
51
+ };
52
+ }
53
+ function discoverSkills(skillsDir, _baseName) {
30
54
  const skills = [];
31
55
  function walk(dir) {
32
56
  let entries;
33
57
  try {
34
- entries = readdirSync(dir, { withFileTypes: true });
58
+ entries = readdirSync(dir, {
59
+ withFileTypes: true,
60
+ encoding: "utf8"
61
+ });
35
62
  } catch {
36
63
  return;
37
64
  }
@@ -86,7 +113,10 @@ async function scanForIntents(root) {
86
113
  const packageDirs = [];
87
114
  let topEntries;
88
115
  try {
89
- topEntries = readdirSync(nodeModulesDir, { withFileTypes: true });
116
+ topEntries = readdirSync(nodeModulesDir, {
117
+ withFileTypes: true,
118
+ encoding: "utf8"
119
+ });
90
120
  } catch {
91
121
  return {
92
122
  packageManager,
@@ -100,7 +130,10 @@ async function scanForIntents(root) {
100
130
  if (entry.name.startsWith("@")) {
101
131
  let scopedEntries;
102
132
  try {
103
- scopedEntries = readdirSync(dirPath, { withFileTypes: true });
133
+ scopedEntries = readdirSync(dirPath, {
134
+ withFileTypes: true,
135
+ encoding: "utf8"
136
+ });
104
137
  } catch {
105
138
  continue;
106
139
  }
@@ -123,9 +156,9 @@ async function scanForIntents(root) {
123
156
  }
124
157
  const pkgName = typeof pkgJson.name === "string" ? pkgJson.name : "unknown";
125
158
  const pkgVersion = typeof pkgJson.version === "string" ? pkgJson.version : "0.0.0";
126
- const intent = validateIntentField(pkgName, pkgJson.intent);
159
+ const intent = validateIntentField(pkgName, pkgJson.intent) ?? deriveIntentConfig(pkgJson);
127
160
  if (!intent) {
128
- warnings.push(`${pkgName} has a skills/ directory but missing or invalid "intent" field in package.json`);
161
+ warnings.push(`${pkgName} has a skills/ directory but could not determine repo/docs from package.json (add a "repository" field or explicit "intent" config)`);
129
162
  continue;
130
163
  }
131
164
  const skills = discoverSkills(skillsDir, pkgName);
@@ -1,7 +1,6 @@
1
1
  //#region src/setup.d.ts
2
2
  interface SetupResult {
3
3
  workflows: string[];
4
- oz: string[];
5
4
  skipped: string[];
6
5
  shim: string | null;
7
6
  }
@@ -47,36 +47,50 @@ function copyTemplates(srcDir, destDir, vars) {
47
47
  skipped
48
48
  };
49
49
  }
50
- const SHIM_CONTENT = `#!/usr/bin/env node
50
+ function getShimContent(ext) {
51
+ return `#!/usr/bin/env node
51
52
  // Auto-generated by @tanstack/intent setup
52
53
  // Exposes the intent end-user CLI for consumers of this library.
53
54
  // Commit this file, then add to your package.json:
54
- // "bin": { "intent": "./bin/intent.js" }
55
+ // "bin": { "intent": "./bin/intent.${ext}" }
55
56
  await import('@tanstack/intent/intent-library')
56
57
  `;
58
+ }
59
+ function detectShimExtension(root) {
60
+ try {
61
+ if (JSON.parse(readFileSync(join(root, "package.json"), "utf8")).type === "module") return "js";
62
+ } catch {}
63
+ return "mjs";
64
+ }
65
+ function findExistingShim(root) {
66
+ const shimJs = join(root, "bin", "intent.js");
67
+ if (existsSync(shimJs)) return shimJs;
68
+ const shimMjs = join(root, "bin", "intent.mjs");
69
+ if (existsSync(shimMjs)) return shimMjs;
70
+ return null;
71
+ }
57
72
  function generateShim(root, result) {
58
- const shimPath = join(root, "bin", "intent.js");
59
- if (existsSync(shimPath)) {
60
- result.skipped.push(shimPath);
73
+ const existingShim = findExistingShim(root);
74
+ if (existingShim) {
75
+ result.skipped.push(existingShim);
61
76
  return;
62
77
  }
78
+ const ext = detectShimExtension(root);
79
+ const shimPath = join(root, "bin", `intent.${ext}`);
63
80
  mkdirSync(join(root, "bin"), { recursive: true });
64
- writeFileSync(shimPath, SHIM_CONTENT);
81
+ writeFileSync(shimPath, getShimContent(ext));
65
82
  result.shim = shimPath;
66
83
  }
67
84
  function runSetup(root, metaDir, args) {
68
85
  const doAll = args.includes("--all");
69
86
  const doWorkflows = doAll || args.includes("--workflows");
70
- const doOz = doAll || args.includes("--oz");
71
87
  const doShim = doAll || args.includes("--shim");
72
- const defaultAll = !doWorkflows && !doOz && !doShim;
73
- const installWorkflows = doWorkflows || defaultAll;
74
- const installOz = doOz || defaultAll;
75
- const installShim = doShim || defaultAll;
88
+ const noFlagsGiven = !doWorkflows && !doShim;
89
+ const installWorkflows = doWorkflows || noFlagsGiven;
90
+ const installShim = doShim || noFlagsGiven;
76
91
  const vars = detectVars(root);
77
92
  const result = {
78
93
  workflows: [],
79
- oz: [],
80
94
  skipped: [],
81
95
  shim: null
82
96
  };
@@ -86,23 +100,18 @@ function runSetup(root, metaDir, args) {
86
100
  result.workflows = copied;
87
101
  result.skipped.push(...skipped);
88
102
  }
89
- if (installOz) {
90
- const { copied, skipped } = copyTemplates(join(templatesDir, "oz"), join(root, ".intent", "oz"), vars);
91
- result.oz = copied;
92
- result.skipped.push(...skipped);
93
- }
94
103
  if (installShim) generateShim(root, result);
95
104
  for (const f of result.workflows) console.log(`✓ Copied workflow: ${f}`);
96
- for (const f of result.oz) console.log(`✓ Copied Oz prompt: ${f}`);
97
105
  for (const f of result.skipped) console.log(` Already exists: ${f}`);
98
106
  if (result.shim) {
107
+ const shimRelative = result.shim.replace(root + "/", "./");
99
108
  console.log(`✓ Generated intent shim: ${result.shim}`);
100
109
  console.log(`\n Add to your package.json:`);
101
- console.log(` "bin": { "intent": "./bin/intent.js" }`);
102
- console.log(`\n Add bin/intent.js to your package.json "files" array.`);
110
+ console.log(` "bin": { "intent": "${shimRelative}" }`);
111
+ console.log(`\n Add "bin" to your package.json "files" array.`);
103
112
  }
104
- if (result.workflows.length === 0 && result.oz.length === 0 && result.shim === null && result.skipped.length === 0) console.log("No templates directory found. Is @tanstack/intent installed?");
105
- else if (result.workflows.length > 0 || result.oz.length > 0) {
113
+ if (result.workflows.length === 0 && result.shim === null && result.skipped.length === 0) console.log("No templates directory found. Is @tanstack/intent installed?");
114
+ else if (result.workflows.length > 0) {
106
115
  console.log(`\nTemplate variables applied:`);
107
116
  console.log(` Package: ${vars.PACKAGE_NAME}`);
108
117
  console.log(` Repo: ${vars.REPO}`);
package/dist/setup.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { n as runSetup, t as SetupResult } from "./setup-N5dttGp_.mjs";
1
+ import { n as runSetup, t as SetupResult } from "./setup-BJ4giTKA.mjs";
2
2
  export { SetupResult, runSetup };
package/dist/setup.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { t as runSetup } from "./setup-CNGz26qL.mjs";
1
+ import { t as runSetup } from "./setup-DGvdyKEq.mjs";
2
2
 
3
3
  export { runSetup };
@@ -0,0 +1,4 @@
1
+ import "./utils-DH3jY3CI.mjs";
2
+ import { t as checkStaleness } from "./staleness-lP6B0O4z.mjs";
3
+
4
+ export { checkStaleness };
@@ -1,4 +1,4 @@
1
- import { n as parseFrontmatter, t as findSkillFiles } from "./utils-DjkEPBxu.mjs";
1
+ import { n as parseFrontmatter, t as findSkillFiles } from "./utils-DH3jY3CI.mjs";
2
2
  import { readFileSync } from "node:fs";
3
3
  import { join, relative, sep } from "node:path";
4
4
 
@@ -48,7 +48,7 @@ interface FeedbackPayload {
48
48
  userComments?: string;
49
49
  }
50
50
  type MetaSkillName = 'domain-discovery' | 'tree-generator' | 'generate-skill' | 'skill-staleness-check';
51
- type AgentName = 'oz' | 'claude-code' | 'cursor' | 'copilot' | 'codex' | 'other';
51
+ type AgentName = 'claude-code' | 'cursor' | 'copilot' | 'codex' | 'other';
52
52
  interface MetaFeedbackPayload {
53
53
  metaSkill: MetaSkillName;
54
54
  library: string;
@@ -27,7 +27,7 @@ function parseFrontmatter(filePath) {
27
27
  return null;
28
28
  }
29
29
  const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
30
- if (!match) return null;
30
+ if (!match?.[1]) return null;
31
31
  try {
32
32
  return parse(match[1]);
33
33
  } catch {