@superblocksteam/vite-plugin-file-sync 2.0.59-next.1 → 2.0.59-next.3

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 (279) hide show
  1. package/dist/ai-service/agent/prompts/build-base-system-prompt.d.ts.map +1 -1
  2. package/dist/ai-service/agent/prompts/build-base-system-prompt.js +10 -1
  3. package/dist/ai-service/agent/prompts/build-base-system-prompt.js.map +1 -1
  4. package/dist/ai-service/agent/subagents/apis/examples.d.ts.map +1 -1
  5. package/dist/ai-service/agent/subagents/apis/examples.js +137 -10
  6. package/dist/ai-service/agent/subagents/apis/examples.js.map +1 -1
  7. package/dist/ai-service/agent/subagents/apis/static-analysis.d.ts.map +1 -1
  8. package/dist/ai-service/agent/subagents/apis/static-analysis.js +14 -7
  9. package/dist/ai-service/agent/subagents/apis/static-analysis.js.map +1 -1
  10. package/dist/ai-service/agent/tool-message-utils.d.ts.map +1 -1
  11. package/dist/ai-service/agent/tool-message-utils.js +6 -2
  12. package/dist/ai-service/agent/tool-message-utils.js.map +1 -1
  13. package/dist/ai-service/agent/tools/apis/analysis.d.ts +9 -0
  14. package/dist/ai-service/agent/tools/apis/analysis.d.ts.map +1 -0
  15. package/dist/ai-service/agent/tools/apis/analysis.js +357 -0
  16. package/dist/ai-service/agent/tools/apis/analysis.js.map +1 -0
  17. package/dist/ai-service/agent/{subagents → tools}/apis/api-executor.d.ts +35 -10
  18. package/dist/ai-service/agent/tools/apis/api-executor.d.ts.map +1 -0
  19. package/dist/ai-service/agent/{subagents → tools}/apis/api-executor.js +179 -94
  20. package/dist/ai-service/agent/tools/apis/api-executor.js.map +1 -0
  21. package/dist/ai-service/agent/tools/apis/api-source.d.ts +19 -0
  22. package/dist/ai-service/agent/tools/apis/api-source.d.ts.map +1 -0
  23. package/dist/ai-service/agent/tools/apis/api-source.js +73 -0
  24. package/dist/ai-service/agent/tools/apis/api-source.js.map +1 -0
  25. package/dist/ai-service/agent/tools/apis/api-validation-orchestrator.d.ts +51 -0
  26. package/dist/ai-service/agent/tools/apis/api-validation-orchestrator.d.ts.map +1 -0
  27. package/dist/ai-service/agent/tools/apis/api-validation-orchestrator.js +510 -0
  28. package/dist/ai-service/agent/tools/apis/api-validation-orchestrator.js.map +1 -0
  29. package/dist/ai-service/agent/tools/apis/build-api-artifact.d.ts +32 -0
  30. package/dist/ai-service/agent/tools/apis/build-api-artifact.d.ts.map +1 -0
  31. package/dist/ai-service/agent/tools/apis/build-api-artifact.js +313 -0
  32. package/dist/ai-service/agent/tools/apis/build-api-artifact.js.map +1 -0
  33. package/dist/ai-service/agent/tools/apis/build-api.d.ts +1 -10
  34. package/dist/ai-service/agent/tools/apis/build-api.d.ts.map +1 -1
  35. package/dist/ai-service/agent/tools/apis/build-api.js +26 -238
  36. package/dist/ai-service/agent/tools/apis/build-api.js.map +1 -1
  37. package/dist/ai-service/agent/tools/apis/get-api-docs.d.ts +11 -0
  38. package/dist/ai-service/agent/tools/apis/get-api-docs.d.ts.map +1 -0
  39. package/dist/ai-service/agent/tools/apis/get-api-docs.js +1809 -0
  40. package/dist/ai-service/agent/tools/apis/get-api-docs.js.map +1 -0
  41. package/dist/ai-service/agent/tools/apis/integration-types.d.ts +37 -0
  42. package/dist/ai-service/agent/tools/apis/integration-types.d.ts.map +1 -0
  43. package/dist/ai-service/agent/tools/apis/integration-types.js +697 -0
  44. package/dist/ai-service/agent/tools/apis/integration-types.js.map +1 -0
  45. package/dist/ai-service/agent/tools/apis/test-api.d.ts +25 -0
  46. package/dist/ai-service/agent/tools/apis/test-api.d.ts.map +1 -0
  47. package/dist/ai-service/agent/tools/apis/test-api.js +194 -0
  48. package/dist/ai-service/agent/tools/apis/test-api.js.map +1 -0
  49. package/dist/ai-service/agent/tools/apis/write-api.d.ts +11 -0
  50. package/dist/ai-service/agent/tools/apis/write-api.d.ts.map +1 -0
  51. package/dist/ai-service/agent/tools/apis/write-api.js +41 -0
  52. package/dist/ai-service/agent/tools/apis/write-api.js.map +1 -0
  53. package/dist/ai-service/agent/tools/build-read-files.js +2 -2
  54. package/dist/ai-service/agent/tools/build-read-files.js.map +1 -1
  55. package/dist/ai-service/agent/tools.d.ts +2 -5
  56. package/dist/ai-service/agent/tools.d.ts.map +1 -1
  57. package/dist/ai-service/agent/tools.js +51 -22
  58. package/dist/ai-service/agent/tools.js.map +1 -1
  59. package/dist/ai-service/agent/tools2/access-control.d.ts +1 -0
  60. package/dist/ai-service/agent/tools2/access-control.d.ts.map +1 -1
  61. package/dist/ai-service/agent/tools2/access-control.js +15 -13
  62. package/dist/ai-service/agent/tools2/access-control.js.map +1 -1
  63. package/dist/ai-service/agent/tools2/registry.d.ts +2 -1
  64. package/dist/ai-service/agent/tools2/registry.d.ts.map +1 -1
  65. package/dist/ai-service/agent/tools2/registry.js +4 -3
  66. package/dist/ai-service/agent/tools2/registry.js.map +1 -1
  67. package/dist/ai-service/agent/tools2/tools/exit-plan-mode.d.ts +2 -1
  68. package/dist/ai-service/agent/tools2/tools/exit-plan-mode.d.ts.map +1 -1
  69. package/dist/ai-service/agent/tools2/tools/exit-plan-mode.js +103 -88
  70. package/dist/ai-service/agent/tools2/tools/exit-plan-mode.js.map +1 -1
  71. package/dist/ai-service/agent/tools2/tools/grep-metadata.d.ts.map +1 -1
  72. package/dist/ai-service/agent/tools2/tools/grep-metadata.js +25 -4
  73. package/dist/ai-service/agent/tools2/tools/grep-metadata.js.map +1 -1
  74. package/dist/ai-service/agent/tools2/types.d.ts +1 -1
  75. package/dist/ai-service/agent/tools2/types.d.ts.map +1 -1
  76. package/dist/ai-service/agent/tools2/types.js.map +1 -1
  77. package/dist/ai-service/agent/tools2/utils.d.ts.map +1 -1
  78. package/dist/ai-service/agent/tools2/utils.js +4 -1
  79. package/dist/ai-service/agent/tools2/utils.js.map +1 -1
  80. package/dist/ai-service/agent/utils.d.ts +1 -3
  81. package/dist/ai-service/agent/utils.d.ts.map +1 -1
  82. package/dist/ai-service/agent/utils.js +44 -4
  83. package/dist/ai-service/agent/utils.js.map +1 -1
  84. package/dist/ai-service/app-interface/shell.d.ts +5 -0
  85. package/dist/ai-service/app-interface/shell.d.ts.map +1 -1
  86. package/dist/ai-service/app-interface/shell.js +17 -2
  87. package/dist/ai-service/app-interface/shell.js.map +1 -1
  88. package/dist/ai-service/chat/chat-session-store.d.ts +7 -0
  89. package/dist/ai-service/chat/chat-session-store.d.ts.map +1 -1
  90. package/dist/ai-service/chat/chat-session-store.js +26 -0
  91. package/dist/ai-service/chat/chat-session-store.js.map +1 -1
  92. package/dist/ai-service/const.d.ts +2 -1
  93. package/dist/ai-service/const.d.ts.map +1 -1
  94. package/dist/ai-service/const.js +1 -0
  95. package/dist/ai-service/const.js.map +1 -1
  96. package/dist/ai-service/index.d.ts +5 -1
  97. package/dist/ai-service/index.d.ts.map +1 -1
  98. package/dist/ai-service/index.js +55 -7
  99. package/dist/ai-service/index.js.map +1 -1
  100. package/dist/ai-service/integrations/metadata-storage/index.d.ts +10 -0
  101. package/dist/ai-service/integrations/metadata-storage/index.d.ts.map +1 -1
  102. package/dist/ai-service/integrations/metadata-storage/local.d.ts +4 -2
  103. package/dist/ai-service/integrations/metadata-storage/local.d.ts.map +1 -1
  104. package/dist/ai-service/integrations/metadata-storage/local.js +35 -9
  105. package/dist/ai-service/integrations/metadata-storage/local.js.map +1 -1
  106. package/dist/ai-service/integrations/store.d.ts +27 -2
  107. package/dist/ai-service/integrations/store.d.ts.map +1 -1
  108. package/dist/ai-service/integrations/store.js +129 -62
  109. package/dist/ai-service/integrations/store.js.map +1 -1
  110. package/dist/ai-service/llm/client.d.ts +123 -0
  111. package/dist/ai-service/llm/client.d.ts.map +1 -0
  112. package/dist/ai-service/llm/client.js +168 -0
  113. package/dist/ai-service/llm/client.js.map +1 -0
  114. package/dist/ai-service/llm/context/context-handle.d.ts +4 -4
  115. package/dist/ai-service/llm/context/context-handle.d.ts.map +1 -1
  116. package/dist/ai-service/llm/context/context-handle.js +7 -3
  117. package/dist/ai-service/llm/context/context-handle.js.map +1 -1
  118. package/dist/ai-service/llm/context/context.d.ts +28 -0
  119. package/dist/ai-service/llm/context/context.d.ts.map +1 -1
  120. package/dist/ai-service/llm/context/context.js +117 -0
  121. package/dist/ai-service/llm/context/context.js.map +1 -1
  122. package/dist/ai-service/llm/context/manager.d.ts +22 -2
  123. package/dist/ai-service/llm/context/manager.d.ts.map +1 -1
  124. package/dist/ai-service/llm/context/manager.js +86 -13
  125. package/dist/ai-service/llm/context/manager.js.map +1 -1
  126. package/dist/ai-service/llm/context/storage/index.d.ts +1 -0
  127. package/dist/ai-service/llm/context/storage/index.d.ts.map +1 -1
  128. package/dist/ai-service/llm/context/storage/local.d.ts +1 -0
  129. package/dist/ai-service/llm/context/storage/local.d.ts.map +1 -1
  130. package/dist/ai-service/llm/context/storage/local.js +13 -1
  131. package/dist/ai-service/llm/context/storage/local.js.map +1 -1
  132. package/dist/ai-service/llm/error.d.ts +14 -4
  133. package/dist/ai-service/llm/error.d.ts.map +1 -1
  134. package/dist/ai-service/llm/error.js +49 -4
  135. package/dist/ai-service/llm/error.js.map +1 -1
  136. package/dist/ai-service/llm/interaction/adapters/vercel.d.ts +67 -0
  137. package/dist/ai-service/llm/interaction/adapters/vercel.d.ts.map +1 -0
  138. package/dist/ai-service/llm/interaction/adapters/vercel.js +110 -0
  139. package/dist/ai-service/llm/interaction/adapters/vercel.js.map +1 -0
  140. package/dist/ai-service/llm/interaction/compose.d.ts +71 -0
  141. package/dist/ai-service/llm/interaction/compose.d.ts.map +1 -0
  142. package/dist/ai-service/llm/interaction/compose.js +88 -0
  143. package/dist/ai-service/llm/interaction/compose.js.map +1 -0
  144. package/dist/ai-service/llm/interaction/index.d.ts +68 -0
  145. package/dist/ai-service/llm/interaction/index.d.ts.map +1 -0
  146. package/dist/ai-service/llm/interaction/index.js +70 -0
  147. package/dist/ai-service/llm/interaction/index.js.map +1 -0
  148. package/dist/ai-service/llm/interaction/middleware.d.ts +52 -0
  149. package/dist/ai-service/llm/interaction/middleware.d.ts.map +1 -0
  150. package/dist/ai-service/llm/interaction/middleware.js +17 -0
  151. package/dist/ai-service/llm/interaction/middleware.js.map +1 -0
  152. package/dist/ai-service/llm/interaction/middlewares/llmobs.d.ts +45 -0
  153. package/dist/ai-service/llm/interaction/middlewares/llmobs.d.ts.map +1 -0
  154. package/dist/ai-service/llm/interaction/middlewares/llmobs.js +85 -0
  155. package/dist/ai-service/llm/interaction/middlewares/llmobs.js.map +1 -0
  156. package/dist/ai-service/llm/interaction/middlewares/logging.d.ts +88 -0
  157. package/dist/ai-service/llm/interaction/middlewares/logging.d.ts.map +1 -0
  158. package/dist/ai-service/llm/interaction/middlewares/logging.js +238 -0
  159. package/dist/ai-service/llm/interaction/middlewares/logging.js.map +1 -0
  160. package/dist/ai-service/llm/interaction/middlewares/profiler.d.ts +47 -0
  161. package/dist/ai-service/llm/interaction/middlewares/profiler.d.ts.map +1 -0
  162. package/dist/ai-service/llm/interaction/middlewares/profiler.js +183 -0
  163. package/dist/ai-service/llm/interaction/middlewares/profiler.js.map +1 -0
  164. package/dist/ai-service/llm/interaction/middlewares/stream-retry.d.ts +121 -0
  165. package/dist/ai-service/llm/interaction/middlewares/stream-retry.d.ts.map +1 -0
  166. package/dist/ai-service/llm/interaction/middlewares/stream-retry.js +291 -0
  167. package/dist/ai-service/llm/interaction/middlewares/stream-retry.js.map +1 -0
  168. package/dist/ai-service/llm/interaction/provider.d.ts +158 -0
  169. package/dist/ai-service/llm/interaction/provider.d.ts.map +1 -0
  170. package/dist/ai-service/llm/interaction/provider.js +15 -0
  171. package/dist/ai-service/llm/interaction/provider.js.map +1 -0
  172. package/dist/ai-service/llm/interaction/stream-lifecycle.d.ts +48 -0
  173. package/dist/ai-service/llm/interaction/stream-lifecycle.d.ts.map +1 -0
  174. package/dist/ai-service/llm/interaction/stream-lifecycle.js +131 -0
  175. package/dist/ai-service/llm/interaction/stream-lifecycle.js.map +1 -0
  176. package/dist/ai-service/llm/provider.d.ts +1 -2
  177. package/dist/ai-service/llm/provider.d.ts.map +1 -1
  178. package/dist/ai-service/llm/provider.js +3 -6
  179. package/dist/ai-service/llm/provider.js.map +1 -1
  180. package/dist/ai-service/llmobs/helpers.d.ts +7 -8
  181. package/dist/ai-service/llmobs/helpers.d.ts.map +1 -1
  182. package/dist/ai-service/llmobs/helpers.js +8 -48
  183. package/dist/ai-service/llmobs/helpers.js.map +1 -1
  184. package/dist/ai-service/llmobs/middleware/stream-text.d.ts +19 -21
  185. package/dist/ai-service/llmobs/middleware/stream-text.d.ts.map +1 -1
  186. package/dist/ai-service/llmobs/middleware/stream-text.js +98 -106
  187. package/dist/ai-service/llmobs/middleware/stream-text.js.map +1 -1
  188. package/dist/ai-service/llmobs/types.d.ts +14 -1
  189. package/dist/ai-service/llmobs/types.d.ts.map +1 -1
  190. package/dist/ai-service/state-machine/clark-fsm.d.ts +75 -5
  191. package/dist/ai-service/state-machine/clark-fsm.d.ts.map +1 -1
  192. package/dist/ai-service/state-machine/clark-fsm.js +100 -0
  193. package/dist/ai-service/state-machine/clark-fsm.js.map +1 -1
  194. package/dist/ai-service/state-machine/handlers/agent-planning.d.ts.map +1 -1
  195. package/dist/ai-service/state-machine/handlers/agent-planning.js +4 -0
  196. package/dist/ai-service/state-machine/handlers/agent-planning.js.map +1 -1
  197. package/dist/ai-service/state-machine/handlers/llm-generating.d.ts.map +1 -1
  198. package/dist/ai-service/state-machine/handlers/llm-generating.js +91 -456
  199. package/dist/ai-service/state-machine/handlers/llm-generating.js.map +1 -1
  200. package/dist/ai-service/state-machine/handlers/runtime-reviewing.js +1 -1
  201. package/dist/ai-service/state-machine/handlers/runtime-reviewing.js.map +1 -1
  202. package/dist/ai-service/state-machine/helpers/peer.d.ts.map +1 -1
  203. package/dist/ai-service/state-machine/helpers/peer.js +15 -0
  204. package/dist/ai-service/state-machine/helpers/peer.js.map +1 -1
  205. package/dist/ai-service/state-machine/mocks.d.ts.map +1 -1
  206. package/dist/ai-service/state-machine/mocks.js +1 -0
  207. package/dist/ai-service/state-machine/mocks.js.map +1 -1
  208. package/dist/ai-service/template-renderer.js +1 -1
  209. package/dist/ai-service/template-renderer.js.map +1 -1
  210. package/dist/ai-service/types.d.ts +30 -0
  211. package/dist/ai-service/types.d.ts.map +1 -1
  212. package/dist/binding-extraction/extract-identifiers.d.ts +14 -0
  213. package/dist/binding-extraction/extract-identifiers.d.ts.map +1 -1
  214. package/dist/binding-extraction/extract-identifiers.js +46 -1
  215. package/dist/binding-extraction/extract-identifiers.js.map +1 -1
  216. package/dist/binding-extraction/js-identifiers.d.ts +14 -0
  217. package/dist/binding-extraction/js-identifiers.d.ts.map +1 -1
  218. package/dist/binding-extraction/js-identifiers.js +168 -0
  219. package/dist/binding-extraction/js-identifiers.js.map +1 -1
  220. package/dist/binding-extraction/python-identifiers.d.ts +5 -0
  221. package/dist/binding-extraction/python-identifiers.d.ts.map +1 -1
  222. package/dist/binding-extraction/python-identifiers.js +76 -7
  223. package/dist/binding-extraction/python-identifiers.js.map +1 -1
  224. package/dist/file-sync-vite-plugin.d.ts.map +1 -1
  225. package/dist/file-sync-vite-plugin.js +73 -3
  226. package/dist/file-sync-vite-plugin.js.map +1 -1
  227. package/dist/file-system-manager.d.ts.map +1 -1
  228. package/dist/file-system-manager.js +6 -4
  229. package/dist/file-system-manager.js.map +1 -1
  230. package/dist/index.d.ts +1 -1
  231. package/dist/index.d.ts.map +1 -1
  232. package/dist/index.js +1 -1
  233. package/dist/index.js.map +1 -1
  234. package/dist/lock-service/activity-tracker.d.ts +14 -2
  235. package/dist/lock-service/activity-tracker.d.ts.map +1 -1
  236. package/dist/lock-service/activity-tracker.js +43 -6
  237. package/dist/lock-service/activity-tracker.js.map +1 -1
  238. package/dist/lock-service/index.d.ts +13 -2
  239. package/dist/lock-service/index.d.ts.map +1 -1
  240. package/dist/lock-service/index.js +130 -44
  241. package/dist/lock-service/index.js.map +1 -1
  242. package/dist/parsing/jsx.d.ts.map +1 -1
  243. package/dist/parsing/jsx.js +78 -66
  244. package/dist/parsing/jsx.js.map +1 -1
  245. package/dist/socket-manager.js +1 -1
  246. package/dist/socket-manager.js.map +1 -1
  247. package/dist/sync-service/list-dir.d.ts.map +1 -1
  248. package/dist/sync-service/list-dir.js +41 -18
  249. package/dist/sync-service/list-dir.js.map +1 -1
  250. package/dist/vite-plugin-yaml-types.d.ts.map +1 -1
  251. package/dist/vite-plugin-yaml-types.js +2 -4
  252. package/dist/vite-plugin-yaml-types.js.map +1 -1
  253. package/package.json +7 -7
  254. package/dist/ai-service/agent/subagents/apis/api-executor.d.ts.map +0 -1
  255. package/dist/ai-service/agent/subagents/apis/api-executor.js.map +0 -1
  256. package/dist/ai-service/agent/subagents/apis/context.d.ts +0 -12
  257. package/dist/ai-service/agent/subagents/apis/context.d.ts.map +0 -1
  258. package/dist/ai-service/agent/subagents/apis/context.js +0 -18
  259. package/dist/ai-service/agent/subagents/apis/context.js.map +0 -1
  260. package/dist/ai-service/agent/subagents/apis/generate-api-source.d.ts +0 -40
  261. package/dist/ai-service/agent/subagents/apis/generate-api-source.d.ts.map +0 -1
  262. package/dist/ai-service/agent/subagents/apis/generate-api-source.js +0 -516
  263. package/dist/ai-service/agent/subagents/apis/generate-api-source.js.map +0 -1
  264. package/dist/ai-service/agent/subagents/apis/state.d.ts +0 -49
  265. package/dist/ai-service/agent/subagents/apis/state.d.ts.map +0 -1
  266. package/dist/ai-service/agent/subagents/apis/state.js +0 -25
  267. package/dist/ai-service/agent/subagents/apis/state.js.map +0 -1
  268. package/dist/ai-service/agent/subagents/apis/system-prompt.d.ts +0 -3
  269. package/dist/ai-service/agent/subagents/apis/system-prompt.d.ts.map +0 -1
  270. package/dist/ai-service/agent/subagents/apis/system-prompt.js +0 -1704
  271. package/dist/ai-service/agent/subagents/apis/system-prompt.js.map +0 -1
  272. package/dist/ai-service/agent/tools/apis/finalize-api.d.ts +0 -11
  273. package/dist/ai-service/agent/tools/apis/finalize-api.d.ts.map +0 -1
  274. package/dist/ai-service/agent/tools/apis/finalize-api.js +0 -133
  275. package/dist/ai-service/agent/tools/apis/finalize-api.js.map +0 -1
  276. package/dist/ai-service/llm/middleware/retry.d.ts +0 -112
  277. package/dist/ai-service/llm/middleware/retry.d.ts.map +0 -1
  278. package/dist/ai-service/llm/middleware/retry.js +0 -239
  279. package/dist/ai-service/llm/middleware/retry.js.map +0 -1
