@stigmer/sdk 3.34.0 → 3.36.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 (342) hide show
  1. package/activity.d.ts.map +1 -1
  2. package/activity.js.map +1 -1
  3. package/artifact-routing.d.ts.map +1 -1
  4. package/artifact-routing.js.map +1 -1
  5. package/authorization-config.d.ts.map +1 -1
  6. package/authorization-config.js.map +1 -1
  7. package/billing.d.ts.map +1 -1
  8. package/billing.js.map +1 -1
  9. package/config.d.ts.map +1 -1
  10. package/config.js.map +1 -1
  11. package/cursor-accounts.d.ts.map +1 -1
  12. package/cursor-accounts.js.map +1 -1
  13. package/ensure-identity-account.d.ts.map +1 -1
  14. package/ensure-identity-account.js.map +1 -1
  15. package/errors.d.ts.map +1 -1
  16. package/errors.js.map +1 -1
  17. package/execution/approval-provenance.d.ts.map +1 -1
  18. package/execution/approval-provenance.js.map +1 -1
  19. package/execution/conversation-rules.d.ts.map +1 -1
  20. package/execution/conversation-rules.js.map +1 -1
  21. package/execution/execution-phases.d.ts.map +1 -1
  22. package/execution/execution-phases.js.map +1 -1
  23. package/execution/file-review-fold.d.ts.map +1 -1
  24. package/execution/file-review-fold.js.map +1 -1
  25. package/execution/to-display-file-change.d.ts.map +1 -1
  26. package/execution/to-display-file-change.js.map +1 -1
  27. package/execution/tool-view.d.ts.map +1 -1
  28. package/execution/tool-view.js.map +1 -1
  29. package/execution/transcript.d.ts.map +1 -1
  30. package/execution/transcript.js.map +1 -1
  31. package/gen/agent.d.ts.map +1 -1
  32. package/gen/agent.js.map +1 -1
  33. package/gen/agentchannel.d.ts.map +1 -1
  34. package/gen/agentchannel.js.map +1 -1
  35. package/gen/agentexecution.d.ts.map +1 -1
  36. package/gen/agentexecution.js.map +1 -1
  37. package/gen/agentinstance.d.ts.map +1 -1
  38. package/gen/agentinstance.js.map +1 -1
  39. package/gen/agentshare.d.ts.map +1 -1
  40. package/gen/agentshare.js.map +1 -1
  41. package/gen/apikey.d.ts.map +1 -1
  42. package/gen/apikey.js.map +1 -1
  43. package/gen/artifact.d.ts.map +1 -1
  44. package/gen/artifact.js.map +1 -1
  45. package/gen/authorization-config.d.ts.map +1 -1
  46. package/gen/authorization-config.js +2 -2
  47. package/gen/authorization-config.js.map +1 -1
  48. package/gen/bidi-stream.d.ts.map +1 -1
  49. package/gen/bidi-stream.js.map +1 -1
  50. package/gen/channelapp.d.ts.map +1 -1
  51. package/gen/channelapp.js.map +1 -1
  52. package/gen/client.d.ts.map +1 -1
  53. package/gen/client.js.map +1 -1
  54. package/gen/environment.d.ts.map +1 -1
  55. package/gen/environment.js.map +1 -1
  56. package/gen/errors.d.ts.map +1 -1
  57. package/gen/errors.js.map +1 -1
  58. package/gen/executioncontext.d.ts.map +1 -1
  59. package/gen/executioncontext.js.map +1 -1
  60. package/gen/iampolicy.d.ts.map +1 -1
  61. package/gen/iampolicy.js.map +1 -1
  62. package/gen/identityaccount.d.ts.map +1 -1
  63. package/gen/identityaccount.js.map +1 -1
  64. package/gen/identityprovider.d.ts.map +1 -1
  65. package/gen/identityprovider.js.map +1 -1
  66. package/gen/invitation.d.ts.map +1 -1
  67. package/gen/invitation.js.map +1 -1
  68. package/gen/license.d.ts.map +1 -1
  69. package/gen/license.js.map +1 -1
  70. package/gen/mcpserver.d.ts.map +1 -1
  71. package/gen/mcpserver.js.map +1 -1
  72. package/gen/memory.d.ts.map +1 -1
  73. package/gen/memory.js.map +1 -1
  74. package/gen/oauthapp.d.ts.map +1 -1
  75. package/gen/oauthapp.js.map +1 -1
  76. package/gen/organization.d.ts.map +1 -1
  77. package/gen/organization.js.map +1 -1
  78. package/gen/plan.d.ts.map +1 -1
  79. package/gen/plan.js.map +1 -1
  80. package/gen/platformclient.d.ts.map +1 -1
  81. package/gen/platformclient.js.map +1 -1
  82. package/gen/plugin.d.ts.map +1 -1
  83. package/gen/plugin.js.map +1 -1
  84. package/gen/proto-utils.d.ts.map +1 -1
  85. package/gen/proto-utils.js.map +1 -1
  86. package/gen/resource-availability.d.ts.map +1 -1
  87. package/gen/resource-availability.js.map +1 -1
  88. package/gen/schedule.d.ts.map +1 -1
  89. package/gen/schedule.js.map +1 -1
  90. package/gen/session.d.ts.map +1 -1
  91. package/gen/session.js.map +1 -1
  92. package/gen/skill.d.ts.map +1 -1
  93. package/gen/skill.js.map +1 -1
  94. package/gen/subscription.d.ts.map +1 -1
  95. package/gen/subscription.js.map +1 -1
  96. package/gen/team.d.ts.map +1 -1
  97. package/gen/team.js.map +1 -1
  98. package/gen/types.d.ts.map +1 -1
  99. package/gen/types.js.map +1 -1
  100. package/gen/workflow.d.ts.map +1 -1
  101. package/gen/workflow.js.map +1 -1
  102. package/gen/workflowexecution.d.ts.map +1 -1
  103. package/gen/workflowexecution.js.map +1 -1
  104. package/gen/workflowinstance.d.ts.map +1 -1
  105. package/gen/workflowinstance.js.map +1 -1
  106. package/github.d.ts.map +1 -1
  107. package/github.js.map +1 -1
  108. package/guest-auth.d.ts.map +1 -1
  109. package/guest-auth.js.map +1 -1
  110. package/iam-principal.d.ts.map +1 -1
  111. package/iam-principal.js.map +1 -1
  112. package/iam-role.d.ts.map +1 -1
  113. package/iam-role.js.map +1 -1
  114. package/index.d.ts.map +1 -1
  115. package/index.js.map +1 -1
  116. package/internal/interceptors.d.ts.map +1 -1
  117. package/internal/interceptors.js.map +1 -1
  118. package/manifest/client.d.ts.map +1 -1
  119. package/manifest/client.js.map +1 -1
  120. package/manifest/document.d.ts.map +1 -1
  121. package/manifest/document.js.map +1 -1
  122. package/manifest/index.d.ts.map +1 -1
  123. package/manifest/index.js.map +1 -1
  124. package/manifest/parse.d.ts.map +1 -1
  125. package/manifest/parse.js.map +1 -1
  126. package/manifest/redaction.d.ts.map +1 -1
  127. package/manifest/redaction.js.map +1 -1
  128. package/manifest/registry.d.ts.map +1 -1
  129. package/manifest/registry.js.map +1 -1
  130. package/manifest/serialize.d.ts.map +1 -1
  131. package/manifest/serialize.js.map +1 -1
  132. package/mcpserver-connect.d.ts.map +1 -1
  133. package/mcpserver-connect.js.map +1 -1
  134. package/node.d.ts.map +1 -1
  135. package/node.js.map +1 -1
  136. package/package.json +2 -2
  137. package/platform-client-auth.d.ts.map +1 -1
  138. package/platform-client-auth.js.map +1 -1
  139. package/platform.d.ts.map +1 -1
  140. package/platform.js.map +1 -1
  141. package/plugin.d.ts.map +1 -1
  142. package/plugin.js.map +1 -1
  143. package/provider-standing.d.ts.map +1 -1
  144. package/provider-standing.js.map +1 -1
  145. package/resource-availability.d.ts.map +1 -1
  146. package/resource-availability.js.map +1 -1
  147. package/runner-adapter.d.ts.map +1 -1
  148. package/runner-adapter.js.map +1 -1
  149. package/search.d.ts.map +1 -1
  150. package/search.js.map +1 -1
  151. package/session.d.ts.map +1 -1
  152. package/session.js.map +1 -1
  153. package/sharing.d.ts.map +1 -1
  154. package/sharing.js.map +1 -1
  155. package/skill.d.ts.map +1 -1
  156. package/skill.js.map +1 -1
  157. package/src/gen/authorization-config.ts +2 -2
  158. package/stigmer.d.ts.map +1 -1
  159. package/stigmer.js.map +1 -1
  160. package/transport.d.ts.map +1 -1
  161. package/transport.js.map +1 -1
  162. package/__tests__/billing.test.d.ts +0 -2
  163. package/__tests__/billing.test.d.ts.map +0 -1
  164. package/__tests__/billing.test.js +0 -120
  165. package/__tests__/billing.test.js.map +0 -1
  166. package/__tests__/config.test.d.ts +0 -2
  167. package/__tests__/config.test.d.ts.map +0 -1
  168. package/__tests__/config.test.js +0 -35
  169. package/__tests__/config.test.js.map +0 -1
  170. package/__tests__/ensure-identity-account.test.d.ts +0 -2
  171. package/__tests__/ensure-identity-account.test.d.ts.map +0 -1
  172. package/__tests__/ensure-identity-account.test.js +0 -108
  173. package/__tests__/ensure-identity-account.test.js.map +0 -1
  174. package/__tests__/errors.test.d.ts +0 -2
  175. package/__tests__/errors.test.d.ts.map +0 -1
  176. package/__tests__/errors.test.js +0 -228
  177. package/__tests__/errors.test.js.map +0 -1
  178. package/__tests__/gen/errors.test.d.ts +0 -2
  179. package/__tests__/gen/errors.test.d.ts.map +0 -1
  180. package/__tests__/gen/errors.test.js +0 -97
  181. package/__tests__/gen/errors.test.js.map +0 -1
  182. package/__tests__/gen/invitation-client.test.d.ts +0 -2
  183. package/__tests__/gen/invitation-client.test.d.ts.map +0 -1
  184. package/__tests__/gen/invitation-client.test.js +0 -106
  185. package/__tests__/gen/invitation-client.test.js.map +0 -1
  186. package/__tests__/gen/proto-utils.test.d.ts +0 -2
  187. package/__tests__/gen/proto-utils.test.d.ts.map +0 -1
  188. package/__tests__/gen/proto-utils.test.js +0 -85
  189. package/__tests__/gen/proto-utils.test.js.map +0 -1
  190. package/__tests__/gen/session-client.test.d.ts +0 -2
  191. package/__tests__/gen/session-client.test.d.ts.map +0 -1
  192. package/__tests__/gen/session-client.test.js +0 -152
  193. package/__tests__/gen/session-client.test.js.map +0 -1
  194. package/__tests__/guest-auth.test.d.ts +0 -2
  195. package/__tests__/guest-auth.test.d.ts.map +0 -1
  196. package/__tests__/guest-auth.test.js +0 -223
  197. package/__tests__/guest-auth.test.js.map +0 -1
  198. package/__tests__/iam-principal.test.d.ts +0 -2
  199. package/__tests__/iam-principal.test.d.ts.map +0 -1
  200. package/__tests__/iam-principal.test.js +0 -65
  201. package/__tests__/iam-principal.test.js.map +0 -1
  202. package/__tests__/manifest.test.d.ts +0 -2
  203. package/__tests__/manifest.test.d.ts.map +0 -1
  204. package/__tests__/manifest.test.js +0 -306
  205. package/__tests__/manifest.test.js.map +0 -1
  206. package/__tests__/mcpserver-connect.test.d.ts +0 -2
  207. package/__tests__/mcpserver-connect.test.d.ts.map +0 -1
  208. package/__tests__/mcpserver-connect.test.js +0 -146
  209. package/__tests__/mcpserver-connect.test.js.map +0 -1
  210. package/__tests__/node.test.d.ts +0 -2
  211. package/__tests__/node.test.d.ts.map +0 -1
  212. package/__tests__/node.test.js +0 -67
  213. package/__tests__/node.test.js.map +0 -1
  214. package/__tests__/platform-client-auth.test.d.ts +0 -2
  215. package/__tests__/platform-client-auth.test.d.ts.map +0 -1
  216. package/__tests__/platform-client-auth.test.js +0 -59
  217. package/__tests__/platform-client-auth.test.js.map +0 -1
  218. package/__tests__/platform.test.d.ts +0 -2
  219. package/__tests__/platform.test.d.ts.map +0 -1
  220. package/__tests__/platform.test.js +0 -52
  221. package/__tests__/platform.test.js.map +0 -1
  222. package/__tests__/plugin.test.d.ts +0 -2
  223. package/__tests__/plugin.test.d.ts.map +0 -1
  224. package/__tests__/plugin.test.js +0 -74
  225. package/__tests__/plugin.test.js.map +0 -1
  226. package/__tests__/resource-availability.test.d.ts +0 -2
  227. package/__tests__/resource-availability.test.d.ts.map +0 -1
  228. package/__tests__/resource-availability.test.js +0 -80
  229. package/__tests__/resource-availability.test.js.map +0 -1
  230. package/__tests__/runner-adapter.test.d.ts +0 -2
  231. package/__tests__/runner-adapter.test.d.ts.map +0 -1
  232. package/__tests__/runner-adapter.test.js +0 -88
  233. package/__tests__/runner-adapter.test.js.map +0 -1
  234. package/__tests__/session.test.d.ts +0 -6
  235. package/__tests__/session.test.d.ts.map +0 -1
  236. package/__tests__/session.test.js +0 -50
  237. package/__tests__/session.test.js.map +0 -1
  238. package/__tests__/sharing.test.d.ts +0 -2
  239. package/__tests__/sharing.test.d.ts.map +0 -1
  240. package/__tests__/sharing.test.js +0 -106
  241. package/__tests__/sharing.test.js.map +0 -1
  242. package/__tests__/skill.test.d.ts +0 -2
  243. package/__tests__/skill.test.d.ts.map +0 -1
  244. package/__tests__/skill.test.js +0 -117
  245. package/__tests__/skill.test.js.map +0 -1
  246. package/__tests__/stigmer.test.d.ts +0 -2
  247. package/__tests__/stigmer.test.d.ts.map +0 -1
  248. package/__tests__/stigmer.test.js +0 -127
  249. package/__tests__/stigmer.test.js.map +0 -1
  250. package/__tests__/update-input-roundtrip.test.d.ts +0 -2
  251. package/__tests__/update-input-roundtrip.test.d.ts.map +0 -1
  252. package/__tests__/update-input-roundtrip.test.js +0 -775
  253. package/__tests__/update-input-roundtrip.test.js.map +0 -1
  254. package/__tests__/update-input.test.d.ts +0 -2
  255. package/__tests__/update-input.test.d.ts.map +0 -1
  256. package/__tests__/update-input.test.js +0 -188
  257. package/__tests__/update-input.test.js.map +0 -1
  258. package/execution/__tests__/approval-provenance.test.d.ts +0 -2
  259. package/execution/__tests__/approval-provenance.test.d.ts.map +0 -1
  260. package/execution/__tests__/approval-provenance.test.js +0 -42
  261. package/execution/__tests__/approval-provenance.test.js.map +0 -1
  262. package/execution/__tests__/file-review-fold.corpus.test.d.ts +0 -2
  263. package/execution/__tests__/file-review-fold.corpus.test.d.ts.map +0 -1
  264. package/execution/__tests__/file-review-fold.corpus.test.js +0 -82
  265. package/execution/__tests__/file-review-fold.corpus.test.js.map +0 -1
  266. package/execution/__tests__/file-review-fold.test.d.ts +0 -2
  267. package/execution/__tests__/file-review-fold.test.d.ts.map +0 -1
  268. package/execution/__tests__/file-review-fold.test.js +0 -184
  269. package/execution/__tests__/file-review-fold.test.js.map +0 -1
  270. package/execution/__tests__/to-display-file-change.test.d.ts +0 -2
  271. package/execution/__tests__/to-display-file-change.test.d.ts.map +0 -1
  272. package/execution/__tests__/to-display-file-change.test.js +0 -81
  273. package/execution/__tests__/to-display-file-change.test.js.map +0 -1
  274. package/execution/__tests__/tool-view.file-changes.test.d.ts +0 -2
  275. package/execution/__tests__/tool-view.file-changes.test.d.ts.map +0 -1
  276. package/execution/__tests__/tool-view.file-changes.test.js +0 -86
  277. package/execution/__tests__/tool-view.file-changes.test.js.map +0 -1
  278. package/execution/__tests__/tool-view.fixtures.test.d.ts +0 -2
  279. package/execution/__tests__/tool-view.fixtures.test.d.ts.map +0 -1
  280. package/execution/__tests__/tool-view.fixtures.test.js +0 -152
  281. package/execution/__tests__/tool-view.fixtures.test.js.map +0 -1
  282. package/execution/__tests__/tool-view.output-ref.test.d.ts +0 -2
  283. package/execution/__tests__/tool-view.output-ref.test.d.ts.map +0 -1
  284. package/execution/__tests__/tool-view.output-ref.test.js +0 -64
  285. package/execution/__tests__/tool-view.output-ref.test.js.map +0 -1
  286. package/execution/__tests__/tool-view.read.test.d.ts +0 -2
  287. package/execution/__tests__/tool-view.read.test.d.ts.map +0 -1
  288. package/execution/__tests__/tool-view.read.test.js +0 -56
  289. package/execution/__tests__/tool-view.read.test.js.map +0 -1
  290. package/execution/__tests__/tool-view.search.test.d.ts +0 -2
  291. package/execution/__tests__/tool-view.search.test.d.ts.map +0 -1
  292. package/execution/__tests__/tool-view.search.test.js +0 -200
  293. package/execution/__tests__/tool-view.search.test.js.map +0 -1
  294. package/execution/__tests__/tool-view.shell.test.d.ts +0 -2
  295. package/execution/__tests__/tool-view.shell.test.d.ts.map +0 -1
  296. package/execution/__tests__/tool-view.shell.test.js +0 -104
  297. package/execution/__tests__/tool-view.shell.test.js.map +0 -1
  298. package/execution/__tests__/transcript.test.d.ts +0 -2
  299. package/execution/__tests__/transcript.test.d.ts.map +0 -1
  300. package/execution/__tests__/transcript.test.js +0 -591
  301. package/execution/__tests__/transcript.test.js.map +0 -1
  302. package/node.test.d.ts +0 -2
  303. package/node.test.d.ts.map +0 -1
  304. package/node.test.js +0 -35
  305. package/node.test.js.map +0 -1
  306. package/src/__tests__/billing.test.ts +0 -146
  307. package/src/__tests__/config.test.ts +0 -52
  308. package/src/__tests__/ensure-identity-account.test.ts +0 -146
  309. package/src/__tests__/errors.test.ts +0 -349
  310. package/src/__tests__/gen/errors.test.ts +0 -138
  311. package/src/__tests__/gen/invitation-client.test.ts +0 -132
  312. package/src/__tests__/gen/proto-utils.test.ts +0 -99
  313. package/src/__tests__/gen/session-client.test.ts +0 -208
  314. package/src/__tests__/guest-auth.test.ts +0 -287
  315. package/src/__tests__/iam-principal.test.ts +0 -82
  316. package/src/__tests__/manifest.test.ts +0 -362
  317. package/src/__tests__/mcpserver-connect.test.ts +0 -181
  318. package/src/__tests__/node.test.ts +0 -74
  319. package/src/__tests__/platform-client-auth.test.ts +0 -76
  320. package/src/__tests__/platform.test.ts +0 -74
  321. package/src/__tests__/plugin.test.ts +0 -92
  322. package/src/__tests__/resource-availability.test.ts +0 -118
  323. package/src/__tests__/runner-adapter.test.ts +0 -122
  324. package/src/__tests__/session.test.ts +0 -66
  325. package/src/__tests__/sharing.test.ts +0 -159
  326. package/src/__tests__/skill.test.ts +0 -150
  327. package/src/__tests__/stigmer.test.ts +0 -170
  328. package/src/__tests__/update-input-roundtrip.test.ts +0 -1007
  329. package/src/__tests__/update-input.test.ts +0 -250
  330. package/src/execution/__tests__/approval-provenance.test.ts +0 -60
  331. package/src/execution/__tests__/file-review-fold.corpus.test.ts +0 -127
  332. package/src/execution/__tests__/file-review-fold.test.ts +0 -281
  333. package/src/execution/__tests__/to-display-file-change.test.ts +0 -106
  334. package/src/execution/__tests__/tool-view.file-changes.test.ts +0 -100
  335. package/src/execution/__tests__/tool-view.fixtures.test.ts +0 -225
  336. package/src/execution/__tests__/tool-view.output-ref.test.ts +0 -76
  337. package/src/execution/__tests__/tool-view.read.test.ts +0 -71
  338. package/src/execution/__tests__/tool-view.search.test.ts +0 -264
  339. package/src/execution/__tests__/tool-view.shell.test.ts +0 -127
  340. package/src/execution/__tests__/transcript.golden.md +0 -100
  341. package/src/execution/__tests__/transcript.test.ts +0 -697
  342. package/src/node.test.ts +0 -38
