@cortexkit/aft 0.15.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 (47) hide show
  1. package/README.md +24 -0
  2. package/dist/__tests__/adapters.test.d.ts +2 -0
  3. package/dist/__tests__/adapters.test.d.ts.map +1 -0
  4. package/dist/__tests__/jsonc.test.d.ts +2 -0
  5. package/dist/__tests__/jsonc.test.d.ts.map +1 -0
  6. package/dist/__tests__/sanitize.test.d.ts +2 -0
  7. package/dist/__tests__/sanitize.test.d.ts.map +1 -0
  8. package/dist/adapters/index.d.ts +14 -0
  9. package/dist/adapters/index.d.ts.map +1 -0
  10. package/dist/adapters/opencode.d.ts +28 -0
  11. package/dist/adapters/opencode.d.ts.map +1 -0
  12. package/dist/adapters/pi.d.ts +25 -0
  13. package/dist/adapters/pi.d.ts.map +1 -0
  14. package/dist/adapters/types.d.ts +80 -0
  15. package/dist/adapters/types.d.ts.map +1 -0
  16. package/dist/commands/doctor.d.ts +7 -0
  17. package/dist/commands/doctor.d.ts.map +1 -0
  18. package/dist/commands/setup.d.ts +2 -0
  19. package/dist/commands/setup.d.ts.map +1 -0
  20. package/dist/index.d.ts +13 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +10343 -0
  23. package/dist/lib/binary-cache.d.ts +9 -0
  24. package/dist/lib/binary-cache.d.ts.map +1 -0
  25. package/dist/lib/binary-probe.d.ts +11 -0
  26. package/dist/lib/binary-probe.d.ts.map +1 -0
  27. package/dist/lib/diagnostics.d.ts +53 -0
  28. package/dist/lib/diagnostics.d.ts.map +1 -0
  29. package/dist/lib/fs-util.d.ts +7 -0
  30. package/dist/lib/fs-util.d.ts.map +1 -0
  31. package/dist/lib/github.d.ts +11 -0
  32. package/dist/lib/github.d.ts.map +1 -0
  33. package/dist/lib/harness-select.d.ts +18 -0
  34. package/dist/lib/harness-select.d.ts.map +1 -0
  35. package/dist/lib/jsonc.d.ts +19 -0
  36. package/dist/lib/jsonc.d.ts.map +1 -0
  37. package/dist/lib/onnx.d.ts +22 -0
  38. package/dist/lib/onnx.d.ts.map +1 -0
  39. package/dist/lib/paths.d.ts +6 -0
  40. package/dist/lib/paths.d.ts.map +1 -0
  41. package/dist/lib/prompts.d.ts +22 -0
  42. package/dist/lib/prompts.d.ts.map +1 -0
  43. package/dist/lib/sanitize.d.ts +13 -0
  44. package/dist/lib/sanitize.d.ts.map +1 -0
  45. package/dist/lib/self-version.d.ts +7 -0
  46. package/dist/lib/self-version.d.ts.map +1 -0
  47. package/package.json +29 -0
