link-agents 0.9.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 (184) hide show
  1. package/AGENTS.md +127 -0
  2. package/README.md +93 -0
  3. package/cursor-rules-notes.md +23 -0
  4. package/dist/cli/interactive.d.ts +9 -0
  5. package/dist/cli/interactive.d.ts.map +1 -0
  6. package/dist/cli/interactive.js +1176 -0
  7. package/dist/cli/interactive.js.map +1 -0
  8. package/dist/cli/options.d.ts +3 -0
  9. package/dist/cli/options.d.ts.map +1 -0
  10. package/dist/cli/options.js +107 -0
  11. package/dist/cli/options.js.map +1 -0
  12. package/dist/cli/options.spec.d.ts +2 -0
  13. package/dist/cli/options.spec.d.ts.map +1 -0
  14. package/dist/cli/options.spec.js +74 -0
  15. package/dist/cli/options.spec.js.map +1 -0
  16. package/dist/clients/definitions.d.ts +5 -0
  17. package/dist/clients/definitions.d.ts.map +1 -0
  18. package/dist/clients/definitions.js +82 -0
  19. package/dist/clients/definitions.js.map +1 -0
  20. package/dist/clients/definitions.spec.d.ts +2 -0
  21. package/dist/clients/definitions.spec.d.ts.map +1 -0
  22. package/dist/clients/definitions.spec.js +135 -0
  23. package/dist/clients/definitions.spec.js.map +1 -0
  24. package/dist/commands/doctor.d.ts +3 -0
  25. package/dist/commands/doctor.d.ts.map +1 -0
  26. package/dist/commands/doctor.js +81 -0
  27. package/dist/commands/doctor.js.map +1 -0
  28. package/dist/commands/restore.d.ts +3 -0
  29. package/dist/commands/restore.d.ts.map +1 -0
  30. package/dist/commands/restore.js +36 -0
  31. package/dist/commands/restore.js.map +1 -0
  32. package/dist/commands/sync.d.ts +3 -0
  33. package/dist/commands/sync.d.ts.map +1 -0
  34. package/dist/commands/sync.js +193 -0
  35. package/dist/commands/sync.js.map +1 -0
  36. package/dist/index.d.ts +3 -0
  37. package/dist/index.d.ts.map +1 -0
  38. package/dist/index.js +30 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/types/index.d.ts +98 -0
  41. package/dist/types/index.d.ts.map +1 -0
  42. package/dist/types/index.js +2 -0
  43. package/dist/types/index.js.map +1 -0
  44. package/dist/utils/apply.d.ts +22 -0
  45. package/dist/utils/apply.d.ts.map +1 -0
  46. package/dist/utils/apply.js +215 -0
  47. package/dist/utils/apply.js.map +1 -0
  48. package/dist/utils/bootstrap.d.ts +18 -0
  49. package/dist/utils/bootstrap.d.ts.map +1 -0
  50. package/dist/utils/bootstrap.js +31 -0
  51. package/dist/utils/bootstrap.js.map +1 -0
  52. package/dist/utils/bootstrap.spec.d.ts +2 -0
  53. package/dist/utils/bootstrap.spec.d.ts.map +1 -0
  54. package/dist/utils/bootstrap.spec.js +92 -0
  55. package/dist/utils/bootstrap.spec.js.map +1 -0
  56. package/dist/utils/canonical.d.ts +17 -0
  57. package/dist/utils/canonical.d.ts.map +1 -0
  58. package/dist/utils/canonical.js +136 -0
  59. package/dist/utils/canonical.js.map +1 -0
  60. package/dist/utils/canonicalState.d.ts +19 -0
  61. package/dist/utils/canonicalState.d.ts.map +1 -0
  62. package/dist/utils/canonicalState.js +21 -0
  63. package/dist/utils/canonicalState.js.map +1 -0
  64. package/dist/utils/cursorHistory.d.ts +7 -0
  65. package/dist/utils/cursorHistory.d.ts.map +1 -0
  66. package/dist/utils/cursorHistory.js +54 -0
  67. package/dist/utils/cursorHistory.js.map +1 -0
  68. package/dist/utils/cursorPaths.d.ts +3 -0
  69. package/dist/utils/cursorPaths.d.ts.map +1 -0
  70. package/dist/utils/cursorPaths.js +17 -0
  71. package/dist/utils/cursorPaths.js.map +1 -0
  72. package/dist/utils/discovery.d.ts +8 -0
  73. package/dist/utils/discovery.d.ts.map +1 -0
  74. package/dist/utils/discovery.js +93 -0
  75. package/dist/utils/discovery.js.map +1 -0
  76. package/dist/utils/frontmatter.d.ts +32 -0
  77. package/dist/utils/frontmatter.d.ts.map +1 -0
  78. package/dist/utils/frontmatter.js +263 -0
  79. package/dist/utils/frontmatter.js.map +1 -0
  80. package/dist/utils/frontmatter.spec.d.ts +2 -0
  81. package/dist/utils/frontmatter.spec.d.ts.map +1 -0
  82. package/dist/utils/frontmatter.spec.js +264 -0
  83. package/dist/utils/frontmatter.spec.js.map +1 -0
  84. package/dist/utils/fs.d.ts +27 -0
  85. package/dist/utils/fs.d.ts.map +1 -0
  86. package/dist/utils/fs.js +137 -0
  87. package/dist/utils/fs.js.map +1 -0
  88. package/dist/utils/fs.spec.d.ts +2 -0
  89. package/dist/utils/fs.spec.d.ts.map +1 -0
  90. package/dist/utils/fs.spec.js +73 -0
  91. package/dist/utils/fs.spec.js.map +1 -0
  92. package/dist/utils/gitignore.d.ts +10 -0
  93. package/dist/utils/gitignore.d.ts.map +1 -0
  94. package/dist/utils/gitignore.js +63 -0
  95. package/dist/utils/gitignore.js.map +1 -0
  96. package/dist/utils/manifest.d.ts +28 -0
  97. package/dist/utils/manifest.d.ts.map +1 -0
  98. package/dist/utils/manifest.js +89 -0
  99. package/dist/utils/manifest.js.map +1 -0
  100. package/dist/utils/mcp.d.ts +73 -0
  101. package/dist/utils/mcp.d.ts.map +1 -0
  102. package/dist/utils/mcp.js +529 -0
  103. package/dist/utils/mcp.js.map +1 -0
  104. package/dist/utils/mcp.spec.d.ts +2 -0
  105. package/dist/utils/mcp.spec.d.ts.map +1 -0
  106. package/dist/utils/mcp.spec.js +488 -0
  107. package/dist/utils/mcp.spec.js.map +1 -0
  108. package/dist/utils/merge.d.ts +17 -0
  109. package/dist/utils/merge.d.ts.map +1 -0
  110. package/dist/utils/merge.js +45 -0
  111. package/dist/utils/merge.js.map +1 -0
  112. package/dist/utils/merge.spec.d.ts +2 -0
  113. package/dist/utils/merge.spec.d.ts.map +1 -0
  114. package/dist/utils/merge.spec.js +134 -0
  115. package/dist/utils/merge.spec.js.map +1 -0
  116. package/dist/utils/paths.d.ts +11 -0
  117. package/dist/utils/paths.d.ts.map +1 -0
  118. package/dist/utils/paths.js +164 -0
  119. package/dist/utils/paths.js.map +1 -0
  120. package/dist/utils/paths.spec.d.ts +2 -0
  121. package/dist/utils/paths.spec.d.ts.map +1 -0
  122. package/dist/utils/paths.spec.js +282 -0
  123. package/dist/utils/paths.spec.js.map +1 -0
  124. package/dist/utils/plan.d.ts +7 -0
  125. package/dist/utils/plan.d.ts.map +1 -0
  126. package/dist/utils/plan.js +118 -0
  127. package/dist/utils/plan.js.map +1 -0
  128. package/dist/utils/plan.spec.d.ts +2 -0
  129. package/dist/utils/plan.spec.d.ts.map +1 -0
  130. package/dist/utils/plan.spec.js +420 -0
  131. package/dist/utils/plan.spec.js.map +1 -0
  132. package/dist/utils/reporting.d.ts +21 -0
  133. package/dist/utils/reporting.d.ts.map +1 -0
  134. package/dist/utils/reporting.js +82 -0
  135. package/dist/utils/reporting.js.map +1 -0
  136. package/dist/utils/reporting.spec.d.ts +2 -0
  137. package/dist/utils/reporting.spec.d.ts.map +1 -0
  138. package/dist/utils/reporting.spec.js +78 -0
  139. package/dist/utils/reporting.spec.js.map +1 -0
  140. package/dist/utils/reset.d.ts +14 -0
  141. package/dist/utils/reset.d.ts.map +1 -0
  142. package/dist/utils/reset.js +81 -0
  143. package/dist/utils/reset.js.map +1 -0
  144. package/dist/utils/revert.d.ts +30 -0
  145. package/dist/utils/revert.d.ts.map +1 -0
  146. package/dist/utils/revert.js +89 -0
  147. package/dist/utils/revert.js.map +1 -0
  148. package/dist/utils/revert.spec.d.ts +2 -0
  149. package/dist/utils/revert.spec.d.ts.map +1 -0
  150. package/dist/utils/revert.spec.js +102 -0
  151. package/dist/utils/revert.spec.js.map +1 -0
  152. package/dist/utils/similarity.d.ts +14 -0
  153. package/dist/utils/similarity.d.ts.map +1 -0
  154. package/dist/utils/similarity.js +70 -0
  155. package/dist/utils/similarity.js.map +1 -0
  156. package/dist/utils/similarity.spec.d.ts +2 -0
  157. package/dist/utils/similarity.spec.d.ts.map +1 -0
  158. package/dist/utils/similarity.spec.js +62 -0
  159. package/dist/utils/similarity.spec.js.map +1 -0
  160. package/dist/utils/snapshots.d.ts +21 -0
  161. package/dist/utils/snapshots.d.ts.map +1 -0
  162. package/dist/utils/snapshots.js +81 -0
  163. package/dist/utils/snapshots.js.map +1 -0
  164. package/dist/utils/snapshots.spec.d.ts +2 -0
  165. package/dist/utils/snapshots.spec.d.ts.map +1 -0
  166. package/dist/utils/snapshots.spec.js +56 -0
  167. package/dist/utils/snapshots.spec.js.map +1 -0
  168. package/dist/utils/syncFilters.d.ts +3 -0
  169. package/dist/utils/syncFilters.d.ts.map +1 -0
  170. package/dist/utils/syncFilters.js +8 -0
  171. package/dist/utils/syncFilters.js.map +1 -0
  172. package/dist/utils/syncRuntime.d.ts +3 -0
  173. package/dist/utils/syncRuntime.d.ts.map +1 -0
  174. package/dist/utils/syncRuntime.js +31 -0
  175. package/dist/utils/syncRuntime.js.map +1 -0
  176. package/dist/utils/validation.d.ts +3 -0
  177. package/dist/utils/validation.d.ts.map +1 -0
  178. package/dist/utils/validation.js +19 -0
  179. package/dist/utils/validation.js.map +1 -0
  180. package/dist/utils/validation.spec.d.ts +2 -0
  181. package/dist/utils/validation.spec.d.ts.map +1 -0
  182. package/dist/utils/validation.spec.js +36 -0
  183. package/dist/utils/validation.spec.js.map +1 -0
  184. package/package.json +63 -0