@@ -1,50 +1,17 @@
1
+ import path from "node:path";
1
2
  import { AiEntityType, AiMode, } from "@superblocksteam/library-shared/types";
2
- import { smoothStream, } from "ai";
3
+ import { hasToolCall, } from "ai";
3
4
  import { getErrorMeta, getLogger } from "../../../util/logger.js";
4
5
  import { buildBaseSystemPrompt } from "../../agent/prompts/build-base-system-prompt.js";
5
- import { getToolCallArguments } from "../../agent/tool-message-utils.js";
6
6
  import { buildTools } from "../../agent/tools.js";
7
7
  import { processStreamChunk } from "../../agent/utils.js";
8
8
  import { LLMProviderError } from "../../llm/error.js";
9
- import { tracedStreamText } from "../../llmobs/helpers.js";
10
- import { processLLMConfig } from "../../util/llm-config-utils.js";
11
9
  import { safeJsonStringify } from "../../util/safe-stringify.js";
12
10
  import { hasToolSuccess } from "../../util/stop-condition.js";
13
- import { AGENT_PLANNED, APP_RUNTIME_UPDATED_WITHOUT_EDITS, LLM_ERRORED, USER_CANCELED, V3_AGENT_FINISHED, } from "../clark-fsm.js";
11
+ import { AGENT_PLANNED, APP_RUNTIME_UPDATED_WITHOUT_EDITS, ClarkStateNames, LLM_ERRORED, USER_CANCELED, V3_AGENT_FINISHED, } from "../clark-fsm.js";
14
12
  import { getContextId } from "../helpers/context-id.js";
