@tanstack/ai-code-mode-skills 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +199 -0
  2. package/dist/esm/code-mode-with-skills.d.ts +58 -0
  3. package/dist/esm/code-mode-with-skills.js +124 -0
  4. package/dist/esm/code-mode-with-skills.js.map +1 -0
  5. package/dist/esm/create-skill-management-tools.d.ts +40 -0
  6. package/dist/esm/create-skill-management-tools.js +198 -0
  7. package/dist/esm/create-skill-management-tools.js.map +1 -0
  8. package/dist/esm/create-skills-system-prompt.d.ts +22 -0
  9. package/dist/esm/create-skills-system-prompt.js +236 -0
  10. package/dist/esm/create-skills-system-prompt.js.map +1 -0
  11. package/dist/esm/generate-skill-types.d.ts +7 -0
  12. package/dist/esm/generate-skill-types.js +87 -0
  13. package/dist/esm/generate-skill-types.js.map +1 -0
  14. package/dist/esm/index.d.ts +13 -0
  15. package/dist/esm/index.js +29 -0
  16. package/dist/esm/index.js.map +1 -0
  17. package/dist/esm/select-relevant-skills.d.ts +29 -0
  18. package/dist/esm/select-relevant-skills.js +79 -0
  19. package/dist/esm/select-relevant-skills.js.map +1 -0
  20. package/dist/esm/skills-to-bindings.d.ts +34 -0
  21. package/dist/esm/skills-to-bindings.js +77 -0
  22. package/dist/esm/skills-to-bindings.js.map +1 -0
  23. package/dist/esm/skills-to-tools.d.ts +74 -0
  24. package/dist/esm/skills-to-tools.js +189 -0
  25. package/dist/esm/skills-to-tools.js.map +1 -0
  26. package/dist/esm/storage/file-storage.d.ts +27 -0
  27. package/dist/esm/storage/file-storage.js +149 -0
  28. package/dist/esm/storage/file-storage.js.map +1 -0
  29. package/dist/esm/storage/index.d.ts +3 -0
  30. package/dist/esm/storage/index.js +7 -0
  31. package/dist/esm/storage/index.js.map +1 -0
  32. package/dist/esm/storage/memory-storage.d.ts +17 -0
  33. package/dist/esm/storage/memory-storage.js +99 -0
  34. package/dist/esm/storage/memory-storage.js.map +1 -0
  35. package/dist/esm/trust-strategies.d.ts +50 -0
  36. package/dist/esm/trust-strategies.js +63 -0
  37. package/dist/esm/trust-strategies.js.map +1 -0
  38. package/dist/esm/types.d.ts +216 -0
  39. package/package.json +82 -0
  40. package/src/code-mode-with-skills.ts +204 -0
  41. package/src/create-skill-management-tools.ts +296 -0
  42. package/src/create-skills-system-prompt.ts +289 -0
  43. package/src/generate-skill-types.ts +162 -0
  44. package/src/index.ts +51 -0
  45. package/src/select-relevant-skills.ts +136 -0
  46. package/src/skills-to-bindings.ts +134 -0
  47. package/src/skills-to-tools.ts +319 -0
  48. package/src/storage/file-storage.ts +243 -0
  49. package/src/storage/index.ts +6 -0
  50. package/src/storage/memory-storage.ts +163 -0
  51. package/src/trust-strategies.ts +142 -0
  52. package/src/types.ts +289 -0
