@agentuity/cli 0.0.58 → 0.0.59

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 (143) hide show
  1. package/dist/cmd/build/bundler.d.ts +1 -1
  2. package/dist/cmd/cloud/agent/get.d.ts +2 -0
  3. package/dist/cmd/cloud/agent/get.d.ts.map +1 -0
  4. package/dist/cmd/cloud/agent/get.js +97 -0
  5. package/dist/cmd/cloud/agent/get.js.map +1 -0
  6. package/dist/cmd/cloud/agent/index.d.ts +2 -0
  7. package/dist/cmd/cloud/agent/index.d.ts.map +1 -0
  8. package/dist/cmd/cloud/agent/index.js +11 -0
  9. package/dist/cmd/cloud/agent/index.js.map +1 -0
  10. package/dist/cmd/cloud/agent/list.d.ts +2 -0
  11. package/dist/cmd/cloud/agent/list.d.ts.map +1 -0
  12. package/dist/cmd/cloud/agent/list.js +101 -0
  13. package/dist/cmd/cloud/agent/list.js.map +1 -0
  14. package/dist/cmd/cloud/agent/schema.d.ts +4 -0
  15. package/dist/cmd/cloud/agent/schema.d.ts.map +1 -0
  16. package/dist/cmd/cloud/agent/schema.js +22 -0
  17. package/dist/cmd/cloud/agent/schema.js.map +1 -0
  18. package/dist/cmd/cloud/apikey/create.d.ts +2 -0
  19. package/dist/cmd/cloud/apikey/create.d.ts.map +1 -0
  20. package/dist/cmd/cloud/apikey/create.js +100 -0
  21. package/dist/cmd/cloud/apikey/create.js.map +1 -0
  22. package/dist/cmd/cloud/apikey/delete.d.ts +2 -0
  23. package/dist/cmd/cloud/apikey/delete.d.ts.map +1 -0
  24. package/dist/cmd/cloud/apikey/delete.js +55 -0
  25. package/dist/cmd/cloud/apikey/delete.js.map +1 -0
  26. package/dist/cmd/cloud/apikey/get.d.ts +2 -0
  27. package/dist/cmd/cloud/apikey/get.d.ts.map +1 -0
  28. package/dist/cmd/cloud/apikey/get.js +57 -0
  29. package/dist/cmd/cloud/apikey/get.js.map +1 -0
  30. package/dist/cmd/cloud/apikey/index.d.ts.map +1 -0
  31. package/dist/cmd/cloud/apikey/index.js +13 -0
  32. package/dist/cmd/cloud/apikey/index.js.map +1 -0
  33. package/dist/cmd/cloud/apikey/list.d.ts +2 -0
  34. package/dist/cmd/cloud/apikey/list.d.ts.map +1 -0
  35. package/dist/cmd/cloud/apikey/list.js +53 -0
  36. package/dist/cmd/cloud/apikey/list.js.map +1 -0
  37. package/dist/cmd/cloud/deployment/index.d.ts.map +1 -1
  38. package/dist/cmd/cloud/deployment/index.js +2 -0
  39. package/dist/cmd/cloud/deployment/index.js.map +1 -1
  40. package/dist/cmd/cloud/deployment/logs.d.ts +2 -0
  41. package/dist/cmd/cloud/deployment/logs.d.ts.map +1 -0
  42. package/dist/cmd/cloud/deployment/logs.js +70 -0
  43. package/dist/cmd/cloud/deployment/logs.js.map +1 -0
  44. package/dist/cmd/cloud/index.d.ts.map +1 -1
  45. package/dist/cmd/cloud/index.js +8 -2
  46. package/dist/cmd/cloud/index.js.map +1 -1
  47. package/dist/cmd/cloud/session/logs.d.ts.map +1 -1
  48. package/dist/cmd/cloud/session/logs.js +12 -9
  49. package/dist/cmd/cloud/session/logs.js.map +1 -1
  50. package/dist/cmd/cloud/stream/delete.d.ts +3 -0
  51. package/dist/cmd/cloud/stream/delete.d.ts.map +1 -0
  52. package/dist/cmd/cloud/stream/delete.js +42 -0
  53. package/dist/cmd/cloud/stream/delete.js.map +1 -0
  54. package/dist/cmd/cloud/stream/get.d.ts +3 -0
  55. package/dist/cmd/cloud/stream/get.d.ts.map +1 -0
  56. package/dist/cmd/cloud/stream/get.js +110 -0
  57. package/dist/cmd/cloud/stream/get.js.map +1 -0
  58. package/dist/cmd/cloud/stream/index.d.ts +3 -0
  59. package/dist/cmd/cloud/stream/index.d.ts.map +1 -0
  60. package/dist/cmd/cloud/stream/index.js +13 -0
  61. package/dist/cmd/cloud/stream/index.js.map +1 -0
  62. package/dist/cmd/cloud/stream/list.d.ts +3 -0
  63. package/dist/cmd/cloud/stream/list.d.ts.map +1 -0
  64. package/dist/cmd/cloud/stream/list.js +131 -0
  65. package/dist/cmd/cloud/stream/list.js.map +1 -0
  66. package/dist/cmd/cloud/stream/util.d.ts +8 -0
  67. package/dist/cmd/cloud/stream/util.d.ts.map +1 -0
  68. package/dist/cmd/cloud/stream/util.js +19 -0
  69. package/dist/cmd/cloud/stream/util.js.map +1 -0
  70. package/dist/cmd/cloud/vector/delete.d.ts +3 -0
  71. package/dist/cmd/cloud/vector/delete.d.ts.map +1 -0
  72. package/dist/cmd/cloud/vector/delete.js +90 -0
  73. package/dist/cmd/cloud/vector/delete.js.map +1 -0
  74. package/dist/cmd/cloud/vector/get.d.ts +3 -0
  75. package/dist/cmd/cloud/vector/get.d.ts.map +1 -0
  76. package/dist/cmd/cloud/vector/get.js +80 -0
  77. package/dist/cmd/cloud/vector/get.js.map +1 -0
  78. package/dist/cmd/cloud/vector/index.d.ts +3 -0
  79. package/dist/cmd/cloud/vector/index.d.ts.map +1 -0
  80. package/dist/cmd/cloud/vector/index.js +14 -0
  81. package/dist/cmd/cloud/vector/index.js.map +1 -0
  82. package/dist/cmd/cloud/vector/search.d.ts +3 -0
  83. package/dist/cmd/cloud/vector/search.d.ts.map +1 -0
  84. package/dist/cmd/cloud/vector/search.js +136 -0
  85. package/dist/cmd/cloud/vector/search.js.map +1 -0
  86. package/dist/cmd/cloud/vector/util.d.ts +8 -0
  87. package/dist/cmd/cloud/vector/util.d.ts.map +1 -0
  88. package/dist/cmd/cloud/vector/util.js +18 -0
  89. package/dist/cmd/cloud/vector/util.js.map +1 -0
  90. package/dist/cmd/dev/agents.d.ts.map +1 -1
  91. package/dist/cmd/dev/agents.js +3 -2
  92. package/dist/cmd/dev/agents.js.map +1 -1
  93. package/dist/cmd/dev/index.js +3 -3
  94. package/dist/cmd/dev/index.js.map +1 -1
  95. package/dist/cmd/index.d.ts.map +1 -1
  96. package/dist/cmd/index.js +38 -42
  97. package/dist/cmd/index.js.map +1 -1
  98. package/dist/schema-parser.d.ts.map +1 -1
  99. package/dist/schema-parser.js +3 -1
  100. package/dist/schema-parser.js.map +1 -1
  101. package/dist/tui.d.ts +10 -1
  102. package/dist/tui.d.ts.map +1 -1
  103. package/dist/tui.js +58 -31
  104. package/dist/tui.js.map +1 -1
  105. package/dist/utils/date.d.ts +14 -0
  106. package/dist/utils/date.d.ts.map +1 -0
  107. package/dist/utils/date.js +51 -0
  108. package/dist/utils/date.js.map +1 -0
  109. package/package.json +6 -6
  110. package/src/cmd/cloud/agent/get.ts +105 -0
  111. package/src/cmd/cloud/agent/index.ts +11 -0
  112. package/src/cmd/cloud/agent/list.ts +107 -0
  113. package/src/cmd/cloud/agent/schema.ts +25 -0
  114. package/src/cmd/cloud/apikey/create.ts +114 -0
  115. package/src/cmd/cloud/apikey/delete.ts +66 -0
  116. package/src/cmd/cloud/apikey/get.ts +62 -0
  117. package/src/cmd/cloud/apikey/index.ts +13 -0
  118. package/src/cmd/cloud/apikey/list.ts +58 -0
  119. package/src/cmd/cloud/deployment/index.ts +2 -0
  120. package/src/cmd/cloud/deployment/logs.ts +75 -0
  121. package/src/cmd/cloud/index.ts +8 -2
  122. package/src/cmd/cloud/session/logs.ts +12 -11
  123. package/src/cmd/cloud/stream/delete.ts +49 -0
  124. package/src/cmd/cloud/stream/get.ts +118 -0
  125. package/src/cmd/cloud/stream/index.ts +14 -0
  126. package/src/cmd/cloud/stream/list.ts +146 -0
  127. package/src/cmd/cloud/stream/util.ts +32 -0
  128. package/src/cmd/cloud/vector/delete.ts +105 -0
  129. package/src/cmd/cloud/vector/get.ts +94 -0
  130. package/src/cmd/cloud/vector/index.ts +15 -0
  131. package/src/cmd/cloud/vector/search.ts +156 -0
  132. package/src/cmd/cloud/vector/util.ts +28 -0
  133. package/src/cmd/dev/agents.ts +4 -3
  134. package/src/cmd/dev/index.ts +3 -3
  135. package/src/cmd/index.ts +38 -42
  136. package/src/schema-parser.ts +3 -1
  137. package/src/tui.ts +69 -36
  138. package/src/utils/date.ts +57 -0
  139. package/dist/cmd/cloud/agents/index.d.ts.map +0 -1
  140. package/dist/cmd/cloud/agents/index.js +0 -133
  141. package/dist/cmd/cloud/agents/index.js.map +0 -1
  142. package/src/cmd/cloud/agents/index.ts +0 -148
  143. /package/dist/cmd/cloud/{agents → apikey}/index.d.ts +0 -0
