@kingcrab/pi-imessage 0.0.43 → 1.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 (191) hide show
  1. package/README.md +93 -127
  2. package/dist/agent/behavior.js +79 -0
  3. package/dist/agent/chats.js +88 -0
  4. package/dist/agent/commands.js +191 -0
  5. package/dist/agent/compaction.js +51 -0
  6. package/dist/agent/deliver.js +139 -0
  7. package/dist/agent/direct-send.js +69 -0
  8. package/dist/agent/harness.js +79 -0
  9. package/dist/agent/health.js +33 -0
  10. package/dist/agent/models.js +69 -0
  11. package/dist/agent/progress-format.js +87 -0
  12. package/dist/agent/progress.js +173 -0
  13. package/dist/agent/prompt.js +79 -0
  14. package/dist/agent/replies.js +10 -0
  15. package/dist/agent/run.js +160 -0
  16. package/dist/agent/scheduling.js +291 -0
  17. package/dist/agent/time.js +18 -0
  18. package/dist/cli.js +88 -191
  19. package/dist/config/settings.js +60 -0
  20. package/dist/extensions/browser.js +326 -0
  21. package/dist/extensions/final-text.js +23 -0
  22. package/dist/extensions/memory.js +109 -0
  23. package/dist/extensions/message.js +33 -0
  24. package/dist/extensions/read-image.js +72 -0
  25. package/dist/extensions/restart.js +100 -0
  26. package/dist/extensions/schedules.js +42 -0
  27. package/dist/extensions/subagent.js +54 -0
  28. package/dist/extensions/web.js +100 -0
  29. package/dist/extensions/workspace.js +98 -0
  30. package/dist/main.js +578 -88
  31. package/dist/transport/attachments.js +37 -0
  32. package/dist/transport/http.js +110 -0
  33. package/dist/{rich-text.js → transport/rich-text.js} +25 -13
  34. package/dist/{send.js → transport/send.js} +13 -13
  35. package/dist/transport/watch.js +124 -0
  36. package/dist/web/app.js +826 -0
  37. package/dist/web/history.js +87 -0
  38. package/dist/web/memory.js +81 -0
  39. package/dist/web/page.js +29 -0
  40. package/dist/web/schedules.js +63 -0
  41. package/dist/web/server.js +382 -0
  42. package/dist/web/style.css +577 -0
  43. package/dist/web/tasks.js +97 -0
  44. package/docs/adr/0001-durable-owns-state.md +11 -0
  45. package/docs/adr/0002-module-layering.md +11 -0
  46. package/docs/adr/0003-replies-at-most-once.md +11 -0
  47. package/docs/adr/0004-native-extensions.md +11 -0
  48. package/docs/adr/0005-history-migration.md +11 -0
  49. package/docs/adr/0006-jsonl-storage.md +11 -0
  50. package/docs/adr/0007-images-by-path.md +11 -0
  51. package/docs/adr/0008-compaction-and-run.md +11 -0
  52. package/docs/adr/0009-one-shot-cutover.md +11 -0
  53. package/docs/adr/0010-test-budget.md +11 -0
  54. package/docs/adr/0011-reconcile-unsent-answers.md +24 -0
  55. package/docs/adr/0012-run-in-owned-conversation.md +22 -0
  56. package/docs/adr/0013-thin-adapters-around-durable.md +18 -0
  57. package/docs/adr/0014-ephemeral-private-storage.md +13 -0
  58. package/docs/adr/0015-ordinary-stop-keeps-native-inbox.md +21 -0
  59. package/docs/adr/0016-process-http-transport.md +21 -0
  60. package/docs/adr/0017-browser-cli-owned-scope.md +22 -0
  61. package/docs/adr/0018-tasks-without-prompt-api.md +19 -0
  62. package/docs/adr/0019-remove-scheduled-services.md +41 -0
  63. package/docs/adr/0020-chat-task-progress.md +41 -0
  64. package/docs/adr/0021-readable-progress-without-link-previews.md +33 -0
  65. package/docs/adr/0022-progress-admission-and-settlement.md +35 -0
  66. package/docs/adr/0023-retain-progress-type-prefixes.md +18 -0
  67. package/docs/adr/0024-status-marker-before-type-prefix.md +13 -0
  68. package/docs/adr/0025-reusable-progress-and-command-preview.md +49 -0
  69. package/docs/adr/0026-inline-command-only-requests.md +16 -0
  70. package/docs/adr/0027-command-preview-width.md +10 -0
  71. package/docs/adr/0028-command-preview-120.md +8 -0
  72. package/docs/adr/0030-shared-web-read-cache.md +33 -0
  73. package/docs/adr/0031-quiet-compaction-progress.md +32 -0
  74. package/docs/adr/0032-native-background-schedules.md +58 -0
  75. package/docs/adr/0033-operator-scheduled-run.md +23 -0
  76. package/docs/adr/0034-machine-local-schedule-time.md +36 -0
  77. package/docs/adr/0035-external-business-task-extensions.md +56 -0
  78. package/docs/adr/0036-workspace-policy-and-neutral-service-id.md +37 -0
  79. package/docs/adr/0037-restart-during-in-flight-work.md +30 -0
  80. package/docs/adr/0038-restart-any-time.md +25 -0
  81. package/docs/adr/0039-rerun-interrupted-tools.md +24 -0
  82. package/docs/adr/0040-chat-progress-notices.md +44 -0
  83. package/docs/adr/0041-restart-and-recovery.md +28 -0
  84. package/docs/adr/0042-background-schedules-and-workspace-extensions.md +44 -0
  85. package/docs/adr/0043-remove-legacy-migration.md +23 -0
  86. package/docs/adr/0044-message-channels.md +32 -0
  87. package/docs/adr/0045-chat-scheduling-tools.md +51 -0
  88. package/docs/adr/0046-selective-command-redaction.md +31 -0
  89. package/docs/adr/0047-one-scheduling-path.md +158 -0
  90. package/docs/adr/0048-quiet-attachment-reads.md +11 -0
  91. package/docs/adr/0049-per-chat-progress-notices.md +21 -0
  92. package/docs/adr/0052-host-owned-self-restart.md +53 -0
  93. package/docs/adr/README.md +54 -0
  94. package/docs/api.md +104 -0
  95. package/docs/architecture.md +164 -0
  96. package/docs/browser.md +93 -0
  97. package/docs/memory.md +27 -0
  98. package/docs/screenshot.png +0 -0
  99. package/docs/workspace-extensions.md +133 -0
  100. package/examples/workspace-extensions/system-context/index.ts +69 -0
  101. package/examples/workspace-extensions/system-context/package.json +3 -0
  102. package/ops/README.md +250 -0
  103. package/ops/preflight.mjs +28 -0
  104. package/package.json +36 -37
  105. package/dist/agent.d.ts +0 -84
  106. package/dist/agent.d.ts.map +0 -1
  107. package/dist/agent.js +0 -780
  108. package/dist/agent.js.map +0 -1
  109. package/dist/cli.d.ts +0 -15
  110. package/dist/cli.d.ts.map +0 -1
  111. package/dist/cli.js.map +0 -1
  112. package/dist/imessage.d.ts +0 -33
  113. package/dist/imessage.d.ts.map +0 -1
  114. package/dist/imessage.js +0 -76
  115. package/dist/imessage.js.map +0 -1
  116. package/dist/logger.d.ts +0 -33
  117. package/dist/logger.d.ts.map +0 -1
  118. package/dist/logger.js +0 -104
  119. package/dist/logger.js.map +0 -1
  120. package/dist/main.d.ts +0 -5
  121. package/dist/main.d.ts.map +0 -1
  122. package/dist/main.js.map +0 -1
  123. package/dist/memory.d.ts +0 -53
  124. package/dist/memory.d.ts.map +0 -1
  125. package/dist/memory.js +0 -196
  126. package/dist/memory.js.map +0 -1
  127. package/dist/model-health.d.ts +0 -11
  128. package/dist/model-health.d.ts.map +0 -1
  129. package/dist/model-health.js +0 -69
  130. package/dist/model-health.js.map +0 -1
  131. package/dist/pipeline.d.ts +0 -27
  132. package/dist/pipeline.d.ts.map +0 -1
  133. package/dist/pipeline.js +0 -59
  134. package/dist/pipeline.js.map +0 -1
  135. package/dist/queue.d.ts +0 -23
  136. package/dist/queue.d.ts.map +0 -1
  137. package/dist/queue.js +0 -89
  138. package/dist/queue.js.map +0 -1
  139. package/dist/reminders.d.ts +0 -42
  140. package/dist/reminders.d.ts.map +0 -1
  141. package/dist/reminders.js +0 -207
  142. package/dist/reminders.js.map +0 -1
  143. package/dist/rich-text.d.ts +0 -26
  144. package/dist/rich-text.d.ts.map +0 -1
  145. package/dist/rich-text.js.map +0 -1
  146. package/dist/self-echo.d.ts +0 -19
  147. package/dist/self-echo.d.ts.map +0 -1
  148. package/dist/self-echo.js +0 -54
  149. package/dist/self-echo.js.map +0 -1
  150. package/dist/send.d.ts +0 -24
  151. package/dist/send.d.ts.map +0 -1
  152. package/dist/send.js.map +0 -1
  153. package/dist/settings.d.ts +0 -44
  154. package/dist/settings.d.ts.map +0 -1
  155. package/dist/settings.js +0 -80
  156. package/dist/settings.js.map +0 -1
  157. package/dist/store.d.ts +0 -57
  158. package/dist/store.d.ts.map +0 -1
  159. package/dist/store.js +0 -124
  160. package/dist/store.js.map +0 -1
  161. package/dist/tasks.d.ts +0 -95
  162. package/dist/tasks.d.ts.map +0 -1
  163. package/dist/tasks.js +0 -384
  164. package/dist/tasks.js.map +0 -1
  165. package/dist/types.d.ts +0 -93
  166. package/dist/types.d.ts.map +0 -1
  167. package/dist/types.js +0 -38
  168. package/dist/types.js.map +0 -1
  169. package/dist/watch.d.ts +0 -21
  170. package/dist/watch.d.ts.map +0 -1
  171. package/dist/watch.js +0 -219
  172. package/dist/watch.js.map +0 -1
  173. package/dist/web/data.d.ts +0 -11
  174. package/dist/web/data.d.ts.map +0 -1
  175. package/dist/web/data.js +0 -56
  176. package/dist/web/data.js.map +0 -1
  177. package/dist/web/html.d.ts +0 -5
  178. package/dist/web/html.d.ts.map +0 -1
  179. package/dist/web/html.js +0 -16
  180. package/dist/web/html.js.map +0 -1
  181. package/dist/web/index.d.ts +0 -25
  182. package/dist/web/index.d.ts.map +0 -1
  183. package/dist/web/index.js +0 -335
  184. package/dist/web/index.js.map +0 -1
  185. package/dist/web/render.d.ts +0 -11
  186. package/dist/web/render.d.ts.map +0 -1
  187. package/dist/web/render.js +0 -56
  188. package/dist/web/render.js.map +0 -1
  189. package/dist/web/templates/logs.eta +0 -75
  190. package/dist/web/templates/memory.eta +0 -91
  191. package/dist/web/templates/page.eta +0 -98
