@noya-app/noya-api-client-react 0.1.44 → 0.1.46

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/index.mjs CHANGED
@@ -2289,8 +2289,6 @@ function useNoyaClientOrFallback() {
2289
2289
 
2290
2290
  // src/react/hooks.ts
2291
2291
  import { useSelector } from "@legendapp/state/react";
2292
- import { GENERATED_PAGE_NAME_COUNT } from "@noya-app/noya-api";
2293
- import { range } from "@noya-app/noya-utils";
2294
2292
  import { useObservable } from "@noya-app/observable-react";
2295
2293
  import { useCallback, useEffect, useMemo as useMemo2, useRef } from "react";
2296
2294
  function useNoyaTools(initial) {
@@ -2422,87 +2420,11 @@ function useMetadata(key) {
2422
2420
  const metadataItem = metadata.find((item) => item.key === key);
2423
2421
  return metadataItem?.value;
2424
2422
  }
2425
- function useGeneratedComponentNames(name) {
2426
- const key = name.trim().toLowerCase();
2427
- const { generatedNames$, loadingNames$ } = useNoyaClientOrFallback();
2428
- const result = useSelector(
2429
- () => generatedNames$[key].get()
2430
- );
2431
- const loading = useSelector(() => loadingNames$[key].get());
2432
- return useMemo2(() => ({ names: result ?? [], loading }), [loading, result]);
2433
- }
2434
- function useGeneratedComponentDescriptions() {
2435
- const { generatedDescriptions$, loadingDescriptions$ } = useNoyaClientOrFallback();
2436
- const descriptions = useSelector(generatedDescriptions$);
2437
- const loading = useSelector(loadingDescriptions$);
2438
- return useMemo2(() => ({ descriptions, loading }), [loading, descriptions]);
2439
- }
2440
- function useGeneratedComponentDescription(name) {
2441
- const key = name.trim().toLowerCase();
2442
- const { generatedDescriptions$, loadingDescriptions$ } = useNoyaClientOrFallback();
2443
- const description = useSelector(
2444
- () => generatedDescriptions$[key].get()
2445
- );
2446
- const loading = useSelector(() => loadingDescriptions$[key].get());
2447
- return useMemo2(() => ({ description, loading }), [loading, description]);
2448
- }
2449
- function useRandomImages() {
2450
- const { randomImages$, loadingRandomImages$ } = useNoyaClientOrFallback();
2451
- const images = useSelector(randomImages$);
2452
- const loading = useSelector(loadingRandomImages$);
2453
- return useMemo2(() => ({ images, loading }), [loading, images]);
2454
- }
2455
- function useRandomIcons() {
2456
- const { randomIcons$, loadingRandomIcons$ } = useNoyaClientOrFallback();
2457
- const icons = useSelector(randomIcons$);
2458
- const loading = useSelector(loadingRandomIcons$);
2459
- return useMemo2(() => ({ icons, loading }), [loading, icons]);
2460
- }
2461
2423
  function useNetworkRequests() {
2462
2424
  const { requests$ } = useNoyaClientOrFallback();
2463
2425
  const requests = useSelector(requests$);
2464
2426
  return requests;
2465
2427
  }
2466
- function useGeneratedPageNames() {
2467
- const { generatedPageNames$ } = useNoyaClientOrFallback();
2468
- const names = useSelector(generatedPageNames$);
2469
- const namesWithDefaultsAndTypes = useMemo2(() => {
2470
- const rangeArray = range(0, GENERATED_PAGE_NAME_COUNT);
2471
- const withDefaults = rangeArray.map((index) => {
2472
- const name = names[index];
2473
- return name ?? { name: `Page ${index + 1}`, loading: true, key: "" };
2474
- });
2475
- return withDefaults.map(
2476
- (name, index) => ({
2477
- ...name,
2478
- index,
2479
- type: "suggestion"
2480
- })
2481
- );
2482
- }, [names]);
2483
- return namesWithDefaultsAndTypes.slice(0, 3);
2484
- }
2485
- function useGeneratedPageComponentNames() {
2486
- const { generatedPageComponentNames$: generatedComponentNames$ } = useNoyaClientOrFallback();
2487
- const names = useSelector(
2488
- generatedComponentNames$
2489
- );
2490
- const namesWithDefaultsAndTypes = useMemo2(() => {
2491
- const rangeArray = range(0, GENERATED_PAGE_NAME_COUNT);
2492
- const withDefaults = rangeArray.map((index) => {
2493
- const name = names[index];
2494
- return name ?? { name: `Component ${index + 1}`, loading: true, key: "" };
2495
- });
2496
- return withDefaults.map(
2497
- (name, index) => ({
2498
- ...name,
2499
- index,
2500
- type: "suggestion"
2501
- })
2502
- );
2503
- }, [names]);
2504
- return namesWithDefaultsAndTypes.slice(0, 3);
2505
- }
2506
2428
  function useNoyaSites() {
2507
2429
  const sites = useSelector(useNoyaClientOrFallback().sites$);
2508
2430
  return sites;
@@ -3373,15 +3295,15 @@ function Or(pattern) {
3373
3295
  if (IsCloseParen(pattern, index))
3374
3296
  count -= 1;
3375
3297
  if (IsSeparator(pattern, index) && count === 0) {
3376
- const range3 = pattern.slice(start, index);
3377
- if (range3.length > 0)
3378
- expressions.push(TemplateLiteralParse(range3));
3298
+ const range2 = pattern.slice(start, index);
3299
+ if (range2.length > 0)
3300
+ expressions.push(TemplateLiteralParse(range2));
3379
3301
  start = index + 1;
3380
3302
  }
3381
3303
  }
3382
- const range2 = pattern.slice(start);
3383
- if (range2.length > 0)
3384
- expressions.push(TemplateLiteralParse(range2));
3304
+ const range = pattern.slice(start);
3305
+ if (range.length > 0)
3306
+ expressions.push(TemplateLiteralParse(range));
3385
3307
  if (expressions.length === 0)
3386
3308
  return { type: "const", const: "" };
3387
3309
  if (expressions.length === 1)
@@ -3414,14 +3336,14 @@ function And(pattern) {
3414
3336
  for (let index = 0; index < pattern.length; index++) {
3415
3337
  if (IsOpenParen(pattern, index)) {
3416
3338
  const [start, end] = Group(pattern, index);
3417
- const range2 = pattern.slice(start, end + 1);
3418
- expressions.push(TemplateLiteralParse(range2));
3339
+ const range = pattern.slice(start, end + 1);
3340
+ expressions.push(TemplateLiteralParse(range));
3419
3341
  index = end;
3420
3342
  } else {
3421
3343
  const [start, end] = Range(pattern, index);
3422
- const range2 = pattern.slice(start, end);
3423
- if (range2.length > 0)
3424
- expressions.push(TemplateLiteralParse(range2));
3344
+ const range = pattern.slice(start, end);
3345
+ if (range.length > 0)
3346
+ expressions.push(TemplateLiteralParse(range));
3425
3347
  index = end - 1;
3426
3348
  }
3427
3349
  }
@@ -5255,20 +5177,8 @@ import { isDeepEqual } from "@noya-app/noya-utils";
5255
5177
  import { Observable as Observable2 } from "@noya-app/observable";
5256
5178
 
5257
5179
  // ../state-manager/src/AssetManager.ts
5258
- import { Base64, memoize, uuid } from "@noya-app/noya-utils";
5180
+ import { Base64, uuid } from "@noya-app/noya-utils";
5259
5181
  import { Observable as Observable3 } from "@noya-app/observable";
5260
- var _toNoyaAsset = memoize(
5261
- (asset) => ({
5262
- id: asset.stableId,
5263
- url: asset.url,
5264
- createdAt: asset.createdAt,
5265
- size: asset.size,
5266
- contentType: asset.contentType,
5267
- width: asset.width ?? null,
5268
- height: asset.height ?? null,
5269
- userId: asset.userId ?? null
5270
- })
5271
- );
5272
5182
 
5273
5183
  // ../noya-schemas/src/nullable.ts
5274
5184
  var Nullable = (schema) => Type.Union([Type.Null(), schema]);
@@ -5331,6 +5241,10 @@ var activityEventSchema = Type.Object({
5331
5241
  });
5332
5242
 
5333
5243
  // ../noya-schemas/src/asset.ts
5244
+ var assetModeSchema = Type.Union([
5245
+ Type.Literal("immutable"),
5246
+ Type.Literal("mutable")
5247
+ ]);
5334
5248
  var assetSchema = Type.Object({
5335
5249
  id: Type.String(),
5336
5250
  stableId: Type.String(),
@@ -5340,7 +5254,9 @@ var assetSchema = Type.Object({
5340
5254
  contentType: Type.Optional(Type.String()),
5341
5255
  width: Type.Union([Type.Null(), Type.Number()]),
5342
5256
  height: Type.Union([Type.Null(), Type.Number()]),
5343
- userId: Type.Union([Type.Null(), Type.String()])
5257
+ userId: Type.Union([Type.Null(), Type.String()]),
5258
+ mode: Type.Optional(assetModeSchema),
5259
+ version: Type.Optional(Type.Number())
5344
5260
  });
5345
5261
 
5346
5262
  // ../noya-schemas/src/encode.ts
@@ -7261,6 +7177,13 @@ import { uuid as uuid2 } from "@noya-app/noya-utils";
7261
7177
  import { uuid as uuid3 } from "@noya-app/noya-utils";
7262
7178
  import { Observable as Observable5 } from "@noya-app/observable";
7263
7179
 
7180
+ // ../state-manager/src/multiplayer.ts
7181
+ import { Cache, hash, isDeepEqual as isDeepEqual3, uuid as uuid5 } from "@noya-app/noya-utils";
7182
+ import { Observable as Observable8, get as get2, set as set2 } from "@noya-app/observable";
7183
+
7184
+ // ../state-manager/src/LogManager.ts
7185
+ import { Observable as Observable6 } from "@noya-app/observable";
7186
+
7264
7187
  // ../state-manager/src/historyEntries.ts
7265
7188
  var HistoryEntries;
7266
7189
  ((HistoryEntries2) => {
@@ -7347,119 +7270,6 @@ var HistoryEntries;
7347
7270
  HistoryEntries2.pathsEqual = pathsEqual;
7348
7271
  })(HistoryEntries || (HistoryEntries = {}));
7349
7272
 
7350
- // ../state-manager/src/IOManager.ts
7351
- import { Observable as Observable6 } from "@noya-app/observable";
7352
-
7353
- // ../state-manager/src/jwt.ts
7354
- function base64UrlEncode(str) {
7355
- return btoa(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
7356
- }
7357
- function base64UrlDecode(str) {
7358
- str = str.replace(/-/g, "+").replace(/_/g, "/");
7359
- switch (str.length % 4) {
7360
- case 2:
7361
- str += "==";
7362
- break;
7363
- case 3:
7364
- str += "=";
7365
- break;
7366
- }
7367
- return atob(str);
7368
- }
7369
- var HEADER = {
7370
- alg: "HS256",
7371
- typ: "JWT"
7372
- };
7373
- var JWT_ERROR = {
7374
- INVALID_JWT_FORMAT: "Invalid JWT format"
7375
- // INVALID_SIGNATURE: "Invalid signature",
7376
- };
7377
- async function createJwt({
7378
- payload,
7379
- secret,
7380
- header
7381
- }) {
7382
- const encoder = new TextEncoder();
7383
- const encodedHeader = base64UrlEncode(
7384
- JSON.stringify({ ...HEADER, ...header })
7385
- );
7386
- const encodedPayload = base64UrlEncode(JSON.stringify(payload));
7387
- const dataToSign = `${encodedHeader}.${encodedPayload}`;
7388
- const key = await crypto.subtle.importKey(
7389
- "raw",
7390
- encoder.encode(secret),
7391
- { name: "HMAC", hash: "SHA-256" },
7392
- false,
7393
- ["sign"]
7394
- );
7395
- const signature = await crypto.subtle.sign(
7396
- "HMAC",
7397
- key,
7398
- encoder.encode(dataToSign)
7399
- );
7400
- const encodedSignature = base64UrlEncode(
7401
- String.fromCharCode(...new Uint8Array(signature))
7402
- );
7403
- return `${dataToSign}.${encodedSignature}`;
7404
- }
7405
- async function decodeJwt({
7406
- token,
7407
- secret
7408
- }) {
7409
- if (typeof token !== "string") {
7410
- throw new Error(JWT_ERROR.INVALID_JWT_FORMAT);
7411
- }
7412
- const [encodedHeader, encodedPayload, encodedSignature] = token.split(".");
7413
- if (!encodedHeader || !encodedPayload || !encodedSignature) {
7414
- throw new Error(JWT_ERROR.INVALID_JWT_FORMAT);
7415
- }
7416
- const headerJson = base64UrlDecode(encodedHeader);
7417
- const payloadJson = base64UrlDecode(encodedPayload);
7418
- const header = JSON.parse(headerJson);
7419
- const payload = JSON.parse(payloadJson);
7420
- const dataToVerify = `${encodedHeader}.${encodedPayload}`;
7421
- const encoder = new TextEncoder();
7422
- if (secret !== void 0) {
7423
- const key = await crypto.subtle.importKey(
7424
- "raw",
7425
- encoder.encode(secret),
7426
- { name: "HMAC", hash: "SHA-256" },
7427
- false,
7428
- ["verify"]
7429
- );
7430
- const binarySignature = base64UrlDecode(encodedSignature);
7431
- const signature = new Uint8Array(
7432
- [...binarySignature].map((char) => char.charCodeAt(0))
7433
- );
7434
- const valid = await crypto.subtle.verify(
7435
- "HMAC",
7436
- key,
7437
- signature,
7438
- encoder.encode(dataToVerify)
7439
- );
7440
- return { header, payload, valid };
7441
- }
7442
- return { header, payload, valid: false };
7443
- }
7444
- var jwt;
7445
- ((jwt2) => {
7446
- jwt2.encode = createJwt;
7447
- jwt2.decode = decodeJwt;
7448
- jwt2.ERROR = JWT_ERROR;
7449
- jwt2.DEFAULT_HEADER = HEADER;
7450
- })(jwt || (jwt = {}));
7451
-
7452
- // ../state-manager/src/LogManager.ts
7453
- import { Observable as Observable7 } from "@noya-app/observable";
7454
-
7455
- // ../state-manager/src/MenuManager.ts
7456
- import { isDeepEqual as isDeepEqual2 } from "@noya-app/noya-utils";
7457
- import { Observable as Observable8 } from "@noya-app/observable";
7458
-
7459
- // ../state-manager/src/multiplayer.ts
7460
- import { Cache, hash, isDeepEqual as isDeepEqual3, uuid as uuid5 } from "@noya-app/noya-utils";
7461
- import { Observable as Observable10, get as get2, set as set2 } from "@noya-app/observable";
7462
-
7463
7273
  // ../../node_modules/@marcbachmann/cel-js/lib/errors.js
7464
7274
  var ParseError = class extends Error {
7465
7275
  #wasConstructedWithAst = false;
@@ -10474,18 +10284,130 @@ celEnvironment.registerFunction("random(): double", () => Math.random()).registe
10474
10284
  ).registerFunction("uuid(): string", () => uuid4());
10475
10285
  var READ_DENIED = Symbol("readDenied");
10476
10286
 
10287
+ // ../state-manager/src/serverScripts.ts
10288
+ import { uuid as createUuid, isDeepEqual as isDeepEqual2 } from "@noya-app/noya-utils";
10289
+
10477
10290
  // ../state-manager/src/stateManager.ts
10478
10291
  import {
10479
- Observable as Observable9,
10292
+ Observable as Observable7,
10480
10293
  get as getPath2
10481
10294
  } from "@noya-app/observable";
10482
10295
 
10483
10296
  // ../state-manager/src/multiplayer.ts
10484
10297
  var createHash = (value, options) => hash(value, { ...options, ignoreUndefinedProperties: true });
10485
10298
 
10299
+ // ../state-manager/src/GitManager.ts
10300
+ import { Observable as Observable9 } from "@noya-app/observable";
10301
+
10302
+ // ../state-manager/src/IOManager.ts
10303
+ import { Observable as Observable10 } from "@noya-app/observable";
10304
+
10305
+ // ../state-manager/src/jwt.ts
10306
+ function base64UrlEncode(str) {
10307
+ return btoa(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
10308
+ }
10309
+ function base64UrlDecode(str) {
10310
+ str = str.replace(/-/g, "+").replace(/_/g, "/");
10311
+ switch (str.length % 4) {
10312
+ case 2:
10313
+ str += "==";
10314
+ break;
10315
+ case 3:
10316
+ str += "=";
10317
+ break;
10318
+ }
10319
+ return atob(str);
10320
+ }
10321
+ var HEADER = {
10322
+ alg: "HS256",
10323
+ typ: "JWT"
10324
+ };
10325
+ var JWT_ERROR = {
10326
+ INVALID_JWT_FORMAT: "Invalid JWT format"
10327
+ // INVALID_SIGNATURE: "Invalid signature",
10328
+ };
10329
+ async function createJwt({
10330
+ payload,
10331
+ secret,
10332
+ header
10333
+ }) {
10334
+ const encoder = new TextEncoder();
10335
+ const encodedHeader = base64UrlEncode(
10336
+ JSON.stringify({ ...HEADER, ...header })
10337
+ );
10338
+ const encodedPayload = base64UrlEncode(JSON.stringify(payload));
10339
+ const dataToSign = `${encodedHeader}.${encodedPayload}`;
10340
+ const key = await crypto.subtle.importKey(
10341
+ "raw",
10342
+ encoder.encode(secret),
10343
+ { name: "HMAC", hash: "SHA-256" },
10344
+ false,
10345
+ ["sign"]
10346
+ );
10347
+ const signature = await crypto.subtle.sign(
10348
+ "HMAC",
10349
+ key,
10350
+ encoder.encode(dataToSign)
10351
+ );
10352
+ const encodedSignature = base64UrlEncode(
10353
+ String.fromCharCode(...new Uint8Array(signature))
10354
+ );
10355
+ return `${dataToSign}.${encodedSignature}`;
10356
+ }
10357
+ async function decodeJwt({
10358
+ token,
10359
+ secret
10360
+ }) {
10361
+ if (typeof token !== "string") {
10362
+ throw new Error(JWT_ERROR.INVALID_JWT_FORMAT);
10363
+ }
10364
+ const [encodedHeader, encodedPayload, encodedSignature] = token.split(".");
10365
+ if (!encodedHeader || !encodedPayload || !encodedSignature) {
10366
+ throw new Error(JWT_ERROR.INVALID_JWT_FORMAT);
10367
+ }
10368
+ const headerJson = base64UrlDecode(encodedHeader);
10369
+ const payloadJson = base64UrlDecode(encodedPayload);
10370
+ const header = JSON.parse(headerJson);
10371
+ const payload = JSON.parse(payloadJson);
10372
+ const dataToVerify = `${encodedHeader}.${encodedPayload}`;
10373
+ const encoder = new TextEncoder();
10374
+ if (secret !== void 0) {
10375
+ const key = await crypto.subtle.importKey(
10376
+ "raw",
10377
+ encoder.encode(secret),
10378
+ { name: "HMAC", hash: "SHA-256" },
10379
+ false,
10380
+ ["verify"]
10381
+ );
10382
+ const binarySignature = base64UrlDecode(encodedSignature);
10383
+ const signature = new Uint8Array(
10384
+ [...binarySignature].map((char) => char.charCodeAt(0))
10385
+ );
10386
+ const valid = await crypto.subtle.verify(
10387
+ "HMAC",
10388
+ key,
10389
+ signature,
10390
+ encoder.encode(dataToVerify)
10391
+ );
10392
+ return { header, payload, valid };
10393
+ }
10394
+ return { header, payload, valid: false };
10395
+ }
10396
+ var jwt;
10397
+ ((jwt2) => {
10398
+ jwt2.encode = createJwt;
10399
+ jwt2.decode = decodeJwt;
10400
+ jwt2.ERROR = JWT_ERROR;
10401
+ jwt2.DEFAULT_HEADER = HEADER;
10402
+ })(jwt || (jwt = {}));
10403
+
10404
+ // ../state-manager/src/MenuManager.ts
10405
+ import { isDeepEqual as isDeepEqual4 } from "@noya-app/noya-utils";
10406
+ import { Observable as Observable11 } from "@noya-app/observable";
10407
+
10486
10408
  // ../state-manager/src/NoyaManager.ts
10487
10409
  import { uuid as uuid12 } from "@noya-app/noya-utils";
10488
- import { Observable as Observable20, set as set3 } from "@noya-app/observable";
10410
+ import { Observable as Observable22, set as set3 } from "@noya-app/observable";
10489
10411
 
10490
10412
  // ../noya-pipeline/src/graphToTasks.ts
10491
10413
  import { get as get3 } from "@noya-app/observable";
@@ -10590,35 +10512,38 @@ var pipelineSchema = Type.Object(
10590
10512
  );
10591
10513
 
10592
10514
  // ../state-manager/src/PipelineManager.ts
10593
- import { Observable as Observable11 } from "@noya-app/observable";
10515
+ import { Observable as Observable12 } from "@noya-app/observable";
10594
10516
 
10595
10517
  // ../state-manager/src/PublishingManager.ts
10596
- import { Observable as Observable12 } from "@noya-app/observable";
10518
+ import { Observable as Observable13 } from "@noya-app/observable";
10597
10519
 
10598
10520
  // ../state-manager/src/ResourceManager.ts
10599
- import { isDeepEqual as isDeepEqual4, uuid as uuid7 } from "@noya-app/noya-utils";
10600
- import { Observable as Observable13 } from "@noya-app/observable";
10521
+ import { isDeepEqual as isDeepEqual5, uuid as uuid7 } from "@noya-app/noya-utils";
10522
+ import { Observable as Observable14 } from "@noya-app/observable";
10523
+
10524
+ // ../state-manager/src/SandboxManager.ts
10525
+ import { Observable as Observable15 } from "@noya-app/observable";
10601
10526
 
10602
10527
  // ../state-manager/src/rpcManager.ts
10603
10528
  import { uuid as uuid8 } from "@noya-app/noya-utils";
10604
- import { Observable as Observable14 } from "@noya-app/observable";
10529
+ import { Observable as Observable16 } from "@noya-app/observable";
10605
10530
 
10606
10531
  // ../state-manager/src/SecretManager.ts
10607
- import { Observable as Observable15 } from "@noya-app/observable";
10532
+ import { Observable as Observable17 } from "@noya-app/observable";
10608
10533
 
10609
10534
  // ../state-manager/src/TaskManager.ts
10610
- import { Observable as Observable16 } from "@noya-app/observable";
10535
+ import { Observable as Observable18 } from "@noya-app/observable";
10611
10536
 
10612
10537
  // ../state-manager/src/TranscriptionManager.ts
10613
10538
  import { Base64 as Base642 } from "@noya-app/noya-utils";
10614
- import { Observable as Observable17 } from "@noya-app/observable";
10539
+ import { Observable as Observable19 } from "@noya-app/observable";
10615
10540
 
10616
10541
  // ../state-manager/src/UserManager.ts
10617
- import { Observable as Observable19 } from "@noya-app/observable";
10542
+ import { Observable as Observable21 } from "@noya-app/observable";
10618
10543
 
10619
10544
  // ../state-manager/src/sync/clientId.ts
10620
10545
  import { uuid as uuid9 } from "@noya-app/noya-utils";
10621
- import { Observable as Observable18 } from "@noya-app/observable";
10546
+ import { Observable as Observable20 } from "@noya-app/observable";
10622
10547
 
10623
10548
  // ../state-manager/src/sync/defaultNames.ts
10624
10549
  import { upperFirst } from "@noya-app/noya-utils";
@@ -10691,9 +10616,9 @@ function getClientAnimalFromName(name) {
10691
10616
  var CLIENT_ID_STORAGE_KEY = "noya-client-id";
10692
10617
  var CLIENT_NAME_STORAGE_KEY = "noya-client-name";
10693
10618
  var CLIENT_IMAGE_STORAGE_KEY = "noya-client-image";
10694
- var clientId$ = new Observable18(void 0);
10695
- var clientName$ = new Observable18(void 0);
10696
- var clientImage$ = new Observable18(void 0);
10619
+ var clientId$ = new Observable20(void 0);
10620
+ var clientName$ = new Observable20(void 0);
10621
+ var clientImage$ = new Observable20(void 0);
10697
10622
  var safeGetItem = (key) => {
10698
10623
  try {
10699
10624
  return typeof localStorage !== "undefined" ? localStorage.getItem(key) : null;
@@ -10745,9 +10670,6 @@ import { Base64 as Base643 } from "@noya-app/noya-utils";
10745
10670
  // ../state-manager/src/sync/localStorageSync.ts
10746
10671
  import { uuid as uuid11 } from "@noya-app/noya-utils";
10747
10672
 
10748
- // ../state-manager/src/serverScripts.ts
10749
- import { uuid as createUuid, isDeepEqual as isDeepEqual5 } from "@noya-app/noya-utils";
10750
-
10751
10673
  // ../noya-keymap/src/hooks.ts
10752
10674
  import { useEffect as useEffect2, useRef as useRef2 } from "react";
10753
10675
 
@@ -10869,11 +10791,11 @@ var createMutatorParametersSchema = Type.Object({
10869
10791
  });
10870
10792
 
10871
10793
  // ../noya-multiplayer-react/src/ai.ts
10872
- import { useEffect as useEffect17 } from "react";
10794
+ import { useEffect as useEffect18 } from "react";
10873
10795
 
10874
10796
  // ../noya-multiplayer-react/src/NoyaStateContext.tsx
10875
10797
  import {
10876
- Observable as Observable21
10798
+ Observable as Observable23
10877
10799
  } from "@noya-app/observable";
10878
10800
 
10879
10801
  // ../noya-react-utils/src/components/AutoSizer.tsx
@@ -11180,26 +11102,26 @@ function downloadBlob(...params) {
11180
11102
  }
11181
11103
 
11182
11104
  // ../noya-multiplayer-react/src/NoyaStateContext.tsx
11183
- import React35, {
11105
+ import React37, {
11184
11106
  createContext as createContext3,
11185
11107
  useCallback as useCallback14,
11186
11108
  useContext as useContext4,
11187
- useEffect as useEffect16,
11109
+ useEffect as useEffect17,
11188
11110
  useMemo as useMemo11,
11189
- useState as useState17
11111
+ useState as useState18
11190
11112
  } from "react";
11191
11113
 
11192
11114
  // ../noya-multiplayer-react/src/noyaApp.ts
11193
- import { useEffect as useEffect15, useMemo as useMemo10, useState as useState16 } from "react";
11115
+ import { useEffect as useEffect16, useMemo as useMemo10, useState as useState17 } from "react";
11194
11116
 
11195
11117
  // ../noya-multiplayer-react/src/hooks.ts
11196
11118
  import {
11197
11119
  createElement as createElement3,
11198
11120
  useCallback as useCallback13,
11199
- useEffect as useEffect14,
11121
+ useEffect as useEffect15,
11200
11122
  useMemo as useMemo9,
11201
- useRef as useRef11,
11202
- useState as useState15,
11123
+ useRef as useRef12,
11124
+ useState as useState16,
11203
11125
  useSyncExternalStore as useSyncExternalStore2
11204
11126
  } from "react";
11205
11127
  import { createRoot as createRoot2 } from "react-dom/client";
@@ -11279,14 +11201,14 @@ var ErrorOverlay = React6.memo(function ErrorOverlay2({
11279
11201
  });
11280
11202
 
11281
11203
  // ../noya-multiplayer-react/src/inspector/useStateInspector.tsx
11282
- import React33 from "react";
11204
+ import React35 from "react";
11283
11205
  import { createRoot } from "react-dom/client";
11284
11206
 
11285
11207
  // ../noya-multiplayer-react/src/inspector/StateInspector.tsx
11286
- import { Base64 as Base644, memoize as memoize2, uuid as uuid13 } from "@noya-app/noya-utils";
11287
- import React31, {
11208
+ import { Base64 as Base644, memoize, uuid as uuid13 } from "@noya-app/noya-utils";
11209
+ import React34, {
11288
11210
  useCallback as useCallback12,
11289
- useEffect as useEffect13,
11211
+ useEffect as useEffect14,
11290
11212
  useLayoutEffect as useLayoutEffect4
11291
11213
  } from "react";
11292
11214
 
@@ -12867,7 +12789,9 @@ function EventsSection({
12867
12789
  setShowEvents,
12868
12790
  colorScheme,
12869
12791
  eventsContainerRef,
12870
- connectionEvents
12792
+ connectionEvents,
12793
+ paused,
12794
+ onTogglePaused
12871
12795
  }) {
12872
12796
  const theme3 = getStateInspectorTheme(colorScheme);
12873
12797
  return /* @__PURE__ */ React25.createElement(
@@ -12876,9 +12800,20 @@ function EventsSection({
12876
12800
  open: showEvents,
12877
12801
  setOpen: setShowEvents,
12878
12802
  title: "Events",
12879
- colorScheme
12803
+ colorScheme,
12804
+ right: /* @__PURE__ */ React25.createElement(StateInspectorButton, { theme: theme3, onClick: onTogglePaused }, paused ? "Resume" : "Pause")
12880
12805
  },
12881
- /* @__PURE__ */ React25.createElement(StateInspectorDisclosureRowInner, { ref: eventsContainerRef }, connectionEvents?.map(
12806
+ /* @__PURE__ */ React25.createElement(StateInspectorDisclosureRowInner, { ref: eventsContainerRef }, paused && /* @__PURE__ */ React25.createElement(
12807
+ "div",
12808
+ {
12809
+ style: {
12810
+ padding: "4px 12px",
12811
+ fontSize: "11px",
12812
+ opacity: 0.7
12813
+ }
12814
+ },
12815
+ "Event streaming paused"
12816
+ ), connectionEvents?.map(
12882
12817
  (event, index) => event.type === "stateChange" ? /* @__PURE__ */ React25.createElement(StateInspectorRow, { key: index, colorScheme }, "connection:", " ", /* @__PURE__ */ React25.createElement("span", { style: { fontStyle: "italic" } }, event.state.toLowerCase())) : /* @__PURE__ */ React25.createElement(
12883
12818
  StateInspectorRow,
12884
12819
  {
@@ -12909,7 +12844,7 @@ function EventsSection({
12909
12844
  }
12910
12845
  )
12911
12846
  )
12912
- ), !connectionEvents && /* @__PURE__ */ React25.createElement(
12847
+ ), !connectionEvents?.length && /* @__PURE__ */ React25.createElement(
12913
12848
  "div",
12914
12849
  {
12915
12850
  style: {
@@ -12925,8 +12860,424 @@ function EventsSection({
12925
12860
  );
12926
12861
  }
12927
12862
 
12863
+ // ../noya-multiplayer-react/src/inspector/sections/GitSection.tsx
12864
+ import React27, { useEffect as useEffect12, useRef as useRef10, useState as useState15 } from "react";
12865
+
12866
+ // ../noya-multiplayer-react/src/inspector/StateInspectorTitleLabel.tsx
12867
+ import React26 from "react";
12868
+ function StateInspectorTitleLabel({
12869
+ children
12870
+ }) {
12871
+ return /* @__PURE__ */ React26.createElement("span", { style: { display: "flex", alignItems: "center", gap: "4px" } }, children);
12872
+ }
12873
+
12874
+ // ../noya-multiplayer-react/src/inspector/sections/GitSection.tsx
12875
+ function GitSection({
12876
+ showGit,
12877
+ setShowGit,
12878
+ colorScheme,
12879
+ gitManager
12880
+ }) {
12881
+ const theme3 = getStateInspectorTheme(colorScheme);
12882
+ const repos = useObservable2(gitManager.repos$);
12883
+ const isInitialized = useObservable2(gitManager.isInitialized$);
12884
+ const repoFiles = useObservable2(gitManager.repoFiles$);
12885
+ const [focusedRepoId, setFocusedRepoId] = useState15(null);
12886
+ const [editingFile, setEditingFile] = useState15(null);
12887
+ const editHandleRef = useRef10(null);
12888
+ const [editContent, setEditContent] = useState15("");
12889
+ const [isEditInitialized, setIsEditInitialized] = useState15(false);
12890
+ const focusedRepo = focusedRepoId ? repos.find((r) => r.id === focusedRepoId) : null;
12891
+ const focusedRepoFilesState = focusedRepoId ? repoFiles[focusedRepoId] : null;
12892
+ const handleFocusRepo = async (repoId) => {
12893
+ if (editHandleRef.current) {
12894
+ editHandleRef.current.close();
12895
+ editHandleRef.current = null;
12896
+ setEditingFile(null);
12897
+ setEditContent("");
12898
+ setIsEditInitialized(false);
12899
+ }
12900
+ setFocusedRepoId(repoId);
12901
+ if (repoId && !repoFiles[repoId]) {
12902
+ await gitManager.fetchRepoFiles(repoId);
12903
+ }
12904
+ };
12905
+ const handleEditFile = (filePath) => {
12906
+ if (!focusedRepoId || !focusedRepoFilesState) return;
12907
+ if (editHandleRef.current) {
12908
+ editHandleRef.current.close();
12909
+ }
12910
+ const handle = gitManager.openEditingHandle(
12911
+ focusedRepoId,
12912
+ filePath,
12913
+ focusedRepoFilesState.ref
12914
+ );
12915
+ editHandleRef.current = handle;
12916
+ setEditingFile(filePath);
12917
+ setIsEditInitialized(false);
12918
+ setEditContent("");
12919
+ };
12920
+ const handleCloseEdit = () => {
12921
+ if (editHandleRef.current) {
12922
+ editHandleRef.current.close();
12923
+ editHandleRef.current = null;
12924
+ }
12925
+ setEditingFile(null);
12926
+ setEditContent("");
12927
+ setIsEditInitialized(false);
12928
+ };
12929
+ useEffect12(() => {
12930
+ const handle = editHandleRef.current;
12931
+ if (!handle) return;
12932
+ const unsubContent = handle.content$.subscribe((content) => {
12933
+ setEditContent(content);
12934
+ });
12935
+ const unsubInitialized = handle.isInitialized$.subscribe((initialized) => {
12936
+ setIsEditInitialized(initialized);
12937
+ });
12938
+ return () => {
12939
+ unsubContent();
12940
+ unsubInitialized();
12941
+ };
12942
+ }, [editingFile]);
12943
+ const handleContentChange = (newContent) => {
12944
+ const handle = editHandleRef.current;
12945
+ if (!handle) return;
12946
+ handle.setState(newContent);
12947
+ };
12948
+ const handleBranchChange = async (ref) => {
12949
+ if (focusedRepoId) {
12950
+ await gitManager.fetchRepoFiles(focusedRepoId, ref);
12951
+ }
12952
+ };
12953
+ const handleAddFile = async () => {
12954
+ if (!focusedRepoId || !focusedRepoFilesState) return;
12955
+ const path2 = prompt("Enter file path (e.g., src/index.ts):");
12956
+ if (!path2) return;
12957
+ try {
12958
+ await gitManager.patchFiles(
12959
+ focusedRepoId,
12960
+ { create: [{ path: path2, content: "" }] },
12961
+ focusedRepoFilesState.ref
12962
+ );
12963
+ } catch (error) {
12964
+ alert(`Failed to create file: ${error}`);
12965
+ }
12966
+ };
12967
+ const handleRenameFile = async (oldPath) => {
12968
+ if (!focusedRepoId || !focusedRepoFilesState) return;
12969
+ const newPath = prompt(`Rename "${oldPath}" to:`, oldPath);
12970
+ if (!newPath || newPath === oldPath) return;
12971
+ try {
12972
+ await gitManager.patchFiles(
12973
+ focusedRepoId,
12974
+ { rename: [{ oldPath, newPath }] },
12975
+ focusedRepoFilesState.ref
12976
+ );
12977
+ } catch (error) {
12978
+ alert(`Failed to rename file: ${error}`);
12979
+ }
12980
+ };
12981
+ const handleDeleteFile = async (path2) => {
12982
+ if (!focusedRepoId || !focusedRepoFilesState) return;
12983
+ const confirmed = confirm(`Delete "${path2}"?`);
12984
+ if (!confirmed) return;
12985
+ try {
12986
+ await gitManager.patchFiles(
12987
+ focusedRepoId,
12988
+ { delete: [{ path: path2 }] },
12989
+ focusedRepoFilesState.ref
12990
+ );
12991
+ if (editingFile === path2) {
12992
+ handleCloseEdit();
12993
+ }
12994
+ } catch (error) {
12995
+ alert(`Failed to delete file: ${error}`);
12996
+ }
12997
+ };
12998
+ return /* @__PURE__ */ React27.createElement(
12999
+ StateInspectorDisclosureSection,
13000
+ {
13001
+ open: showGit,
13002
+ setOpen: setShowGit,
13003
+ title: /* @__PURE__ */ React27.createElement(StateInspectorTitleLabel, null, "Git Repos (", repos.length, ")", /* @__PURE__ */ React27.createElement(ColoredDot, { type: isInitialized ? "success" : "error" })),
13004
+ colorScheme,
13005
+ right: /* @__PURE__ */ React27.createElement("span", { style: { display: "flex", gap: "10px" } }, /* @__PURE__ */ React27.createElement(
13006
+ StateInspectorButton,
13007
+ {
13008
+ theme: theme3,
13009
+ onClick: async () => {
13010
+ try {
13011
+ await gitManager.initRepo();
13012
+ } catch (error) {
13013
+ console.error("[GitSection] Failed to create repo:", error);
13014
+ }
13015
+ }
13016
+ },
13017
+ "Init Repo"
13018
+ ))
13019
+ },
13020
+ /* @__PURE__ */ React27.createElement(StateInspectorDisclosureRowInner, null, /* @__PURE__ */ React27.createElement("div", { style: { padding: "4px 12px", display: "flex", gap: "4px" } }, /* @__PURE__ */ React27.createElement(
13021
+ "select",
13022
+ {
13023
+ name: "repoSelector",
13024
+ value: focusedRepoId ?? "",
13025
+ style: { flex: "1 1 auto", height: "19px", minWidth: 0 },
13026
+ onChange: (e) => {
13027
+ const value = e.target.value;
13028
+ handleFocusRepo(value || null);
13029
+ }
13030
+ },
13031
+ /* @__PURE__ */ React27.createElement("option", { value: "" }, "Select a repo..."),
13032
+ repos.map((repo) => /* @__PURE__ */ React27.createElement("option", { key: repo.id, value: repo.id }, repo.id))
13033
+ ), focusedRepoId && /* @__PURE__ */ React27.createElement(
13034
+ StateInspectorButton,
13035
+ {
13036
+ theme: theme3,
13037
+ onClick: () => gitManager.fetchRepoFiles(focusedRepoId)
13038
+ },
13039
+ "Refresh"
13040
+ ), /* @__PURE__ */ React27.createElement(
13041
+ "label",
13042
+ {
13043
+ style: {
13044
+ display: "flex",
13045
+ alignItems: "center",
13046
+ gap: "4px",
13047
+ fontSize: "11px",
13048
+ whiteSpace: "nowrap"
13049
+ }
13050
+ },
13051
+ "[Include Content = ",
13052
+ gitManager.includeContent ? "true" : "false",
13053
+ "]"
13054
+ )), focusedRepo && focusedRepoFilesState && /* @__PURE__ */ React27.createElement(React27.Fragment, null, /* @__PURE__ */ React27.createElement(
13055
+ "div",
13056
+ {
13057
+ style: {
13058
+ padding: "4px 12px",
13059
+ display: "flex",
13060
+ gap: "8px",
13061
+ alignItems: "center",
13062
+ fontSize: "12px"
13063
+ }
13064
+ },
13065
+ /* @__PURE__ */ React27.createElement("span", { style: { color: theme3.BASE_COLOR } }, "Branch:"),
13066
+ focusedRepoFilesState.branches.length > 0 ? /* @__PURE__ */ React27.createElement(
13067
+ "select",
13068
+ {
13069
+ value: focusedRepoFilesState.ref,
13070
+ style: { flex: "1 1 auto", height: "19px" },
13071
+ onChange: (e) => handleBranchChange(e.target.value)
13072
+ },
13073
+ focusedRepoFilesState.branches.map((branch) => /* @__PURE__ */ React27.createElement("option", { key: branch.name, value: branch.name }, branch.name))
13074
+ ) : /* @__PURE__ */ React27.createElement("span", { style: { opacity: 0.6, fontStyle: "italic" } }, focusedRepoFilesState.ref || "No branches"),
13075
+ focusedRepoFilesState.oid && /* @__PURE__ */ React27.createElement(
13076
+ "span",
13077
+ {
13078
+ style: {
13079
+ fontFamily: "monospace",
13080
+ fontSize: "10px",
13081
+ opacity: 0.6
13082
+ },
13083
+ title: focusedRepoFilesState.oid
13084
+ },
13085
+ focusedRepoFilesState.oid.slice(0, 7),
13086
+ focusedRepoFilesState.fetchState === "refreshing" && "\u2026"
13087
+ ),
13088
+ /* @__PURE__ */ React27.createElement(
13089
+ StateInspectorButton,
13090
+ {
13091
+ theme: theme3,
13092
+ onClick: handleAddFile,
13093
+ style: { fontSize: "10px", padding: "2px 6px" }
13094
+ },
13095
+ "+ Add File"
13096
+ )
13097
+ ), focusedRepoFilesState.fetchState === "loading" && /* @__PURE__ */ React27.createElement(
13098
+ "div",
13099
+ {
13100
+ style: {
13101
+ padding: "12px",
13102
+ fontSize: "12px"
13103
+ }
13104
+ },
13105
+ "Loading files..."
13106
+ ), focusedRepoFilesState.error && /* @__PURE__ */ React27.createElement(
13107
+ "div",
13108
+ {
13109
+ style: {
13110
+ padding: "12px",
13111
+ fontSize: "12px",
13112
+ color: "#f44"
13113
+ }
13114
+ },
13115
+ "Error: ",
13116
+ focusedRepoFilesState.error
13117
+ ), focusedRepoFilesState.fetchState !== "loading" && !focusedRepoFilesState.error && focusedRepoFilesState.files.length === 0 && /* @__PURE__ */ React27.createElement(
13118
+ "div",
13119
+ {
13120
+ style: {
13121
+ padding: "12px",
13122
+ fontSize: "12px"
13123
+ }
13124
+ },
13125
+ "No files (empty repo)"
13126
+ ), !editingFile && focusedRepoFilesState.files.map((file, index) => {
13127
+ const fileInfo = focusedRepoFilesState.fileContents?.find(
13128
+ (f) => f.path === file
13129
+ );
13130
+ let preview = "";
13131
+ if (fileInfo) {
13132
+ try {
13133
+ const decoded = atob(fileInfo.content);
13134
+ preview = decoded.slice(0, 40).replace(/\n/g, " ").replace(/\s+/g, " ");
13135
+ if (decoded.length > 40) preview += "\u2026";
13136
+ } catch {
13137
+ }
13138
+ }
13139
+ return /* @__PURE__ */ React27.createElement(
13140
+ "div",
13141
+ {
13142
+ key: index,
13143
+ style: {
13144
+ padding: "2px 12px",
13145
+ display: "flex",
13146
+ justifyContent: "space-between",
13147
+ alignItems: "center",
13148
+ gap: "8px",
13149
+ borderBottom: `1px solid ${colorScheme === "light" ? "rgb(223 223 223)" : "rgb(29 29 29)"}`
13150
+ }
13151
+ },
13152
+ /* @__PURE__ */ React27.createElement(
13153
+ "span",
13154
+ {
13155
+ style: {
13156
+ fontFamily: "monospace",
13157
+ fontSize: "11px",
13158
+ overflow: "hidden",
13159
+ textOverflow: "ellipsis",
13160
+ whiteSpace: "nowrap",
13161
+ minWidth: 0,
13162
+ display: "flex",
13163
+ gap: "8px"
13164
+ },
13165
+ title: file
13166
+ },
13167
+ /* @__PURE__ */ React27.createElement("span", null, file),
13168
+ preview && /* @__PURE__ */ React27.createElement("span", { style: { opacity: 0.5 } }, preview)
13169
+ ),
13170
+ /* @__PURE__ */ React27.createElement("span", { style: { display: "flex", gap: "4px", flexShrink: 0 } }, /* @__PURE__ */ React27.createElement(
13171
+ StateInspectorButton,
13172
+ {
13173
+ theme: theme3,
13174
+ onClick: () => handleEditFile(file),
13175
+ style: { fontSize: "10px", padding: "2px 6px" }
13176
+ },
13177
+ "Edit"
13178
+ ), /* @__PURE__ */ React27.createElement(
13179
+ StateInspectorButton,
13180
+ {
13181
+ theme: theme3,
13182
+ onClick: () => handleRenameFile(file),
13183
+ style: { fontSize: "10px", padding: "2px 6px" }
13184
+ },
13185
+ "Rename"
13186
+ ), /* @__PURE__ */ React27.createElement(
13187
+ StateInspectorButton,
13188
+ {
13189
+ theme: theme3,
13190
+ onClick: () => handleDeleteFile(file),
13191
+ style: { fontSize: "10px", padding: "2px 6px" }
13192
+ },
13193
+ "Delete"
13194
+ ))
13195
+ );
13196
+ }), editingFile && /* @__PURE__ */ React27.createElement(
13197
+ "div",
13198
+ {
13199
+ style: {
13200
+ padding: "8px 12px",
13201
+ borderTop: `1px solid ${theme3.DIVIDER_COLOR}`,
13202
+ flex: "1 1 auto",
13203
+ display: "flex",
13204
+ flexDirection: "column",
13205
+ minHeight: 0
13206
+ }
13207
+ },
13208
+ /* @__PURE__ */ React27.createElement(
13209
+ "div",
13210
+ {
13211
+ style: {
13212
+ display: "flex",
13213
+ justifyContent: "space-between",
13214
+ alignItems: "center",
13215
+ marginBottom: "8px",
13216
+ flexShrink: 0
13217
+ }
13218
+ },
13219
+ /* @__PURE__ */ React27.createElement(
13220
+ "span",
13221
+ {
13222
+ style: {
13223
+ fontFamily: "monospace",
13224
+ fontSize: "11px",
13225
+ fontWeight: "bold"
13226
+ }
13227
+ },
13228
+ editingFile,
13229
+ !isEditInitialized && /* @__PURE__ */ React27.createElement("span", { style: { opacity: 0.5, marginLeft: "8px" } }, "Loading...")
13230
+ ),
13231
+ /* @__PURE__ */ React27.createElement(
13232
+ StateInspectorButton,
13233
+ {
13234
+ theme: theme3,
13235
+ onClick: handleCloseEdit,
13236
+ style: { fontSize: "10px", padding: "2px 6px" }
13237
+ },
13238
+ "Close"
13239
+ )
13240
+ ),
13241
+ /* @__PURE__ */ React27.createElement(
13242
+ "textarea",
13243
+ {
13244
+ value: editContent,
13245
+ onChange: (e) => handleContentChange(e.target.value),
13246
+ disabled: !isEditInitialized,
13247
+ style: {
13248
+ width: "100%",
13249
+ flex: "1 1 auto",
13250
+ minHeight: "100px",
13251
+ fontFamily: "monospace",
13252
+ fontSize: "11px",
13253
+ padding: "8px",
13254
+ border: `1px solid ${theme3.DIVIDER_COLOR}`,
13255
+ borderRadius: "4px",
13256
+ backgroundColor: theme3.ROW_BACKGROUND,
13257
+ color: theme3.BASE_COLOR,
13258
+ resize: "none",
13259
+ boxSizing: "border-box"
13260
+ }
13261
+ }
13262
+ )
13263
+ )), repos.length === 0 && /* @__PURE__ */ React27.createElement(
13264
+ "div",
13265
+ {
13266
+ style: {
13267
+ padding: "12px",
13268
+ fontSize: "12px",
13269
+ display: "flex",
13270
+ flexDirection: "column",
13271
+ gap: "4px"
13272
+ }
13273
+ },
13274
+ /* @__PURE__ */ React27.createElement("span", null, "No git repos")
13275
+ ))
13276
+ );
13277
+ }
13278
+
12928
13279
  // ../noya-multiplayer-react/src/inspector/sections/HistorySection.tsx
12929
- import React26, { useEffect as useEffect12, useRef as useRef10 } from "react";
13280
+ import React28, { useEffect as useEffect13, useRef as useRef11 } from "react";
12930
13281
 
12931
13282
  // ../noya-multiplayer-react/src/inspector/utils.ts
12932
13283
  function pathToString(extendedPath) {
@@ -12981,15 +13332,15 @@ function HistorySection({
12981
13332
  historySnapshot,
12982
13333
  multiplayerStateManager
12983
13334
  }) {
12984
- const ref = useRef10(null);
13335
+ const ref = useRef11(null);
12985
13336
  const theme3 = getStateInspectorTheme(colorScheme);
12986
13337
  const solidBorderColor = getStateInspectorBorderColor(colorScheme);
12987
- useEffect12(() => {
13338
+ useEffect13(() => {
12988
13339
  if (ref.current) {
12989
13340
  ref.current.scrollTop = ref.current.scrollHeight;
12990
13341
  }
12991
13342
  }, [historySnapshot]);
12992
- useEffect12(() => {
13343
+ useEffect13(() => {
12993
13344
  if (!ref.current) return;
12994
13345
  const historyEntry = ref.current.querySelector(
12995
13346
  `#${HISTORY_ELEMENT_PREFIX}${historySnapshot.historyIndex}`
@@ -13001,14 +13352,14 @@ function HistorySection({
13001
13352
  });
13002
13353
  }
13003
13354
  }, [historySnapshot.historyIndex]);
13004
- return /* @__PURE__ */ React26.createElement(
13355
+ return /* @__PURE__ */ React28.createElement(
13005
13356
  StateInspectorDisclosureSection,
13006
13357
  {
13007
13358
  open: showHistory,
13008
13359
  setOpen: setShowHistory,
13009
13360
  title: "History",
13010
13361
  colorScheme,
13011
- right: /* @__PURE__ */ React26.createElement(
13362
+ right: /* @__PURE__ */ React28.createElement(
13012
13363
  "span",
13013
13364
  {
13014
13365
  style: {
@@ -13016,7 +13367,7 @@ function HistorySection({
13016
13367
  gap: "4px"
13017
13368
  }
13018
13369
  },
13019
- /* @__PURE__ */ React26.createElement(
13370
+ /* @__PURE__ */ React28.createElement(
13020
13371
  StateInspectorButton,
13021
13372
  {
13022
13373
  disabled: !historySnapshot.canUndo,
@@ -13025,7 +13376,7 @@ function HistorySection({
13025
13376
  multiplayerStateManager.undo();
13026
13377
  }
13027
13378
  },
13028
- /* @__PURE__ */ React26.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ React26.createElement(
13379
+ /* @__PURE__ */ React28.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ React28.createElement(
13029
13380
  "svg",
13030
13381
  {
13031
13382
  xmlns: "http://www.w3.org/2000/svg",
@@ -13033,7 +13384,7 @@ function HistorySection({
13033
13384
  height: "1em",
13034
13385
  viewBox: "0 0 20 20"
13035
13386
  },
13036
- /* @__PURE__ */ React26.createElement(
13387
+ /* @__PURE__ */ React28.createElement(
13037
13388
  "path",
13038
13389
  {
13039
13390
  fill: "currentColor",
@@ -13042,7 +13393,7 @@ function HistorySection({
13042
13393
  )
13043
13394
  ))
13044
13395
  ),
13045
- /* @__PURE__ */ React26.createElement(
13396
+ /* @__PURE__ */ React28.createElement(
13046
13397
  StateInspectorButton,
13047
13398
  {
13048
13399
  disabled: !historySnapshot.canRedo,
@@ -13051,7 +13402,7 @@ function HistorySection({
13051
13402
  multiplayerStateManager.redo();
13052
13403
  }
13053
13404
  },
13054
- /* @__PURE__ */ React26.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ React26.createElement(
13405
+ /* @__PURE__ */ React28.createElement("span", { style: { width: "12px", height: "12px" } }, /* @__PURE__ */ React28.createElement(
13055
13406
  "svg",
13056
13407
  {
13057
13408
  xmlns: "http://www.w3.org/2000/svg",
@@ -13059,7 +13410,7 @@ function HistorySection({
13059
13410
  height: "1em",
13060
13411
  viewBox: "0 0 20 20"
13061
13412
  },
13062
- /* @__PURE__ */ React26.createElement(
13413
+ /* @__PURE__ */ React28.createElement(
13063
13414
  "path",
13064
13415
  {
13065
13416
  fill: "currentColor",
@@ -13070,7 +13421,7 @@ function HistorySection({
13070
13421
  )
13071
13422
  )
13072
13423
  },
13073
- /* @__PURE__ */ React26.createElement(StateInspectorDisclosureRowInner, { ref }, /* @__PURE__ */ React26.createElement(
13424
+ /* @__PURE__ */ React28.createElement(StateInspectorDisclosureRowInner, { ref }, /* @__PURE__ */ React28.createElement(
13074
13425
  "div",
13075
13426
  {
13076
13427
  id: `${HISTORY_ELEMENT_PREFIX}0`,
@@ -13084,7 +13435,7 @@ function HistorySection({
13084
13435
  background: historySnapshot.historyIndex === 0 ? "rgb(59 130 246 / 15%)" : void 0
13085
13436
  }
13086
13437
  },
13087
- /* @__PURE__ */ React26.createElement(
13438
+ /* @__PURE__ */ React28.createElement(
13088
13439
  "span",
13089
13440
  {
13090
13441
  style: {
@@ -13099,7 +13450,7 @@ function HistorySection({
13099
13450
  ), historySnapshot.history.map((entry, index) => {
13100
13451
  const metadata = entry.metadata;
13101
13452
  const { id, name, timestamp, ...rest } = metadata;
13102
- return /* @__PURE__ */ React26.createElement(
13453
+ return /* @__PURE__ */ React28.createElement(
13103
13454
  "div",
13104
13455
  {
13105
13456
  id: `${HISTORY_ELEMENT_PREFIX}${index + 1}`,
@@ -13110,7 +13461,7 @@ function HistorySection({
13110
13461
  background: index + 1 === historySnapshot.historyIndex ? "rgb(59 130 246 / 15%)" : void 0
13111
13462
  }
13112
13463
  },
13113
- typeof name === "string" && /* @__PURE__ */ React26.createElement(
13464
+ typeof name === "string" && /* @__PURE__ */ React28.createElement(
13114
13465
  "pre",
13115
13466
  {
13116
13467
  style: {
@@ -13121,9 +13472,9 @@ function HistorySection({
13121
13472
  }
13122
13473
  },
13123
13474
  entry.metadata.name,
13124
- Object.keys(rest).length > 0 && /* @__PURE__ */ React26.createElement(themedObjectInspector, { data: rest, theme: theme3 })
13475
+ Object.keys(rest).length > 0 && /* @__PURE__ */ React28.createElement(themedObjectInspector, { data: rest, theme: theme3 })
13125
13476
  ),
13126
- entry.redoPatches?.map((patch, j) => /* @__PURE__ */ React26.createElement(
13477
+ entry.redoPatches?.map((patch, j) => /* @__PURE__ */ React28.createElement(
13127
13478
  "pre",
13128
13479
  {
13129
13480
  key: j,
@@ -13134,10 +13485,10 @@ function HistorySection({
13134
13485
  margin: 0
13135
13486
  }
13136
13487
  },
13137
- patch.op === "add" && /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)), " = ", /* @__PURE__ */ React26.createElement(themedObjectInspector, { data: patch.value, theme: theme3 })),
13138
- patch.op === "replace" && /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)), " = ", /* @__PURE__ */ React26.createElement(themedObjectInspector, { data: patch.value, theme: theme3 })),
13139
- patch.op === "remove" && /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement("span", { style: { color: theme3.OBJECT_VALUE_STRING_COLOR } }, "delete", " "), /* @__PURE__ */ React26.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path))),
13140
- patch.op === "move" && /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.from)), " -> ", /* @__PURE__ */ React26.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)))
13488
+ patch.op === "add" && /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)), " = ", /* @__PURE__ */ React28.createElement(themedObjectInspector, { data: patch.value, theme: theme3 })),
13489
+ patch.op === "replace" && /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)), " = ", /* @__PURE__ */ React28.createElement(themedObjectInspector, { data: patch.value, theme: theme3 })),
13490
+ patch.op === "remove" && /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement("span", { style: { color: theme3.OBJECT_VALUE_STRING_COLOR } }, "delete", " "), /* @__PURE__ */ React28.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path))),
13491
+ patch.op === "move" && /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.from)), " -> ", /* @__PURE__ */ React28.createElement("span", { style: { fontStyle: "italic" } }, pathToString(patch.path)))
13141
13492
  ))
13142
13493
  );
13143
13494
  }))
@@ -13145,7 +13496,7 @@ function HistorySection({
13145
13496
  }
13146
13497
 
13147
13498
  // ../noya-multiplayer-react/src/inspector/sections/ServerScriptLogsSection.tsx
13148
- import React27 from "react";
13499
+ import React29 from "react";
13149
13500
  var levelColors = {
13150
13501
  error: "#f87171",
13151
13502
  warn: "#facc15",
@@ -13161,19 +13512,20 @@ function ServerScriptLogsSection({
13161
13512
  logs,
13162
13513
  containerRef,
13163
13514
  paused,
13164
- onTogglePaused
13515
+ onTogglePaused,
13516
+ title = "Server Script Logs"
13165
13517
  }) {
13166
13518
  const theme3 = getStateInspectorTheme(colorScheme);
13167
- return /* @__PURE__ */ React27.createElement(
13519
+ return /* @__PURE__ */ React29.createElement(
13168
13520
  StateInspectorDisclosureSection,
13169
13521
  {
13170
13522
  open: showLogs,
13171
13523
  setOpen: setShowLogs,
13172
- title: "Server Script Logs",
13524
+ title,
13173
13525
  colorScheme,
13174
- right: /* @__PURE__ */ React27.createElement(StateInspectorButton, { theme: theme3, onClick: onTogglePaused }, paused ? "Resume" : "Pause")
13526
+ right: /* @__PURE__ */ React29.createElement(StateInspectorButton, { theme: theme3, onClick: onTogglePaused }, paused ? "Resume" : "Pause")
13175
13527
  },
13176
- /* @__PURE__ */ React27.createElement(StateInspectorDisclosureRowInner, { ref: containerRef }, paused && /* @__PURE__ */ React27.createElement(
13528
+ /* @__PURE__ */ React29.createElement(StateInspectorDisclosureRowInner, { ref: containerRef }, paused && /* @__PURE__ */ React29.createElement(
13177
13529
  "div",
13178
13530
  {
13179
13531
  style: {
@@ -13183,7 +13535,7 @@ function ServerScriptLogsSection({
13183
13535
  }
13184
13536
  },
13185
13537
  "Log streaming paused"
13186
- ), logs.map((log) => /* @__PURE__ */ React27.createElement(StateInspectorRow, { key: log.id, colorScheme }, /* @__PURE__ */ React27.createElement(
13538
+ ), logs.map((log) => /* @__PURE__ */ React29.createElement(StateInspectorRow, { key: log.id, colorScheme }, /* @__PURE__ */ React29.createElement(
13187
13539
  "div",
13188
13540
  {
13189
13541
  style: {
@@ -13196,9 +13548,21 @@ function ServerScriptLogsSection({
13196
13548
  textTransform: "uppercase"
13197
13549
  }
13198
13550
  },
13199
- /* @__PURE__ */ React27.createElement("span", null, formatTimestamp(log.timestamp)),
13200
- /* @__PURE__ */ React27.createElement("span", { style: { color: levelColors[log.level] } }, log.level),
13201
- /* @__PURE__ */ React27.createElement(
13551
+ /* @__PURE__ */ React29.createElement("span", null, formatTimestamp(log.timestamp)),
13552
+ /* @__PURE__ */ React29.createElement("span", { style: { color: levelColors[log.level] } }, log.level),
13553
+ (log.origin || log.target || log.mode) && /* @__PURE__ */ React29.createElement(
13554
+ "span",
13555
+ {
13556
+ style: {
13557
+ fontFamily: "monospace",
13558
+ textTransform: "none",
13559
+ fontSize: "10px",
13560
+ opacity: 0.75
13561
+ }
13562
+ },
13563
+ [log.origin ?? log.target, log.mode].filter(Boolean).join(" / ")
13564
+ ),
13565
+ /* @__PURE__ */ React29.createElement(
13202
13566
  "span",
13203
13567
  {
13204
13568
  style: {
@@ -13209,7 +13573,7 @@ function ServerScriptLogsSection({
13209
13573
  },
13210
13574
  log.scriptId
13211
13575
  )
13212
- ), /* @__PURE__ */ React27.createElement(
13576
+ ), /* @__PURE__ */ React29.createElement(
13213
13577
  "div",
13214
13578
  {
13215
13579
  style: {
@@ -13218,16 +13582,15 @@ function ServerScriptLogsSection({
13218
13582
  gap: "4px"
13219
13583
  }
13220
13584
  },
13221
- log.values.length > 0 ? log.values.map((value, index) => /* @__PURE__ */ React27.createElement(
13585
+ log.values.length > 0 ? log.values.map((value, index) => /* @__PURE__ */ React29.createElement(
13222
13586
  themedObjectInspector,
13223
13587
  {
13224
13588
  key: index,
13225
13589
  data: value,
13226
- theme: theme3,
13227
- expandLevel: 3
13590
+ theme: theme3
13228
13591
  }
13229
- )) : /* @__PURE__ */ React27.createElement("span", { style: { fontSize: "11px", opacity: 0.7 } }, "No data")
13230
- ))), !logs?.length && /* @__PURE__ */ React27.createElement(
13592
+ )) : /* @__PURE__ */ React29.createElement("span", { style: { fontSize: "11px", opacity: 0.7 } }, "No data")
13593
+ ))), !logs?.length && /* @__PURE__ */ React29.createElement(
13231
13594
  "div",
13232
13595
  {
13233
13596
  style: {
@@ -13238,7 +13601,7 @@ function ServerScriptLogsSection({
13238
13601
  gap: "4px"
13239
13602
  }
13240
13603
  },
13241
- /* @__PURE__ */ React27.createElement("span", null, "No logs received")
13604
+ /* @__PURE__ */ React29.createElement("span", null, "No logs received")
13242
13605
  ))
13243
13606
  );
13244
13607
  }
@@ -13766,16 +14129,8 @@ function decodeAll(buffer) {
13766
14129
  return { state, schema, assets, assetMap };
13767
14130
  }
13768
14131
 
13769
- // ../noya-multiplayer-react/src/inspector/StateInspectorTitleLabel.tsx
13770
- import React28 from "react";
13771
- function StateInspectorTitleLabel({
13772
- children
13773
- }) {
13774
- return /* @__PURE__ */ React28.createElement("span", { style: { display: "flex", alignItems: "center", gap: "4px" } }, children);
13775
- }
13776
-
13777
14132
  // ../noya-multiplayer-react/src/inspector/StateInspectorToggleButton.tsx
13778
- import React29 from "react";
14133
+ import React30 from "react";
13779
14134
  function StateInspectorToggleButton({
13780
14135
  showInspector,
13781
14136
  setShowInspector,
@@ -13783,7 +14138,7 @@ function StateInspectorToggleButton({
13783
14138
  anchor
13784
14139
  }) {
13785
14140
  const isRightAnchor = anchor === "right";
13786
- const rightIcon = /* @__PURE__ */ React29.createElement(
14141
+ const rightIcon = /* @__PURE__ */ React30.createElement(
13787
14142
  "svg",
13788
14143
  {
13789
14144
  xmlns: "http://www.w3.org/2000/svg",
@@ -13793,7 +14148,7 @@ function StateInspectorToggleButton({
13793
14148
  stroke: "currentColor",
13794
14149
  className: "size-6"
13795
14150
  },
13796
- /* @__PURE__ */ React29.createElement(
14151
+ /* @__PURE__ */ React30.createElement(
13797
14152
  "path",
13798
14153
  {
13799
14154
  strokeLinecap: "round",
@@ -13802,7 +14157,7 @@ function StateInspectorToggleButton({
13802
14157
  }
13803
14158
  )
13804
14159
  );
13805
- const leftIcon = /* @__PURE__ */ React29.createElement(
14160
+ const leftIcon = /* @__PURE__ */ React30.createElement(
13806
14161
  "svg",
13807
14162
  {
13808
14163
  xmlns: "http://www.w3.org/2000/svg",
@@ -13812,7 +14167,7 @@ function StateInspectorToggleButton({
13812
14167
  stroke: "currentColor",
13813
14168
  className: "size-6"
13814
14169
  },
13815
- /* @__PURE__ */ React29.createElement(
14170
+ /* @__PURE__ */ React30.createElement(
13816
14171
  "path",
13817
14172
  {
13818
14173
  strokeLinecap: "round",
@@ -13821,7 +14176,7 @@ function StateInspectorToggleButton({
13821
14176
  }
13822
14177
  )
13823
14178
  );
13824
- return /* @__PURE__ */ React29.createElement(
14179
+ return /* @__PURE__ */ React30.createElement(
13825
14180
  "span",
13826
14181
  {
13827
14182
  role: "button",
@@ -13842,15 +14197,15 @@ function StateInspectorToggleButton({
13842
14197
  setShowInspector(!showInspector);
13843
14198
  }
13844
14199
  },
13845
- showInspector ? "Hide Inspector" : /* @__PURE__ */ React29.createElement("span", { style: { width: "12px", height: "12px" } }, isRightAnchor ? rightIcon : leftIcon)
14200
+ showInspector ? "Hide Inspector" : /* @__PURE__ */ React30.createElement("span", { style: { width: "12px", height: "12px" } }, isRightAnchor ? rightIcon : leftIcon)
13846
14201
  );
13847
14202
  }
13848
14203
 
13849
14204
  // ../noya-multiplayer-react/src/inspector/useLocalStorageState.tsx
13850
- import React30 from "react";
14205
+ import React31 from "react";
13851
14206
  var localStorage2 = typeof window !== "undefined" ? window.localStorage : null;
13852
14207
  function useLocalStorageState(key, defaultValue) {
13853
- const [state, setState] = React30.useState(() => {
14208
+ const [state, setState] = React31.useState(() => {
13854
14209
  const value = localStorage2?.getItem(key);
13855
14210
  let result = defaultValue;
13856
14211
  if (value) {
@@ -13869,6 +14224,31 @@ function useLocalStorageState(key, defaultValue) {
13869
14224
  return [state, setLocalStorageState];
13870
14225
  }
13871
14226
 
14227
+ // ../noya-multiplayer-react/src/inspector/usePausedStream.ts
14228
+ import React33 from "react";
14229
+ function usePausedStream(items) {
14230
+ const [paused, setPaused] = React33.useState(false);
14231
+ const [visibleItems, setVisibleItems] = React33.useState(items ?? []);
14232
+ const togglePaused = React33.useCallback(() => {
14233
+ setPaused((value) => {
14234
+ if (!value) {
14235
+ setVisibleItems(items ?? []);
14236
+ }
14237
+ return !value;
14238
+ });
14239
+ }, [items]);
14240
+ React33.useEffect(() => {
14241
+ if (paused) return;
14242
+ setVisibleItems(items ?? []);
14243
+ }, [items, paused]);
14244
+ return {
14245
+ paused,
14246
+ setPaused,
14247
+ togglePaused,
14248
+ visibleItems
14249
+ };
14250
+ }
14251
+
13872
14252
  // ../noya-multiplayer-react/src/inspector/StateInspector.tsx
13873
14253
  var StateInspector = memoGeneric(function StateInspector2({
13874
14254
  noyaManager,
@@ -13889,18 +14269,20 @@ var StateInspector = memoGeneric(function StateInspector2({
13889
14269
  ioManager,
13890
14270
  resourceManager,
13891
14271
  activityEventsManager,
13892
- logManager
14272
+ logManager,
14273
+ gitManager
13893
14274
  } = noyaManager;
13894
- const [didMount, setDidMount] = React31.useState(false);
14275
+ const [didMount, setDidMount] = React34.useState(false);
13895
14276
  const tasks = useObservable2(taskManager.tasks$);
13896
14277
  const inputs = useObservable2(ioManager.inputs$);
13897
14278
  const outputTransforms = useObservable2(ioManager.outputTransforms$);
13898
14279
  useLayoutEffect4(() => {
13899
14280
  setDidMount(true);
13900
14281
  }, []);
13901
- const eventsContainerRef = React31.useRef(null);
13902
- const activityEventsContainerRef = React31.useRef(null);
13903
- const serverLogsContainerRef = React31.useRef(null);
14282
+ const eventsContainerRef = React34.useRef(null);
14283
+ const activityEventsContainerRef = React34.useRef(null);
14284
+ const serverLogsContainerRef = React34.useRef(null);
14285
+ const serverSimulationLogsContainerRef = React34.useRef(null);
13904
14286
  const [showInspector, setShowInspector] = useLocalStorageState(
13905
14287
  "noya-multiplayer-react-show-inspector",
13906
14288
  true
@@ -13917,6 +14299,10 @@ var StateInspector = memoGeneric(function StateInspector2({
13917
14299
  "noya-multiplayer-react-show-users",
13918
14300
  true
13919
14301
  );
14302
+ const [showUserDetails, setShowUserDetails] = useLocalStorageState(
14303
+ "noya-multiplayer-react-show-user-details",
14304
+ false
14305
+ );
13920
14306
  const [showData, setShowData] = useLocalStorageState(
13921
14307
  "noya-multiplayer-react-show-data",
13922
14308
  true
@@ -13957,35 +14343,55 @@ var StateInspector = memoGeneric(function StateInspector2({
13957
14343
  "noya-multiplayer-react-show-server-logs",
13958
14344
  false
13959
14345
  );
14346
+ const [showServerSimulationLogs, setShowServerSimulationLogs] = useLocalStorageState(
14347
+ "noya-multiplayer-react-show-server-simulation-logs",
14348
+ false
14349
+ );
14350
+ const [showGit, setShowGit] = useLocalStorageState(
14351
+ "noya-multiplayer-react-show-git",
14352
+ false
14353
+ );
14354
+ const [showSimulation, setShowSimulation] = useLocalStorageState(
14355
+ "noya-multiplayer-react-show-simulation",
14356
+ false
14357
+ );
13960
14358
  const connectionEvents = useObservable2(connectionEventManager.events$);
13961
- useEffect13(() => {
14359
+ const {
14360
+ visibleItems: visibleConnectionEvents,
14361
+ paused: connectionEventsPaused,
14362
+ togglePaused: toggleConnectionEventsPaused
14363
+ } = usePausedStream(connectionEvents);
14364
+ useEffect14(() => {
13962
14365
  if (eventsContainerRef.current) {
13963
14366
  eventsContainerRef.current.scrollTop = eventsContainerRef.current.scrollHeight;
13964
14367
  }
13965
- }, [connectionEvents]);
14368
+ }, [visibleConnectionEvents]);
13966
14369
  const serverLogs = useObservable2(logManager.logs$);
13967
- const [serverLogsPaused, setServerLogsPaused] = React31.useState(false);
13968
- const [visibleServerLogs, setVisibleServerLogs] = React31.useState(
13969
- serverLogs ?? []
14370
+ const {
14371
+ visibleItems: visibleServerLogs,
14372
+ paused: serverLogsPaused,
14373
+ togglePaused: toggleServerLogsPaused
14374
+ } = usePausedStream(serverLogs);
14375
+ const serverSimulationLogs = useObservable2(
14376
+ multiplayerStateManager.serverSimulationLogs$
13970
14377
  );
13971
- const toggleServerLogsPaused = useCallback12(() => {
13972
- setServerLogsPaused((value) => {
13973
- if (!value) {
13974
- setVisibleServerLogs(serverLogs ?? []);
13975
- }
13976
- return !value;
13977
- });
13978
- }, [serverLogs]);
13979
- useEffect13(() => {
13980
- if (serverLogsPaused) return;
13981
- setVisibleServerLogs(serverLogs ?? []);
13982
- }, [serverLogs, serverLogsPaused]);
13983
- useEffect13(() => {
14378
+ const {
14379
+ visibleItems: visibleServerSimulationLogs,
14380
+ paused: serverSimulationLogsPaused,
14381
+ togglePaused: toggleServerSimulationLogsPaused
14382
+ } = usePausedStream(serverSimulationLogs);
14383
+ useEffect14(() => {
13984
14384
  if (!showServerLogs) return;
13985
14385
  if (serverLogsContainerRef.current) {
13986
14386
  serverLogsContainerRef.current.scrollTop = serverLogsContainerRef.current.scrollHeight;
13987
14387
  }
13988
14388
  }, [showServerLogs, visibleServerLogs]);
14389
+ useEffect14(() => {
14390
+ if (!showServerSimulationLogs) return;
14391
+ if (serverSimulationLogsContainerRef.current) {
14392
+ serverSimulationLogsContainerRef.current.scrollTop = serverSimulationLogsContainerRef.current.scrollHeight;
14393
+ }
14394
+ }, [showServerSimulationLogs, visibleServerSimulationLogs]);
13989
14395
  const multipeerStateInitialized = useObservable2(
13990
14396
  multiplayerStateManager.isInitialized$
13991
14397
  );
@@ -13997,8 +14403,10 @@ var StateInspector = memoGeneric(function StateInspector2({
13997
14403
  const assetsInitialized = useObservable2(assetManager.isInitialized$);
13998
14404
  const secrets = useObservable2(secretManager.secrets$);
13999
14405
  const secretsInitialized = useObservable2(secretManager.isInitialized$);
14000
- const connectedUsers = useObservable2(userManager.connectedUsers$);
14406
+ const connectedUsers = useObservable2(userManager.allUsers$);
14001
14407
  const connectionId = useObservable2(userManager.currentConnectionId$);
14408
+ const simulationDiagnostics = multiplayerStateManager.getServerSimulationDiagnostics?.() ?? null;
14409
+ const showSimulationLogsSection = (simulationDiagnostics?.simulateLocally ?? false) || visibleServerSimulationLogs.length > 0;
14002
14410
  const state = useObservable2(multiplayerStateManager.optimisticState$);
14003
14411
  const inputsInitialized = useObservable2(ioManager.inputsInitialized$);
14004
14412
  const outputTransformsInitialized = useObservable2(
@@ -14042,7 +14450,7 @@ var StateInspector = memoGeneric(function StateInspector2({
14042
14450
  }, [noyaManager]);
14043
14451
  if (!didMount) return null;
14044
14452
  if (!showInspector) {
14045
- return /* @__PURE__ */ React31.createElement(
14453
+ return /* @__PURE__ */ React34.createElement(
14046
14454
  "div",
14047
14455
  {
14048
14456
  ...props,
@@ -14054,7 +14462,7 @@ var StateInspector = memoGeneric(function StateInspector2({
14054
14462
  },
14055
14463
  onClick: () => setShowInspector(true)
14056
14464
  },
14057
- /* @__PURE__ */ React31.createElement(
14465
+ /* @__PURE__ */ React34.createElement(
14058
14466
  StateInspectorToggleButton,
14059
14467
  {
14060
14468
  showInspector,
@@ -14065,7 +14473,7 @@ var StateInspector = memoGeneric(function StateInspector2({
14065
14473
  )
14066
14474
  );
14067
14475
  }
14068
- return /* @__PURE__ */ React31.createElement(
14476
+ return /* @__PURE__ */ React34.createElement(
14069
14477
  "div",
14070
14478
  {
14071
14479
  ...props,
@@ -14074,7 +14482,7 @@ var StateInspector = memoGeneric(function StateInspector2({
14074
14482
  ...props.style
14075
14483
  }
14076
14484
  },
14077
- /* @__PURE__ */ React31.createElement(
14485
+ /* @__PURE__ */ React34.createElement(
14078
14486
  StateInspectorDisclosureSection,
14079
14487
  {
14080
14488
  isFirst: true,
@@ -14084,9 +14492,17 @@ var StateInspector = memoGeneric(function StateInspector2({
14084
14492
  colorScheme,
14085
14493
  style: {
14086
14494
  flex: "0 0 auto",
14087
- maxHeight: "200px"
14495
+ maxHeight: "50%",
14496
+ overflowY: "auto"
14088
14497
  },
14089
- right: /* @__PURE__ */ React31.createElement(
14498
+ right: /* @__PURE__ */ React34.createElement("span", { style: { display: "flex", gap: "10px" } }, /* @__PURE__ */ React34.createElement(
14499
+ StateInspectorButton,
14500
+ {
14501
+ theme: theme3,
14502
+ onClick: () => setShowUserDetails(!showUserDetails)
14503
+ },
14504
+ "Toggle details"
14505
+ ), /* @__PURE__ */ React34.createElement(
14090
14506
  StateInspectorToggleButton,
14091
14507
  {
14092
14508
  showInspector,
@@ -14094,19 +14510,21 @@ var StateInspector = memoGeneric(function StateInspector2({
14094
14510
  theme: theme3,
14095
14511
  anchor
14096
14512
  }
14097
- )
14513
+ ))
14098
14514
  },
14099
- /* @__PURE__ */ React31.createElement(StateInspectorDisclosureRowInner, { style: { flex: "0 0 auto" } }, connectedUsers?.map((user, index, array) => {
14100
- const identifier = user.userId ?? user.connectionId;
14101
- return /* @__PURE__ */ React31.createElement(
14515
+ /* @__PURE__ */ React34.createElement(StateInspectorDisclosureRowInner, { style: { flex: "0 0 auto" } }, connectedUsers?.filter((user) => showUserDetails || !user.inactive).map((user, index, array) => {
14516
+ return /* @__PURE__ */ React34.createElement(
14102
14517
  StateInspectorRow,
14103
14518
  {
14104
14519
  key: user.connectionId,
14105
14520
  colorScheme,
14106
14521
  variant: user.connectionId === connectionId ? "up" : void 0,
14107
- bordered: index !== array.length - 1
14522
+ bordered: index !== array.length - 1,
14523
+ style: {
14524
+ opacity: user.inactive ? 0.5 : 1
14525
+ }
14108
14526
  },
14109
- user.image && /* @__PURE__ */ React31.createElement(
14527
+ user.image && /* @__PURE__ */ React34.createElement(
14110
14528
  "img",
14111
14529
  {
14112
14530
  src: user.image,
@@ -14123,12 +14541,9 @@ var StateInspector = memoGeneric(function StateInspector2({
14123
14541
  }
14124
14542
  }
14125
14543
  ),
14126
- user.name,
14127
- " (",
14128
- ellipsis(identifier, 8, "middle"),
14129
- ")"
14544
+ showUserDetails ? /* @__PURE__ */ React34.createElement(themedObjectInspector, { data: user, theme: theme3 }) : user.name
14130
14545
  );
14131
- }), !connectedUsers && /* @__PURE__ */ React31.createElement(
14546
+ }), !connectedUsers && /* @__PURE__ */ React34.createElement(
14132
14547
  "div",
14133
14548
  {
14134
14549
  style: {
@@ -14139,13 +14554,13 @@ var StateInspector = memoGeneric(function StateInspector2({
14139
14554
  gap: "4px"
14140
14555
  }
14141
14556
  },
14142
- /* @__PURE__ */ React31.createElement("span", null, "No connected users")
14557
+ /* @__PURE__ */ React34.createElement("span", null, "No connected users")
14143
14558
  ))
14144
14559
  ),
14145
- /* @__PURE__ */ React31.createElement(
14560
+ /* @__PURE__ */ React34.createElement(
14146
14561
  StateInspectorDisclosureSection,
14147
14562
  {
14148
- title: /* @__PURE__ */ React31.createElement(StateInspectorTitleLabel, null, "Data", /* @__PURE__ */ React31.createElement(
14563
+ title: /* @__PURE__ */ React34.createElement(StateInspectorTitleLabel, null, "Data", /* @__PURE__ */ React34.createElement(
14149
14564
  ColoredDot,
14150
14565
  {
14151
14566
  type: multipeerStateInitialized ? "success" : "error"
@@ -14154,7 +14569,7 @@ var StateInspector = memoGeneric(function StateInspector2({
14154
14569
  colorScheme,
14155
14570
  setOpen: setShowData,
14156
14571
  open: showData,
14157
- right: /* @__PURE__ */ React31.createElement(
14572
+ right: /* @__PURE__ */ React34.createElement(
14158
14573
  "span",
14159
14574
  {
14160
14575
  style: {
@@ -14162,9 +14577,9 @@ var StateInspector = memoGeneric(function StateInspector2({
14162
14577
  gap: "12px"
14163
14578
  }
14164
14579
  },
14165
- /* @__PURE__ */ React31.createElement(StateInspectorButton, { theme: theme3, onClick: handleImportAll }, "Import"),
14166
- /* @__PURE__ */ React31.createElement(StateInspectorButton, { theme: theme3, onClick: handleExportAll }, "Export"),
14167
- /* @__PURE__ */ React31.createElement(
14580
+ /* @__PURE__ */ React34.createElement(StateInspectorButton, { theme: theme3, onClick: handleImportAll }, "Import"),
14581
+ /* @__PURE__ */ React34.createElement(StateInspectorButton, { theme: theme3, onClick: handleExportAll }, "Export"),
14582
+ /* @__PURE__ */ React34.createElement(
14168
14583
  StateInspectorButton,
14169
14584
  {
14170
14585
  theme: theme3,
@@ -14176,14 +14591,14 @@ var StateInspector = memoGeneric(function StateInspector2({
14176
14591
  )
14177
14592
  )
14178
14593
  },
14179
- /* @__PURE__ */ React31.createElement(StateInspectorDisclosureRowInner, null, /* @__PURE__ */ React31.createElement(StateInspectorRow, { colorScheme }, /* @__PURE__ */ React31.createElement(
14594
+ /* @__PURE__ */ React34.createElement(StateInspectorDisclosureRowInner, null, /* @__PURE__ */ React34.createElement(StateInspectorRow, { colorScheme }, /* @__PURE__ */ React34.createElement(
14180
14595
  themedObjectInspector,
14181
14596
  {
14182
14597
  name: multiplayerStateManager.schema ? "state" : void 0,
14183
14598
  data: state,
14184
14599
  theme: theme3
14185
14600
  }
14186
- )), multiplayerStateManager.schema && /* @__PURE__ */ React31.createElement(StateInspectorRow, { colorScheme }, /* @__PURE__ */ React31.createElement(
14601
+ )), multiplayerStateManager.schema && /* @__PURE__ */ React34.createElement(StateInspectorRow, { colorScheme }, /* @__PURE__ */ React34.createElement(
14187
14602
  themedObjectInspector,
14188
14603
  {
14189
14604
  name: "schema",
@@ -14192,7 +14607,7 @@ var StateInspector = memoGeneric(function StateInspector2({
14192
14607
  }
14193
14608
  )))
14194
14609
  ),
14195
- /* @__PURE__ */ React31.createElement(
14610
+ /* @__PURE__ */ React34.createElement(
14196
14611
  HistorySection,
14197
14612
  {
14198
14613
  showHistory,
@@ -14202,14 +14617,14 @@ var StateInspector = memoGeneric(function StateInspector2({
14202
14617
  multiplayerStateManager
14203
14618
  }
14204
14619
  ),
14205
- /* @__PURE__ */ React31.createElement(
14620
+ /* @__PURE__ */ React34.createElement(
14206
14621
  StateInspectorDisclosureSection,
14207
14622
  {
14208
14623
  open: showAssets,
14209
14624
  setOpen: setShowAssets,
14210
- title: /* @__PURE__ */ React31.createElement(StateInspectorTitleLabel, null, "Assets (", assets.length, ")", /* @__PURE__ */ React31.createElement(ColoredDot, { type: assetsInitialized ? "success" : "error" })),
14625
+ title: /* @__PURE__ */ React34.createElement(StateInspectorTitleLabel, null, "Assets (", assets.length, ")", /* @__PURE__ */ React34.createElement(ColoredDot, { type: assetsInitialized ? "success" : "error" })),
14211
14626
  colorScheme,
14212
- right: /* @__PURE__ */ React31.createElement("span", { style: { display: "flex", gap: "10px" } }, /* @__PURE__ */ React31.createElement(
14627
+ right: /* @__PURE__ */ React34.createElement("span", { style: { display: "flex", gap: "10px" } }, /* @__PURE__ */ React34.createElement(
14213
14628
  StateInspectorButton,
14214
14629
  {
14215
14630
  theme: theme3,
@@ -14224,7 +14639,7 @@ var StateInspector = memoGeneric(function StateInspector2({
14224
14639
  }
14225
14640
  },
14226
14641
  "Delete all"
14227
- ), /* @__PURE__ */ React31.createElement(
14642
+ ), /* @__PURE__ */ React34.createElement(
14228
14643
  StateInspectorButton,
14229
14644
  {
14230
14645
  theme: theme3,
@@ -14237,54 +14652,69 @@ var StateInspector = memoGeneric(function StateInspector2({
14237
14652
  }
14238
14653
  },
14239
14654
  "Reload"
14240
- ), /* @__PURE__ */ React31.createElement(
14655
+ ), /* @__PURE__ */ React34.createElement(
14241
14656
  StateInspectorButton,
14242
14657
  {
14243
14658
  theme: theme3,
14244
- onClick: () => {
14245
- const input = document.createElement("input");
14246
- input.type = "file";
14247
- input.onchange = () => {
14248
- const file = input.files?.[0];
14249
- if (file) {
14250
- const reader = new FileReader();
14251
- reader.onload = () => {
14252
- const buffer = reader.result;
14253
- assetManager.create(new Uint8Array(buffer));
14254
- };
14255
- reader.readAsArrayBuffer(file);
14256
- }
14257
- };
14258
- input.click();
14659
+ onClick: async () => {
14660
+ const file = await uploadFile();
14661
+ assetManager.create(file);
14259
14662
  }
14260
14663
  },
14261
14664
  "Upload"
14665
+ ), /* @__PURE__ */ React34.createElement(
14666
+ StateInspectorButton,
14667
+ {
14668
+ theme: theme3,
14669
+ onClick: async () => {
14670
+ const file = await uploadFile();
14671
+ assetManager.create({
14672
+ data: new Uint8Array(await file.arrayBuffer()),
14673
+ contentType: file.type,
14674
+ mode: "mutable"
14675
+ });
14676
+ }
14677
+ },
14678
+ "Upload Mutable"
14262
14679
  ))
14263
14680
  },
14264
- /* @__PURE__ */ React31.createElement(StateInspectorDisclosureRowInner, null, assets.map((asset) => /* @__PURE__ */ React31.createElement(StateInspectorRow, { key: asset.id, colorScheme }, /* @__PURE__ */ React31.createElement(
14681
+ /* @__PURE__ */ React34.createElement(StateInspectorDisclosureRowInner, null, assets.map((asset) => /* @__PURE__ */ React34.createElement(StateInspectorRow, { key: asset.id, colorScheme }, /* @__PURE__ */ React34.createElement(
14265
14682
  themedObjectInspector,
14266
14683
  {
14267
14684
  name: asset.id,
14268
14685
  data: truncateAsset(asset),
14269
14686
  theme: theme3
14270
14687
  }
14271
- ), /* @__PURE__ */ React31.createElement(
14688
+ ), /* @__PURE__ */ React34.createElement("div", { style: { display: "flex", gap: "4px" } }, asset.mode === "mutable" && /* @__PURE__ */ React34.createElement(
14689
+ StateInspectorButton,
14690
+ {
14691
+ theme: theme3,
14692
+ onClick: async () => {
14693
+ const file = await uploadFile();
14694
+ assetManager.update(asset.id, {
14695
+ data: new Uint8Array(await file.arrayBuffer()),
14696
+ contentType: file.type
14697
+ });
14698
+ }
14699
+ },
14700
+ "Replace"
14701
+ ), /* @__PURE__ */ React34.createElement(
14272
14702
  StateInspectorButton,
14273
14703
  {
14274
14704
  theme: theme3,
14275
14705
  onClick: () => assetManager.delete(asset.id)
14276
14706
  },
14277
14707
  "Delete"
14278
- ))))
14708
+ )))))
14279
14709
  ),
14280
- advanced && /* @__PURE__ */ React31.createElement(
14710
+ advanced && /* @__PURE__ */ React34.createElement(
14281
14711
  StateInspectorDisclosureSection,
14282
14712
  {
14283
- title: /* @__PURE__ */ React31.createElement(StateInspectorTitleLabel, null, "Resources (", resources.length, ")", /* @__PURE__ */ React31.createElement(ColoredDot, { type: resourcesInitialized ? "success" : "error" })),
14713
+ title: /* @__PURE__ */ React34.createElement(StateInspectorTitleLabel, null, "Resources (", resources.length, ")", /* @__PURE__ */ React34.createElement(ColoredDot, { type: resourcesInitialized ? "success" : "error" })),
14284
14714
  colorScheme,
14285
14715
  open: showResources,
14286
14716
  setOpen: setShowResources,
14287
- right: /* @__PURE__ */ React31.createElement("span", { style: { display: "flex", gap: "10px" } }, /* @__PURE__ */ React31.createElement(
14717
+ right: /* @__PURE__ */ React34.createElement("span", { style: { display: "flex", gap: "10px" } }, /* @__PURE__ */ React34.createElement(
14288
14718
  StateInspectorButton,
14289
14719
  {
14290
14720
  theme: theme3,
@@ -14299,7 +14729,7 @@ var StateInspector = memoGeneric(function StateInspector2({
14299
14729
  }
14300
14730
  },
14301
14731
  "Delete all"
14302
- ), /* @__PURE__ */ React31.createElement(
14732
+ ), /* @__PURE__ */ React34.createElement(
14303
14733
  StateInspectorButton,
14304
14734
  {
14305
14735
  theme: theme3,
@@ -14312,7 +14742,7 @@ var StateInspector = memoGeneric(function StateInspector2({
14312
14742
  }
14313
14743
  },
14314
14744
  "Create Directory"
14315
- ), /* @__PURE__ */ React31.createElement(
14745
+ ), /* @__PURE__ */ React34.createElement(
14316
14746
  StateInspectorButton,
14317
14747
  {
14318
14748
  theme: theme3,
@@ -14332,21 +14762,21 @@ var StateInspector = memoGeneric(function StateInspector2({
14332
14762
  "Create Asset"
14333
14763
  ))
14334
14764
  },
14335
- /* @__PURE__ */ React31.createElement(StateInspectorDisclosureRowInner, null, resources?.map((resource) => /* @__PURE__ */ React31.createElement(StateInspectorRow, { key: resource.id, colorScheme }, /* @__PURE__ */ React31.createElement(
14765
+ /* @__PURE__ */ React34.createElement(StateInspectorDisclosureRowInner, null, resources?.map((resource) => /* @__PURE__ */ React34.createElement(StateInspectorRow, { key: resource.id, colorScheme }, /* @__PURE__ */ React34.createElement(
14336
14766
  themedObjectInspector,
14337
14767
  {
14338
14768
  name: resource.path,
14339
14769
  data: resource,
14340
14770
  theme: theme3
14341
14771
  }
14342
- ), /* @__PURE__ */ React31.createElement("div", { style: { display: "flex", gap: "4px" } }, /* @__PURE__ */ React31.createElement(
14772
+ ), /* @__PURE__ */ React34.createElement("div", { style: { display: "flex", gap: "4px" } }, /* @__PURE__ */ React34.createElement(
14343
14773
  StateInspectorButton,
14344
14774
  {
14345
14775
  theme: theme3,
14346
14776
  onClick: () => resourceManager.deleteResource({ id: resource.id })
14347
14777
  },
14348
14778
  "Delete"
14349
- ), /* @__PURE__ */ React31.createElement(
14779
+ ), /* @__PURE__ */ React34.createElement(
14350
14780
  StateInspectorButton,
14351
14781
  {
14352
14782
  theme: theme3,
@@ -14359,14 +14789,23 @@ var StateInspector = memoGeneric(function StateInspector2({
14359
14789
  "Rename"
14360
14790
  )))))
14361
14791
  ),
14362
- advanced && /* @__PURE__ */ React31.createElement(
14792
+ advanced && /* @__PURE__ */ React34.createElement(
14363
14793
  StateInspectorDisclosureSection,
14364
14794
  {
14365
- title: /* @__PURE__ */ React31.createElement(StateInspectorTitleLabel, null, "Secrets", /* @__PURE__ */ React31.createElement(ColoredDot, { type: secretsInitialized ? "success" : "error" })),
14795
+ title: /* @__PURE__ */ React34.createElement(StateInspectorTitleLabel, null, "Secrets (", secrets.length, ")", /* @__PURE__ */ React34.createElement(ColoredDot, { type: secretsInitialized ? "success" : "error" })),
14366
14796
  colorScheme,
14367
14797
  open: showSecrets,
14368
14798
  setOpen: setShowSecrets,
14369
- right: /* @__PURE__ */ React31.createElement(
14799
+ right: /* @__PURE__ */ React34.createElement("span", { style: { display: "flex", gap: "10px" } }, /* @__PURE__ */ React34.createElement(
14800
+ StateInspectorButton,
14801
+ {
14802
+ theme: theme3,
14803
+ onClick: () => {
14804
+ void secretManager.fetchSecrets();
14805
+ }
14806
+ },
14807
+ "Refresh"
14808
+ ), /* @__PURE__ */ React34.createElement(
14370
14809
  StateInspectorButton,
14371
14810
  {
14372
14811
  theme: theme3,
@@ -14379,9 +14818,9 @@ var StateInspector = memoGeneric(function StateInspector2({
14379
14818
  }
14380
14819
  },
14381
14820
  "Create"
14382
- )
14821
+ ))
14383
14822
  },
14384
- /* @__PURE__ */ React31.createElement(StateInspectorDisclosureRowInner, null, secrets.map((secret) => /* @__PURE__ */ React31.createElement(StateInspectorRow, { key: secret.id, colorScheme }, /* @__PURE__ */ React31.createElement(themedObjectInspector, { data: secret, theme: theme3 }), /* @__PURE__ */ React31.createElement(
14823
+ /* @__PURE__ */ React34.createElement(StateInspectorDisclosureRowInner, null, secrets.map((secret) => /* @__PURE__ */ React34.createElement(StateInspectorRow, { key: secret.id, colorScheme }, /* @__PURE__ */ React34.createElement(themedObjectInspector, { data: secret, theme: theme3 }), /* @__PURE__ */ React34.createElement(
14385
14824
  StateInspectorButton,
14386
14825
  {
14387
14826
  theme: theme3,
@@ -14390,15 +14829,24 @@ var StateInspector = memoGeneric(function StateInspector2({
14390
14829
  "Delete"
14391
14830
  ))))
14392
14831
  ),
14393
- advanced && /* @__PURE__ */ React31.createElement(
14832
+ advanced && /* @__PURE__ */ React34.createElement(
14833
+ GitSection,
14834
+ {
14835
+ showGit,
14836
+ setShowGit,
14837
+ colorScheme,
14838
+ gitManager
14839
+ }
14840
+ ),
14841
+ advanced && /* @__PURE__ */ React34.createElement(
14394
14842
  StateInspectorDisclosureSection,
14395
14843
  {
14396
14844
  open: showInputs,
14397
14845
  setOpen: setShowInputs,
14398
- title: /* @__PURE__ */ React31.createElement(StateInspectorTitleLabel, null, "Inputs", /* @__PURE__ */ React31.createElement(ColoredDot, { type: inputsInitialized ? "success" : "error" })),
14846
+ title: /* @__PURE__ */ React34.createElement(StateInspectorTitleLabel, null, "Inputs (", inputs.length, ")", /* @__PURE__ */ React34.createElement(ColoredDot, { type: inputsInitialized ? "success" : "error" })),
14399
14847
  colorScheme
14400
14848
  },
14401
- /* @__PURE__ */ React31.createElement(StateInspectorDisclosureRowInner, null, inputs?.map((input) => /* @__PURE__ */ React31.createElement(StateInspectorRow, { key: input.id, colorScheme }, /* @__PURE__ */ React31.createElement(themedObjectInspector, { data: input, theme: theme3 }))), !inputs?.length && /* @__PURE__ */ React31.createElement(
14849
+ /* @__PURE__ */ React34.createElement(StateInspectorDisclosureRowInner, null, inputs?.map((input) => /* @__PURE__ */ React34.createElement(StateInspectorRow, { key: input.id, colorScheme }, /* @__PURE__ */ React34.createElement(themedObjectInspector, { data: input, theme: theme3 }))), !inputs?.length && /* @__PURE__ */ React34.createElement(
14402
14850
  "div",
14403
14851
  {
14404
14852
  style: {
@@ -14409,15 +14857,15 @@ var StateInspector = memoGeneric(function StateInspector2({
14409
14857
  gap: "4px"
14410
14858
  }
14411
14859
  },
14412
- /* @__PURE__ */ React31.createElement("span", null, "No inputs")
14860
+ /* @__PURE__ */ React34.createElement("span", null, "No inputs")
14413
14861
  ))
14414
14862
  ),
14415
- advanced && /* @__PURE__ */ React31.createElement(
14863
+ advanced && /* @__PURE__ */ React34.createElement(
14416
14864
  StateInspectorDisclosureSection,
14417
14865
  {
14418
14866
  open: showOutputTransforms,
14419
14867
  setOpen: setShowOutputTransforms,
14420
- title: /* @__PURE__ */ React31.createElement(StateInspectorTitleLabel, null, "Output Transforms", /* @__PURE__ */ React31.createElement(
14868
+ title: /* @__PURE__ */ React34.createElement(StateInspectorTitleLabel, null, "Output Transforms (", outputTransforms.length, ")", /* @__PURE__ */ React34.createElement(
14421
14869
  ColoredDot,
14422
14870
  {
14423
14871
  type: outputTransformsInitialized ? "success" : "error"
@@ -14425,7 +14873,7 @@ var StateInspector = memoGeneric(function StateInspector2({
14425
14873
  )),
14426
14874
  colorScheme
14427
14875
  },
14428
- /* @__PURE__ */ React31.createElement(StateInspectorDisclosureRowInner, null, outputTransforms?.map((transform) => /* @__PURE__ */ React31.createElement(StateInspectorRow, { key: transform.id, colorScheme }, /* @__PURE__ */ React31.createElement(themedObjectInspector, { data: transform, theme: theme3 }))), !outputTransforms?.length && /* @__PURE__ */ React31.createElement(
14876
+ /* @__PURE__ */ React34.createElement(StateInspectorDisclosureRowInner, null, outputTransforms?.map((transform) => /* @__PURE__ */ React34.createElement(StateInspectorRow, { key: transform.id, colorScheme }, /* @__PURE__ */ React34.createElement(themedObjectInspector, { data: transform, theme: theme3 }))), !outputTransforms?.length && /* @__PURE__ */ React34.createElement(
14429
14877
  "div",
14430
14878
  {
14431
14879
  style: {
@@ -14436,10 +14884,10 @@ var StateInspector = memoGeneric(function StateInspector2({
14436
14884
  gap: "4px"
14437
14885
  }
14438
14886
  },
14439
- /* @__PURE__ */ React31.createElement("span", null, "No output transforms")
14887
+ /* @__PURE__ */ React34.createElement("span", null, "No output transforms")
14440
14888
  ))
14441
14889
  ),
14442
- advanced && /* @__PURE__ */ React31.createElement(
14890
+ advanced && /* @__PURE__ */ React34.createElement(
14443
14891
  StateInspectorDisclosureSection,
14444
14892
  {
14445
14893
  title: "Tasks",
@@ -14447,7 +14895,7 @@ var StateInspector = memoGeneric(function StateInspector2({
14447
14895
  open: showTasks,
14448
14896
  setOpen: setShowTasks
14449
14897
  },
14450
- /* @__PURE__ */ React31.createElement(StateInspectorDisclosureRowInner, null, tasks?.map((task) => /* @__PURE__ */ React31.createElement(
14898
+ /* @__PURE__ */ React34.createElement(StateInspectorDisclosureRowInner, null, tasks?.map((task) => /* @__PURE__ */ React34.createElement(
14451
14899
  StateInspectorRow,
14452
14900
  {
14453
14901
  key: task.id,
@@ -14456,7 +14904,7 @@ var StateInspector = memoGeneric(function StateInspector2({
14456
14904
  backgroundColor: task.status === "done" ? "rgba(0,255,0,0.2)" : task.status === "error" ? "rgba(255,0,0,0.2)" : void 0
14457
14905
  }
14458
14906
  },
14459
- /* @__PURE__ */ React31.createElement(
14907
+ /* @__PURE__ */ React34.createElement(
14460
14908
  themedObjectInspector,
14461
14909
  {
14462
14910
  name: task.name,
@@ -14466,7 +14914,7 @@ var StateInspector = memoGeneric(function StateInspector2({
14466
14914
  )
14467
14915
  )))
14468
14916
  ),
14469
- /* @__PURE__ */ React31.createElement(
14917
+ /* @__PURE__ */ React34.createElement(
14470
14918
  StateInspectorDisclosureSection,
14471
14919
  {
14472
14920
  open: showShared,
@@ -14474,7 +14922,7 @@ var StateInspector = memoGeneric(function StateInspector2({
14474
14922
  title: "Shared Connection Data",
14475
14923
  colorScheme
14476
14924
  },
14477
- /* @__PURE__ */ React31.createElement(StateInspectorDisclosureRowInner, null, Object.entries(shared).map(([key, value]) => /* @__PURE__ */ React31.createElement(StateInspectorRow, { key, colorScheme }, /* @__PURE__ */ React31.createElement(
14925
+ /* @__PURE__ */ React34.createElement(StateInspectorDisclosureRowInner, null, Object.entries(shared).map(([key, value]) => /* @__PURE__ */ React34.createElement(StateInspectorRow, { key, colorScheme }, /* @__PURE__ */ React34.createElement(
14478
14926
  themedObjectInspector,
14479
14927
  {
14480
14928
  name: key,
@@ -14484,7 +14932,7 @@ var StateInspector = memoGeneric(function StateInspector2({
14484
14932
  }
14485
14933
  ))))
14486
14934
  ),
14487
- /* @__PURE__ */ React31.createElement(
14935
+ /* @__PURE__ */ React34.createElement(
14488
14936
  ServerScriptLogsSection,
14489
14937
  {
14490
14938
  colorScheme,
@@ -14496,7 +14944,44 @@ var StateInspector = memoGeneric(function StateInspector2({
14496
14944
  containerRef: serverLogsContainerRef
14497
14945
  }
14498
14946
  ),
14499
- advanced && /* @__PURE__ */ React31.createElement(
14947
+ showSimulationLogsSection && /* @__PURE__ */ React34.createElement(
14948
+ ServerScriptLogsSection,
14949
+ {
14950
+ title: "Server Script Simulation Logs",
14951
+ colorScheme,
14952
+ showLogs: showServerSimulationLogs,
14953
+ setShowLogs: setShowServerSimulationLogs,
14954
+ logs: visibleServerSimulationLogs,
14955
+ paused: serverSimulationLogsPaused,
14956
+ onTogglePaused: toggleServerSimulationLogsPaused,
14957
+ containerRef: serverSimulationLogsContainerRef
14958
+ }
14959
+ ),
14960
+ /* @__PURE__ */ React34.createElement(
14961
+ StateInspectorDisclosureSection,
14962
+ {
14963
+ open: showSimulation,
14964
+ setOpen: setShowSimulation,
14965
+ title: "Server Simulation",
14966
+ colorScheme
14967
+ },
14968
+ /* @__PURE__ */ React34.createElement(StateInspectorDisclosureRowInner, null, /* @__PURE__ */ React34.createElement(StateInspectorRow, { colorScheme }, /* @__PURE__ */ React34.createElement(
14969
+ themedObjectInspector,
14970
+ {
14971
+ name: "status",
14972
+ data: simulationDiagnostics ?? {
14973
+ simulateLocally: false,
14974
+ simulatorActive: false,
14975
+ clockSkewMs: 0,
14976
+ invocations: [],
14977
+ pendingPredictions: []
14978
+ },
14979
+ theme: theme3,
14980
+ expandLevel: 2
14981
+ }
14982
+ )))
14983
+ ),
14984
+ advanced && /* @__PURE__ */ React34.createElement(
14500
14985
  ActivityEventsSection,
14501
14986
  {
14502
14987
  colorScheme,
@@ -14506,10 +14991,12 @@ var StateInspector = memoGeneric(function StateInspector2({
14506
14991
  activityEventsManager
14507
14992
  }
14508
14993
  ),
14509
- /* @__PURE__ */ React31.createElement(
14994
+ /* @__PURE__ */ React34.createElement(
14510
14995
  EventsSection,
14511
14996
  {
14512
- connectionEvents,
14997
+ connectionEvents: visibleConnectionEvents,
14998
+ paused: connectionEventsPaused,
14999
+ onTogglePaused: toggleConnectionEventsPaused,
14513
15000
  colorScheme,
14514
15001
  eventsContainerRef,
14515
15002
  showEvents,
@@ -14518,7 +15005,7 @@ var StateInspector = memoGeneric(function StateInspector2({
14518
15005
  )
14519
15006
  );
14520
15007
  });
14521
- var truncateAsset = memoize2((asset) => {
15008
+ var truncateAsset = memoize((asset) => {
14522
15009
  if (asset.url.startsWith("data:") || asset.url.startsWith("blob:")) {
14523
15010
  return { ...asset, url: ellipsis(asset.url, 40) };
14524
15011
  }
@@ -14535,15 +15022,15 @@ function useManagedHistory(stateManager) {
14535
15022
  }
14536
15023
 
14537
15024
  // ../noya-multiplayer-react/src/singleton.tsx
14538
- import React34 from "react";
15025
+ import React36 from "react";
14539
15026
 
14540
15027
  // ../noya-multiplayer-react/src/NoyaStateContext.tsx
14541
15028
  var AnyNoyaStateContext = createContext3(void 0);
14542
15029
  var emptyArray = [];
14543
15030
  function useActivityEventsForManager(streamFilter, activityEventsManager) {
14544
- const [streamId, setStreamId] = useState17(void 0);
15031
+ const [streamId, setStreamId] = useState18(void 0);
14545
15032
  const stableStreamFilter = useJsonMemo(streamFilter);
14546
- useEffect16(() => {
15033
+ useEffect17(() => {
14547
15034
  if (!stableStreamFilter) return;
14548
15035
  const streamId2 = activityEventsManager.subscribe(stableStreamFilter);
14549
15036
  setStreamId(streamId2);
@@ -14557,8 +15044,8 @@ function useActivityEventsForManager(streamFilter, activityEventsManager) {
14557
15044
  }
14558
15045
 
14559
15046
  // ../noya-multiplayer-react/src/components/UserPointersOverlay.tsx
14560
- import { Observable as Observable22 } from "@noya-app/observable";
14561
- import React36, { useEffect as useEffect18, useMemo as useMemo12, useState as useState18 } from "react";
15047
+ import { Observable as Observable24 } from "@noya-app/observable";
15048
+ import React38, { useEffect as useEffect19, useMemo as useMemo12, useState as useState19 } from "react";
14562
15049
  function shouldShow(hideAfter, updatedAt) {
14563
15050
  return !!updatedAt && Date.now() - updatedAt < hideAfter;
14564
15051
  }
@@ -14571,15 +15058,15 @@ var UserPointerInternal = memoGeneric(function UserPointerInternal2({
14571
15058
  const observable = useMemo12(() => {
14572
15059
  const metadata$ = sharedConnectionDataManager.metadata$.observePath([user.connectionId]).throttle(50);
14573
15060
  const data$ = sharedConnectionDataManager.data$.observePath([user.connectionId]).throttle(50);
14574
- return Observable22.combine([metadata$, data$], ([metadata2, data2]) => {
15061
+ return Observable24.combine([metadata$, data$], ([metadata2, data2]) => {
14575
15062
  return { metadata: metadata2, data: data2 };
14576
15063
  });
14577
15064
  }, [sharedConnectionDataManager, user.connectionId]);
14578
15065
  const { metadata, data } = useObservable2(observable);
14579
- const [, setForceUpdate] = useState18(0);
15066
+ const [, setForceUpdate] = useState19(0);
14580
15067
  const updatedAt = metadata?.updatedAt ?? 0;
14581
15068
  const show = shouldShow(hideAfter, updatedAt);
14582
- useEffect18(() => {
15069
+ useEffect19(() => {
14583
15070
  if (!show) return;
14584
15071
  const timeoutId = setTimeout(() => {
14585
15072
  setForceUpdate((prev) => prev + 1);
@@ -14603,9 +15090,9 @@ var UserPointersOverlay = memoGeneric(function UserPointers({
14603
15090
  sharedConnectionDataManager.currentConnectionId$
14604
15091
  );
14605
15092
  const connectedUsers = useObservable2(userManager.connectedUsers$);
14606
- return /* @__PURE__ */ React36.createElement(React36.Fragment, null, connectedUsers.map((user) => {
15093
+ return /* @__PURE__ */ React38.createElement(React38.Fragment, null, connectedUsers.map((user) => {
14607
15094
  if (user.connectionId === currentConnectionId) return null;
14608
- return /* @__PURE__ */ React36.createElement(
15095
+ return /* @__PURE__ */ React38.createElement(
14609
15096
  UserPointerInternal,
14610
15097
  {
14611
15098
  key: user.connectionId,
@@ -14621,7 +15108,7 @@ var UserPointersOverlay = memoGeneric(function UserPointers({
14621
15108
  import {
14622
15109
  RefetchableObservable
14623
15110
  } from "@noya-app/observable-store";
14624
- import { useCallback as useCallback15, useEffect as useEffect19, useMemo as useMemo13 } from "react";
15111
+ import { useCallback as useCallback15, useEffect as useEffect20, useMemo as useMemo13 } from "react";
14625
15112
  function useTable(table, {
14626
15113
  where,
14627
15114
  select
@@ -14665,7 +15152,7 @@ function useTable(table, {
14665
15152
  }
14666
15153
  );
14667
15154
  }, [stableSelect, stableWhere, table, options.policy, options.debug]);
14668
- useEffect19(() => {
15155
+ useEffect20(() => {
14669
15156
  observable.start?.();
14670
15157
  }, [observable]);
14671
15158
  const { status, data } = useObservable2(observable);
@@ -14764,11 +15251,6 @@ export {
14764
15251
  useActivityEventsList,
14765
15252
  useFileList,
14766
15253
  useFileListItem,
14767
- useGeneratedComponentDescription,
14768
- useGeneratedComponentDescriptions,
14769
- useGeneratedComponentNames,
14770
- useGeneratedPageComponentNames,
14771
- useGeneratedPageNames,
14772
15254
  useIsBeta,
14773
15255
  useMetadata,
14774
15256
  useNetworkRequests,
@@ -14800,8 +15282,6 @@ export {
14800
15282
  useOptionalNoyaTags,
14801
15283
  useOptionalNoyaTools,
14802
15284
  useOptionalNoyaUserData,
14803
- useRandomIcons,
14804
- useRandomImages,
14805
15285
  useResourcesList,
14806
15286
  useTable,
14807
15287
  useUser