dexto 1.14.5 → 2.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. package/dist/cli/auth/billing.d.ts +0 -6
  2. package/dist/cli/auth/billing.d.ts.map +1 -1
  3. package/dist/cli/auth/billing.js +0 -23
  4. package/dist/cli/auth/constants.d.ts +3 -31
  5. package/dist/cli/auth/constants.d.ts.map +1 -1
  6. package/dist/cli/auth/constants.js +9 -33
  7. package/dist/cli/auth/index.d.ts +2 -9
  8. package/dist/cli/auth/index.d.ts.map +1 -1
  9. package/dist/cli/auth/index.js +2 -7
  10. package/dist/cli/auth/sign-in-runtime.d.ts +12 -0
  11. package/dist/cli/auth/sign-in-runtime.d.ts.map +1 -0
  12. package/dist/cli/auth/sign-in-runtime.js +59 -0
  13. package/dist/cli/cloud/app-scopes.d.ts +4 -0
  14. package/dist/cli/cloud/app-scopes.d.ts.map +1 -0
  15. package/dist/cli/cloud/app-scopes.js +19 -0
  16. package/dist/cli/cloud/command.d.ts +143 -0
  17. package/dist/cli/cloud/command.d.ts.map +1 -0
  18. package/dist/cli/cloud/command.js +202 -0
  19. package/dist/cli/cloud/commands/account.d.ts +11 -0
  20. package/dist/cli/cloud/commands/account.d.ts.map +1 -0
  21. package/dist/cli/cloud/commands/account.js +128 -0
  22. package/dist/cli/cloud/commands/agents.d.ts +3 -0
  23. package/dist/cli/cloud/commands/agents.d.ts.map +1 -0
  24. package/dist/cli/cloud/commands/agents.js +524 -0
  25. package/dist/cli/cloud/commands/api.d.ts +3 -0
  26. package/dist/cli/cloud/commands/api.d.ts.map +1 -0
  27. package/dist/cli/cloud/commands/api.js +26 -0
  28. package/dist/cli/cloud/commands/app-files.d.ts +29 -0
  29. package/dist/cli/cloud/commands/app-files.d.ts.map +1 -0
  30. package/dist/cli/cloud/commands/app-files.js +72 -0
  31. package/dist/cli/cloud/commands/automations.d.ts +3 -0
  32. package/dist/cli/cloud/commands/automations.d.ts.map +1 -0
  33. package/dist/cli/cloud/commands/automations.js +232 -0
  34. package/dist/cli/cloud/commands/chats.d.ts +3 -0
  35. package/dist/cli/cloud/commands/chats.d.ts.map +1 -0
  36. package/dist/cli/cloud/commands/chats.js +189 -0
  37. package/dist/cli/cloud/commands/data-deletions.d.ts +3 -0
  38. package/dist/cli/cloud/commands/data-deletions.d.ts.map +1 -0
  39. package/dist/cli/cloud/commands/data-deletions.js +54 -0
  40. package/dist/cli/cloud/commands/deploys.d.ts +10 -0
  41. package/dist/cli/cloud/commands/deploys.d.ts.map +1 -0
  42. package/dist/cli/cloud/commands/deploys.js +223 -0
  43. package/dist/cli/cloud/commands/drive.d.ts +12 -0
  44. package/dist/cli/cloud/commands/drive.d.ts.map +1 -0
  45. package/dist/cli/cloud/commands/drive.js +320 -0
  46. package/dist/cli/cloud/commands/files.d.ts +24 -0
  47. package/dist/cli/cloud/commands/files.d.ts.map +1 -0
  48. package/dist/cli/cloud/commands/files.js +282 -0
  49. package/dist/cli/cloud/commands/find.d.ts +3 -0
  50. package/dist/cli/cloud/commands/find.d.ts.map +1 -0
  51. package/dist/cli/cloud/commands/find.js +63 -0
  52. package/dist/cli/cloud/commands/models.d.ts +3 -0
  53. package/dist/cli/cloud/commands/models.d.ts.map +1 -0
  54. package/dist/cli/cloud/commands/models.js +248 -0
  55. package/dist/cli/cloud/commands/profile.d.ts +3 -0
  56. package/dist/cli/cloud/commands/profile.d.ts.map +1 -0
  57. package/dist/cli/cloud/commands/profile.js +119 -0
  58. package/dist/cli/cloud/commands/projects.d.ts +5 -0
  59. package/dist/cli/cloud/commands/projects.d.ts.map +1 -0
  60. package/dist/cli/cloud/commands/projects.js +66 -0
  61. package/dist/cli/cloud/commands/publish.d.ts +3 -0
  62. package/dist/cli/cloud/commands/publish.d.ts.map +1 -0
  63. package/dist/cli/cloud/commands/publish.js +138 -0
  64. package/dist/cli/cloud/commands/sandboxes.d.ts +3 -0
  65. package/dist/cli/cloud/commands/sandboxes.d.ts.map +1 -0
  66. package/dist/cli/cloud/commands/sandboxes.js +265 -0
  67. package/dist/cli/cloud/commands/secrets.d.ts +3 -0
  68. package/dist/cli/cloud/commands/secrets.d.ts.map +1 -0
  69. package/dist/cli/cloud/commands/secrets.js +110 -0
  70. package/dist/cli/cloud/commands/skills.d.ts +3 -0
  71. package/dist/cli/cloud/commands/skills.d.ts.map +1 -0
  72. package/dist/cli/cloud/commands/skills.js +202 -0
  73. package/dist/cli/cloud/commands/web.d.ts +3 -0
  74. package/dist/cli/cloud/commands/web.d.ts.map +1 -0
  75. package/dist/cli/cloud/commands/web.js +53 -0
  76. package/dist/cli/cloud/commands/workspace-apps.d.ts +58 -0
  77. package/dist/cli/cloud/commands/workspace-apps.d.ts.map +1 -0
  78. package/dist/cli/cloud/commands/workspace-apps.js +656 -0
  79. package/dist/cli/cloud/commands/workspace.d.ts +36 -0
  80. package/dist/cli/cloud/commands/workspace.d.ts.map +1 -0
  81. package/dist/cli/cloud/commands/workspace.js +279 -0
  82. package/dist/cli/cloud/connection.d.ts +33 -0
  83. package/dist/cli/cloud/connection.d.ts.map +1 -0
  84. package/dist/cli/cloud/connection.js +38 -0
  85. package/dist/cli/cloud/events.d.ts +63 -0
  86. package/dist/cli/cloud/events.d.ts.map +1 -0
  87. package/dist/cli/cloud/events.js +72 -0
  88. package/dist/cli/cloud/host.d.ts +9 -0
  89. package/dist/cli/cloud/host.d.ts.map +1 -0
  90. package/dist/cli/cloud/host.js +105 -0
  91. package/dist/cli/cloud/local-chats.d.ts +73 -0
  92. package/dist/cli/cloud/local-chats.d.ts.map +1 -0
  93. package/dist/cli/cloud/local-chats.js +441 -0
  94. package/dist/cli/cloud/output.d.ts +34 -0
  95. package/dist/cli/cloud/output.d.ts.map +1 -0
  96. package/dist/cli/cloud/output.js +76 -0
  97. package/dist/cli/cloud/run.d.ts +26 -0
  98. package/dist/cli/cloud/run.d.ts.map +1 -0
  99. package/dist/cli/cloud/run.js +444 -0
  100. package/dist/cli/cloud/runtime.d.ts +33 -0
  101. package/dist/cli/cloud/runtime.d.ts.map +1 -0
  102. package/dist/cli/cloud/runtime.js +86 -0
  103. package/dist/cli/cloud/tar.d.ts +9 -0
  104. package/dist/cli/cloud/tar.d.ts.map +1 -0
  105. package/dist/cli/cloud/tar.js +69 -0
  106. package/dist/cli/cloud/transfer.d.ts +13 -0
  107. package/dist/cli/cloud/transfer.d.ts.map +1 -0
  108. package/dist/cli/cloud/transfer.js +35 -0
  109. package/dist/cli/cloud/v1.d.ts +19 -0
  110. package/dist/cli/cloud/v1.d.ts.map +1 -0
  111. package/dist/cli/cloud/v1.js +65 -0
  112. package/dist/cli/cloud/zip.d.ts +8 -0
  113. package/dist/cli/cloud/zip.d.ts.map +1 -0
  114. package/dist/cli/cloud/zip.js +66 -0
  115. package/dist/cli/commands/auth/sign-in-commands.d.ts +62 -0
  116. package/dist/cli/commands/auth/sign-in-commands.d.ts.map +1 -0
  117. package/dist/cli/commands/auth/sign-in-commands.js +247 -0
  118. package/dist/cli/commands/auth/sign-in-context.d.ts +16 -0
  119. package/dist/cli/commands/auth/sign-in-context.d.ts.map +1 -0
  120. package/dist/cli/commands/auth/sign-in-context.js +68 -0
  121. package/dist/cli/commands/cloud/register.d.ts +5 -0
  122. package/dist/cli/commands/cloud/register.d.ts.map +1 -1
  123. package/dist/cli/commands/cloud/register.js +42 -24
  124. package/dist/cli/commands/create-app.js +5 -6
  125. package/dist/cli/commands/create-image.d.ts.map +1 -1
  126. package/dist/cli/commands/create-image.js +9 -10
  127. package/dist/cli/commands/index.d.ts +0 -2
  128. package/dist/cli/commands/index.d.ts.map +1 -1
  129. package/dist/cli/commands/index.js +0 -2
  130. package/dist/cli/commands/init.d.ts +0 -2
  131. package/dist/cli/commands/init.d.ts.map +1 -1
  132. package/dist/cli/commands/init.js +5 -26
  133. package/dist/cli/commands/run/headless.js +2 -2
  134. package/dist/cli/commands/run/output.d.ts +29 -10
  135. package/dist/cli/commands/run/output.d.ts.map +1 -1
  136. package/dist/cli/commands/run/output.js +44 -22
  137. package/dist/cli/commands/run/register.d.ts.map +1 -1
  138. package/dist/cli/commands/run/register.js +21 -9
  139. package/dist/cli/commands/session/register.d.ts.map +1 -1
  140. package/dist/cli/commands/session/register.js +51 -21
  141. package/dist/cli/commands/session-commands.js +1 -1
  142. package/dist/cli/commands/setup.js +17 -14
  143. package/dist/cli/help-json.d.ts +22 -0
  144. package/dist/cli/help-json.d.ts.map +1 -0
  145. package/dist/cli/help-json.js +20 -0
  146. package/dist/cli/modes/cli.d.ts.map +1 -1
  147. package/dist/cli/modes/cli.js +42 -9
  148. package/dist/cli/modes/server.js +8 -8
  149. package/dist/cli/modes/web.js +3 -3
  150. package/dist/cli/utils/dexto-auth-check.d.ts +1 -1
  151. package/dist/cli/utils/dexto-auth-check.d.ts.map +1 -1
  152. package/dist/cli/utils/dexto-auth-check.js +4 -5
  153. package/dist/cli/utils/dexto-setup.d.ts +4 -5
  154. package/dist/cli/utils/dexto-setup.d.ts.map +1 -1
  155. package/dist/cli/utils/dexto-setup.js +17 -14
  156. package/dist/cli/utils/provider-setup.js +1 -1
  157. package/dist/cli/utils/scaffolding-utils.d.ts +9 -3
  158. package/dist/cli/utils/scaffolding-utils.d.ts.map +1 -1
  159. package/dist/cli/utils/scaffolding-utils.js +48 -40
  160. package/dist/cli/utils/version-check.d.ts.map +1 -1
  161. package/dist/cli/utils/version-check.js +2 -1
  162. package/dist/index-main.js +33 -65
  163. package/dist/webui/assets/index-D9xiOs62.js +1649 -0
  164. package/dist/webui/index.html +1 -1
  165. package/package.json +15 -14
  166. package/dist/cli/auth/api-client.d.ts +0 -125
  167. package/dist/cli/auth/api-client.d.ts.map +0 -1
  168. package/dist/cli/auth/api-client.js +0 -585
  169. package/dist/cli/auth/device.d.ts +0 -14
  170. package/dist/cli/auth/device.d.ts.map +0 -1
  171. package/dist/cli/auth/device.js +0 -84
  172. package/dist/cli/auth/dexto-api-key.d.ts +0 -34
  173. package/dist/cli/auth/dexto-api-key.d.ts.map +0 -1
  174. package/dist/cli/auth/dexto-api-key.js +0 -160
  175. package/dist/cli/auth/login-persistence.d.ts +0 -15
  176. package/dist/cli/auth/login-persistence.d.ts.map +0 -1
  177. package/dist/cli/auth/login-persistence.js +0 -72
  178. package/dist/cli/auth/oauth.d.ts +0 -39
  179. package/dist/cli/auth/oauth.d.ts.map +0 -1
  180. package/dist/cli/auth/oauth.js +0 -434
  181. package/dist/cli/auth/service.d.ts +0 -24
  182. package/dist/cli/auth/service.d.ts.map +0 -1
  183. package/dist/cli/auth/service.js +0 -161
  184. package/dist/cli/auth/types.d.ts +0 -11
  185. package/dist/cli/auth/types.d.ts.map +0 -1
  186. package/dist/cli/auth/types.js +0 -1
  187. package/dist/cli/cloud-chat.d.ts +0 -18
  188. package/dist/cli/cloud-chat.d.ts.map +0 -1
  189. package/dist/cli/cloud-chat.js +0 -734
  190. package/dist/cli/commands/auth/index.d.ts +0 -4
  191. package/dist/cli/commands/auth/index.d.ts.map +0 -1
  192. package/dist/cli/commands/auth/index.js +0 -4
  193. package/dist/cli/commands/auth/login.d.ts +0 -12
  194. package/dist/cli/commands/auth/login.d.ts.map +0 -1
  195. package/dist/cli/commands/auth/login.js +0 -153
  196. package/dist/cli/commands/auth/logout.d.ts +0 -5
  197. package/dist/cli/commands/auth/logout.d.ts.map +0 -1
  198. package/dist/cli/commands/auth/logout.js +0 -81
  199. package/dist/cli/commands/auth/register.d.ts +0 -3
  200. package/dist/cli/commands/auth/register.d.ts.map +0 -1
  201. package/dist/cli/commands/auth/register.js +0 -96
  202. package/dist/cli/commands/auth/status.d.ts +0 -2
  203. package/dist/cli/commands/auth/status.d.ts.map +0 -1
  204. package/dist/cli/commands/auth/status.js +0 -22
  205. package/dist/cli/commands/billing/index.d.ts +0 -2
  206. package/dist/cli/commands/billing/index.d.ts.map +0 -1
  207. package/dist/cli/commands/billing/index.js +0 -2
  208. package/dist/cli/commands/billing/register.d.ts +0 -3
  209. package/dist/cli/commands/billing/register.d.ts.map +0 -1
  210. package/dist/cli/commands/billing/register.js +0 -20
  211. package/dist/cli/commands/billing/status.d.ts +0 -8
  212. package/dist/cli/commands/billing/status.d.ts.map +0 -1
  213. package/dist/cli/commands/billing/status.js +0 -71
  214. package/dist/cli/commands/cloud/discovery.d.ts +0 -17
  215. package/dist/cli/commands/cloud/discovery.d.ts.map +0 -1
  216. package/dist/cli/commands/cloud/discovery.js +0 -88
  217. package/dist/cli/commands/deploy/client.d.ts +0 -113
  218. package/dist/cli/commands/deploy/client.d.ts.map +0 -1
  219. package/dist/cli/commands/deploy/client.js +0 -519
  220. package/dist/cli/commands/deploy/config.d.ts +0 -37
  221. package/dist/cli/commands/deploy/config.d.ts.map +0 -1
  222. package/dist/cli/commands/deploy/config.js +0 -144
  223. package/dist/cli/commands/deploy/entry-agent.d.ts +0 -3
  224. package/dist/cli/commands/deploy/entry-agent.d.ts.map +0 -1
  225. package/dist/cli/commands/deploy/entry-agent.js +0 -70
  226. package/dist/cli/commands/deploy/index.d.ts +0 -12
  227. package/dist/cli/commands/deploy/index.d.ts.map +0 -1
  228. package/dist/cli/commands/deploy/index.js +0 -370
  229. package/dist/cli/commands/deploy/links.d.ts +0 -3
  230. package/dist/cli/commands/deploy/links.d.ts.map +0 -1
  231. package/dist/cli/commands/deploy/links.js +0 -53
  232. package/dist/cli/commands/deploy/register.d.ts +0 -6
  233. package/dist/cli/commands/deploy/register.d.ts.map +0 -1
  234. package/dist/cli/commands/deploy/register.js +0 -128
  235. package/dist/cli/commands/deploy/snapshot.d.ts +0 -12
  236. package/dist/cli/commands/deploy/snapshot.d.ts.map +0 -1
  237. package/dist/cli/commands/deploy/snapshot.js +0 -76
  238. package/dist/cli/commands/deploy/state.d.ts +0 -13
  239. package/dist/cli/commands/deploy/state.d.ts.map +0 -1
  240. package/dist/cli/commands/deploy/state.js +0 -122
  241. package/dist/cli/commands/span/register.d.ts +0 -6
  242. package/dist/cli/commands/span/register.d.ts.map +0 -1
  243. package/dist/cli/commands/span/register.js +0 -25
  244. package/dist/cli/commands/trace/client.d.ts +0 -98
  245. package/dist/cli/commands/trace/client.d.ts.map +0 -1
  246. package/dist/cli/commands/trace/client.js +0 -150
  247. package/dist/cli/commands/trace/format.d.ts +0 -5
  248. package/dist/cli/commands/trace/format.d.ts.map +0 -1
  249. package/dist/cli/commands/trace/format.js +0 -58
  250. package/dist/cli/commands/trace/index.d.ts +0 -21
  251. package/dist/cli/commands/trace/index.d.ts.map +0 -1
  252. package/dist/cli/commands/trace/index.js +0 -49
  253. package/dist/cli/commands/trace/register.d.ts +0 -6
  254. package/dist/cli/commands/trace/register.d.ts.map +0 -1
  255. package/dist/cli/commands/trace/register.js +0 -71
  256. package/dist/webui/assets/index-DEfRFmFT.js +0 -1667
