@okrlinkhub/agent-bridge 0.2.0 → 2.0.1

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 (70) hide show
  1. package/README.md +132 -122
  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 +108 -0
  5. package/dist/cli/init.js.map +1 -0
  6. package/dist/client/index.d.ts +54 -262
  7. package/dist/client/index.d.ts.map +1 -1
  8. package/dist/client/index.js +188 -539
  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 +75 -257
  14. package/dist/component/_generated/component.d.ts.map +1 -1
  15. package/dist/component/agentBridgeUtils.d.ts +9 -0
  16. package/dist/component/agentBridgeUtils.d.ts.map +1 -0
  17. package/dist/component/agentBridgeUtils.js +36 -0
  18. package/dist/component/agentBridgeUtils.js.map +1 -0
  19. package/dist/component/agents.d.ts +30 -0
  20. package/dist/component/agents.d.ts.map +1 -0
  21. package/dist/component/agents.js +124 -0
  22. package/dist/component/agents.js.map +1 -0
  23. package/dist/component/gateway.d.ts +46 -51
  24. package/dist/component/gateway.d.ts.map +1 -1
  25. package/dist/component/gateway.js +176 -227
  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 +58 -223
  32. package/dist/component/schema.d.ts.map +1 -1
  33. package/dist/component/schema.js +32 -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 +124 -0
  41. package/src/client/index.test.ts +147 -0
  42. package/src/client/index.ts +310 -790
  43. package/src/component/_generated/api.ts +4 -8
  44. package/src/component/_generated/component.ts +75 -310
  45. package/src/component/agentBridgeUtils.ts +56 -0
  46. package/src/component/agents.ts +138 -0
  47. package/src/component/gateway.ts +213 -279
  48. package/src/component/permissions.ts +89 -259
  49. package/src/component/schema.ts +34 -146
  50. package/src/react/index.ts +5 -6
  51. package/dist/component/channels.d.ts +0 -83
  52. package/dist/component/channels.d.ts.map +0 -1
  53. package/dist/component/channels.js +0 -288
  54. package/dist/component/channels.js.map +0 -1
  55. package/dist/component/circuitBreaker.d.ts +0 -73
  56. package/dist/component/circuitBreaker.d.ts.map +0 -1
  57. package/dist/component/circuitBreaker.js +0 -216
  58. package/dist/component/circuitBreaker.js.map +0 -1
  59. package/dist/component/provisioning.d.ts +0 -87
  60. package/dist/component/provisioning.d.ts.map +0 -1
  61. package/dist/component/provisioning.js +0 -343
  62. package/dist/component/provisioning.js.map +0 -1
  63. package/dist/component/registry.d.ts +0 -46
  64. package/dist/component/registry.d.ts.map +0 -1
  65. package/dist/component/registry.js +0 -121
  66. package/dist/component/registry.js.map +0 -1
  67. package/src/component/channels.ts +0 -374
  68. package/src/component/circuitBreaker.ts +0 -250
  69. package/src/component/provisioning.ts +0 -402
  70. package/src/component/registry.ts +0 -152
@@ -1,9 +1,9 @@
1
1
  import { v } from "convex/values";
2
- import { mutation, query, internalQuery } from "./_generated/server.js";
2
+ import { mutation, query } from "./_generated/server.js";
3
+ import { patternMatchesAvailableFunctions } from "./agentBridgeUtils.js";
3
4
 
