glass-connect 0.3.0 → 1.0.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 (3) hide show
  1. package/README.md +17 -3
  2. package/dist/cli.js +283 -150
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -7,8 +7,22 @@ Project, or share the computer with an organization.
7
7
  npx glass-connect@latest
8
8
  ```
9
9
 
10
- Enter the one-time code in **Glass Settings Computers**. The command installs a per-user
11
- background service on macOS, Windows, and Linux, including a private copy of its Node runtime. Use
12
- `glass-connect status`, `stop`, `start`, or `uninstall` to manage it.
10
+ The command opens a host-bound Glass pairing link. If the link is opened in a different Glass
11
+ environment, that environment cannot approve the challenge. You can select the preview backend
12
+ explicitly:
13
+
14
+ ```sh
15
+ npx glass-connect@latest --environment preview
16
+ ```
17
+
18
+ The command installs a per-user background service on macOS, Windows, and Linux, including a
19
+ private copy of its Node runtime. Use `glass-connect update` to replace that service with the exact
20
+ version you installed. Use `glass-connect status`, `stop`, `start`, or `uninstall` to manage it.
21
+
22
+ For a pinned update, use the exact published version:
23
+
24
+ ```sh
25
+ npx glass-connect@1.0.0 update
26
+ ```
13
27
 
14
28
  Glass Connect requires Node.js 24.13.1 or newer for installation.
package/dist/cli.js CHANGED
@@ -53,32 +53,32 @@ var __toESM = (mod2, isNodeMode, target) => (target = mod2 != null ? __create(__
53
53
  var pipeArguments, Prototype, Class;
54
54
  var init_Pipeable = __esm({
55
55
  "../../node_modules/.pnpm/effect@4.0.0-rc.108/node_modules/effect/dist/Pipeable.js"() {
56
- pipeArguments = (self, args3) => {
57
- switch (args3.length) {
56
+ pipeArguments = (self, args4) => {
57
+ switch (args4.length) {
58
58
  case 0:
59
59
  return self;
60
60
  case 1:
61
- return args3[0](self);
61
+ return args4[0](self);
62
62
  case 2:
63
- return args3[1](args3[0](self));
63
+ return args4[1](args4[0](self));
64
64
  case 3:
65
- return args3[2](args3[1](args3[0](self)));
65
+ return args4[2](args4[1](args4[0](self)));
66
66
  case 4:
67
- return args3[3](args3[2](args3[1](args3[0](self))));
67
+ return args4[3](args4[2](args4[1](args4[0](self))));
68
68
  case 5:
69
- return args3[4](args3[3](args3[2](args3[1](args3[0](self)))));
69
+ return args4[4](args4[3](args4[2](args4[1](args4[0](self)))));
70
70
  case 6:
71
- return args3[5](args3[4](args3[3](args3[2](args3[1](args3[0](self))))));
71
+ return args4[5](args4[4](args4[3](args4[2](args4[1](args4[0](self))))));
72
72
  case 7:
73
- return args3[6](args3[5](args3[4](args3[3](args3[2](args3[1](args3[0](self)))))));
73
+ return args4[6](args4[5](args4[4](args4[3](args4[2](args4[1](args4[0](self)))))));
74
74
  case 8:
75
- return args3[7](args3[6](args3[5](args3[4](args3[3](args3[2](args3[1](args3[0](self))))))));
75
+ return args4[7](args4[6](args4[5](args4[4](args4[3](args4[2](args4[1](args4[0](self))))))));
76
76
  case 9:
77
- return args3[8](args3[7](args3[6](args3[5](args3[4](args3[3](args3[2](args3[1](args3[0](self)))))))));
77
+ return args4[8](args4[7](args4[6](args4[5](args4[4](args4[3](args4[2](args4[1](args4[0](self)))))))));
78
78
  default: {
79
79
  let ret = self;
80
- for (let i = 0, len = args3.length; i < len; i++) {
81
- ret = args3[i](ret);
80
+ for (let i = 0, len = args4.length; i < len; i++) {
81
+ ret = args4[i](ret);
82
82
  }
83
83
  return ret;
84
84
  }
@@ -99,8 +99,8 @@ var init_Pipeable = __esm({
99
99
  });
100
100
 
101
101
  // ../../node_modules/.pnpm/effect@4.0.0-rc.108/node_modules/effect/dist/Function.js
102
- function pipe(a, ...args3) {
103
- return pipeArguments(a, args3);
102
+ function pipe(a, ...args4) {
103
+ return pipeArguments(a, args4);
104
104
  }
105
105
  function memoize(f2) {
106
106
  const cache = /* @__PURE__ */ new WeakMap();
@@ -160,9 +160,9 @@ var init_Function = __esm({
160
160
  if (arguments.length >= arity) {
161
161
  return body.apply(this, arguments);
162
162
  }
163
- const args3 = arguments;
163
+ const args4 = arguments;
164
164
  return function(self) {
165
- return body(self, ...args3);
165
+ return body(self, ...args4);
166
166
  };
167
167
  };
168
168
  }
@@ -1104,7 +1104,7 @@ var init_core = __esm({
1104
1104
  }
1105
1105
  };
1106
1106
  causeDie = (defect) => new CauseImpl([new Die(defect)]);
1107
- causeAnnotate = /* @__PURE__ */ dual((args3) => isCause(args3[0]), (self, annotations, options) => {
1107
+ causeAnnotate = /* @__PURE__ */ dual((args4) => isCause(args4[0]), (self, annotations, options) => {
1108
1108
  if (annotations.mapUnsafe.size === 0) return self;
1109
1109
  return new CauseImpl(self.reasons.map((f2) => f2.annotate(annotations, options)));
1110
1110
  });
@@ -1215,14 +1215,14 @@ var init_core = __esm({
1215
1215
  Error2 = /* @__PURE__ */ (function() {
1216
1216
  const plainArgsSymbol = /* @__PURE__ */ Symbol.for("effect/Data/Error/plainArgs");
1217
1217
  return class Base extends YieldableError {
1218
- constructor(args3) {
1219
- super(args3?.message, args3?.cause ? {
1220
- cause: args3.cause
1218
+ constructor(args4) {
1219
+ super(args4?.message, args4?.cause ? {
1220
+ cause: args4.cause
1221
1221
  } : void 0);
1222
- if (args3) {
1223
- assignProperties(this, args3);
1222
+ if (args4) {
1223
+ assignProperties(this, args4);
1224
1224
  Object.defineProperty(this, plainArgsSymbol, {
1225
- value: args3,
1225
+ value: args4,
1226
1226
  enumerable: false
1227
1227
  });
1228
1228
  }
@@ -2282,7 +2282,7 @@ var init_stackTraceLimit = __esm({
2282
2282
  });
2283
2283
 
2284
2284
  // ../../node_modules/.pnpm/effect@4.0.0-rc.108/node_modules/effect/dist/internal/effect.js
2285
- var Interrupt, causeInterrupt, findFail, findError, hasInterrupts, hasInterruptsOnly, causeCombine, causeMap, causePartition, causeSquash, causePrettyErrors, causePrettyError, causePrettyMessage, locationRegExp, cleanErrorStack, addStackAnnotations, interruptCauseStack, currentStackTrace, causePretty, renderPrettyError, renderErrorCause, FiberTypeId, fiberVariance, fiberIdStore, getCurrentFiber, FiberImpl, deferredInterruptCont, fiberMiddleware, fiberStackAnnotations, fiberAwait, fiberAwaitAll, fiberInterrupt, fiberInterruptAs, fiberInterruptAll, succeed3, failCause, fail3, sync, suspend, fromResult, yieldNowWith, yieldNow, succeedNone, failCauseSync, die, failSync, void_, try_, promise, tryPromise, withFiberId, callbackOptions, asyncFinalizer, callback, never, gen, fnUntraced, defineFunctionLength, fnUntracedEager, fromIteratorEagerUnsafe, fromIteratorUnsafe, as, asSome, andThen, tap, asVoid, raceAllFirst, raceFirst, flatMap2, OnSuccessProto, effectIsExit, flatMapEager, map3, mapEager, mapErrorEager, exitInterrupt, exitIsSuccess, exitIsFailure, exitFilterCause, exitVoid, exitMap, exitMapError, exitZipRight, exitAsVoidAll, serviceOption, updateContext, context, getContext, contextWith, provideContext, provideService, provideServiceImpl, forever, catchCause, OnFailureProto, catchCauseFilter, catch_, tapCause, tapCauseFilter, tapError, catchIf, catchTag, mapError2, orDie, ignore, result, matchCauseEffect, OnSuccessAndFailureProto, matchEffect, match4, matchEager, exit, exitPrimitive, timeoutOrElse, timeout, ScopeTypeId, ScopeCloseableTypeId, scopeTag, scopeClose, scopeCloseUnsafe, scopeCloseFinalizers, scopeForkUnsafe, scopeAddFinalizerExit, scopeAddFinalizer, scopeAddFinalizerUnsafe, scopeRemoveFinalizerUnsafe, scopeMakeUnsafe, constScopeEmpty, scope, provideScope, scoped, scopedWith, acquireRelease, addFinalizer, onExitPrimitive, onExit, ensuring, onExitFilter, onError, interrupt, uninterruptible, setInterruptible, setInterruptibleTrue, setInterruptibleFalse, setFiberInterruptible, interruptible, uninterruptibleMask, all, whileLoop, forEach, forEachSequential, iterateEagerImpl, iterateEager, forEachConcurrent, forkUnsafe, forkDetach, forkIn, forkScoped, runForkWith, fiberRunIn, runFork, runPromiseExitWith, runPromiseWith, runSyncExitWith, runSyncExit, succeedTrue, succeedFalse, Latch, makeLatchUnsafe, ClockRef, MAX_TIMER_MILLIS, ClockImpl, nanosPerMilli, monotonicNowNanos, wallTimeNanos, clockWith, sleep, TimeoutErrorTypeId, TimeoutError, IllegalArgumentErrorTypeId, IllegalArgumentError, ExceededCapacityErrorTypeId, ExceededCapacityError, AsyncFiberErrorTypeId, AsyncFiberError, UnknownErrorTypeId, UnknownError, ConsoleRef, logLevelToOrder, LogLevelOrder, isLogLevelGreaterThan, CurrentLoggers, LogToStderr, LoggerTypeId, LoggerProto, loggerMake, formatLabel, formatLogSpan, logWithLevel, colors, logLevelColors, defaultDateFormat, defaultLogger, tracerLogger;
2285
+ var Interrupt, causeInterrupt, findFail, findError, hasInterrupts, hasInterruptsOnly, causeCombine, causeMap, causePartition, causeSquash, causePrettyErrors, causePrettyError, causePrettyMessage, locationRegExp, cleanErrorStack, addStackAnnotations, interruptCauseStack, currentStackTrace, causePretty, renderPrettyError, renderErrorCause, FiberTypeId, fiberVariance, fiberIdStore, getCurrentFiber, FiberImpl, deferredInterruptCont, fiberMiddleware, fiberStackAnnotations, fiberAwait, fiberAwaitAll, fiberInterrupt, fiberInterruptAs, fiberInterruptAll, succeed3, failCause, fail3, sync, suspend, fromResult, yieldNowWith, yieldNow, succeedNone, failCauseSync, die, failSync, void_, try_, tryPromise, withFiberId, callbackOptions, asyncFinalizer, callback, never, gen, fnUntraced, defineFunctionLength, fnUntracedEager, fromIteratorEagerUnsafe, fromIteratorUnsafe, as, asSome, andThen, tap, asVoid, raceAllFirst, raceFirst, flatMap2, OnSuccessProto, effectIsExit, flatMapEager, map3, mapEager, mapErrorEager, exitInterrupt, exitIsSuccess, exitIsFailure, exitFilterCause, exitVoid, exitMap, exitMapError, exitZipRight, exitAsVoidAll, serviceOption, updateContext, context, getContext, contextWith, provideContext, provideService, provideServiceImpl, forever, catchCause, OnFailureProto, catchCauseFilter, catch_, tapCause, tapCauseFilter, tapError, catchIf, catchTag, mapError2, orDie, ignore, result, matchCauseEffect, OnSuccessAndFailureProto, matchEffect, match4, matchEager, exit, exitPrimitive, timeoutOrElse, timeout, ScopeTypeId, ScopeCloseableTypeId, scopeTag, scopeClose, scopeCloseUnsafe, scopeCloseFinalizers, scopeForkUnsafe, scopeAddFinalizerExit, scopeAddFinalizer, scopeAddFinalizerUnsafe, scopeRemoveFinalizerUnsafe, scopeMakeUnsafe, constScopeEmpty, scope, provideScope, scoped, scopedWith, acquireRelease, addFinalizer, onExitPrimitive, onExit, ensuring, onExitFilter, onError, interrupt, uninterruptible, setInterruptible, setInterruptibleTrue, setInterruptibleFalse, setFiberInterruptible, interruptible, uninterruptibleMask, all, whileLoop, forEach, forEachSequential, iterateEagerImpl, iterateEager, forEachConcurrent, forkUnsafe, forkDetach, forkIn, forkScoped, runForkWith, fiberRunIn, runFork, runPromiseExitWith, runPromiseWith, runSyncExitWith, runSyncExit, succeedTrue, succeedFalse, Latch, makeLatchUnsafe, ClockRef, MAX_TIMER_MILLIS, ClockImpl, nanosPerMilli, monotonicNowNanos, wallTimeNanos, clockWith, sleep, currentTimeMillis, TimeoutErrorTypeId, TimeoutError, IllegalArgumentErrorTypeId, IllegalArgumentError, ExceededCapacityErrorTypeId, ExceededCapacityError, AsyncFiberErrorTypeId, AsyncFiberError, UnknownErrorTypeId, UnknownError, ConsoleRef, logLevelToOrder, LogLevelOrder, isLogLevelGreaterThan, CurrentLoggers, LogToStderr, LoggerTypeId, LoggerProto, loggerMake, formatLabel, formatLogSpan, logWithLevel, colors, logLevelColors, defaultDateFormat, defaultLogger, tracerLogger;
2286
2286
  var init_effect = __esm({
2287
2287
  "../../node_modules/.pnpm/effect@4.0.0-rc.108/node_modules/effect/dist/internal/effect.js"() {
2288
2288
  init_Array();
@@ -2790,7 +2790,7 @@ ${prefix3}}`;
2790
2790
  return sync(() => cancel?.());
