@mesh-tech/mesh-cli 0.43.3 → 0.45.0

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.
Files changed (62) hide show
  1. package/dist/bin/{mesh.auth-preflight-JTUNS42O.js → mesh.auth-preflight-3ASNYA3I.js} +1 -1
  2. package/dist/bin/{mesh.chunk-QE5LUIHN.js → mesh.chunk-252LTIHZ.js} +2 -2
  3. package/dist/bin/{mesh.chunk-TYM27CO3.js → mesh.chunk-4Y3JGAYZ.js} +1 -1
  4. package/dist/bin/{mesh.chunk-OOWKJR4H.js → mesh.chunk-6OGUV2DU.js} +1 -1
  5. package/dist/bin/{mesh.chunk-VCQKLVZJ.js → mesh.chunk-G4TCVQLL.js} +603 -145
  6. package/dist/bin/mesh.chunk-G4TCVQLL.js.map +6 -0
  7. package/dist/bin/{mesh.chunk-ZNM3DDAM.js → mesh.chunk-HPLMVIBO.js} +1 -1
  8. package/dist/bin/{mesh.chunk-QUKWWFZI.js → mesh.chunk-JSY6THRF.js} +1 -1
  9. package/dist/bin/{mesh.chunk-PANTMVC3.js → mesh.chunk-NN3LTNUM.js} +3 -3
  10. package/dist/bin/{mesh.chunk-HB2IZKLP.js → mesh.chunk-SFIJZF3S.js} +786 -276
  11. package/dist/bin/{mesh.chunk-HB2IZKLP.js.map → mesh.chunk-SFIJZF3S.js.map} +3 -3
  12. package/dist/bin/{mesh.chunk-HC7V75J3.js → mesh.chunk-UJAPUO2W.js} +1 -1
  13. package/dist/bin/{mesh.create-app-DVMZDEQP.js → mesh.create-app-BHB3BGH7.js} +3 -3
  14. package/dist/bin/{mesh.dev-token-server-4N6HGQAF.js → mesh.dev-token-server-6TNWX5TY.js} +2 -2
  15. package/dist/bin/mesh.js +9 -9
  16. package/dist/bin/{mesh.login-Q6R5GMVM.js → mesh.login-4O5PMS25.js} +2 -2
  17. package/dist/bin/{mesh.platform-setup-YK6KSOP7.js → mesh.platform-setup-MTY6ICAO.js} +1 -1
  18. package/dist/bin/{mesh.program-GEKNV2LY.js → mesh.program-CMOLQWZI.js} +9 -9
  19. package/dist/bin/{mesh.registry-KA3CNNPZ.js → mesh.registry-BDBH6DRP.js} +4 -4
  20. package/dist/bin/{mesh.registry-identity-DSTAHXUS.js → mesh.registry-identity-QOGDEMZO.js} +3 -3
  21. package/dist/bin/{mesh.review-command-3ZXPS6Y3.js → mesh.review-command-E7V2L5AM.js} +3 -3
  22. package/dist/bin/{mesh.start-HE6P3TCS.js → mesh.start-3MUKXN2U.js} +2 -2
  23. package/dist/bin/{mesh.wizard-QGWPV4XN.js → mesh.wizard-EH3SQEHW.js} +7 -7
  24. package/dist/build-info.json +2 -2
  25. package/dist/src/commands/dev.d.ts +1 -0
  26. package/dist/src/commands/dev.js +57 -1
  27. package/dist/src/commands/temporal.js +146 -42
  28. package/dist/src/commands/temporal.js.map +3 -3
  29. package/dist/src/commands/workflow.d.ts +14 -0
  30. package/dist/src/commands/workflow.js +43 -31
  31. package/dist/src/commands/workstation.d.ts +3 -0
  32. package/dist/src/commands/workstation.js +395 -0
  33. package/dist/src/program.js +2 -0
  34. package/dist/src/utils/temporal-inspect.d.ts +17 -0
  35. package/dist/src/utils/temporal-inspect.js +71 -0
  36. package/dist/src/utils/workstation-machine.d.ts +54 -0
  37. package/dist/src/utils/workstation-machine.js +282 -0
  38. package/dist/src/utils/workstation-routes.d.ts +77 -0
  39. package/dist/src/utils/workstation-routes.js +180 -0
  40. package/fragments/base/README.md.hbs +3 -0
  41. package/package.json +2 -2
  42. package/skills/mesh/SKILL.md +5 -4
  43. package/skills/mesh/references/worktrees.md +4 -1
  44. package/dist/bin/mesh.chunk-VCQKLVZJ.js.map +0 -6
  45. /package/dist/bin/{mesh.auth-preflight-JTUNS42O.js.map → mesh.auth-preflight-3ASNYA3I.js.map} +0 -0
  46. /package/dist/bin/{mesh.chunk-QE5LUIHN.js.map → mesh.chunk-252LTIHZ.js.map} +0 -0
  47. /package/dist/bin/{mesh.chunk-TYM27CO3.js.map → mesh.chunk-4Y3JGAYZ.js.map} +0 -0
  48. /package/dist/bin/{mesh.chunk-OOWKJR4H.js.map → mesh.chunk-6OGUV2DU.js.map} +0 -0
  49. /package/dist/bin/{mesh.chunk-ZNM3DDAM.js.map → mesh.chunk-HPLMVIBO.js.map} +0 -0
  50. /package/dist/bin/{mesh.chunk-QUKWWFZI.js.map → mesh.chunk-JSY6THRF.js.map} +0 -0
  51. /package/dist/bin/{mesh.chunk-PANTMVC3.js.map → mesh.chunk-NN3LTNUM.js.map} +0 -0
  52. /package/dist/bin/{mesh.chunk-HC7V75J3.js.map → mesh.chunk-UJAPUO2W.js.map} +0 -0
  53. /package/dist/bin/{mesh.create-app-DVMZDEQP.js.map → mesh.create-app-BHB3BGH7.js.map} +0 -0
  54. /package/dist/bin/{mesh.dev-token-server-4N6HGQAF.js.map → mesh.dev-token-server-6TNWX5TY.js.map} +0 -0
  55. /package/dist/bin/{mesh.login-Q6R5GMVM.js.map → mesh.login-4O5PMS25.js.map} +0 -0
  56. /package/dist/bin/{mesh.platform-setup-YK6KSOP7.js.map → mesh.platform-setup-MTY6ICAO.js.map} +0 -0
  57. /package/dist/bin/{mesh.program-GEKNV2LY.js.map → mesh.program-CMOLQWZI.js.map} +0 -0
  58. /package/dist/bin/{mesh.registry-KA3CNNPZ.js.map → mesh.registry-BDBH6DRP.js.map} +0 -0
  59. /package/dist/bin/{mesh.registry-identity-DSTAHXUS.js.map → mesh.registry-identity-QOGDEMZO.js.map} +0 -0
  60. /package/dist/bin/{mesh.review-command-3ZXPS6Y3.js.map → mesh.review-command-E7V2L5AM.js.map} +0 -0
  61. /package/dist/bin/{mesh.start-HE6P3TCS.js.map → mesh.start-3MUKXN2U.js.map} +0 -0
  62. /package/dist/bin/{mesh.wizard-QGWPV4XN.js.map → mesh.wizard-EH3SQEHW.js.map} +0 -0
