@supyagent/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/dist/index.d.ts +64 -0
- package/dist/index.js +155 -0
- package/dist/index.js.map +1 -0
- package/dist/prisma.d.ts +111 -0
- package/dist/prisma.js +67 -0
- package/dist/prisma.js.map +1 -0
- package/dist/react.d.ts +56 -0
- package/dist/react.js +407 -0
- package/dist/react.js.map +1 -0
- package/package.json +56 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/** Mirrors the ToolSchema.metadata from supyagent_service tool-schemas.ts */
|
|
2
|
+
interface ToolMetadata {
|
|
3
|
+
provider: string;
|
|
4
|
+
service: string;
|
|
5
|
+
permission: string;
|
|
6
|
+
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
7
|
+
path: string;
|
|
8
|
+
bodyDefaults?: Record<string, string>;
|
|
9
|
+
category?: string;
|
|
10
|
+
tags?: string[];
|
|
11
|
+
}
|
|
12
|
+
/** A single tool as returned by the /api/v1/tools endpoint */
|
|
13
|
+
interface OpenAITool {
|
|
14
|
+
type: "function";
|
|
15
|
+
function: {
|
|
16
|
+
name: string;
|
|
17
|
+
description: string;
|
|
18
|
+
parameters: {
|
|
19
|
+
type: "object";
|
|
20
|
+
properties: Record<string, unknown>;
|
|
21
|
+
required?: string[];
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
metadata: ToolMetadata;
|
|
25
|
+
}
|
|
26
|
+
/** Response shape from GET /api/v1/tools */
|
|
27
|
+
interface ToolsResponse {
|
|
28
|
+
tools: OpenAITool[];
|
|
29
|
+
base_url: string;
|
|
30
|
+
total: number;
|
|
31
|
+
}
|
|
32
|
+
/** Options for the supyagent() factory */
|
|
33
|
+
interface SupyagentOptions {
|
|
34
|
+
apiKey: string;
|
|
35
|
+
baseUrl?: string;
|
|
36
|
+
}
|
|
37
|
+
/** Options for the tools() method */
|
|
38
|
+
interface ToolFilterOptions {
|
|
39
|
+
/** Filter to only these providers, services, or tool names */
|
|
40
|
+
only?: string[];
|
|
41
|
+
/** Exclude these providers, services, or tool names */
|
|
42
|
+
except?: string[];
|
|
43
|
+
/** Cache TTL in seconds. true = 60s, number = custom TTL, false/undefined = no cache */
|
|
44
|
+
cache?: boolean | number;
|
|
45
|
+
}
|
|
46
|
+
/** The supyagent client interface */
|
|
47
|
+
interface SupyagentClient {
|
|
48
|
+
tools(options?: ToolFilterOptions): Promise<Record<string, unknown>>;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Create a supyagent client for fetching and converting tools.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* import { supyagent } from '@supyagent/sdk';
|
|
57
|
+
*
|
|
58
|
+
* const client = supyagent({ apiKey: process.env.SUPYAGENT_API_KEY! });
|
|
59
|
+
* const tools = await client.tools({ cache: 300 });
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
declare function supyagent(options: SupyagentOptions): SupyagentClient;
|
|
63
|
+
|
|
64
|
+
export { type OpenAITool, type SupyagentClient, type SupyagentOptions, type ToolFilterOptions, type ToolMetadata, type ToolsResponse, supyagent };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
// src/core/cache.ts
|
|
2
|
+
var TTLCache = class {
|
|
3
|
+
store = /* @__PURE__ */ new Map();
|
|
4
|
+
get(key) {
|
|
5
|
+
const entry = this.store.get(key);
|
|
6
|
+
if (!entry) return void 0;
|
|
7
|
+
if (Date.now() > entry.expiresAt) {
|
|
8
|
+
this.store.delete(key);
|
|
9
|
+
return void 0;
|
|
10
|
+
}
|
|
11
|
+
return entry.data;
|
|
12
|
+
}
|
|
13
|
+
set(key, data, ttlSeconds) {
|
|
14
|
+
this.store.set(key, {
|
|
15
|
+
data,
|
|
16
|
+
expiresAt: Date.now() + ttlSeconds * 1e3
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
clear() {
|
|
20
|
+
this.store.clear();
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// src/core/tool-converter.ts
|
|
25
|
+
import { tool, jsonSchema } from "ai";
|
|
26
|
+
|
|
27
|
+
// src/core/http-executor.ts
|
|
28
|
+
function createExecutor(metadata, baseUrl, apiKey) {
|
|
29
|
+
return async (args) => {
|
|
30
|
+
const { method, path, bodyDefaults } = metadata;
|
|
31
|
+
const remainingArgs = { ...args };
|
|
32
|
+
let resolvedPath = path;
|
|
33
|
+
const pathParams = path.match(/\{(\w+)\}/g);
|
|
34
|
+
if (pathParams) {
|
|
35
|
+
for (const param of pathParams) {
|
|
36
|
+
const paramName = param.slice(1, -1);
|
|
37
|
+
if (paramName in remainingArgs) {
|
|
38
|
+
resolvedPath = resolvedPath.replace(
|
|
39
|
+
param,
|
|
40
|
+
encodeURIComponent(String(remainingArgs[paramName]))
|
|
41
|
+
);
|
|
42
|
+
delete remainingArgs[paramName];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
let url = `${baseUrl}${resolvedPath}`;
|
|
47
|
+
const fetchOptions = {
|
|
48
|
+
method,
|
|
49
|
+
headers: {
|
|
50
|
+
Authorization: `Bearer ${apiKey}`,
|
|
51
|
+
"Content-Type": "application/json"
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
if (method === "GET" || method === "DELETE") {
|
|
55
|
+
const params = new URLSearchParams();
|
|
56
|
+
for (const [key, value] of Object.entries(remainingArgs)) {
|
|
57
|
+
if (value !== void 0 && value !== null) {
|
|
58
|
+
params.set(key, String(value));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const qs = params.toString();
|
|
62
|
+
if (qs) url += `?${qs}`;
|
|
63
|
+
} else {
|
|
64
|
+
const body = { ...bodyDefaults, ...remainingArgs };
|
|
65
|
+
fetchOptions.body = JSON.stringify(body);
|
|
66
|
+
}
|
|
67
|
+
const response = await fetch(url, fetchOptions);
|
|
68
|
+
const data = await response.json();
|
|
69
|
+
return data;
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// src/core/tool-converter.ts
|
|
74
|
+
function convertTools(tools, baseUrl, apiKey) {
|
|
75
|
+
const result = {};
|
|
76
|
+
for (const t of tools) {
|
|
77
|
+
const { name, description, parameters } = t.function;
|
|
78
|
+
const metadata = t.metadata;
|
|
79
|
+
result[name] = tool({
|
|
80
|
+
description,
|
|
81
|
+
parameters: jsonSchema(parameters),
|
|
82
|
+
execute: createExecutor(metadata, baseUrl, apiKey)
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
function filterTools(tools, options) {
|
|
88
|
+
let filtered = tools;
|
|
89
|
+
if (options.only && options.only.length > 0) {
|
|
90
|
+
const onlySet = new Set(options.only.map((s) => s.toLowerCase()));
|
|
91
|
+
filtered = filtered.filter((t) => {
|
|
92
|
+
const name = t.function.name.toLowerCase();
|
|
93
|
+
const provider = t.metadata.provider.toLowerCase();
|
|
94
|
+
const service = t.metadata.service.toLowerCase();
|
|
95
|
+
return onlySet.has(name) || onlySet.has(provider) || onlySet.has(service);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
if (options.except && options.except.length > 0) {
|
|
99
|
+
const exceptSet = new Set(options.except.map((s) => s.toLowerCase()));
|
|
100
|
+
filtered = filtered.filter((t) => {
|
|
101
|
+
const name = t.function.name.toLowerCase();
|
|
102
|
+
const provider = t.metadata.provider.toLowerCase();
|
|
103
|
+
const service = t.metadata.service.toLowerCase();
|
|
104
|
+
return !exceptSet.has(name) && !exceptSet.has(provider) && !exceptSet.has(service);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
return filtered;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// src/core/client.ts
|
|
111
|
+
var DEFAULT_BASE_URL = "https://app.supyagent.com";
|
|
112
|
+
var CACHE_KEY = "tools";
|
|
113
|
+
function supyagent(options) {
|
|
114
|
+
const { apiKey, baseUrl = DEFAULT_BASE_URL } = options;
|
|
115
|
+
const cache = new TTLCache();
|
|
116
|
+
return {
|
|
117
|
+
async tools(filterOptions) {
|
|
118
|
+
const cacheTTL = resolveCacheTTL(filterOptions?.cache);
|
|
119
|
+
let response = cacheTTL > 0 ? cache.get(CACHE_KEY) : void 0;
|
|
120
|
+
if (!response) {
|
|
121
|
+
const res = await fetch(`${baseUrl}/api/v1/tools`, {
|
|
122
|
+
headers: {
|
|
123
|
+
Authorization: `Bearer ${apiKey}`,
|
|
124
|
+
"Content-Type": "application/json"
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
if (!res.ok) {
|
|
128
|
+
const error = await res.text();
|
|
129
|
+
throw new Error(
|
|
130
|
+
`Supyagent API error (${res.status}): ${error}`
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
response = await res.json();
|
|
134
|
+
if (cacheTTL > 0) {
|
|
135
|
+
cache.set(CACHE_KEY, response, cacheTTL);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const toolBaseUrl = response.base_url || baseUrl;
|
|
139
|
+
const filtered = filterTools(response.tools, {
|
|
140
|
+
only: filterOptions?.only,
|
|
141
|
+
except: filterOptions?.except
|
|
142
|
+
});
|
|
143
|
+
return convertTools(filtered, toolBaseUrl, apiKey);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
function resolveCacheTTL(cache) {
|
|
148
|
+
if (cache === true) return 60;
|
|
149
|
+
if (typeof cache === "number") return cache;
|
|
150
|
+
return 0;
|
|
151
|
+
}
|
|
152
|
+
export {
|
|
153
|
+
supyagent
|
|
154
|
+
};
|
|
155
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/cache.ts","../src/core/tool-converter.ts","../src/core/http-executor.ts","../src/core/client.ts"],"sourcesContent":["interface CacheEntry<T> {\n data: T;\n expiresAt: number;\n}\n\nexport class TTLCache<T> {\n private store = new Map<string, CacheEntry<T>>();\n\n get(key: string): T | undefined {\n const entry = this.store.get(key);\n if (!entry) return undefined;\n if (Date.now() > entry.expiresAt) {\n this.store.delete(key);\n return undefined;\n }\n return entry.data;\n }\n\n set(key: string, data: T, ttlSeconds: number): void {\n this.store.set(key, {\n data,\n expiresAt: Date.now() + ttlSeconds * 1000,\n });\n }\n\n clear(): void {\n this.store.clear();\n }\n}\n","import { tool, jsonSchema } from \"ai\";\nimport type { OpenAITool } from \"./types.js\";\nimport { createExecutor } from \"./http-executor.js\";\n\n/**\n * Converts an array of OpenAI-format tools from the supyagent API\n * into a Record of AI SDK tool() instances ready for streamText/generateText.\n */\nexport function convertTools(\n tools: OpenAITool[],\n baseUrl: string,\n apiKey: string\n): Record<string, ReturnType<typeof tool>> {\n const result: Record<string, ReturnType<typeof tool>> = {};\n\n for (const t of tools) {\n const { name, description, parameters } = t.function;\n const metadata = t.metadata;\n\n result[name] = tool({\n description,\n parameters: jsonSchema(parameters as Parameters<typeof jsonSchema>[0]),\n execute: createExecutor(metadata, baseUrl, apiKey),\n });\n }\n\n return result;\n}\n\n/**\n * Filter tools by provider, service, or tool name.\n */\nexport function filterTools(\n tools: OpenAITool[],\n options: { only?: string[]; except?: string[] }\n): OpenAITool[] {\n let filtered = tools;\n\n if (options.only && options.only.length > 0) {\n const onlySet = new Set(options.only.map((s) => s.toLowerCase()));\n filtered = filtered.filter((t) => {\n const name = t.function.name.toLowerCase();\n const provider = t.metadata.provider.toLowerCase();\n const service = t.metadata.service.toLowerCase();\n return onlySet.has(name) || onlySet.has(provider) || onlySet.has(service);\n });\n }\n\n if (options.except && options.except.length > 0) {\n const exceptSet = new Set(options.except.map((s) => s.toLowerCase()));\n filtered = filtered.filter((t) => {\n const name = t.function.name.toLowerCase();\n const provider = t.metadata.provider.toLowerCase();\n const service = t.metadata.service.toLowerCase();\n return (\n !exceptSet.has(name) &&\n !exceptSet.has(provider) &&\n !exceptSet.has(service)\n );\n });\n }\n\n return filtered;\n}\n","import type { ToolMetadata } from \"./types.js\";\n\n/**\n * Creates an execute function for a tool that calls the supyagent API.\n *\n * Handles:\n * - Path parameter substitution (e.g., {messageId} in /api/v1/gmail/messages/{messageId})\n * - GET/DELETE: remaining args → query string\n * - POST/PUT/PATCH: merge bodyDefaults + remaining args → JSON body\n */\nexport function createExecutor(\n metadata: ToolMetadata,\n baseUrl: string,\n apiKey: string\n): (args: Record<string, unknown>) => Promise<unknown> {\n return async (args: Record<string, unknown>) => {\n const { method, path, bodyDefaults } = metadata;\n\n // Extract path parameters and substitute into the path\n const remainingArgs = { ...args };\n let resolvedPath = path;\n\n const pathParams = path.match(/\\{(\\w+)\\}/g);\n if (pathParams) {\n for (const param of pathParams) {\n const paramName = param.slice(1, -1);\n if (paramName in remainingArgs) {\n resolvedPath = resolvedPath.replace(\n param,\n encodeURIComponent(String(remainingArgs[paramName]))\n );\n delete remainingArgs[paramName];\n }\n }\n }\n\n let url = `${baseUrl}${resolvedPath}`;\n\n const fetchOptions: RequestInit = {\n method,\n headers: {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\",\n },\n };\n\n if (method === \"GET\" || method === \"DELETE\") {\n // Remaining args go as query parameters\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(remainingArgs)) {\n if (value !== undefined && value !== null) {\n params.set(key, String(value));\n }\n }\n const qs = params.toString();\n if (qs) url += `?${qs}`;\n } else {\n // POST/PUT/PATCH: merge bodyDefaults with remaining args\n const body = { ...bodyDefaults, ...remainingArgs };\n fetchOptions.body = JSON.stringify(body);\n }\n\n const response = await fetch(url, fetchOptions);\n const data = await response.json();\n return data;\n };\n}\n","import type {\n SupyagentOptions,\n SupyagentClient,\n ToolFilterOptions,\n ToolsResponse,\n} from \"./types.js\";\nimport { TTLCache } from \"./cache.js\";\nimport { convertTools, filterTools } from \"./tool-converter.js\";\n\nconst DEFAULT_BASE_URL = \"https://app.supyagent.com\";\nconst CACHE_KEY = \"tools\";\n\n/**\n * Create a supyagent client for fetching and converting tools.\n *\n * @example\n * ```ts\n * import { supyagent } from '@supyagent/sdk';\n *\n * const client = supyagent({ apiKey: process.env.SUPYAGENT_API_KEY! });\n * const tools = await client.tools({ cache: 300 });\n * ```\n */\nexport function supyagent(options: SupyagentOptions): SupyagentClient {\n const { apiKey, baseUrl = DEFAULT_BASE_URL } = options;\n const cache = new TTLCache<ToolsResponse>();\n\n return {\n async tools(filterOptions?: ToolFilterOptions) {\n const cacheTTL = resolveCacheTTL(filterOptions?.cache);\n\n // Check cache\n let response = cacheTTL > 0 ? cache.get(CACHE_KEY) : undefined;\n\n if (!response) {\n // Fetch from API\n const res = await fetch(`${baseUrl}/api/v1/tools`, {\n headers: {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\",\n },\n });\n\n if (!res.ok) {\n const error = await res.text();\n throw new Error(\n `Supyagent API error (${res.status}): ${error}`\n );\n }\n\n response = (await res.json()) as ToolsResponse;\n\n // Store in cache if TTL > 0\n if (cacheTTL > 0) {\n cache.set(CACHE_KEY, response, cacheTTL);\n }\n }\n\n // Use API-reported base_url for tool execution\n const toolBaseUrl = response.base_url || baseUrl;\n\n // Filter\n const filtered = filterTools(response.tools, {\n only: filterOptions?.only,\n except: filterOptions?.except,\n });\n\n // Convert to AI SDK tools\n return convertTools(filtered, toolBaseUrl, apiKey);\n },\n };\n}\n\nfunction resolveCacheTTL(cache?: boolean | number): number {\n if (cache === true) return 60;\n if (typeof cache === \"number\") return cache;\n return 0;\n}\n"],"mappings":"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","names":[]}
|
package/dist/prisma.d.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/** A chat summary for listing */
|
|
2
|
+
interface ChatSummary {
|
|
3
|
+
id: string;
|
|
4
|
+
title: string;
|
|
5
|
+
createdAt: Date;
|
|
6
|
+
updatedAt: Date;
|
|
7
|
+
}
|
|
8
|
+
/** Chat persistence adapter interface */
|
|
9
|
+
interface ChatAdapter {
|
|
10
|
+
/** Save or update a chat with its messages (append-only) */
|
|
11
|
+
saveChat(chatId: string, messages: UIMessageLike[]): Promise<void>;
|
|
12
|
+
/** Load all messages for a chat */
|
|
13
|
+
loadChat(chatId: string): Promise<UIMessageLike[]>;
|
|
14
|
+
/** List all chats (summary only) */
|
|
15
|
+
listChats(): Promise<ChatSummary[]>;
|
|
16
|
+
/** Delete a chat and all its messages */
|
|
17
|
+
deleteChat(chatId: string): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Minimal UIMessage-compatible interface.
|
|
21
|
+
* Matches Vercel AI SDK's UIMessage shape without importing it directly.
|
|
22
|
+
*/
|
|
23
|
+
interface UIMessageLike {
|
|
24
|
+
id: string;
|
|
25
|
+
role: string;
|
|
26
|
+
parts: Array<{
|
|
27
|
+
type: string;
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
}>;
|
|
30
|
+
metadata?: Record<string, unknown>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Minimal PrismaClient interface — just the methods we use.
|
|
35
|
+
* Avoids importing @prisma/client at the type level.
|
|
36
|
+
*/
|
|
37
|
+
interface PrismaLike {
|
|
38
|
+
chat: {
|
|
39
|
+
upsert: (args: {
|
|
40
|
+
where: {
|
|
41
|
+
id: string;
|
|
42
|
+
};
|
|
43
|
+
create: {
|
|
44
|
+
id: string;
|
|
45
|
+
title: string;
|
|
46
|
+
};
|
|
47
|
+
update: {
|
|
48
|
+
title?: string;
|
|
49
|
+
};
|
|
50
|
+
}) => Promise<unknown>;
|
|
51
|
+
findMany: (args: {
|
|
52
|
+
orderBy: {
|
|
53
|
+
updatedAt: string;
|
|
54
|
+
};
|
|
55
|
+
select: {
|
|
56
|
+
id: boolean;
|
|
57
|
+
title: boolean;
|
|
58
|
+
createdAt: boolean;
|
|
59
|
+
updatedAt: boolean;
|
|
60
|
+
};
|
|
61
|
+
}) => Promise<ChatSummary[]>;
|
|
62
|
+
delete: (args: {
|
|
63
|
+
where: {
|
|
64
|
+
id: string;
|
|
65
|
+
};
|
|
66
|
+
}) => Promise<unknown>;
|
|
67
|
+
};
|
|
68
|
+
message: {
|
|
69
|
+
count: (args: {
|
|
70
|
+
where: {
|
|
71
|
+
chatId: string;
|
|
72
|
+
};
|
|
73
|
+
}) => Promise<number>;
|
|
74
|
+
createMany: (args: {
|
|
75
|
+
data: Array<{
|
|
76
|
+
id: string;
|
|
77
|
+
chatId: string;
|
|
78
|
+
role: string;
|
|
79
|
+
parts: string;
|
|
80
|
+
metadata: string | null;
|
|
81
|
+
}>;
|
|
82
|
+
}) => Promise<unknown>;
|
|
83
|
+
findMany: (args: {
|
|
84
|
+
where: {
|
|
85
|
+
chatId: string;
|
|
86
|
+
};
|
|
87
|
+
orderBy: {
|
|
88
|
+
createdAt: string;
|
|
89
|
+
};
|
|
90
|
+
}) => Promise<Array<{
|
|
91
|
+
id: string;
|
|
92
|
+
role: string;
|
|
93
|
+
parts: string;
|
|
94
|
+
metadata: string | null;
|
|
95
|
+
}>>;
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Create a ChatAdapter backed by Prisma.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```ts
|
|
103
|
+
* import { createPrismaAdapter } from '@supyagent/sdk/prisma';
|
|
104
|
+
* import { prisma } from '@/lib/prisma';
|
|
105
|
+
*
|
|
106
|
+
* const adapter = createPrismaAdapter(prisma);
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
declare function createPrismaAdapter(prisma: PrismaLike): ChatAdapter;
|
|
110
|
+
|
|
111
|
+
export { type ChatAdapter, type ChatSummary, type UIMessageLike, createPrismaAdapter };
|
package/dist/prisma.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// src/persistence/prisma-adapter.ts
|
|
2
|
+
function createPrismaAdapter(prisma) {
|
|
3
|
+
return {
|
|
4
|
+
async saveChat(chatId, messages) {
|
|
5
|
+
const firstUserMsg = messages.find((m) => m.role === "user");
|
|
6
|
+
const title = extractTitle(firstUserMsg);
|
|
7
|
+
await prisma.chat.upsert({
|
|
8
|
+
where: { id: chatId },
|
|
9
|
+
create: { id: chatId, title },
|
|
10
|
+
update: { title }
|
|
11
|
+
});
|
|
12
|
+
const existingCount = await prisma.message.count({
|
|
13
|
+
where: { chatId }
|
|
14
|
+
});
|
|
15
|
+
const newMessages = messages.slice(existingCount);
|
|
16
|
+
if (newMessages.length > 0) {
|
|
17
|
+
await prisma.message.createMany({
|
|
18
|
+
data: newMessages.map((msg) => ({
|
|
19
|
+
id: msg.id,
|
|
20
|
+
chatId,
|
|
21
|
+
role: msg.role,
|
|
22
|
+
parts: JSON.stringify(msg.parts),
|
|
23
|
+
metadata: msg.metadata ? JSON.stringify(msg.metadata) : null
|
|
24
|
+
}))
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
async loadChat(chatId) {
|
|
29
|
+
const messages = await prisma.message.findMany({
|
|
30
|
+
where: { chatId },
|
|
31
|
+
orderBy: { createdAt: "asc" }
|
|
32
|
+
});
|
|
33
|
+
return messages.map((msg) => ({
|
|
34
|
+
id: msg.id,
|
|
35
|
+
role: msg.role,
|
|
36
|
+
parts: JSON.parse(msg.parts),
|
|
37
|
+
metadata: msg.metadata ? JSON.parse(msg.metadata) : void 0
|
|
38
|
+
}));
|
|
39
|
+
},
|
|
40
|
+
async listChats() {
|
|
41
|
+
return prisma.chat.findMany({
|
|
42
|
+
orderBy: { updatedAt: "desc" },
|
|
43
|
+
select: {
|
|
44
|
+
id: true,
|
|
45
|
+
title: true,
|
|
46
|
+
createdAt: true,
|
|
47
|
+
updatedAt: true
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
},
|
|
51
|
+
async deleteChat(chatId) {
|
|
52
|
+
await prisma.chat.delete({ where: { id: chatId } });
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function extractTitle(message) {
|
|
57
|
+
if (!message) return "New Chat";
|
|
58
|
+
const textPart = message.parts.find((p) => p.type === "text");
|
|
59
|
+
if (textPart && typeof textPart.text === "string") {
|
|
60
|
+
return textPart.text.slice(0, 100);
|
|
61
|
+
}
|
|
62
|
+
return "New Chat";
|
|
63
|
+
}
|
|
64
|
+
export {
|
|
65
|
+
createPrismaAdapter
|
|
66
|
+
};
|
|
67
|
+
//# sourceMappingURL=prisma.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/persistence/prisma-adapter.ts"],"sourcesContent":["import type { ChatAdapter, ChatSummary, UIMessageLike } from \"./types.js\";\n\n/**\n * Minimal PrismaClient interface — just the methods we use.\n * Avoids importing @prisma/client at the type level.\n */\ninterface PrismaLike {\n chat: {\n upsert: (args: {\n where: { id: string };\n create: { id: string; title: string };\n update: { title?: string };\n }) => Promise<unknown>;\n findMany: (args: {\n orderBy: { updatedAt: string };\n select: { id: boolean; title: boolean; createdAt: boolean; updatedAt: boolean };\n }) => Promise<ChatSummary[]>;\n delete: (args: { where: { id: string } }) => Promise<unknown>;\n };\n message: {\n count: (args: { where: { chatId: string } }) => Promise<number>;\n createMany: (args: {\n data: Array<{\n id: string;\n chatId: string;\n role: string;\n parts: string;\n metadata: string | null;\n }>;\n }) => Promise<unknown>;\n findMany: (args: {\n where: { chatId: string };\n orderBy: { createdAt: string };\n }) => Promise<Array<{\n id: string;\n role: string;\n parts: string;\n metadata: string | null;\n }>>;\n };\n}\n\n/**\n * Create a ChatAdapter backed by Prisma.\n *\n * @example\n * ```ts\n * import { createPrismaAdapter } from '@supyagent/sdk/prisma';\n * import { prisma } from '@/lib/prisma';\n *\n * const adapter = createPrismaAdapter(prisma);\n * ```\n */\nexport function createPrismaAdapter(prisma: PrismaLike): ChatAdapter {\n return {\n async saveChat(chatId: string, messages: UIMessageLike[]) {\n // Extract title from first user message\n const firstUserMsg = messages.find((m) => m.role === \"user\");\n const title = extractTitle(firstUserMsg);\n\n // Upsert the chat record\n await prisma.chat.upsert({\n where: { id: chatId },\n create: { id: chatId, title },\n update: { title },\n });\n\n // Append-only: count existing messages, create only new ones\n const existingCount = await prisma.message.count({\n where: { chatId },\n });\n\n const newMessages = messages.slice(existingCount);\n if (newMessages.length > 0) {\n await prisma.message.createMany({\n data: newMessages.map((msg) => ({\n id: msg.id,\n chatId,\n role: msg.role,\n parts: JSON.stringify(msg.parts),\n metadata: msg.metadata ? JSON.stringify(msg.metadata) : null,\n })),\n });\n }\n },\n\n async loadChat(chatId: string) {\n const messages = await prisma.message.findMany({\n where: { chatId },\n orderBy: { createdAt: \"asc\" },\n });\n\n return messages.map((msg) => ({\n id: msg.id,\n role: msg.role,\n parts: JSON.parse(msg.parts),\n metadata: msg.metadata ? JSON.parse(msg.metadata) : undefined,\n }));\n },\n\n async listChats() {\n return prisma.chat.findMany({\n orderBy: { updatedAt: \"desc\" },\n select: {\n id: true,\n title: true,\n createdAt: true,\n updatedAt: true,\n },\n });\n },\n\n async deleteChat(chatId: string) {\n await prisma.chat.delete({ where: { id: chatId } });\n },\n };\n}\n\nfunction extractTitle(message?: UIMessageLike): string {\n if (!message) return \"New Chat\";\n const textPart = message.parts.find((p) => p.type === \"text\");\n if (textPart && typeof textPart.text === \"string\") {\n return textPart.text.slice(0, 100);\n }\n return \"New Chat\";\n}\n"],"mappings":";AAqDO,SAAS,oBAAoB,QAAiC;AACnE,SAAO;AAAA,IACL,MAAM,SAAS,QAAgB,UAA2B;AAExD,YAAM,eAAe,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM;AAC3D,YAAM,QAAQ,aAAa,YAAY;AAGvC,YAAM,OAAO,KAAK,OAAO;AAAA,QACvB,OAAO,EAAE,IAAI,OAAO;AAAA,QACpB,QAAQ,EAAE,IAAI,QAAQ,MAAM;AAAA,QAC5B,QAAQ,EAAE,MAAM;AAAA,MAClB,CAAC;AAGD,YAAM,gBAAgB,MAAM,OAAO,QAAQ,MAAM;AAAA,QAC/C,OAAO,EAAE,OAAO;AAAA,MAClB,CAAC;AAED,YAAM,cAAc,SAAS,MAAM,aAAa;AAChD,UAAI,YAAY,SAAS,GAAG;AAC1B,cAAM,OAAO,QAAQ,WAAW;AAAA,UAC9B,MAAM,YAAY,IAAI,CAAC,SAAS;AAAA,YAC9B,IAAI,IAAI;AAAA,YACR;AAAA,YACA,MAAM,IAAI;AAAA,YACV,OAAO,KAAK,UAAU,IAAI,KAAK;AAAA,YAC/B,UAAU,IAAI,WAAW,KAAK,UAAU,IAAI,QAAQ,IAAI;AAAA,UAC1D,EAAE;AAAA,QACJ,CAAC;AAAA,MACH;AAAA,IACF;AAAA,IAEA,MAAM,SAAS,QAAgB;AAC7B,YAAM,WAAW,MAAM,OAAO,QAAQ,SAAS;AAAA,QAC7C,OAAO,EAAE,OAAO;AAAA,QAChB,SAAS,EAAE,WAAW,MAAM;AAAA,MAC9B,CAAC;AAED,aAAO,SAAS,IAAI,CAAC,SAAS;AAAA,QAC5B,IAAI,IAAI;AAAA,QACR,MAAM,IAAI;AAAA,QACV,OAAO,KAAK,MAAM,IAAI,KAAK;AAAA,QAC3B,UAAU,IAAI,WAAW,KAAK,MAAM,IAAI,QAAQ,IAAI;AAAA,MACtD,EAAE;AAAA,IACJ;AAAA,IAEA,MAAM,YAAY;AAChB,aAAO,OAAO,KAAK,SAAS;AAAA,QAC1B,SAAS,EAAE,WAAW,OAAO;AAAA,QAC7B,QAAQ;AAAA,UACN,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,WAAW;AAAA,UACX,WAAW;AAAA,QACb;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,WAAW,QAAgB;AAC/B,YAAM,OAAO,KAAK,OAAO,EAAE,OAAO,EAAE,IAAI,OAAO,EAAE,CAAC;AAAA,IACpD;AAAA,EACF;AACF;AAEA,SAAS,aAAa,SAAiC;AACrD,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,WAAW,QAAQ,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM;AAC5D,MAAI,YAAY,OAAO,SAAS,SAAS,UAAU;AACjD,WAAO,SAAS,KAAK,MAAM,GAAG,GAAG;AAAA,EACnC;AACA,SAAO;AACT;","names":[]}
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
interface ToolCallPart {
|
|
4
|
+
type: string;
|
|
5
|
+
toolInvocation?: {
|
|
6
|
+
toolName: string;
|
|
7
|
+
state: string;
|
|
8
|
+
args?: Record<string, unknown>;
|
|
9
|
+
result?: unknown;
|
|
10
|
+
};
|
|
11
|
+
toolName?: string;
|
|
12
|
+
state?: string;
|
|
13
|
+
args?: Record<string, unknown>;
|
|
14
|
+
}
|
|
15
|
+
interface SupyagentToolCallProps {
|
|
16
|
+
part: ToolCallPart;
|
|
17
|
+
}
|
|
18
|
+
declare function SupyagentToolCall({ part }: SupyagentToolCallProps): react_jsx_runtime.JSX.Element;
|
|
19
|
+
|
|
20
|
+
interface ToolResultPart {
|
|
21
|
+
type: string;
|
|
22
|
+
toolInvocation?: {
|
|
23
|
+
toolName: string;
|
|
24
|
+
state: string;
|
|
25
|
+
result?: unknown;
|
|
26
|
+
};
|
|
27
|
+
toolName?: string;
|
|
28
|
+
state?: string;
|
|
29
|
+
result?: unknown;
|
|
30
|
+
}
|
|
31
|
+
interface SupyagentToolResultProps {
|
|
32
|
+
part: ToolResultPart;
|
|
33
|
+
}
|
|
34
|
+
declare function SupyagentToolResult({ part }: SupyagentToolResultProps): react_jsx_runtime.JSX.Element | null;
|
|
35
|
+
|
|
36
|
+
interface ProviderIconProps {
|
|
37
|
+
toolName: string;
|
|
38
|
+
className?: string;
|
|
39
|
+
}
|
|
40
|
+
declare function ProviderIcon({ toolName, className }: ProviderIconProps): react_jsx_runtime.JSX.Element;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Extract provider/service prefix from a tool name.
|
|
44
|
+
* Tool names follow `{service}_{action}` convention.
|
|
45
|
+
*/
|
|
46
|
+
declare function getProviderFromToolName(toolName: string): string;
|
|
47
|
+
/**
|
|
48
|
+
* Convert a tool name like "gmail_list_messages" to "List messages".
|
|
49
|
+
*/
|
|
50
|
+
declare function humanizeToolName(toolName: string): string;
|
|
51
|
+
/**
|
|
52
|
+
* Get a display label for a provider.
|
|
53
|
+
*/
|
|
54
|
+
declare function getProviderLabel(provider: string): string;
|
|
55
|
+
|
|
56
|
+
export { ProviderIcon, SupyagentToolCall, SupyagentToolResult, getProviderFromToolName, getProviderLabel, humanizeToolName };
|
package/dist/react.js
ADDED
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/ui/tool-call.tsx
|
|
4
|
+
import { useState } from "react";
|
|
5
|
+
import { ChevronDown, ChevronRight, Check, AlertCircle, Loader2 } from "lucide-react";
|
|
6
|
+
|
|
7
|
+
// src/ui/provider-icon.tsx
|
|
8
|
+
import {
|
|
9
|
+
Mail,
|
|
10
|
+
Calendar,
|
|
11
|
+
HardDrive,
|
|
12
|
+
MessageSquare,
|
|
13
|
+
Github,
|
|
14
|
+
Wrench,
|
|
15
|
+
Bell,
|
|
16
|
+
FileText,
|
|
17
|
+
Table2,
|
|
18
|
+
Presentation
|
|
19
|
+
} from "lucide-react";
|
|
20
|
+
|
|
21
|
+
// src/ui/utils.ts
|
|
22
|
+
function getProviderFromToolName(toolName) {
|
|
23
|
+
const idx = toolName.indexOf("_");
|
|
24
|
+
return idx > 0 ? toolName.slice(0, idx) : toolName;
|
|
25
|
+
}
|
|
26
|
+
function humanizeToolName(toolName) {
|
|
27
|
+
const idx = toolName.indexOf("_");
|
|
28
|
+
if (idx < 0) return toolName;
|
|
29
|
+
const action = toolName.slice(idx + 1);
|
|
30
|
+
const words = action.replace(/_/g, " ");
|
|
31
|
+
return words.charAt(0).toUpperCase() + words.slice(1);
|
|
32
|
+
}
|
|
33
|
+
var PROVIDER_LABELS = {
|
|
34
|
+
gmail: "Gmail",
|
|
35
|
+
calendar: "Calendar",
|
|
36
|
+
drive: "Drive",
|
|
37
|
+
slack: "Slack",
|
|
38
|
+
github: "GitHub",
|
|
39
|
+
discord: "Discord",
|
|
40
|
+
notion: "Notion",
|
|
41
|
+
hubspot: "HubSpot",
|
|
42
|
+
linkedin: "LinkedIn",
|
|
43
|
+
twitter: "Twitter",
|
|
44
|
+
telegram: "Telegram",
|
|
45
|
+
microsoft: "Microsoft",
|
|
46
|
+
outlook: "Outlook",
|
|
47
|
+
onedrive: "OneDrive",
|
|
48
|
+
whatsapp: "WhatsApp",
|
|
49
|
+
inbox: "Inbox",
|
|
50
|
+
docs: "Docs",
|
|
51
|
+
sheets: "Sheets",
|
|
52
|
+
slides: "Slides"
|
|
53
|
+
};
|
|
54
|
+
function getProviderLabel(provider) {
|
|
55
|
+
return PROVIDER_LABELS[provider] || provider.charAt(0).toUpperCase() + provider.slice(1);
|
|
56
|
+
}
|
|
57
|
+
function getFormatterType(toolName) {
|
|
58
|
+
const provider = getProviderFromToolName(toolName);
|
|
59
|
+
switch (provider) {
|
|
60
|
+
case "gmail":
|
|
61
|
+
return "email";
|
|
62
|
+
case "calendar":
|
|
63
|
+
return "calendar";
|
|
64
|
+
case "slack":
|
|
65
|
+
return "slack";
|
|
66
|
+
case "github":
|
|
67
|
+
return "github";
|
|
68
|
+
case "drive":
|
|
69
|
+
return "drive";
|
|
70
|
+
default:
|
|
71
|
+
return "generic";
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// src/ui/provider-icon.tsx
|
|
76
|
+
import { jsx } from "react/jsx-runtime";
|
|
77
|
+
var ICON_MAP = {
|
|
78
|
+
gmail: Mail,
|
|
79
|
+
calendar: Calendar,
|
|
80
|
+
drive: HardDrive,
|
|
81
|
+
slack: MessageSquare,
|
|
82
|
+
github: Github,
|
|
83
|
+
discord: MessageSquare,
|
|
84
|
+
notion: FileText,
|
|
85
|
+
inbox: Bell,
|
|
86
|
+
docs: FileText,
|
|
87
|
+
sheets: Table2,
|
|
88
|
+
slides: Presentation
|
|
89
|
+
};
|
|
90
|
+
function ProviderIcon({ toolName, className = "h-4 w-4" }) {
|
|
91
|
+
const provider = getProviderFromToolName(toolName);
|
|
92
|
+
const Icon = ICON_MAP[provider] || Wrench;
|
|
93
|
+
return /* @__PURE__ */ jsx(Icon, { className });
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// src/ui/tool-call.tsx
|
|
97
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
98
|
+
function SupyagentToolCall({ part }) {
|
|
99
|
+
const [expanded, setExpanded] = useState(false);
|
|
100
|
+
const toolName = part.toolName || part.toolInvocation?.toolName || "unknown";
|
|
101
|
+
const state = part.state || part.toolInvocation?.state || "input-available";
|
|
102
|
+
const args = part.args || part.toolInvocation?.args;
|
|
103
|
+
const provider = getProviderFromToolName(toolName);
|
|
104
|
+
const providerLabel = getProviderLabel(provider);
|
|
105
|
+
const actionLabel = humanizeToolName(toolName);
|
|
106
|
+
const isStreaming = state === "input-streaming";
|
|
107
|
+
const isError = state === "output-error";
|
|
108
|
+
const isDone = state === "output-available";
|
|
109
|
+
return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-zinc-800 bg-zinc-900/50 overflow-hidden", children: [
|
|
110
|
+
/* @__PURE__ */ jsxs(
|
|
111
|
+
"button",
|
|
112
|
+
{
|
|
113
|
+
type: "button",
|
|
114
|
+
onClick: () => args && setExpanded(!expanded),
|
|
115
|
+
className: "flex items-center gap-2 w-full px-3 py-2 text-left hover:bg-zinc-800/50 transition-colors",
|
|
116
|
+
children: [
|
|
117
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
118
|
+
/* @__PURE__ */ jsx2(ProviderIcon, { toolName, className: "h-4 w-4 text-zinc-400" }),
|
|
119
|
+
isStreaming && /* @__PURE__ */ jsx2(Loader2, { className: "absolute -top-1 -right-1 h-3 w-3 text-blue-400 animate-spin" })
|
|
120
|
+
] }),
|
|
121
|
+
/* @__PURE__ */ jsx2("span", { className: "text-xs text-zinc-500", children: providerLabel }),
|
|
122
|
+
/* @__PURE__ */ jsx2("span", { className: "text-sm text-zinc-300 flex-1", children: actionLabel }),
|
|
123
|
+
isDone && /* @__PURE__ */ jsx2(Check, { className: "h-3.5 w-3.5 text-green-400" }),
|
|
124
|
+
isError && /* @__PURE__ */ jsx2(AlertCircle, { className: "h-3.5 w-3.5 text-red-400" }),
|
|
125
|
+
isStreaming && /* @__PURE__ */ jsx2("span", { className: "text-xs text-zinc-500 animate-pulse", children: "Running..." }),
|
|
126
|
+
args && (expanded ? /* @__PURE__ */ jsx2(ChevronDown, { className: "h-3.5 w-3.5 text-zinc-500" }) : /* @__PURE__ */ jsx2(ChevronRight, { className: "h-3.5 w-3.5 text-zinc-500" }))
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
),
|
|
130
|
+
expanded && args && /* @__PURE__ */ jsx2("div", { className: "border-t border-zinc-800 px-3 py-2", children: /* @__PURE__ */ jsx2("pre", { className: "text-xs text-zinc-400 overflow-x-auto", children: JSON.stringify(args, null, 2) }) })
|
|
131
|
+
] });
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// src/ui/formatters/email.tsx
|
|
135
|
+
import { Mail as Mail2, Paperclip } from "lucide-react";
|
|
136
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
137
|
+
function isEmailData(data) {
|
|
138
|
+
return typeof data === "object" && data !== null && ("subject" in data || "from" in data || "snippet" in data);
|
|
139
|
+
}
|
|
140
|
+
function EmailCard({ email }) {
|
|
141
|
+
return /* @__PURE__ */ jsxs2("div", { className: "rounded-lg border border-zinc-800 bg-zinc-900/50 p-3 space-y-2", children: [
|
|
142
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-start gap-2", children: [
|
|
143
|
+
/* @__PURE__ */ jsx3(Mail2, { className: "h-4 w-4 text-zinc-400 mt-0.5 shrink-0" }),
|
|
144
|
+
/* @__PURE__ */ jsxs2("div", { className: "min-w-0 flex-1", children: [
|
|
145
|
+
/* @__PURE__ */ jsx3("p", { className: "text-sm font-medium text-zinc-200 truncate", children: email.subject || "No subject" }),
|
|
146
|
+
email.from && /* @__PURE__ */ jsx3("p", { className: "text-xs text-zinc-400 truncate", children: email.from })
|
|
147
|
+
] }),
|
|
148
|
+
email.hasAttachments && /* @__PURE__ */ jsx3(Paperclip, { className: "h-3.5 w-3.5 text-zinc-500 shrink-0" })
|
|
149
|
+
] }),
|
|
150
|
+
email.snippet && /* @__PURE__ */ jsx3("p", { className: "text-xs text-zinc-400 line-clamp-2", children: email.snippet }),
|
|
151
|
+
email.date && /* @__PURE__ */ jsx3("p", { className: "text-xs text-zinc-500", children: email.date })
|
|
152
|
+
] });
|
|
153
|
+
}
|
|
154
|
+
function EmailFormatter({ data }) {
|
|
155
|
+
if (isEmailData(data)) {
|
|
156
|
+
return /* @__PURE__ */ jsx3(EmailCard, { email: data });
|
|
157
|
+
}
|
|
158
|
+
if (Array.isArray(data)) {
|
|
159
|
+
const emails = data.filter(isEmailData);
|
|
160
|
+
if (emails.length > 0) {
|
|
161
|
+
return /* @__PURE__ */ jsx3("div", { className: "space-y-2", children: emails.map((email, i) => /* @__PURE__ */ jsx3(EmailCard, { email }, email.id || i)) });
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (typeof data === "object" && data !== null && "messages" in data) {
|
|
165
|
+
const messages = data.messages;
|
|
166
|
+
if (Array.isArray(messages)) {
|
|
167
|
+
const emails = messages.filter(isEmailData);
|
|
168
|
+
if (emails.length > 0) {
|
|
169
|
+
return /* @__PURE__ */ jsx3("div", { className: "space-y-2", children: emails.map((email, i) => /* @__PURE__ */ jsx3(EmailCard, { email }, email.id || i)) });
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return /* @__PURE__ */ jsx3("pre", { className: "rounded-lg border border-zinc-800 bg-zinc-950 p-3 text-xs text-zinc-300 overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// src/ui/formatters/calendar-event.tsx
|
|
177
|
+
import { Calendar as Calendar2, MapPin, Users } from "lucide-react";
|
|
178
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
179
|
+
function isCalendarEvent(data) {
|
|
180
|
+
return typeof data === "object" && data !== null && ("summary" in data || "start" in data);
|
|
181
|
+
}
|
|
182
|
+
function formatDateTime(dt) {
|
|
183
|
+
if (!dt) return "";
|
|
184
|
+
const raw = dt.dateTime || dt.date;
|
|
185
|
+
if (!raw) return "";
|
|
186
|
+
try {
|
|
187
|
+
const date = new Date(raw);
|
|
188
|
+
return dt.dateTime ? date.toLocaleString(void 0, { dateStyle: "medium", timeStyle: "short" }) : date.toLocaleDateString(void 0, { dateStyle: "medium" });
|
|
189
|
+
} catch {
|
|
190
|
+
return raw;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
function EventCard({ event }) {
|
|
194
|
+
const startStr = formatDateTime(event.start);
|
|
195
|
+
const endStr = formatDateTime(event.end);
|
|
196
|
+
return /* @__PURE__ */ jsxs3("div", { className: "rounded-lg border border-zinc-800 bg-zinc-900/50 p-3 space-y-2", children: [
|
|
197
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-start gap-2", children: [
|
|
198
|
+
/* @__PURE__ */ jsx4(Calendar2, { className: "h-4 w-4 text-zinc-400 mt-0.5 shrink-0" }),
|
|
199
|
+
/* @__PURE__ */ jsxs3("div", { className: "min-w-0 flex-1", children: [
|
|
200
|
+
/* @__PURE__ */ jsx4("p", { className: "text-sm font-medium text-zinc-200", children: event.summary || "Untitled event" }),
|
|
201
|
+
startStr && /* @__PURE__ */ jsxs3("p", { className: "text-xs text-zinc-400", children: [
|
|
202
|
+
startStr,
|
|
203
|
+
endStr ? ` \u2192 ${endStr}` : ""
|
|
204
|
+
] })
|
|
205
|
+
] })
|
|
206
|
+
] }),
|
|
207
|
+
event.location && /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-1.5 text-xs text-zinc-400", children: [
|
|
208
|
+
/* @__PURE__ */ jsx4(MapPin, { className: "h-3 w-3 shrink-0" }),
|
|
209
|
+
/* @__PURE__ */ jsx4("span", { className: "truncate", children: event.location })
|
|
210
|
+
] }),
|
|
211
|
+
event.attendees && event.attendees.length > 0 && /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-1.5 text-xs text-zinc-400", children: [
|
|
212
|
+
/* @__PURE__ */ jsx4(Users, { className: "h-3 w-3 shrink-0" }),
|
|
213
|
+
/* @__PURE__ */ jsx4("span", { className: "truncate", children: event.attendees.map((a) => a.displayName || a.email).join(", ") })
|
|
214
|
+
] })
|
|
215
|
+
] });
|
|
216
|
+
}
|
|
217
|
+
function CalendarEventFormatter({ data }) {
|
|
218
|
+
if (isCalendarEvent(data)) {
|
|
219
|
+
return /* @__PURE__ */ jsx4(EventCard, { event: data });
|
|
220
|
+
}
|
|
221
|
+
if (Array.isArray(data)) {
|
|
222
|
+
const events = data.filter(isCalendarEvent);
|
|
223
|
+
if (events.length > 0) {
|
|
224
|
+
return /* @__PURE__ */ jsx4("div", { className: "space-y-2", children: events.map((event, i) => /* @__PURE__ */ jsx4(EventCard, { event }, event.id || i)) });
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
if (typeof data === "object" && data !== null && "events" in data) {
|
|
228
|
+
const events = data.events;
|
|
229
|
+
if (Array.isArray(events)) {
|
|
230
|
+
const calEvents = events.filter(isCalendarEvent);
|
|
231
|
+
if (calEvents.length > 0) {
|
|
232
|
+
return /* @__PURE__ */ jsx4("div", { className: "space-y-2", children: calEvents.map((event, i) => /* @__PURE__ */ jsx4(EventCard, { event }, event.id || i)) });
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return /* @__PURE__ */ jsx4("pre", { className: "rounded-lg border border-zinc-800 bg-zinc-950 p-3 text-xs text-zinc-300 overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// src/ui/formatters/slack-message.tsx
|
|
240
|
+
import { MessageSquare as MessageSquare2, Hash } from "lucide-react";
|
|
241
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
242
|
+
function isSlackMessage(data) {
|
|
243
|
+
return typeof data === "object" && data !== null && ("text" in data || "channel" in data);
|
|
244
|
+
}
|
|
245
|
+
function MessageBubble({ message }) {
|
|
246
|
+
return /* @__PURE__ */ jsxs4("div", { className: "rounded-lg border border-zinc-800 bg-zinc-900/50 p-3 space-y-1.5", children: [
|
|
247
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
|
|
248
|
+
/* @__PURE__ */ jsx5(MessageSquare2, { className: "h-4 w-4 text-zinc-400 shrink-0" }),
|
|
249
|
+
message.channel && /* @__PURE__ */ jsxs4("span", { className: "flex items-center gap-0.5 text-xs text-zinc-400", children: [
|
|
250
|
+
/* @__PURE__ */ jsx5(Hash, { className: "h-3 w-3" }),
|
|
251
|
+
message.channel
|
|
252
|
+
] }),
|
|
253
|
+
message.user && /* @__PURE__ */ jsx5("span", { className: "text-xs text-zinc-500", children: message.user })
|
|
254
|
+
] }),
|
|
255
|
+
message.text && /* @__PURE__ */ jsx5("p", { className: "text-sm text-zinc-300", children: message.text })
|
|
256
|
+
] });
|
|
257
|
+
}
|
|
258
|
+
function SlackMessageFormatter({ data }) {
|
|
259
|
+
if (isSlackMessage(data)) {
|
|
260
|
+
return /* @__PURE__ */ jsx5(MessageBubble, { message: data });
|
|
261
|
+
}
|
|
262
|
+
if (Array.isArray(data)) {
|
|
263
|
+
const messages = data.filter(isSlackMessage);
|
|
264
|
+
if (messages.length > 0) {
|
|
265
|
+
return /* @__PURE__ */ jsx5("div", { className: "space-y-2", children: messages.map((msg, i) => /* @__PURE__ */ jsx5(MessageBubble, { message: msg }, msg.ts || i)) });
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
if (typeof data === "object" && data !== null && "messages" in data) {
|
|
269
|
+
const messages = data.messages;
|
|
270
|
+
if (Array.isArray(messages)) {
|
|
271
|
+
const slackMsgs = messages.filter(isSlackMessage);
|
|
272
|
+
if (slackMsgs.length > 0) {
|
|
273
|
+
return /* @__PURE__ */ jsx5("div", { className: "space-y-2", children: slackMsgs.map((msg, i) => /* @__PURE__ */ jsx5(MessageBubble, { message: msg }, msg.ts || i)) });
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return /* @__PURE__ */ jsx5("pre", { className: "rounded-lg border border-zinc-800 bg-zinc-950 p-3 text-xs text-zinc-300 overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// src/ui/formatters/github.tsx
|
|
281
|
+
import { CircleDot, GitPullRequest } from "lucide-react";
|
|
282
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
283
|
+
function isGithubItem(data) {
|
|
284
|
+
return typeof data === "object" && data !== null && ("title" in data || "number" in data);
|
|
285
|
+
}
|
|
286
|
+
function GithubCard({ item }) {
|
|
287
|
+
const isPR = !!item.pull_request;
|
|
288
|
+
const stateColor = item.state === "open" ? "text-green-400" : item.state === "closed" ? "text-red-400" : "text-zinc-400";
|
|
289
|
+
return /* @__PURE__ */ jsxs5("div", { className: "rounded-lg border border-zinc-800 bg-zinc-900/50 p-3 space-y-1.5", children: [
|
|
290
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-start gap-2", children: [
|
|
291
|
+
isPR ? /* @__PURE__ */ jsx6(GitPullRequest, { className: `h-4 w-4 mt-0.5 shrink-0 ${stateColor}` }) : /* @__PURE__ */ jsx6(CircleDot, { className: `h-4 w-4 mt-0.5 shrink-0 ${stateColor}` }),
|
|
292
|
+
/* @__PURE__ */ jsxs5("div", { className: "min-w-0 flex-1", children: [
|
|
293
|
+
/* @__PURE__ */ jsxs5("p", { className: "text-sm font-medium text-zinc-200", children: [
|
|
294
|
+
item.title,
|
|
295
|
+
item.number && /* @__PURE__ */ jsxs5("span", { className: "text-zinc-500 font-normal", children: [
|
|
296
|
+
" #",
|
|
297
|
+
item.number
|
|
298
|
+
] })
|
|
299
|
+
] }),
|
|
300
|
+
item.user?.login && /* @__PURE__ */ jsx6("p", { className: "text-xs text-zinc-400", children: item.user.login })
|
|
301
|
+
] })
|
|
302
|
+
] }),
|
|
303
|
+
item.body && /* @__PURE__ */ jsx6("p", { className: "text-xs text-zinc-400 line-clamp-2", children: item.body })
|
|
304
|
+
] });
|
|
305
|
+
}
|
|
306
|
+
function GithubFormatter({ data }) {
|
|
307
|
+
if (isGithubItem(data)) {
|
|
308
|
+
return /* @__PURE__ */ jsx6(GithubCard, { item: data });
|
|
309
|
+
}
|
|
310
|
+
if (Array.isArray(data)) {
|
|
311
|
+
const items = data.filter(isGithubItem);
|
|
312
|
+
if (items.length > 0) {
|
|
313
|
+
return /* @__PURE__ */ jsx6("div", { className: "space-y-2", children: items.map((item, i) => /* @__PURE__ */ jsx6(GithubCard, { item }, item.number || i)) });
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return /* @__PURE__ */ jsx6("pre", { className: "rounded-lg border border-zinc-800 bg-zinc-950 p-3 text-xs text-zinc-300 overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// src/ui/formatters/drive-file.tsx
|
|
320
|
+
import { FileText as FileText2, Folder, Image, Film, FileSpreadsheet } from "lucide-react";
|
|
321
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
322
|
+
function isDriveFile(data) {
|
|
323
|
+
return typeof data === "object" && data !== null && ("name" in data || "mimeType" in data);
|
|
324
|
+
}
|
|
325
|
+
function getFileIcon(mimeType) {
|
|
326
|
+
if (!mimeType) return FileText2;
|
|
327
|
+
if (mimeType.includes("folder")) return Folder;
|
|
328
|
+
if (mimeType.includes("image")) return Image;
|
|
329
|
+
if (mimeType.includes("video")) return Film;
|
|
330
|
+
if (mimeType.includes("spreadsheet") || mimeType.includes("excel")) return FileSpreadsheet;
|
|
331
|
+
return FileText2;
|
|
332
|
+
}
|
|
333
|
+
function FileCard({ file }) {
|
|
334
|
+
const Icon = getFileIcon(file.mimeType);
|
|
335
|
+
return /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-3 rounded-lg border border-zinc-800 bg-zinc-900/50 p-3", children: [
|
|
336
|
+
/* @__PURE__ */ jsx7(Icon, { className: "h-4 w-4 text-zinc-400 shrink-0" }),
|
|
337
|
+
/* @__PURE__ */ jsxs6("div", { className: "min-w-0 flex-1", children: [
|
|
338
|
+
/* @__PURE__ */ jsx7("p", { className: "text-sm text-zinc-200 truncate", children: file.name || "Untitled" }),
|
|
339
|
+
file.modifiedTime && /* @__PURE__ */ jsx7("p", { className: "text-xs text-zinc-500", children: new Date(file.modifiedTime).toLocaleDateString() })
|
|
340
|
+
] })
|
|
341
|
+
] });
|
|
342
|
+
}
|
|
343
|
+
function DriveFileFormatter({ data }) {
|
|
344
|
+
if (isDriveFile(data)) {
|
|
345
|
+
return /* @__PURE__ */ jsx7(FileCard, { file: data });
|
|
346
|
+
}
|
|
347
|
+
if (Array.isArray(data)) {
|
|
348
|
+
const files = data.filter(isDriveFile);
|
|
349
|
+
if (files.length > 0) {
|
|
350
|
+
return /* @__PURE__ */ jsx7("div", { className: "space-y-1.5", children: files.map((file, i) => /* @__PURE__ */ jsx7(FileCard, { file }, file.id || i)) });
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
if (typeof data === "object" && data !== null && "files" in data) {
|
|
354
|
+
const files = data.files;
|
|
355
|
+
if (Array.isArray(files)) {
|
|
356
|
+
const driveFiles = files.filter(isDriveFile);
|
|
357
|
+
if (driveFiles.length > 0) {
|
|
358
|
+
return /* @__PURE__ */ jsx7("div", { className: "space-y-1.5", children: driveFiles.map((file, i) => /* @__PURE__ */ jsx7(FileCard, { file }, file.id || i)) });
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return /* @__PURE__ */ jsx7("pre", { className: "rounded-lg border border-zinc-800 bg-zinc-950 p-3 text-xs text-zinc-300 overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// src/ui/formatters/generic.tsx
|
|
366
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
367
|
+
function GenericFormatter({ data }) {
|
|
368
|
+
if (data === null || data === void 0) {
|
|
369
|
+
return /* @__PURE__ */ jsx8("p", { className: "text-sm text-zinc-500 italic", children: "No data returned" });
|
|
370
|
+
}
|
|
371
|
+
return /* @__PURE__ */ jsx8("pre", { className: "rounded-lg border border-zinc-800 bg-zinc-950 p-3 text-xs text-zinc-300 overflow-x-auto max-h-96 overflow-y-auto", children: JSON.stringify(data, null, 2) });
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// src/ui/tool-result.tsx
|
|
375
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
376
|
+
function SupyagentToolResult({ part }) {
|
|
377
|
+
const state = part.state ?? part.toolInvocation?.state;
|
|
378
|
+
const result = "result" in part ? part.result : part.toolInvocation?.result;
|
|
379
|
+
const toolName = part.toolName ?? part.toolInvocation?.toolName ?? "unknown";
|
|
380
|
+
if (state !== "output-available" || result === void 0) {
|
|
381
|
+
return null;
|
|
382
|
+
}
|
|
383
|
+
const formatterType = getFormatterType(toolName);
|
|
384
|
+
switch (formatterType) {
|
|
385
|
+
case "email":
|
|
386
|
+
return /* @__PURE__ */ jsx9(EmailFormatter, { data: result });
|
|
387
|
+
case "calendar":
|
|
388
|
+
return /* @__PURE__ */ jsx9(CalendarEventFormatter, { data: result });
|
|
389
|
+
case "slack":
|
|
390
|
+
return /* @__PURE__ */ jsx9(SlackMessageFormatter, { data: result });
|
|
391
|
+
case "github":
|
|
392
|
+
return /* @__PURE__ */ jsx9(GithubFormatter, { data: result });
|
|
393
|
+
case "drive":
|
|
394
|
+
return /* @__PURE__ */ jsx9(DriveFileFormatter, { data: result });
|
|
395
|
+
default:
|
|
396
|
+
return /* @__PURE__ */ jsx9(GenericFormatter, { data: result });
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
export {
|
|
400
|
+
ProviderIcon,
|
|
401
|
+
SupyagentToolCall,
|
|
402
|
+
SupyagentToolResult,
|
|
403
|
+
getProviderFromToolName,
|
|
404
|
+
getProviderLabel,
|
|
405
|
+
humanizeToolName
|
|
406
|
+
};
|
|
407
|
+
//# sourceMappingURL=react.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ui/tool-call.tsx","../src/ui/provider-icon.tsx","../src/ui/utils.ts","../src/ui/formatters/email.tsx","../src/ui/formatters/calendar-event.tsx","../src/ui/formatters/slack-message.tsx","../src/ui/formatters/github.tsx","../src/ui/formatters/drive-file.tsx","../src/ui/formatters/generic.tsx","../src/ui/tool-result.tsx"],"sourcesContent":["import React, { useState } from \"react\";\nimport { ChevronDown, ChevronRight, Check, AlertCircle, Loader2 } from \"lucide-react\";\nimport { ProviderIcon } from \"./provider-icon.js\";\nimport { humanizeToolName, getProviderLabel, getProviderFromToolName } from \"./utils.js\";\n\ninterface ToolCallPart {\n type: string;\n toolInvocation?: {\n toolName: string;\n state: string;\n args?: Record<string, unknown>;\n result?: unknown;\n };\n // AI SDK v4 tool-invocation parts\n toolName?: string;\n state?: string;\n args?: Record<string, unknown>;\n}\n\ninterface SupyagentToolCallProps {\n part: ToolCallPart;\n}\n\nexport function SupyagentToolCall({ part }: SupyagentToolCallProps) {\n const [expanded, setExpanded] = useState(false);\n\n const toolName = part.toolName || part.toolInvocation?.toolName || \"unknown\";\n const state = part.state || part.toolInvocation?.state || \"input-available\";\n const args = part.args || part.toolInvocation?.args;\n\n const provider = getProviderFromToolName(toolName);\n const providerLabel = getProviderLabel(provider);\n const actionLabel = humanizeToolName(toolName);\n\n const isStreaming = state === \"input-streaming\";\n const isError = state === \"output-error\";\n const isDone = state === \"output-available\";\n\n return (\n <div className=\"rounded-lg border border-zinc-800 bg-zinc-900/50 overflow-hidden\">\n <button\n type=\"button\"\n onClick={() => args && setExpanded(!expanded)}\n className=\"flex items-center gap-2 w-full px-3 py-2 text-left hover:bg-zinc-800/50 transition-colors\"\n >\n <div className=\"relative\">\n <ProviderIcon toolName={toolName} className=\"h-4 w-4 text-zinc-400\" />\n {isStreaming && (\n <Loader2 className=\"absolute -top-1 -right-1 h-3 w-3 text-blue-400 animate-spin\" />\n )}\n </div>\n\n <span className=\"text-xs text-zinc-500\">{providerLabel}</span>\n <span className=\"text-sm text-zinc-300 flex-1\">{actionLabel}</span>\n\n {isDone && <Check className=\"h-3.5 w-3.5 text-green-400\" />}\n {isError && <AlertCircle className=\"h-3.5 w-3.5 text-red-400\" />}\n {isStreaming && (\n <span className=\"text-xs text-zinc-500 animate-pulse\">Running...</span>\n )}\n\n {args && (\n expanded\n ? <ChevronDown className=\"h-3.5 w-3.5 text-zinc-500\" />\n : <ChevronRight className=\"h-3.5 w-3.5 text-zinc-500\" />\n )}\n </button>\n\n {expanded && args && (\n <div className=\"border-t border-zinc-800 px-3 py-2\">\n <pre className=\"text-xs text-zinc-400 overflow-x-auto\">\n {JSON.stringify(args, null, 2)}\n </pre>\n </div>\n )}\n </div>\n );\n}\n","import React from \"react\";\nimport {\n Mail,\n Calendar,\n HardDrive,\n MessageSquare,\n Github,\n type LucideIcon,\n Wrench,\n Bell,\n FileText,\n Table2,\n Presentation,\n} from \"lucide-react\";\nimport { getProviderFromToolName } from \"./utils.js\";\n\nconst ICON_MAP: Record<string, LucideIcon> = {\n gmail: Mail,\n calendar: Calendar,\n drive: HardDrive,\n slack: MessageSquare,\n github: Github,\n discord: MessageSquare,\n notion: FileText,\n inbox: Bell,\n docs: FileText,\n sheets: Table2,\n slides: Presentation,\n};\n\ninterface ProviderIconProps {\n toolName: string;\n className?: string;\n}\n\nexport function ProviderIcon({ toolName, className = \"h-4 w-4\" }: ProviderIconProps) {\n const provider = getProviderFromToolName(toolName);\n const Icon = ICON_MAP[provider] || Wrench;\n return <Icon className={className} />;\n}\n","/**\n * Extract provider/service prefix from a tool name.\n * Tool names follow `{service}_{action}` convention.\n */\nexport function getProviderFromToolName(toolName: string): string {\n const idx = toolName.indexOf(\"_\");\n return idx > 0 ? toolName.slice(0, idx) : toolName;\n}\n\n/**\n * Convert a tool name like \"gmail_list_messages\" to \"List messages\".\n */\nexport function humanizeToolName(toolName: string): string {\n const idx = toolName.indexOf(\"_\");\n if (idx < 0) return toolName;\n const action = toolName.slice(idx + 1);\n const words = action.replace(/_/g, \" \");\n return words.charAt(0).toUpperCase() + words.slice(1);\n}\n\n/**\n * Provider display names.\n */\nexport const PROVIDER_LABELS: Record<string, string> = {\n gmail: \"Gmail\",\n calendar: \"Calendar\",\n drive: \"Drive\",\n slack: \"Slack\",\n github: \"GitHub\",\n discord: \"Discord\",\n notion: \"Notion\",\n hubspot: \"HubSpot\",\n linkedin: \"LinkedIn\",\n twitter: \"Twitter\",\n telegram: \"Telegram\",\n microsoft: \"Microsoft\",\n outlook: \"Outlook\",\n onedrive: \"OneDrive\",\n whatsapp: \"WhatsApp\",\n inbox: \"Inbox\",\n docs: \"Docs\",\n sheets: \"Sheets\",\n slides: \"Slides\",\n};\n\n/**\n * Get a display label for a provider.\n */\nexport function getProviderLabel(provider: string): string {\n return PROVIDER_LABELS[provider] || provider.charAt(0).toUpperCase() + provider.slice(1);\n}\n\n/**\n * Determine which formatter to use based on tool name prefix.\n */\nexport type FormatterType =\n | \"email\"\n | \"calendar\"\n | \"slack\"\n | \"github\"\n | \"drive\"\n | \"generic\";\n\nexport function getFormatterType(toolName: string): FormatterType {\n const provider = getProviderFromToolName(toolName);\n switch (provider) {\n case \"gmail\":\n return \"email\";\n case \"calendar\":\n return \"calendar\";\n case \"slack\":\n return \"slack\";\n case \"github\":\n return \"github\";\n case \"drive\":\n return \"drive\";\n default:\n return \"generic\";\n }\n}\n","import React from \"react\";\nimport { Mail, Paperclip } from \"lucide-react\";\n\ninterface EmailData {\n id?: string;\n subject?: string;\n from?: string;\n to?: string;\n date?: string;\n snippet?: string;\n body?: string;\n hasAttachments?: boolean;\n labels?: string[];\n}\n\ninterface EmailFormatterProps {\n data: unknown;\n}\n\nfunction isEmailData(data: unknown): data is EmailData {\n return typeof data === \"object\" && data !== null && (\"subject\" in data || \"from\" in data || \"snippet\" in data);\n}\n\nfunction EmailCard({ email }: { email: EmailData }) {\n return (\n <div className=\"rounded-lg border border-zinc-800 bg-zinc-900/50 p-3 space-y-2\">\n <div className=\"flex items-start gap-2\">\n <Mail className=\"h-4 w-4 text-zinc-400 mt-0.5 shrink-0\" />\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium text-zinc-200 truncate\">\n {email.subject || \"No subject\"}\n </p>\n {email.from && (\n <p className=\"text-xs text-zinc-400 truncate\">{email.from}</p>\n )}\n </div>\n {email.hasAttachments && (\n <Paperclip className=\"h-3.5 w-3.5 text-zinc-500 shrink-0\" />\n )}\n </div>\n {email.snippet && (\n <p className=\"text-xs text-zinc-400 line-clamp-2\">{email.snippet}</p>\n )}\n {email.date && (\n <p className=\"text-xs text-zinc-500\">{email.date}</p>\n )}\n </div>\n );\n}\n\nexport function EmailFormatter({ data }: EmailFormatterProps) {\n // Single email\n if (isEmailData(data)) {\n return <EmailCard email={data} />;\n }\n\n // Array of emails (list response)\n if (Array.isArray(data)) {\n const emails = data.filter(isEmailData);\n if (emails.length > 0) {\n return (\n <div className=\"space-y-2\">\n {emails.map((email, i) => (\n <EmailCard key={email.id || i} email={email} />\n ))}\n </div>\n );\n }\n }\n\n // Object with messages array\n if (typeof data === \"object\" && data !== null && \"messages\" in data) {\n const messages = (data as { messages: unknown[] }).messages;\n if (Array.isArray(messages)) {\n const emails = messages.filter(isEmailData);\n if (emails.length > 0) {\n return (\n <div className=\"space-y-2\">\n {emails.map((email, i) => (\n <EmailCard key={email.id || i} email={email} />\n ))}\n </div>\n );\n }\n }\n }\n\n // Fallback to raw\n return (\n <pre className=\"rounded-lg border border-zinc-800 bg-zinc-950 p-3 text-xs text-zinc-300 overflow-x-auto max-h-96 overflow-y-auto\">\n {JSON.stringify(data, null, 2)}\n </pre>\n );\n}\n","import React from \"react\";\nimport { Calendar, MapPin, Users } from \"lucide-react\";\n\ninterface CalendarEventData {\n id?: string;\n summary?: string;\n description?: string;\n start?: { dateTime?: string; date?: string };\n end?: { dateTime?: string; date?: string };\n location?: string;\n attendees?: Array<{ email?: string; displayName?: string }>;\n status?: string;\n}\n\ninterface CalendarEventFormatterProps {\n data: unknown;\n}\n\nfunction isCalendarEvent(data: unknown): data is CalendarEventData {\n return typeof data === \"object\" && data !== null && (\"summary\" in data || \"start\" in data);\n}\n\nfunction formatDateTime(dt?: { dateTime?: string; date?: string }): string {\n if (!dt) return \"\";\n const raw = dt.dateTime || dt.date;\n if (!raw) return \"\";\n try {\n const date = new Date(raw);\n return dt.dateTime\n ? date.toLocaleString(undefined, { dateStyle: \"medium\", timeStyle: \"short\" })\n : date.toLocaleDateString(undefined, { dateStyle: \"medium\" });\n } catch {\n return raw;\n }\n}\n\nfunction EventCard({ event }: { event: CalendarEventData }) {\n const startStr = formatDateTime(event.start);\n const endStr = formatDateTime(event.end);\n\n return (\n <div className=\"rounded-lg border border-zinc-800 bg-zinc-900/50 p-3 space-y-2\">\n <div className=\"flex items-start gap-2\">\n <Calendar className=\"h-4 w-4 text-zinc-400 mt-0.5 shrink-0\" />\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium text-zinc-200\">\n {event.summary || \"Untitled event\"}\n </p>\n {startStr && (\n <p className=\"text-xs text-zinc-400\">\n {startStr}\n {endStr ? ` → ${endStr}` : \"\"}\n </p>\n )}\n </div>\n </div>\n {event.location && (\n <div className=\"flex items-center gap-1.5 text-xs text-zinc-400\">\n <MapPin className=\"h-3 w-3 shrink-0\" />\n <span className=\"truncate\">{event.location}</span>\n </div>\n )}\n {event.attendees && event.attendees.length > 0 && (\n <div className=\"flex items-center gap-1.5 text-xs text-zinc-400\">\n <Users className=\"h-3 w-3 shrink-0\" />\n <span className=\"truncate\">\n {event.attendees.map((a) => a.displayName || a.email).join(\", \")}\n </span>\n </div>\n )}\n </div>\n );\n}\n\nexport function CalendarEventFormatter({ data }: CalendarEventFormatterProps) {\n if (isCalendarEvent(data)) {\n return <EventCard event={data} />;\n }\n\n if (Array.isArray(data)) {\n const events = data.filter(isCalendarEvent);\n if (events.length > 0) {\n return (\n <div className=\"space-y-2\">\n {events.map((event, i) => (\n <EventCard key={event.id || i} event={event} />\n ))}\n </div>\n );\n }\n }\n\n if (typeof data === \"object\" && data !== null && \"events\" in data) {\n const events = (data as { events: unknown[] }).events;\n if (Array.isArray(events)) {\n const calEvents = events.filter(isCalendarEvent);\n if (calEvents.length > 0) {\n return (\n <div className=\"space-y-2\">\n {calEvents.map((event, i) => (\n <EventCard key={event.id || i} event={event} />\n ))}\n </div>\n );\n }\n }\n }\n\n return (\n <pre className=\"rounded-lg border border-zinc-800 bg-zinc-950 p-3 text-xs text-zinc-300 overflow-x-auto max-h-96 overflow-y-auto\">\n {JSON.stringify(data, null, 2)}\n </pre>\n );\n}\n","import React from \"react\";\nimport { MessageSquare, Hash } from \"lucide-react\";\n\ninterface SlackMessageData {\n text?: string;\n channel?: string;\n user?: string;\n ts?: string;\n ok?: boolean;\n}\n\ninterface SlackMessageFormatterProps {\n data: unknown;\n}\n\nfunction isSlackMessage(data: unknown): data is SlackMessageData {\n return typeof data === \"object\" && data !== null && (\"text\" in data || \"channel\" in data);\n}\n\nfunction MessageBubble({ message }: { message: SlackMessageData }) {\n return (\n <div className=\"rounded-lg border border-zinc-800 bg-zinc-900/50 p-3 space-y-1.5\">\n <div className=\"flex items-center gap-2\">\n <MessageSquare className=\"h-4 w-4 text-zinc-400 shrink-0\" />\n {message.channel && (\n <span className=\"flex items-center gap-0.5 text-xs text-zinc-400\">\n <Hash className=\"h-3 w-3\" />\n {message.channel}\n </span>\n )}\n {message.user && (\n <span className=\"text-xs text-zinc-500\">{message.user}</span>\n )}\n </div>\n {message.text && (\n <p className=\"text-sm text-zinc-300\">{message.text}</p>\n )}\n </div>\n );\n}\n\nexport function SlackMessageFormatter({ data }: SlackMessageFormatterProps) {\n if (isSlackMessage(data)) {\n return <MessageBubble message={data} />;\n }\n\n if (Array.isArray(data)) {\n const messages = data.filter(isSlackMessage);\n if (messages.length > 0) {\n return (\n <div className=\"space-y-2\">\n {messages.map((msg, i) => (\n <MessageBubble key={msg.ts || i} message={msg} />\n ))}\n </div>\n );\n }\n }\n\n if (typeof data === \"object\" && data !== null && \"messages\" in data) {\n const messages = (data as { messages: unknown[] }).messages;\n if (Array.isArray(messages)) {\n const slackMsgs = messages.filter(isSlackMessage);\n if (slackMsgs.length > 0) {\n return (\n <div className=\"space-y-2\">\n {slackMsgs.map((msg, i) => (\n <MessageBubble key={msg.ts || i} message={msg} />\n ))}\n </div>\n );\n }\n }\n }\n\n return (\n <pre className=\"rounded-lg border border-zinc-800 bg-zinc-950 p-3 text-xs text-zinc-300 overflow-x-auto max-h-96 overflow-y-auto\">\n {JSON.stringify(data, null, 2)}\n </pre>\n );\n}\n","import React from \"react\";\nimport { Github, CircleDot, GitPullRequest } from \"lucide-react\";\n\ninterface GithubItemData {\n title?: string;\n number?: number;\n state?: string;\n html_url?: string;\n body?: string;\n user?: { login?: string };\n created_at?: string;\n pull_request?: unknown;\n}\n\ninterface GithubFormatterProps {\n data: unknown;\n}\n\nfunction isGithubItem(data: unknown): data is GithubItemData {\n return typeof data === \"object\" && data !== null && (\"title\" in data || \"number\" in data);\n}\n\nfunction GithubCard({ item }: { item: GithubItemData }) {\n const isPR = !!item.pull_request;\n const stateColor =\n item.state === \"open\"\n ? \"text-green-400\"\n : item.state === \"closed\"\n ? \"text-red-400\"\n : \"text-zinc-400\";\n\n return (\n <div className=\"rounded-lg border border-zinc-800 bg-zinc-900/50 p-3 space-y-1.5\">\n <div className=\"flex items-start gap-2\">\n {isPR ? (\n <GitPullRequest className={`h-4 w-4 mt-0.5 shrink-0 ${stateColor}`} />\n ) : (\n <CircleDot className={`h-4 w-4 mt-0.5 shrink-0 ${stateColor}`} />\n )}\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium text-zinc-200\">\n {item.title}\n {item.number && (\n <span className=\"text-zinc-500 font-normal\"> #{item.number}</span>\n )}\n </p>\n {item.user?.login && (\n <p className=\"text-xs text-zinc-400\">{item.user.login}</p>\n )}\n </div>\n </div>\n {item.body && (\n <p className=\"text-xs text-zinc-400 line-clamp-2\">{item.body}</p>\n )}\n </div>\n );\n}\n\nexport function GithubFormatter({ data }: GithubFormatterProps) {\n if (isGithubItem(data)) {\n return <GithubCard item={data} />;\n }\n\n if (Array.isArray(data)) {\n const items = data.filter(isGithubItem);\n if (items.length > 0) {\n return (\n <div className=\"space-y-2\">\n {items.map((item, i) => (\n <GithubCard key={item.number || i} item={item} />\n ))}\n </div>\n );\n }\n }\n\n return (\n <pre className=\"rounded-lg border border-zinc-800 bg-zinc-950 p-3 text-xs text-zinc-300 overflow-x-auto max-h-96 overflow-y-auto\">\n {JSON.stringify(data, null, 2)}\n </pre>\n );\n}\n","import React from \"react\";\nimport { FileText, Folder, Image, Film, FileSpreadsheet } from \"lucide-react\";\n\ninterface DriveFileData {\n id?: string;\n name?: string;\n mimeType?: string;\n modifiedTime?: string;\n size?: string | number;\n webViewLink?: string;\n}\n\ninterface DriveFileFormatterProps {\n data: unknown;\n}\n\nfunction isDriveFile(data: unknown): data is DriveFileData {\n return typeof data === \"object\" && data !== null && (\"name\" in data || \"mimeType\" in data);\n}\n\nfunction getFileIcon(mimeType?: string) {\n if (!mimeType) return FileText;\n if (mimeType.includes(\"folder\")) return Folder;\n if (mimeType.includes(\"image\")) return Image;\n if (mimeType.includes(\"video\")) return Film;\n if (mimeType.includes(\"spreadsheet\") || mimeType.includes(\"excel\")) return FileSpreadsheet;\n return FileText;\n}\n\nfunction FileCard({ file }: { file: DriveFileData }) {\n const Icon = getFileIcon(file.mimeType);\n\n return (\n <div className=\"flex items-center gap-3 rounded-lg border border-zinc-800 bg-zinc-900/50 p-3\">\n <Icon className=\"h-4 w-4 text-zinc-400 shrink-0\" />\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm text-zinc-200 truncate\">{file.name || \"Untitled\"}</p>\n {file.modifiedTime && (\n <p className=\"text-xs text-zinc-500\">\n {new Date(file.modifiedTime).toLocaleDateString()}\n </p>\n )}\n </div>\n </div>\n );\n}\n\nexport function DriveFileFormatter({ data }: DriveFileFormatterProps) {\n if (isDriveFile(data)) {\n return <FileCard file={data} />;\n }\n\n if (Array.isArray(data)) {\n const files = data.filter(isDriveFile);\n if (files.length > 0) {\n return (\n <div className=\"space-y-1.5\">\n {files.map((file, i) => (\n <FileCard key={file.id || i} file={file} />\n ))}\n </div>\n );\n }\n }\n\n if (typeof data === \"object\" && data !== null && \"files\" in data) {\n const files = (data as { files: unknown[] }).files;\n if (Array.isArray(files)) {\n const driveFiles = files.filter(isDriveFile);\n if (driveFiles.length > 0) {\n return (\n <div className=\"space-y-1.5\">\n {driveFiles.map((file, i) => (\n <FileCard key={file.id || i} file={file} />\n ))}\n </div>\n );\n }\n }\n }\n\n return (\n <pre className=\"rounded-lg border border-zinc-800 bg-zinc-950 p-3 text-xs text-zinc-300 overflow-x-auto max-h-96 overflow-y-auto\">\n {JSON.stringify(data, null, 2)}\n </pre>\n );\n}\n","import React from \"react\";\n\ninterface GenericFormatterProps {\n data: unknown;\n}\n\nexport function GenericFormatter({ data }: GenericFormatterProps) {\n if (data === null || data === undefined) {\n return (\n <p className=\"text-sm text-zinc-500 italic\">No data returned</p>\n );\n }\n\n return (\n <pre className=\"rounded-lg border border-zinc-800 bg-zinc-950 p-3 text-xs text-zinc-300 overflow-x-auto max-h-96 overflow-y-auto\">\n {JSON.stringify(data, null, 2)}\n </pre>\n );\n}\n","import React from \"react\";\nimport { getFormatterType, getProviderFromToolName } from \"./utils.js\";\nimport { EmailFormatter } from \"./formatters/email.js\";\nimport { CalendarEventFormatter } from \"./formatters/calendar-event.js\";\nimport { SlackMessageFormatter } from \"./formatters/slack-message.js\";\nimport { GithubFormatter } from \"./formatters/github.js\";\nimport { DriveFileFormatter } from \"./formatters/drive-file.js\";\nimport { GenericFormatter } from \"./formatters/generic.js\";\n\ninterface ToolResultPart {\n type: string;\n toolInvocation?: {\n toolName: string;\n state: string;\n result?: unknown;\n };\n toolName?: string;\n state?: string;\n result?: unknown;\n}\n\ninterface SupyagentToolResultProps {\n part: ToolResultPart;\n}\n\nexport function SupyagentToolResult({ part }: SupyagentToolResultProps) {\n const state = part.state ?? part.toolInvocation?.state;\n const result = \"result\" in part ? part.result : part.toolInvocation?.result;\n const toolName = part.toolName ?? part.toolInvocation?.toolName ?? \"unknown\";\n\n // Only render when we have a result\n if (state !== \"output-available\" || result === undefined) {\n return null;\n }\n\n const formatterType = getFormatterType(toolName);\n\n // Route to provider-specific formatter\n switch (formatterType) {\n case \"email\":\n return <EmailFormatter data={result} />;\n case \"calendar\":\n return <CalendarEventFormatter data={result} />;\n case \"slack\":\n return <SlackMessageFormatter data={result} />;\n case \"github\":\n return <GithubFormatter data={result} />;\n case \"drive\":\n return <DriveFileFormatter data={result} />;\n default:\n return <GenericFormatter data={result} />;\n }\n}\n"],"mappings":";;;AAAA,SAAgB,gBAAgB;AAChC,SAAS,aAAa,cAAc,OAAO,aAAa,eAAe;;;ACAvE;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACTA,SAAS,wBAAwB,UAA0B;AAChE,QAAM,MAAM,SAAS,QAAQ,GAAG;AAChC,SAAO,MAAM,IAAI,SAAS,MAAM,GAAG,GAAG,IAAI;AAC5C;AAKO,SAAS,iBAAiB,UAA0B;AACzD,QAAM,MAAM,SAAS,QAAQ,GAAG;AAChC,MAAI,MAAM,EAAG,QAAO;AACpB,QAAM,SAAS,SAAS,MAAM,MAAM,CAAC;AACrC,QAAM,QAAQ,OAAO,QAAQ,MAAM,GAAG;AACtC,SAAO,MAAM,OAAO,CAAC,EAAE,YAAY,IAAI,MAAM,MAAM,CAAC;AACtD;AAKO,IAAM,kBAA0C;AAAA,EACrD,OAAO;AAAA,EACP,UAAU;AAAA,EACV,OAAO;AAAA,EACP,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU;AAAA,EACV,WAAW;AAAA,EACX,SAAS;AAAA,EACT,UAAU;AAAA,EACV,UAAU;AAAA,EACV,OAAO;AAAA,EACP,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,QAAQ;AACV;AAKO,SAAS,iBAAiB,UAA0B;AACzD,SAAO,gBAAgB,QAAQ,KAAK,SAAS,OAAO,CAAC,EAAE,YAAY,IAAI,SAAS,MAAM,CAAC;AACzF;AAaO,SAAS,iBAAiB,UAAiC;AAChE,QAAM,WAAW,wBAAwB,QAAQ;AACjD,UAAQ,UAAU;AAAA,IAChB,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;;;ADzCS;AAtBT,IAAM,WAAuC;AAAA,EAC3C,OAAO;AAAA,EACP,UAAU;AAAA,EACV,OAAO;AAAA,EACP,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,QAAQ;AACV;AAOO,SAAS,aAAa,EAAE,UAAU,YAAY,UAAU,GAAsB;AACnF,QAAM,WAAW,wBAAwB,QAAQ;AACjD,QAAM,OAAO,SAAS,QAAQ,KAAK;AACnC,SAAO,oBAAC,QAAK,WAAsB;AACrC;;;ADMQ,SACE,OAAAA,MADF;AAtBD,SAAS,kBAAkB,EAAE,KAAK,GAA2B;AAClE,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAE9C,QAAM,WAAW,KAAK,YAAY,KAAK,gBAAgB,YAAY;AACnE,QAAM,QAAQ,KAAK,SAAS,KAAK,gBAAgB,SAAS;AAC1D,QAAM,OAAO,KAAK,QAAQ,KAAK,gBAAgB;AAE/C,QAAM,WAAW,wBAAwB,QAAQ;AACjD,QAAM,gBAAgB,iBAAiB,QAAQ;AAC/C,QAAM,cAAc,iBAAiB,QAAQ;AAE7C,QAAM,cAAc,UAAU;AAC9B,QAAM,UAAU,UAAU;AAC1B,QAAM,SAAS,UAAU;AAEzB,SACE,qBAAC,SAAI,WAAU,oEACb;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM,QAAQ,YAAY,CAAC,QAAQ;AAAA,QAC5C,WAAU;AAAA,QAEV;AAAA,+BAAC,SAAI,WAAU,YACb;AAAA,4BAAAA,KAAC,gBAAa,UAAoB,WAAU,yBAAwB;AAAA,YACnE,eACC,gBAAAA,KAAC,WAAQ,WAAU,+DAA8D;AAAA,aAErF;AAAA,UAEA,gBAAAA,KAAC,UAAK,WAAU,yBAAyB,yBAAc;AAAA,UACvD,gBAAAA,KAAC,UAAK,WAAU,gCAAgC,uBAAY;AAAA,UAE3D,UAAU,gBAAAA,KAAC,SAAM,WAAU,8BAA6B;AAAA,UACxD,WAAW,gBAAAA,KAAC,eAAY,WAAU,4BAA2B;AAAA,UAC7D,eACC,gBAAAA,KAAC,UAAK,WAAU,uCAAsC,wBAAU;AAAA,UAGjE,SACC,WACI,gBAAAA,KAAC,eAAY,WAAU,6BAA4B,IACnD,gBAAAA,KAAC,gBAAa,WAAU,6BAA4B;AAAA;AAAA;AAAA,IAE5D;AAAA,IAEC,YAAY,QACX,gBAAAA,KAAC,SAAI,WAAU,sCACb,0BAAAA,KAAC,SAAI,WAAU,yCACZ,eAAK,UAAU,MAAM,MAAM,CAAC,GAC/B,GACF;AAAA,KAEJ;AAEJ;;;AG5EA,SAAS,QAAAC,OAAM,iBAAiB;AA0BxB,gBAAAC,MACA,QAAAC,aADA;AARR,SAAS,YAAY,MAAkC;AACrD,SAAO,OAAO,SAAS,YAAY,SAAS,SAAS,aAAa,QAAQ,UAAU,QAAQ,aAAa;AAC3G;AAEA,SAAS,UAAU,EAAE,MAAM,GAAyB;AAClD,SACE,gBAAAA,MAAC,SAAI,WAAU,kEACb;AAAA,oBAAAA,MAAC,SAAI,WAAU,0BACb;AAAA,sBAAAD,KAACD,OAAA,EAAK,WAAU,yCAAwC;AAAA,MACxD,gBAAAE,MAAC,SAAI,WAAU,kBACb;AAAA,wBAAAD,KAAC,OAAE,WAAU,8CACV,gBAAM,WAAW,cACpB;AAAA,QACC,MAAM,QACL,gBAAAA,KAAC,OAAE,WAAU,kCAAkC,gBAAM,MAAK;AAAA,SAE9D;AAAA,MACC,MAAM,kBACL,gBAAAA,KAAC,aAAU,WAAU,sCAAqC;AAAA,OAE9D;AAAA,IACC,MAAM,WACL,gBAAAA,KAAC,OAAE,WAAU,sCAAsC,gBAAM,SAAQ;AAAA,IAElE,MAAM,QACL,gBAAAA,KAAC,OAAE,WAAU,yBAAyB,gBAAM,MAAK;AAAA,KAErD;AAEJ;AAEO,SAAS,eAAe,EAAE,KAAK,GAAwB;AAE5D,MAAI,YAAY,IAAI,GAAG;AACrB,WAAO,gBAAAA,KAAC,aAAU,OAAO,MAAM;AAAA,EACjC;AAGA,MAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,UAAM,SAAS,KAAK,OAAO,WAAW;AACtC,QAAI,OAAO,SAAS,GAAG;AACrB,aACE,gBAAAA,KAAC,SAAI,WAAU,aACZ,iBAAO,IAAI,CAAC,OAAO,MAClB,gBAAAA,KAAC,aAA8B,SAAf,MAAM,MAAM,CAAiB,CAC9C,GACH;AAAA,IAEJ;AAAA,EACF;AAGA,MAAI,OAAO,SAAS,YAAY,SAAS,QAAQ,cAAc,MAAM;AACnE,UAAM,WAAY,KAAiC;AACnD,QAAI,MAAM,QAAQ,QAAQ,GAAG;AAC3B,YAAM,SAAS,SAAS,OAAO,WAAW;AAC1C,UAAI,OAAO,SAAS,GAAG;AACrB,eACE,gBAAAA,KAAC,SAAI,WAAU,aACZ,iBAAO,IAAI,CAAC,OAAO,MAClB,gBAAAA,KAAC,aAA8B,SAAf,MAAM,MAAM,CAAiB,CAC9C,GACH;AAAA,MAEJ;AAAA,IACF;AAAA,EACF;AAGA,SACE,gBAAAA,KAAC,SAAI,WAAU,oHACZ,eAAK,UAAU,MAAM,MAAM,CAAC,GAC/B;AAEJ;;;AC5FA,SAAS,YAAAE,WAAU,QAAQ,aAAa;AA0ChC,gBAAAC,MAMI,QAAAC,aANJ;AAzBR,SAAS,gBAAgB,MAA0C;AACjE,SAAO,OAAO,SAAS,YAAY,SAAS,SAAS,aAAa,QAAQ,WAAW;AACvF;AAEA,SAAS,eAAe,IAAmD;AACzE,MAAI,CAAC,GAAI,QAAO;AAChB,QAAM,MAAM,GAAG,YAAY,GAAG;AAC9B,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI;AACF,UAAM,OAAO,IAAI,KAAK,GAAG;AACzB,WAAO,GAAG,WACN,KAAK,eAAe,QAAW,EAAE,WAAW,UAAU,WAAW,QAAQ,CAAC,IAC1E,KAAK,mBAAmB,QAAW,EAAE,WAAW,SAAS,CAAC;AAAA,EAChE,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,UAAU,EAAE,MAAM,GAAiC;AAC1D,QAAM,WAAW,eAAe,MAAM,KAAK;AAC3C,QAAM,SAAS,eAAe,MAAM,GAAG;AAEvC,SACE,gBAAAA,MAAC,SAAI,WAAU,kEACb;AAAA,oBAAAA,MAAC,SAAI,WAAU,0BACb;AAAA,sBAAAD,KAACD,WAAA,EAAS,WAAU,yCAAwC;AAAA,MAC5D,gBAAAE,MAAC,SAAI,WAAU,kBACb;AAAA,wBAAAD,KAAC,OAAE,WAAU,qCACV,gBAAM,WAAW,kBACpB;AAAA,QACC,YACC,gBAAAC,MAAC,OAAE,WAAU,yBACV;AAAA;AAAA,UACA,SAAS,WAAM,MAAM,KAAK;AAAA,WAC7B;AAAA,SAEJ;AAAA,OACF;AAAA,IACC,MAAM,YACL,gBAAAA,MAAC,SAAI,WAAU,mDACb;AAAA,sBAAAD,KAAC,UAAO,WAAU,oBAAmB;AAAA,MACrC,gBAAAA,KAAC,UAAK,WAAU,YAAY,gBAAM,UAAS;AAAA,OAC7C;AAAA,IAED,MAAM,aAAa,MAAM,UAAU,SAAS,KAC3C,gBAAAC,MAAC,SAAI,WAAU,mDACb;AAAA,sBAAAD,KAAC,SAAM,WAAU,oBAAmB;AAAA,MACpC,gBAAAA,KAAC,UAAK,WAAU,YACb,gBAAM,UAAU,IAAI,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,IAAI,GACjE;AAAA,OACF;AAAA,KAEJ;AAEJ;AAEO,SAAS,uBAAuB,EAAE,KAAK,GAAgC;AAC5E,MAAI,gBAAgB,IAAI,GAAG;AACzB,WAAO,gBAAAA,KAAC,aAAU,OAAO,MAAM;AAAA,EACjC;AAEA,MAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,UAAM,SAAS,KAAK,OAAO,eAAe;AAC1C,QAAI,OAAO,SAAS,GAAG;AACrB,aACE,gBAAAA,KAAC,SAAI,WAAU,aACZ,iBAAO,IAAI,CAAC,OAAO,MAClB,gBAAAA,KAAC,aAA8B,SAAf,MAAM,MAAM,CAAiB,CAC9C,GACH;AAAA,IAEJ;AAAA,EACF;AAEA,MAAI,OAAO,SAAS,YAAY,SAAS,QAAQ,YAAY,MAAM;AACjE,UAAM,SAAU,KAA+B;AAC/C,QAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,YAAM,YAAY,OAAO,OAAO,eAAe;AAC/C,UAAI,UAAU,SAAS,GAAG;AACxB,eACE,gBAAAA,KAAC,SAAI,WAAU,aACZ,oBAAU,IAAI,CAAC,OAAO,MACrB,gBAAAA,KAAC,aAA8B,SAAf,MAAM,MAAM,CAAiB,CAC9C,GACH;AAAA,MAEJ;AAAA,IACF;AAAA,EACF;AAEA,SACE,gBAAAA,KAAC,SAAI,WAAU,oHACZ,eAAK,UAAU,MAAM,MAAM,CAAC,GAC/B;AAEJ;;;AChHA,SAAS,iBAAAE,gBAAe,YAAY;AAsB5B,gBAAAC,MAEE,QAAAC,aAFF;AARR,SAAS,eAAe,MAAyC;AAC/D,SAAO,OAAO,SAAS,YAAY,SAAS,SAAS,UAAU,QAAQ,aAAa;AACtF;AAEA,SAAS,cAAc,EAAE,QAAQ,GAAkC;AACjE,SACE,gBAAAA,MAAC,SAAI,WAAU,oEACb;AAAA,oBAAAA,MAAC,SAAI,WAAU,2BACb;AAAA,sBAAAD,KAACD,gBAAA,EAAc,WAAU,kCAAiC;AAAA,MACzD,QAAQ,WACP,gBAAAE,MAAC,UAAK,WAAU,mDACd;AAAA,wBAAAD,KAAC,QAAK,WAAU,WAAU;AAAA,QACzB,QAAQ;AAAA,SACX;AAAA,MAED,QAAQ,QACP,gBAAAA,KAAC,UAAK,WAAU,yBAAyB,kBAAQ,MAAK;AAAA,OAE1D;AAAA,IACC,QAAQ,QACP,gBAAAA,KAAC,OAAE,WAAU,yBAAyB,kBAAQ,MAAK;AAAA,KAEvD;AAEJ;AAEO,SAAS,sBAAsB,EAAE,KAAK,GAA+B;AAC1E,MAAI,eAAe,IAAI,GAAG;AACxB,WAAO,gBAAAA,KAAC,iBAAc,SAAS,MAAM;AAAA,EACvC;AAEA,MAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,UAAM,WAAW,KAAK,OAAO,cAAc;AAC3C,QAAI,SAAS,SAAS,GAAG;AACvB,aACE,gBAAAA,KAAC,SAAI,WAAU,aACZ,mBAAS,IAAI,CAAC,KAAK,MAClB,gBAAAA,KAAC,iBAAgC,SAAS,OAAtB,IAAI,MAAM,CAAiB,CAChD,GACH;AAAA,IAEJ;AAAA,EACF;AAEA,MAAI,OAAO,SAAS,YAAY,SAAS,QAAQ,cAAc,MAAM;AACnE,UAAM,WAAY,KAAiC;AACnD,QAAI,MAAM,QAAQ,QAAQ,GAAG;AAC3B,YAAM,YAAY,SAAS,OAAO,cAAc;AAChD,UAAI,UAAU,SAAS,GAAG;AACxB,eACE,gBAAAA,KAAC,SAAI,WAAU,aACZ,oBAAU,IAAI,CAAC,KAAK,MACnB,gBAAAA,KAAC,iBAAgC,SAAS,OAAtB,IAAI,MAAM,CAAiB,CAChD,GACH;AAAA,MAEJ;AAAA,IACF;AAAA,EACF;AAEA,SACE,gBAAAA,KAAC,SAAI,WAAU,oHACZ,eAAK,UAAU,MAAM,MAAM,CAAC,GAC/B;AAEJ;;;AC/EA,SAAiB,WAAW,sBAAsB;AAkCxC,gBAAAE,MAQI,QAAAC,aARJ;AAjBV,SAAS,aAAa,MAAuC;AAC3D,SAAO,OAAO,SAAS,YAAY,SAAS,SAAS,WAAW,QAAQ,YAAY;AACtF;AAEA,SAAS,WAAW,EAAE,KAAK,GAA6B;AACtD,QAAM,OAAO,CAAC,CAAC,KAAK;AACpB,QAAM,aACJ,KAAK,UAAU,SACX,mBACA,KAAK,UAAU,WACb,iBACA;AAER,SACE,gBAAAA,MAAC,SAAI,WAAU,oEACb;AAAA,oBAAAA,MAAC,SAAI,WAAU,0BACZ;AAAA,aACC,gBAAAD,KAAC,kBAAe,WAAW,2BAA2B,UAAU,IAAI,IAEpE,gBAAAA,KAAC,aAAU,WAAW,2BAA2B,UAAU,IAAI;AAAA,MAEjE,gBAAAC,MAAC,SAAI,WAAU,kBACb;AAAA,wBAAAA,MAAC,OAAE,WAAU,qCACV;AAAA,eAAK;AAAA,UACL,KAAK,UACJ,gBAAAA,MAAC,UAAK,WAAU,6BAA4B;AAAA;AAAA,YAAG,KAAK;AAAA,aAAO;AAAA,WAE/D;AAAA,QACC,KAAK,MAAM,SACV,gBAAAD,KAAC,OAAE,WAAU,yBAAyB,eAAK,KAAK,OAAM;AAAA,SAE1D;AAAA,OACF;AAAA,IACC,KAAK,QACJ,gBAAAA,KAAC,OAAE,WAAU,sCAAsC,eAAK,MAAK;AAAA,KAEjE;AAEJ;AAEO,SAAS,gBAAgB,EAAE,KAAK,GAAyB;AAC9D,MAAI,aAAa,IAAI,GAAG;AACtB,WAAO,gBAAAA,KAAC,cAAW,MAAM,MAAM;AAAA,EACjC;AAEA,MAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,UAAM,QAAQ,KAAK,OAAO,YAAY;AACtC,QAAI,MAAM,SAAS,GAAG;AACpB,aACE,gBAAAA,KAAC,SAAI,WAAU,aACZ,gBAAM,IAAI,CAAC,MAAM,MAChB,gBAAAA,KAAC,cAAkC,QAAlB,KAAK,UAAU,CAAe,CAChD,GACH;AAAA,IAEJ;AAAA,EACF;AAEA,SACE,gBAAAA,KAAC,SAAI,WAAU,oHACZ,eAAK,UAAU,MAAM,MAAM,CAAC,GAC/B;AAEJ;;;AChFA,SAAS,YAAAE,WAAU,QAAQ,OAAO,MAAM,uBAAuB;AAiCzD,gBAAAC,MACA,QAAAC,aADA;AAlBN,SAAS,YAAY,MAAsC;AACzD,SAAO,OAAO,SAAS,YAAY,SAAS,SAAS,UAAU,QAAQ,cAAc;AACvF;AAEA,SAAS,YAAY,UAAmB;AACtC,MAAI,CAAC,SAAU,QAAOF;AACtB,MAAI,SAAS,SAAS,QAAQ,EAAG,QAAO;AACxC,MAAI,SAAS,SAAS,OAAO,EAAG,QAAO;AACvC,MAAI,SAAS,SAAS,OAAO,EAAG,QAAO;AACvC,MAAI,SAAS,SAAS,aAAa,KAAK,SAAS,SAAS,OAAO,EAAG,QAAO;AAC3E,SAAOA;AACT;AAEA,SAAS,SAAS,EAAE,KAAK,GAA4B;AACnD,QAAM,OAAO,YAAY,KAAK,QAAQ;AAEtC,SACE,gBAAAE,MAAC,SAAI,WAAU,gFACb;AAAA,oBAAAD,KAAC,QAAK,WAAU,kCAAiC;AAAA,IACjD,gBAAAC,MAAC,SAAI,WAAU,kBACb;AAAA,sBAAAD,KAAC,OAAE,WAAU,kCAAkC,eAAK,QAAQ,YAAW;AAAA,MACtE,KAAK,gBACJ,gBAAAA,KAAC,OAAE,WAAU,yBACV,cAAI,KAAK,KAAK,YAAY,EAAE,mBAAmB,GAClD;AAAA,OAEJ;AAAA,KACF;AAEJ;AAEO,SAAS,mBAAmB,EAAE,KAAK,GAA4B;AACpE,MAAI,YAAY,IAAI,GAAG;AACrB,WAAO,gBAAAA,KAAC,YAAS,MAAM,MAAM;AAAA,EAC/B;AAEA,MAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,UAAM,QAAQ,KAAK,OAAO,WAAW;AACrC,QAAI,MAAM,SAAS,GAAG;AACpB,aACE,gBAAAA,KAAC,SAAI,WAAU,eACZ,gBAAM,IAAI,CAAC,MAAM,MAChB,gBAAAA,KAAC,YAA4B,QAAd,KAAK,MAAM,CAAe,CAC1C,GACH;AAAA,IAEJ;AAAA,EACF;AAEA,MAAI,OAAO,SAAS,YAAY,SAAS,QAAQ,WAAW,MAAM;AAChE,UAAM,QAAS,KAA8B;AAC7C,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,YAAM,aAAa,MAAM,OAAO,WAAW;AAC3C,UAAI,WAAW,SAAS,GAAG;AACzB,eACE,gBAAAA,KAAC,SAAI,WAAU,eACZ,qBAAW,IAAI,CAAC,MAAM,MACrB,gBAAAA,KAAC,YAA4B,QAAd,KAAK,MAAM,CAAe,CAC1C,GACH;AAAA,MAEJ;AAAA,IACF;AAAA,EACF;AAEA,SACE,gBAAAA,KAAC,SAAI,WAAU,oHACZ,eAAK,UAAU,MAAM,MAAM,CAAC,GAC/B;AAEJ;;;AC7EM,gBAAAE,YAAA;AAHC,SAAS,iBAAiB,EAAE,KAAK,GAA0B;AAChE,MAAI,SAAS,QAAQ,SAAS,QAAW;AACvC,WACE,gBAAAA,KAAC,OAAE,WAAU,gCAA+B,8BAAgB;AAAA,EAEhE;AAEA,SACE,gBAAAA,KAAC,SAAI,WAAU,oHACZ,eAAK,UAAU,MAAM,MAAM,CAAC,GAC/B;AAEJ;;;ACsBa,gBAAAC,YAAA;AAfN,SAAS,oBAAoB,EAAE,KAAK,GAA6B;AACtE,QAAM,QAAQ,KAAK,SAAS,KAAK,gBAAgB;AACjD,QAAM,SAAS,YAAY,OAAO,KAAK,SAAS,KAAK,gBAAgB;AACrE,QAAM,WAAW,KAAK,YAAY,KAAK,gBAAgB,YAAY;AAGnE,MAAI,UAAU,sBAAsB,WAAW,QAAW;AACxD,WAAO;AAAA,EACT;AAEA,QAAM,gBAAgB,iBAAiB,QAAQ;AAG/C,UAAQ,eAAe;AAAA,IACrB,KAAK;AACH,aAAO,gBAAAA,KAAC,kBAAe,MAAM,QAAQ;AAAA,IACvC,KAAK;AACH,aAAO,gBAAAA,KAAC,0BAAuB,MAAM,QAAQ;AAAA,IAC/C,KAAK;AACH,aAAO,gBAAAA,KAAC,yBAAsB,MAAM,QAAQ;AAAA,IAC9C,KAAK;AACH,aAAO,gBAAAA,KAAC,mBAAgB,MAAM,QAAQ;AAAA,IACxC,KAAK;AACH,aAAO,gBAAAA,KAAC,sBAAmB,MAAM,QAAQ;AAAA,IAC3C;AACE,aAAO,gBAAAA,KAAC,oBAAiB,MAAM,QAAQ;AAAA,EAC3C;AACF;","names":["jsx","Mail","jsx","jsxs","Calendar","jsx","jsxs","MessageSquare","jsx","jsxs","jsx","jsxs","FileText","jsx","jsxs","jsx","jsx"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@supyagent/sdk",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Supyagent SDK — AI SDK tools, persistence, and UI components",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"import": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts"
|
|
10
|
+
},
|
|
11
|
+
"./prisma": {
|
|
12
|
+
"import": "./dist/prisma.js",
|
|
13
|
+
"types": "./dist/prisma.d.ts"
|
|
14
|
+
},
|
|
15
|
+
"./react": {
|
|
16
|
+
"import": "./dist/react.js",
|
|
17
|
+
"types": "./dist/react.d.ts"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": ["dist"],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsup",
|
|
23
|
+
"test": "vitest run",
|
|
24
|
+
"test:watch": "vitest",
|
|
25
|
+
"clean": "rm -rf dist"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"ai": "^4.1.0"
|
|
29
|
+
},
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"@prisma/client": ">=5.0.0",
|
|
32
|
+
"lucide-react": ">=0.300.0",
|
|
33
|
+
"react": ">=18.0.0",
|
|
34
|
+
"react-dom": ">=18.0.0"
|
|
35
|
+
},
|
|
36
|
+
"peerDependenciesMeta": {
|
|
37
|
+
"@prisma/client": { "optional": true },
|
|
38
|
+
"lucide-react": { "optional": true },
|
|
39
|
+
"react": { "optional": true },
|
|
40
|
+
"react-dom": { "optional": true }
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@testing-library/jest-dom": "^6.6.3",
|
|
44
|
+
"@testing-library/react": "^16.1.0",
|
|
45
|
+
"@types/react": "^19.0.0",
|
|
46
|
+
"@types/react-dom": "^19.0.0",
|
|
47
|
+
"jsdom": "^25.0.0",
|
|
48
|
+
"react": "^19.0.0",
|
|
49
|
+
"react-dom": "^19.0.0",
|
|
50
|
+
"lucide-react": "^0.468.0",
|
|
51
|
+
"tsup": "^8.3.0",
|
|
52
|
+
"typescript": "^5.7.0",
|
|
53
|
+
"vitest": "^2.1.0"
|
|
54
|
+
},
|
|
55
|
+
"license": "MIT"
|
|
56
|
+
}
|