2791
2791
  });
2792
2792
  fiberInterrupt = (self) => withFiber((fiber2) => fiberInterruptAs(self, fiber2.id));
2793
- fiberInterruptAs = /* @__PURE__ */ dual((args3) => hasProperty(args3[0], FiberTypeId), (self, fiberId2, annotations) => withFiber((parent) => {
2793
+ fiberInterruptAs = /* @__PURE__ */ dual((args4) => hasProperty(args4[0], FiberTypeId), (self, fiberId2, annotations) => withFiber((parent) => {
2794
2794
  let ann = fiberStackAnnotations(parent);
2795
2795
  ann = ann && annotations ? merge(ann, annotations) : ann ?? annotations;
2796
2796
  self.interruptUnsafe(fiberId2, ann);
@@ -2856,9 +2856,6 @@ ${prefix3}}`;
2856
2856
  }
2857
2857
  });
2858
2858
  };
2859
- promise = (evaluate2) => callbackOptions(function(resume, signal) {
2860
- internalCall(() => evaluate2(signal)).then((a) => resume(succeed3(a)), (e) => resume(die(e)));
2861
- }, evaluate2.length !== 0);
2862
2859
  tryPromise = (options) => {
2863
2860
  const f2 = typeof options === "function" ? options : options.try;
2864
2861
  const catcher = typeof options === "function" ? (cause) => new UnknownError(cause, "An error occurred in Effect.tryPromise") : options.catch;
@@ -2925,7 +2922,7 @@ ${prefix3}}`;
2925
2922
  });
2926
2923
  callback = (register) => callbackOptions(register, register.length >= 2);
2927
2924
  never = /* @__PURE__ */ callback(constVoid);
2928
- gen = (...args3) => suspend(() => fromIteratorUnsafe(args3.length === 1 ? args3[0]() : args3[1].call(args3[0].self)));
2925
+ gen = (...args4) => suspend(() => fromIteratorUnsafe(args4.length === 1 ? args4[0]() : args4[1].call(args4[0].self)));
2929
2926
  fnUntraced = (body, ...pipeables) => {
2930
2927
  const fn2 = pipeables.length === 0 ? function() {
2931
2928
  return suspend(() => fromIteratorUnsafe(body.apply(this, arguments)));
@@ -3039,7 +3036,7 @@ ${prefix3}}`;
3039
3036
  }
3040
3037
  return fiberInterruptAll(fibers);
3041
3038
  }));
3042
- raceFirst = /* @__PURE__ */ dual((args3) => isEffect(args3[1]), (self, that, options) => raceAllFirst([self, that], options));
3039
+ raceFirst = /* @__PURE__ */ dual((args4) => isEffect(args4[1]), (self, that, options) => raceAllFirst([self, that], options));
3043
3040
  flatMap2 = /* @__PURE__ */ dual(2, (self, f2) => {
3044
3041
  const onSuccess = Object.create(OnSuccessProto);
3045
3042
  onSuccess[args] = self;
@@ -3114,7 +3111,7 @@ ${prefix3}}`;
3114
3111
  if (prev === implementation) return s3;
3115
3112
  return add(s3, service3, implementation);
3116
3113
  });
3117
- forever = /* @__PURE__ */ dual((args3) => isEffect(args3[0]), (self, options) => whileLoop({
3114
+ forever = /* @__PURE__ */ dual((args4) => isEffect(args4[0]), (self, options) => whileLoop({
3118
3115
  while: constTrue,
3119
3116
  body: constant(options?.disableYield ? self : flatMap2(self, (_2) => yieldNow)),
3120
3117
  step: constVoid
@@ -3146,7 +3143,7 @@ ${prefix3}}`;
3146
3143
  return andThen(internalCall(() => f2(result2.success, cause)), failCause(cause));
3147
3144
  }));
3148
3145
  tapError = /* @__PURE__ */ dual(2, (self, f2) => tapCauseFilter(self, findError, (e) => f2(e)));
3149
- catchIf = /* @__PURE__ */ dual((args3) => isEffect(args3[0]), (self, predicate, f2, orElse) => catchCause(self, (cause) => {
3146
+ catchIf = /* @__PURE__ */ dual((args4) => isEffect(args4[0]), (self, predicate, f2, orElse) => catchCause(self, (cause) => {
3150
3147
  const error = findError(cause);
3151
3148
  if (isFailure2(error)) return failCause(error.failure);
3152
3149
  if (!predicate(error.success)) {
@@ -3154,13 +3151,13 @@ ${prefix3}}`;
3154
3151
  }
3155
3152
  return internalCall(() => f2(error.success));
3156
3153
  }));
3157
- catchTag = /* @__PURE__ */ dual((args3) => isEffect(args3[0]), (self, k2, f2, orElse) => {
3154
+ catchTag = /* @__PURE__ */ dual((args4) => isEffect(args4[0]), (self, k2, f2, orElse) => {
3158
3155
  const pred = Array.isArray(k2) ? (e) => hasProperty(e, "_tag") && k2.includes(e._tag) : isTagged(k2);
3159
3156
  return catchIf(self, pred, f2, orElse);
3160
3157
  });
3161
3158
  mapError2 = /* @__PURE__ */ dual(2, (self, f2) => catch_(self, (error) => failSync(() => f2(error))));
3162
3159
  orDie = (self) => catch_(self, die);
3163
- ignore = /* @__PURE__ */ dual((args3) => isEffect(args3[0]), (self, options) => {
3160
+ ignore = /* @__PURE__ */ dual((args4) => isEffect(args4[0]), (self, options) => {
3164
3161
  if (!options?.log) {
3165
3162
  return matchEffect(self, {
3166
3163
  onFailure: (_2) => void_,
@@ -3436,7 +3433,7 @@ ${prefix3}}`;
3436
3433
  return exitVoid;
3437
3434
  }
3438
3435
  });
3439
- forEach = /* @__PURE__ */ dual((args3) => typeof args3[1] === "function", (iterable, f2, options) => suspend(() => {
3436
+ forEach = /* @__PURE__ */ dual((args4) => typeof args4[1] === "function", (iterable, f2, options) => suspend(() => {
3440
3437
  const concurrencyOption = options?.concurrency ?? 1;
3441
3438
  const concurrency = concurrencyOption === "unbounded" ? Number.POSITIVE_INFINITY : Math.max(1, concurrencyOption);
3442
3439
  if (concurrency === 1) {
@@ -3644,8 +3641,8 @@ ${prefix3}}`;
3644
3641
  }
3645
3642
  return child;
3646
3643
  };
3647
- forkDetach = /* @__PURE__ */ dual((args3) => isEffect(args3[0]), (self, options) => withFiber((fiber2) => succeed3(forkUnsafe(fiber2, self, options?.startImmediately, true, options?.uninterruptible))));
3648
- forkIn = /* @__PURE__ */ dual((args3) => isEffect(args3[0]), (self, scope3, options) => withFiber((parent) => {
3644
+ forkDetach = /* @__PURE__ */ dual((args4) => isEffect(args4[0]), (self, options) => withFiber((fiber2) => succeed3(forkUnsafe(fiber2, self, options?.startImmediately, true, options?.uninterruptible))));
3645
+ forkIn = /* @__PURE__ */ dual((args4) => isEffect(args4[0]), (self, scope3, options) => withFiber((parent) => {
3649
3646
  const fiber2 = forkUnsafe(parent, self, options?.startImmediately, true, options?.uninterruptible);
3650
3647
  if (!fiber2._exit) {
3651
3648
  if (scope3.state._tag !== "Closed") {
@@ -3659,7 +3656,7 @@ ${prefix3}}`;
3659
3656
  }
3660
3657
  return succeed3(fiber2);
3661
3658
  }));
3662
- forkScoped = /* @__PURE__ */ dual((args3) => isEffect(args3[0]), (self, options) => flatMap2(scope, (scope3) => forkIn(self, scope3, options)));
3659
+ forkScoped = /* @__PURE__ */ dual((args4) => isEffect(args4[0]), (self, options) => flatMap2(scope, (scope3) => forkIn(self, scope3, options)));
3663
3660
  runForkWith = (context3) => (effect2, options) => {
3664
3661
  const fiber2 = new FiberImpl(options?.scheduler ? add(context3, Scheduler, options.scheduler) : context3, options?.uninterruptible !== true);
3665
3662
  fiber2.evaluate(effect2);
@@ -3873,6 +3870,7 @@ ${prefix3}}`;
3873
3870
  })();
3874
3871
  clockWith = (f2) => withFiber((fiber2) => f2(fiber2.getRef(ClockRef)));
3875
3872
  sleep = (duration) => clockWith((clock) => clock.sleep(fromInputUnsafe(duration)));
3873
+ currentTimeMillis = /* @__PURE__ */ clockWith((clock) => clock.currentTimeMillis);
3876
3874
  TimeoutErrorTypeId = "~effect/Cause/TimeoutError";
3877
3875
  TimeoutError = class extends (/* @__PURE__ */ TaggedError("TimeoutError")) {
3878
3876
  [TimeoutErrorTypeId] = TimeoutErrorTypeId;
@@ -4318,6 +4316,15 @@ var init_Layer = __esm({
4318
4316
  }
4319
4317
  });
4320
4318
 
4319
+ // ../../node_modules/.pnpm/effect@4.0.0-rc.108/node_modules/effect/dist/Clock.js
4320
+ var currentTimeMillis2;
4321
+ var init_Clock = __esm({
4322
+ "../../node_modules/.pnpm/effect@4.0.0-rc.108/node_modules/effect/dist/Clock.js"() {
4323
+ init_effect();
4324
+ currentTimeMillis2 = currentTimeMillis;
4325
+ }
4326
+ });
4327
+
4321
4328
  // ../../node_modules/.pnpm/effect@4.0.0-rc.108/node_modules/effect/dist/Pull.js
4322
4329
  var catchDone, isDoneCause, isDoneFailure, filterDone, filterDoneLeftover, doneExitFromCause, matchEffect2;
4323
4330
  var init_Pull = __esm({
@@ -4475,7 +4482,7 @@ var init_layer = __esm({
4475
4482
  init_core();
4476
4483
  init_effect();
4477
4484
  provideLayer = (self, layer13, options) => scopedWith((scope3) => flatMap2(options?.local ? buildWithMemoMap(layer13, makeMemoMapUnsafe(), scope3) : buildWithScope(layer13, scope3), (context3) => provideContext(self, context3)));
4478
- provide2 = /* @__PURE__ */ dual((args3) => isEffect(args3[0]), (self, source, options) => isContext(source) ? provideContext(self, source) : provideLayer(self, Array.isArray(source) ? mergeAll2(...source) : source, options));
4485
+ provide2 = /* @__PURE__ */ dual((args4) => isEffect(args4[0]), (self, source, options) => isContext(source) ? provideContext(self, source) : provideLayer(self, Array.isArray(source) ? mergeAll2(...source) : source, options));
4479
4486
  }
4480
4487
  });
4481
4488
 
@@ -4548,7 +4555,7 @@ var init_schedule = __esm({
4548
4555
  });
4549
4556
 
4550
4557
  // ../../node_modules/.pnpm/effect@4.0.0-rc.108/node_modules/effect/dist/Effect.js
4551
- var isEffect2, all2, forEach2, whileLoop2, promise2, tryPromise2, succeed6, succeedNone2, suspend2, sync2, void_3, callback2, gen2, fail6, failCause3, failCauseSync2, die2, try_2, withFiber2, fromResult2, flatMap3, andThen2, tap2, exit2, map5, as2, asVoid2, catch_2, catchTag2, catchCause2, mapError3, orDie2, tapError2, tapCause2, retry2, ignore2, timeout2, timeoutOrElse2, sleep2, raceFirst2, matchEffect3, context2, provide3, provideContext2, serviceOption2, scope2, scoped2, scopedWith2, acquireRelease2, addFinalizer3, ensuring2, onError2, onExit2, interrupt2, uninterruptible2, uninterruptibleMask2, forever3, repeat2, forkIn2, forkScoped2, forkDetach2, runFork2, runForkWith2, runPromiseWith2, runSyncExit2, fnUntraced2, clockWith2, logError, effectify, mapEager2, mapErrorEager2, flatMapEager2, fnUntracedEager2;
4558
+ var isEffect2, all2, forEach2, whileLoop2, tryPromise2, succeed6, succeedNone2, suspend2, sync2, void_3, callback2, gen2, fail6, failCause3, failCauseSync2, die2, try_2, withFiber2, fromResult2, flatMap3, andThen2, tap2, exit2, map5, as2, asVoid2, catch_2, catchTag2, catchCause2, mapError3, orDie2, tapError2, tapCause2, retry2, ignore2, timeout2, timeoutOrElse2, sleep2, raceFirst2, matchEffect3, context2, provide3, provideContext2, serviceOption2, scope2, scoped2, scopedWith2, acquireRelease2, addFinalizer3, ensuring2, onError2, onExit2, interrupt2, uninterruptible2, uninterruptibleMask2, forever3, repeat2, forkIn2, forkScoped2, forkDetach2, runFork2, runForkWith2, runPromiseWith2, runSyncExit2, fnUntraced2, clockWith2, logError, effectify, mapEager2, mapErrorEager2, flatMapEager2, fnUntracedEager2;
4552
4559
  var init_Effect = __esm({
4553
4560
  "../../node_modules/.pnpm/effect@4.0.0-rc.108/node_modules/effect/dist/Effect.js"() {
4554
4561
  init_core();
@@ -4559,7 +4566,6 @@ var init_Effect = __esm({
4559
4566
  all2 = all;
4560
4567
  forEach2 = forEach;
4561
4568
  whileLoop2 = whileLoop;
4562
- promise2 = promise;
4563
4569
  tryPromise2 = tryPromise;
4564
4570
  succeed6 = succeed3;
4565
4571
  succeedNone2 = succeedNone;
@@ -4623,17 +4629,17 @@ var init_Effect = __esm({
4623
4629
  fnUntraced2 = fnUntraced;
4624
4630
  clockWith2 = clockWith;
4625
4631
  logError = /* @__PURE__ */ logWithLevel("Error");
4626
- effectify = (fn2, onError4, onSyncError) => (...args3) => callback2((resume) => {
4632
+ effectify = (fn2, onError4, onSyncError) => (...args4) => callback2((resume) => {
4627
4633
  try {
4628
- fn2(...args3, (err, result2) => {
4634
+ fn2(...args4, (err, result2) => {
4629
4635
  if (err) {
4630
- resume(fail6(onError4 ? onError4(err, args3) : err));
4636
+ resume(fail6(onError4 ? onError4(err, args4) : err));
4631
4637
  } else {
4632
4638
  resume(succeed6(result2));
4633
4639
  }
4634
4640
  });
4635
4641
  } catch (err) {
4636
- resume(onSyncError ? fail6(onSyncError(err, args3)) : die2(err));
4642
+ resume(onSyncError ? fail6(onSyncError(err, args4)) : die2(err));
4637
4643
  }
4638
4644
  });
4639
4645
  mapEager2 = mapEager;
@@ -4777,7 +4783,7 @@ var init_parser = __esm({
4777
4783
  missingExit = /* @__PURE__ */ succeed7(missing);
4778
4784
  sameExit = /* @__PURE__ */ succeed7(missing);
4779
4785
  toOption = (value) => value === missing ? none2() : some2(value);
4780
- fromOptionExit = (option3) => option3._tag === "None" ? missingExit : succeed7(option3.value);
4786
+ fromOptionExit = (option4) => option4._tag === "None" ? missingExit : succeed7(option4.value);
4781
4787
  }
4782
4788
  });
4783
4789
 
@@ -7519,8 +7525,8 @@ function getClassSchemaFactory(from, identifier3, annotations) {
7519
7525
  }),
7520
7526
  toCodec: ([from2]) => new Link(from2.ast, transformation),
7521
7527
  toArbitrary: ([from2]) => () => ({
7522
- arbitrary: from2.arbitrary.map((args3) => new self(args3)),
7523
- terminal: from2.terminal?.map((args3) => new self(args3))
7528
+ arbitrary: from2.arbitrary.map((args4) => new self(args4)),
7529
+ terminal: from2.terminal?.map((args4) => new self(args4))
7524
7530
  }),
7525
7531
  toFormatter: ([from2]) => (t) => `${self.identifier}(${from2(t)})`,
7526
7532
  [SENTINELS_ANNOTATION_KEY]: collectSentinels(from.ast),
@@ -7965,7 +7971,7 @@ var init_connect = __esm({
7965
7971
  });
7966
7972
  ConnectPresence = Struct({
7967
7973
  connectedAt: NullOr(IsoDateTime),
7968
- environmentId: String4.check(isMinLength(1), isMaxLength(128)),
7974
+ environmentId: ExecutionEnvironmentId,
7969
7975
  lastSeenAt: NullOr(IsoDateTime),
7970
7976
  nodeVersion: NullOr(String4.check(isMinLength(1), isMaxLength(64))),
7971
7977
  protocolVersion: NullOr(Int.check(isGreaterThanOrEqualTo2(1))),
@@ -7974,7 +7980,10 @@ var init_connect = __esm({
7974
7980
  ConnectCompatibility = Struct({
7975
7981
  maximumProtocolVersion: Int.check(isGreaterThanOrEqualTo2(1)),
7976
7982
  minimumNodeVersion: String4.check(isMinLength(5), isMaxLength(64)),
7977
- minimumProtocolVersion: Int.check(isGreaterThanOrEqualTo2(1))
7983
+ minimumProtocolVersion: Int.check(isGreaterThanOrEqualTo2(1)),
7984
+ recommendedNodeVersion: optional2(
7985
+ String4.check(isMinLength(5), isMaxLength(64))
7986
+ )
7978
7987
  }).check(
7979
7988
  makeFilter2(
7980
7989
  (value) => value.maximumProtocolVersion >= value.minimumProtocolVersion || "Maximum protocol version must not precede the minimum"
@@ -8627,7 +8636,7 @@ var init_Channel = __esm({
8627
8636
  }
8628
8637
  return isReadonlyArrayNonEmpty(passes) ? succeed6(passes) : flatMap3(pull, loop);
8629
8638
  }))));
8630
- merge2 = /* @__PURE__ */ dual((args3) => isChannel(args3[0]) && isChannel(args3[1]), (left, right, options) => fromTransformBracket(fnUntraced2(function* (upstream, _scope, forkedScope) {
8639
+ merge2 = /* @__PURE__ */ dual((args4) => isChannel(args4[0]) && isChannel(args4[1]), (left, right, options) => fromTransformBracket(fnUntraced2(function* (upstream, _scope, forkedScope) {
8631
8640
  const strategy = options?.haltStrategy ?? "both";
8632
8641
  const queue = yield* bounded(0);
8633
8642
  yield* addFinalizer2(forkedScope, shutdown(queue));
@@ -8990,10 +8999,10 @@ var init_Stream = __esm({
8990
8999
  let i = 0;
8991
9000
  return fromChannel3(map7(self.channel, map2((o) => f2(o, i++))));
8992
9001
  }));
8993
- merge3 = /* @__PURE__ */ dual((args3) => isStream(args3[0]) && isStream(args3[1]), (self, that, options) => fromChannel3(merge2(toChannel2(self), toChannel2(that), options)));
9002
+ merge3 = /* @__PURE__ */ dual((args4) => isStream(args4[0]) && isStream(args4[1]), (self, that, options) => fromChannel3(merge2(toChannel2(self), toChannel2(that), options)));
8994
9003
  filter6 = /* @__PURE__ */ dual(2, (self, predicate) => fromChannel3(filterArray(toChannel2(self), predicate)));
8995
9004
  take3 = /* @__PURE__ */ dual(2, (self, n) => n < 1 ? empty5 : takeUntil(self, (_2, i) => i === n - 1));
8996
- takeUntil = /* @__PURE__ */ dual((args3) => isStream(args3[0]), (self, predicate, options) => transformPull2(self, (pull, _scope) => sync2(() => {
9005
+ takeUntil = /* @__PURE__ */ dual((args4) => isStream(args4[0]), (self, predicate, options) => transformPull2(self, (pull, _scope) => sync2(() => {
8997
9006
  let i = 0;
8998
9007
  let done4 = false;
8999
9008
  const pump = flatMap3(suspend2(() => done4 ? done2() : pull), (chunk) => {
@@ -9027,7 +9036,7 @@ var init_Stream = __esm({
9027
9036
  });
9028
9037
  return suspend2(() => done4 ? done4 : pull);
9029
9038
  })));
9030
- decodeText = /* @__PURE__ */ dual((args3) => isStream(args3[0]), (self, options) => suspend4(() => {
9039
+ decodeText = /* @__PURE__ */ dual((args4) => isStream(args4[0]), (self, options) => suspend4(() => {
9031
9040
  const decoder2 = new TextDecoder(options?.encoding);
9032
9041
  return map8(self, (chunk) => decoder2.decode(chunk, {
9033
9042
  stream: true
@@ -9703,10 +9712,10 @@ var init_ChildProcess = __esm({
9703
9712
  isCommand = (u2) => hasProperty(u2, TypeId23);
9704
9713
  isStandardCommand = (command2) => command2._tag === "StandardCommand";
9705
9714
  isPipedCommand = (command2) => command2._tag === "PipedCommand";
9706
- makeStandardCommand = (command2, args3, options) => Object.assign(Object.create(Proto2), {
9715
+ makeStandardCommand = (command2, args4, options) => Object.assign(Object.create(Proto2), {
9707
9716
  _tag: "StandardCommand",
9708
9717
  command: command2,
9709
- args: args3,
9718
+ args: args4,
9710
9719
  options
9711
9720
  });
9712
9721
  makePipedCommand = (left, right, options = {}) => Object.assign(Object.create(Proto2), {
@@ -9715,46 +9724,46 @@ var init_ChildProcess = __esm({
9715
9724
  right,
9716
9725
  options
9717
9726
  });
9718
- make16 = function make17(...args3) {
9719
- if (isTemplateString(args3[0])) {
9720
- const [templates, ...expressions] = args3;
9727
+ make16 = function make17(...args4) {
9728
+ if (isTemplateString(args4[0])) {
9729
+ const [templates, ...expressions] = args4;
9721
9730
  const tokens = parseTemplates(templates, expressions);
9722
9731
  return makeStandardCommand(tokens[0] ?? "", tokens.slice(1), {});
9723
9732
  }
9724
- if (typeof args3[0] === "object" && !Array.isArray(args3[0]) && !isTemplateString(args3[0])) {
9725
- const options2 = args3[0];
9733
+ if (typeof args4[0] === "object" && !Array.isArray(args4[0]) && !isTemplateString(args4[0])) {
9734
+ const options2 = args4[0];
9726
9735
  return function(templates, ...expressions) {
9727
9736
  const tokens = parseTemplates(templates, expressions);
9728
9737
  return makeStandardCommand(tokens[0] ?? "", tokens.slice(1), options2);
9729
9738
  };
9730
9739
  }
9731
- if (typeof args3[0] === "string" && !Array.isArray(args3[1])) {
9732
- const [command3, options2 = {}] = args3;
9740
+ if (typeof args4[0] === "string" && !Array.isArray(args4[1])) {
9741
+ const [command3, options2 = {}] = args4;
9733
9742
  return makeStandardCommand(command3, [], options2);
9734
9743
  }
9735
- const [command2, cmdArgs = [], options = {}] = args3;
9744
+ const [command2, cmdArgs = [], options = {}] = args4;
9736
9745
  return makeStandardCommand(command2, cmdArgs, options);
9737
9746
  };
9738
- pipeTo2 = /* @__PURE__ */ dual((args3) => isCommand(args3[0]) && isCommand(args3[1]), (self, that, options) => makePipedCommand(self, that, options ?? {}));
9739
- prefix = function prefix2(...args3) {
9740
- if (isCommand(args3[0]) && args3.length > 1) {
9741
- const [self, ...rest] = args3;
9747
+ pipeTo2 = /* @__PURE__ */ dual((args4) => isCommand(args4[0]) && isCommand(args4[1]), (self, that, options) => makePipedCommand(self, that, options ?? {}));
9748
+ prefix = function prefix2(...args4) {
9749
+ if (isCommand(args4[0]) && args4.length > 1) {
9750
+ const [self, ...rest] = args4;
9742
9751
  const prefixSpec2 = parsePrefixArgs(rest);
9743
9752
  return applyPrefix(self, prefixSpec2);
9744
9753
  }
9745
- const prefixSpec = parsePrefixArgs(args3);
9754
+ const prefixSpec = parsePrefixArgs(args4);
9746
9755
  return (self) => applyPrefix(self, prefixSpec);
9747
9756
  };
9748
- parsePrefixArgs = (args3) => {
9749
- if (isTemplateString(args3[0])) {
9750
- const [templates, ...expressions] = args3;
9757
+ parsePrefixArgs = (args4) => {
9758
+ if (isTemplateString(args4[0])) {
9759
+ const [templates, ...expressions] = args4;
9751
9760
  const tokens = parseTemplates(templates, expressions);
9752
9761
  return {
9753
9762
  command: tokens[0] ?? "",
9754
9763
  args: tokens.slice(1)
9755
9764
  };
9756
9765
  }
9757
- const [command2, cmdArgs = []] = args3;
9766
+ const [command2, cmdArgs = []] = args4;
9758
9767
  return {
9759
9768
  command: command2,
9760
9769
  args: cmdArgs
@@ -10151,24 +10160,24 @@ var init_NodeChildProcessSpawner = __esm({
10151
10160
  };
10152
10161
  };
10153
10162
  const resolveOutputOption = (options, streamName) => {
10154
- const option3 = options[streamName];
10155
- if (isUndefined(option3)) {
10163
+ const option4 = options[streamName];
10164
+ if (isUndefined(option4)) {
10156
10165
  return {
10157
10166
  stream: "pipe"
10158
10167
  };
10159
10168
  }
10160
- if (typeof option3 === "string") {
10169
+ if (typeof option4 === "string") {
10161
10170
  return {
10162
- stream: option3
10171
+ stream: option4
10163
10172
  };
10164
10173
  }
10165
- if (isSink(option3)) {
10174
+ if (isSink(option4)) {
10166
10175
  return {
10167
- stream: option3
10176
+ stream: option4
10168
10177
  };
10169
10178
  }
10170
10179
  return {
10171
- stream: option3.stream
10180
+ stream: option4.stream
10172
10181
  };
10173
10182
  };
10174
10183
  const resolveAdditionalFds = (options) => {
@@ -10311,8 +10320,8 @@ var init_NodeChildProcessSpawner = __esm({
10311
10320
  handle.on("error", (error) => {
10312
10321
  resume(fail6(toPlatformError("spawn", error, command2)));
10313
10322
  });
10314
- handle.on("exit", (...args3) => {
10315
- doneUnsafe(deferred, succeed4(args3));
10323
+ handle.on("exit", (...args4) => {
10324
+ doneUnsafe(deferred, succeed4(args4));
10316
10325
  });
10317
10326
  handle.on("spawn", () => {
10318
10327
  resume(succeed6([handle, deferred]));
@@ -11460,7 +11469,7 @@ var init_Runtime = __esm({
11460
11469
  if (hasInterruptsOnly2(exit3.cause)) return onExit4(130);
11461
11470
  return onExit4(getErrorExitCode(squash(exit3.cause)));
11462
11471
  };
11463
- makeRunMain = (f2) => dual((args3) => isEffect2(args3[0]), (effect2, options) => {
11472
+ makeRunMain = (f2) => dual((args4) => isEffect2(args4[0]), (effect2, options) => {
11464
11473
  const fiber2 = options?.disableErrorReporting === true ? runFork2(effect2) : runFork2(tapCause2(effect2, (cause) => {
11465
11474
  if (hasInterruptsOnly2(cause)) return void_3;
11466
11475
  const isReported = getErrorReported(squash(cause));
@@ -11549,7 +11558,7 @@ var init_process = __esm({
11549
11558
  });
11550
11559
 
11551
11560
  // ../../packages/contracts/src/connect-tunnel.ts
11552
- var Base64Url, base64Url, Hostname, KeyVersion, ManagedTunnelConfiguration, releaseBase, cloudflaredReleaseManifest, proofFields, TunnelEnvironmentProof, LocalOrigin, TunnelConfigurationRequest, TunnelReleaseRequest, ValidateClientTicketRequest, PublishNodePresenceRequest, ValidateClientTicketResponse, TunnelNodeWelcome, TunnelHealthResponse, tunnelHealthSigningPayload, tunnelClientProofPayload, tunnelWelcomeSigningPayload, decodeTunnelConfigurationRequest, decodeValidateClientTicketRequest, decodeTunnelReleaseRequest, decodePublishNodePresenceRequest, decodeManagedTunnelConfiguration, decodeValidateClientTicketResponse, decodeTunnelNodeWelcome, decodeTunnelHealthResponse;
11561
+ var Base64Url, base64Url, Hostname, KeyVersion, ManagedTunnelConfiguration, releaseBase, cloudflaredReleaseManifest, proofFields, CreateNodeProofChallengeRequest, TunnelEnvironmentProof, LocalOrigin, TunnelConfigurationRequest, TunnelReleaseRequest, ValidateClientTicketRequest, PublishNodePresenceRequest, ValidateClientTicketResponse, TunnelNodeWelcome, TunnelHealthResponse, tunnelHealthSigningPayload, tunnelClientProofPayload, tunnelWelcomeSigningPayload, decodeTunnelConfigurationRequest, decodeCreateNodeProofChallengeRequest, decodeValidateClientTicketRequest, decodeTunnelReleaseRequest, decodePublishNodePresenceRequest, decodeManagedTunnelConfiguration, decodeValidateClientTicketResponse, decodeTunnelNodeWelcome, decodeTunnelHealthResponse;
11553
11562
  var init_connect_tunnel = __esm({
11554
11563
  "../../packages/contracts/src/connect-tunnel.ts"() {
11555
11564
  "use strict";
@@ -11625,6 +11634,9 @@ var init_connect_tunnel = __esm({
11625
11634
  proofChallengeId: EnvironmentChallengeId,
11626
11635
  signature: base64Url(86)
11627
11636
  };
11637
+ CreateNodeProofChallengeRequest = Struct({
11638
+ environmentId: ExecutionEnvironmentId
11639
+ });
11628
11640
  TunnelEnvironmentProof = Struct(proofFields);
11629
11641
  LocalOrigin = String4.check(
11630
11642
  makeFilter2((value) => {
@@ -11709,6 +11721,9 @@ var init_connect_tunnel = __esm({
11709
11721
  String(welcome.protocolVersion)
11710
11722
  ].join("\n");
11711
11723
  decodeTunnelConfigurationRequest = decodeUnknownExact(TunnelConfigurationRequest);
11724
+ decodeCreateNodeProofChallengeRequest = decodeUnknownExact(
11725
+ CreateNodeProofChallengeRequest
11726
+ );
11712
11727
  decodeValidateClientTicketRequest = decodeUnknownExact(ValidateClientTicketRequest);
11713
11728
  decodeTunnelReleaseRequest = decodeUnknownExact(TunnelReleaseRequest);
11714
11729
  decodePublishNodePresenceRequest = decodeUnknownExact(PublishNodePresenceRequest);
@@ -14955,7 +14970,7 @@ var init_environments = __esm({
14955
14970
  init_ids();
14956
14971
  init_schema2();
14957
14972
  environmentCredentialScope = "glass-connect";
14958
- environmentPairingApprovalPath = "/#glass-connect-pair";
14973
+ environmentPairingApprovalPath = "/pair";
14959
14974
  maxEnvironmentDisplayNameLength = 120;
14960
14975
  EnvironmentPlatform = Literals(["linux", "macos", "windows"]);
14961
14976
  Base64Url2 = String4.check(isPattern2(/^[A-Za-z0-9_-]+$/u));
@@ -15061,18 +15076,20 @@ var init_environments = __esm({
15061
15076
  });
15062
15077
 
15063
15078
  // src/identity.ts
15064
- import { createPrivateKey, generateKeyPairSync, sign } from "node:crypto";
15079
+ import { createPrivateKey, generateKeyPairSync, randomUUID, sign } from "node:crypto";
15065
15080
  import { chmod as chmod4, mkdir as mkdir3, open as open3, readFile as readFile4, rename as rename4 } from "node:fs/promises";
15066
15081
  import { homedir } from "node:os";
15067
15082
  import { dirname as dirname2, join as join3 } from "node:path";
15068
- var EnvironmentRequestError, IdentityError, StoredNodeIdentitySchema, decodeStoredNodeIdentity, isRecord, defaultIdentityPath, createNodeIdentity, loadNodeIdentity, saveNodeIdentity, signChallenge, signPrivateKey, request, beginPairing, finishPairing, refreshCredential;
15083
+ var EnvironmentRequestError, IdentityError, PairingPendingError, StoredNodeIdentitySchema, decodeStoredNodeIdentity, isRecord, defaultIdentityPath, createNodeIdentity, loadNodeIdentity, saveNodeIdentity, signChallenge, signPrivateKey, request, beginPairing, finishPairing, refreshCredential;
15069
15084
  var init_identity = __esm({
15070
15085
  "src/identity.ts"() {
15071
15086
  "use strict";
15072
15087
  init_environments();
15073
15088
  init_schema2();
15089
+ init_Clock();
15074
15090
  init_Duration();
15075
15091
  init_Effect();
15092
+ init_Schedule();
15076
15093
  init_Schema();
15077
15094
  EnvironmentRequestError = class extends TaggedError3()(
15078
15095
  "EnvironmentRequestError",
@@ -15084,6 +15101,10 @@ var init_identity = __esm({
15084
15101
  operation: Literals(["create", "decode", "load", "request", "save", "sign"])
15085
15102
  }) {
15086
15103
  };
15104
+ PairingPendingError = class extends TaggedError3()("PairingPendingError", {
15105
+ reason: Literal2("approval-pending")
15106
+ }) {
15107
+ };
15087
15108
  StoredNodeIdentitySchema = Struct({
15088
15109
  apiOrigin: String4,
15089
15110
  credential: NullOr(EnvironmentCredential),
@@ -15149,7 +15170,7 @@ var init_identity = __esm({
15149
15170
  saveNodeIdentity = (identity2, path = defaultIdentityPath()) => tryPromise2({
15150
15171
  try: async () => {
15151
15172
  await mkdir3(dirname2(path), { recursive: true, mode: 448 });
15152
- const temporary = `${path}.${process.pid}.${crypto.randomUUID()}.tmp`;
15173
+ const temporary = `${path}.${process.pid}.${randomUUID()}.tmp`;
15153
15174
  const file = await open3(temporary, "wx", 384);
15154
15175
  try {
15155
15176
  await file.writeFile(`${JSON.stringify(identity2, null, 2)}
@@ -15222,7 +15243,8 @@ var init_identity = __esm({
15222
15243
  );
15223
15244
  finishPairing = (identity2, pairing) => {
15224
15245
  const poll2 = gen2(function* () {
15225
- if (Date.parse(pairing.expiresAt) <= Date.now()) {
15246
+ const now = yield* currentTimeMillis2;
15247
+ if (Date.parse(pairing.expiresAt) <= now) {
15226
15248
  return yield* new IdentityError({ cause: "pairing-expired", operation: "request" });
15227
15249
  }
15228
15250
  const status = yield* request(
@@ -15235,7 +15257,7 @@ var init_identity = __esm({
15235
15257
  decodeEnvironmentPairingStatus
15236
15258
  );
15237
15259
  if (status.status === "approved") {
15238
- const environment = yield* request(
15260
+ const environment2 = yield* request(
15239
15261
  identity2,
15240
15262
  "/v1/environment-pairings/complete",
15241
15263
  {
@@ -15245,11 +15267,18 @@ var init_identity = __esm({
15245
15267
  },
15246
15268
  decodeExecutionEnvironment
15247
15269
  );
15248
- return { ...identity2, environment };
15270
+ return { ...identity2, environment: environment2 };
15249
15271
  }
15250
- yield* sleep2(seconds(2));
15251
- return yield* suspend2(() => poll2);
15252
- });
15272
+ return yield* new PairingPendingError({ reason: "approval-pending" });
15273
+ }).pipe(
15274
+ retry2({
15275
+ schedule: spaced(seconds(2)),
15276
+ while: (error) => error instanceof PairingPendingError
15277
+ }),
15278
+ mapError3(
15279
+ (error) => error instanceof PairingPendingError ? new IdentityError({ cause: error, operation: "request" }) : error
15280
+ )
15281
+ );
15253
15282
  return poll2;
15254
15283
  };
15255
15284
  refreshCredential = (identity2) => gen2(function* () {
@@ -15259,7 +15288,8 @@ var init_identity = __esm({
15259
15288
  operation: "request"
15260
15289
  });
15261
15290
  }
15262
- if (identity2.credential !== null && Date.parse(identity2.credential.expiresAt) > Date.now() + 3e4) {
15291
+ const now = yield* currentTimeMillis2;
15292
+ if (identity2.credential !== null && Date.parse(identity2.credential.expiresAt) > now + 3e4) {
15263
15293
  return identity2;
15264
15294
  }
15265
15295
  const challenge = yield* request(
@@ -15283,7 +15313,7 @@ var init_identity = __esm({
15283
15313
  });
15284
15314
 
15285
15315
  // src/service-lifecycle.ts
15286
- import { createHash as createHash3, randomUUID } from "node:crypto";
15316
+ import { createHash as createHash3, randomUUID as randomUUID2 } from "node:crypto";
15287
15317
  import {
15288
15318
  chmod as chmod5,
15289
15319
  copyFile as copyFile3,
@@ -15334,10 +15364,10 @@ var init_service_lifecycle = __esm({
15334
15364
  };
15335
15365
  serviceName = "com.glass.connect";
15336
15366
  windowsTaskName = "Glass Connect";
15337
- run3 = (command2, args3, allowFailure = false) => gen2(function* () {
15367
+ run3 = (command2, args4, allowFailure = false) => gen2(function* () {
15338
15368
  const [stderr, code] = yield* scoped2(
15339
15369
  gen2(function* () {
15340
- const child = yield* ChildProcess_exports.make(command2, args3, {
15370
+ const child = yield* ChildProcess_exports.make(command2, args4, {
15341
15371
  stdin: "ignore",
15342
15372
  stdout: "ignore"
15343
15373
  });
@@ -15367,10 +15397,10 @@ var init_service_lifecycle = __esm({
15367
15397
  }
15368
15398
  return code;
15369
15399
  });
15370
- runOutput = (command2, args3) => gen2(function* () {
15400
+ runOutput = (command2, args4) => gen2(function* () {
15371
15401
  const [stdout, code] = yield* scoped2(
15372
15402
  gen2(function* () {
15373
- const child = yield* ChildProcess_exports.make(command2, args3, {
15403
+ const child = yield* ChildProcess_exports.make(command2, args4, {
15374
15404
  stdin: "ignore",
15375
15405
  stdout: "pipe"
15376
15406
  });
@@ -15514,15 +15544,8 @@ set "GLASS_CONNECT_READY_PATH=${batchValue(paths.ready)}"\r
15514
15544
  serviceStatus = (value = process.platform) => gen2(function* () {
15515
15545
  const platform2 = yield* platformOf(value);
15516
15546
  if (platform2 === "win32") {
15517
- const result2 = yield* runOutput("schtasks.exe", [
15518
- "/Query",
15519
- "/TN",
15520
- windowsTaskName,
15521
- "/FO",
15522
- "LIST",
15523
- "/V"
15524
- ]);
15525
- return result2.code === 0 && /Status:\s+Running/i.test(result2.stdout) ? "running" : "stopped";
15547
+ const result2 = yield* runOutput("schtasks.exe", ["/Query", "/TN", windowsTaskName, "/XML"]);
15548
+ return result2.code === 0 && /<State>\s*Running\s*<\/State>/i.test(result2.stdout) ? "running" : "stopped";
15526
15549
  }
15527
15550
  const code = platform2 === "darwin" ? yield* run3(
15528
15551
  "launchctl",
@@ -15567,10 +15590,29 @@ set "GLASS_CONNECT_READY_PATH=${batchValue(paths.ready)}"\r
15567
15590
  );
15568
15591
  };
15569
15592
  publishCurrentRelease = (paths, releaseRoot, platform2) => tryLifecycle("install", async () => {
15570
- const stagedLink = `${paths.currentRoot}.${process.pid}.${randomUUID()}.new`;
15593
+ const stagedLink = `${paths.currentRoot}.${process.pid}.${randomUUID2()}.new`;
15571
15594
  await symlink3(releaseRoot, stagedLink, platform2 === "win32" ? "junction" : "dir");
15572
- if (platform2 === "win32") await rm3(paths.currentRoot, { force: true });
15573
- await rename5(stagedLink, paths.currentRoot);
15595
+ if (platform2 !== "win32") {
15596
+ await rename5(stagedLink, paths.currentRoot);
15597
+ return;
15598
+ }
15599
+ const previousLink = `${paths.currentRoot}.${process.pid}.${randomUUID2()}.old`;
15600
+ let previousMoved = false;
15601
+ try {
15602
+ await rename5(paths.currentRoot, previousLink);
15603
+ previousMoved = true;
15604
+ } catch (cause) {
15605
+ const code = cause instanceof Error && "code" in cause ? cause.code : void 0;
15606
+ if (code !== "ENOENT") throw cause;
15607
+ }
15608
+ try {
15609
+ await rename5(stagedLink, paths.currentRoot);
15610
+ } catch (cause) {
15611
+ if (previousMoved) await rename5(previousLink, paths.currentRoot).catch(() => void 0);
15612
+ await rm3(stagedLink, { force: true }).catch(() => void 0);
15613
+ throw cause;
15614
+ }
15615
+ if (previousMoved) await rm3(previousLink, { force: true });
15574
15616
  });
15575
15617
  activeRelease = (paths) => tryLifecycle("install", async () => {
15576
15618
  const root = await readlink2(paths.currentRoot).catch(() => null);
@@ -15627,7 +15669,7 @@ set "GLASS_CONNECT_READY_PATH=${batchValue(paths.ready)}"\r
15627
15669
  })
15628
15670
  );
15629
15671
  const paths = servicePaths(input.identityPath, `${input.version}-${digest3}`);
15630
- const stagedConfig = `${path}.${process.pid}.${randomUUID()}.new`;
15672
+ const stagedConfig = `${path}.${process.pid}.${randomUUID2()}.new`;
15631
15673
  yield* tryLifecycle("install", async () => {
15632
15674
  await writeFile4(
15633
15675
  stagedConfig,
@@ -15689,6 +15731,40 @@ set "GLASS_CONNECT_READY_PATH=${batchValue(paths.ready)}"\r
15689
15731
  }
15690
15732
  });
15691
15733
 
15734
+ // src/pairing-url.ts
15735
+ var toOrigin, buildEnvironmentPairingUrl;
15736
+ var init_pairing_url = __esm({
15737
+ "src/pairing-url.ts"() {
15738
+ "use strict";
15739
+ init_environments();
15740
+ toOrigin = (value, label) => {
15741
+ let url;
15742
+ try {
15743
+ url = new URL(value);
15744
+ } catch (cause) {
15745
+ throw new Error(`${label} must be an absolute HTTP(S) origin.`, { cause });
15746
+ }
15747
+ const local = url.protocol === "http:" && ["127.0.0.1", "localhost"].includes(url.hostname);
15748
+ if (url.protocol !== "https:" && !local || url.username !== "" || url.password !== "" || url.pathname !== "" && url.pathname !== "/" || url.search !== "" || url.hash !== "") {
15749
+ throw new Error(`${label} must be an absolute HTTP(S) origin.`);
15750
+ }
15751
+ return url;
15752
+ };
15753
+ buildEnvironmentPairingUrl = ({
15754
+ cloudOrigin,
15755
+ pairingToken,
15756
+ productOrigin: productOrigin2
15757
+ }) => {
15758
+ const cloud = toOrigin(cloudOrigin, "Glass Cloud origin");
15759
+ const product = toOrigin(productOrigin2, "Glass product origin");
15760
+ const url = new URL(environmentPairingApprovalPath, product);
15761
+ url.search = `?host=${cloud.origin}`;
15762
+ url.hash = `token=${encodeURIComponent(pairingToken)}`;
15763
+ return url.toString();
15764
+ };
15765
+ }
15766
+ });
15767
+
15692
15768
  // src/tunnel-control.ts
15693
15769
  var IdentityStoreError, TunnelControlError, TunnelControlTransportError, TunnelControlProtocolError, responseMessage, decodeResponse, createTunnelControl;
15694
15770
  var init_tunnel_control = __esm({
@@ -15826,10 +15902,10 @@ var init_tunnel_control = __esm({
15826
15902
 
15827
15903
  // ../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/esm/cryptoNode.js
15828
15904
  import * as nc from "node:crypto";
15829
- var crypto2;
15905
+ var crypto;
15830
15906
  var init_cryptoNode = __esm({
15831
15907
  "../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/esm/cryptoNode.js"() {
15832
- crypto2 = nc && typeof nc === "object" && "webcrypto" in nc ? nc.webcrypto : nc && typeof nc === "object" && "randomBytes" in nc ? nc : void 0;
15908
+ crypto = nc && typeof nc === "object" && "webcrypto" in nc ? nc.webcrypto : nc && typeof nc === "object" && "randomBytes" in nc ? nc : void 0;
15833
15909
  }
15834
15910
  });
15835
15911
 
@@ -15888,11 +15964,11 @@ function createHasher(hashCons) {
15888
15964
  return hashC;
15889
15965
  }
15890
15966
  function randomBytes3(bytesLength = 32) {
15891
- if (crypto2 && typeof crypto2.getRandomValues === "function") {
15892
- return crypto2.getRandomValues(new Uint8Array(bytesLength));
15967
+ if (crypto && typeof crypto.getRandomValues === "function") {
15968
+ return crypto.getRandomValues(new Uint8Array(bytesLength));
15893
15969
  }
15894
- if (crypto2 && typeof crypto2.randomBytes === "function") {
15895
- return Uint8Array.from(crypto2.randomBytes(bytesLength));
15970
+ if (crypto && typeof crypto.randomBytes === "function") {
15971
+ return Uint8Array.from(crypto.randomBytes(bytesLength));
15896
15972
  }
15897
15973
  throw new Error("crypto.getRandomValues must be defined");
15898
15974
  }
@@ -16417,11 +16493,11 @@ function validateObject(object, validators, optValidators = {}) {
16417
16493
  }
16418
16494
  function memoized(fn2) {
16419
16495
  const map9 = /* @__PURE__ */ new WeakMap();
16420
- return (arg, ...args3) => {
16496
+ return (arg, ...args4) => {
16421
16497
  const val = map9.get(arg);
16422
16498
  if (val !== void 0)
16423
16499
  return val;
16424
- const computed = fn2(arg, ...args3);
16500
+ const computed = fn2(arg, ...args4);
16425
16501
  map9.set(arg, computed);
16426
16502
  return computed;
16427
16503
  };
@@ -21221,6 +21297,7 @@ var init_tunnel_origin = __esm({
21221
21297
  init_webapi();
21222
21298
  init_ids();
21223
21299
  init_wrapper();
21300
+ init_Clock();
21224
21301
  init_Effect();
21225
21302
  init_Option();
21226
21303
  init_Semaphore();
@@ -21239,7 +21316,11 @@ var init_tunnel_origin = __esm({
21239
21316
  const sockets = /* @__PURE__ */ new Set();
21240
21317
  const authenticationPermits = makeUnsafe5(maxPendingAuthentications);
21241
21318
  const authenticate = (ticket) => authenticationPermits.withPermitsIfAvailable(1)(
21242
- all2([options.control.validateTicket(ticket), options.getAuthority()])
21319
+ all2([
21320
+ options.control.validateTicket(ticket),
21321
+ options.getAuthority(),
21322
+ currentTimeMillis2
21323
+ ])
21243
21324
  );
21244
21325
  const server = createServer2((request2, response) => {
21245
21326
  void (async () => {
@@ -21263,17 +21344,17 @@ var init_tunnel_origin = __esm({
21263
21344
  response.end();
21264
21345
  return;
21265
21346
  }
21266
- const [validation, authority] = authenticated.value;
21267
- const environment = authority.identity.environment;
21268
- if (environment === null || environment.revokedAt !== null || validation.environmentId !== environment.id || validation.keyVersion !== environment.keyVersion || validation.clientNonce !== nonce || validation.hostname !== authority.hostname || Date.parse(validation.expiresAt) <= Date.now() || !ed25519.verify(
21347
+ const [validation, authority, currentTimeMillis3] = authenticated.value;
21348
+ const environment2 = authority.identity.environment;
21349
+ if (environment2 === null || environment2.revokedAt !== null || validation.environmentId !== environment2.id || validation.keyVersion !== environment2.keyVersion || validation.clientNonce !== nonce || validation.hostname !== authority.hostname || Date.parse(validation.expiresAt) <= currentTimeMillis3 || !ed25519.verify(
21269
21350
  base64url_exports.decode(clientProof),
21270
21351
  new TextEncoder().encode(tunnelClientProofPayload(ticket, nonce)),
21271
21352
  base64url_exports.decode(validation.clientPublicKey)
21272
21353
  ))
21273
21354
  throw new TunnelOriginError({ reason: "authority" });
21274
21355
  const unsigned = {
21275
- checkedAt: parseIsoDateTime((/* @__PURE__ */ new Date()).toISOString()),
21276
- environmentId: environment.id,
21356
+ checkedAt: parseIsoDateTime(new Date(currentTimeMillis3).toISOString()),
21357
+ environmentId: environment2.id,
21277
21358
  hostname: authority.hostname,
21278
21359
  nodeVersion: options.nodeVersion,
21279
21360
  nonce,
@@ -21320,6 +21401,7 @@ var init_tunnel_origin = __esm({
21320
21401
  }
21321
21402
  let validation;
21322
21403
  let authority;
21404
+ let currentTimeMillis3;
21323
21405
  try {
21324
21406
  const authenticated = await runPromise3(
21325
21407
  authenticate(values[1].slice("glass-ticket.".length))
@@ -21330,15 +21412,15 @@ var init_tunnel_origin = __esm({
21330
21412
  );
21331
21413
  return;
21332
21414
  }
21333
- [validation, authority] = authenticated.value;
21415
+ [validation, authority, currentTimeMillis3] = authenticated.value;
21334
21416
  } catch {
21335
21417
  socket.end("HTTP/1.1 401 Unauthorized\r\nConnection: close\r\n\r\n");
21336
21418
  return;
21337
21419
  }
21338
- const environment = authority.identity.environment;
21420
+ const environment2 = authority.identity.environment;
21339
21421
  const rawTicket = values[1].slice("glass-ticket.".length);
21340
21422
  const clientProof = values[2].slice("glass-proof.".length);
21341
- if (environment === null || environment.revokedAt !== null || validation.environmentId !== environment.id || validation.keyVersion !== environment.keyVersion || validation.hostname !== authority.hostname || Date.parse(validation.expiresAt) <= Date.now() || !/^[A-Za-z0-9_-]{86}$/u.test(clientProof) || !ed25519.verify(
21423
+ if (environment2 === null || environment2.revokedAt !== null || validation.environmentId !== environment2.id || validation.keyVersion !== environment2.keyVersion || validation.hostname !== authority.hostname || Date.parse(validation.expiresAt) <= currentTimeMillis3 || !/^[A-Za-z0-9_-]{86}$/u.test(clientProof) || !ed25519.verify(
21342
21424
  base64url_exports.decode(clientProof),
21343
21425
  new TextEncoder().encode(tunnelClientProofPayload(rawTicket, validation.clientNonce)),
21344
21426
  base64url_exports.decode(validation.clientPublicKey)
@@ -21407,12 +21489,11 @@ __export(main_exports, {
21407
21489
  import { writeFile as writeFile5 } from "node:fs/promises";
21408
21490
  import { hostname, platform } from "node:os";
21409
21491
  import { dirname as dirname4, join as join5 } from "node:path";
21410
- var executionNodeVersion, ExecutionNodeError, executionDescriptor, args2, command, option2, identityPath, pairComputer, requireCompatibleCloud, runChild, program;
21492
+ var executionNodeVersion, ExecutionNodeError, ReadyFileError, executionDescriptor, args2, command, option2, identityPath, pairComputer, requireCompatibleCloud, runChild, program;
21411
21493
  var init_main = __esm({
21412
21494
  "src/main.ts"() {
21413
21495
  "use strict";
21414
21496
  init_connect();
21415
- init_connect();
21416
21497
  init_NodeServices();
21417
21498
  init_NodeRuntime2();
21418
21499
  init_Duration();
@@ -21424,13 +21505,19 @@ var init_main = __esm({
21424
21505
  init_cloudflared();
21425
21506
  init_identity();
21426
21507
  init_service_lifecycle();
21508
+ init_pairing_url();
21427
21509
  init_tunnel_control();
21428
21510
  init_tunnel_origin();
21429
- executionNodeVersion = "0.3.0";
21511
+ executionNodeVersion = "1.0.0";
21430
21512
  ExecutionNodeError = class extends TaggedError3()("ExecutionNodeError", {
21431
21513
  message: String4
21432
21514
  }) {
21433
21515
  };
21516
+ ReadyFileError = class extends TaggedError3()("ReadyFileError", {
21517
+ cause: Defect(),
21518
+ path: String4
21519
+ }) {
21520
+ };
21434
21521
  executionDescriptor = () => ({
21435
21522
  kind: "execution-node",
21436
21523
  nodeVersion: executionNodeVersion,
@@ -21449,10 +21536,17 @@ var init_main = __esm({
21449
21536
  const nodePlatform = platform() === "darwin" ? "macos" : platform() === "win32" ? "windows" : "linux";
21450
21537
  const pairing = yield* beginPairing(identity2, option2("--name") ?? hostname(), nodePlatform);
21451
21538
  yield* saveNodeIdentity(identity2, identityPath);
21539
+ const pairingOrigin = process.env.GLASS_CONNECT_PAIRING_ORIGIN ?? identity2.apiOrigin;
21452
21540
  process.stdout.write(
21453
21541
  `Connect this computer to Glass.
21454
21542
  One-time code: ${pairing.pairingCode}
21455
- Open Glass: ${new URL(pairing.approvalPath, identity2.apiOrigin)}
21543
+ Open Glass: ${buildEnvironmentPairingUrl(
21544
+ {
21545
+ cloudOrigin: identity2.apiOrigin,
21546
+ pairingToken: pairing.pairingCode,
21547
+ productOrigin: pairingOrigin
21548
+ }
21549
+ )}
21456
21550
  Waiting for approval\u2026
21457
21551
  `
21458
21552
  );
@@ -21479,11 +21573,17 @@ Waiting for approval\u2026
21479
21573
  const versionParts = (value) => value.split(".").map((part) => Number(part));
21480
21574
  const currentParts = versionParts(executionNodeVersion);
21481
21575
  const minimumParts = versionParts(decoded.minimumNodeVersion);
21576
+ const recommendedNodeVersion = decoded.recommendedNodeVersion ?? decoded.minimumNodeVersion;
21482
21577
  const nodeTooOld = [0, 1, 2].some((index) => {
21483
21578
  const current = currentParts[index] ?? 0;
21484
21579
  const minimum = minimumParts[index] ?? 0;
21485
21580
  return current < minimum && currentParts.slice(0, index).every((part, prior) => part === minimumParts[prior]);
21486
21581
  });
21582
+ if (executionNodeVersion !== recommendedNodeVersion)
21583
+ process.stderr.write(
21584
+ `Glass Connect ${executionNodeVersion} is running. Recommended version is ${recommendedNodeVersion}; update with npx glass-connect@${recommendedNodeVersion} update.
21585
+ `
21586
+ );
21487
21587
  if (glassConnectProtocolVersion < decoded.minimumProtocolVersion || glassConnectProtocolVersion > decoded.maximumProtocolVersion || nodeTooOld)
21488
21588
  return yield* new TunnelControlError({
21489
21589
  status: 426,
@@ -21505,11 +21605,11 @@ Waiting for approval\u2026
21505
21605
  });
21506
21606
  program = gen2(function* () {
21507
21607
  if (command === "start" || command === "install") {
21508
- const configuredOrigin = process.env.GLASS_CLOUD_ORIGIN;
21608
+ const configuredOrigin2 = process.env.GLASS_CLOUD_ORIGIN;
21509
21609
  let identity2 = yield* loadNodeIdentity(identityPath);
21510
- if (identity2 !== null && configuredOrigin !== void 0 && new URL(identity2.apiOrigin).origin !== new URL(configuredOrigin).origin)
21610
+ if (identity2 !== null && configuredOrigin2 !== void 0 && new URL(identity2.apiOrigin).origin !== new URL(configuredOrigin2).origin)
21511
21611
  return yield* new ExecutionNodeError({
21512
- message: `This Glass Connect identity belongs to ${identity2.apiOrigin}. Use stage-specific state for ${configuredOrigin}.`
21612
+ message: `This Glass Connect identity belongs to ${identity2.apiOrigin}. Use stage-specific state for ${configuredOrigin2}.`
21513
21613
  });
21514
21614
  if (identity2 !== null && identity2.environment !== null) {
21515
21615
  const storedIdentity = identity2;
@@ -21528,7 +21628,7 @@ Waiting for approval\u2026
21528
21628
  )
21529
21629
  );
21530
21630
  } else {
21531
- const origin = configuredOrigin ?? identity2?.apiOrigin;
21631
+ const origin = configuredOrigin2 ?? identity2?.apiOrigin;
21532
21632
  if (origin === void 0)
21533
21633
  return yield* new ExecutionNodeError({
21534
21634
  message: "Glass Connect has no configured Glass Cloud origin."
@@ -21554,7 +21654,7 @@ Waiting for approval\u2026
21554
21654
  }
21555
21655
  } else if (command === "help") {
21556
21656
  process.stdout.write(
21557
- "Usage: glass-connect [start|install] [--name NAME] | stop | status | uninstall | descriptor\n"
21657
+ "Usage: glass-connect [start|install] [--name NAME] [--environment preview|production] [--cloud-origin URL] [--pairing-origin URL] [--identity-path PATH] | update | stop | status | uninstall | descriptor\n"
21558
21658
  );
21559
21659
  } else if (command === "descriptor") {
21560
21660
  process.stdout.write(`${JSON.stringify(executionDescriptor())}
@@ -21570,6 +21670,25 @@ Waiting for approval\u2026
21570
21670
  process.stdout.write(
21571
21671
  "Glass Connect background service was removed. The paired computer identity was preserved.\n"
21572
21672
  );
21673
+ } else if (command === "update") {
21674
+ const identity2 = yield* loadNodeIdentity(identityPath);
21675
+ if (identity2 === null || identity2.environment === null)
21676
+ return yield* new ExecutionNodeError({
21677
+ message: "No connected computer exists. Start Glass Connect first."
21678
+ });
21679
+ const entryPath = process.argv[1];
21680
+ if (entryPath === void 0)
21681
+ return yield* new ExecutionNodeError({
21682
+ message: "Glass Connect cannot locate its installed entry point."
21683
+ });
21684
+ yield* installService({
21685
+ cloudOrigin: identity2.apiOrigin,
21686
+ entryPath,
21687
+ identityPath,
21688
+ version: executionNodeVersion
21689
+ });
21690
+ process.stdout.write(`Glass Connect ${executionNodeVersion} is installed and running.
21691
+ `);
21573
21692
  } else if (command === "connect") {
21574
21693
  let identity2 = yield* loadNodeIdentity(identityPath);
21575
21694
  if (identity2 === null || identity2.environment === null)
@@ -21647,13 +21766,14 @@ Waiting for approval\u2026
21647
21766
  yield* control.publishPresence(executionNodeVersion, "connected");
21648
21767
  const readyPath = process.env.GLASS_CONNECT_READY_PATH;
21649
21768
  if (readyPath !== void 0) {
21650
- yield* promise2(
21651
- () => writeFile5(readyPath, `${executionNodeVersion}
21769
+ yield* tryPromise2({
21770
+ try: () => writeFile5(readyPath, `${executionNodeVersion}
21652
21771
  `, {
21653
21772
  encoding: "utf8",
21654
21773
  mode: 384
21655
- })
21656
- );
21774
+ }),
21775
+ catch: (cause) => new ReadyFileError({ cause, path: readyPath })
21776
+ });
21657
21777
  }
21658
21778
  if (heartbeat !== null) yield* interrupt3(heartbeat);
21659
21779
  heartbeat = yield* forkDetach2(
@@ -21680,7 +21800,7 @@ Waiting for approval\u2026
21680
21800
  process.once(signal, () => runFork3(shutdown2));
21681
21801
  } else {
21682
21802
  return yield* new ExecutionNodeError({
21683
- message: "Usage: glass-connect [start|install] [--name NAME] | stop | status | uninstall | descriptor"
21803
+ message: "Usage: glass-connect [start|install] [--name NAME] [--environment preview|production] [--cloud-origin URL] [--pairing-origin URL] [--identity-path PATH] | update | stop | status | uninstall | descriptor"
21684
21804
  });
21685
21805
  }
21686
21806
  });
@@ -21692,19 +21812,32 @@ Waiting for approval\u2026
21692
21812
  var glass_cloud_default = {
21693
21813
  origins: {
21694
21814
  production: "https://glasscloud-api-prod-lcuxsmngpdigrgum.naaiyyyy.workers.dev",
21695
- staging: "https://glasscloud-api-staging-rmhiqpuua7m4g6a3.naaiyyyy.workers.dev"
21815
+ preview: "https://glasscloud-api-staging-rmhiqpuua7m4g6a3.naaiyyyy.workers.dev"
21696
21816
  },
21697
21817
  services: {
21698
- stagingTunnelControl: "glasscloud-tunnelcontrol-staging-uyzu7wweagwmmwd2"
21818
+ previewTunnelControl: "glasscloud-tunnelcontrol-staging-uyzu7wweagwmmwd2"
21699
21819
  }
21700
21820
  };
21701
21821
 
21702
21822
  // npm/cli.ts
21703
21823
  import { homedir as homedir3 } from "node:os";
21704
21824
  import { join as join6 } from "node:path";
21705
- var productionStateRoot = join6(homedir3(), ".glass", "production");
21706
- process.env.GLASS_CLOUD_ORIGIN ??= glass_cloud_default.origins.production;
21707
- process.env.GLASS_NODE_IDENTITY_PATH ??= join6(productionStateRoot, "execution-node.json");
21825
+ var args3 = process.argv.slice(2);
21826
+ var option3 = (name) => {
21827
+ const index = args3.indexOf(name);
21828
+ return index < 0 ? void 0 : args3[index + 1];
21829
+ };
21830
+ var requestedEnvironment = option3("--environment");
21831
+ if (requestedEnvironment !== void 0 && !["preview", "production"].includes(requestedEnvironment)) {
21832
+ throw new Error("--environment must be preview or production.");
21833
+ }
21834
+ var environment = requestedEnvironment === "preview" ? "preview" : "production";
21835
+ var configuredOrigin = option3("--cloud-origin") ?? (requestedEnvironment === void 0 ? process.env.GLASS_CLOUD_ORIGIN : environment === "preview" ? glass_cloud_default.origins.preview : glass_cloud_default.origins.production) ?? (environment === "preview" ? glass_cloud_default.origins.preview : glass_cloud_default.origins.production);
21836
+ var productOrigin = option3("--pairing-origin") ?? process.env.GLASS_CONNECT_PAIRING_ORIGIN ?? configuredOrigin;
21837
+ var stateRoot = join6(homedir3(), ".glass", environment);
21838
+ process.env.GLASS_CLOUD_ORIGIN = configuredOrigin;
21839
+ process.env.GLASS_CONNECT_PAIRING_ORIGIN = productOrigin;
21840
+ process.env.GLASS_NODE_IDENTITY_PATH = option3("--identity-path") ?? (requestedEnvironment === void 0 && process.env.GLASS_NODE_IDENTITY_PATH !== void 0 ? process.env.GLASS_NODE_IDENTITY_PATH : join6(stateRoot, "execution-node.json"));
21708
21841
  process.env.GLASS_CONNECT_BUNDLED = "1";
21709
21842
  await Promise.resolve().then(() => (init_main(), main_exports));
21710
21843
  /*! Bundled license information:
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "glass-connect",
3
- "version": "0.3.0",
3
+ "version": "1.0.0",
4
4
  "description": "Publish a computer to Glass with one command.",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
7
7
  "type": "git",
8
- "url": "git+https://github.com/naaiyy/Glass.git",
8
+ "url": "git+https://github.com/Glass-HQ/Glass-cloud.git",
9
9
  "directory": "apps/execution-node/npm"
10
10
  },
11
11
  "bin": {