@@ -107,7 +107,7 @@ async function registryPreflight(opts) {
107
107
  const probe = await probeRegistryToken(opts);
108
108
  let session = null;
109
109
  try {
110
- const { readRegistrySession } = await import("./mesh.registry-identity-DSTAHXUS.js");
110
+ const { readRegistrySession } = await import("./mesh.registry-identity-QOGDEMZO.js");
111
111
  session = readRegistrySession();
112
112
  } catch {
113
113
  }
@@ -13,14 +13,14 @@ import {
13
13
  resolveAppDir,
14
14
  shouldBootstrapAppsRepo,
15
15
  workspaceGlobForApp
16
- } from "./mesh.chunk-QE5LUIHN.js";
16
+ } from "./mesh.chunk-252LTIHZ.js";
17
17
  import "./mesh.chunk-F4654EPX.js";
18
- import "./mesh.chunk-HB2IZKLP.js";
18
+ import "./mesh.chunk-SFIJZF3S.js";
19
19
  import "./mesh.chunk-PL3P54MY.js";
20
20
  import "./mesh.chunk-MCBMHWXP.js";
21
21
  import "./mesh.chunk-WFFDF346.js";
22
22
  import "./mesh.chunk-IQOBTL42.js";
23
- import "./mesh.chunk-HC7V75J3.js";
23
+ import "./mesh.chunk-UJAPUO2W.js";
24
24
  export {
25
25
  NO_REGISTRY_ACCESS_MESSAGE,
26
26
  PLATFORM_MONOREPO_NAME,
@@ -2,7 +2,7 @@ import {
2
2
  decodeJwtPayload,
3
3
  getValidToken,
4
4
  readCredentials
5
- } from "./mesh.chunk-HB2IZKLP.js";
5
+ } from "./mesh.chunk-SFIJZF3S.js";
6
6
  import "./mesh.chunk-PL3P54MY.js";
7
7
  import "./mesh.chunk-MCBMHWXP.js";
8
8
  import {
@@ -10,7 +10,7 @@ import {
10
10
  logWarn
11
11
  } from "./mesh.chunk-WFFDF346.js";
12
12
  import "./mesh.chunk-IQOBTL42.js";
13
- import "./mesh.chunk-HC7V75J3.js";
13
+ import "./mesh.chunk-UJAPUO2W.js";
14
14
 
15
15
  // packages/mesh-cli/src/commands/dev-token-server.ts
16
16
  import * as http from "node:http";
package/dist/bin/mesh.js CHANGED
@@ -1,25 +1,25 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  createProgram
4
- } from "./mesh.chunk-VCQKLVZJ.js";
5
- import "./mesh.chunk-QUKWWFZI.js";
4
+ } from "./mesh.chunk-G4TCVQLL.js";
5
+ import "./mesh.chunk-JSY6THRF.js";
6
6
  import {
7
7
  formatVersionLine,
8
8
  resolveCliRuntime
9
- } from "./mesh.chunk-OOWKJR4H.js";
10
- import "./mesh.chunk-QE5LUIHN.js";
11
- import "./mesh.chunk-ZNM3DDAM.js";
12
- import "./mesh.chunk-PANTMVC3.js";
9
+ } from "./mesh.chunk-6OGUV2DU.js";
10
+ import "./mesh.chunk-252LTIHZ.js";
11
+ import "./mesh.chunk-HPLMVIBO.js";
12
+ import "./mesh.chunk-NN3LTNUM.js";
13
13
  import "./mesh.chunk-F4654EPX.js";