4
- // --- Permission result type ---
5
-
6
- const permissionResultValidator = v.object({
5
+ const permissionRuleValidator = v.object({
6
+ pattern: v.string(),
7
7
  permission: v.union(
8
8
  v.literal("allow"),
9
9
  v.literal("deny"),
@@ -12,180 +12,57 @@ const permissionResultValidator = v.object({
12
12
  rateLimitConfig: v.optional(
13
13
  v.object({
14
14
  requestsPerHour: v.number(),
15
- tokenBudget: v.number(),
15
+ tokenBudget: v.optional(v.number()),
16
16
  }),
17
17
  ),
18
- matchedPattern: v.optional(v.string()),
19
18
  });
20
19
 
21
- // --- Pattern matching utilities ---
22
-
23
- /**
24
- * Calculate specificity score for a pattern.
25
- * More specific patterns (longer fixed prefix before the first wildcard)
26
- * get higher scores.
27
- */
28
- function patternSpecificity(pattern: string): number {
29
- const wildcardIndex = pattern.indexOf("*");
30
- if (wildcardIndex === -1) return pattern.length;
31
- return wildcardIndex;
32
- }
33
-
34
- /**
35
- * Check if a function name matches a permission pattern.
36
- * Supports "*" as a wildcard that matches any characters.
37
- * Examples: "okr:*" matches "okr:getObjectives", "*" matches anything.
38
- */
39
- function matchesPattern(functionName: string, pattern: string): boolean {
40
- if (pattern === "*") return true;
41
- // Escape regex special chars except *, then replace * with .*
42
- const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
43
- const regexStr = "^" + escaped.replace(/\*/g, ".*") + "$";
44
- const regex = new RegExp(regexStr);
45
- return regex.test(functionName);
46
- }
47
-
48
- // --- Public functions ---
49
-
50
- /**
51
- * Set a permission for an agent on a specific app.
52
- * If a permission with the same agentId + appName + functionPattern exists, it is updated.
53
- */
54
- export const setPermission = mutation({
20
+ export const setAgentPermissions = mutation({
55
21
  args: {
56
- agentId: v.string(),
57
- appName: v.string(),
58
- functionPattern: v.string(),
59
- permission: v.union(
60
- v.literal("allow"),
61
- v.literal("deny"),
62
- v.literal("rate_limited"),
63
- ),
64
- rateLimitConfig: v.optional(
65
- v.object({
66
- requestsPerHour: v.number(),
67
- tokenBudget: v.number(),
68
- }),
69
- ),
70
- createdBy: v.string(),
22
+ agentId: v.id("agents"),
23
+ rules: v.array(permissionRuleValidator),
24
+ availableFunctionKeys: v.array(v.string()),
71
25
  },
72
- returns: v.string(),
26
+ returns: v.number(),
73
27
  handler: async (ctx, args) => {
74
- // Check for existing permission with same pattern
75
- const existing = await ctx.db
76
- .query("functionPermissions")
77
- .withIndex("by_agent_and_app", (q) =>
78
- q.eq("agentId", args.agentId).eq("appName", args.appName),
79
- )
80
- .collect();
81
-
82
- const match = existing.find(
83
- (p) => p.functionPattern === args.functionPattern,
84
- );
85
-
86
- if (match) {
87
- await ctx.db.patch(match._id, {
88
- permission: args.permission,
89
- rateLimitConfig: args.rateLimitConfig,
90
- createdBy: args.createdBy,
91
- createdAt: Date.now(),
92
- });
93
- return match._id;
28
+ for (const rule of args.rules) {
29
+ const isValid = patternMatchesAvailableFunctions(
30
+ rule.pattern,
31
+ args.availableFunctionKeys,
32
+ );
33
+ if (!isValid) {
34
+ throw new Error(
35
+ `Pattern "${rule.pattern}" does not match any configured function`,
36
+ );
37
+ }
94
38
  }
95
39
 
96
- const id = await ctx.db.insert("functionPermissions", {
97
- agentId: args.agentId,
98
- appName: args.appName,
99
- functionPattern: args.functionPattern,
100
- permission: args.permission,
101
- rateLimitConfig: args.rateLimitConfig,
102
- createdAt: Date.now(),
103
- createdBy: args.createdBy,
104
- });
105
- return id;
106
- },
107
- });
108
-
109
- /**
110
- * Remove a specific permission.
111
- */
112
- export const removePermission = mutation({
113
- args: {
114
- agentId: v.string(),
115
- appName: v.string(),
116
- functionPattern: v.string(),
117
- },
118
- returns: v.boolean(),
119
- handler: async (ctx, args) => {
120
- const perms = await ctx.db
121
- .query("functionPermissions")
122
- .withIndex("by_agent_and_app", (q) =>
123
- q.eq("agentId", args.agentId).eq("appName", args.appName),
124
- )
125
- .collect();
126
-
127
- const match = perms.find(
128
- (p) => p.functionPattern === args.functionPattern,
129
- );
130
-
131
- if (!match) return false;
132
-
133
- await ctx.db.delete(match._id);
134
- return true;
135
- },
136
- });
137
-
138
- /**
139
- * Check permission for a specific function call.
140
- * Applies pattern matching with specificity ordering (most specific pattern wins).
141
- * Default: deny if no matching pattern is found.
142
- */
143
- export const checkPermission = query({
144
- args: {
145
- agentId: v.string(),
146
- appName: v.string(),
147
- functionName: v.string(),
148
- },
149
- returns: permissionResultValidator,
150
- handler: async (ctx, args) => {
151
- const permissions = await ctx.db
152
- .query("functionPermissions")
153
- .withIndex("by_agent_and_app", (q) =>
154
- q.eq("agentId", args.agentId).eq("appName", args.appName),
155
- )
40
+ const existingRules = await ctx.db
41
+ .query("agentPermissions")
42
+ .withIndex("by_agentId", (q) => q.eq("agentId", args.agentId))
156
43
  .collect();
157
44
 
158
- // Find all matching patterns and sort by specificity (most specific first)
159
- const matches = permissions
160
- .filter((p) => matchesPattern(args.functionName, p.functionPattern))
161
- .sort(
162
- (a, b) =>
163
- patternSpecificity(b.functionPattern) -
164
- patternSpecificity(a.functionPattern),
165
- );
45
+ for (const existingRule of existingRules) {
46
+ await ctx.db.delete(existingRule._id);
47
+ }
166
48
 
167
- if (matches.length === 0) {
168
- // Default: deny
169
- return { permission: "deny" as const };
49
+ for (const rule of args.rules) {
50
+ await ctx.db.insert("agentPermissions", {
51
+ agentId: args.agentId,
52
+ functionPattern: rule.pattern,
53
+ permission: rule.permission,
54
+ rateLimitConfig: rule.rateLimitConfig,
55
+ updatedAt: Date.now(),
56
+ });
170
57
  }
171
58
 
172
- // Most specific pattern wins
173
- const best = matches[0];
174
- return {
175
- permission: best.permission,
176
- rateLimitConfig: best.rateLimitConfig,
177
- matchedPattern: best.functionPattern,
178
- };
59
+ return args.rules.length;
179
60
  },
180
61
  });
181
62
 
182
- /**
183
- * List all permissions for an agent on a specific app.
184
- */
185
- export const listPermissions = query({
63
+ export const listAgentPermissions = query({
186
64
  args: {
187
- agentId: v.string(),
188
- appName: v.string(),
65
+ agentId: v.id("agents"),
189
66
  },
190
67
  returns: v.array(
191
68
  v.object({
@@ -198,124 +75,77 @@ export const listPermissions = query({
198
75
  rateLimitConfig: v.optional(
199
76
  v.object({
200
77
  requestsPerHour: v.number(),
201
- tokenBudget: v.number(),
78
+ tokenBudget: v.optional(v.number()),
202
79
  }),
203
80
  ),
204
- createdAt: v.number(),
205
- createdBy: v.string(),
81
+ updatedAt: v.number(),
206
82
  }),
207
83
  ),
208
84
  handler: async (ctx, args) => {
209
- const perms = await ctx.db
210
- .query("functionPermissions")
211
- .withIndex("by_agent_and_app", (q) =>
212
- q.eq("agentId", args.agentId).eq("appName", args.appName),
213
- )
85
+ const rules = await ctx.db
86
+ .query("agentPermissions")
87
+ .withIndex("by_agentId", (q) => q.eq("agentId", args.agentId))
214
88
  .collect();
215
89
 
216
- return perms.map((p) => ({
217
- functionPattern: p.functionPattern,
218
- permission: p.permission,
219
- rateLimitConfig: p.rateLimitConfig,
220
- createdAt: p.createdAt,
221
- createdBy: p.createdBy,
90
+ return rules.map((rule) => ({
91
+ functionPattern: rule.functionPattern,
92
+ permission: rule.permission,
93
+ rateLimitConfig: rule.rateLimitConfig,
94
+ updatedAt: rule.updatedAt,
222
95
  }));
223
96
  },
224
97
  });
225
98
 
226
- /**
227
- * Remove all permissions for a specific agent on a specific app.
228
- */
229
- export const clearPermissions = mutation({
99
+ export const setFunctionOverrides = mutation({
230
100
  args: {
231
- agentId: v.string(),
232
- appName: v.string(),
101
+ overrides: v.array(
102
+ v.object({
103
+ key: v.string(),
104
+ enabled: v.boolean(),
105
+ globalRateLimit: v.optional(v.number()),
106
+ }),
107
+ ),
108
+ availableFunctionKeys: v.array(v.string()),
233
109
  },
234
110
  returns: v.number(),
235
111
  handler: async (ctx, args) => {
236
- const perms = await ctx.db
237
- .query("functionPermissions")
238
- .withIndex("by_agent_and_app", (q) =>
239
- q.eq("agentId", args.agentId).eq("appName", args.appName),
240
- )
241
- .collect();
242
-
243
- for (const perm of perms) {
244
- await ctx.db.delete(perm._id);
112
+ for (const override of args.overrides) {
113
+ if (!args.availableFunctionKeys.includes(override.key)) {
114
+ throw new Error(`Function "${override.key}" is not exposed in config`);
115
+ }
116
+
117
+ const existing = await ctx.db
118
+ .query("agentFunctions")
119
+ .withIndex("by_key", (q) => q.eq("key", override.key))
120
+ .unique();
121
+ if (existing) {
122
+ await ctx.db.patch(existing._id, {
123
+ enabled: override.enabled,
124
+ globalRateLimit: override.globalRateLimit,
125
+ });
126
+ } else {
127
+ await ctx.db.insert("agentFunctions", {
128
+ key: override.key,
129
+ enabled: override.enabled,
130
+ globalRateLimit: override.globalRateLimit,
131
+ });
132
+ }
245
133
  }
246
134
 
247
- return perms.length;
135
+ return args.overrides.length;
248
136
  },
249
137
  });
250
138
 
251
- /**
252
- * Debug helper: show permission matching for a specific function call.
253
- */
254
- export const debugMatchPermission = query({
255
- args: {
256
- agentId: v.string(),
257
- appName: v.string(),
258
- functionName: v.string(),
259
- },
260
- returns: v.object({
261
- functionName: v.string(),
262
- permissions: v.array(
263
- v.object({
264
- functionPattern: v.string(),
265
- permission: v.union(
266
- v.literal("allow"),
267
- v.literal("deny"),
268
- v.literal("rate_limited"),
269
- ),
270
- specificity: v.number(),
271
- }),
272
- ),
273
- matches: v.array(
274
- v.object({
275
- functionPattern: v.string(),
276
- permission: v.union(
277
- v.literal("allow"),
278
- v.literal("deny"),
279
- v.literal("rate_limited"),
280
- ),
281
- specificity: v.number(),
282
- }),
283
- ),
284
- bestMatch: v.optional(
285
- v.object({
286
- functionPattern: v.string(),
287
- permission: v.union(
288
- v.literal("allow"),
289
- v.literal("deny"),
290
- v.literal("rate_limited"),
291
- ),
292
- specificity: v.number(),
293
- }),
294
- ),
295
- }),
296
- handler: async (ctx, args) => {
297
- const permissions = await ctx.db
298
- .query("functionPermissions")
299
- .withIndex("by_agent_and_app", (q) =>
300
- q.eq("agentId", args.agentId).eq("appName", args.appName),
301
- )
302
- .collect();
303
-
304
- const withSpecificity = permissions.map((p) => ({
305
- functionPattern: p.functionPattern,
306
- permission: p.permission,
307
- specificity: patternSpecificity(p.functionPattern),
308
- }));
309
-
310
- const matches = withSpecificity
311
- .filter((p) => matchesPattern(args.functionName, p.functionPattern))
312
- .sort((a, b) => b.specificity - a.specificity);
313
-
314
- return {
315
- functionName: args.functionName,
316
- permissions: withSpecificity,
317
- matches,
318
- bestMatch: matches[0],
319
- };
139
+ export const listFunctionOverrides = query({
140
+ args: {},
141
+ returns: v.array(
142
+ v.object({
143
+ key: v.string(),
144
+ enabled: v.boolean(),
145
+ globalRateLimit: v.optional(v.number()),
146
+ }),
147
+ ),
148
+ handler: async (ctx) => {
149
+ return await ctx.db.query("agentFunctions").collect();
320
150
  },
321
151
  });
@@ -2,66 +2,22 @@ import { defineSchema, defineTable } from "convex/server";
2
2
  import { v } from "convex/values";
3
3
 
4
4
  export default defineSchema({
5
- // Provisioning Tokens (generated by IT admin, distributed to employees)
6
- provisioningTokens: defineTable({
7
- tokenHash: v.string(), // SHA-256 hash of the APT (e.g. "apt_live_xxx")
8
- employeeEmail: v.string(),
9
- department: v.string(),
10
- maxApps: v.number(), // How many apps this token can register (default 5)
11
- usedCount: v.number(),
12
- expiresAt: v.number(), // Token expiration timestamp
13
- isActive: v.boolean(),
14
- createdBy: v.string(), // Admin email who created the token
15
- })
16
- .index("by_token_hash", ["tokenHash"])
17
- .index("by_email", ["employeeEmail"]),
18
-
19
- // Registered agents (created on first provisioning)
20
- registeredAgents: defineTable({
21
- agentId: v.string(), // UUID generated at first provisioning
22
- employeeEmail: v.string(),
23
- department: v.string(),
24
- firstRegisteredAt: v.number(),
25
- lastSeenAt: v.number(),
26
- isActive: v.boolean(),
27
- revokedAt: v.optional(v.number()),
28
- revokedBy: v.optional(v.string()),
29
- })
30
- .index("by_agent_id", ["agentId"])
31
- .index("by_email", ["employeeEmail"]),
32
-
33
- // Per-app per-agent instances (one per app per agent)
34
- agentAppInstances: defineTable({
35
- agentId: v.string(),
36
- appName: v.string(),
37
- instanceTokenHash: v.string(), // SHA-256 hash of the instance token
38
- registeredAt: v.number(),
39
- expiresAt: v.number(),
40
- lastActivityAt: v.number(),
41
- monthlyRequests: v.number(), // Request counter for this app
5
+ agents: defineTable({
6
+ name: v.string(),
7
+ appKey: v.optional(v.string()),
8
+ apiKeyHash: v.string(),
9
+ enabled: v.boolean(),
10
+ rateLimit: v.number(),
11
+ lastUsed: v.optional(v.number()),
12
+ createdAt: v.number(),
42
13
  })
43
- .index("by_instance_token_hash", ["instanceTokenHash"])
44
- .index("by_agent_and_app", ["agentId", "appName"]),
14
+ .index("by_apiKeyHash", ["apiKeyHash"])
15
+ .index("by_appKey", ["appKey"])
16
+ .index("by_enabled", ["enabled"]),
45
17
 
46
- // Function Handle Registry: maps function aliases to actual function handles
47
- functionRegistry: defineTable({
48
- appName: v.string(),
49
- functionName: v.string(), // Alias e.g. "okr:getObjectives"
50
- functionHandle: v.string(), // Function handle string from createFunctionHandle()
51
- functionType: v.union(
52
- v.literal("query"),
53
- v.literal("mutation"),
54
- v.literal("action"),
55
- ),
56
- description: v.optional(v.string()),
57
- registeredAt: v.number(),
58
- }).index("by_app_and_function", ["appName", "functionName"]),
59
-
60
- // Dynamic permissions: who can do what on which app
61
- functionPermissions: defineTable({
62
- agentId: v.string(),
63
- appName: v.string(),
64
- functionPattern: v.string(), // e.g. "okr:*", "okr:createObjective", "*"
18
+ agentPermissions: defineTable({
19
+ agentId: v.id("agents"),
20
+ functionPattern: v.string(),
65
21
  permission: v.union(
66
22
  v.literal("allow"),
67
23
  v.literal("deny"),
@@ -70,96 +26,28 @@ export default defineSchema({
70
26
  rateLimitConfig: v.optional(
71
27
  v.object({
72
28
  requestsPerHour: v.number(),
73
- tokenBudget: v.number(),
29
+ tokenBudget: v.optional(v.number()),
74
30
  }),
75
31
  ),
76
- createdAt: v.number(),
77
- createdBy: v.string(), // Admin email
78
- })
79
- .index("by_agent_and_app", ["agentId", "appName"])
80
- .index("by_app_and_pattern", ["appName", "functionPattern"]),
81
-
82
- // Audit log for all access attempts
83
- accessLog: defineTable({
32
+ updatedAt: v.number(),
33
+ }).index("by_agentId", ["agentId"]),
34
+
35
+ agentFunctions: defineTable({
36
+ key: v.string(),
37
+ enabled: v.boolean(),
38
+ globalRateLimit: v.optional(v.number()),
39
+ }).index("by_key", ["key"]),
40
+
41
+ agentLogs: defineTable({
42
+ agentId: v.id("agents"),
43
+ functionKey: v.string(),
44
+ args: v.any(),
45
+ result: v.optional(v.any()),
46
+ error: v.optional(v.string()),
47
+ duration: v.number(),
84
48
  timestamp: v.number(),
85
- agentId: v.string(),
86
- appName: v.string(),
87
- functionCalled: v.string(),
88
- permission: v.string(), // "allow", "deny", "rate_limited"
89
- errorMessage: v.optional(v.string()),
90
- durationMs: v.optional(v.number()),
91
49
  })
92
- .index("by_agent_and_timestamp", ["agentId", "timestamp"])
93
- .index("by_app_and_function", ["appName", "functionCalled"]),
94
-
95
- // Circuit breaker counters (per agent, per app, per hour window)
96
- circuitCounters: defineTable({
97
- agentId: v.string(),
98
- appName: v.string(),
99
- windowHour: v.string(), // "2026-02-08T14" (ISO truncated to hour)
100
- requestCount: v.number(),
101
- tokenEstimate: v.number(),
102
- isBlocked: v.boolean(),
103
- blockedReason: v.optional(v.string()),
104
- blockedAt: v.optional(v.number()),
105
- })
106
- .index("by_agentId_and_appName_and_windowHour", [
107
- "agentId",
108
- "appName",
109
- "windowHour",
110
- ])
111
- .index("by_isBlocked", ["isBlocked"]),
112
-
113
- // A2A intra-app channels (thematic channels within an app)
114
- appChannels: defineTable({
115
- appName: v.string(),
116
- channelName: v.string(),
117
- description: v.optional(v.string()),
118
- createdAt: v.number(),
119
- isActive: v.boolean(),
120
- }).index("by_appName_and_channelName", ["appName", "channelName"]),
121
-
122
- // A2A channel messages
123
- channelMessages: defineTable({
124
- appName: v.string(),
125
- channelName: v.string(),
126
- messageId: v.string(), // UUID
127
- fromAgentId: v.string(),
128
- payload: v.string(), // JSON serialized
129
- metadata: v.object({
130
- priority: v.number(), // 1-10
131
- ttl: v.number(), // TTL in ms
132
- }),
133
- sentAt: v.number(),
134
- expiresAt: v.number(),
135
- readBy: v.array(v.string()), // Array of agentIds that have read this message
136
- })
137
- .index("by_appName_and_channelName_and_sentAt", [
138
- "appName",
139
- "channelName",
140
- "sentAt",
141
- ])
142
- .index("by_expiresAt", ["expiresAt"]),
143
-
144
- // Per-app configuration (no global singleton)
145
- appConfigs: defineTable({
146
- appName: v.string(),
147
- defaultPermissions: v.array(
148
- v.object({
149
- pattern: v.string(),
150
- permission: v.union(
151
- v.literal("allow"),
152
- v.literal("deny"),
153
- v.literal("rate_limited"),
154
- ),
155
- rateLimitConfig: v.optional(
156
- v.object({
157
- requestsPerHour: v.number(),
158
- tokenBudget: v.number(),
159
- }),
160
- ),
161
- }),
162
- ),
163
- configuredAt: v.number(),
164
- }).index("by_app_name", ["appName"]),
50
+ .index("by_agentId_and_timestamp", ["agentId", "timestamp"])
51
+ .index("by_functionKey", ["functionKey"])
52
+ .index("by_timestamp", ["timestamp"]),
165
53
  });
@@ -1,11 +1,10 @@
1
1
  "use client";
2
2
 
3
- // React hooks and components for the Agent Bridge admin panel.
4
- // These will be expanded in future versions.
5
-
6
- export { AgentBridge } from "../client/index.js";
3
+ // React helpers for Agent Bridge integrations.
4
+ export { registerRoutes, normalizeAgentBridgeConfig } from "../client/index.js";
7
5
  export type {
8
6
  AgentBridgeConfig,
9
- FunctionDef,
10
- DefaultPermission,
7
+ AgentBridgeFunctionDefinition,
8
+ AgentBridgeFunctionMetadata,
9
+ AgentBridgeFunctionType,
11
10
  } from "../client/index.js";