@slashfi/agents-sdk 0.15.0 → 0.17.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.
- package/dist/agent-definitions/auth.d.ts.map +1 -1
- package/dist/agent-definitions/auth.js +44 -11
- package/dist/agent-definitions/auth.js.map +1 -1
- package/dist/agent-definitions/integrations.d.ts.map +1 -1
- package/dist/agent-definitions/integrations.js +106 -45
- package/dist/agent-definitions/integrations.js.map +1 -1
- package/dist/agent-definitions/remote-registry.d.ts.map +1 -1
- package/dist/agent-definitions/remote-registry.js +174 -45
- package/dist/agent-definitions/remote-registry.js.map +1 -1
- package/dist/agent-definitions/secrets.d.ts.map +1 -1
- package/dist/agent-definitions/secrets.js +1 -4
- package/dist/agent-definitions/secrets.js.map +1 -1
- package/dist/agent-definitions/users.d.ts.map +1 -1
- package/dist/agent-definitions/users.js +14 -3
- package/dist/agent-definitions/users.js.map +1 -1
- package/dist/define-config.d.ts +125 -0
- package/dist/define-config.d.ts.map +1 -0
- package/dist/define-config.js +75 -0
- package/dist/define-config.js.map +1 -0
- package/dist/define.d.ts +11 -2
- package/dist/define.d.ts.map +1 -1
- package/dist/define.js +57 -26
- package/dist/define.js.map +1 -1
- package/dist/events.d.ts +133 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +57 -0
- package/dist/events.js.map +1 -0
- package/dist/index.d.ts +16 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -3
- package/dist/index.js.map +1 -1
- package/dist/integration-interface.d.ts +3 -3
- package/dist/integration-interface.d.ts.map +1 -1
- package/dist/integration-interface.js +29 -21
- package/dist/integration-interface.js.map +1 -1
- package/dist/integrations-store.d.ts +2 -2
- package/dist/integrations-store.d.ts.map +1 -1
- package/dist/integrations-store.js +3 -3
- package/dist/integrations-store.js.map +1 -1
- package/dist/jwt.d.ts.map +1 -1
- package/dist/jwt.js +7 -5
- package/dist/jwt.js.map +1 -1
- package/dist/key-manager.d.ts.map +1 -1
- package/dist/key-manager.js +5 -3
- package/dist/key-manager.js.map +1 -1
- package/dist/oidc-signin.d.ts +32 -0
- package/dist/oidc-signin.d.ts.map +1 -0
- package/dist/oidc-signin.js +138 -0
- package/dist/oidc-signin.js.map +1 -0
- package/dist/registry-consumer.d.ts +104 -0
- package/dist/registry-consumer.d.ts.map +1 -0
- package/dist/registry-consumer.js +230 -0
- package/dist/registry-consumer.js.map +1 -0
- package/dist/registry.d.ts +20 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +167 -20
- package/dist/registry.js.map +1 -1
- package/dist/secret-collection.d.ts.map +1 -1
- package/dist/secret-collection.js.map +1 -1
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +222 -27
- package/dist/server.js.map +1 -1
- package/dist/test-utils/mock-oidc-server.d.ts +36 -0
- package/dist/test-utils/mock-oidc-server.d.ts.map +1 -0
- package/dist/test-utils/mock-oidc-server.js +96 -0
- package/dist/test-utils/mock-oidc-server.js.map +1 -0
- package/dist/types.d.ts +27 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/agent-definitions/auth.ts +106 -38
- package/src/agent-definitions/integrations.ts +201 -73
- package/src/agent-definitions/remote-registry.ts +262 -65
- package/src/agent-definitions/secrets.ts +22 -8
- package/src/agent-definitions/users.ts +16 -4
- package/src/consumer.test.ts +536 -0
- package/src/define-config.ts +205 -0
- package/src/define.ts +134 -46
- package/src/events.ts +237 -0
- package/src/index.ts +90 -8
- package/src/integration-interface.ts +52 -28
- package/src/integrations-store.ts +9 -5
- package/src/jwt.ts +48 -19
- package/src/key-manager.test.ts +22 -13
- package/src/key-manager.ts +8 -10
- package/src/oidc-signin.ts +223 -0
- package/src/registry-consumer.ts +413 -0
- package/src/registry.ts +237 -29
- package/src/secret-collection.ts +2 -1
- package/src/server.test.ts +304 -238
- package/src/server.ts +371 -69
- package/src/test-utils/mock-oidc-server.ts +123 -0
- package/src/types.ts +80 -18
package/src/registry.ts
CHANGED
|
@@ -4,13 +4,22 @@
|
|
|
4
4
|
* Manages registered agents and handles callAgent requests.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { dirname, resolve } from "node:path";
|
|
8
|
+
import type {
|
|
9
|
+
AgentEvent,
|
|
10
|
+
EventCallback,
|
|
11
|
+
EventType,
|
|
12
|
+
} from "./events.js";
|
|
13
|
+
import { createEventBus } from "./events.js";
|
|
7
14
|
import type {
|
|
8
15
|
AgentAction,
|
|
9
16
|
AgentDefinition,
|
|
17
|
+
AgentRefEntry,
|
|
10
18
|
CallAgentDescribeToolsResponse,
|
|
11
19
|
CallAgentErrorResponse,
|
|
12
20
|
CallAgentExecuteToolResponse,
|
|
13
21
|
CallAgentLearnResponse,
|
|
22
|
+
CallAgentLoadRequest,
|
|
14
23
|
CallAgentLoadResponse,
|
|
15
24
|
CallAgentRequest,
|
|
16
25
|
CallAgentResponse,
|
|
@@ -31,6 +40,25 @@ const DEFAULT_SUPPORTED_ACTIONS: AgentAction[] = [
|
|
|
31
40
|
// Agent Registry Interface
|
|
32
41
|
// ============================================
|
|
33
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Middleware hooks for registry lifecycle actions.
|
|
45
|
+
* Each hook receives the default handler fn and context,
|
|
46
|
+
* giving full control: call default, skip it, try/catch, or enhance.
|
|
47
|
+
*/
|
|
48
|
+
export interface RegistryMiddleware {
|
|
49
|
+
load?: (
|
|
50
|
+
defaultFn: (
|
|
51
|
+
agent: AgentDefinition,
|
|
52
|
+
request: CallAgentLoadRequest,
|
|
53
|
+
) => Promise<CallAgentLoadResponse>,
|
|
54
|
+
ctx: {
|
|
55
|
+
agent: AgentDefinition;
|
|
56
|
+
request: CallAgentLoadRequest;
|
|
57
|
+
registry: AgentRegistry;
|
|
58
|
+
},
|
|
59
|
+
) => Promise<CallAgentLoadResponse>;
|
|
60
|
+
}
|
|
61
|
+
|
|
34
62
|
/**
|
|
35
63
|
* Options for creating an agent registry.
|
|
36
64
|
*/
|
|
@@ -39,6 +67,8 @@ export interface AgentRegistryOptions {
|
|
|
39
67
|
defaultVisibility?: Visibility;
|
|
40
68
|
/** Factory to enrich ToolContext with application-specific data */
|
|
41
69
|
contextFactory?: ContextFactory;
|
|
70
|
+
/** Lifecycle middleware hooks */
|
|
71
|
+
middleware?: RegistryMiddleware;
|
|
42
72
|
}
|
|
43
73
|
|
|
44
74
|
/**
|
|
@@ -62,6 +92,12 @@ export interface AgentRegistry {
|
|
|
62
92
|
|
|
63
93
|
/** Call an agent (execute action) */
|
|
64
94
|
call(request: CallAgentRequest): Promise<CallAgentResponse>;
|
|
95
|
+
|
|
96
|
+
/** Register an event listener (global scope — fires for all agents) */
|
|
97
|
+
on<T extends EventType>(eventType: T, callback: EventCallback<T>): void;
|
|
98
|
+
|
|
99
|
+
/** Emit an event to all listeners. Used by the runtime to push lifecycle events. */
|
|
100
|
+
emit(event: AgentEvent): Promise<void>;
|
|
65
101
|
}
|
|
66
102
|
|
|
67
103
|
// ============================================
|
|
@@ -88,13 +124,16 @@ export interface AgentRegistry {
|
|
|
88
124
|
* Factory function that enriches the base ToolContext with application-specific data.
|
|
89
125
|
* Called before every tool execution.
|
|
90
126
|
*/
|
|
91
|
-
export type ContextFactory = (
|
|
127
|
+
export type ContextFactory = (
|
|
128
|
+
baseCtx: import("./types.js").ToolContext,
|
|
129
|
+
) => import("./types.js").ToolContext;
|
|
92
130
|
|
|
93
131
|
export function createAgentRegistry(
|
|
94
132
|
options: AgentRegistryOptions = {},
|
|
95
133
|
): AgentRegistry {
|
|
96
134
|
const { defaultVisibility = "internal" } = options;
|
|
97
135
|
const agents = new Map<string, AgentDefinition>();
|
|
136
|
+
const eventBus = createEventBus();
|
|
98
137
|
|
|
99
138
|
/**
|
|
100
139
|
* Check if agent supports the requested action.
|
|
@@ -182,9 +221,143 @@ export function createAgentRegistry(
|
|
|
182
221
|
}
|
|
183
222
|
}
|
|
184
223
|
|
|
224
|
+
function resolveRefPath(currentPath: string, ref: string): string {
|
|
225
|
+
if (ref.startsWith("@") && !ref.includes("/")) {
|
|
226
|
+
return `/agents/${ref}`;
|
|
227
|
+
}
|
|
228
|
+
if (ref.startsWith("../") || ref.startsWith("./")) {
|
|
229
|
+
const dir = dirname(currentPath);
|
|
230
|
+
return resolve(dir, ref);
|
|
231
|
+
}
|
|
232
|
+
if (ref.startsWith("/")) {
|
|
233
|
+
return ref;
|
|
234
|
+
}
|
|
235
|
+
return `/agents/${ref}`;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function buildToolsSection(
|
|
239
|
+
ownTools: ToolSchema[],
|
|
240
|
+
agentRefs: AgentRefEntry[],
|
|
241
|
+
): string {
|
|
242
|
+
const hasOwnTools = ownTools.length > 0;
|
|
243
|
+
const hasRefTools = agentRefs.some((ref) => ref.tools.length > 0);
|
|
244
|
+
if (!hasOwnTools && !hasRefTools) return "";
|
|
245
|
+
|
|
246
|
+
const lines: string[] = ["\n\n## Available Tools\n"];
|
|
247
|
+
|
|
248
|
+
if (hasOwnTools) {
|
|
249
|
+
lines.push("| Tool | Description |", "|------|-------------|");
|
|
250
|
+
for (const t of ownTools) {
|
|
251
|
+
lines.push(`| ${t.name} | ${t.description} |`);
|
|
252
|
+
}
|
|
253
|
+
lines.push("");
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
for (const ref of agentRefs) {
|
|
257
|
+
if (ref.tools.length > 0) {
|
|
258
|
+
lines.push(`### From ${ref.key} (${ref.path})\n`);
|
|
259
|
+
lines.push("| Tool | Description |", "|------|-------------|");
|
|
260
|
+
for (const t of ref.tools) {
|
|
261
|
+
lines.push(`| ${t.name} | ${t.description} |`);
|
|
262
|
+
}
|
|
263
|
+
lines.push("");
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return lines.join("\n");
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
async function defaultLoad(
|
|
271
|
+
agent: AgentDefinition,
|
|
272
|
+
request: CallAgentLoadRequest,
|
|
273
|
+
): Promise<CallAgentLoadResponse> {
|
|
274
|
+
const toolSchemas: ToolSchema[] = agent.tools
|
|
275
|
+
.filter((t: ToolDefinition) =>
|
|
276
|
+
checkToolAccess(agent, t.name, request.callerId, request.callerType),
|
|
277
|
+
)
|
|
278
|
+
.map((t: ToolDefinition) => ({
|
|
279
|
+
name: t.name,
|
|
280
|
+
description: t.description,
|
|
281
|
+
inputSchema: t.inputSchema,
|
|
282
|
+
...(t.outputSchema && { outputSchema: t.outputSchema }),
|
|
283
|
+
}));
|
|
284
|
+
|
|
285
|
+
const agentRefs: AgentRefEntry[] = [];
|
|
286
|
+
const refs = agent.config?.refs;
|
|
287
|
+
if (refs) {
|
|
288
|
+
for (const [key, refConfig] of Object.entries(refs)) {
|
|
289
|
+
const refPath = resolveRefPath(agent.path, key);
|
|
290
|
+
const refAgent = agents.get(refPath);
|
|
291
|
+
const allTools = (refAgent?.tools ?? [])
|
|
292
|
+
.filter((t: ToolDefinition) =>
|
|
293
|
+
checkToolAccess(
|
|
294
|
+
refAgent!,
|
|
295
|
+
t.name,
|
|
296
|
+
request.callerId,
|
|
297
|
+
request.callerType,
|
|
298
|
+
),
|
|
299
|
+
)
|
|
300
|
+
.map((t: ToolDefinition) => ({
|
|
301
|
+
name: t.name,
|
|
302
|
+
description: t.description,
|
|
303
|
+
inputSchema: t.inputSchema,
|
|
304
|
+
...(t.outputSchema && { outputSchema: t.outputSchema }),
|
|
305
|
+
}));
|
|
306
|
+
const publicFilter = refAgent?.config?.public?.tools;
|
|
307
|
+
const tools = publicFilter
|
|
308
|
+
? allTools.filter((t) => publicFilter.includes(t.name))
|
|
309
|
+
: allTools;
|
|
310
|
+
agentRefs.push({
|
|
311
|
+
key,
|
|
312
|
+
path: refPath,
|
|
313
|
+
description: refConfig.description ?? key,
|
|
314
|
+
tools,
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const systemPrompt =
|
|
320
|
+
agent.entrypoint + buildToolsSection(toolSchemas, agentRefs);
|
|
321
|
+
|
|
322
|
+
return {
|
|
323
|
+
success: true,
|
|
324
|
+
result: {
|
|
325
|
+
path: agent.path,
|
|
326
|
+
entrypoint: agent.entrypoint,
|
|
327
|
+
systemPrompt,
|
|
328
|
+
contextMessages: [],
|
|
329
|
+
config: agent.config,
|
|
330
|
+
tools: toolSchemas,
|
|
331
|
+
agentRefs,
|
|
332
|
+
},
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
|
|
185
336
|
const registry: AgentRegistry = {
|
|
186
337
|
register(agent: AgentDefinition): void {
|
|
187
338
|
agents.set(agent.path, agent);
|
|
339
|
+
|
|
340
|
+
// Collect agent-level listeners into the bus
|
|
341
|
+
if (agent._listeners) {
|
|
342
|
+
for (const entry of agent._listeners) {
|
|
343
|
+
eventBus._onScoped(entry.eventType, entry.callback, {
|
|
344
|
+
agentPath: agent.path,
|
|
345
|
+
toolName: entry.toolScope,
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// Collect tool-level listeners into the bus
|
|
351
|
+
for (const tool of agent.tools) {
|
|
352
|
+
if (tool._listeners) {
|
|
353
|
+
for (const entry of tool._listeners) {
|
|
354
|
+
eventBus._onScoped(entry.eventType, entry.callback, {
|
|
355
|
+
agentPath: agent.path,
|
|
356
|
+
toolName: tool.name,
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
188
361
|
},
|
|
189
362
|
|
|
190
363
|
get(path: string): AgentDefinition | undefined {
|
|
@@ -203,6 +376,14 @@ export function createAgentRegistry(
|
|
|
203
376
|
return Array.from(agents.keys());
|
|
204
377
|
},
|
|
205
378
|
|
|
379
|
+
on<T extends EventType>(eventType: T, callback: EventCallback<T>): void {
|
|
380
|
+
eventBus.on(eventType, callback);
|
|
381
|
+
},
|
|
382
|
+
|
|
383
|
+
async emit(event: AgentEvent): Promise<void> {
|
|
384
|
+
await eventBus.emit(event);
|
|
385
|
+
},
|
|
386
|
+
|
|
206
387
|
async call(request: CallAgentRequest): Promise<CallAgentResponse> {
|
|
207
388
|
const agent = agents.get(request.path);
|
|
208
389
|
|
|
@@ -311,15 +492,59 @@ export function createAgentRegistry(
|
|
|
311
492
|
error: `Tool ${request.tool} has no execute function`,
|
|
312
493
|
} as CallAgentErrorResponse;
|
|
313
494
|
}
|
|
314
|
-
|
|
495
|
+
|
|
496
|
+
// Emit tool/call before execution
|
|
497
|
+
const startMs = Date.now();
|
|
498
|
+
await eventBus.emit({
|
|
499
|
+
type: "tool/call",
|
|
500
|
+
agentPath: agent.path,
|
|
501
|
+
tool: request.tool!,
|
|
502
|
+
params: request.params,
|
|
503
|
+
timestamp: startMs,
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
let result: unknown;
|
|
507
|
+
try {
|
|
508
|
+
result = await tool.execute(request.params, ctx);
|
|
509
|
+
} catch (err) {
|
|
510
|
+
// Emit tool/error on failure
|
|
511
|
+
await eventBus.emit({
|
|
512
|
+
type: "tool/error",
|
|
513
|
+
agentPath: agent.path,
|
|
514
|
+
tool: request.tool!,
|
|
515
|
+
params: request.params,
|
|
516
|
+
error: err,
|
|
517
|
+
durationMs: Date.now() - startMs,
|
|
518
|
+
timestamp: Date.now(),
|
|
519
|
+
}).catch(() => {}); // don't let emit error mask tool error
|
|
520
|
+
|
|
521
|
+
return {
|
|
522
|
+
success: false,
|
|
523
|
+
error: err instanceof Error ? err.message : String(err),
|
|
524
|
+
code: "TOOL_EXECUTION_ERROR",
|
|
525
|
+
} as CallAgentErrorResponse;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// Emit tool/result after success
|
|
529
|
+
await eventBus.emit({
|
|
530
|
+
type: "tool/result",
|
|
531
|
+
agentPath: agent.path,
|
|
532
|
+
tool: request.tool!,
|
|
533
|
+
params: request.params,
|
|
534
|
+
result,
|
|
535
|
+
durationMs: Date.now() - startMs,
|
|
536
|
+
timestamp: Date.now(),
|
|
537
|
+
});
|
|
538
|
+
|
|
315
539
|
return {
|
|
316
540
|
success: true,
|
|
317
541
|
result,
|
|
318
542
|
} as CallAgentExecuteToolResponse;
|
|
319
|
-
} catch (
|
|
543
|
+
} catch (outerErr) {
|
|
544
|
+
// Catch-all for unexpected errors (e.g., emit failures)
|
|
320
545
|
return {
|
|
321
546
|
success: false,
|
|
322
|
-
error:
|
|
547
|
+
error: outerErr instanceof Error ? outerErr.message : String(outerErr),
|
|
323
548
|
code: "TOOL_EXECUTION_ERROR",
|
|
324
549
|
} as CallAgentErrorResponse;
|
|
325
550
|
}
|
|
@@ -352,31 +577,14 @@ export function createAgentRegistry(
|
|
|
352
577
|
}
|
|
353
578
|
|
|
354
579
|
case "load": {
|
|
355
|
-
|
|
356
|
-
.
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
)
|
|
364
|
-
.map((t: ToolDefinition) => ({
|
|
365
|
-
name: t.name,
|
|
366
|
-
description: t.description,
|
|
367
|
-
inputSchema: t.inputSchema,
|
|
368
|
-
...(t.outputSchema && { outputSchema: t.outputSchema }),
|
|
369
|
-
}));
|
|
370
|
-
|
|
371
|
-
return {
|
|
372
|
-
success: true,
|
|
373
|
-
result: {
|
|
374
|
-
path: agent.path,
|
|
375
|
-
entrypoint: agent.entrypoint,
|
|
376
|
-
config: agent.config,
|
|
377
|
-
tools: toolSchemas,
|
|
378
|
-
},
|
|
379
|
-
} as CallAgentLoadResponse;
|
|
580
|
+
if (options.middleware?.load) {
|
|
581
|
+
return options.middleware.load(defaultLoad, {
|
|
582
|
+
agent,
|
|
583
|
+
request,
|
|
584
|
+
registry,
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
return defaultLoad(agent, request);
|
|
380
588
|
}
|
|
381
589
|
|
|
382
590
|
case "learn": {
|
package/src/secret-collection.ts
CHANGED
|
@@ -44,7 +44,8 @@ export const pendingCollections = new Map<string, PendingCollection>();
|
|
|
44
44
|
|
|
45
45
|
/** Generate a random one-time token for secret collection */
|
|
46
46
|
export function generateCollectionToken(): string {
|
|
47
|
-
const chars =
|
|
47
|
+
const chars =
|
|
48
|
+
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
48
49
|
let token = "";
|
|
49
50
|
for (let i = 0; i < 48; i++) {
|
|
50
51
|
token += chars[Math.floor(Math.random() * chars.length)];
|