@tarquinen/opencode-dcp 1.0.4 → 1.1.0-beta.2

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 (82) hide show
  1. package/README.md +68 -43
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +47 -17
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/config.d.ts +20 -7
  6. package/dist/lib/config.d.ts.map +1 -1
  7. package/dist/lib/config.js +320 -158
  8. package/dist/lib/config.js.map +1 -1
  9. package/dist/lib/hooks.d.ts.map +1 -1
  10. package/dist/lib/hooks.js +3 -0
  11. package/dist/lib/hooks.js.map +1 -1
  12. package/dist/lib/logger.d.ts +17 -0
  13. package/dist/lib/logger.d.ts.map +1 -1
  14. package/dist/lib/logger.js +90 -7
  15. package/dist/lib/logger.js.map +1 -1
  16. package/dist/lib/messages/prune.d.ts.map +1 -1
  17. package/dist/lib/messages/prune.js +90 -29
  18. package/dist/lib/messages/prune.js.map +1 -1
  19. package/dist/lib/messages/utils.js +7 -7
  20. package/dist/lib/model-selector.d.ts +3 -3
  21. package/dist/lib/model-selector.d.ts.map +1 -1
  22. package/dist/lib/model-selector.js +34 -34
  23. package/dist/lib/model-selector.js.map +1 -1
  24. package/dist/lib/prompt.d.ts.map +1 -1
  25. package/dist/lib/prompt.js +37 -25
  26. package/dist/lib/prompt.js.map +1 -1
  27. package/dist/lib/prompts/discard-tool-spec.txt +56 -0
  28. package/dist/lib/prompts/extract-tool-spec.txt +79 -0
  29. package/dist/lib/prompts/nudge/nudge-both.txt +10 -0
  30. package/dist/lib/prompts/nudge/nudge-discard.txt +9 -0
  31. package/dist/lib/prompts/nudge/nudge-extract.txt +9 -0
  32. package/dist/lib/prompts/{synthetic.txt → system/system-prompt-both.txt} +23 -13
  33. package/dist/lib/prompts/system/system-prompt-discard.txt +49 -0
  34. package/dist/lib/prompts/system/system-prompt-extract.txt +49 -0
  35. package/dist/lib/shared-utils.d.ts.map +1 -1
  36. package/dist/lib/shared-utils.js +1 -1
  37. package/dist/lib/shared-utils.js.map +1 -1
  38. package/dist/lib/state/persistence.d.ts.map +1 -1
  39. package/dist/lib/state/persistence.js +4 -7
  40. package/dist/lib/state/persistence.js.map +1 -1
  41. package/dist/lib/state/state.d.ts +1 -0
  42. package/dist/lib/state/state.d.ts.map +1 -1
  43. package/dist/lib/state/state.js +26 -6
  44. package/dist/lib/state/state.js.map +1 -1
  45. package/dist/lib/state/tool-cache.d.ts.map +1 -1
  46. package/dist/lib/state/tool-cache.js +24 -10
  47. package/dist/lib/state/tool-cache.js.map +1 -1
  48. package/dist/lib/state/types.d.ts +2 -0
  49. package/dist/lib/state/types.d.ts.map +1 -1
  50. package/dist/lib/strategies/deduplication.js +4 -4
  51. package/dist/lib/strategies/deduplication.js.map +1 -1
  52. package/dist/lib/strategies/index.d.ts +1 -1
  53. package/dist/lib/strategies/index.d.ts.map +1 -1
  54. package/dist/lib/strategies/index.js +1 -1
  55. package/dist/lib/strategies/index.js.map +1 -1
  56. package/dist/lib/strategies/on-idle.d.ts.map +1 -1
  57. package/dist/lib/strategies/on-idle.js +25 -24
  58. package/dist/lib/strategies/on-idle.js.map +1 -1
  59. package/dist/lib/strategies/supersede-writes.js +4 -4
  60. package/dist/lib/strategies/supersede-writes.js.map +1 -1
  61. package/dist/lib/strategies/{prune-tool.d.ts → tools.d.ts} +3 -6
  62. package/dist/lib/strategies/tools.d.ts.map +1 -0
  63. package/dist/lib/strategies/tools.js +127 -0
  64. package/dist/lib/strategies/tools.js.map +1 -0
  65. package/dist/lib/strategies/utils.d.ts +0 -1
  66. package/dist/lib/strategies/utils.d.ts.map +1 -1
  67. package/dist/lib/strategies/utils.js +20 -10
  68. package/dist/lib/strategies/utils.js.map +1 -1
  69. package/dist/lib/ui/notification.d.ts +1 -0
  70. package/dist/lib/ui/notification.d.ts.map +1 -1
  71. package/dist/lib/ui/notification.js +44 -20
  72. package/dist/lib/ui/notification.js.map +1 -1
  73. package/dist/lib/ui/utils.d.ts.map +1 -1
  74. package/dist/lib/ui/utils.js +9 -9
  75. package/dist/lib/ui/utils.js.map +1 -1
  76. package/package.json +61 -58
  77. package/dist/lib/prompts/nudge.txt +0 -10
  78. package/dist/lib/prompts/tool.txt +0 -72
  79. package/dist/lib/strategies/prune-tool.d.ts.map +0 -1
  80. package/dist/lib/strategies/prune-tool.js +0 -88
  81. package/dist/lib/strategies/prune-tool.js.map +0 -1
  82. /package/dist/lib/prompts/{pruning.txt → on-idle-analysis.txt} +0 -0
