dexto 1.14.6 → 2.0.0-beta.1

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 (297) hide show
  1. package/dist/agents/coding-agent/coding-agent.yml +0 -2
  2. package/dist/cli/agent-audit.d.ts +12 -0
  3. package/dist/cli/agent-audit.d.ts.map +1 -0
  4. package/dist/cli/agent-audit.js +52 -0
  5. package/dist/cli/auth/billing.d.ts +0 -6
  6. package/dist/cli/auth/billing.d.ts.map +1 -1
  7. package/dist/cli/auth/billing.js +0 -23
  8. package/dist/cli/auth/constants.d.ts +3 -31
  9. package/dist/cli/auth/constants.d.ts.map +1 -1
  10. package/dist/cli/auth/constants.js +9 -33
  11. package/dist/cli/auth/index.d.ts +2 -9
  12. package/dist/cli/auth/index.d.ts.map +1 -1
  13. package/dist/cli/auth/index.js +2 -7
  14. package/dist/cli/auth/sign-in-runtime.d.ts +12 -0
  15. package/dist/cli/auth/sign-in-runtime.d.ts.map +1 -0
  16. package/dist/cli/auth/sign-in-runtime.js +59 -0
  17. package/dist/cli/cloud/app-scopes.d.ts +4 -0
  18. package/dist/cli/cloud/app-scopes.d.ts.map +1 -0
  19. package/dist/cli/cloud/app-scopes.js +19 -0
  20. package/dist/cli/cloud/command.d.ts +107 -0
  21. package/dist/cli/cloud/command.d.ts.map +1 -0
  22. package/dist/cli/cloud/command.js +154 -0
  23. package/dist/cli/cloud/commands/account.d.ts +11 -0
  24. package/dist/cli/cloud/commands/account.d.ts.map +1 -0
  25. package/dist/cli/cloud/commands/account.js +129 -0
  26. package/dist/cli/cloud/commands/agents.d.ts +3 -0
  27. package/dist/cli/cloud/commands/agents.d.ts.map +1 -0
  28. package/dist/cli/cloud/commands/agents.js +526 -0
  29. package/dist/cli/cloud/commands/api.d.ts +3 -0
  30. package/dist/cli/cloud/commands/api.d.ts.map +1 -0
  31. package/dist/cli/cloud/commands/api.js +26 -0
  32. package/dist/cli/cloud/commands/app-files.d.ts +29 -0
  33. package/dist/cli/cloud/commands/app-files.d.ts.map +1 -0
  34. package/dist/cli/cloud/commands/app-files.js +72 -0
  35. package/dist/cli/cloud/commands/artifacts.d.ts +3 -0
  36. package/dist/cli/cloud/commands/artifacts.d.ts.map +1 -0
  37. package/dist/cli/cloud/commands/artifacts.js +267 -0
  38. package/dist/cli/cloud/commands/automations.d.ts +3 -0
  39. package/dist/cli/cloud/commands/automations.d.ts.map +1 -0
  40. package/dist/cli/cloud/commands/automations.js +233 -0
  41. package/dist/cli/cloud/commands/chats.d.ts +3 -0
  42. package/dist/cli/cloud/commands/chats.d.ts.map +1 -0
  43. package/dist/cli/cloud/commands/chats.js +204 -0
  44. package/dist/cli/cloud/commands/data-deletions.d.ts +3 -0
  45. package/dist/cli/cloud/commands/data-deletions.d.ts.map +1 -0
  46. package/dist/cli/cloud/commands/data-deletions.js +55 -0
  47. package/dist/cli/cloud/commands/deploys.d.ts +10 -0
  48. package/dist/cli/cloud/commands/deploys.d.ts.map +1 -0
  49. package/dist/cli/cloud/commands/deploys.js +225 -0
  50. package/dist/cli/cloud/commands/drive.d.ts +12 -0
  51. package/dist/cli/cloud/commands/drive.d.ts.map +1 -0
  52. package/dist/cli/cloud/commands/drive.js +321 -0
  53. package/dist/cli/cloud/commands/files.d.ts +24 -0
  54. package/dist/cli/cloud/commands/files.d.ts.map +1 -0
  55. package/dist/cli/cloud/commands/files.js +284 -0
  56. package/dist/cli/cloud/commands/find.d.ts +3 -0
  57. package/dist/cli/cloud/commands/find.d.ts.map +1 -0
  58. package/dist/cli/cloud/commands/find.js +63 -0
  59. package/dist/cli/cloud/commands/models.d.ts +3 -0
  60. package/dist/cli/cloud/commands/models.d.ts.map +1 -0
  61. package/dist/cli/cloud/commands/models.js +250 -0
  62. package/dist/cli/cloud/commands/profile.d.ts +3 -0
  63. package/dist/cli/cloud/commands/profile.d.ts.map +1 -0
  64. package/dist/cli/cloud/commands/profile.js +120 -0
  65. package/dist/cli/cloud/commands/projects.d.ts +5 -0
  66. package/dist/cli/cloud/commands/projects.d.ts.map +1 -0
  67. package/dist/cli/cloud/commands/projects.js +66 -0
  68. package/dist/cli/cloud/commands/publish.d.ts +3 -0
  69. package/dist/cli/cloud/commands/publish.d.ts.map +1 -0
  70. package/dist/cli/cloud/commands/publish.js +139 -0
  71. package/dist/cli/cloud/commands/sandboxes.d.ts +3 -0
  72. package/dist/cli/cloud/commands/sandboxes.d.ts.map +1 -0
  73. package/dist/cli/cloud/commands/sandboxes.js +266 -0
  74. package/dist/cli/cloud/commands/secrets.d.ts +3 -0
  75. package/dist/cli/cloud/commands/secrets.d.ts.map +1 -0
  76. package/dist/cli/cloud/commands/secrets.js +111 -0
  77. package/dist/cli/cloud/commands/skills.d.ts +3 -0
  78. package/dist/cli/cloud/commands/skills.d.ts.map +1 -0
  79. package/dist/cli/cloud/commands/skills.js +203 -0
  80. package/dist/cli/cloud/commands/traces.d.ts +3 -0
  81. package/dist/cli/cloud/commands/traces.d.ts.map +1 -0
  82. package/dist/cli/cloud/commands/traces.js +142 -0
  83. package/dist/cli/cloud/commands/web.d.ts +3 -0
  84. package/dist/cli/cloud/commands/web.d.ts.map +1 -0
  85. package/dist/cli/cloud/commands/web.js +53 -0
  86. package/dist/cli/cloud/commands/workspace-apps.d.ts +58 -0
  87. package/dist/cli/cloud/commands/workspace-apps.d.ts.map +1 -0
  88. package/dist/cli/cloud/commands/workspace-apps.js +657 -0
  89. package/dist/cli/cloud/commands/workspace.d.ts +36 -0
  90. package/dist/cli/cloud/commands/workspace.d.ts.map +1 -0
  91. package/dist/cli/cloud/commands/workspace.js +281 -0
  92. package/dist/cli/cloud/connection.d.ts +33 -0
  93. package/dist/cli/cloud/connection.d.ts.map +1 -0
  94. package/dist/cli/cloud/connection.js +38 -0
  95. package/dist/cli/cloud/events.d.ts +63 -0
  96. package/dist/cli/cloud/events.d.ts.map +1 -0
  97. package/dist/cli/cloud/events.js +72 -0
  98. package/dist/cli/cloud/host.d.ts +9 -0
  99. package/dist/cli/cloud/host.d.ts.map +1 -0
  100. package/dist/cli/cloud/host.js +109 -0
  101. package/dist/cli/cloud/output.d.ts +34 -0
  102. package/dist/cli/cloud/output.d.ts.map +1 -0
  103. package/dist/cli/cloud/output.js +77 -0
  104. package/dist/cli/cloud/run.d.ts +26 -0
  105. package/dist/cli/cloud/run.d.ts.map +1 -0
  106. package/dist/cli/cloud/run.js +444 -0
  107. package/dist/cli/cloud/runtime.d.ts +33 -0
  108. package/dist/cli/cloud/runtime.d.ts.map +1 -0
  109. package/dist/cli/cloud/runtime.js +86 -0
  110. package/dist/cli/cloud/tar.d.ts +9 -0
  111. package/dist/cli/cloud/tar.d.ts.map +1 -0
  112. package/dist/cli/cloud/tar.js +69 -0
  113. package/dist/cli/cloud/transfer.d.ts +13 -0
  114. package/dist/cli/cloud/transfer.d.ts.map +1 -0
  115. package/dist/cli/cloud/transfer.js +36 -0
  116. package/dist/cli/cloud/v1.d.ts +20 -0
  117. package/dist/cli/cloud/v1.d.ts.map +1 -0
  118. package/dist/cli/cloud/v1.js +66 -0
  119. package/dist/cli/cloud/zip.d.ts +8 -0
  120. package/dist/cli/cloud/zip.d.ts.map +1 -0
  121. package/dist/cli/cloud/zip.js +66 -0
  122. package/dist/cli/commands/auth/sign-in-commands.d.ts +62 -0
  123. package/dist/cli/commands/auth/sign-in-commands.d.ts.map +1 -0
  124. package/dist/cli/commands/auth/sign-in-commands.js +248 -0
  125. package/dist/cli/commands/auth/sign-in-context.d.ts +16 -0
  126. package/dist/cli/commands/auth/sign-in-context.d.ts.map +1 -0
  127. package/dist/cli/commands/auth/sign-in-context.js +68 -0
  128. package/dist/cli/commands/cloud/register.d.ts +5 -0
  129. package/dist/cli/commands/cloud/register.d.ts.map +1 -1
  130. package/dist/cli/commands/cloud/register.js +44 -24
  131. package/dist/cli/commands/create-app.js +5 -6
  132. package/dist/cli/commands/create-image.d.ts.map +1 -1
  133. package/dist/cli/commands/create-image.js +9 -10
  134. package/dist/cli/commands/index.d.ts +0 -2
  135. package/dist/cli/commands/index.d.ts.map +1 -1
  136. package/dist/cli/commands/index.js +0 -2
  137. package/dist/cli/commands/init.d.ts +0 -2
  138. package/dist/cli/commands/init.d.ts.map +1 -1
  139. package/dist/cli/commands/init.js +5 -26
  140. package/dist/cli/commands/run/headless.d.ts.map +1 -1
  141. package/dist/cli/commands/run/headless.js +57 -2
  142. package/dist/cli/commands/run/output.d.ts +29 -10
  143. package/dist/cli/commands/run/output.d.ts.map +1 -1
  144. package/dist/cli/commands/run/output.js +44 -22
  145. package/dist/cli/commands/run/register.d.ts.map +1 -1
  146. package/dist/cli/commands/run/register.js +21 -9
  147. package/dist/cli/commands/run/step-log.d.ts +11 -0
  148. package/dist/cli/commands/run/step-log.d.ts.map +1 -0
  149. package/dist/cli/commands/run/step-log.js +42 -0
  150. package/dist/cli/commands/session/register.d.ts.map +1 -1
  151. package/dist/cli/commands/session/register.js +51 -21
  152. package/dist/cli/commands/session-commands.js +1 -1
  153. package/dist/cli/commands/setup.js +17 -14
  154. package/dist/cli/failure.d.ts +29 -0
  155. package/dist/cli/failure.d.ts.map +1 -0
  156. package/dist/cli/failure.js +31 -0
  157. package/dist/cli/help-json.d.ts +22 -0
  158. package/dist/cli/help-json.d.ts.map +1 -0
  159. package/dist/cli/help-json.js +20 -0
  160. package/dist/cli/import/claude-code.d.ts +10 -0
  161. package/dist/cli/import/claude-code.d.ts.map +1 -0
  162. package/dist/cli/import/claude-code.js +131 -0
  163. package/dist/cli/import/codex.d.ts +27 -0
  164. package/dist/cli/import/codex.d.ts.map +1 -0
  165. package/dist/cli/import/codex.js +148 -0
  166. package/dist/cli/import/git.d.ts +19 -0
  167. package/dist/cli/import/git.d.ts.map +1 -0
  168. package/dist/cli/import/git.js +95 -0
  169. package/dist/cli/import/local-chats.d.ts +28 -0
  170. package/dist/cli/import/local-chats.d.ts.map +1 -0
  171. package/dist/cli/import/local-chats.js +129 -0
  172. package/dist/cli/import/redaction.d.ts +37 -0
  173. package/dist/cli/import/redaction.d.ts.map +1 -0
  174. package/dist/cli/import/redaction.js +148 -0
  175. package/dist/cli/import/test-utils.d.ts +16 -0
  176. package/dist/cli/import/test-utils.d.ts.map +1 -0
  177. package/dist/cli/import/test-utils.js +223 -0
  178. package/dist/cli/import/transcript.d.ts +75 -0
  179. package/dist/cli/import/transcript.d.ts.map +1 -0
  180. package/dist/cli/import/transcript.js +123 -0
  181. package/dist/cli/interaction.d.ts +18 -0
  182. package/dist/cli/interaction.d.ts.map +1 -0
  183. package/dist/cli/interaction.js +30 -0
  184. package/dist/cli/modes/cli.d.ts.map +1 -1
  185. package/dist/cli/modes/cli.js +42 -9
  186. package/dist/cli/modes/server.js +8 -8
  187. package/dist/cli/modes/web.js +3 -3
  188. package/dist/cli/output.d.ts +9 -0
  189. package/dist/cli/output.d.ts.map +1 -0
  190. package/dist/cli/output.js +6 -0
  191. package/dist/cli/utils/dexto-auth-check.d.ts +1 -1
  192. package/dist/cli/utils/dexto-auth-check.d.ts.map +1 -1
  193. package/dist/cli/utils/dexto-auth-check.js +4 -5
  194. package/dist/cli/utils/dexto-setup.d.ts +4 -5
  195. package/dist/cli/utils/dexto-setup.d.ts.map +1 -1
  196. package/dist/cli/utils/dexto-setup.js +17 -14
  197. package/dist/cli/utils/provider-setup.js +1 -1
  198. package/dist/cli/utils/scaffolding-utils.d.ts +9 -3
  199. package/dist/cli/utils/scaffolding-utils.d.ts.map +1 -1
  200. package/dist/cli/utils/scaffolding-utils.js +48 -40
  201. package/dist/cli/utils/version-check.d.ts.map +1 -1
  202. package/dist/cli/utils/version-check.js +2 -1
  203. package/dist/index-main.js +44 -65
  204. package/dist/webui/assets/index-D9xiOs62.js +1649 -0
  205. package/dist/webui/index.html +1 -1
  206. package/package.json +15 -14
  207. package/dist/cli/auth/api-client.d.ts +0 -125
  208. package/dist/cli/auth/api-client.d.ts.map +0 -1
  209. package/dist/cli/auth/api-client.js +0 -585
  210. package/dist/cli/auth/device.d.ts +0 -14
  211. package/dist/cli/auth/device.d.ts.map +0 -1
  212. package/dist/cli/auth/device.js +0 -84
  213. package/dist/cli/auth/dexto-api-key.d.ts +0 -34
  214. package/dist/cli/auth/dexto-api-key.d.ts.map +0 -1
  215. package/dist/cli/auth/dexto-api-key.js +0 -160
  216. package/dist/cli/auth/login-persistence.d.ts +0 -15
  217. package/dist/cli/auth/login-persistence.d.ts.map +0 -1
  218. package/dist/cli/auth/login-persistence.js +0 -72
  219. package/dist/cli/auth/oauth.d.ts +0 -39
  220. package/dist/cli/auth/oauth.d.ts.map +0 -1
  221. package/dist/cli/auth/oauth.js +0 -434
  222. package/dist/cli/auth/service.d.ts +0 -24
  223. package/dist/cli/auth/service.d.ts.map +0 -1
  224. package/dist/cli/auth/service.js +0 -161
  225. package/dist/cli/auth/types.d.ts +0 -11
  226. package/dist/cli/auth/types.d.ts.map +0 -1
  227. package/dist/cli/auth/types.js +0 -1
  228. package/dist/cli/cloud-chat.d.ts +0 -18
  229. package/dist/cli/cloud-chat.d.ts.map +0 -1
  230. package/dist/cli/cloud-chat.js +0 -734
  231. package/dist/cli/commands/auth/index.d.ts +0 -4
  232. package/dist/cli/commands/auth/index.d.ts.map +0 -1
  233. package/dist/cli/commands/auth/index.js +0 -4
  234. package/dist/cli/commands/auth/login.d.ts +0 -12
  235. package/dist/cli/commands/auth/login.d.ts.map +0 -1
  236. package/dist/cli/commands/auth/login.js +0 -153
  237. package/dist/cli/commands/auth/logout.d.ts +0 -5
  238. package/dist/cli/commands/auth/logout.d.ts.map +0 -1
  239. package/dist/cli/commands/auth/logout.js +0 -81
  240. package/dist/cli/commands/auth/register.d.ts +0 -3
  241. package/dist/cli/commands/auth/register.d.ts.map +0 -1
  242. package/dist/cli/commands/auth/register.js +0 -96
  243. package/dist/cli/commands/auth/status.d.ts +0 -2
  244. package/dist/cli/commands/auth/status.d.ts.map +0 -1
  245. package/dist/cli/commands/auth/status.js +0 -22
  246. package/dist/cli/commands/billing/index.d.ts +0 -2
  247. package/dist/cli/commands/billing/index.d.ts.map +0 -1
  248. package/dist/cli/commands/billing/index.js +0 -2
  249. package/dist/cli/commands/billing/register.d.ts +0 -3
  250. package/dist/cli/commands/billing/register.d.ts.map +0 -1
  251. package/dist/cli/commands/billing/register.js +0 -20
  252. package/dist/cli/commands/billing/status.d.ts +0 -8
  253. package/dist/cli/commands/billing/status.d.ts.map +0 -1
  254. package/dist/cli/commands/billing/status.js +0 -71
  255. package/dist/cli/commands/cloud/discovery.d.ts +0 -17
  256. package/dist/cli/commands/cloud/discovery.d.ts.map +0 -1
  257. package/dist/cli/commands/cloud/discovery.js +0 -88
  258. package/dist/cli/commands/deploy/client.d.ts +0 -113
  259. package/dist/cli/commands/deploy/client.d.ts.map +0 -1
  260. package/dist/cli/commands/deploy/client.js +0 -519
  261. package/dist/cli/commands/deploy/config.d.ts +0 -37
  262. package/dist/cli/commands/deploy/config.d.ts.map +0 -1
  263. package/dist/cli/commands/deploy/config.js +0 -144
  264. package/dist/cli/commands/deploy/entry-agent.d.ts +0 -3
  265. package/dist/cli/commands/deploy/entry-agent.d.ts.map +0 -1
  266. package/dist/cli/commands/deploy/entry-agent.js +0 -70
  267. package/dist/cli/commands/deploy/index.d.ts +0 -12
  268. package/dist/cli/commands/deploy/index.d.ts.map +0 -1
  269. package/dist/cli/commands/deploy/index.js +0 -370
  270. package/dist/cli/commands/deploy/links.d.ts +0 -3
  271. package/dist/cli/commands/deploy/links.d.ts.map +0 -1
  272. package/dist/cli/commands/deploy/links.js +0 -53
  273. package/dist/cli/commands/deploy/register.d.ts +0 -6
  274. package/dist/cli/commands/deploy/register.d.ts.map +0 -1
  275. package/dist/cli/commands/deploy/register.js +0 -128
  276. package/dist/cli/commands/deploy/snapshot.d.ts +0 -12
  277. package/dist/cli/commands/deploy/snapshot.d.ts.map +0 -1
  278. package/dist/cli/commands/deploy/snapshot.js +0 -76
  279. package/dist/cli/commands/deploy/state.d.ts +0 -13
  280. package/dist/cli/commands/deploy/state.d.ts.map +0 -1
  281. package/dist/cli/commands/deploy/state.js +0 -122
  282. package/dist/cli/commands/span/register.d.ts +0 -6
  283. package/dist/cli/commands/span/register.d.ts.map +0 -1
  284. package/dist/cli/commands/span/register.js +0 -25
  285. package/dist/cli/commands/trace/client.d.ts +0 -98
  286. package/dist/cli/commands/trace/client.d.ts.map +0 -1
  287. package/dist/cli/commands/trace/client.js +0 -150
  288. package/dist/cli/commands/trace/format.d.ts +0 -5
  289. package/dist/cli/commands/trace/format.d.ts.map +0 -1
  290. package/dist/cli/commands/trace/format.js +0 -58
  291. package/dist/cli/commands/trace/index.d.ts +0 -21
  292. package/dist/cli/commands/trace/index.d.ts.map +0 -1
  293. package/dist/cli/commands/trace/index.js +0 -49
  294. package/dist/cli/commands/trace/register.d.ts +0 -6
  295. package/dist/cli/commands/trace/register.d.ts.map +0 -1
  296. package/dist/cli/commands/trace/register.js +0 -71
  297. package/dist/webui/assets/index-DEfRFmFT.js +0 -1667
