@pablopunk/tau 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -682,7 +682,9 @@ const HubLinkSchema = Type.Object({
682
682
  hubUrl: Type.Union([Type.String(), Type.Null()]),
683
683
  since: Type.Union([Type.Number(), Type.Null()]),
684
684
  /** A neutral sentence for the user ("Hub unreachable", "Update tau on the hub"). */
685
- message: Type.Union([Type.String(), Type.Null()])
685
+ message: Type.Union([Type.String(), Type.Null()]),
686
+ /** The OS of this tau itself ("darwin arm64"), set by core on every read. */
687
+ os: Type.Optional(Type.String())
686
688
  });
687
689
  const HUB_LINK_NONE = {
688
690
  state: "none",
@@ -827,6 +829,15 @@ const OpenTerminalInputSchema = Type.Object({
827
829
  });
828
830
  const TerminalAvailabilitySchema = Type.Object({ available: Type.Boolean() });
829
831
  //#endregion
832
+ //#region ../protocol/src/updates.ts
833
+ /** This tau's version against the latest published one. `latest` and `checkedAt` are null until a check succeeds. */
834
+ const UpdateStatusSchema = Type.Object({
835
+ current: Type.String(),
836
+ latest: Type.Union([Type.String(), Type.Null()]),
837
+ checkedAt: Type.Union([Type.Number(), Type.Null()]),
838
+ behind: Type.Boolean()
839
+ });
840
+ //#endregion
830
841
  //#region ../protocol/src/rest.ts
831
842
  const API_PREFIX$1 = "/api";
832
843
  const LIVE_PATH = `${API_PREFIX$1}/live`;
@@ -962,6 +973,18 @@ const routes = {
962
973
  path: `${API_PREFIX$1}/machines/link`,
963
974
  status: 200
964
975
  },
976
+ getUpdateStatus: {
977
+ method: "GET",
978
+ path: `${API_PREFIX$1}/update`,
979
+ status: 200,
980
+ response: UpdateStatusSchema
981
+ },
982
+ refreshUpdateStatus: {
983
+ method: "POST",
984
+ path: `${API_PREFIX$1}/update/refresh`,
985
+ status: 200,
986
+ response: UpdateStatusSchema
987
+ },
965
988
  getSettings: {
966
989
  method: "GET",
967
990
  path: `${API_PREFIX$1}/settings`,
@@ -2524,7 +2547,7 @@ function* chunkBody(id, body, text = false) {
2524
2547
  * `protocol-version.test.ts` fails when the surface changes and this value does not; run
2525
2548
  * `mise exec -- pnpm --filter @tau/protocol bump-protocol` to rewrite it.
2526
2549
  */
2527
- const PROTOCOL_VERSION = "2920245394fa6ab6f484a959fae886b4";
2550
+ const PROTOCOL_VERSION = "52f4e01e45d4338519dfea5564becdf1";
2528
2551
  //#endregion
2529
2552
  //#region ../protocol/src/retry.ts
2530
2553
  const RETRY_ENTRY_KINDS = [
@@ -2545,6 +2568,41 @@ function isRetryable(view) {
2545
2568
  return last !== void 0 && !isFinishedAnswer(last);
2546
2569
  }
2547
2570
  //#endregion
2571
+ //#region ../protocol/src/versions.ts
2572
+ const PLAIN = /^(\d+)\.(\d+)\.(\d+)$/;
2573
+ const WITH_PRE = /^(\d+)\.(\d+)\.(\d+)(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
2574
+ const isPlainVersion = (text) => PLAIN.test(text);
2575
+ function parts(version) {
2576
+ const match = WITH_PRE.exec(version);
2577
+ if (!match) throw new Error(`Not a version: ${version}`);
2578
+ return {
2579
+ core: [
2580
+ Number(match[1]),
2581
+ Number(match[2]),
2582
+ Number(match[3])
2583
+ ],
2584
+ prerelease: version.includes("-")
2585
+ };
2586
+ }
2587
+ /** Negative when `a < b`, 0 when equal, positive when `a > b`. A prerelease is below its release. */
2588
+ function compareVersions(a, b) {
2589
+ const left = parts(a);
2590
+ const right = parts(b);
2591
+ for (let index = 0; index < 3; index++) {
2592
+ const diff = (left.core[index] ?? 0) - (right.core[index] ?? 0);
2593
+ if (diff !== 0) return diff;
2594
+ }
2595
+ return Number(right.prerelease) - Number(left.prerelease);
2596
+ }
2597
+ /** Total: `undefined` when either side is empty or not a version. Equal or ahead is not behind. */
2598
+ function isBehind(current, latest) {
2599
+ try {
2600
+ return compareVersions(current, latest) < 0;
2601
+ } catch {
2602
+ return;
2603
+ }
2604
+ }
2605
+ //#endregion
2548
2606
  //#region ../protocol/src/view-text.ts
2549
2607
  const TOOL_ARGUMENT_LIMIT = 80;
2550
2608
  const blocksOf$1 = (content) => Array.isArray(content) ? content : [];
@@ -5883,7 +5941,7 @@ function loadConfig2() {
5883
5941
  throw new Error(`Failed to parse ${CONFIG_PATH3}: ${message}`);
5884
5942
  }
5885
5943
  }
5886
- function withTimeout(signal, timeoutMs) {
5944
+ function withTimeout$1(signal, timeoutMs) {
5887
5945
  const timeout = AbortSignal.timeout(timeoutMs);
5888
5946
  return signal ? AbortSignal.any([signal, timeout]) : timeout;
5889
5947
  }
@@ -6017,7 +6075,7 @@ function isGeminiApiAvailableWithVideo() {
6017
6075
  return hasGeminiApiKeySource2() || isGatewayConfigured();
6018
6076
  }
6019
6077
  async function queryGeminiApiWithInlineData(prompt, data, mimeType, options = {}) {
6020
- const signal = withTimeout(options.signal, options.timeoutMs ?? 12e4);
6078
+ const signal = withTimeout$1(options.signal, options.timeoutMs ?? 12e4);
6021
6079
  const apiKey = isGeminiAdcAvailable() ? null : options.apiKey ?? await getApiKey(signal);
6022
6080
  if (!apiKey && !isGatewayConfigured() && !isGeminiAdcAvailable()) throw new Error(`Gemini API not configured. Either:
6023
6081
  1. Configure geminiApiKey in ${CONFIG_PATH3} or set GEMINI_API_KEY
@@ -6049,7 +6107,7 @@ async function queryGeminiApiWithInlineData(prompt, data, mimeType, options = {}
6049
6107
  };
6050
6108
  }
6051
6109
  async function queryGeminiApiWithVideo(prompt, videoUri, options = {}) {
6052
- const signal = withTimeout(options.signal, options.timeoutMs ?? 12e4);
6110
+ const signal = withTimeout$1(options.signal, options.timeoutMs ?? 12e4);
6053
6111
  const apiKey = options.apiKey ?? await getApiKey(signal);
6054
6112
  if (!apiKey && !isGatewayConfigured()) throw new Error(`Gemini API not configured. Either:
6055
6113
  1. Configure geminiApiKey in ${CONFIG_PATH3} or set GEMINI_API_KEY
@@ -8188,7 +8246,7 @@ async function fetchBatch(urls, apiKey, signal, options = {}) {
8188
8246
  return tinyFishJsonRequest("Fetch", TINYFISH_FETCH_URL, apiKey, {
8189
8247
  method: "POST",
8190
8248
  body: JSON.stringify(fetchBody(urls, options))
8191
- }, FETCH_TIMEOUT_MS, signal);
8249
+ }, FETCH_TIMEOUT_MS$1, signal);
8192
8250
  }
8193
8251
  async function fetchInlineContent(urls, apiKey, signal) {
8194
8252
  const content = [];
@@ -8277,7 +8335,7 @@ var TINYFISH_SEARCH_URL;
8277
8335
  var TINYFISH_FETCH_URL;
8278
8336
  var CONFIG_PATH11;
8279
8337
  var SEARCH_TIMEOUT_MS5;
8280
- var FETCH_TIMEOUT_MS;
8338
+ var FETCH_TIMEOUT_MS$1;
8281
8339
  var MAX_FETCH_URLS;
8282
8340
  var MAX_FETCH_PER_URL_TIMEOUT_MS;
8283
8341
  var cachedConfig10;
@@ -8292,7 +8350,7 @@ var init_tinyfish = __esm({ "tinyfish.ts"() {
8292
8350
  TINYFISH_FETCH_URL = "https://api.fetch.tinyfish.ai";
8293
8351
  CONFIG_PATH11 = getWebSearchConfigPath();
8294
8352
  SEARCH_TIMEOUT_MS5 = 6e4;
8295
- FETCH_TIMEOUT_MS = 15e4;
8353
+ FETCH_TIMEOUT_MS$1 = 15e4;
8296
8354
  MAX_FETCH_URLS = 10;
8297
8355
  MAX_FETCH_PER_URL_TIMEOUT_MS = 11e4;
8298
8356
  cachedConfig10 = null;
@@ -37376,7 +37434,10 @@ function createMachines(deps) {
37376
37434
  await deps.access.revokeDevice(id);
37377
37435
  announce();
37378
37436
  },
37379
- hubState: async () => link,
37437
+ hubState: async () => ({
37438
+ ...link,
37439
+ os: `${process.platform} ${process.arch}`
37440
+ }),
37380
37441
  async disconnectHub() {
37381
37442
  await deps.forgetHub?.();
37382
37443
  link = HUB_LINK_NONE;
@@ -41880,7 +41941,10 @@ function createFakeRemoteAdapter(now = Date.now) {
41880
41941
  state: "online",
41881
41942
  since: now()
41882
41943
  } : online()),
41883
- disable: async () => set(REMOTE_OFF),
41944
+ disable: async () => set({
41945
+ ...REMOTE_OFF,
41946
+ url: current.url
41947
+ }),
41884
41948
  recreate: async () => set(online()),
41885
41949
  onStatus(listener) {
41886
41950
  listeners.add(listener);
@@ -41900,6 +41964,9 @@ function createFakeRemoteAdapter(now = Date.now) {
41900
41964
  close: async () => void listeners.clear()
41901
41965
  };
41902
41966
  }
41967
+ //#endregion
41968
+ //#region ../core/src/remote/neutral-text.ts
41969
+ const STARTING_TEXT = "Setting up remote access (usually 3-6 minutes).";
41903
41970
  const OFFLINE_TEXT = "Cannot reach the tunnel service";
41904
41971
  const RECREATE_TEXT = "The tunnel has been offline for 10 minutes. You can make a new URL.";
41905
41972
  const GENERIC = "The tunnel service had a problem.";
@@ -41913,6 +41980,14 @@ function isNetworkFailure(error) {
41913
41980
  return NETWORK_CODES.test(text);
41914
41981
  }
41915
41982
  const neutralFailure = (error) => neutralRemoteText(isNetworkFailure(error));
41983
+ const CREATE_DEADLINE_MS = 72e4;
41984
+ const STAGE_TEXT = {
41985
+ "generating-csr": "Preparing the certificate request.",
41986
+ "requesting-certificate": "Requesting the certificate.",
41987
+ "waiting-certificate": "Waiting for the certificate (usually 3-6 minutes)."
41988
+ };
41989
+ /** The message for a provisioning stage; stages without text keep the generic one. */
41990
+ const stageText = (stage) => STAGE_TEXT[stage] ?? "Setting up remote access (usually 3-6 minutes).";
41916
41991
  //#endregion
41917
41992
  //#region ../core/src/remote/status-machine.ts
41918
41993
  const RECREATE_AFTER_MS = 6e5;
@@ -41956,8 +42031,8 @@ function createStatusMachine(now, schedule = timeoutSchedule) {
41956
42031
  if (offlineStates.includes(state) && !keepsOfflineClock) armRecreateTimer();
41957
42032
  if (!offlineStates.includes(state)) cancelTimer?.();
41958
42033
  const canRecreate = keepsOfflineClock && current.canRecreate;
41959
- const message = patch.message ?? (state === "starting" ? "Starting. The first time takes a few minutes." : null);
41960
- const url = patch.url === void 0 ? state === "off" ? null : current.url : patch.url;
42034
+ const message = patch.message ?? (state === "starting" ? keptStartingMessage(current) : null);
42035
+ const url = patch.url === void 0 ? current.url : patch.url;
41961
42036
  const since = state === current.state && current.since !== null ? current.since : now();
41962
42037
  publish({
41963
42038
  ...current,
@@ -41976,6 +42051,7 @@ function createStatusMachine(now, schedule = timeoutSchedule) {
41976
42051
  }
41977
42052
  };
41978
42053
  }
42054
+ const keptStartingMessage = (current) => current.state === "starting" && current.message ? current.message : STARTING_TEXT;
41979
42055
  //#endregion
41980
42056
  //#region ../core/src/remote/tunnel-profiles.ts
41981
42057
  const profileNameFor = (directory) => `tau-${createHash("sha256").update(directory).digest("hex").slice(0, 8)}`;
@@ -42055,7 +42131,20 @@ function createOpenTunnelAdapter(deps) {
42055
42131
  }
42056
42132
  }
42057
42133
  async function connect(run) {
42058
- const identity = await client.tunnel.get({ profile }) ?? await client.tunnel.resume({ profile }) ?? await client.tunnel.create({ profile });
42134
+ const onProgress = (stage) => {
42135
+ if (run === generation && machine.status().state === "starting") machine.set("starting", { message: stageText(stage) });
42136
+ };
42137
+ const cancelCreate = schedule(() => {
42138
+ if (run === generation && machine.status().state === "starting") machine.set("error", { message: OFFLINE_TEXT });
42139
+ }, CREATE_DEADLINE_MS);
42140
+ const identity = await client.tunnel.get({ profile }) ?? await client.tunnel.resume({
42141
+ profile,
42142
+ onProgress
42143
+ }) ?? await client.tunnel.create({
42144
+ profile,
42145
+ onProgress
42146
+ });
42147
+ cancelCreate();
42059
42148
  if (run !== generation) return;
42060
42149
  const url = urlOf(identity.hostname);
42061
42150
  machine.set("starting", { url });
@@ -42095,6 +42184,10 @@ function createOpenTunnelAdapter(deps) {
42095
42184
  connection = void 0;
42096
42185
  await live?.close().catch(() => void 0);
42097
42186
  }
42187
+ async function showKeptUrl() {
42188
+ const kept = await client.tunnel.get({ profile }).catch(() => void 0);
42189
+ if (kept && machine.status().state === "off") machine.set("off", { url: urlOf(kept.hostname) });
42190
+ }
42098
42191
  const active = () => [
42099
42192
  "starting",
42100
42193
  "online",
@@ -42111,13 +42204,7 @@ function createOpenTunnelAdapter(deps) {
42111
42204
  },
42112
42205
  async disable() {
42113
42206
  await stopConnection();
42114
- try {
42115
- await client.tunnel.remove({ profile });
42116
- } catch {
42117
- await profiles.retireMain().catch(() => void 0);
42118
- retryRemovals();
42119
- }
42120
- machine.set("off");
42207
+ machine.set("off", { message: null });
42121
42208
  return machine.status();
42122
42209
  },
42123
42210
  async recreate() {
@@ -42133,6 +42220,7 @@ function createOpenTunnelAdapter(deps) {
42133
42220
  retryRemovals();
42134
42221
  if (holdReason) machine.set("off", { message: holdReason });
42135
42222
  else if (enabled) await this.enable();
42223
+ else await showKeptUrl();
42136
42224
  },
42137
42225
  async close() {
42138
42226
  await stopConnection();
@@ -42157,8 +42245,6 @@ function createRemoteService({ adapter, settings, access, changes, forgetMachine
42157
42245
  async disable() {
42158
42246
  const status = await adapter.disable();
42159
42247
  await settings.setRemoteEnabled(false);
42160
- await access.clearAll();
42161
- await forgetMachines?.();
42162
42248
  changes.emit({ resource: "remote" });
42163
42249
  return status;
42164
42250
  },
@@ -43130,6 +43216,70 @@ function createTitleService(deps) {
43130
43216
  }
43131
43217
  } };
43132
43218
  }
43219
+ //#endregion
43220
+ //#region ../core/src/updates/update-service.ts
43221
+ const REFRESH_EVERY_MS = 216e5;
43222
+ const FETCH_TIMEOUT_MS = 1e4;
43223
+ function withTimeout(work, ms) {
43224
+ let timer;
43225
+ const timeout = new Promise((_, reject) => {
43226
+ timer = setTimeout(() => reject(/* @__PURE__ */ new Error("timed out")), ms);
43227
+ timer.unref();
43228
+ });
43229
+ return Promise.race([work, timeout]).finally(() => clearTimeout(timer));
43230
+ }
43231
+ function createUpdateService(deps) {
43232
+ let latest = null;
43233
+ let checkedAt = null;
43234
+ let lastAttemptAt = null;
43235
+ let inflight;
43236
+ let timer;
43237
+ let stopped = false;
43238
+ const snapshot = () => ({
43239
+ current: deps.currentVersion,
43240
+ latest,
43241
+ checkedAt,
43242
+ behind: latest === null ? false : isBehind(deps.currentVersion, latest) ?? false
43243
+ });
43244
+ const check = () => {
43245
+ if (inflight) return inflight;
43246
+ lastAttemptAt = deps.now();
43247
+ inflight = withTimeout(Promise.resolve().then(deps.latestVersion), FETCH_TIMEOUT_MS).then((version) => {
43248
+ latest = version;
43249
+ checkedAt = deps.now();
43250
+ }).catch(() => void 0).finally(() => {
43251
+ inflight = void 0;
43252
+ });
43253
+ return inflight;
43254
+ };
43255
+ const startTimer = () => {
43256
+ if (timer || stopped) return;
43257
+ timer = setInterval(() => void check(), REFRESH_EVERY_MS);
43258
+ timer.unref();
43259
+ };
43260
+ return {
43261
+ async status() {
43262
+ if (lastAttemptAt === null && !stopped) {
43263
+ check();
43264
+ startTimer();
43265
+ }
43266
+ return snapshot();
43267
+ },
43268
+ async refresh() {
43269
+ if (stopped) return snapshot();
43270
+ startTimer();
43271
+ const recent = lastAttemptAt !== null && deps.now() - lastAttemptAt < 6e4;
43272
+ if (inflight) await inflight;
43273
+ else if (!recent) await check();
43274
+ return snapshot();
43275
+ },
43276
+ stop() {
43277
+ stopped = true;
43278
+ if (timer) clearInterval(timer);
43279
+ timer = void 0;
43280
+ }
43281
+ };
43282
+ }
43133
43283
  const CRASH_LOOP_WINDOW_MS = 3e5;
43134
43284
  const REASONS = [
43135
43285
  "clean",
@@ -43793,6 +43943,11 @@ async function createCoreWith(options, deps) {
43793
43943
  remoteUrl: () => tunnel.status().url,
43794
43944
  announce: () => changes.emit({ resource: "devices" })
43795
43945
  });
43946
+ const updates = createUpdateService({
43947
+ currentVersion: options.currentVersion,
43948
+ latestVersion: options.latestVersion,
43949
+ now: deps.now
43950
+ });
43796
43951
  const machines = createMachines({
43797
43952
  directory: home.machinesDirectory,
43798
43953
  now: deps.now,
@@ -43879,10 +44034,15 @@ async function createCoreWith(options, deps) {
43879
44034
  mcp,
43880
44035
  changes
43881
44036
  }),
44037
+ updates: {
44038
+ status: () => updates.status(),
44039
+ refresh: () => updates.refresh()
44040
+ },
43882
44041
  onChange: (listener) => changes.subscribe(listener),
43883
44042
  close() {
43884
44043
  closing ??= (async () => {
43885
44044
  changes.clear();
44045
+ updates.stop();
43886
44046
  await remote.close();
43887
44047
  await archivedCleanup.stop();
43888
44048
  clones.stopAll();
@@ -43925,27 +44085,4 @@ function publishServerUrl(home, url, version) {
43925
44085
  }));
43926
44086
  }
43927
44087
  //#endregion
43928
- //#region src/lifecycle/wait-for-lock.ts
43929
- const LOCK_POLL_MS = 5e3;
43930
- const sleepFor = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
43931
- /** `serve --service` waits here while a foreground tau holds the home, so no manager sees an exit loop. */
43932
- async function waitForFreeHome(home, dependencies = {}) {
43933
- const { readInstance = readRunningInstance, sleep = sleepFor, log, intervalMs = LOCK_POLL_MS } = dependencies;
43934
- let announced = false;
43935
- for (let owner = await readInstance(home); owner; owner = await readInstance(home)) {
43936
- if (!announced) log?.(`Another tau (pid ${owner.pid}) holds ${home}. Waiting for it to stop.`);
43937
- announced = true;
43938
- await sleep(intervalMs);
43939
- }
43940
- }
43941
- /** Polls until the running server has published its URL. */
43942
- async function waitForUrl(home, dependencies = {}) {
43943
- const { readInstance = readRunningInstance, sleep = sleepFor, intervalMs = 250, attempts = 60 } = dependencies;
43944
- for (let attempt = 0; attempt < attempts; attempt += 1) {
43945
- const info = await readInstance(home);
43946
- if (info?.url) return info;
43947
- await sleep(intervalMs);
43948
- }
43949
- }
43950
- //#endregion
43951
- export { routes as $, changedFrame as A, COMMAND_NOUNS as B, LIVE_MAX_FRAME_BYTES as C, TERMINAL_STREAM_PATH as D, TERMINAL_STREAM_MAX_INPUT_BYTES as E, ERROR_STATUS as F, isModelRefNode as G, commandOf as H, isAppError as I, LIVE_PATH as J, routeFields as K, isErrorBody as L, decodeServerFrame as M, encodeFrame as N, TerminalClientFrameSchema as O, AppError as P, iconCandidateUrl as Q, toErrorBody as R, encodeDataFrame as S, TERMINAL_STREAM_CLOSE_UNKNOWN as T, commands as U, FLOW_COMMANDS as V, flagNameOf as W, PAIR_PAGE_PATH as X, MESSAGE_BODY_LIMIT as Y, fillPath as Z, LINK_PING_INTERVAL_MS as _, readRunningInstance as a, chunkBody as b, lastAssistantText as c, CHUNK_BYTES as d, HUB_LINK_NONE as et, CREDIT_WINDOW_BYTES as f, LINK_OFFLINE_AFTER_MS as g, LINK_NO_CREDIT_CLOSE_MS as h, publishServerUrl as i, RedeemPairingResponseSchema as it, decodeClientFrame as j, WS_MAX_PAYLOAD_BYTES as k, viewToText as l, LINK_CLOSE_UPDATE_REQUIRED as m, waitForFreeHome as n, nextViewState as nt, createCore as o, LINK_CLOSE_NO_CREDIT as p, API_PREFIX$1 as q, waitForUrl as r, RETIRED_OPS as rt, createExitMarker as s, LOCK_POLL_MS as t, MACHINE_PROXY_PREFIX as tt, PROTOCOL_VERSION as u, LinkFrameSchema as v, TERMINAL_STREAM_CLOSE_SLOW as w, decodeDataFrame as x, MACHINE_LINK_PATH as y, AUTO_FIELDS as z };
44088
+ export { routes as $, changedFrame as A, COMMAND_NOUNS as B, LIVE_MAX_FRAME_BYTES as C, TERMINAL_STREAM_PATH as D, TERMINAL_STREAM_MAX_INPUT_BYTES as E, ERROR_STATUS as F, isModelRefNode as G, commandOf as H, isAppError as I, LIVE_PATH as J, routeFields as K, isErrorBody as L, decodeServerFrame as M, encodeFrame as N, TerminalClientFrameSchema as O, AppError as P, iconCandidateUrl as Q, toErrorBody as R, encodeDataFrame as S, TERMINAL_STREAM_CLOSE_UNKNOWN as T, commands as U, FLOW_COMMANDS as V, flagNameOf as W, PAIR_PAGE_PATH as X, MESSAGE_BODY_LIMIT as Y, fillPath as Z, LINK_PING_INTERVAL_MS as _, lastAssistantText as a, chunkBody as b, isBehind as c, CHUNK_BYTES as d, HUB_LINK_NONE as et, CREDIT_WINDOW_BYTES as f, LINK_OFFLINE_AFTER_MS as g, LINK_NO_CREDIT_CLOSE_MS as h, createExitMarker as i, RedeemPairingResponseSchema as it, decodeClientFrame as j, WS_MAX_PAYLOAD_BYTES as k, isPlainVersion as l, LINK_CLOSE_UPDATE_REQUIRED as m, readRunningInstance as n, nextViewState as nt, viewToText as o, LINK_CLOSE_NO_CREDIT as p, API_PREFIX$1 as q, createCore as r, RETIRED_OPS as rt, compareVersions as s, publishServerUrl as t, MACHINE_PROXY_PREFIX as tt, PROTOCOL_VERSION as u, LinkFrameSchema as v, TERMINAL_STREAM_CLOSE_SLOW as w, decodeDataFrame as x, MACHINE_LINK_PATH as y, AUTO_FIELDS as z };
@@ -0,0 +1 @@
1
+ export { r as waitForUrl } from "./wait-for-lock-CrSl2mi1.js";
@@ -0,0 +1,25 @@
1
+ import { n as readRunningInstance } from "./src-DO9LUlhi.js";
2
+ //#region src/lifecycle/wait-for-lock.ts
3
+ const LOCK_POLL_MS = 5e3;
4
+ const sleepFor = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
5
+ /** `serve --service` waits here while a foreground tau holds the home, so no manager sees an exit loop. */
6
+ async function waitForFreeHome(home, dependencies = {}) {
7
+ const { readInstance = readRunningInstance, sleep = sleepFor, log, intervalMs = LOCK_POLL_MS } = dependencies;
8
+ let announced = false;
9
+ for (let owner = await readInstance(home); owner; owner = await readInstance(home)) {
10
+ if (!announced) log?.(`Another tau (pid ${owner.pid}) holds ${home}. Waiting for it to stop.`);
11
+ announced = true;
12
+ await sleep(intervalMs);
13
+ }
14
+ }
15
+ /** Polls until the running server has published its URL. */
16
+ async function waitForUrl(home, dependencies = {}) {
17
+ const { readInstance = readRunningInstance, sleep = sleepFor, intervalMs = 250, attempts = 60 } = dependencies;
18
+ for (let attempt = 0; attempt < attempts; attempt += 1) {
19
+ const info = await readInstance(home);
20
+ if (info?.url) return info;
21
+ await sleep(intervalMs);
22
+ }
23
+ }
24
+ //#endregion
25
+ export { waitForFreeHome as n, waitForUrl as r, LOCK_POLL_MS as t };