skillshield 1.0.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 (167) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +400 -0
  3. package/dist/channels/discord.d.ts +18 -0
  4. package/dist/channels/discord.d.ts.map +1 -0
  5. package/dist/channels/discord.js +275 -0
  6. package/dist/channels/discord.js.map +1 -0
  7. package/dist/channels/index.d.ts +67 -0
  8. package/dist/channels/index.d.ts.map +1 -0
  9. package/dist/channels/index.js +127 -0
  10. package/dist/channels/index.js.map +1 -0
  11. package/dist/channels/slack.d.ts +20 -0
  12. package/dist/channels/slack.d.ts.map +1 -0
  13. package/dist/channels/slack.js +296 -0
  14. package/dist/channels/slack.js.map +1 -0
  15. package/dist/channels/telegram.d.ts +20 -0
  16. package/dist/channels/telegram.d.ts.map +1 -0
  17. package/dist/channels/telegram.js +223 -0
  18. package/dist/channels/telegram.js.map +1 -0
  19. package/dist/channels/whatsapp.d.ts +25 -0
  20. package/dist/channels/whatsapp.d.ts.map +1 -0
  21. package/dist/channels/whatsapp.js +187 -0
  22. package/dist/channels/whatsapp.js.map +1 -0
  23. package/dist/cli/commands/badge.d.ts +11 -0
  24. package/dist/cli/commands/badge.d.ts.map +1 -0
  25. package/dist/cli/commands/badge.js +98 -0
  26. package/dist/cli/commands/badge.js.map +1 -0
  27. package/dist/cli/commands/config.d.ts +3 -0
  28. package/dist/cli/commands/config.d.ts.map +1 -0
  29. package/dist/cli/commands/config.js +140 -0
  30. package/dist/cli/commands/config.js.map +1 -0
  31. package/dist/cli/commands/deploy.d.ts +3 -0
  32. package/dist/cli/commands/deploy.d.ts.map +1 -0
  33. package/dist/cli/commands/deploy.js +56 -0
  34. package/dist/cli/commands/deploy.js.map +1 -0
  35. package/dist/cli/commands/init.d.ts +3 -0
  36. package/dist/cli/commands/init.d.ts.map +1 -0
  37. package/dist/cli/commands/init.js +99 -0
  38. package/dist/cli/commands/init.js.map +1 -0
  39. package/dist/cli/commands/install.d.ts +3 -0
  40. package/dist/cli/commands/install.d.ts.map +1 -0
  41. package/dist/cli/commands/install.js +90 -0
  42. package/dist/cli/commands/install.js.map +1 -0
  43. package/dist/cli/commands/list.d.ts +3 -0
  44. package/dist/cli/commands/list.d.ts.map +1 -0
  45. package/dist/cli/commands/list.js +76 -0
  46. package/dist/cli/commands/list.js.map +1 -0
  47. package/dist/cli/commands/run.d.ts +3 -0
  48. package/dist/cli/commands/run.d.ts.map +1 -0
  49. package/dist/cli/commands/run.js +160 -0
  50. package/dist/cli/commands/run.js.map +1 -0
  51. package/dist/cli/commands/scan.d.ts +3 -0
  52. package/dist/cli/commands/scan.d.ts.map +1 -0
  53. package/dist/cli/commands/scan.js +133 -0
  54. package/dist/cli/commands/scan.js.map +1 -0
  55. package/dist/cli/commands/search.d.ts +3 -0
  56. package/dist/cli/commands/search.d.ts.map +1 -0
  57. package/dist/cli/commands/search.js +56 -0
  58. package/dist/cli/commands/search.js.map +1 -0
  59. package/dist/cli/index.d.ts +3 -0
  60. package/dist/cli/index.d.ts.map +1 -0
  61. package/dist/cli/index.js +70 -0
  62. package/dist/cli/index.js.map +1 -0
  63. package/dist/core/config.d.ts +167 -0
  64. package/dist/core/config.d.ts.map +1 -0
  65. package/dist/core/config.js +398 -0
  66. package/dist/core/config.js.map +1 -0
  67. package/dist/core/parser.d.ts +34 -0
  68. package/dist/core/parser.d.ts.map +1 -0
  69. package/dist/core/parser.js +462 -0
  70. package/dist/core/parser.js.map +1 -0
  71. package/dist/core/runtime.d.ts +68 -0
  72. package/dist/core/runtime.d.ts.map +1 -0
  73. package/dist/core/runtime.js +560 -0
  74. package/dist/core/runtime.js.map +1 -0
  75. package/dist/core/types.d.ts +525 -0
  76. package/dist/core/types.d.ts.map +1 -0
  77. package/dist/core/types.js +44 -0
  78. package/dist/core/types.js.map +1 -0
  79. package/dist/guard/index.d.ts +57 -0
  80. package/dist/guard/index.d.ts.map +1 -0
  81. package/dist/guard/index.js +238 -0
  82. package/dist/guard/index.js.map +1 -0
  83. package/dist/guard/patterns.d.ts +21 -0
  84. package/dist/guard/patterns.d.ts.map +1 -0
  85. package/dist/guard/patterns.js +797 -0
  86. package/dist/guard/patterns.js.map +1 -0
  87. package/dist/hub/index.d.ts +44 -0
  88. package/dist/hub/index.d.ts.map +1 -0
  89. package/dist/hub/index.js +144 -0
  90. package/dist/hub/index.js.map +1 -0
  91. package/dist/hub/registry.d.ts +52 -0
  92. package/dist/hub/registry.d.ts.map +1 -0
  93. package/dist/hub/registry.js +192 -0
  94. package/dist/hub/registry.js.map +1 -0
  95. package/dist/i18n/index.d.ts +19 -0
  96. package/dist/i18n/index.d.ts.map +1 -0
  97. package/dist/i18n/index.js +92 -0
  98. package/dist/i18n/index.js.map +1 -0
  99. package/dist/i18n/locales/en.d.ts +110 -0
  100. package/dist/i18n/locales/en.d.ts.map +1 -0
  101. package/dist/i18n/locales/en.js +123 -0
  102. package/dist/i18n/locales/en.js.map +1 -0
  103. package/dist/i18n/locales/es.d.ts +110 -0
  104. package/dist/i18n/locales/es.d.ts.map +1 -0
  105. package/dist/i18n/locales/es.js +123 -0
  106. package/dist/i18n/locales/es.js.map +1 -0
  107. package/dist/i18n/locales/pt.d.ts +110 -0
  108. package/dist/i18n/locales/pt.d.ts.map +1 -0
  109. package/dist/i18n/locales/pt.js +123 -0
  110. package/dist/i18n/locales/pt.js.map +1 -0
  111. package/dist/i18n/locales/zh.d.ts +110 -0
  112. package/dist/i18n/locales/zh.d.ts.map +1 -0
  113. package/dist/i18n/locales/zh.js +123 -0
  114. package/dist/i18n/locales/zh.js.map +1 -0
  115. package/dist/index.d.ts +168 -0
  116. package/dist/index.d.ts.map +1 -0
  117. package/dist/index.js +275 -0
  118. package/dist/index.js.map +1 -0
  119. package/dist/router/index.d.ts +89 -0
  120. package/dist/router/index.d.ts.map +1 -0
  121. package/dist/router/index.js +292 -0
  122. package/dist/router/index.js.map +1 -0
  123. package/dist/router/providers.d.ts +48 -0
  124. package/dist/router/providers.d.ts.map +1 -0
  125. package/dist/router/providers.js +733 -0
  126. package/dist/router/providers.js.map +1 -0
  127. package/dist/runtime/executor.d.ts +96 -0
  128. package/dist/runtime/executor.d.ts.map +1 -0
  129. package/dist/runtime/executor.js +389 -0
  130. package/dist/runtime/executor.js.map +1 -0
  131. package/dist/sandbox/index.d.ts +52 -0
  132. package/dist/sandbox/index.d.ts.map +1 -0
  133. package/dist/sandbox/index.js +248 -0
  134. package/dist/sandbox/index.js.map +1 -0
  135. package/dist/security/skillguard.d.ts +25 -0
  136. package/dist/security/skillguard.d.ts.map +1 -0
  137. package/dist/security/skillguard.js +137 -0
  138. package/dist/security/skillguard.js.map +1 -0
  139. package/dist/tools/index.d.ts +55 -0
  140. package/dist/tools/index.d.ts.map +1 -0
  141. package/dist/tools/index.js +276 -0
  142. package/dist/tools/index.js.map +1 -0
  143. package/dist/tools/web-engine.d.ts +158 -0
  144. package/dist/tools/web-engine.d.ts.map +1 -0
  145. package/dist/tools/web-engine.js +802 -0
  146. package/dist/tools/web-engine.js.map +1 -0
  147. package/dist/tools/web-tools.d.ts +173 -0
  148. package/dist/tools/web-tools.d.ts.map +1 -0
  149. package/dist/tools/web-tools.js +251 -0
  150. package/dist/tools/web-tools.js.map +1 -0
  151. package/dist/utils/errors.d.ts +44 -0
  152. package/dist/utils/errors.d.ts.map +1 -0
  153. package/dist/utils/errors.js +130 -0
  154. package/dist/utils/errors.js.map +1 -0
  155. package/dist/utils/logger.d.ts +28 -0
  156. package/dist/utils/logger.d.ts.map +1 -0
  157. package/dist/utils/logger.js +121 -0
  158. package/dist/utils/logger.js.map +1 -0
  159. package/examples/basic-usage.ts +276 -0
  160. package/examples/code-reviewer.skill.md +83 -0
  161. package/examples/creative-writer.skill.md +80 -0
  162. package/examples/data-analyzer.skill.md +61 -0
  163. package/examples/hello-world.skill.md +36 -0
  164. package/examples/sample-skill.md +156 -0
  165. package/examples/summarizer.skill.md +62 -0
  166. package/examples/translator.skill.md +45 -0
  167. package/package.json +110 -0
