@runlayer/hooks-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/README.md +292 -0
- package/dist/claude-agent-sdk.d.ts +43 -0
- package/dist/claude-agent-sdk.d.ts.map +1 -0
- package/dist/claude-agent-sdk.js +202 -0
- package/dist/claude-agent-sdk.js.map +1 -0
- package/dist/client.d.ts +142 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +536 -0
- package/dist/client.js.map +1 -0
- package/dist/google-adk.d.ts +26 -0
- package/dist/google-adk.d.ts.map +1 -0
- package/dist/google-adk.js +33 -0
- package/dist/google-adk.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/internal.d.ts +4 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +4 -0
- package/dist/internal.js.map +1 -0
- package/dist/openai-agents-sdk.d.ts +28 -0
- package/dist/openai-agents-sdk.d.ts.map +1 -0
- package/dist/openai-agents-sdk.js +31 -0
- package/dist/openai-agents-sdk.js.map +1 -0
- package/dist/preflight.d.ts +14 -0
- package/dist/preflight.d.ts.map +1 -0
- package/dist/preflight.js +35 -0
- package/dist/preflight.js.map +1 -0
- package/dist/tool-adapter.d.ts +29 -0
- package/dist/tool-adapter.d.ts.map +1 -0
- package/dist/tool-adapter.js +61 -0
- package/dist/tool-adapter.js.map +1 -0
- package/dist/tool-enforcement.d.ts +18 -0
- package/dist/tool-enforcement.d.ts.map +1 -0
- package/dist/tool-enforcement.js +114 -0
- package/dist/tool-enforcement.js.map +1 -0
- package/dist/vercel-ai-sdk.d.ts +20 -0
- package/dist/vercel-ai-sdk.d.ts.map +1 -0
- package/dist/vercel-ai-sdk.js +29 -0
- package/dist/vercel-ai-sdk.js.map +1 -0
- package/package.json +68 -0
package/README.md
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
# Runlayer Hooks TypeScript SDK
|
|
2
|
+
|
|
3
|
+
First-party Hooks TypeScript SDK for wiring agent runtimes into Runlayer governance,
|
|
4
|
+
telemetry, and hook enforcement.
|
|
5
|
+
|
|
6
|
+
Phase 1 supports Claude Agent SDK hooks plus structural adapters for common
|
|
7
|
+
TypeScript agent tool APIs:
|
|
8
|
+
|
|
9
|
+
- lifecycle telemetry for session, prompt, and stop events
|
|
10
|
+
- pre-tool enforcement with argument rewriting
|
|
11
|
+
- post-tool output scanning and blocking
|
|
12
|
+
- failed tool telemetry
|
|
13
|
+
- direct MCP source enforcement
|
|
14
|
+
- preflight session emission for ingestion checks
|
|
15
|
+
- transcript-bearing `Stop` emission for completed assistant messages
|
|
16
|
+
- Vercel AI SDK tool wrappers
|
|
17
|
+
- OpenAI Agents SDK function tool wrappers
|
|
18
|
+
- Google ADK `FunctionTool` option wrappers
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
pnpm add @runlayer/hooks-sdk@0.1.0
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Install the framework package you use separately, such as
|
|
27
|
+
`@anthropic-ai/claude-agent-sdk`, `ai`, `@openai/agents`, or `@google/adk`.
|
|
28
|
+
|
|
29
|
+
## Configure
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
export RUNLAYER_BASE_URL="https://your-runlayer-instance.com"
|
|
33
|
+
export RUNLAYER_API_KEY="rl_..."
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
For agent account authentication, set client credentials instead:
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
export RUNLAYER_BASE_URL="https://your-runlayer-instance.com"
|
|
40
|
+
export RUNLAYER_AGENT_CLIENT_ID="client_..."
|
|
41
|
+
export RUNLAYER_AGENT_CLIENT_SECRET="..."
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The SDK exchanges these credentials for a Runlayer bearer token with
|
|
45
|
+
`client_credentials`, then caches and refreshes that token internally. Do not
|
|
46
|
+
configure or pass a pre-minted bearer token.
|
|
47
|
+
|
|
48
|
+
For OBO agent tokens, also set:
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
export RUNLAYER_AGENT_SUBJECT_TOKEN="user@example.com"
|
|
52
|
+
export RUNLAYER_AGENT_SUBJECT_TOKEN_TYPE="urn:runlayer:token-type:user-email"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`RunlayerClient.fromEnv()` defaults to `client: "typescript-sdk"` so phase 1
|
|
56
|
+
events are attributed to the first-party Hooks TypeScript SDK in Runlayer.
|
|
57
|
+
|
|
58
|
+
Optional runtime controls:
|
|
59
|
+
|
|
60
|
+
| Variable | Purpose |
|
|
61
|
+
| ---------------------------------------- | ---------------------------------------------------------------------------------------------------- |
|
|
62
|
+
| `RUNLAYER_HOOK_TIMEOUT_MS` | Hook request timeout. Defaults to `10000`. |
|
|
63
|
+
| `RUNLAYER_HOOK_MAX_TOOL_OUTPUT_BYTES` | Maximum serialized tool output sent to Runlayer. Defaults to `65536`. |
|
|
64
|
+
| `RUNLAYER_HOOK_ENFORCEMENT_FAILURE_MODE` | Defaults to `closed`; set to `open` only if tool calls should continue when Runlayer is unreachable. |
|
|
65
|
+
| `RUNLAYER_ALLOW_INSECURE_TRANSPORT=1` | Allow non-HTTPS `RUNLAYER_BASE_URL` for local development. |
|
|
66
|
+
|
|
67
|
+
Enforcement calls fail closed by default. Lifecycle telemetry is best-effort
|
|
68
|
+
unless a helper documents strict behavior. Tool output is capped before upload,
|
|
69
|
+
and failed tool details include bounded stdout/stderr/output fields with
|
|
70
|
+
truncation metadata.
|
|
71
|
+
|
|
72
|
+
The SDK skips pre-tool and post-tool enforcement for Runlayer's own MCP server
|
|
73
|
+
names (`runlayer`, `runlayer-plugin`, and `onelayer`) and for MCP calls whose
|
|
74
|
+
`toolUrl` points at a Runlayer proxy URL. Third-party MCP tools stay enforced by
|
|
75
|
+
default. Use `shouldEnforceTool(...)` or `toolEnforcement` when building a
|
|
76
|
+
custom TypeScript adapter. Additional `ignoredMcpServerNames` are added to the
|
|
77
|
+
default Runlayer self-MCP skip list; set `skipRunlayerSelfMcp: false` only if you
|
|
78
|
+
need to enforce those self-MCP names. If you call `shouldEnforceTool(...)`
|
|
79
|
+
directly with absolute self-hosted Runlayer MCP proxy URLs, pass
|
|
80
|
+
`runlayerBaseUrl`; `RunlayerClient` does this automatically.
|
|
81
|
+
|
|
82
|
+
## Claude Agent SDK Hooks
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
86
|
+
import {
|
|
87
|
+
claudeAgentSdkAssistantMessageToTranscriptLine,
|
|
88
|
+
createClaudeAgentSdkHooks,
|
|
89
|
+
emitClaudeAgentSdkTranscriptStop,
|
|
90
|
+
RunlayerClient,
|
|
91
|
+
} from "@runlayer/hooks-sdk/claude-agent-sdk";
|
|
92
|
+
|
|
93
|
+
const runlayer = RunlayerClient.fromEnv({
|
|
94
|
+
clientVersion: "my-agent/1.0.0",
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const transcriptLines: string[] = [];
|
|
98
|
+
let sessionId: string | undefined;
|
|
99
|
+
|
|
100
|
+
for await (const message of query({
|
|
101
|
+
prompt: "Inspect this workspace",
|
|
102
|
+
options: {
|
|
103
|
+
hooks: createClaudeAgentSdkHooks(runlayer, { includeStop: false }),
|
|
104
|
+
thinking: { type: "adaptive" },
|
|
105
|
+
},
|
|
106
|
+
})) {
|
|
107
|
+
if (message.type === "system" && message.subtype === "init") {
|
|
108
|
+
sessionId = message.session_id;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (message.type === "assistant") {
|
|
112
|
+
transcriptLines.push(claudeAgentSdkAssistantMessageToTranscriptLine(message.message));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (sessionId) {
|
|
117
|
+
await emitClaudeAgentSdkTranscriptStop(runlayer, {
|
|
118
|
+
model: "claude-agent-sdk",
|
|
119
|
+
sessionId,
|
|
120
|
+
transcriptLines,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Use `includeStop: false` when you emit a transcript-bearing `Stop` manually.
|
|
126
|
+
That lets Runlayer extract assistant thinking/reasoning blocks from the
|
|
127
|
+
transcript instead of receiving a bare lifecycle stop.
|
|
128
|
+
|
|
129
|
+
## Preflight
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
import { RunlayerClient, sendRunlayerPreflight } from "@runlayer/hooks-sdk";
|
|
133
|
+
|
|
134
|
+
const result = await sendRunlayerPreflight(RunlayerClient.fromEnv(), {
|
|
135
|
+
prompt: "Runlayer ingestion preflight",
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
console.log(result.sessionId);
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Tool Wrapping
|
|
142
|
+
|
|
143
|
+
Use `runTool` when you are invoking tools yourself rather than through a Claude
|
|
144
|
+
Agent SDK hook.
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
const output = await runlayer.runTool({
|
|
148
|
+
execute: async (toolInput) => {
|
|
149
|
+
return runLocalTool(toolInput);
|
|
150
|
+
},
|
|
151
|
+
sessionId: "session-id",
|
|
152
|
+
toolInput: { command: "cat README.md" },
|
|
153
|
+
toolName: "Bash",
|
|
154
|
+
toolType: "shell",
|
|
155
|
+
});
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Pass `toolUrl` when wrapping MCP tools manually. Runlayer proxy URLs such as
|
|
159
|
+
`/api/v1/proxy/<id>/mcp`, `/api/v1/proxy/plugins/<id>/mcp`,
|
|
160
|
+
`/api/v1/proxy/skills/<id>/mcp`, and `/api/v1/proxy/agent-account/<id>/mcp` are
|
|
161
|
+
skipped automatically because the proxy already runs MCP policy and scanner
|
|
162
|
+
enforcement.
|
|
163
|
+
|
|
164
|
+
## Vercel AI SDK Tools
|
|
165
|
+
|
|
166
|
+
Wrap a Vercel AI SDK tool set before passing it to `generateText`,
|
|
167
|
+
`streamText`, or a `ToolLoopAgent`.
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
import { streamText, tool } from "ai";
|
|
171
|
+
import { withRunlayerVercelAiTools, RunlayerClient } from "@runlayer/hooks-sdk/vercel-ai-sdk";
|
|
172
|
+
|
|
173
|
+
const runlayer = RunlayerClient.fromEnv({
|
|
174
|
+
clientVersion: "my-agent/1.0.0",
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
const tools = withRunlayerVercelAiTools(
|
|
178
|
+
{
|
|
179
|
+
getWeather: tool({
|
|
180
|
+
description: "Get weather for a city",
|
|
181
|
+
inputSchema: {
|
|
182
|
+
type: "object",
|
|
183
|
+
properties: { city: { type: "string" } },
|
|
184
|
+
required: ["city"],
|
|
185
|
+
},
|
|
186
|
+
execute: async ({ city }) => ({ forecast: `sunny in ${city}` }),
|
|
187
|
+
}),
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
client: runlayer,
|
|
191
|
+
sessionId: "session-id",
|
|
192
|
+
},
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
await streamText({
|
|
196
|
+
model,
|
|
197
|
+
prompt: "Check the weather in Paris",
|
|
198
|
+
tools,
|
|
199
|
+
});
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
The adapter preserves the Vercel execution options and forwards `toolCallId` to
|
|
203
|
+
Runlayer as `toolUseId`.
|
|
204
|
+
|
|
205
|
+
## OpenAI Agents SDK Tools
|
|
206
|
+
|
|
207
|
+
Wrap function tool options before passing them to OpenAI Agents SDK's `tool(...)`
|
|
208
|
+
helper.
|
|
209
|
+
|
|
210
|
+
```ts
|
|
211
|
+
import { tool } from "@openai/agents";
|
|
212
|
+
import {
|
|
213
|
+
withRunlayerOpenAIAgentsTool,
|
|
214
|
+
RunlayerClient,
|
|
215
|
+
} from "@runlayer/hooks-sdk/openai-agents-sdk";
|
|
216
|
+
|
|
217
|
+
const runlayer = RunlayerClient.fromEnv({
|
|
218
|
+
clientVersion: "my-agent/1.0.0",
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
const lookupTicket = tool(
|
|
222
|
+
withRunlayerOpenAIAgentsTool(
|
|
223
|
+
{
|
|
224
|
+
name: "lookup_ticket",
|
|
225
|
+
description: "Look up a support ticket",
|
|
226
|
+
parameters: {
|
|
227
|
+
type: "object",
|
|
228
|
+
properties: { ticketId: { type: "string" } },
|
|
229
|
+
required: ["ticketId"],
|
|
230
|
+
},
|
|
231
|
+
execute: async ({ ticketId }) => `ticket:${ticketId}`,
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
client: runlayer,
|
|
235
|
+
sessionId: "session-id",
|
|
236
|
+
},
|
|
237
|
+
),
|
|
238
|
+
);
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
The adapter preserves `context` and `details` arguments and reads common
|
|
242
|
+
`toolCall` IDs from `details`.
|
|
243
|
+
|
|
244
|
+
## Google ADK Tools
|
|
245
|
+
|
|
246
|
+
Wrap Google ADK `FunctionTool` options before constructing the tool.
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
import { FunctionTool } from "@google/adk";
|
|
250
|
+
import { withRunlayerGoogleAdkTool, RunlayerClient } from "@runlayer/hooks-sdk/google-adk";
|
|
251
|
+
|
|
252
|
+
const runlayer = RunlayerClient.fromEnv({
|
|
253
|
+
clientVersion: "my-agent/1.0.0",
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
const searchTickets = new FunctionTool(
|
|
257
|
+
withRunlayerGoogleAdkTool(
|
|
258
|
+
{
|
|
259
|
+
name: "search_tickets",
|
|
260
|
+
description: "Search support tickets",
|
|
261
|
+
parameters: {
|
|
262
|
+
type: "object",
|
|
263
|
+
properties: { query: { type: "string" } },
|
|
264
|
+
required: ["query"],
|
|
265
|
+
},
|
|
266
|
+
execute: async ({ query }) => ({ query }),
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
client: runlayer,
|
|
270
|
+
sessionId: "session-id",
|
|
271
|
+
},
|
|
272
|
+
),
|
|
273
|
+
);
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## Direct MCP Source Enforcement
|
|
277
|
+
|
|
278
|
+
When the deployment exposes direct MCP source validation, configure the endpoint
|
|
279
|
+
path and call `enforceMcpSource` before executing a direct MCP tool.
|
|
280
|
+
|
|
281
|
+
```ts
|
|
282
|
+
const runlayer = RunlayerClient.fromEnv({
|
|
283
|
+
directMcpSourceEnforcementPath: "/api/v1/hooks/direct-mcp-source",
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
await runlayer.enforceMcpSource({
|
|
287
|
+
generationId: "generation-id",
|
|
288
|
+
sessionId: "session-id",
|
|
289
|
+
toolName: "mcp__github__list_repos",
|
|
290
|
+
url: "https://tenant.runlayer.com/api/v1/proxy/server-id/mcp",
|
|
291
|
+
});
|
|
292
|
+
```
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { RunlayerClient, type HookEventName, type JsonObject } from "./client.js";
|
|
2
|
+
export type ClaudeAgentSdkHookEvent = HookEventName;
|
|
3
|
+
export type ClaudeAgentSdkHookInput = JsonObject & {
|
|
4
|
+
hook_event_name: string;
|
|
5
|
+
session_id?: string;
|
|
6
|
+
tool_input?: unknown;
|
|
7
|
+
tool_name?: string;
|
|
8
|
+
tool_response?: unknown;
|
|
9
|
+
tool_url?: string;
|
|
10
|
+
tool_use_id?: string;
|
|
11
|
+
};
|
|
12
|
+
export type ClaudeAgentSdkHookJsonOutput = JsonObject & {
|
|
13
|
+
continue?: boolean;
|
|
14
|
+
hookSpecificOutput?: JsonObject;
|
|
15
|
+
reason?: string;
|
|
16
|
+
stopReason?: string;
|
|
17
|
+
systemMessage?: string;
|
|
18
|
+
};
|
|
19
|
+
export type ClaudeAgentSdkHookCallback = (input: ClaudeAgentSdkHookInput, toolUseId?: string, options?: {
|
|
20
|
+
signal?: AbortSignal;
|
|
21
|
+
}) => ClaudeAgentSdkHookJsonOutput | Promise<ClaudeAgentSdkHookJsonOutput>;
|
|
22
|
+
export type ClaudeAgentSdkHookCallbackMatcher = {
|
|
23
|
+
hooks: ClaudeAgentSdkHookCallback[];
|
|
24
|
+
matcher?: string;
|
|
25
|
+
};
|
|
26
|
+
export type ClaudeAgentSdkHooksOptions = {
|
|
27
|
+
includeStop?: boolean;
|
|
28
|
+
};
|
|
29
|
+
export type ClaudeAgentSdkTranscriptStopOptions = {
|
|
30
|
+
extraPayload?: JsonObject;
|
|
31
|
+
model: string;
|
|
32
|
+
sessionId: string;
|
|
33
|
+
source?: string;
|
|
34
|
+
strict?: boolean;
|
|
35
|
+
transcriptLines: readonly string[];
|
|
36
|
+
};
|
|
37
|
+
export declare function createClaudeAgentSdkHooks(client: RunlayerClient, options?: ClaudeAgentSdkHooksOptions): Partial<Record<ClaudeAgentSdkHookEvent, ClaudeAgentSdkHookCallbackMatcher[]>>;
|
|
38
|
+
export declare function claudeAgentSdkAssistantMessageToTranscriptLine(assistantMessage: unknown): string;
|
|
39
|
+
export declare function emitClaudeAgentSdkTranscriptStop(client: RunlayerClient, options: ClaudeAgentSdkTranscriptStopOptions): Promise<void>;
|
|
40
|
+
export declare function toolTypeFromName(toolName: string): string;
|
|
41
|
+
export { RunlayerBlockedError, RunlayerClient, RunlayerHookClient, isRunlayerMcpProxyUrl, mcpServerNameFromToolName, shouldEnforceTool, } from "./client.js";
|
|
42
|
+
export type { JsonObject, RunlayerToolContext, RunlayerToolEnforcementOptions, RunlayerToolEnforcementPredicate, } from "./client.js";
|
|
43
|
+
//# sourceMappingURL=claude-agent-sdk.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-agent-sdk.d.ts","sourceRoot":"","sources":["../src/claude-agent-sdk.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,UAAU,EAChB,MAAM,aAAa,CAAC;AAGrB,MAAM,MAAM,uBAAuB,GAAG,aAAa,CAAC;AAEpD,MAAM,MAAM,uBAAuB,GAAG,UAAU,GAAG;IACjD,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG,UAAU,GAAG;IACtD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,kBAAkB,CAAC,EAAE,UAAU,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG,CACvC,KAAK,EAAE,uBAAuB,EAC9B,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE,KAC/B,4BAA4B,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAAC;AAE1E,MAAM,MAAM,iCAAiC,GAAG;IAC9C,KAAK,EAAE,0BAA0B,EAAE,CAAC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,mCAAmC,GAAG;IAChD,YAAY,CAAC,EAAE,UAAU,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC,CAAC;AAEF,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,cAAc,EACtB,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAAC,MAAM,CAAC,uBAAuB,EAAE,iCAAiC,EAAE,CAAC,CAAC,CAe/E;AAED,wBAAgB,8CAA8C,CAAC,gBAAgB,EAAE,OAAO,GAAG,MAAM,CAEhG;AAED,wBAAsB,gCAAgC,CACpD,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,mCAAmC,GAC3C,OAAO,CAAC,IAAI,CAAC,CAYf;AAwMD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAqBzD;AAED,OAAO,EACL,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,GAClB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,UAAU,EACV,mBAAmB,EACnB,8BAA8B,EAC9B,gCAAgC,GACjC,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { RunlayerBlockedError, } from "./client.js";
|
|
2
|
+
import { stripUndefined } from "./internal.js";
|
|
3
|
+
export function createClaudeAgentSdkHooks(client, options = {}) {
|
|
4
|
+
const hooks = {
|
|
5
|
+
SessionStart: [{ hooks: [createLifecycleHook(client, "SessionStart")] }],
|
|
6
|
+
SessionEnd: [{ hooks: [createLifecycleHook(client, "SessionEnd")] }],
|
|
7
|
+
UserPromptSubmit: [{ hooks: [createLifecycleHook(client, "UserPromptSubmit")] }],
|
|
8
|
+
PreToolUse: [{ hooks: [createPreToolUseHook(client)] }],
|
|
9
|
+
PostToolUse: [{ hooks: [createPostToolUseHook(client)] }],
|
|
10
|
+
PostToolUseFailure: [{ hooks: [createPostToolUseFailureHook(client)] }],
|
|
11
|
+
};
|
|
12
|
+
if (options.includeStop ?? true) {
|
|
13
|
+
hooks.Stop = [{ hooks: [createLifecycleHook(client, "Stop")] }];
|
|
14
|
+
}
|
|
15
|
+
return hooks;
|
|
16
|
+
}
|
|
17
|
+
export function claudeAgentSdkAssistantMessageToTranscriptLine(assistantMessage) {
|
|
18
|
+
return JSON.stringify({ message: assistantMessage });
|
|
19
|
+
}
|
|
20
|
+
export async function emitClaudeAgentSdkTranscriptStop(client, options) {
|
|
21
|
+
await client.emitEvent("Stop", {
|
|
22
|
+
model: options.model,
|
|
23
|
+
session_id: options.sessionId,
|
|
24
|
+
source: options.source ?? "claude-agent-sdk",
|
|
25
|
+
...options.extraPayload,
|
|
26
|
+
}, options.transcriptLines.join("\n"), { strict: options.strict ?? true });
|
|
27
|
+
}
|
|
28
|
+
function createLifecycleHook(client, eventName) {
|
|
29
|
+
return async (input, toolUseId) => {
|
|
30
|
+
await client.emitEvent(eventName, {
|
|
31
|
+
...hookInputPayload(input),
|
|
32
|
+
tool_use_id: toolUseId ?? toolUseIdFromInput(input),
|
|
33
|
+
});
|
|
34
|
+
return {};
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function createPreToolUseHook(client) {
|
|
38
|
+
return async (input, toolUseId) => {
|
|
39
|
+
if (!isPreToolUseInput(input)) {
|
|
40
|
+
return {};
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
const result = await client.beforeTool({
|
|
44
|
+
sessionId: input.session_id,
|
|
45
|
+
toolInput: asJsonObject(input.tool_input),
|
|
46
|
+
toolName: input.tool_name,
|
|
47
|
+
toolType: toolTypeFromName(input.tool_name),
|
|
48
|
+
toolUrl: toolUrlFromInput(input),
|
|
49
|
+
toolUseId: toolUseId ?? input.tool_use_id,
|
|
50
|
+
});
|
|
51
|
+
if (!result.modified) {
|
|
52
|
+
return {};
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
hookSpecificOutput: {
|
|
56
|
+
hookEventName: "PreToolUse",
|
|
57
|
+
permissionDecision: "allow",
|
|
58
|
+
updatedInput: result.toolInput,
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
if (error instanceof RunlayerBlockedError) {
|
|
64
|
+
return {
|
|
65
|
+
reason: error.message,
|
|
66
|
+
hookSpecificOutput: {
|
|
67
|
+
hookEventName: "PreToolUse",
|
|
68
|
+
permissionDecision: "deny",
|
|
69
|
+
permissionDecisionReason: error.message,
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function createPostToolUseHook(client) {
|
|
78
|
+
return async (input, toolUseId) => {
|
|
79
|
+
if (!isPostToolUseInput(input)) {
|
|
80
|
+
return {};
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
await client.afterTool({
|
|
84
|
+
durationMs: durationMsFromHookInput(input),
|
|
85
|
+
sessionId: input.session_id,
|
|
86
|
+
toolInput: asJsonObject(input.tool_input),
|
|
87
|
+
toolName: input.tool_name,
|
|
88
|
+
toolOutput: input.tool_response,
|
|
89
|
+
toolType: toolTypeFromName(input.tool_name),
|
|
90
|
+
toolUrl: toolUrlFromInput(input),
|
|
91
|
+
toolUseId: toolUseId ?? input.tool_use_id,
|
|
92
|
+
});
|
|
93
|
+
return {};
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
if (error instanceof RunlayerBlockedError) {
|
|
97
|
+
return blockedPostToolOutput("PostToolUse", error.message);
|
|
98
|
+
}
|
|
99
|
+
throw error;
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function createPostToolUseFailureHook(client) {
|
|
104
|
+
return async (input, toolUseId) => {
|
|
105
|
+
if (!isPostToolUseFailureInput(input)) {
|
|
106
|
+
return {};
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
await client.afterTool({
|
|
110
|
+
durationMs: durationMsFromHookInput(input),
|
|
111
|
+
errorMessage: input.error,
|
|
112
|
+
isError: true,
|
|
113
|
+
sessionId: input.session_id,
|
|
114
|
+
toolInput: asJsonObject(input.tool_input),
|
|
115
|
+
toolName: input.tool_name,
|
|
116
|
+
toolOutput: input.tool_response ?? input.error,
|
|
117
|
+
toolType: toolTypeFromName(input.tool_name),
|
|
118
|
+
toolUrl: toolUrlFromInput(input),
|
|
119
|
+
toolUseId: toolUseId ?? input.tool_use_id,
|
|
120
|
+
});
|
|
121
|
+
return {};
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
if (error instanceof RunlayerBlockedError) {
|
|
125
|
+
return blockedPostToolOutput("PostToolUseFailure", error.message);
|
|
126
|
+
}
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function blockedPostToolOutput(hookEventName, message) {
|
|
132
|
+
return {
|
|
133
|
+
continue: false,
|
|
134
|
+
stopReason: message,
|
|
135
|
+
systemMessage: message,
|
|
136
|
+
hookSpecificOutput: {
|
|
137
|
+
hookEventName,
|
|
138
|
+
updatedMCPToolOutput: `[Blocked by Runlayer] ${message}`,
|
|
139
|
+
updatedToolOutput: `[Blocked by Runlayer] ${message}`,
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function isPreToolUseInput(input) {
|
|
144
|
+
return hasToolHookShape(input, "PreToolUse");
|
|
145
|
+
}
|
|
146
|
+
function isPostToolUseInput(input) {
|
|
147
|
+
return hasToolHookShape(input, "PostToolUse");
|
|
148
|
+
}
|
|
149
|
+
function isPostToolUseFailureInput(input) {
|
|
150
|
+
return hasToolHookShape(input, "PostToolUseFailure");
|
|
151
|
+
}
|
|
152
|
+
function hasToolHookShape(input, hookEventName) {
|
|
153
|
+
return (input.hook_event_name === hookEventName &&
|
|
154
|
+
typeof input.session_id === "string" &&
|
|
155
|
+
typeof input.tool_name === "string");
|
|
156
|
+
}
|
|
157
|
+
function hookInputPayload(input) {
|
|
158
|
+
const payload = input;
|
|
159
|
+
return stripUndefined(payload);
|
|
160
|
+
}
|
|
161
|
+
function toolUseIdFromInput(input) {
|
|
162
|
+
if ("tool_use_id" in input && typeof input.tool_use_id === "string") {
|
|
163
|
+
return input.tool_use_id;
|
|
164
|
+
}
|
|
165
|
+
return undefined;
|
|
166
|
+
}
|
|
167
|
+
function toolUrlFromInput(input) {
|
|
168
|
+
const candidates = [input.tool_url, input.url, input.mcp_url, input.server_url];
|
|
169
|
+
return candidates.find((candidate) => typeof candidate === "string");
|
|
170
|
+
}
|
|
171
|
+
function asJsonObject(value) {
|
|
172
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
173
|
+
return value;
|
|
174
|
+
}
|
|
175
|
+
return { value };
|
|
176
|
+
}
|
|
177
|
+
function durationMsFromHookInput(input) {
|
|
178
|
+
const candidate = input.duration_ms;
|
|
179
|
+
return typeof candidate === "number" ? candidate : undefined;
|
|
180
|
+
}
|
|
181
|
+
export function toolTypeFromName(toolName) {
|
|
182
|
+
if (toolName.startsWith("mcp__")) {
|
|
183
|
+
return "mcp";
|
|
184
|
+
}
|
|
185
|
+
const lower = toolName.toLowerCase();
|
|
186
|
+
if (lower === "bash" || lower === "shell") {
|
|
187
|
+
return "shell";
|
|
188
|
+
}
|
|
189
|
+
if (lower === "read" || lower === "readfile") {
|
|
190
|
+
return "file_read";
|
|
191
|
+
}
|
|
192
|
+
if (lower === "write" ||
|
|
193
|
+
lower === "edit" ||
|
|
194
|
+
lower === "multiedit" ||
|
|
195
|
+
lower === "writefile" ||
|
|
196
|
+
lower === "editfile") {
|
|
197
|
+
return "file_write";
|
|
198
|
+
}
|
|
199
|
+
return "other";
|
|
200
|
+
}
|
|
201
|
+
export { RunlayerBlockedError, RunlayerClient, RunlayerHookClient, isRunlayerMcpProxyUrl, mcpServerNameFromToolName, shouldEnforceTool, } from "./client.js";
|
|
202
|
+
//# sourceMappingURL=claude-agent-sdk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-agent-sdk.js","sourceRoot":"","sources":["../src/claude-agent-sdk.ts"],"names":[],"mappings":"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"}
|