commune-ai 0.2.2 → 0.2.4
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 +89 -0
- package/dist/client.d.ts +14 -5
- package/dist/client.js +10 -21
- package/dist/index.js +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/webhooks.js +0 -1
- package/package.json +23 -2
package/README.md
CHANGED
|
@@ -263,6 +263,95 @@ export COMMUNE_API_KEY="your_key_from_dashboard"
|
|
|
263
263
|
|
|
264
264
|
---
|
|
265
265
|
|
|
266
|
+
## Structured extraction (per inbox)
|
|
267
|
+
You can attach a **JSON schema** to a specific inbox so Commune extracts structured data from inbound emails.
|
|
268
|
+
|
|
269
|
+
### 1) Add a schema to an inbox (dashboard)
|
|
270
|
+
In **Dashboard → Inboxes**, open an inbox and add a Structured Extraction schema. Save it and enable extraction.
|
|
271
|
+
|
|
272
|
+
### 2) Set the schema via SDK (optional)
|
|
273
|
+
```ts
|
|
274
|
+
await client.inboxes.setExtractionSchema({
|
|
275
|
+
domainId: "domain-123",
|
|
276
|
+
inboxId: "inbox-456",
|
|
277
|
+
schema: {
|
|
278
|
+
name: "invoice_extraction",
|
|
279
|
+
description: "Extract invoice details",
|
|
280
|
+
enabled: true,
|
|
281
|
+
schema: {
|
|
282
|
+
type: "object",
|
|
283
|
+
properties: {
|
|
284
|
+
invoiceNumber: { type: "string" },
|
|
285
|
+
amount: { type: "number" },
|
|
286
|
+
dueDate: { type: "string" }
|
|
287
|
+
},
|
|
288
|
+
required: ["invoiceNumber", "amount"],
|
|
289
|
+
additionalProperties: false
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### 3) Read extracted data in your webhook
|
|
296
|
+
The webhook payload includes the structured output when extraction is enabled.
|
|
297
|
+
|
|
298
|
+
```ts
|
|
299
|
+
const handler = createWebhookHandler({
|
|
300
|
+
onEvent: async (message, context) => {
|
|
301
|
+
const extracted = context.payload.extractedData
|
|
302
|
+
|| message.metadata?.extracted_data
|
|
303
|
+
|| null;
|
|
304
|
+
|
|
305
|
+
if (extracted) {
|
|
306
|
+
// use structured fields in your agent workflow
|
|
307
|
+
console.log("Extracted:", extracted);
|
|
308
|
+
}
|
|
309
|
+
},
|
|
310
|
+
});
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
> Tip: Keep your schema minimal (only the fields you need). You can evolve it over time.
|
|
314
|
+
|
|
315
|
+
### Example: Invoice extraction (end-to-end)
|
|
316
|
+
```ts
|
|
317
|
+
import { CommuneClient, createWebhookHandler } from "@commune/sdk";
|
|
318
|
+
|
|
319
|
+
const client = new CommuneClient({ apiKey: process.env.COMMUNE_API_KEY! });
|
|
320
|
+
|
|
321
|
+
await client.inboxes.setExtractionSchema({
|
|
322
|
+
domainId: "domain-123",
|
|
323
|
+
inboxId: "inbox-456",
|
|
324
|
+
schema: {
|
|
325
|
+
name: "invoice_extraction",
|
|
326
|
+
enabled: true,
|
|
327
|
+
schema: {
|
|
328
|
+
type: "object",
|
|
329
|
+
properties: {
|
|
330
|
+
invoiceNumber: { type: "string" },
|
|
331
|
+
amount: { type: "number" },
|
|
332
|
+
vendor: { type: "string" }
|
|
333
|
+
},
|
|
334
|
+
required: ["invoiceNumber", "amount"],
|
|
335
|
+
additionalProperties: false
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
const handler = createWebhookHandler({
|
|
341
|
+
onEvent: async (message, context) => {
|
|
342
|
+
const extracted = context.payload.extractedData;
|
|
343
|
+
if (!extracted) return;
|
|
344
|
+
|
|
345
|
+
console.log("Invoice:", extracted.invoiceNumber);
|
|
346
|
+
console.log("Amount:", extracted.amount);
|
|
347
|
+
|
|
348
|
+
await processInvoice(extracted);
|
|
349
|
+
},
|
|
350
|
+
});
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
---
|
|
354
|
+
|
|
266
355
|
## Webhook verification (Commune → your app)
|
|
267
356
|
Commune signs outbound webhooks using your **inbox webhook secret**. Verify the
|
|
268
357
|
signature before processing the request.
|
package/dist/client.d.ts
CHANGED
|
@@ -19,11 +19,6 @@ export declare class CommuneClient {
|
|
|
19
19
|
verify: (domainId: string) => Promise<Record<string, unknown>>;
|
|
20
20
|
records: (domainId: string) => Promise<unknown[]>;
|
|
21
21
|
status: (domainId: string) => Promise<Record<string, unknown>>;
|
|
22
|
-
createWebhook: (domainId: string, payload?: {
|
|
23
|
-
endpoint?: string;
|
|
24
|
-
events?: string[];
|
|
25
|
-
}) => Promise<Record<string, unknown>>;
|
|
26
|
-
saveWebhookSecret: (domainId: string, secret: string) => Promise<Record<string, unknown>>;
|
|
27
22
|
};
|
|
28
23
|
inboxes: {
|
|
29
24
|
list: (domainId: string) => Promise<InboxEntry[]>;
|
|
@@ -46,6 +41,20 @@ export declare class CommuneClient {
|
|
|
46
41
|
endpoint: string;
|
|
47
42
|
events?: string[];
|
|
48
43
|
}) => Promise<InboxEntry>;
|
|
44
|
+
setExtractionSchema: (payload: {
|
|
45
|
+
domainId: string;
|
|
46
|
+
inboxId: string;
|
|
47
|
+
schema: {
|
|
48
|
+
name: string;
|
|
49
|
+
description?: string;
|
|
50
|
+
enabled?: boolean;
|
|
51
|
+
schema: Record<string, any>;
|
|
52
|
+
};
|
|
53
|
+
}) => Promise<InboxEntry>;
|
|
54
|
+
removeExtractionSchema: (payload: {
|
|
55
|
+
domainId: string;
|
|
56
|
+
inboxId: string;
|
|
57
|
+
}) => Promise<InboxEntry>;
|
|
49
58
|
};
|
|
50
59
|
messages: {
|
|
51
60
|
send: (payload: SendMessagePayload) => Promise<Record<string, unknown>>;
|
package/dist/client.js
CHANGED
|
@@ -38,15 +38,6 @@ export class CommuneClient {
|
|
|
38
38
|
status: async (domainId) => {
|
|
39
39
|
return this.request(`/api/domains/${encodeURIComponent(domainId)}/status`);
|
|
40
40
|
},
|
|
41
|
-
createWebhook: async (domainId, payload) => {
|
|
42
|
-
return this.request(`/api/domains/${encodeURIComponent(domainId)}/webhook`, {
|
|
43
|
-
method: 'POST',
|
|
44
|
-
json: payload,
|
|
45
|
-
});
|
|
46
|
-
},
|
|
47
|
-
saveWebhookSecret: async (domainId, secret) => {
|
|
48
|
-
return this.request(`/api/domains/${encodeURIComponent(domainId)}/webhook/secret`, { method: 'POST', json: { secret } });
|
|
49
|
-
},
|
|
50
41
|
};
|
|
51
42
|
this.inboxes = {
|
|
52
43
|
list: async (domainId) => {
|
|
@@ -70,14 +61,20 @@ export class CommuneClient {
|
|
|
70
61
|
setWebhook: async (domainId, inboxId, payload) => {
|
|
71
62
|
return this.request(`/api/domains/${encodeURIComponent(domainId)}/inboxes/${encodeURIComponent(inboxId)}/webhook`, { method: 'POST', json: payload });
|
|
72
63
|
},
|
|
64
|
+
setExtractionSchema: async (payload) => {
|
|
65
|
+
const { domainId, inboxId, schema } = payload;
|
|
66
|
+
return this.request(`/api/domains/${encodeURIComponent(domainId)}/inboxes/${encodeURIComponent(inboxId)}/extraction-schema`, { method: 'PUT', json: schema });
|
|
67
|
+
},
|
|
68
|
+
removeExtractionSchema: async (payload) => {
|
|
69
|
+
const { domainId, inboxId } = payload;
|
|
70
|
+
return this.request(`/api/domains/${encodeURIComponent(domainId)}/inboxes/${encodeURIComponent(inboxId)}/extraction-schema`, { method: 'DELETE' });
|
|
71
|
+
},
|
|
73
72
|
};
|
|
74
73
|
this.messages = {
|
|
75
74
|
send: async (payload) => {
|
|
76
|
-
// Always send as email (Slack support coming soon)
|
|
77
|
-
const emailPayload = { ...payload, channel: 'email' };
|
|
78
75
|
return this.request('/api/messages/send', {
|
|
79
76
|
method: 'POST',
|
|
80
|
-
json:
|
|
77
|
+
json: payload,
|
|
81
78
|
});
|
|
82
79
|
},
|
|
83
80
|
list: async (params) => {
|
|
@@ -99,10 +96,8 @@ export class CommuneClient {
|
|
|
99
96
|
})}`);
|
|
100
97
|
},
|
|
101
98
|
};
|
|
102
|
-
// Semantic search across all organizational emails
|
|
99
|
+
// Semantic search across all organizational emails
|
|
103
100
|
this.search = async (params) => {
|
|
104
|
-
// Placeholder for future semantic search implementation
|
|
105
|
-
// This will search across all emails in the organization
|
|
106
101
|
return this.request(`/api/search${buildQuery({
|
|
107
102
|
q: params.query,
|
|
108
103
|
limit: params.limit || 10,
|
|
@@ -117,16 +112,10 @@ export class CommuneClient {
|
|
|
117
112
|
return this.request(`/api/attachments/${encodeURIComponent(attachmentId)}`);
|
|
118
113
|
},
|
|
119
114
|
};
|
|
120
|
-
if (!options.apiKey) {
|
|
121
|
-
throw new Error('API key is required. Get one from your Commune dashboard at https://commune.ai');
|
|
122
|
-
}
|
|
123
115
|
this.baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, '');
|
|
124
116
|
this.apiKey = options.apiKey;
|
|
125
117
|
this.headers = options.headers;
|
|
126
118
|
this.fetcher = options.fetcher || fetch;
|
|
127
|
-
if (!this.apiKey) {
|
|
128
|
-
throw new Error('CommuneClient requires apiKey');
|
|
129
|
-
}
|
|
130
119
|
}
|
|
131
120
|
async request(path, options = {}) {
|
|
132
121
|
const { json, headers, ...rest } = options;
|
package/dist/index.js
CHANGED
package/dist/types.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export interface MessageMetadata {
|
|
|
17
17
|
message_id?: string | null;
|
|
18
18
|
provider?: 'resend' | 'email' | string;
|
|
19
19
|
raw?: unknown;
|
|
20
|
+
extracted_data?: Record<string, any>;
|
|
20
21
|
}
|
|
21
22
|
export interface UnifiedMessage {
|
|
22
23
|
_id?: string;
|
|
@@ -63,6 +64,12 @@ export interface InboxEntry {
|
|
|
63
64
|
metadata?: Record<string, unknown>;
|
|
64
65
|
};
|
|
65
66
|
webhook?: InboxWebhook;
|
|
67
|
+
extractionSchema?: {
|
|
68
|
+
name: string;
|
|
69
|
+
description?: string;
|
|
70
|
+
schema: Record<string, any>;
|
|
71
|
+
enabled: boolean;
|
|
72
|
+
};
|
|
66
73
|
createdAt?: string;
|
|
67
74
|
status?: string;
|
|
68
75
|
}
|
|
@@ -132,6 +139,7 @@ export interface InboundEmailWebhookPayload {
|
|
|
132
139
|
event: unknown;
|
|
133
140
|
email: unknown;
|
|
134
141
|
message: UnifiedMessage;
|
|
142
|
+
extractedData?: Record<string, any>;
|
|
135
143
|
}
|
|
136
144
|
export interface ApiError {
|
|
137
145
|
message?: string;
|
package/dist/webhooks.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "commune-ai",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "Our email infrastructure - webhooks, threads, history, and semantic search",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -15,9 +15,30 @@
|
|
|
15
15
|
"dist",
|
|
16
16
|
"README.md"
|
|
17
17
|
],
|
|
18
|
+
"keywords": [
|
|
19
|
+
"email",
|
|
20
|
+
"slack",
|
|
21
|
+
"ai",
|
|
22
|
+
"agent",
|
|
23
|
+
"webhook",
|
|
24
|
+
"communication",
|
|
25
|
+
"inbox",
|
|
26
|
+
"api"
|
|
27
|
+
],
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "https://github.com/commune-ai/commune"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://github.com/commune-ai/commune#readme",
|
|
34
|
+
"bugs": {
|
|
35
|
+
"url": "https://github.com/commune-ai/commune/issues"
|
|
36
|
+
},
|
|
18
37
|
"scripts": {
|
|
19
38
|
"build": "tsc -p tsconfig.json",
|
|
20
|
-
"clean": "rm -rf dist"
|
|
39
|
+
"clean": "rm -rf dist",
|
|
40
|
+
"prepublishOnly": "npm run clean && npm run build",
|
|
41
|
+
"prepack": "npm run build"
|
|
21
42
|
},
|
|
22
43
|
"dependencies": {
|
|
23
44
|
"svix": "^1.44.0"
|