@@ -0,0 +1,99 @@
1
+ import { createDefaultTrustStrategy } from "../trust-strategies.js";
2
+ function createMemorySkillStorage(optionsOrSkills = []) {
3
+ const options = Array.isArray(optionsOrSkills) ? { initialSkills: optionsOrSkills } : optionsOrSkills;
4
+ const { initialSkills = [], trustStrategy = createDefaultTrustStrategy() } = options;
5
+ const skills = /* @__PURE__ */ new Map();
6
+ for (const skill of initialSkills) {
7
+ skills.set(skill.name, skill);
8
+ }
9
+ async function loadIndex() {
10
+ return Array.from(skills.values()).map((skill) => ({
11
+ id: skill.id,
12
+ name: skill.name,
13
+ description: skill.description,
14
+ usageHints: skill.usageHints,
15
+ trustLevel: skill.trustLevel
16
+ }));
17
+ }
18
+ async function loadAll() {
19
+ return Array.from(skills.values());
20
+ }
21
+ async function get(name) {
22
+ return skills.get(name) ?? null;
23
+ }
24
+ async function save(skill) {
25
+ const now = (/* @__PURE__ */ new Date()).toISOString();
26
+ const existing = skills.get(skill.name);
27
+ const fullSkill = {
28
+ ...skill,
29
+ createdAt: existing?.createdAt ?? now,
30
+ updatedAt: now
31
+ };
32
+ skills.set(skill.name, fullSkill);
33
+ return fullSkill;
34
+ }
35
+ async function deleteSkill(name) {
36
+ if (!skills.has(name)) {
37
+ return false;
38
+ }
39
+ skills.delete(name);
40
+ return true;
41
+ }
42
+ async function search(query, options2 = {}) {
43
+ const { limit = 5 } = options2;
44
+ const queryLower = query.toLowerCase();
45
+ const terms = queryLower.split(/\s+/);
46
+ const scored = Array.from(skills.values()).map((skill) => {
47
+ let score = 0;
48
+ const searchText = [skill.name, skill.description, ...skill.usageHints].join(" ").toLowerCase();
49
+ for (const term of terms) {
50
+ if (searchText.includes(term)) {
51
+ score += 1;
52
+ }
53
+ if (skill.name.toLowerCase().includes(term)) {
54
+ score += 2;
55
+ }
56
+ }
57
+ return { skill, score };
58
+ });
59
+ return scored.filter((s) => s.score > 0).sort((a, b) => b.score - a.score).slice(0, limit).map((s) => ({
60
+ id: s.skill.id,
61
+ name: s.skill.name,
62
+ description: s.skill.description,
63
+ usageHints: s.skill.usageHints,
64
+ trustLevel: s.skill.trustLevel
65
+ }));
66
+ }
67
+ async function updateStats(name, success) {
68
+ const skill = skills.get(name);
69
+ if (!skill) return;
70
+ const { executions, successRate } = skill.stats;
71
+ const newExecutions = executions + 1;
72
+ const newSuccessRate = (successRate * executions + (success ? 1 : 0)) / newExecutions;
73
+ const newStats = { executions: newExecutions, successRate: newSuccessRate };
74
+ const newTrustLevel = trustStrategy.calculateTrustLevel(
75
+ skill.trustLevel,
76
+ newStats
77
+ );
78
+ skills.set(name, {
79
+ ...skill,
80
+ stats: newStats,
81
+ trustLevel: newTrustLevel,
82
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
83
+ });
84
+ }
85
+ return {
86
+ loadIndex,
87
+ loadAll,
88
+ get,
89
+ save,
90
+ delete: deleteSkill,
91
+ search,
92
+ updateStats,
93
+ trustStrategy
94
+ };
95
+ }
96
+ export {
97
+ createMemorySkillStorage
98
+ };
99
+ //# sourceMappingURL=memory-storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-storage.js","sources":["../../../src/storage/memory-storage.ts"],"sourcesContent":["import { createDefaultTrustStrategy } from '../trust-strategies'\nimport type {\n Skill,\n SkillIndexEntry,\n SkillSearchOptions,\n SkillStorage,\n} from '../types'\nimport type { TrustStrategy } from '../trust-strategies'\n\nexport interface MemorySkillStorageOptions {\n /**\n * Initial skills to populate the storage with\n */\n initialSkills?: Array<Skill>\n\n /**\n * Trust strategy for determining skill trust levels\n * @default createDefaultTrustStrategy()\n */\n trustStrategy?: TrustStrategy\n}\n\n/**\n * In-memory skill storage for testing and demos\n */\nexport function createMemorySkillStorage(\n optionsOrSkills: MemorySkillStorageOptions | Array<Skill> = [],\n): SkillStorage {\n const options = Array.isArray(optionsOrSkills)\n ? { initialSkills: optionsOrSkills }\n : optionsOrSkills\n\n const { initialSkills = [], trustStrategy = createDefaultTrustStrategy() } =\n options\n\n // Store skills in a Map for O(1) lookup\n const skills = new Map<string, Skill>()\n\n // Initialize with any provided skills\n for (const skill of initialSkills) {\n skills.set(skill.name, skill)\n }\n\n async function loadIndex(): Promise<Array<SkillIndexEntry>> {\n return Array.from(skills.values()).map((skill) => ({\n id: skill.id,\n name: skill.name,\n description: skill.description,\n usageHints: skill.usageHints,\n trustLevel: skill.trustLevel,\n }))\n }\n\n async function loadAll(): Promise<Array<Skill>> {\n return Array.from(skills.values())\n }\n\n async function get(name: string): Promise<Skill | null> {\n return skills.get(name) ?? null\n }\n\n async function save(\n skill: Omit<Skill, 'createdAt' | 'updatedAt'>,\n ): Promise<Skill> {\n const now = new Date().toISOString()\n const existing = skills.get(skill.name)\n\n const fullSkill: Skill = {\n ...skill,\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n }\n\n skills.set(skill.name, fullSkill)\n return fullSkill\n }\n\n async function deleteSkill(name: string): Promise<boolean> {\n if (!skills.has(name)) {\n return false\n }\n skills.delete(name)\n return true\n }\n\n async function search(\n query: string,\n options: SkillSearchOptions = {},\n ): Promise<Array<SkillIndexEntry>> {\n const { limit = 5 } = options\n\n // Simple text matching\n const queryLower = query.toLowerCase()\n const terms = queryLower.split(/\\s+/)\n\n const scored = Array.from(skills.values()).map((skill) => {\n let score = 0\n const searchText = [skill.name, skill.description, ...skill.usageHints]\n .join(' ')\n .toLowerCase()\n\n for (const term of terms) {\n if (searchText.includes(term)) {\n score += 1\n }\n // Boost exact name matches\n if (skill.name.toLowerCase().includes(term)) {\n score += 2\n }\n }\n\n return { skill, score }\n })\n\n return scored\n .filter((s) => s.score > 0)\n .sort((a, b) => b.score - a.score)\n .slice(0, limit)\n .map((s) => ({\n id: s.skill.id,\n name: s.skill.name,\n description: s.skill.description,\n usageHints: s.skill.usageHints,\n trustLevel: s.skill.trustLevel,\n }))\n }\n\n async function updateStats(name: string, success: boolean): Promise<void> {\n const skill = skills.get(name)\n if (!skill) return\n\n const { executions, successRate } = skill.stats\n const newExecutions = executions + 1\n const newSuccessRate =\n (successRate * executions + (success ? 1 : 0)) / newExecutions\n\n const newStats = { executions: newExecutions, successRate: newSuccessRate }\n\n // Use trust strategy to calculate new trust level\n const newTrustLevel = trustStrategy.calculateTrustLevel(\n skill.trustLevel,\n newStats,\n )\n\n skills.set(name, {\n ...skill,\n stats: newStats,\n trustLevel: newTrustLevel,\n updatedAt: new Date().toISOString(),\n })\n }\n\n return {\n loadIndex,\n loadAll,\n get,\n save,\n delete: deleteSkill,\n search,\n updateStats,\n trustStrategy,\n }\n}\n"],"names":["options"],"mappings":";AAyBO,SAAS,yBACd,kBAA4D,IAC9C;AACd,QAAM,UAAU,MAAM,QAAQ,eAAe,IACzC,EAAE,eAAe,oBACjB;AAEJ,QAAM,EAAE,gBAAgB,CAAA,GAAI,gBAAgB,2BAAA,MAC1C;AAGF,QAAM,6BAAa,IAAA;AAGnB,aAAW,SAAS,eAAe;AACjC,WAAO,IAAI,MAAM,MAAM,KAAK;AAAA,EAC9B;AAEA,iBAAe,YAA6C;AAC1D,WAAO,MAAM,KAAK,OAAO,OAAA,CAAQ,EAAE,IAAI,CAAC,WAAW;AAAA,MACjD,IAAI,MAAM;AAAA,MACV,MAAM,MAAM;AAAA,MACZ,aAAa,MAAM;AAAA,MACnB,YAAY,MAAM;AAAA,MAClB,YAAY,MAAM;AAAA,IAAA,EAClB;AAAA,EACJ;AAEA,iBAAe,UAAiC;AAC9C,WAAO,MAAM,KAAK,OAAO,OAAA,CAAQ;AAAA,EACnC;AAEA,iBAAe,IAAI,MAAqC;AACtD,WAAO,OAAO,IAAI,IAAI,KAAK;AAAA,EAC7B;AAEA,iBAAe,KACb,OACgB;AAChB,UAAM,OAAM,oBAAI,KAAA,GAAO,YAAA;AACvB,UAAM,WAAW,OAAO,IAAI,MAAM,IAAI;AAEtC,UAAM,YAAmB;AAAA,MACvB,GAAG;AAAA,MACH,WAAW,UAAU,aAAa;AAAA,MAClC,WAAW;AAAA,IAAA;AAGb,WAAO,IAAI,MAAM,MAAM,SAAS;AAChC,WAAO;AAAA,EACT;AAEA,iBAAe,YAAY,MAAgC;AACzD,QAAI,CAAC,OAAO,IAAI,IAAI,GAAG;AACrB,aAAO;AAAA,IACT;AACA,WAAO,OAAO,IAAI;AAClB,WAAO;AAAA,EACT;AAEA,iBAAe,OACb,OACAA,WAA8B,IACG;AACjC,UAAM,EAAE,QAAQ,EAAA,IAAMA;AAGtB,UAAM,aAAa,MAAM,YAAA;AACzB,UAAM,QAAQ,WAAW,MAAM,KAAK;AAEpC,UAAM,SAAS,MAAM,KAAK,OAAO,QAAQ,EAAE,IAAI,CAAC,UAAU;AACxD,UAAI,QAAQ;AACZ,YAAM,aAAa,CAAC,MAAM,MAAM,MAAM,aAAa,GAAG,MAAM,UAAU,EACnE,KAAK,GAAG,EACR,YAAA;AAEH,iBAAW,QAAQ,OAAO;AACxB,YAAI,WAAW,SAAS,IAAI,GAAG;AAC7B,mBAAS;AAAA,QACX;AAEA,YAAI,MAAM,KAAK,YAAA,EAAc,SAAS,IAAI,GAAG;AAC3C,mBAAS;AAAA,QACX;AAAA,MACF;AAEA,aAAO,EAAE,OAAO,MAAA;AAAA,IAClB,CAAC;AAED,WAAO,OACJ,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,EACzB,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,EAChC,MAAM,GAAG,KAAK,EACd,IAAI,CAAC,OAAO;AAAA,MACX,IAAI,EAAE,MAAM;AAAA,MACZ,MAAM,EAAE,MAAM;AAAA,MACd,aAAa,EAAE,MAAM;AAAA,MACrB,YAAY,EAAE,MAAM;AAAA,MACpB,YAAY,EAAE,MAAM;AAAA,IAAA,EACpB;AAAA,EACN;AAEA,iBAAe,YAAY,MAAc,SAAiC;AACxE,UAAM,QAAQ,OAAO,IAAI,IAAI;AAC7B,QAAI,CAAC,MAAO;AAEZ,UAAM,EAAE,YAAY,YAAA,IAAgB,MAAM;AAC1C,UAAM,gBAAgB,aAAa;AACnC,UAAM,kBACH,cAAc,cAAc,UAAU,IAAI,MAAM;AAEnD,UAAM,WAAW,EAAE,YAAY,eAAe,aAAa,eAAA;AAG3D,UAAM,gBAAgB,cAAc;AAAA,MAClC,MAAM;AAAA,MACN;AAAA,IAAA;AAGF,WAAO,IAAI,MAAM;AAAA,MACf,GAAG;AAAA,MACH,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,YAAW,oBAAI,KAAA,GAAO,YAAA;AAAA,IAAY,CACnC;AAAA,EACH;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;"}
@@ -0,0 +1,50 @@
1
+ import { SkillStats, TrustLevel } from './types.js';
2
+ /**
3
+ * Strategy for determining skill trust levels
4
+ */
5
+ export interface TrustStrategy {
6
+ /**
7
+ * Get the initial trust level for a newly created skill
8
+ */
9
+ getInitialTrustLevel: () => TrustLevel;
10
+ /**
11
+ * Calculate the new trust level based on execution stats
12
+ */
13
+ calculateTrustLevel: (currentLevel: TrustLevel, stats: SkillStats) => TrustLevel;
14
+ }
15
+ /**
16
+ * Default trust strategy - skills must earn trust through successful executions
17
+ *
18
+ * - untrusted: New skill (0 executions)
19
+ * - provisional: 10+ executions with ≥90% success rate
20
+ * - trusted: 100+ executions with ≥95% success rate
21
+ */
22
+ export declare function createDefaultTrustStrategy(): TrustStrategy;
23
+ /**
24
+ * Always trusted strategy - skills are immediately trusted upon creation
25
+ *
26
+ * Use this for development/testing or when you trust the LLM's code generation
27
+ */
28
+ export declare function createAlwaysTrustedStrategy(): TrustStrategy;
29
+ /**
30
+ * Relaxed trust strategy - faster trust promotion for development
31
+ *
32
+ * - untrusted: New skill (0 executions)
33
+ * - provisional: 3+ executions with ≥80% success rate
34
+ * - trusted: 10+ executions with ≥90% success rate
35
+ */
36
+ export declare function createRelaxedTrustStrategy(): TrustStrategy;
37
+ /**
38
+ * Custom trust strategy with configurable thresholds
39
+ */
40
+ export declare function createCustomTrustStrategy(config: {
41
+ initialLevel?: TrustLevel;
42
+ provisionalThreshold?: {
43
+ executions: number;
44
+ successRate: number;
45
+ };
46
+ trustedThreshold?: {
47
+ executions: number;
48
+ successRate: number;
49
+ };
50
+ }): TrustStrategy;
@@ -0,0 +1,63 @@
1
+ function createDefaultTrustStrategy() {
2
+ return {
3
+ getInitialTrustLevel: () => "untrusted",
4
+ calculateTrustLevel: (currentLevel, stats) => {
5
+ const { executions, successRate } = stats;
6
+ if (currentLevel === "untrusted" && executions >= 10 && successRate >= 0.9) {
7
+ return "provisional";
8
+ }
9
+ if (currentLevel === "provisional" && executions >= 100 && successRate >= 0.95) {
10
+ return "trusted";
11
+ }
12
+ return currentLevel;
13
+ }
14
+ };
15
+ }
16
+ function createAlwaysTrustedStrategy() {
17
+ return {
18
+ getInitialTrustLevel: () => "trusted",
19
+ calculateTrustLevel: () => "trusted"
20
+ };
21
+ }
22
+ function createRelaxedTrustStrategy() {
23
+ return {
24
+ getInitialTrustLevel: () => "untrusted",
25
+ calculateTrustLevel: (currentLevel, stats) => {
26
+ const { executions, successRate } = stats;
27
+ if (currentLevel === "untrusted" && executions >= 3 && successRate >= 0.8) {
28
+ return "provisional";
29
+ }
30
+ if (currentLevel === "provisional" && executions >= 10 && successRate >= 0.9) {
31
+ return "trusted";
32
+ }
33
+ return currentLevel;
34
+ }
35
+ };
36
+ }
37
+ function createCustomTrustStrategy(config) {
38
+ const {
39
+ initialLevel = "untrusted",
40
+ provisionalThreshold = { executions: 10, successRate: 0.9 },
41
+ trustedThreshold = { executions: 100, successRate: 0.95 }
42
+ } = config;
43
+ return {
44
+ getInitialTrustLevel: () => initialLevel,
45
+ calculateTrustLevel: (currentLevel, stats) => {
46
+ const { executions, successRate } = stats;
47
+ if (currentLevel === "untrusted" && executions >= provisionalThreshold.executions && successRate >= provisionalThreshold.successRate) {
48
+ return "provisional";
49
+ }
50
+ if (currentLevel === "provisional" && executions >= trustedThreshold.executions && successRate >= trustedThreshold.successRate) {
51
+ return "trusted";
52
+ }
53
+ return currentLevel;
54
+ }
55
+ };
56
+ }
57
+ export {
58
+ createAlwaysTrustedStrategy,
59
+ createCustomTrustStrategy,
60
+ createDefaultTrustStrategy,
61
+ createRelaxedTrustStrategy
62
+ };
63
+ //# sourceMappingURL=trust-strategies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trust-strategies.js","sources":["../../src/trust-strategies.ts"],"sourcesContent":["import type { SkillStats, TrustLevel } from './types'\n\n/**\n * Strategy for determining skill trust levels\n */\nexport interface TrustStrategy {\n /**\n * Get the initial trust level for a newly created skill\n */\n getInitialTrustLevel: () => TrustLevel\n\n /**\n * Calculate the new trust level based on execution stats\n */\n calculateTrustLevel: (\n currentLevel: TrustLevel,\n stats: SkillStats,\n ) => TrustLevel\n}\n\n/**\n * Default trust strategy - skills must earn trust through successful executions\n *\n * - untrusted: New skill (0 executions)\n * - provisional: 10+ executions with ≥90% success rate\n * - trusted: 100+ executions with ≥95% success rate\n */\nexport function createDefaultTrustStrategy(): TrustStrategy {\n return {\n getInitialTrustLevel: () => 'untrusted',\n\n calculateTrustLevel: (currentLevel, stats) => {\n const { executions, successRate } = stats\n\n if (\n currentLevel === 'untrusted' &&\n executions >= 10 &&\n successRate >= 0.9\n ) {\n return 'provisional'\n }\n\n if (\n currentLevel === 'provisional' &&\n executions >= 100 &&\n successRate >= 0.95\n ) {\n return 'trusted'\n }\n\n return currentLevel\n },\n }\n}\n\n/**\n * Always trusted strategy - skills are immediately trusted upon creation\n *\n * Use this for development/testing or when you trust the LLM's code generation\n */\nexport function createAlwaysTrustedStrategy(): TrustStrategy {\n return {\n getInitialTrustLevel: () => 'trusted',\n calculateTrustLevel: () => 'trusted',\n }\n}\n\n/**\n * Relaxed trust strategy - faster trust promotion for development\n *\n * - untrusted: New skill (0 executions)\n * - provisional: 3+ executions with ≥80% success rate\n * - trusted: 10+ executions with ≥90% success rate\n */\nexport function createRelaxedTrustStrategy(): TrustStrategy {\n return {\n getInitialTrustLevel: () => 'untrusted',\n\n calculateTrustLevel: (currentLevel, stats) => {\n const { executions, successRate } = stats\n\n if (\n currentLevel === 'untrusted' &&\n executions >= 3 &&\n successRate >= 0.8\n ) {\n return 'provisional'\n }\n\n if (\n currentLevel === 'provisional' &&\n executions >= 10 &&\n successRate >= 0.9\n ) {\n return 'trusted'\n }\n\n return currentLevel\n },\n }\n}\n\n/**\n * Custom trust strategy with configurable thresholds\n */\nexport function createCustomTrustStrategy(config: {\n initialLevel?: TrustLevel\n provisionalThreshold?: { executions: number; successRate: number }\n trustedThreshold?: { executions: number; successRate: number }\n}): TrustStrategy {\n const {\n initialLevel = 'untrusted',\n provisionalThreshold = { executions: 10, successRate: 0.9 },\n trustedThreshold = { executions: 100, successRate: 0.95 },\n } = config\n\n return {\n getInitialTrustLevel: () => initialLevel,\n\n calculateTrustLevel: (currentLevel, stats) => {\n const { executions, successRate } = stats\n\n if (\n currentLevel === 'untrusted' &&\n executions >= provisionalThreshold.executions &&\n successRate >= provisionalThreshold.successRate\n ) {\n return 'provisional'\n }\n\n if (\n currentLevel === 'provisional' &&\n executions >= trustedThreshold.executions &&\n successRate >= trustedThreshold.successRate\n ) {\n return 'trusted'\n }\n\n return currentLevel\n },\n }\n}\n"],"names":[],"mappings":"AA2BO,SAAS,6BAA4C;AAC1D,SAAO;AAAA,IACL,sBAAsB,MAAM;AAAA,IAE5B,qBAAqB,CAAC,cAAc,UAAU;AAC5C,YAAM,EAAE,YAAY,YAAA,IAAgB;AAEpC,UACE,iBAAiB,eACjB,cAAc,MACd,eAAe,KACf;AACA,eAAO;AAAA,MACT;AAEA,UACE,iBAAiB,iBACjB,cAAc,OACd,eAAe,MACf;AACA,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,IACT;AAAA,EAAA;AAEJ;AAOO,SAAS,8BAA6C;AAC3D,SAAO;AAAA,IACL,sBAAsB,MAAM;AAAA,IAC5B,qBAAqB,MAAM;AAAA,EAAA;AAE/B;AASO,SAAS,6BAA4C;AAC1D,SAAO;AAAA,IACL,sBAAsB,MAAM;AAAA,IAE5B,qBAAqB,CAAC,cAAc,UAAU;AAC5C,YAAM,EAAE,YAAY,YAAA,IAAgB;AAEpC,UACE,iBAAiB,eACjB,cAAc,KACd,eAAe,KACf;AACA,eAAO;AAAA,MACT;AAEA,UACE,iBAAiB,iBACjB,cAAc,MACd,eAAe,KACf;AACA,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,IACT;AAAA,EAAA;AAEJ;AAKO,SAAS,0BAA0B,QAIxB;AAChB,QAAM;AAAA,IACJ,eAAe;AAAA,IACf,uBAAuB,EAAE,YAAY,IAAI,aAAa,IAAA;AAAA,IACtD,mBAAmB,EAAE,YAAY,KAAK,aAAa,KAAA;AAAA,EAAK,IACtD;AAEJ,SAAO;AAAA,IACL,sBAAsB,MAAM;AAAA,IAE5B,qBAAqB,CAAC,cAAc,UAAU;AAC5C,YAAM,EAAE,YAAY,YAAA,IAAgB;AAEpC,UACE,iBAAiB,eACjB,cAAc,qBAAqB,cACnC,eAAe,qBAAqB,aACpC;AACA,eAAO;AAAA,MACT;AAEA,UACE,iBAAiB,iBACjB,cAAc,iBAAiB,cAC/B,eAAe,iBAAiB,aAChC;AACA,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,IACT;AAAA,EAAA;AAEJ;"}
@@ -0,0 +1,216 @@
1
+ import { AnyTextAdapter, ModelMessage, ToolRegistry } from '@tanstack/ai';
2
+ import { CodeModeToolConfig } from '@tanstack/ai-code-mode';
3
+ import { TrustStrategy } from './trust-strategies.js';
4
+ /**
5
+ * Trust level for a skill
6
+ * - untrusted: Newly created, not yet proven
7
+ * - provisional: Has been successfully executed 10+ times with 90%+ success
8
+ * - trusted: Has been successfully executed 100+ times with 95%+ success
9
+ */
10
+ export type TrustLevel = 'untrusted' | 'provisional' | 'trusted';
11
+ /**
12
+ * Execution statistics for a skill
13
+ */
14
+ export interface SkillStats {
15
+ /**
16
+ * Total number of times this skill has been executed
17
+ */
18
+ executions: number;
19
+ /**
20
+ * Success rate (0-1) based on execution history
21
+ */
22
+ successRate: number;
23
+ }
24
+ /**
25
+ * A reusable skill that can be executed in the Code Mode sandbox
26
+ */
27
+ export interface Skill {
28
+ /**
29
+ * Unique identifier for the skill
30
+ */
31
+ id: string;
32
+ /**
33
+ * Unique name in snake_case (e.g., 'fetch_github_stats')
34
+ * This becomes the function name with skill_ prefix in the sandbox
35
+ */
36
+ name: string;
37
+ /**
38
+ * Human-readable description of what the skill does
39
+ */
40
+ description: string;
41
+ /**
42
+ * TypeScript code that implements the skill
43
+ * The code receives `input` as a variable and can call:
44
+ * - external_* functions (tools)
45
+ * - other skill_* functions (skills)
46
+ * Should return a value
47
+ */
48
+ code: string;
49
+ /**
50
+ * JSON Schema describing the input parameter
51
+ */
52
+ inputSchema: Record<string, unknown>;
53
+ /**
54
+ * JSON Schema describing the return value
55
+ */
56
+ outputSchema: Record<string, unknown>;
57
+ /**
58
+ * Hints about when to use this skill
59
+ * e.g., "Use when comparing NPM package popularity"
60
+ */
61
+ usageHints: Array<string>;
62
+ /**
63
+ * Names of other skills this skill depends on/calls
64
+ */
65
+ dependsOn: Array<string>;
66
+ /**
67
+ * Trust level based on execution history
68
+ */
69
+ trustLevel: TrustLevel;
70
+ /**
71
+ * Execution statistics
72
+ */
73
+ stats: SkillStats;
74
+ /**
75
+ * ISO timestamp when the skill was created
76
+ */
77
+ createdAt: string;
78
+ /**
79
+ * ISO timestamp when the skill was last updated
80
+ */
81
+ updatedAt: string;
82
+ }
83
+ /**
84
+ * Lightweight skill entry for the index (metadata only, no code)
85
+ * Used for fast loading and skill selection
86
+ */
87
+ export type SkillIndexEntry = Pick<Skill, 'id' | 'name' | 'description' | 'usageHints' | 'trustLevel'>;
88
+ /**
89
+ * Options for searching skills
90
+ */
91
+ export interface SkillSearchOptions {
92
+ /**
93
+ * Maximum number of results to return
94
+ * @default 5
95
+ */
96
+ limit?: number;
97
+ }
98
+ /**
99
+ * Interface for skill storage implementations
100
+ */
101
+ export interface SkillStorage {
102
+ /**
103
+ * Load the skill index (lightweight metadata for all skills)
104
+ */
105
+ loadIndex: () => Promise<Array<SkillIndexEntry>>;
106
+ /**
107
+ * Load all skills with full details (including code)
108
+ */
109
+ loadAll: () => Promise<Array<Skill>>;
110
+ /**
111
+ * Get a skill by name
112
+ */
113
+ get: (name: string) => Promise<Skill | null>;
114
+ /**
115
+ * Save a skill (create or update)
116
+ */
117
+ save: (skill: Omit<Skill, 'createdAt' | 'updatedAt'>) => Promise<Skill>;
118
+ /**
119
+ * Delete a skill by name
120
+ */
121
+ delete: (name: string) => Promise<boolean>;
122
+ /**
123
+ * Search for skills by query
124
+ */
125
+ search: (query: string, options?: SkillSearchOptions) => Promise<Array<SkillIndexEntry>>;
126
+ /**
127
+ * Update execution statistics for a skill
128
+ */
129
+ updateStats: (name: string, success: boolean) => Promise<void>;
130
+ /**
131
+ * Trust strategy used by this storage (optional, for creating new skills)
132
+ */
133
+ trustStrategy?: TrustStrategy;
134
+ }
135
+ /**
136
+ * Configuration for the skills system
137
+ */
138
+ export interface SkillsConfig {
139
+ /**
140
+ * Storage implementation for skills
141
+ */
142
+ storage: SkillStorage;
143
+ /**
144
+ * Maximum number of skills to load into context per request
145
+ * @default 5
146
+ */
147
+ maxSkillsInContext?: number;
148
+ /**
149
+ * Trust strategy for determining skill trust levels
150
+ * @default createDefaultTrustStrategy()
151
+ */
152
+ trustStrategy?: TrustStrategy;
153
+ }
154
+ /**
155
+ * Options for codeModeWithSkills
156
+ */
157
+ export interface CodeModeWithSkillsOptions {
158
+ /**
159
+ * Code Mode tool configuration (driver, tools, timeout, memoryLimit)
160
+ */
161
+ config: CodeModeToolConfig;
162
+ /**
163
+ * Text adapter for skill selection (should be a cheap/fast model)
164
+ */
165
+ adapter: AnyTextAdapter;
166
+ /**
167
+ * Skills configuration
168
+ */
169
+ skills: SkillsConfig;
170
+ /**
171
+ * Current conversation messages (used for context-aware skill selection)
172
+ */
173
+ messages: Array<ModelMessage>;
174
+ /**
175
+ * Whether to include skills as direct tools (not just sandbox bindings).
176
+ * When true, skills become first-class tools the LLM can call directly.
177
+ * @default true
178
+ */
179
+ skillsAsTools?: boolean;
180
+ }
181
+ /**
182
+ * Result from codeModeWithSkills
183
+ */
184
+ export interface CodeModeWithSkillsResult {
185
+ /**
186
+ * Tool registry for dynamic tool management.
187
+ * Pass this to chat() via the toolRegistry option.
188
+ * Skills registered mid-stream will be added to this registry.
189
+ */
190
+ toolsRegistry: ToolRegistry;
191
+ /**
192
+ * System prompt documenting available skills and external functions
193
+ */
194
+ systemPrompt: string;
195
+ /**
196
+ * Skills that were selected for this request
197
+ */
198
+ selectedSkills: Array<Skill>;
199
+ }
200
+ /**
201
+ * A skill transformed into a format suitable for sandbox injection
202
+ */
203
+ export interface SkillBinding {
204
+ /**
205
+ * Function name with skill_ prefix
206
+ */
207
+ name: string;
208
+ /**
209
+ * The skill this binding wraps
210
+ */
211
+ skill: Skill;
212
+ /**
213
+ * Execute function that runs the skill code
214
+ */
215
+ execute: (input: unknown) => Promise<unknown>;
216
+ }
package/package.json ADDED
@@ -0,0 +1,82 @@
1
+ {
2
+ "name": "@tanstack/ai-code-mode-skills",
3
+ "version": "0.1.0",
4
+ "description": "Persistent skill library for TanStack AI Code Mode - LLM-created reusable code snippets",
5
+ "author": "",
6
+ "license": "MIT",
7
+ "publishConfig": {
8
+ "access": "public"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/TanStack/ai.git",
13
+ "directory": "packages/typescript/ai-code-mode-skills"
14
+ },
15
+ "type": "module",
16
+ "module": "./dist/esm/index.js",
17
+ "types": "./dist/esm/index.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/esm/index.d.ts",
21
+ "import": "./dist/esm/index.js"
22
+ },
23
+ "./storage": {
24
+ "types": "./dist/esm/storage/index.d.ts",
25
+ "import": "./dist/esm/storage/index.js"
26
+ }
27
+ },
28
+ "sideEffects": false,
29
+ "engines": {
30
+ "node": ">=18"
31
+ },
32
+ "files": [
33
+ "dist",
34
+ "src"
35
+ ],
36
+ "scripts": {
37
+ "build": "vite build",
38
+ "clean": "premove ./build ./dist",
39
+ "lint:fix": "eslint ./src --fix",
40
+ "test:build": "publint --strict",
41
+ "test:eslint": "eslint ./src",
42
+ "test:lib": "vitest --passWithNoTests",
43
+ "test:lib:dev": "pnpm test:lib --watch",
44
+ "test:types": "tsc",
45
+ "test:cli": "tsx test-cli/cli.ts",
46
+ "test:cli:run": "tsx test-cli/cli.ts run",
47
+ "test:cli:run:all": "tsx test-cli/cli.ts run --adapters openai,anthropic,gemini",
48
+ "test:cli:list": "tsx test-cli/cli.ts list",
49
+ "test:cli:simulated": "tsx test-cli/cli.ts simulated",
50
+ "test:cli:registry": "tsx test-cli/cli.ts registry",
51
+ "test:cli:live": "tsx test-cli/cli.ts live",
52
+ "test:cli:structured": "tsx test-cli/cli.ts structured"
53
+ },
54
+ "keywords": [
55
+ "ai",
56
+ "tanstack",
57
+ "code-mode",
58
+ "skills",
59
+ "llm",
60
+ "sandbox"
61
+ ],
62
+ "dependencies": {
63
+ "@tanstack/ai": "workspace:*",
64
+ "@tanstack/ai-code-mode": "workspace:*"
65
+ },
66
+ "peerDependencies": {
67
+ "@tanstack/ai": "workspace:*",
68
+ "@tanstack/ai-code-mode": "workspace:*",
69
+ "zod": "^3.0.0 || ^4.0.0"
70
+ },
71
+ "devDependencies": {
72
+ "@tanstack/ai-anthropic": "workspace:*",
73
+ "@tanstack/ai-gemini": "workspace:*",
74
+ "@tanstack/ai-isolate-node": "workspace:*",
75
+ "@tanstack/ai-openai": "workspace:*",
76
+ "@vitest/coverage-v8": "4.0.14",
77
+ "commander": "^13.1.0",
78
+ "dotenv": "^17.2.3",
79
+ "tsx": "^4.21.0",
80
+ "zod": "^4.2.0"
81
+ }
82
+ }