package/dist/index.js ADDED
@@ -0,0 +1,275 @@
1
+ /**
2
+ * SkillKit — The open-source runtime for SKILL.md files
3
+ * Execute ClawHub's 10,700+ skills with any AI model, in any language, securely.
4
+ *
5
+ * @module skillkit
6
+ * @version 1.0.0
7
+ * @license MIT
8
+ * @author ArtefactForge <hello@artefactforge.ai>
9
+ * @see https://github.com/artefactforge/skillkit
10
+ */
11
+ // ─── Internal imports for SkillKit facade class ─────────────────────────────
12
+ import { parseSkillFile as _parseSkillFile, parseSkillContent as _parseSkillContent } from './core/parser.js';
13
+ import { SkillRunner as _SkillRunner } from './core/runtime.js';
14
+ import { getConfig as _getConfig } from './core/config.js';
15
+ import { SkillGuard as _SkillGuard } from './guard/index.js';
16
+ import { ToolRegistry as _ToolRegistry } from './tools/index.js';
17
+ import { ChannelManager as _ChannelManager } from './channels/index.js';
18
+ import { SandboxManager as _SandboxManager } from './sandbox/index.js';
19
+ import { Logger as _Logger } from './utils/logger.js';
20
+ import { ParseError as _ParseError, SecurityError as _SecurityError } from './utils/errors.js';
21
+ import { fetchSkill as _fetchSkill, searchSkills as _searchSkills } from './hub/index.js';
22
+ import { getInstalled as _getInstalled, installSkill as _registryInstallSkill, listInstalled as _listInstalled } from './hub/registry.js';
23
+ import { setLocale as _setLocale } from './i18n/index.js';
24
+ // ─── Core: Parser, Runtime, Types, Config ────────────────────────────────────
25
+ export { parseSkillFile, parseSkillContent, validateSkill, } from './core/parser.js';
26
+ export { SkillRunner, executeSkill, } from './core/runtime.js';
27
+ export { ConfigManager, getConfig, initializeConfig, resetConfig, } from './core/config.js';
28
+ export { ModelProvider, ThreatLevel, ChannelType, } from './core/types.js';
29
+ // ─── Model Router ────────────────────────────────────────────────────────────
30
+ export { ModelRouter, } from './router/index.js';
31
+ export { PROVIDER_REGISTRY, getProvider, getModel, listFreeModels, getModelsByCapability, } from './router/providers.js';
32
+ // ─── SkillGuard (Security Engine) ────────────────────────────────────────────
33
+ export { SkillGuard, } from './guard/index.js';
34
+ export { MALICIOUS_PATTERNS, getPatternsByCategory, getThreatLevel, } from './guard/patterns.js';
35
+ // ─── ClawHub Client ──────────────────────────────────────────────────────────
36
+ export { fetchSkill, searchSkills, listPopular, getSkillMetadata, clearCache, } from './hub/index.js';
37
+ export { installSkill as registryInstallSkill, getInstalled, listInstalled, removeSkill, updateSkill, } from './hub/registry.js';
38
+ // ─── Channel Adapters ────────────────────────────────────────────────────────
39
+ export { ChannelManager, BaseChannelAdapter, } from './channels/index.js';
40
+ export { WhatsAppAdapter, createWhatsAppAdapter } from './channels/whatsapp.js';
41
+ export { TelegramAdapter, createTelegramAdapter } from './channels/telegram.js';
42
+ export { DiscordAdapter, createDiscordAdapter } from './channels/discord.js';
43
+ export { SlackAdapter, createSlackAdapter } from './channels/slack.js';
44
+ // ─── Tool System ─────────────────────────────────────────────────────────────
45
+ export { ToolRegistry, } from './tools/index.js';
46
+ // Native web intelligence tools (no API keys required)
47
+ export { WebSearchTool, WebExtractTool, WebCrawlTool, WebResearchTool, WebMapTool, createWebTools, } from './tools/web-tools.js';
48
+ export { nativeSearch, nativeExtract, nativeCrawl, nativeResearch, nativeMap, } from './tools/web-engine.js';
49
+ // ─── Sandbox ─────────────────────────────────────────────────────────────────
50
+ export { SandboxManager, ProcessSandbox, DockerSandbox, } from './sandbox/index.js';
51
+ // ─── Utilities ───────────────────────────────────────────────────────────────
52
+ export { Logger, defaultLogger } from './utils/logger.js';
53
+ export { SkillKitError, ParseError, ModelError, SecurityError, ChannelError, HubError, SandboxError, ConfigError, ToolError, TimeoutError, formatError, formatErrorForCLI, } from './utils/errors.js';
54
+ // ─── i18n ────────────────────────────────────────────────────────────────────
55
+ export { t, setLocale, getLocale, getAvailableLocales } from './i18n/index.js';
56
+ // ─── Version ─────────────────────────────────────────────────────────────────
57
+ export const VERSION = '1.0.0';
58
+ export const CODENAME = 'ForgeOne';
59
+ /**
60
+ * Main SkillKit facade class
61
+ * Provides the high-level API for running skills, scanning for security,
62
+ * and managing the entire lifecycle.
63
+ *
64
+ * @example
65
+ * ```ts
66
+ * import { SkillKit } from 'skillkit';
67
+ *
68
+ * // Run a skill with DeepSeek (free)
69
+ * const result = await SkillKit.run('./my-skill.md', {
70
+ * model: 'deepseek-chat',
71
+ * provider: 'deepseek',
72
+ * input: 'Analyze my sales data',
73
+ * });
74
+ *
75
+ * // Security scan a skill before running
76
+ * const report = await SkillKit.scan('./untrusted-skill.md');
77
+ * if (report.overallStatus === 'APPROVED') {
78
+ * await SkillKit.run('./untrusted-skill.md');
79
+ * }
80
+ * ```
81
+ */
82
+ export class SkillKit {
83
+ constructor() {
84
+ this.logger = new _Logger();
85
+ this.toolRegistry = new _ToolRegistry();
86
+ this.channelManager = new _ChannelManager();
87
+ this.sandboxManager = new _SandboxManager();
88
+ this.guard = new _SkillGuard();
89
+ }
90
+ /** Get or create singleton instance */
91
+ static getInstance() {
92
+ if (!SkillKit.instance) {
93
+ SkillKit.instance = new SkillKit();
94
+ }
95
+ return SkillKit.instance;
96
+ }
97
+ /** Access the tool registry */
98
+ getTools() { return this.toolRegistry; }
99
+ /** Access the channel manager */
100
+ getChannels() { return this.channelManager; }
101
+ /** Access the sandbox manager */
102
+ getSandbox() { return this.sandboxManager; }
103
+ /** Access the logger */
104
+ getLogger() { return this.logger; }
105
+ /** Access SkillGuard security scanner */
106
+ getGuard() { return this.guard; }
107
+ /** Access SkillGuard security scanner */
108
+ getSecurityGuard() { return this.guard; }
109
+ /**
110
+ * Run a SKILL.md file with the specified model and options.
111
+ * Automatically scans for security threats before execution.
112
+ *
113
+ * @param skillPath - Path to SKILL.md file, ClawHub skill ID, or installed skill name
114
+ * @param options - Execution options (model, provider, input, etc.)
115
+ * @returns Execution result with output, token usage, and cost estimate
116
+ */
117
+ static async run(skillPath, options = {}) {
118
+ const instance = SkillKit.getInstance();
119
+ const { logger, guard } = instance;
120
+ logger.info(`SkillKit v${VERSION} — Running: ${skillPath}`);
121
+ // Step 1: Parse the skill
122
+ let skill;
123
+ try {
124
+ skill = _parseSkillFile(skillPath);
125
+ }
126
+ catch {
127
+ // Try loading from local registry
128
+ const installed = await _getInstalled(skillPath);
129
+ if (installed) {
130
+ skill = _parseSkillContent(installed.content);
131
+ }
132
+ else {
133
+ throw new _ParseError(`Could not load skill: ${skillPath}`);
134
+ }
135
+ }
136
+ // Step 2: Security scan (ALWAYS runs — cannot be skipped for safety)
137
+ const report = await guard.scanSkill(skill.body || '');
138
+ if (report.overallStatus === 'BLOCKED') {
139
+ throw new _SecurityError(`Skill blocked by SkillGuard: ${report.summary}`, { report });
140
+ }
141
+ if (report.overallStatus === 'REVIEW_REQUIRED') {
142
+ logger.warn(`Security warning: ${report.summary}`);
143
+ }
144
+ // Step 3: Configure model
145
+ const config = _getConfig();
146
+ const provider = options.provider || String(config.getConfig().defaultProvider) || 'anthropic';
147
+ const model = options.model || 'deepseek-chat';
148
+ // Step 4: Execute via SkillRunner
149
+ const runner = new _SkillRunner({
150
+ verbose: options.verbose,
151
+ });
152
+ const result = await runner.executeSkill(skillPath, { prompt: options.input || '' }, {
153
+ model,
154
+ provider: provider,
155
+ streaming: options.stream,
156
+ timeout: options.timeout ?? 120000,
157
+ });
158
+ logger.info(`Execution complete. Tokens: ${result.usage?.totalTokens || 'N/A'}`);
159
+ return result;
160
+ }
161
+ /**
162
+ * Security scan a SKILL.md file.
163
+ *
164
+ * @param target - Path to SKILL.md file or raw content string
165
+ * @returns Full security report with threats, score, and recommendations
166
+ */
167
+ static async scan(target) {
168
+ const instance = SkillKit.getInstance();
169
+ let content;
170
+ try {
171
+ // Try reading as file path
172
+ const { readFileSync } = await import('fs');
173
+ content = readFileSync(target, 'utf-8');
174
+ }
175
+ catch {
176
+ // Treat as raw content
177
+ content = target;
178
+ }
179
+ return instance.guard.scanSkill(content);
180
+ }
181
+ /**
182
+ * Search ClawHub for skills.
183
+ *
184
+ * @param query - Search query
185
+ * @param options - Search options (limit, safeOnly, etc.)
186
+ * @returns Array of matching skills from ClawHub
187
+ */
188
+ static async search(query, options) {
189
+ return _searchSkills(query, options);
190
+ }
191
+ /**
192
+ * Install a skill from ClawHub with automatic security scanning.
193
+ *
194
+ * @param skillId - ClawHub skill ID or URL
195
+ * @param options - Install options
196
+ * @returns Installation result
197
+ */
198
+ static async install(skillId, options) {
199
+ const instance = SkillKit.getInstance();
200
+ const { guard, logger } = instance;
201
+ logger.info(`Installing skill: ${skillId}`);
202
+ // Fetch from hub
203
+ const skillData = await _fetchSkill(skillId);
204
+ // Security scan (ALWAYS runs — blocked skills cannot be installed)
205
+ const report = await guard.scanSkill(skillData.content);
206
+ if (report.overallStatus === 'BLOCKED') {
207
+ throw new _SecurityError(`Skill blocked by SkillGuard (score: ${report.safetyScore}/100). This skill contains malicious patterns and CANNOT be installed.`, { report });
208
+ }
209
+ // Install to local registry
210
+ const parsed = _parseSkillContent(skillData.content);
211
+ const installed = await _registryInstallSkill(parsed.metadata.name, skillData.content, {
212
+ source: `clawhub://${skillId}`,
213
+ });
214
+ logger.info(`Skill installed: ${parsed.metadata.name}`);
215
+ return { name: parsed.metadata.name, version: parsed.metadata.version };
216
+ }
217
+ /** List all installed skills */
218
+ static async listSkills() {
219
+ return _listInstalled();
220
+ }
221
+ /** Get available AI tools formatted for Vercel AI SDK */
222
+ static getToolsForAI() {
223
+ const instance = SkillKit.getInstance();
224
+ return instance.toolRegistry.getToolsForVercelAI();
225
+ }
226
+ /** List registered tools */
227
+ static listTools() {
228
+ const instance = SkillKit.getInstance();
229
+ return instance.toolRegistry.listTools().map((t) => ({
230
+ name: t.name,
231
+ description: t.description,
232
+ }));
233
+ }
234
+ /** List active messaging channels */
235
+ static getActiveChannels() {
236
+ const instance = SkillKit.getInstance();
237
+ return instance.channelManager.getActiveChannels();
238
+ }
239
+ }
240
+ /**
241
+ * Initialize SkillKit with configuration options.
242
+ * Call this once at startup for optimal setup.
243
+ *
244
+ * @example
245
+ * ```ts
246
+ * const kit = await initializeSkillKit({
247
+ * verbose: true,
248
+ * toolsToLoad: ['tavily_search', 'file_read'],
249
+ * });
250
+ * ```
251
+ */
252
+ export async function initializeSkillKit(config) {
253
+ const kit = SkillKit.getInstance();
254
+ const logger = kit.getLogger();
255
+ if (config?.verbose) {
256
+ logger.setVerbose(true);
257
+ }
258
+ if (config?.locale) {
259
+ _setLocale(config.locale);
260
+ }
261
+ // Native web intelligence tools are auto-registered by ToolRegistry.
262
+ // No API keys needed — works out of the box.
263
+ const webActive = kit.getTools().isWebIntelligenceActive();
264
+ if (webActive) {
265
+ logger.info('Native web intelligence: ACTIVE (search, extract, crawl, research, map) — zero API keys required');
266
+ }
267
+ else {
268
+ logger.warn('Native web intelligence: FAILED to register — check node-fetch dependency');
269
+ }
270
+ logger.info(`SkillKit v${VERSION} (${CODENAME}) initialized`);
271
+ return kit;
272
+ }
273
+ // ─── Convenience singleton ───────────────────────────────────────────────────
274
+ export const skillkit = SkillKit.getInstance();
275
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ import { LanguageModelV1 } from "ai";
2
+ export interface ModelConfig {
3
+ provider: string;
4
+ model: string;
5
+ apiKey?: string;
6
+ baseUrl?: string;
7
+ temperature?: number;
8
+ maxTokens?: number;
9
+ topP?: number;
10
+ frequencyPenalty?: number;
11
+ presencePenalty?: number;
12
+ }
13
+ export interface SkillRequirements {
14
+ minContextWindow?: number;
15
+ requiresVision?: boolean;
16
+ requiresTools?: boolean;
17
+ requiresStreaming?: boolean;
18
+ preferredProviders?: string[];
19
+ maxCostPerMTok?: number;
20
+ }
21
+ export interface ModelInstance {
22
+ id: string;
23
+ provider: string;
24
+ model: string;
25
+ instance: LanguageModelV1;
26
+ contextWindow: number;
27
+ maxOutput: number;
28
+ costPer1kTokens: number;
29
+ }
30
+ export interface CostEstimate {
31
+ provider: string;
32
+ model: string;
33
+ inputTokens: number;
34
+ outputTokens: number;
35
+ estimatedCost: number;
36
+ currency: string;
37
+ }
38
+ export declare class ModelRouter {
39
+ private models;
40
+ private modelMetadata;
41
+ private apiKeys;
42
+ private fallbackChain;
43
+ constructor(config?: Record<string, ModelConfig>);
44
+ private initializeApiKeys;
45
+ private setupFallbackChain;
46
+ createModelInstance(provider: string, model: string, overrideConfig?: Partial<ModelConfig>): Promise<ModelInstance>;
47
+ private createProviderInstance;
48
+ routeToModel(skillRequirements: SkillRequirements, userPreferences?: Partial<ModelConfig>): Promise<ModelInstance>;
49
+ private findSuitableModels;
50
+ generateResponse(modelInstance: ModelInstance, prompt: string, systemPrompt?: string, options?: {
51
+ temperature?: number;
52
+ maxTokens?: number;
53
+ }): Promise<string>;
54
+ streamResponse(modelInstance: ModelInstance, prompt: string, systemPrompt?: string, options?: {
55
+ temperature?: number;
56
+ maxTokens?: number;
57
+ onChunk?: (chunk: string) => void;
58
+ }): Promise<string>;
59
+ estimateCost(modelInstance: ModelInstance, inputTokens: number, outputTokens: number): CostEstimate;
60
+ getAvailableModels(): Array<{
61
+ provider: string;
62
+ models: Array<{
63
+ id: string;
64
+ name: string;
65
+ contextWindow: number;
66
+ costPer1kTokens: number;
67
+ }>;
68
+ }>;
69
+ listFreeModels(): Array<{
70
+ provider: string;
71
+ model: string;
72
+ name: string;
73
+ }>;
74
+ validateApiKey(provider: string, apiKey: string): Promise<boolean>;
75
+ setFallbackChain(providers: string[]): void;
76
+ getFallbackChain(): string[];
77
+ }
78
+ export declare function createModel(config: ModelConfig): Promise<ModelInstance>;
79
+ export declare function getAvailableModels(): Array<{
80
+ provider: string;
81
+ models: Array<{
82
+ id: string;
83
+ name: string;
84
+ contextWindow: number;
85
+ costPer1kTokens: number;
86
+ }>;
87
+ }>;
88
+ export default ModelRouter;
89
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/router/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,292 @@
1
+ import { generateText, streamText, } from "ai";
2
+ import { createOpenAI } from "@ai-sdk/openai";
3
+ import { createAnthropic } from "@ai-sdk/anthropic";
4
+ import { createGoogleGenerativeAI } from "@ai-sdk/google";
5
+ import { createOllama } from "ollama-ai-provider";
6
+ import { PROVIDER_REGISTRY } from "./providers.js";
7
+ export class ModelRouter {
8
+ constructor(config = {}) {
9
+ this.models = new Map();
10
+ this.modelMetadata = new Map();
11
+ this.apiKeys = {};
12
+ this.fallbackChain = [];
13
+ this.initializeApiKeys(config);
14
+ this.setupFallbackChain(config);
15
+ }
16
+ initializeApiKeys(config) {
17
+ for (const [key, modelConfig] of Object.entries(config)) {
18
+ if (modelConfig.apiKey) {
19
+ this.apiKeys[modelConfig.provider] = modelConfig.apiKey;
20
+ }
21
+ else if (process.env[`${modelConfig.provider.toUpperCase()}_API_KEY`]) {
22
+ this.apiKeys[modelConfig.provider] = process.env[`${modelConfig.provider.toUpperCase()}_API_KEY`];
23
+ }
24
+ }
25
+ }
26
+ setupFallbackChain(config) {
27
+ const priorityOrder = [
28
+ "anthropic",
29
+ "openai",
30
+ "google",
31
+ "groq",
32
+ "deepseek",
33
+ "together",
34
+ "fireworks",
35
+ "qwen",
36
+ "ollama",
37
+ ];
38
+ this.fallbackChain = priorityOrder.filter((provider) => Object.values(config).some((c) => c.provider === provider));
39
+ }
40
+ async createModelInstance(provider, model, overrideConfig) {
41
+ const cacheKey = `${provider}:${model}`;
42
+ if (this.models.has(cacheKey)) {
43
+ const instance = this.models.get(cacheKey);
44
+ const metadata = this.modelMetadata.get(cacheKey);
45
+ return {
46
+ id: cacheKey,
47
+ provider,
48
+ model,
49
+ instance,
50
+ contextWindow: metadata.contextWindow,
51
+ maxOutput: metadata.maxOutput,
52
+ costPer1kTokens: metadata.costPer1kTokens,
53
+ };
54
+ }
55
+ const providerData = PROVIDER_REGISTRY[provider];
56
+ if (!providerData) {
57
+ throw new Error(`Unknown provider: ${provider}`);
58
+ }
59
+ const modelData = providerData.models.find((m) => m.id === model);
60
+ if (!modelData) {
61
+ throw new Error(`Unknown model: ${model} for provider: ${provider}`);
62
+ }
63
+ const apiKey = overrideConfig?.apiKey ||
64
+ this.apiKeys[provider] ||
65
+ process.env[`${provider.toUpperCase()}_API_KEY`];
66
+ if (providerData.requiresApiKey && !apiKey) {
67
+ throw new Error(`API key required for ${provider}. Set ${provider.toUpperCase()}_API_KEY environment variable.`);
68
+ }
69
+ const instance = this.createProviderInstance(provider, model, apiKey, overrideConfig);
70
+ this.models.set(cacheKey, instance);
71
+ this.modelMetadata.set(cacheKey, modelData);
72
+ return {
73
+ id: cacheKey,
74
+ provider,
75
+ model,
76
+ instance,
77
+ contextWindow: modelData.contextWindow,
78
+ maxOutput: modelData.maxOutput,
79
+ costPer1kTokens: modelData.costPer1kTokens,
80
+ };
81
+ }
82
+ createProviderInstance(provider, model, apiKey, config) {
83
+ // Generation params (temperature, maxTokens, etc.) are passed to
84
+ // generateText/streamText, NOT to the model constructor.
85
+ switch (provider.toLowerCase()) {
86
+ case "openai": {
87
+ const client = createOpenAI({
88
+ apiKey: apiKey || process.env.OPENAI_API_KEY,
89
+ });
90
+ return client(model);
91
+ }
92
+ case "anthropic": {
93
+ const client = createAnthropic({
94
+ apiKey: apiKey || process.env.ANTHROPIC_API_KEY,
95
+ });
96
+ return client(model);
97
+ }
98
+ case "google": {
99
+ const client = createGoogleGenerativeAI({
100
+ apiKey: apiKey || process.env.GOOGLE_API_KEY,
101
+ });
102
+ return client(model);
103
+ }
104
+ case "ollama": {
105
+ const baseURL = config?.baseUrl || "http://localhost:11434";
106
+ return createOllama({ baseURL })(model);
107
+ }
108
+ case "deepseek": {
109
+ const client = createOpenAI({
110
+ apiKey: apiKey || process.env.DEEPSEEK_API_KEY,
111
+ baseURL: config?.baseUrl || "https://api.deepseek.com/beta",
112
+ });
113
+ return client(model);
114
+ }
115
+ case "qwen": {
116
+ const client = createOpenAI({
117
+ apiKey: apiKey || process.env.QWEN_API_KEY,
118
+ baseURL: config?.baseUrl || "https://dashscope.aliyuncs.com/compatible-mode/v1",
119
+ });
120
+ return client(model);
121
+ }
122
+ case "groq": {
123
+ const client = createOpenAI({
124
+ apiKey: apiKey || process.env.GROQ_API_KEY,
125
+ baseURL: config?.baseUrl || "https://api.groq.com/openai/v1",
126
+ });
127
+ return client(model);
128
+ }
129
+ case "together": {
130
+ const client = createOpenAI({
131
+ apiKey: apiKey || process.env.TOGETHER_API_KEY,
132
+ baseURL: config?.baseUrl || "https://api.together.xyz/v1",
133
+ });
134
+ return client(model);
135
+ }
136
+ case "fireworks": {
137
+ const client = createOpenAI({
138
+ apiKey: apiKey || process.env.FIREWORKS_API_KEY,
139
+ baseURL: config?.baseUrl || "https://api.fireworks.ai/inference/v1",
140
+ });
141
+ return client(model);
142
+ }
143
+ case "kimi": {
144
+ const client = createOpenAI({
145
+ apiKey: apiKey || process.env.KIMI_API_KEY || process.env.MOONSHOT_API_KEY,
146
+ baseURL: config?.baseUrl || "https://api.moonshot.cn/v1",
147
+ });
148
+ return client(model);
149
+ }
150
+ case "zhipu": {
151
+ const client = createOpenAI({
152
+ apiKey: apiKey || process.env.ZHIPU_API_KEY,
153
+ baseURL: config?.baseUrl || "https://open.bigmodel.cn/api/paas/v4",
154
+ });
155
+ return client(model);
156
+ }
157
+ default:
158
+ throw new Error(`Unsupported provider: ${provider}`);
159
+ }
160
+ }
161
+ async routeToModel(skillRequirements, userPreferences) {
162
+ const candidates = this.findSuitableModels(skillRequirements);
163
+ if (candidates.length === 0) {
164
+ throw new Error("No suitable model found matching the skill requirements");
165
+ }
166
+ const selectedProvider = skillRequirements.preferredProviders?.[0] ||
167
+ candidates[0].provider || ["anthropic", "openai"][0];
168
+ const selectedModel = candidates.find((c) => c.provider === selectedProvider) || candidates[0];
169
+ return this.createModelInstance(selectedModel.provider, selectedModel.model, userPreferences);
170
+ }
171
+ findSuitableModels(requirements) {
172
+ const results = [];
173
+ for (const [providerName, providerData] of Object.entries(PROVIDER_REGISTRY)) {
174
+ for (const model of providerData.models) {
175
+ const matches = (!requirements.minContextWindow ||
176
+ model.contextWindow >= requirements.minContextWindow) &&
177
+ (!requirements.requiresVision ||
178
+ model.capabilities?.vision) &&
179
+ (!requirements.requiresTools ||
180
+ model.capabilities?.tools) &&
181
+ (!requirements.requiresStreaming ||
182
+ model.capabilities?.streaming) &&
183
+ (!requirements.maxCostPerMTok ||
184
+ model.costPer1kTokens <= requirements.maxCostPerMTok);
185
+ if (matches) {
186
+ results.push({
187
+ provider: providerName,
188
+ model: model.id,
189
+ });
190
+ }
191
+ }
192
+ }
193
+ return results;
194
+ }
195
+ async generateResponse(modelInstance, prompt, systemPrompt, options) {
196
+ const messages = [{ role: "user", content: prompt }];
197
+ const result = await generateText({
198
+ model: modelInstance.instance,
199
+ system: systemPrompt,
200
+ messages,
201
+ temperature: options?.temperature,
202
+ maxTokens: options?.maxTokens,
203
+ });
204
+ return result.text;
205
+ }
206
+ async streamResponse(modelInstance, prompt, systemPrompt, options) {
207
+ const messages = [{ role: "user", content: prompt }];
208
+ const stream = await streamText({
209
+ model: modelInstance.instance,
210
+ system: systemPrompt,
211
+ messages,
212
+ temperature: options?.temperature,
213
+ maxTokens: options?.maxTokens,
214
+ });
215
+ let fullText = "";
216
+ for await (const chunk of stream.textStream) {
217
+ fullText += chunk;
218
+ options?.onChunk?.(chunk);
219
+ }
220
+ return fullText;
221
+ }
222
+ estimateCost(modelInstance, inputTokens, outputTokens) {
223
+ const inputCost = (inputTokens / 1000) * modelInstance.costPer1kTokens;
224
+ const outputCost = (outputTokens / 1000) * modelInstance.costPer1kTokens;
225
+ return {
226
+ provider: modelInstance.provider,
227
+ model: modelInstance.model,
228
+ inputTokens,
229
+ outputTokens,
230
+ estimatedCost: inputCost + outputCost,
231
+ currency: "USD",
232
+ };
233
+ }
234
+ getAvailableModels() {
235
+ return Object.entries(PROVIDER_REGISTRY).map(([provider, data]) => ({
236
+ provider,
237
+ models: data.models.map((m) => ({
238
+ id: m.id,
239
+ name: m.name,
240
+ contextWindow: m.contextWindow,
241
+ costPer1kTokens: m.costPer1kTokens,
242
+ })),
243
+ }));
244
+ }
245
+ listFreeModels() {
246
+ const freeModels = [];
247
+ for (const [providerName, providerData] of Object.entries(PROVIDER_REGISTRY)) {
248
+ if (providerData.freeTier) {
249
+ for (const model of providerData.models) {
250
+ if (model.costPer1kTokens === 0 || model.costPer1kTokens < 0.0001) {
251
+ freeModels.push({
252
+ provider: providerName,
253
+ model: model.id,
254
+ name: model.name,
255
+ });
256
+ }
257
+ }
258
+ }
259
+ }
260
+ return freeModels;
261
+ }
262
+ async validateApiKey(provider, apiKey) {
263
+ try {
264
+ const instance = await this.createModelInstance(provider, PROVIDER_REGISTRY[provider]?.models[0]?.id || "default", { apiKey });
265
+ await generateText({
266
+ model: instance.instance,
267
+ prompt: "Test",
268
+ maxTokens: 1,
269
+ });
270
+ return true;
271
+ }
272
+ catch {
273
+ return false;
274
+ }
275
+ }
276
+ setFallbackChain(providers) {
277
+ this.fallbackChain = providers.filter((p) => Object.keys(PROVIDER_REGISTRY).includes(p));
278
+ }
279
+ getFallbackChain() {
280
+ return this.fallbackChain;
281
+ }
282
+ }
283
+ export async function createModel(config) {
284
+ const router = new ModelRouter();
285
+ return router.createModelInstance(config.provider, config.model, config);
286
+ }
287
+ export function getAvailableModels() {
288
+ const router = new ModelRouter();
289
+ return router.getAvailableModels();
290
+ }
291
+ export default ModelRouter;
292
+ //# sourceMappingURL=index.js.map