@agentuity/cli 0.1.16 → 0.1.18
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.
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +3 -1
- package/dist/cli.js.map +1 -1
- package/dist/cmd/build/ast.d.ts.map +1 -1
- package/dist/cmd/build/ast.js +68 -2
- package/dist/cmd/build/ast.js.map +1 -1
- package/dist/cmd/build/vite/registry-generator.d.ts.map +1 -1
- package/dist/cmd/build/vite/registry-generator.js +112 -23
- package/dist/cmd/build/vite/registry-generator.js.map +1 -1
- package/dist/cmd/build/vite/route-discovery.d.ts +4 -0
- package/dist/cmd/build/vite/route-discovery.d.ts.map +1 -1
- package/dist/cmd/build/vite/route-discovery.js +4 -0
- package/dist/cmd/build/vite/route-discovery.js.map +1 -1
- package/dist/cmd/cloud/env/delete.d.ts.map +1 -1
- package/dist/cmd/cloud/env/delete.js +8 -2
- package/dist/cmd/cloud/env/delete.js.map +1 -1
- package/dist/cmd/cloud/env/get.d.ts.map +1 -1
- package/dist/cmd/cloud/env/get.js +4 -1
- package/dist/cmd/cloud/env/get.js.map +1 -1
- package/dist/cmd/cloud/env/import.d.ts.map +1 -1
- package/dist/cmd/cloud/env/import.js +5 -8
- package/dist/cmd/cloud/env/import.js.map +1 -1
- package/dist/cmd/cloud/env/list.d.ts.map +1 -1
- package/dist/cmd/cloud/env/list.js +11 -6
- package/dist/cmd/cloud/env/list.js.map +1 -1
- package/dist/cmd/cloud/env/pull.d.ts.map +1 -1
- package/dist/cmd/cloud/env/pull.js.map +1 -1
- package/dist/cmd/cloud/env/push.d.ts.map +1 -1
- package/dist/cmd/cloud/env/push.js +1 -7
- package/dist/cmd/cloud/env/push.js.map +1 -1
- package/dist/cmd/cloud/env/set.d.ts.map +1 -1
- package/dist/cmd/cloud/env/set.js +4 -1
- package/dist/cmd/cloud/env/set.js.map +1 -1
- package/dist/cmd/cloud/index.d.ts.map +1 -1
- package/dist/cmd/cloud/index.js +2 -0
- package/dist/cmd/cloud/index.js.map +1 -1
- package/dist/cmd/cloud/queue/ack.d.ts +3 -0
- package/dist/cmd/cloud/queue/ack.d.ts.map +1 -0
- package/dist/cmd/cloud/queue/ack.js +45 -0
- package/dist/cmd/cloud/queue/ack.js.map +1 -0
- package/dist/cmd/cloud/queue/create.d.ts +3 -0
- package/dist/cmd/cloud/queue/create.d.ts.map +1 -0
- package/dist/cmd/cloud/queue/create.js +80 -0
- package/dist/cmd/cloud/queue/create.js.map +1 -0
- package/dist/cmd/cloud/queue/delete.d.ts +3 -0
- package/dist/cmd/cloud/queue/delete.d.ts.map +1 -0
- package/dist/cmd/cloud/queue/delete.js +50 -0
- package/dist/cmd/cloud/queue/delete.js.map +1 -0
- package/dist/cmd/cloud/queue/destinations.d.ts +3 -0
- package/dist/cmd/cloud/queue/destinations.d.ts.map +1 -0
- package/dist/cmd/cloud/queue/destinations.js +232 -0
- package/dist/cmd/cloud/queue/destinations.js.map +1 -0
- package/dist/cmd/cloud/queue/dlq.d.ts +3 -0
- package/dist/cmd/cloud/queue/dlq.d.ts.map +1 -0
- package/dist/cmd/cloud/queue/dlq.js +168 -0
- package/dist/cmd/cloud/queue/dlq.js.map +1 -0
- package/dist/cmd/cloud/queue/get.d.ts +3 -0
- package/dist/cmd/cloud/queue/get.d.ts.map +1 -0
- package/dist/cmd/cloud/queue/get.js +130 -0
- package/dist/cmd/cloud/queue/get.js.map +1 -0
- package/dist/cmd/cloud/queue/index.d.ts +3 -0
- package/dist/cmd/cloud/queue/index.d.ts.map +1 -0
- package/dist/cmd/cloud/queue/index.js +65 -0
- package/dist/cmd/cloud/queue/index.js.map +1 -0
- package/dist/cmd/cloud/queue/list.d.ts +3 -0
- package/dist/cmd/cloud/queue/list.d.ts.map +1 -0
- package/dist/cmd/cloud/queue/list.js +71 -0
- package/dist/cmd/cloud/queue/list.js.map +1 -0
- package/dist/cmd/cloud/queue/messages.d.ts +3 -0
- package/dist/cmd/cloud/queue/messages.d.ts.map +1 -0
- package/dist/cmd/cloud/queue/messages.js +137 -0
- package/dist/cmd/cloud/queue/messages.js.map +1 -0
- package/dist/cmd/cloud/queue/nack.d.ts +3 -0
- package/dist/cmd/cloud/queue/nack.d.ts.map +1 -0
- package/dist/cmd/cloud/queue/nack.js +45 -0
- package/dist/cmd/cloud/queue/nack.js.map +1 -0
- package/dist/cmd/cloud/queue/pause.d.ts +3 -0
- package/dist/cmd/cloud/queue/pause.d.ts.map +1 -0
- package/dist/cmd/cloud/queue/pause.js +36 -0
- package/dist/cmd/cloud/queue/pause.js.map +1 -0
- package/dist/cmd/cloud/queue/publish.d.ts +3 -0
- package/dist/cmd/cloud/queue/publish.d.ts.map +1 -0
- package/dist/cmd/cloud/queue/publish.js +76 -0
- package/dist/cmd/cloud/queue/publish.js.map +1 -0
- package/dist/cmd/cloud/queue/receive.d.ts +3 -0
- package/dist/cmd/cloud/queue/receive.d.ts.map +1 -0
- package/dist/cmd/cloud/queue/receive.js +67 -0
- package/dist/cmd/cloud/queue/receive.js.map +1 -0
- package/dist/cmd/cloud/queue/resume.d.ts +3 -0
- package/dist/cmd/cloud/queue/resume.d.ts.map +1 -0
- package/dist/cmd/cloud/queue/resume.js +35 -0
- package/dist/cmd/cloud/queue/resume.js.map +1 -0
- package/dist/cmd/cloud/queue/sources.d.ts +3 -0
- package/dist/cmd/cloud/queue/sources.d.ts.map +1 -0
- package/dist/cmd/cloud/queue/sources.js +290 -0
- package/dist/cmd/cloud/queue/sources.js.map +1 -0
- package/dist/cmd/cloud/queue/stats.d.ts +3 -0
- package/dist/cmd/cloud/queue/stats.d.ts.map +1 -0
- package/dist/cmd/cloud/queue/stats.js +239 -0
- package/dist/cmd/cloud/queue/stats.js.map +1 -0
- package/dist/cmd/cloud/queue/util.d.ts +26 -0
- package/dist/cmd/cloud/queue/util.d.ts.map +1 -0
- package/dist/cmd/cloud/queue/util.js +19 -0
- package/dist/cmd/cloud/queue/util.js.map +1 -0
- package/dist/cmd/cloud/sandbox/snapshot/build.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/build.js +152 -30
- package/dist/cmd/cloud/sandbox/snapshot/build.js.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/create.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/create.js +19 -7
- package/dist/cmd/cloud/sandbox/snapshot/create.js.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/get.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/get.js +20 -0
- package/dist/cmd/cloud/sandbox/snapshot/get.js.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/list.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/list.js +4 -0
- package/dist/cmd/cloud/sandbox/snapshot/list.js.map +1 -1
- package/dist/cmd/cloud/vector/stats.d.ts.map +1 -1
- package/dist/cmd/cloud/vector/stats.js +8 -0
- package/dist/cmd/cloud/vector/stats.js.map +1 -1
- package/dist/cmd/project/template-flow.d.ts.map +1 -1
- package/dist/cmd/project/template-flow.js.map +1 -1
- package/dist/env-util.d.ts +6 -1
- package/dist/env-util.d.ts.map +1 -1
- package/dist/env-util.js +16 -2
- package/dist/env-util.js.map +1 -1
- package/dist/errors.d.ts +4 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +6 -0
- package/dist/errors.js.map +1 -1
- package/dist/schema-parser.d.ts.map +1 -1
- package/dist/schema-parser.js +2 -2
- package/dist/schema-parser.js.map +1 -1
- package/dist/tui/box.d.ts +8 -0
- package/dist/tui/box.d.ts.map +1 -1
- package/dist/tui/box.js +78 -0
- package/dist/tui/box.js.map +1 -1
- package/dist/tui.d.ts +11 -1
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +16 -8
- package/dist/tui.js.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +6 -6
- package/src/cli.ts +5 -1
- package/src/cmd/build/ast.ts +88 -2
- package/src/cmd/build/vite/registry-generator.ts +120 -24
- package/src/cmd/build/vite/route-discovery.ts +16 -0
- package/src/cmd/cloud/env/delete.ts +18 -5
- package/src/cmd/cloud/env/get.ts +10 -3
- package/src/cmd/cloud/env/import.ts +10 -11
- package/src/cmd/cloud/env/list.ts +19 -9
- package/src/cmd/cloud/env/org-util.ts +1 -1
- package/src/cmd/cloud/env/pull.ts +9 -4
- package/src/cmd/cloud/env/push.ts +5 -9
- package/src/cmd/cloud/env/set.ts +10 -3
- package/src/cmd/cloud/index.ts +2 -0
- package/src/cmd/cloud/queue/ack.ts +50 -0
- package/src/cmd/cloud/queue/create.ts +91 -0
- package/src/cmd/cloud/queue/delete.ts +57 -0
- package/src/cmd/cloud/queue/destinations.ts +287 -0
- package/src/cmd/cloud/queue/dlq.ts +203 -0
- package/src/cmd/cloud/queue/get.ts +158 -0
- package/src/cmd/cloud/queue/index.ts +66 -0
- package/src/cmd/cloud/queue/list.ts +81 -0
- package/src/cmd/cloud/queue/messages.ts +160 -0
- package/src/cmd/cloud/queue/nack.ts +50 -0
- package/src/cmd/cloud/queue/pause.ts +41 -0
- package/src/cmd/cloud/queue/publish.ts +88 -0
- package/src/cmd/cloud/queue/receive.ts +76 -0
- package/src/cmd/cloud/queue/resume.ts +40 -0
- package/src/cmd/cloud/queue/sources.ts +352 -0
- package/src/cmd/cloud/queue/stats.ts +297 -0
- package/src/cmd/cloud/queue/util.ts +34 -0
- package/src/cmd/cloud/sandbox/snapshot/build.ts +186 -31
- package/src/cmd/cloud/sandbox/snapshot/create.ts +24 -7
- package/src/cmd/cloud/sandbox/snapshot/get.ts +20 -0
- package/src/cmd/cloud/sandbox/snapshot/list.ts +4 -0
- package/src/cmd/cloud/vector/stats.ts +9 -0
- package/src/cmd/project/template-flow.ts +1 -3
- package/src/env-util.ts +17 -2
- package/src/errors.ts +8 -0
- package/src/schema-parser.ts +6 -3
- package/src/tui/box.ts +104 -0
- package/src/tui.ts +28 -8
- package/src/types.ts +0 -1
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createCommand } from '../../../types';
|
|
3
|
+
import * as tui from '../../../tui';
|
|
4
|
+
import { createQueueAPIClient, getQueueApiOptions } from './util';
|
|
5
|
+
import { getCommand } from '../../../command-prefix';
|
|
6
|
+
import { getOrgAnalytics, getQueueAnalytics, streamOrgAnalytics, streamQueueAnalytics, } from '@agentuity/server';
|
|
7
|
+
const StatsResponseSchema = z.union([
|
|
8
|
+
z.object({ type: z.literal('org'), analytics: z.unknown() }),
|
|
9
|
+
z.object({ type: z.literal('queue'), analytics: z.unknown() }),
|
|
10
|
+
z.object({ type: z.literal('stream'), events: z.array(z.unknown()) }),
|
|
11
|
+
]);
|
|
12
|
+
function formatNumber(n) {
|
|
13
|
+
if (n >= 1_000_000)
|
|
14
|
+
return `${(n / 1_000_000).toFixed(1)}M`;
|
|
15
|
+
if (n >= 1_000)
|
|
16
|
+
return `${(n / 1_000).toFixed(1)}K`;
|
|
17
|
+
return String(n);
|
|
18
|
+
}
|
|
19
|
+
function formatPercent(n) {
|
|
20
|
+
return `${n.toFixed(2)}%`;
|
|
21
|
+
}
|
|
22
|
+
function formatLatency(ms) {
|
|
23
|
+
if (ms >= 1000)
|
|
24
|
+
return `${(ms / 1000).toFixed(1)}s`;
|
|
25
|
+
return `${Math.round(ms)}ms`;
|
|
26
|
+
}
|
|
27
|
+
function formatDuration(start, end) {
|
|
28
|
+
const startDate = new Date(start);
|
|
29
|
+
const endDate = new Date(end);
|
|
30
|
+
const hours = Math.round((endDate.getTime() - startDate.getTime()) / 3600000);
|
|
31
|
+
if (hours >= 24)
|
|
32
|
+
return `${Math.round(hours / 24)}d`;
|
|
33
|
+
return `${hours}h`;
|
|
34
|
+
}
|
|
35
|
+
function displayOrgAnalytics(analytics) {
|
|
36
|
+
const { summary, queues, period } = analytics;
|
|
37
|
+
tui.info(`Organization Analytics (${formatDuration(period.start, period.end)})`);
|
|
38
|
+
tui.newline();
|
|
39
|
+
console.log(tui.colorPrimary('Summary:'));
|
|
40
|
+
console.log(` ${tui.muted('Total Queues:')} ${summary.total_queues}`);
|
|
41
|
+
console.log(` ${tui.muted('Published:')} ${formatNumber(summary.total_messages_published)}`);
|
|
42
|
+
console.log(` ${tui.muted('Delivered:')} ${formatNumber(summary.total_messages_delivered)}`);
|
|
43
|
+
console.log(` ${tui.muted('Acknowledged:')} ${formatNumber(summary.total_messages_acknowledged)}`);
|
|
44
|
+
console.log(` ${tui.muted('DLQ Messages:')} ${formatNumber(summary.total_dlq_messages)}`);
|
|
45
|
+
console.log(` ${tui.muted('Avg Latency:')} ${formatLatency(summary.avg_latency_ms)}`);
|
|
46
|
+
console.log(` ${tui.muted('P95 Latency:')} ${formatLatency(summary.p95_latency_ms)}`);
|
|
47
|
+
console.log(` ${tui.muted('Error Rate:')} ${formatPercent(summary.error_rate_percent)}`);
|
|
48
|
+
if (queues.length > 0) {
|
|
49
|
+
tui.newline();
|
|
50
|
+
console.log(tui.colorPrimary('Queues:'));
|
|
51
|
+
const tableData = queues.map((q) => ({
|
|
52
|
+
Name: q.name,
|
|
53
|
+
Type: q.queue_type,
|
|
54
|
+
Published: formatNumber(q.messages_published),
|
|
55
|
+
Delivered: formatNumber(q.messages_delivered),
|
|
56
|
+
Backlog: formatNumber(q.backlog),
|
|
57
|
+
DLQ: formatNumber(q.dlq_count),
|
|
58
|
+
'Avg Latency': formatLatency(q.avg_latency_ms),
|
|
59
|
+
'Error %': formatPercent(q.error_rate_percent),
|
|
60
|
+
}));
|
|
61
|
+
tui.table(tableData);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function displayQueueAnalytics(analytics) {
|
|
65
|
+
const { queue_name, queue_type, period, current, period_stats, latency, consumer_latency } = analytics;
|
|
66
|
+
tui.info(`Queue: ${queue_name} (${queue_type})`);
|
|
67
|
+
console.log(tui.colorWarning(`Period: ${formatDuration(period.start, period.end)}`));
|
|
68
|
+
tui.newline();
|
|
69
|
+
console.log(tui.colorPrimary('Current State:'));
|
|
70
|
+
console.log(` ${tui.muted('Backlog:')} ${formatNumber(current.backlog)}`);
|
|
71
|
+
console.log(` ${tui.muted('In-Flight:')} ${formatNumber(current.messages_in_flight)}`);
|
|
72
|
+
console.log(` ${tui.muted('DLQ:')} ${formatNumber(current.dlq_count)}`);
|
|
73
|
+
console.log(` ${tui.muted('Consumers:')} ${current.active_consumers}`);
|
|
74
|
+
if (current.oldest_message_age_seconds != null) {
|
|
75
|
+
console.log(` ${tui.muted('Oldest Msg Age:')} ${current.oldest_message_age_seconds}s`);
|
|
76
|
+
}
|
|
77
|
+
tui.newline();
|
|
78
|
+
console.log(tui.colorPrimary('Period Stats:'));
|
|
79
|
+
console.log(` ${tui.muted('Published:')} ${formatNumber(period_stats.messages_published)}`);
|
|
80
|
+
console.log(` ${tui.muted('Delivered:')} ${formatNumber(period_stats.messages_delivered)}`);
|
|
81
|
+
console.log(` ${tui.muted('Acknowledged:')} ${formatNumber(period_stats.messages_acknowledged)}`);
|
|
82
|
+
console.log(` ${tui.muted('Failed:')} ${formatNumber(period_stats.messages_failed)}`);
|
|
83
|
+
console.log(` ${tui.muted('Replayed:')} ${formatNumber(period_stats.messages_replayed)}`);
|
|
84
|
+
console.log(` ${tui.muted('Bytes Published:')} ${tui.formatBytes(period_stats.bytes_published)}`);
|
|
85
|
+
console.log(` ${tui.muted('Delivery Attempts:')} ${formatNumber(period_stats.delivery_attempts)}`);
|
|
86
|
+
console.log(` ${tui.muted('Retries:')} ${formatNumber(period_stats.retry_count)}`);
|
|
87
|
+
tui.newline();
|
|
88
|
+
console.log(tui.colorPrimary('Delivery Latency:'));
|
|
89
|
+
console.log(` ${tui.muted('Average:')} ${formatLatency(latency.avg_ms)}`);
|
|
90
|
+
if (latency.p50_ms != null)
|
|
91
|
+
console.log(` ${tui.muted('Median (P50):')} ${formatLatency(latency.p50_ms)}`);
|
|
92
|
+
if (latency.p95_ms != null)
|
|
93
|
+
console.log(` ${tui.muted('P95:')} ${formatLatency(latency.p95_ms)}`);
|
|
94
|
+
if (latency.p99_ms != null)
|
|
95
|
+
console.log(` ${tui.muted('P99:')} ${formatLatency(latency.p99_ms)}`);
|
|
96
|
+
if (latency.max_ms != null)
|
|
97
|
+
console.log(` ${tui.muted('Max:')} ${formatLatency(latency.max_ms)}`);
|
|
98
|
+
tui.newline();
|
|
99
|
+
console.log(tui.colorPrimary('Consumer Latency:'));
|
|
100
|
+
console.log(` ${tui.muted('Average:')} ${formatLatency(consumer_latency.avg_ms)}`);
|
|
101
|
+
if (consumer_latency.p50_ms != null)
|
|
102
|
+
console.log(` ${tui.muted('Median (P50):')} ${formatLatency(consumer_latency.p50_ms)}`);
|
|
103
|
+
if (consumer_latency.p95_ms != null)
|
|
104
|
+
console.log(` ${tui.muted('P95:')} ${formatLatency(consumer_latency.p95_ms)}`);
|
|
105
|
+
if (consumer_latency.p99_ms != null)
|
|
106
|
+
console.log(` ${tui.muted('P99:')} ${formatLatency(consumer_latency.p99_ms)}`);
|
|
107
|
+
if (analytics.destinations && analytics.destinations.length > 0) {
|
|
108
|
+
tui.newline();
|
|
109
|
+
tui.info('Destinations:');
|
|
110
|
+
const destData = analytics.destinations.map((d) => {
|
|
111
|
+
const total = d.success_count + d.failure_count;
|
|
112
|
+
const errorRate = total > 0 ? (d.failure_count / total) * 100 : 0;
|
|
113
|
+
return {
|
|
114
|
+
ID: d.id.slice(0, 12) + '...',
|
|
115
|
+
URL: d.url.length > 40 ? d.url.slice(0, 37) + '...' : d.url,
|
|
116
|
+
Success: formatNumber(d.success_count),
|
|
117
|
+
Failed: formatNumber(d.failure_count),
|
|
118
|
+
'Avg Response': d.avg_response_time_ms ? formatLatency(d.avg_response_time_ms) : '-',
|
|
119
|
+
'Error %': formatPercent(errorRate),
|
|
120
|
+
};
|
|
121
|
+
});
|
|
122
|
+
tui.table(destData);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function displayStreamEvent(event, queueName) {
|
|
126
|
+
const time = new Date(event.timestamp).toLocaleTimeString();
|
|
127
|
+
const prefix = queueName ? `[${queueName}]` : '[org]';
|
|
128
|
+
process.stdout.write('\x1b[2K\r');
|
|
129
|
+
process.stdout.write(`${tui.colorMuted(time)} ${prefix} ` +
|
|
130
|
+
`Backlog: ${tui.colorInfo(formatNumber(event.backlog))} | ` +
|
|
131
|
+
`In-Flight: ${tui.colorInfo(formatNumber(event.messages_in_flight))} | ` +
|
|
132
|
+
`Throughput: ${tui.colorSuccess(formatNumber(event.throughput_1m))}/min | ` +
|
|
133
|
+
`Latency: ${formatLatency(event.avg_latency_ms)} | ` +
|
|
134
|
+
`Errors: ${event.error_rate_1m > 0 ? tui.colorError(String(event.error_rate_1m)) : '0'}/min`);
|
|
135
|
+
}
|
|
136
|
+
export const statsSubcommand = createCommand({
|
|
137
|
+
name: 'stats',
|
|
138
|
+
description: 'View queue analytics and statistics',
|
|
139
|
+
tags: ['read-only', 'requires-auth'],
|
|
140
|
+
requires: { auth: true, org: true },
|
|
141
|
+
examples: [
|
|
142
|
+
{
|
|
143
|
+
command: getCommand('cloud queue stats'),
|
|
144
|
+
description: 'View org-level analytics for all queues',
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
command: getCommand('cloud queue stats --name my-queue'),
|
|
148
|
+
description: 'View detailed analytics for a specific queue',
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
command: getCommand('cloud queue stats --live'),
|
|
152
|
+
description: 'Stream real-time stats (Ctrl+C to exit)',
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
command: getCommand('cloud queue stats --name my-queue --live --interval 10'),
|
|
156
|
+
description: 'Stream queue stats every 10 seconds',
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
schema: {
|
|
160
|
+
args: z.object({
|
|
161
|
+
name: z.string().optional().describe('Queue name (omit for org-level stats)'),
|
|
162
|
+
}),
|
|
163
|
+
options: z.object({
|
|
164
|
+
live: z.boolean().default(false).describe('Stream real-time stats'),
|
|
165
|
+
interval: z.number().default(5).describe('Refresh interval in seconds (for --live)'),
|
|
166
|
+
start: z.string().optional().describe('Start time (ISO 8601)'),
|
|
167
|
+
end: z.string().optional().describe('End time (ISO 8601)'),
|
|
168
|
+
granularity: z.enum(['minute', 'hour', 'day']).optional().describe('Time granularity'),
|
|
169
|
+
}),
|
|
170
|
+
response: StatsResponseSchema,
|
|
171
|
+
},
|
|
172
|
+
idempotent: true,
|
|
173
|
+
async handler(ctx) {
|
|
174
|
+
const { args, opts, options } = ctx;
|
|
175
|
+
const client = await createQueueAPIClient(ctx);
|
|
176
|
+
const apiOptions = getQueueApiOptions(ctx);
|
|
177
|
+
const analyticsOptions = {
|
|
178
|
+
...apiOptions,
|
|
179
|
+
start: opts.start,
|
|
180
|
+
end: opts.end,
|
|
181
|
+
granularity: opts.granularity,
|
|
182
|
+
};
|
|
183
|
+
if (opts.live) {
|
|
184
|
+
const events = [];
|
|
185
|
+
tui.info(`Streaming stats every ${opts.interval}s... ${tui.colorMuted('(Ctrl+C to exit)')}`);
|
|
186
|
+
tui.info('');
|
|
187
|
+
const handleInterrupt = () => {
|
|
188
|
+
tui.info('');
|
|
189
|
+
tui.info('Stream stopped.');
|
|
190
|
+
process.exit(0);
|
|
191
|
+
};
|
|
192
|
+
process.on('SIGINT', handleInterrupt);
|
|
193
|
+
try {
|
|
194
|
+
if (args.name) {
|
|
195
|
+
const stream = streamQueueAnalytics(client, args.name, {
|
|
196
|
+
interval: opts.interval,
|
|
197
|
+
orgId: apiOptions?.orgId,
|
|
198
|
+
});
|
|
199
|
+
for await (const event of stream) {
|
|
200
|
+
events.push(event);
|
|
201
|
+
if (!options.json) {
|
|
202
|
+
displayStreamEvent(event, args.name);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
const stream = streamOrgAnalytics(client, {
|
|
208
|
+
interval: opts.interval,
|
|
209
|
+
orgId: apiOptions?.orgId,
|
|
210
|
+
});
|
|
211
|
+
for await (const event of stream) {
|
|
212
|
+
events.push(event);
|
|
213
|
+
if (!options.json) {
|
|
214
|
+
displayStreamEvent(event);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
finally {
|
|
220
|
+
process.off('SIGINT', handleInterrupt);
|
|
221
|
+
}
|
|
222
|
+
return { type: 'stream', events };
|
|
223
|
+
}
|
|
224
|
+
if (args.name) {
|
|
225
|
+
const analytics = await getQueueAnalytics(client, args.name, analyticsOptions);
|
|
226
|
+
if (!options.json) {
|
|
227
|
+
displayQueueAnalytics(analytics);
|
|
228
|
+
}
|
|
229
|
+
return { type: 'queue', analytics };
|
|
230
|
+
}
|
|
231
|
+
const analytics = await getOrgAnalytics(client, analyticsOptions);
|
|
232
|
+
if (!options.json) {
|
|
233
|
+
displayOrgAnalytics(analytics);
|
|
234
|
+
}
|
|
235
|
+
return { type: 'org', analytics };
|
|
236
|
+
},
|
|
237
|
+
});
|
|
238
|
+
export default statsSubcommand;
|
|
239
|
+
//# sourceMappingURL=stats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../../../src/cmd/cloud/queue/stats.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Logger } from '@agentuity/core';
|
|
2
|
+
import { APIClient, type QueueApiOptions } from '@agentuity/server';
|
|
3
|
+
import type { AuthData, Config, GlobalOptions } from '../../../types';
|
|
4
|
+
/**
|
|
5
|
+
* Context required for queue API operations.
|
|
6
|
+
*/
|
|
7
|
+
export interface QueueContext {
|
|
8
|
+
logger: Logger;
|
|
9
|
+
auth: AuthData;
|
|
10
|
+
config: Config | null;
|
|
11
|
+
options: GlobalOptions;
|
|
12
|
+
orgId?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Creates an API client for queue operations.
|
|
16
|
+
*
|
|
17
|
+
* Queues are global resources that don't require a project context.
|
|
18
|
+
* Uses the global Catalyst API client with user authentication.
|
|
19
|
+
*/
|
|
20
|
+
export declare function createQueueAPIClient(ctx: QueueContext): Promise<APIClient>;
|
|
21
|
+
/**
|
|
22
|
+
* Creates QueueApiOptions from the CLI context.
|
|
23
|
+
* Prioritizes explicit orgId on context, then falls back to global --org-id option.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getQueueApiOptions(ctx: QueueContext): QueueApiOptions | undefined;
|
|
26
|
+
//# sourceMappingURL=util.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../../src/cmd/cloud/queue/util.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEtE;;GAEG;AACH,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,aAAa,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAEhF;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,YAAY,GAAG,eAAe,GAAG,SAAS,CAGjF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { getGlobalCatalystAPIClient } from '../../../config';
|
|
2
|
+
/**
|
|
3
|
+
* Creates an API client for queue operations.
|
|
4
|
+
*
|
|
5
|
+
* Queues are global resources that don't require a project context.
|
|
6
|
+
* Uses the global Catalyst API client with user authentication.
|
|
7
|
+
*/
|
|
8
|
+
export async function createQueueAPIClient(ctx) {
|
|
9
|
+
return getGlobalCatalystAPIClient(ctx.logger, ctx.auth, ctx.config?.name);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Creates QueueApiOptions from the CLI context.
|
|
13
|
+
* Prioritizes explicit orgId on context, then falls back to global --org-id option.
|
|
14
|
+
*/
|
|
15
|
+
export function getQueueApiOptions(ctx) {
|
|
16
|
+
const orgId = ctx.orgId ?? ctx.options.orgId;
|
|
17
|
+
return orgId ? { orgId } : undefined;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../../../src/cmd/cloud/queue/util.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAc7D;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,GAAiB;IAC3D,OAAO,0BAA0B,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAC3E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAiB;IACnD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC;IAC7C,OAAO,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AACtC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../../../src/cmd/cloud/sandbox/snapshot/build.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../../../src/cmd/cloud/sandbox/snapshot/build.ts"],"names":[],"mappings":"AAuBA,eAAO,MAAM,kBAAkB,QAAiC,CAAC;AACjE,eAAO,MAAM,uBAAuB,MAAM,CAAC;AA4R3C,eAAO,MAAM,eAAe,yCA4lB1B,CAAC;AAEH,eAAe,eAAe,CAAC"}
|
|
@@ -5,8 +5,9 @@ import { YAML } from 'bun';
|
|
|
5
5
|
import * as tar from 'tar';
|
|
6
6
|
import { createCommand } from '../../../../types';
|
|
7
7
|
import * as tui from '../../../../tui';
|
|
8
|
+
import { ErrorCode } from '../../../../errors';
|
|
8
9
|
import { getCommand } from '../../../../command-prefix';
|
|
9
|
-
import { snapshotBuildInit, snapshotBuildFinalize, SnapshotBuildFileSchema, } from '@agentuity/server';
|
|
10
|
+
import { snapshotBuildInit, snapshotBuildFinalize, snapshotUpload, SnapshotBuildFileSchema, } from '@agentuity/server';
|
|
10
11
|
import { getCatalystAPIClient } from '../../../../config';
|
|
11
12
|
import { validateAptDependencies } from '../../../../utils/apt-validator';
|
|
12
13
|
import { encryptFIPSKEMDEMStream } from '../../../../crypto/box';
|
|
@@ -28,7 +29,11 @@ const SnapshotBuildResponseSchema = z.object({
|
|
|
28
29
|
.record(z.string(), z.string())
|
|
29
30
|
.optional()
|
|
30
31
|
.describe('User-defined metadata key-value pairs'),
|
|
32
|
+
error: z.string().optional().describe('Error message if build failed'),
|
|
33
|
+
malwareDetected: z.boolean().optional().describe('True if malware was detected'),
|
|
34
|
+
virusName: z.string().optional().describe('Name of detected virus'),
|
|
31
35
|
});
|
|
36
|
+
const MALWARE_REGEX = /malware detected \(([^)]+)\)/i;
|
|
32
37
|
function buildFileTree(files) {
|
|
33
38
|
const root = { name: '', isFile: false, children: new Map() };
|
|
34
39
|
for (const file of files) {
|
|
@@ -172,6 +177,27 @@ async function createTarGzArchive(directory, files, outputPath) {
|
|
|
172
177
|
cwd: directory,
|
|
173
178
|
}, filePaths);
|
|
174
179
|
}
|
|
180
|
+
function createProgressStream(file, totalSize, onProgress) {
|
|
181
|
+
let bytesRead = 0;
|
|
182
|
+
const reader = file.stream().getReader();
|
|
183
|
+
return new ReadableStream({
|
|
184
|
+
async pull(controller) {
|
|
185
|
+
const { done, value } = await reader.read();
|
|
186
|
+
if (done) {
|
|
187
|
+
controller.close();
|
|
188
|
+
onProgress(100);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
bytesRead += value.byteLength;
|
|
192
|
+
const percent = Math.min(99, Math.floor((bytesRead / totalSize) * 100));
|
|
193
|
+
onProgress(percent);
|
|
194
|
+
controller.enqueue(value);
|
|
195
|
+
},
|
|
196
|
+
cancel() {
|
|
197
|
+
reader.cancel();
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
}
|
|
175
201
|
async function generateContentHash(params) {
|
|
176
202
|
const hash = createHash('sha256');
|
|
177
203
|
hash.update(`runtime:${params.runtime}\n`);
|
|
@@ -186,7 +212,8 @@ async function generateContentHash(params) {
|
|
|
186
212
|
const sortedFiles = [...params.files].sort((a, b) => a.path.localeCompare(b.path));
|
|
187
213
|
for (const file of sortedFiles) {
|
|
188
214
|
const contentHash = params.fileHashes.get(file.path) ?? '';
|
|
189
|
-
|
|
215
|
+
const mode = file.mode.toString(8).padStart(4, '0');
|
|
216
|
+
hash.update(`file:${file.path}:${file.size}:${contentHash}:${mode}:${file.contentType}\n`);
|
|
190
217
|
}
|
|
191
218
|
}
|
|
192
219
|
if (params.env && Object.keys(params.env).length > 0) {
|
|
@@ -195,6 +222,7 @@ async function generateContentHash(params) {
|
|
|
195
222
|
hash.update(`env:${key}=${params.env[key]}\n`);
|
|
196
223
|
}
|
|
197
224
|
}
|
|
225
|
+
hash.update(`access:${params.isPublic ? 'public' : 'private'}\n`);
|
|
198
226
|
return hash.digest('hex');
|
|
199
227
|
}
|
|
200
228
|
export const buildSubcommand = createCommand({
|
|
@@ -242,12 +270,42 @@ export const buildSubcommand = createCommand({
|
|
|
242
270
|
description: z.string().optional().describe('Snapshot description (overrides build file)'),
|
|
243
271
|
metadata: z.array(z.string()).optional().describe('Metadata key-value pairs (KEY=VALUE)'),
|
|
244
272
|
force: z.boolean().optional().describe('Force rebuild even if content is unchanged'),
|
|
273
|
+
public: z
|
|
274
|
+
.boolean()
|
|
275
|
+
.optional()
|
|
276
|
+
.describe('Make snapshot public (enables virus scanning, no encryption)'),
|
|
277
|
+
confirm: z
|
|
278
|
+
.boolean()
|
|
279
|
+
.optional()
|
|
280
|
+
.describe('Confirm public snapshot publishing (required for --public)'),
|
|
245
281
|
}),
|
|
246
282
|
response: SnapshotBuildResponseSchema,
|
|
247
283
|
},
|
|
248
284
|
async handler(ctx) {
|
|
249
285
|
const { args, opts, options, auth, region, config, logger, orgId } = ctx;
|
|
250
286
|
const dryRun = options.dryRun === true;
|
|
287
|
+
const isPublic = opts.public === true;
|
|
288
|
+
if (isPublic && !dryRun) {
|
|
289
|
+
if (!opts.confirm) {
|
|
290
|
+
if (!tui.isTTYLike()) {
|
|
291
|
+
logger.fatal(`Publishing a public snapshot requires confirmation.\n\n` +
|
|
292
|
+
`Public snapshots make all environment variables and files publicly accessible.\n\n` +
|
|
293
|
+
`To proceed, add the --confirm flag:\n` +
|
|
294
|
+
` ${getCommand('cloud sandbox snapshot build . --public --confirm')}\n\n` +
|
|
295
|
+
`To preview what will be published, use --dry-run first:\n` +
|
|
296
|
+
` ${getCommand('cloud sandbox snapshot build . --public --dry-run')}`);
|
|
297
|
+
}
|
|
298
|
+
tui.warningBox('Public Snapshot', `You are publishing a public snapshot.\n\n` +
|
|
299
|
+
`This will make all environment variables and\n` +
|
|
300
|
+
`files in the snapshot publicly accessible.\n\n` +
|
|
301
|
+
`Run with --dry-run to preview the contents.`);
|
|
302
|
+
console.log('');
|
|
303
|
+
const confirmed = await tui.confirm('Proceed with public snapshot?', false);
|
|
304
|
+
if (!confirmed) {
|
|
305
|
+
logger.fatal('Aborted');
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
251
309
|
const directory = resolve(args.directory);
|
|
252
310
|
if (!existsSync(directory)) {
|
|
253
311
|
logger.fatal(`Directory not found: ${directory}`);
|
|
@@ -362,19 +420,32 @@ export const buildSubcommand = createCommand({
|
|
|
362
420
|
if (buildConfig.files && buildConfig.files.length > 0) {
|
|
363
421
|
files = await resolveFileGlobs(directory, buildConfig.files);
|
|
364
422
|
}
|
|
365
|
-
const
|
|
366
|
-
path: f.path,
|
|
367
|
-
size: f.size,
|
|
368
|
-
}));
|
|
369
|
-
const totalSize = fileList.reduce((sum, f) => sum + f.size, 0);
|
|
370
|
-
const fileHashes = new Map();
|
|
423
|
+
const fileMetadata = new Map();
|
|
371
424
|
for (const file of files.values()) {
|
|
372
425
|
const fullPath = join(directory, file.path);
|
|
373
426
|
const bunFile = Bun.file(fullPath);
|
|
374
427
|
const content = await bunFile.arrayBuffer();
|
|
375
428
|
const hash = createHash('sha256').update(Buffer.from(content)).digest('hex');
|
|
376
|
-
|
|
429
|
+
const contentType = bunFile.type || 'application/octet-stream';
|
|
430
|
+
const stat = statSync(fullPath);
|
|
431
|
+
const mode = stat.mode & 0o7777; // Extract permission bits only
|
|
432
|
+
fileMetadata.set(file.path, { sha256: hash, contentType, mode });
|
|
433
|
+
}
|
|
434
|
+
const fileHashes = new Map();
|
|
435
|
+
for (const [path, meta] of fileMetadata) {
|
|
436
|
+
fileHashes.set(path, meta.sha256);
|
|
377
437
|
}
|
|
438
|
+
const fileList = Array.from(files.values()).map((f) => {
|
|
439
|
+
const meta = fileMetadata.get(f.path);
|
|
440
|
+
return {
|
|
441
|
+
path: f.path,
|
|
442
|
+
size: f.size,
|
|
443
|
+
sha256: meta?.sha256 ?? '',
|
|
444
|
+
contentType: meta?.contentType ?? 'application/octet-stream',
|
|
445
|
+
mode: meta?.mode ?? 0o644,
|
|
446
|
+
};
|
|
447
|
+
});
|
|
448
|
+
const totalSize = fileList.reduce((sum, f) => sum + f.size, 0);
|
|
378
449
|
const contentHash = await generateContentHash({
|
|
379
450
|
runtime: buildConfig.runtime,
|
|
380
451
|
description: finalDescription,
|
|
@@ -382,6 +453,7 @@ export const buildSubcommand = createCommand({
|
|
|
382
453
|
files: fileList,
|
|
383
454
|
fileHashes,
|
|
384
455
|
env: finalEnv,
|
|
456
|
+
isPublic,
|
|
385
457
|
});
|
|
386
458
|
if (dryRun) {
|
|
387
459
|
if (!options.json) {
|
|
@@ -393,10 +465,11 @@ export const buildSubcommand = createCommand({
|
|
|
393
465
|
Description: finalDescription ?? '-',
|
|
394
466
|
Runtime: buildConfig.runtime,
|
|
395
467
|
Tag: opts.tag ?? 'latest',
|
|
468
|
+
Access: isPublic ? 'public' : 'private',
|
|
396
469
|
Size: tui.formatBytes(totalSize),
|
|
397
470
|
Files: fileList.length.toFixed(),
|
|
398
471
|
},
|
|
399
|
-
], ['Name', 'Description', 'Runtime', 'Tag', 'Size', 'Files'], { layout: 'vertical', padStart: ' ' });
|
|
472
|
+
], ['Name', 'Description', 'Runtime', 'Tag', 'Access', 'Size', 'Files'], { layout: 'vertical', padStart: ' ' });
|
|
400
473
|
if (buildConfig.dependencies && buildConfig.dependencies.length > 0) {
|
|
401
474
|
console.log('');
|
|
402
475
|
tui.info('Dependencies:');
|
|
@@ -458,11 +531,12 @@ export const buildSubcommand = createCommand({
|
|
|
458
531
|
return await snapshotBuildInit(client, {
|
|
459
532
|
runtime: buildConfig.runtime,
|
|
460
533
|
name: finalName,
|
|
461
|
-
tag: opts.tag,
|
|
534
|
+
tag: opts.tag ?? 'latest',
|
|
462
535
|
description: finalDescription,
|
|
463
536
|
contentHash,
|
|
464
537
|
force: opts.force,
|
|
465
|
-
encrypt:
|
|
538
|
+
encrypt: !isPublic,
|
|
539
|
+
public: isPublic,
|
|
466
540
|
orgId,
|
|
467
541
|
});
|
|
468
542
|
},
|
|
@@ -490,7 +564,7 @@ export const buildSubcommand = createCommand({
|
|
|
490
564
|
userMetadata: finalMetadata,
|
|
491
565
|
};
|
|
492
566
|
}
|
|
493
|
-
// Encrypt the archive if public key is provided
|
|
567
|
+
// Encrypt the archive if public key is provided (private snapshots only)
|
|
494
568
|
let uploadPath = archivePath;
|
|
495
569
|
let uploadSize = archiveSize;
|
|
496
570
|
if (initResult.publicKey) {
|
|
@@ -518,26 +592,74 @@ export const buildSubcommand = createCommand({
|
|
|
518
592
|
uploadPath = encryptedPath;
|
|
519
593
|
uploadSize = Bun.file(encryptedPath).size;
|
|
520
594
|
}
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
595
|
+
if (initResult.uploadUrl) {
|
|
596
|
+
// Private snapshot: upload directly to S3
|
|
597
|
+
// Use Bun.file() directly as body - Bun sets Content-Length automatically from file size
|
|
598
|
+
await tui.spinner({
|
|
599
|
+
message: 'Uploading snapshot...',
|
|
600
|
+
clearOnSuccess: true,
|
|
601
|
+
callback: async () => {
|
|
602
|
+
const uploadFile = Bun.file(uploadPath);
|
|
603
|
+
const response = await fetch(initResult.uploadUrl, {
|
|
604
|
+
method: 'PUT',
|
|
605
|
+
headers: {
|
|
606
|
+
'Content-Type': 'application/gzip',
|
|
607
|
+
},
|
|
608
|
+
body: uploadFile,
|
|
609
|
+
});
|
|
610
|
+
if (!response.ok) {
|
|
611
|
+
throw new Error(`Upload failed: ${response.status} ${response.statusText}`);
|
|
612
|
+
}
|
|
613
|
+
},
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
else {
|
|
617
|
+
// Public snapshot: upload via Catalyst (with virus scanning)
|
|
618
|
+
try {
|
|
619
|
+
await tui.spinner({
|
|
620
|
+
message: 'Uploading and scanning snapshot...',
|
|
621
|
+
type: 'progress',
|
|
622
|
+
clearOnSuccess: true,
|
|
623
|
+
clearOnError: true,
|
|
624
|
+
callback: async (updateProgress) => {
|
|
625
|
+
const uploadFile = Bun.file(uploadPath);
|
|
626
|
+
const progressStream = createProgressStream(uploadFile, uploadSize, updateProgress);
|
|
627
|
+
await snapshotUpload(client, {
|
|
628
|
+
snapshotId: initResult.snapshotId,
|
|
629
|
+
body: progressStream,
|
|
630
|
+
contentLength: uploadSize,
|
|
631
|
+
orgId,
|
|
632
|
+
});
|
|
532
633
|
},
|
|
533
|
-
body: uploadFile,
|
|
534
634
|
});
|
|
535
|
-
|
|
536
|
-
|
|
635
|
+
}
|
|
636
|
+
catch (err) {
|
|
637
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
638
|
+
const malwareMatch = MALWARE_REGEX.exec(errorMessage);
|
|
639
|
+
if (malwareMatch) {
|
|
640
|
+
const virusName = malwareMatch[1];
|
|
641
|
+
if (options.json) {
|
|
642
|
+
console.log(JSON.stringify({
|
|
643
|
+
snapshotId: '',
|
|
644
|
+
name: finalName ?? '',
|
|
645
|
+
tag: opts.tag ?? 'latest',
|
|
646
|
+
runtime: buildConfig.runtime,
|
|
647
|
+
sizeBytes: totalSize,
|
|
648
|
+
fileCount: fileList.length,
|
|
649
|
+
createdAt: new Date().toISOString(),
|
|
650
|
+
error: errorMessage,
|
|
651
|
+
malwareDetected: true,
|
|
652
|
+
virusName,
|
|
653
|
+
}, null, 2));
|
|
654
|
+
process.exit(ErrorCode.MALWARE_DETECTED);
|
|
655
|
+
}
|
|
656
|
+
console.log('');
|
|
657
|
+
tui.errorBox('Malware Detected', `Your snapshot was rejected because it contains malware.\n\nVirus: ${virusName}\n\nPlease remove the infected files and try again.`);
|
|
658
|
+
tui.fatal('Snapshot build failed due to malware detection', ErrorCode.MALWARE_DETECTED);
|
|
537
659
|
}
|
|
538
|
-
|
|
539
|
-
}
|
|
540
|
-
}
|
|
660
|
+
throw err;
|
|
661
|
+
}
|
|
662
|
+
}
|
|
541
663
|
const snapshot = await tui.spinner({
|
|
542
664
|
message: 'Finalizing snapshot...',
|
|
543
665
|
clearOnSuccess: true,
|