@agentuity/cli 2.0.11 → 2.0.13
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/cache/resource-region.d.ts.map +1 -1
- package/dist/cache/resource-region.js +48 -25
- package/dist/cache/resource-region.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +15 -8
- package/dist/cli.js.map +1 -1
- package/dist/cmd/build/vite/bun-dev-server.d.ts +20 -0
- package/dist/cmd/build/vite/bun-dev-server.d.ts.map +1 -1
- package/dist/cmd/build/vite/bun-dev-server.js +62 -4
- package/dist/cmd/build/vite/bun-dev-server.js.map +1 -1
- package/dist/cmd/build/vite/index.d.ts +0 -1
- package/dist/cmd/build/vite/index.d.ts.map +1 -1
- package/dist/cmd/build/vite/index.js +0 -1
- package/dist/cmd/build/vite/index.js.map +1 -1
- package/dist/cmd/build/vite/static-renderer.d.ts +17 -0
- package/dist/cmd/build/vite/static-renderer.d.ts.map +1 -1
- package/dist/cmd/build/vite/static-renderer.js +18 -6
- package/dist/cmd/build/vite/static-renderer.js.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server-config.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server-config.js +34 -27
- package/dist/cmd/build/vite/vite-asset-server-config.js.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server.d.ts +9 -0
- package/dist/cmd/build/vite/vite-asset-server.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server.js +5 -1
- package/dist/cmd/build/vite/vite-asset-server.js.map +1 -1
- package/dist/cmd/build/vite/vite-builder.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-builder.js +12 -1
- package/dist/cmd/build/vite/vite-builder.js.map +1 -1
- package/dist/cmd/build/vite/ws-proxy.d.ts +15 -1
- package/dist/cmd/build/vite/ws-proxy.d.ts.map +1 -1
- package/dist/cmd/build/vite/ws-proxy.js +33 -0
- package/dist/cmd/build/vite/ws-proxy.js.map +1 -1
- package/dist/cmd/cloud/deploy.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.js +98 -39
- package/dist/cmd/cloud/deploy.js.map +1 -1
- package/dist/cmd/cloud/sandbox/checkpoint/create.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/checkpoint/create.js +3 -4
- package/dist/cmd/cloud/sandbox/checkpoint/create.js.map +1 -1
- package/dist/cmd/cloud/sandbox/checkpoint/delete.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/checkpoint/delete.js +3 -4
- package/dist/cmd/cloud/sandbox/checkpoint/delete.js.map +1 -1
- package/dist/cmd/cloud/sandbox/checkpoint/list.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/checkpoint/list.js +3 -4
- package/dist/cmd/cloud/sandbox/checkpoint/list.js.map +1 -1
- package/dist/cmd/cloud/sandbox/checkpoint/restore.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/checkpoint/restore.js +3 -4
- package/dist/cmd/cloud/sandbox/checkpoint/restore.js.map +1 -1
- package/dist/cmd/cloud/sandbox/create.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/create.js +13 -4
- package/dist/cmd/cloud/sandbox/create.js.map +1 -1
- package/dist/cmd/cloud/sandbox/delete.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/delete.js +3 -4
- package/dist/cmd/cloud/sandbox/delete.js.map +1 -1
- package/dist/cmd/cloud/sandbox/env.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/env.js +3 -5
- package/dist/cmd/cloud/sandbox/env.js.map +1 -1
- package/dist/cmd/cloud/sandbox/exec.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/exec.js +114 -41
- package/dist/cmd/cloud/sandbox/exec.js.map +1 -1
- package/dist/cmd/cloud/sandbox/execution/list.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/execution/list.js +3 -5
- package/dist/cmd/cloud/sandbox/execution/list.js.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/cp.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/cp.js +61 -113
- package/dist/cmd/cloud/sandbox/fs/cp.js.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/download.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/download.js +11 -22
- package/dist/cmd/cloud/sandbox/fs/download.js.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/ls.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/ls.js +3 -5
- package/dist/cmd/cloud/sandbox/fs/ls.js.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/mkdir.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/mkdir.js +3 -5
- package/dist/cmd/cloud/sandbox/fs/mkdir.js.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/rm.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/rm.js +3 -5
- 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 +3 -5
- package/dist/cmd/cloud/sandbox/fs/rmdir.js.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/upload.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/fs/upload.js +7 -8
- package/dist/cmd/cloud/sandbox/fs/upload.js.map +1 -1
- package/dist/cmd/cloud/sandbox/get.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/get.js +21 -7
- package/dist/cmd/cloud/sandbox/get.js.map +1 -1
- package/dist/cmd/cloud/sandbox/job/create.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/job/create.js +3 -4
- package/dist/cmd/cloud/sandbox/job/create.js.map +1 -1
- package/dist/cmd/cloud/sandbox/job/destroy.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/job/destroy.js +3 -4
- package/dist/cmd/cloud/sandbox/job/destroy.js.map +1 -1
- package/dist/cmd/cloud/sandbox/job/get.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/job/get.js +3 -4
- package/dist/cmd/cloud/sandbox/job/get.js.map +1 -1
- package/dist/cmd/cloud/sandbox/job/list.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/job/list.js +3 -4
- package/dist/cmd/cloud/sandbox/job/list.js.map +1 -1
- package/dist/cmd/cloud/sandbox/job/logs.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/job/logs.js +4 -4
- package/dist/cmd/cloud/sandbox/job/logs.js.map +1 -1
- package/dist/cmd/cloud/sandbox/pause.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/pause.js +21 -5
- package/dist/cmd/cloud/sandbox/pause.js.map +1 -1
- package/dist/cmd/cloud/sandbox/resume.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/resume.js +3 -4
- package/dist/cmd/cloud/sandbox/resume.js.map +1 -1
- package/dist/cmd/cloud/sandbox/run.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/run.js +36 -7
- package/dist/cmd/cloud/sandbox/run.js.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/create.js +4 -4
- package/dist/cmd/cloud/sandbox/snapshot/create.js.map +1 -1
- package/dist/cmd/cloud/sandbox/util.d.ts +19 -0
- package/dist/cmd/cloud/sandbox/util.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/util.js +40 -2
- package/dist/cmd/cloud/sandbox/util.js.map +1 -1
- package/dist/cmd/coder/create.js +7 -7
- package/dist/cmd/coder/create.js.map +1 -1
- package/dist/cmd/coder/start.d.ts.map +1 -1
- package/dist/cmd/coder/start.js +3 -0
- package/dist/cmd/coder/start.js.map +1 -1
- package/dist/cmd/coder/tui-init.js +1 -1
- package/dist/cmd/coder/tui-init.js.map +1 -1
- package/dist/cmd/coder/update.js +8 -8
- package/dist/cmd/coder/update.js.map +1 -1
- package/dist/cmd/coder/workspace/common.d.ts +29 -0
- package/dist/cmd/coder/workspace/common.d.ts.map +1 -0
- package/dist/cmd/coder/workspace/common.js +83 -0
- package/dist/cmd/coder/workspace/common.js.map +1 -0
- package/dist/cmd/coder/workspace/create.d.ts.map +1 -1
- package/dist/cmd/coder/workspace/create.js +57 -32
- package/dist/cmd/coder/workspace/create.js.map +1 -1
- package/dist/cmd/coder/workspace/get.d.ts.map +1 -1
- package/dist/cmd/coder/workspace/get.js +2 -5
- package/dist/cmd/coder/workspace/get.js.map +1 -1
- package/dist/cmd/coder/workspace/index.d.ts.map +1 -1
- package/dist/cmd/coder/workspace/index.js +11 -1
- package/dist/cmd/coder/workspace/index.js.map +1 -1
- package/dist/cmd/coder/workspace/list.d.ts.map +1 -1
- package/dist/cmd/coder/workspace/list.js +4 -0
- package/dist/cmd/coder/workspace/list.js.map +1 -1
- package/dist/cmd/coder/workspace/refresh.d.ts +2 -0
- package/dist/cmd/coder/workspace/refresh.d.ts.map +1 -0
- package/dist/cmd/coder/workspace/refresh.js +59 -0
- package/dist/cmd/coder/workspace/refresh.js.map +1 -0
- package/dist/cmd/coder/workspace/update.d.ts +2 -0
- package/dist/cmd/coder/workspace/update.d.ts.map +1 -0
- package/dist/cmd/coder/workspace/update.js +131 -0
- package/dist/cmd/coder/workspace/update.js.map +1 -0
- package/dist/cmd/coder/workspace/validate-dependencies.d.ts +2 -0
- package/dist/cmd/coder/workspace/validate-dependencies.d.ts.map +1 -0
- package/dist/cmd/coder/workspace/validate-dependencies.js +70 -0
- package/dist/cmd/coder/workspace/validate-dependencies.js.map +1 -0
- package/dist/cmd/dev/dev-lock.d.ts.map +1 -1
- package/dist/cmd/dev/dev-lock.js +43 -17
- package/dist/cmd/dev/dev-lock.js.map +1 -1
- package/dist/cmd/dev/index.d.ts.map +1 -1
- package/dist/cmd/dev/index.js +211 -125
- package/dist/cmd/dev/index.js.map +1 -1
- package/dist/cmd/dev/process-manager.d.ts +41 -1
- package/dist/cmd/dev/process-manager.d.ts.map +1 -1
- package/dist/cmd/dev/process-manager.js +160 -31
- package/dist/cmd/dev/process-manager.js.map +1 -1
- package/dist/cmd/project/create.d.ts.map +1 -1
- package/dist/cmd/project/create.js +0 -2
- package/dist/cmd/project/create.js.map +1 -1
- package/dist/cmd/project/index.d.ts.map +1 -1
- package/dist/cmd/project/index.js +0 -3
- package/dist/cmd/project/index.js.map +1 -1
- package/dist/cmd/project/random-name.d.ts +17 -0
- package/dist/cmd/project/random-name.d.ts.map +1 -0
- package/dist/cmd/project/random-name.js +144 -0
- package/dist/cmd/project/random-name.js.map +1 -0
- package/dist/cmd/project/template-flow.d.ts +0 -1
- package/dist/cmd/project/template-flow.d.ts.map +1 -1
- package/dist/cmd/project/template-flow.js +180 -275
- package/dist/cmd/project/template-flow.js.map +1 -1
- package/dist/composite-logger.d.ts.map +1 -1
- package/dist/composite-logger.js +19 -0
- package/dist/composite-logger.js.map +1 -1
- package/dist/config.d.ts +18 -16
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +46 -16
- package/dist/config.js.map +1 -1
- package/dist/tui/prompt.d.ts +29 -0
- package/dist/tui/prompt.d.ts.map +1 -1
- package/dist/tui/prompt.js +180 -8
- package/dist/tui/prompt.js.map +1 -1
- package/package.json +7 -7
- package/src/cache/resource-region.ts +68 -44
- package/src/cli.ts +30 -8
- package/src/cmd/ai/prompt/web.md +43 -17
- package/src/cmd/build/vite/bun-dev-server.ts +92 -6
- package/src/cmd/build/vite/index.ts +0 -1
- package/src/cmd/build/vite/static-renderer.ts +18 -7
- package/src/cmd/build/vite/vite-asset-server-config.ts +37 -27
- package/src/cmd/build/vite/vite-asset-server.ts +5 -1
- package/src/cmd/build/vite/vite-builder.ts +12 -1
- package/src/cmd/build/vite/ws-proxy.ts +52 -3
- package/src/cmd/cloud/deploy.ts +117 -49
- package/src/cmd/cloud/sandbox/checkpoint/create.ts +10 -4
- package/src/cmd/cloud/sandbox/checkpoint/delete.ts +10 -4
- package/src/cmd/cloud/sandbox/checkpoint/list.ts +10 -4
- package/src/cmd/cloud/sandbox/checkpoint/restore.ts +10 -4
- package/src/cmd/cloud/sandbox/create.ts +14 -4
- package/src/cmd/cloud/sandbox/delete.ts +10 -4
- package/src/cmd/cloud/sandbox/env.ts +10 -5
- package/src/cmd/cloud/sandbox/exec.ts +157 -42
- package/src/cmd/cloud/sandbox/execution/list.ts +10 -5
- package/src/cmd/cloud/sandbox/fs/cp.ts +94 -126
- package/src/cmd/cloud/sandbox/fs/download.ts +18 -25
- package/src/cmd/cloud/sandbox/fs/ls.ts +10 -5
- package/src/cmd/cloud/sandbox/fs/mkdir.ts +10 -5
- package/src/cmd/cloud/sandbox/fs/rm.ts +10 -5
- package/src/cmd/cloud/sandbox/fs/rmdir.ts +10 -5
- package/src/cmd/cloud/sandbox/fs/upload.ts +14 -8
- package/src/cmd/cloud/sandbox/get.ts +28 -7
- package/src/cmd/cloud/sandbox/job/create.ts +10 -4
- package/src/cmd/cloud/sandbox/job/destroy.ts +10 -4
- package/src/cmd/cloud/sandbox/job/get.ts +10 -4
- package/src/cmd/cloud/sandbox/job/list.ts +10 -4
- package/src/cmd/cloud/sandbox/job/logs.ts +11 -4
- package/src/cmd/cloud/sandbox/pause.ts +31 -5
- package/src/cmd/cloud/sandbox/resume.ts +10 -4
- package/src/cmd/cloud/sandbox/run.ts +49 -11
- package/src/cmd/cloud/sandbox/snapshot/create.ts +6 -6
- package/src/cmd/cloud/sandbox/util.ts +63 -2
- package/src/cmd/coder/create.ts +8 -8
- package/src/cmd/coder/start.ts +3 -0
- package/src/cmd/coder/tui-init.ts +1 -1
- package/src/cmd/coder/update.ts +7 -7
- package/src/cmd/coder/workspace/common.ts +103 -0
- package/src/cmd/coder/workspace/create.ts +84 -37
- package/src/cmd/coder/workspace/get.ts +2 -5
- package/src/cmd/coder/workspace/index.ts +13 -1
- package/src/cmd/coder/workspace/list.ts +4 -0
- package/src/cmd/coder/workspace/refresh.ts +63 -0
- package/src/cmd/coder/workspace/update.ts +154 -0
- package/src/cmd/coder/workspace/validate-dependencies.ts +75 -0
- package/src/cmd/dev/dev-lock.ts +50 -16
- package/src/cmd/dev/index.ts +249 -134
- package/src/cmd/dev/process-manager.ts +173 -33
- package/src/cmd/project/create.ts +0 -2
- package/src/cmd/project/index.ts +0 -3
- package/src/cmd/project/random-name.ts +152 -0
- package/src/cmd/project/template-flow.ts +196 -305
- package/src/composite-logger.ts +20 -0
- package/src/config.ts +69 -19
- package/src/tui/prompt.ts +214 -8
- package/dist/cmd/build/vite/public-asset-path-plugin.d.ts +0 -45
- package/dist/cmd/build/vite/public-asset-path-plugin.d.ts.map +0 -1
- package/dist/cmd/build/vite/public-asset-path-plugin.js +0 -166
- package/dist/cmd/build/vite/public-asset-path-plugin.js.map +0 -1
- package/dist/cmd/project/auth/generate.d.ts +0 -5
- package/dist/cmd/project/auth/generate.d.ts.map +0 -1
- package/dist/cmd/project/auth/generate.js +0 -102
- package/dist/cmd/project/auth/generate.js.map +0 -1
- package/dist/cmd/project/auth/index.d.ts +0 -2
- package/dist/cmd/project/auth/index.d.ts.map +0 -1
- package/dist/cmd/project/auth/index.js +0 -21
- package/dist/cmd/project/auth/index.js.map +0 -1
- package/dist/cmd/project/auth/init.d.ts +0 -2
- package/dist/cmd/project/auth/init.d.ts.map +0 -1
- package/dist/cmd/project/auth/init.js +0 -213
- package/dist/cmd/project/auth/init.js.map +0 -1
- package/dist/cmd/project/auth/shared.d.ts +0 -93
- package/dist/cmd/project/auth/shared.d.ts.map +0 -1
- package/dist/cmd/project/auth/shared.js +0 -475
- package/dist/cmd/project/auth/shared.js.map +0 -1
- package/src/cmd/build/vite/public-asset-path-plugin.ts +0 -209
- package/src/cmd/project/auth/generate.ts +0 -116
- package/src/cmd/project/auth/index.ts +0 -21
- package/src/cmd/project/auth/init.ts +0 -256
- package/src/cmd/project/auth/shared.ts +0 -591
|
@@ -3,7 +3,7 @@ import { z } from 'zod';
|
|
|
3
3
|
import { getCommand } from '../../../../command-prefix';
|
|
4
4
|
import * as tui from '../../../../tui';
|
|
5
5
|
import { createCommand } from '../../../../types';
|
|
6
|
-
import { createSandboxClient,
|
|
6
|
+
import { createSandboxClient, resolveSandboxTarget } from '../util';
|
|
7
7
|
|
|
8
8
|
const SNAPSHOT_NAME_REGEX = /^[a-zA-Z0-9_-]+$/;
|
|
9
9
|
const SNAPSHOT_TAG_REGEX = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
|
|
@@ -88,15 +88,15 @@ export const createSubcommand = createCommand({
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
const profileName = config?.name;
|
|
91
|
-
const
|
|
91
|
+
const sandboxInfo = await resolveSandboxTarget(
|
|
92
92
|
logger,
|
|
93
93
|
auth,
|
|
94
|
-
|
|
94
|
+
null,
|
|
95
95
|
args.sandboxId,
|
|
96
|
-
|
|
96
|
+
profileName,
|
|
97
97
|
config
|
|
98
98
|
);
|
|
99
|
-
const client = createSandboxClient(logger, auth, region);
|
|
99
|
+
const client = createSandboxClient(logger, auth, sandboxInfo.region);
|
|
100
100
|
|
|
101
101
|
const snapshot = await snapshotCreate(client, {
|
|
102
102
|
sandboxId: args.sandboxId,
|
|
@@ -104,7 +104,7 @@ export const createSubcommand = createCommand({
|
|
|
104
104
|
description: opts.description,
|
|
105
105
|
tag: opts.tag,
|
|
106
106
|
public: opts.public,
|
|
107
|
-
orgId,
|
|
107
|
+
orgId: sandboxInfo.orgId ?? orgId,
|
|
108
108
|
});
|
|
109
109
|
|
|
110
110
|
if (!options.json) {
|
|
@@ -1,17 +1,69 @@
|
|
|
1
|
-
import { readFileSync } from 'node:fs';
|
|
1
|
+
import { fstatSync, readFileSync, statSync } from 'node:fs';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
3
|
import type { FileToWrite, Logger } from '@agentuity/core';
|
|
4
|
-
import { APIClient, getServiceUrls, sandboxGet } from '@agentuity/server';
|
|
4
|
+
import { APIClient, getServiceUrls, sandboxGet, sandboxResolve } from '@agentuity/server';
|
|
5
5
|
import { deleteResourceRegion, getResourceInfo, setResourceInfo } from '../../../cache';
|
|
6
6
|
import { getGlobalCatalystAPIClient } from '../../../config';
|
|
7
7
|
import { ErrorCode } from '../../../errors';
|
|
8
8
|
import * as tui from '../../../tui';
|
|
9
9
|
import type { AuthData, Config } from '../../../types';
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Detect if a file descriptor is redirected to /dev/null (or NUL on Windows).
|
|
13
|
+
* Used to optimize stream creation - when output goes to /dev/null, we can
|
|
14
|
+
* skip creating the stream entirely on the server.
|
|
15
|
+
*
|
|
16
|
+
* @param fd - File descriptor (1 for stdout, 2 for stderr)
|
|
17
|
+
* @returns true if the fd points to /dev/null
|
|
18
|
+
*/
|
|
19
|
+
export function detectNullStream(fd: number): boolean {
|
|
20
|
+
try {
|
|
21
|
+
const fdStat = fstatSync(fd);
|
|
22
|
+
const nullPath = process.platform === 'win32' ? 'NUL' : '/dev/null';
|
|
23
|
+
const nullStat = statSync(nullPath);
|
|
24
|
+
return fdStat.dev === nullStat.dev && fdStat.ino === nullStat.ino;
|
|
25
|
+
} catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
11
30
|
export function createSandboxClient(logger: Logger, auth: AuthData, region: string): APIClient {
|
|
12
31
|
return new APIClient(getServiceUrls(region).catalyst, logger, auth.apiKey);
|
|
13
32
|
}
|
|
14
33
|
|
|
34
|
+
export interface ResolvedSandboxTarget {
|
|
35
|
+
region: string;
|
|
36
|
+
orgId: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Resolve sandbox routing context using cache-first lookup.
|
|
41
|
+
* Falls back to the CLI resolve endpoint on cache miss or partial cache.
|
|
42
|
+
*/
|
|
43
|
+
export async function resolveSandboxTarget(
|
|
44
|
+
logger: Logger,
|
|
45
|
+
auth: AuthData,
|
|
46
|
+
apiClient: APIClient | null = null,
|
|
47
|
+
sandboxId: string,
|
|
48
|
+
profileName = 'production',
|
|
49
|
+
config?: Config | null
|
|
50
|
+
): Promise<ResolvedSandboxTarget> {
|
|
51
|
+
const cachedInfo = await getResourceInfo('sandbox', profileName, sandboxId);
|
|
52
|
+
if (cachedInfo?.region && cachedInfo?.orgId) {
|
|
53
|
+
logger.trace(
|
|
54
|
+
`[sandbox] Found cached target for ${sandboxId}: ${cachedInfo.region}/${cachedInfo.orgId}`
|
|
55
|
+
);
|
|
56
|
+
return { region: cachedInfo.region, orgId: cachedInfo.orgId };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
logger.trace(`[sandbox] Cache miss for target ${sandboxId}, resolving via CLI API`);
|
|
60
|
+
const globalClient =
|
|
61
|
+
apiClient ?? (await getGlobalCatalystAPIClient(logger, auth, profileName, undefined, config));
|
|
62
|
+
const sandbox = await sandboxResolve(globalClient, sandboxId);
|
|
63
|
+
await setResourceInfo('sandbox', profileName, sandboxId, sandbox.region, sandbox.orgId);
|
|
64
|
+
return { region: sandbox.region, orgId: sandbox.orgId };
|
|
65
|
+
}
|
|
66
|
+
|
|
15
67
|
/**
|
|
16
68
|
* Look up the region for a sandbox, using cache-first strategy.
|
|
17
69
|
* Falls back to API lookup if not in cache.
|
|
@@ -64,6 +116,15 @@ export async function cacheSandboxRegion(
|
|
|
64
116
|
await setResourceInfo('sandbox', profileName, sandboxId, region);
|
|
65
117
|
}
|
|
66
118
|
|
|
119
|
+
export async function cacheSandboxTarget(
|
|
120
|
+
profileName = 'production',
|
|
121
|
+
sandboxId: string,
|
|
122
|
+
region: string,
|
|
123
|
+
orgId?: string
|
|
124
|
+
): Promise<void> {
|
|
125
|
+
await setResourceInfo('sandbox', profileName, sandboxId, region, orgId);
|
|
126
|
+
}
|
|
127
|
+
|
|
67
128
|
/**
|
|
68
129
|
* Clear cached region for a sandbox after delete
|
|
69
130
|
*/
|
package/src/cmd/coder/create.ts
CHANGED
|
@@ -46,9 +46,9 @@ export const createCoderSubcommand = createSubcommand({
|
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
command: getCommand(
|
|
49
|
-
'coder create "Review this change" --default-agent code-review --
|
|
49
|
+
'coder create "Review this change" --default-agent code-review --enabled-agents code-review'
|
|
50
50
|
),
|
|
51
|
-
description: 'Create with
|
|
51
|
+
description: 'Create with a selected agent roster and a custom default route target',
|
|
52
52
|
},
|
|
53
53
|
],
|
|
54
54
|
schema: {
|
|
@@ -96,10 +96,10 @@ export const createCoderSubcommand = createSubcommand({
|
|
|
96
96
|
// Resources
|
|
97
97
|
workspaceId: z.string().optional().describe('Workspace ID to use'),
|
|
98
98
|
tags: z.string().optional().describe('Comma-separated tags'),
|
|
99
|
-
|
|
99
|
+
enabledAgents: z
|
|
100
100
|
.string()
|
|
101
101
|
.optional()
|
|
102
|
-
.describe('Comma-separated
|
|
102
|
+
.describe('Comma-separated built-in/custom agents to include'),
|
|
103
103
|
env: z
|
|
104
104
|
.string()
|
|
105
105
|
.optional()
|
|
@@ -121,7 +121,7 @@ export const createCoderSubcommand = createSubcommand({
|
|
|
121
121
|
// Build the create session request body from flags
|
|
122
122
|
const body: CoderCreateSessionRequest & {
|
|
123
123
|
defaultAgent?: string;
|
|
124
|
-
|
|
124
|
+
enabledAgents?: string[];
|
|
125
125
|
} = {
|
|
126
126
|
task: args.task,
|
|
127
127
|
...(opts?.label && { label: opts.label }),
|
|
@@ -167,10 +167,10 @@ export const createCoderSubcommand = createSubcommand({
|
|
|
167
167
|
.split(',')
|
|
168
168
|
.map((t) => t.trim())
|
|
169
169
|
.filter(Boolean);
|
|
170
|
-
if (opts?.
|
|
171
|
-
body.
|
|
170
|
+
if (opts?.enabledAgents)
|
|
171
|
+
body.enabledAgents = opts.enabledAgents
|
|
172
172
|
.split(',')
|
|
173
|
-
.map((
|
|
173
|
+
.map((name) => name.trim())
|
|
174
174
|
.filter(Boolean);
|
|
175
175
|
if (opts?.savedSkillIds)
|
|
176
176
|
body.savedSkillIds = opts.savedSkillIds
|
package/src/cmd/coder/start.ts
CHANGED
|
@@ -128,6 +128,8 @@ export const startSubcommand = createSubcommand({
|
|
|
128
128
|
},
|
|
129
129
|
async handler(ctx) {
|
|
130
130
|
const { opts, options } = ctx;
|
|
131
|
+
// Keep Pi's interactive install telemetry disabled for Agentuity CLI sessions.
|
|
132
|
+
process.env.PI_TELEMETRY = '0';
|
|
131
133
|
|
|
132
134
|
// Resolve working directory from optional --dir option
|
|
133
135
|
let cwd = process.cwd();
|
|
@@ -388,6 +390,7 @@ export const startSubcommand = createSubcommand({
|
|
|
388
390
|
AGENTUITY_CODER_HUB_URL: hubWsUrl,
|
|
389
391
|
};
|
|
390
392
|
env.AGENTUITY_CODER_API_KEY = ctx.auth.apiKey;
|
|
393
|
+
env.AGENTUITY_ORGID = ctx.orgId;
|
|
391
394
|
|
|
392
395
|
if (opts?.agent) {
|
|
393
396
|
env.AGENTUITY_CODER_AGENT = opts.agent;
|
package/src/cmd/coder/update.ts
CHANGED
|
@@ -54,10 +54,10 @@ export const updateSubcommand = createSubcommand({
|
|
|
54
54
|
loopAutoContinue: z.boolean().optional().describe('Auto-continue loop'),
|
|
55
55
|
loopAllowDetached: z.boolean().optional().describe('Allow detached loop execution'),
|
|
56
56
|
tags: z.string().optional().describe('Comma-separated tags (replaces existing)'),
|
|
57
|
-
|
|
57
|
+
enabledAgents: z
|
|
58
58
|
.string()
|
|
59
59
|
.optional()
|
|
60
|
-
.describe('Comma-separated
|
|
60
|
+
.describe('Comma-separated built-in/custom agents (replaces existing)'),
|
|
61
61
|
}),
|
|
62
62
|
},
|
|
63
63
|
async handler(ctx) {
|
|
@@ -81,10 +81,10 @@ export const updateSubcommand = createSubcommand({
|
|
|
81
81
|
.map((t) => t.trim())
|
|
82
82
|
.filter(Boolean);
|
|
83
83
|
}
|
|
84
|
-
if (opts?.
|
|
85
|
-
body.
|
|
84
|
+
if (opts?.enabledAgents) {
|
|
85
|
+
body.enabledAgents = opts.enabledAgents
|
|
86
86
|
.split(',')
|
|
87
|
-
.map((
|
|
87
|
+
.map((name) => name.trim())
|
|
88
88
|
.filter(Boolean);
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -105,7 +105,7 @@ export const updateSubcommand = createSubcommand({
|
|
|
105
105
|
|
|
106
106
|
if (Object.keys(body).length === 0) {
|
|
107
107
|
tui.fatal(
|
|
108
|
-
'No update fields provided. Use --label, --visibility, --tags, --agent, --default-agent, --
|
|
108
|
+
'No update fields provided. Use --label, --visibility, --tags, --agent, --default-agent, --enabled-agents, --workflow-mode, or loop options.',
|
|
109
109
|
ErrorCode.VALIDATION_FAILED
|
|
110
110
|
);
|
|
111
111
|
}
|
|
@@ -125,7 +125,7 @@ export const updateSubcommand = createSubcommand({
|
|
|
125
125
|
if (opts?.tags) fields.push(`Tags: ${(body.tags as string[]).join(', ')}`);
|
|
126
126
|
if (opts?.agent) fields.push(`Agent: ${opts.agent}`);
|
|
127
127
|
if (opts?.defaultAgent) fields.push(`Default agent: ${opts.defaultAgent}`);
|
|
128
|
-
if (opts?.
|
|
128
|
+
if (opts?.enabledAgents) fields.push(`Enabled agents: ${opts.enabledAgents}`);
|
|
129
129
|
if (opts?.workflowMode || body.loop) fields.push(`Workflow: ${body.workflowMode}`);
|
|
130
130
|
|
|
131
131
|
for (const f of fields) {
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type CoderCreateWorkspaceRequest,
|
|
3
|
+
type CoderUpdateWorkspaceRequest,
|
|
4
|
+
type CoderWorkspaceDetail,
|
|
5
|
+
} from '@agentuity/core/coder';
|
|
6
|
+
import { StructuredError } from '@agentuity/core';
|
|
7
|
+
import * as tui from '../../../tui';
|
|
8
|
+
|
|
9
|
+
export const EMPTY_WORKSPACE_ERROR =
|
|
10
|
+
'A workspace needs at least one repo, dependency, setup script, saved skill, skill bucket, or agent';
|
|
11
|
+
export const SetupScriptValidationError = StructuredError('SetupScriptValidationError')<{
|
|
12
|
+
message: string;
|
|
13
|
+
path?: string;
|
|
14
|
+
}>();
|
|
15
|
+
|
|
16
|
+
export function parseCommaList(value?: string): string[] {
|
|
17
|
+
return value
|
|
18
|
+
? value
|
|
19
|
+
.split(',')
|
|
20
|
+
.map((item) => item.trim())
|
|
21
|
+
.filter(Boolean)
|
|
22
|
+
: [];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function readSetupScript(input: {
|
|
26
|
+
setupScript?: string;
|
|
27
|
+
setupScriptFile?: string;
|
|
28
|
+
}): Promise<string | undefined> {
|
|
29
|
+
if (input.setupScript !== undefined && input.setupScriptFile) {
|
|
30
|
+
throw new SetupScriptValidationError({
|
|
31
|
+
message: 'Use either --setup-script or --setup-script-file, not both.',
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
if (input.setupScript !== undefined) return input.setupScript;
|
|
35
|
+
if (!input.setupScriptFile) return undefined;
|
|
36
|
+
try {
|
|
37
|
+
return await Bun.file(input.setupScriptFile).text();
|
|
38
|
+
} catch (error) {
|
|
39
|
+
throw new SetupScriptValidationError({
|
|
40
|
+
message: `Failed to read setup script file "${input.setupScriptFile}": ${
|
|
41
|
+
error instanceof Error ? error.message : String(error)
|
|
42
|
+
}`,
|
|
43
|
+
path: input.setupScriptFile,
|
|
44
|
+
cause: error,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function hasWorkspaceSelections(input: CoderCreateWorkspaceRequest): boolean {
|
|
50
|
+
return (
|
|
51
|
+
(input.repos?.length ?? 0) > 0 ||
|
|
52
|
+
(input.dependencies?.length ?? 0) > 0 ||
|
|
53
|
+
Boolean(input.setupScript?.trim()) ||
|
|
54
|
+
(input.savedSkillIds?.length ?? 0) > 0 ||
|
|
55
|
+
(input.skillBucketIds?.length ?? 0) > 0 ||
|
|
56
|
+
(input.enabledAgents?.length ?? 0) > 0
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function hasWorkspaceUpdate(input: CoderUpdateWorkspaceRequest): boolean {
|
|
61
|
+
return Object.keys(input).length > 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function formatWorkspaceValidationMessage(issues: Array<{ message: string }>): string {
|
|
65
|
+
const messages = [...new Set(issues.map((issue) => issue.message).filter(Boolean))];
|
|
66
|
+
if (messages.length === 0) {
|
|
67
|
+
return 'Invalid workspace configuration';
|
|
68
|
+
}
|
|
69
|
+
if (messages.includes(EMPTY_WORKSPACE_ERROR)) {
|
|
70
|
+
return `${EMPTY_WORKSPACE_ERROR}. Use --repo, --dependency, --setup-script, or --enabled-agents.`;
|
|
71
|
+
}
|
|
72
|
+
return messages.join('; ');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function printWorkspaceSummary(workspace: CoderWorkspaceDetail): void {
|
|
76
|
+
const enabledAgents = Array.isArray(workspace.enabledAgents)
|
|
77
|
+
? workspace.enabledAgents.filter((name): name is string => typeof name === 'string')
|
|
78
|
+
: [];
|
|
79
|
+
const dependencies = Array.isArray(workspace.dependencies) ? workspace.dependencies : [];
|
|
80
|
+
|
|
81
|
+
tui.output(` Name: ${tui.bold(workspace.name)}`);
|
|
82
|
+
if (workspace.description) {
|
|
83
|
+
tui.output(` Description: ${workspace.description}`);
|
|
84
|
+
}
|
|
85
|
+
tui.output(` Scope: ${workspace.scope}`);
|
|
86
|
+
tui.output(` Repos: ${workspace.repoCount}`);
|
|
87
|
+
tui.output(` Selections: ${workspace.selectionCount}`);
|
|
88
|
+
if (dependencies.length > 0) {
|
|
89
|
+
tui.output(` Dependencies:${dependencies.length === 1 ? ` ${dependencies[0]}` : ''}`);
|
|
90
|
+
for (const dependency of dependencies.length === 1 ? [] : dependencies) {
|
|
91
|
+
tui.output(` - ${dependency}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (workspace.setupScript) {
|
|
95
|
+
tui.output(' Setup: configured');
|
|
96
|
+
}
|
|
97
|
+
if (workspace.snapshot?.status) {
|
|
98
|
+
tui.output(` Snapshot: ${workspace.snapshot.status}`);
|
|
99
|
+
}
|
|
100
|
+
if (enabledAgents.length > 0) {
|
|
101
|
+
tui.output(` Agents: ${enabledAgents.join(', ')}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -1,37 +1,51 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { APIError, ValidationInputError, ValidationOutputError } from '@agentuity/core';
|
|
3
|
+
import {
|
|
4
|
+
CoderClient,
|
|
5
|
+
CoderCreateWorkspaceRequestSchema,
|
|
6
|
+
type CoderCreateWorkspaceRequest,
|
|
7
|
+
} from '@agentuity/core/coder';
|
|
4
8
|
import { createSubcommand } from '../../../types';
|
|
5
9
|
import * as tui from '../../../tui';
|
|
6
10
|
import { getCommand } from '../../../command-prefix';
|
|
7
11
|
import { ErrorCode } from '../../../errors';
|
|
8
12
|
import { resolveGitHubRepo } from '../resolve-repo';
|
|
13
|
+
import {
|
|
14
|
+
EMPTY_WORKSPACE_ERROR,
|
|
15
|
+
formatWorkspaceValidationMessage,
|
|
16
|
+
hasWorkspaceSelections,
|
|
17
|
+
parseCommaList,
|
|
18
|
+
printWorkspaceSummary,
|
|
19
|
+
readSetupScript,
|
|
20
|
+
} from './common';
|
|
9
21
|
|
|
10
22
|
export const createWorkspaceSubcommand = createSubcommand({
|
|
11
23
|
name: 'create',
|
|
12
24
|
aliases: ['new', 'add'],
|
|
13
|
-
description: 'Create a new Coder workspace',
|
|
25
|
+
description: 'Create a new Coder workspace with at least one repo or agent',
|
|
14
26
|
tags: ['mutating', 'requires-auth'],
|
|
15
27
|
requires: { auth: true, org: true },
|
|
16
28
|
examples: [
|
|
17
|
-
{
|
|
18
|
-
command: getCommand('coder workspace create "My Workspace"'),
|
|
19
|
-
description: 'Create a workspace with a name',
|
|
20
|
-
},
|
|
21
29
|
{
|
|
22
30
|
command: getCommand(
|
|
23
|
-
'coder workspace create "My Workspace" --
|
|
31
|
+
'coder workspace create "My Workspace" --repo https://github.com/org/repo --repo-branch main'
|
|
24
32
|
),
|
|
25
|
-
description: 'Create
|
|
33
|
+
description: 'Create a workspace with a repository',
|
|
26
34
|
},
|
|
27
35
|
{
|
|
28
36
|
command: getCommand(
|
|
29
|
-
'coder workspace create "My Workspace" --
|
|
37
|
+
'coder workspace create "My Workspace" --dependency git --setup-script-file ./setup.sh --scope org'
|
|
30
38
|
),
|
|
31
|
-
description: 'Create
|
|
39
|
+
description: 'Create an org-scoped workspace with dependencies and a setup script',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
command: getCommand('coder workspace create "My Workspace" --enabled-agents code-review'),
|
|
43
|
+
description: 'Create a workspace with an agent roster',
|
|
32
44
|
},
|
|
33
45
|
{
|
|
34
|
-
command: getCommand(
|
|
46
|
+
command: getCommand(
|
|
47
|
+
'coder workspace create "My Workspace" --enabled-agents code-review --json'
|
|
48
|
+
),
|
|
35
49
|
description: 'Create a workspace and return JSON output',
|
|
36
50
|
},
|
|
37
51
|
],
|
|
@@ -45,10 +59,22 @@ export const createWorkspaceSubcommand = createSubcommand({
|
|
|
45
59
|
scope: z.string().optional().describe('Workspace scope: user or org'),
|
|
46
60
|
repo: z.string().optional().describe('Repository URL to add'),
|
|
47
61
|
repoBranch: z.string().optional().describe('Branch for the repository'),
|
|
48
|
-
|
|
62
|
+
dependency: z
|
|
63
|
+
.string()
|
|
64
|
+
.optional()
|
|
65
|
+
.describe('Comma-separated APT dependencies to install into workspace snapshots'),
|
|
66
|
+
setupScript: z
|
|
67
|
+
.string()
|
|
68
|
+
.optional()
|
|
69
|
+
.describe('Inline shell script to run while preparing workspace snapshots'),
|
|
70
|
+
setupScriptFile: z
|
|
49
71
|
.string()
|
|
50
72
|
.optional()
|
|
51
|
-
.describe('
|
|
73
|
+
.describe('Path to a shell script to run while preparing workspace snapshots'),
|
|
74
|
+
enabledAgents: z
|
|
75
|
+
.string()
|
|
76
|
+
.optional()
|
|
77
|
+
.describe('Comma-separated built-in/custom agents to include'),
|
|
52
78
|
}),
|
|
53
79
|
},
|
|
54
80
|
async handler(ctx) {
|
|
@@ -59,9 +85,7 @@ export const createWorkspaceSubcommand = createSubcommand({
|
|
|
59
85
|
orgId: ctx.orgId,
|
|
60
86
|
});
|
|
61
87
|
|
|
62
|
-
const body: CoderCreateWorkspaceRequest
|
|
63
|
-
agentSlugs?: string[];
|
|
64
|
-
} = {
|
|
88
|
+
const body: CoderCreateWorkspaceRequest = {
|
|
65
89
|
name: args.name,
|
|
66
90
|
...(opts?.description && { description: opts.description }),
|
|
67
91
|
...(opts?.scope && { scope: opts.scope as 'user' | 'org' }),
|
|
@@ -78,18 +102,44 @@ export const createWorkspaceSubcommand = createSubcommand({
|
|
|
78
102
|
return;
|
|
79
103
|
}
|
|
80
104
|
}
|
|
81
|
-
if (opts?.
|
|
82
|
-
body.
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
105
|
+
if (opts?.dependency) {
|
|
106
|
+
body.dependencies = parseCommaList(opts.dependency);
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
const setupScript = await readSetupScript({
|
|
110
|
+
setupScript: opts?.setupScript,
|
|
111
|
+
setupScriptFile: opts?.setupScriptFile,
|
|
112
|
+
});
|
|
113
|
+
if (setupScript !== undefined) body.setupScript = setupScript;
|
|
114
|
+
} catch (err) {
|
|
115
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
116
|
+
tui.fatal(`Failed to read setup script: ${msg}`, ErrorCode.VALIDATION_FAILED);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (opts?.enabledAgents) {
|
|
120
|
+
body.enabledAgents = parseCommaList(opts.enabledAgents);
|
|
121
|
+
}
|
|
122
|
+
if (!hasWorkspaceSelections(body)) {
|
|
123
|
+
tui.fatal(
|
|
124
|
+
`Failed to create workspace: ${EMPTY_WORKSPACE_ERROR}. Use --repo, --dependency, --setup-script, or --enabled-agents.`,
|
|
125
|
+
ErrorCode.VALIDATION_FAILED
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const validationResult = CoderCreateWorkspaceRequestSchema.safeParse(body);
|
|
130
|
+
if (!validationResult.success) {
|
|
131
|
+
ctx.logger.trace(
|
|
132
|
+
'Validation issues: %s',
|
|
133
|
+
JSON.stringify(validationResult.error.issues, null, 2)
|
|
134
|
+
);
|
|
135
|
+
tui.fatal(
|
|
136
|
+
`Failed to create workspace: ${formatWorkspaceValidationMessage(validationResult.error.issues)}`,
|
|
137
|
+
ErrorCode.VALIDATION_FAILED
|
|
138
|
+
);
|
|
86
139
|
}
|
|
87
140
|
|
|
88
141
|
try {
|
|
89
|
-
const created = await client.createWorkspace(
|
|
90
|
-
const createdAgentSlugs = Array.isArray(created.agentSlugs)
|
|
91
|
-
? created.agentSlugs.filter((slug): slug is string => typeof slug === 'string')
|
|
92
|
-
: [];
|
|
142
|
+
const created = await client.createWorkspace(validationResult.data);
|
|
93
143
|
|
|
94
144
|
if (options.json) {
|
|
95
145
|
return created;
|
|
@@ -97,22 +147,19 @@ export const createWorkspaceSubcommand = createSubcommand({
|
|
|
97
147
|
|
|
98
148
|
tui.success(`Workspace ${created.id} created.`);
|
|
99
149
|
tui.newline();
|
|
100
|
-
|
|
101
|
-
if (created.description) {
|
|
102
|
-
tui.output(` Description: ${created.description}`);
|
|
103
|
-
}
|
|
104
|
-
tui.output(` Scope: ${created.scope}`);
|
|
105
|
-
tui.output(` Repos: ${created.repoCount}`);
|
|
106
|
-
tui.output(` Selections: ${created.selectionCount}`);
|
|
107
|
-
if (createdAgentSlugs.length > 0) {
|
|
108
|
-
tui.output(` Agents: ${createdAgentSlugs.join(', ')}`);
|
|
109
|
-
}
|
|
150
|
+
printWorkspaceSummary(created);
|
|
110
151
|
|
|
111
152
|
return created;
|
|
112
153
|
} catch (err) {
|
|
113
|
-
if (err instanceof ValidationOutputError) {
|
|
154
|
+
if (err instanceof ValidationInputError || err instanceof ValidationOutputError) {
|
|
114
155
|
ctx.logger.trace('Validation response URL: %s', err.url ?? 'unknown');
|
|
115
156
|
ctx.logger.trace('Validation issues: %s', JSON.stringify(err.issues, null, 2));
|
|
157
|
+
tui.fatal(
|
|
158
|
+
`Failed to create workspace: ${formatWorkspaceValidationMessage(err.issues)}`,
|
|
159
|
+
ErrorCode.VALIDATION_FAILED
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
if (err instanceof APIError && err.status >= 400 && err.status < 500) {
|
|
116
163
|
tui.fatal(`Failed to create workspace: ${err.message}`, ErrorCode.VALIDATION_FAILED);
|
|
117
164
|
}
|
|
118
165
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -5,6 +5,7 @@ import { createSubcommand } from '../../../types';
|
|
|
5
5
|
import * as tui from '../../../tui';
|
|
6
6
|
import { getCommand } from '../../../command-prefix';
|
|
7
7
|
import { ErrorCode } from '../../../errors';
|
|
8
|
+
import { printWorkspaceSummary } from './common';
|
|
8
9
|
|
|
9
10
|
function formatRelativeTime(isoDate: string): string {
|
|
10
11
|
const parsed = new Date(isoDate).getTime();
|
|
@@ -63,11 +64,7 @@ export const getWorkspaceSubcommand = createSubcommand({
|
|
|
63
64
|
tui.header(`Workspace: ${workspace.name}`);
|
|
64
65
|
tui.newline();
|
|
65
66
|
tui.output(` ID: ${workspace.id}`);
|
|
66
|
-
|
|
67
|
-
if (workspace.description) {
|
|
68
|
-
tui.output(` Description: ${workspace.description}`);
|
|
69
|
-
}
|
|
70
|
-
tui.output(` Scope: ${workspace.scope}`);
|
|
67
|
+
printWorkspaceSummary(workspace);
|
|
71
68
|
tui.output(` Owner: ${workspace.ownerUserId}`);
|
|
72
69
|
tui.output(` Created: ${formatRelativeTime(workspace.createdAt)}`);
|
|
73
70
|
tui.output(` Updated: ${formatRelativeTime(workspace.updatedAt)}`);
|
|
@@ -2,6 +2,9 @@ import { createCommand } from '../../../types';
|
|
|
2
2
|
import { listSubcommand } from './list';
|
|
3
3
|
import { createWorkspaceSubcommand } from './create';
|
|
4
4
|
import { getWorkspaceSubcommand } from './get';
|
|
5
|
+
import { refreshWorkspaceSnapshotSubcommand } from './refresh';
|
|
6
|
+
import { updateWorkspaceSubcommand } from './update';
|
|
7
|
+
import { validateWorkspaceDependenciesSubcommand } from './validate-dependencies';
|
|
5
8
|
import { deleteWorkspaceSubcommand } from './delete';
|
|
6
9
|
import { getCommand } from '../../../command-prefix';
|
|
7
10
|
|
|
@@ -17,7 +20,9 @@ export const workspaceCommand = createCommand({
|
|
|
17
20
|
description: 'List all workspaces',
|
|
18
21
|
},
|
|
19
22
|
{
|
|
20
|
-
command: getCommand(
|
|
23
|
+
command: getCommand(
|
|
24
|
+
'coder workspace create "My Workspace" --repo https://github.com/org/repo'
|
|
25
|
+
),
|
|
21
26
|
description: 'Create a new workspace',
|
|
22
27
|
},
|
|
23
28
|
{
|
|
@@ -28,11 +33,18 @@ export const workspaceCommand = createCommand({
|
|
|
28
33
|
command: getCommand('coder workspace delete ws_abc123'),
|
|
29
34
|
description: 'Delete a workspace',
|
|
30
35
|
},
|
|
36
|
+
{
|
|
37
|
+
command: getCommand('coder workspace validate-dependencies git,nodejs'),
|
|
38
|
+
description: 'Validate workspace dependencies',
|
|
39
|
+
},
|
|
31
40
|
],
|
|
32
41
|
subcommands: [
|
|
33
42
|
listSubcommand,
|
|
34
43
|
createWorkspaceSubcommand,
|
|
35
44
|
getWorkspaceSubcommand,
|
|
45
|
+
updateWorkspaceSubcommand,
|
|
46
|
+
refreshWorkspaceSnapshotSubcommand,
|
|
47
|
+
validateWorkspaceDependenciesSubcommand,
|
|
36
48
|
deleteWorkspaceSubcommand,
|
|
37
49
|
],
|
|
38
50
|
});
|
|
@@ -83,6 +83,8 @@ export const listSubcommand = createSubcommand({
|
|
|
83
83
|
Name: w.name,
|
|
84
84
|
Scope: w.scope,
|
|
85
85
|
Repos: String(w.repoCount),
|
|
86
|
+
Deps: String(w.dependencies?.length ?? 0),
|
|
87
|
+
Snapshot: w.snapshot?.status ?? '',
|
|
86
88
|
Selections: String(w.selectionCount),
|
|
87
89
|
Created: formatRelativeTime(w.createdAt),
|
|
88
90
|
})),
|
|
@@ -91,6 +93,8 @@ export const listSubcommand = createSubcommand({
|
|
|
91
93
|
{ name: 'Name', alignment: 'left' },
|
|
92
94
|
{ name: 'Scope', alignment: 'center' },
|
|
93
95
|
{ name: 'Repos', alignment: 'right' },
|
|
96
|
+
{ name: 'Deps', alignment: 'right' },
|
|
97
|
+
{ name: 'Snapshot', alignment: 'left' },
|
|
94
98
|
{ name: 'Selections', alignment: 'right' },
|
|
95
99
|
{ name: 'Created', alignment: 'right' },
|
|
96
100
|
]
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { APIError, ValidationOutputError } from '@agentuity/core';
|
|
3
|
+
import { CoderClient } from '@agentuity/core/coder';
|
|
4
|
+
import { createSubcommand } from '../../../types';
|
|
5
|
+
import * as tui from '../../../tui';
|
|
6
|
+
import { getCommand } from '../../../command-prefix';
|
|
7
|
+
import { ErrorCode } from '../../../errors';
|
|
8
|
+
import { printWorkspaceSummary } from './common';
|
|
9
|
+
|
|
10
|
+
export const refreshWorkspaceSnapshotSubcommand = createSubcommand({
|
|
11
|
+
name: 'refresh',
|
|
12
|
+
aliases: ['snapshot-refresh', 'rebuild'],
|
|
13
|
+
description: 'Refresh a Coder workspace snapshot',
|
|
14
|
+
tags: ['mutating', 'requires-auth'],
|
|
15
|
+
requires: { auth: true, org: true },
|
|
16
|
+
examples: [
|
|
17
|
+
{
|
|
18
|
+
command: getCommand('coder workspace refresh ws_abc123'),
|
|
19
|
+
description: 'Queue a workspace snapshot refresh',
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
schema: {
|
|
23
|
+
args: z.object({
|
|
24
|
+
workspaceId: z.string().describe('Workspace ID to refresh'),
|
|
25
|
+
}),
|
|
26
|
+
options: z.object({
|
|
27
|
+
url: z.string().optional().describe('Coder API URL override'),
|
|
28
|
+
}),
|
|
29
|
+
},
|
|
30
|
+
async handler(ctx) {
|
|
31
|
+
const { args, opts, options } = ctx;
|
|
32
|
+
const client = new CoderClient({
|
|
33
|
+
apiKey: ctx.auth.apiKey,
|
|
34
|
+
url: opts?.url,
|
|
35
|
+
orgId: ctx.orgId,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
const workspace = await client.refreshWorkspaceSnapshot(args.workspaceId);
|
|
40
|
+
if (options.json) {
|
|
41
|
+
return workspace;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
tui.success(`Workspace ${workspace.id} snapshot refresh queued.`);
|
|
45
|
+
tui.newline();
|
|
46
|
+
printWorkspaceSummary(workspace);
|
|
47
|
+
return workspace;
|
|
48
|
+
} catch (err) {
|
|
49
|
+
if (err instanceof ValidationOutputError) {
|
|
50
|
+
ctx.logger.trace('Validation response URL: %s', err.url ?? 'unknown');
|
|
51
|
+
ctx.logger.trace('Validation issues: %s', JSON.stringify(err.issues, null, 2));
|
|
52
|
+
}
|
|
53
|
+
if (err instanceof APIError && err.status >= 400 && err.status < 500) {
|
|
54
|
+
tui.fatal(
|
|
55
|
+
`Failed to refresh workspace snapshot: ${err.message}`,
|
|
56
|
+
ErrorCode.VALIDATION_FAILED
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
60
|
+
tui.fatal(`Failed to refresh workspace snapshot: ${msg}`, ErrorCode.NETWORK_ERROR);
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
});
|