@animalabs/agent-framework 0.6.7 → 0.6.8

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 (36) hide show
  1. package/dist/src/agent.d.ts +1 -34
  2. package/dist/src/agent.d.ts.map +1 -1
  3. package/dist/src/agent.js +55 -137
  4. package/dist/src/agent.js.map +1 -1
  5. package/dist/src/framework.d.ts +0 -56
  6. package/dist/src/framework.d.ts.map +1 -1
  7. package/dist/src/framework.js +45 -1733
  8. package/dist/src/framework.js.map +1 -1
  9. package/dist/src/types/agent.d.ts +0 -12
  10. package/dist/src/types/agent.d.ts.map +1 -1
  11. package/dist/test/helpers/mock-membrane.js +1 -1
  12. package/dist/test/helpers/mock-membrane.js.map +1 -1
  13. package/dist/test/mcpl-awareness-barrier.test.js +1 -228
  14. package/dist/test/mcpl-awareness-barrier.test.js.map +1 -1
  15. package/dist/test/refusal-single-call.test.d.ts +2 -0
  16. package/dist/test/refusal-single-call.test.d.ts.map +1 -0
  17. package/dist/test/refusal-single-call.test.js +177 -0
  18. package/dist/test/refusal-single-call.test.js.map +1 -0
  19. package/dist/tsconfig.tsbuildinfo +1 -1
  20. package/package.json +2 -2
  21. package/src/agent.ts +60 -226
  22. package/src/framework.ts +72 -2387
  23. package/src/types/agent.ts +0 -12
  24. package/dist/src/canonical-json.d.ts +0 -2
  25. package/dist/src/canonical-json.d.ts.map +0 -1
  26. package/dist/src/canonical-json.js +0 -23
  27. package/dist/src/canonical-json.js.map +0 -1
  28. package/dist/test/primary-summary-refusal-fallback-integration.test.d.ts +0 -2
  29. package/dist/test/primary-summary-refusal-fallback-integration.test.d.ts.map +0 -1
  30. package/dist/test/primary-summary-refusal-fallback-integration.test.js +0 -1955
  31. package/dist/test/primary-summary-refusal-fallback-integration.test.js.map +0 -1
  32. package/dist/test/primary-summary-refusal-fallback.test.d.ts +0 -2
  33. package/dist/test/primary-summary-refusal-fallback.test.d.ts.map +0 -1
  34. package/dist/test/primary-summary-refusal-fallback.test.js +0 -753
  35. package/dist/test/primary-summary-refusal-fallback.test.js.map +0 -1
  36. package/src/canonical-json.ts +0 -22