package/package.json CHANGED
@@ -1,60 +1,63 @@
1
1
  {
2
- "$schema": "https://json.schemastore.org/package.json",
3
- "name": "@tarquinen/opencode-dcp",
4
- "version": "1.0.4",
5
- "type": "module",
6
- "description": "OpenCode plugin that optimizes token usage by pruning obsolete tool outputs from conversation context",
7
- "main": "./dist/index.js",
8
- "types": "./dist/index.d.ts",
9
- "scripts": {
10
- "clean": "rm -rf dist",
11
- "build": "npm run clean && tsc && cp -r lib/prompts dist/lib/prompts",
12
- "postbuild": "rm -rf dist/logs",
13
- "prepublishOnly": "npm run build",
14
- "dev": "opencode plugin dev",
15
- "typecheck": "tsc --noEmit",
16
- "test": "node --import tsx --test tests/*.test.ts"
17
- },
18
- "keywords": [
19
- "opencode",
20
- "opencode-plugin",
21
- "plugin",
22
- "context",
23
- "pruning",
24
- "optimization",
25
- "tokens"
26
- ],
27
- "repository": {
28
- "type": "git",
29
- "url": "git+https://github.com/Tarquinen/opencode-dynamic-context-pruning.git"
30
- },
31
- "bugs": {
32
- "url": "https://github.com/Tarquinen/opencode-dynamic-context-pruning/issues"
33
- },
34
- "homepage": "https://github.com/Tarquinen/opencode-dynamic-context-pruning#readme",
35
- "author": "tarquinen",
36
- "license": "MIT",
37
- "peerDependencies": {
38
- "@opencode-ai/plugin": ">=0.13.7"
39
- },
40
- "dependencies": {
41
- "@ai-sdk/openai-compatible": "^1.0.28",
42
- "@opencode-ai/sdk": "latest",
43
- "@tarquinen/opencode-auth-provider": "^0.1.7",
44
- "ai": "^5.0.106",
45
- "gpt-tokenizer": "^3.4.0",
46
- "jsonc-parser": "^3.3.1",
47
- "zod": "^4.1.13"
48
- },
49
- "devDependencies": {
50
- "@opencode-ai/plugin": "^1.0.143",
51
- "@types/node": "^24.10.1",
52
- "tsx": "^4.21.0",
53
- "typescript": "^5.9.3"
54
- },
55
- "files": [
56
- "dist/",
57
- "README.md",
58
- "LICENSE"
59
- ]
2
+ "$schema": "https://json.schemastore.org/package.json",
3
+ "name": "@tarquinen/opencode-dcp",
4
+ "version": "1.1.0-beta.2",
5
+ "type": "module",
6
+ "description": "OpenCode plugin that optimizes token usage by pruning obsolete tool outputs from conversation context",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "scripts": {
10
+ "clean": "rm -rf dist",
11
+ "build": "npm run clean && tsc && cp -r lib/prompts dist/lib/prompts",
12
+ "postbuild": "rm -rf dist/logs",
13
+ "prepublishOnly": "npm run build",
14
+ "dev": "opencode plugin dev",
15
+ "typecheck": "tsc --noEmit",
16
+ "test": "node --import tsx --test tests/*.test.ts",
17
+ "format": "prettier --write .",
18
+ "format:check": "prettier --check ."
19
+ },
20
+ "keywords": [
21
+ "opencode",
22
+ "opencode-plugin",
23
+ "plugin",
24
+ "context",
25
+ "pruning",
26
+ "optimization",
27
+ "tokens"
28
+ ],
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "git+https://github.com/Tarquinen/opencode-dynamic-context-pruning.git"
32
+ },
33
+ "bugs": {
34
+ "url": "https://github.com/Tarquinen/opencode-dynamic-context-pruning/issues"
35
+ },
36
+ "homepage": "https://github.com/Tarquinen/opencode-dynamic-context-pruning#readme",
37
+ "author": "tarquinen",
38
+ "license": "MIT",
39
+ "peerDependencies": {
40
+ "@opencode-ai/plugin": ">=0.13.7"
41
+ },
42
+ "dependencies": {
43
+ "@ai-sdk/openai-compatible": "^1.0.28",
44
+ "@opencode-ai/sdk": "latest",
45
+ "@tarquinen/opencode-auth-provider": "^0.1.7",
46
+ "ai": "^5.0.106",
47
+ "gpt-tokenizer": "^3.4.0",
48
+ "jsonc-parser": "^3.3.1",
49
+ "zod": "^4.1.13"
50
+ },
51
+ "devDependencies": {
52
+ "@opencode-ai/plugin": "^1.0.143",
53
+ "@types/node": "^24.10.1",
54
+ "prettier": "^3.4.2",
55
+ "tsx": "^4.21.0",
56
+ "typescript": "^5.9.3"
57
+ },
58
+ "files": [
59
+ "dist/",
60
+ "README.md",
61
+ "LICENSE"
62
+ ]
60
63
  }