package/AGENTS.md ADDED
@@ -0,0 +1,127 @@
1
+ # AGENTS.md — link-agents
2
+
3
+ Guidance for autonomous coding agents contributing to the `link-agents` package.
4
+
5
+ ## TL;DR
6
+
7
+ - Prefer TypeScript (NodeNext modules).
8
+ - Run `npm install` then `npm run build` before shipping changes.
9
+ - Run `npm test` to verify all tests pass.
10
+ - Default CLI mode is interactive; keep UX non-destructive.
11
+
12
+ > Note: the public CLI now centers on `sync`, `doctor`, and `restore` subcommands. Older mode/flag descriptions below are legacy until the rest of this document is refreshed.
13
+
14
+ ## Project Overview
15
+
16
+ - **Purpose:** synchronize agent artifacts (AGENTS, commands, prompts, rules, skills, MCP configs) across Codex, Claude Code, Claude Desktop, Cursor, Windsurf, Cline, Roo Code, Gemini CLI, OpenCode, VS Code, Antigravity, Goose, and the current project.
17
+ - **Entry point:** `src/index.ts` (CLI executable exported via `bin.link-agents`).
18
+
19
+ ## Key Modules
20
+
21
+ ### CLI Layer
22
+
23
+ - `src/cli/options.ts` — argument parsing (commander)
24
+ - `src/cli/interactive-v2.ts` — interactive TUI flow using @clack/prompts
25
+
26
+ ### Core Utils
27
+
28
+ - `src/utils/discovery.ts` — asset discovery via globbing
29
+ - `src/utils/plan.ts` — merge/source planning logic
30
+ - `src/utils/apply.ts` — file writes with backup, verification, skip-unchanged
31
+ - `src/utils/fs.ts` — filesystem utilities (read, write, symlink, backup, hash)
32
+ - `src/utils/mcp.ts` — MCP config parsing, merging, validation, secret obfuscation
33
+ - `src/utils/similarity.ts` — content similarity calculation for conflict resolution
34
+ - `src/utils/paths.ts` — path normalization and canonical path resolution
35
+ - `src/utils/validation.ts` — asset validation utilities
36
+ - `src/utils/cursorHistory.ts` — Cursor UI "Rules & Config" export helper
37
+
38
+ ### Client Definitions
39
+
40
+ - `src/clients/definitions.ts` — client root paths and asset type mappings
41
+
42
+ ### Types
43
+
44
+ - `src/types/index.ts` — shared TypeScript types
45
+
46
+ ## Interactive Flow
47
+
48
+ The interactive mode (`npm run dev`) follows this sequence:
49
+
50
+ 1. Select scope (global/project)
51
+ 2. Select direction (push/pull/sync)
52
+ 3. Scan all clients for assets
53
+ 4. Detect & resolve conflicts (shows similarity %, modification time)
54
+ 5. Select target clients (shows diff counts: +new, ~update)
55
+ 6. Build sync plan
56
+ 7. Review MCP servers (shows env vars with secrets obfuscated, diffs between clients)
57
+ 8. Validate MCP configs (check commands exist, warn about removals)
58
+ 9. Show planned changes
59
+ 10. Confirm apply
60
+ 11. Ask about symlinks vs copying
61
+ 12. Apply with backup, skip-unchanged, and post-verification
62
+
63
+ ## Workflow
64
+
65
+ 1. Install deps with `npm install`.
66
+ 2. Use `npm run dev` for iterative runs (`tsx`).
67
+ 3. Run `npm run build` before publishing; output lives in `dist/`.
68
+ 4. Run `npm test` to run vitest tests.
69
+ 5. Keep new dependencies minimal and ESM-friendly.
70
+
71
+ ## Style & Testing
72
+
73
+ - Strict TypeScript; avoid `any`.
74
+ - Prefer pure utilities over side effects.
75
+ - Add unit tests with `vitest` when adding planners or new merge behaviors.
76
+ - Tests live alongside source files as `*.spec.ts`.
77
+
78
+ ## Safety Features
79
+
80
+ ### File Operations
81
+
82
+ - Never touch directories outside defined client roots without explicit confirmation.
83
+ - Interactive mode is the safest default; `--dry-run` should work in every mode.
84
+ - `writeFileSafe` ensures directories exist before writing.
85
+ - Backup files (`.bak`) are created before overwriting existing files.
86
+ - Post-write verification ensures file was written correctly.
87
+ - Unchanged files are skipped (hash comparison).
88
+
89
+ ### MCP Handling
90
+
91
+ - Secrets in env vars are auto-detected and obfuscated in display.
92
+ - Detected patterns: API keys, tokens, passwords, long alphanumeric strings.
93
+ - MCP configs are validated before apply (check for missing commands).
94
+ - Warnings shown when servers would be removed from target.
95
+ - Users can pick which version when same server has different configs across clients.
96
+
97
+ ### Sync Direction
98
+
99
+ - `push`: Project -> Global clients
100
+ - `pull`: Global clients -> Project
101
+ - `sync`: Merge all and sync everywhere
102
+
103
+ ### Symlinks
104
+
105
+ - `--link` flag or interactive prompt to use symlinks instead of copying.
106
+ - Symlinks keep files in sync automatically.
107
+
108
+ ## Client Notes
109
+
110
+ - Claude commands are treated as Codex `prompts/*.md` during sync—Codex users must restart the CLI/IDE after syncing so slash commands reload.
111
+ - Writing to Codex's home (e.g., `~/.codex/agents` or `~/.codex/prompts`) may require elevated permissions.
112
+ - Codex uses `prompts/` for commands (not `commands/`).
113
+ - Claude Desktop only supports MCP configs (`claude_desktop_config.json`), no agents/commands/rules/skills.
114
+
115
+ ## CLI Flags
116
+
117
+ | Flag | Description |
118
+ | ------------------- | ---------------------------------------------- |
119
+ | `--dry-run` | Show what would be done without making changes |
120
+ | `--link` | Use symlinks instead of copying files |
121
+ | `--separate-claude-md` | Leave Claude's `CLAUDE.md` unmanaged during sync |
122
+ | `--verbose` | Show detailed output |
123
+ | `--scope <scope>` | `global`, `project`, or `all` |
124
+ | `--direction <dir>` | `push`, `pull`, or `sync` |
125
+ | `--source <client>` | Source client name |
126
+ | `--clients <names>` | Comma-separated client names |
127
+ | `--types <types>` | Comma-separated asset types |
package/README.md ADDED
@@ -0,0 +1,93 @@
1
+ # link-agents
2
+
3
+ Synchronize canonical `.agents` assets across AI coding assistants.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ npx link-agents sync
9
+ ```
10
+
11
+ This command:
12
+
13
+ 1. Reads canonical assets from `.agents/`
14
+ 2. Bootstraps missing canonical assets from legacy client files when possible
15
+ 3. Warns about unsupported legacy inputs like `~/.cursor/rules/*`
16
+ 4. Fans out canonical assets to client-specific locations
17
+ 5. Creates a restore point before mutating targets
18
+
19
+ ## Canonical Layout
20
+
21
+ ```text
22
+ .agents/
23
+ AGENTS.md
24
+ commands/
25
+ skills/
26
+ mcp.json
27
+ ```
28
+
29
+ `link-agents` treats `.agents/*` as the source of truth once those files exist.
30
+
31
+ ## Commands
32
+
33
+ ### `sync`
34
+
35
+ Bootstrap canonical assets if needed, then sync them to supported clients.
36
+
37
+ ```bash
38
+ npx link-agents sync
39
+ npx link-agents sync --dry-run
40
+ npx link-agents sync --link
41
+ npx link-agents sync --copy
42
+ npx link-agents sync --separate-claude-md
43
+ npx link-agents sync --bootstrap-source claude
44
+ npx link-agents sync --clients claude,cursor
45
+ npx link-agents sync --types agents,mcp
46
+ ```
47
+
48
+ Notes:
49
+
50
+ - `--link` prefers symlinks when target bytes can exactly reuse canonical bytes.
51
+ - `--copy` always writes independent copies.
52
+ - If neither flag is provided and the terminal is interactive, `sync` asks which write mode to use.
53
+ - `--separate-claude-md` leaves `CLAUDE.md` unmanaged for that run.
54
+ - If bootstrap is ambiguous, interactive sync asks which client to use; non-interactive sync requires `--bootstrap-source`.
55
+
56
+ ### `doctor`
57
+
58
+ Inspect canonical sync health, ignored legacy inputs, broken generated targets, and canonical assets eligible for bootstrap.
59
+
60
+ ```bash
61
+ npx link-agents doctor
62
+ npx link-agents doctor --verbose
63
+ ```
64
+
65
+ ### `restore`
66
+
67
+ Restore sync-managed targets from a snapshot.
68
+
69
+ ```bash
70
+ npx link-agents restore --latest
71
+ npx link-agents restore --list
72
+ npx link-agents restore --id <snapshot-id>
73
+ npx link-agents restore --latest --dry-run
74
+ ```
75
+
76
+ ## Supported Clients
77
+
78
+ Public sync targets only home-directory clients. The repo-local `.agents/*` tree is canonical storage, not a public client target.
79
+
80
+ | Client | Root | Agents | Commands | Skills | MCP |
81
+ | --------- | -------------------- | ----------- | -------------------------------- | ------------------------------------- | -------------- |
82
+ | `codex` | `~/.codex` | `AGENTS.md` | `skills/commands/**/SKILL.md` | `skills/**/SKILL.md` | `config.toml` |
83
+ | `claude` | `~/.claude` | `CLAUDE.md` | `commands/**/*.md` | — | — |
84
+ | `cursor` | `~/.cursor` | `AGENTS.md` | `commands/**/*.md` | — | `mcp.json` |
85
+ | `opencode`| `~/.config/opencode` | `AGENTS.md` | `command/**/*.md` | `skill/**/SKILL.md` | `opencode.json` |
86
+
87
+ ## Behavior Notes
88
+
89
+ - `~/.cursor/rules/*` is treated as an unsupported legacy input. It is reported by `sync`/`doctor`, but never imported into canonical storage.
90
+ - `CLAUDE.md` can be left unmanaged with `--separate-claude-md`.
91
+ - Restore points are created before `sync` mutates targets.
92
+ - Generated symlinks always point back to canonical `.agents/*` sources, not to legacy client files.
93
+ - Public sync does not read from or write to legacy project-level command locations.
@@ -0,0 +1,23 @@
1
+ # Cursor User Rules Storage Notes
2
+
3
+ ## Global rule files
4
+ - The Cursor desktop app stores each global "Rules and Config" entry as Markdown files under `~/Library/Application Support/Cursor/User/History/<hash>/`.
5
+ - Every rule folder contains multiple `.md` copies (for example `OVGe.md`, `BDkg.md`, etc.) that all mirror the text shown in the UI. These are the files to back up/edit when exporting rules.
6
+ - The same folder also includes an `entries.json` with metadata (timestamps, IDs) that Cursor uses internally; it is not required when copying text.
7
+
8
+ ## Example (rule reminding agent to ask clarifying questions)
9
+ - Files located at `~/Library/Application Support/Cursor/User/History/5dbb075c/`:
10
+ - `OVGe.md`, `BDkg.md`, `N4sE.md`, `NSdP.md`, `7oPW.md`: contain the full rule content ("Expert AI Programming Assistant" instructions).
11
+ - `entries.json`: metadata that can be ignored unless you need Cursor’s IDs.
12
+
13
+ ## How to extract your current rules
14
+ 1. `cd ~/Library/Application\ Support/Cursor/User/History`.
15
+ 2. Inspect the folders (each is a short hash) and open the `.md` file(s) inside to read or copy the rule text.
16
+ 3. To find a specific line (e.g. "yarn install fails"), use ripgrep: `rg -n "yarn install fails" "~/Library/Application Support/Cursor/User/History"`.
17
+ 4. The matches show the exact hash + file name, so you can open and archive that Markdown.
18
+
19
+ ## Key takeaways
20
+ - Cursor does **not** save those rules in `settings.json`; the History tree is the source of truth.
21
+ - The `.md` files are plain text and safe to version-control or back up.
22
+ - Searching within `~/Library/Application Support/Cursor/User/History` is the quickest way to locate any current rule snippet.
23
+ - `link-agents --export-cursor-history --cursor-history-dest "~/.cursor/AGENTS.md"` can aggregate every history rule into a single file (adjust the destination if you prefer a different path).
@@ -0,0 +1,9 @@
1
+ import type { ClientDefinition, SyncDirection, SyncOptions, SyncPlanEntry, SyncScope } from "../types/index.js";
2
+ export interface InteractiveResult {
3
+ proceed: boolean;
4
+ entries: SyncPlanEntry[];
5
+ scope: SyncScope;
6
+ direction: SyncDirection;
7
+ }
8
+ export declare function runInteractiveFlow(defs: ClientDefinition[], options: SyncOptions): Promise<InteractiveResult>;
9
+ //# sourceMappingURL=interactive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interactive.d.ts","sourceRoot":"","sources":["../../src/cli/interactive.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAKV,gBAAgB,EAEhB,aAAa,EACb,WAAW,EACX,aAAa,EACb,SAAS,EACV,MAAM,mBAAmB,CAAC;AAyE3B,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,KAAK,EAAE,SAAS,CAAC;IACjB,SAAS,EAAE,aAAa,CAAC;CAC1B;AAED,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,gBAAgB,EAAE,EACxB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,iBAAiB,CAAC,CAiL5B"}