@agentuity/cli 0.1.23 → 0.1.24
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 +36 -5
- package/dist/cli.js.map +1 -1
- package/dist/cmd/ai/cadence/index.d.ts +3 -0
- package/dist/cmd/ai/cadence/index.d.ts.map +1 -0
- package/dist/cmd/ai/cadence/index.js +29 -0
- package/dist/cmd/ai/cadence/index.js.map +1 -0
- package/dist/cmd/ai/cadence/list.d.ts +3 -0
- package/dist/cmd/ai/cadence/list.d.ts.map +1 -0
- package/dist/cmd/ai/cadence/list.js +167 -0
- package/dist/cmd/ai/cadence/list.js.map +1 -0
- package/dist/cmd/ai/cadence/pause.d.ts +3 -0
- package/dist/cmd/ai/cadence/pause.d.ts.map +1 -0
- package/dist/cmd/ai/cadence/pause.js +103 -0
- package/dist/cmd/ai/cadence/pause.js.map +1 -0
- package/dist/cmd/ai/cadence/resume.d.ts +3 -0
- package/dist/cmd/ai/cadence/resume.d.ts.map +1 -0
- package/dist/cmd/ai/cadence/resume.js +106 -0
- package/dist/cmd/ai/cadence/resume.js.map +1 -0
- package/dist/cmd/ai/cadence/status.d.ts +3 -0
- package/dist/cmd/ai/cadence/status.d.ts.map +1 -0
- package/dist/cmd/ai/cadence/status.js +129 -0
- package/dist/cmd/ai/cadence/status.js.map +1 -0
- package/dist/cmd/ai/cadence/stop.d.ts +3 -0
- package/dist/cmd/ai/cadence/stop.d.ts.map +1 -0
- package/dist/cmd/ai/cadence/stop.js +107 -0
- package/dist/cmd/ai/cadence/stop.js.map +1 -0
- package/dist/cmd/ai/cadence/util.d.ts +44 -0
- package/dist/cmd/ai/cadence/util.d.ts.map +1 -0
- package/dist/cmd/ai/cadence/util.js +52 -0
- package/dist/cmd/ai/cadence/util.js.map +1 -0
- package/dist/cmd/ai/index.d.ts.map +1 -1
- package/dist/cmd/ai/index.js +2 -1
- package/dist/cmd/ai/index.js.map +1 -1
- package/dist/cmd/auth/machine/setup.js +1 -1
- package/dist/cmd/auth/machine/setup.js.map +1 -1
- package/dist/cmd/auth/ssh/add.js +1 -1
- package/dist/cmd/auth/ssh/add.js.map +1 -1
- package/dist/cmd/cloud/eval/get.d.ts +2 -0
- package/dist/cmd/cloud/eval/get.d.ts.map +1 -0
- package/dist/cmd/cloud/eval/get.js +79 -0
- package/dist/cmd/cloud/eval/get.js.map +1 -0
- package/dist/cmd/cloud/eval/index.d.ts +2 -0
- package/dist/cmd/cloud/eval/index.d.ts.map +1 -0
- package/dist/cmd/cloud/eval/index.js +15 -0
- package/dist/cmd/cloud/eval/index.js.map +1 -0
- package/dist/cmd/cloud/eval/list.d.ts +2 -0
- package/dist/cmd/cloud/eval/list.d.ts.map +1 -0
- package/dist/cmd/cloud/eval/list.js +119 -0
- package/dist/cmd/cloud/eval/list.js.map +1 -0
- package/dist/cmd/cloud/eval-run/get.d.ts +2 -0
- package/dist/cmd/cloud/eval-run/get.d.ts.map +1 -0
- package/dist/cmd/cloud/eval-run/get.js +106 -0
- package/dist/cmd/cloud/eval-run/get.js.map +1 -0
- package/dist/cmd/cloud/eval-run/index.d.ts +2 -0
- package/dist/cmd/cloud/eval-run/index.d.ts.map +1 -0
- package/dist/cmd/cloud/eval-run/index.js +15 -0
- package/dist/cmd/cloud/eval-run/index.js.map +1 -0
- package/dist/cmd/cloud/eval-run/list.d.ts +2 -0
- package/dist/cmd/cloud/eval-run/list.d.ts.map +1 -0
- package/dist/cmd/cloud/eval-run/list.js +140 -0
- package/dist/cmd/cloud/eval-run/list.js.map +1 -0
- package/dist/cmd/cloud/index.d.ts.map +1 -1
- package/dist/cmd/cloud/index.js +4 -0
- package/dist/cmd/cloud/index.js.map +1 -1
- package/dist/cmd/cloud/machine/list.d.ts.map +1 -1
- package/dist/cmd/cloud/machine/list.js +16 -0
- package/dist/cmd/cloud/machine/list.js.map +1 -1
- package/dist/cmd/cloud/queue/dlq.d.ts.map +1 -1
- package/dist/cmd/cloud/queue/dlq.js +15 -10
- package/dist/cmd/cloud/queue/dlq.js.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/build.d.ts.map +1 -1
- 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 +5 -1
- package/dist/cmd/cloud/sandbox/snapshot/create.js.map +1 -1
- package/dist/cmd/cloud/storage/upload.js +1 -1
- package/dist/cmd/cloud/storage/upload.js.map +1 -1
- package/dist/cmd/cloud/vector/stats.d.ts.map +1 -1
- package/dist/cmd/cloud/vector/stats.js +3 -1
- package/dist/cmd/cloud/vector/stats.js.map +1 -1
- package/dist/cmd/cloud/vector/upsert.js +1 -1
- package/dist/cmd/cloud/vector/upsert.js.map +1 -1
- package/dist/cmd/project/delete.d.ts.map +1 -1
- package/dist/cmd/project/delete.js +46 -10
- package/dist/cmd/project/delete.js.map +1 -1
- package/dist/cmd/setup/index.d.ts.map +1 -1
- package/dist/cmd/setup/index.js +4 -1
- package/dist/cmd/setup/index.js.map +1 -1
- package/dist/env-util.d.ts.map +1 -1
- package/dist/env-util.js +4 -1
- package/dist/env-util.js.map +1 -1
- package/dist/schema-parser.d.ts +17 -1
- package/dist/schema-parser.d.ts.map +1 -1
- package/dist/schema-parser.js +131 -2
- package/dist/schema-parser.js.map +1 -1
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +4 -0
- package/dist/tui.js.map +1 -1
- package/package.json +6 -6
- package/src/cli.ts +40 -5
- package/src/cmd/ai/cadence/index.ts +30 -0
- package/src/cmd/ai/cadence/list.ts +183 -0
- package/src/cmd/ai/cadence/pause.ts +119 -0
- package/src/cmd/ai/cadence/resume.ts +124 -0
- package/src/cmd/ai/cadence/status.ts +141 -0
- package/src/cmd/ai/cadence/stop.ts +124 -0
- package/src/cmd/ai/cadence/util.ts +86 -0
- package/src/cmd/ai/index.ts +2 -1
- package/src/cmd/auth/machine/setup.ts +1 -1
- package/src/cmd/auth/ssh/add.ts +1 -1
- package/src/cmd/cloud/eval/get.ts +85 -0
- package/src/cmd/cloud/eval/index.ts +15 -0
- package/src/cmd/cloud/eval/list.ts +129 -0
- package/src/cmd/cloud/eval-run/get.ts +113 -0
- package/src/cmd/cloud/eval-run/index.ts +15 -0
- package/src/cmd/cloud/eval-run/list.ts +150 -0
- package/src/cmd/cloud/index.ts +4 -0
- package/src/cmd/cloud/machine/list.ts +16 -0
- package/src/cmd/cloud/queue/dlq.ts +15 -10
- package/src/cmd/cloud/sandbox/snapshot/build.ts +5 -1
- package/src/cmd/cloud/sandbox/snapshot/create.ts +5 -1
- package/src/cmd/cloud/storage/upload.ts +1 -1
- package/src/cmd/cloud/vector/stats.ts +3 -1
- package/src/cmd/cloud/vector/upsert.ts +1 -1
- package/src/cmd/project/delete.ts +55 -10
- package/src/cmd/setup/index.ts +4 -1
- package/src/env-util.ts +4 -1
- package/src/schema-parser.ts +150 -2
- package/src/tui.ts +5 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createCommand } from '../../../types';
|
|
3
|
+
import * as tui from '../../../tui';
|
|
4
|
+
import {
|
|
5
|
+
createCadenceKVAdapter,
|
|
6
|
+
CADENCE_NAMESPACE,
|
|
7
|
+
getLoopStateKey,
|
|
8
|
+
parseLoopState,
|
|
9
|
+
type CadenceLoop,
|
|
10
|
+
} from './util';
|
|
11
|
+
import { getCommand } from '../../../command-prefix';
|
|
12
|
+
|
|
13
|
+
const CadencePauseResponseSchema = z.object({
|
|
14
|
+
success: z.boolean(),
|
|
15
|
+
loopId: z.string(),
|
|
16
|
+
previousStatus: z.string().optional(),
|
|
17
|
+
newStatus: z.string().optional(),
|
|
18
|
+
message: z.string(),
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export const pauseSubcommand = createCommand({
|
|
22
|
+
name: 'pause',
|
|
23
|
+
description: 'Pause a running Cadence loop',
|
|
24
|
+
tags: ['mutating', 'updates-resource', 'fast', 'requires-auth'],
|
|
25
|
+
requires: { auth: true },
|
|
26
|
+
examples: [{ command: getCommand('cadence pause lp_auth_impl'), description: 'Pause a loop' }],
|
|
27
|
+
schema: {
|
|
28
|
+
args: z.object({
|
|
29
|
+
loopId: z.string().min(1).describe('The loop ID to pause'),
|
|
30
|
+
}),
|
|
31
|
+
response: CadencePauseResponseSchema,
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
async handler(ctx) {
|
|
35
|
+
const { args, options } = ctx;
|
|
36
|
+
const kv = await createCadenceKVAdapter(ctx);
|
|
37
|
+
|
|
38
|
+
const key = getLoopStateKey(args.loopId);
|
|
39
|
+
const result = await kv.get(CADENCE_NAMESPACE, key);
|
|
40
|
+
|
|
41
|
+
if (!result.exists || !result.data) {
|
|
42
|
+
if (!options.json) {
|
|
43
|
+
tui.error(`Loop ${args.loopId} not found.`);
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
success: false,
|
|
47
|
+
loopId: args.loopId,
|
|
48
|
+
message: 'Loop not found',
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
let data: unknown;
|
|
53
|
+
if (typeof result.data === 'string') {
|
|
54
|
+
try {
|
|
55
|
+
data = JSON.parse(result.data);
|
|
56
|
+
} catch {
|
|
57
|
+
if (!options.json) {
|
|
58
|
+
tui.error(`Failed to parse loop state for ${args.loopId}`);
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
success: false,
|
|
62
|
+
loopId: args.loopId,
|
|
63
|
+
message: 'Failed to parse loop state',
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
} else {
|
|
67
|
+
data = result.data;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const loop = parseLoopState(data);
|
|
71
|
+
if (!loop) {
|
|
72
|
+
if (!options.json) {
|
|
73
|
+
tui.error(`Invalid loop state for ${args.loopId}`);
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
success: false,
|
|
77
|
+
loopId: args.loopId,
|
|
78
|
+
message: 'Invalid loop state',
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (loop.status !== 'running') {
|
|
83
|
+
if (!options.json) {
|
|
84
|
+
tui.warning(`Loop ${args.loopId} is not running (status: ${loop.status})`);
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
success: false,
|
|
88
|
+
loopId: args.loopId,
|
|
89
|
+
previousStatus: loop.status,
|
|
90
|
+
message: `Cannot pause loop with status: ${loop.status}`,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Update status to paused
|
|
95
|
+
const updatedLoop: CadenceLoop = {
|
|
96
|
+
...loop,
|
|
97
|
+
status: 'paused',
|
|
98
|
+
updatedAt: new Date().toISOString(),
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
await kv.set(CADENCE_NAMESPACE, key, JSON.stringify(updatedLoop), {
|
|
102
|
+
contentType: 'application/json',
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
if (!options.json) {
|
|
106
|
+
tui.success(`Paused loop ${args.loopId}`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return {
|
|
110
|
+
success: true,
|
|
111
|
+
loopId: args.loopId,
|
|
112
|
+
previousStatus: 'running',
|
|
113
|
+
newStatus: 'paused',
|
|
114
|
+
message: 'Loop paused successfully',
|
|
115
|
+
};
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
export default pauseSubcommand;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createCommand } from '../../../types';
|
|
3
|
+
import * as tui from '../../../tui';
|
|
4
|
+
import {
|
|
5
|
+
createCadenceKVAdapter,
|
|
6
|
+
CADENCE_NAMESPACE,
|
|
7
|
+
getLoopStateKey,
|
|
8
|
+
parseLoopState,
|
|
9
|
+
type CadenceLoop,
|
|
10
|
+
} from './util';
|
|
11
|
+
import { getCommand } from '../../../command-prefix';
|
|
12
|
+
|
|
13
|
+
const CadenceResumeResponseSchema = z.object({
|
|
14
|
+
success: z.boolean(),
|
|
15
|
+
loopId: z.string(),
|
|
16
|
+
previousStatus: z.string().optional(),
|
|
17
|
+
newStatus: z.string().optional(),
|
|
18
|
+
message: z.string(),
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export const resumeSubcommand = createCommand({
|
|
22
|
+
name: 'resume',
|
|
23
|
+
description: 'Resume a paused Cadence loop',
|
|
24
|
+
tags: ['mutating', 'updates-resource', 'fast', 'requires-auth'],
|
|
25
|
+
requires: { auth: true },
|
|
26
|
+
examples: [
|
|
27
|
+
{ command: getCommand('cadence resume lp_auth_impl'), description: 'Resume a paused loop' },
|
|
28
|
+
],
|
|
29
|
+
schema: {
|
|
30
|
+
args: z.object({
|
|
31
|
+
loopId: z.string().min(1).describe('The loop ID to resume'),
|
|
32
|
+
}),
|
|
33
|
+
response: CadenceResumeResponseSchema,
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
async handler(ctx) {
|
|
37
|
+
const { args, options } = ctx;
|
|
38
|
+
const kv = await createCadenceKVAdapter(ctx);
|
|
39
|
+
|
|
40
|
+
const key = getLoopStateKey(args.loopId);
|
|
41
|
+
const result = await kv.get(CADENCE_NAMESPACE, key);
|
|
42
|
+
|
|
43
|
+
if (!result.exists || !result.data) {
|
|
44
|
+
if (!options.json) {
|
|
45
|
+
tui.error(`Loop ${args.loopId} not found.`);
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
success: false,
|
|
49
|
+
loopId: args.loopId,
|
|
50
|
+
message: 'Loop not found',
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let data: unknown;
|
|
55
|
+
if (typeof result.data === 'string') {
|
|
56
|
+
try {
|
|
57
|
+
data = JSON.parse(result.data);
|
|
58
|
+
} catch {
|
|
59
|
+
if (!options.json) {
|
|
60
|
+
tui.error(`Failed to parse loop state for ${args.loopId}`);
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
success: false,
|
|
64
|
+
loopId: args.loopId,
|
|
65
|
+
message: 'Failed to parse loop state',
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
} else {
|
|
69
|
+
data = result.data;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const loop = parseLoopState(data);
|
|
73
|
+
if (!loop) {
|
|
74
|
+
if (!options.json) {
|
|
75
|
+
tui.error(`Invalid loop state for ${args.loopId}`);
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
success: false,
|
|
79
|
+
loopId: args.loopId,
|
|
80
|
+
message: 'Invalid loop state',
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (loop.status !== 'paused') {
|
|
85
|
+
if (!options.json) {
|
|
86
|
+
tui.warning(`Loop ${args.loopId} is not paused (status: ${loop.status})`);
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
success: false,
|
|
90
|
+
loopId: args.loopId,
|
|
91
|
+
previousStatus: loop.status,
|
|
92
|
+
message: `Cannot resume loop with status: ${loop.status}`,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Update status to running
|
|
97
|
+
const updatedLoop: CadenceLoop = {
|
|
98
|
+
...loop,
|
|
99
|
+
status: 'running',
|
|
100
|
+
updatedAt: new Date().toISOString(),
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
await kv.set(CADENCE_NAMESPACE, key, JSON.stringify(updatedLoop), {
|
|
104
|
+
contentType: 'application/json',
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
if (!options.json) {
|
|
108
|
+
tui.success(`Resumed loop ${args.loopId}`);
|
|
109
|
+
tui.info(
|
|
110
|
+
'Note: The loop will continue when the Open Code session checks for status updates.'
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
success: true,
|
|
116
|
+
loopId: args.loopId,
|
|
117
|
+
previousStatus: 'paused',
|
|
118
|
+
newStatus: 'running',
|
|
119
|
+
message: 'Loop resumed successfully',
|
|
120
|
+
};
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
export default resumeSubcommand;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createCommand } from '../../../types';
|
|
3
|
+
import * as tui from '../../../tui';
|
|
4
|
+
import { createCadenceKVAdapter, CADENCE_NAMESPACE, getLoopStateKey, parseLoopState } from './util';
|
|
5
|
+
import { getCommand } from '../../../command-prefix';
|
|
6
|
+
|
|
7
|
+
const CadenceStatusResponseSchema = z.object({
|
|
8
|
+
found: z.boolean(),
|
|
9
|
+
loop: z
|
|
10
|
+
.object({
|
|
11
|
+
loopId: z.string(),
|
|
12
|
+
status: z.string(),
|
|
13
|
+
iteration: z.number(),
|
|
14
|
+
maxIterations: z.number(),
|
|
15
|
+
prompt: z.string(),
|
|
16
|
+
projectLabel: z.string().optional(),
|
|
17
|
+
sessionId: z.string().optional(),
|
|
18
|
+
createdAt: z.string(),
|
|
19
|
+
updatedAt: z.string(),
|
|
20
|
+
lastError: z.string().optional(),
|
|
21
|
+
})
|
|
22
|
+
.optional(),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export const statusSubcommand = createCommand({
|
|
26
|
+
name: 'status',
|
|
27
|
+
aliases: ['get', 'show'],
|
|
28
|
+
description: 'Get status of a Cadence loop',
|
|
29
|
+
tags: ['read-only', 'fast', 'requires-auth'],
|
|
30
|
+
requires: { auth: true },
|
|
31
|
+
examples: [
|
|
32
|
+
{ command: getCommand('cadence status lp_auth_impl'), description: 'Get loop status' },
|
|
33
|
+
],
|
|
34
|
+
schema: {
|
|
35
|
+
args: z.object({
|
|
36
|
+
loopId: z.string().min(1).describe('The loop ID (e.g., lp_auth_impl)'),
|
|
37
|
+
}),
|
|
38
|
+
response: CadenceStatusResponseSchema,
|
|
39
|
+
},
|
|
40
|
+
idempotent: true,
|
|
41
|
+
|
|
42
|
+
async handler(ctx) {
|
|
43
|
+
const { args, options } = ctx;
|
|
44
|
+
const kv = await createCadenceKVAdapter(ctx);
|
|
45
|
+
|
|
46
|
+
const key = getLoopStateKey(args.loopId);
|
|
47
|
+
const result = await kv.get(CADENCE_NAMESPACE, key);
|
|
48
|
+
|
|
49
|
+
if (!result.exists || !result.data) {
|
|
50
|
+
if (!options.json) {
|
|
51
|
+
tui.warning(`Loop ${args.loopId} not found.`);
|
|
52
|
+
}
|
|
53
|
+
return { found: false };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
let data: unknown;
|
|
57
|
+
if (typeof result.data === 'string') {
|
|
58
|
+
try {
|
|
59
|
+
data = JSON.parse(result.data);
|
|
60
|
+
} catch {
|
|
61
|
+
if (!options.json) {
|
|
62
|
+
tui.error(`Failed to parse loop state for ${args.loopId}`);
|
|
63
|
+
}
|
|
64
|
+
return { found: false };
|
|
65
|
+
}
|
|
66
|
+
} else {
|
|
67
|
+
data = result.data;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const loop = parseLoopState(data);
|
|
71
|
+
if (!loop) {
|
|
72
|
+
if (!options.json) {
|
|
73
|
+
tui.error(`Invalid loop state for ${args.loopId}`);
|
|
74
|
+
}
|
|
75
|
+
return { found: false };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (!options.json) {
|
|
79
|
+
console.log();
|
|
80
|
+
tui.info(`Cadence Loop: ${tui.colorPrimary(loop.loopId)}`);
|
|
81
|
+
console.log();
|
|
82
|
+
|
|
83
|
+
const details = [
|
|
84
|
+
['Status', formatStatus(loop.status)],
|
|
85
|
+
['Iteration', `${loop.iteration} / ${loop.maxIterations}`],
|
|
86
|
+
['Project', loop.projectLabel ?? '-'],
|
|
87
|
+
['Session', loop.sessionId ?? '-'],
|
|
88
|
+
['Created', loop.createdAt],
|
|
89
|
+
['Updated', loop.updatedAt],
|
|
90
|
+
];
|
|
91
|
+
|
|
92
|
+
if (loop.lastError) {
|
|
93
|
+
details.push(['Last Error', tui.colorError(loop.lastError)]);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
for (const [label, value] of details) {
|
|
97
|
+
console.log(` ${tui.muted(label + ':')} ${value}`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
console.log();
|
|
101
|
+
console.log(tui.muted('Task:'));
|
|
102
|
+
console.log(` ${loop.prompt}`);
|
|
103
|
+
console.log();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
found: true,
|
|
108
|
+
loop: {
|
|
109
|
+
loopId: loop.loopId,
|
|
110
|
+
status: loop.status,
|
|
111
|
+
iteration: loop.iteration,
|
|
112
|
+
maxIterations: loop.maxIterations,
|
|
113
|
+
prompt: loop.prompt,
|
|
114
|
+
projectLabel: loop.projectLabel,
|
|
115
|
+
sessionId: loop.sessionId,
|
|
116
|
+
createdAt: loop.createdAt,
|
|
117
|
+
updatedAt: loop.updatedAt,
|
|
118
|
+
lastError: loop.lastError,
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
function formatStatus(status: string): string {
|
|
125
|
+
switch (status) {
|
|
126
|
+
case 'running':
|
|
127
|
+
return tui.colorSuccess('● running');
|
|
128
|
+
case 'paused':
|
|
129
|
+
return tui.colorWarning('⏸ paused');
|
|
130
|
+
case 'completed':
|
|
131
|
+
return tui.colorSuccess('✓ completed');
|
|
132
|
+
case 'failed':
|
|
133
|
+
return tui.colorError('✗ failed');
|
|
134
|
+
case 'cancelled':
|
|
135
|
+
return tui.muted('○ cancelled');
|
|
136
|
+
default:
|
|
137
|
+
return status;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export default statusSubcommand;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createCommand } from '../../../types';
|
|
3
|
+
import * as tui from '../../../tui';
|
|
4
|
+
import {
|
|
5
|
+
createCadenceKVAdapter,
|
|
6
|
+
CADENCE_NAMESPACE,
|
|
7
|
+
getLoopStateKey,
|
|
8
|
+
parseLoopState,
|
|
9
|
+
type CadenceLoop,
|
|
10
|
+
} from './util';
|
|
11
|
+
import { getCommand } from '../../../command-prefix';
|
|
12
|
+
|
|
13
|
+
const CadenceStopResponseSchema = z.object({
|
|
14
|
+
success: z.boolean(),
|
|
15
|
+
loopId: z.string(),
|
|
16
|
+
previousStatus: z.string().optional(),
|
|
17
|
+
newStatus: z.string().optional(),
|
|
18
|
+
message: z.string(),
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export const stopSubcommand = createCommand({
|
|
22
|
+
name: 'stop',
|
|
23
|
+
aliases: ['cancel'],
|
|
24
|
+
description: 'Stop and cancel a Cadence loop',
|
|
25
|
+
tags: ['mutating', 'updates-resource', 'fast', 'requires-auth'],
|
|
26
|
+
requires: { auth: true },
|
|
27
|
+
examples: [
|
|
28
|
+
{ command: getCommand('cadence stop lp_auth_impl'), description: 'Stop and cancel a loop' },
|
|
29
|
+
],
|
|
30
|
+
schema: {
|
|
31
|
+
args: z.object({
|
|
32
|
+
loopId: z.string().min(1).describe('The loop ID to stop'),
|
|
33
|
+
}),
|
|
34
|
+
response: CadenceStopResponseSchema,
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
async handler(ctx) {
|
|
38
|
+
const { args, options } = ctx;
|
|
39
|
+
const kv = await createCadenceKVAdapter(ctx);
|
|
40
|
+
|
|
41
|
+
const key = getLoopStateKey(args.loopId);
|
|
42
|
+
const result = await kv.get(CADENCE_NAMESPACE, key);
|
|
43
|
+
|
|
44
|
+
if (!result.exists || !result.data) {
|
|
45
|
+
if (!options.json) {
|
|
46
|
+
tui.error(`Loop ${args.loopId} not found.`);
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
success: false,
|
|
50
|
+
loopId: args.loopId,
|
|
51
|
+
message: 'Loop not found',
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let data: unknown;
|
|
56
|
+
if (typeof result.data === 'string') {
|
|
57
|
+
try {
|
|
58
|
+
data = JSON.parse(result.data);
|
|
59
|
+
} catch {
|
|
60
|
+
if (!options.json) {
|
|
61
|
+
tui.error(`Failed to parse loop state for ${args.loopId}`);
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
success: false,
|
|
65
|
+
loopId: args.loopId,
|
|
66
|
+
message: 'Failed to parse loop state',
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
} else {
|
|
70
|
+
data = result.data;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const loop = parseLoopState(data);
|
|
74
|
+
if (!loop) {
|
|
75
|
+
if (!options.json) {
|
|
76
|
+
tui.error(`Invalid loop state for ${args.loopId}`);
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
success: false,
|
|
80
|
+
loopId: args.loopId,
|
|
81
|
+
message: 'Invalid loop state',
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const previousStatus = loop.status;
|
|
86
|
+
|
|
87
|
+
if (loop.status === 'completed' || loop.status === 'cancelled') {
|
|
88
|
+
if (!options.json) {
|
|
89
|
+
tui.warning(`Loop ${args.loopId} is already ${loop.status}`);
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
success: false,
|
|
93
|
+
loopId: args.loopId,
|
|
94
|
+
previousStatus,
|
|
95
|
+
message: `Loop is already ${loop.status}`,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Update status to cancelled
|
|
100
|
+
const updatedLoop: CadenceLoop = {
|
|
101
|
+
...loop,
|
|
102
|
+
status: 'cancelled',
|
|
103
|
+
updatedAt: new Date().toISOString(),
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
await kv.set(CADENCE_NAMESPACE, key, JSON.stringify(updatedLoop), {
|
|
107
|
+
contentType: 'application/json',
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
if (!options.json) {
|
|
111
|
+
tui.success(`Stopped loop ${args.loopId}`);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
success: true,
|
|
116
|
+
loopId: args.loopId,
|
|
117
|
+
previousStatus,
|
|
118
|
+
newStatus: 'cancelled',
|
|
119
|
+
message: 'Loop cancelled successfully',
|
|
120
|
+
};
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
export default stopSubcommand;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { KeyValueStorageService, type Logger } from '@agentuity/core';
|
|
2
|
+
import { createServerFetchAdapter, getServiceUrls } from '@agentuity/server';
|
|
3
|
+
import { getDefaultRegion } from '../../../config';
|
|
4
|
+
import type { AuthData, Config } from '../../../types';
|
|
5
|
+
|
|
6
|
+
/** KV namespace for Cadence loop state */
|
|
7
|
+
export const CADENCE_NAMESPACE = 'agentuity-opencode-tasks';
|
|
8
|
+
|
|
9
|
+
/** Prefix for loop state keys */
|
|
10
|
+
export const LOOP_KEY_PREFIX = 'loop:';
|
|
11
|
+
|
|
12
|
+
export interface CadenceLoop {
|
|
13
|
+
loopId: string;
|
|
14
|
+
parentId?: string;
|
|
15
|
+
projectLabel?: string;
|
|
16
|
+
sessionId?: string;
|
|
17
|
+
status: 'running' | 'paused' | 'completed' | 'failed' | 'cancelled';
|
|
18
|
+
iteration: number;
|
|
19
|
+
maxIterations: number;
|
|
20
|
+
prompt: string;
|
|
21
|
+
createdAt: string;
|
|
22
|
+
updatedAt: string;
|
|
23
|
+
lastError?: string;
|
|
24
|
+
sandbox?: {
|
|
25
|
+
mode: 'off' | 'per_iteration' | 'persistent';
|
|
26
|
+
sandboxId?: string;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface CadenceContext {
|
|
31
|
+
logger: Logger;
|
|
32
|
+
config: Config | null;
|
|
33
|
+
auth: AuthData;
|
|
34
|
+
project?: { region: string };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Creates a KV storage service for Cadence operations.
|
|
39
|
+
*/
|
|
40
|
+
export async function createCadenceKVAdapter(ctx: CadenceContext): Promise<KeyValueStorageService> {
|
|
41
|
+
const adapter = createServerFetchAdapter(
|
|
42
|
+
{
|
|
43
|
+
headers: {
|
|
44
|
+
Authorization: `Bearer ${ctx.auth.apiKey}`,
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
ctx.logger
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const region = ctx.project?.region || (await getDefaultRegion(ctx.config?.name, ctx.config));
|
|
51
|
+
const urls = getServiceUrls(region);
|
|
52
|
+
const baseUrl = urls.catalyst;
|
|
53
|
+
return new KeyValueStorageService(baseUrl, adapter);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Gets the state key for a loop.
|
|
58
|
+
*/
|
|
59
|
+
export function getLoopStateKey(loopId: string): string {
|
|
60
|
+
return `${LOOP_KEY_PREFIX}${loopId}:state`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Parses a loop state from KV storage.
|
|
65
|
+
*/
|
|
66
|
+
export function parseLoopState(data: unknown): CadenceLoop | null {
|
|
67
|
+
if (!data || typeof data !== 'object') return null;
|
|
68
|
+
|
|
69
|
+
const loop = data as Record<string, unknown>;
|
|
70
|
+
if (!loop.loopId || !loop.status || !loop.prompt) return null;
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
loopId: String(loop.loopId),
|
|
74
|
+
parentId: loop.parentId ? String(loop.parentId) : undefined,
|
|
75
|
+
projectLabel: loop.projectLabel ? String(loop.projectLabel) : undefined,
|
|
76
|
+
sessionId: loop.sessionId ? String(loop.sessionId) : undefined,
|
|
77
|
+
status: loop.status as CadenceLoop['status'],
|
|
78
|
+
iteration: Number(loop.iteration) || 1,
|
|
79
|
+
maxIterations: Number(loop.maxIterations) || 50,
|
|
80
|
+
prompt: String(loop.prompt),
|
|
81
|
+
createdAt: String(loop.createdAt),
|
|
82
|
+
updatedAt: String(loop.updatedAt),
|
|
83
|
+
lastError: loop.lastError ? String(loop.lastError) : undefined,
|
|
84
|
+
sandbox: loop.sandbox as CadenceLoop['sandbox'],
|
|
85
|
+
};
|
|
86
|
+
}
|
package/src/cmd/ai/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createCommand } from '../../types';
|
|
2
|
+
import cadenceCommand from './cadence';
|
|
2
3
|
import capabilitiesCommand from './capabilities';
|
|
3
4
|
import promptCommand from './prompt';
|
|
4
5
|
import schemaCommand from './schema';
|
|
@@ -29,5 +30,5 @@ export const command = createCommand({
|
|
|
29
30
|
description: 'Generate Agent Skills from CLI schema',
|
|
30
31
|
},
|
|
31
32
|
],
|
|
32
|
-
subcommands: [opencodeCommand, capabilitiesCommand, promptCommand, schemaCommand, skillsCommand],
|
|
33
|
+
subcommands: [opencodeCommand, cadenceCommand, capabilitiesCommand, promptCommand, schemaCommand, skillsCommand],
|
|
33
34
|
});
|
|
@@ -15,7 +15,7 @@ export const setupSubcommand = createSubcommand({
|
|
|
15
15
|
name: 'setup',
|
|
16
16
|
description:
|
|
17
17
|
'Set up machine authentication by uploading a public key for self-hosted infrastructure',
|
|
18
|
-
tags: ['mutating', 'slow', 'requires-auth'],
|
|
18
|
+
tags: ['mutating', 'slow', 'requires-auth', 'uses-stdin'],
|
|
19
19
|
examples: [
|
|
20
20
|
{
|
|
21
21
|
command: `${getCommand('auth machine setup')} --file ./public-key.pem`,
|
package/src/cmd/auth/ssh/add.ts
CHANGED
|
@@ -115,7 +115,7 @@ export const addCommand = createSubcommand({
|
|
|
115
115
|
name: 'add',
|
|
116
116
|
aliases: ['create'],
|
|
117
117
|
description: 'Add an SSH public key to your account (reads from file or stdin)',
|
|
118
|
-
tags: ['mutating', 'creates-resource', 'slow', 'requires-auth'],
|
|
118
|
+
tags: ['mutating', 'creates-resource', 'slow', 'requires-auth', 'uses-stdin'],
|
|
119
119
|
idempotent: false,
|
|
120
120
|
requires: { apiClient: true, auth: true },
|
|
121
121
|
examples: [
|