@askexenow/exe-os 0.9.92 → 0.9.93

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/cli.js CHANGED
@@ -20315,7 +20315,7 @@ function hydrateEnv(raw, opts) {
20315
20315
  for (const [key, value] of env.entries()) {
20316
20316
  if (!/CHANGEME/.test(value)) continue;
20317
20317
  if (key === "EXE_LICENSE_KEY" && license) replacements[key] = license;
20318
- else if (key === "MONITOR_AGENT_KEY") continue;
20318
+ else if (key === "MONITOR_AGENT_TOKEN" || key === "MONITOR_AGENT_KEY") continue;
20319
20319
  else if (key === "EXE_GATEWAY_WS_RELAY_AUTH_TOKEN") replacements[key] = randomHexSecret(24);
20320
20320
  else if (key.endsWith("_PASSWORD")) replacements[key] = randomSecret(24);
20321
20321
  else if (key.endsWith("_TOKEN")) replacements[key] = randomHexSecret(32);
@@ -20327,6 +20327,45 @@ function hydrateEnv(raw, opts) {
20327
20327
  const remaining = [...parseEnv(next).entries()].filter(([, value]) => /CHANGEME/.test(value)).map(([key, value]) => `${key}=${value}`);
20328
20328
  return { raw: next, hadPlaceholders: /CHANGEME/.test(raw), remaining: [...new Set(remaining)] };
20329
20329
  }
20330
+ async function pairMonitorAgent(hubUrl, licenseKey, domain, envFile) {
20331
+ if (!hubUrl || !licenseKey || !domain) {
20332
+ return { paired: false, error: "Missing hubUrl, licenseKey, or domain for monitor pairing" };
20333
+ }
20334
+ const registrationUrl = `${hubUrl.replace(/\/+$/, "")}/api/register-agent`;
20335
+ try {
20336
+ const res = await fetch(registrationUrl, {
20337
+ method: "POST",
20338
+ headers: {
20339
+ "content-type": "application/json",
20340
+ authorization: `Bearer ${licenseKey}`
20341
+ },
20342
+ body: JSON.stringify({ name: domain, host: domain, port: 45876 }),
20343
+ signal: AbortSignal.timeout(15e3)
20344
+ });
20345
+ if (!res.ok) {
20346
+ const body = await res.text().catch(() => "");
20347
+ return { paired: false, error: `Monitor hub returned HTTP ${res.status}: ${body}` };
20348
+ }
20349
+ const data = await res.json();
20350
+ if (!data.token || !data.key) {
20351
+ return { paired: false, error: "Monitor hub response missing token or key" };
20352
+ }
20353
+ if (existsSync34(envFile)) {
20354
+ const envRaw = readFileSync29(envFile, "utf8");
20355
+ const patched = patchEnv(envRaw, {
20356
+ MONITOR_AGENT_TOKEN: data.token,
20357
+ MONITOR_AGENT_KEY: data.key
20358
+ });
20359
+ if (patched !== envRaw) {
20360
+ writeFileSync25(envFile, patched, { mode: 384 });
20361
+ }
20362
+ }
20363
+ return { paired: true, systemName: data.name ?? domain };
20364
+ } catch (err) {
20365
+ const reason = err instanceof Error ? err.message : String(err);
20366
+ return { paired: false, error: `Monitor hub unreachable: ${reason}` };
20367
+ }
20368
+ }
20330
20369
  function bootstrapStackHost(options) {
20331
20370
  const exec2 = options.exec ?? defaultExec;
20332
20371
  const createdFiles = [];
@@ -20399,6 +20438,24 @@ async function runStackUpdate(options) {
20399
20438
  const report = bootstrapStackHost({ ...options, installDocker: options.installDocker ?? !!options.yes });
20400
20439
  if (!options.dryRun) assertHostReadyForApply(report);
20401
20440
  }
20441
+ const hubUrl = options.monitorHubUrl || parseEnv(readFileSync29(options.envFile, "utf8")).get("MONITOR_HUB_URL") || "";
20442
+ const pairLicense = options.licenseKey || process.env.EXE_LICENSE_KEY || loadLicense() || "";
20443
+ const pairDomain = options.domain || process.env.EXE_STACK_DOMAIN || process.env.CUSTOMER_DOMAIN || "";
20444
+ if (hubUrl && pairLicense && pairDomain) {
20445
+ const envBefore = readFileSync29(options.envFile, "utf8");
20446
+ const hasPlaceholder = /CHANGEME/.test(parseEnv(envBefore).get("MONITOR_AGENT_TOKEN") ?? "");
20447
+ if (hasPlaceholder) {
20448
+ const pair = options.pairMonitor ? options.pairMonitor(hubUrl, pairLicense, pairDomain, options.envFile) : pairMonitorAgent(hubUrl, pairLicense, pairDomain, options.envFile);
20449
+ const result = await pair;
20450
+ if (typeof result === "object" && result && "paired" in result) {
20451
+ if (result.paired) {
20452
+ console.log(`[stack-update] Monitor agent paired: ${result.systemName}`);
20453
+ } else {
20454
+ console.warn(`[stack-update] Monitor pairing skipped: ${result.error}`);
20455
+ }
20456
+ }
20457
+ }
20458
+ }
20402
20459
  const manifest = await loadStackManifest(options.manifestRef, options.fetchText, options.manifestPublicKey, options.manifestAuthToken);
20403
20460
  const envRaw = readFileSync29(options.envFile, "utf8");
20404
20461
  const plan = createStackUpdatePlan(manifest, envRaw, options.targetVersion);
@@ -467,7 +467,7 @@ function hydrateEnv(raw, opts) {
467
467
  for (const [key, value] of env.entries()) {
468
468
  if (!/CHANGEME/.test(value)) continue;
469
469
  if (key === "EXE_LICENSE_KEY" && license) replacements[key] = license;
470
- else if (key === "MONITOR_AGENT_KEY") continue;
470
+ else if (key === "MONITOR_AGENT_TOKEN" || key === "MONITOR_AGENT_KEY") continue;
471
471
  else if (key === "EXE_GATEWAY_WS_RELAY_AUTH_TOKEN") replacements[key] = randomHexSecret(24);
472
472
  else if (key.endsWith("_PASSWORD")) replacements[key] = randomSecret(24);
473
473
  else if (key.endsWith("_TOKEN")) replacements[key] = randomHexSecret(32);
@@ -479,6 +479,45 @@ function hydrateEnv(raw, opts) {
479
479
  const remaining = [...parseEnv(next).entries()].filter(([, value]) => /CHANGEME/.test(value)).map(([key, value]) => `${key}=${value}`);
480
480
  return { raw: next, hadPlaceholders: /CHANGEME/.test(raw), remaining: [...new Set(remaining)] };
481
481
  }
482
+ async function pairMonitorAgent(hubUrl, licenseKey, domain, envFile) {
483
+ if (!hubUrl || !licenseKey || !domain) {
484
+ return { paired: false, error: "Missing hubUrl, licenseKey, or domain for monitor pairing" };
485
+ }
486
+ const registrationUrl = `${hubUrl.replace(/\/+$/, "")}/api/register-agent`;
487
+ try {
488
+ const res = await fetch(registrationUrl, {
489
+ method: "POST",
490
+ headers: {
491
+ "content-type": "application/json",
492
+ authorization: `Bearer ${licenseKey}`
493
+ },
494
+ body: JSON.stringify({ name: domain, host: domain, port: 45876 }),
495
+ signal: AbortSignal.timeout(15e3)
496
+ });
497
+ if (!res.ok) {
498
+ const body = await res.text().catch(() => "");
499
+ return { paired: false, error: `Monitor hub returned HTTP ${res.status}: ${body}` };
500
+ }
501
+ const data = await res.json();
502
+ if (!data.token || !data.key) {
503
+ return { paired: false, error: "Monitor hub response missing token or key" };
504
+ }
505
+ if (existsSync4(envFile)) {
506
+ const envRaw = readFileSync3(envFile, "utf8");
507
+ const patched = patchEnv(envRaw, {
508
+ MONITOR_AGENT_TOKEN: data.token,
509
+ MONITOR_AGENT_KEY: data.key
510
+ });
511
+ if (patched !== envRaw) {
512
+ writeFileSync2(envFile, patched, { mode: 384 });
513
+ }
514
+ }
515
+ return { paired: true, systemName: data.name ?? domain };
516
+ } catch (err) {
517
+ const reason = err instanceof Error ? err.message : String(err);
518
+ return { paired: false, error: `Monitor hub unreachable: ${reason}` };
519
+ }
520
+ }
482
521
  function bootstrapStackHost(options) {
483
522
  const exec = options.exec ?? defaultExec;
484
523
  const createdFiles = [];
@@ -551,6 +590,24 @@ async function runStackUpdate(options) {
551
590
  const report = bootstrapStackHost({ ...options, installDocker: options.installDocker ?? !!options.yes });
552
591
  if (!options.dryRun) assertHostReadyForApply(report);
553
592
  }
593
+ const hubUrl = options.monitorHubUrl || parseEnv(readFileSync3(options.envFile, "utf8")).get("MONITOR_HUB_URL") || "";
594
+ const pairLicense = options.licenseKey || process.env.EXE_LICENSE_KEY || loadLicense() || "";
595
+ const pairDomain = options.domain || process.env.EXE_STACK_DOMAIN || process.env.CUSTOMER_DOMAIN || "";
596
+ if (hubUrl && pairLicense && pairDomain) {
597
+ const envBefore = readFileSync3(options.envFile, "utf8");
598
+ const hasPlaceholder = /CHANGEME/.test(parseEnv(envBefore).get("MONITOR_AGENT_TOKEN") ?? "");
599
+ if (hasPlaceholder) {
600
+ const pair = options.pairMonitor ? options.pairMonitor(hubUrl, pairLicense, pairDomain, options.envFile) : pairMonitorAgent(hubUrl, pairLicense, pairDomain, options.envFile);
601
+ const result = await pair;
602
+ if (typeof result === "object" && result && "paired" in result) {
603
+ if (result.paired) {
604
+ console.log(`[stack-update] Monitor agent paired: ${result.systemName}`);
605
+ } else {
606
+ console.warn(`[stack-update] Monitor pairing skipped: ${result.error}`);
607
+ }
608
+ }
609
+ }
610
+ }
554
611
  const manifest = await loadStackManifest(options.manifestRef, options.fetchText, options.manifestPublicKey, options.manifestAuthToken);
555
612
  const envRaw = readFileSync3(options.envFile, "utf8");
556
613
  const plan = createStackUpdatePlan(manifest, envRaw, options.targetVersion);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askexenow/exe-os",
3
- "version": "0.9.92",
3
+ "version": "0.9.93",
4
4
  "description": "AI employee operating system — persistent memory, task management, and multi-agent coordination for Claude Code.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",