@agentuity/cli 0.1.24 → 0.1.25
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 +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/cmd/ai/cadence/index.d.ts.map +1 -1
- package/dist/cmd/ai/cadence/index.js +8 -2
- package/dist/cmd/ai/cadence/index.js.map +1 -1
- package/dist/cmd/ai/index.d.ts.map +1 -1
- package/dist/cmd/ai/index.js +8 -1
- package/dist/cmd/ai/index.js.map +1 -1
- package/dist/cmd/build/patch/index.d.ts.map +1 -1
- package/dist/cmd/build/patch/index.js +4 -0
- package/dist/cmd/build/patch/index.js.map +1 -1
- package/dist/cmd/build/patch/otel-llm.d.ts +10 -0
- package/dist/cmd/build/patch/otel-llm.d.ts.map +1 -0
- package/dist/cmd/build/patch/otel-llm.js +374 -0
- package/dist/cmd/build/patch/otel-llm.js.map +1 -0
- package/dist/cmd/cloud/db/create.js +3 -3
- package/dist/cmd/cloud/db/create.js.map +1 -1
- package/dist/cmd/cloud/deploy.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.js +55 -2
- package/dist/cmd/cloud/deploy.js.map +1 -1
- package/dist/cmd/cloud/env/pull.d.ts.map +1 -1
- package/dist/cmd/cloud/env/pull.js +26 -17
- package/dist/cmd/cloud/env/pull.js.map +1 -1
- package/dist/cmd/cloud/eval-run/list.d.ts.map +1 -1
- package/dist/cmd/cloud/eval-run/list.js +5 -1
- package/dist/cmd/cloud/eval-run/list.js.map +1 -1
- package/dist/cmd/cloud/queue/dlq.d.ts.map +1 -1
- package/dist/cmd/cloud/queue/dlq.js.map +1 -1
- package/dist/cmd/cloud/sandbox/download.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/download.js +8 -3
- package/dist/cmd/cloud/sandbox/download.js.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/build.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/build.js +43 -36
- package/dist/cmd/cloud/sandbox/snapshot/build.js.map +1 -1
- package/dist/cmd/cloud/sandbox/upload.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/upload.js +8 -1
- package/dist/cmd/cloud/sandbox/upload.js.map +1 -1
- package/dist/cmd/profile/create.js +2 -2
- package/dist/cmd/profile/create.js.map +1 -1
- package/dist/cmd/project/create.d.ts.map +1 -1
- package/dist/cmd/project/create.js +6 -3
- package/dist/cmd/project/create.js.map +1 -1
- package/dist/utils/deps.d.ts +8 -0
- package/dist/utils/deps.d.ts.map +1 -0
- package/dist/utils/deps.js +36 -0
- package/dist/utils/deps.js.map +1 -0
- package/package.json +6 -6
- package/src/cli.ts +1 -5
- package/src/cmd/ai/cadence/index.ts +8 -2
- package/src/cmd/ai/index.ts +8 -1
- package/src/cmd/build/patch/index.ts +4 -0
- package/src/cmd/build/patch/otel-llm.ts +421 -0
- package/src/cmd/cloud/db/create.ts +3 -3
- package/src/cmd/cloud/deploy.ts +77 -1
- package/src/cmd/cloud/env/pull.ts +29 -19
- package/src/cmd/cloud/eval-run/list.ts +5 -1
- package/src/cmd/cloud/queue/dlq.ts +11 -10
- package/src/cmd/cloud/sandbox/download.ts +9 -3
- package/src/cmd/cloud/sandbox/snapshot/build.ts +59 -44
- package/src/cmd/cloud/sandbox/upload.ts +9 -1
- package/src/cmd/profile/create.ts +2 -2
- package/src/cmd/project/create.ts +6 -3
- package/src/utils/deps.ts +54 -0
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate the OTel wrapper code for LLM chat completions.
|
|
3
|
+
* This creates a span with GenAI semantic conventions.
|
|
4
|
+
*/
|
|
5
|
+
function generateChatCompletionsWrapper(config) {
|
|
6
|
+
const { provider, className, inputTokensField, outputTokensField, responseIdField = 'id', finishReasonPath, responseContentPath, requestMessagesField = 'messages', streamDeltaContentPath, streamFinishReasonPath, streamUsagePath = 'usage', } = config;
|
|
7
|
+
// Generate code to extract nested field (e.g., 'choices[0].finish_reason')
|
|
8
|
+
const generateFieldAccess = (path, varName) => {
|
|
9
|
+
if (!path)
|
|
10
|
+
return 'undefined';
|
|
11
|
+
// Convert path like 'choices[0].finish_reason' to safe access
|
|
12
|
+
const parts = path.split('.');
|
|
13
|
+
let code = varName;
|
|
14
|
+
for (const part of parts) {
|
|
15
|
+
const match = part.match(/^(\w+)\[(\d+)\]$/);
|
|
16
|
+
if (match) {
|
|
17
|
+
code = `(${code}?.${match[1]}?.[${match[2]}])`;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
code = `(${code}?.${part})`;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return code;
|
|
24
|
+
};
|
|
25
|
+
const finishReasonCode = generateFieldAccess(finishReasonPath, 'response');
|
|
26
|
+
const responseContentCode = generateFieldAccess(responseContentPath, 'response');
|
|
27
|
+
const streamDeltaCode = generateFieldAccess(streamDeltaContentPath, 'chunk');
|
|
28
|
+
const streamFinishCode = generateFieldAccess(streamFinishReasonPath, 'chunk');
|
|
29
|
+
const streamUsageCode = generateFieldAccess(streamUsagePath, 'chunk');
|
|
30
|
+
return `
|
|
31
|
+
import * as _otel_api from '@opentelemetry/api';
|
|
32
|
+
|
|
33
|
+
const _ATTR_GEN_AI_SYSTEM = 'gen_ai.system';
|
|
34
|
+
const _ATTR_GEN_AI_REQUEST_MODEL = 'gen_ai.request.model';
|
|
35
|
+
const _ATTR_GEN_AI_REQUEST_MAX_TOKENS = 'gen_ai.request.max_tokens';
|
|
36
|
+
const _ATTR_GEN_AI_REQUEST_TEMPERATURE = 'gen_ai.request.temperature';
|
|
37
|
+
const _ATTR_GEN_AI_REQUEST_TOP_P = 'gen_ai.request.top_p';
|
|
38
|
+
const _ATTR_GEN_AI_REQUEST_FREQUENCY_PENALTY = 'gen_ai.request.frequency_penalty';
|
|
39
|
+
const _ATTR_GEN_AI_REQUEST_PRESENCE_PENALTY = 'gen_ai.request.presence_penalty';
|
|
40
|
+
const _ATTR_GEN_AI_RESPONSE_MODEL = 'gen_ai.response.model';
|
|
41
|
+
const _ATTR_GEN_AI_RESPONSE_ID = 'gen_ai.response.id';
|
|
42
|
+
const _ATTR_GEN_AI_RESPONSE_FINISH_REASONS = 'gen_ai.response.finish_reasons';
|
|
43
|
+
const _ATTR_GEN_AI_USAGE_INPUT_TOKENS = 'gen_ai.usage.input_tokens';
|
|
44
|
+
const _ATTR_GEN_AI_USAGE_OUTPUT_TOKENS = 'gen_ai.usage.output_tokens';
|
|
45
|
+
const _ATTR_GEN_AI_OPERATION_NAME = 'gen_ai.operation.name';
|
|
46
|
+
const _ATTR_GEN_AI_REQUEST_MESSAGES = 'gen_ai.request.messages';
|
|
47
|
+
const _ATTR_GEN_AI_RESPONSE_TEXT = 'gen_ai.response.text';
|
|
48
|
+
|
|
49
|
+
const _otel_tracer = _otel_api.trace.getTracer('@agentuity/otel-llm', '1.0.0');
|
|
50
|
+
|
|
51
|
+
function _wrapAsyncIterator(iterator, span, inputTokensField, outputTokensField) {
|
|
52
|
+
let contentChunks = [];
|
|
53
|
+
let finishReason = null;
|
|
54
|
+
let usage = null;
|
|
55
|
+
let model = null;
|
|
56
|
+
let responseId = null;
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
[Symbol.asyncIterator]() {
|
|
60
|
+
return this;
|
|
61
|
+
},
|
|
62
|
+
async next() {
|
|
63
|
+
try {
|
|
64
|
+
const result = await iterator.next();
|
|
65
|
+
if (result.done) {
|
|
66
|
+
// Stream complete - finalize span
|
|
67
|
+
if (contentChunks.length > 0) {
|
|
68
|
+
span.setAttribute(_ATTR_GEN_AI_RESPONSE_TEXT, contentChunks.join(''));
|
|
69
|
+
}
|
|
70
|
+
if (finishReason) {
|
|
71
|
+
span.setAttribute(_ATTR_GEN_AI_RESPONSE_FINISH_REASONS, JSON.stringify([finishReason]));
|
|
72
|
+
}
|
|
73
|
+
if (model) {
|
|
74
|
+
span.setAttribute(_ATTR_GEN_AI_RESPONSE_MODEL, model);
|
|
75
|
+
}
|
|
76
|
+
if (responseId) {
|
|
77
|
+
span.setAttribute(_ATTR_GEN_AI_RESPONSE_ID, responseId);
|
|
78
|
+
}
|
|
79
|
+
if (usage) {
|
|
80
|
+
if (usage[inputTokensField] !== undefined) {
|
|
81
|
+
span.setAttribute(_ATTR_GEN_AI_USAGE_INPUT_TOKENS, usage[inputTokensField]);
|
|
82
|
+
}
|
|
83
|
+
if (usage[outputTokensField] !== undefined) {
|
|
84
|
+
span.setAttribute(_ATTR_GEN_AI_USAGE_OUTPUT_TOKENS, usage[outputTokensField]);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
span.setStatus({ code: _otel_api.SpanStatusCode.OK });
|
|
88
|
+
span.end();
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const chunk = result.value;
|
|
93
|
+
|
|
94
|
+
// Capture model and id from first chunk
|
|
95
|
+
if (chunk.model && !model) {
|
|
96
|
+
model = chunk.model;
|
|
97
|
+
}
|
|
98
|
+
if (chunk.id && !responseId) {
|
|
99
|
+
responseId = chunk.id;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Capture delta content
|
|
103
|
+
const deltaContent = ${streamDeltaCode};
|
|
104
|
+
if (deltaContent) {
|
|
105
|
+
contentChunks.push(deltaContent);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Capture finish reason
|
|
109
|
+
const chunkFinishReason = ${streamFinishCode};
|
|
110
|
+
if (chunkFinishReason) {
|
|
111
|
+
finishReason = chunkFinishReason;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Capture usage (usually in final chunk with stream_options)
|
|
115
|
+
const chunkUsage = ${streamUsageCode};
|
|
116
|
+
if (chunkUsage) {
|
|
117
|
+
usage = chunkUsage;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return result;
|
|
121
|
+
} catch (error) {
|
|
122
|
+
span.setStatus({ code: _otel_api.SpanStatusCode.ERROR, message: error?.message });
|
|
123
|
+
span.recordException(error);
|
|
124
|
+
span.end();
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
async return(value) {
|
|
129
|
+
span.setStatus({ code: _otel_api.SpanStatusCode.OK });
|
|
130
|
+
span.end();
|
|
131
|
+
if (iterator.return) {
|
|
132
|
+
return iterator.return(value);
|
|
133
|
+
}
|
|
134
|
+
return { done: true, value };
|
|
135
|
+
},
|
|
136
|
+
async throw(error) {
|
|
137
|
+
span.setStatus({ code: _otel_api.SpanStatusCode.ERROR, message: error?.message });
|
|
138
|
+
span.recordException(error);
|
|
139
|
+
span.end();
|
|
140
|
+
if (iterator.throw) {
|
|
141
|
+
return iterator.throw(error);
|
|
142
|
+
}
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function _wrapStream(stream, span, inputTokensField, outputTokensField) {
|
|
149
|
+
// Get the original iterator
|
|
150
|
+
const originalIterator = stream[Symbol.asyncIterator]();
|
|
151
|
+
const wrappedIterator = _wrapAsyncIterator(originalIterator, span, inputTokensField, outputTokensField);
|
|
152
|
+
|
|
153
|
+
// Return a proxy that wraps the async iterator but preserves other properties/methods
|
|
154
|
+
return new Proxy(stream, {
|
|
155
|
+
get(target, prop) {
|
|
156
|
+
if (prop === Symbol.asyncIterator) {
|
|
157
|
+
return () => wrappedIterator;
|
|
158
|
+
}
|
|
159
|
+
// Preserve other stream methods like tee(), toReadableStream(), etc.
|
|
160
|
+
const value = target[prop];
|
|
161
|
+
if (typeof value === 'function') {
|
|
162
|
+
return value.bind(target);
|
|
163
|
+
}
|
|
164
|
+
return value;
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Safely patch the class if it exists
|
|
170
|
+
let _original_create;
|
|
171
|
+
try {
|
|
172
|
+
if (typeof ${className} === 'undefined' || !${className}.prototype || typeof ${className}.prototype.create !== 'function') {
|
|
173
|
+
console.debug('[Agentuity OTel] Skipping patch: ${className}.prototype.create not found or not a function');
|
|
174
|
+
} else {
|
|
175
|
+
_original_create = ${className}.prototype.create;
|
|
176
|
+
${className}.prototype.create = _agentuity_otel_create;
|
|
177
|
+
}
|
|
178
|
+
} catch (e) {
|
|
179
|
+
console.debug('[Agentuity OTel] Failed to patch ${className}:', e?.message || e);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function _agentuity_otel_create(body, options) {
|
|
183
|
+
// If patching failed, _original_create won't be set - this shouldn't happen but handle gracefully
|
|
184
|
+
if (!_original_create) {
|
|
185
|
+
throw new Error('[Agentuity OTel] ${className}.prototype.create was not properly patched');
|
|
186
|
+
}
|
|
187
|
+
const attributes = {
|
|
188
|
+
[_ATTR_GEN_AI_SYSTEM]: '${provider}',
|
|
189
|
+
[_ATTR_GEN_AI_OPERATION_NAME]: 'chat',
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
if (body.model) {
|
|
193
|
+
attributes[_ATTR_GEN_AI_REQUEST_MODEL] = body.model;
|
|
194
|
+
}
|
|
195
|
+
if (body.max_tokens) {
|
|
196
|
+
attributes[_ATTR_GEN_AI_REQUEST_MAX_TOKENS] = body.max_tokens;
|
|
197
|
+
}
|
|
198
|
+
if (body.temperature !== undefined) {
|
|
199
|
+
attributes[_ATTR_GEN_AI_REQUEST_TEMPERATURE] = body.temperature;
|
|
200
|
+
}
|
|
201
|
+
if (body.top_p !== undefined) {
|
|
202
|
+
attributes[_ATTR_GEN_AI_REQUEST_TOP_P] = body.top_p;
|
|
203
|
+
}
|
|
204
|
+
if (body.frequency_penalty !== undefined) {
|
|
205
|
+
attributes[_ATTR_GEN_AI_REQUEST_FREQUENCY_PENALTY] = body.frequency_penalty;
|
|
206
|
+
}
|
|
207
|
+
if (body.presence_penalty !== undefined) {
|
|
208
|
+
attributes[_ATTR_GEN_AI_REQUEST_PRESENCE_PENALTY] = body.presence_penalty;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Capture request messages
|
|
212
|
+
if (body.${requestMessagesField} && Array.isArray(body.${requestMessagesField})) {
|
|
213
|
+
try {
|
|
214
|
+
attributes[_ATTR_GEN_AI_REQUEST_MESSAGES] = JSON.stringify(body.${requestMessagesField});
|
|
215
|
+
} catch (e) {
|
|
216
|
+
// Ignore serialization errors
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const spanName = body.model ? \`chat \${body.model}\` : 'chat';
|
|
221
|
+
|
|
222
|
+
return _otel_tracer.startActiveSpan(spanName, { attributes, kind: _otel_api.SpanKind.CLIENT }, (span) => {
|
|
223
|
+
let result;
|
|
224
|
+
try {
|
|
225
|
+
result = _original_create.call(this, body, options);
|
|
226
|
+
} catch (error) {
|
|
227
|
+
span.setStatus({ code: _otel_api.SpanStatusCode.ERROR, message: error?.message });
|
|
228
|
+
span.recordException(error);
|
|
229
|
+
span.end();
|
|
230
|
+
throw error;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Handle streaming responses
|
|
234
|
+
if (body.stream) {
|
|
235
|
+
// Result is a Promise that resolves to a Stream
|
|
236
|
+
if (result && typeof result.then === 'function') {
|
|
237
|
+
return result.then((stream) => {
|
|
238
|
+
try {
|
|
239
|
+
return _wrapStream(stream, span, '${inputTokensField}', '${outputTokensField}');
|
|
240
|
+
} catch (error) {
|
|
241
|
+
span.setStatus({ code: _otel_api.SpanStatusCode.ERROR, message: error?.message });
|
|
242
|
+
span.recordException(error);
|
|
243
|
+
span.end();
|
|
244
|
+
throw error;
|
|
245
|
+
}
|
|
246
|
+
}).catch((error) => {
|
|
247
|
+
span.setStatus({ code: _otel_api.SpanStatusCode.ERROR, message: error?.message });
|
|
248
|
+
span.recordException(error);
|
|
249
|
+
span.end();
|
|
250
|
+
throw error;
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
// Result is already a Stream - wrap in try/catch for synchronous failures
|
|
254
|
+
try {
|
|
255
|
+
return _wrapStream(result, span, '${inputTokensField}', '${outputTokensField}');
|
|
256
|
+
} catch (error) {
|
|
257
|
+
span.setStatus({ code: _otel_api.SpanStatusCode.ERROR, message: error?.message });
|
|
258
|
+
span.recordException(error);
|
|
259
|
+
span.end();
|
|
260
|
+
throw error;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Handle non-streaming responses
|
|
265
|
+
if (result && typeof result.then === 'function') {
|
|
266
|
+
return result.then((response) => {
|
|
267
|
+
if (response) {
|
|
268
|
+
if (response.model) {
|
|
269
|
+
span.setAttribute(_ATTR_GEN_AI_RESPONSE_MODEL, response.model);
|
|
270
|
+
}
|
|
271
|
+
if (response.${responseIdField}) {
|
|
272
|
+
span.setAttribute(_ATTR_GEN_AI_RESPONSE_ID, response.${responseIdField});
|
|
273
|
+
}
|
|
274
|
+
if (response.usage) {
|
|
275
|
+
if (response.usage.${inputTokensField} !== undefined) {
|
|
276
|
+
span.setAttribute(_ATTR_GEN_AI_USAGE_INPUT_TOKENS, response.usage.${inputTokensField});
|
|
277
|
+
}
|
|
278
|
+
if (response.usage.${outputTokensField} !== undefined) {
|
|
279
|
+
span.setAttribute(_ATTR_GEN_AI_USAGE_OUTPUT_TOKENS, response.usage.${outputTokensField});
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
// Extract finish reason
|
|
283
|
+
const finishReason = ${finishReasonCode};
|
|
284
|
+
if (finishReason) {
|
|
285
|
+
span.setAttribute(_ATTR_GEN_AI_RESPONSE_FINISH_REASONS, JSON.stringify([finishReason]));
|
|
286
|
+
}
|
|
287
|
+
// Extract response content
|
|
288
|
+
const responseContent = ${responseContentCode};
|
|
289
|
+
if (responseContent) {
|
|
290
|
+
span.setAttribute(_ATTR_GEN_AI_RESPONSE_TEXT, responseContent);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
span.setStatus({ code: _otel_api.SpanStatusCode.OK });
|
|
294
|
+
span.end();
|
|
295
|
+
return response;
|
|
296
|
+
}).catch((error) => {
|
|
297
|
+
span.setStatus({ code: _otel_api.SpanStatusCode.ERROR, message: error?.message });
|
|
298
|
+
span.recordException(error);
|
|
299
|
+
span.end();
|
|
300
|
+
throw error;
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
span.end();
|
|
305
|
+
return result;
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
`;
|
|
309
|
+
}
|
|
310
|
+
export function generatePatches() {
|
|
311
|
+
const patches = new Map();
|
|
312
|
+
// OpenAI Chat Completions - patch resources/chat/completions/completions.mjs
|
|
313
|
+
patches.set('openai:otel', {
|
|
314
|
+
module: 'openai',
|
|
315
|
+
filename: 'resources/chat/completions/completions',
|
|
316
|
+
body: {
|
|
317
|
+
after: generateChatCompletionsWrapper({
|
|
318
|
+
provider: 'openai',
|
|
319
|
+
className: 'Completions',
|
|
320
|
+
inputTokensField: 'prompt_tokens',
|
|
321
|
+
outputTokensField: 'completion_tokens',
|
|
322
|
+
responseIdField: 'id',
|
|
323
|
+
finishReasonPath: 'choices[0].finish_reason',
|
|
324
|
+
responseContentPath: 'choices[0].message.content',
|
|
325
|
+
requestMessagesField: 'messages',
|
|
326
|
+
streamDeltaContentPath: 'choices[0].delta.content',
|
|
327
|
+
streamFinishReasonPath: 'choices[0].finish_reason',
|
|
328
|
+
streamUsagePath: 'usage',
|
|
329
|
+
}),
|
|
330
|
+
},
|
|
331
|
+
});
|
|
332
|
+
// Anthropic Messages - patch resources/messages.mjs
|
|
333
|
+
patches.set('@anthropic-ai/sdk:otel', {
|
|
334
|
+
module: '@anthropic-ai/sdk',
|
|
335
|
+
filename: 'resources/messages',
|
|
336
|
+
body: {
|
|
337
|
+
after: generateChatCompletionsWrapper({
|
|
338
|
+
provider: 'anthropic',
|
|
339
|
+
className: 'Messages',
|
|
340
|
+
inputTokensField: 'input_tokens',
|
|
341
|
+
outputTokensField: 'output_tokens',
|
|
342
|
+
responseIdField: 'id',
|
|
343
|
+
finishReasonPath: 'stop_reason',
|
|
344
|
+
responseContentPath: 'content[0].text',
|
|
345
|
+
requestMessagesField: 'messages',
|
|
346
|
+
streamDeltaContentPath: 'delta.text',
|
|
347
|
+
streamFinishReasonPath: 'delta.stop_reason',
|
|
348
|
+
streamUsagePath: 'usage',
|
|
349
|
+
}),
|
|
350
|
+
},
|
|
351
|
+
});
|
|
352
|
+
// Groq Chat Completions - patch resources/chat/completions.mjs
|
|
353
|
+
patches.set('groq-sdk:otel', {
|
|
354
|
+
module: 'groq-sdk',
|
|
355
|
+
filename: 'resources/chat/completions',
|
|
356
|
+
body: {
|
|
357
|
+
after: generateChatCompletionsWrapper({
|
|
358
|
+
provider: 'groq',
|
|
359
|
+
className: 'Completions',
|
|
360
|
+
inputTokensField: 'prompt_tokens',
|
|
361
|
+
outputTokensField: 'completion_tokens',
|
|
362
|
+
responseIdField: 'id',
|
|
363
|
+
finishReasonPath: 'choices[0].finish_reason',
|
|
364
|
+
responseContentPath: 'choices[0].message.content',
|
|
365
|
+
requestMessagesField: 'messages',
|
|
366
|
+
streamDeltaContentPath: 'choices[0].delta.content',
|
|
367
|
+
streamFinishReasonPath: 'choices[0].finish_reason',
|
|
368
|
+
streamUsagePath: 'x_groq.usage',
|
|
369
|
+
}),
|
|
370
|
+
},
|
|
371
|
+
});
|
|
372
|
+
return patches;
|
|
373
|
+
}
|
|
374
|
+
//# sourceMappingURL=otel-llm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otel-llm.js","sourceRoot":"","sources":["../../../../src/cmd/build/patch/otel-llm.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,10 +15,10 @@ export const createSubcommand = defineSubcommand({
|
|
|
15
15
|
idempotent: false,
|
|
16
16
|
requires: { auth: true, org: true, region: true },
|
|
17
17
|
examples: [
|
|
18
|
-
{ command: getCommand('cloud db create'), description: 'Create new
|
|
18
|
+
{ command: getCommand('cloud db create'), description: 'Create new database' },
|
|
19
19
|
{ command: getCommand('cloud db new'), description: 'Run new command' },
|
|
20
|
-
{ command: getCommand('cloud db create --name my-db'), description: 'Create new
|
|
21
|
-
{ command: getCommand('--dry-run cloud db create'), description: 'Create new
|
|
20
|
+
{ command: getCommand('cloud db create --name my-db'), description: 'Create new database' },
|
|
21
|
+
{ command: getCommand('--dry-run cloud db create'), description: 'Create new database' },
|
|
22
22
|
],
|
|
23
23
|
schema: {
|
|
24
24
|
options: z.object({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../../../src/cmd/cloud/db/create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,EAAE,gBAAgB,IAAI,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,MAAM,CAAC,MAAM,gBAAgB,GAAG,gBAAgB,CAAC;IAChD,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE,CAAC,KAAK,CAAC;IAChB,WAAW,EAAE,gCAAgC;IAC7C,IAAI,EAAE,CAAC,UAAU,EAAE,kBAAkB,EAAE,MAAM,EAAE,eAAe,EAAE,qBAAqB,CAAC;IACtF,UAAU,EAAE,KAAK;IACjB,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;IACjD,QAAQ,EAAE;QACT,EAAE,OAAO,EAAE,UAAU,CAAC,iBAAiB,CAAC,EAAE,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../../../src/cmd/cloud/db/create.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../../src/cmd/cloud/deploy.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../../src/cmd/cloud/deploy.ts"],"names":[],"mappings":"AAmFA,eAAO,MAAM,gBAAgB,sCA4iC3B,CAAC"}
|
package/dist/cmd/cloud/deploy.js
CHANGED
|
@@ -14,17 +14,18 @@ import { runGitLink } from '../git/link';
|
|
|
14
14
|
import { runSteps, stepSuccess, stepSkipped, stepError, pauseStepUI, } from '../../steps';
|
|
15
15
|
import { viteBundle } from '../build/vite-bundler';
|
|
16
16
|
import { loadBuildMetadata, getStreamURL } from '../../config';
|
|
17
|
-
import { projectEnvUpdate, projectDeploymentCreate, projectDeploymentUpdate, projectDeploymentComplete, projectDeploymentStatus, validateResources, getAppBaseURL, } from '@agentuity/server';
|
|
17
|
+
import { projectEnvUpdate, projectDeploymentCreate, projectDeploymentUpdate, projectDeploymentComplete, projectDeploymentStatus, projectDeploymentMalwareCheck, validateResources, getAppBaseURL, } from '@agentuity/server';
|
|
18
18
|
import { findExistingEnvFile, readEnvFile, filterAgentuitySdkKeys, splitEnvAndSecrets, } from '../../env-util';
|
|
19
19
|
import { zipDir } from '../../utils/zip';
|
|
20
20
|
import { encryptFIPSKEMDEMStream } from '../../crypto/box';
|
|
21
21
|
import { getCommand } from '../../command-prefix';
|
|
22
22
|
import * as domain from '../../domain';
|
|
23
|
-
import { ErrorCode } from '../../errors';
|
|
23
|
+
import { ErrorCode, getExitCode } from '../../errors';
|
|
24
24
|
import { typecheck } from '../build/typecheck';
|
|
25
25
|
import { BuildReportCollector, setGlobalCollector, clearGlobalCollector } from '../../build-report';
|
|
26
26
|
import { runForkedDeploy } from './deploy-fork';
|
|
27
27
|
import { validateAptDependencies } from '../../utils/apt-validator';
|
|
28
|
+
import { extractDependencies } from '../../utils/deps';
|
|
28
29
|
const DeploymentCancelledError = StructuredError('DeploymentCancelled', 'Deployment cancelled by user');
|
|
29
30
|
const DeployResponseSchema = z.object({
|
|
30
31
|
success: z.boolean().describe('Whether deployment succeeded'),
|
|
@@ -114,6 +115,7 @@ export const deploySubcommand = createSubcommand({
|
|
|
114
115
|
let instructions;
|
|
115
116
|
let complete;
|
|
116
117
|
let statusResult;
|
|
118
|
+
let malwareCheckPromise;
|
|
117
119
|
const logs = [];
|
|
118
120
|
const sdkKey = await loadProjectSDKKey(ctx.logger, ctx.projectDir);
|
|
119
121
|
// Ensure SDK key is present before proceeding
|
|
@@ -248,6 +250,27 @@ export const deploySubcommand = createSubcommand({
|
|
|
248
250
|
logger.fatal(`Failed to parse AGENTUITY_DEPLOYMENT: ${err}`);
|
|
249
251
|
}
|
|
250
252
|
}
|
|
253
|
+
// Start malware check async (runs in parallel with build)
|
|
254
|
+
if (deployment) {
|
|
255
|
+
malwareCheckPromise = (async () => {
|
|
256
|
+
try {
|
|
257
|
+
logger.debug('Starting malware dependency check');
|
|
258
|
+
const packages = await extractDependencies(projectDir, logger);
|
|
259
|
+
if (packages.length === 0) {
|
|
260
|
+
logger.debug('No packages to check for malware');
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
logger.debug('Checking %d packages for malware', packages.length);
|
|
264
|
+
const result = await projectDeploymentMalwareCheck(apiClient, deployment.id, packages);
|
|
265
|
+
logger.debug('Malware check complete: action=%s, flagged=%d', result.action, result.summary.flagged);
|
|
266
|
+
return result;
|
|
267
|
+
}
|
|
268
|
+
catch (error) {
|
|
269
|
+
logger.warn('Malware check failed: %s', error);
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
})();
|
|
273
|
+
}
|
|
251
274
|
try {
|
|
252
275
|
await saveProjectDir(projectDir);
|
|
253
276
|
// Check GitHub status and prompt for setup if not linked
|
|
@@ -415,6 +438,36 @@ export const deploySubcommand = createSubcommand({
|
|
|
415
438
|
}
|
|
416
439
|
},
|
|
417
440
|
},
|
|
441
|
+
{
|
|
442
|
+
label: 'Security Scan',
|
|
443
|
+
run: async () => {
|
|
444
|
+
if (!malwareCheckPromise) {
|
|
445
|
+
return stepSkipped('malware check not started');
|
|
446
|
+
}
|
|
447
|
+
const result = await malwareCheckPromise;
|
|
448
|
+
if (!result) {
|
|
449
|
+
return stepSkipped('malware check unavailable');
|
|
450
|
+
}
|
|
451
|
+
if (result.action === 'block' && result.findings.length > 0) {
|
|
452
|
+
if (opts.reportFile) {
|
|
453
|
+
for (const finding of result.findings) {
|
|
454
|
+
collector.addGeneralError('deploy', `Malicious package: ${finding.name}@${finding.version} (${finding.reason})`);
|
|
455
|
+
}
|
|
456
|
+
await collector.forceWrite();
|
|
457
|
+
}
|
|
458
|
+
const packageList = result.findings
|
|
459
|
+
.map((f) => `• ${f.name}@${f.version} (${f.reason})`)
|
|
460
|
+
.join('\n');
|
|
461
|
+
// Pause step UI to cleanly render error box
|
|
462
|
+
pauseStepUI(true);
|
|
463
|
+
tui.newline();
|
|
464
|
+
tui.errorBox('Malicious Packages Detected', `Your deployment was blocked because it contains known malicious packages:\n\n${packageList}\n\nRemove these packages from your project and try again.`);
|
|
465
|
+
tui.newline();
|
|
466
|
+
process.exit(getExitCode(ErrorCode.MALWARE_DETECTED));
|
|
467
|
+
}
|
|
468
|
+
return stepSuccess([`Scanned ${result.summary.scanned} packages`]);
|
|
469
|
+
},
|
|
470
|
+
},
|
|
418
471
|
{
|
|
419
472
|
label: 'Encrypt and Upload Deployment',
|
|
420
473
|
run: async (stepCtx) => {
|