@@ -0,0 +1,73 @@
1
+ import type { CloudRuntime } from './runtime.js';
2
+ export type LocalChatSource = 'claude-code' | 'codex';
3
+ export declare const LOCAL_CHAT_SOURCES: readonly LocalChatSource[];
4
+ interface LocalChatMessage {
5
+ readonly createdAt: string;
6
+ readonly role: 'assistant' | 'user';
7
+ readonly text: string;
8
+ }
9
+ export interface LocalChat {
10
+ readonly cwd: string | null;
11
+ readonly gitBranch: string | null;
12
+ readonly id: string;
13
+ readonly messages: readonly LocalChatMessage[];
14
+ /** The transcript file it was read from. */
15
+ readonly path: string;
16
+ readonly source: LocalChatSource;
17
+ readonly startedAt: string;
18
+ readonly title: string;
19
+ readonly updatedAt: string;
20
+ }
21
+ /** What `dexto_chat_import` takes; its bounds are the server's too. */
22
+ export interface ChatImportInput {
23
+ readonly cwd?: string;
24
+ readonly gitBranch?: string;
25
+ readonly messages: readonly LocalChatMessage[];
26
+ readonly source: LocalChatSource;
27
+ readonly sourceSessionId: string;
28
+ readonly title: string;
29
+ }
30
+ export declare const MAX_IMPORT_MESSAGES = 2000;
31
+ export declare const MAX_MESSAGE_CHARS = 64000;
32
+ /**
33
+ * A Claude Code session file: one Agent SDK message per line (`type` `user` or `assistant`, with
34
+ * Anthropic `message.content`), plus `summary` lines that title it. Sidechain (subagent) and meta
35
+ * lines are left out, as is thinking.
36
+ */
37
+ export declare function parseClaudeCodeTranscript(text: string, file: string): LocalChat | null;
38
+ /**
39
+ * A Codex rollout: `{timestamp, type, payload}` lines, as `codex-rs/history` writes them. The
40
+ * `session_meta` line names the thread; `response_item` lines carry messages and tool calls.
41
+ * Developer and system messages, injected context and reasoning are left out.
42
+ */
43
+ export declare function parseCodexRollout(text: string, file: string): LocalChat | null;
44
+ export declare function redactSecrets(text: string): {
45
+ counts: Record<string, number>;
46
+ text: string;
47
+ };
48
+ type PreparedImport = {
49
+ readonly input: ChatImportInput;
50
+ readonly kind: 'ready';
51
+ /** How many of each kind of secret were redacted, counted from the markers sent. */
52
+ readonly redactions: Readonly<Record<string, number>>;
53
+ /** How many messages were cut to the size limit. */
54
+ readonly truncated: number;
55
+ } | {
56
+ readonly kind: 'skipped';
57
+ readonly reason: string;
58
+ };
59
+ /** The chat as it is sent: redacted, each message within the size limit, or why it can't go. */
60
+ export declare function toImportInput(chat: LocalChat): PreparedImport;
61
+ export interface LocalChatQuery {
62
+ /** Another sessions folder to read instead of the source's own. */
63
+ readonly dir: string | null;
64
+ /** Keep sessions whose working directory is this folder or inside it. */
65
+ readonly folder: string | null;
66
+ /** Keep sessions with a turn at or after this date. */
67
+ readonly since: string | null;
68
+ readonly source: LocalChatSource;
69
+ }
70
+ /** The source's sessions on this machine that match the query, newest first. */
71
+ export declare function findLocalChats(runtime: Pick<CloudRuntime, 'environment' | 'homeDirectory'>, query: LocalChatQuery): Promise<LocalChat[]>;
72
+ export {};
73
+ //# sourceMappingURL=local-chats.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-chats.d.ts","sourceRoot":"","sources":["../../../src/cli/cloud/local-chats.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,441 @@
1
+ // Reads Claude Code and Codex chats on this machine into redacted, bounded turns to import.
2
+ import { readdir, readFile, stat } from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import { UsageError } from './command.js';
5
+ export const LOCAL_CHAT_SOURCES = ['claude-code', 'codex'];
6
+ export const MAX_IMPORT_MESSAGES = 2_000;
7
+ export const MAX_MESSAGE_CHARS = 64_000;
8
+ const MAX_IMPORT_CHARS = 4_000_000;
9
+ const MAX_TITLE_CHARS = 200;
10
+ const MAX_CWD_CHARS = 1_024;
11
+ const MAX_BRANCH_CHARS = 255;
12
+ /** How much of one tool call's input or result an imported chat keeps. */
13
+ const MAX_TOOL_CHARS = 4_000;
14
+ /** A transcript file larger than this is not read. */
15
+ const MAX_FILE_BYTES = 64 * 1024 * 1024;
16
+ const SOURCE_SESSION_ID = /^[A-Za-z0-9._:-]{1,200}$/u;
17
+ // ---------------------------------------------------------------------------------------------
18
+ // Turns
19
+ // ---------------------------------------------------------------------------------------------
20
+ /**
21
+ * Collects turns as a chat shows them: each person's message, then one assistant message holding
22
+ * everything the agent said and ran until the next one.
23
+ */
24
+ function createTurns() {
25
+ const messages = [];
26
+ let assistant = null;
27
+ let lastAt = null;
28
+ const flush = () => {
29
+ if (assistant !== null && assistant.parts.length > 0)
30
+ messages.push({
31
+ createdAt: assistant.createdAt,
32
+ role: 'assistant',
33
+ text: assistant.parts.join('\n\n'),
34
+ });
35
+ assistant = null;
36
+ };
37
+ return {
38
+ assistant(text, createdAt) {
39
+ if (text.trim() === '')
40
+ return;
41
+ assistant ??= { createdAt, parts: [] };
42
+ assistant.parts.push(text.trim());
43
+ lastAt = createdAt;
44
+ },
45
+ /** The turns, and when the last thing in them happened. */
46
+ done() {
47
+ flush();
48
+ return { lastAt, messages };
49
+ },
50
+ user(text, createdAt) {
51
+ if (text.trim() === '')
52
+ return;
53
+ flush();
54
+ messages.push({ createdAt, role: 'user', text: text.trim() });
55
+ lastAt = createdAt;
56
+ },
57
+ };
58
+ }
59
+ function truncate(text, max) {
60
+ if (text.length <= max)
61
+ return text;
62
+ const marker = `\n… [${text.length - max} more characters left out]`;
63
+ return `${text.slice(0, Math.max(0, max - marker.length))}${marker}`;
64
+ }
65
+ /** Text in a fence no backtick run inside it can close. */
66
+ function fenced(text) {
67
+ const longest = Math.max(2, ...[...text.matchAll(/`+/gu)].map((run) => run[0].length));
68
+ const fence = '`'.repeat(longest + 1);
69
+ return `${fence}\n${text}\n${fence}`;
70
+ }
71
+ /** Redacted whole, then cut: a cut can leave a secret no pattern still matches. */
72
+ function toolBody(text) {
73
+ return fenced(truncate(redactSecrets(text).text, MAX_TOOL_CHARS));
74
+ }
75
+ function toolCallText(name, input) {
76
+ const body = typeof input === 'string' ? prettyJson(input) : JSON.stringify(input ?? null, null, 2);
77
+ return `**Tool call: ${name}**\n${toolBody(body)}`;
78
+ }
79
+ function toolResultText(output) {
80
+ return `**Tool result**\n${toolBody(output)}`;
81
+ }
82
+ /** A JSON string pretty-printed, or as it is when it isn't JSON. */
83
+ function prettyJson(text) {
84
+ try {
85
+ return JSON.stringify(JSON.parse(text), null, 2);
86
+ }
87
+ catch {
88
+ return text;
89
+ }
90
+ }
91
+ function firstLine(text) {
92
+ const line = text.split('\n').find((each) => each.trim() !== '') ?? '';
93
+ return truncate(line.trim(), 80);
94
+ }
95
+ function isRecord(value) {
96
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
97
+ }
98
+ function stringField(value, key) {
99
+ const field = value[key];
100
+ return typeof field === 'string' && field !== '' ? field : null;
101
+ }
102
+ /** Each line that is a JSON object; a torn or foreign line is left out. */
103
+ function jsonLines(text) {
104
+ return text.split('\n').flatMap((line) => {
105
+ if (line.trim() === '')
106
+ return [];
107
+ try {
108
+ const value = JSON.parse(line);
109
+ return isRecord(value) ? [value] : [];
110
+ }
111
+ catch {
112
+ return [];
113
+ }
114
+ });
115
+ }
116
+ function validTime(value) {
117
+ if (value === null)
118
+ return null;
119
+ const time = new Date(value);
120
+ return Number.isNaN(time.getTime()) ? null : time.toISOString();
121
+ }
122
+ function finishChat(fields, { lastAt, messages }) {
123
+ const first = messages[0];
124
+ if (first === undefined || lastAt === null || !messages.some((m) => m.role === 'user'))
125
+ return null;
126
+ const firstUser = messages.find((message) => message.role === 'user');
127
+ return {
128
+ ...fields,
129
+ messages,
130
+ startedAt: first.createdAt,
131
+ title: truncate(fields.title ?? firstLine(firstUser?.text ?? 'Imported chat'), 200),
132
+ updatedAt: lastAt,
133
+ };
134
+ }
135
+ // ---------------------------------------------------------------------------------------------
136
+ // Claude Code
137
+ // ---------------------------------------------------------------------------------------------
138
+ /** What Claude Code writes as a `user` line but the person never typed: slash commands and their output. */
139
+ const CLAUDE_CODE_INJECTED = /^\s*<(command-name|command-message|local-command-[a-z]+)>/u;
140
+ /**
141
+ * A Claude Code session file: one Agent SDK message per line (`type` `user` or `assistant`, with
142
+ * Anthropic `message.content`), plus `summary` lines that title it. Sidechain (subagent) and meta
143
+ * lines are left out, as is thinking.
144
+ */
145
+ export function parseClaudeCodeTranscript(text, file) {
146
+ const turns = createTurns();
147
+ let sessionId = null;
148
+ let cwd = null;
149
+ let gitBranch = null;
150
+ let title = null;
151
+ for (const line of jsonLines(text)) {
152
+ if (line.type === 'summary') {
153
+ title ??= stringField(line, 'summary');
154
+ continue;
155
+ }
156
+ if (line.type !== 'user' && line.type !== 'assistant')
157
+ continue;
158
+ if (line.isSidechain === true || line.isMeta === true)
159
+ continue;
160
+ const message = line.message;
161
+ const at = validTime(stringField(line, 'timestamp'));
162
+ if (!isRecord(message) || at === null)
163
+ continue;
164
+ sessionId ??= stringField(line, 'sessionId');
165
+ cwd ??= stringField(line, 'cwd');
166
+ gitBranch ??= stringField(line, 'gitBranch');
167
+ const content = message.content;
168
+ if (typeof content === 'string') {
169
+ if (line.type === 'assistant')
170
+ turns.assistant(content, at);
171
+ else if (!CLAUDE_CODE_INJECTED.test(content))
172
+ turns.user(content, at);
173
+ continue;
174
+ }
175
+ if (!Array.isArray(content))
176
+ continue;
177
+ for (const block of content) {
178
+ if (!isRecord(block))
179
+ continue;
180
+ if (block.type === 'text' && typeof block.text === 'string') {
181
+ if (line.type === 'assistant')
182
+ turns.assistant(block.text, at);
183
+ else if (!CLAUDE_CODE_INJECTED.test(block.text))
184
+ turns.user(block.text, at);
185
+ }
186
+ else if (block.type === 'tool_use') {
187
+ turns.assistant(toolCallText(stringField(block, 'name') ?? 'tool', block.input), at);
188
+ }
189
+ else if (block.type === 'tool_result') {
190
+ turns.assistant(toolResultText(claudeToolResultText(block.content)), at);
191
+ }
192
+ else if (block.type === 'image' && line.type === 'user') {
193
+ turns.user('[An image was attached here; it was not imported.]', at);
194
+ }
195
+ }
196
+ }
197
+ const id = sessionId ?? path.basename(file, '.jsonl');
198
+ return finishChat({ cwd, gitBranch, id, path: file, source: 'claude-code', title }, turns.done());
199
+ }
200
+ function claudeToolResultText(content) {
201
+ if (typeof content === 'string')
202
+ return content;
203
+ if (!Array.isArray(content))
204
+ return '';
205
+ return content
206
+ .map((part) => isRecord(part) && typeof part.text === 'string'
207
+ ? part.text
208
+ : isRecord(part) && part.type === 'image'
209
+ ? '[image]'
210
+ : '')
211
+ .filter((part) => part !== '')
212
+ .join('\n');
213
+ }
214
+ // ---------------------------------------------------------------------------------------------
215
+ // Codex
216
+ // ---------------------------------------------------------------------------------------------
217
+ /** Context Codex sends as `user` messages that the person never typed. */
218
+ const CODEX_INJECTED = /^\s*(<environment_context>|<user_instructions>|<permissions instructions>|<turn_aborted>|# AGENTS\.md instructions)/u;
219
+ /**
220
+ * A Codex rollout: `{timestamp, type, payload}` lines, as `codex-rs/history` writes them. The
221
+ * `session_meta` line names the thread; `response_item` lines carry messages and tool calls.
222
+ * Developer and system messages, injected context and reasoning are left out.
223
+ */
224
+ export function parseCodexRollout(text, file) {
225
+ const turns = createTurns();
226
+ let id = null;
227
+ let cwd = null;
228
+ let gitBranch = null;
229
+ for (const line of jsonLines(text)) {
230
+ const payload = line.payload;
231
+ if (!isRecord(payload))
232
+ continue;
233
+ if (line.type === 'session_meta') {
234
+ id ??= stringField(payload, 'id');
235
+ cwd ??= stringField(payload, 'cwd');
236
+ if (isRecord(payload.git))
237
+ gitBranch ??= stringField(payload.git, 'branch');
238
+ continue;
239
+ }
240
+ const at = validTime(stringField(line, 'timestamp'));
241
+ if (line.type !== 'response_item' || at === null)
242
+ continue;
243
+ switch (payload.type) {
244
+ case 'message': {
245
+ const said = codexContentText(payload.content);
246
+ if (payload.role === 'user' && !CODEX_INJECTED.test(said))
247
+ turns.user(said, at);
248
+ if (payload.role === 'assistant')
249
+ turns.assistant(said, at);
250
+ break;
251
+ }
252
+ case 'function_call':
253
+ turns.assistant(toolCallText(stringField(payload, 'name') ?? 'tool', payload.arguments ?? ''), at);
254
+ break;
255
+ case 'custom_tool_call':
256
+ turns.assistant(toolCallText(stringField(payload, 'name') ?? 'tool', payload.input ?? ''), at);
257
+ break;
258
+ case 'local_shell_call': {
259
+ const action = isRecord(payload.action) ? payload.action : {};
260
+ const command = Array.isArray(action.command) ? action.command : [];
261
+ turns.assistant(toolCallText('shell', { command }), at);
262
+ break;
263
+ }
264
+ case 'function_call_output':
265
+ case 'custom_tool_call_output':
266
+ turns.assistant(toolResultText(codexOutputText(payload.output)), at);
267
+ break;
268
+ }
269
+ }
270
+ return finishChat({
271
+ cwd,
272
+ gitBranch,
273
+ id: id ?? path.basename(file, '.jsonl'),
274
+ path: file,
275
+ source: 'codex',
276
+ title: null,
277
+ }, turns.done());
278
+ }
279
+ function codexContentText(content) {
280
+ if (!Array.isArray(content))
281
+ return '';
282
+ return content
283
+ .map((part) => (isRecord(part) && typeof part.text === 'string' ? part.text : ''))
284
+ .filter((part) => part !== '')
285
+ .join('\n');
286
+ }
287
+ function codexOutputText(output) {
288
+ if (typeof output === 'string')
289
+ return output;
290
+ if (isRecord(output) && typeof output.content === 'string')
291
+ return output.content;
292
+ return codexContentText(output);
293
+ }
294
+ // ---------------------------------------------------------------------------------------------
295
+ // Redaction and bounds
296
+ // ---------------------------------------------------------------------------------------------
297
+ /** Credential shapes, most specific first; each match becomes `[redacted:<kind>]`. */
298
+ const SECRET_PATTERNS = [
299
+ ['private_key', /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/gu],
300
+ ['secret_key', /\bsk-[A-Za-z0-9_-]{20,}/gu],
301
+ ['github_token', /\b(?:gh[pousr]_[A-Za-z0-9]{36,}|github_pat_[A-Za-z0-9_]{22,})/gu],
302
+ ['aws_access_key', /\b(?:AKIA|ASIA)[0-9A-Z]{16}\b/gu],
303
+ ['slack_token', /\bxox[abprs]-[A-Za-z0-9-]{10,}/gu],
304
+ ['google_api_key', /\bAIza[0-9A-Za-z_-]{35}/gu],
305
+ ['jwt', /\beyJ[A-Za-z0-9_-]{8,}\.eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}/gu],
306
+ ['bearer_token', /\bBearer\s+[A-Za-z0-9._~+/=-]{16,}/gu],
307
+ ];
308
+ /** `password = value` and the like: the name stays, the value goes. */
309
+ const SECRET_ASSIGNMENT = /\b((?:[A-Za-z0-9_]*_)?(?:password|passwd|secret|token|api[_-]?key)["']?\s*[:=]\s*["']?)([^\s"'[]{8,})/giu;
310
+ const REDACTED_MARKER = /\[redacted:([a-z_]+)\]/gu;
311
+ export function redactSecrets(text) {
312
+ const counts = {};
313
+ const count = (kind) => {
314
+ counts[kind] = (counts[kind] ?? 0) + 1;
315
+ };
316
+ let redacted = text;
317
+ for (const [kind, pattern] of SECRET_PATTERNS)
318
+ redacted = redacted.replace(pattern, () => {
319
+ count(kind);
320
+ return `[redacted:${kind}]`;
321
+ });
322
+ redacted = redacted.replace(SECRET_ASSIGNMENT, (_match, name) => {
323
+ count('assignment');
324
+ return `${name}[redacted:assignment]`;
325
+ });
326
+ return { counts, text: redacted };
327
+ }
328
+ /** The chat as it is sent: redacted, each message within the size limit, or why it can't go. */
329
+ export function toImportInput(chat) {
330
+ if (!SOURCE_SESSION_ID.test(chat.id))
331
+ return { kind: 'skipped', reason: "Its session id isn't one Dexto takes." };
332
+ if (chat.messages.length > MAX_IMPORT_MESSAGES)
333
+ return { kind: 'skipped', reason: `It has more than ${MAX_IMPORT_MESSAGES} messages.` };
334
+ let truncated = 0;
335
+ let total = 0;
336
+ const messages = chat.messages.map((message) => {
337
+ const { text } = redactSecrets(message.text);
338
+ if (text.length > MAX_MESSAGE_CHARS)
339
+ truncated += 1;
340
+ const bounded = truncate(text, MAX_MESSAGE_CHARS);
341
+ total += bounded.length;
342
+ return { createdAt: message.createdAt, role: message.role, text: bounded };
343
+ });
344
+ if (total > MAX_IMPORT_CHARS)
345
+ return {
346
+ kind: 'skipped',
347
+ reason: `It has more than ${MAX_IMPORT_CHARS.toLocaleString('en-US')} characters.`,
348
+ };
349
+ const title = redactSecrets(chat.title).text.slice(0, MAX_TITLE_CHARS);
350
+ const cwd = chat.cwd === null ? null : redactSecrets(chat.cwd).text;
351
+ const gitBranch = chat.gitBranch === null ? null : redactSecrets(chat.gitBranch).text;
352
+ const input = {
353
+ ...(cwd === null || cwd.length > MAX_CWD_CHARS ? {} : { cwd }),
354
+ ...(gitBranch === null || gitBranch.length > MAX_BRANCH_CHARS ? {} : { gitBranch }),
355
+ messages,
356
+ source: chat.source,
357
+ sourceSessionId: chat.id,
358
+ title: title.trim() === '' ? 'Imported chat' : title,
359
+ };
360
+ return { input, kind: 'ready', redactions: redactionCounts(input), truncated };
361
+ }
362
+ /** Each `[redacted:<kind>]` in what is sent, including those made while reading tool output. */
363
+ function redactionCounts(input) {
364
+ const counts = {};
365
+ const sent = [input.title, input.cwd ?? '', input.gitBranch ?? ''];
366
+ for (const text of [...sent, ...input.messages.map((message) => message.text)])
367
+ for (const [, kind = ''] of text.matchAll(REDACTED_MARKER))
368
+ counts[kind] = (counts[kind] ?? 0) + 1;
369
+ return counts;
370
+ }
371
+ /** Where a source keeps its sessions on this machine. */
372
+ function localChatsFolder(runtime, source) {
373
+ if (source === 'claude-code')
374
+ return path.join(runtime.environment.CLAUDE_CONFIG_DIR ?? path.join(runtime.homeDirectory, '.claude'), 'projects');
375
+ return path.join(runtime.environment.CODEX_HOME ?? path.join(runtime.homeDirectory, '.codex'), 'sessions');
376
+ }
377
+ /** The source's sessions on this machine that match the query, newest first. */
378
+ export async function findLocalChats(runtime, query) {
379
+ if (query.dir !== null)
380
+ await readdir(query.dir).catch(() => {
381
+ throw new UsageError(`--dir ${query.dir} is not a folder this can read.`);
382
+ });
383
+ const folder = query.dir ?? localChatsFolder(runtime, query.source);
384
+ const since = query.since === null ? null : new Date(query.since);
385
+ const files = query.source === 'claude-code' ? await claudeCodeFiles(folder) : await codexFiles(folder);
386
+ const parse = query.source === 'claude-code' ? parseClaudeCodeTranscript : parseCodexRollout;
387
+ const within = query.folder === null ? null : path.resolve(query.folder);
388
+ const chats = [];
389
+ for (const file of files) {
390
+ const stats = await stat(file).catch(() => null);
391
+ if (stats === null || stats.size > MAX_FILE_BYTES)
392
+ continue;
393
+ const chat = parse(await readFile(file, 'utf8'), file);
394
+ if (chat === null)
395
+ continue;
396
+ if (since !== null && new Date(chat.updatedAt) < since)
397
+ continue;
398
+ if (within !== null && !insideFolder(chat.cwd, within))
399
+ continue;
400
+ chats.push(chat);
401
+ }
402
+ return chats.sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
403
+ }
404
+ function insideFolder(cwd, folder) {
405
+ if (cwd === null)
406
+ return false;
407
+ const relative = path.relative(folder, cwd);
408
+ return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
409
+ }
410
+ async function entries(folder) {
411
+ return await readdir(folder, { withFileTypes: true }).catch(() => []);
412
+ }
413
+ /** `projects/<project>/<session>.jsonl`; deeper files are a session's subagents. */
414
+ async function claudeCodeFiles(folder) {
415
+ const files = [];
416
+ for (const project of await entries(folder)) {
417
+ if (!project.isDirectory())
418
+ continue;
419
+ for (const file of await entries(path.join(folder, project.name)))
420
+ if (file.isFile() && file.name.endsWith('.jsonl'))
421
+ files.push(path.join(folder, project.name, file.name));
422
+ }
423
+ return files;
424
+ }
425
+ /** `sessions/YYYY/MM/DD/rollout-*.jsonl`; compressed rollouts are left out. */
426
+ async function codexFiles(folder) {
427
+ const files = [];
428
+ const visit = async (dir, depth) => {
429
+ for (const entry of await entries(dir)) {
430
+ const full = path.join(dir, entry.name);
431
+ if (entry.isDirectory() && depth < 3)
432
+ await visit(full, depth + 1);
433
+ else if (entry.isFile() &&
434
+ entry.name.startsWith('rollout-') &&
435
+ entry.name.endsWith('.jsonl'))
436
+ files.push(full);
437
+ }
438
+ };
439
+ await visit(folder, 0);
440
+ return files;
441
+ }
@@ -0,0 +1,34 @@
1
+ import type { CloudRuntime } from './runtime.js';
2
+ export interface Column<Row> {
3
+ readonly header: string;
4
+ readonly value: (row: Row) => string | number | boolean | null | undefined;
5
+ }
6
+ export interface Output {
7
+ /** Whether records and lists print as JSON. */
8
+ readonly json: boolean;
9
+ /**
10
+ * Whether content, such as a file, a command's output or a model's reply, prints as its JSON
11
+ * record: only with an explicit --json, so piped content stays intact.
12
+ */
13
+ readonly jsonContent: boolean;
14
+ /** A page of a list: a table, plus how to read the next page when there is one. */
15
+ list<Row>(page: ListPage<Row>, columns: readonly Column<Row>[]): void;
16
+ /** One resource: its fields, one per line. */
17
+ record(value: unknown): void;
18
+ /** A line for people; JSON output prints the value instead. */
19
+ result(value: unknown, text: string): void;
20
+ /** Progress and hints, on stderr so stdout stays parseable. */
21
+ note(text: string): void;
22
+ }
23
+ /** A list, paged or not: some `/v1` lists return everything at once. */
24
+ export type ListPage<Row> = {
25
+ readonly data: readonly Row[];
26
+ } | {
27
+ readonly data: readonly Row[];
28
+ readonly has_more: boolean;
29
+ readonly next_after: string | number | null;
30
+ };
31
+ /** `json` and `table` as asked; `auto` is tables at a terminal and JSON anywhere else. */
32
+ export type OutputFormat = 'auto' | 'json' | 'table';
33
+ export declare function createOutput(runtime: CloudRuntime, format: OutputFormat): Output;
34
+ //# sourceMappingURL=output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../../src/cli/cloud/output.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,WAAW,MAAM,CAAC,GAAG;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC;CAC9E;AAED,MAAM,WAAW,MAAM;IACnB,+CAA+C;IAC/C,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,mFAAmF;IACnF,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,SAAS,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC;IACtE,8CAA8C;IAC9C,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAC7B,+DAA+D;IAC/D,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAE3C,+DAA+D;IAC/D,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,wEAAwE;AACxE,MAAM,MAAM,QAAQ,CAAC,GAAG,IAClB;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,EAAE,CAAA;CAAE,GACjC;IACI,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,EAAE,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;CAC/C,CAAC;AAER,0FAA0F;AAC1F,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAErD,wBAAgB,YAAY,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,CAiChF"}
@@ -0,0 +1,76 @@
1
+ // Prints API values: JSON for agents (--json, or stdout not a terminal), tables for people.
2
+ import chalk from 'chalk';
3
+ export function createOutput(runtime, format) {
4
+ const json = format === 'json' || (format === 'auto' && !runtime.stdoutIsTerminal);
5
+ const color = runtime.color;
6
+ const printJson = (value) => {
7
+ runtime.writeOutput(`${JSON.stringify(value, null, 2)}\n`);
8
+ };
9
+ return {
10
+ json,
11
+ jsonContent: format === 'json',
12
+ list(page, columns) {
13
+ if (json)
14
+ return printJson(page);
15
+ if (page.data.length === 0) {
16
+ runtime.writeOutput(`${dim('None.', color)}\n`);
17
+ return;
18
+ }
19
+ runtime.writeOutput(renderTable(page.data, columns, color));
20
+ if ('next_after' in page && page.has_more && page.next_after !== null)
21
+ runtime.writeError(`${dim(`More results: add --after ${String(page.next_after)}`, color)}\n`);
22
+ },
23
+ note(text) {
24
+ runtime.writeError(`${dim(text, color)}\n`);
25
+ },
26
+ record(value) {
27
+ if (json)
28
+ return printJson(value);
29
+ runtime.writeOutput(renderRecord(value, color));
30
+ },
31
+ result(value, text) {
32
+ if (json)
33
+ return printJson(value);
34
+ runtime.writeOutput(`${text}\n`);
35
+ },
36
+ };
37
+ }
38
+ function renderTable(rows, columns, color) {
39
+ const cells = rows.map((row) => columns.map((column) => cell(column.value(row))));
40
+ const widths = columns.map((column, index) => Math.max(column.header.length, ...cells.map((row) => (row[index] ?? '').length)));
41
+ const line = (values) => values
42
+ .map((value, index) => index === values.length - 1 ? value : value.padEnd(widths[index] ?? 0))
43
+ .join(' ')
44
+ .trimEnd();
45
+ const header = line(columns.map((column) => column.header.toUpperCase()));
46
+ return `${color ? chalk.bold(header) : header}\n${cells.map(line).join('\n')}\n`;
47
+ }
48
+ /** Top-level fields aligned; nested values as compact JSON. */
49
+ function renderRecord(value, color) {
50
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
51
+ return `${JSON.stringify(value, null, 2)}\n`;
52
+ const entries = Object.entries(value);
53
+ const width = Math.max(...entries.map(([key]) => key.length));
54
+ return `${entries
55
+ .map(([key, field]) => `${dim(key.padEnd(width), color)} ${recordField(field)}`)
56
+ .join('\n')}\n`;
57
+ }
58
+ function recordField(value) {
59
+ if (value === null)
60
+ return '-';
61
+ if (typeof value === 'string')
62
+ return value.includes('\n') ? JSON.stringify(value) : value;
63
+ if (typeof value === 'number' || typeof value === 'boolean')
64
+ return String(value);
65
+ return JSON.stringify(value);
66
+ }
67
+ const MAX_CELL = 60;
68
+ function cell(value) {
69
+ if (value === null || value === undefined)
70
+ return '-';
71
+ const text = String(value).replace(/\s+/gu, ' ');
72
+ return text.length > MAX_CELL ? `${text.slice(0, MAX_CELL - 1)}…` : text;
73
+ }
74
+ function dim(text, color) {
75
+ return color ? chalk.dim(text) : text;
76
+ }
@@ -0,0 +1,26 @@
1
+ import { type Command, type OptionSpec } from './command.js';
2
+ import type { SignInFor } from './commands/account.js';
3
+ import type { Connection, ConnectionOverrides } from './connection.js';
4
+ import type { CloudRuntime } from './runtime.js';
5
+ /** One area of commands in help, such as `projects` under `cloud`. */
6
+ export interface Group {
7
+ readonly name: string;
8
+ readonly summary: string;
9
+ }
10
+ /** What the commands run against: injected so tests use a fake server and sign-in. */
11
+ export interface CloudHost {
12
+ readonly commands: readonly Command[];
13
+ /** Help's areas by the words before them, such as `cloud`. */
14
+ readonly groups: Readonly<Record<string, readonly Group[]>>;
15
+ readonly runtime: CloudRuntime;
16
+ /** The connection for these overrides; null when signed out. */
17
+ readonly resolveConnection: (overrides: ConnectionOverrides) => Promise<Connection | null>;
18
+ /** The sign-in context login, logout, whoami and accounts run in. */
19
+ readonly signIn: SignInFor;
20
+ /** Signs the profile in again asking for `scope`; true once it did. */
21
+ readonly signInForScope: (overrides: ConnectionOverrides, scope: string) => Promise<boolean>;
22
+ }
23
+ export declare const GLOBAL_OPTIONS: Readonly<Record<string, OptionSpec>>;
24
+ /** Runs one command line, such as `cloud secrets list --json`; returns its exit code. */
25
+ export declare function runCloud(host: CloudHost, argv: readonly string[]): Promise<number>;
26
+ //# sourceMappingURL=run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/cli/cloud/run.ts"],"names":[],"mappings":"AAKA,OAAO,EAOH,KAAK,OAAO,EAGZ,KAAK,UAAU,EAElB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAOvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,sEAAsE;AACtE,MAAM,WAAW,KAAK;IAClB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC5B;AAED,sFAAsF;AACtF,MAAM,WAAW,SAAS;IACtB,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IACtC,8DAA8D;IAC9D,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC,CAAC,CAAC;IAC5D,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,gEAAgE;IAChE,QAAQ,CAAC,iBAAiB,EAAE,CAAC,SAAS,EAAE,mBAAmB,KAAK,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IAC3F,qEAAqE;IACrE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,uEAAuE;IACvE,QAAQ,CAAC,cAAc,EAAE,CAAC,SAAS,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAChG;AAED,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAgC/D,CAAC;AASF,yFAAyF;AACzF,wBAAsB,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAExF"}