@okrlinkhub/agent-bridge 0.2.0 → 2.0.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.
Files changed (69) hide show
  1. package/README.md +96 -127
  2. package/dist/cli/init.d.ts +3 -0
  3. package/dist/cli/init.d.ts.map +1 -0
  4. package/dist/cli/init.js +100 -0
  5. package/dist/cli/init.js.map +1 -0
  6. package/dist/client/index.d.ts +50 -262
  7. package/dist/client/index.d.ts.map +1 -1
  8. package/dist/client/index.js +127 -536
  9. package/dist/client/index.js.map +1 -1
  10. package/dist/component/_generated/api.d.ts +4 -8
  11. package/dist/component/_generated/api.d.ts.map +1 -1
  12. package/dist/component/_generated/api.js.map +1 -1
  13. package/dist/component/_generated/component.d.ts +58 -257
  14. package/dist/component/_generated/component.d.ts.map +1 -1
  15. package/dist/component/agentBridgeUtils.d.ts +8 -0
  16. package/dist/component/agentBridgeUtils.d.ts.map +1 -0
  17. package/dist/component/agentBridgeUtils.js +33 -0
  18. package/dist/component/agentBridgeUtils.js.map +1 -0
  19. package/dist/component/agents.d.ts +27 -0
  20. package/dist/component/agents.d.ts.map +1 -0
  21. package/dist/component/agents.js +94 -0
  22. package/dist/component/agents.js.map +1 -0
  23. package/dist/component/gateway.d.ts +25 -55
  24. package/dist/component/gateway.d.ts.map +1 -1
  25. package/dist/component/gateway.js +120 -205
  26. package/dist/component/gateway.js.map +1 -1
  27. package/dist/component/permissions.d.ts +30 -84
  28. package/dist/component/permissions.d.ts.map +1 -1
  29. package/dist/component/permissions.js +80 -203
  30. package/dist/component/permissions.js.map +1 -1
  31. package/dist/component/schema.d.ts +55 -223
  32. package/dist/component/schema.d.ts.map +1 -1
  33. package/dist/component/schema.js +30 -126
  34. package/dist/component/schema.js.map +1 -1
  35. package/dist/react/index.d.ts +2 -2
  36. package/dist/react/index.d.ts.map +1 -1
  37. package/dist/react/index.js +2 -3
  38. package/dist/react/index.js.map +1 -1
  39. package/package.json +3 -2
  40. package/src/cli/init.ts +116 -0
  41. package/src/client/index.ts +224 -792
  42. package/src/component/_generated/api.ts +4 -8
  43. package/src/component/_generated/component.ts +55 -312
  44. package/src/component/agentBridgeUtils.ts +52 -0
  45. package/src/component/agents.ts +106 -0
  46. package/src/component/gateway.ts +142 -252
  47. package/src/component/permissions.ts +89 -259
  48. package/src/component/schema.ts +32 -146
  49. package/src/react/index.ts +5 -6
  50. package/dist/component/channels.d.ts +0 -83
  51. package/dist/component/channels.d.ts.map +0 -1
  52. package/dist/component/channels.js +0 -288
  53. package/dist/component/channels.js.map +0 -1
  54. package/dist/component/circuitBreaker.d.ts +0 -73
  55. package/dist/component/circuitBreaker.d.ts.map +0 -1
  56. package/dist/component/circuitBreaker.js +0 -216
  57. package/dist/component/circuitBreaker.js.map +0 -1
  58. package/dist/component/provisioning.d.ts +0 -87
  59. package/dist/component/provisioning.d.ts.map +0 -1
  60. package/dist/component/provisioning.js +0 -343
  61. package/dist/component/provisioning.js.map +0 -1
  62. package/dist/component/registry.d.ts +0 -46
  63. package/dist/component/registry.d.ts.map +0 -1
  64. package/dist/component/registry.js +0 -121
  65. package/dist/component/registry.js.map +0 -1
  66. package/src/component/channels.ts +0 -374
  67. package/src/component/circuitBreaker.ts +0 -250
  68. package/src/component/provisioning.ts +0 -402
  69. package/src/component/registry.ts +0 -152
package/README.md CHANGED
@@ -1,181 +1,150 @@
1
- # Convex Agent Bridge
1
+ # Convex Agent Bridge (Config-First)
2
2
 