14
- import "./mesh.chunk-TYM27CO3.js";
15
- import "./mesh.chunk-HB2IZKLP.js";
14
+ import "./mesh.chunk-4Y3JGAYZ.js";
15
+ import "./mesh.chunk-SFIJZF3S.js";
16
16
  import "./mesh.chunk-PL3P54MY.js";
17
17
  import "./mesh.chunk-MCBMHWXP.js";
18
18
  import "./mesh.chunk-WFFDF346.js";
19
19
  import {
20
20
  handleCliError
21
21
  } from "./mesh.chunk-IQOBTL42.js";
22
- import "./mesh.chunk-HC7V75J3.js";
22
+ import "./mesh.chunk-UJAPUO2W.js";
23
23
  import "./mesh.chunk-OW5EMVG5.js";
24
24
 
25
25
  // packages/mesh-cli/bin/mesh.ts
@@ -40,12 +40,12 @@ import {
40
40
  tokenStillValid,
41
41
  withDiscoveredFields,
42
42
  writeContextConfig
43
- } from "./mesh.chunk-HB2IZKLP.js";
43
+ } from "./mesh.chunk-SFIJZF3S.js";
44
44
  import "./mesh.chunk-PL3P54MY.js";
45
45
  import "./mesh.chunk-MCBMHWXP.js";
46
46
  import "./mesh.chunk-WFFDF346.js";
47
47
  import "./mesh.chunk-IQOBTL42.js";
48
- import "./mesh.chunk-HC7V75J3.js";
48
+ import "./mesh.chunk-UJAPUO2W.js";
49
49
  export {
50
50
  CONFIG_DIR,
51
51
  CONFIG_FILE,
@@ -15,7 +15,7 @@ import {
15
15
  validateEnv,
16
16
  validateRegion,
17
17
  validateStateBucket
18
- } from "./mesh.chunk-ZNM3DDAM.js";
18
+ } from "./mesh.chunk-HPLMVIBO.js";
19
19
  import "./mesh.chunk-IQOBTL42.js";
20
20
  export {
21
21
  DOMAIN_REQUIRED_MESSAGE,
@@ -2,20 +2,20 @@ import {
2
2
  CLI_DESCRIPTION,
3
3
  CLI_NAME,
4
4
  createProgram
5
- } from "./mesh.chunk-VCQKLVZJ.js";
6
- import "./mesh.chunk-QUKWWFZI.js";
7
- import "./mesh.chunk-OOWKJR4H.js";
8
- import "./mesh.chunk-QE5LUIHN.js";
9
- import "./mesh.chunk-ZNM3DDAM.js";
10
- import "./mesh.chunk-PANTMVC3.js";
5
+ } from "./mesh.chunk-G4TCVQLL.js";
6
+ import "./mesh.chunk-JSY6THRF.js";
7
+ import "./mesh.chunk-6OGUV2DU.js";
8
+ import "./mesh.chunk-252LTIHZ.js";
9
+ import "./mesh.chunk-HPLMVIBO.js";
10
+ import "./mesh.chunk-NN3LTNUM.js";
11
11
  import "./mesh.chunk-F4654EPX.js";
12
- import "./mesh.chunk-TYM27CO3.js";
13
- import "./mesh.chunk-HB2IZKLP.js";
12
+ import "./mesh.chunk-4Y3JGAYZ.js";
13
+ import "./mesh.chunk-SFIJZF3S.js";
14
14
  import "./mesh.chunk-PL3P54MY.js";
15
15
  import "./mesh.chunk-MCBMHWXP.js";
16
16
  import "./mesh.chunk-WFFDF346.js";
17
17
  import "./mesh.chunk-IQOBTL42.js";
18
- import "./mesh.chunk-HC7V75J3.js";
18
+ import "./mesh.chunk-UJAPUO2W.js";
19
19
  import "./mesh.chunk-OW5EMVG5.js";
20
20
  export {
21
21
  CLI_DESCRIPTION,
@@ -17,14 +17,14 @@ import {
17
17
  runRegistryStatus,
18
18
  shouldRemintAfter,
19
19
  shouldRepairUserNpmrc
20
- } from "./mesh.chunk-PANTMVC3.js";
21
- import "./mesh.chunk-TYM27CO3.js";
22
- import "./mesh.chunk-HB2IZKLP.js";
20
+ } from "./mesh.chunk-NN3LTNUM.js";
21
+ import "./mesh.chunk-4Y3JGAYZ.js";
22
+ import "./mesh.chunk-SFIJZF3S.js";
23
23
  import "./mesh.chunk-PL3P54MY.js";
24
24
  import "./mesh.chunk-MCBMHWXP.js";
25
25
  import "./mesh.chunk-WFFDF346.js";
26
26
  import "./mesh.chunk-IQOBTL42.js";
