@reactive-agents/tools 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Tyler Buell
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,53 @@
1
+ # @reactive-agents/tools
2
+
3
+ Tool system for the [Reactive Agents](https://tylerjrbuell.github.io/reactive-agents-ts/) framework.
4
+
5
+ Provides a type-safe tool registry, sandboxed execution, and an MCP (Model Context Protocol) client.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ bun add @reactive-agents/tools effect
11
+ ```
12
+
13
+ ## Features
14
+
15
+ - **Tool registry** — register typed tools with Effect-TS schemas
16
+ - **Sandboxed execution** — tools run in isolation with timeout and resource limits
17
+ - **MCP client** — connect to any MCP-compatible tool server
18
+
19
+ ## Usage
20
+
21
+ ```typescript
22
+ import { ReactiveAgents } from "reactive-agents";
23
+ import { defineTool } from "@reactive-agents/tools";
24
+ import { Schema } from "effect";
25
+
26
+ const searchTool = defineTool({
27
+ name: "web_search",
28
+ description: "Search the web for information",
29
+ input: Schema.Struct({ query: Schema.String }),
30
+ handler: ({ query }) => Effect.succeed(`Results for: ${query}`),
31
+ });
32
+
33
+ const agent = await ReactiveAgents.create()
34
+ .withName("research-agent")
35
+ .withProvider("anthropic")
36
+ .withReasoning()
37
+ .withTools([searchTool])
38
+ .build();
39
+
40
+ const result = await agent.run("What are the latest AI developments?");
41
+ ```
42
+
43
+ ## MCP Client
44
+
45
+ ```typescript
46
+ const agent = await ReactiveAgents.create()
47
+ .withTools({ mcp: { url: "http://localhost:3000" } })
48
+ .build();
49
+ ```
50
+
51
+ ## Documentation
52
+
53
+ Full documentation at [tylerjrbuell.github.io/reactive-agents-ts/guides/tools/](https://tylerjrbuell.github.io/reactive-agents-ts/guides/tools/)
@@ -0,0 +1,242 @@
1
+ import { Schema, Context, Effect, Layer } from 'effect';
2
+ import * as effect_Cause from 'effect/Cause';
3
+ import * as effect_Types from 'effect/Types';
4
+ import * as _reactive_agents_core from '@reactive-agents/core';
5
+ import { EventBus } from '@reactive-agents/core';
6
+
7
+ declare const ToolParameterSchema: Schema.Struct<{
8
+ name: typeof Schema.String;
9
+ type: Schema.Literal<["string", "number", "boolean", "object", "array"]>;
10
+ description: typeof Schema.String;
11
+ required: typeof Schema.Boolean;
12
+ default: Schema.optional<typeof Schema.Unknown>;
13
+ enum: Schema.optional<Schema.Array$<typeof Schema.String>>;
14
+ }>;
15
+ type ToolParameter = typeof ToolParameterSchema.Type;
16
+ declare const ToolDefinitionSchema: Schema.Struct<{
17
+ name: typeof Schema.String;
18
+ description: typeof Schema.String;
19
+ parameters: Schema.Array$<Schema.Struct<{
20
+ name: typeof Schema.String;
21
+ type: Schema.Literal<["string", "number", "boolean", "object", "array"]>;
22
+ description: typeof Schema.String;
23
+ required: typeof Schema.Boolean;
24
+ default: Schema.optional<typeof Schema.Unknown>;
25
+ enum: Schema.optional<Schema.Array$<typeof Schema.String>>;
26
+ }>>;
27
+ returnType: Schema.optional<typeof Schema.String>;
28
+ category: Schema.optional<Schema.Literal<["search", "file", "code", "http", "data", "custom"]>>;
29
+ riskLevel: Schema.Literal<["low", "medium", "high", "critical"]>;
30
+ timeoutMs: typeof Schema.Number;
31
+ requiresApproval: typeof Schema.Boolean;
32
+ source: Schema.Literal<["builtin", "mcp", "function", "plugin"]>;
33
+ }>;
34
+ type ToolDefinition = typeof ToolDefinitionSchema.Type;
35
+ declare const ToolInputSchema: Schema.Struct<{
36
+ toolName: typeof Schema.String;
37
+ arguments: Schema.Record$<typeof Schema.String, typeof Schema.Unknown>;
38
+ agentId: typeof Schema.String;
39
+ sessionId: typeof Schema.String;
40
+ correlationId: Schema.optional<typeof Schema.String>;
41
+ }>;
42
+ type ToolInput = typeof ToolInputSchema.Type;
43
+ declare const ToolOutputSchema: Schema.Struct<{
44
+ toolName: typeof Schema.String;
45
+ success: typeof Schema.Boolean;
46
+ result: typeof Schema.Unknown;
47
+ error: Schema.optional<typeof Schema.String>;
48
+ executionTimeMs: typeof Schema.Number;
49
+ metadata: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.Unknown>>;
50
+ }>;
51
+ type ToolOutput = typeof ToolOutputSchema.Type;
52
+ declare const MCPServerSchema: Schema.Struct<{
53
+ name: typeof Schema.String;
54
+ version: typeof Schema.String;
55
+ transport: Schema.Literal<["stdio", "sse", "websocket"]>;
56
+ endpoint: Schema.optional<typeof Schema.String>;
57
+ command: Schema.optional<typeof Schema.String>;
58
+ args: Schema.optional<Schema.Array$<typeof Schema.String>>;
59
+ tools: Schema.Array$<typeof Schema.String>;
60
+ status: Schema.Literal<["connected", "disconnected", "error"]>;
61
+ }>;
62
+ type MCPServer = typeof MCPServerSchema.Type;
63
+ declare const MCPRequestSchema: Schema.Struct<{
64
+ jsonrpc: Schema.Literal<["2.0"]>;
65
+ id: Schema.Union<[typeof Schema.String, typeof Schema.Number]>;
66
+ method: typeof Schema.String;
67
+ params: Schema.optional<typeof Schema.Unknown>;
68
+ }>;
69
+ type MCPRequest = typeof MCPRequestSchema.Type;
70
+ declare const MCPResponseSchema: Schema.Struct<{
71
+ jsonrpc: Schema.Literal<["2.0"]>;
72
+ id: Schema.Union<[typeof Schema.String, typeof Schema.Number]>;
73
+ result: Schema.optional<typeof Schema.Unknown>;
74
+ error: Schema.optional<Schema.Struct<{
75
+ code: typeof Schema.Number;
76
+ message: typeof Schema.String;
77
+ data: Schema.optional<typeof Schema.Unknown>;
78
+ }>>;
79
+ }>;
80
+ type MCPResponse = typeof MCPResponseSchema.Type;
81
+ declare const FunctionCallingToolSchema: Schema.Struct<{
82
+ name: typeof Schema.String;
83
+ description: typeof Schema.String;
84
+ input_schema: Schema.Record$<typeof Schema.String, typeof Schema.Unknown>;
85
+ }>;
86
+ type FunctionCallingTool = typeof FunctionCallingToolSchema.Type;
87
+
88
+ declare const ToolNotFoundError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & {
89
+ readonly _tag: "ToolNotFoundError";
90
+ } & Readonly<A>;
91
+ declare class ToolNotFoundError extends ToolNotFoundError_base<{
92
+ readonly message: string;
93
+ readonly toolName: string;
94
+ readonly availableTools?: readonly string[];
95
+ }> {
96
+ }
97
+ declare const ToolExecutionError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & {
98
+ readonly _tag: "ToolExecutionError";
99
+ } & Readonly<A>;
100
+ declare class ToolExecutionError extends ToolExecutionError_base<{
101
+ readonly message: string;
102
+ readonly toolName: string;
103
+ readonly input?: unknown;
104
+ readonly cause?: unknown;
105
+ }> {
106
+ }
107
+ declare const ToolTimeoutError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & {
108
+ readonly _tag: "ToolTimeoutError";
109
+ } & Readonly<A>;
110
+ declare class ToolTimeoutError extends ToolTimeoutError_base<{
111
+ readonly message: string;
112
+ readonly toolName: string;
113
+ readonly timeoutMs: number;
114
+ }> {
115
+ }
116
+ declare const ToolValidationError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & {
117
+ readonly _tag: "ToolValidationError";
118
+ } & Readonly<A>;
119
+ declare class ToolValidationError extends ToolValidationError_base<{
120
+ readonly message: string;
121
+ readonly toolName: string;
122
+ readonly parameter: string;
123
+ readonly expected: string;
124
+ readonly received: string;
125
+ }> {
126
+ }
127
+ declare const MCPConnectionError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & {
128
+ readonly _tag: "MCPConnectionError";
129
+ } & Readonly<A>;
130
+ declare class MCPConnectionError extends MCPConnectionError_base<{
131
+ readonly message: string;
132
+ readonly serverName: string;
133
+ readonly transport: string;
134
+ readonly cause?: unknown;
135
+ }> {
136
+ }
137
+ declare const ToolAuthorizationError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & {
138
+ readonly _tag: "ToolAuthorizationError";
139
+ } & Readonly<A>;
140
+ declare class ToolAuthorizationError extends ToolAuthorizationError_base<{
141
+ readonly message: string;
142
+ readonly toolName: string;
143
+ readonly agentId: string;
144
+ }> {
145
+ }
146
+
147
+ declare const ToolService_base: Context.TagClass<ToolService, "ToolService", {
148
+ readonly execute: (input: ToolInput) => Effect.Effect<ToolOutput, ToolNotFoundError | ToolExecutionError | ToolTimeoutError | ToolValidationError | ToolAuthorizationError>;
149
+ readonly register: (definition: ToolDefinition, handler: (args: Record<string, unknown>) => Effect.Effect<unknown, ToolExecutionError>) => Effect.Effect<void, never>;
150
+ readonly connectMCPServer: (config: Pick<MCPServer, "name" | "transport" | "endpoint" | "command" | "args">) => Effect.Effect<MCPServer, MCPConnectionError>;
151
+ readonly disconnectMCPServer: (serverName: string) => Effect.Effect<void, MCPConnectionError>;
152
+ readonly listTools: (filter?: {
153
+ category?: string;
154
+ source?: string;
155
+ riskLevel?: string;
156
+ }) => Effect.Effect<readonly ToolDefinition[], never>;
157
+ readonly getTool: (name: string) => Effect.Effect<ToolDefinition, ToolNotFoundError>;
158
+ readonly toFunctionCallingFormat: () => Effect.Effect<readonly FunctionCallingTool[], never>;
159
+ readonly listMCPServers: () => Effect.Effect<readonly MCPServer[], never>;
160
+ }>;
161
+ declare class ToolService extends ToolService_base {
162
+ }
163
+ declare const ToolServiceLive: Layer.Layer<ToolService, never, EventBus>;
164
+
165
+ interface RegisteredTool {
166
+ readonly definition: ToolDefinition;
167
+ readonly handler: (args: Record<string, unknown>) => Effect.Effect<unknown, ToolExecutionError>;
168
+ }
169
+ declare const makeToolRegistry: Effect.Effect<{
170
+ register: (definition: ToolDefinition, handler: (args: Record<string, unknown>) => Effect.Effect<unknown, ToolExecutionError>) => Effect.Effect<void, never>;
171
+ get: (name: string) => Effect.Effect<RegisteredTool, ToolNotFoundError>;
172
+ list: (filter?: {
173
+ category?: string;
174
+ source?: string;
175
+ riskLevel?: string;
176
+ }) => Effect.Effect<readonly ToolDefinition[], never>;
177
+ toFunctionCallingFormat: () => Effect.Effect<readonly FunctionCallingTool[], never>;
178
+ }, never, never>;
179
+
180
+ declare const makeMCPClient: Effect.Effect<{
181
+ connect: (config: Pick<MCPServer, "name" | "transport" | "endpoint" | "command" | "args">) => Effect.Effect<MCPServer, MCPConnectionError>;
182
+ callTool: (serverName: string, toolName: string, args: Record<string, unknown>) => Effect.Effect<unknown, MCPConnectionError | ToolExecutionError>;
183
+ disconnect: (serverName: string) => Effect.Effect<void, MCPConnectionError>;
184
+ listServers: () => Effect.Effect<readonly MCPServer[], never>;
185
+ }, never, never>;
186
+
187
+ /**
188
+ * Adapt a native function into a ToolDefinition + handler pair
189
+ * suitable for registration in the ToolRegistry.
190
+ */
191
+ declare const adaptFunction: (opts: {
192
+ readonly name: string;
193
+ readonly description: string;
194
+ readonly parameters: ToolDefinition["parameters"];
195
+ readonly category?: ToolDefinition["category"];
196
+ readonly riskLevel?: ToolDefinition["riskLevel"];
197
+ readonly timeoutMs?: number;
198
+ readonly fn: (args: Record<string, unknown>) => Effect.Effect<unknown, ToolExecutionError>;
199
+ }) => {
200
+ definition: ToolDefinition;
201
+ handler: (args: Record<string, unknown>) => Effect.Effect<unknown, ToolExecutionError>;
202
+ };
203
+ /**
204
+ * Convert a ToolDefinition to the Anthropic/OpenAI function calling format.
205
+ */
206
+ declare const toFunctionCallingTool: (definition: ToolDefinition) => FunctionCallingTool;
207
+
208
+ declare const makeSandbox: () => {
209
+ execute: <A>(fn: () => Effect.Effect<A, ToolExecutionError>, options: {
210
+ timeoutMs: number;
211
+ toolName?: string;
212
+ }) => Effect.Effect<A, ToolExecutionError | ToolTimeoutError>;
213
+ };
214
+
215
+ declare const validateToolInput: (definition: ToolDefinition, args: Record<string, unknown>) => Effect.Effect<Record<string, unknown>, ToolValidationError>;
216
+
217
+ declare const webSearchTool: ToolDefinition;
218
+ declare const webSearchHandler: (args: Record<string, unknown>) => Effect.Effect<unknown, ToolExecutionError>;
219
+
220
+ declare const fileReadTool: ToolDefinition;
221
+ declare const fileReadHandler: (args: Record<string, unknown>) => Effect.Effect<unknown, ToolExecutionError>;
222
+ declare const fileWriteTool: ToolDefinition;
223
+ declare const fileWriteHandler: (args: Record<string, unknown>) => Effect.Effect<unknown, ToolExecutionError>;
224
+
225
+ declare const httpGetTool: ToolDefinition;
226
+ declare const httpGetHandler: (args: Record<string, unknown>) => Effect.Effect<unknown, ToolExecutionError>;
227
+
228
+ declare const codeExecuteTool: ToolDefinition;
229
+ declare const codeExecuteHandler: (args: Record<string, unknown>) => Effect.Effect<unknown, ToolExecutionError>;
230
+
231
+ /**
232
+ * Creates the full Tools layer with all dependencies wired.
233
+ * Requires EventBus to be provided (or uses EventBusLive by default).
234
+ */
235
+ declare const createToolsLayer: () => Layer.Layer<ToolService, never, never>;
236
+ /**
237
+ * ToolServiceLive layer that requires EventBus to be provided externally.
238
+ * Use this when composing with a shared EventBus from the runtime.
239
+ */
240
+ declare const ToolsLayer: Layer.Layer<ToolService, never, _reactive_agents_core.EventBus>;
241
+
242
+ export { type FunctionCallingTool, FunctionCallingToolSchema, MCPConnectionError, type MCPRequest, MCPRequestSchema, type MCPResponse, MCPResponseSchema, type MCPServer, MCPServerSchema, type RegisteredTool, ToolAuthorizationError, type ToolDefinition, ToolDefinitionSchema, ToolExecutionError, type ToolInput, ToolInputSchema, ToolNotFoundError, type ToolOutput, ToolOutputSchema, type ToolParameter, ToolParameterSchema, ToolService, ToolServiceLive, ToolTimeoutError, ToolValidationError, ToolsLayer, adaptFunction, codeExecuteHandler, codeExecuteTool, createToolsLayer, fileReadHandler, fileReadTool, fileWriteHandler, fileWriteTool, httpGetHandler, httpGetTool, makeMCPClient, makeSandbox, makeToolRegistry, toFunctionCallingTool, validateToolInput, webSearchHandler, webSearchTool };
package/dist/index.js ADDED
@@ -0,0 +1,762 @@
1
+ // src/types.ts
2
+ import { Schema } from "effect";
3
+ var ToolParameterSchema = Schema.Struct({
4
+ name: Schema.String,
5
+ type: Schema.Literal("string", "number", "boolean", "object", "array"),
6
+ description: Schema.String,
7
+ required: Schema.Boolean,
8
+ default: Schema.optional(Schema.Unknown),
9
+ enum: Schema.optional(Schema.Array(Schema.String))
10
+ });
11
+ var ToolDefinitionSchema = Schema.Struct({
12
+ name: Schema.String,
13
+ description: Schema.String,
14
+ parameters: Schema.Array(ToolParameterSchema),
15
+ returnType: Schema.optional(Schema.String),
16
+ category: Schema.optional(
17
+ Schema.Literal("search", "file", "code", "http", "data", "custom")
18
+ ),
19
+ riskLevel: Schema.Literal("low", "medium", "high", "critical"),
20
+ timeoutMs: Schema.Number,
21
+ requiresApproval: Schema.Boolean,
22
+ source: Schema.Literal("builtin", "mcp", "function", "plugin")
23
+ });
24
+ var ToolInputSchema = Schema.Struct({
25
+ toolName: Schema.String,
26
+ arguments: Schema.Record({ key: Schema.String, value: Schema.Unknown }),
27
+ agentId: Schema.String,
28
+ sessionId: Schema.String,
29
+ correlationId: Schema.optional(Schema.String)
30
+ });
31
+ var ToolOutputSchema = Schema.Struct({
32
+ toolName: Schema.String,
33
+ success: Schema.Boolean,
34
+ result: Schema.Unknown,
35
+ error: Schema.optional(Schema.String),
36
+ executionTimeMs: Schema.Number,
37
+ metadata: Schema.optional(
38
+ Schema.Record({ key: Schema.String, value: Schema.Unknown })
39
+ )
40
+ });
41
+ var MCPServerSchema = Schema.Struct({
42
+ name: Schema.String,
43
+ version: Schema.String,
44
+ transport: Schema.Literal("stdio", "sse", "websocket"),
45
+ endpoint: Schema.optional(Schema.String),
46
+ command: Schema.optional(Schema.String),
47
+ args: Schema.optional(Schema.Array(Schema.String)),
48
+ tools: Schema.Array(Schema.String),
49
+ status: Schema.Literal("connected", "disconnected", "error")
50
+ });
51
+ var MCPRequestSchema = Schema.Struct({
52
+ jsonrpc: Schema.Literal("2.0"),
53
+ id: Schema.Union(Schema.String, Schema.Number),
54
+ method: Schema.String,
55
+ params: Schema.optional(Schema.Unknown)
56
+ });
57
+ var MCPResponseSchema = Schema.Struct({
58
+ jsonrpc: Schema.Literal("2.0"),
59
+ id: Schema.Union(Schema.String, Schema.Number),
60
+ result: Schema.optional(Schema.Unknown),
61
+ error: Schema.optional(
62
+ Schema.Struct({
63
+ code: Schema.Number,
64
+ message: Schema.String,
65
+ data: Schema.optional(Schema.Unknown)
66
+ })
67
+ )
68
+ });
69
+ var FunctionCallingToolSchema = Schema.Struct({
70
+ name: Schema.String,
71
+ description: Schema.String,
72
+ input_schema: Schema.Record({ key: Schema.String, value: Schema.Unknown })
73
+ });
74
+
75
+ // src/errors.ts
76
+ import { Data } from "effect";
77
+ var ToolNotFoundError = class extends Data.TaggedError("ToolNotFoundError") {
78
+ };
79
+ var ToolExecutionError = class extends Data.TaggedError(
80
+ "ToolExecutionError"
81
+ ) {
82
+ };
83
+ var ToolTimeoutError = class extends Data.TaggedError("ToolTimeoutError") {
84
+ };
85
+ var ToolValidationError = class extends Data.TaggedError(
86
+ "ToolValidationError"
87
+ ) {
88
+ };
89
+ var MCPConnectionError = class extends Data.TaggedError(
90
+ "MCPConnectionError"
91
+ ) {
92
+ };
93
+ var ToolAuthorizationError = class extends Data.TaggedError(
94
+ "ToolAuthorizationError"
95
+ ) {
96
+ };
97
+
98
+ // src/tool-service.ts
99
+ import { Effect as Effect5, Context, Layer } from "effect";
100
+
101
+ // src/registry/tool-registry.ts
102
+ import { Effect, Ref } from "effect";
103
+ var makeToolRegistry = Effect.gen(function* () {
104
+ const toolsRef = yield* Ref.make(/* @__PURE__ */ new Map());
105
+ const register = (definition, handler) => Ref.update(toolsRef, (tools) => {
106
+ const newTools = new Map(tools);
107
+ newTools.set(definition.name, { definition, handler });
108
+ return newTools;
109
+ });
110
+ const get = (name) => Effect.gen(function* () {
111
+ const tools = yield* Ref.get(toolsRef);
112
+ const tool = tools.get(name);
113
+ if (!tool) {
114
+ const available = [...tools.keys()];
115
+ return yield* Effect.fail(
116
+ new ToolNotFoundError({
117
+ message: `Tool "${name}" not found`,
118
+ toolName: name,
119
+ availableTools: available
120
+ })
121
+ );
122
+ }
123
+ return tool;
124
+ });
125
+ const list = (filter) => Effect.gen(function* () {
126
+ const tools = yield* Ref.get(toolsRef);
127
+ let definitions = [...tools.values()].map((t) => t.definition);
128
+ if (filter?.category)
129
+ definitions = definitions.filter((d) => d.category === filter.category);
130
+ if (filter?.source)
131
+ definitions = definitions.filter((d) => d.source === filter.source);
132
+ if (filter?.riskLevel)
133
+ definitions = definitions.filter(
134
+ (d) => d.riskLevel === filter.riskLevel
135
+ );
136
+ return definitions;
137
+ });
138
+ const toFunctionCallingFormat = () => Effect.gen(function* () {
139
+ const tools = yield* Ref.get(toolsRef);
140
+ return [...tools.values()].map((t) => ({
141
+ name: t.definition.name,
142
+ description: t.definition.description,
143
+ input_schema: {
144
+ type: "object",
145
+ properties: Object.fromEntries(
146
+ t.definition.parameters.map((p) => [
147
+ p.name,
148
+ {
149
+ type: p.type,
150
+ description: p.description,
151
+ ...p.enum ? { enum: p.enum } : {}
152
+ }
153
+ ])
154
+ ),
155
+ required: t.definition.parameters.filter((p) => p.required).map((p) => p.name)
156
+ }
157
+ }));
158
+ });
159
+ return { register, get, list, toFunctionCallingFormat };
160
+ });
161
+
162
+ // src/mcp/mcp-client.ts
163
+ import { Effect as Effect2, Ref as Ref2 } from "effect";
164
+ var createTransport = (_config) => Effect2.void;
165
+ var sendRequest = (_config, request) => Effect2.succeed({
166
+ jsonrpc: "2.0",
167
+ id: request.id,
168
+ result: {}
169
+ });
170
+ var makeMCPClient = Effect2.gen(function* () {
171
+ const serversRef = yield* Ref2.make(/* @__PURE__ */ new Map());
172
+ const requestIdRef = yield* Ref2.make(0);
173
+ const nextRequestId = Ref2.updateAndGet(requestIdRef, (id) => id + 1);
174
+ const connect = (config) => Effect2.gen(function* () {
175
+ yield* createTransport(config).pipe(
176
+ Effect2.mapError(
177
+ (e) => new MCPConnectionError({
178
+ message: `Failed to connect to MCP server "${config.name}"`,
179
+ serverName: config.name,
180
+ transport: config.transport,
181
+ cause: e
182
+ })
183
+ )
184
+ );
185
+ const reqId1 = yield* nextRequestId;
186
+ const initResponse = yield* sendRequest(config, {
187
+ jsonrpc: "2.0",
188
+ id: reqId1,
189
+ method: "initialize",
190
+ params: {
191
+ protocolVersion: "2024-11-05",
192
+ capabilities: { tools: {} },
193
+ clientInfo: { name: "reactive-agents", version: "1.0.0" }
194
+ }
195
+ });
196
+ const reqId2 = yield* nextRequestId;
197
+ const toolsResponse = yield* sendRequest(config, {
198
+ jsonrpc: "2.0",
199
+ id: reqId2,
200
+ method: "tools/list"
201
+ });
202
+ const toolNames = Array.isArray(toolsResponse.result) ? toolsResponse.result.map(
203
+ (t) => t.name
204
+ ) : [];
205
+ const server = {
206
+ name: config.name,
207
+ version: initResponse.result?.serverInfo != null ? String(
208
+ initResponse.result.serverInfo?.version
209
+ ) : "unknown",
210
+ transport: config.transport,
211
+ endpoint: config.endpoint,
212
+ command: config.command,
213
+ args: config.args,
214
+ tools: toolNames,
215
+ status: "connected"
216
+ };
217
+ yield* Ref2.update(serversRef, (servers) => {
218
+ const newServers = new Map(servers);
219
+ newServers.set(server.name, server);
220
+ return newServers;
221
+ });
222
+ return server;
223
+ });
224
+ const callTool = (serverName, toolName, args) => Effect2.gen(function* () {
225
+ const servers = yield* Ref2.get(serversRef);
226
+ const server = servers.get(serverName);
227
+ if (!server || server.status !== "connected") {
228
+ return yield* Effect2.fail(
229
+ new MCPConnectionError({
230
+ message: `MCP server "${serverName}" not connected`,
231
+ serverName,
232
+ transport: server?.transport ?? "unknown"
233
+ })
234
+ );
235
+ }
236
+ const reqId = yield* nextRequestId;
237
+ const response = yield* sendRequest(
238
+ {
239
+ name: serverName,
240
+ transport: server.transport,
241
+ endpoint: server.endpoint,
242
+ command: server.command
243
+ },
244
+ {
245
+ jsonrpc: "2.0",
246
+ id: reqId,
247
+ method: "tools/call",
248
+ params: { name: toolName, arguments: args }
249
+ }
250
+ );
251
+ if (response.error) {
252
+ return yield* Effect2.fail(
253
+ new ToolExecutionError({
254
+ message: `MCP tool "${toolName}" failed: ${response.error.message}`,
255
+ toolName,
256
+ input: args
257
+ })
258
+ );
259
+ }
260
+ return response.result;
261
+ });
262
+ const disconnect = (serverName) => Ref2.update(serversRef, (servers) => {
263
+ const newServers = new Map(servers);
264
+ const server = newServers.get(serverName);
265
+ if (server) {
266
+ newServers.set(serverName, { ...server, status: "disconnected" });
267
+ }
268
+ return newServers;
269
+ });
270
+ const listServers = () => Effect2.gen(function* () {
271
+ const servers = yield* Ref2.get(serversRef);
272
+ return [...servers.values()];
273
+ });
274
+ return { connect, callTool, disconnect, listServers };
275
+ });
276
+
277
+ // src/execution/sandbox.ts
278
+ import { Duration, Effect as Effect3 } from "effect";
279
+ var makeSandbox = () => {
280
+ const execute = (fn, options) => fn().pipe(
281
+ // Enforce timeout
282
+ Effect3.timeoutFail({
283
+ duration: Duration.millis(options.timeoutMs),
284
+ onTimeout: () => new ToolTimeoutError({
285
+ message: `Tool execution timed out after ${options.timeoutMs}ms`,
286
+ toolName: options.toolName ?? "unknown",
287
+ timeoutMs: options.timeoutMs
288
+ })
289
+ }),
290
+ // Catch unexpected errors
291
+ Effect3.catchAllDefect(
292
+ (defect) => Effect3.fail(
293
+ new ToolExecutionError({
294
+ message: `Tool crashed: ${String(defect)}`,
295
+ toolName: options.toolName ?? "unknown",
296
+ cause: defect
297
+ })
298
+ )
299
+ )
300
+ );
301
+ return { execute };
302
+ };
303
+
304
+ // src/validation/input-validator.ts
305
+ import { Effect as Effect4 } from "effect";
306
+ var validateToolInput = (definition, args) => Effect4.gen(function* () {
307
+ const validated = {};
308
+ for (const param of definition.parameters) {
309
+ const value = args[param.name];
310
+ if (param.required && (value === void 0 || value === null)) {
311
+ return yield* Effect4.fail(
312
+ new ToolValidationError({
313
+ message: `Missing required parameter "${param.name}"`,
314
+ toolName: definition.name,
315
+ parameter: param.name,
316
+ expected: param.type,
317
+ received: "undefined"
318
+ })
319
+ );
320
+ }
321
+ if (value === void 0) {
322
+ if (param.default !== void 0) {
323
+ validated[param.name] = param.default;
324
+ }
325
+ continue;
326
+ }
327
+ const actualType = Array.isArray(value) ? "array" : typeof value;
328
+ if (actualType !== param.type && !(param.type === "object" && actualType === "object")) {
329
+ return yield* Effect4.fail(
330
+ new ToolValidationError({
331
+ message: `Parameter "${param.name}" expected ${param.type}, got ${actualType}`,
332
+ toolName: definition.name,
333
+ parameter: param.name,
334
+ expected: param.type,
335
+ received: actualType
336
+ })
337
+ );
338
+ }
339
+ if (param.enum && typeof value === "string" && !param.enum.includes(value)) {
340
+ return yield* Effect4.fail(
341
+ new ToolValidationError({
342
+ message: `Parameter "${param.name}" must be one of: ${param.enum.join(", ")}`,
343
+ toolName: definition.name,
344
+ parameter: param.name,
345
+ expected: param.enum.join(" | "),
346
+ received: String(value)
347
+ })
348
+ );
349
+ }
350
+ validated[param.name] = value;
351
+ }
352
+ return validated;
353
+ });
354
+
355
+ // src/tool-service.ts
356
+ import { EventBus } from "@reactive-agents/core";
357
+ var ToolService = class extends Context.Tag("ToolService")() {
358
+ };
359
+ var ToolServiceLive = Layer.effect(
360
+ ToolService,
361
+ Effect5.gen(function* () {
362
+ const eventBus = yield* EventBus;
363
+ const registry = yield* makeToolRegistry;
364
+ const mcpClient = yield* makeMCPClient;
365
+ const sandbox = makeSandbox();
366
+ const execute = (input) => Effect5.gen(function* () {
367
+ const startTime = Date.now();
368
+ const tool = yield* registry.get(input.toolName);
369
+ const validatedArgs = yield* validateToolInput(
370
+ tool.definition,
371
+ input.arguments
372
+ );
373
+ const result = yield* sandbox.execute(
374
+ () => tool.handler(validatedArgs),
375
+ {
376
+ timeoutMs: tool.definition.timeoutMs,
377
+ toolName: input.toolName
378
+ }
379
+ );
380
+ const executionTimeMs = Date.now() - startTime;
381
+ yield* eventBus.publish({
382
+ _tag: "Custom",
383
+ type: "tools.executed",
384
+ payload: {
385
+ toolName: input.toolName,
386
+ success: true,
387
+ executionTimeMs
388
+ }
389
+ });
390
+ return {
391
+ toolName: input.toolName,
392
+ success: true,
393
+ result,
394
+ executionTimeMs
395
+ };
396
+ });
397
+ const register = (definition, handler) => registry.register(definition, handler);
398
+ const connectMCPServer = (config) => Effect5.gen(function* () {
399
+ const server = yield* mcpClient.connect(config);
400
+ for (const toolName of server.tools) {
401
+ yield* registry.register(
402
+ {
403
+ name: `${server.name}/${toolName}`,
404
+ description: `MCP tool from ${server.name}`,
405
+ parameters: [],
406
+ riskLevel: "medium",
407
+ timeoutMs: 3e4,
408
+ requiresApproval: false,
409
+ source: "mcp"
410
+ },
411
+ (args) => mcpClient.callTool(server.name, toolName, args).pipe(
412
+ Effect5.mapError(
413
+ (e) => new ToolExecutionError({
414
+ message: `MCP tool ${toolName} failed`,
415
+ toolName,
416
+ cause: e
417
+ })
418
+ )
419
+ )
420
+ );
421
+ }
422
+ yield* eventBus.publish({
423
+ _tag: "Custom",
424
+ type: "tools.mcp-connected",
425
+ payload: { serverName: server.name, tools: server.tools }
426
+ });
427
+ return server;
428
+ });
429
+ const disconnectMCPServer = (serverName) => Effect5.gen(function* () {
430
+ yield* mcpClient.disconnect(serverName);
431
+ yield* eventBus.publish({
432
+ _tag: "Custom",
433
+ type: "tools.mcp-disconnected",
434
+ payload: { serverName }
435
+ });
436
+ });
437
+ const listTools = (filter) => registry.list(filter);
438
+ const getTool = (name) => registry.get(name).pipe(Effect5.map((t) => t.definition));
439
+ const toFunctionCallingFormat = () => registry.toFunctionCallingFormat();
440
+ const listMCPServers = () => mcpClient.listServers();
441
+ return {
442
+ execute,
443
+ register,
444
+ connectMCPServer,
445
+ disconnectMCPServer,
446
+ listTools,
447
+ getTool,
448
+ toFunctionCallingFormat,
449
+ listMCPServers
450
+ };
451
+ })
452
+ );
453
+
454
+ // src/function-calling/function-adapter.ts
455
+ import "effect";
456
+ var adaptFunction = (opts) => ({
457
+ definition: {
458
+ name: opts.name,
459
+ description: opts.description,
460
+ parameters: opts.parameters,
461
+ category: opts.category,
462
+ riskLevel: opts.riskLevel ?? "low",
463
+ timeoutMs: opts.timeoutMs ?? 3e4,
464
+ requiresApproval: false,
465
+ source: "function"
466
+ },
467
+ handler: opts.fn
468
+ });
469
+ var toFunctionCallingTool = (definition) => ({
470
+ name: definition.name,
471
+ description: definition.description,
472
+ input_schema: {
473
+ type: "object",
474
+ properties: Object.fromEntries(
475
+ definition.parameters.map((p) => [
476
+ p.name,
477
+ {
478
+ type: p.type,
479
+ description: p.description,
480
+ ...p.enum ? { enum: p.enum } : {}
481
+ }
482
+ ])
483
+ ),
484
+ required: definition.parameters.filter((p) => p.required).map((p) => p.name)
485
+ }
486
+ });
487
+
488
+ // src/skills/web-search.ts
489
+ import { Effect as Effect7 } from "effect";
490
+ var webSearchTool = {
491
+ name: "web-search",
492
+ description: "Search the web for information using a query string",
493
+ parameters: [
494
+ {
495
+ name: "query",
496
+ type: "string",
497
+ description: "Search query",
498
+ required: true
499
+ },
500
+ {
501
+ name: "maxResults",
502
+ type: "number",
503
+ description: "Max results to return",
504
+ required: false,
505
+ default: 5
506
+ }
507
+ ],
508
+ category: "search",
509
+ riskLevel: "low",
510
+ timeoutMs: 1e4,
511
+ requiresApproval: false,
512
+ source: "builtin"
513
+ };
514
+ var webSearchHandler = (args) => Effect7.tryPromise({
515
+ try: async () => {
516
+ const query = args.query;
517
+ const maxResults = args.maxResults ?? 5;
518
+ return {
519
+ query,
520
+ maxResults,
521
+ results: [],
522
+ message: "Web search stub - configure TAVILY_API_KEY for real results"
523
+ };
524
+ },
525
+ catch: (e) => new ToolExecutionError({
526
+ message: `Web search failed: ${e}`,
527
+ toolName: "web-search",
528
+ cause: e
529
+ })
530
+ });
531
+
532
+ // src/skills/file-operations.ts
533
+ import { Effect as Effect8 } from "effect";
534
+ import * as fs from "fs/promises";
535
+ import * as path from "path";
536
+ var fileReadTool = {
537
+ name: "file-read",
538
+ description: "Read the contents of a file",
539
+ parameters: [
540
+ {
541
+ name: "path",
542
+ type: "string",
543
+ description: "File path to read",
544
+ required: true
545
+ },
546
+ {
547
+ name: "encoding",
548
+ type: "string",
549
+ description: "File encoding",
550
+ required: false,
551
+ default: "utf-8"
552
+ }
553
+ ],
554
+ category: "file",
555
+ riskLevel: "medium",
556
+ timeoutMs: 5e3,
557
+ requiresApproval: false,
558
+ source: "builtin"
559
+ };
560
+ var fileReadHandler = (args) => Effect8.tryPromise({
561
+ try: async () => {
562
+ const filePath = args.path;
563
+ const encoding = args.encoding ?? "utf-8";
564
+ const resolved = path.resolve(filePath);
565
+ const allowedBase = process.cwd();
566
+ if (!resolved.startsWith(allowedBase)) {
567
+ throw new Error(`Path traversal detected: ${filePath}`);
568
+ }
569
+ return await fs.readFile(resolved, { encoding });
570
+ },
571
+ catch: (e) => new ToolExecutionError({
572
+ message: `File read failed: ${e}`,
573
+ toolName: "file-read",
574
+ cause: e
575
+ })
576
+ });
577
+ var fileWriteTool = {
578
+ name: "file-write",
579
+ description: "Write contents to a file",
580
+ parameters: [
581
+ {
582
+ name: "path",
583
+ type: "string",
584
+ description: "File path to write",
585
+ required: true
586
+ },
587
+ {
588
+ name: "content",
589
+ type: "string",
590
+ description: "Content to write",
591
+ required: true
592
+ },
593
+ {
594
+ name: "encoding",
595
+ type: "string",
596
+ description: "File encoding",
597
+ required: false,
598
+ default: "utf-8"
599
+ }
600
+ ],
601
+ category: "file",
602
+ riskLevel: "high",
603
+ timeoutMs: 5e3,
604
+ requiresApproval: true,
605
+ source: "builtin"
606
+ };
607
+ var fileWriteHandler = (args) => Effect8.tryPromise({
608
+ try: async () => {
609
+ const filePath = args.path;
610
+ const content = args.content;
611
+ const encoding = args.encoding ?? "utf-8";
612
+ const resolved = path.resolve(filePath);
613
+ const allowedBase = process.cwd();
614
+ if (!resolved.startsWith(allowedBase)) {
615
+ throw new Error(`Path traversal detected: ${filePath}`);
616
+ }
617
+ await fs.writeFile(resolved, content, { encoding });
618
+ return { written: true, path: resolved };
619
+ },
620
+ catch: (e) => new ToolExecutionError({
621
+ message: `File write failed: ${e}`,
622
+ toolName: "file-write",
623
+ cause: e
624
+ })
625
+ });
626
+
627
+ // src/skills/http-client.ts
628
+ import { Effect as Effect9 } from "effect";
629
+ var httpGetTool = {
630
+ name: "http-get",
631
+ description: "Make an HTTP GET request to a URL",
632
+ parameters: [
633
+ {
634
+ name: "url",
635
+ type: "string",
636
+ description: "URL to fetch",
637
+ required: true
638
+ },
639
+ {
640
+ name: "headers",
641
+ type: "object",
642
+ description: "Optional request headers",
643
+ required: false
644
+ }
645
+ ],
646
+ category: "http",
647
+ riskLevel: "medium",
648
+ timeoutMs: 15e3,
649
+ requiresApproval: false,
650
+ source: "builtin"
651
+ };
652
+ var httpGetHandler = (args) => Effect9.tryPromise({
653
+ try: async () => {
654
+ const url = args.url;
655
+ const headers = args.headers ?? {};
656
+ const response = await fetch(url, { method: "GET", headers });
657
+ const contentType = response.headers.get("content-type") ?? "";
658
+ let body;
659
+ if (contentType.includes("application/json")) {
660
+ body = await response.json();
661
+ } else {
662
+ body = await response.text();
663
+ }
664
+ return {
665
+ status: response.status,
666
+ statusText: response.statusText,
667
+ headers: Object.fromEntries(response.headers.entries()),
668
+ body
669
+ };
670
+ },
671
+ catch: (e) => new ToolExecutionError({
672
+ message: `HTTP GET failed: ${e}`,
673
+ toolName: "http-get",
674
+ cause: e
675
+ })
676
+ });
677
+
678
+ // src/skills/code-execution.ts
679
+ import { Effect as Effect10 } from "effect";
680
+ var codeExecuteTool = {
681
+ name: "code-execute",
682
+ description: "Execute a JavaScript/TypeScript code snippet in a sandboxed environment",
683
+ parameters: [
684
+ {
685
+ name: "code",
686
+ type: "string",
687
+ description: "Code to execute",
688
+ required: true
689
+ },
690
+ {
691
+ name: "language",
692
+ type: "string",
693
+ description: "Programming language",
694
+ required: false,
695
+ default: "javascript",
696
+ enum: ["javascript", "typescript"]
697
+ }
698
+ ],
699
+ category: "code",
700
+ riskLevel: "critical",
701
+ timeoutMs: 3e4,
702
+ requiresApproval: true,
703
+ source: "builtin"
704
+ };
705
+ var codeExecuteHandler = (args) => Effect10.try({
706
+ try: () => {
707
+ const code = args.code;
708
+ return {
709
+ code,
710
+ executed: false,
711
+ message: "Code execution stub - production implementation requires sandboxed runtime"
712
+ };
713
+ },
714
+ catch: (e) => new ToolExecutionError({
715
+ message: `Code execution failed: ${e}`,
716
+ toolName: "code-execute",
717
+ cause: e
718
+ })
719
+ });
720
+
721
+ // src/runtime.ts
722
+ import { Layer as Layer2 } from "effect";
723
+ import { EventBusLive } from "@reactive-agents/core";
724
+ var createToolsLayer = () => ToolServiceLive.pipe(Layer2.provide(EventBusLive));
725
+ var ToolsLayer = ToolServiceLive;
726
+ export {
727
+ FunctionCallingToolSchema,
728
+ MCPConnectionError,
729
+ MCPRequestSchema,
730
+ MCPResponseSchema,
731
+ MCPServerSchema,
732
+ ToolAuthorizationError,
733
+ ToolDefinitionSchema,
734
+ ToolExecutionError,
735
+ ToolInputSchema,
736
+ ToolNotFoundError,
737
+ ToolOutputSchema,
738
+ ToolParameterSchema,
739
+ ToolService,
740
+ ToolServiceLive,
741
+ ToolTimeoutError,
742
+ ToolValidationError,
743
+ ToolsLayer,
744
+ adaptFunction,
745
+ codeExecuteHandler,
746
+ codeExecuteTool,
747
+ createToolsLayer,
748
+ fileReadHandler,
749
+ fileReadTool,
750
+ fileWriteHandler,
751
+ fileWriteTool,
752
+ httpGetHandler,
753
+ httpGetTool,
754
+ makeMCPClient,
755
+ makeSandbox,
756
+ makeToolRegistry,
757
+ toFunctionCallingTool,
758
+ validateToolInput,
759
+ webSearchHandler,
760
+ webSearchTool
761
+ };
762
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts","../src/errors.ts","../src/tool-service.ts","../src/registry/tool-registry.ts","../src/mcp/mcp-client.ts","../src/execution/sandbox.ts","../src/validation/input-validator.ts","../src/function-calling/function-adapter.ts","../src/skills/web-search.ts","../src/skills/file-operations.ts","../src/skills/http-client.ts","../src/skills/code-execution.ts","../src/runtime.ts"],"sourcesContent":["import { Schema } from \"effect\";\n\n// ─── Tool Definition ───\n\nexport const ToolParameterSchema = Schema.Struct({\n name: Schema.String,\n type: Schema.Literal(\"string\", \"number\", \"boolean\", \"object\", \"array\"),\n description: Schema.String,\n required: Schema.Boolean,\n default: Schema.optional(Schema.Unknown),\n enum: Schema.optional(Schema.Array(Schema.String)),\n});\nexport type ToolParameter = typeof ToolParameterSchema.Type;\n\nexport const ToolDefinitionSchema = Schema.Struct({\n name: Schema.String,\n description: Schema.String,\n parameters: Schema.Array(ToolParameterSchema),\n returnType: Schema.optional(Schema.String),\n category: Schema.optional(\n Schema.Literal(\"search\", \"file\", \"code\", \"http\", \"data\", \"custom\"),\n ),\n riskLevel: Schema.Literal(\"low\", \"medium\", \"high\", \"critical\"),\n timeoutMs: Schema.Number,\n requiresApproval: Schema.Boolean,\n source: Schema.Literal(\"builtin\", \"mcp\", \"function\", \"plugin\"),\n});\nexport type ToolDefinition = typeof ToolDefinitionSchema.Type;\n\n// ─── Tool Execution ───\n\nexport const ToolInputSchema = Schema.Struct({\n toolName: Schema.String,\n arguments: Schema.Record({ key: Schema.String, value: Schema.Unknown }),\n agentId: Schema.String,\n sessionId: Schema.String,\n correlationId: Schema.optional(Schema.String),\n});\nexport type ToolInput = typeof ToolInputSchema.Type;\n\nexport const ToolOutputSchema = Schema.Struct({\n toolName: Schema.String,\n success: Schema.Boolean,\n result: Schema.Unknown,\n error: Schema.optional(Schema.String),\n executionTimeMs: Schema.Number,\n metadata: Schema.optional(\n Schema.Record({ key: Schema.String, value: Schema.Unknown }),\n ),\n});\nexport type ToolOutput = typeof ToolOutputSchema.Type;\n\n// ─── MCP Types ───\n\nexport const MCPServerSchema = Schema.Struct({\n name: Schema.String,\n version: Schema.String,\n transport: Schema.Literal(\"stdio\", \"sse\", \"websocket\"),\n endpoint: Schema.optional(Schema.String),\n command: Schema.optional(Schema.String),\n args: Schema.optional(Schema.Array(Schema.String)),\n tools: Schema.Array(Schema.String),\n status: Schema.Literal(\"connected\", \"disconnected\", \"error\"),\n});\nexport type MCPServer = typeof MCPServerSchema.Type;\n\nexport const MCPRequestSchema = Schema.Struct({\n jsonrpc: Schema.Literal(\"2.0\"),\n id: Schema.Union(Schema.String, Schema.Number),\n method: Schema.String,\n params: Schema.optional(Schema.Unknown),\n});\nexport type MCPRequest = typeof MCPRequestSchema.Type;\n\nexport const MCPResponseSchema = Schema.Struct({\n jsonrpc: Schema.Literal(\"2.0\"),\n id: Schema.Union(Schema.String, Schema.Number),\n result: Schema.optional(Schema.Unknown),\n error: Schema.optional(\n Schema.Struct({\n code: Schema.Number,\n message: Schema.String,\n data: Schema.optional(Schema.Unknown),\n }),\n ),\n});\nexport type MCPResponse = typeof MCPResponseSchema.Type;\n\n// ─── Function Calling (Anthropic/OpenAI format) ───\n\nexport const FunctionCallingToolSchema = Schema.Struct({\n name: Schema.String,\n description: Schema.String,\n input_schema: Schema.Record({ key: Schema.String, value: Schema.Unknown }),\n});\nexport type FunctionCallingTool = typeof FunctionCallingToolSchema.Type;\n","import { Data } from \"effect\";\n\nexport class ToolNotFoundError extends Data.TaggedError(\"ToolNotFoundError\")<{\n readonly message: string;\n readonly toolName: string;\n readonly availableTools?: readonly string[];\n}> {}\n\nexport class ToolExecutionError extends Data.TaggedError(\n \"ToolExecutionError\",\n)<{\n readonly message: string;\n readonly toolName: string;\n readonly input?: unknown;\n readonly cause?: unknown;\n}> {}\n\nexport class ToolTimeoutError extends Data.TaggedError(\"ToolTimeoutError\")<{\n readonly message: string;\n readonly toolName: string;\n readonly timeoutMs: number;\n}> {}\n\nexport class ToolValidationError extends Data.TaggedError(\n \"ToolValidationError\",\n)<{\n readonly message: string;\n readonly toolName: string;\n readonly parameter: string;\n readonly expected: string;\n readonly received: string;\n}> {}\n\nexport class MCPConnectionError extends Data.TaggedError(\n \"MCPConnectionError\",\n)<{\n readonly message: string;\n readonly serverName: string;\n readonly transport: string;\n readonly cause?: unknown;\n}> {}\n\nexport class ToolAuthorizationError extends Data.TaggedError(\n \"ToolAuthorizationError\",\n)<{\n readonly message: string;\n readonly toolName: string;\n readonly agentId: string;\n}> {}\n","import { Effect, Context, Layer } from \"effect\";\n\nimport type {\n ToolInput,\n ToolOutput,\n ToolDefinition,\n MCPServer,\n FunctionCallingTool,\n} from \"./types.js\";\nimport {\n ToolNotFoundError,\n ToolExecutionError,\n ToolTimeoutError,\n ToolValidationError,\n ToolAuthorizationError,\n MCPConnectionError,\n} from \"./errors.js\";\nimport { makeToolRegistry } from \"./registry/tool-registry.js\";\nimport { makeMCPClient } from \"./mcp/mcp-client.js\";\nimport { makeSandbox } from \"./execution/sandbox.js\";\nimport { validateToolInput } from \"./validation/input-validator.js\";\nimport { EventBus } from \"@reactive-agents/core\";\n\n// ─── Service Tag ───\n\nexport class ToolService extends Context.Tag(\"ToolService\")<\n ToolService,\n {\n readonly execute: (\n input: ToolInput,\n ) => Effect.Effect<\n ToolOutput,\n | ToolNotFoundError\n | ToolExecutionError\n | ToolTimeoutError\n | ToolValidationError\n | ToolAuthorizationError\n >;\n\n readonly register: (\n definition: ToolDefinition,\n handler: (\n args: Record<string, unknown>,\n ) => Effect.Effect<unknown, ToolExecutionError>,\n ) => Effect.Effect<void, never>;\n\n readonly connectMCPServer: (\n config: Pick<\n MCPServer,\n \"name\" | \"transport\" | \"endpoint\" | \"command\" | \"args\"\n >,\n ) => Effect.Effect<MCPServer, MCPConnectionError>;\n\n readonly disconnectMCPServer: (\n serverName: string,\n ) => Effect.Effect<void, MCPConnectionError>;\n\n readonly listTools: (filter?: {\n category?: string;\n source?: string;\n riskLevel?: string;\n }) => Effect.Effect<readonly ToolDefinition[], never>;\n\n readonly getTool: (\n name: string,\n ) => Effect.Effect<ToolDefinition, ToolNotFoundError>;\n\n readonly toFunctionCallingFormat: () => Effect.Effect<\n readonly FunctionCallingTool[],\n never\n >;\n\n readonly listMCPServers: () => Effect.Effect<readonly MCPServer[], never>;\n }\n>() {}\n\n// ─── Live Implementation ───\n\nexport const ToolServiceLive = Layer.effect(\n ToolService,\n Effect.gen(function* () {\n const eventBus = yield* EventBus;\n const registry = yield* makeToolRegistry;\n const mcpClient = yield* makeMCPClient;\n const sandbox = makeSandbox();\n\n const execute = (\n input: ToolInput,\n ): Effect.Effect<\n ToolOutput,\n | ToolNotFoundError\n | ToolExecutionError\n | ToolTimeoutError\n | ToolValidationError\n | ToolAuthorizationError\n > =>\n Effect.gen(function* () {\n const startTime = Date.now();\n\n // Step 1: Look up tool\n const tool = yield* registry.get(input.toolName);\n\n // Step 2: Validate input\n const validatedArgs = yield* validateToolInput(\n tool.definition,\n input.arguments,\n );\n\n // Step 3: Execute in sandbox with timeout\n const result = yield* sandbox.execute(\n () => tool.handler(validatedArgs),\n {\n timeoutMs: tool.definition.timeoutMs,\n toolName: input.toolName,\n },\n );\n\n const executionTimeMs = Date.now() - startTime;\n\n // Step 4: Emit event\n yield* eventBus.publish({\n _tag: \"Custom\",\n type: \"tools.executed\",\n payload: {\n toolName: input.toolName,\n success: true,\n executionTimeMs,\n },\n });\n\n return {\n toolName: input.toolName,\n success: true as const,\n result,\n executionTimeMs,\n } satisfies ToolOutput;\n });\n\n const register = (\n definition: ToolDefinition,\n handler: (\n args: Record<string, unknown>,\n ) => Effect.Effect<unknown, ToolExecutionError>,\n ): Effect.Effect<void, never> => registry.register(definition, handler);\n\n const connectMCPServer = (\n config: Pick<\n MCPServer,\n \"name\" | \"transport\" | \"endpoint\" | \"command\" | \"args\"\n >,\n ): Effect.Effect<MCPServer, MCPConnectionError> =>\n Effect.gen(function* () {\n const server = yield* mcpClient.connect(config);\n\n // Register each MCP tool in the registry\n for (const toolName of server.tools) {\n yield* registry.register(\n {\n name: `${server.name}/${toolName}`,\n description: `MCP tool from ${server.name}`,\n parameters: [],\n riskLevel: \"medium\",\n timeoutMs: 30_000,\n requiresApproval: false,\n source: \"mcp\",\n },\n (args) =>\n mcpClient.callTool(server.name, toolName, args).pipe(\n Effect.mapError(\n (e) =>\n new ToolExecutionError({\n message: `MCP tool ${toolName} failed`,\n toolName,\n cause: e,\n }),\n ),\n ),\n );\n }\n\n yield* eventBus.publish({\n _tag: \"Custom\",\n type: \"tools.mcp-connected\",\n payload: { serverName: server.name, tools: server.tools },\n });\n\n return server;\n });\n\n const disconnectMCPServer = (\n serverName: string,\n ): Effect.Effect<void, MCPConnectionError> =>\n Effect.gen(function* () {\n yield* mcpClient.disconnect(serverName);\n yield* eventBus.publish({\n _tag: \"Custom\",\n type: \"tools.mcp-disconnected\",\n payload: { serverName },\n });\n });\n\n const listTools = (filter?: {\n category?: string;\n source?: string;\n riskLevel?: string;\n }): Effect.Effect<readonly ToolDefinition[], never> =>\n registry.list(filter);\n\n const getTool = (\n name: string,\n ): Effect.Effect<ToolDefinition, ToolNotFoundError> =>\n registry.get(name).pipe(Effect.map((t) => t.definition));\n\n const toFunctionCallingFormat = (): Effect.Effect<\n readonly FunctionCallingTool[],\n never\n > => registry.toFunctionCallingFormat();\n\n const listMCPServers = (): Effect.Effect<readonly MCPServer[], never> =>\n mcpClient.listServers();\n\n return {\n execute,\n register,\n connectMCPServer,\n disconnectMCPServer,\n listTools,\n getTool,\n toFunctionCallingFormat,\n listMCPServers,\n };\n }),\n);\n","import { Effect, Ref } from \"effect\";\n\nimport type { ToolDefinition, FunctionCallingTool } from \"../types.js\";\nimport { ToolNotFoundError, ToolExecutionError } from \"../errors.js\";\n\nexport interface RegisteredTool {\n readonly definition: ToolDefinition;\n readonly handler: (\n args: Record<string, unknown>,\n ) => Effect.Effect<unknown, ToolExecutionError>;\n}\n\nexport const makeToolRegistry = Effect.gen(function* () {\n const toolsRef = yield* Ref.make<Map<string, RegisteredTool>>(new Map());\n\n const register = (\n definition: ToolDefinition,\n handler: (\n args: Record<string, unknown>,\n ) => Effect.Effect<unknown, ToolExecutionError>,\n ): Effect.Effect<void, never> =>\n Ref.update(toolsRef, (tools) => {\n const newTools = new Map(tools);\n newTools.set(definition.name, { definition, handler });\n return newTools;\n });\n\n const get = (\n name: string,\n ): Effect.Effect<RegisteredTool, ToolNotFoundError> =>\n Effect.gen(function* () {\n const tools = yield* Ref.get(toolsRef);\n const tool = tools.get(name);\n if (!tool) {\n const available = [...tools.keys()];\n return yield* Effect.fail(\n new ToolNotFoundError({\n message: `Tool \"${name}\" not found`,\n toolName: name,\n availableTools: available,\n }),\n );\n }\n return tool;\n });\n\n const list = (filter?: {\n category?: string;\n source?: string;\n riskLevel?: string;\n }): Effect.Effect<readonly ToolDefinition[], never> =>\n Effect.gen(function* () {\n const tools = yield* Ref.get(toolsRef);\n let definitions = [...tools.values()].map((t) => t.definition);\n\n if (filter?.category)\n definitions = definitions.filter((d) => d.category === filter.category);\n if (filter?.source)\n definitions = definitions.filter((d) => d.source === filter.source);\n if (filter?.riskLevel)\n definitions = definitions.filter(\n (d) => d.riskLevel === filter.riskLevel,\n );\n\n return definitions;\n });\n\n const toFunctionCallingFormat = (): Effect.Effect<\n readonly FunctionCallingTool[],\n never\n > =>\n Effect.gen(function* () {\n const tools = yield* Ref.get(toolsRef);\n return [...tools.values()].map((t) => ({\n name: t.definition.name,\n description: t.definition.description,\n input_schema: {\n type: \"object\" as unknown,\n properties: Object.fromEntries(\n t.definition.parameters.map((p) => [\n p.name,\n {\n type: p.type,\n description: p.description,\n ...(p.enum ? { enum: p.enum } : {}),\n },\n ]),\n ) as Record<string, unknown>,\n required: t.definition.parameters\n .filter((p) => p.required)\n .map((p) => p.name),\n } as Record<string, unknown>,\n }));\n });\n\n return { register, get, list, toFunctionCallingFormat };\n});\n","import { Effect, Ref } from \"effect\";\n\nimport type { MCPServer, MCPRequest, MCPResponse } from \"../types.js\";\nimport { MCPConnectionError, ToolExecutionError } from \"../errors.js\";\n\n// ─── Transport Creation (stub - real implementation varies by transport) ───\n\nconst createTransport = (\n _config: Pick<\n MCPServer,\n \"name\" | \"transport\" | \"endpoint\" | \"command\" | \"args\"\n >,\n): Effect.Effect<void, unknown> => Effect.void;\n\n// ─── JSON-RPC request sender (stub) ───\n\nconst sendRequest = (\n _config: Pick<MCPServer, \"name\" | \"transport\" | \"endpoint\" | \"command\">,\n request: MCPRequest,\n): Effect.Effect<MCPResponse, MCPConnectionError> =>\n Effect.succeed({\n jsonrpc: \"2.0\" as const,\n id: request.id,\n result: {},\n });\n\nexport const makeMCPClient = Effect.gen(function* () {\n const serversRef = yield* Ref.make<Map<string, MCPServer>>(new Map());\n const requestIdRef = yield* Ref.make(0);\n\n const nextRequestId = Ref.updateAndGet(requestIdRef, (id) => id + 1);\n\n const connect = (\n config: Pick<\n MCPServer,\n \"name\" | \"transport\" | \"endpoint\" | \"command\" | \"args\"\n >,\n ): Effect.Effect<MCPServer, MCPConnectionError> =>\n Effect.gen(function* () {\n // Step 1: Establish connection based on transport\n yield* createTransport(config).pipe(\n Effect.mapError(\n (e) =>\n new MCPConnectionError({\n message: `Failed to connect to MCP server \"${config.name}\"`,\n serverName: config.name,\n transport: config.transport,\n cause: e,\n }),\n ),\n );\n\n // Step 2: Initialize protocol (send initialize request)\n const reqId1 = yield* nextRequestId;\n const initResponse = yield* sendRequest(config, {\n jsonrpc: \"2.0\",\n id: reqId1,\n method: \"initialize\",\n params: {\n protocolVersion: \"2024-11-05\",\n capabilities: { tools: {} },\n clientInfo: { name: \"reactive-agents\", version: \"1.0.0\" },\n },\n });\n\n // Step 3: Discover available tools\n const reqId2 = yield* nextRequestId;\n const toolsResponse = yield* sendRequest(config, {\n jsonrpc: \"2.0\",\n id: reqId2,\n method: \"tools/list\",\n });\n\n const toolNames = Array.isArray(toolsResponse.result)\n ? toolsResponse.result.map(\n (t: Record<string, unknown>) => t.name as string,\n )\n : [];\n\n const server: MCPServer = {\n name: config.name,\n version:\n (initResponse.result as Record<string, unknown>)?.serverInfo !=\n null\n ? String(\n (\n (initResponse.result as Record<string, unknown>)\n .serverInfo as Record<string, unknown>\n )?.version,\n )\n : \"unknown\",\n transport: config.transport,\n endpoint: config.endpoint,\n command: config.command,\n args: config.args,\n tools: toolNames,\n status: \"connected\",\n };\n\n yield* Ref.update(serversRef, (servers) => {\n const newServers = new Map(servers);\n newServers.set(server.name, server);\n return newServers;\n });\n\n return server;\n });\n\n const callTool = (\n serverName: string,\n toolName: string,\n args: Record<string, unknown>,\n ): Effect.Effect<unknown, MCPConnectionError | ToolExecutionError> =>\n Effect.gen(function* () {\n const servers = yield* Ref.get(serversRef);\n const server = servers.get(serverName);\n\n if (!server || server.status !== \"connected\") {\n return yield* Effect.fail(\n new MCPConnectionError({\n message: `MCP server \"${serverName}\" not connected`,\n serverName,\n transport: server?.transport ?? \"unknown\",\n }),\n );\n }\n\n const reqId = yield* nextRequestId;\n const response = yield* sendRequest(\n {\n name: serverName,\n transport: server.transport,\n endpoint: server.endpoint,\n command: server.command,\n },\n {\n jsonrpc: \"2.0\",\n id: reqId,\n method: \"tools/call\",\n params: { name: toolName, arguments: args },\n },\n );\n\n if (response.error) {\n return yield* Effect.fail(\n new ToolExecutionError({\n message: `MCP tool \"${toolName}\" failed: ${response.error.message}`,\n toolName,\n input: args,\n }),\n );\n }\n\n return response.result;\n });\n\n const disconnect = (\n serverName: string,\n ): Effect.Effect<void, MCPConnectionError> =>\n Ref.update(serversRef, (servers) => {\n const newServers = new Map(servers);\n const server = newServers.get(serverName);\n if (server) {\n newServers.set(serverName, { ...server, status: \"disconnected\" });\n }\n return newServers;\n });\n\n const listServers = (): Effect.Effect<readonly MCPServer[], never> =>\n Effect.gen(function* () {\n const servers = yield* Ref.get(serversRef);\n return [...servers.values()];\n });\n\n return { connect, callTool, disconnect, listServers };\n});\n","import { Duration, Effect } from \"effect\";\n\nimport { ToolExecutionError, ToolTimeoutError } from \"../errors.js\";\n\nexport const makeSandbox = () => {\n const execute = <A>(\n fn: () => Effect.Effect<A, ToolExecutionError>,\n options: { timeoutMs: number; toolName?: string },\n ): Effect.Effect<A, ToolExecutionError | ToolTimeoutError> =>\n fn().pipe(\n // Enforce timeout\n Effect.timeoutFail({\n duration: Duration.millis(options.timeoutMs),\n onTimeout: () =>\n new ToolTimeoutError({\n message: `Tool execution timed out after ${options.timeoutMs}ms`,\n toolName: options.toolName ?? \"unknown\",\n timeoutMs: options.timeoutMs,\n }),\n }),\n // Catch unexpected errors\n Effect.catchAllDefect((defect) =>\n Effect.fail(\n new ToolExecutionError({\n message: `Tool crashed: ${String(defect)}`,\n toolName: options.toolName ?? \"unknown\",\n cause: defect,\n }),\n ),\n ),\n );\n\n return { execute };\n};\n","import { Effect } from \"effect\";\n\nimport type { ToolDefinition } from \"../types.js\";\nimport { ToolValidationError } from \"../errors.js\";\n\nexport const validateToolInput = (\n definition: ToolDefinition,\n args: Record<string, unknown>,\n): Effect.Effect<Record<string, unknown>, ToolValidationError> =>\n Effect.gen(function* () {\n const validated: Record<string, unknown> = {};\n\n for (const param of definition.parameters) {\n const value = args[param.name];\n\n // Check required\n if (param.required && (value === undefined || value === null)) {\n return yield* Effect.fail(\n new ToolValidationError({\n message: `Missing required parameter \"${param.name}\"`,\n toolName: definition.name,\n parameter: param.name,\n expected: param.type,\n received: \"undefined\",\n }),\n );\n }\n\n if (value === undefined) {\n if (param.default !== undefined) {\n validated[param.name] = param.default;\n }\n continue;\n }\n\n // Type check\n const actualType = Array.isArray(value) ? \"array\" : typeof value;\n if (\n actualType !== param.type &&\n !(param.type === \"object\" && actualType === \"object\")\n ) {\n return yield* Effect.fail(\n new ToolValidationError({\n message: `Parameter \"${param.name}\" expected ${param.type}, got ${actualType}`,\n toolName: definition.name,\n parameter: param.name,\n expected: param.type,\n received: actualType,\n }),\n );\n }\n\n // Enum check\n if (\n param.enum &&\n typeof value === \"string\" &&\n !param.enum.includes(value)\n ) {\n return yield* Effect.fail(\n new ToolValidationError({\n message: `Parameter \"${param.name}\" must be one of: ${param.enum.join(\", \")}`,\n toolName: definition.name,\n parameter: param.name,\n expected: param.enum.join(\" | \"),\n received: String(value),\n }),\n );\n }\n\n validated[param.name] = value;\n }\n\n return validated;\n });\n","import { Effect } from \"effect\";\n\nimport type { ToolDefinition, FunctionCallingTool } from \"../types.js\";\nimport { ToolExecutionError } from \"../errors.js\";\n\n/**\n * Adapt a native function into a ToolDefinition + handler pair\n * suitable for registration in the ToolRegistry.\n */\nexport const adaptFunction = (opts: {\n readonly name: string;\n readonly description: string;\n readonly parameters: ToolDefinition[\"parameters\"];\n readonly category?: ToolDefinition[\"category\"];\n readonly riskLevel?: ToolDefinition[\"riskLevel\"];\n readonly timeoutMs?: number;\n readonly fn: (\n args: Record<string, unknown>,\n ) => Effect.Effect<unknown, ToolExecutionError>;\n}): {\n definition: ToolDefinition;\n handler: (\n args: Record<string, unknown>,\n ) => Effect.Effect<unknown, ToolExecutionError>;\n} => ({\n definition: {\n name: opts.name,\n description: opts.description,\n parameters: opts.parameters,\n category: opts.category,\n riskLevel: opts.riskLevel ?? \"low\",\n timeoutMs: opts.timeoutMs ?? 30_000,\n requiresApproval: false,\n source: \"function\" as const,\n },\n handler: opts.fn,\n});\n\n/**\n * Convert a ToolDefinition to the Anthropic/OpenAI function calling format.\n */\nexport const toFunctionCallingTool = (\n definition: ToolDefinition,\n): FunctionCallingTool => ({\n name: definition.name,\n description: definition.description,\n input_schema: {\n type: \"object\" as unknown,\n properties: Object.fromEntries(\n definition.parameters.map((p) => [\n p.name,\n {\n type: p.type,\n description: p.description,\n ...(p.enum ? { enum: p.enum } : {}),\n },\n ]),\n ) as Record<string, unknown>,\n required: definition.parameters\n .filter((p) => p.required)\n .map((p) => p.name),\n } as Record<string, unknown>,\n});\n","import { Effect } from \"effect\";\n\nimport type { ToolDefinition } from \"../types.js\";\nimport { ToolExecutionError } from \"../errors.js\";\n\nexport const webSearchTool: ToolDefinition = {\n name: \"web-search\",\n description: \"Search the web for information using a query string\",\n parameters: [\n {\n name: \"query\",\n type: \"string\",\n description: \"Search query\",\n required: true,\n },\n {\n name: \"maxResults\",\n type: \"number\",\n description: \"Max results to return\",\n required: false,\n default: 5,\n },\n ],\n category: \"search\",\n riskLevel: \"low\",\n timeoutMs: 10_000,\n requiresApproval: false,\n source: \"builtin\",\n};\n\nexport const webSearchHandler = (\n args: Record<string, unknown>,\n): Effect.Effect<unknown, ToolExecutionError> =>\n Effect.tryPromise({\n try: async () => {\n const query = args.query as string;\n const maxResults = (args.maxResults as number) ?? 5;\n\n // In production: call search API (Tavily, SerpAPI, etc.)\n // Stub implementation for Phase 1\n return {\n query,\n maxResults,\n results: [],\n message: \"Web search stub - configure TAVILY_API_KEY for real results\",\n };\n },\n catch: (e) =>\n new ToolExecutionError({\n message: `Web search failed: ${e}`,\n toolName: \"web-search\",\n cause: e,\n }),\n });\n","import { Effect } from \"effect\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\n\nimport type { ToolDefinition } from \"../types.js\";\nimport { ToolExecutionError } from \"../errors.js\";\n\nexport const fileReadTool: ToolDefinition = {\n name: \"file-read\",\n description: \"Read the contents of a file\",\n parameters: [\n {\n name: \"path\",\n type: \"string\",\n description: \"File path to read\",\n required: true,\n },\n {\n name: \"encoding\",\n type: \"string\",\n description: \"File encoding\",\n required: false,\n default: \"utf-8\",\n },\n ],\n category: \"file\",\n riskLevel: \"medium\",\n timeoutMs: 5_000,\n requiresApproval: false,\n source: \"builtin\",\n};\n\nexport const fileReadHandler = (\n args: Record<string, unknown>,\n): Effect.Effect<unknown, ToolExecutionError> =>\n Effect.tryPromise({\n try: async () => {\n const filePath = args.path as string;\n const encoding = (args.encoding as BufferEncoding) ?? \"utf-8\";\n\n // Security: resolve path and check it's within allowed directory\n const resolved = path.resolve(filePath);\n const allowedBase = process.cwd();\n if (!resolved.startsWith(allowedBase)) {\n throw new Error(`Path traversal detected: ${filePath}`);\n }\n\n return await fs.readFile(resolved, { encoding });\n },\n catch: (e) =>\n new ToolExecutionError({\n message: `File read failed: ${e}`,\n toolName: \"file-read\",\n cause: e,\n }),\n });\n\nexport const fileWriteTool: ToolDefinition = {\n name: \"file-write\",\n description: \"Write contents to a file\",\n parameters: [\n {\n name: \"path\",\n type: \"string\",\n description: \"File path to write\",\n required: true,\n },\n {\n name: \"content\",\n type: \"string\",\n description: \"Content to write\",\n required: true,\n },\n {\n name: \"encoding\",\n type: \"string\",\n description: \"File encoding\",\n required: false,\n default: \"utf-8\",\n },\n ],\n category: \"file\",\n riskLevel: \"high\",\n timeoutMs: 5_000,\n requiresApproval: true,\n source: \"builtin\",\n};\n\nexport const fileWriteHandler = (\n args: Record<string, unknown>,\n): Effect.Effect<unknown, ToolExecutionError> =>\n Effect.tryPromise({\n try: async () => {\n const filePath = args.path as string;\n const content = args.content as string;\n const encoding = (args.encoding as BufferEncoding) ?? \"utf-8\";\n\n const resolved = path.resolve(filePath);\n const allowedBase = process.cwd();\n if (!resolved.startsWith(allowedBase)) {\n throw new Error(`Path traversal detected: ${filePath}`);\n }\n\n await fs.writeFile(resolved, content, { encoding });\n return { written: true, path: resolved };\n },\n catch: (e) =>\n new ToolExecutionError({\n message: `File write failed: ${e}`,\n toolName: \"file-write\",\n cause: e,\n }),\n });\n","import { Effect } from \"effect\";\n\nimport type { ToolDefinition } from \"../types.js\";\nimport { ToolExecutionError } from \"../errors.js\";\n\nexport const httpGetTool: ToolDefinition = {\n name: \"http-get\",\n description: \"Make an HTTP GET request to a URL\",\n parameters: [\n {\n name: \"url\",\n type: \"string\",\n description: \"URL to fetch\",\n required: true,\n },\n {\n name: \"headers\",\n type: \"object\",\n description: \"Optional request headers\",\n required: false,\n },\n ],\n category: \"http\",\n riskLevel: \"medium\",\n timeoutMs: 15_000,\n requiresApproval: false,\n source: \"builtin\",\n};\n\nexport const httpGetHandler = (\n args: Record<string, unknown>,\n): Effect.Effect<unknown, ToolExecutionError> =>\n Effect.tryPromise({\n try: async () => {\n const url = args.url as string;\n const headers = (args.headers as Record<string, string>) ?? {};\n\n const response = await fetch(url, { method: \"GET\", headers });\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n\n let body: unknown;\n if (contentType.includes(\"application/json\")) {\n body = await response.json();\n } else {\n body = await response.text();\n }\n\n return {\n status: response.status,\n statusText: response.statusText,\n headers: Object.fromEntries(response.headers.entries()),\n body,\n };\n },\n catch: (e) =>\n new ToolExecutionError({\n message: `HTTP GET failed: ${e}`,\n toolName: \"http-get\",\n cause: e,\n }),\n });\n","import { Effect } from \"effect\";\n\nimport type { ToolDefinition } from \"../types.js\";\nimport { ToolExecutionError } from \"../errors.js\";\n\nexport const codeExecuteTool: ToolDefinition = {\n name: \"code-execute\",\n description: \"Execute a JavaScript/TypeScript code snippet in a sandboxed environment\",\n parameters: [\n {\n name: \"code\",\n type: \"string\",\n description: \"Code to execute\",\n required: true,\n },\n {\n name: \"language\",\n type: \"string\",\n description: \"Programming language\",\n required: false,\n default: \"javascript\",\n enum: [\"javascript\", \"typescript\"],\n },\n ],\n category: \"code\",\n riskLevel: \"critical\",\n timeoutMs: 30_000,\n requiresApproval: true,\n source: \"builtin\",\n};\n\nexport const codeExecuteHandler = (\n args: Record<string, unknown>,\n): Effect.Effect<unknown, ToolExecutionError> =>\n Effect.try({\n try: () => {\n const code = args.code as string;\n // Phase 1: Simple eval-based execution (stub)\n // In production: use isolated-vm or Worker threads\n // For safety, we only return a stub response\n return {\n code,\n executed: false,\n message:\n \"Code execution stub - production implementation requires sandboxed runtime\",\n };\n },\n catch: (e) =>\n new ToolExecutionError({\n message: `Code execution failed: ${e}`,\n toolName: \"code-execute\",\n cause: e,\n }),\n });\n","import { Layer } from \"effect\";\n\nimport { EventBusLive } from \"@reactive-agents/core\";\nimport { ToolServiceLive } from \"./tool-service.js\";\n\n/**\n * Creates the full Tools layer with all dependencies wired.\n * Requires EventBus to be provided (or uses EventBusLive by default).\n */\nexport const createToolsLayer = () =>\n ToolServiceLive.pipe(Layer.provide(EventBusLive));\n\n/**\n * ToolServiceLive layer that requires EventBus to be provided externally.\n * Use this when composing with a shared EventBus from the runtime.\n */\nexport const ToolsLayer = ToolServiceLive;\n"],"mappings":"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","names":["Effect","Effect","Ref","Effect","Ref","Effect","Effect","Effect","Effect","Effect","Effect","Effect","Effect","Effect","Effect","Effect","Effect","Effect","Layer","Layer"]}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@reactive-agents/tools",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsup --config ../../tsup.config.base.ts",
9
+ "typecheck": "tsc --noEmit",
10
+ "test": "bun test",
11
+ "test:watch": "bun test --watch"
12
+ },
13
+ "dependencies": {
14
+ "effect": "^3.10.0",
15
+ "@reactive-agents/core": "0.1.0"
16
+ },
17
+ "devDependencies": {
18
+ "typescript": "^5.7.0",
19
+ "bun-types": "latest"
20
+ },
21
+ "license": "MIT",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/tylerjrbuell/reactive-agents-ts.git",
25
+ "directory": "packages/tools"
26
+ },
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "files": [
31
+ "dist",
32
+ "README.md",
33
+ "LICENSE"
34
+ ],
35
+ "exports": {
36
+ ".": {
37
+ "types": "./dist/index.d.ts",
38
+ "import": "./dist/index.js",
39
+ "default": "./dist/index.js"
40
+ }
41
+ },
42
+ "description": "Tool system for Reactive Agents — registry, sandboxed execution, and MCP client",
43
+ "homepage": "https://tylerjrbuell.github.io/reactive-agents-ts/",
44
+ "bugs": {
45
+ "url": "https://github.com/tylerjrbuell/reactive-agents-ts/issues"
46
+ }
47
+ }