@askexenow/exe-os 0.8.59 → 0.8.60

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.
@@ -1482,8 +1482,8 @@ var init_license = __esm({
1482
1482
  CACHE_PATH = path5.join(EXE_AI_DIR, "license-cache.json");
1483
1483
  DEVICE_ID_PATH = path5.join(EXE_AI_DIR, "device-id");
1484
1484
  PLAN_LIMITS = {
1485
- free: { devices: 1, employees: 1, memories: 5e3 },
1486
- pro: { devices: 2, employees: 5, memories: 1e5 },
1485
+ free: { devices: 1, employees: 1, memories: 5e4 },
1486
+ pro: { devices: 2, employees: 5, memories: 25e4 },
1487
1487
  team: { devices: 10, employees: 20, memories: 1e6 },
1488
1488
  agency: { devices: 50, employees: 100, memories: 1e7 },
1489
1489
  enterprise: { devices: -1, employees: -1, memories: -1 }
@@ -3477,18 +3477,21 @@ function exportBehaviorsSync(agentId, projectName2, sessionKey) {
3477
3477
  function getMySession() {
3478
3478
  return getTransport().getMySession();
3479
3479
  }
3480
+ function isRootSession(name) {
3481
+ return name.length > 0 && !name.includes("-");
3482
+ }
3480
3483
  function employeeSessionName(employee, exeSession, instance) {
3481
- if (!/^exe\d+$/.test(exeSession)) {
3484
+ if (!isRootSession(exeSession)) {
3482
3485
  const root = extractRootExe(exeSession);
3483
3486
  if (root) {
3484
3487
  process.stderr.write(
3485
- `[tmux-routing] WARN: exeSession="${exeSession}" is not a root exe session, using "${root}" instead
3488
+ `[tmux-routing] WARN: exeSession="${exeSession}" is not a root session, using "${root}" instead
3486
3489
  `
3487
3490
  );
3488
3491
  exeSession = root;
3489
3492
  } else {
3490
3493
  throw new Error(
3491
- `Invalid exeSession "${exeSession}" \u2014 must be a root exe session (e.g., "exe1"), not an agent session`
3494
+ `Invalid exeSession "${exeSession}" \u2014 contains a dash but no recognizable root session. Pass a root session name (e.g., "exe1", "work", "yoda1")`
3492
3495
  );
3493
3496
  }
3494
3497
  }
@@ -3496,7 +3499,7 @@ function employeeSessionName(employee, exeSession, instance) {
3496
3499
  const name = `${employee}${suffix}-${exeSession}`;
3497
3500
  if (!VALID_SESSION_NAME.test(name)) {
3498
3501
  throw new Error(
3499
- `Invalid session name "${name}" \u2014 must match {agent}-exe{N} or {agent}{instance}-exe{N}`
3502
+ `Invalid session name "${name}" \u2014 must match {agent}-{rootSession} or {agent}{instance}-{rootSession}`
3500
3503
  );
3501
3504
  }
3502
3505
  return name;
@@ -3739,11 +3742,11 @@ function ensureEmployee(employeeName, exeSession, projectDir, opts) {
3739
3742
  error: `Error: pass employee name ('${bare}'), not session name ('${employeeName}')`
3740
3743
  };
3741
3744
  }
3742
- if (!/^exe\d+$/.test(exeSession)) {
3745
+ if (!isRootSession(exeSession)) {
3743
3746
  const root = extractRootExe(exeSession);
3744
3747
  if (root) {
3745
3748
  process.stderr.write(
3746
- `[ensureEmployee] WARN: caller passed exeSession="${exeSession}" (not a root exe). Auto-correcting to "${root}".
3749
+ `[ensureEmployee] WARN: caller passed exeSession="${exeSession}" (not a root session). Auto-correcting to "${root}".
3747
3750
  `
3748
3751
  );
3749
3752
  exeSession = root;
@@ -3751,7 +3754,7 @@ function ensureEmployee(employeeName, exeSession, projectDir, opts) {
3751
3754
  return {
3752
3755
  status: "failed",
3753
3756
  sessionName: "",
3754
- error: `Invalid exeSession "${exeSession}" \u2014 must be a root exe session (e.g., "exe1")`
3757
+ error: `Invalid exeSession "${exeSession}" \u2014 contains a dash but no recognizable root session. Pass a root session name (e.g., "exe1", "work", "yoda1")`
3755
3758
  };
3756
3759
  }
3757
3760
  }
@@ -4016,7 +4019,7 @@ var init_tmux_routing = __esm({
4016
4019
  SPAWN_LOCK_DIR = path13.join(os5.homedir(), ".exe-os", "spawn-locks");
4017
4020
  SESSION_CACHE = path13.join(os5.homedir(), ".exe-os", "session-cache");
4018
4021
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
4019
- VALID_SESSION_NAME = /^[a-z]+-exe\d+$|^[a-z]+\d+-exe\d+$/;
4022
+ VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
4020
4023
  VERIFY_PANE_LINES = 200;
4021
4024
  INTERCOM_DEBOUNCE_MS = 3e4;
4022
4025
  INTERCOM_LOG2 = path13.join(os5.homedir(), ".exe-os", "intercom.log");
@@ -1482,8 +1482,8 @@ var init_license = __esm({
1482
1482
  CACHE_PATH = path5.join(EXE_AI_DIR, "license-cache.json");
1483
1483
  DEVICE_ID_PATH = path5.join(EXE_AI_DIR, "device-id");
1484
1484
  PLAN_LIMITS = {
1485
- free: { devices: 1, employees: 1, memories: 5e3 },
1486
- pro: { devices: 2, employees: 5, memories: 1e5 },
1485
+ free: { devices: 1, employees: 1, memories: 5e4 },
1486
+ pro: { devices: 2, employees: 5, memories: 25e4 },
1487
1487
  team: { devices: 10, employees: 20, memories: 1e6 },
1488
1488
  agency: { devices: 50, employees: 100, memories: 1e7 },
1489
1489
  enterprise: { devices: -1, employees: -1, memories: -1 }
@@ -3471,18 +3471,21 @@ function exportBehaviorsSync(agentId, projectName, sessionKey) {
3471
3471
  function getMySession() {
3472
3472
  return getTransport().getMySession();
3473
3473
  }
3474
+ function isRootSession(name) {
3475
+ return name.length > 0 && !name.includes("-");
3476
+ }
3474
3477
  function employeeSessionName(employee, exeSession, instance) {
3475
- if (!/^exe\d+$/.test(exeSession)) {
3478
+ if (!isRootSession(exeSession)) {
3476
3479
  const root = extractRootExe(exeSession);
3477
3480
  if (root) {
3478
3481
  process.stderr.write(
3479
- `[tmux-routing] WARN: exeSession="${exeSession}" is not a root exe session, using "${root}" instead
3482
+ `[tmux-routing] WARN: exeSession="${exeSession}" is not a root session, using "${root}" instead
3480
3483
  `
3481
3484
  );
3482
3485
  exeSession = root;
3483
3486
  } else {
3484
3487
  throw new Error(
3485
- `Invalid exeSession "${exeSession}" \u2014 must be a root exe session (e.g., "exe1"), not an agent session`
3488
+ `Invalid exeSession "${exeSession}" \u2014 contains a dash but no recognizable root session. Pass a root session name (e.g., "exe1", "work", "yoda1")`
3486
3489
  );
3487
3490
  }
3488
3491
  }
@@ -3490,7 +3493,7 @@ function employeeSessionName(employee, exeSession, instance) {
3490
3493
  const name = `${employee}${suffix}-${exeSession}`;
3491
3494
  if (!VALID_SESSION_NAME.test(name)) {
3492
3495
  throw new Error(
3493
- `Invalid session name "${name}" \u2014 must match {agent}-exe{N} or {agent}{instance}-exe{N}`
3496
+ `Invalid session name "${name}" \u2014 must match {agent}-{rootSession} or {agent}{instance}-{rootSession}`
3494
3497
  );
3495
3498
  }
3496
3499
  return name;
@@ -3733,11 +3736,11 @@ function ensureEmployee(employeeName, exeSession, projectDir, opts) {
3733
3736
  error: `Error: pass employee name ('${bare}'), not session name ('${employeeName}')`
3734
3737
  };
3735
3738
  }
3736
- if (!/^exe\d+$/.test(exeSession)) {
3739
+ if (!isRootSession(exeSession)) {
3737
3740
  const root = extractRootExe(exeSession);
3738
3741
  if (root) {
3739
3742
  process.stderr.write(
3740
- `[ensureEmployee] WARN: caller passed exeSession="${exeSession}" (not a root exe). Auto-correcting to "${root}".
3743
+ `[ensureEmployee] WARN: caller passed exeSession="${exeSession}" (not a root session). Auto-correcting to "${root}".
3741
3744
  `
3742
3745
  );
3743
3746
  exeSession = root;
@@ -3745,7 +3748,7 @@ function ensureEmployee(employeeName, exeSession, projectDir, opts) {
3745
3748
  return {
3746
3749
  status: "failed",
3747
3750
  sessionName: "",
3748
- error: `Invalid exeSession "${exeSession}" \u2014 must be a root exe session (e.g., "exe1")`
3751
+ error: `Invalid exeSession "${exeSession}" \u2014 contains a dash but no recognizable root session. Pass a root session name (e.g., "exe1", "work", "yoda1")`
3749
3752
  };
3750
3753
  }
3751
3754
  }
@@ -4010,7 +4013,7 @@ var init_tmux_routing = __esm({
4010
4013
  SPAWN_LOCK_DIR = path13.join(os5.homedir(), ".exe-os", "spawn-locks");
4011
4014
  SESSION_CACHE = path13.join(os5.homedir(), ".exe-os", "session-cache");
4012
4015
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
4013
- VALID_SESSION_NAME = /^[a-z]+-exe\d+$|^[a-z]+\d+-exe\d+$/;
4016
+ VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
4014
4017
  VERIFY_PANE_LINES = 200;
4015
4018
  INTERCOM_DEBOUNCE_MS = 3e4;
4016
4019
  INTERCOM_LOG2 = path13.join(os5.homedir(), ".exe-os", "intercom.log");
package/dist/bin/setup.js CHANGED
@@ -784,6 +784,32 @@ function readCachedToken() {
784
784
  return null;
785
785
  }
786
786
  }
787
+ function getRawCachedPlan() {
788
+ try {
789
+ const token = readCachedToken();
790
+ if (!token) return null;
791
+ const parts = token.split(".");
792
+ if (parts.length !== 3) return null;
793
+ const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString());
794
+ const plan = payload.plan ?? "free";
795
+ const limits = PLAN_LIMITS[plan] ?? PLAN_LIMITS.free;
796
+ process.stderr.write(
797
+ `[license] WARN: using unverified cached plan (API unreachable, JWT expired). Plan: ${plan}
798
+ `
799
+ );
800
+ return {
801
+ valid: true,
802
+ plan,
803
+ email: payload.sub ?? "",
804
+ expiresAt: payload.exp ? new Date(payload.exp * 1e3).toISOString() : null,
805
+ deviceLimit: limits.devices,
806
+ employeeLimit: limits.employees,
807
+ memoryLimit: limits.memories
808
+ };
809
+ } catch {
810
+ return null;
811
+ }
812
+ }
787
813
  function cacheResponse(token) {
788
814
  try {
789
815
  writeFileSync(CACHE_PATH, JSON.stringify({ token }), "utf8");
@@ -804,6 +830,8 @@ async function validateLicense(apiKey, deviceId) {
804
830
  if (data.error === "device_limit_exceeded") {
805
831
  const cached2 = await getCachedLicense();
806
832
  if (cached2) return cached2;
833
+ const raw2 = getRawCachedPlan();
834
+ if (raw2) return { ...raw2, valid: false };
807
835
  return { ...FREE_LICENSE, valid: false, plan: "free" };
808
836
  }
809
837
  if (data.token) {
@@ -824,10 +852,14 @@ async function validateLicense(apiKey, deviceId) {
824
852
  }
825
853
  const cached = await getCachedLicense();
826
854
  if (cached) return cached;
855
+ const raw = getRawCachedPlan();
856
+ if (raw) return raw;
827
857
  return { ...FREE_LICENSE, valid: false, plan: "free" };
828
858
  } catch {
829
859
  const cached = await getCachedLicense();
830
860
  if (cached) return cached;
861
+ const rawFallback = getRawCachedPlan();
862
+ if (rawFallback) return rawFallback;
831
863
  return { ...FREE_LICENSE, valid: false, error: "offline" };
832
864
  }
833
865
  }
@@ -1016,8 +1048,8 @@ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
1016
1048
  -----END PUBLIC KEY-----`;
1017
1049
  LICENSE_JWT_ALG = "ES256";
1018
1050
  PLAN_LIMITS = {
1019
- free: { devices: 1, employees: 1, memories: 5e3 },
1020
- pro: { devices: 2, employees: 5, memories: 1e5 },
1051
+ free: { devices: 1, employees: 1, memories: 5e4 },
1052
+ pro: { devices: 2, employees: 5, memories: 25e4 },
1021
1053
  team: { devices: 10, employees: 20, memories: 1e6 },
1022
1054
  agency: { devices: 50, employees: 100, memories: 1e7 },
1023
1055
  enterprise: { devices: -1, employees: -1, memories: -1 }
@@ -1029,7 +1061,7 @@ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
1029
1061
  expiresAt: null,
1030
1062
  deviceLimit: 1,
1031
1063
  employeeLimit: 1,
1032
- memoryLimit: 5e3
1064
+ memoryLimit: 5e4
1033
1065
  };
1034
1066
  CACHE_MAX_AGE_MS = 36e5;
1035
1067
  _revalTimer = null;
@@ -215,6 +215,32 @@ function readCachedToken() {
215
215
  return null;
216
216
  }
217
217
  }
218
+ function getRawCachedPlan() {
219
+ try {
220
+ const token = readCachedToken();
221
+ if (!token) return null;
222
+ const parts = token.split(".");
223
+ if (parts.length !== 3) return null;
224
+ const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString());
225
+ const plan = payload.plan ?? "free";
226
+ const limits = PLAN_LIMITS[plan] ?? PLAN_LIMITS.free;
227
+ process.stderr.write(
228
+ `[license] WARN: using unverified cached plan (API unreachable, JWT expired). Plan: ${plan}
229
+ `
230
+ );
231
+ return {
232
+ valid: true,
233
+ plan,
234
+ email: payload.sub ?? "",
235
+ expiresAt: payload.exp ? new Date(payload.exp * 1e3).toISOString() : null,
236
+ deviceLimit: limits.devices,
237
+ employeeLimit: limits.employees,
238
+ memoryLimit: limits.memories
239
+ };
240
+ } catch {
241
+ return null;
242
+ }
243
+ }
218
244
  function cacheResponse(token) {
219
245
  try {
220
246
  writeFileSync(CACHE_PATH, JSON.stringify({ token }), "utf8");
@@ -235,6 +261,8 @@ async function validateLicense(apiKey, deviceId) {
235
261
  if (data.error === "device_limit_exceeded") {
236
262
  const cached2 = await getCachedLicense();
237
263
  if (cached2) return cached2;
264
+ const raw2 = getRawCachedPlan();
265
+ if (raw2) return { ...raw2, valid: false };
238
266
  return { ...FREE_LICENSE, valid: false, plan: "free" };
239
267
  }
240
268
  if (data.token) {
@@ -255,10 +283,14 @@ async function validateLicense(apiKey, deviceId) {
255
283
  }
256
284
  const cached = await getCachedLicense();
257
285
  if (cached) return cached;
286
+ const raw = getRawCachedPlan();
287
+ if (raw) return raw;
258
288
  return { ...FREE_LICENSE, valid: false, plan: "free" };
259
289
  } catch {
260
290
  const cached = await getCachedLicense();
261
291
  if (cached) return cached;
292
+ const rawFallback = getRawCachedPlan();
293
+ if (rawFallback) return rawFallback;
262
294
  return { ...FREE_LICENSE, valid: false, error: "offline" };
263
295
  }
264
296
  }
@@ -447,8 +479,8 @@ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
447
479
  -----END PUBLIC KEY-----`;
448
480
  LICENSE_JWT_ALG = "ES256";
449
481
  PLAN_LIMITS = {
450
- free: { devices: 1, employees: 1, memories: 5e3 },
451
- pro: { devices: 2, employees: 5, memories: 1e5 },
482
+ free: { devices: 1, employees: 1, memories: 5e4 },
483
+ pro: { devices: 2, employees: 5, memories: 25e4 },
452
484
  team: { devices: 10, employees: 20, memories: 1e6 },
453
485
  agency: { devices: 50, employees: 100, memories: 1e7 },
454
486
  enterprise: { devices: -1, employees: -1, memories: -1 }
@@ -460,7 +492,7 @@ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
460
492
  expiresAt: null,
461
493
  deviceLimit: 1,
462
494
  employeeLimit: 1,
463
- memoryLimit: 5e3
495
+ memoryLimit: 5e4
464
496
  };
465
497
  CACHE_MAX_AGE_MS = 36e5;
466
498
  _revalTimer = null;
@@ -3411,8 +3411,8 @@ var init_license = __esm({
3411
3411
  CACHE_PATH = path9.join(EXE_AI_DIR, "license-cache.json");
3412
3412
  DEVICE_ID_PATH = path9.join(EXE_AI_DIR, "device-id");
3413
3413
  PLAN_LIMITS = {
3414
- free: { devices: 1, employees: 1, memories: 5e3 },
3415
- pro: { devices: 2, employees: 5, memories: 1e5 },
3414
+ free: { devices: 1, employees: 1, memories: 5e4 },
3415
+ pro: { devices: 2, employees: 5, memories: 25e4 },
3416
3416
  team: { devices: 10, employees: 20, memories: 1e6 },
3417
3417
  agency: { devices: 50, employees: 100, memories: 1e7 },
3418
3418
  enterprise: { devices: -1, employees: -1, memories: -1 }
@@ -5360,18 +5360,21 @@ function exportBehaviorsSync(agentId, projectName, sessionKey) {
5360
5360
  function getMySession() {
5361
5361
  return getTransport().getMySession();
5362
5362
  }
5363
+ function isRootSession(name) {
5364
+ return name.length > 0 && !name.includes("-");
5365
+ }
5363
5366
  function employeeSessionName(employee, exeSession, instance) {
5364
- if (!/^exe\d+$/.test(exeSession)) {
5367
+ if (!isRootSession(exeSession)) {
5365
5368
  const root = extractRootExe(exeSession);
5366
5369
  if (root) {
5367
5370
  process.stderr.write(
5368
- `[tmux-routing] WARN: exeSession="${exeSession}" is not a root exe session, using "${root}" instead
5371
+ `[tmux-routing] WARN: exeSession="${exeSession}" is not a root session, using "${root}" instead
5369
5372
  `
5370
5373
  );
5371
5374
  exeSession = root;
5372
5375
  } else {
5373
5376
  throw new Error(
5374
- `Invalid exeSession "${exeSession}" \u2014 must be a root exe session (e.g., "exe1"), not an agent session`
5377
+ `Invalid exeSession "${exeSession}" \u2014 contains a dash but no recognizable root session. Pass a root session name (e.g., "exe1", "work", "yoda1")`
5375
5378
  );
5376
5379
  }
5377
5380
  }
@@ -5379,7 +5382,7 @@ function employeeSessionName(employee, exeSession, instance) {
5379
5382
  const name = `${employee}${suffix}-${exeSession}`;
5380
5383
  if (!VALID_SESSION_NAME.test(name)) {
5381
5384
  throw new Error(
5382
- `Invalid session name "${name}" \u2014 must match {agent}-exe{N} or {agent}{instance}-exe{N}`
5385
+ `Invalid session name "${name}" \u2014 must match {agent}-{rootSession} or {agent}{instance}-{rootSession}`
5383
5386
  );
5384
5387
  }
5385
5388
  return name;
@@ -5622,11 +5625,11 @@ function ensureEmployee(employeeName, exeSession, projectDir, opts) {
5622
5625
  error: `Error: pass employee name ('${bare}'), not session name ('${employeeName}')`
5623
5626
  };
5624
5627
  }
5625
- if (!/^exe\d+$/.test(exeSession)) {
5628
+ if (!isRootSession(exeSession)) {
5626
5629
  const root = extractRootExe(exeSession);
5627
5630
  if (root) {
5628
5631
  process.stderr.write(
5629
- `[ensureEmployee] WARN: caller passed exeSession="${exeSession}" (not a root exe). Auto-correcting to "${root}".
5632
+ `[ensureEmployee] WARN: caller passed exeSession="${exeSession}" (not a root session). Auto-correcting to "${root}".
5630
5633
  `
5631
5634
  );
5632
5635
  exeSession = root;
@@ -5634,7 +5637,7 @@ function ensureEmployee(employeeName, exeSession, projectDir, opts) {
5634
5637
  return {
5635
5638
  status: "failed",
5636
5639
  sessionName: "",
5637
- error: `Invalid exeSession "${exeSession}" \u2014 must be a root exe session (e.g., "exe1")`
5640
+ error: `Invalid exeSession "${exeSession}" \u2014 contains a dash but no recognizable root session. Pass a root session name (e.g., "exe1", "work", "yoda1")`
5638
5641
  };
5639
5642
  }
5640
5643
  }
@@ -5899,7 +5902,7 @@ var init_tmux_routing = __esm({
5899
5902
  SPAWN_LOCK_DIR = path17.join(os7.homedir(), ".exe-os", "spawn-locks");
5900
5903
  SESSION_CACHE = path17.join(os7.homedir(), ".exe-os", "session-cache");
5901
5904
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
5902
- VALID_SESSION_NAME = /^[a-z]+-exe\d+$|^[a-z]+\d+-exe\d+$/;
5905
+ VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
5903
5906
  VERIFY_PANE_LINES = 200;
5904
5907
  INTERCOM_DEBOUNCE_MS = 3e4;
5905
5908
  INTERCOM_LOG2 = path17.join(os7.homedir(), ".exe-os", "intercom.log");
@@ -2093,8 +2093,8 @@ var init_license = __esm({
2093
2093
  CACHE_PATH = path8.join(EXE_AI_DIR, "license-cache.json");
2094
2094
  DEVICE_ID_PATH = path8.join(EXE_AI_DIR, "device-id");
2095
2095
  PLAN_LIMITS = {
2096
- free: { devices: 1, employees: 1, memories: 5e3 },
2097
- pro: { devices: 2, employees: 5, memories: 1e5 },
2096
+ free: { devices: 1, employees: 1, memories: 5e4 },
2097
+ pro: { devices: 2, employees: 5, memories: 25e4 },
2098
2098
  team: { devices: 10, employees: 20, memories: 1e6 },
2099
2099
  agency: { devices: 50, employees: 100, memories: 1e7 },
2100
2100
  enterprise: { devices: -1, employees: -1, memories: -1 }
@@ -2598,18 +2598,21 @@ function exportBehaviorsSync(agentId, projectName, sessionKey) {
2598
2598
  function getMySession() {
2599
2599
  return getTransport().getMySession();
2600
2600
  }
2601
+ function isRootSession(name) {
2602
+ return name.length > 0 && !name.includes("-");
2603
+ }
2601
2604
  function employeeSessionName(employee, exeSession, instance) {
2602
- if (!/^exe\d+$/.test(exeSession)) {
2605
+ if (!isRootSession(exeSession)) {
2603
2606
  const root = extractRootExe(exeSession);
2604
2607
  if (root) {
2605
2608
  process.stderr.write(
2606
- `[tmux-routing] WARN: exeSession="${exeSession}" is not a root exe session, using "${root}" instead
2609
+ `[tmux-routing] WARN: exeSession="${exeSession}" is not a root session, using "${root}" instead
2607
2610
  `
2608
2611
  );
2609
2612
  exeSession = root;
2610
2613
  } else {
2611
2614
  throw new Error(
2612
- `Invalid exeSession "${exeSession}" \u2014 must be a root exe session (e.g., "exe1"), not an agent session`
2615
+ `Invalid exeSession "${exeSession}" \u2014 contains a dash but no recognizable root session. Pass a root session name (e.g., "exe1", "work", "yoda1")`
2613
2616
  );
2614
2617
  }
2615
2618
  }
@@ -2617,7 +2620,7 @@ function employeeSessionName(employee, exeSession, instance) {
2617
2620
  const name = `${employee}${suffix}-${exeSession}`;
2618
2621
  if (!VALID_SESSION_NAME.test(name)) {
2619
2622
  throw new Error(
2620
- `Invalid session name "${name}" \u2014 must match {agent}-exe{N} or {agent}{instance}-exe{N}`
2623
+ `Invalid session name "${name}" \u2014 must match {agent}-{rootSession} or {agent}{instance}-{rootSession}`
2621
2624
  );
2622
2625
  }
2623
2626
  return name;
@@ -2860,11 +2863,11 @@ function ensureEmployee(employeeName, exeSession, projectDir, opts) {
2860
2863
  error: `Error: pass employee name ('${bare}'), not session name ('${employeeName}')`
2861
2864
  };
2862
2865
  }
2863
- if (!/^exe\d+$/.test(exeSession)) {
2866
+ if (!isRootSession(exeSession)) {
2864
2867
  const root = extractRootExe(exeSession);
2865
2868
  if (root) {
2866
2869
  process.stderr.write(
2867
- `[ensureEmployee] WARN: caller passed exeSession="${exeSession}" (not a root exe). Auto-correcting to "${root}".
2870
+ `[ensureEmployee] WARN: caller passed exeSession="${exeSession}" (not a root session). Auto-correcting to "${root}".
2868
2871
  `
2869
2872
  );
2870
2873
  exeSession = root;
@@ -2872,7 +2875,7 @@ function ensureEmployee(employeeName, exeSession, projectDir, opts) {
2872
2875
  return {
2873
2876
  status: "failed",
2874
2877
  sessionName: "",
2875
- error: `Invalid exeSession "${exeSession}" \u2014 must be a root exe session (e.g., "exe1")`
2878
+ error: `Invalid exeSession "${exeSession}" \u2014 contains a dash but no recognizable root session. Pass a root session name (e.g., "exe1", "work", "yoda1")`
2876
2879
  };
2877
2880
  }
2878
2881
  }
@@ -3137,7 +3140,7 @@ var init_tmux_routing = __esm({
3137
3140
  SPAWN_LOCK_DIR = path10.join(os6.homedir(), ".exe-os", "spawn-locks");
3138
3141
  SESSION_CACHE = path10.join(os6.homedir(), ".exe-os", "session-cache");
3139
3142
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
3140
- VALID_SESSION_NAME = /^[a-z]+-exe\d+$|^[a-z]+\d+-exe\d+$/;
3143
+ VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
3141
3144
  VERIFY_PANE_LINES = 200;
3142
3145
  INTERCOM_DEBOUNCE_MS = 3e4;
3143
3146
  INTERCOM_LOG2 = path10.join(os6.homedir(), ".exe-os", "intercom.log");
@@ -1481,8 +1481,8 @@ var init_license = __esm({
1481
1481
  CACHE_PATH = path5.join(EXE_AI_DIR, "license-cache.json");
1482
1482
  DEVICE_ID_PATH = path5.join(EXE_AI_DIR, "device-id");
1483
1483
  PLAN_LIMITS = {
1484
- free: { devices: 1, employees: 1, memories: 5e3 },
1485
- pro: { devices: 2, employees: 5, memories: 1e5 },
1484
+ free: { devices: 1, employees: 1, memories: 5e4 },
1485
+ pro: { devices: 2, employees: 5, memories: 25e4 },
1486
1486
  team: { devices: 10, employees: 20, memories: 1e6 },
1487
1487
  agency: { devices: 50, employees: 100, memories: 1e7 },
1488
1488
  enterprise: { devices: -1, employees: -1, memories: -1 }
@@ -3476,18 +3476,21 @@ function exportBehaviorsSync(agentId, projectName, sessionKey) {
3476
3476
  function getMySession() {
3477
3477
  return getTransport().getMySession();
3478
3478
  }
3479
+ function isRootSession(name) {
3480
+ return name.length > 0 && !name.includes("-");
3481
+ }
3479
3482
  function employeeSessionName(employee, exeSession, instance) {
3480
- if (!/^exe\d+$/.test(exeSession)) {
3483
+ if (!isRootSession(exeSession)) {
3481
3484
  const root = extractRootExe(exeSession);
3482
3485
  if (root) {
3483
3486
  process.stderr.write(
3484
- `[tmux-routing] WARN: exeSession="${exeSession}" is not a root exe session, using "${root}" instead
3487
+ `[tmux-routing] WARN: exeSession="${exeSession}" is not a root session, using "${root}" instead
3485
3488
  `
3486
3489
  );
3487
3490
  exeSession = root;
3488
3491
  } else {
3489
3492
  throw new Error(
3490
- `Invalid exeSession "${exeSession}" \u2014 must be a root exe session (e.g., "exe1"), not an agent session`
3493
+ `Invalid exeSession "${exeSession}" \u2014 contains a dash but no recognizable root session. Pass a root session name (e.g., "exe1", "work", "yoda1")`
3491
3494
  );
3492
3495
  }
3493
3496
  }
@@ -3495,7 +3498,7 @@ function employeeSessionName(employee, exeSession, instance) {
3495
3498
  const name = `${employee}${suffix}-${exeSession}`;
3496
3499
  if (!VALID_SESSION_NAME.test(name)) {
3497
3500
  throw new Error(
3498
- `Invalid session name "${name}" \u2014 must match {agent}-exe{N} or {agent}{instance}-exe{N}`
3501
+ `Invalid session name "${name}" \u2014 must match {agent}-{rootSession} or {agent}{instance}-{rootSession}`
3499
3502
  );
3500
3503
  }
3501
3504
  return name;
@@ -3738,11 +3741,11 @@ function ensureEmployee(employeeName, exeSession, projectDir, opts) {
3738
3741
  error: `Error: pass employee name ('${bare}'), not session name ('${employeeName}')`
3739
3742
  };
3740
3743
  }
3741
- if (!/^exe\d+$/.test(exeSession)) {
3744
+ if (!isRootSession(exeSession)) {
3742
3745
  const root = extractRootExe(exeSession);
3743
3746
  if (root) {
3744
3747
  process.stderr.write(
3745
- `[ensureEmployee] WARN: caller passed exeSession="${exeSession}" (not a root exe). Auto-correcting to "${root}".
3748
+ `[ensureEmployee] WARN: caller passed exeSession="${exeSession}" (not a root session). Auto-correcting to "${root}".
3746
3749
  `
3747
3750
  );
3748
3751
  exeSession = root;
@@ -3750,7 +3753,7 @@ function ensureEmployee(employeeName, exeSession, projectDir, opts) {
3750
3753
  return {
3751
3754
  status: "failed",
3752
3755
  sessionName: "",
3753
- error: `Invalid exeSession "${exeSession}" \u2014 must be a root exe session (e.g., "exe1")`
3756
+ error: `Invalid exeSession "${exeSession}" \u2014 contains a dash but no recognizable root session. Pass a root session name (e.g., "exe1", "work", "yoda1")`
3754
3757
  };
3755
3758
  }
3756
3759
  }
@@ -4015,7 +4018,7 @@ var init_tmux_routing = __esm({
4015
4018
  SPAWN_LOCK_DIR = path13.join(os5.homedir(), ".exe-os", "spawn-locks");
4016
4019
  SESSION_CACHE = path13.join(os5.homedir(), ".exe-os", "session-cache");
4017
4020
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
4018
- VALID_SESSION_NAME = /^[a-z]+-exe\d+$|^[a-z]+\d+-exe\d+$/;
4021
+ VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
4019
4022
  VERIFY_PANE_LINES = 200;
4020
4023
  INTERCOM_DEBOUNCE_MS = 3e4;
4021
4024
  INTERCOM_LOG2 = path13.join(os5.homedir(), ".exe-os", "intercom.log");