15
13
  import { transitionFrom } from "../helpers/transition.js";
16
- function formatSummaryForAgents(latestSummary) {
17
- if (!latestSummary) {
18
- return null;
19
- }
20
- const parts = [];
21
- if (latestSummary.outcome === "accepted") {
22
- parts.push(`The user *accepted* the changes associated with the following summary. They have been applied to the application.`);
23
- }
24
- else if (latestSummary.outcome === "rejected") {
25
- parts.push(`The user *rejected* the changes associated with the following summary. The changes were discarded.`);
26
- }
27
- if (latestSummary.summary) {
28
- parts.push(`Summary: ${latestSummary.summary}`);
29
- }
30
- if (latestSummary.goals && latestSummary.goals.length > 0) {
31
- parts.push(`User Goals: ${latestSummary.goals.join(", ")}`);
32
- }
33
- if (latestSummary.decisions && latestSummary.decisions.length > 0) {
34
- parts.push(`Decisions: ${latestSummary.decisions.join(", ")}`);
35
- }
36
- if (latestSummary.adviceToAgents) {
37
- parts.push(`Agent Advice: ${latestSummary.adviceToAgents}`);
38
- }
39
- if (latestSummary.relevantFilePaths &&
40
- latestSummary.relevantFilePaths.length > 0) {
41
- parts.push(`Relevant files:\n${latestSummary.relevantFilePaths
42
- .map((path) => `- ${path}`)
43
- .join("\n")}`);
44
- }
45
- return parts.length > 0 ? parts.join("\n\n") : null;
46
- }
47
- const buildUserMessage = (userPrompt, promptContext, planContext, mode, services) => {
14
+ const buildUserMessage = (userPrompt, promptContext, planContext, mode, services, userChanges) => {
48
15
  const content = [];
49
16
  const focusedEntities = promptContext?.entities;
50
17
  const focusedEntitiesWithSemanticInfo = focusedEntities?.map((entity) => {
@@ -62,6 +29,38 @@ const buildUserMessage = (userPrompt, promptContext, planContext, mode, services
62
29
  const selectedIntegrations = promptContext?.integrations;
63
30
  const planApproved = planContext?.approved;
64
31
  const planSummary = planContext?.plan;
32
+ // Add user changes if present
33
+ if (userChanges && userChanges.length > 0) {
34
+ const appRootDirPath = services.appShell.appRootDirPath;
35
+ const changeDescriptions = userChanges.map((change) => {
36
+ switch (change.type) {
37
+ case "deleteComponents":
38
+ return `- Deleted ${change.componentCount} component(s) from ${path.relative(appRootDirPath, change.path)}`;
39
+ case "createComponent":
40
+ return `- Added a new component to ${path.relative(appRootDirPath, change.path)}`;
41
+ case "reparent":
42
+ return `- Moved components in ${path.relative(appRootDirPath, change.path)}`;
43
+ case "batchUpdate": {
44
+ const relativePaths = change.paths.map((p) => path.relative(appRootDirPath, p));
45
+ return `- Made ${change.updateCount} changes to ${relativePaths.length > 1 ? `${relativePaths.length} files` : relativePaths[0]}`;
46
+ }
47
+ case "addPage":
48
+ return `- Created a new page at ${path.relative(appRootDirPath, change.path)}`;
49
+ case "deletePage":
50
+ return `- Deleted page at ${path.relative(appRootDirPath, change.path)}`;
51
+ case "apiUpdate":
52
+ return `- Modified API "${change.apiName}"`;
53
+ case "apiDelete":
54
+ return `- Deleted API "${change.apiName}"`;
55
+ case "fileChanged":
56
+ return `- Edited code in ${path.relative(appRootDirPath, change.filePath)}`;
57
+ }
58
+ });
59
+ content.push({
60
+ type: "text",
61
+ text: `<recent_user_changes>\nSince your last interaction, the user has made the following changes:\n${changeDescriptions.join("\n")}\n\nThe current state of the application reflects all of these changes.\n</recent_user_changes>\n\n`,
62
+ });
63
+ }
65
64
  // Add focused entities if present
66
65
  if (focusedEntities?.length) {
67
66
  content.push({
@@ -117,446 +116,82 @@ const buildUserMessage = (userPrompt, promptContext, planContext, mode, services
117
116
  };
118
117
  };
119
118
  export const doLLMGenerating = (clark, services) => {
120
- const { chatSessionStore } = services;
121
119
  const transitionTo = transitionFrom(clark);
122
120
  return async ({ event }) => {
123
121
  switch (event.type) {
124
122
  case AGENT_PLANNED: {
125
123
  const { userPrompt, promptContext } = event;
126
- const { abortController } = clark.context;
127
124
  const provider = services.llmProvider.name;
128
- const contextId = getContextId(clark, services);
129
- const contextOptions = clark.context.llmConfig?.contextOptions;
130
- // Generate a unique owner ID for this LLM generation session
131
- const ownerId = `llm-generating-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
132
- // Acquire exclusive context access
133
- const contextHandle = await services.contextManager.acquireContext(contextId, ownerId, {
134
- contextOptions,
135
- acquireOptions: {
136
- waitTimeoutMs: 30000, // Wait up to 30 seconds for context
137
- lockTimeoutMs: 600000, // Hold lock for up to 10 minutes
138
- retryIntervalMs: 100,
125
+ const mode = clark.context.currentMode;
126
+ const planContext = clark.context.planContext;
127
+ const planApproved = planContext?.approved;
128
+ const system = buildBaseSystemPrompt(mode);
129
+ const user = buildUserMessage(userPrompt, promptContext, planContext, mode, services, clark.context.userChanges);
130
+ const tools = await buildTools(clark, services);
131
+ const result = await clark.streamText(services, {
132
+ user,
133
+ system,
134
+ tools,
135
+ context: {
136
+ contextId: getContextId(clark, services),
139
137
  },
138
+ stopWhen: [
139
+ hasToolSuccess("build_finalize"),
140
+ hasToolSuccess("exitPlanMode"),
141
+ hasToolCall("askMultiChoice"),
142
+ () => clark.state === ClarkStateNames.AwaitingUser,
143
+ ],
140
144
  });
141
145
  try {
142
- const context = contextHandle.context;
143
- const mode = clark.context.currentMode;
144
- const planContext = clark.context.planContext;
145
- const planApproved = planContext?.approved;
146
- await chatSessionStore.getMessages();
147
- const latestSummary = await chatSessionStore.getLatestSummary();
148
- if (latestSummary) {
149
- context.seedIfEmpty({
150
- role: "user",
151
- content: `Reference the context from the previous exchange with the user, if relevant:\n\n${formatSummaryForAgents(latestSummary)}`,
152
- });
153
- }
154
- const systemPrompt = buildBaseSystemPrompt(mode);
155
- const system = {
156
- role: "system",
157
- content: systemPrompt,
158
- };
159
- context.setSystemPrompt(system);
160
- const prompt = buildUserMessage(userPrompt, promptContext, planContext, mode, services);
161
- context.startTurn(prompt);
162
- const messages = context.getMessages();
163
- const model = services.llmProvider.modelForClassification("broad_edit");
164
- // Process LLM configuration up front so we can log it once at the top
165
- const llmConfig = clark.context.llmConfig;
166
- const disabledTools = clark.context.llmConfig?.disabledTools;
167
- const { headers, thinkingEnabled, thinkingBudgetTokens, interleavedThinking, providerOptions, } = processLLMConfig(llmConfig, 5000, // default budget tokens
168
- `LLM Generating (model=${model.modelId}, disabledTools=${disabledTools?.length ? disabledTools.join(",") : "none"})`);
169
- const conversationId = Date.now();
170
- const startTimestamp = new Date().toISOString();
171
- const runTimestamp = clark.context.runTimestamp || startTimestamp;
172
- // Initialize log content
173
- const logRef = {
174
- content: `=== LLM CONVERSATION START [${conversationId}] ===\n`,
175
- };
176
- logRef.content += `Timestamp: ${startTimestamp}\n`;
177
- logRef.content += `Model: ${model.modelId}\n`;
178
- // Log AI provider config
179
- logRef.content += `Provider Config: provider=${llmConfig?.provider || "anthropic (default)"}, thinking=${thinkingEnabled}, budget=${thinkingBudgetTokens}, interleaved=${interleavedThinking}`;
180
- if (disabledTools?.length) {
181
- logRef.content += `, disabledTools=${disabledTools.join(",")}`;
146
+ for await (const chunk of result.fullStream) {
147
+ await processStreamChunk(chunk, clark, services);
182
148
  }
183
- if (headers && Object.keys(headers).length > 0) {
184
- logRef.content += `, headers=${JSON.stringify(headers)}`;
185
- }
186
- logRef.content += `--- INPUT MESSAGES ---\n`;
187
- logRef.content += `[SYSTEM] ${systemPrompt}\n\n`;
188
- logRef.content += `[${system.role.toUpperCase()}] ${system.content}\n\n`;
189
- logRef.content += `--- USER INPUT ---\n`;
190
- logRef.content += `${userPrompt}\n\n`;
191
- if (promptContext) {
192
- if (promptContext.entities?.length) {
193
- logRef.content += `[FOCUSED ENTITIES] ${safeJsonStringify(promptContext.entities)}\n`;
194
- }
195
- if (promptContext.integrations?.length) {
196
- logRef.content += `[SELECTED INTEGRATIONS] ${safeJsonStringify(promptContext.integrations.map(({ id, name, type }) => ({ id, name, type })))}\n`;
197
- }
198
- if (promptContext.attachments?.length) {
199
- logRef.content += `[ATTACHMENTS] ${promptContext.attachments.length} attachment(s)\n`;
200
- promptContext.attachments.forEach((attachment, idx) => {
201
- logRef.content += ` ${idx + 1}. Type: ${attachment.type}\n`;
202
- });
203
- }
204
- }
205
- if (mode !== undefined) {
206
- logRef.content += `[MODE] ${mode === AiMode.PLAN ? "Plan" : "Build"} mode\n`;
207
- }
208
- if (planContext) {
209
- logRef.content += `[PLAN CONTEXT] Approved: ${planContext.approved}, Has Plan: ${!!planContext.plan}\n`;
149
+ }
150
+ catch (err) {
151
+ let error;
152
+ if (LLMProviderError.isInstance(err)) {
153
+ error = err;
210
154
  }
211
- logRef.content += `\n`;
212
- // Note: Input token count will be logged once LLM call begins
213
- // buildTools now returns filtered tools based on mode via registry
214
- const actualTools = await buildTools(clark, services, promptContext, logRef, disabledTools);
215
- logRef.content += `Mode: ${mode}, Available tools: ${Object.keys(actualTools).length}\n`;
216
- logRef.content += `Tools: ${Object.keys(actualTools).join(", ")}\n\n`;
217
- let stepCount = 0;
218
- // Track cumulative token usage across all steps
219
- let totalInputTokens = 0;
220
- let totalOutputTokens = 0;
221
- let totalCachedTokens = 0;
222
- services.clarkProfiler.startLLMWaiting({
223
- messages: messages,
224
- model: model.modelId,
225
- });
226
- let firstTokenReceived = false;
227
- let thinkingSpanActive = false;
228
- let textSpanActive = false;
229
- const allReasoningDeltas = [];
230
- let currentStepReasoningDeltas = [];
231
- let currentStepTextDeltas = [];
232
- getLogger().info(`CURRENT_MODE: ${mode}`);
233
- const build = tracedStreamText({
234
- abortSignal: abortController?.signal,
235
- model,
236
- providerOptions,
237
- headers,
238
- experimental_transform: [smoothStream({ chunking: "line" })],
239
- messages,
240
- tools: actualTools,
241
- prepareStep: async (step) => {
242
- context.startStep();
243
- const messages = context.getMessages();
244
- return { ...step, messages };
245
- },
246
- stopWhen: [
247
- hasToolSuccess("build_finalize"),
248
- hasToolSuccess("exitPlanMode"),
249
- hasToolSuccess("askMultiChoice"),
250
- ],
251
- onChunk: (chunkData) => {
252
- if (!firstTokenReceived) {
253
- firstTokenReceived = true;
254
- services.clarkProfiler.startLLMStreaming({
255
- firstChunk: chunkData.chunk.type === "text-delta"
256
- ? chunkData.chunk.text
257
- : `[${chunkData.chunk.type}]`,
258
- });
259
- }
260
- if (chunkData.chunk.type === "reasoning-delta") {
261
- const thinkingTrack = "thinking";
262
- services.clarkProfiler
263
- .getProfiler()
264
- .createTrack(thinkingTrack, "AI Thinking/Reasoning", "llm");
265
- allReasoningDeltas.push(chunkData.chunk.text);
266
- currentStepReasoningDeltas.push(chunkData.chunk.text);
267
- if (!thinkingSpanActive) {
268
- thinkingSpanActive = true;
269
- services.clarkProfiler
270
- .getProfiler()
271
- .startFrame(`Thinking Step ${stepCount + 1}`, thinkingTrack, {
272
- stepNumber: stepCount + 1,
273
- chunkType: chunkData.chunk.type,
274
- });
275
- }
276
- }
277
- if (chunkData.chunk.type === "text-delta") {
278
- const textTrack = "text_generation";
279
- services.clarkProfiler
280
- .getProfiler()
281
- .createTrack(textTrack, "Text Generation", "llm");
282
- currentStepTextDeltas.push(chunkData.chunk.text);
283
- if (!textSpanActive) {
284
- textSpanActive = true;
285
- services.clarkProfiler
286
- .getProfiler()
287
- .startFrame(`Text Generation Step ${stepCount + 1}`, textTrack, {
288
- stepNumber: stepCount + 1,
289
- firstTextDelta: chunkData.chunk.text.slice(0, 50) +
290
- (chunkData.chunk.text.length > 50 ? "..." : ""),
291
- });
292
- }
293
- }
294
- },
295
- onStepFinish: async (step) => {
296
- stepCount++;
297
- const stepTimestamp = new Date().toISOString();
298
- context.endStep(step.response.messages, step.usage);
299
- logRef.content += `--- OUTPUT STEP ${stepCount} [${stepTimestamp}] ---\n`;
300
- if (step.reasoning && thinkingSpanActive) {
301
- const thinkingTrack = "thinking";
302
- services.clarkProfiler
303
- .getProfiler()
304
- .updateActiveFrameArgs(thinkingTrack, {
305
- completeReasoningText: currentStepReasoningDeltas.join(" "),
306
- reasoningLength: step.reasoning.length,
307
- stepComplete: true,
308
- });
309
- services.clarkProfiler.getProfiler().endFrame(thinkingTrack);
310
- thinkingSpanActive = false;
311
- currentStepReasoningDeltas = [];
312
- }
313
- // Log token usage for this step and accumulate totals
314
- if (step.usage) {
315
- const stepInputTokens = step.usage.inputTokens ?? 0;
316
- const stepOutputTokens = step.usage.outputTokens ?? 0;
317
- const stepCachedTokens = step.usage.cachedInputTokens ?? 0;
318
- // Accumulate totals
319
- totalInputTokens += stepInputTokens;
320
- totalOutputTokens += stepOutputTokens;
321
- totalCachedTokens += stepCachedTokens;
322
- logRef.content += `[TOKEN USAGE] Input: ${stepInputTokens}, Output: ${stepOutputTokens}, Total: ${step.usage.totalTokens ?? 0}`;
323
- if (stepCachedTokens) {
324
- logRef.content += `, Cached: ${stepCachedTokens}`;
325
- }
326
- logRef.content += `\n`;
327
- }
328
- const apiToolCall = step.toolCalls.find((toolCall) => toolCall.toolName === "build_generateApiSource");
329
- const apiName = apiToolCall?.input?.apiName;
330
- const apiGroup = apiName ? `api-${apiName}` : undefined;
331
- // Record tool calls FIRST before other messages to ensure proper ordering
332
- const toolsCalled = step.content
333
- .filter((c) => c.type === "tool-result")
334
- .map((c) => ({
335
- toolName: c.toolName,
336
- input: JSON.stringify(c.input),
337
- output: JSON.stringify(c.output, null, 2),
338
- }));
339
- if (toolsCalled.length > 0) {
340
- logRef.content += `[TOOLS CALLED]\n`;
341
- toolsCalled.forEach((tool, idx) => {
342
- logRef.content += ` Tool ${idx + 1}: ${tool.toolName}\n`;
343
- logRef.content += ` Input: ${tool.input}\n`;
344
- logRef.content += ` Output: ${tool.output}\n`;
345
- });
346
- try {
347
- await Promise.all(step.toolCalls.map(async (toolCall) => {
348
- const args = await getToolCallArguments(toolCall.toolName, toolCall.input, clark);
349
- await services.chatSessionStore.recordAssistant({
350
- type: "tool",
351
- tool: toolCall.toolName,
352
- args: args,
353
- ...(apiGroup && { group: apiGroup }),
354
- });
355
- }));
356
- }
357
- catch (error) {
358
- getLogger().error("Failed to record tool calls", getErrorMeta(error));
359
- }
360
- // Record profiling events
361
- toolsCalled.forEach((tool, idx) => {
362
- let parsedInput, parsedOutput;
363
- try {
364
- parsedInput = JSON.parse(tool.input);
365
- }
366
- catch {
367
- parsedInput = tool.input;
368
- }
369
- try {
370
- parsedOutput = JSON.parse(tool.output);
371
- }
372
- catch {
373
- parsedOutput = tool.output;
374
- }
375
- services.clarkProfiler
376
- .getProfiler()
377
- .addInstantEvent(`Tool Call: ${tool.toolName}`, "llm", {
378
- step: stepCount,
379
- toolIndex: idx + 1,
380
- toolName: tool.toolName,
381
- input: parsedInput,
382
- output: parsedOutput,
383
- inputSize: tool.input.length,
384
- outputSize: tool.output.length,
385
- });
386
- });
387
- }
388
- // Record reasoning messages AFTER tool calls
389
- if (step.reasoning) {
390
- const reasoningLines = [
391
- "[REASONING]",
392
- ...step.reasoning.map(({ text }) => text),
393
- "",
394
- ];
395
- logRef.content += reasoningLines.join("\n");
396
- const reasoningText = step.reasoning
397
- .map(({ text }) => text)
398
- .join("");
399
- if (reasoningText) {
400
- try {
401
- await services.chatSessionStore.recordAssistant({
402
- type: "reasoning",
403
- text: reasoningText,
404
- ...(apiGroup && { group: apiGroup }),
405
- });
406
- }
407
- catch (error) {
408
- getLogger().error("Failed to record message from LLM", getErrorMeta(error));
409
- }
410
- }
411
- }
412
- if (step.text && textSpanActive) {
413
- const textTrack = "text_generation";
414
- services.clarkProfiler
415
- .getProfiler()
416
- .updateActiveFrameArgs(textTrack, {
417
- completeTextContent: currentStepTextDeltas.join(""),
418
- finalText: step.text,
419
- textLength: step.text.length,
420
- stepComplete: true,
421
- });
422
- services.clarkProfiler.getProfiler().endFrame(textTrack);
423
- textSpanActive = false;
424
- currentStepTextDeltas = [];
425
- }
426
- // Record text messages AFTER tool calls and reasoning
427
- if (step.text) {
428
- logRef.content += `[ASSISTANT TEXT] ${step.text}\n`;
429
- try {
430
- await services.chatSessionStore.recordAssistant({
431
- type: "text",
432
- text: step.text,
433
- ...(apiGroup && { group: apiGroup }),
434
- });
435
- }
436
- catch (error) {
437
- getLogger().error("Failed to record message from LLM", getErrorMeta(error));
438
- }
439
- }
440
- logRef.content += `\n`;
441
- },
442
- onFinish: (result) => {
443
- context.endTurn(result.totalUsage);
444
- },
445
- }, clark.tracer, clark.logger);
446
- try {
447
- for await (const chunk of build.fullStream) {
448
- await processStreamChunk(chunk, clark, services, logRef);
449
- }
155
+ else {
156
+ error = new LLMProviderError({ provider, cause: err });
450
157
  }
451
- catch (err) {
452
- let error;
453
- if (LLMProviderError.isInstance(err)) {
454
- error = err;
455
- }
456
- else {
457
- error = new LLMProviderError({ provider, cause: err });
458
- }
459
- if (error.type === "aborted") {
460
- getLogger().info("LLM generation aborted by user");
461
- void clark.send({
462
- type: USER_CANCELED,
463
- });
464
- return;
465
- }
466
- getLogger().error("LLM stream processing failed", getErrorMeta(error));
158
+ if (error.type === "aborted") {
159
+ getLogger().info("LLM generation aborted by user");
467
160
  void clark.send({
468
- type: LLM_ERRORED,
469
- error,
161
+ type: USER_CANCELED,
470
162
  });
471
163
  return;
472
164
  }
473
- if (firstTokenReceived) {
474
- services.clarkProfiler.endFrame();
475
- }
476
- services.clarkProfiler.endFrame();
477
- if (thinkingSpanActive) {
478
- services.clarkProfiler.getProfiler().endFrame("thinking");
479
- }
480
- if (textSpanActive) {
481
- services.clarkProfiler.getProfiler().endFrame("text_generation");
482
- }
483
- const endTimestamp = new Date().toISOString();
484
- logRef.content += `=== LLM CONVERSATION END [${conversationId}] ===\n`;
485
- logRef.content += `End Timestamp: ${endTimestamp}\n`;
486
- logRef.content += `Total Steps: ${stepCount}\n`;
487
- // Log final token usage summary using accumulated totals
488
- const finalTotalTokens = totalInputTokens + totalOutputTokens;
489
- logRef.content += `[TOTAL TOKEN USAGE] Input: ${totalInputTokens}, Output: ${totalOutputTokens}, Total: ${finalTotalTokens}`;
490
- if (totalCachedTokens > 0) {
491
- logRef.content += `, Cached: ${totalCachedTokens}`;
492
- }
493
- logRef.content += `\n`;
494
- try {
495
- // Create TokenRequestData object from accumulated step data (not AI SDK usage which is only final step)
496
- const requestTokenData = {
497
- requestId: conversationId.toString(),
498
- inputTokens: totalInputTokens,
499
- outputTokens: totalOutputTokens,
500
- totalTokens: totalInputTokens + totalOutputTokens,
501
- cachedInputTokens: totalCachedTokens,
502
- model: model.modelId,
503
- startTime: startTimestamp,
504
- endTime: endTimestamp,
505
- };
506
- await clark.context.peer?.call.aiPushTokenUsage(requestTokenData);
507
- }
508
- catch (error) {
509
- // Token tracking is non-critical - log error but don't fail the AI request
510
- getLogger().warn("Failed to send token usage data", error instanceof Error ? error.message : String(error));
511
- }
512
- // Save the complete log using saveGeneratedArtifact
513
- try {
514
- const logArtifact = {
515
- type: "file",
516
- filePath: `llm-conversation-${conversationId}.log`,
517
- content: logRef.content,
518
- };
519
- const stepId = `llm-conversation-${conversationId}`;
520
- await services.appShell.saveGeneratedArtifact(logArtifact, stepId, runTimestamp);
521
- getLogger().debug("LLM conversation log saved");
522
- }
523
- catch (error) {
524
- getLogger().error("Failed to save LLM conversation log", {
525
- error: {
526
- kind: "SaveLogError",
527
- message: error instanceof Error ? error.message : String(error),
528
- stack: error instanceof Error ? error.stack : undefined,
529
- },
530
- });
531
- }
532
- // Check if there are local draft changes
533
- const hasLocalDraft = await services.draftInterface.hasLocalDraftChanges();
534
- // In PLAN mode, only proceed to draft state if:
535
- // 1. User has approved the plan
536
- // 2. There are actual file changes (hasLocalDraft === true)
537
- if (mode === AiMode.PLAN) {
538
- if (!planApproved || !hasLocalDraft) {
539
- void transitionTo({
540
- type: APP_RUNTIME_UPDATED_WITHOUT_EDITS,
541
- });
542
- return;
543
- }
544
- // If plan is approved and there are changes, fall through to create draft
545
- }
546
- if (hasLocalDraft) {
547
- void transitionTo({
548
- type: V3_AGENT_FINISHED,
549
- });
550
- }
551
- else {
165
+ getLogger().error("LLM stream processing failed", getErrorMeta(error));
166
+ void clark.send({
167
+ type: LLM_ERRORED,
168
+ error,
169
+ });
170
+ return;
171
+ }
172
+ // Check if there are local draft changes
173
+ const hasLocalDraft = await services.draftInterface.hasLocalDraftChanges();
174
+ // In PLAN mode, only proceed to draft state if:
175
+ // 1. User has approved the plan
176
+ // 2. There are actual file changes (hasLocalDraft === true)
177
+ if (mode === AiMode.PLAN) {
178
+ if (!planApproved || !hasLocalDraft) {
552
179
  void transitionTo({
553
180
  type: APP_RUNTIME_UPDATED_WITHOUT_EDITS,
554
181
  });
182
+ return;
555
183
  }
184
+ // If plan is approved and there are changes, fall through to create draft
556
185
  }
557
- finally {
558
- // Always release the context lock when done
559
- contextHandle.release();
186
+ if (hasLocalDraft) {
187
+ void transitionTo({
188
+ type: V3_AGENT_FINISHED,
189
+ });
190
+ }
191
+ else {
192
+ void transitionTo({
193
+ type: APP_RUNTIME_UPDATED_WITHOUT_EDITS,
194
+ });
560
195
  }
561
196
  }
562
197
  }