@@ -1,10 +0,0 @@
1
- <instruction name=context_management_required>
2
- **CRITICAL CONTEXT WARNING:** Your context window is filling with tool outputs. Strict adherence to context hygiene is required.
3
-
4
- **Immediate Actions Required:**
5
- 1. **Garbage Collect:** If you read files or ran commands that yielded no value, prune them NOW. Do not summarize them.
6
- 2. **Task Cleanup:** If a sub-task is complete, prune the tools used.
7
- 3. **Consolidate:** If you are holding valuable raw data, you *must* distill the insights into your narrative and prune the raw entry.
8
-
9
- **Protocol:** You should prioritize this cleanup, but do not interrupt a critical atomic operation if one is in progress. Once the immediate step is done, you must prune.
10
- </instruction>
@@ -1,72 +0,0 @@
1
- Prunes tool outputs from context to manage conversation size and reduce noise. For `write` and `edit` tools, the input content is pruned instead of the output.
2
-
3
- ## IMPORTANT: The Prunable List
4
- A `<prunable-tools>` list is injected into user messages showing available tool outputs you can prune. Each line has the format `ID: tool, parameter` (e.g., `20: read, /path/to/file.ts`). You MUST only use numeric IDs that appear in this list to select which tools to prune.
5
-
6
- **Note:** For `write` and `edit` tools, pruning removes the input content (the code being written/edited) while preserving the output confirmation. This is useful after completing a file modification when you no longer need the raw content in context.
7
-
8
- ## CRITICAL: When and How to Prune
9
-
10
- You must use this tool in three specific scenarios. The rules for distillation (summarizing findings) differ for each. **You must specify the reason as the first element of the `ids` array** to indicate which scenario applies.
11
-
12
- ### 1. Task Completion (Clean Up) — reason: `completion`
13
- **When:** You have successfully completed a specific unit of work (e.g., fixed a bug, wrote a file, answered a question).
14
- **Action:** Prune the tools used for that task.
15
- **Distillation:** NOT REQUIRED. Since the task is done, the raw data is no longer needed. Simply state that the task is complete.
16
-
17
- ### 2. Removing Noise (Garbage Collection) — reason: `noise`
18
- **When:** You have read files or run commands that turned out to be irrelevant, unhelpful, or outdated (meaning later tools have provided fresher, more valid information).
19
- **Action:** Prune these specific tool outputs immediately.
20
- **Distillation:** FORBIDDEN. Do not pollute the context by summarizing useless information. Just cut it out.
21
-
22
- ### 3. Context Conservation (Research & Consolidation) — reason: `consolidation`
23
- **When:** You have gathered useful information. Prune frequently as you work (e.g., after reading a few files), rather than waiting for a "long" phase to end.
24
- **Action:** Convert raw data into distilled knowledge. This allows you to discard large outputs (like full file reads) while keeping only the specific parts you need (like a single function signature or constant).
25
- **Distillation:** MANDATORY. Before pruning, you *must* explicitly summarize the key findings from *every* tool you plan to prune.
26
- - **Extract specific value:** If you read a large file but only care about one function, record that function's details and prune the whole read.
27
- - Narrative format: "I found X in file Y..."
28
- - Capture all relevant details (function names, logic, constraints).
29
- - Once distilled into your response history, the raw tool output can be safely pruned.
30
- - **Know when distillation isn't enough:** If you'll need to edit a file, grep for exact strings, or reference precise syntax, keep the raw output. Distillation works for understanding; implementation often requires the original.
31
- - **Prefer keeping over re-fetching:** If uncertain whether you'll need the output again, keep it. The cost of retaining context is lower than the cost of redundant tool calls.
32
-
33
- ## Best Practices
34
- - **Don't wait too long:** Prune frequently to keep the context agile.
35
- - **Be surgical:** You can mix strategies. Prune noise without comment, while distilling useful context in the same turn.
36
- - **Verify:** Ensure you have captured what you need before deleting useful raw data.
37
- - **Think ahead:** Before pruning, ask: "Will I need this output for an upcoming task?" If you researched a file you'll later edit, or gathered context for implementation, do NOT prune it—even if you've distilled findings. Distillation captures *knowledge*; implementation requires *context*.
38
-
39
- ## Examples
40
-
41
- <example_noise>
42
- Assistant: [Reads 'wrong_file.ts']
43
- This file isn't relevant to the auth system. I'll remove it to clear the context.
44
- [Uses prune with ids: ["noise", "5"]]
45
- </example_noise>
46
-
47
- <example_consolidation>
48
- Assistant: [Reads 5 different config files]
49
- I have analyzed the configuration. Here is the distillation:
50
- - 'config.ts' uses port 3000.
51
- - 'db.ts' connects to mongo:27017.
52
- - The other 3 files were defaults.
53
- I have preserved the signals above, so I am now pruning the raw reads.
54
- [Uses prune with ids: ["consolidation", "10", "11", "12", "13", "14"]]
55
- </example_consolidation>
56
-
57
- <example_completion>
58
- Assistant: [Runs tests, they pass]
59
- The tests passed. The feature is verified.
60
- [Uses prune with ids: ["completion", "20", "21"]]
61
- </example_completion>
62
-
63
- <example_keep>
64
- Assistant: [Reads 'auth.ts' to understand the login flow]
65
- I've understood the auth flow. I'll need to modify this file to add the new validation, so I'm keeping this read in context rather than distilling and pruning.
66
- </example_keep>
67
-
68
- <example_edit_completion>
69
- Assistant: [Edits 'auth.ts' to add validation]
70
- The edit was successful. I no longer need the raw edit content in context.
71
- [Uses prune with ids: ["completion", "15"]]
72
- </example_edit_completion>
@@ -1 +0,0 @@
1
- {"version":3,"file":"prune-tool.d.ts","sourceRoot":"","sources":["../../../lib/strategies/prune-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAiC,MAAM,UAAU,CAAA;AAC3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAM7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAOvC,MAAM,WAAW,gBAAgB;IAC7B,MAAM,EAAE,GAAG,CAAA;IACX,KAAK,EAAE,YAAY,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,YAAY,CAAA;IACpB,gBAAgB,EAAE,MAAM,CAAA;CAC3B;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC3B,GAAG,EAAE,gBAAgB,GACtB,UAAU,CAAC,OAAO,IAAI,CAAC,CA2GzB"}
@@ -1,88 +0,0 @@
1
- import { tool } from "@opencode-ai/plugin";
2
- import { buildToolIdList } from "../messages/utils";
3
- import { sendUnifiedNotification } from "../ui/notification";
4
- import { formatPruningResultForTool } from "../ui/utils";
5
- import { ensureSessionInitialized } from "../state";
6
- import { saveSessionState } from "../state/persistence";
7
- import { loadPrompt } from "../prompt";
8
- import { calculateTokensSaved, getCurrentParams } from "./utils";
9
- /** Tool description loaded from prompts/tool.txt */
10
- const TOOL_DESCRIPTION = loadPrompt("tool");
11
- /**
12
- * Creates the prune tool definition.
13
- * Accepts numeric IDs from the <prunable-tools> list and prunes those tool outputs.
14
- */
15
- export function createPruneTool(ctx) {
16
- return tool({
17
- description: TOOL_DESCRIPTION,
18
- args: {
19
- ids: tool.schema.array(tool.schema.string()).describe("First element is the reason ('completion', 'noise', 'consolidation'), followed by numeric IDs as strings to prune"),
20
- },
21
- async execute(args, toolCtx) {
22
- const { client, state, logger, config, workingDirectory } = ctx;
23
- const sessionId = toolCtx.sessionID;
24
- logger.info("Prune tool invoked");
25
- logger.info(JSON.stringify(args));
26
- if (!args.ids || args.ids.length === 0) {
27
- logger.debug("Prune tool called but args.ids is empty or undefined: " + JSON.stringify(args));
28
- return "No IDs provided. Check the <prunable-tools> list for available IDs to prune.";
29
- }
30
- // Parse reason from first element, numeric IDs from the rest
31
- const reason = args.ids[0];
32
- const validReasons = ["completion", "noise", "consolidation"];
33
- if (typeof reason !== "string" || !validReasons.includes(reason)) {
34
- logger.debug("Invalid pruning reason provided: " + reason);
35
- return "No valid pruning reason found. Use 'completion', 'noise', or 'consolidation' as the first element.";
36
- }
37
- const numericToolIds = args.ids.slice(1)
38
- .map(id => parseInt(id, 10))
39
- .filter((n) => !isNaN(n));
40
- if (numericToolIds.length === 0) {
41
- logger.debug("No numeric tool IDs provided for pruning, yet prune tool was called: " + JSON.stringify(args));
42
- return "No numeric IDs provided. Format: [reason, id1, id2, ...] where reason is 'completion', 'noise', or 'consolidation'.";
43
- }
44
- // Fetch messages to calculate tokens and find current agent
45
- const messagesResponse = await client.session.messages({
46
- path: { id: sessionId }
47
- });
48
- const messages = messagesResponse.data || messagesResponse;
49
- await ensureSessionInitialized(ctx.client, state, sessionId, logger, messages);
50
- const currentParams = getCurrentParams(messages, logger);
51
- const toolIdList = buildToolIdList(state, messages, logger);
52
- // Validate that all numeric IDs are within bounds
53
- if (numericToolIds.some(id => id < 0 || id >= toolIdList.length)) {
54
- logger.debug("Invalid tool IDs provided: " + numericToolIds.join(", "));
55
- return "Invalid IDs provided. Only use numeric IDs from the <prunable-tools> list.";
56
- }
57
- // Check for protected tools (model hallucinated an ID not in the prunable list)
58
- for (const index of numericToolIds) {
59
- const id = toolIdList[index];
60
- const metadata = state.toolParameters.get(id);
61
- if (metadata && config.strategies.pruneTool.protectedTools.includes(metadata.tool)) {
62
- return "Invalid IDs provided. Only use numeric IDs from the <prunable-tools> list.";
63
- }
64
- }
65
- const pruneToolIds = numericToolIds.map(index => toolIdList[index]);
66
- state.prune.toolIds.push(...pruneToolIds);
67
- const toolMetadata = new Map();
68
- for (const id of pruneToolIds) {
69
- const toolParameters = state.toolParameters.get(id);
70
- if (toolParameters) {
71
- toolMetadata.set(id, toolParameters);
72
- }
73
- else {
74
- logger.debug("No metadata found for ID", { id });
75
- }
76
- }
77
- state.stats.pruneTokenCounter += calculateTokensSaved(state, messages, pruneToolIds);
78
- await sendUnifiedNotification(client, logger, config, state, sessionId, pruneToolIds, toolMetadata, reason, currentParams, workingDirectory);
79
- state.stats.totalPruneTokens += state.stats.pruneTokenCounter;
80
- state.stats.pruneTokenCounter = 0;
81
- state.nudgeCounter = 0;
82
- saveSessionState(state, logger)
83
- .catch(err => logger.error("Failed to persist state", { error: err.message }));
84
- return formatPruningResultForTool(pruneToolIds, toolMetadata, workingDirectory);
85
- },
86
- });
87
- }
88
- //# sourceMappingURL=prune-tool.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prune-tool.js","sourceRoot":"","sources":["../../../lib/strategies/prune-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AAG1C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAe,uBAAuB,EAAE,MAAM,oBAAoB,CAAA;AACzE,OAAO,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAA;AACxD,OAAO,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAEvD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AACtC,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAEhE,oDAAoD;AACpD,MAAM,gBAAgB,GAAG,UAAU,CAAC,MAAM,CAAC,CAAA;AAU3C;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC3B,GAAqB;IAErB,OAAO,IAAI,CAAC;QACR,WAAW,EAAE,gBAAgB;QAC7B,IAAI,EAAE;YACF,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAClB,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CACvB,CAAC,QAAQ,CACN,mHAAmH,CACtH;SACJ;QACD,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO;YACvB,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,GAAG,GAAG,CAAA;YAC/D,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAA;YAEnC,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAA;YACjC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;YAEjC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACrC,MAAM,CAAC,KAAK,CAAC,wDAAwD,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;gBAC7F,OAAO,8EAA8E,CAAA;YACzF,CAAC;YAED,6DAA6D;YAE7D,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAC3B,MAAM,YAAY,GAAG,CAAC,YAAY,EAAE,OAAO,EAAE,eAAe,CAAU,CAAA;YACtE,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAa,CAAC,EAAE,CAAC;gBACtE,MAAM,CAAC,KAAK,CAAC,mCAAmC,GAAG,MAAM,CAAC,CAAA;gBAC1D,OAAO,oGAAoG,CAAA;YAC/G,CAAC;YAED,MAAM,cAAc,GAAa,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;iBAC7C,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;iBAC3B,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;YAC1C,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC9B,MAAM,CAAC,KAAK,CAAC,uEAAuE,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;gBAC5G,OAAO,qHAAqH,CAAA;YAChI,CAAC;YAED,4DAA4D;YAC5D,MAAM,gBAAgB,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;gBACnD,IAAI,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE;aAC1B,CAAC,CAAA;YACF,MAAM,QAAQ,GAAgB,gBAAgB,CAAC,IAAI,IAAI,gBAAgB,CAAA;YAEvE,MAAM,wBAAwB,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAA;YAE9E,MAAM,aAAa,GAAG,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;YACxD,MAAM,UAAU,GAAa,eAAe,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAA;YAErE,kDAAkD;YAClD,IAAI,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC/D,MAAM,CAAC,KAAK,CAAC,6BAA6B,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;gBACvE,OAAO,4EAA4E,CAAA;YACvF,CAAC;YAED,gFAAgF;YAChF,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;gBACjC,MAAM,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC,CAAA;gBAC5B,MAAM,QAAQ,GAAG,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;gBAC7C,IAAI,QAAQ,IAAI,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,cAAc,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;oBACjF,OAAO,4EAA4E,CAAA;gBACvF,CAAC;YACL,CAAC;YAED,MAAM,YAAY,GAAa,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAA;YAC7E,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,CAAA;YAEzC,MAAM,YAAY,GAAG,IAAI,GAAG,EAA8B,CAAA;YAC1D,KAAK,MAAM,EAAE,IAAI,YAAY,EAAE,CAAC;gBAC5B,MAAM,cAAc,GAAG,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;gBACnD,IAAI,cAAc,EAAE,CAAC;oBACjB,YAAY,CAAC,GAAG,CAAC,EAAE,EAAE,cAAc,CAAC,CAAA;gBACxC,CAAC;qBAAM,CAAC;oBACJ,MAAM,CAAC,KAAK,CAAC,0BAA0B,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;gBACpD,CAAC;YACL,CAAC;YAED,KAAK,CAAC,KAAK,CAAC,iBAAiB,IAAI,oBAAoB,CAAC,KAAK,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAA;YAEpF,MAAM,uBAAuB,CACzB,MAAM,EACN,MAAM,EACN,MAAM,EACN,KAAK,EACL,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,MAAqB,EACrB,aAAa,EACb,gBAAgB,CACnB,CAAA;YAED,KAAK,CAAC,KAAK,CAAC,gBAAgB,IAAI,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAA;YAC7D,KAAK,CAAC,KAAK,CAAC,iBAAiB,GAAG,CAAC,CAAA;YACjC,KAAK,CAAC,YAAY,GAAG,CAAC,CAAA;YAEtB,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC;iBAC1B,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,yBAAyB,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;YAElF,OAAO,0BAA0B,CAC7B,YAAY,EACZ,YAAY,EACZ,gBAAgB,CACnB,CAAA;QACL,CAAC;KACJ,CAAC,CAAA;AACN,CAAC"}