@slashfi/agents-sdk 0.1.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/src/build.ts ADDED
@@ -0,0 +1,238 @@
1
+ /**
2
+ * Build Agents
3
+ *
4
+ * Scans a directory for agent definitions and generates a registry file.
5
+ *
6
+ * Convention:
7
+ * - Agent directories start with `@` (e.g., `@my-agent`)
8
+ * - Each agent has:
9
+ * - `entrypoint.md` - System prompt
10
+ * - `agent.config.ts` - Configuration (exports default AgentConfig)
11
+ * - `*.tool.ts` - Tool definitions (exports `{toolName}Tool`)
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * // scripts/build-agents.ts
16
+ * import { buildAgents } from '@slashfi/agents-sdk';
17
+ *
18
+ * await buildAgents({
19
+ * agentsDir: './src/agents',
20
+ * outFile: './src/agents/_generated-registry.ts',
21
+ * });
22
+ * ```
23
+ */
24
+
25
+ import { readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
26
+ import { join } from "node:path";
27
+
28
+ /**
29
+ * Options for building agents.
30
+ */
31
+ export interface BuildAgentsOptions {
32
+ /** Directory containing agent folders (e.g., './src/agents') */
33
+ agentsDir: string;
34
+
35
+ /** Output file path for the generated registry */
36
+ outFile: string;
37
+
38
+ /**
39
+ * Import path for the SDK.
40
+ * @default '@slashfi/agents-sdk'
41
+ */
42
+ sdkImport?: string;
43
+
44
+ /**
45
+ * Default visibility for agents.
46
+ * @default 'internal'
47
+ */
48
+ defaultVisibility?: "public" | "internal" | "private";
49
+
50
+ /**
51
+ * Whether to use double quotes for strings.
52
+ * @default false (single quotes)
53
+ */
54
+ doubleQuotes?: boolean;
55
+ }
56
+
57
+ /**
58
+ * Result of building agents.
59
+ */
60
+ export interface BuildAgentsResult {
61
+ /** Number of agents processed */
62
+ agentCount: number;
63
+
64
+ /** Paths of agents that were processed */
65
+ agents: string[];
66
+
67
+ /** Agents that were skipped (missing required files) */
68
+ skipped: string[];
69
+
70
+ /** Path to the generated output file */
71
+ outFile: string;
72
+ }
73
+
74
+ /**
75
+ * Convert kebab-case to camelCase.
76
+ */
77
+ function toCamelCase(str: string): string {
78
+ return str
79
+ .split("-")
80
+ .map((part, i) =>
81
+ i === 0 ? part : part.charAt(0).toUpperCase() + part.slice(1),
82
+ )
83
+ .join("");
84
+ }
85
+
86
+ /**
87
+ * Escape a string for use in a JavaScript string literal.
88
+ */
89
+ function escapeString(str: string, quote: string): string {
90
+ return str
91
+ .replace(/\\/g, "\\\\")
92
+ .replace(new RegExp(quote, "g"), `\\${quote}`)
93
+ .replace(/\n/g, "\\n")
94
+ .replace(/\r/g, "\\r")
95
+ .replace(/\t/g, "\\t");
96
+ }
97
+
98
+ /**
99
+ * Build agents from a directory.
100
+ *
101
+ * Scans the given directory for agent folders (starting with `@`) and generates
102
+ * a TypeScript file that creates and populates an agent registry.
103
+ */
104
+ export async function buildAgents(
105
+ options: BuildAgentsOptions,
106
+ ): Promise<BuildAgentsResult> {
107
+ const {
108
+ agentsDir,
109
+ outFile,
110
+ sdkImport = "@slashfi/agents-sdk",
111
+ defaultVisibility = "internal",
112
+ doubleQuotes = false,
113
+ } = options;
114
+
115
+ const q = doubleQuotes ? '"' : "'";
116
+ const agents: string[] = [];
117
+ const skipped: string[] = [];
118
+
119
+ // Find all agent directories (start with @)
120
+ const agentDirs = readdirSync(agentsDir).filter((name) => {
121
+ if (!name.startsWith("@")) return false;
122
+ try {
123
+ const stat = statSync(join(agentsDir, name));
124
+ return stat.isDirectory();
125
+ } catch {
126
+ return false;
127
+ }
128
+ });
129
+
130
+ const imports: string[] = [];
131
+ const registrations: string[] = [];
132
+ const exportItems: string[] = [];
133
+
134
+ for (const agentDir of agentDirs) {
135
+ const agentPath = join(agentsDir, agentDir);
136
+ const entrypointPath = join(agentPath, "entrypoint.md");
137
+ const configPath = join(agentPath, "agent.config.ts");
138
+
139
+ // Check if required files exist
140
+ try {
141
+ statSync(entrypointPath);
142
+ statSync(configPath);
143
+ } catch {
144
+ skipped.push(agentDir);
145
+ continue;
146
+ }
147
+
148
+ // Read entrypoint content
149
+ const entrypoint = readFileSync(entrypointPath, "utf-8");
150
+
151
+ // Find tool files
152
+ const toolFiles = readdirSync(agentPath).filter((f) =>
153
+ f.endsWith(".tool.ts"),
154
+ );
155
+
156
+ // Generate variable name from directory (e.g., @product-applications -> productApplications)
157
+ const varName = toCamelCase(agentDir.slice(1));
158
+
159
+ // Add config import
160
+ imports.push(
161
+ `import ${varName}Config from ${q}./${agentDir}/agent.config.js${q};`,
162
+ );
163
+
164
+ // Add tool imports and collect tool info
165
+ const toolEntries: Array<{ varName: string; name: string }> = [];
166
+ for (const toolFile of toolFiles) {
167
+ const baseName = toolFile.replace(".tool.ts", "");
168
+ // Convert kebab-case to camelCase for JS variable: get-status -> getStatusTool
169
+ const toolVarName = `${toCamelCase(baseName)}Tool`;
170
+ // Tool name is just the filename (kebab-case): get-status
171
+ const toolName = baseName;
172
+ imports.push(
173
+ `import { ${toolVarName} } from ${q}./${agentDir}/${toolFile.replace(".ts", ".js")}${q};`,
174
+ );
175
+ toolEntries.push({ varName: toolVarName, name: toolName });
176
+ }
177
+
178
+ // Read config to get the path override if specified
179
+ const configContent = readFileSync(configPath, "utf-8");
180
+ const pathMatch = configContent.match(/path:\s*['"]([^'"]+)['"]/);
181
+ const registeredPath = pathMatch ? pathMatch[1] : agentDir;
182
+
183
+ // Generate tools array with name override
184
+ const toolsArray = toolEntries
185
+ .map((t) => `{ ...${t.varName}, name: ${q}${t.name}${q} }`)
186
+ .join(", ");
187
+
188
+ // Generate agent definition
189
+ const entrypointEscaped = escapeString(entrypoint, q);
190
+ registrations.push(`
191
+ const ${varName}Agent = defineAgent({
192
+ path: ${q}${registeredPath}${q},
193
+ entrypoint: ${q}${entrypointEscaped}${q},
194
+ config: ${varName}Config,
195
+ tools: [${toolsArray}],
196
+ visibility: ${q}${defaultVisibility}${q},
197
+ });
198
+ agentRegistry.register(${varName}Agent);`);
199
+
200
+ exportItems.push(` ${varName}: ${varName}Agent,`);
201
+ agents.push(registeredPath);
202
+ }
203
+
204
+ const output = `/**
205
+ * AUTO-GENERATED FILE - DO NOT EDIT
206
+ * Generated by buildAgents from ${sdkImport}
207
+ *
208
+ * This file bundles agent entrypoints at build time.
209
+ * Tool names are derived from filenames (kebab-case).
210
+ */
211
+
212
+ import { createAgentRegistry, defineAgent } from ${q}${sdkImport}${q};
213
+
214
+ ${imports.join("\n")}
215
+
216
+ // Create registry
217
+ export const agentRegistry = createAgentRegistry({
218
+ defaultVisibility: ${q}${defaultVisibility}${q},
219
+ });
220
+
221
+ // Register agents
222
+ ${registrations.join("\n")}
223
+
224
+ // Export agents
225
+ export const agents = {
226
+ ${exportItems.join("\n")}
227
+ };
228
+ `;
229
+
230
+ writeFileSync(outFile, output);
231
+
232
+ return {
233
+ agentCount: agents.length,
234
+ agents,
235
+ skipped,
236
+ outFile,
237
+ };
238
+ }
package/src/define.ts ADDED
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Define Agent and Tool Functions
3
+ *
4
+ * Factory functions for creating agent and tool definitions.
5
+ */
6
+
7
+ import type {
8
+ AgentConfig,
9
+ AgentDefinition,
10
+ AgentRuntime,
11
+ JsonSchema,
12
+ ToolContext,
13
+ ToolDefinition,
14
+ Visibility,
15
+ } from "./types.js";
16
+
17
+ // ============================================
18
+ // defineTool
19
+ // ============================================
20
+
21
+ export interface DefineToolOptions<
22
+ TContext extends ToolContext = ToolContext,
23
+ TInput = unknown,
24
+ TOutput = unknown,
25
+ > {
26
+ /** Tool name (unique within agent) */
27
+ name: string;
28
+
29
+ /** Short description for tool discovery */
30
+ description: string;
31
+
32
+ /** JSON Schema for input parameters */
33
+ inputSchema: JsonSchema;
34
+
35
+ /** JSON Schema for output (optional) */
36
+ outputSchema?: JsonSchema;
37
+
38
+ /** Visibility level */
39
+ visibility?: Visibility;
40
+
41
+ /** Explicit allowed callers */
42
+ allowedCallers?: string[];
43
+
44
+ /** Execute function */
45
+ execute: (input: TInput, ctx: TContext) => Promise<TOutput>;
46
+ }
47
+
48
+ /**
49
+ * Create a tool definition.
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * const greet = defineTool({
54
+ * name: 'greet',
55
+ * description: 'Greet a user',
56
+ * inputSchema: {
57
+ * type: 'object',
58
+ * properties: {
59
+ * name: { type: 'string', description: 'Name to greet' }
60
+ * },
61
+ * required: ['name']
62
+ * },
63
+ * execute: async (input) => ({ message: `Hello, ${input.name}!` })
64
+ * });
65
+ * ```
66
+ */
67
+ export function defineTool<
68
+ TContext extends ToolContext = ToolContext,
69
+ TInput = unknown,
70
+ TOutput = unknown,
71
+ >(
72
+ options: DefineToolOptions<TContext, TInput, TOutput>,
73
+ ): ToolDefinition<TContext, TInput, TOutput> {
74
+ return {
75
+ name: options.name,
76
+ description: options.description,
77
+ inputSchema: options.inputSchema,
78
+ outputSchema: options.outputSchema,
79
+ visibility: options.visibility,
80
+ allowedCallers: options.allowedCallers,
81
+ execute: options.execute,
82
+ };
83
+ }
84
+
85
+ // ============================================
86
+ // defineAgent
87
+ // ============================================
88
+
89
+ export interface DefineAgentOptions<
90
+ TContext extends ToolContext = ToolContext,
91
+ > {
92
+ /** Agent path (e.g., '@example', '/agents/my-agent') */
93
+ path: string;
94
+
95
+ /** System prompt / entrypoint content */
96
+ entrypoint: string;
97
+
98
+ /** Agent configuration */
99
+ config?: AgentConfig;
100
+
101
+ /** Tools provided by this agent */
102
+ tools?: ToolDefinition<TContext, unknown, unknown>[];
103
+
104
+ /**
105
+ * Runtime hooks factory.
106
+ * Called once to create the runtime for this agent.
107
+ */
108
+ runtime?: () => AgentRuntime;
109
+
110
+ /** Visibility level */
111
+ visibility?: Visibility;
112
+
113
+ /** Explicit allowed callers */
114
+ allowedCallers?: string[];
115
+ }
116
+
117
+ /**
118
+ * Create an agent definition.
119
+ *
120
+ * @example
121
+ * ```typescript
122
+ * const agent = defineAgent({
123
+ * path: '@my-agent',
124
+ * entrypoint: 'You are a helpful assistant.',
125
+ * config: {
126
+ * name: 'My Agent',
127
+ * description: 'A helpful agent'
128
+ * },
129
+ * tools: [greet, echo],
130
+ * runtime: () => ({
131
+ * onInvoke: async (ctx) => {
132
+ * console.log(`Invoked with: ${ctx.prompt}`);
133
+ * },
134
+ * onTick: async (ctx) => {
135
+ * console.log(`Tick at ${ctx.timestamp}`);
136
+ * }
137
+ * })
138
+ * });
139
+ * ```
140
+ */
141
+ export function defineAgent<TContext extends ToolContext = ToolContext>(
142
+ options: DefineAgentOptions<TContext>,
143
+ ): AgentDefinition<TContext> {
144
+ return {
145
+ path: options.path,
146
+ entrypoint: options.entrypoint,
147
+ config: options.config,
148
+ tools: options.tools ?? [],
149
+ runtime: options.runtime,
150
+ visibility: options.visibility,
151
+ allowedCallers: options.allowedCallers,
152
+ };
153
+ }
package/src/index.ts ADDED
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Agents SDK
3
+ *
4
+ * SDK for building AI agents with tool definitions, JSON-RPC servers,
5
+ * and built-in OAuth2 authentication.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import {
10
+ * defineAgent,
11
+ * defineTool,
12
+ * createAgentRegistry,
13
+ * createAgentServer,
14
+ * createAuthAgent,
15
+ * } from '@slashfi/agents-sdk';
16
+ *
17
+ * // Define a tool
18
+ * const greet = defineTool({
19
+ * name: 'greet',
20
+ * description: 'Greet a user',
21
+ * inputSchema: {
22
+ * type: 'object',
23
+ * properties: {
24
+ * name: { type: 'string', description: 'Name to greet' }
25
+ * },
26
+ * required: ['name']
27
+ * },
28
+ * execute: async (input) => ({ message: `Hello, ${input.name}!` })
29
+ * });
30
+ *
31
+ * // Define an agent
32
+ * const agent = defineAgent({
33
+ * path: '@my-agent',
34
+ * entrypoint: 'You are a helpful assistant.',
35
+ * tools: [greet]
36
+ * });
37
+ *
38
+ * // Create registry with auth
39
+ * const registry = createAgentRegistry();
40
+ * registry.register(createAuthAgent({ rootKey: process.env.ROOT_KEY! }));
41
+ * registry.register(agent);
42
+ *
43
+ * // Start server - auth auto-detected
44
+ * const server = createAgentServer(registry, { port: 3000 });
45
+ * await server.start();
46
+ * ```
47
+ *
48
+ * @packageDocumentation
49
+ */
50
+
51
+ // Types
52
+ export type {
53
+ AgentAction,
54
+ AgentConfig,
55
+ AgentDefinition,
56
+ AgentRuntime,
57
+ CallAgentAskRequest,
58
+ CallAgentAskResponse,
59
+ CallAgentDescribeToolsRequest,
60
+ CallAgentDescribeToolsResponse,
61
+ CallAgentErrorResponse,
62
+ CallAgentExecuteToolRequest,
63
+ CallAgentExecuteToolResponse,
64
+ CallAgentInvokeRequest,
65
+ CallAgentInvokeResponse,
66
+ CallAgentLearnRequest,
67
+ CallAgentLearnResponse,
68
+ CallAgentLoadRequest,
69
+ CallAgentLoadResponse,
70
+ CallAgentRequest,
71
+ CallAgentResponse,
72
+ CallerType,
73
+ CoreContext,
74
+ InvokeContext,
75
+ JsonSchema,
76
+ LearnContext,
77
+ MessageContext,
78
+ StepContext,
79
+ TickContext,
80
+ ToolContext,
81
+ ToolDefinition,
82
+ ToolSchema,
83
+ ToolSelectionContext,
84
+ Visibility,
85
+ } from "./types.js";
86
+
87
+ // Define functions
88
+ export { defineAgent, defineTool } from "./define.js";
89
+ export type { DefineAgentOptions, DefineToolOptions } from "./define.js";
90
+
91
+ // Registry
92
+ export { createAgentRegistry } from "./registry.js";
93
+ export type { AgentRegistry, AgentRegistryOptions } from "./registry.js";
94
+
95
+ // Server
96
+ export { createAgentServer } from "./server.js";
97
+ export type { AgentServer, AgentServerOptions } from "./server.js";
98
+
99
+ // Auth
100
+ export { createAuthAgent, createMemoryAuthStore } from "./auth.js";
101
+ export type {
102
+ AuthClient,
103
+ AuthIdentity,
104
+ AuthStore,
105
+ AuthToken,
106
+ CreateAuthAgentOptions,
107
+ } from "./auth.js";
108
+
109
+ // Build
110
+ export { buildAgents } from "./build.js";
111
+ export type { BuildAgentsOptions, BuildAgentsResult } from "./build.js";