@@ -0,0 +1,11 @@
1
+ import { type Command } from '../command.js';
2
+ import type { SignInContext } from '../../commands/auth/sign-in-commands.js';
3
+ /** Builds the sign-in context a command runs in; the host owns where sign-ins live. */
4
+ export type SignInFor = (io: {
5
+ readonly result: SignInContext['result'];
6
+ readonly note: SignInContext['note'];
7
+ readonly confirm: SignInContext['confirm'];
8
+ readonly signal: AbortSignal;
9
+ }) => Promise<SignInContext>;
10
+ export declare function accountCommands(signIn: SignInFor, creditsUrl: string): readonly Command[];
11
+ //# sourceMappingURL=account.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account.d.ts","sourceRoot":"","sources":["../../../../src/cli/cloud/commands/account.ts"],"names":[],"mappings":"AAMA,OAAO,EAMH,KAAK,OAAO,EAEf,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAE7E,uFAAuF;AACvF,MAAM,MAAM,SAAS,GAAG,CAAC,EAAE,EAAE;IACzB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IACzC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IAC3C,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;CAChC,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;AAW7B,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,OAAO,EAAE,CAoJzF"}
@@ -0,0 +1,129 @@
1
+ // `login`, `logout`, `whoami`, `accounts`, `models list` and `billing`: who commands act as, and
2
+ // the models and credits that sign-in reaches, under the CLI's one output contract.
3
+ import { confirm } from '../../interaction.js';
4
+ import { unwrap } from '@dexto/cloud-client';
5
+ import { argument, flag, listOption, stringOption, YES_OPTION, } from '../command.js';
6
+ function signInIo(context) {
7
+ return {
8
+ result: (value, text) => context.output.result(value, text),
9
+ note: (text) => context.output.note(text),
10
+ confirm: (question) => confirm(context, question),
11
+ signal: context.runtime.signal,
12
+ };
13
+ }
14
+ export function accountCommands(signIn, creditsUrl) {
15
+ const commands = () => import('../../commands/auth/sign-in-commands.js');
16
+ const login = {
17
+ options: {
18
+ device: {
19
+ description: 'Approve a code on any device, for SSH sessions and machines without a browser.',
20
+ type: 'boolean',
21
+ },
22
+ 'no-browser': {
23
+ description: 'Print the sign-in link instead of opening it.',
24
+ type: 'boolean',
25
+ },
26
+ org: {
27
+ description: 'Sign in for this organization, saved as a profile named after it and used from now on.',
28
+ type: 'string',
29
+ valueName: 'ORG',
30
+ },
31
+ scope: {
32
+ description: 'Also ask for a permission, such as drive:write; a first sign-in only reads.',
33
+ multiple: true,
34
+ type: 'string',
35
+ valueName: 'SCOPE',
36
+ },
37
+ },
38
+ path: ['login'],
39
+ summary: 'Sign in to Dexto with your browser or a device code; --api-key saves a key instead, for CI.',
40
+ async run(context, input) {
41
+ await (await commands()).login(await signIn(signInIo(context)), {
42
+ profile: context.overrides.profile,
43
+ org: stringOption(input, 'org') ?? null,
44
+ device: flag(input, 'device'),
45
+ browser: !flag(input, 'no-browser'),
46
+ scopes: listOption(input, 'scope'),
47
+ apiKey: context.overrides.apiKey,
48
+ });
49
+ },
50
+ };
51
+ const logout = {
52
+ path: ['logout'],
53
+ summary: 'End the sign-in on the server and forget it here.',
54
+ async run(context) {
55
+ await (await commands()).logout(await signIn(signInIo(context)), { profile: context.overrides.profile });
56
+ },
57
+ };
58
+ const whoami = {
59
+ path: ['whoami'],
60
+ summary: 'Show who Dexto commands act as: the profile, account, organization and project.',
61
+ async run(context) {
62
+ await (await commands()).whoami(await signIn(signInIo(context)), {
63
+ profile: context.overrides.profile,
64
+ apiKey: context.overrides.apiKey,
65
+ });
66
+ },
67
+ };
68
+ const accountsList = {
69
+ path: ['accounts', 'list'],
70
+ summary: 'List saved sign-ins, one per account and organization; * marks the one in use.',
71
+ async run(context) {
72
+ await (await commands()).listAccounts(await signIn(signInIo(context)), { profile: context.overrides.profile });
73
+ },
74
+ };
75
+ const accountsUse = {
76
+ arguments: '<profile>',
77
+ path: ['accounts', 'use'],
78
+ summary: 'Use this saved sign-in from now on.',
79
+ async run(context, input) {
80
+ await (await commands()).useAccount(await signIn(signInIo(context)), argument(input, 0, 'profile'));
81
+ },
82
+ };
83
+ const accountsRemove = {
84
+ arguments: '<profile>',
85
+ options: YES_OPTION,
86
+ path: ['accounts', 'remove'],
87
+ summary: 'Log a saved sign-in out and forget it here. Asks first.',
88
+ async run(context, input) {
89
+ await (await commands()).removeAccount(await signIn(signInIo(context)), argument(input, 0, 'profile'), {
90
+ yes: flag(input, 'yes'),
91
+ });
92
+ },
93
+ };
94
+ const modelsList = {
95
+ path: ['models', 'list'],
96
+ summary: 'List the models Dexto serves on your sign-in, as dexto/<model>.',
97
+ async run(context) {
98
+ const models = await unwrap(await (await context.client()).GET('/v1/models'));
99
+ context.output.list({ data: models.data.map((model) => ({ ...model, id: `dexto/${model.id}` })) }, [
100
+ { header: 'id', value: (model) => model.id },
101
+ { header: 'name', value: (model) => model.name },
102
+ { header: 'context', value: (model) => model.context_window },
103
+ ]);
104
+ },
105
+ };
106
+ const billing = {
107
+ options: {
108
+ buy: { description: 'Open the page to buy Dexto credits.', type: 'boolean' },
109
+ },
110
+ path: ['billing'],
111
+ summary: "Show the organization's credit balance and recent spending.",
112
+ async run(context, input) {
113
+ const summary = await unwrap(await (await context.client()).GET('/v1/billing/summary'));
114
+ context.output.result(summary, [
115
+ `$${summary.balance_usd.toFixed(2)} remaining. Buy more with dexto billing --buy.`,
116
+ `$${summary.last_30_days.total_cost_usd.toFixed(4)} over ${summary.last_30_days.total_usage_events} requests in the last 30 days.`,
117
+ ...summary.recent_model_usage
118
+ .slice(0, 5)
119
+ .map((usage) => ` ${new Date(usage.timestamp).toLocaleString()} ${usage.model}: $${usage.cost_usd.toFixed(4)}`),
120
+ ].join('\n'));
121
+ if (flag(input, 'buy')) {
122
+ context.output.note(`Buy credits at ${creditsUrl}`);
123
+ const { openBrowserUrl } = await import('../../auth/browser-launch.js');
124
+ await openBrowserUrl(creditsUrl).catch(() => undefined);
125
+ }
126
+ },
127
+ };
128
+ return [login, logout, whoami, accountsList, accountsUse, accountsRemove, modelsList, billing];
129
+ }
@@ -0,0 +1,3 @@
1
+ import { type Command } from '../command.js';
2
+ export declare const agentCommands: readonly Command[];
3
+ //# sourceMappingURL=agents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../../../src/cli/cloud/commands/agents.ts"],"names":[],"mappings":"AAQA,OAAO,EAaH,KAAK,OAAO,EAIf,MAAM,eAAe,CAAC;AA8oBvB,eAAO,MAAM,aAAa,EAAE,SAAS,OAAO,EAiB3C,CAAC"}
@@ -0,0 +1,526 @@
1
+ // `cloud agents`: define agents, chat with them, and read their sessions, messages and runs.
2
+ import { EXIT_CODES } from '../../failure.js';
3
+ import { confirm, requireConsent } from '../../interaction.js';
4
+ import chalk from 'chalk';
5
+ import { unwrap } from '@dexto/cloud-client';
6
+ import { argument, BODY_OPTIONS, flag, integerOption, isJsonObject, listOption, PAGE_OPTIONS, pageQuery, readJsonBody, stringOption, UsageError, YES_OPTION, } from '../command.js';
7
+ import { sessionEvents } from '../events.js';
8
+ function agentPath(agentId) {
9
+ return { params: { path: { agent_id: agentId } } };
10
+ }
11
+ function sessionPath(agentId, sessionId) {
12
+ return { params: { path: { agent_id: agentId, session_id: sessionId } } };
13
+ }
14
+ const AGENT_COLUMNS = [
15
+ { header: 'id', value: (agent) => agent.id },
16
+ { header: 'name', value: (agent) => agent.name },
17
+ { header: 'model', value: (agent) => agent.model ?? 'plan default' },
18
+ { header: 'version', value: (agent) => agent.version },
19
+ { header: 'tools', value: (agent) => agent.tools.map((tool) => tool.type).join(',') },
20
+ ];
21
+ /** Tool kinds a flag can add with their defaults; richer tools come from --file. */
22
+ const SIMPLE_TOOLS = {
23
+ automations: { type: 'automations' },
24
+ files: { type: 'files' },
25
+ media: { type: 'media' },
26
+ sandbox: { sandbox: { size: 'large', type: 'session' }, type: 'sandbox' },
27
+ web_fetch: { type: 'web_fetch' },
28
+ web_search: { type: 'web_search' },
29
+ };
30
+ const DEFINITION_OPTIONS = {
31
+ ...BODY_OPTIONS,
32
+ description: { description: 'A description for your reference.', type: 'string' },
33
+ instructions: { description: "The agent's system instructions.", type: 'string' },
34
+ model: { description: 'A model id from dexto cloud models list.', type: 'string' },
35
+ name: { description: 'Display name.', type: 'string' },
36
+ tool: {
37
+ description: `Add a tool: ${Object.keys(SIMPLE_TOOLS).join(', ')}. Others need --file.`,
38
+ multiple: true,
39
+ type: 'string',
40
+ valueName: 'KIND',
41
+ },
42
+ };
43
+ const list = {
44
+ options: PAGE_OPTIONS,
45
+ path: ['cloud', 'agents', 'list'],
46
+ summary: "List the project's agents.",
47
+ async run(context, input) {
48
+ const page = await unwrap(await (await context.client()).GET('/v1/agents', { params: { query: pageQuery(input) } }));
49
+ context.output.list(page, AGENT_COLUMNS);
50
+ },
51
+ };
52
+ const get = {
53
+ arguments: '<agent_id>',
54
+ path: ['cloud', 'agents', 'get'],
55
+ summary: "Show an agent's current version.",
56
+ async run(context, input) {
57
+ context.output.record(await unwrap(await (await context.client()).GET('/v1/agents/{agent_id}', agentPath(argument(input, 0, 'agent_id')))));
58
+ },
59
+ };
60
+ const create = {
61
+ options: DEFINITION_OPTIONS,
62
+ path: ['cloud', 'agents', 'create'],
63
+ summary: 'Create an agent from flags, or from a full definition with --file or --data.',
64
+ async run(context, input) {
65
+ const body = await readJsonBody(context, input);
66
+ const definition = mergeDefinition(body === null ? null : asDefinition(body), input);
67
+ const agent = await unwrap(await (await context.client()).POST('/v1/agents', { body: definition }));
68
+ context.output.result(agent, `Created agent ${agent.id} (${agent.name}).`);
69
+ },
70
+ };
71
+ const update = {
72
+ arguments: '<agent_id>',
73
+ options: DEFINITION_OPTIONS,
74
+ path: ['cloud', 'agents', 'update'],
75
+ summary: 'Change an agent: flags change those fields, --file replaces the whole definition.',
76
+ async run(context, input) {
77
+ const client = await context.client();
78
+ const agentId = argument(input, 0, 'agent_id');
79
+ const body = await readJsonBody(context, input);
80
+ // The API only replaces whole definitions, so a field change reads the current one first.
81
+ const current = await unwrap(await client.GET('/v1/agents/{agent_id}', agentPath(agentId)));
82
+ const base = body === null ? definitionOf(current) : asDefinition(body);
83
+ const agent = await unwrap(await client.PUT('/v1/agents/{agent_id}', {
84
+ ...agentPath(agentId),
85
+ body: { ...mergeDefinition(base, input), expected_version: current.version },
86
+ }));
87
+ context.output.result(agent, `Updated agent ${agent.id} to version ${agent.version}.`);
88
+ },
89
+ };
90
+ const archive = {
91
+ arguments: '<agent_id>',
92
+ options: YES_OPTION,
93
+ path: ['cloud', 'agents', 'archive'],
94
+ summary: 'Archive an agent: it accepts no new runs and its session sandboxes end.',
95
+ async run(context, input) {
96
+ const id = argument(input, 0, 'agent_id');
97
+ await requireConsent(context, flag(input, 'yes'), `Archiving agent ${id} stops its new runs and ends its session sandboxes.`);
98
+ const agent = await unwrap(await (await context.client()).DELETE('/v1/agents/{agent_id}', agentPath(id)));
99
+ context.output.result(agent, `Archived agent ${agent.id}.`);
100
+ },
101
+ };
102
+ const chat = {
103
+ arguments: '<agent_id> [message...]',
104
+ options: {
105
+ session: {
106
+ description: 'Continue this session instead of starting one.',
107
+ type: 'string',
108
+ valueName: 'ID',
109
+ },
110
+ user: {
111
+ description: 'The end-user label for a new session (default cli).',
112
+ type: 'string',
113
+ },
114
+ yes: { description: 'Approve every tool call the agent asks to make.', type: 'boolean' },
115
+ },
116
+ path: ['cloud', 'agents', 'chat'],
117
+ summary: 'Send a message and stream the reply. Without a message at a terminal, keeps chatting until an empty line.',
118
+ async run(context, input) {
119
+ const client = await context.client();
120
+ const agentId = argument(input, 0, 'agent_id');
121
+ const sessionId = stringOption(input, 'session') ??
122
+ (await unwrap(await client.POST('/v1/agents/{agent_id}/sessions', {
123
+ ...agentPath(agentId),
124
+ body: { user: stringOption(input, 'user') ?? 'cli' },
125
+ }))).id;
126
+ context.output.note(`Session ${sessionId}`);
127
+ const turn = (message) => runTurn(context, client, { agentId, approveAll: flag(input, 'yes'), sessionId }, message);
128
+ const message = input.positionals.slice(1).join(' ');
129
+ if (message.length > 0)
130
+ return await turn(message);
131
+ const prompt = context.runtime.prompt;
132
+ if (prompt === null)
133
+ return await turn((await context.runtime.readStdin()).trim());
134
+ for (;;) {
135
+ const next = (await prompt(chalk.bold('> '), { secret: false })).trim();
136
+ if (next.length === 0)
137
+ return 0;
138
+ const code = await turn(next);
139
+ if (code !== 0)
140
+ return code;
141
+ }
142
+ },
143
+ };
144
+ /**
145
+ * Sends one message and renders its run from the session's events until the run ends. The
146
+ * stream opens before the message is sent so the run's first events are not missed.
147
+ */
148
+ async function runTurn(context, client, target, content) {
149
+ if (content.length === 0)
150
+ throw new UsageError('The message is empty.');
151
+ const { runtime, output } = context;
152
+ const stop = new AbortController();
153
+ const onAbort = () => stop.abort();
154
+ runtime.signal.addEventListener('abort', onAbort);
155
+ const events = sessionEvents(context, target.agentId, target.sessionId, stop.signal)[Symbol.asyncIterator]();
156
+ let next = events.next();
157
+ try {
158
+ const run = await unwrap(await client.POST('/v1/agents/{agent_id}/sessions/{session_id}/messages', {
159
+ ...sessionPath(target.agentId, target.sessionId),
160
+ body: { content },
161
+ }));
162
+ let streamedText = false;
163
+ for (;;) {
164
+ const result = await next;
165
+ if (result.done)
166
+ break;
167
+ next = events.next();
168
+ const event = result.value;
169
+ if (event.run_id !== run.id)
170
+ continue;
171
+ // A reply is content: only an explicit --json prints its events.
172
+ if (output.jsonContent)
173
+ runtime.writeOutput(`${JSON.stringify(event)}\n`);
174
+ else
175
+ streamedText = renderEvent(context, event, streamedText);
176
+ if (event.type === 'approval.requested') {
177
+ const decided = await decide(context, client, target, event);
178
+ if (!decided)
179
+ return EXIT_CODES.waiting_on_person;
180
+ }
181
+ if (event.type === 'run.completed')
182
+ return 0;
183
+ if (event.type === 'run.failed')
184
+ return 1;
185
+ if (event.type === 'run.cancelled')
186
+ return 130;
187
+ }
188
+ // The stream closed before the run ended: report what the run says now.
189
+ const latest = await unwrap(await client.GET('/v1/agents/{agent_id}/sessions/{session_id}/runs/{run_id}', {
190
+ params: {
191
+ path: {
192
+ agent_id: target.agentId,
193
+ session_id: target.sessionId,
194
+ run_id: run.id,
195
+ },
196
+ },
197
+ }));
198
+ output.note(`The event stream closed; run ${run.id} is ${latest.status}.`);
199
+ return latest.status === 'failed' ? 1 : 0;
200
+ }
201
+ finally {
202
+ runtime.signal.removeEventListener('abort', onAbort);
203
+ stop.abort();
204
+ await next.catch(() => undefined);
205
+ }
206
+ }
207
+ /** Writes one event for people; returns whether the current message has streamed text. */
208
+ function renderEvent(context, event, streamedText) {
209
+ const { runtime, output } = context;
210
+ switch (event.type) {
211
+ case 'message.delta':
212
+ runtime.writeOutput(event.text);
213
+ return true;
214
+ case 'message.completed':
215
+ runtime.writeOutput(streamedText ? '\n' : `${event.text}\n`);
216
+ return false;
217
+ case 'tool.started':
218
+ output.note(`→ ${event.name} ${summarize(event.arguments)}`);
219
+ return streamedText;
220
+ case 'tool.completed':
221
+ output.note(event.error === null
222
+ ? `✓ ${event.name}`
223
+ : `✗ ${event.name} ${event.status}: ${event.error.message}`);
224
+ return streamedText;
225
+ case 'run.completed':
226
+ output.note(`Run ${event.run_id} ${event.stop_reason}: ${event.usage.input_tokens} in, ${event.usage.output_tokens} out, ${event.usage.credits} credits.`);
227
+ return false;
228
+ case 'run.failed':
229
+ runtime.writeError(`Run failed (${event.error.code}): ${event.error.message}\n`);
230
+ return false;
231
+ case 'run.cancelled':
232
+ output.note(`Run ${event.run_id} was cancelled.`);
233
+ return false;
234
+ case 'approval.requested':
235
+ case 'approval.resolved':
236
+ case 'run.started':
237
+ return streamedText;
238
+ }
239
+ }
240
+ /** Decides a requested approval at the terminal; false when nobody here can. */
241
+ async function decide(context, client, target, event) {
242
+ const tool = event.tool_name ?? 'a tool';
243
+ const approve = target.approveAll ||
244
+ (context.runtime.prompt !== null &&
245
+ (await confirm(context, `Allow ${tool} ${summarize(event.input)}?`)));
246
+ if (!approve && context.runtime.prompt === null) {
247
+ context.output.note(`The run waits for approval ${event.approval_id}. Decide it with: dexto cloud agents approve ${target.agentId} ${target.sessionId} ${event.approval_id} (or reject)`);
248
+ return false;
249
+ }
250
+ await unwrap(await client.POST('/v1/agents/{agent_id}/sessions/{session_id}/approvals/{approval_id}', {
251
+ params: {
252
+ path: {
253
+ agent_id: target.agentId,
254
+ session_id: target.sessionId,
255
+ approval_id: event.approval_id,
256
+ },
257
+ },
258
+ body: { decision: approve ? 'approve' : 'reject' },
259
+ }));
260
+ return true;
261
+ }
262
+ function decisionCommand(decision) {
263
+ return {
264
+ arguments: '<agent_id> <session_id> <approval_id>',
265
+ options: decision === 'reject'
266
+ ? { message: { description: 'Why, for the agent.', type: 'string' } }
267
+ : {},
268
+ path: ['cloud', 'agents', decision],
269
+ summary: `${decision === 'approve' ? 'Approve' : 'Reject'} a tool call a run is waiting on.`,
270
+ async run(context, input) {
271
+ const message = stringOption(input, 'message');
272
+ const result = await unwrap(await (await context.client()).POST('/v1/agents/{agent_id}/sessions/{session_id}/approvals/{approval_id}', {
273
+ params: {
274
+ path: {
275
+ agent_id: argument(input, 0, 'agent_id'),
276
+ session_id: argument(input, 1, 'session_id'),
277
+ approval_id: argument(input, 2, 'approval_id'),
278
+ },
279
+ },
280
+ body: { decision, ...(message === undefined ? {} : { message }) },
281
+ }));
282
+ context.output.result(result, `${result.decision} ${result.approval_id}.`);
283
+ },
284
+ };
285
+ }
286
+ const sessionsList = {
287
+ arguments: '<agent_id>',
288
+ options: {
289
+ ...PAGE_OPTIONS,
290
+ user: { description: "Only this end user's sessions.", type: 'string' },
291
+ },
292
+ path: ['cloud', 'agents', 'sessions', 'list'],
293
+ summary: "List an agent's sessions.",
294
+ async run(context, input) {
295
+ const user = stringOption(input, 'user');
296
+ const page = await unwrap(await (await context.client()).GET('/v1/agents/{agent_id}/sessions', {
297
+ params: {
298
+ path: { agent_id: argument(input, 0, 'agent_id') },
299
+ query: { ...pageQuery(input), ...(user === undefined ? {} : { user }) },
300
+ },
301
+ }));
302
+ context.output.list(page, [
303
+ { header: 'id', value: (session) => session.id },
304
+ { header: 'user', value: (session) => session.user },
305
+ { header: 'version', value: (session) => session.version },
306
+ { header: 'active run', value: (session) => session.active_run?.status ?? null },
307
+ { header: 'created', value: (session) => session.created_at },
308
+ ]);
309
+ },
310
+ };
311
+ const sessionsGet = {
312
+ arguments: '<agent_id> <session_id>',
313
+ path: ['cloud', 'agents', 'sessions', 'get'],
314
+ summary: 'Show a session and its active run.',
315
+ async run(context, input) {
316
+ context.output.record(await unwrap(await (await context.client()).GET('/v1/agents/{agent_id}/sessions/{session_id}', sessionPath(argument(input, 0, 'agent_id'), argument(input, 1, 'session_id')))));
317
+ },
318
+ };
319
+ const sessionsDelete = {
320
+ arguments: '<agent_id> <session_id>',
321
+ options: YES_OPTION,
322
+ path: ['cloud', 'agents', 'sessions', 'delete'],
323
+ summary: 'Delete a session with its messages, runs and stored tool output.',
324
+ async run(context, input) {
325
+ const sessionId = argument(input, 1, 'session_id');
326
+ await requireConsent(context, flag(input, 'yes'), `Deleting session ${sessionId} removes its messages, runs and stored tool output for good.`);
327
+ const result = await unwrap(await (await context.client()).DELETE('/v1/agents/{agent_id}/sessions/{session_id}', sessionPath(argument(input, 0, 'agent_id'), sessionId)));
328
+ context.output.result(result, `Deleted session ${result.id}.`);
329
+ },
330
+ };
331
+ const sessionsCancel = {
332
+ arguments: '<agent_id> <session_id>',
333
+ path: ['cloud', 'agents', 'sessions', 'cancel'],
334
+ summary: "Cancel the session's active run.",
335
+ async run(context, input) {
336
+ const run = await unwrap(await (await context.client()).POST('/v1/agents/{agent_id}/sessions/{session_id}/cancel', sessionPath(argument(input, 0, 'agent_id'), argument(input, 1, 'session_id'))));
337
+ context.output.result(run, `Run ${run.id} is ${run.status}.`);
338
+ },
339
+ };
340
+ const messages = {
341
+ arguments: '<agent_id> <session_id>',
342
+ options: PAGE_OPTIONS,
343
+ path: ['cloud', 'agents', 'messages'],
344
+ summary: "Read a session's messages, oldest first.",
345
+ async run(context, input) {
346
+ // Messages page by sequence number, not by an opaque cursor like every other list.
347
+ const after = integerOption(input, 'after');
348
+ const limit = integerOption(input, 'limit');
349
+ const page = await unwrap(await (await context.client()).GET('/v1/agents/{agent_id}/sessions/{session_id}/messages', {
350
+ params: {
351
+ path: {
352
+ agent_id: argument(input, 0, 'agent_id'),
353
+ session_id: argument(input, 1, 'session_id'),
354
+ },
355
+ query: {
356
+ ...(after === undefined ? {} : { after }),
357
+ ...(limit === undefined ? {} : { limit }),
358
+ },
359
+ },
360
+ }));
361
+ if (context.output.json)
362
+ return context.output.list(page, []);
363
+ for (const message of page.data)
364
+ context.runtime.writeOutput(`${chalk.bold(message.role)}: ${message.text}\n\n`);
365
+ if (page.has_more && page.next_after !== null)
366
+ context.output.note(`More messages: add --after ${page.next_after}`);
367
+ },
368
+ };
369
+ const runsList = {
370
+ arguments: '<agent_id> <session_id>',
371
+ options: PAGE_OPTIONS,
372
+ path: ['cloud', 'agents', 'runs', 'list'],
373
+ summary: "List a session's runs, newest first.",
374
+ async run(context, input) {
375
+ const page = await unwrap(await (await context.client()).GET('/v1/agents/{agent_id}/sessions/{session_id}/runs', {
376
+ params: {
377
+ path: {
378
+ agent_id: argument(input, 0, 'agent_id'),
379
+ session_id: argument(input, 1, 'session_id'),
380
+ },
381
+ query: pageQuery(input),
382
+ },
383
+ }));
384
+ context.output.list(page, [
385
+ { header: 'id', value: (run) => run.id },
386
+ { header: 'status', value: (run) => run.status },
387
+ { header: 'stop reason', value: (run) => run.stop_reason },
388
+ { header: 'credits', value: (run) => run.usage.credits },
389
+ { header: 'created', value: (run) => run.created_at },
390
+ ]);
391
+ },
392
+ };
393
+ const runsGet = {
394
+ arguments: '<agent_id> <session_id> <run_id>',
395
+ path: ['cloud', 'agents', 'runs', 'get'],
396
+ summary: 'Show a run: its status, why it stopped and what it used.',
397
+ async run(context, input) {
398
+ context.output.record(await unwrap(await (await context.client()).GET('/v1/agents/{agent_id}/sessions/{session_id}/runs/{run_id}', {
399
+ params: {
400
+ path: {
401
+ agent_id: argument(input, 0, 'agent_id'),
402
+ session_id: argument(input, 1, 'session_id'),
403
+ run_id: argument(input, 2, 'run_id'),
404
+ },
405
+ },
406
+ })));
407
+ },
408
+ };
409
+ const runsSteps = {
410
+ arguments: '<agent_id> <session_id> <run_id>',
411
+ path: ['cloud', 'agents', 'runs', 'steps'],
412
+ summary: 'List what a run did: each model turn and tool call.',
413
+ async run(context, input) {
414
+ const client = await context.client();
415
+ const path = {
416
+ agent_id: argument(input, 0, 'agent_id'),
417
+ session_id: argument(input, 1, 'session_id'),
418
+ run_id: argument(input, 2, 'run_id'),
419
+ };
420
+ // Every page, so the whole run reads as one list.
421
+ const steps = [];
422
+ let after;
423
+ for (;;) {
424
+ const page = await unwrap(await client.GET('/v1/agents/{agent_id}/sessions/{session_id}/runs/{run_id}/steps', {
425
+ params: { path, query: after === undefined ? {} : { after } },
426
+ }));
427
+ steps.push(...page.data);
428
+ if (!page.has_more || page.next_after === null)
429
+ break;
430
+ after = page.next_after;
431
+ }
432
+ context.output.list({ data: steps }, [
433
+ { header: 'type', value: (step) => step.type },
434
+ { header: 'status', value: (step) => step.status },
435
+ {
436
+ header: 'detail',
437
+ value: (step) => step.error !== null
438
+ ? `${step.error.code}: ${step.error.message}`
439
+ : step.type === 'model_turn'
440
+ ? step.text
441
+ : `${step.name} ${summarize(step.arguments)}`,
442
+ },
443
+ { header: 'started', value: (step) => step.started_at },
444
+ ]);
445
+ },
446
+ };
447
+ function mergeDefinition(base, input) {
448
+ const name = stringOption(input, 'name') ?? base?.name;
449
+ const instructions = stringOption(input, 'instructions') ?? base?.instructions;
450
+ if (name === undefined || instructions === undefined)
451
+ throw new UsageError('An agent needs --name and --instructions, or a definition in --file.');
452
+ const description = stringOption(input, 'description') ?? base?.description;
453
+ const model = stringOption(input, 'model') ?? base?.model;
454
+ const added = listOption(input, 'tool').map((kind) => {
455
+ const tool = SIMPLE_TOOLS[kind];
456
+ if (tool === undefined)
457
+ throw new UsageError(`Unknown tool ${kind}. Flags add ${Object.keys(SIMPLE_TOOLS).join(', ')}; put others in --file.`);
458
+ return tool;
459
+ });
460
+ return {
461
+ instructions,
462
+ name,
463
+ ...(description === undefined ? {} : { description }),
464
+ ...(model === undefined ? {} : { model }),
465
+ tools: [...(base?.tools ?? []), ...added],
466
+ };
467
+ }
468
+ /**
469
+ * The definition to replace an agent with, from what reading it returned. A read tool's fields
470
+ * are a superset of what a definition accepts (a session sandbox reads as small or large but is
471
+ * created only large), so the read shape is passed back as is and the API judges it.
472
+ */
473
+ function definitionOf(agent) {
474
+ return {
475
+ description: agent.description,
476
+ instructions: agent.instructions,
477
+ model: agent.model,
478
+ name: agent.name,
479
+ tools: agent.tools.map(definitionTool),
480
+ };
481
+ }
482
+ function definitionTool(tool) {
483
+ if (tool.type !== 'sandbox')
484
+ return tool;
485
+ if (tool.sandbox.type === 'project')
486
+ return { ...tool, sandbox: tool.sandbox };
487
+ if (tool.sandbox.size !== 'large')
488
+ throw new UsageError(`This agent's session sandbox is ${tool.sandbox.size}, which a definition cannot set. Replace the whole definition with --file.`);
489
+ return { ...tool, sandbox: { size: 'large', type: 'session' } };
490
+ }
491
+ /** The API validates the whole definition; the CLI checks only what it reads itself. */
492
+ function isDefinition(value) {
493
+ return (isJsonObject(value) &&
494
+ typeof value.name === 'string' &&
495
+ typeof value.instructions === 'string' &&
496
+ (value.tools === undefined || Array.isArray(value.tools)));
497
+ }
498
+ function asDefinition(value) {
499
+ if (!isDefinition(value))
500
+ throw new UsageError('The agent definition needs name and instructions strings.');
501
+ return value;
502
+ }
503
+ function summarize(value) {
504
+ if (value === null || value === undefined)
505
+ return '';
506
+ const text = typeof value === 'string' ? value : JSON.stringify(value);
507
+ return text.length > 120 ? `${text.slice(0, 119)}…` : text;
508
+ }
509
+ export const agentCommands = [
510
+ list,
511
+ get,
512
+ create,
513
+ update,
514
+ archive,
515
+ chat,
516
+ decisionCommand('approve'),
517
+ decisionCommand('reject'),
518
+ sessionsList,
519
+ sessionsGet,
520
+ sessionsDelete,
521
+ sessionsCancel,
522
+ messages,
523
+ runsList,
524
+ runsGet,
525
+ runsSteps,
526
+ ];