@agentplugged/claw 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 (149) hide show
  1. package/dist/cli.d.ts +11 -0
  2. package/dist/cli.d.ts.map +1 -0
  3. package/dist/cli.js +111 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/config.d.ts +29 -0
  6. package/dist/config.d.ts.map +1 -0
  7. package/dist/config.js +94 -0
  8. package/dist/config.js.map +1 -0
  9. package/dist/index.d.ts +17 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +54 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/memory/capture.d.ts +13 -0
  14. package/dist/memory/capture.d.ts.map +1 -0
  15. package/dist/memory/capture.js +102 -0
  16. package/dist/memory/capture.js.map +1 -0
  17. package/dist/memory/db.d.ts +56 -0
  18. package/dist/memory/db.d.ts.map +1 -0
  19. package/dist/memory/db.js +206 -0
  20. package/dist/memory/db.js.map +1 -0
  21. package/dist/memory/index.d.ts +8 -0
  22. package/dist/memory/index.d.ts.map +1 -0
  23. package/dist/memory/index.js +42 -0
  24. package/dist/memory/index.js.map +1 -0
  25. package/dist/memory/llm-extract.d.ts +13 -0
  26. package/dist/memory/llm-extract.d.ts.map +1 -0
  27. package/dist/memory/llm-extract.js +135 -0
  28. package/dist/memory/llm-extract.js.map +1 -0
  29. package/dist/memory/recall.d.ts +16 -0
  30. package/dist/memory/recall.d.ts.map +1 -0
  31. package/dist/memory/recall.js +131 -0
  32. package/dist/memory/recall.js.map +1 -0
  33. package/dist/observability/collector.d.ts +40 -0
  34. package/dist/observability/collector.d.ts.map +1 -0
  35. package/dist/observability/collector.js +119 -0
  36. package/dist/observability/collector.js.map +1 -0
  37. package/dist/observability/db.d.ts +60 -0
  38. package/dist/observability/db.d.ts.map +1 -0
  39. package/dist/observability/db.js +189 -0
  40. package/dist/observability/db.js.map +1 -0
  41. package/dist/observability/index.d.ts +7 -0
  42. package/dist/observability/index.d.ts.map +1 -0
  43. package/dist/observability/index.js +35 -0
  44. package/dist/observability/index.js.map +1 -0
  45. package/dist/observability/queries.d.ts +54 -0
  46. package/dist/observability/queries.d.ts.map +1 -0
  47. package/dist/observability/queries.js +181 -0
  48. package/dist/observability/queries.js.map +1 -0
  49. package/dist/router/classifier.d.ts +8 -0
  50. package/dist/router/classifier.d.ts.map +1 -0
  51. package/dist/router/classifier.js +90 -0
  52. package/dist/router/classifier.js.map +1 -0
  53. package/dist/router/fallback.d.ts +18 -0
  54. package/dist/router/fallback.d.ts.map +1 -0
  55. package/dist/router/fallback.js +102 -0
  56. package/dist/router/fallback.js.map +1 -0
  57. package/dist/router/index.d.ts +5 -0
  58. package/dist/router/index.d.ts.map +1 -0
  59. package/dist/router/index.js +214 -0
  60. package/dist/router/index.js.map +1 -0
  61. package/dist/router/leak-detector.d.ts +33 -0
  62. package/dist/router/leak-detector.d.ts.map +1 -0
  63. package/dist/router/leak-detector.js +320 -0
  64. package/dist/router/leak-detector.js.map +1 -0
  65. package/dist/router/logger.d.ts +18 -0
  66. package/dist/router/logger.d.ts.map +1 -0
  67. package/dist/router/logger.js +130 -0
  68. package/dist/router/logger.js.map +1 -0
  69. package/dist/router/models.d.ts +5 -0
  70. package/dist/router/models.d.ts.map +1 -0
  71. package/dist/router/models.js +96 -0
  72. package/dist/router/models.js.map +1 -0
  73. package/dist/router/providers.d.ts +4 -0
  74. package/dist/router/providers.d.ts.map +1 -0
  75. package/dist/router/providers.js +323 -0
  76. package/dist/router/providers.js.map +1 -0
  77. package/dist/router/strategy.d.ts +29 -0
  78. package/dist/router/strategy.d.ts.map +1 -0
  79. package/dist/router/strategy.js +169 -0
  80. package/dist/router/strategy.js.map +1 -0
  81. package/dist/router/types.d.ts +63 -0
  82. package/dist/router/types.d.ts.map +1 -0
  83. package/dist/router/types.js +3 -0
  84. package/dist/router/types.js.map +1 -0
  85. package/dist/sidecar/auth.d.ts +7 -0
  86. package/dist/sidecar/auth.d.ts.map +1 -0
  87. package/dist/sidecar/auth.js +36 -0
  88. package/dist/sidecar/auth.js.map +1 -0
  89. package/dist/sidecar/index.d.ts +2 -0
  90. package/dist/sidecar/index.d.ts.map +1 -0
  91. package/dist/sidecar/index.js +336 -0
  92. package/dist/sidecar/index.js.map +1 -0
  93. package/dist/sidecar/routes/addons.d.ts +6 -0
  94. package/dist/sidecar/routes/addons.d.ts.map +1 -0
  95. package/dist/sidecar/routes/addons.js +332 -0
  96. package/dist/sidecar/routes/addons.js.map +1 -0
  97. package/dist/sidecar/routes/backup.d.ts +7 -0
  98. package/dist/sidecar/routes/backup.d.ts.map +1 -0
  99. package/dist/sidecar/routes/backup.js +204 -0
  100. package/dist/sidecar/routes/backup.js.map +1 -0
  101. package/dist/sidecar/routes/channels.d.ts +4 -0
  102. package/dist/sidecar/routes/channels.d.ts.map +1 -0
  103. package/dist/sidecar/routes/channels.js +120 -0
  104. package/dist/sidecar/routes/channels.js.map +1 -0
  105. package/dist/sidecar/routes/health.d.ts +5 -0
  106. package/dist/sidecar/routes/health.d.ts.map +1 -0
  107. package/dist/sidecar/routes/health.js +28 -0
  108. package/dist/sidecar/routes/health.js.map +1 -0
  109. package/dist/sidecar/routes/memory.d.ts +7 -0
  110. package/dist/sidecar/routes/memory.d.ts.map +1 -0
  111. package/dist/sidecar/routes/memory.js +234 -0
  112. package/dist/sidecar/routes/memory.js.map +1 -0
  113. package/dist/sidecar/routes/metrics.d.ts +5 -0
  114. package/dist/sidecar/routes/metrics.d.ts.map +1 -0
  115. package/dist/sidecar/routes/metrics.js +273 -0
  116. package/dist/sidecar/routes/metrics.js.map +1 -0
  117. package/dist/sidecar/routes/restart.d.ts +4 -0
  118. package/dist/sidecar/routes/restart.d.ts.map +1 -0
  119. package/dist/sidecar/routes/restart.js +81 -0
  120. package/dist/sidecar/routes/restart.js.map +1 -0
  121. package/dist/sidecar/routes/router-config.d.ts +5 -0
  122. package/dist/sidecar/routes/router-config.d.ts.map +1 -0
  123. package/dist/sidecar/routes/router-config.js +150 -0
  124. package/dist/sidecar/routes/router-config.js.map +1 -0
  125. package/dist/sidecar/routes/security.d.ts +8 -0
  126. package/dist/sidecar/routes/security.d.ts.map +1 -0
  127. package/dist/sidecar/routes/security.js +308 -0
  128. package/dist/sidecar/routes/security.js.map +1 -0
  129. package/dist/sidecar/routes/skills.d.ts +5 -0
  130. package/dist/sidecar/routes/skills.d.ts.map +1 -0
  131. package/dist/sidecar/routes/skills.js +146 -0
  132. package/dist/sidecar/routes/skills.js.map +1 -0
  133. package/dist/sidecar/routes/soul.d.ts +4 -0
  134. package/dist/sidecar/routes/soul.d.ts.map +1 -0
  135. package/dist/sidecar/routes/soul.js +115 -0
  136. package/dist/sidecar/routes/soul.js.map +1 -0
  137. package/dist/sidecar/routes/team.d.ts +4 -0
  138. package/dist/sidecar/routes/team.d.ts.map +1 -0
  139. package/dist/sidecar/routes/team.js +139 -0
  140. package/dist/sidecar/routes/team.js.map +1 -0
  141. package/dist/sidecar/routes/update.d.ts +4 -0
  142. package/dist/sidecar/routes/update.d.ts.map +1 -0
  143. package/dist/sidecar/routes/update.js +96 -0
  144. package/dist/sidecar/routes/update.js.map +1 -0
  145. package/dist/sidecar/utils.d.ts +9 -0
  146. package/dist/sidecar/utils.d.ts.map +1 -0
  147. package/dist/sidecar/utils.js +57 -0
  148. package/dist/sidecar/utils.js.map +1 -0
  149. package/package.json +45 -0
