@keemakr/agent-sdk 0.4.0 → 0.7.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/README.md +94 -22
- package/dist/client.d.ts +53 -3
- package/dist/client.js +52 -6
- package/dist/connectors.d.ts +8 -0
- package/dist/connectors.generated.d.ts +276 -0
- package/dist/connectors.generated.js +240 -0
- package/dist/connectors.js +28 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/verify-grant.d.ts +20 -0
- package/dist/verify-grant.js +52 -0
- package/package.json +10 -4
package/README.md
CHANGED
|
@@ -19,11 +19,11 @@ Peer dependencies (match your eve agent): `eve@0.13.0`, `jose@^6.2.3`.
|
|
|
19
19
|
|
|
20
20
|
Set these in your deployed agent's environment:
|
|
21
21
|
|
|
22
|
-
| Variable
|
|
23
|
-
|
|
24
|
-
| `KEE_CORE_JWKS_URL`
|
|
22
|
+
| Variable | Purpose |
|
|
23
|
+
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
|
|
24
|
+
| `KEE_CORE_JWKS_URL` | keemakr-core's JWKS endpoint, e.g. `https://app.keemakr.com/.well-known/jwks.json`. Enables grant verification. |
|
|
25
25
|
| `KEE_AGENT_AUDIENCE` | This deployment's audience — your runtime URL's origin, e.g. `https://my-agent.example.com`. Must match the audience the operator mints. |
|
|
26
|
-
| `KEE_CORE_URL`
|
|
26
|
+
| `KEE_CORE_URL` | keemakr-core's base URL for capability calls, e.g. `https://app.keemakr.com`. (Derived from `KEE_CORE_JWKS_URL` if unset.) |
|
|
27
27
|
|
|
28
28
|
If `KEE_CORE_JWKS_URL` is unset, `grantAuth()` skips entirely — useful during local development.
|
|
29
29
|
|
|
@@ -32,9 +32,9 @@ If `KEE_CORE_JWKS_URL` is unset, `grantAuth()` skips entirely — useful during
|
|
|
32
32
|
`grantAuth()` returns an eve `AuthFn`. Put it ahead of any fallback:
|
|
33
33
|
|
|
34
34
|
```ts title="agent/channels/eve.ts"
|
|
35
|
-
import { localDev, vercelOidc } from
|
|
36
|
-
import { eveChannel } from
|
|
37
|
-
import { grantAuth } from
|
|
35
|
+
import { localDev, vercelOidc } from 'eve/channels/auth';
|
|
36
|
+
import { eveChannel } from 'eve/channels/eve';
|
|
37
|
+
import { grantAuth } from '@keemakr/agent-sdk';
|
|
38
38
|
|
|
39
39
|
export default eveChannel({
|
|
40
40
|
auth: [localDev(), vercelOidc(), grantAuth()],
|
|
@@ -46,9 +46,9 @@ On success the verified tenant id and scopes are attached to the session auth co
|
|
|
46
46
|
## 2. Reach tenant data from a tool
|
|
47
47
|
|
|
48
48
|
```ts title="agent/tools/find_email.ts"
|
|
49
|
-
import { defineTool } from
|
|
50
|
-
import { z } from
|
|
51
|
-
import { useKee } from
|
|
49
|
+
import { defineTool } from 'eve/tools';
|
|
50
|
+
import { z } from 'zod';
|
|
51
|
+
import { useKee } from '@keemakr/agent-sdk';
|
|
52
52
|
|
|
53
53
|
export default defineTool({
|
|
54
54
|
description: "Find a lead's work email.",
|
|
@@ -60,7 +60,7 @@ export default defineTool({
|
|
|
60
60
|
async execute(args, ctx) {
|
|
61
61
|
const kee = useKee(ctx);
|
|
62
62
|
// Proxy path: the credential stays in keemakr-core; you get the result.
|
|
63
|
-
const result = await kee.connections.hunter.call(
|
|
63
|
+
const result = await kee.connections.hunter.call('email-finder', args);
|
|
64
64
|
return result; // { email, score, status }
|
|
65
65
|
},
|
|
66
66
|
});
|
|
@@ -82,34 +82,106 @@ await kee.connections.get("hunter").call("email-finder", { ... }); // equivalent
|
|
|
82
82
|
const { access_token } = await kee.connections.hunter.token();
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
+
### Discover connectors + operations
|
|
86
|
+
|
|
87
|
+
`@keemakr/agent-sdk/connectors` ships a generated, typed manifest of every connector keemakr-core exposes — provider slugs, `maturity`, and each operation's name + JSON-Schema arg contract. Use it to discover what's callable (and get autocomplete on provider + op names) **without** scanning a core checkout or hitting a running instance. It's **metadata only** — no credentials.
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import { connectors, opNames, isReady } from '@keemakr/agent-sdk/connectors';
|
|
91
|
+
|
|
92
|
+
opNames('hunter'); // → ["email-finder"]
|
|
93
|
+
connectors.hunter.ops['email-finder'].inputSchema; // JSON Schema for the args
|
|
94
|
+
isReady('meta'); // false while a connector is coming_soon
|
|
95
|
+
connectors.meta.maturity; // "coming_soon" | "ready"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
A `coming_soon` connector is declarable in your `entry.json` `dependencies` today; its operations start callable (and `isReady` flips to `true`) once core ships them — **no change to your agent**.
|
|
99
|
+
|
|
100
|
+
**Refresh the manifest** after core ships new connectors/operations (it's a committed snapshot of `GET /api/connections/catalog`):
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
curl -s "$KEE_CORE_URL/api/connections/catalog" > src/connectors.snapshot.json
|
|
104
|
+
npm run gen:connectors # or: npm run build (runs gen first)
|
|
105
|
+
```
|
|
106
|
+
|
|
85
107
|
### Memory (cross-session, tenant-shared)
|
|
86
108
|
|
|
87
109
|
```ts
|
|
88
|
-
await kee.memory.set(
|
|
89
|
-
await kee.memory.get(
|
|
90
|
-
await kee.memory.list(
|
|
91
|
-
await kee.memory.delete(
|
|
110
|
+
await kee.memory.set('prefs', 'tone', { tone: 'formal' });
|
|
111
|
+
await kee.memory.get('prefs', 'tone'); // → { tone: "formal" }
|
|
112
|
+
await kee.memory.list('prefs'); // → entries in the namespace
|
|
113
|
+
await kee.memory.delete('prefs', 'tone');
|
|
92
114
|
// Semantic search by meaning (embeddings):
|
|
93
|
-
const hits = await kee.memory.search(
|
|
115
|
+
const hits = await kee.memory.search('how should I speak to the user?', { limit: 5 });
|
|
94
116
|
// → [{ namespace, key, value, score, … }] (score 0–1, nearest first)
|
|
95
117
|
```
|
|
96
118
|
|
|
119
|
+
Memory is tenant-shared: any of the tenant's installed agents can read/write any
|
|
120
|
+
namespace. Concurrent writers should take turns — every entry carries a
|
|
121
|
+
monotonic `version`, and conditional writes lose gracefully instead of
|
|
122
|
+
clobbering:
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
const entry = await kee.memory.getEntry('crm', 'lead:acme'); // { value, version, … }
|
|
126
|
+
try {
|
|
127
|
+
await kee.memory.set('crm', 'lead:acme', next, { ifVersion: entry!.version });
|
|
128
|
+
} catch (e) {
|
|
129
|
+
if (e instanceof MemoryConflictError) {
|
|
130
|
+
// someone wrote first — e.current is the winning entry; re-read, re-derive, retry
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Or merge one field with no read at all (object values only):
|
|
134
|
+
await kee.memory.patch('crm', 'lead:acme', { status: 'contacted' });
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Use memory for your agent's own continuity (preferences, cursors, entity
|
|
138
|
+
state) — durable documents belong in the tenant knowledge base, which you read
|
|
139
|
+
via `kee.kb`.
|
|
140
|
+
|
|
141
|
+
### Knowledge base (read-only retrieval)
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
const hits = await kee.kb.search('what is our refund policy?', { k: 5 });
|
|
145
|
+
// → [{ text, score, provenance: { title, source_uri, … } }]
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Scoped server-side to the collections bound to your agent + the tenant's
|
|
149
|
+
default corpus + the shared platform KB (`kb:retrieve` scope, granted to every
|
|
150
|
+
install). Hybrid retrieval, reranked in core; `text` may be a wider parent
|
|
151
|
+
context for clause-level documents.
|
|
152
|
+
|
|
97
153
|
### Platform tools
|
|
98
154
|
|
|
99
155
|
```ts
|
|
100
|
-
await kee.tools.list();
|
|
101
|
-
await kee.tools.run(
|
|
156
|
+
await kee.tools.list(); // tools this grant is entitled to
|
|
157
|
+
await kee.tools.run('current-time'); // run one in keemakr-core
|
|
102
158
|
```
|
|
103
159
|
|
|
104
160
|
A call whose grant lacks the required scope returns a `KeeError` with `status: 403`; an expired/invalid grant returns `status: 401`.
|
|
105
161
|
|
|
106
|
-
##
|
|
162
|
+
## Autonomous / scheduled runs
|
|
163
|
+
|
|
164
|
+
A cron/scheduled turn has no operator session, so it gets no session grant. keemakr-core can mint a **machine grant** for it (gated on the tenant's per-install `unattended_consent`). If your remote runs **outside** an eve channel, verify that grant directly:
|
|
107
165
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
166
|
+
```ts
|
|
167
|
+
import { verifyGrant } from '@keemakr/agent-sdk';
|
|
168
|
+
|
|
169
|
+
const claims = await verifyGrant(grantToken, { audience: process.env.KEE_AGENT_AUDIENCE });
|
|
170
|
+
if (!claims) throw new Error('invalid or expired grant');
|
|
171
|
+
// claims.tenantId, claims.scopes, claims.aud, claims.exp
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Inside an eve channel, `grantAuth()` already accepts machine grants (same token shape) — no extra work.
|
|
175
|
+
|
|
176
|
+
## Credential & model contract
|
|
177
|
+
|
|
178
|
+
- **Tenant/service credentials live in keemakr-core**, reached only via the proxy — the credential never crosses the wire. Tenant is always the verified grant, resolved server-side; never pass a tenant id from tool input.
|
|
179
|
+
- **The token path is opt-in and scope-gated** (`conn:<provider>:token`), declared per dependency in `entry.json` (`"access": "token"`).
|
|
180
|
+
- **You MAY hold your own model key.** There is no platform model gateway today, so an agent routing its own LLM calls (its own Anthropic/AI-Gateway key) is expected and fine — that is _not_ a credential leak. A leak is a _tenant/service_ credential read in agent code.
|
|
111
181
|
- Every capability call re-verifies the grant and enforces scope on the server.
|
|
112
182
|
|
|
183
|
+
Full contract: keemakr-core `docs/CONNECTOR-CONTRACT.md`.
|
|
184
|
+
|
|
113
185
|
## License
|
|
114
186
|
|
|
115
187
|
MIT
|
package/dist/client.d.ts
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
export interface KeeError extends Error {
|
|
2
2
|
status?: number;
|
|
3
|
+
/** Parsed error-response body, when core sent one (e.g. the conflicting entry on 409). */
|
|
4
|
+
body?: unknown;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* A conditional memory write (`ifVersion`) lost the race — another agent wrote
|
|
8
|
+
* the key first. `current` is the entry as it now stands (null when the key was
|
|
9
|
+
* deleted concurrently). Re-read, re-derive, retry.
|
|
10
|
+
*/
|
|
11
|
+
export declare class MemoryConflictError extends Error {
|
|
12
|
+
status: 409;
|
|
13
|
+
current: MemoryEntry | null;
|
|
14
|
+
constructor(current: MemoryEntry | null);
|
|
3
15
|
}
|
|
4
16
|
export interface KeeContext {
|
|
5
17
|
session?: {
|
|
@@ -26,6 +38,8 @@ export interface MemoryEntry {
|
|
|
26
38
|
key: string;
|
|
27
39
|
value: unknown;
|
|
28
40
|
written_by_agent: string | null;
|
|
41
|
+
/** Monotonic write counter — pass as `ifVersion` for compare-and-swap writes. */
|
|
42
|
+
version: number;
|
|
29
43
|
created_at: string;
|
|
30
44
|
updated_at: string;
|
|
31
45
|
}
|
|
@@ -43,10 +57,25 @@ export interface MemorySearchHit extends MemoryEntry {
|
|
|
43
57
|
export interface KeeMemory {
|
|
44
58
|
/** Read a key's value, or null if absent. */
|
|
45
59
|
get(namespace: string, key: string): Promise<unknown | null>;
|
|
46
|
-
/** Read the full entry (value + provenance + timestamps), or null. */
|
|
60
|
+
/** Read the full entry (value + provenance + version + timestamps), or null. */
|
|
47
61
|
getEntry(namespace: string, key: string): Promise<MemoryEntry | null>;
|
|
48
|
-
/**
|
|
49
|
-
|
|
62
|
+
/**
|
|
63
|
+
* Write a key. Returns the stored entry. Pass `ifVersion` (from a prior
|
|
64
|
+
* getEntry) to make it a compare-and-swap: throws MemoryConflictError when
|
|
65
|
+
* another agent wrote the key in between.
|
|
66
|
+
*/
|
|
67
|
+
set(namespace: string, key: string, value: unknown, opts?: {
|
|
68
|
+
ifVersion?: number;
|
|
69
|
+
}): Promise<MemoryEntry>;
|
|
70
|
+
/**
|
|
71
|
+
* Shallow-merge `delta` into an existing object value without reading it
|
|
72
|
+
* first — safe under concurrency for the "add one field" case. Throws
|
|
73
|
+
* MemoryConflictError on an `ifVersion` mismatch; a KeeError with status 404
|
|
74
|
+
* when the key is absent, 422 when the stored value isn't an object.
|
|
75
|
+
*/
|
|
76
|
+
patch(namespace: string, key: string, delta: Record<string, unknown>, opts?: {
|
|
77
|
+
ifVersion?: number;
|
|
78
|
+
}): Promise<MemoryEntry>;
|
|
50
79
|
/** Delete a key. Returns whether it existed. */
|
|
51
80
|
delete(namespace: string, key: string): Promise<boolean>;
|
|
52
81
|
/** List every entry in a namespace (tenant-wide). */
|
|
@@ -57,6 +86,26 @@ export interface KeeMemory {
|
|
|
57
86
|
limit?: number;
|
|
58
87
|
}): Promise<MemorySearchHit[]>;
|
|
59
88
|
}
|
|
89
|
+
/** One KB retrieval hit. `text` is the chunk (or its parent context for
|
|
90
|
+
* parent-child-chunked documents); `score` is the reranker's relevance when
|
|
91
|
+
* reranking ran, else the RRF fusion score. */
|
|
92
|
+
export interface KBHit {
|
|
93
|
+
text: string;
|
|
94
|
+
score: number;
|
|
95
|
+
provenance: Record<string, unknown>;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Tenant knowledge-base retrieval. The agent sees the collections bound to it
|
|
99
|
+
* plus the tenant's default corpus plus the shared platform KB — scoping is
|
|
100
|
+
* enforced server-side from the grant. Requires the `kb:retrieve` scope
|
|
101
|
+
* (granted to every install).
|
|
102
|
+
*/
|
|
103
|
+
export interface KeeKb {
|
|
104
|
+
/** Semantic + lexical + reranked search over the agent-visible knowledge. */
|
|
105
|
+
search(query: string, opts?: {
|
|
106
|
+
k?: number;
|
|
107
|
+
}): Promise<KBHit[]>;
|
|
108
|
+
}
|
|
60
109
|
/** Platform registry tools (Shape B) — defined in core, run server-side. */
|
|
61
110
|
export interface KeeTools {
|
|
62
111
|
/** List the registry tools this grant is entitled to. */
|
|
@@ -76,6 +125,7 @@ export interface Kee {
|
|
|
76
125
|
get(provider: string): KeeConnection;
|
|
77
126
|
};
|
|
78
127
|
memory: KeeMemory;
|
|
128
|
+
kb: KeeKb;
|
|
79
129
|
tools: KeeTools;
|
|
80
130
|
}
|
|
81
131
|
/**
|
package/dist/client.js
CHANGED
|
@@ -4,12 +4,27 @@
|
|
|
4
4
|
// /api/capability/* endpoints, forwarding the grant. Core re-verifies the grant
|
|
5
5
|
// and enforces scope on every call; the SDK never sees a raw credential on the
|
|
6
6
|
// proxy path.
|
|
7
|
-
function keeError(message, status) {
|
|
7
|
+
function keeError(message, status, body) {
|
|
8
8
|
const e = new Error(message);
|
|
9
9
|
e.name = 'KeeError';
|
|
10
10
|
e.status = status;
|
|
11
|
+
e.body = body;
|
|
11
12
|
return e;
|
|
12
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* A conditional memory write (`ifVersion`) lost the race — another agent wrote
|
|
16
|
+
* the key first. `current` is the entry as it now stands (null when the key was
|
|
17
|
+
* deleted concurrently). Re-read, re-derive, retry.
|
|
18
|
+
*/
|
|
19
|
+
export class MemoryConflictError extends Error {
|
|
20
|
+
status = 409;
|
|
21
|
+
current;
|
|
22
|
+
constructor(current) {
|
|
23
|
+
super('memory version conflict — the key changed since it was read');
|
|
24
|
+
this.name = 'MemoryConflictError';
|
|
25
|
+
this.current = current;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
13
28
|
function readGrant(ctx) {
|
|
14
29
|
const attrs = ctx?.session?.auth?.current?.attributes ?? {};
|
|
15
30
|
const token = typeof attrs.grant_token === 'string' ? attrs.grant_token : undefined;
|
|
@@ -46,7 +61,7 @@ async function capabilityFetch(grant, path, body, method = 'POST') {
|
|
|
46
61
|
});
|
|
47
62
|
const json = (await res.json().catch(() => ({})));
|
|
48
63
|
if (!res.ok) {
|
|
49
|
-
throw keeError(json.error ?? `capability request failed (${res.status})`, res.status);
|
|
64
|
+
throw keeError(json.error ?? `capability request failed (${res.status})`, res.status, json);
|
|
50
65
|
}
|
|
51
66
|
return json;
|
|
52
67
|
}
|
|
@@ -92,9 +107,31 @@ export function useKee(ctx) {
|
|
|
92
107
|
const entry = await this.getEntry(namespace, key);
|
|
93
108
|
return entry ? entry.value : null;
|
|
94
109
|
},
|
|
95
|
-
async set(namespace, key, value) {
|
|
96
|
-
|
|
97
|
-
|
|
110
|
+
async set(namespace, key, value, opts) {
|
|
111
|
+
try {
|
|
112
|
+
const json = (await capabilityFetch(grant, `memory/${enc(namespace)}/${enc(key)}`, { value, expected_version: opts?.ifVersion }, 'PUT'));
|
|
113
|
+
return json.entry;
|
|
114
|
+
}
|
|
115
|
+
catch (e) {
|
|
116
|
+
if (e.status === 409) {
|
|
117
|
+
const body = e.body;
|
|
118
|
+
throw new MemoryConflictError(body?.entry ?? null);
|
|
119
|
+
}
|
|
120
|
+
throw e;
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
async patch(namespace, key, delta, opts) {
|
|
124
|
+
try {
|
|
125
|
+
const json = (await capabilityFetch(grant, `memory/${enc(namespace)}/${enc(key)}`, { delta, expected_version: opts?.ifVersion }, 'PATCH'));
|
|
126
|
+
return json.entry;
|
|
127
|
+
}
|
|
128
|
+
catch (e) {
|
|
129
|
+
if (e.status === 409) {
|
|
130
|
+
const body = e.body;
|
|
131
|
+
throw new MemoryConflictError(body?.entry ?? null);
|
|
132
|
+
}
|
|
133
|
+
throw e;
|
|
134
|
+
}
|
|
98
135
|
},
|
|
99
136
|
async delete(namespace, key) {
|
|
100
137
|
const json = (await capabilityFetch(grant, `memory/${enc(namespace)}/${enc(key)}`, undefined, 'DELETE'));
|
|
@@ -113,6 +150,15 @@ export function useKee(ctx) {
|
|
|
113
150
|
return json.hits ?? [];
|
|
114
151
|
},
|
|
115
152
|
};
|
|
153
|
+
const kb = {
|
|
154
|
+
async search(query, opts) {
|
|
155
|
+
const json = (await capabilityFetch(grant, 'kb/retrieve', {
|
|
156
|
+
query,
|
|
157
|
+
k: opts?.k,
|
|
158
|
+
}));
|
|
159
|
+
return json.hits ?? [];
|
|
160
|
+
},
|
|
161
|
+
};
|
|
116
162
|
const tools = {
|
|
117
163
|
async list() {
|
|
118
164
|
const json = (await capabilityFetch(grant, 'tools', undefined, 'GET'));
|
|
@@ -125,5 +171,5 @@ export function useKee(ctx) {
|
|
|
125
171
|
return json.result;
|
|
126
172
|
},
|
|
127
173
|
};
|
|
128
|
-
return { tenantId: grant.tenantId, scopes: grant.scopes, connections, memory, tools };
|
|
174
|
+
return { tenantId: grant.tenantId, scopes: grant.scopes, connections, memory, kb, tools };
|
|
129
175
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { connectors, type ConnectorName, type ConnectorInfo, type ConnectorOp, type ConnectorOps, } from './connectors.generated.js';
|
|
2
|
+
import { type ConnectorName } from './connectors.generated.js';
|
|
3
|
+
/** All provider slugs in the manifest. */
|
|
4
|
+
export declare function providerNames(): ConnectorName[];
|
|
5
|
+
/** The operation names a provider exposes (empty for a coming_soon stub). */
|
|
6
|
+
export declare function opNames(provider: ConnectorName): string[];
|
|
7
|
+
/** True when the provider's connect path is proven and its operations are callable. */
|
|
8
|
+
export declare function isReady(provider: ConnectorName): boolean;
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
export type ConnectorName = "agent-sessions" | "apify" | "apollo" | "cal-com" | "calendly" | "clearbit" | "drip" | "elevenlabs" | "facebook" | "fal" | "hubspot" | "hunter" | "instagram" | "instantly" | "mailchimp" | "meta" | "pagespeed" | "posthog" | "salesforce" | "sendgrid" | "slack" | "stripe" | "twilio" | "whatsapp" | "wordpress";
|
|
2
|
+
/** Per-provider operation names (autocomplete for `.call(op)`). */
|
|
3
|
+
export interface ConnectorOps {
|
|
4
|
+
"agent-sessions": never;
|
|
5
|
+
"apify": never;
|
|
6
|
+
"apollo": never;
|
|
7
|
+
"cal-com": never;
|
|
8
|
+
"calendly": never;
|
|
9
|
+
"clearbit": never;
|
|
10
|
+
"drip": never;
|
|
11
|
+
"elevenlabs": never;
|
|
12
|
+
"facebook": never;
|
|
13
|
+
"fal": never;
|
|
14
|
+
"hubspot": never;
|
|
15
|
+
"hunter": "email-finder";
|
|
16
|
+
"instagram": never;
|
|
17
|
+
"instantly": never;
|
|
18
|
+
"mailchimp": never;
|
|
19
|
+
"meta": never;
|
|
20
|
+
"pagespeed": never;
|
|
21
|
+
"posthog": never;
|
|
22
|
+
"salesforce": never;
|
|
23
|
+
"sendgrid": never;
|
|
24
|
+
"slack": never;
|
|
25
|
+
"stripe": never;
|
|
26
|
+
"twilio": never;
|
|
27
|
+
"whatsapp": never;
|
|
28
|
+
"wordpress": never;
|
|
29
|
+
}
|
|
30
|
+
export interface ConnectorOp {
|
|
31
|
+
description: string | null;
|
|
32
|
+
/** JSON Schema (draft 2020-12) for the operation's arguments. */
|
|
33
|
+
inputSchema: unknown;
|
|
34
|
+
}
|
|
35
|
+
export interface ConnectorInfo {
|
|
36
|
+
displayName: string;
|
|
37
|
+
authKind: string;
|
|
38
|
+
category: string | null;
|
|
39
|
+
/** 'ready' → connectable + operations callable; 'coming_soon' → declared, ops not yet wired. */
|
|
40
|
+
maturity: string;
|
|
41
|
+
docUrl: string | null;
|
|
42
|
+
ops: Record<string, ConnectorOp>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The connector catalog as of the last snapshot refresh. Metadata only — no
|
|
46
|
+
* credentials. Keyed by provider slug; each entry lists its callable operations
|
|
47
|
+
* and their JSON-Schema arg contracts.
|
|
48
|
+
*/
|
|
49
|
+
export declare const connectors: {
|
|
50
|
+
readonly "agent-sessions": {
|
|
51
|
+
readonly displayName: "Agent Session Feed";
|
|
52
|
+
readonly authKind: "api_key";
|
|
53
|
+
readonly category: "voice";
|
|
54
|
+
readonly maturity: "ready";
|
|
55
|
+
readonly docUrl: null;
|
|
56
|
+
readonly ops: {};
|
|
57
|
+
};
|
|
58
|
+
readonly apify: {
|
|
59
|
+
readonly displayName: "Apify";
|
|
60
|
+
readonly authKind: "api_key";
|
|
61
|
+
readonly category: "scraping";
|
|
62
|
+
readonly maturity: "ready";
|
|
63
|
+
readonly docUrl: "https://docs.apify.com/api/v2";
|
|
64
|
+
readonly ops: {};
|
|
65
|
+
};
|
|
66
|
+
readonly apollo: {
|
|
67
|
+
readonly displayName: "Apollo.io";
|
|
68
|
+
readonly authKind: "api_key";
|
|
69
|
+
readonly category: "sales-intelligence";
|
|
70
|
+
readonly maturity: "ready";
|
|
71
|
+
readonly docUrl: "https://docs.apollo.io/reference/introduction";
|
|
72
|
+
readonly ops: {};
|
|
73
|
+
};
|
|
74
|
+
readonly "cal-com": {
|
|
75
|
+
readonly displayName: "Cal.com";
|
|
76
|
+
readonly authKind: "api_key";
|
|
77
|
+
readonly category: "scheduling";
|
|
78
|
+
readonly maturity: "ready";
|
|
79
|
+
readonly docUrl: "https://cal.com/docs/api-reference";
|
|
80
|
+
readonly ops: {};
|
|
81
|
+
};
|
|
82
|
+
readonly calendly: {
|
|
83
|
+
readonly displayName: "Calendly";
|
|
84
|
+
readonly authKind: "api_key";
|
|
85
|
+
readonly category: "scheduling";
|
|
86
|
+
readonly maturity: "coming_soon";
|
|
87
|
+
readonly docUrl: "https://developer.calendly.com/api-docs";
|
|
88
|
+
readonly ops: {};
|
|
89
|
+
};
|
|
90
|
+
readonly clearbit: {
|
|
91
|
+
readonly displayName: "Clearbit";
|
|
92
|
+
readonly authKind: "api_key";
|
|
93
|
+
readonly category: "sales-intelligence";
|
|
94
|
+
readonly maturity: "ready";
|
|
95
|
+
readonly docUrl: "https://dashboard.clearbit.com/docs";
|
|
96
|
+
readonly ops: {};
|
|
97
|
+
};
|
|
98
|
+
readonly drip: {
|
|
99
|
+
readonly displayName: "Drip";
|
|
100
|
+
readonly authKind: "api_key";
|
|
101
|
+
readonly category: "email";
|
|
102
|
+
readonly maturity: "ready";
|
|
103
|
+
readonly docUrl: "https://developer.drip.com/";
|
|
104
|
+
readonly ops: {};
|
|
105
|
+
};
|
|
106
|
+
readonly elevenlabs: {
|
|
107
|
+
readonly displayName: "ElevenLabs";
|
|
108
|
+
readonly authKind: "api_key";
|
|
109
|
+
readonly category: "voice";
|
|
110
|
+
readonly maturity: "ready";
|
|
111
|
+
readonly docUrl: "https://elevenlabs.io/docs/api-reference";
|
|
112
|
+
readonly ops: {};
|
|
113
|
+
};
|
|
114
|
+
readonly facebook: {
|
|
115
|
+
readonly displayName: "Facebook";
|
|
116
|
+
readonly authKind: "oauth2";
|
|
117
|
+
readonly category: "channel";
|
|
118
|
+
readonly maturity: "ready";
|
|
119
|
+
readonly docUrl: "https://developers.facebook.com/docs/pages-api";
|
|
120
|
+
readonly ops: {};
|
|
121
|
+
};
|
|
122
|
+
readonly fal: {
|
|
123
|
+
readonly displayName: "fal.ai";
|
|
124
|
+
readonly authKind: "api_key";
|
|
125
|
+
readonly category: "media";
|
|
126
|
+
readonly maturity: "coming_soon";
|
|
127
|
+
readonly docUrl: "https://fal.ai/docs";
|
|
128
|
+
readonly ops: {};
|
|
129
|
+
};
|
|
130
|
+
readonly hubspot: {
|
|
131
|
+
readonly displayName: "HubSpot";
|
|
132
|
+
readonly authKind: "api_key";
|
|
133
|
+
readonly category: "crm";
|
|
134
|
+
readonly maturity: "ready";
|
|
135
|
+
readonly docUrl: "https://developers.hubspot.com/docs/api/private-apps";
|
|
136
|
+
readonly ops: {};
|
|
137
|
+
};
|
|
138
|
+
readonly hunter: {
|
|
139
|
+
readonly displayName: "Hunter.io";
|
|
140
|
+
readonly authKind: "api_key";
|
|
141
|
+
readonly category: "email";
|
|
142
|
+
readonly maturity: "ready";
|
|
143
|
+
readonly docUrl: "https://hunter.io/api-documentation/v2";
|
|
144
|
+
readonly ops: {
|
|
145
|
+
readonly "email-finder": {
|
|
146
|
+
readonly description: "Find a person's email address at a company domain by their name. Returns the email, a confidence score, and verification status.";
|
|
147
|
+
readonly inputSchema: {
|
|
148
|
+
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
|
|
149
|
+
readonly type: "object";
|
|
150
|
+
readonly properties: {
|
|
151
|
+
readonly domain: {
|
|
152
|
+
readonly type: "string";
|
|
153
|
+
readonly minLength: 1;
|
|
154
|
+
readonly description: "Company domain, e.g. \"stripe.com\".";
|
|
155
|
+
};
|
|
156
|
+
readonly first_name: {
|
|
157
|
+
readonly type: "string";
|
|
158
|
+
readonly minLength: 1;
|
|
159
|
+
readonly description: "The person first name.";
|
|
160
|
+
};
|
|
161
|
+
readonly last_name: {
|
|
162
|
+
readonly type: "string";
|
|
163
|
+
readonly minLength: 1;
|
|
164
|
+
readonly description: "The person last name.";
|
|
165
|
+
};
|
|
166
|
+
};
|
|
167
|
+
readonly required: readonly ["domain", "first_name", "last_name"];
|
|
168
|
+
};
|
|
169
|
+
};
|
|
170
|
+
};
|
|
171
|
+
};
|
|
172
|
+
readonly instagram: {
|
|
173
|
+
readonly displayName: "Instagram";
|
|
174
|
+
readonly authKind: "oauth2";
|
|
175
|
+
readonly category: "channel";
|
|
176
|
+
readonly maturity: "ready";
|
|
177
|
+
readonly docUrl: "https://developers.facebook.com/docs/instagram-platform";
|
|
178
|
+
readonly ops: {};
|
|
179
|
+
};
|
|
180
|
+
readonly instantly: {
|
|
181
|
+
readonly displayName: "Instantly.ai";
|
|
182
|
+
readonly authKind: "api_key";
|
|
183
|
+
readonly category: "email";
|
|
184
|
+
readonly maturity: "ready";
|
|
185
|
+
readonly docUrl: "https://developer.instantly.ai/";
|
|
186
|
+
readonly ops: {};
|
|
187
|
+
};
|
|
188
|
+
readonly mailchimp: {
|
|
189
|
+
readonly displayName: "Mailchimp";
|
|
190
|
+
readonly authKind: "api_key";
|
|
191
|
+
readonly category: "email";
|
|
192
|
+
readonly maturity: "ready";
|
|
193
|
+
readonly docUrl: "https://mailchimp.com/developer/marketing/api/";
|
|
194
|
+
readonly ops: {};
|
|
195
|
+
};
|
|
196
|
+
readonly meta: {
|
|
197
|
+
readonly displayName: "Meta Ads (Marketing API)";
|
|
198
|
+
readonly authKind: "api_key";
|
|
199
|
+
readonly category: "advertising";
|
|
200
|
+
readonly maturity: "coming_soon";
|
|
201
|
+
readonly docUrl: "https://developers.facebook.com/docs/marketing-apis";
|
|
202
|
+
readonly ops: {};
|
|
203
|
+
};
|
|
204
|
+
readonly pagespeed: {
|
|
205
|
+
readonly displayName: "PageSpeed Insights";
|
|
206
|
+
readonly authKind: "api_key";
|
|
207
|
+
readonly category: "analytics";
|
|
208
|
+
readonly maturity: "coming_soon";
|
|
209
|
+
readonly docUrl: "https://developers.google.com/speed/docs/insights/v5/get-started";
|
|
210
|
+
readonly ops: {};
|
|
211
|
+
};
|
|
212
|
+
readonly posthog: {
|
|
213
|
+
readonly displayName: "PostHog";
|
|
214
|
+
readonly authKind: "api_key";
|
|
215
|
+
readonly category: "analytics";
|
|
216
|
+
readonly maturity: "ready";
|
|
217
|
+
readonly docUrl: "https://posthog.com/docs/api";
|
|
218
|
+
readonly ops: {};
|
|
219
|
+
};
|
|
220
|
+
readonly salesforce: {
|
|
221
|
+
readonly displayName: "Salesforce";
|
|
222
|
+
readonly authKind: "api_key";
|
|
223
|
+
readonly category: "crm";
|
|
224
|
+
readonly maturity: "coming_soon";
|
|
225
|
+
readonly docUrl: "https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/";
|
|
226
|
+
readonly ops: {};
|
|
227
|
+
};
|
|
228
|
+
readonly sendgrid: {
|
|
229
|
+
readonly displayName: "SendGrid";
|
|
230
|
+
readonly authKind: "api_key";
|
|
231
|
+
readonly category: "email";
|
|
232
|
+
readonly maturity: "ready";
|
|
233
|
+
readonly docUrl: "https://docs.sendgrid.com/api-reference";
|
|
234
|
+
readonly ops: {};
|
|
235
|
+
};
|
|
236
|
+
readonly slack: {
|
|
237
|
+
readonly displayName: "Slack";
|
|
238
|
+
readonly authKind: "api_key";
|
|
239
|
+
readonly category: "messaging";
|
|
240
|
+
readonly maturity: "coming_soon";
|
|
241
|
+
readonly docUrl: "https://api.slack.com/methods/chat.postMessage";
|
|
242
|
+
readonly ops: {};
|
|
243
|
+
};
|
|
244
|
+
readonly stripe: {
|
|
245
|
+
readonly displayName: "Stripe";
|
|
246
|
+
readonly authKind: "oauth2";
|
|
247
|
+
readonly category: "payments";
|
|
248
|
+
readonly maturity: "coming_soon";
|
|
249
|
+
readonly docUrl: "https://docs.stripe.com/connect/oauth-reference";
|
|
250
|
+
readonly ops: {};
|
|
251
|
+
};
|
|
252
|
+
readonly twilio: {
|
|
253
|
+
readonly displayName: "Twilio";
|
|
254
|
+
readonly authKind: "api_key";
|
|
255
|
+
readonly category: "sms";
|
|
256
|
+
readonly maturity: "ready";
|
|
257
|
+
readonly docUrl: "https://www.twilio.com/docs/usage/api";
|
|
258
|
+
readonly ops: {};
|
|
259
|
+
};
|
|
260
|
+
readonly whatsapp: {
|
|
261
|
+
readonly displayName: "WhatsApp";
|
|
262
|
+
readonly authKind: "oauth2";
|
|
263
|
+
readonly category: "channel";
|
|
264
|
+
readonly maturity: "coming_soon";
|
|
265
|
+
readonly docUrl: "https://developers.facebook.com/docs/whatsapp";
|
|
266
|
+
readonly ops: {};
|
|
267
|
+
};
|
|
268
|
+
readonly wordpress: {
|
|
269
|
+
readonly displayName: "WordPress";
|
|
270
|
+
readonly authKind: "oauth2";
|
|
271
|
+
readonly category: "cms";
|
|
272
|
+
readonly maturity: "ready";
|
|
273
|
+
readonly docUrl: "https://developer.wordpress.com/docs/oauth2/";
|
|
274
|
+
readonly ops: {};
|
|
275
|
+
};
|
|
276
|
+
};
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
// AUTO-GENERATED by scripts/gen-connectors.mjs — DO NOT EDIT BY HAND.
|
|
2
|
+
// Source: src/connectors.snapshot.json (a committed copy of keemakr-core's
|
|
3
|
+
// GET /api/connections/catalog). Refresh: see scripts/gen-connectors.mjs header.
|
|
4
|
+
/**
|
|
5
|
+
* The connector catalog as of the last snapshot refresh. Metadata only — no
|
|
6
|
+
* credentials. Keyed by provider slug; each entry lists its callable operations
|
|
7
|
+
* and their JSON-Schema arg contracts.
|
|
8
|
+
*/
|
|
9
|
+
export const connectors = {
|
|
10
|
+
"agent-sessions": {
|
|
11
|
+
"displayName": "Agent Session Feed",
|
|
12
|
+
"authKind": "api_key",
|
|
13
|
+
"category": "voice",
|
|
14
|
+
"maturity": "ready",
|
|
15
|
+
"docUrl": null,
|
|
16
|
+
"ops": {}
|
|
17
|
+
},
|
|
18
|
+
"apify": {
|
|
19
|
+
"displayName": "Apify",
|
|
20
|
+
"authKind": "api_key",
|
|
21
|
+
"category": "scraping",
|
|
22
|
+
"maturity": "ready",
|
|
23
|
+
"docUrl": "https://docs.apify.com/api/v2",
|
|
24
|
+
"ops": {}
|
|
25
|
+
},
|
|
26
|
+
"apollo": {
|
|
27
|
+
"displayName": "Apollo.io",
|
|
28
|
+
"authKind": "api_key",
|
|
29
|
+
"category": "sales-intelligence",
|
|
30
|
+
"maturity": "ready",
|
|
31
|
+
"docUrl": "https://docs.apollo.io/reference/introduction",
|
|
32
|
+
"ops": {}
|
|
33
|
+
},
|
|
34
|
+
"cal-com": {
|
|
35
|
+
"displayName": "Cal.com",
|
|
36
|
+
"authKind": "api_key",
|
|
37
|
+
"category": "scheduling",
|
|
38
|
+
"maturity": "ready",
|
|
39
|
+
"docUrl": "https://cal.com/docs/api-reference",
|
|
40
|
+
"ops": {}
|
|
41
|
+
},
|
|
42
|
+
"calendly": {
|
|
43
|
+
"displayName": "Calendly",
|
|
44
|
+
"authKind": "api_key",
|
|
45
|
+
"category": "scheduling",
|
|
46
|
+
"maturity": "coming_soon",
|
|
47
|
+
"docUrl": "https://developer.calendly.com/api-docs",
|
|
48
|
+
"ops": {}
|
|
49
|
+
},
|
|
50
|
+
"clearbit": {
|
|
51
|
+
"displayName": "Clearbit",
|
|
52
|
+
"authKind": "api_key",
|
|
53
|
+
"category": "sales-intelligence",
|
|
54
|
+
"maturity": "ready",
|
|
55
|
+
"docUrl": "https://dashboard.clearbit.com/docs",
|
|
56
|
+
"ops": {}
|
|
57
|
+
},
|
|
58
|
+
"drip": {
|
|
59
|
+
"displayName": "Drip",
|
|
60
|
+
"authKind": "api_key",
|
|
61
|
+
"category": "email",
|
|
62
|
+
"maturity": "ready",
|
|
63
|
+
"docUrl": "https://developer.drip.com/",
|
|
64
|
+
"ops": {}
|
|
65
|
+
},
|
|
66
|
+
"elevenlabs": {
|
|
67
|
+
"displayName": "ElevenLabs",
|
|
68
|
+
"authKind": "api_key",
|
|
69
|
+
"category": "voice",
|
|
70
|
+
"maturity": "ready",
|
|
71
|
+
"docUrl": "https://elevenlabs.io/docs/api-reference",
|
|
72
|
+
"ops": {}
|
|
73
|
+
},
|
|
74
|
+
"facebook": {
|
|
75
|
+
"displayName": "Facebook",
|
|
76
|
+
"authKind": "oauth2",
|
|
77
|
+
"category": "channel",
|
|
78
|
+
"maturity": "ready",
|
|
79
|
+
"docUrl": "https://developers.facebook.com/docs/pages-api",
|
|
80
|
+
"ops": {}
|
|
81
|
+
},
|
|
82
|
+
"fal": {
|
|
83
|
+
"displayName": "fal.ai",
|
|
84
|
+
"authKind": "api_key",
|
|
85
|
+
"category": "media",
|
|
86
|
+
"maturity": "coming_soon",
|
|
87
|
+
"docUrl": "https://fal.ai/docs",
|
|
88
|
+
"ops": {}
|
|
89
|
+
},
|
|
90
|
+
"hubspot": {
|
|
91
|
+
"displayName": "HubSpot",
|
|
92
|
+
"authKind": "api_key",
|
|
93
|
+
"category": "crm",
|
|
94
|
+
"maturity": "ready",
|
|
95
|
+
"docUrl": "https://developers.hubspot.com/docs/api/private-apps",
|
|
96
|
+
"ops": {}
|
|
97
|
+
},
|
|
98
|
+
"hunter": {
|
|
99
|
+
"displayName": "Hunter.io",
|
|
100
|
+
"authKind": "api_key",
|
|
101
|
+
"category": "email",
|
|
102
|
+
"maturity": "ready",
|
|
103
|
+
"docUrl": "https://hunter.io/api-documentation/v2",
|
|
104
|
+
"ops": {
|
|
105
|
+
"email-finder": {
|
|
106
|
+
"description": "Find a person's email address at a company domain by their name. Returns the email, a confidence score, and verification status.",
|
|
107
|
+
"inputSchema": {
|
|
108
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
109
|
+
"type": "object",
|
|
110
|
+
"properties": {
|
|
111
|
+
"domain": {
|
|
112
|
+
"type": "string",
|
|
113
|
+
"minLength": 1,
|
|
114
|
+
"description": "Company domain, e.g. \"stripe.com\"."
|
|
115
|
+
},
|
|
116
|
+
"first_name": {
|
|
117
|
+
"type": "string",
|
|
118
|
+
"minLength": 1,
|
|
119
|
+
"description": "The person first name."
|
|
120
|
+
},
|
|
121
|
+
"last_name": {
|
|
122
|
+
"type": "string",
|
|
123
|
+
"minLength": 1,
|
|
124
|
+
"description": "The person last name."
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
"required": [
|
|
128
|
+
"domain",
|
|
129
|
+
"first_name",
|
|
130
|
+
"last_name"
|
|
131
|
+
]
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
"instagram": {
|
|
137
|
+
"displayName": "Instagram",
|
|
138
|
+
"authKind": "oauth2",
|
|
139
|
+
"category": "channel",
|
|
140
|
+
"maturity": "ready",
|
|
141
|
+
"docUrl": "https://developers.facebook.com/docs/instagram-platform",
|
|
142
|
+
"ops": {}
|
|
143
|
+
},
|
|
144
|
+
"instantly": {
|
|
145
|
+
"displayName": "Instantly.ai",
|
|
146
|
+
"authKind": "api_key",
|
|
147
|
+
"category": "email",
|
|
148
|
+
"maturity": "ready",
|
|
149
|
+
"docUrl": "https://developer.instantly.ai/",
|
|
150
|
+
"ops": {}
|
|
151
|
+
},
|
|
152
|
+
"mailchimp": {
|
|
153
|
+
"displayName": "Mailchimp",
|
|
154
|
+
"authKind": "api_key",
|
|
155
|
+
"category": "email",
|
|
156
|
+
"maturity": "ready",
|
|
157
|
+
"docUrl": "https://mailchimp.com/developer/marketing/api/",
|
|
158
|
+
"ops": {}
|
|
159
|
+
},
|
|
160
|
+
"meta": {
|
|
161
|
+
"displayName": "Meta Ads (Marketing API)",
|
|
162
|
+
"authKind": "api_key",
|
|
163
|
+
"category": "advertising",
|
|
164
|
+
"maturity": "coming_soon",
|
|
165
|
+
"docUrl": "https://developers.facebook.com/docs/marketing-apis",
|
|
166
|
+
"ops": {}
|
|
167
|
+
},
|
|
168
|
+
"pagespeed": {
|
|
169
|
+
"displayName": "PageSpeed Insights",
|
|
170
|
+
"authKind": "api_key",
|
|
171
|
+
"category": "analytics",
|
|
172
|
+
"maturity": "coming_soon",
|
|
173
|
+
"docUrl": "https://developers.google.com/speed/docs/insights/v5/get-started",
|
|
174
|
+
"ops": {}
|
|
175
|
+
},
|
|
176
|
+
"posthog": {
|
|
177
|
+
"displayName": "PostHog",
|
|
178
|
+
"authKind": "api_key",
|
|
179
|
+
"category": "analytics",
|
|
180
|
+
"maturity": "ready",
|
|
181
|
+
"docUrl": "https://posthog.com/docs/api",
|
|
182
|
+
"ops": {}
|
|
183
|
+
},
|
|
184
|
+
"salesforce": {
|
|
185
|
+
"displayName": "Salesforce",
|
|
186
|
+
"authKind": "api_key",
|
|
187
|
+
"category": "crm",
|
|
188
|
+
"maturity": "coming_soon",
|
|
189
|
+
"docUrl": "https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/",
|
|
190
|
+
"ops": {}
|
|
191
|
+
},
|
|
192
|
+
"sendgrid": {
|
|
193
|
+
"displayName": "SendGrid",
|
|
194
|
+
"authKind": "api_key",
|
|
195
|
+
"category": "email",
|
|
196
|
+
"maturity": "ready",
|
|
197
|
+
"docUrl": "https://docs.sendgrid.com/api-reference",
|
|
198
|
+
"ops": {}
|
|
199
|
+
},
|
|
200
|
+
"slack": {
|
|
201
|
+
"displayName": "Slack",
|
|
202
|
+
"authKind": "api_key",
|
|
203
|
+
"category": "messaging",
|
|
204
|
+
"maturity": "coming_soon",
|
|
205
|
+
"docUrl": "https://api.slack.com/methods/chat.postMessage",
|
|
206
|
+
"ops": {}
|
|
207
|
+
},
|
|
208
|
+
"stripe": {
|
|
209
|
+
"displayName": "Stripe",
|
|
210
|
+
"authKind": "oauth2",
|
|
211
|
+
"category": "payments",
|
|
212
|
+
"maturity": "coming_soon",
|
|
213
|
+
"docUrl": "https://docs.stripe.com/connect/oauth-reference",
|
|
214
|
+
"ops": {}
|
|
215
|
+
},
|
|
216
|
+
"twilio": {
|
|
217
|
+
"displayName": "Twilio",
|
|
218
|
+
"authKind": "api_key",
|
|
219
|
+
"category": "sms",
|
|
220
|
+
"maturity": "ready",
|
|
221
|
+
"docUrl": "https://www.twilio.com/docs/usage/api",
|
|
222
|
+
"ops": {}
|
|
223
|
+
},
|
|
224
|
+
"whatsapp": {
|
|
225
|
+
"displayName": "WhatsApp",
|
|
226
|
+
"authKind": "oauth2",
|
|
227
|
+
"category": "channel",
|
|
228
|
+
"maturity": "coming_soon",
|
|
229
|
+
"docUrl": "https://developers.facebook.com/docs/whatsapp",
|
|
230
|
+
"ops": {}
|
|
231
|
+
},
|
|
232
|
+
"wordpress": {
|
|
233
|
+
"displayName": "WordPress",
|
|
234
|
+
"authKind": "oauth2",
|
|
235
|
+
"category": "cms",
|
|
236
|
+
"maturity": "ready",
|
|
237
|
+
"docUrl": "https://developer.wordpress.com/docs/oauth2/",
|
|
238
|
+
"ops": {}
|
|
239
|
+
}
|
|
240
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// @keemakr/agent-sdk/connectors — the generated connector manifest.
|
|
2
|
+
//
|
|
3
|
+
// A typed, metadata-only view of keemakr-core's connector catalog so an agent
|
|
4
|
+
// author (and the port kit) can discover providers + operation names + their arg
|
|
5
|
+
// schemas WITHOUT scanning a core checkout or hitting a running instance. Credential-
|
|
6
|
+
// free by construction — this is the same data GET /api/connections/catalog serves,
|
|
7
|
+
// committed as a snapshot (src/connectors.snapshot.json) and codegen'd into
|
|
8
|
+
// connectors.generated.ts. Refresh: see scripts/gen-connectors.mjs.
|
|
9
|
+
//
|
|
10
|
+
// Usage:
|
|
11
|
+
// import { connectors, opNames } from '@keemakr/agent-sdk/connectors';
|
|
12
|
+
// connectors.hunter.ops['email-finder'].inputSchema; // JSON Schema for the args
|
|
13
|
+
// opNames('meta'); // string[] of meta's op names
|
|
14
|
+
// isReady('meta'); // false while coming_soon
|
|
15
|
+
export { connectors, } from './connectors.generated.js';
|
|
16
|
+
import { connectors } from './connectors.generated.js';
|
|
17
|
+
/** All provider slugs in the manifest. */
|
|
18
|
+
export function providerNames() {
|
|
19
|
+
return Object.keys(connectors);
|
|
20
|
+
}
|
|
21
|
+
/** The operation names a provider exposes (empty for a coming_soon stub). */
|
|
22
|
+
export function opNames(provider) {
|
|
23
|
+
return Object.keys(connectors[provider]?.ops ?? {});
|
|
24
|
+
}
|
|
25
|
+
/** True when the provider's connect path is proven and its operations are callable. */
|
|
26
|
+
export function isReady(provider) {
|
|
27
|
+
return connectors[provider]?.maturity === 'ready';
|
|
28
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { grantAuth } from './grant-auth.js';
|
|
2
|
-
export {
|
|
2
|
+
export { verifyGrant, type VerifiedGrant } from './verify-grant.js';
|
|
3
|
+
export { useKee, MemoryConflictError, type Kee, type KeeConnection, type KeeContext, type KeeError, type KeeMemory, type KeeKb, type KBHit, type KeeTools, type MemoryEntry, type MemorySearchHit, } from './client.js';
|
|
3
4
|
export { keemakrToolDirectory } from './tool-directory.js';
|
package/dist/index.js
CHANGED
|
@@ -9,5 +9,6 @@
|
|
|
9
9
|
// const kee = useKee(ctx);
|
|
10
10
|
// const r = await kee.connections.hunter.call('email-finder', { domain, first_name, last_name });
|
|
11
11
|
export { grantAuth } from './grant-auth.js';
|
|
12
|
-
export {
|
|
12
|
+
export { verifyGrant } from './verify-grant.js';
|
|
13
|
+
export { useKee, MemoryConflictError, } from './client.js';
|
|
13
14
|
export { keemakrToolDirectory } from './tool-directory.js';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Trusted claims after verifyGrant() succeeds. */
|
|
2
|
+
export interface VerifiedGrant {
|
|
3
|
+
tenantId: string;
|
|
4
|
+
installedAgent: string | null;
|
|
5
|
+
scopes: string[];
|
|
6
|
+
traceId: string | null;
|
|
7
|
+
aud: string | null;
|
|
8
|
+
exp: number | null;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Verify a capability grant (session OR machine) against keemakr-core's JWKS.
|
|
12
|
+
* Returns the trusted claims, or `null` on any failure (bad signature, wrong
|
|
13
|
+
* issuer/audience, expired). Both `jwksUrl` and `audience` fall back to
|
|
14
|
+
* KEE_CORE_JWKS_URL / KEE_AGENT_AUDIENCE. `audience` is strongly recommended: a
|
|
15
|
+
* grant is only valid for the remote it was minted for.
|
|
16
|
+
*/
|
|
17
|
+
export declare function verifyGrant(token: string, opts?: {
|
|
18
|
+
jwksUrl?: string;
|
|
19
|
+
audience?: string;
|
|
20
|
+
}): Promise<VerifiedGrant | null>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Standalone capability-grant verification — for a scheduled/headless remote.
|
|
2
|
+
//
|
|
3
|
+
// grantAuth() (grant-auth.ts) is the right entry point for an eve CHANNEL: it
|
|
4
|
+
// returns an AuthFn. But an autonomous/machine turn may run OUTSIDE a channel (a
|
|
5
|
+
// cron worker that received a machine grant from core's machine-grant endpoint
|
|
6
|
+
// and wants to verify it before acting). verifyGrant() is that path: give it the
|
|
7
|
+
// token, get back the trusted claims (or null), verifying signature + issuer +
|
|
8
|
+
// audience against core's JWKS.
|
|
9
|
+
//
|
|
10
|
+
// A machine grant is the SAME token shape as a session grant (same issuer, aud,
|
|
11
|
+
// tenant_id, scopes) — only the TTL and the mint path differ — so this one
|
|
12
|
+
// verifier covers both.
|
|
13
|
+
import { createRemoteJWKSet, jwtVerify } from 'jose';
|
|
14
|
+
const GRANT_ISSUER = 'keemakr';
|
|
15
|
+
let jwks = null;
|
|
16
|
+
function jwksFor(url) {
|
|
17
|
+
if (!jwks)
|
|
18
|
+
jwks = createRemoteJWKSet(new URL(url));
|
|
19
|
+
return jwks;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Verify a capability grant (session OR machine) against keemakr-core's JWKS.
|
|
23
|
+
* Returns the trusted claims, or `null` on any failure (bad signature, wrong
|
|
24
|
+
* issuer/audience, expired). Both `jwksUrl` and `audience` fall back to
|
|
25
|
+
* KEE_CORE_JWKS_URL / KEE_AGENT_AUDIENCE. `audience` is strongly recommended: a
|
|
26
|
+
* grant is only valid for the remote it was minted for.
|
|
27
|
+
*/
|
|
28
|
+
export async function verifyGrant(token, opts) {
|
|
29
|
+
const jwksUrl = opts?.jwksUrl ?? process.env.KEE_CORE_JWKS_URL;
|
|
30
|
+
if (!jwksUrl)
|
|
31
|
+
return null;
|
|
32
|
+
const expectedAud = opts?.audience ?? process.env.KEE_AGENT_AUDIENCE;
|
|
33
|
+
try {
|
|
34
|
+
const { payload } = await jwtVerify(token, jwksFor(jwksUrl), {
|
|
35
|
+
issuer: GRANT_ISSUER,
|
|
36
|
+
...(expectedAud ? { audience: expectedAud } : {}),
|
|
37
|
+
});
|
|
38
|
+
if (typeof payload.tenant_id !== 'string' || !Array.isArray(payload.scopes))
|
|
39
|
+
return null;
|
|
40
|
+
return {
|
|
41
|
+
tenantId: payload.tenant_id,
|
|
42
|
+
installedAgent: typeof payload.installed_agent === 'string' ? payload.installed_agent : null,
|
|
43
|
+
scopes: payload.scopes.map(String),
|
|
44
|
+
traceId: typeof payload.trace_id === 'string' ? payload.trace_id : null,
|
|
45
|
+
aud: typeof payload.aud === 'string' ? payload.aud : null,
|
|
46
|
+
exp: typeof payload.exp === 'number' ? payload.exp : null,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@keemakr/agent-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "The floor for keemakr marketplace agents: verify the capability grant and reach tenant connections, memory, and shared platform tools through keemakr-core — without holding raw secrets or resolving the tenant yourself.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
"./tool-directory": {
|
|
15
15
|
"types": "./dist/tool-directory.d.ts",
|
|
16
16
|
"import": "./dist/tool-directory.js"
|
|
17
|
+
},
|
|
18
|
+
"./connectors": {
|
|
19
|
+
"types": "./dist/connectors.d.ts",
|
|
20
|
+
"import": "./dist/connectors.js"
|
|
17
21
|
}
|
|
18
22
|
},
|
|
19
23
|
"files": [
|
|
@@ -25,11 +29,13 @@
|
|
|
25
29
|
},
|
|
26
30
|
"repository": {
|
|
27
31
|
"type": "git",
|
|
28
|
-
"url": "git+https://github.com/fsztpartners/keemakr
|
|
32
|
+
"url": "git+https://github.com/fsztpartners/keemakr.git",
|
|
33
|
+
"directory": "packages/agent-sdk"
|
|
29
34
|
},
|
|
30
35
|
"scripts": {
|
|
31
|
-
"
|
|
32
|
-
"
|
|
36
|
+
"gen:connectors": "node scripts/gen-connectors.mjs",
|
|
37
|
+
"build": "npm run gen:connectors && tsc -p tsconfig.json",
|
|
38
|
+
"typecheck": "npm run gen:connectors && tsc --noEmit",
|
|
33
39
|
"prepublishOnly": "npm run build"
|
|
34
40
|
},
|
|
35
41
|
"peerDependencies": {
|