sigma-agents 0.1.6 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/profiles.d.ts +7 -1
- package/dist/profiles.d.ts.map +1 -1
- package/dist/profiles.js +38 -4
- package/dist/profiles.js.map +1 -1
- package/dist/router.d.ts +6 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +165 -34
- package/dist/router.js.map +1 -1
- package/dist/sub-agent.d.ts +1 -1
- package/dist/sub-agent.d.ts.map +1 -1
- package/dist/sub-agent.js +13 -22
- package/dist/sub-agent.js.map +1 -1
- package/dist/types.d.ts +3 -3
- package/dist/types.d.ts.map +1 -1
- package/package.json +34 -31
- package/src/index.ts +4 -4
- package/src/profiles.ts +126 -88
- package/src/router.ts +275 -136
- package/src/sub-agent.ts +153 -160
- package/src/types.ts +32 -29
package/src/router.ts
CHANGED
|
@@ -1,138 +1,277 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import type { RoutingConfig, TaskCategory } from "./types.js";
|
|
3
3
|
|
|
4
4
|
export class SmartRouter {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
5
|
+
private config: RoutingConfig;
|
|
6
|
+
|
|
7
|
+
constructor(config: RoutingConfig) {
|
|
8
|
+
this.config = config;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Analyse le prompt et retourne la catégorie de tâche
|
|
13
|
+
* Priorité : debug > code > plan > review > test > explore > general
|
|
14
|
+
*/
|
|
15
|
+
classifyTask(prompt: string): TaskCategory {
|
|
16
|
+
const lowerPrompt = prompt.toLowerCase();
|
|
17
|
+
const categories: TaskCategory[] = [];
|
|
18
|
+
|
|
19
|
+
if (!this.config?.routes) {
|
|
20
|
+
return "general";
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Check each category
|
|
24
|
+
for (const [category, route] of Object.entries(this.config.routes)) {
|
|
25
|
+
if (!Array.isArray(route?.keywords)) continue;
|
|
26
|
+
const hasKeyword = route.keywords.some((keyword) => lowerPrompt.includes(keyword.toLowerCase()));
|
|
27
|
+
|
|
28
|
+
if (hasKeyword) {
|
|
29
|
+
categories.push(category as TaskCategory);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (categories.length === 0) {
|
|
34
|
+
return "general";
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Apply priorities
|
|
38
|
+
const priorityOrder: TaskCategory[] = ["debug", "code", "plan", "review", "test", "explore", "general"];
|
|
39
|
+
|
|
40
|
+
for (const priority of priorityOrder) {
|
|
41
|
+
if (categories.includes(priority)) {
|
|
42
|
+
return priority;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return categories[0];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Retourne le modèle et l'agent recommandés pour un prompt
|
|
51
|
+
*/
|
|
52
|
+
getRecommendation(prompt: string): { model: string; agent: string | null; category: TaskCategory } {
|
|
53
|
+
const category = this.classifyTask(prompt);
|
|
54
|
+
const route = this.config.routes[category];
|
|
55
|
+
|
|
56
|
+
if (!route) {
|
|
57
|
+
return {
|
|
58
|
+
model: this.config.default.model,
|
|
59
|
+
agent: this.config.default.agent,
|
|
60
|
+
category,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
model: route.preferredModel,
|
|
66
|
+
agent: route.agent,
|
|
67
|
+
category,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Charge la configuration depuis un fichier JSON
|
|
73
|
+
*/
|
|
74
|
+
static async loadConfig(configPath: string): Promise<RoutingConfig> {
|
|
75
|
+
try {
|
|
76
|
+
const content = await readFile(configPath, "utf8");
|
|
77
|
+
const parsed: unknown = JSON.parse(content);
|
|
78
|
+
|
|
79
|
+
if (!SmartRouter.validateRoutingConfig(parsed)) {
|
|
80
|
+
console.warn(
|
|
81
|
+
`Invalid routing config structure in ${configPath}; falling back to defaults`,
|
|
82
|
+
);
|
|
83
|
+
return SmartRouter.defaultConfig();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return parsed;
|
|
87
|
+
} catch {
|
|
88
|
+
// File doesn't exist yet — use defaults silently
|
|
89
|
+
return SmartRouter.defaultConfig();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Valide la structure d'une RoutingConfig chargée depuis un fichier non fiable.
|
|
95
|
+
* Fail-safe : retourne false sur toute incohérence structurelle.
|
|
96
|
+
*/
|
|
97
|
+
static validateRoutingConfig(config: unknown): config is RoutingConfig {
|
|
98
|
+
if (typeof config !== "object" || config === null) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const candidate = config as Record<string, unknown>;
|
|
103
|
+
|
|
104
|
+
const routes = candidate.routes;
|
|
105
|
+
if (typeof routes !== "object" || routes === null) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
for (const route of Object.values(routes as Record<string, unknown>)) {
|
|
110
|
+
if (typeof route !== "object" || route === null) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
const r = route as Record<string, unknown>;
|
|
114
|
+
if (typeof r.preferredModel !== "string" || typeof r.fallback !== "string") {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
if (!(r.agent === null || typeof r.agent === "string")) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
if (!Array.isArray(r.keywords) || !r.keywords.every((k) => typeof k === "string")) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const defaults = candidate.default;
|
|
126
|
+
if (typeof defaults !== "object" || defaults === null) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
const d = defaults as Record<string, unknown>;
|
|
130
|
+
if (typeof d.model !== "string") {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
if (!(d.agent === null || typeof d.agent === "string")) {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Default configuration with provider-agnostic model names.
|
|
142
|
+
* Uses 'default' as model placeholder — the actual model is determined
|
|
143
|
+
* at runtime by /phi-init or the user's routing.json.
|
|
144
|
+
*/
|
|
145
|
+
static defaultConfig(): RoutingConfig {
|
|
146
|
+
return {
|
|
147
|
+
routes: {
|
|
148
|
+
code: {
|
|
149
|
+
preferredModel: "default",
|
|
150
|
+
fallback: "default",
|
|
151
|
+
agent: null,
|
|
152
|
+
keywords: [
|
|
153
|
+
"code",
|
|
154
|
+
"implement",
|
|
155
|
+
"write",
|
|
156
|
+
"create",
|
|
157
|
+
"build",
|
|
158
|
+
"développer",
|
|
159
|
+
"coder",
|
|
160
|
+
"programmer",
|
|
161
|
+
"function",
|
|
162
|
+
"class",
|
|
163
|
+
"method",
|
|
164
|
+
],
|
|
165
|
+
},
|
|
166
|
+
debug: {
|
|
167
|
+
preferredModel: "default",
|
|
168
|
+
fallback: "default",
|
|
169
|
+
agent: null,
|
|
170
|
+
keywords: [
|
|
171
|
+
"debug",
|
|
172
|
+
"fix",
|
|
173
|
+
"error",
|
|
174
|
+
"bug",
|
|
175
|
+
"broken",
|
|
176
|
+
"issue",
|
|
177
|
+
"problem",
|
|
178
|
+
"repair",
|
|
179
|
+
"correct",
|
|
180
|
+
"erreur",
|
|
181
|
+
"problème",
|
|
182
|
+
"réparer",
|
|
183
|
+
],
|
|
184
|
+
},
|
|
185
|
+
explore: {
|
|
186
|
+
preferredModel: "default",
|
|
187
|
+
fallback: "default",
|
|
188
|
+
agent: null,
|
|
189
|
+
keywords: [
|
|
190
|
+
"explore",
|
|
191
|
+
"understand",
|
|
192
|
+
"analyze",
|
|
193
|
+
"examine",
|
|
194
|
+
"investigate",
|
|
195
|
+
"study",
|
|
196
|
+
"review",
|
|
197
|
+
"explorer",
|
|
198
|
+
"analyser",
|
|
199
|
+
"comprendre",
|
|
200
|
+
],
|
|
201
|
+
},
|
|
202
|
+
plan: {
|
|
203
|
+
preferredModel: "default",
|
|
204
|
+
fallback: "default",
|
|
205
|
+
agent: null,
|
|
206
|
+
keywords: [
|
|
207
|
+
"plan",
|
|
208
|
+
"design",
|
|
209
|
+
"architecture",
|
|
210
|
+
"strategy",
|
|
211
|
+
"approach",
|
|
212
|
+
"structure",
|
|
213
|
+
"organize",
|
|
214
|
+
"concevoir",
|
|
215
|
+
"planifier",
|
|
216
|
+
"architecture",
|
|
217
|
+
],
|
|
218
|
+
},
|
|
219
|
+
test: {
|
|
220
|
+
preferredModel: "default",
|
|
221
|
+
fallback: "default",
|
|
222
|
+
agent: null,
|
|
223
|
+
keywords: [
|
|
224
|
+
"test",
|
|
225
|
+
"testing",
|
|
226
|
+
"unit",
|
|
227
|
+
"integration",
|
|
228
|
+
"verify",
|
|
229
|
+
"validate",
|
|
230
|
+
"check",
|
|
231
|
+
"tester",
|
|
232
|
+
"vérifier",
|
|
233
|
+
"valider",
|
|
234
|
+
],
|
|
235
|
+
},
|
|
236
|
+
review: {
|
|
237
|
+
preferredModel: "default",
|
|
238
|
+
fallback: "default",
|
|
239
|
+
agent: null,
|
|
240
|
+
keywords: [
|
|
241
|
+
"review",
|
|
242
|
+
"audit",
|
|
243
|
+
"check",
|
|
244
|
+
"validate",
|
|
245
|
+
"quality",
|
|
246
|
+
"improve",
|
|
247
|
+
"optimize",
|
|
248
|
+
"réviser",
|
|
249
|
+
"améliorer",
|
|
250
|
+
"optimiser",
|
|
251
|
+
],
|
|
252
|
+
},
|
|
253
|
+
general: {
|
|
254
|
+
preferredModel: "default",
|
|
255
|
+
fallback: "default",
|
|
256
|
+
agent: null,
|
|
257
|
+
keywords: [
|
|
258
|
+
"help",
|
|
259
|
+
"explain",
|
|
260
|
+
"what",
|
|
261
|
+
"how",
|
|
262
|
+
"why",
|
|
263
|
+
"question",
|
|
264
|
+
"aide",
|
|
265
|
+
"expliquer",
|
|
266
|
+
"comment",
|
|
267
|
+
"pourquoi",
|
|
268
|
+
],
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
default: {
|
|
272
|
+
model: "default",
|
|
273
|
+
agent: null,
|
|
274
|
+
},
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
}
|