@@ -0,0 +1,323 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.forwardToProvider = forwardToProvider;
4
+ // ---------------------------------------------------------------------------
5
+ // Helpers — OpenAI → Anthropic conversion
6
+ // ---------------------------------------------------------------------------
7
+ function openAiMessagesToAnthropic(messages) {
8
+ let system;
9
+ const converted = [];
10
+ for (const msg of messages) {
11
+ if (msg.role === "system") {
12
+ system = msg.content;
13
+ continue;
14
+ }
15
+ if (msg.role === "user" || msg.role === "assistant") {
16
+ if (msg.tool_calls && msg.tool_calls.length > 0) {
17
+ // Assistant message with tool calls
18
+ const content = msg.content
19
+ ? [{ type: "text", text: msg.content }]
20
+ : [];
21
+ for (const tc of msg.tool_calls) {
22
+ content.push({
23
+ type: "tool_use",
24
+ id: tc.id,
25
+ name: tc.function.name,
26
+ input: JSON.parse(tc.function.arguments || "{}"),
27
+ });
28
+ }
29
+ converted.push({ role: "assistant", content });
30
+ }
31
+ else {
32
+ converted.push({ role: msg.role, content: msg.content });
33
+ }
34
+ }
35
+ if (msg.role === "tool") {
36
+ // Tool result — must follow an assistant message
37
+ const toolResult = {
38
+ type: "tool_result",
39
+ id: msg.tool_call_id,
40
+ text: msg.content,
41
+ };
42
+ // Append to a user message
43
+ converted.push({ role: "user", content: [toolResult] });
44
+ }
45
+ }
46
+ return { system, messages: converted };
47
+ }
48
+ function anthropicResponseToOpenAi(response, requestedModel) {
49
+ let text = "";
50
+ const toolCalls = [];
51
+ for (const block of response.content) {
52
+ if (block.type === "text" && block.text) {
53
+ text += block.text;
54
+ }
55
+ else if (block.type === "tool_use" && block.id && block.name) {
56
+ toolCalls.push({
57
+ id: block.id,
58
+ type: "function",
59
+ function: {
60
+ name: block.name,
61
+ arguments: JSON.stringify(block.input ?? {}),
62
+ },
63
+ });
64
+ }
65
+ }
66
+ const message = {
67
+ role: "assistant",
68
+ content: text,
69
+ };
70
+ if (toolCalls.length > 0) {
71
+ message.tool_calls = toolCalls;
72
+ }
73
+ return {
74
+ id: response.id,
75
+ object: "chat.completion",
76
+ created: Math.floor(Date.now() / 1000),
77
+ model: requestedModel,
78
+ choices: [
79
+ {
80
+ index: 0,
81
+ message,
82
+ finish_reason: response.stop_reason ?? "stop",
83
+ },
84
+ ],
85
+ usage: {
86
+ prompt_tokens: response.usage.input_tokens,
87
+ completion_tokens: response.usage.output_tokens,
88
+ total_tokens: response.usage.input_tokens + response.usage.output_tokens,
89
+ },
90
+ };
91
+ }
92
+ // ---------------------------------------------------------------------------
93
+ // Anthropic provider
94
+ // ---------------------------------------------------------------------------
95
+ async function forwardToAnthropic(provider, model, request) {
96
+ const { system, messages } = openAiMessagesToAnthropic(request.messages);
97
+ const body = {
98
+ model: model.id,
99
+ max_tokens: request.max_tokens ?? model.maxTokens,
100
+ messages,
101
+ };
102
+ if (system)
103
+ body.system = system;
104
+ if (request.temperature !== undefined)
105
+ body.temperature = request.temperature;
106
+ if (request.tools && request.tools.length > 0) {
107
+ body.tools = request.tools.map((t) => ({
108
+ name: t.function.name,
109
+ description: t.function.description,
110
+ input_schema: t.function.parameters ?? {
111
+ type: "object",
112
+ properties: {},
113
+ },
114
+ }));
115
+ }
116
+ const response = await fetch("https://api.anthropic.com/v1/messages", {
117
+ method: "POST",
118
+ headers: {
119
+ "Content-Type": "application/json",
120
+ "x-api-key": provider.apiKey,
121
+ "anthropic-version": "2023-06-01",
122
+ },
123
+ body: JSON.stringify(body),
124
+ });
125
+ if (!response.ok) {
126
+ const errorText = await response.text();
127
+ throw new Error(`Anthropic API error ${response.status}: ${errorText}`);
128
+ }
129
+ const data = (await response.json());
130
+ return anthropicResponseToOpenAi(data, model.id);
131
+ }
132
+ // ---------------------------------------------------------------------------
133
+ // Helpers — OpenAI → Google Gemini conversion
134
+ // ---------------------------------------------------------------------------
135
+ function openAiMessagesToGemini(messages) {
136
+ let systemInstruction;
137
+ const contents = [];
138
+ for (const msg of messages) {
139
+ if (msg.role === "system") {
140
+ systemInstruction = msg.content;
141
+ continue;
142
+ }
143
+ if (msg.role === "user") {
144
+ contents.push({
145
+ role: "user",
146
+ parts: [{ text: msg.content }],
147
+ });
148
+ continue;
149
+ }
150
+ if (msg.role === "assistant") {
151
+ const parts = [];
152
+ if (msg.content) {
153
+ parts.push({ text: msg.content });
154
+ }
155
+ if (msg.tool_calls && msg.tool_calls.length > 0) {
156
+ for (const tc of msg.tool_calls) {
157
+ parts.push({
158
+ functionCall: {
159
+ name: tc.function.name,
160
+ args: JSON.parse(tc.function.arguments || "{}"),
161
+ },
162
+ });
163
+ }
164
+ }
165
+ contents.push({ role: "model", parts });
166
+ continue;
167
+ }
168
+ if (msg.role === "tool") {
169
+ // Tool result — append as a user turn with functionResponse
170
+ contents.push({
171
+ role: "user",
172
+ parts: [
173
+ {
174
+ functionResponse: {
175
+ name: msg.tool_call_id ?? "unknown",
176
+ response: { content: msg.content },
177
+ },
178
+ },
179
+ ],
180
+ });
181
+ }
182
+ }
183
+ return { systemInstruction, contents };
184
+ }
185
+ function geminiResponseToOpenAi(response, requestedModel) {
186
+ const candidate = response.candidates[0];
187
+ let text = "";
188
+ const toolCalls = [];
189
+ for (const part of candidate.content.parts) {
190
+ if (part.text) {
191
+ text += part.text;
192
+ }
193
+ else if (part.functionCall) {
194
+ toolCalls.push({
195
+ id: `call_${part.functionCall.name}_${Date.now()}`,
196
+ type: "function",
197
+ function: {
198
+ name: part.functionCall.name,
199
+ arguments: JSON.stringify(part.functionCall.args ?? {}),
200
+ },
201
+ });
202
+ }
203
+ }
204
+ const message = {
205
+ role: "assistant",
206
+ content: text,
207
+ };
208
+ if (toolCalls.length > 0) {
209
+ message.tool_calls = toolCalls;
210
+ }
211
+ // Gemini finish reasons: STOP, MAX_TOKENS, SAFETY, RECITATION, OTHER
212
+ const finishReason = candidate.finishReason === "MAX_TOKENS"
213
+ ? "length"
214
+ : "stop";
215
+ return {
216
+ id: `gemini-${Date.now()}`,
217
+ object: "chat.completion",
218
+ created: Math.floor(Date.now() / 1000),
219
+ model: requestedModel,
220
+ choices: [
221
+ {
222
+ index: 0,
223
+ message,
224
+ finish_reason: finishReason,
225
+ },
226
+ ],
227
+ usage: {
228
+ prompt_tokens: response.usageMetadata.promptTokenCount,
229
+ completion_tokens: response.usageMetadata.candidatesTokenCount,
230
+ total_tokens: response.usageMetadata.totalTokenCount,
231
+ },
232
+ };
233
+ }
234
+ // ---------------------------------------------------------------------------
235
+ // Google provider
236
+ // ---------------------------------------------------------------------------
237
+ async function forwardToGoogle(provider, model, request) {
238
+ const { systemInstruction, contents } = openAiMessagesToGemini(request.messages);
239
+ const body = {
240
+ contents,
241
+ };
242
+ if (systemInstruction) {
243
+ body.systemInstruction = { parts: [{ text: systemInstruction }] };
244
+ }
245
+ const generationConfig = {};
246
+ if (request.max_tokens !== undefined) {
247
+ generationConfig.maxOutputTokens = request.max_tokens;
248
+ }
249
+ else {
250
+ generationConfig.maxOutputTokens = model.maxTokens;
251
+ }
252
+ if (request.temperature !== undefined) {
253
+ generationConfig.temperature = request.temperature;
254
+ }
255
+ body.generationConfig = generationConfig;
256
+ if (request.tools && request.tools.length > 0) {
257
+ body.tools = [
258
+ {
259
+ functionDeclarations: request.tools.map((t) => ({
260
+ name: t.function.name,
261
+ description: t.function.description,
262
+ parameters: t.function.parameters ?? {
263
+ type: "object",
264
+ properties: {},
265
+ },
266
+ })),
267
+ },
268
+ ];
269
+ }
270
+ const url = `https://generativelanguage.googleapis.com/v1beta/models/${model.id}:generateContent?key=${provider.apiKey}`;
271
+ const response = await fetch(url, {
272
+ method: "POST",
273
+ headers: {
274
+ "Content-Type": "application/json",
275
+ },
276
+ body: JSON.stringify(body),
277
+ });
278
+ if (!response.ok) {
279
+ const errorText = await response.text();
280
+ throw new Error(`Google Gemini API error ${response.status}: ${errorText}`);
281
+ }
282
+ const data = (await response.json());
283
+ return geminiResponseToOpenAi(data, model.id);
284
+ }
285
+ // ---------------------------------------------------------------------------
286
+ // OpenAI provider
287
+ // ---------------------------------------------------------------------------
288
+ async function forwardToOpenAi(provider, model, request) {
289
+ const body = {
290
+ ...request,
291
+ model: model.id,
292
+ stream: false, // V1: no streaming
293
+ };
294
+ const response = await fetch("https://api.openai.com/v1/chat/completions", {
295
+ method: "POST",
296
+ headers: {
297
+ "Content-Type": "application/json",
298
+ Authorization: `Bearer ${provider.apiKey}`,
299
+ },
300
+ body: JSON.stringify(body),
301
+ });
302
+ if (!response.ok) {
303
+ const errorText = await response.text();
304
+ throw new Error(`OpenAI API error ${response.status}: ${errorText}`);
305
+ }
306
+ return (await response.json());
307
+ }
308
+ // ---------------------------------------------------------------------------
309
+ // Main dispatcher
310
+ // ---------------------------------------------------------------------------
311
+ async function forwardToProvider(provider, model, request) {
312
+ switch (provider.name) {
313
+ case "anthropic":
314
+ return forwardToAnthropic(provider, model, request);
315
+ case "openai":
316
+ return forwardToOpenAi(provider, model, request);
317
+ case "google":
318
+ return forwardToGoogle(provider, model, request);
319
+ default:
320
+ throw new Error(`Unknown provider "${provider.name}". Supported: anthropic, openai, google`);
321
+ }
322
+ }
323
+ //# sourceMappingURL=providers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.js","sourceRoot":"","sources":["../../src/router/providers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { ModelConfig, ProviderConfig } from "../config";
2
+ import { Complexity } from "./classifier";
3
+ export type Strategy = "economy" | "balanced" | "quality" | "speed" | "custom";
4
+ export interface SkillRoutingRule {
5
+ /** Glob pattern ou nom exact du skill (supporte * comme wildcard simple). */
6
+ skillPattern: string;
7
+ /** Model id exact à utiliser si cette règle matche. Prioritaire sur preferredTier. */
8
+ preferredModel?: string;
9
+ /** Tier à utiliser si cette règle matche et qu'aucun preferredModel n'est défini. */
10
+ preferredTier?: "economy" | "standard" | "premium";
11
+ /** Coût maximum accepté par appel en dollars (estimé sur 1K tokens input + output). */
12
+ maxCostPerCall?: number;
13
+ }
14
+ export interface SelectedModel {
15
+ provider: ProviderConfig;
16
+ model: ModelConfig;
17
+ }
18
+ /**
19
+ * Selects the optimal provider + model for the given complexity and strategy.
20
+ * Prefers providers in declaration order (first provider wins on equal footing).
21
+ *
22
+ * @param complexity - Complexité de la requête (low / medium / high)
23
+ * @param strategy - Stratégie de routing
24
+ * @param providers - Liste des providers configurés
25
+ * @param skillName - (optionnel) Nom du skill en cours d'exécution
26
+ * @param customRules - (optionnel) Règles de routing par skill (strategy "custom")
27
+ */
28
+ export declare function selectModel(complexity: Complexity, strategy: Strategy, providers: ProviderConfig[], skillName?: string, customRules?: SkillRoutingRule[]): SelectedModel;
29
+ //# sourceMappingURL=strategy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strategy.d.ts","sourceRoot":"","sources":["../../src/router/strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE/E,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,YAAY,EAAE,MAAM,CAAC;IACrB,sFAAsF;IACtF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qFAAqF;IACrF,aAAa,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;IACnD,uFAAuF;IACvF,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,cAAc,CAAC;IACzB,KAAK,EAAE,WAAW,CAAC;CACpB;AA0GD;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CACzB,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,cAAc,EAAE,EAC3B,SAAS,CAAC,EAAE,MAAM,EAClB,WAAW,CAAC,EAAE,gBAAgB,EAAE,GAC/B,aAAa,CAmGf"}
@@ -0,0 +1,169 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.selectModel = selectModel;
4
+ const models_1 = require("./models");
5
+ /**
6
+ * Teste si un skillName matche un pattern.
7
+ * Supporte le wildcard simple `*` (correspond à tout sauf `/`).
8
+ * Exact match vérifié en premier.
9
+ */
10
+ function matchesSkillPattern(skillName, pattern) {
11
+ if (pattern === skillName)
12
+ return true;
13
+ // Convertit le glob simple en RegExp :
14
+ // - échapper les caractères spéciaux de RegExp
15
+ // - remplacer * par [^/]* (wildcard hors séparateur de chemin)
16
+ const regexSource = pattern
17
+ .replace(/[.+^${}()|[\]\\]/g, "\\$&")
18
+ .replace(/\*/g, "[^/]*");
19
+ return new RegExp(`^${regexSource}$`).test(skillName);
20
+ }
21
+ /**
22
+ * Calcule le coût estimé d'un appel pour un modèle donné.
23
+ * Convention : 1 000 tokens en entrée + 1 000 tokens en sortie.
24
+ */
25
+ function estimatedCostPerCall(model) {
26
+ const INPUT_TOKENS = 1_000;
27
+ const OUTPUT_TOKENS = 1_000;
28
+ return ((model.inputPrice * INPUT_TOKENS + model.outputPrice * OUTPUT_TOKENS) /
29
+ 1_000_000);
30
+ }
31
+ /**
32
+ * Maps a strategy + complexity to a model tier.
33
+ */
34
+ function resolveTier(complexity, strategy) {
35
+ if (strategy === "quality") {
36
+ return "premium";
37
+ }
38
+ if (strategy === "economy") {
39
+ // Economy: cap at standard, never use premium
40
+ if (complexity === "low")
41
+ return "economy";
42
+ return "standard";
43
+ }
44
+ if (strategy === "speed") {
45
+ // Speed: always cheapest tier regardless of complexity
46
+ return "economy";
47
+ }
48
+ // balanced (default)
49
+ if (complexity === "low")
50
+ return "economy";
51
+ if (complexity === "medium")
52
+ return "standard";
53
+ return "premium";
54
+ }
55
+ /**
56
+ * Find a model of the given tier within a provider's enabled model list.
57
+ * Falls back to a higher tier if the desired tier is not available.
58
+ * Optionally filters out models whose estimated cost exceeds maxCostPerCall.
59
+ */
60
+ function findModelForTier(models, desiredTier, maxCostPerCall) {
61
+ const tierOrder = ["economy", "standard", "premium"];
62
+ const startIndex = tierOrder.indexOf(desiredTier);
63
+ const eligible = maxCostPerCall !== undefined
64
+ ? models.filter((m) => estimatedCostPerCall(m) <= maxCostPerCall)
65
+ : models;
66
+ // Try desired tier first, then escalate
67
+ for (let i = startIndex; i < tierOrder.length; i++) {
68
+ const candidate = eligible.find((m) => m.tier === tierOrder[i]);
69
+ if (candidate)
70
+ return candidate;
71
+ }
72
+ // Fall back to any eligible model
73
+ return eligible[0];
74
+ }
75
+ /**
76
+ * Résout la règle custom qui s'applique à un skillName donné.
77
+ * Exact match en premier, puis glob.
78
+ * Retourne undefined si aucune règle ne matche.
79
+ */
80
+ function resolveCustomRule(skillName, rules) {
81
+ // 1. Exact match prioritaire
82
+ const exact = rules.find((r) => r.skillPattern === skillName);
83
+ if (exact)
84
+ return exact;
85
+ // 2. Glob match (premier trouvé)
86
+ return rules.find((r) => matchesSkillPattern(skillName, r.skillPattern));
87
+ }
88
+ /**
89
+ * Selects the optimal provider + model for the given complexity and strategy.
90
+ * Prefers providers in declaration order (first provider wins on equal footing).
91
+ *
92
+ * @param complexity - Complexité de la requête (low / medium / high)
93
+ * @param strategy - Stratégie de routing
94
+ * @param providers - Liste des providers configurés
95
+ * @param skillName - (optionnel) Nom du skill en cours d'exécution
96
+ * @param customRules - (optionnel) Règles de routing par skill (strategy "custom")
97
+ */
98
+ function selectModel(complexity, strategy, providers, skillName, customRules) {
99
+ const enabledProviders = providers.filter((p) => p.enabled);
100
+ if (enabledProviders.length === 0) {
101
+ throw new Error("No enabled providers configured. Check your claw config.");
102
+ }
103
+ // --- Stratégie "custom" avec skillName ---
104
+ if (strategy === "custom" && skillName) {
105
+ const matchedRule = customRules && customRules.length > 0
106
+ ? resolveCustomRule(skillName, customRules)
107
+ : undefined;
108
+ if (matchedRule) {
109
+ // Cas 1 : preferredModel défini → trouver le modèle exact dans les providers
110
+ if (matchedRule.preferredModel) {
111
+ for (const provider of enabledProviders) {
112
+ const registryModels = models_1.MODELS_BY_PROVIDER.get(provider.name) ?? [];
113
+ const availableIds = new Set(provider.models.map((m) => m.id));
114
+ const model = registryModels.find((m) => m.id === matchedRule.preferredModel && availableIds.has(m.id));
115
+ if (model) {
116
+ // Vérifier maxCostPerCall si présent
117
+ if (matchedRule.maxCostPerCall === undefined ||
118
+ estimatedCostPerCall(model) <= matchedRule.maxCostPerCall) {
119
+ return { provider, model };
120
+ }
121
+ }
122
+ }
123
+ // preferredModel non disponible ou trop cher → fallback tier si défini,
124
+ // sinon on continue vers le fallback balanced plus bas
125
+ }
126
+ // Cas 2 : preferredTier défini (ou fallback du preferredModel non trouvé)
127
+ if (matchedRule.preferredTier) {
128
+ for (const provider of enabledProviders) {
129
+ const registryModels = models_1.MODELS_BY_PROVIDER.get(provider.name) ?? [];
130
+ const availableIds = new Set(provider.models.map((m) => m.id));
131
+ const eligibleModels = registryModels.filter((m) => availableIds.has(m.id));
132
+ if (eligibleModels.length === 0)
133
+ continue;
134
+ const model = findModelForTier(eligibleModels, matchedRule.preferredTier, matchedRule.maxCostPerCall);
135
+ if (model)
136
+ return { provider, model };
137
+ }
138
+ // Aucun modèle du tier trouvé → fallback balanced
139
+ }
140
+ // Cas 3 : règle matchée mais sans preferredModel ni preferredTier
141
+ // → fallback balanced ci-dessous
142
+ }
143
+ // Aucune règle ne matche, ou règle sans instruction de modèle → fallback balanced
144
+ return selectModel(complexity, "balanced", providers);
145
+ }
146
+ // --- Stratégies standard (economy / balanced / quality / speed) ---
147
+ const targetTier = resolveTier(complexity, strategy);
148
+ for (const provider of enabledProviders) {
149
+ // Use the registry to get canonical model list for this provider
150
+ const registryModels = models_1.MODELS_BY_PROVIDER.get(provider.name) ?? [];
151
+ // Intersect with provider's declared models (so only configured ones are used)
152
+ const availableIds = new Set(provider.models.map((m) => m.id));
153
+ const eligibleModels = registryModels.filter((m) => availableIds.has(m.id));
154
+ if (eligibleModels.length === 0)
155
+ continue;
156
+ const model = findModelForTier(eligibleModels, targetTier);
157
+ if (model) {
158
+ return { provider, model };
159
+ }
160
+ }
161
+ // Last resort: first provider, first model
162
+ const fallbackProvider = enabledProviders[0];
163
+ const fallbackModel = fallbackProvider.models[0] ??
164
+ (() => {
165
+ throw new Error("Provider has no models configured.");
166
+ })();
167
+ return { provider: fallbackProvider, model: fallbackModel };
168
+ }
169
+ //# sourceMappingURL=strategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strategy.js","sourceRoot":"","sources":["../../src/router/strategy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ export interface ToolFunction {
2
+ name: string;
3
+ description?: string;
4
+ parameters?: Record<string, unknown>;
5
+ }
6
+ export interface Tool {
7
+ type: "function";
8
+ function: ToolFunction;
9
+ }
10
+ export interface ToolCall {
11
+ id: string;
12
+ type: "function";
13
+ function: {
14
+ name: string;
15
+ arguments: string;
16
+ };
17
+ }
18
+ export interface ChatMessage {
19
+ role: "system" | "user" | "assistant" | "tool";
20
+ content: string;
21
+ tool_calls?: ToolCall[];
22
+ tool_call_id?: string;
23
+ }
24
+ export interface ChatCompletionRequest {
25
+ model: string;
26
+ messages: ChatMessage[];
27
+ max_tokens?: number;
28
+ temperature?: number;
29
+ tools?: Tool[];
30
+ stream?: boolean;
31
+ }
32
+ export interface ChatCompletionResponse {
33
+ id: string;
34
+ object: "chat.completion";
35
+ created: number;
36
+ model: string;
37
+ choices: Array<{
38
+ index: number;
39
+ message: ChatMessage;
40
+ finish_reason: string;
41
+ }>;
42
+ usage: {
43
+ prompt_tokens: number;
44
+ completion_tokens: number;
45
+ total_tokens: number;
46
+ };
47
+ }
48
+ export interface RouterLogEntry {
49
+ timestamp: string;
50
+ model: string;
51
+ provider: string;
52
+ inputTokens: number;
53
+ outputTokens: number;
54
+ cost: number;
55
+ latencyMs: number;
56
+ complexity: string;
57
+ strategy: string;
58
+ fallback: boolean;
59
+ success: boolean;
60
+ error?: string;
61
+ leakDetected?: boolean;
62
+ }
63
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/router/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,YAAY,CAAC;CACxB;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,QAAQ,EAAE,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,KAAK,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,WAAW,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC,CAAC;IACH,KAAK,EAAE;QACL,aAAa,EAAE,MAAM,CAAC;QACtB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/router/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ import { IncomingMessage } from "http";
2
+ /**
3
+ * Validates the Authorization header against the management secret.
4
+ * Expected format: "Authorization: Bearer {secret}"
5
+ */
6
+ export declare function requireAuth(req: IncomingMessage, secret: string): boolean;
7
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/sidecar/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAgBzE"}