@agentuity/cli 2.0.7 → 2.0.8
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 +4 -2
- package/dist/cli.js.map +1 -1
- package/dist/cmd/build/vite/route-discovery.d.ts.map +1 -1
- package/dist/cmd/build/vite/route-discovery.js +6 -0
- package/dist/cmd/build/vite/route-discovery.js.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/rm.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/rm.js +9 -3
- package/dist/cmd/cloud/sandbox/fs/rm.js.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/rmdir.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/rmdir.js +9 -3
- package/dist/cmd/cloud/sandbox/fs/rmdir.js.map +1 -1
- package/dist/cmd/coder/archive.d.ts +2 -0
- package/dist/cmd/coder/archive.d.ts.map +1 -0
- package/dist/cmd/coder/archive.js +57 -0
- package/dist/cmd/coder/archive.js.map +1 -0
- package/dist/cmd/coder/create.d.ts +2 -0
- package/dist/cmd/coder/create.d.ts.map +1 -0
- package/dist/cmd/coder/create.js +245 -0
- package/dist/cmd/coder/create.js.map +1 -0
- package/dist/cmd/coder/delete.d.ts +2 -0
- package/dist/cmd/coder/delete.d.ts.map +1 -0
- package/dist/cmd/coder/delete.js +64 -0
- package/dist/cmd/coder/delete.js.map +1 -0
- package/dist/cmd/coder/events.d.ts +2 -0
- package/dist/cmd/coder/events.d.ts.map +1 -0
- package/dist/cmd/coder/events.js +99 -0
- package/dist/cmd/coder/events.js.map +1 -0
- package/dist/cmd/coder/extension-path.d.ts +8 -0
- package/dist/cmd/coder/extension-path.d.ts.map +1 -0
- package/dist/cmd/coder/extension-path.js +59 -0
- package/dist/cmd/coder/extension-path.js.map +1 -0
- package/dist/cmd/coder/get.d.ts +2 -0
- package/dist/cmd/coder/get.d.ts.map +1 -0
- package/dist/cmd/coder/{inspect.js → get.js} +38 -42
- package/dist/cmd/coder/get.js.map +1 -0
- package/dist/cmd/coder/index.d.ts.map +1 -1
- package/dist/cmd/coder/index.js +52 -7
- package/dist/cmd/coder/index.js.map +1 -1
- package/dist/cmd/coder/list.d.ts.map +1 -1
- package/dist/cmd/coder/list.js +26 -42
- package/dist/cmd/coder/list.js.map +1 -1
- package/dist/cmd/coder/loop.d.ts +2 -0
- package/dist/cmd/coder/loop.d.ts.map +1 -0
- package/dist/cmd/coder/loop.js +78 -0
- package/dist/cmd/coder/loop.js.map +1 -0
- package/dist/cmd/coder/participants.d.ts +2 -0
- package/dist/cmd/coder/participants.d.ts.map +1 -0
- package/dist/cmd/coder/participants.js +93 -0
- package/dist/cmd/coder/participants.js.map +1 -0
- package/dist/cmd/coder/replay.d.ts +2 -0
- package/dist/cmd/coder/replay.d.ts.map +1 -0
- package/dist/cmd/coder/replay.js +53 -0
- package/dist/cmd/coder/replay.js.map +1 -0
- package/dist/cmd/coder/resolve-repo.d.ts +27 -0
- package/dist/cmd/coder/resolve-repo.d.ts.map +1 -0
- package/dist/cmd/coder/resolve-repo.js +97 -0
- package/dist/cmd/coder/resolve-repo.js.map +1 -0
- package/dist/cmd/coder/skill/buckets.d.ts +2 -0
- package/dist/cmd/coder/skill/buckets.d.ts.map +1 -0
- package/dist/cmd/coder/skill/buckets.js +174 -0
- package/dist/cmd/coder/skill/buckets.js.map +1 -0
- package/dist/cmd/coder/skill/delete.d.ts +2 -0
- package/dist/cmd/coder/skill/delete.d.ts.map +1 -0
- package/dist/cmd/coder/skill/delete.js +64 -0
- package/dist/cmd/coder/skill/delete.js.map +1 -0
- package/dist/cmd/coder/skill/index.d.ts +2 -0
- package/dist/cmd/coder/skill/index.d.ts.map +1 -0
- package/dist/cmd/coder/skill/index.js +33 -0
- package/dist/cmd/coder/skill/index.js.map +1 -0
- package/dist/cmd/coder/skill/list.d.ts +2 -0
- package/dist/cmd/coder/skill/list.d.ts.map +1 -0
- package/dist/cmd/coder/skill/list.js +93 -0
- package/dist/cmd/coder/skill/list.js.map +1 -0
- package/dist/cmd/coder/skill/save.d.ts +2 -0
- package/dist/cmd/coder/skill/save.d.ts.map +1 -0
- package/dist/cmd/coder/skill/save.js +77 -0
- package/dist/cmd/coder/skill/save.js.map +1 -0
- package/dist/cmd/coder/start.d.ts.map +1 -1
- package/dist/cmd/coder/start.js +87 -131
- package/dist/cmd/coder/start.js.map +1 -1
- package/dist/cmd/coder/tui-init.d.ts.map +1 -1
- package/dist/cmd/coder/tui-init.js +7 -2
- package/dist/cmd/coder/tui-init.js.map +1 -1
- package/dist/cmd/coder/update.d.ts +2 -0
- package/dist/cmd/coder/update.d.ts.map +1 -0
- package/dist/cmd/coder/update.js +126 -0
- package/dist/cmd/coder/update.js.map +1 -0
- package/dist/cmd/coder/users.d.ts +2 -0
- package/dist/cmd/coder/users.d.ts.map +1 -0
- package/dist/cmd/coder/users.js +97 -0
- package/dist/cmd/coder/users.js.map +1 -0
- package/dist/cmd/coder/workspace/create.d.ts +2 -0
- package/dist/cmd/coder/workspace/create.d.ts.map +1 -0
- package/dist/cmd/coder/workspace/create.js +97 -0
- package/dist/cmd/coder/workspace/create.js.map +1 -0
- package/dist/cmd/coder/workspace/delete.d.ts +2 -0
- package/dist/cmd/coder/workspace/delete.d.ts.map +1 -0
- package/dist/cmd/coder/workspace/delete.js +64 -0
- package/dist/cmd/coder/workspace/delete.js.map +1 -0
- package/dist/cmd/coder/workspace/get.d.ts +2 -0
- package/dist/cmd/coder/workspace/get.d.ts.map +1 -0
- package/dist/cmd/coder/workspace/get.js +109 -0
- package/dist/cmd/coder/workspace/get.js.map +1 -0
- package/dist/cmd/coder/workspace/index.d.ts +2 -0
- package/dist/cmd/coder/workspace/index.d.ts.map +1 -0
- package/dist/cmd/coder/workspace/index.js +38 -0
- package/dist/cmd/coder/workspace/index.js.map +1 -0
- package/dist/cmd/coder/workspace/list.d.ts +2 -0
- package/dist/cmd/coder/workspace/list.d.ts.map +1 -0
- package/dist/cmd/coder/workspace/list.js +93 -0
- package/dist/cmd/coder/workspace/list.js.map +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -3
- package/dist/config.js.map +1 -1
- package/dist/types.d.ts +1 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +0 -10
- package/dist/types.js.map +1 -1
- package/package.json +7 -6
- package/src/cli.ts +4 -2
- package/src/cmd/ai/prompt/agent.md +6 -6
- package/src/cmd/build/vite/route-discovery.ts +8 -0
- package/src/cmd/cloud/sandbox/fs/rm.ts +8 -3
- package/src/cmd/cloud/sandbox/fs/rmdir.ts +8 -3
- package/src/cmd/coder/archive.ts +59 -0
- package/src/cmd/coder/create.ts +268 -0
- package/src/cmd/coder/delete.ts +67 -0
- package/src/cmd/coder/events.ts +106 -0
- package/src/cmd/coder/extension-path.ts +71 -0
- package/src/cmd/coder/{inspect.ts → get.ts} +45 -69
- package/src/cmd/coder/index.ts +52 -7
- package/src/cmd/coder/list.ts +29 -89
- package/src/cmd/coder/loop.ts +85 -0
- package/src/cmd/coder/participants.ts +100 -0
- package/src/cmd/coder/replay.ts +58 -0
- package/src/cmd/coder/resolve-repo.ts +119 -0
- package/src/cmd/coder/skill/buckets.ts +191 -0
- package/src/cmd/coder/skill/delete.ts +67 -0
- package/src/cmd/coder/skill/index.ts +35 -0
- package/src/cmd/coder/skill/list.ts +97 -0
- package/src/cmd/coder/skill/save.ts +84 -0
- package/src/cmd/coder/start.ts +101 -174
- package/src/cmd/coder/tui-init.ts +7 -3
- package/src/cmd/coder/update.ts +128 -0
- package/src/cmd/coder/users.ts +101 -0
- package/src/cmd/coder/workspace/create.ts +104 -0
- package/src/cmd/coder/workspace/delete.ts +70 -0
- package/src/cmd/coder/workspace/get.ts +112 -0
- package/src/cmd/coder/workspace/index.ts +38 -0
- package/src/cmd/coder/workspace/list.ts +101 -0
- package/src/config.ts +4 -3
- package/src/types.ts +0 -10
- package/dist/cmd/coder/config/index.d.ts +0 -2
- package/dist/cmd/coder/config/index.d.ts.map +0 -1
- package/dist/cmd/coder/config/index.js +0 -20
- package/dist/cmd/coder/config/index.js.map +0 -1
- package/dist/cmd/coder/config/set.d.ts +0 -2
- package/dist/cmd/coder/config/set.d.ts.map +0 -1
- package/dist/cmd/coder/config/set.js +0 -100
- package/dist/cmd/coder/config/set.js.map +0 -1
- package/dist/cmd/coder/hub-url.d.ts +0 -47
- package/dist/cmd/coder/hub-url.d.ts.map +0 -1
- package/dist/cmd/coder/hub-url.js +0 -148
- package/dist/cmd/coder/hub-url.js.map +0 -1
- package/dist/cmd/coder/inspect.d.ts +0 -2
- package/dist/cmd/coder/inspect.d.ts.map +0 -1
- package/dist/cmd/coder/inspect.js.map +0 -1
- package/dist/coder-config.d.ts +0 -14
- package/dist/coder-config.d.ts.map +0 -1
- package/dist/coder-config.js +0 -119
- package/dist/coder-config.js.map +0 -1
- package/src/cmd/coder/config/index.ts +0 -20
- package/src/cmd/coder/config/set.ts +0 -112
- package/src/cmd/coder/hub-url.ts +0 -205
- package/src/coder-config.ts +0 -141
|
@@ -1,22 +1,20 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import {
|
|
3
|
+
CoderClient,
|
|
4
|
+
CoderSessionArchivedError,
|
|
5
|
+
CoderSessionNotFoundError,
|
|
6
|
+
} from '@agentuity/core/coder';
|
|
7
|
+
import { ValidationOutputError } from '@agentuity/core';
|
|
8
|
+
|
|
2
9
|
import { createSubcommand } from '../../types';
|
|
3
10
|
import * as tui from '../../tui';
|
|
4
11
|
import { getCommand } from '../../command-prefix';
|
|
5
12
|
import { ErrorCode } from '../../errors';
|
|
6
|
-
import {
|
|
7
|
-
clearStoredHubApiKeyOnUnauthorized,
|
|
8
|
-
formatHubUnauthorizedMessage,
|
|
9
|
-
formatMissingHubUrlMessage,
|
|
10
|
-
getHubResponseErrorMessage,
|
|
11
|
-
getHubUrlSetupGuidance,
|
|
12
|
-
hubFetchHeaders,
|
|
13
|
-
isHubUnauthorizedStatus,
|
|
14
|
-
resolveHubApiKey,
|
|
15
|
-
resolveHubUrl,
|
|
16
|
-
} from './hub-url';
|
|
17
13
|
|
|
18
14
|
function formatRelativeTime(isoDate: string): string {
|
|
19
|
-
const
|
|
15
|
+
const parsed = new Date(isoDate).getTime();
|
|
16
|
+
if (Number.isNaN(parsed)) return 'unknown';
|
|
17
|
+
const diffMs = Math.max(0, Date.now() - parsed);
|
|
20
18
|
const seconds = Math.floor(diffMs / 1000);
|
|
21
19
|
if (seconds < 60) return `${seconds}s ago`;
|
|
22
20
|
const minutes = Math.floor(seconds / 60);
|
|
@@ -38,17 +36,19 @@ function formatDuration(ms: number): string {
|
|
|
38
36
|
return `${hours}h ${remainMin}m`;
|
|
39
37
|
}
|
|
40
38
|
|
|
41
|
-
export const
|
|
42
|
-
name: '
|
|
39
|
+
export const getSubcommand = createSubcommand({
|
|
40
|
+
name: 'get',
|
|
41
|
+
aliases: ['show', 'inspect'],
|
|
43
42
|
description: 'Show detailed information about a Coder Hub session',
|
|
44
43
|
tags: ['read-only', 'fast', 'requires-auth'],
|
|
44
|
+
requires: { auth: true, org: true },
|
|
45
45
|
examples: [
|
|
46
46
|
{
|
|
47
|
-
command: getCommand('coder
|
|
48
|
-
description: '
|
|
47
|
+
command: getCommand('coder get codesess_abc123'),
|
|
48
|
+
description: 'Get a session by ID',
|
|
49
49
|
},
|
|
50
50
|
{
|
|
51
|
-
command: getCommand('coder
|
|
51
|
+
command: getCommand('coder get codesess_abc123 --json'),
|
|
52
52
|
description: 'Get session details as JSON',
|
|
53
53
|
},
|
|
54
54
|
],
|
|
@@ -58,20 +58,17 @@ export const inspectSubcommand = createSubcommand({
|
|
|
58
58
|
session_id: z.string().describe('Coder session ID to inspect'),
|
|
59
59
|
}),
|
|
60
60
|
options: z.object({
|
|
61
|
-
|
|
61
|
+
url: z.string().optional().describe('Coder API URL override'),
|
|
62
62
|
}),
|
|
63
63
|
},
|
|
64
64
|
async handler(ctx) {
|
|
65
|
-
const { args, options, opts
|
|
65
|
+
const { args, options, opts } = ctx;
|
|
66
66
|
const sessionId = args.session_id;
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const resolvedHubApiKey = await resolveHubApiKey(config);
|
|
67
|
+
const client = new CoderClient({
|
|
68
|
+
apiKey: ctx.auth.apiKey,
|
|
69
|
+
url: opts?.url,
|
|
70
|
+
orgId: ctx.orgId,
|
|
71
|
+
});
|
|
75
72
|
|
|
76
73
|
let data: {
|
|
77
74
|
sessionId: string;
|
|
@@ -79,18 +76,18 @@ export const inspectSubcommand = createSubcommand({
|
|
|
79
76
|
status: string;
|
|
80
77
|
createdAt: string;
|
|
81
78
|
mode: string;
|
|
82
|
-
context
|
|
79
|
+
context?: {
|
|
83
80
|
branch?: string;
|
|
84
81
|
workingDirectory?: string;
|
|
85
82
|
};
|
|
86
|
-
participants
|
|
83
|
+
participants?: Array<{
|
|
87
84
|
id: string;
|
|
88
85
|
role: string;
|
|
89
86
|
transport: string;
|
|
90
87
|
connectedAt: string;
|
|
91
88
|
idle: boolean;
|
|
92
89
|
}>;
|
|
93
|
-
tasks
|
|
90
|
+
tasks?: Array<{
|
|
94
91
|
taskId: string;
|
|
95
92
|
agent: string;
|
|
96
93
|
status: string;
|
|
@@ -99,7 +96,7 @@ export const inspectSubcommand = createSubcommand({
|
|
|
99
96
|
startedAt: string;
|
|
100
97
|
completedAt?: string;
|
|
101
98
|
}>;
|
|
102
|
-
agentActivity
|
|
99
|
+
agentActivity?: Record<
|
|
103
100
|
string,
|
|
104
101
|
{
|
|
105
102
|
name: string;
|
|
@@ -112,46 +109,23 @@ export const inspectSubcommand = createSubcommand({
|
|
|
112
109
|
};
|
|
113
110
|
|
|
114
111
|
try {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
});
|
|
119
|
-
if (isHubUnauthorizedStatus(resp.status)) {
|
|
120
|
-
const message = await getHubResponseErrorMessage(resp);
|
|
121
|
-
const clearedStoredKey = await clearStoredHubApiKeyOnUnauthorized(
|
|
122
|
-
resp.status,
|
|
123
|
-
resolvedHubApiKey,
|
|
124
|
-
config
|
|
125
|
-
);
|
|
126
|
-
tui.fatal(
|
|
127
|
-
formatHubUnauthorizedMessage(hubUrl, message, { clearedStoredKey }),
|
|
128
|
-
ErrorCode.API_ERROR
|
|
129
|
-
);
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
if (resp.status === 404) {
|
|
112
|
+
data = (await client.getSession(sessionId)) as unknown as typeof data;
|
|
113
|
+
} catch (err) {
|
|
114
|
+
if (err instanceof CoderSessionNotFoundError) {
|
|
133
115
|
tui.fatal(`Session not found: ${sessionId}`, ErrorCode.RESOURCE_NOT_FOUND);
|
|
134
116
|
return;
|
|
135
117
|
}
|
|
136
|
-
if (
|
|
118
|
+
if (err instanceof CoderSessionArchivedError) {
|
|
137
119
|
tui.fatal(`Session has shut down: ${sessionId}`, ErrorCode.RESOURCE_NOT_FOUND);
|
|
138
120
|
return;
|
|
139
121
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
ErrorCode.API_ERROR
|
|
145
|
-
);
|
|
146
|
-
return;
|
|
122
|
+
|
|
123
|
+
if (err instanceof ValidationOutputError) {
|
|
124
|
+
ctx.logger.trace('Validation response URL: %s', err.url ?? 'unknown');
|
|
125
|
+
ctx.logger.trace('Validation issues: %s', JSON.stringify(err.issues, null, 2));
|
|
147
126
|
}
|
|
148
|
-
data = (await resp.json()) as typeof data;
|
|
149
|
-
} catch (err) {
|
|
150
127
|
const msg = err instanceof Error ? err.message : String(err);
|
|
151
|
-
tui.fatal(
|
|
152
|
-
`Could not connect to Coder Hub at ${hubUrl}: ${msg}\n\n${getHubUrlSetupGuidance()}`,
|
|
153
|
-
ErrorCode.NETWORK_ERROR
|
|
154
|
-
);
|
|
128
|
+
tui.fatal(`Failed to inspect Coder session ${sessionId}: ${msg}`, ErrorCode.NETWORK_ERROR);
|
|
155
129
|
return;
|
|
156
130
|
}
|
|
157
131
|
|
|
@@ -164,17 +138,18 @@ export const inspectSubcommand = createSubcommand({
|
|
|
164
138
|
console.log();
|
|
165
139
|
console.log(` Session: ${label} (${data.sessionId})`);
|
|
166
140
|
const parts = [`Status: ${data.status}`, `Mode: ${data.mode}`];
|
|
167
|
-
if (data.context
|
|
141
|
+
if (data.context?.branch) parts.push(`Branch: ${data.context.branch}`);
|
|
168
142
|
console.log(` ${parts.join(' | ')}`);
|
|
169
143
|
console.log(` Created: ${data.createdAt}`);
|
|
170
144
|
|
|
171
145
|
// Participants
|
|
172
146
|
console.log();
|
|
173
147
|
console.log(' Participants:');
|
|
174
|
-
|
|
148
|
+
const participants = data.participants ?? [];
|
|
149
|
+
if (participants.length === 0) {
|
|
175
150
|
console.log(' (none)');
|
|
176
151
|
} else {
|
|
177
|
-
for (const p of
|
|
152
|
+
for (const p of participants) {
|
|
178
153
|
const idle = p.idle ? ' (idle)' : '';
|
|
179
154
|
const connected = p.connectedAt
|
|
180
155
|
? ` connected ${formatRelativeTime(p.connectedAt)}`
|
|
@@ -186,10 +161,11 @@ export const inspectSubcommand = createSubcommand({
|
|
|
186
161
|
}
|
|
187
162
|
|
|
188
163
|
// Tasks
|
|
189
|
-
|
|
164
|
+
const tasks = data.tasks ?? [];
|
|
165
|
+
if (tasks.length > 0) {
|
|
190
166
|
console.log();
|
|
191
167
|
console.log(' Tasks:');
|
|
192
|
-
for (const t of
|
|
168
|
+
for (const t of tasks) {
|
|
193
169
|
const dur = t.duration ? formatDuration(t.duration) : '-';
|
|
194
170
|
const prompt = t.prompt.length > 40 ? t.prompt.slice(0, 37) + '...' : t.prompt;
|
|
195
171
|
console.log(
|
|
@@ -199,7 +175,7 @@ export const inspectSubcommand = createSubcommand({
|
|
|
199
175
|
}
|
|
200
176
|
|
|
201
177
|
// Agent Activity
|
|
202
|
-
const agents = Object.values(data.agentActivity);
|
|
178
|
+
const agents = Object.values(data.agentActivity ?? {});
|
|
203
179
|
if (agents.length > 0) {
|
|
204
180
|
console.log();
|
|
205
181
|
console.log(' Agent Activity:');
|
package/src/cmd/coder/index.ts
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
import { createCommand } from '../../types';
|
|
2
|
-
import { configSubcommand } from './config';
|
|
3
2
|
import { listSubcommand } from './list';
|
|
4
|
-
import {
|
|
3
|
+
import { getSubcommand } from './get';
|
|
5
4
|
import { startSubcommand } from './start';
|
|
5
|
+
import { createCoderSubcommand } from './create';
|
|
6
|
+
import { deleteSubcommand } from './delete';
|
|
7
|
+
import { archiveSubcommand } from './archive';
|
|
8
|
+
import { updateSubcommand } from './update';
|
|
9
|
+
import { usersSubcommand } from './users';
|
|
10
|
+
import { loopSubcommand } from './loop';
|
|
11
|
+
import { replaySubcommand } from './replay';
|
|
12
|
+
import { participantsSubcommand } from './participants';
|
|
13
|
+
import { eventsSubcommand } from './events';
|
|
14
|
+
import { workspaceCommand } from './workspace';
|
|
15
|
+
import { skillCommand } from './skill';
|
|
6
16
|
import { getCommand } from '../../command-prefix';
|
|
7
17
|
|
|
8
18
|
export const command = createCommand({
|
|
@@ -14,19 +24,54 @@ export const command = createCommand({
|
|
|
14
24
|
command: getCommand('coder start'),
|
|
15
25
|
description: 'Start a Pi session connected to the Coder Hub',
|
|
16
26
|
},
|
|
27
|
+
{
|
|
28
|
+
command: getCommand('coder create "Build a REST API"'),
|
|
29
|
+
description: 'Create a new Coder session with a task',
|
|
30
|
+
},
|
|
17
31
|
{
|
|
18
32
|
command: getCommand('coder ls'),
|
|
19
33
|
description: 'List all active Coder Hub sessions',
|
|
20
34
|
},
|
|
21
35
|
{
|
|
22
|
-
command: getCommand('coder
|
|
36
|
+
command: getCommand('coder get <session-id>'),
|
|
23
37
|
description: 'Show detailed session information',
|
|
24
38
|
},
|
|
25
39
|
{
|
|
26
|
-
command: getCommand('coder
|
|
27
|
-
description: '
|
|
40
|
+
command: getCommand('coder users'),
|
|
41
|
+
description: 'List known Coder Hub users',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
command: getCommand('coder loop <session-id>'),
|
|
45
|
+
description: 'Get loop state for a session',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
command: getCommand('coder events <session-id> --limit 100'),
|
|
49
|
+
description: 'Show recent event history for a session',
|
|
28
50
|
},
|
|
51
|
+
{
|
|
52
|
+
command: getCommand('coder workspace list'),
|
|
53
|
+
description: 'List Coder workspaces',
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
command: getCommand('coder skill list'),
|
|
57
|
+
description: 'List saved skills',
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
subcommands: [
|
|
61
|
+
startSubcommand,
|
|
62
|
+
createCoderSubcommand,
|
|
63
|
+
listSubcommand,
|
|
64
|
+
getSubcommand,
|
|
65
|
+
updateSubcommand,
|
|
66
|
+
deleteSubcommand,
|
|
67
|
+
archiveSubcommand,
|
|
68
|
+
usersSubcommand,
|
|
69
|
+
loopSubcommand,
|
|
70
|
+
replaySubcommand,
|
|
71
|
+
participantsSubcommand,
|
|
72
|
+
eventsSubcommand,
|
|
73
|
+
workspaceCommand,
|
|
74
|
+
skillCommand,
|
|
29
75
|
],
|
|
30
|
-
|
|
31
|
-
optional: { auth: true },
|
|
76
|
+
requires: { auth: true, org: true },
|
|
32
77
|
});
|
package/src/cmd/coder/list.ts
CHANGED
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import {
|
|
3
|
+
CoderClient,
|
|
4
|
+
type CoderSessionListItem,
|
|
5
|
+
CoderSessionListItemSchema,
|
|
6
|
+
} from '@agentuity/core/coder';
|
|
7
|
+
import { ValidationOutputError } from '@agentuity/core';
|
|
2
8
|
import { createSubcommand } from '../../types';
|
|
3
9
|
import * as tui from '../../tui';
|
|
4
10
|
import { getCommand } from '../../command-prefix';
|
|
5
11
|
import { ErrorCode } from '../../errors';
|
|
6
|
-
import {
|
|
7
|
-
clearStoredHubApiKeyOnUnauthorized,
|
|
8
|
-
formatHubUnauthorizedMessage,
|
|
9
|
-
formatMissingHubUrlMessage,
|
|
10
|
-
getHubResponseErrorMessage,
|
|
11
|
-
getHubUrlSetupGuidance,
|
|
12
|
-
hubFetchHeaders,
|
|
13
|
-
isHubUnauthorizedStatus,
|
|
14
|
-
resolveHubApiKey,
|
|
15
|
-
resolveHubUrl,
|
|
16
|
-
} from './hub-url';
|
|
17
12
|
|
|
18
13
|
function formatRelativeTime(isoDate: string): string {
|
|
19
|
-
const
|
|
14
|
+
const parsed = new Date(isoDate).getTime();
|
|
15
|
+
if (Number.isNaN(parsed)) return 'unknown';
|
|
16
|
+
const diffMs = Math.max(0, Date.now() - parsed);
|
|
20
17
|
const seconds = Math.floor(diffMs / 1000);
|
|
21
18
|
if (seconds < 60) return `${seconds}s ago`;
|
|
22
19
|
const minutes = Math.floor(seconds / 60);
|
|
@@ -27,20 +24,6 @@ function formatRelativeTime(isoDate: string): string {
|
|
|
27
24
|
return `${days}d ago`;
|
|
28
25
|
}
|
|
29
26
|
|
|
30
|
-
const SessionListResponseSchema = z.array(
|
|
31
|
-
z.object({
|
|
32
|
-
sessionId: z.string().describe('Session ID'),
|
|
33
|
-
label: z.string().describe('Human-readable session label'),
|
|
34
|
-
status: z.string().describe('Session status'),
|
|
35
|
-
mode: z.string().describe('Session mode (sandbox or tui)'),
|
|
36
|
-
createdAt: z.string().describe('Creation timestamp'),
|
|
37
|
-
taskCount: z.number().describe('Number of tasks'),
|
|
38
|
-
subAgentCount: z.number().describe('Number of sub-agents'),
|
|
39
|
-
observerCount: z.number().describe('Number of observers'),
|
|
40
|
-
participantCount: z.number().describe('Total participant count'),
|
|
41
|
-
})
|
|
42
|
-
);
|
|
43
|
-
|
|
44
27
|
export const listSubcommand = createSubcommand({
|
|
45
28
|
name: 'list',
|
|
46
29
|
description: 'List active Coder Hub sessions',
|
|
@@ -57,79 +40,34 @@ export const listSubcommand = createSubcommand({
|
|
|
57
40
|
],
|
|
58
41
|
aliases: ['ls'],
|
|
59
42
|
idempotent: true,
|
|
43
|
+
requires: { auth: true, org: true },
|
|
60
44
|
schema: {
|
|
61
45
|
options: z.object({
|
|
62
|
-
|
|
46
|
+
url: z.string().optional().describe('Coder API URL override'),
|
|
63
47
|
}),
|
|
64
|
-
response:
|
|
48
|
+
response: z.array(CoderSessionListItemSchema),
|
|
65
49
|
},
|
|
66
50
|
async handler(ctx) {
|
|
67
|
-
const { options, opts
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const resolvedHubApiKey = await resolveHubApiKey(config);
|
|
76
|
-
|
|
77
|
-
let data: {
|
|
78
|
-
sessions: {
|
|
79
|
-
websocket: Array<{
|
|
80
|
-
sessionId: string;
|
|
81
|
-
label: string;
|
|
82
|
-
status: string;
|
|
83
|
-
mode: string;
|
|
84
|
-
createdAt: string;
|
|
85
|
-
taskCount: number;
|
|
86
|
-
subAgentCount: number;
|
|
87
|
-
observerCount: number;
|
|
88
|
-
participantCount: number;
|
|
89
|
-
}>;
|
|
90
|
-
sandbox: Array<Record<string, unknown>>;
|
|
91
|
-
};
|
|
92
|
-
total: number;
|
|
93
|
-
};
|
|
51
|
+
const { options, opts } = ctx;
|
|
52
|
+
const client = new CoderClient({
|
|
53
|
+
apiKey: ctx.auth.apiKey,
|
|
54
|
+
url: opts?.url,
|
|
55
|
+
orgId: ctx.orgId,
|
|
56
|
+
});
|
|
94
57
|
|
|
58
|
+
let sessions: CoderSessionListItem[] = [];
|
|
95
59
|
try {
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
signal: AbortSignal.timeout(10_000),
|
|
99
|
-
});
|
|
100
|
-
if (!resp.ok) {
|
|
101
|
-
const message = await getHubResponseErrorMessage(resp);
|
|
102
|
-
if (isHubUnauthorizedStatus(resp.status)) {
|
|
103
|
-
const clearedStoredKey = await clearStoredHubApiKeyOnUnauthorized(
|
|
104
|
-
resp.status,
|
|
105
|
-
resolvedHubApiKey,
|
|
106
|
-
config
|
|
107
|
-
);
|
|
108
|
-
tui.fatal(
|
|
109
|
-
formatHubUnauthorizedMessage(hubUrl, message, { clearedStoredKey }),
|
|
110
|
-
ErrorCode.API_ERROR
|
|
111
|
-
);
|
|
112
|
-
return [];
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
tui.fatal(
|
|
116
|
-
`Hub returned ${resp.status}: ${message}. Is the Coder Hub running at ${hubUrl}?`,
|
|
117
|
-
ErrorCode.API_ERROR
|
|
118
|
-
);
|
|
119
|
-
return [];
|
|
120
|
-
}
|
|
121
|
-
data = (await resp.json()) as typeof data;
|
|
60
|
+
const response = await client.listSessions();
|
|
61
|
+
sessions = response.sessions;
|
|
122
62
|
} catch (err) {
|
|
63
|
+
if (err instanceof ValidationOutputError) {
|
|
64
|
+
ctx.logger.trace('Validation response URL: %s', err.url ?? 'unknown');
|
|
65
|
+
ctx.logger.trace('Validation issues: %s', JSON.stringify(err.issues, null, 2));
|
|
66
|
+
}
|
|
123
67
|
const msg = err instanceof Error ? err.message : String(err);
|
|
124
|
-
tui.fatal(
|
|
125
|
-
`Could not connect to Coder Hub at ${hubUrl}: ${msg}\n\n${getHubUrlSetupGuidance()}`,
|
|
126
|
-
ErrorCode.NETWORK_ERROR
|
|
127
|
-
);
|
|
128
|
-
return [];
|
|
68
|
+
tui.fatal(`Failed to list Coder sessions: ${msg}`, ErrorCode.NETWORK_ERROR);
|
|
129
69
|
}
|
|
130
70
|
|
|
131
|
-
const sessions = data.sessions.websocket;
|
|
132
|
-
|
|
133
71
|
if (options.json) {
|
|
134
72
|
return sessions;
|
|
135
73
|
}
|
|
@@ -140,10 +78,11 @@ export const listSubcommand = createSubcommand({
|
|
|
140
78
|
}
|
|
141
79
|
|
|
142
80
|
const tableData = sessions.map((s) => ({
|
|
143
|
-
'Session ID': s.sessionId
|
|
81
|
+
'Session ID': s.sessionId,
|
|
144
82
|
Label: s.label || '-',
|
|
145
83
|
Status: s.status,
|
|
146
84
|
Mode: s.mode,
|
|
85
|
+
Owner: s.owner?.name ?? s.owner?.userId ?? '-',
|
|
147
86
|
Observers: String(s.observerCount),
|
|
148
87
|
Agents: String(s.subAgentCount),
|
|
149
88
|
Tasks: String(s.taskCount),
|
|
@@ -155,6 +94,7 @@ export const listSubcommand = createSubcommand({
|
|
|
155
94
|
{ name: 'Label', alignment: 'left' },
|
|
156
95
|
{ name: 'Status', alignment: 'center' },
|
|
157
96
|
{ name: 'Mode', alignment: 'center' },
|
|
97
|
+
{ name: 'Owner', alignment: 'left' },
|
|
158
98
|
{ name: 'Observers', alignment: 'right' },
|
|
159
99
|
{ name: 'Agents', alignment: 'right' },
|
|
160
100
|
{ name: 'Tasks', alignment: 'right' },
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { CoderClient } from '@agentuity/core/coder';
|
|
3
|
+
import { ValidationOutputError } from '@agentuity/core';
|
|
4
|
+
import { createSubcommand } from '../../types';
|
|
5
|
+
import * as tui from '../../tui';
|
|
6
|
+
import { getCommand } from '../../command-prefix';
|
|
7
|
+
import { ErrorCode } from '../../errors';
|
|
8
|
+
|
|
9
|
+
export const loopSubcommand = createSubcommand({
|
|
10
|
+
name: 'loop',
|
|
11
|
+
description: 'Get loop-mode state for a Coder Hub session',
|
|
12
|
+
tags: ['read-only', 'fast', 'requires-auth'],
|
|
13
|
+
idempotent: true,
|
|
14
|
+
requires: { auth: true, org: true },
|
|
15
|
+
examples: [
|
|
16
|
+
{
|
|
17
|
+
command: getCommand('coder loop codesess_abc123'),
|
|
18
|
+
description: 'Show loop state for a session',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
command: getCommand('coder loop codesess_abc123 --json'),
|
|
22
|
+
description: 'Get loop state as JSON',
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
schema: {
|
|
26
|
+
args: z.object({
|
|
27
|
+
sessionId: z.string().describe('Session ID to inspect loop state for'),
|
|
28
|
+
}),
|
|
29
|
+
options: z.object({
|
|
30
|
+
url: z.string().optional().describe('Coder API URL override'),
|
|
31
|
+
}),
|
|
32
|
+
},
|
|
33
|
+
async handler(ctx) {
|
|
34
|
+
const { args, opts, options } = ctx;
|
|
35
|
+
const client = new CoderClient({
|
|
36
|
+
apiKey: ctx.auth.apiKey,
|
|
37
|
+
url: opts?.url,
|
|
38
|
+
orgId: ctx.orgId,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
const state = await client.getLoopState(args.sessionId);
|
|
43
|
+
|
|
44
|
+
if (options.json) {
|
|
45
|
+
return state;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const rows: Array<{ Field: string; Value: string }> = [
|
|
49
|
+
{ Field: 'Session ID', Value: state.sessionId },
|
|
50
|
+
{ Field: 'Workflow Mode', Value: state.workflowMode },
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
if (!state.loop) {
|
|
54
|
+
rows.push({ Field: 'Loop Status', Value: 'not active' });
|
|
55
|
+
} else {
|
|
56
|
+
rows.push({ Field: 'Loop Status', Value: state.loop.status });
|
|
57
|
+
rows.push({ Field: 'Iteration', Value: String(state.loop.iteration) });
|
|
58
|
+
rows.push({
|
|
59
|
+
Field: 'Max Iterations',
|
|
60
|
+
Value: String(state.loop.maxIterations ?? '-'),
|
|
61
|
+
});
|
|
62
|
+
rows.push({ Field: 'Goal', Value: state.loop.goal ?? '-' });
|
|
63
|
+
rows.push({ Field: 'Summary', Value: state.loop.summary ?? '-' });
|
|
64
|
+
rows.push({ Field: 'Next Action', Value: state.loop.nextAction ?? '-' });
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
tui.table(rows, [
|
|
68
|
+
{ name: 'Field', alignment: 'left' },
|
|
69
|
+
{ name: 'Value', alignment: 'left' },
|
|
70
|
+
]);
|
|
71
|
+
|
|
72
|
+
return state;
|
|
73
|
+
} catch (err) {
|
|
74
|
+
if (err instanceof ValidationOutputError) {
|
|
75
|
+
ctx.logger.trace('Validation response URL: %s', err.url ?? 'unknown');
|
|
76
|
+
ctx.logger.trace('Validation issues: %s', JSON.stringify(err.issues, null, 2));
|
|
77
|
+
}
|
|
78
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
79
|
+
tui.fatal(
|
|
80
|
+
`Failed to get loop state for ${args.sessionId}: ${msg}`,
|
|
81
|
+
ErrorCode.NETWORK_ERROR
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { CoderClient } from '@agentuity/core/coder';
|
|
3
|
+
import { ValidationOutputError } from '@agentuity/core';
|
|
4
|
+
import { createSubcommand } from '../../types';
|
|
5
|
+
import * as tui from '../../tui';
|
|
6
|
+
import { getCommand } from '../../command-prefix';
|
|
7
|
+
import { ErrorCode } from '../../errors';
|
|
8
|
+
|
|
9
|
+
function formatRelativeTime(isoDate: string): string {
|
|
10
|
+
const parsed = new Date(isoDate).getTime();
|
|
11
|
+
if (Number.isNaN(parsed)) return 'unknown';
|
|
12
|
+
const diffMs = Math.max(0, Date.now() - parsed);
|
|
13
|
+
const seconds = Math.floor(diffMs / 1000);
|
|
14
|
+
if (seconds < 60) return `${seconds}s ago`;
|
|
15
|
+
const minutes = Math.floor(seconds / 60);
|
|
16
|
+
if (minutes < 60) return `${minutes}m ago`;
|
|
17
|
+
const hours = Math.floor(minutes / 60);
|
|
18
|
+
if (hours < 24) return `${hours}h ago`;
|
|
19
|
+
const days = Math.floor(hours / 24);
|
|
20
|
+
return `${days}d ago`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const participantsSubcommand = createSubcommand({
|
|
24
|
+
name: 'participants',
|
|
25
|
+
aliases: ['participant', 'members'],
|
|
26
|
+
description: 'List participants for a Coder Hub session',
|
|
27
|
+
tags: ['read-only', 'fast', 'requires-auth'],
|
|
28
|
+
idempotent: true,
|
|
29
|
+
requires: { auth: true, org: true },
|
|
30
|
+
examples: [
|
|
31
|
+
{
|
|
32
|
+
command: getCommand('coder participants codesess_abc123'),
|
|
33
|
+
description: 'List session participants',
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
command: getCommand('coder participants codesess_abc123 --json'),
|
|
37
|
+
description: 'Get session participants as JSON',
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
schema: {
|
|
41
|
+
args: z.object({
|
|
42
|
+
sessionId: z.string().describe('Session ID to list participants for'),
|
|
43
|
+
}),
|
|
44
|
+
options: z.object({
|
|
45
|
+
url: z.string().optional().describe('Coder API URL override'),
|
|
46
|
+
}),
|
|
47
|
+
},
|
|
48
|
+
async handler(ctx) {
|
|
49
|
+
const { args, opts, options } = ctx;
|
|
50
|
+
const client = new CoderClient({
|
|
51
|
+
apiKey: ctx.auth.apiKey,
|
|
52
|
+
url: opts?.url,
|
|
53
|
+
orgId: ctx.orgId,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
const data = await client.listParticipants(args.sessionId);
|
|
58
|
+
|
|
59
|
+
if (options.json) {
|
|
60
|
+
return data;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (data.participants.length === 0) {
|
|
64
|
+
tui.info(`No participants found for session ${args.sessionId}.`);
|
|
65
|
+
return data;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
tui.table(
|
|
69
|
+
data.participants.map((p) => ({
|
|
70
|
+
ID: p.id,
|
|
71
|
+
Role: p.role,
|
|
72
|
+
'Agent Role': p.agentRole ?? '-',
|
|
73
|
+
Transport: p.transport ?? '-',
|
|
74
|
+
Connected: p.connectedAt ? formatRelativeTime(p.connectedAt) : '-',
|
|
75
|
+
'Last Activity': p.lastActivityAt ? formatRelativeTime(p.lastActivityAt) : '-',
|
|
76
|
+
})),
|
|
77
|
+
[
|
|
78
|
+
{ name: 'ID', alignment: 'left' },
|
|
79
|
+
{ name: 'Role', alignment: 'left' },
|
|
80
|
+
{ name: 'Agent Role', alignment: 'left' },
|
|
81
|
+
{ name: 'Transport', alignment: 'center' },
|
|
82
|
+
{ name: 'Connected', alignment: 'right' },
|
|
83
|
+
{ name: 'Last Activity', alignment: 'right' },
|
|
84
|
+
]
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
return data;
|
|
88
|
+
} catch (err) {
|
|
89
|
+
if (err instanceof ValidationOutputError) {
|
|
90
|
+
ctx.logger.trace('Validation response URL: %s', err.url ?? 'unknown');
|
|
91
|
+
ctx.logger.trace('Validation issues: %s', JSON.stringify(err.issues, null, 2));
|
|
92
|
+
}
|
|
93
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
94
|
+
tui.fatal(
|
|
95
|
+
`Failed to list participants for session ${args.sessionId}: ${msg}`,
|
|
96
|
+
ErrorCode.NETWORK_ERROR
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
});
|