deepspace 0.28.1 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -4500,59 +4500,10 @@ interface UseCheckoutReturn {
4500
4500
  }
4501
4501
  declare function useCheckout(opts?: UseCheckoutOpts): UseCheckoutReturn;
4502
4502
 
4503
- /**
4504
- * Client-side error reporter (opt-in) — the browser half of client-side error
4505
- * reporting.
4506
- *
4507
- * // src/main.tsx (or your root)
4508
- * import { installClientErrorReporter } from 'deepspace'
4509
- * installClientErrorReporter()
4510
- *
4511
- * Hooks `window` 'error' + 'unhandledrejection' and forwards each to the app's
4512
- * own Worker (see `registerClientErrorRoute` in 'deepspace/worker'), where it
4513
- * lands in Workers Logs and shows up in `deepspace logs` tagged CLIENT.
4514
- *
4515
- * Best-effort by contract: it dedupes, caps how many it sends per page load,
4516
- * and NEVER throws — a broken reporter must not break the app it watches.
4517
- */
4518
- interface ClientErrorReporterOptions {
4519
- /** Override the ingestion path (default `/_deepspace/client-errors`). */
4520
- endpoint?: string;
4521
- /** Max reports sent per page load — a runaway loop can't flood (default 50). */
4522
- maxReports?: number;
4523
- }
4524
- /**
4525
- * Install global handlers that forward uncaught browser errors to the app's
4526
- * Worker. No-op outside a browser. Returns an uninstall function.
4527
- */
4528
- declare function installClientErrorReporter(options?: ClientErrorReporterOptions): () => void;
4529
- /**
4530
- * Manually report a caught error — e.g. from a React error boundary's
4531
- * `componentDidCatch`. No-op outside a browser; never throws. Unlike the
4532
- * auto-installed handlers this has no client-side dedupe/cap — it relies on the
4533
- * ingestion route's per-isolate throttle — so call it from boundaries (which
4534
- * unmount rather than loop), not a hot path.
4535
- */
4536
- declare function reportClientError(error: unknown, options?: ClientErrorReporterOptions & {
4537
- componentStack?: string;
4538
- }): void;
4539
-
4540
- type ClientErrorKind = 'error' | 'unhandledrejection' | 'react';
4541
- /** A sanitized, capped browser-error report — the wire + log-line payload. */
4542
- interface ClientErrorReport {
4543
- kind: ClientErrorKind;
4544
- message: string;
4545
- name?: string;
4546
- stack?: string;
4547
- /** Page URL where it fired (href or the script filename). */
4548
- url?: string;
4549
- line?: number;
4550
- col?: number;
4551
- }
4552
-
4553
4503
  /**
4554
4504
  * `deepspace logs` wire DTO — the single source of truth for the whitelisted
4555
- * shape the platform telemetry reader emits and every consumer reads.
4505
+ * shape the platform telemetry reader emits and every consumer reads, plus
4506
+ * the one plain-text rendering of it (`logEventText`).
4556
4507
  *
4557
4508
  * The producer is `platform/deploy-worker/src/lib/workers-logs.ts` (which
4558
4509
  * rebuilds each event field-by-field from a raw Cloudflare row — see the
@@ -4560,8 +4511,9 @@ interface ClientErrorReport {
4560
4511
  * (`cli/commands/logs.ts`), the dashboard Logs panel
4561
4512
  * (`apps/dashboard/src/lib/apps.ts`), and the e2e whitelist assertion
4562
4513
  * (`tests/e2e/tests/logs.spec.ts`). This module used to be hand-mirrored in
4563
- * all four places; `source` was added to three of them and missed in the
4564
- * e2e whitelist, so it now lives here once and they import it.
4514
+ * all four places, and the copies drifted for real: a field addition (the
4515
+ * since-removed `source`) landed in three of them and missed the e2e
4516
+ * whitelist. It now lives here once and they import it.
4565
4517
  *
4566
4518
  * Isomorphic — no DOM, no Hono, no platform types — so it re-exports cleanly
4567
4519
  * from both `deepspace` (client) and `deepspace/worker` and is safe to import
@@ -4578,13 +4530,6 @@ interface AppLogEvent {
4578
4530
  level: LogLevel;
4579
4531
  eventType: 'log' | 'request' | 'exception' | 'other';
4580
4532
  message: string;
4581
- /**
4582
- * Present (= `'client'`) only for a browser-forwarded error the app's own
4583
- * Worker re-logged via `registerClientErrorRoute`. Absent means the log was
4584
- * emitted server-side — there is no explicit `'server'` value, so consumers
4585
- * branch on `source === 'client'`, never on a truthy/other check.
4586
- */
4587
- source?: 'client';
4588
4533
  /**
4589
4534
  * The runtime's verdict on the invocation (`ok`, `exception`, `exceededCpu`,
4590
4535
  * `canceled`, …) — present on `request` and other invocation-summary events
@@ -4601,11 +4546,11 @@ interface AppLogEvent {
4601
4546
  status?: number;
4602
4547
  };
4603
4548
  /**
4604
- * The exception that ESCAPED the Worker (`eventType: 'exception'`), or a
4605
- * browser-reported one (`source: 'client'`). An error the app catches and
4606
- * `console.error`s is a plain `log` line — and the Workers runtime renders a
4607
- * logged Error object as its stack frames without the message, so log the
4608
- * message text yourself (`console.error(\`… ${err.message}\`, err.stack)`).
4549
+ * The exception that ESCAPED the Worker (`eventType: 'exception'`). An
4550
+ * error the app catches and `console.error`s is a plain `log` line — and
4551
+ * the Workers runtime renders a logged Error OBJECT as its stack frames
4552
+ * without the message, so render it through `loggableError(err)` (below):
4553
+ * message first, bounded cause chain, capped at the reader's budget.
4609
4554
  */
