@agentuity/cli 0.0.49 → 0.0.50
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/cmd/agents/index.d.ts +2 -0
- package/dist/cmd/agents/index.d.ts.map +1 -0
- package/dist/cmd/auth/ssh/list.d.ts.map +1 -1
- package/dist/cmd/bundle/ast.d.ts +3 -1
- package/dist/cmd/bundle/ast.d.ts.map +1 -1
- package/dist/cmd/bundle/plugin.d.ts.map +1 -1
- package/dist/cmd/cloud/deployment/list.d.ts.map +1 -1
- package/dist/cmd/cloud/index.d.ts.map +1 -1
- package/dist/cmd/cloud/session/get.d.ts +2 -0
- package/dist/cmd/cloud/session/get.d.ts.map +1 -0
- package/dist/cmd/cloud/session/index.d.ts +2 -0
- package/dist/cmd/cloud/session/index.d.ts.map +1 -0
- package/dist/cmd/cloud/session/list.d.ts +2 -0
- package/dist/cmd/cloud/session/list.d.ts.map +1 -0
- package/dist/cmd/cloud/session/logs.d.ts +2 -0
- package/dist/cmd/cloud/session/logs.d.ts.map +1 -0
- package/dist/cmd/dev/agents.d.ts +2 -0
- package/dist/cmd/dev/agents.d.ts.map +1 -0
- package/dist/cmd/dev/index.d.ts.map +1 -1
- package/dist/cmd/dev/sync.d.ts +12 -0
- package/dist/cmd/dev/sync.d.ts.map +1 -0
- package/dist/repl.d.ts +2 -6
- package/dist/repl.d.ts.map +1 -1
- package/dist/tui.d.ts +24 -0
- package/dist/tui.d.ts.map +1 -1
- package/dist/types.d.ts +12 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/format.d.ts +9 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/package.json +6 -3
- package/src/cli.ts +6 -4
- package/src/cmd/agents/index.ts +147 -0
- package/src/cmd/auth/ssh/list.ts +10 -16
- package/src/cmd/bundle/ast.test.ts +2 -2
- package/src/cmd/bundle/ast.ts +85 -17
- package/src/cmd/bundle/plugin.ts +24 -2
- package/src/cmd/cloud/deployment/list.ts +16 -22
- package/src/cmd/cloud/index.ts +2 -0
- package/src/cmd/cloud/session/get.ts +164 -0
- package/src/cmd/cloud/session/index.ts +11 -0
- package/src/cmd/cloud/session/list.ts +145 -0
- package/src/cmd/cloud/session/logs.ts +68 -0
- package/src/cmd/dev/agents.ts +122 -0
- package/src/cmd/dev/index.ts +101 -7
- package/src/cmd/dev/sync.ts +414 -0
- package/src/cmd/project/list.ts +1 -1
- package/src/cmd/project/show.ts +1 -1
- package/src/repl.ts +2 -12
- package/src/tui.ts +94 -0
- package/src/types.ts +13 -10
- package/src/utils/format.ts +17 -0
package/src/cmd/bundle/ast.ts
CHANGED
|
@@ -116,6 +116,10 @@ function hashSHA1(...val: string[]): string {
|
|
|
116
116
|
return hasher.digest().toHex();
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
export function getDevmodeDeploymentId(projectId: string, endpointId: string): string {
|
|
120
|
+
return `devmode_${hashSHA1(projectId, endpointId)}`;
|
|
121
|
+
}
|
|
122
|
+
|
|
119
123
|
function getAgentId(
|
|
120
124
|
projectId: string,
|
|
121
125
|
deploymentId: string,
|
|
@@ -151,6 +155,10 @@ function generateStableAgentId(projectId: string, name: string): string {
|
|
|
151
155
|
return `agentid_${hashSHA1(projectId, name)}`.substring(0, 64);
|
|
152
156
|
}
|
|
153
157
|
|
|
158
|
+
function generateStableEvalId(projectId: string, agentId: string, name: string): string {
|
|
159
|
+
return `evalid_${hashSHA1(projectId, agentId, name)}`.substring(0, 64);
|
|
160
|
+
}
|
|
161
|
+
|
|
154
162
|
type AcornParseResultType = ReturnType<typeof acornLoose.parse>;
|
|
155
163
|
|
|
156
164
|
function augmentAgentMetadataNode(
|
|
@@ -242,14 +250,29 @@ function setLiteralValue(literal: ASTLiteral, value: string) {
|
|
|
242
250
|
}
|
|
243
251
|
|
|
244
252
|
function augmentEvalMetadataNode(
|
|
253
|
+
projectId: string,
|
|
254
|
+
agentId: string,
|
|
245
255
|
id: string,
|
|
246
256
|
name: string,
|
|
247
257
|
rel: string,
|
|
248
258
|
version: string,
|
|
249
|
-
|
|
250
|
-
metadataObj: ASTObjectExpression
|
|
259
|
+
_ast: AcornParseResultType,
|
|
260
|
+
metadataObj: ASTObjectExpression,
|
|
261
|
+
_filename: string
|
|
251
262
|
): void {
|
|
252
|
-
|
|
263
|
+
const metadata = parseObjectExpressionToMap(metadataObj);
|
|
264
|
+
// Name can come from metadata.name or variable name (already resolved in caller)
|
|
265
|
+
// If metadata doesn't have name, we'll add it from the resolved name
|
|
266
|
+
if (!metadata.has('name')) {
|
|
267
|
+
metadataObj.properties.push(createObjectPropertyNode('name', name));
|
|
268
|
+
}
|
|
269
|
+
const descriptionNode = metadataObj.properties.find((x) => x.key.name === 'description')?.value;
|
|
270
|
+
const description = descriptionNode ? (descriptionNode as ASTLiteral).value : '';
|
|
271
|
+
const effectiveAgentId = agentId || '';
|
|
272
|
+
const _evalId = getEvalId(projectId, effectiveAgentId, rel, name, version); // Deployment-specific ID (not used, kept for potential future use)
|
|
273
|
+
const stableEvalId = generateStableEvalId(projectId, effectiveAgentId, name);
|
|
274
|
+
|
|
275
|
+
// Check if id, version, identifier, filename, evalId already exist
|
|
253
276
|
const existingKeys = new Set<string>();
|
|
254
277
|
for (const prop of metadataObj.properties) {
|
|
255
278
|
if (prop.key.type === 'Identifier') {
|
|
@@ -286,12 +309,12 @@ function augmentEvalMetadataNode(
|
|
|
286
309
|
}
|
|
287
310
|
|
|
288
311
|
if (!existingKeys.has('identifier')) {
|
|
289
|
-
metadataObj.properties.push(createObjectPropertyNode('identifier',
|
|
312
|
+
metadataObj.properties.push(createObjectPropertyNode('identifier', name));
|
|
290
313
|
} else {
|
|
291
314
|
for (const prop of metadataObj.properties) {
|
|
292
315
|
if (prop.key.type === 'Identifier' && prop.key.name === 'identifier') {
|
|
293
316
|
if (prop.value.type === 'Literal') {
|
|
294
|
-
setLiteralValue(prop.value as ASTLiteral,
|
|
317
|
+
setLiteralValue(prop.value as ASTLiteral, name);
|
|
295
318
|
}
|
|
296
319
|
break;
|
|
297
320
|
}
|
|
@@ -310,6 +333,32 @@ function augmentEvalMetadataNode(
|
|
|
310
333
|
}
|
|
311
334
|
}
|
|
312
335
|
}
|
|
336
|
+
|
|
337
|
+
if (!existingKeys.has('evalId')) {
|
|
338
|
+
metadataObj.properties.push(createObjectPropertyNode('evalId', stableEvalId));
|
|
339
|
+
} else {
|
|
340
|
+
for (const prop of metadataObj.properties) {
|
|
341
|
+
if (prop.key.type === 'Identifier' && prop.key.name === 'evalId') {
|
|
342
|
+
if (prop.value.type === 'Literal') {
|
|
343
|
+
setLiteralValue(prop.value as ASTLiteral, stableEvalId);
|
|
344
|
+
}
|
|
345
|
+
break;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (!existingKeys.has('description')) {
|
|
351
|
+
metadataObj.properties.push(createObjectPropertyNode('description', description));
|
|
352
|
+
} else {
|
|
353
|
+
for (const prop of metadataObj.properties) {
|
|
354
|
+
if (prop.key.type === 'Identifier' && prop.key.name === 'description') {
|
|
355
|
+
if (prop.value.type === 'Literal') {
|
|
356
|
+
setLiteralValue(prop.value as ASTLiteral, description);
|
|
357
|
+
}
|
|
358
|
+
break;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
313
362
|
}
|
|
314
363
|
|
|
315
364
|
export function parseEvalMetadata(
|
|
@@ -317,7 +366,8 @@ export function parseEvalMetadata(
|
|
|
317
366
|
filename: string,
|
|
318
367
|
contents: string,
|
|
319
368
|
projectId: string,
|
|
320
|
-
deploymentId: string
|
|
369
|
+
deploymentId: string,
|
|
370
|
+
agentId?: string
|
|
321
371
|
): [
|
|
322
372
|
string,
|
|
323
373
|
Array<{
|
|
@@ -326,6 +376,7 @@ export function parseEvalMetadata(
|
|
|
326
376
|
version: string;
|
|
327
377
|
identifier: string;
|
|
328
378
|
name: string;
|
|
379
|
+
evalId: string;
|
|
329
380
|
description?: string;
|
|
330
381
|
}>,
|
|
331
382
|
] {
|
|
@@ -339,8 +390,6 @@ export function parseEvalMetadata(
|
|
|
339
390
|
logger.trace(`Parsing evals from ${filename}`);
|
|
340
391
|
const ast = acornLoose.parse(contents, { ecmaVersion: 'latest', sourceType: 'module' });
|
|
341
392
|
const rel = relative(rootDir, filename);
|
|
342
|
-
const dir = dirname(filename);
|
|
343
|
-
const identifier = basename(dir);
|
|
344
393
|
const version = hash(contents);
|
|
345
394
|
const evals: Array<{
|
|
346
395
|
filename: string;
|
|
@@ -348,17 +397,16 @@ export function parseEvalMetadata(
|
|
|
348
397
|
version: string;
|
|
349
398
|
identifier: string;
|
|
350
399
|
name: string;
|
|
400
|
+
evalId: string;
|
|
351
401
|
description?: string;
|
|
352
402
|
}> = [];
|
|
353
403
|
|
|
354
|
-
// Find all agent.createEval() calls
|
|
404
|
+
// Find all exported agent.createEval() calls
|
|
355
405
|
for (const body of ast.body) {
|
|
356
406
|
let variableDeclaration: { declarations: Array<ASTVariableDeclarator> } | undefined;
|
|
357
407
|
|
|
358
|
-
//
|
|
359
|
-
if (body.type === '
|
|
360
|
-
variableDeclaration = body as { declarations: Array<ASTVariableDeclarator> };
|
|
361
|
-
} else if (body.type === 'ExportNamedDeclaration') {
|
|
408
|
+
// Only process exported VariableDeclarations
|
|
409
|
+
if (body.type === 'ExportNamedDeclaration') {
|
|
362
410
|
const exportDecl = body as {
|
|
363
411
|
declaration?: { type: string; declarations?: Array<ASTVariableDeclarator> };
|
|
364
412
|
};
|
|
@@ -447,14 +495,31 @@ export function parseEvalMetadata(
|
|
|
447
495
|
);
|
|
448
496
|
|
|
449
497
|
// Inject metadata into AST if metadata object exists
|
|
498
|
+
let stableEvalId: string;
|
|
499
|
+
const effectiveAgentId = agentId || '';
|
|
450
500
|
if (metadataObj) {
|
|
451
501
|
augmentEvalMetadataNode(
|
|
502
|
+
projectId,
|
|
503
|
+
effectiveAgentId,
|
|
452
504
|
evalId,
|
|
453
505
|
finalName,
|
|
454
506
|
rel,
|
|
455
507
|
version,
|
|
456
|
-
|
|
457
|
-
metadataObj
|
|
508
|
+
ast,
|
|
509
|
+
metadataObj,
|
|
510
|
+
filename
|
|
511
|
+
);
|
|
512
|
+
// Extract evalId from metadata after augmentation
|
|
513
|
+
const metadata = parseObjectExpressionToMap(metadataObj);
|
|
514
|
+
stableEvalId =
|
|
515
|
+
metadata.get('evalId') ||
|
|
516
|
+
generateStableEvalId(projectId, effectiveAgentId, finalName);
|
|
517
|
+
} else {
|
|
518
|
+
// If no metadata object, generate stable evalId
|
|
519
|
+
stableEvalId = generateStableEvalId(
|
|
520
|
+
projectId,
|
|
521
|
+
effectiveAgentId,
|
|
522
|
+
finalName
|
|
458
523
|
);
|
|
459
524
|
}
|
|
460
525
|
|
|
@@ -462,8 +527,9 @@ export function parseEvalMetadata(
|
|
|
462
527
|
filename: rel,
|
|
463
528
|
id: evalId,
|
|
464
529
|
version,
|
|
465
|
-
identifier,
|
|
530
|
+
identifier: finalName,
|
|
466
531
|
name: finalName,
|
|
532
|
+
evalId: stableEvalId,
|
|
467
533
|
description: evalDescription,
|
|
468
534
|
});
|
|
469
535
|
}
|
|
@@ -639,12 +705,14 @@ export async function parseAgentMetadata(
|
|
|
639
705
|
const evalsSource = await evalsFile.text();
|
|
640
706
|
const transpiler = new Bun.Transpiler({ loader: 'ts', target: 'bun' });
|
|
641
707
|
const evalsContents = transpiler.transformSync(evalsSource);
|
|
708
|
+
const agentId = result[1].get('agentId') || '';
|
|
642
709
|
const [, evals] = parseEvalMetadata(
|
|
643
710
|
rootDir,
|
|
644
711
|
evalsPath,
|
|
645
712
|
evalsContents,
|
|
646
713
|
projectId,
|
|
647
|
-
deploymentId
|
|
714
|
+
deploymentId,
|
|
715
|
+
agentId
|
|
648
716
|
);
|
|
649
717
|
if (evals.length > 0) {
|
|
650
718
|
logger.trace(`Adding ${evals.length} eval(s) to agent metadata for ${name}`);
|
package/src/cmd/bundle/plugin.ts
CHANGED
|
@@ -578,6 +578,7 @@ const AgentuityBundler: BunPlugin = {
|
|
|
578
578
|
version: v.get('version')!,
|
|
579
579
|
name: v.get('name')!,
|
|
580
580
|
description: v.get('description') ?? '<no description provided>',
|
|
581
|
+
projectId,
|
|
581
582
|
};
|
|
582
583
|
|
|
583
584
|
const evalsStr = v.get('evals');
|
|
@@ -586,7 +587,17 @@ const AgentuityBundler: BunPlugin = {
|
|
|
586
587
|
`[plugin] Found evals string for agent ${agentData.name}, parsing...`
|
|
587
588
|
);
|
|
588
589
|
try {
|
|
589
|
-
|
|
590
|
+
const parsedEvals = JSON.parse(evalsStr) as Array<
|
|
591
|
+
Omit<
|
|
592
|
+
NonNullable<BuildMetadata['agents'][number]['evals']>[number],
|
|
593
|
+
'agentIdentifier' | 'projectId'
|
|
594
|
+
>
|
|
595
|
+
>;
|
|
596
|
+
agentData.evals = parsedEvals.map((evalItem) => ({
|
|
597
|
+
...evalItem,
|
|
598
|
+
agentIdentifier: agentData.agentId,
|
|
599
|
+
projectId,
|
|
600
|
+
}));
|
|
590
601
|
logger.trace(
|
|
591
602
|
`[plugin] Successfully parsed ${agentData.evals?.length ?? 0} eval(s) for agent ${agentData.name}`
|
|
592
603
|
);
|
|
@@ -614,6 +625,7 @@ const AgentuityBundler: BunPlugin = {
|
|
|
614
625
|
version: sub.get('version')!,
|
|
615
626
|
name: sub.get('name')!,
|
|
616
627
|
description: sub.get('description') ?? '<no description provided>',
|
|
628
|
+
projectId,
|
|
617
629
|
};
|
|
618
630
|
|
|
619
631
|
// Add evals for subagents if any
|
|
@@ -623,7 +635,17 @@ const AgentuityBundler: BunPlugin = {
|
|
|
623
635
|
`[plugin] Found evals string for subagent ${subagentData.name}, parsing...`
|
|
624
636
|
);
|
|
625
637
|
try {
|
|
626
|
-
|
|
638
|
+
const parsedSubEvals = JSON.parse(subEvalsStr) as Array<
|
|
639
|
+
Omit<
|
|
640
|
+
NonNullable<BuildMetadata['agents'][number]['evals']>[number],
|
|
641
|
+
'agentIdentifier' | 'projectId'
|
|
642
|
+
>
|
|
643
|
+
>;
|
|
644
|
+
subagentData.evals = parsedSubEvals.map((evalItem) => ({
|
|
645
|
+
...evalItem,
|
|
646
|
+
agentIdentifier: subagentData.agentId,
|
|
647
|
+
projectId,
|
|
648
|
+
}));
|
|
627
649
|
logger.trace(
|
|
628
650
|
`[plugin] Successfully parsed ${subagentData.evals?.length ?? 0} eval(s) for subagent ${subagentData.name}`
|
|
629
651
|
);
|
|
@@ -3,7 +3,6 @@ import { createSubcommand } from '../../../types';
|
|
|
3
3
|
import * as tui from '../../../tui';
|
|
4
4
|
import { projectDeploymentList } from '@agentuity/server';
|
|
5
5
|
import { resolveProjectId } from './utils';
|
|
6
|
-
import { Table } from 'console-table-printer';
|
|
7
6
|
import { getCommand } from '../../../command-prefix';
|
|
8
7
|
import { ErrorCode } from '../../../errors';
|
|
9
8
|
|
|
@@ -64,28 +63,23 @@ export const listSubcommand = createSubcommand({
|
|
|
64
63
|
return [];
|
|
65
64
|
}
|
|
66
65
|
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
],
|
|
76
|
-
});
|
|
66
|
+
const tableData = deployments.map((d) => ({
|
|
67
|
+
ID: d.id,
|
|
68
|
+
State: d.state || 'unknown',
|
|
69
|
+
Active: d.active ? 'Yes' : '',
|
|
70
|
+
Created: new Date(d.createdAt).toLocaleString(),
|
|
71
|
+
Message: d.message || '',
|
|
72
|
+
Tags: d.tags.join(', '),
|
|
73
|
+
}));
|
|
77
74
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
table.printTable();
|
|
75
|
+
tui.table(tableData, [
|
|
76
|
+
{ name: 'ID', alignment: 'left' },
|
|
77
|
+
{ name: 'State', alignment: 'left' },
|
|
78
|
+
{ name: 'Active', alignment: 'center' },
|
|
79
|
+
{ name: 'Created', alignment: 'left' },
|
|
80
|
+
{ name: 'Message', alignment: 'left' },
|
|
81
|
+
{ name: 'Tags', alignment: 'left' },
|
|
82
|
+
]);
|
|
89
83
|
|
|
90
84
|
return deployments.map((d) => ({
|
|
91
85
|
id: d.id,
|
package/src/cmd/cloud/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createCommand } from '../../types';
|
|
2
2
|
import { deploySubcommand } from './deploy';
|
|
3
3
|
import { resourceSubcommand } from './resource';
|
|
4
|
+
import { sessionCommand } from './session';
|
|
4
5
|
import { sshSubcommand } from './ssh';
|
|
5
6
|
import { scpSubcommand } from './scp';
|
|
6
7
|
import { deploymentCommand } from './deployment';
|
|
@@ -12,6 +13,7 @@ export const command = createCommand({
|
|
|
12
13
|
subcommands: [
|
|
13
14
|
deploySubcommand,
|
|
14
15
|
resourceSubcommand,
|
|
16
|
+
sessionCommand,
|
|
15
17
|
sshSubcommand,
|
|
16
18
|
scpSubcommand,
|
|
17
19
|
deploymentCommand,
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createSubcommand } from '../../../types';
|
|
3
|
+
import * as tui from '../../../tui';
|
|
4
|
+
import { sessionGet } from '@agentuity/server';
|
|
5
|
+
import { getCommand } from '../../../command-prefix';
|
|
6
|
+
import { ErrorCode } from '../../../errors';
|
|
7
|
+
import { getCatalystAPIClient } from '../../../config';
|
|
8
|
+
|
|
9
|
+
const SessionGetResponseSchema = z.object({
|
|
10
|
+
id: z.string().describe('Session ID'),
|
|
11
|
+
created_at: z.string().describe('Creation timestamp'),
|
|
12
|
+
start_time: z.string().describe('Start time'),
|
|
13
|
+
end_time: z.string().nullable().describe('End time'),
|
|
14
|
+
duration: z.number().nullable().describe('Duration in nanoseconds'),
|
|
15
|
+
org_id: z.string().describe('Organization ID'),
|
|
16
|
+
project_id: z.string().describe('Project ID'),
|
|
17
|
+
deployment_id: z.string().describe('Deployment ID'),
|
|
18
|
+
agent_ids: z.array(z.string()).describe('Agent IDs'),
|
|
19
|
+
trigger: z.string().describe('Trigger type'),
|
|
20
|
+
env: z.string().describe('Environment'),
|
|
21
|
+
devmode: z.boolean().describe('Dev mode'),
|
|
22
|
+
pending: z.boolean().describe('Pending'),
|
|
23
|
+
success: z.boolean().describe('Success'),
|
|
24
|
+
error: z.string().nullable().describe('Error message'),
|
|
25
|
+
method: z.string().describe('HTTP method'),
|
|
26
|
+
url: z.string().describe('Request URL'),
|
|
27
|
+
route_id: z.string().describe('Route ID'),
|
|
28
|
+
thread_id: z.string().describe('Thread ID'),
|
|
29
|
+
agentNames: z.array(z.string()).describe('Agent names'),
|
|
30
|
+
evalRuns: z.array(z.object({
|
|
31
|
+
id: z.string(),
|
|
32
|
+
created_at: z.string(),
|
|
33
|
+
eval_id: z.string(),
|
|
34
|
+
pending: z.boolean(),
|
|
35
|
+
success: z.boolean(),
|
|
36
|
+
error: z.string().nullable(),
|
|
37
|
+
result: z.string().nullable(),
|
|
38
|
+
})).describe('Eval runs'),
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
export const getSubcommand = createSubcommand({
|
|
42
|
+
name: 'get',
|
|
43
|
+
description: 'Get details about a specific session',
|
|
44
|
+
tags: ['read-only', 'fast', 'requires-auth'],
|
|
45
|
+
examples: [`${getCommand('cloud session get')} sess_abc123xyz`],
|
|
46
|
+
requires: { auth: true },
|
|
47
|
+
idempotent: true,
|
|
48
|
+
schema: {
|
|
49
|
+
args: z.object({
|
|
50
|
+
session_id: z.string().describe('Session ID'),
|
|
51
|
+
}),
|
|
52
|
+
response: SessionGetResponseSchema,
|
|
53
|
+
},
|
|
54
|
+
async handler(ctx) {
|
|
55
|
+
const { config, logger, auth, args, options } = ctx;
|
|
56
|
+
const catalystClient = getCatalystAPIClient(config, logger, auth);
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const enriched = await sessionGet(catalystClient, { id: args.session_id });
|
|
60
|
+
const session = enriched.session;
|
|
61
|
+
|
|
62
|
+
const result = {
|
|
63
|
+
id: session.id,
|
|
64
|
+
created_at: session.created_at,
|
|
65
|
+
start_time: session.start_time,
|
|
66
|
+
end_time: session.end_time,
|
|
67
|
+
duration: session.duration,
|
|
68
|
+
org_id: session.org_id,
|
|
69
|
+
project_id: session.project_id,
|
|
70
|
+
deployment_id: session.deployment_id,
|
|
71
|
+
agent_ids: session.agent_ids,
|
|
72
|
+
trigger: session.trigger,
|
|
73
|
+
env: session.env,
|
|
74
|
+
devmode: session.devmode,
|
|
75
|
+
pending: session.pending,
|
|
76
|
+
success: session.success,
|
|
77
|
+
error: session.error,
|
|
78
|
+
method: session.method,
|
|
79
|
+
url: session.url,
|
|
80
|
+
route_id: session.route_id,
|
|
81
|
+
thread_id: session.thread_id,
|
|
82
|
+
agentNames: enriched.agentNames,
|
|
83
|
+
evalRuns: enriched.evalRuns.map(run => ({
|
|
84
|
+
id: run.id,
|
|
85
|
+
eval_id: run.eval_id,
|
|
86
|
+
created_at: run.created_at,
|
|
87
|
+
pending: run.pending,
|
|
88
|
+
success: run.success,
|
|
89
|
+
error: run.error,
|
|
90
|
+
result: run.result,
|
|
91
|
+
})),
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
if (options.json) {
|
|
95
|
+
console.log(JSON.stringify(result, null, 2));
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
tui.banner(`Session ${session.id}`, `Status: ${session.success ? 'Success' : 'Failed'}`);
|
|
100
|
+
|
|
101
|
+
console.log(tui.bold('ID: ') + session.id);
|
|
102
|
+
console.log(tui.bold('Project: ') + session.project_id);
|
|
103
|
+
console.log(tui.bold('Deployment: ') + (session.deployment_id || '-'));
|
|
104
|
+
console.log(tui.bold('Created: ') + new Date(session.created_at).toLocaleString());
|
|
105
|
+
console.log(tui.bold('Start: ') + new Date(session.start_time).toLocaleString());
|
|
106
|
+
if (session.end_time) {
|
|
107
|
+
console.log(tui.bold('End: ') + new Date(session.end_time).toLocaleString());
|
|
108
|
+
}
|
|
109
|
+
if (session.duration) {
|
|
110
|
+
console.log(
|
|
111
|
+
tui.bold('Duration: ') + `${(session.duration / 1_000_000).toFixed(0)}ms`
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
console.log(tui.bold('Method: ') + session.method);
|
|
115
|
+
console.log(tui.bold('URL: ') + tui.link(session.url, session.url));
|
|
116
|
+
console.log(tui.bold('Trigger: ') + session.trigger);
|
|
117
|
+
console.log(tui.bold('Environment: ') + session.env);
|
|
118
|
+
console.log(tui.bold('Dev Mode: ') + (session.devmode ? 'Yes' : 'No'));
|
|
119
|
+
console.log(tui.bold('Success: ') + (session.success ? '✓' : '✗'));
|
|
120
|
+
console.log(tui.bold('Pending: ') + (session.pending ? 'Yes' : 'No'));
|
|
121
|
+
if (session.error) {
|
|
122
|
+
console.log(tui.bold('Error: ') + tui.error(session.error));
|
|
123
|
+
}
|
|
124
|
+
if (enriched.agentNames.length > 0) {
|
|
125
|
+
const agentDisplay = enriched.agentNames.map((name, idx) => {
|
|
126
|
+
const agentId = session.agent_ids[idx];
|
|
127
|
+
return `${name} ${tui.muted(`(${agentId})`)}`;
|
|
128
|
+
}).join(', ');
|
|
129
|
+
console.log(tui.bold('Agents: ') + agentDisplay);
|
|
130
|
+
}
|
|
131
|
+
console.log(tui.bold('Route ID: ') + session.route_id);
|
|
132
|
+
console.log(tui.bold('Thread ID: ') + session.thread_id);
|
|
133
|
+
|
|
134
|
+
if (enriched.evalRuns.length > 0) {
|
|
135
|
+
console.log('');
|
|
136
|
+
console.log(tui.bold('Eval Runs:'));
|
|
137
|
+
const evalTableData = enriched.evalRuns.map((run) => ({
|
|
138
|
+
ID: run.id,
|
|
139
|
+
'Eval ID': run.eval_id,
|
|
140
|
+
Success: run.success ? '✓' : '✗',
|
|
141
|
+
Pending: run.pending ? '⏳' : '✓',
|
|
142
|
+
Error: run.error || 'No',
|
|
143
|
+
Created: new Date(run.created_at).toLocaleString(),
|
|
144
|
+
}));
|
|
145
|
+
|
|
146
|
+
tui.table(evalTableData, [
|
|
147
|
+
{ name: 'ID', alignment: 'left' },
|
|
148
|
+
{ name: 'Eval ID', alignment: 'left' },
|
|
149
|
+
{ name: 'Success', alignment: 'center' },
|
|
150
|
+
{ name: 'Pending', alignment: 'center' },
|
|
151
|
+
{ name: 'Error', alignment: 'left' },
|
|
152
|
+
{ name: 'Created', alignment: 'left' },
|
|
153
|
+
]);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return result;
|
|
157
|
+
} catch (ex) {
|
|
158
|
+
tui.fatal(
|
|
159
|
+
`Failed to get session: ${ex instanceof Error ? ex.message : String(ex)}`,
|
|
160
|
+
ErrorCode.API_ERROR
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createCommand } from '../../../types';
|
|
2
|
+
import { getSubcommand } from './get';
|
|
3
|
+
import { listSubcommand } from './list';
|
|
4
|
+
import { logsSubcommand } from './logs';
|
|
5
|
+
|
|
6
|
+
export const sessionCommand = createCommand({
|
|
7
|
+
name: 'session',
|
|
8
|
+
description: 'Manage sessions',
|
|
9
|
+
tags: ['requires-auth'],
|
|
10
|
+
subcommands: [getSubcommand, listSubcommand, logsSubcommand],
|
|
11
|
+
});
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createSubcommand } from '../../../types';
|
|
3
|
+
import * as tui from '../../../tui';
|
|
4
|
+
import { sessionList } from '@agentuity/server';
|
|
5
|
+
import { getCommand } from '../../../command-prefix';
|
|
6
|
+
import { ErrorCode } from '../../../errors';
|
|
7
|
+
import { getCatalystAPIClient } from '../../../config';
|
|
8
|
+
|
|
9
|
+
const SessionListResponseSchema = z.array(
|
|
10
|
+
z.object({
|
|
11
|
+
id: z.string().describe('Session ID'),
|
|
12
|
+
created_at: z.string().describe('Creation timestamp'),
|
|
13
|
+
success: z.boolean().describe('Whether the session succeeded'),
|
|
14
|
+
duration: z.number().nullable().describe('Duration in nanoseconds'),
|
|
15
|
+
method: z.string().describe('HTTP method'),
|
|
16
|
+
url: z.string().describe('Request URL'),
|
|
17
|
+
trigger: z.string().describe('Trigger type'),
|
|
18
|
+
env: z.string().describe('Environment'),
|
|
19
|
+
})
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
export const listSubcommand = createSubcommand({
|
|
23
|
+
name: 'list',
|
|
24
|
+
description: 'List recent sessions',
|
|
25
|
+
tags: ['read-only', 'fast', 'requires-auth'],
|
|
26
|
+
examples: [
|
|
27
|
+
`${getCommand('cloud session list')} # List 10 most recent sessions`,
|
|
28
|
+
`${getCommand('cloud session list')} --count=25 # List 25 most recent sessions`,
|
|
29
|
+
`${getCommand('cloud session list')} --project-id=proj_* # Filter by project`,
|
|
30
|
+
`${getCommand('cloud session list')} --deployment-id=* # Filter by deployment`,
|
|
31
|
+
`${getCommand('cloud session list')} --success=true # Only successful sessions`,
|
|
32
|
+
`${getCommand('cloud session list')} --devmode=false # Only production sessions`,
|
|
33
|
+
`${getCommand('cloud session list')} --trigger=api # Only API triggered sessions`,
|
|
34
|
+
`${getCommand('cloud session list')} --env=production # Only production environment`,
|
|
35
|
+
],
|
|
36
|
+
aliases: ['ls'],
|
|
37
|
+
requires: { auth: true },
|
|
38
|
+
optional: { project: true },
|
|
39
|
+
idempotent: true,
|
|
40
|
+
pagination: {
|
|
41
|
+
supported: true,
|
|
42
|
+
defaultLimit: 10,
|
|
43
|
+
maxLimit: 100,
|
|
44
|
+
parameters: {
|
|
45
|
+
limit: 'count',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
schema: {
|
|
49
|
+
options: z.object({
|
|
50
|
+
count: z.coerce
|
|
51
|
+
.number()
|
|
52
|
+
.int()
|
|
53
|
+
.min(1)
|
|
54
|
+
.max(100)
|
|
55
|
+
.default(10)
|
|
56
|
+
.describe('Number of sessions to list (1–100)'),
|
|
57
|
+
projectId: z.string().optional().describe('Filter by project ID'),
|
|
58
|
+
deploymentId: z.string().optional().describe('Filter by deployment ID'),
|
|
59
|
+
trigger: z.string().optional().describe('Filter by trigger type (api, cron, webhook)'),
|
|
60
|
+
env: z.string().optional().describe('Filter by environment'),
|
|
61
|
+
threadId: z.string().optional().describe('Filter by thread ID'),
|
|
62
|
+
agentIdentifier: z.string().optional().describe('Filter by agent identifier'),
|
|
63
|
+
devmode: z.coerce.boolean().optional().describe('Filter by dev mode (true/false)'),
|
|
64
|
+
success: z.coerce.boolean().optional().describe('Filter by success status (true/false)'),
|
|
65
|
+
startAfter: z.string().optional().describe('Filter by start time after (ISO 8601)'),
|
|
66
|
+
startBefore: z.string().optional().describe('Filter by start time before (ISO 8601)'),
|
|
67
|
+
}),
|
|
68
|
+
response: SessionListResponseSchema,
|
|
69
|
+
},
|
|
70
|
+
async handler(ctx) {
|
|
71
|
+
const { config, logger, auth, project, opts, options } = ctx;
|
|
72
|
+
const catalystClient = getCatalystAPIClient(config, logger, auth);
|
|
73
|
+
|
|
74
|
+
const projectId = opts.projectId || project?.projectId;
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
const sessions = await sessionList(catalystClient, {
|
|
78
|
+
count: opts.count,
|
|
79
|
+
projectId,
|
|
80
|
+
deploymentId: opts.deploymentId,
|
|
81
|
+
trigger: opts.trigger,
|
|
82
|
+
env: opts.env,
|
|
83
|
+
devmode: opts.devmode,
|
|
84
|
+
success: opts.success,
|
|
85
|
+
threadId: opts.threadId,
|
|
86
|
+
agentIdentifier: opts.agentIdentifier,
|
|
87
|
+
startAfter: opts.startAfter,
|
|
88
|
+
startBefore: opts.startBefore,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const result = sessions.map((s) => ({
|
|
92
|
+
id: s.id,
|
|
93
|
+
created_at: s.created_at,
|
|
94
|
+
success: s.success,
|
|
95
|
+
duration: s.duration,
|
|
96
|
+
method: s.method,
|
|
97
|
+
url: s.url,
|
|
98
|
+
trigger: s.trigger,
|
|
99
|
+
env: s.env,
|
|
100
|
+
}));
|
|
101
|
+
|
|
102
|
+
if (options.json) {
|
|
103
|
+
console.log(JSON.stringify(result, null, 2));
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (sessions.length === 0) {
|
|
108
|
+
tui.info('No sessions found.');
|
|
109
|
+
return [];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const tableData = sessions.map((s) => {
|
|
113
|
+
const urlPath = new URL(s.url).pathname;
|
|
114
|
+
return {
|
|
115
|
+
ID: s.id,
|
|
116
|
+
Created: new Date(s.created_at).toLocaleString(),
|
|
117
|
+
Success: s.success ? '✓' : '✗',
|
|
118
|
+
Duration: s.duration ? `${(s.duration / 1_000_000).toFixed(0)}ms` : '-',
|
|
119
|
+
Method: s.method,
|
|
120
|
+
Path: urlPath.length > 50 ? urlPath.substring(0, 47) + '...' : urlPath,
|
|
121
|
+
Trigger: s.trigger,
|
|
122
|
+
Env: s.env,
|
|
123
|
+
};
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
tui.table(tableData, [
|
|
127
|
+
{ name: 'ID', alignment: 'left' },
|
|
128
|
+
{ name: 'Created', alignment: 'left' },
|
|
129
|
+
{ name: 'Success', alignment: 'center' },
|
|
130
|
+
{ name: 'Duration', alignment: 'right' },
|
|
131
|
+
{ name: 'Method', alignment: 'left' },
|
|
132
|
+
{ name: 'Path', alignment: 'left' },
|
|
133
|
+
{ name: 'Trigger', alignment: 'left' },
|
|
134
|
+
{ name: 'Env', alignment: 'left' },
|
|
135
|
+
]);
|
|
136
|
+
|
|
137
|
+
return result;
|
|
138
|
+
} catch (ex) {
|
|
139
|
+
tui.fatal(
|
|
140
|
+
`Failed to list sessions: ${ex instanceof Error ? ex.message : String(ex)}`,
|
|
141
|
+
ErrorCode.API_ERROR
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
});
|