@jellyos/agent 0.1.1

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 (59) hide show
  1. package/README.md +375 -0
  2. package/bin/jellyagent +31 -0
  3. package/dist/api/ExtensionAPI.d.ts +92 -0
  4. package/dist/api/ExtensionAPI.d.ts.map +1 -0
  5. package/dist/api/ExtensionAPI.js +15 -0
  6. package/dist/api/ExtensionAPI.js.map +1 -0
  7. package/dist/api/Registry.d.ts +54 -0
  8. package/dist/api/Registry.d.ts.map +1 -0
  9. package/dist/api/Registry.js +101 -0
  10. package/dist/api/Registry.js.map +1 -0
  11. package/dist/cli.d.ts +6 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +134 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/index.d.ts +18 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +24 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/loader.d.ts +23 -0
  20. package/dist/loader.d.ts.map +1 -0
  21. package/dist/loader.js +84 -0
  22. package/dist/loader.js.map +1 -0
  23. package/dist/runner/AgentRunner.d.ts +66 -0
  24. package/dist/runner/AgentRunner.d.ts.map +1 -0
  25. package/dist/runner/AgentRunner.js +179 -0
  26. package/dist/runner/AgentRunner.js.map +1 -0
  27. package/dist/runner/ModelClient.d.ts +77 -0
  28. package/dist/runner/ModelClient.d.ts.map +1 -0
  29. package/dist/runner/ModelClient.js +224 -0
  30. package/dist/runner/ModelClient.js.map +1 -0
  31. package/dist/runner/SwarmRouter.d.ts +58 -0
  32. package/dist/runner/SwarmRouter.d.ts.map +1 -0
  33. package/dist/runner/SwarmRouter.js +153 -0
  34. package/dist/runner/SwarmRouter.js.map +1 -0
  35. package/dist/runner/ToolDispatcher.d.ts +19 -0
  36. package/dist/runner/ToolDispatcher.d.ts.map +1 -0
  37. package/dist/runner/ToolDispatcher.js +64 -0
  38. package/dist/runner/ToolDispatcher.js.map +1 -0
  39. package/dist/session/SessionManager.d.ts +23 -0
  40. package/dist/session/SessionManager.d.ts.map +1 -0
  41. package/dist/session/SessionManager.js +50 -0
  42. package/dist/session/SessionManager.js.map +1 -0
  43. package/dist/tui/App.d.ts +18 -0
  44. package/dist/tui/App.d.ts.map +1 -0
  45. package/dist/tui/App.js +188 -0
  46. package/dist/tui/App.js.map +1 -0
  47. package/dist/tui/REPL.d.ts +22 -0
  48. package/dist/tui/REPL.d.ts.map +1 -0
  49. package/dist/tui/REPL.js +46 -0
  50. package/dist/tui/REPL.js.map +1 -0
  51. package/dist/tui/StatusBar.d.ts +16 -0
  52. package/dist/tui/StatusBar.d.ts.map +1 -0
  53. package/dist/tui/StatusBar.js +15 -0
  54. package/dist/tui/StatusBar.js.map +1 -0
  55. package/dist/tui/theme.d.ts +30 -0
  56. package/dist/tui/theme.d.ts.map +1 -0
  57. package/dist/tui/theme.js +41 -0
  58. package/dist/tui/theme.js.map +1 -0
  59. package/package.json +59 -0