3
3
  [![npm version](https://badge.fury.io/js/@okrlinkhub%2Fagent-bridge.svg)](https://badge.fury.io/js/@okrlinkhub%2Fagent-bridge)
4
4
 
5
- A Convex component that acts as a **Security Gateway** between external AI agents
6
- (e.g. OpenClaw on Railway) and your Convex app's functions. It provides:
5
+ `@okrlinkhub/agent-bridge` espone un gateway HTTP per agenti esterni con approccio **config-first**:
7
6
 
8
- - **Function Handle Registry**: Register which of your app's functions agents can call
9
- - **Dynamic Permissions**: Pattern-based access control (e.g. `"okr:read*"` -> allow)
10
- - **Distributed Provisioning**: Token-based agent registration with self-service onboarding
11
- - **Audit Logging**: Full access log of all agent interactions
12
- - **HTTP Gateway**: Single endpoint for agents to call registered functions securely
7
+ - dichiari le funzioni Convex esposte in un solo file;
8
+ - configuri i permessi in batch solo su quelle funzioni;
9
+ - non modifichi query/mutation/action Convex esistenti.
13
10
 
14
- Found a bug? Feature request?
15
- [File it here](https://github.com/okrlinkhub/agent-bridge/issues).
16
-
17
- ## Installation
11
+ ## Installazione
18
12
 
19
13
  ```sh
20
14
  npm install @okrlinkhub/agent-bridge
21
15
  ```
22
16
 
23
- Add the component to your `convex/convex.config.ts`:
17
+ ## Setup rapido
18
+
19
+ ### 1) Inizializza i file nel consumer
20
+
21
+ ```sh
22
+ npx @okrlinkhub/agent-bridge init
23
+ ```
24
+
25
+ Questo genera:
26
+
27
+ - `agent-bridge.config.ts`
28
+ - `convex/agentBridge.ts`
29
+
30
+ ### 2) Abilita il componente in `convex/convex.config.ts`
24
31
 
25
32
  ```ts
26
- // convex/convex.config.ts
27
33
  import { defineApp } from "convex/server";
28
34
  import agentBridge from "@okrlinkhub/agent-bridge/convex.config.js";
29
35
 
30
36
  const app = defineApp();
31
37
  app.use(agentBridge);
32
-
33
38
  export default app;
34
39
  ```
35
40
 
36
- ## Quick Start
37
-
38
- ### 1. Initialize the client
41
+ ### 3) Monta le route in `convex/http.ts`
39
42
 
40
43
  ```ts
41
- // convex/agentBridge.ts
42
- import { AgentBridge } from "@okrlinkhub/agent-bridge";
43
- import { components } from "./_generated/api";
44
-
45
- export const bridge = new AgentBridge(components.agentBridge, {
46
- appName: "my-app",
47
- defaultPermissions: [
48
- { pattern: "myapp:read*", permission: "allow" },
49
- { pattern: "myapp:write*", permission: "rate_limited", rateLimitConfig: { requestsPerHour: 50, tokenBudget: 50000 } },
50
- { pattern: "*", permission: "deny" },
51
- ],
52
- });
44
+ import { httpRouter } from "convex/server";
45
+ import { registerAgentBridgeRoutes } from "./agentBridge";
46
+
47
+ const http = httpRouter();
48
+ registerAgentBridgeRoutes(http);
49
+ export default http;
53
50
  ```
54
51
 
55
- ### 2. Register functions that agents can call
52
+ ### 4) Configura funzioni esposte in `agent-bridge.config.ts`
56
53
 
57
54
  ```ts
58
- import { mutation } from "./_generated/server";
59
- import { createFunctionHandle } from "convex/server";
60
- import { api } from "./_generated/api";
61
- import { bridge } from "./agentBridge";
62
-
63
- export const setup = mutation({
64
- args: {},
65
- returns: v.null(),
66
- handler: async (ctx) => {
67
- await bridge.configure(ctx);
68
-
69
- const handle = await createFunctionHandle(api.myFunctions.getItems);
70
- await bridge.registerFunction(ctx, {
71
- name: "myapp:getItems",
72
- handle,
73
- type: "query",
74
- description: "List all items",
75
- });
76
-
77
- return null;
55
+ import { api } from "./convex/_generated/api";
56
+ import { defineAgentBridgeConfig } from "@okrlinkhub/agent-bridge";
57
+
58
+ export default defineAgentBridgeConfig({
59
+ functions: {
60
+ "cart.calculatePrice": { ref: api.cart.calculatePrice, type: "query" },
61
+ "cart.applyDiscount": { ref: api.cart.applyDiscount, type: "mutation" },
62
+ "okr.create": { ref: api.okr.create, type: "mutation" },
63
+ },
64
+ metadata: {
65
+ "cart.calculatePrice": {
66
+ description: "Calcola prezzo totale",
67
+ riskLevel: "low",
68
+ category: "commerce",
69
+ },
78
70
  },
79
71
  });
80
72
  ```
81
73
 
82
- ### 3. Mount HTTP routes
74
+ ## Endpoint HTTP esposti
83
75
 
84
- ```ts
85
- // convex/http.ts
86
- import { httpRouter } from "convex/server";
87
- import { registerRoutes } from "@okrlinkhub/agent-bridge";
88
- import { components } from "./_generated/api";
76
+ - `POST /agent/execute`
77
+ - `GET /agent/functions`
89
78
 
90
- const http = httpRouter();
79
+ ### `POST /agent/execute`
91
80
 
92
- // Exposes:
93
- // POST /agent-bridge/execute -- Gateway for agent function calls
94
- // POST /agent-bridge/provision -- Agent self-provisioning
95
- // GET /agent-bridge/health -- Health check
96
- registerRoutes(http, components.agentBridge, {
97
- appName: "my-app",
98
- });
81
+ Header richiesto:
99
82
 
100
- export default http;
101
- ```
83
+ - `X-Agent-API-Key: <api-key>`
102
84
 
103
- ### 4. Generate a provisioning token (admin)
85
+ Body richiesto:
104
86
 
105
- ```ts
106
- export const generateToken = mutation({
107
- args: { email: v.string(), department: v.string() },
108
- handler: async (ctx, args) => {
109
- // Authenticate admin here
110
- return await bridge.generateProvisioningToken(ctx, {
111
- employeeEmail: args.email,
112
- department: args.department,
113
- createdBy: "admin@company.com",
114
- });
115
- },
116
- });
87
+ ```json
88
+ {
89
+ "functionKey": "cart.calculatePrice",
90
+ "args": { "cartId": "..." }
91
+ }
117
92
  ```
118
93
 
119
- ## How It Works
120
-
121
- ### Agent Provisioning Flow
122
-
123
- 1. **IT Admin** generates a Provisioning Token (APT) via the `generateProvisioningToken` method
124
- 2. **Employee** uses the APT to self-register on an app by calling `POST /agent-bridge/provision`
125
- 3. The component creates an agent record and returns an `instanceToken` (valid 24h)
126
- 4. The agent uses the `instanceToken` for all subsequent function calls
127
-
128
- ### Function Execution Flow
94
+ Risposta:
129
95
 
130
- 1. Agent sends `POST /agent-bridge/execute` with `{ instanceToken, functionName, args }`
131
- 2. The gateway validates the token, checks permissions via pattern matching
132
- 3. If authorized, executes the registered function handle and returns the result
133
- 4. All access attempts are logged to the audit table
96
+ - successo: `{ "success": true, "result": ... }`
97
+ - errore: `{ "success": false, "error": "..." }`
134
98
 
135
- ### Permission Pattern Matching
99
+ Codici principali: `401`, `403`, `404`, `429`, `500`.
136
100
 
137
- Permissions use glob-style patterns with `*` wildcards:
101
+ ## Gestione agenti e permessi
138
102
 
139
- | Pattern | Matches |
140
- |---------|---------|
141
- | `*` | Everything (catch-all) |
142
- | `okr:*` | All OKR functions |
143
- | `okr:read*` | `okr:readObjectives`, `okr:readKeyResults`, etc. |
144
- | `okr:createObjective` | Only this specific function |
103
+ Mutation/query del componente disponibili in `components.agentBridge`:
145
104
 
146
- More specific patterns take priority over wildcards. Default behavior when no pattern matches: **deny**.
105
+ - `agents.createAgent`
106
+ - `agents.updateAgent`
107
+ - `agents.rotateApiKey`
108
+ - `agents.listAgents`
109
+ - `permissions.setAgentPermissions` (batch)
110
+ - `permissions.listAgentPermissions`
111
+ - `permissions.setFunctionOverrides` (batch)
112
+ - `permissions.listFunctionOverrides`
113
+ - `gateway.queryAccessLog`
147
114
 
148
- ## API Reference
115
+ ### Esempio permessi batch
149
116
 
150
- ### `AgentBridge` class
117
+ ```ts
118
+ await ctx.runMutation(components.agentBridge.permissions.setAgentPermissions, {
119
+ agentId,
120
+ rules: [
121
+ { pattern: "cart.*", permission: "allow" },
122
+ {
123
+ pattern: "okr.create",
124
+ permission: "rate_limited",
125
+ rateLimitConfig: { requestsPerHour: 60, tokenBudget: 50000 },
126
+ },
127
+ ],
128
+ availableFunctionKeys: Object.keys(config.functions),
129
+ });
130
+ ```
151
131
 
152
- | Method | Description |
153
- |--------|-------------|
154
- | `configure(ctx)` | Initialize component configuration |
155
- | `registerFunction(ctx, fn)` | Register a callable function |
156
- | `registerFunctions(ctx, fns)` | Bulk register functions |
157
- | `unregisterFunction(ctx, name)` | Remove a function |
158
- | `listFunctions(ctx)` | List registered functions |
159
- | `generateProvisioningToken(ctx, opts)` | Create an APT (admin) |
160
- | `listAgents(ctx)` | List registered agents |
161
- | `revokeAgent(ctx, opts)` | Revoke an agent globally |
162
- | `revokeAppInstance(ctx, opts)` | Revoke a specific app instance |
163
- | `setPermission(ctx, opts)` | Set/update a permission |
164
- | `removePermission(ctx, opts)` | Remove a permission |
165
- | `listPermissions(ctx, agentId)` | List agent permissions |
166
- | `queryAccessLog(ctx, opts)` | Query audit logs |
132
+ ## Migrazione 0.2 -> next major
167
133
 
168
- ### `registerRoutes(http, component, config)`
134
+ Breaking changes principali:
169
135
 
170
- Registers HTTP endpoints on the host app's router:
136
+ - rimosso il flusso provisioning token/instance token;
137
+ - rimossa la registrazione runtime delle funzioni via `createFunctionHandle`;
138
+ - rimosso l’uso della classe `AgentBridge` legacy.
171
139
 
172
- - `POST /agent-bridge/execute` -- Execute a registered function
173
- - `POST /agent-bridge/provision` -- Agent self-provisioning
174
- - `GET /agent-bridge/health` -- Health check
140
+ Nuovo flusso:
175
141
 
176
- See [example/convex/example.ts](./example/convex/example.ts) for a complete working example.
142
+ 1. config funzioni in `agent-bridge.config.ts`;
143
+ 2. auth via `X-Agent-API-Key`;
144
+ 3. policy in batch via mutation del componente;
145
+ 4. log centralizzato in `agentLogs`.
177
146
 
178
- ## Development
147
+ ## Sviluppo locale
179
148
 
180
149
  ```sh
181
150
  npm i
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":""}
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env node
2
+ import { access, mkdir, writeFile } from "node:fs/promises";
3
+ import path from "node:path";
4
+ const cwd = process.cwd();
5
+ async function exists(targetPath) {
6
+ try {
7
+ await access(targetPath);
8
+ return true;
9
+ }
10
+ catch {
11
+ return false;
12
+ }
13
+ }
14
+ async function writeIfMissing(relativePath, content) {
15
+ const absolutePath = path.join(cwd, relativePath);
16
+ if (await exists(absolutePath)) {
17
+ return "skipped";
18
+ }
19
+ await mkdir(path.dirname(absolutePath), { recursive: true });
20
+ await writeFile(absolutePath, content, "utf8");
21
+ return "created";
22
+ }
23
+ const configTemplate = `import { api } from "./convex/_generated/api";
24
+ import { defineAgentBridgeConfig } from "@okrlinkhub/agent-bridge";
25
+
26
+ export default defineAgentBridgeConfig({
27
+ functions: {
28
+ "cart.calculatePrice": {
29
+ ref: api.cart.calculatePrice,
30
+ type: "query",
31
+ },
32
+ "cart.applyDiscount": {
33
+ ref: api.cart.applyDiscount,
34
+ type: "mutation",
35
+ },
36
+ },
37
+ metadata: {
38
+ "cart.calculatePrice": {
39
+ description: "Calcola il prezzo totale del carrello",
40
+ riskLevel: "low",
41
+ category: "commerce",
42
+ },
43
+ },
44
+ });
45
+ `;
46
+ const bridgeHttpTemplate = `import { registerRoutes } from "@okrlinkhub/agent-bridge";
47
+ import { components } from "./_generated/api";
48
+ import config from "../agent-bridge.config";
49
+
50
+ export function registerAgentBridgeRoutes(
51
+ http: Parameters<typeof registerRoutes>[0],
52
+ ) {
53
+ registerRoutes(http, components.agentBridge, config, {
54
+ pathPrefix: "/agent",
55
+ });
56
+ }
57
+ `;
58
+ const integrationNotes = `
59
+ [agent-bridge] Init completed.
60
+
61
+ Next steps:
62
+ 1) Add component in convex/convex.config.ts:
63
+
64
+ import { defineApp } from "convex/server";
65
+ import agentBridge from "@okrlinkhub/agent-bridge/convex.config.js";
66
+
67
+ const app = defineApp();
68
+ app.use(agentBridge);
69
+ export default app;
70
+
71
+ 2) Mount routes in convex/http.ts:
72
+
73
+ import { httpRouter } from "convex/server";
74
+ import { registerAgentBridgeRoutes } from "./agentBridge";
75
+
76
+ const http = httpRouter();
77
+ registerAgentBridgeRoutes(http);
78
+ export default http;
79
+
80
+ 3) Create agents and permissions with component mutations:
81
+ - components.agentBridge.agents.createAgent
82
+ - components.agentBridge.permissions.setAgentPermissions
83
+ - components.agentBridge.permissions.setFunctionOverrides
84
+ `;
85
+ async function main() {
86
+ const commandArg = process.argv[2];
87
+ if (commandArg && commandArg !== "init") {
88
+ console.error(`[agent-bridge] Unknown command "${commandArg}".`);
89
+ console.error("Usage: npx @okrlinkhub/agent-bridge init");
90
+ process.exitCode = 1;
91
+ return;
92
+ }
93
+ const configResult = await writeIfMissing("agent-bridge.config.ts", configTemplate);
94
+ const bridgeResult = await writeIfMissing("convex/agentBridge.ts", bridgeHttpTemplate);
95
+ console.log(`[agent-bridge] agent-bridge.config.ts: ${configResult === "created" ? "created" : "skipped (already exists)"}`);
96
+ console.log(`[agent-bridge] convex/agentBridge.ts: ${bridgeResult === "created" ? "created" : "skipped (already exists)"}`);
97
+ console.log(integrationNotes.trim());
98
+ }
99
+ void main();
100
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;AAE1B,KAAK,UAAU,MAAM,CAAC,UAAkB;IACtC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,KAAK,UAAU,cAAc,CAC3B,YAAoB,EACpB,OAAe;IAEf,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAClD,IAAI,MAAM,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;QAC/B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,MAAM,SAAS,CAAC,YAAY,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC/C,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;CAsBtB,CAAC;AAEF,MAAM,kBAAkB,GAAG;;;;;;;;;;;CAW1B,CAAC;AAEF,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BxB,CAAC;AAEF,KAAK,UAAU,IAAI;IACjB,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACnC,IAAI,UAAU,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;QACxC,OAAO,CAAC,KAAK,CAAC,mCAAmC,UAAU,IAAI,CAAC,CAAC;QACjE,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC1D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,cAAc,CAAC,wBAAwB,EAAE,cAAc,CAAC,CAAC;IACpF,MAAM,YAAY,GAAG,MAAM,cAAc,CAAC,uBAAuB,EAAE,kBAAkB,CAAC,CAAC;IAEvF,OAAO,CAAC,GAAG,CACT,0CAA0C,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,0BAA0B,EAAE,CAChH,CAAC;IACF,OAAO,CAAC,GAAG,CACT,yCAAyC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,0BAA0B,EAAE,CAC/G,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC;AACvC,CAAC;AAED,KAAK,IAAI,EAAE,CAAC"}