@tanstack/ai-code-mode-snippets 0.3.14
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/LICENSE +21 -0
- package/README.md +208 -0
- package/dist/esm/code-mode-with-snippets.d.ts +65 -0
- package/dist/esm/code-mode-with-snippets.js +145 -0
- package/dist/esm/code-mode-with-snippets.js.map +1 -0
- package/dist/esm/create-snippet-management-tools.d.ts +40 -0
- package/dist/esm/create-snippet-management-tools.js +173 -0
- package/dist/esm/create-snippet-management-tools.js.map +1 -0
- package/dist/esm/create-snippets-system-prompt.d.ts +22 -0
- package/dist/esm/create-snippets-system-prompt.js +234 -0
- package/dist/esm/create-snippets-system-prompt.js.map +1 -0
- package/dist/esm/generate-snippet-types.d.ts +7 -0
- package/dist/esm/generate-snippet-types.js +79 -0
- package/dist/esm/generate-snippet-types.js.map +1 -0
- package/dist/esm/index.d.ts +14 -0
- package/dist/esm/index.js +10 -0
- package/dist/esm/select-relevant-snippets.d.ts +29 -0
- package/dist/esm/select-relevant-snippets.js +56 -0
- package/dist/esm/select-relevant-snippets.js.map +1 -0
- package/dist/esm/snippets-to-bindings.d.ts +34 -0
- package/dist/esm/snippets-to-bindings.js +74 -0
- package/dist/esm/snippets-to-bindings.js.map +1 -0
- package/dist/esm/snippets-to-tools.d.ts +74 -0
- package/dist/esm/snippets-to-tools.js +147 -0
- package/dist/esm/snippets-to-tools.js.map +1 -0
- package/dist/esm/storage/file-storage.d.ts +27 -0
- package/dist/esm/storage/file-storage.js +155 -0
- package/dist/esm/storage/file-storage.js.map +1 -0
- package/dist/esm/storage/index.d.ts +3 -0
- package/dist/esm/storage/index.js +3 -0
- package/dist/esm/storage/memory-storage.d.ts +17 -0
- package/dist/esm/storage/memory-storage.js +100 -0
- package/dist/esm/storage/memory-storage.js.map +1 -0
- package/dist/esm/trust-strategies.d.ts +50 -0
- package/dist/esm/trust-strategies.js +73 -0
- package/dist/esm/trust-strategies.js.map +1 -0
- package/dist/esm/types.d.ts +216 -0
- package/package.json +92 -0
- package/src/code-mode-with-snippets.ts +210 -0
- package/src/create-snippet-management-tools.ts +298 -0
- package/src/create-snippets-system-prompt.ts +289 -0
- package/src/generate-snippet-types.ts +162 -0
- package/src/index.ts +60 -0
- package/src/select-relevant-snippets.ts +136 -0
- package/src/snippets-to-bindings.ts +135 -0
- package/src/snippets-to-tools.ts +325 -0
- package/src/storage/file-storage.ts +275 -0
- package/src/storage/index.ts +6 -0
- package/src/storage/memory-storage.ts +172 -0
- package/src/trust-strategies.ts +142 -0
- package/src/types.ts +289 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-storage.js","names":[],"sources":["../../../src/storage/memory-storage.ts"],"sourcesContent":["import { createDefaultTrustStrategy } from '../trust-strategies'\nimport type {\n Snippet,\n SnippetIndexEntry,\n SnippetSearchOptions,\n SnippetStorage,\n} from '../types'\nimport type { TrustStrategy } from '../trust-strategies'\n\nexport interface MemorySnippetStorageOptions {\n /**\n * Initial snippets to populate the storage with\n */\n initialSnippets?: Array<Snippet>\n\n /**\n * Trust strategy for determining snippet trust levels\n * @default createDefaultTrustStrategy()\n */\n trustStrategy?: TrustStrategy\n}\n\n/**\n * In-memory snippet storage for testing and demos\n */\nexport function createMemorySnippetStorage(\n optionsOrSnippets: MemorySnippetStorageOptions | Array<Snippet> = [],\n): SnippetStorage {\n const options = Array.isArray(optionsOrSnippets)\n ? { initialSnippets: optionsOrSnippets }\n : optionsOrSnippets\n\n const { initialSnippets = [], trustStrategy = createDefaultTrustStrategy() } =\n options\n\n // Store snippets in a Map for O(1) lookup\n const snippets = new Map<string, Snippet>()\n\n // Initialize with any provided snippets\n for (const snippet of initialSnippets) {\n snippets.set(snippet.name, snippet)\n }\n\n function loadIndex(): Promise<Array<SnippetIndexEntry>> {\n return Promise.resolve(\n Array.from(snippets.values()).map((snippet) => ({\n id: snippet.id,\n name: snippet.name,\n description: snippet.description,\n usageHints: snippet.usageHints,\n trustLevel: snippet.trustLevel,\n })),\n )\n }\n\n function loadAll(): Promise<Array<Snippet>> {\n return Promise.resolve(Array.from(snippets.values()))\n }\n\n function get(name: string): Promise<Snippet | null> {\n return Promise.resolve(snippets.get(name) ?? null)\n }\n\n function save(\n snippet: Omit<Snippet, 'createdAt' | 'updatedAt'>,\n ): Promise<Snippet> {\n const now = new Date().toISOString()\n const existing = snippets.get(snippet.name)\n\n const fullSnippet: Snippet = {\n ...snippet,\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n }\n\n snippets.set(snippet.name, fullSnippet)\n return Promise.resolve(fullSnippet)\n }\n\n function deleteSnippet(name: string): Promise<boolean> {\n if (!snippets.has(name)) {\n return Promise.resolve(false)\n }\n snippets.delete(name)\n return Promise.resolve(true)\n }\n\n function search(\n query: string,\n searchOptions: SnippetSearchOptions = {},\n ): Promise<Array<SnippetIndexEntry>> {\n const { limit = 5 } = searchOptions\n\n // Simple text matching\n const queryLower = query.toLowerCase()\n const terms = queryLower.split(/\\s+/)\n\n const scored = Array.from(snippets.values()).map((snippet) => {\n let score = 0\n const searchText = [\n snippet.name,\n snippet.description,\n ...snippet.usageHints,\n ]\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 (snippet.name.toLowerCase().includes(term)) {\n score += 2\n }\n }\n\n return { snippet, score }\n })\n\n return Promise.resolve(\n 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.snippet.id,\n name: s.snippet.name,\n description: s.snippet.description,\n usageHints: s.snippet.usageHints,\n trustLevel: s.snippet.trustLevel,\n })),\n )\n }\n\n function updateStats(name: string, success: boolean): Promise<void> {\n const snippet = snippets.get(name)\n if (!snippet) return Promise.resolve()\n\n const { executions, successRate } = snippet.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 snippet.trustLevel,\n newStats,\n )\n\n snippets.set(name, {\n ...snippet,\n stats: newStats,\n trustLevel: newTrustLevel,\n updatedAt: new Date().toISOString(),\n })\n return Promise.resolve()\n }\n\n return {\n loadIndex,\n loadAll,\n get,\n save,\n delete: deleteSnippet,\n search,\n updateStats,\n trustStrategy,\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { SnippetStats, TrustLevel } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Strategy for determining snippet trust levels
|
|
4
|
+
*/
|
|
5
|
+
export interface TrustStrategy {
|
|
6
|
+
/**
|
|
7
|
+
* Get the initial trust level for a newly created snippet
|
|
8
|
+
*/
|
|
9
|
+
getInitialTrustLevel: () => TrustLevel;
|
|
10
|
+
/**
|
|
11
|
+
* Calculate the new trust level based on execution stats
|
|
12
|
+
*/
|
|
13
|
+
calculateTrustLevel: (currentLevel: TrustLevel, stats: SnippetStats) => TrustLevel;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Default trust strategy - snippets must earn trust through successful executions
|
|
17
|
+
*
|
|
18
|
+
* - untrusted: New snippet (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 - snippets 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 snippet (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,73 @@
|
|
|
1
|
+
//#region src/trust-strategies.ts
|
|
2
|
+
/**
|
|
3
|
+
* Default trust strategy - snippets must earn trust through successful executions
|
|
4
|
+
*
|
|
5
|
+
* - untrusted: New snippet (0 executions)
|
|
6
|
+
* - provisional: 10+ executions with ≥90% success rate
|
|
7
|
+
* - trusted: 100+ executions with ≥95% success rate
|
|
8
|
+
*/
|
|
9
|
+
function createDefaultTrustStrategy() {
|
|
10
|
+
return {
|
|
11
|
+
getInitialTrustLevel: () => "untrusted",
|
|
12
|
+
calculateTrustLevel: (currentLevel, stats) => {
|
|
13
|
+
const { executions, successRate } = stats;
|
|
14
|
+
if (currentLevel === "untrusted" && executions >= 10 && successRate >= .9) return "provisional";
|
|
15
|
+
if (currentLevel === "provisional" && executions >= 100 && successRate >= .95) return "trusted";
|
|
16
|
+
return currentLevel;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Always trusted strategy - snippets are immediately trusted upon creation
|
|
22
|
+
*
|
|
23
|
+
* Use this for development/testing or when you trust the LLM's code generation
|
|
24
|
+
*/
|
|
25
|
+
function createAlwaysTrustedStrategy() {
|
|
26
|
+
return {
|
|
27
|
+
getInitialTrustLevel: () => "trusted",
|
|
28
|
+
calculateTrustLevel: () => "trusted"
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Relaxed trust strategy - faster trust promotion for development
|
|
33
|
+
*
|
|
34
|
+
* - untrusted: New snippet (0 executions)
|
|
35
|
+
* - provisional: 3+ executions with ≥80% success rate
|
|
36
|
+
* - trusted: 10+ executions with ≥90% success rate
|
|
37
|
+
*/
|
|
38
|
+
function createRelaxedTrustStrategy() {
|
|
39
|
+
return {
|
|
40
|
+
getInitialTrustLevel: () => "untrusted",
|
|
41
|
+
calculateTrustLevel: (currentLevel, stats) => {
|
|
42
|
+
const { executions, successRate } = stats;
|
|
43
|
+
if (currentLevel === "untrusted" && executions >= 3 && successRate >= .8) return "provisional";
|
|
44
|
+
if (currentLevel === "provisional" && executions >= 10 && successRate >= .9) return "trusted";
|
|
45
|
+
return currentLevel;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Custom trust strategy with configurable thresholds
|
|
51
|
+
*/
|
|
52
|
+
function createCustomTrustStrategy(config) {
|
|
53
|
+
const { initialLevel = "untrusted", provisionalThreshold = {
|
|
54
|
+
executions: 10,
|
|
55
|
+
successRate: .9
|
|
56
|
+
}, trustedThreshold = {
|
|
57
|
+
executions: 100,
|
|
58
|
+
successRate: .95
|
|
59
|
+
} } = config;
|
|
60
|
+
return {
|
|
61
|
+
getInitialTrustLevel: () => initialLevel,
|
|
62
|
+
calculateTrustLevel: (currentLevel, stats) => {
|
|
63
|
+
const { executions, successRate } = stats;
|
|
64
|
+
if (currentLevel === "untrusted" && executions >= provisionalThreshold.executions && successRate >= provisionalThreshold.successRate) return "provisional";
|
|
65
|
+
if (currentLevel === "provisional" && executions >= trustedThreshold.executions && successRate >= trustedThreshold.successRate) return "trusted";
|
|
66
|
+
return currentLevel;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
71
|
+
export { createAlwaysTrustedStrategy, createCustomTrustStrategy, createDefaultTrustStrategy, createRelaxedTrustStrategy };
|
|
72
|
+
|
|
73
|
+
//# sourceMappingURL=trust-strategies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trust-strategies.js","names":[],"sources":["../../src/trust-strategies.ts"],"sourcesContent":["import type { SnippetStats, TrustLevel } from './types'\n\n/**\n * Strategy for determining snippet trust levels\n */\nexport interface TrustStrategy {\n /**\n * Get the initial trust level for a newly created snippet\n */\n getInitialTrustLevel: () => TrustLevel\n\n /**\n * Calculate the new trust level based on execution stats\n */\n calculateTrustLevel: (\n currentLevel: TrustLevel,\n stats: SnippetStats,\n ) => TrustLevel\n}\n\n/**\n * Default trust strategy - snippets must earn trust through successful executions\n *\n * - untrusted: New snippet (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 - snippets 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 snippet (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"],"mappings":";;;;;;;;AA2BA,SAAgB,6BAA4C;CAC1D,OAAO;EACL,4BAA4B;EAE5B,sBAAsB,cAAc,UAAU;GAC5C,MAAM,EAAE,YAAY,gBAAgB;GAEpC,IACE,iBAAiB,eACjB,cAAc,MACd,eAAe,IAEf,OAAO;GAGT,IACE,iBAAiB,iBACjB,cAAc,OACd,eAAe,KAEf,OAAO;GAGT,OAAO;EACT;CACF;AACF;;;;;;AAOA,SAAgB,8BAA6C;CAC3D,OAAO;EACL,4BAA4B;EAC5B,2BAA2B;CAC7B;AACF;;;;;;;;AASA,SAAgB,6BAA4C;CAC1D,OAAO;EACL,4BAA4B;EAE5B,sBAAsB,cAAc,UAAU;GAC5C,MAAM,EAAE,YAAY,gBAAgB;GAEpC,IACE,iBAAiB,eACjB,cAAc,KACd,eAAe,IAEf,OAAO;GAGT,IACE,iBAAiB,iBACjB,cAAc,MACd,eAAe,IAEf,OAAO;GAGT,OAAO;EACT;CACF;AACF;;;;AAKA,SAAgB,0BAA0B,QAIxB;CAChB,MAAM,EACJ,eAAe,aACf,uBAAuB;EAAE,YAAY;EAAI,aAAa;CAAI,GAC1D,mBAAmB;EAAE,YAAY;EAAK,aAAa;CAAK,MACtD;CAEJ,OAAO;EACL,4BAA4B;EAE5B,sBAAsB,cAAc,UAAU;GAC5C,MAAM,EAAE,YAAY,gBAAgB;GAEpC,IACE,iBAAiB,eACjB,cAAc,qBAAqB,cACnC,eAAe,qBAAqB,aAEpC,OAAO;GAGT,IACE,iBAAiB,iBACjB,cAAc,iBAAiB,cAC/B,eAAe,iBAAiB,aAEhC,OAAO;GAGT,OAAO;EACT;CACF;AACF"}
|
|
@@ -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 snippet
|
|
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 snippet
|
|
13
|
+
*/
|
|
14
|
+
export interface SnippetStats {
|
|
15
|
+
/**
|
|
16
|
+
* Total number of times this snippet 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 snippet that can be executed in the Code Mode sandbox
|
|
26
|
+
*/
|
|
27
|
+
export interface Snippet {
|
|
28
|
+
/**
|
|
29
|
+
* Unique identifier for the snippet
|
|
30
|
+
*/
|
|
31
|
+
id: string;
|
|
32
|
+
/**
|
|
33
|
+
* Unique name in snake_case (e.g., 'fetch_github_stats')
|
|
34
|
+
* This becomes the function name with snippet_ prefix in the sandbox
|
|
35
|
+
*/
|
|
36
|
+
name: string;
|
|
37
|
+
/**
|
|
38
|
+
* Human-readable description of what the snippet does
|
|
39
|
+
*/
|
|
40
|
+
description: string;
|
|
41
|
+
/**
|
|
42
|
+
* TypeScript code that implements the snippet
|
|
43
|
+
* The code receives `input` as a variable and can call:
|
|
44
|
+
* - external_* functions (tools)
|
|
45
|
+
* - other snippet_* functions (snippets)
|
|
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 snippet
|
|
59
|
+
* e.g., "Use when comparing NPM package popularity"
|
|
60
|
+
*/
|
|
61
|
+
usageHints: Array<string>;
|
|
62
|
+
/**
|
|
63
|
+
* Names of other snippets this snippet 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: SnippetStats;
|
|
74
|
+
/**
|
|
75
|
+
* ISO timestamp when the snippet was created
|
|
76
|
+
*/
|
|
77
|
+
createdAt: string;
|
|
78
|
+
/**
|
|
79
|
+
* ISO timestamp when the snippet was last updated
|
|
80
|
+
*/
|
|
81
|
+
updatedAt: string;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Lightweight snippet entry for the index (metadata only, no code)
|
|
85
|
+
* Used for fast loading and snippet selection
|
|
86
|
+
*/
|
|
87
|
+
export type SnippetIndexEntry = Pick<Snippet, 'id' | 'name' | 'description' | 'usageHints' | 'trustLevel'>;
|
|
88
|
+
/**
|
|
89
|
+
* Options for searching snippets
|
|
90
|
+
*/
|
|
91
|
+
export interface SnippetSearchOptions {
|
|
92
|
+
/**
|
|
93
|
+
* Maximum number of results to return
|
|
94
|
+
* @default 5
|
|
95
|
+
*/
|
|
96
|
+
limit?: number;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Interface for snippet storage implementations
|
|
100
|
+
*/
|
|
101
|
+
export interface SnippetStorage {
|
|
102
|
+
/**
|
|
103
|
+
* Load the snippet index (lightweight metadata for all snippets)
|
|
104
|
+
*/
|
|
105
|
+
loadIndex: () => Promise<Array<SnippetIndexEntry>>;
|
|
106
|
+
/**
|
|
107
|
+
* Load all snippets with full details (including code)
|
|
108
|
+
*/
|
|
109
|
+
loadAll: () => Promise<Array<Snippet>>;
|
|
110
|
+
/**
|
|
111
|
+
* Get a snippet by name
|
|
112
|
+
*/
|
|
113
|
+
get: (name: string) => Promise<Snippet | null>;
|
|
114
|
+
/**
|
|
115
|
+
* Save a snippet (create or update)
|
|
116
|
+
*/
|
|
117
|
+
save: (snippet: Omit<Snippet, 'createdAt' | 'updatedAt'>) => Promise<Snippet>;
|
|
118
|
+
/**
|
|
119
|
+
* Delete a snippet by name
|
|
120
|
+
*/
|
|
121
|
+
delete: (name: string) => Promise<boolean>;
|
|
122
|
+
/**
|
|
123
|
+
* Search for snippets by query
|
|
124
|
+
*/
|
|
125
|
+
search: (query: string, options?: SnippetSearchOptions) => Promise<Array<SnippetIndexEntry>>;
|
|
126
|
+
/**
|
|
127
|
+
* Update execution statistics for a snippet
|
|
128
|
+
*/
|
|
129
|
+
updateStats: (name: string, success: boolean) => Promise<void>;
|
|
130
|
+
/**
|
|
131
|
+
* Trust strategy used by this storage (optional, for creating new snippets)
|
|
132
|
+
*/
|
|
133
|
+
trustStrategy?: TrustStrategy;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Configuration for the snippets system
|
|
137
|
+
*/
|
|
138
|
+
export interface SnippetsConfig {
|
|
139
|
+
/**
|
|
140
|
+
* Storage implementation for snippets
|
|
141
|
+
*/
|
|
142
|
+
storage: SnippetStorage;
|
|
143
|
+
/**
|
|
144
|
+
* Maximum number of snippets to load into context per request
|
|
145
|
+
* @default 5
|
|
146
|
+
*/
|
|
147
|
+
maxSnippetsInContext?: number;
|
|
148
|
+
/**
|
|
149
|
+
* Trust strategy for determining snippet trust levels
|
|
150
|
+
* @default createDefaultTrustStrategy()
|
|
151
|
+
*/
|
|
152
|
+
trustStrategy?: TrustStrategy;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Options for codeModeWithSnippets
|
|
156
|
+
*/
|
|
157
|
+
export interface CodeModeWithSnippetsOptions {
|
|
158
|
+
/**
|
|
159
|
+
* Code Mode tool configuration (driver, tools, timeout, memoryLimit)
|
|
160
|
+
*/
|
|
161
|
+
config: CodeModeToolConfig;
|
|
162
|
+
/**
|
|
163
|
+
* Text adapter for snippet selection (should be a cheap/fast model)
|
|
164
|
+
*/
|
|
165
|
+
adapter: AnyTextAdapter;
|
|
166
|
+
/**
|
|
167
|
+
* Snippets configuration
|
|
168
|
+
*/
|
|
169
|
+
snippets: SnippetsConfig;
|
|
170
|
+
/**
|
|
171
|
+
* Current conversation messages (used for context-aware snippet selection)
|
|
172
|
+
*/
|
|
173
|
+
messages: Array<ModelMessage>;
|
|
174
|
+
/**
|
|
175
|
+
* Whether to include snippets as direct tools (not just sandbox bindings).
|
|
176
|
+
* When true, snippets become first-class tools the LLM can call directly.
|
|
177
|
+
* @default true
|
|
178
|
+
*/
|
|
179
|
+
snippetsAsTools?: boolean;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Result from codeModeWithSnippets
|
|
183
|
+
*/
|
|
184
|
+
export interface CodeModeWithSnippetsResult {
|
|
185
|
+
/**
|
|
186
|
+
* Tool registry for dynamic tool management.
|
|
187
|
+
* Pass this to chat() via the toolRegistry option.
|
|
188
|
+
* Snippets registered mid-stream will be added to this registry.
|
|
189
|
+
*/
|
|
190
|
+
toolsRegistry: ToolRegistry;
|
|
191
|
+
/**
|
|
192
|
+
* System prompt documenting available snippets and external functions
|
|
193
|
+
*/
|
|
194
|
+
systemPrompt: string;
|
|
195
|
+
/**
|
|
196
|
+
* Snippets that were selected for this request
|
|
197
|
+
*/
|
|
198
|
+
selectedSnippets: Array<Snippet>;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* A snippet transformed into a format suitable for sandbox injection
|
|
202
|
+
*/
|
|
203
|
+
export interface SnippetBinding {
|
|
204
|
+
/**
|
|
205
|
+
* Function name with snippet_ prefix
|
|
206
|
+
*/
|
|
207
|
+
name: string;
|
|
208
|
+
/**
|
|
209
|
+
* The snippet this binding wraps
|
|
210
|
+
*/
|
|
211
|
+
snippet: Snippet;
|
|
212
|
+
/**
|
|
213
|
+
* Execute function that runs the snippet code
|
|
214
|
+
*/
|
|
215
|
+
execute: (input: unknown) => Promise<unknown>;
|
|
216
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tanstack/ai-code-mode-snippets",
|
|
3
|
+
"version": "0.3.14",
|
|
4
|
+
"description": "Persistent runtime snippet library for TanStack AI Code Mode agents and sandboxed tool orchestration.",
|
|
5
|
+
"author": "Tanner Linsley",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"homepage": "https://tanstack.com/ai",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/TanStack/ai.git",
|
|
11
|
+
"directory": "packages/ai-code-mode-snippets"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/TanStack/ai/issues"
|
|
15
|
+
},
|
|
16
|
+
"funding": {
|
|
17
|
+
"type": "github",
|
|
18
|
+
"url": "https://github.com/sponsors/tannerlinsley"
|
|
19
|
+
},
|
|
20
|
+
"type": "module",
|
|
21
|
+
"module": "./dist/esm/index.js",
|
|
22
|
+
"types": "./dist/esm/index.d.ts",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/esm/index.d.ts",
|
|
26
|
+
"import": "./dist/esm/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./storage": {
|
|
29
|
+
"types": "./dist/esm/storage/index.d.ts",
|
|
30
|
+
"import": "./dist/esm/storage/index.js"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"sideEffects": false,
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=18"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist",
|
|
39
|
+
"src"
|
|
40
|
+
],
|
|
41
|
+
"keywords": [
|
|
42
|
+
"ai",
|
|
43
|
+
"ai-sdk",
|
|
44
|
+
"typescript",
|
|
45
|
+
"tanstack",
|
|
46
|
+
"code-mode",
|
|
47
|
+
"snippets",
|
|
48
|
+
"agents",
|
|
49
|
+
"llm",
|
|
50
|
+
"sandbox",
|
|
51
|
+
"tool-calling",
|
|
52
|
+
"tanstack-intent"
|
|
53
|
+
],
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"@tanstack/ai": "^0.44.1",
|
|
56
|
+
"@tanstack/ai-code-mode": "^0.3.11"
|
|
57
|
+
},
|
|
58
|
+
"peerDependencies": {
|
|
59
|
+
"zod": "^3.0.0 || ^4.0.0",
|
|
60
|
+
"@tanstack/ai": "^0.44.1",
|
|
61
|
+
"@tanstack/ai-code-mode": "^0.3.11"
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {
|
|
64
|
+
"@vitest/coverage-v8": "4.1.10",
|
|
65
|
+
"commander": "^13.1.0",
|
|
66
|
+
"dotenv": "^17.2.3",
|
|
67
|
+
"tsx": "^4.23.12",
|
|
68
|
+
"zod": "^4.2.0",
|
|
69
|
+
"@tanstack/ai-gemini": "0.23.0",
|
|
70
|
+
"@tanstack/ai-anthropic": "0.16.5",
|
|
71
|
+
"@tanstack/ai-openai": "0.19.0",
|
|
72
|
+
"@tanstack/ai-isolate-node": "0.1.50"
|
|
73
|
+
},
|
|
74
|
+
"scripts": {
|
|
75
|
+
"build": "vite build",
|
|
76
|
+
"clean": "premove ./build ./dist",
|
|
77
|
+
"lint:fix": "oxlint src --type-aware --fix",
|
|
78
|
+
"test:build": "publint --strict",
|
|
79
|
+
"test:oxlint": "oxlint src --type-aware",
|
|
80
|
+
"test:lib": "vitest --passWithNoTests",
|
|
81
|
+
"test:lib:dev": "pnpm test:lib --watch",
|
|
82
|
+
"test:types": "tsc",
|
|
83
|
+
"test:cli": "tsx test-cli/cli.ts",
|
|
84
|
+
"test:cli:run": "tsx test-cli/cli.ts run",
|
|
85
|
+
"test:cli:run:all": "tsx test-cli/cli.ts run --adapters openai,anthropic,gemini",
|
|
86
|
+
"test:cli:list": "tsx test-cli/cli.ts list",
|
|
87
|
+
"test:cli:simulated": "tsx test-cli/cli.ts simulated",
|
|
88
|
+
"test:cli:registry": "tsx test-cli/cli.ts registry",
|
|
89
|
+
"test:cli:live": "tsx test-cli/cli.ts live",
|
|
90
|
+
"test:cli:structured": "tsx test-cli/cli.ts structured"
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createCodeModeSystemPrompt,
|
|
3
|
+
createCodeModeTool,
|
|
4
|
+
toolsToBindings,
|
|
5
|
+
} from '@tanstack/ai-code-mode'
|
|
6
|
+
import { createToolRegistry } from '@tanstack/ai'
|
|
7
|
+
import { selectRelevantSnippets } from './select-relevant-snippets'
|
|
8
|
+
import { createSnippetManagementTools } from './create-snippet-management-tools'
|
|
9
|
+
import { createSnippetsSystemPrompt } from './create-snippets-system-prompt'
|
|
10
|
+
import { snippetsToTools } from './snippets-to-tools'
|
|
11
|
+
import type {
|
|
12
|
+
CodeModeWithSnippetsOptions,
|
|
13
|
+
CodeModeWithSnippetsResult,
|
|
14
|
+
Snippet,
|
|
15
|
+
} from './types'
|
|
16
|
+
import type { ToolBinding } from '@tanstack/ai-code-mode'
|
|
17
|
+
|
|
18
|
+
export type { CodeModeWithSnippetsOptions, CodeModeWithSnippetsResult }
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Create Code Mode tools and system prompt with snippets integration.
|
|
22
|
+
*
|
|
23
|
+
* This function:
|
|
24
|
+
* 1. Loads the snippet index from storage
|
|
25
|
+
* 2. Uses a cheap/fast LLM to select relevant snippets based on conversation context
|
|
26
|
+
* 3. Creates the execute_typescript tool with dynamic snippet bindings
|
|
27
|
+
* 4. Creates snippet management tools (search, get, register)
|
|
28
|
+
* 5. Generates system prompts documenting available snippets
|
|
29
|
+
* 6. Returns a ToolRegistry that allows dynamic snippet additions mid-stream
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* // Node-only file storage lives behind the `/storage` subpath:
|
|
34
|
+
* import { createFileSnippetStorage } from '@tanstack/ai-code-mode-snippets/storage'
|
|
35
|
+
*
|
|
36
|
+
* const { toolsRegistry, systemPrompt, selectedSnippets } = await codeModeWithSnippets({
|
|
37
|
+
* config: {
|
|
38
|
+
* driver: createNodeIsolateDriver(),
|
|
39
|
+
* tools: allTools,
|
|
40
|
+
* timeout: 60000,
|
|
41
|
+
* },
|
|
42
|
+
* adapter: openaiText('gpt-4o-mini'), // Cheap model for selection
|
|
43
|
+
* snippets: {
|
|
44
|
+
* storage: createFileSnippetStorage('./.snippets'),
|
|
45
|
+
* maxSnippetsInContext: 5,
|
|
46
|
+
* },
|
|
47
|
+
* messages,
|
|
48
|
+
* });
|
|
49
|
+
*
|
|
50
|
+
* const stream = chat({
|
|
51
|
+
* adapter: openaiText('gpt-4o'), // Main model
|
|
52
|
+
* toolRegistry: toolsRegistry, // Dynamic tool registry
|
|
53
|
+
* messages,
|
|
54
|
+
* systemPrompts: [BASE_PROMPT, systemPrompt],
|
|
55
|
+
* });
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export async function codeModeWithSnippets({
|
|
59
|
+
config,
|
|
60
|
+
adapter,
|
|
61
|
+
snippets,
|
|
62
|
+
messages,
|
|
63
|
+
snippetsAsTools = true,
|
|
64
|
+
}: CodeModeWithSnippetsOptions): Promise<CodeModeWithSnippetsResult> {
|
|
65
|
+
const { storage, maxSnippetsInContext = 5 } = snippets
|
|
66
|
+
|
|
67
|
+
// 1. Load the snippet index (lightweight metadata only)
|
|
68
|
+
const snippetIndex = await storage.loadIndex()
|
|
69
|
+
|
|
70
|
+
// 2. Use adapter to select relevant snippets based on transcript
|
|
71
|
+
const selectedSnippets = await selectRelevantSnippets({
|
|
72
|
+
adapter,
|
|
73
|
+
messages,
|
|
74
|
+
snippetIndex,
|
|
75
|
+
maxSnippets: maxSnippetsInContext,
|
|
76
|
+
storage,
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
// Pre-compute bindings from base tools (shared across snippet executions)
|
|
80
|
+
const baseBindings = toolsToBindings(config.tools, 'external_')
|
|
81
|
+
|
|
82
|
+
// 3. Create the execute_typescript tool with dynamic snippet bindings
|
|
83
|
+
const codeModeTool = createCodeModeTool({
|
|
84
|
+
...config,
|
|
85
|
+
// Dynamic snippet bindings - fetched at execution time
|
|
86
|
+
getSnippetBindings: async () => {
|
|
87
|
+
// Get all snippets from storage (includes newly registered ones)
|
|
88
|
+
const allSnippets = await storage.loadAll()
|
|
89
|
+
// Convert to bindings with snippet_ prefix
|
|
90
|
+
const snippetBindings: Record<string, ToolBinding> = {}
|
|
91
|
+
for (const snippet of allSnippets) {
|
|
92
|
+
// Create a simple binding that executes the snippet code
|
|
93
|
+
snippetBindings[`snippet_${snippet.name}`] = {
|
|
94
|
+
name: `snippet_${snippet.name}`,
|
|
95
|
+
description: snippet.description,
|
|
96
|
+
inputSchema: snippet.inputSchema,
|
|
97
|
+
outputSchema: snippet.outputSchema,
|
|
98
|
+
execute: async (input: unknown) => {
|
|
99
|
+
// This is a simplified execution - the full snippetToTool handles events
|
|
100
|
+
const wrappedCode = `const input = ${JSON.stringify(input)};\n${snippet.code}`
|
|
101
|
+
const { stripTypeScript, createEventAwareBindings } =
|
|
102
|
+
await import('@tanstack/ai-code-mode')
|
|
103
|
+
const strippedCode = await stripTypeScript(wrappedCode)
|
|
104
|
+
const context = await config.driver.createContext({
|
|
105
|
+
bindings: createEventAwareBindings(baseBindings, () => {}),
|
|
106
|
+
timeout: config.timeout,
|
|
107
|
+
...(config.memoryLimit !== undefined && {
|
|
108
|
+
memoryLimit: config.memoryLimit,
|
|
109
|
+
}),
|
|
110
|
+
})
|
|
111
|
+
try {
|
|
112
|
+
const result = await context.execute(strippedCode)
|
|
113
|
+
if (!result.success) {
|
|
114
|
+
throw new Error(
|
|
115
|
+
result.error?.message || 'Snippet execution failed',
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
return result.value
|
|
119
|
+
} finally {
|
|
120
|
+
await context.dispose()
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return snippetBindings
|
|
126
|
+
},
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
// 4. Create a mutable tool registry
|
|
130
|
+
const registry = createToolRegistry()
|
|
131
|
+
|
|
132
|
+
// 5. Add the execute_typescript tool to the registry
|
|
133
|
+
registry.add(codeModeTool)
|
|
134
|
+
|
|
135
|
+
// 6. Create snippet management tools (they need access to the registry)
|
|
136
|
+
const snippetManagementTools = createSnippetManagementTools({
|
|
137
|
+
storage,
|
|
138
|
+
registry,
|
|
139
|
+
config,
|
|
140
|
+
baseBindings,
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
for (const tool of snippetManagementTools) {
|
|
144
|
+
registry.add(tool)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// 7. Convert selected snippets to direct tools and add to registry (if enabled)
|
|
148
|
+
if (snippetsAsTools && selectedSnippets.length > 0) {
|
|
149
|
+
const snippetToolsList = snippetsToTools({
|
|
150
|
+
snippets: selectedSnippets,
|
|
151
|
+
driver: config.driver,
|
|
152
|
+
tools: config.tools,
|
|
153
|
+
storage,
|
|
154
|
+
timeout: config.timeout,
|
|
155
|
+
memoryLimit: config.memoryLimit,
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
for (const snippetTool of snippetToolsList) {
|
|
159
|
+
registry.add(snippetTool)
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// 8. Generate combined system prompt
|
|
164
|
+
const basePrompt = createCodeModeSystemPrompt(config)
|
|
165
|
+
const snippetsPrompt = createSnippetsSystemPrompt({
|
|
166
|
+
selectedSnippets,
|
|
167
|
+
totalSnippetCount: snippetIndex.length,
|
|
168
|
+
snippetsAsTools,
|
|
169
|
+
})
|
|
170
|
+
const systemPrompt = basePrompt + '\n\n' + snippetsPrompt
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
toolsRegistry: registry,
|
|
174
|
+
systemPrompt,
|
|
175
|
+
selectedSnippets,
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Create a Code Mode tool configuration extended with snippets.
|
|
181
|
+
* This is an alternative to codeModeWithSnippets that returns
|
|
182
|
+
* a config object instead of directly creating tools.
|
|
183
|
+
*
|
|
184
|
+
* Useful when you want more control over the tool creation process.
|
|
185
|
+
*/
|
|
186
|
+
export function createCodeModeWithSnippetsConfig({
|
|
187
|
+
config,
|
|
188
|
+
selectedSnippets,
|
|
189
|
+
storage,
|
|
190
|
+
}: {
|
|
191
|
+
config: CodeModeWithSnippetsOptions['config']
|
|
192
|
+
selectedSnippets: Array<Snippet>
|
|
193
|
+
storage: CodeModeWithSnippetsOptions['snippets']['storage']
|
|
194
|
+
}) {
|
|
195
|
+
// Create snippet tools for direct calling
|
|
196
|
+
const snippetToolsList = snippetsToTools({
|
|
197
|
+
snippets: selectedSnippets,
|
|
198
|
+
driver: config.driver,
|
|
199
|
+
tools: config.tools,
|
|
200
|
+
storage,
|
|
201
|
+
timeout: config.timeout,
|
|
202
|
+
memoryLimit: config.memoryLimit,
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
return {
|
|
206
|
+
...config,
|
|
207
|
+
snippetTools: snippetToolsList,
|
|
208
|
+
selectedSnippets,
|
|
209
|
+
}
|
|
210
|
+
}
|