@armoriq/sdk-dev 0.4.2 → 0.6.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/dist/client.d.ts +7 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +21 -6
- package/dist/client.js.map +1 -1
- package/dist/integrations/langchain.d.ts +100 -0
- package/dist/integrations/langchain.d.ts.map +1 -0
- package/dist/integrations/langchain.js +296 -0
- package/dist/integrations/langchain.js.map +1 -0
- package/dist/integrations/strands.d.ts +37 -16
- package/dist/integrations/strands.d.ts.map +1 -1
- package/dist/integrations/strands.js +133 -32
- package/dist/integrations/strands.js.map +1 -1
- package/dist/models.d.ts +2 -2
- package/dist/models.d.ts.map +1 -1
- package/dist/session.d.ts +12 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +42 -0
- package/dist/session.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ArmorIQ SDK — LangChain integration (TypeScript).
|
|
4
|
+
*
|
|
5
|
+
* Mirrors the Python langchain bundle and the Strands/ADK integrations: one
|
|
6
|
+
* factory per process, one callback handler per (user, agent). It wires two
|
|
7
|
+
* LangChain callbacks:
|
|
8
|
+
*
|
|
9
|
+
* handleLLMEnd -> capture the tool calls the model actually chose this turn
|
|
10
|
+
* as the intent plan and mint the ArmorIQ intent token.
|
|
11
|
+
* handleToolStart -> enforce per-user policy before each tool runs; block/hold
|
|
12
|
+
* by throwing, which LangChain surfaces as a tool error and
|
|
13
|
+
* skips execution (the handler sets raiseError so the throw
|
|
14
|
+
* is not swallowed).
|
|
15
|
+
*
|
|
16
|
+
* Fail-closed: a tool runs only on an explicit ArmorIQ allow. A block, an
|
|
17
|
+
* un-approved hold, or any enforcement error throws. On HOLD the handler emits
|
|
18
|
+
* onEvent("hold", ...), then awaits the delegation decision asynchronously
|
|
19
|
+
* (session.awaitApproval) — approved lets the tool run; rejected/timeout throws.
|
|
20
|
+
*
|
|
21
|
+
* @langchain/core is an optional peer dep, loaded lazily so importing this module
|
|
22
|
+
* never requires langchain to be installed.
|
|
23
|
+
*
|
|
24
|
+
* Usage:
|
|
25
|
+
* const armoriq = new ArmorIQLangChain({ client, mode: 'sdk' });
|
|
26
|
+
* const handler = await armoriq.forUser('alice@acme.com', { goal: 'reconcile' });
|
|
27
|
+
* await agentExecutor.invoke({ input: 'Pay invoice 1234' }, { callbacks: [handler] });
|
|
28
|
+
*/
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
exports.ArmorIQLangChainEnforcer = exports.ArmorIQLangChain = void 0;
|
|
31
|
+
exports.toolCallsFromLLMResult = toolCallsFromLLMResult;
|
|
32
|
+
exports.coerceArgs = coerceArgs;
|
|
33
|
+
const exceptions_1 = require("../exceptions");
|
|
34
|
+
class ArmorIQLangChain {
|
|
35
|
+
client;
|
|
36
|
+
mode;
|
|
37
|
+
validitySeconds;
|
|
38
|
+
defaultMcpName;
|
|
39
|
+
approvalWaitSeconds;
|
|
40
|
+
approvalPollInterval;
|
|
41
|
+
customParser;
|
|
42
|
+
_bootstrap;
|
|
43
|
+
constructor(opts) {
|
|
44
|
+
this.client = opts.client;
|
|
45
|
+
this.mode = opts.mode ?? 'sdk';
|
|
46
|
+
this.validitySeconds = opts.validitySeconds ?? 3600;
|
|
47
|
+
this.defaultMcpName = opts.defaultMcpName;
|
|
48
|
+
this.customParser = opts.toolNameParser;
|
|
49
|
+
this.approvalWaitSeconds =
|
|
50
|
+
opts.approvalWaitSeconds ??
|
|
51
|
+
Number(process.env.ARMORIQ_APPROVAL_WAIT_SECONDS ?? '300');
|
|
52
|
+
this.approvalPollInterval = opts.approvalPollInterval ?? 5;
|
|
53
|
+
}
|
|
54
|
+
async bootstrap() {
|
|
55
|
+
if (!this._bootstrap)
|
|
56
|
+
this._bootstrap = await this.client.bootstrap();
|
|
57
|
+
return this._bootstrap;
|
|
58
|
+
}
|
|
59
|
+
async toolNameParser() {
|
|
60
|
+
if (this.customParser)
|
|
61
|
+
return this.customParser;
|
|
62
|
+
const toolMap = (await this.bootstrap()).toolMap ?? {};
|
|
63
|
+
const defaultMcp = this.defaultMcpName ?? 'unknown';
|
|
64
|
+
return (toolName) => {
|
|
65
|
+
const mcp = toolMap[toolName];
|
|
66
|
+
if (mcp)
|
|
67
|
+
return { mcp, action: toolName };
|
|
68
|
+
if (toolName.includes('__')) {
|
|
69
|
+
const [prefix, ...rest] = toolName.split('__');
|
|
70
|
+
return { mcp: prefix, action: rest.join('__') };
|
|
71
|
+
}
|
|
72
|
+
return { mcp: defaultMcp, action: toolName };
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
invalidateUser(userEmail) {
|
|
76
|
+
this.client.invalidateUser(userEmail);
|
|
77
|
+
}
|
|
78
|
+
/** Return a LangChain callback handler that enforces every tool call for this
|
|
79
|
+
* user. Pass it via config { callbacks: [handler] }. */
|
|
80
|
+
async forUser(userEmail, opts) {
|
|
81
|
+
const scope = this.client.forUser(userEmail);
|
|
82
|
+
const enforcer = new ArmorIQLangChainEnforcer({
|
|
83
|
+
factory: this,
|
|
84
|
+
scope,
|
|
85
|
+
userEmail: userEmail.trim().toLowerCase(),
|
|
86
|
+
goal: opts?.goal,
|
|
87
|
+
onEvent: opts?.onEvent,
|
|
88
|
+
parser: await this.toolNameParser(),
|
|
89
|
+
});
|
|
90
|
+
return buildCallback(enforcer);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
exports.ArmorIQLangChain = ArmorIQLangChain;
|
|
94
|
+
/** Framework-agnostic enforcement core (no langchain import), so the allow/hold/
|
|
95
|
+
* block logic is unit-testable without the langchain package. */
|
|
96
|
+
class ArmorIQLangChainEnforcer {
|
|
97
|
+
factory;
|
|
98
|
+
scope;
|
|
99
|
+
userEmail;
|
|
100
|
+
goal;
|
|
101
|
+
onEvent;
|
|
102
|
+
parser;
|
|
103
|
+
session;
|
|
104
|
+
planStarted = false;
|
|
105
|
+
constructor(args) {
|
|
106
|
+
this.factory = args.factory;
|
|
107
|
+
this.scope = args.scope;
|
|
108
|
+
this.userEmail = args.userEmail;
|
|
109
|
+
this.goal = args.goal;
|
|
110
|
+
this.onEvent = args.onEvent;
|
|
111
|
+
this.parser = args.parser;
|
|
112
|
+
}
|
|
113
|
+
emit(kind, payload) {
|
|
114
|
+
if (!this.onEvent)
|
|
115
|
+
return;
|
|
116
|
+
try {
|
|
117
|
+
this.onEvent(kind, payload);
|
|
118
|
+
}
|
|
119
|
+
catch (exc) {
|
|
120
|
+
console.warn(`[armoriq] onEvent(${kind}) callback failed: ${exc.message}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
ensureSession() {
|
|
124
|
+
if (!this.session) {
|
|
125
|
+
this.session = this.scope.startSession({
|
|
126
|
+
mode: this.factory.mode,
|
|
127
|
+
validitySeconds: this.factory.validitySeconds,
|
|
128
|
+
toolNameParser: this.parser,
|
|
129
|
+
defaultMcpName: this.factory.defaultMcpName,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
return this.session;
|
|
133
|
+
}
|
|
134
|
+
async capturePlan(toolCalls) {
|
|
135
|
+
if (!toolCalls.length)
|
|
136
|
+
return;
|
|
137
|
+
await this.ensureSession().startPlan(toolCalls, this.goal);
|
|
138
|
+
this.planStarted = true;
|
|
139
|
+
}
|
|
140
|
+
async captureFromLlm(toolCalls) {
|
|
141
|
+
try {
|
|
142
|
+
await this.capturePlan(toolCalls);
|
|
143
|
+
}
|
|
144
|
+
catch (exc) {
|
|
145
|
+
console.warn(`[armoriq] langchain plan capture (handleLLMEnd) failed: ${exc.message}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/** Allow -> return; block/hold-denied -> throw (LangChain stops the tool). */
|
|
149
|
+
async enforceTool(toolName, args) {
|
|
150
|
+
args = args || {};
|
|
151
|
+
try {
|
|
152
|
+
if (!this.planStarted) {
|
|
153
|
+
// Fail-safe: handleLLMEnd normally mints the plan from the model's chosen
|
|
154
|
+
// tool calls first. If it didn't, mint from the tool actually being called.
|
|
155
|
+
await this.capturePlan([{ name: toolName, args }]);
|
|
156
|
+
}
|
|
157
|
+
const session = this.ensureSession();
|
|
158
|
+
const decision = await session.check(toolName, args, this.userEmail);
|
|
159
|
+
if (decision.allowed)
|
|
160
|
+
return; // explicit allow -> tool runs
|
|
161
|
+
if (decision.action === 'hold') {
|
|
162
|
+
this.emit('hold', {
|
|
163
|
+
tool: toolName,
|
|
164
|
+
delegationId: decision.delegationId,
|
|
165
|
+
reason: decision.reason,
|
|
166
|
+
});
|
|
167
|
+
const outcome = await session.awaitApproval(decision.delegationId, {
|
|
168
|
+
timeout: this.factory.approvalWaitSeconds,
|
|
169
|
+
interval: this.factory.approvalPollInterval,
|
|
170
|
+
userEmail: this.userEmail,
|
|
171
|
+
});
|
|
172
|
+
if (outcome === 'approved') {
|
|
173
|
+
this.emit('approved', { tool: toolName, delegationId: decision.delegationId });
|
|
174
|
+
return; // approved -> tool runs
|
|
175
|
+
}
|
|
176
|
+
this.emit(outcome, {
|
|
177
|
+
tool: toolName,
|
|
178
|
+
delegationId: decision.delegationId,
|
|
179
|
+
reason: decision.reason,
|
|
180
|
+
});
|
|
181
|
+
throw new exceptions_1.PolicyHoldException(`ArmorIQ hold ${outcome}: ${decision.reason ?? 'approval required'}`);
|
|
182
|
+
}
|
|
183
|
+
const reason = decision.reason ?? 'blocked by policy';
|
|
184
|
+
this.emit('block', { tool: toolName, reason });
|
|
185
|
+
throw new exceptions_1.PolicyBlockedException(`ArmorIQ ${decision.action}: ${reason}`);
|
|
186
|
+
}
|
|
187
|
+
catch (exc) {
|
|
188
|
+
if (exc instanceof exceptions_1.PolicyBlockedException || exc instanceof exceptions_1.PolicyHoldException) {
|
|
189
|
+
throw exc;
|
|
190
|
+
}
|
|
191
|
+
// Fail closed: never let a tool run if enforcement errored.
|
|
192
|
+
const msg = exc.message ?? String(exc);
|
|
193
|
+
this.emit('error', { tool: toolName, error: msg });
|
|
194
|
+
throw new exceptions_1.PolicyBlockedException(`ArmorIQ enforcement error (fail-closed): ${msg}`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/** Report an executed tool to ArmorIQ so the plan lifecycle closes (advances to
|
|
198
|
+
* 'completed' once all declared steps have run). Only called after a tool actually
|
|
199
|
+
* ran — enforcement-cancelled tools never reach here. Best-effort: audit failures
|
|
200
|
+
* are logged, never allowed to break the run (mirrors the strands AfterToolCall). */
|
|
201
|
+
async reportExecution(toolName, args, result, error) {
|
|
202
|
+
if (!this.session || !this.planStarted)
|
|
203
|
+
return;
|
|
204
|
+
try {
|
|
205
|
+
await this.session.report(toolName, args ?? {}, result, {
|
|
206
|
+
status: error ? 'error' : 'success',
|
|
207
|
+
errorMessage: error,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
catch (exc) {
|
|
211
|
+
console.warn(`[armoriq] langchain execution report failed for ${toolName}: ${exc.message}`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
exports.ArmorIQLangChainEnforcer = ArmorIQLangChainEnforcer;
|
|
216
|
+
function toolCallsFromLLMResult(output) {
|
|
217
|
+
const calls = [];
|
|
218
|
+
for (const row of output?.generations ?? []) {
|
|
219
|
+
for (const gen of row ?? []) {
|
|
220
|
+
const msg = gen?.message;
|
|
221
|
+
for (const tc of (msg?.tool_calls ?? [])) {
|
|
222
|
+
const name = tc?.name;
|
|
223
|
+
if (name)
|
|
224
|
+
calls.push({ name, args: tc.args ?? {} });
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return calls;
|
|
229
|
+
}
|
|
230
|
+
function coerceArgs(input) {
|
|
231
|
+
if (input && typeof input === 'object')
|
|
232
|
+
return input;
|
|
233
|
+
if (typeof input === 'string' && input) {
|
|
234
|
+
try {
|
|
235
|
+
const parsed = JSON.parse(input);
|
|
236
|
+
return parsed && typeof parsed === 'object' ? parsed : { input: parsed };
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
return { input };
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return {};
|
|
243
|
+
}
|
|
244
|
+
function buildCallback(enforcer) {
|
|
245
|
+
let BaseCallbackHandler;
|
|
246
|
+
try {
|
|
247
|
+
// Optional peer dep — loaded lazily so importing this module never needs langchain.
|
|
248
|
+
BaseCallbackHandler = require('@langchain/core/callbacks/base').BaseCallbackHandler;
|
|
249
|
+
}
|
|
250
|
+
catch {
|
|
251
|
+
throw new Error('@langchain/core is not installed.\nInstall it with: npm install @langchain/core');
|
|
252
|
+
}
|
|
253
|
+
class ArmorIQLangChainCallback extends BaseCallbackHandler {
|
|
254
|
+
name = 'armoriq';
|
|
255
|
+
// Propagate our block/hold throws so LangChain actually stops the tool.
|
|
256
|
+
raiseError = true;
|
|
257
|
+
awaitHandlers = true;
|
|
258
|
+
// runId -> {name, args} for tools that passed enforcement and ran, so
|
|
259
|
+
// handleToolEnd/handleToolError can report the execution (close the plan).
|
|
260
|
+
pending = {};
|
|
261
|
+
async handleLLMEnd(output) {
|
|
262
|
+
const calls = toolCallsFromLLMResult(output);
|
|
263
|
+
if (calls.length)
|
|
264
|
+
await enforcer.captureFromLlm(calls);
|
|
265
|
+
}
|
|
266
|
+
async handleToolStart(tool, input, runId, _parentRunId, _tags, _metadata, runName) {
|
|
267
|
+
const toolName = runName ||
|
|
268
|
+
tool?.name ||
|
|
269
|
+
(Array.isArray(tool?.id) ? tool.id[tool.id.length - 1] : '') ||
|
|
270
|
+
'';
|
|
271
|
+
const args = coerceArgs(input);
|
|
272
|
+
await enforcer.enforceTool(toolName, args); // throws to block/hold-deny
|
|
273
|
+
// Only reached when allowed -> the tool will run; remember it so
|
|
274
|
+
// handleToolEnd can report the execution and close the plan lifecycle.
|
|
275
|
+
if (runId)
|
|
276
|
+
this.pending[runId] = { name: toolName, args };
|
|
277
|
+
}
|
|
278
|
+
async handleToolEnd(output, runId) {
|
|
279
|
+
const info = runId ? this.pending[runId] : undefined;
|
|
280
|
+
if (info) {
|
|
281
|
+
delete this.pending[runId];
|
|
282
|
+
await enforcer.reportExecution(info.name, info.args, output);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
async handleToolError(err, runId) {
|
|
286
|
+
const info = runId ? this.pending[runId] : undefined;
|
|
287
|
+
if (info) {
|
|
288
|
+
delete this.pending[runId];
|
|
289
|
+
const msg = err?.message ?? String(err);
|
|
290
|
+
await enforcer.reportExecution(info.name, info.args, msg, msg);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return new ArmorIQLangChainCallback();
|
|
295
|
+
}
|
|
296
|
+
//# sourceMappingURL=langchain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"langchain.js","sourceRoot":"","sources":["../../src/integrations/langchain.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;;;AAgOH,wDAYC;AAED,gCAWC;AAtPD,8CAA4E;AAgB5E,MAAa,gBAAgB;IAClB,MAAM,CAAgB;IACtB,IAAI,CAAyB;IAC7B,eAAe,CAAS;IACxB,cAAc,CAAU;IACxB,mBAAmB,CAAS;IAC5B,oBAAoB,CAAS;IAC9B,YAAY,CAAkB;IAC9B,UAAU,CAAuB;IAEzC,YAAY,IAA6B;QACvC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC;QAC/B,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC;QACpD,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC;QAC1C,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,cAAc,CAAC;QACxC,IAAI,CAAC,mBAAmB;YACtB,IAAI,CAAC,mBAAmB;gBACxB,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,6BAA6B,IAAI,KAAK,CAAC,CAAC;QAC7D,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC,oBAAoB,IAAI,CAAC,CAAC;IAC7D,CAAC;IAED,KAAK,CAAC,SAAS;QACb,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,IAAI,CAAC,UAAU,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QACtE,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,cAAc;QAClB,IAAI,IAAI,CAAC,YAAY;YAAE,OAAO,IAAI,CAAC,YAAY,CAAC;QAChD,MAAM,OAAO,GAA2B,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC;QAC/E,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,IAAI,SAAS,CAAC;QACpD,OAAO,CAAC,QAAgB,EAAE,EAAE;YAC1B,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;YAC9B,IAAI,GAAG;gBAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;YAC1C,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC5B,MAAM,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC/C,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAClD,CAAC;YACD,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;QAC/C,CAAC,CAAC;IACJ,CAAC;IAED,cAAc,CAAC,SAAiB;QAC9B,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IACxC,CAAC;IAED;4DACwD;IACxD,KAAK,CAAC,OAAO,CACX,SAAiB,EACjB,IAA2C;QAE3C,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAAG,IAAI,wBAAwB,CAAC;YAC5C,OAAO,EAAE,IAAI;YACb,KAAK;YACL,SAAS,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE;YACzC,IAAI,EAAE,IAAI,EAAE,IAAI;YAChB,OAAO,EAAE,IAAI,EAAE,OAAO;YACtB,MAAM,EAAE,MAAM,IAAI,CAAC,cAAc,EAAE;SACpC,CAAC,CAAC;QACH,OAAO,aAAa,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC;CACF;AA/DD,4CA+DC;AAED;iEACiE;AACjE,MAAa,wBAAwB;IAC3B,OAAO,CAAmB;IAC1B,KAAK,CAAmB;IACxB,SAAS,CAAS;IAClB,IAAI,CAAU;IACd,OAAO,CAAW;IAClB,MAAM,CAAiB;IAC/B,OAAO,CAAkB;IACzB,WAAW,GAAG,KAAK,CAAC;IAEpB,YAAY,IAOX;QACC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACxB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QAChC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAC5B,CAAC;IAEO,IAAI,CAAC,IAAY,EAAE,OAA4B;QACrD,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO;QAC1B,IAAI,CAAC;YACH,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,qBAAqB,IAAI,sBAAuB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QACxF,CAAC;IACH,CAAC;IAEO,aAAa;QACnB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC;gBACrC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI;gBACvB,eAAe,EAAE,IAAI,CAAC,OAAO,CAAC,eAAe;gBAC7C,cAAc,EAAE,IAAI,CAAC,MAAM;gBAC3B,cAAc,EAAE,IAAI,CAAC,OAAO,CAAC,cAAc;aAC5C,CAAC,CAAC;QACL,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAEO,KAAK,CAAC,WAAW,CAAC,SAA6C;QACrE,IAAI,CAAC,SAAS,CAAC,MAAM;YAAE,OAAO;QAC9B,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3D,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,SAA6C;QAChE,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,2DAA4D,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QACpG,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,KAAK,CAAC,WAAW,CAAC,QAAgB,EAAE,IAAyB;QAC3D,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;QAClB,IAAI,CAAC;YACH,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;gBACtB,0EAA0E;gBAC1E,4EAA4E;gBAC5E,MAAM,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YACrD,CAAC;YACD,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YACrC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;YAErE,IAAI,QAAQ,CAAC,OAAO;gBAAE,OAAO,CAAC,8BAA8B;YAE5D,IAAI,QAAQ,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBAC/B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;oBAChB,IAAI,EAAE,QAAQ;oBACd,YAAY,EAAE,QAAQ,CAAC,YAAY;oBACnC,MAAM,EAAE,QAAQ,CAAC,MAAM;iBACxB,CAAC,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,YAAa,EAAE;oBAClE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,mBAAmB;oBACzC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,oBAAoB;oBAC3C,SAAS,EAAE,IAAI,CAAC,SAAS;iBAC1B,CAAC,CAAC;gBACH,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;oBAC3B,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC;oBAC/E,OAAO,CAAC,wBAAwB;gBAClC,CAAC;gBACD,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;oBACjB,IAAI,EAAE,QAAQ;oBACd,YAAY,EAAE,QAAQ,CAAC,YAAY;oBACnC,MAAM,EAAE,QAAQ,CAAC,MAAM;iBACxB,CAAC,CAAC;gBACH,MAAM,IAAI,gCAAmB,CAC3B,gBAAgB,OAAO,KAAK,QAAQ,CAAC,MAAM,IAAI,mBAAmB,EAAE,CACrE,CAAC;YACJ,CAAC;YAED,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,IAAI,mBAAmB,CAAC;YACtD,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;YAC/C,MAAM,IAAI,mCAAsB,CAAC,WAAW,QAAQ,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC,CAAC;QAC5E,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,mCAAsB,IAAI,GAAG,YAAY,gCAAmB,EAAE,CAAC;gBAChF,MAAM,GAAG,CAAC;YACZ,CAAC;YACD,4DAA4D;YAC5D,MAAM,GAAG,GAAI,GAAa,CAAC,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;YAClD,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;YACnD,MAAM,IAAI,mCAAsB,CAAC,4CAA4C,GAAG,EAAE,CAAC,CAAC;QACtF,CAAC;IACH,CAAC;IAED;;;yFAGqF;IACrF,KAAK,CAAC,eAAe,CACnB,QAAgB,EAChB,IAAyB,EACzB,MAAe,EACf,KAAc;QAEd,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW;YAAE,OAAO;QAC/C,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,IAAI,EAAE,EAAE,MAAM,EAAE;gBACtD,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;gBACnC,YAAY,EAAE,KAAK;aACpB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CACV,mDAAmD,QAAQ,KAAM,GAAa,CAAC,OAAO,EAAE,CACzF,CAAC;QACJ,CAAC;IACH,CAAC;CACF;AAxID,4DAwIC;AAED,SAAgB,sBAAsB,CAAC,MAAW;IAChD,MAAM,KAAK,GAAuC,EAAE,CAAC;IACrD,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,WAAW,IAAI,EAAE,EAAE,CAAC;QAC5C,KAAK,MAAM,GAAG,IAAI,GAAG,IAAI,EAAE,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,GAAG,EAAE,OAAO,CAAC;YACzB,KAAK,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,UAAU,IAAI,EAAE,CAAU,EAAE,CAAC;gBAClD,MAAM,IAAI,GAAG,EAAE,EAAE,IAAI,CAAC;gBACtB,IAAI,IAAI;oBAAE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;YACtD,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAgB,UAAU,CAAC,KAAU;IACnC,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACrD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,EAAE,CAAC;QACvC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACjC,OAAO,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAC3E,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,KAAK,EAAE,CAAC;QACnB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,aAAa,CAAC,QAAkC;IACvD,IAAI,mBAAwB,CAAC;IAC7B,IAAI,CAAC;QACH,oFAAoF;QACpF,mBAAmB,GAAI,OAAe,CAAC,gCAAgC,CAAC,CAAC,mBAAmB,CAAC;IAC/F,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,iFAAiF,CAClF,CAAC;IACJ,CAAC;IAED,MAAM,wBAAyB,SAAQ,mBAAmB;QACxD,IAAI,GAAG,SAAS,CAAC;QACjB,wEAAwE;QACxE,UAAU,GAAG,IAAI,CAAC;QAClB,aAAa,GAAG,IAAI,CAAC;QACrB,sEAAsE;QACtE,2EAA2E;QAC3E,OAAO,GAAgE,EAAE,CAAC;QAE1E,KAAK,CAAC,YAAY,CAAC,MAAW;YAC5B,MAAM,KAAK,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAC;YAC7C,IAAI,KAAK,CAAC,MAAM;gBAAE,MAAM,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QACzD,CAAC;QAED,KAAK,CAAC,eAAe,CACnB,IAAS,EACT,KAAa,EACb,KAAc,EACd,YAAqB,EACrB,KAAgB,EAChB,SAAmC,EACnC,OAAgB;YAEhB,MAAM,QAAQ,GACZ,OAAO;gBACP,IAAI,EAAE,IAAI;gBACV,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5D,EAAE,CAAC;YACL,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;YAC/B,MAAM,QAAQ,CAAC,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,4BAA4B;YACxE,iEAAiE;YACjE,uEAAuE;YACvE,IAAI,KAAK;gBAAE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QAC5D,CAAC;QAED,KAAK,CAAC,aAAa,CAAC,MAAW,EAAE,KAAc;YAC7C,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACrD,IAAI,IAAI,EAAE,CAAC;gBACT,OAAO,IAAI,CAAC,OAAO,CAAC,KAAe,CAAC,CAAC;gBACrC,MAAM,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC/D,CAAC;QACH,CAAC;QAED,KAAK,CAAC,eAAe,CAAC,GAAQ,EAAE,KAAc;YAC5C,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACrD,IAAI,IAAI,EAAE,CAAC;gBACT,OAAO,IAAI,CAAC,OAAO,CAAC,KAAe,CAAC,CAAC;gBACrC,MAAM,GAAG,GAAI,GAAa,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;gBACnD,MAAM,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;KACF;IAED,OAAO,IAAI,wBAAwB,EAAE,CAAC;AACxC,CAAC"}
|
|
@@ -1,42 +1,48 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ArmorIQ SDK — AWS Strands Agents integration (TypeScript).
|
|
3
3
|
*
|
|
4
|
-
* Mirrors the Python
|
|
5
|
-
*
|
|
4
|
+
* Mirrors the Python strands bundle. One factory per process, one plugin per
|
|
5
|
+
* (user, agent). It wires two Strands lifecycle hooks:
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* AfterModelCallEvent → capture the tool calls the model actually chose this
|
|
8
|
+
* turn as the intent plan and mint the ArmorIQ intent
|
|
9
|
+
* token (declaring only the tools the turn intends to
|
|
10
|
+
* run — not the agent's whole tool set — so a read-only
|
|
11
|
+
* turn is not flagged 'held' at issuance).
|
|
12
|
+
* BeforeToolCallEvent → enforce per-user policy before each tool runs;
|
|
13
|
+
* block/hold by setting event.cancel_tool.
|
|
10
14
|
*
|
|
11
15
|
* Fail-closed: a tool runs only on an explicit ArmorIQ allow. A block, a hold
|
|
12
|
-
* that is not approved in time, or any enforcement error cancels the tool.
|
|
13
|
-
*
|
|
14
|
-
*
|
|
16
|
+
* that is not approved in time, or any enforcement error cancels the tool. On
|
|
17
|
+
* HOLD the (async) hook emits onEvent("hold", ...), then awaits the delegation
|
|
18
|
+
* decision asynchronously (session.awaitApproval) — approved lets the tool run;
|
|
19
|
+
* rejected or timeout cancels it. The wait is non-blocking, so the host app can
|
|
20
|
+
* stream live UI updates (held → approved → success) while it waits.
|
|
15
21
|
*
|
|
16
22
|
* Strands' TS SDK is duck-typed here (`any`) so this module has no hard
|
|
17
23
|
* dependency on the strands package; attach the plugin via Agent({ plugins: [p] })
|
|
18
24
|
* or p.register(agent).
|
|
19
|
-
*
|
|
20
|
-
* Usage:
|
|
21
|
-
* const armoriq = new ArmorIQStrands({ client, mode: 'sdk' });
|
|
22
|
-
* const plugin = await armoriq.forUser('alice@acme.com', { goal: 'reconcile' });
|
|
23
|
-
* const agent = new Agent({ model, tools, plugins: [plugin] });
|
|
24
25
|
*/
|
|
25
26
|
import { ArmorIQClient, ArmorIQUserScope } from '../client';
|
|
26
27
|
import { SessionOptions } from '../session';
|
|
27
28
|
import { ToolNameParser } from '../plan_builder';
|
|
29
|
+
export type OnEvent = (kind: string, payload: Record<string, any>) => void;
|
|
28
30
|
export interface ArmorIQStrandsOptions {
|
|
29
31
|
client: ArmorIQClient;
|
|
30
32
|
mode?: SessionOptions['mode'];
|
|
31
33
|
validitySeconds?: number;
|
|
32
34
|
defaultMcpName?: string;
|
|
33
35
|
toolNameParser?: ToolNameParser;
|
|
36
|
+
approvalWaitSeconds?: number;
|
|
37
|
+
approvalPollInterval?: number;
|
|
34
38
|
}
|
|
35
39
|
export declare class ArmorIQStrands {
|
|
36
40
|
readonly client: ArmorIQClient;
|
|
37
41
|
readonly mode: SessionOptions['mode'];
|
|
38
42
|
readonly validitySeconds: number;
|
|
39
43
|
readonly defaultMcpName?: string;
|
|
44
|
+
readonly approvalWaitSeconds: number;
|
|
45
|
+
readonly approvalPollInterval: number;
|
|
40
46
|
private customParser?;
|
|
41
47
|
private _bootstrap?;
|
|
42
48
|
constructor(opts: ArmorIQStrandsOptions);
|
|
@@ -45,6 +51,7 @@ export declare class ArmorIQStrands {
|
|
|
45
51
|
invalidateUser(userEmail: string): void;
|
|
46
52
|
forUser(userEmail: string, opts?: {
|
|
47
53
|
goal?: string;
|
|
54
|
+
onEvent?: OnEvent;
|
|
48
55
|
}): Promise<ArmorIQStrandsPlugin>;
|
|
49
56
|
}
|
|
50
57
|
export declare class ArmorIQStrandsPlugin {
|
|
@@ -52,6 +59,7 @@ export declare class ArmorIQStrandsPlugin {
|
|
|
52
59
|
private scope;
|
|
53
60
|
private userEmail;
|
|
54
61
|
private goal?;
|
|
62
|
+
private onEvent?;
|
|
55
63
|
private parser;
|
|
56
64
|
private session?;
|
|
57
65
|
private planStarted;
|
|
@@ -60,15 +68,28 @@ export declare class ArmorIQStrandsPlugin {
|
|
|
60
68
|
scope: ArmorIQUserScope;
|
|
61
69
|
userEmail: string;
|
|
62
70
|
goal?: string;
|
|
71
|
+
onEvent?: OnEvent;
|
|
63
72
|
parser: ToolNameParser;
|
|
64
73
|
});
|
|
65
74
|
/** Strands Plugin entrypoint: register our hooks on the agent. */
|
|
66
75
|
initAgent(agent: any): void;
|
|
67
|
-
/** Wire the
|
|
76
|
+
/** Wire the AfterModelCall + BeforeToolCall hooks onto a Strands agent. */
|
|
68
77
|
register(agent: any): void;
|
|
78
|
+
private emit;
|
|
69
79
|
private ensureSession;
|
|
70
|
-
private
|
|
71
|
-
|
|
80
|
+
private capturePlan;
|
|
81
|
+
/** Extract {name, args} for each toolUse block in a Strands model message. */
|
|
82
|
+
static toolCallsFromMessage(message: any): Array<{
|
|
83
|
+
name: string;
|
|
84
|
+
args: any;
|
|
85
|
+
}>;
|
|
86
|
+
private onAfterModelCall;
|
|
72
87
|
private beforeToolCall;
|
|
88
|
+
/** Report a tool execution to ArmorIQ once it has actually run, so the plan
|
|
89
|
+
* lifecycle closes (advances to 'completed' when all declared steps have run)
|
|
90
|
+
* instead of sitting 'active' forever. Tools we cancelled for enforcement
|
|
91
|
+
* (block/rejected/timeout/error) never ran, so they are skipped. Best-effort:
|
|
92
|
+
* audit failures are logged, never allowed to break the run. */
|
|
93
|
+
private onAfterToolCall;
|
|
73
94
|
}
|
|
74
95
|
//# sourceMappingURL=strands.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strands.d.ts","sourceRoot":"","sources":["../../src/integrations/strands.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"strands.d.ts","sourceRoot":"","sources":["../../src/integrations/strands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAkB,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAIjD,MAAM,MAAM,OAAO,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;AAE3E,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,aAAa,CAAC;IACtB,IAAI,CAAC,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,qBAAa,cAAc;IACzB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACtC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,OAAO,CAAC,YAAY,CAAC,CAAiB;IACtC,OAAO,CAAC,UAAU,CAAC,CAAsB;gBAE7B,IAAI,EAAE,qBAAqB;IAYjC,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAKzC,cAAc,IAAI,OAAO,CAAC,cAAc,CAAC;IAe/C,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAIjC,OAAO,CACX,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAC1C,OAAO,CAAC,oBAAoB,CAAC;CAWjC;AAED,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,KAAK,CAAmB;IAChC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,IAAI,CAAC,CAAS;IACtB,OAAO,CAAC,OAAO,CAAC,CAAU;IAC1B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,OAAO,CAAC,CAAiB;IACjC,OAAO,CAAC,WAAW,CAAS;gBAEhB,IAAI,EAAE;QAChB,OAAO,EAAE,cAAc,CAAC;QACxB,KAAK,EAAE,gBAAgB,CAAC;QACxB,SAAS,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,MAAM,EAAE,cAAc,CAAC;KACxB;IASD,kEAAkE;IAClE,SAAS,CAAC,KAAK,EAAE,GAAG,GAAG,IAAI;IAI3B,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,GAAG,GAAG,IAAI;IAY1B,OAAO,CAAC,IAAI;IASZ,OAAO,CAAC,aAAa;YAYP,WAAW;IAMzB,8EAA8E;IAC9E,MAAM,CAAC,oBAAoB,CAAC,OAAO,EAAE,GAAG,GAAG,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,GAAG,CAAA;KAAE,CAAC;YAa/D,gBAAgB;YAWhB,cAAc;IAyD5B;;;;oEAIgE;YAClD,eAAe;CAqB9B"}
|