opencode-command-hooks 0.1.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 (46) hide show
  1. package/README.md +796 -0
  2. package/dist/config/agent.d.ts +82 -0
  3. package/dist/config/agent.d.ts.map +1 -0
  4. package/dist/config/agent.js +145 -0
  5. package/dist/config/agent.js.map +1 -0
  6. package/dist/config/global.d.ts +36 -0
  7. package/dist/config/global.d.ts.map +1 -0
  8. package/dist/config/global.js +219 -0
  9. package/dist/config/global.js.map +1 -0
  10. package/dist/config/markdown.d.ts +119 -0
  11. package/dist/config/markdown.d.ts.map +1 -0
  12. package/dist/config/markdown.js +373 -0
  13. package/dist/config/markdown.js.map +1 -0
  14. package/dist/config/merge.d.ts +67 -0
  15. package/dist/config/merge.d.ts.map +1 -0
  16. package/dist/config/merge.js +192 -0
  17. package/dist/config/merge.js.map +1 -0
  18. package/dist/execution/shell.d.ts +55 -0
  19. package/dist/execution/shell.d.ts.map +1 -0
  20. package/dist/execution/shell.js +187 -0
  21. package/dist/execution/shell.js.map +1 -0
  22. package/dist/execution/template.d.ts +55 -0
  23. package/dist/execution/template.d.ts.map +1 -0
  24. package/dist/execution/template.js +106 -0
  25. package/dist/execution/template.js.map +1 -0
  26. package/dist/executor.d.ts +54 -0
  27. package/dist/executor.d.ts.map +1 -0
  28. package/dist/executor.js +314 -0
  29. package/dist/executor.js.map +1 -0
  30. package/dist/index.d.ts +22 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +359 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/logging.d.ts +24 -0
  35. package/dist/logging.d.ts.map +1 -0
  36. package/dist/logging.js +57 -0
  37. package/dist/logging.js.map +1 -0
  38. package/dist/schemas.d.ts +425 -0
  39. package/dist/schemas.d.ts.map +1 -0
  40. package/dist/schemas.js +150 -0
  41. package/dist/schemas.js.map +1 -0
  42. package/dist/types/hooks.d.ts +635 -0
  43. package/dist/types/hooks.d.ts.map +1 -0
  44. package/dist/types/hooks.js +12 -0
  45. package/dist/types/hooks.js.map +1 -0
  46. package/package.json +66 -0