@@ -0,0 +1,77 @@
1
+ /**
2
+ * ModelClient — sends messages to any OpenAI-compatible model API.
3
+ *
4
+ * Provider priority (auto-detected from env):
5
+ * OpenRouter > Anthropic compat > OpenAI > local (ollama/lm-studio)
6
+ *
7
+ * Model rotation: resolveModelChain() returns up to 5 configs — the AgentRunner
8
+ * walks the chain on 429 (rate limit) or 5xx errors, providing seamless fallback.
9
+ *
10
+ * All outbound, all local — no inbound ports, no server.
11
+ */
12
+ export interface Message {
13
+ role: "system" | "user" | "assistant" | "tool";
14
+ content: string | null;
15
+ name?: string;
16
+ tool_calls?: ToolCall[];
17
+ tool_call_id?: string;
18
+ }
19
+ export interface ToolCall {
20
+ id: string;
21
+ type: "function";
22
+ function: {
23
+ name: string;
24
+ arguments: string;
25
+ };
26
+ }
27
+ export interface ChatChunk {
28
+ type: "delta" | "tool_call" | "done" | "error";
29
+ text?: string;
30
+ tool_calls?: ToolCall[];
31
+ error?: string;
32
+ finish_reason?: string;
33
+ /** HTTP status code — used by AgentRunner for rate-limit detection */
34
+ status?: number;
35
+ }
36
+ export interface ModelConfig {
37
+ baseUrl: string;
38
+ apiKey: string;
39
+ model: string;
40
+ maxTokens: number;
41
+ temperature: number;
42
+ siteUrl?: string;
43
+ siteName?: string;
44
+ }
45
+ /**
46
+ * Build the ordered model fallback chain.
47
+ *
48
+ * User-configurable pool: JELLY_MODEL_1 … JELLY_MODEL_5
49
+ * If any JELLY_MODEL_N vars are set they take priority; up to 5 are used in
50
+ * order. Unset slots are filled with provider-appropriate defaults.
51
+ *
52
+ * JELLY_MODEL_N format: just the model ID string, e.g.
53
+ * JELLY_MODEL_1=anthropic/claude-opus-4-5
54
+ * JELLY_MODEL_2=openai/gpt-4o
55
+ * JELLY_MODEL_3=google/gemini-2.5-pro
56
+ */
57
+ export declare function resolveModelChain(): ModelConfig[];
58
+ /** Convenience: returns just the primary (first) model config */
59
+ export declare function resolveModelConfig(): ModelConfig;
60
+ export declare class ModelClient {
61
+ private cfg;
62
+ constructor(cfg: ModelConfig);
63
+ /**
64
+ * Stream a chat completion. Yields ChatChunk objects.
65
+ * On HTTP error the generator yields a single { type: "error", status, error }
66
+ * chunk and returns — the caller (AgentRunner) decides whether to rotate.
67
+ */
68
+ stream(messages: Message[], tools?: Array<{
69
+ type: "function";
70
+ function: {
71
+ name: string;
72
+ description: string;
73
+ parameters: unknown;
74
+ };
75
+ }>): AsyncGenerator<ChatChunk>;
76
+ }
77
+ //# sourceMappingURL=ModelClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ModelClient.d.ts","sourceRoot":"","sources":["../../src/runner/ModelClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,OAAO;IACtB,IAAI,EAAW,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IACxD,OAAO,EAAQ,MAAM,GAAG,IAAI,CAAC;IAC7B,IAAI,CAAC,EAAU,MAAM,CAAC;IACtB,UAAU,CAAC,EAAI,QAAQ,EAAE,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAQ,MAAM,CAAC;IACjB,IAAI,EAAM,UAAU,CAAC;IACrB,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/C;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAY,OAAO,GAAG,WAAW,GAAG,MAAM,GAAG,OAAO,CAAC;IACzD,IAAI,CAAC,EAAW,MAAM,CAAC;IACvB,UAAU,CAAC,EAAK,QAAQ,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAU,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,sEAAsE;IACtE,MAAM,CAAC,EAAS,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAM,MAAM,CAAC;IACpB,MAAM,EAAO,MAAM,CAAC;IACpB,KAAK,EAAQ,MAAM,CAAC;IACpB,SAAS,EAAI,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAK,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAI,MAAM,CAAC;CACrB;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,IAAI,WAAW,EAAE,CAgFjD;AAED,iEAAiE;AACjE,wBAAgB,kBAAkB,IAAI,WAAW,CAEhD;AAID,qBAAa,WAAW;IACV,OAAO,CAAC,GAAG;gBAAH,GAAG,EAAE,WAAW;IAEpC;;;;OAIG;IACI,MAAM,CACX,QAAQ,EAAE,OAAO,EAAE,EACnB,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,QAAQ,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,OAAO,CAAA;SAAE,CAAA;KAAE,CAAC,GACxG,cAAc,CAAC,SAAS,CAAC;CA2G7B"}
@@ -0,0 +1,224 @@
1
+ /**
2
+ * ModelClient — sends messages to any OpenAI-compatible model API.
3
+ *
4
+ * Provider priority (auto-detected from env):
5
+ * OpenRouter > Anthropic compat > OpenAI > local (ollama/lm-studio)
6
+ *
7
+ * Model rotation: resolveModelChain() returns up to 5 configs — the AgentRunner
8
+ * walks the chain on 429 (rate limit) or 5xx errors, providing seamless fallback.
9
+ *
10
+ * All outbound, all local — no inbound ports, no server.
11
+ */
12
+ // ── Model rotation chain ──────────────────────────────────────────────────────
13
+ /**
14
+ * Build the ordered model fallback chain.
15
+ *
16
+ * User-configurable pool: JELLY_MODEL_1 … JELLY_MODEL_5
17
+ * If any JELLY_MODEL_N vars are set they take priority; up to 5 are used in
18
+ * order. Unset slots are filled with provider-appropriate defaults.
19
+ *
20
+ * JELLY_MODEL_N format: just the model ID string, e.g.
21
+ * JELLY_MODEL_1=anthropic/claude-opus-4-5
22
+ * JELLY_MODEL_2=openai/gpt-4o
23
+ * JELLY_MODEL_3=google/gemini-2.5-pro
24
+ */
25
+ export function resolveModelChain() {
26
+ const env = process.env;
27
+ const tokens = parseInt(env.MAX_TOKENS ?? "8192");
28
+ const temp = parseFloat(env.TEMPERATURE ?? "0.7");
29
+ // ── Collect user-configured model IDs (JELLY_MODEL_1..5) ────────────────
30
+ const userModels = [];
31
+ for (let i = 1; i <= 5; i++) {
32
+ const m = env[`JELLY_MODEL_${i}`];
33
+ if (m?.trim())
34
+ userModels.push(m.trim());
35
+ }
36
+ // ── OpenRouter — supports all providers via a single key ─────────────────
37
+ if (env.OPENROUTER_API_KEY) {
38
+ const base = "https://openrouter.ai/api/v1";
39
+ const key = env.OPENROUTER_API_KEY;
40
+ const siteUrl = env.OPENROUTER_SITE_URL ?? "https://jellychain.fun";
41
+ const siteName = env.OPENROUTER_SITE_NAME ?? "JellyOS";
42
+ const mk = (model) => ({
43
+ baseUrl: base, apiKey: key, model, maxTokens: tokens, temperature: temp,
44
+ siteUrl, siteName,
45
+ });
46
+ const defaults = [
47
+ env.DEFAULT_MODEL ?? "anthropic/claude-sonnet-4-5",
48
+ "anthropic/claude-3-haiku",
49
+ "openai/gpt-4o-mini",
50
+ "google/gemini-flash-1.5",
51
+ "meta-llama/llama-3-8b-instruct:free",
52
+ ];
53
+ // Merge: user-configured models first, then fill remaining slots with defaults
54
+ const merged = [...userModels, ...defaults.filter(d => !userModels.includes(d))].slice(0, 5);
55
+ return merged.map(mk);
56
+ }
57
+ // ── Anthropic direct (OpenAI-compat endpoint) ────────────────────────────
58
+ if (env.ANTHROPIC_API_KEY) {
59
+ const base = "https://api.anthropic.com/v1";
60
+ const key = env.ANTHROPIC_API_KEY;
61
+ const mk = (model) => ({
62
+ baseUrl: base, apiKey: key, model, maxTokens: tokens, temperature: temp,
63
+ });
64
+ const defaults = [
65
+ env.DEFAULT_MODEL ?? "claude-sonnet-4-5-20251101",
66
+ "claude-3-haiku-20240307",
67
+ "claude-3-5-haiku-20241022",
68
+ ];
69
+ const merged = [...userModels, ...defaults.filter(d => !userModels.includes(d))].slice(0, 5);
70
+ return merged.map(mk);
71
+ }
72
+ // ── OpenAI direct ────────────────────────────────────────────────────────
73
+ if (env.OPENAI_API_KEY) {
74
+ const base = env.OPENAI_BASE_URL ?? "https://api.openai.com/v1";
75
+ const key = env.OPENAI_API_KEY;
76
+ const mk = (model) => ({
77
+ baseUrl: base, apiKey: key, model, maxTokens: tokens, temperature: temp,
78
+ });
79
+ const defaults = [
80
+ env.DEFAULT_MODEL ?? "gpt-4o",
81
+ "gpt-4o-mini",
82
+ "gpt-3.5-turbo",
83
+ ];
84
+ const merged = [...userModels, ...defaults.filter(d => !userModels.includes(d))].slice(0, 5);
85
+ return merged.map(mk);
86
+ }
87
+ // ── Local model (ollama, lm-studio, etc.) — single entry, no rotation ───
88
+ if (env.OPENAI_BASE_URL) {
89
+ return [{
90
+ baseUrl: env.OPENAI_BASE_URL,
91
+ apiKey: env.OPENAI_API_KEY ?? "local",
92
+ model: userModels[0] ?? env.DEFAULT_MODEL ?? "llama3",
93
+ maxTokens: tokens,
94
+ temperature: temp,
95
+ }];
96
+ }
97
+ throw new Error("No API key found. Set OPENROUTER_API_KEY, ANTHROPIC_API_KEY, or OPENAI_API_KEY in ~/.jellyos/.env");
98
+ }
99
+ /** Convenience: returns just the primary (first) model config */
100
+ export function resolveModelConfig() {
101
+ return resolveModelChain()[0];
102
+ }
103
+ // ── ModelClient ───────────────────────────────────────────────────────────────
104
+ export class ModelClient {
105
+ cfg;
106
+ constructor(cfg) {
107
+ this.cfg = cfg;
108
+ }
109
+ /**
110
+ * Stream a chat completion. Yields ChatChunk objects.
111
+ * On HTTP error the generator yields a single { type: "error", status, error }
112
+ * chunk and returns — the caller (AgentRunner) decides whether to rotate.
113
+ */
114
+ async *stream(messages, tools) {
115
+ const headers = {
116
+ "Content-Type": "application/json",
117
+ "Authorization": `Bearer ${this.cfg.apiKey}`,
118
+ "User-Agent": "JellyOS/1.0",
119
+ };
120
+ if (this.cfg.siteUrl)
121
+ headers["HTTP-Referer"] = this.cfg.siteUrl;
122
+ if (this.cfg.siteName)
123
+ headers["X-Title"] = this.cfg.siteName;
124
+ const body = {
125
+ model: this.cfg.model,
126
+ messages,
127
+ max_tokens: this.cfg.maxTokens,
128
+ temperature: this.cfg.temperature,
129
+ stream: true,
130
+ };
131
+ if (tools && tools.length > 0) {
132
+ body.tools = tools;
133
+ body.tool_choice = "auto";
134
+ }
135
+ let res;
136
+ try {
137
+ res = await fetch(`${this.cfg.baseUrl}/chat/completions`, {
138
+ method: "POST",
139
+ headers,
140
+ body: JSON.stringify(body),
141
+ signal: AbortSignal.timeout(120_000),
142
+ });
143
+ }
144
+ catch (e) {
145
+ yield { type: "error", error: `Network error: ${e.message}`, status: 0 };
146
+ return;
147
+ }
148
+ if (!res.ok) {
149
+ const err = await res.text().catch(() => res.statusText);
150
+ yield { type: "error", error: `Model API ${res.status}: ${err}`, status: res.status };
151
+ return;
152
+ }
153
+ // Accumulate tool calls across chunks (they arrive fragmented)
154
+ const toolCallMap = new Map();
155
+ const reader = res.body.getReader();
156
+ const decoder = new TextDecoder();
157
+ let buf = "";
158
+ while (true) {
159
+ const { done, value } = await reader.read();
160
+ if (done)
161
+ break;
162
+ buf += decoder.decode(value, { stream: true });
163
+ const lines = buf.split("\n");
164
+ buf = lines.pop() ?? "";
165
+ for (const line of lines) {
166
+ const trimmed = line.trim();
167
+ if (!trimmed || trimmed === "data: [DONE]")
168
+ continue;
169
+ if (!trimmed.startsWith("data: "))
170
+ continue;
171
+ let chunk;
172
+ try {
173
+ chunk = JSON.parse(trimmed.slice(6));
174
+ }
175
+ catch {
176
+ continue;
177
+ }
178
+ const delta = chunk.choices?.[0]?.delta;
179
+ if (!delta)
180
+ continue;
181
+ if (delta.content) {
182
+ yield { type: "delta", text: delta.content };
183
+ }
184
+ if (delta.tool_calls) {
185
+ for (const tc of delta.tool_calls) {
186
+ const idx = tc.index ?? 0;
187
+ const existing = toolCallMap.get(idx) ?? { id: "", name: "", args: "" };
188
+ if (tc.id)
189
+ existing.id += tc.id;
190
+ if (tc.function?.name)
191
+ existing.name += tc.function.name;
192
+ if (tc.function?.arguments)
193
+ existing.args += tc.function.arguments;
194
+ toolCallMap.set(idx, existing);
195
+ }
196
+ }
197
+ const finish = chunk.choices?.[0]?.finish_reason;
198
+ if (finish === "tool_calls" || finish === "stop") {
199
+ if (toolCallMap.size > 0) {
200
+ const tool_calls = [...toolCallMap.values()].map(tc => ({
201
+ id: tc.id || `call_${Date.now()}`,
202
+ type: "function",
203
+ function: { name: tc.name, arguments: tc.args },
204
+ }));
205
+ yield { type: "tool_call", tool_calls };
206
+ toolCallMap.clear();
207
+ }
208
+ yield { type: "done", finish_reason: finish };
209
+ }
210
+ }
211
+ }
212
+ // Flush any remaining tool calls if stream ended without finish_reason
213
+ if (toolCallMap.size > 0) {
214
+ const tool_calls = [...toolCallMap.values()].map(tc => ({
215
+ id: tc.id || `call_${Date.now()}`,
216
+ type: "function",
217
+ function: { name: tc.name, arguments: tc.args },
218
+ }));
219
+ yield { type: "tool_call", tool_calls };
220
+ }
221
+ yield { type: "done", finish_reason: "end" };
222
+ }
223
+ }
224
+ //# sourceMappingURL=ModelClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ModelClient.js","sourceRoot":"","sources":["../../src/runner/ModelClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * SwarmRouter — complexity scoring and task decomposition.
3
+ *
4
+ * For complex prompts (score >= threshold) the runner decomposes the request
5
+ * into 2–5 sub-tasks, executes them with a capped worker pool, then feeds all
6
+ * results to a reviewer model that synthesises a final answer.
7
+ *
8
+ * Sub-task execution is sequential inside each worker slot to avoid hammering
9
+ * the provider; concurrency is capped at Math.min(maxAgents, os.cpus().length).
10
+ */
11
+ export interface SwarmConfig {
12
+ /** Maximum parallel workers (hard cap: 5). Default: min(cpuCount, 3). */
13
+ maxAgents?: number;
14
+ /** Complexity score threshold above which swarm activates. Default: 40. */
15
+ complexityThreshold?: number;
16
+ }
17
+ export interface SubTaskResult {
18
+ task: string;
19
+ result: string;
20
+ model: string;
21
+ ms: number;
22
+ }
23
+ /**
24
+ * Returns a score 0–100 reflecting prompt complexity.
25
+ * Tuned so "check ETH price" ≈ 10, "analyze ETH and BTC then predict" ≈ 55.
26
+ */
27
+ export declare function scoreComplexity(prompt: string): number;
28
+ /**
29
+ * Splits a complex prompt into 2–5 focused sub-task strings.
30
+ * Uses simple heuristics so no extra model call is needed.
31
+ */
32
+ export declare function decompose(prompt: string, maxTasks: number): string[];
33
+ export declare class SwarmRouter {
34
+ private maxAgents;
35
+ private complexityThreshold;
36
+ constructor(cfg?: SwarmConfig);
37
+ /** True when the prompt is complex enough to warrant swarm execution. */
38
+ shouldSwarm(prompt: string): boolean;
39
+ /**
40
+ * Decompose prompt into sub-tasks, execute them in groups of 3 (up to 5
41
+ * agents total), then synthesise with a reviewer model.
42
+ *
43
+ * Groups-of-3 planner:
44
+ * tasks = decompose(prompt, maxAgents) → 2–5 sub-tasks
45
+ * batches = chunk(tasks, 3) → [[t1,t2,t3],[t4,t5]] for 5 tasks
46
+ * each batch runs in parallel; batches run sequentially
47
+ * reviewer model synthesises all results into a unified answer
48
+ *
49
+ * @param prompt - Original user message
50
+ * @param systemPrompt - Current system prompt (passed to each sub-agent + reviewer)
51
+ * @param onProgress - Called as each sub-task completes
52
+ */
53
+ run(prompt: string, systemPrompt: string, onProgress: (result: SubTaskResult, remaining: number) => void): Promise<{
54
+ synthesis: string;
55
+ subResults: SubTaskResult[];
56
+ }>;
57
+ }
58
+ //# sourceMappingURL=SwarmRouter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SwarmRouter.d.ts","sourceRoot":"","sources":["../../src/runner/SwarmRouter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,MAAM,WAAW,WAAW;IAC1B,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAI,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAG,MAAM,CAAC;IACf,EAAE,EAAM,MAAM,CAAC;CAChB;AASD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAetD;AAID;;;GAGG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAqBpE;AAqCD,qBAAa,WAAW;IACtB,OAAO,CAAC,SAAS,CAAmB;IACpC,OAAO,CAAC,mBAAmB,CAAS;gBAExB,GAAG,GAAE,WAAgB;IAMjC,yEAAyE;IACzE,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAIpC;;;;;;;;;;;;;OAaG;IACG,GAAG,CACP,MAAM,EAAQ,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAI,CAAC,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,GAC/D,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,aAAa,EAAE,CAAA;KAAE,CAAC;CAoD/D"}
@@ -0,0 +1,153 @@
1
+ /**
2
+ * SwarmRouter — complexity scoring and task decomposition.
3
+ *
4
+ * For complex prompts (score >= threshold) the runner decomposes the request
5
+ * into 2–5 sub-tasks, executes them with a capped worker pool, then feeds all
6
+ * results to a reviewer model that synthesises a final answer.
7
+ *
8
+ * Sub-task execution is sequential inside each worker slot to avoid hammering
9
+ * the provider; concurrency is capped at Math.min(maxAgents, os.cpus().length).
10
+ */
11
+ import os from "os";
12
+ import { ModelClient, resolveModelChain } from "./ModelClient.js";
13
+ // ── Complexity scoring ───────────────────────────────────────────────────────
14
+ const CONJUNCTION_RE = /\b(and|also|then|additionally|plus|as well as|furthermore)\b/gi;
15
+ const MULTI_CHAIN_RE = /\b(eth|btc|sol|bnb|avax|matic|cosmos|atom|arb|op)\b/gi;
16
+ const ACTION_VERB_RE = /\b(analyze|compare|predict|scan|check|simulate|estimate|backtest|evaluate|assess)\b/gi;
17
+ const QUESTION_RE = /\?/g;
18
+ /**
19
+ * Returns a score 0–100 reflecting prompt complexity.
20
+ * Tuned so "check ETH price" ≈ 10, "analyze ETH and BTC then predict" ≈ 55.
21
+ */
22
+ export function scoreComplexity(prompt) {
23
+ const conjunctions = (prompt.match(CONJUNCTION_RE) ?? []).length;
24
+ const chains = new Set((prompt.match(MULTI_CHAIN_RE) ?? []).map(s => s.toLowerCase())).size;
25
+ const actions = (prompt.match(ACTION_VERB_RE) ?? []).length;
26
+ const questions = (prompt.match(QUESTION_RE) ?? []).length;
27
+ const wordCount = prompt.trim().split(/\s+/).length;
28
+ return Math.min(100, conjunctions * 12 +
29
+ chains * 8 +
30
+ actions * 10 +
31
+ questions * 5 +
32
+ Math.floor(wordCount / 8));
33
+ }
34
+ // ── Task decomposition ───────────────────────────────────────────────────────
35
+ /**
36
+ * Splits a complex prompt into 2–5 focused sub-task strings.
37
+ * Uses simple heuristics so no extra model call is needed.
38
+ */
39
+ export function decompose(prompt, maxTasks) {
40
+ const cap = Math.max(2, Math.min(maxTasks, 5));
41
+ // Split on explicit conjunctions / punctuation
42
+ const parts = prompt
43
+ .split(/,\s*| and | also | then | additionally | plus /i)
44
+ .map(s => s.trim())
45
+ .filter(s => s.length > 4);
46
+ if (parts.length >= 2) {
47
+ return parts.slice(0, cap);
48
+ }
49
+ // Fallback: split action verbs into separate sub-questions
50
+ const verbMatches = [...prompt.matchAll(/\b(analyze|compare|predict|scan|check|estimate|evaluate)\b[^,.?]*/gi)];
51
+ if (verbMatches.length >= 2) {
52
+ return verbMatches.slice(0, cap).map(m => m[0].trim());
53
+ }
54
+ // Cannot decompose meaningfully → return as-is (single task)
55
+ return [prompt];
56
+ }
57
+ // ── Reviewer synthesis ───────────────────────────────────────────────────────
58
+ async function reviewerSynthesize(originalPrompt, results, systemPrompt) {
59
+ const chain = resolveModelChain();
60
+ const cfg = chain[0];
61
+ const client = new ModelClient(cfg);
62
+ const context = results
63
+ .map((r, i) => `### Sub-task ${i + 1}: ${r.task}\n${r.result}`)
64
+ .join("\n\n");
65
+ const messages = [
66
+ { role: "system", content: systemPrompt },
67
+ {
68
+ role: "user",
69
+ content: `You are a synthesis reviewer. The following sub-tasks were run in response to the user's original request.\n\n` +
70
+ `**Original request:** ${originalPrompt}\n\n${context}\n\n` +
71
+ `Write a concise, unified answer that directly addresses the original request using all the above findings.`,
72
+ },
73
+ ];
74
+ let out = "";
75
+ for await (const chunk of client.stream(messages, [])) {
76
+ if (chunk.type === "delta" && chunk.text)
77
+ out += chunk.text;
78
+ }
79
+ return out || results.map(r => r.result).join("\n\n---\n\n");
80
+ }
81
+ // ── SwarmRouter class ────────────────────────────────────────────────────────
82
+ export class SwarmRouter {
83
+ maxAgents;
84
+ complexityThreshold;
85
+ constructor(cfg = {}) {
86
+ const cpus = os.cpus().length;
87
+ this.maxAgents = Math.min(cfg.maxAgents ?? Math.min(cpus, 3), 5);
88
+ this.complexityThreshold = cfg.complexityThreshold ?? 40;
89
+ }
90
+ /** True when the prompt is complex enough to warrant swarm execution. */
91
+ shouldSwarm(prompt) {
92
+ return scoreComplexity(prompt) >= this.complexityThreshold;
93
+ }
94
+ /**
95
+ * Decompose prompt into sub-tasks, execute them in groups of 3 (up to 5
96
+ * agents total), then synthesise with a reviewer model.
97
+ *
98
+ * Groups-of-3 planner:
99
+ * tasks = decompose(prompt, maxAgents) → 2–5 sub-tasks
100
+ * batches = chunk(tasks, 3) → [[t1,t2,t3],[t4,t5]] for 5 tasks
101
+ * each batch runs in parallel; batches run sequentially
102
+ * reviewer model synthesises all results into a unified answer
103
+ *
104
+ * @param prompt - Original user message
105
+ * @param systemPrompt - Current system prompt (passed to each sub-agent + reviewer)
106
+ * @param onProgress - Called as each sub-task completes
107
+ */
108
+ async run(prompt, systemPrompt, onProgress) {
109
+ const tasks = decompose(prompt, this.maxAgents);
110
+ const chain = resolveModelChain();
111
+ const subResults = [];
112
+ // Split tasks into groups of 3 (the required "groups-of-3" planner)
113
+ const GROUP_SIZE = 3;
114
+ const batches = [];
115
+ for (let i = 0; i < tasks.length; i += GROUP_SIZE) {
116
+ batches.push(tasks.slice(i, i + GROUP_SIZE));
117
+ }
118
+ let modelIdx = 1; // reserve chain[0] for reviewer
119
+ const runOne = async (task, mIdx, remaining) => {
120
+ const cfg = chain[mIdx % chain.length] ?? chain[0];
121
+ const client = new ModelClient(cfg);
122
+ const msgs = [
123
+ { role: "system", content: systemPrompt },
124
+ { role: "user", content: task },
125
+ ];
126
+ const t0 = Date.now();
127
+ let out = "";
128
+ for await (const chunk of client.stream(msgs, [])) {
129
+ if (chunk.type === "delta" && chunk.text)
130
+ out += chunk.text;
131
+ }
132
+ const r = {
133
+ task,
134
+ result: out || "(no output)",
135
+ model: cfg.model,
136
+ ms: Date.now() - t0,
137
+ };
138
+ subResults.push(r);
139
+ onProgress(r, remaining);
140
+ };
141
+ // Execute batches sequentially; within each batch run up to 3 in parallel
142
+ let remaining = tasks.length;
143
+ for (const batch of batches) {
144
+ await Promise.all(batch.map(task => {
145
+ remaining--;
146
+ return runOne(task, modelIdx++, remaining);
147
+ }));
148
+ }
149
+ const synthesis = await reviewerSynthesize(prompt, subResults, systemPrompt);
150
+ return { synthesis, subResults };
151
+ }
152
+ }
153
+ //# sourceMappingURL=SwarmRouter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SwarmRouter.js","sourceRoot":"","sources":["../../src/runner/SwarmRouter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * ToolDispatcher — executes tool calls from the model response.
3
+ * Looks up tool by name in the Registry, validates params, runs execute().
4
+ */
5
+ import type { Registry } from "../api/Registry.js";
6
+ import type { ToolCall } from "./ModelClient.js";
7
+ export interface ToolResult {
8
+ tool_call_id: string;
9
+ name: string;
10
+ content: string;
11
+ isError: boolean;
12
+ }
13
+ export declare class ToolDispatcher {
14
+ private registry;
15
+ constructor(registry: Registry);
16
+ dispatch(calls: ToolCall[]): Promise<ToolResult[]>;
17
+ private execute;
18
+ }
19
+ //# sourceMappingURL=ToolDispatcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToolDispatcher.d.ts","sourceRoot":"","sources":["../../src/runner/ToolDispatcher.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEjD,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAU,MAAM,CAAC;IACrB,OAAO,EAAO,MAAM,CAAC;IACrB,OAAO,EAAO,OAAO,CAAC;CACvB;AAED,qBAAa,cAAc;IACb,OAAO,CAAC,QAAQ;gBAAR,QAAQ,EAAE,QAAQ;IAEhC,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;YAI1C,OAAO;CAkDtB"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * ToolDispatcher — executes tool calls from the model response.
3
+ * Looks up tool by name in the Registry, validates params, runs execute().
4
+ */
5
+ import { Value } from "@sinclair/typebox/value";
6
+ export class ToolDispatcher {
7
+ registry;
8
+ constructor(registry) {
9
+ this.registry = registry;
10
+ }
11
+ async dispatch(calls) {
12
+ return Promise.all(calls.map(tc => this.execute(tc)));
13
+ }
14
+ async execute(tc) {
15
+ const tool = this.registry.getTool(tc.function.name);
16
+ if (!tool) {
17
+ return {
18
+ tool_call_id: tc.id,
19
+ name: tc.function.name,
20
+ content: `Unknown tool: ${tc.function.name}`,
21
+ isError: true,
22
+ };
23
+ }
24
+ let params;
25
+ try {
26
+ params = JSON.parse(tc.function.arguments || "{}");
27
+ }
28
+ catch {
29
+ return {
30
+ tool_call_id: tc.id,
31
+ name: tc.function.name,
32
+ content: `Invalid JSON arguments: ${tc.function.arguments}`,
33
+ isError: true,
34
+ };
35
+ }
36
+ // Validate params against the tool's TypeBox schema
37
+ if (!Value.Check(tool.parameters, params)) {
38
+ const errors = [...Value.Errors(tool.parameters, params)]
39
+ .slice(0, 3)
40
+ .map(e => `${e.path}: ${e.message}`)
41
+ .join("; ");
42
+ return {
43
+ tool_call_id: tc.id,
44
+ name: tc.function.name,
45
+ content: `Parameter validation failed: ${errors}`,
46
+ isError: true,
47
+ };
48
+ }
49
+ try {
50
+ const result = await tool.execute(tc.id, params);
51
+ const content = result.content.map(c => c.text).join("\n");
52
+ return { tool_call_id: tc.id, name: tc.function.name, content, isError: false };
53
+ }
54
+ catch (e) {
55
+ return {
56
+ tool_call_id: tc.id,
57
+ name: tc.function.name,
58
+ content: `Tool error: ${e?.message ?? String(e)}`,
59
+ isError: true,
60
+ };
61
+ }
62
+ }
63
+ }
64
+ //# sourceMappingURL=ToolDispatcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToolDispatcher.js","sourceRoot":"","sources":["../../src/runner/ToolDispatcher.ts"],"names":[],"mappings":"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"}