@radaros/core 0.3.4 → 0.3.6

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 (60) hide show
  1. package/dist/index.d.ts +1407 -0
  2. package/dist/index.js +5269 -0
  3. package/package.json +6 -2
  4. package/src/a2a/a2a-remote-agent.ts +0 -270
  5. package/src/a2a/types.ts +0 -142
  6. package/src/agent/agent.ts +0 -417
  7. package/src/agent/llm-loop.ts +0 -290
  8. package/src/agent/run-context.ts +0 -35
  9. package/src/agent/types.ts +0 -89
  10. package/src/events/event-bus.ts +0 -45
  11. package/src/events/types.ts +0 -16
  12. package/src/guardrails/types.ts +0 -5
  13. package/src/hooks/types.ts +0 -6
  14. package/src/index.ts +0 -157
  15. package/src/knowledge/knowledge-base.ts +0 -146
  16. package/src/logger/logger.ts +0 -249
  17. package/src/mcp/mcp-client.ts +0 -264
  18. package/src/memory/memory.ts +0 -87
  19. package/src/memory/types.ts +0 -13
  20. package/src/memory/user-memory.ts +0 -211
  21. package/src/models/provider.ts +0 -22
  22. package/src/models/providers/anthropic.ts +0 -360
  23. package/src/models/providers/google.ts +0 -386
  24. package/src/models/providers/ollama.ts +0 -211
  25. package/src/models/providers/openai.ts +0 -345
  26. package/src/models/providers/vertex.ts +0 -427
  27. package/src/models/registry.ts +0 -107
  28. package/src/models/types.ts +0 -124
  29. package/src/session/session-manager.ts +0 -75
  30. package/src/session/types.ts +0 -10
  31. package/src/storage/driver.ts +0 -10
  32. package/src/storage/in-memory.ts +0 -44
  33. package/src/storage/mongodb.ts +0 -70
  34. package/src/storage/postgres.ts +0 -81
  35. package/src/storage/sqlite.ts +0 -81
  36. package/src/team/modes.ts +0 -1
  37. package/src/team/team.ts +0 -323
  38. package/src/team/types.ts +0 -26
  39. package/src/toolkits/base.ts +0 -15
  40. package/src/toolkits/duckduckgo.ts +0 -256
  41. package/src/toolkits/gmail.ts +0 -226
  42. package/src/toolkits/hackernews.ts +0 -121
  43. package/src/toolkits/websearch.ts +0 -158
  44. package/src/toolkits/whatsapp.ts +0 -209
  45. package/src/tools/define-tool.ts +0 -22
  46. package/src/tools/tool-executor.ts +0 -221
  47. package/src/tools/types.ts +0 -36
  48. package/src/utils/retry.ts +0 -56
  49. package/src/vector/base.ts +0 -44
  50. package/src/vector/embeddings/google.ts +0 -64
  51. package/src/vector/embeddings/openai.ts +0 -66
  52. package/src/vector/in-memory.ts +0 -115
  53. package/src/vector/mongodb.ts +0 -241
  54. package/src/vector/pgvector.ts +0 -169
  55. package/src/vector/qdrant.ts +0 -203
  56. package/src/vector/types.ts +0 -55
  57. package/src/workflow/step-runner.ts +0 -303
  58. package/src/workflow/types.ts +0 -55
  59. package/src/workflow/workflow.ts +0 -68
  60. package/tsconfig.json +0 -8
