@agentuity/cli 0.1.9 → 0.1.10
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/README.md +2 -2
- package/bin/cli.ts +8 -0
- package/dist/cache/index.d.ts +2 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +2 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/resource-region.d.ts +46 -0
- package/dist/cache/resource-region.d.ts.map +1 -0
- package/dist/cache/resource-region.js +115 -0
- package/dist/cache/resource-region.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +44 -32
- package/dist/cli.js.map +1 -1
- package/dist/cmd/ai/capabilities/show.d.ts.map +1 -1
- package/dist/cmd/ai/capabilities/show.js +12 -15
- package/dist/cmd/ai/capabilities/show.js.map +1 -1
- package/dist/cmd/ai/prompt/llm.js +5 -5
- package/dist/cmd/ai/prompt/llm.js.map +1 -1
- package/dist/cmd/auth/logout.d.ts.map +1 -1
- package/dist/cmd/auth/logout.js +5 -2
- package/dist/cmd/auth/logout.js.map +1 -1
- package/dist/cmd/build/ast.d.ts.map +1 -1
- package/dist/cmd/build/ast.js +87 -1
- package/dist/cmd/build/ast.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 +8 -3
- package/dist/cmd/build/vite/vite-asset-server-config.js.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server.js +5 -3
- package/dist/cmd/build/vite/vite-asset-server.js.map +1 -1
- package/dist/cmd/cloud/db/delete.d.ts.map +1 -1
- package/dist/cmd/cloud/db/delete.js +69 -11
- package/dist/cmd/cloud/db/delete.js.map +1 -1
- package/dist/cmd/cloud/db/get.d.ts.map +1 -1
- package/dist/cmd/cloud/db/get.js +23 -7
- package/dist/cmd/cloud/db/get.js.map +1 -1
- package/dist/cmd/cloud/db/list.d.ts.map +1 -1
- package/dist/cmd/cloud/db/list.js +15 -7
- package/dist/cmd/cloud/db/list.js.map +1 -1
- package/dist/cmd/cloud/db/logs.d.ts.map +1 -1
- package/dist/cmd/cloud/db/logs.js +24 -4
- package/dist/cmd/cloud/db/logs.js.map +1 -1
- package/dist/cmd/cloud/deploy.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.js +38 -0
- package/dist/cmd/cloud/deploy.js.map +1 -1
- package/dist/cmd/cloud/env/delete.d.ts.map +1 -1
- package/dist/cmd/cloud/env/delete.js +30 -13
- package/dist/cmd/cloud/env/delete.js.map +1 -1
- package/dist/cmd/cloud/env/get.d.ts.map +1 -1
- package/dist/cmd/cloud/env/get.js +27 -30
- package/dist/cmd/cloud/env/get.js.map +1 -1
- package/dist/cmd/cloud/env/import.d.ts.map +1 -1
- package/dist/cmd/cloud/env/import.js +41 -48
- package/dist/cmd/cloud/env/import.js.map +1 -1
- package/dist/cmd/cloud/env/index.d.ts.map +1 -1
- package/dist/cmd/cloud/env/index.js +6 -2
- package/dist/cmd/cloud/env/index.js.map +1 -1
- package/dist/cmd/cloud/env/list.d.ts.map +1 -1
- package/dist/cmd/cloud/env/list.js +51 -28
- package/dist/cmd/cloud/env/list.js.map +1 -1
- package/dist/cmd/cloud/env/pull.d.ts.map +1 -1
- package/dist/cmd/cloud/env/pull.js +3 -3
- package/dist/cmd/cloud/env/pull.js.map +1 -1
- package/dist/cmd/cloud/env/push.d.ts.map +1 -1
- package/dist/cmd/cloud/env/push.js +31 -11
- package/dist/cmd/cloud/env/push.js.map +1 -1
- package/dist/cmd/cloud/env/set.d.ts.map +1 -1
- package/dist/cmd/cloud/env/set.js +41 -26
- package/dist/cmd/cloud/env/set.js.map +1 -1
- package/dist/cmd/cloud/index.d.ts.map +1 -1
- package/dist/cmd/cloud/index.js +0 -2
- package/dist/cmd/cloud/index.js.map +1 -1
- package/dist/cmd/cloud/region-lookup.d.ts +18 -0
- package/dist/cmd/cloud/region-lookup.d.ts.map +1 -0
- package/dist/cmd/cloud/region-lookup.js +64 -0
- package/dist/cmd/cloud/region-lookup.js.map +1 -0
- package/dist/cmd/cloud/sandbox/cp.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/cp.js +5 -3
- package/dist/cmd/cloud/sandbox/cp.js.map +1 -1
- package/dist/cmd/cloud/sandbox/create.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/create.js +43 -6
- 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 +5 -3
- package/dist/cmd/cloud/sandbox/delete.js.map +1 -1
- package/dist/cmd/cloud/sandbox/download.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/download.js +4 -3
- package/dist/cmd/cloud/sandbox/download.js.map +1 -1
- package/dist/cmd/cloud/sandbox/env.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/env.js +4 -3
- 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 +4 -3
- package/dist/cmd/cloud/sandbox/exec.js.map +1 -1
- package/dist/cmd/cloud/sandbox/execution/get.js +4 -4
- package/dist/cmd/cloud/sandbox/execution/get.js.map +1 -1
- package/dist/cmd/cloud/sandbox/execution/index.js +1 -1
- package/dist/cmd/cloud/sandbox/execution/index.js.map +1 -1
- package/dist/cmd/cloud/sandbox/execution/list.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/execution/list.js +4 -3
- package/dist/cmd/cloud/sandbox/execution/list.js.map +1 -1
- package/dist/cmd/cloud/sandbox/get.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/get.js +9 -4
- package/dist/cmd/cloud/sandbox/get.js.map +1 -1
- package/dist/cmd/cloud/sandbox/index.js +1 -1
- package/dist/cmd/cloud/sandbox/index.js.map +1 -1
- package/dist/cmd/cloud/sandbox/list.js +4 -4
- package/dist/cmd/cloud/sandbox/list.js.map +1 -1
- package/dist/cmd/cloud/sandbox/ls.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/ls.js +4 -3
- package/dist/cmd/cloud/sandbox/ls.js.map +1 -1
- package/dist/cmd/cloud/sandbox/mkdir.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/mkdir.js +4 -3
- package/dist/cmd/cloud/sandbox/mkdir.js.map +1 -1
- package/dist/cmd/cloud/sandbox/rm.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/rm.js +4 -3
- package/dist/cmd/cloud/sandbox/rm.js.map +1 -1
- package/dist/cmd/cloud/sandbox/rmdir.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/rmdir.js +4 -3
- package/dist/cmd/cloud/sandbox/rmdir.js.map +1 -1
- package/dist/cmd/cloud/sandbox/run.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/run.js +44 -6
- package/dist/cmd/cloud/sandbox/run.js.map +1 -1
- package/dist/cmd/cloud/sandbox/runtime/index.js +1 -1
- package/dist/cmd/cloud/sandbox/runtime/index.js.map +1 -1
- package/dist/cmd/cloud/sandbox/runtime/list.js +4 -4
- package/dist/cmd/cloud/sandbox/runtime/list.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 -3
- package/dist/cmd/cloud/sandbox/snapshot/create.js.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/delete.js +4 -4
- package/dist/cmd/cloud/sandbox/snapshot/delete.js.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/get.js +4 -4
- package/dist/cmd/cloud/sandbox/snapshot/get.js.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/index.js +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/index.js.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/list.js +4 -4
- package/dist/cmd/cloud/sandbox/snapshot/list.js.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/tag.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/tag.js +4 -4
- package/dist/cmd/cloud/sandbox/snapshot/tag.js.map +1 -1
- package/dist/cmd/cloud/sandbox/upload.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/upload.js +4 -3
- package/dist/cmd/cloud/sandbox/upload.js.map +1 -1
- package/dist/cmd/cloud/sandbox/util.d.ts +13 -0
- package/dist/cmd/cloud/sandbox/util.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/util.js +40 -1
- package/dist/cmd/cloud/sandbox/util.js.map +1 -1
- package/dist/cmd/cloud/scp/download.d.ts.map +1 -1
- package/dist/cmd/cloud/scp/download.js +6 -2
- package/dist/cmd/cloud/scp/download.js.map +1 -1
- package/dist/cmd/cloud/scp/upload.d.ts.map +1 -1
- package/dist/cmd/cloud/scp/upload.js +6 -2
- package/dist/cmd/cloud/scp/upload.js.map +1 -1
- package/dist/cmd/cloud/session/get.js +4 -4
- package/dist/cmd/cloud/session/get.js.map +1 -1
- package/dist/cmd/cloud/session/list.js +4 -4
- package/dist/cmd/cloud/session/list.js.map +1 -1
- package/dist/cmd/cloud/ssh.d.ts.map +1 -1
- package/dist/cmd/cloud/ssh.js +7 -2
- package/dist/cmd/cloud/ssh.js.map +1 -1
- package/dist/cmd/cloud/storage/delete.d.ts.map +1 -1
- package/dist/cmd/cloud/storage/delete.js +46 -10
- package/dist/cmd/cloud/storage/delete.js.map +1 -1
- package/dist/cmd/cloud/storage/download.d.ts.map +1 -1
- package/dist/cmd/cloud/storage/download.js +19 -6
- package/dist/cmd/cloud/storage/download.js.map +1 -1
- package/dist/cmd/cloud/storage/get.d.ts.map +1 -1
- package/dist/cmd/cloud/storage/get.js +19 -6
- package/dist/cmd/cloud/storage/get.js.map +1 -1
- package/dist/cmd/cloud/storage/list.d.ts.map +1 -1
- package/dist/cmd/cloud/storage/list.js +17 -7
- package/dist/cmd/cloud/storage/list.js.map +1 -1
- package/dist/cmd/cloud/storage/upload.d.ts.map +1 -1
- package/dist/cmd/cloud/storage/upload.js +19 -6
- package/dist/cmd/cloud/storage/upload.js.map +1 -1
- package/dist/cmd/cloud/thread/delete.js +4 -4
- package/dist/cmd/cloud/thread/delete.js.map +1 -1
- package/dist/cmd/cloud/thread/get.js +4 -4
- package/dist/cmd/cloud/thread/get.js.map +1 -1
- package/dist/cmd/cloud/thread/list.js +4 -4
- package/dist/cmd/cloud/thread/list.js.map +1 -1
- package/dist/cmd/project/auth/init.d.ts.map +1 -1
- package/dist/cmd/project/auth/init.js +6 -3
- package/dist/cmd/project/auth/init.js.map +1 -1
- package/dist/cmd/project/auth/shared.d.ts +6 -2
- package/dist/cmd/project/auth/shared.d.ts.map +1 -1
- package/dist/cmd/project/auth/shared.js +40 -12
- package/dist/cmd/project/auth/shared.js.map +1 -1
- package/dist/config.d.ts +37 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +51 -8
- package/dist/config.js.map +1 -1
- package/dist/env-util.d.ts +25 -2
- package/dist/env-util.d.ts.map +1 -1
- package/dist/env-util.js +44 -4
- package/dist/env-util.js.map +1 -1
- package/dist/utils/apt-validator.d.ts +20 -0
- package/dist/utils/apt-validator.d.ts.map +1 -0
- package/dist/utils/apt-validator.js +157 -0
- package/dist/utils/apt-validator.js.map +1 -0
- package/package.json +6 -6
- package/src/cache/index.ts +11 -0
- package/src/cache/resource-region.ts +183 -0
- package/src/cli.ts +47 -38
- package/src/cmd/ai/capabilities/show.ts +12 -15
- package/src/cmd/ai/prompt/llm.ts +5 -5
- package/src/cmd/auth/logout.ts +5 -2
- package/src/cmd/build/ast.ts +160 -1
- package/src/cmd/build/vite/vite-asset-server-config.ts +7 -3
- package/src/cmd/build/vite/vite-asset-server.ts +6 -3
- package/src/cmd/cloud/db/delete.ts +83 -11
- package/src/cmd/cloud/db/get.ts +29 -7
- package/src/cmd/cloud/db/list.ts +16 -7
- package/src/cmd/cloud/db/logs.ts +33 -4
- package/src/cmd/cloud/deploy.ts +49 -0
- package/src/cmd/cloud/env/delete.ts +36 -12
- package/src/cmd/cloud/env/get.ts +28 -27
- package/src/cmd/cloud/env/import.ts +43 -56
- package/src/cmd/cloud/env/index.ts +6 -2
- package/src/cmd/cloud/env/list.ts +57 -30
- package/src/cmd/cloud/env/pull.ts +9 -3
- package/src/cmd/cloud/env/push.ts +44 -11
- package/src/cmd/cloud/env/set.ts +49 -30
- package/src/cmd/cloud/index.ts +0 -2
- package/src/cmd/cloud/region-lookup.ts +89 -0
- package/src/cmd/cloud/sandbox/cp.ts +5 -3
- package/src/cmd/cloud/sandbox/create.ts +50 -6
- package/src/cmd/cloud/sandbox/delete.ts +6 -3
- package/src/cmd/cloud/sandbox/download.ts +4 -3
- package/src/cmd/cloud/sandbox/env.ts +4 -3
- package/src/cmd/cloud/sandbox/exec.ts +4 -3
- package/src/cmd/cloud/sandbox/execution/get.ts +4 -4
- package/src/cmd/cloud/sandbox/execution/index.ts +1 -1
- package/src/cmd/cloud/sandbox/execution/list.ts +4 -3
- package/src/cmd/cloud/sandbox/get.ts +10 -4
- package/src/cmd/cloud/sandbox/index.ts +1 -1
- package/src/cmd/cloud/sandbox/list.ts +4 -4
- package/src/cmd/cloud/sandbox/ls.ts +4 -3
- package/src/cmd/cloud/sandbox/mkdir.ts +4 -3
- package/src/cmd/cloud/sandbox/rm.ts +4 -3
- package/src/cmd/cloud/sandbox/rmdir.ts +4 -3
- package/src/cmd/cloud/sandbox/run.ts +51 -6
- package/src/cmd/cloud/sandbox/runtime/index.ts +1 -1
- package/src/cmd/cloud/sandbox/runtime/list.ts +4 -4
- package/src/cmd/cloud/sandbox/snapshot/create.ts +11 -5
- package/src/cmd/cloud/sandbox/snapshot/delete.ts +4 -4
- package/src/cmd/cloud/sandbox/snapshot/get.ts +4 -4
- package/src/cmd/cloud/sandbox/snapshot/index.ts +1 -1
- package/src/cmd/cloud/sandbox/snapshot/list.ts +4 -4
- package/src/cmd/cloud/sandbox/snapshot/tag.ts +7 -5
- package/src/cmd/cloud/sandbox/upload.ts +4 -3
- package/src/cmd/cloud/sandbox/util.ts +60 -1
- package/src/cmd/cloud/scp/download.ts +14 -2
- package/src/cmd/cloud/scp/upload.ts +14 -2
- package/src/cmd/cloud/session/get.ts +4 -4
- package/src/cmd/cloud/session/list.ts +4 -4
- package/src/cmd/cloud/ssh.ts +15 -2
- package/src/cmd/cloud/storage/delete.ts +61 -10
- package/src/cmd/cloud/storage/download.ts +31 -6
- package/src/cmd/cloud/storage/get.ts +31 -6
- package/src/cmd/cloud/storage/list.ts +18 -7
- package/src/cmd/cloud/storage/upload.ts +31 -6
- package/src/cmd/cloud/thread/delete.ts +4 -4
- package/src/cmd/cloud/thread/get.ts +4 -4
- package/src/cmd/cloud/thread/list.ts +4 -4
- package/src/cmd/project/auth/init.ts +7 -3
- package/src/cmd/project/auth/shared.ts +52 -13
- package/src/config.ts +64 -8
- package/src/env-util.ts +50 -5
- package/src/utils/apt-validator.ts +215 -0
- package/dist/cmd/cloud/secret/delete.d.ts +0 -2
- package/dist/cmd/cloud/secret/delete.d.ts.map +0 -1
- package/dist/cmd/cloud/secret/delete.js +0 -53
- package/dist/cmd/cloud/secret/delete.js.map +0 -1
- package/dist/cmd/cloud/secret/get.d.ts +0 -2
- package/dist/cmd/cloud/secret/get.d.ts.map +0 -1
- package/dist/cmd/cloud/secret/get.js +0 -73
- package/dist/cmd/cloud/secret/get.js.map +0 -1
- package/dist/cmd/cloud/secret/import.d.ts +0 -2
- package/dist/cmd/cloud/secret/import.d.ts.map +0 -1
- package/dist/cmd/cloud/secret/import.js +0 -91
- package/dist/cmd/cloud/secret/import.js.map +0 -1
- package/dist/cmd/cloud/secret/index.d.ts +0 -3
- package/dist/cmd/cloud/secret/index.d.ts.map +0 -1
- package/dist/cmd/cloud/secret/index.js +0 -33
- package/dist/cmd/cloud/secret/index.js.map +0 -1
- package/dist/cmd/cloud/secret/list.d.ts +0 -2
- package/dist/cmd/cloud/secret/list.d.ts.map +0 -1
- package/dist/cmd/cloud/secret/list.js +0 -65
- package/dist/cmd/cloud/secret/list.js.map +0 -1
- package/dist/cmd/cloud/secret/pull.d.ts +0 -2
- package/dist/cmd/cloud/secret/pull.d.ts.map +0 -1
- package/dist/cmd/cloud/secret/pull.js +0 -82
- package/dist/cmd/cloud/secret/pull.js.map +0 -1
- package/dist/cmd/cloud/secret/push.d.ts +0 -2
- package/dist/cmd/cloud/secret/push.d.ts.map +0 -1
- package/dist/cmd/cloud/secret/push.js +0 -61
- package/dist/cmd/cloud/secret/push.js.map +0 -1
- package/dist/cmd/cloud/secret/set.d.ts +0 -2
- package/dist/cmd/cloud/secret/set.d.ts.map +0 -1
- package/dist/cmd/cloud/secret/set.js +0 -63
- package/dist/cmd/cloud/secret/set.js.map +0 -1
- package/src/cmd/cloud/secret/delete.ts +0 -65
- package/src/cmd/cloud/secret/get.ts +0 -77
- package/src/cmd/cloud/secret/import.ts +0 -110
- package/src/cmd/cloud/secret/index.ts +0 -33
- package/src/cmd/cloud/secret/list.ts +0 -70
- package/src/cmd/cloud/secret/pull.ts +0 -92
- package/src/cmd/cloud/secret/push.ts +0 -69
- package/src/cmd/cloud/secret/set.ts +0 -76
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { StructuredError } from '@agentuity/core';
|
|
2
|
+
import { getAppBaseURL } from '@agentuity/server';
|
|
3
|
+
import { getUserAgent } from '../api';
|
|
4
|
+
import { getDefaultConfigDir } from '../config';
|
|
5
|
+
import { join, dirname } from 'node:path';
|
|
6
|
+
import { mkdir } from 'node:fs/promises';
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
const AptValidationError = StructuredError('AptValidationError');
|
|
9
|
+
const AptValidationAPIError = StructuredError('AptValidationAPIError')();
|
|
10
|
+
const AptValidationResponseError = StructuredError('AptValidationResponseError')();
|
|
11
|
+
const InvalidPackageSchema = z.object({
|
|
12
|
+
package: z.string(),
|
|
13
|
+
error: z.string(),
|
|
14
|
+
requestedVersion: z.string().optional(),
|
|
15
|
+
availableVersions: z.array(z.string()).optional(),
|
|
16
|
+
searchUrl: z.string(),
|
|
17
|
+
});
|
|
18
|
+
const ValidateAptDependenciesResponseSchema = z.object({
|
|
19
|
+
success: z.boolean(),
|
|
20
|
+
data: z
|
|
21
|
+
.object({
|
|
22
|
+
valid: z.array(z.string()),
|
|
23
|
+
invalid: z.array(InvalidPackageSchema),
|
|
24
|
+
})
|
|
25
|
+
.optional(),
|
|
26
|
+
message: z.string().optional(),
|
|
27
|
+
});
|
|
28
|
+
const REQUEST_TIMEOUT_MS = 30000; // 30 seconds client-side timeout
|
|
29
|
+
const CacheEntrySchema = z.object({
|
|
30
|
+
timestamp: z.number(),
|
|
31
|
+
});
|
|
32
|
+
const ValidationCacheSchema = z.object({
|
|
33
|
+
version: z.number(),
|
|
34
|
+
entries: z.record(z.string(), CacheEntrySchema),
|
|
35
|
+
});
|
|
36
|
+
const CACHE_VERSION = 1;
|
|
37
|
+
const CACHE_TTL_MS = 90 * 24 * 60 * 60 * 1000; // 90 days
|
|
38
|
+
function getCachePath() {
|
|
39
|
+
return join(getDefaultConfigDir(), 'dependency-validation.json');
|
|
40
|
+
}
|
|
41
|
+
async function loadCache(logger) {
|
|
42
|
+
const cachePath = getCachePath();
|
|
43
|
+
try {
|
|
44
|
+
const file = Bun.file(cachePath);
|
|
45
|
+
if (await file.exists()) {
|
|
46
|
+
const content = await file.json();
|
|
47
|
+
const parsed = ValidationCacheSchema.safeParse(content);
|
|
48
|
+
if (parsed.success && parsed.data.version === CACHE_VERSION) {
|
|
49
|
+
return parsed.data;
|
|
50
|
+
}
|
|
51
|
+
logger.debug('Cache invalid or version mismatch, starting fresh');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
logger.debug('Failed to load validation cache: %s', err);
|
|
56
|
+
}
|
|
57
|
+
return { version: CACHE_VERSION, entries: {} };
|
|
58
|
+
}
|
|
59
|
+
async function saveCache(cache, logger) {
|
|
60
|
+
const cachePath = getCachePath();
|
|
61
|
+
try {
|
|
62
|
+
await mkdir(dirname(cachePath), { recursive: true });
|
|
63
|
+
await Bun.write(cachePath, JSON.stringify(cache, null, 2));
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
logger.debug('Failed to save validation cache: %s', err);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function isCacheEntryValid(entry) {
|
|
70
|
+
return Date.now() - entry.timestamp < CACHE_TTL_MS;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Validate apt dependencies against the Debian package repository.
|
|
74
|
+
* Uses a local cache to avoid redundant API calls.
|
|
75
|
+
* Calls the app API which checks packages against snapshot.debian.org.
|
|
76
|
+
*/
|
|
77
|
+
export async function validateAptDependencies(packages, region, config, logger) {
|
|
78
|
+
if (packages.length === 0) {
|
|
79
|
+
return { valid: [], invalid: [] };
|
|
80
|
+
}
|
|
81
|
+
const cache = await loadCache(logger);
|
|
82
|
+
const now = Date.now();
|
|
83
|
+
const cachedValid = [];
|
|
84
|
+
const uncachedPackages = [];
|
|
85
|
+
// Check cache for each package (only valid packages are cached)
|
|
86
|
+
for (const pkg of packages) {
|
|
87
|
+
const entry = cache.entries[pkg];
|
|
88
|
+
if (entry && isCacheEntryValid(entry)) {
|
|
89
|
+
cachedValid.push(pkg);
|
|
90
|
+
logger.debug('Cache hit (valid): %s', pkg);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
uncachedPackages.push(pkg);
|
|
94
|
+
logger.debug('Cache miss: %s', pkg);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// If all packages are cached, return immediately
|
|
98
|
+
if (uncachedPackages.length === 0) {
|
|
99
|
+
logger.debug('All %d packages found in cache', packages.length);
|
|
100
|
+
return { valid: cachedValid, invalid: [] };
|
|
101
|
+
}
|
|
102
|
+
logger.debug('Validating %d uncached packages (%d cached)', uncachedPackages.length, packages.length - uncachedPackages.length);
|
|
103
|
+
const appBaseUrl = getAppBaseURL(region, config?.overrides);
|
|
104
|
+
const url = `${appBaseUrl}/api/cli/validate/apt-dependencies`;
|
|
105
|
+
const response = await fetch(url, {
|
|
106
|
+
method: 'POST',
|
|
107
|
+
headers: {
|
|
108
|
+
'Content-Type': 'application/json',
|
|
109
|
+
'User-Agent': getUserAgent(config),
|
|
110
|
+
},
|
|
111
|
+
body: JSON.stringify({ packages: uncachedPackages }),
|
|
112
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
113
|
+
});
|
|
114
|
+
if (!response.ok) {
|
|
115
|
+
const text = await response.text();
|
|
116
|
+
throw new AptValidationAPIError({
|
|
117
|
+
message: `Failed to validate apt dependencies: HTTP ${response.status}`,
|
|
118
|
+
status: response.status,
|
|
119
|
+
body: text,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
let json;
|
|
123
|
+
try {
|
|
124
|
+
json = await response.json();
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
throw new AptValidationResponseError({
|
|
128
|
+
message: 'Invalid JSON in API response',
|
|
129
|
+
parseError: err instanceof Error ? err.message : String(err),
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
const parsed = ValidateAptDependenciesResponseSchema.safeParse(json);
|
|
133
|
+
if (!parsed.success) {
|
|
134
|
+
throw new AptValidationResponseError({
|
|
135
|
+
message: 'Invalid API response structure',
|
|
136
|
+
parseError: parsed.error.message,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
const result = parsed.data;
|
|
140
|
+
if (!result.success || !result.data) {
|
|
141
|
+
throw new AptValidationError({
|
|
142
|
+
message: result.message ?? 'Failed to validate apt dependencies',
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
// Update cache with valid results only (don't cache invalid packages)
|
|
146
|
+
for (const pkg of result.data.valid) {
|
|
147
|
+
cache.entries[pkg] = { timestamp: now };
|
|
148
|
+
}
|
|
149
|
+
await saveCache(cache, logger);
|
|
150
|
+
logger.debug('Apt validation complete: %d valid, %d invalid (from API)', result.data.valid.length, result.data.invalid.length);
|
|
151
|
+
// Combine cached and fresh results
|
|
152
|
+
return {
|
|
153
|
+
valid: [...cachedValid, ...result.data.valid],
|
|
154
|
+
invalid: result.data.invalid,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=apt-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apt-validator.js","sourceRoot":"","sources":["../../src/utils/apt-validator.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentuity/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"author": "Agentuity employees and contributors",
|
|
6
6
|
"type": "module",
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
"prepublishOnly": "bun run clean && bun run build"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@agentuity/auth": "0.1.
|
|
44
|
-
"@agentuity/core": "0.1.
|
|
45
|
-
"@agentuity/server": "0.1.
|
|
43
|
+
"@agentuity/auth": "0.1.10",
|
|
44
|
+
"@agentuity/core": "0.1.10",
|
|
45
|
+
"@agentuity/server": "0.1.10",
|
|
46
46
|
"@datasert/cronjs-parser": "^1.4.0",
|
|
47
47
|
"@terascope/fetch-github-release": "^2.2.1",
|
|
48
48
|
"@vitejs/plugin-react": "^5.1.2",
|
|
@@ -60,10 +60,10 @@
|
|
|
60
60
|
"typescript": "^5.9.0",
|
|
61
61
|
"vite": "^7.2.7",
|
|
62
62
|
"zod": "^4.3.5",
|
|
63
|
-
"@agentuity/frontend": "0.1.
|
|
63
|
+
"@agentuity/frontend": "0.1.10"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@agentuity/test-utils": "0.1.
|
|
66
|
+
"@agentuity/test-utils": "0.1.10",
|
|
67
67
|
"@types/adm-zip": "^0.5.7",
|
|
68
68
|
"@types/bun": "latest",
|
|
69
69
|
"@types/tar-fs": "^2.0.4",
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { Database } from 'bun:sqlite';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { mkdir } from 'node:fs/promises';
|
|
4
|
+
import { getDefaultConfigDir } from '../config';
|
|
5
|
+
|
|
6
|
+
const TTL_DAYS = 7;
|
|
7
|
+
const TTL_MS = TTL_DAYS * 24 * 60 * 60 * 1000;
|
|
8
|
+
|
|
9
|
+
let db: Database | null = null;
|
|
10
|
+
|
|
11
|
+
async function getDatabase(): Promise<Database> {
|
|
12
|
+
if (db) {
|
|
13
|
+
return db;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const configDir = getDefaultConfigDir();
|
|
17
|
+
await mkdir(configDir, { recursive: true });
|
|
18
|
+
|
|
19
|
+
const dbPath = join(configDir, 'resource.db');
|
|
20
|
+
db = new Database(dbPath);
|
|
21
|
+
|
|
22
|
+
db.run(`
|
|
23
|
+
CREATE TABLE IF NOT EXISTS resource_region_cache (
|
|
24
|
+
resource_type TEXT NOT NULL,
|
|
25
|
+
profile TEXT NOT NULL,
|
|
26
|
+
id TEXT NOT NULL,
|
|
27
|
+
region TEXT NOT NULL,
|
|
28
|
+
org_id TEXT,
|
|
29
|
+
last_updated INTEGER NOT NULL,
|
|
30
|
+
PRIMARY KEY (resource_type, profile, id)
|
|
31
|
+
)
|
|
32
|
+
`);
|
|
33
|
+
|
|
34
|
+
db.run(`
|
|
35
|
+
CREATE INDEX IF NOT EXISTS idx_last_updated
|
|
36
|
+
ON resource_region_cache(last_updated)
|
|
37
|
+
`);
|
|
38
|
+
|
|
39
|
+
return db;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function pruneOldEntries(database: Database): void {
|
|
43
|
+
const cutoff = Date.now() - TTL_MS;
|
|
44
|
+
database.run('DELETE FROM resource_region_cache WHERE last_updated < ?', [cutoff]);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export type ResourceType = 'sandbox' | 'bucket' | 'db' | 'project' | 'deployment';
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Resource info returned from cache lookup
|
|
51
|
+
*/
|
|
52
|
+
export interface ResourceInfo {
|
|
53
|
+
region: string;
|
|
54
|
+
orgId?: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Get the cached info (region and orgId) for a resource.
|
|
59
|
+
* Returns null if not found or expired.
|
|
60
|
+
*/
|
|
61
|
+
export async function getResourceInfo(
|
|
62
|
+
type: ResourceType,
|
|
63
|
+
profile: string,
|
|
64
|
+
id: string
|
|
65
|
+
): Promise<ResourceInfo | null> {
|
|
66
|
+
const database = await getDatabase();
|
|
67
|
+
const cutoff = Date.now() - TTL_MS;
|
|
68
|
+
|
|
69
|
+
const row = database
|
|
70
|
+
.query<
|
|
71
|
+
{ region: string; org_id: string | null; last_updated: number },
|
|
72
|
+
[string, string, string]
|
|
73
|
+
>('SELECT region, org_id, last_updated FROM resource_region_cache WHERE resource_type = ? AND profile = ? AND id = ?')
|
|
74
|
+
.get(type, profile, id);
|
|
75
|
+
|
|
76
|
+
if (!row) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Check if entry is expired
|
|
81
|
+
if (row.last_updated < cutoff) {
|
|
82
|
+
// Remove stale entry
|
|
83
|
+
database.run(
|
|
84
|
+
'DELETE FROM resource_region_cache WHERE resource_type = ? AND profile = ? AND id = ?',
|
|
85
|
+
[type, profile, id]
|
|
86
|
+
);
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
region: row.region,
|
|
92
|
+
orgId: row.org_id ?? undefined,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Get the cached region for a resource.
|
|
98
|
+
* Returns null if not found or expired.
|
|
99
|
+
* @deprecated Use getResourceInfo() to get both region and orgId
|
|
100
|
+
*/
|
|
101
|
+
export async function getResourceRegion(
|
|
102
|
+
type: ResourceType,
|
|
103
|
+
profile: string,
|
|
104
|
+
id: string
|
|
105
|
+
): Promise<string | null> {
|
|
106
|
+
const info = await getResourceInfo(type, profile, id);
|
|
107
|
+
return info?.region ?? null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Set the cached info for a resource.
|
|
112
|
+
* Uses INSERT OR REPLACE to upsert.
|
|
113
|
+
*/
|
|
114
|
+
export async function setResourceInfo(
|
|
115
|
+
type: ResourceType,
|
|
116
|
+
profile: string,
|
|
117
|
+
id: string,
|
|
118
|
+
region: string,
|
|
119
|
+
orgId?: string
|
|
120
|
+
): Promise<void> {
|
|
121
|
+
const database = await getDatabase();
|
|
122
|
+
|
|
123
|
+
pruneOldEntries(database);
|
|
124
|
+
|
|
125
|
+
database.run(
|
|
126
|
+
`INSERT OR REPLACE INTO resource_region_cache
|
|
127
|
+
(resource_type, profile, id, region, org_id, last_updated)
|
|
128
|
+
VALUES (?, ?, ?, ?, ?, ?)`,
|
|
129
|
+
[type, profile, id, region, orgId ?? null, Date.now()]
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Set the cached region for a resource.
|
|
135
|
+
* Uses INSERT OR REPLACE to upsert.
|
|
136
|
+
* @deprecated Use setResourceInfo() to set both region and orgId
|
|
137
|
+
*/
|
|
138
|
+
export async function setResourceRegion(
|
|
139
|
+
type: ResourceType,
|
|
140
|
+
profile: string,
|
|
141
|
+
id: string,
|
|
142
|
+
region: string
|
|
143
|
+
): Promise<void> {
|
|
144
|
+
await setResourceInfo(type, profile, id, region);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Delete the cached info for a resource.
|
|
149
|
+
* Called when a resource is deleted.
|
|
150
|
+
*/
|
|
151
|
+
export async function deleteResourceRegion(
|
|
152
|
+
type: ResourceType,
|
|
153
|
+
profile: string,
|
|
154
|
+
id: string
|
|
155
|
+
): Promise<void> {
|
|
156
|
+
const database = await getDatabase();
|
|
157
|
+
|
|
158
|
+
database.run(
|
|
159
|
+
'DELETE FROM resource_region_cache WHERE resource_type = ? AND profile = ? AND id = ?',
|
|
160
|
+
[type, profile, id]
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Clear all cached entries for a specific profile.
|
|
166
|
+
* Useful when switching profiles or logging out.
|
|
167
|
+
*/
|
|
168
|
+
export async function clearProfileCache(profile: string): Promise<void> {
|
|
169
|
+
const database = await getDatabase();
|
|
170
|
+
|
|
171
|
+
database.run('DELETE FROM resource_region_cache WHERE profile = ?', [profile]);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Close the database connection.
|
|
176
|
+
* Should be called on CLI exit for clean shutdown.
|
|
177
|
+
*/
|
|
178
|
+
export function closeDatabase(): void {
|
|
179
|
+
if (db) {
|
|
180
|
+
db.close();
|
|
181
|
+
db = null;
|
|
182
|
+
}
|
|
183
|
+
}
|
package/src/cli.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mkdir } from 'node:fs/promises';
|
|
1
|
+
import { mkdir, unlink } from 'node:fs/promises';
|
|
2
2
|
import { homedir } from 'node:os';
|
|
3
3
|
import { resolve, join } from 'node:path';
|
|
4
4
|
import { Command } from 'commander';
|
|
@@ -369,7 +369,7 @@ function handleProjectConfigError(
|
|
|
369
369
|
error &&
|
|
370
370
|
typeof error === 'object' &&
|
|
371
371
|
'name' in error &&
|
|
372
|
-
error.name === '
|
|
372
|
+
error.name === 'ProjectConfigNotFoundException'
|
|
373
373
|
) {
|
|
374
374
|
exitWithError(
|
|
375
375
|
createError(ErrorCode.PROJECT_NOT_FOUND, 'Invalid project folder', undefined, [
|
|
@@ -685,91 +685,100 @@ async function getRegion(regions: RegionList): Promise<string> {
|
|
|
685
685
|
interface ResolveRegionOptions {
|
|
686
686
|
options: Record<string, unknown>;
|
|
687
687
|
apiClient: APIClientType;
|
|
688
|
-
|
|
688
|
+
profileName: string;
|
|
689
689
|
logger: Logger;
|
|
690
690
|
required: boolean;
|
|
691
691
|
region?: string;
|
|
692
692
|
}
|
|
693
693
|
|
|
694
|
-
const REGIONS_CACHE_FILE = 'regions.json';
|
|
695
694
|
const REGIONS_CACHE_MAX_AGE_MS = 5 * 24 * 60 * 60 * 1000; // 5 days
|
|
695
|
+
const LEGACY_REGIONS_CACHE_FILE = 'regions.json';
|
|
696
|
+
|
|
697
|
+
function getRegionsCacheFile(profileName: string): string {
|
|
698
|
+
return `regions-${profileName}.json`;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
async function removeLegacyRegionsCache(logger: Logger): Promise<void> {
|
|
702
|
+
try {
|
|
703
|
+
const legacyPath = join(getDefaultConfigDir(), LEGACY_REGIONS_CACHE_FILE);
|
|
704
|
+
const file = Bun.file(legacyPath);
|
|
705
|
+
if (await file.exists()) {
|
|
706
|
+
await unlink(legacyPath);
|
|
707
|
+
logger.trace('removed legacy regions cache file');
|
|
708
|
+
}
|
|
709
|
+
} catch {
|
|
710
|
+
// Ignore errors when removing legacy file
|
|
711
|
+
}
|
|
712
|
+
}
|
|
696
713
|
|
|
697
714
|
interface RegionsCacheData {
|
|
698
715
|
timestamp: number;
|
|
699
716
|
regions: RegionList;
|
|
700
|
-
apiUrl?: string; // Added to make cache profile-aware
|
|
701
717
|
}
|
|
702
718
|
|
|
703
|
-
async function getCachedRegions(
|
|
719
|
+
async function getCachedRegions(profileName: string, logger: Logger): Promise<RegionList | null> {
|
|
704
720
|
try {
|
|
705
|
-
|
|
721
|
+
// Clean up legacy single-file cache from older versions
|
|
722
|
+
await removeLegacyRegionsCache(logger);
|
|
723
|
+
|
|
724
|
+
const cachePath = join(getDefaultConfigDir(), getRegionsCacheFile(profileName));
|
|
706
725
|
const file = Bun.file(cachePath);
|
|
707
726
|
if (!(await file.exists())) {
|
|
708
727
|
return null;
|
|
709
728
|
}
|
|
710
729
|
const data: RegionsCacheData = await file.json();
|
|
711
|
-
// Check if cache is for the same API URL (profile-aware)
|
|
712
|
-
if (data.apiUrl && data.apiUrl !== apiUrl) {
|
|
713
|
-
logger.trace(
|
|
714
|
-
'regions cache is for different API URL (cached: %s, current: %s)',
|
|
715
|
-
data.apiUrl,
|
|
716
|
-
apiUrl
|
|
717
|
-
);
|
|
718
|
-
return null;
|
|
719
|
-
}
|
|
720
730
|
const age = Date.now() - data.timestamp;
|
|
721
731
|
if (age > REGIONS_CACHE_MAX_AGE_MS) {
|
|
722
|
-
logger.trace('regions cache expired (age: %dms)', age);
|
|
732
|
+
logger.trace('regions cache expired for profile %s (age: %dms)', profileName, age);
|
|
723
733
|
return null;
|
|
724
734
|
}
|
|
725
|
-
logger.trace('using cached regions (age: %dms)', age);
|
|
735
|
+
logger.trace('using cached regions for profile %s (age: %dms)', profileName, age);
|
|
726
736
|
return data.regions;
|
|
727
737
|
} catch (error) {
|
|
728
|
-
logger.trace('failed to read regions cache: %s', error);
|
|
738
|
+
logger.trace('failed to read regions cache for profile %s: %s', profileName, error);
|
|
729
739
|
return null;
|
|
730
740
|
}
|
|
731
741
|
}
|
|
732
742
|
|
|
733
743
|
async function saveRegionsCache(
|
|
734
|
-
|
|
744
|
+
profileName: string,
|
|
735
745
|
regions: RegionList,
|
|
736
746
|
logger: Logger
|
|
737
747
|
): Promise<void> {
|
|
738
748
|
try {
|
|
739
749
|
const cacheDir = getDefaultConfigDir();
|
|
740
750
|
await mkdir(cacheDir, { recursive: true });
|
|
741
|
-
const cachePath = join(cacheDir,
|
|
751
|
+
const cachePath = join(cacheDir, getRegionsCacheFile(profileName));
|
|
742
752
|
const data: RegionsCacheData = {
|
|
743
753
|
timestamp: Date.now(),
|
|
744
754
|
regions,
|
|
745
|
-
apiUrl,
|
|
746
755
|
};
|
|
747
756
|
await Bun.write(cachePath, JSON.stringify(data));
|
|
748
|
-
logger.trace('saved regions cache for %s',
|
|
757
|
+
logger.trace('saved regions cache for profile %s', profileName);
|
|
749
758
|
} catch (error) {
|
|
750
|
-
logger.trace('failed to save regions cache: %s', error);
|
|
759
|
+
logger.trace('failed to save regions cache for profile %s: %s', profileName, error);
|
|
751
760
|
}
|
|
752
761
|
}
|
|
753
762
|
|
|
754
763
|
async function fetchRegionsWithCache(
|
|
755
|
-
|
|
764
|
+
profileName: string,
|
|
756
765
|
apiClient: APIClientType,
|
|
757
766
|
logger: Logger
|
|
758
767
|
): Promise<RegionList> {
|
|
759
|
-
const cached = await getCachedRegions(
|
|
768
|
+
const cached = await getCachedRegions(profileName, logger);
|
|
760
769
|
if (cached) {
|
|
761
770
|
return cached;
|
|
762
771
|
}
|
|
763
772
|
const regions = await listRegions(apiClient);
|
|
764
|
-
await saveRegionsCache(
|
|
773
|
+
await saveRegionsCache(profileName, regions, logger);
|
|
765
774
|
return regions;
|
|
766
775
|
}
|
|
767
776
|
|
|
768
777
|
async function resolveRegion(opts: ResolveRegionOptions): Promise<string | undefined> {
|
|
769
|
-
const { options, apiClient,
|
|
778
|
+
const { options, apiClient, profileName, logger, required } = opts;
|
|
770
779
|
|
|
771
780
|
// Fetch regions (with caching)
|
|
772
|
-
const regions = await fetchRegionsWithCache(
|
|
781
|
+
const regions = await fetchRegionsWithCache(profileName, apiClient, logger);
|
|
773
782
|
|
|
774
783
|
// No regions available
|
|
775
784
|
if (regions.length === 0) {
|
|
@@ -1129,7 +1138,7 @@ async function registerSubcommand(
|
|
|
1129
1138
|
error &&
|
|
1130
1139
|
typeof error === 'object' &&
|
|
1131
1140
|
'name' in error &&
|
|
1132
|
-
error.name === '
|
|
1141
|
+
error.name === 'ProjectConfigNotFoundException'
|
|
1133
1142
|
) {
|
|
1134
1143
|
// If TTY is available, prompt user to select a project
|
|
1135
1144
|
const hasTTY = process.stdin.isTTY && process.stdout.isTTY;
|
|
@@ -1237,7 +1246,7 @@ async function registerSubcommand(
|
|
|
1237
1246
|
return resolveRegion({
|
|
1238
1247
|
options: options as Record<string, unknown>,
|
|
1239
1248
|
apiClient,
|
|
1240
|
-
|
|
1249
|
+
profileName: baseCtx.config?.name ?? defaultProfileName,
|
|
1241
1250
|
logger: baseCtx.logger,
|
|
1242
1251
|
required: !!normalized.requiresRegion,
|
|
1243
1252
|
region: project?.region,
|
|
@@ -1306,7 +1315,7 @@ async function registerSubcommand(
|
|
|
1306
1315
|
return resolveRegion({
|
|
1307
1316
|
options: options as Record<string, unknown>,
|
|
1308
1317
|
apiClient,
|
|
1309
|
-
|
|
1318
|
+
profileName: baseCtx.config?.name ?? defaultProfileName,
|
|
1310
1319
|
logger: baseCtx.logger,
|
|
1311
1320
|
required: !!normalized.requiresRegion,
|
|
1312
1321
|
region: project?.region,
|
|
@@ -1420,7 +1429,7 @@ async function registerSubcommand(
|
|
|
1420
1429
|
const region = await resolveRegion({
|
|
1421
1430
|
options: options as Record<string, unknown>,
|
|
1422
1431
|
apiClient,
|
|
1423
|
-
|
|
1432
|
+
profileName: baseCtx.config?.name ?? defaultProfileName,
|
|
1424
1433
|
logger: baseCtx.logger,
|
|
1425
1434
|
required: !!normalized.requiresRegion,
|
|
1426
1435
|
region: project?.region,
|
|
@@ -1485,7 +1494,7 @@ async function registerSubcommand(
|
|
|
1485
1494
|
const region = await resolveRegion({
|
|
1486
1495
|
options: options as Record<string, unknown>,
|
|
1487
1496
|
apiClient,
|
|
1488
|
-
|
|
1497
|
+
profileName: baseCtx.config?.name ?? defaultProfileName,
|
|
1489
1498
|
logger: baseCtx.logger,
|
|
1490
1499
|
required: !!normalized.requiresRegion,
|
|
1491
1500
|
});
|
|
@@ -1597,7 +1606,7 @@ async function registerSubcommand(
|
|
|
1597
1606
|
const region = await resolveRegion({
|
|
1598
1607
|
options: options as Record<string, unknown>,
|
|
1599
1608
|
apiClient,
|
|
1600
|
-
|
|
1609
|
+
profileName: baseCtx.config?.name ?? defaultProfileName,
|
|
1601
1610
|
logger: baseCtx.logger,
|
|
1602
1611
|
required: !!normalized.requiresRegion,
|
|
1603
1612
|
region: project?.region,
|
|
@@ -1726,7 +1735,7 @@ export async function registerCommands(
|
|
|
1726
1735
|
const region = await resolveRegion({
|
|
1727
1736
|
options: baseCtx.options as unknown as Record<string, unknown>,
|
|
1728
1737
|
apiClient,
|
|
1729
|
-
|
|
1738
|
+
profileName: baseCtx.config?.name ?? defaultProfileName,
|
|
1730
1739
|
logger: baseCtx.logger,
|
|
1731
1740
|
required: !!normalized.requiresRegion,
|
|
1732
1741
|
});
|
|
@@ -1784,7 +1793,7 @@ export async function registerCommands(
|
|
|
1784
1793
|
const region = await resolveRegion({
|
|
1785
1794
|
options: baseCtx.options as unknown as Record<string, unknown>,
|
|
1786
1795
|
apiClient,
|
|
1787
|
-
|
|
1796
|
+
profileName: baseCtx.config?.name ?? defaultProfileName,
|
|
1788
1797
|
logger: baseCtx.logger,
|
|
1789
1798
|
required: !!normalized.requiresRegion,
|
|
1790
1799
|
});
|
|
@@ -1805,7 +1814,7 @@ export async function registerCommands(
|
|
|
1805
1814
|
const region = await resolveRegion({
|
|
1806
1815
|
options: baseCtx.options as unknown as Record<string, unknown>,
|
|
1807
1816
|
apiClient,
|
|
1808
|
-
|
|
1817
|
+
profileName: baseCtx.config?.name ?? defaultProfileName,
|
|
1809
1818
|
logger: baseCtx.logger,
|
|
1810
1819
|
required: !!normalized.requiresRegion,
|
|
1811
1820
|
});
|
|
@@ -112,19 +112,11 @@ export const showSubcommand = createSubcommand({
|
|
|
112
112
|
requiresAuth: true,
|
|
113
113
|
requiresProject: true,
|
|
114
114
|
},
|
|
115
|
-
{
|
|
116
|
-
id: 'secrets',
|
|
117
|
-
name: 'Secrets Management',
|
|
118
|
-
description: 'Store and retrieve secrets securely',
|
|
119
|
-
commands: ['secret list', 'secret set', 'secret get', 'secret delete'],
|
|
120
|
-
requiresAuth: true,
|
|
121
|
-
requiresProject: true,
|
|
122
|
-
},
|
|
123
115
|
{
|
|
124
116
|
id: 'env',
|
|
125
|
-
name: 'Environment Variables',
|
|
126
|
-
description: 'Manage environment variables',
|
|
127
|
-
commands: ['env list', 'env set', 'env get', 'env delete'],
|
|
117
|
+
name: 'Environment Variables & Secrets',
|
|
118
|
+
description: 'Manage environment variables and secrets',
|
|
119
|
+
commands: ['env list', 'env set', 'env set --secret', 'env get', 'env delete'],
|
|
128
120
|
requiresAuth: true,
|
|
129
121
|
requiresProject: true,
|
|
130
122
|
},
|
|
@@ -189,7 +181,7 @@ export const showSubcommand = createSubcommand({
|
|
|
189
181
|
'auth signup',
|
|
190
182
|
'auth login',
|
|
191
183
|
'project create',
|
|
192
|
-
'
|
|
184
|
+
'env set API_KEY <value> --secret',
|
|
193
185
|
'dev',
|
|
194
186
|
],
|
|
195
187
|
},
|
|
@@ -199,9 +191,14 @@ export const showSubcommand = createSubcommand({
|
|
|
199
191
|
steps: ['bundle', 'cloud deploy', 'cloud deployment logs', 'cloud deployment show'],
|
|
200
192
|
},
|
|
201
193
|
{
|
|
202
|
-
name: 'Manage
|
|
203
|
-
description: 'Configure
|
|
204
|
-
steps: [
|
|
194
|
+
name: 'Manage Environment Variables',
|
|
195
|
+
description: 'Configure environment variables and secrets',
|
|
196
|
+
steps: [
|
|
197
|
+
'env list',
|
|
198
|
+
'env set <key> <value>',
|
|
199
|
+
'env set <key> <value> --secret',
|
|
200
|
+
'env get <key>',
|
|
201
|
+
],
|
|
205
202
|
},
|
|
206
203
|
{
|
|
207
204
|
name: 'SSH Key Setup',
|