@@ -0,0 +1,66 @@
1
+ import { z } from 'zod';
2
+ import { createSubcommand } from '../../../types';
3
+ import * as tui from '../../../tui';
4
+ import { apikeyDelete } from '@agentuity/server';
5
+ import { getCommand } from '../../../command-prefix';
6
+ import { ErrorCode } from '../../../errors';
7
+
8
+ const APIKeyDeleteResponseSchema = z.object({
9
+ success: z.boolean().describe('Whether the operation succeeded'),
10
+ id: z.string().describe('API key id that was deleted'),
11
+ });
12
+
13
+ export const deleteSubcommand = createSubcommand({
14
+ name: 'delete',
15
+ aliases: ['del', 'rm'],
16
+ description: 'Delete an API key (soft delete)',
17
+ tags: ['destructive', 'deletes-resource', 'slow', 'requires-auth'],
18
+ idempotent: true,
19
+ examples: [
20
+ getCommand('cloud apikey delete <id>'),
21
+ getCommand('cloud apikey del <id>'),
22
+ getCommand('cloud apikey rm <id>'),
23
+ ],
24
+ requires: { auth: true, apiClient: true },
25
+ schema: {
26
+ args: z.object({
27
+ id: z.string().describe('the API key id to delete'),
28
+ }),
29
+ response: APIKeyDeleteResponseSchema,
30
+ },
31
+
32
+ async handler(ctx) {
33
+ const { args, apiClient, options } = ctx;
34
+
35
+ let rowsAffected: Awaited<ReturnType<typeof apikeyDelete>>;
36
+ try {
37
+ rowsAffected = await tui.spinner('Deleting API key', () => {
38
+ return apikeyDelete(apiClient, args.id);
39
+ });
40
+ } catch (error) {
41
+ if (error instanceof Error && error.message.includes('not found')) {
42
+ tui.fatal(
43
+ `API key '${args.id}' not found or is not a custom key`,
44
+ ErrorCode.RESOURCE_NOT_FOUND
45
+ );
46
+ }
47
+ throw error;
48
+ }
49
+
50
+ if (rowsAffected === 0) {
51
+ tui.fatal(
52
+ `API key '${args.id}' not found or is not a custom key`,
53
+ ErrorCode.RESOURCE_NOT_FOUND
54
+ );
55
+ }
56
+
57
+ if (!options.json) {
58
+ tui.success(`API key '${args.id}' deleted successfully`);
59
+ }
60
+
61
+ return {
62
+ success: true,
63
+ id: args.id,
64
+ };
65
+ },
66
+ });
@@ -0,0 +1,62 @@
1
+ import { z } from 'zod';
2
+ import { createSubcommand } from '../../../types';
3
+ import * as tui from '../../../tui';
4
+ import { apikeyGet } from '@agentuity/server';
5
+ import { getCommand } from '../../../command-prefix';
6
+ import { ErrorCode } from '../../../errors';
7
+
8
+ export const getSubcommand = createSubcommand({
9
+ name: 'get',
10
+ description: 'Get a specific API key by id',
11
+ tags: ['read-only', 'fast', 'requires-auth'],
12
+ examples: [getCommand('cloud apikey get <id>')],
13
+ requires: { auth: true, apiClient: true },
14
+ idempotent: true,
15
+ schema: {
16
+ args: z.object({
17
+ id: z.string().describe('the API key id'),
18
+ }),
19
+ },
20
+
21
+ async handler(ctx) {
22
+ const { args, apiClient, options } = ctx;
23
+
24
+ let apiKey: Awaited<ReturnType<typeof apikeyGet>>;
25
+ try {
26
+ apiKey = await tui.spinner('Fetching API key', () => {
27
+ return apikeyGet(apiClient, args.id);
28
+ });
29
+ } catch (error) {
30
+ if (error instanceof Error && error.message.includes('not found')) {
31
+ tui.fatal(`API key '${args.id}' not found`, ErrorCode.RESOURCE_NOT_FOUND);
32
+ }
33
+ throw error;
34
+ }
35
+
36
+ if (!options.json) {
37
+ if (process.stdout.isTTY) {
38
+ tui.newline();
39
+ tui.success('API Key Details:');
40
+ tui.newline();
41
+ }
42
+
43
+ const rows = [
44
+ {
45
+ ID: apiKey.id,
46
+ Name: apiKey.name,
47
+ Type: apiKey.type,
48
+ 'Organization ID': apiKey.orgId,
49
+ Project: apiKey.project?.name ?? '-',
50
+ 'Project ID': apiKey.project?.id ?? '-',
51
+ 'Last Used': apiKey.lastUsedAt || 'Never',
52
+ 'Expires At': apiKey.expiresAt ?? 'Never',
53
+ 'Created At': apiKey.createdAt,
54
+ },
55
+ ];
56
+
57
+ tui.table(rows);
58
+ }
59
+
60
+ return apiKey;
61
+ },
62
+ });
@@ -0,0 +1,13 @@
1
+ import { createCommand } from '../../../types';
2
+ import { createSubcommand } from './create';
3
+ import { listSubcommand } from './list';
4
+ import { getSubcommand } from './get';
5
+ import { deleteSubcommand } from './delete';
6
+
7
+ export const command = createCommand({
8
+ name: 'apikey',
9
+ description: 'Manage API keys',
10
+ tags: ['fast', 'requires-auth'],
11
+ subcommands: [createSubcommand, listSubcommand, getSubcommand, deleteSubcommand],
12
+ });
13
+ export default command;
@@ -0,0 +1,58 @@
1
+ import { z } from 'zod';
2
+ import { createSubcommand } from '../../../types';
3
+ import * as tui from '../../../tui';
4
+ import { apikeyList } from '@agentuity/server';
5
+ import { getCommand } from '../../../command-prefix';
6
+
7
+ export const listSubcommand = createSubcommand({
8
+ name: 'list',
9
+ aliases: ['ls'],
10
+ description: 'List all API keys',
11
+ tags: ['read-only', 'fast', 'requires-auth'],
12
+ examples: [getCommand('cloud apikey list'), getCommand('cloud apikey ls')],
13
+ requires: { auth: true, apiClient: true },
14
+ idempotent: true,
15
+ schema: {
16
+ options: z.object({
17
+ orgId: z.string().optional().describe('filter by organization id'),
18
+ projectId: z.string().optional().describe('filter by project id'),
19
+ }),
20
+ },
21
+
22
+ async handler(ctx) {
23
+ const { opts, apiClient, options } = ctx;
24
+
25
+ const apiKeys = await tui.spinner('Fetching API keys', () => {
26
+ return apikeyList(apiClient, {
27
+ orgId: opts?.orgId,
28
+ projectId: opts?.projectId,
29
+ });
30
+ });
31
+
32
+ if (!options.json) {
33
+ if (apiKeys.length === 0) {
34
+ tui.info('No API keys found');
35
+ } else {
36
+ if (process.stdout.isTTY) {
37
+ tui.newline();
38
+ tui.success(`API Keys (${apiKeys.length}):`);
39
+ tui.newline();
40
+ }
41
+
42
+ const rows = apiKeys.map((key) => ({
43
+ ID: key.id,
44
+ Name: key.name,
45
+ Type: key.type,
46
+ Project: key.project?.name ?? '-',
47
+ 'Last Used': key.lastUsedAt || 'Never',
48
+ 'Expires At': key.expiresAt ?? 'Never',
49
+ 'Created At': key.createdAt,
50
+ }));
51
+
52
+ tui.table(rows);
53
+ }
54
+ }
55
+
56
+ return apiKeys;
57
+ },
58
+ });
@@ -1,5 +1,6 @@
1
1
  import { createCommand } from '../../../types';