27
- import "./mesh.chunk-HC7V75J3.js";
27
+ import "./mesh.chunk-UJAPUO2W.js";
28
28
  export {
29
29
  CONTEXT_IGNORED_NOTICE,
30
30
  NOT_AUTHORIZED_RERUN,
@@ -15,13 +15,13 @@ import {
15
15
  registrySessionCandidates,
16
16
  registryTokenRoles,
17
17
  resolveRegistryIdentity
18
- } from "./mesh.chunk-TYM27CO3.js";
19
- import "./mesh.chunk-HB2IZKLP.js";
18
+ } from "./mesh.chunk-4Y3JGAYZ.js";
19
+ import "./mesh.chunk-SFIJZF3S.js";
20
20
  import "./mesh.chunk-PL3P54MY.js";
21
21
  import "./mesh.chunk-MCBMHWXP.js";
22
22
  import "./mesh.chunk-WFFDF346.js";
23
23
  import "./mesh.chunk-IQOBTL42.js";
24
- import "./mesh.chunk-HC7V75J3.js";
24
+ import "./mesh.chunk-UJAPUO2W.js";
25
25
  export {
26
26
  REGISTRY_ALIAS,
27
27
  REGISTRY_CREDENTIAL_KEY,
@@ -10,15 +10,15 @@ import {
10
10
  discoverStackExternalServices,
11
11
  ensureAwsCredentialsForStack,
12
12
  resolveExternalServiceScope
13
- } from "./mesh.chunk-QUKWWFZI.js";
14
- import "./mesh.chunk-HB2IZKLP.js";
13
+ } from "./mesh.chunk-JSY6THRF.js";
14
+ import "./mesh.chunk-SFIJZF3S.js";
15
15
  import "./mesh.chunk-PL3P54MY.js";
16
16
  import "./mesh.chunk-MCBMHWXP.js";
17
17
  import {
18
18
  logInfo
19
19
  } from "./mesh.chunk-WFFDF346.js";
20
20
  import "./mesh.chunk-IQOBTL42.js";
21
- import "./mesh.chunk-HC7V75J3.js";
21
+ import "./mesh.chunk-UJAPUO2W.js";
22
22
 
23
23
  // packages/mesh-cli/src/commands/mcp/review-command.ts
24
24
  import { SSMClient } from "@aws-sdk/client-ssm";
@@ -4,7 +4,7 @@ import {
4
4
  reportAssembly,
5
5
  resolveCliRuntime,
6
6
  runAssemble
7
- } from "./mesh.chunk-OOWKJR4H.js";
7
+ } from "./mesh.chunk-6OGUV2DU.js";
8
8
  import {
9
9
  logError,
10
10
  logInfo,
@@ -13,7 +13,7 @@ import {
13
13
  import {
14
14
  homeNpmrcPath,
15
15
  parseNpmrcRegistryAuth
16
- } from "./mesh.chunk-HC7V75J3.js";
16
+ } from "./mesh.chunk-UJAPUO2W.js";
17
17
 
18
18
  // packages/mesh-cli/src/docs/start.ts
19
19
  import { execFileSync as execFileSync2 } from "node:child_process";
@@ -2,24 +2,24 @@ import {
2
2
  bootstrapAppsRepo,
3
3
  isInsidePlatformMonorepo,
4
4
  shouldBootstrapAppsRepo
5
- } from "./mesh.chunk-QE5LUIHN.js";
5
+ } from "./mesh.chunk-252LTIHZ.js";
6
6
  import {
7
7
  PLATFORM_SETUP_DEFAULTS,
8
8
  ensureStateBucket,
9
9
  renderPlatformNextSteps,
10
10
  resolvePlatformSetup,
11
11
  scaffoldPlatformRepo
12
- } from "./mesh.chunk-ZNM3DDAM.js";
12
+ } from "./mesh.chunk-HPLMVIBO.js";
13
13
  import {
14
14
  RegistryNotAuthorizedError
15
- } from "./mesh.chunk-PANTMVC3.js";
15
+ } from "./mesh.chunk-NN3LTNUM.js";
16
16
  import {
17
17
  resolveTargetRoot,
18
18
  syncSkills
19
19
  } from "./mesh.chunk-F4654EPX.js";
20
20
  import {
21
21
  readRegistrySession
22
- } from "./mesh.chunk-TYM27CO3.js";
22
+ } from "./mesh.chunk-4Y3JGAYZ.js";
23
23
  import {
24
24
  detectLocalTenant,
25
25
  discoverConfigForContext,
@@ -31,7 +31,7 @@ import {
31
31
  runLoginFlow,
32
32
  tokenStillValid,
33
33
  writeMeshJson
34
- } from "./mesh.chunk-HB2IZKLP.js";
34
+ } from "./mesh.chunk-SFIJZF3S.js";
35
35
  import "./mesh.chunk-PL3P54MY.js";
36
36
  import "./mesh.chunk-MCBMHWXP.js";
37
37
  import {
@@ -44,7 +44,7 @@ import {
44
44
  } from "./mesh.chunk-IQOBTL42.js";
45
45
  import {
46
46
  probeRegistryToken
47
- } from "./mesh.chunk-HC7V75J3.js";
47
+ } from "./mesh.chunk-UJAPUO2W.js";
48
48
 
49
49
  // packages/mesh-cli/src/commands/init/wizard.ts
50
50
  import * as fs from "fs";