package/dist/index.js ADDED
@@ -0,0 +1,359 @@
1
+ import { createLogger, setGlobalLogger, logger } from "./logging.js";
2
+ import { executeHooks } from "./executor.js";
3
+ import { loadGlobalConfig } from "./config/global.js";
4
+ import { loadAgentConfig } from "./config/agent.js";
5
+ import { mergeConfigs } from "./config/merge.js";
6
+ // Export unified executor
7
+ export { executeHooks } from "./executor.js";
8
+ /**
9
+ * Helper to extract string values from event properties
10
+ */
11
+ function normalizeString(value) {
12
+ return typeof value === "string" ? value : undefined;
13
+ }
14
+ const TOOL_ARGS_TTL_MS = 5 * 60 * 1000;
15
+ const toolCallArgsCache = new Map();
16
+ function storeToolArgs(callId, args) {
17
+ if (!callId || !args)
18
+ return;
19
+ const existing = toolCallArgsCache.get(callId);
20
+ if (existing?.cleanup) {
21
+ clearTimeout(existing.cleanup);
22
+ }
23
+ const cleanup = setTimeout(() => {
24
+ toolCallArgsCache.delete(callId);
25
+ }, TOOL_ARGS_TTL_MS);
26
+ toolCallArgsCache.set(callId, { args, cleanup });
27
+ }
28
+ function getToolArgs(callId) {
29
+ if (!callId)
30
+ return undefined;
31
+ return toolCallArgsCache.get(callId)?.args;
32
+ }
33
+ function deleteToolArgs(callId) {
34
+ if (!callId)
35
+ return;
36
+ const entry = toolCallArgsCache.get(callId);
37
+ if (entry?.cleanup) {
38
+ clearTimeout(entry.cleanup);
39
+ }
40
+ toolCallArgsCache.delete(callId);
41
+ }
42
+ /**
43
+ * Check if a value matches a pattern (string, array of strings, or wildcard)
44
+ */
45
+ function matches(pattern, value) {
46
+ if (!pattern)
47
+ return true; // Omitted pattern matches all
48
+ if (pattern === "*")
49
+ return true; // Wildcard matches all
50
+ if (Array.isArray(pattern))
51
+ return value ? pattern.includes(value) : false;
52
+ return value === pattern;
53
+ }
54
+ /**
55
+ * Filter session hooks that match the given criteria
56
+ */
57
+ function filterSessionHooks(hooks, criteria) {
58
+ return hooks.filter((hook) => {
59
+ if (hook.when.event !== criteria.event)
60
+ return false;
61
+ return matches(hook.when.agent, criteria.agent);
62
+ });
63
+ }
64
+ /**
65
+ * Filter tool hooks that match the given criteria
66
+ */
67
+ function filterToolHooks(hooks, criteria) {
68
+ return hooks.filter((hook) => {
69
+ if (hook.when.phase !== criteria.phase)
70
+ return false;
71
+ if (!matches(hook.when.tool, criteria.toolName))
72
+ return false;
73
+ if (!matches(hook.when.callingAgent, criteria.callingAgent))
74
+ return false;
75
+ if (!matches(hook.when.slashCommand, criteria.slashCommand))
76
+ return false;
77
+ // Match tool args if specified in the hook
78
+ if (hook.when.toolArgs && criteria.toolArgs) {
79
+ for (const [key, expectedValue] of Object.entries(hook.when.toolArgs)) {
80
+ const actualValue = criteria.toolArgs[key];
81
+ if (!matches(expectedValue, actualValue)) {
82
+ return false;
83
+ }
84
+ }
85
+ }
86
+ return true;
87
+ });
88
+ }
89
+ /**
90
+ * OpenCode Command Hooks Plugin
91
+ *
92
+ * Allows users to declaratively attach shell commands to agent/tool/slash-command
93
+ * lifecycle events via configuration in opencode.json or markdown frontmatter.
94
+ *
95
+ * Features:
96
+ * - Tool hooks (before/after tool execution)
97
+ * - Session hooks (on session lifecycle events)
98
+ * - Configuration via global config or per-agent/command markdown
99
+ * - Non-blocking error semantics
100
+ *
101
+ * Architecture:
102
+ * - Simplified event handlers that extract context and call executeHooks
103
+ * - No state tracking (pendingAfterEvents, completedAfterEvents removed)
104
+ * - Unified executor handles all hook matching and execution
105
+ */
106
+ const plugin = async ({ client }) => {
107
+ const clientLogger = createLogger(client);
108
+ setGlobalLogger(clientLogger);
109
+ try {
110
+ logger.info("Initializing OpenCode Command Hooks plugin...");
111
+ const hooks = {
112
+ /**
113
+ * Config hook for plugin initialization
114
+ * Called by OpenCode during plugin initialization to provide configuration.
115
+ * We don't need to do anything with this config as we load our configuration
116
+ * from .opencode/command-hooks.jsonc, but we need to implement this hook
117
+ * to prevent OpenCode from throwing an error when it tries to call it.
118
+ */
119
+ config: async (_input) => {
120
+ void _input;
121
+ logger.debug("Config hook called");
122
+ // No-op for now - we load config from .opencode/command-hooks.jsonc
123
+ // This hook is called by OpenCode during plugin initialization
124
+ },
125
+ /**
126
+ * Event hook for session lifecycle events
127
+ * Supports: session.start, session.idle, tool.result
128
+ *
129
+ * Note: The Plugin type from @opencode-ai/plugin may not include session.start
130
+ * in its event type union, but it is documented as a supported event in the
131
+ * OpenCode SDK. We use a type assertion to allow this event type.
132
+ */
133
+ event: async ({ event }) => {
134
+ // Handle session.start event
135
+ if (event.type === "session.start") {
136
+ logger.debug("Received session.start event");
137
+ const sessionId = normalizeString(event.properties?.sessionID);
138
+ const agent = normalizeString(event.properties?.agent);
139
+ if (!sessionId) {
140
+ logger.debug("session.start event missing sessionID");
141
+ return;
142
+ }
143
+ try {
144
+ // Load config
145
+ const globalConfig = await loadGlobalConfig();
146
+ const markdownConfig = { tool: [], session: [] };
147
+ const { config: mergedConfig } = mergeConfigs(globalConfig, markdownConfig);
148
+ // Filter session hooks for session.start
149
+ const matchedHooks = filterSessionHooks(mergedConfig.session || [], {
150
+ event: "session.start",
151
+ agent,
152
+ });
153
+ logger.debug(`Matched ${matchedHooks.length} hook(s) for session.start`);
154
+ // Build execution context
155
+ const context = {
156
+ sessionId,
157
+ agent: agent || "unknown",
158
+ };
159
+ // Execute hooks
160
+ await executeHooks(matchedHooks, context, client);
161
+ }
162
+ catch (error) {
163
+ const errorMessage = error instanceof Error ? error.message : String(error);
164
+ logger.error(`Error handling session.start event: ${errorMessage}`);
165
+ }
166
+ }
167
+ // Handle session.idle event
168
+ if (event.type === "session.idle") {
169
+ logger.debug("Received session.idle event");
170
+ const sessionId = normalizeString(event.properties?.sessionID);
171
+ const agent = normalizeString(event.properties?.agent);
172
+ if (!sessionId) {
173
+ logger.debug("session.idle event missing sessionID");
174
+ return;
175
+ }
176
+ try {
177
+ // Load config
178
+ const globalConfig = await loadGlobalConfig();
179
+ const markdownConfig = { tool: [], session: [] };
180
+ const { config: mergedConfig } = mergeConfigs(globalConfig, markdownConfig);
181
+ // Filter session hooks for session.idle
182
+ const matchedHooks = filterSessionHooks(mergedConfig.session || [], {
183
+ event: "session.idle",
184
+ agent,
185
+ });
186
+ logger.debug(`Matched ${matchedHooks.length} hook(s) for session.idle`);
187
+ // Build execution context
188
+ const context = {
189
+ sessionId,
190
+ agent: agent || "unknown",
191
+ };
192
+ // Execute hooks
193
+ await executeHooks(matchedHooks, context, client);
194
+ }
195
+ catch (error) {
196
+ const errorMessage = error instanceof Error ? error.message : String(error);
197
+ logger.error(`Error handling session.idle event: ${errorMessage}`);
198
+ }
199
+ }
200
+ // Handle tool.result event (fires when tool finishes)
201
+ if (event.type === "tool.result") {
202
+ logger.debug("Received tool.result event");
203
+ const toolName = normalizeString(event.properties?.name ?? event.properties?.tool);
204
+ const sessionId = normalizeString(event.properties?.sessionID ?? event.properties?.sessionId);
205
+ const agent = normalizeString(event.properties?.agent);
206
+ const callId = normalizeString(event.properties?.callID ?? event.properties?.callId);
207
+ const storedToolArgs = getToolArgs(callId);
208
+ if (!sessionId || !toolName) {
209
+ logger.debug("tool.result event missing sessionID or tool name");
210
+ return;
211
+ }
212
+ try {
213
+ // Load global config
214
+ const globalConfig = await loadGlobalConfig();
215
+ // Load agent-specific config if this is a task tool with subagent_type
216
+ let agentConfig = { tool: [], session: [] };
217
+ if (toolName === "task" && storedToolArgs) {
218
+ const subagentType = normalizeString(storedToolArgs.subagent_type);
219
+ if (subagentType) {
220
+ logger.debug(`Detected task tool call with subagent_type: ${subagentType}`);
221
+ agentConfig = await loadAgentConfig(subagentType);
222
+ }
223
+ }
224
+ const { config: mergedConfig } = mergeConfigs(globalConfig, agentConfig);
225
+ // Filter tool hooks for after phase
226
+ const matchedHooks = filterToolHooks(mergedConfig.tool || [], {
227
+ phase: "after",
228
+ toolName,
229
+ callingAgent: agent,
230
+ slashCommand: normalizeString(event.properties?.slashCommand),
231
+ toolArgs: storedToolArgs,
232
+ });
233
+ logger.debug(`Matched ${matchedHooks.length} hook(s) for tool.result (after phase)`);
234
+ // Build execution context
235
+ const context = {
236
+ sessionId,
237
+ agent: agent || "unknown",
238
+ tool: toolName,
239
+ callId,
240
+ toolArgs: storedToolArgs,
241
+ };
242
+ // Execute hooks
243
+ await executeHooks(matchedHooks, context, client);
244
+ deleteToolArgs(callId);
245
+ }
246
+ catch (error) {
247
+ const errorMessage = error instanceof Error ? error.message : String(error);
248
+ logger.error(`Error handling tool.result event: ${errorMessage}`);
249
+ }
250
+ }
251
+ },
252
+ /**
253
+ * Tool execution before hook
254
+ * Runs before a tool is executed
255
+ */
256
+ "tool.execute.before": async (input, output) => {
257
+ logger.debug(`Received tool.execute.before for tool: ${input.tool}`);
258
+ try {
259
+ // Load global config
260
+ const globalConfig = await loadGlobalConfig();
261
+ // Load agent-specific config if this is a task tool with subagent_type
262
+ let agentConfig = { tool: [], session: [] };
263
+ let subagentType;
264
+ if (input.tool === "task") {
265
+ subagentType = normalizeString(output.args.subagent_type) || undefined;
266
+ if (subagentType) {
267
+ logger.debug(`Detected task tool call with subagent_type: ${subagentType}`);
268
+ agentConfig = await loadAgentConfig(subagentType);
269
+ }
270
+ }
271
+ const { config: mergedConfig } = mergeConfigs(globalConfig, agentConfig);
272
+ // Filter tool hooks for before phase
273
+ const matchedHooks = filterToolHooks(mergedConfig.tool || [], {
274
+ phase: "before",
275
+ toolName: input.tool,
276
+ callingAgent: subagentType,
277
+ slashCommand: undefined,
278
+ toolArgs: output.args,
279
+ });
280
+ logger.debug(`Matched ${matchedHooks.length} hook(s) for tool.execute.before`);
281
+ // Build execution context
282
+ const context = {
283
+ sessionId: input.sessionID,
284
+ agent: subagentType || "unknown",
285
+ tool: input.tool,
286
+ callId: input.callID,
287
+ toolArgs: output.args,
288
+ };
289
+ storeToolArgs(input.callID, output.args);
290
+ // Execute hooks
291
+ await executeHooks(matchedHooks, context, client);
292
+ }
293
+ catch (error) {
294
+ const errorMessage = error instanceof Error ? error.message : String(error);
295
+ logger.error(`Error handling tool.execute.before: ${errorMessage}`);
296
+ }
297
+ },
298
+ /**
299
+ * Tool execution after hook
300
+ * Runs after a tool completes (only if output is present - sync tools)
301
+ */
302
+ "tool.execute.after": async (input, toolOutput) => {
303
+ logger.debug(`Received tool.execute.after for tool: ${input.tool}`);
304
+ // Only process if output is present (sync tools)
305
+ if (!toolOutput) {
306
+ logger.debug(`Skipping tool.execute.after for ${input.tool}: no output (async tool)`);
307
+ return;
308
+ }
309
+ const storedToolArgs = getToolArgs(input.callID);
310
+ try {
311
+ // Load global config
312
+ const globalConfig = await loadGlobalConfig();
313
+ // Load agent-specific config if this is a task tool with subagent_type
314
+ let agentConfig = { tool: [], session: [] };
315
+ let subagentType;
316
+ if (input.tool === "task" && storedToolArgs) {
317
+ subagentType = normalizeString(storedToolArgs.subagent_type) || undefined;
318
+ if (subagentType) {
319
+ logger.debug(`Detected task tool call with subagent_type: ${subagentType}`);
320
+ agentConfig = await loadAgentConfig(subagentType);
321
+ }
322
+ }
323
+ const { config: mergedConfig } = mergeConfigs(globalConfig, agentConfig);
324
+ // Filter tool hooks for after phase
325
+ const matchedHooks = filterToolHooks(mergedConfig.tool || [], {
326
+ phase: "after",
327
+ toolName: input.tool,
328
+ callingAgent: subagentType,
329
+ slashCommand: undefined,
330
+ toolArgs: storedToolArgs,
331
+ });
332
+ logger.debug(`Matched ${matchedHooks.length} hook(s) for tool.execute.after`);
333
+ // Build execution context
334
+ const context = {
335
+ sessionId: input.sessionID,
336
+ agent: subagentType || "unknown",
337
+ tool: input.tool,
338
+ callId: input.callID,
339
+ toolArgs: storedToolArgs,
340
+ };
341
+ // Execute hooks
342
+ await executeHooks(matchedHooks, context, client);
343
+ }
344
+ catch (error) {
345
+ const errorMessage = error instanceof Error ? error.message : String(error);
346
+ logger.error(`Error handling tool.execute.after: ${errorMessage}`);
347
+ }
348
+ },
349
+ };
350
+ logger.info(`Plugin returning hooks: ${Object.keys(hooks).join(", ")}`);
351
+ return hooks;
352
+ }
353
+ catch (error) {
354
+ logger.error(`Error in plugin initialization: ${error instanceof Error ? error.message : String(error)}`);
355
+ throw error;
356
+ }
357
+ };
358
+ export default plugin;
359
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { OpencodeClient } from "@opencode-ai/sdk";
2
+ export type LogLevel = "debug" | "info" | "error";
3
+ /**
4
+ * Creates a logger that uses OpenCode's SDK logging.
5
+ * Logs are written to ~/.local/share/opencode/log/
6
+ */
7
+ export declare function createLogger(client: OpencodeClient): {
8
+ debug: (message: string) => void;
9
+ info: (message: string) => void;
10
+ error: (message: string) => void;
11
+ };
12
+ export type Logger = ReturnType<typeof createLogger>;
13
+ /**
14
+ * Set the global logger instance.
15
+ * Called once during plugin initialization with the SDK client.
16
+ */
17
+ export declare function setGlobalLogger(newLogger: Logger): void;
18
+ /**
19
+ * Proxy logger that always delegates to the current global logger.
20
+ * This allows modules to import `logger` at load time, and it will
21
+ * correctly use the real logger once it's initialized.
22
+ */
23
+ export declare const logger: Logger;
24
+ //# sourceMappingURL=logging.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../src/logging.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEtD,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAA;AAEjD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,cAAc;qBAiB9B,MAAM;oBACP,MAAM;qBACL,MAAM;EAE1B;AAED,MAAM,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAA;AAYpD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAEvD;AAED;;;;GAIG;AACH,eAAO,MAAM,MAAM,EAAE,MAUV,CAAA"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Creates a logger that uses OpenCode's SDK logging.
3
+ * Logs are written to ~/.local/share/opencode/log/
4
+ */
5
+ export function createLogger(client) {
6
+ const log = (level, message) => {
7
+ if (client?.app?.log) {
8
+ client.app.log({
9
+ body: {
10
+ service: "opencode-command-hooks",
11
+ level,
12
+ message,
13
+ },
14
+ }).catch((error) => {
15
+ const errorMessage = error instanceof Error ? error.message : String(error);
16
+ console.error(`[opencode-command-hooks] Failed to log: ${errorMessage}`);
17
+ });
18
+ }
19
+ };
20
+ return {
21
+ debug: (message) => log("debug", message),
22
+ info: (message) => log("info", message),
23
+ error: (message) => log("error", message),
24
+ };
25
+ }
26
+ // Internal global logger state
27
+ let globalLogger = null;
28
+ // No-op logger for when no client is available
29
+ const noopLogger = {
30
+ debug: () => { },
31
+ info: () => { },
32
+ error: () => { },
33
+ };
34
+ /**
35
+ * Set the global logger instance.
36
+ * Called once during plugin initialization with the SDK client.
37
+ */
38
+ export function setGlobalLogger(newLogger) {
39
+ globalLogger = newLogger;
40
+ }
41
+ /**
42
+ * Proxy logger that always delegates to the current global logger.
43
+ * This allows modules to import `logger` at load time, and it will
44
+ * correctly use the real logger once it's initialized.
45
+ */
46
+ export const logger = {
47
+ get debug() {
48
+ return (globalLogger ?? noopLogger).debug;
49
+ },
50
+ get info() {
51
+ return (globalLogger ?? noopLogger).info;
52
+ },
53
+ get error() {
54
+ return (globalLogger ?? noopLogger).error;
55
+ },
56
+ };
57
+ //# sourceMappingURL=logging.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logging.js","sourceRoot":"","sources":["../src/logging.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,MAAsB;IACjD,MAAM,GAAG,GAAG,CAAC,KAAe,EAAE,OAAe,EAAQ,EAAE;QACrD,IAAI,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;YACrB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;gBACb,IAAI,EAAE;oBACJ,OAAO,EAAE,wBAAwB;oBACjC,KAAK;oBACL,OAAO;iBACR;aACF,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;gBACjB,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;gBAC3E,OAAO,CAAC,KAAK,CAAC,2CAA2C,YAAY,EAAE,CAAC,CAAA;YAC1E,CAAC,CAAC,CAAA;QACJ,CAAC;IACH,CAAC,CAAA;IAED,OAAO;QACL,KAAK,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC;QACjD,IAAI,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;QAC/C,KAAK,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC;KAClD,CAAA;AACH,CAAC;AAID,+BAA+B;AAC/B,IAAI,YAAY,GAAkB,IAAI,CAAA;AAEtC,+CAA+C;AAC/C,MAAM,UAAU,GAAW;IACzB,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;IACf,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;IACd,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;CAChB,CAAA;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,YAAY,GAAG,SAAS,CAAA;AAC1B,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,MAAM,GAAW;IAC5B,IAAI,KAAK;QACP,OAAO,CAAC,YAAY,IAAI,UAAU,CAAC,CAAC,KAAK,CAAA;IAC3C,CAAC;IACD,IAAI,IAAI;QACN,OAAO,CAAC,YAAY,IAAI,UAAU,CAAC,CAAC,IAAI,CAAA;IAC1C,CAAC;IACD,IAAI,KAAK;QACP,OAAO,CAAC,YAAY,IAAI,UAAU,CAAC,CAAC,KAAK,CAAA;IAC3C,CAAC;CACQ,CAAA"}