@knocklabs/agent-toolkit 0.1.9 → 0.1.11

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 CHANGED
@@ -11,6 +11,7 @@
11
11
  - [Model Context Protocol (MCP)](#model-context-protocol-mcp)
12
12
  - [AI SDK](#ai-sdk)
13
13
  - [OpenAI](#openai)
14
+ - [Langchain](#langchain)
14
15
 
15
16
  ## Getting started
16
17
 
@@ -23,6 +24,7 @@ Using the Knock agent toolkit allows you to build powerful agent systems that ar
23
24
  The Knock Agent Toolkit provides three main entry points:
24
25
 
25
26
  - `@knocklabs/agent-toolkit/ai-sdk`: Helpers for integrating with Vercel's AI SDK.
27
+ - `@knocklabs/agent-tookkit/langchain`: Helpers for integrating with [Langchain's JS SDK](https://github.com/langchain-ai/langchainjs).
26
28
  - `@knocklabs/agent-toolkit/openai`: Helpers for integrating with the OpenAI SDK.
27
29
  - `@knocklabs/agent-toolkit/modelcontextprotocol`: Low level helpers for integrating with the Model Context Protocol (MCP).
28
30
 
@@ -66,6 +68,12 @@ npx -y @knocklabs/agent-toolkit -p local-mcp --tools "workflows.*"
66
68
  npx -y @knocklabs/agent-toolkit -p local-mcp --tools "workflows.triggerWorkflow"
67
69
  ```
68
70
 
71
+ If you wish to enable workflows-as-tools within the MCP server, you must set the `--workflows` flag to pass in a list of approved workflow keys to expose. This ensures that you keep the number of tools exposed to your MCP client to a minimum.
72
+
73
+ ```
74
+ npx -y @knocklabs/agent-toolkit -p local-mcp --workflows comment-created activate-account
75
+ ```
76
+
69
77
  It's also possible to pass `environment`, `userId`, and `tenant` to the local MCP server to set default values. Use the `--help` flag to view additional server options.
70
78
 
71
79
  ### AI SDK
@@ -84,7 +92,6 @@ npm install @knocklabs/agent-toolkit
84
92
  import { createKnockToolkit } from "@knocklabs/agent-toolkit/ai-sdk";
85
93
  import { openai } from "@ai-sdk/openai";
86
94
  import { streamText } from "ai";
87
- import { auth } from "@clerk/nextjs/server";
88
95
  import { systemPrompt } from "@/lib/ai/prompts";
89
96
 
90
97
  export const maxDuration = 30;
@@ -132,25 +139,89 @@ import OpenAI from "openai";
132
139
 
133
140
  const openai = new OpenAI();
134
141
 
135
- const toolkit = await createKnockToolkit({
136
- serviceToken: "kst_12345",
137
- permissions: {
138
- // Set the permissions of the tools to expose
139
- workflows: { read: true, run: true, manage: true },
140
- },
141
- });
142
-
143
- const completion = await openai.chat.completions.create({
144
- model: "gpt-4o",
145
- messages,
146
- // The tools given here are determined by the `permissions`
147
- // list above in the configuration. For instance, here we're only
148
- // allowing the workflows
149
- tools: toolkit.getAllTools(),
150
- });
151
-
152
- // Execute the tool calls
153
- const toolMessages = await Promise.all(
154
- message.tool_calls.map((tc) => toolkit.handleToolCall(tc))
155
- );
142
+ async function main() {
143
+ const toolkit = await createKnockToolkit({
144
+ serviceToken: "kst_12345",
145
+ permissions: {
146
+ // Set the permissions of the tools to expose
147
+ workflows: { read: true, run: true, manage: true },
148
+ },
149
+ });
150
+
151
+ const completion = await openai.chat.completions.create({
152
+ model: "gpt-4o",
153
+ messages,
154
+ // The tools given here are determined by the `permissions`
155
+ // list above in the configuration. For instance, here we're only
156
+ // allowing the workflows
157
+ tools: toolkit.getAllTools(),
158
+ });
159
+
160
+ // Execute the tool calls
161
+ const toolMessages = await Promise.all(
162
+ message.tool_calls.map((tc) => toolkit.handleToolCall(tc))
163
+ );
164
+ }
165
+
166
+ main();
167
+ ```
168
+
169
+ ### Langchain
170
+
171
+ The agent toolkit provides a `createKnockToolkit` under the `/langchain` path for easily integrating into the Lanchain JS SDK and returning tools ready for use.
172
+
173
+ 1. Install the package:
174
+
175
+ ```
176
+ npm install @knocklabs/agent-toolkit
177
+ ```
178
+
179
+ 2. Import the `createKnockToolkit` helper, configure it, and use it in your LLM calling:
180
+
181
+ ```typescript
182
+ import { createKnockToolkit } from "@knocklabs/agent-toolkit/langchain";
183
+ import { ChatOpenAI } from "@langchain/openai";
184
+ import { HumanMessage, SystemMessage } from "@langchain/core/messages";
185
+ import { LangChainAdapter } from "ai";
186
+
187
+ const systemPrompt = `You are a helpful assistant.`;
188
+
189
+ export const maxDuration = 30;
190
+
191
+ export async function POST(req: Request) {
192
+ const { prompt } = await req.json();
193
+ // Optional - get the auth context from the request
194
+ const authContext = await auth.protect();
195
+
196
+ // Instantiate a new Knock toolkit
197
+ const toolkit = await createKnockToolkit({
198
+ serviceToken: "kst_12345",
199
+ permissions: {
200
+ // (optional but recommended): Set the permissions of the tools to expose
201
+ workflows: { read: true, run: true, manage: true },
202
+ },
203
+ });
204
+
205
+ const model = new ChatOpenAI({ model: "gpt-4o", temperature: 0 });
206
+
207
+ const modelWithTools = model.bindTools(toolkit.getAllTools());
208
+
209
+ const messages = [new SystemMessage(systemPrompt), new HumanMessage(prompt)];
210
+ const aiMessage = await modelWithTools.invoke(messages);
211
+ messages.push(aiMessage);
212
+
213
+ for (const toolCall of aiMessage.tool_calls || []) {
214
+ // Call the selected tool by its `name`
215
+ const selectedTool = toolkit.getToolMap()[toolCall.name];
216
+ const toolMessage = await selectedTool.invoke(toolCall);
217
+
218
+ messages.push(toolMessage);
219
+ }
220
+
221
+ // To simplify the setup, this example uses the ai-sdk langchain adapter
222
+ // to stream the results back to the /langchain page.
223
+ // For more details, see: https://sdk.vercel.ai/providers/adapters/langchain
224
+ const stream = await modelWithTools.stream(messages);
225
+ return LangChainAdapter.toDataStreamResponse(stream);
226
+ }
156
227
  ```
@@ -1,6 +1,28 @@
1
1
  import { ToolSet, Tool } from 'ai';
2
- import { T as ToolkitConfig, a as ToolCategory } from '../types-BJFe1DAl.js';
2
+ import { a as DeferredToolCall, b as DeferredToolCallConfig, K as KnockOutboundWebhookEvent, D as DeferredToolCallInteractionResult } from '../types-CrTRlRnE.js';
3
+ import { ToolkitConfig, ToolCategory } from '../types.js';
4
+ import { ToolInvocation } from '@ai-sdk/ui-utils';
5
+ import '@knocklabs/node/dist/src/resources/messages/interfaces';
3
6
 
7
+ /**
8
+ * Convert a deferred tool call to a tool invocation. Useful when building an assistant
9
+ * response from a deferred tool call.
10
+ *
11
+ * @param deferredToolCall - The deferred tool call to convert.
12
+ * @param result - The result of the tool call.
13
+ * @returns The tool invocation.
14
+ */
15
+ declare function deferredToolCallToToolInvocation(deferredToolCall: DeferredToolCall, result: unknown): ToolInvocation;
16
+
17
+ type KnockToolkit = {
18
+ getAllTools: () => ToolSet;
19
+ getTools: (category: ToolCategory) => ToolSet;
20
+ getToolMap: () => Record<string, Tool>;
21
+ requireHumanInput: (toolsToWrap: ToolSet, inputConfig: DeferredToolCallConfig) => ToolSet;
22
+ resumeToolExecution: (toolInteraction: DeferredToolCall) => Promise<unknown>;
23
+ wrappedToolsRequiringInput: () => Map<string, Tool>;
24
+ handleMessageInteraction: (event: KnockOutboundWebhookEvent) => DeferredToolCallInteractionResult | null;
25
+ };
4
26
  /**
5
27
  * Creates a Knock toolkit for use with the AI SDK.
6
28
  *
@@ -24,29 +46,6 @@ import { T as ToolkitConfig, a as ToolCategory } from '../types-BJFe1DAl.js';
24
46
  * @param config - The configuration to use for the toolkit
25
47
  * @returns A toolkit for use with the AI SDK
26
48
  */
27
- declare const createKnockToolkit: (config: ToolkitConfig) => Promise<{
28
- /**
29
- * Get all tools for all categories. When the `config.permissions.workflows.run` is set, then workflow triggers for
30
- * the specified workflows will be included in the returned tools.
31
- *
32
- * @returns A promise that resolves to a set of tools
33
- */
34
- getAllTools: () => Promise<ToolSet>;
35
- /**
36
- * Get all tools for a specific category. When trying to get tools for the `workflows` category and the run permission is set,
37
- * the workflow triggers for the specified workflows will be included in the returned tools.
38
- *
39
- * @param category - The category of tools to get
40
- * @returns An array of tools for the given category
41
- */
42
- getTools: (category: ToolCategory) => Promise<ToolSet>;
43
- /**
44
- * Get a map of all tools by method name. When the `config.permissions.workflows.run` is set, then workflow triggers for
45
- * the specified workflows will be included in the returned tools.
46
- *
47
- * @returns A map of all tools by method name
48
- */
49
- getToolMap: () => Promise<Record<string, Tool>>;
50
- }>;
49
+ declare const createKnockToolkit: (config: ToolkitConfig) => Promise<KnockToolkit>;
51
50
 
52
- export { createKnockToolkit };
51
+ export { createKnockToolkit, deferredToolCallToToolInvocation };
@@ -1,10 +1,16 @@
1
+ import {
2
+ handleMessageInteraction,
3
+ triggerHumanInTheLoopWorkflow,
4
+ wrapToolDescription
5
+ } from "../chunk-6O7VMHBN.js";
1
6
  import {
2
7
  createKnockClient
3
8
  } from "../chunk-OMZBTWDH.js";
4
9
  import {
5
10
  getToolMap,
6
11
  getToolsByPermissionsInCategories
7
- } from "../chunk-6UHXLKAV.js";
12
+ } from "../chunk-URQB3FDZ.js";
13
+ import "../chunk-G3PMV62Z.js";
8
14
 
9
15
  // src/ai-sdk/tool-converter.ts
10
16
  import { tool } from "ai";
@@ -26,6 +32,18 @@ var knockToolsToToolSet = (knockClient, config, knockTools) => {
26
32
  );
27
33
  };
28
34
 
35
+ // src/ai-sdk/helpers.ts
36
+ function deferredToolCallToToolInvocation(deferredToolCall, result) {
37
+ return {
38
+ args: deferredToolCall.args,
39
+ toolName: deferredToolCall.method,
40
+ toolCallId: deferredToolCall.extra?.toolCallId,
41
+ state: "result",
42
+ step: 0,
43
+ result
44
+ };
45
+ }
46
+
29
47
  // src/ai-sdk/index.ts
30
48
  var createKnockToolkit = async (config) => {
31
49
  const knockClient = createKnockClient(config);
@@ -35,14 +53,15 @@ var createKnockToolkit = async (config) => {
35
53
  );
36
54
  const allTools = Object.values(allowedToolsByCategory).flat();
37
55
  const toolsByMethod = getToolMap(allTools);
38
- return {
56
+ const wrappedToolsRequiringInput = /* @__PURE__ */ new Map();
57
+ return Promise.resolve({
39
58
  /**
40
59
  * Get all tools for all categories. When the `config.permissions.workflows.run` is set, then workflow triggers for
41
60
  * the specified workflows will be included in the returned tools.
42
61
  *
43
62
  * @returns A promise that resolves to a set of tools
44
63
  */
45
- getAllTools: async () => {
64
+ getAllTools: () => {
46
65
  return knockToolsToToolSet(knockClient, config, allTools);
47
66
  },
48
67
  /**
@@ -52,7 +71,7 @@ var createKnockToolkit = async (config) => {
52
71
  * @param category - The category of tools to get
53
72
  * @returns An array of tools for the given category
54
73
  */
55
- getTools: async (category) => {
74
+ getTools: (category) => {
56
75
  return knockToolsToToolSet(
57
76
  knockClient,
58
77
  config,
@@ -65,7 +84,7 @@ var createKnockToolkit = async (config) => {
65
84
  *
66
85
  * @returns A map of all tools by method name
67
86
  */
68
- getToolMap: async () => {
87
+ getToolMap: () => {
69
88
  return Object.entries(toolsByMethod).reduce(
70
89
  (acc, [method, tool2]) => ({
71
90
  ...acc,
@@ -73,10 +92,89 @@ var createKnockToolkit = async (config) => {
73
92
  }),
74
93
  {}
75
94
  );
76
- }
77
- };
95
+ },
96
+ /**
97
+ * Wraps one or more tools to require human input.
98
+ *
99
+ * @param toolsToWrap - The tools to wrap
100
+ * @param inputConfig - The configuration to use for the HITL request
101
+ */
102
+ requireHumanInput: (toolsToWrap, inputConfig) => {
103
+ const wrappedTools = {};
104
+ for (const [method, toolToWrap] of Object.entries(toolsToWrap)) {
105
+ wrappedToolsRequiringInput.set(method, { ...toolToWrap });
106
+ const wrappedTool = {
107
+ ...toolToWrap,
108
+ description: wrapToolDescription(toolToWrap.description ?? ""),
109
+ execute: async (input, options) => {
110
+ const toolExecution = {
111
+ method,
112
+ args: input,
113
+ extra: {
114
+ toolCallId: options.toolCallId
115
+ }
116
+ };
117
+ await triggerHumanInTheLoopWorkflow({
118
+ knockClient,
119
+ config,
120
+ toolCall: toolExecution,
121
+ inputConfig
122
+ });
123
+ return {
124
+ type: "tool-status",
125
+ status: "pending-input",
126
+ toolCallId: options.toolCallId
127
+ };
128
+ }
129
+ };
130
+ wrappedTools[method] = wrappedTool;
131
+ }
132
+ return wrappedTools;
133
+ },
134
+ /**
135
+ * Returns any tools that were wrapped with `requireHumanInput`.
136
+ *
137
+ * @returns A map of wrapped tools that require human input
138
+ */
139
+ wrappedToolsRequiringInput: () => wrappedToolsRequiringInput,
140
+ /**
141
+ * Resumes the execution of a tool that required human input.
142
+ *
143
+ * @param toolInteraction - The tool interaction to resume
144
+ * @returns A promise that resolves to the result of the tool execution
145
+ */
146
+ resumeToolExecution: async (toolInteraction) => {
147
+ const tool2 = wrappedToolsRequiringInput.get(toolInteraction.method);
148
+ if (!tool2) {
149
+ throw new Error(
150
+ `Tool "${toolInteraction.method}" not found. Did you forget to wrap the tool with requireHumanInput?`
151
+ );
152
+ }
153
+ if (!tool2.execute) {
154
+ throw new Error(
155
+ `Tool "${toolInteraction.method}" does not have an execute method. Nothing to resume.`
156
+ );
157
+ }
158
+ const options = toolInteraction.extra;
159
+ const result = await tool2.execute(toolInteraction.args, options);
160
+ return {
161
+ type: "tool-status",
162
+ status: "completed",
163
+ toolCallId: options.toolCallId,
164
+ result
165
+ };
166
+ },
167
+ /**
168
+ * Handles a message interaction event by parsing it into a well-known format.
169
+ *
170
+ * @param event - The message interaction event
171
+ * @returns An deferred tool call, or null if the event is not a message interaction
172
+ */
173
+ handleMessageInteraction
174
+ });
78
175
  };
79
176
  export {
80
- createKnockToolkit
177
+ createKnockToolkit,
178
+ deferredToolCallToToolInvocation
81
179
  };
82
180
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/ai-sdk/tool-converter.ts","../../src/ai-sdk/index.ts"],"sourcesContent":["import type { Tool } from \"ai\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\n\nimport { KnockClient } from \"../lib/knock-client.js\";\nimport { KnockTool } from \"../lib/knock-tool.js\";\nimport { Config } from \"../types.js\";\n\n/**\n * Convert a KnockTool to an AI Tool, ready to pass to the AI SDK.\n */\nconst knockToolToAiTool = (\n knockClient: KnockClient,\n config: Config,\n knockTool: KnockTool\n): Tool => {\n return tool({\n description: knockTool.description,\n parameters: knockTool.parameters ?? z.object({}),\n execute: knockTool.bindExecute(knockClient, config),\n });\n};\n\n/**\n * Convert a list of KnockTools to an AI ToolSet, ready to pass to the AI SDK.\n */\nconst knockToolsToToolSet = (\n knockClient: KnockClient,\n config: Config,\n knockTools: KnockTool[]\n) => {\n return knockTools.reduce(\n (acc, tool) => {\n acc[tool.method] = knockToolToAiTool(knockClient, config, tool);\n return acc;\n },\n {} as Record<string, Tool>\n );\n};\n\nexport { knockToolToAiTool, knockToolsToToolSet };\n","import { Tool, ToolSet } from \"ai\";\n\nimport { createKnockClient } from \"../lib/knock-client.js\";\nimport { getToolMap, getToolsByPermissionsInCategories } from \"../lib/utils.js\";\nimport { ToolCategory, ToolkitConfig } from \"../types.js\";\n\nimport { knockToolsToToolSet, knockToolToAiTool } from \"./tool-converter.js\";\n\n/**\n * Creates a Knock toolkit for use with the AI SDK.\n *\n * You can filter the set of tools that are available by setting the `config.permissions` property.\n *\n * When the `config.permissions.workflows.run` is set, then workflow triggers for\n * the specified workflows will be included in the returned tools.\n *\n * You can also specify a list of workflow keys to include in the returned tools, should you wish to\n * limit the set of workflows that are available.\n *\n * @example\n * ```ts\n * const toolkit = await createKnockToolkit({\n * permissions: {\n * workflows: { read: true },\n * },\n * });\n * ```\n *\n * @param config - The configuration to use for the toolkit\n * @returns A toolkit for use with the AI SDK\n */\nconst createKnockToolkit = async (config: ToolkitConfig) => {\n const knockClient = createKnockClient(config);\n const allowedToolsByCategory = await getToolsByPermissionsInCategories(\n knockClient,\n config\n );\n const allTools = Object.values(allowedToolsByCategory).flat();\n const toolsByMethod = getToolMap(allTools);\n\n return {\n /**\n * Get all tools for all categories. When the `config.permissions.workflows.run` is set, then workflow triggers for\n * the specified workflows will be included in the returned tools.\n *\n * @returns A promise that resolves to a set of tools\n */\n getAllTools: async (): Promise<ToolSet> => {\n return knockToolsToToolSet(knockClient, config, allTools);\n },\n\n /**\n * Get all tools for a specific category. When trying to get tools for the `workflows` category and the run permission is set,\n * the workflow triggers for the specified workflows will be included in the returned tools.\n *\n * @param category - The category of tools to get\n * @returns An array of tools for the given category\n */\n getTools: async (category: ToolCategory): Promise<ToolSet> => {\n return knockToolsToToolSet(\n knockClient,\n config,\n allowedToolsByCategory[category]\n );\n },\n\n /**\n * Get a map of all tools by method name. When the `config.permissions.workflows.run` is set, then workflow triggers for\n * the specified workflows will be included in the returned tools.\n *\n * @returns A map of all tools by method name\n */\n getToolMap: async (): Promise<Record<string, Tool>> => {\n return Object.entries(toolsByMethod).reduce(\n (acc, [method, tool]) => ({\n ...acc,\n [method]: knockToolToAiTool(knockClient, config, tool),\n }),\n {} as Record<string, Tool>\n );\n },\n };\n};\n\nexport { createKnockToolkit };\n"],"mappings":";;;;;;;;;AACA,SAAS,YAAY;AACrB,SAAS,SAAS;AASlB,IAAM,oBAAoB,CACxB,aACA,QACA,cACS;AACT,SAAO,KAAK;AAAA,IACV,aAAa,UAAU;AAAA,IACvB,YAAY,UAAU,cAAc,EAAE,OAAO,CAAC,CAAC;AAAA,IAC/C,SAAS,UAAU,YAAY,aAAa,MAAM;AAAA,EACpD,CAAC;AACH;AAKA,IAAM,sBAAsB,CAC1B,aACA,QACA,eACG;AACH,SAAO,WAAW;AAAA,IAChB,CAAC,KAAKA,UAAS;AACb,UAAIA,MAAK,MAAM,IAAI,kBAAkB,aAAa,QAAQA,KAAI;AAC9D,aAAO;AAAA,IACT;AAAA,IACA,CAAC;AAAA,EACH;AACF;;;ACPA,IAAM,qBAAqB,OAAO,WAA0B;AAC1D,QAAM,cAAc,kBAAkB,MAAM;AAC5C,QAAM,yBAAyB,MAAM;AAAA,IACnC;AAAA,IACA;AAAA,EACF;AACA,QAAM,WAAW,OAAO,OAAO,sBAAsB,EAAE,KAAK;AAC5D,QAAM,gBAAgB,WAAW,QAAQ;AAEzC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOL,aAAa,YAA8B;AACzC,aAAO,oBAAoB,aAAa,QAAQ,QAAQ;AAAA,IAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASA,UAAU,OAAO,aAA6C;AAC5D,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA,uBAAuB,QAAQ;AAAA,MACjC;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQA,YAAY,YAA2C;AACrD,aAAO,OAAO,QAAQ,aAAa,EAAE;AAAA,QACnC,CAAC,KAAK,CAAC,QAAQC,KAAI,OAAO;AAAA,UACxB,GAAG;AAAA,UACH,CAAC,MAAM,GAAG,kBAAkB,aAAa,QAAQA,KAAI;AAAA,QACvD;AAAA,QACA,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;","names":["tool","tool"]}
1
+ {"version":3,"sources":["../../src/ai-sdk/tool-converter.ts","../../src/ai-sdk/helpers.ts","../../src/ai-sdk/index.ts"],"sourcesContent":["import type { Tool } from \"ai\";\nimport { tool } from \"ai\";\nimport { z } from \"zod\";\n\nimport { KnockClient } from \"../lib/knock-client.js\";\nimport { KnockTool } from \"../lib/knock-tool.js\";\nimport { Config } from \"../types.js\";\n\n/**\n * Convert a KnockTool to an AI Tool, ready to pass to the AI SDK.\n */\nconst knockToolToAiTool = (\n knockClient: KnockClient,\n config: Config,\n knockTool: KnockTool\n): Tool => {\n return tool({\n description: knockTool.description,\n parameters: knockTool.parameters ?? z.object({}),\n execute: knockTool.bindExecute(knockClient, config),\n });\n};\n\n/**\n * Convert a list of KnockTools to an AI ToolSet, ready to pass to the AI SDK.\n */\nconst knockToolsToToolSet = (\n knockClient: KnockClient,\n config: Config,\n knockTools: KnockTool[]\n) => {\n return knockTools.reduce(\n (acc, tool) => {\n acc[tool.method] = knockToolToAiTool(knockClient, config, tool);\n return acc;\n },\n {} as Record<string, Tool>\n );\n};\n\nexport { knockToolToAiTool, knockToolsToToolSet };\n","import { ToolInvocation } from \"@ai-sdk/ui-utils\";\n\nimport { DeferredToolCall } from \"@/lib/human-in-the-loop/types\";\n\n/**\n * Convert a deferred tool call to a tool invocation. Useful when building an assistant\n * response from a deferred tool call.\n *\n * @param deferredToolCall - The deferred tool call to convert.\n * @param result - The result of the tool call.\n * @returns The tool invocation.\n */\nfunction deferredToolCallToToolInvocation(\n deferredToolCall: DeferredToolCall,\n result: unknown\n): ToolInvocation {\n return {\n args: deferredToolCall.args,\n toolName: deferredToolCall.method,\n toolCallId: deferredToolCall.extra?.toolCallId as string,\n state: \"result\",\n step: 0,\n result,\n };\n}\n\nexport { deferredToolCallToToolInvocation };\n","import { Tool, ToolExecutionOptions, ToolSet } from \"ai\";\n\nimport {\n handleMessageInteraction,\n triggerHumanInTheLoopWorkflow,\n wrapToolDescription,\n} from \"../lib/human-in-the-loop/index.js\";\nimport {\n DeferredToolCall,\n DeferredToolCallConfig,\n KnockOutboundWebhookEvent,\n DeferredToolCallInteractionResult,\n} from \"../lib/human-in-the-loop/types.js\";\nimport { createKnockClient } from \"../lib/knock-client.js\";\nimport { getToolMap, getToolsByPermissionsInCategories } from \"../lib/utils.js\";\nimport { ToolCategory, ToolkitConfig } from \"../types.js\";\n\nimport { knockToolsToToolSet, knockToolToAiTool } from \"./tool-converter.js\";\n\ntype KnockToolkit = {\n getAllTools: () => ToolSet;\n getTools: (category: ToolCategory) => ToolSet;\n getToolMap: () => Record<string, Tool>;\n requireHumanInput: (\n toolsToWrap: ToolSet,\n inputConfig: DeferredToolCallConfig\n ) => ToolSet;\n resumeToolExecution: (toolInteraction: DeferredToolCall) => Promise<unknown>;\n wrappedToolsRequiringInput: () => Map<string, Tool>;\n handleMessageInteraction: (\n event: KnockOutboundWebhookEvent\n ) => DeferredToolCallInteractionResult | null;\n};\n\n/**\n * Creates a Knock toolkit for use with the AI SDK.\n *\n * You can filter the set of tools that are available by setting the `config.permissions` property.\n *\n * When the `config.permissions.workflows.run` is set, then workflow triggers for\n * the specified workflows will be included in the returned tools.\n *\n * You can also specify a list of workflow keys to include in the returned tools, should you wish to\n * limit the set of workflows that are available.\n *\n * @example\n * ```ts\n * const toolkit = await createKnockToolkit({\n * permissions: {\n * workflows: { read: true },\n * },\n * });\n * ```\n *\n * @param config - The configuration to use for the toolkit\n * @returns A toolkit for use with the AI SDK\n */\nconst createKnockToolkit = async (\n config: ToolkitConfig\n): Promise<KnockToolkit> => {\n const knockClient = createKnockClient(config);\n const allowedToolsByCategory = await getToolsByPermissionsInCategories(\n knockClient,\n config\n );\n const allTools = Object.values(allowedToolsByCategory).flat();\n const toolsByMethod = getToolMap(allTools);\n\n const wrappedToolsRequiringInput = new Map<string, Tool>();\n\n return Promise.resolve({\n /**\n * Get all tools for all categories. When the `config.permissions.workflows.run` is set, then workflow triggers for\n * the specified workflows will be included in the returned tools.\n *\n * @returns A promise that resolves to a set of tools\n */\n getAllTools: (): ToolSet => {\n return knockToolsToToolSet(knockClient, config, allTools);\n },\n\n /**\n * Get all tools for a specific category. When trying to get tools for the `workflows` category and the run permission is set,\n * the workflow triggers for the specified workflows will be included in the returned tools.\n *\n * @param category - The category of tools to get\n * @returns An array of tools for the given category\n */\n getTools: (category: ToolCategory): ToolSet => {\n return knockToolsToToolSet(\n knockClient,\n config,\n allowedToolsByCategory[category]\n );\n },\n\n /**\n * Get a map of all tools by method name. When the `config.permissions.workflows.run` is set, then workflow triggers for\n * the specified workflows will be included in the returned tools.\n *\n * @returns A map of all tools by method name\n */\n getToolMap: (): Record<string, Tool> => {\n return Object.entries(toolsByMethod).reduce(\n (acc, [method, tool]) => ({\n ...acc,\n [method]: knockToolToAiTool(knockClient, config, tool),\n }),\n {} as Record<string, Tool>\n );\n },\n\n /**\n * Wraps one or more tools to require human input.\n *\n * @param toolsToWrap - The tools to wrap\n * @param inputConfig - The configuration to use for the HITL request\n */\n requireHumanInput: (\n toolsToWrap: ToolSet,\n inputConfig: DeferredToolCallConfig\n ): ToolSet => {\n const wrappedTools: Record<string, Tool> = {};\n\n for (const [method, toolToWrap] of Object.entries(toolsToWrap)) {\n // Keep a reference to the original tool so we can use it later\n wrappedToolsRequiringInput.set(method, { ...toolToWrap });\n\n const wrappedTool = {\n ...toolToWrap,\n description: wrapToolDescription(toolToWrap.description ?? \"\"),\n execute: async (input: any, options: ToolExecutionOptions) => {\n const toolExecution = {\n method,\n args: input,\n extra: {\n toolCallId: options.toolCallId,\n },\n };\n\n await triggerHumanInTheLoopWorkflow({\n knockClient,\n config,\n toolCall: toolExecution,\n inputConfig,\n });\n\n // TODO: Consider injecting a hook here to allow the AI SDK to react to the tool call being deferred\n return {\n type: \"tool-status\",\n status: \"pending-input\",\n toolCallId: options.toolCallId,\n };\n },\n };\n\n wrappedTools[method] = wrappedTool;\n }\n\n return wrappedTools;\n },\n\n /**\n * Returns any tools that were wrapped with `requireHumanInput`.\n *\n * @returns A map of wrapped tools that require human input\n */\n wrappedToolsRequiringInput: () => wrappedToolsRequiringInput,\n\n /**\n * Resumes the execution of a tool that required human input.\n *\n * @param toolInteraction - The tool interaction to resume\n * @returns A promise that resolves to the result of the tool execution\n */\n resumeToolExecution: async (toolInteraction: DeferredToolCall) => {\n const tool = wrappedToolsRequiringInput.get(toolInteraction.method);\n\n if (!tool) {\n throw new Error(\n `Tool \"${toolInteraction.method}\" not found. Did you forget to wrap the tool with requireHumanInput?`\n );\n }\n\n if (!tool.execute) {\n throw new Error(\n `Tool \"${toolInteraction.method}\" does not have an execute method. Nothing to resume.`\n );\n }\n\n const options = toolInteraction.extra as unknown as ToolExecutionOptions;\n const result = await tool.execute(toolInteraction.args, options);\n\n // Return two message objects to represent the tool call and the call result having\n // finished. Note: this can result in duplicate tool call IDs being present in the message history.\n return {\n type: \"tool-status\",\n status: \"completed\",\n toolCallId: options.toolCallId,\n result,\n };\n },\n\n /**\n * Handles a message interaction event by parsing it into a well-known format.\n *\n * @param event - The message interaction event\n * @returns An deferred tool call, or null if the event is not a message interaction\n */\n handleMessageInteraction,\n });\n};\n\nexport * from \"./helpers.js\";\nexport { createKnockToolkit };\n"],"mappings":"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","names":["tool","tool"]}
@@ -0,0 +1,57 @@
1
+ // src/lib/human-in-the-loop/index.ts
2
+ function wrapToolDescription(description) {
3
+ return `${description}
4
+
5
+ This tool call is deferred. You will NOT receive a result from this tool but this is NOT an error. Do NOT retry the tool call as the result will be the same. The tool call result will be provided to you in the future.`;
6
+ }
7
+ async function triggerHumanInTheLoopWorkflow({
8
+ knockClient,
9
+ config,
10
+ toolCall,
11
+ inputConfig
12
+ }) {
13
+ const knock = await knockClient.publicApi(config.environment);
14
+ const result = await knock.workflows.trigger(inputConfig.workflow, {
15
+ data: {
16
+ type: "deferred_tool_call",
17
+ tool_call: toolCall,
18
+ metadata: inputConfig.metadata
19
+ },
20
+ recipients: inputConfig.recipients,
21
+ tenant: inputConfig.tenant,
22
+ actor: inputConfig.actor
23
+ });
24
+ return result;
25
+ }
26
+ function handleMessageInteraction(event) {
27
+ const { data: message } = event;
28
+ if (event.type !== "message.interacted") {
29
+ return null;
30
+ }
31
+ if (message.data.type !== "deferred_tool_call" || !message.data.tool_call) {
32
+ return null;
33
+ }
34
+ const messageData = message.data;
35
+ return {
36
+ workflow: message.source.key,
37
+ interaction: event.event_data,
38
+ toolCall: {
39
+ method: messageData.tool_call.method,
40
+ args: messageData.tool_call.args,
41
+ extra: messageData.tool_call.extra
42
+ },
43
+ metadata: messageData.metadata,
44
+ context: {
45
+ messageId: message.id,
46
+ channelId: message.channel_id,
47
+ timestamp: event.created_at
48
+ }
49
+ };
50
+ }
51
+
52
+ export {
53
+ wrapToolDescription,
54
+ triggerHumanInTheLoopWorkflow,
55
+ handleMessageInteraction
56
+ };
57
+ //# sourceMappingURL=chunk-6O7VMHBN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/human-in-the-loop/index.ts"],"sourcesContent":["import { Config } from \"@/types\";\n\nimport { KnockClient } from \"../knock-client\";\n\nimport {\n DeferredToolCallWorkflowData,\n DeferredToolCallConfig,\n KnockOutboundWebhookEvent,\n DeferredToolCall,\n DeferredToolCallInteractionResult,\n} from \"./types\";\n\nfunction wrapToolDescription(description: string) {\n return `${description}\\n\\nThis tool call is deferred. You will NOT receive a result from this tool but this is NOT an error. Do NOT retry the tool call as the result will be the same. The tool call result will be provided to you in the future.`;\n}\n\n/**\n * Triggers a human in the loop workflow.\n *\n * @param knockClient - The Knock client to use.\n * @param toolCall - The tool call to trigger.\n * @param config - The configuration to use.\n */\nasync function triggerHumanInTheLoopWorkflow({\n knockClient,\n config,\n toolCall,\n inputConfig,\n}: {\n knockClient: KnockClient;\n config: Config;\n toolCall: DeferredToolCall;\n inputConfig: DeferredToolCallConfig;\n}) {\n const knock = await knockClient.publicApi(config.environment);\n\n const result = await knock.workflows.trigger(inputConfig.workflow, {\n data: {\n type: \"deferred_tool_call\",\n tool_call: toolCall,\n metadata: inputConfig.metadata,\n } as DeferredToolCallWorkflowData,\n recipients: inputConfig.recipients,\n tenant: inputConfig.tenant,\n actor: inputConfig.actor,\n });\n\n return result;\n}\n\n/**\n * Given an outboundwebhook event, this function will parse the event into a normalized format.\n *\n * If the event is not associated with a deferred tool call, this function will return null.\n *\n * @param event - The outbound webhook event\n * @returns A deferred tool call interaction result, or null if the event is not a deferred tool call\n */\nfunction handleMessageInteraction(\n event: KnockOutboundWebhookEvent\n): DeferredToolCallInteractionResult | null {\n const { data: message } = event;\n\n // We only care about message.interacted events\n if (event.type !== \"message.interacted\") {\n return null;\n }\n\n // We only care about messages that contain a tool call\n if (message.data.type !== \"deferred_tool_call\" || !message.data.tool_call) {\n return null;\n }\n\n const messageData = message.data as DeferredToolCallWorkflowData;\n\n return {\n workflow: message.source.key,\n interaction: event.event_data,\n toolCall: {\n method: messageData.tool_call.method,\n args: messageData.tool_call.args,\n extra: messageData.tool_call.extra,\n },\n metadata: messageData.metadata,\n context: {\n messageId: message.id,\n channelId: message.channel_id,\n timestamp: event.created_at,\n },\n };\n}\n\nexport {\n handleMessageInteraction,\n triggerHumanInTheLoopWorkflow,\n wrapToolDescription,\n};\n"],"mappings":";AAYA,SAAS,oBAAoB,aAAqB;AAChD,SAAO,GAAG,WAAW;AAAA;AAAA;AACvB;AASA,eAAe,8BAA8B;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,QAAM,QAAQ,MAAM,YAAY,UAAU,OAAO,WAAW;AAE5D,QAAM,SAAS,MAAM,MAAM,UAAU,QAAQ,YAAY,UAAU;AAAA,IACjE,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU,YAAY;AAAA,IACxB;AAAA,IACA,YAAY,YAAY;AAAA,IACxB,QAAQ,YAAY;AAAA,IACpB,OAAO,YAAY;AAAA,EACrB,CAAC;AAED,SAAO;AACT;AAUA,SAAS,yBACP,OAC0C;AAC1C,QAAM,EAAE,MAAM,QAAQ,IAAI;AAG1B,MAAI,MAAM,SAAS,sBAAsB;AACvC,WAAO;AAAA,EACT;AAGA,MAAI,QAAQ,KAAK,SAAS,wBAAwB,CAAC,QAAQ,KAAK,WAAW;AACzE,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,QAAQ;AAE5B,SAAO;AAAA,IACL,UAAU,QAAQ,OAAO;AAAA,IACzB,aAAa,MAAM;AAAA,IACnB,UAAU;AAAA,MACR,QAAQ,YAAY,UAAU;AAAA,MAC9B,MAAM,YAAY,UAAU;AAAA,MAC5B,OAAO,YAAY,UAAU;AAAA,IAC/B;AAAA,IACA,UAAU,YAAY;AAAA,IACtB,SAAS;AAAA,MACP,WAAW,QAAQ;AAAA,MACnB,WAAW,QAAQ;AAAA,MACnB,WAAW,MAAM;AAAA,IACnB;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,36 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __commonJS = (cb, mod) => function __require() {
8
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
+ };
10
+ var __export = (target, all) => {
11
+ for (var name in all)
12
+ __defProp(target, name, { get: all[name], enumerable: true });
13
+ };
14
+ var __copyProps = (to, from, except, desc) => {
15
+ if (from && typeof from === "object" || typeof from === "function") {
16
+ for (let key of __getOwnPropNames(from))
17
+ if (!__hasOwnProp.call(to, key) && key !== except)
18
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
23
+ // If the importer is in node compatibility mode or this is not an ESM
24
+ // file that has been converted to a CommonJS file using a Babel-
25
+ // compatible transform (i.e. "__esModule" has not been set), then set
26
+ // "default" to the CommonJS "module.exports" for node compatibility.
27
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
28
+ mod
29
+ ));
30
+
31
+ export {
32
+ __commonJS,
33
+ __export,
34
+ __toESM
35
+ };
36
+ //# sourceMappingURL=chunk-G3PMV62Z.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  allTools,
3
3
  createWorkflowTools
4
- } from "./chunk-6UHXLKAV.js";
4
+ } from "./chunk-URQB3FDZ.js";
5
5
 
6
6
  // src/modelcontextprotocol/adapter.ts
7
7
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
8
8
  import { z } from "zod";
9
9
  var KnockMcpServer = class extends McpServer {
10
10
  constructor(knockClient, config, tools) {
11
- super({ name: "Knock", version: "0.1.9" });
11
+ super({ name: "Knock", version: "0.1.11" });
12
12
  tools.forEach((tool) => {
13
13
  const toolParams = tool.parameters ?? z.object({});
14
14
  this.tool(
@@ -28,10 +28,14 @@ var KnockMcpServer = class extends McpServer {
28
28
 
29
29
  // src/modelcontextprotocol/index.ts
30
30
  var createKnockMcpServer = async (params) => {
31
- const { tools, knockClient, config } = params;
31
+ const { tools, knockClient, config, workflows } = params;
32
32
  let baseTools = tools || Object.values(allTools);
33
- if (baseTools.some((tool) => tool.method === "list_workflows")) {
34
- const workflowTools = await createWorkflowTools(knockClient, config);
33
+ if (workflows && Array.isArray(workflows) && workflows.length > 0) {
34
+ const workflowTools = await createWorkflowTools(
35
+ knockClient,
36
+ config,
37
+ workflows
38
+ );
35
39
  baseTools = [...baseTools, ...workflowTools];
36
40
  }
37
41
  return Promise.resolve(new KnockMcpServer(knockClient, config, baseTools));
@@ -40,4 +44,4 @@ var createKnockMcpServer = async (params) => {
40
44
  export {
41
45
  createKnockMcpServer
42
46
  };
43
- //# sourceMappingURL=chunk-VGU7NXYJ.js.map
47
+ //# sourceMappingURL=chunk-H3YEJMMF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/modelcontextprotocol/adapter.ts","../src/modelcontextprotocol/index.ts"],"sourcesContent":["import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n\nimport { KnockClient } from \"../lib/knock-client.js\";\nimport type { KnockTool } from \"../lib/knock-tool.js\";\nimport { Config } from \"../types.js\";\n\nexport class KnockMcpServer extends McpServer {\n constructor(knockClient: KnockClient, config: Config, tools: KnockTool[]) {\n super({ name: \"Knock\", version: PACKAGE_VERSION });\n\n tools.forEach((tool) => {\n const toolParams = tool.parameters ?? z.object({});\n\n this.tool(\n tool.method,\n tool.description,\n toolParams.shape,\n async (arg: unknown) => {\n const res = await tool.bindExecute(knockClient, config)(arg);\n\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(res) }],\n };\n }\n );\n });\n }\n}\n","import { KnockClient } from \"../lib/knock-client.js\";\nimport type { KnockTool } from \"../lib/knock-tool.js\";\nimport { allTools } from \"../lib/tools/index.js\";\nimport { createWorkflowTools } from \"../lib/tools/workflows-as-tools.js\";\nimport { Config } from \"../types.js\";\n\nimport { KnockMcpServer } from \"./adapter.js\";\n\ntype CreateKnockMcpServerParams = {\n /**\n * Array of Knock tools to enable in the server.\n */\n tools?: KnockTool[];\n\n /**\n * A Knock client to use for the server.\n */\n knockClient: KnockClient;\n\n /**\n * The config to use for the server.\n */\n config: Config;\n\n /**\n * The workflows to enable as tools in the MCP server.\n */\n workflows?: string[];\n};\n\n/**\n * Creates a Knock MCP Server with the given parameters.\n */\nexport const createKnockMcpServer = async (\n params: CreateKnockMcpServerParams\n): Promise<KnockMcpServer> => {\n const { tools, knockClient, config, workflows } = params;\n\n let baseTools = tools || Object.values(allTools);\n\n if (workflows && Array.isArray(workflows) && workflows.length > 0) {\n const workflowTools = await createWorkflowTools(\n knockClient,\n config,\n workflows\n );\n\n baseTools = [...baseTools, ...workflowTools];\n }\n\n return Promise.resolve(new KnockMcpServer(knockClient, config, baseTools));\n};\n"],"mappings":";;;;;;AAAA,SAAS,iBAAiB;AAC1B,SAAS,SAAS;AAMX,IAAM,iBAAN,cAA6B,UAAU;AAAA,EAC5C,YAAY,aAA0B,QAAgB,OAAoB;AACxE,UAAM,EAAE,MAAM,SAAS,SAAS,SAAgB,CAAC;AAEjD,UAAM,QAAQ,CAAC,SAAS;AACtB,YAAM,aAAa,KAAK,cAAc,EAAE,OAAO,CAAC,CAAC;AAEjD,WAAK;AAAA,QACH,KAAK;AAAA,QACL,KAAK;AAAA,QACL,WAAW;AAAA,QACX,OAAO,QAAiB;AACtB,gBAAM,MAAM,MAAM,KAAK,YAAY,aAAa,MAAM,EAAE,GAAG;AAE3D,iBAAO;AAAA,YACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,GAAG,EAAE,CAAC;AAAA,UAChE;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACKO,IAAM,uBAAuB,OAClC,WAC4B;AAC5B,QAAM,EAAE,OAAO,aAAa,QAAQ,UAAU,IAAI;AAElD,MAAI,YAAY,SAAS,OAAO,OAAO,QAAQ;AAE/C,MAAI,aAAa,MAAM,QAAQ,SAAS,KAAK,UAAU,SAAS,GAAG;AACjE,UAAM,gBAAgB,MAAM;AAAA,MAC1B;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,gBAAY,CAAC,GAAG,WAAW,GAAG,aAAa;AAAA,EAC7C;AAEA,SAAO,QAAQ,QAAQ,IAAI,eAAe,aAAa,QAAQ,SAAS,CAAC;AAC3E;","names":[]}