@slashfi/agents-sdk 0.25.0 → 0.26.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/bm25.d.ts +46 -0
- package/dist/bm25.d.ts.map +1 -0
- package/dist/bm25.js +103 -0
- package/dist/bm25.js.map +1 -0
- package/dist/cjs/bm25.js +106 -0
- package/dist/cjs/bm25.js.map +1 -0
- package/dist/cjs/events.js.map +1 -1
- package/dist/cjs/index.js +6 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/registry.js +198 -169
- package/dist/cjs/registry.js.map +1 -1
- package/dist/cjs/server.js +105 -1
- package/dist/cjs/server.js.map +1 -1
- package/dist/events.d.ts +62 -9
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/registry.d.ts +12 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +198 -169
- package/dist/registry.js.map +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +105 -1
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
- package/src/bm25.test.ts +86 -0
- package/src/bm25.ts +146 -0
- package/src/events.ts +60 -13
- package/src/index.ts +19 -0
- package/src/registry.ts +56 -8
- package/src/server.ts +126 -1
package/src/registry.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { dirname, resolve } from "node:path";
|
|
8
|
-
import type { AgentEvent, EventCallback, EventType } from "./events.js";
|
|
8
|
+
import type { AgentEvent, BaseEvent, CustomEventMap, EventCallback, EventType } from "./events.js";
|
|
9
9
|
import { createEventBus } from "./events.js";
|
|
10
10
|
import type { SerializedAgentDefinition } from "./serialized.js";
|
|
11
11
|
import type {
|
|
@@ -55,6 +55,7 @@ export interface RegistryMiddleware {
|
|
|
55
55
|
registry: AgentRegistry;
|
|
56
56
|
},
|
|
57
57
|
) => Promise<CallAgentLoadResponse>;
|
|
58
|
+
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
/**
|
|
@@ -97,6 +98,21 @@ export interface AgentRegistry {
|
|
|
97
98
|
|
|
98
99
|
/** Emit an event to all listeners. Used by the runtime to push lifecycle events. */
|
|
99
100
|
emit(event: AgentEvent): Promise<void>;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Trigger a custom event. Only accepts custom event types (not system events
|
|
104
|
+
* like tool/call, tool/result, etc. which are managed by the runtime).
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```ts
|
|
108
|
+
* // After augmenting CustomEventMap:
|
|
109
|
+
* registry.trigger('callback/resolve', { type: 'callback/resolve', ... });
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
trigger<T extends Extract<keyof CustomEventMap, string>>(
|
|
113
|
+
eventType: T,
|
|
114
|
+
event: CustomEventMap[T] & BaseEvent,
|
|
115
|
+
): Promise<void>;
|
|
100
116
|
}
|
|
101
117
|
|
|
102
118
|
// ============================================
|
|
@@ -412,7 +428,7 @@ export function createAgentRegistry(
|
|
|
412
428
|
};
|
|
413
429
|
}
|
|
414
430
|
|
|
415
|
-
const
|
|
431
|
+
const registryObj: AgentRegistry = {
|
|
416
432
|
register(input: AgentDefinition | SerializedAgentDefinition): void {
|
|
417
433
|
let agent: AgentDefinition;
|
|
418
434
|
if (isSerialized(input)) {
|
|
@@ -473,7 +489,42 @@ export function createAgentRegistry(
|
|
|
473
489
|
await eventBus.emit(event);
|
|
474
490
|
},
|
|
475
491
|
|
|
492
|
+
async trigger<T extends Extract<keyof CustomEventMap, string>>(
|
|
493
|
+
_eventType: T,
|
|
494
|
+
event: CustomEventMap[T] & BaseEvent,
|
|
495
|
+
): Promise<void> {
|
|
496
|
+
await eventBus.emit(event as never);
|
|
497
|
+
},
|
|
498
|
+
|
|
476
499
|
async call(request: CallAgentRequest): Promise<CallAgentResponse> {
|
|
500
|
+
// Emit call event — listeners can next()/resolve() to control flow
|
|
501
|
+
let intercepted: CallAgentResponse | undefined;
|
|
502
|
+
let nextCalled = false;
|
|
503
|
+
let nextResult: CallAgentResponse | undefined;
|
|
504
|
+
await eventBus.emit({
|
|
505
|
+
type: "call",
|
|
506
|
+
agentPath: request.path,
|
|
507
|
+
timestamp: Date.now(),
|
|
508
|
+
request,
|
|
509
|
+
async next() {
|
|
510
|
+
nextCalled = true;
|
|
511
|
+
nextResult = await callInternal(request);
|
|
512
|
+
return nextResult;
|
|
513
|
+
},
|
|
514
|
+
resolve(response: CallAgentResponse) {
|
|
515
|
+
intercepted = response;
|
|
516
|
+
},
|
|
517
|
+
});
|
|
518
|
+
if (intercepted) return intercepted;
|
|
519
|
+
if (nextCalled) return nextResult!;
|
|
520
|
+
// No listener engaged — run default
|
|
521
|
+
return callInternal(request);
|
|
522
|
+
},
|
|
523
|
+
};
|
|
524
|
+
|
|
525
|
+
return registryObj;
|
|
526
|
+
|
|
527
|
+
async function callInternal(request: CallAgentRequest): Promise<CallAgentResponse> {
|
|
477
528
|
const agent = agents.get(request.path);
|
|
478
529
|
|
|
479
530
|
if (!agent) {
|
|
@@ -673,7 +724,7 @@ export function createAgentRegistry(
|
|
|
673
724
|
return options.middleware.load(defaultLoad, {
|
|
674
725
|
agent,
|
|
675
726
|
request,
|
|
676
|
-
registry,
|
|
727
|
+
registry: registryObj,
|
|
677
728
|
});
|
|
678
729
|
}
|
|
679
730
|
return defaultLoad(agent, request);
|
|
@@ -717,8 +768,5 @@ export function createAgentRegistry(
|
|
|
717
768
|
} as CallAgentErrorResponse;
|
|
718
769
|
}
|
|
719
770
|
}
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
return registry;
|
|
724
|
-
}
|
|
771
|
+
}
|
|
772
|
+
}
|
package/src/server.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Minimal JSON-RPC server implementing the MCP protocol for agent interaction.
|
|
5
5
|
* Handles only core SDK concerns:
|
|
6
6
|
* - MCP protocol (initialize, tools/list, tools/call)
|
|
7
|
-
* - Agent registry routing (call_agent, list_agents)
|
|
7
|
+
* - Agent registry routing (call_agent, list_agents, search_agent_tools)
|
|
8
8
|
* - Auth resolution (Bearer tokens, root key, JWT)
|
|
9
9
|
* - OAuth2 token exchange (client_credentials)
|
|
10
10
|
* - Health check
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
type SecretStore,
|
|
31
31
|
processSecretParams,
|
|
32
32
|
} from "./agent-definitions/secrets.js";
|
|
33
|
+
import { type BM25Document, createBM25Index } from "./bm25.js";
|
|
33
34
|
import { verifyJwt } from "./jwt.js";
|
|
34
35
|
import type { SigningKey } from "./jwt.js";
|
|
35
36
|
import {
|
|
@@ -442,6 +443,32 @@ function getToolDefinitions() {
|
|
|
442
443
|
properties: {},
|
|
443
444
|
},
|
|
444
445
|
},
|
|
446
|
+
{
|
|
447
|
+
name: "search_agent_tools",
|
|
448
|
+
description:
|
|
449
|
+
"Search across all registered agent tools using natural language. Returns tools ranked by relevance using BM25 scoring.",
|
|
450
|
+
inputSchema: {
|
|
451
|
+
type: "object",
|
|
452
|
+
properties: {
|
|
453
|
+
query: {
|
|
454
|
+
type: "string",
|
|
455
|
+
description:
|
|
456
|
+
"Natural language search query (e.g. 'send a message', 'database query')",
|
|
457
|
+
},
|
|
458
|
+
agents: {
|
|
459
|
+
type: "array",
|
|
460
|
+
items: { type: "string" },
|
|
461
|
+
description:
|
|
462
|
+
"Optional list of agent paths to search within (e.g. ['@notifications', '@db']). Searches all agents if omitted.",
|
|
463
|
+
},
|
|
464
|
+
limit: {
|
|
465
|
+
type: "number",
|
|
466
|
+
description: "Maximum number of results to return (default: 10)",
|
|
467
|
+
},
|
|
468
|
+
},
|
|
469
|
+
required: ["query"],
|
|
470
|
+
},
|
|
471
|
+
},
|
|
445
472
|
];
|
|
446
473
|
}
|
|
447
474
|
|
|
@@ -609,6 +636,104 @@ export function createAgentServer(
|
|
|
609
636
|
});
|
|
610
637
|
}
|
|
611
638
|
|
|
639
|
+
case "search_agent_tools": {
|
|
640
|
+
const { query, agents: agentFilter, limit: resultLimit } = args as {
|
|
641
|
+
query: string;
|
|
642
|
+
agents?: string[];
|
|
643
|
+
limit?: number;
|
|
644
|
+
};
|
|
645
|
+
|
|
646
|
+
const agents = registry.list();
|
|
647
|
+
const visible = agents.filter((agent) => {
|
|
648
|
+
if (!canSeeAgent(agent, auth)) return false;
|
|
649
|
+
if (agentFilter && agentFilter.length > 0) {
|
|
650
|
+
return agentFilter.includes(agent.path);
|
|
651
|
+
}
|
|
652
|
+
return true;
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
// Build search documents from all visible tools
|
|
656
|
+
const documents: (BM25Document & {
|
|
657
|
+
agentPath: string;
|
|
658
|
+
toolName: string;
|
|
659
|
+
description: string;
|
|
660
|
+
agentName?: string;
|
|
661
|
+
agentDescription?: string;
|
|
662
|
+
})[] = [];
|
|
663
|
+
|
|
664
|
+
for (const agent of visible) {
|
|
665
|
+
const visibleTools = agent.tools.filter((t) => {
|
|
666
|
+
const tv = t.visibility ?? "internal";
|
|
667
|
+
if (auth?.isRoot) return true;
|
|
668
|
+
if (tv === "public") return true;
|
|
669
|
+
if (
|
|
670
|
+
tv === "authenticated" &&
|
|
671
|
+
auth?.callerId &&
|
|
672
|
+
auth.callerId !== "anonymous"
|
|
673
|
+
)
|
|
674
|
+
return true;
|
|
675
|
+
if (tv === "internal" && auth) return true;
|
|
676
|
+
return false;
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
for (const tool of visibleTools) {
|
|
680
|
+
// Build searchable text from tool name, description, agent context, and schema
|
|
681
|
+
const parts = [
|
|
682
|
+
tool.name,
|
|
683
|
+
tool.description,
|
|
684
|
+
agent.config?.name ?? "",
|
|
685
|
+
agent.config?.description ?? "",
|
|
686
|
+
agent.path,
|
|
687
|
+
];
|
|
688
|
+
|
|
689
|
+
// Include property names and descriptions from input schema
|
|
690
|
+
const schema = tool.inputSchema as any;
|
|
691
|
+
if (schema?.properties) {
|
|
692
|
+
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
693
|
+
parts.push(key);
|
|
694
|
+
if ((prop as any)?.description) {
|
|
695
|
+
parts.push((prop as any).description);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
documents.push({
|
|
701
|
+
id: `${agent.path}/${tool.name}`,
|
|
702
|
+
text: parts.join(" "),
|
|
703
|
+
agentPath: agent.path,
|
|
704
|
+
toolName: tool.name,
|
|
705
|
+
description: tool.description,
|
|
706
|
+
agentName: agent.config?.name,
|
|
707
|
+
agentDescription: agent.config?.description,
|
|
708
|
+
});
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
const index = createBM25Index(documents);
|
|
713
|
+
const results = index.search(query, resultLimit ?? 10);
|
|
714
|
+
|
|
715
|
+
// Map results back to tool details
|
|
716
|
+
const docMap = new Map(documents.map((d) => [d.id, d]));
|
|
717
|
+
const matches = results.map((r) => {
|
|
718
|
+
const doc = docMap.get(r.id)!;
|
|
719
|
+
return {
|
|
720
|
+
agentPath: doc.agentPath,
|
|
721
|
+
tool: doc.toolName,
|
|
722
|
+
description: doc.description,
|
|
723
|
+
agentName: doc.agentName,
|
|
724
|
+
agentDescription: doc.agentDescription,
|
|
725
|
+
score: r.score,
|
|
726
|
+
};
|
|
727
|
+
});
|
|
728
|
+
|
|
729
|
+
return mcpResult({
|
|
730
|
+
success: true,
|
|
731
|
+
query,
|
|
732
|
+
results: matches,
|
|
733
|
+
total: matches.length,
|
|
734
|
+
});
|
|
735
|
+
}
|
|
736
|
+
|
|
612
737
|
default:
|
|
613
738
|
throw new Error(`Unknown tool: ${toolName}`);
|
|
614
739
|
}
|