package/README.md ADDED
@@ -0,0 +1,24 @@
1
+ # @cortexkit/aft
2
+
3
+ Unified CLI for [Agent File Tools (AFT)](https://github.com/cortexkit/aft) — setup, doctor, and diagnostics across supported agent harnesses.
4
+
5
+ ## Usage
6
+
7
+ ```bash
8
+ bunx --bun @cortexkit/aft setup # interactive setup for one or more harnesses
9
+ bunx --bun @cortexkit/aft doctor # check and fix configuration issues
10
+ bunx --bun @cortexkit/aft doctor --force # force clear plugin cache
11
+ bunx --bun @cortexkit/aft doctor --issue # collect diagnostics and open a GitHub issue
12
+ ```
13
+
14
+ By default the CLI auto-detects which harnesses are installed on your system (OpenCode, Pi). When multiple are detected, it prompts you to choose. Use `--harness opencode` or `--harness pi` to target one explicitly.
15
+
16
+ ## Supported harnesses
17
+
18
+ - **OpenCode** — `@cortexkit/aft-opencode` plugin
19
+ - **Pi** — `@cortexkit/aft-pi` extension
20
+
21
+ ## Learn more
22
+
23
+ - Main repository: <https://github.com/cortexkit/aft>
24
+ - Issues: <https://github.com/cortexkit/aft/issues>
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=adapters.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapters.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/adapters.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=jsonc.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonc.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/jsonc.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=sanitize.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/sanitize.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,14 @@
1
+ import { OpenCodeAdapter } from "./opencode.js";
2
+ import { PiAdapter } from "./pi.js";
3
+ import type { HarnessAdapter, HarnessKind } from "./types.js";
4
+ export type { HarnessAdapter, HarnessKind } from "./types.js";
5
+ export { OpenCodeAdapter, PiAdapter };
6
+ export declare function getAllAdapters(): HarnessAdapter[];
7
+ export declare function getAdapter(kind: HarnessKind): HarnessAdapter;
8
+ /** Adapters whose host binary is on PATH. Order: installed first, then rest. */
9
+ export declare function getAdaptersPreferInstalled(): HarnessAdapter[];
10
+ /** Adapters that have AFT registered (either via plugin entry or `pi install`). */
11
+ export declare function getAdaptersWithPluginRegistered(): HarnessAdapter[];
12
+ /** Adapters whose host is installed, regardless of whether AFT is registered. */
13
+ export declare function getInstalledAdapters(): HarnessAdapter[];
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9D,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,CAAC;AAItC,wBAAgB,cAAc,IAAI,cAAc,EAAE,CAEjD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,GAAG,cAAc,CAI5D;AAED,gFAAgF;AAChF,wBAAgB,0BAA0B,IAAI,cAAc,EAAE,CAM7D;AAED,mFAAmF;AACnF,wBAAgB,+BAA+B,IAAI,cAAc,EAAE,CAElE;AAED,iFAAiF;AACjF,wBAAgB,oBAAoB,IAAI,cAAc,EAAE,CAEvD"}
@@ -0,0 +1,28 @@
1
+ import type { HarnessAdapter, HarnessConfigPaths, PluginCacheInfo, PluginEntryResult } from "./types.js";
2
+ export declare class OpenCodeAdapter implements HarnessAdapter {
3
+ readonly kind: "opencode";
4
+ readonly displayName = "OpenCode";
5
+ readonly pluginPackageName = "@cortexkit/aft-opencode";
6
+ readonly pluginEntryWithVersion = "@cortexkit/aft-opencode@latest";
7
+ isInstalled(): boolean;
8
+ getHostVersion(): string | null;
9
+ detectConfigPaths(): HarnessConfigPaths;
10
+ hasPluginEntry(): boolean;
11
+ ensurePluginEntry(): Promise<PluginEntryResult>;
12
+ getPluginCacheInfo(): PluginCacheInfo;
13
+ getStorageDir(): string;
14
+ getLogFile(): string;
15
+ getInstallHint(): string;
16
+ clearPluginCache(force: boolean): Promise<{
17
+ action: "cleared" | "up_to_date" | "not_found" | "not_applicable" | "error";
18
+ path: string;
19
+ cached?: string;
20
+ latest?: string;
21
+ error?: string;
22
+ }>;
23
+ /** Exposed for diagnostic reporting — harness-specific side data. */
24
+ getOpenCodeCacheDir(): string;
25
+ /** For doctor: directory size helpers for each storage subtree. */
26
+ describeStorageSubtrees(): Record<string, number>;
27
+ }
28
+ //# sourceMappingURL=opencode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode.d.ts","sourceRoot":"","sources":["../../src/adapters/opencode.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EAClB,MAAM,YAAY,CAAC;AA8BpB,qBAAa,eAAgB,YAAW,cAAc;IACpD,QAAQ,CAAC,IAAI,EAAG,UAAU,CAAU;IACpC,QAAQ,CAAC,WAAW,cAAc;IAClC,QAAQ,CAAC,iBAAiB,6BAAe;IACzC,QAAQ,CAAC,sBAAsB,oCAAgB;IAE/C,WAAW,IAAI,OAAO;IAStB,cAAc,IAAI,MAAM,GAAG,IAAI;IAQ/B,iBAAiB,IAAI,kBAAkB;IAgBvC,cAAc,IAAI,OAAO;IAOnB,iBAAiB,IAAI,OAAO,CAAC,iBAAiB,CAAC;IAgDrD,kBAAkB,IAAI,eAAe;IA0BrC,aAAa,IAAI,MAAM;IAKvB,UAAU,IAAI,MAAM;IAIpB,cAAc,IAAI,MAAM;IAIlB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;QAC9C,MAAM,EAAE,SAAS,GAAG,YAAY,GAAG,WAAW,GAAG,gBAAgB,GAAG,OAAO,CAAC;QAC5E,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IAgCF,qEAAqE;IACrE,mBAAmB,IAAI,MAAM;IAI7B,mEAAmE;IACnE,uBAAuB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;CAUlD"}
@@ -0,0 +1,25 @@
1
+ import type { HarnessAdapter, HarnessConfigPaths, PluginCacheInfo, PluginEntryResult } from "./types.js";
2
+ export declare class PiAdapter implements HarnessAdapter {
3
+ readonly kind: "pi";
4
+ readonly displayName = "Pi";
5
+ readonly pluginPackageName = "@cortexkit/aft-pi";
6
+ readonly pluginEntryWithVersion = "npm:@cortexkit/aft-pi";
7
+ isInstalled(): boolean;
8
+ getHostVersion(): string | null;
9
+ detectConfigPaths(): HarnessConfigPaths;
10
+ hasPluginEntry(): boolean;
11
+ ensurePluginEntry(): Promise<PluginEntryResult>;
12
+ getPluginCacheInfo(): PluginCacheInfo;
13
+ getStorageDir(): string;
14
+ getLogFile(): string;
15
+ getInstallHint(): string;
16
+ clearPluginCache(_force: boolean): Promise<{
17
+ action: "cleared" | "up_to_date" | "not_found" | "not_applicable" | "error";
18
+ path: string;
19
+ cached?: string;
20
+ latest?: string;
21
+ error?: string;
22
+ }>;
23
+ describeStorageSubtrees(): Record<string, number>;
24
+ }
25
+ //# sourceMappingURL=pi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi.d.ts","sourceRoot":"","sources":["../../src/adapters/pi.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAuDpB,qBAAa,SAAU,YAAW,cAAc;IAC9C,QAAQ,CAAC,IAAI,EAAG,IAAI,CAAU;IAC9B,QAAQ,CAAC,WAAW,QAAQ;IAC5B,QAAQ,CAAC,iBAAiB,uBAAe;IACzC,QAAQ,CAAC,sBAAsB,2BAAgB;IAE/C,WAAW,IAAI,OAAO;IAStB,cAAc,IAAI,MAAM,GAAG,IAAI;IAQ/B,iBAAiB,IAAI,kBAAkB;IAevC,cAAc,IAAI,OAAO;IAInB,iBAAiB,IAAI,OAAO,CAAC,iBAAiB,CAAC;IAmCrD,kBAAkB,IAAI,eAAe;IA6BrC,aAAa,IAAI,MAAM;IAKvB,UAAU,IAAI,MAAM;IAIpB,cAAc,IAAI,MAAM;IAIlB,gBAAgB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC;QAC/C,MAAM,EAAE,SAAS,GAAG,YAAY,GAAG,WAAW,GAAG,gBAAgB,GAAG,OAAO,CAAC;QAC5E,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IASF,uBAAuB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;CAUlD"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * HarnessAdapter — abstracts what the unified AFT CLI needs to know about a
3
+ * specific agent harness (OpenCode, Pi, and future entries).
4
+ *
5
+ * Each adapter covers:
6
+ * 1. *Detection* — is the harness installed? is AFT registered with it?
7
+ * 2. *Configuration* — where do its config files live, how are they read/written?
8
+ * 3. *Runtime state* — log file, storage dir, plugin cache dir
9
+ * 4. *Setup* — how a user installs/registers our plugin with it
10
+ *
11
+ * Everything here is synchronous or returns synchronously-resolvable
12
+ * structures; async work lives in the command layer.
13
+ */
14
+ export type HarnessKind = "opencode" | "pi";
15
+ export interface HarnessConfigPaths {
16
+ /** Primary config dir (e.g. `~/.config/opencode`, `~/.pi/agent`). */
17
+ configDir: string;
18
+ /** Harness's main config file (opencode.jsonc, pi's internal config if any). */
19
+ harnessConfig: string;
20
+ harnessConfigFormat: "json" | "jsonc" | "none";
21
+ /** AFT user-level config (`<configDir>/aft.jsonc` or equivalent). */
22
+ aftConfig: string;
23
+ aftConfigFormat: "json" | "jsonc" | "none";
24
+ /** Optional harness-specific UI/TUI config (OpenCode's `tui.jsonc`; undefined for Pi). */
25
+ tuiConfig?: string;
26
+ tuiConfigFormat?: "json" | "jsonc" | "none";
27
+ }
28
+ export interface PluginCacheInfo {
29
+ path: string;
30
+ cached?: string;
31
+ latest?: string;
32
+ exists: boolean;
33
+ }
34
+ export interface PluginEntryResult {
35
+ /** True if the plugin was added or was already present. */
36
+ ok: boolean;
37
+ /** Human-readable action description for the doctor/setup output. */
38
+ action: "already_present" | "added" | "updated" | "config_missing" | "error";
39
+ message: string;
40
+ configPath: string;
41
+ }
42
+ export interface HarnessAdapter {
43
+ readonly kind: HarnessKind;
44
+ readonly displayName: string;
45
+ readonly pluginPackageName: string;
46
+ readonly pluginEntryWithVersion: string;
47
+ /** Is the harness's host CLI (`opencode`, `pi`) on PATH? */
48
+ isInstalled(): boolean;
49
+ getHostVersion(): string | null;
50
+ detectConfigPaths(): HarnessConfigPaths;
51
+ /**
52
+ * Check whether our plugin is registered with the harness. For OpenCode this
53
+ * reads the `plugin` array in opencode.jsonc. For Pi it checks the extension
54
+ * index because Pi manages its own registration.
55
+ */
56
+ hasPluginEntry(): boolean;
57
+ /**
58
+ * Ensure the plugin is registered. May prompt, may run shell commands (Pi),
59
+ * may edit config files (OpenCode). Idempotent.
60
+ */
61
+ ensurePluginEntry(): Promise<PluginEntryResult>;
62
+ getPluginCacheInfo(): PluginCacheInfo;
63
+ getStorageDir(): string;
64
+ getLogFile(): string;
65
+ /** User-facing hint when the harness isn't installed. */
66
+ getInstallHint(): string;
67
+ /**
68
+ * Harness-aware version of `doctor --force` cache clearing. OpenCode nukes
69
+ * its bunx package cache; Pi may be a no-op because Pi caches are managed by
70
+ * `pi install` itself.
71
+ */
72
+ clearPluginCache(force: boolean): Promise<{
73
+ action: "cleared" | "up_to_date" | "not_found" | "not_applicable" | "error";
74
+ path: string;
75
+ cached?: string;
76
+ latest?: string;
77
+ error?: string;
78
+ }>;
79
+ }
80
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/adapters/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,IAAI,CAAC;AAE5C,MAAM,WAAW,kBAAkB;IACjC,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;IAC/C,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;IAC3C,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;CAC7C;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,2DAA2D;IAC3D,EAAE,EAAE,OAAO,CAAC;IACZ,qEAAqE;IACrE,MAAM,EAAE,iBAAiB,GAAG,OAAO,GAAG,SAAS,GAAG,gBAAgB,GAAG,OAAO,CAAC;IAC7E,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IAExC,4DAA4D;IAC5D,WAAW,IAAI,OAAO,CAAC;IACvB,cAAc,IAAI,MAAM,GAAG,IAAI,CAAC;IAEhC,iBAAiB,IAAI,kBAAkB,CAAC;IAExC;;;;OAIG;IACH,cAAc,IAAI,OAAO,CAAC;IAE1B;;;OAGG;IACH,iBAAiB,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAEhD,kBAAkB,IAAI,eAAe,CAAC;IACtC,aAAa,IAAI,MAAM,CAAC;IACxB,UAAU,IAAI,MAAM,CAAC;IAErB,yDAAyD;IACzD,cAAc,IAAI,MAAM,CAAC;IAEzB;;;;OAIG;IACH,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;QACxC,MAAM,EAAE,SAAS,GAAG,YAAY,GAAG,WAAW,GAAG,gBAAgB,GAAG,OAAO,CAAC;QAC5E,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;CACJ"}
@@ -0,0 +1,7 @@
1
+ export interface DoctorOptions {
2
+ force: boolean;
3
+ issue: boolean;
4
+ argv: string[];
5
+ }
6
+ export declare function runDoctor(options: DoctorOptions): Promise<number>;
7
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,wBAAsB,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAgFvE"}
@@ -0,0 +1,2 @@
1
+ export declare function runSetup(argv: string[]): Promise<number>;
2
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"AAIA,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA+C9D"}
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @cortexkit/aft — unified CLI for Agent File Tools.
4
+ *
5
+ * Entry point parses argv and dispatches to commands. Harness selection
6
+ * (OpenCode, Pi) is auto-detected from installed config paths; explicit
7
+ * `--harness <name>` overrides detection.
8
+ */
9
+ declare const command: string;
10
+ declare const args: string[];
11
+ declare function printHelp(): void;
12
+ declare function main(): Promise<number>;
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;GAMG;AAEH,QAAA,MAAM,OAAO,QAAkB,CAAC;AAChC,QAAA,MAAM,IAAI,UAAwB,CAAC;AAEnC,iBAAS,SAAS,IAAI,IAAI,CAqBzB;AAED,iBAAe,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAarC"}