primitive-admin 1.2.0-alpha.0 → 1.2.0-alpha.10

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 (412) hide show
  1. package/README.md +108 -136
  2. package/assets/skill/skills/primitive-platform/SKILL.md +37 -4
  3. package/dist/bin/primitive.js +30 -35
  4. package/dist/bin/primitive.js.map +1 -1
  5. package/dist/src/commands/agent-sessions.d.ts +133 -0
  6. package/dist/src/commands/agent-sessions.js +792 -0
  7. package/dist/src/commands/agent-sessions.js.map +1 -0
  8. package/dist/src/commands/analytics.js +0 -148
  9. package/dist/src/commands/analytics.js.map +1 -1
  10. package/dist/src/commands/apps-children.d.ts +54 -0
  11. package/dist/src/commands/apps-children.js +631 -0
  12. package/dist/src/commands/apps-children.js.map +1 -0
  13. package/dist/src/commands/apps.d.ts +6 -0
  14. package/dist/src/commands/apps.js +131 -9
  15. package/dist/src/commands/apps.js.map +1 -1
  16. package/dist/src/commands/auth-sessions.d.ts +3 -3
  17. package/dist/src/commands/auth-sessions.js +117 -23
  18. package/dist/src/commands/auth-sessions.js.map +1 -1
  19. package/dist/src/commands/auth.js +460 -36
  20. package/dist/src/commands/auth.js.map +1 -1
  21. package/dist/src/commands/collections.js +316 -256
  22. package/dist/src/commands/collections.js.map +1 -1
  23. package/dist/src/commands/config.d.ts +1 -1
  24. package/dist/src/commands/config.js +60 -28
  25. package/dist/src/commands/config.js.map +1 -1
  26. package/dist/src/commands/connections.js +12 -17
  27. package/dist/src/commands/connections.js.map +1 -1
  28. package/dist/src/commands/database-type-configs.js +2 -76
  29. package/dist/src/commands/database-type-configs.js.map +1 -1
  30. package/dist/src/commands/databases.d.ts +9 -0
  31. package/dist/src/commands/databases.js +228 -566
  32. package/dist/src/commands/databases.js.map +1 -1
  33. package/dist/src/commands/db3-types.d.ts +15 -0
  34. package/dist/src/commands/db3-types.js +157 -0
  35. package/dist/src/commands/db3-types.js.map +1 -0
  36. package/dist/src/commands/db3.d.ts +12 -0
  37. package/dist/src/commands/db3.js +1052 -0
  38. package/dist/src/commands/db3.js.map +1 -0
  39. package/dist/src/commands/documents.d.ts +121 -2
  40. package/dist/src/commands/documents.js +1601 -1251
  41. package/dist/src/commands/documents.js.map +1 -1
  42. package/dist/src/commands/env.d.ts +9 -1
  43. package/dist/src/commands/env.js +164 -49
  44. package/dist/src/commands/env.js.map +1 -1
  45. package/dist/src/commands/function-trigger-commands.d.ts +28 -0
  46. package/dist/src/commands/function-trigger-commands.js +341 -0
  47. package/dist/src/commands/function-trigger-commands.js.map +1 -0
  48. package/dist/src/commands/functions.js +297 -24
  49. package/dist/src/commands/functions.js.map +1 -1
  50. package/dist/src/commands/groups.js +150 -49
  51. package/dist/src/commands/groups.js.map +1 -1
  52. package/dist/src/commands/guides.js +5 -5
  53. package/dist/src/commands/init.d.ts +7 -0
  54. package/dist/src/commands/init.js +23 -5
  55. package/dist/src/commands/init.js.map +1 -1
  56. package/dist/src/commands/integrations.js +14 -8
  57. package/dist/src/commands/integrations.js.map +1 -1
  58. package/dist/src/commands/metadata-category-configs.d.ts +2 -2
  59. package/dist/src/commands/metadata-category-configs.js +2 -2
  60. package/dist/src/commands/prompts.d.ts +7 -0
  61. package/dist/src/commands/prompts.js +48 -5
  62. package/dist/src/commands/prompts.js.map +1 -1
  63. package/dist/src/commands/scripts.d.ts +9 -17
  64. package/dist/src/commands/scripts.js +24 -479
  65. package/dist/src/commands/scripts.js.map +1 -1
  66. package/dist/src/commands/sessions.js +3 -8
  67. package/dist/src/commands/sessions.js.map +1 -1
  68. package/dist/src/commands/sync-app-settings.d.ts +36 -8
  69. package/dist/src/commands/sync-app-settings.js +109 -23
  70. package/dist/src/commands/sync-app-settings.js.map +1 -1
  71. package/dist/src/commands/sync.d.ts +436 -613
  72. package/dist/src/commands/sync.js +2604 -5977
  73. package/dist/src/commands/sync.js.map +1 -1
  74. package/dist/src/commands/tokens.js +4 -9
  75. package/dist/src/commands/tokens.js.map +1 -1
  76. package/dist/src/commands/users.js +77 -2
  77. package/dist/src/commands/users.js.map +1 -1
  78. package/dist/src/commands/workflows.d.ts +5 -83
  79. package/dist/src/commands/workflows.js +57 -2282
  80. package/dist/src/commands/workflows.js.map +1 -1
  81. package/dist/src/lib/aggregate-output.d.ts +25 -0
  82. package/dist/src/lib/aggregate-output.js +53 -0
  83. package/dist/src/lib/aggregate-output.js.map +1 -0
  84. package/dist/src/lib/api-client.d.ts +681 -581
  85. package/dist/src/lib/api-client.js +880 -851
  86. package/dist/src/lib/api-client.js.map +1 -1
  87. package/dist/src/lib/app-settings-descriptor.d.ts +47 -1
  88. package/dist/src/lib/app-settings-descriptor.js +114 -10
  89. package/dist/src/lib/app-settings-descriptor.js.map +1 -1
  90. package/dist/src/lib/auth-fixtures.d.ts +44 -0
  91. package/dist/src/lib/auth-fixtures.js +61 -0
  92. package/dist/src/lib/auth-fixtures.js.map +1 -0
  93. package/dist/src/lib/auth-flow.d.ts +41 -1
  94. package/dist/src/lib/auth-flow.js +70 -16
  95. package/dist/src/lib/auth-flow.js.map +1 -1
  96. package/dist/src/lib/block-layout.d.ts +12 -23
  97. package/dist/src/lib/block-layout.js +26 -92
  98. package/dist/src/lib/block-layout.js.map +1 -1
  99. package/dist/src/lib/block-selector.d.ts +2 -2
  100. package/dist/src/lib/block-selector.js +2 -2
  101. package/dist/src/lib/child-apps-local.d.ts +164 -0
  102. package/dist/src/lib/child-apps-local.js +258 -0
  103. package/dist/src/lib/child-apps-local.js.map +1 -0
  104. package/dist/src/lib/ci-session-request.d.ts +22 -0
  105. package/dist/src/lib/ci-session-request.js +51 -0
  106. package/dist/src/lib/ci-session-request.js.map +1 -0
  107. package/dist/src/lib/codegen-shared/generatedFiles.d.ts +10 -8
  108. package/dist/src/lib/codegen-shared/generatedFiles.js +21 -15
  109. package/dist/src/lib/codegen-shared/generatedFiles.js.map +1 -1
  110. package/dist/src/lib/codegen-shared/prettierStable.d.ts +1 -1
  111. package/dist/src/lib/codegen-shared/prettierStable.js +1 -1
  112. package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.d.ts +2 -2
  113. package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.js +2 -2
  114. package/dist/src/lib/collection-export.d.ts +76 -15
  115. package/dist/src/lib/collection-export.js +116 -23
  116. package/dist/src/lib/collection-export.js.map +1 -1
  117. package/dist/src/lib/collection-principal.d.ts +22 -0
  118. package/dist/src/lib/collection-principal.js +35 -0
  119. package/dist/src/lib/collection-principal.js.map +1 -0
  120. package/dist/src/lib/config-object-descriptor.d.ts +3 -22
  121. package/dist/src/lib/config-object-descriptor.js +56 -291
  122. package/dist/src/lib/config-object-descriptor.js.map +1 -1
  123. package/dist/src/lib/config-payload.js +2 -3
  124. package/dist/src/lib/config-payload.js.map +1 -1
  125. package/dist/src/lib/config-surface.d.ts +5 -7
  126. package/dist/src/lib/config-surface.js +18 -40
  127. package/dist/src/lib/config-surface.js.map +1 -1
  128. package/dist/src/lib/connections-list.d.ts +10 -0
  129. package/dist/src/lib/connections-list.js +18 -0
  130. package/dist/src/lib/connections-list.js.map +1 -0
  131. package/dist/src/lib/credentials-home.d.ts +58 -0
  132. package/dist/src/lib/credentials-home.js +204 -0
  133. package/dist/src/lib/credentials-home.js.map +1 -0
  134. package/dist/src/lib/credentials-lock.d.ts +88 -0
  135. package/dist/src/lib/credentials-lock.js +302 -0
  136. package/dist/src/lib/credentials-lock.js.map +1 -0
  137. package/dist/src/lib/credentials-store.d.ts +179 -24
  138. package/dist/src/lib/credentials-store.js +712 -77
  139. package/dist/src/lib/credentials-store.js.map +1 -1
  140. package/dist/src/lib/csv.d.ts +8 -9
  141. package/dist/src/lib/csv.js +3 -4
  142. package/dist/src/lib/csv.js.map +1 -1
  143. package/dist/src/lib/custodian.d.ts +8 -0
  144. package/dist/src/lib/custodian.js +18 -0
  145. package/dist/src/lib/custodian.js.map +1 -0
  146. package/dist/src/lib/db-codegen/dbGenerator.js +5 -16
  147. package/dist/src/lib/db-codegen/dbGenerator.js.map +1 -1
  148. package/dist/src/lib/db-codegen/dbNaming.d.ts +5 -13
  149. package/dist/src/lib/db-codegen/dbNaming.js +5 -17
  150. package/dist/src/lib/db-codegen/dbNaming.js.map +1 -1
  151. package/dist/src/lib/db-codegen/dbTemplates.d.ts +7 -56
  152. package/dist/src/lib/db-codegen/dbTemplates.js +25 -125
  153. package/dist/src/lib/db-codegen/dbTemplates.js.map +1 -1
  154. package/dist/src/lib/db-codegen/dbTsTypes.d.ts +2 -2
  155. package/dist/src/lib/db-codegen/dbTsTypes.js +2 -2
  156. package/dist/src/lib/db-codegen/dbTypeIR.d.ts +67 -2
  157. package/dist/src/lib/db-codegen/dbTypeIR.js +13 -2
  158. package/dist/src/lib/db-codegen/dbTypeIR.js.map +1 -1
  159. package/dist/src/lib/db3-export.d.ts +231 -0
  160. package/dist/src/lib/db3-export.js +510 -0
  161. package/dist/src/lib/db3-export.js.map +1 -0
  162. package/dist/src/lib/db3-index-output.d.ts +27 -0
  163. package/dist/src/lib/db3-index-output.js +49 -0
  164. package/dist/src/lib/db3-index-output.js.map +1 -0
  165. package/dist/src/lib/document-export-lookups.d.ts +31 -0
  166. package/dist/src/lib/document-export-lookups.js +53 -0
  167. package/dist/src/lib/document-export-lookups.js.map +1 -0
  168. package/dist/src/lib/document-export-permissions.d.ts +7 -5
  169. package/dist/src/lib/document-export-permissions.js +7 -5
  170. package/dist/src/lib/document-export-permissions.js.map +1 -1
  171. package/dist/src/lib/document-export-record-log.d.ts +57 -0
  172. package/dist/src/lib/document-export-record-log.js +215 -0
  173. package/dist/src/lib/document-export-record-log.js.map +1 -0
  174. package/dist/src/lib/document-ingest-artifact.d.ts +26 -2
  175. package/dist/src/lib/document-ingest-artifact.js +42 -8
  176. package/dist/src/lib/document-ingest-artifact.js.map +1 -1
  177. package/dist/src/lib/document-ingest-format2.d.ts +36 -0
  178. package/dist/src/lib/document-ingest-format2.js +78 -0
  179. package/dist/src/lib/document-ingest-format2.js.map +1 -0
  180. package/dist/src/lib/document-ingest-input.d.ts +9 -0
  181. package/dist/src/lib/document-ingest-input.js +28 -1
  182. package/dist/src/lib/document-ingest-input.js.map +1 -1
  183. package/dist/src/lib/document-ingest-rows.d.ts +16 -0
  184. package/dist/src/lib/document-ingest-rows.js +17 -0
  185. package/dist/src/lib/document-ingest-rows.js.map +1 -1
  186. package/dist/src/lib/document-ingest.d.ts +33 -1
  187. package/dist/src/lib/document-ingest.js +49 -0
  188. package/dist/src/lib/document-ingest.js.map +1 -1
  189. package/dist/src/lib/document-schema-rows.d.ts +42 -0
  190. package/dist/src/lib/document-schema-rows.js +53 -0
  191. package/dist/src/lib/document-schema-rows.js.map +1 -0
  192. package/dist/src/lib/env-resolver-core.d.ts +70 -2
  193. package/dist/src/lib/env-resolver-core.js +137 -20
  194. package/dist/src/lib/env-resolver-core.js.map +1 -1
  195. package/dist/src/lib/env-resolver.d.ts +14 -2
  196. package/dist/src/lib/env-resolver.js +32 -10
  197. package/dist/src/lib/env-resolver.js.map +1 -1
  198. package/dist/src/lib/function-authorize-check.d.ts +142 -0
  199. package/dist/src/lib/function-authorize-check.js +310 -0
  200. package/dist/src/lib/function-authorize-check.js.map +1 -0
  201. package/dist/src/lib/function-authorize-view.d.ts +15 -0
  202. package/dist/src/lib/function-authorize-view.js +50 -0
  203. package/dist/src/lib/function-authorize-view.js.map +1 -0
  204. package/dist/src/lib/function-bundle.d.ts +38 -18
  205. package/dist/src/lib/function-bundle.js +96 -35
  206. package/dist/src/lib/function-bundle.js.map +1 -1
  207. package/dist/src/lib/function-collect.d.ts +75 -12
  208. package/dist/src/lib/function-collect.js +427 -12
  209. package/dist/src/lib/function-collect.js.map +1 -1
  210. package/dist/src/lib/function-db-types.d.ts +29 -0
  211. package/dist/src/lib/function-db-types.js +117 -7
  212. package/dist/src/lib/function-db-types.js.map +1 -1
  213. package/dist/src/lib/function-document-types.d.ts +5 -3
  214. package/dist/src/lib/function-document-types.js +10 -14
  215. package/dist/src/lib/function-document-types.js.map +1 -1
  216. package/dist/src/lib/function-lint.d.ts +34 -0
  217. package/dist/src/lib/function-lint.js +112 -0
  218. package/dist/src/lib/function-lint.js.map +1 -0
  219. package/dist/src/lib/function-log-row.js +21 -2
  220. package/dist/src/lib/function-log-row.js.map +1 -1
  221. package/dist/src/lib/function-run.d.ts +16 -21
  222. package/dist/src/lib/function-run.js +37 -30
  223. package/dist/src/lib/function-run.js.map +1 -1
  224. package/dist/src/lib/function-schema-codegen.d.ts +1 -1
  225. package/dist/src/lib/function-schema-codegen.js +5 -5
  226. package/dist/src/lib/function-schema-codegen.js.map +1 -1
  227. package/dist/src/lib/function-source-roots.d.ts +67 -0
  228. package/dist/src/lib/function-source-roots.js +148 -0
  229. package/dist/src/lib/function-source-roots.js.map +1 -0
  230. package/dist/src/lib/function-sync.d.ts +108 -22
  231. package/dist/src/lib/function-sync.js +127 -39
  232. package/dist/src/lib/function-sync.js.map +1 -1
  233. package/dist/src/lib/function-trigger-listing.d.ts +11 -6
  234. package/dist/src/lib/function-trigger-listing.js +32 -11
  235. package/dist/src/lib/function-trigger-listing.js.map +1 -1
  236. package/dist/src/lib/function-typecheck.d.ts +37 -2
  237. package/dist/src/lib/function-typecheck.js +210 -28
  238. package/dist/src/lib/function-typecheck.js.map +1 -1
  239. package/dist/src/lib/function-versions.d.ts +2 -0
  240. package/dist/src/lib/function-versions.js +1 -0
  241. package/dist/src/lib/function-versions.js.map +1 -1
  242. package/dist/src/lib/generated-allowlist.js +0 -20
  243. package/dist/src/lib/generated-allowlist.js.map +1 -1
  244. package/dist/src/lib/generated-config-surfaces.d.ts +703 -201
  245. package/dist/src/lib/generated-config-surfaces.js +2335 -2033
  246. package/dist/src/lib/generated-config-surfaces.js.map +1 -1
  247. package/dist/src/lib/generated-sdk-types.d.ts +1 -1
  248. package/dist/src/lib/generated-sdk-types.js +1 -1
  249. package/dist/src/lib/generated-sdk-types.js.map +1 -1
  250. package/dist/src/lib/init-adopt.js +12 -3
  251. package/dist/src/lib/init-adopt.js.map +1 -1
  252. package/dist/src/lib/init-login-note.d.ts +13 -0
  253. package/dist/src/lib/init-login-note.js +22 -0
  254. package/dist/src/lib/init-login-note.js.map +1 -0
  255. package/dist/src/lib/json-value.d.ts +6 -0
  256. package/dist/src/lib/json-value.js +13 -0
  257. package/dist/src/lib/json-value.js.map +1 -0
  258. package/dist/src/lib/load-routes.d.ts +33 -0
  259. package/dist/src/lib/load-routes.js +35 -0
  260. package/dist/src/lib/load-routes.js.map +1 -0
  261. package/dist/src/lib/local-state.d.ts +38 -7
  262. package/dist/src/lib/local-state.js +172 -49
  263. package/dist/src/lib/local-state.js.map +1 -1
  264. package/dist/src/lib/local-test-cases.d.ts +5 -2
  265. package/dist/src/lib/local-test-cases.js +7 -4
  266. package/dist/src/lib/local-test-cases.js.map +1 -1
  267. package/dist/src/lib/log-inspection.d.ts +42 -4
  268. package/dist/src/lib/log-inspection.js +37 -5
  269. package/dist/src/lib/log-inspection.js.map +1 -1
  270. package/dist/src/lib/login-exchange-check.d.ts +18 -0
  271. package/dist/src/lib/login-exchange-check.js +27 -0
  272. package/dist/src/lib/login-exchange-check.js.map +1 -0
  273. package/dist/src/lib/login-scope-lines.d.ts +25 -0
  274. package/dist/src/lib/login-scope-lines.js +45 -0
  275. package/dist/src/lib/login-scope-lines.js.map +1 -0
  276. package/dist/src/lib/logout-admin-session.d.ts +2 -1
  277. package/dist/src/lib/logout-admin-session.js +7 -1
  278. package/dist/src/lib/logout-admin-session.js.map +1 -1
  279. package/dist/src/lib/object-status-filter.d.ts +9 -1
  280. package/dist/src/lib/object-status-filter.js +9 -1
  281. package/dist/src/lib/object-status-filter.js.map +1 -1
  282. package/dist/src/lib/output.js +2 -0
  283. package/dist/src/lib/output.js.map +1 -1
  284. package/dist/src/lib/paginate.d.ts +0 -5
  285. package/dist/src/lib/paginate.js +0 -5
  286. package/dist/src/lib/paginate.js.map +1 -1
  287. package/dist/src/lib/pin-refusal-hint.d.ts +12 -0
  288. package/dist/src/lib/pin-refusal-hint.js +35 -0
  289. package/dist/src/lib/pin-refusal-hint.js.map +1 -0
  290. package/dist/src/lib/primitive-env-plugin.d.ts +99 -0
  291. package/dist/src/lib/primitive-env-plugin.js +408 -0
  292. package/dist/src/lib/primitive-env-plugin.js.map +1 -0
  293. package/dist/src/lib/project-config.d.ts +7 -0
  294. package/dist/src/lib/project-config.js +22 -1
  295. package/dist/src/lib/project-config.js.map +1 -1
  296. package/dist/src/lib/project-login-apps.d.ts +8 -0
  297. package/dist/src/lib/project-login-apps.js +27 -0
  298. package/dist/src/lib/project-login-apps.js.map +1 -0
  299. package/dist/src/lib/prompt-schema-codegen.d.ts +10 -3
  300. package/dist/src/lib/prompt-schema-codegen.js +52 -11
  301. package/dist/src/lib/prompt-schema-codegen.js.map +1 -1
  302. package/dist/src/lib/pull-write.d.ts +31 -0
  303. package/dist/src/lib/pull-write.js +49 -0
  304. package/dist/src/lib/pull-write.js.map +1 -0
  305. package/dist/src/lib/push-failure-report.d.ts +45 -0
  306. package/dist/src/lib/push-failure-report.js +57 -0
  307. package/dist/src/lib/push-failure-report.js.map +1 -0
  308. package/dist/src/lib/records-verbs.d.ts +69 -0
  309. package/dist/src/lib/records-verbs.js +40 -0
  310. package/dist/src/lib/records-verbs.js.map +1 -0
  311. package/dist/src/lib/refresh-admin-credentials.d.ts +7 -0
  312. package/dist/src/lib/refresh-admin-credentials.js +16 -4
  313. package/dist/src/lib/refresh-admin-credentials.js.map +1 -1
  314. package/dist/src/lib/root-import-decision.d.ts +65 -0
  315. package/dist/src/lib/root-import-decision.js +109 -0
  316. package/dist/src/lib/root-import-decision.js.map +1 -0
  317. package/dist/src/lib/run-status.d.ts +1 -1
  318. package/dist/src/lib/run-status.generated.d.ts +2 -2
  319. package/dist/src/lib/run-status.generated.js +3 -1
  320. package/dist/src/lib/run-status.generated.js.map +1 -1
  321. package/dist/src/lib/run-status.js +1 -1
  322. package/dist/src/lib/schema-codegen/generated-schema-descriptor.d.ts +129 -0
  323. package/dist/src/lib/schema-codegen/generated-schema-descriptor.js +269 -0
  324. package/dist/src/lib/schema-codegen/generated-schema-descriptor.js.map +1 -0
  325. package/dist/src/lib/schema-codegen/naming.d.ts +35 -0
  326. package/dist/src/lib/schema-codegen/naming.js +83 -0
  327. package/dist/src/lib/schema-codegen/naming.js.map +1 -0
  328. package/dist/src/lib/schema-codegen/schemaToTs.d.ts +82 -0
  329. package/dist/src/lib/schema-codegen/schemaToTs.js +305 -0
  330. package/dist/src/lib/schema-codegen/schemaToTs.js.map +1 -0
  331. package/dist/src/lib/scope-request.d.ts +84 -0
  332. package/dist/src/lib/scope-request.js +235 -0
  333. package/dist/src/lib/scope-request.js.map +1 -0
  334. package/dist/src/lib/session-id.d.ts +9 -0
  335. package/dist/src/lib/session-id.js +28 -0
  336. package/dist/src/lib/session-id.js.map +1 -0
  337. package/dist/src/lib/snapshot-build-rows.d.ts +21 -0
  338. package/dist/src/lib/snapshot-build-rows.js +22 -0
  339. package/dist/src/lib/snapshot-build-rows.js.map +1 -1
  340. package/dist/src/lib/snapshot-build.js +8 -3
  341. package/dist/src/lib/snapshot-build.js.map +1 -1
  342. package/dist/src/lib/snapshots.d.ts +17 -1
  343. package/dist/src/lib/snapshots.js +50 -2
  344. package/dist/src/lib/snapshots.js.map +1 -1
  345. package/dist/src/lib/swift-codegen/agentGenerator.d.ts +6 -2
  346. package/dist/src/lib/swift-codegen/agentGenerator.js +57 -5
  347. package/dist/src/lib/swift-codegen/agentGenerator.js.map +1 -1
  348. package/dist/src/lib/swift-codegen/banners.d.ts +34 -7
  349. package/dist/src/lib/swift-codegen/banners.js +37 -7
  350. package/dist/src/lib/swift-codegen/banners.js.map +1 -1
  351. package/dist/src/lib/swift-codegen/dbGenerator.d.ts +4 -3
  352. package/dist/src/lib/swift-codegen/dbGenerator.js +14 -117
  353. package/dist/src/lib/swift-codegen/dbGenerator.js.map +1 -1
  354. package/dist/src/lib/swift-codegen/functionGenerator.d.ts +3 -3
  355. package/dist/src/lib/swift-codegen/functionGenerator.js +23 -18
  356. package/dist/src/lib/swift-codegen/functionGenerator.js.map +1 -1
  357. package/dist/src/lib/swift-codegen/generator.d.ts +5 -5
  358. package/dist/src/lib/swift-codegen/generator.js +35 -40
  359. package/dist/src/lib/swift-codegen/generator.js.map +1 -1
  360. package/dist/src/lib/swift-codegen/schemaToSwift.d.ts +3 -3
  361. package/dist/src/lib/swift-codegen/schemaToSwift.js +4 -4
  362. package/dist/src/lib/swift-codegen/schemaToSwift.js.map +1 -1
  363. package/dist/src/lib/swift-codegen/swiftKeys.d.ts +19 -0
  364. package/dist/src/lib/swift-codegen/swiftKeys.js +31 -0
  365. package/dist/src/lib/swift-codegen/swiftKeys.js.map +1 -0
  366. package/dist/src/lib/sync-paths.d.ts +35 -0
  367. package/dist/src/lib/sync-paths.js +57 -5
  368. package/dist/src/lib/sync-paths.js.map +1 -1
  369. package/dist/src/lib/sync-resource-types.d.ts +26 -26
  370. package/dist/src/lib/sync-resource-types.js +61 -189
  371. package/dist/src/lib/sync-resource-types.js.map +1 -1
  372. package/dist/src/lib/sync-selectors.d.ts +5 -1
  373. package/dist/src/lib/sync-selectors.js +23 -13
  374. package/dist/src/lib/sync-selectors.js.map +1 -1
  375. package/dist/src/lib/test-case-file-names.d.ts +3 -5
  376. package/dist/src/lib/test-case-file-names.js +3 -5
  377. package/dist/src/lib/test-case-file-names.js.map +1 -1
  378. package/dist/src/lib/toml-database-config.d.ts +15 -75
  379. package/dist/src/lib/toml-database-config.js +17 -306
  380. package/dist/src/lib/toml-database-config.js.map +1 -1
  381. package/dist/src/lib/transient-retry.d.ts +43 -0
  382. package/dist/src/lib/transient-retry.js +94 -0
  383. package/dist/src/lib/transient-retry.js.map +1 -0
  384. package/dist/src/lib/vars-override.d.ts +105 -0
  385. package/dist/src/lib/vars-override.js +143 -0
  386. package/dist/src/lib/vars-override.js.map +1 -0
  387. package/dist/src/lib/webhook-capture.d.ts +43 -0
  388. package/dist/src/lib/webhook-capture.js +91 -0
  389. package/dist/src/lib/webhook-capture.js.map +1 -0
  390. package/dist/src/lib/webhook-deliver.d.ts +18 -20
  391. package/dist/src/lib/webhook-deliver.js +34 -89
  392. package/dist/src/lib/webhook-deliver.js.map +1 -1
  393. package/dist/src/lib/webhook-test-run.d.ts +32 -0
  394. package/dist/src/lib/webhook-test-run.js +108 -0
  395. package/dist/src/lib/webhook-test-run.js.map +1 -0
  396. package/dist/src/lib/workflow-codegen/generator.d.ts +7 -7
  397. package/dist/src/lib/workflow-codegen/generator.js +16 -23
  398. package/dist/src/lib/workflow-codegen/generator.js.map +1 -1
  399. package/dist/src/lib/workflow-codegen/invokerIR.d.ts +6 -12
  400. package/dist/src/lib/workflow-codegen/invokerIR.js +4 -5
  401. package/dist/src/lib/workflow-codegen/invokerIR.js.map +1 -1
  402. package/dist/src/lib/workflow-toml-validator.d.ts +2 -0
  403. package/dist/src/lib/workflow-toml-validator.js +28 -1
  404. package/dist/src/lib/workflow-toml-validator.js.map +1 -1
  405. package/dist/src/types/index.d.ts +30 -37
  406. package/dist/src/validators.d.ts +7 -55
  407. package/dist/src/validators.js +7 -53
  408. package/dist/src/validators.js.map +1 -1
  409. package/dist/src/vite.d.ts +17 -0
  410. package/dist/src/vite.js +18 -0
  411. package/dist/src/vite.js.map +1 -0
  412. package/package.json +20 -12