2
2
  import { listSubcommand } from './list';
3
+ import { logsSubcommand } from './logs';
3
4
  import { showSubcommand } from './show';
4
5
  import { removeSubcommand } from './remove';
5
6
  import { rollbackSubcommand } from './rollback';
@@ -12,6 +13,7 @@ export const deploymentCommand = createCommand({
12
13
  aliases: ['deployments', 'dep'],
13
14
  subcommands: [
14
15
  listSubcommand,
16
+ logsSubcommand,
15
17
  showSubcommand,
16
18
  removeSubcommand,
17
19
  rollbackSubcommand,
@@ -0,0 +1,75 @@
1
+ import { z } from 'zod';
2
+ import { createSubcommand } from '../../../types';
3
+ import * as tui from '../../../tui';
4
+ import { projectDeploymentLogs, DeploymentLogSchema } from '@agentuity/server';
5
+ import { resolveProjectId } from './utils';
6
+ import { getCommand } from '../../../command-prefix';
7
+ import { ErrorCode } from '../../../errors';
8
+
9
+ export const logsSubcommand = createSubcommand({
10
+ name: 'logs',
11
+ aliases: ['log'],
12
+ description: 'View logs for a specific deployment',
13
+ tags: ['read-only', 'fast', 'requires-auth', 'requires-deployment'],
14
+ examples: [
15
+ `${getCommand('cloud deployment logs')} deploy_abc123xyz`,
16
+ `${getCommand('cloud deployment logs')} deploy_abc123xyz --limit=50`,
17
+ `${getCommand('cloud deployment logs')} deploy_abc123xyz --no-timestamps # hide timestamps`,
18
+ `${getCommand('cloud deployment logs')} deploy_abc123xyz --project-id=proj_abc123xyz`,
19
+ ],
20
+ requires: { auth: true, apiClient: true },
21
+ optional: { project: true },
22
+ prerequisites: ['cloud deploy'],
23
+ schema: {
24
+ args: z.object({
25
+ deployment_id: z.string().describe('Deployment ID'),
26
+ }),
27
+ options: z.object({
28
+ projectId: z.string().optional().describe('Project ID'),
29
+ limit: z.coerce
30
+ .number()
31
+ .int()
32
+ .min(1)
33
+ .default(100)
34
+ .describe('Maximum number of logs to return'),
35
+ timestamps: z.boolean().default(true).describe('Show timestamps in output'),
36
+ }),
37
+ response: z.array(DeploymentLogSchema),
38
+ },
39
+ idempotent: true,
40
+ async handler(ctx) {
41
+ const { apiClient, args, options } = ctx;
42
+ const limit = ctx.opts.limit;
43
+ const showTimestamps = ctx.opts.timestamps;
44
+
45
+ try {
46
+ const projectId = resolveProjectId(ctx, { projectId: ctx.opts.projectId });
47
+ const logs = await projectDeploymentLogs(apiClient, projectId, args.deployment_id, limit);
48
+
49
+ if (!options.json) {
50
+ if (logs.length === 0) {
51
+ tui.info('No logs found for this deployment');
52
+ } else {
53
+ for (const log of logs) {
54
+ const severityColor = tui.getSeverityColor(log.severity);
55
+ if (showTimestamps) {
56
+ const timestamp = new Date(log.timestamp).toLocaleString();
57
+ console.log(
58
+ `${tui.muted(timestamp)} ${severityColor(log.severity.padEnd(5))} ${log.body}`
59
+ );
60
+ } else {
61
+ console.log(`${severityColor(log.severity.padEnd(5))} ${log.body}`);
62
+ }
63
+ }
64
+ }
65
+ }
66
+
67
+ return logs;
68
+ } catch (ex) {
69
+ tui.fatal(
70
+ `Failed to fetch deployment logs: ${ex instanceof Error ? ex.message : String(ex)}`,
71
+ ErrorCode.API_ERROR
72
+ );
73
+ }
74
+ },
75
+ });
@@ -6,19 +6,25 @@ import { sshSubcommand } from './ssh';
6
6
  import { scpSubcommand } from './scp';
7
7
  import { deploymentCommand } from './deployment';
8
8
  import keyvalueCommand from './keyvalue';
9
- import agentsCommand from './agents';
9
+ import { agentCommand } from './agent';
10
10
  import objectstoreCommand from './objectstore';
11
11
  import envCommand from './env';
12
12
  import secretCommand from './secret';
13
+ import apikeyCommand from './apikey';
14
+ import streamCommand from './stream';
15
+ import vectorCommand from './vector';
13
16
 
14
17
  export const command = createCommand({
15
18
  name: 'cloud',
16
19
  description: 'Cloud related commands',
17
20
  tags: ['slow', 'requires-auth'],
18
21
  subcommands: [
22
+ apikeyCommand,
19
23
  keyvalueCommand,
20
- agentsCommand,
24
+ agentCommand,
21
25
  objectstoreCommand,
26
+ streamCommand,
27
+ vectorCommand,
22
28
  envCommand,
23
29
  secretCommand,
24
30
  deploySubcommand,
@@ -15,9 +15,13 @@ const SessionLogsResponseSchema = z.array(
15
15
 
16
16
  export const logsSubcommand = createSubcommand({
17
17
  name: 'logs',
18
+ aliases: ['log'],
18
19
  description: 'Get logs for a specific session',
19
20
  tags: ['read-only', 'slow', 'requires-auth'],
20
- examples: [`${getCommand('cloud session logs')} sess_abc123xyz`],
21
+ examples: [
22
+ `${getCommand('cloud session logs')} sess_abc123xyz`,
23
+ `${getCommand('cloud session logs')} --no-timestamps # hide timestamps`,
24
+ ],
21
25
  requires: { auth: true, apiClient: true },
22
26
  optional: { project: true },
23
27
  idempotent: true,
@@ -28,11 +32,13 @@ export const logsSubcommand = createSubcommand({
28
32
  options: z.object({
29
33
  projectId: z.string().optional().describe('Project ID (for display purposes)'),
30
34
  deploymentId: z.string().optional().describe('Deployment ID (for display purposes)'),
35
+ timestamps: z.boolean().default(true).describe('Show timestamps in output'),
31
36
  }),
32
37
  response: SessionLogsResponseSchema,
33
38
  },
34
39
  async handler(ctx) {
35
40
  const { apiClient, args, options } = ctx;
41
+ const showTimestamps = ctx.opts.timestamps ?? true;
36
42
 
37
43
  try {
38
44
  const logs = await sessionLogs(apiClient, { id: args.session_id });
@@ -41,19 +47,14 @@ export const logsSubcommand = createSubcommand({
41
47
  if (logs.length === 0) {
42
48
  tui.info('No logs found for this session.');
43
49
  } else {
44
- tui.banner(`Logs for Session ${args.session_id}`, `${logs.length} log entries`);
45
-
46
50
  for (const log of logs) {
47
- const timestamp = new Date(log.timestamp).toLocaleTimeString();
51
+ const timestamp = showTimestamps
52
+ ? `${tui.muted(new Date(log.timestamp).toLocaleTimeString())} `
53
+ : '';
48
54
  const severity = log.severity.padEnd(5);
49
- const severityColor =
50
- log.severity === 'ERROR'
51
- ? tui.error(severity)
52
- : log.severity === 'WARN'
53
- ? tui.warning(severity)
54
- : tui.muted(severity);
55
+ const severityColor = tui.getSeverityColor(log.severity)(severity);
55
56
 
56
- console.log(`${tui.muted(timestamp)} ${severityColor} ${log.body}`);
57
+ console.log(`${timestamp}${severityColor} ${log.body}`);
57
58
  }
58
59
  }
59
60
  }
@@ -0,0 +1,49 @@
1
+ import { z } from 'zod';
2
+ import { createCommand } from '../../../types';
3
+ import * as tui from '../../../tui';
4
+ import { createStorageAdapter } from './util';
5
+ import { getCommand } from '../../../command-prefix';
6
+
7
+ const DeleteStreamResponseSchema = z.object({
8
+ id: z.string().describe('Stream ID'),
9
+ });
10
+
11
+ export const deleteSubcommand = createCommand({
12
+ name: 'delete',
13
+ aliases: ['del', 'rm'],
14
+ description: 'Delete a stream by ID (soft delete)',
15
+ tags: ['destructive', 'deletes-resource', 'slow', 'requires-auth'],
16
+ idempotent: true,
17
+ requires: { auth: true, project: true },
18
+ examples: [
19
+ `${getCommand('stream delete stream-id-123')} - Delete a stream`,
20
+ `${getCommand('stream rm stream-id-456')} - Delete stream (using alias)`,
21
+ `${getCommand('stream del stream-id-789')} - Delete stream (using alias)`,
22
+ ],
23
+ schema: {
24
+ args: z.object({
25
+ id: z.string().min(1).describe('the stream ID to delete'),
26
+ }),
27
+ response: DeleteStreamResponseSchema,
28
+ },
29
+
30
+ async handler(ctx) {
31
+ const { args, options } = ctx;
32
+ const started = Date.now();
33
+ const storage = await createStorageAdapter(ctx);
34
+
35
+ await storage.delete(args.id);
36
+
37
+ const durationMs = Date.now() - started;
38
+
39
+ if (!options.json) {
40
+ tui.success(`deleted stream ${args.id} in ${durationMs.toFixed(1)}ms`);
41
+ }
42
+
43
+ return {
44
+ id: args.id,
45
+ };
46
+ },
47
+ });
48
+
49
+ export default deleteSubcommand;
@@ -0,0 +1,118 @@
1
+ import { z } from 'zod';
2
+ import { createCommand } from '../../../types';
3
+ import * as tui from '../../../tui';
4
+ import { createStorageAdapter } from './util';
5
+ import { getCommand } from '../../../command-prefix';
6
+
7
+ function formatBytes(bytes: number): string {
8
+ if (bytes === 0) return '0 B';
9
+ if (bytes < 1024) return `${bytes} B`;
10
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} KB`;
11
+ if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
12
+ return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
13
+ }
14
+
15
+ const GetStreamResponseSchema = z.object({
16
+ id: z.string().describe('Stream ID'),
17
+ name: z.string().describe('Stream name'),
18
+ metadata: z.record(z.string(), z.string()).describe('Stream metadata'),
19
+ url: z.string().describe('Public URL'),
20
+ sizeBytes: z.number().describe('Size in bytes'),
21
+ });
22
+
23
+ export const getSubcommand = createCommand({
24
+ name: 'get',
25
+ description: 'Get detailed information about a specific stream',
26
+ tags: ['read-only', 'slow', 'requires-auth'],
27
+ requires: { auth: true, project: true },
28
+ idempotent: true,
29
+ examples: [
30
+ `${getCommand('stream get stream-id-123')} - Get stream details`,
31
+ `${getCommand('stream get stream-id-123 --json')} - Get stream as JSON`,
32
+ `${getCommand('stream get stream-id-123 --output stream.dat')} - Download stream to file`,
33
+ `${getCommand('stream get stream-id-123 -o stream.dat')} - Download stream (short flag)`,
34
+ ],
35
+ schema: {
36
+ args: z.object({
37
+ id: z.string().min(1).describe('the stream ID'),
38
+ }),
39
+ options: z.object({
40
+ output: z.string().optional().describe('download stream content to file'),
41
+ }),
42
+ response: GetStreamResponseSchema,
43
+ },
44
+
45
+ async handler(ctx) {
46
+ const { args, opts, options } = ctx;
47
+ const started = Date.now();
48
+ const storage = await createStorageAdapter(ctx);
49
+
50
+ // If --output is specified, download the stream content
51
+ if (opts.output) {
52
+ const readable = await storage.download(args.id);
53
+ const file = Bun.file(opts.output);
54
+ const writer = file.writer();
55
+
56
+ const reader = readable.getReader();
57
+ try {
58
+ while (true) {
59
+ const { done, value } = await reader.read();
60
+ if (done) break;
61
+ writer.write(value);
62
+ }
63
+ await writer.end();
64
+ const durationMs = Date.now() - started;
65
+ const stats = await Bun.file(opts.output).stat();
66
+ tui.success(
67
+ `downloaded ${formatBytes(stats.size)} to ${opts.output} in ${durationMs.toFixed(1)}ms`
68
+ );
69
+
70
+ // Fetch stream metadata to populate the response
71
+ const stream = await storage.get(args.id);
72
+ return {
73
+ id: args.id,
74
+ name: stream.name ?? '',
75
+ metadata: stream.metadata ?? {},
76
+ url: stream.url ?? '',
77
+ sizeBytes: stats.size,
78
+ };
79
+ } finally {
80
+ reader.releaseLock();
81
+ }
82
+ }
83
+
84
+ // Otherwise, get metadata
85
+ const stream = await storage.get(args.id);
86
+ const durationMs = Date.now() - started;
87
+
88
+ if (!options.json) {
89
+ if (!stream) {
90
+ tui.fatal(`Failed to retrieve stream metadata for ${args.id}`);
91
+ }
92
+
93
+ const sizeBytes = stream.sizeBytes ?? 0;
94
+
95
+ console.log(`Name: ${tui.bold(stream.name ?? 'unknown')}`);
96
+ console.log(`ID: ${stream.id}`);
97
+ console.log(`Size: ${formatBytes(sizeBytes)}`);
98
+ console.log(`URL: ${tui.link(stream.url ?? 'unknown')}`);
99
+ if (stream.metadata && Object.keys(stream.metadata).length > 0) {
100
+ console.log(`Metadata:`);
101
+ for (const [key, value] of Object.entries(stream.metadata)) {
102
+ console.log(` ${key}: ${value}`);
103
+ }
104
+ }
105
+ tui.success(`retrieved in ${durationMs.toFixed(1)}ms`);
106
+ }
107
+
108
+ return {
109
+ id: stream.id,
110
+ name: stream.name,
111
+ metadata: stream.metadata,
112
+ url: stream.url,
113
+ sizeBytes: stream.sizeBytes,
114
+ };
115
+ },
116
+ });
117
+
118
+ export default getSubcommand;
@@ -0,0 +1,14 @@
1
+ import { createCommand } from '../../../types';
2
+ import listSubcommand from './list';
3
+ import getSubcommand from './get';
4
+ import deleteSubcommand from './delete';
5
+
6
+ export const streamCommand = createCommand({
7
+ name: 'stream',
8
+ aliases: ['streams'],
9
+ description: 'Manage streams',
10
+ tags: ['slow', 'requires-auth'],
11
+ subcommands: [listSubcommand, getSubcommand, deleteSubcommand],
12
+ });
13
+
14
+ export default streamCommand;