@@ -1,427 +0,0 @@
1
- import { createRequire } from "node:module";
2
- import type { ModelProvider } from "../provider.js";
3
- import {
4
- getTextContent,
5
- isMultiModal,
6
- type ChatMessage,
7
- type ContentPart,
8
- type ModelConfig,
9
- type ModelResponse,
10
- type StreamChunk,
11
- type ToolDefinition,
12
- type TokenUsage,
13
- type ToolCall,
14
- } from "../types.js";
15
-
16
- const _require = createRequire(import.meta.url);
17
-
18
- export interface VertexAIConfig {
19
- project?: string;
20
- location?: string;
21
- /** Service account key JSON string or path (optional — uses ADC by default). */
22
- credentials?: string;
23
- }
24
-
25
- /**
26
- * Vertex AI provider using Google's @google/genai SDK in Vertex mode.
27
- *
28
- * Authentication (in order of precedence):
29
- * 1. Explicit `project` + `location` in config
30
- * 2. GOOGLE_CLOUD_PROJECT / GOOGLE_CLOUD_LOCATION env vars
31
- * 3. Application Default Credentials (gcloud auth)
32
- */
33
- export class VertexAIProvider implements ModelProvider {
34
- readonly providerId = "vertex";
35
- readonly modelId: string;
36
- private ai: any = null;
37
- private GoogleGenAICtor: any;
38
- private project: string;
39
- private location: string;
40
-
41
- constructor(modelId: string, config?: VertexAIConfig) {
42
- this.modelId = modelId;
43
- this.project =
44
- config?.project ??
45
- process.env.GOOGLE_CLOUD_PROJECT ??
46
- process.env.GCLOUD_PROJECT ??
47
- "";
48
- this.location =
49
- config?.location ??
50
- process.env.GOOGLE_CLOUD_LOCATION ??
51
- process.env.GOOGLE_CLOUD_REGION ??
52
- "us-central1";
53
-
54
- if (!this.project) {
55
- throw new Error(
56
- "VertexAIProvider: 'project' is required. Pass it in config or set GOOGLE_CLOUD_PROJECT env var."
57
- );
58
- }
59
-
60
- try {
61
- const { GoogleGenAI } = _require("@google/genai");
62
- this.GoogleGenAICtor = GoogleGenAI;
63
- } catch {
64
- throw new Error(
65
- "@google/genai is required for VertexAIProvider. Install it: npm install @google/genai"
66
- );
67
- }
68
- }
69
-
70
- private getClient(): any {
71
- if (this.ai) return this.ai;
72
- this.ai = new this.GoogleGenAICtor({
73
- vertexai: true,
74
- project: this.project,
75
- location: this.location,
76
- });
77
- return this.ai;
78
- }
79
-
80
- async generate(
81
- messages: ChatMessage[],
82
- options?: ModelConfig & { tools?: ToolDefinition[] }
83
- ): Promise<ModelResponse> {
84
- const { systemInstruction, contents } = this.toGoogleMessages(messages);
85
-
86
- const config: Record<string, unknown> = {};
87
- if (options?.temperature !== undefined)
88
- config.temperature = options.temperature;
89
- if (options?.maxTokens !== undefined)
90
- config.maxOutputTokens = options.maxTokens;
91
- if (options?.topP !== undefined) config.topP = options.topP;
92
- if (options?.stop) config.stopSequences = options.stop;
93
-
94
- if (options?.responseFormat) {
95
- config.responseMimeType = "application/json";
96
- const rf = options.responseFormat;
97
- if (
98
- typeof rf === "object" &&
99
- rf !== null &&
100
- "type" in rf &&
101
- rf.type === "json_schema" &&
102
- "schema" in rf &&
103
- rf.schema
104
- ) {
105
- config.responseSchema = this.cleanJsonSchema(
106
- rf.schema as Record<string, unknown>
107
- );
108
- }
109
- }
110
-
111
- if (options?.reasoning?.enabled) {
112
- config.thinkingConfig = {
113
- thinkingBudget: options.reasoning.budgetTokens ?? 10000,
114
- };
115
- }
116
-
117
- const params: Record<string, unknown> = {
118
- model: this.modelId,
119
- contents,
120
- config,
121
- };
122
-
123
- if (systemInstruction) params.systemInstruction = systemInstruction;
124
- if (options?.tools?.length) {
125
- params.tools = [
126
- { functionDeclarations: this.toGoogleTools(options.tools) },
127
- ];
128
- }
129
-
130
- const client = this.getClient();
131
- const response = await client.models.generateContent(params);
132
- return this.normalizeResponse(response);
133
- }
134
-
135
- async *stream(
136
- messages: ChatMessage[],
137
- options?: ModelConfig & { tools?: ToolDefinition[] }
138
- ): AsyncGenerator<StreamChunk> {
139
- const { systemInstruction, contents } = this.toGoogleMessages(messages);
140
-
141
- const config: Record<string, unknown> = {};
142
- if (options?.temperature !== undefined)
143
- config.temperature = options.temperature;
144
- if (options?.maxTokens !== undefined)
145
- config.maxOutputTokens = options.maxTokens;
146
- if (options?.topP !== undefined) config.topP = options.topP;
147
- if (options?.stop) config.stopSequences = options.stop;
148
-
149
- if (options?.reasoning?.enabled) {
150
- config.thinkingConfig = {
151
- thinkingBudget: options.reasoning.budgetTokens ?? 10000,
152
- };
153
- }
154
-
155
- const params: Record<string, unknown> = {
156
- model: this.modelId,
157
- contents,
158
- config,
159
- };
160
-
161
- if (systemInstruction) params.systemInstruction = systemInstruction;
162
- if (options?.tools?.length) {
163
- params.tools = [
164
- { functionDeclarations: this.toGoogleTools(options.tools) },
165
- ];
166
- }
167
-
168
- const client = this.getClient();
169
- const streamResult = await client.models.generateContentStream(params);
170
-
171
- let toolCallCounter = 0;
172
-
173
- for await (const chunk of streamResult) {
174
- const candidate = chunk.candidates?.[0];
175
- if (!candidate?.content?.parts) continue;
176
-
177
- for (const part of candidate.content.parts) {
178
- if (part.thought) {
179
- yield { type: "thinking", text: part.text ?? "" };
180
- } else if (part.text) {
181
- yield { type: "text", text: part.text };
182
- }
183
-
184
- if (part.functionCall) {
185
- const id = `vertex_tc_${toolCallCounter++}`;
186
- yield {
187
- type: "tool_call_start",
188
- toolCall: { id, name: part.functionCall.name },
189
- };
190
- yield {
191
- type: "tool_call_delta",
192
- toolCallId: id,
193
- argumentsDelta: JSON.stringify(part.functionCall.args ?? {}),
194
- };
195
- yield { type: "tool_call_end", toolCallId: id };
196
- }
197
- }
198
-
199
- if (candidate.finishReason) {
200
- let finishReason = "stop";
201
- if (
202
- candidate.finishReason === "STOP" ||
203
- candidate.finishReason === "END_TURN"
204
- )
205
- finishReason = "stop";
206
- else if (candidate.finishReason === "MAX_TOKENS")
207
- finishReason = "length";
208
- else if (candidate.finishReason === "SAFETY")
209
- finishReason = "content_filter";
210
-
211
- const hasToolCalls = candidate.content?.parts?.some(
212
- (p: any) => p.functionCall
213
- );
214
- if (hasToolCalls) finishReason = "tool_calls";
215
-
216
- yield {
217
- type: "finish",
218
- finishReason,
219
- usage: chunk.usageMetadata
220
- ? {
221
- promptTokens: chunk.usageMetadata.promptTokenCount ?? 0,
222
- completionTokens:
223
- chunk.usageMetadata.candidatesTokenCount ?? 0,
224
- totalTokens: chunk.usageMetadata.totalTokenCount ?? 0,
225
- }
226
- : undefined,
227
- };
228
- }
229
- }
230
- }
231
-
232
- // ── Message conversion (identical to GoogleProvider) ─────────────────────
233
-
234
- private toGoogleMessages(messages: ChatMessage[]): {
235
- systemInstruction: string | undefined;
236
- contents: unknown[];
237
- } {
238
- let systemInstruction: string | undefined;
239
- const contents: unknown[] = [];
240
-
241
- for (const msg of messages) {
242
- if (msg.role === "system") {
243
- systemInstruction = getTextContent(msg.content) || undefined;
244
- continue;
245
- }
246
-
247
- if (msg.role === "user") {
248
- if (isMultiModal(msg.content)) {
249
- contents.push({
250
- role: "user",
251
- parts: msg.content.map((p) => this.partToGoogle(p)),
252
- });
253
- } else {
254
- contents.push({
255
- role: "user",
256
- parts: [{ text: msg.content ?? "" }],
257
- });
258
- }
259
- continue;
260
- }
261
-
262
- if (msg.role === "assistant") {
263
- const parts: unknown[] = [];
264
- if (msg.content) parts.push({ text: msg.content });
265
- if (msg.toolCalls) {
266
- for (const tc of msg.toolCalls) {
267
- parts.push({
268
- functionCall: { name: tc.name, args: tc.arguments },
269
- });
270
- }
271
- }
272
- if (parts.length === 0) parts.push({ text: "" });
273
- contents.push({ role: "model", parts });
274
- continue;
275
- }
276
-
277
- if (msg.role === "tool") {
278
- contents.push({
279
- role: "function",
280
- parts: [
281
- {
282
- functionResponse: {
283
- name: msg.name ?? "unknown",
284
- response: { result: msg.content ?? "" },
285
- },
286
- },
287
- ],
288
- });
289
- continue;
290
- }
291
- }
292
-
293
- return { systemInstruction, contents };
294
- }
295
-
296
- private partToGoogle(part: ContentPart): unknown {
297
- switch (part.type) {
298
- case "text":
299
- return { text: part.text };
300
- case "image":
301
- case "audio":
302
- case "file": {
303
- const isUrl =
304
- part.data.startsWith("http://") || part.data.startsWith("https://");
305
- if (isUrl) {
306
- return {
307
- fileData: {
308
- fileUri: part.data,
309
- mimeType:
310
- part.mimeType ??
311
- (part.type === "image"
312
- ? "image/png"
313
- : "application/octet-stream"),
314
- },
315
- };
316
- }
317
- return {
318
- inlineData: {
319
- data: part.data,
320
- mimeType:
321
- part.mimeType ??
322
- (part.type === "image"
323
- ? "image/png"
324
- : part.type === "audio"
325
- ? "audio/mp3"
326
- : "application/octet-stream"),
327
- },
328
- };
329
- }
330
- }
331
- }
332
-
333
- private toGoogleTools(tools: ToolDefinition[]): unknown[] {
334
- return tools.map((t) => ({
335
- name: t.name,
336
- description: t.description,
337
- parameters: t.parameters,
338
- }));
339
- }
340
-
341
- private cleanJsonSchema(
342
- schema: Record<string, unknown>
343
- ): Record<string, unknown> {
344
- const cleaned = { ...schema };
345
- delete cleaned["$schema"];
346
- delete cleaned["$ref"];
347
- delete cleaned["additionalProperties"];
348
-
349
- if (cleaned.properties && typeof cleaned.properties === "object") {
350
- const props: Record<string, unknown> = {};
351
- for (const [key, val] of Object.entries(
352
- cleaned.properties as Record<string, unknown>
353
- )) {
354
- props[key] =
355
- typeof val === "object" && val
356
- ? this.cleanJsonSchema(val as Record<string, unknown>)
357
- : val;
358
- }
359
- cleaned.properties = props;
360
- }
361
-
362
- if (cleaned.items && typeof cleaned.items === "object") {
363
- cleaned.items = this.cleanJsonSchema(
364
- cleaned.items as Record<string, unknown>
365
- );
366
- }
367
-
368
- return cleaned;
369
- }
370
-
371
- private normalizeResponse(response: any): ModelResponse & { thinking?: string } {
372
- const candidate = response.candidates?.[0];
373
- const parts = candidate?.content?.parts ?? [];
374
-
375
- let textContent = "";
376
- let thinkingContent = "";
377
- const toolCalls: ToolCall[] = [];
378
- let toolCallCounter = 0;
379
-
380
- for (const part of parts) {
381
- if (part.thought && part.text) {
382
- thinkingContent += part.text;
383
- } else if (part.text) {
384
- textContent += part.text;
385
- }
386
- if (part.functionCall) {
387
- toolCalls.push({
388
- id: `vertex_tc_${toolCallCounter++}`,
389
- name: part.functionCall.name,
390
- arguments: part.functionCall.args ?? {},
391
- });
392
- }
393
- }
394
-
395
- const thinkingTokens = response.usageMetadata?.thoughtsTokenCount ?? 0;
396
- const usage: TokenUsage = {
397
- promptTokens: response.usageMetadata?.promptTokenCount ?? 0,
398
- completionTokens: response.usageMetadata?.candidatesTokenCount ?? 0,
399
- totalTokens: response.usageMetadata?.totalTokenCount ?? 0,
400
- ...(thinkingTokens > 0 ? { reasoningTokens: thinkingTokens } : {}),
401
- };
402
-
403
- let finishReason: ModelResponse["finishReason"] = "stop";
404
- if (toolCalls.length > 0) finishReason = "tool_calls";
405
- else if (candidate?.finishReason === "MAX_TOKENS")
406
- finishReason = "length";
407
- else if (candidate?.finishReason === "SAFETY")
408
- finishReason = "content_filter";
409
-
410
- const result: ModelResponse & { thinking?: string } = {
411
- message: {
412
- role: "assistant",
413
- content: textContent || null,
414
- toolCalls: toolCalls.length > 0 ? toolCalls : undefined,
415
- },
416
- usage,
417
- finishReason,
418
- raw: response,
419
- };
420
-
421
- if (thinkingContent) {
422
- result.thinking = thinkingContent;
423
- }
424
-
425
- return result;
426
- }
427
- }
@@ -1,107 +0,0 @@
1
- import type { ModelProvider } from "./provider.js";
2
- import { OpenAIProvider } from "./providers/openai.js";
3
- import { AnthropicProvider } from "./providers/anthropic.js";
4
- import { GoogleProvider } from "./providers/google.js";
5
- import { OllamaProvider } from "./providers/ollama.js";
6
- import { VertexAIProvider } from "./providers/vertex.js";
7
-
8
- type ProviderFactory = (
9
- modelId: string,
10
- config?: Record<string, unknown>
11
- ) => ModelProvider;
12
-
13
- export class ModelRegistry {
14
- private factories = new Map<string, ProviderFactory>();
15
-
16
- register(providerId: string, factory: ProviderFactory): void {
17
- this.factories.set(providerId, factory);
18
- }
19
-
20
- resolve(
21
- providerId: string,
22
- modelId: string,
23
- config?: Record<string, unknown>
24
- ): ModelProvider {
25
- const factory = this.factories.get(providerId);
26
- if (!factory) {
27
- throw new Error(
28
- `Unknown provider "${providerId}". Register it first with registry.register().`
29
- );
30
- }
31
- return factory(modelId, config);
32
- }
33
-
34
- has(providerId: string): boolean {
35
- return this.factories.has(providerId);
36
- }
37
- }
38
-
39
- export const registry = new ModelRegistry();
40
-
41
- registry.register(
42
- "openai",
43
- (modelId, config) =>
44
- new OpenAIProvider(modelId, config as { apiKey?: string; baseURL?: string })
45
- );
46
-
47
- registry.register(
48
- "anthropic",
49
- (modelId, config) =>
50
- new AnthropicProvider(modelId, config as { apiKey?: string })
51
- );
52
-
53
- registry.register(
54
- "google",
55
- (modelId, config) =>
56
- new GoogleProvider(modelId, config as { apiKey?: string })
57
- );
58
-
59
- registry.register(
60
- "ollama",
61
- (modelId, config) =>
62
- new OllamaProvider(modelId, config as { host?: string })
63
- );
64
-
65
- export function openai(
66
- modelId: string,
67
- config?: { apiKey?: string; baseURL?: string }
68
- ): ModelProvider {
69
- return registry.resolve("openai", modelId, config);
70
- }
71
-
72
- export function anthropic(
73
- modelId: string,
74
- config?: { apiKey?: string }
75
- ): ModelProvider {
76
- return registry.resolve("anthropic", modelId, config);
77
- }
78
-
79
- export function google(
80
- modelId: string,
81
- config?: { apiKey?: string }
82
- ): ModelProvider {
83
- return registry.resolve("google", modelId, config);
84
- }
85
-
86
- export function ollama(
87
- modelId: string,
88
- config?: { host?: string }
89
- ): ModelProvider {
90
- return registry.resolve("ollama", modelId, config);
91
- }
92
-
93
- registry.register(
94
- "vertex",
95
- (modelId, config) =>
96
- new VertexAIProvider(
97
- modelId,
98
- config as { project?: string; location?: string; credentials?: string }
99
- )
100
- );
101
-
102
- export function vertex(
103
- modelId: string,
104
- config?: { project?: string; location?: string; credentials?: string }
105
- ): ModelProvider {
106
- return registry.resolve("vertex", modelId, config);
107
- }
@@ -1,124 +0,0 @@
1
- export type MessageRole = "system" | "user" | "assistant" | "tool";
2
-
3
- // ── Multi-modal content parts ─────────────────────────────────────────────
4
-
5
- export interface TextPart {
6
- type: "text";
7
- text: string;
8
- }
9
-
10
- export interface ImagePart {
11
- type: "image";
12
- /** Base64-encoded image data OR a URL. */
13
- data: string;
14
- mimeType?: "image/png" | "image/jpeg" | "image/gif" | "image/webp";
15
- }
16
-
17
- export interface AudioPart {
18
- type: "audio";
19
- /** Base64-encoded audio data. */
20
- data: string;
21
- mimeType?: "audio/mp3" | "audio/wav" | "audio/ogg" | "audio/webm";
22
- }
23
-
24
- export interface FilePart {
25
- type: "file";
26
- /** Base64-encoded file data OR a URL. */
27
- data: string;
28
- mimeType: string;
29
- filename?: string;
30
- }
31
-
32
- export type ContentPart = TextPart | ImagePart | AudioPart | FilePart;
33
-
34
- /** Convenience: plain string, or an array of multi-modal content parts. */
35
- export type MessageContent = string | ContentPart[];
36
-
37
- // ── Chat message ──────────────────────────────────────────────────────────
38
-
39
- export interface ChatMessage {
40
- role: MessageRole;
41
- content: MessageContent | null;
42
- toolCalls?: ToolCall[];
43
- toolCallId?: string;
44
- name?: string;
45
- }
46
-
47
- // ── Tool definitions ──────────────────────────────────────────────────────
48
-
49
- export interface ToolCall {
50
- id: string;
51
- name: string;
52
- arguments: Record<string, unknown>;
53
- }
54
-
55
- export interface ToolDefinition {
56
- name: string;
57
- description: string;
58
- parameters: Record<string, unknown>;
59
- }
60
-
61
- // ── Token usage ───────────────────────────────────────────────────────────
62
-
63
- export interface TokenUsage {
64
- promptTokens: number;
65
- completionTokens: number;
66
- totalTokens: number;
67
- reasoningTokens?: number;
68
- }
69
-
70
- // ── Model response ────────────────────────────────────────────────────────
71
-
72
- export interface ModelResponse {
73
- message: ChatMessage;
74
- usage: TokenUsage;
75
- finishReason: "stop" | "tool_calls" | "length" | "content_filter";
76
- raw: unknown;
77
- }
78
-
79
- export type StreamChunk =
80
- | { type: "text"; text: string }
81
- | { type: "thinking"; text: string }
82
- | { type: "tool_call_start"; toolCall: { id: string; name: string } }
83
- | { type: "tool_call_delta"; toolCallId: string; argumentsDelta: string }
84
- | { type: "tool_call_end"; toolCallId: string }
85
- | { type: "finish"; finishReason: string; usage?: TokenUsage };
86
-
87
- // ── Model config ──────────────────────────────────────────────────────────
88
-
89
- export interface ReasoningConfig {
90
- enabled: boolean;
91
- /** Reasoning effort for OpenAI o-series models. */
92
- effort?: "low" | "medium" | "high";
93
- /** Token budget for thinking (Anthropic / Gemini). */
94
- budgetTokens?: number;
95
- }
96
-
97
- export interface ModelConfig {
98
- temperature?: number;
99
- maxTokens?: number;
100
- topP?: number;
101
- stop?: string[];
102
- responseFormat?: "text" | "json" | { type: "json_schema"; schema: Record<string, unknown>; name?: string };
103
- /** Per-request API key override. When provided, the provider uses this key instead of the one set at construction. */
104
- apiKey?: string;
105
- /** Enable extended thinking / reasoning. */
106
- reasoning?: ReasoningConfig;
107
- }
108
-
109
- // ── Helpers ───────────────────────────────────────────────────────────────
110
-
111
- /** Extract the text content from a MessageContent value. */
112
- export function getTextContent(content: MessageContent | null): string {
113
- if (content === null) return "";
114
- if (typeof content === "string") return content;
115
- return content
116
- .filter((p): p is TextPart => p.type === "text")
117
- .map((p) => p.text)
118
- .join("");
119
- }
120
-
121
- /** Check if content has multi-modal parts. */
122
- export function isMultiModal(content: MessageContent | null): content is ContentPart[] {
123
- return Array.isArray(content);
124
- }