@@ -0,0 +1,792 @@
1
+ import { createHash } from "crypto";
2
+ import { readFileSync, writeFileSync } from "fs";
3
+ import { basename, resolve as resolvePath } from "path";
4
+ import { lookup as mimeLookup } from "mime-types";
5
+ import { ulid } from "ulid";
6
+ import { ApiClient } from "../lib/api-client.js";
7
+ import { resolveAppId } from "../lib/config.js";
8
+ import { error, formatDate, formatDuration, formatTable, info, json, keyValue, result, success, } from "../lib/output.js";
9
+ import { confirmPrompt } from "../lib/confirm-prompt.js";
10
+ import { pageCursorOption, pageLimitOption, parsePageLimit, printEmptyPage, printPageHint, } from "../lib/list-options.js";
11
+ import { normalizeCliListEnvelope } from "../lib/paginate.js";
12
+ import { describeRecordsFailure } from "./documents.js";
13
+ /**
14
+ * `primitive agent-sessions` — inspect and delete agent sessions (#3809,
15
+ * design-docs/agents.md §D7). A data noun: `list` one user's sessions, `get`
16
+ * one session's binding, status, active turn and — for app owners and admins —
17
+ * the session object's state, and `delete` a session with its document.
18
+ * `transcript`, `steps` and `artifacts` read the conversation's rows by
19
+ * session ID, and `upload` and `download` move a session's files (#4589);
20
+ * none takes a document ID. The rows never hold the system prompt or a
21
+ * turn's context, so those stay visible only through `get` to app owners and
22
+ * admins. `primitive sessions` is sign-in sessions.
23
+ */
24
+ /** The `object` keys `get` prints as sections; any other key is printed as JSON. */
25
+ const OBJECT_SECTIONS = new Set([
26
+ "pending",
27
+ "deletedAt",
28
+ "initializing",
29
+ "turn",
30
+ "lastTurn",
31
+ "queue",
32
+ "leaseUntil",
33
+ "alarmAt",
34
+ "calls",
35
+ ]);
36
+ const ROWS_NOTE = `
37
+ The conversation itself (messages, parts, steps) lives in the session's
38
+ document. Read it by session ID with:
39
+ $ primitive agent-sessions transcript <session-id>
40
+ $ primitive agent-sessions steps <session-id>
41
+ $ primitive agent-sessions artifacts <session-id>
42
+ or as raw rows, by the session's document ID:
43
+ $ primitive documents records query <document-id> PrimitiveMessage
44
+ $ primitive documents records query <document-id> PrimitivePart
45
+ $ primitive documents records query <document-id> PrimitiveStep
46
+ $ primitive documents records query <document-id> PrimitiveSession
47
+ `;
48
+ /** Who `transcript`, `steps` and `artifacts` answer: the session document's own readers. */
49
+ const READERS_NOTE = `The rows are read under the session document's own permissions: every
50
+ member of the session reads them, and so does a console admin of the app. An
51
+ app owner or admin who is not in the session can \`get\` it but is refused
52
+ here (403) unless granted the document.
53
+ `;
54
+ const list = (values) => Array.isArray(values) && values.length > 0 ? values.map(String).join(", ") : "-";
55
+ /**
56
+ * Delete one agent session: confirm unless `yes`, then one `DELETE`. Answers
57
+ * whether it was deleted or the prompt was declined; a refusal throws (the
58
+ * prompt's non-TTY refusal included, before any request).
59
+ */
60
+ export async function deleteAgentSessionAction(options, deps) {
61
+ if (!options.yes) {
62
+ const ok = await deps.confirm(`Delete agent session ${options.sessionId} and its document? This cannot be undone.`);
63
+ if (!ok)
64
+ return "cancelled";
65
+ }
66
+ const answer = await deps.client.deleteAgentSession(options.appId, options.sessionId);
67
+ deps.print(options.json ? JSON.stringify(answer, null, 2) : `Agent session ${options.sessionId} deleted.`);
68
+ return "deleted";
69
+ }
70
+ /** The active turn, as `get` prints it. */
71
+ function printTurn(turn) {
72
+ if (!turn) {
73
+ result("Turn", "none");
74
+ return;
75
+ }
76
+ result("Turn", turn.turnId);
77
+ result(" Phase", turn.phase);
78
+ result(" Rounds", turn.rounds);
79
+ result(" Initiator", turn.initiatorUserId);
80
+ result(" Started", turn.startedAt ? formatDate(turn.startedAt) : null);
81
+ result(" Answered by", turn.answeredBy);
82
+ if (turn.pause) {
83
+ result(" Waiting on", `${list(turn.pause.callIds)} (until ${formatDate(turn.pause.expiresAt)})`);
84
+ }
85
+ if (turn.pending)
86
+ result(" Pending", turn.pending.kind);
87
+ }
88
+ /** The session object's state, for app owners and admins. */
89
+ function printObject(object) {
90
+ console.log("");
91
+ console.log("Session object");
92
+ result("Deleted at", object.deletedAt ? formatDate(object.deletedAt) : null);
93
+ result("Initializing", object.initializing ? formatDate(object.initializing) : null);
94
+ result("Pending changes", Array.isArray(object.pending) ? object.pending.length : 0);
95
+ const queue = Array.isArray(object.queue) ? object.queue : [];
96
+ result("Queue", queue.length > 0
97
+ ? queue
98
+ .map((entry) => {
99
+ const count = Array.isArray(entry?.messageIds) ? entry.messageIds.length : 0;
100
+ return `${entry?.userId} (${count} message${count === 1 ? "" : "s"})`;
101
+ })
102
+ .join(", ")
103
+ : "empty");
104
+ result("Lease until", object.leaseUntil ? formatDate(object.leaseUntil) : null);
105
+ result("Alarm at", object.alarmAt ? formatDate(object.alarmAt) : null);
106
+ const last = object.lastTurn;
107
+ if (last) {
108
+ result("Last turn", last.turnId);
109
+ result(" Outcome", `${last.outcome}${last.code ? ` (${last.code})` : ""}`);
110
+ result(" Started", last.startedAt ? formatDate(last.startedAt) : null);
111
+ result(" Ended", last.endedAt ? formatDate(last.endedAt) : null);
112
+ result(" Rounds", last.rounds);
113
+ }
114
+ else {
115
+ result("Last turn", "none");
116
+ }
117
+ const calls = Array.isArray(object.calls) ? object.calls : [];
118
+ if (calls.length > 0) {
119
+ console.log("");
120
+ console.log(formatTable(calls.map((call) => ({ ...call, endedBy: call.endedBy ?? (call.discarded ? "discarded" : "-") })), [
121
+ { header: "CALL", key: "callId" },
122
+ { header: "TOOL", key: "toolName" },
123
+ { header: "STATE", key: "state" },
124
+ { header: "ATTEMPTS", key: "attempts" },
125
+ { header: "ENDED BY", key: "endedBy" },
126
+ ]));
127
+ }
128
+ // The configuration pinned at the active turn's start, else the last turn's.
129
+ const pinned = object.turn ?? last;
130
+ if (typeof pinned?.systemPrompt === "string") {
131
+ console.log("");
132
+ console.log("Pinned system prompt:");
133
+ console.log(pinned.systemPrompt);
134
+ }
135
+ if (Array.isArray(pinned?.tools) && pinned.tools.length > 0) {
136
+ console.log("");
137
+ console.log("Pinned tools:");
138
+ for (const tool of pinned.tools) {
139
+ const how = [tool.runs, tool.runs === "server" ? tool.invoke ?? "request" : undefined].filter(Boolean).join(", ");
140
+ console.log(` ${tool.name}${how ? ` (${how})` : ""}`);
141
+ }
142
+ }
143
+ // Keys this CLI does not know yet, as they came.
144
+ for (const [key, value] of Object.entries(object)) {
145
+ if (OBJECT_SECTIONS.has(key))
146
+ continue;
147
+ console.log("");
148
+ console.log(`${key}:`);
149
+ console.log(JSON.stringify(value, null, 2));
150
+ }
151
+ }
152
+ /** A part's JSON columns: stored as text, printed as the values they hold. */
153
+ const PART_JSON_COLUMNS = ["input", "output", "artifact", "providerMetadata", "data"];
154
+ /** A step's JSON columns. */
155
+ const STEP_JSON_COLUMNS = ["historySelection"];
156
+ /** At most this many message ids in one parts filter: the records route's `$in` cap. */
157
+ export const PARTS_BATCH_SIZE = 1000;
158
+ /**
159
+ * At most this many bytes of encoded filter in one parts request. The filter
160
+ * rides in the query string and Cloudflare refuses a URL over 16 KB, so this
161
+ * leaves room for the path, the sort, the limit and a continuation cursor.
162
+ */
163
+ export const PARTS_FILTER_MAX_BYTES = 8 * 1024;
164
+ /** Parts asked for per request: the records route's maximum `limit`. */
165
+ const PARTS_PAGE_LIMIT = 10_000;
166
+ /** The most parts requests one transcript page makes before it fails. */
167
+ export const MAX_PARTS_REQUESTS = 64;
168
+ /**
169
+ * A session row with its JSON columns decoded from their stored text. A
170
+ * column whose text is not JSON is left as that text.
171
+ */
172
+ export function decodeSessionRow(row, columns = PART_JSON_COLUMNS) {
173
+ const decoded = { ...row };
174
+ for (const column of columns) {
175
+ const text = decoded[column];
176
+ if (typeof text !== "string")
177
+ continue;
178
+ try {
179
+ decoded[column] = JSON.parse(text);
180
+ }
181
+ catch {
182
+ // Not JSON: kept as it came.
183
+ }
184
+ }
185
+ return decoded;
186
+ }
187
+ /** A text's length once encoded into the query string, as the api client sends it. */
188
+ const queryBytes = (text) => new URLSearchParams({ q: text }).toString().length - "q=".length;
189
+ /** The parts filter around its ids, `{"messageId":{"$in":[]}}`, encoded. */
190
+ const PARTS_FILTER_FRAME_BYTES = queryBytes(JSON.stringify({ messageId: { $in: [] } }));
191
+ const ID_SEPARATOR_BYTES = queryBytes(",");
192
+ /**
193
+ * Message ids in order, in batches one parts filter can carry: at most
194
+ * `maxIds` ids (the `$in` cap) and at most `maxFilterBytes` of encoded filter
195
+ * (the URL budget). An id too long for the budget alone gets a batch of its own.
196
+ */
197
+ export function batchMessageIds(ids, { maxIds = PARTS_BATCH_SIZE, maxFilterBytes = PARTS_FILTER_MAX_BYTES } = {}) {
198
+ const batches = [];
199
+ let batch = [];
200
+ let bytes = PARTS_FILTER_FRAME_BYTES;
201
+ for (const id of ids) {
202
+ const idBytes = queryBytes(JSON.stringify(id));
203
+ if (batch.length > 0 && (batch.length >= maxIds || bytes + ID_SEPARATOR_BYTES + idBytes > maxFilterBytes)) {
204
+ batches.push(batch);
205
+ batch = [];
206
+ bytes = PARTS_FILTER_FRAME_BYTES;
207
+ }
208
+ bytes += (batch.length > 0 ? ID_SEPARATOR_BYTES : 0) + idBytes;
209
+ batch.push(id);
210
+ }
211
+ if (batch.length > 0)
212
+ batches.push(batch);
213
+ return batches;
214
+ }
215
+ /**
216
+ * The page's messages in their order, each with a `parts` array of its parts
217
+ * by `seq`, whatever order the parts arrived in.
218
+ */
219
+ export function joinTranscriptPage(messages, parts) {
220
+ const byMessage = new Map();
221
+ for (const part of parts) {
222
+ const own = byMessage.get(part.messageId);
223
+ if (own)
224
+ own.push(part);
225
+ else
226
+ byMessage.set(part.messageId, [part]);
227
+ }
228
+ return messages.map((message) => ({
229
+ ...message,
230
+ parts: [...(byMessage.get(message.id) ?? [])].sort((a, b) => Number(a.seq) - Number(b.seq)),
231
+ }));
232
+ }
233
+ /** Where a tool call's artifact lives: on a blob, inline on the row, or nowhere. */
234
+ export function artifactOf(part) {
235
+ if (typeof part.artifactBlobId === "string" && part.artifactBlobId) {
236
+ return { kind: "blob", blobId: part.artifactBlobId };
237
+ }
238
+ if (part.artifact !== undefined && part.artifact !== null)
239
+ return { kind: "inline", value: part.artifact };
240
+ return { kind: "none" };
241
+ }
242
+ function artifactLabel(part) {
243
+ const artifact = artifactOf(part);
244
+ return artifact.kind === "blob" ? `blob ${artifact.blobId}` : artifact.kind === "inline" ? "inline" : "-";
245
+ }
246
+ /** A decoded value on one line: text as it is, anything else as compact JSON. */
247
+ const compact = (value) => (typeof value === "string" ? value : JSON.stringify(value));
248
+ const present = (value) => value !== undefined && value !== null && value !== "";
249
+ function formatPart(part) {
250
+ switch (part.kind) {
251
+ case "text":
252
+ case "reasoning":
253
+ return [` [${part.kind}] ${String(part.text ?? "").replace(/\n/g, "\n ")}`];
254
+ case "tool_call": {
255
+ const lines = [` [tool_call] ${part.toolName} (${part.toolCallId}) ${part.state}`];
256
+ if (present(part.input))
257
+ lines.push(` input: ${compact(part.input)}`);
258
+ if (present(part.output))
259
+ lines.push(` output: ${compact(part.output)}`);
260
+ if (artifactOf(part).kind !== "none")
261
+ lines.push(` artifact: ${artifactLabel(part)}`);
262
+ if (present(part.errorCode) || present(part.errorText)) {
263
+ lines.push(` error: ${[part.errorCode, part.errorText].filter(present).join(" ")}`);
264
+ }
265
+ return lines;
266
+ }
267
+ case "file":
268
+ return [` [file] ${part.filename} ${part.mediaType} ${part.sizeBytes} bytes blob ${part.blobId}`];
269
+ case "event":
270
+ return [` [event] ${part.eventKind}${present(part.data) ? ` ${compact(part.data)}` : ""}`];
271
+ default:
272
+ // A kind this CLI does not know yet, as it came.
273
+ return [` [${part.kind}] ${JSON.stringify(part)}`];
274
+ }
275
+ }
276
+ /** One transcript message as `transcript` prints it: a header, then a line per part. */
277
+ export function formatTranscriptMessage(message) {
278
+ const header = [
279
+ `#${message.seq}`,
280
+ message.authorKind,
281
+ message.authorUserId,
282
+ formatDate(message.createdAt),
283
+ message.turnId ? `turn ${message.turnId}` : undefined,
284
+ ]
285
+ .filter(present)
286
+ .join(" ");
287
+ return [header, ...(Array.isArray(message.parts) ? message.parts : []).flatMap(formatPart)];
288
+ }
289
+ async function sessionDocumentId(client, appId, sessionId) {
290
+ const session = await client.getAgentSession(appId, sessionId);
291
+ return session.documentId;
292
+ }
293
+ function envelopeOf(page, items) {
294
+ return { items, hasMore: page.hasMore, ...(page.nextCursor ? { nextCursor: page.nextCursor } : {}) };
295
+ }
296
+ /**
297
+ * One page of a session's conversation, oldest first: the session's messages
298
+ * by `seq`, each with every one of its parts. The parts are read in batches
299
+ * of message ids, each followed through its cursor, so a printed message is
300
+ * never missing a part; a page that needs more than `MAX_PARTS_REQUESTS`
301
+ * parts requests fails instead.
302
+ */
303
+ export async function transcriptAction(options, client) {
304
+ const documentId = await sessionDocumentId(client, options.appId, options.sessionId);
305
+ const page = await client.queryDocumentRecords(options.appId, documentId, "PrimitiveMessage", {
306
+ ...(options.turnId ? { filter: { turnId: options.turnId } } : {}),
307
+ sort: { seq: 1 },
308
+ limit: options.limit,
309
+ cursor: options.cursor,
310
+ });
311
+ const ids = page.items.map((message) => message.id);
312
+ const parts = [];
313
+ let requests = 0;
314
+ for (const batch of batchMessageIds(ids)) {
315
+ let cursor;
316
+ do {
317
+ if (requests >= MAX_PARTS_REQUESTS) {
318
+ throw new Error(`Transcript page too large to assemble (${ids.length} messages, more than ${MAX_PARTS_REQUESTS} parts requests); use a smaller --limit.`);
319
+ }
320
+ requests++;
321
+ const answer = await client.queryDocumentRecords(options.appId, documentId, "PrimitivePart", {
322
+ filter: { messageId: { $in: batch } },
323
+ sort: { seq: 1 },
324
+ limit: PARTS_PAGE_LIMIT,
325
+ cursor,
326
+ });
327
+ parts.push(...answer.items.map((part) => decodeSessionRow(part)));
328
+ cursor = answer.hasMore ? answer.nextCursor : undefined;
329
+ } while (cursor);
330
+ }
331
+ return envelopeOf(page, joinTranscriptPage(page.items, parts));
332
+ }
333
+ /** One page of a session's steps, oldest first. */
334
+ async function stepsAction(options, client) {
335
+ const documentId = await sessionDocumentId(client, options.appId, options.sessionId);
336
+ const page = await client.queryDocumentRecords(options.appId, documentId, "PrimitiveStep", {
337
+ ...(options.turnId ? { filter: { turnId: options.turnId } } : {}),
338
+ sort: { startedAt: 1 },
339
+ limit: options.limit,
340
+ cursor: options.cursor,
341
+ });
342
+ return envelopeOf(page, page.items.map((step) => decodeSessionRow(step, STEP_JSON_COLUMNS)));
343
+ }
344
+ /** One page of a session's tool calls, oldest first. */
345
+ async function toolCallsAction(options, client) {
346
+ const documentId = await sessionDocumentId(client, options.appId, options.sessionId);
347
+ const page = await client.queryDocumentRecords(options.appId, documentId, "PrimitivePart", {
348
+ filter: { kind: "tool_call" },
349
+ sort: { createdAt: 1 },
350
+ limit: options.limit,
351
+ cursor: options.cursor,
352
+ });
353
+ return envelopeOf(page, page.items.map((part) => decodeSessionRow(part)));
354
+ }
355
+ /**
356
+ * One tool call's artifact: `found: false` when the session has no tool call
357
+ * part by that id, else its value — read from the session's attachment when
358
+ * the artifact is a blob, `null` when the call has none.
359
+ */
360
+ export async function readArtifactAction(options, client) {
361
+ const documentId = await sessionDocumentId(client, options.appId, options.sessionId);
362
+ const page = await client.queryDocumentRecords(options.appId, documentId, "PrimitivePart", {
363
+ filter: { id: options.partId, kind: "tool_call" },
364
+ limit: 1,
365
+ });
366
+ const [part] = page.items;
367
+ if (!part)
368
+ return { found: false };
369
+ const artifact = artifactOf(decodeSessionRow(part));
370
+ if (artifact.kind === "none")
371
+ return { found: true, value: null };
372
+ if (artifact.kind === "inline")
373
+ return { found: true, value: artifact.value };
374
+ const bytes = await client.downloadAgentSessionAttachment(options.appId, options.sessionId, artifact.blobId);
375
+ return { found: true, value: JSON.parse(bytes.toString("utf8")) };
376
+ }
377
+ /**
378
+ * Upload one file to a session: read it, then one `PUT` on the session's
379
+ * attachment route with the size and base64 SHA-256 the route checks. The
380
+ * blob ID defaults to a fresh ULID, the filename to the file's basename and
381
+ * the content type to the filename's MIME type. An unreadable file fails
382
+ * before any request.
383
+ */
384
+ export async function uploadAttachmentAction(options, client) {
385
+ let data;
386
+ try {
387
+ data = readFileSync(resolvePath(options.filePath));
388
+ }
389
+ catch (err) {
390
+ throw new Error(`Failed to read file: ${err?.message ?? String(err)}`);
391
+ }
392
+ const blobId = options.blobId || ulid();
393
+ const filename = options.filename || basename(options.filePath) || "upload";
394
+ const contentType = options.contentType || mimeLookup(filename) || "application/octet-stream";
395
+ const sha256 = createHash("sha256").update(data).digest("base64");
396
+ const answer = await client.uploadAgentSessionAttachment(options.appId, options.sessionId, blobId, data, {
397
+ filename,
398
+ contentType,
399
+ sha256,
400
+ });
401
+ return { answer, blobId, filename, contentType, numBytes: data.length };
402
+ }
403
+ /**
404
+ * Download one of a session's files: the bytes go to `output` with a success
405
+ * line, or to stdout alone. A refusal throws with nothing written.
406
+ */
407
+ export async function downloadAttachmentAction(options, deps) {
408
+ const data = await deps.client.downloadAgentSessionAttachment(options.appId, options.sessionId, options.blobId);
409
+ if (options.output) {
410
+ deps.writeFile(resolvePath(options.output), data);
411
+ deps.print(`Downloaded to ${options.output} (${data.length} bytes)`);
412
+ }
413
+ else {
414
+ deps.writeStdout(data);
415
+ }
416
+ return data;
417
+ }
418
+ /** The step table's display row. */
419
+ function stepCells(step) {
420
+ const providerModel = [step.provider, step.model].filter(present).join("/");
421
+ return {
422
+ ...step,
423
+ providerModel: providerModel || step.toolName || step.functionName || "-",
424
+ tokens: present(step.totalTokens) ? step.totalTokens : "-",
425
+ costCell: present(step.cost) ? step.cost : "-",
426
+ errorCell: step.errorCode || "-",
427
+ };
428
+ }
429
+ export function registerAgentSessionsCommands(program) {
430
+ const agentSessions = program
431
+ .command("agent-sessions")
432
+ .description("Inspect agent sessions, read their conversations, move their files, and delete them")
433
+ .addHelpText("after", `
434
+ An agent session is one conversation with an agent, created by a server
435
+ function (ctx.agents.createSession). App owners and admins list any user's
436
+ sessions, get any session — including the session object's state: each
437
+ turn's pinned system prompt and tools, the queue and the call ledger — and
438
+ delete any session. Members read their own sessions' transcript, steps and
439
+ artifacts, and the owner and participants upload files to them. This is not
440
+ \`primitive sessions\`, which lists sign-in sessions.
441
+ ${ROWS_NOTE}
442
+ Examples:
443
+ $ primitive agent-sessions list --user-id 01HXY...
444
+ $ primitive agent-sessions list --user-id 01HXY... --agent advisor --json
445
+ $ primitive agent-sessions get 01HXZ...
446
+ $ primitive agent-sessions transcript 01HXZ... --limit 20
447
+ $ primitive agent-sessions steps 01HXZ... --turn 01HXT...
448
+ $ primitive agent-sessions artifacts 01HXZ...
449
+ $ primitive agent-sessions artifacts 01HXZ... 01HXP... --json
450
+ $ primitive agent-sessions upload 01HXZ... ./receipt.png
451
+ $ primitive agent-sessions download 01HXZ... 01HXB... --output ./receipt.png
452
+ $ primitive agent-sessions delete 01HXZ... --yes
453
+ `);
454
+ agentSessions
455
+ .command("list")
456
+ .description("List one user's agent sessions, newest first")
457
+ .option("--app <app-id>", "App ID (uses current app if not specified)")
458
+ // Required, but checked in the action (the `sessions list` precedent).
459
+ .option("--user-id <user-id>", "List sessions this user owns or belongs to")
460
+ .option("--agent <key>", "Only this agent's sessions")
461
+ .option("--scope <scope>", "Only sessions created with exactly this scope")
462
+ .addOption(pageLimitOption())
463
+ .addOption(pageCursorOption())
464
+ .option("--json", "Output as JSON")
465
+ .action(async (options) => {
466
+ const userId = options.userId;
467
+ if (!userId) {
468
+ error("required option '--user-id <user-id>' not specified");
469
+ process.exit(1);
470
+ }
471
+ const limit = parsePageLimit(options.limit);
472
+ const resolvedAppId = resolveAppId(undefined, options);
473
+ const client = new ApiClient();
474
+ try {
475
+ const page = normalizeCliListEnvelope(await client.listAgentSessions(resolvedAppId, {
476
+ userId,
477
+ agent: options.agent,
478
+ scope: options.scope,
479
+ limit,
480
+ cursor: options.cursor,
481
+ }));
482
+ if (options.json) {
483
+ json(page);
484
+ return;
485
+ }
486
+ if (page.items.length === 0) {
487
+ printEmptyPage(page, "agent sessions");
488
+ return;
489
+ }
490
+ console.log(formatTable(page.items, [
491
+ { header: "SESSION", key: "sessionId" },
492
+ { header: "AGENT", key: "agentKey" },
493
+ { header: "SCOPE", key: "scope" },
494
+ { header: "ROLE", key: "role" },
495
+ { header: "TITLE", key: "title", flex: true },
496
+ // The listed user's unread dot (#4256): activity they have not marked read.
497
+ { header: "UNREAD", key: "hasUnread", format: (value) => (value === true ? "•" : "-") },
498
+ { header: "LAST ACTIVITY", key: "lastActivityAt", format: formatDate },
499
+ { header: "DOCUMENT", key: "documentId" },
500
+ ]));
501
+ printPageHint(page);
502
+ }
503
+ catch (err) {
504
+ error(describeRecordsFailure(err));
505
+ process.exit(1);
506
+ }
507
+ });
508
+ agentSessions
509
+ .command("get")
510
+ .description("Show an agent session: its binding, status, members, active turn and object state")
511
+ .argument("<session-id>", "Session ID")
512
+ .option("--app <app-id>", "App ID (uses current app if not specified)")
513
+ .option("--json", "Output the server's answer as JSON")
514
+ .addHelpText("after", `
515
+ App owners and admins also see the session object's state: the active and
516
+ last turn with the system prompt and tools pinned at the turn's start, the
517
+ queue, the lease, the next alarm and the server tool calls (never their
518
+ input). Keys this CLI does not know are printed as JSON.
519
+ ${ROWS_NOTE}`)
520
+ .action(async (sessionId, options) => {
521
+ const resolvedAppId = resolveAppId(undefined, options);
522
+ const client = new ApiClient();
523
+ try {
524
+ const session = await client.getAgentSession(resolvedAppId, sessionId);
525
+ if (options.json) {
526
+ json(session);
527
+ return;
528
+ }
529
+ result("Session ID", session.sessionId);
530
+ result("Agent", session.agentKey);
531
+ result("Document ID", session.documentId);
532
+ result("Owner", session.ownerUserId);
533
+ result("Created", formatDate(session.createdAt));
534
+ result("Status", session.status);
535
+ result("Title", session.title);
536
+ result("Scope", session.scope);
537
+ result("Last activity", session.lastActivityAt ? formatDate(session.lastActivityAt) : null);
538
+ result("Unread", session.hasUnread === true ? "yes" : "no");
539
+ result("Last read", session.lastReadAt ? formatDate(session.lastReadAt) : null);
540
+ result("Viewers", list(session.members?.viewers));
541
+ result("Participants", list(session.members?.participants));
542
+ result("Your role", session.role);
543
+ printTurn(session.turn);
544
+ if (session.object && typeof session.object === "object")
545
+ printObject(session.object);
546
+ }
547
+ catch (err) {
548
+ error(describeRecordsFailure(err));
549
+ process.exit(1);
550
+ }
551
+ });
552
+ agentSessions
553
+ .command("transcript")
554
+ .description("Show one page of a session's conversation: its messages, oldest first, with their parts")
555
+ .argument("<session-id>", "Session ID")
556
+ .option("--app <app-id>", "App ID (uses current app if not specified)")
557
+ .option("--turn <turn-id>", "Only this turn's messages")
558
+ .addOption(pageLimitOption())
559
+ .addOption(pageCursorOption())
560
+ .option("--json", "Output as JSON")
561
+ .addHelpText("after", `
562
+ Each message prints with its parts: text, reasoning, tool calls (input, output
563
+ and where the artifact lives), files and events. --json prints the one list
564
+ envelope, each message with a \`parts\` array and the JSON columns decoded.
565
+
566
+ ${READERS_NOTE}`)
567
+ .action(async (sessionId, options) => {
568
+ const limit = parsePageLimit(options.limit);
569
+ const resolvedAppId = resolveAppId(undefined, options);
570
+ try {
571
+ const page = await transcriptAction({ appId: resolvedAppId, sessionId, limit, cursor: options.cursor, turnId: options.turn }, new ApiClient());
572
+ if (options.json) {
573
+ json(page);
574
+ return;
575
+ }
576
+ if (page.items.length === 0) {
577
+ printEmptyPage(page, "messages");
578
+ return;
579
+ }
580
+ for (const message of page.items)
581
+ console.log(formatTranscriptMessage(message).join("\n"));
582
+ printPageHint(page);
583
+ }
584
+ catch (err) {
585
+ error(describeRecordsFailure(err));
586
+ process.exit(1);
587
+ }
588
+ });
589
+ agentSessions
590
+ .command("steps")
591
+ .description("Show one page of a session's turn steps, oldest first: model, tool, context and history calls")
592
+ .argument("<session-id>", "Session ID")
593
+ .option("--app <app-id>", "App ID (uses current app if not specified)")
594
+ .option("--turn <turn-id>", "Only this turn's steps")
595
+ .addOption(pageLimitOption())
596
+ .addOption(pageCursorOption())
597
+ .option("--json", "Output as JSON")
598
+ .addHelpText("after", `\n${READERS_NOTE}`)
599
+ .action(async (sessionId, options) => {
600
+ const limit = parsePageLimit(options.limit);
601
+ const resolvedAppId = resolveAppId(undefined, options);
602
+ try {
603
+ const page = await stepsAction({ appId: resolvedAppId, sessionId, limit, cursor: options.cursor, turnId: options.turn }, new ApiClient());
604
+ if (options.json) {
605
+ json(page);
606
+ return;
607
+ }
608
+ if (page.items.length === 0) {
609
+ printEmptyPage(page, "steps");
610
+ return;
611
+ }
612
+ console.log(formatTable(page.items.map(stepCells), [
613
+ { header: "TURN", key: "turnId" },
614
+ { header: "SEQ", key: "seq" },
615
+ { header: "KIND", key: "kind" },
616
+ { header: "STATUS", key: "status" },
617
+ { header: "STARTED", key: "startedAt", format: formatDate },
618
+ { header: "DURATION", key: "durationMs", format: formatDuration },
619
+ { header: "PROVIDER/MODEL", key: "providerModel" },
620
+ { header: "TOKENS", key: "tokens" },
621
+ { header: "COST", key: "costCell" },
622
+ { header: "ERROR", key: "errorCell" },
623
+ ]));
624
+ printPageHint(page);
625
+ }
626
+ catch (err) {
627
+ error(describeRecordsFailure(err));
628
+ process.exit(1);
629
+ }
630
+ });
631
+ agentSessions
632
+ .command("artifacts")
633
+ .description("List a session's tool calls and where their artifacts live, or print one call's artifact")
634
+ .argument("<session-id>", "Session ID")
635
+ .argument("[part-id]", "A tool call's part ID: print its artifact")
636
+ .option("--app <app-id>", "App ID (uses current app if not specified)")
637
+ .addOption(pageLimitOption())
638
+ .addOption(pageCursorOption())
639
+ .option("--json", "Output as JSON")
640
+ .addHelpText("after", `
641
+ Without a part ID, one page of the session's tool calls, oldest first; the
642
+ ARTIFACT column says whether each artifact is inline, on a blob, or absent.
643
+ With a part ID (the PART column), the artifact's value as JSON, read from the
644
+ session's attachments when it is a blob.
645
+
646
+ ${READERS_NOTE}`)
647
+ .action(async (sessionId, partId, options) => {
648
+ const resolvedAppId = resolveAppId(undefined, options);
649
+ if (partId !== undefined) {
650
+ try {
651
+ const read = await readArtifactAction({ appId: resolvedAppId, sessionId, partId }, new ApiClient());
652
+ if (!read.found) {
653
+ error(`No tool call part ${partId} in session ${sessionId}`);
654
+ process.exit(1);
655
+ }
656
+ if (read.value === null && !options.json) {
657
+ info("This call has no artifact.");
658
+ return;
659
+ }
660
+ json(read.value);
661
+ }
662
+ catch (err) {
663
+ error(describeRecordsFailure(err));
664
+ process.exit(1);
665
+ }
666
+ return;
667
+ }
668
+ const limit = parsePageLimit(options.limit);
669
+ try {
670
+ const page = await toolCallsAction({ appId: resolvedAppId, sessionId, limit, cursor: options.cursor }, new ApiClient());
671
+ if (options.json) {
672
+ json(page);
673
+ return;
674
+ }
675
+ if (page.items.length === 0) {
676
+ printEmptyPage(page, "tool calls");
677
+ return;
678
+ }
679
+ console.log(formatTable(page.items.map((part) => ({ ...part, artifactCell: artifactLabel(part) })), [
680
+ { header: "PART", key: "id" },
681
+ { header: "CALL", key: "toolCallId" },
682
+ { header: "TOOL", key: "toolName" },
683
+ { header: "STATE", key: "state" },
684
+ { header: "MESSAGE", key: "messageId" },
685
+ { header: "ARTIFACT", key: "artifactCell" },
686
+ ]));
687
+ printPageHint(page);
688
+ }
689
+ catch (err) {
690
+ error(describeRecordsFailure(err));
691
+ process.exit(1);
692
+ }
693
+ });
694
+ agentSessions
695
+ .command("upload")
696
+ .description("Upload a file to a session, for a message to reference")
697
+ .argument("<session-id>", "Session ID")
698
+ .argument("<file-path>", "Path to the file to upload")
699
+ .option("--app <app-id>", "App ID (uses current app if not specified)")
700
+ .option("--blob-id <id>", "Blob ID to upload under (a new ULID if not specified)")
701
+ .option("--filename <name>", "Filename to store (the file's own name if not specified)")
702
+ .option("--content-type <type>", "Content type (from the filename's extension if not specified)")
703
+ .option("--json", "Output the server's answer as JSON")
704
+ .addHelpText("after", `
705
+ The session's owner and participants upload. Uploading the same bytes under
706
+ the same blob ID again succeeds without sending them; different bytes under
707
+ an existing ID are refused. A message carries the file by its blob ID.
708
+ `)
709
+ .action(async (sessionId, filePath, options) => {
710
+ const resolvedAppId = resolveAppId(undefined, options);
711
+ try {
712
+ const done = await uploadAttachmentAction({
713
+ appId: resolvedAppId,
714
+ sessionId,
715
+ filePath,
716
+ blobId: options.blobId,
717
+ filename: options.filename,
718
+ contentType: options.contentType,
719
+ }, new ApiClient());
720
+ if (options.json) {
721
+ json(done.answer);
722
+ return;
723
+ }
724
+ const blobId = done.answer?.blobId ?? done.blobId;
725
+ const filename = done.answer?.filename ?? done.filename;
726
+ success(`${done.answer?.bytesTransferred === 0 ? "Already uploaded" : "Uploaded"} ${filename} to session ${sessionId}.`);
727
+ keyValue("Blob ID", blobId);
728
+ keyValue("Filename", filename);
729
+ keyValue("Content Type", done.answer?.contentType ?? done.contentType);
730
+ keyValue("Size", `${done.answer?.numBytes ?? done.numBytes} bytes`);
731
+ info(`Reference it in a message as files: [{ blobId: "${blobId}" }].`);
732
+ }
733
+ catch (err) {
734
+ error(describeRecordsFailure(err));
735
+ process.exit(1);
736
+ }
737
+ });
738
+ agentSessions
739
+ .command("download")
740
+ .description("Download one of a session's files: an upload or a tool call's artifact blob")
741
+ .argument("<session-id>", "Session ID")
742
+ .argument("<blob-id>", "Blob ID")
743
+ .option("--app <app-id>", "App ID (uses current app if not specified)")
744
+ .option("--output <path>", "Output file path (defaults to stdout)")
745
+ .addHelpText("after", `
746
+ Every member of the session and every app owner and admin downloads. Without
747
+ --output the bytes are written to stdout unchanged.
748
+ `)
749
+ .action(async (sessionId, blobId, options) => {
750
+ const resolvedAppId = resolveAppId(undefined, options);
751
+ try {
752
+ await downloadAttachmentAction({ appId: resolvedAppId, sessionId, blobId, output: options.output }, {
753
+ client: new ApiClient(),
754
+ writeFile: (path, data) => writeFileSync(path, data),
755
+ writeStdout: (data) => process.stdout.write(data),
756
+ print: success,
757
+ });
758
+ }
759
+ catch (err) {
760
+ error(describeRecordsFailure(err));
761
+ process.exit(1);
762
+ }
763
+ });
764
+ agentSessions
765
+ .command("delete")
766
+ .description("Delete an agent session and its document")
767
+ .argument("<session-id>", "Session ID")
768
+ .option("--app <app-id>", "App ID (uses current app if not specified)")
769
+ .option("-y, --yes", "Skip confirmation prompt")
770
+ .option("--json", "Output as JSON")
771
+ .addHelpText("after", `
772
+ The session's owner, app owners and admins delete; the document and its rows
773
+ go with it. Deleting a session that is already deleted succeeds again.
774
+ `)
775
+ .action(async (sessionId, options) => {
776
+ const resolvedAppId = resolveAppId(undefined, options);
777
+ try {
778
+ const outcome = await deleteAgentSessionAction({ appId: resolvedAppId, sessionId, yes: options.yes === true, json: options.json === true }, {
779
+ client: new ApiClient(),
780
+ confirm: confirmPrompt,
781
+ print: (line) => (options.json ? console.log(line) : success(line)),
782
+ });
783
+ if (outcome === "cancelled")
784
+ info("Cancelled.");
785
+ }
786
+ catch (err) {
787
+ error(describeRecordsFailure(err));
788
+ process.exit(1);
789
+ }
790
+ });
791
+ }
792
+ //# sourceMappingURL=agent-sessions.js.map