@agentuity/cli 0.0.55 → 0.0.56
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/cmd/ai/schema/generate.d.ts +3 -0
- package/dist/cmd/ai/schema/generate.d.ts.map +1 -0
- package/dist/cmd/ai/schema/generate.js +50 -0
- package/dist/cmd/ai/schema/generate.js.map +1 -0
- package/dist/cmd/ai/schema/index.d.ts.map +1 -1
- package/dist/cmd/ai/schema/index.js +2 -1
- package/dist/cmd/ai/schema/index.js.map +1 -1
- package/dist/cmd/build/ast.d.ts.map +1 -1
- package/dist/cmd/build/ast.js +101 -81
- package/dist/cmd/build/ast.js.map +1 -1
- package/dist/cmd/build/ast.test.js +135 -370
- package/dist/cmd/build/ast.test.js.map +1 -1
- package/dist/cmd/build/bundler.d.ts.map +1 -1
- package/dist/cmd/build/bundler.js +8 -5
- package/dist/cmd/build/bundler.js.map +1 -1
- package/dist/cmd/build/plugin.d.ts.map +1 -1
- package/dist/cmd/build/plugin.js +9 -1
- package/dist/cmd/build/plugin.js.map +1 -1
- package/dist/cmd/cloud/session/get.d.ts.map +1 -1
- package/dist/cmd/cloud/session/get.js +77 -17
- package/dist/cmd/cloud/session/get.js.map +1 -1
- package/dist/cmd/project/template-flow.d.ts.map +1 -1
- package/dist/cmd/project/template-flow.js +1 -0
- package/dist/cmd/project/template-flow.js.map +1 -1
- package/dist/config.d.ts +27 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +31 -3
- package/dist/config.js.map +1 -1
- package/dist/types.d.ts +24 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +4 -75
- package/dist/types.js.map +1 -1
- package/package.json +3 -3
- package/src/cmd/ai/schema/generate.ts +64 -0
- package/src/cmd/ai/schema/index.ts +2 -1
- package/src/cmd/build/ast.test.ts +157 -549
- package/src/cmd/build/ast.ts +115 -89
- package/src/cmd/build/bundler.ts +8 -5
- package/src/cmd/build/plugin.ts +10 -1
- package/src/cmd/cloud/session/get.ts +91 -19
- package/src/cmd/project/template-flow.ts +1 -0
- package/src/config.ts +44 -5
- package/src/types.ts +5 -84
package/src/cmd/build/ast.ts
CHANGED
|
@@ -790,111 +790,137 @@ export async function parseRoute(
|
|
|
790
790
|
const routes: RouteDefinition = [];
|
|
791
791
|
const routePrefix = filename.includes('src/agents') ? '/agent' : '/api';
|
|
792
792
|
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
if (
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
793
|
+
try {
|
|
794
|
+
for (const body of ast.body) {
|
|
795
|
+
if (body.type === 'ExpressionStatement') {
|
|
796
|
+
const statement = body as ASTExpressionStatement;
|
|
797
|
+
|
|
798
|
+
// Validate that the expression is a call expression (e.g. function call)
|
|
799
|
+
if (statement.expression.type !== 'CallExpression') {
|
|
800
|
+
continue;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
const callee = statement.expression.callee;
|
|
804
|
+
|
|
805
|
+
// Validate that the callee is a member expression (e.g. object.method())
|
|
806
|
+
// This handles cases like 'console.log()' or 'router.get()'
|
|
807
|
+
// direct function calls like 'myFunc()' have type 'Identifier' and will be skipped
|
|
808
|
+
if (callee.type !== 'MemberExpression') {
|
|
809
|
+
continue;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
if (callee.object.type === 'Identifier' && statement.expression.arguments?.length > 0) {
|
|
813
|
+
const identifier = callee.object as ASTNodeIdentifier;
|
|
814
|
+
if (identifier.name === variableName) {
|
|
815
|
+
let method = (callee.property as ASTNodeIdentifier).name;
|
|
816
|
+
let type = 'api';
|
|
817
|
+
const action = statement.expression.arguments[0];
|
|
818
|
+
let suffix = '';
|
|
819
|
+
let config: Record<string, unknown> | undefined;
|
|
820
|
+
switch (method) {
|
|
821
|
+
case 'get':
|
|
822
|
+
case 'put':
|
|
823
|
+
case 'post':
|
|
824
|
+
case 'patch':
|
|
825
|
+
case 'delete': {
|
|
826
|
+
if (action && (action as ASTLiteral).type === 'Literal') {
|
|
827
|
+
suffix = (action as ASTLiteral).value;
|
|
828
|
+
} else {
|
|
829
|
+
throw new Error(
|
|
830
|
+
`unsupported HTTP method ${method} in ${filename} at line ${body.start}`
|
|
831
|
+
);
|
|
832
|
+
}
|
|
814
833
|
break;
|
|
815
834
|
}
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
835
|
+
case 'stream':
|
|
836
|
+
case 'sse':
|
|
837
|
+
case 'websocket': {
|
|
838
|
+
type = method;
|
|
839
|
+
method = 'post';
|
|
840
|
+
const theaction = action as ASTLiteral;
|
|
841
|
+
if (theaction.type === 'Literal') {
|
|
842
|
+
suffix = theaction.value;
|
|
843
|
+
break;
|
|
844
|
+
}
|
|
826
845
|
break;
|
|
827
846
|
}
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
847
|
+
case 'sms': {
|
|
848
|
+
type = method;
|
|
849
|
+
method = 'post';
|
|
850
|
+
const theaction = action as ASTObjectExpression;
|
|
851
|
+
if (theaction.type === 'ObjectExpression') {
|
|
852
|
+
config = {};
|
|
853
|
+
theaction.properties.forEach((p) => {
|
|
854
|
+
if (p.value.type === 'Literal') {
|
|
855
|
+
const literal = p.value as ASTLiteral;
|
|
856
|
+
config![p.key.name] = literal.value;
|
|
857
|
+
}
|
|
858
|
+
});
|
|
859
|
+
const number = theaction.properties.find((p) => p.key.name === 'number');
|
|
860
|
+
if (number && number.value.type === 'Literal') {
|
|
861
|
+
const phoneNumber = number.value as ASTLiteral;
|
|
862
|
+
suffix = hash(phoneNumber.value);
|
|
863
|
+
break;
|
|
840
864
|
}
|
|
841
|
-
});
|
|
842
|
-
const number = theaction.properties.find((p) => p.key.name === 'number');
|
|
843
|
-
if (number && number.value.type === 'Literal') {
|
|
844
|
-
const phoneNumber = number.value as ASTLiteral;
|
|
845
|
-
suffix = hash(phoneNumber.value);
|
|
846
|
-
break;
|
|
847
865
|
}
|
|
866
|
+
break;
|
|
848
867
|
}
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
868
|
+
case 'email': {
|
|
869
|
+
type = method;
|
|
870
|
+
method = 'post';
|
|
871
|
+
const theaction = action as ASTLiteral;
|
|
872
|
+
if (theaction.type === 'Literal') {
|
|
873
|
+
const email = theaction.value;
|
|
874
|
+
suffix = hash(email);
|
|
875
|
+
break;
|
|
876
|
+
}
|
|
858
877
|
break;
|
|
859
878
|
}
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
879
|
+
case 'cron': {
|
|
880
|
+
type = method;
|
|
881
|
+
method = 'post';
|
|
882
|
+
const theaction = action as ASTLiteral;
|
|
883
|
+
if (theaction.type === 'Literal') {
|
|
884
|
+
const number = theaction.value;
|
|
885
|
+
suffix = hash(number);
|
|
886
|
+
break;
|
|
887
|
+
}
|
|
869
888
|
break;
|
|
870
889
|
}
|
|
871
|
-
|
|
890
|
+
default: {
|
|
891
|
+
throw new Error(
|
|
892
|
+
`unsupported router method ${method} in ${filename} at line ${body.start}`
|
|
893
|
+
);
|
|
894
|
+
}
|
|
872
895
|
}
|
|
896
|
+
const thepath = `${routePrefix}/${routeName}/${suffix}`
|
|
897
|
+
.replaceAll(/\/{2,}/g, '/')
|
|
898
|
+
.replaceAll(/\/$/g, '');
|
|
899
|
+
const id = generateRouteId(
|
|
900
|
+
projectId,
|
|
901
|
+
deploymentId,
|
|
902
|
+
type,
|
|
903
|
+
method,
|
|
904
|
+
rel,
|
|
905
|
+
thepath,
|
|
906
|
+
version
|
|
907
|
+
);
|
|
908
|
+
routes.push({
|
|
909
|
+
id,
|
|
910
|
+
method: method as 'get' | 'post' | 'put' | 'delete' | 'patch',
|
|
911
|
+
type: type as 'api' | 'sms' | 'email' | 'cron',
|
|
912
|
+
filename: rel,
|
|
913
|
+
path: thepath,
|
|
914
|
+
version,
|
|
915
|
+
config,
|
|
916
|
+
});
|
|
873
917
|
}
|
|
874
|
-
const thepath = `${routePrefix}/${routeName}/${suffix}`
|
|
875
|
-
.replaceAll(/\/{2,}/g, '/')
|
|
876
|
-
.replaceAll(/\/$/g, '');
|
|
877
|
-
const id = generateRouteId(
|
|
878
|
-
projectId,
|
|
879
|
-
deploymentId,
|
|
880
|
-
type,
|
|
881
|
-
method,
|
|
882
|
-
rel,
|
|
883
|
-
thepath,
|
|
884
|
-
version
|
|
885
|
-
);
|
|
886
|
-
routes.push({
|
|
887
|
-
id,
|
|
888
|
-
method: method as 'get' | 'post' | 'put' | 'delete' | 'patch',
|
|
889
|
-
type: type as 'api' | 'sms' | 'email' | 'cron',
|
|
890
|
-
filename: rel,
|
|
891
|
-
path: thepath,
|
|
892
|
-
version,
|
|
893
|
-
config,
|
|
894
|
-
});
|
|
895
918
|
}
|
|
896
919
|
}
|
|
897
920
|
}
|
|
921
|
+
} catch (error) {
|
|
922
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
923
|
+
throw new Error(`Failed to parse route file ${filename}: ${err.message}`);
|
|
898
924
|
}
|
|
899
925
|
return routes;
|
|
900
926
|
}
|
package/src/cmd/build/bundler.ts
CHANGED
|
@@ -358,13 +358,16 @@ export async function bundle({
|
|
|
358
358
|
.map((s) => s.trim())
|
|
359
359
|
.filter(Boolean);
|
|
360
360
|
}
|
|
361
|
-
|
|
362
|
-
if (branch) {
|
|
363
|
-
const
|
|
364
|
-
if (
|
|
365
|
-
|
|
361
|
+
let branch = process.env.GITHUB_HEAD_REF;
|
|
362
|
+
if (!branch) {
|
|
363
|
+
const branchText = $`git branch --show-current`.nothrow().quiet();
|
|
364
|
+
if (branchText) {
|
|
365
|
+
branch = await branchText.text();
|
|
366
366
|
}
|
|
367
367
|
}
|
|
368
|
+
if (branch) {
|
|
369
|
+
buildmetadata.deployment.git.branch = branch.trim();
|
|
370
|
+
}
|
|
368
371
|
const commit = $`git rev-parse HEAD`.nothrow().quiet();
|
|
369
372
|
if (commit) {
|
|
370
373
|
const sha = await commit.text();
|
package/src/cmd/build/plugin.ts
CHANGED
|
@@ -493,7 +493,6 @@ const AgentuityBundler: BunPlugin = {
|
|
|
493
493
|
projectId,
|
|
494
494
|
deploymentId
|
|
495
495
|
);
|
|
496
|
-
routeDefinitions = [...routeDefinitions, ...definitions];
|
|
497
496
|
|
|
498
497
|
let agentDetail: Record<string, string> = {};
|
|
499
498
|
|
|
@@ -504,6 +503,7 @@ const AgentuityBundler: BunPlugin = {
|
|
|
504
503
|
}
|
|
505
504
|
agentDetail = {
|
|
506
505
|
name,
|
|
506
|
+
id: md.get('id')!,
|
|
507
507
|
path: `.${agent}`,
|
|
508
508
|
filename: md.get('filename')!,
|
|
509
509
|
identifier: md.get('identifier')!,
|
|
@@ -514,8 +514,14 @@ const AgentuityBundler: BunPlugin = {
|
|
|
514
514
|
agentDetail.parent = parentName;
|
|
515
515
|
}
|
|
516
516
|
agentInfo.push(agentDetail);
|
|
517
|
+
for (const def of definitions) {
|
|
518
|
+
def.agentIds = [agentDetail.agentId, agentDetail.id];
|
|
519
|
+
}
|
|
517
520
|
}
|
|
518
521
|
|
|
522
|
+
// do this after handling the agent association (if any)
|
|
523
|
+
routeDefinitions = [...routeDefinitions, ...definitions];
|
|
524
|
+
|
|
519
525
|
let buffer = `await (async() => {
|
|
520
526
|
const { createAgentMiddleware, getRouter, registerAgent } = await import('@agentuity/runtime');
|
|
521
527
|
const router = getRouter()!;
|
|
@@ -657,6 +663,9 @@ if (route !== '/workbench') {
|
|
|
657
663
|
if (!v.has('name')) {
|
|
658
664
|
throw new Error('agent metadata is missing expected name property');
|
|
659
665
|
}
|
|
666
|
+
if (!v.has('agentId')) {
|
|
667
|
+
throw new Error('agent metadata is missing expected agentId property');
|
|
668
|
+
}
|
|
660
669
|
|
|
661
670
|
const parentName = v.get('parent');
|
|
662
671
|
if (parentName) {
|
|
@@ -1,11 +1,29 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { createSubcommand } from '../../../types';
|
|
3
3
|
import * as tui from '../../../tui';
|
|
4
|
-
import { sessionGet } from '@agentuity/server';
|
|
4
|
+
import { sessionGet, type SpanNode } from '@agentuity/server';
|
|
5
5
|
import { getCommand } from '../../../command-prefix';
|
|
6
6
|
import { ErrorCode } from '../../../errors';
|
|
7
7
|
import { getCatalystAPIClient } from '../../../config';
|
|
8
8
|
|
|
9
|
+
const SpanNodeSchema: z.ZodType<SpanNode> = z.lazy(() =>
|
|
10
|
+
z.object({
|
|
11
|
+
id: z.string().describe('Span ID'),
|
|
12
|
+
duration: z.number().describe('Duration in milliseconds'),
|
|
13
|
+
operation: z.string().describe('Operation name'),
|
|
14
|
+
attributes: z.record(z.string(), z.unknown()).describe('Span attributes'),
|
|
15
|
+
children: z.array(SpanNodeSchema).optional().describe('Child spans'),
|
|
16
|
+
})
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
const RouteInfoSchema = z
|
|
20
|
+
.object({
|
|
21
|
+
id: z.string().describe('Route ID'),
|
|
22
|
+
method: z.string().describe('HTTP method'),
|
|
23
|
+
path: z.string().describe('Route path'),
|
|
24
|
+
})
|
|
25
|
+
.nullable();
|
|
26
|
+
|
|
9
27
|
const SessionGetResponseSchema = z.object({
|
|
10
28
|
id: z.string().describe('Session ID'),
|
|
11
29
|
created_at: z.string().describe('Creation timestamp'),
|
|
@@ -26,8 +44,15 @@ const SessionGetResponseSchema = z.object({
|
|
|
26
44
|
url: z.string().describe('Request URL'),
|
|
27
45
|
route_id: z.string().describe('Route ID'),
|
|
28
46
|
thread_id: z.string().describe('Thread ID'),
|
|
29
|
-
|
|
30
|
-
|
|
47
|
+
agents: z
|
|
48
|
+
.array(
|
|
49
|
+
z.object({
|
|
50
|
+
name: z.string(),
|
|
51
|
+
identifier: z.string(),
|
|
52
|
+
})
|
|
53
|
+
)
|
|
54
|
+
.describe('Agents'),
|
|
55
|
+
eval_runs: z
|
|
31
56
|
.array(
|
|
32
57
|
z.object({
|
|
33
58
|
id: z.string(),
|
|
@@ -40,8 +65,41 @@ const SessionGetResponseSchema = z.object({
|
|
|
40
65
|
})
|
|
41
66
|
)
|
|
42
67
|
.describe('Eval runs'),
|
|
68
|
+
timeline: SpanNodeSchema.nullable().optional().describe('Session timeline'),
|
|
69
|
+
route: RouteInfoSchema.optional().describe('Route information'),
|
|
43
70
|
});
|
|
44
71
|
|
|
72
|
+
function formatDuration(ms: number): string {
|
|
73
|
+
if (ms < 1) {
|
|
74
|
+
return `${(ms * 1000).toFixed(0)}µs`;
|
|
75
|
+
}
|
|
76
|
+
if (ms < 1000) {
|
|
77
|
+
return `${ms.toFixed(1)}ms`;
|
|
78
|
+
}
|
|
79
|
+
return `${(ms / 1000).toFixed(2)}s`;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function printTimeline(node: SpanNode, prefix: string, isLast = true): void {
|
|
83
|
+
const connector = isLast ? '└── ' : '├── ';
|
|
84
|
+
const duration = tui.muted(`(${formatDuration(node.duration)})`);
|
|
85
|
+
let extra = '';
|
|
86
|
+
if (node.operation.startsWith('agentuity.')) {
|
|
87
|
+
if ('name' in node.attributes && 'key' in node.attributes) {
|
|
88
|
+
extra = tui.colorSuccess(`${node.attributes.name} ${node.attributes.key}`) + ' ';
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (node.operation.startsWith('HTTP ') && 'http.url' in node.attributes) {
|
|
92
|
+
extra = `${tui.colorSuccess(node.attributes['http.url'] as string)} `;
|
|
93
|
+
}
|
|
94
|
+
console.log(`${prefix}${connector}${node.operation} ${extra}${duration}`);
|
|
95
|
+
|
|
96
|
+
const childPrefix = prefix + (isLast ? ' ' : '│ ');
|
|
97
|
+
const children = node.children ?? [];
|
|
98
|
+
children.forEach((child, index) => {
|
|
99
|
+
printTimeline(child, childPrefix, index === children.length - 1);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
45
103
|
export const getSubcommand = createSubcommand({
|
|
46
104
|
name: 'get',
|
|
47
105
|
description: 'Get details about a specific session',
|
|
@@ -83,8 +141,8 @@ export const getSubcommand = createSubcommand({
|
|
|
83
141
|
url: session.url,
|
|
84
142
|
route_id: session.route_id,
|
|
85
143
|
thread_id: session.thread_id,
|
|
86
|
-
|
|
87
|
-
|
|
144
|
+
agents: enriched.agents,
|
|
145
|
+
eval_runs: enriched.evalRuns.map((run) => ({
|
|
88
146
|
id: run.id,
|
|
89
147
|
eval_id: run.eval_id,
|
|
90
148
|
created_at: run.created_at,
|
|
@@ -93,6 +151,8 @@ export const getSubcommand = createSubcommand({
|
|
|
93
151
|
error: run.error,
|
|
94
152
|
result: run.result,
|
|
95
153
|
})),
|
|
154
|
+
timeline: enriched.timeline,
|
|
155
|
+
route: enriched.route,
|
|
96
156
|
};
|
|
97
157
|
|
|
98
158
|
if (options.json) {
|
|
@@ -100,17 +160,14 @@ export const getSubcommand = createSubcommand({
|
|
|
100
160
|
return result;
|
|
101
161
|
}
|
|
102
162
|
|
|
103
|
-
tui.banner(`Session ${session.id}`, `Status: ${session.success ? 'Success' : 'Failed'}`);
|
|
104
|
-
|
|
105
163
|
console.log(tui.bold('ID: ') + session.id);
|
|
106
164
|
console.log(tui.bold('Project: ') + session.project_id);
|
|
107
165
|
console.log(tui.bold('Deployment: ') + (session.deployment_id || '-'));
|
|
108
|
-
console.log(tui.bold('Created: ') + new Date(session.created_at).toLocaleString());
|
|
109
166
|
console.log(tui.bold('Start: ') + new Date(session.start_time).toLocaleString());
|
|
110
167
|
if (session.end_time) {
|
|
111
168
|
console.log(tui.bold('End: ') + new Date(session.end_time).toLocaleString());
|
|
112
169
|
}
|
|
113
|
-
if (session.duration) {
|
|
170
|
+
if (session.duration && session.end_time) {
|
|
114
171
|
console.log(
|
|
115
172
|
tui.bold('Duration: ') + `${(session.duration / 1_000_000).toFixed(0)}ms`
|
|
116
173
|
);
|
|
@@ -118,23 +175,32 @@ export const getSubcommand = createSubcommand({
|
|
|
118
175
|
console.log(tui.bold('Method: ') + session.method);
|
|
119
176
|
console.log(tui.bold('URL: ') + tui.link(session.url, session.url));
|
|
120
177
|
console.log(tui.bold('Trigger: ') + session.trigger);
|
|
121
|
-
|
|
178
|
+
if (session.env !== 'production') {
|
|
179
|
+
console.log(tui.bold('Environment: ') + session.env);
|
|
180
|
+
}
|
|
122
181
|
console.log(tui.bold('Dev Mode: ') + (session.devmode ? 'Yes' : 'No'));
|
|
123
|
-
console.log(
|
|
182
|
+
console.log(
|
|
183
|
+
tui.bold('Success: ') +
|
|
184
|
+
(session.success ? tui.colorSuccess('✓') : tui.colorError('✗'))
|
|
185
|
+
);
|
|
124
186
|
console.log(tui.bold('Pending: ') + (session.pending ? 'Yes' : 'No'));
|
|
125
187
|
if (session.error) {
|
|
126
188
|
console.log(tui.bold('Error: ') + tui.error(session.error));
|
|
127
189
|
}
|
|
128
|
-
if (enriched.
|
|
129
|
-
const agentDisplay = enriched.
|
|
130
|
-
.map((
|
|
131
|
-
const agentId = session.agent_ids[idx];
|
|
132
|
-
return `${name} ${tui.muted(`(${agentId})`)}`;
|
|
133
|
-
})
|
|
190
|
+
if (enriched.agents.length > 0) {
|
|
191
|
+
const agentDisplay = enriched.agents
|
|
192
|
+
.map((agent) => `${agent.name} ${tui.muted(`(${agent.identifier})`)}`)
|
|
134
193
|
.join(', ');
|
|
135
194
|
console.log(tui.bold('Agents: ') + agentDisplay);
|
|
136
195
|
}
|
|
137
|
-
|
|
196
|
+
if (enriched.route) {
|
|
197
|
+
console.log(
|
|
198
|
+
tui.bold('Route: ') +
|
|
199
|
+
`${enriched.route.method.toUpperCase()} ${enriched.route.path} ${tui.muted(`(${enriched.route.id})`)}`
|
|
200
|
+
);
|
|
201
|
+
} else {
|
|
202
|
+
console.log(tui.bold('Route ID: ') + session.route_id);
|
|
203
|
+
}
|
|
138
204
|
console.log(tui.bold('Thread ID: ') + session.thread_id);
|
|
139
205
|
|
|
140
206
|
if (enriched.evalRuns.length > 0) {
|
|
@@ -143,7 +209,7 @@ export const getSubcommand = createSubcommand({
|
|
|
143
209
|
const evalTableData = enriched.evalRuns.map((run) => ({
|
|
144
210
|
ID: run.id,
|
|
145
211
|
'Eval ID': run.eval_id,
|
|
146
|
-
Success: run.success ? '✓' : '✗',
|
|
212
|
+
Success: run.success ? tui.colorSuccess('✓') : tui.colorError('✗'),
|
|
147
213
|
Pending: run.pending ? '⏳' : '✓',
|
|
148
214
|
Error: run.error || 'No',
|
|
149
215
|
Created: new Date(run.created_at).toLocaleString(),
|
|
@@ -159,6 +225,12 @@ export const getSubcommand = createSubcommand({
|
|
|
159
225
|
]);
|
|
160
226
|
}
|
|
161
227
|
|
|
228
|
+
if (result.timeline) {
|
|
229
|
+
console.log('');
|
|
230
|
+
console.log(tui.bold('Timeline:'));
|
|
231
|
+
printTimeline(result.timeline, '');
|
|
232
|
+
}
|
|
233
|
+
|
|
162
234
|
return result;
|
|
163
235
|
} catch (ex) {
|
|
164
236
|
tui.fatal(
|
package/src/config.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { existsSync } from 'node:fs';
|
|
2
|
+
import { existsSync, mkdirSync } from 'node:fs';
|
|
3
3
|
import type { Logger } from '@agentuity/core';
|
|
4
4
|
import {
|
|
5
5
|
BuildMetadataSchema,
|
|
@@ -486,6 +486,7 @@ class ProjectConfigNotFoundExpection extends Error {
|
|
|
486
486
|
type ProjectConfig = z.infer<typeof ProjectSchema>;
|
|
487
487
|
|
|
488
488
|
function generateJSON5WithComments(
|
|
489
|
+
jsonSchema: string,
|
|
489
490
|
schema: z.ZodObject<z.ZodRawShape>,
|
|
490
491
|
data: Record<string, unknown>
|
|
491
492
|
): string {
|
|
@@ -493,6 +494,8 @@ function generateJSON5WithComments(
|
|
|
493
494
|
const shape = schema.shape;
|
|
494
495
|
const keys = Object.keys(shape);
|
|
495
496
|
|
|
497
|
+
lines.push(` "$schema": "${jsonSchema}",`);
|
|
498
|
+
|
|
496
499
|
for (let i = 0; i < keys.length; i++) {
|
|
497
500
|
const key = keys[i];
|
|
498
501
|
const fieldSchema = shape[key] as z.ZodTypeAny;
|
|
@@ -551,23 +554,59 @@ export async function loadProjectConfig(
|
|
|
551
554
|
return result.data;
|
|
552
555
|
}
|
|
553
556
|
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
+
export const InitialProjectConfigSchema = z.intersection(
|
|
558
|
+
ProjectSchema,
|
|
559
|
+
z.object({
|
|
560
|
+
sdkKey: z.string().describe('the project specific SDK key'),
|
|
561
|
+
$schema: z.string().optional(),
|
|
562
|
+
})
|
|
563
|
+
);
|
|
564
|
+
|
|
565
|
+
type InitialProjectConfig = z.infer<typeof InitialProjectConfigSchema>;
|
|
557
566
|
|
|
558
567
|
export async function createProjectConfig(dir: string, config: InitialProjectConfig) {
|
|
559
568
|
const { sdkKey, ...sanitizedConfig } = config;
|
|
560
569
|
|
|
570
|
+
// generate the project config
|
|
561
571
|
const configPath = join(dir, 'agentuity.json');
|
|
562
|
-
const json5Content = generateJSON5WithComments(
|
|
572
|
+
const json5Content = generateJSON5WithComments(
|
|
573
|
+
'https://agentuity.dev/schema/cli/v1/agentuity.json',
|
|
574
|
+
ProjectSchema,
|
|
575
|
+
sanitizedConfig
|
|
576
|
+
);
|
|
563
577
|
await Bun.write(configPath, json5Content + '\n');
|
|
564
578
|
|
|
579
|
+
// generate the .env file with initial secret
|
|
565
580
|
const envPath = join(dir, '.env');
|
|
566
581
|
const comment =
|
|
567
582
|
'# AGENTUITY_SDK_KEY is a sensitive value and should not be committed to version control.';
|
|
568
583
|
const content = `${comment}\nAGENTUITY_SDK_KEY=${sdkKey}\n`;
|
|
569
584
|
await Bun.write(envPath, content);
|
|
570
585
|
await chmod(envPath, 0o600);
|
|
586
|
+
|
|
587
|
+
// generate the vscode settings
|
|
588
|
+
const vscodeDir = join(dir, '.vscode');
|
|
589
|
+
mkdirSync(vscodeDir);
|
|
590
|
+
|
|
591
|
+
const settings = {
|
|
592
|
+
'files.associations': {
|
|
593
|
+
'agentuity.json': 'jsonc',
|
|
594
|
+
},
|
|
595
|
+
'search.exclude': {
|
|
596
|
+
'**/.git/**': true,
|
|
597
|
+
'**/node_modules/**': true,
|
|
598
|
+
'**/bun.lock': true,
|
|
599
|
+
'**/.agentuity/**': true,
|
|
600
|
+
},
|
|
601
|
+
'json.schemas': [
|
|
602
|
+
{
|
|
603
|
+
fileMatch: ['agentuity.json'],
|
|
604
|
+
url: 'https://agentuity.dev/schema/cli/v1/agentuity.json',
|
|
605
|
+
},
|
|
606
|
+
],
|
|
607
|
+
};
|
|
608
|
+
|
|
609
|
+
await Bun.write(join(vscodeDir, 'settings.json'), JSON.stringify(settings, null, 2));
|
|
571
610
|
}
|
|
572
611
|
|
|
573
612
|
export async function loadBuildMetadata(dir: string): Promise<BuildMetadata> {
|