chat-agent-toolkit 1.2.72 → 1.2.74
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/connectors/index.d.ts +84 -0
- package/dist/connectors/server.d.ts +46 -0
- package/dist/connectors/smoke-test.d.ts +5 -0
- package/dist/index.d.ts +2 -0
- package/dist/research-agent.cjs.js +1 -1
- package/dist/research-agent.cjs.js.map +1 -1
- package/dist/research-agent.es.js +1 -1
- package/dist/research-agent.es.js.map +1 -1
- package/package.json +13 -2
- package/src/connectors/README.md +374 -0
- package/src/connectors/catalog.json +1 -0
- package/src/connectors/index.ts +128 -0
- package/src/connectors/oomol-saas-server.js +125 -0
- package/src/connectors/package-lock.json +872 -0
- package/src/connectors/package.json +19 -0
- package/src/connectors/server.js +125 -0
- package/src/connectors/server.ts +220 -0
- package/src/connectors/smoke-test.js +14 -0
- package/src/connectors/smoke-test.ts +44 -0
- package/src/index.ts +4 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenConnector Integration for OOMOL SaaS
|
|
3
|
+
*
|
|
4
|
+
* Multi-tenant connector platform for OAuth & credential management.
|
|
5
|
+
* Allows users to link external accounts (Gmail, Slack, GitHub, Airtable, etc.)
|
|
6
|
+
* securely managed by OOMOL Cloud.
|
|
7
|
+
*
|
|
8
|
+
* @module connectors
|
|
9
|
+
* @see {@link https://connector.oomol.com}
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { ProjectConnector } from "chat-agent-toolkit/connectors";
|
|
13
|
+
*
|
|
14
|
+
* const project = new ProjectConnector({
|
|
15
|
+
* apiKey: process.env.OOMOL_PROJECT_API_KEY,
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* const user = project.forUser(userId);
|
|
19
|
+
* const oauth = await user.connect.oauth({
|
|
20
|
+
* service: "gmail",
|
|
21
|
+
* returnUri: "https://myapp.com/oauth-callback",
|
|
22
|
+
* });
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
// Re-export OOMOL Connector SDK types and classes
|
|
27
|
+
export type {
|
|
28
|
+
ConnectorError as OOMOLConnectorError,
|
|
29
|
+
ProjectConnector as OOMOLProjectConnector,
|
|
30
|
+
} from "@oomol-lab/connector";
|
|
31
|
+
export { ConnectorError, ProjectConnector } from "@oomol-lab/connector";
|
|
32
|
+
|
|
33
|
+
// Catalog data: 900+ integrated providers with OAuth/API-key support
|
|
34
|
+
import catalogJson from "./catalog.json";
|
|
35
|
+
import providerIndexJson from "./openconnector-providers-index.json";
|
|
36
|
+
|
|
37
|
+
export type CatalogProvider = {
|
|
38
|
+
service: string;
|
|
39
|
+
displayName: string;
|
|
40
|
+
categories: string[];
|
|
41
|
+
authTypes: ("oauth2" | "api_key" | "custom_credential" | "no_auth")[];
|
|
42
|
+
actionCount: number;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export type ProviderIndexEntry = CatalogProvider & {
|
|
46
|
+
homepageUrl?: string;
|
|
47
|
+
actions?: string[];
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Lightweight provider catalog (basic info: service, display name, auth types).
|
|
52
|
+
* ~900 providers, fast catalog search and picker UI.
|
|
53
|
+
*/
|
|
54
|
+
export const catalog: CatalogProvider[] = catalogJson as CatalogProvider[];
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Detailed provider index with action lists and metadata.
|
|
58
|
+
* Use for deep integration: listing available actions, mapping capabilities.
|
|
59
|
+
*/
|
|
60
|
+
export const providerIndex: ProviderIndexEntry[] =
|
|
61
|
+
providerIndexJson as ProviderIndexEntry[];
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Search the catalog by service name or display name.
|
|
65
|
+
* @param query Search term (case-insensitive)
|
|
66
|
+
* @param limit Max results
|
|
67
|
+
* @returns Matching providers
|
|
68
|
+
*/
|
|
69
|
+
export function searchCatalog(query: string, limit = 100): CatalogProvider[] {
|
|
70
|
+
const q = query.toLowerCase();
|
|
71
|
+
return catalog
|
|
72
|
+
.filter(
|
|
73
|
+
(p) =>
|
|
74
|
+
p.service.toLowerCase().includes(q) ||
|
|
75
|
+
p.displayName.toLowerCase().includes(q)
|
|
76
|
+
)
|
|
77
|
+
.slice(0, limit);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Get a provider by service ID.
|
|
82
|
+
* @param serviceId The provider's service identifier (e.g., "gmail", "slack")
|
|
83
|
+
* @returns Provider info or undefined
|
|
84
|
+
*/
|
|
85
|
+
export function getCatalogProvider(serviceId: string): CatalogProvider | undefined {
|
|
86
|
+
return catalog.find((p) => p.service === serviceId);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Get detailed provider info including actions.
|
|
91
|
+
* @param serviceId The provider's service identifier
|
|
92
|
+
* @returns Detailed provider entry or undefined
|
|
93
|
+
*/
|
|
94
|
+
export function getProviderDetails(serviceId: string): ProviderIndexEntry | undefined {
|
|
95
|
+
return providerIndex.find((p) => p.service === serviceId);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Filter catalog by authentication type.
|
|
100
|
+
* @param authType The auth type to filter by
|
|
101
|
+
* @returns Providers supporting this auth type
|
|
102
|
+
*/
|
|
103
|
+
export function getCatalogByAuthType(
|
|
104
|
+
authType: "oauth2" | "api_key" | "custom_credential" | "no_auth"
|
|
105
|
+
): CatalogProvider[] {
|
|
106
|
+
return catalog.filter((p) => p.authTypes.includes(authType));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Filter catalog by category.
|
|
111
|
+
* @param category The category to filter by (e.g., "Communication", "Productivity")
|
|
112
|
+
* @returns Providers in this category
|
|
113
|
+
*/
|
|
114
|
+
export function getCatalogByCategory(category: string): CatalogProvider[] {
|
|
115
|
+
return catalog.filter((p) => p.categories.includes(category));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Get all unique categories in the catalog.
|
|
120
|
+
* @returns Sorted list of category names
|
|
121
|
+
*/
|
|
122
|
+
export function getCatalogCategories(): string[] {
|
|
123
|
+
const categories = new Set<string>();
|
|
124
|
+
catalog.forEach((p) => p.categories.forEach((c) => categories.add(c)));
|
|
125
|
+
return Array.from(categories).sort();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export type { Express } from "express";
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-tenant connector server on OOMOL Cloud (https://connector.oomol.com/v1).
|
|
3
|
+
*
|
|
4
|
+
* OOMOL hosts everything: OAuth apps, credential vault, token refresh, provider calls.
|
|
5
|
+
* Each of YOUR app's users links THEIR OWN accounts (Gmail, Slack, GitHub, ...) via
|
|
6
|
+
* ProjectConnector — the composio/pipedream "managed auth" model.
|
|
7
|
+
*
|
|
8
|
+
* Setup:
|
|
9
|
+
* 1. Create a project in the OOMOL console and copy its API key (oo_proj_...).
|
|
10
|
+
* 2. OOMOL_PROJECT_API_KEY=oo_proj_... npm start
|
|
11
|
+
*
|
|
12
|
+
* externalUserId = your app's own user id (from your auth/session layer). NEVER let the
|
|
13
|
+
* client pick another user's id — derive it server-side from the authenticated session.
|
|
14
|
+
*/
|
|
15
|
+
import express from "express";
|
|
16
|
+
import { readFile } from "node:fs/promises";
|
|
17
|
+
import { ConnectorError, ProjectConnector } from "@oomol-lab/connector";
|
|
18
|
+
|
|
19
|
+
const PORT = process.env.PORT ?? 8787;
|
|
20
|
+
const APP_ORIGIN = process.env.APP_ORIGIN ?? `http://localhost:${PORT}`;
|
|
21
|
+
|
|
22
|
+
const project = new ProjectConnector({
|
|
23
|
+
apiKey: process.env.OOMOL_PROJECT_API_KEY ?? "oo_proj_missing",
|
|
24
|
+
// baseUrl defaults to OOMOL Cloud: https://connector.oomol.com/v1
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const catalog = JSON.parse(await readFile(new URL("./catalog.json", import.meta.url), "utf8"));
|
|
28
|
+
const byService = new Map(catalog.map((p) => [p.service, p]));
|
|
29
|
+
|
|
30
|
+
const app = express();
|
|
31
|
+
app.use(express.json());
|
|
32
|
+
|
|
33
|
+
// DEMO ONLY: replace with your real session auth. Everything below trusts req.userId.
|
|
34
|
+
app.use((req, _res, next) => {
|
|
35
|
+
req.userId = req.get("x-user-id") ?? "demo_user";
|
|
36
|
+
next();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
/** Provider catalog for your "add a connection" picker. */
|
|
40
|
+
app.get("/api/catalog", (req, res) => {
|
|
41
|
+
const q = (req.query.q ?? "").toString().toLowerCase();
|
|
42
|
+
const list = q
|
|
43
|
+
? catalog.filter((p) => p.service.includes(q) || p.displayName.toLowerCase().includes(q))
|
|
44
|
+
: catalog;
|
|
45
|
+
res.json(list.slice(0, Number(req.query.limit ?? 100)));
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Start a connection for the logged-in user.
|
|
50
|
+
* OAuth providers -> returns { authorizationUrl, requestId } — redirect the user there.
|
|
51
|
+
* API-key/custom -> pass { apiKey } or { values } — connects synchronously.
|
|
52
|
+
*/
|
|
53
|
+
app.post("/api/connections", async (req, res) => {
|
|
54
|
+
const { service, connectionName, apiKey, values } = req.body ?? {};
|
|
55
|
+
const provider = byService.get(service);
|
|
56
|
+
if (!provider) return res.status(404).json({ error: "unknown_service", service });
|
|
57
|
+
|
|
58
|
+
const user = project.forUser(req.userId);
|
|
59
|
+
try {
|
|
60
|
+
if (provider.authTypes.includes("oauth2") && !apiKey && !values) {
|
|
61
|
+
const request = await user.connect.oauth({
|
|
62
|
+
service,
|
|
63
|
+
connectionName,
|
|
64
|
+
returnUri: `${APP_ORIGIN}/connected?service=${encodeURIComponent(service)}`,
|
|
65
|
+
});
|
|
66
|
+
// Redirect your user to authorizationUrl; poll GET /api/connections/requests/:id after.
|
|
67
|
+
return res.json({
|
|
68
|
+
pending: true,
|
|
69
|
+
requestId: request.id,
|
|
70
|
+
authorizationUrl: request.authorizationUrl,
|
|
71
|
+
status: request.status,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
const account = apiKey
|
|
75
|
+
? await user.connect.apiKey({ service, apiKey, connectionName })
|
|
76
|
+
: await user.connect.customCredential({ service, values: values ?? {}, connectionName });
|
|
77
|
+
return res.json({
|
|
78
|
+
pending: false,
|
|
79
|
+
connectedAccountId: account.connectedAccountId,
|
|
80
|
+
status: account.status,
|
|
81
|
+
available: account.available,
|
|
82
|
+
});
|
|
83
|
+
} catch (err) {
|
|
84
|
+
return sendConnectorError(res, err);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
/** Poll an OAuth connection request until the user finishes authorizing. */
|
|
89
|
+
app.get("/api/connections/requests/:id", async (req, res) => {
|
|
90
|
+
try {
|
|
91
|
+
const request = await project.getConnectionRequest(req.params.id);
|
|
92
|
+
res.json(request); // status: initiated | connected | failed | expired
|
|
93
|
+
} catch (err) {
|
|
94
|
+
sendConnectorError(res, err);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
/** Run any catalog action as the logged-in user (e.g. "gmail.search_threads"). */
|
|
99
|
+
app.post("/api/actions/:actionId", async (req, res) => {
|
|
100
|
+
const { input = {}, connectionName } = req.body ?? {};
|
|
101
|
+
try {
|
|
102
|
+
const out = await project
|
|
103
|
+
.forUser(req.userId)
|
|
104
|
+
.executeRaw(req.params.actionId, input, connectionName ? { connectionName } : undefined);
|
|
105
|
+
res.json(out); // { data, executionId, actionId, message }
|
|
106
|
+
} catch (err) {
|
|
107
|
+
sendConnectorError(res, err);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
/** Landing page OOMOL returns the user to after OAuth consent. */
|
|
112
|
+
app.get("/connected", (req, res) => {
|
|
113
|
+
res.send(`<p>${req.query.service ?? "Account"} connected — you can close this tab.</p>`);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
function sendConnectorError(res, err) {
|
|
117
|
+
if (err instanceof ConnectorError) {
|
|
118
|
+
// e.g. provider_config_not_found, connection_alias_conflict, app_not_ready, client_wait_timeout
|
|
119
|
+
return res.status(err.status || 502).json({ error: err.code, message: err.message });
|
|
120
|
+
}
|
|
121
|
+
console.error(err);
|
|
122
|
+
return res.status(500).json({ error: "internal_error" });
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
app.listen(PORT, () => console.log(`OOMOL SaaS connector server on :${PORT} (gateway: connector.oomol.com)`));
|