@marktoflow/integrations 2.0.0-alpha.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1341 -0
- package/dist/adapters/claude-agent-hooks.d.ts.map +1 -0
- package/dist/adapters/claude-agent-hooks.js +339 -0
- package/dist/adapters/claude-agent-hooks.js.map +1 -0
- package/dist/adapters/claude-agent-types.d.ts +426 -0
- package/dist/adapters/claude-agent-types.d.ts.map +1 -0
- package/dist/adapters/claude-agent-types.js +62 -0
- package/dist/adapters/claude-agent-types.js.map +1 -0
- package/dist/adapters/claude-agent-workflow.d.ts +393 -0
- package/dist/adapters/claude-agent-workflow.d.ts.map +1 -0
- package/dist/adapters/claude-agent-workflow.js +445 -0
- package/dist/adapters/claude-agent-workflow.js.map +1 -0
- package/dist/adapters/claude-agent.d.ts +189 -0
- package/dist/adapters/claude-agent.d.ts.map +1 -0
- package/dist/adapters/claude-agent.js +504 -0
- package/dist/adapters/claude-agent.js.map +1 -0
- package/dist/adapters/claude-code.d.ts +34 -0
- package/dist/adapters/claude-code.d.ts.map +1 -0
- package/dist/adapters/claude-code.js +89 -0
- package/dist/adapters/claude-code.js.map +1 -0
- package/dist/adapters/codex-types.d.ts +463 -0
- package/dist/adapters/codex-types.d.ts.map +1 -0
- package/dist/adapters/codex-types.js +53 -0
- package/dist/adapters/codex-types.js.map +1 -0
- package/dist/adapters/codex-workflow.d.ts +414 -0
- package/dist/adapters/codex-workflow.d.ts.map +1 -0
- package/dist/adapters/codex-workflow.js +470 -0
- package/dist/adapters/codex-workflow.js.map +1 -0
- package/dist/adapters/codex.d.ts +154 -0
- package/dist/adapters/codex.d.ts.map +1 -0
- package/dist/adapters/codex.js +416 -0
- package/dist/adapters/codex.js.map +1 -0
- package/dist/adapters/github-copilot-types.d.ts +1012 -0
- package/dist/adapters/github-copilot-types.d.ts.map +1 -0
- package/dist/adapters/github-copilot-types.js +80 -0
- package/dist/adapters/github-copilot-types.js.map +1 -0
- package/dist/adapters/github-copilot-workflow.d.ts +462 -0
- package/dist/adapters/github-copilot-workflow.d.ts.map +1 -0
- package/dist/adapters/github-copilot-workflow.js +473 -0
- package/dist/adapters/github-copilot-workflow.js.map +1 -0
- package/dist/adapters/github-copilot.d.ts +280 -0
- package/dist/adapters/github-copilot.d.ts.map +1 -0
- package/dist/adapters/github-copilot.js +468 -0
- package/dist/adapters/github-copilot.js.map +1 -0
- package/dist/adapters/ollama.d.ts.map +1 -0
- package/dist/adapters/ollama.js +9 -0
- package/dist/adapters/ollama.js.map +1 -0
- package/dist/adapters/opencode.d.ts +41 -0
- package/dist/adapters/opencode.d.ts.map +1 -0
- package/dist/adapters/opencode.js +148 -0
- package/dist/adapters/opencode.js.map +1 -0
- package/dist/index.d.ts +52 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +161 -0
- package/dist/index.js.map +1 -0
- package/dist/services/ai-browser.d.ts +112 -0
- package/dist/services/ai-browser.d.ts.map +1 -0
- package/dist/services/ai-browser.js +363 -0
- package/dist/services/ai-browser.js.map +1 -0
- package/dist/services/airtable.d.ts.map +1 -0
- package/dist/services/airtable.js +295 -0
- package/dist/services/airtable.js.map +1 -0
- package/dist/services/asana.d.ts +159 -0
- package/dist/services/asana.d.ts.map +1 -0
- package/dist/services/asana.js +196 -0
- package/dist/services/asana.js.map +1 -0
- package/dist/services/aws-s3.d.ts +89 -0
- package/dist/services/aws-s3.d.ts.map +1 -0
- package/dist/services/aws-s3.js +154 -0
- package/dist/services/aws-s3.js.map +1 -0
- package/dist/services/confluence.d.ts.map +1 -0
- package/dist/services/confluence.js +356 -0
- package/dist/services/confluence.js.map +1 -0
- package/dist/services/discord.d.ts.map +1 -0
- package/dist/services/discord.js +279 -0
- package/dist/services/discord.js.map +1 -0
- package/dist/services/dropbox.d.ts +134 -0
- package/dist/services/dropbox.d.ts.map +1 -0
- package/dist/services/dropbox.js +190 -0
- package/dist/services/dropbox.js.map +1 -0
- package/dist/services/github.d.ts.map +1 -0
- package/dist/services/github.js +13 -0
- package/dist/services/github.js.map +1 -0
- package/dist/services/gmail-trigger.d.ts.map +1 -0
- package/dist/services/gmail-trigger.js +172 -0
- package/dist/services/gmail-trigger.js.map +1 -0
- package/dist/services/gmail.d.ts.map +1 -0
- package/dist/services/gmail.js +372 -0
- package/dist/services/gmail.js.map +1 -0
- package/dist/services/google-calendar.d.ts.map +1 -0
- package/dist/services/google-calendar.js +357 -0
- package/dist/services/google-calendar.js.map +1 -0
- package/dist/services/google-docs.d.ts.map +1 -0
- package/dist/services/google-docs.js +332 -0
- package/dist/services/google-docs.js.map +1 -0
- package/dist/services/google-drive.d.ts.map +1 -0
- package/dist/services/google-drive.js +327 -0
- package/dist/services/google-drive.js.map +1 -0
- package/dist/services/google-sheets.d.ts.map +1 -0
- package/dist/services/google-sheets.js +391 -0
- package/dist/services/google-sheets.js.map +1 -0
- package/dist/services/http.d.ts.map +1 -0
- package/dist/services/http.js +284 -0
- package/dist/services/http.js.map +1 -0
- package/dist/services/jira.d.ts.map +1 -0
- package/dist/services/jira.js +35 -0
- package/dist/services/jira.js.map +1 -0
- package/dist/services/linear.d.ts.map +1 -0
- package/dist/services/linear.js +326 -0
- package/dist/services/linear.js.map +1 -0
- package/dist/services/mailchimp.d.ts +169 -0
- package/dist/services/mailchimp.d.ts.map +1 -0
- package/dist/services/mailchimp.js +180 -0
- package/dist/services/mailchimp.js.map +1 -0
- package/dist/services/mysql.d.ts.map +1 -0
- package/dist/services/mysql.js +250 -0
- package/dist/services/mysql.js.map +1 -0
- package/dist/services/notion.d.ts.map +1 -0
- package/dist/services/notion.js +358 -0
- package/dist/services/notion.js.map +1 -0
- package/dist/services/outlook-trigger.d.ts.map +1 -0
- package/dist/services/outlook-trigger.js +204 -0
- package/dist/services/outlook-trigger.js.map +1 -0
- package/dist/services/outlook.d.ts.map +1 -0
- package/dist/services/outlook.js +486 -0
- package/dist/services/outlook.js.map +1 -0
- package/dist/services/playwright.d.ts +678 -0
- package/dist/services/playwright.d.ts.map +1 -0
- package/dist/services/playwright.js +1141 -0
- package/dist/services/playwright.js.map +1 -0
- package/dist/services/postgres.d.ts.map +1 -0
- package/dist/services/postgres.js +230 -0
- package/dist/services/postgres.js.map +1 -0
- package/dist/services/sendgrid.d.ts +43 -0
- package/dist/services/sendgrid.d.ts.map +1 -0
- package/dist/services/sendgrid.js +87 -0
- package/dist/services/sendgrid.js.map +1 -0
- package/dist/services/shopify.d.ts +160 -0
- package/dist/services/shopify.d.ts.map +1 -0
- package/dist/services/shopify.js +166 -0
- package/dist/services/shopify.js.map +1 -0
- package/dist/services/slack-socket.d.ts.map +1 -0
- package/dist/services/slack-socket.js +48 -0
- package/dist/services/slack-socket.js.map +1 -0
- package/dist/services/slack.d.ts.map +1 -0
- package/dist/services/slack.js +11 -0
- package/dist/services/slack.js.map +1 -0
- package/dist/services/stripe.d.ts +275 -0
- package/dist/services/stripe.d.ts.map +1 -0
- package/dist/services/stripe.js +229 -0
- package/dist/services/stripe.js.map +1 -0
- package/dist/services/supabase.d.ts.map +1 -0
- package/dist/services/supabase.js +328 -0
- package/dist/services/supabase.js.map +1 -0
- package/dist/services/teams.d.ts +224 -0
- package/dist/services/teams.d.ts.map +1 -0
- package/dist/services/teams.js +229 -0
- package/dist/services/teams.js.map +1 -0
- package/dist/services/telegram.d.ts.map +1 -0
- package/dist/services/telegram.js +247 -0
- package/dist/services/telegram.js.map +1 -0
- package/dist/services/trello.d.ts +160 -0
- package/dist/services/trello.d.ts.map +1 -0
- package/dist/services/trello.js +194 -0
- package/dist/services/trello.js.map +1 -0
- package/dist/services/twilio.d.ts +126 -0
- package/dist/services/twilio.d.ts.map +1 -0
- package/dist/services/twilio.js +153 -0
- package/dist/services/twilio.js.map +1 -0
- package/dist/services/whatsapp.d.ts.map +1 -0
- package/dist/services/whatsapp.js +253 -0
- package/dist/services/whatsapp.js.map +1 -0
- package/dist/services/zendesk.d.ts +134 -0
- package/dist/services/zendesk.d.ts.map +1 -0
- package/dist/services/zendesk.js +148 -0
- package/dist/services/zendesk.js.map +1 -0
- package/dist/tools/script.d.ts +21 -0
- package/dist/tools/script.d.ts.map +1 -0
- package/dist/tools/script.js +136 -0
- package/dist/tools/script.js.map +1 -0
- package/package.json +98 -0
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Browser Automation Client
|
|
3
|
+
*
|
|
4
|
+
* Provides AI-powered browser automation using GitHub Copilot or Claude Code SDK
|
|
5
|
+
* as backends instead of relying on external API services.
|
|
6
|
+
*
|
|
7
|
+
* This integrates with marktoflow's existing AI adapters to provide natural language
|
|
8
|
+
* browser control without additional API costs.
|
|
9
|
+
*/
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// AI Browser Client
|
|
12
|
+
// ============================================================================
|
|
13
|
+
/**
|
|
14
|
+
* AI-powered browser automation client
|
|
15
|
+
*
|
|
16
|
+
* Uses GitHub Copilot or Claude Code SDK for AI reasoning instead of
|
|
17
|
+
* external API services like OpenAI or Anthropic.
|
|
18
|
+
*/
|
|
19
|
+
export class AIBrowserClient {
|
|
20
|
+
backend;
|
|
21
|
+
aiClient;
|
|
22
|
+
playwrightClient;
|
|
23
|
+
debug;
|
|
24
|
+
constructor(config) {
|
|
25
|
+
this.backend = config.backend;
|
|
26
|
+
this.aiClient = config.aiClient;
|
|
27
|
+
this.playwrightClient = config.playwrightClient;
|
|
28
|
+
this.debug = config.debug ?? false;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Perform an action described in natural language
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* await client.act({ action: 'Click the login button' });
|
|
35
|
+
* await client.act({ action: 'Type "john@example.com" into the email field' });
|
|
36
|
+
*/
|
|
37
|
+
async act(options) {
|
|
38
|
+
try {
|
|
39
|
+
// Get current page context
|
|
40
|
+
const pageInfo = await this.playwrightClient.pageInfo(false);
|
|
41
|
+
const prompt = this.buildActPrompt(options.action, pageInfo.url, pageInfo.title);
|
|
42
|
+
if (this.debug) {
|
|
43
|
+
console.log('[AI Browser] Act prompt:', prompt);
|
|
44
|
+
}
|
|
45
|
+
// Query AI backend
|
|
46
|
+
const response = await this.queryAI(prompt);
|
|
47
|
+
if (this.debug) {
|
|
48
|
+
console.log('[AI Browser] AI response:', response);
|
|
49
|
+
}
|
|
50
|
+
// Parse AI response
|
|
51
|
+
const parsedAction = this.parseActionResponse(response);
|
|
52
|
+
if (!parsedAction) {
|
|
53
|
+
throw new Error('Failed to parse AI response');
|
|
54
|
+
}
|
|
55
|
+
// Execute the action via Playwright
|
|
56
|
+
await this.executeAction(parsedAction);
|
|
57
|
+
return {
|
|
58
|
+
success: true,
|
|
59
|
+
message: `Executed: ${options.action}`,
|
|
60
|
+
action: options.action,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
return {
|
|
65
|
+
success: false,
|
|
66
|
+
message: error instanceof Error ? error.message : String(error),
|
|
67
|
+
action: options.action,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Observe the current page and identify available actions
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* const elements = await client.observe({ instruction: 'Find all form inputs' });
|
|
76
|
+
*/
|
|
77
|
+
async observe(options) {
|
|
78
|
+
try {
|
|
79
|
+
// Get page content
|
|
80
|
+
const pageInfo = await this.playwrightClient.pageInfo(true);
|
|
81
|
+
const prompt = this.buildObservePrompt(pageInfo.content || '', pageInfo.url, options?.instruction);
|
|
82
|
+
if (this.debug) {
|
|
83
|
+
console.log('[AI Browser] Observe prompt:', prompt.slice(0, 500) + '...');
|
|
84
|
+
}
|
|
85
|
+
const response = await this.queryAI(prompt);
|
|
86
|
+
if (this.debug) {
|
|
87
|
+
console.log('[AI Browser] AI response:', response);
|
|
88
|
+
}
|
|
89
|
+
// Parse elements from AI response
|
|
90
|
+
return this.parseObserveResponse(response);
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
console.error('[AI Browser] Observe error:', error);
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Extract structured data using AI
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* const data = await client.aiExtract({
|
|
102
|
+
* instruction: 'Extract all product names and prices',
|
|
103
|
+
* schema: {
|
|
104
|
+
* type: 'object',
|
|
105
|
+
* properties: {
|
|
106
|
+
* products: {
|
|
107
|
+
* type: 'array',
|
|
108
|
+
* items: {
|
|
109
|
+
* type: 'object',
|
|
110
|
+
* properties: {
|
|
111
|
+
* name: { type: 'string' },
|
|
112
|
+
* price: { type: 'number' }
|
|
113
|
+
* }
|
|
114
|
+
* }
|
|
115
|
+
* }
|
|
116
|
+
* }
|
|
117
|
+
* }
|
|
118
|
+
* });
|
|
119
|
+
*/
|
|
120
|
+
async aiExtract(options) {
|
|
121
|
+
try {
|
|
122
|
+
// Get page content
|
|
123
|
+
const pageInfo = await this.playwrightClient.pageInfo(true);
|
|
124
|
+
const prompt = this.buildExtractPrompt(pageInfo.content || '', pageInfo.url, options.instruction, options.schema);
|
|
125
|
+
if (this.debug) {
|
|
126
|
+
console.log('[AI Browser] Extract prompt:', prompt.slice(0, 500) + '...');
|
|
127
|
+
}
|
|
128
|
+
const response = await this.queryAI(prompt);
|
|
129
|
+
if (this.debug) {
|
|
130
|
+
console.log('[AI Browser] AI response:', response);
|
|
131
|
+
}
|
|
132
|
+
// Parse extracted data
|
|
133
|
+
const data = this.parseExtractResponse(response);
|
|
134
|
+
return { data };
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
throw new Error(`AI extraction failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// ============================================================================
|
|
141
|
+
// Private Methods - AI Communication
|
|
142
|
+
// ============================================================================
|
|
143
|
+
async queryAI(prompt) {
|
|
144
|
+
if (this.backend === 'copilot') {
|
|
145
|
+
const client = this.aiClient;
|
|
146
|
+
return await client.send({ prompt });
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
const client = this.aiClient;
|
|
150
|
+
return await client.generate({ prompt });
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// ============================================================================
|
|
154
|
+
// Private Methods - Prompt Building
|
|
155
|
+
// ============================================================================
|
|
156
|
+
buildActPrompt(action, url, title) {
|
|
157
|
+
return `You are an AI browser automation assistant. Convert natural language actions to Playwright commands.
|
|
158
|
+
|
|
159
|
+
Current Page:
|
|
160
|
+
- URL: ${url}
|
|
161
|
+
- Title: ${title}
|
|
162
|
+
|
|
163
|
+
User Action: "${action}"
|
|
164
|
+
|
|
165
|
+
Available Playwright Actions:
|
|
166
|
+
- navigate: { url, waitUntil? }
|
|
167
|
+
- click: { selector, button?, force? }
|
|
168
|
+
- type: { selector, text, delay?, clear? }
|
|
169
|
+
- fill: { selector, value }
|
|
170
|
+
- select: { selector, values }
|
|
171
|
+
- check: { selector }
|
|
172
|
+
- uncheck: { selector }
|
|
173
|
+
- hover: { selector }
|
|
174
|
+
- press: { selector, key }
|
|
175
|
+
- wait: { selector?, url?, loadState?, timeout? }
|
|
176
|
+
|
|
177
|
+
IMPORTANT:
|
|
178
|
+
1. Return ONLY valid JSON in this exact format:
|
|
179
|
+
{ "action": "click", "inputs": { "selector": "#button" } }
|
|
180
|
+
2. Choose the most appropriate selector (id, class, text, or CSS selector)
|
|
181
|
+
3. For typing text, use "fill" for instant input or "type" for keyboard simulation
|
|
182
|
+
4. For navigation, use "navigate"
|
|
183
|
+
5. NO explanatory text, ONLY the JSON object
|
|
184
|
+
|
|
185
|
+
Example Responses:
|
|
186
|
+
- "Click the login button" -> { "action": "click", "inputs": { "selector": "button:has-text('Login')" } }
|
|
187
|
+
- "Type email@example.com in the email field" -> { "action": "fill", "inputs": { "selector": "input[type='email']", "value": "email@example.com" } }
|
|
188
|
+
- "Select 'United States' from country dropdown" -> { "action": "select", "inputs": { "selector": "#country", "values": "United States" } }
|
|
189
|
+
|
|
190
|
+
Now convert this action to JSON:
|
|
191
|
+
"${action}"
|
|
192
|
+
|
|
193
|
+
JSON:`;
|
|
194
|
+
}
|
|
195
|
+
buildObservePrompt(htmlContent, url, instruction) {
|
|
196
|
+
// Limit HTML content to avoid token limits
|
|
197
|
+
const maxLength = 15000;
|
|
198
|
+
const truncatedHtml = htmlContent.length > maxLength
|
|
199
|
+
? htmlContent.slice(0, maxLength) + '\n... (truncated)'
|
|
200
|
+
: htmlContent;
|
|
201
|
+
return `You are analyzing a web page to identify interactive elements.
|
|
202
|
+
|
|
203
|
+
Current Page URL: ${url}
|
|
204
|
+
|
|
205
|
+
${instruction ? `Focus: ${instruction}\n` : ''}
|
|
206
|
+
HTML Content:
|
|
207
|
+
${truncatedHtml}
|
|
208
|
+
|
|
209
|
+
Analyze the page and identify interactive elements (buttons, links, inputs, forms, etc.).
|
|
210
|
+
|
|
211
|
+
Return a JSON array of elements in this exact format:
|
|
212
|
+
[
|
|
213
|
+
{
|
|
214
|
+
"selector": "CSS selector for the element",
|
|
215
|
+
"description": "What this element does",
|
|
216
|
+
"tagName": "HTML tag name",
|
|
217
|
+
"text": "visible text if any",
|
|
218
|
+
"actions": ["click", "fill", "select", etc.]
|
|
219
|
+
}
|
|
220
|
+
]
|
|
221
|
+
|
|
222
|
+
IMPORTANT:
|
|
223
|
+
1. Return ONLY valid JSON array, no explanatory text
|
|
224
|
+
2. Provide actionable CSS selectors (id, class, or text-based)
|
|
225
|
+
3. Include only interactive elements that can be automated
|
|
226
|
+
4. Limit to the 10 most important elements
|
|
227
|
+
5. For forms, identify input fields, buttons, and selects
|
|
228
|
+
|
|
229
|
+
JSON Array:`;
|
|
230
|
+
}
|
|
231
|
+
buildExtractPrompt(htmlContent, url, instruction, schema) {
|
|
232
|
+
const maxLength = 15000;
|
|
233
|
+
const truncatedHtml = htmlContent.length > maxLength
|
|
234
|
+
? htmlContent.slice(0, maxLength) + '\n... (truncated)'
|
|
235
|
+
: htmlContent;
|
|
236
|
+
return `You are extracting structured data from a web page.
|
|
237
|
+
|
|
238
|
+
Current Page URL: ${url}
|
|
239
|
+
|
|
240
|
+
Extraction Task: ${instruction}
|
|
241
|
+
|
|
242
|
+
${schema ? `Expected JSON Schema:\n${JSON.stringify(schema, null, 2)}\n` : ''}
|
|
243
|
+
HTML Content:
|
|
244
|
+
${truncatedHtml}
|
|
245
|
+
|
|
246
|
+
Extract the requested data and return it as valid JSON.
|
|
247
|
+
|
|
248
|
+
IMPORTANT:
|
|
249
|
+
1. Return ONLY valid JSON, no explanatory text
|
|
250
|
+
2. Follow the provided schema if given
|
|
251
|
+
3. Extract accurate data from the HTML
|
|
252
|
+
4. Use null for missing values
|
|
253
|
+
5. Ensure all property names match the schema
|
|
254
|
+
|
|
255
|
+
JSON:`;
|
|
256
|
+
}
|
|
257
|
+
// ============================================================================
|
|
258
|
+
// Private Methods - Response Parsing
|
|
259
|
+
// ============================================================================
|
|
260
|
+
parseActionResponse(response) {
|
|
261
|
+
try {
|
|
262
|
+
// Extract JSON from response (handle markdown code blocks)
|
|
263
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
264
|
+
if (!jsonMatch) {
|
|
265
|
+
console.error('[AI Browser] No JSON found in response:', response);
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
269
|
+
if (!parsed.action || !parsed.inputs) {
|
|
270
|
+
console.error('[AI Browser] Invalid action format:', parsed);
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
return parsed;
|
|
274
|
+
}
|
|
275
|
+
catch (error) {
|
|
276
|
+
console.error('[AI Browser] Failed to parse action:', error, response);
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
parseObserveResponse(response) {
|
|
281
|
+
try {
|
|
282
|
+
// Extract JSON array from response
|
|
283
|
+
const jsonMatch = response.match(/\[[\s\S]*\]/);
|
|
284
|
+
if (!jsonMatch) {
|
|
285
|
+
console.error('[AI Browser] No JSON array found in response');
|
|
286
|
+
return [];
|
|
287
|
+
}
|
|
288
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
289
|
+
if (!Array.isArray(parsed)) {
|
|
290
|
+
console.error('[AI Browser] Response is not an array');
|
|
291
|
+
return [];
|
|
292
|
+
}
|
|
293
|
+
return parsed;
|
|
294
|
+
}
|
|
295
|
+
catch (error) {
|
|
296
|
+
console.error('[AI Browser] Failed to parse observe response:', error);
|
|
297
|
+
return [];
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
parseExtractResponse(response) {
|
|
301
|
+
try {
|
|
302
|
+
// Extract JSON from response
|
|
303
|
+
const jsonMatch = response.match(/\{[\s\S]*\}|\[[\s\S]*\]/);
|
|
304
|
+
if (!jsonMatch) {
|
|
305
|
+
throw new Error('No JSON found in AI response');
|
|
306
|
+
}
|
|
307
|
+
return JSON.parse(jsonMatch[0]);
|
|
308
|
+
}
|
|
309
|
+
catch (error) {
|
|
310
|
+
throw new Error(`Failed to parse extraction response: ${error instanceof Error ? error.message : String(error)}`);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
// ============================================================================
|
|
314
|
+
// Private Methods - Action Execution
|
|
315
|
+
// ============================================================================
|
|
316
|
+
async executeAction(action) {
|
|
317
|
+
const { action: actionName, inputs } = action;
|
|
318
|
+
// Map action names to Playwright client methods
|
|
319
|
+
switch (actionName) {
|
|
320
|
+
case 'navigate':
|
|
321
|
+
await this.playwrightClient.navigate(inputs);
|
|
322
|
+
break;
|
|
323
|
+
case 'click':
|
|
324
|
+
await this.playwrightClient.click(inputs);
|
|
325
|
+
break;
|
|
326
|
+
case 'type':
|
|
327
|
+
await this.playwrightClient.type(inputs);
|
|
328
|
+
break;
|
|
329
|
+
case 'fill':
|
|
330
|
+
await this.playwrightClient.fill(inputs);
|
|
331
|
+
break;
|
|
332
|
+
case 'select':
|
|
333
|
+
await this.playwrightClient.select(inputs);
|
|
334
|
+
break;
|
|
335
|
+
case 'check': {
|
|
336
|
+
const checkInputs = inputs;
|
|
337
|
+
await this.playwrightClient.check(checkInputs.selector);
|
|
338
|
+
break;
|
|
339
|
+
}
|
|
340
|
+
case 'uncheck': {
|
|
341
|
+
const uncheckInputs = inputs;
|
|
342
|
+
await this.playwrightClient.uncheck(uncheckInputs.selector);
|
|
343
|
+
break;
|
|
344
|
+
}
|
|
345
|
+
case 'hover': {
|
|
346
|
+
const hoverInputs = inputs;
|
|
347
|
+
await this.playwrightClient.hover(hoverInputs.selector);
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
case 'press': {
|
|
351
|
+
const pressInputs = inputs;
|
|
352
|
+
await this.playwrightClient.press(pressInputs.selector, pressInputs.key);
|
|
353
|
+
break;
|
|
354
|
+
}
|
|
355
|
+
case 'wait':
|
|
356
|
+
await this.playwrightClient.wait(inputs);
|
|
357
|
+
break;
|
|
358
|
+
default:
|
|
359
|
+
throw new Error(`Unsupported action: ${actionName}`);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
//# sourceMappingURL=ai-browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-browser.js","sourceRoot":"","sources":["../../src/services/ai-browser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"airtable.d.ts","sourceRoot":"","sources":["../../src/services/airtable.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Airtable Integration
|
|
3
|
+
*
|
|
4
|
+
* Flexible database/spreadsheet platform.
|
|
5
|
+
* API Docs: https://airtable.com/developers/web/api/introduction
|
|
6
|
+
*/
|
|
7
|
+
const AIRTABLE_API_URL = 'https://api.airtable.com/v0';
|
|
8
|
+
/**
|
|
9
|
+
* Airtable API client for workflow integration
|
|
10
|
+
*/
|
|
11
|
+
export class AirtableClient {
|
|
12
|
+
token;
|
|
13
|
+
baseId;
|
|
14
|
+
constructor(token, baseId) {
|
|
15
|
+
this.token = token;
|
|
16
|
+
this.baseId = baseId;
|
|
17
|
+
}
|
|
18
|
+
async request(method, path, body) {
|
|
19
|
+
const response = await fetch(`${AIRTABLE_API_URL}${path}`, {
|
|
20
|
+
method,
|
|
21
|
+
headers: {
|
|
22
|
+
Authorization: `Bearer ${this.token}`,
|
|
23
|
+
'Content-Type': 'application/json',
|
|
24
|
+
},
|
|
25
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
26
|
+
});
|
|
27
|
+
if (!response.ok) {
|
|
28
|
+
const error = await response.text();
|
|
29
|
+
throw new Error(`Airtable API error: ${response.status} ${error}`);
|
|
30
|
+
}
|
|
31
|
+
// Handle 204 No Content
|
|
32
|
+
if (response.status === 204) {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
return (await response.json());
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Set the default base ID
|
|
39
|
+
*/
|
|
40
|
+
setBase(baseId) {
|
|
41
|
+
this.baseId = baseId;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* List all bases the user has access to
|
|
45
|
+
*/
|
|
46
|
+
async listBases() {
|
|
47
|
+
const data = await this.request('GET', '/meta/bases');
|
|
48
|
+
return data.bases.map((b) => ({
|
|
49
|
+
id: b.id,
|
|
50
|
+
name: b.name,
|
|
51
|
+
permissionLevel: b.permissionLevel,
|
|
52
|
+
}));
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Get base schema (tables and fields)
|
|
56
|
+
*/
|
|
57
|
+
async getBaseSchema(baseId) {
|
|
58
|
+
const id = baseId ?? this.baseId;
|
|
59
|
+
if (!id)
|
|
60
|
+
throw new Error('Base ID is required');
|
|
61
|
+
const data = await this.request('GET', `/meta/bases/${id}/tables`);
|
|
62
|
+
return data.tables.map((t) => ({
|
|
63
|
+
id: t.id,
|
|
64
|
+
name: t.name,
|
|
65
|
+
primaryFieldId: t.primaryFieldId,
|
|
66
|
+
fields: t.fields ?? [],
|
|
67
|
+
views: t.views ?? [],
|
|
68
|
+
}));
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* List records from a table
|
|
72
|
+
*/
|
|
73
|
+
async listRecords(tableIdOrName, options = {}, baseId) {
|
|
74
|
+
const id = baseId ?? this.baseId;
|
|
75
|
+
if (!id)
|
|
76
|
+
throw new Error('Base ID is required');
|
|
77
|
+
const params = [];
|
|
78
|
+
if (options.fields) {
|
|
79
|
+
options.fields.forEach((f) => params.push(`fields[]=${encodeURIComponent(f)}`));
|
|
80
|
+
}
|
|
81
|
+
if (options.filterByFormula) {
|
|
82
|
+
params.push(`filterByFormula=${encodeURIComponent(options.filterByFormula)}`);
|
|
83
|
+
}
|
|
84
|
+
if (options.maxRecords)
|
|
85
|
+
params.push(`maxRecords=${options.maxRecords}`);
|
|
86
|
+
if (options.pageSize)
|
|
87
|
+
params.push(`pageSize=${options.pageSize}`);
|
|
88
|
+
if (options.sort) {
|
|
89
|
+
options.sort.forEach((s, i) => {
|
|
90
|
+
params.push(`sort[${i}][field]=${encodeURIComponent(s.field)}`);
|
|
91
|
+
if (s.direction)
|
|
92
|
+
params.push(`sort[${i}][direction]=${s.direction}`);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
if (options.view)
|
|
96
|
+
params.push(`view=${encodeURIComponent(options.view)}`);
|
|
97
|
+
if (options.offset)
|
|
98
|
+
params.push(`offset=${options.offset}`);
|
|
99
|
+
if (options.cellFormat)
|
|
100
|
+
params.push(`cellFormat=${options.cellFormat}`);
|
|
101
|
+
if (options.timeZone)
|
|
102
|
+
params.push(`timeZone=${encodeURIComponent(options.timeZone)}`);
|
|
103
|
+
if (options.userLocale)
|
|
104
|
+
params.push(`userLocale=${encodeURIComponent(options.userLocale)}`);
|
|
105
|
+
const query = params.length ? `?${params.join('&')}` : '';
|
|
106
|
+
const encodedTable = encodeURIComponent(tableIdOrName);
|
|
107
|
+
const data = await this.request('GET', `/${id}/${encodedTable}${query}`);
|
|
108
|
+
return {
|
|
109
|
+
records: data.records.map((r) => ({
|
|
110
|
+
id: r.id,
|
|
111
|
+
createdTime: r.createdTime,
|
|
112
|
+
fields: r.fields,
|
|
113
|
+
})),
|
|
114
|
+
offset: data.offset,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Get all records (handles pagination automatically)
|
|
119
|
+
*/
|
|
120
|
+
async getAllRecords(tableIdOrName, options = {}, baseId) {
|
|
121
|
+
const allRecords = [];
|
|
122
|
+
let offset;
|
|
123
|
+
do {
|
|
124
|
+
const result = await this.listRecords(tableIdOrName, { ...options, offset }, baseId);
|
|
125
|
+
allRecords.push(...result.records);
|
|
126
|
+
offset = result.offset;
|
|
127
|
+
} while (offset);
|
|
128
|
+
return allRecords;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Get a single record by ID
|
|
132
|
+
*/
|
|
133
|
+
async getRecord(tableIdOrName, recordId, baseId) {
|
|
134
|
+
const id = baseId ?? this.baseId;
|
|
135
|
+
if (!id)
|
|
136
|
+
throw new Error('Base ID is required');
|
|
137
|
+
const encodedTable = encodeURIComponent(tableIdOrName);
|
|
138
|
+
const data = await this.request('GET', `/${id}/${encodedTable}/${recordId}`);
|
|
139
|
+
return {
|
|
140
|
+
id: data.id,
|
|
141
|
+
createdTime: data.createdTime,
|
|
142
|
+
fields: data.fields,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Create a single record
|
|
147
|
+
*/
|
|
148
|
+
async createRecord(tableIdOrName, options, baseId) {
|
|
149
|
+
const id = baseId ?? this.baseId;
|
|
150
|
+
if (!id)
|
|
151
|
+
throw new Error('Base ID is required');
|
|
152
|
+
const encodedTable = encodeURIComponent(tableIdOrName);
|
|
153
|
+
const data = await this.request('POST', `/${id}/${encodedTable}`, {
|
|
154
|
+
fields: options.fields,
|
|
155
|
+
typecast: options.typecast,
|
|
156
|
+
});
|
|
157
|
+
return {
|
|
158
|
+
id: data.id,
|
|
159
|
+
createdTime: data.createdTime,
|
|
160
|
+
fields: data.fields,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Create multiple records (up to 10 at a time)
|
|
165
|
+
*/
|
|
166
|
+
async createRecords(tableIdOrName, records, baseId) {
|
|
167
|
+
const id = baseId ?? this.baseId;
|
|
168
|
+
if (!id)
|
|
169
|
+
throw new Error('Base ID is required');
|
|
170
|
+
if (records.length > 10) {
|
|
171
|
+
throw new Error('Airtable allows maximum 10 records per request');
|
|
172
|
+
}
|
|
173
|
+
const encodedTable = encodeURIComponent(tableIdOrName);
|
|
174
|
+
const data = await this.request('POST', `/${id}/${encodedTable}`, {
|
|
175
|
+
records: records.map((r) => ({
|
|
176
|
+
fields: r.fields,
|
|
177
|
+
typecast: r.typecast,
|
|
178
|
+
})),
|
|
179
|
+
});
|
|
180
|
+
return data.records.map((r) => ({
|
|
181
|
+
id: r.id,
|
|
182
|
+
createdTime: r.createdTime,
|
|
183
|
+
fields: r.fields,
|
|
184
|
+
}));
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Update a single record
|
|
188
|
+
*/
|
|
189
|
+
async updateRecord(tableIdOrName, recordId, options, baseId) {
|
|
190
|
+
const id = baseId ?? this.baseId;
|
|
191
|
+
if (!id)
|
|
192
|
+
throw new Error('Base ID is required');
|
|
193
|
+
const encodedTable = encodeURIComponent(tableIdOrName);
|
|
194
|
+
const data = await this.request('PATCH', `/${id}/${encodedTable}/${recordId}`, {
|
|
195
|
+
fields: options.fields,
|
|
196
|
+
typecast: options.typecast,
|
|
197
|
+
});
|
|
198
|
+
return {
|
|
199
|
+
id: data.id,
|
|
200
|
+
createdTime: data.createdTime,
|
|
201
|
+
fields: data.fields,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Update multiple records (up to 10 at a time)
|
|
206
|
+
*/
|
|
207
|
+
async updateRecords(tableIdOrName, records, baseId) {
|
|
208
|
+
const id = baseId ?? this.baseId;
|
|
209
|
+
if (!id)
|
|
210
|
+
throw new Error('Base ID is required');
|
|
211
|
+
if (records.length > 10) {
|
|
212
|
+
throw new Error('Airtable allows maximum 10 records per request');
|
|
213
|
+
}
|
|
214
|
+
const encodedTable = encodeURIComponent(tableIdOrName);
|
|
215
|
+
const data = await this.request('PATCH', `/${id}/${encodedTable}`, {
|
|
216
|
+
records,
|
|
217
|
+
});
|
|
218
|
+
return data.records.map((r) => ({
|
|
219
|
+
id: r.id,
|
|
220
|
+
createdTime: r.createdTime,
|
|
221
|
+
fields: r.fields,
|
|
222
|
+
}));
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Replace a record (destructive update - clears unspecified fields)
|
|
226
|
+
*/
|
|
227
|
+
async replaceRecord(tableIdOrName, recordId, options, baseId) {
|
|
228
|
+
const id = baseId ?? this.baseId;
|
|
229
|
+
if (!id)
|
|
230
|
+
throw new Error('Base ID is required');
|
|
231
|
+
const encodedTable = encodeURIComponent(tableIdOrName);
|
|
232
|
+
const data = await this.request('PUT', `/${id}/${encodedTable}/${recordId}`, {
|
|
233
|
+
fields: options.fields,
|
|
234
|
+
typecast: options.typecast,
|
|
235
|
+
});
|
|
236
|
+
return {
|
|
237
|
+
id: data.id,
|
|
238
|
+
createdTime: data.createdTime,
|
|
239
|
+
fields: data.fields,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Delete a single record
|
|
244
|
+
*/
|
|
245
|
+
async deleteRecord(tableIdOrName, recordId, baseId) {
|
|
246
|
+
const id = baseId ?? this.baseId;
|
|
247
|
+
if (!id)
|
|
248
|
+
throw new Error('Base ID is required');
|
|
249
|
+
const encodedTable = encodeURIComponent(tableIdOrName);
|
|
250
|
+
return this.request('DELETE', `/${id}/${encodedTable}/${recordId}`);
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Delete multiple records (up to 10 at a time)
|
|
254
|
+
*/
|
|
255
|
+
async deleteRecords(tableIdOrName, recordIds, baseId) {
|
|
256
|
+
const id = baseId ?? this.baseId;
|
|
257
|
+
if (!id)
|
|
258
|
+
throw new Error('Base ID is required');
|
|
259
|
+
if (recordIds.length > 10) {
|
|
260
|
+
throw new Error('Airtable allows maximum 10 records per request');
|
|
261
|
+
}
|
|
262
|
+
const encodedTable = encodeURIComponent(tableIdOrName);
|
|
263
|
+
const params = recordIds.map((rid) => `records[]=${rid}`).join('&');
|
|
264
|
+
return this.request('DELETE', `/${id}/${encodedTable}?${params}`);
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Find records matching a formula
|
|
268
|
+
*/
|
|
269
|
+
async findRecords(tableIdOrName, formula, options = {}, baseId) {
|
|
270
|
+
return this.getAllRecords(tableIdOrName, { ...options, filterByFormula: formula }, baseId);
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Find a single record by field value
|
|
274
|
+
*/
|
|
275
|
+
async findOne(tableIdOrName, fieldName, value, baseId) {
|
|
276
|
+
const formula = typeof value === 'string' ? `{${fieldName}} = "${value}"` : `{${fieldName}} = ${value}`;
|
|
277
|
+
const result = await this.listRecords(tableIdOrName, { filterByFormula: formula, maxRecords: 1 }, baseId);
|
|
278
|
+
return result.records[0] ?? null;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
export const AirtableInitializer = {
|
|
282
|
+
async initialize(_module, config) {
|
|
283
|
+
const token = config.auth?.['token'];
|
|
284
|
+
const baseId = config.options?.['base_id'];
|
|
285
|
+
if (!token) {
|
|
286
|
+
throw new Error('Airtable SDK requires auth.token (personal access token)');
|
|
287
|
+
}
|
|
288
|
+
const client = new AirtableClient(token, baseId);
|
|
289
|
+
return {
|
|
290
|
+
client,
|
|
291
|
+
actions: client,
|
|
292
|
+
};
|
|
293
|
+
},
|
|
294
|
+
};
|
|
295
|
+
//# sourceMappingURL=airtable.js.map
|