@rnsk/toolkits 0.0.2 → 0.0.3

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.
Files changed (72) hide show
  1. package/README.md +104 -0
  2. package/dist/core/index.d.ts +1 -0
  3. package/dist/core/index.js +1 -0
  4. package/dist/core/schema-helpers.d.ts +20 -0
  5. package/dist/core/schema-helpers.js +157 -0
  6. package/dist/index.d.ts +0 -1
  7. package/dist/index.js +0 -1
  8. package/dist/toolkits/github/tools/Actions/list-workflow-jobs.d.ts +1 -1
  9. package/dist/toolkits/github/tools/Activity/list-notifications.d.ts +1 -1
  10. package/dist/toolkits/github/tools/Issues/add-issue-labels.d.ts +1 -1
  11. package/dist/toolkits/github/tools/Issues/list-authenticated-user-issues.d.ts +1 -1
  12. package/dist/toolkits/github/tools/Issues/list-org-issues.d.ts +1 -1
  13. package/dist/toolkits/github/tools/Issues/list-user-account-issues.d.ts +1 -1
  14. package/dist/toolkits/github/tools/Organizations/list-org-repositories.d.ts +1 -1
  15. package/dist/toolkits/github/tools/Webhooks/create-repo-webhook.d.ts +1 -1
  16. package/dist/toolkits/gmail/icon.js +14 -14
  17. package/dist/toolkits/gmail/manifest.js +78 -5
  18. package/dist/toolkits/gmail/tools/create-draft.d.ts +34 -0
  19. package/dist/toolkits/gmail/tools/create-draft.js +60 -0
  20. package/dist/toolkits/gmail/tools/delete-draft.d.ts +23 -0
  21. package/dist/toolkits/gmail/tools/delete-draft.js +34 -0
  22. package/dist/toolkits/gmail/tools/get-draft.d.ts +32 -0
  23. package/dist/toolkits/gmail/tools/get-draft.js +36 -0
  24. package/dist/toolkits/gmail/tools/get-message.d.ts +12 -12
  25. package/dist/toolkits/gmail/tools/get-message.js +3 -24
  26. package/dist/toolkits/gmail/tools/get-thread.d.ts +29 -0
  27. package/dist/toolkits/gmail/tools/get-thread.js +39 -0
  28. package/dist/toolkits/gmail/tools/index.d.ts +17 -0
  29. package/dist/toolkits/gmail/tools/index.js +17 -0
  30. package/dist/toolkits/gmail/tools/list-drafts.d.ts +28 -0
  31. package/dist/toolkits/gmail/tools/list-drafts.js +43 -0
  32. package/dist/toolkits/gmail/tools/list-labels.d.ts +20 -0
  33. package/dist/toolkits/gmail/tools/list-labels.js +46 -0
  34. package/dist/toolkits/gmail/tools/list-threads.d.ts +28 -0
  35. package/dist/toolkits/gmail/tools/list-threads.js +43 -0
  36. package/dist/toolkits/gmail/tools/modify-message-labels.d.ts +31 -0
  37. package/dist/toolkits/gmail/tools/modify-message-labels.js +44 -0
  38. package/dist/toolkits/gmail/tools/reply-to-thread.d.ts +33 -0
  39. package/dist/toolkits/gmail/tools/reply-to-thread.js +58 -0
  40. package/dist/toolkits/gmail/tools/send-draft.d.ts +29 -0
  41. package/dist/toolkits/gmail/tools/send-draft.js +41 -0
  42. package/dist/toolkits/gmail/tools/send-message.d.ts +4 -1
  43. package/dist/toolkits/gmail/tools/send-message.js +18 -16
  44. package/dist/toolkits/gmail/tools/trash-message.d.ts +29 -0
  45. package/dist/toolkits/gmail/tools/trash-message.js +37 -0
  46. package/dist/toolkits/gmail/tools/untrash-message.d.ts +29 -0
  47. package/dist/toolkits/gmail/tools/untrash-message.js +37 -0
  48. package/dist/toolkits/gmail/tools/utils.d.ts +41 -0
  49. package/dist/toolkits/gmail/tools/utils.js +97 -0
  50. package/dist/toolkits/google-calendar/manifest.js +1 -1
  51. package/dist/toolkits/google-calendar/tools/delete-event.d.ts +27 -0
  52. package/dist/toolkits/google-calendar/tools/delete-event.js +38 -0
  53. package/dist/toolkits/google-calendar/tools/get-event.d.ts +24 -0
  54. package/dist/toolkits/google-calendar/tools/get-event.js +37 -0
  55. package/dist/toolkits/google-calendar/tools/index.d.ts +181 -3
  56. package/dist/toolkits/google-calendar/tools/index.js +31 -2
  57. package/dist/toolkits/google-calendar/tools/search-events.d.ts +27 -0
  58. package/dist/toolkits/google-calendar/tools/search-events.js +49 -0
  59. package/dist/toolkits/google-calendar/tools/update-event.d.ts +29 -0
  60. package/dist/toolkits/google-calendar/tools/update-event.js +56 -0
  61. package/dist/toolkits/google-sheets/manifest.js +2 -2
  62. package/dist/toolkits/google-sheets/tools/append-values.d.ts +41 -0
  63. package/dist/toolkits/google-sheets/tools/append-values.js +51 -0
  64. package/dist/toolkits/google-sheets/tools/clear-values.d.ts +27 -0
  65. package/dist/toolkits/google-sheets/tools/clear-values.js +41 -0
  66. package/dist/toolkits/google-sheets/tools/create-spreadsheet.d.ts +33 -0
  67. package/dist/toolkits/google-sheets/tools/create-spreadsheet.js +59 -0
  68. package/dist/toolkits/google-sheets/tools/index.d.ts +205 -7
  69. package/dist/toolkits/google-sheets/tools/index.js +39 -4
  70. package/dist/toolkits/google-sheets/tools/update-values.d.ts +38 -0
  71. package/dist/toolkits/google-sheets/tools/update-values.js +50 -0
  72. package/package.json +2 -5
