thinkwork-cli 0.3.1 → 0.3.2
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 +21 -0
- package/dist/cli.js +41 -12
- package/dist/terraform/modules/thinkwork/variables.tf +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -64,6 +64,8 @@ No repo clone required — `thinkwork init` scaffolds all Terraform modules from
|
|
|
64
64
|
|
|
65
65
|
| Command | Description |
|
|
66
66
|
|---------|-------------|
|
|
67
|
+
| `thinkwork status` | Discover all deployed environments in AWS (clickable URLs) |
|
|
68
|
+
| `thinkwork status -s <stage>` | Detailed view for one environment |
|
|
67
69
|
| `thinkwork outputs -s <stage>` | Show deployment outputs (API URL, Cognito IDs, etc.) |
|
|
68
70
|
| `thinkwork config list` | List all initialized environments |
|
|
69
71
|
| `thinkwork config list -s <stage>` | Show full config for an environment (secrets masked) |
|
|
@@ -110,6 +112,25 @@ All initialized environments are saved to `~/.thinkwork/environments/<stage>/con
|
|
|
110
112
|
|
|
111
113
|
## Examples
|
|
112
114
|
|
|
115
|
+
### Check all environments
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
thinkwork status
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
Environments
|
|
123
|
+
──────────────────────────────────────────────────────────────────────
|
|
124
|
+
Stage Source Lambdas AgentCore Memory URLs
|
|
125
|
+
──────────────────────────────────────────────────────────────────────
|
|
126
|
+
● dev aws+cli 42 active hindsight ✓ API: https://ho7oy...
|
|
127
|
+
WS: dcrs2r...
|
|
128
|
+
Mem: http://tw-dev...
|
|
129
|
+
──────────────────────────────────────────────────────────────────────
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
URLs are clickable in supported terminals (iTerm2, Windows Terminal, VS Code, etc.).
|
|
133
|
+
|
|
113
134
|
### Switch memory engine
|
|
114
135
|
|
|
115
136
|
```bash
|
package/dist/cli.js
CHANGED
|
@@ -1276,6 +1276,10 @@ output "hindsight_endpoint" { value = module.thinkwork.hindsight_endpoint }
|
|
|
1276
1276
|
// src/commands/status.ts
|
|
1277
1277
|
import { execSync as execSync6 } from "child_process";
|
|
1278
1278
|
import chalk6 from "chalk";
|
|
1279
|
+
function link(url, label) {
|
|
1280
|
+
const text = label || url;
|
|
1281
|
+
return `\x1B]8;;${url}\x1B\\${text}\x1B]8;;\x1B\\`;
|
|
1282
|
+
}
|
|
1279
1283
|
function runAws(cmd) {
|
|
1280
1284
|
try {
|
|
1281
1285
|
return execSync6(`aws ${cmd}`, {
|
|
@@ -1308,6 +1312,10 @@ function discoverAwsStages(region) {
|
|
|
1308
1312
|
`apigatewayv2 get-apis --region ${region} --query "Items[?Name=='thinkwork-${stage}-api'].ApiEndpoint|[0]" --output text`
|
|
1309
1313
|
);
|
|
1310
1314
|
if (apiRaw && apiRaw !== "None") info.apiEndpoint = apiRaw;
|
|
1315
|
+
const appsyncRaw = runAws(
|
|
1316
|
+
`appsync list-graphql-apis --region ${region} --query "graphqlApis[?name=='thinkwork-${stage}-subscriptions'].uris.REALTIME|[0]" --output text`
|
|
1317
|
+
);
|
|
1318
|
+
if (appsyncRaw && appsyncRaw !== "None") info.appsyncUrl = appsyncRaw;
|
|
1311
1319
|
const acRaw = runAws(
|
|
1312
1320
|
`lambda get-function --function-name thinkwork-${stage}-agentcore --region ${region} --query "Configuration.State" --output text 2>/dev/null`
|
|
1313
1321
|
);
|
|
@@ -1325,6 +1333,7 @@ function discoverAwsStages(region) {
|
|
|
1325
1333
|
`elbv2 describe-load-balancers --region ${region} --query "LoadBalancers[?contains(LoadBalancerName, 'tw-${stage}-hindsight')].DNSName|[0]" --output text`
|
|
1326
1334
|
);
|
|
1327
1335
|
if (albRaw && albRaw !== "None") {
|
|
1336
|
+
info.hindsightEndpoint = `http://${albRaw}`;
|
|
1328
1337
|
try {
|
|
1329
1338
|
const health = execSync6(`curl -s --max-time 3 http://${albRaw}/health`, { encoding: "utf-8" }).trim();
|
|
1330
1339
|
info.hindsightHealth = health.includes("healthy") ? "healthy" : "unhealthy";
|
|
@@ -1381,19 +1390,21 @@ function registerStatusCommand(program2) {
|
|
|
1381
1390
|
console.log(` ${chalk6.bold("Source:")} ${info.source === "both" ? "AWS + local config" : info.source === "aws" ? "AWS (no local config)" : "local only (not in AWS)"}`);
|
|
1382
1391
|
console.log(` ${chalk6.bold("Region:")} ${info.region}`);
|
|
1383
1392
|
console.log(` ${chalk6.bold("Account:")} ${info.accountId}`);
|
|
1384
|
-
|
|
1385
|
-
if (info.lambdaCount) console.log(` ${chalk6.bold("Lambda fns:")} ${info.lambdaCount}`);
|
|
1393
|
+
console.log(` ${chalk6.bold("Lambda fns:")} ${info.lambdaCount || "\u2014"}`);
|
|
1386
1394
|
console.log(` ${chalk6.bold("AgentCore:")} ${info.agentcoreStatus || "unknown"}`);
|
|
1387
1395
|
console.log(` ${chalk6.bold("Memory:")} ${info.memoryEngine || "unknown"}`);
|
|
1388
1396
|
if (info.hindsightHealth) console.log(` ${chalk6.bold("Hindsight:")} ${info.hindsightHealth}`);
|
|
1389
1397
|
if (info.bucketName) console.log(` ${chalk6.bold("S3 bucket:")} ${info.bucketName}`);
|
|
1398
|
+
console.log("");
|
|
1399
|
+
console.log(chalk6.bold(" URLs:"));
|
|
1400
|
+
if (info.apiEndpoint) console.log(` API: ${link(info.apiEndpoint)}`);
|
|
1401
|
+
if (info.appsyncUrl) console.log(` WebSocket: ${link(info.appsyncUrl)}`);
|
|
1402
|
+
if (info.hindsightEndpoint) console.log(` Hindsight: ${link(info.hindsightEndpoint)}`);
|
|
1390
1403
|
console.log(chalk6.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
1391
1404
|
const local = loadEnvironment(opts.stage);
|
|
1392
1405
|
if (local) {
|
|
1393
|
-
console.log("");
|
|
1394
1406
|
console.log(chalk6.dim(` Terraform dir: ${local.terraformDir}`));
|
|
1395
1407
|
} else {
|
|
1396
|
-
console.log("");
|
|
1397
1408
|
console.log(chalk6.dim(` No local config. Run: thinkwork init -s ${opts.stage}`));
|
|
1398
1409
|
}
|
|
1399
1410
|
console.log("");
|
|
@@ -1405,22 +1416,40 @@ function registerStatusCommand(program2) {
|
|
|
1405
1416
|
console.log("");
|
|
1406
1417
|
return;
|
|
1407
1418
|
}
|
|
1419
|
+
const COL1 = 16;
|
|
1420
|
+
const COL2 = 10;
|
|
1421
|
+
const COL3 = 10;
|
|
1422
|
+
const COL4 = 14;
|
|
1423
|
+
const COL5 = 14;
|
|
1424
|
+
const pad = " ".repeat(2 + 2 + COL1 + COL2 + COL3 + COL4 + COL5);
|
|
1408
1425
|
console.log(chalk6.bold(" Environments"));
|
|
1409
|
-
console.log(chalk6.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
1426
|
+
console.log(chalk6.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
1410
1427
|
console.log(
|
|
1411
|
-
chalk6.dim(" ") + "Stage".padEnd(
|
|
1428
|
+
chalk6.dim(" ") + "Stage".padEnd(COL1) + "Source".padEnd(COL2) + "Lambdas".padEnd(COL3) + "AgentCore".padEnd(COL4) + "Memory".padEnd(COL5) + "URLs"
|
|
1412
1429
|
);
|
|
1413
|
-
console.log(chalk6.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
1430
|
+
console.log(chalk6.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
1414
1431
|
for (const [, info] of [...merged].sort((a, b) => a[0].localeCompare(b[0]))) {
|
|
1415
1432
|
const sourceBadge = info.source === "both" ? chalk6.green("\u25CF") : info.source === "aws" ? chalk6.yellow("\u25CF") : chalk6.dim("\u25CB");
|
|
1416
1433
|
const acStatus = info.agentcoreStatus === "Active" ? chalk6.green("active") : info.agentcoreStatus === "not deployed" ? chalk6.dim("\u2014") : chalk6.yellow(info.agentcoreStatus || "\u2014");
|
|
1417
1434
|
const memBadge = info.memoryEngine === "hindsight" ? info.hindsightHealth === "healthy" ? chalk6.magenta("hindsight \u2713") : chalk6.yellow("hindsight ?") : chalk6.dim(info.memoryEngine || "\u2014");
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
);
|
|
1435
|
+
const prefix = ` ${sourceBadge} ` + chalk6.bold(info.stage.padEnd(COL1 - 1)) + " " + (info.source === "both" ? "aws+cli" : info.source).padEnd(COL2) + String(info.lambdaCount || "\u2014").padEnd(COL3);
|
|
1436
|
+
const urls = [];
|
|
1437
|
+
if (info.apiEndpoint) urls.push(`API: ${link(info.apiEndpoint, info.apiEndpoint)}`);
|
|
1438
|
+
if (info.appsyncUrl) urls.push(`WS: ${link(info.appsyncUrl, info.appsyncUrl.replace("wss://", "").split(".")[0] + "...")}`);
|
|
1439
|
+
if (info.hindsightEndpoint) urls.push(`Mem: ${link(info.hindsightEndpoint, info.hindsightEndpoint)}`);
|
|
1440
|
+
if (urls.length === 0) {
|
|
1441
|
+
console.log(prefix + acStatus.padEnd(22) + memBadge.padEnd(22) + chalk6.dim("\u2014"));
|
|
1442
|
+
} else {
|
|
1443
|
+
console.log(prefix + acStatus.padEnd(22) + memBadge.padEnd(22) + chalk6.dim(urls[0]));
|
|
1444
|
+
for (let i = 1; i < urls.length; i++) {
|
|
1445
|
+
console.log(pad + chalk6.dim(urls[i]));
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1421
1448
|
}
|
|
1422
|
-
console.log(chalk6.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
1423
|
-
console.log(
|
|
1449
|
+
console.log(chalk6.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
1450
|
+
console.log(
|
|
1451
|
+
chalk6.dim(` ${merged.size} environment(s) `) + chalk6.green("\u25CF") + chalk6.dim(" aws+cli ") + chalk6.yellow("\u25CF") + chalk6.dim(" aws only ") + chalk6.dim("\u25CB local only")
|
|
1452
|
+
);
|
|
1424
1453
|
console.log("");
|
|
1425
1454
|
console.log(` Details: ${chalk6.cyan("thinkwork status -s <stage>")}`);
|
|
1426
1455
|
console.log("");
|
|
@@ -152,7 +152,7 @@ variable "memory_engine" {
|
|
|
152
152
|
variable "hindsight_image_tag" {
|
|
153
153
|
description = "Hindsight Docker image tag (only used when memory_engine = 'hindsight')"
|
|
154
154
|
type = string
|
|
155
|
-
default = "0.
|
|
155
|
+
default = "0.5.0"
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
variable "agentcore_memory_id" {
|