@@ -0,0 +1,177 @@
1
+ import { test } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { mkdtempSync, rmSync } from 'node:fs';
4
+ import { tmpdir } from 'node:os';
5
+ import { join } from 'node:path';
6
+ import { AgentFramework } from '../src/index.js';
7
+ import { MockMembrane, createMockResponse } from './helpers/mock-membrane.js';
8
+ class RefusalHarnessModule {
9
+ name = 'test';
10
+ toolCalls = [];
11
+ speeches = [];
12
+ ctx = null;
13
+ async start(ctx) {
14
+ this.ctx = ctx;
15
+ ctx.registerSpeechHandler('*');
16
+ }
17
+ async stop() {
18
+ this.ctx?.unregisterSpeechHandler();
19
+ this.ctx = null;
20
+ }
21
+ getTools() {
22
+ return [{
23
+ name: 'echo',
24
+ description: 'Echo input',
25
+ inputSchema: {
26
+ type: 'object',
27
+ properties: {
28
+ message: { type: 'string' },
29
+ },
30
+ },
31
+ }];
32
+ }
33
+ async handleToolCall(call) {
34
+ this.toolCalls.push(call);
35
+ return { success: true, data: { echoed: call.input } };
36
+ }
37
+ async onProcess(event, _state) {
38
+ if (event.type !== 'external-message')
39
+ return {};
40
+ return {
41
+ addMessages: [{
42
+ participant: 'User',
43
+ content: [{ type: 'text', text: String(event.content) }],
44
+ }],
45
+ requestInference: true,
46
+ };
47
+ }
48
+ async onAgentSpeech(_agentName, content) {
49
+ const text = content
50
+ .filter((block) => block.type === 'text')
51
+ .map((block) => block.text)
52
+ .join('\n');
53
+ if (text)
54
+ this.speeches.push(text);
55
+ }
56
+ }
57
+ function refusalResponse(content = []) {
58
+ return {
59
+ ...createMockResponse(content, 'refusal'),
60
+ content,
61
+ stopReason: 'refusal',
62
+ toolCalls: [],
63
+ rawAssistantText: content
64
+ .filter((block) => block.type === 'text')
65
+ .map((block) => block.text)
66
+ .join(''),
67
+ usage: { inputTokens: 40, outputTokens: 0 },
68
+ details: {
69
+ stop: { reason: 'refusal', wasTruncated: false },
70
+ usage: { inputTokens: 40, outputTokens: 0 },
71
+ timing: { totalDurationMs: 100, attempts: 1 },
72
+ model: { requested: 'test-model', actual: 'test-model', provider: 'mock' },
73
+ cache: { markersInRequest: 0, tokensCreated: 0, tokensRead: 0, hitRatio: 0 },
74
+ },
75
+ raw: {
76
+ request: {},
77
+ response: {
78
+ stop_details: { category: 'reasoning_extraction' },
79
+ },
80
+ },
81
+ };
82
+ }
83
+ async function createFramework(storePath, membrane, module) {
84
+ return AgentFramework.create({
85
+ storePath,
86
+ membrane: membrane.asMembrane(),
87
+ agents: [{
88
+ name: 'assistant',
89
+ model: 'test-model',
90
+ systemPrompt: 'system',
91
+ }],
92
+ modules: [module],
93
+ syncIntervalMs: 0,
94
+ });
95
+ }
96
+ function pendingRequests(framework) {
97
+ return framework.pendingRequests;
98
+ }
99
+ test('zero-output refusal makes exactly one provider call and restart stays idle', async () => {
100
+ const tempDir = mkdtempSync(join(tmpdir(), 'af-refusal-zero-'));
101
+ const storePath = join(tempDir, 'store.chronicle');
102
+ let framework;
103
+ let restarted;
104
+ try {
105
+ const firstModule = new RefusalHarnessModule();
106
+ const firstMembrane = new MockMembrane();
107
+ firstMembrane.pushResponse(refusalResponse());
108
+ framework = await createFramework(storePath, firstMembrane, firstModule);
109
+ framework.pushEvent({
110
+ type: 'external-message',
111
+ source: 'test',
112
+ content: 'trigger refusal',
113
+ metadata: {},
114
+ });
115
+ await framework.runUntilIdle();
116
+ assert.equal(firstMembrane.calls.length, 1);
117
+ assert.equal(firstModule.toolCalls.length, 0);
118
+ assert.deepEqual(firstModule.speeches, []);
119
+ assert.equal(pendingRequests(framework).length, 0);
120
+ await framework.stop();
121
+ framework = undefined;
122
+ const secondModule = new RefusalHarnessModule();
123
+ const secondMembrane = new MockMembrane();
124
+ restarted = await createFramework(storePath, secondMembrane, secondModule);
125
+ assert.equal(secondMembrane.calls.length, 0, 'restart must not redispatch a refused turn');
126
+ assert.equal(secondModule.toolCalls.length, 0);
127
+ assert.deepEqual(secondModule.speeches, []);
128
+ assert.equal(pendingRequests(restarted).length, 0);
129
+ }
130
+ finally {
131
+ await restarted?.stop();
132
+ await framework?.stop();
133
+ rmSync(tempDir, { recursive: true, force: true });
134
+ }
135
+ });
136
+ test('partial refusal output remains single-call, does not execute tools, and restart stays idle', async () => {
137
+ const tempDir = mkdtempSync(join(tmpdir(), 'af-refusal-partial-'));
138
+ const storePath = join(tempDir, 'store.chronicle');
139
+ let framework;
140
+ let restarted;
141
+ try {
142
+ const firstModule = new RefusalHarnessModule();
143
+ const firstMembrane = new MockMembrane();
144
+ firstMembrane.pushResponse(refusalResponse([
145
+ { type: 'text', text: 'partial before' },
146
+ { type: 'tool_use', id: 'call-1', name: 'test--echo', input: { message: 'should-not-run' } },
147
+ { type: 'text', text: 'partial after' },
148
+ ]));
149
+ framework = await createFramework(storePath, firstMembrane, firstModule);
150
+ framework.pushEvent({
151
+ type: 'external-message',
152
+ source: 'test',
153
+ content: 'trigger partial refusal',
154
+ metadata: {},
155
+ });
156
+ await framework.runUntilIdle();
157
+ assert.equal(firstMembrane.calls.length, 1);
158
+ assert.equal(firstModule.toolCalls.length, 0, 'refused tool blocks must not execute');
159
+ assert.deepEqual(firstModule.speeches, ['partial before\npartial after']);
160
+ assert.equal(pendingRequests(framework).length, 0);
161
+ await framework.stop();
162
+ framework = undefined;
163
+ const secondModule = new RefusalHarnessModule();
164
+ const secondMembrane = new MockMembrane();
165
+ restarted = await createFramework(storePath, secondMembrane, secondModule);
166
+ assert.equal(secondMembrane.calls.length, 0, 'restart must not invent a transformed retry');
167
+ assert.equal(secondModule.toolCalls.length, 0);
168
+ assert.deepEqual(secondModule.speeches, []);
169
+ assert.equal(pendingRequests(restarted).length, 0);
170
+ }
171
+ finally {
172
+ await restarted?.stop();
173
+ await framework?.stop();
174
+ rmSync(tempDir, { recursive: true, force: true });
175
+ }
176
+ });
177
+ //# sourceMappingURL=refusal-single-call.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refusal-single-call.test.js","sourceRoot":"","sources":["../../test/refusal-single-call.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAYjC,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAE9E,MAAM,oBAAoB;IACf,IAAI,GAAG,MAAM,CAAC;IACd,SAAS,GAAe,EAAE,CAAC;IAC3B,QAAQ,GAAa,EAAE,CAAC;IACzB,GAAG,GAAyB,IAAI,CAAC;IAEzC,KAAK,CAAC,KAAK,CAAC,GAAkB;QAC5B,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,GAAG,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,CAAC,GAAG,EAAE,uBAAuB,EAAE,CAAC;QACpC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;IAClB,CAAC;IAED,QAAQ;QACN,OAAO,CAAC;gBACN,IAAI,EAAE,MAAM;gBACZ,WAAW,EAAE,YAAY;gBACzB,WAAW,EAAE;oBACX,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;qBAC5B;iBACF;aACF,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,IAAc;QACjC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,KAAmB,EAAE,MAAoB;QACvD,IAAI,KAAK,CAAC,IAAI,KAAK,kBAAkB;YAAE,OAAO,EAAE,CAAC;QACjD,OAAO;YACL,WAAW,EAAE,CAAC;oBACZ,WAAW,EAAE,MAAM;oBACnB,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;iBACzD,CAAC;YACF,gBAAgB,EAAE,IAAI;SACvB,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,UAAkB,EAAE,OAAuB;QAC7D,MAAM,IAAI,GAAG,OAAO;aACjB,MAAM,CAAC,CAAC,KAAK,EAA0D,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC;aAChG,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;aAC1B,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,IAAI,IAAI;YAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC;CACF;AAED,SAAS,eAAe,CAAC,UAA0B,EAAE;IACnD,OAAO;QACL,GAAG,kBAAkB,CAAC,OAAO,EAAE,SAAS,CAAC;QACzC,OAAO;QACP,UAAU,EAAE,SAAS;QACrB,SAAS,EAAE,EAAE;QACb,gBAAgB,EAAE,OAAO;aACtB,MAAM,CAAC,CAAC,KAAK,EAA0D,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC;aAChG,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;aAC1B,IAAI,CAAC,EAAE,CAAC;QACX,KAAK,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,YAAY,EAAE,CAAC,EAAE;QAC3C,OAAO,EAAE;YACP,IAAI,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE;YAChD,KAAK,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,YAAY,EAAE,CAAC,EAAE;YAC3C,MAAM,EAAE,EAAE,eAAe,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE;YAC7C,KAAK,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE;YAC1E,KAAK,EAAE,EAAE,gBAAgB,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE;SAC7E;QACD,GAAG,EAAE;YACH,OAAO,EAAE,EAAE;YACX,QAAQ,EAAE;gBACR,YAAY,EAAE,EAAE,QAAQ,EAAE,sBAAsB,EAAE;aACnD;SACF;KAC+B,CAAC;AACrC,CAAC;AAED,KAAK,UAAU,eAAe,CAC5B,SAAiB,EACjB,QAAsB,EACtB,MAA4B;IAE5B,OAAO,cAAc,CAAC,MAAM,CAAC;QAC3B,SAAS;QACT,QAAQ,EAAE,QAAQ,CAAC,UAAU,EAAE;QAC/B,MAAM,EAAE,CAAC;gBACP,IAAI,EAAE,WAAW;gBACjB,KAAK,EAAE,YAAY;gBACnB,YAAY,EAAE,QAAQ;aACvB,CAAC;QACF,OAAO,EAAE,CAAC,MAAM,CAAC;QACjB,cAAc,EAAE,CAAC;KAClB,CAAC,CAAC;AACL,CAAC;AAED,SAAS,eAAe,CAAC,SAAyB;IAChD,OAAQ,SAAuD,CAAC,eAAe,CAAC;AAClF,CAAC;AAED,IAAI,CAAC,4EAA4E,EAAE,KAAK,IAAI,EAAE;IAC5F,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,kBAAkB,CAAC,CAAC,CAAC;IAChE,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;IACnD,IAAI,SAAqC,CAAC;IAC1C,IAAI,SAAqC,CAAC;IAE1C,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC/C,MAAM,aAAa,GAAG,IAAI,YAAY,EAAE,CAAC;QACzC,aAAa,CAAC,YAAY,CAAC,eAAe,EAAE,CAAC,CAAC;QAE9C,SAAS,GAAG,MAAM,eAAe,CAAC,SAAS,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;QACzE,SAAS,CAAC,SAAS,CAAC;YAClB,IAAI,EAAE,kBAAkB;YACxB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,iBAAiB;YAC1B,QAAQ,EAAE,EAAE;SACb,CAAC,CAAC;QACH,MAAM,SAAS,CAAC,YAAY,EAAE,CAAC;QAE/B,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC9C,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAC3C,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAEnD,MAAM,SAAS,CAAC,IAAI,EAAE,CAAC;QACvB,SAAS,GAAG,SAAS,CAAC;QAEtB,MAAM,YAAY,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAChD,MAAM,cAAc,GAAG,IAAI,YAAY,EAAE,CAAC;QAC1C,SAAS,GAAG,MAAM,eAAe,CAAC,SAAS,EAAE,cAAc,EAAE,YAAY,CAAC,CAAC;QAE3E,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,4CAA4C,CAAC,CAAC;QAC3F,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC/C,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAC5C,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACrD,CAAC;YAAS,CAAC;QACT,MAAM,SAAS,EAAE,IAAI,EAAE,CAAC;QACxB,MAAM,SAAS,EAAE,IAAI,EAAE,CAAC;QACxB,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,4FAA4F,EAAE,KAAK,IAAI,EAAE;IAC5G,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,qBAAqB,CAAC,CAAC,CAAC;IACnE,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;IACnD,IAAI,SAAqC,CAAC;IAC1C,IAAI,SAAqC,CAAC;IAE1C,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC/C,MAAM,aAAa,GAAG,IAAI,YAAY,EAAE,CAAC;QACzC,aAAa,CAAC,YAAY,CAAC,eAAe,CAAC;YACzC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,EAAE;YACxC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,gBAAgB,EAAE,EAAkB;YAC5G,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE;SACxC,CAAC,CAAC,CAAC;QAEJ,SAAS,GAAG,MAAM,eAAe,CAAC,SAAS,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;QACzE,SAAS,CAAC,SAAS,CAAC;YAClB,IAAI,EAAE,kBAAkB;YACxB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,yBAAyB;YAClC,QAAQ,EAAE,EAAE;SACb,CAAC,CAAC;QACH,MAAM,SAAS,CAAC,YAAY,EAAE,CAAC;QAE/B,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,sCAAsC,CAAC,CAAC;QACtF,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,+BAA+B,CAAC,CAAC,CAAC;QAC1E,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAEnD,MAAM,SAAS,CAAC,IAAI,EAAE,CAAC;QACvB,SAAS,GAAG,SAAS,CAAC;QAEtB,MAAM,YAAY,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAChD,MAAM,cAAc,GAAG,IAAI,YAAY,EAAE,CAAC;QAC1C,SAAS,GAAG,MAAM,eAAe,CAAC,SAAS,EAAE,cAAc,EAAE,YAAY,CAAC,CAAC;QAE3E,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,6CAA6C,CAAC,CAAC;QAC5F,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC/C,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAC5C,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACrD,CAAC;YAAS,CAAC;QACT,MAAM,SAAS,EAAE,IAAI,EAAE,CAAC;QACxB,MAAM,SAAS,EAAE,IAAI,EAAE,CAAC;QACxB,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC;AACH,CAAC,CAAC,CAAC"}