package/README.md ADDED
@@ -0,0 +1,104 @@
1
+ # @rnsk/toolkits
2
+
3
+ Manifest-driven toolkit registry for AI agents — connector definitions you publish as npm and wire into [Runstack](https://runstack.engineer).
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@rnsk/toolkits.svg)](https://www.npmjs.com/package/@rnsk/toolkits)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](../../LICENSE)
7
+
8
+ > This is **not** [`@rnsk/tools`](https://www.npmjs.com/package/@rnsk/tools) (the MCP client SDK). `@rnsk/toolkits` ships **connector implementations** — manifests, tools, OAuth specs, and icons.
9
+
10
+ ## What this package contains
11
+
12
+ | Export | Purpose |
13
+ |--------|---------|
14
+ | `@rnsk/toolkits` | All toolkit manifests, `registerAllTools()`, `getAllTools()` |
15
+ | `@rnsk/toolkits/core` | Types, `defineToolkit`, validation, schema helpers |
16
+
17
+ ## Seed toolkits (v0.0.3)
18
+
19
+ **223 tools** across **8 toolkits**.
20
+
21
+ | Toolkit | Tools | Auth |
22
+ |---------|------:|------|
23
+ | mathematics | 9 | none |
24
+ | linear | 3 | OAuth2 |
25
+ | gmail | 15 | OAuth2 |
26
+ | web-search (Firecrawl) | 2 | service env |
27
+ | github | 173 | OAuth2 |
28
+ | notion | 8 | OAuth2 |
29
+ | google-calendar | 6 | OAuth2 |
30
+ | google-sheets | 7 | OAuth2 |
31
+
32
+ ## Install
33
+
34
+ ```bash
35
+ npm install @rnsk/toolkits
36
+ ```
37
+
38
+ Peer dependencies: `ai`, `zod`.
39
+
40
+ ## Usage
41
+
42
+ Register every toolkit tool into your application's registry:
43
+
44
+ ```ts
45
+ import { toolkits, registerAllTools } from '@rnsk/toolkits';
46
+
47
+ registerAllTools(myRegistry);
48
+ ```
49
+
50
+ Inspect manifests or build custom registration:
51
+
52
+ ```ts
53
+ import { toolkits } from '@rnsk/toolkits';
54
+ import { defineToolkit, validateManifests } from '@rnsk/toolkits/core';
55
+
56
+ for (const manifest of toolkits) {
57
+ console.log(manifest.id, manifest.tools.length);
58
+ }
59
+ ```
60
+
61
+ Runstack loads this package server-side, registers tools, and routes agent requests through its own meta-tool layer. You can publish a **private fork** or scoped package and point Runstack at your version to host connectors outside the public registry.
62
+
63
+ ## Toolkit structure
64
+
65
+ Each toolkit lives under `src/toolkits/<id>/`:
66
+
67
+ ```
68
+ <id>/
69
+ manifest.ts # defineToolkit({ displayName, auth, tools, ... })
70
+ icon.ts # SVG/PNG data URI
71
+ tools/
72
+ *.ts # one tool per file (AI SDK tool() + execute)
73
+ index.ts # exports array
74
+ ```
75
+
76
+ After adding a toolkit, register it in `src/index.ts`, then run `npm run validate && npm run build`.
77
+
78
+ ## Local testing
79
+
80
+ The repo includes a **sandbox** (not published to npm) for exercising tools at runtime:
81
+
82
+ ```bash
83
+ cd ../../sandbox
84
+ cp .env.local.example .env.local
85
+ npm run dev
86
+ ```
87
+
88
+ Use `POST /api/tools/execute` to invoke a tool directly with the same credential-injection pattern Runstack uses. See the [repository README](../../README.md) for sandbox endpoints.
89
+
90
+ ## Versioning
91
+
92
+ Pre-1.0 (`0.0.x`): patch releases add toolkits and tools. Pin an exact version in production (e.g. `"0.0.3"`).
93
+
94
+ ## Contributing
95
+
96
+ See [CONTRIBUTING.md](../../CONTRIBUTING.md) in the repository root.
97
+
98
+ ## Security
99
+
100
+ Report vulnerabilities privately — [SECURITY.md](../../SECURITY.md). Toolkit `execute` functions run server-side with user credentials; every PR is reviewed for token handling and outbound hosts.
101
+
102
+ ## License
103
+
104
+ MIT
@@ -2,5 +2,6 @@ export { CONNECTOR_CATEGORIES, type ConnectorCategory } from './categories.js';
2
2
  export { defineToolkit, defineTool, toolkitCamelId } from './define.js';
3
3
  export { inferToolScope } from './scope.js';
4
4
  export { validateManifests, getAuthType, } from './validate.js';
5
+ export { TOOL_OUTPUT_JSON_SCHEMA, getToolInputZodSchema, resolveZodObjectShape, toolInputToJsonSchema, extractParameterInfo, coerceArguments, type ParameterInfo, } from './schema-helpers.js';
5
6
  export type { ToolkitManifest, ToolDefinition, ToolkitIcon, ToolkitAuthSpec, ToolkitAuthType, ToolScope, OAuthProviderSpec, EnvVarSpec, ToolkitAvailability, } from './types.js';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -2,4 +2,5 @@ export { CONNECTOR_CATEGORIES } from './categories.js';
2
2
  export { defineToolkit, defineTool, toolkitCamelId } from './define.js';
3
3
  export { inferToolScope } from './scope.js';
4
4
  export { validateManifests, getAuthType, } from './validate.js';
5
+ export { TOOL_OUTPUT_JSON_SCHEMA, getToolInputZodSchema, resolveZodObjectShape, toolInputToJsonSchema, extractParameterInfo, coerceArguments, } from './schema-helpers.js';
5
6
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,20 @@
1
+ export declare const TOOL_OUTPUT_JSON_SCHEMA: Record<string, unknown>;
2
+ export declare function getToolInputZodSchema(tool: any): any | null;
3
+ export declare function resolveZodObjectShape(schema: {
4
+ shape?: Record<string, unknown>;
5
+ _def?: {
6
+ shape?: Record<string, unknown> | (() => Record<string, unknown>);
7
+ };
8
+ } | null | undefined): Record<string, unknown> | null;
9
+ export declare function toolInputToJsonSchema(tool: any, requiredAuth?: string): Record<string, unknown>;
10
+ export interface ParameterInfo {
11
+ type: string;
12
+ required: boolean;
13
+ description?: string;
14
+ itemType?: string;
15
+ options?: string[];
16
+ values?: string[];
17
+ }
18
+ export declare function extractParameterInfo(zodType: any): ParameterInfo | Record<string, unknown>;
19
+ export declare function coerceArguments(args: Record<string, unknown>, schema: any): Record<string, unknown>;
20
+ //# sourceMappingURL=schema-helpers.d.ts.map
@@ -0,0 +1,157 @@
1
+ import { zodToJsonSchema } from 'zod-to-json-schema';
2
+ export const TOOL_OUTPUT_JSON_SCHEMA = {
3
+ type: 'object',
4
+ description: 'JSON object returned by the tool. May include result data or an error field.',
5
+ additionalProperties: true,
6
+ };
7
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
+ export function getToolInputZodSchema(tool) {
9
+ if (!tool || typeof tool !== 'object')
10
+ return null;
11
+ return tool.inputSchema ?? tool._def?.parameters ?? null;
12
+ }
13
+ export function resolveZodObjectShape(schema) {
14
+ if (!schema)
15
+ return null;
16
+ if (schema.shape)
17
+ return schema.shape;
18
+ const defShape = schema._def?.shape;
19
+ if (typeof defShape === 'function')
20
+ return defShape();
21
+ if (defShape && typeof defShape === 'object')
22
+ return defShape;
23
+ return null;
24
+ }
25
+ function flattenJsonSchema(schema) {
26
+ if (schema.$ref && typeof schema.$ref === 'string' && schema.definitions) {
27
+ const refName = schema.$ref.replace('#/definitions/', '');
28
+ const definitions = schema.definitions;
29
+ const resolved = definitions[refName];
30
+ if (resolved) {
31
+ return {
32
+ ...resolved,
33
+ ...(schema.$schema ? { $schema: schema.$schema } : {}),
34
+ };
35
+ }
36
+ }
37
+ return schema;
38
+ }
39
+ function stripAuthFromJsonSchema(schema, requiredAuth) {
40
+ const properties = schema.properties;
41
+ if (!properties)
42
+ return schema;
43
+ const filtered = { ...properties };
44
+ for (const key of Object.keys(filtered)) {
45
+ if (key === requiredAuth || key.endsWith('Token')) {
46
+ delete filtered[key];
47
+ }
48
+ }
49
+ const required = Array.isArray(schema.required)
50
+ ? schema.required.filter((key) => key !== requiredAuth && !key.endsWith('Token'))
51
+ : undefined;
52
+ return {
53
+ ...schema,
54
+ properties: filtered,
55
+ ...(required && required.length > 0 ? { required } : {}),
56
+ };
57
+ }
58
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
59
+ export function toolInputToJsonSchema(tool, requiredAuth) {
60
+ const zodSchema = getToolInputZodSchema(tool);
61
+ if (!zodSchema) {
62
+ return { type: 'object', properties: {} };
63
+ }
64
+ const jsonSchema = zodToJsonSchema(zodSchema, {
65
+ $refStrategy: 'none',
66
+ });
67
+ return stripAuthFromJsonSchema(flattenJsonSchema(jsonSchema), requiredAuth);
68
+ }
69
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
70
+ export function extractParameterInfo(zodType) {
71
+ const typeName = zodType._def?.typeName;
72
+ const info = {
73
+ type: typeName?.replace('Zod', '').toLowerCase() || 'unknown',
74
+ required: !(zodType?.isOptional?.() ?? false),
75
+ description: zodType.description || undefined,
76
+ };
77
+ switch (typeName) {
78
+ case 'ZodNumber':
79
+ info.type = 'number';
80
+ break;
81
+ case 'ZodString':
82
+ info.type = 'string';
83
+ break;
84
+ case 'ZodBoolean':
85
+ info.type = 'boolean';
86
+ break;
87
+ case 'ZodArray':
88
+ info.type = 'array';
89
+ info.itemType = extractParameterInfo(zodType._def.type).type;
90
+ break;
91
+ case 'ZodObject':
92
+ info.type = 'object';
93
+ break;
94
+ case 'ZodUnion':
95
+ info.type = 'union';
96
+ info.options =
97
+ zodType._def.options?.map(
98
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
99
+ (opt) => extractParameterInfo(opt).type) || [];
100
+ break;
101
+ case 'ZodEnum':
102
+ info.type = 'enum';
103
+ info.values = zodType._def.values || [];
104
+ break;
105
+ case 'ZodOptional': {
106
+ const innerInfo = extractParameterInfo(zodType._def.innerType);
107
+ return { ...innerInfo, required: false };
108
+ }
109
+ default:
110
+ info.type = typeName?.replace('Zod', '').toLowerCase() || 'any';
111
+ }
112
+ return info;
113
+ }
114
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
115
+ export function coerceArguments(args, schema) {
116
+ const shape = resolveZodObjectShape(schema);
117
+ if (!shape)
118
+ return args;
119
+ const coercedArgs = {};
120
+ for (const [key, value] of Object.entries(args)) {
121
+ const fieldSchema = shape[key];
122
+ if (!fieldSchema) {
123
+ coercedArgs[key] = value;
124
+ continue;
125
+ }
126
+ let typeName = fieldSchema._def?.typeName;
127
+ let actualSchema = fieldSchema;
128
+ if (typeName === 'ZodOptional') {
129
+ actualSchema = fieldSchema._def?.innerType;
130
+ typeName = actualSchema?._def?.typeName;
131
+ }
132
+ try {
133
+ switch (typeName) {
134
+ case 'ZodNumber':
135
+ coercedArgs[key] = typeof value === 'string' ? parseFloat(value) : Number(value);
136
+ break;
137
+ case 'ZodString':
138
+ coercedArgs[key] = String(value);
139
+ break;
140
+ case 'ZodBoolean':
141
+ coercedArgs[key] =
142
+ typeof value === 'string' ? value.toLowerCase() === 'true' : Boolean(value);
143
+ break;
144
+ case 'ZodArray':
145
+ coercedArgs[key] = Array.isArray(value) ? value : [value];
146
+ break;
147
+ default:
148
+ coercedArgs[key] = value;
149
+ }
150
+ }
151
+ catch {
152
+ coercedArgs[key] = value;
153
+ }
154
+ }
155
+ return coercedArgs;
156
+ }
157
+ //# sourceMappingURL=schema-helpers.js.map
package/dist/index.d.ts CHANGED
@@ -10,7 +10,6 @@ import type { ToolkitManifest } from './core/types.js';
10
10
  export declare const toolkits: ToolkitManifest[];
11
11
  export { mathematics, linear, gmail, webSearch, github, notion, googleCalendar, googleSheets, };
12
12
  export * from './core/index.js';
13
- export * from './runtime/index.js';
14
13
  export declare function getAllTools(): {
15
14
  name: string;
16
15
  description: string;
package/dist/index.js CHANGED
@@ -18,7 +18,6 @@ export const toolkits = [
18
18
  ];
19
19
  export { mathematics, linear, gmail, webSearch, github, notion, googleCalendar, googleSheets, };
20
20
  export * from './core/index.js';
21
- export * from './runtime/index.js';
22
21
  export function getAllTools() {
23
22
  return toolkits.flatMap((t) => t.tools.map((toolDef) => ({
24
23
  name: toolDef.name,
@@ -2,7 +2,7 @@ export declare const listWorkflowJobs: import("ai").Tool<{
2
2
  repo: string;
3
3
  owner: string;
4
4
  run_id: number;
5
- filter?: "latest" | "all" | undefined;
5
+ filter?: "all" | "latest" | undefined;
6
6
  githubToken?: string | undefined;
7
7
  per_page?: number | undefined;
8
8
  page?: number | undefined;
@@ -1,8 +1,8 @@
1
1
  export declare const listNotifications: import("ai").Tool<{
2
+ all?: boolean | undefined;
2
3
  githubToken?: string | undefined;
3
4
  per_page?: number | undefined;
4
5
  page?: number | undefined;
5
- all?: boolean | undefined;
6
6
  participating?: boolean | undefined;
7
7
  }, {
8
8
  error: string;
@@ -1,8 +1,8 @@
1
1
  export declare const addIssueLabels: import("ai").Tool<{
2
+ labels: string[];
2
3
  repo: string;
3
4
  owner: string;
4
5
  issueNumber: number;
5
- labels: string[];
6
6
  githubToken?: string | undefined;
7
7
  }, {
8
8
  error: string;
@@ -2,12 +2,12 @@ export declare const listAuthenticatedUserIssues: import("ai").Tool<{
2
2
  sort?: "created" | "updated" | "comments" | undefined;
3
3
  filter?: "all" | "assigned" | "created" | "mentioned" | "subscribed" | undefined;
4
4
  since?: string | undefined;
5
+ labels?: string | undefined;
5
6
  githubToken?: string | undefined;
6
7
  per_page?: number | undefined;
7
8
  page?: number | undefined;
8
9
  state?: "all" | "open" | "closed" | undefined;
9
10
  direction?: "asc" | "desc" | undefined;
10
- labels?: string | undefined;
11
11
  }, {
12
12
  number: number;
13
13
  title: string;
@@ -3,12 +3,12 @@ export declare const listOrgIssues: import("ai").Tool<{
3
3
  sort?: "created" | "updated" | "comments" | undefined;
4
4
  filter?: "all" | "assigned" | "created" | "mentioned" | "subscribed" | undefined;
5
5
  since?: string | undefined;
6
+ labels?: string | undefined;
6
7
  githubToken?: string | undefined;
7
8
  per_page?: number | undefined;
8
9
  page?: number | undefined;
9
10
  state?: "all" | "open" | "closed" | undefined;
10
11
  direction?: "asc" | "desc" | undefined;
11
- labels?: string | undefined;
12
12
  }, {
13
13
  number: number;
14
14
  title: string;
@@ -2,12 +2,12 @@ export declare const listUserAccountIssues: import("ai").Tool<{
2
2
  sort?: "created" | "updated" | "comments" | undefined;
3
3
  filter?: "all" | "assigned" | "created" | "mentioned" | "subscribed" | undefined;
4
4
  since?: string | undefined;
5
+ labels?: string | undefined;
5
6
  githubToken?: string | undefined;
6
7
  per_page?: number | undefined;
7
8
  page?: number | undefined;
8
9
  state?: "all" | "open" | "closed" | undefined;
9
10
  direction?: "asc" | "desc" | undefined;
10
- labels?: string | undefined;
11
11
  }, {
12
12
  number: number;
13
13
  title: string;
@@ -1,6 +1,6 @@
1
1
  export declare const listOrgRepositories: import("ai").Tool<{
2
2
  org: string;
3
- type?: "sources" | "all" | "public" | "member" | "private" | "forks" | undefined;
3
+ type?: "all" | "sources" | "public" | "member" | "private" | "forks" | undefined;
4
4
  githubToken?: string | undefined;
5
5
  per_page?: number | undefined;
6
6
  page?: number | undefined;
@@ -8,8 +8,8 @@ export declare const createRepoWebhook: import("ai").Tool<{
8
8
  insecure_ssl?: string | undefined;
9
9
  };
10
10
  githubToken?: string | undefined;
11
- name?: string | undefined;
12
11
  events?: string[] | undefined;
12
+ name?: string | undefined;
13
13
  active?: boolean | undefined;
14
14
  }, {
15
15
  error: string;
@@ -4,22 +4,22 @@ const SVG = `<svg width="800" height="636.36322" fill="none" viewBox="0 0 800 63
4
4
  <path fill="url(#b)" d="M 141.93685,20.255746 C 105.42331,-10.435083 50.946177,-5.7169131 20.255349,30.796627 -10.435479,67.305622 -5.7173098,121.78275 30.79623,152.47813 l 345.80818,290.6765 a 36.36354,36.36354 0 0 0 46.79533,0 L 769.20792,152.47358 C 805.71691,121.78275 810.43508,67.305622 779.74426,30.792081 749.05343,-5.7169131 694.5763,-10.435083 658.0673,20.255746 L 399.9998,237.18245 Z" id="path3" style="fill:url(#b);stroke-width:4.54544"/>
5
5
  <defs id="defs16">
6
6
  <linearGradient id="a" x1="165" x2="165" y1="44" y2="166" gradientUnits="userSpaceOnUse" gradientTransform="matrix(4.5454426,0,0,4.5454426,-36.362684,-118.18025)">
7
- <stop stopColor="#60d673" id="stop3"/>
8
- <stop offset=".17" stopColor="#42c868" id="stop4"/>
9
- <stop offset=".39" stopColor="#0ebc5f" id="stop5"/>
10
- <stop offset=".62" stopColor="#00a9bb" id="stop6"/>
11
- <stop offset=".86" stopColor="#3c90ff" id="stop7"/>
12
- <stop offset="1" stopColor="#3186ff" id="stop8"/>
7
+ <stop stop-color="#60d673" id="stop3"/>
8
+ <stop offset=".17" stop-color="#42c868" id="stop4"/>
9
+ <stop offset=".39" stop-color="#0ebc5f" id="stop5"/>
10
+ <stop offset=".62" stop-color="#00a9bb" id="stop6"/>
11
+ <stop offset=".86" stop-color="#3c90ff" id="stop7"/>
12
+ <stop offset="1" stop-color="#3186ff" id="stop8"/>
13
13
  </linearGradient>
14
14
  <linearGradient id="b" x1="8" x2="184" y1="46.130001" y2="46.130001" gradientUnits="userSpaceOnUse" gradientTransform="matrix(4.5454426,0,0,4.5454426,-36.362684,-118.18025)">
15
- <stop offset=".08" stopColor="#ff63a0" id="stop9"/>
16
- <stop offset=".3" stopColor="#fc413d" id="stop10"/>
17
- <stop offset=".5" stopColor="#fc413d" id="stop11"/>
18
- <stop offset=".65" stopColor="#fc413d" id="stop12"/>
19
- <stop offset=".72" stopColor="#fc5c30" id="stop13"/>
20
- <stop offset=".86" stopColor="#feb10c" id="stop14"/>
21
- <stop offset=".91" stopColor="#fec700" id="stop15"/>
22
- <stop offset=".96" stopColor="#ffdb0f" id="stop16"/>
15
+ <stop offset=".08" stop-color="#ff63a0" id="stop9"/>
16
+ <stop offset=".3" stop-color="#fc413d" id="stop10"/>
17
+ <stop offset=".5" stop-color="#fc413d" id="stop11"/>
18
+ <stop offset=".65" stop-color="#fc413d" id="stop12"/>
19
+ <stop offset=".72" stop-color="#fc5c30" id="stop13"/>
20
+ <stop offset=".86" stop-color="#feb10c" id="stop14"/>
21
+ <stop offset=".91" stop-color="#fec700" id="stop15"/>
22
+ <stop offset=".96" stop-color="#ffdb0f" id="stop16"/>
23
23
  </linearGradient>
24
24
  </defs>
25
25
  </svg>`;
@@ -1,12 +1,10 @@
1
1
  import { defineToolkit, defineTool } from '../../core/define.js';
2
2
  import { GMAIL_ICON } from './icon.js';
3
- import { listMessages } from './tools/list-messages.js';
4
- import { getMessage } from './tools/get-message.js';
5
- import { sendMessage } from './tools/send-message.js';
3
+ import { listMessages, getMessage, sendMessage, createDraft, listDrafts, getDraft, sendDraft, deleteDraft, listThreads, getThread, replyToThread, listLabels, modifyMessageLabels, trashMessage, untrashMessage, } from './tools/index.js';
6
4
  export default defineToolkit({
7
5
  id: 'gmail',
8
6
  displayName: 'Gmail',
9
- shortDescription: 'List, read, and send emails.',
7
+ shortDescription: 'Read, search, draft, send, and organize emails and threads.',
10
8
  category: 'Collaboration & Communication',
11
9
  icon: GMAIL_ICON,
12
10
  auth: {
@@ -20,10 +18,13 @@ export default defineToolkit({
20
18
  scopes: [
21
19
  'https://www.googleapis.com/auth/gmail.readonly',
22
20
  'https://www.googleapis.com/auth/gmail.send',
21
+ 'https://www.googleapis.com/auth/gmail.compose',
22
+ 'https://www.googleapis.com/auth/gmail.modify',
23
+ 'https://www.googleapis.com/auth/gmail.labels',
23
24
  ],
24
25
  exchangeStyle: 'form',
25
26
  extraAuthParams: { access_type: 'offline', prompt: 'consent' },
26
- connectDescription: 'Connect Gmail to read, draft, and send emails with AI-driven summarization.',
27
+ connectDescription: 'Connect Gmail to read, draft, send, search, and organize emails and conversation threads.',
27
28
  callbackPath: '/api/auth/gmail/callback',
28
29
  stateCookie: 'google_oauth_state',
29
30
  },
@@ -48,6 +49,78 @@ export default defineToolkit({
48
49
  requiredAuth: 'gmailToken',
49
50
  scope: 'write',
50
51
  }),
52
+ defineTool({
53
+ name: 'gmailCreateDraft',
54
+ tool: createDraft,
55
+ requiredAuth: 'gmailToken',
56
+ scope: 'write',
57
+ }),
58
+ defineTool({
59
+ name: 'gmailListDrafts',
60
+ tool: listDrafts,
61
+ requiredAuth: 'gmailToken',
62
+ scope: 'read',
63
+ }),
64
+ defineTool({
65
+ name: 'gmailGetDraft',
66
+ tool: getDraft,
67
+ requiredAuth: 'gmailToken',
68
+ scope: 'read',
69
+ }),
70
+ defineTool({
71
+ name: 'gmailSendDraft',
72
+ tool: sendDraft,
73
+ requiredAuth: 'gmailToken',
74
+ scope: 'write',
75
+ }),
76
+ defineTool({
77
+ name: 'gmailDeleteDraft',
78
+ tool: deleteDraft,
79
+ requiredAuth: 'gmailToken',
80
+ scope: 'delete',
81
+ }),
82
+ defineTool({
83
+ name: 'gmailListThreads',
84
+ tool: listThreads,
85
+ requiredAuth: 'gmailToken',
86
+ scope: 'read',
87
+ }),
88
+ defineTool({
89
+ name: 'gmailGetThread',
90
+ tool: getThread,
91
+ requiredAuth: 'gmailToken',
92
+ scope: 'read',
93
+ }),
94
+ defineTool({
95
+ name: 'gmailReplyToThread',
96
+ tool: replyToThread,
97
+ requiredAuth: 'gmailToken',
98
+ scope: 'write',
99
+ }),
100
+ defineTool({
101
+ name: 'gmailListLabels',
102
+ tool: listLabels,
103
+ requiredAuth: 'gmailToken',
104
+ scope: 'read',
105
+ }),
106
+ defineTool({
107
+ name: 'gmailModifyMessageLabels',
108
+ tool: modifyMessageLabels,
109
+ requiredAuth: 'gmailToken',
110
+ scope: 'write',
111
+ }),
112
+ defineTool({
113
+ name: 'gmailTrashMessage',
114
+ tool: trashMessage,
115
+ requiredAuth: 'gmailToken',
116
+ scope: 'delete',
117
+ }),
118
+ defineTool({
119
+ name: 'gmailUntrashMessage',
120
+ tool: untrashMessage,
121
+ requiredAuth: 'gmailToken',
122
+ scope: 'write',
123
+ }),
51
124
  ],
52
125
  meta: { since: '0.0.1' },
53
126
  });
@@ -0,0 +1,34 @@
1
+ export declare const createDraft: import("ai").Tool<{
2
+ subject: string;
3
+ to: string;
4
+ body: string;
5
+ gmailToken?: string | undefined;
6
+ threadId?: string | undefined;
7
+ cc?: string | undefined;
8
+ bcc?: string | undefined;
9
+ }, {
10
+ error: string;
11
+ details: any;
12
+ success?: undefined;
13
+ draftId?: undefined;
14
+ messageId?: undefined;
15
+ threadId?: undefined;
16
+ message?: undefined;
17
+ } | {
18
+ success: boolean;
19
+ draftId: any;
20
+ messageId: any;
21
+ threadId: any;
22
+ error?: undefined;
23
+ details?: undefined;
24
+ message?: undefined;
25
+ } | {
26
+ error: string;
27
+ message: string;
28
+ details?: undefined;
29
+ success?: undefined;
30
+ draftId?: undefined;
31
+ messageId?: undefined;
32
+ threadId?: undefined;
33
+ }>;
34
+ //# sourceMappingURL=create-draft.d.ts.map
@@ -0,0 +1,60 @@
1
+ import { tool } from 'ai';
2
+ import { z } from 'zod';
3
+ import { encodeRFC822Message } from './utils.js';
4
+ export const createDraft = tool({
5
+ description: 'Create a draft email in Gmail without sending it immediately. Highly recommended for human-in-the-loop review.',
6
+ inputSchema: z.object({
7
+ gmailToken: z.string().optional().describe('Injected by system; do not provide'),
8
+ to: z.string().describe('Recipient email address'),
9
+ subject: z.string().describe('Email subject'),
10
+ body: z.string().describe('Email body (plain text)'),
11
+ cc: z.string().optional().describe('Optional CC recipient email address(es), comma-separated'),
12
+ bcc: z.string().optional().describe('Optional BCC recipient email address(es), comma-separated'),
13
+ threadId: z.string().optional().describe('Optional thread ID to associate the draft with an existing conversation thread'),
14
+ }),
15
+ execute: async ({ gmailToken, to, subject, body, cc, bcc, threadId }) => {
16
+ try {
17
+ const encodedMessage = encodeRFC822Message({
18
+ to,
19
+ subject,
20
+ body,
21
+ cc,
22
+ bcc,
23
+ });
24
+ const messagePayload = {
25
+ raw: encodedMessage,
26
+ };
27
+ if (threadId) {
28
+ messagePayload.threadId = threadId;
29
+ }
30
+ const response = await fetch('https://gmail.googleapis.com/gmail/v1/users/me/drafts', {
31
+ method: 'POST',
32
+ headers: {
33
+ Authorization: `Bearer ${gmailToken}`,
34
+ 'Content-Type': 'application/json',
35
+ },
36
+ body: JSON.stringify({
37
+ message: messagePayload,
38
+ }),
39
+ });
40
+ if (!response.ok) {
41
+ const error = await response.json();
42
+ return { error: 'Failed to create draft', details: error };
43
+ }
44
+ const data = await response.json();
45
+ return {
46
+ success: true,
47
+ draftId: data.id,
48
+ messageId: data.message?.id,
49
+ threadId: data.message?.threadId,
50
+ };
51
+ }
52
+ catch (error) {
53
+ return {
54
+ error: 'Error creating draft',
55
+ message: error instanceof Error ? error.message : 'Unknown error',
56
+ };
57
+ }
58
+ },
59
+ });
60
+ //# sourceMappingURL=create-draft.js.map