@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.
- package/README.md +96 -127
- package/dist/cli/init.d.ts +3 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +100 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/client/index.d.ts +50 -262
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +127 -536
- package/dist/client/index.js.map +1 -1
- package/dist/component/_generated/api.d.ts +4 -8
- package/dist/component/_generated/api.d.ts.map +1 -1
- package/dist/component/_generated/api.js.map +1 -1
- package/dist/component/_generated/component.d.ts +58 -257
- package/dist/component/_generated/component.d.ts.map +1 -1
- package/dist/component/agentBridgeUtils.d.ts +8 -0
- package/dist/component/agentBridgeUtils.d.ts.map +1 -0
- package/dist/component/agentBridgeUtils.js +33 -0
- package/dist/component/agentBridgeUtils.js.map +1 -0
- package/dist/component/agents.d.ts +27 -0
- package/dist/component/agents.d.ts.map +1 -0
- package/dist/component/agents.js +94 -0
- package/dist/component/agents.js.map +1 -0
- package/dist/component/gateway.d.ts +25 -55
- package/dist/component/gateway.d.ts.map +1 -1
- package/dist/component/gateway.js +120 -205
- package/dist/component/gateway.js.map +1 -1
- package/dist/component/permissions.d.ts +30 -84
- package/dist/component/permissions.d.ts.map +1 -1
- package/dist/component/permissions.js +80 -203
- package/dist/component/permissions.js.map +1 -1
- package/dist/component/schema.d.ts +55 -223
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js +30 -126
- package/dist/component/schema.js.map +1 -1
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +2 -3
- package/dist/react/index.js.map +1 -1
- package/package.json +3 -2
- package/src/cli/init.ts +116 -0
- package/src/client/index.ts +224 -792
- package/src/component/_generated/api.ts +4 -8
- package/src/component/_generated/component.ts +55 -312
- package/src/component/agentBridgeUtils.ts +52 -0
- package/src/component/agents.ts +106 -0
- package/src/component/gateway.ts +142 -252
- package/src/component/permissions.ts +89 -259
- package/src/component/schema.ts +32 -146
- package/src/react/index.ts +5 -6
- package/dist/component/channels.d.ts +0 -83
- package/dist/component/channels.d.ts.map +0 -1
- package/dist/component/channels.js +0 -288
- package/dist/component/channels.js.map +0 -1
- package/dist/component/circuitBreaker.d.ts +0 -73
- package/dist/component/circuitBreaker.d.ts.map +0 -1
- package/dist/component/circuitBreaker.js +0 -216
- package/dist/component/circuitBreaker.js.map +0 -1
- package/dist/component/provisioning.d.ts +0 -87
- package/dist/component/provisioning.d.ts.map +0 -1
- package/dist/component/provisioning.js +0 -343
- package/dist/component/provisioning.js.map +0 -1
- package/dist/component/registry.d.ts +0 -46
- package/dist/component/registry.d.ts.map +0 -1
- package/dist/component/registry.js +0 -121
- package/dist/component/registry.js.map +0 -1
- package/src/component/channels.ts +0 -374
- package/src/component/circuitBreaker.ts +0 -250
- package/src/component/provisioning.ts +0 -402
- 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
|
[](https://badge.fury.io/js/@okrlinkhub%2Fagent-bridge)
|
|
4
4
|
|
|
5
|
-
|
|
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
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
37
|
-
|
|
38
|
-
### 1. Initialize the client
|
|
41
|
+
### 3) Monta le route in `convex/http.ts`
|
|
39
42
|
|
|
40
43
|
```ts
|
|
41
|
-
|
|
42
|
-
import {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
###
|
|
52
|
+
### 4) Configura funzioni esposte in `agent-bridge.config.ts`
|
|
56
53
|
|
|
57
54
|
```ts
|
|
58
|
-
import {
|
|
59
|
-
import {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
-
|
|
74
|
+
## Endpoint HTTP esposti
|
|
83
75
|
|
|
84
|
-
|
|
85
|
-
|
|
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
|
-
|
|
79
|
+
### `POST /agent/execute`
|
|
91
80
|
|
|
92
|
-
|
|
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
|
-
|
|
101
|
-
```
|
|
83
|
+
- `X-Agent-API-Key: <api-key>`
|
|
102
84
|
|
|
103
|
-
|
|
85
|
+
Body richiesto:
|
|
104
86
|
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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
|
-
|
|
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
|
-
|
|
131
|
-
|
|
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
|
-
|
|
99
|
+
Codici principali: `401`, `403`, `404`, `429`, `500`.
|
|
136
100
|
|
|
137
|
-
|
|
101
|
+
## Gestione agenti e permessi
|
|
138
102
|
|
|
139
|
-
|
|
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
|
-
|
|
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
|
-
|
|
115
|
+
### Esempio permessi batch
|
|
149
116
|
|
|
150
|
-
|
|
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
|
-
|
|
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
|
-
|
|
134
|
+
Breaking changes principali:
|
|
169
135
|
|
|
170
|
-
|
|
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
|
-
|
|
173
|
-
- `POST /agent-bridge/provision` -- Agent self-provisioning
|
|
174
|
-
- `GET /agent-bridge/health` -- Health check
|
|
140
|
+
Nuovo flusso:
|
|
175
141
|
|
|
176
|
-
|
|
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
|
-
##
|
|
147
|
+
## Sviluppo locale
|
|
179
148
|
|
|
180
149
|
```sh
|
|
181
150
|
npm i
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":""}
|
package/dist/cli/init.js
ADDED
|
@@ -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"}
|