@@ -157,7 +157,7 @@ var registryStep = {
157
157
  try {
158
158
  logInfo(REGISTRY_WHY);
159
159
  const login = ctx.seams?.runRegistryLogin ?? (async (opts) => {
160
- const { runRegistryLogin } = await import("./mesh.registry-KA3CNNPZ.js");
160
+ const { runRegistryLogin } = await import("./mesh.registry-BDBH6DRP.js");
161
161
  await runRegistryLogin(void 0, opts);
162
162
  });
163
163
  await login({ device: ctx.device, profile: ctx.profile });
@@ -1,4 +1,4 @@
1
1
  {
2
- "commit": "67750469b",
3
- "builtAt": "2026-11-09T14:05:29.095Z"
2
+ "commit": "f796ae877",
3
+ "builtAt": "2026-11-15T16:42:23.109Z"
4
4
  }
@@ -12,6 +12,7 @@ interface DevService {
12
12
  command: string[];
13
13
  env?: Record<string, DevEnvVar>;
14
14
  kind?: 'dagster';
15
+ route?: string | false;
15
16
  }
16
17
  interface DevTunnel {
17
18
  host: string;
@@ -36,6 +36,8 @@ import { ALL_CHECKS, aggregateStatus, classifyPaneLiveness, classifySessionServi
36
36
  import { awaitServiceReadiness, paneTail, parseWaitSeconds, portHeldByAnother, RESTART_READY_TIMEOUT_MS, TEMPORAL_WORKER_RUNNING, } from './dev-readiness.js';
37
37
  import { resolveWorktreeIdentity, withAppScopedPortBlock, blockBasePort, PORT_BLOCK_SERVICE_SUBRANGE, } from '../utils/worktree-identity.js';
38
38
  import { devSessionsRoot } from '../utils/dev-sessions-root.js';
39
+ import { workstationRenewalWarnings } from '../utils/workstation-machine.js';
40
+ import { planSessionRoutes, readWorkstationIdentity, removeSessionRoutes, usableRouteUrls, worktreeRouteSuffix, writeSessionRoutes, } from '../utils/workstation-routes.js';
39
41
  export function registerServiceProbes(devOutput, tenant, probeFiles) {
40
42
  const services = {};
41
43
  for (const [name, service] of Object.entries(devOutput.services)) {
@@ -142,6 +144,12 @@ function removeSessionState(sessionName) {
142
144
  fs.unlinkSync(getSessionStatePath(sessionName));
143
145
  }
144
146
  catch { }
147
+ try {
148
+ const removed = removeSessionRoutes(sessionName);
149
+ if (removed.length > 0)
150
+ logInfo(`Removed workstation routes: ${removed.join(', ')}`);
151
+ }
152
+ catch { }
145
153
  try {
146
154
  fs.rmSync(getSessionEnvDir(sessionName), { recursive: true, force: true });
147
155
  }
@@ -1345,6 +1353,45 @@ async function updateDevboxProxy(devOutput, appRoot) {
1345
1353
  logInfo(` http://${hostname} → localhost:${port}`);
1346
1354
  }
1347
1355
  }
1356
+ function planWorkstationRoutes(appRoot, devOutput) {
1357
+ const identity = readWorkstationIdentity();
1358
+ if (!identity)
1359
+ return [];
1360
+ return planSessionRoutes({
1361
+ identity,
1362
+ app: devOutput.app ?? path.basename(appRoot),
1363
+ services: devOutput.services,
1364
+ suffix: worktreeRouteSuffix(resolveWorktreeIdentity(appRoot), process.env.MESH_DEV_ROUTE_SUFFIX),
1365
+ });
1366
+ }
1367
+ function workstationUrlVar(appRoot, devOutput, serviceName) {
1368
+ try {
1369
+ const url = usableRouteUrls(planWorkstationRoutes(appRoot, devOutput))[serviceName];
1370
+ return url ? { MESH_DEV_PUBLIC_URL: url } : {};
1371
+ }
1372
+ catch {
1373
+ return {};
1374
+ }
1375
+ }
1376
+ function applyWorkstationRoutes(sessionName, appRoot, devOutput) {
1377
+ try {
1378
+ const planned = planWorkstationRoutes(appRoot, devOutput);
1379
+ if (planned.length === 0)
1380
+ return {};
1381
+ const result = writeSessionRoutes(sessionName, planned);
1382
+ for (const warning of workstationRenewalWarnings())
1383
+ logWarn(warning);
1384
+ for (const c of result.conflicts) {
1385
+ logWarn(`Workstation route ${c.hostname} is held by ${c.heldBy} (port ${c.heldPort}); ${c.service} (port ${c.port}) is not routed. ` +
1386
+ 'Pick another name with --route-suffix <name>.');
1387
+ }
1388
+ return result.urls;
1389
+ }
1390
+ catch (e) {
1391
+ logWarn(`Workstation routes skipped: ${e.message}`);
1392
+ return {};
1393
+ }
1394
+ }
1348
1395
  async function setupSubdomainRouting(devOutput, appRoot) {
1349
1396
  const tsInfo = await getTailscaleInfo();
1350
1397
  if (!tsInfo)
@@ -1589,6 +1636,7 @@ async function startServices(sessionName, appRoot, devOutput, headless, awsEnv,
1589
1636
  logInfo(' Hub UI will show unauthenticated state without valid credentials.');
1590
1637
  }
1591
1638
  const monorepoRoot = findMonorepoRoot();
1639
+ const routeUrls = applyWorkstationRoutes(sessionName, appRoot, devOutput);
1592
1640
  const notLaunched = [];
1593
1641
  for (const [name, service] of Object.entries(devOutput.services)) {
1594
1642
  const cmd = service.command.join(' ');
@@ -1632,6 +1680,7 @@ async function startServices(sessionName, appRoot, devOutput, headless, awsEnv,
1632
1680
  ...temporalAuthVars,
1633
1681
  ...devUserVars,
1634
1682
  ...(taskQueueSuffix ? { MESH_TASK_QUEUE_SUFFIX: taskQueueSuffix } : {}),
1683
+ ...(routeUrls[name] ? { MESH_DEV_PUBLIC_URL: routeUrls[name] } : {}),
1635
1684
  ...awsEnv,
1636
1685
  ...sessionEnv,
1637
1686
  };
@@ -1682,7 +1731,10 @@ async function startServices(sessionName, appRoot, devOutput, headless, awsEnv,
1682
1731
  const s = devOutput.services[name];
1683
1732
  const hasCmd = s.command && s.command.length > 0;
1684
1733
  if (hasCmd) {
1685
- if (subdomainCtx && s.port) {
1734
+ if (routeUrls[name]) {
1735
+ console.log(` ${name.padEnd(20)} ${routeUrls[name]} (localhost:${s.port})`);
1736
+ }
1737
+ else if (subdomainCtx && s.port) {
1686
1738
  console.log(` ${name.padEnd(20)} http://${name}.${subdomainCtx.baseDomain}`);
1687
1739
  }
1688
1740
  else {
@@ -1836,6 +1888,7 @@ async function restartService(sessionName, serviceName, appRoot, devOutput, awsE
1836
1888
  ...temporalAuthVars,
1837
1889
  ...resolveDevUserVars(merged),
1838
1890
  ...(taskQueueSuffix ? { MESH_TASK_QUEUE_SUFFIX: taskQueueSuffix } : {}),
1891
+ ...workstationUrlVar(appRoot, merged, serviceName),
1839
1892
  ...awsEnv,
1840
1893
  ...readTmuxSessionEnv(sessionName, ['KUBECONFIG', 'DEV_USER_TOKEN_URL']),
1841
1894
  };
@@ -2034,6 +2087,7 @@ export function registerDevCommand(program) {
2034
2087
  .option('--stack <stack>', 'Pulumi stack name (default: auto-detect)')
2035
2088
  .addOption(new Option('--stage <stack>', 'Deprecated alias for --stack').hideHelp())
2036
2089
  .option('--headless', 'Start without attaching to tmux')
2090
+ .option('--route-suffix <name>', "On a workstation: the suffix of this session's HTTPS names (default: the worktree's name; '' for none)")
2037
2091
  .option('--kill', 'Kill existing dev session')
2038
2092
  .option('--status', 'Show service status')
2039
2093
  .option('--json', 'Output status as JSON (with --status)')
@@ -2053,6 +2107,8 @@ export function registerDevCommand(program) {
2053
2107
  await startTokenServer(Number(port), context);
2054
2108
  });
2055
2109
  dev.action(async (options) => {
2110
+ if (options.routeSuffix !== undefined)
2111
+ process.env.MESH_DEV_ROUTE_SUFFIX = options.routeSuffix;
2056
2112
  if (options.profile) {
2057
2113
  applyAwsProfileOverride(options.profile);
2058
2114
  }
@@ -901,6 +901,22 @@ var init_worktree_identity = __esm({
901
901
  }
902
902
  });
903
903
 
904
+ // packages/mesh-cli/src/utils/workstation-routes.ts
905
+ var init_workstation_routes = __esm({
906
+ "packages/mesh-cli/src/utils/workstation-routes.ts"() {
907
+ "use strict";
908
+ }
909
+ });
910
+
911
+ // packages/mesh-cli/src/utils/workstation-machine.ts
912
+ var init_workstation_machine = __esm({
913
+ "packages/mesh-cli/src/utils/workstation-machine.ts"() {
914
+ "use strict";
915
+ init_log();
916
+ init_workstation_routes();
917
+ }
918
+ });
919
+
904
920
  // packages/mesh-cli/src/commands/dev.ts
905
921
  import { Option } from "commander";
906
922
  import { SecretsManagerClient as SecretsManagerClient2, GetSecretValueCommand as GetSecretValueCommand2 } from "@aws-sdk/client-secrets-manager";
@@ -938,6 +954,8 @@ var init_dev = __esm({
938
954
  init_dev_readiness();
939
955
  init_worktree_identity();
940
956
  init_dev_sessions_root();
957
+ init_workstation_machine();
958
+ init_workstation_routes();
941
959
  }
942
960
  });
943
961
 
@@ -1903,6 +1921,69 @@ var init_capture_history = __esm({
1903
1921
  }
1904
1922
  });
1905
1923
 
1924
+ // packages/mesh-cli/src/utils/temporal-inspect.ts
1925
+ import { createRequire } from "node:module";
1926
+ function enumMemberName(member, prefix2) {
1927
+ return member.slice(prefix2.length).toLowerCase().split("_").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("");
1928
+ }
1929
+ function eventTypeNames(enumObject = loadEventTypeEnum()) {
1930
+ const names = {};
1931
+ for (const [member, value] of Object.entries(enumObject)) {
1932
+ if (typeof value === "number" && member.startsWith("EVENT_TYPE_") && value !== 0) {
1933
+ names[value] = enumMemberName(member, "EVENT_TYPE_");
1934
+ }
1935
+ }
1936
+ return names;
1937
+ }
1938
+ function loadEventTypeEnum() {
1939
+ try {
1940
+ const require2 = createRequire(import.meta.url);
1941
+ const fromClient = createRequire(require2.resolve("@temporalio/client"));
1942
+ const proto = fromClient("@temporalio/proto");
1943
+ return proto.temporal.api.enums.v1.EventType;
1944
+ } catch {
1945
+ return {};
1946
+ }
1947
+ }
1948
+ var LIST_STATUSES = {
1949
+ running: "Running",
1950
+ completed: "Completed",
1951
+ failed: "Failed",
1952
+ canceled: "Canceled",
1953
+ terminated: "Terminated",
1954
+ "continued-as-new": "ContinuedAsNew",
1955
+ "timed-out": "TimedOut"
1956
+ };
1957
+ function quote(value) {
1958
+ return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
1959
+ }
1960
+ function buildListQuery(opts) {
1961
+ const clauses = [];
1962
+ if (opts.type) clauses.push(`WorkflowType = ${quote(opts.type)}`);
1963
+ if (opts.status) {
1964
+ const status = LIST_STATUSES[opts.status.toLowerCase()];
1965
+ if (!status) throw new Error(`--status must be one of: ${Object.keys(LIST_STATUSES).join(", ")}`);
1966
+ clauses.push(`ExecutionStatus = ${quote(status)}`);
1967
+ }
1968
+ if (opts.parent) clauses.push(`ParentWorkflowId = ${quote(opts.parent)}`);
1969
+ if (opts.query) clauses.push(clauses.length > 0 ? `(${opts.query})` : opts.query);
1970
+ return clauses.join(" AND ");
1971
+ }
1972
+ function formatListRows(rows) {
1973
+ const table = [
1974
+ ["WORKFLOW ID", "TYPE", "STATUS", "STARTED", "PARENT"],
1975
+ ...rows.map((r) => [
1976
+ r.workflowId,
1977
+ r.type,
1978
+ r.status,
1979
+ r.startTime ? r.startTime.toISOString().replace(/\.\d{3}Z$/, "Z") : "-",
1980
+ r.parentWorkflowId ?? "-"
1981
+ ])
1982
+ ];
1983
+ const widths = table[0].map((_, i) => Math.max(...table.map((row) => row[i].length)));
1984
+ return table.map((row) => row.map((cell, i) => i === row.length - 1 ? cell : cell.padEnd(widths[i])).join(" "));
1985
+ }
1986
+
1906
1987
  // packages/mesh-cli/src/commands/temporal.ts
1907
1988
  init_log();
1908
1989
  import { spawnSync } from "node:child_process";
@@ -2385,47 +2466,16 @@ async function resolveBearerToken(auth) {
2385
2466
  return void 0;
2386
2467
  }
2387
2468
  }
2388
- var EVENT_TYPE_NAMES = {
2389
- 1: "WorkflowExecutionStarted",
2390
- 2: "WorkflowExecutionCompleted",
2391
- 3: "WorkflowExecutionFailed",
2392
- 4: "WorkflowExecutionTimedOut",
2393
- 5: "WorkflowTaskScheduled",
2394
- 6: "WorkflowTaskStarted",
2395
- 7: "WorkflowTaskCompleted",
2396
- 8: "WorkflowTaskTimedOut",
2397
- 9: "WorkflowTaskFailed",
2398
- 10: "ActivityTaskScheduled",
2399
- 11: "ActivityTaskStarted",
2400
- 12: "ActivityTaskCompleted",
2401
- 13: "ActivityTaskFailed",
2402
- 14: "ActivityTaskTimedOut",
2403
- 15: "ActivityTaskCancelRequested",
2404
- 16: "ActivityTaskCanceled",
2405
- 17: "TimerStarted",
2406
- 18: "TimerFired",
2407
- 19: "TimerCanceled",
2408
- 20: "WorkflowExecutionCancelRequested",
2409
- 21: "WorkflowExecutionCanceled",
2410
- 24: "WorkflowExecutionSignaled",
2411
- // not 22/23 which were removed
2412
- 25: "WorkflowExecutionTerminated",
2413
- 26: "WorkflowExecutionSignaled",
2414
- 29: "WorkflowPropertiesModified",
2415
- 40: "ChildWorkflowExecutionStarted",
2416
- 41: "ChildWorkflowExecutionCompleted",
2417
- 42: "ChildWorkflowExecutionFailed",
2418
- 43: "ChildWorkflowExecutionCanceled",
2419
- 44: "ChildWorkflowExecutionTimedOut",
2420
- 45: "ChildWorkflowExecutionTerminated",
2421
- 46: "WorkflowPropertiesModified",
2422
- 48: "NexusOperationScheduled",
2423
- 49: "NexusOperationStarted",
2424
- 50: "NexusOperationCompleted",
2425
- 51: "NexusOperationFailed",
2426
- 52: "NexusOperationCanceled",
2427
- 53: "NexusOperationTimedOut"
2428
- };
2469
+ var eventTypeNameTable;
2470
+ function eventTypeName(type) {
2471
+ if (!eventTypeNameTable) {
2472
+ eventTypeNameTable = eventTypeNames();
2473
+ if (Object.keys(eventTypeNameTable).length === 0) {
2474
+ logWarn("could not load Temporal's EventType enum; event names will show as Unknown(n)");
2475
+ }
2476
+ }
2477
+ return eventTypeNameTable[type] ?? `Unknown(${type})`;
2478
+ }
2429
2479
  var STATUS_NAMES = {
2430
2480
  0: "UNSPECIFIED",
2431
2481
  1: "RUNNING",
@@ -2558,7 +2608,7 @@ ${totalShown} events shown (workflow ended).`);
2558
2608
  }
2559
2609
  async function printEvent(event, decrypter) {
2560
2610
  const eventType = event.eventType ?? 0;
2561
- const typeName = EVENT_TYPE_NAMES[eventType] ?? `Unknown(${eventType})`;
2611
+ const typeName = eventTypeName(eventType);
2562
2612
  const id = String(event.eventId).padStart(4);
2563
2613
  const detail = extractEventDetail(event);
2564
2614
  const detailStr = detail ? ` \u2014 ${detail}` : "";
@@ -2818,6 +2868,50 @@ function warnIfNotGitIgnored(outPath) {
2818
2868
  This fixture contains DECRYPTED production payloads. Add it to .gitignore or move it outside the repo \u2014 do NOT commit it.`
2819
2869
  );
2820
2870
  }
2871
+ function timestampToDate(ts) {
2872
+ if (!ts || ts.seconds === null || ts.seconds === void 0) return void 0;
2873
+ const seconds = Number(ts.seconds);
2874
+ return Number.isFinite(seconds) ? new Date(seconds * 1e3 + Math.floor((ts.nanos ?? 0) / 1e6)) : void 0;
2875
+ }
2876
+ async function listWorkflows(options) {
2877
+ const query = buildListQuery(options);
2878
+ const limit = Math.max(1, parseInt(options.limit ?? "20", 10) || 20);
2879
+ const conn = await connect(options);
2880
+ try {
2881
+ const rows = [];
2882
+ let nextPageToken;
2883
+ do {
2884
+ const page = await conn.connection.workflowService.listWorkflowExecutions({
2885
+ namespace: conn.namespace,
2886
+ query,
2887
+ pageSize: Math.min(limit - rows.length, 100),
2888
+ ...nextPageToken ? { nextPageToken } : {}
2889
+ });
2890
+ for (const info of page.executions ?? []) {
2891
+ rows.push({
2892
+ workflowId: info.execution?.workflowId ?? "?",
2893
+ type: info.type?.name ?? "?",
2894
+ status: STATUS_NAMES[info.status ?? 0] ?? String(info.status),
2895
+ startTime: timestampToDate(info.startTime),
2896
+ ...info.parentExecution?.workflowId ? { parentWorkflowId: info.parentExecution.workflowId } : {}
2897
+ });
2898
+ if (rows.length >= limit) break;
2899
+ }
2900
+ nextPageToken = page.nextPageToken?.length ? page.nextPageToken : void 0;
2901
+ } while (nextPageToken && rows.length < limit);
2902
+ if (options.json) {
2903
+ console.log(JSON.stringify(rows, null, 2));
2904
+ return;
2905
+ }
2906
+ if (rows.length === 0) {
2907
+ console.log(`No workflows${query ? ` match ${query}` : ""} in ${conn.namespace}.`);
2908
+ return;
2909
+ }
2910
+ for (const line of formatListRows(rows)) console.log(line);
2911
+ } finally {
2912
+ conn.connection.close();
2913
+ }
2914
+ }
2821
2915
  async function terminateWorkflow(workflowId, runId, options) {
2822
2916
  const conn = await connect(options);
2823
2917
  try {
@@ -2850,6 +2944,16 @@ async function connect(options) {
2850
2944
  function registerTemporalCommands(program) {
2851
2945
  const temporal = program.command("temporal").description("Inspect Temporal workflows for the current app/stack");
2852
2946
  const sharedOpts = (cmd) => cmd.option("--stack <stack>", "Pulumi stack name (auto-detected from current directory)").option("--address <addr>", "Temporal server address (default: from stack output)").option("--namespace <ns>", "Temporal namespace (default: from stack output)");
2947
+ sharedOpts(
2948
+ temporal.command("list").description("List workflows in the app's namespace, running first, then most recently closed (find the id the other commands take)").option("--type <workflowType>", "only this workflow type (e.g. agentWorkflow)").option("--status <status>", `only this status: ${Object.keys(LIST_STATUSES).join(", ")}`).option("--parent <workflowId>", "only the children of this workflow").option("--query <visibilityQuery>", "a Temporal visibility query, AND-ed with the flags above").option("-n, --limit <n>", "maximum workflows to list", "20").option("--json", "print JSON")
2949
+ ).action(async (opts) => {
2950
+ try {
2951
+ await listWorkflows(opts);
2952
+ } catch (err) {
2953
+ logError(err instanceof Error ? err.message : String(err));
2954
+ process.exitCode = 1;
2955
+ }
2956
+ });
2853
2957
  sharedOpts(
2854
2958
  temporal.command("describe <workflowId> [runId]").description("Show workflow status and metadata")
2855
2959
  ).action(async (workflowId, runId, opts) => {