4610
4555
  exception?: {
4611
4556
  name: string;
@@ -4635,8 +4580,52 @@ interface AppLogsResponse {
4635
4580
  * (deploy-worker/CLI/dashboard, which import it), while the e2e mirror remains a
4636
4581
  * knowingly-accepted duplicate.
4637
4582
  */
4638
- declare const APP_LOG_EVENT_KEYS: readonly ["id", "timestamp", "level", "eventType", "message", "source", "outcome", "request", "exception"];
4583
+ declare const APP_LOG_EVENT_KEYS: readonly ["id", "timestamp", "level", "eventType", "message", "outcome", "request", "exception"];
4639
4584
  type AppLogEventKey = (typeof APP_LOG_EVENT_KEYS)[number];
4585
+ /**
4586
+ * One event → its plain-text body: what the event *says*, with no colors,
4587
+ * tags, timestamps, or stack frames — those belong to each renderer. Shared
4588
+ * by the CLI line formatter and the dashboard rows (which also use it as the
4589
+ * search corpus), so "does this event mention X" means the same thing in
4590
+ * both.
4591
+ */
4592
+ declare function logEventText(e: AppLogEvent): string;
4593
+ /**
4594
+ * An error as a string that survives Workers Logs ingestion. The telemetry
4595
+ * pipeline serializes a logged Error OBJECT down to its stack FRAMES — the
4596
+ * `Error: <message>` first line is dropped (observed 2026-08; Hono's default
4597
+ * handler does exactly `console.error(err)`, which is why an uncaught route
4598
+ * error showed up in `deepspace logs` as bare frames). A STRING passes
4599
+ * through verbatim. V8 stacks already open with `Error: <message>` (prefix
4600
+ * test, not substring); frames-only stacks get the header prepended; a
4601
+ * missing stack degrades to the header alone. `cause` chains and
4602
+ * `AggregateError.errors` are walked (bounded, cycle-safe) because the only
4603
+ * actionable text of the most common Workers error — `TypeError: fetch
4604
+ * failed` — lives there. Rendering is budgeted at every step: pieces are
4605
+ * sliced and the walk stops once MAX_LOG_TEXT_LENGTH is reached (error text
4606
+ * is often request-derived, and unbounded intermediates measured >100 MB on
4607
+ * hostile chains), and the final string never exceeds the budget the reader
4608
+ * truncates at (a call-site prefix can still push a full-budget line past
4609
+ * it — the reader re-cuts with the same `truncateLogText`). Never throws: a
4610
+ * hostile NODE (throwing getters, revoked Proxies, null-prototype
4611
+ * throwables) degrades to a tag IN PLACE so the rest of the render — the
4612
+ * part with the actionable message — survives. So:
4613
+ * `console.error(loggableError(err))`, never `console.error(err)`.
4614
+ */
4615
+ declare function loggableError(err: unknown): string;
4616
+ /**
4617
+ * Cut a string to `MAX_LOG_TEXT_LENGTH` INCLUDING the truncation marker —
4618
+ * the one truncation for log text, shared by the write side (`loggableError`)
4619
+ * and the read side (the deploy-worker reader's per-field cap), so the two
4620
+ * cannot drift. Steps back off a high surrogate so the cut never leaves a
4621
+ * lone half of a surrogate pair in the log line.
4622
+ */
4623
+ declare function truncateLogText(s: string): string;
4624
+ /** The one write-side budget for rendered error text, matching the reader's
4625
+ * per-field cap (the deploy-worker's log reader imports this so the two
4626
+ * sides cannot drift). The rendered string INCLUDING any truncation marker
4627
+ * stays within it. */
4628
+ declare const MAX_LOG_TEXT_LENGTH: number;
4640
4629
 
4641
4630
  /**
4642
4631
  * The customer-visible storage schedule, in bytes, PER ACCOUNT — the total an
@@ -4660,4 +4649,4 @@ declare const ACCOUNT_STORAGE_LIMIT_BYTES: {
4660
4649
  declare function storageLimitForTier(tier: string | null | undefined): number;
4661
4650
  declare function formatBytes(bytes: number): string;
4662
4651
 
4663
- export { ACCOUNT_STORAGE_LIMIT_BYTES, ACTION_ROUTES_BEARER_GUARD_MIGRATION_ID, ACTION_TOOLS_DELETE_WHERE_MIGRATION_ID, ANONYMOUS_USER_ID_PREFIX, APP_LOG_EVENT_KEYS, ASYNC_RESOURCE_DEFAULTS, type AdHocChargeOpts, type AiStreamAction, type AiStreamChunk, type ApiErrorIssue, type AppLogEvent, type AppLogEventKey, type AppLogsResponse, type AppMigrationIdsValidation, type AsyncResourceDefaults, type AsyncResourceState, type AsyncResourceStatus, AuthGate, type AuthGateProps, AuthOverlay, Awareness, type AwarenessState, type AwarenessStates, BUILD_INJECTED_APP_ID_MIGRATION_ID, type BaseMessage, type CanvasShapeClient, type Channel, type ChannelMember, type ChargeOnceOpts, type ChargeOnceResult, type ClientErrorKind, type ClientErrorReport, type ClientErrorReporterOptions, type ClientMessage, type CollectionSchema, type ConnectionAttachment, type ConnectionStatus, type CronHistoryEntry, type CronMutationResult, type CronTaskState, DEEPSPACE_AGENT_PROFILES, DEEPSPACE_AI_DEFAULTS, DEEPSPACE_AI_MODELS, DEEPSPACE_MODEL_CATALOG_PROVENANCE, DEEPSPACE_THEME_PROPERTIES, DEFAULT_USER_COLORS, type DeepSpaceAIModel, type DeepSpaceAIModelId, type DeepSpaceAIProvider, type DeepSpaceAgentProfile, type DeepSpaceAgentProfileId, type DeepSpaceAgentSupport, DeepSpaceAuthProvider, type DeepSpaceThemeConfig, DeepSpaceThemeProvider, type DeepSpaceThemeProviderProps, type DeriveLoadStateInput, ENV, type Environment, type FileAttachment, type GroupedReaction, GuestBanner, type HandlerContext, type IntegrationResponse, type JobStatusView, type JobView, LOG_LEVELS, type LoadState, type LoadStateAuthInput, type LoadStateStatusInput, type LogLevel, MSG, MSG_AWARENESS, MSG_SYNC, MSG_SYNC_STEP1, MSG_SYNC_STEP2, MSG_SYNC_UPDATE, MSG_YJS_AWARENESS, MSG_YJS_SYNC, type Message, type MessageHandlers, type MsgType, type NormalizedApiError, type PagedResourceFetchArgs, type PagedResourcePage, type PagedResourceState, type PagedResourceStatus, type PlanInfo, PlatformApiError, type PresencePeerClient, PricingTable, type PricingTablePlan, type PricingTablePrice, type ProductChargeOpts, type ProtocolMessage, type Purchase, type Query, type R2FileInfo, type R2FileListPage, type R2Scope, type R2UploadResult, RECORD_NOT_FOUND, ROLES, ROLE_ADMIN, ROLE_ANONYMOUS, ROLE_CONFIG, ROLE_DEFAULT, type Reaction, type ReadReceipt, type RecordData, RecordProvider, type RecordProviderProps, RecordRoomNotReadyError, RecordScope, type RequestOptions, type ResolvedDeepSpaceAgentModel, type Role, type RoomUser, SECURE_ROOM_BOUNDARIES_MIGRATION_ID, type ScopeEntry, ScopeRegistryProvider, type ServerMessage, SignedIn, SignedOut, type SubscribeOpts, type SubscribeResult, type SubscriptionState, type SubscriptionStatus, type SyncResult, type UseAsyncResourceOptions, type UseAuthProfileReadyOptions, type UseAuthStatusOptions, type UseCanvasResult, type UseCheckoutOpts, type UseCronMonitorResult, type UseJobsResult, type UsePagedResourceOptions, type UsePresenceRoomResult, type UseR2FilesReturn, type UseVoiceAgentOptions, type UseVoiceAgentResult, type UseYjsFieldResult, type UseYjsRoomResult, type UseYjsTextResult, type User, type UserCredits, type UserInfo, type UserKarma, type UserProfile, type ViewportClient, type VoiceStatus, type VoiceTranscriptEntry, WORKER_OWNED_NOT_FOUND_MIGRATION_ID, type WriteError, applyDeepSpaceTheme, applyUIThemeTokens, authClient, canAutoLoadPagedResource, clampPagedResourceItems, clearAuthToken, clearDeepSpaceTheme, clientBuild, createDecoder, createEncoder, decodeAiStreamChunk, deriveLoadState, detectEnvironment, dispatch, encode, encodeAwarenessMessage, encodeSyncStep1, encodeSyncStep2, encodeUpdate, formatBytes, formatFileSize, getApiUrl, getAuthToken, getAuthUrl, getDeepSpaceAIModel, getEnvironmentConfig, getMessageType, getPagedResourceCooldownMs, getPlatformWorkerUrl, getUserColor, handleAwarenessMessage, handleSyncMessage, hasContent, installClientErrorReporter, integration, isAnonymousUserId, isAsyncResourceSlow, isDarkColor, isImageFile, isLocalDev, isProduction, isWriterRole, listDeepSpaceAgentModels, parseSseLine, readThemeFromDOM, readVarUint, readVarUint8Array, reportClientError, resetEnvironmentCache, resolveDeepSpaceAgentModel, serverBuild, signIn, signOut, storageLimitForTier, toConnectionStatus, toUint8Array, useAsyncResource, useAuth, useAuthProfileReady, useAuthStatus, useAuthUser, useCanvas, useChannelMembers, useChannels, useCheckout, useCronMonitor, useDisplayName, useIsDarkTheme, useJobs, useMessages, useMutations, usePagedResource, usePresence, usePresenceRoom, useQuery, useR2Files, useReactions, useReadReceipts, useRecordContext, useSession, useSubscription, useUser, useUserLookup, useUsers, useVoiceAgent, useYjsField, useYjsRoom, useYjsText, validateAppMigrationIds, writeVarUint, writeVarUint8Array };
4652
+ export { ACCOUNT_STORAGE_LIMIT_BYTES, ACTION_ROUTES_BEARER_GUARD_MIGRATION_ID, ACTION_TOOLS_DELETE_WHERE_MIGRATION_ID, ANONYMOUS_USER_ID_PREFIX, APP_LOG_EVENT_KEYS, ASYNC_RESOURCE_DEFAULTS, type AdHocChargeOpts, type AiStreamAction, type AiStreamChunk, type ApiErrorIssue, type AppLogEvent, type AppLogEventKey, type AppLogsResponse, type AppMigrationIdsValidation, type AsyncResourceDefaults, type AsyncResourceState, type AsyncResourceStatus, AuthGate, type AuthGateProps, AuthOverlay, Awareness, type AwarenessState, type AwarenessStates, BUILD_INJECTED_APP_ID_MIGRATION_ID, type BaseMessage, type CanvasShapeClient, type Channel, type ChannelMember, type ChargeOnceOpts, type ChargeOnceResult, type ClientMessage, type CollectionSchema, type ConnectionAttachment, type ConnectionStatus, type CronHistoryEntry, type CronMutationResult, type CronTaskState, DEEPSPACE_AGENT_PROFILES, DEEPSPACE_AI_DEFAULTS, DEEPSPACE_AI_MODELS, DEEPSPACE_MODEL_CATALOG_PROVENANCE, DEEPSPACE_THEME_PROPERTIES, DEFAULT_USER_COLORS, type DeepSpaceAIModel, type DeepSpaceAIModelId, type DeepSpaceAIProvider, type DeepSpaceAgentProfile, type DeepSpaceAgentProfileId, type DeepSpaceAgentSupport, DeepSpaceAuthProvider, type DeepSpaceThemeConfig, DeepSpaceThemeProvider, type DeepSpaceThemeProviderProps, type DeriveLoadStateInput, ENV, type Environment, type FileAttachment, type GroupedReaction, GuestBanner, type HandlerContext, type IntegrationResponse, type JobStatusView, type JobView, LOG_LEVELS, type LoadState, type LoadStateAuthInput, type LoadStateStatusInput, type LogLevel, MAX_LOG_TEXT_LENGTH, MSG, MSG_AWARENESS, MSG_SYNC, MSG_SYNC_STEP1, MSG_SYNC_STEP2, MSG_SYNC_UPDATE, MSG_YJS_AWARENESS, MSG_YJS_SYNC, type Message, type MessageHandlers, type MsgType, type NormalizedApiError, type PagedResourceFetchArgs, type PagedResourcePage, type PagedResourceState, type PagedResourceStatus, type PlanInfo, PlatformApiError, type PresencePeerClient, PricingTable, type PricingTablePlan, type PricingTablePrice, type ProductChargeOpts, type ProtocolMessage, type Purchase, type Query, type R2FileInfo, type R2FileListPage, type R2Scope, type R2UploadResult, RECORD_NOT_FOUND, ROLES, ROLE_ADMIN, ROLE_ANONYMOUS, ROLE_CONFIG, ROLE_DEFAULT, type Reaction, type ReadReceipt, type RecordData, RecordProvider, type RecordProviderProps, RecordRoomNotReadyError, RecordScope, type RequestOptions, type ResolvedDeepSpaceAgentModel, type Role, type RoomUser, SECURE_ROOM_BOUNDARIES_MIGRATION_ID, type ScopeEntry, ScopeRegistryProvider, type ServerMessage, SignedIn, SignedOut, type SubscribeOpts, type SubscribeResult, type SubscriptionState, type SubscriptionStatus, type SyncResult, type UseAsyncResourceOptions, type UseAuthProfileReadyOptions, type UseAuthStatusOptions, type UseCanvasResult, type UseCheckoutOpts, type UseCronMonitorResult, type UseJobsResult, type UsePagedResourceOptions, type UsePresenceRoomResult, type UseR2FilesReturn, type UseVoiceAgentOptions, type UseVoiceAgentResult, type UseYjsFieldResult, type UseYjsRoomResult, type UseYjsTextResult, type User, type UserCredits, type UserInfo, type UserKarma, type UserProfile, type ViewportClient, type VoiceStatus, type VoiceTranscriptEntry, WORKER_OWNED_NOT_FOUND_MIGRATION_ID, type WriteError, applyDeepSpaceTheme, applyUIThemeTokens, authClient, canAutoLoadPagedResource, clampPagedResourceItems, clearAuthToken, clearDeepSpaceTheme, clientBuild, createDecoder, createEncoder, decodeAiStreamChunk, deriveLoadState, detectEnvironment, dispatch, encode, encodeAwarenessMessage, encodeSyncStep1, encodeSyncStep2, encodeUpdate, formatBytes, formatFileSize, getApiUrl, getAuthToken, getAuthUrl, getDeepSpaceAIModel, getEnvironmentConfig, getMessageType, getPagedResourceCooldownMs, getPlatformWorkerUrl, getUserColor, handleAwarenessMessage, handleSyncMessage, hasContent, integration, isAnonymousUserId, isAsyncResourceSlow, isDarkColor, isImageFile, isLocalDev, isProduction, isWriterRole, listDeepSpaceAgentModels, logEventText, loggableError, parseSseLine, readThemeFromDOM, readVarUint, readVarUint8Array, resetEnvironmentCache, resolveDeepSpaceAgentModel, serverBuild, signIn, signOut, storageLimitForTier, toConnectionStatus, toUint8Array, truncateLogText, useAsyncResource, useAuth, useAuthProfileReady, useAuthStatus, useAuthUser, useCanvas, useChannelMembers, useChannels, useCheckout, useCronMonitor, useDisplayName, useIsDarkTheme, useJobs, useMessages, useMutations, usePagedResource, usePresence, usePresenceRoom, useQuery, useR2Files, useReactions, useReadReceipts, useRecordContext, useSession, useSubscription, useUser, useUserLookup, useUsers, useVoiceAgent, useYjsField, useYjsRoom, useYjsText, validateAppMigrationIds, writeVarUint, writeVarUint8Array };
package/dist/index.js CHANGED
@@ -5567,149 +5567,115 @@ function useCheckout(opts) {
5567
5567
  };
5568
5568
  }
5569
5569
 
5570
- // src/shared/client-errors.ts
5571
- var CLIENT_ERROR_PATH = "/_deepspace/client-errors";
5572
- var CLIENT_ERROR_CAPS = {
5573
- message: 1024,
5574
- stack: 4096,
5575
- name: 256,
5576
- url: 512
5577
- };
5578
- function capText(value, max) {
5579
- if (typeof value !== "string") return void 0;
5580
- return value.length > max ? value.slice(0, max) : value;
5581
- }
5582
- function finiteNumber(value) {
5583
- return typeof value === "number" && Number.isFinite(value) ? value : void 0;
5584
- }
5585
- function normalizeClientErrorReport(raw) {
5586
- if (typeof raw !== "object" || raw === null) return null;
5587
- const o = raw;
5588
- const kind = o.kind === "unhandledrejection" || o.kind === "react" ? o.kind : "error";
5589
- const message = capText(o.message, CLIENT_ERROR_CAPS.message) ?? "";
5590
- const name = capText(o.name, CLIENT_ERROR_CAPS.name);
5591
- const stack = capText(o.stack, CLIENT_ERROR_CAPS.stack);
5592
- const url = capText(o.url, CLIENT_ERROR_CAPS.url);
5593
- const line = finiteNumber(o.line);
5594
- const col = finiteNumber(o.col);
5595
- if (!message && !stack) return null;
5596
- const report = { kind, message: message || (name ?? "Error") };
5597
- if (name) report.name = name;
5598
- if (stack) report.stack = stack;
5599
- if (url) report.url = url;
5600
- if (line !== void 0) report.line = line;
5601
- if (col !== void 0) report.col = col;
5602
- return report;
5570
+ // src/shared/log-events.ts
5571
+ var LOG_LEVELS = ["debug", "log", "info", "warn", "error"];
5572
+ var APP_LOG_EVENT_KEYS = [
5573
+ "id",
5574
+ "timestamp",
5575
+ "level",
5576
+ "eventType",
5577
+ "message",
5578
+ "outcome",
5579
+ "request",
5580
+ "exception"
5581
+ ];
5582
+ function logEventText(e) {
5583
+ if (e.eventType === "exception" && e.exception) {
5584
+ const where = e.request ? ` \u2014 ${e.request.method} ${e.request.path}` : "";
5585
+ return `${e.exception.name}: ${e.exception.message}${where}`;
5586
+ }
5587
+ if (e.eventType === "request" && e.request) {
5588
+ const status = e.request.status !== void 0 ? ` ${e.request.status}` : "";
5589
+ const outcome = e.outcome && e.outcome !== "ok" ? ` (${e.outcome})` : "";
5590
+ return `${e.request.method} ${e.request.path}${status}${outcome}`;
5591
+ }
5592
+ return e.message;
5603
5593
  }
5604
-
5605
- // src/client/errors.ts
5606
- function stripQuery(u) {
5607
- if (!u) return void 0;
5594
+ function loggableError(err) {
5608
5595
  try {
5609
- const parsed = new URL(u, window.location?.href);
5610
- return parsed.origin + parsed.pathname;
5596
+ return truncateLogText(renderError(err, 0));
5611
5597
  } catch {
5612
- return void 0;
5598
+ return tagOf(err);
5613
5599
  }
5614
5600
  }
5615
- function post(endpoint, report) {
5601
+ function truncateLogText(s) {
5602
+ if (s.length <= MAX_LOG_TEXT_LENGTH) return s;
5603
+ let cut = MAX_LOG_TEXT_LENGTH - TRUNCATION_MARKER.length;
5604
+ const last = s.charCodeAt(cut - 1);
5605
+ if (last >= 55296 && last <= 56319) cut -= 1;
5606
+ return s.slice(0, cut) + TRUNCATION_MARKER;
5607
+ }
5608
+ var MAX_LOG_TEXT_LENGTH = 8 * 1024;
5609
+ var TRUNCATION_MARKER = "\u2026 [truncated]";
5610
+ var MAX_CAUSE_DEPTH = 4;
5611
+ function tagOf(err) {
5616
5612
  try {
5617
- void fetch(endpoint, {
5618
- method: "POST",
5619
- keepalive: true,
5620
- headers: { "Content-Type": "application/json" },
5621
- body: JSON.stringify(report)
5622
- }).catch(() => {
5623
- });
5613
+ return Object.prototype.toString.call(err);
5624
5614
  } catch {
5615
+ return "[unloggable error]";
5625
5616
  }
5626
5617
  }
5627
- var installed = false;
5628
- function installClientErrorReporter(options = {}) {
5629
- if (typeof window === "undefined" || installed) return () => {
5630
- };
5631
- installed = true;
5632
- const endpoint = options.endpoint ?? CLIENT_ERROR_PATH;
5633
- const maxReports = options.maxReports ?? 50;
5634
- const seen = /* @__PURE__ */ new Set();
5635
- let sent = 0;
5636
- const send = (raw) => {
5637
- const report = normalizeClientErrorReport(raw);
5638
- if (!report) return;
5639
- const key = `${report.kind}:${report.name ?? ""}:${report.message}`;
5640
- if (seen.has(key)) return;
5641
- if (sent >= maxReports) return;
5642
- seen.add(key);
5643
- sent += 1;
5644
- post(endpoint, report);
5645
- };
5646
- const onError = (event) => {
5647
- try {
5648
- const err = event.error;
5649
- send({
5650
- kind: "error",
5651
- name: err?.name,
5652
- message: err?.message ?? event.message,
5653
- stack: err?.stack,
5654
- url: stripQuery(event.filename || window.location?.href),
5655
- line: event.lineno,
5656
- col: event.colno
5657
- });
5658
- } catch {
5659
- }
5660
- };
5661
- const onRejection = (event) => {
5618
+ function renderError(err, depth) {
5619
+ let isError;
5620
+ try {
5621
+ isError = err instanceof Error;
5622
+ } catch {
5623
+ return tagOf(err);
5624
+ }
5625
+ if (!isError) {
5662
5626
  try {
5663
- const reason = event.reason;
5664
- const isError = reason instanceof Error;
5665
- send({
5666
- kind: "unhandledrejection",
5667
- name: isError ? reason.name : void 0,
5668
- message: isError ? reason.message : String(reason),
5669
- stack: isError ? reason.stack : void 0,
5670
- url: stripQuery(window.location?.href)
5671
- });
5627
+ return String(err).slice(0, MAX_LOG_TEXT_LENGTH + 1);
5672
5628
  } catch {
5629
+ return tagOf(err);
5673
5630
  }
5674
- };
5675
- window.addEventListener("error", onError);
5676
- window.addEventListener("unhandledrejection", onRejection);
5677
- return () => {
5678
- window.removeEventListener("error", onError);
5679
- window.removeEventListener("unhandledrejection", onRejection);
5680
- installed = false;
5681
- };
5682
- }
5683
- function reportClientError(error, options = {}) {
5684
- if (typeof window === "undefined") return;
5631
+ }
5632
+ const e = err;
5633
+ let out;
5685
5634
  try {
5686
- const isError = error instanceof Error;
5687
- const report = normalizeClientErrorReport({
5688
- kind: "react",
5689
- name: isError ? error.name : void 0,
5690
- message: isError ? error.message : String(error),
5691
- stack: (isError ? error.stack : void 0) ?? options.componentStack,
5692
- url: stripQuery(window.location?.href)
5693
- });
5694
- if (!report) return;
5695
- post(options.endpoint ?? CLIENT_ERROR_PATH, report);
5635
+ const stack = typeof e.stack === "string" ? e.stack : void 0;
5636
+ const head = (e.message ? `${e.name}: ${e.message}` : `${e.name}`).slice(
5637
+ 0,
5638
+ MAX_LOG_TEXT_LENGTH + 1
5639
+ );
5640
+ if (!stack) out = head;
5641
+ else if (stack.startsWith(head)) out = stack.slice(0, MAX_LOG_TEXT_LENGTH + 1);
5642
+ else out = `${head}
5643
+ ${stack.slice(0, MAX_LOG_TEXT_LENGTH + 1)}`;
5644
+ } catch {
5645
+ return tagOf(err);
5646
+ }
5647
+ try {
5648
+ if (e instanceof AggregateError && Array.isArray(e.errors)) {
5649
+ if (depth < MAX_CAUSE_DEPTH) {
5650
+ for (const sub of e.errors.slice(0, MAX_CAUSE_DEPTH)) {
5651
+ if (out.length >= MAX_LOG_TEXT_LENGTH) return out + "\n\u2026 [cause chain truncated]";
5652
+ out += `
5653
+ caused by: ${renderError(sub, depth + 1)}`;
5654
+ }
5655
+ if (e.errors.length > MAX_CAUSE_DEPTH) {
5656
+ out += `
5657
+ \u2026 [${e.errors.length - MAX_CAUSE_DEPTH} more errors]`;
5658
+ }
5659
+ } else {
5660
+ out += "\n\u2026 [cause chain truncated]";
5661
+ }
5662
+ }
5663
+ const cause = e.cause;
5664
+ if (cause != null) {
5665
+ if (depth >= MAX_CAUSE_DEPTH) {
5666
+ if (!out.endsWith("\u2026 [cause chain truncated]")) out += "\n\u2026 [cause chain truncated]";
5667
+ } else if (out.length < MAX_LOG_TEXT_LENGTH) {
5668
+ out += `
5669
+ caused by: ${renderError(cause, depth + 1)}`;
5670
+ } else {
5671
+ out += "\n\u2026 [cause chain truncated]";
5672
+ }
5673
+ }
5696
5674
  } catch {
5675
+ out += "\n\u2026 [cause chain unrenderable]";
5697
5676
  }
5677
+ return out;
5698
5678
  }
5699
-
5700
- // src/shared/log-events.ts
5701
- var LOG_LEVELS = ["debug", "log", "info", "warn", "error"];
5702
- var APP_LOG_EVENT_KEYS = [
5703
- "id",
5704
- "timestamp",
5705
- "level",
5706
- "eventType",
5707
- "message",
5708
- "source",
5709
- "outcome",
5710
- "request",
5711
- "exception"
5712
- ];
5713
5679
  export {
5714
5680
  ACCOUNT_STORAGE_LIMIT_BYTES,
5715
5681
  ACTION_ROUTES_BEARER_GUARD_MIGRATION_ID,
@@ -5732,6 +5698,7 @@ export {
5732
5698
  ENV,
5733
5699
  GuestBanner,
5734
5700
  LOG_LEVELS,
5701
+ MAX_LOG_TEXT_LENGTH,
5735
5702
  MSG,
5736
5703
  MSG_AWARENESS,
5737
5704
  MSG_SYNC,
@@ -5789,7 +5756,6 @@ export {
5789
5756
  handleAwarenessMessage,
5790
5757
  handleSyncMessage,
5791
5758
  hasContent,
5792
- installClientErrorReporter,
5793
5759
  integration,
5794
5760
  isAnonymousUserId,
5795
5761
  isAsyncResourceSlow,
@@ -5799,11 +5765,12 @@ export {
5799
5765
  isProduction,
5800
5766
  isWriterRole,
5801
5767
  listDeepSpaceAgentModels,
5768
+ logEventText,
5769
+ loggableError,
5802
5770
  parseSseLine,
5803
5771
  readThemeFromDOM,
5804
5772
  readVarUint,
5805
5773
  readVarUint8Array,
5806
- reportClientError,
5807
5774
  resetEnvironmentCache,
5808
5775
  resolveDeepSpaceAgentModel,
5809
5776
  serverBuild,
@@ -5812,6 +5779,7 @@ export {
5812
5779
  storageLimitForTier,
5813
5780
  toConnectionStatus,
5814
5781
  toUint8Array,
5782
+ truncateLogText,
5815
5783
  useAsyncResource,
5816
5784
  useAuth,
5817
5785
  useAuthProfileReady,