@@ -1,697 +0,0 @@
1
- // The canonical session transcript (stigmer/stigmer#814): assembly rules,
2
- // offload resolution, and the two serializations.
3
- //
4
- // The Markdown format is a pinned contract: transcript.golden.md freezes the
5
- // exact rendering of a transcript exercising every construct (thinking,
6
- // system, tool calls with args/results, offloaded outputs resolved and
7
- // noted, sub-agent nesting, build-from-plan and in-progress markers). A
8
- // deliberate format change regenerates the golden with
9
- // UPDATE_TRANSCRIPT_GOLDEN=1 npx vitest run src/execution/__tests__/transcript.test.ts
10
- // and reviews the diff; an accidental one fails here.
11
-
12
- import { readFileSync, writeFileSync } from "node:fs";
13
- import { fileURLToPath } from "node:url";
14
- import { dirname, resolve } from "node:path";
15
- import { describe, it, expect } from "vitest";
16
- import { create } from "@bufbuild/protobuf";
17
- import type { JsonObject } from "@bufbuild/protobuf";
18
- import {
19
- AgentExecutionSchema,
20
- type AgentExecution,
21
- } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
22
- import {
23
- ExecutionPhase,
24
- MessageType,
25
- ToolCallStatus,
26
- } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
27
- import {
28
- AgentExecutionListSchema,
29
- GetArtifactContentResponseSchema,
30
- type GetArtifactContentRequest,
31
- type GetArtifactContentResponse,
32
- } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/io_pb";
33
- import { SessionSchema } from "@stigmer/protos/ai/stigmer/agentic/session/v1/api_pb";
34
- import {
35
- assembleSessionTranscript,
36
- fetchSessionTranscript,
37
- resolveOffloadedOutputs,
38
- transcriptToJson,
39
- transcriptToMarkdown,
40
- type ResolvedToolOutput,
41
- } from "../transcript";
42
-
43
- const here = dirname(fileURLToPath(import.meta.url));
44
-
45
- // ---------------------------------------------------------------------------
46
- // Fixture builders
47
- // ---------------------------------------------------------------------------
48
-
49
- function session() {
50
- return create(SessionSchema, {
51
- metadata: { id: "ses_01" },
52
- spec: { subject: "Fix the flaky test", agentInstanceId: "agi_01" },
53
- });
54
- }
55
-
56
- /** Turn 1: prompt echo dedupe, thinking, tool call with args + inline
57
- * result + duration, offloaded text output, image output, raw system. */
58
- function exec1(): AgentExecution {
59
- return create(AgentExecutionSchema, {
60
- metadata: { id: "aex_01a" },
61
- spec: { sessionId: "ses_01", message: "Why is CI red?" },
62
- status: {
63
- phase: ExecutionPhase.EXECUTION_COMPLETED,
64
- startedAt: "2026-08-20T10:00:00Z",
65
- completedAt: "2026-08-20T10:01:00Z",
66
- messages: [
67
- {
68
- type: MessageType.MESSAGE_HUMAN,
69
- content: "Why is CI red?",
70
- timestamp: "2026-08-20T10:00:01Z",
71
- },
72
- {
73
- type: MessageType.MESSAGE_THINKING,
74
- content: "The failure is in the retry loop.\nLet me check.",
75
- timestamp: "2026-08-20T10:00:02Z",
76
- },
77
- {
78
- type: MessageType.MESSAGE_AI,
79
- content: "Let me look.",
80
- timestamp: "2026-08-20T10:00:04Z",
81
- toolCalls: [
82
- {
83
- id: "tc_1",
84
- name: "shell_command",
85
- args: { command: "go test ./..." } as JsonObject,
86
- result: "FAIL: TestRetry",
87
- status: ToolCallStatus.TOOL_CALL_COMPLETED,
88
- startedAt: "2026-08-20T10:00:05Z",
89
- completedAt: "2026-08-20T10:00:07Z",
90
- },
91
- ],
92
- },
93
- {
94
- type: MessageType.MESSAGE_AI,
95
- content: "",
96
- timestamp: "2026-08-20T10:00:10Z",
97
- toolCalls: [
98
- {
99
- id: "tc_2",
100
- name: "read_file",
101
- args: { path: "retry.go" } as JsonObject,
102
- status: ToolCallStatus.TOOL_CALL_COMPLETED,
103
- outputRef: {
104
- storageKey: "artifacts/aex_01a/toolcalls/tc_2.txt",
105
- sizeBytes: 2048n,
106
- mimeType: "text/plain",
107
- truncatedPreview: "package retry…",
108
- },
109
- },
110
- {
111
- id: "tc_3",
112
- name: "screenshot",
113
- status: ToolCallStatus.TOOL_CALL_COMPLETED,
114
- outputRef: {
115
- storageKey: "artifacts/aex_01a/toolcalls/tc_3.png",
116
- sizeBytes: 4096n,
117
- mimeType: "image/png",
118
- isImage: true,
119
- },
120
- },
121
- ],
122
- },
123
- {
124
- type: MessageType.MESSAGE_SYSTEM,
125
- content: "Approval received",
126
- timestamp: "2026-08-20T10:00:20Z",
127
- },
128
- ],
129
- },
130
- });
131
- }
132
-
133
- /** Superseded by exec3's edit-and-resubmit — excluded by default. */
134
- function exec2(): AgentExecution {
135
- return create(AgentExecutionSchema, {
136
- metadata: { id: "aex_01b" },
137
- spec: { sessionId: "ses_01", message: "old prompt" },
138
- status: { phase: ExecutionPhase.EXECUTION_COMPLETED },
139
- });
140
- }
141
-
142
- /** Turn 2: edit-and-resubmit successor with a sub-agent delegation. */
143
- function exec3(): AgentExecution {
144
- return create(AgentExecutionSchema, {
145
- metadata: { id: "aex_01c" },
146
- spec: {
147
- sessionId: "ses_01",
148
- message: "edited prompt",
149
- supersedesExecutionId: "aex_01b",
150
- },
151
- status: {
152
- phase: ExecutionPhase.EXECUTION_COMPLETED,
153
- startedAt: "2026-08-20T11:00:00Z",
154
- messages: [
155
- {
156
- type: MessageType.MESSAGE_AI,
157
- content: "Delegating.",
158
- toolCalls: [
159
- {
160
- id: "tc_sa",
161
- name: "task",
162
- status: ToolCallStatus.TOOL_CALL_COMPLETED,
163
- },
164
- ],
165
- },
166
- ],
167
- subAgentExecutions: [
168
- {
169
- id: "tc_sa",
170
- name: "explore",
171
- subject: "Explore the repo",
172
- input: "find tests",
173
- output: "found 3",
174
- startedAt: "2026-08-20T11:00:01Z",
175
- completedAt: "2026-08-20T11:00:06Z",
176
- messages: [
177
- {
178
- type: MessageType.MESSAGE_AI,
179
- content: "Scanning.",
180
- toolCalls: [
181
- {
182
- id: "tc_sa_1",
183
- name: "grep",
184
- result: "3 matches",
185
- status: ToolCallStatus.TOOL_CALL_COMPLETED,
186
- outputRef: {
187
- // Sub-agent outputs are stored under the PARENT
188
- // execution's id — the storage key is the record of it.
189
- storageKey: "artifacts/aex_01c/toolcalls/tc_sa_1.txt",
190
- sizeBytes: 64n,
191
- mimeType: "text/plain",
192
- truncatedPreview: "3 matches…",
193
- },
194
- },
195
- ],
196
- },
197
- ],
198
- },
199
- ],
200
- },
201
- });
202
- }
203
-
204
- /** Turn 3: an in-flight Build-from-plan turn. */
205
- function exec4(): AgentExecution {
206
- return create(AgentExecutionSchema, {
207
- metadata: { id: "aex_01d" },
208
- spec: {
209
- sessionId: "ses_01",
210
- message: "Build from plan",
211
- executionConfig: { buildFromPlan: true },
212
- },
213
- status: {
214
- phase: ExecutionPhase.EXECUTION_IN_PROGRESS,
215
- startedAt: "2026-08-20T12:00:00Z",
216
- messages: [{ type: MessageType.MESSAGE_AI, content: "Working on it." }],
217
- },
218
- });
219
- }
220
-
221
- function allExecutions(): AgentExecution[] {
222
- // Deliberately scrambled: assembly must restore ULID order.
223
- return [exec3(), exec1(), exec4(), exec2()];
224
- }
225
-
226
- const RESOLVED: Record<string, ResolvedToolOutput> = {
227
- "artifacts/aex_01a/toolcalls/tc_2.txt": {
228
- storageKey: "artifacts/aex_01a/toolcalls/tc_2.txt",
229
- content: "package retry\n\nfunc Do() {}",
230
- truncated: false,
231
- totalSizeBytes: 2048,
232
- mimeType: "text/plain",
233
- isImage: false,
234
- },
235
- "artifacts/aex_01a/toolcalls/tc_3.png": {
236
- storageKey: "artifacts/aex_01a/toolcalls/tc_3.png",
237
- truncated: false,
238
- totalSizeBytes: 4096,
239
- mimeType: "image/png",
240
- isImage: true,
241
- },
242
- "artifacts/aex_01c/toolcalls/tc_sa_1.txt": {
243
- storageKey: "artifacts/aex_01c/toolcalls/tc_sa_1.txt",
244
- content: "3 matches in test/",
245
- truncated: false,
246
- totalSizeBytes: 64,
247
- mimeType: "text/plain",
248
- isImage: false,
249
- },
250
- };
251
-
252
- // ---------------------------------------------------------------------------
253
- // Assembly
254
- // ---------------------------------------------------------------------------
255
-
256
- describe("assembleSessionTranscript", () => {
257
- it("orders turns chronologically by ULID regardless of input order", () => {
258
- const t = assembleSessionTranscript(session(), allExecutions());
259
- expect(t.turns.map((x) => x.execution.metadata?.id)).toEqual([
260
- "aex_01a",
261
- "aex_01c",
262
- "aex_01d",
263
- ]);
264
- });
265
-
266
- it("excludes superseded turns by default, matching the conversation view", () => {
267
- const t = assembleSessionTranscript(session(), allExecutions());
268
- expect(
269
- t.turns.some((x) => x.execution.metadata?.id === "aex_01b"),
270
- ).toBe(false);
271
- expect(t.includesSuperseded).toBe(false);
272
- });
273
-
274
- it("keeps superseded turns, marked, when includeSuperseded is set", () => {
275
- const t = assembleSessionTranscript(session(), allExecutions(), {
276
- includeSuperseded: true,
277
- });
278
- const ids = t.turns.map((x) => x.execution.metadata?.id);
279
- expect(ids).toEqual(["aex_01a", "aex_01b", "aex_01c", "aex_01d"]);
280
- expect(t.turns.map((x) => x.superseded)).toEqual([
281
- false,
282
- true,
283
- false,
284
- false,
285
- ]);
286
- });
287
-
288
- it("synthesizes user prompts by the shared rule", () => {
289
- const t = assembleSessionTranscript(session(), allExecutions());
290
- expect(t.turns[0].userPrompt).toBe("Why is CI red?");
291
- // Build-from-plan: machine label, no user prose.
292
- expect(t.turns[2].userPrompt).toBeNull();
293
- expect(t.turns[2].isBuildFromPlan).toBe(true);
294
- });
295
-
296
- it("suppresses the 'execute' placeholder prompt", () => {
297
- const exec = create(AgentExecutionSchema, {
298
- metadata: { id: "aex_x" },
299
- spec: { sessionId: "ses_01", message: "execute" },
300
- status: { phase: ExecutionPhase.EXECUTION_COMPLETED },
301
- });
302
- const t = assembleSessionTranscript(session(), [exec]);
303
- expect(t.turns[0].userPrompt).toBeNull();
304
- expect(t.turns[0].isBuildFromPlan).toBe(false);
305
- });
306
-
307
- it("marks non-terminal executions in progress", () => {
308
- const t = assembleSessionTranscript(session(), allExecutions());
309
- expect(t.turns.map((x) => x.inProgress)).toEqual([false, false, true]);
310
- });
311
- });
312
-
313
- // ---------------------------------------------------------------------------
314
- // Offload resolution
315
- // ---------------------------------------------------------------------------
316
-
317
- type ContentByKey = Record<
318
- string,
319
- { content: string; truncated?: boolean; totalSizeBytes?: number } | Error
320
- >;
321
-
322
- function fakeArtifactClient(contentByKey: ContentByKey) {
323
- const requests: GetArtifactContentRequest[] = [];
324
- return {
325
- requests,
326
- client: {
327
- agentExecution: {
328
- listBySession: () => Promise.reject(new Error("not under test")),
329
- getArtifactContent: (input: GetArtifactContentRequest) => {
330
- requests.push(input);
331
- const entry = contentByKey[input.storageKey];
332
- if (entry === undefined) {
333
- return Promise.reject(new Error(`no such key: ${input.storageKey}`));
334
- }
335
- if (entry instanceof Error) return Promise.reject(entry);
336
- return Promise.resolve(
337
- create(GetArtifactContentResponseSchema, {
338
- content: new TextEncoder().encode(entry.content),
339
- truncated: entry.truncated ?? false,
340
- totalSizeBytes: BigInt(entry.totalSizeBytes ?? entry.content.length),
341
- }),
342
- );
343
- },
344
- },
345
- },
346
- };
347
- }
348
-
349
- describe("resolveOffloadedOutputs", () => {
350
- it("resolves parent and sub-agent refs, deriving each execution id from the storage key", async () => {
351
- const { client, requests } = fakeArtifactClient({
352
- "artifacts/aex_01a/toolcalls/tc_2.txt": { content: "full file" },
353
- "artifacts/aex_01c/toolcalls/tc_sa_1.txt": { content: "3 matches in test/" },
354
- });
355
- const resolved = await resolveOffloadedOutputs(client, allExecutions());
356
-
357
- expect(resolved["artifacts/aex_01a/toolcalls/tc_2.txt"].content).toBe(
358
- "full file",
359
- );
360
- // The sub-agent's ref (nested in exec3's sub_agent_executions) resolved
361
- // under the PARENT execution's id, taken from the key itself.
362
- const subAgentRequest = requests.find(
363
- (r) => r.storageKey === "artifacts/aex_01c/toolcalls/tc_sa_1.txt",
364
- );
365
- expect(subAgentRequest?.executionId).toBe("aex_01c");
366
- });
367
-
368
- it("never fetches image refs, but records them for the serializers", async () => {
369
- const { client, requests } = fakeArtifactClient({
370
- "artifacts/aex_01a/toolcalls/tc_2.txt": { content: "full file" },
371
- "artifacts/aex_01c/toolcalls/tc_sa_1.txt": { content: "x" },
372
- });
373
- const resolved = await resolveOffloadedOutputs(client, allExecutions());
374
-
375
- const imageKey = "artifacts/aex_01a/toolcalls/tc_3.png";
376
- expect(requests.some((r) => r.storageKey === imageKey)).toBe(false);
377
- expect(resolved[imageKey]).toMatchObject({
378
- isImage: true,
379
- mimeType: "image/png",
380
- totalSizeBytes: 4096,
381
- });
382
- });
383
-
384
- it("tolerates individual fetch failures — the rest still resolve", async () => {
385
- const { client } = fakeArtifactClient({
386
- "artifacts/aex_01a/toolcalls/tc_2.txt": new Error("storage unavailable"),
387
- "artifacts/aex_01c/toolcalls/tc_sa_1.txt": { content: "3 matches in test/" },
388
- });
389
- const resolved = await resolveOffloadedOutputs(client, allExecutions());
390
-
391
- expect(resolved["artifacts/aex_01a/toolcalls/tc_2.txt"].error).toBe(
392
- "storage unavailable",
393
- );
394
- expect(resolved["artifacts/aex_01a/toolcalls/tc_2.txt"].content).toBeUndefined();
395
- expect(
396
- resolved["artifacts/aex_01c/toolcalls/tc_sa_1.txt"].content,
397
- ).toBe("3 matches in test/");
398
- });
399
-
400
- it("carries the server's truncation flag and true size", async () => {
401
- const { client } = fakeArtifactClient({
402
- "artifacts/aex_01a/toolcalls/tc_2.txt": {
403
- content: "first half…",
404
- truncated: true,
405
- totalSizeBytes: 1048576,
406
- },
407
- "artifacts/aex_01c/toolcalls/tc_sa_1.txt": { content: "x" },
408
- });
409
- const resolved = await resolveOffloadedOutputs(client, allExecutions());
410
- expect(resolved["artifacts/aex_01a/toolcalls/tc_2.txt"]).toMatchObject({
411
- truncated: true,
412
- totalSizeBytes: 1048576,
413
- });
414
- });
415
-
416
- it("holds at most `concurrency` fetches in flight and still resolves every ref", async () => {
417
- // Six text refs on one execution, a pool of two. The fake parks every
418
- // fetch on a deferred so the in-flight count is observable, then releases
419
- // them one at a time; the pool must never exceed two and must drain all six.
420
- const keys = Array.from({ length: 6 }, (_, i) => `artifacts/aex_pool/toolcalls/tc_${i}.txt`);
421
- const execution = create(AgentExecutionSchema, {
422
- metadata: { id: "aex_pool" },
423
- status: {
424
- messages: [
425
- {
426
- type: MessageType.MESSAGE_AI,
427
- toolCalls: keys.map((storageKey, i) => ({
428
- id: `tc_${i}`,
429
- name: "read_file",
430
- status: ToolCallStatus.TOOL_CALL_COMPLETED,
431
- outputRef: { storageKey, mimeType: "text/plain" },
432
- })),
433
- },
434
- ],
435
- },
436
- });
437
-
438
- const releases: Array<() => void> = [];
439
- let inFlight = 0;
440
- let maxInFlight = 0;
441
- const client = {
442
- agentExecution: {
443
- listBySession: () => Promise.reject(new Error("not under test")),
444
- getArtifactContent: (input: GetArtifactContentRequest) => {
445
- inFlight++;
446
- maxInFlight = Math.max(maxInFlight, inFlight);
447
- return new Promise<GetArtifactContentResponse>((resolveFetch) => {
448
- releases.push(() => {
449
- inFlight--;
450
- resolveFetch(
451
- create(GetArtifactContentResponseSchema, {
452
- content: new TextEncoder().encode(input.storageKey),
453
- }),
454
- );
455
- });
456
- });
457
- },
458
- },
459
- };
460
-
461
- const resolving = resolveOffloadedOutputs(client, [execution], { concurrency: 2 });
462
- // Release the six fetches one at a time. A macrotask boundary between
463
- // releases lets the pool's microtask chain run to its next fetch, so the
464
- // observation is deterministic: no timers, no races.
465
- let released = 0;
466
- while (released < keys.length) {
467
- const release = releases.shift();
468
- if (release) {
469
- release();
470
- released++;
471
- } else {
472
- await new Promise((tick) => setTimeout(tick, 0));
473
- }
474
- }
475
- const resolved = await resolving;
476
-
477
- // Exactly two: never more (the bound holds) and never fewer (the pool is
478
- // genuinely parallel, not a serial loop wearing a `concurrency` option).
479
- expect(maxInFlight).toBe(2);
480
- for (const key of keys) {
481
- expect(resolved[key].content).toBe(key);
482
- }
483
- });
484
- });
485
-
486
- // ---------------------------------------------------------------------------
487
- // Fetch
488
- // ---------------------------------------------------------------------------
489
-
490
- describe("fetchSessionTranscript", () => {
491
- function fakeClient(overrides?: { totalPages?: number }) {
492
- const artifacts = fakeArtifactClient({
493
- "artifacts/aex_01a/toolcalls/tc_2.txt": { content: "full file" },
494
- "artifacts/aex_01c/toolcalls/tc_sa_1.txt": { content: "3 matches" },
495
- });
496
- return {
497
- session: { get: (id: string) => Promise.resolve(session()) },
498
- agentExecution: {
499
- ...artifacts.client.agentExecution,
500
- listBySession: () =>
501
- Promise.resolve(
502
- create(AgentExecutionListSchema, {
503
- totalPages: overrides?.totalPages ?? 1,
504
- entries: allExecutions(),
505
- }),
506
- ),
507
- },
508
- };
509
- }
510
-
511
- it("assembles the full transcript with outputs resolved", async () => {
512
- const t = await fetchSessionTranscript(fakeClient(), "ses_01");
513
- expect(t.turns).toHaveLength(3);
514
- expect(
515
- t.resolvedOutputs["artifacts/aex_01a/toolcalls/tc_2.txt"].content,
516
- ).toBe("full file");
517
- });
518
-
519
- it("skips output resolution when disabled", async () => {
520
- const t = await fetchSessionTranscript(fakeClient(), "ses_01", {
521
- resolveOutputs: false,
522
- });
523
- expect(Object.keys(t.resolvedOutputs)).toHaveLength(0);
524
- });
525
-
526
- it("refuses to export a silently truncated conversation if the server ever paginates", async () => {
527
- await expect(
528
- fetchSessionTranscript(fakeClient({ totalPages: 2 }), "ses_01"),
529
- ).rejects.toThrow(/2 pages .* single page/s);
530
- });
531
- });
532
-
533
- // ---------------------------------------------------------------------------
534
- // Markdown
535
- // ---------------------------------------------------------------------------
536
-
537
- describe("transcriptToMarkdown", () => {
538
- it("matches the pinned format contract (transcript.golden.md)", () => {
539
- const t = assembleSessionTranscript(session(), allExecutions(), {
540
- resolvedOutputs: RESOLVED,
541
- });
542
- const goldenPath = resolve(here, "transcript.golden.md");
543
- const actual = transcriptToMarkdown(t);
544
- if (process.env.UPDATE_TRANSCRIPT_GOLDEN) {
545
- writeFileSync(goldenPath, actual);
546
- }
547
- expect(actual).toBe(readFileSync(goldenPath, "utf8"));
548
- });
549
-
550
- it("stamps the export time only when provided", () => {
551
- const t = assembleSessionTranscript(session(), [exec1()]);
552
- expect(transcriptToMarkdown(t)).not.toContain("Exported:");
553
- expect(
554
- transcriptToMarkdown(t, { generatedAt: "2026-08-22T06:00:00Z" }),
555
- ).toContain("- Exported: 2026-08-22T06:00:00Z");
556
- });
557
-
558
- it("falls back to the ref's preview, with an honest note, when an output is unresolved", () => {
559
- const t = assembleSessionTranscript(session(), [exec1()]);
560
- const md = transcriptToMarkdown(t);
561
- expect(md).toContain("_Offloaded output not resolved — showing preview._");
562
- expect(md).toContain("package retry…");
563
- });
564
-
565
- it("notes the fetch failure when resolution was attempted and failed", () => {
566
- const t = assembleSessionTranscript(session(), [exec1()], {
567
- resolvedOutputs: {
568
- "artifacts/aex_01a/toolcalls/tc_2.txt": {
569
- storageKey: "artifacts/aex_01a/toolcalls/tc_2.txt",
570
- truncated: false,
571
- mimeType: "text/plain",
572
- isImage: false,
573
- error: "storage unavailable",
574
- },
575
- },
576
- });
577
- expect(transcriptToMarkdown(t)).toContain(
578
- "_Offloaded output unavailable (storage unavailable) — showing preview._",
579
- );
580
- });
581
-
582
- it("marks server-truncated outputs with the byte counts", () => {
583
- const t = assembleSessionTranscript(session(), [exec1()], {
584
- resolvedOutputs: {
585
- "artifacts/aex_01a/toolcalls/tc_2.txt": {
586
- storageKey: "artifacts/aex_01a/toolcalls/tc_2.txt",
587
- content: "0123456789",
588
- truncated: true,
589
- totalSizeBytes: 1048576,
590
- mimeType: "text/plain",
591
- isImage: false,
592
- },
593
- },
594
- });
595
- expect(transcriptToMarkdown(t)).toContain(
596
- "_Output truncated at 10 of 1048576 bytes (server content cap)._",
597
- );
598
- });
599
-
600
- it("sizes fences past backtick runs in the content", () => {
601
- const exec = create(AgentExecutionSchema, {
602
- metadata: { id: "aex_x" },
603
- spec: { sessionId: "ses_01", message: "prompt" },
604
- status: {
605
- phase: ExecutionPhase.EXECUTION_COMPLETED,
606
- messages: [
607
- {
608
- type: MessageType.MESSAGE_AI,
609
- content: "",
610
- toolCalls: [
611
- {
612
- id: "tc",
613
- name: "shell_command",
614
- result: "a fence: ```md\ninside\n```",
615
- status: ToolCallStatus.TOOL_CALL_COMPLETED,
616
- },
617
- ],
618
- },
619
- ],
620
- },
621
- });
622
- const md = transcriptToMarkdown(
623
- assembleSessionTranscript(session(), [exec]),
624
- );
625
- expect(md).toContain("````\na fence: ```md\ninside\n```\n````");
626
- });
627
-
628
- it("marks kept superseded turns", () => {
629
- const t = assembleSessionTranscript(session(), allExecutions(), {
630
- includeSuperseded: true,
631
- });
632
- const md = transcriptToMarkdown(t);
633
- expect(md).toContain("- Includes superseded (edited-and-resubmitted) turns");
634
- expect(md).toContain("_Superseded by an edited resubmission._");
635
- expect(md).toContain("old prompt");
636
- });
637
- });
638
-
639
- // ---------------------------------------------------------------------------
640
- // JSON
641
- // ---------------------------------------------------------------------------
642
-
643
- describe("transcriptToJson", () => {
644
- it("is JSON.stringify-safe despite bigint proto fields (protojson contract)", () => {
645
- const t = assembleSessionTranscript(session(), allExecutions(), {
646
- resolvedOutputs: RESOLVED,
647
- });
648
- // sizeBytes is int64 → bigint on the proto; a raw stringify of the
649
- // transcript would throw. The projection must not.
650
- const text = JSON.stringify(transcriptToJson(t), null, 2);
651
- const parsed = JSON.parse(text);
652
- expect(parsed.format).toBe("stigmer.ai/session-transcript/v1");
653
- expect(parsed.session.metadata.id).toBe("ses_01");
654
- expect(parsed.turns).toHaveLength(3);
655
- // protojson: snake_case field names, int64 as string.
656
- expect(
657
- parsed.turns[0].execution.status.messages[3].tool_calls[0].output_ref
658
- .size_bytes,
659
- ).toBe("2048");
660
- });
661
-
662
- it("carries the canonical-rule verdicts per turn", () => {
663
- const t = assembleSessionTranscript(session(), allExecutions(), {
664
- includeSuperseded: true,
665
- });
666
- const parsed = JSON.parse(JSON.stringify(transcriptToJson(t)));
667
- expect(parsed.includes_superseded).toBe(true);
668
- expect(parsed.turns[0].user_prompt).toBe("Why is CI red?");
669
- expect(parsed.turns[1].superseded).toBe(true);
670
- expect(parsed.turns[3].build_from_plan).toBe(true);
671
- expect(parsed.turns[3].in_progress).toBe(true);
672
- });
673
-
674
- it("strips the internal Temporal callback token from execution status", () => {
675
- const exec = exec1();
676
- exec.status!.callbackToken = new TextEncoder().encode("task-token");
677
- const t = assembleSessionTranscript(session(), [exec]);
678
- const parsed = JSON.parse(JSON.stringify(transcriptToJson(t)));
679
- expect(parsed.turns[0].execution.status.callback_token).toBeUndefined();
680
- // The strip is surgical — the rest of status is intact.
681
- expect(parsed.turns[0].execution.status.messages).toHaveLength(5);
682
- });
683
-
684
- it("keys resolved outputs by storage key with plain-JSON fields", () => {
685
- const t = assembleSessionTranscript(session(), allExecutions(), {
686
- resolvedOutputs: RESOLVED,
687
- });
688
- const parsed = JSON.parse(JSON.stringify(transcriptToJson(t)));
689
- expect(
690
- parsed.resolved_outputs["artifacts/aex_01a/toolcalls/tc_2.txt"],
691
- ).toMatchObject({
692
- content: "package retry\n\nfunc Do() {}",
693
- mime_type: "text/plain",
694
- total_size_bytes: 2048,
695
- });
696
- });
697
- });