package/package.json CHANGED
@@ -1,55 +1,54 @@
1
1
  {
2
2
  "name": "@kingcrab/pi-imessage",
3
- "version": "0.0.43",
4
- "description": "AI-powered iMessage bot using pi coding agent — understands images, quoted replies, and conversation context",
5
- "type": "module",
3
+ "version": "1.1.0",
4
+ "description": "A minimal, self-managing iMessage bot powered by Pi Durable",
6
5
  "license": "MIT",
7
- "author": "Henry Zhu",
8
- "homepage": "https://github.com/daya0576/pi-imessage#readme",
9
- "bugs": "https://github.com/daya0576/pi-imessage/issues",
10
- "keywords": ["imessage", "ai", "chatbot", "pi", "macos"],
11
- "bin": {
12
- "pi-imessage": "./dist/cli.js"
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/daya0576/pi-imessage.git"
13
9
  },
14
- "files": ["dist", "!dist/__tests__", "README.md", "LICENSE"],
10
+ "files": [
11
+ "dist",
12
+ "docs",
13
+ "examples",
14
+ "ops/README.md",
15
+ "ops/preflight.mjs"
16
+ ],
15
17
  "publishConfig": {
16
18
  "access": "public",
17
19
  "provenance": true
18
20
  },
19
- "repository": {
20
- "type": "git",
21
- "url": "git+https://github.com/daya0576/pi-imessage.git"
21
+ "type": "module",
22
+ "bin": {
23
+ "pi-imessage": "dist/cli.js"
22
24
  },
23
25
  "engines": {
24
- "node": ">=20.0.0"
26
+ "node": ">=22.22.2"
25
27
  },
26
28
  "scripts": {
27
- "build": "tsc && mkdir -p dist/web/templates && cp src/web/templates/* dist/web/templates/",
28
- "prepublishOnly": "npm run build",
29
- "dev": "NODE_OPTIONS='--use-env-proxy' tsx watch src/main.ts",
30
- "start": "NODE_OPTIONS='--use-env-proxy' tsx src/main.ts",
31
- "test": "vitest run",
32
- "typecheck": "tsc --noEmit",
33
- "lint": "biome check .",
34
- "format": "biome format --write .",
35
- "check": "tsc --noEmit && biome check ."
29
+ "build": "tsc -p tsconfig.build.json && cp src/web/app.js src/web/style.css dist/web/",
30
+ "prepack": "npm run build",
31
+ "test:package": "npm run build && node ops/package-smoke.mjs",
32
+ "start": "node --use-env-proxy --experimental-strip-types src/cli.ts serve",
33
+ "check": "tsc --noEmit && biome check .",
34
+ "test": "vitest run"
36
35
  },
37
36
  "dependencies": {
38
- "@earendil-works/pi-agent-core": "0.84.1",
39
- "@earendil-works/pi-ai": "0.84.1",
40
- "@earendil-works/pi-coding-agent": "0.84.1",
41
- "better-sqlite3": "^12.6.2",
42
- "dotenv": "^17.3.1",
43
- "eta": "^4.5.1"
37
+ "@earendil-works/chord": "1.4.0",
38
+ "@earendil-works/pi-ai": "1.4.0",
39
+ "@earendil-works/pi-coding-agent": "1.4.0",
40
+ "@earendil-works/pi-durable": "1.4.0",
41
+ "better-sqlite3": "13.0.3",
42
+ "defuddle": "0.19.4",
43
+ "sharp": "0.35.5",
44
+ "undici": "8.10.2",
45
+ "unpdf": "1.8.1"
44
46
  },
45
47
  "devDependencies": {
46
- "@biomejs/biome": "^1.9.4",
47
- "@types/better-sqlite3": "^7.6.13",
48
- "@types/node": "^22.0.0",
49
- "@types/sharp": "^0.31.1",
50
- "@vitest/coverage-v8": "^3.2.4",
51
- "tsx": "^4.0.0",
52
- "typescript": "^5.7.3",
53
- "vitest": "^3.0.0"
48
+ "@biomejs/biome": "2.5.15",
49
+ "@types/better-sqlite3": "7.6.13",
50
+ "@types/node": "22.20.5",
51
+ "typescript": "7.0.2",
52
+ "vitest": "5.0.3"
54
53
  }
55
54
  }
package/dist/agent.d.ts DELETED
@@ -1,84 +0,0 @@
1
- /**
2
- * Agent module — text-in / text-out AI processor per iMessage chat.
3
- *
4
- * Each chat gets a lazily-created AgentSession with persistent context
5
- * (context.jsonl per chat directory).
6
- *
7
- * Concurrency: callers must serialize messages for the same chat externally
8
- * (imessage.ts does this via per-chat promise chains). Different chats run
9
- * concurrently.
10
- *
11
- * Model: uses ~/.pi/agent/ defaults (via createAgentSession).
12
- */
13
- import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
14
- import { type AgentSession } from "@earendil-works/pi-coding-agent";
15
- import type { AgentReply, IncomingMessage } from "./types.js";
16
- /**
17
- * Abort a prompt only after this much continuous inactivity. Any agent event —
18
- * including streamed model output and tool start/end events — refreshes it.
19
- */
20
- export declare const AGENT_IDLE_TIMEOUT_MS: number;
21
- /** Absolute safety ceiling that activity cannot extend. */
22
- export declare const AGENT_MAX_PROMPT_DURATION_MS: number;
23
- export declare const AGENT_COMPACT_TIMEOUT_MS: number;
24
- export declare const AUTO_COMPACT_CONTEXT_RATIO: number;
25
- export declare const AUTO_COMPACT_FALLBACK_TOKENS = 100000;
26
- /**
27
- * Compact relative to the selected model's context window instead of using a
28
- * fixed low threshold. AGENT_AUTO_COMPACT_TOKENS remains an explicit override.
29
- */
30
- export declare function getAutoCompactTokenThreshold(contextWindow?: number, explicitTokens?: string): number;
31
- /** Enable OpenAI priority processing without enabling user-discovered extensions. */
32
- export declare function openAiCodexFastExtension(pi: ExtensionAPI): void;
33
- export interface AgentManagerConfig {
34
- workingDir: string;
35
- }
36
- /**
37
- * Stop model work without injecting a synthetic user message into the transcript.
38
- *
39
- * AgentSession.steer("stop") is not an abort API: it queues a literal user
40
- * message. If the current operation fails before consuming that queue (for
41
- * example, compaction fails), the stale "stop" can be delivered with a later
42
- * real chat message and misattributed to that sender.
43
- */
44
- export declare function clearAndAbortSession(session: Pick<AgentSession, "abort" | "clearQueue">): Promise<void>;
45
- /**
46
- * Race an async operation against a wall-clock timeout.
47
- *
48
- * If `operation()` settles first, its result (or rejection) is passed through
49
- * and the timer is cleared. If the timeout fires first, `onTimeout()` is invoked
50
- * (best-effort — e.g. to abort the underlying request) and the returned promise
51
- * rejects with a timeout Error. A failure inside `onTimeout()` never masks the
52
- * timeout rejection.
53
- *
54
- * Note: this does not cancel `operation()` itself — cancellation must happen via
55
- * `onTimeout` (the SDK exposes `AgentSession.abort()`). The timeout rejects
56
- * immediately without waiting for cancellation, because a stuck abort must not
57
- * keep the caller blocked.
58
- */
59
- export declare function runWithTimeout<T>(operation: () => Promise<T>, onTimeout: () => Promise<void> | void, timeoutMs: number): Promise<T>;
60
- export type ActivityTimeoutKind = "idle" | "max_duration";
61
- /**
62
- * Race an operation against a sliding inactivity timeout and a separate hard
63
- * duration ceiling. Calling `markActivity()` refreshes only the idle timer.
64
- */
65
- export declare function runWithActivityTimeout<T>(operation: (markActivity: () => void) => Promise<T>, onTimeout: (kind: ActivityTimeoutKind) => Promise<void> | void, idleTimeoutMs: number, maxDurationMs: number): Promise<T>;
66
- export declare function createAgentManager(config: AgentManagerConfig): Promise<{
67
- processMessage: (msg: IncomingMessage, handler: (reply: AgentReply) => Promise<void>, options?: {
68
- streamingBehavior?: "steer" | "followUp";
69
- }) => Promise<void>;
70
- newSession: (chatGuid: string) => Promise<void>;
71
- getSessionStatus: (chatGuid: string) => Promise<string>;
72
- getRuntimeStatus: () => {
73
- activePrompts: number;
74
- sessions: number;
75
- lastAgentActivityAt: string | null;
76
- };
77
- reload: (chatGuid: string) => Promise<void>;
78
- stop: (chatGuid: string) => Promise<void>;
79
- compact: (chatGuid: string, customInstructions?: string) => Promise<string>;
80
- }>;
81
- type CreatedAgentManager = Awaited<ReturnType<typeof createAgentManager>>;
82
- export type AgentManager = Pick<CreatedAgentManager, "processMessage" | "newSession" | "getSessionStatus" | "reload" | "stop" | "compact"> & Partial<Pick<CreatedAgentManager, "getRuntimeStatus">>;
83
- export {};
84
- //# sourceMappingURL=agent.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAoB,YAAY,EAAE,MAAM,iCAAiC,CAAC;AACtF,OAAO,EACN,KAAK,YAAY,EAQjB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAI9D;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAAqE,CAAC;AAExG,2DAA2D;AAC3D,eAAO,MAAM,4BAA4B,QAA6E,CAAC;AACvH,eAAO,MAAM,wBAAwB,QAAuE,CAAC;AAC7G,eAAO,MAAM,0BAA0B,QAAmE,CAAC;AAC3G,eAAO,MAAM,4BAA4B,SAAU,CAAC;AAEpD;;;GAGG;AACH,wBAAgB,4BAA4B,CAC3C,aAAa,CAAC,EAAE,MAAM,EACtB,cAAc,SAA8C,GAC1D,MAAM,CAWR;AAID,qFAAqF;AACrF,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAU/D;AAED,MAAM,WAAW,kBAAkB;IAClC,UAAU,EAAE,MAAM,CAAC;CACnB;AASD;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,OAAO,GAAG,YAAY,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAG7G;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAsB,cAAc,CAAC,CAAC,EACrC,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,EACrC,SAAS,EAAE,MAAM,GACf,OAAO,CAAC,CAAC,CAAC,CAiBZ;AAED,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,cAAc,CAAC;AAE1D;;;GAGG;AACH,wBAAsB,sBAAsB,CAAC,CAAC,EAC7C,SAAS,EAAE,CAAC,YAAY,EAAE,MAAM,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EACnD,SAAS,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,EAC9D,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,GACnB,OAAO,CAAC,CAAC,CAAC,CA6CZ;AAuTD,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB;0BAuE5D,eAAe,WACX,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,YACnC;QAAE,iBAAiB,CAAC,EAAE,OAAO,GAAG,UAAU,CAAA;KAAE,KACpD,OAAO,CAAC,IAAI,CAAC;2BA+LoB,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;iCAkBhB,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;;;;;;uBAuClC,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;qBAzFxB,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;wBAWnB,MAAM,uBAAuB,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;GAkHtF;AAWD,KAAK,mBAAmB,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC,CAAC;AAC1E,MAAM,MAAM,YAAY,GAAG,IAAI,CAC9B,mBAAmB,EACnB,gBAAgB,GAAG,YAAY,GAAG,kBAAkB,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CACpF,GACA,OAAO,CAAC,IAAI,CAAC,mBAAmB,EAAE,kBAAkB,CAAC,CAAC,CAAC"}